[unity] Cleanup: Spine Editor/Utility/SpineEditorUtilities class into multiple files with partial class qualifier.

This commit is contained in:
Harald Csaszar 2019-07-17 01:47:32 +02:00
parent 9583cb9183
commit ddf5082dc4
26 changed files with 2855 additions and 2311 deletions

View File

@ -138,7 +138,10 @@
* When receiving namespace related errors, replace using statements of `using Spine.Unity.Modules.AttachmentTools;` with `using Spine.Unity.AttachmentTools;`. You can remove `using Spine.Unity.Modules;` statements when a `using Spine.Unity` statement is already present in the file.
* `AttachmentTools`, `SkeletonPartsRenderer`, `SkeletonRenderSeparator`, `SkeletonRendererCustomMaterials` changed to namespace `Spine.Unity`.
* `SkeletonGhost`, `SkeletonGhostRenderer`, `AtlasRegionAttacher`, `SkeletonGraphicMirror`, `SkeletonRagdoll`, `SkeletonRagdoll2D`, `SkeletonUtilityEyeConstraint`, `SkeletonUtilityGroundConstraint`, `SkeletonUtilityKinematicShadow` changed to namespace `Spine.Unity.Examples`.
* Split `Editor/Utility/SpineEditorUtilities` class into multiple files with partial class qualifier.
* Nested classes `SpineEditorUtilities.AssetUtility` and `SpineEditorUtilities.EditorInstantiation` are now no longer nested. If you receive namespace related errors, replace any occurrance of
* `SpineEditorUtilities.AssetUtility` with `AssetUtility` and
* `SpineEditorUtilities.EditorInstantiation` with `EditorInstantiation`.
* **Additions**
* **Spine Preferences stored in Assets/Editor/SpineSettings.asset** Now Spine uses the new `SettingsProvider` API, storing settings in a SpineSettings.asset file which can be shared with team members. Your old preferences are automatically migrated to the new system.

View File

@ -113,7 +113,7 @@ namespace Spine.Unity.Editor {
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(SpineEditorUtilities.AssetUtility.GetPathSafeName(animationName), ThisAnimationReferenceAsset.name, System.StringComparison.OrdinalIgnoreCase))
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));

View File

