This commit is contained in:
Nim XD
2024-08-27 21:01:33 +05:30
parent 99eaf514fd
commit 121a1b7c73
31803 changed files with 623461 additions and 623399 deletions

View File

@@ -1,182 +1,182 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
[CustomEditor(typeof(AnimationReferenceAsset))]
public class AnimationReferenceAssetEditor : Editor {
const string InspectorHelpText = "This is a Spine-Unity Animation Reference Asset. It serializes a reference to a SkeletonData asset and an animationName. It does not contain actual animation data. At runtime, it stores a reference to a Spine.Animation.\n\n" +
"You can use this in your AnimationState calls instead of a string animation name or a Spine.Animation reference. Use its implicit conversion into Spine.Animation or its .Animation property.\n\n" +
"Use AnimationReferenceAssets as an alternative to storing strings or finding animations and caching per component. This only does the lookup by string once, and allows you to store and manage animations via asset references.";
readonly SkeletonInspectorPreview preview = new SkeletonInspectorPreview();
FieldInfo skeletonDataAssetField = typeof(AnimationReferenceAsset).GetField("skeletonDataAsset", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo nameField = typeof(AnimationReferenceAsset).GetField("animationName", BindingFlags.NonPublic | BindingFlags.Instance);
AnimationReferenceAsset ThisAnimationReferenceAsset { get { return target as AnimationReferenceAsset; } }
SkeletonDataAsset ThisSkeletonDataAsset { get { return skeletonDataAssetField.GetValue(ThisAnimationReferenceAsset) as SkeletonDataAsset; } }
string ThisAnimationName { get { return nameField.GetValue(ThisAnimationReferenceAsset) as string; } }
bool changeNextFrame = false;
SerializedProperty animationNameProperty;
SkeletonDataAsset lastSkeletonDataAsset;
SkeletonData lastSkeletonData;
void OnEnable () { HandleOnEnablePreview(); }
void OnDestroy () {
HandleOnDestroyPreview();
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
EditorApplication.update -= preview.HandleEditorUpdate;
}
public override void OnInspectorGUI () {
animationNameProperty = animationNameProperty ?? serializedObject.FindProperty("animationName");
string animationName = animationNameProperty.stringValue;
Animation animation = null;
if (ThisSkeletonDataAsset != null) {
var skeletonData = ThisSkeletonDataAsset.GetSkeletonData(true);
if (skeletonData != null) {
animation = skeletonData.FindAnimation(animationName);
}
}
bool animationNotFound = (animation == null);
if (changeNextFrame) {
changeNextFrame = false;
if (ThisSkeletonDataAsset != lastSkeletonDataAsset || ThisSkeletonDataAsset.GetSkeletonData(true) != lastSkeletonData) {
preview.Clear();
preview.Initialize(Repaint, ThisSkeletonDataAsset, LastSkinName);
if (animationNotFound) {
animationNameProperty.stringValue = "";
preview.ClearAnimationSetupPose();
}
}
preview.ClearAnimationSetupPose();
if (!string.IsNullOrEmpty(animationNameProperty.stringValue))
preview.PlayPauseAnimation(animationNameProperty.stringValue, true);
}
//EditorGUILayout.HelpBox(AnimationReferenceAssetEditor.InspectorHelpText, MessageType.Info, true);
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
DrawDefaultInspector();
if (EditorGUI.EndChangeCheck()) {
changeNextFrame = true;
}
// Draw extra info below default inspector.
EditorGUILayout.Space();
if (ThisSkeletonDataAsset == null) {
EditorGUILayout.HelpBox("SkeletonDataAsset is missing.", MessageType.Error);
} else if (string.IsNullOrEmpty(animationName)) {
EditorGUILayout.HelpBox("No animation selected.", MessageType.Warning);
} else if (animationNotFound) {
EditorGUILayout.HelpBox(string.Format("Animation named {0} was not found for this Skeleton.", animationNameProperty.stringValue), MessageType.Warning);
} else {
using (new SpineInspectorUtility.BoxScope()) {
if (!string.Equals(AssetUtility.GetPathSafeName(animationName), ThisAnimationReferenceAsset.name, System.StringComparison.OrdinalIgnoreCase))
EditorGUILayout.HelpBox("Animation name value does not match this asset's name. Inspectors using this asset may be misleading.", MessageType.None);
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(animationName, SpineEditorUtilities.Icons.animation));
if (animation != null) {
EditorGUILayout.LabelField(string.Format("Timelines: {0}", animation.Timelines.Count));
EditorGUILayout.LabelField(string.Format("Duration: {0} sec", animation.Duration));
}
}
}
lastSkeletonDataAsset = ThisSkeletonDataAsset;
lastSkeletonData = ThisSkeletonDataAsset.GetSkeletonData(true);
}
#region Preview Handlers
string TargetAssetGUID { get { return AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(ThisSkeletonDataAsset)); } }
string LastSkinKey { get { return TargetAssetGUID + "_lastSkin"; } }
string LastSkinName { get { return EditorPrefs.GetString(LastSkinKey, ""); } }
void HandleOnEnablePreview () {
if (ThisSkeletonDataAsset != null && ThisSkeletonDataAsset.skeletonJSON == null)
return;
SpineEditorUtilities.ConfirmInitialization();
// This handles the case where the managed editor assembly is unloaded before recompilation when code changes.
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
AppDomain.CurrentDomain.DomainUnload += OnDomainUnload;
preview.Initialize(this.Repaint, ThisSkeletonDataAsset, LastSkinName);
preview.PlayPauseAnimation(ThisAnimationName, true);
preview.OnSkinChanged -= HandleOnSkinChanged;
preview.OnSkinChanged += HandleOnSkinChanged;
EditorApplication.update -= preview.HandleEditorUpdate;
EditorApplication.update += preview.HandleEditorUpdate;
}
private void OnDomainUnload (object sender, EventArgs e) {
OnDestroy();
}
private void HandleOnSkinChanged (string skinName) {
EditorPrefs.SetString(LastSkinKey, skinName);
preview.PlayPauseAnimation(ThisAnimationName, true);
}
void HandleOnDestroyPreview () {
EditorApplication.update -= preview.HandleEditorUpdate;
preview.OnDestroy();
}
override public bool HasPreviewGUI () {
if (serializedObject.isEditingMultipleObjects) return false;
return ThisSkeletonDataAsset != null && ThisSkeletonDataAsset.GetSkeletonData(true) != null;
}
override public void OnInteractivePreviewGUI (Rect r, GUIStyle background) {
preview.Initialize(this.Repaint, ThisSkeletonDataAsset);
preview.HandleInteractivePreviewGUI(r, background);
}
public override GUIContent GetPreviewTitle () { return SpineInspectorUtility.TempContent("Preview"); }
public override void OnPreviewSettings () { preview.HandleDrawSettings(); }
public override Texture2D RenderStaticPreview (string assetPath, UnityEngine.Object[] subAssets, int width, int height) { return preview.GetStaticPreview(width, height); }
#endregion
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
[CustomEditor(typeof(AnimationReferenceAsset))]
public class AnimationReferenceAssetEditor : Editor {
const string InspectorHelpText = "This is a Spine-Unity Animation Reference Asset. It serializes a reference to a SkeletonData asset and an animationName. It does not contain actual animation data. At runtime, it stores a reference to a Spine.Animation.\n\n" +
"You can use this in your AnimationState calls instead of a string animation name or a Spine.Animation reference. Use its implicit conversion into Spine.Animation or its .Animation property.\n\n" +
"Use AnimationReferenceAssets as an alternative to storing strings or finding animations and caching per component. This only does the lookup by string once, and allows you to store and manage animations via asset references.";
readonly SkeletonInspectorPreview preview = new SkeletonInspectorPreview();
FieldInfo skeletonDataAssetField = typeof(AnimationReferenceAsset).GetField("skeletonDataAsset", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo nameField = typeof(AnimationReferenceAsset).GetField("animationName", BindingFlags.NonPublic | BindingFlags.Instance);
AnimationReferenceAsset ThisAnimationReferenceAsset { get { return target as AnimationReferenceAsset; } }
SkeletonDataAsset ThisSkeletonDataAsset { get { return skeletonDataAssetField.GetValue(ThisAnimationReferenceAsset) as SkeletonDataAsset; } }
string ThisAnimationName { get { return nameField.GetValue(ThisAnimationReferenceAsset) as string; } }
bool changeNextFrame = false;
SerializedProperty animationNameProperty;
SkeletonDataAsset lastSkeletonDataAsset;
SkeletonData lastSkeletonData;
void OnEnable () { HandleOnEnablePreview(); }
void OnDestroy () {
HandleOnDestroyPreview();
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
EditorApplication.update -= preview.HandleEditorUpdate;
}
public override void OnInspectorGUI () {
animationNameProperty = animationNameProperty ?? serializedObject.FindProperty("animationName");
string animationName = animationNameProperty.stringValue;
Animation animation = null;
if (ThisSkeletonDataAsset != null) {
var skeletonData = ThisSkeletonDataAsset.GetSkeletonData(true);
if (skeletonData != null) {
animation = skeletonData.FindAnimation(animationName);
}
}
bool animationNotFound = (animation == null);
if (changeNextFrame) {
changeNextFrame = false;
if (ThisSkeletonDataAsset != lastSkeletonDataAsset || ThisSkeletonDataAsset.GetSkeletonData(true) != lastSkeletonData) {
preview.Clear();
preview.Initialize(Repaint, ThisSkeletonDataAsset, LastSkinName);
if (animationNotFound) {
animationNameProperty.stringValue = "";
preview.ClearAnimationSetupPose();
}
}
preview.ClearAnimationSetupPose();
if (!string.IsNullOrEmpty(animationNameProperty.stringValue))
preview.PlayPauseAnimation(animationNameProperty.stringValue, true);
}
//EditorGUILayout.HelpBox(AnimationReferenceAssetEditor.InspectorHelpText, MessageType.Info, true);
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
DrawDefaultInspector();
if (EditorGUI.EndChangeCheck()) {
changeNextFrame = true;
}
// Draw extra info below default inspector.
EditorGUILayout.Space();
if (ThisSkeletonDataAsset == null) {
EditorGUILayout.HelpBox("SkeletonDataAsset is missing.", MessageType.Error);
} else if (string.IsNullOrEmpty(animationName)) {
EditorGUILayout.HelpBox("No animation selected.", MessageType.Warning);
} else if (animationNotFound) {
EditorGUILayout.HelpBox(string.Format("Animation named {0} was not found for this Skeleton.", animationNameProperty.stringValue), MessageType.Warning);
} else {
using (new SpineInspectorUtility.BoxScope()) {
if (!string.Equals(AssetUtility.GetPathSafeName(animationName), ThisAnimationReferenceAsset.name, System.StringComparison.OrdinalIgnoreCase))
EditorGUILayout.HelpBox("Animation name value does not match this asset's name. Inspectors using this asset may be misleading.", MessageType.None);
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(animationName, SpineEditorUtilities.Icons.animation));
if (animation != null) {
EditorGUILayout.LabelField(string.Format("Timelines: {0}", animation.Timelines.Count));
EditorGUILayout.LabelField(string.Format("Duration: {0} sec", animation.Duration));
}
}
}
lastSkeletonDataAsset = ThisSkeletonDataAsset;
lastSkeletonData = ThisSkeletonDataAsset.GetSkeletonData(true);
}
#region Preview Handlers
string TargetAssetGUID { get { return AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(ThisSkeletonDataAsset)); } }
string LastSkinKey { get { return TargetAssetGUID + "_lastSkin"; } }
string LastSkinName { get { return EditorPrefs.GetString(LastSkinKey, ""); } }
void HandleOnEnablePreview () {
if (ThisSkeletonDataAsset != null && ThisSkeletonDataAsset.skeletonJSON == null)
return;
SpineEditorUtilities.ConfirmInitialization();
// This handles the case where the managed editor assembly is unloaded before recompilation when code changes.
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
AppDomain.CurrentDomain.DomainUnload += OnDomainUnload;
preview.Initialize(this.Repaint, ThisSkeletonDataAsset, LastSkinName);
preview.PlayPauseAnimation(ThisAnimationName, true);
preview.OnSkinChanged -= HandleOnSkinChanged;
preview.OnSkinChanged += HandleOnSkinChanged;
EditorApplication.update -= preview.HandleEditorUpdate;
EditorApplication.update += preview.HandleEditorUpdate;
}
private void OnDomainUnload (object sender, EventArgs e) {
OnDestroy();
}
private void HandleOnSkinChanged (string skinName) {
EditorPrefs.SetString(LastSkinKey, skinName);
preview.PlayPauseAnimation(ThisAnimationName, true);
}
void HandleOnDestroyPreview () {
EditorApplication.update -= preview.HandleEditorUpdate;
preview.OnDestroy();
}
override public bool HasPreviewGUI () {
if (serializedObject.isEditingMultipleObjects) return false;
return ThisSkeletonDataAsset != null && ThisSkeletonDataAsset.GetSkeletonData(true) != null;
}
override public void OnInteractivePreviewGUI (Rect r, GUIStyle background) {
preview.Initialize(this.Repaint, ThisSkeletonDataAsset);
preview.HandleInteractivePreviewGUI(r, background);
}
public override GUIContent GetPreviewTitle () { return SpineInspectorUtility.TempContent("Preview"); }
public override void OnPreviewSettings () { preview.HandleDrawSettings(); }
public override Texture2D RenderStaticPreview (string assetPath, UnityEngine.Object[] subAssets, int width, int height) { return preview.GetStaticPreview(width, height); }
#endregion
}
}

View File

@@ -1,383 +1,383 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
//#define BAKE_ALL_BUTTON
//#define REGION_BAKING_MESH
using Spine;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
[CustomEditor(typeof(SpineAtlasAsset)), CanEditMultipleObjects]
public class SpineAtlasAssetInspector : UnityEditor.Editor {
SerializedProperty atlasFile, materials;
SpineAtlasAsset atlasAsset;
GUIContent spriteSlicesLabel;
GUIContent SpriteSlicesLabel {
get {
if (spriteSlicesLabel == null) {
spriteSlicesLabel = new GUIContent(
"Apply Regions as Texture Sprite Slices",
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, " +
"your SpriteRenderer should use the generated Spine _Material asset (or any Material with a PMA shader) instead of Sprites-Default.");
}
return spriteSlicesLabel;
}
}
static List<AtlasRegion> GetRegions (Atlas atlas) {
FieldInfo regionsField = SpineInspectorUtility.GetNonPublicField(typeof(Atlas), "regions");
return (List<AtlasRegion>)regionsField.GetValue(atlas);
}
void OnEnable () {
SpineEditorUtilities.ConfirmInitialization();
atlasFile = serializedObject.FindProperty("atlasFile");
materials = serializedObject.FindProperty("materials");
materials.isExpanded = true;
atlasAsset = (SpineAtlasAsset)target;
#if REGION_BAKING_MESH
UpdateBakedList();
#endif
}
#if REGION_BAKING_MESH
private List<bool> baked;
private List<GameObject> bakedObjects;
void UpdateBakedList () {
AtlasAsset asset = (AtlasAsset)target;
baked = new List<bool>();
bakedObjects = new List<GameObject>();
if (atlasFile.objectReferenceValue != null) {
List<AtlasRegion> regions = this.Regions;
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
for (int i = 0; i < regions.Count; i++) {
AtlasRegion region = regions[i];
string bakedPrefabPath = Path.Combine(bakedDirPath, AssetUtility.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
baked.Add(prefab != null);
bakedObjects.Add(prefab);
}
}
}
#endif
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
DrawDefaultInspector();
return;
}
serializedObject.Update();
atlasAsset = (atlasAsset == null) ? (SpineAtlasAsset)target : atlasAsset;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(atlasFile);
EditorGUILayout.PropertyField(materials, true);
if (EditorGUI.EndChangeCheck()) {
serializedObject.ApplyModifiedProperties();
atlasAsset.Clear();
atlasAsset.GetAtlas();
}
if (materials.arraySize == 0) {
EditorGUILayout.HelpBox("No materials", MessageType.Error);
return;
}
for (int i = 0; i < materials.arraySize; i++) {
SerializedProperty prop = materials.GetArrayElementAtIndex(i);
var material = (Material)prop.objectReferenceValue;
if (material == null) {
EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error);
return;
}
}
EditorGUILayout.Space();
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Set Mipmap Bias to " + SpinePreferences.DEFAULT_MIPMAPBIAS, tooltip: "This may help textures with mipmaps be less blurry when used for 2D sprites."))) {
foreach (var m in atlasAsset.materials) {
var texture = m.mainTexture;
string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
var importer = (TextureImporter)TextureImporter.GetAtPath(texturePath);
importer.mipMapBias = SpinePreferences.DEFAULT_MIPMAPBIAS;
EditorUtility.SetDirty(texture);
}
Debug.Log("Texture mipmap bias set to " + SpinePreferences.DEFAULT_MIPMAPBIAS);
}
EditorGUILayout.Space();
if (atlasFile.objectReferenceValue != null) {
if (SpineInspectorUtility.LargeCenteredButton(SpriteSlicesLabel)) {
var atlas = atlasAsset.GetAtlas();
foreach (var m in atlasAsset.materials)
UpdateSpriteSlices(m.mainTexture, atlas);
}
}
EditorGUILayout.Space();
#if REGION_BAKING_MESH
if (atlasFile.objectReferenceValue != null) {
Atlas atlas = asset.GetAtlas();
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
EditorGUILayout.LabelField(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
EditorGUI.indentLevel++;
AtlasPage lastPage = null;
for (int i = 0; i < regions.Count; i++) {
if (lastPage != regions[i].page) {
if (lastPage != null) {
EditorGUILayout.Separator();
EditorGUILayout.Separator();
}
lastPage = regions[i].page;
Material mat = ((Material)lastPage.rendererObject);
if (mat != null) {
GUILayout.BeginHorizontal();
{
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
EditorGUI.EndDisabledGroup();
}
GUILayout.EndHorizontal();
} else {
EditorGUILayout.LabelField(new GUIContent("Page missing material!", SpineEditorUtilities.Icons.warning));
}
}
GUILayout.BeginHorizontal();
{
//EditorGUILayout.ToggleLeft(baked[i] ? "" : regions[i].name, baked[i]);
bool result = baked[i] ? EditorGUILayout.ToggleLeft("", baked[i], GUILayout.Width(24)) : EditorGUILayout.ToggleLeft(" " + regions[i].name, baked[i]);
if(baked[i]){
EditorGUILayout.ObjectField(bakedObjects[i], typeof(GameObject), false, GUILayout.Width(250));
}
if (result && !baked[i]) {
//bake
baked[i] = true;
bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
EditorGUIUtility.PingObject(bakedObjects[i]);
} else if (!result && baked[i]) {
//unbake
bool unbakeResult = EditorUtility.DisplayDialog("Delete Baked Region", "Do you want to delete the prefab for " + regions[i].name, "Yes", "Cancel");
switch (unbakeResult) {
case true:
//delete
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
AssetDatabase.DeleteAsset(bakedPrefabPath);
baked[i] = false;
break;
case false:
//do nothing
break;
}
}
}
GUILayout.EndHorizontal();
}
EditorGUI.indentLevel--;
#if BAKE_ALL_BUTTON
// Check state
bool allBaked = true;
bool allUnbaked = true;
for (int i = 0; i < regions.Count; i++) {
allBaked &= baked[i];
allUnbaked &= !baked[i];
}
if (!allBaked && GUILayout.Button("Bake All")) {
for (int i = 0; i < regions.Count; i++) {
if (!baked[i]) {
baked[i] = true;
bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
}
}
} else if (!allUnbaked && GUILayout.Button("Unbake All")) {
bool unbakeResult = EditorUtility.DisplayDialog("Delete All Baked Regions", "Are you sure you want to unbake all region prefabs? This cannot be undone.", "Yes", "Cancel");
switch (unbakeResult) {
case true:
//delete
for (int i = 0; i < regions.Count; i++) {
if (baked[i]) {
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
AssetDatabase.DeleteAsset(bakedPrefabPath);
baked[i] = false;
}
}
break;
case false:
//do nothing
break;
}
}
#endif
}
#else
if (atlasFile.objectReferenceValue != null) {
int baseIndent = EditorGUI.indentLevel;
var regions = SpineAtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
int regionsCount = regions.Count;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
EditorGUILayout.LabelField(string.Format("{0} regions total", regionsCount));
}
AtlasPage lastPage = null;
for (int i = 0; i < regionsCount; i++) {
if (lastPage != regions[i].page) {
if (lastPage != null) {
EditorGUILayout.Separator();
EditorGUILayout.Separator();
}
lastPage = regions[i].page;
Material mat = ((Material)lastPage.rendererObject);
if (mat != null) {
EditorGUI.indentLevel = baseIndent;
using (new GUILayout.HorizontalScope())
using (new EditorGUI.DisabledGroupScope(true))
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
EditorGUI.indentLevel = baseIndent + 1;
} else {
EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
}
}
string regionName = regions[i].name;
Texture2D icon = SpineEditorUtilities.Icons.image;
if (regionName.EndsWith(" ")) {
regionName = string.Format("'{0}'", regions[i].name);
icon = SpineEditorUtilities.Icons.warning;
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon, "Region name ends with whitespace. This may cause errors. Please check your source image filenames."));
} else {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon));
}
}
EditorGUI.indentLevel = baseIndent;
}
#endif
if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
atlasAsset.Clear();
}
static public void UpdateSpriteSlices (Texture texture, Atlas atlas) {
string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
var t = (TextureImporter)TextureImporter.GetAtPath(texturePath);
t.spriteImportMode = SpriteImportMode.Multiple;
var spriteSheet = t.spritesheet;
var sprites = new List<SpriteMetaData>(spriteSheet);
var regions = SpineAtlasAssetInspector.GetRegions(atlas);
char[] FilenameDelimiter = { '.' };
int updatedCount = 0;
int addedCount = 0;
foreach (var r in regions) {
string pageName = r.page.name.Split(FilenameDelimiter, StringSplitOptions.RemoveEmptyEntries)[0];
string textureName = texture.name;
bool pageMatch = string.Equals(pageName, textureName, StringComparison.Ordinal);
// if (pageMatch) {
// int pw = r.page.width;
// int ph = r.page.height;
// bool mismatchSize = pw != texture.width || pw > t.maxTextureSize || ph != texture.height || ph > t.maxTextureSize;
// if (mismatchSize)
// Debug.LogWarningFormat("Size mismatch found.\nExpected atlas size is {0}x{1}. Texture Import Max Size of texture '{2}'({4}x{5}) is currently set to {3}.", pw, ph, texture.name, t.maxTextureSize, texture.width, texture.height);
// }
int spriteIndex = pageMatch ? sprites.FindIndex(
(s) => string.Equals(s.name, r.name, StringComparison.Ordinal)
) : -1;
bool spriteNameMatchExists = spriteIndex >= 0;
if (pageMatch) {
Rect spriteRect = new Rect();
if (r.degrees == 90) {
spriteRect.width = r.height;
spriteRect.height = r.width;
} else {
spriteRect.width = r.width;
spriteRect.height = r.height;
}
spriteRect.x = r.x;
spriteRect.y = r.page.height - spriteRect.height - r.y;
if (spriteNameMatchExists) {
var s = sprites[spriteIndex];
s.rect = spriteRect;
sprites[spriteIndex] = s;
updatedCount++;
} else {
sprites.Add(new SpriteMetaData {
name = r.name,
pivot = new Vector2(0.5f, 0.5f),
rect = spriteRect
});
addedCount++;
}
}
}
t.spritesheet = sprites.ToArray();
EditorUtility.SetDirty(t);
AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate);
EditorGUIUtility.PingObject(texture);
Debug.Log(string.Format("Applied sprite slices to {2}. {0} added. {1} updated.", addedCount, updatedCount, texture.name));
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
//#define BAKE_ALL_BUTTON
//#define REGION_BAKING_MESH
using Spine;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
[CustomEditor(typeof(SpineAtlasAsset)), CanEditMultipleObjects]
public class SpineAtlasAssetInspector : UnityEditor.Editor {
SerializedProperty atlasFile, materials;
SpineAtlasAsset atlasAsset;
GUIContent spriteSlicesLabel;
GUIContent SpriteSlicesLabel {
get {
if (spriteSlicesLabel == null) {
spriteSlicesLabel = new GUIContent(
"Apply Regions as Texture Sprite Slices",
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, " +
"your SpriteRenderer should use the generated Spine _Material asset (or any Material with a PMA shader) instead of Sprites-Default.");
}
return spriteSlicesLabel;
}
}
static List<AtlasRegion> GetRegions (Atlas atlas) {
FieldInfo regionsField = SpineInspectorUtility.GetNonPublicField(typeof(Atlas), "regions");
return (List<AtlasRegion>)regionsField.GetValue(atlas);
}
void OnEnable () {
SpineEditorUtilities.ConfirmInitialization();
atlasFile = serializedObject.FindProperty("atlasFile");
materials = serializedObject.FindProperty("materials");
materials.isExpanded = true;
atlasAsset = (SpineAtlasAsset)target;
#if REGION_BAKING_MESH
UpdateBakedList();
#endif
}
#if REGION_BAKING_MESH
private List<bool> baked;
private List<GameObject> bakedObjects;
void UpdateBakedList () {
AtlasAsset asset = (AtlasAsset)target;
baked = new List<bool>();
bakedObjects = new List<GameObject>();
if (atlasFile.objectReferenceValue != null) {
List<AtlasRegion> regions = this.Regions;
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
for (int i = 0; i < regions.Count; i++) {
AtlasRegion region = regions[i];
string bakedPrefabPath = Path.Combine(bakedDirPath, AssetUtility.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
baked.Add(prefab != null);
bakedObjects.Add(prefab);
}
}
}
#endif
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
DrawDefaultInspector();
return;
}
serializedObject.Update();
atlasAsset = (atlasAsset == null) ? (SpineAtlasAsset)target : atlasAsset;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(atlasFile);
EditorGUILayout.PropertyField(materials, true);
if (EditorGUI.EndChangeCheck()) {
serializedObject.ApplyModifiedProperties();
atlasAsset.Clear();
atlasAsset.GetAtlas();
}
if (materials.arraySize == 0) {
EditorGUILayout.HelpBox("No materials", MessageType.Error);
return;
}
for (int i = 0; i < materials.arraySize; i++) {
SerializedProperty prop = materials.GetArrayElementAtIndex(i);
var material = (Material)prop.objectReferenceValue;
if (material == null) {
EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error);
return;
}
}
EditorGUILayout.Space();
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Set Mipmap Bias to " + SpinePreferences.DEFAULT_MIPMAPBIAS, tooltip: "This may help textures with mipmaps be less blurry when used for 2D sprites."))) {
foreach (var m in atlasAsset.materials) {
var texture = m.mainTexture;
string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
var importer = (TextureImporter)TextureImporter.GetAtPath(texturePath);
importer.mipMapBias = SpinePreferences.DEFAULT_MIPMAPBIAS;
EditorUtility.SetDirty(texture);
}
Debug.Log("Texture mipmap bias set to " + SpinePreferences.DEFAULT_MIPMAPBIAS);
}
EditorGUILayout.Space();
if (atlasFile.objectReferenceValue != null) {
if (SpineInspectorUtility.LargeCenteredButton(SpriteSlicesLabel)) {
var atlas = atlasAsset.GetAtlas();
foreach (var m in atlasAsset.materials)
UpdateSpriteSlices(m.mainTexture, atlas);
}
}
EditorGUILayout.Space();
#if REGION_BAKING_MESH
if (atlasFile.objectReferenceValue != null) {
Atlas atlas = asset.GetAtlas();
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
EditorGUILayout.LabelField(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
EditorGUI.indentLevel++;
AtlasPage lastPage = null;
for (int i = 0; i < regions.Count; i++) {
if (lastPage != regions[i].page) {
if (lastPage != null) {
EditorGUILayout.Separator();
EditorGUILayout.Separator();
}
lastPage = regions[i].page;
Material mat = ((Material)lastPage.rendererObject);
if (mat != null) {
GUILayout.BeginHorizontal();
{
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
EditorGUI.EndDisabledGroup();
}
GUILayout.EndHorizontal();
} else {
EditorGUILayout.LabelField(new GUIContent("Page missing material!", SpineEditorUtilities.Icons.warning));
}
}
GUILayout.BeginHorizontal();
{
//EditorGUILayout.ToggleLeft(baked[i] ? "" : regions[i].name, baked[i]);
bool result = baked[i] ? EditorGUILayout.ToggleLeft("", baked[i], GUILayout.Width(24)) : EditorGUILayout.ToggleLeft(" " + regions[i].name, baked[i]);
if(baked[i]){
EditorGUILayout.ObjectField(bakedObjects[i], typeof(GameObject), false, GUILayout.Width(250));
}
if (result && !baked[i]) {
//bake
baked[i] = true;
bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
EditorGUIUtility.PingObject(bakedObjects[i]);
} else if (!result && baked[i]) {
//unbake
bool unbakeResult = EditorUtility.DisplayDialog("Delete Baked Region", "Do you want to delete the prefab for " + regions[i].name, "Yes", "Cancel");
switch (unbakeResult) {
case true:
//delete
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
AssetDatabase.DeleteAsset(bakedPrefabPath);
baked[i] = false;
break;
case false:
//do nothing
break;
}
}
}
GUILayout.EndHorizontal();
}
EditorGUI.indentLevel--;
#if BAKE_ALL_BUTTON
// Check state
bool allBaked = true;
bool allUnbaked = true;
for (int i = 0; i < regions.Count; i++) {
allBaked &= baked[i];
allUnbaked &= !baked[i];
}
if (!allBaked && GUILayout.Button("Bake All")) {
for (int i = 0; i < regions.Count; i++) {
if (!baked[i]) {
baked[i] = true;
bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
}
}
} else if (!allUnbaked && GUILayout.Button("Unbake All")) {
bool unbakeResult = EditorUtility.DisplayDialog("Delete All Baked Regions", "Are you sure you want to unbake all region prefabs? This cannot be undone.", "Yes", "Cancel");
switch (unbakeResult) {
case true:
//delete
for (int i = 0; i < regions.Count; i++) {
if (baked[i]) {
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
AssetDatabase.DeleteAsset(bakedPrefabPath);
baked[i] = false;
}
}
break;
case false:
//do nothing
break;
}
}
#endif
}
#else
if (atlasFile.objectReferenceValue != null) {
int baseIndent = EditorGUI.indentLevel;
var regions = SpineAtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
int regionsCount = regions.Count;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
EditorGUILayout.LabelField(string.Format("{0} regions total", regionsCount));
}
AtlasPage lastPage = null;
for (int i = 0; i < regionsCount; i++) {
if (lastPage != regions[i].page) {
if (lastPage != null) {
EditorGUILayout.Separator();
EditorGUILayout.Separator();
}
lastPage = regions[i].page;
Material mat = ((Material)lastPage.rendererObject);
if (mat != null) {
EditorGUI.indentLevel = baseIndent;
using (new GUILayout.HorizontalScope())
using (new EditorGUI.DisabledGroupScope(true))
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
EditorGUI.indentLevel = baseIndent + 1;
} else {
EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
}
}
string regionName = regions[i].name;
Texture2D icon = SpineEditorUtilities.Icons.image;
if (regionName.EndsWith(" ")) {
regionName = string.Format("'{0}'", regions[i].name);
icon = SpineEditorUtilities.Icons.warning;
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon, "Region name ends with whitespace. This may cause errors. Please check your source image filenames."));
} else {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon));
}
}
EditorGUI.indentLevel = baseIndent;
}
#endif
if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
atlasAsset.Clear();
}
static public void UpdateSpriteSlices (Texture texture, Atlas atlas) {
string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
var t = (TextureImporter)TextureImporter.GetAtPath(texturePath);
t.spriteImportMode = SpriteImportMode.Multiple;
var spriteSheet = t.spritesheet;
var sprites = new List<SpriteMetaData>(spriteSheet);
var regions = SpineAtlasAssetInspector.GetRegions(atlas);
char[] FilenameDelimiter = { '.' };
int updatedCount = 0;
int addedCount = 0;
foreach (var r in regions) {
string pageName = r.page.name.Split(FilenameDelimiter, StringSplitOptions.RemoveEmptyEntries)[0];
string textureName = texture.name;
bool pageMatch = string.Equals(pageName, textureName, StringComparison.Ordinal);
// if (pageMatch) {
// int pw = r.page.width;
// int ph = r.page.height;
// bool mismatchSize = pw != texture.width || pw > t.maxTextureSize || ph != texture.height || ph > t.maxTextureSize;
// if (mismatchSize)
// Debug.LogWarningFormat("Size mismatch found.\nExpected atlas size is {0}x{1}. Texture Import Max Size of texture '{2}'({4}x{5}) is currently set to {3}.", pw, ph, texture.name, t.maxTextureSize, texture.width, texture.height);
// }
int spriteIndex = pageMatch ? sprites.FindIndex(
(s) => string.Equals(s.name, r.name, StringComparison.Ordinal)
) : -1;
bool spriteNameMatchExists = spriteIndex >= 0;
if (pageMatch) {
Rect spriteRect = new Rect();
if (r.degrees == 90) {
spriteRect.width = r.height;
spriteRect.height = r.width;
} else {
spriteRect.width = r.width;
spriteRect.height = r.height;
}
spriteRect.x = r.x;
spriteRect.y = r.page.height - spriteRect.height - r.y;
if (spriteNameMatchExists) {
var s = sprites[spriteIndex];
s.rect = spriteRect;
sprites[spriteIndex] = s;
updatedCount++;
} else {
sprites.Add(new SpriteMetaData {
name = r.name,
pivot = new Vector2(0.5f, 0.5f),
rect = spriteRect
});
addedCount++;
}
}
}
t.spritesheet = sprites.ToArray();
EditorUtility.SetDirty(t);
AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate);
EditorGUIUtility.PingObject(texture);
Debug.Log(string.Format("Applied sprite slices to {2}. {0} added. {1} updated.", addedCount, updatedCount, texture.name));
}
}
}

View File

@@ -1,153 +1,153 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
[CustomEditor(typeof(SpineSpriteAtlasAsset)), CanEditMultipleObjects]
public class SpineSpriteAtlasAssetInspector : UnityEditor.Editor {
SerializedProperty atlasFile, materials;
SpineSpriteAtlasAsset atlasAsset;
static List<AtlasRegion> GetRegions (Atlas atlas) {
FieldInfo regionsField = SpineInspectorUtility.GetNonPublicField(typeof(Atlas), "regions");
return (List<AtlasRegion>)regionsField.GetValue(atlas);
}
void OnEnable () {
SpineEditorUtilities.ConfirmInitialization();
atlasFile = serializedObject.FindProperty("spriteAtlasFile");
materials = serializedObject.FindProperty("materials");
materials.isExpanded = true;
atlasAsset = (SpineSpriteAtlasAsset)target;
if (!SpineSpriteAtlasAsset.AnySpriteAtlasNeedsRegionsLoaded())
return;
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
EditorApplication.update += SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
}
void OnDisable () {
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
DrawDefaultInspector();
return;
}
serializedObject.Update();
atlasAsset = (atlasAsset == null) ? (SpineSpriteAtlasAsset)target : atlasAsset;
if (atlasAsset.RegionsNeedLoading) {
if (GUILayout.Button(SpineInspectorUtility.TempContent("Load regions by entering Play mode"), GUILayout.Height(20))) {
EditorApplication.isPlaying = true;
}
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(atlasFile);
EditorGUILayout.PropertyField(materials, true);
if (EditorGUI.EndChangeCheck()) {
serializedObject.ApplyModifiedProperties();
atlasAsset.Clear();
atlasAsset.GetAtlas();
atlasAsset.updateRegionsInPlayMode = true;
}
if (materials.arraySize == 0) {
EditorGUILayout.HelpBox("No materials", MessageType.Error);
return;
}
for (int i = 0; i < materials.arraySize; i++) {
SerializedProperty prop = materials.GetArrayElementAtIndex(i);
var material = (Material)prop.objectReferenceValue;
if (material == null) {
EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error);
return;
}
}
if (atlasFile.objectReferenceValue != null) {
int baseIndent = EditorGUI.indentLevel;
var regions = SpineSpriteAtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
int regionsCount = regions.Count;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
EditorGUILayout.LabelField(string.Format("{0} regions total", regionsCount));
}
AtlasPage lastPage = null;
for (int i = 0; i < regionsCount; i++) {
if (lastPage != regions[i].page) {
if (lastPage != null) {
EditorGUILayout.Separator();
EditorGUILayout.Separator();
}
lastPage = regions[i].page;
Material mat = ((Material)lastPage.rendererObject);
if (mat != null) {
EditorGUI.indentLevel = baseIndent;
using (new GUILayout.HorizontalScope())
using (new EditorGUI.DisabledGroupScope(true))
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
EditorGUI.indentLevel = baseIndent + 1;
} else {
EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
}
}
string regionName = regions[i].name;
Texture2D icon = SpineEditorUtilities.Icons.image;
if (regionName.EndsWith(" ")) {
regionName = string.Format("'{0}'", regions[i].name);
icon = SpineEditorUtilities.Icons.warning;
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon, "Region name ends with whitespace. This may cause errors. Please check your source image filenames."));
} else {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon));
}
}
EditorGUI.indentLevel = baseIndent;
}
if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
atlasAsset.Clear();
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
[CustomEditor(typeof(SpineSpriteAtlasAsset)), CanEditMultipleObjects]
public class SpineSpriteAtlasAssetInspector : UnityEditor.Editor {
SerializedProperty atlasFile, materials;
SpineSpriteAtlasAsset atlasAsset;
static List<AtlasRegion> GetRegions (Atlas atlas) {
FieldInfo regionsField = SpineInspectorUtility.GetNonPublicField(typeof(Atlas), "regions");
return (List<AtlasRegion>)regionsField.GetValue(atlas);
}
void OnEnable () {
SpineEditorUtilities.ConfirmInitialization();
atlasFile = serializedObject.FindProperty("spriteAtlasFile");
materials = serializedObject.FindProperty("materials");
materials.isExpanded = true;
atlasAsset = (SpineSpriteAtlasAsset)target;
if (!SpineSpriteAtlasAsset.AnySpriteAtlasNeedsRegionsLoaded())
return;
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
EditorApplication.update += SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
}
void OnDisable () {
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
DrawDefaultInspector();
return;
}
serializedObject.Update();
atlasAsset = (atlasAsset == null) ? (SpineSpriteAtlasAsset)target : atlasAsset;
if (atlasAsset.RegionsNeedLoading) {
if (GUILayout.Button(SpineInspectorUtility.TempContent("Load regions by entering Play mode"), GUILayout.Height(20))) {
EditorApplication.isPlaying = true;
}
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(atlasFile);
EditorGUILayout.PropertyField(materials, true);
if (EditorGUI.EndChangeCheck()) {
serializedObject.ApplyModifiedProperties();
atlasAsset.Clear();
atlasAsset.GetAtlas();
atlasAsset.updateRegionsInPlayMode = true;
}
if (materials.arraySize == 0) {
EditorGUILayout.HelpBox("No materials", MessageType.Error);
return;
}
for (int i = 0; i < materials.arraySize; i++) {
SerializedProperty prop = materials.GetArrayElementAtIndex(i);
var material = (Material)prop.objectReferenceValue;
if (material == null) {
EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error);
return;
}
}
if (atlasFile.objectReferenceValue != null) {
int baseIndent = EditorGUI.indentLevel;
var regions = SpineSpriteAtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
int regionsCount = regions.Count;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
EditorGUILayout.LabelField(string.Format("{0} regions total", regionsCount));
}
AtlasPage lastPage = null;
for (int i = 0; i < regionsCount; i++) {
if (lastPage != regions[i].page) {
if (lastPage != null) {
EditorGUILayout.Separator();
EditorGUILayout.Separator();
}
lastPage = regions[i].page;
Material mat = ((Material)lastPage.rendererObject);
if (mat != null) {
EditorGUI.indentLevel = baseIndent;
using (new GUILayout.HorizontalScope())
using (new EditorGUI.DisabledGroupScope(true))
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
EditorGUI.indentLevel = baseIndent + 1;
} else {
EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
}
}
string regionName = regions[i].name;
Texture2D icon = SpineEditorUtilities.Icons.image;
if (regionName.EndsWith(" ")) {
regionName = string.Format("'{0}'", regions[i].name);
icon = SpineEditorUtilities.Icons.warning;
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon, "Region name ends with whitespace. This may cause errors. Please check your source image filenames."));
} else {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon));
}
}
EditorGUI.indentLevel = baseIndent;
}
if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
atlasAsset.Clear();
}
}
}

View File

@@ -1,208 +1,208 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
using Event = UnityEngine.Event;
[CustomEditor(typeof(BoneFollowerGraphic)), CanEditMultipleObjects]
public class BoneFollowerGraphicInspector : Editor {
SerializedProperty boneName, skeletonGraphic, followXYPosition, followZPosition, followBoneRotation,
followLocalScale, followParentWorldScale, followSkeletonFlip, maintainedAxisOrientation;
BoneFollowerGraphic targetBoneFollower;
bool needsReset;
#region Context Menu Item
[MenuItem("CONTEXT/SkeletonGraphic/Add BoneFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonGraphic = cmd.context as SkeletonGraphic;
var go = EditorInstantiation.NewGameObject("BoneFollower", true, typeof(RectTransform));
var t = go.transform;
t.SetParent(skeletonGraphic.transform);
t.localPosition = Vector3.zero;
var f = go.AddComponent<BoneFollowerGraphic>();
f.skeletonGraphic = skeletonGraphic;
f.SetBone(skeletonGraphic.Skeleton.RootBone.Data.Name);
EditorGUIUtility.PingObject(t);
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollowerGraphic");
}
// Validate
[MenuItem("CONTEXT/SkeletonGraphic/Add BoneFollower GameObject", true)]
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonGraphic = cmd.context as SkeletonGraphic;
return skeletonGraphic.IsValid;
}
#endregion
void OnEnable () {
skeletonGraphic = serializedObject.FindProperty("skeletonGraphic");
boneName = serializedObject.FindProperty("boneName");
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
followXYPosition = serializedObject.FindProperty("followXYPosition");
followZPosition = serializedObject.FindProperty("followZPosition");
followLocalScale = serializedObject.FindProperty("followLocalScale");
followParentWorldScale = serializedObject.FindProperty("followParentWorldScale");
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
maintainedAxisOrientation = serializedObject.FindProperty("maintainedAxisOrientation");
targetBoneFollower = (BoneFollowerGraphic)target;
if (targetBoneFollower.SkeletonGraphic != null)
targetBoneFollower.SkeletonGraphic.Initialize(false);
if (!targetBoneFollower.valid || needsReset) {
targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
}
public void OnSceneGUI () {
var tbf = target as BoneFollowerGraphic;
var skeletonGraphicComponent = tbf.SkeletonGraphic;
if (skeletonGraphicComponent == null) return;
var transform = skeletonGraphicComponent.transform;
var skeleton = skeletonGraphicComponent.Skeleton;
var canvas = skeletonGraphicComponent.canvas;
float positionScale = canvas == null ? 1f : skeletonGraphicComponent.canvas.referencePixelsPerUnit;
if (string.IsNullOrEmpty(boneName.stringValue)) {
SpineHandles.DrawBones(transform, skeleton, positionScale);
SpineHandles.DrawBoneNames(transform, skeleton, positionScale);
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
} else {
var targetBone = tbf.bone;
if (targetBone == null) return;
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor, positionScale);
Handles.Label(targetBone.GetWorldPosition(transform, positionScale), targetBone.Data.Name, SpineHandles.BoneNameStyle);
}
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
if (needsReset) {
needsReset = false;
foreach (var o in targets) {
var bf = (BoneFollower)o;
bf.Initialize();
bf.LateUpdate();
}
SceneView.RepaintAll();
}
EditorGUI.BeginChangeCheck();
DrawDefaultInspector();
needsReset |= EditorGUI.EndChangeCheck();
return;
}
if (needsReset && Event.current.type == EventType.Layout) {
targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
serializedObject.Update();
// Find Renderer
if (skeletonGraphic.objectReferenceValue == null) {
SkeletonGraphic parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonGraphic>();
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
skeletonGraphic.objectReferenceValue = parentRenderer;
Debug.Log("Inspector automatically assigned BoneFollowerGraphic.SkeletonGraphic");
}
}
EditorGUILayout.PropertyField(skeletonGraphic);
var skeletonGraphicComponent = skeletonGraphic.objectReferenceValue as SkeletonGraphic;
if (skeletonGraphicComponent != null) {
if (skeletonGraphicComponent.gameObject == targetBoneFollower.gameObject) {
skeletonGraphic.objectReferenceValue = null;
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollowerGraphic can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonGraphic from a different GameObject.", "Ok");
}
}
if (!targetBoneFollower.valid) {
needsReset = true;
}
if (targetBoneFollower.valid) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(boneName);
needsReset |= EditorGUI.EndChangeCheck();
EditorGUILayout.PropertyField(followBoneRotation);
EditorGUILayout.PropertyField(followXYPosition);
EditorGUILayout.PropertyField(followZPosition);
EditorGUILayout.PropertyField(followLocalScale);
EditorGUILayout.PropertyField(followParentWorldScale);
EditorGUILayout.PropertyField(followSkeletonFlip);
if ((followSkeletonFlip.hasMultipleDifferentValues || followSkeletonFlip.boolValue == false) &&
(followBoneRotation.hasMultipleDifferentValues || followBoneRotation.boolValue == true)) {
using (new SpineInspectorUtility.IndentScope())
EditorGUILayout.PropertyField(maintainedAxisOrientation);
}
//BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
} else {
var boneFollowerSkeletonGraphic = targetBoneFollower.skeletonGraphic;
if (boneFollowerSkeletonGraphic == null) {
EditorGUILayout.HelpBox("SkeletonGraphic is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonMecanim).", MessageType.Warning);
} else {
boneFollowerSkeletonGraphic.Initialize(false);
if (boneFollowerSkeletonGraphic.skeletonDataAsset == null)
EditorGUILayout.HelpBox("Assigned SkeletonGraphic does not have SkeletonData assigned to it.", MessageType.Warning);
if (!boneFollowerSkeletonGraphic.IsValid)
EditorGUILayout.HelpBox("Assigned SkeletonGraphic is invalid. Check target SkeletonGraphic, its SkeletonData asset or the console for other errors.", MessageType.Warning);
}
}
var current = Event.current;
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
if (wasUndo)
targetBoneFollower.Initialize();
serializedObject.ApplyModifiedProperties();
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
using Event = UnityEngine.Event;
[CustomEditor(typeof(BoneFollowerGraphic)), CanEditMultipleObjects]
public class BoneFollowerGraphicInspector : Editor {
SerializedProperty boneName, skeletonGraphic, followXYPosition, followZPosition, followBoneRotation,
followLocalScale, followParentWorldScale, followSkeletonFlip, maintainedAxisOrientation;
BoneFollowerGraphic targetBoneFollower;
bool needsReset;
#region Context Menu Item
[MenuItem("CONTEXT/SkeletonGraphic/Add BoneFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonGraphic = cmd.context as SkeletonGraphic;
var go = EditorInstantiation.NewGameObject("BoneFollower", true, typeof(RectTransform));
var t = go.transform;
t.SetParent(skeletonGraphic.transform);
t.localPosition = Vector3.zero;
var f = go.AddComponent<BoneFollowerGraphic>();
f.skeletonGraphic = skeletonGraphic;
f.SetBone(skeletonGraphic.Skeleton.RootBone.Data.Name);
EditorGUIUtility.PingObject(t);
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollowerGraphic");
}
// Validate
[MenuItem("CONTEXT/SkeletonGraphic/Add BoneFollower GameObject", true)]
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonGraphic = cmd.context as SkeletonGraphic;
return skeletonGraphic.IsValid;
}
#endregion
void OnEnable () {
skeletonGraphic = serializedObject.FindProperty("skeletonGraphic");
boneName = serializedObject.FindProperty("boneName");
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
followXYPosition = serializedObject.FindProperty("followXYPosition");
followZPosition = serializedObject.FindProperty("followZPosition");
followLocalScale = serializedObject.FindProperty("followLocalScale");
followParentWorldScale = serializedObject.FindProperty("followParentWorldScale");
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
maintainedAxisOrientation = serializedObject.FindProperty("maintainedAxisOrientation");
targetBoneFollower = (BoneFollowerGraphic)target;
if (targetBoneFollower.SkeletonGraphic != null)
targetBoneFollower.SkeletonGraphic.Initialize(false);
if (!targetBoneFollower.valid || needsReset) {
targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
}
public void OnSceneGUI () {
var tbf = target as BoneFollowerGraphic;
var skeletonGraphicComponent = tbf.SkeletonGraphic;
if (skeletonGraphicComponent == null) return;
var transform = skeletonGraphicComponent.transform;
var skeleton = skeletonGraphicComponent.Skeleton;
var canvas = skeletonGraphicComponent.canvas;
float positionScale = canvas == null ? 1f : skeletonGraphicComponent.canvas.referencePixelsPerUnit;
if (string.IsNullOrEmpty(boneName.stringValue)) {
SpineHandles.DrawBones(transform, skeleton, positionScale);
SpineHandles.DrawBoneNames(transform, skeleton, positionScale);
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
} else {
var targetBone = tbf.bone;
if (targetBone == null) return;
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor, positionScale);
Handles.Label(targetBone.GetWorldPosition(transform, positionScale), targetBone.Data.Name, SpineHandles.BoneNameStyle);
}
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
if (needsReset) {
needsReset = false;
foreach (var o in targets) {
var bf = (BoneFollower)o;
bf.Initialize();
bf.LateUpdate();
}
SceneView.RepaintAll();
}
EditorGUI.BeginChangeCheck();
DrawDefaultInspector();
needsReset |= EditorGUI.EndChangeCheck();
return;
}
if (needsReset && Event.current.type == EventType.Layout) {
targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
serializedObject.Update();
// Find Renderer
if (skeletonGraphic.objectReferenceValue == null) {
SkeletonGraphic parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonGraphic>();
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
skeletonGraphic.objectReferenceValue = parentRenderer;
Debug.Log("Inspector automatically assigned BoneFollowerGraphic.SkeletonGraphic");
}
}
EditorGUILayout.PropertyField(skeletonGraphic);
var skeletonGraphicComponent = skeletonGraphic.objectReferenceValue as SkeletonGraphic;
if (skeletonGraphicComponent != null) {
if (skeletonGraphicComponent.gameObject == targetBoneFollower.gameObject) {
skeletonGraphic.objectReferenceValue = null;
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollowerGraphic can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonGraphic from a different GameObject.", "Ok");
}
}
if (!targetBoneFollower.valid) {
needsReset = true;
}
if (targetBoneFollower.valid) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(boneName);
needsReset |= EditorGUI.EndChangeCheck();
EditorGUILayout.PropertyField(followBoneRotation);
EditorGUILayout.PropertyField(followXYPosition);
EditorGUILayout.PropertyField(followZPosition);
EditorGUILayout.PropertyField(followLocalScale);
EditorGUILayout.PropertyField(followParentWorldScale);
EditorGUILayout.PropertyField(followSkeletonFlip);
if ((followSkeletonFlip.hasMultipleDifferentValues || followSkeletonFlip.boolValue == false) &&
(followBoneRotation.hasMultipleDifferentValues || followBoneRotation.boolValue == true)) {
using (new SpineInspectorUtility.IndentScope())
EditorGUILayout.PropertyField(maintainedAxisOrientation);
}
//BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
} else {
var boneFollowerSkeletonGraphic = targetBoneFollower.skeletonGraphic;
if (boneFollowerSkeletonGraphic == null) {
EditorGUILayout.HelpBox("SkeletonGraphic is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonMecanim).", MessageType.Warning);
} else {
boneFollowerSkeletonGraphic.Initialize(false);
if (boneFollowerSkeletonGraphic.skeletonDataAsset == null)
EditorGUILayout.HelpBox("Assigned SkeletonGraphic does not have SkeletonData assigned to it.", MessageType.Warning);
if (!boneFollowerSkeletonGraphic.IsValid)
EditorGUILayout.HelpBox("Assigned SkeletonGraphic is invalid. Check target SkeletonGraphic, its SkeletonData asset or the console for other errors.", MessageType.Warning);
}
}
var current = Event.current;
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
if (wasUndo)
targetBoneFollower.Initialize();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -1,230 +1,230 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
using Event = UnityEngine.Event;
[CustomEditor(typeof(BoneFollower)), CanEditMultipleObjects]
public class BoneFollowerInspector : Editor {
SerializedProperty boneName, skeletonRenderer, followXYPosition, followZPosition, followBoneRotation,
followLocalScale, followParentWorldScale, followSkeletonFlip, maintainedAxisOrientation;
BoneFollower targetBoneFollower;
bool needsReset;
#region Context Menu Item
[MenuItem("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var go = EditorInstantiation.NewGameObject("New BoneFollower", true);
var t = go.transform;
t.SetParent(skeletonRenderer.transform);
t.localPosition = Vector3.zero;
var f = go.AddComponent<BoneFollower>();
f.skeletonRenderer = skeletonRenderer;
EditorGUIUtility.PingObject(t);
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollower");
}
// Validate
[MenuItem("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject", true)]
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
return skeletonRenderer.valid;
}
[MenuItem("CONTEXT/BoneFollower/Rename BoneFollower GameObject")]
static void RenameGameObject (MenuCommand cmd) {
AutonameGameObject(cmd.context as BoneFollower);
}
#endregion
static void AutonameGameObject (BoneFollower boneFollower) {
if (boneFollower == null) return;
string boneName = boneFollower.boneName;
boneFollower.gameObject.name = string.IsNullOrEmpty(boneName) ? "BoneFollower" : string.Format("{0} (BoneFollower)", boneName);
}
void OnEnable () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
boneName = serializedObject.FindProperty("boneName");
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
followXYPosition = serializedObject.FindProperty("followXYPosition");
followZPosition = serializedObject.FindProperty("followZPosition");
followLocalScale = serializedObject.FindProperty("followLocalScale");
followParentWorldScale = serializedObject.FindProperty("followParentWorldScale");
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
maintainedAxisOrientation = serializedObject.FindProperty("maintainedAxisOrientation");
targetBoneFollower = (BoneFollower)target;
if (targetBoneFollower.SkeletonRenderer != null)
targetBoneFollower.SkeletonRenderer.Initialize(false);
if (!targetBoneFollower.valid || needsReset) {
targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
}
public void OnSceneGUI () {
var tbf = target as BoneFollower;
var skeletonRendererComponent = tbf.skeletonRenderer;
if (skeletonRendererComponent == null) return;
var transform = skeletonRendererComponent.transform;
var skeleton = skeletonRendererComponent.skeleton;
if (string.IsNullOrEmpty(boneName.stringValue)) {
SpineHandles.DrawBones(transform, skeleton);
SpineHandles.DrawBoneNames(transform, skeleton);
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
} else {
var targetBone = tbf.bone;
if (targetBone == null) return;
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor);
Handles.Label(targetBone.GetWorldPosition(transform), targetBone.Data.Name, SpineHandles.BoneNameStyle);
}
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
if (needsReset) {
needsReset = false;
foreach (var o in targets) {
var bf = (BoneFollower)o;
bf.Initialize();
bf.LateUpdate();
}
SceneView.RepaintAll();
}
EditorGUI.BeginChangeCheck();
DrawDefaultInspector();
needsReset |= EditorGUI.EndChangeCheck();
return;
}
if (needsReset && Event.current.type == EventType.Layout) {
targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
serializedObject.Update();
// Find Renderer
if (skeletonRenderer.objectReferenceValue == null) {
SkeletonRenderer parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonRenderer>();
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
skeletonRenderer.objectReferenceValue = parentRenderer;
Debug.Log("Inspector automatically assigned BoneFollower.SkeletonRenderer");
}
}
EditorGUILayout.PropertyField(skeletonRenderer);
var skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
if (skeletonRendererReference != null) {
if (skeletonRendererReference.gameObject == targetBoneFollower.gameObject) {
skeletonRenderer.objectReferenceValue = null;
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok");
}
}
if (!targetBoneFollower.valid) {
needsReset = true;
}
if (targetBoneFollower.valid) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(boneName);
needsReset |= EditorGUI.EndChangeCheck();
EditorGUILayout.PropertyField(followBoneRotation);
EditorGUILayout.PropertyField(followXYPosition);
EditorGUILayout.PropertyField(followZPosition);
EditorGUILayout.PropertyField(followLocalScale);
EditorGUILayout.PropertyField(followParentWorldScale);
EditorGUILayout.PropertyField(followSkeletonFlip);
if ((followSkeletonFlip.hasMultipleDifferentValues || followSkeletonFlip.boolValue == false) &&
(followBoneRotation.hasMultipleDifferentValues || followBoneRotation.boolValue == true)) {
using (new SpineInspectorUtility.IndentScope())
EditorGUILayout.PropertyField(maintainedAxisOrientation);
}
BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
} else {
var boneFollowerSkeletonRenderer = targetBoneFollower.skeletonRenderer;
if (boneFollowerSkeletonRenderer == null) {
EditorGUILayout.HelpBox("SkeletonRenderer is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonMecanim).", MessageType.Warning);
} else {
boneFollowerSkeletonRenderer.Initialize(false);
if (boneFollowerSkeletonRenderer.skeletonDataAsset == null)
EditorGUILayout.HelpBox("Assigned SkeletonRenderer does not have SkeletonData assigned to it.", MessageType.Warning);
if (!boneFollowerSkeletonRenderer.valid)
EditorGUILayout.HelpBox("Assigned SkeletonRenderer is invalid. Check target SkeletonRenderer, its SkeletonData asset or the console for other errors.", MessageType.Warning);
}
}
var current = Event.current;
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
if (wasUndo)
targetBoneFollower.Initialize();
serializedObject.ApplyModifiedProperties();
}
internal static void RecommendRigidbodyButton (Component component) {
bool hasCollider2D = component.GetComponent<Collider2D>() != null || component.GetComponent<BoundingBoxFollower>() != null;
bool hasCollider3D = !hasCollider2D && component.GetComponent<Collider>();
bool missingRigidBody = (hasCollider2D && component.GetComponent<Rigidbody2D>() == null) || (hasCollider3D && component.GetComponent<Rigidbody>() == null);
if (missingRigidBody) {
using (new SpineInspectorUtility.BoxScope()) {
EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning);
var rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody);
string rbLabel = string.Format("Add {0}", rbType.Name);
var rbContent = SpineInspectorUtility.TempContent(rbLabel, SpineInspectorUtility.UnityIcon(rbType), "Add a rigidbody to this GameObject to be the Physics body parent of the attached collider.");
if (SpineInspectorUtility.CenteredButton(rbContent)) component.gameObject.AddComponent(rbType);
}
}
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
using Event = UnityEngine.Event;
[CustomEditor(typeof(BoneFollower)), CanEditMultipleObjects]
public class BoneFollowerInspector : Editor {
SerializedProperty boneName, skeletonRenderer, followXYPosition, followZPosition, followBoneRotation,
followLocalScale, followParentWorldScale, followSkeletonFlip, maintainedAxisOrientation;
BoneFollower targetBoneFollower;
bool needsReset;
#region Context Menu Item
[MenuItem("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var go = EditorInstantiation.NewGameObject("New BoneFollower", true);
var t = go.transform;
t.SetParent(skeletonRenderer.transform);
t.localPosition = Vector3.zero;
var f = go.AddComponent<BoneFollower>();
f.skeletonRenderer = skeletonRenderer;
EditorGUIUtility.PingObject(t);
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollower");
}
// Validate
[MenuItem("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject", true)]
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
return skeletonRenderer.valid;
}
[MenuItem("CONTEXT/BoneFollower/Rename BoneFollower GameObject")]
static void RenameGameObject (MenuCommand cmd) {
AutonameGameObject(cmd.context as BoneFollower);
}
#endregion
static void AutonameGameObject (BoneFollower boneFollower) {
if (boneFollower == null) return;
string boneName = boneFollower.boneName;
boneFollower.gameObject.name = string.IsNullOrEmpty(boneName) ? "BoneFollower" : string.Format("{0} (BoneFollower)", boneName);
}
void OnEnable () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
boneName = serializedObject.FindProperty("boneName");
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
followXYPosition = serializedObject.FindProperty("followXYPosition");
followZPosition = serializedObject.FindProperty("followZPosition");
followLocalScale = serializedObject.FindProperty("followLocalScale");
followParentWorldScale = serializedObject.FindProperty("followParentWorldScale");
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
maintainedAxisOrientation = serializedObject.FindProperty("maintainedAxisOrientation");
targetBoneFollower = (BoneFollower)target;
if (targetBoneFollower.SkeletonRenderer != null)
targetBoneFollower.SkeletonRenderer.Initialize(false);
if (!targetBoneFollower.valid || needsReset) {
targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
}
public void OnSceneGUI () {
var tbf = target as BoneFollower;
var skeletonRendererComponent = tbf.skeletonRenderer;
if (skeletonRendererComponent == null) return;
var transform = skeletonRendererComponent.transform;
var skeleton = skeletonRendererComponent.skeleton;
if (string.IsNullOrEmpty(boneName.stringValue)) {
SpineHandles.DrawBones(transform, skeleton);
SpineHandles.DrawBoneNames(transform, skeleton);
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
} else {
var targetBone = tbf.bone;
if (targetBone == null) return;
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor);
Handles.Label(targetBone.GetWorldPosition(transform), targetBone.Data.Name, SpineHandles.BoneNameStyle);
}
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
if (needsReset) {
needsReset = false;
foreach (var o in targets) {
var bf = (BoneFollower)o;
bf.Initialize();
bf.LateUpdate();
}
SceneView.RepaintAll();
}
EditorGUI.BeginChangeCheck();
DrawDefaultInspector();
needsReset |= EditorGUI.EndChangeCheck();
return;
}
if (needsReset && Event.current.type == EventType.Layout) {
targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
serializedObject.Update();
// Find Renderer
if (skeletonRenderer.objectReferenceValue == null) {
SkeletonRenderer parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonRenderer>();
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
skeletonRenderer.objectReferenceValue = parentRenderer;
Debug.Log("Inspector automatically assigned BoneFollower.SkeletonRenderer");
}
}
EditorGUILayout.PropertyField(skeletonRenderer);
var skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
if (skeletonRendererReference != null) {
if (skeletonRendererReference.gameObject == targetBoneFollower.gameObject) {
skeletonRenderer.objectReferenceValue = null;
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok");
}
}
if (!targetBoneFollower.valid) {
needsReset = true;
}
if (targetBoneFollower.valid) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(boneName);
needsReset |= EditorGUI.EndChangeCheck();
EditorGUILayout.PropertyField(followBoneRotation);
EditorGUILayout.PropertyField(followXYPosition);
EditorGUILayout.PropertyField(followZPosition);
EditorGUILayout.PropertyField(followLocalScale);
EditorGUILayout.PropertyField(followParentWorldScale);
EditorGUILayout.PropertyField(followSkeletonFlip);
if ((followSkeletonFlip.hasMultipleDifferentValues || followSkeletonFlip.boolValue == false) &&
(followBoneRotation.hasMultipleDifferentValues || followBoneRotation.boolValue == true)) {
using (new SpineInspectorUtility.IndentScope())
EditorGUILayout.PropertyField(maintainedAxisOrientation);
}
BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
} else {
var boneFollowerSkeletonRenderer = targetBoneFollower.skeletonRenderer;
if (boneFollowerSkeletonRenderer == null) {
EditorGUILayout.HelpBox("SkeletonRenderer is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonMecanim).", MessageType.Warning);
} else {
boneFollowerSkeletonRenderer.Initialize(false);
if (boneFollowerSkeletonRenderer.skeletonDataAsset == null)
EditorGUILayout.HelpBox("Assigned SkeletonRenderer does not have SkeletonData assigned to it.", MessageType.Warning);
if (!boneFollowerSkeletonRenderer.valid)
EditorGUILayout.HelpBox("Assigned SkeletonRenderer is invalid. Check target SkeletonRenderer, its SkeletonData asset or the console for other errors.", MessageType.Warning);
}
}
var current = Event.current;
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
if (wasUndo)
targetBoneFollower.Initialize();
serializedObject.ApplyModifiedProperties();
}
internal static void RecommendRigidbodyButton (Component component) {
bool hasCollider2D = component.GetComponent<Collider2D>() != null || component.GetComponent<BoundingBoxFollower>() != null;
bool hasCollider3D = !hasCollider2D && component.GetComponent<Collider>();
bool missingRigidBody = (hasCollider2D && component.GetComponent<Rigidbody2D>() == null) || (hasCollider3D && component.GetComponent<Rigidbody>() == null);
if (missingRigidBody) {
using (new SpineInspectorUtility.BoxScope()) {
EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning);
var rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody);
string rbLabel = string.Format("Add {0}", rbType.Name);
var rbContent = SpineInspectorUtility.TempContent(rbLabel, SpineInspectorUtility.UnityIcon(rbType), "Add a rigidbody to this GameObject to be the Physics body parent of the attached collider.");
if (SpineInspectorUtility.CenteredButton(rbContent)) component.gameObject.AddComponent(rbType);
}
}
}
}
}

View File

@@ -1,271 +1,271 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
using Icons = SpineEditorUtilities.Icons;
[CustomEditor(typeof(BoundingBoxFollowerGraphic))]
public class BoundingBoxFollowerGraphicInspector : UnityEditor.Editor {
SerializedProperty skeletonGraphic, slotName,
isTrigger, usedByEffector, usedByComposite, clearStateOnDisable;
BoundingBoxFollowerGraphic follower;
bool rebuildRequired = false;
bool addBoneFollower = false;
bool sceneRepaintRequired = false;
bool debugIsExpanded;
GUIContent addBoneFollowerLabel;
GUIContent AddBoneFollowerLabel {
get {
if (addBoneFollowerLabel == null) addBoneFollowerLabel = new GUIContent("Add Bone Follower", Icons.bone);
return addBoneFollowerLabel;
}
}
void InitializeEditor () {
skeletonGraphic = serializedObject.FindProperty("skeletonGraphic");
slotName = serializedObject.FindProperty("slotName");
isTrigger = serializedObject.FindProperty("isTrigger");
usedByEffector = serializedObject.FindProperty("usedByEffector");
usedByComposite = serializedObject.FindProperty("usedByComposite");
clearStateOnDisable = serializedObject.FindProperty("clearStateOnDisable");
follower = (BoundingBoxFollowerGraphic)target;
}
public override void OnInspectorGUI () {
#if !NEW_PREFAB_SYSTEM
bool isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
#else
bool isInspectingPrefab = false;
#endif
// Note: when calling InitializeEditor() in OnEnable, it throws exception
// "SerializedObjectNotCreatableException: Object at index 0 is null".
InitializeEditor();
// Try to auto-assign SkeletonGraphic field.
if (skeletonGraphic.objectReferenceValue == null) {
var foundSkeletonGraphic = follower.GetComponentInParent<SkeletonGraphic>();
if (foundSkeletonGraphic != null)
Debug.Log("BoundingBoxFollowerGraphic automatically assigned: " + foundSkeletonGraphic.gameObject.name);
else if (Event.current.type == EventType.Repaint)
Debug.Log("No Spine GameObject detected. Make sure to set this GameObject as a child of the Spine GameObject; or set BoundingBoxFollowerGraphic's 'Skeleton Graphic' field in the inspector.");
skeletonGraphic.objectReferenceValue = foundSkeletonGraphic;
serializedObject.ApplyModifiedProperties();
InitializeEditor();
}
var skeletonGraphicValue = skeletonGraphic.objectReferenceValue as SkeletonGraphic;
if (skeletonGraphicValue != null && skeletonGraphicValue.gameObject == follower.gameObject) {
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
EditorGUILayout.HelpBox("It's ideal to add BoundingBoxFollowerGraphic to a separate child GameObject of the Spine GameObject.", MessageType.Warning);
if (GUILayout.Button(new GUIContent("Move BoundingBoxFollowerGraphic to new GameObject", Icons.boundingBox), GUILayout.Height(30f))) {
AddBoundingBoxFollowerGraphicChild(skeletonGraphicValue, follower);
DestroyImmediate(follower);
return;
}
}
EditorGUILayout.Space();
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(skeletonGraphic);
EditorGUILayout.PropertyField(slotName, new GUIContent("Slot"));
if (EditorGUI.EndChangeCheck()) {
serializedObject.ApplyModifiedProperties();
InitializeEditor();
#if !NEW_PREFAB_SYSTEM
if (!isInspectingPrefab)
rebuildRequired = true;
#endif
}
using (new SpineInspectorUtility.LabelWidthScope(150f)) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(isTrigger);
EditorGUILayout.PropertyField(usedByEffector);
EditorGUILayout.PropertyField(usedByComposite);
bool colliderParamChanged = EditorGUI.EndChangeCheck();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(clearStateOnDisable, new GUIContent(clearStateOnDisable.displayName, "Enable this if you are pooling your Spine GameObject"));
bool clearStateChanged = EditorGUI.EndChangeCheck();
if (clearStateChanged || colliderParamChanged) {
serializedObject.ApplyModifiedProperties();
InitializeEditor();
if (colliderParamChanged)
foreach (var col in follower.colliderTable.Values) {
col.isTrigger = isTrigger.boolValue;
col.usedByEffector = usedByEffector.boolValue;
col.usedByComposite = usedByComposite.boolValue;
}
}
}
if (isInspectingPrefab) {
follower.colliderTable.Clear();
follower.nameTable.Clear();
EditorGUILayout.HelpBox("BoundingBoxAttachments cannot be previewed in prefabs.", MessageType.Info);
// How do you prevent components from being saved into the prefab? No such HideFlag. DontSaveInEditor | DontSaveInBuild does not work. DestroyImmediate does not work.
var collider = follower.GetComponent<PolygonCollider2D>();
if (collider != null) Debug.LogWarning("Found BoundingBoxFollowerGraphic collider components in prefab. These are disposed and regenerated at runtime.");
} else {
using (new SpineInspectorUtility.BoxScope()) {
if (debugIsExpanded = EditorGUILayout.Foldout(debugIsExpanded, "Debug Colliders")) {
EditorGUI.indentLevel++;
EditorGUILayout.LabelField(string.Format("Attachment Names ({0} PolygonCollider2D)", follower.colliderTable.Count));
EditorGUI.BeginChangeCheck();
foreach (var kp in follower.nameTable) {
string attachmentName = kp.Value;
var collider = follower.colliderTable[kp.Key];
bool isPlaceholder = attachmentName != kp.Key.Name;
collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? attachmentName : string.Format("{0} [{1}]", attachmentName, kp.Key.Name), isPlaceholder ? Icons.skinPlaceholder : Icons.boundingBox), collider.enabled);
}
sceneRepaintRequired |= EditorGUI.EndChangeCheck();
EditorGUI.indentLevel--;
}
}
}
if (follower.Slot == null)
follower.Initialize(false);
bool hasBoneFollower = follower.GetComponent<BoneFollowerGraphic>() != null;
if (!hasBoneFollower) {
bool buttonDisabled = follower.Slot == null;
using (new EditorGUI.DisabledGroupScope(buttonDisabled)) {
addBoneFollower |= SpineInspectorUtility.LargeCenteredButton(AddBoneFollowerLabel, true);
EditorGUILayout.Space();
}
}
if (Event.current.type == EventType.Repaint) {
if (addBoneFollower) {
var boneFollower = follower.gameObject.AddComponent<BoneFollowerGraphic>();
boneFollower.skeletonGraphic = skeletonGraphicValue;
boneFollower.SetBone(follower.Slot.Data.BoneData.Name);
addBoneFollower = false;
}
if (sceneRepaintRequired) {
SceneView.RepaintAll();
sceneRepaintRequired = false;
}
if (rebuildRequired) {
follower.Initialize();
rebuildRequired = false;
}
}
}
#region Menus
[MenuItem("CONTEXT/SkeletonGraphic/Add BoundingBoxFollowerGraphic GameObject")]
static void AddBoundingBoxFollowerGraphicChild (MenuCommand command) {
var go = AddBoundingBoxFollowerGraphicChild((SkeletonGraphic)command.context);
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollowerGraphic");
}
[MenuItem("CONTEXT/SkeletonGraphic/Add all BoundingBoxFollowerGraphic GameObjects")]
static void AddAllBoundingBoxFollowerGraphicChildren (MenuCommand command) {
var objects = AddAllBoundingBoxFollowerGraphicChildren((SkeletonGraphic)command.context);
foreach (var go in objects)
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollowerGraphic");
}
#endregion
public static GameObject AddBoundingBoxFollowerGraphicChild (SkeletonGraphic skeletonGraphic,
BoundingBoxFollowerGraphic original = null, string name = "BoundingBoxFollowerGraphic",
string slotName = null) {
var go = EditorInstantiation.NewGameObject(name, true);
go.transform.SetParent(skeletonGraphic.transform, false);
go.AddComponent<RectTransform>();
var newFollower = go.AddComponent<BoundingBoxFollowerGraphic>();
if (original != null) {
newFollower.slotName = original.slotName;
newFollower.isTrigger = original.isTrigger;
newFollower.usedByEffector = original.usedByEffector;
newFollower.usedByComposite = original.usedByComposite;
newFollower.clearStateOnDisable = original.clearStateOnDisable;
}
if (slotName != null)
newFollower.slotName = slotName;
newFollower.skeletonGraphic = skeletonGraphic;
newFollower.Initialize();
Selection.activeGameObject = go;
EditorGUIUtility.PingObject(go);
return go;
}
public static List<GameObject> AddAllBoundingBoxFollowerGraphicChildren (
SkeletonGraphic skeletonGraphic, BoundingBoxFollowerGraphic original = null) {
List<GameObject> createdGameObjects = new List<GameObject>();
foreach (var skin in skeletonGraphic.Skeleton.Data.Skins) {
var attachments = skin.Attachments;
foreach (var entry in attachments) {
var boundingBoxAttachment = entry.Attachment as BoundingBoxAttachment;
if (boundingBoxAttachment == null)
continue;
int slotIndex = entry.SlotIndex;
var slot = skeletonGraphic.Skeleton.Slots.Items[slotIndex];
string slotName = slot.Data.Name;
GameObject go = AddBoundingBoxFollowerGraphicChild(skeletonGraphic,
original, boundingBoxAttachment.Name, slotName);
var boneFollower = go.AddComponent<BoneFollowerGraphic>();
boneFollower.skeletonGraphic = skeletonGraphic;
boneFollower.SetBone(slot.Data.BoneData.Name);
createdGameObjects.Add(go);
}
}
return createdGameObjects;
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
using Icons = SpineEditorUtilities.Icons;
[CustomEditor(typeof(BoundingBoxFollowerGraphic))]
public class BoundingBoxFollowerGraphicInspector : UnityEditor.Editor {
SerializedProperty skeletonGraphic, slotName,
isTrigger, usedByEffector, usedByComposite, clearStateOnDisable;
BoundingBoxFollowerGraphic follower;
bool rebuildRequired = false;
bool addBoneFollower = false;
bool sceneRepaintRequired = false;
bool debugIsExpanded;
GUIContent addBoneFollowerLabel;
GUIContent AddBoneFollowerLabel {
get {
if (addBoneFollowerLabel == null) addBoneFollowerLabel = new GUIContent("Add Bone Follower", Icons.bone);
return addBoneFollowerLabel;
}
}
void InitializeEditor () {
skeletonGraphic = serializedObject.FindProperty("skeletonGraphic");
slotName = serializedObject.FindProperty("slotName");
isTrigger = serializedObject.FindProperty("isTrigger");
usedByEffector = serializedObject.FindProperty("usedByEffector");
usedByComposite = serializedObject.FindProperty("usedByComposite");
clearStateOnDisable = serializedObject.FindProperty("clearStateOnDisable");
follower = (BoundingBoxFollowerGraphic)target;
}
public override void OnInspectorGUI () {
#if !NEW_PREFAB_SYSTEM
bool isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
#else
bool isInspectingPrefab = false;
#endif
// Note: when calling InitializeEditor() in OnEnable, it throws exception
// "SerializedObjectNotCreatableException: Object at index 0 is null".
InitializeEditor();
// Try to auto-assign SkeletonGraphic field.
if (skeletonGraphic.objectReferenceValue == null) {
var foundSkeletonGraphic = follower.GetComponentInParent<SkeletonGraphic>();
if (foundSkeletonGraphic != null)
Debug.Log("BoundingBoxFollowerGraphic automatically assigned: " + foundSkeletonGraphic.gameObject.name);
else if (Event.current.type == EventType.Repaint)
Debug.Log("No Spine GameObject detected. Make sure to set this GameObject as a child of the Spine GameObject; or set BoundingBoxFollowerGraphic's 'Skeleton Graphic' field in the inspector.");
skeletonGraphic.objectReferenceValue = foundSkeletonGraphic;
serializedObject.ApplyModifiedProperties();
InitializeEditor();
}
var skeletonGraphicValue = skeletonGraphic.objectReferenceValue as SkeletonGraphic;
if (skeletonGraphicValue != null && skeletonGraphicValue.gameObject == follower.gameObject) {
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
EditorGUILayout.HelpBox("It's ideal to add BoundingBoxFollowerGraphic to a separate child GameObject of the Spine GameObject.", MessageType.Warning);
if (GUILayout.Button(new GUIContent("Move BoundingBoxFollowerGraphic to new GameObject", Icons.boundingBox), GUILayout.Height(30f))) {
AddBoundingBoxFollowerGraphicChild(skeletonGraphicValue, follower);
DestroyImmediate(follower);
return;
}
}
EditorGUILayout.Space();
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(skeletonGraphic);
EditorGUILayout.PropertyField(slotName, new GUIContent("Slot"));
if (EditorGUI.EndChangeCheck()) {
serializedObject.ApplyModifiedProperties();
InitializeEditor();
#if !NEW_PREFAB_SYSTEM
if (!isInspectingPrefab)
rebuildRequired = true;
#endif
}
using (new SpineInspectorUtility.LabelWidthScope(150f)) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(isTrigger);
EditorGUILayout.PropertyField(usedByEffector);
EditorGUILayout.PropertyField(usedByComposite);
bool colliderParamChanged = EditorGUI.EndChangeCheck();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(clearStateOnDisable, new GUIContent(clearStateOnDisable.displayName, "Enable this if you are pooling your Spine GameObject"));
bool clearStateChanged = EditorGUI.EndChangeCheck();
if (clearStateChanged || colliderParamChanged) {
serializedObject.ApplyModifiedProperties();
InitializeEditor();
if (colliderParamChanged)
foreach (var col in follower.colliderTable.Values) {
col.isTrigger = isTrigger.boolValue;
col.usedByEffector = usedByEffector.boolValue;
col.usedByComposite = usedByComposite.boolValue;
}
}
}
if (isInspectingPrefab) {
follower.colliderTable.Clear();
follower.nameTable.Clear();
EditorGUILayout.HelpBox("BoundingBoxAttachments cannot be previewed in prefabs.", MessageType.Info);
// How do you prevent components from being saved into the prefab? No such HideFlag. DontSaveInEditor | DontSaveInBuild does not work. DestroyImmediate does not work.
var collider = follower.GetComponent<PolygonCollider2D>();
if (collider != null) Debug.LogWarning("Found BoundingBoxFollowerGraphic collider components in prefab. These are disposed and regenerated at runtime.");
} else {
using (new SpineInspectorUtility.BoxScope()) {
if (debugIsExpanded = EditorGUILayout.Foldout(debugIsExpanded, "Debug Colliders")) {
EditorGUI.indentLevel++;
EditorGUILayout.LabelField(string.Format("Attachment Names ({0} PolygonCollider2D)", follower.colliderTable.Count));
EditorGUI.BeginChangeCheck();
foreach (var kp in follower.nameTable) {
string attachmentName = kp.Value;
var collider = follower.colliderTable[kp.Key];
bool isPlaceholder = attachmentName != kp.Key.Name;
collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? attachmentName : string.Format("{0} [{1}]", attachmentName, kp.Key.Name), isPlaceholder ? Icons.skinPlaceholder : Icons.boundingBox), collider.enabled);
}
sceneRepaintRequired |= EditorGUI.EndChangeCheck();
EditorGUI.indentLevel--;
}
}
}
if (follower.Slot == null)
follower.Initialize(false);
bool hasBoneFollower = follower.GetComponent<BoneFollowerGraphic>() != null;
if (!hasBoneFollower) {
bool buttonDisabled = follower.Slot == null;
using (new EditorGUI.DisabledGroupScope(buttonDisabled)) {
addBoneFollower |= SpineInspectorUtility.LargeCenteredButton(AddBoneFollowerLabel, true);
EditorGUILayout.Space();
}
}
if (Event.current.type == EventType.Repaint) {
if (addBoneFollower) {
var boneFollower = follower.gameObject.AddComponent<BoneFollowerGraphic>();
boneFollower.skeletonGraphic = skeletonGraphicValue;
boneFollower.SetBone(follower.Slot.Data.BoneData.Name);
addBoneFollower = false;
}
if (sceneRepaintRequired) {
SceneView.RepaintAll();
sceneRepaintRequired = false;
}
if (rebuildRequired) {
follower.Initialize();
rebuildRequired = false;
}
}
}
#region Menus
[MenuItem("CONTEXT/SkeletonGraphic/Add BoundingBoxFollowerGraphic GameObject")]
static void AddBoundingBoxFollowerGraphicChild (MenuCommand command) {
var go = AddBoundingBoxFollowerGraphicChild((SkeletonGraphic)command.context);
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollowerGraphic");
}
[MenuItem("CONTEXT/SkeletonGraphic/Add all BoundingBoxFollowerGraphic GameObjects")]
static void AddAllBoundingBoxFollowerGraphicChildren (MenuCommand command) {
var objects = AddAllBoundingBoxFollowerGraphicChildren((SkeletonGraphic)command.context);
foreach (var go in objects)
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollowerGraphic");
}
#endregion
public static GameObject AddBoundingBoxFollowerGraphicChild (SkeletonGraphic skeletonGraphic,
BoundingBoxFollowerGraphic original = null, string name = "BoundingBoxFollowerGraphic",
string slotName = null) {
var go = EditorInstantiation.NewGameObject(name, true);
go.transform.SetParent(skeletonGraphic.transform, false);
go.AddComponent<RectTransform>();
var newFollower = go.AddComponent<BoundingBoxFollowerGraphic>();
if (original != null) {
newFollower.slotName = original.slotName;
newFollower.isTrigger = original.isTrigger;
newFollower.usedByEffector = original.usedByEffector;
newFollower.usedByComposite = original.usedByComposite;
newFollower.clearStateOnDisable = original.clearStateOnDisable;
}
if (slotName != null)
newFollower.slotName = slotName;
newFollower.skeletonGraphic = skeletonGraphic;
newFollower.Initialize();
Selection.activeGameObject = go;
EditorGUIUtility.PingObject(go);
return go;
}
public static List<GameObject> AddAllBoundingBoxFollowerGraphicChildren (
SkeletonGraphic skeletonGraphic, BoundingBoxFollowerGraphic original = null) {
List<GameObject> createdGameObjects = new List<GameObject>();
foreach (var skin in skeletonGraphic.Skeleton.Data.Skins) {
var attachments = skin.Attachments;
foreach (var entry in attachments) {
var boundingBoxAttachment = entry.Attachment as BoundingBoxAttachment;
if (boundingBoxAttachment == null)
continue;
int slotIndex = entry.SlotIndex;
var slot = skeletonGraphic.Skeleton.Slots.Items[slotIndex];
string slotName = slot.Data.Name;
GameObject go = AddBoundingBoxFollowerGraphicChild(skeletonGraphic,
original, boundingBoxAttachment.Name, slotName);
var boneFollower = go.AddComponent<BoneFollowerGraphic>();
boneFollower.skeletonGraphic = skeletonGraphic;
boneFollower.SetBone(slot.Data.BoneData.Name);
createdGameObjects.Add(go);
}
}
return createdGameObjects;
}
}
}

View File

@@ -1,270 +1,270 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
using Icons = SpineEditorUtilities.Icons;
[CustomEditor(typeof(BoundingBoxFollower))]
public class BoundingBoxFollowerInspector : UnityEditor.Editor {
SerializedProperty skeletonRenderer, slotName,
isTrigger, usedByEffector, usedByComposite, clearStateOnDisable;
BoundingBoxFollower follower;
bool rebuildRequired = false;
bool addBoneFollower = false;
bool sceneRepaintRequired = false;
bool debugIsExpanded;
GUIContent addBoneFollowerLabel;
GUIContent AddBoneFollowerLabel {
get {
if (addBoneFollowerLabel == null) addBoneFollowerLabel = new GUIContent("Add Bone Follower", Icons.bone);
return addBoneFollowerLabel;
}
}
void InitializeEditor () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
slotName = serializedObject.FindProperty("slotName");
isTrigger = serializedObject.FindProperty("isTrigger");
usedByEffector = serializedObject.FindProperty("usedByEffector");
usedByComposite = serializedObject.FindProperty("usedByComposite");
clearStateOnDisable = serializedObject.FindProperty("clearStateOnDisable");
follower = (BoundingBoxFollower)target;
}
public override void OnInspectorGUI () {
#if !NEW_PREFAB_SYSTEM
bool isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
#else
bool isInspectingPrefab = false;
#endif
// Note: when calling InitializeEditor() in OnEnable, it throws exception
// "SerializedObjectNotCreatableException: Object at index 0 is null".
InitializeEditor();
// Try to auto-assign SkeletonRenderer field.
if (skeletonRenderer.objectReferenceValue == null) {
var foundSkeletonRenderer = follower.GetComponentInParent<SkeletonRenderer>();
if (foundSkeletonRenderer != null)
Debug.Log("BoundingBoxFollower automatically assigned: " + foundSkeletonRenderer.gameObject.name);
else if (Event.current.type == EventType.Repaint)
Debug.Log("No Spine GameObject detected. Make sure to set this GameObject as a child of the Spine GameObject; or set BoundingBoxFollower's 'Skeleton Renderer' field in the inspector.");
skeletonRenderer.objectReferenceValue = foundSkeletonRenderer;
serializedObject.ApplyModifiedProperties();
InitializeEditor();
}
var skeletonRendererValue = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
if (skeletonRendererValue != null && skeletonRendererValue.gameObject == follower.gameObject) {
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
EditorGUILayout.HelpBox("It's ideal to add BoundingBoxFollower to a separate child GameObject of the Spine GameObject.", MessageType.Warning);
if (GUILayout.Button(new GUIContent("Move BoundingBoxFollower to new GameObject", Icons.boundingBox), GUILayout.Height(30f))) {
AddBoundingBoxFollowerChild(skeletonRendererValue, follower);
DestroyImmediate(follower);
return;
}
}
EditorGUILayout.Space();
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(skeletonRenderer);
EditorGUILayout.PropertyField(slotName, new GUIContent("Slot"));
if (EditorGUI.EndChangeCheck()) {
serializedObject.ApplyModifiedProperties();
InitializeEditor();
#if !NEW_PREFAB_SYSTEM
if (!isInspectingPrefab)
rebuildRequired = true;
#endif
}
using (new SpineInspectorUtility.LabelWidthScope(150f)) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(isTrigger);
EditorGUILayout.PropertyField(usedByEffector);
EditorGUILayout.PropertyField(usedByComposite);
bool colliderParamChanged = EditorGUI.EndChangeCheck();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(clearStateOnDisable, new GUIContent(clearStateOnDisable.displayName, "Enable this if you are pooling your Spine GameObject"));
bool clearStateChanged = EditorGUI.EndChangeCheck();
if (clearStateChanged || colliderParamChanged) {
serializedObject.ApplyModifiedProperties();
InitializeEditor();
if (colliderParamChanged)
foreach (var col in follower.colliderTable.Values) {
col.isTrigger = isTrigger.boolValue;
col.usedByEffector = usedByEffector.boolValue;
col.usedByComposite = usedByComposite.boolValue;
}
}
}
if (isInspectingPrefab) {
follower.colliderTable.Clear();
follower.nameTable.Clear();
EditorGUILayout.HelpBox("BoundingBoxAttachments cannot be previewed in prefabs.", MessageType.Info);
// How do you prevent components from being saved into the prefab? No such HideFlag. DontSaveInEditor | DontSaveInBuild does not work. DestroyImmediate does not work.
var collider = follower.GetComponent<PolygonCollider2D>();
if (collider != null) Debug.LogWarning("Found BoundingBoxFollower collider components in prefab. These are disposed and regenerated at runtime.");
} else {
using (new SpineInspectorUtility.BoxScope()) {
if (debugIsExpanded = EditorGUILayout.Foldout(debugIsExpanded, "Debug Colliders")) {
EditorGUI.indentLevel++;
EditorGUILayout.LabelField(string.Format("Attachment Names ({0} PolygonCollider2D)", follower.colliderTable.Count));
EditorGUI.BeginChangeCheck();
foreach (var kp in follower.nameTable) {
string attachmentName = kp.Value;
var collider = follower.colliderTable[kp.Key];
bool isPlaceholder = attachmentName != kp.Key.Name;
collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? attachmentName : string.Format("{0} [{1}]", attachmentName, kp.Key.Name), isPlaceholder ? Icons.skinPlaceholder : Icons.boundingBox), collider.enabled);
}
sceneRepaintRequired |= EditorGUI.EndChangeCheck();
EditorGUI.indentLevel--;
}
}
}
if (follower.Slot == null)
follower.Initialize(false);
bool hasBoneFollower = follower.GetComponent<BoneFollower>() != null;
if (!hasBoneFollower) {
bool buttonDisabled = follower.Slot == null;
using (new EditorGUI.DisabledGroupScope(buttonDisabled)) {
addBoneFollower |= SpineInspectorUtility.LargeCenteredButton(AddBoneFollowerLabel, true);
EditorGUILayout.Space();
}
}
if (Event.current.type == EventType.Repaint) {
if (addBoneFollower) {
var boneFollower = follower.gameObject.AddComponent<BoneFollower>();
boneFollower.skeletonRenderer = skeletonRendererValue;
boneFollower.SetBone(follower.Slot.Data.BoneData.Name);
addBoneFollower = false;
}
if (sceneRepaintRequired) {
SceneView.RepaintAll();
sceneRepaintRequired = false;
}
if (rebuildRequired) {
follower.Initialize();
rebuildRequired = false;
}
}
}
#region Menus
[MenuItem("CONTEXT/SkeletonRenderer/Add BoundingBoxFollower GameObject")]
static void AddBoundingBoxFollowerChild (MenuCommand command) {
var go = AddBoundingBoxFollowerChild((SkeletonRenderer)command.context);
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollower");
}
[MenuItem("CONTEXT/SkeletonRenderer/Add all BoundingBoxFollower GameObjects")]
static void AddAllBoundingBoxFollowerChildren (MenuCommand command) {
var objects = AddAllBoundingBoxFollowerChildren((SkeletonRenderer)command.context);
foreach (var go in objects)
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollower");
}
#endregion
public static GameObject AddBoundingBoxFollowerChild (SkeletonRenderer skeletonRenderer,
BoundingBoxFollower original = null, string name = "BoundingBoxFollower",
string slotName = null) {
var go = EditorInstantiation.NewGameObject(name, true);
go.transform.SetParent(skeletonRenderer.transform, false);
var newFollower = go.AddComponent<BoundingBoxFollower>();
if (original != null) {
newFollower.slotName = original.slotName;
newFollower.isTrigger = original.isTrigger;
newFollower.usedByEffector = original.usedByEffector;
newFollower.usedByComposite = original.usedByComposite;
newFollower.clearStateOnDisable = original.clearStateOnDisable;
}
if (slotName != null)
newFollower.slotName = slotName;
newFollower.skeletonRenderer = skeletonRenderer;
newFollower.Initialize();
Selection.activeGameObject = go;
EditorGUIUtility.PingObject(go);
return go;
}
public static List<GameObject> AddAllBoundingBoxFollowerChildren (
SkeletonRenderer skeletonRenderer, BoundingBoxFollower original = null) {
List<GameObject> createdGameObjects = new List<GameObject>();
foreach (var skin in skeletonRenderer.Skeleton.Data.Skins) {
var attachments = skin.Attachments;
foreach (var entry in attachments) {
var boundingBoxAttachment = entry.Attachment as BoundingBoxAttachment;
if (boundingBoxAttachment == null)
continue;
int slotIndex = entry.SlotIndex;
var slot = skeletonRenderer.Skeleton.Slots.Items[slotIndex];
string slotName = slot.Data.Name;
GameObject go = AddBoundingBoxFollowerChild(skeletonRenderer,
original, boundingBoxAttachment.Name, slotName);
var boneFollower = go.AddComponent<BoneFollower>();
boneFollower.skeletonRenderer = skeletonRenderer;
boneFollower.SetBone(slot.Data.BoneData.Name);
createdGameObjects.Add(go);
}
}
return createdGameObjects;
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
using Icons = SpineEditorUtilities.Icons;
[CustomEditor(typeof(BoundingBoxFollower))]
public class BoundingBoxFollowerInspector : UnityEditor.Editor {
SerializedProperty skeletonRenderer, slotName,
isTrigger, usedByEffector, usedByComposite, clearStateOnDisable;
BoundingBoxFollower follower;
bool rebuildRequired = false;
bool addBoneFollower = false;
bool sceneRepaintRequired = false;
bool debugIsExpanded;
GUIContent addBoneFollowerLabel;
GUIContent AddBoneFollowerLabel {
get {
if (addBoneFollowerLabel == null) addBoneFollowerLabel = new GUIContent("Add Bone Follower", Icons.bone);
return addBoneFollowerLabel;
}
}
void InitializeEditor () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
slotName = serializedObject.FindProperty("slotName");
isTrigger = serializedObject.FindProperty("isTrigger");
usedByEffector = serializedObject.FindProperty("usedByEffector");
usedByComposite = serializedObject.FindProperty("usedByComposite");
clearStateOnDisable = serializedObject.FindProperty("clearStateOnDisable");
follower = (BoundingBoxFollower)target;
}
public override void OnInspectorGUI () {
#if !NEW_PREFAB_SYSTEM
bool isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
#else
bool isInspectingPrefab = false;
#endif
// Note: when calling InitializeEditor() in OnEnable, it throws exception
// "SerializedObjectNotCreatableException: Object at index 0 is null".
InitializeEditor();
// Try to auto-assign SkeletonRenderer field.
if (skeletonRenderer.objectReferenceValue == null) {
var foundSkeletonRenderer = follower.GetComponentInParent<SkeletonRenderer>();
if (foundSkeletonRenderer != null)
Debug.Log("BoundingBoxFollower automatically assigned: " + foundSkeletonRenderer.gameObject.name);
else if (Event.current.type == EventType.Repaint)
Debug.Log("No Spine GameObject detected. Make sure to set this GameObject as a child of the Spine GameObject; or set BoundingBoxFollower's 'Skeleton Renderer' field in the inspector.");
skeletonRenderer.objectReferenceValue = foundSkeletonRenderer;
serializedObject.ApplyModifiedProperties();
InitializeEditor();
}
var skeletonRendererValue = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
if (skeletonRendererValue != null && skeletonRendererValue.gameObject == follower.gameObject) {
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
EditorGUILayout.HelpBox("It's ideal to add BoundingBoxFollower to a separate child GameObject of the Spine GameObject.", MessageType.Warning);
if (GUILayout.Button(new GUIContent("Move BoundingBoxFollower to new GameObject", Icons.boundingBox), GUILayout.Height(30f))) {
AddBoundingBoxFollowerChild(skeletonRendererValue, follower);
DestroyImmediate(follower);
return;
}
}
EditorGUILayout.Space();
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(skeletonRenderer);
EditorGUILayout.PropertyField(slotName, new GUIContent("Slot"));
if (EditorGUI.EndChangeCheck()) {
serializedObject.ApplyModifiedProperties();
InitializeEditor();
#if !NEW_PREFAB_SYSTEM
if (!isInspectingPrefab)
rebuildRequired = true;
#endif
}
using (new SpineInspectorUtility.LabelWidthScope(150f)) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(isTrigger);
EditorGUILayout.PropertyField(usedByEffector);
EditorGUILayout.PropertyField(usedByComposite);
bool colliderParamChanged = EditorGUI.EndChangeCheck();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(clearStateOnDisable, new GUIContent(clearStateOnDisable.displayName, "Enable this if you are pooling your Spine GameObject"));
bool clearStateChanged = EditorGUI.EndChangeCheck();
if (clearStateChanged || colliderParamChanged) {
serializedObject.ApplyModifiedProperties();
InitializeEditor();
if (colliderParamChanged)
foreach (var col in follower.colliderTable.Values) {
col.isTrigger = isTrigger.boolValue;
col.usedByEffector = usedByEffector.boolValue;
col.usedByComposite = usedByComposite.boolValue;
}
}
}
if (isInspectingPrefab) {
follower.colliderTable.Clear();
follower.nameTable.Clear();
EditorGUILayout.HelpBox("BoundingBoxAttachments cannot be previewed in prefabs.", MessageType.Info);
// How do you prevent components from being saved into the prefab? No such HideFlag. DontSaveInEditor | DontSaveInBuild does not work. DestroyImmediate does not work.
var collider = follower.GetComponent<PolygonCollider2D>();
if (collider != null) Debug.LogWarning("Found BoundingBoxFollower collider components in prefab. These are disposed and regenerated at runtime.");
} else {
using (new SpineInspectorUtility.BoxScope()) {
if (debugIsExpanded = EditorGUILayout.Foldout(debugIsExpanded, "Debug Colliders")) {
EditorGUI.indentLevel++;
EditorGUILayout.LabelField(string.Format("Attachment Names ({0} PolygonCollider2D)", follower.colliderTable.Count));
EditorGUI.BeginChangeCheck();
foreach (var kp in follower.nameTable) {
string attachmentName = kp.Value;
var collider = follower.colliderTable[kp.Key];
bool isPlaceholder = attachmentName != kp.Key.Name;
collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? attachmentName : string.Format("{0} [{1}]", attachmentName, kp.Key.Name), isPlaceholder ? Icons.skinPlaceholder : Icons.boundingBox), collider.enabled);
}
sceneRepaintRequired |= EditorGUI.EndChangeCheck();
EditorGUI.indentLevel--;
}
}
}
if (follower.Slot == null)
follower.Initialize(false);
bool hasBoneFollower = follower.GetComponent<BoneFollower>() != null;
if (!hasBoneFollower) {
bool buttonDisabled = follower.Slot == null;
using (new EditorGUI.DisabledGroupScope(buttonDisabled)) {
addBoneFollower |= SpineInspectorUtility.LargeCenteredButton(AddBoneFollowerLabel, true);
EditorGUILayout.Space();
}
}
if (Event.current.type == EventType.Repaint) {
if (addBoneFollower) {
var boneFollower = follower.gameObject.AddComponent<BoneFollower>();
boneFollower.skeletonRenderer = skeletonRendererValue;
boneFollower.SetBone(follower.Slot.Data.BoneData.Name);
addBoneFollower = false;
}
if (sceneRepaintRequired) {
SceneView.RepaintAll();
sceneRepaintRequired = false;
}
if (rebuildRequired) {
follower.Initialize();
rebuildRequired = false;
}
}
}
#region Menus
[MenuItem("CONTEXT/SkeletonRenderer/Add BoundingBoxFollower GameObject")]
static void AddBoundingBoxFollowerChild (MenuCommand command) {
var go = AddBoundingBoxFollowerChild((SkeletonRenderer)command.context);
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollower");
}
[MenuItem("CONTEXT/SkeletonRenderer/Add all BoundingBoxFollower GameObjects")]
static void AddAllBoundingBoxFollowerChildren (MenuCommand command) {
var objects = AddAllBoundingBoxFollowerChildren((SkeletonRenderer)command.context);
foreach (var go in objects)
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollower");
}
#endregion
public static GameObject AddBoundingBoxFollowerChild (SkeletonRenderer skeletonRenderer,
BoundingBoxFollower original = null, string name = "BoundingBoxFollower",
string slotName = null) {
var go = EditorInstantiation.NewGameObject(name, true);
go.transform.SetParent(skeletonRenderer.transform, false);
var newFollower = go.AddComponent<BoundingBoxFollower>();
if (original != null) {
newFollower.slotName = original.slotName;
newFollower.isTrigger = original.isTrigger;
newFollower.usedByEffector = original.usedByEffector;
newFollower.usedByComposite = original.usedByComposite;
newFollower.clearStateOnDisable = original.clearStateOnDisable;
}
if (slotName != null)
newFollower.slotName = slotName;
newFollower.skeletonRenderer = skeletonRenderer;
newFollower.Initialize();
Selection.activeGameObject = go;
EditorGUIUtility.PingObject(go);
return go;
}
public static List<GameObject> AddAllBoundingBoxFollowerChildren (
SkeletonRenderer skeletonRenderer, BoundingBoxFollower original = null) {
List<GameObject> createdGameObjects = new List<GameObject>();
foreach (var skin in skeletonRenderer.Skeleton.Data.Skins) {
var attachments = skin.Attachments;
foreach (var entry in attachments) {
var boundingBoxAttachment = entry.Attachment as BoundingBoxAttachment;
if (boundingBoxAttachment == null)
continue;
int slotIndex = entry.SlotIndex;
var slot = skeletonRenderer.Skeleton.Slots.Items[slotIndex];
string slotName = slot.Data.Name;
GameObject go = AddBoundingBoxFollowerChild(skeletonRenderer,
original, boundingBoxAttachment.Name, slotName);
var boneFollower = go.AddComponent<BoneFollower>();
boneFollower.skeletonRenderer = skeletonRenderer;
boneFollower.SetBone(slot.Data.BoneData.Name);
createdGameObjects.Add(go);
}
}
return createdGameObjects;
}
}
}

View File

@@ -1,187 +1,187 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
using Event = UnityEngine.Event;
[CustomEditor(typeof(PointFollower)), CanEditMultipleObjects]
public class PointFollowerInspector : Editor {
SerializedProperty slotName, pointAttachmentName, skeletonRenderer, followZPosition, followBoneRotation, followSkeletonFlip;
PointFollower targetPointFollower;
bool needsReset;
#region Context Menu Item
[MenuItem("CONTEXT/SkeletonRenderer/Add PointFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var go = EditorInstantiation.NewGameObject("PointFollower", true);
var t = go.transform;
t.SetParent(skeletonRenderer.transform);
t.localPosition = Vector3.zero;
var f = go.AddComponent<PointFollower>();
f.skeletonRenderer = skeletonRenderer;
EditorGUIUtility.PingObject(t);
Undo.RegisterCreatedObjectUndo(go, "Add PointFollower");
}
// Validate
[MenuItem("CONTEXT/SkeletonRenderer/Add PointFollower GameObject", true)]
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
return skeletonRenderer.valid;
}
#endregion
void OnEnable () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
slotName = serializedObject.FindProperty("slotName");
pointAttachmentName = serializedObject.FindProperty("pointAttachmentName");
targetPointFollower = (PointFollower)target;
if (targetPointFollower.skeletonRenderer != null)
targetPointFollower.skeletonRenderer.Initialize(false);
if (!targetPointFollower.IsValid || needsReset) {
targetPointFollower.Initialize();
targetPointFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
}
public void OnSceneGUI () {
var tbf = target as PointFollower;
var skeletonRendererComponent = tbf.skeletonRenderer;
if (skeletonRendererComponent == null)
return;
var skeleton = skeletonRendererComponent.skeleton;
var skeletonTransform = skeletonRendererComponent.transform;
if (string.IsNullOrEmpty(pointAttachmentName.stringValue)) {
// Draw all active PointAttachments in the current skin
var currentSkin = skeleton.Skin;
if (currentSkin != skeleton.Data.DefaultSkin) DrawPointsInSkin(skeleton.Data.DefaultSkin, skeleton, skeletonTransform);
if (currentSkin != null) DrawPointsInSkin(currentSkin, skeleton, skeletonTransform);
} else {
Slot slot = skeleton.FindSlot(slotName.stringValue);
if (slot != null) {
int slotIndex = slot.Data.Index;
var point = skeleton.GetAttachment(slotIndex, pointAttachmentName.stringValue) as PointAttachment;
if (point != null) {
DrawPointAttachmentWithLabel(point, slot.Bone, skeletonTransform);
}
}
}
}
static void DrawPointsInSkin (Skin skin, Skeleton skeleton, Transform transform) {
foreach (var skinEntry in skin.Attachments) {
var attachment = skinEntry.Attachment as PointAttachment;
if (attachment != null) {
var slot = skeleton.Slots.Items[skinEntry.SlotIndex];
DrawPointAttachmentWithLabel(attachment, slot.Bone, transform);
}
}
}
static void DrawPointAttachmentWithLabel (PointAttachment point, Bone bone, Transform transform) {
Vector3 labelOffset = new Vector3(0f, -0.2f, 0f);
SpineHandles.DrawPointAttachment(bone, point, transform);
Handles.Label(labelOffset + point.GetWorldPosition(bone, transform), point.Name, SpineHandles.PointNameStyle);
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
if (needsReset) {
needsReset = false;
foreach (var o in targets) {
var bf = (BoneFollower)o;
bf.Initialize();
bf.LateUpdate();
}
SceneView.RepaintAll();
}
EditorGUI.BeginChangeCheck();
DrawDefaultInspector();
needsReset |= EditorGUI.EndChangeCheck();
return;
}
if (needsReset && Event.current.type == EventType.Layout) {
targetPointFollower.Initialize();
targetPointFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
serializedObject.Update();
DrawDefaultInspector();
// Find Renderer
if (skeletonRenderer.objectReferenceValue == null) {
SkeletonRenderer parentRenderer = targetPointFollower.GetComponentInParent<SkeletonRenderer>();
if (parentRenderer != null && parentRenderer.gameObject != targetPointFollower.gameObject) {
skeletonRenderer.objectReferenceValue = parentRenderer;
Debug.Log("Inspector automatically assigned PointFollower.SkeletonRenderer");
}
}
var skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
if (skeletonRendererReference != null) {
if (skeletonRendererReference.gameObject == targetPointFollower.gameObject) {
skeletonRenderer.objectReferenceValue = null;
EditorUtility.DisplayDialog("Invalid assignment.", "PointFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your PointFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok");
}
}
if (!targetPointFollower.IsValid) {
needsReset = true;
}
var current = Event.current;
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
if (wasUndo)
targetPointFollower.Initialize();
serializedObject.ApplyModifiedProperties();
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
using Event = UnityEngine.Event;
[CustomEditor(typeof(PointFollower)), CanEditMultipleObjects]
public class PointFollowerInspector : Editor {
SerializedProperty slotName, pointAttachmentName, skeletonRenderer, followZPosition, followBoneRotation, followSkeletonFlip;
PointFollower targetPointFollower;
bool needsReset;
#region Context Menu Item
[MenuItem("CONTEXT/SkeletonRenderer/Add PointFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var go = EditorInstantiation.NewGameObject("PointFollower", true);
var t = go.transform;
t.SetParent(skeletonRenderer.transform);
t.localPosition = Vector3.zero;
var f = go.AddComponent<PointFollower>();
f.skeletonRenderer = skeletonRenderer;
EditorGUIUtility.PingObject(t);
Undo.RegisterCreatedObjectUndo(go, "Add PointFollower");
}
// Validate
[MenuItem("CONTEXT/SkeletonRenderer/Add PointFollower GameObject", true)]
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
return skeletonRenderer.valid;
}
#endregion
void OnEnable () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
slotName = serializedObject.FindProperty("slotName");
pointAttachmentName = serializedObject.FindProperty("pointAttachmentName");
targetPointFollower = (PointFollower)target;
if (targetPointFollower.skeletonRenderer != null)
targetPointFollower.skeletonRenderer.Initialize(false);
if (!targetPointFollower.IsValid || needsReset) {
targetPointFollower.Initialize();
targetPointFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
}
public void OnSceneGUI () {
var tbf = target as PointFollower;
var skeletonRendererComponent = tbf.skeletonRenderer;
if (skeletonRendererComponent == null)
return;
var skeleton = skeletonRendererComponent.skeleton;
var skeletonTransform = skeletonRendererComponent.transform;
if (string.IsNullOrEmpty(pointAttachmentName.stringValue)) {
// Draw all active PointAttachments in the current skin
var currentSkin = skeleton.Skin;
if (currentSkin != skeleton.Data.DefaultSkin) DrawPointsInSkin(skeleton.Data.DefaultSkin, skeleton, skeletonTransform);
if (currentSkin != null) DrawPointsInSkin(currentSkin, skeleton, skeletonTransform);
} else {
Slot slot = skeleton.FindSlot(slotName.stringValue);
if (slot != null) {
int slotIndex = slot.Data.Index;
var point = skeleton.GetAttachment(slotIndex, pointAttachmentName.stringValue) as PointAttachment;
if (point != null) {
DrawPointAttachmentWithLabel(point, slot.Bone, skeletonTransform);
}
}
}
}
static void DrawPointsInSkin (Skin skin, Skeleton skeleton, Transform transform) {
foreach (var skinEntry in skin.Attachments) {
var attachment = skinEntry.Attachment as PointAttachment;
if (attachment != null) {
var slot = skeleton.Slots.Items[skinEntry.SlotIndex];
DrawPointAttachmentWithLabel(attachment, slot.Bone, transform);
}
}
}
static void DrawPointAttachmentWithLabel (PointAttachment point, Bone bone, Transform transform) {
Vector3 labelOffset = new Vector3(0f, -0.2f, 0f);
SpineHandles.DrawPointAttachment(bone, point, transform);
Handles.Label(labelOffset + point.GetWorldPosition(bone, transform), point.Name, SpineHandles.PointNameStyle);
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
if (needsReset) {
needsReset = false;
foreach (var o in targets) {
var bf = (BoneFollower)o;
bf.Initialize();
bf.LateUpdate();
}
SceneView.RepaintAll();
}
EditorGUI.BeginChangeCheck();
DrawDefaultInspector();
needsReset |= EditorGUI.EndChangeCheck();
return;
}
if (needsReset && Event.current.type == EventType.Layout) {
targetPointFollower.Initialize();
targetPointFollower.LateUpdate();
needsReset = false;
SceneView.RepaintAll();
}
serializedObject.Update();
DrawDefaultInspector();
// Find Renderer
if (skeletonRenderer.objectReferenceValue == null) {
SkeletonRenderer parentRenderer = targetPointFollower.GetComponentInParent<SkeletonRenderer>();
if (parentRenderer != null && parentRenderer.gameObject != targetPointFollower.gameObject) {
skeletonRenderer.objectReferenceValue = parentRenderer;
Debug.Log("Inspector automatically assigned PointFollower.SkeletonRenderer");
}
}
var skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
if (skeletonRendererReference != null) {
if (skeletonRendererReference.gameObject == targetPointFollower.gameObject) {
skeletonRenderer.objectReferenceValue = null;
EditorUtility.DisplayDialog("Invalid assignment.", "PointFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your PointFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok");
}
}
if (!targetPointFollower.IsValid) {
needsReset = true;
}
var current = Event.current;
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
if (wasUndo)
targetPointFollower.Initialize();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -1,131 +1,131 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonAnimation))]
[CanEditMultipleObjects]
public class SkeletonAnimationInspector : SkeletonRendererInspector {
protected SerializedProperty animationName, loop, timeScale, autoReset;
protected bool wasAnimationParameterChanged = false;
readonly GUIContent LoopLabel = new GUIContent("Loop", "Whether or not .AnimationName should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.");
readonly GUIContent TimeScaleLabel = new GUIContent("Time Scale", "The rate at which animations progress over time. 1 means normal speed. 0.5 means 50% speed.");
protected override void OnEnable () {
base.OnEnable();
animationName = serializedObject.FindProperty("_animationName");
loop = serializedObject.FindProperty("loop");
timeScale = serializedObject.FindProperty("timeScale");
}
protected override void DrawInspectorGUI (bool multi) {
base.DrawInspectorGUI(multi);
if (!TargetIsValid) return;
bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject);
foreach (var o in targets)
TrySetAnimation(o as SkeletonAnimation);
EditorGUILayout.Space();
if (!sameData) {
EditorGUILayout.DelayedTextField(animationName);
} else {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(animationName);
wasAnimationParameterChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(loop, LoopLabel);
wasAnimationParameterChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
EditorGUILayout.PropertyField(timeScale, TimeScaleLabel);
foreach (var o in targets) {
var component = o as SkeletonAnimation;
component.timeScale = Mathf.Max(component.timeScale, 0);
}
EditorGUILayout.Space();
SkeletonRootMotionParameter();
serializedObject.ApplyModifiedProperties();
}
protected void TrySetAnimation (SkeletonAnimation skeletonAnimation) {
if (skeletonAnimation == null) return;
if (!skeletonAnimation.valid || skeletonAnimation.AnimationState == null)
return;
TrackEntry current = skeletonAnimation.AnimationState.GetCurrent(0);
if (!isInspectingPrefab) {
string activeAnimation = (current != null) ? current.Animation.Name : "";
bool activeLoop = (current != null) ? current.Loop : false;
bool animationParameterChanged = this.wasAnimationParameterChanged &&
((activeAnimation != animationName.stringValue) || (activeLoop != loop.boolValue));
if (animationParameterChanged) {
this.wasAnimationParameterChanged = false;
var skeleton = skeletonAnimation.Skeleton;
var state = skeletonAnimation.AnimationState;
if (!Application.isPlaying) {
if (state != null) state.ClearTrack(0);
skeleton.SetToSetupPose();
}
Spine.Animation animationToUse = skeleton.Data.FindAnimation(animationName.stringValue);
if (!Application.isPlaying) {
if (animationToUse != null) {
skeletonAnimation.AnimationState.SetAnimation(0, animationToUse, loop.boolValue);
}
skeletonAnimation.Update(0);
skeletonAnimation.LateUpdate();
requireRepaint = true;
} else {
if (animationToUse != null)
state.SetAnimation(0, animationToUse, loop.boolValue);
else
state.ClearTrack(0);
}
}
// Reflect animationName serialized property in the inspector even if SetAnimation API was used.
if (Application.isPlaying) {
if (current != null && current.Animation != null) {
if (skeletonAnimation.AnimationName != animationName.stringValue)
animationName.stringValue = current.Animation.Name;
}
}
}
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonAnimation))]
[CanEditMultipleObjects]
public class SkeletonAnimationInspector : SkeletonRendererInspector {
protected SerializedProperty animationName, loop, timeScale, autoReset;
protected bool wasAnimationParameterChanged = false;
readonly GUIContent LoopLabel = new GUIContent("Loop", "Whether or not .AnimationName should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.");
readonly GUIContent TimeScaleLabel = new GUIContent("Time Scale", "The rate at which animations progress over time. 1 means normal speed. 0.5 means 50% speed.");
protected override void OnEnable () {
base.OnEnable();
animationName = serializedObject.FindProperty("_animationName");
loop = serializedObject.FindProperty("loop");
timeScale = serializedObject.FindProperty("timeScale");
}
protected override void DrawInspectorGUI (bool multi) {
base.DrawInspectorGUI(multi);
if (!TargetIsValid) return;
bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject);
foreach (var o in targets)
TrySetAnimation(o as SkeletonAnimation);
EditorGUILayout.Space();
if (!sameData) {
EditorGUILayout.DelayedTextField(animationName);
} else {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(animationName);
wasAnimationParameterChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(loop, LoopLabel);
wasAnimationParameterChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
EditorGUILayout.PropertyField(timeScale, TimeScaleLabel);
foreach (var o in targets) {
var component = o as SkeletonAnimation;
component.timeScale = Mathf.Max(component.timeScale, 0);
}
EditorGUILayout.Space();
SkeletonRootMotionParameter();
serializedObject.ApplyModifiedProperties();
}
protected void TrySetAnimation (SkeletonAnimation skeletonAnimation) {
if (skeletonAnimation == null) return;
if (!skeletonAnimation.valid || skeletonAnimation.AnimationState == null)
return;
TrackEntry current = skeletonAnimation.AnimationState.GetCurrent(0);
if (!isInspectingPrefab) {
string activeAnimation = (current != null) ? current.Animation.Name : "";
bool activeLoop = (current != null) ? current.Loop : false;
bool animationParameterChanged = this.wasAnimationParameterChanged &&
((activeAnimation != animationName.stringValue) || (activeLoop != loop.boolValue));
if (animationParameterChanged) {
this.wasAnimationParameterChanged = false;
var skeleton = skeletonAnimation.Skeleton;
var state = skeletonAnimation.AnimationState;
if (!Application.isPlaying) {
if (state != null) state.ClearTrack(0);
skeleton.SetToSetupPose();
}
Spine.Animation animationToUse = skeleton.Data.FindAnimation(animationName.stringValue);
if (!Application.isPlaying) {
if (animationToUse != null) {
skeletonAnimation.AnimationState.SetAnimation(0, animationToUse, loop.boolValue);
}
skeletonAnimation.Update(0);
skeletonAnimation.LateUpdate();
requireRepaint = true;
} else {
if (animationToUse != null)
state.SetAnimation(0, animationToUse, loop.boolValue);
else
state.ClearTrack(0);
}
}
// Reflect animationName serialized property in the inspector even if SetAnimation API was used.
if (Application.isPlaying) {
if (current != null && current.Animation != null) {
if (skeletonAnimation.AnimationName != animationName.stringValue)
animationName.stringValue = current.Animation.Name;
}
}
}
}
}
}

View File

@@ -1,159 +1,159 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine.Unity.Examples;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
// This script is not intended for use with code. See spine-unity documentation page for additional information.
[CustomEditor(typeof(SkeletonGraphicCustomMaterials))]
public class SkeletonGraphicCustomMaterialsInspector : UnityEditor.Editor {
List<SkeletonGraphicCustomMaterials.AtlasMaterialOverride> componentCustomMaterialOverrides, _customMaterialOverridesPrev;
List<SkeletonGraphicCustomMaterials.AtlasTextureOverride> componentCustomTextureOverrides, _customTextureOverridesPrev;
SkeletonGraphicCustomMaterials component;
const BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;
MethodInfo RemoveCustomMaterialOverrides, RemoveCustomTextureOverrides, SetCustomMaterialOverrides, SetCustomTextureOverrides;
#region SkeletonGraphic context menu
[MenuItem("CONTEXT/SkeletonGraphic/Add Basic Serialized Custom Materials")]
static void AddSkeletonGraphicCustomMaterials (MenuCommand menuCommand) {
var skeletonGraphic = (SkeletonGraphic)menuCommand.context;
var newComponent = skeletonGraphic.gameObject.AddComponent<SkeletonGraphicCustomMaterials>();
Undo.RegisterCreatedObjectUndo(newComponent, "Add Basic Serialized Custom Materials");
}
[MenuItem("CONTEXT/SkeletonGraphic/Add Basic Serialized Custom Materials", true)]
static bool AddSkeletonGraphicCustomMaterials_Validate (MenuCommand menuCommand) {
var skeletonGraphic = (SkeletonGraphic)menuCommand.context;
return (skeletonGraphic.GetComponent<SkeletonGraphicCustomMaterials>() == null);
}
#endregion
void OnEnable () {
Type cm = typeof(SkeletonGraphicCustomMaterials);
RemoveCustomMaterialOverrides = cm.GetMethod("RemoveCustomMaterialOverrides", PrivateInstance);
RemoveCustomTextureOverrides = cm.GetMethod("RemoveCustomTextureOverrides", PrivateInstance);
SetCustomMaterialOverrides = cm.GetMethod("SetCustomMaterialOverrides", PrivateInstance);
SetCustomTextureOverrides = cm.GetMethod("SetCustomTextureOverrides", PrivateInstance);
}
public override void OnInspectorGUI () {
component = (SkeletonGraphicCustomMaterials)target;
var skeletonGraphic = component.skeletonGraphic;
// Draw the default inspector
DrawDefaultInspector();
if (serializedObject.isEditingMultipleObjects)
return;
if (componentCustomMaterialOverrides == null) {
Type cm = typeof(SkeletonGraphicCustomMaterials);
componentCustomMaterialOverrides = cm.GetField("customMaterialOverrides", PrivateInstance).GetValue(component) as List<SkeletonGraphicCustomMaterials.AtlasMaterialOverride>;
componentCustomTextureOverrides = cm.GetField("customTextureOverrides", PrivateInstance).GetValue(component) as List<SkeletonGraphicCustomMaterials.AtlasTextureOverride>;
if (componentCustomMaterialOverrides == null) {
Debug.Log("Reflection failed.");
return;
}
}
// Fill with current values at start
if (_customMaterialOverridesPrev == null || _customTextureOverridesPrev == null) {
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
_customTextureOverridesPrev = CopyList(componentCustomTextureOverrides);
}
// Compare new values with saved. If change is detected:
// store new values, restore old values, remove overrides, restore new values, restore overrides.
// 1. Store new values
var customMaterialOverridesNew = CopyList(componentCustomMaterialOverrides);
var customTextureOverridesNew = CopyList(componentCustomTextureOverrides);
// Detect changes
if (!_customMaterialOverridesPrev.SequenceEqual(customMaterialOverridesNew) ||
!_customTextureOverridesPrev.SequenceEqual(customTextureOverridesNew)) {
// 2. Restore old values
componentCustomMaterialOverrides.Clear();
componentCustomTextureOverrides.Clear();
componentCustomMaterialOverrides.AddRange(_customMaterialOverridesPrev);
componentCustomTextureOverrides.AddRange(_customTextureOverridesPrev);
// 3. Remove overrides
RemoveCustomMaterials();
// 4. Restore new values
componentCustomMaterialOverrides.Clear();
componentCustomTextureOverrides.Clear();
componentCustomMaterialOverrides.AddRange(customMaterialOverridesNew);
componentCustomTextureOverrides.AddRange(customTextureOverridesNew);
// 5. Restore overrides
SetCustomMaterials();
if (skeletonGraphic != null)
skeletonGraphic.LateUpdate();
}
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
_customTextureOverridesPrev = CopyList(componentCustomTextureOverrides);
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Clear and Reapply Changes", tooltip: "Removes all non-serialized overrides in the SkeletonGraphic and reapplies the overrides on this component."))) {
if (skeletonGraphic != null) {
skeletonGraphic.CustomMaterialOverride.Clear();
skeletonGraphic.CustomTextureOverride.Clear();
RemoveCustomMaterials();
SetCustomMaterials();
skeletonGraphic.LateUpdate();
}
}
}
void RemoveCustomMaterials () {
RemoveCustomMaterialOverrides.Invoke(component, null);
RemoveCustomTextureOverrides.Invoke(component, null);
}
void SetCustomMaterials () {
SetCustomMaterialOverrides.Invoke(component, null);
SetCustomTextureOverrides.Invoke(component, null);
}
static List<T> CopyList<T> (List<T> list) {
return list.GetRange(0, list.Count);
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine.Unity.Examples;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
// This script is not intended for use with code. See spine-unity documentation page for additional information.
[CustomEditor(typeof(SkeletonGraphicCustomMaterials))]
public class SkeletonGraphicCustomMaterialsInspector : UnityEditor.Editor {
List<SkeletonGraphicCustomMaterials.AtlasMaterialOverride> componentCustomMaterialOverrides, _customMaterialOverridesPrev;
List<SkeletonGraphicCustomMaterials.AtlasTextureOverride> componentCustomTextureOverrides, _customTextureOverridesPrev;
SkeletonGraphicCustomMaterials component;
const BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;
MethodInfo RemoveCustomMaterialOverrides, RemoveCustomTextureOverrides, SetCustomMaterialOverrides, SetCustomTextureOverrides;
#region SkeletonGraphic context menu
[MenuItem("CONTEXT/SkeletonGraphic/Add Basic Serialized Custom Materials")]
static void AddSkeletonGraphicCustomMaterials (MenuCommand menuCommand) {
var skeletonGraphic = (SkeletonGraphic)menuCommand.context;
var newComponent = skeletonGraphic.gameObject.AddComponent<SkeletonGraphicCustomMaterials>();
Undo.RegisterCreatedObjectUndo(newComponent, "Add Basic Serialized Custom Materials");
}
[MenuItem("CONTEXT/SkeletonGraphic/Add Basic Serialized Custom Materials", true)]
static bool AddSkeletonGraphicCustomMaterials_Validate (MenuCommand menuCommand) {
var skeletonGraphic = (SkeletonGraphic)menuCommand.context;
return (skeletonGraphic.GetComponent<SkeletonGraphicCustomMaterials>() == null);
}
#endregion
void OnEnable () {
Type cm = typeof(SkeletonGraphicCustomMaterials);
RemoveCustomMaterialOverrides = cm.GetMethod("RemoveCustomMaterialOverrides", PrivateInstance);
RemoveCustomTextureOverrides = cm.GetMethod("RemoveCustomTextureOverrides", PrivateInstance);
SetCustomMaterialOverrides = cm.GetMethod("SetCustomMaterialOverrides", PrivateInstance);
SetCustomTextureOverrides = cm.GetMethod("SetCustomTextureOverrides", PrivateInstance);
}
public override void OnInspectorGUI () {
component = (SkeletonGraphicCustomMaterials)target;
var skeletonGraphic = component.skeletonGraphic;
// Draw the default inspector
DrawDefaultInspector();
if (serializedObject.isEditingMultipleObjects)
return;
if (componentCustomMaterialOverrides == null) {
Type cm = typeof(SkeletonGraphicCustomMaterials);
componentCustomMaterialOverrides = cm.GetField("customMaterialOverrides", PrivateInstance).GetValue(component) as List<SkeletonGraphicCustomMaterials.AtlasMaterialOverride>;
componentCustomTextureOverrides = cm.GetField("customTextureOverrides", PrivateInstance).GetValue(component) as List<SkeletonGraphicCustomMaterials.AtlasTextureOverride>;
if (componentCustomMaterialOverrides == null) {
Debug.Log("Reflection failed.");
return;
}
}
// Fill with current values at start
if (_customMaterialOverridesPrev == null || _customTextureOverridesPrev == null) {
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
_customTextureOverridesPrev = CopyList(componentCustomTextureOverrides);
}
// Compare new values with saved. If change is detected:
// store new values, restore old values, remove overrides, restore new values, restore overrides.
// 1. Store new values
var customMaterialOverridesNew = CopyList(componentCustomMaterialOverrides);
var customTextureOverridesNew = CopyList(componentCustomTextureOverrides);
// Detect changes
if (!_customMaterialOverridesPrev.SequenceEqual(customMaterialOverridesNew) ||
!_customTextureOverridesPrev.SequenceEqual(customTextureOverridesNew)) {
// 2. Restore old values
componentCustomMaterialOverrides.Clear();
componentCustomTextureOverrides.Clear();
componentCustomMaterialOverrides.AddRange(_customMaterialOverridesPrev);
componentCustomTextureOverrides.AddRange(_customTextureOverridesPrev);
// 3. Remove overrides
RemoveCustomMaterials();
// 4. Restore new values
componentCustomMaterialOverrides.Clear();
componentCustomTextureOverrides.Clear();
componentCustomMaterialOverrides.AddRange(customMaterialOverridesNew);
componentCustomTextureOverrides.AddRange(customTextureOverridesNew);
// 5. Restore overrides
SetCustomMaterials();
if (skeletonGraphic != null)
skeletonGraphic.LateUpdate();
}
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
_customTextureOverridesPrev = CopyList(componentCustomTextureOverrides);
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Clear and Reapply Changes", tooltip: "Removes all non-serialized overrides in the SkeletonGraphic and reapplies the overrides on this component."))) {
if (skeletonGraphic != null) {
skeletonGraphic.CustomMaterialOverride.Clear();
skeletonGraphic.CustomTextureOverride.Clear();
RemoveCustomMaterials();
SetCustomMaterials();
skeletonGraphic.LateUpdate();
}
}
}
void RemoveCustomMaterials () {
RemoveCustomMaterialOverrides.Invoke(component, null);
RemoveCustomTextureOverrides.Invoke(component, null);
}
void SetCustomMaterials () {
SetCustomMaterialOverrides.Invoke(component, null);
SetCustomTextureOverrides.Invoke(component, null);
}
static List<T> CopyList<T> (List<T> list) {
return list.GetRange(0, list.Count);
}
}
}

View File

@@ -1,153 +1,153 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
// Contributed by: Mitch Thompson
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonMecanim))]
[CanEditMultipleObjects]
public class SkeletonMecanimInspector : SkeletonRendererInspector {
public static bool mecanimSettingsFoldout;
protected SerializedProperty autoReset;
protected SerializedProperty useCustomMixMode;
protected SerializedProperty layerMixModes;
protected SerializedProperty layerBlendModes;
protected override void OnEnable () {
base.OnEnable();
SerializedProperty mecanimTranslator = serializedObject.FindProperty("translator");
autoReset = mecanimTranslator.FindPropertyRelative("autoReset");
useCustomMixMode = mecanimTranslator.FindPropertyRelative("useCustomMixMode");
layerMixModes = mecanimTranslator.FindPropertyRelative("layerMixModes");
layerBlendModes = mecanimTranslator.FindPropertyRelative("layerBlendModes");
}
protected override void DrawInspectorGUI (bool multi) {
AddRootMotionComponentIfEnabled();
base.DrawInspectorGUI(multi);
using (new SpineInspectorUtility.BoxScope()) {
mecanimSettingsFoldout = EditorGUILayout.Foldout(mecanimSettingsFoldout, "Mecanim Translator");
if (mecanimSettingsFoldout) {
EditorGUILayout.PropertyField(autoReset, new GUIContent("Auto Reset",
"When set to true, the skeleton state is mixed out to setup-" +
"pose when an animation finishes, according to the " +
"animation's keyed items."));
EditorGUILayout.PropertyField(useCustomMixMode, new GUIContent("Custom MixMode",
"When disabled, the recommended MixMode is used according to the layer blend mode. Enable to specify a custom MixMode for each Mecanim layer."));
if (useCustomMixMode.hasMultipleDifferentValues || useCustomMixMode.boolValue == true) {
DrawLayerSettings();
EditorGUILayout.Space();
}
}
}
}
protected void AddRootMotionComponentIfEnabled () {
foreach (var t in targets) {
var component = t as Component;
var animator = component.GetComponent<Animator>();
if (animator != null && animator.applyRootMotion) {
if (component.GetComponent<SkeletonMecanimRootMotion>() == null) {
component.gameObject.AddComponent<SkeletonMecanimRootMotion>();
}
}
}
}
protected void DrawLayerSettings () {
string[] layerNames = GetLayerNames();
float widthLayerColumn = 140;
float widthMixColumn = 84;
using (new GUILayout.HorizontalScope()) {
var rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, EditorGUIUtility.singleLineHeight);
rect.width = widthLayerColumn;
EditorGUI.LabelField(rect, SpineInspectorUtility.TempContent("Mecanim Layer"), EditorStyles.boldLabel);
var savedIndent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
rect.position += new Vector2(rect.width, 0);
rect.width = widthMixColumn;
EditorGUI.LabelField(rect, SpineInspectorUtility.TempContent("Mix Mode"), EditorStyles.boldLabel);
EditorGUI.indentLevel = savedIndent;
}
using (new SpineInspectorUtility.IndentScope()) {
int layerCount = layerMixModes.arraySize;
for (int i = 0; i < layerCount; ++i) {
using (new GUILayout.HorizontalScope()) {
string layerName = i < layerNames.Length ? layerNames[i] : ("Layer " + i);
var rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, EditorGUIUtility.singleLineHeight);
rect.width = widthLayerColumn;
EditorGUI.PrefixLabel(rect, SpineInspectorUtility.TempContent(layerName));
var savedIndent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
var mixMode = layerMixModes.GetArrayElementAtIndex(i);
rect.position += new Vector2(rect.width, 0);
rect.width = widthMixColumn;
EditorGUI.PropertyField(rect, mixMode, GUIContent.none);
EditorGUI.indentLevel = savedIndent;
}
}
}
}
protected string[] GetLayerNames () {
int maxLayerCount = 0;
int maxIndex = 0;
for (int i = 0; i < targets.Length; ++i) {
var skeletonMecanim = ((SkeletonMecanim)targets[i]);
int count = skeletonMecanim.Translator.MecanimLayerCount;
if (count > maxLayerCount) {
maxLayerCount = count;
maxIndex = i;
}
}
if (maxLayerCount == 0)
return new string[0];
var skeletonMecanimMaxLayers = ((SkeletonMecanim)targets[maxIndex]);
return skeletonMecanimMaxLayers.Translator.MecanimLayerNames;
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
// Contributed by: Mitch Thompson
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonMecanim))]
[CanEditMultipleObjects]
public class SkeletonMecanimInspector : SkeletonRendererInspector {
public static bool mecanimSettingsFoldout;
protected SerializedProperty autoReset;
protected SerializedProperty useCustomMixMode;
protected SerializedProperty layerMixModes;
protected SerializedProperty layerBlendModes;
protected override void OnEnable () {
base.OnEnable();
SerializedProperty mecanimTranslator = serializedObject.FindProperty("translator");
autoReset = mecanimTranslator.FindPropertyRelative("autoReset");
useCustomMixMode = mecanimTranslator.FindPropertyRelative("useCustomMixMode");
layerMixModes = mecanimTranslator.FindPropertyRelative("layerMixModes");
layerBlendModes = mecanimTranslator.FindPropertyRelative("layerBlendModes");
}
protected override void DrawInspectorGUI (bool multi) {
AddRootMotionComponentIfEnabled();
base.DrawInspectorGUI(multi);
using (new SpineInspectorUtility.BoxScope()) {
mecanimSettingsFoldout = EditorGUILayout.Foldout(mecanimSettingsFoldout, "Mecanim Translator");
if (mecanimSettingsFoldout) {
EditorGUILayout.PropertyField(autoReset, new GUIContent("Auto Reset",
"When set to true, the skeleton state is mixed out to setup-" +
"pose when an animation finishes, according to the " +
"animation's keyed items."));
EditorGUILayout.PropertyField(useCustomMixMode, new GUIContent("Custom MixMode",
"When disabled, the recommended MixMode is used according to the layer blend mode. Enable to specify a custom MixMode for each Mecanim layer."));
if (useCustomMixMode.hasMultipleDifferentValues || useCustomMixMode.boolValue == true) {
DrawLayerSettings();
EditorGUILayout.Space();
}
}
}
}
protected void AddRootMotionComponentIfEnabled () {
foreach (var t in targets) {
var component = t as Component;
var animator = component.GetComponent<Animator>();
if (animator != null && animator.applyRootMotion) {
if (component.GetComponent<SkeletonMecanimRootMotion>() == null) {
component.gameObject.AddComponent<SkeletonMecanimRootMotion>();
}
}
}
}
protected void DrawLayerSettings () {
string[] layerNames = GetLayerNames();
float widthLayerColumn = 140;
float widthMixColumn = 84;
using (new GUILayout.HorizontalScope()) {
var rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, EditorGUIUtility.singleLineHeight);
rect.width = widthLayerColumn;
EditorGUI.LabelField(rect, SpineInspectorUtility.TempContent("Mecanim Layer"), EditorStyles.boldLabel);
var savedIndent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
rect.position += new Vector2(rect.width, 0);
rect.width = widthMixColumn;
EditorGUI.LabelField(rect, SpineInspectorUtility.TempContent("Mix Mode"), EditorStyles.boldLabel);
EditorGUI.indentLevel = savedIndent;
}
using (new SpineInspectorUtility.IndentScope()) {
int layerCount = layerMixModes.arraySize;
for (int i = 0; i < layerCount; ++i) {
using (new GUILayout.HorizontalScope()) {
string layerName = i < layerNames.Length ? layerNames[i] : ("Layer " + i);
var rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, EditorGUIUtility.singleLineHeight);
rect.width = widthLayerColumn;
EditorGUI.PrefixLabel(rect, SpineInspectorUtility.TempContent(layerName));
var savedIndent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
var mixMode = layerMixModes.GetArrayElementAtIndex(i);
rect.position += new Vector2(rect.width, 0);
rect.width = widthMixColumn;
EditorGUI.PropertyField(rect, mixMode, GUIContent.none);
EditorGUI.indentLevel = savedIndent;
}
}
}
}
protected string[] GetLayerNames () {
int maxLayerCount = 0;
int maxIndex = 0;
for (int i = 0; i < targets.Length; ++i) {
var skeletonMecanim = ((SkeletonMecanim)targets[i]);
int count = skeletonMecanim.Translator.MecanimLayerCount;
if (count > maxLayerCount) {
maxLayerCount = count;
maxIndex = i;
}
}
if (maxLayerCount == 0)
return new string[0];
var skeletonMecanimMaxLayers = ((SkeletonMecanim)targets[maxIndex]);
return skeletonMecanimMaxLayers.Translator.MecanimLayerNames;
}
}
}

View File

@@ -1,81 +1,81 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonMecanimRootMotion))]
[CanEditMultipleObjects]
public class SkeletonMecanimRootMotionInspector : SkeletonRootMotionBaseInspector {
protected SerializedProperty mecanimLayerFlags;
protected GUIContent mecanimLayersLabel;
protected override void OnEnable () {
base.OnEnable();
mecanimLayerFlags = serializedObject.FindProperty("mecanimLayerFlags");
mecanimLayersLabel = new UnityEngine.GUIContent("Mecanim Layers", "Mecanim layers to apply root motion at. Defaults to the first Mecanim layer.");
}
override public void OnInspectorGUI () {
base.MainPropertyFields();
MecanimLayerMaskPropertyField();
base.OptionalPropertyFields();
serializedObject.ApplyModifiedProperties();
}
protected string[] GetLayerNames () {
int maxLayerCount = 0;
int maxIndex = 0;
for (int i = 0; i < targets.Length; ++i) {
var skeletonMecanim = ((SkeletonMecanimRootMotion)targets[i]).SkeletonMecanim;
int count = skeletonMecanim.Translator.MecanimLayerCount;
if (count > maxLayerCount) {
maxLayerCount = count;
maxIndex = i;
}
}
if (maxLayerCount == 0)
return new string[0];
var skeletonMecanimMaxLayers = ((SkeletonMecanimRootMotion)targets[maxIndex]).SkeletonMecanim;
return skeletonMecanimMaxLayers.Translator.MecanimLayerNames;
}
protected void MecanimLayerMaskPropertyField () {
string[] layerNames = GetLayerNames();
if (layerNames.Length > 0)
mecanimLayerFlags.intValue = EditorGUILayout.MaskField(
mecanimLayersLabel, mecanimLayerFlags.intValue, layerNames);
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonMecanimRootMotion))]
[CanEditMultipleObjects]
public class SkeletonMecanimRootMotionInspector : SkeletonRootMotionBaseInspector {
protected SerializedProperty mecanimLayerFlags;
protected GUIContent mecanimLayersLabel;
protected override void OnEnable () {
base.OnEnable();
mecanimLayerFlags = serializedObject.FindProperty("mecanimLayerFlags");
mecanimLayersLabel = new UnityEngine.GUIContent("Mecanim Layers", "Mecanim layers to apply root motion at. Defaults to the first Mecanim layer.");
}
override public void OnInspectorGUI () {
base.MainPropertyFields();
MecanimLayerMaskPropertyField();
base.OptionalPropertyFields();
serializedObject.ApplyModifiedProperties();
}
protected string[] GetLayerNames () {
int maxLayerCount = 0;
int maxIndex = 0;
for (int i = 0; i < targets.Length; ++i) {
var skeletonMecanim = ((SkeletonMecanimRootMotion)targets[i]).SkeletonMecanim;
int count = skeletonMecanim.Translator.MecanimLayerCount;
if (count > maxLayerCount) {
maxLayerCount = count;
maxIndex = i;
}
}
if (maxLayerCount == 0)
return new string[0];
var skeletonMecanimMaxLayers = ((SkeletonMecanimRootMotion)targets[maxIndex]).SkeletonMecanim;
return skeletonMecanimMaxLayers.Translator.MecanimLayerNames;
}
protected void MecanimLayerMaskPropertyField () {
string[] layerNames = GetLayerNames();
if (layerNames.Length > 0)
mecanimLayerFlags.intValue = EditorGUILayout.MaskField(
mecanimLayersLabel, mecanimLayerFlags.intValue, layerNames);
}
}
}

View File

@@ -1,165 +1,165 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#define SPINE_OPTIONAL_MATERIALOVERRIDE
// Contributed by: Lost Polygon
using Spine.Unity.Examples;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
// This script is not intended for use with code. See the readme.txt file in SkeletonRendererCustomMaterials folder to learn more.
[CustomEditor(typeof(SkeletonRendererCustomMaterials))]
public class SkeletonRendererCustomMaterialsInspector : UnityEditor.Editor {
List<SkeletonRendererCustomMaterials.AtlasMaterialOverride> componentCustomMaterialOverrides, _customMaterialOverridesPrev;
List<SkeletonRendererCustomMaterials.SlotMaterialOverride> componentCustomSlotMaterials, _customSlotMaterialsPrev;
SkeletonRendererCustomMaterials component;
const BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;
MethodInfo RemoveCustomMaterialOverrides, RemoveCustomSlotMaterials, SetCustomMaterialOverrides, SetCustomSlotMaterials;
#region SkeletonRenderer context menu
[MenuItem("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials")]
static void AddSkeletonRendererCustomMaterials (MenuCommand menuCommand) {
var skeletonRenderer = (SkeletonRenderer)menuCommand.context;
var newComponent = skeletonRenderer.gameObject.AddComponent<SkeletonRendererCustomMaterials>();
Undo.RegisterCreatedObjectUndo(newComponent, "Add Basic Serialized Custom Materials");
}
[MenuItem("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials", true)]
static bool AddSkeletonRendererCustomMaterials_Validate (MenuCommand menuCommand) {
var skeletonRenderer = (SkeletonRenderer)menuCommand.context;
return (skeletonRenderer.GetComponent<SkeletonRendererCustomMaterials>() == null);
}
#endregion
void OnEnable () {
Type cm = typeof(SkeletonRendererCustomMaterials);
RemoveCustomMaterialOverrides = cm.GetMethod("RemoveCustomMaterialOverrides", PrivateInstance);
RemoveCustomSlotMaterials = cm.GetMethod("RemoveCustomSlotMaterials", PrivateInstance);
SetCustomMaterialOverrides = cm.GetMethod("SetCustomMaterialOverrides", PrivateInstance);
SetCustomSlotMaterials = cm.GetMethod("SetCustomSlotMaterials", PrivateInstance);
}
public override void OnInspectorGUI () {
component = (SkeletonRendererCustomMaterials)target;
var skeletonRenderer = component.skeletonRenderer;
// Draw the default inspector
DrawDefaultInspector();
if (serializedObject.isEditingMultipleObjects)
return;
if (componentCustomMaterialOverrides == null) {
Type cm = typeof(SkeletonRendererCustomMaterials);
componentCustomMaterialOverrides = cm.GetField("customMaterialOverrides", PrivateInstance).GetValue(component) as List<SkeletonRendererCustomMaterials.AtlasMaterialOverride>;
componentCustomSlotMaterials = cm.GetField("customSlotMaterials", PrivateInstance).GetValue(component) as List<SkeletonRendererCustomMaterials.SlotMaterialOverride>;
if (componentCustomMaterialOverrides == null) {
Debug.Log("Reflection failed.");
return;
}
}
// Fill with current values at start
if (_customMaterialOverridesPrev == null || _customSlotMaterialsPrev == null) {
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
_customSlotMaterialsPrev = CopyList(componentCustomSlotMaterials);
}
// Compare new values with saved. If change is detected:
// store new values, restore old values, remove overrides, restore new values, restore overrides.
// 1. Store new values
var customMaterialOverridesNew = CopyList(componentCustomMaterialOverrides);
var customSlotMaterialsNew = CopyList(componentCustomSlotMaterials);
// Detect changes
if (!_customMaterialOverridesPrev.SequenceEqual(customMaterialOverridesNew) ||
!_customSlotMaterialsPrev.SequenceEqual(customSlotMaterialsNew)) {
// 2. Restore old values
componentCustomMaterialOverrides.Clear();
componentCustomSlotMaterials.Clear();
componentCustomMaterialOverrides.AddRange(_customMaterialOverridesPrev);
componentCustomSlotMaterials.AddRange(_customSlotMaterialsPrev);
// 3. Remove overrides
RemoveCustomMaterials();
// 4. Restore new values
componentCustomMaterialOverrides.Clear();
componentCustomSlotMaterials.Clear();
componentCustomMaterialOverrides.AddRange(customMaterialOverridesNew);
componentCustomSlotMaterials.AddRange(customSlotMaterialsNew);
// 5. Restore overrides
SetCustomMaterials();
if (skeletonRenderer != null)
skeletonRenderer.LateUpdate();
}
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
_customSlotMaterialsPrev = CopyList(componentCustomSlotMaterials);
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Clear and Reapply Changes", tooltip: "Removes all non-serialized overrides in the SkeletonRenderer and reapplies the overrides on this component."))) {
if (skeletonRenderer != null) {
#if SPINE_OPTIONAL_MATERIALOVERRIDE
skeletonRenderer.CustomMaterialOverride.Clear();
#endif
skeletonRenderer.CustomSlotMaterials.Clear();
RemoveCustomMaterials();
SetCustomMaterials();
skeletonRenderer.LateUpdate();
}
}
}
void RemoveCustomMaterials () {
RemoveCustomMaterialOverrides.Invoke(component, null);
RemoveCustomSlotMaterials.Invoke(component, null);
}
void SetCustomMaterials () {
SetCustomMaterialOverrides.Invoke(component, null);
SetCustomSlotMaterials.Invoke(component, null);
}
static List<T> CopyList<T> (List<T> list) {
return list.GetRange(0, list.Count);
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#define SPINE_OPTIONAL_MATERIALOVERRIDE
// Contributed by: Lost Polygon
using Spine.Unity.Examples;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
// This script is not intended for use with code. See the readme.txt file in SkeletonRendererCustomMaterials folder to learn more.
[CustomEditor(typeof(SkeletonRendererCustomMaterials))]
public class SkeletonRendererCustomMaterialsInspector : UnityEditor.Editor {
List<SkeletonRendererCustomMaterials.AtlasMaterialOverride> componentCustomMaterialOverrides, _customMaterialOverridesPrev;
List<SkeletonRendererCustomMaterials.SlotMaterialOverride> componentCustomSlotMaterials, _customSlotMaterialsPrev;
SkeletonRendererCustomMaterials component;
const BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;
MethodInfo RemoveCustomMaterialOverrides, RemoveCustomSlotMaterials, SetCustomMaterialOverrides, SetCustomSlotMaterials;
#region SkeletonRenderer context menu
[MenuItem("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials")]
static void AddSkeletonRendererCustomMaterials (MenuCommand menuCommand) {
var skeletonRenderer = (SkeletonRenderer)menuCommand.context;
var newComponent = skeletonRenderer.gameObject.AddComponent<SkeletonRendererCustomMaterials>();
Undo.RegisterCreatedObjectUndo(newComponent, "Add Basic Serialized Custom Materials");
}
[MenuItem("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials", true)]
static bool AddSkeletonRendererCustomMaterials_Validate (MenuCommand menuCommand) {
var skeletonRenderer = (SkeletonRenderer)menuCommand.context;
return (skeletonRenderer.GetComponent<SkeletonRendererCustomMaterials>() == null);
}
#endregion
void OnEnable () {
Type cm = typeof(SkeletonRendererCustomMaterials);
RemoveCustomMaterialOverrides = cm.GetMethod("RemoveCustomMaterialOverrides", PrivateInstance);
RemoveCustomSlotMaterials = cm.GetMethod("RemoveCustomSlotMaterials", PrivateInstance);
SetCustomMaterialOverrides = cm.GetMethod("SetCustomMaterialOverrides", PrivateInstance);
SetCustomSlotMaterials = cm.GetMethod("SetCustomSlotMaterials", PrivateInstance);
}
public override void OnInspectorGUI () {
component = (SkeletonRendererCustomMaterials)target;
var skeletonRenderer = component.skeletonRenderer;
// Draw the default inspector
DrawDefaultInspector();
if (serializedObject.isEditingMultipleObjects)
return;
if (componentCustomMaterialOverrides == null) {
Type cm = typeof(SkeletonRendererCustomMaterials);
componentCustomMaterialOverrides = cm.GetField("customMaterialOverrides", PrivateInstance).GetValue(component) as List<SkeletonRendererCustomMaterials.AtlasMaterialOverride>;
componentCustomSlotMaterials = cm.GetField("customSlotMaterials", PrivateInstance).GetValue(component) as List<SkeletonRendererCustomMaterials.SlotMaterialOverride>;
if (componentCustomMaterialOverrides == null) {
Debug.Log("Reflection failed.");
return;
}
}
// Fill with current values at start
if (_customMaterialOverridesPrev == null || _customSlotMaterialsPrev == null) {
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
_customSlotMaterialsPrev = CopyList(componentCustomSlotMaterials);
}
// Compare new values with saved. If change is detected:
// store new values, restore old values, remove overrides, restore new values, restore overrides.
// 1. Store new values
var customMaterialOverridesNew = CopyList(componentCustomMaterialOverrides);
var customSlotMaterialsNew = CopyList(componentCustomSlotMaterials);
// Detect changes
if (!_customMaterialOverridesPrev.SequenceEqual(customMaterialOverridesNew) ||
!_customSlotMaterialsPrev.SequenceEqual(customSlotMaterialsNew)) {
// 2. Restore old values
componentCustomMaterialOverrides.Clear();
componentCustomSlotMaterials.Clear();
componentCustomMaterialOverrides.AddRange(_customMaterialOverridesPrev);
componentCustomSlotMaterials.AddRange(_customSlotMaterialsPrev);
// 3. Remove overrides
RemoveCustomMaterials();
// 4. Restore new values
componentCustomMaterialOverrides.Clear();
componentCustomSlotMaterials.Clear();
componentCustomMaterialOverrides.AddRange(customMaterialOverridesNew);
componentCustomSlotMaterials.AddRange(customSlotMaterialsNew);
// 5. Restore overrides
SetCustomMaterials();
if (skeletonRenderer != null)
skeletonRenderer.LateUpdate();
}
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
_customSlotMaterialsPrev = CopyList(componentCustomSlotMaterials);
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Clear and Reapply Changes", tooltip: "Removes all non-serialized overrides in the SkeletonRenderer and reapplies the overrides on this component."))) {
if (skeletonRenderer != null) {
#if SPINE_OPTIONAL_MATERIALOVERRIDE
skeletonRenderer.CustomMaterialOverride.Clear();
#endif
skeletonRenderer.CustomSlotMaterials.Clear();
RemoveCustomMaterials();
SetCustomMaterials();
skeletonRenderer.LateUpdate();
}
}
}
void RemoveCustomMaterials () {
RemoveCustomMaterialOverrides.Invoke(component, null);
RemoveCustomSlotMaterials.Invoke(component, null);
}
void SetCustomMaterials () {
SetCustomMaterialOverrides.Invoke(component, null);
SetCustomSlotMaterials.Invoke(component, null);
}
static List<T> CopyList<T> (List<T> list) {
return list.GetRange(0, list.Count);
}
}
}

View File

@@ -1,124 +1,124 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonRootMotionBase))]
[CanEditMultipleObjects]
public class SkeletonRootMotionBaseInspector : UnityEditor.Editor {
protected SerializedProperty rootMotionBoneName;
protected SerializedProperty transformPositionX;
protected SerializedProperty transformPositionY;
protected SerializedProperty rootMotionScaleX;
protected SerializedProperty rootMotionScaleY;
protected SerializedProperty rootMotionTranslateXPerY;
protected SerializedProperty rootMotionTranslateYPerX;
protected SerializedProperty rigidBody2D;
protected SerializedProperty applyRigidbody2DGravity;
protected SerializedProperty rigidBody;
protected GUIContent rootMotionBoneNameLabel;
protected GUIContent transformPositionXLabel;
protected GUIContent transformPositionYLabel;
protected GUIContent rootMotionScaleXLabel;
protected GUIContent rootMotionScaleYLabel;
protected GUIContent rootMotionTranslateXPerYLabel;
protected GUIContent rootMotionTranslateYPerXLabel;
protected GUIContent rigidBody2DLabel;
protected GUIContent applyRigidbody2DGravityLabel;
protected GUIContent rigidBodyLabel;
protected virtual void OnEnable () {
rootMotionBoneName = serializedObject.FindProperty("rootMotionBoneName");
transformPositionX = serializedObject.FindProperty("transformPositionX");
transformPositionY = serializedObject.FindProperty("transformPositionY");
rootMotionScaleX = serializedObject.FindProperty("rootMotionScaleX");
rootMotionScaleY = serializedObject.FindProperty("rootMotionScaleY");
rootMotionTranslateXPerY = serializedObject.FindProperty("rootMotionTranslateXPerY");
rootMotionTranslateYPerX = serializedObject.FindProperty("rootMotionTranslateYPerX");
rigidBody2D = serializedObject.FindProperty("rigidBody2D");
applyRigidbody2DGravity = serializedObject.FindProperty("applyRigidbody2DGravity");
rigidBody = serializedObject.FindProperty("rigidBody");
rootMotionBoneNameLabel = new UnityEngine.GUIContent("Root Motion Bone", "The bone to take the motion from.");
transformPositionXLabel = new UnityEngine.GUIContent("X", "Root transform position (X)");
transformPositionYLabel = new UnityEngine.GUIContent("Y", "Use the Y-movement of the bone.");
rootMotionScaleXLabel = new UnityEngine.GUIContent("Root Motion Scale (X)", "Scale applied to the horizontal root motion delta. Can be used for delta compensation to e.g. stretch a jump to the desired distance.");
rootMotionScaleYLabel = new UnityEngine.GUIContent("Root Motion Scale (Y)", "Scale applied to the vertical root motion delta. Can be used for delta compensation to e.g. stretch a jump to the desired distance.");
rootMotionTranslateXPerYLabel = new UnityEngine.GUIContent("Root Motion Translate (X)", "Added X translation per root motion Y delta. Can be used for delta compensation when scaling is not enough, to e.g. offset a horizontal jump to a vertically different goal.");
rootMotionTranslateYPerXLabel = new UnityEngine.GUIContent("Root Motion Translate (Y)", "Added Y translation per root motion X delta. Can be used for delta compensation when scaling is not enough, to e.g. offset a horizontal jump to a vertically different goal.");
rigidBody2DLabel = new UnityEngine.GUIContent("Rigidbody2D",
"Optional Rigidbody2D: Assign a Rigidbody2D here if you want " +
" to apply the root motion to the rigidbody instead of the Transform." +
"\n\n" +
"Note that animation and physics updates are not always in sync." +
"Some jitter may result at certain framerates.");
applyRigidbody2DGravityLabel = new UnityEngine.GUIContent("Apply Gravity",
"Apply Rigidbody2D Gravity");
rigidBodyLabel = new UnityEngine.GUIContent("Rigidbody",
"Optional Rigidbody: Assign a Rigidbody here if you want " +
" to apply the root motion to the rigidbody instead of the Transform." +
"\n\n" +
"Note that animation and physics updates are not always in sync." +
"Some jitter may result at certain framerates.");
}
public override void OnInspectorGUI () {
MainPropertyFields();
OptionalPropertyFields();
serializedObject.ApplyModifiedProperties();
}
protected virtual void MainPropertyFields () {
EditorGUILayout.PropertyField(rootMotionBoneName, rootMotionBoneNameLabel);
EditorGUILayout.PropertyField(transformPositionX, transformPositionXLabel);
EditorGUILayout.PropertyField(transformPositionY, transformPositionYLabel);
EditorGUILayout.PropertyField(rootMotionScaleX, rootMotionScaleXLabel);
EditorGUILayout.PropertyField(rootMotionScaleY, rootMotionScaleYLabel);
EditorGUILayout.PropertyField(rootMotionTranslateXPerY, rootMotionTranslateXPerYLabel);
EditorGUILayout.PropertyField(rootMotionTranslateYPerX, rootMotionTranslateYPerXLabel);
}
protected virtual void OptionalPropertyFields () {
EditorGUILayout.PropertyField(rigidBody2D, rigidBody2DLabel);
if (rigidBody2D.objectReferenceValue != null || rigidBody2D.hasMultipleDifferentValues) {
using (new SpineInspectorUtility.IndentScope())
EditorGUILayout.PropertyField(applyRigidbody2DGravity, applyRigidbody2DGravityLabel);
}
EditorGUILayout.PropertyField(rigidBody, rigidBodyLabel);
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonRootMotionBase))]
[CanEditMultipleObjects]
public class SkeletonRootMotionBaseInspector : UnityEditor.Editor {
protected SerializedProperty rootMotionBoneName;
protected SerializedProperty transformPositionX;
protected SerializedProperty transformPositionY;
protected SerializedProperty rootMotionScaleX;
protected SerializedProperty rootMotionScaleY;
protected SerializedProperty rootMotionTranslateXPerY;
protected SerializedProperty rootMotionTranslateYPerX;
protected SerializedProperty rigidBody2D;
protected SerializedProperty applyRigidbody2DGravity;
protected SerializedProperty rigidBody;
protected GUIContent rootMotionBoneNameLabel;
protected GUIContent transformPositionXLabel;
protected GUIContent transformPositionYLabel;
protected GUIContent rootMotionScaleXLabel;
protected GUIContent rootMotionScaleYLabel;
protected GUIContent rootMotionTranslateXPerYLabel;
protected GUIContent rootMotionTranslateYPerXLabel;
protected GUIContent rigidBody2DLabel;
protected GUIContent applyRigidbody2DGravityLabel;
protected GUIContent rigidBodyLabel;
protected virtual void OnEnable () {
rootMotionBoneName = serializedObject.FindProperty("rootMotionBoneName");
transformPositionX = serializedObject.FindProperty("transformPositionX");
transformPositionY = serializedObject.FindProperty("transformPositionY");
rootMotionScaleX = serializedObject.FindProperty("rootMotionScaleX");
rootMotionScaleY = serializedObject.FindProperty("rootMotionScaleY");
rootMotionTranslateXPerY = serializedObject.FindProperty("rootMotionTranslateXPerY");
rootMotionTranslateYPerX = serializedObject.FindProperty("rootMotionTranslateYPerX");
rigidBody2D = serializedObject.FindProperty("rigidBody2D");
applyRigidbody2DGravity = serializedObject.FindProperty("applyRigidbody2DGravity");
rigidBody = serializedObject.FindProperty("rigidBody");
rootMotionBoneNameLabel = new UnityEngine.GUIContent("Root Motion Bone", "The bone to take the motion from.");
transformPositionXLabel = new UnityEngine.GUIContent("X", "Root transform position (X)");
transformPositionYLabel = new UnityEngine.GUIContent("Y", "Use the Y-movement of the bone.");
rootMotionScaleXLabel = new UnityEngine.GUIContent("Root Motion Scale (X)", "Scale applied to the horizontal root motion delta. Can be used for delta compensation to e.g. stretch a jump to the desired distance.");
rootMotionScaleYLabel = new UnityEngine.GUIContent("Root Motion Scale (Y)", "Scale applied to the vertical root motion delta. Can be used for delta compensation to e.g. stretch a jump to the desired distance.");
rootMotionTranslateXPerYLabel = new UnityEngine.GUIContent("Root Motion Translate (X)", "Added X translation per root motion Y delta. Can be used for delta compensation when scaling is not enough, to e.g. offset a horizontal jump to a vertically different goal.");
rootMotionTranslateYPerXLabel = new UnityEngine.GUIContent("Root Motion Translate (Y)", "Added Y translation per root motion X delta. Can be used for delta compensation when scaling is not enough, to e.g. offset a horizontal jump to a vertically different goal.");
rigidBody2DLabel = new UnityEngine.GUIContent("Rigidbody2D",
"Optional Rigidbody2D: Assign a Rigidbody2D here if you want " +
" to apply the root motion to the rigidbody instead of the Transform." +
"\n\n" +
"Note that animation and physics updates are not always in sync." +
"Some jitter may result at certain framerates.");
applyRigidbody2DGravityLabel = new UnityEngine.GUIContent("Apply Gravity",
"Apply Rigidbody2D Gravity");
rigidBodyLabel = new UnityEngine.GUIContent("Rigidbody",
"Optional Rigidbody: Assign a Rigidbody here if you want " +
" to apply the root motion to the rigidbody instead of the Transform." +
"\n\n" +
"Note that animation and physics updates are not always in sync." +
"Some jitter may result at certain framerates.");
}
public override void OnInspectorGUI () {
MainPropertyFields();
OptionalPropertyFields();
serializedObject.ApplyModifiedProperties();
}
protected virtual void MainPropertyFields () {
EditorGUILayout.PropertyField(rootMotionBoneName, rootMotionBoneNameLabel);
EditorGUILayout.PropertyField(transformPositionX, transformPositionXLabel);
EditorGUILayout.PropertyField(transformPositionY, transformPositionYLabel);
EditorGUILayout.PropertyField(rootMotionScaleX, rootMotionScaleXLabel);
EditorGUILayout.PropertyField(rootMotionScaleY, rootMotionScaleYLabel);
EditorGUILayout.PropertyField(rootMotionTranslateXPerY, rootMotionTranslateXPerYLabel);
EditorGUILayout.PropertyField(rootMotionTranslateYPerX, rootMotionTranslateYPerXLabel);
}
protected virtual void OptionalPropertyFields () {
EditorGUILayout.PropertyField(rigidBody2D, rigidBody2DLabel);
if (rigidBody2D.objectReferenceValue != null || rigidBody2D.hasMultipleDifferentValues) {
using (new SpineInspectorUtility.IndentScope())
EditorGUILayout.PropertyField(applyRigidbody2DGravity, applyRigidbody2DGravityLabel);
}
EditorGUILayout.PropertyField(rigidBody, rigidBodyLabel);
}
}
}

View File

@@ -1,79 +1,79 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonRootMotion))]
[CanEditMultipleObjects]
public class SkeletonRootMotionInspector : SkeletonRootMotionBaseInspector {
protected SerializedProperty animationTrackFlags;
protected GUIContent animationTrackFlagsLabel;
string[] TrackNames;
protected override void OnEnable () {
base.OnEnable();
animationTrackFlags = serializedObject.FindProperty("animationTrackFlags");
animationTrackFlagsLabel = new UnityEngine.GUIContent("Animation Tracks",
"Animation tracks to apply root motion at. Defaults to the first" +
" animation track (index 0).");
}
override public void OnInspectorGUI () {
base.MainPropertyFields();
AnimationTracksPropertyField();
base.OptionalPropertyFields();
serializedObject.ApplyModifiedProperties();
}
protected void AnimationTracksPropertyField () {
if (TrackNames == null) {
InitTrackNames();
}
animationTrackFlags.intValue = EditorGUILayout.MaskField(
animationTrackFlagsLabel, animationTrackFlags.intValue, TrackNames);
}
protected void InitTrackNames () {
int numEntries = 32;
TrackNames = new string[numEntries];
for (int i = 0; i < numEntries; ++i) {
TrackNames[i] = string.Format("Track {0}", i);
}
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonRootMotion))]
[CanEditMultipleObjects]
public class SkeletonRootMotionInspector : SkeletonRootMotionBaseInspector {
protected SerializedProperty animationTrackFlags;
protected GUIContent animationTrackFlagsLabel;
string[] TrackNames;
protected override void OnEnable () {
base.OnEnable();
animationTrackFlags = serializedObject.FindProperty("animationTrackFlags");
animationTrackFlagsLabel = new UnityEngine.GUIContent("Animation Tracks",
"Animation tracks to apply root motion at. Defaults to the first" +
" animation track (index 0).");
}
override public void OnInspectorGUI () {
base.MainPropertyFields();
AnimationTracksPropertyField();
base.OptionalPropertyFields();
serializedObject.ApplyModifiedProperties();
}
protected void AnimationTracksPropertyField () {
if (TrackNames == null) {
InitTrackNames();
}
animationTrackFlags.intValue = EditorGUILayout.MaskField(
animationTrackFlagsLabel, animationTrackFlags.intValue, TrackNames);
}
protected void InitTrackNames () {
int numEntries = 32;
TrackNames = new string[numEntries];
for (int i = 0; i < numEntries; ++i) {
TrackNames[i] = string.Format("Track {0}", i);
}
}
}
}

View File

@@ -1,188 +1,188 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Icons = SpineEditorUtilities.Icons;
[CustomEditor(typeof(SkeletonUtility))]
public class SkeletonUtilityInspector : UnityEditor.Editor {
SkeletonUtility skeletonUtility;
Skeleton skeleton;
SkeletonRenderer skeletonRenderer;
SkeletonGraphic skeletonGraphic;
#if !NEW_PREFAB_SYSTEM
bool isPrefab;
#endif
readonly GUIContent SpawnHierarchyButtonLabel = new GUIContent("Spawn Hierarchy", Icons.skeleton);
void OnEnable () {
skeletonUtility = (SkeletonUtility)target;
skeletonRenderer = skeletonUtility.skeletonRenderer;
skeletonGraphic = skeletonUtility.skeletonGraphic;
skeleton = skeletonUtility.Skeleton;
if (skeleton == null) {
if (skeletonRenderer != null) {
skeletonRenderer.Initialize(false);
skeletonRenderer.LateUpdate();
} else if (skeletonGraphic != null) {
skeletonGraphic.Initialize(false);
skeletonGraphic.LateUpdate();
}
skeleton = skeletonUtility.Skeleton;
}
if ((skeletonRenderer != null && !skeletonRenderer.valid) ||
(skeletonGraphic != null && !skeletonGraphic.IsValid)) return;
#if !NEW_PREFAB_SYSTEM
isPrefab |= PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab;
#endif
}
public override void OnInspectorGUI () {
#if !NEW_PREFAB_SYSTEM
if (isPrefab) {
GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning));
return;
}
#endif
serializedObject.Update();
if ((skeletonRenderer != null && !skeletonRenderer.valid) ||
(skeletonGraphic != null && !skeletonGraphic.IsValid)) {
GUILayout.Label(new GUIContent("Spine Component invalid. Check SkeletonData asset.", Icons.warning));
return;
}
EditorGUILayout.PropertyField(serializedObject.FindProperty("boneRoot"), SpineInspectorUtility.TempContent("Skeleton Root"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("flipBy180DegreeRotation"), SpineInspectorUtility.TempContent("Flip by Rotation", null,
"If true, Skeleton.ScaleX and Skeleton.ScaleY are followed " +
"by 180 degree rotation. If false, negative Transform scale is used. " +
"Note that using negative scale is consistent with previous behaviour (hence the default), " +
"however causes serious problems with rigidbodies and physics. Therefore, it is recommended to " +
"enable this parameter where possible. When creating hinge chains for a chain of skeleton bones " +
"via SkeletonUtilityBone, it is mandatory to have this parameter enabled."));
bool hasRootBone = skeletonUtility.boneRoot != null;
if (!hasRootBone)
EditorGUILayout.HelpBox("No hierarchy found. Use Spawn Hierarchy to generate GameObjects for bones.", MessageType.Info);
using (new EditorGUI.DisabledGroupScope(hasRootBone)) {
if (SpineInspectorUtility.LargeCenteredButton(SpawnHierarchyButtonLabel))
SpawnHierarchyContextMenu();
}
if (hasRootBone) {
if (SpineInspectorUtility.CenteredButton(new GUIContent("Remove Hierarchy"))) {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Remove Hierarchy");
Undo.DestroyObjectImmediate(skeletonUtility.boneRoot.gameObject);
skeletonUtility.boneRoot = null;
}
}
serializedObject.ApplyModifiedProperties();
}
void SpawnHierarchyContextMenu () {
var menu = new GenericMenu();
menu.AddItem(new GUIContent("Follow all bones"), false, SpawnFollowHierarchy);
menu.AddItem(new GUIContent("Follow (Root Only)"), false, SpawnFollowHierarchyRootOnly);
menu.AddSeparator("");
menu.AddItem(new GUIContent("Override all bones"), false, SpawnOverrideHierarchy);
menu.AddItem(new GUIContent("Override (Root Only)"), false, SpawnOverrideHierarchyRootOnly);
menu.ShowAsContext();
}
public static void AttachIcon (SkeletonUtilityBone boneComponent) {
Skeleton skeleton = boneComponent.hierarchy.Skeleton;
Texture2D icon = boneComponent.bone.Data.Length == 0 ? Icons.nullBone : Icons.boneNib;
foreach (IkConstraint c in skeleton.IkConstraints)
if (c.Target == boneComponent.bone) {
icon = Icons.constraintNib;
break;
}
typeof(EditorGUIUtility).InvokeMember("SetIconForObject", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, null, new object[2] {
boneComponent.gameObject,
icon
});
}
static void AttachIconsToChildren (Transform root) {
if (root != null) {
var utilityBones = root.GetComponentsInChildren<SkeletonUtilityBone>();
foreach (var utilBone in utilityBones)
AttachIcon(utilBone);
}
}
void SpawnFollowHierarchy () {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Hierarchy");
Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Follow, true, true, true);
AttachIconsToChildren(skeletonUtility.boneRoot);
}
void SpawnFollowHierarchyRootOnly () {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Root");
Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Follow, true, true, true);
AttachIconsToChildren(skeletonUtility.boneRoot);
}
void SpawnOverrideHierarchy () {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Hierarchy");
Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Override, true, true, true);
AttachIconsToChildren(skeletonUtility.boneRoot);
}
void SpawnOverrideHierarchyRootOnly () {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Root");
Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Override, true, true, true);
AttachIconsToChildren(skeletonUtility.boneRoot);
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Icons = SpineEditorUtilities.Icons;
[CustomEditor(typeof(SkeletonUtility))]
public class SkeletonUtilityInspector : UnityEditor.Editor {
SkeletonUtility skeletonUtility;
Skeleton skeleton;
SkeletonRenderer skeletonRenderer;
SkeletonGraphic skeletonGraphic;
#if !NEW_PREFAB_SYSTEM
bool isPrefab;
#endif
readonly GUIContent SpawnHierarchyButtonLabel = new GUIContent("Spawn Hierarchy", Icons.skeleton);
void OnEnable () {
skeletonUtility = (SkeletonUtility)target;
skeletonRenderer = skeletonUtility.skeletonRenderer;
skeletonGraphic = skeletonUtility.skeletonGraphic;
skeleton = skeletonUtility.Skeleton;
if (skeleton == null) {
if (skeletonRenderer != null) {
skeletonRenderer.Initialize(false);
skeletonRenderer.LateUpdate();
} else if (skeletonGraphic != null) {
skeletonGraphic.Initialize(false);
skeletonGraphic.LateUpdate();
}
skeleton = skeletonUtility.Skeleton;
}
if ((skeletonRenderer != null && !skeletonRenderer.valid) ||
(skeletonGraphic != null && !skeletonGraphic.IsValid)) return;
#if !NEW_PREFAB_SYSTEM
isPrefab |= PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab;
#endif
}
public override void OnInspectorGUI () {
#if !NEW_PREFAB_SYSTEM
if (isPrefab) {
GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning));
return;
}
#endif
serializedObject.Update();
if ((skeletonRenderer != null && !skeletonRenderer.valid) ||
(skeletonGraphic != null && !skeletonGraphic.IsValid)) {
GUILayout.Label(new GUIContent("Spine Component invalid. Check SkeletonData asset.", Icons.warning));
return;
}
EditorGUILayout.PropertyField(serializedObject.FindProperty("boneRoot"), SpineInspectorUtility.TempContent("Skeleton Root"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("flipBy180DegreeRotation"), SpineInspectorUtility.TempContent("Flip by Rotation", null,
"If true, Skeleton.ScaleX and Skeleton.ScaleY are followed " +
"by 180 degree rotation. If false, negative Transform scale is used. " +
"Note that using negative scale is consistent with previous behaviour (hence the default), " +
"however causes serious problems with rigidbodies and physics. Therefore, it is recommended to " +
"enable this parameter where possible. When creating hinge chains for a chain of skeleton bones " +
"via SkeletonUtilityBone, it is mandatory to have this parameter enabled."));
bool hasRootBone = skeletonUtility.boneRoot != null;
if (!hasRootBone)
EditorGUILayout.HelpBox("No hierarchy found. Use Spawn Hierarchy to generate GameObjects for bones.", MessageType.Info);
using (new EditorGUI.DisabledGroupScope(hasRootBone)) {
if (SpineInspectorUtility.LargeCenteredButton(SpawnHierarchyButtonLabel))
SpawnHierarchyContextMenu();
}
if (hasRootBone) {
if (SpineInspectorUtility.CenteredButton(new GUIContent("Remove Hierarchy"))) {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Remove Hierarchy");
Undo.DestroyObjectImmediate(skeletonUtility.boneRoot.gameObject);
skeletonUtility.boneRoot = null;
}
}
serializedObject.ApplyModifiedProperties();
}
void SpawnHierarchyContextMenu () {
var menu = new GenericMenu();
menu.AddItem(new GUIContent("Follow all bones"), false, SpawnFollowHierarchy);
menu.AddItem(new GUIContent("Follow (Root Only)"), false, SpawnFollowHierarchyRootOnly);
menu.AddSeparator("");
menu.AddItem(new GUIContent("Override all bones"), false, SpawnOverrideHierarchy);
menu.AddItem(new GUIContent("Override (Root Only)"), false, SpawnOverrideHierarchyRootOnly);
menu.ShowAsContext();
}
public static void AttachIcon (SkeletonUtilityBone boneComponent) {
Skeleton skeleton = boneComponent.hierarchy.Skeleton;
Texture2D icon = boneComponent.bone.Data.Length == 0 ? Icons.nullBone : Icons.boneNib;
foreach (IkConstraint c in skeleton.IkConstraints)
if (c.Target == boneComponent.bone) {
icon = Icons.constraintNib;
break;
}
typeof(EditorGUIUtility).InvokeMember("SetIconForObject", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, null, new object[2] {
boneComponent.gameObject,
icon
});
}
static void AttachIconsToChildren (Transform root) {
if (root != null) {
var utilityBones = root.GetComponentsInChildren<SkeletonUtilityBone>();
foreach (var utilBone in utilityBones)
AttachIcon(utilBone);
}
}
void SpawnFollowHierarchy () {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Hierarchy");
Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Follow, true, true, true);
AttachIconsToChildren(skeletonUtility.boneRoot);
}
void SpawnFollowHierarchyRootOnly () {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Root");
Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Follow, true, true, true);
AttachIconsToChildren(skeletonUtility.boneRoot);
}
void SpawnOverrideHierarchy () {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Hierarchy");
Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Override, true, true, true);
AttachIconsToChildren(skeletonUtility.boneRoot);
}
void SpawnOverrideHierarchyRootOnly () {
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Root");
Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Override, true, true, true);
AttachIconsToChildren(skeletonUtility.boneRoot);
}
}
}

View File

@@ -1,390 +1,390 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!181963792 &2655988077585873504
Preset:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: PMATexturePreset
m_TargetType:
m_NativeTypeID: 1006
m_ManagedTypePPtr: {fileID: 0}
m_ManagedTypeFallback:
m_Properties:
- target: {fileID: 0}
propertyPath: m_ExternalObjects.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapMode
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_EnableMipMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_sRGBTexture
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_LinearTexture
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_FadeOut
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_BorderMipMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapsPreserveCoverage
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaTestReferenceValue
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapFadeDistanceStart
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapFadeDistanceEnd
value: 3
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_ConvertToNormalMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_ExternalNormalMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_HeightScale
value: 0.25
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_NormalMapFilter
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_IsReadable
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_StreamingMipmaps
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_StreamingMipmapsPriority
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_GrayScaleToAlpha
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_GenerateCubemap
value: 6
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CubemapConvolution
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SeamlessCubemap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureFormat
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_FilterMode
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_Aniso
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_MipBias
value: -100
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapU
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapV
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapW
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_NPOTScale
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_Lightmap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteMode
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteExtrude
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteMeshType
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_Alignment
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePixelsToUnits
value: 100
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.w
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteGenerateFallbackPhysicsShape
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaUsage
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaIsTransparency
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteTessellationDetail
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureType
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureShape
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SingleChannelComponent
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MaxTextureSizeSet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CompressionQualitySet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureFormatSet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.size
value: 2
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget
value: DefaultTexturePlatform
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_Overridden
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_ForceMaximumCompressionQuality_BC6H_BC7
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget
value: Standalone
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_Overridden
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_ForceMaximumCompressionQuality_BC6H_BC7
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Sprites.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Outline.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Bones.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_SpriteID
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_InternalID
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Vertices.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Indices.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Edges.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Weights.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_SecondaryTextures.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePackingTag
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PSDRemoveMatte
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PSDShowRemoveMatteOption
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_UserData
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AssetBundleName
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AssetBundleVariant
value:
objectReference: {fileID: 0}
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!181963792 &2655988077585873504
Preset:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: PMATexturePreset
m_TargetType:
m_NativeTypeID: 1006
m_ManagedTypePPtr: {fileID: 0}
m_ManagedTypeFallback:
m_Properties:
- target: {fileID: 0}
propertyPath: m_ExternalObjects.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapMode
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_EnableMipMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_sRGBTexture
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_LinearTexture
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_FadeOut
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_BorderMipMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapsPreserveCoverage
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaTestReferenceValue
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapFadeDistanceStart
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapFadeDistanceEnd
value: 3
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_ConvertToNormalMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_ExternalNormalMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_HeightScale
value: 0.25
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_NormalMapFilter
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_IsReadable
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_StreamingMipmaps
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_StreamingMipmapsPriority
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_GrayScaleToAlpha
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_GenerateCubemap
value: 6
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CubemapConvolution
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SeamlessCubemap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureFormat
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_FilterMode
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_Aniso
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_MipBias
value: -100
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapU
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapV
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapW
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_NPOTScale
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_Lightmap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteMode
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteExtrude
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteMeshType
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_Alignment
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePixelsToUnits
value: 100
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.w
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteGenerateFallbackPhysicsShape
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaUsage
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaIsTransparency
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteTessellationDetail
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureType
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureShape
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SingleChannelComponent
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MaxTextureSizeSet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CompressionQualitySet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureFormatSet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.size
value: 2
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget
value: DefaultTexturePlatform
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_Overridden
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_ForceMaximumCompressionQuality_BC6H_BC7
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget
value: Standalone
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_Overridden
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_ForceMaximumCompressionQuality_BC6H_BC7
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Sprites.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Outline.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Bones.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_SpriteID
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_InternalID
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Vertices.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Indices.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Edges.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Weights.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_SecondaryTextures.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePackingTag
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PSDRemoveMatte
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PSDShowRemoveMatteOption
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_UserData
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AssetBundleName
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AssetBundleVariant
value:
objectReference: {fileID: 0}

View File

@@ -1,390 +1,390 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!181963792 &2655988077585873504
Preset:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: StraightAlphaPreset
m_TargetType:
m_NativeTypeID: 1006
m_ManagedTypePPtr: {fileID: 0}
m_ManagedTypeFallback:
m_Properties:
- target: {fileID: 0}
propertyPath: m_ExternalObjects.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapMode
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_EnableMipMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_sRGBTexture
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_LinearTexture
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_FadeOut
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_BorderMipMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapsPreserveCoverage
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaTestReferenceValue
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapFadeDistanceStart
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapFadeDistanceEnd
value: 3
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_ConvertToNormalMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_ExternalNormalMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_HeightScale
value: 0.25
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_NormalMapFilter
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_IsReadable
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_StreamingMipmaps
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_StreamingMipmapsPriority
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_GrayScaleToAlpha
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_GenerateCubemap
value: 6
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CubemapConvolution
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SeamlessCubemap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureFormat
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_FilterMode
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_Aniso
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_MipBias
value: -100
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapU
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapV
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapW
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_NPOTScale
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_Lightmap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteMode
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteExtrude
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteMeshType
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_Alignment
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePixelsToUnits
value: 100
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.w
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteGenerateFallbackPhysicsShape
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaUsage
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaIsTransparency
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteTessellationDetail
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureType
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureShape
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SingleChannelComponent
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MaxTextureSizeSet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CompressionQualitySet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureFormatSet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.size
value: 2
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget
value: DefaultTexturePlatform
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_Overridden
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_ForceMaximumCompressionQuality_BC6H_BC7
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget
value: Standalone
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_Overridden
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_ForceMaximumCompressionQuality_BC6H_BC7
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Sprites.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Outline.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Bones.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_SpriteID
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_InternalID
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Vertices.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Indices.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Edges.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Weights.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_SecondaryTextures.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePackingTag
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PSDRemoveMatte
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PSDShowRemoveMatteOption
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_UserData
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AssetBundleName
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AssetBundleVariant
value:
objectReference: {fileID: 0}
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!181963792 &2655988077585873504
Preset:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: StraightAlphaPreset
m_TargetType:
m_NativeTypeID: 1006
m_ManagedTypePPtr: {fileID: 0}
m_ManagedTypeFallback:
m_Properties:
- target: {fileID: 0}
propertyPath: m_ExternalObjects.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapMode
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_EnableMipMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_sRGBTexture
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_LinearTexture
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_FadeOut
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_BorderMipMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapsPreserveCoverage
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaTestReferenceValue
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapFadeDistanceStart
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MipMapFadeDistanceEnd
value: 3
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_ConvertToNormalMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_ExternalNormalMap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_HeightScale
value: 0.25
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_NormalMapFilter
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_IsReadable
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_StreamingMipmaps
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_StreamingMipmapsPriority
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_GrayScaleToAlpha
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_GenerateCubemap
value: 6
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CubemapConvolution
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SeamlessCubemap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureFormat
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_FilterMode
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_Aniso
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_MipBias
value: -100
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapU
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapV
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureSettings.m_WrapW
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_NPOTScale
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_Lightmap
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteMode
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteExtrude
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteMeshType
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_Alignment
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePixelsToUnits
value: 100
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteBorder.w
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteGenerateFallbackPhysicsShape
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaUsage
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AlphaIsTransparency
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteTessellationDetail
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureType
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureShape
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SingleChannelComponent
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_MaxTextureSizeSet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_CompressionQualitySet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_TextureFormatSet
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.size
value: 2
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_BuildTarget
value: DefaultTexturePlatform
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_ResizeAlgorithm
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_TextureFormat
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_TextureCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_CrunchedCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_AllowsAlphaSplitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_Overridden
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_AndroidETC2FallbackOverride
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[0].m_ForceMaximumCompressionQuality_BC6H_BC7
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_BuildTarget
value: Standalone
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_MaxTextureSize
value: 2048
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_ResizeAlgorithm
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_TextureFormat
value: -1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_TextureCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_CompressionQuality
value: 50
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_CrunchedCompression
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_AllowsAlphaSplitting
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_Overridden
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_AndroidETC2FallbackOverride
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PlatformSettings.Array.data[1].m_ForceMaximumCompressionQuality_BC6H_BC7
value: 1
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Sprites.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Outline.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_PhysicsShape.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Bones.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_SpriteID
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_InternalID
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Vertices.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Indices.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Edges.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_Weights.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpriteSheet.m_SecondaryTextures.Array.size
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_SpritePackingTag
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PSDRemoveMatte
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_PSDShowRemoveMatteOption
value: 0
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_UserData
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AssetBundleName
value:
objectReference: {fileID: 0}
- target: {fileID: 0}
propertyPath: m_AssetBundleVariant
value:
objectReference: {fileID: 0}

View File

@@ -1,47 +1,47 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public static class Menus {
[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
static public void CreateSkeletonRendererGameObject () {
EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonRenderer>("New SkeletonRenderer", true);
}
[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
static public void CreateSkeletonAnimationGameObject () {
EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonAnimation>("New SkeletonAnimation", true);
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public static class Menus {
[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
static public void CreateSkeletonRendererGameObject () {
EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonRenderer>("New SkeletonRenderer", true);
}
[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
static public void CreateSkeletonAnimationGameObject () {
EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonAnimation>("New SkeletonAnimation", true);
}
}
}

View File

@@ -1,221 +1,221 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine.Unity;
using UnityEditor;
using UnityEngine;
using SpineInspectorUtility = Spine.Unity.Editor.SpineInspectorUtility;
public class SpineShaderWithOutlineGUI : ShaderGUI {
protected MaterialEditor _materialEditor;
bool _showAdvancedOutlineSettings = false;
bool _showStencilSettings = false;
MaterialProperty _OutlineWidth = null;
MaterialProperty _OutlineColor = null;
MaterialProperty _OutlineReferenceTexWidth = null;
MaterialProperty _ThresholdEnd = null;
MaterialProperty _OutlineSmoothness = null;
MaterialProperty _Use8Neighbourhood = null;
MaterialProperty _OutlineMipLevel = null;
MaterialProperty _StencilComp = null;
MaterialProperty _StencilRef = null;
static GUIContent _EnableOutlineText = new GUIContent("Outline", "Enable outline rendering. Draws an outline by sampling 4 or 8 neighbourhood pixels at a given distance specified via 'Outline Width'.");
static GUIContent _OutlineWidthText = new GUIContent("Outline Width", "");
static GUIContent _OutlineColorText = new GUIContent("Outline Color", "");
static GUIContent _OutlineReferenceTexWidthText = new GUIContent("Reference Texture Width", "");
static GUIContent _ThresholdEndText = new GUIContent("Outline Threshold", "");
static GUIContent _OutlineSmoothnessText = new GUIContent("Outline Smoothness", "");
static GUIContent _Use8NeighbourhoodText = new GUIContent("Sample 8 Neighbours", "");
static GUIContent _OutlineMipLevelText = new GUIContent("Outline Mip Level", "");
static GUIContent _StencilCompText = new GUIContent("Stencil Comparison", "");
static GUIContent _StencilRefText = new GUIContent("Stencil Reference", "");
static GUIContent _OutlineAdvancedText = new GUIContent("Advanced", "");
static GUIContent _ShowStencilText = new GUIContent("Stencil", "Stencil parameters for mask interaction.");
protected const string ShaderOutlineNamePrefix = "Spine/Outline/";
protected const string ShaderNormalNamePrefix = "Spine/";
protected const string ShaderWithoutStandardVariantSuffix = "OutlineOnly";
#region ShaderGUI
public override void OnGUI (MaterialEditor materialEditor, MaterialProperty[] properties) {
FindProperties(properties); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
_materialEditor = materialEditor;
base.OnGUI(materialEditor, properties);
EditorGUILayout.Space();
RenderStencilProperties();
EditorGUILayout.Space();
RenderOutlineProperties();
}
#endregion
#region Virtual Interface
protected virtual void FindProperties (MaterialProperty[] props) {
_OutlineWidth = FindProperty("_OutlineWidth", props, false);
_OutlineReferenceTexWidth = FindProperty("_OutlineReferenceTexWidth", props, false);
_OutlineColor = FindProperty("_OutlineColor", props, false);
_ThresholdEnd = FindProperty("_ThresholdEnd", props, false);
_OutlineSmoothness = FindProperty("_OutlineSmoothness", props, false);
_Use8Neighbourhood = FindProperty("_Use8Neighbourhood", props, false);
_OutlineMipLevel = FindProperty("_OutlineMipLevel", props, false);
_StencilComp = FindProperty("_StencilComp", props, false);
_StencilRef = FindProperty("_StencilRef", props, false);
if (_StencilRef == null)
_StencilRef = FindProperty("_Stencil", props, false);
}
protected virtual void RenderStencilProperties () {
if (_StencilComp == null)
return; // not a shader supporting custom stencil operations
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
_showStencilSettings = EditorGUILayout.Foldout(_showStencilSettings, _ShowStencilText);
if (_showStencilSettings) {
using (new SpineInspectorUtility.IndentScope()) {
_materialEditor.ShaderProperty(_StencilComp, _StencilCompText);
_materialEditor.ShaderProperty(_StencilRef, _StencilRefText);
}
}
}
protected virtual void RenderOutlineProperties () {
if (_OutlineWidth == null)
return; // not an outline shader
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
bool mixedValue;
bool hasOutlineVariant = !IsShaderWithoutStandardVariantShader(_materialEditor, out mixedValue);
bool isOutlineEnabled = true;
if (hasOutlineVariant) {
isOutlineEnabled = IsOutlineEnabled(_materialEditor, out mixedValue);
EditorGUI.showMixedValue = mixedValue;
EditorGUI.BeginChangeCheck();
var origFontStyle = EditorStyles.label.fontStyle;
EditorStyles.label.fontStyle = FontStyle.Bold;
isOutlineEnabled = EditorGUILayout.Toggle(_EnableOutlineText, isOutlineEnabled);
EditorStyles.label.fontStyle = origFontStyle;
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck()) {
foreach (Material material in _materialEditor.targets) {
SwitchShaderToOutlineSettings(material, isOutlineEnabled);
}
}
} else {
var origFontStyle = EditorStyles.label.fontStyle;
EditorStyles.label.fontStyle = FontStyle.Bold;
EditorGUILayout.LabelField(_EnableOutlineText);
EditorStyles.label.fontStyle = origFontStyle;
}
if (isOutlineEnabled) {
_materialEditor.ShaderProperty(_OutlineWidth, _OutlineWidthText);
_materialEditor.ShaderProperty(_OutlineColor, _OutlineColorText);
_showAdvancedOutlineSettings = EditorGUILayout.Foldout(_showAdvancedOutlineSettings, _OutlineAdvancedText);
if (_showAdvancedOutlineSettings) {
using (new SpineInspectorUtility.IndentScope()) {
_materialEditor.ShaderProperty(_OutlineReferenceTexWidth, _OutlineReferenceTexWidthText);
_materialEditor.ShaderProperty(_ThresholdEnd, _ThresholdEndText);
_materialEditor.ShaderProperty(_OutlineSmoothness, _OutlineSmoothnessText);
_materialEditor.ShaderProperty(_Use8Neighbourhood, _Use8NeighbourhoodText);
_materialEditor.ShaderProperty(_OutlineMipLevel, _OutlineMipLevelText);
}
}
}
}
#endregion
#region Private Functions
void SwitchShaderToOutlineSettings (Material material, bool enableOutline) {
var shaderName = material.shader.name;
bool isSetToOutlineShader = shaderName.Contains(ShaderOutlineNamePrefix);
if (isSetToOutlineShader && !enableOutline) {
shaderName = shaderName.Replace(ShaderOutlineNamePrefix, ShaderNormalNamePrefix);
_materialEditor.SetShader(Shader.Find(shaderName), false);
return;
} else if (!isSetToOutlineShader && enableOutline) {
shaderName = shaderName.Replace(ShaderNormalNamePrefix, ShaderOutlineNamePrefix);
_materialEditor.SetShader(Shader.Find(shaderName), false);
return;
}
}
static bool IsOutlineEnabled (MaterialEditor editor, out bool mixedValue) {
mixedValue = false;
bool isAnyEnabled = false;
foreach (Material material in editor.targets) {
if (material.shader.name.Contains(ShaderOutlineNamePrefix)) {
isAnyEnabled = true;
} else if (isAnyEnabled) {
mixedValue = true;
}
}
return isAnyEnabled;
}
static bool IsShaderWithoutStandardVariantShader (MaterialEditor editor, out bool mixedValue) {
mixedValue = false;
bool isAnyShaderWithoutVariant = false;
foreach (Material material in editor.targets) {
if (material.shader.name.Contains(ShaderWithoutStandardVariantSuffix)) {
isAnyShaderWithoutVariant = true;
} else if (isAnyShaderWithoutVariant) {
mixedValue = true;
}
}
return isAnyShaderWithoutVariant;
}
static bool BoldToggleField (GUIContent label, bool value) {
FontStyle origFontStyle = EditorStyles.label.fontStyle;
EditorStyles.label.fontStyle = FontStyle.Bold;
value = EditorGUILayout.Toggle(label, value, EditorStyles.toggle);
EditorStyles.label.fontStyle = origFontStyle;
return value;
}
#endregion
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine.Unity;
using UnityEditor;
using UnityEngine;
using SpineInspectorUtility = Spine.Unity.Editor.SpineInspectorUtility;
public class SpineShaderWithOutlineGUI : ShaderGUI {
protected MaterialEditor _materialEditor;
bool _showAdvancedOutlineSettings = false;
bool _showStencilSettings = false;
MaterialProperty _OutlineWidth = null;
MaterialProperty _OutlineColor = null;
MaterialProperty _OutlineReferenceTexWidth = null;
MaterialProperty _ThresholdEnd = null;
MaterialProperty _OutlineSmoothness = null;
MaterialProperty _Use8Neighbourhood = null;
MaterialProperty _OutlineMipLevel = null;
MaterialProperty _StencilComp = null;
MaterialProperty _StencilRef = null;
static GUIContent _EnableOutlineText = new GUIContent("Outline", "Enable outline rendering. Draws an outline by sampling 4 or 8 neighbourhood pixels at a given distance specified via 'Outline Width'.");
static GUIContent _OutlineWidthText = new GUIContent("Outline Width", "");
static GUIContent _OutlineColorText = new GUIContent("Outline Color", "");
static GUIContent _OutlineReferenceTexWidthText = new GUIContent("Reference Texture Width", "");
static GUIContent _ThresholdEndText = new GUIContent("Outline Threshold", "");
static GUIContent _OutlineSmoothnessText = new GUIContent("Outline Smoothness", "");
static GUIContent _Use8NeighbourhoodText = new GUIContent("Sample 8 Neighbours", "");
static GUIContent _OutlineMipLevelText = new GUIContent("Outline Mip Level", "");
static GUIContent _StencilCompText = new GUIContent("Stencil Comparison", "");
static GUIContent _StencilRefText = new GUIContent("Stencil Reference", "");
static GUIContent _OutlineAdvancedText = new GUIContent("Advanced", "");
static GUIContent _ShowStencilText = new GUIContent("Stencil", "Stencil parameters for mask interaction.");
protected const string ShaderOutlineNamePrefix = "Spine/Outline/";
protected const string ShaderNormalNamePrefix = "Spine/";
protected const string ShaderWithoutStandardVariantSuffix = "OutlineOnly";
#region ShaderGUI
public override void OnGUI (MaterialEditor materialEditor, MaterialProperty[] properties) {
FindProperties(properties); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
_materialEditor = materialEditor;
base.OnGUI(materialEditor, properties);
EditorGUILayout.Space();
RenderStencilProperties();
EditorGUILayout.Space();
RenderOutlineProperties();
}
#endregion
#region Virtual Interface
protected virtual void FindProperties (MaterialProperty[] props) {
_OutlineWidth = FindProperty("_OutlineWidth", props, false);
_OutlineReferenceTexWidth = FindProperty("_OutlineReferenceTexWidth", props, false);
_OutlineColor = FindProperty("_OutlineColor", props, false);
_ThresholdEnd = FindProperty("_ThresholdEnd", props, false);
_OutlineSmoothness = FindProperty("_OutlineSmoothness", props, false);
_Use8Neighbourhood = FindProperty("_Use8Neighbourhood", props, false);
_OutlineMipLevel = FindProperty("_OutlineMipLevel", props, false);
_StencilComp = FindProperty("_StencilComp", props, false);
_StencilRef = FindProperty("_StencilRef", props, false);
if (_StencilRef == null)
_StencilRef = FindProperty("_Stencil", props, false);
}
protected virtual void RenderStencilProperties () {
if (_StencilComp == null)
return; // not a shader supporting custom stencil operations
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
_showStencilSettings = EditorGUILayout.Foldout(_showStencilSettings, _ShowStencilText);
if (_showStencilSettings) {
using (new SpineInspectorUtility.IndentScope()) {
_materialEditor.ShaderProperty(_StencilComp, _StencilCompText);
_materialEditor.ShaderProperty(_StencilRef, _StencilRefText);
}
}
}
protected virtual void RenderOutlineProperties () {
if (_OutlineWidth == null)
return; // not an outline shader
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
bool mixedValue;
bool hasOutlineVariant = !IsShaderWithoutStandardVariantShader(_materialEditor, out mixedValue);
bool isOutlineEnabled = true;
if (hasOutlineVariant) {
isOutlineEnabled = IsOutlineEnabled(_materialEditor, out mixedValue);
EditorGUI.showMixedValue = mixedValue;
EditorGUI.BeginChangeCheck();
var origFontStyle = EditorStyles.label.fontStyle;
EditorStyles.label.fontStyle = FontStyle.Bold;
isOutlineEnabled = EditorGUILayout.Toggle(_EnableOutlineText, isOutlineEnabled);
EditorStyles.label.fontStyle = origFontStyle;
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck()) {
foreach (Material material in _materialEditor.targets) {
SwitchShaderToOutlineSettings(material, isOutlineEnabled);
}
}
} else {
var origFontStyle = EditorStyles.label.fontStyle;
EditorStyles.label.fontStyle = FontStyle.Bold;
EditorGUILayout.LabelField(_EnableOutlineText);
EditorStyles.label.fontStyle = origFontStyle;
}
if (isOutlineEnabled) {
_materialEditor.ShaderProperty(_OutlineWidth, _OutlineWidthText);
_materialEditor.ShaderProperty(_OutlineColor, _OutlineColorText);
_showAdvancedOutlineSettings = EditorGUILayout.Foldout(_showAdvancedOutlineSettings, _OutlineAdvancedText);
if (_showAdvancedOutlineSettings) {
using (new SpineInspectorUtility.IndentScope()) {
_materialEditor.ShaderProperty(_OutlineReferenceTexWidth, _OutlineReferenceTexWidthText);
_materialEditor.ShaderProperty(_ThresholdEnd, _ThresholdEndText);
_materialEditor.ShaderProperty(_OutlineSmoothness, _OutlineSmoothnessText);
_materialEditor.ShaderProperty(_Use8Neighbourhood, _Use8NeighbourhoodText);
_materialEditor.ShaderProperty(_OutlineMipLevel, _OutlineMipLevelText);
}
}
}
}
#endregion
#region Private Functions
void SwitchShaderToOutlineSettings (Material material, bool enableOutline) {
var shaderName = material.shader.name;
bool isSetToOutlineShader = shaderName.Contains(ShaderOutlineNamePrefix);
if (isSetToOutlineShader && !enableOutline) {
shaderName = shaderName.Replace(ShaderOutlineNamePrefix, ShaderNormalNamePrefix);
_materialEditor.SetShader(Shader.Find(shaderName), false);
return;
} else if (!isSetToOutlineShader && enableOutline) {
shaderName = shaderName.Replace(ShaderNormalNamePrefix, ShaderOutlineNamePrefix);
_materialEditor.SetShader(Shader.Find(shaderName), false);
return;
}
}
static bool IsOutlineEnabled (MaterialEditor editor, out bool mixedValue) {
mixedValue = false;
bool isAnyEnabled = false;
foreach (Material material in editor.targets) {
if (material.shader.name.Contains(ShaderOutlineNamePrefix)) {
isAnyEnabled = true;
} else if (isAnyEnabled) {
mixedValue = true;
}
}
return isAnyEnabled;
}
static bool IsShaderWithoutStandardVariantShader (MaterialEditor editor, out bool mixedValue) {
mixedValue = false;
bool isAnyShaderWithoutVariant = false;
foreach (Material material in editor.targets) {
if (material.shader.name.Contains(ShaderWithoutStandardVariantSuffix)) {
isAnyShaderWithoutVariant = true;
} else if (isAnyShaderWithoutVariant) {
mixedValue = true;
}
}
return isAnyShaderWithoutVariant;
}
static bool BoldToggleField (GUIContent label, bool value) {
FontStyle origFontStyle = EditorStyles.label.fontStyle;
EditorStyles.label.fontStyle = FontStyle.Bold;
value = EditorGUILayout.Toggle(label, value, EditorStyles.toggle);
EditorStyles.label.fontStyle = origFontStyle;
return value;
}
#endregion
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +1,50 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEngine;
namespace Spine.Unity.Editor {
public static class AssetDatabaseAvailabilityDetector {
const string MarkerResourceName = "SpineAssetDatabaseMarker";
private static bool isMarkerLoaded;
public static bool IsAssetDatabaseAvailable (bool forceCheck = false) {
if (!forceCheck && isMarkerLoaded)
return true;
TextAsset markerTextAsset = Resources.Load<TextAsset>(AssetDatabaseAvailabilityDetector.MarkerResourceName);
isMarkerLoaded = markerTextAsset != null;
if (markerTextAsset != null) {
Resources.UnloadAsset(markerTextAsset);
}
return isMarkerLoaded;
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEngine;
namespace Spine.Unity.Editor {
public static class AssetDatabaseAvailabilityDetector {
const string MarkerResourceName = "SpineAssetDatabaseMarker";
private static bool isMarkerLoaded;
public static bool IsAssetDatabaseAvailable (bool forceCheck = false) {
if (!forceCheck && isMarkerLoaded)
return true;
TextAsset markerTextAsset = Resources.Load<TextAsset>(AssetDatabaseAvailabilityDetector.MarkerResourceName);
isMarkerLoaded = markerTextAsset != null;
if (markerTextAsset != null) {
Resources.UnloadAsset(markerTextAsset);
}
return isMarkerLoaded;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,276 +1,276 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
// from spine-unity 4.0 onward BlendModeMaterialAssets are obsolete and shall be upgraded.
#define UPGRADE_ALL_BLEND_MODE_MATERIALS
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public class BlendModeMaterialsUtility {
public const string MATERIAL_SUFFIX_MULTIPLY = "-Multiply";
public const string MATERIAL_SUFFIX_SCREEN = "-Screen";
public const string MATERIAL_SUFFIX_ADDITIVE = "-Additive";
#if UPGRADE_ALL_BLEND_MODE_MATERIALS
public const bool ShallUpgradeBlendModeMaterials = true;
#else
public const bool ShallUpgradeBlendModeMaterials = false;
#endif
protected class TemplateMaterials {
public Material multiplyTemplate;
public Material screenTemplate;
public Material additiveTemplate;
};
public static void UpgradeBlendModeMaterials (SkeletonDataAsset skeletonDataAsset) {
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
if (skeletonData == null)
return;
UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData, true);
}
public static void UpdateBlendModeMaterials (SkeletonDataAsset skeletonDataAsset) {
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
if (skeletonData == null)
return;
UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData, false);
}
public static void UpdateBlendModeMaterials (SkeletonDataAsset skeletonDataAsset, ref SkeletonData skeletonData,
bool upgradeFromModifierAssets = ShallUpgradeBlendModeMaterials) {
TemplateMaterials templateMaterials = new TemplateMaterials();
bool anyMaterialsChanged = ClearUndesiredMaterialEntries(skeletonDataAsset);
var blendModesModifierAsset = FindBlendModeMaterialsModifierAsset(skeletonDataAsset);
if (blendModesModifierAsset) {
if (upgradeFromModifierAssets) {
TransferSettingsFromModifierAsset(blendModesModifierAsset,
skeletonDataAsset, templateMaterials);
UpdateBlendmodeMaterialsRequiredState(skeletonDataAsset, skeletonData);
} else
return;
} else {
if (!UpdateBlendmodeMaterialsRequiredState(skeletonDataAsset, skeletonData))
return;
AssignPreferencesTemplateMaterials(templateMaterials);
}
bool success = CreateAndAssignMaterials(skeletonDataAsset, templateMaterials, ref anyMaterialsChanged);
if (success) {
if (blendModesModifierAsset != null) {
RemoveObsoleteModifierAsset(blendModesModifierAsset, skeletonDataAsset);
}
}
SpineEditorUtilities.ClearSkeletonDataAsset(skeletonDataAsset);
skeletonData = skeletonDataAsset.GetSkeletonData(true);
if (anyMaterialsChanged)
ReloadSceneSkeletons(skeletonDataAsset);
AssetDatabase.SaveAssets();
}
protected static bool ClearUndesiredMaterialEntries (SkeletonDataAsset skeletonDataAsset) {
Predicate<BlendModeMaterials.ReplacementMaterial> ifMaterialMissing = r => r.material == null;
bool anyMaterialsChanged = false;
if (!skeletonDataAsset.blendModeMaterials.applyAdditiveMaterial) {
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.additiveMaterials.Count > 0;
skeletonDataAsset.blendModeMaterials.additiveMaterials.Clear();
} else
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.additiveMaterials.RemoveAll(ifMaterialMissing) != 0;
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.multiplyMaterials.RemoveAll(ifMaterialMissing) != 0;
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.screenMaterials.RemoveAll(ifMaterialMissing) != 0;
return anyMaterialsChanged;
}
protected static BlendModeMaterialsAsset FindBlendModeMaterialsModifierAsset (SkeletonDataAsset skeletonDataAsset) {
foreach (var modifierAsset in skeletonDataAsset.skeletonDataModifiers) {
if (modifierAsset is BlendModeMaterialsAsset)
return (BlendModeMaterialsAsset)modifierAsset;
}
return null;
}
protected static bool UpdateBlendmodeMaterialsRequiredState (SkeletonDataAsset skeletonDataAsset, SkeletonData skeletonData) {
return skeletonDataAsset.blendModeMaterials.UpdateBlendmodeMaterialsRequiredState(skeletonData);
}
protected static void TransferSettingsFromModifierAsset (BlendModeMaterialsAsset modifierAsset,
SkeletonDataAsset skeletonDataAsset, TemplateMaterials templateMaterials) {
skeletonDataAsset.blendModeMaterials.TransferSettingsFrom(modifierAsset);
templateMaterials.multiplyTemplate = modifierAsset.multiplyMaterialTemplate;
templateMaterials.screenTemplate = modifierAsset.screenMaterialTemplate;
templateMaterials.additiveTemplate = modifierAsset.additiveMaterialTemplate;
}
protected static void RemoveObsoleteModifierAsset (BlendModeMaterialsAsset modifierAsset,
SkeletonDataAsset skeletonDataAsset) {
skeletonDataAsset.skeletonDataModifiers.Remove(modifierAsset);
Debug.Log(string.Format("BlendModeMaterialsAsset upgraded to built-in BlendModeMaterials at SkeletonData asset '{0}'.",
skeletonDataAsset.name), skeletonDataAsset);
EditorUtility.SetDirty(skeletonDataAsset);
}
protected static void AssignPreferencesTemplateMaterials (TemplateMaterials templateMaterials) {
templateMaterials.multiplyTemplate = SpineEditorUtilities.Preferences.BlendModeMaterialMultiply;
templateMaterials.screenTemplate = SpineEditorUtilities.Preferences.BlendModeMaterialScreen;
templateMaterials.additiveTemplate = SpineEditorUtilities.Preferences.BlendModeMaterialAdditive;
}
protected static bool CreateAndAssignMaterials (SkeletonDataAsset skeletonDataAsset,
TemplateMaterials templateMaterials, ref bool anyReplacementMaterialsChanged) {
bool anyCreationFailed = false;
var blendModeMaterials = skeletonDataAsset.blendModeMaterials;
bool applyAdditiveMaterial = blendModeMaterials.applyAdditiveMaterial;
var skinEntries = new List<Skin.SkinEntry>();
SpineEditorUtilities.ClearSkeletonDataAsset(skeletonDataAsset);
skeletonDataAsset.isUpgradingBlendModeMaterials = true;
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
var slotsItems = skeletonData.Slots.Items;
for (int slotIndex = 0, slotCount = skeletonData.Slots.Count; slotIndex < slotCount; slotIndex++) {
var slot = slotsItems[slotIndex];
if (slot.BlendMode == BlendMode.Normal) continue;
if (!applyAdditiveMaterial && slot.BlendMode == BlendMode.Additive) continue;
List<BlendModeMaterials.ReplacementMaterial> replacementMaterials = null;
Material materialTemplate = null;
string materialSuffix = null;
switch (slot.BlendMode) {
case BlendMode.Multiply:
replacementMaterials = blendModeMaterials.multiplyMaterials;
materialTemplate = templateMaterials.multiplyTemplate;
materialSuffix = MATERIAL_SUFFIX_MULTIPLY;
break;
case BlendMode.Screen:
replacementMaterials = blendModeMaterials.screenMaterials;
materialTemplate = templateMaterials.screenTemplate;
materialSuffix = MATERIAL_SUFFIX_SCREEN;
break;
case BlendMode.Additive:
replacementMaterials = blendModeMaterials.additiveMaterials;
materialTemplate = templateMaterials.additiveTemplate;
materialSuffix = MATERIAL_SUFFIX_ADDITIVE;
break;
}
skinEntries.Clear();
foreach (var skin in skeletonData.Skins)
skin.GetAttachments(slotIndex, skinEntries);
foreach (var entry in skinEntries) {
var renderableAttachment = entry.Attachment as IHasRendererObject;
if (renderableAttachment != null) {
var originalRegion = (AtlasRegion)renderableAttachment.RendererObject;
bool replacementExists = replacementMaterials.Exists(
replacement => replacement.pageName == originalRegion.page.name);
if (!replacementExists) {
bool createdNewMaterial;
var replacement = CreateOrLoadReplacementMaterial(originalRegion, materialTemplate, materialSuffix, out createdNewMaterial);
if (replacement != null) {
replacementMaterials.Add(replacement);
anyReplacementMaterialsChanged = true;
if (createdNewMaterial) {
Debug.Log(string.Format("Created blend mode Material '{0}' for SkeletonData asset '{1}'.",
replacement.material.name, skeletonDataAsset), replacement.material);
}
} else {
Debug.LogError(string.Format("Failed creating blend mode Material for SkeletonData asset '{0}'," +
" atlas page '{1}', template '{2}'.",
skeletonDataAsset.name, originalRegion.page.name, materialTemplate.name),
skeletonDataAsset);
anyCreationFailed = true;
}
}
}
}
}
skeletonDataAsset.isUpgradingBlendModeMaterials = false;
EditorUtility.SetDirty(skeletonDataAsset);
return !anyCreationFailed;
}
protected static string GetBlendModeMaterialPath (AtlasPage originalPage, string materialSuffix) {
var originalMaterial = originalPage.rendererObject as Material;
var originalPath = AssetDatabase.GetAssetPath(originalMaterial);
return originalPath.Replace(".mat", materialSuffix + ".mat");
}
protected static BlendModeMaterials.ReplacementMaterial CreateOrLoadReplacementMaterial (
AtlasRegion originalRegion, Material materialTemplate, string materialSuffix, out bool createdNewMaterial) {
createdNewMaterial = false;
var newReplacement = new BlendModeMaterials.ReplacementMaterial();
var originalPage = originalRegion.page;
var originalMaterial = originalPage.rendererObject as Material;
var blendMaterialPath = GetBlendModeMaterialPath(originalPage, materialSuffix);
newReplacement.pageName = originalPage.name;
if (File.Exists(blendMaterialPath)) {
newReplacement.material = AssetDatabase.LoadAssetAtPath<Material>(blendMaterialPath);
} else {
var blendModeMaterial = new Material(materialTemplate) {
name = originalMaterial.name + " " + materialTemplate.name,
mainTexture = originalMaterial.mainTexture
};
newReplacement.material = blendModeMaterial;
AssetDatabase.CreateAsset(blendModeMaterial, blendMaterialPath);
EditorUtility.SetDirty(blendModeMaterial);
createdNewMaterial = true;
}
if (newReplacement.material)
return newReplacement;
else
return null;
}
protected static void ReloadSceneSkeletons (SkeletonDataAsset skeletonDataAsset) {
if (SpineEditorUtilities.Preferences.autoReloadSceneSkeletons)
SpineEditorUtilities.DataReloadHandler.ReloadSceneSkeletonComponents(skeletonDataAsset);
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
// from spine-unity 4.0 onward BlendModeMaterialAssets are obsolete and shall be upgraded.
#define UPGRADE_ALL_BLEND_MODE_MATERIALS
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public class BlendModeMaterialsUtility {
public const string MATERIAL_SUFFIX_MULTIPLY = "-Multiply";
public const string MATERIAL_SUFFIX_SCREEN = "-Screen";
public const string MATERIAL_SUFFIX_ADDITIVE = "-Additive";
#if UPGRADE_ALL_BLEND_MODE_MATERIALS
public const bool ShallUpgradeBlendModeMaterials = true;
#else
public const bool ShallUpgradeBlendModeMaterials = false;
#endif
protected class TemplateMaterials {
public Material multiplyTemplate;
public Material screenTemplate;
public Material additiveTemplate;
};
public static void UpgradeBlendModeMaterials (SkeletonDataAsset skeletonDataAsset) {
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
if (skeletonData == null)
return;
UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData, true);
}
public static void UpdateBlendModeMaterials (SkeletonDataAsset skeletonDataAsset) {
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
if (skeletonData == null)
return;
UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData, false);
}
public static void UpdateBlendModeMaterials (SkeletonDataAsset skeletonDataAsset, ref SkeletonData skeletonData,
bool upgradeFromModifierAssets = ShallUpgradeBlendModeMaterials) {
TemplateMaterials templateMaterials = new TemplateMaterials();
bool anyMaterialsChanged = ClearUndesiredMaterialEntries(skeletonDataAsset);
var blendModesModifierAsset = FindBlendModeMaterialsModifierAsset(skeletonDataAsset);
if (blendModesModifierAsset) {
if (upgradeFromModifierAssets) {
TransferSettingsFromModifierAsset(blendModesModifierAsset,
skeletonDataAsset, templateMaterials);
UpdateBlendmodeMaterialsRequiredState(skeletonDataAsset, skeletonData);
} else
return;
} else {
if (!UpdateBlendmodeMaterialsRequiredState(skeletonDataAsset, skeletonData))
return;
AssignPreferencesTemplateMaterials(templateMaterials);
}
bool success = CreateAndAssignMaterials(skeletonDataAsset, templateMaterials, ref anyMaterialsChanged);
if (success) {
if (blendModesModifierAsset != null) {
RemoveObsoleteModifierAsset(blendModesModifierAsset, skeletonDataAsset);
}
}
SpineEditorUtilities.ClearSkeletonDataAsset(skeletonDataAsset);
skeletonData = skeletonDataAsset.GetSkeletonData(true);
if (anyMaterialsChanged)
ReloadSceneSkeletons(skeletonDataAsset);
AssetDatabase.SaveAssets();
}
protected static bool ClearUndesiredMaterialEntries (SkeletonDataAsset skeletonDataAsset) {
Predicate<BlendModeMaterials.ReplacementMaterial> ifMaterialMissing = r => r.material == null;
bool anyMaterialsChanged = false;
if (!skeletonDataAsset.blendModeMaterials.applyAdditiveMaterial) {
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.additiveMaterials.Count > 0;
skeletonDataAsset.blendModeMaterials.additiveMaterials.Clear();
} else
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.additiveMaterials.RemoveAll(ifMaterialMissing) != 0;
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.multiplyMaterials.RemoveAll(ifMaterialMissing) != 0;
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.screenMaterials.RemoveAll(ifMaterialMissing) != 0;
return anyMaterialsChanged;
}
protected static BlendModeMaterialsAsset FindBlendModeMaterialsModifierAsset (SkeletonDataAsset skeletonDataAsset) {
foreach (var modifierAsset in skeletonDataAsset.skeletonDataModifiers) {
if (modifierAsset is BlendModeMaterialsAsset)
return (BlendModeMaterialsAsset)modifierAsset;
}
return null;
}
protected static bool UpdateBlendmodeMaterialsRequiredState (SkeletonDataAsset skeletonDataAsset, SkeletonData skeletonData) {
return skeletonDataAsset.blendModeMaterials.UpdateBlendmodeMaterialsRequiredState(skeletonData);
}
protected static void TransferSettingsFromModifierAsset (BlendModeMaterialsAsset modifierAsset,
SkeletonDataAsset skeletonDataAsset, TemplateMaterials templateMaterials) {
skeletonDataAsset.blendModeMaterials.TransferSettingsFrom(modifierAsset);
templateMaterials.multiplyTemplate = modifierAsset.multiplyMaterialTemplate;
templateMaterials.screenTemplate = modifierAsset.screenMaterialTemplate;
templateMaterials.additiveTemplate = modifierAsset.additiveMaterialTemplate;
}
protected static void RemoveObsoleteModifierAsset (BlendModeMaterialsAsset modifierAsset,
SkeletonDataAsset skeletonDataAsset) {
skeletonDataAsset.skeletonDataModifiers.Remove(modifierAsset);
Debug.Log(string.Format("BlendModeMaterialsAsset upgraded to built-in BlendModeMaterials at SkeletonData asset '{0}'.",
skeletonDataAsset.name), skeletonDataAsset);
EditorUtility.SetDirty(skeletonDataAsset);
}
protected static void AssignPreferencesTemplateMaterials (TemplateMaterials templateMaterials) {
templateMaterials.multiplyTemplate = SpineEditorUtilities.Preferences.BlendModeMaterialMultiply;
templateMaterials.screenTemplate = SpineEditorUtilities.Preferences.BlendModeMaterialScreen;
templateMaterials.additiveTemplate = SpineEditorUtilities.Preferences.BlendModeMaterialAdditive;
}
protected static bool CreateAndAssignMaterials (SkeletonDataAsset skeletonDataAsset,
TemplateMaterials templateMaterials, ref bool anyReplacementMaterialsChanged) {
bool anyCreationFailed = false;
var blendModeMaterials = skeletonDataAsset.blendModeMaterials;
bool applyAdditiveMaterial = blendModeMaterials.applyAdditiveMaterial;
var skinEntries = new List<Skin.SkinEntry>();
SpineEditorUtilities.ClearSkeletonDataAsset(skeletonDataAsset);
skeletonDataAsset.isUpgradingBlendModeMaterials = true;
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
var slotsItems = skeletonData.Slots.Items;
for (int slotIndex = 0, slotCount = skeletonData.Slots.Count; slotIndex < slotCount; slotIndex++) {
var slot = slotsItems[slotIndex];
if (slot.BlendMode == BlendMode.Normal) continue;
if (!applyAdditiveMaterial && slot.BlendMode == BlendMode.Additive) continue;
List<BlendModeMaterials.ReplacementMaterial> replacementMaterials = null;
Material materialTemplate = null;
string materialSuffix = null;
switch (slot.BlendMode) {
case BlendMode.Multiply:
replacementMaterials = blendModeMaterials.multiplyMaterials;
materialTemplate = templateMaterials.multiplyTemplate;
materialSuffix = MATERIAL_SUFFIX_MULTIPLY;
break;
case BlendMode.Screen:
replacementMaterials = blendModeMaterials.screenMaterials;
materialTemplate = templateMaterials.screenTemplate;
materialSuffix = MATERIAL_SUFFIX_SCREEN;
break;
case BlendMode.Additive:
replacementMaterials = blendModeMaterials.additiveMaterials;
materialTemplate = templateMaterials.additiveTemplate;
materialSuffix = MATERIAL_SUFFIX_ADDITIVE;
break;
}
skinEntries.Clear();
foreach (var skin in skeletonData.Skins)
skin.GetAttachments(slotIndex, skinEntries);
foreach (var entry in skinEntries) {
var renderableAttachment = entry.Attachment as IHasRendererObject;
if (renderableAttachment != null) {
var originalRegion = (AtlasRegion)renderableAttachment.RendererObject;
bool replacementExists = replacementMaterials.Exists(
replacement => replacement.pageName == originalRegion.page.name);
if (!replacementExists) {
bool createdNewMaterial;
var replacement = CreateOrLoadReplacementMaterial(originalRegion, materialTemplate, materialSuffix, out createdNewMaterial);
if (replacement != null) {
replacementMaterials.Add(replacement);
anyReplacementMaterialsChanged = true;
if (createdNewMaterial) {
Debug.Log(string.Format("Created blend mode Material '{0}' for SkeletonData asset '{1}'.",
replacement.material.name, skeletonDataAsset), replacement.material);
}
} else {
Debug.LogError(string.Format("Failed creating blend mode Material for SkeletonData asset '{0}'," +
" atlas page '{1}', template '{2}'.",
skeletonDataAsset.name, originalRegion.page.name, materialTemplate.name),
skeletonDataAsset);
anyCreationFailed = true;
}
}
}
}
}
skeletonDataAsset.isUpgradingBlendModeMaterials = false;
EditorUtility.SetDirty(skeletonDataAsset);
return !anyCreationFailed;
}
protected static string GetBlendModeMaterialPath (AtlasPage originalPage, string materialSuffix) {
var originalMaterial = originalPage.rendererObject as Material;
var originalPath = AssetDatabase.GetAssetPath(originalMaterial);
return originalPath.Replace(".mat", materialSuffix + ".mat");
}
protected static BlendModeMaterials.ReplacementMaterial CreateOrLoadReplacementMaterial (
AtlasRegion originalRegion, Material materialTemplate, string materialSuffix, out bool createdNewMaterial) {
createdNewMaterial = false;
var newReplacement = new BlendModeMaterials.ReplacementMaterial();
var originalPage = originalRegion.page;
var originalMaterial = originalPage.rendererObject as Material;
var blendMaterialPath = GetBlendModeMaterialPath(originalPage, materialSuffix);
newReplacement.pageName = originalPage.name;
if (File.Exists(blendMaterialPath)) {
newReplacement.material = AssetDatabase.LoadAssetAtPath<Material>(blendMaterialPath);
} else {
var blendModeMaterial = new Material(materialTemplate) {
name = originalMaterial.name + " " + materialTemplate.name,
mainTexture = originalMaterial.mainTexture
};
newReplacement.material = blendModeMaterial;
AssetDatabase.CreateAsset(blendModeMaterial, blendMaterialPath);
EditorUtility.SetDirty(blendModeMaterial);
createdNewMaterial = true;
}
if (newReplacement.material)
return newReplacement;
else
return null;
}
protected static void ReloadSceneSkeletons (SkeletonDataAsset skeletonDataAsset) {
if (SpineEditorUtilities.Preferences.autoReloadSceneSkeletons)
SpineEditorUtilities.DataReloadHandler.ReloadSceneSkeletonComponents(skeletonDataAsset);
}
}
}

View File

@@ -1,179 +1,179 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
#if UNITY_2018 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEWHIERARCHYWINDOWCALLBACKS
#endif
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public partial class SpineEditorUtilities {
public static class SpineTK2DEditorUtility {
const string SPINE_TK2D_DEFINE = "SPINE_TK2D";
internal static bool IsTK2DInstalled () {
return (Shader.Find("tk2d/SolidVertexColor") != null ||
Shader.Find("tk2d/AdditiveVertexColor") != null);
}
internal static bool IsTK2DAllowed {
get {
return false; // replace with "return true;" to allow TK2D support
}
}
internal static void EnableTK2D () {
if (!IsTK2DAllowed)
return;
SpineBuildEnvUtility.DisableSpineAsmdefFiles();
SpineBuildEnvUtility.EnableBuildDefine(SPINE_TK2D_DEFINE);
}
internal static void DisableTK2D () {
SpineBuildEnvUtility.EnableSpineAsmdefFiles();
SpineBuildEnvUtility.DisableBuildDefine(SPINE_TK2D_DEFINE);
}
}
}
public static class SpineBuildEnvUtility {
static bool IsInvalidGroup (BuildTargetGroup group) {
int gi = (int)group;
return
gi == 15 || gi == 16
||
group == BuildTargetGroup.Unknown;
}
public static bool EnableBuildDefine (string define) {
bool wasDefineAdded = false;
Debug.LogWarning("Please ignore errors \"PlayerSettings Validation: Requested build target group doesn't exist\" below");
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
if (IsInvalidGroup(group))
continue;
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
if (!defines.Contains(define)) {
wasDefineAdded = true;
if (defines.EndsWith(";", System.StringComparison.Ordinal))
defines += define;
else
defines += ";" + define;
PlayerSettings.SetScriptingDefineSymbolsForGroup(group, defines);
}
}
Debug.LogWarning("Please ignore errors \"PlayerSettings Validation: Requested build target group doesn't exist\" above");
if (wasDefineAdded) {
Debug.LogWarning("Setting Scripting Define Symbol " + define);
} else {
Debug.LogWarning("Already Set Scripting Define Symbol " + define);
}
return wasDefineAdded;
}
public static bool DisableBuildDefine (string define) {
bool wasDefineRemoved = false;
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
if (IsInvalidGroup(group))
continue;
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
if (defines.Contains(define)) {
wasDefineRemoved = true;
if (defines.Contains(define + ";"))
defines = defines.Replace(define + ";", "");
else
defines = defines.Replace(define, "");
PlayerSettings.SetScriptingDefineSymbolsForGroup(group, defines);
}
}
if (wasDefineRemoved) {
Debug.LogWarning("Removing Scripting Define Symbol " + define);
} else {
Debug.LogWarning("Already Removed Scripting Define Symbol " + define);
}
return wasDefineRemoved;
}
public static void DisableSpineAsmdefFiles () {
SetAsmdefFileActive("spine-unity-editor", false);
SetAsmdefFileActive("spine-unity", false);
}
public static void EnableSpineAsmdefFiles () {
SetAsmdefFileActive("spine-unity-editor", true);
SetAsmdefFileActive("spine-unity", true);
}
internal static void SetAsmdefFileActive (string filename, bool setActive) {
string typeSearchString = setActive ? " t:TextAsset" : " t:AssemblyDefinitionAsset";
string extensionBeforeChange = setActive ? ".txt" : ".asmdef";
string[] guids = AssetDatabase.FindAssets(filename + typeSearchString);
foreach (string guid in guids) {
string currentPath = AssetDatabase.GUIDToAssetPath(guid);
if (System.IO.Path.GetExtension(currentPath) != extensionBeforeChange) // asmdef is also found as t:TextAsset, so check
continue;
string targetPath = System.IO.Path.ChangeExtension(currentPath, setActive ? "asmdef" : "txt");
if (System.IO.File.Exists(currentPath) && !System.IO.File.Exists(targetPath)) {
System.IO.File.Copy(currentPath, targetPath);
System.IO.File.Copy(currentPath + ".meta", targetPath + ".meta");
}
AssetDatabase.DeleteAsset(currentPath);
}
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
#if UNITY_2018 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEWHIERARCHYWINDOWCALLBACKS
#endif
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public partial class SpineEditorUtilities {
public static class SpineTK2DEditorUtility {
const string SPINE_TK2D_DEFINE = "SPINE_TK2D";
internal static bool IsTK2DInstalled () {
return (Shader.Find("tk2d/SolidVertexColor") != null ||
Shader.Find("tk2d/AdditiveVertexColor") != null);
}
internal static bool IsTK2DAllowed {
get {
return false; // replace with "return true;" to allow TK2D support
}
}
internal static void EnableTK2D () {
if (!IsTK2DAllowed)
return;
SpineBuildEnvUtility.DisableSpineAsmdefFiles();
SpineBuildEnvUtility.EnableBuildDefine(SPINE_TK2D_DEFINE);
}
internal static void DisableTK2D () {
SpineBuildEnvUtility.EnableSpineAsmdefFiles();
SpineBuildEnvUtility.DisableBuildDefine(SPINE_TK2D_DEFINE);
}
}
}
public static class SpineBuildEnvUtility {
static bool IsInvalidGroup (BuildTargetGroup group) {
int gi = (int)group;
return
gi == 15 || gi == 16
||
group == BuildTargetGroup.Unknown;
}
public static bool EnableBuildDefine (string define) {
bool wasDefineAdded = false;
Debug.LogWarning("Please ignore errors \"PlayerSettings Validation: Requested build target group doesn't exist\" below");
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
if (IsInvalidGroup(group))
continue;
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
if (!defines.Contains(define)) {
wasDefineAdded = true;
if (defines.EndsWith(";", System.StringComparison.Ordinal))
defines += define;
else
defines += ";" + define;
PlayerSettings.SetScriptingDefineSymbolsForGroup(group, defines);
}
}
Debug.LogWarning("Please ignore errors \"PlayerSettings Validation: Requested build target group doesn't exist\" above");
if (wasDefineAdded) {
Debug.LogWarning("Setting Scripting Define Symbol " + define);
} else {
Debug.LogWarning("Already Set Scripting Define Symbol " + define);
}
return wasDefineAdded;
}
public static bool DisableBuildDefine (string define) {
bool wasDefineRemoved = false;
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
if (IsInvalidGroup(group))
continue;
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
if (defines.Contains(define)) {
wasDefineRemoved = true;
if (defines.Contains(define + ";"))
defines = defines.Replace(define + ";", "");
else
defines = defines.Replace(define, "");
PlayerSettings.SetScriptingDefineSymbolsForGroup(group, defines);
}
}
if (wasDefineRemoved) {
Debug.LogWarning("Removing Scripting Define Symbol " + define);
} else {
Debug.LogWarning("Already Removed Scripting Define Symbol " + define);
}
return wasDefineRemoved;
}
public static void DisableSpineAsmdefFiles () {
SetAsmdefFileActive("spine-unity-editor", false);
SetAsmdefFileActive("spine-unity", false);
}
public static void EnableSpineAsmdefFiles () {
SetAsmdefFileActive("spine-unity-editor", true);
SetAsmdefFileActive("spine-unity", true);
}
internal static void SetAsmdefFileActive (string filename, bool setActive) {
string typeSearchString = setActive ? " t:TextAsset" : " t:AssemblyDefinitionAsset";
string extensionBeforeChange = setActive ? ".txt" : ".asmdef";
string[] guids = AssetDatabase.FindAssets(filename + typeSearchString);
foreach (string guid in guids) {
string currentPath = AssetDatabase.GUIDToAssetPath(guid);
if (System.IO.Path.GetExtension(currentPath) != extensionBeforeChange) // asmdef is also found as t:TextAsset, so check
continue;
string targetPath = System.IO.Path.ChangeExtension(currentPath, setActive ? "asmdef" : "txt");
if (System.IO.File.Exists(currentPath) && !System.IO.File.Exists(targetPath)) {
System.IO.File.Copy(currentPath, targetPath);
System.IO.File.Copy(currentPath + ".meta", targetPath + ".meta");
}
AssetDatabase.DeleteAsset(currentPath);
}
}
}
}

View File

@@ -1,144 +1,144 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public partial class SpineEditorUtilities {
public static class DataReloadHandler {
internal static Dictionary<int, string> savedSkeletonDataAssetAtSKeletonGraphicID = new Dictionary<int, string>();
#if NEWPLAYMODECALLBACKS
internal static void OnPlaymodeStateChanged (PlayModeStateChange stateChange) {
#else
internal static void OnPlaymodeStateChanged () {
#endif
ReloadAllActiveSkeletonsEditMode();
}
public static void ReloadAllActiveSkeletonsEditMode () {
if (EditorApplication.isPaused) return;
if (EditorApplication.isPlaying) return;
if (EditorApplication.isCompiling) return;
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
var skeletonDataAssetsToReload = new HashSet<SkeletonDataAsset>();
var activeSkeletonRenderers = GameObject.FindObjectsOfType<SkeletonRenderer>();
foreach (var sr in activeSkeletonRenderers) {
var skeletonDataAsset = sr.skeletonDataAsset;
if (skeletonDataAsset != null) skeletonDataAssetsToReload.Add(skeletonDataAsset);
}
// Under some circumstances (e.g. on first import) SkeletonGraphic objects
// have their skeletonGraphic.skeletonDataAsset reference corrupted
// by the instance of the ScriptableObject being destroyed but still assigned.
// Here we save the skeletonGraphic.skeletonDataAsset asset path in order
// to restore it later.
var activeSkeletonGraphics = GameObject.FindObjectsOfType<SkeletonGraphic>();
foreach (var skeletonGraphic in activeSkeletonGraphics) {
var skeletonDataAsset = skeletonGraphic.skeletonDataAsset;
if (skeletonDataAsset != null) {
var assetPath = AssetDatabase.GetAssetPath(skeletonDataAsset);
var sgID = skeletonGraphic.GetInstanceID();
savedSkeletonDataAssetAtSKeletonGraphicID[sgID] = assetPath;
skeletonDataAssetsToReload.Add(skeletonDataAsset);
}
}
foreach (var skeletonDataAsset in skeletonDataAssetsToReload) {
ReloadSkeletonDataAsset(skeletonDataAsset, false);
}
foreach (var skeletonRenderer in activeSkeletonRenderers)
skeletonRenderer.Initialize(true);
foreach (var skeletonGraphic in activeSkeletonGraphics)
skeletonGraphic.Initialize(true);
}
public static void ReloadSceneSkeletonComponents (SkeletonDataAsset skeletonDataAsset) {
if (EditorApplication.isPaused) return;
if (EditorApplication.isPlaying) return;
if (EditorApplication.isCompiling) return;
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
var activeSkeletonRenderers = GameObject.FindObjectsOfType<SkeletonRenderer>();
foreach (var renderer in activeSkeletonRenderers) {
if (renderer.isActiveAndEnabled && renderer.skeletonDataAsset == skeletonDataAsset) renderer.Initialize(true);
}
var activeSkeletonGraphics = GameObject.FindObjectsOfType<SkeletonGraphic>();
foreach (var graphic in activeSkeletonGraphics) {
if (graphic.isActiveAndEnabled && graphic.skeletonDataAsset == skeletonDataAsset)
graphic.Initialize(true);
}
}
public static void ClearAnimationReferenceAssets (SkeletonDataAsset skeletonDataAsset) {
ForEachAnimationReferenceAsset(skeletonDataAsset, (referenceAsset) => referenceAsset.Clear());
}
public static void ReloadAnimationReferenceAssets (SkeletonDataAsset skeletonDataAsset) {
ForEachAnimationReferenceAsset(skeletonDataAsset, (referenceAsset) => referenceAsset.Initialize());
}
private static void ForEachAnimationReferenceAsset (SkeletonDataAsset skeletonDataAsset,
System.Action<AnimationReferenceAsset> func) {
string[] guids = UnityEditor.AssetDatabase.FindAssets("t:AnimationReferenceAsset");
foreach (string guid in guids) {
string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
if (!string.IsNullOrEmpty(path)) {
var referenceAsset = UnityEditor.AssetDatabase.LoadAssetAtPath<AnimationReferenceAsset>(path);
if (referenceAsset.SkeletonDataAsset == skeletonDataAsset)
func(referenceAsset);
}
}
}
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public partial class SpineEditorUtilities {
public static class DataReloadHandler {
internal static Dictionary<int, string> savedSkeletonDataAssetAtSKeletonGraphicID = new Dictionary<int, string>();
#if NEWPLAYMODECALLBACKS
internal static void OnPlaymodeStateChanged (PlayModeStateChange stateChange) {
#else
internal static void OnPlaymodeStateChanged () {
#endif
ReloadAllActiveSkeletonsEditMode();
}
public static void ReloadAllActiveSkeletonsEditMode () {
if (EditorApplication.isPaused) return;
if (EditorApplication.isPlaying) return;
if (EditorApplication.isCompiling) return;
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
var skeletonDataAssetsToReload = new HashSet<SkeletonDataAsset>();
var activeSkeletonRenderers = GameObject.FindObjectsOfType<SkeletonRenderer>();
foreach (var sr in activeSkeletonRenderers) {
var skeletonDataAsset = sr.skeletonDataAsset;
if (skeletonDataAsset != null) skeletonDataAssetsToReload.Add(skeletonDataAsset);
}
// Under some circumstances (e.g. on first import) SkeletonGraphic objects
// have their skeletonGraphic.skeletonDataAsset reference corrupted
// by the instance of the ScriptableObject being destroyed but still assigned.
// Here we save the skeletonGraphic.skeletonDataAsset asset path in order
// to restore it later.
var activeSkeletonGraphics = GameObject.FindObjectsOfType<SkeletonGraphic>();
foreach (var skeletonGraphic in activeSkeletonGraphics) {
var skeletonDataAsset = skeletonGraphic.skeletonDataAsset;
if (skeletonDataAsset != null) {
var assetPath = AssetDatabase.GetAssetPath(skeletonDataAsset);
var sgID = skeletonGraphic.GetInstanceID();
savedSkeletonDataAssetAtSKeletonGraphicID[sgID] = assetPath;
skeletonDataAssetsToReload.Add(skeletonDataAsset);
}
}
foreach (var skeletonDataAsset in skeletonDataAssetsToReload) {
ReloadSkeletonDataAsset(skeletonDataAsset, false);
}
foreach (var skeletonRenderer in activeSkeletonRenderers)
skeletonRenderer.Initialize(true);
foreach (var skeletonGraphic in activeSkeletonGraphics)
skeletonGraphic.Initialize(true);
}
public static void ReloadSceneSkeletonComponents (SkeletonDataAsset skeletonDataAsset) {
if (EditorApplication.isPaused) return;
if (EditorApplication.isPlaying) return;
if (EditorApplication.isCompiling) return;
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
var activeSkeletonRenderers = GameObject.FindObjectsOfType<SkeletonRenderer>();
foreach (var renderer in activeSkeletonRenderers) {
if (renderer.isActiveAndEnabled && renderer.skeletonDataAsset == skeletonDataAsset) renderer.Initialize(true);
}
var activeSkeletonGraphics = GameObject.FindObjectsOfType<SkeletonGraphic>();
foreach (var graphic in activeSkeletonGraphics) {
if (graphic.isActiveAndEnabled && graphic.skeletonDataAsset == skeletonDataAsset)
graphic.Initialize(true);
}
}
public static void ClearAnimationReferenceAssets (SkeletonDataAsset skeletonDataAsset) {
ForEachAnimationReferenceAsset(skeletonDataAsset, (referenceAsset) => referenceAsset.Clear());
}
public static void ReloadAnimationReferenceAssets (SkeletonDataAsset skeletonDataAsset) {
ForEachAnimationReferenceAsset(skeletonDataAsset, (referenceAsset) => referenceAsset.Initialize());
}
private static void ForEachAnimationReferenceAsset (SkeletonDataAsset skeletonDataAsset,
System.Action<AnimationReferenceAsset> func) {
string[] guids = UnityEditor.AssetDatabase.FindAssets("t:AnimationReferenceAsset");
foreach (string guid in guids) {
string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
if (!string.IsNullOrEmpty(path)) {
var referenceAsset = UnityEditor.AssetDatabase.LoadAssetAtPath<AnimationReferenceAsset>(path);
if (referenceAsset.SkeletonDataAsset == skeletonDataAsset)
func(referenceAsset);
}
}
}
}
}
}

View File

@@ -1,147 +1,147 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public partial class SpineEditorUtilities {
public static class Icons {
public static Texture2D skeleton;
public static Texture2D nullBone;
public static Texture2D bone;
public static Texture2D poseBones;
public static Texture2D boneNib;
public static Texture2D slot;
public static Texture2D slotRoot;
public static Texture2D skinPlaceholder;
public static Texture2D image;
public static Texture2D genericAttachment;
public static Texture2D boundingBox;
public static Texture2D point;
public static Texture2D mesh;
public static Texture2D weights;
public static Texture2D path;
public static Texture2D clipping;
public static Texture2D skin;
public static Texture2D skinsRoot;
public static Texture2D animation;
public static Texture2D animationRoot;
public static Texture2D spine;
public static Texture2D userEvent;
public static Texture2D constraintNib;
public static Texture2D constraintRoot;
public static Texture2D constraintTransform;
public static Texture2D constraintPath;
public static Texture2D constraintIK;
public static Texture2D warning;
public static Texture2D skeletonUtility;
public static Texture2D hingeChain;
public static Texture2D subMeshRenderer;
public static Texture2D skeletonDataAssetIcon;
public static Texture2D info;
public static Texture2D unity;
static Texture2D LoadIcon (string filename) {
return (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/" + filename);
}
public static void Initialize () {
skeleton = LoadIcon("icon-skeleton.png");
nullBone = LoadIcon("icon-null.png");
bone = LoadIcon("icon-bone.png");
poseBones = LoadIcon("icon-poseBones.png");
boneNib = LoadIcon("icon-boneNib.png");
slot = LoadIcon("icon-slot.png");
slotRoot = LoadIcon("icon-slotRoot.png");
skinPlaceholder = LoadIcon("icon-skinPlaceholder.png");
genericAttachment = LoadIcon("icon-attachment.png");
image = LoadIcon("icon-image.png");
boundingBox = LoadIcon("icon-boundingBox.png");
point = LoadIcon("icon-point.png");
mesh = LoadIcon("icon-mesh.png");
weights = LoadIcon("icon-weights.png");
path = LoadIcon("icon-path.png");
clipping = LoadIcon("icon-clipping.png");
skin = LoadIcon("icon-skin.png");
skinsRoot = LoadIcon("icon-skinsRoot.png");
animation = LoadIcon("icon-animation.png");
animationRoot = LoadIcon("icon-animationRoot.png");
spine = LoadIcon("icon-spine.png");
userEvent = LoadIcon("icon-event.png");
constraintNib = LoadIcon("icon-constraintNib.png");
constraintRoot = LoadIcon("icon-constraints.png");
constraintTransform = LoadIcon("icon-constraintTransform.png");
constraintPath = LoadIcon("icon-constraintPath.png");
constraintIK = LoadIcon("icon-constraintIK.png");
warning = LoadIcon("icon-warning.png");
skeletonUtility = LoadIcon("icon-skeletonUtility.png");
hingeChain = LoadIcon("icon-hingeChain.png");
subMeshRenderer = LoadIcon("icon-subMeshRenderer.png");
skeletonDataAssetIcon = LoadIcon("SkeletonDataAsset Icon.png");
info = EditorGUIUtility.FindTexture("console.infoicon.sml");
unity = EditorGUIUtility.FindTexture("SceneAsset Icon");
}
public static Texture2D GetAttachmentIcon (Attachment attachment) {
// Analysis disable once CanBeReplacedWithTryCastAndCheckForNull
if (attachment is RegionAttachment)
return Icons.image;
else if (attachment is MeshAttachment)
return ((MeshAttachment)attachment).IsWeighted() ? Icons.weights : Icons.mesh;
else if (attachment is BoundingBoxAttachment)
return Icons.boundingBox;
else if (attachment is PointAttachment)
return Icons.point;
else if (attachment is PathAttachment)
return Icons.path;
else if (attachment is ClippingAttachment)
return Icons.clipping;
else
return Icons.warning;
}
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public partial class SpineEditorUtilities {
public static class Icons {
public static Texture2D skeleton;
public static Texture2D nullBone;
public static Texture2D bone;
public static Texture2D poseBones;
public static Texture2D boneNib;
public static Texture2D slot;
public static Texture2D slotRoot;
public static Texture2D skinPlaceholder;
public static Texture2D image;
public static Texture2D genericAttachment;
public static Texture2D boundingBox;
public static Texture2D point;
public static Texture2D mesh;
public static Texture2D weights;
public static Texture2D path;
public static Texture2D clipping;
public static Texture2D skin;
public static Texture2D skinsRoot;
public static Texture2D animation;
public static Texture2D animationRoot;
public static Texture2D spine;
public static Texture2D userEvent;
public static Texture2D constraintNib;
public static Texture2D constraintRoot;
public static Texture2D constraintTransform;
public static Texture2D constraintPath;
public static Texture2D constraintIK;
public static Texture2D warning;
public static Texture2D skeletonUtility;
public static Texture2D hingeChain;
public static Texture2D subMeshRenderer;
public static Texture2D skeletonDataAssetIcon;
public static Texture2D info;
public static Texture2D unity;
static Texture2D LoadIcon (string filename) {
return (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/" + filename);
}
public static void Initialize () {
skeleton = LoadIcon("icon-skeleton.png");
nullBone = LoadIcon("icon-null.png");
bone = LoadIcon("icon-bone.png");
poseBones = LoadIcon("icon-poseBones.png");
boneNib = LoadIcon("icon-boneNib.png");
slot = LoadIcon("icon-slot.png");
slotRoot = LoadIcon("icon-slotRoot.png");
skinPlaceholder = LoadIcon("icon-skinPlaceholder.png");
genericAttachment = LoadIcon("icon-attachment.png");
image = LoadIcon("icon-image.png");
boundingBox = LoadIcon("icon-boundingBox.png");
point = LoadIcon("icon-point.png");
mesh = LoadIcon("icon-mesh.png");
weights = LoadIcon("icon-weights.png");
path = LoadIcon("icon-path.png");
clipping = LoadIcon("icon-clipping.png");
skin = LoadIcon("icon-skin.png");
skinsRoot = LoadIcon("icon-skinsRoot.png");
animation = LoadIcon("icon-animation.png");
animationRoot = LoadIcon("icon-animationRoot.png");
spine = LoadIcon("icon-spine.png");
userEvent = LoadIcon("icon-event.png");
constraintNib = LoadIcon("icon-constraintNib.png");
constraintRoot = LoadIcon("icon-constraints.png");
constraintTransform = LoadIcon("icon-constraintTransform.png");
constraintPath = LoadIcon("icon-constraintPath.png");
constraintIK = LoadIcon("icon-constraintIK.png");
warning = LoadIcon("icon-warning.png");
skeletonUtility = LoadIcon("icon-skeletonUtility.png");
hingeChain = LoadIcon("icon-hingeChain.png");
subMeshRenderer = LoadIcon("icon-subMeshRenderer.png");
skeletonDataAssetIcon = LoadIcon("SkeletonDataAsset Icon.png");
info = EditorGUIUtility.FindTexture("console.infoicon.sml");
unity = EditorGUIUtility.FindTexture("SceneAsset Icon");
}
public static Texture2D GetAttachmentIcon (Attachment attachment) {
// Analysis disable once CanBeReplacedWithTryCastAndCheckForNull
if (attachment is RegionAttachment)
return Icons.image;
else if (attachment is MeshAttachment)
return ((MeshAttachment)attachment).IsWeighted() ? Icons.weights : Icons.mesh;
else if (attachment is BoundingBoxAttachment)
return Icons.boundingBox;
else if (attachment is PointAttachment)
return Icons.point;
else if (attachment is PathAttachment)
return Icons.path;
else if (attachment is ClippingAttachment)
return Icons.clipping;
else
return Icons.warning;
}
}
}
}

View File

@@ -1,199 +1,199 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using EventType = UnityEngine.EventType;
public partial class SpineEditorUtilities {
public static class DragAndDropInstantiation {
public struct SpawnMenuData {
public Vector3 spawnPoint;
public Transform parent;
public int siblingIndex;
public SkeletonDataAsset skeletonDataAsset;
public EditorInstantiation.InstantiateDelegate instantiateDelegate;
public bool isUI;
}
public static void SceneViewDragAndDrop (SceneView sceneview) {
var current = UnityEngine.Event.current;
var references = DragAndDrop.objectReferences;
if (current.type == EventType.Layout)
return;
// Allow drag and drop of one SkeletonDataAsset.
if (references.Length == 1) {
var skeletonDataAsset = references[0] as SkeletonDataAsset;
if (skeletonDataAsset != null) {
var mousePos = current.mousePosition;
bool invalidSkeletonData = skeletonDataAsset.GetSkeletonData(true) == null;
if (invalidSkeletonData) {
DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
Handles.BeginGUI();
GUI.Label(new Rect(mousePos + new Vector2(20f, 20f), new Vector2(400f, 40f)), new GUIContent(string.Format("{0} is invalid.\nCannot create new Spine GameObject.", skeletonDataAsset.name), SpineEditorUtilities.Icons.warning));
Handles.EndGUI();
return;
} else {
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
Handles.BeginGUI();
GUI.Label(new Rect(mousePos + new Vector2(20f, 20f), new Vector2(400f, 20f)), new GUIContent(string.Format("Create Spine GameObject ({0})", skeletonDataAsset.skeletonJSON.name), SpineEditorUtilities.Icons.skeletonDataAssetIcon));
Handles.EndGUI();
if (current.type == EventType.DragPerform) {
RectTransform rectTransform = (Selection.activeGameObject == null) ? null : Selection.activeGameObject.GetComponent<RectTransform>();
Plane plane = (rectTransform == null) ? new Plane(Vector3.back, Vector3.zero) : new Plane(-rectTransform.forward, rectTransform.position);
Vector3 spawnPoint = MousePointToWorldPoint2D(mousePos, sceneview.camera, plane);
ShowInstantiateContextMenu(skeletonDataAsset, spawnPoint, null, 0);
DragAndDrop.AcceptDrag();
current.Use();
}
}
}
}
}
public static void ShowInstantiateContextMenu (SkeletonDataAsset skeletonDataAsset, Vector3 spawnPoint,
Transform parent, int siblingIndex = 0) {
var menu = new GenericMenu();
// SkeletonAnimation
menu.AddItem(new GUIContent("SkeletonAnimation"), false, HandleSkeletonComponentDrop, new SpawnMenuData {
skeletonDataAsset = skeletonDataAsset,
spawnPoint = spawnPoint,
parent = parent,
siblingIndex = siblingIndex,
instantiateDelegate = (data) => EditorInstantiation.InstantiateSkeletonAnimation(data),
isUI = false
});
// SkeletonGraphic
var skeletonGraphicInspectorType = System.Type.GetType("Spine.Unity.Editor.SkeletonGraphicInspector");
if (skeletonGraphicInspectorType != null) {
var graphicInstantiateDelegate = skeletonGraphicInspectorType.GetMethod("SpawnSkeletonGraphicFromDrop", BindingFlags.Static | BindingFlags.Public);
if (graphicInstantiateDelegate != null)
menu.AddItem(new GUIContent("SkeletonGraphic (UI)"), false, HandleSkeletonComponentDrop, new SpawnMenuData {
skeletonDataAsset = skeletonDataAsset,
spawnPoint = spawnPoint,
parent = parent,
siblingIndex = siblingIndex,
instantiateDelegate = System.Delegate.CreateDelegate(typeof(EditorInstantiation.InstantiateDelegate), graphicInstantiateDelegate) as EditorInstantiation.InstantiateDelegate,
isUI = true
});
}
#if SPINE_SKELETONMECANIM
menu.AddSeparator("");
// SkeletonMecanim
menu.AddItem(new GUIContent("SkeletonMecanim"), false, HandleSkeletonComponentDrop, new SpawnMenuData {
skeletonDataAsset = skeletonDataAsset,
spawnPoint = spawnPoint,
parent = parent,
siblingIndex = siblingIndex,
instantiateDelegate = (data) => EditorInstantiation.InstantiateSkeletonMecanim(data),
isUI = false
});
#endif
menu.ShowAsContext();
}
public static void HandleSkeletonComponentDrop (object spawnMenuData) {
var data = (SpawnMenuData)spawnMenuData;
if (data.skeletonDataAsset.GetSkeletonData(true) == null) {
EditorUtility.DisplayDialog("Invalid SkeletonDataAsset", "Unable to create Spine GameObject.\n\nPlease check your SkeletonDataAsset.", "Ok");
return;
}
bool isUI = data.isUI;
Component newSkeletonComponent = data.instantiateDelegate.Invoke(data.skeletonDataAsset);
GameObject newGameObject = newSkeletonComponent.gameObject;
Transform newTransform = newGameObject.transform;
var usedParent = data.parent != null ? data.parent.gameObject : isUI ? Selection.activeGameObject : null;
if (usedParent)
newTransform.SetParent(usedParent.transform, false);
if (data.siblingIndex != 0)
newTransform.SetSiblingIndex(data.siblingIndex);
newTransform.position = isUI ? data.spawnPoint : RoundVector(data.spawnPoint, 2);
if (isUI) {
if (usedParent != null && usedParent.GetComponent<RectTransform>() != null) {
((SkeletonGraphic)newSkeletonComponent).MatchRectTransformWithBounds();
} else
Debug.Log("Created a UI Skeleton GameObject not under a RectTransform. It may not be visible until you parent it to a canvas.");
}
if (!isUI && usedParent != null && usedParent.transform.localScale != Vector3.one)
Debug.Log("New Spine GameObject was parented to a scaled Transform. It may not be the intended size.");
Selection.activeGameObject = newGameObject;
//EditorGUIUtility.PingObject(newGameObject); // Doesn't work when setting activeGameObject.
Undo.RegisterCreatedObjectUndo(newGameObject, "Create Spine GameObject");
}
/// <summary>
/// Rounds off vector components to a number of decimal digits.
/// </summary>
public static Vector3 RoundVector (Vector3 vector, int digits) {
vector.x = (float)System.Math.Round(vector.x, digits);
vector.y = (float)System.Math.Round(vector.y, digits);
vector.z = (float)System.Math.Round(vector.z, digits);
return vector;
}
/// <summary>
/// Converts a mouse point to a world point on a plane.
/// </summary>
static Vector3 MousePointToWorldPoint2D (Vector2 mousePosition, Camera camera, Plane plane) {
var screenPos = new Vector3(mousePosition.x, camera.pixelHeight - mousePosition.y, 0f);
var ray = camera.ScreenPointToRay(screenPos);
float distance;
bool hit = plane.Raycast(ray, out distance);
return ray.GetPoint(distance);
}
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using EventType = UnityEngine.EventType;
public partial class SpineEditorUtilities {
public static class DragAndDropInstantiation {
public struct SpawnMenuData {
public Vector3 spawnPoint;
public Transform parent;
public int siblingIndex;
public SkeletonDataAsset skeletonDataAsset;
public EditorInstantiation.InstantiateDelegate instantiateDelegate;
public bool isUI;
}
public static void SceneViewDragAndDrop (SceneView sceneview) {
var current = UnityEngine.Event.current;
var references = DragAndDrop.objectReferences;
if (current.type == EventType.Layout)
return;
// Allow drag and drop of one SkeletonDataAsset.
if (references.Length == 1) {
var skeletonDataAsset = references[0] as SkeletonDataAsset;
if (skeletonDataAsset != null) {
var mousePos = current.mousePosition;
bool invalidSkeletonData = skeletonDataAsset.GetSkeletonData(true) == null;
if (invalidSkeletonData) {
DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
Handles.BeginGUI();
GUI.Label(new Rect(mousePos + new Vector2(20f, 20f), new Vector2(400f, 40f)), new GUIContent(string.Format("{0} is invalid.\nCannot create new Spine GameObject.", skeletonDataAsset.name), SpineEditorUtilities.Icons.warning));
Handles.EndGUI();
return;
} else {
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
Handles.BeginGUI();
GUI.Label(new Rect(mousePos + new Vector2(20f, 20f), new Vector2(400f, 20f)), new GUIContent(string.Format("Create Spine GameObject ({0})", skeletonDataAsset.skeletonJSON.name), SpineEditorUtilities.Icons.skeletonDataAssetIcon));
Handles.EndGUI();
if (current.type == EventType.DragPerform) {
RectTransform rectTransform = (Selection.activeGameObject == null) ? null : Selection.activeGameObject.GetComponent<RectTransform>();
Plane plane = (rectTransform == null) ? new Plane(Vector3.back, Vector3.zero) : new Plane(-rectTransform.forward, rectTransform.position);
Vector3 spawnPoint = MousePointToWorldPoint2D(mousePos, sceneview.camera, plane);
ShowInstantiateContextMenu(skeletonDataAsset, spawnPoint, null, 0);
DragAndDrop.AcceptDrag();
current.Use();
}
}
}
}
}
public static void ShowInstantiateContextMenu (SkeletonDataAsset skeletonDataAsset, Vector3 spawnPoint,
Transform parent, int siblingIndex = 0) {
var menu = new GenericMenu();
// SkeletonAnimation
menu.AddItem(new GUIContent("SkeletonAnimation"), false, HandleSkeletonComponentDrop, new SpawnMenuData {
skeletonDataAsset = skeletonDataAsset,
spawnPoint = spawnPoint,
parent = parent,
siblingIndex = siblingIndex,
instantiateDelegate = (data) => EditorInstantiation.InstantiateSkeletonAnimation(data),
isUI = false
});
// SkeletonGraphic
var skeletonGraphicInspectorType = System.Type.GetType("Spine.Unity.Editor.SkeletonGraphicInspector");
if (skeletonGraphicInspectorType != null) {
var graphicInstantiateDelegate = skeletonGraphicInspectorType.GetMethod("SpawnSkeletonGraphicFromDrop", BindingFlags.Static | BindingFlags.Public);
if (graphicInstantiateDelegate != null)
menu.AddItem(new GUIContent("SkeletonGraphic (UI)"), false, HandleSkeletonComponentDrop, new SpawnMenuData {
skeletonDataAsset = skeletonDataAsset,
spawnPoint = spawnPoint,
parent = parent,
siblingIndex = siblingIndex,
instantiateDelegate = System.Delegate.CreateDelegate(typeof(EditorInstantiation.InstantiateDelegate), graphicInstantiateDelegate) as EditorInstantiation.InstantiateDelegate,
isUI = true
});
}
#if SPINE_SKELETONMECANIM
menu.AddSeparator("");
// SkeletonMecanim
menu.AddItem(new GUIContent("SkeletonMecanim"), false, HandleSkeletonComponentDrop, new SpawnMenuData {
skeletonDataAsset = skeletonDataAsset,
spawnPoint = spawnPoint,
parent = parent,
siblingIndex = siblingIndex,
instantiateDelegate = (data) => EditorInstantiation.InstantiateSkeletonMecanim(data),
isUI = false
});
#endif
menu.ShowAsContext();
}
public static void HandleSkeletonComponentDrop (object spawnMenuData) {
var data = (SpawnMenuData)spawnMenuData;
if (data.skeletonDataAsset.GetSkeletonData(true) == null) {
EditorUtility.DisplayDialog("Invalid SkeletonDataAsset", "Unable to create Spine GameObject.\n\nPlease check your SkeletonDataAsset.", "Ok");
return;
}
bool isUI = data.isUI;
Component newSkeletonComponent = data.instantiateDelegate.Invoke(data.skeletonDataAsset);
GameObject newGameObject = newSkeletonComponent.gameObject;
Transform newTransform = newGameObject.transform;
var usedParent = data.parent != null ? data.parent.gameObject : isUI ? Selection.activeGameObject : null;
if (usedParent)
newTransform.SetParent(usedParent.transform, false);
if (data.siblingIndex != 0)
newTransform.SetSiblingIndex(data.siblingIndex);
newTransform.position = isUI ? data.spawnPoint : RoundVector(data.spawnPoint, 2);
if (isUI) {
if (usedParent != null && usedParent.GetComponent<RectTransform>() != null) {
((SkeletonGraphic)newSkeletonComponent).MatchRectTransformWithBounds();
} else
Debug.Log("Created a UI Skeleton GameObject not under a RectTransform. It may not be visible until you parent it to a canvas.");
}
if (!isUI && usedParent != null && usedParent.transform.localScale != Vector3.one)
Debug.Log("New Spine GameObject was parented to a scaled Transform. It may not be the intended size.");
Selection.activeGameObject = newGameObject;
//EditorGUIUtility.PingObject(newGameObject); // Doesn't work when setting activeGameObject.
Undo.RegisterCreatedObjectUndo(newGameObject, "Create Spine GameObject");
}
/// <summary>
/// Rounds off vector components to a number of decimal digits.
/// </summary>
public static Vector3 RoundVector (Vector3 vector, int digits) {
vector.x = (float)System.Math.Round(vector.x, digits);
vector.y = (float)System.Math.Round(vector.y, digits);
vector.z = (float)System.Math.Round(vector.z, digits);
return vector;
}
/// <summary>
/// Converts a mouse point to a world point on a plane.
/// </summary>
static Vector3 MousePointToWorldPoint2D (Vector2 mousePosition, Camera camera, Plane plane) {
var screenPos = new Vector3(mousePosition.x, camera.pixelHeight - mousePosition.y, 0f);
var ray = camera.ScreenPointToRay(screenPos);
float distance;
bool hit = plane.Raycast(ray, out distance);
return ray.GetPoint(distance);
}
}
}
}

View File

@@ -1,434 +1,434 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
#if UNITY_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public partial class SpineEditorUtilities {
#if NEW_PREFERENCES_SETTINGS_PROVIDER
static class SpineSettingsProviderRegistration {
[SettingsProvider]
public static SettingsProvider CreateSpineSettingsProvider () {
var provider = new SettingsProvider("Spine", SettingsScope.User) {
label = "Spine",
guiHandler = (searchContext) => {
var settings = SpinePreferences.GetOrCreateSettings();
var serializedSettings = new SerializedObject(settings);
SpinePreferences.HandlePreferencesGUI(serializedSettings);
if (serializedSettings.ApplyModifiedProperties())
OldPreferences.SaveToEditorPrefs(settings);
},
// Populate the search keywords to enable smart search filtering and label highlighting:
keywords = new HashSet<string>(new[] { "Spine", "Preferences", "Skeleton", "Default", "Mix", "Duration" })
};
return provider;
}
}
#else
// Preferences entry point
[PreferenceItem("Spine")]
static void PreferencesGUI () {
Preferences.HandlePreferencesGUI();
}
#endif
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static SpinePreferences Preferences {
get {
return SpinePreferences.GetOrCreateSettings();
}
}
#endif
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static class OldPreferences {
#else
public static class Preferences {
#endif
const string DEFAULT_SCALE_KEY = "SPINE_DEFAULT_SCALE";
public static float defaultScale = SpinePreferences.DEFAULT_DEFAULT_SCALE;
const string DEFAULT_MIX_KEY = "SPINE_DEFAULT_MIX";
public static float defaultMix = SpinePreferences.DEFAULT_DEFAULT_MIX;
const string DEFAULT_SHADER_KEY = "SPINE_DEFAULT_SHADER";
public static string defaultShader = SpinePreferences.DEFAULT_DEFAULT_SHADER;
public static string DefaultShader {
get { return !string.IsNullOrEmpty(defaultShader) ? defaultShader : SpinePreferences.DEFAULT_DEFAULT_SHADER; }
set { defaultShader = value; }
}
const string DEFAULT_ZSPACING_KEY = "SPINE_DEFAULT_ZSPACING";
public static float defaultZSpacing = SpinePreferences.DEFAULT_DEFAULT_ZSPACING;
const string DEFAULT_INSTANTIATE_LOOP_KEY = "SPINE_DEFAULT_INSTANTIATE_LOOP";
public static bool defaultInstantiateLoop = SpinePreferences.DEFAULT_DEFAULT_INSTANTIATE_LOOP;
const string SHOW_HIERARCHY_ICONS_KEY = "SPINE_SHOW_HIERARCHY_ICONS";
public static bool showHierarchyIcons = SpinePreferences.DEFAULT_SHOW_HIERARCHY_ICONS;
const string SET_TEXTUREIMPORTER_SETTINGS_KEY = "SPINE_SET_TEXTUREIMPORTER_SETTINGS";
public static bool setTextureImporterSettings = SpinePreferences.DEFAULT_SET_TEXTUREIMPORTER_SETTINGS;
const string TEXTURE_SETTINGS_REFERENCE_KEY = "SPINE_TEXTURE_SETTINGS_REFERENCE";
public static string textureSettingsReference = SpinePreferences.DEFAULT_TEXTURE_SETTINGS_REFERENCE;
public static bool UsesPMAWorkflow {
get {
return SpinePreferences.IsPMAWorkflow(textureSettingsReference);
}
}
const string BLEND_MODE_MATERIAL_MULTIPLY_KEY = "SPINE_BLENDMODE_MATERIAL_MULTIPLY";
const string BLEND_MODE_MATERIAL_SCREEN_KEY = "SPINE_BLENDMODE_MATERIAL_SCREEN";
const string BLEND_MODE_MATERIAL_ADDITIVE_KEY = "SPINE_BLENDMODE_MATERIAL_ADDITIVE";
public static string blendModeMaterialMultiply = "";
public static string blendModeMaterialScreen = "";
public static string blendModeMaterialAdditive = "";
public const string DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL = SpinePreferences.DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL;
public const string DEFAULT_BLEND_MODE_SCREEN_MATERIAL = SpinePreferences.DEFAULT_BLEND_MODE_SCREEN_MATERIAL;
public const string DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL = SpinePreferences.DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL;
public static Material BlendModeMaterialMultiply {
get { return AssetDatabase.LoadAssetAtPath<Material>(blendModeMaterialMultiply); }
}
public static Material BlendModeMaterialScreen {
get { return AssetDatabase.LoadAssetAtPath<Material>(blendModeMaterialScreen); }
}
public static Material BlendModeMaterialAdditive {
get { return AssetDatabase.LoadAssetAtPath<Material>(blendModeMaterialAdditive); }
}
const string ATLASTXT_WARNING_KEY = "SPINE_ATLASTXT_WARNING";
public static bool atlasTxtImportWarning = SpinePreferences.DEFAULT_ATLASTXT_WARNING;
const string TEXTUREIMPORTER_WARNING_KEY = "SPINE_TEXTUREIMPORTER_WARNING";
public static bool textureImporterWarning = SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING;
const string COMPONENTMATERIAL_WARNING_KEY = "SPINE_COMPONENTMATERIAL_WARNING";
public static bool componentMaterialWarning = SpinePreferences.DEFAULT_COMPONENTMATERIAL_WARNING;
public const float DEFAULT_MIPMAPBIAS = SpinePreferences.DEFAULT_MIPMAPBIAS;
public const string SCENE_ICONS_SCALE_KEY = "SPINE_SCENE_ICONS_SCALE";
public static float handleScale = SpinePreferences.DEFAULT_SCENE_ICONS_SCALE;
const string AUTO_RELOAD_SCENESKELETONS_KEY = "SPINE_AUTO_RELOAD_SCENESKELETONS";
public static bool autoReloadSceneSkeletons = SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS;
const string MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY = "SPINE_MECANIM_EVENT_INCLUDE_FOLDERNAME";
public static bool mecanimEventIncludeFolderName = SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME;
const string TIMELINE_USE_BLEND_DURATION_KEY = "SPINE_TIMELINE_USE_BLEND_DURATION_KEY";
public static bool timelineUseBlendDuration = SpinePreferences.DEFAULT_TIMELINE_USE_BLEND_DURATION;
static bool preferencesLoaded = false;
public static void Load () {
if (preferencesLoaded)
return;
defaultMix = EditorPrefs.GetFloat(DEFAULT_MIX_KEY, SpinePreferences.DEFAULT_DEFAULT_MIX);
defaultScale = EditorPrefs.GetFloat(DEFAULT_SCALE_KEY, SpinePreferences.DEFAULT_DEFAULT_SCALE);
defaultZSpacing = EditorPrefs.GetFloat(DEFAULT_ZSPACING_KEY, SpinePreferences.DEFAULT_DEFAULT_ZSPACING);
defaultShader = EditorPrefs.GetString(DEFAULT_SHADER_KEY, SpinePreferences.DEFAULT_DEFAULT_SHADER);
showHierarchyIcons = EditorPrefs.GetBool(SHOW_HIERARCHY_ICONS_KEY, SpinePreferences.DEFAULT_SHOW_HIERARCHY_ICONS);
setTextureImporterSettings = EditorPrefs.GetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, SpinePreferences.DEFAULT_SET_TEXTUREIMPORTER_SETTINGS);
textureSettingsReference = EditorPrefs.GetString(TEXTURE_SETTINGS_REFERENCE_KEY, SpinePreferences.DEFAULT_TEXTURE_SETTINGS_REFERENCE);
blendModeMaterialMultiply = EditorPrefs.GetString(BLEND_MODE_MATERIAL_MULTIPLY_KEY, "");
blendModeMaterialScreen = EditorPrefs.GetString(BLEND_MODE_MATERIAL_SCREEN_KEY, "");
blendModeMaterialAdditive = EditorPrefs.GetString(BLEND_MODE_MATERIAL_ADDITIVE_KEY, "");
autoReloadSceneSkeletons = EditorPrefs.GetBool(AUTO_RELOAD_SCENESKELETONS_KEY, SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS);
mecanimEventIncludeFolderName = EditorPrefs.GetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME);
atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, SpinePreferences.DEFAULT_ATLASTXT_WARNING);
textureImporterWarning = EditorPrefs.GetBool(TEXTUREIMPORTER_WARNING_KEY, SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING);
componentMaterialWarning = EditorPrefs.GetBool(COMPONENTMATERIAL_WARNING_KEY, SpinePreferences.DEFAULT_COMPONENTMATERIAL_WARNING);
timelineUseBlendDuration = EditorPrefs.GetBool(TIMELINE_USE_BLEND_DURATION_KEY, SpinePreferences.DEFAULT_TIMELINE_USE_BLEND_DURATION);
handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, SpinePreferences.DEFAULT_SCENE_ICONS_SCALE);
preferencesLoaded = true;
}
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static void CopyOldToNewPreferences (ref SpinePreferences newPreferences) {
newPreferences.defaultMix = EditorPrefs.GetFloat(DEFAULT_MIX_KEY, SpinePreferences.DEFAULT_DEFAULT_MIX);
newPreferences.defaultScale = EditorPrefs.GetFloat(DEFAULT_SCALE_KEY, SpinePreferences.DEFAULT_DEFAULT_SCALE);
newPreferences.defaultZSpacing = EditorPrefs.GetFloat(DEFAULT_ZSPACING_KEY, SpinePreferences.DEFAULT_DEFAULT_ZSPACING);
newPreferences.defaultShader = EditorPrefs.GetString(DEFAULT_SHADER_KEY, SpinePreferences.DEFAULT_DEFAULT_SHADER);
newPreferences.showHierarchyIcons = EditorPrefs.GetBool(SHOW_HIERARCHY_ICONS_KEY, SpinePreferences.DEFAULT_SHOW_HIERARCHY_ICONS);
newPreferences.setTextureImporterSettings = EditorPrefs.GetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, SpinePreferences.DEFAULT_SET_TEXTUREIMPORTER_SETTINGS);
newPreferences.textureSettingsReference = EditorPrefs.GetString(TEXTURE_SETTINGS_REFERENCE_KEY, SpinePreferences.DEFAULT_TEXTURE_SETTINGS_REFERENCE);
newPreferences.autoReloadSceneSkeletons = EditorPrefs.GetBool(AUTO_RELOAD_SCENESKELETONS_KEY, SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS);
newPreferences.mecanimEventIncludeFolderName = EditorPrefs.GetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME);
newPreferences.atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, SpinePreferences.DEFAULT_ATLASTXT_WARNING);
newPreferences.textureImporterWarning = EditorPrefs.GetBool(TEXTUREIMPORTER_WARNING_KEY, SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING);
newPreferences.componentMaterialWarning = EditorPrefs.GetBool(COMPONENTMATERIAL_WARNING_KEY, SpinePreferences.DEFAULT_COMPONENTMATERIAL_WARNING);
newPreferences.timelineUseBlendDuration = EditorPrefs.GetBool(TIMELINE_USE_BLEND_DURATION_KEY, SpinePreferences.DEFAULT_TIMELINE_USE_BLEND_DURATION);
newPreferences.handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, SpinePreferences.DEFAULT_SCENE_ICONS_SCALE);
}
public static void SaveToEditorPrefs (SpinePreferences preferences) {
EditorPrefs.SetFloat(DEFAULT_MIX_KEY, preferences.defaultMix);
EditorPrefs.SetFloat(DEFAULT_SCALE_KEY, preferences.defaultScale);
EditorPrefs.SetFloat(DEFAULT_ZSPACING_KEY, preferences.defaultZSpacing);
EditorPrefs.SetString(DEFAULT_SHADER_KEY, preferences.defaultShader);
EditorPrefs.SetBool(SHOW_HIERARCHY_ICONS_KEY, preferences.showHierarchyIcons);
EditorPrefs.SetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, preferences.setTextureImporterSettings);
EditorPrefs.SetString(TEXTURE_SETTINGS_REFERENCE_KEY, preferences.textureSettingsReference);
EditorPrefs.SetBool(AUTO_RELOAD_SCENESKELETONS_KEY, preferences.autoReloadSceneSkeletons);
EditorPrefs.SetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, preferences.mecanimEventIncludeFolderName);
EditorPrefs.SetBool(ATLASTXT_WARNING_KEY, preferences.atlasTxtImportWarning);
EditorPrefs.SetBool(TEXTUREIMPORTER_WARNING_KEY, preferences.textureImporterWarning);
EditorPrefs.SetBool(COMPONENTMATERIAL_WARNING_KEY, preferences.componentMaterialWarning);
EditorPrefs.SetBool(TIMELINE_USE_BLEND_DURATION_KEY, preferences.timelineUseBlendDuration);
EditorPrefs.SetFloat(SCENE_ICONS_SCALE_KEY, preferences.handleScale);
}
#endif
#if !NEW_PREFERENCES_SETTINGS_PROVIDER
public static void HandlePreferencesGUI () {
if (!preferencesLoaded)
Load();
EditorGUI.BeginChangeCheck();
showHierarchyIcons = EditorGUILayout.Toggle(new GUIContent("Show Hierarchy Icons", "Show relevant icons on GameObjects with Spine Components on them. Disable this if you have large, complex scenes."), showHierarchyIcons);
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetBool(SHOW_HIERARCHY_ICONS_KEY, showHierarchyIcons);
#if NEWPLAYMODECALLBACKS
HierarchyHandler.IconsOnPlaymodeStateChanged(PlayModeStateChange.EnteredEditMode);
#else
HierarchyHandler.IconsOnPlaymodeStateChanged();
#endif
}
BoolPrefsField(ref autoReloadSceneSkeletons, AUTO_RELOAD_SCENESKELETONS_KEY, new GUIContent("Auto-reload scene components", "Reloads Skeleton components in the scene whenever their SkeletonDataAsset is modified. This makes it so changes in the SkeletonDataAsset inspector are immediately reflected. This may be slow when your scenes have large numbers of SkeletonRenderers or SkeletonGraphic."));
EditorGUILayout.Separator();
EditorGUILayout.LabelField("Auto-Import Settings", EditorStyles.boldLabel);
{
SpineEditorUtilities.FloatPrefsField(ref defaultMix, DEFAULT_MIX_KEY, new GUIContent("Default Mix", "The Default Mix Duration for newly imported SkeletonDataAssets."), min: 0);
SpineEditorUtilities.FloatPrefsField(ref defaultScale, DEFAULT_SCALE_KEY, new GUIContent("Default SkeletonData Scale", "The Default skeleton import scale for newly imported SkeletonDataAssets."), min: 0.0000001f);
EditorGUI.BeginChangeCheck();
var shader = (EditorGUILayout.ObjectField("Default Shader", Shader.Find(defaultShader), typeof(Shader), false) as Shader);
defaultShader = shader != null ? shader.name : SpinePreferences.DEFAULT_DEFAULT_SHADER;
if (EditorGUI.EndChangeCheck())
EditorPrefs.SetString(DEFAULT_SHADER_KEY, defaultShader);
SpineEditorUtilities.BoolPrefsField(ref setTextureImporterSettings, SET_TEXTUREIMPORTER_SETTINGS_KEY, new GUIContent("Apply Atlas Texture Settings", "Apply the recommended settings for Texture Importers."));
SpineEditorUtilities.Texture2DPrefsField(ref textureSettingsReference, TEXTURE_SETTINGS_REFERENCE_KEY, new GUIContent("Atlas Texture Reference Settings", "Apply the selected reference texture import settings at newly imported atlas textures. When exporting atlas textures from Spine with \"Premultiply alpha\" enabled (the default), you can leave it at \"PMAPresetTemplate\". If you have disabled \"Premultiply alpha\", set it to \"StraightAlphaPresetTemplate\". You can also create your own reference texture asset and assign it here."));
if (string.IsNullOrEmpty(textureSettingsReference)) {
var pmaTextureSettingsReferenceGUIDS = AssetDatabase.FindAssets("PMAPresetTemplate");
if (pmaTextureSettingsReferenceGUIDS.Length > 0) {
textureSettingsReference = AssetDatabase.GUIDToAssetPath(pmaTextureSettingsReferenceGUIDS[0]);
EditorPrefs.SetString(TEXTURE_SETTINGS_REFERENCE_KEY, textureSettingsReference);
}
}
SpineEditorUtilities.MaterialPrefsField(ref blendModeMaterialAdditive, BLEND_MODE_MATERIAL_ADDITIVE_KEY, new GUIContent("Additive Material", "Additive blend mode Material template."));
if (string.IsNullOrEmpty(blendModeMaterialAdditive)) {
var blendModeMaterialAdditiveGUIDS = AssetDatabase.FindAssets(DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL);
if (blendModeMaterialAdditiveGUIDS.Length > 0) {
blendModeMaterialAdditive = AssetDatabase.GUIDToAssetPath(blendModeMaterialAdditiveGUIDS[0]);
}
}
SpineEditorUtilities.MaterialPrefsField(ref blendModeMaterialMultiply, BLEND_MODE_MATERIAL_MULTIPLY_KEY, new GUIContent("Multiply Material", "Multiply blend mode Material template."));
if (string.IsNullOrEmpty(blendModeMaterialMultiply)) {
var blendModeMaterialMultiplyGUIDS = AssetDatabase.FindAssets(DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL);
if (blendModeMaterialMultiplyGUIDS.Length > 0) {
blendModeMaterialMultiply = AssetDatabase.GUIDToAssetPath(blendModeMaterialMultiplyGUIDS[0]);
}
}
SpineEditorUtilities.MaterialPrefsField(ref blendModeMaterialScreen, BLEND_MODE_MATERIAL_SCREEN_KEY, new GUIContent("Screen Material", "Screen blend mode Material template."));
if (string.IsNullOrEmpty(blendModeMaterialScreen)) {
var blendModeMaterialScreenGUIDS = AssetDatabase.FindAssets(DEFAULT_BLEND_MODE_SCREEN_MATERIAL);
if (blendModeMaterialScreenGUIDS.Length > 0) {
blendModeMaterialScreen = AssetDatabase.GUIDToAssetPath(blendModeMaterialScreenGUIDS[0]);
}
}
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Warnings", EditorStyles.boldLabel);
{
SpineEditorUtilities.BoolPrefsField(ref atlasTxtImportWarning, ATLASTXT_WARNING_KEY, new GUIContent("Atlas Extension Warning", "Log a warning and recommendation whenever a `.atlas` file is found."));
SpineEditorUtilities.BoolPrefsField(ref textureImporterWarning, TEXTUREIMPORTER_WARNING_KEY, new GUIContent("Texture Settings Warning", "Log a warning and recommendation whenever Texture Import Settings are detected that could lead to undesired effects, e.g. white border artifacts."));
SpineEditorUtilities.BoolPrefsField(ref componentMaterialWarning, COMPONENTMATERIAL_WARNING_KEY, new GUIContent("Component & Material Warning", "Log a warning and recommendation whenever Component and Material settings are not compatible."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Editor Instantiation", EditorStyles.boldLabel);
{
EditorGUI.BeginChangeCheck();
defaultZSpacing = EditorGUILayout.Slider("Default Slot Z-Spacing", defaultZSpacing, -0.1f, 0f);
if (EditorGUI.EndChangeCheck())
EditorPrefs.SetFloat(DEFAULT_ZSPACING_KEY, defaultZSpacing);
SpineEditorUtilities.BoolPrefsField(ref defaultInstantiateLoop, DEFAULT_INSTANTIATE_LOOP_KEY, new GUIContent("Default Loop", "Spawn Spine GameObjects with loop enabled."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mecanim Bake Settings", EditorStyles.boldLabel);
{
SpineEditorUtilities.BoolPrefsField(ref mecanimEventIncludeFolderName, MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, new GUIContent("Include Folder Name in Event", "When enabled, Mecanim events will call methods named 'FolderNameEventName', when disabled it will call 'EventName'."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Handles and Gizmos", EditorStyles.boldLabel);
{
EditorGUI.BeginChangeCheck();
handleScale = EditorGUILayout.Slider("Editor Bone Scale", handleScale, 0.01f, 2f);
handleScale = Mathf.Max(0.01f, handleScale);
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetFloat(SCENE_ICONS_SCALE_KEY, handleScale);
SceneView.RepaintAll();
}
}
#if SPINE_TK2D_DEFINE
bool isTK2DDefineSet = true;
#else
bool isTK2DDefineSet = false;
#endif
bool isTK2DAllowed = SpineTK2DEditorUtility.IsTK2DAllowed;
if (SpineTK2DEditorUtility.IsTK2DInstalled() || isTK2DDefineSet) {
GUILayout.Space(20);
EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel);
using (new GUILayout.HorizontalScope()) {
EditorGUILayout.PrefixLabel("Define TK2D");
if (isTK2DAllowed && GUILayout.Button("Enable", GUILayout.Width(64)))
SpineTK2DEditorUtility.EnableTK2D();
if (GUILayout.Button("Disable", GUILayout.Width(64)))
SpineTK2DEditorUtility.DisableTK2D();
}
#if !SPINE_TK2D_DEFINE
if (!isTK2DAllowed) {
EditorGUILayout.LabelField("To allow TK2D support, please modify line 67 in", EditorStyles.boldLabel);
EditorGUILayout.LabelField("Spine/Editor/spine-unity/Editor/Util./BuildSettings.cs", EditorStyles.boldLabel);
}
#endif
}
GUILayout.Space(20);
EditorGUILayout.LabelField("Timeline Extension", EditorStyles.boldLabel);
{
SpineEditorUtilities.BoolPrefsField(ref timelineUseBlendDuration, TIMELINE_USE_BLEND_DURATION_KEY, new GUIContent("Use Blend Duration", "When enabled, MixDuration will be synced with timeline clip transition duration 'Ease In Duration'."));
}
}
#endif // !NEW_PREFERENCES_SETTINGS_PROVIDER
}
static void BoolPrefsField (ref bool currentValue, string editorPrefsKey, GUIContent label) {
EditorGUI.BeginChangeCheck();
currentValue = EditorGUILayout.Toggle(label, currentValue);
if (EditorGUI.EndChangeCheck())
EditorPrefs.SetBool(editorPrefsKey, currentValue);
}
static void FloatPrefsField (ref float currentValue, string editorPrefsKey, GUIContent label, float min = float.NegativeInfinity, float max = float.PositiveInfinity) {
EditorGUI.BeginChangeCheck();
currentValue = EditorGUILayout.DelayedFloatField(label, currentValue);
if (EditorGUI.EndChangeCheck()) {
currentValue = Mathf.Clamp(currentValue, min, max);
EditorPrefs.SetFloat(editorPrefsKey, currentValue);
}
}
static void Texture2DPrefsField (ref string currentValue, string editorPrefsKey, GUIContent label) {
EditorGUI.BeginChangeCheck();
EditorGUIUtility.wideMode = true;
var texture = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<Texture2D>(currentValue), typeof(Object), false) as Texture2D);
currentValue = texture != null ? AssetDatabase.GetAssetPath(texture) : "";
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetString(editorPrefsKey, currentValue);
}
}
static void MaterialPrefsField (ref string currentValue, string editorPrefsKey, GUIContent label) {
EditorGUI.BeginChangeCheck();
EditorGUIUtility.wideMode = true;
var material = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<Material>(currentValue), typeof(Object), false) as Material);
currentValue = material != null ? AssetDatabase.GetAssetPath(material) : "";
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetString(editorPrefsKey, currentValue);
}
}
public static void FloatPropertyField (SerializedProperty property, GUIContent label, float min = float.NegativeInfinity, float max = float.PositiveInfinity) {
EditorGUI.BeginChangeCheck();
property.floatValue = EditorGUILayout.DelayedFloatField(label, property.floatValue);
if (EditorGUI.EndChangeCheck()) {
property.floatValue = Mathf.Clamp(property.floatValue, min, max);
}
}
public static void ShaderPropertyField (SerializedProperty property, GUIContent label, string fallbackShaderName) {
var shader = (EditorGUILayout.ObjectField(label, Shader.Find(property.stringValue), typeof(Shader), false) as Shader);
property.stringValue = shader != null ? shader.name : fallbackShaderName;
}
public static void MaterialPropertyField (SerializedProperty property, GUIContent label) {
var material = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<Material>(property.stringValue), typeof(Material), false) as Material);
property.stringValue = material ? AssetDatabase.GetAssetPath(material) : "";
}
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static void PresetAssetPropertyField (SerializedProperty property, GUIContent label) {
var texturePreset = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<UnityEditor.Presets.Preset>(property.stringValue), typeof(UnityEditor.Presets.Preset), false) as UnityEditor.Presets.Preset);
bool isTexturePreset = texturePreset != null && texturePreset.GetTargetTypeName() == "TextureImporter";
property.stringValue = isTexturePreset ? AssetDatabase.GetAssetPath(texturePreset) : "";
}
#endif
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
#if UNITY_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public partial class SpineEditorUtilities {
#if NEW_PREFERENCES_SETTINGS_PROVIDER
static class SpineSettingsProviderRegistration {
[SettingsProvider]
public static SettingsProvider CreateSpineSettingsProvider () {
var provider = new SettingsProvider("Spine", SettingsScope.User) {
label = "Spine",
guiHandler = (searchContext) => {
var settings = SpinePreferences.GetOrCreateSettings();
var serializedSettings = new SerializedObject(settings);
SpinePreferences.HandlePreferencesGUI(serializedSettings);
if (serializedSettings.ApplyModifiedProperties())
OldPreferences.SaveToEditorPrefs(settings);
},
// Populate the search keywords to enable smart search filtering and label highlighting:
keywords = new HashSet<string>(new[] { "Spine", "Preferences", "Skeleton", "Default", "Mix", "Duration" })
};
return provider;
}
}
#else
// Preferences entry point
[PreferenceItem("Spine")]
static void PreferencesGUI () {
Preferences.HandlePreferencesGUI();
}
#endif
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static SpinePreferences Preferences {
get {
return SpinePreferences.GetOrCreateSettings();
}
}
#endif
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static class OldPreferences {
#else
public static class Preferences {
#endif
const string DEFAULT_SCALE_KEY = "SPINE_DEFAULT_SCALE";
public static float defaultScale = SpinePreferences.DEFAULT_DEFAULT_SCALE;
const string DEFAULT_MIX_KEY = "SPINE_DEFAULT_MIX";
public static float defaultMix = SpinePreferences.DEFAULT_DEFAULT_MIX;
const string DEFAULT_SHADER_KEY = "SPINE_DEFAULT_SHADER";
public static string defaultShader = SpinePreferences.DEFAULT_DEFAULT_SHADER;
public static string DefaultShader {
get { return !string.IsNullOrEmpty(defaultShader) ? defaultShader : SpinePreferences.DEFAULT_DEFAULT_SHADER; }
set { defaultShader = value; }
}
const string DEFAULT_ZSPACING_KEY = "SPINE_DEFAULT_ZSPACING";
public static float defaultZSpacing = SpinePreferences.DEFAULT_DEFAULT_ZSPACING;
const string DEFAULT_INSTANTIATE_LOOP_KEY = "SPINE_DEFAULT_INSTANTIATE_LOOP";
public static bool defaultInstantiateLoop = SpinePreferences.DEFAULT_DEFAULT_INSTANTIATE_LOOP;
const string SHOW_HIERARCHY_ICONS_KEY = "SPINE_SHOW_HIERARCHY_ICONS";
public static bool showHierarchyIcons = SpinePreferences.DEFAULT_SHOW_HIERARCHY_ICONS;
const string SET_TEXTUREIMPORTER_SETTINGS_KEY = "SPINE_SET_TEXTUREIMPORTER_SETTINGS";
public static bool setTextureImporterSettings = SpinePreferences.DEFAULT_SET_TEXTUREIMPORTER_SETTINGS;
const string TEXTURE_SETTINGS_REFERENCE_KEY = "SPINE_TEXTURE_SETTINGS_REFERENCE";
public static string textureSettingsReference = SpinePreferences.DEFAULT_TEXTURE_SETTINGS_REFERENCE;
public static bool UsesPMAWorkflow {
get {
return SpinePreferences.IsPMAWorkflow(textureSettingsReference);
}
}
const string BLEND_MODE_MATERIAL_MULTIPLY_KEY = "SPINE_BLENDMODE_MATERIAL_MULTIPLY";
const string BLEND_MODE_MATERIAL_SCREEN_KEY = "SPINE_BLENDMODE_MATERIAL_SCREEN";
const string BLEND_MODE_MATERIAL_ADDITIVE_KEY = "SPINE_BLENDMODE_MATERIAL_ADDITIVE";
public static string blendModeMaterialMultiply = "";
public static string blendModeMaterialScreen = "";
public static string blendModeMaterialAdditive = "";
public const string DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL = SpinePreferences.DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL;
public const string DEFAULT_BLEND_MODE_SCREEN_MATERIAL = SpinePreferences.DEFAULT_BLEND_MODE_SCREEN_MATERIAL;
public const string DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL = SpinePreferences.DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL;
public static Material BlendModeMaterialMultiply {
get { return AssetDatabase.LoadAssetAtPath<Material>(blendModeMaterialMultiply); }
}
public static Material BlendModeMaterialScreen {
get { return AssetDatabase.LoadAssetAtPath<Material>(blendModeMaterialScreen); }
}
public static Material BlendModeMaterialAdditive {
get { return AssetDatabase.LoadAssetAtPath<Material>(blendModeMaterialAdditive); }
}
const string ATLASTXT_WARNING_KEY = "SPINE_ATLASTXT_WARNING";
public static bool atlasTxtImportWarning = SpinePreferences.DEFAULT_ATLASTXT_WARNING;
const string TEXTUREIMPORTER_WARNING_KEY = "SPINE_TEXTUREIMPORTER_WARNING";
public static bool textureImporterWarning = SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING;
const string COMPONENTMATERIAL_WARNING_KEY = "SPINE_COMPONENTMATERIAL_WARNING";
public static bool componentMaterialWarning = SpinePreferences.DEFAULT_COMPONENTMATERIAL_WARNING;
public const float DEFAULT_MIPMAPBIAS = SpinePreferences.DEFAULT_MIPMAPBIAS;
public const string SCENE_ICONS_SCALE_KEY = "SPINE_SCENE_ICONS_SCALE";
public static float handleScale = SpinePreferences.DEFAULT_SCENE_ICONS_SCALE;
const string AUTO_RELOAD_SCENESKELETONS_KEY = "SPINE_AUTO_RELOAD_SCENESKELETONS";
public static bool autoReloadSceneSkeletons = SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS;
const string MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY = "SPINE_MECANIM_EVENT_INCLUDE_FOLDERNAME";
public static bool mecanimEventIncludeFolderName = SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME;
const string TIMELINE_USE_BLEND_DURATION_KEY = "SPINE_TIMELINE_USE_BLEND_DURATION_KEY";
public static bool timelineUseBlendDuration = SpinePreferences.DEFAULT_TIMELINE_USE_BLEND_DURATION;
static bool preferencesLoaded = false;
public static void Load () {
if (preferencesLoaded)
return;
defaultMix = EditorPrefs.GetFloat(DEFAULT_MIX_KEY, SpinePreferences.DEFAULT_DEFAULT_MIX);
defaultScale = EditorPrefs.GetFloat(DEFAULT_SCALE_KEY, SpinePreferences.DEFAULT_DEFAULT_SCALE);
defaultZSpacing = EditorPrefs.GetFloat(DEFAULT_ZSPACING_KEY, SpinePreferences.DEFAULT_DEFAULT_ZSPACING);
defaultShader = EditorPrefs.GetString(DEFAULT_SHADER_KEY, SpinePreferences.DEFAULT_DEFAULT_SHADER);
showHierarchyIcons = EditorPrefs.GetBool(SHOW_HIERARCHY_ICONS_KEY, SpinePreferences.DEFAULT_SHOW_HIERARCHY_ICONS);
setTextureImporterSettings = EditorPrefs.GetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, SpinePreferences.DEFAULT_SET_TEXTUREIMPORTER_SETTINGS);
textureSettingsReference = EditorPrefs.GetString(TEXTURE_SETTINGS_REFERENCE_KEY, SpinePreferences.DEFAULT_TEXTURE_SETTINGS_REFERENCE);
blendModeMaterialMultiply = EditorPrefs.GetString(BLEND_MODE_MATERIAL_MULTIPLY_KEY, "");
blendModeMaterialScreen = EditorPrefs.GetString(BLEND_MODE_MATERIAL_SCREEN_KEY, "");
blendModeMaterialAdditive = EditorPrefs.GetString(BLEND_MODE_MATERIAL_ADDITIVE_KEY, "");
autoReloadSceneSkeletons = EditorPrefs.GetBool(AUTO_RELOAD_SCENESKELETONS_KEY, SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS);
mecanimEventIncludeFolderName = EditorPrefs.GetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME);
atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, SpinePreferences.DEFAULT_ATLASTXT_WARNING);
textureImporterWarning = EditorPrefs.GetBool(TEXTUREIMPORTER_WARNING_KEY, SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING);
componentMaterialWarning = EditorPrefs.GetBool(COMPONENTMATERIAL_WARNING_KEY, SpinePreferences.DEFAULT_COMPONENTMATERIAL_WARNING);
timelineUseBlendDuration = EditorPrefs.GetBool(TIMELINE_USE_BLEND_DURATION_KEY, SpinePreferences.DEFAULT_TIMELINE_USE_BLEND_DURATION);
handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, SpinePreferences.DEFAULT_SCENE_ICONS_SCALE);
preferencesLoaded = true;
}
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static void CopyOldToNewPreferences (ref SpinePreferences newPreferences) {
newPreferences.defaultMix = EditorPrefs.GetFloat(DEFAULT_MIX_KEY, SpinePreferences.DEFAULT_DEFAULT_MIX);
newPreferences.defaultScale = EditorPrefs.GetFloat(DEFAULT_SCALE_KEY, SpinePreferences.DEFAULT_DEFAULT_SCALE);
newPreferences.defaultZSpacing = EditorPrefs.GetFloat(DEFAULT_ZSPACING_KEY, SpinePreferences.DEFAULT_DEFAULT_ZSPACING);
newPreferences.defaultShader = EditorPrefs.GetString(DEFAULT_SHADER_KEY, SpinePreferences.DEFAULT_DEFAULT_SHADER);
newPreferences.showHierarchyIcons = EditorPrefs.GetBool(SHOW_HIERARCHY_ICONS_KEY, SpinePreferences.DEFAULT_SHOW_HIERARCHY_ICONS);
newPreferences.setTextureImporterSettings = EditorPrefs.GetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, SpinePreferences.DEFAULT_SET_TEXTUREIMPORTER_SETTINGS);
newPreferences.textureSettingsReference = EditorPrefs.GetString(TEXTURE_SETTINGS_REFERENCE_KEY, SpinePreferences.DEFAULT_TEXTURE_SETTINGS_REFERENCE);
newPreferences.autoReloadSceneSkeletons = EditorPrefs.GetBool(AUTO_RELOAD_SCENESKELETONS_KEY, SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS);
newPreferences.mecanimEventIncludeFolderName = EditorPrefs.GetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME);
newPreferences.atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, SpinePreferences.DEFAULT_ATLASTXT_WARNING);
newPreferences.textureImporterWarning = EditorPrefs.GetBool(TEXTUREIMPORTER_WARNING_KEY, SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING);
newPreferences.componentMaterialWarning = EditorPrefs.GetBool(COMPONENTMATERIAL_WARNING_KEY, SpinePreferences.DEFAULT_COMPONENTMATERIAL_WARNING);
newPreferences.timelineUseBlendDuration = EditorPrefs.GetBool(TIMELINE_USE_BLEND_DURATION_KEY, SpinePreferences.DEFAULT_TIMELINE_USE_BLEND_DURATION);
newPreferences.handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, SpinePreferences.DEFAULT_SCENE_ICONS_SCALE);
}
public static void SaveToEditorPrefs (SpinePreferences preferences) {
EditorPrefs.SetFloat(DEFAULT_MIX_KEY, preferences.defaultMix);
EditorPrefs.SetFloat(DEFAULT_SCALE_KEY, preferences.defaultScale);
EditorPrefs.SetFloat(DEFAULT_ZSPACING_KEY, preferences.defaultZSpacing);
EditorPrefs.SetString(DEFAULT_SHADER_KEY, preferences.defaultShader);
EditorPrefs.SetBool(SHOW_HIERARCHY_ICONS_KEY, preferences.showHierarchyIcons);
EditorPrefs.SetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, preferences.setTextureImporterSettings);
EditorPrefs.SetString(TEXTURE_SETTINGS_REFERENCE_KEY, preferences.textureSettingsReference);
EditorPrefs.SetBool(AUTO_RELOAD_SCENESKELETONS_KEY, preferences.autoReloadSceneSkeletons);
EditorPrefs.SetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, preferences.mecanimEventIncludeFolderName);
EditorPrefs.SetBool(ATLASTXT_WARNING_KEY, preferences.atlasTxtImportWarning);
EditorPrefs.SetBool(TEXTUREIMPORTER_WARNING_KEY, preferences.textureImporterWarning);
EditorPrefs.SetBool(COMPONENTMATERIAL_WARNING_KEY, preferences.componentMaterialWarning);
EditorPrefs.SetBool(TIMELINE_USE_BLEND_DURATION_KEY, preferences.timelineUseBlendDuration);
EditorPrefs.SetFloat(SCENE_ICONS_SCALE_KEY, preferences.handleScale);
}
#endif
#if !NEW_PREFERENCES_SETTINGS_PROVIDER
public static void HandlePreferencesGUI () {
if (!preferencesLoaded)
Load();
EditorGUI.BeginChangeCheck();
showHierarchyIcons = EditorGUILayout.Toggle(new GUIContent("Show Hierarchy Icons", "Show relevant icons on GameObjects with Spine Components on them. Disable this if you have large, complex scenes."), showHierarchyIcons);
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetBool(SHOW_HIERARCHY_ICONS_KEY, showHierarchyIcons);
#if NEWPLAYMODECALLBACKS
HierarchyHandler.IconsOnPlaymodeStateChanged(PlayModeStateChange.EnteredEditMode);
#else
HierarchyHandler.IconsOnPlaymodeStateChanged();
#endif
}
BoolPrefsField(ref autoReloadSceneSkeletons, AUTO_RELOAD_SCENESKELETONS_KEY, new GUIContent("Auto-reload scene components", "Reloads Skeleton components in the scene whenever their SkeletonDataAsset is modified. This makes it so changes in the SkeletonDataAsset inspector are immediately reflected. This may be slow when your scenes have large numbers of SkeletonRenderers or SkeletonGraphic."));
EditorGUILayout.Separator();
EditorGUILayout.LabelField("Auto-Import Settings", EditorStyles.boldLabel);
{
SpineEditorUtilities.FloatPrefsField(ref defaultMix, DEFAULT_MIX_KEY, new GUIContent("Default Mix", "The Default Mix Duration for newly imported SkeletonDataAssets."), min: 0);
SpineEditorUtilities.FloatPrefsField(ref defaultScale, DEFAULT_SCALE_KEY, new GUIContent("Default SkeletonData Scale", "The Default skeleton import scale for newly imported SkeletonDataAssets."), min: 0.0000001f);
EditorGUI.BeginChangeCheck();
var shader = (EditorGUILayout.ObjectField("Default Shader", Shader.Find(defaultShader), typeof(Shader), false) as Shader);
defaultShader = shader != null ? shader.name : SpinePreferences.DEFAULT_DEFAULT_SHADER;
if (EditorGUI.EndChangeCheck())
EditorPrefs.SetString(DEFAULT_SHADER_KEY, defaultShader);
SpineEditorUtilities.BoolPrefsField(ref setTextureImporterSettings, SET_TEXTUREIMPORTER_SETTINGS_KEY, new GUIContent("Apply Atlas Texture Settings", "Apply the recommended settings for Texture Importers."));
SpineEditorUtilities.Texture2DPrefsField(ref textureSettingsReference, TEXTURE_SETTINGS_REFERENCE_KEY, new GUIContent("Atlas Texture Reference Settings", "Apply the selected reference texture import settings at newly imported atlas textures. When exporting atlas textures from Spine with \"Premultiply alpha\" enabled (the default), you can leave it at \"PMAPresetTemplate\". If you have disabled \"Premultiply alpha\", set it to \"StraightAlphaPresetTemplate\". You can also create your own reference texture asset and assign it here."));
if (string.IsNullOrEmpty(textureSettingsReference)) {
var pmaTextureSettingsReferenceGUIDS = AssetDatabase.FindAssets("PMAPresetTemplate");
if (pmaTextureSettingsReferenceGUIDS.Length > 0) {
textureSettingsReference = AssetDatabase.GUIDToAssetPath(pmaTextureSettingsReferenceGUIDS[0]);
EditorPrefs.SetString(TEXTURE_SETTINGS_REFERENCE_KEY, textureSettingsReference);
}
}
SpineEditorUtilities.MaterialPrefsField(ref blendModeMaterialAdditive, BLEND_MODE_MATERIAL_ADDITIVE_KEY, new GUIContent("Additive Material", "Additive blend mode Material template."));
if (string.IsNullOrEmpty(blendModeMaterialAdditive)) {
var blendModeMaterialAdditiveGUIDS = AssetDatabase.FindAssets(DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL);
if (blendModeMaterialAdditiveGUIDS.Length > 0) {
blendModeMaterialAdditive = AssetDatabase.GUIDToAssetPath(blendModeMaterialAdditiveGUIDS[0]);
}
}
SpineEditorUtilities.MaterialPrefsField(ref blendModeMaterialMultiply, BLEND_MODE_MATERIAL_MULTIPLY_KEY, new GUIContent("Multiply Material", "Multiply blend mode Material template."));
if (string.IsNullOrEmpty(blendModeMaterialMultiply)) {
var blendModeMaterialMultiplyGUIDS = AssetDatabase.FindAssets(DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL);
if (blendModeMaterialMultiplyGUIDS.Length > 0) {
blendModeMaterialMultiply = AssetDatabase.GUIDToAssetPath(blendModeMaterialMultiplyGUIDS[0]);
}
}
SpineEditorUtilities.MaterialPrefsField(ref blendModeMaterialScreen, BLEND_MODE_MATERIAL_SCREEN_KEY, new GUIContent("Screen Material", "Screen blend mode Material template."));
if (string.IsNullOrEmpty(blendModeMaterialScreen)) {
var blendModeMaterialScreenGUIDS = AssetDatabase.FindAssets(DEFAULT_BLEND_MODE_SCREEN_MATERIAL);
if (blendModeMaterialScreenGUIDS.Length > 0) {
blendModeMaterialScreen = AssetDatabase.GUIDToAssetPath(blendModeMaterialScreenGUIDS[0]);
}
}
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Warnings", EditorStyles.boldLabel);
{
SpineEditorUtilities.BoolPrefsField(ref atlasTxtImportWarning, ATLASTXT_WARNING_KEY, new GUIContent("Atlas Extension Warning", "Log a warning and recommendation whenever a `.atlas` file is found."));
SpineEditorUtilities.BoolPrefsField(ref textureImporterWarning, TEXTUREIMPORTER_WARNING_KEY, new GUIContent("Texture Settings Warning", "Log a warning and recommendation whenever Texture Import Settings are detected that could lead to undesired effects, e.g. white border artifacts."));
SpineEditorUtilities.BoolPrefsField(ref componentMaterialWarning, COMPONENTMATERIAL_WARNING_KEY, new GUIContent("Component & Material Warning", "Log a warning and recommendation whenever Component and Material settings are not compatible."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Editor Instantiation", EditorStyles.boldLabel);
{
EditorGUI.BeginChangeCheck();
defaultZSpacing = EditorGUILayout.Slider("Default Slot Z-Spacing", defaultZSpacing, -0.1f, 0f);
if (EditorGUI.EndChangeCheck())
EditorPrefs.SetFloat(DEFAULT_ZSPACING_KEY, defaultZSpacing);
SpineEditorUtilities.BoolPrefsField(ref defaultInstantiateLoop, DEFAULT_INSTANTIATE_LOOP_KEY, new GUIContent("Default Loop", "Spawn Spine GameObjects with loop enabled."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mecanim Bake Settings", EditorStyles.boldLabel);
{
SpineEditorUtilities.BoolPrefsField(ref mecanimEventIncludeFolderName, MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, new GUIContent("Include Folder Name in Event", "When enabled, Mecanim events will call methods named 'FolderNameEventName', when disabled it will call 'EventName'."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Handles and Gizmos", EditorStyles.boldLabel);
{
EditorGUI.BeginChangeCheck();
handleScale = EditorGUILayout.Slider("Editor Bone Scale", handleScale, 0.01f, 2f);
handleScale = Mathf.Max(0.01f, handleScale);
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetFloat(SCENE_ICONS_SCALE_KEY, handleScale);
SceneView.RepaintAll();
}
}
#if SPINE_TK2D_DEFINE
bool isTK2DDefineSet = true;
#else
bool isTK2DDefineSet = false;
#endif
bool isTK2DAllowed = SpineTK2DEditorUtility.IsTK2DAllowed;
if (SpineTK2DEditorUtility.IsTK2DInstalled() || isTK2DDefineSet) {
GUILayout.Space(20);
EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel);
using (new GUILayout.HorizontalScope()) {
EditorGUILayout.PrefixLabel("Define TK2D");
if (isTK2DAllowed && GUILayout.Button("Enable", GUILayout.Width(64)))
SpineTK2DEditorUtility.EnableTK2D();
if (GUILayout.Button("Disable", GUILayout.Width(64)))
SpineTK2DEditorUtility.DisableTK2D();
}
#if !SPINE_TK2D_DEFINE
if (!isTK2DAllowed) {
EditorGUILayout.LabelField("To allow TK2D support, please modify line 67 in", EditorStyles.boldLabel);
EditorGUILayout.LabelField("Spine/Editor/spine-unity/Editor/Util./BuildSettings.cs", EditorStyles.boldLabel);
}
#endif
}
GUILayout.Space(20);
EditorGUILayout.LabelField("Timeline Extension", EditorStyles.boldLabel);
{
SpineEditorUtilities.BoolPrefsField(ref timelineUseBlendDuration, TIMELINE_USE_BLEND_DURATION_KEY, new GUIContent("Use Blend Duration", "When enabled, MixDuration will be synced with timeline clip transition duration 'Ease In Duration'."));
}
}
#endif // !NEW_PREFERENCES_SETTINGS_PROVIDER
}
static void BoolPrefsField (ref bool currentValue, string editorPrefsKey, GUIContent label) {
EditorGUI.BeginChangeCheck();
currentValue = EditorGUILayout.Toggle(label, currentValue);
if (EditorGUI.EndChangeCheck())
EditorPrefs.SetBool(editorPrefsKey, currentValue);
}
static void FloatPrefsField (ref float currentValue, string editorPrefsKey, GUIContent label, float min = float.NegativeInfinity, float max = float.PositiveInfinity) {
EditorGUI.BeginChangeCheck();
currentValue = EditorGUILayout.DelayedFloatField(label, currentValue);
if (EditorGUI.EndChangeCheck()) {
currentValue = Mathf.Clamp(currentValue, min, max);
EditorPrefs.SetFloat(editorPrefsKey, currentValue);
}
}
static void Texture2DPrefsField (ref string currentValue, string editorPrefsKey, GUIContent label) {
EditorGUI.BeginChangeCheck();
EditorGUIUtility.wideMode = true;
var texture = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<Texture2D>(currentValue), typeof(Object), false) as Texture2D);
currentValue = texture != null ? AssetDatabase.GetAssetPath(texture) : "";
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetString(editorPrefsKey, currentValue);
}
}
static void MaterialPrefsField (ref string currentValue, string editorPrefsKey, GUIContent label) {
EditorGUI.BeginChangeCheck();
EditorGUIUtility.wideMode = true;
var material = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<Material>(currentValue), typeof(Object), false) as Material);
currentValue = material != null ? AssetDatabase.GetAssetPath(material) : "";
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetString(editorPrefsKey, currentValue);
}
}
public static void FloatPropertyField (SerializedProperty property, GUIContent label, float min = float.NegativeInfinity, float max = float.PositiveInfinity) {
EditorGUI.BeginChangeCheck();
property.floatValue = EditorGUILayout.DelayedFloatField(label, property.floatValue);
if (EditorGUI.EndChangeCheck()) {
property.floatValue = Mathf.Clamp(property.floatValue, min, max);
}
}
public static void ShaderPropertyField (SerializedProperty property, GUIContent label, string fallbackShaderName) {
var shader = (EditorGUILayout.ObjectField(label, Shader.Find(property.stringValue), typeof(Shader), false) as Shader);
property.stringValue = shader != null ? shader.name : fallbackShaderName;
}
public static void MaterialPropertyField (SerializedProperty property, GUIContent label) {
var material = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<Material>(property.stringValue), typeof(Material), false) as Material);
property.stringValue = material ? AssetDatabase.GetAssetPath(material) : "";
}
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static void PresetAssetPropertyField (SerializedProperty property, GUIContent label) {
var texturePreset = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<UnityEditor.Presets.Preset>(property.stringValue), typeof(UnityEditor.Presets.Preset), false) as UnityEditor.Presets.Preset);
bool isTexturePreset = texturePreset != null && texturePreset.GetTargetTypeName() == "TextureImporter";
property.stringValue = isTexturePreset ? AssetDatabase.GetAssetPath(texturePreset) : "";
}
#endif
}
}

View File

@@ -1,228 +1,228 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_1_OR_NEWER
#define HAS_BUILD_PROCESS_WITH_REPORT
#endif
#if UNITY_2020_2_OR_NEWER
#define HAS_ON_POSTPROCESS_PREFAB
#endif
#if (UNITY_2020_3 && !(UNITY_2020_3_1 || UNITY_2020_3_2 || UNITY_2020_3_3 || UNITY_2020_3_4 || UNITY_2020_3_5 || UNITY_2020_3_6 || UNITY_2020_3_7 || UNITY_2020_3_8 || UNITY_2020_3_9 || UNITY_2020_3_10 || UNITY_2020_3_11 || UNITY_2020_3_12 || UNITY_2020_3_13 || UNITY_2020_3_14 || UNITY_2020_3_15))
#define UNITY_2020_3_16_OR_NEWER
#endif
#if (UNITY_2021_1 && !(UNITY_2021_1_1 || UNITY_2021_1_2 || UNITY_2021_1_3 || UNITY_2021_1_4 || UNITY_2021_1_5 || UNITY_2021_1_6 || UNITY_2021_1_7 || UNITY_2021_1_8 || UNITY_2021_1_9 || UNITY_2021_1_10 || UNITY_2021_1_11 || UNITY_2021_1_12 || UNITY_2021_1_13 || UNITY_2021_1_14 || UNITY_2021_1_15 || UNITY_2021_1_16))
#define UNITY_2021_1_17_OR_NEWER
#endif
#if UNITY_2020_3_16_OR_NEWER || UNITY_2021_1_17_OR_NEWER
#define HAS_SAVE_ASSET_IF_DIRTY
#endif
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;
#if HAS_BUILD_PROCESS_WITH_REPORT
using UnityEditor.Build.Reporting;
#endif
namespace Spine.Unity.Editor {
public class SpineBuildProcessor {
internal static bool isBuilding = false;
#if HAS_ON_POSTPROCESS_PREFAB
static List<string> prefabsToRestore = new List<string>();
#endif
static Dictionary<string, string> spriteAtlasTexturesToRestore = new Dictionary<string, string>();
internal static void PreprocessBuild () {
isBuilding = true;
#if HAS_ON_POSTPROCESS_PREFAB
PreprocessSpinePrefabMeshes();
#endif
PreprocessSpriteAtlases();
}
internal static void PostprocessBuild () {
isBuilding = false;
#if HAS_ON_POSTPROCESS_PREFAB
PostprocessSpinePrefabMeshes();
#endif
PostprocessSpriteAtlases();
}
#if HAS_ON_POSTPROCESS_PREFAB
internal static void PreprocessSpinePrefabMeshes () {
BuildUtilities.IsInSkeletonAssetBuildPreProcessing = true;
try {
AssetDatabase.StartAssetEditing();
prefabsToRestore.Clear();
var prefabAssets = AssetDatabase.FindAssets("t:Prefab");
foreach (var asset in prefabAssets) {
string assetPath = AssetDatabase.GUIDToAssetPath(asset);
GameObject prefabGameObject = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
if (SpineEditorUtilities.CleanupSpinePrefabMesh(prefabGameObject)) {
#if HAS_SAVE_ASSET_IF_DIRTY
AssetDatabase.SaveAssetIfDirty(prefabGameObject);
#endif
prefabsToRestore.Add(assetPath);
}
EditorUtility.UnloadUnusedAssetsImmediate();
}
AssetDatabase.StopAssetEditing();
#if !HAS_SAVE_ASSET_IF_DIRTY
if (prefabAssets.Length > 0)
AssetDatabase.SaveAssets();
#endif
} finally {
BuildUtilities.IsInSkeletonAssetBuildPreProcessing = false;
}
}
internal static void PostprocessSpinePrefabMeshes () {
BuildUtilities.IsInSkeletonAssetBuildPostProcessing = true;
try {
foreach (string assetPath in prefabsToRestore) {
GameObject g = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
SpineEditorUtilities.SetupSpinePrefabMesh(g, null);
#if HAS_SAVE_ASSET_IF_DIRTY
AssetDatabase.SaveAssetIfDirty(g);
#endif
}
#if !HAS_SAVE_ASSET_IF_DIRTY
if (prefabsToRestore.Count > 0)
AssetDatabase.SaveAssets();
#endif
prefabsToRestore.Clear();
} finally {
BuildUtilities.IsInSkeletonAssetBuildPostProcessing = false;
}
}
#endif
internal static void PreprocessSpriteAtlases () {
BuildUtilities.IsInSpriteAtlasBuildPreProcessing = true;
try {
AssetDatabase.StartAssetEditing();
spriteAtlasTexturesToRestore.Clear();
var spriteAtlasAssets = AssetDatabase.FindAssets("t:SpineSpriteAtlasAsset");
foreach (var asset in spriteAtlasAssets) {
string assetPath = AssetDatabase.GUIDToAssetPath(asset);
SpineSpriteAtlasAsset atlasAsset = AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(assetPath);
if (atlasAsset && atlasAsset.materials.Length > 0) {
spriteAtlasTexturesToRestore[assetPath] = AssetDatabase.GetAssetPath(atlasAsset.materials[0].mainTexture);
atlasAsset.materials[0].mainTexture = null;
}
#if HAS_SAVE_ASSET_IF_DIRTY
AssetDatabase.SaveAssetIfDirty(atlasAsset);
#endif
EditorUtility.UnloadUnusedAssetsImmediate();
}
AssetDatabase.StopAssetEditing();
#if !HAS_SAVE_ASSET_IF_DIRTY
if (spriteAtlasAssets.Length > 0)
AssetDatabase.SaveAssets();
#endif
} finally {
BuildUtilities.IsInSpriteAtlasBuildPreProcessing = false;
}
}
internal static void PostprocessSpriteAtlases () {
BuildUtilities.IsInSpriteAtlasBuildPostProcessing = true;
try {
foreach (var pair in spriteAtlasTexturesToRestore) {
string assetPath = pair.Key;
SpineSpriteAtlasAsset atlasAsset = AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(assetPath);
if (atlasAsset && atlasAsset.materials.Length > 0) {
Texture atlasTexture = AssetDatabase.LoadAssetAtPath<Texture>(pair.Value);
atlasAsset.materials[0].mainTexture = atlasTexture;
}
#if HAS_SAVE_ASSET_IF_DIRTY
AssetDatabase.SaveAssetIfDirty(atlasAsset);
#endif
}
#if !HAS_SAVE_ASSET_IF_DIRTY
if (spriteAtlasTexturesToRestore.Count > 0)
AssetDatabase.SaveAssets();
#endif
spriteAtlasTexturesToRestore.Clear();
} finally {
BuildUtilities.IsInSpriteAtlasBuildPostProcessing = false;
}
}
}
public class SpineBuildPreprocessor :
#if HAS_BUILD_PROCESS_WITH_REPORT
IPreprocessBuildWithReport
#else
IPreprocessBuild
#endif
{
public int callbackOrder {
get { return -2000; }
}
#if HAS_BUILD_PROCESS_WITH_REPORT
void IPreprocessBuildWithReport.OnPreprocessBuild (BuildReport report) {
SpineBuildProcessor.PreprocessBuild();
}
#else
void IPreprocessBuild.OnPreprocessBuild (BuildTarget target, string path) {
SpineBuildProcessor.PreprocessBuild();
}
#endif
}
public class SpineBuildPostprocessor :
#if HAS_BUILD_PROCESS_WITH_REPORT
IPostprocessBuildWithReport
#else
IPostprocessBuild
#endif
{
public int callbackOrder {
get { return 2000; }
}
#if HAS_BUILD_PROCESS_WITH_REPORT
void IPostprocessBuildWithReport.OnPostprocessBuild (BuildReport report) {
SpineBuildProcessor.PostprocessBuild();
}
#else
void IPostprocessBuild.OnPostprocessBuild (BuildTarget target, string path) {
SpineBuildProcessor.PostprocessBuild();
}
#endif
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_1_OR_NEWER
#define HAS_BUILD_PROCESS_WITH_REPORT
#endif
#if UNITY_2020_2_OR_NEWER
#define HAS_ON_POSTPROCESS_PREFAB
#endif
#if (UNITY_2020_3 && !(UNITY_2020_3_1 || UNITY_2020_3_2 || UNITY_2020_3_3 || UNITY_2020_3_4 || UNITY_2020_3_5 || UNITY_2020_3_6 || UNITY_2020_3_7 || UNITY_2020_3_8 || UNITY_2020_3_9 || UNITY_2020_3_10 || UNITY_2020_3_11 || UNITY_2020_3_12 || UNITY_2020_3_13 || UNITY_2020_3_14 || UNITY_2020_3_15))
#define UNITY_2020_3_16_OR_NEWER
#endif
#if (UNITY_2021_1 && !(UNITY_2021_1_1 || UNITY_2021_1_2 || UNITY_2021_1_3 || UNITY_2021_1_4 || UNITY_2021_1_5 || UNITY_2021_1_6 || UNITY_2021_1_7 || UNITY_2021_1_8 || UNITY_2021_1_9 || UNITY_2021_1_10 || UNITY_2021_1_11 || UNITY_2021_1_12 || UNITY_2021_1_13 || UNITY_2021_1_14 || UNITY_2021_1_15 || UNITY_2021_1_16))
#define UNITY_2021_1_17_OR_NEWER
#endif
#if UNITY_2020_3_16_OR_NEWER || UNITY_2021_1_17_OR_NEWER
#define HAS_SAVE_ASSET_IF_DIRTY
#endif
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;
#if HAS_BUILD_PROCESS_WITH_REPORT
using UnityEditor.Build.Reporting;
#endif
namespace Spine.Unity.Editor {
public class SpineBuildProcessor {
internal static bool isBuilding = false;
#if HAS_ON_POSTPROCESS_PREFAB
static List<string> prefabsToRestore = new List<string>();
#endif
static Dictionary<string, string> spriteAtlasTexturesToRestore = new Dictionary<string, string>();
internal static void PreprocessBuild () {
isBuilding = true;
#if HAS_ON_POSTPROCESS_PREFAB
PreprocessSpinePrefabMeshes();
#endif
PreprocessSpriteAtlases();
}
internal static void PostprocessBuild () {
isBuilding = false;
#if HAS_ON_POSTPROCESS_PREFAB
PostprocessSpinePrefabMeshes();
#endif
PostprocessSpriteAtlases();
}
#if HAS_ON_POSTPROCESS_PREFAB
internal static void PreprocessSpinePrefabMeshes () {
BuildUtilities.IsInSkeletonAssetBuildPreProcessing = true;
try {
AssetDatabase.StartAssetEditing();
prefabsToRestore.Clear();
var prefabAssets = AssetDatabase.FindAssets("t:Prefab");
foreach (var asset in prefabAssets) {
string assetPath = AssetDatabase.GUIDToAssetPath(asset);
GameObject prefabGameObject = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
if (SpineEditorUtilities.CleanupSpinePrefabMesh(prefabGameObject)) {
#if HAS_SAVE_ASSET_IF_DIRTY
AssetDatabase.SaveAssetIfDirty(prefabGameObject);
#endif
prefabsToRestore.Add(assetPath);
}
EditorUtility.UnloadUnusedAssetsImmediate();
}
AssetDatabase.StopAssetEditing();
#if !HAS_SAVE_ASSET_IF_DIRTY
if (prefabAssets.Length > 0)
AssetDatabase.SaveAssets();
#endif
} finally {
BuildUtilities.IsInSkeletonAssetBuildPreProcessing = false;
}
}
internal static void PostprocessSpinePrefabMeshes () {
BuildUtilities.IsInSkeletonAssetBuildPostProcessing = true;
try {
foreach (string assetPath in prefabsToRestore) {
GameObject g = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
SpineEditorUtilities.SetupSpinePrefabMesh(g, null);
#if HAS_SAVE_ASSET_IF_DIRTY
AssetDatabase.SaveAssetIfDirty(g);
#endif
}
#if !HAS_SAVE_ASSET_IF_DIRTY
if (prefabsToRestore.Count > 0)
AssetDatabase.SaveAssets();
#endif
prefabsToRestore.Clear();
} finally {
BuildUtilities.IsInSkeletonAssetBuildPostProcessing = false;
}
}
#endif
internal static void PreprocessSpriteAtlases () {
BuildUtilities.IsInSpriteAtlasBuildPreProcessing = true;
try {
AssetDatabase.StartAssetEditing();
spriteAtlasTexturesToRestore.Clear();
var spriteAtlasAssets = AssetDatabase.FindAssets("t:SpineSpriteAtlasAsset");
foreach (var asset in spriteAtlasAssets) {
string assetPath = AssetDatabase.GUIDToAssetPath(asset);
SpineSpriteAtlasAsset atlasAsset = AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(assetPath);
if (atlasAsset && atlasAsset.materials.Length > 0) {
spriteAtlasTexturesToRestore[assetPath] = AssetDatabase.GetAssetPath(atlasAsset.materials[0].mainTexture);
atlasAsset.materials[0].mainTexture = null;
}
#if HAS_SAVE_ASSET_IF_DIRTY
AssetDatabase.SaveAssetIfDirty(atlasAsset);
#endif
EditorUtility.UnloadUnusedAssetsImmediate();
}
AssetDatabase.StopAssetEditing();
#if !HAS_SAVE_ASSET_IF_DIRTY
if (spriteAtlasAssets.Length > 0)
AssetDatabase.SaveAssets();
#endif
} finally {
BuildUtilities.IsInSpriteAtlasBuildPreProcessing = false;
}
}
internal static void PostprocessSpriteAtlases () {
BuildUtilities.IsInSpriteAtlasBuildPostProcessing = true;
try {
foreach (var pair in spriteAtlasTexturesToRestore) {
string assetPath = pair.Key;
SpineSpriteAtlasAsset atlasAsset = AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(assetPath);
if (atlasAsset && atlasAsset.materials.Length > 0) {
Texture atlasTexture = AssetDatabase.LoadAssetAtPath<Texture>(pair.Value);
atlasAsset.materials[0].mainTexture = atlasTexture;
}
#if HAS_SAVE_ASSET_IF_DIRTY
AssetDatabase.SaveAssetIfDirty(atlasAsset);
#endif
}
#if !HAS_SAVE_ASSET_IF_DIRTY
if (spriteAtlasTexturesToRestore.Count > 0)
AssetDatabase.SaveAssets();
#endif
spriteAtlasTexturesToRestore.Clear();
} finally {
BuildUtilities.IsInSpriteAtlasBuildPostProcessing = false;
}
}
}
public class SpineBuildPreprocessor :
#if HAS_BUILD_PROCESS_WITH_REPORT
IPreprocessBuildWithReport
#else
IPreprocessBuild
#endif
{
public int callbackOrder {
get { return -2000; }
}
#if HAS_BUILD_PROCESS_WITH_REPORT
void IPreprocessBuildWithReport.OnPreprocessBuild (BuildReport report) {
SpineBuildProcessor.PreprocessBuild();
}
#else
void IPreprocessBuild.OnPreprocessBuild (BuildTarget target, string path) {
SpineBuildProcessor.PreprocessBuild();
}
#endif
}
public class SpineBuildPostprocessor :
#if HAS_BUILD_PROCESS_WITH_REPORT
IPostprocessBuildWithReport
#else
IPostprocessBuild
#endif
{
public int callbackOrder {
get { return 2000; }
}
#if HAS_BUILD_PROCESS_WITH_REPORT
void IPostprocessBuildWithReport.OnPostprocessBuild (BuildReport report) {
SpineBuildProcessor.PostprocessBuild();
}
#else
void IPostprocessBuild.OnPostprocessBuild (BuildTarget target, string path) {
SpineBuildProcessor.PostprocessBuild();
}
#endif
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,376 +1,376 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public static class SpineInspectorUtility {
public static string Pluralize (int n, string singular, string plural) {
return n + " " + (n == 1 ? singular : plural);
}
public static string PluralThenS (int n) {
return n == 1 ? "" : "s";
}
public static string EmDash {
get { return "\u2014"; }
}
static GUIContent tempContent;
internal static GUIContent TempContent (string text, Texture2D image = null, string tooltip = null) {
if (tempContent == null) tempContent = new GUIContent();
tempContent.text = text;
tempContent.image = image;
tempContent.tooltip = tooltip;
return tempContent;
}
public static void PropertyFieldWideLabel (SerializedProperty property, GUIContent label = null, float minimumLabelWidth = 150) {
EditorGUIUtility.labelWidth = minimumLabelWidth;
EditorGUILayout.PropertyField(property, label ?? TempContent(property.displayName, null, property.tooltip));
EditorGUIUtility.labelWidth = 0; // Resets to default
}
public static void PropertyFieldFitLabel (SerializedProperty property, GUIContent label = null, float extraSpace = 5f) {
label = label ?? TempContent(property.displayName, null, property.tooltip);
float width = GUI.skin.label.CalcSize(TempContent(label.text)).x + extraSpace;
if (label.image != null)
width += EditorGUIUtility.singleLineHeight;
PropertyFieldWideLabel(property, label, width);
}
/// <summary>Multi-edit-compatible version of EditorGUILayout.ToggleLeft(SerializedProperty)</summary>
public static void ToggleLeftLayout (SerializedProperty property, GUIContent label = null, float width = 120f) {
if (label == null) label = SpineInspectorUtility.TempContent(property.displayName, tooltip: property.tooltip);
if (property.hasMultipleDifferentValues) {
bool previousShowMixedValue = EditorGUI.showMixedValue;
EditorGUI.showMixedValue = true;
bool clicked = EditorGUILayout.ToggleLeft(label, property.boolValue, GUILayout.Width(width));
if (clicked) property.boolValue = true; // Set all values to true when clicked.
EditorGUI.showMixedValue = previousShowMixedValue;
} else {
property.boolValue = EditorGUILayout.ToggleLeft(label, property.boolValue, GUILayout.Width(width));
}
}
/// <summary>Multi-edit-compatible version of EditorGUILayout.ToggleLeft(SerializedProperty)</summary>
public static void ToggleLeft (Rect rect, SerializedProperty property, GUIContent label = null) {
if (label == null) label = SpineInspectorUtility.TempContent(property.displayName, tooltip: property.tooltip);
if (property.hasMultipleDifferentValues) {
bool previousShowMixedValue = EditorGUI.showMixedValue;
EditorGUI.showMixedValue = true;
bool clicked = EditorGUI.ToggleLeft(rect, label, property.boolValue);
if (clicked) property.boolValue = true; // Set all values to true when clicked.
EditorGUI.showMixedValue = previousShowMixedValue;
} else {
property.boolValue = EditorGUI.ToggleLeft(rect, label, property.boolValue);
}
}
public static bool UndoRedoPerformed (UnityEngine.Event current) {
return current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed";
}
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;
}
public static FieldInfo GetNonPublicField (System.Type type, string fieldName) {
return type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
}
#region SerializedProperty Helpers
public static SerializedProperty FindBaseOrSiblingProperty (this SerializedProperty property, string propertyName) {
if (string.IsNullOrEmpty(propertyName)) return null;
SerializedProperty relativeProperty = property.serializedObject.FindProperty(propertyName); // baseProperty
// If base property is not found, look for the sibling property.
if (relativeProperty == null) {
string propertyPath = property.propertyPath;
int localPathLength = property.name.Length;
string newPropertyPath = propertyPath.Remove(propertyPath.Length - localPathLength, localPathLength) + propertyName;
relativeProperty = property.serializedObject.FindProperty(newPropertyPath);
// If a direct sibling property was not found, try to find the sibling of the array.
if (relativeProperty == null && property.isArray) {
int propertyPathLength = propertyPath.Length;
int dotCount = 0;
const int SiblingOfListDotCount = 3;
for (int i = 1; i < propertyPathLength; i++) {
if (propertyPath[propertyPathLength - i] == '.') {
dotCount++;
if (dotCount >= SiblingOfListDotCount) {
localPathLength = i - 1;
break;
}
}
}
newPropertyPath = propertyPath.Remove(propertyPath.Length - localPathLength, localPathLength) + propertyName;
relativeProperty = property.serializedObject.FindProperty(newPropertyPath);
}
}
return relativeProperty;
}
#endregion
#region Layout Scopes
static GUIStyle grayMiniLabel;
public static GUIStyle GrayMiniLabel {
get {
if (grayMiniLabel == null) {
grayMiniLabel = new GUIStyle(EditorStyles.centeredGreyMiniLabel) {
alignment = TextAnchor.UpperLeft
};
}
return grayMiniLabel;
}
}
public class LabelWidthScope : System.IDisposable {
public LabelWidthScope (float minimumLabelWidth = 190f) {
EditorGUIUtility.labelWidth = minimumLabelWidth;
}
public void Dispose () {
EditorGUIUtility.labelWidth = 0f;
}
}
public class IndentScope : System.IDisposable {
public IndentScope () { EditorGUI.indentLevel++; }
public void Dispose () { EditorGUI.indentLevel--; }
}
public class BoxScope : System.IDisposable {
readonly bool indent;
static GUIStyle boxScopeStyle;
public static GUIStyle BoxScopeStyle {
get {
if (boxScopeStyle == null) {
boxScopeStyle = new GUIStyle(EditorStyles.helpBox);
RectOffset p = boxScopeStyle.padding; // RectOffset is a class
p.right += 6;
p.top += 1;
p.left += 3;
}
return boxScopeStyle;
}
}
public BoxScope (bool indent = true) {
this.indent = indent;
EditorGUILayout.BeginVertical(BoxScopeStyle);
if (indent) EditorGUI.indentLevel++;
}
public void Dispose () {
if (indent) EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
}
}
#endregion
#region Button
const float CenterButtonMaxWidth = 270f;
const float CenterButtonHeight = 30f;
static GUIStyle spineButtonStyle;
static GUIStyle SpineButtonStyle {
get {
if (spineButtonStyle == null) {
spineButtonStyle = new GUIStyle(GUI.skin.button);
spineButtonStyle.padding = new RectOffset(10, 10, 10, 10);
}
return spineButtonStyle;
}
}
public static bool LargeCenteredButton (string label, bool sideSpace = true, float maxWidth = CenterButtonMaxWidth) {
if (sideSpace) {
bool clicked;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.Space();
clicked = GUILayout.Button(label, SpineButtonStyle, GUILayout.MaxWidth(maxWidth), GUILayout.Height(CenterButtonHeight));
EditorGUILayout.Space();
}
EditorGUILayout.Space();
return clicked;
} else {
return GUILayout.Button(label, GUILayout.MaxWidth(CenterButtonMaxWidth), GUILayout.Height(CenterButtonHeight));
}
}
public static bool LargeCenteredButton (GUIContent content, bool sideSpace = true, float maxWidth = CenterButtonMaxWidth) {
if (sideSpace) {
bool clicked;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.Space();
clicked = GUILayout.Button(content, SpineButtonStyle, GUILayout.MaxWidth(maxWidth), GUILayout.Height(CenterButtonHeight));
EditorGUILayout.Space();
}
EditorGUILayout.Space();
return clicked;
} else {
return GUILayout.Button(content, GUILayout.MaxWidth(CenterButtonMaxWidth), GUILayout.Height(CenterButtonHeight));
}
}
public static bool CenteredButton (GUIContent content, float height = 20f, bool sideSpace = true, float maxWidth = CenterButtonMaxWidth) {
if (sideSpace) {
bool clicked;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.Space();
clicked = GUILayout.Button(content, GUILayout.MaxWidth(maxWidth), GUILayout.Height(height));
EditorGUILayout.Space();
}
EditorGUILayout.Space();
return clicked;
} else {
return GUILayout.Button(content, GUILayout.MaxWidth(maxWidth), GUILayout.Height(height));
}
}
#endregion
#region Multi-Editing Helpers
public static bool TargetsUseSameData (SerializedObject so) {
if (so.isEditingMultipleObjects) {
int n = so.targetObjects.Length;
var first = so.targetObjects[0] as IHasSkeletonDataAsset;
for (int i = 1; i < n; i++) {
var sr = so.targetObjects[i] as IHasSkeletonDataAsset;
if (sr != null && sr.SkeletonDataAsset != first.SkeletonDataAsset)
return false;
}
}
return true;
}
public static SerializedObject GetRenderersSerializedObject (SerializedObject serializedObject) {
if (serializedObject.isEditingMultipleObjects) {
var renderers = new List<Object>();
foreach (var o in serializedObject.targetObjects) {
var component = o as Component;
if (component != null) {
var renderer = component.GetComponent<Renderer>();
if (renderer != null)
renderers.Add(renderer);
}
}
return new SerializedObject(renderers.ToArray());
} else {
var component = serializedObject.targetObject as Component;
if (component != null) {
var renderer = component.GetComponent<Renderer>();
if (renderer != null)
return new SerializedObject(renderer);
}
}
return null;
}
#endregion
#region Sorting Layer Field Helpers
static readonly GUIContent SortingLayerLabel = new GUIContent("Sorting Layer", "MeshRenderer.sortingLayerID");
static readonly GUIContent OrderInLayerLabel = new GUIContent("Order in Layer", "MeshRenderer.sortingOrder");
static MethodInfo m_SortingLayerFieldMethod;
static MethodInfo SortingLayerFieldMethod {
get {
if (m_SortingLayerFieldMethod == null)
m_SortingLayerFieldMethod = typeof(EditorGUILayout).GetMethod("SortingLayerField", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle) }, null);
return m_SortingLayerFieldMethod;
}
}
public struct SerializedSortingProperties {
public SerializedObject renderer;
public SerializedProperty sortingLayerID;
public SerializedProperty sortingOrder;
public SerializedSortingProperties (Renderer r) : this(new SerializedObject(r)) { }
public SerializedSortingProperties (Object[] renderers) : this(new SerializedObject(renderers)) { }
public SerializedSortingProperties (SerializedObject rendererSerializedObject) {
renderer = rendererSerializedObject;
sortingLayerID = renderer.FindProperty("m_SortingLayerID");
sortingOrder = renderer.FindProperty("m_SortingOrder");
}
public void ApplyModifiedProperties () {
renderer.ApplyModifiedProperties();
// SetDirty
if (renderer.isEditingMultipleObjects)
foreach (var o in renderer.targetObjects)
EditorUtility.SetDirty(o);
else
EditorUtility.SetDirty(renderer.targetObject);
}
}
public static void SortingPropertyFields (SerializedSortingProperties prop, bool applyModifiedProperties) {
if (applyModifiedProperties)
EditorGUI.BeginChangeCheck();
if (SpineInspectorUtility.SortingLayerFieldMethod != null && prop.sortingLayerID != null)
SpineInspectorUtility.SortingLayerFieldMethod.Invoke(null, new object[] { SortingLayerLabel, prop.sortingLayerID, EditorStyles.popup });
else
EditorGUILayout.PropertyField(prop.sortingLayerID);
EditorGUILayout.PropertyField(prop.sortingOrder, OrderInLayerLabel);
if (applyModifiedProperties && EditorGUI.EndChangeCheck())
prop.ApplyModifiedProperties();
}
#endregion
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public static class SpineInspectorUtility {
public static string Pluralize (int n, string singular, string plural) {
return n + " " + (n == 1 ? singular : plural);
}
public static string PluralThenS (int n) {
return n == 1 ? "" : "s";
}
public static string EmDash {
get { return "\u2014"; }
}
static GUIContent tempContent;
internal static GUIContent TempContent (string text, Texture2D image = null, string tooltip = null) {
if (tempContent == null) tempContent = new GUIContent();
tempContent.text = text;
tempContent.image = image;
tempContent.tooltip = tooltip;
return tempContent;
}
public static void PropertyFieldWideLabel (SerializedProperty property, GUIContent label = null, float minimumLabelWidth = 150) {
EditorGUIUtility.labelWidth = minimumLabelWidth;
EditorGUILayout.PropertyField(property, label ?? TempContent(property.displayName, null, property.tooltip));
EditorGUIUtility.labelWidth = 0; // Resets to default
}
public static void PropertyFieldFitLabel (SerializedProperty property, GUIContent label = null, float extraSpace = 5f) {
label = label ?? TempContent(property.displayName, null, property.tooltip);
float width = GUI.skin.label.CalcSize(TempContent(label.text)).x + extraSpace;
if (label.image != null)
width += EditorGUIUtility.singleLineHeight;
PropertyFieldWideLabel(property, label, width);
}
/// <summary>Multi-edit-compatible version of EditorGUILayout.ToggleLeft(SerializedProperty)</summary>
public static void ToggleLeftLayout (SerializedProperty property, GUIContent label = null, float width = 120f) {
if (label == null) label = SpineInspectorUtility.TempContent(property.displayName, tooltip: property.tooltip);
if (property.hasMultipleDifferentValues) {
bool previousShowMixedValue = EditorGUI.showMixedValue;
EditorGUI.showMixedValue = true;
bool clicked = EditorGUILayout.ToggleLeft(label, property.boolValue, GUILayout.Width(width));
if (clicked) property.boolValue = true; // Set all values to true when clicked.
EditorGUI.showMixedValue = previousShowMixedValue;
} else {
property.boolValue = EditorGUILayout.ToggleLeft(label, property.boolValue, GUILayout.Width(width));
}
}
/// <summary>Multi-edit-compatible version of EditorGUILayout.ToggleLeft(SerializedProperty)</summary>
public static void ToggleLeft (Rect rect, SerializedProperty property, GUIContent label = null) {
if (label == null) label = SpineInspectorUtility.TempContent(property.displayName, tooltip: property.tooltip);
if (property.hasMultipleDifferentValues) {
bool previousShowMixedValue = EditorGUI.showMixedValue;
EditorGUI.showMixedValue = true;
bool clicked = EditorGUI.ToggleLeft(rect, label, property.boolValue);
if (clicked) property.boolValue = true; // Set all values to true when clicked.
EditorGUI.showMixedValue = previousShowMixedValue;
} else {
property.boolValue = EditorGUI.ToggleLeft(rect, label, property.boolValue);
}
}
public static bool UndoRedoPerformed (UnityEngine.Event current) {
return current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed";
}
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;
}
public static FieldInfo GetNonPublicField (System.Type type, string fieldName) {
return type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
}
#region SerializedProperty Helpers
public static SerializedProperty FindBaseOrSiblingProperty (this SerializedProperty property, string propertyName) {
if (string.IsNullOrEmpty(propertyName)) return null;
SerializedProperty relativeProperty = property.serializedObject.FindProperty(propertyName); // baseProperty
// If base property is not found, look for the sibling property.
if (relativeProperty == null) {
string propertyPath = property.propertyPath;
int localPathLength = property.name.Length;
string newPropertyPath = propertyPath.Remove(propertyPath.Length - localPathLength, localPathLength) + propertyName;
relativeProperty = property.serializedObject.FindProperty(newPropertyPath);
// If a direct sibling property was not found, try to find the sibling of the array.
if (relativeProperty == null && property.isArray) {
int propertyPathLength = propertyPath.Length;
int dotCount = 0;
const int SiblingOfListDotCount = 3;
for (int i = 1; i < propertyPathLength; i++) {
if (propertyPath[propertyPathLength - i] == '.') {
dotCount++;
if (dotCount >= SiblingOfListDotCount) {
localPathLength = i - 1;
break;
}
}
}
newPropertyPath = propertyPath.Remove(propertyPath.Length - localPathLength, localPathLength) + propertyName;
relativeProperty = property.serializedObject.FindProperty(newPropertyPath);
}
}
return relativeProperty;
}
#endregion
#region Layout Scopes
static GUIStyle grayMiniLabel;
public static GUIStyle GrayMiniLabel {
get {
if (grayMiniLabel == null) {
grayMiniLabel = new GUIStyle(EditorStyles.centeredGreyMiniLabel) {
alignment = TextAnchor.UpperLeft
};
}
return grayMiniLabel;
}
}
public class LabelWidthScope : System.IDisposable {
public LabelWidthScope (float minimumLabelWidth = 190f) {
EditorGUIUtility.labelWidth = minimumLabelWidth;
}
public void Dispose () {
EditorGUIUtility.labelWidth = 0f;
}
}
public class IndentScope : System.IDisposable {
public IndentScope () { EditorGUI.indentLevel++; }
public void Dispose () { EditorGUI.indentLevel--; }
}
public class BoxScope : System.IDisposable {
readonly bool indent;
static GUIStyle boxScopeStyle;
public static GUIStyle BoxScopeStyle {
get {
if (boxScopeStyle == null) {
boxScopeStyle = new GUIStyle(EditorStyles.helpBox);
RectOffset p = boxScopeStyle.padding; // RectOffset is a class
p.right += 6;
p.top += 1;
p.left += 3;
}
return boxScopeStyle;
}
}
public BoxScope (bool indent = true) {
this.indent = indent;
EditorGUILayout.BeginVertical(BoxScopeStyle);
if (indent) EditorGUI.indentLevel++;
}
public void Dispose () {
if (indent) EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
}
}
#endregion
#region Button
const float CenterButtonMaxWidth = 270f;
const float CenterButtonHeight = 30f;
static GUIStyle spineButtonStyle;
static GUIStyle SpineButtonStyle {
get {
if (spineButtonStyle == null) {
spineButtonStyle = new GUIStyle(GUI.skin.button);
spineButtonStyle.padding = new RectOffset(10, 10, 10, 10);
}
return spineButtonStyle;
}
}
public static bool LargeCenteredButton (string label, bool sideSpace = true, float maxWidth = CenterButtonMaxWidth) {
if (sideSpace) {
bool clicked;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.Space();
clicked = GUILayout.Button(label, SpineButtonStyle, GUILayout.MaxWidth(maxWidth), GUILayout.Height(CenterButtonHeight));
EditorGUILayout.Space();
}
EditorGUILayout.Space();
return clicked;
} else {
return GUILayout.Button(label, GUILayout.MaxWidth(CenterButtonMaxWidth), GUILayout.Height(CenterButtonHeight));
}
}
public static bool LargeCenteredButton (GUIContent content, bool sideSpace = true, float maxWidth = CenterButtonMaxWidth) {
if (sideSpace) {
bool clicked;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.Space();
clicked = GUILayout.Button(content, SpineButtonStyle, GUILayout.MaxWidth(maxWidth), GUILayout.Height(CenterButtonHeight));
EditorGUILayout.Space();
}
EditorGUILayout.Space();
return clicked;
} else {
return GUILayout.Button(content, GUILayout.MaxWidth(CenterButtonMaxWidth), GUILayout.Height(CenterButtonHeight));
}
}
public static bool CenteredButton (GUIContent content, float height = 20f, bool sideSpace = true, float maxWidth = CenterButtonMaxWidth) {
if (sideSpace) {
bool clicked;
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.Space();
clicked = GUILayout.Button(content, GUILayout.MaxWidth(maxWidth), GUILayout.Height(height));
EditorGUILayout.Space();
}
EditorGUILayout.Space();
return clicked;
} else {
return GUILayout.Button(content, GUILayout.MaxWidth(maxWidth), GUILayout.Height(height));
}
}
#endregion
#region Multi-Editing Helpers
public static bool TargetsUseSameData (SerializedObject so) {
if (so.isEditingMultipleObjects) {
int n = so.targetObjects.Length;
var first = so.targetObjects[0] as IHasSkeletonDataAsset;
for (int i = 1; i < n; i++) {
var sr = so.targetObjects[i] as IHasSkeletonDataAsset;
if (sr != null && sr.SkeletonDataAsset != first.SkeletonDataAsset)
return false;
}
}
return true;
}
public static SerializedObject GetRenderersSerializedObject (SerializedObject serializedObject) {
if (serializedObject.isEditingMultipleObjects) {
var renderers = new List<Object>();
foreach (var o in serializedObject.targetObjects) {
var component = o as Component;
if (component != null) {
var renderer = component.GetComponent<Renderer>();
if (renderer != null)
renderers.Add(renderer);
}
}
return new SerializedObject(renderers.ToArray());
} else {
var component = serializedObject.targetObject as Component;
if (component != null) {
var renderer = component.GetComponent<Renderer>();
if (renderer != null)
return new SerializedObject(renderer);
}
}
return null;
}
#endregion
#region Sorting Layer Field Helpers
static readonly GUIContent SortingLayerLabel = new GUIContent("Sorting Layer", "MeshRenderer.sortingLayerID");
static readonly GUIContent OrderInLayerLabel = new GUIContent("Order in Layer", "MeshRenderer.sortingOrder");
static MethodInfo m_SortingLayerFieldMethod;
static MethodInfo SortingLayerFieldMethod {
get {
if (m_SortingLayerFieldMethod == null)
m_SortingLayerFieldMethod = typeof(EditorGUILayout).GetMethod("SortingLayerField", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle) }, null);
return m_SortingLayerFieldMethod;
}
}
public struct SerializedSortingProperties {
public SerializedObject renderer;
public SerializedProperty sortingLayerID;
public SerializedProperty sortingOrder;
public SerializedSortingProperties (Renderer r) : this(new SerializedObject(r)) { }
public SerializedSortingProperties (Object[] renderers) : this(new SerializedObject(renderers)) { }
public SerializedSortingProperties (SerializedObject rendererSerializedObject) {
renderer = rendererSerializedObject;
sortingLayerID = renderer.FindProperty("m_SortingLayerID");
sortingOrder = renderer.FindProperty("m_SortingOrder");
}
public void ApplyModifiedProperties () {
renderer.ApplyModifiedProperties();
// SetDirty
if (renderer.isEditingMultipleObjects)
foreach (var o in renderer.targetObjects)
EditorUtility.SetDirty(o);
else
EditorUtility.SetDirty(renderer.targetObject);
}
}
public static void SortingPropertyFields (SerializedSortingProperties prop, bool applyModifiedProperties) {
if (applyModifiedProperties)
EditorGUI.BeginChangeCheck();
if (SpineInspectorUtility.SortingLayerFieldMethod != null && prop.sortingLayerID != null)
SpineInspectorUtility.SortingLayerFieldMethod.Invoke(null, new object[] { SortingLayerLabel, prop.sortingLayerID, EditorStyles.popup });
else
EditorGUILayout.PropertyField(prop.sortingLayerID);
EditorGUILayout.PropertyField(prop.sortingOrder, OrderInLayerLabel);
if (applyModifiedProperties && EditorGUI.EndChangeCheck())
prop.ApplyModifiedProperties();
}
#endregion
}
}

View File

@@ -1,246 +1,246 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
#if UNITY_2018 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEWHIERARCHYWINDOWCALLBACKS
#endif
#if UNITY_2017_1_OR_NEWER
#define BUILT_IN_SPRITE_MASK_COMPONENT
#endif
#if BUILT_IN_SPRITE_MASK_COMPONENT
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection;
namespace Spine.Unity.Editor {
public class SpineMaskUtilities {
private const string MATERIAL_FILENAME_SUFFIX_INSIDE_MASK = "_InsideMask";
private const string MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK = "_OutsideMask";
public static void EditorAssignSpriteMaskMaterials(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
var maskInteraction = skeleton.maskInteraction;
var meshRenderer = skeleton.GetComponent<MeshRenderer>();
if (maskMaterials.materialsMaskDisabled.Length > 0 && maskMaterials.materialsMaskDisabled[0] != null &&
maskInteraction == SpriteMaskInteraction.None) {
meshRenderer.materials = maskMaterials.materialsMaskDisabled;
}
else if (maskInteraction == SpriteMaskInteraction.VisibleInsideMask) {
if (maskMaterials.materialsInsideMask.Length == 0 || maskMaterials.materialsInsideMask[0] == null)
EditorInitSpriteMaskMaterialsInsideMask(skeleton);
meshRenderer.materials = maskMaterials.materialsInsideMask;
}
else if (maskInteraction == SpriteMaskInteraction.VisibleOutsideMask) {
if (maskMaterials.materialsOutsideMask.Length == 0 || maskMaterials.materialsOutsideMask[0] == null)
EditorInitSpriteMaskMaterialsOutsideMask(skeleton);
meshRenderer.materials = maskMaterials.materialsOutsideMask;
}
}
public static bool AreMaskMaterialsMissing(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
var maskInteraction = skeleton.maskInteraction;
if (maskInteraction == SpriteMaskInteraction.VisibleInsideMask) {
return (maskMaterials.materialsInsideMask.Length == 0 || maskMaterials.materialsInsideMask[0] == null);
}
else if (maskInteraction == SpriteMaskInteraction.VisibleOutsideMask) {
return (maskMaterials.materialsOutsideMask.Length == 0 || maskMaterials.materialsOutsideMask[0] == null);
}
return false;
}
public static void EditorInitMaskMaterials(SkeletonRenderer skeleton, SkeletonRenderer.SpriteMaskInteractionMaterials maskMaterials, SpriteMaskInteraction maskType) {
if (maskType == SpriteMaskInteraction.None) {
EditorConfirmDisabledMaskMaterialsInit(skeleton);
}
else if (maskType == SpriteMaskInteraction.VisibleInsideMask) {
EditorInitSpriteMaskMaterialsInsideMask(skeleton);
}
else if (maskType == SpriteMaskInteraction.VisibleOutsideMask) {
EditorInitSpriteMaskMaterialsOutsideMask(skeleton);
}
}
public static void EditorDeleteMaskMaterials(SkeletonRenderer.SpriteMaskInteractionMaterials maskMaterials, SpriteMaskInteraction maskType) {
Material[] targetMaterials;
if (maskType == SpriteMaskInteraction.VisibleInsideMask) {
targetMaterials = maskMaterials.materialsInsideMask;
}
else if (maskType == SpriteMaskInteraction.VisibleOutsideMask) {
targetMaterials = maskMaterials.materialsOutsideMask;
}
else {
Debug.LogWarning("EditorDeleteMaskMaterials: Normal materials are kept as a reference and shall never be deleted.");
return;
}
for (int i = 0; i < targetMaterials.Length; ++i) {
var material = targetMaterials[i];
if (material != null) {
string materialPath = UnityEditor.AssetDatabase.GetAssetPath(material);
UnityEditor.AssetDatabase.DeleteAsset(materialPath);
Debug.Log(string.Concat("Deleted material '", materialPath, "'"));
}
}
if (maskType == SpriteMaskInteraction.VisibleInsideMask) {
maskMaterials.materialsInsideMask = new Material[0];
}
else if (maskType == SpriteMaskInteraction.VisibleOutsideMask) {
maskMaterials.materialsOutsideMask = new Material[0];
}
}
private static void EditorInitSpriteMaskMaterialsInsideMask(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
EditorInitSpriteMaskMaterialsForMaskType(skeleton, SkeletonRenderer.STENCIL_COMP_MASKINTERACTION_VISIBLE_INSIDE,
ref maskMaterials.materialsInsideMask);
}
private static void EditorInitSpriteMaskMaterialsOutsideMask(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
EditorInitSpriteMaskMaterialsForMaskType(skeleton, SkeletonRenderer.STENCIL_COMP_MASKINTERACTION_VISIBLE_OUTSIDE,
ref maskMaterials.materialsOutsideMask);
}
private static void EditorInitSpriteMaskMaterialsForMaskType(SkeletonRenderer skeleton, UnityEngine.Rendering.CompareFunction maskFunction,
ref Material[] materialsToFill) {
if (!EditorConfirmDisabledMaskMaterialsInit(skeleton))
return;
var maskMaterials = skeleton.maskMaterials;
var originalMaterials = maskMaterials.materialsMaskDisabled;
materialsToFill = new Material[originalMaterials.Length];
for (int i = 0; i < originalMaterials.Length; i++) {
Material newMaterial = null;
if (!Application.isPlaying) {
newMaterial = EditorCreateOrLoadMaskMaterialAsset(maskMaterials, maskFunction, originalMaterials[i]);
}
if (newMaterial == null) {
newMaterial = new Material(originalMaterials[i]);
newMaterial.SetFloat(SkeletonRenderer.STENCIL_COMP_PARAM_ID, (int)maskFunction);
}
materialsToFill[i] = newMaterial;
}
}
private static bool EditorConfirmDisabledMaskMaterialsInit(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
if (maskMaterials.materialsMaskDisabled.Length > 0 && maskMaterials.materialsMaskDisabled[0] != null) {
return true;
}
var meshRenderer = skeleton.GetComponent<MeshRenderer>();
Material[] currentMaterials = meshRenderer.sharedMaterials;
if (currentMaterials.Length == 0 || currentMaterials[0] == null) {
Debug.LogWarning("No materials found assigned at " + skeleton.name);
return false;
}
// We have to be sure that there has not been a recompilation or similar events that led to
// inside- or outside-mask materials being assigned to meshRenderer.sharedMaterials.
string firstMaterialPath = UnityEditor.AssetDatabase.GetAssetPath(currentMaterials[0]);
if (firstMaterialPath.Contains(MATERIAL_FILENAME_SUFFIX_INSIDE_MASK) ||
firstMaterialPath.Contains(MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK)) {
maskMaterials.materialsMaskDisabled = new Material[currentMaterials.Length];
for (int i = 0; i < currentMaterials.Length; ++i) {
string path = UnityEditor.AssetDatabase.GetAssetPath(currentMaterials[i]);
string correctPath = null;
if (path.Contains(MATERIAL_FILENAME_SUFFIX_INSIDE_MASK)) {
correctPath = path.Replace(MATERIAL_FILENAME_SUFFIX_INSIDE_MASK, "");
}
else if (path.Contains(MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK)) {
correctPath = path.Replace(MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK, "");
}
if (correctPath != null) {
Material material = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(correctPath);
if (material == null)
Debug.LogWarning("No original ignore-mask material found for path " + correctPath);
maskMaterials.materialsMaskDisabled[i] = material;
}
}
}
else {
maskMaterials.materialsMaskDisabled = currentMaterials;
}
return true;
}
public static Material EditorCreateOrLoadMaskMaterialAsset(SkeletonRenderer.SpriteMaskInteractionMaterials maskMaterials,
UnityEngine.Rendering.CompareFunction maskFunction, Material originalMaterial) {
string originalMaterialPath = UnityEditor.AssetDatabase.GetAssetPath(originalMaterial);
int posOfExtensionDot = originalMaterialPath.LastIndexOf('.');
string materialPath = (maskFunction == SkeletonRenderer.STENCIL_COMP_MASKINTERACTION_VISIBLE_INSIDE) ?
originalMaterialPath.Insert(posOfExtensionDot, MATERIAL_FILENAME_SUFFIX_INSIDE_MASK) :
originalMaterialPath.Insert(posOfExtensionDot, MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK);
Material material = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(materialPath);
if (material != null) {
return material;
}
material = new Material(originalMaterial);
material.SetFloat(SkeletonRenderer.STENCIL_COMP_PARAM_ID, (int)maskFunction);
UnityEditor.AssetDatabase.CreateAsset(material, materialPath);
Debug.Log(string.Concat("Created material '", materialPath, "' for mask interaction based on '", originalMaterialPath, "'."));
UnityEditor.EditorUtility.SetDirty(material);
UnityEditor.AssetDatabase.SaveAssets();
return material;
}
}
}
#endif // BUILT_IN_SPRITE_MASK_COMPONENT
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma warning disable 0219
#define SPINE_SKELETONMECANIM
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
#if UNITY_2018 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEWHIERARCHYWINDOWCALLBACKS
#endif
#if UNITY_2017_1_OR_NEWER
#define BUILT_IN_SPRITE_MASK_COMPONENT
#endif
#if BUILT_IN_SPRITE_MASK_COMPONENT
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection;
namespace Spine.Unity.Editor {
public class SpineMaskUtilities {
private const string MATERIAL_FILENAME_SUFFIX_INSIDE_MASK = "_InsideMask";
private const string MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK = "_OutsideMask";
public static void EditorAssignSpriteMaskMaterials(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
var maskInteraction = skeleton.maskInteraction;
var meshRenderer = skeleton.GetComponent<MeshRenderer>();
if (maskMaterials.materialsMaskDisabled.Length > 0 && maskMaterials.materialsMaskDisabled[0] != null &&
maskInteraction == SpriteMaskInteraction.None) {
meshRenderer.materials = maskMaterials.materialsMaskDisabled;
}
else if (maskInteraction == SpriteMaskInteraction.VisibleInsideMask) {
if (maskMaterials.materialsInsideMask.Length == 0 || maskMaterials.materialsInsideMask[0] == null)
EditorInitSpriteMaskMaterialsInsideMask(skeleton);
meshRenderer.materials = maskMaterials.materialsInsideMask;
}
else if (maskInteraction == SpriteMaskInteraction.VisibleOutsideMask) {
if (maskMaterials.materialsOutsideMask.Length == 0 || maskMaterials.materialsOutsideMask[0] == null)
EditorInitSpriteMaskMaterialsOutsideMask(skeleton);
meshRenderer.materials = maskMaterials.materialsOutsideMask;
}
}
public static bool AreMaskMaterialsMissing(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
var maskInteraction = skeleton.maskInteraction;
if (maskInteraction == SpriteMaskInteraction.VisibleInsideMask) {
return (maskMaterials.materialsInsideMask.Length == 0 || maskMaterials.materialsInsideMask[0] == null);
}
else if (maskInteraction == SpriteMaskInteraction.VisibleOutsideMask) {
return (maskMaterials.materialsOutsideMask.Length == 0 || maskMaterials.materialsOutsideMask[0] == null);
}
return false;
}
public static void EditorInitMaskMaterials(SkeletonRenderer skeleton, SkeletonRenderer.SpriteMaskInteractionMaterials maskMaterials, SpriteMaskInteraction maskType) {
if (maskType == SpriteMaskInteraction.None) {
EditorConfirmDisabledMaskMaterialsInit(skeleton);
}
else if (maskType == SpriteMaskInteraction.VisibleInsideMask) {
EditorInitSpriteMaskMaterialsInsideMask(skeleton);
}
else if (maskType == SpriteMaskInteraction.VisibleOutsideMask) {
EditorInitSpriteMaskMaterialsOutsideMask(skeleton);
}
}
public static void EditorDeleteMaskMaterials(SkeletonRenderer.SpriteMaskInteractionMaterials maskMaterials, SpriteMaskInteraction maskType) {
Material[] targetMaterials;
if (maskType == SpriteMaskInteraction.VisibleInsideMask) {
targetMaterials = maskMaterials.materialsInsideMask;
}
else if (maskType == SpriteMaskInteraction.VisibleOutsideMask) {
targetMaterials = maskMaterials.materialsOutsideMask;
}
else {
Debug.LogWarning("EditorDeleteMaskMaterials: Normal materials are kept as a reference and shall never be deleted.");
return;
}
for (int i = 0; i < targetMaterials.Length; ++i) {
var material = targetMaterials[i];
if (material != null) {
string materialPath = UnityEditor.AssetDatabase.GetAssetPath(material);
UnityEditor.AssetDatabase.DeleteAsset(materialPath);
Debug.Log(string.Concat("Deleted material '", materialPath, "'"));
}
}
if (maskType == SpriteMaskInteraction.VisibleInsideMask) {
maskMaterials.materialsInsideMask = new Material[0];
}
else if (maskType == SpriteMaskInteraction.VisibleOutsideMask) {
maskMaterials.materialsOutsideMask = new Material[0];
}
}
private static void EditorInitSpriteMaskMaterialsInsideMask(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
EditorInitSpriteMaskMaterialsForMaskType(skeleton, SkeletonRenderer.STENCIL_COMP_MASKINTERACTION_VISIBLE_INSIDE,
ref maskMaterials.materialsInsideMask);
}
private static void EditorInitSpriteMaskMaterialsOutsideMask(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
EditorInitSpriteMaskMaterialsForMaskType(skeleton, SkeletonRenderer.STENCIL_COMP_MASKINTERACTION_VISIBLE_OUTSIDE,
ref maskMaterials.materialsOutsideMask);
}
private static void EditorInitSpriteMaskMaterialsForMaskType(SkeletonRenderer skeleton, UnityEngine.Rendering.CompareFunction maskFunction,
ref Material[] materialsToFill) {
if (!EditorConfirmDisabledMaskMaterialsInit(skeleton))
return;
var maskMaterials = skeleton.maskMaterials;
var originalMaterials = maskMaterials.materialsMaskDisabled;
materialsToFill = new Material[originalMaterials.Length];
for (int i = 0; i < originalMaterials.Length; i++) {
Material newMaterial = null;
if (!Application.isPlaying) {
newMaterial = EditorCreateOrLoadMaskMaterialAsset(maskMaterials, maskFunction, originalMaterials[i]);
}
if (newMaterial == null) {
newMaterial = new Material(originalMaterials[i]);
newMaterial.SetFloat(SkeletonRenderer.STENCIL_COMP_PARAM_ID, (int)maskFunction);
}
materialsToFill[i] = newMaterial;
}
}
private static bool EditorConfirmDisabledMaskMaterialsInit(SkeletonRenderer skeleton) {
var maskMaterials = skeleton.maskMaterials;
if (maskMaterials.materialsMaskDisabled.Length > 0 && maskMaterials.materialsMaskDisabled[0] != null) {
return true;
}
var meshRenderer = skeleton.GetComponent<MeshRenderer>();
Material[] currentMaterials = meshRenderer.sharedMaterials;
if (currentMaterials.Length == 0 || currentMaterials[0] == null) {
Debug.LogWarning("No materials found assigned at " + skeleton.name);
return false;
}
// We have to be sure that there has not been a recompilation or similar events that led to
// inside- or outside-mask materials being assigned to meshRenderer.sharedMaterials.
string firstMaterialPath = UnityEditor.AssetDatabase.GetAssetPath(currentMaterials[0]);
if (firstMaterialPath.Contains(MATERIAL_FILENAME_SUFFIX_INSIDE_MASK) ||
firstMaterialPath.Contains(MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK)) {
maskMaterials.materialsMaskDisabled = new Material[currentMaterials.Length];
for (int i = 0; i < currentMaterials.Length; ++i) {
string path = UnityEditor.AssetDatabase.GetAssetPath(currentMaterials[i]);
string correctPath = null;
if (path.Contains(MATERIAL_FILENAME_SUFFIX_INSIDE_MASK)) {
correctPath = path.Replace(MATERIAL_FILENAME_SUFFIX_INSIDE_MASK, "");
}
else if (path.Contains(MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK)) {
correctPath = path.Replace(MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK, "");
}
if (correctPath != null) {
Material material = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(correctPath);
if (material == null)
Debug.LogWarning("No original ignore-mask material found for path " + correctPath);
maskMaterials.materialsMaskDisabled[i] = material;
}
}
}
else {
maskMaterials.materialsMaskDisabled = currentMaterials;
}
return true;
}
public static Material EditorCreateOrLoadMaskMaterialAsset(SkeletonRenderer.SpriteMaskInteractionMaterials maskMaterials,
UnityEngine.Rendering.CompareFunction maskFunction, Material originalMaterial) {
string originalMaterialPath = UnityEditor.AssetDatabase.GetAssetPath(originalMaterial);
int posOfExtensionDot = originalMaterialPath.LastIndexOf('.');
string materialPath = (maskFunction == SkeletonRenderer.STENCIL_COMP_MASKINTERACTION_VISIBLE_INSIDE) ?
originalMaterialPath.Insert(posOfExtensionDot, MATERIAL_FILENAME_SUFFIX_INSIDE_MASK) :
originalMaterialPath.Insert(posOfExtensionDot, MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK);
Material material = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(materialPath);
if (material != null) {
return material;
}
material = new Material(originalMaterial);
material.SetFloat(SkeletonRenderer.STENCIL_COMP_PARAM_ID, (int)maskFunction);
UnityEditor.AssetDatabase.CreateAsset(material, materialPath);
Debug.Log(string.Concat("Created material '", materialPath, "' for mask interaction based on '", originalMaterialPath, "'."));
UnityEditor.EditorUtility.SetDirty(material);
UnityEditor.AssetDatabase.SaveAssets();
return material;
}
}
}
#endif // BUILT_IN_SPRITE_MASK_COMPONENT

File diff suppressed because it is too large Load Diff

View File

@@ -1,174 +1,174 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
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 = "\nSkeleton baking is not the primary use case for Spine skeletons." +
"\nUse baking if you have specialized uses, such as simplified skeletons with movement driven by physics." +
"\n\nBaked Skeletons do not support the following:" +
"\n\tDisabled rotation or scale inheritance" +
"\n\tLocal Shear" +
"\n\tAll Constraint types" +
"\n\tWeighted mesh verts with more than 4 bound bones" +
"\n\nBaked Animations do not support the following:" +
"\n\tMesh Deform Keys" +
"\n\tColor Keys" +
"\n\tDraw Order Keys" +
"\n\nAnimation Curves are sampled at 60fps and are not realtime." +
"\nConstraint animations are also baked into animation curves." +
"\nSee 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;
bool hasExtraSkins = skeletonData.Skins.Count > 1;
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));
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Slots: " + skeletonData.Slots.Count, Icons.slotRoot));
if (hasExtraSkins) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Skins: " + skeletonData.Skins.Count, Icons.skinsRoot));
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Current skin attachments: " + (bakeSkin == null ? 0 : bakeSkin.Attachments.Count), Icons.skinPlaceholder));
} else if (skeletonData.Skins.Count == 1) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Skins: 1 (only default Skin)", Icons.skinsRoot));
}
int totalAttachments = 0;
foreach (var s in skeletonData.Skins)
totalAttachments += s.Attachments.Count;
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Total Attachments: " + totalAttachments, Icons.genericAttachment));
}
}
using (new SpineInspectorUtility.BoxScope(false)) {
EditorGUILayout.LabelField("Animations", EditorStyles.boldLabel);
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Animations: " + skeletonData.Animations.Count, Icons.animation));
using (new SpineInspectorUtility.IndentScope()) {
bakeAnimations = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake Animations", Icons.animationRoot), bakeAnimations);
using (new EditorGUI.DisabledScope(!bakeAnimations)) {
using (new SpineInspectorUtility.IndentScope()) {
bakeIK = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake IK", Icons.constraintIK), bakeIK);
bakeEventOptions = (SendMessageOptions)EditorGUILayout.EnumPopup(SpineInspectorUtility.TempContent("Event Options", Icons.userEvent), bakeEventOptions);
}
}
}
}
EditorGUILayout.Space();
if (!string.IsNullOrEmpty(skinToBake) && UnityEngine.Event.current.type == EventType.Repaint)
bakeSkin = skeletonData.FindSkin(skinToBake) ?? skeletonData.DefaultSkin;
var prefabIcon = EditorGUIUtility.FindTexture("PrefabModel Icon");
if (hasExtraSkins) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(so.FindProperty("skinToBake"));
if (EditorGUI.EndChangeCheck()) {
so.ApplyModifiedProperties();
Repaint();
}
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake Skeleton with Skin ({0})", (bakeSkin == null ? "default" : bakeSkin.Name)), prefabIcon))) {
SkeletonBaker.BakeToPrefab(skeletonDataAsset, new ExposedList<Skin>(new[] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
}
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake All ({0} skins)", skeletonData.Skins.Count), prefabIcon))) {
SkeletonBaker.BakeToPrefab(skeletonDataAsset, skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
}
} else {
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Bake Skeleton", prefabIcon))) {
SkeletonBaker.BakeToPrefab(skeletonDataAsset, new ExposedList<Skin>(new[] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
}
}
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
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 = "\nSkeleton baking is not the primary use case for Spine skeletons." +
"\nUse baking if you have specialized uses, such as simplified skeletons with movement driven by physics." +
"\n\nBaked Skeletons do not support the following:" +
"\n\tDisabled rotation or scale inheritance" +
"\n\tLocal Shear" +
"\n\tAll Constraint types" +
"\n\tWeighted mesh verts with more than 4 bound bones" +
"\n\nBaked Animations do not support the following:" +
"\n\tMesh Deform Keys" +
"\n\tColor Keys" +
"\n\tDraw Order Keys" +
"\n\nAnimation Curves are sampled at 60fps and are not realtime." +
"\nConstraint animations are also baked into animation curves." +
"\nSee 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;
bool hasExtraSkins = skeletonData.Skins.Count > 1;
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));
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Slots: " + skeletonData.Slots.Count, Icons.slotRoot));
if (hasExtraSkins) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Skins: " + skeletonData.Skins.Count, Icons.skinsRoot));
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Current skin attachments: " + (bakeSkin == null ? 0 : bakeSkin.Attachments.Count), Icons.skinPlaceholder));
} else if (skeletonData.Skins.Count == 1) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Skins: 1 (only default Skin)", Icons.skinsRoot));
}
int totalAttachments = 0;
foreach (var s in skeletonData.Skins)
totalAttachments += s.Attachments.Count;
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Total Attachments: " + totalAttachments, Icons.genericAttachment));
}
}
using (new SpineInspectorUtility.BoxScope(false)) {
EditorGUILayout.LabelField("Animations", EditorStyles.boldLabel);
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Animations: " + skeletonData.Animations.Count, Icons.animation));
using (new SpineInspectorUtility.IndentScope()) {
bakeAnimations = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake Animations", Icons.animationRoot), bakeAnimations);
using (new EditorGUI.DisabledScope(!bakeAnimations)) {
using (new SpineInspectorUtility.IndentScope()) {
bakeIK = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake IK", Icons.constraintIK), bakeIK);
bakeEventOptions = (SendMessageOptions)EditorGUILayout.EnumPopup(SpineInspectorUtility.TempContent("Event Options", Icons.userEvent), bakeEventOptions);
}
}
}
}
EditorGUILayout.Space();
if (!string.IsNullOrEmpty(skinToBake) && UnityEngine.Event.current.type == EventType.Repaint)
bakeSkin = skeletonData.FindSkin(skinToBake) ?? skeletonData.DefaultSkin;
var prefabIcon = EditorGUIUtility.FindTexture("PrefabModel Icon");
if (hasExtraSkins) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(so.FindProperty("skinToBake"));
if (EditorGUI.EndChangeCheck()) {
so.ApplyModifiedProperties();
Repaint();
}
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake Skeleton with Skin ({0})", (bakeSkin == null ? "default" : bakeSkin.Name)), prefabIcon))) {
SkeletonBaker.BakeToPrefab(skeletonDataAsset, new ExposedList<Skin>(new[] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
}
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake All ({0} skins)", skeletonData.Skins.Count), prefabIcon))) {
SkeletonBaker.BakeToPrefab(skeletonDataAsset, skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
}
} else {
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Bake Skeleton", prefabIcon))) {
SkeletonBaker.BakeToPrefab(skeletonDataAsset, new ExposedList<Skin>(new[] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
}
}
}
}
}

View File

@@ -1,364 +1,364 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
#if UNITY_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
#if UNITY_2020_2_OR_NEWER
#define HAS_ON_POSTPROCESS_PREFAB
#endif
using System.Threading;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public class SpinePreferences : ScriptableObject {
#if NEW_PREFERENCES_SETTINGS_PROVIDER
static int wasPreferencesDirCreated = 0;
static int wasPreferencesAssetCreated = 0;
#endif
public const string SPINE_SETTINGS_ASSET_PATH = "Assets/Editor/SpineSettings.asset";
#if SPINE_TK2D
internal const float DEFAULT_DEFAULT_SCALE = 1f;
#else
internal const float DEFAULT_DEFAULT_SCALE = 0.01f;
#endif
public float defaultScale = DEFAULT_DEFAULT_SCALE;
internal const float DEFAULT_DEFAULT_MIX = 0.2f;
public float defaultMix = DEFAULT_DEFAULT_MIX;
internal const string DEFAULT_DEFAULT_SHADER = "Spine/Skeleton";
public string defaultShader = DEFAULT_DEFAULT_SHADER;
public string DefaultShader {
get { return !string.IsNullOrEmpty(defaultShader) ? defaultShader : DEFAULT_DEFAULT_SHADER; }
set { defaultShader = value; }
}
internal const float DEFAULT_DEFAULT_ZSPACING = 0f;
public float defaultZSpacing = DEFAULT_DEFAULT_ZSPACING;
internal const bool DEFAULT_DEFAULT_INSTANTIATE_LOOP = true;
public bool defaultInstantiateLoop = DEFAULT_DEFAULT_INSTANTIATE_LOOP;
internal const bool DEFAULT_SHOW_HIERARCHY_ICONS = true;
public bool showHierarchyIcons = DEFAULT_SHOW_HIERARCHY_ICONS;
internal const bool DEFAULT_SET_TEXTUREIMPORTER_SETTINGS = true;
public bool setTextureImporterSettings = DEFAULT_SET_TEXTUREIMPORTER_SETTINGS;
internal const string DEFAULT_TEXTURE_SETTINGS_REFERENCE = "";
public string textureSettingsReference = DEFAULT_TEXTURE_SETTINGS_REFERENCE;
#if HAS_ON_POSTPROCESS_PREFAB
internal const bool DEFAULT_FIX_PREFAB_OVERRIDE_VIA_MESH_FILTER = false;
public bool fixPrefabOverrideViaMeshFilter = DEFAULT_FIX_PREFAB_OVERRIDE_VIA_MESH_FILTER;
#endif
public bool UsesPMAWorkflow {
get {
return IsPMAWorkflow(textureSettingsReference);
}
}
public static bool IsPMAWorkflow (string textureSettingsReference) {
if (textureSettingsReference == null)
return true;
string settingsReference = textureSettingsReference.ToLower();
if (settingsReference.Contains("straight") || !settingsReference.Contains("pma"))
return false;
return true;
}
public const string DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL = "SkeletonPMAMultiply";
public const string DEFAULT_BLEND_MODE_SCREEN_MATERIAL = "SkeletonPMAScreen";
public const string DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL = "SkeletonPMAAdditive";
public Material blendModeMaterialMultiply = null;
public Material blendModeMaterialScreen = null;
public Material blendModeMaterialAdditive = null;
public string FindPathOfAsset (string assetName) {
string typeSearchString = assetName;
string[] guids = AssetDatabase.FindAssets(typeSearchString);
if (guids.Length > 0) {
return AssetDatabase.GUIDToAssetPath(guids[0]);
}
return null;
}
public Material BlendModeMaterialMultiply {
get {
if (blendModeMaterialMultiply == null) {
string path = FindPathOfAsset(DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL);
blendModeMaterialMultiply = AssetDatabase.LoadAssetAtPath<Material>(path);
}
return blendModeMaterialMultiply;
}
}
public Material BlendModeMaterialScreen {
get {
if (blendModeMaterialScreen == null) {
string path = FindPathOfAsset(DEFAULT_BLEND_MODE_SCREEN_MATERIAL);
blendModeMaterialScreen = AssetDatabase.LoadAssetAtPath<Material>(path);
}
return blendModeMaterialScreen;
}
}
public Material BlendModeMaterialAdditive {
get {
if (blendModeMaterialAdditive == null) {
string path = FindPathOfAsset(DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL);
blendModeMaterialAdditive = AssetDatabase.LoadAssetAtPath<Material>(path);
}
return blendModeMaterialAdditive;
}
}
internal const bool DEFAULT_ATLASTXT_WARNING = true;
public bool atlasTxtImportWarning = DEFAULT_ATLASTXT_WARNING;
internal const bool DEFAULT_TEXTUREIMPORTER_WARNING = true;
public bool textureImporterWarning = DEFAULT_TEXTUREIMPORTER_WARNING;
internal const bool DEFAULT_COMPONENTMATERIAL_WARNING = true;
public bool componentMaterialWarning = DEFAULT_COMPONENTMATERIAL_WARNING;
public const float DEFAULT_MIPMAPBIAS = -0.5f;
public const bool DEFAULT_AUTO_RELOAD_SCENESKELETONS = true;
public bool autoReloadSceneSkeletons = DEFAULT_AUTO_RELOAD_SCENESKELETONS;
public const string SCENE_ICONS_SCALE_KEY = "SPINE_SCENE_ICONS_SCALE";
internal const float DEFAULT_SCENE_ICONS_SCALE = 1f;
[Range(0.01f, 2f)]
public float handleScale = DEFAULT_SCENE_ICONS_SCALE;
public const bool DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME = true;
public bool mecanimEventIncludeFolderName = DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME;
// Timeline extension module
public const bool DEFAULT_TIMELINE_USE_BLEND_DURATION = true;
public bool timelineUseBlendDuration = DEFAULT_TIMELINE_USE_BLEND_DURATION;
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static void Load () {
GetOrCreateSettings();
}
static SpinePreferences settings = null;
internal static SpinePreferences GetOrCreateSettings () {
if (settings != null)
return settings;
settings = AssetDatabase.LoadAssetAtPath<SpinePreferences>(SPINE_SETTINGS_ASSET_PATH);
if (settings == null)
settings = FindSpinePreferences();
if (settings == null) {
settings = ScriptableObject.CreateInstance<SpinePreferences>();
SpineEditorUtilities.OldPreferences.CopyOldToNewPreferences(ref settings);
// Multiple threads may be calling this method during import, creating the folder
// multiple times with ascending number suffix. Atomic wasPreferencesDirCreated int
// variable is used to prevent any redundant create operations.
if (!AssetDatabase.IsValidFolder("Assets/Editor") && Interlocked.Exchange(ref wasPreferencesDirCreated, 1) == 0)
AssetDatabase.CreateFolder("Assets", "Editor");
if (Interlocked.Exchange(ref wasPreferencesAssetCreated, 1) == 0)
AssetDatabase.CreateAsset(settings, SPINE_SETTINGS_ASSET_PATH);
}
#if HAS_ON_POSTPROCESS_PREFAB
SkeletonRenderer.fixPrefabOverrideViaMeshFilterGlobal = settings.fixPrefabOverrideViaMeshFilter;
#endif
return settings;
}
static SpinePreferences FindSpinePreferences () {
string typeSearchString = " t:SpinePreferences";
string[] guids = AssetDatabase.FindAssets(typeSearchString);
foreach (string guid in guids) {
string path = AssetDatabase.GUIDToAssetPath(guid);
var preferences = AssetDatabase.LoadAssetAtPath<SpinePreferences>(path);
if (preferences != null)
return preferences;
}
return null;
}
private static void ShowBlendModeMaterialProperty (SerializedProperty blendModeMaterialProperty,
string blendType, bool isTexturePresetPMA) {
EditorGUILayout.PropertyField(blendModeMaterialProperty, new GUIContent(blendType + " Material", blendType + " blend mode Material template."));
var material = blendModeMaterialProperty.objectReferenceValue as Material;
if (material == null)
return;
bool isMaterialPMA = MaterialChecks.IsPMATextureMaterial(material);
if (!isTexturePresetPMA && isMaterialPMA) {
EditorGUILayout.HelpBox(string.Format("'{0} Material' uses PMA but 'Atlas Texture Settings' uses Straight Alpha. " +
"You might want to assign 'SkeletonStraight{0}' instead.", blendType), MessageType.Warning);
} else if (isTexturePresetPMA && !isMaterialPMA) {
EditorGUILayout.HelpBox(string.Format("'{0} Material' uses Straight Alpha but 'Atlas Texture Settings' uses PMA. " +
"You might want to assign 'SkeletonPMA{0}' instead.", blendType), MessageType.Warning);
}
}
public static void HandlePreferencesGUI (SerializedObject settings) {
float prevLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 250;
using (new EditorGUI.IndentLevelScope()) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(settings.FindProperty("showHierarchyIcons"), new GUIContent("Show Hierarchy Icons", "Show relevant icons on GameObjects with Spine Components on them. Disable this if you have large, complex scenes."));
if (EditorGUI.EndChangeCheck()) {
#if NEWPLAYMODECALLBACKS
SpineEditorUtilities.HierarchyHandler.IconsOnPlaymodeStateChanged(PlayModeStateChange.EnteredEditMode);
#else
SpineEditorUtilities.HierarchyHandler.IconsOnPlaymodeStateChanged();
#endif
}
EditorGUILayout.PropertyField(settings.FindProperty("autoReloadSceneSkeletons"), new GUIContent("Auto-reload scene components", "Reloads Skeleton components in the scene whenever their SkeletonDataAsset is modified. This makes it so changes in the SkeletonData asset inspector are immediately reflected. This may be slow when your scenes have large numbers of SkeletonRenderers or SkeletonGraphic."));
EditorGUILayout.Separator();
EditorGUILayout.LabelField("Auto-Import Settings", EditorStyles.boldLabel);
{
SpineEditorUtilities.FloatPropertyField(settings.FindProperty("defaultMix"), new GUIContent("Default Mix", "The Default Mix Duration for newly imported SkeletonDataAssets."), min: 0f);
SpineEditorUtilities.FloatPropertyField(settings.FindProperty("defaultScale"), new GUIContent("Default SkeletonData Scale", "The Default skeleton import scale for newly imported SkeletonDataAssets."), min: 0.0000001f);
SpineEditorUtilities.ShaderPropertyField(settings.FindProperty("defaultShader"), new GUIContent("Default Shader"), SpinePreferences.DEFAULT_DEFAULT_SHADER);
EditorGUILayout.PropertyField(settings.FindProperty("setTextureImporterSettings"), new GUIContent("Apply Atlas Texture Settings", "Apply reference settings for Texture Importers."));
var textureSettingsRef = settings.FindProperty("textureSettingsReference");
SpineEditorUtilities.PresetAssetPropertyField(textureSettingsRef, new GUIContent("Atlas Texture Settings", "Apply the selected texture import settings at newly imported atlas textures. When exporting atlas textures from Spine with \"Premultiply alpha\" enabled (the default), you can leave it at \"PMATexturePreset\". If you have disabled \"Premultiply alpha\", set it to \"StraightAlphaTexturePreset\". You can also create your own TextureImporter Preset asset and assign it here."));
if (string.IsNullOrEmpty(textureSettingsRef.stringValue)) {
var pmaTextureSettingsReferenceGUIDS = AssetDatabase.FindAssets("PMATexturePreset");
if (pmaTextureSettingsReferenceGUIDS.Length > 0) {
var assetPath = AssetDatabase.GUIDToAssetPath(pmaTextureSettingsReferenceGUIDS[0]);
if (!string.IsNullOrEmpty(assetPath))
textureSettingsRef.stringValue = assetPath;
}
}
SerializedProperty blendModeMaterialAdditive = settings.FindProperty("blendModeMaterialAdditive");
SerializedProperty blendModeMaterialMultiply = settings.FindProperty("blendModeMaterialMultiply");
SerializedProperty blendModeMaterialScreen = settings.FindProperty("blendModeMaterialScreen");
bool isTexturePresetPMA = IsPMAWorkflow(textureSettingsRef.stringValue);
ShowBlendModeMaterialProperty(blendModeMaterialAdditive, "Additive", isTexturePresetPMA);
ShowBlendModeMaterialProperty(blendModeMaterialMultiply, "Multiply", isTexturePresetPMA);
ShowBlendModeMaterialProperty(blendModeMaterialScreen, "Screen", isTexturePresetPMA);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Warnings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(settings.FindProperty("atlasTxtImportWarning"), new GUIContent("Atlas Extension Warning", "Log a warning and recommendation whenever a `.atlas` file is found."));
EditorGUILayout.PropertyField(settings.FindProperty("textureImporterWarning"), new GUIContent("Texture Settings Warning", "Log a warning and recommendation whenever Texture Import Settings are detected that could lead to undesired effects, e.g. white border artifacts."));
EditorGUILayout.PropertyField(settings.FindProperty("componentMaterialWarning"), new GUIContent("Component & Material Warning", "Log a warning and recommendation whenever Component and Material settings are not compatible."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Editor Instantiation", EditorStyles.boldLabel);
{
EditorGUILayout.Slider(settings.FindProperty("defaultZSpacing"), -0.1f, 0f, new GUIContent("Default Slot Z-Spacing"));
EditorGUILayout.PropertyField(settings.FindProperty("defaultInstantiateLoop"), new GUIContent("Default Loop", "Spawn Spine GameObjects with loop enabled."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mecanim Bake Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(settings.FindProperty("mecanimEventIncludeFolderName"), new GUIContent("Include Folder Name in Event", "When enabled, Mecanim events will call methods named 'FolderNameEventName', when disabled it will call 'EventName'."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Handles and Gizmos", EditorStyles.boldLabel);
{
EditorGUI.BeginChangeCheck();
var scaleProperty = settings.FindProperty("handleScale");
EditorGUILayout.PropertyField(scaleProperty, new GUIContent("Editor Bone Scale"));
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetFloat(SpinePreferences.SCENE_ICONS_SCALE_KEY, scaleProperty.floatValue);
SceneView.RepaintAll();
}
}
#if HAS_ON_POSTPROCESS_PREFAB
EditorGUILayout.Space();
EditorGUILayout.LabelField("Prefabs", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(settings.FindProperty("fixPrefabOverrideViaMeshFilter"), new GUIContent("Fix Prefab Overr. MeshFilter", "Fixes the prefab always being marked as changed (sets the MeshFilter's hide flags to DontSaveInEditor), but at the cost of references to the MeshFilter by other components being lost. This is a global setting that can be overwritten on each SkeletonRenderer"));
SkeletonRenderer.fixPrefabOverrideViaMeshFilterGlobal = settings.FindProperty("fixPrefabOverrideViaMeshFilter").boolValue;
}
#endif
#if SPINE_TK2D_DEFINE
bool isTK2DDefineSet = true;
#else
bool isTK2DDefineSet = false;
#endif
bool isTK2DAllowed = SpineEditorUtilities.SpineTK2DEditorUtility.IsTK2DAllowed;
if (SpineEditorUtilities.SpineTK2DEditorUtility.IsTK2DInstalled() || isTK2DDefineSet) {
GUILayout.Space(20);
EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel);
using (new GUILayout.HorizontalScope()) {
EditorGUILayout.PrefixLabel("Define TK2D");
if (isTK2DAllowed && GUILayout.Button("Enable", GUILayout.Width(64)))
SpineEditorUtilities.SpineTK2DEditorUtility.EnableTK2D();
if (GUILayout.Button("Disable", GUILayout.Width(64)))
SpineEditorUtilities.SpineTK2DEditorUtility.DisableTK2D();
}
#if !SPINE_TK2D_DEFINE
if (!isTK2DAllowed) {
EditorGUILayout.LabelField("To allow TK2D support, please modify line 67 in", EditorStyles.boldLabel);
EditorGUILayout.LabelField("Spine/Editor/spine-unity/Editor/Util./BuildSettings.cs", EditorStyles.boldLabel);
}
#endif
}
GUILayout.Space(20);
EditorGUILayout.LabelField("Timeline Extension", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(settings.FindProperty("timelineUseBlendDuration"), new GUIContent("Use Blend Duration", "When enabled, MixDuration will be synced with timeline clip transition duration 'Ease In Duration'."));
}
}
EditorGUIUtility.labelWidth = prevLabelWidth;
}
#endif // NEW_PREFERENCES_SETTINGS_PROVIDER
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2017_2_OR_NEWER
#define NEWPLAYMODECALLBACKS
#endif
#if UNITY_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
#if UNITY_2020_2_OR_NEWER
#define HAS_ON_POSTPROCESS_PREFAB
#endif
using System.Threading;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
public class SpinePreferences : ScriptableObject {
#if NEW_PREFERENCES_SETTINGS_PROVIDER
static int wasPreferencesDirCreated = 0;
static int wasPreferencesAssetCreated = 0;
#endif
public const string SPINE_SETTINGS_ASSET_PATH = "Assets/Editor/SpineSettings.asset";
#if SPINE_TK2D
internal const float DEFAULT_DEFAULT_SCALE = 1f;
#else
internal const float DEFAULT_DEFAULT_SCALE = 0.01f;
#endif
public float defaultScale = DEFAULT_DEFAULT_SCALE;
internal const float DEFAULT_DEFAULT_MIX = 0.2f;
public float defaultMix = DEFAULT_DEFAULT_MIX;
internal const string DEFAULT_DEFAULT_SHADER = "Spine/Skeleton";
public string defaultShader = DEFAULT_DEFAULT_SHADER;
public string DefaultShader {
get { return !string.IsNullOrEmpty(defaultShader) ? defaultShader : DEFAULT_DEFAULT_SHADER; }
set { defaultShader = value; }
}
internal const float DEFAULT_DEFAULT_ZSPACING = 0f;
public float defaultZSpacing = DEFAULT_DEFAULT_ZSPACING;
internal const bool DEFAULT_DEFAULT_INSTANTIATE_LOOP = true;
public bool defaultInstantiateLoop = DEFAULT_DEFAULT_INSTANTIATE_LOOP;
internal const bool DEFAULT_SHOW_HIERARCHY_ICONS = true;
public bool showHierarchyIcons = DEFAULT_SHOW_HIERARCHY_ICONS;
internal const bool DEFAULT_SET_TEXTUREIMPORTER_SETTINGS = true;
public bool setTextureImporterSettings = DEFAULT_SET_TEXTUREIMPORTER_SETTINGS;
internal const string DEFAULT_TEXTURE_SETTINGS_REFERENCE = "";
public string textureSettingsReference = DEFAULT_TEXTURE_SETTINGS_REFERENCE;
#if HAS_ON_POSTPROCESS_PREFAB
internal const bool DEFAULT_FIX_PREFAB_OVERRIDE_VIA_MESH_FILTER = false;
public bool fixPrefabOverrideViaMeshFilter = DEFAULT_FIX_PREFAB_OVERRIDE_VIA_MESH_FILTER;
#endif
public bool UsesPMAWorkflow {
get {
return IsPMAWorkflow(textureSettingsReference);
}
}
public static bool IsPMAWorkflow (string textureSettingsReference) {
if (textureSettingsReference == null)
return true;
string settingsReference = textureSettingsReference.ToLower();
if (settingsReference.Contains("straight") || !settingsReference.Contains("pma"))
return false;
return true;
}
public const string DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL = "SkeletonPMAMultiply";
public const string DEFAULT_BLEND_MODE_SCREEN_MATERIAL = "SkeletonPMAScreen";
public const string DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL = "SkeletonPMAAdditive";
public Material blendModeMaterialMultiply = null;
public Material blendModeMaterialScreen = null;
public Material blendModeMaterialAdditive = null;
public string FindPathOfAsset (string assetName) {
string typeSearchString = assetName;
string[] guids = AssetDatabase.FindAssets(typeSearchString);
if (guids.Length > 0) {
return AssetDatabase.GUIDToAssetPath(guids[0]);
}
return null;
}
public Material BlendModeMaterialMultiply {
get {
if (blendModeMaterialMultiply == null) {
string path = FindPathOfAsset(DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL);
blendModeMaterialMultiply = AssetDatabase.LoadAssetAtPath<Material>(path);
}
return blendModeMaterialMultiply;
}
}
public Material BlendModeMaterialScreen {
get {
if (blendModeMaterialScreen == null) {
string path = FindPathOfAsset(DEFAULT_BLEND_MODE_SCREEN_MATERIAL);
blendModeMaterialScreen = AssetDatabase.LoadAssetAtPath<Material>(path);
}
return blendModeMaterialScreen;
}
}
public Material BlendModeMaterialAdditive {
get {
if (blendModeMaterialAdditive == null) {
string path = FindPathOfAsset(DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL);
blendModeMaterialAdditive = AssetDatabase.LoadAssetAtPath<Material>(path);
}
return blendModeMaterialAdditive;
}
}
internal const bool DEFAULT_ATLASTXT_WARNING = true;
public bool atlasTxtImportWarning = DEFAULT_ATLASTXT_WARNING;
internal const bool DEFAULT_TEXTUREIMPORTER_WARNING = true;
public bool textureImporterWarning = DEFAULT_TEXTUREIMPORTER_WARNING;
internal const bool DEFAULT_COMPONENTMATERIAL_WARNING = true;
public bool componentMaterialWarning = DEFAULT_COMPONENTMATERIAL_WARNING;
public const float DEFAULT_MIPMAPBIAS = -0.5f;
public const bool DEFAULT_AUTO_RELOAD_SCENESKELETONS = true;
public bool autoReloadSceneSkeletons = DEFAULT_AUTO_RELOAD_SCENESKELETONS;
public const string SCENE_ICONS_SCALE_KEY = "SPINE_SCENE_ICONS_SCALE";
internal const float DEFAULT_SCENE_ICONS_SCALE = 1f;
[Range(0.01f, 2f)]
public float handleScale = DEFAULT_SCENE_ICONS_SCALE;
public const bool DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME = true;
public bool mecanimEventIncludeFolderName = DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME;
// Timeline extension module
public const bool DEFAULT_TIMELINE_USE_BLEND_DURATION = true;
public bool timelineUseBlendDuration = DEFAULT_TIMELINE_USE_BLEND_DURATION;
#if NEW_PREFERENCES_SETTINGS_PROVIDER
public static void Load () {
GetOrCreateSettings();
}
static SpinePreferences settings = null;
internal static SpinePreferences GetOrCreateSettings () {
if (settings != null)
return settings;
settings = AssetDatabase.LoadAssetAtPath<SpinePreferences>(SPINE_SETTINGS_ASSET_PATH);
if (settings == null)
settings = FindSpinePreferences();
if (settings == null) {
settings = ScriptableObject.CreateInstance<SpinePreferences>();
SpineEditorUtilities.OldPreferences.CopyOldToNewPreferences(ref settings);
// Multiple threads may be calling this method during import, creating the folder
// multiple times with ascending number suffix. Atomic wasPreferencesDirCreated int
// variable is used to prevent any redundant create operations.
if (!AssetDatabase.IsValidFolder("Assets/Editor") && Interlocked.Exchange(ref wasPreferencesDirCreated, 1) == 0)
AssetDatabase.CreateFolder("Assets", "Editor");
if (Interlocked.Exchange(ref wasPreferencesAssetCreated, 1) == 0)
AssetDatabase.CreateAsset(settings, SPINE_SETTINGS_ASSET_PATH);
}
#if HAS_ON_POSTPROCESS_PREFAB
SkeletonRenderer.fixPrefabOverrideViaMeshFilterGlobal = settings.fixPrefabOverrideViaMeshFilter;
#endif
return settings;
}
static SpinePreferences FindSpinePreferences () {
string typeSearchString = " t:SpinePreferences";
string[] guids = AssetDatabase.FindAssets(typeSearchString);
foreach (string guid in guids) {
string path = AssetDatabase.GUIDToAssetPath(guid);
var preferences = AssetDatabase.LoadAssetAtPath<SpinePreferences>(path);
if (preferences != null)
return preferences;
}
return null;
}
private static void ShowBlendModeMaterialProperty (SerializedProperty blendModeMaterialProperty,
string blendType, bool isTexturePresetPMA) {
EditorGUILayout.PropertyField(blendModeMaterialProperty, new GUIContent(blendType + " Material", blendType + " blend mode Material template."));
var material = blendModeMaterialProperty.objectReferenceValue as Material;
if (material == null)
return;
bool isMaterialPMA = MaterialChecks.IsPMATextureMaterial(material);
if (!isTexturePresetPMA && isMaterialPMA) {
EditorGUILayout.HelpBox(string.Format("'{0} Material' uses PMA but 'Atlas Texture Settings' uses Straight Alpha. " +
"You might want to assign 'SkeletonStraight{0}' instead.", blendType), MessageType.Warning);
} else if (isTexturePresetPMA && !isMaterialPMA) {
EditorGUILayout.HelpBox(string.Format("'{0} Material' uses Straight Alpha but 'Atlas Texture Settings' uses PMA. " +
"You might want to assign 'SkeletonPMA{0}' instead.", blendType), MessageType.Warning);
}
}
public static void HandlePreferencesGUI (SerializedObject settings) {
float prevLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 250;
using (new EditorGUI.IndentLevelScope()) {
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(settings.FindProperty("showHierarchyIcons"), new GUIContent("Show Hierarchy Icons", "Show relevant icons on GameObjects with Spine Components on them. Disable this if you have large, complex scenes."));
if (EditorGUI.EndChangeCheck()) {
#if NEWPLAYMODECALLBACKS
SpineEditorUtilities.HierarchyHandler.IconsOnPlaymodeStateChanged(PlayModeStateChange.EnteredEditMode);
#else
SpineEditorUtilities.HierarchyHandler.IconsOnPlaymodeStateChanged();
#endif
}
EditorGUILayout.PropertyField(settings.FindProperty("autoReloadSceneSkeletons"), new GUIContent("Auto-reload scene components", "Reloads Skeleton components in the scene whenever their SkeletonDataAsset is modified. This makes it so changes in the SkeletonData asset inspector are immediately reflected. This may be slow when your scenes have large numbers of SkeletonRenderers or SkeletonGraphic."));
EditorGUILayout.Separator();
EditorGUILayout.LabelField("Auto-Import Settings", EditorStyles.boldLabel);
{
SpineEditorUtilities.FloatPropertyField(settings.FindProperty("defaultMix"), new GUIContent("Default Mix", "The Default Mix Duration for newly imported SkeletonDataAssets."), min: 0f);
SpineEditorUtilities.FloatPropertyField(settings.FindProperty("defaultScale"), new GUIContent("Default SkeletonData Scale", "The Default skeleton import scale for newly imported SkeletonDataAssets."), min: 0.0000001f);
SpineEditorUtilities.ShaderPropertyField(settings.FindProperty("defaultShader"), new GUIContent("Default Shader"), SpinePreferences.DEFAULT_DEFAULT_SHADER);
EditorGUILayout.PropertyField(settings.FindProperty("setTextureImporterSettings"), new GUIContent("Apply Atlas Texture Settings", "Apply reference settings for Texture Importers."));
var textureSettingsRef = settings.FindProperty("textureSettingsReference");
SpineEditorUtilities.PresetAssetPropertyField(textureSettingsRef, new GUIContent("Atlas Texture Settings", "Apply the selected texture import settings at newly imported atlas textures. When exporting atlas textures from Spine with \"Premultiply alpha\" enabled (the default), you can leave it at \"PMATexturePreset\". If you have disabled \"Premultiply alpha\", set it to \"StraightAlphaTexturePreset\". You can also create your own TextureImporter Preset asset and assign it here."));
if (string.IsNullOrEmpty(textureSettingsRef.stringValue)) {
var pmaTextureSettingsReferenceGUIDS = AssetDatabase.FindAssets("PMATexturePreset");
if (pmaTextureSettingsReferenceGUIDS.Length > 0) {
var assetPath = AssetDatabase.GUIDToAssetPath(pmaTextureSettingsReferenceGUIDS[0]);
if (!string.IsNullOrEmpty(assetPath))
textureSettingsRef.stringValue = assetPath;
}
}
SerializedProperty blendModeMaterialAdditive = settings.FindProperty("blendModeMaterialAdditive");
SerializedProperty blendModeMaterialMultiply = settings.FindProperty("blendModeMaterialMultiply");
SerializedProperty blendModeMaterialScreen = settings.FindProperty("blendModeMaterialScreen");
bool isTexturePresetPMA = IsPMAWorkflow(textureSettingsRef.stringValue);
ShowBlendModeMaterialProperty(blendModeMaterialAdditive, "Additive", isTexturePresetPMA);
ShowBlendModeMaterialProperty(blendModeMaterialMultiply, "Multiply", isTexturePresetPMA);
ShowBlendModeMaterialProperty(blendModeMaterialScreen, "Screen", isTexturePresetPMA);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Warnings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(settings.FindProperty("atlasTxtImportWarning"), new GUIContent("Atlas Extension Warning", "Log a warning and recommendation whenever a `.atlas` file is found."));
EditorGUILayout.PropertyField(settings.FindProperty("textureImporterWarning"), new GUIContent("Texture Settings Warning", "Log a warning and recommendation whenever Texture Import Settings are detected that could lead to undesired effects, e.g. white border artifacts."));
EditorGUILayout.PropertyField(settings.FindProperty("componentMaterialWarning"), new GUIContent("Component & Material Warning", "Log a warning and recommendation whenever Component and Material settings are not compatible."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Editor Instantiation", EditorStyles.boldLabel);
{
EditorGUILayout.Slider(settings.FindProperty("defaultZSpacing"), -0.1f, 0f, new GUIContent("Default Slot Z-Spacing"));
EditorGUILayout.PropertyField(settings.FindProperty("defaultInstantiateLoop"), new GUIContent("Default Loop", "Spawn Spine GameObjects with loop enabled."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mecanim Bake Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(settings.FindProperty("mecanimEventIncludeFolderName"), new GUIContent("Include Folder Name in Event", "When enabled, Mecanim events will call methods named 'FolderNameEventName', when disabled it will call 'EventName'."));
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Handles and Gizmos", EditorStyles.boldLabel);
{
EditorGUI.BeginChangeCheck();
var scaleProperty = settings.FindProperty("handleScale");
EditorGUILayout.PropertyField(scaleProperty, new GUIContent("Editor Bone Scale"));
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetFloat(SpinePreferences.SCENE_ICONS_SCALE_KEY, scaleProperty.floatValue);
SceneView.RepaintAll();
}
}
#if HAS_ON_POSTPROCESS_PREFAB
EditorGUILayout.Space();
EditorGUILayout.LabelField("Prefabs", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(settings.FindProperty("fixPrefabOverrideViaMeshFilter"), new GUIContent("Fix Prefab Overr. MeshFilter", "Fixes the prefab always being marked as changed (sets the MeshFilter's hide flags to DontSaveInEditor), but at the cost of references to the MeshFilter by other components being lost. This is a global setting that can be overwritten on each SkeletonRenderer"));
SkeletonRenderer.fixPrefabOverrideViaMeshFilterGlobal = settings.FindProperty("fixPrefabOverrideViaMeshFilter").boolValue;
}
#endif
#if SPINE_TK2D_DEFINE
bool isTK2DDefineSet = true;
#else
bool isTK2DDefineSet = false;
#endif
bool isTK2DAllowed = SpineEditorUtilities.SpineTK2DEditorUtility.IsTK2DAllowed;
if (SpineEditorUtilities.SpineTK2DEditorUtility.IsTK2DInstalled() || isTK2DDefineSet) {
GUILayout.Space(20);
EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel);
using (new GUILayout.HorizontalScope()) {
EditorGUILayout.PrefixLabel("Define TK2D");
if (isTK2DAllowed && GUILayout.Button("Enable", GUILayout.Width(64)))
SpineEditorUtilities.SpineTK2DEditorUtility.EnableTK2D();
if (GUILayout.Button("Disable", GUILayout.Width(64)))
SpineEditorUtilities.SpineTK2DEditorUtility.DisableTK2D();
}
#if !SPINE_TK2D_DEFINE
if (!isTK2DAllowed) {
EditorGUILayout.LabelField("To allow TK2D support, please modify line 67 in", EditorStyles.boldLabel);
EditorGUILayout.LabelField("Spine/Editor/spine-unity/Editor/Util./BuildSettings.cs", EditorStyles.boldLabel);
}
#endif
}
GUILayout.Space(20);
EditorGUILayout.LabelField("Timeline Extension", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(settings.FindProperty("timelineUseBlendDuration"), new GUIContent("Use Blend Duration", "When enabled, MixDuration will be synced with timeline clip transition duration 'Ease In Duration'."));
}
}
EditorGUIUtility.labelWidth = prevLabelWidth;
}
#endif // NEW_PREFERENCES_SETTINGS_PROVIDER
}
}

View File

@@ -1,168 +1,168 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
using Icons = SpineEditorUtilities.Icons;
public class SpriteAtlasImportWindow : EditorWindow {
const bool IsUtilityWindow = false;
[MenuItem("Window/Spine/SpriteAtlas Import", false, 5000)]
public static void Init (MenuCommand command) {
var window = EditorWindow.GetWindow<SpriteAtlasImportWindow>(IsUtilityWindow);
window.minSize = new Vector2(284f, 256f);
window.maxSize = new Vector2(500f, 256f);
window.titleContent = new GUIContent("Spine SpriteAtlas Import", Icons.spine);
window.Show();
}
public UnityEngine.U2D.SpriteAtlas spriteAtlasAsset;
public TextAsset skeletonDataFile;
public SpineSpriteAtlasAsset spineSpriteAtlasAsset;
SerializedObject so;
void OnEnable () {
if (!SpineSpriteAtlasAsset.AnySpriteAtlasNeedsRegionsLoaded())
return;
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
EditorApplication.update += SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
}
void OnDisable () {
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
}
void OnGUI () {
so = so ?? new SerializedObject(this);
EditorGUIUtility.wideMode = true;
EditorGUILayout.LabelField("Spine SpriteAtlas Import", EditorStyles.boldLabel);
using (new SpineInspectorUtility.BoxScope()) {
EditorGUI.BeginChangeCheck();
var spriteAtlasAssetProperty = so.FindProperty("spriteAtlasAsset");
EditorGUILayout.PropertyField(spriteAtlasAssetProperty, new GUIContent("SpriteAtlas", EditorGUIUtility.IconContent("SpriteAtlas Icon").image));
if (EditorGUI.EndChangeCheck()) {
so.ApplyModifiedProperties();
if (spriteAtlasAsset != null) {
if (AssetUtility.SpriteAtlasSettingsNeedAdjustment(spriteAtlasAsset)) {
AssetUtility.AdjustSpriteAtlasSettings(spriteAtlasAsset);
}
GenerateAssetsFromSpriteAtlas(spriteAtlasAsset);
}
}
var spineSpriteAtlasAssetProperty = so.FindProperty("spineSpriteAtlasAsset");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(spineSpriteAtlasAssetProperty, new GUIContent("SpineSpriteAtlasAsset", EditorGUIUtility.IconContent("ScriptableObject Icon").image));
if (spineSpriteAtlasAssetProperty.objectReferenceValue == null) {
spineSpriteAtlasAssetProperty.objectReferenceValue = spineSpriteAtlasAsset = FindSpineSpriteAtlasAsset(spriteAtlasAsset);
}
if (EditorGUI.EndChangeCheck()) {
so.ApplyModifiedProperties();
}
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(spineSpriteAtlasAsset == null)) {
if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Load regions by entering Play mode"))) {
GenerateAssetsFromSpriteAtlas(spriteAtlasAsset);
SpineSpriteAtlasAsset.UpdateByStartingEditorPlayMode();
}
}
using (new SpineInspectorUtility.BoxScope()) {
if (spriteAtlasAsset == null) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Please assign SpriteAtlas file.", Icons.warning), GUILayout.Height(46));
} else if (spineSpriteAtlasAsset == null || spineSpriteAtlasAsset.RegionsNeedLoading) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Please hit 'Load regions ..' to load\nregion info. Play mode is started\nand stopped automatically.", Icons.warning), GUILayout.Height(54));
} else {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("SpriteAtlas imported\nsuccessfully.", Icons.spine), GUILayout.Height(46));
}
}
}
bool isAtlasComplete = (spineSpriteAtlasAsset != null && !spineSpriteAtlasAsset.RegionsNeedLoading);
bool canImportSkeleton = (spriteAtlasAsset != null && skeletonDataFile != null);
using (new SpineInspectorUtility.BoxScope()) {
using (new EditorGUI.DisabledScope(!isAtlasComplete)) {
var skeletonDataAssetProperty = so.FindProperty("skeletonDataFile");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(skeletonDataAssetProperty, SpineInspectorUtility.TempContent("Skeleton json/skel file", Icons.spine));
if (EditorGUI.EndChangeCheck()) {
so.ApplyModifiedProperties();
}
EditorGUILayout.Space();
}
using (new EditorGUI.DisabledScope(!canImportSkeleton)) {
if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Import Skeleton"))) {
//AssetUtility.IngestSpriteAtlas(spriteAtlasAsset, null);
string skeletonPath = AssetDatabase.GetAssetPath(skeletonDataFile);
string[] skeletons = new string[] { skeletonPath };
AssetUtility.ImportSpineContent(skeletons, null);
}
}
}
}
void GenerateAssetsFromSpriteAtlas (UnityEngine.U2D.SpriteAtlas spriteAtlasAsset) {
AssetUtility.IngestSpriteAtlas(spriteAtlasAsset, null);
string texturePath;
if (AssetUtility.GeneratePngFromSpriteAtlas(spriteAtlasAsset, out texturePath)) {
Debug.Log(string.Format("Generated SpriteAtlas texture '{0}'", texturePath), spriteAtlasAsset);
}
}
SpineSpriteAtlasAsset FindSpineSpriteAtlasAsset (UnityEngine.U2D.SpriteAtlas spriteAtlasAsset) {
string path = AssetDatabase.GetAssetPath(spriteAtlasAsset).Replace(".spriteatlas", AssetUtility.SpriteAtlasSuffix + ".asset");
if (System.IO.File.Exists(path)) {
return AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(path);
}
return null;
}
SkeletonDataAsset FindSkeletonDataAsset (TextAsset skeletonDataFile) {
string path = AssetDatabase.GetAssetPath(skeletonDataFile);
path = path.Replace(".json", AssetUtility.SkeletonDataSuffix + ".asset");
path = path.Replace(".skel.bytes", AssetUtility.SkeletonDataSuffix + ".asset");
if (System.IO.File.Exists(path)) {
return AssetDatabase.LoadAssetAtPath<SkeletonDataAsset>(path);
}
return null;
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor;
using Icons = SpineEditorUtilities.Icons;
public class SpriteAtlasImportWindow : EditorWindow {
const bool IsUtilityWindow = false;
[MenuItem("Window/Spine/SpriteAtlas Import", false, 5000)]
public static void Init (MenuCommand command) {
var window = EditorWindow.GetWindow<SpriteAtlasImportWindow>(IsUtilityWindow);
window.minSize = new Vector2(284f, 256f);
window.maxSize = new Vector2(500f, 256f);
window.titleContent = new GUIContent("Spine SpriteAtlas Import", Icons.spine);
window.Show();
}
public UnityEngine.U2D.SpriteAtlas spriteAtlasAsset;
public TextAsset skeletonDataFile;
public SpineSpriteAtlasAsset spineSpriteAtlasAsset;
SerializedObject so;
void OnEnable () {
if (!SpineSpriteAtlasAsset.AnySpriteAtlasNeedsRegionsLoaded())
return;
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
EditorApplication.update += SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
}
void OnDisable () {
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
}
void OnGUI () {
so = so ?? new SerializedObject(this);
EditorGUIUtility.wideMode = true;
EditorGUILayout.LabelField("Spine SpriteAtlas Import", EditorStyles.boldLabel);
using (new SpineInspectorUtility.BoxScope()) {
EditorGUI.BeginChangeCheck();
var spriteAtlasAssetProperty = so.FindProperty("spriteAtlasAsset");
EditorGUILayout.PropertyField(spriteAtlasAssetProperty, new GUIContent("SpriteAtlas", EditorGUIUtility.IconContent("SpriteAtlas Icon").image));
if (EditorGUI.EndChangeCheck()) {
so.ApplyModifiedProperties();
if (spriteAtlasAsset != null) {
if (AssetUtility.SpriteAtlasSettingsNeedAdjustment(spriteAtlasAsset)) {
AssetUtility.AdjustSpriteAtlasSettings(spriteAtlasAsset);
}
GenerateAssetsFromSpriteAtlas(spriteAtlasAsset);
}
}
var spineSpriteAtlasAssetProperty = so.FindProperty("spineSpriteAtlasAsset");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(spineSpriteAtlasAssetProperty, new GUIContent("SpineSpriteAtlasAsset", EditorGUIUtility.IconContent("ScriptableObject Icon").image));
if (spineSpriteAtlasAssetProperty.objectReferenceValue == null) {
spineSpriteAtlasAssetProperty.objectReferenceValue = spineSpriteAtlasAsset = FindSpineSpriteAtlasAsset(spriteAtlasAsset);
}
if (EditorGUI.EndChangeCheck()) {
so.ApplyModifiedProperties();
}
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(spineSpriteAtlasAsset == null)) {
if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Load regions by entering Play mode"))) {
GenerateAssetsFromSpriteAtlas(spriteAtlasAsset);
SpineSpriteAtlasAsset.UpdateByStartingEditorPlayMode();
}
}
using (new SpineInspectorUtility.BoxScope()) {
if (spriteAtlasAsset == null) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Please assign SpriteAtlas file.", Icons.warning), GUILayout.Height(46));
} else if (spineSpriteAtlasAsset == null || spineSpriteAtlasAsset.RegionsNeedLoading) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Please hit 'Load regions ..' to load\nregion info. Play mode is started\nand stopped automatically.", Icons.warning), GUILayout.Height(54));
} else {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("SpriteAtlas imported\nsuccessfully.", Icons.spine), GUILayout.Height(46));
}
}
}
bool isAtlasComplete = (spineSpriteAtlasAsset != null && !spineSpriteAtlasAsset.RegionsNeedLoading);
bool canImportSkeleton = (spriteAtlasAsset != null && skeletonDataFile != null);
using (new SpineInspectorUtility.BoxScope()) {
using (new EditorGUI.DisabledScope(!isAtlasComplete)) {
var skeletonDataAssetProperty = so.FindProperty("skeletonDataFile");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(skeletonDataAssetProperty, SpineInspectorUtility.TempContent("Skeleton json/skel file", Icons.spine));
if (EditorGUI.EndChangeCheck()) {
so.ApplyModifiedProperties();
}
EditorGUILayout.Space();
}
using (new EditorGUI.DisabledScope(!canImportSkeleton)) {
if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Import Skeleton"))) {
//AssetUtility.IngestSpriteAtlas(spriteAtlasAsset, null);
string skeletonPath = AssetDatabase.GetAssetPath(skeletonDataFile);
string[] skeletons = new string[] { skeletonPath };
AssetUtility.ImportSpineContent(skeletons, null);
}
}
}
}
void GenerateAssetsFromSpriteAtlas (UnityEngine.U2D.SpriteAtlas spriteAtlasAsset) {
AssetUtility.IngestSpriteAtlas(spriteAtlasAsset, null);
string texturePath;
if (AssetUtility.GeneratePngFromSpriteAtlas(spriteAtlasAsset, out texturePath)) {
Debug.Log(string.Format("Generated SpriteAtlas texture '{0}'", texturePath), spriteAtlasAsset);
}
}
SpineSpriteAtlasAsset FindSpineSpriteAtlasAsset (UnityEngine.U2D.SpriteAtlas spriteAtlasAsset) {
string path = AssetDatabase.GetAssetPath(spriteAtlasAsset).Replace(".spriteatlas", AssetUtility.SpriteAtlasSuffix + ".asset");
if (System.IO.File.Exists(path)) {
return AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(path);
}
return null;
}
SkeletonDataAsset FindSkeletonDataAsset (TextAsset skeletonDataFile) {
string path = AssetDatabase.GetAssetPath(skeletonDataFile);
path = path.Replace(".json", AssetUtility.SkeletonDataSuffix + ".asset");
path = path.Replace(".skel.bytes", AssetUtility.SkeletonDataSuffix + ".asset");
if (System.IO.File.Exists(path)) {
return AssetDatabase.LoadAssetAtPath<SkeletonDataAsset>(path);
}
return null;
}
}
}

View File

@@ -1,58 +1,58 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine.Unity.Editor;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Examples {
[CustomEditor(typeof(SkeletonPartsRenderer))]
public class SkeletonRenderPartInspector : UnityEditor.Editor {
SpineInspectorUtility.SerializedSortingProperties sortingProperties;
void OnEnable () {
sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(SpineInspectorUtility.GetRenderersSerializedObject(serializedObject));
}
public override void OnInspectorGUI () {
SpineInspectorUtility.SortingPropertyFields(sortingProperties, true);
if (!serializedObject.isEditingMultipleObjects) {
EditorGUILayout.Space();
if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Select SkeletonRenderer", SpineEditorUtilities.Icons.spine))) {
var thisSkeletonPartsRenderer = target as SkeletonPartsRenderer;
var srs = thisSkeletonPartsRenderer.GetComponentInParent<SkeletonRenderSeparator>();
if (srs != null && srs.partsRenderers.Contains(thisSkeletonPartsRenderer) && srs.SkeletonRenderer != null)
Selection.activeGameObject = srs.SkeletonRenderer.gameObject;
}
}
}
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using Spine.Unity.Editor;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Examples {
[CustomEditor(typeof(SkeletonPartsRenderer))]
public class SkeletonRenderPartInspector : UnityEditor.Editor {
SpineInspectorUtility.SerializedSortingProperties sortingProperties;
void OnEnable () {
sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(SpineInspectorUtility.GetRenderersSerializedObject(serializedObject));
}
public override void OnInspectorGUI () {
SpineInspectorUtility.SortingPropertyFields(sortingProperties, true);
if (!serializedObject.isEditingMultipleObjects) {
EditorGUILayout.Space();
if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Select SkeletonRenderer", SpineEditorUtilities.Icons.spine))) {
var thisSkeletonPartsRenderer = target as SkeletonPartsRenderer;
var srs = thisSkeletonPartsRenderer.GetComponentInParent<SkeletonRenderSeparator>();
if (srs != null && srs.partsRenderers.Contains(thisSkeletonPartsRenderer) && srs.SkeletonRenderer != null)
Selection.activeGameObject = srs.SkeletonRenderer.gameObject;
}
}
}
}
}

View File

@@ -1,321 +1,321 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
using Spine.Unity;
using Spine.Unity.Editor;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Examples {
[CustomEditor(typeof(SkeletonRenderSeparator))]
public class SkeletonRenderSeparatorInspector : UnityEditor.Editor {
SkeletonRenderSeparator component;
// Properties
SerializedProperty skeletonRenderer_, copyPropertyBlock_, copyMeshRendererFlags_, partsRenderers_;
static bool partsRenderersExpanded = false;
// For separator field.
SerializedObject skeletonRendererSerializedObject;
SerializedProperty separatorNamesProp;
static bool skeletonRendererExpanded = true;
bool slotsReapplyRequired = false;
bool partsRendererInitRequired = false;
void OnEnable () {
if (component == null)
component = target as SkeletonRenderSeparator;
skeletonRenderer_ = serializedObject.FindProperty("skeletonRenderer");
copyPropertyBlock_ = serializedObject.FindProperty("copyPropertyBlock");
copyMeshRendererFlags_ = serializedObject.FindProperty("copyMeshRendererFlags");
var partsRenderers = component.partsRenderers;
partsRenderers_ = serializedObject.FindProperty("partsRenderers");
partsRenderers_.isExpanded = partsRenderersExpanded || // last state
partsRenderers.Contains(null) || // null items found
partsRenderers.Count < 1 || // no parts renderers
(skeletonRenderer_.objectReferenceValue != null && SkeletonRendererSeparatorCount + 1 > partsRenderers.Count); // not enough parts renderers
}
int SkeletonRendererSeparatorCount {
get {
if (Application.isPlaying)
return component.SkeletonRenderer.separatorSlots.Count;
else
return separatorNamesProp == null ? 0 : separatorNamesProp.arraySize;
}
}
public override void OnInspectorGUI () {
// Restore mesh part for undo logic after undo of "Add Parts Renderer".
// Triggers regeneration and assignment of the mesh filter's mesh.
bool isMeshFilterAlwaysNull = false;
#if UNITY_EDITOR && NEW_PREFAB_SYSTEM
// Don't store mesh or material at the prefab, otherwise it will permanently reload
var prefabType = UnityEditor.PrefabUtility.GetPrefabAssetType(component);
if (UnityEditor.PrefabUtility.IsPartOfPrefabAsset(component) &&
(prefabType == UnityEditor.PrefabAssetType.Regular || prefabType == UnityEditor.PrefabAssetType.Variant)) {
isMeshFilterAlwaysNull = true;
}
#endif
if (!isMeshFilterAlwaysNull && component.GetComponent<MeshFilter>() && component.GetComponent<MeshFilter>().sharedMesh == null) {
component.OnDisable();
component.OnEnable();
}
var componentRenderers = component.partsRenderers;
int totalParts;
using (new SpineInspectorUtility.LabelWidthScope()) {
bool componentEnabled = component.enabled;
bool checkBox = EditorGUILayout.Toggle("Enable Separator", componentEnabled);
if (checkBox != componentEnabled)
component.enabled = checkBox;
if (component.SkeletonRenderer.disableRenderingOnOverride && !component.enabled)
EditorGUILayout.HelpBox("By default, SkeletonRenderer's MeshRenderer is disabled while the SkeletonRenderSeparator takes over rendering. It is re-enabled when SkeletonRenderSeparator is disabled.", MessageType.Info);
EditorGUILayout.PropertyField(copyPropertyBlock_);
EditorGUILayout.PropertyField(copyMeshRendererFlags_);
}
// SkeletonRenderer Box
using (new SpineInspectorUtility.BoxScope(false)) {
// Fancy SkeletonRenderer foldout reference field
{
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
var foldoutSkeletonRendererRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
EditorGUI.PropertyField(foldoutSkeletonRendererRect, skeletonRenderer_);
if (EditorGUI.EndChangeCheck())
serializedObject.ApplyModifiedProperties();
if (component.SkeletonRenderer != null) {
skeletonRendererExpanded = EditorGUI.Foldout(foldoutSkeletonRendererRect, skeletonRendererExpanded, "");
}
EditorGUI.indentLevel--;
}
int separatorCount = 0;
EditorGUI.BeginChangeCheck();
if (component.SkeletonRenderer != null) {
// Separators from SkeletonRenderer
{
bool skeletonRendererMismatch = skeletonRendererSerializedObject != null && skeletonRendererSerializedObject.targetObject != component.SkeletonRenderer;
if (separatorNamesProp == null || skeletonRendererMismatch) {
if (component.SkeletonRenderer != null) {
skeletonRendererSerializedObject = new SerializedObject(component.SkeletonRenderer);
separatorNamesProp = skeletonRendererSerializedObject.FindProperty("separatorSlotNames");
separatorNamesProp.isExpanded = true;
}
}
if (separatorNamesProp != null) {
if (skeletonRendererExpanded) {
EditorGUI.indentLevel++;
SkeletonRendererInspector.SeparatorsField(separatorNamesProp);
EditorGUI.indentLevel--;
}
separatorCount = this.SkeletonRendererSeparatorCount;
}
}
if (SkeletonRendererSeparatorCount == 0) {
EditorGUILayout.HelpBox("Separators are empty. Change the size to 1 and choose a slot if you want the render to be separated.", MessageType.Info);
}
}
if (EditorGUI.EndChangeCheck()) {
skeletonRendererSerializedObject.ApplyModifiedProperties();
if (!Application.isPlaying)
slotsReapplyRequired = true;
}
totalParts = separatorCount + 1;
var counterStyle = skeletonRendererExpanded ? EditorStyles.label : EditorStyles.miniLabel;
EditorGUILayout.LabelField(string.Format("{0}: separates into {1}.", SpineInspectorUtility.Pluralize(separatorCount, "separator", "separators"), SpineInspectorUtility.Pluralize(totalParts, "part", "parts")), counterStyle);
}
// Parts renderers
using (new SpineInspectorUtility.BoxScope(false)) {
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(this.partsRenderers_, true);
EditorGUI.indentLevel--;
// Null items warning
bool nullItemsFound = componentRenderers.Contains(null);
if (nullItemsFound)
EditorGUILayout.HelpBox("Some items in the parts renderers list are null and may cause problems.\n\nYou can right-click on that element and choose 'Delete Array Element' to remove it.", MessageType.Warning);
// (Button) Match Separators count
if (separatorNamesProp != null) {
int currentRenderers = 0;
foreach (var r in componentRenderers) {
if (r != null)
currentRenderers++;
}
int extraRenderersNeeded = totalParts - currentRenderers;
if (component.enabled && component.SkeletonRenderer != null && extraRenderersNeeded > 0) {
EditorGUILayout.HelpBox(string.Format("Insufficient parts renderers. Some parts will not be rendered."), MessageType.Warning);
string addMissingLabel = string.Format("Add the missing renderer{1} ({0}) ", extraRenderersNeeded, SpineInspectorUtility.PluralThenS(extraRenderersNeeded));
if (GUILayout.Button(addMissingLabel, GUILayout.Height(30f))) {
AddPartsRenderer(extraRenderersNeeded);
DetectOrphanedPartsRenderers(component);
partsRendererInitRequired = true;
}
}
}
if (partsRenderers_.isExpanded != partsRenderersExpanded) partsRenderersExpanded = partsRenderers_.isExpanded;
if (partsRenderers_.isExpanded) {
using (new EditorGUILayout.HorizontalScope()) {
// (Button) Destroy Renderers button
if (componentRenderers.Count > 0) {
if (GUILayout.Button("Clear Parts Renderers")) {
// Do you really want to destroy all?
Undo.RegisterCompleteObjectUndo(component, "Clear Parts Renderers");
if (EditorUtility.DisplayDialog("Destroy Renderers", "Do you really want to destroy all the Parts Renderer GameObjects in the list?", "Destroy", "Cancel")) {
foreach (var r in componentRenderers) {
if (r != null)
Undo.DestroyObjectImmediate(r.gameObject);
}
componentRenderers.Clear();
// Do you also want to destroy orphans? (You monster.)
DetectOrphanedPartsRenderers(component);
}
}
}
// (Button) Add Part Renderer button
if (GUILayout.Button("Add Parts Renderer")) {
AddPartsRenderer(1);
partsRendererInitRequired = true;
}
}
}
}
serializedObject.ApplyModifiedProperties();
if (partsRendererInitRequired) {
Undo.RegisterCompleteObjectUndo(component.GetComponent<MeshRenderer>(), "Add Parts Renderers");
component.OnEnable();
partsRendererInitRequired = false;
}
if (slotsReapplyRequired && UnityEngine.Event.current.type == EventType.Repaint) {
component.SkeletonRenderer.ReapplySeparatorSlotNames();
component.SkeletonRenderer.LateUpdate();
SceneView.RepaintAll();
slotsReapplyRequired = false;
}
}
public void AddPartsRenderer (int count) {
var componentRenderers = component.partsRenderers;
bool emptyFound = componentRenderers.Contains(null);
if (emptyFound) {
bool userClearEntries = EditorUtility.DisplayDialog("Empty entries found", "Null entries found. Do you want to remove null entries before adding the new renderer? ", "Clear Empty Entries", "Don't Clear");
if (userClearEntries) componentRenderers.RemoveAll(x => x == null);
}
Undo.RegisterCompleteObjectUndo(component, "Add Parts Renderers");
for (int i = 0; i < count; i++) {
int index = componentRenderers.Count;
var smr = SkeletonPartsRenderer.NewPartsRendererGameObject(component.transform, index.ToString());
Undo.RegisterCreatedObjectUndo(smr.gameObject, "New Parts Renderer GameObject.");
componentRenderers.Add(smr);
// increment renderer sorting order.
if (index == 0) continue;
var prev = componentRenderers[index - 1]; if (prev == null) continue;
var prevMeshRenderer = prev.GetComponent<MeshRenderer>();
var currentMeshRenderer = smr.GetComponent<MeshRenderer>();
if (prevMeshRenderer == null || currentMeshRenderer == null) continue;
int prevSortingLayer = prevMeshRenderer.sortingLayerID;
int prevSortingOrder = prevMeshRenderer.sortingOrder;
currentMeshRenderer.sortingLayerID = prevSortingLayer;
currentMeshRenderer.sortingOrder = prevSortingOrder + SkeletonRenderSeparator.DefaultSortingOrderIncrement;
}
}
/// <summary>Detects orphaned parts renderers and offers to delete them.</summary>
public void DetectOrphanedPartsRenderers (SkeletonRenderSeparator component) {
var children = component.GetComponentsInChildren<SkeletonPartsRenderer>();
var orphans = new System.Collections.Generic.List<SkeletonPartsRenderer>();
foreach (var r in children) {
if (!component.partsRenderers.Contains(r))
orphans.Add(r);
}
if (orphans.Count > 0) {
if (EditorUtility.DisplayDialog("Destroy Submesh Renderers", "Unassigned renderers were found. Do you want to delete them? (These may belong to another Render Separator in the same hierarchy. If you don't have another Render Separator component in the children of this GameObject, it's likely safe to delete. Warning: This operation cannot be undone.)", "Delete", "Cancel")) {
foreach (var o in orphans) {
Undo.DestroyObjectImmediate(o.gameObject);
}
}
}
}
#region SkeletonRenderer Context Menu Item
[MenuItem("CONTEXT/SkeletonRenderer/Add Skeleton Render Separator")]
static void AddRenderSeparatorComponent (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var newComponent = skeletonRenderer.gameObject.AddComponent<SkeletonRenderSeparator>();
Undo.RegisterCreatedObjectUndo(newComponent, "Add SkeletonRenderSeparator");
}
// Validate
[MenuItem("CONTEXT/SkeletonRenderer/Add Skeleton Render Separator", true)]
static bool ValidateAddRenderSeparatorComponent (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var separator = skeletonRenderer.GetComponent<SkeletonRenderSeparator>();
bool separatorNotOnObject = separator == null;
return separatorNotOnObject;
}
#endregion
}
}
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
#define NEW_PREFAB_SYSTEM
#endif
using Spine.Unity;
using Spine.Unity.Editor;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Examples {
[CustomEditor(typeof(SkeletonRenderSeparator))]
public class SkeletonRenderSeparatorInspector : UnityEditor.Editor {
SkeletonRenderSeparator component;
// Properties
SerializedProperty skeletonRenderer_, copyPropertyBlock_, copyMeshRendererFlags_, partsRenderers_;
static bool partsRenderersExpanded = false;
// For separator field.
SerializedObject skeletonRendererSerializedObject;
SerializedProperty separatorNamesProp;
static bool skeletonRendererExpanded = true;
bool slotsReapplyRequired = false;
bool partsRendererInitRequired = false;
void OnEnable () {
if (component == null)
component = target as SkeletonRenderSeparator;
skeletonRenderer_ = serializedObject.FindProperty("skeletonRenderer");
copyPropertyBlock_ = serializedObject.FindProperty("copyPropertyBlock");
copyMeshRendererFlags_ = serializedObject.FindProperty("copyMeshRendererFlags");
var partsRenderers = component.partsRenderers;
partsRenderers_ = serializedObject.FindProperty("partsRenderers");
partsRenderers_.isExpanded = partsRenderersExpanded || // last state
partsRenderers.Contains(null) || // null items found
partsRenderers.Count < 1 || // no parts renderers
(skeletonRenderer_.objectReferenceValue != null && SkeletonRendererSeparatorCount + 1 > partsRenderers.Count); // not enough parts renderers
}
int SkeletonRendererSeparatorCount {
get {
if (Application.isPlaying)
return component.SkeletonRenderer.separatorSlots.Count;
else
return separatorNamesProp == null ? 0 : separatorNamesProp.arraySize;
}
}
public override void OnInspectorGUI () {
// Restore mesh part for undo logic after undo of "Add Parts Renderer".
// Triggers regeneration and assignment of the mesh filter's mesh.
bool isMeshFilterAlwaysNull = false;
#if UNITY_EDITOR && NEW_PREFAB_SYSTEM
// Don't store mesh or material at the prefab, otherwise it will permanently reload
var prefabType = UnityEditor.PrefabUtility.GetPrefabAssetType(component);
if (UnityEditor.PrefabUtility.IsPartOfPrefabAsset(component) &&
(prefabType == UnityEditor.PrefabAssetType.Regular || prefabType == UnityEditor.PrefabAssetType.Variant)) {
isMeshFilterAlwaysNull = true;
}
#endif
if (!isMeshFilterAlwaysNull && component.GetComponent<MeshFilter>() && component.GetComponent<MeshFilter>().sharedMesh == null) {
component.OnDisable();
component.OnEnable();
}
var componentRenderers = component.partsRenderers;
int totalParts;
using (new SpineInspectorUtility.LabelWidthScope()) {
bool componentEnabled = component.enabled;
bool checkBox = EditorGUILayout.Toggle("Enable Separator", componentEnabled);
if (checkBox != componentEnabled)
component.enabled = checkBox;
if (component.SkeletonRenderer.disableRenderingOnOverride && !component.enabled)
EditorGUILayout.HelpBox("By default, SkeletonRenderer's MeshRenderer is disabled while the SkeletonRenderSeparator takes over rendering. It is re-enabled when SkeletonRenderSeparator is disabled.", MessageType.Info);
EditorGUILayout.PropertyField(copyPropertyBlock_);
EditorGUILayout.PropertyField(copyMeshRendererFlags_);
}
// SkeletonRenderer Box
using (new SpineInspectorUtility.BoxScope(false)) {
// Fancy SkeletonRenderer foldout reference field
{
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
var foldoutSkeletonRendererRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
EditorGUI.PropertyField(foldoutSkeletonRendererRect, skeletonRenderer_);
if (EditorGUI.EndChangeCheck())
serializedObject.ApplyModifiedProperties();
if (component.SkeletonRenderer != null) {
skeletonRendererExpanded = EditorGUI.Foldout(foldoutSkeletonRendererRect, skeletonRendererExpanded, "");
}
EditorGUI.indentLevel--;
}
int separatorCount = 0;
EditorGUI.BeginChangeCheck();
if (component.SkeletonRenderer != null) {
// Separators from SkeletonRenderer
{
bool skeletonRendererMismatch = skeletonRendererSerializedObject != null && skeletonRendererSerializedObject.targetObject != component.SkeletonRenderer;
if (separatorNamesProp == null || skeletonRendererMismatch) {
if (component.SkeletonRenderer != null) {
skeletonRendererSerializedObject = new SerializedObject(component.SkeletonRenderer);
separatorNamesProp = skeletonRendererSerializedObject.FindProperty("separatorSlotNames");
separatorNamesProp.isExpanded = true;
}
}
if (separatorNamesProp != null) {
if (skeletonRendererExpanded) {
EditorGUI.indentLevel++;
SkeletonRendererInspector.SeparatorsField(separatorNamesProp);
EditorGUI.indentLevel--;
}
separatorCount = this.SkeletonRendererSeparatorCount;
}
}
if (SkeletonRendererSeparatorCount == 0) {
EditorGUILayout.HelpBox("Separators are empty. Change the size to 1 and choose a slot if you want the render to be separated.", MessageType.Info);
}
}
if (EditorGUI.EndChangeCheck()) {
skeletonRendererSerializedObject.ApplyModifiedProperties();
if (!Application.isPlaying)
slotsReapplyRequired = true;
}
totalParts = separatorCount + 1;
var counterStyle = skeletonRendererExpanded ? EditorStyles.label : EditorStyles.miniLabel;
EditorGUILayout.LabelField(string.Format("{0}: separates into {1}.", SpineInspectorUtility.Pluralize(separatorCount, "separator", "separators"), SpineInspectorUtility.Pluralize(totalParts, "part", "parts")), counterStyle);
}
// Parts renderers
using (new SpineInspectorUtility.BoxScope(false)) {
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(this.partsRenderers_, true);
EditorGUI.indentLevel--;
// Null items warning
bool nullItemsFound = componentRenderers.Contains(null);
if (nullItemsFound)
EditorGUILayout.HelpBox("Some items in the parts renderers list are null and may cause problems.\n\nYou can right-click on that element and choose 'Delete Array Element' to remove it.", MessageType.Warning);
// (Button) Match Separators count
if (separatorNamesProp != null) {
int currentRenderers = 0;
foreach (var r in componentRenderers) {
if (r != null)
currentRenderers++;
}
int extraRenderersNeeded = totalParts - currentRenderers;
if (component.enabled && component.SkeletonRenderer != null && extraRenderersNeeded > 0) {
EditorGUILayout.HelpBox(string.Format("Insufficient parts renderers. Some parts will not be rendered."), MessageType.Warning);
string addMissingLabel = string.Format("Add the missing renderer{1} ({0}) ", extraRenderersNeeded, SpineInspectorUtility.PluralThenS(extraRenderersNeeded));
if (GUILayout.Button(addMissingLabel, GUILayout.Height(30f))) {
AddPartsRenderer(extraRenderersNeeded);
DetectOrphanedPartsRenderers(component);
partsRendererInitRequired = true;
}
}
}
if (partsRenderers_.isExpanded != partsRenderersExpanded) partsRenderersExpanded = partsRenderers_.isExpanded;
if (partsRenderers_.isExpanded) {
using (new EditorGUILayout.HorizontalScope()) {
// (Button) Destroy Renderers button
if (componentRenderers.Count > 0) {
if (GUILayout.Button("Clear Parts Renderers")) {
// Do you really want to destroy all?
Undo.RegisterCompleteObjectUndo(component, "Clear Parts Renderers");
if (EditorUtility.DisplayDialog("Destroy Renderers", "Do you really want to destroy all the Parts Renderer GameObjects in the list?", "Destroy", "Cancel")) {
foreach (var r in componentRenderers) {
if (r != null)
Undo.DestroyObjectImmediate(r.gameObject);
}
componentRenderers.Clear();
// Do you also want to destroy orphans? (You monster.)
DetectOrphanedPartsRenderers(component);
}
}
}
// (Button) Add Part Renderer button
if (GUILayout.Button("Add Parts Renderer")) {
AddPartsRenderer(1);
partsRendererInitRequired = true;
}
}
}
}
serializedObject.ApplyModifiedProperties();
if (partsRendererInitRequired) {
Undo.RegisterCompleteObjectUndo(component.GetComponent<MeshRenderer>(), "Add Parts Renderers");
component.OnEnable();
partsRendererInitRequired = false;
}
if (slotsReapplyRequired && UnityEngine.Event.current.type == EventType.Repaint) {
component.SkeletonRenderer.ReapplySeparatorSlotNames();
component.SkeletonRenderer.LateUpdate();
SceneView.RepaintAll();
slotsReapplyRequired = false;
}
}
public void AddPartsRenderer (int count) {
var componentRenderers = component.partsRenderers;
bool emptyFound = componentRenderers.Contains(null);
if (emptyFound) {
bool userClearEntries = EditorUtility.DisplayDialog("Empty entries found", "Null entries found. Do you want to remove null entries before adding the new renderer? ", "Clear Empty Entries", "Don't Clear");
if (userClearEntries) componentRenderers.RemoveAll(x => x == null);
}
Undo.RegisterCompleteObjectUndo(component, "Add Parts Renderers");
for (int i = 0; i < count; i++) {
int index = componentRenderers.Count;
var smr = SkeletonPartsRenderer.NewPartsRendererGameObject(component.transform, index.ToString());
Undo.RegisterCreatedObjectUndo(smr.gameObject, "New Parts Renderer GameObject.");
componentRenderers.Add(smr);
// increment renderer sorting order.
if (index == 0) continue;
var prev = componentRenderers[index - 1]; if (prev == null) continue;
var prevMeshRenderer = prev.GetComponent<MeshRenderer>();
var currentMeshRenderer = smr.GetComponent<MeshRenderer>();
if (prevMeshRenderer == null || currentMeshRenderer == null) continue;
int prevSortingLayer = prevMeshRenderer.sortingLayerID;
int prevSortingOrder = prevMeshRenderer.sortingOrder;
currentMeshRenderer.sortingLayerID = prevSortingLayer;
currentMeshRenderer.sortingOrder = prevSortingOrder + SkeletonRenderSeparator.DefaultSortingOrderIncrement;
}
}
/// <summary>Detects orphaned parts renderers and offers to delete them.</summary>
public void DetectOrphanedPartsRenderers (SkeletonRenderSeparator component) {
var children = component.GetComponentsInChildren<SkeletonPartsRenderer>();
var orphans = new System.Collections.Generic.List<SkeletonPartsRenderer>();
foreach (var r in children) {
if (!component.partsRenderers.Contains(r))
orphans.Add(r);
}
if (orphans.Count > 0) {
if (EditorUtility.DisplayDialog("Destroy Submesh Renderers", "Unassigned renderers were found. Do you want to delete them? (These may belong to another Render Separator in the same hierarchy. If you don't have another Render Separator component in the children of this GameObject, it's likely safe to delete. Warning: This operation cannot be undone.)", "Delete", "Cancel")) {
foreach (var o in orphans) {
Undo.DestroyObjectImmediate(o.gameObject);
}
}
}
}
#region SkeletonRenderer Context Menu Item
[MenuItem("CONTEXT/SkeletonRenderer/Add Skeleton Render Separator")]
static void AddRenderSeparatorComponent (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var newComponent = skeletonRenderer.gameObject.AddComponent<SkeletonRenderSeparator>();
Undo.RegisterCreatedObjectUndo(newComponent, "Add SkeletonRenderSeparator");
}
// Validate
[MenuItem("CONTEXT/SkeletonRenderer/Add Skeleton Render Separator", true)]
static bool ValidateAddRenderSeparatorComponent (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var separator = skeletonRenderer.GetComponent<SkeletonRenderSeparator>();
bool separatorNotOnObject = separator == null;
return separatorNotOnObject;
}
#endregion
}
}