mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[unity/tk2d] Update editor code. Some cleanup and fixes. (#608)
* Initial cleanup and review. * More cleanup and review. * Removed missing atlas warnings for TK2D. Better button labels. Separated specialized/utility shaders. * Clearer wording. More checks. * Fix for Inspector reflowing between GUI events. * Basic TK2D warning message. * Fix play buttons. Removed useless reimport button for TK2D. Minor fixes.
This commit is contained in:
parent
2a6e2b8dfc
commit
5cceb22406
@ -24,20 +24,21 @@ namespace Spine.Unity.Editor {
|
|||||||
static bool showAttachments = false;
|
static bool showAttachments = false;
|
||||||
|
|
||||||
#if SPINE_BAKING
|
#if SPINE_BAKING
|
||||||
static bool showBaking = false;
|
static bool isBakingExpanded = false;
|
||||||
static bool bakeAnimations = true;
|
static bool bakeAnimations = true;
|
||||||
static bool bakeIK = true;
|
static bool bakeIK = true;
|
||||||
static SendMessageOptions bakeEventOptions = SendMessageOptions.DontRequireReceiver;
|
static SendMessageOptions bakeEventOptions = SendMessageOptions.DontRequireReceiver;
|
||||||
|
const string ShowBakingPrefsKey = "SkeletonDataAssetInspector_showUnity";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SerializedProperty atlasAssets, skeletonJSON, scale, fromAnimation, toAnimation, duration, defaultMix;
|
SerializedProperty atlasAssets, skeletonJSON, scale, fromAnimation, toAnimation, duration, defaultMix;
|
||||||
#if SPINE_SKELETON_ANIMATOR
|
#if SPINE_TK2D
|
||||||
static bool showMecanim = false;
|
SerializedProperty spriteCollection;
|
||||||
SerializedProperty controller;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SPINE_TK2D
|
#if SPINE_SKELETON_ANIMATOR
|
||||||
private SerializedProperty spriteCollection;
|
static bool isMecanimExpanded = false;
|
||||||
|
SerializedProperty controller;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool m_initialized = false;
|
bool m_initialized = false;
|
||||||
@ -48,42 +49,48 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
List<string> warnings = new List<string>();
|
List<string> warnings = new List<string>();
|
||||||
|
|
||||||
|
GUIStyle activePlayButtonStyle, idlePlayButtonStyle;
|
||||||
|
|
||||||
void OnEnable () {
|
void OnEnable () {
|
||||||
SpineEditorUtilities.ConfirmInitialization();
|
SpineEditorUtilities.ConfirmInitialization();
|
||||||
|
|
||||||
atlasAssets = serializedObject.FindProperty("atlasAssets");
|
atlasAssets = serializedObject.FindProperty("atlasAssets");
|
||||||
atlasAssets.isExpanded = true;
|
|
||||||
skeletonJSON = serializedObject.FindProperty("skeletonJSON");
|
skeletonJSON = serializedObject.FindProperty("skeletonJSON");
|
||||||
scale = serializedObject.FindProperty("scale");
|
scale = serializedObject.FindProperty("scale");
|
||||||
fromAnimation = serializedObject.FindProperty("fromAnimation");
|
fromAnimation = serializedObject.FindProperty("fromAnimation");
|
||||||
toAnimation = serializedObject.FindProperty("toAnimation");
|
toAnimation = serializedObject.FindProperty("toAnimation");
|
||||||
duration = serializedObject.FindProperty("duration");
|
duration = serializedObject.FindProperty("duration");
|
||||||
defaultMix = serializedObject.FindProperty("defaultMix");
|
defaultMix = serializedObject.FindProperty("defaultMix");
|
||||||
|
|
||||||
|
idlePlayButtonStyle = new GUIStyle(EditorStyles.toolbarButton);
|
||||||
|
activePlayButtonStyle = new GUIStyle(EditorStyles.toolbarButton);
|
||||||
|
activePlayButtonStyle.normal.textColor = Color.red;
|
||||||
|
|
||||||
#if SPINE_SKELETON_ANIMATOR
|
#if SPINE_SKELETON_ANIMATOR
|
||||||
controller = serializedObject.FindProperty("controller");
|
controller = serializedObject.FindProperty("controller");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SPINE_TK2D
|
#if SPINE_TK2D
|
||||||
|
atlasAssets.isExpanded = false;
|
||||||
spriteCollection = serializedObject.FindProperty("spriteCollection");
|
spriteCollection = serializedObject.FindProperty("spriteCollection");
|
||||||
|
#else
|
||||||
|
atlasAssets.isExpanded = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SPINE_BAKING
|
||||||
|
isBakingExpanded = EditorPrefs.GetBool(ShowBakingPrefsKey, false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_skeletonDataAsset = (SkeletonDataAsset)target;
|
m_skeletonDataAsset = (SkeletonDataAsset)target;
|
||||||
m_skeletonDataAssetGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_skeletonDataAsset));
|
m_skeletonDataAssetGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_skeletonDataAsset));
|
||||||
|
EditorApplication.update += EditorUpdate;
|
||||||
EditorApplication.update += Update;
|
|
||||||
|
|
||||||
m_skeletonData = m_skeletonDataAsset.GetSkeletonData(false);
|
m_skeletonData = m_skeletonDataAsset.GetSkeletonData(false);
|
||||||
|
|
||||||
#if SPINE_BAKING
|
|
||||||
showBaking = EditorPrefs.GetBool("SkeletonDataAssetInspector_showUnity", false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
InitPreview();
|
|
||||||
RepopulateWarnings();
|
RepopulateWarnings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDestroy () {
|
void OnDestroy () {
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
EditorApplication.update -= Update;
|
EditorApplication.update -= EditorUpdate;
|
||||||
this.DestroyPreviewInstances();
|
this.DestroyPreviewInstances();
|
||||||
if (this.m_previewUtility != null) {
|
if (this.m_previewUtility != null) {
|
||||||
this.m_previewUtility.Cleanup();
|
this.m_previewUtility.Cleanup();
|
||||||
@ -101,26 +108,26 @@ namespace Spine.Unity.Editor {
|
|||||||
using (new EditorGUI.DisabledGroupScope(spriteCollection.objectReferenceValue != null)) {
|
using (new EditorGUI.DisabledGroupScope(spriteCollection.objectReferenceValue != null)) {
|
||||||
EditorGUILayout.PropertyField(atlasAssets, true);
|
EditorGUILayout.PropertyField(atlasAssets, true);
|
||||||
}
|
}
|
||||||
|
EditorGUILayout.LabelField("spine-tk2d", EditorStyles.boldLabel);
|
||||||
EditorGUILayout.PropertyField(spriteCollection, true);
|
EditorGUILayout.PropertyField(spriteCollection, true);
|
||||||
#endif
|
#endif
|
||||||
|
EditorGUILayout.Space();
|
||||||
EditorGUILayout.PropertyField(skeletonJSON);
|
EditorGUILayout.PropertyField(skeletonJSON);
|
||||||
EditorGUILayout.PropertyField(scale);
|
EditorGUILayout.PropertyField(scale);
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
if (EditorGUI.EndChangeCheck()) {
|
if (EditorGUI.EndChangeCheck()) {
|
||||||
if (serializedObject.ApplyModifiedProperties()) {
|
if (serializedObject.ApplyModifiedProperties()) {
|
||||||
|
|
||||||
if (m_previewUtility != null) {
|
if (m_previewUtility != null) {
|
||||||
m_previewUtility.Cleanup();
|
m_previewUtility.Cleanup();
|
||||||
m_previewUtility = null;
|
m_previewUtility = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
RepopulateWarnings();
|
RepopulateWarnings();
|
||||||
OnEnable();
|
OnEnable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (m_skeletonData != null) {
|
if (m_skeletonData != null) {
|
||||||
DrawAnimationStateInfo();
|
DrawAnimationStateInfo();
|
||||||
DrawAnimationList();
|
DrawAnimationList();
|
||||||
@ -129,10 +136,22 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
DrawReimportButton();
|
#if !SPINE_TK2D
|
||||||
//Show Warnings
|
// Reimport Button
|
||||||
foreach (var str in warnings)
|
using (new EditorGUI.DisabledGroupScope(skeletonJSON.objectReferenceValue == null)) {
|
||||||
EditorGUILayout.LabelField(new GUIContent(str, SpineEditorUtilities.Icons.warning));
|
if (GUILayout.Button(new GUIContent("Attempt Reimport", SpineEditorUtilities.Icons.warning))) {
|
||||||
|
DoReimport();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
EditorGUILayout.HelpBox("Couldn't load SkeletonData.", MessageType.Error);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// List warnings.
|
||||||
|
foreach (var line in warnings)
|
||||||
|
EditorGUILayout.LabelField(new GUIContent(line, SpineEditorUtilities.Icons.warning));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Application.isPlaying)
|
if(!Application.isPlaying)
|
||||||
@ -141,37 +160,58 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
void DrawUnityTools () {
|
void DrawUnityTools () {
|
||||||
#if SPINE_SKELETON_ANIMATOR
|
#if SPINE_SKELETON_ANIMATOR
|
||||||
showMecanim = EditorGUILayout.Foldout(showMecanim, new GUIContent("SkeletonAnimator", SpineEditorUtilities.Icons.unityIcon));
|
isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, new GUIContent("SkeletonAnimator", SpineEditorUtilities.Icons.unityIcon));
|
||||||
if (showMecanim) {
|
if (isMecanimExpanded) {
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
EditorGUILayout.PropertyField(controller, new GUIContent("Controller", SpineEditorUtilities.Icons.controllerIcon));
|
EditorGUILayout.PropertyField(controller, new GUIContent("Controller", SpineEditorUtilities.Icons.controllerIcon));
|
||||||
if (controller.objectReferenceValue == null) {
|
if (controller.objectReferenceValue == null) {
|
||||||
|
|
||||||
|
// Generate Mecanim Controller Button
|
||||||
using (new GUILayout.HorizontalScope()) {
|
using (new GUILayout.HorizontalScope()) {
|
||||||
GUILayout.Space(32);
|
GUILayout.Space(EditorGUIUtility.labelWidth);
|
||||||
if (GUILayout.Button(new GUIContent("Generate Mecanim Controller"), GUILayout.Width(195), GUILayout.Height(20)))
|
if (GUILayout.Button(new GUIContent("Generate Mecanim Controller"), GUILayout.Height(20)))
|
||||||
SkeletonBaker.GenerateMecanimAnimationClips(m_skeletonDataAsset);
|
SkeletonBaker.GenerateMecanimAnimationClips(m_skeletonDataAsset);
|
||||||
}
|
}
|
||||||
EditorGUILayout.LabelField("SkeletonAnimator is the Mecanim alternative to SkeletonAnimation. It is not required.", EditorStyles.miniLabel);
|
EditorGUILayout.HelpBox("SkeletonAnimator is the Mecanim alternative to SkeletonAnimation.\nIt is not required.", MessageType.Info);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
// Update AnimationClips button.
|
||||||
using (new GUILayout.HorizontalScope()) {
|
using (new GUILayout.HorizontalScope()) {
|
||||||
GUILayout.Space(EditorGUIUtility.labelWidth);
|
GUILayout.Space(EditorGUIUtility.labelWidth);
|
||||||
if (GUILayout.Button(new GUIContent("Force Update AnimationClips"), GUILayout.Height(20)))
|
if (GUILayout.Button(new GUIContent("Force Update AnimationClips"), GUILayout.Height(20)))
|
||||||
SkeletonBaker.GenerateMecanimAnimationClips(m_skeletonDataAsset);
|
SkeletonBaker.GenerateMecanimAnimationClips(m_skeletonDataAsset);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SPINE_BAKING
|
#if SPINE_BAKING
|
||||||
bool pre = showBaking;
|
bool pre = isBakingExpanded;
|
||||||
showBaking = EditorGUILayout.Foldout(showBaking, new GUIContent("Baking", SpineEditorUtilities.Icons.unityIcon));
|
isBakingExpanded = EditorGUILayout.Foldout(isBakingExpanded, new GUIContent("Baking", SpineEditorUtilities.Icons.unityIcon));
|
||||||
if (pre != showBaking)
|
if (pre != isBakingExpanded)
|
||||||
EditorPrefs.SetBool("SkeletonDataAssetInspector_showUnity", showBaking);
|
EditorPrefs.SetBool(ShowBakingPrefsKey, isBakingExpanded);
|
||||||
|
|
||||||
if (showBaking) {
|
if (isBakingExpanded) {
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
EditorGUILayout.HelpBox("WARNING!\n\nBaking is NOT the same as SkeletonAnimator!\nDoes not support the following:\n\tFlipX or Y\n\tInheritScale\n\tColor Keys\n\tDraw Order Keys\n\tIK and Curves are sampled at 60fps and are not realtime.\n\tPlease read SkeletonBaker.cs comments for full details.\n\nThe main use of Baking is to export Spine projects to be used without the Spine Runtime (ie: for sale on the Asset Store, or background objects that are animated only with a wind noise generator)", MessageType.Warning, true);
|
const string BakingWarningMessage =
|
||||||
|
"WARNING!" +
|
||||||
|
"\nBaking is NOT the same as SkeletonAnimator!" +
|
||||||
|
|
||||||
|
"\n\nThe main use of Baking is to export Spine projects to be used without the Spine Runtime (ie: for sale on the Asset Store, or background objects that are animated only with a wind noise generator)" +
|
||||||
|
|
||||||
|
"\n\nBaking also does not support the following:" +
|
||||||
|
"\n\tDisabled transform inheritance" +
|
||||||
|
"\n\tShear" +
|
||||||
|
"\n\tColor Keys" +
|
||||||
|
"\n\tDraw Order Keys" +
|
||||||
|
"\n\tAll Constraint types" +
|
||||||
|
|
||||||
|
"\n\nCurves are sampled at 60fps and are not realtime." +
|
||||||
|
"\nPlease read SkeletonBaker.cs comments for full details.";
|
||||||
|
EditorGUILayout.HelpBox(BakingWarningMessage, MessageType.Warning, true);
|
||||||
|
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
bakeAnimations = EditorGUILayout.Toggle("Bake Animations", bakeAnimations);
|
bakeAnimations = EditorGUILayout.Toggle("Bake Animations", bakeAnimations);
|
||||||
@ -182,15 +222,19 @@ namespace Spine.Unity.Editor {
|
|||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bake Skin buttons.
|
||||||
using (new GUILayout.HorizontalScope()) {
|
using (new GUILayout.HorizontalScope()) {
|
||||||
if (GUILayout.Button(new GUIContent("Bake All Skins", SpineEditorUtilities.Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(150)))
|
if (GUILayout.Button(new GUIContent("Bake All Skins", SpineEditorUtilities.Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(150)))
|
||||||
SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, m_skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
|
SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, m_skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
|
||||||
|
|
||||||
string skinName = "<No Skin>";
|
// If m_skeletonAnimation is lazy-instantiated elsewhere, this can cause contents to change between Layout and Repaint events, causing scope errors.
|
||||||
|
if (m_skeletonData != null && m_skeletonAnimation == null)
|
||||||
|
InitPreview();
|
||||||
|
|
||||||
if (m_skeletonAnimation != null && m_skeletonAnimation.skeleton != null) { // If m_skeletonAnimation is lazy-instantiated, this can cause contents to change between Layout and Repaint events, which can cause scope errors.
|
if (m_skeletonAnimation != null && m_skeletonAnimation.skeleton != null) {
|
||||||
Skin bakeSkin = m_skeletonAnimation.skeleton.Skin;
|
Skin bakeSkin = m_skeletonAnimation.skeleton.Skin;
|
||||||
|
|
||||||
|
string skinName = "<No Skin>";
|
||||||
if (bakeSkin == null) {
|
if (bakeSkin == null) {
|
||||||
skinName = "Default";
|
skinName = "Default";
|
||||||
bakeSkin = m_skeletonData.Skins.Items[0];
|
bakeSkin = m_skeletonData.Skins.Items[0];
|
||||||
@ -203,7 +247,7 @@ namespace Spine.Unity.Editor {
|
|||||||
using (new GUILayout.HorizontalScope()) {
|
using (new GUILayout.HorizontalScope()) {
|
||||||
GUILayout.Label(new GUIContent("Skins", SpineEditorUtilities.Icons.skinsRoot), GUILayout.Width(50));
|
GUILayout.Label(new GUIContent("Skins", SpineEditorUtilities.Icons.skinsRoot), GUILayout.Width(50));
|
||||||
if (GUILayout.Button(skinName, EditorStyles.popup, GUILayout.Width(196))) {
|
if (GUILayout.Button(skinName, EditorStyles.popup, GUILayout.Width(196))) {
|
||||||
SelectSkinContext();
|
DrawSkinDropdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,16 +260,6 @@ namespace Spine.Unity.Editor {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawReimportButton () {
|
|
||||||
bool isJsonFieldEmpty = skeletonJSON.objectReferenceValue == null;
|
|
||||||
using (new EditorGUI.DisabledGroupScope(isJsonFieldEmpty)) {
|
|
||||||
if (GUILayout.Button(new GUIContent("Attempt Reimport", SpineEditorUtilities.Icons.warning))) {
|
|
||||||
DoReimport();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoReimport () {
|
void DoReimport () {
|
||||||
SpineEditorUtilities.ImportSpineContent(new string[] { AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue) }, true);
|
SpineEditorUtilities.ImportSpineContent(new string[] { AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue) }, true);
|
||||||
|
|
||||||
@ -248,7 +282,6 @@ namespace Spine.Unity.Editor {
|
|||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
EditorGUILayout.PropertyField(defaultMix);
|
EditorGUILayout.PropertyField(defaultMix);
|
||||||
|
|
||||||
// Animation names
|
|
||||||
var animations = new string[m_skeletonData.Animations.Count];
|
var animations = new string[m_skeletonData.Animations.Count];
|
||||||
for (int i = 0; i < animations.Length; i++)
|
for (int i = 0; i < animations.Length; i++)
|
||||||
animations[i] = m_skeletonData.Animations.Items[i].Name;
|
animations[i] = m_skeletonData.Animations.Items[i].Name;
|
||||||
@ -268,6 +301,7 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using (new EditorGUILayout.HorizontalScope()) {
|
using (new EditorGUILayout.HorizontalScope()) {
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
if (GUILayout.Button("Add Mix")) {
|
if (GUILayout.Button("Add Mix")) {
|
||||||
@ -284,7 +318,6 @@ namespace Spine.Unity.Editor {
|
|||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
needToSerialize = true;
|
needToSerialize = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawAnimationList () {
|
void DrawAnimationList () {
|
||||||
@ -303,39 +336,35 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EditorGUILayout.LabelField("Name", "Duration");
|
EditorGUILayout.LabelField("Name", "Duration");
|
||||||
foreach (Spine.Animation a in m_skeletonData.Animations) {
|
foreach (Spine.Animation animation in m_skeletonData.Animations) {
|
||||||
using (new GUILayout.HorizontalScope()) {
|
using (new GUILayout.HorizontalScope()) {
|
||||||
if (m_skeletonAnimation != null && m_skeletonAnimation.state != null) {
|
if (m_skeletonAnimation != null && m_skeletonAnimation.state != null) {
|
||||||
if (m_skeletonAnimation.state.GetCurrent(0) != null && m_skeletonAnimation.state.GetCurrent(0).Animation == a) {
|
var activeTrack = m_skeletonAnimation.state.GetCurrent(0);
|
||||||
GUI.contentColor = Color.red;
|
if (activeTrack != null && activeTrack.Animation == animation) {
|
||||||
if (GUILayout.Button("\u25BA", EditorStyles.toolbarButton, GUILayout.Width(24))) {
|
if (GUILayout.Button("\u25BA", activePlayButtonStyle, GUILayout.Width(24))) {
|
||||||
StopAnimation();
|
StopAnimation();
|
||||||
}
|
}
|
||||||
GUI.contentColor = Color.white;
|
|
||||||
} else {
|
} else {
|
||||||
if (GUILayout.Button("\u25BA", EditorStyles.toolbarButton, GUILayout.Width(24))) {
|
if (GUILayout.Button("\u25BA", idlePlayButtonStyle, GUILayout.Width(24))) {
|
||||||
PlayAnimation(a.Name, true);
|
PlayAnimation(animation.Name, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GUILayout.Label("?", GUILayout.Width(24));
|
GUILayout.Label("-", GUILayout.Width(24));
|
||||||
}
|
}
|
||||||
EditorGUILayout.LabelField(new GUIContent(a.Name, SpineEditorUtilities.Icons.animation), new GUIContent(a.Duration.ToString("f3") + "s" + ("(" + (Mathf.RoundToInt(a.Duration * 30)) + ")").PadLeft(12, ' ')));
|
EditorGUILayout.LabelField(new GUIContent(animation.Name, SpineEditorUtilities.Icons.animation), new GUIContent(animation.Duration.ToString("f3") + "s" + ("(" + (Mathf.RoundToInt(animation.Duration * 30)) + ")").PadLeft(12, ' ')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DrawSlotList () {
|
void DrawSlotList () {
|
||||||
showSlotList = EditorGUILayout.Foldout(showSlotList, new GUIContent("Slots", SpineEditorUtilities.Icons.slotRoot));
|
showSlotList = EditorGUILayout.Foldout(showSlotList, new GUIContent("Slots", SpineEditorUtilities.Icons.slotRoot));
|
||||||
|
|
||||||
if (!showSlotList)
|
if (!showSlotList) return;
|
||||||
return;
|
if (m_skeletonAnimation == null || m_skeletonAnimation.skeleton == null) return;
|
||||||
|
|
||||||
if (m_skeletonAnimation == null || m_skeletonAnimation.skeleton == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
showAttachments = EditorGUILayout.ToggleLeft("Show Attachments", showAttachments);
|
showAttachments = EditorGUILayout.ToggleLeft("Show Attachments", showAttachments);
|
||||||
} catch {
|
} catch {
|
||||||
@ -346,10 +375,7 @@ namespace Spine.Unity.Editor {
|
|||||||
List<string> slotAttachmentNames = new List<string>();
|
List<string> slotAttachmentNames = new List<string>();
|
||||||
List<string> defaultSkinAttachmentNames = new List<string>();
|
List<string> defaultSkinAttachmentNames = new List<string>();
|
||||||
var defaultSkin = m_skeletonData.Skins.Items[0];
|
var defaultSkin = m_skeletonData.Skins.Items[0];
|
||||||
Skin skin = m_skeletonAnimation.skeleton.Skin;
|
Skin skin = m_skeletonAnimation.skeleton.Skin ?? defaultSkin;
|
||||||
if (skin == null) {
|
|
||||||
skin = defaultSkin;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = m_skeletonAnimation.skeleton.Slots.Count - 1; i >= 0; i--) {
|
for (int i = m_skeletonAnimation.skeleton.Slots.Count - 1; i >= 0; i--) {
|
||||||
Slot slot = m_skeletonAnimation.skeleton.Slots.Items[i];
|
Slot slot = m_skeletonAnimation.skeleton.Slots.Items[i];
|
||||||
@ -364,7 +390,6 @@ namespace Spine.Unity.Editor {
|
|||||||
skin.FindNamesForSlot(i, slotAttachmentNames);
|
skin.FindNamesForSlot(i, slotAttachmentNames);
|
||||||
skin.FindAttachmentsForSlot(i, slotAttachments);
|
skin.FindAttachmentsForSlot(i, slotAttachments);
|
||||||
|
|
||||||
|
|
||||||
if (skin != defaultSkin) {
|
if (skin != defaultSkin) {
|
||||||
defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames);
|
defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames);
|
||||||
defaultSkin.FindNamesForSlot(i, slotAttachmentNames);
|
defaultSkin.FindNamesForSlot(i, slotAttachmentNames);
|
||||||
@ -375,7 +400,7 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
for (int a = 0; a < slotAttachments.Count; a++) {
|
for (int a = 0; a < slotAttachments.Count; a++) {
|
||||||
Attachment attachment = slotAttachments[a];
|
Attachment attachment = slotAttachments[a];
|
||||||
string name = slotAttachmentNames[a];
|
string attachmentName = slotAttachmentNames[a];
|
||||||
|
|
||||||
Texture2D icon = null;
|
Texture2D icon = null;
|
||||||
var type = attachment.GetType();
|
var type = attachment.GetType();
|
||||||
@ -391,15 +416,15 @@ namespace Spine.Unity.Editor {
|
|||||||
else
|
else
|
||||||
icon = SpineEditorUtilities.Icons.warning;
|
icon = SpineEditorUtilities.Icons.warning;
|
||||||
|
|
||||||
//TODO: Waterboard Nate
|
// MITCH: left todo: Waterboard Nate
|
||||||
//if (name != attachment.Name)
|
//if (name != attachment.Name)
|
||||||
//icon = SpineEditorUtilities.Icons.skinPlaceholder;
|
//icon = SpineEditorUtilities.Icons.skinPlaceholder;
|
||||||
|
|
||||||
bool initialState = slot.Attachment == attachment;
|
bool initialState = slot.Attachment == attachment;
|
||||||
|
|
||||||
bool toggled = EditorGUILayout.ToggleLeft(new GUIContent(name, icon), slot.Attachment == attachment);
|
bool toggled = EditorGUILayout.ToggleLeft(new GUIContent(attachmentName, icon), slot.Attachment == attachment);
|
||||||
|
|
||||||
if (!defaultSkinAttachmentNames.Contains(name)) {
|
if (!defaultSkinAttachmentNames.Contains(attachmentName)) {
|
||||||
Rect skinPlaceHolderIconRect = GUILayoutUtility.GetLastRect();
|
Rect skinPlaceHolderIconRect = GUILayoutUtility.GetLastRect();
|
||||||
skinPlaceHolderIconRect.width = SpineEditorUtilities.Icons.skinPlaceholder.width;
|
skinPlaceHolderIconRect.width = SpineEditorUtilities.Icons.skinPlaceholder.width;
|
||||||
skinPlaceHolderIconRect.height = SpineEditorUtilities.Icons.skinPlaceholder.height;
|
skinPlaceHolderIconRect.height = SpineEditorUtilities.Icons.skinPlaceholder.height;
|
||||||
@ -407,11 +432,7 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (toggled != initialState) {
|
if (toggled != initialState) {
|
||||||
if (toggled) {
|
slot.Attachment = toggled ? attachment : null;
|
||||||
slot.Attachment = attachment;
|
|
||||||
} else {
|
|
||||||
slot.Attachment = null;
|
|
||||||
}
|
|
||||||
m_requireRefresh = true;
|
m_requireRefresh = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -421,17 +442,16 @@ namespace Spine.Unity.Editor {
|
|||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RepopulateWarnings () {
|
void RepopulateWarnings () {
|
||||||
warnings.Clear();
|
warnings.Clear();
|
||||||
|
|
||||||
if (skeletonJSON.objectReferenceValue == null)
|
if (skeletonJSON.objectReferenceValue == null) {
|
||||||
warnings.Add("Missing Skeleton JSON");
|
warnings.Add("Missing Skeleton JSON");
|
||||||
else {
|
} else {
|
||||||
|
|
||||||
if (SpineEditorUtilities.IsValidSpineData((TextAsset)skeletonJSON.objectReferenceValue) == false) {
|
if (SpineEditorUtilities.IsValidSpineData((TextAsset)skeletonJSON.objectReferenceValue) == false) {
|
||||||
warnings.Add("Skeleton data file is not a valid JSON or binary file.");
|
warnings.Add("Skeleton data file is not a valid JSON or binary file.");
|
||||||
} else {
|
} else {
|
||||||
|
#if !SPINE_TK2D
|
||||||
bool detectedNullAtlasEntry = false;
|
bool detectedNullAtlasEntry = false;
|
||||||
var atlasList = new List<Atlas>();
|
var atlasList = new List<Atlas>();
|
||||||
for (int i = 0; i < atlasAssets.arraySize; i++) {
|
for (int i = 0; i < atlasAssets.arraySize; i++) {
|
||||||
@ -446,7 +466,7 @@ namespace Spine.Unity.Editor {
|
|||||||
if (detectedNullAtlasEntry)
|
if (detectedNullAtlasEntry)
|
||||||
warnings.Add("AtlasAsset elements cannot be Null");
|
warnings.Add("AtlasAsset elements cannot be Null");
|
||||||
else {
|
else {
|
||||||
//get requirements
|
// Get requirements.
|
||||||
var missingPaths = SpineEditorUtilities.GetRequiredAtlasRegions(AssetDatabase.GetAssetPath((TextAsset)skeletonJSON.objectReferenceValue));
|
var missingPaths = SpineEditorUtilities.GetRequiredAtlasRegions(AssetDatabase.GetAssetPath((TextAsset)skeletonJSON.objectReferenceValue));
|
||||||
|
|
||||||
foreach (var atlas in atlasList) {
|
foreach (var atlas in atlasList) {
|
||||||
@ -462,11 +482,18 @@ namespace Spine.Unity.Editor {
|
|||||||
warnings.Add("Missing Region: '" + str + "'");
|
warnings.Add("Missing Region: '" + str + "'");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (spriteCollection.objectReferenceValue == null) {
|
||||||
|
warnings.Add("SkeletonDataAsset requires tk2DSpriteCollectionData.");
|
||||||
|
} else {
|
||||||
|
warnings.Add("Your sprite collection may have missing images.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preview window stuff
|
#region Preview Window
|
||||||
PreviewRenderUtility m_previewUtility;
|
PreviewRenderUtility m_previewUtility;
|
||||||
GameObject m_previewInstance;
|
GameObject m_previewInstance;
|
||||||
Vector2 previewDir;
|
Vector2 previewDir;
|
||||||
@ -526,10 +553,15 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
void CreatePreviewInstances () {
|
void CreatePreviewInstances () {
|
||||||
this.DestroyPreviewInstances();
|
this.DestroyPreviewInstances();
|
||||||
|
|
||||||
|
var skeletonDataAsset = (SkeletonDataAsset)target;
|
||||||
|
if (skeletonDataAsset.GetSkeletonData(false) == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (this.m_previewInstance == null) {
|
if (this.m_previewInstance == null) {
|
||||||
string skinName = EditorPrefs.GetString(m_skeletonDataAssetGUID + "_lastSkin", "");
|
string skinName = EditorPrefs.GetString(m_skeletonDataAssetGUID + "_lastSkin", "");
|
||||||
|
|
||||||
m_previewInstance = SpineEditorUtilities.InstantiateSkeletonAnimation((SkeletonDataAsset)target, skinName).gameObject;
|
m_previewInstance = SpineEditorUtilities.InstantiateSkeletonAnimation(skeletonDataAsset, skinName).gameObject;
|
||||||
m_previewInstance.hideFlags = HideFlags.HideAndDontSave;
|
m_previewInstance.hideFlags = HideFlags.HideAndDontSave;
|
||||||
m_previewInstance.layer = 0x1f;
|
m_previewInstance.layer = 0x1f;
|
||||||
|
|
||||||
@ -555,7 +587,7 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override bool HasPreviewGUI () {
|
public override bool HasPreviewGUI () {
|
||||||
//TODO: validate json data
|
// MITCH: left todo: validate json data
|
||||||
|
|
||||||
for (int i = 0; i < atlasAssets.arraySize; i++) {
|
for (int i = 0; i < atlasAssets.arraySize; i++) {
|
||||||
var prop = atlasAssets.GetArrayElementAtIndex(i);
|
var prop = atlasAssets.GetArrayElementAtIndex(i);
|
||||||
@ -584,8 +616,8 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
DrawSkinToolbar(r);
|
DrawSkinToolbar(r);
|
||||||
NormalizedTimeBar(r);
|
NormalizedTimeBar(r);
|
||||||
//TODO: implement panning
|
// MITCH: left a todo: Implement panning
|
||||||
// this.previewDir = Drag2D(this.previewDir, r);
|
// this.previewDir = Drag2D(this.previewDir, r);
|
||||||
MouseScroll(r);
|
MouseScroll(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,14 +625,13 @@ namespace Spine.Unity.Editor {
|
|||||||
Vector3 m_posGoal = new Vector3(0, 0, -10);
|
Vector3 m_posGoal = new Vector3(0, 0, -10);
|
||||||
double m_adjustFrameEndTime = 0;
|
double m_adjustFrameEndTime = 0;
|
||||||
|
|
||||||
private void AdjustCameraGoals (bool calculateMixTime) {
|
void AdjustCameraGoals (bool calculateMixTime) {
|
||||||
if (this.m_previewInstance == null)
|
if (this.m_previewInstance == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (calculateMixTime) {
|
if (calculateMixTime) {
|
||||||
if (m_skeletonAnimation.state.GetCurrent(0) != null) {
|
if (m_skeletonAnimation.state.GetCurrent(0) != null)
|
||||||
m_adjustFrameEndTime = EditorApplication.timeSinceStartup + m_skeletonAnimation.state.GetCurrent(0).Mix;
|
m_adjustFrameEndTime = EditorApplication.timeSinceStartup + m_skeletonAnimation.state.GetCurrent(0).Mix;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject go = this.m_previewInstance;
|
GameObject go = this.m_previewInstance;
|
||||||
@ -609,17 +640,16 @@ namespace Spine.Unity.Editor {
|
|||||||
m_posGoal = bounds.center + new Vector3(0, 0, -10);
|
m_posGoal = bounds.center + new Vector3(0, 0, -10);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AdjustCameraGoals () {
|
void AdjustCameraGoals () {
|
||||||
AdjustCameraGoals(false);
|
AdjustCameraGoals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AdjustCamera () {
|
void AdjustCamera () {
|
||||||
if (m_previewUtility == null)
|
if (m_previewUtility == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (EditorApplication.timeSinceStartup < m_adjustFrameEndTime) {
|
if (EditorApplication.timeSinceStartup < m_adjustFrameEndTime)
|
||||||
AdjustCameraGoals();
|
AdjustCameraGoals();
|
||||||
}
|
|
||||||
|
|
||||||
float orthoSet = Mathf.Lerp(this.m_previewUtility.m_Camera.orthographicSize, m_orthoGoal, 0.1f);
|
float orthoSet = Mathf.Lerp(this.m_previewUtility.m_Camera.orthographicSize, m_orthoGoal, 0.1f);
|
||||||
|
|
||||||
@ -635,17 +665,14 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DoRenderPreview (bool drawHandles) {
|
void DoRenderPreview (bool drawHandles) {
|
||||||
GameObject go = this.m_previewInstance;
|
GameObject go = this.m_previewInstance;
|
||||||
|
|
||||||
if (m_requireRefresh && go != null) {
|
if (m_requireRefresh && go != null) {
|
||||||
go.GetComponent<Renderer>().enabled = true;
|
go.GetComponent<Renderer>().enabled = true;
|
||||||
|
|
||||||
if (EditorApplication.isPlaying) {
|
if (!EditorApplication.isPlaying)
|
||||||
//do nothing
|
|
||||||
} else {
|
|
||||||
m_skeletonAnimation.Update((Time.realtimeSinceStartup - m_lastTime));
|
m_skeletonAnimation.Update((Time.realtimeSinceStartup - m_lastTime));
|
||||||
}
|
|
||||||
|
|
||||||
m_lastTime = Time.realtimeSinceStartup;
|
m_lastTime = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
@ -666,10 +693,8 @@ namespace Spine.Unity.Editor {
|
|||||||
Handles.SetCamera(m_previewUtility.m_Camera);
|
Handles.SetCamera(m_previewUtility.m_Camera);
|
||||||
foreach (var slot in m_skeletonAnimation.skeleton.Slots) {
|
foreach (var slot in m_skeletonAnimation.skeleton.Slots) {
|
||||||
var boundingBoxAttachment = slot.Attachment as BoundingBoxAttachment;
|
var boundingBoxAttachment = slot.Attachment as BoundingBoxAttachment;
|
||||||
|
if (boundingBoxAttachment != null)
|
||||||
if (boundingBoxAttachment != null) {
|
|
||||||
DrawBoundingBox (slot.Bone, boundingBoxAttachment);
|
DrawBoundingBox (slot.Bone, boundingBoxAttachment);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,9 +717,8 @@ namespace Spine.Unity.Editor {
|
|||||||
vert.x = worldVerts[i];
|
vert.x = worldVerts[i];
|
||||||
vert.y = worldVerts[i + 1];
|
vert.y = worldVerts[i + 1];
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0)
|
||||||
Handles.DrawLine(lastVert, vert);
|
Handles.DrawLine(lastVert, vert);
|
||||||
}
|
|
||||||
|
|
||||||
lastVert = vert;
|
lastVert = vert;
|
||||||
}
|
}
|
||||||
@ -703,7 +727,7 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update () {
|
void EditorUpdate () {
|
||||||
AdjustCamera();
|
AdjustCamera();
|
||||||
|
|
||||||
if (m_playing) {
|
if (m_playing) {
|
||||||
@ -740,29 +764,11 @@ namespace Spine.Unity.Editor {
|
|||||||
popRect.x += 44;
|
popRect.x += 44;
|
||||||
|
|
||||||
if (GUI.Button(popRect, label, EditorStyles.popup)) {
|
if (GUI.Button(popRect, label, EditorStyles.popup)) {
|
||||||
SelectSkinContext();
|
DrawSkinDropdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectSkinContext () {
|
|
||||||
var menu = new GenericMenu();
|
|
||||||
foreach (Skin s in m_skeletonData.Skins) {
|
|
||||||
menu.AddItem(new GUIContent(s.Name), this.m_skeletonAnimation.skeleton.Skin == s, SetSkin, (object)s);
|
|
||||||
}
|
|
||||||
menu.ShowAsContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSkin (object o) {
|
|
||||||
Skin skin = (Skin)o;
|
|
||||||
|
|
||||||
m_skeletonAnimation.initialSkinName = skin.Name;
|
|
||||||
m_skeletonAnimation.Initialize(true);
|
|
||||||
m_requireRefresh = true;
|
|
||||||
|
|
||||||
EditorPrefs.SetString(m_skeletonDataAssetGUID + "_lastSkin", skin.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NormalizedTimeBar (Rect r) {
|
void NormalizedTimeBar (Rect r) {
|
||||||
if (m_skeletonAnimation == null)
|
if (m_skeletonAnimation == null)
|
||||||
return;
|
return;
|
||||||
@ -792,11 +798,10 @@ namespace Spine.Unity.Editor {
|
|||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
|
|
||||||
for (int i = 0; i < m_animEvents.Count; i++) {
|
for (int i = 0; i < m_animEvents.Count; i++) {
|
||||||
//TODO: Tooltip
|
// MITCH: left todo: Tooltip
|
||||||
//Spine.Event spev = animEvents[i];
|
//Spine.Event spev = animEvents[i];
|
||||||
|
|
||||||
float fr = m_animEventFrames[i];
|
float fr = m_animEventFrames[i];
|
||||||
|
|
||||||
var evRect = new Rect(barRect);
|
var evRect = new Rect(barRect);
|
||||||
evRect.x = Mathf.Clamp(((fr / t.Animation.Duration) * width) - (SpineEditorUtilities.Icons._event.width / 2), barRect.x, float.MaxValue);
|
evRect.x = Mathf.Clamp(((fr / t.Animation.Duration) * width) - (SpineEditorUtilities.Icons._event.width / 2), barRect.x, float.MaxValue);
|
||||||
evRect.width = SpineEditorUtilities.Icons._event.width;
|
evRect.width = SpineEditorUtilities.Icons._event.width;
|
||||||
@ -804,20 +809,17 @@ namespace Spine.Unity.Editor {
|
|||||||
evRect.y += SpineEditorUtilities.Icons._event.height;
|
evRect.y += SpineEditorUtilities.Icons._event.height;
|
||||||
GUI.DrawTexture(evRect, SpineEditorUtilities.Icons._event);
|
GUI.DrawTexture(evRect, SpineEditorUtilities.Icons._event);
|
||||||
|
|
||||||
|
// MITCH: left todo: Tooltip
|
||||||
//TODO: Tooltip
|
// UnityEngine.Event ev = UnityEngine.Event.current;
|
||||||
/*
|
// if (ev.isMouse) {
|
||||||
UnityEngine.Event ev = UnityEngine.Event.current;
|
// if (evRect.Contains(ev.mousePosition)) {
|
||||||
if(ev.isMouse){
|
// Rect tooltipRect = new Rect(evRect);
|
||||||
if(evRect.Contains(ev.mousePosition)){
|
// tooltipRect.width = 500;
|
||||||
Rect tooltipRect = new Rect(evRect);
|
// tooltipRect.y -= 4;
|
||||||
tooltipRect.width = 500;
|
// tooltipRect.x += 4;
|
||||||
tooltipRect.y -= 4;
|
// GUI.Label(tooltipRect, spev.Data.Name);
|
||||||
tooltipRect.x += 4;
|
// }
|
||||||
GUI.Label(tooltipRect, spev.Data.Name);
|
// }
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -825,11 +827,9 @@ namespace Spine.Unity.Editor {
|
|||||||
void MouseScroll (Rect position) {
|
void MouseScroll (Rect position) {
|
||||||
UnityEngine.Event current = UnityEngine.Event.current;
|
UnityEngine.Event current = UnityEngine.Event.current;
|
||||||
int controlID = GUIUtility.GetControlID(SliderHash, FocusType.Passive);
|
int controlID = GUIUtility.GetControlID(SliderHash, FocusType.Passive);
|
||||||
|
|
||||||
switch (current.GetTypeForControl(controlID)) {
|
switch (current.GetTypeForControl(controlID)) {
|
||||||
case EventType.ScrollWheel:
|
case EventType.ScrollWheel:
|
||||||
if (position.Contains(current.mousePosition)) {
|
if (position.Contains(current.mousePosition)) {
|
||||||
|
|
||||||
m_orthoGoal += current.delta.y;
|
m_orthoGoal += current.delta.y;
|
||||||
m_orthoGoal = Mathf.Max(0.01f, m_orthoGoal);
|
m_orthoGoal = Mathf.Max(0.01f, m_orthoGoal);
|
||||||
GUIUtility.hotControl = controlID;
|
GUIUtility.hotControl = controlID;
|
||||||
@ -837,50 +837,49 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Implement preview panning
|
// MITCH: left todo: Implement preview panning
|
||||||
/*
|
/*
|
||||||
static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
|
static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
|
||||||
{
|
|
||||||
int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
|
|
||||||
UnityEngine.Event current = UnityEngine.Event.current;
|
|
||||||
switch (current.GetTypeForControl(controlID))
|
|
||||||
{
|
{
|
||||||
case EventType.MouseDown:
|
int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
|
||||||
if (position.Contains(current.mousePosition) && (position.width > 50f))
|
UnityEngine.Event current = UnityEngine.Event.current;
|
||||||
|
switch (current.GetTypeForControl(controlID))
|
||||||
{
|
{
|
||||||
GUIUtility.hotControl = controlID;
|
case EventType.MouseDown:
|
||||||
current.Use();
|
if (position.Contains(current.mousePosition) && (position.width > 50f))
|
||||||
EditorGUIUtility.SetWantsMouseJumping(1);
|
{
|
||||||
}
|
GUIUtility.hotControl = controlID;
|
||||||
return scrollPosition;
|
current.Use();
|
||||||
|
EditorGUIUtility.SetWantsMouseJumping(1);
|
||||||
|
}
|
||||||
|
return scrollPosition;
|
||||||
|
|
||||||
case EventType.MouseUp:
|
case EventType.MouseUp:
|
||||||
if (GUIUtility.hotControl == controlID)
|
if (GUIUtility.hotControl == controlID)
|
||||||
{
|
{
|
||||||
GUIUtility.hotControl = 0;
|
GUIUtility.hotControl = 0;
|
||||||
}
|
}
|
||||||
EditorGUIUtility.SetWantsMouseJumping(0);
|
EditorGUIUtility.SetWantsMouseJumping(0);
|
||||||
return scrollPosition;
|
return scrollPosition;
|
||||||
|
|
||||||
case EventType.MouseMove:
|
case EventType.MouseMove:
|
||||||
return scrollPosition;
|
return scrollPosition;
|
||||||
|
|
||||||
case EventType.MouseDrag:
|
case EventType.MouseDrag:
|
||||||
if (GUIUtility.hotControl == controlID)
|
if (GUIUtility.hotControl == controlID)
|
||||||
{
|
{
|
||||||
scrollPosition -= (Vector2) (((current.delta * (!current.shift ? ((float) 1) : ((float) 3))) / Mathf.Min(position.width, position.height)) * 140f);
|
scrollPosition -= (Vector2) (((current.delta * (!current.shift ? ((float) 1) : ((float) 3))) / Mathf.Min(position.width, position.height)) * 140f);
|
||||||
scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90f, 90f);
|
scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90f, 90f);
|
||||||
current.Use();
|
current.Use();
|
||||||
GUI.changed = true;
|
GUI.changed = true;
|
||||||
|
}
|
||||||
|
return scrollPosition;
|
||||||
}
|
}
|
||||||
return scrollPosition;
|
return scrollPosition;
|
||||||
}
|
}
|
||||||
return scrollPosition;
|
*/
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public override GUIContent GetPreviewTitle () {
|
public override GUIContent GetPreviewTitle () {
|
||||||
return new GUIContent("Preview");
|
return new GUIContent("Preview");
|
||||||
@ -901,8 +900,8 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Fix first-import error
|
// MITCH: left todo: Fix first-import error
|
||||||
//TODO: Update preview without thumbnail
|
// MITCH: left todo: Update preview without thumbnail
|
||||||
public override Texture2D RenderStaticPreview (string assetPath, UnityEngine.Object[] subAssets, int width, int height) {
|
public override Texture2D RenderStaticPreview (string assetPath, UnityEngine.Object[] subAssets, int width, int height) {
|
||||||
var tex = new Texture2D(width, height, TextureFormat.ARGB32, false);
|
var tex = new Texture2D(width, height, TextureFormat.ARGB32, false);
|
||||||
|
|
||||||
@ -920,7 +919,7 @@ namespace Spine.Unity.Editor {
|
|||||||
this.m_previewUtility.BeginStaticPreview(new Rect(0, 0, width, height));
|
this.m_previewUtility.BeginStaticPreview(new Rect(0, 0, width, height));
|
||||||
this.DoRenderPreview(false);
|
this.DoRenderPreview(false);
|
||||||
|
|
||||||
//TODO: Figure out why this is throwing errors on first attempt
|
//MITCH: left todo: Figure out why this is throwing errors on first attempt
|
||||||
// if(m_previewUtility != null){
|
// if(m_previewUtility != null){
|
||||||
// Handles.SetCamera(this.m_previewUtility.m_Camera);
|
// Handles.SetCamera(this.m_previewUtility.m_Camera);
|
||||||
// Handles.BeginGUI();
|
// Handles.BeginGUI();
|
||||||
@ -930,6 +929,27 @@ namespace Spine.Unity.Editor {
|
|||||||
tex = this.m_previewUtility.EndStaticPreview();
|
tex = this.m_previewUtility.EndStaticPreview();
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Skin Dropdown Context Menu
|
||||||
|
void DrawSkinDropdown () {
|
||||||
|
var menu = new GenericMenu();
|
||||||
|
foreach (Skin s in m_skeletonData.Skins)
|
||||||
|
menu.AddItem(new GUIContent(s.Name), this.m_skeletonAnimation.skeleton.Skin == s, SetSkin, s);
|
||||||
|
|
||||||
|
menu.ShowAsContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSkin (object o) {
|
||||||
|
Skin skin = (Skin)o;
|
||||||
|
|
||||||
|
m_skeletonAnimation.initialSkinName = skin.Name;
|
||||||
|
m_skeletonAnimation.Initialize(true);
|
||||||
|
m_requireRefresh = true;
|
||||||
|
|
||||||
|
EditorPrefs.SetString(m_skeletonDataAssetGUID + "_lastSkin", skin.Name);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,7 @@ using Spine;
|
|||||||
|
|
||||||
namespace Spine.Unity.Editor {
|
namespace Spine.Unity.Editor {
|
||||||
|
|
||||||
|
// Analysis disable once ConvertToStaticType
|
||||||
[InitializeOnLoad]
|
[InitializeOnLoad]
|
||||||
public class SpineEditorUtilities : AssetPostprocessor {
|
public class SpineEditorUtilities : AssetPostprocessor {
|
||||||
|
|
||||||
@ -78,47 +79,42 @@ namespace Spine.Unity.Editor {
|
|||||||
public static Texture2D unityIcon;
|
public static Texture2D unityIcon;
|
||||||
public static Texture2D controllerIcon;
|
public static Texture2D controllerIcon;
|
||||||
|
|
||||||
public static Mesh boneMesh {
|
internal static Mesh _boneMesh;
|
||||||
|
public static Mesh BoneMesh {
|
||||||
get {
|
get {
|
||||||
if (_boneMesh == null) {
|
if (_boneMesh == null) {
|
||||||
_boneMesh = new Mesh();
|
_boneMesh = new Mesh();
|
||||||
_boneMesh.vertices = new Vector3[4] {
|
_boneMesh.vertices = new [] {
|
||||||
Vector3.zero,
|
new Vector3(0, 0, 0),
|
||||||
new Vector3(-0.1f, 0.1f, 0),
|
new Vector3(-0.1f, 0.1f, 0),
|
||||||
Vector3.up,
|
new Vector3(0, 1, 0),
|
||||||
new Vector3(0.1f, 0.1f, 0)
|
new Vector3(0.1f, 0.1f, 0)
|
||||||
};
|
};
|
||||||
_boneMesh.uv = new Vector2[4];
|
_boneMesh.uv = new Vector2[4];
|
||||||
_boneMesh.triangles = new int[6] { 0, 1, 2, 2, 3, 0 };
|
_boneMesh.triangles = new [] { 0, 1, 2, 2, 3, 0 };
|
||||||
_boneMesh.RecalculateBounds();
|
_boneMesh.RecalculateBounds();
|
||||||
_boneMesh.RecalculateNormals();
|
_boneMesh.RecalculateNormals();
|
||||||
}
|
}
|
||||||
|
|
||||||
return _boneMesh;
|
return _boneMesh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Mesh _boneMesh;
|
internal static Material _boneMaterial;
|
||||||
|
public static Material BoneMaterial {
|
||||||
public static Material boneMaterial {
|
|
||||||
get {
|
get {
|
||||||
if (_boneMaterial == null) {
|
if (_boneMaterial == null) {
|
||||||
#if UNITY_4_3
|
#if UNITY_4_3
|
||||||
_boneMaterial = new Material(Shader.Find("Particles/Alpha Blended"));
|
_boneMaterial = new Material(Shader.Find("Particles/Alpha Blended"));
|
||||||
_boneMaterial.SetColor("_TintColor", new Color(0.4f, 0.4f, 0.4f, 0.25f));
|
_boneMaterial.SetColor("_TintColor", new Color(0.4f, 0.4f, 0.4f, 0.25f));
|
||||||
#else
|
#else
|
||||||
_boneMaterial = new Material(Shader.Find("Spine/Bones"));
|
_boneMaterial = new Material(Shader.Find("Hidden/Spine/Bones"));
|
||||||
_boneMaterial.SetColor("_Color", new Color(0.4f, 0.4f, 0.4f, 0.25f));
|
_boneMaterial.SetColor("_Color", new Color(0.4f, 0.4f, 0.4f, 0.25f));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _boneMaterial;
|
return _boneMaterial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Material _boneMaterial;
|
|
||||||
|
|
||||||
public static void Initialize () {
|
public static void Initialize () {
|
||||||
skeleton = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skeleton.png");
|
skeleton = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skeleton.png");
|
||||||
nullBone = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-null.png");
|
nullBone = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-null.png");
|
||||||
@ -152,17 +148,19 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
public static string editorPath = "";
|
public static string editorPath = "";
|
||||||
public static string editorGUIPath = "";
|
public static string editorGUIPath = "";
|
||||||
|
public static bool initialized;
|
||||||
|
|
||||||
static HashSet<string> assetsImportedInWrongState;
|
static HashSet<string> assetsImportedInWrongState;
|
||||||
static Dictionary<int, GameObject> skeletonRendererTable;
|
static Dictionary<int, GameObject> skeletonRendererTable;
|
||||||
static Dictionary<int, SkeletonUtilityBone> skeletonUtilityBoneTable;
|
static Dictionary<int, SkeletonUtilityBone> skeletonUtilityBoneTable;
|
||||||
static Dictionary<int, BoundingBoxFollower> boundingBoxFollowerTable;
|
static Dictionary<int, BoundingBoxFollower> boundingBoxFollowerTable;
|
||||||
|
|
||||||
|
const string DEFAULT_MIX_KEY = "SPINE_DEFAULT_MIX";
|
||||||
public static float defaultScale = 0.01f;
|
public static float defaultScale = 0.01f;
|
||||||
public static float defaultMix = 0.2f;
|
public static float defaultMix = 0.2f;
|
||||||
public static string defaultShader = "Spine/Skeleton";
|
public static string defaultShader = "Spine/Skeleton";
|
||||||
public static bool initialized;
|
|
||||||
|
|
||||||
const string DEFAULT_MIX_KEY = "SPINE_DEFAULT_MIX";
|
|
||||||
|
|
||||||
|
#region Initialization
|
||||||
static SpineEditorUtilities () {
|
static SpineEditorUtilities () {
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
@ -193,8 +191,39 @@ namespace Spine.Unity.Editor {
|
|||||||
if (!initialized || Icons.skeleton == null)
|
if (!initialized || Icons.skeleton == null)
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Hierarchy Icon
|
#region Spine Preferences and Defaults
|
||||||
|
static bool preferencesLoaded = false;
|
||||||
|
|
||||||
|
[PreferenceItem("Spine")]
|
||||||
|
static void PreferencesGUI () {
|
||||||
|
if (!preferencesLoaded) {
|
||||||
|
preferencesLoaded = true;
|
||||||
|
defaultMix = EditorPrefs.GetFloat(DEFAULT_MIX_KEY, 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField("Auto-Import Settings", EditorStyles.boldLabel);
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
defaultMix = EditorGUILayout.FloatField("Default Mix", defaultMix);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
EditorPrefs.SetFloat(DEFAULT_MIX_KEY, defaultMix);
|
||||||
|
|
||||||
|
GUILayout.Space(20);
|
||||||
|
EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel);
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.PrefixLabel("TK2D");
|
||||||
|
|
||||||
|
if (GUILayout.Button("Enable", GUILayout.Width(64)))
|
||||||
|
EnableTK2D();
|
||||||
|
if (GUILayout.Button("Disable", GUILayout.Width(64)))
|
||||||
|
DisableTK2D();
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Hierarchy Icons
|
||||||
static void HierarchyWindowChanged () {
|
static void HierarchyWindowChanged () {
|
||||||
skeletonRendererTable.Clear();
|
skeletonRendererTable.Clear();
|
||||||
skeletonUtilityBoneTable.Clear();
|
skeletonUtilityBoneTable.Clear();
|
||||||
@ -218,48 +247,37 @@ namespace Spine.Unity.Editor {
|
|||||||
Rect r = new Rect(selectionRect);
|
Rect r = new Rect(selectionRect);
|
||||||
r.x = r.width - 15;
|
r.x = r.width - 15;
|
||||||
r.width = 15;
|
r.width = 15;
|
||||||
|
|
||||||
GUI.Label(r, Icons.spine);
|
GUI.Label(r, Icons.spine);
|
||||||
} else if (skeletonUtilityBoneTable.ContainsKey(instanceId)) {
|
} else if (skeletonUtilityBoneTable.ContainsKey(instanceId)) {
|
||||||
Rect r = new Rect(selectionRect);
|
Rect r = new Rect(selectionRect);
|
||||||
r.x -= 26;
|
r.x -= 26;
|
||||||
|
|
||||||
if (skeletonUtilityBoneTable[instanceId] != null) {
|
if (skeletonUtilityBoneTable[instanceId] != null) {
|
||||||
if (skeletonUtilityBoneTable[instanceId].transform.childCount == 0)
|
if (skeletonUtilityBoneTable[instanceId].transform.childCount == 0)
|
||||||
r.x += 13;
|
r.x += 13;
|
||||||
|
|
||||||
r.y += 2;
|
r.y += 2;
|
||||||
|
|
||||||
r.width = 13;
|
r.width = 13;
|
||||||
r.height = 13;
|
r.height = 13;
|
||||||
|
if (skeletonUtilityBoneTable[instanceId].mode == SkeletonUtilityBone.Mode.Follow)
|
||||||
if (skeletonUtilityBoneTable[instanceId].mode == SkeletonUtilityBone.Mode.Follow) {
|
|
||||||
GUI.DrawTexture(r, Icons.bone);
|
GUI.DrawTexture(r, Icons.bone);
|
||||||
} else {
|
else
|
||||||
GUI.DrawTexture(r, Icons.poseBones);
|
GUI.DrawTexture(r, Icons.poseBones);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (boundingBoxFollowerTable.ContainsKey(instanceId)) {
|
} else if (boundingBoxFollowerTable.ContainsKey(instanceId)) {
|
||||||
Rect r = new Rect(selectionRect);
|
Rect r = new Rect(selectionRect);
|
||||||
r.x -= 26;
|
r.x -= 26;
|
||||||
|
|
||||||
if (boundingBoxFollowerTable[instanceId] != null) {
|
if (boundingBoxFollowerTable[instanceId] != null) {
|
||||||
if (boundingBoxFollowerTable[instanceId].transform.childCount == 0)
|
if (boundingBoxFollowerTable[instanceId].transform.childCount == 0)
|
||||||
r.x += 13;
|
r.x += 13;
|
||||||
|
|
||||||
r.y += 2;
|
r.y += 2;
|
||||||
|
|
||||||
r.width = 13;
|
r.width = 13;
|
||||||
r.height = 13;
|
r.height = 13;
|
||||||
|
|
||||||
GUI.DrawTexture(r, Icons.boundingBox);
|
GUI.DrawTexture(r, Icons.boundingBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Auto-Import Entry Point
|
||||||
static void OnPostprocessAllAssets (string[] imported, string[] deleted, string[] moved, string[] movedFromAssetPaths) {
|
static void OnPostprocessAllAssets (string[] imported, string[] deleted, string[] moved, string[] movedFromAssetPaths) {
|
||||||
if (imported.Length == 0)
|
if (imported.Length == 0)
|
||||||
return;
|
return;
|
||||||
@ -298,9 +316,8 @@ namespace Spine.Unity.Editor {
|
|||||||
string extension = Path.GetExtension(str).ToLower();
|
string extension = Path.GetExtension(str).ToLower();
|
||||||
switch (extension) {
|
switch (extension) {
|
||||||
case ".txt":
|
case ".txt":
|
||||||
if (str.EndsWith(".atlas.txt")) {
|
if (str.EndsWith(".atlas.txt", System.StringComparison.Ordinal))
|
||||||
atlasPaths.Add(str);
|
atlasPaths.Add(str);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ".png":
|
case ".png":
|
||||||
case ".jpg":
|
case ".jpg":
|
||||||
@ -311,7 +328,7 @@ namespace Spine.Unity.Editor {
|
|||||||
skeletonPaths.Add(str);
|
skeletonPaths.Add(str);
|
||||||
break;
|
break;
|
||||||
case ".bytes":
|
case ".bytes":
|
||||||
if (str.ToLower().EndsWith(".skel.bytes")) {
|
if (str.ToLower().EndsWith(".skel.bytes", System.StringComparison.Ordinal)) {
|
||||||
if (IsValidSpineData((TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset))))
|
if (IsValidSpineData((TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset))))
|
||||||
skeletonPaths.Add(str);
|
skeletonPaths.Add(str);
|
||||||
}
|
}
|
||||||
@ -319,20 +336,16 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Import atlases first.
|
||||||
List<AtlasAsset> atlases = new List<AtlasAsset>();
|
var atlases = new List<AtlasAsset>();
|
||||||
|
|
||||||
//import atlases first
|
|
||||||
foreach (string ap in atlasPaths) {
|
foreach (string ap in atlasPaths) {
|
||||||
if (!reimport && CheckForValidAtlas(ap))
|
// MITCH: left note: Always import atlas data now.
|
||||||
continue;
|
|
||||||
|
|
||||||
TextAsset atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(ap, typeof(TextAsset));
|
TextAsset atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(ap, typeof(TextAsset));
|
||||||
AtlasAsset atlas = IngestSpineAtlas(atlasText);
|
AtlasAsset atlas = IngestSpineAtlas(atlasText);
|
||||||
atlases.Add(atlas);
|
atlases.Add(atlas);
|
||||||
}
|
}
|
||||||
|
|
||||||
//import skeletons and match them with atlases
|
// Import skeletons and match them with atlases.
|
||||||
bool abortSkeletonImport = false;
|
bool abortSkeletonImport = false;
|
||||||
foreach (string sp in skeletonPaths) {
|
foreach (string sp in skeletonPaths) {
|
||||||
if (!reimport && CheckForValidSkeletonData(sp)) {
|
if (!reimport && CheckForValidSkeletonData(sp)) {
|
||||||
@ -340,19 +353,27 @@ namespace Spine.Unity.Editor {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string dir = Path.GetDirectoryName(sp);
|
string dir = Path.GetDirectoryName(sp);
|
||||||
|
|
||||||
|
#if SPINE_TK2D
|
||||||
|
IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, null);
|
||||||
|
#else
|
||||||
var localAtlases = FindAtlasesAtPath(dir);
|
var localAtlases = FindAtlasesAtPath(dir);
|
||||||
var requiredPaths = GetRequiredAtlasRegions(sp);
|
var requiredPaths = GetRequiredAtlasRegions(sp);
|
||||||
var atlasMatch = GetMatchingAtlas(requiredPaths, localAtlases);
|
var atlasMatch = GetMatchingAtlas(requiredPaths, localAtlases);
|
||||||
|
|
||||||
if (atlasMatch != null) {
|
if (atlasMatch != null) {
|
||||||
IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, atlasMatch);
|
IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, atlasMatch);
|
||||||
} else {
|
} else {
|
||||||
bool resolved = false;
|
bool resolved = false;
|
||||||
while (!resolved) {
|
while (!resolved) {
|
||||||
int result = EditorUtility.DisplayDialogComplex("Skeleton JSON Import Error!", "Could not find matching AtlasAsset for " + Path.GetFileNameWithoutExtension(sp), "Select", "Skip", "Abort");
|
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(sp);
|
||||||
|
int result = EditorUtility.DisplayDialogComplex(
|
||||||
|
string.Format("Missing AtlasAsset for \"{0}\"", filename),
|
||||||
|
string.Format("Could not find matching AtlasAsset for \"{0}\"", filename),
|
||||||
|
"Choose AtlaseAssets...", "Skip this", "Stop importing all"
|
||||||
|
);
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case -1:
|
case -1:
|
||||||
Debug.Log("Select Atlas");
|
Debug.Log("Select Atlas");
|
||||||
@ -366,25 +387,19 @@ namespace Spine.Unity.Editor {
|
|||||||
IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, atlasMatch);
|
IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, atlasMatch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0: // Choose AtlaseAssets...
|
||||||
var atlasList = MultiAtlasDialog(requiredPaths, Path.GetDirectoryName(sp), Path.GetFileNameWithoutExtension(sp));
|
var atlasList = MultiAtlasDialog(requiredPaths, Path.GetDirectoryName(sp), Path.GetFileNameWithoutExtension(sp));
|
||||||
|
|
||||||
if (atlasList != null)
|
if (atlasList != null)
|
||||||
IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, atlasList.ToArray());
|
IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, atlasList.ToArray());
|
||||||
|
|
||||||
resolved = true;
|
resolved = true;
|
||||||
break;
|
break;
|
||||||
|
case 1: // Skip
|
||||||
case 1:
|
|
||||||
Debug.Log("Skipped importing: " + Path.GetFileName(sp));
|
Debug.Log("Skipped importing: " + Path.GetFileName(sp));
|
||||||
resolved = true;
|
resolved = true;
|
||||||
break;
|
break;
|
||||||
|
case 2: // Stop importing all
|
||||||
|
|
||||||
case 2:
|
|
||||||
//abort
|
|
||||||
abortSkeletonImport = true;
|
abortSkeletonImport = true;
|
||||||
resolved = true;
|
resolved = true;
|
||||||
break;
|
break;
|
||||||
@ -394,46 +409,22 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
if (abortSkeletonImport)
|
if (abortSkeletonImport)
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
// MITCH: left a todo: any post processing of images
|
||||||
//TODO: any post processing of images
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool CheckForValidSkeletonData (string skeletonJSONPath) {
|
|
||||||
|
|
||||||
string dir = Path.GetDirectoryName(skeletonJSONPath);
|
|
||||||
TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonJSONPath, typeof(TextAsset));
|
|
||||||
DirectoryInfo dirInfo = new DirectoryInfo(dir);
|
|
||||||
|
|
||||||
FileInfo[] files = dirInfo.GetFiles("*.asset");
|
|
||||||
|
|
||||||
foreach (var f in files) {
|
|
||||||
string localPath = dir + "/" + f.Name;
|
|
||||||
var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object));
|
|
||||||
if (obj is SkeletonDataAsset) {
|
|
||||||
var skeletonDataAsset = (SkeletonDataAsset)obj;
|
|
||||||
if (skeletonDataAsset.skeletonJSON == textAsset)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ResetExistingSkeletonData (string skeletonJSONPath) {
|
static void ResetExistingSkeletonData (string skeletonJSONPath) {
|
||||||
|
|
||||||
string dir = Path.GetDirectoryName(skeletonJSONPath);
|
string dir = Path.GetDirectoryName(skeletonJSONPath);
|
||||||
TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonJSONPath, typeof(TextAsset));
|
TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonJSONPath, typeof(TextAsset));
|
||||||
DirectoryInfo dirInfo = new DirectoryInfo(dir);
|
DirectoryInfo dirInfo = new DirectoryInfo(dir);
|
||||||
|
|
||||||
FileInfo[] files = dirInfo.GetFiles("*.asset");
|
FileInfo[] files = dirInfo.GetFiles("*.asset");
|
||||||
|
|
||||||
foreach (var f in files) {
|
foreach (var f in files) {
|
||||||
string localPath = dir + "/" + f.Name;
|
string localPath = dir + "/" + f.Name;
|
||||||
var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object));
|
var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object));
|
||||||
if (obj is SkeletonDataAsset) {
|
var skeletonDataAsset = obj as SkeletonDataAsset;
|
||||||
var skeletonDataAsset = (SkeletonDataAsset)obj;
|
if (skeletonDataAsset != null) {
|
||||||
|
|
||||||
if (skeletonDataAsset.skeletonJSON == textAsset) {
|
if (skeletonDataAsset.skeletonJSON == textAsset) {
|
||||||
if (Selection.activeObject == skeletonDataAsset)
|
if (Selection.activeObject == skeletonDataAsset)
|
||||||
Selection.activeObject = null;
|
Selection.activeObject = null;
|
||||||
@ -461,10 +452,14 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||||
string currentHash = skeletonData != null ? skeletonData.Hash : null;
|
string currentHash = skeletonData != null ? skeletonData.Hash : null;
|
||||||
if (currentHash == null || lastHash != currentHash) {
|
|
||||||
//do any upkeep on synchronized assets
|
#if SPINE_SKELETONANIMATOR
|
||||||
|
if (currentHash == null || lastHash != currentHash)
|
||||||
UpdateMecanimClips(skeletonDataAsset);
|
UpdateMecanimClips(skeletonDataAsset);
|
||||||
}
|
#endif
|
||||||
|
|
||||||
|
// if (currentHash == null || lastHash != currentHash)
|
||||||
|
// Do any upkeep on synchronized assets
|
||||||
|
|
||||||
if (currentHash != null) {
|
if (currentHash != null) {
|
||||||
EditorPrefs.SetString(guid + "_hash", currentHash);
|
EditorPrefs.SetString(guid + "_hash", currentHash);
|
||||||
@ -473,99 +468,62 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
static bool CheckForValidAtlas (string atlasPath) {
|
#region Match SkeletonData with Atlases
|
||||||
return false;
|
static List<AtlasAsset> MultiAtlasDialog (List<string> requiredPaths, string initialDirectory, string filename = "") {
|
||||||
//////////////DEPRECATED - always check for new atlas data now
|
|
||||||
/*
|
|
||||||
string dir = Path.GetDirectoryName(atlasPath);
|
|
||||||
TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(TextAsset));
|
|
||||||
DirectoryInfo dirInfo = new DirectoryInfo(dir);
|
|
||||||
|
|
||||||
FileInfo[] files = dirInfo.GetFiles("*.asset");
|
|
||||||
|
|
||||||
foreach (var f in files) {
|
|
||||||
string localPath = dir + "/" + f.Name;
|
|
||||||
var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object));
|
|
||||||
if (obj is AtlasAsset) {
|
|
||||||
var atlasAsset = (AtlasAsset)obj;
|
|
||||||
if (atlasAsset.atlasFile == textAsset) {
|
|
||||||
|
|
||||||
|
|
||||||
Atlas atlas = atlasAsset.GetAtlas();
|
|
||||||
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
|
|
||||||
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
|
|
||||||
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, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
|
|
||||||
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
|
|
||||||
|
|
||||||
if (prefab != null) {
|
|
||||||
Debug.Log("Updating: " + region.name);
|
|
||||||
BakeRegion(atlasAsset, region);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<AtlasAsset> MultiAtlasDialog (List<string> requiredPaths, string initialDirectory, string header = "") {
|
|
||||||
|
|
||||||
List<AtlasAsset> atlasAssets = new List<AtlasAsset>();
|
List<AtlasAsset> atlasAssets = new List<AtlasAsset>();
|
||||||
|
|
||||||
bool resolved = false;
|
bool resolved = false;
|
||||||
string lastAtlasPath = initialDirectory;
|
string lastAtlasPath = initialDirectory;
|
||||||
while (!resolved) {
|
while (!resolved) {
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.AppendLine(header);
|
|
||||||
sb.AppendLine("Atlases:");
|
|
||||||
if (atlasAssets.Count == 0) {
|
|
||||||
sb.AppendLine("\t--none--");
|
|
||||||
}
|
|
||||||
for (int i = 0; i < atlasAssets.Count; i++) {
|
|
||||||
sb.AppendLine("\t" + atlasAssets[i].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.AppendLine();
|
// Build dialog box message.
|
||||||
sb.AppendLine("Missing Regions:");
|
var missingRegions = new List<string>(requiredPaths);
|
||||||
|
var dialogText = new StringBuilder();
|
||||||
|
{
|
||||||
|
dialogText.AppendLine(string.Format("SkeletonDataAsset for \"{0}\"", filename));
|
||||||
|
dialogText.AppendLine("has missing regions.");
|
||||||
|
dialogText.AppendLine();
|
||||||
|
dialogText.AppendLine("Current Atlases:");
|
||||||
|
|
||||||
List<string> missingRegions = new List<string>(requiredPaths);
|
if (atlasAssets.Count == 0)
|
||||||
|
dialogText.AppendLine("\t--none--");
|
||||||
|
|
||||||
foreach (var atlasAsset in atlasAssets) {
|
for (int i = 0; i < atlasAssets.Count; i++)
|
||||||
var atlas = atlasAsset.GetAtlas();
|
dialogText.AppendLine("\t" + atlasAssets[i].name);
|
||||||
for (int i = 0; i < missingRegions.Count; i++) {
|
|
||||||
if (atlas.FindRegion(missingRegions[i]) != null) {
|
dialogText.AppendLine();
|
||||||
missingRegions.RemoveAt(i);
|
dialogText.AppendLine("Missing Regions:");
|
||||||
i--;
|
|
||||||
|
foreach (var atlasAsset in atlasAssets) {
|
||||||
|
var atlas = atlasAsset.GetAtlas();
|
||||||
|
for (int i = 0; i < missingRegions.Count; i++) {
|
||||||
|
if (atlas.FindRegion(missingRegions[i]) != null) {
|
||||||
|
missingRegions.RemoveAt(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int n = missingRegions.Count;
|
||||||
|
if (n == 0) break;
|
||||||
|
|
||||||
|
const int MaxListLength = 15;
|
||||||
|
for (int i = 0; (i < n && i < MaxListLength); i++)
|
||||||
|
dialogText.AppendLine("\t" + missingRegions[i]);
|
||||||
|
|
||||||
|
if (n > MaxListLength) dialogText.AppendLine(string.Format("\t... {0} more...", n - MaxListLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (missingRegions.Count == 0) {
|
// Show dialog box.
|
||||||
break;
|
int result = EditorUtility.DisplayDialogComplex(
|
||||||
}
|
"SkeletonDataAsset has missing Atlas.",
|
||||||
|
dialogText.ToString(),
|
||||||
for (int i = 0; i < missingRegions.Count; i++) {
|
"Browse...", "Import anyway", "Cancel"
|
||||||
sb.AppendLine("\t" + missingRegions[i]);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
int result = EditorUtility.DisplayDialogComplex("Atlas Selection", sb.ToString(), "Select", "Finish", "Abort");
|
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case 0:
|
case 0: // Browse...
|
||||||
AtlasAsset selectedAtlasAsset = GetAtlasDialog(lastAtlasPath);
|
AtlasAsset selectedAtlasAsset = GetAtlasDialog(lastAtlasPath);
|
||||||
if (selectedAtlasAsset != null) {
|
if (selectedAtlasAsset != null) {
|
||||||
var atlas = selectedAtlasAsset.GetAtlas();
|
var atlas = selectedAtlasAsset.GetAtlas();
|
||||||
@ -576,32 +534,26 @@ namespace Spine.Unity.Editor {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atlasAssets.Add(selectedAtlasAsset);
|
atlasAssets.Add(selectedAtlasAsset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 1: // Import anyway
|
||||||
case 1:
|
|
||||||
resolved = true;
|
resolved = true;
|
||||||
break;
|
break;
|
||||||
|
case 2: // Cancel
|
||||||
case 2:
|
|
||||||
atlasAssets = null;
|
atlasAssets = null;
|
||||||
resolved = true;
|
resolved = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return atlasAssets;
|
return atlasAssets;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AtlasAsset GetAtlasDialog (string dirPath) {
|
static AtlasAsset GetAtlasDialog (string dirPath) {
|
||||||
string path = EditorUtility.OpenFilePanel("Select AtlasAsset...", dirPath, "asset");
|
string path = EditorUtility.OpenFilePanel("Select AtlasAsset...", dirPath, "asset");
|
||||||
if (path == "")
|
|
||||||
return null;
|
if (path == "") return null; // Canceled or closed by user.
|
||||||
|
|
||||||
int subLen = Application.dataPath.Length - 6;
|
int subLen = Application.dataPath.Length - 6;
|
||||||
string assetRelativePath = path.Substring(subLen, path.Length - subLen).Replace("\\", "/");
|
string assetRelativePath = path.Substring(subLen, path.Length - subLen).Replace("\\", "/");
|
||||||
@ -641,10 +593,8 @@ namespace Spine.Unity.Editor {
|
|||||||
foreach (KeyValuePair<string, object> attachmentEntry in ((Dictionary<string, object>)slotEntry.Value)) {
|
foreach (KeyValuePair<string, object> attachmentEntry in ((Dictionary<string, object>)slotEntry.Value)) {
|
||||||
var data = ((Dictionary<string, object>)attachmentEntry.Value);
|
var data = ((Dictionary<string, object>)attachmentEntry.Value);
|
||||||
if (data.ContainsKey("type")) {
|
if (data.ContainsKey("type")) {
|
||||||
if ((string)data["type"] == "boundingbox") {
|
if ((string)data["type"] == "boundingbox")
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (data.ContainsKey("path"))
|
if (data.ContainsKey("path"))
|
||||||
requiredPaths.Add((string)data["path"]);
|
requiredPaths.Add((string)data["path"]);
|
||||||
@ -652,13 +602,13 @@ namespace Spine.Unity.Editor {
|
|||||||
requiredPaths.Add((string)data["name"]);
|
requiredPaths.Add((string)data["name"]);
|
||||||
else
|
else
|
||||||
requiredPaths.Add(attachmentEntry.Key);
|
requiredPaths.Add(attachmentEntry.Key);
|
||||||
//requiredPaths.Add((string)sdf["path"]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return requiredPaths;
|
return requiredPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AtlasAsset GetMatchingAtlas (List<string> requiredPaths, List<AtlasAsset> atlasAssets) {
|
static AtlasAsset GetMatchingAtlas (List<string> requiredPaths, List<AtlasAsset> atlasAssets) {
|
||||||
AtlasAsset atlasAssetMatch = null;
|
AtlasAsset atlasAssetMatch = null;
|
||||||
|
|
||||||
@ -676,65 +626,55 @@ namespace Spine.Unity.Editor {
|
|||||||
atlasAssetMatch = a;
|
atlasAssetMatch = a;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return atlasAssetMatch;
|
return atlasAssetMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class AtlasRequirementLoader : AttachmentLoader {
|
||||||
|
List<string> requirementList;
|
||||||
|
public AtlasRequirementLoader (List<string> requirementList) {
|
||||||
|
this.requirementList = requirementList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
|
||||||
|
requirementList.Add(path);
|
||||||
|
return new RegionAttachment(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
|
||||||
|
requirementList.Add(path);
|
||||||
|
return new MeshAttachment(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeightedMeshAttachment NewWeightedMeshAttachment(Skin skin, string name, string path) {
|
||||||
|
requirementList.Add(path);
|
||||||
|
return new WeightedMeshAttachment(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
|
||||||
|
return new BoundingBoxAttachment(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Import Atlases
|
||||||
static List<AtlasAsset> FindAtlasesAtPath (string path) {
|
static List<AtlasAsset> FindAtlasesAtPath (string path) {
|
||||||
List<AtlasAsset> arr = new List<AtlasAsset>();
|
List<AtlasAsset> arr = new List<AtlasAsset>();
|
||||||
|
|
||||||
DirectoryInfo dir = new DirectoryInfo(path);
|
DirectoryInfo dir = new DirectoryInfo(path);
|
||||||
FileInfo[] assetInfoArr = dir.GetFiles("*.asset");
|
FileInfo[] assetInfoArr = dir.GetFiles("*.asset");
|
||||||
|
|
||||||
int subLen = Application.dataPath.Length - 6;
|
int subLen = Application.dataPath.Length - 6;
|
||||||
|
|
||||||
foreach (var f in assetInfoArr) {
|
foreach (var f in assetInfoArr) {
|
||||||
string assetRelativePath = f.FullName.Substring(subLen, f.FullName.Length - subLen).Replace("\\", "/");
|
string assetRelativePath = f.FullName.Substring(subLen, f.FullName.Length - subLen).Replace("\\", "/");
|
||||||
|
|
||||||
Object obj = AssetDatabase.LoadAssetAtPath(assetRelativePath, typeof(AtlasAsset));
|
Object obj = AssetDatabase.LoadAssetAtPath(assetRelativePath, typeof(AtlasAsset));
|
||||||
if (obj != null) {
|
if (obj != null)
|
||||||
arr.Add(obj as AtlasAsset);
|
arr.Add(obj as AtlasAsset);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsValidSpineData (TextAsset asset) {
|
|
||||||
if (asset.name.Contains(".skel")) return true;
|
|
||||||
|
|
||||||
object obj = null;
|
|
||||||
try {
|
|
||||||
obj = Json.Deserialize(new StringReader(asset.text));
|
|
||||||
} catch (System.Exception) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj == null) {
|
|
||||||
Debug.LogError("Is not valid JSON");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var root = obj as Dictionary<string, object>;
|
|
||||||
if (root == null) {
|
|
||||||
Debug.LogError("Parser returned an incorrect type.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!root.ContainsKey("skeleton"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// var skeletonInfo = (Dictionary<string, object>)root["skeleton"];
|
|
||||||
// string spineVersion = (string)skeletonInfo["spine"];
|
|
||||||
// TODO: Warn users of old version incompatibility.
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static AtlasAsset IngestSpineAtlas (TextAsset atlasText) {
|
static AtlasAsset IngestSpineAtlas (TextAsset atlasText) {
|
||||||
if (atlasText == null) {
|
if (atlasText == null) {
|
||||||
Debug.LogWarning("Atlas source cannot be null!");
|
Debug.LogWarning("Atlas source cannot be null!");
|
||||||
@ -805,7 +745,6 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
mat.mainTexture = texture;
|
mat.mainTexture = texture;
|
||||||
EditorUtility.SetDirty(mat);
|
EditorUtility.SetDirty(mat);
|
||||||
|
|
||||||
AssetDatabase.SaveAssets();
|
AssetDatabase.SaveAssets();
|
||||||
|
|
||||||
atlasAsset.materials[i] = mat;
|
atlasAsset.materials[i] = mat;
|
||||||
@ -820,11 +759,9 @@ namespace Spine.Unity.Editor {
|
|||||||
atlasAsset.Reset();
|
atlasAsset.Reset();
|
||||||
|
|
||||||
EditorUtility.SetDirty(atlasAsset);
|
EditorUtility.SetDirty(atlasAsset);
|
||||||
|
|
||||||
AssetDatabase.SaveAssets();
|
AssetDatabase.SaveAssets();
|
||||||
|
|
||||||
|
// Iterate regions and bake marked.
|
||||||
//iterate regions and bake marked
|
|
||||||
Atlas atlas = atlasAsset.GetAtlas();
|
Atlas atlas = atlasAsset.GetAtlas();
|
||||||
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
|
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
|
||||||
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
|
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
|
||||||
@ -837,7 +774,6 @@ namespace Spine.Unity.Editor {
|
|||||||
AtlasRegion region = regions[i];
|
AtlasRegion region = regions[i];
|
||||||
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
|
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
|
||||||
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
|
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
|
||||||
|
|
||||||
if (prefab != null) {
|
if (prefab != null) {
|
||||||
BakeRegion(atlasAsset, region, false);
|
BakeRegion(atlasAsset, region, false);
|
||||||
hasBakedRegions = true;
|
hasBakedRegions = true;
|
||||||
@ -851,7 +787,9 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
return (AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset));
|
return (AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset));
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Bake Atlas Region
|
||||||
public static GameObject BakeRegion (AtlasAsset atlasAsset, AtlasRegion region, bool autoSave = true) {
|
public static GameObject BakeRegion (AtlasAsset atlasAsset, AtlasRegion region, bool autoSave = true) {
|
||||||
Atlas atlas = atlasAsset.GetAtlas();
|
Atlas atlas = atlasAsset.GetAtlas();
|
||||||
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
||||||
@ -869,7 +807,7 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
if (prefab == null) {
|
if (prefab == null) {
|
||||||
root = new GameObject("temp", typeof(MeshFilter), typeof(MeshRenderer));
|
root = new GameObject("temp", typeof(MeshFilter), typeof(MeshRenderer));
|
||||||
prefab = (GameObject)PrefabUtility.CreatePrefab(bakedPrefabPath, root);
|
prefab = PrefabUtility.CreatePrefab(bakedPrefabPath, root);
|
||||||
isNewPrefab = true;
|
isNewPrefab = true;
|
||||||
Object.DestroyImmediate(root);
|
Object.DestroyImmediate(root);
|
||||||
}
|
}
|
||||||
@ -891,23 +829,45 @@ namespace Spine.Unity.Editor {
|
|||||||
AssetDatabase.Refresh();
|
AssetDatabase.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
prefab.GetComponent<MeshRenderer>().sharedMaterial = mat;
|
prefab.GetComponent<MeshRenderer>().sharedMaterial = mat;
|
||||||
|
|
||||||
return prefab;
|
return prefab;
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
public static string GetPathSafeRegionName (AtlasRegion region) {
|
#region Import SkeletonData (json or binary)
|
||||||
return region.name.Replace("/", "_");
|
|
||||||
}
|
|
||||||
|
|
||||||
static SkeletonDataAsset IngestSpineProject (TextAsset spineJson, params AtlasAsset[] atlasAssets) {
|
static SkeletonDataAsset IngestSpineProject (TextAsset spineJson, params AtlasAsset[] atlasAssets) {
|
||||||
string primaryName = Path.GetFileNameWithoutExtension(spineJson.name);
|
string primaryName = Path.GetFileNameWithoutExtension(spineJson.name);
|
||||||
string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(spineJson));
|
string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(spineJson));
|
||||||
string filePath = assetPath + "/" + primaryName + "_SkeletonData.asset";
|
string filePath = assetPath + "/" + primaryName + "_SkeletonData.asset";
|
||||||
|
|
||||||
if (spineJson != null && atlasAssets != null) {
|
#if SPINE_TK2D
|
||||||
|
if (spineJson != null) {
|
||||||
|
SkeletonDataAsset skeletonDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset));
|
||||||
|
if (skeletonDataAsset == null) {
|
||||||
|
skeletonDataAsset = SkeletonDataAsset.CreateInstance<SkeletonDataAsset>();
|
||||||
|
skeletonDataAsset.skeletonJSON = spineJson;
|
||||||
|
skeletonDataAsset.fromAnimation = new string[0];
|
||||||
|
skeletonDataAsset.toAnimation = new string[0];
|
||||||
|
skeletonDataAsset.duration = new float[0];
|
||||||
|
skeletonDataAsset.defaultMix = defaultMix;
|
||||||
|
skeletonDataAsset.scale = defaultScale;
|
||||||
|
|
||||||
|
AssetDatabase.CreateAsset(skeletonDataAsset, filePath);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
} else {
|
||||||
|
skeletonDataAsset.Reset();
|
||||||
|
skeletonDataAsset.GetSkeletonData(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return skeletonDataAsset;
|
||||||
|
} else {
|
||||||
|
EditorUtility.DisplayDialog("Error!", "Tried to ingest null Spine data.", "OK");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
if (spineJson != null && atlasAssets != null) {
|
||||||
SkeletonDataAsset skelDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset));
|
SkeletonDataAsset skelDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset));
|
||||||
if (skelDataAsset == null) {
|
if (skelDataAsset == null) {
|
||||||
skelDataAsset = SkeletonDataAsset.CreateInstance<SkeletonDataAsset>();
|
skelDataAsset = SkeletonDataAsset.CreateInstance<SkeletonDataAsset>();
|
||||||
@ -932,7 +892,52 @@ namespace Spine.Unity.Editor {
|
|||||||
EditorUtility.DisplayDialog("Error!", "Must specify both Spine JSON and AtlasAsset array", "OK");
|
EditorUtility.DisplayDialog("Error!", "Must specify both Spine JSON and AtlasAsset array", "OK");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Checking Methods
|
||||||
|
static bool CheckForValidSkeletonData (string skeletonJSONPath) {
|
||||||
|
string dir = Path.GetDirectoryName(skeletonJSONPath);
|
||||||
|
TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonJSONPath, typeof(TextAsset));
|
||||||
|
DirectoryInfo dirInfo = new DirectoryInfo(dir);
|
||||||
|
FileInfo[] files = dirInfo.GetFiles("*.asset");
|
||||||
|
|
||||||
|
foreach (var path in files) {
|
||||||
|
string localPath = dir + "/" + path.Name;
|
||||||
|
var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object));
|
||||||
|
var skeletonDataAsset = obj as SkeletonDataAsset;
|
||||||
|
if (skeletonDataAsset != null && skeletonDataAsset.skeletonJSON == textAsset)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsValidSpineData (TextAsset asset) {
|
||||||
|
if (asset.name.Contains(".skel")) return true;
|
||||||
|
|
||||||
|
object obj = null;
|
||||||
|
obj = Json.Deserialize(new StringReader(asset.text));
|
||||||
|
|
||||||
|
if (obj == null) {
|
||||||
|
Debug.LogError("Is not valid JSON.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var root = obj as Dictionary<string, object>;
|
||||||
|
if (root == null) {
|
||||||
|
Debug.LogError("Parser returned an incorrect type.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.ContainsKey("skeleton");
|
||||||
|
|
||||||
|
// TODO: Warn users of old version incompatibility.
|
||||||
|
// var skeletonInfo = (Dictionary<string, object>)root["skeleton"];
|
||||||
|
// string spineVersion = (string)skeletonInfo["spine"];
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region SkeletonAnimation Menu
|
#region SkeletonAnimation Menu
|
||||||
[MenuItem("Assets/Spine/Instantiate (SkeletonAnimation)", false, 10)]
|
[MenuItem("Assets/Spine/Instantiate (SkeletonAnimation)", false, 10)]
|
||||||
@ -963,18 +968,20 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static SkeletonAnimation InstantiateSkeletonAnimation (SkeletonDataAsset skeletonDataAsset, string skinName) {
|
public static SkeletonAnimation InstantiateSkeletonAnimation (SkeletonDataAsset skeletonDataAsset, string skinName) {
|
||||||
return InstantiateSkeletonAnimation(skeletonDataAsset, skeletonDataAsset.GetSkeletonData(true).FindSkin(skinName));
|
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||||
|
var skin = skeletonData != null ? skeletonData.FindSkin(skinName) : null;
|
||||||
|
return InstantiateSkeletonAnimation(skeletonDataAsset, skin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SkeletonAnimation InstantiateSkeletonAnimation (SkeletonDataAsset skeletonDataAsset, Skin skin = null) {
|
public static SkeletonAnimation InstantiateSkeletonAnimation (SkeletonDataAsset skeletonDataAsset, Skin skin = null) {
|
||||||
string spineGameObjectName = string.Format("Spine GameObject ({0})", skeletonDataAsset.name.Replace("_SkeletonData", ""));
|
string spineGameObjectName = string.Format("Spine GameObject ({0})", skeletonDataAsset.name.Replace("_SkeletonData", ""));
|
||||||
GameObject go = new GameObject(spineGameObjectName, typeof(MeshFilter), typeof(MeshRenderer), typeof(SkeletonAnimation));
|
GameObject go = new GameObject(spineGameObjectName, typeof(MeshFilter), typeof(MeshRenderer), typeof(SkeletonAnimation));
|
||||||
SkeletonAnimation anim = go.GetComponent<SkeletonAnimation>();
|
SkeletonAnimation newSkeletonAnimation = go.GetComponent<SkeletonAnimation>();
|
||||||
anim.skeletonDataAsset = skeletonDataAsset;
|
newSkeletonAnimation.skeletonDataAsset = skeletonDataAsset;
|
||||||
|
|
||||||
bool requiresNormals = false;
|
bool requiresNormals = false;
|
||||||
|
|
||||||
foreach (AtlasAsset atlasAsset in anim.skeletonDataAsset.atlasAssets) {
|
foreach (AtlasAsset atlasAsset in newSkeletonAnimation.skeletonDataAsset.atlasAssets) {
|
||||||
foreach (Material m in atlasAsset.materials) {
|
foreach (Material m in atlasAsset.materials) {
|
||||||
if (m.shader.name.Contains("Lit")) {
|
if (m.shader.name.Contains("Lit")) {
|
||||||
requiresNormals = true;
|
requiresNormals = true;
|
||||||
@ -983,9 +990,7 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newSkeletonAnimation.calculateNormals = requiresNormals;
|
||||||
|
|
||||||
anim.calculateNormals = requiresNormals;
|
|
||||||
|
|
||||||
SkeletonData data = skeletonDataAsset.GetSkeletonData(true);
|
SkeletonData data = skeletonDataAsset.GetSkeletonData(true);
|
||||||
|
|
||||||
@ -994,8 +999,12 @@ namespace Spine.Unity.Editor {
|
|||||||
string reloadAtlasPath = AssetDatabase.GetAssetPath(skeletonDataAsset.atlasAssets[i]);
|
string reloadAtlasPath = AssetDatabase.GetAssetPath(skeletonDataAsset.atlasAssets[i]);
|
||||||
skeletonDataAsset.atlasAssets[i] = (AtlasAsset)AssetDatabase.LoadAssetAtPath(reloadAtlasPath, typeof(AtlasAsset));
|
skeletonDataAsset.atlasAssets[i] = (AtlasAsset)AssetDatabase.LoadAssetAtPath(reloadAtlasPath, typeof(AtlasAsset));
|
||||||
}
|
}
|
||||||
|
data = skeletonDataAsset.GetSkeletonData(false);
|
||||||
|
}
|
||||||
|
|
||||||
data = skeletonDataAsset.GetSkeletonData(true);
|
if (data == null) {
|
||||||
|
Debug.LogWarning("Tried to instantiate a skeleton from an invalid SkeletonDataAsset.");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skin == null)
|
if (skin == null)
|
||||||
@ -1004,17 +1013,17 @@ namespace Spine.Unity.Editor {
|
|||||||
if (skin == null)
|
if (skin == null)
|
||||||
skin = data.Skins.Items[0];
|
skin = data.Skins.Items[0];
|
||||||
|
|
||||||
anim.Initialize(false);
|
newSkeletonAnimation.Initialize(false);
|
||||||
|
|
||||||
anim.skeleton.SetSkin(skin);
|
newSkeletonAnimation.skeleton.SetSkin(skin);
|
||||||
anim.initialSkinName = skin.Name;
|
newSkeletonAnimation.initialSkinName = skin.Name;
|
||||||
|
|
||||||
anim.skeleton.Update(1);
|
newSkeletonAnimation.skeleton.Update(1);
|
||||||
anim.state.Update(1);
|
newSkeletonAnimation.state.Update(1);
|
||||||
anim.state.Apply(anim.skeleton);
|
newSkeletonAnimation.state.Apply(newSkeletonAnimation.skeleton);
|
||||||
anim.skeleton.UpdateWorldTransform();
|
newSkeletonAnimation.skeleton.UpdateWorldTransform();
|
||||||
|
|
||||||
return anim;
|
return newSkeletonAnimation;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -1115,37 +1124,7 @@ namespace Spine.Unity.Editor {
|
|||||||
#endif
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Spine Preferences
|
#region TK2D Support
|
||||||
static bool preferencesLoaded = false;
|
|
||||||
|
|
||||||
[PreferenceItem("Spine")]
|
|
||||||
static void PreferencesGUI () {
|
|
||||||
if (!preferencesLoaded) {
|
|
||||||
preferencesLoaded = true;
|
|
||||||
defaultMix = EditorPrefs.GetFloat(DEFAULT_MIX_KEY, 0.2f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EditorGUILayout.LabelField("Auto-Import Settings", EditorStyles.boldLabel);
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
defaultMix = EditorGUILayout.FloatField("Default Mix", defaultMix);
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
EditorPrefs.SetFloat(DEFAULT_MIX_KEY, defaultMix);
|
|
||||||
|
|
||||||
GUILayout.Space(20);
|
|
||||||
EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel);
|
|
||||||
GUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.PrefixLabel("TK2D");
|
|
||||||
|
|
||||||
if (GUILayout.Button("Enable", GUILayout.Width(64)))
|
|
||||||
EnableTK2D();
|
|
||||||
if (GUILayout.Button("Disable", GUILayout.Width(64)))
|
|
||||||
DisableTK2D();
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
//TK2D Support
|
|
||||||
const string SPINE_TK2D_DEFINE = "SPINE_TK2D";
|
const string SPINE_TK2D_DEFINE = "SPINE_TK2D";
|
||||||
|
|
||||||
static void EnableTK2D () {
|
static void EnableTK2D () {
|
||||||
@ -1195,32 +1174,10 @@ namespace Spine.Unity.Editor {
|
|||||||
Debug.LogWarning("Already Removed Scripting Define Symbol " + SPINE_TK2D_DEFINE);
|
Debug.LogWarning("Already Removed Scripting Define Symbol " + SPINE_TK2D_DEFINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
public class AtlasRequirementLoader : AttachmentLoader {
|
public static string GetPathSafeRegionName (AtlasRegion region) {
|
||||||
|
return region.name.Replace("/", "_");
|
||||||
List<string> requirementList;
|
|
||||||
public AtlasRequirementLoader (List<string> requirementList) {
|
|
||||||
this.requirementList = requirementList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
|
|
||||||
requirementList.Add(path);
|
|
||||||
return new RegionAttachment(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
|
|
||||||
requirementList.Add(path);
|
|
||||||
return new MeshAttachment(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WeightedMeshAttachment NewWeightedMeshAttachment(Skin skin, string name, string path) {
|
|
||||||
requirementList.Add(path);
|
|
||||||
return new WeightedMeshAttachment(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
|
|
||||||
return new BoundingBoxAttachment(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
//Shader written by Alex Dixon
|
//Shader written by Alex Dixon
|
||||||
Shader "Spine/SkeletonGhost"
|
Shader "Spine/Special/SkeletonGhost"
|
||||||
{
|
{
|
||||||
Properties
|
Properties
|
||||||
{
|
{
|
||||||
@ -32,14 +32,12 @@ Shader "Spine/SkeletonGhost"
|
|||||||
float4 vertex : POSITION;
|
float4 vertex : POSITION;
|
||||||
float2 texcoord : TEXCOORD0;
|
float2 texcoord : TEXCOORD0;
|
||||||
float4 color : COLOR;
|
float4 color : COLOR;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vertex_output
|
struct vertex_output
|
||||||
{
|
{
|
||||||
float4 pos : SV_POSITION;
|
float4 pos : SV_POSITION;
|
||||||
float2 uv : TEXCOORD0;
|
float2 uv : TEXCOORD0;
|
||||||
|
|
||||||
float4 color : COLOR;
|
float4 color : COLOR;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ namespace Spine.Unity.Modules {
|
|||||||
|
|
||||||
void Start () {
|
void Start () {
|
||||||
if (ghostShader == null)
|
if (ghostShader == null)
|
||||||
ghostShader = Shader.Find("Spine/SkeletonGhost");
|
ghostShader = Shader.Find("Spine/Special/SkeletonGhost");
|
||||||
|
|
||||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||||
meshFilter = GetComponent<MeshFilter>();
|
meshFilter = GetComponent<MeshFilter>();
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
Shader "Spine/Bones" {
|
Shader "Hidden/Spine/Bones" {
|
||||||
Properties {
|
Properties {
|
||||||
_Color ("Color", Color) = (0.5,0.5,0.5,0.5)
|
_Color ("Color", Color) = (0.5,0.5,0.5,0.5)
|
||||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||||
@ -57,7 +57,6 @@ Category {
|
|||||||
|
|
||||||
sampler2D_float _CameraDepthTexture;
|
sampler2D_float _CameraDepthTexture;
|
||||||
|
|
||||||
|
|
||||||
fixed4 frag (v2f i) : SV_Target
|
fixed4 frag (v2f i) : SV_Target
|
||||||
{
|
{
|
||||||
return 2.0f * i.color * _Color * tex2D(_MainTex, i.texcoord);
|
return 2.0f * i.color * _Color * tex2D(_MainTex, i.texcoord);
|
||||||
|
|||||||
@ -1,21 +1,12 @@
|
|||||||
Shader "Spine/HiddenPass" {
|
Shader "Spine/Special/HiddenPass" {
|
||||||
SubShader
|
SubShader
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
Tags {"Queue" = "Geometry-1" }
|
Tags {"Queue" = "Geometry-1" }
|
||||||
|
|
||||||
Lighting Off
|
Lighting Off
|
||||||
|
|
||||||
Pass
|
Pass
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
ZWrite Off
|
ZWrite Off
|
||||||
|
|
||||||
ColorMask 0
|
ColorMask 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -257,7 +257,9 @@ namespace Spine.Unity {
|
|||||||
var workingSubmeshInstructions = workingInstruction.submeshInstructions; // Items array should not be cached. There is dynamic writing to this list.
|
var workingSubmeshInstructions = workingInstruction.submeshInstructions; // Items array should not be cached. There is dynamic writing to this list.
|
||||||
workingSubmeshInstructions.Clear(false);
|
workingSubmeshInstructions.Clear(false);
|
||||||
|
|
||||||
|
#if !SPINE_TK2D
|
||||||
bool isCustomSlotMaterialsPopulated = customSlotMaterials.Count > 0;
|
bool isCustomSlotMaterialsPopulated = customSlotMaterials.Count > 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
int vertexCount = 0;
|
int vertexCount = 0;
|
||||||
int submeshVertexCount = 0;
|
int submeshVertexCount = 0;
|
||||||
|
|||||||
@ -114,8 +114,8 @@ namespace Spine.Unity.Editor {
|
|||||||
Vector3 forward = transform.TransformDirection(rot * Vector3.right);
|
Vector3 forward = transform.TransformDirection(rot * Vector3.right);
|
||||||
forward *= flipRotation;
|
forward *= flipRotation;
|
||||||
|
|
||||||
SpineEditorUtilities.Icons.boneMaterial.SetPass(0);
|
SpineEditorUtilities.Icons.BoneMaterial.SetPass(0);
|
||||||
Graphics.DrawMeshNow(SpineEditorUtilities.Icons.boneMesh, Matrix4x4.TRS(vec, Quaternion.LookRotation(transform.forward, forward), Vector3.one * b.Data.Length * b.WorldScaleX));
|
Graphics.DrawMeshNow(SpineEditorUtilities.Icons.BoneMesh, Matrix4x4.TRS(vec, Quaternion.LookRotation(transform.forward, forward), Vector3.one * b.Data.Length * b.WorldScaleX));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user