@ -255,7 +255,7 @@ namespace Spine.Unity.Editor {
FieldInfo nameField = typeof(AnimationReferenceAsset).GetField("animationName", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo skeletonDataAssetField = typeof(AnimationReferenceAsset).GetField("skeletonDataAsset", BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var animation in targetSkeletonData.Animations) {
string assetPath = string.Format("{0}/{1}.asset", dataPath, SpineEditorUtilities.AssetUtility.GetPathSafeName(animation.Name));
string assetPath = string.Format("{0}/{1}.asset", dataPath, AssetUtility.GetPathSafeName(animation.Name));
AnimationReferenceAsset existingAsset = AssetDatabase.LoadAssetAtPath<AnimationReferenceAsset>(assetPath);
if (existingAsset == null) {
AnimationReferenceAsset newAsset = ScriptableObject.CreateInstance<AnimationReferenceAsset>();
@ -600,7 +600,7 @@ namespace Spine.Unity.Editor {
warnings.Add("Missing Skeleton JSON");
} else {
var fieldValue = (TextAsset)skeletonJSON.objectReferenceValue;
if (!SpineEditorUtilities.AssetUtility.IsSpineData(fieldValue)) {
if (!AssetUtility.IsSpineData(fieldValue)) {
warnings.Add("Skeleton data file is not a valid Spine JSON or binary file.");
} else {
#if SPINE_TK2D
@ -631,7 +631,7 @@ namespace Spine.Unity.Editor {
} else {
List<string> missingPaths = null;
if (atlasAssets.arraySize > 0) {
missingPaths = SpineEditorUtilities.AssetUtility.GetRequiredAtlasRegions(AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue));
missingPaths = AssetUtility.GetRequiredAtlasRegions(AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue));
foreach (var atlas in atlasList) {
for (int i = 0; i < missingPaths.Count; i++) {
@ -661,7 +661,7 @@ namespace Spine.Unity.Editor {
}
void DoReimport () {
SpineEditorUtilities.AssetUtility.ImportSpineContent(new [] { AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue) }, true);
AssetUtility.ImportSpineContent(new [] { AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue) }, true);
preview.Clear();
InitializeEditor();
EditorUtility.SetDirty(targetSkeletonDataAsset);
@ -831,7 +831,7 @@ namespace Spine.Unity.Editor {
if (previewGameObject == null) {
try {
previewGameObject = SpineEditorUtilities.EditorInstantiation.InstantiateSkeletonAnimation(skeletonDataAsset, skinName).gameObject;
previewGameObject = EditorInstantiation.InstantiateSkeletonAnimation(skeletonDataAsset, skinName).gameObject;
if (previewGameObject != null) {
previewGameObject.hideFlags = HideFlags.HideAndDontSave;

View File

@ -92,7 +92,7 @@ namespace Spine.Unity.Editor {
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
for (int i = 0; i < regions.Count; i++) {
AtlasRegion region = regions[i];
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.AssetUtility.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
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);

View File

@ -47,7 +47,7 @@ namespace Spine.Unity.Editor {
[MenuItem ("CONTEXT/SkeletonGraphic/Add BoneFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonGraphic = cmd.context as SkeletonGraphic;
var go = SpineEditorUtilities.EditorInstantiation.NewGameObject("BoneFollower", typeof(RectTransform));
var go = EditorInstantiation.NewGameObject("BoneFollower", typeof(RectTransform));
var t = go.transform;
t.SetParent(skeletonGraphic.transform);
t.localPosition = Vector3.zero;

View File

@ -45,7 +45,7 @@ namespace Spine.Unity.Editor {
[MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var go = SpineEditorUtilities.EditorInstantiation.NewGameObject("New BoneFollower");
var go = EditorInstantiation.NewGameObject("New BoneFollower");
var t = go.transform;
t.SetParent(skeletonRenderer.transform);
t.localPosition = Vector3.zero;

View File

@ -191,7 +191,7 @@ namespace Spine.Unity.Editor {
#endregion
static GameObject AddBoundingBoxFollowerChild (SkeletonRenderer sr, BoundingBoxFollower original = null) {
var go = SpineEditorUtilities.EditorInstantiation.NewGameObject("BoundingBoxFollower");
var go = EditorInstantiation.NewGameObject("BoundingBoxFollower");
go.transform.SetParent(sr.transform, false);
var newFollower = go.AddComponent<BoundingBoxFollower>();

View File

@ -46,7 +46,7 @@ namespace Spine.Unity.Editor {
[MenuItem("CONTEXT/SkeletonRenderer/Add PointFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer;
var go = SpineEditorUtilities.EditorInstantiation.NewGameObject("PointFollower");
var go = EditorInstantiation.NewGameObject("PointFollower");
var t = go.transform;
t.SetParent(skeletonRenderer.transform);
t.localPosition = Vector3.zero;

View File

@ -205,7 +205,7 @@ namespace Spine.Unity.Editor {
}
static GameObject NewSkeletonGraphicGameObject (string gameObjectName) {
var go = SpineEditorUtilities.EditorInstantiation.NewGameObject(gameObjectName, typeof(RectTransform), typeof(CanvasRenderer), typeof(SkeletonGraphic));
var go = EditorInstantiation.NewGameObject(gameObjectName, typeof(RectTransform), typeof(CanvasRenderer), typeof(SkeletonGraphic));
var graphic = go.GetComponent<SkeletonGraphic>();
graphic.material = SkeletonGraphicInspector.DefaultSkeletonGraphicMaterial;
return go;

View File

@ -36,12 +36,12 @@ namespace Spine.Unity.Editor {
public static class Menus {
[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
static public void CreateSkeletonRendererGameObject () {
SpineEditorUtilities.EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
}
[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
static public void CreateSkeletonAnimationGameObject () {
SpineEditorUtilities.EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
EditorInstantiation.InstantiateEmptySpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
}
}
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -0,0 +1,339 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions.
*
* Copyright (c) 2013-2019, 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.
*
* THIS SOFTWARE IS 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 THIS SOFTWARE,
* 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_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
#if UNITY_2019_1_OR_NEWER
#define NEW_TIMELINE_AS_PACKAGE
#endif
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection;
using System.Globalization;
namespace Spine.Unity.Editor {
public partial class SpineEditorUtilities {
public static class SpineTK2DEditorUtility {
const string SPINE_TK2D_DEFINE = "SPINE_TK2D";
internal static void EnableTK2D () {
SpineBuildEnvUtility.DisableSpineAsmdefFiles();
SpineBuildEnvUtility.EnableBuildDefine(SPINE_TK2D_DEFINE);
}
internal static void DisableTK2D () {
SpineBuildEnvUtility.EnableSpineAsmdefFiles();
SpineBuildEnvUtility.DisableBuildDefine(SPINE_TK2D_DEFINE);
}
}
public static class SpinePackageDependencyUtility
{
public enum RequestState {
NoRequestIssued = 0,
InProgress,
Success,
Failure
}
#if NEW_TIMELINE_AS_PACKAGE
const string SPINE_TIMELINE_PACKAGE_DOWNLOADED_DEFINE = "SPINE_TIMELINE_PACKAGE_DOWNLOADED";
const string TIMELINE_PACKAGE_NAME = "com.unity.timeline";
const string TIMELINE_ASMDEF_DEPENDENCY_STRING = "\"Unity.Timeline\"";
static UnityEditor.PackageManager.Requests.AddRequest timelineRequest = null;
/// <summary>
/// Enables Spine's Timeline components by downloading the Timeline Package in Unity 2019 and newer
/// and setting respective compile definitions once downloaded.
/// </summary>
internal static void EnableTimelineSupport () {
Debug.Log("Downloading Timeline package " + TIMELINE_PACKAGE_NAME + ".");
timelineRequest = UnityEditor.PackageManager.Client.Add(TIMELINE_PACKAGE_NAME);
// Note: unfortunately there is no callback provided, only polling support.
// So polling HandlePendingAsyncTimelineRequest() is necessary.
EditorApplication.update -= UpdateAsyncTimelineRequest;
EditorApplication.update += UpdateAsyncTimelineRequest;
}
public static void UpdateAsyncTimelineRequest () {
HandlePendingAsyncTimelineRequest();
}
public static RequestState HandlePendingAsyncTimelineRequest () {
if (timelineRequest == null)
return RequestState.NoRequestIssued;
var status = timelineRequest.Status;
if (status == UnityEditor.PackageManager.StatusCode.InProgress) {
return RequestState.InProgress;
}
else {
EditorApplication.update -= UpdateAsyncTimelineRequest;
timelineRequest = null;
if (status == UnityEditor.PackageManager.StatusCode.Failure) {
Debug.LogError("Download of package " + TIMELINE_PACKAGE_NAME + " failed!");
return RequestState.Failure;
}
else { // status == UnityEditor.PackageManager.StatusCode.Success
HandleSuccessfulTimelinePackageDownload();
return RequestState.Success;
}
}
}
internal static void DisableTimelineSupport () {
SpineBuildEnvUtility.DisableBuildDefine(SPINE_TIMELINE_PACKAGE_DOWNLOADED_DEFINE);
SpineBuildEnvUtility.RemoveDependencyFromAsmdefFile(TIMELINE_ASMDEF_DEPENDENCY_STRING);
}
internal static void HandleSuccessfulTimelinePackageDownload () {
#if !SPINE_TK2D
SpineBuildEnvUtility.EnableSpineAsmdefFiles();
#endif
SpineBuildEnvUtility.AddDependencyToAsmdefFile(TIMELINE_ASMDEF_DEPENDENCY_STRING);
SpineBuildEnvUtility.EnableBuildDefine(SPINE_TIMELINE_PACKAGE_DOWNLOADED_DEFINE);
ReimportTimelineScripts();
}
internal static void ReimportTimelineScripts () {
// Note: unfortunately AssetDatabase::Refresh is not enough and
// ImportAsset on a dir does not have the desired effect.
List<string> searchStrings = new List<string>();
searchStrings.Add("SpineAnimationStateBehaviour t:script");
searchStrings.Add("SpineAnimationStateClip t:script");
searchStrings.Add("SpineAnimationStateMixerBehaviour t:script");
searchStrings.Add("SpineAnimationStateTrack t:script");
searchStrings.Add("SpineSkeletonFlipBehaviour t:script");
searchStrings.Add("SpineSkeletonFlipClip t:script");
searchStrings.Add("SpineSkeletonFlipMixerBehaviour t:script");
searchStrings.Add("SpineSkeletonFlipTrack t:script");
searchStrings.Add("SkeletonAnimationPlayableHandle t:script");
searchStrings.Add("SpinePlayableHandleBase t:script");
foreach (string searchString in searchStrings) {
string[] guids = AssetDatabase.FindAssets(searchString);
foreach (string guid in guids) {
string currentPath = AssetDatabase.GUIDToAssetPath(guid);
AssetDatabase.ImportAsset(currentPath, ImportAssetOptions.ForceUpdate);
}
}
}
#endif
}
}
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);
}
public static void AddDependencyToAsmdefFile (string dependencyName) {
string asmdefName = "spine-unity";
string filePath = FindAsmdefFile(asmdefName);
if (string.IsNullOrEmpty(filePath))
return;
if (System.IO.File.Exists(filePath)) {
string fileContent = File.ReadAllText(filePath);
if (!fileContent.Contains("references")) {
string nameLine = string.Concat("\"name\": \"", asmdefName, "\"");
fileContent = fileContent.Replace(nameLine,
nameLine +
@",\n""references"": []");
}
if (!fileContent.Contains(dependencyName)) {
fileContent = fileContent.Replace(@"""references"": [",
@"""references"": [" + dependencyName);
File.WriteAllText(filePath, fileContent);
}
}
}
public static void RemoveDependencyFromAsmdefFile (string dependencyName) {
string asmdefName = "spine-unity";
string filePath = FindAsmdefFile(asmdefName);
if (string.IsNullOrEmpty(filePath))
return;
if (System.IO.File.Exists(filePath)) {
string fileContent = File.ReadAllText(filePath);
// this simple implementation shall suffice for now.
if (fileContent.Contains(dependencyName)) {
fileContent = fileContent.Replace(dependencyName, "");
File.WriteAllText(filePath, fileContent);
}
}
}
internal static string FindAsmdefFile (string filename) {
string filePath = FindAsmdefFile(filename, isDisabledFile: false);
if (string.IsNullOrEmpty(filePath))
filePath = FindAsmdefFile(filename, isDisabledFile: true);
return filePath;
}
internal static string FindAsmdefFile (string filename, bool isDisabledFile) {
string typeSearchString = isDisabledFile ? " t:TextAsset" : " t:AssemblyDefinitionAsset";
string extension = isDisabledFile ? ".txt" : ".asmdef";
string filenameWithExtension = filename + (isDisabledFile ? ".txt" : ".asmdef");
string[] guids = AssetDatabase.FindAssets(filename + typeSearchString);
foreach (string guid in guids) {
string currentPath = AssetDatabase.GUIDToAssetPath(guid);
if (!string.IsNullOrEmpty(currentPath)) {
if (System.IO.Path.GetFileName(currentPath) == filenameWithExtension)
return currentPath;
}
}
return null;
}
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.HasExtension(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

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

View File

@ -0,0 +1,149 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions.
*
* Copyright (c) 2013-2019, 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.
*
* THIS SOFTWARE IS 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 THIS SOFTWARE,
* 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_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
#if UNITY_2019_1_OR_NEWER
#define NEW_TIMELINE_AS_PACKAGE
#endif
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection;
using System.Globalization;
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 sg in activeSkeletonGraphics) {
var skeletonDataAsset = sg.skeletonDataAsset;
if (skeletonDataAsset != null) {
var assetPath = AssetDatabase.GetAssetPath(skeletonDataAsset);
var sgID = sg.GetInstanceID();
savedSkeletonDataAssetAtSKeletonGraphicID[sgID] = assetPath;
skeletonDataAssetsToReload.Add(skeletonDataAsset);
}
}
foreach (var sda in skeletonDataAssetsToReload) {
sda.Clear();
sda.GetSkeletonData(true);
}
foreach (var sr in activeSkeletonRenderers) {
var meshRenderer = sr.GetComponent<MeshRenderer>();
var sharedMaterials = meshRenderer.sharedMaterials;
foreach (var m in sharedMaterials) {
if (m == null) {
sr.Initialize(true);
break;
}
}
}
foreach (var sg in activeSkeletonGraphics) {
if (sg.mainTexture == null)
sg.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 sr in activeSkeletonRenderers) {
if (sr.isActiveAndEnabled && sr.skeletonDataAsset == skeletonDataAsset) sr.Initialize(true);
}
var activeSkeletonGraphics = GameObject.FindObjectsOfType<SkeletonGraphic>();
foreach (var sg in activeSkeletonGraphics) {
if (sg.isActiveAndEnabled && sg.skeletonDataAsset == skeletonDataAsset) sg.Initialize(true);
}
}
}
}
}

View File

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

View File

@ -0,0 +1,167 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions.
*
* Copyright (c) 2013-2019, 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.
*
* THIS SOFTWARE IS 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 THIS SOFTWARE,
* 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_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
#if UNITY_2019_1_OR_NEWER
#define NEW_TIMELINE_AS_PACKAGE
#endif
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection;
using System.Globalization;
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

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

View File

@ -0,0 +1,203 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions.
*
* Copyright (c) 2013-2019, 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.
*
* THIS SOFTWARE IS 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 THIS SOFTWARE,
* 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_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
#if UNITY_2019_1_OR_NEWER
#define NEW_TIMELINE_AS_PACKAGE
#endif
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection;
using System.Globalization;
namespace Spine.Unity.Editor {
using EventType = UnityEngine.EventType;
public partial class SpineEditorUtilities {
public static class DragAndDropInstantiation {
public struct SpawnMenuData {
public Vector3 spawnPoint;
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);
DragAndDrop.AcceptDrag();
current.Use();
}
}
}
}
}
public static void ShowInstantiateContextMenu (SkeletonDataAsset skeletonDataAsset, Vector3 spawnPoint) {
var menu = new GenericMenu();
// SkeletonAnimation
menu.AddItem(new GUIContent("SkeletonAnimation"), false, HandleSkeletonComponentDrop, new SpawnMenuData {
skeletonDataAsset = skeletonDataAsset,
spawnPoint = spawnPoint,
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,
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,
instantiateDelegate = (data) => EditorInstantiation.InstantiateSkeletonMecanim(data)
});
#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 activeGameObject = Selection.activeGameObject;
if (isUI && activeGameObject != null)
newTransform.SetParent(activeGameObject.transform, false);
newTransform.position = isUI ? data.spawnPoint : RoundVector(data.spawnPoint, 2);
if (isUI && (activeGameObject == null || activeGameObject.GetComponent<RectTransform>() == null))
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 && activeGameObject != null && activeGameObject.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

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

View File

@ -0,0 +1,313 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions.
*
* Copyright (c) 2013-2019, 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.
*
* THIS SOFTWARE IS 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 THIS SOFTWARE,
* 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_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
#if UNITY_2019_1_OR_NEWER
#define NEW_TIMELINE_AS_PACKAGE
#endif
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection;
using System.Globalization;
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;
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 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;
public const float DEFAULT_MIPMAPBIAS = SpinePreferences.DEFAULT_MIPMAPBIAS;
public const float DEFAULT_SCENE_ICONS_SCALE = SpinePreferences.DEFAULT_SCENE_ICONS_SCALE;
public const string SCENE_ICONS_SCALE_KEY = SpinePreferences.SCENE_ICONS_SCALE_KEY;
const string AUTO_RELOAD_SCENESKELETONS_KEY = "SPINE_AUTO_RELOAD_SCENESKELETONS";
public static bool autoReloadSceneSkeletons = SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS;
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);
autoReloadSceneSkeletons = EditorPrefs.GetBool(AUTO_RELOAD_SCENESKELETONS_KEY, SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS);
atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, SpinePreferences.DEFAULT_ATLASTXT_WARNING);
textureImporterWarning = EditorPrefs.GetBool(TEXTUREIMPORTER_WARNING_KEY, SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING);
SpineHandles.handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, 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.autoReloadSceneSkeletons = EditorPrefs.GetBool(AUTO_RELOAD_SCENESKELETONS_KEY, SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS);
newPreferences.atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, SpinePreferences.DEFAULT_ATLASTXT_WARNING);
newPreferences.textureImporterWarning = EditorPrefs.GetBool(TEXTUREIMPORTER_WARNING_KEY, SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING);
}
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.SetBool(AUTO_RELOAD_SCENESKELETONS_KEY, preferences.autoReloadSceneSkeletons);
EditorPrefs.SetBool(ATLASTXT_WARNING_KEY, preferences.atlasTxtImportWarning);
EditorPrefs.SetBool(TEXTUREIMPORTER_WARNING_KEY, preferences.textureImporterWarning);
}
#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."));
}
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."));
}
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("Handles and Gizmos", EditorStyles.boldLabel);
{
EditorGUI.BeginChangeCheck();
SpineHandles.handleScale = EditorGUILayout.Slider("Editor Bone Scale", SpineHandles.handleScale, 0.01f, 2f);
SpineHandles.handleScale = Mathf.Max(0.01f, SpineHandles.handleScale);
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetFloat(SCENE_ICONS_SCALE_KEY, SpineHandles.handleScale);
SceneView.RepaintAll();
}
}
#if NEW_TIMELINE_AS_PACKAGE
GUILayout.Space(20);
EditorGUILayout.LabelField("Timeline Support", EditorStyles.boldLabel);
using (new GUILayout.HorizontalScope()) {
EditorGUILayout.PrefixLabel("Timeline Package Support");
var requestState = SpineEditorUtilities.SpinePackageDependencyUtility.HandlePendingAsyncTimelineRequest();
using (new EditorGUI.DisabledGroupScope(requestState != SpineEditorUtilities.SpinePackageDependencyUtility.RequestState.NoRequestIssued)) {
if (GUILayout.Button("Enable", GUILayout.Width(64)))
SpineEditorUtilities.SpinePackageDependencyUtility.EnableTimelineSupport();
if (GUILayout.Button("Disable", GUILayout.Width(64)))
SpineEditorUtilities.SpinePackageDependencyUtility.DisableTimelineSupport();
}
}
#endif
GUILayout.Space(20);
EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel);
using (new GUILayout.HorizontalScope()) {
EditorGUILayout.PrefixLabel("Define TK2D");
if (GUILayout.Button("Enable", GUILayout.Width(64)))
SpineTK2DEditorUtility.EnableTK2D();
if (GUILayout.Button("Disable", GUILayout.Width(64)))
SpineTK2DEditorUtility.DisableTK2D();
}
}
#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);
}
}
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;
}
}
}

View File

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

View File

@ -0,0 +1,522 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions.
*
* Copyright (c) 2013-2019, 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.
*
* THIS SOFTWARE IS 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 THIS SOFTWARE,
* 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_2018_3_OR_NEWER
#define NEW_PREFERENCES_SETTINGS_PROVIDER
#endif
#if UNITY_2019_1_OR_NEWER
#define NEW_TIMELINE_AS_PACKAGE
#endif
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Reflection;
using System.Globalization;
namespace Spine.Unity.Editor {
using EventType = UnityEngine.EventType;
public static class SpineHandles {
internal static float handleScale = 1f;
public static Color BoneColor { get { return new Color(0.8f, 0.8f, 0.8f, 0.4f); } }
public static Color PathColor { get { return new Color(254/255f, 127/255f, 0); } }
public static Color TransformContraintColor { get { return new Color(170/255f, 226/255f, 35/255f); } }
public static Color IkColor { get { return new Color(228/255f,90/255f,43/255f); } }
public static Color PointColor { get { return new Color(1f, 1f, 0f, 1f); } }
static Vector3[] _boneMeshVerts = {
new Vector3(0, 0, 0),
new Vector3(0.1f, 0.1f, 0),
new Vector3(1, 0, 0),
new Vector3(0.1f, -0.1f, 0)
};
static Mesh _boneMesh;
public static Mesh BoneMesh {
get {
if (_boneMesh == null) {
_boneMesh = new Mesh {
vertices = _boneMeshVerts,
uv = new Vector2[4],
triangles = new [] { 0, 1, 2, 2, 3, 0 }
};
_boneMesh.RecalculateBounds();
_boneMesh.RecalculateNormals();
}
return _boneMesh;
}
}
static Mesh _arrowheadMesh;
public static Mesh ArrowheadMesh {
get {
if (_arrowheadMesh == null) {
_arrowheadMesh = new Mesh {
vertices = new [] {
new Vector3(0, 0),
new Vector3(-0.1f, 0.05f),
new Vector3(-0.1f, -0.05f)
},
uv = new Vector2[3],
triangles = new [] { 0, 1, 2 }
};
_arrowheadMesh.RecalculateBounds();
_arrowheadMesh.RecalculateNormals();
}
return _arrowheadMesh;
}
}
static Material _boneMaterial;
static Material BoneMaterial {
get {
if (_boneMaterial == null) {
_boneMaterial = new Material(Shader.Find("Hidden/Spine/Bones"));
_boneMaterial.SetColor("_Color", SpineHandles.BoneColor);
}
return _boneMaterial;
}
}
public static Material GetBoneMaterial () {
BoneMaterial.SetColor("_Color", SpineHandles.BoneColor);
return BoneMaterial;
}
public static Material GetBoneMaterial (Color color) {
BoneMaterial.SetColor("_Color", color);
return BoneMaterial;
}
static Material _ikMaterial;
public static Material IKMaterial {
get {
if (_ikMaterial == null) {
_ikMaterial = new Material(Shader.Find("Hidden/Spine/Bones"));
_ikMaterial.SetColor("_Color", SpineHandles.IkColor);
}
return _ikMaterial;
}
}
static GUIStyle _boneNameStyle;
public static GUIStyle BoneNameStyle {
get {
if (_boneNameStyle == null) {
_boneNameStyle = new GUIStyle(EditorStyles.whiteMiniLabel) {
alignment = TextAnchor.MiddleCenter,
stretchWidth = true,
padding = new RectOffset(0, 0, 0, 0),
contentOffset = new Vector2(-5f, 0f)
};
}
return _boneNameStyle;
}
}
static GUIStyle _pathNameStyle;
public static GUIStyle PathNameStyle {
get {
if (_pathNameStyle == null) {
_pathNameStyle = new GUIStyle(SpineHandles.BoneNameStyle);
_pathNameStyle.normal.textColor = SpineHandles.PathColor;
}
return _pathNameStyle;
}
}
static GUIStyle _pointNameStyle;
public static GUIStyle PointNameStyle {
get {
if (_pointNameStyle == null) {
_pointNameStyle = new GUIStyle(SpineHandles.BoneNameStyle);
_pointNameStyle.normal.textColor = SpineHandles.PointColor;
}
return _pointNameStyle;
}
}
public static void DrawBoneNames (Transform transform, Skeleton skeleton, float positionScale = 1f) {
GUIStyle style = BoneNameStyle;
foreach (Bone b in skeleton.Bones) {
if (!b.Active) continue;
var pos = new Vector3(b.WorldX * positionScale, b.WorldY * positionScale, 0) + (new Vector3(b.A, b.C) * (b.Data.Length * 0.5f));
pos = transform.TransformPoint(pos);
Handles.Label(pos, b.Data.Name, style);
}
}
public static void DrawBones (Transform transform, Skeleton skeleton, float positionScale = 1f) {
float boneScale = 1.8f; // Draw the root bone largest;
DrawCrosshairs2D(skeleton.Bones.Items[0].GetWorldPosition(transform), 0.08f, positionScale);
foreach (Bone b in skeleton.Bones) {
if (!b.Active) continue;
DrawBone(transform, b, boneScale, positionScale);
boneScale = 1f;
}
}
static Vector3[] _boneWireBuffer = new Vector3[5];
static Vector3[] GetBoneWireBuffer (Matrix4x4 m) {
for (int i = 0, n = _boneMeshVerts.Length; i < n; i++)
_boneWireBuffer[i] = m.MultiplyPoint(_boneMeshVerts[i]);
_boneWireBuffer[4] = _boneWireBuffer[0]; // closed polygon.
return _boneWireBuffer;
}
public static void DrawBoneWireframe (Transform transform, Bone b, Color color, float skeletonRenderScale = 1f) {
Handles.color = color;
var pos = new Vector3(b.WorldX * skeletonRenderScale, b.WorldY * skeletonRenderScale, 0);
float length = b.Data.Length;
if (length > 0) {
Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX);
Vector3 scale = Vector3.one * length * b.WorldScaleX * skeletonRenderScale;
const float my = 1.5f;
scale.y *= (SpineHandles.handleScale + 1) * 0.5f;
scale.y = Mathf.Clamp(scale.x, -my * skeletonRenderScale, my * skeletonRenderScale);
Handles.DrawPolyLine(GetBoneWireBuffer(transform.localToWorldMatrix * Matrix4x4.TRS(pos, rot, scale)));
var wp = transform.TransformPoint(pos);
DrawBoneCircle(wp, color, transform.forward, skeletonRenderScale);
} else {
var wp = transform.TransformPoint(pos);
DrawBoneCircle(wp, color, transform.forward, skeletonRenderScale);
}
}
public static void DrawBone (Transform transform, Bone b, float boneScale, float skeletonRenderScale = 1f) {
var pos = new Vector3(b.WorldX * skeletonRenderScale, b.WorldY * skeletonRenderScale, 0);
float length = b.Data.Length;
if (length > 0) {
Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX);
Vector3 scale = Vector3.one * length * b.WorldScaleX * skeletonRenderScale;
const float my = 1.5f;
scale.y *= (SpineHandles.handleScale + 1f) * 0.5f;
scale.y = Mathf.Clamp(scale.x, -my * skeletonRenderScale, my * skeletonRenderScale);
SpineHandles.GetBoneMaterial().SetPass(0);
Graphics.DrawMeshNow(SpineHandles.BoneMesh, transform.localToWorldMatrix * Matrix4x4.TRS(pos, rot, scale));
} else {
var wp = transform.TransformPoint(pos);
DrawBoneCircle(wp, SpineHandles.BoneColor, transform.forward, boneScale * skeletonRenderScale);
}
}
public static void DrawBone (Transform transform, Bone b, float boneScale, Color color, float skeletonRenderScale = 1f) {
var pos = new Vector3(b.WorldX * skeletonRenderScale, b.WorldY * skeletonRenderScale, 0);
float length = b.Data.Length;
if (length > 0) {
Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX);
Vector3 scale = Vector3.one * length * b.WorldScaleX;
const float my = 1.5f;
scale.y *= (SpineHandles.handleScale + 1f) * 0.5f;
scale.y = Mathf.Clamp(scale.x, -my, my);
SpineHandles.GetBoneMaterial(color).SetPass(0);
Graphics.DrawMeshNow(SpineHandles.BoneMesh, transform.localToWorldMatrix * Matrix4x4.TRS(pos, rot, scale));
} else {
var wp = transform.TransformPoint(pos);
DrawBoneCircle(wp, color, transform.forward, boneScale * skeletonRenderScale);
}
}
public static void DrawPaths (Transform transform, Skeleton skeleton) {
foreach (Slot s in skeleton.DrawOrder) {
var p = s.Attachment as PathAttachment;
if (p != null) SpineHandles.DrawPath(s, p, transform, true);
}
}
static float[] pathVertexBuffer;
public static void DrawPath (Slot s, PathAttachment p, Transform t, bool includeName) {
int worldVerticesLength = p.WorldVerticesLength;
if (pathVertexBuffer == null || pathVertexBuffer.Length < worldVerticesLength)
pathVertexBuffer = new float[worldVerticesLength];
float[] pv = pathVertexBuffer;
p.ComputeWorldVertices(s, pv);
var ocolor = Handles.color;
Handles.color = SpineHandles.PathColor;
Matrix4x4 m = t.localToWorldMatrix;
const int step = 6;
int n = worldVerticesLength - step;
Vector3 p0, p1, p2, p3;
for (int i = 2; i < n; i += step) {
p0 = m.MultiplyPoint(new Vector3(pv[i], pv[i+1]));
p1 = m.MultiplyPoint(new Vector3(pv[i+2], pv[i+3]));
p2 = m.MultiplyPoint(new Vector3(pv[i+4], pv[i+5]));
p3 = m.MultiplyPoint(new Vector3(pv[i+6], pv[i+7]));
DrawCubicBezier(p0, p1, p2, p3);
}
n += step;
if (p.Closed) {
p0 = m.MultiplyPoint(new Vector3(pv[n - 4], pv[n - 3]));
p1 = m.MultiplyPoint(new Vector3(pv[n - 2], pv[n - 1]));
p2 = m.MultiplyPoint(new Vector3(pv[0], pv[1]));
p3 = m.MultiplyPoint(new Vector3(pv[2], pv[3]));
DrawCubicBezier(p0, p1, p2, p3);
}
const float endCapSize = 0.05f;
Vector3 firstPoint = m.MultiplyPoint(new Vector3(pv[2], pv[3]));
SpineHandles.DrawDot(firstPoint, endCapSize);
//if (!p.Closed) SpineHandles.DrawDot(m.MultiplyPoint(new Vector3(pv[n - 4], pv[n - 3])), endCapSize);
if (includeName) Handles.Label(firstPoint + new Vector3(0,0.1f), p.Name, PathNameStyle);
Handles.color = ocolor;
}
public static void DrawDot (Vector3 position, float size) {
Handles.DotHandleCap(0, position, Quaternion.identity, size * HandleUtility.GetHandleSize(position), EventType.Ignore); //Handles.DotCap(0, position, Quaternion.identity, size * HandleUtility.GetHandleSize(position));
}
public static void DrawBoundingBoxes (Transform transform, Skeleton skeleton) {
foreach (var slot in skeleton.Slots) {
var bba = slot.Attachment as BoundingBoxAttachment;
if (bba != null) SpineHandles.DrawBoundingBox(slot, bba, transform);
}
}
public static void DrawBoundingBox (Slot slot, BoundingBoxAttachment box, Transform t) {
if (box.Vertices.Length <= 2) return; // Handle cases where user creates a BoundingBoxAttachment but doesn't actually define it.
var worldVerts = new float[box.WorldVerticesLength];
box.ComputeWorldVertices(slot, worldVerts);
Handles.color = Color.green;
Vector3 lastVert = Vector3.zero;
Vector3 vert = Vector3.zero;
Vector3 firstVert = t.TransformPoint(new Vector3(worldVerts[0], worldVerts[1], 0));
for (int i = 0; i < worldVerts.Length; i += 2) {
vert.x = worldVerts[i];
vert.y = worldVerts[i + 1];
vert.z = 0;
vert = t.TransformPoint(vert);
if (i > 0)
Handles.DrawLine(lastVert, vert);
lastVert = vert;
}
Handles.DrawLine(lastVert, firstVert);
}
public static void DrawPointAttachment (Bone bone, PointAttachment pointAttachment, Transform skeletonTransform) {
if (bone == null) return;
if (pointAttachment == null) return;
Vector2 localPos;
pointAttachment.ComputeWorldPosition(bone, out localPos.x, out localPos.y);
float localRotation = pointAttachment.ComputeWorldRotation(bone);
Matrix4x4 m = Matrix4x4.TRS(localPos, Quaternion.Euler(0, 0, localRotation), Vector3.one) * Matrix4x4.TRS(Vector3.right * 0.25f, Quaternion.identity, Vector3.one);
DrawBoneCircle(skeletonTransform.TransformPoint(localPos), SpineHandles.PointColor, Vector3.back, 1.3f);
DrawArrowhead(skeletonTransform.localToWorldMatrix * m);
}
public static void DrawConstraints (Transform transform, Skeleton skeleton, float skeletonRenderScale = 1f) {
Vector3 targetPos;
Vector3 pos;
bool active;
Color handleColor;
const float Thickness = 4f;
Vector3 normal = transform.forward;
// Transform Constraints
handleColor = SpineHandles.TransformContraintColor;
foreach (var tc in skeleton.TransformConstraints) {
var targetBone = tc.Target;
targetPos = targetBone.GetWorldPosition(transform, skeletonRenderScale);
if (tc.TranslateMix > 0) {
if (tc.TranslateMix != 1f) {
Handles.color = handleColor;
foreach (var b in tc.Bones) {
pos = b.GetWorldPosition(transform, skeletonRenderScale);
Handles.DrawDottedLine(targetPos, pos, Thickness);
}
}
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal, 1.3f * skeletonRenderScale);
Handles.color = handleColor;
SpineHandles.DrawCrosshairs(targetPos, 0.2f, targetBone.A, targetBone.B, targetBone.C, targetBone.D, transform, skeletonRenderScale);
}
}
// IK Constraints
handleColor = SpineHandles.IkColor;
foreach (var ikc in skeleton.IkConstraints) {
Bone targetBone = ikc.Target;
targetPos = targetBone.GetWorldPosition(transform, skeletonRenderScale);
var bones = ikc.Bones;
active = ikc.Mix > 0;
if (active) {
pos = bones.Items[0].GetWorldPosition(transform, skeletonRenderScale);
switch (bones.Count) {
case 1: {
Handles.color = handleColor;
Handles.DrawLine(targetPos, pos);
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal);
var m = bones.Items[0].GetMatrix4x4();
m.m03 = targetBone.WorldX * skeletonRenderScale;
m.m13 = targetBone.WorldY * skeletonRenderScale;
SpineHandles.DrawArrowhead(transform.localToWorldMatrix * m);
break;
}
case 2: {
Bone childBone = bones.Items[1];
Vector3 child = childBone.GetWorldPosition(transform, skeletonRenderScale);
Handles.color = handleColor;
Handles.DrawLine(child, pos);
Handles.DrawLine(targetPos, child);
SpineHandles.DrawBoneCircle(pos, handleColor, normal, 0.5f);
SpineHandles.DrawBoneCircle(child, handleColor, normal, 0.5f);
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal);
var m = childBone.GetMatrix4x4();
m.m03 = targetBone.WorldX * skeletonRenderScale;
m.m13 = targetBone.WorldY * skeletonRenderScale;
SpineHandles.DrawArrowhead(transform.localToWorldMatrix * m);
break;
}
}
}
//Handles.Label(targetPos, ikc.Data.Name, SpineHandles.BoneNameStyle);
}
// Path Constraints
handleColor = SpineHandles.PathColor;
foreach (var pc in skeleton.PathConstraints) {
active = pc.TranslateMix > 0;
if (active)
foreach (var b in pc.Bones)
SpineHandles.DrawBoneCircle(b.GetWorldPosition(transform, skeletonRenderScale), handleColor, normal, 1f * skeletonRenderScale);
}
}
static void DrawCrosshairs2D (Vector3 position, float scale, float skeletonRenderScale = 1f) {
scale *= SpineHandles.handleScale * skeletonRenderScale;
Handles.DrawLine(position + new Vector3(-scale, 0), position + new Vector3(scale, 0));
Handles.DrawLine(position + new Vector3(0, -scale), position + new Vector3(0, scale));
}
static void DrawCrosshairs (Vector3 position, float scale, float a, float b, float c, float d, Transform transform, float skeletonRenderScale = 1f) {
scale *= SpineHandles.handleScale * skeletonRenderScale;
var xOffset = (Vector3)(new Vector2(a, c).normalized * scale);
var yOffset = (Vector3)(new Vector2(b, d).normalized * scale);
xOffset = transform.TransformDirection(xOffset);
yOffset = transform.TransformDirection(yOffset);
Handles.DrawLine(position + xOffset, position - xOffset);
Handles.DrawLine(position + yOffset, position - yOffset);
}
static void DrawArrowhead2D (Vector3 pos, float localRotation, float scale = 1f) {
scale *= SpineHandles.handleScale;
SpineHandles.IKMaterial.SetPass(0);
Graphics.DrawMeshNow(SpineHandles.ArrowheadMesh, Matrix4x4.TRS(pos, Quaternion.Euler(0, 0, localRotation), new Vector3(scale, scale, scale)));
}
static void DrawArrowhead (Vector3 pos, Quaternion worldQuaternion) {
Graphics.DrawMeshNow(SpineHandles.ArrowheadMesh, pos, worldQuaternion, 0);
}
static void DrawArrowhead (Matrix4x4 m) {
float s = SpineHandles.handleScale;
m.m00 *= s;
m.m01 *= s;
m.m02 *= s;
m.m10 *= s;
m.m11 *= s;
m.m12 *= s;
m.m20 *= s;
m.m21 *= s;
m.m22 *= s;
SpineHandles.IKMaterial.SetPass(0);
Graphics.DrawMeshNow(SpineHandles.ArrowheadMesh, m);
}
static void DrawBoneCircle (Vector3 pos, Color outlineColor, Vector3 normal, float scale = 1f) {
scale *= SpineHandles.handleScale;
Color o = Handles.color;
Handles.color = outlineColor;
float firstScale = 0.08f * scale;
Handles.DrawSolidDisc(pos, normal, firstScale);
const float Thickness = 0.03f;
float secondScale = firstScale - (Thickness * SpineHandles.handleScale * scale);
if (secondScale > 0f) {
Handles.color = new Color(0.3f, 0.3f, 0.3f, 0.5f);
Handles.DrawSolidDisc(pos, normal, secondScale);
}
Handles.color = o;
}
internal static void DrawCubicBezier (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) {
Handles.DrawBezier(p0, p3, p1, p2, Handles.color, Texture2D.whiteTexture, 2f);
// const float dotSize = 0.01f;
// Quaternion q = Quaternion.identity;
// Handles.DotCap(0, p0, q, dotSize);
// Handles.DotCap(0, p1, q, dotSize);
// Handles.DotCap(0, p2, q, dotSize);
// Handles.DotCap(0, p3, q, dotSize);
// Handles.DrawLine(p0, p1);
// Handles.DrawLine(p3, p2);
}
}
}

View File

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

View File

@ -88,7 +88,7 @@ namespace Spine.Unity.Editor {
}
string dataPath = AssetDatabase.GetAssetPath(skeletonDataAsset);
string controllerPath = dataPath.Replace(SpineEditorUtilities.AssetUtility.SkeletonDataSuffix, "_Controller").Replace(".asset", ".controller");
string controllerPath = dataPath.Replace(AssetUtility.SkeletonDataSuffix, "_Controller").Replace(".asset", ".controller");
UnityEditor.Animations.AnimatorController controller;
if (skeletonDataAsset.controller != null) {
controller = (UnityEditor.Animations.AnimatorController)skeletonDataAsset.controller;
@ -295,7 +295,7 @@ namespace Spine.Unity.Editor {
}
}
GameObject prefabRoot = SpineEditorUtilities.EditorInstantiation.NewGameObject("root");
GameObject prefabRoot = EditorInstantiation.NewGameObject("root");
Dictionary<string, Transform> slotTable = new Dictionary<string, Transform>();
Dictionary<string, Transform> boneTable = new Dictionary<string, Transform>();
@ -304,7 +304,7 @@ namespace Spine.Unity.Editor {
//create bones
for (int i = 0; i < skeletonData.Bones.Count; i++) {
var boneData = skeletonData.Bones.Items[i];
Transform boneTransform = SpineEditorUtilities.EditorInstantiation.NewGameObject(boneData.Name).transform;
Transform boneTransform = EditorInstantiation.NewGameObject(boneData.Name).transform;
boneTransform.parent = prefabRoot.transform;
boneTable.Add(boneTransform.name, boneTransform);
boneList.Add(boneTransform);
@ -335,7 +335,7 @@ namespace Spine.Unity.Editor {
//create slots and attachments
for (int slotIndex = 0; slotIndex < skeletonData.Slots.Count; slotIndex++) {
var slotData = skeletonData.Slots.Items[slotIndex];
Transform slotTransform = SpineEditorUtilities.EditorInstantiation.NewGameObject(slotData.Name).transform;
Transform slotTransform = EditorInstantiation.NewGameObject(slotData.Name).transform;
slotTransform.parent = prefabRoot.transform;
slotTable.Add(slotData.Name, slotTransform);
@ -399,7 +399,7 @@ namespace Spine.Unity.Editor {
} else
continue;
Transform attachmentTransform = SpineEditorUtilities.EditorInstantiation.NewGameObject(attachmentName).transform;
Transform attachmentTransform = EditorInstantiation.NewGameObject(attachmentName).transform;
attachmentTransform.parent = slotTransform;
attachmentTransform.localPosition = offset;
@ -1425,7 +1425,7 @@ namespace Spine.Unity.Editor {
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.AssetUtility.GetPathSafeName(region.name) + ".prefab").Replace("\\", "/");
string bakedPrefabPath = Path.Combine(bakedDirPath, AssetUtility.GetPathSafeName(region.name) + ".prefab").Replace("\\", "/");
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
GameObject root;
@ -1436,7 +1436,7 @@ namespace Spine.Unity.Editor {
Directory.CreateDirectory(bakedDirPath);
if (prefab == null) {
root = SpineEditorUtilities.EditorInstantiation.NewGameObject("temp", typeof(MeshFilter), typeof(MeshRenderer));
root = EditorInstantiation.NewGameObject("temp", typeof(MeshFilter), typeof(MeshRenderer));
#if NEW_PREFAB_SYSTEM
prefab = PrefabUtility.SaveAsPrefabAsset(root, bakedPrefabPath);
#else