Compare commits
No commits in common. "966acd38e1002c18973cf395e2825feb100eeba0" and "27b7cf979b8312aa1f902f72e1485214c8803fb3" have entirely different histories.
966acd38e1
...
27b7cf979b
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bda3fb9806abb464482e9cb8e77949cd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,39 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b29e98153ec2fbd44b8f7da1b41194e8, type: 3}
|
||||
m_Name: SpineSettings
|
||||
m_EditorClassIdentifier:
|
||||
defaultScale: 0.01
|
||||
defaultMix: 0.2
|
||||
defaultShader: Spine/Skeleton
|
||||
defaultZSpacing: 0
|
||||
defaultInstantiateLoop: 1
|
||||
defaultPhysicsPositionInheritance: {x: 1, y: 1}
|
||||
defaultPhysicsRotationInheritance: 1
|
||||
showHierarchyIcons: 1
|
||||
reloadAfterPlayMode: 1
|
||||
setTextureImporterSettings: 1
|
||||
textureSettingsReference:
|
||||
fixPrefabOverrideViaMeshFilter: 0
|
||||
removePrefabPreviewMeshes: 0
|
||||
blendModeMaterialMultiply: {fileID: 0}
|
||||
blendModeMaterialScreen: {fileID: 0}
|
||||
blendModeMaterialAdditive: {fileID: 0}
|
||||
atlasTxtImportWarning: 1
|
||||
textureImporterWarning: 1
|
||||
componentMaterialWarning: 1
|
||||
skeletonDataAssetNoFileError: 1
|
||||
autoReloadSceneSkeletons: 1
|
||||
handleScale: 1
|
||||
mecanimEventIncludeFolderName: 1
|
||||
timelineDefaultMixDuration: 0
|
||||
timelineUseBlendDuration: 1
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd90f0f8a3e9d0544bbd18c6257570fc
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -547,7 +547,11 @@ RectTransform:
|
||||
- {fileID: 2135586306}
|
||||
- {fileID: 1584193622}
|
||||
- {fileID: 1995711213}
|
||||
- {fileID: 332149378}
|
||||
- {fileID: 580834436}
|
||||
- {fileID: 2029421261}
|
||||
- {fileID: 252325264}
|
||||
- {fileID: 935748551}
|
||||
m_Father: {fileID: 1225833476}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@ -835,7 +839,7 @@ GameObject:
|
||||
- component: {fileID: 214046554}
|
||||
- component: {fileID: 214046553}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_Name: Text (Legacy)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -1146,7 +1150,6 @@ GameObject:
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 252325264}
|
||||
- component: {fileID: 252325265}
|
||||
m_Layer: 5
|
||||
m_Name: HegemonPanel
|
||||
m_TagString: Untagged
|
||||
@ -1161,35 +1164,21 @@ RectTransform:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 252325263}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 43098355}
|
||||
- {fileID: 394223518}
|
||||
m_Father: {fileID: 1225833476}
|
||||
m_RootOrder: 6
|
||||
m_Father: {fileID: 142654719}
|
||||
m_RootOrder: 11
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5398135, y: 0.882}
|
||||
m_AnchorMax: {x: 1, y: 0.966}
|
||||
m_AnchoredPosition: {x: -2.580017, y: -9.944824}
|
||||
m_SizeDelta: {x: 8.150024, y: 21.190414}
|
||||
m_SizeDelta: {x: 8.150024, y: 21.1904}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &252325265
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 252325263}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: bccc9804fcaee0b4dbf55f78a599bc2c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
timeText: {fileID: 1632850612}
|
||||
timeNum: 0
|
||||
--- !u!1 &271727214
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -1242,7 +1231,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 0
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
@ -1279,7 +1268,7 @@ GameObject:
|
||||
- component: {fileID: 284545412}
|
||||
- component: {fileID: 284545411}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_Name: Text (Legacy)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -1426,13 +1415,13 @@ RectTransform:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 332149377}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1225833476}
|
||||
m_RootOrder: 7
|
||||
m_Father: {fileID: 142654719}
|
||||
m_RootOrder: 8
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0.93435806}
|
||||
m_AnchorMax: {x: 0.2895423, y: 0.98676854}
|
||||
@ -1975,20 +1964,20 @@ RectTransform:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 580834435}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1406968644}
|
||||
- {fileID: 1804033313}
|
||||
m_Father: {fileID: 1225833476}
|
||||
m_RootOrder: 5
|
||||
m_Father: {fileID: 142654719}
|
||||
m_RootOrder: 9
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.04054228, y: 0.901642}
|
||||
m_AnchorMax: {x: 0.2895423, y: 0.93435806}
|
||||
m_AnchoredPosition: {x: 2.9500732, y: -1.7998047}
|
||||
m_SizeDelta: {x: -0.83999634, y: 5.9396896}
|
||||
m_SizeDelta: {x: -0.83999634, y: 5.9396973}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &586134487
|
||||
GameObject:
|
||||
@ -2040,7 +2029,7 @@ GameObject:
|
||||
- component: {fileID: 632503726}
|
||||
- component: {fileID: 632503725}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_Name: Text (Legacy)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -2907,7 +2896,6 @@ GameObject:
|
||||
- component: {fileID: 935748551}
|
||||
- component: {fileID: 935748553}
|
||||
- component: {fileID: 935748552}
|
||||
- component: {fileID: 935748554}
|
||||
m_Layer: 5
|
||||
m_Name: BettingBtns
|
||||
m_TagString: Untagged
|
||||
@ -2922,7 +2910,7 @@ RectTransform:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 935748550}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
@ -2930,8 +2918,8 @@ RectTransform:
|
||||
- {fileID: 1227559356}
|
||||
- {fileID: 1954526985}
|
||||
- {fileID: 1737087530}
|
||||
m_Father: {fileID: 1225833476}
|
||||
m_RootOrder: 4
|
||||
m_Father: {fileID: 142654719}
|
||||
m_RootOrder: 12
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.15748437}
|
||||
m_AnchorMax: {x: 0.5, y: 0.15748437}
|
||||
@ -2976,22 +2964,6 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 935748550}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &935748554
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 935748550}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4fb563e68ba8d9747a0dc8bd431d8495, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
BetList: {fileID: 1737087529}
|
||||
NumBtn: {fileID: 1954526986}
|
||||
BetText: {fileID: 251123273}
|
||||
BetValue: 0
|
||||
--- !u!1 &1049673026
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -3596,10 +3568,6 @@ RectTransform:
|
||||
- {fileID: 142654719}
|
||||
- {fileID: 760515341}
|
||||
- {fileID: 86707888}
|
||||
- {fileID: 935748551}
|
||||
- {fileID: 580834436}
|
||||
- {fileID: 252325264}
|
||||
- {fileID: 332149378}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@ -3743,7 +3711,7 @@ GameObject:
|
||||
- component: {fileID: 1227980072}
|
||||
- component: {fileID: 1227980071}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_Name: Text (Legacy)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -4891,7 +4859,7 @@ GameObject:
|
||||
- component: {fileID: 1565478605}
|
||||
- component: {fileID: 1565478604}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_Name: Text (Legacy)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -6572,11 +6540,11 @@ RectTransform:
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 142654719}
|
||||
m_RootOrder: 8
|
||||
m_RootOrder: 10
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0.12415764}
|
||||
m_AnchoredPosition: {x: 0, y: -0.49902344}
|
||||
m_AnchoredPosition: {x: 0, y: -0.49951172}
|
||||
m_SizeDelta: {x: -3, y: -1}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &2029421262
|
||||
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a04ee1d11f4fbf14cbabb39c94909c0a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,44 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class BettingBtn : MonoBehaviour
|
||||
{
|
||||
public GameObject BetList;
|
||||
public Button NumBtn;
|
||||
public Text BetText;
|
||||
public float BetValue;//投注的值
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
BetList.SetActive(false);
|
||||
NumBtn.onClick.AddListener(OnClickNumBtn);
|
||||
BetValue = 50;//默认50
|
||||
SetBet();
|
||||
}
|
||||
|
||||
void OnClickNumBtn()
|
||||
{
|
||||
BetList.SetActive(true);
|
||||
|
||||
}
|
||||
|
||||
void SetBet()
|
||||
{
|
||||
// 获取所有的Button组件
|
||||
Button[] buttons = BetList.GetComponentsInChildren<Button>();
|
||||
|
||||
// 遍历每一个Button,添加点击事件
|
||||
foreach (Button button in buttons)
|
||||
{
|
||||
button.onClick.AddListener(() => {
|
||||
BetText.text = button.transform.GetComponentInChildren<Text>().text;
|
||||
BetValue = float.Parse(BetText.text);
|
||||
BetList.SetActive(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fb563e68ba8d9747a0dc8bd431d8495
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,33 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class HegemonTime : MonoBehaviour
|
||||
{
|
||||
public Text timeText;
|
||||
public int timeNum;
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
timeNum = 60;
|
||||
StartCoroutine(StartGame());
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
|
||||
}
|
||||
private IEnumerator StartGame()
|
||||
{
|
||||
while (timeNum >=0)
|
||||
{
|
||||
timeText.text = timeNum.ToString(); // ÏÔʾÕûÊýÃëÊý
|
||||
yield return new WaitForSeconds(1f); // µÈ´ý1Ãë
|
||||
timeNum -= 1;
|
||||
}
|
||||
timeNum = 60;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bccc9804fcaee0b4dbf55f78a599bc2c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30918bcaadaaecc42bc215ff52f75b21
|
||||
folderAsset: yes
|
||||
timeCreated: 1488288531
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f09c19426de438b408307e7ff432e4b5
|
||||
timeCreated: 1727118056
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad14d5a4cd7a0444286d315541ee0495
|
||||
folderAsset: yes
|
||||
timeCreated: 1527569319
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "spine-unity-editor",
|
||||
"references": [
|
||||
"spine-csharp",
|
||||
"spine-unity"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 173464ddf4cdb6640a4dfa8a9281ad69
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83fbec88df35fe34bab43a5dde6788af
|
||||
folderAsset: yes
|
||||
timeCreated: 1527569675
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,5 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0e95036e72b08544a9d295dd4366f40
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb646ac6e394e534b80d5cac61478488
|
||||
folderAsset: yes
|
||||
timeCreated: 1563305058
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,182 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Editor = UnityEditor.Editor;
|
||||
|
||||
[CustomEditor(typeof(AnimationReferenceAsset))]
|
||||
public class AnimationReferenceAssetEditor : Editor {
|
||||
|
||||
const string InspectorHelpText = "This is a Spine-Unity Animation Reference Asset. It serializes a reference to a SkeletonData asset and an animationName. It does not contain actual animation data. At runtime, it stores a reference to a Spine.Animation.\n\n" +
|
||||
"You can use this in your AnimationState calls instead of a string animation name or a Spine.Animation reference. Use its implicit conversion into Spine.Animation or its .Animation property.\n\n" +
|
||||
"Use AnimationReferenceAssets as an alternative to storing strings or finding animations and caching per component. This only does the lookup by string once, and allows you to store and manage animations via asset references.";
|
||||
|
||||
readonly SkeletonInspectorPreview preview = new SkeletonInspectorPreview();
|
||||
FieldInfo skeletonDataAssetField = typeof(AnimationReferenceAsset).GetField("skeletonDataAsset", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
FieldInfo nameField = typeof(AnimationReferenceAsset).GetField("animationName", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
AnimationReferenceAsset ThisAnimationReferenceAsset { get { return target as AnimationReferenceAsset; } }
|
||||
SkeletonDataAsset ThisSkeletonDataAsset { get { return skeletonDataAssetField.GetValue(ThisAnimationReferenceAsset) as SkeletonDataAsset; } }
|
||||
string ThisAnimationName { get { return nameField.GetValue(ThisAnimationReferenceAsset) as string; } }
|
||||
|
||||
bool changeNextFrame = false;
|
||||
SerializedProperty animationNameProperty;
|
||||
SkeletonDataAsset lastSkeletonDataAsset;
|
||||
SkeletonData lastSkeletonData;
|
||||
|
||||
void OnEnable () { HandleOnEnablePreview(); }
|
||||
void OnDestroy () {
|
||||
HandleOnDestroyPreview();
|
||||
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
|
||||
EditorApplication.update -= preview.HandleEditorUpdate;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
animationNameProperty = animationNameProperty ?? serializedObject.FindProperty("animationName");
|
||||
string animationName = animationNameProperty.stringValue;
|
||||
|
||||
Animation animation = null;
|
||||
if (ThisSkeletonDataAsset != null) {
|
||||
SkeletonData skeletonData = ThisSkeletonDataAsset.GetSkeletonData(true);
|
||||
if (skeletonData != null) {
|
||||
animation = skeletonData.FindAnimation(animationName);
|
||||
}
|
||||
}
|
||||
bool animationNotFound = (animation == null);
|
||||
|
||||
if (changeNextFrame) {
|
||||
changeNextFrame = false;
|
||||
|
||||
if (ThisSkeletonDataAsset != lastSkeletonDataAsset || ThisSkeletonDataAsset.GetSkeletonData(true) != lastSkeletonData) {
|
||||
preview.Clear();
|
||||
preview.Initialize(Repaint, ThisSkeletonDataAsset, LastSkinName);
|
||||
|
||||
if (animationNotFound) {
|
||||
animationNameProperty.stringValue = "";
|
||||
preview.ClearAnimationSetupPose();
|
||||
}
|
||||
}
|
||||
|
||||
preview.ClearAnimationSetupPose();
|
||||
|
||||
if (!string.IsNullOrEmpty(animationNameProperty.stringValue))
|
||||
preview.PlayPauseAnimation(animationNameProperty.stringValue, true);
|
||||
}
|
||||
|
||||
//EditorGUILayout.HelpBox(AnimationReferenceAssetEditor.InspectorHelpText, MessageType.Info, true);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DrawDefaultInspector();
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
changeNextFrame = true;
|
||||
}
|
||||
|
||||
// Draw extra info below default inspector.
|
||||
EditorGUILayout.Space();
|
||||
if (ThisSkeletonDataAsset == null) {
|
||||
EditorGUILayout.HelpBox("SkeletonDataAsset is missing.", MessageType.Error);
|
||||
} else if (string.IsNullOrEmpty(animationName)) {
|
||||
EditorGUILayout.HelpBox("No animation selected.", MessageType.Warning);
|
||||
} else if (animationNotFound) {
|
||||
EditorGUILayout.HelpBox(string.Format("Animation named {0} was not found for this Skeleton.", animationNameProperty.stringValue), MessageType.Warning);
|
||||
} else {
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
if (!string.Equals(AssetUtility.GetPathSafeName(animationName), ThisAnimationReferenceAsset.name, System.StringComparison.OrdinalIgnoreCase))
|
||||
EditorGUILayout.HelpBox("Animation name value does not match this asset's name. Inspectors using this asset may be misleading.", MessageType.None);
|
||||
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(animationName, SpineEditorUtilities.Icons.animation));
|
||||
if (animation != null) {
|
||||
EditorGUILayout.LabelField(string.Format("Timelines: {0}", animation.Timelines.Count));
|
||||
EditorGUILayout.LabelField(string.Format("Duration: {0} sec", animation.Duration));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastSkeletonDataAsset = ThisSkeletonDataAsset;
|
||||
lastSkeletonData = ThisSkeletonDataAsset.GetSkeletonData(true);
|
||||
}
|
||||
|
||||
#region Preview Handlers
|
||||
string TargetAssetGUID { get { return AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(ThisSkeletonDataAsset)); } }
|
||||
string LastSkinKey { get { return TargetAssetGUID + "_lastSkin"; } }
|
||||
string LastSkinName { get { return EditorPrefs.GetString(LastSkinKey, ""); } }
|
||||
|
||||
void HandleOnEnablePreview () {
|
||||
if (ThisSkeletonDataAsset != null && ThisSkeletonDataAsset.skeletonJSON == null)
|
||||
return;
|
||||
SpineEditorUtilities.ConfirmInitialization();
|
||||
|
||||
// This handles the case where the managed editor assembly is unloaded before recompilation when code changes.
|
||||
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
|
||||
AppDomain.CurrentDomain.DomainUnload += OnDomainUnload;
|
||||
|
||||
preview.Initialize(this.Repaint, ThisSkeletonDataAsset, LastSkinName);
|
||||
preview.PlayPauseAnimation(ThisAnimationName, true);
|
||||
preview.OnSkinChanged -= HandleOnSkinChanged;
|
||||
preview.OnSkinChanged += HandleOnSkinChanged;
|
||||
EditorApplication.update -= preview.HandleEditorUpdate;
|
||||
EditorApplication.update += preview.HandleEditorUpdate;
|
||||
}
|
||||
|
||||
private void OnDomainUnload (object sender, EventArgs e) {
|
||||
OnDestroy();
|
||||
}
|
||||
|
||||
private void HandleOnSkinChanged (string skinName) {
|
||||
EditorPrefs.SetString(LastSkinKey, skinName);
|
||||
preview.PlayPauseAnimation(ThisAnimationName, true);
|
||||
}
|
||||
|
||||
void HandleOnDestroyPreview () {
|
||||
EditorApplication.update -= preview.HandleEditorUpdate;
|
||||
preview.OnDestroy();
|
||||
}
|
||||
|
||||
override public bool HasPreviewGUI () {
|
||||
if (serializedObject.isEditingMultipleObjects) return false;
|
||||
return ThisSkeletonDataAsset != null && ThisSkeletonDataAsset.GetSkeletonData(true) != null;
|
||||
}
|
||||
|
||||
override public void OnInteractivePreviewGUI (Rect r, GUIStyle background) {
|
||||
preview.Initialize(this.Repaint, ThisSkeletonDataAsset);
|
||||
preview.HandleInteractivePreviewGUI(r, background);
|
||||
}
|
||||
|
||||
public override GUIContent GetPreviewTitle () { return SpineInspectorUtility.TempContent("Preview"); }
|
||||
public override void OnPreviewSettings () { preview.HandleDrawSettings(); }
|
||||
public override Texture2D RenderStaticPreview (string assetPath, UnityEngine.Object[] subAssets, int width, int height) { return preview.GetStaticPreview(width, height); }
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9511532e80feed24881a5863f5485446
|
||||
timeCreated: 1523316585
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01cbef8f24d105f4bafa9668d669e040
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@ -1,390 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
//#define BAKE_ALL_BUTTON
|
||||
//#define REGION_BAKING_MESH
|
||||
|
||||
using Spine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Event = UnityEngine.Event;
|
||||
|
||||
[CustomEditor(typeof(SpineAtlasAsset)), CanEditMultipleObjects]
|
||||
public class SpineAtlasAssetInspector : UnityEditor.Editor {
|
||||
SerializedProperty atlasFile, materials, textureLoadingMode, onDemandTextureLoader;
|
||||
SpineAtlasAsset atlasAsset;
|
||||
|
||||
GUIContent spriteSlicesLabel;
|
||||
GUIContent SpriteSlicesLabel {
|
||||
get {
|
||||
if (spriteSlicesLabel == null) {
|
||||
spriteSlicesLabel = new GUIContent(
|
||||
"Apply Regions as Texture Sprite Slices",
|
||||
SpineEditorUtilities.Icons.unity,
|
||||
"Adds Sprite slices to atlas texture(s). " +
|
||||
"Updates existing slices if ones with matching names exist. \n\n" +
|
||||
"If your atlas was exported with Premultiply Alpha, " +
|
||||
"your SpriteRenderer should use the generated Spine _Material asset (or any Material with a PMA shader) instead of Sprites-Default.");
|
||||
}
|
||||
return spriteSlicesLabel;
|
||||
}
|
||||
}
|
||||
|
||||
static List<AtlasRegion> GetRegions (Atlas atlas) {
|
||||
FieldInfo regionsField = SpineInspectorUtility.GetNonPublicField(typeof(Atlas), "regions");
|
||||
return (List<AtlasRegion>)regionsField.GetValue(atlas);
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
SpineEditorUtilities.ConfirmInitialization();
|
||||
atlasFile = serializedObject.FindProperty("atlasFile");
|
||||
materials = serializedObject.FindProperty("materials");
|
||||
textureLoadingMode = serializedObject.FindProperty("textureLoadingMode");
|
||||
onDemandTextureLoader = serializedObject.FindProperty("onDemandTextureLoader");
|
||||
materials.isExpanded = true;
|
||||
atlasAsset = (SpineAtlasAsset)target;
|
||||
#if REGION_BAKING_MESH
|
||||
UpdateBakedList();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if REGION_BAKING_MESH
|
||||
private List<bool> baked;
|
||||
private List<GameObject> bakedObjects;
|
||||
|
||||
void UpdateBakedList () {
|
||||
AtlasAsset asset = (AtlasAsset)target;
|
||||
baked = new List<bool>();
|
||||
bakedObjects = new List<GameObject>();
|
||||
if (atlasFile.objectReferenceValue != null) {
|
||||
List<AtlasRegion> regions = this.Regions;
|
||||
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
||||
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
|
||||
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
|
||||
for (int i = 0; i < regions.Count; i++) {
|
||||
AtlasRegion region = regions[i];
|
||||
string bakedPrefabPath = Path.Combine(bakedDirPath, AssetUtility.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
|
||||
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
|
||||
baked.Add(prefab != null);
|
||||
bakedObjects.Add(prefab);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
DrawDefaultInspector();
|
||||
return;
|
||||
}
|
||||
|
||||
serializedObject.Update();
|
||||
atlasAsset = (atlasAsset == null) ? (SpineAtlasAsset)target : atlasAsset;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(atlasFile);
|
||||
EditorGUILayout.PropertyField(materials, true);
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
atlasAsset.Clear();
|
||||
atlasAsset.GetAtlas();
|
||||
}
|
||||
|
||||
if (materials.arraySize == 0) {
|
||||
EditorGUILayout.HelpBox("No materials", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < materials.arraySize; i++) {
|
||||
SerializedProperty prop = materials.GetArrayElementAtIndex(i);
|
||||
Material material = (Material)prop.objectReferenceValue;
|
||||
if (material == null) {
|
||||
EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (textureLoadingMode != null) {
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.PropertyField(textureLoadingMode);
|
||||
EditorGUILayout.PropertyField(onDemandTextureLoader);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Set Mipmap Bias to " + SpinePreferences.DEFAULT_MIPMAPBIAS, tooltip: "This may help textures with mipmaps be less blurry when used for 2D sprites."))) {
|
||||
foreach (Material m in atlasAsset.materials) {
|
||||
Texture texture = m.mainTexture;
|
||||
string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
|
||||
TextureImporter importer = (TextureImporter)TextureImporter.GetAtPath(texturePath);
|
||||
importer.mipMapBias = SpinePreferences.DEFAULT_MIPMAPBIAS;
|
||||
EditorUtility.SetDirty(texture);
|
||||
}
|
||||
Debug.Log("Texture mipmap bias set to " + SpinePreferences.DEFAULT_MIPMAPBIAS);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
if (atlasFile.objectReferenceValue != null) {
|
||||
if (SpineInspectorUtility.LargeCenteredButton(SpriteSlicesLabel)) {
|
||||
Atlas atlas = atlasAsset.GetAtlas();
|
||||
foreach (Material m in atlasAsset.materials)
|
||||
UpdateSpriteSlices(m.mainTexture, atlas);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
#if REGION_BAKING_MESH
|
||||
if (atlasFile.objectReferenceValue != null) {
|
||||
Atlas atlas = asset.GetAtlas();
|
||||
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
|
||||
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
|
||||
EditorGUILayout.LabelField(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
|
||||
EditorGUI.indentLevel++;
|
||||
AtlasPage lastPage = null;
|
||||
for (int i = 0; i < regions.Count; i++) {
|
||||
if (lastPage != regions[i].page) {
|
||||
if (lastPage != null) {
|
||||
EditorGUILayout.Separator();
|
||||
EditorGUILayout.Separator();
|
||||
}
|
||||
lastPage = regions[i].page;
|
||||
Material mat = ((Material)lastPage.rendererObject);
|
||||
if (mat != null) {
|
||||
GUILayout.BeginHorizontal();
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
} else {
|
||||
EditorGUILayout.LabelField(new GUIContent("Page missing material!", SpineEditorUtilities.Icons.warning));
|
||||
}
|
||||
}
|
||||
GUILayout.BeginHorizontal();
|
||||
{
|
||||
//EditorGUILayout.ToggleLeft(baked[i] ? "" : regions[i].name, baked[i]);
|
||||
bool result = baked[i] ? EditorGUILayout.ToggleLeft("", baked[i], GUILayout.Width(24)) : EditorGUILayout.ToggleLeft(" " + regions[i].name, baked[i]);
|
||||
if(baked[i]){
|
||||
EditorGUILayout.ObjectField(bakedObjects[i], typeof(GameObject), false, GUILayout.Width(250));
|
||||
}
|
||||
if (result && !baked[i]) {
|
||||
//bake
|
||||
baked[i] = true;
|
||||
bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
|
||||
EditorGUIUtility.PingObject(bakedObjects[i]);
|
||||
} else if (!result && baked[i]) {
|
||||
//unbake
|
||||
bool unbakeResult = EditorUtility.DisplayDialog("Delete Baked Region", "Do you want to delete the prefab for " + regions[i].name, "Yes", "Cancel");
|
||||
switch (unbakeResult) {
|
||||
case true:
|
||||
//delete
|
||||
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
||||
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
|
||||
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
|
||||
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
|
||||
AssetDatabase.DeleteAsset(bakedPrefabPath);
|
||||
baked[i] = false;
|
||||
break;
|
||||
case false:
|
||||
//do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
#if BAKE_ALL_BUTTON
|
||||
// Check state
|
||||
bool allBaked = true;
|
||||
bool allUnbaked = true;
|
||||
for (int i = 0; i < regions.Count; i++) {
|
||||
allBaked &= baked[i];
|
||||
allUnbaked &= !baked[i];
|
||||
}
|
||||
|
||||
if (!allBaked && GUILayout.Button("Bake All")) {
|
||||
for (int i = 0; i < regions.Count; i++) {
|
||||
if (!baked[i]) {
|
||||
baked[i] = true;
|
||||
bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (!allUnbaked && GUILayout.Button("Unbake All")) {
|
||||
bool unbakeResult = EditorUtility.DisplayDialog("Delete All Baked Regions", "Are you sure you want to unbake all region prefabs? This cannot be undone.", "Yes", "Cancel");
|
||||
switch (unbakeResult) {
|
||||
case true:
|
||||
//delete
|
||||
for (int i = 0; i < regions.Count; i++) {
|
||||
if (baked[i]) {
|
||||
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
||||
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
|
||||
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
|
||||
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
|
||||
AssetDatabase.DeleteAsset(bakedPrefabPath);
|
||||
baked[i] = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case false:
|
||||
//do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
#else
|
||||
if (atlasFile.objectReferenceValue != null) {
|
||||
|
||||
|
||||
int baseIndent = EditorGUI.indentLevel;
|
||||
|
||||
List<AtlasRegion> regions = SpineAtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
|
||||
int regionsCount = regions.Count;
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
|
||||
EditorGUILayout.LabelField(string.Format("{0} regions total", regionsCount));
|
||||
}
|
||||
AtlasPage lastPage = null;
|
||||
for (int i = 0; i < regionsCount; i++) {
|
||||
if (lastPage != regions[i].page) {
|
||||
if (lastPage != null) {
|
||||
EditorGUILayout.Separator();
|
||||
EditorGUILayout.Separator();
|
||||
}
|
||||
lastPage = regions[i].page;
|
||||
Material mat = ((Material)lastPage.rendererObject);
|
||||
if (mat != null) {
|
||||
EditorGUI.indentLevel = baseIndent;
|
||||
using (new GUILayout.HorizontalScope())
|
||||
using (new EditorGUI.DisabledGroupScope(true))
|
||||
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
|
||||
EditorGUI.indentLevel = baseIndent + 1;
|
||||
} else {
|
||||
EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
string regionName = regions[i].name;
|
||||
Texture2D icon = SpineEditorUtilities.Icons.image;
|
||||
if (regionName.EndsWith(" ")) {
|
||||
regionName = string.Format("'{0}'", regions[i].name);
|
||||
icon = SpineEditorUtilities.Icons.warning;
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon, "Region name ends with whitespace. This may cause errors. Please check your source image filenames."));
|
||||
} else {
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon));
|
||||
}
|
||||
|
||||
}
|
||||
EditorGUI.indentLevel = baseIndent;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
|
||||
atlasAsset.Clear();
|
||||
}
|
||||
|
||||
static public void UpdateSpriteSlices (Texture texture, Atlas atlas) {
|
||||
string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
|
||||
TextureImporter t = (TextureImporter)TextureImporter.GetAtPath(texturePath);
|
||||
t.spriteImportMode = SpriteImportMode.Multiple;
|
||||
SpriteMetaData[] spriteSheet = t.spritesheet;
|
||||
List<SpriteMetaData> sprites = new List<SpriteMetaData>(spriteSheet);
|
||||
|
||||
List<AtlasRegion> regions = SpineAtlasAssetInspector.GetRegions(atlas);
|
||||
int updatedCount = 0;
|
||||
int addedCount = 0;
|
||||
|
||||
foreach (AtlasRegion r in regions) {
|
||||
string pageName = System.IO.Path.GetFileNameWithoutExtension(r.page.name);
|
||||
string textureName = texture.name;
|
||||
bool pageMatch = string.Equals(pageName, textureName, StringComparison.Ordinal);
|
||||
|
||||
// if (pageMatch) {
|
||||
// int pw = r.page.width;
|
||||
// int ph = r.page.height;
|
||||
// bool mismatchSize = pw != texture.width || pw > t.maxTextureSize || ph != texture.height || ph > t.maxTextureSize;
|
||||
// if (mismatchSize)
|
||||
// Debug.LogWarningFormat("Size mismatch found.\nExpected atlas size is {0}x{1}. Texture Import Max Size of texture '{2}'({4}x{5}) is currently set to {3}.", pw, ph, texture.name, t.maxTextureSize, texture.width, texture.height);
|
||||
// }
|
||||
|
||||
int spriteIndex = pageMatch ? sprites.FindIndex(
|
||||
(s) => string.Equals(s.name, r.name, StringComparison.Ordinal)
|
||||
) : -1;
|
||||
bool spriteNameMatchExists = spriteIndex >= 0;
|
||||
|
||||
if (pageMatch) {
|
||||
Rect spriteRect = new Rect();
|
||||
|
||||
if (r.degrees == 90) {
|
||||
spriteRect.width = r.height;
|
||||
spriteRect.height = r.width;
|
||||
} else {
|
||||
spriteRect.width = r.width;
|
||||
spriteRect.height = r.height;
|
||||
}
|
||||
spriteRect.x = r.x;
|
||||
spriteRect.y = r.page.height - spriteRect.height - r.y;
|
||||
|
||||
if (spriteNameMatchExists) {
|
||||
SpriteMetaData s = sprites[spriteIndex];
|
||||
s.rect = spriteRect;
|
||||
sprites[spriteIndex] = s;
|
||||
updatedCount++;
|
||||
} else {
|
||||
sprites.Add(new SpriteMetaData {
|
||||
name = r.name,
|
||||
pivot = new Vector2(0.5f, 0.5f),
|
||||
rect = spriteRect
|
||||
});
|
||||
addedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
t.spritesheet = sprites.ToArray();
|
||||
EditorUtility.SetDirty(t);
|
||||
AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate);
|
||||
EditorGUIUtility.PingObject(texture);
|
||||
Debug.Log(string.Format("Applied sprite slices to {2}. {0} added. {1} updated.", addedCount, updatedCount, texture.name));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca9b3ce36d70a05408e3bdd5e92c7f64
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,153 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Event = UnityEngine.Event;
|
||||
|
||||
[CustomEditor(typeof(SpineSpriteAtlasAsset)), CanEditMultipleObjects]
|
||||
public class SpineSpriteAtlasAssetInspector : UnityEditor.Editor {
|
||||
SerializedProperty atlasFile, materials;
|
||||
SpineSpriteAtlasAsset atlasAsset;
|
||||
|
||||
static List<AtlasRegion> GetRegions (Atlas atlas) {
|
||||
FieldInfo regionsField = SpineInspectorUtility.GetNonPublicField(typeof(Atlas), "regions");
|
||||
return (List<AtlasRegion>)regionsField.GetValue(atlas);
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
SpineEditorUtilities.ConfirmInitialization();
|
||||
atlasFile = serializedObject.FindProperty("spriteAtlasFile");
|
||||
materials = serializedObject.FindProperty("materials");
|
||||
materials.isExpanded = true;
|
||||
atlasAsset = (SpineSpriteAtlasAsset)target;
|
||||
|
||||
if (!SpineSpriteAtlasAsset.AnySpriteAtlasNeedsRegionsLoaded())
|
||||
return;
|
||||
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
|
||||
EditorApplication.update += SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
EditorApplication.update -= SpineSpriteAtlasAsset.UpdateWhenEditorPlayModeStarted;
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
DrawDefaultInspector();
|
||||
return;
|
||||
}
|
||||
|
||||
serializedObject.Update();
|
||||
atlasAsset = (atlasAsset == null) ? (SpineSpriteAtlasAsset)target : atlasAsset;
|
||||
|
||||
if (atlasAsset.RegionsNeedLoading) {
|
||||
if (GUILayout.Button(SpineInspectorUtility.TempContent("Load regions by entering Play mode"), GUILayout.Height(20))) {
|
||||
EditorApplication.isPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(atlasFile);
|
||||
EditorGUILayout.PropertyField(materials, true);
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
atlasAsset.Clear();
|
||||
atlasAsset.GetAtlas();
|
||||
atlasAsset.updateRegionsInPlayMode = true;
|
||||
}
|
||||
|
||||
if (materials.arraySize == 0) {
|
||||
EditorGUILayout.HelpBox("No materials", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < materials.arraySize; i++) {
|
||||
SerializedProperty prop = materials.GetArrayElementAtIndex(i);
|
||||
Material material = (Material)prop.objectReferenceValue;
|
||||
if (material == null) {
|
||||
EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (atlasFile.objectReferenceValue != null) {
|
||||
int baseIndent = EditorGUI.indentLevel;
|
||||
|
||||
List<AtlasRegion> regions = SpineSpriteAtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
|
||||
int regionsCount = regions.Count;
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
|
||||
EditorGUILayout.LabelField(string.Format("{0} regions total", regionsCount));
|
||||
}
|
||||
AtlasPage lastPage = null;
|
||||
for (int i = 0; i < regionsCount; i++) {
|
||||
if (lastPage != regions[i].page) {
|
||||
if (lastPage != null) {
|
||||
EditorGUILayout.Separator();
|
||||
EditorGUILayout.Separator();
|
||||
}
|
||||
lastPage = regions[i].page;
|
||||
Material mat = ((Material)lastPage.rendererObject);
|
||||
if (mat != null) {
|
||||
EditorGUI.indentLevel = baseIndent;
|
||||
using (new GUILayout.HorizontalScope())
|
||||
using (new EditorGUI.DisabledGroupScope(true))
|
||||
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
|
||||
EditorGUI.indentLevel = baseIndent + 1;
|
||||
} else {
|
||||
EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
string regionName = regions[i].name;
|
||||
Texture2D icon = SpineEditorUtilities.Icons.image;
|
||||
if (regionName.EndsWith(" ")) {
|
||||
regionName = string.Format("'{0}'", regions[i].name);
|
||||
icon = SpineEditorUtilities.Icons.warning;
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon, "Region name ends with whitespace. This may cause errors. Please check your source image filenames."));
|
||||
} else {
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon));
|
||||
}
|
||||
}
|
||||
EditorGUI.indentLevel = baseIndent;
|
||||
}
|
||||
|
||||
if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
|
||||
atlasAsset.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f063dc5ff6881db4a9ee2e059812cba2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0134640f881c8d24d812a6f9af9d0761
|
||||
folderAsset: yes
|
||||
timeCreated: 1563304704
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,209 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
using Editor = UnityEditor.Editor;
|
||||
using Event = UnityEngine.Event;
|
||||
|
||||
[CustomEditor(typeof(BoneFollowerGraphic)), CanEditMultipleObjects]
|
||||
public class BoneFollowerGraphicInspector : Editor {
|
||||
|
||||
SerializedProperty boneName, skeletonGraphic, followXYPosition, followZPosition, followBoneRotation,
|
||||
followLocalScale, followParentWorldScale, followSkeletonFlip, maintainedAxisOrientation;
|
||||
BoneFollowerGraphic targetBoneFollower;
|
||||
bool needsReset;
|
||||
|
||||
#region Context Menu Item
|
||||
[MenuItem("CONTEXT/SkeletonGraphic/Add BoneFollower GameObject")]
|
||||
static void AddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
SkeletonGraphic skeletonGraphic = cmd.context as SkeletonGraphic;
|
||||
GameObject go = EditorInstantiation.NewGameObject("BoneFollower", true, typeof(RectTransform));
|
||||
Transform t = go.transform;
|
||||
t.SetParent(skeletonGraphic.transform);
|
||||
t.localPosition = Vector3.zero;
|
||||
|
||||
BoneFollowerGraphic f = go.AddComponent<BoneFollowerGraphic>();
|
||||
f.skeletonGraphic = skeletonGraphic;
|
||||
f.SetBone(skeletonGraphic.Skeleton.RootBone.Data.Name);
|
||||
|
||||
EditorGUIUtility.PingObject(t);
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollowerGraphic");
|
||||
}
|
||||
|
||||
// Validate
|
||||
[MenuItem("CONTEXT/SkeletonGraphic/Add BoneFollower GameObject", true)]
|
||||
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
SkeletonGraphic skeletonGraphic = cmd.context as SkeletonGraphic;
|
||||
return skeletonGraphic.IsValid;
|
||||
}
|
||||
#endregion
|
||||
|
||||
void OnEnable () {
|
||||
skeletonGraphic = serializedObject.FindProperty("skeletonGraphic");
|
||||
boneName = serializedObject.FindProperty("boneName");
|
||||
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
|
||||
followXYPosition = serializedObject.FindProperty("followXYPosition");
|
||||
followZPosition = serializedObject.FindProperty("followZPosition");
|
||||
followLocalScale = serializedObject.FindProperty("followLocalScale");
|
||||
followParentWorldScale = serializedObject.FindProperty("followParentWorldScale");
|
||||
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
|
||||
maintainedAxisOrientation = serializedObject.FindProperty("maintainedAxisOrientation");
|
||||
|
||||
targetBoneFollower = (BoneFollowerGraphic)target;
|
||||
if (targetBoneFollower.SkeletonGraphic != null)
|
||||
targetBoneFollower.SkeletonGraphic.Initialize(false);
|
||||
|
||||
if (!targetBoneFollower.valid || needsReset) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSceneGUI () {
|
||||
BoneFollowerGraphic tbf = target as BoneFollowerGraphic;
|
||||
SkeletonGraphic skeletonGraphicComponent = tbf.SkeletonGraphic;
|
||||
if (skeletonGraphicComponent == null) return;
|
||||
|
||||
Transform transform = skeletonGraphicComponent.transform;
|
||||
Skeleton skeleton = skeletonGraphicComponent.Skeleton;
|
||||
float positionScale = skeletonGraphicComponent.MeshScale;
|
||||
Vector2 positionOffset = skeletonGraphicComponent.GetScaledPivotOffset();
|
||||
|
||||
if (string.IsNullOrEmpty(boneName.stringValue)) {
|
||||
SpineHandles.DrawBones(transform, skeleton, positionScale, positionOffset);
|
||||
SpineHandles.DrawBoneNames(transform, skeleton, positionScale, positionOffset);
|
||||
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
|
||||
} else {
|
||||
Bone targetBone = tbf.bone;
|
||||
if (targetBone == null) return;
|
||||
|
||||
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor, positionScale, positionOffset);
|
||||
Handles.Label(targetBone.GetWorldPosition(transform, positionScale, positionOffset),
|
||||
targetBone.Data.Name, SpineHandles.BoneNameStyle);
|
||||
}
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
if (needsReset) {
|
||||
needsReset = false;
|
||||
foreach (Object o in targets) {
|
||||
BoneFollower bf = (BoneFollower)o;
|
||||
bf.Initialize();
|
||||
bf.LateUpdate();
|
||||
}
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DrawDefaultInspector();
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
if (needsReset && Event.current.type == EventType.Layout) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
serializedObject.Update();
|
||||
|
||||
// Find Renderer
|
||||
if (skeletonGraphic.objectReferenceValue == null) {
|
||||
SkeletonGraphic parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonGraphic>();
|
||||
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
|
||||
skeletonGraphic.objectReferenceValue = parentRenderer;
|
||||
Debug.Log("Inspector automatically assigned BoneFollowerGraphic.SkeletonGraphic");
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(skeletonGraphic);
|
||||
SkeletonGraphic skeletonGraphicComponent = skeletonGraphic.objectReferenceValue as SkeletonGraphic;
|
||||
if (skeletonGraphicComponent != null) {
|
||||
if (skeletonGraphicComponent.gameObject == targetBoneFollower.gameObject) {
|
||||
skeletonGraphic.objectReferenceValue = null;
|
||||
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollowerGraphic can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonGraphic from a different GameObject.", "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetBoneFollower.valid) {
|
||||
needsReset = true;
|
||||
}
|
||||
|
||||
if (targetBoneFollower.valid) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(boneName);
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
|
||||
EditorGUILayout.PropertyField(followBoneRotation);
|
||||
EditorGUILayout.PropertyField(followXYPosition);
|
||||
EditorGUILayout.PropertyField(followZPosition);
|
||||
EditorGUILayout.PropertyField(followLocalScale);
|
||||
EditorGUILayout.PropertyField(followParentWorldScale);
|
||||
EditorGUILayout.PropertyField(followSkeletonFlip);
|
||||
if ((followSkeletonFlip.hasMultipleDifferentValues || followSkeletonFlip.boolValue == false) &&
|
||||
(followBoneRotation.hasMultipleDifferentValues || followBoneRotation.boolValue == true)) {
|
||||
using (new SpineInspectorUtility.IndentScope())
|
||||
EditorGUILayout.PropertyField(maintainedAxisOrientation);
|
||||
}
|
||||
|
||||
//BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
|
||||
} else {
|
||||
SkeletonGraphic boneFollowerSkeletonGraphic = targetBoneFollower.skeletonGraphic;
|
||||
if (boneFollowerSkeletonGraphic == null) {
|
||||
EditorGUILayout.HelpBox("SkeletonGraphic is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonMecanim).", MessageType.Warning);
|
||||
} else {
|
||||
boneFollowerSkeletonGraphic.Initialize(false);
|
||||
|
||||
if (boneFollowerSkeletonGraphic.skeletonDataAsset == null)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonGraphic does not have SkeletonData assigned to it.", MessageType.Warning);
|
||||
|
||||
if (!boneFollowerSkeletonGraphic.IsValid)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonGraphic is invalid. Check target SkeletonGraphic, its SkeletonData asset or the console for other errors.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
Event current = Event.current;
|
||||
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
|
||||
if (wasUndo)
|
||||
targetBoneFollower.Initialize();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da44a8561fd243c43a1f77bda36de0eb
|
||||
timeCreated: 1499279157
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,230 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
using Editor = UnityEditor.Editor;
|
||||
using Event = UnityEngine.Event;
|
||||
|
||||
[CustomEditor(typeof(BoneFollower)), CanEditMultipleObjects]
|
||||
public class BoneFollowerInspector : Editor {
|
||||
SerializedProperty boneName, skeletonRenderer, followXYPosition, followZPosition, followBoneRotation,
|
||||
followLocalScale, followParentWorldScale, followSkeletonFlip, maintainedAxisOrientation;
|
||||
BoneFollower targetBoneFollower;
|
||||
bool needsReset;
|
||||
|
||||
#region Context Menu Item
|
||||
[MenuItem("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject")]
|
||||
static void AddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
SkeletonRenderer skeletonRenderer = cmd.context as SkeletonRenderer;
|
||||
GameObject go = EditorInstantiation.NewGameObject("New BoneFollower", true);
|
||||
Transform t = go.transform;
|
||||
t.SetParent(skeletonRenderer.transform);
|
||||
t.localPosition = Vector3.zero;
|
||||
|
||||
BoneFollower f = go.AddComponent<BoneFollower>();
|
||||
f.skeletonRenderer = skeletonRenderer;
|
||||
|
||||
EditorGUIUtility.PingObject(t);
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollower");
|
||||
}
|
||||
|
||||
// Validate
|
||||
[MenuItem("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject", true)]
|
||||
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
SkeletonRenderer skeletonRenderer = cmd.context as SkeletonRenderer;
|
||||
return skeletonRenderer.valid;
|
||||
}
|
||||
|
||||
[MenuItem("CONTEXT/BoneFollower/Rename BoneFollower GameObject")]
|
||||
static void RenameGameObject (MenuCommand cmd) {
|
||||
AutonameGameObject(cmd.context as BoneFollower);
|
||||
}
|
||||
#endregion
|
||||
|
||||
static void AutonameGameObject (BoneFollower boneFollower) {
|
||||
if (boneFollower == null) return;
|
||||
|
||||
string boneName = boneFollower.boneName;
|
||||
boneFollower.gameObject.name = string.IsNullOrEmpty(boneName) ? "BoneFollower" : string.Format("{0} (BoneFollower)", boneName);
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
|
||||
boneName = serializedObject.FindProperty("boneName");
|
||||
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
|
||||
followXYPosition = serializedObject.FindProperty("followXYPosition");
|
||||
followZPosition = serializedObject.FindProperty("followZPosition");
|
||||
followLocalScale = serializedObject.FindProperty("followLocalScale");
|
||||
followParentWorldScale = serializedObject.FindProperty("followParentWorldScale");
|
||||
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
|
||||
maintainedAxisOrientation = serializedObject.FindProperty("maintainedAxisOrientation");
|
||||
|
||||
targetBoneFollower = (BoneFollower)target;
|
||||
if (targetBoneFollower.SkeletonRenderer != null)
|
||||
targetBoneFollower.SkeletonRenderer.Initialize(false);
|
||||
|
||||
if (!targetBoneFollower.valid || needsReset) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSceneGUI () {
|
||||
BoneFollower tbf = target as BoneFollower;
|
||||
SkeletonRenderer skeletonRendererComponent = tbf.skeletonRenderer;
|
||||
if (skeletonRendererComponent == null) return;
|
||||
|
||||
Transform transform = skeletonRendererComponent.transform;
|
||||
Skeleton skeleton = skeletonRendererComponent.skeleton;
|
||||
|
||||
if (string.IsNullOrEmpty(boneName.stringValue)) {
|
||||
SpineHandles.DrawBones(transform, skeleton);
|
||||
SpineHandles.DrawBoneNames(transform, skeleton);
|
||||
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
|
||||
} else {
|
||||
Bone targetBone = tbf.bone;
|
||||
if (targetBone == null) return;
|
||||
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor);
|
||||
Handles.Label(targetBone.GetWorldPosition(transform), targetBone.Data.Name, SpineHandles.BoneNameStyle);
|
||||
}
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
if (needsReset) {
|
||||
needsReset = false;
|
||||
foreach (UnityEngine.Object o in targets) {
|
||||
BoneFollower bf = (BoneFollower)o;
|
||||
bf.Initialize();
|
||||
bf.LateUpdate();
|
||||
}
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DrawDefaultInspector();
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
if (needsReset && Event.current.type == EventType.Layout) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
serializedObject.Update();
|
||||
|
||||
// Find Renderer
|
||||
if (skeletonRenderer.objectReferenceValue == null) {
|
||||
SkeletonRenderer parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonRenderer>();
|
||||
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
|
||||
skeletonRenderer.objectReferenceValue = parentRenderer;
|
||||
Debug.Log("Inspector automatically assigned BoneFollower.SkeletonRenderer");
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(skeletonRenderer);
|
||||
SkeletonRenderer skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
|
||||
if (skeletonRendererReference != null) {
|
||||
if (skeletonRendererReference.gameObject == targetBoneFollower.gameObject) {
|
||||
skeletonRenderer.objectReferenceValue = null;
|
||||
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetBoneFollower.valid) {
|
||||
needsReset = true;
|
||||
}
|
||||
|
||||
if (targetBoneFollower.valid) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(boneName);
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
|
||||
EditorGUILayout.PropertyField(followBoneRotation);
|
||||
EditorGUILayout.PropertyField(followXYPosition);
|
||||
EditorGUILayout.PropertyField(followZPosition);
|
||||
EditorGUILayout.PropertyField(followLocalScale);
|
||||
EditorGUILayout.PropertyField(followParentWorldScale);
|
||||
EditorGUILayout.PropertyField(followSkeletonFlip);
|
||||
if ((followSkeletonFlip.hasMultipleDifferentValues || followSkeletonFlip.boolValue == false) &&
|
||||
(followBoneRotation.hasMultipleDifferentValues || followBoneRotation.boolValue == true)) {
|
||||
using (new SpineInspectorUtility.IndentScope())
|
||||
EditorGUILayout.PropertyField(maintainedAxisOrientation);
|
||||
}
|
||||
|
||||
BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
|
||||
} else {
|
||||
SkeletonRenderer boneFollowerSkeletonRenderer = targetBoneFollower.skeletonRenderer;
|
||||
if (boneFollowerSkeletonRenderer == null) {
|
||||
EditorGUILayout.HelpBox("SkeletonRenderer is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonMecanim).", MessageType.Warning);
|
||||
} else {
|
||||
boneFollowerSkeletonRenderer.Initialize(false);
|
||||
|
||||
if (boneFollowerSkeletonRenderer.skeletonDataAsset == null)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonRenderer does not have SkeletonData assigned to it.", MessageType.Warning);
|
||||
|
||||
if (!boneFollowerSkeletonRenderer.valid)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonRenderer is invalid. Check target SkeletonRenderer, its SkeletonData asset or the console for other errors.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
Event current = Event.current;
|
||||
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
|
||||
if (wasUndo)
|
||||
targetBoneFollower.Initialize();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
internal static void RecommendRigidbodyButton (Component component) {
|
||||
bool hasCollider2D = component.GetComponent<Collider2D>() != null || component.GetComponent<BoundingBoxFollower>() != null;
|
||||
bool hasCollider3D = !hasCollider2D && component.GetComponent<Collider>();
|
||||
bool missingRigidBody = (hasCollider2D && component.GetComponent<Rigidbody2D>() == null) || (hasCollider3D && component.GetComponent<Rigidbody>() == null);
|
||||
if (missingRigidBody) {
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning);
|
||||
System.Type rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody);
|
||||
string rbLabel = string.Format("Add {0}", rbType.Name);
|
||||
GUIContent rbContent = SpineInspectorUtility.TempContent(rbLabel, SpineInspectorUtility.UnityIcon(rbType), "Add a rigidbody to this GameObject to be the Physics body parent of the attached collider.");
|
||||
if (SpineInspectorUtility.CenteredButton(rbContent)) component.gameObject.AddComponent(rbType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c71ca35fd6241cb49a0b0756a664fcf7
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,271 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Event = UnityEngine.Event;
|
||||
using Icons = SpineEditorUtilities.Icons;
|
||||
|
||||
[CustomEditor(typeof(BoundingBoxFollowerGraphic))]
|
||||
public class BoundingBoxFollowerGraphicInspector : UnityEditor.Editor {
|
||||
SerializedProperty skeletonGraphic, slotName,
|
||||
isTrigger, usedByEffector, usedByComposite, clearStateOnDisable;
|
||||
BoundingBoxFollowerGraphic follower;
|
||||
bool rebuildRequired = false;
|
||||
bool addBoneFollower = false;
|
||||
bool sceneRepaintRequired = false;
|
||||
bool debugIsExpanded;
|
||||
|
||||
GUIContent addBoneFollowerLabel;
|
||||
GUIContent AddBoneFollowerLabel {
|
||||
get {
|
||||
if (addBoneFollowerLabel == null) addBoneFollowerLabel = new GUIContent("Add Bone Follower", Icons.bone);
|
||||
return addBoneFollowerLabel;
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeEditor () {
|
||||
skeletonGraphic = serializedObject.FindProperty("skeletonGraphic");
|
||||
slotName = serializedObject.FindProperty("slotName");
|
||||
isTrigger = serializedObject.FindProperty("isTrigger");
|
||||
usedByEffector = serializedObject.FindProperty("usedByEffector");
|
||||
usedByComposite = serializedObject.FindProperty("usedByComposite");
|
||||
clearStateOnDisable = serializedObject.FindProperty("clearStateOnDisable");
|
||||
follower = (BoundingBoxFollowerGraphic)target;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
|
||||
#if !NEW_PREFAB_SYSTEM
|
||||
bool isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
|
||||
#else
|
||||
bool isInspectingPrefab = false;
|
||||
#endif
|
||||
|
||||
// Note: when calling InitializeEditor() in OnEnable, it throws exception
|
||||
// "SerializedObjectNotCreatableException: Object at index 0 is null".
|
||||
InitializeEditor();
|
||||
|
||||
// Try to auto-assign SkeletonGraphic field.
|
||||
if (skeletonGraphic.objectReferenceValue == null) {
|
||||
SkeletonGraphic foundSkeletonGraphic = follower.GetComponentInParent<SkeletonGraphic>();
|
||||
if (foundSkeletonGraphic != null)
|
||||
Debug.Log("BoundingBoxFollowerGraphic automatically assigned: " + foundSkeletonGraphic.gameObject.name);
|
||||
else if (Event.current.type == EventType.Repaint)
|
||||
Debug.Log("No Spine GameObject detected. Make sure to set this GameObject as a child of the Spine GameObject; or set BoundingBoxFollowerGraphic's 'Skeleton Graphic' field in the inspector.");
|
||||
|
||||
skeletonGraphic.objectReferenceValue = foundSkeletonGraphic;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
InitializeEditor();
|
||||
}
|
||||
|
||||
SkeletonGraphic skeletonGraphicValue = skeletonGraphic.objectReferenceValue as SkeletonGraphic;
|
||||
if (skeletonGraphicValue != null && skeletonGraphicValue.gameObject == follower.gameObject) {
|
||||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
|
||||
EditorGUILayout.HelpBox("It's ideal to add BoundingBoxFollowerGraphic to a separate child GameObject of the Spine GameObject.", MessageType.Warning);
|
||||
|
||||
if (GUILayout.Button(new GUIContent("Move BoundingBoxFollowerGraphic to new GameObject", Icons.boundingBox), GUILayout.Height(30f))) {
|
||||
AddBoundingBoxFollowerGraphicChild(skeletonGraphicValue, follower);
|
||||
DestroyImmediate(follower);
|
||||
return;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(skeletonGraphic);
|
||||
EditorGUILayout.PropertyField(slotName, new GUIContent("Slot"));
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
InitializeEditor();
|
||||
#if !NEW_PREFAB_SYSTEM
|
||||
if (!isInspectingPrefab)
|
||||
rebuildRequired = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
using (new SpineInspectorUtility.LabelWidthScope(150f)) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(isTrigger);
|
||||
EditorGUILayout.PropertyField(usedByEffector);
|
||||
EditorGUILayout.PropertyField(usedByComposite);
|
||||
bool colliderParamChanged = EditorGUI.EndChangeCheck();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(clearStateOnDisable, new GUIContent(clearStateOnDisable.displayName, "Enable this if you are pooling your Spine GameObject"));
|
||||
bool clearStateChanged = EditorGUI.EndChangeCheck();
|
||||
|
||||
if (clearStateChanged || colliderParamChanged) {
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
InitializeEditor();
|
||||
if (colliderParamChanged)
|
||||
foreach (PolygonCollider2D col in follower.colliderTable.Values) {
|
||||
col.isTrigger = isTrigger.boolValue;
|
||||
col.usedByEffector = usedByEffector.boolValue;
|
||||
col.usedByComposite = usedByComposite.boolValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isInspectingPrefab) {
|
||||
follower.colliderTable.Clear();
|
||||
follower.nameTable.Clear();
|
||||
EditorGUILayout.HelpBox("BoundingBoxAttachments cannot be previewed in prefabs.", MessageType.Info);
|
||||
|
||||
// How do you prevent components from being saved into the prefab? No such HideFlag. DontSaveInEditor | DontSaveInBuild does not work. DestroyImmediate does not work.
|
||||
PolygonCollider2D collider = follower.GetComponent<PolygonCollider2D>();
|
||||
if (collider != null) Debug.LogWarning("Found BoundingBoxFollowerGraphic collider components in prefab. These are disposed and regenerated at runtime.");
|
||||
|
||||
} else {
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
if (debugIsExpanded = EditorGUILayout.Foldout(debugIsExpanded, "Debug Colliders")) {
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.LabelField(string.Format("Attachment Names ({0} PolygonCollider2D)", follower.colliderTable.Count));
|
||||
EditorGUI.BeginChangeCheck();
|
||||
foreach (KeyValuePair<BoundingBoxAttachment, string> kp in follower.nameTable) {
|
||||
string attachmentName = kp.Value;
|
||||
PolygonCollider2D collider = follower.colliderTable[kp.Key];
|
||||
bool isPlaceholder = attachmentName != kp.Key.Name;
|
||||
collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? attachmentName : string.Format("{0} [{1}]", attachmentName, kp.Key.Name), isPlaceholder ? Icons.skinPlaceholder : Icons.boundingBox), collider.enabled);
|
||||
}
|
||||
sceneRepaintRequired |= EditorGUI.EndChangeCheck();
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (follower.Slot == null)
|
||||
follower.Initialize(false);
|
||||
bool hasBoneFollower = follower.GetComponent<BoneFollowerGraphic>() != null;
|
||||
if (!hasBoneFollower) {
|
||||
bool buttonDisabled = follower.Slot == null;
|
||||
using (new EditorGUI.DisabledGroupScope(buttonDisabled)) {
|
||||
addBoneFollower |= SpineInspectorUtility.LargeCenteredButton(AddBoneFollowerLabel, true);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Event.current.type == EventType.Repaint) {
|
||||
if (addBoneFollower) {
|
||||
BoneFollowerGraphic boneFollower = follower.gameObject.AddComponent<BoneFollowerGraphic>();
|
||||
boneFollower.skeletonGraphic = skeletonGraphicValue;
|
||||
boneFollower.SetBone(follower.Slot.Data.BoneData.Name);
|
||||
addBoneFollower = false;
|
||||
}
|
||||
|
||||
if (sceneRepaintRequired) {
|
||||
SceneView.RepaintAll();
|
||||
sceneRepaintRequired = false;
|
||||
}
|
||||
|
||||
if (rebuildRequired) {
|
||||
follower.Initialize();
|
||||
rebuildRequired = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Menus
|
||||
[MenuItem("CONTEXT/SkeletonGraphic/Add BoundingBoxFollowerGraphic GameObject")]
|
||||
static void AddBoundingBoxFollowerGraphicChild (MenuCommand command) {
|
||||
GameObject go = AddBoundingBoxFollowerGraphicChild((SkeletonGraphic)command.context);
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollowerGraphic");
|
||||
}
|
||||
|
||||
[MenuItem("CONTEXT/SkeletonGraphic/Add all BoundingBoxFollowerGraphic GameObjects")]
|
||||
static void AddAllBoundingBoxFollowerGraphicChildren (MenuCommand command) {
|
||||
List<GameObject> objects = AddAllBoundingBoxFollowerGraphicChildren((SkeletonGraphic)command.context);
|
||||
foreach (GameObject go in objects)
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollowerGraphic");
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static GameObject AddBoundingBoxFollowerGraphicChild (SkeletonGraphic skeletonGraphic,
|
||||
BoundingBoxFollowerGraphic original = null, string name = "BoundingBoxFollowerGraphic",
|
||||
string slotName = null) {
|
||||
|
||||
GameObject go = EditorInstantiation.NewGameObject(name, true);
|
||||
go.transform.SetParent(skeletonGraphic.transform, false);
|
||||
go.AddComponent<RectTransform>();
|
||||
BoundingBoxFollowerGraphic newFollower = go.AddComponent<BoundingBoxFollowerGraphic>();
|
||||
|
||||
if (original != null) {
|
||||
newFollower.slotName = original.slotName;
|
||||
newFollower.isTrigger = original.isTrigger;
|
||||
newFollower.usedByEffector = original.usedByEffector;
|
||||
newFollower.usedByComposite = original.usedByComposite;
|
||||
newFollower.clearStateOnDisable = original.clearStateOnDisable;
|
||||
}
|
||||
if (slotName != null)
|
||||
newFollower.slotName = slotName;
|
||||
|
||||
newFollower.skeletonGraphic = skeletonGraphic;
|
||||
newFollower.Initialize();
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
EditorGUIUtility.PingObject(go);
|
||||
return go;
|
||||
}
|
||||
|
||||
public static List<GameObject> AddAllBoundingBoxFollowerGraphicChildren (
|
||||
SkeletonGraphic skeletonGraphic, BoundingBoxFollowerGraphic original = null) {
|
||||
|
||||
List<GameObject> createdGameObjects = new List<GameObject>();
|
||||
foreach (Skin skin in skeletonGraphic.Skeleton.Data.Skins) {
|
||||
ICollection<Skin.SkinEntry> attachments = skin.Attachments;
|
||||
foreach (Skin.SkinEntry entry in attachments) {
|
||||
BoundingBoxAttachment boundingBoxAttachment = entry.Attachment as BoundingBoxAttachment;
|
||||
if (boundingBoxAttachment == null)
|
||||
continue;
|
||||
int slotIndex = entry.SlotIndex;
|
||||
Slot slot = skeletonGraphic.Skeleton.Slots.Items[slotIndex];
|
||||
string slotName = slot.Data.Name;
|
||||
GameObject go = AddBoundingBoxFollowerGraphicChild(skeletonGraphic,
|
||||
original, boundingBoxAttachment.Name, slotName);
|
||||
BoneFollowerGraphic boneFollower = go.AddComponent<BoneFollowerGraphic>();
|
||||
boneFollower.skeletonGraphic = skeletonGraphic;
|
||||
boneFollower.SetBone(slot.Data.BoneData.Name);
|
||||
createdGameObjects.Add(go);
|
||||
}
|
||||
}
|
||||
return createdGameObjects;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c4f5b276299bc048ad00f3cd2d1ea09
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,270 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Event = UnityEngine.Event;
|
||||
using Icons = SpineEditorUtilities.Icons;
|
||||
|
||||
[CustomEditor(typeof(BoundingBoxFollower))]
|
||||
public class BoundingBoxFollowerInspector : UnityEditor.Editor {
|
||||
SerializedProperty skeletonRenderer, slotName,
|
||||
isTrigger, usedByEffector, usedByComposite, clearStateOnDisable;
|
||||
BoundingBoxFollower follower;
|
||||
bool rebuildRequired = false;
|
||||
bool addBoneFollower = false;
|
||||
bool sceneRepaintRequired = false;
|
||||
bool debugIsExpanded;
|
||||
|
||||
GUIContent addBoneFollowerLabel;
|
||||
GUIContent AddBoneFollowerLabel {
|
||||
get {
|
||||
if (addBoneFollowerLabel == null) addBoneFollowerLabel = new GUIContent("Add Bone Follower", Icons.bone);
|
||||
return addBoneFollowerLabel;
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeEditor () {
|
||||
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
|
||||
slotName = serializedObject.FindProperty("slotName");
|
||||
isTrigger = serializedObject.FindProperty("isTrigger");
|
||||
usedByEffector = serializedObject.FindProperty("usedByEffector");
|
||||
usedByComposite = serializedObject.FindProperty("usedByComposite");
|
||||
clearStateOnDisable = serializedObject.FindProperty("clearStateOnDisable");
|
||||
follower = (BoundingBoxFollower)target;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
|
||||
#if !NEW_PREFAB_SYSTEM
|
||||
bool isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
|
||||
#else
|
||||
bool isInspectingPrefab = false;
|
||||
#endif
|
||||
|
||||
// Note: when calling InitializeEditor() in OnEnable, it throws exception
|
||||
// "SerializedObjectNotCreatableException: Object at index 0 is null".
|
||||
InitializeEditor();
|
||||
|
||||
// Try to auto-assign SkeletonRenderer field.
|
||||
if (skeletonRenderer.objectReferenceValue == null) {
|
||||
SkeletonRenderer foundSkeletonRenderer = follower.GetComponentInParent<SkeletonRenderer>();
|
||||
if (foundSkeletonRenderer != null)
|
||||
Debug.Log("BoundingBoxFollower automatically assigned: " + foundSkeletonRenderer.gameObject.name);
|
||||
else if (Event.current.type == EventType.Repaint)
|
||||
Debug.Log("No Spine GameObject detected. Make sure to set this GameObject as a child of the Spine GameObject; or set BoundingBoxFollower's 'Skeleton Renderer' field in the inspector.");
|
||||
|
||||
skeletonRenderer.objectReferenceValue = foundSkeletonRenderer;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
InitializeEditor();
|
||||
}
|
||||
|
||||
SkeletonRenderer skeletonRendererValue = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
|
||||
if (skeletonRendererValue != null && skeletonRendererValue.gameObject == follower.gameObject) {
|
||||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
|
||||
EditorGUILayout.HelpBox("It's ideal to add BoundingBoxFollower to a separate child GameObject of the Spine GameObject.", MessageType.Warning);
|
||||
|
||||
if (GUILayout.Button(new GUIContent("Move BoundingBoxFollower to new GameObject", Icons.boundingBox), GUILayout.Height(30f))) {
|
||||
AddBoundingBoxFollowerChild(skeletonRendererValue, follower);
|
||||
DestroyImmediate(follower);
|
||||
return;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(skeletonRenderer);
|
||||
EditorGUILayout.PropertyField(slotName, new GUIContent("Slot"));
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
InitializeEditor();
|
||||
#if !NEW_PREFAB_SYSTEM
|
||||
if (!isInspectingPrefab)
|
||||
rebuildRequired = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
using (new SpineInspectorUtility.LabelWidthScope(150f)) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(isTrigger);
|
||||
EditorGUILayout.PropertyField(usedByEffector);
|
||||
EditorGUILayout.PropertyField(usedByComposite);
|
||||
bool colliderParamChanged = EditorGUI.EndChangeCheck();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(clearStateOnDisable, new GUIContent(clearStateOnDisable.displayName, "Enable this if you are pooling your Spine GameObject"));
|
||||
bool clearStateChanged = EditorGUI.EndChangeCheck();
|
||||
|
||||
if (clearStateChanged || colliderParamChanged) {
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
InitializeEditor();
|
||||
if (colliderParamChanged)
|
||||
foreach (PolygonCollider2D col in follower.colliderTable.Values) {
|
||||
col.isTrigger = isTrigger.boolValue;
|
||||
col.usedByEffector = usedByEffector.boolValue;
|
||||
col.usedByComposite = usedByComposite.boolValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isInspectingPrefab) {
|
||||
follower.colliderTable.Clear();
|
||||
follower.nameTable.Clear();
|
||||
EditorGUILayout.HelpBox("BoundingBoxAttachments cannot be previewed in prefabs.", MessageType.Info);
|
||||
|
||||
// How do you prevent components from being saved into the prefab? No such HideFlag. DontSaveInEditor | DontSaveInBuild does not work. DestroyImmediate does not work.
|
||||
PolygonCollider2D collider = follower.GetComponent<PolygonCollider2D>();
|
||||
if (collider != null) Debug.LogWarning("Found BoundingBoxFollower collider components in prefab. These are disposed and regenerated at runtime.");
|
||||
|
||||
} else {
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
if (debugIsExpanded = EditorGUILayout.Foldout(debugIsExpanded, "Debug Colliders")) {
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.LabelField(string.Format("Attachment Names ({0} PolygonCollider2D)", follower.colliderTable.Count));
|
||||
EditorGUI.BeginChangeCheck();
|
||||
foreach (KeyValuePair<BoundingBoxAttachment, string> pair in follower.nameTable) {
|
||||
string attachmentName = pair.Value;
|
||||
PolygonCollider2D collider = follower.colliderTable[pair.Key];
|
||||
bool isPlaceholder = attachmentName != pair.Key.Name;
|
||||
collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? attachmentName : string.Format("{0} [{1}]", attachmentName, pair.Key.Name), isPlaceholder ? Icons.skinPlaceholder : Icons.boundingBox), collider.enabled);
|
||||
}
|
||||
sceneRepaintRequired |= EditorGUI.EndChangeCheck();
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (follower.Slot == null)
|
||||
follower.Initialize(false);
|
||||
bool hasBoneFollower = follower.GetComponent<BoneFollower>() != null;
|
||||
if (!hasBoneFollower) {
|
||||
bool buttonDisabled = follower.Slot == null;
|
||||
using (new EditorGUI.DisabledGroupScope(buttonDisabled)) {
|
||||
addBoneFollower |= SpineInspectorUtility.LargeCenteredButton(AddBoneFollowerLabel, true);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Event.current.type == EventType.Repaint) {
|
||||
if (addBoneFollower) {
|
||||
BoneFollower boneFollower = follower.gameObject.AddComponent<BoneFollower>();
|
||||
boneFollower.skeletonRenderer = skeletonRendererValue;
|
||||
boneFollower.SetBone(follower.Slot.Data.BoneData.Name);
|
||||
addBoneFollower = false;
|
||||
}
|
||||
|
||||
if (sceneRepaintRequired) {
|
||||
SceneView.RepaintAll();
|
||||
sceneRepaintRequired = false;
|
||||
}
|
||||
|
||||
if (rebuildRequired) {
|
||||
follower.Initialize();
|
||||
rebuildRequired = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Menus
|
||||
[MenuItem("CONTEXT/SkeletonRenderer/Add BoundingBoxFollower GameObject")]
|
||||
static void AddBoundingBoxFollowerChild (MenuCommand command) {
|
||||
GameObject go = AddBoundingBoxFollowerChild((SkeletonRenderer)command.context);
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollower");
|
||||
}
|
||||
|
||||
[MenuItem("CONTEXT/SkeletonRenderer/Add all BoundingBoxFollower GameObjects")]
|
||||
static void AddAllBoundingBoxFollowerChildren (MenuCommand command) {
|
||||
List<GameObject> objects = AddAllBoundingBoxFollowerChildren((SkeletonRenderer)command.context);
|
||||
foreach (GameObject go in objects)
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add BoundingBoxFollower");
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static GameObject AddBoundingBoxFollowerChild (SkeletonRenderer skeletonRenderer,
|
||||
BoundingBoxFollower original = null, string name = "BoundingBoxFollower",
|
||||
string slotName = null) {
|
||||
|
||||
GameObject go = EditorInstantiation.NewGameObject(name, true);
|
||||
go.transform.SetParent(skeletonRenderer.transform, false);
|
||||
BoundingBoxFollower newFollower = go.AddComponent<BoundingBoxFollower>();
|
||||
|
||||
if (original != null) {
|
||||
newFollower.slotName = original.slotName;
|
||||
newFollower.isTrigger = original.isTrigger;
|
||||
newFollower.usedByEffector = original.usedByEffector;
|
||||
newFollower.usedByComposite = original.usedByComposite;
|
||||
newFollower.clearStateOnDisable = original.clearStateOnDisable;
|
||||
}
|
||||
if (slotName != null)
|
||||
newFollower.slotName = slotName;
|
||||
|
||||
newFollower.skeletonRenderer = skeletonRenderer;
|
||||
newFollower.Initialize();
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
EditorGUIUtility.PingObject(go);
|
||||
return go;
|
||||
}
|
||||
|
||||
public static List<GameObject> AddAllBoundingBoxFollowerChildren (
|
||||
SkeletonRenderer skeletonRenderer, BoundingBoxFollower original = null) {
|
||||
|
||||
List<GameObject> createdGameObjects = new List<GameObject>();
|
||||
foreach (Skin skin in skeletonRenderer.Skeleton.Data.Skins) {
|
||||
ICollection<Skin.SkinEntry> attachments = skin.Attachments;
|
||||
foreach (Skin.SkinEntry entry in attachments) {
|
||||
BoundingBoxAttachment boundingBoxAttachment = entry.Attachment as BoundingBoxAttachment;
|
||||
if (boundingBoxAttachment == null)
|
||||
continue;
|
||||
int slotIndex = entry.SlotIndex;
|
||||
Slot slot = skeletonRenderer.Skeleton.Slots.Items[slotIndex];
|
||||
string slotName = slot.Data.Name;
|
||||
GameObject go = AddBoundingBoxFollowerChild(skeletonRenderer,
|
||||
original, boundingBoxAttachment.Name, slotName);
|
||||
BoneFollower boneFollower = go.AddComponent<BoneFollower>();
|
||||
boneFollower.skeletonRenderer = skeletonRenderer;
|
||||
boneFollower.SetBone(slot.Data.BoneData.Name);
|
||||
createdGameObjects.Add(go);
|
||||
}
|
||||
}
|
||||
return createdGameObjects;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 670a3cefa3853bd48b5da53a424fd542
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@ -1,187 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
using Editor = UnityEditor.Editor;
|
||||
using Event = UnityEngine.Event;
|
||||
|
||||
[CustomEditor(typeof(PointFollower)), CanEditMultipleObjects]
|
||||
public class PointFollowerInspector : Editor {
|
||||
SerializedProperty slotName, pointAttachmentName, skeletonRenderer, followZPosition, followBoneRotation, followSkeletonFlip;
|
||||
PointFollower targetPointFollower;
|
||||
bool needsReset;
|
||||
|
||||
#region Context Menu Item
|
||||
[MenuItem("CONTEXT/SkeletonRenderer/Add PointFollower GameObject")]
|
||||
static void AddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
SkeletonRenderer skeletonRenderer = cmd.context as SkeletonRenderer;
|
||||
GameObject go = EditorInstantiation.NewGameObject("PointFollower", true);
|
||||
Transform t = go.transform;
|
||||
t.SetParent(skeletonRenderer.transform);
|
||||
t.localPosition = Vector3.zero;
|
||||
|
||||
PointFollower f = go.AddComponent<PointFollower>();
|
||||
f.skeletonRenderer = skeletonRenderer;
|
||||
|
||||
EditorGUIUtility.PingObject(t);
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add PointFollower");
|
||||
}
|
||||
|
||||
// Validate
|
||||
[MenuItem("CONTEXT/SkeletonRenderer/Add PointFollower GameObject", true)]
|
||||
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
SkeletonRenderer skeletonRenderer = cmd.context as SkeletonRenderer;
|
||||
return skeletonRenderer.valid;
|
||||
}
|
||||
#endregion
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
|
||||
slotName = serializedObject.FindProperty("slotName");
|
||||
pointAttachmentName = serializedObject.FindProperty("pointAttachmentName");
|
||||
|
||||
targetPointFollower = (PointFollower)target;
|
||||
if (targetPointFollower.skeletonRenderer != null)
|
||||
targetPointFollower.skeletonRenderer.Initialize(false);
|
||||
|
||||
if (!targetPointFollower.IsValid || needsReset) {
|
||||
targetPointFollower.Initialize();
|
||||
targetPointFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSceneGUI () {
|
||||
PointFollower tbf = target as PointFollower;
|
||||
SkeletonRenderer skeletonRendererComponent = tbf.skeletonRenderer;
|
||||
if (skeletonRendererComponent == null)
|
||||
return;
|
||||
|
||||
Skeleton skeleton = skeletonRendererComponent.skeleton;
|
||||
Transform skeletonTransform = skeletonRendererComponent.transform;
|
||||
|
||||
if (string.IsNullOrEmpty(pointAttachmentName.stringValue)) {
|
||||
// Draw all active PointAttachments in the current skin
|
||||
Skin currentSkin = skeleton.Skin;
|
||||
if (currentSkin != skeleton.Data.DefaultSkin) DrawPointsInSkin(skeleton.Data.DefaultSkin, skeleton, skeletonTransform);
|
||||
if (currentSkin != null) DrawPointsInSkin(currentSkin, skeleton, skeletonTransform);
|
||||
} else {
|
||||
Slot slot = skeleton.FindSlot(slotName.stringValue);
|
||||
if (slot != null) {
|
||||
int slotIndex = slot.Data.Index;
|
||||
PointAttachment point = skeleton.GetAttachment(slotIndex, pointAttachmentName.stringValue) as PointAttachment;
|
||||
if (point != null) {
|
||||
DrawPointAttachmentWithLabel(point, slot.Bone, skeletonTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawPointsInSkin (Skin skin, Skeleton skeleton, Transform transform) {
|
||||
foreach (Skin.SkinEntry skinEntry in skin.Attachments) {
|
||||
PointAttachment attachment = skinEntry.Attachment as PointAttachment;
|
||||
if (attachment != null) {
|
||||
Slot slot = skeleton.Slots.Items[skinEntry.SlotIndex];
|
||||
DrawPointAttachmentWithLabel(attachment, slot.Bone, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawPointAttachmentWithLabel (PointAttachment point, Bone bone, Transform transform) {
|
||||
Vector3 labelOffset = new Vector3(0f, -0.2f, 0f);
|
||||
SpineHandles.DrawPointAttachment(bone, point, transform);
|
||||
Handles.Label(labelOffset + point.GetWorldPosition(bone, transform), point.Name, SpineHandles.PointNameStyle);
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
if (needsReset) {
|
||||
needsReset = false;
|
||||
foreach (Object o in targets) {
|
||||
BoneFollower bf = (BoneFollower)o;
|
||||
bf.Initialize();
|
||||
bf.LateUpdate();
|
||||
}
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DrawDefaultInspector();
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
if (needsReset && Event.current.type == EventType.Layout) {
|
||||
targetPointFollower.Initialize();
|
||||
targetPointFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
serializedObject.Update();
|
||||
|
||||
DrawDefaultInspector();
|
||||
|
||||
// Find Renderer
|
||||
if (skeletonRenderer.objectReferenceValue == null) {
|
||||
SkeletonRenderer parentRenderer = targetPointFollower.GetComponentInParent<SkeletonRenderer>();
|
||||
if (parentRenderer != null && parentRenderer.gameObject != targetPointFollower.gameObject) {
|
||||
skeletonRenderer.objectReferenceValue = parentRenderer;
|
||||
Debug.Log("Inspector automatically assigned PointFollower.SkeletonRenderer");
|
||||
}
|
||||
}
|
||||
|
||||
SkeletonRenderer skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
|
||||
if (skeletonRendererReference != null) {
|
||||
if (skeletonRendererReference.gameObject == targetPointFollower.gameObject) {
|
||||
skeletonRenderer.objectReferenceValue = null;
|
||||
EditorUtility.DisplayDialog("Invalid assignment.", "PointFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your PointFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetPointFollower.IsValid) {
|
||||
needsReset = true;
|
||||
}
|
||||
|
||||
Event current = Event.current;
|
||||
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
|
||||
if (wasUndo)
|
||||
targetPointFollower.Initialize();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c7e838a8ec295a4e9c53602f690f42f
|
||||
timeCreated: 1518163038
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,137 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
[CustomEditor(typeof(SkeletonAnimation))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonAnimationInspector : SkeletonRendererInspector {
|
||||
protected SerializedProperty animationName, loop, timeScale, unscaledTime, autoReset;
|
||||
protected bool wasAnimationParameterChanged = false;
|
||||
readonly GUIContent LoopLabel = new GUIContent("Loop", "Whether or not .AnimationName should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.");
|
||||
readonly GUIContent TimeScaleLabel = new GUIContent("Time Scale", "The rate at which animations progress over time. 1 means normal speed. 0.5 means 50% speed.");
|
||||
readonly GUIContent UnscaledTimeLabel = new GUIContent("Unscaled Time",
|
||||
"If enabled, AnimationState uses unscaled game time (Time.unscaledDeltaTime), " +
|
||||
"running animations independent of e.g. game pause (Time.timeScale). " +
|
||||
"Instance SkeletonAnimation.timeScale will still be applied.");
|
||||
|
||||
protected override void OnEnable () {
|
||||
base.OnEnable();
|
||||
animationName = serializedObject.FindProperty("_animationName");
|
||||
loop = serializedObject.FindProperty("loop");
|
||||
timeScale = serializedObject.FindProperty("timeScale");
|
||||
unscaledTime = serializedObject.FindProperty("unscaledTime");
|
||||
}
|
||||
|
||||
protected override void DrawInspectorGUI (bool multi) {
|
||||
base.DrawInspectorGUI(multi);
|
||||
if (!TargetIsValid) return;
|
||||
bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject);
|
||||
|
||||
foreach (UnityEngine.Object o in targets)
|
||||
TrySetAnimation(o as SkeletonAnimation);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
if (!sameData) {
|
||||
EditorGUILayout.DelayedTextField(animationName);
|
||||
} else {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(animationName);
|
||||
wasAnimationParameterChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(loop, LoopLabel);
|
||||
wasAnimationParameterChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
|
||||
EditorGUILayout.PropertyField(timeScale, TimeScaleLabel);
|
||||
foreach (UnityEngine.Object o in targets) {
|
||||
SkeletonAnimation component = o as SkeletonAnimation;
|
||||
component.timeScale = Mathf.Max(component.timeScale, 0);
|
||||
}
|
||||
EditorGUILayout.PropertyField(unscaledTime, UnscaledTimeLabel);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
SkeletonRootMotionParameter();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
protected void TrySetAnimation (SkeletonAnimation skeletonAnimation) {
|
||||
if (skeletonAnimation == null) return;
|
||||
if (!skeletonAnimation.valid || skeletonAnimation.AnimationState == null)
|
||||
return;
|
||||
|
||||
TrackEntry current = skeletonAnimation.AnimationState.GetCurrent(0);
|
||||
if (!isInspectingPrefab) {
|
||||
string activeAnimation = (current != null) ? current.Animation.Name : "";
|
||||
bool activeLoop = (current != null) ? current.Loop : false;
|
||||
bool animationParameterChanged = this.wasAnimationParameterChanged &&
|
||||
((activeAnimation != animationName.stringValue) || (activeLoop != loop.boolValue));
|
||||
if (animationParameterChanged) {
|
||||
this.wasAnimationParameterChanged = false;
|
||||
Skeleton skeleton = skeletonAnimation.Skeleton;
|
||||
AnimationState state = skeletonAnimation.AnimationState;
|
||||
|
||||
if (!Application.isPlaying) {
|
||||
if (state != null) state.ClearTrack(0);
|
||||
skeleton.SetToSetupPose();
|
||||
}
|
||||
|
||||
Spine.Animation animationToUse = skeleton.Data.FindAnimation(animationName.stringValue);
|
||||
|
||||
if (!Application.isPlaying) {
|
||||
if (animationToUse != null) {
|
||||
skeletonAnimation.AnimationState.SetAnimation(0, animationToUse, loop.boolValue);
|
||||
}
|
||||
skeletonAnimation.Update(0);
|
||||
skeletonAnimation.LateUpdate();
|
||||
requireRepaint = true;
|
||||
} else {
|
||||
if (animationToUse != null)
|
||||
state.SetAnimation(0, animationToUse, loop.boolValue);
|
||||
else
|
||||
state.ClearTrack(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Reflect animationName serialized property in the inspector even if SetAnimation API was used.
|
||||
if (Application.isPlaying) {
|
||||
if (current != null && current.Animation != null) {
|
||||
if (skeletonAnimation.AnimationName != animationName.stringValue)
|
||||
animationName.stringValue = current.Animation.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39fbfef61034ca045b5aa80088e1e8a4
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,159 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Spine.Unity.Examples;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
// This script is not intended for use with code. See spine-unity documentation page for additional information.
|
||||
[CustomEditor(typeof(SkeletonGraphicCustomMaterials))]
|
||||
public class SkeletonGraphicCustomMaterialsInspector : UnityEditor.Editor {
|
||||
List<SkeletonGraphicCustomMaterials.AtlasMaterialOverride> componentCustomMaterialOverrides, _customMaterialOverridesPrev;
|
||||
List<SkeletonGraphicCustomMaterials.AtlasTextureOverride> componentCustomTextureOverrides, _customTextureOverridesPrev;
|
||||
SkeletonGraphicCustomMaterials component;
|
||||
|
||||
const BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;
|
||||
MethodInfo RemoveCustomMaterialOverrides, RemoveCustomTextureOverrides, SetCustomMaterialOverrides, SetCustomTextureOverrides;
|
||||
|
||||
#region SkeletonGraphic context menu
|
||||
[MenuItem("CONTEXT/SkeletonGraphic/Add Basic Serialized Custom Materials")]
|
||||
static void AddSkeletonGraphicCustomMaterials (MenuCommand menuCommand) {
|
||||
SkeletonGraphic skeletonGraphic = (SkeletonGraphic)menuCommand.context;
|
||||
SkeletonGraphicCustomMaterials newComponent = skeletonGraphic.gameObject.AddComponent<SkeletonGraphicCustomMaterials>();
|
||||
Undo.RegisterCreatedObjectUndo(newComponent, "Add Basic Serialized Custom Materials");
|
||||
}
|
||||
|
||||
[MenuItem("CONTEXT/SkeletonGraphic/Add Basic Serialized Custom Materials", true)]
|
||||
static bool AddSkeletonGraphicCustomMaterials_Validate (MenuCommand menuCommand) {
|
||||
SkeletonGraphic skeletonGraphic = (SkeletonGraphic)menuCommand.context;
|
||||
return (skeletonGraphic.GetComponent<SkeletonGraphicCustomMaterials>() == null);
|
||||
}
|
||||
#endregion
|
||||
|
||||
void OnEnable () {
|
||||
Type cm = typeof(SkeletonGraphicCustomMaterials);
|
||||
RemoveCustomMaterialOverrides = cm.GetMethod("RemoveCustomMaterialOverrides", PrivateInstance);
|
||||
RemoveCustomTextureOverrides = cm.GetMethod("RemoveCustomTextureOverrides", PrivateInstance);
|
||||
SetCustomMaterialOverrides = cm.GetMethod("SetCustomMaterialOverrides", PrivateInstance);
|
||||
SetCustomTextureOverrides = cm.GetMethod("SetCustomTextureOverrides", PrivateInstance);
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
component = (SkeletonGraphicCustomMaterials)target;
|
||||
SkeletonGraphic skeletonGraphic = component.skeletonGraphic;
|
||||
|
||||
// Draw the default inspector
|
||||
DrawDefaultInspector();
|
||||
|
||||
if (serializedObject.isEditingMultipleObjects)
|
||||
return;
|
||||
|
||||
if (componentCustomMaterialOverrides == null) {
|
||||
Type cm = typeof(SkeletonGraphicCustomMaterials);
|
||||
componentCustomMaterialOverrides = cm.GetField("customMaterialOverrides", PrivateInstance).GetValue(component) as List<SkeletonGraphicCustomMaterials.AtlasMaterialOverride>;
|
||||
componentCustomTextureOverrides = cm.GetField("customTextureOverrides", PrivateInstance).GetValue(component) as List<SkeletonGraphicCustomMaterials.AtlasTextureOverride>;
|
||||
if (componentCustomMaterialOverrides == null) {
|
||||
Debug.Log("Reflection failed.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill with current values at start
|
||||
if (_customMaterialOverridesPrev == null || _customTextureOverridesPrev == null) {
|
||||
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
|
||||
_customTextureOverridesPrev = CopyList(componentCustomTextureOverrides);
|
||||
}
|
||||
|
||||
// Compare new values with saved. If change is detected:
|
||||
// store new values, restore old values, remove overrides, restore new values, restore overrides.
|
||||
|
||||
// 1. Store new values
|
||||
var customMaterialOverridesNew = CopyList(componentCustomMaterialOverrides);
|
||||
var customTextureOverridesNew = CopyList(componentCustomTextureOverrides);
|
||||
|
||||
// Detect changes
|
||||
if (!_customMaterialOverridesPrev.SequenceEqual(customMaterialOverridesNew) ||
|
||||
!_customTextureOverridesPrev.SequenceEqual(customTextureOverridesNew)) {
|
||||
// 2. Restore old values
|
||||
componentCustomMaterialOverrides.Clear();
|
||||
componentCustomTextureOverrides.Clear();
|
||||
componentCustomMaterialOverrides.AddRange(_customMaterialOverridesPrev);
|
||||
componentCustomTextureOverrides.AddRange(_customTextureOverridesPrev);
|
||||
|
||||
// 3. Remove overrides
|
||||
RemoveCustomMaterials();
|
||||
|
||||
// 4. Restore new values
|
||||
componentCustomMaterialOverrides.Clear();
|
||||
componentCustomTextureOverrides.Clear();
|
||||
componentCustomMaterialOverrides.AddRange(customMaterialOverridesNew);
|
||||
componentCustomTextureOverrides.AddRange(customTextureOverridesNew);
|
||||
|
||||
// 5. Restore overrides
|
||||
SetCustomMaterials();
|
||||
|
||||
if (skeletonGraphic != null)
|
||||
skeletonGraphic.LateUpdate();
|
||||
}
|
||||
|
||||
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
|
||||
_customTextureOverridesPrev = CopyList(componentCustomTextureOverrides);
|
||||
|
||||
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Clear and Reapply Changes", tooltip: "Removes all non-serialized overrides in the SkeletonGraphic and reapplies the overrides on this component."))) {
|
||||
if (skeletonGraphic != null) {
|
||||
skeletonGraphic.CustomMaterialOverride.Clear();
|
||||
skeletonGraphic.CustomTextureOverride.Clear();
|
||||
RemoveCustomMaterials();
|
||||
SetCustomMaterials();
|
||||
skeletonGraphic.LateUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveCustomMaterials () {
|
||||
RemoveCustomMaterialOverrides.Invoke(component, null);
|
||||
RemoveCustomTextureOverrides.Invoke(component, null);
|
||||
}
|
||||
|
||||
void SetCustomMaterials () {
|
||||
SetCustomMaterialOverrides.Invoke(component, null);
|
||||
SetCustomTextureOverrides.Invoke(component, null);
|
||||
}
|
||||
|
||||
static List<T> CopyList<T> (List<T> list) {
|
||||
return list.GetRange(0, list.Count);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 349bf125947e3aa4bb78690fec69ea17
|
||||
timeCreated: 1588789940
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,897 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
#if UNITY_2018_2_OR_NEWER
|
||||
#define HAS_CULL_TRANSPARENT_MESH
|
||||
#endif
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define NEWPLAYMODECALLBACKS
|
||||
#endif
|
||||
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Icons = SpineEditorUtilities.Icons;
|
||||
|
||||
[CustomEditor(typeof(SkeletonGraphic))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonGraphicInspector : UnityEditor.Editor {
|
||||
|
||||
const string SeparatorSlotNamesFieldName = "separatorSlotNames";
|
||||
const string ReloadButtonString = "Reload";
|
||||
protected GUIContent SkeletonDataAssetLabel, UpdateTimingLabel;
|
||||
static GUILayoutOption reloadButtonWidth;
|
||||
static GUILayoutOption ReloadButtonWidth { get { return reloadButtonWidth = reloadButtonWidth ?? GUILayout.Width(GUI.skin.label.CalcSize(new GUIContent(ReloadButtonString)).x + 20); } }
|
||||
static GUIStyle ReloadButtonStyle { get { return EditorStyles.miniButton; } }
|
||||
|
||||
SerializedProperty material, color;
|
||||
SerializedProperty additiveMaterial, multiplyMaterial, screenMaterial;
|
||||
SerializedProperty skeletonDataAsset, initialSkinName;
|
||||
SerializedProperty startingAnimation, startingLoop, timeScale, freeze,
|
||||
updateTiming, updateWhenInvisible, unscaledTime, layoutScaleMode, editReferenceRect;
|
||||
SerializedProperty physicsPositionInheritanceFactor, physicsRotationInheritanceFactor, physicsMovementRelativeTo;
|
||||
SerializedProperty initialFlipX, initialFlipY;
|
||||
SerializedProperty meshGeneratorSettings;
|
||||
SerializedProperty useClipping, zSpacing, tintBlack, canvasGroupCompatible, pmaVertexColors, addNormals, calculateTangents, immutableTriangles;
|
||||
|
||||
SerializedProperty allowMultipleCanvasRenderers, separatorSlotNames, enableSeparatorSlots,
|
||||
updateSeparatorPartLocation, updateSeparatorPartScale;
|
||||
SerializedProperty raycastTarget, maskable;
|
||||
|
||||
readonly GUIContent UseClippingLabel = new GUIContent("Use Clipping",
|
||||
"When disabled, clipping attachments are ignored. This may be used to save performance.");
|
||||
readonly GUIContent ZSpacingLabel = new GUIContent("Z Spacing",
|
||||
"A value other than 0 adds a space between each rendered attachment to prevent Z Fighting when using shaders" +
|
||||
" that read or write to the depth buffer. Large values may cause unwanted parallax and spaces depending on " +
|
||||
"camera setup.");
|
||||
readonly GUIContent TintBlackLabel = new GUIContent("Tint Black (!)",
|
||||
"Adds black tint vertex data to the mesh as UV2 and UV3. Black tinting requires that the shader interpret " +
|
||||
"UV2 and UV3 as black tint colors for this effect to work. You may then want to use the " +
|
||||
"[Spine/SkeletonGraphic Tint Black] shader.");
|
||||
readonly GUIContent CanvasGroupCompatibleLabel = new GUIContent("CanvasGroup Compatible",
|
||||
"Enable when using SkeletonGraphic under a CanvasGroup. " +
|
||||
"When enabled, PMA Vertex Color alpha value is stored at uv2.g instead of color.a to capture " +
|
||||
"CanvasGroup modifying color.a. Also helps to detect correct parameter setting combinations.");
|
||||
readonly GUIContent PMAVertexColorsLabel = new GUIContent("PMA Vertex Colors",
|
||||
"Use this if you are using the default Spine/Skeleton shader or any premultiply-alpha shader.");
|
||||
readonly GUIContent AddNormalsLabel = new GUIContent("Add Normals",
|
||||
"Use this if your shader requires vertex normals. A more efficient solution for 2D setups is to modify the " +
|
||||
"shader to assume a single normal value for the whole mesh.");
|
||||
readonly GUIContent CalculateTangentsLabel = new GUIContent("Solve Tangents",
|
||||
"Calculates the tangents per frame. Use this if you are using lit shaders (usually with normal maps) that " +
|
||||
"require vertex tangents.");
|
||||
readonly GUIContent ImmutableTrianglesLabel = new GUIContent("Immutable Triangles",
|
||||
"Enable to optimize rendering for skeletons that never change attachment visbility");
|
||||
|
||||
readonly GUIContent UnscaledTimeLabel = new GUIContent("Unscaled Time",
|
||||
"If enabled, AnimationState uses unscaled game time (Time.unscaledDeltaTime), " +
|
||||
"running animations independent of e.g. game pause (Time.timeScale). " +
|
||||
"Instance SkeletonAnimation.timeScale will still be applied.");
|
||||
readonly GUIContent PhysicsPositionInheritanceFactorLabel = new GUIContent("Position",
|
||||
"When set to non-zero, Transform position movement in X and Y direction is applied to skeleton " +
|
||||
"PhysicsConstraints, multiplied by these " +
|
||||
"\nX and Y scale factors to the right. Typical (X,Y) values are " +
|
||||
"\n(1,1) to apply XY movement normally, " +
|
||||
"\n(2,2) to apply movement with double intensity, " +
|
||||
"\n(1,0) to apply only horizontal movement, or" +
|
||||
"\n(0,0) to not apply any Transform position movement at all.");
|
||||
readonly GUIContent PhysicsRotationInheritanceFactorLabel = new GUIContent("Rotation",
|
||||
"When set to non-zero, Transform rotation movement is applied to skeleton PhysicsConstraints, " +
|
||||
"multiplied by this scale factor to the right. Typical values are " +
|
||||
"\n1 to apply movement normally, " +
|
||||
"\n2 to apply movement with double intensity, or " +
|
||||
"\n0 to not apply any Transform rotation movement at all.");
|
||||
readonly GUIContent PhysicsMovementRelativeToLabel = new GUIContent("Movement relative to",
|
||||
"Reference transform relative to which physics movement will be calculated, or null to use world location.");
|
||||
|
||||
SkeletonGraphic thisSkeletonGraphic;
|
||||
protected bool isInspectingPrefab;
|
||||
protected bool slotsReapplyRequired = false;
|
||||
protected bool forceReloadQueued = false;
|
||||
|
||||
protected bool TargetIsValid {
|
||||
get {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
foreach (UnityEngine.Object c in targets) {
|
||||
SkeletonGraphic component = (SkeletonGraphic)c;
|
||||
if (!component.IsValid)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
SkeletonGraphic component = (SkeletonGraphic)target;
|
||||
return component.IsValid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
isInspectingPrefab = false;
|
||||
#else
|
||||
isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
|
||||
#endif
|
||||
SpineEditorUtilities.ConfirmInitialization();
|
||||
|
||||
// Labels
|
||||
SkeletonDataAssetLabel = new GUIContent("SkeletonData Asset", Icons.spine);
|
||||
UpdateTimingLabel = new GUIContent("Animation Update", "Whether to update the animation in normal Update (the default), physics step FixedUpdate, or manually via a user call.");
|
||||
|
||||
SerializedObject so = this.serializedObject;
|
||||
thisSkeletonGraphic = target as SkeletonGraphic;
|
||||
|
||||
// MaskableGraphic
|
||||
material = so.FindProperty("m_Material");
|
||||
color = so.FindProperty("m_SkeletonColor");
|
||||
raycastTarget = so.FindProperty("m_RaycastTarget");
|
||||
maskable = so.FindProperty("m_Maskable");
|
||||
|
||||
// SkeletonRenderer
|
||||
additiveMaterial = so.FindProperty("additiveMaterial");
|
||||
multiplyMaterial = so.FindProperty("multiplyMaterial");
|
||||
screenMaterial = so.FindProperty("screenMaterial");
|
||||
|
||||
skeletonDataAsset = so.FindProperty("skeletonDataAsset");
|
||||
initialSkinName = so.FindProperty("initialSkinName");
|
||||
|
||||
initialFlipX = so.FindProperty("initialFlipX");
|
||||
initialFlipY = so.FindProperty("initialFlipY");
|
||||
|
||||
// SkeletonAnimation
|
||||
startingAnimation = so.FindProperty("startingAnimation");
|
||||
startingLoop = so.FindProperty("startingLoop");
|
||||
timeScale = so.FindProperty("timeScale");
|
||||
unscaledTime = so.FindProperty("unscaledTime");
|
||||
freeze = so.FindProperty("freeze");
|
||||
updateTiming = so.FindProperty("updateTiming");
|
||||
updateWhenInvisible = so.FindProperty("updateWhenInvisible");
|
||||
layoutScaleMode = so.FindProperty("layoutScaleMode");
|
||||
editReferenceRect = so.FindProperty("editReferenceRect");
|
||||
physicsPositionInheritanceFactor = so.FindProperty("physicsPositionInheritanceFactor");
|
||||
physicsRotationInheritanceFactor = so.FindProperty("physicsRotationInheritanceFactor");
|
||||
physicsMovementRelativeTo = so.FindProperty("physicsMovementRelativeTo");
|
||||
|
||||
meshGeneratorSettings = so.FindProperty("meshGenerator").FindPropertyRelative("settings");
|
||||
meshGeneratorSettings.isExpanded = SkeletonRendererInspector.advancedFoldout;
|
||||
|
||||
useClipping = meshGeneratorSettings.FindPropertyRelative("useClipping");
|
||||
zSpacing = meshGeneratorSettings.FindPropertyRelative("zSpacing");
|
||||
tintBlack = meshGeneratorSettings.FindPropertyRelative("tintBlack");
|
||||
canvasGroupCompatible = meshGeneratorSettings.FindPropertyRelative("canvasGroupCompatible");
|
||||
pmaVertexColors = meshGeneratorSettings.FindPropertyRelative("pmaVertexColors");
|
||||
calculateTangents = meshGeneratorSettings.FindPropertyRelative("calculateTangents");
|
||||
addNormals = meshGeneratorSettings.FindPropertyRelative("addNormals");
|
||||
immutableTriangles = meshGeneratorSettings.FindPropertyRelative("immutableTriangles");
|
||||
|
||||
allowMultipleCanvasRenderers = so.FindProperty("allowMultipleCanvasRenderers");
|
||||
updateSeparatorPartLocation = so.FindProperty("updateSeparatorPartLocation");
|
||||
updateSeparatorPartScale = so.FindProperty("updateSeparatorPartScale");
|
||||
enableSeparatorSlots = so.FindProperty("enableSeparatorSlots");
|
||||
|
||||
separatorSlotNames = so.FindProperty("separatorSlotNames");
|
||||
separatorSlotNames.isExpanded = true;
|
||||
|
||||
#if NEWPLAYMODECALLBACKS
|
||||
EditorApplication.playModeStateChanged += OnPlaymodeChanged;
|
||||
#else
|
||||
EditorApplication.playmodeStateChanged += OnPlaymodeChanged;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
#if NEWPLAYMODECALLBACKS
|
||||
EditorApplication.playModeStateChanged -= OnPlaymodeChanged;
|
||||
#else
|
||||
EditorApplication.playmodeStateChanged -= OnPlaymodeChanged;
|
||||
#endif
|
||||
DisableEditReferenceRectMode();
|
||||
}
|
||||
|
||||
#if NEWPLAYMODECALLBACKS
|
||||
void OnPlaymodeChanged (PlayModeStateChange mode) {
|
||||
#else
|
||||
void OnPlaymodeChanged () {
|
||||
#endif
|
||||
DisableEditReferenceRectMode();
|
||||
}
|
||||
|
||||
void DisableEditReferenceRectMode () {
|
||||
foreach (UnityEngine.Object c in targets) {
|
||||
SkeletonGraphic component = (SkeletonGraphic)c;
|
||||
component.EditReferenceRect = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
|
||||
if (UnityEngine.Event.current.type == EventType.Layout) {
|
||||
if (forceReloadQueued) {
|
||||
forceReloadQueued = false;
|
||||
foreach (UnityEngine.Object c in targets) {
|
||||
SpineEditorUtilities.ReloadSkeletonDataAssetAndComponent(c as SkeletonGraphic);
|
||||
}
|
||||
} else {
|
||||
foreach (UnityEngine.Object c in targets) {
|
||||
SkeletonGraphic component = c as SkeletonGraphic;
|
||||
if (!component.IsValid) {
|
||||
SpineEditorUtilities.ReinitializeComponent(component);
|
||||
if (!component.IsValid) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool wasChanged = false;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) {
|
||||
SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel);
|
||||
if (GUILayout.Button(ReloadButtonString, ReloadButtonStyle, ReloadButtonWidth))
|
||||
forceReloadQueued = true;
|
||||
}
|
||||
|
||||
if (thisSkeletonGraphic.skeletonDataAsset == null) {
|
||||
EditorGUILayout.HelpBox("You need to assign a SkeletonData asset first.", MessageType.Info);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
serializedObject.Update();
|
||||
return;
|
||||
}
|
||||
if (!SpineEditorUtilities.SkeletonDataAssetIsValid(thisSkeletonGraphic.skeletonDataAsset)) {
|
||||
EditorGUILayout.HelpBox("SkeletonData asset error. Please check SkeletonData asset.", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
using (new SpineInspectorUtility.LabelWidthScope(100)) {
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.PropertyField(material);
|
||||
if (GUILayout.Button("Detect", EditorStyles.miniButton, GUILayout.Width(67f))) {
|
||||
Undo.RecordObjects(targets, "Detect Material");
|
||||
foreach (UnityEngine.Object skeletonGraphic in targets) {
|
||||
DetectMaterial((SkeletonGraphic)skeletonGraphic);
|
||||
}
|
||||
}
|
||||
}
|
||||
EditorGUILayout.PropertyField(color);
|
||||
}
|
||||
|
||||
string errorMessage = null;
|
||||
if (SpineEditorUtilities.Preferences.componentMaterialWarning &&
|
||||
MaterialChecks.IsMaterialSetupProblematic(thisSkeletonGraphic, ref errorMessage)) {
|
||||
EditorGUILayout.HelpBox(errorMessage, MessageType.Error, true);
|
||||
}
|
||||
|
||||
bool isSingleRendererOnly = (!allowMultipleCanvasRenderers.hasMultipleDifferentValues && allowMultipleCanvasRenderers.boolValue == false);
|
||||
bool isSeparationEnabledButNotMultipleRenderers =
|
||||
isSingleRendererOnly && (!enableSeparatorSlots.hasMultipleDifferentValues && enableSeparatorSlots.boolValue == true);
|
||||
bool meshRendersIncorrectlyWithSingleRenderer =
|
||||
isSingleRendererOnly && SkeletonHasMultipleSubmeshes();
|
||||
|
||||
if (isSeparationEnabledButNotMultipleRenderers || meshRendersIncorrectlyWithSingleRenderer)
|
||||
meshGeneratorSettings.isExpanded = true;
|
||||
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
|
||||
EditorGUILayout.PropertyField(meshGeneratorSettings, SpineInspectorUtility.TempContent("Advanced..."), includeChildren: false);
|
||||
SkeletonRendererInspector.advancedFoldout = meshGeneratorSettings.isExpanded;
|
||||
if (meshGeneratorSettings.isExpanded) {
|
||||
EditorGUILayout.Space();
|
||||
using (new SpineInspectorUtility.IndentScope()) {
|
||||
DrawMeshSettings();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
using (new SpineInspectorUtility.LabelWidthScope()) {
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PropertyField(allowMultipleCanvasRenderers, SpineInspectorUtility.TempContent("Multiple CanvasRenderers"));
|
||||
|
||||
if (GUILayout.Button(new GUIContent("Trim Renderers", "Remove currently unused CanvasRenderer GameObjects. These will be regenerated whenever needed."),
|
||||
EditorStyles.miniButton, GUILayout.Width(100f))) {
|
||||
|
||||
Undo.RecordObjects(targets, "Trim Renderers");
|
||||
foreach (UnityEngine.Object skeletonGraphic in targets) {
|
||||
((SkeletonGraphic)skeletonGraphic).TrimRenderers();
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
BlendModeMaterials blendModeMaterials = thisSkeletonGraphic.skeletonDataAsset.blendModeMaterials;
|
||||
if (allowMultipleCanvasRenderers.boolValue == true && blendModeMaterials.RequiresBlendModeMaterials) {
|
||||
using (new SpineInspectorUtility.IndentScope()) {
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField("Blend Mode Materials", EditorStyles.boldLabel);
|
||||
|
||||
if (GUILayout.Button(new GUIContent("Detect", "Auto-Assign Blend Mode Materials according to Vertex Data and Texture settings."),
|
||||
EditorStyles.miniButton, GUILayout.Width(100f))) {
|
||||
|
||||
Undo.RecordObjects(targets, "Detect Blend Mode Materials");
|
||||
foreach (UnityEngine.Object skeletonGraphic in targets) {
|
||||
DetectBlendModeMaterials((SkeletonGraphic)skeletonGraphic);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
bool usesAdditiveMaterial = blendModeMaterials.applyAdditiveMaterial;
|
||||
bool pmaVertexColors = thisSkeletonGraphic.MeshGenerator.settings.pmaVertexColors;
|
||||
if (pmaVertexColors)
|
||||
using (new EditorGUI.DisabledGroupScope(true)) {
|
||||
EditorGUILayout.LabelField("Additive Material - Unused with PMA Vertex Colors", EditorStyles.label);
|
||||
}
|
||||
else if (usesAdditiveMaterial)
|
||||
EditorGUILayout.PropertyField(additiveMaterial, SpineInspectorUtility.TempContent("Additive Material", null, "SkeletonGraphic Material for 'Additive' blend mode slots. Unused when 'PMA Vertex Colors' is enabled."));
|
||||
else
|
||||
using (new EditorGUI.DisabledGroupScope(true)) {
|
||||
EditorGUILayout.LabelField("No Additive Mat - 'Apply Additive Material' disabled at SkeletonDataAsset", EditorStyles.label);
|
||||
}
|
||||
EditorGUILayout.PropertyField(multiplyMaterial, SpineInspectorUtility.TempContent("Multiply Material", null, "SkeletonGraphic Material for 'Multiply' blend mode slots."));
|
||||
EditorGUILayout.PropertyField(screenMaterial, SpineInspectorUtility.TempContent("Screen Material", null, "SkeletonGraphic Material for 'Screen' blend mode slots."));
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(updateTiming, UpdateTimingLabel);
|
||||
EditorGUILayout.PropertyField(updateWhenInvisible);
|
||||
}
|
||||
|
||||
// warning box
|
||||
if (isSeparationEnabledButNotMultipleRenderers) {
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
meshGeneratorSettings.isExpanded = true;
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("'Multiple Canvas Renderers' must be enabled\nwhen 'Enable Separation' is enabled.", Icons.warning), GUILayout.Height(42), GUILayout.Width(340));
|
||||
}
|
||||
} else if (meshRendersIncorrectlyWithSingleRenderer) {
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
meshGeneratorSettings.isExpanded = true;
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("This mesh uses multiple atlas pages or blend modes.\n" +
|
||||
"You need to enable 'Multiple Canvas Renderers'\n" +
|
||||
"for correct rendering. Consider packing\n" +
|
||||
"attachments to a single atlas page if possible.", Icons.warning), GUILayout.Height(60), GUILayout.Width(380));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
SeparatorsField(separatorSlotNames, enableSeparatorSlots, updateSeparatorPartLocation, updateSeparatorPartScale);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
using (new SpineInspectorUtility.LabelWidthScope()) {
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Physics Inheritance", SpineEditorUtilities.Icons.constraintPhysics), EditorStyles.boldLabel);
|
||||
|
||||
using (new GUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.LabelField(PhysicsPositionInheritanceFactorLabel, GUILayout.Width(EditorGUIUtility.labelWidth));
|
||||
int savedIndentLevel = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
EditorGUILayout.PropertyField(physicsPositionInheritanceFactor, GUIContent.none, GUILayout.MinWidth(60));
|
||||
EditorGUI.indentLevel = savedIndentLevel;
|
||||
}
|
||||
EditorGUILayout.PropertyField(physicsRotationInheritanceFactor, PhysicsRotationInheritanceFactorLabel);
|
||||
EditorGUILayout.PropertyField(physicsMovementRelativeTo, PhysicsMovementRelativeToLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.PropertyField(initialSkinName);
|
||||
{
|
||||
Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.PrefixLabel(rect, SpineInspectorUtility.TempContent("Initial Flip"));
|
||||
rect.x += EditorGUIUtility.labelWidth;
|
||||
rect.width = 30f;
|
||||
SpineInspectorUtility.ToggleLeft(rect, initialFlipX, SpineInspectorUtility.TempContent("X", tooltip: "initialFlipX"));
|
||||
rect.x += 35f;
|
||||
SpineInspectorUtility.ToggleLeft(rect, initialFlipY, SpineInspectorUtility.TempContent("Y", tooltip: "initialFlipY"));
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Animation", EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(startingAnimation);
|
||||
EditorGUILayout.PropertyField(startingLoop);
|
||||
EditorGUILayout.PropertyField(timeScale);
|
||||
EditorGUILayout.PropertyField(unscaledTime, UnscaledTimeLabel);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.PropertyField(freeze);
|
||||
EditorGUILayout.Space();
|
||||
SkeletonRendererInspector.SkeletonRootMotionParameter(targets);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("UI", EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(raycastTarget);
|
||||
if (maskable != null) EditorGUILayout.PropertyField(maskable);
|
||||
|
||||
EditorGUILayout.PropertyField(layoutScaleMode);
|
||||
|
||||
using (new EditorGUI.DisabledGroupScope(layoutScaleMode.intValue == 0)) {
|
||||
EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
|
||||
EditorGUILayout.PrefixLabel("Edit Layout Bounds");
|
||||
editReferenceRect.boolValue = GUILayout.Toggle(editReferenceRect.boolValue,
|
||||
EditorGUIUtility.IconContent("EditCollider"), EditorStyles.miniButton, GUILayout.Width(40f));
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
if (layoutScaleMode.intValue == 0) {
|
||||
editReferenceRect.boolValue = false;
|
||||
}
|
||||
|
||||
using (new EditorGUI.DisabledGroupScope(editReferenceRect.boolValue == false && layoutScaleMode.intValue != 0)) {
|
||||
EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
|
||||
EditorGUILayout.PrefixLabel("Match RectTransform with Mesh");
|
||||
if (GUILayout.Button("Match", EditorStyles.miniButton, GUILayout.Width(65f))) {
|
||||
foreach (UnityEngine.Object skeletonGraphic in targets) {
|
||||
MatchRectTransformWithBounds((SkeletonGraphic)skeletonGraphic);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (TargetIsValid && !isInspectingPrefab) {
|
||||
EditorGUILayout.Space();
|
||||
if (SpineInspectorUtility.CenteredButton(new GUIContent("Add Skeleton Utility", Icons.skeletonUtility), 21, true, 200f))
|
||||
foreach (UnityEngine.Object t in targets) {
|
||||
Component component = t as Component;
|
||||
if (component.GetComponent<SkeletonUtility>() == null) {
|
||||
component.gameObject.AddComponent<SkeletonUtility>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasChanged |= EditorGUI.EndChangeCheck();
|
||||
if (wasChanged) {
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
slotsReapplyRequired = true;
|
||||
}
|
||||
|
||||
if (slotsReapplyRequired && UnityEngine.Event.current.type == EventType.Repaint) {
|
||||
foreach (UnityEngine.Object target in targets) {
|
||||
SkeletonGraphic skeletonGraphic = (SkeletonGraphic)target;
|
||||
skeletonGraphic.ReapplySeparatorSlotNames();
|
||||
skeletonGraphic.LateUpdate();
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
slotsReapplyRequired = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawMeshSettings () {
|
||||
EditorGUILayout.PropertyField(useClipping, UseClippingLabel);
|
||||
const float MinZSpacing = -0.1f;
|
||||
const float MaxZSpacing = 0f;
|
||||
EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing, ZSpacingLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
using (new SpineInspectorUtility.LabelWidthScope()) {
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", SpineInspectorUtility.UnityIcon<MeshFilter>()), EditorStyles.boldLabel);
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.PropertyField(tintBlack, TintBlackLabel);
|
||||
if (GUILayout.Button("Detect", EditorStyles.miniButton, GUILayout.Width(65f))) {
|
||||
Undo.RecordObjects(targets, "Detect Tint Black");
|
||||
foreach (UnityEngine.Object skeletonGraphic in targets) {
|
||||
DetectTintBlack((SkeletonGraphic)skeletonGraphic);
|
||||
}
|
||||
}
|
||||
}
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.PropertyField(canvasGroupCompatible, CanvasGroupCompatibleLabel);
|
||||
if (GUILayout.Button("Detect", EditorStyles.miniButton, GUILayout.Width(65f))) {
|
||||
Undo.RecordObjects(targets, "Detect CanvasGroup Compatible");
|
||||
foreach (UnityEngine.Object skeletonGraphic in targets) {
|
||||
DetectCanvasGroupCompatible((SkeletonGraphic)skeletonGraphic);
|
||||
}
|
||||
}
|
||||
}
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel);
|
||||
if (GUILayout.Button("Detect", EditorStyles.miniButton, GUILayout.Width(65f))) {
|
||||
Undo.RecordObjects(targets, "Detect PMA Vertex Colors");
|
||||
foreach (UnityEngine.Object skeletonGraphic in targets) {
|
||||
DetectPMAVertexColors((SkeletonGraphic)skeletonGraphic);
|
||||
}
|
||||
}
|
||||
}
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button("Detect Settings", EditorStyles.miniButton, GUILayout.Width(100f))) {
|
||||
Undo.RecordObjects(targets, "Detect Settings");
|
||||
foreach (UnityEngine.Object skeletonGraphic in targets) {
|
||||
DetectTintBlack((SkeletonGraphic)skeletonGraphic);
|
||||
DetectCanvasGroupCompatible((SkeletonGraphic)skeletonGraphic);
|
||||
DetectPMAVertexColors((SkeletonGraphic)skeletonGraphic);
|
||||
}
|
||||
}
|
||||
if (GUILayout.Button("Detect Material", EditorStyles.miniButton, GUILayout.Width(100f))) {
|
||||
Undo.RecordObjects(targets, "Detect Material");
|
||||
foreach (UnityEngine.Object skeletonGraphic in targets) {
|
||||
DetectMaterial((SkeletonGraphic)skeletonGraphic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(addNormals, AddNormalsLabel);
|
||||
EditorGUILayout.PropertyField(calculateTangents, CalculateTangentsLabel);
|
||||
EditorGUILayout.PropertyField(immutableTriangles, ImmutableTrianglesLabel);
|
||||
}
|
||||
}
|
||||
|
||||
protected bool SkeletonHasMultipleSubmeshes () {
|
||||
foreach (UnityEngine.Object target in targets) {
|
||||
SkeletonGraphic skeletonGraphic = (SkeletonGraphic)target;
|
||||
if (skeletonGraphic.HasMultipleSubmeshInstructions())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void OnSceneGUI () {
|
||||
SkeletonGraphic skeletonGraphic = (SkeletonGraphic)target;
|
||||
|
||||
if (skeletonGraphic.layoutScaleMode != SkeletonGraphic.LayoutMode.None) {
|
||||
if (skeletonGraphic.EditReferenceRect) {
|
||||
SpineHandles.DrawRectTransformRect(skeletonGraphic, Color.gray);
|
||||
SpineHandles.DrawReferenceRect(skeletonGraphic, Color.green);
|
||||
} else {
|
||||
SpineHandles.DrawReferenceRect(skeletonGraphic, Color.blue);
|
||||
}
|
||||
}
|
||||
SpineHandles.DrawPivotOffsetHandle(skeletonGraphic, Color.green);
|
||||
}
|
||||
|
||||
public static void SetSeparatorSlotNames (SkeletonRenderer skeletonRenderer, string[] newSlotNames) {
|
||||
FieldInfo field = SpineInspectorUtility.GetNonPublicField(typeof(SkeletonRenderer), SeparatorSlotNamesFieldName);
|
||||
field.SetValue(skeletonRenderer, newSlotNames);
|
||||
}
|
||||
|
||||
public static string[] GetSeparatorSlotNames (SkeletonRenderer skeletonRenderer) {
|
||||
FieldInfo field = SpineInspectorUtility.GetNonPublicField(typeof(SkeletonRenderer), SeparatorSlotNamesFieldName);
|
||||
return field.GetValue(skeletonRenderer) as string[];
|
||||
}
|
||||
|
||||
public static void SeparatorsField (SerializedProperty separatorSlotNames, SerializedProperty enableSeparatorSlots,
|
||||
SerializedProperty updateSeparatorPartLocation, SerializedProperty updateSeparatorPartScale) {
|
||||
|
||||
bool multi = separatorSlotNames.serializedObject.isEditingMultipleObjects;
|
||||
bool hasTerminalSlot = false;
|
||||
if (!multi) {
|
||||
ISkeletonComponent sr = separatorSlotNames.serializedObject.targetObject as ISkeletonComponent;
|
||||
Skeleton skeleton = sr.Skeleton;
|
||||
int lastSlot = skeleton.Slots.Count - 1;
|
||||
if (skeleton != null) {
|
||||
for (int i = 0, n = separatorSlotNames.arraySize; i < n; i++) {
|
||||
string slotName = separatorSlotNames.GetArrayElementAtIndex(i).stringValue;
|
||||
SlotData slot = skeleton.Data.FindSlot(slotName);
|
||||
int index = slot != null ? slot.Index : -1;
|
||||
if (index == 0 || index == lastSlot) {
|
||||
hasTerminalSlot = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string terminalSlotWarning = hasTerminalSlot ? " (!)" : "";
|
||||
|
||||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
|
||||
const string SeparatorsDescription = "Stored names of slots where the Skeleton's render will be split into different batches. This is used by separate components that split the render into different MeshRenderers or GameObjects.";
|
||||
if (separatorSlotNames.isExpanded) {
|
||||
EditorGUILayout.PropertyField(separatorSlotNames, SpineInspectorUtility.TempContent(separatorSlotNames.displayName + terminalSlotWarning, Icons.slotRoot, SeparatorsDescription), true);
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button("+", GUILayout.MaxWidth(28f), GUILayout.MaxHeight(15f))) {
|
||||
separatorSlotNames.arraySize++;
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
} else
|
||||
EditorGUILayout.PropertyField(separatorSlotNames, new GUIContent(separatorSlotNames.displayName + string.Format("{0} [{1}]", terminalSlotWarning, separatorSlotNames.arraySize), SeparatorsDescription), true);
|
||||
|
||||
using (new SpineInspectorUtility.LabelWidthScope()) {
|
||||
EditorGUILayout.PropertyField(enableSeparatorSlots, SpineInspectorUtility.TempContent("Enable Separation", tooltip: "Whether to enable separation at the above separator slots."));
|
||||
EditorGUILayout.PropertyField(updateSeparatorPartLocation, SpineInspectorUtility.TempContent("Update Part Location", tooltip: "Update separator part GameObject location to match the position of the SkeletonGraphic. This can be helpful when re-parenting parts to a different GameObject."));
|
||||
EditorGUILayout.PropertyField(updateSeparatorPartScale, SpineInspectorUtility.TempContent("Update Part Scale", tooltip: "Update separator part GameObject scale to match the scale (lossyScale) of the SkeletonGraphic. This can be helpful when re-parenting parts to a different GameObject."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Auto Detect Setting
|
||||
static void DetectTintBlack (SkeletonGraphic skeletonGraphic) {
|
||||
bool requiresTintBlack = HasTintBlackSlot(skeletonGraphic);
|
||||
if (requiresTintBlack)
|
||||
Debug.Log(string.Format("Found Tint-Black slot at '{0}'", skeletonGraphic));
|
||||
else
|
||||
Debug.Log(string.Format("No Tint-Black slot found at '{0}'", skeletonGraphic));
|
||||
skeletonGraphic.MeshGenerator.settings.tintBlack = requiresTintBlack;
|
||||
}
|
||||
|
||||
static bool HasTintBlackSlot (SkeletonGraphic skeletonGraphic) {
|
||||
SlotData[] slotsItems = skeletonGraphic.SkeletonData.Slots.Items;
|
||||
for (int i = 0, count = skeletonGraphic.SkeletonData.Slots.Count; i < count; ++i) {
|
||||
SlotData slotData = slotsItems[i];
|
||||
if (slotData.HasSecondColor)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void DetectCanvasGroupCompatible (SkeletonGraphic skeletonGraphic) {
|
||||
bool requiresCanvasGroupCompatible = IsBelowCanvasGroup(skeletonGraphic);
|
||||
if (requiresCanvasGroupCompatible)
|
||||
Debug.Log(string.Format("Skeleton is a child of CanvasGroup: '{0}'", skeletonGraphic));
|
||||
else
|
||||
Debug.Log(string.Format("Skeleton is not a child of CanvasGroup: '{0}'", skeletonGraphic));
|
||||
skeletonGraphic.MeshGenerator.settings.canvasGroupCompatible = requiresCanvasGroupCompatible;
|
||||
}
|
||||
|
||||
static bool IsBelowCanvasGroup (SkeletonGraphic skeletonGraphic) {
|
||||
return skeletonGraphic.gameObject.GetComponentInParent<CanvasGroup>() != null;
|
||||
}
|
||||
|
||||
static void DetectPMAVertexColors (SkeletonGraphic skeletonGraphic) {
|
||||
MeshGenerator.Settings settings = skeletonGraphic.MeshGenerator.settings;
|
||||
bool usesSpineShader = MaterialChecks.UsesSpineShader(skeletonGraphic.material);
|
||||
if (!usesSpineShader) {
|
||||
Debug.Log(string.Format("Skeleton is not using a Spine shader, thus the shader is likely " +
|
||||
"not using PMA vertex color: '{0}'", skeletonGraphic));
|
||||
skeletonGraphic.MeshGenerator.settings.pmaVertexColors = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool requiresPMAVertexColorsDisabled = settings.canvasGroupCompatible && !settings.tintBlack;
|
||||
if (requiresPMAVertexColorsDisabled) {
|
||||
Debug.Log(string.Format("Skeleton requires PMA Vertex Colors disabled: '{0}'", skeletonGraphic));
|
||||
skeletonGraphic.MeshGenerator.settings.pmaVertexColors = false;
|
||||
} else {
|
||||
Debug.Log(string.Format("Skeleton requires or permits PMA Vertex Colors enabled: '{0}'", skeletonGraphic));
|
||||
skeletonGraphic.MeshGenerator.settings.pmaVertexColors = true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSkeletonTexturePMA (SkeletonGraphic skeletonGraphic, out bool detectionSucceeded) {
|
||||
Texture texture = skeletonGraphic.mainTexture;
|
||||
string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
|
||||
TextureImporter importer = (TextureImporter)TextureImporter.GetAtPath(texturePath);
|
||||
if (importer.alphaIsTransparency != importer.sRGBTexture) {
|
||||
Debug.LogWarning(string.Format("Texture '{0}' at skeleton '{1}' is neither configured correctly for " +
|
||||
"PMA nor Straight Alpha.", texture, skeletonGraphic), texture);
|
||||
detectionSucceeded = false;
|
||||
return false;
|
||||
}
|
||||
detectionSucceeded = true;
|
||||
bool isPMATexture = !importer.alphaIsTransparency && !importer.sRGBTexture;
|
||||
return isPMATexture;
|
||||
}
|
||||
|
||||
static void DetectMaterial (SkeletonGraphic skeletonGraphic) {
|
||||
MeshGenerator.Settings settings = skeletonGraphic.MeshGenerator.settings;
|
||||
|
||||
bool detectionSucceeded;
|
||||
bool usesPMATexture = IsSkeletonTexturePMA(skeletonGraphic, out detectionSucceeded);
|
||||
if (!detectionSucceeded) {
|
||||
Debug.LogWarning(string.Format("Unable to assign Material for skeleton '{0}'.", skeletonGraphic), skeletonGraphic);
|
||||
return;
|
||||
}
|
||||
|
||||
Material newMaterial = null;
|
||||
if (usesPMATexture) {
|
||||
if (settings.tintBlack) {
|
||||
if (settings.canvasGroupCompatible)
|
||||
newMaterial = MaterialWithName("SkeletonGraphicTintBlack-CanvasGroup");
|
||||
else
|
||||
newMaterial = MaterialWithName("SkeletonGraphicTintBlack");
|
||||
} else { // not tintBlack
|
||||
if (settings.canvasGroupCompatible)
|
||||
newMaterial = MaterialWithName("SkeletonGraphicDefault-CanvasGroup");
|
||||
else
|
||||
newMaterial = MaterialWithName("SkeletonGraphicDefault");
|
||||
}
|
||||
} else { // straight alpha texture
|
||||
if (settings.tintBlack) {
|
||||
if (settings.canvasGroupCompatible)
|
||||
newMaterial = MaterialWithName("SkeletonGraphicTintBlack-CanvasGroupStraight");
|
||||
else
|
||||
newMaterial = MaterialWithName("SkeletonGraphicTintBlack-Straight");
|
||||
} else { // not tintBlack
|
||||
if (settings.canvasGroupCompatible)
|
||||
newMaterial = MaterialWithName("SkeletonGraphicDefault-CanvasGroupStraight");
|
||||
else
|
||||
newMaterial = MaterialWithName("SkeletonGraphicDefault-Straight");
|
||||
}
|
||||
}
|
||||
if (newMaterial != null) {
|
||||
Debug.Log(string.Format("Assigning material '{0}' at skeleton '{1}'",
|
||||
newMaterial, skeletonGraphic), newMaterial);
|
||||
skeletonGraphic.material = newMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
static void DetectBlendModeMaterials (SkeletonGraphic skeletonGraphic) {
|
||||
bool detectionSucceeded;
|
||||
bool usesPMATexture = IsSkeletonTexturePMA(skeletonGraphic, out detectionSucceeded);
|
||||
if (!detectionSucceeded) {
|
||||
Debug.LogWarning(string.Format("Unable to assign Blend Mode materials for skeleton '{0}'.", skeletonGraphic), skeletonGraphic);
|
||||
return;
|
||||
}
|
||||
DetectBlendModeMaterial(skeletonGraphic, BlendMode.Additive, usesPMATexture);
|
||||
DetectBlendModeMaterial(skeletonGraphic, BlendMode.Multiply, usesPMATexture);
|
||||
DetectBlendModeMaterial(skeletonGraphic, BlendMode.Screen, usesPMATexture);
|
||||
}
|
||||
|
||||
static void DetectBlendModeMaterial (SkeletonGraphic skeletonGraphic, BlendMode blendMode, bool usesPMATexture) {
|
||||
MeshGenerator.Settings settings = skeletonGraphic.MeshGenerator.settings;
|
||||
|
||||
string optionalTintBlack = settings.tintBlack ? "TintBlack" : "";
|
||||
string blendModeString = blendMode.ToString();
|
||||
string optionalDash = settings.canvasGroupCompatible || !usesPMATexture ? "-" : "";
|
||||
string optionalCanvasGroup = settings.canvasGroupCompatible ? "CanvasGroup" : "";
|
||||
string optionalStraight = !usesPMATexture ? "Straight" : "";
|
||||
|
||||
string materialName = string.Format("SkeletonGraphic{0}{1}{2}{3}{4}",
|
||||
optionalTintBlack, blendModeString, optionalDash, optionalCanvasGroup, optionalStraight);
|
||||
Material newMaterial = MaterialWithName(materialName);
|
||||
|
||||
if (newMaterial != null) {
|
||||
switch (blendMode) {
|
||||
case BlendMode.Additive:
|
||||
skeletonGraphic.additiveMaterial = newMaterial;
|
||||
break;
|
||||
case BlendMode.Multiply:
|
||||
skeletonGraphic.multiplyMaterial = newMaterial;
|
||||
break;
|
||||
case BlendMode.Screen:
|
||||
skeletonGraphic.screenMaterial = newMaterial;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Menus
|
||||
[MenuItem("CONTEXT/SkeletonGraphic/Match RectTransform with Mesh Bounds")]
|
||||
static void MatchRectTransformWithBounds (MenuCommand command) {
|
||||
SkeletonGraphic skeletonGraphic = (SkeletonGraphic)command.context;
|
||||
MatchRectTransformWithBounds(skeletonGraphic);
|
||||
}
|
||||
|
||||
static void MatchRectTransformWithBounds (SkeletonGraphic skeletonGraphic) {
|
||||
if (!skeletonGraphic.MatchRectTransformWithBounds())
|
||||
Debug.Log("Mesh was not previously generated.");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Spine/SkeletonGraphic (UnityUI)", false, 15)]
|
||||
static public void SkeletonGraphicCreateMenuItem () {
|
||||
GameObject parentGameObject = Selection.activeObject as GameObject;
|
||||
RectTransform parentTransform = parentGameObject == null ? null : parentGameObject.GetComponent<RectTransform>();
|
||||
|
||||
if (parentTransform == null)
|
||||
Debug.LogWarning("Your new SkeletonGraphic will not be visible until it is placed under a Canvas");
|
||||
|
||||
GameObject gameObject = NewSkeletonGraphicGameObject("New SkeletonGraphic");
|
||||
gameObject.transform.SetParent(parentTransform, false);
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = gameObject;
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
|
||||
// SpineEditorUtilities.InstantiateDelegate. Used by drag and drop.
|
||||
public static Component SpawnSkeletonGraphicFromDrop (SkeletonDataAsset data) {
|
||||
return InstantiateSkeletonGraphic(data);
|
||||
}
|
||||
|
||||
public static SkeletonGraphic InstantiateSkeletonGraphic (SkeletonDataAsset skeletonDataAsset, string skinName) {
|
||||
return InstantiateSkeletonGraphic(skeletonDataAsset, skeletonDataAsset.GetSkeletonData(true).FindSkin(skinName));
|
||||
}
|
||||
|
||||
public static SkeletonGraphic InstantiateSkeletonGraphic (SkeletonDataAsset skeletonDataAsset, Skin skin = null) {
|
||||
string spineGameObjectName = string.Format("SkeletonGraphic ({0})", skeletonDataAsset.name.Replace("_SkeletonData", ""));
|
||||
GameObject go = NewSkeletonGraphicGameObject(spineGameObjectName);
|
||||
SkeletonGraphic graphic = go.GetComponent<SkeletonGraphic>();
|
||||
graphic.skeletonDataAsset = skeletonDataAsset;
|
||||
|
||||
SkeletonData data = skeletonDataAsset.GetSkeletonData(true);
|
||||
|
||||
if (data == null) {
|
||||
for (int i = 0; i < skeletonDataAsset.atlasAssets.Length; i++) {
|
||||
string reloadAtlasPath = AssetDatabase.GetAssetPath(skeletonDataAsset.atlasAssets[i]);
|
||||
skeletonDataAsset.atlasAssets[i] = (AtlasAssetBase)AssetDatabase.LoadAssetAtPath(reloadAtlasPath, typeof(AtlasAssetBase));
|
||||
}
|
||||
|
||||
data = skeletonDataAsset.GetSkeletonData(true);
|
||||
}
|
||||
|
||||
skin = skin ?? data.DefaultSkin ?? data.Skins.Items[0];
|
||||
graphic.MeshGenerator.settings.zSpacing = SpineEditorUtilities.Preferences.defaultZSpacing;
|
||||
|
||||
graphic.startingLoop = SpineEditorUtilities.Preferences.defaultInstantiateLoop;
|
||||
graphic.PhysicsPositionInheritanceFactor = SpineEditorUtilities.Preferences.defaultPhysicsPositionInheritance;
|
||||
graphic.PhysicsRotationInheritanceFactor = SpineEditorUtilities.Preferences.defaultPhysicsRotationInheritance;
|
||||
graphic.Initialize(false);
|
||||
if (skin != null) graphic.Skeleton.SetSkin(skin);
|
||||
graphic.initialSkinName = skin.Name;
|
||||
graphic.Skeleton.UpdateWorldTransform(Skeleton.Physics.Update);
|
||||
graphic.UpdateMesh();
|
||||
return graphic;
|
||||
}
|
||||
|
||||
static GameObject NewSkeletonGraphicGameObject (string gameObjectName) {
|
||||
GameObject go = EditorInstantiation.NewGameObject(gameObjectName, true, typeof(RectTransform), typeof(CanvasRenderer), typeof(SkeletonGraphic));
|
||||
SkeletonGraphic graphic = go.GetComponent<SkeletonGraphic>();
|
||||
graphic.material = SkeletonGraphicInspector.DefaultSkeletonGraphicMaterial;
|
||||
graphic.additiveMaterial = SkeletonGraphicInspector.DefaultSkeletonGraphicAdditiveMaterial;
|
||||
graphic.multiplyMaterial = SkeletonGraphicInspector.DefaultSkeletonGraphicMultiplyMaterial;
|
||||
graphic.screenMaterial = SkeletonGraphicInspector.DefaultSkeletonGraphicScreenMaterial;
|
||||
|
||||
#if HAS_CULL_TRANSPARENT_MESH
|
||||
CanvasRenderer canvasRenderer = go.GetComponent<CanvasRenderer>();
|
||||
canvasRenderer.cullTransparentMesh = false;
|
||||
#endif
|
||||
return go;
|
||||
}
|
||||
|
||||
public static Material DefaultSkeletonGraphicMaterial {
|
||||
get { return MaterialWithName("SkeletonGraphicDefault"); }
|
||||
}
|
||||
|
||||
public static Material DefaultSkeletonGraphicAdditiveMaterial {
|
||||
get { return MaterialWithName("SkeletonGraphicAdditive"); }
|
||||
}
|
||||
|
||||
public static Material DefaultSkeletonGraphicMultiplyMaterial {
|
||||
get { return MaterialWithName("SkeletonGraphicMultiply"); }
|
||||
}
|
||||
|
||||
public static Material DefaultSkeletonGraphicScreenMaterial {
|
||||
get { return MaterialWithName("SkeletonGraphicScreen"); }
|
||||
}
|
||||
|
||||
protected static Material MaterialWithName (string name) {
|
||||
string[] guids = AssetDatabase.FindAssets(name + " t:material");
|
||||
if (guids.Length <= 0) return null;
|
||||
|
||||
int closestNameDistance = int.MaxValue;
|
||||
int closestNameIndex = 0;
|
||||
for (int i = 0; i < guids.Length; ++i) {
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
string assetName = System.IO.Path.GetFileNameWithoutExtension(assetPath);
|
||||
int distance = string.CompareOrdinal(assetName, name);
|
||||
if (distance < closestNameDistance) {
|
||||
closestNameDistance = distance;
|
||||
closestNameIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
string foundAssetPath = AssetDatabase.GUIDToAssetPath(guids[closestNameIndex]);
|
||||
if (string.IsNullOrEmpty(foundAssetPath)) return null;
|
||||
|
||||
Material firstMaterial = AssetDatabase.LoadAssetAtPath<Material>(foundAssetPath);
|
||||
return firstMaterial;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d81cc76b52fcdf499b2db252a317726
|
||||
timeCreated: 1455570945
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,153 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
[CustomEditor(typeof(SkeletonMecanim))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonMecanimInspector : SkeletonRendererInspector {
|
||||
public static bool mecanimSettingsFoldout;
|
||||
|
||||
protected SerializedProperty autoReset;
|
||||
protected SerializedProperty useCustomMixMode;
|
||||
protected SerializedProperty layerMixModes;
|
||||
protected SerializedProperty layerBlendModes;
|
||||
|
||||
protected override void OnEnable () {
|
||||
base.OnEnable();
|
||||
SerializedProperty mecanimTranslator = serializedObject.FindProperty("translator");
|
||||
autoReset = mecanimTranslator.FindPropertyRelative("autoReset");
|
||||
useCustomMixMode = mecanimTranslator.FindPropertyRelative("useCustomMixMode");
|
||||
layerMixModes = mecanimTranslator.FindPropertyRelative("layerMixModes");
|
||||
layerBlendModes = mecanimTranslator.FindPropertyRelative("layerBlendModes");
|
||||
}
|
||||
|
||||
protected override void DrawInspectorGUI (bool multi) {
|
||||
|
||||
AddRootMotionComponentIfEnabled();
|
||||
|
||||
base.DrawInspectorGUI(multi);
|
||||
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
mecanimSettingsFoldout = EditorGUILayout.Foldout(mecanimSettingsFoldout, "Mecanim Translator");
|
||||
if (mecanimSettingsFoldout) {
|
||||
EditorGUILayout.PropertyField(autoReset, new GUIContent("Auto Reset",
|
||||
"When set to true, the skeleton state is mixed out to setup-" +
|
||||
"pose when an animation finishes, according to the " +
|
||||
"animation's keyed items."));
|
||||
|
||||
EditorGUILayout.PropertyField(useCustomMixMode, new GUIContent("Custom MixMode",
|
||||
"When disabled, the recommended MixMode is used according to the layer blend mode. Enable to specify a custom MixMode for each Mecanim layer."));
|
||||
|
||||
if (useCustomMixMode.hasMultipleDifferentValues || useCustomMixMode.boolValue == true) {
|
||||
DrawLayerSettings();
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void AddRootMotionComponentIfEnabled () {
|
||||
foreach (UnityEngine.Object t in targets) {
|
||||
Component component = t as Component;
|
||||
Animator animator = component.GetComponent<Animator>();
|
||||
if (animator != null && animator.applyRootMotion) {
|
||||
if (component.GetComponent<SkeletonMecanimRootMotion>() == null) {
|
||||
component.gameObject.AddComponent<SkeletonMecanimRootMotion>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawLayerSettings () {
|
||||
string[] layerNames = GetLayerNames();
|
||||
float widthLayerColumn = 140;
|
||||
float widthMixColumn = 84;
|
||||
|
||||
using (new GUILayout.HorizontalScope()) {
|
||||
Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, EditorGUIUtility.singleLineHeight);
|
||||
rect.width = widthLayerColumn;
|
||||
EditorGUI.LabelField(rect, SpineInspectorUtility.TempContent("Mecanim Layer"), EditorStyles.boldLabel);
|
||||
|
||||
int savedIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
rect.position += new Vector2(rect.width, 0);
|
||||
rect.width = widthMixColumn;
|
||||
EditorGUI.LabelField(rect, SpineInspectorUtility.TempContent("Mix Mode"), EditorStyles.boldLabel);
|
||||
|
||||
EditorGUI.indentLevel = savedIndent;
|
||||
}
|
||||
|
||||
using (new SpineInspectorUtility.IndentScope()) {
|
||||
int layerCount = layerMixModes.arraySize;
|
||||
for (int i = 0; i < layerCount; ++i) {
|
||||
using (new GUILayout.HorizontalScope()) {
|
||||
string layerName = i < layerNames.Length ? layerNames[i] : ("Layer " + i);
|
||||
|
||||
Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, EditorGUIUtility.singleLineHeight);
|
||||
rect.width = widthLayerColumn;
|
||||
EditorGUI.PrefixLabel(rect, SpineInspectorUtility.TempContent(layerName));
|
||||
|
||||
int savedIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
SerializedProperty mixMode = layerMixModes.GetArrayElementAtIndex(i);
|
||||
rect.position += new Vector2(rect.width, 0);
|
||||
rect.width = widthMixColumn;
|
||||
EditorGUI.PropertyField(rect, mixMode, GUIContent.none);
|
||||
|
||||
EditorGUI.indentLevel = savedIndent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string[] GetLayerNames () {
|
||||
int maxLayerCount = 0;
|
||||
int maxIndex = 0;
|
||||
for (int i = 0; i < targets.Length; ++i) {
|
||||
SkeletonMecanim skeletonMecanim = ((SkeletonMecanim)targets[i]);
|
||||
int count = skeletonMecanim.Translator.MecanimLayerCount;
|
||||
if (count > maxLayerCount) {
|
||||
maxLayerCount = count;
|
||||
maxIndex = i;
|
||||
}
|
||||
}
|
||||
if (maxLayerCount == 0)
|
||||
return new string[0];
|
||||
SkeletonMecanim skeletonMecanimMaxLayers = ((SkeletonMecanim)targets[maxIndex]);
|
||||
return skeletonMecanimMaxLayers.Translator.MecanimLayerNames;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a9ca5213a3a4614c9a9f2e60909bc33
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,81 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
[CustomEditor(typeof(SkeletonMecanimRootMotion))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonMecanimRootMotionInspector : SkeletonRootMotionBaseInspector {
|
||||
protected SerializedProperty mecanimLayerFlags;
|
||||
|
||||
protected GUIContent mecanimLayersLabel;
|
||||
|
||||
protected override void OnEnable () {
|
||||
base.OnEnable();
|
||||
mecanimLayerFlags = serializedObject.FindProperty("mecanimLayerFlags");
|
||||
|
||||
mecanimLayersLabel = new UnityEngine.GUIContent("Mecanim Layers", "Mecanim layers to apply root motion at. Defaults to the first Mecanim layer.");
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
|
||||
base.MainPropertyFields();
|
||||
MecanimLayerMaskPropertyField();
|
||||
|
||||
base.OptionalPropertyFields();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
protected string[] GetLayerNames () {
|
||||
int maxLayerCount = 0;
|
||||
int maxIndex = 0;
|
||||
for (int i = 0; i < targets.Length; ++i) {
|
||||
SkeletonMecanim skeletonMecanim = ((SkeletonMecanimRootMotion)targets[i]).SkeletonMecanim;
|
||||
int count = skeletonMecanim.Translator.MecanimLayerCount;
|
||||
if (count > maxLayerCount) {
|
||||
maxLayerCount = count;
|
||||
maxIndex = i;
|
||||
}
|
||||
}
|
||||
if (maxLayerCount == 0)
|
||||
return new string[0];
|
||||
SkeletonMecanim skeletonMecanimMaxLayers = ((SkeletonMecanimRootMotion)targets[maxIndex]).SkeletonMecanim;
|
||||
return skeletonMecanimMaxLayers.Translator.MecanimLayerNames;
|
||||
}
|
||||
|
||||
protected void MecanimLayerMaskPropertyField () {
|
||||
string[] layerNames = GetLayerNames();
|
||||
if (layerNames.Length > 0)
|
||||
mecanimLayerFlags.intValue = EditorGUILayout.MaskField(
|
||||
mecanimLayersLabel, mecanimLayerFlags.intValue, layerNames);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4613924c50d66cf458f0db803776dd2f
|
||||
timeCreated: 1593175106
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,165 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#define SPINE_OPTIONAL_MATERIALOVERRIDE
|
||||
|
||||
// Contributed by: Lost Polygon
|
||||
|
||||
using Spine.Unity.Examples;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
// This script is not intended for use with code. See the readme.txt file in SkeletonRendererCustomMaterials folder to learn more.
|
||||
[CustomEditor(typeof(SkeletonRendererCustomMaterials))]
|
||||
public class SkeletonRendererCustomMaterialsInspector : UnityEditor.Editor {
|
||||
List<SkeletonRendererCustomMaterials.AtlasMaterialOverride> componentCustomMaterialOverrides, _customMaterialOverridesPrev;
|
||||
List<SkeletonRendererCustomMaterials.SlotMaterialOverride> componentCustomSlotMaterials, _customSlotMaterialsPrev;
|
||||
SkeletonRendererCustomMaterials component;
|
||||
|
||||
const BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;
|
||||
MethodInfo RemoveCustomMaterialOverrides, RemoveCustomSlotMaterials, SetCustomMaterialOverrides, SetCustomSlotMaterials;
|
||||
|
||||
#region SkeletonRenderer context menu
|
||||
[MenuItem("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials")]
|
||||
static void AddSkeletonRendererCustomMaterials (MenuCommand menuCommand) {
|
||||
SkeletonRenderer skeletonRenderer = (SkeletonRenderer)menuCommand.context;
|
||||
SkeletonRendererCustomMaterials newComponent = skeletonRenderer.gameObject.AddComponent<SkeletonRendererCustomMaterials>();
|
||||
Undo.RegisterCreatedObjectUndo(newComponent, "Add Basic Serialized Custom Materials");
|
||||
}
|
||||
|
||||
[MenuItem("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials", true)]
|
||||
static bool AddSkeletonRendererCustomMaterials_Validate (MenuCommand menuCommand) {
|
||||
SkeletonRenderer skeletonRenderer = (SkeletonRenderer)menuCommand.context;
|
||||
return (skeletonRenderer.GetComponent<SkeletonRendererCustomMaterials>() == null);
|
||||
}
|
||||
#endregion
|
||||
|
||||
void OnEnable () {
|
||||
Type cm = typeof(SkeletonRendererCustomMaterials);
|
||||
RemoveCustomMaterialOverrides = cm.GetMethod("RemoveCustomMaterialOverrides", PrivateInstance);
|
||||
RemoveCustomSlotMaterials = cm.GetMethod("RemoveCustomSlotMaterials", PrivateInstance);
|
||||
SetCustomMaterialOverrides = cm.GetMethod("SetCustomMaterialOverrides", PrivateInstance);
|
||||
SetCustomSlotMaterials = cm.GetMethod("SetCustomSlotMaterials", PrivateInstance);
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
component = (SkeletonRendererCustomMaterials)target;
|
||||
SkeletonRenderer skeletonRenderer = component.skeletonRenderer;
|
||||
|
||||
// Draw the default inspector
|
||||
DrawDefaultInspector();
|
||||
|
||||
if (serializedObject.isEditingMultipleObjects)
|
||||
return;
|
||||
|
||||
if (componentCustomMaterialOverrides == null) {
|
||||
Type cm = typeof(SkeletonRendererCustomMaterials);
|
||||
componentCustomMaterialOverrides = cm.GetField("customMaterialOverrides", PrivateInstance).GetValue(component) as List<SkeletonRendererCustomMaterials.AtlasMaterialOverride>;
|
||||
componentCustomSlotMaterials = cm.GetField("customSlotMaterials", PrivateInstance).GetValue(component) as List<SkeletonRendererCustomMaterials.SlotMaterialOverride>;
|
||||
if (componentCustomMaterialOverrides == null) {
|
||||
Debug.Log("Reflection failed.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill with current values at start
|
||||
if (_customMaterialOverridesPrev == null || _customSlotMaterialsPrev == null) {
|
||||
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
|
||||
_customSlotMaterialsPrev = CopyList(componentCustomSlotMaterials);
|
||||
}
|
||||
|
||||
// Compare new values with saved. If change is detected:
|
||||
// store new values, restore old values, remove overrides, restore new values, restore overrides.
|
||||
|
||||
// 1. Store new values
|
||||
var customMaterialOverridesNew = CopyList(componentCustomMaterialOverrides);
|
||||
var customSlotMaterialsNew = CopyList(componentCustomSlotMaterials);
|
||||
|
||||
// Detect changes
|
||||
if (!_customMaterialOverridesPrev.SequenceEqual(customMaterialOverridesNew) ||
|
||||
!_customSlotMaterialsPrev.SequenceEqual(customSlotMaterialsNew)) {
|
||||
// 2. Restore old values
|
||||
componentCustomMaterialOverrides.Clear();
|
||||
componentCustomSlotMaterials.Clear();
|
||||
componentCustomMaterialOverrides.AddRange(_customMaterialOverridesPrev);
|
||||
componentCustomSlotMaterials.AddRange(_customSlotMaterialsPrev);
|
||||
|
||||
// 3. Remove overrides
|
||||
RemoveCustomMaterials();
|
||||
|
||||
// 4. Restore new values
|
||||
componentCustomMaterialOverrides.Clear();
|
||||
componentCustomSlotMaterials.Clear();
|
||||
componentCustomMaterialOverrides.AddRange(customMaterialOverridesNew);
|
||||
componentCustomSlotMaterials.AddRange(customSlotMaterialsNew);
|
||||
|
||||
// 5. Restore overrides
|
||||
SetCustomMaterials();
|
||||
|
||||
if (skeletonRenderer != null)
|
||||
skeletonRenderer.LateUpdate();
|
||||
}
|
||||
|
||||
_customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
|
||||
_customSlotMaterialsPrev = CopyList(componentCustomSlotMaterials);
|
||||
|
||||
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Clear and Reapply Changes", tooltip: "Removes all non-serialized overrides in the SkeletonRenderer and reapplies the overrides on this component."))) {
|
||||
if (skeletonRenderer != null) {
|
||||
#if SPINE_OPTIONAL_MATERIALOVERRIDE
|
||||
skeletonRenderer.CustomMaterialOverride.Clear();
|
||||
#endif
|
||||
skeletonRenderer.CustomSlotMaterials.Clear();
|
||||
RemoveCustomMaterials();
|
||||
SetCustomMaterials();
|
||||
skeletonRenderer.LateUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveCustomMaterials () {
|
||||
RemoveCustomMaterialOverrides.Invoke(component, null);
|
||||
RemoveCustomSlotMaterials.Invoke(component, null);
|
||||
}
|
||||
|
||||
void SetCustomMaterials () {
|
||||
SetCustomMaterialOverrides.Invoke(component, null);
|
||||
SetCustomSlotMaterials.Invoke(component, null);
|
||||
}
|
||||
|
||||
static List<T> CopyList<T> (List<T> list) {
|
||||
return list.GetRange(0, list.Count);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e70f7f2a241d6d34aafd6a4a52a368d0
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,682 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#else
|
||||
#define NO_PREFAB_MESH
|
||||
#endif
|
||||
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
#define PER_MATERIAL_PROPERTY_BLOCKS
|
||||
#endif
|
||||
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
#define BUILT_IN_SPRITE_MASK_COMPONENT
|
||||
#endif
|
||||
|
||||
#if UNITY_2020_2_OR_NEWER
|
||||
#define HAS_ON_POSTPROCESS_PREFAB
|
||||
#endif
|
||||
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Event = UnityEngine.Event;
|
||||
using Icons = SpineEditorUtilities.Icons;
|
||||
|
||||
[CustomEditor(typeof(SkeletonRenderer))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonRendererInspector : UnityEditor.Editor {
|
||||
public static bool advancedFoldout;
|
||||
protected bool loadingFailed = false;
|
||||
|
||||
const string SeparatorSlotNamesFieldName = "separatorSlotNames";
|
||||
|
||||
protected SerializedProperty skeletonDataAsset, initialSkinName;
|
||||
protected SerializedProperty initialFlipX, initialFlipY;
|
||||
protected SerializedProperty updateTiming, updateWhenInvisible, singleSubmesh, separatorSlotNames,
|
||||
clearStateOnDisable, immutableTriangles, fixDrawOrder, fixPrefabOverrideViaMeshFilter;
|
||||
protected SerializedProperty normals, tangents, zSpacing, pmaVertexColors, tintBlack; // MeshGenerator settings
|
||||
protected SerializedProperty maskInteraction;
|
||||
protected SerializedProperty maskMaterialsNone, maskMaterialsInside, maskMaterialsOutside;
|
||||
protected SerializedProperty physicsPositionInheritanceFactor, physicsRotationInheritanceFactor, physicsMovementRelativeTo;
|
||||
protected SpineInspectorUtility.SerializedSortingProperties sortingProperties;
|
||||
protected bool wasInitParameterChanged = false;
|
||||
protected bool requireRepaint = false;
|
||||
|
||||
protected bool isInspectingPrefab;
|
||||
protected bool forceReloadQueued = false;
|
||||
protected bool setMaskNoneMaterialsQueued = false;
|
||||
protected bool setInsideMaskMaterialsQueued = false;
|
||||
protected bool setOutsideMaskMaterialsQueued = false;
|
||||
protected bool deleteInsideMaskMaterialsQueued = false;
|
||||
protected bool deleteOutsideMaskMaterialsQueued = false;
|
||||
|
||||
protected GUIContent SkeletonDataAssetLabel, SkeletonUtilityButtonContent;
|
||||
protected GUIContent PMAVertexColorsLabel, ClearStateOnDisableLabel, ZSpacingLabel, ImmubleTrianglesLabel,
|
||||
TintBlackLabel, UpdateTimingLabel, UpdateWhenInvisibleLabel, SingleSubmeshLabel, FixDrawOrderLabel, FixPrefabOverrideViaMeshFilterLabel;
|
||||
protected GUIContent NormalsLabel, TangentsLabel, MaskInteractionLabel;
|
||||
protected GUIContent MaskMaterialsHeadingLabel, MaskMaterialsNoneLabel, MaskMaterialsInsideLabel, MaskMaterialsOutsideLabel;
|
||||
protected GUIContent SetMaterialButtonLabel, ClearMaterialButtonLabel, DeleteMaterialButtonLabel;
|
||||
|
||||
readonly GUIContent PhysicsPositionInheritanceFactorLabel = new GUIContent("Position",
|
||||
"When set to non-zero, Transform position movement in X and Y direction is applied to skeleton " +
|
||||
"PhysicsConstraints, multiplied by these " +
|
||||
"\nX and Y scale factors to the right. Typical (X,Y) values are " +
|
||||
"\n(1,1) to apply XY movement normally, " +
|
||||
"\n(2,2) to apply movement with double intensity, " +
|
||||
"\n(1,0) to apply only horizontal movement, or" +
|
||||
"\n(0,0) to not apply any Transform position movement at all.");
|
||||
readonly GUIContent PhysicsRotationInheritanceFactorLabel = new GUIContent("Rotation",
|
||||
"When set to non-zero, Transform rotation movement is applied to skeleton PhysicsConstraints, " +
|
||||
"multiplied by this scale factor to the right. Typical values are " +
|
||||
"\n1 to apply movement normally, " +
|
||||
"\n2 to apply movement with double intensity, or " +
|
||||
"\n0 to not apply any Transform rotation movement at all.");
|
||||
readonly GUIContent PhysicsMovementRelativeToLabel = new GUIContent("Movement relative to",
|
||||
"Reference transform relative to which physics movement will be calculated, or null to use world location.");
|
||||
|
||||
const string ReloadButtonString = "Reload";
|
||||
static GUILayoutOption reloadButtonWidth;
|
||||
static GUILayoutOption ReloadButtonWidth { get { return reloadButtonWidth = reloadButtonWidth ?? GUILayout.Width(GUI.skin.label.CalcSize(new GUIContent(ReloadButtonString)).x + 20); } }
|
||||
static GUIStyle ReloadButtonStyle { get { return EditorStyles.miniButton; } }
|
||||
|
||||
protected bool TargetIsValid {
|
||||
get {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
foreach (UnityEngine.Object o in targets) {
|
||||
SkeletonRenderer component = (SkeletonRenderer)o;
|
||||
if (!component.valid)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
SkeletonRenderer component = (SkeletonRenderer)target;
|
||||
return component.valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnEnable () {
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
isInspectingPrefab = false;
|
||||
#else
|
||||
isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
|
||||
#endif
|
||||
SpineEditorUtilities.ConfirmInitialization();
|
||||
loadingFailed = false;
|
||||
|
||||
// Labels
|
||||
SkeletonDataAssetLabel = new GUIContent("SkeletonData Asset", Icons.spine);
|
||||
SkeletonUtilityButtonContent = new GUIContent("Add Skeleton Utility", Icons.skeletonUtility);
|
||||
ImmubleTrianglesLabel = new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility");
|
||||
PMAVertexColorsLabel = new GUIContent("PMA Vertex Colors", "Use this if you are using the default Spine/Skeleton shader or any premultiply-alpha shader.");
|
||||
ClearStateOnDisableLabel = new GUIContent("Clear State On Disable", "Use this if you are pooling or enabling/disabling your Spine GameObject.");
|
||||
ZSpacingLabel = new GUIContent("Z Spacing", "A value other than 0 adds a space between each rendered attachment to prevent Z Fighting when using shaders that read or write to the depth buffer. Large values may cause unwanted parallax and spaces depending on camera setup.");
|
||||
NormalsLabel = new GUIContent("Add Normals", "Use this if your shader requires vertex normals. A more efficient solution for 2D setups is to modify the shader to assume a single normal value for the whole mesh.");
|
||||
TangentsLabel = new GUIContent("Solve Tangents", "Calculates the tangents per frame. Use this if you are using lit shaders (usually with normal maps) that require vertex tangents.");
|
||||
TintBlackLabel = new GUIContent("Tint Black (!)", "Adds black tint vertex data to the mesh as UV2 and UV3. Black tinting requires that the shader interpret UV2 and UV3 as black tint colors for this effect to work. You may also use the default [Spine/Skeleton Tint Black] shader.\n\nIf you only need to tint the whole skeleton and not individual parts, the [Spine/Skeleton Tint] shader is recommended for better efficiency and changing/animating the _Black material property via MaterialPropertyBlock.");
|
||||
SingleSubmeshLabel = new GUIContent("Use Single Submesh", "Simplifies submesh generation by assuming you are only using one Material and need only one submesh. This is will disable multiple materials, render separation, and custom slot materials.");
|
||||
UpdateTimingLabel = new GUIContent("Animation Update", "Whether to update the animation in normal Update (the default), physics step FixedUpdate, or manually via a user call.");
|
||||
UpdateWhenInvisibleLabel = new GUIContent("Update When Invisible", "Update mode used when the MeshRenderer becomes invisible. Update mode is automatically reset to UpdateMode.FullUpdate when the mesh becomes visible again.");
|
||||
FixDrawOrderLabel = new GUIContent("Fix Draw Order", "Applies only when 3+ submeshes are used (2+ materials with alternating order, e.g. \"A B A\"). If true, GPU instancing will be disabled at all materials and MaterialPropertyBlocks are assigned at each material to prevent aggressive batching of submeshes by e.g. the LWRP renderer, leading to incorrect draw order (e.g. \"A1 B A2\" changed to \"A1A2 B\"). You can disable this parameter when everything is drawn correctly to save the additional performance cost. Note: the GPU instancing setting will remain disabled at affected material assets after exiting play mode, you have to enable it manually if you accidentally enabled this parameter.");
|
||||
FixPrefabOverrideViaMeshFilterLabel = new GUIContent("Fix Prefab Overr. MeshFilter", "Fixes the prefab always being marked as changed (sets the MeshFilter's hide flags to DontSaveInEditor), but at the cost of references to the MeshFilter by other components being lost. For global settings see Edit - Preferences - Spine.");
|
||||
MaskInteractionLabel = new GUIContent("Mask Interaction", "SkeletonRenderer's interaction with a Sprite Mask.");
|
||||
MaskMaterialsHeadingLabel = new GUIContent("Mask Interaction Materials", "Materials used for different interaction with sprite masks.");
|
||||
MaskMaterialsNoneLabel = new GUIContent("Normal Materials", "Normal materials used when Mask Interaction is set to None.");
|
||||
MaskMaterialsInsideLabel = new GUIContent("Inside Mask", "Materials used when Mask Interaction is set to Inside Mask.");
|
||||
MaskMaterialsOutsideLabel = new GUIContent("Outside Mask", "Materials used when Mask Interaction is set to Outside Mask.");
|
||||
SetMaterialButtonLabel = new GUIContent("Set", "Prepares material references for switching to the corresponding Mask Interaction mode at runtime. Creates the required materials if they do not exist.");
|
||||
ClearMaterialButtonLabel = new GUIContent("Clear", "Clears unused material references. Note: when switching to the corresponding Mask Interaction mode at runtime, a new material is generated on the fly.");
|
||||
DeleteMaterialButtonLabel = new GUIContent("Delete", "Clears unused material references and deletes the corresponding assets. Note: when switching to the corresponding Mask Interaction mode at runtime, a new material is generated on the fly.");
|
||||
|
||||
SerializedObject so = this.serializedObject;
|
||||
skeletonDataAsset = so.FindProperty("skeletonDataAsset");
|
||||
initialSkinName = so.FindProperty("initialSkinName");
|
||||
initialFlipX = so.FindProperty("initialFlipX");
|
||||
initialFlipY = so.FindProperty("initialFlipY");
|
||||
normals = so.FindProperty("addNormals");
|
||||
tangents = so.FindProperty("calculateTangents");
|
||||
immutableTriangles = so.FindProperty("immutableTriangles");
|
||||
pmaVertexColors = so.FindProperty("pmaVertexColors");
|
||||
clearStateOnDisable = so.FindProperty("clearStateOnDisable");
|
||||
tintBlack = so.FindProperty("tintBlack");
|
||||
updateTiming = so.FindProperty("updateTiming");
|
||||
updateWhenInvisible = so.FindProperty("updateWhenInvisible");
|
||||
singleSubmesh = so.FindProperty("singleSubmesh");
|
||||
fixDrawOrder = so.FindProperty("fixDrawOrder");
|
||||
fixPrefabOverrideViaMeshFilter = so.FindProperty("fixPrefabOverrideViaMeshFilter");
|
||||
maskInteraction = so.FindProperty("maskInteraction");
|
||||
maskMaterialsNone = so.FindProperty("maskMaterials.materialsMaskDisabled");
|
||||
maskMaterialsInside = so.FindProperty("maskMaterials.materialsInsideMask");
|
||||
maskMaterialsOutside = so.FindProperty("maskMaterials.materialsOutsideMask");
|
||||
physicsPositionInheritanceFactor = so.FindProperty("physicsPositionInheritanceFactor");
|
||||
physicsRotationInheritanceFactor = so.FindProperty("physicsRotationInheritanceFactor");
|
||||
physicsMovementRelativeTo = so.FindProperty("physicsMovementRelativeTo");
|
||||
|
||||
separatorSlotNames = so.FindProperty("separatorSlotNames");
|
||||
separatorSlotNames.isExpanded = true;
|
||||
|
||||
zSpacing = so.FindProperty("zSpacing");
|
||||
|
||||
SerializedObject renderersSerializedObject = SpineInspectorUtility.GetRenderersSerializedObject(serializedObject); // Allows proper multi-edit behavior.
|
||||
sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(renderersSerializedObject);
|
||||
}
|
||||
|
||||
public void OnSceneGUI () {
|
||||
SkeletonRenderer skeletonRenderer = (SkeletonRenderer)target;
|
||||
if (loadingFailed)
|
||||
return;
|
||||
|
||||
Skeleton skeleton = skeletonRenderer.Skeleton;
|
||||
if (skeleton == null) {
|
||||
loadingFailed = true;
|
||||
return;
|
||||
}
|
||||
Transform transform = skeletonRenderer.transform;
|
||||
if (skeleton == null) return;
|
||||
|
||||
SpineHandles.DrawBones(transform, skeleton);
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
bool multi = serializedObject.isEditingMultipleObjects;
|
||||
DrawInspectorGUI(multi);
|
||||
HandleSkinChange();
|
||||
if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current) ||
|
||||
AreAnyMaskMaterialsMissing()) {
|
||||
if (!Application.isPlaying) {
|
||||
foreach (UnityEngine.Object o in targets)
|
||||
SpineEditorUtilities.ReinitializeComponent((SkeletonRenderer)o);
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
if (!isInspectingPrefab) {
|
||||
if (requireRepaint) {
|
||||
SceneView.RepaintAll();
|
||||
requireRepaint = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DrawInspectorGUI (bool multi) {
|
||||
// Initialize.
|
||||
if (Event.current.type == EventType.Layout) {
|
||||
if (forceReloadQueued) {
|
||||
forceReloadQueued = false;
|
||||
foreach (UnityEngine.Object c in targets) {
|
||||
SpineEditorUtilities.ReloadSkeletonDataAssetAndComponent(c as SkeletonRenderer);
|
||||
}
|
||||
} else {
|
||||
foreach (UnityEngine.Object c in targets) {
|
||||
SkeletonRenderer component = c as SkeletonRenderer;
|
||||
if (!component.valid) {
|
||||
SpineEditorUtilities.ReinitializeComponent(component);
|
||||
if (!component.valid) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILT_IN_SPRITE_MASK_COMPONENT
|
||||
if (setMaskNoneMaterialsQueued) {
|
||||
setMaskNoneMaterialsQueued = false;
|
||||
foreach (UnityEngine.Object c in targets)
|
||||
EditorSetMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.None);
|
||||
}
|
||||
if (setInsideMaskMaterialsQueued) {
|
||||
setInsideMaskMaterialsQueued = false;
|
||||
foreach (UnityEngine.Object c in targets)
|
||||
EditorSetMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleInsideMask);
|
||||
}
|
||||
if (setOutsideMaskMaterialsQueued) {
|
||||
setOutsideMaskMaterialsQueued = false;
|
||||
foreach (UnityEngine.Object c in targets)
|
||||
EditorSetMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleOutsideMask);
|
||||
}
|
||||
|
||||
if (deleteInsideMaskMaterialsQueued) {
|
||||
deleteInsideMaskMaterialsQueued = false;
|
||||
foreach (UnityEngine.Object c in targets)
|
||||
EditorDeleteMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleInsideMask);
|
||||
}
|
||||
if (deleteOutsideMaskMaterialsQueued) {
|
||||
deleteOutsideMaskMaterialsQueued = false;
|
||||
foreach (UnityEngine.Object c in targets)
|
||||
EditorDeleteMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleOutsideMask);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NO_PREFAB_MESH
|
||||
if (isInspectingPrefab) {
|
||||
foreach (UnityEngine.Object c in targets) {
|
||||
SkeletonRenderer component = (SkeletonRenderer)c;
|
||||
MeshFilter meshFilter = component.GetComponent<MeshFilter>();
|
||||
if (meshFilter != null && meshFilter.sharedMesh != null)
|
||||
meshFilter.sharedMesh = null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool valid = TargetIsValid;
|
||||
|
||||
foreach (UnityEngine.Object o in targets)
|
||||
ApplyModifiedMeshParameters(o as SkeletonRenderer);
|
||||
|
||||
// Fields.
|
||||
if (multi) {
|
||||
using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) {
|
||||
SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel);
|
||||
if (GUILayout.Button(ReloadButtonString, ReloadButtonStyle, ReloadButtonWidth))
|
||||
forceReloadQueued = true;
|
||||
}
|
||||
|
||||
if (valid) EditorGUILayout.PropertyField(initialSkinName, SpineInspectorUtility.TempContent("Initial Skin"));
|
||||
|
||||
} else {
|
||||
SkeletonRenderer component = (SkeletonRenderer)target;
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) {
|
||||
SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel);
|
||||
if (component.valid) {
|
||||
if (GUILayout.Button(ReloadButtonString, ReloadButtonStyle, ReloadButtonWidth))
|
||||
forceReloadQueued = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (component.skeletonDataAsset == null) {
|
||||
EditorGUILayout.HelpBox("SkeletonData asset required", MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SpineEditorUtilities.SkeletonDataAssetIsValid(component.skeletonDataAsset)) {
|
||||
EditorGUILayout.HelpBox("SkeletonData asset error. Please check SkeletonData asset.", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (valid)
|
||||
EditorGUILayout.PropertyField(initialSkinName, SpineInspectorUtility.TempContent("Initial Skin"));
|
||||
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// Sorting Layers
|
||||
SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true);
|
||||
|
||||
if (maskInteraction != null) EditorGUILayout.PropertyField(maskInteraction, MaskInteractionLabel);
|
||||
|
||||
if (!valid)
|
||||
return;
|
||||
|
||||
string errorMessage = null;
|
||||
if (SpineEditorUtilities.Preferences.componentMaterialWarning &&
|
||||
MaterialChecks.IsMaterialSetupProblematic((SkeletonRenderer)this.target, ref errorMessage)) {
|
||||
EditorGUILayout.HelpBox(errorMessage, MessageType.Error, true);
|
||||
}
|
||||
|
||||
// More Render Options...
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
|
||||
advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
|
||||
if (advancedFoldout) {
|
||||
EditorGUILayout.Space();
|
||||
if (GUILayout.Button("Debug", EditorStyles.miniButton, GUILayout.Width(65f)))
|
||||
SkeletonDebugWindow.Init();
|
||||
} else {
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (advancedFoldout) {
|
||||
|
||||
using (new SpineInspectorUtility.IndentScope()) {
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
SpineInspectorUtility.ToggleLeftLayout(initialFlipX);
|
||||
SpineInspectorUtility.ToggleLeftLayout(initialFlipY);
|
||||
wasInitParameterChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField("Renderer and Update Settings", EditorStyles.boldLabel);
|
||||
using (new SpineInspectorUtility.LabelWidthScope()) {
|
||||
// Optimization options
|
||||
if (updateTiming != null) EditorGUILayout.PropertyField(updateTiming, UpdateTimingLabel);
|
||||
if (updateWhenInvisible != null) EditorGUILayout.PropertyField(updateWhenInvisible, UpdateWhenInvisibleLabel);
|
||||
|
||||
if (singleSubmesh != null) EditorGUILayout.PropertyField(singleSubmesh, SingleSubmeshLabel);
|
||||
#if PER_MATERIAL_PROPERTY_BLOCKS
|
||||
if (fixDrawOrder != null) EditorGUILayout.PropertyField(fixDrawOrder, FixDrawOrderLabel);
|
||||
#endif
|
||||
if (immutableTriangles != null) EditorGUILayout.PropertyField(immutableTriangles, ImmubleTrianglesLabel);
|
||||
EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
#if HAS_ON_POSTPROCESS_PREFAB
|
||||
if (fixPrefabOverrideViaMeshFilter != null) EditorGUILayout.PropertyField(fixPrefabOverrideViaMeshFilter, FixPrefabOverrideViaMeshFilterLabel);
|
||||
EditorGUILayout.Space();
|
||||
#endif
|
||||
}
|
||||
|
||||
SeparatorsField(separatorSlotNames);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// Render options
|
||||
const float MinZSpacing = -0.1f;
|
||||
const float MaxZSpacing = 0f;
|
||||
EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing, ZSpacingLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
using (new SpineInspectorUtility.LabelWidthScope()) {
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", SpineInspectorUtility.UnityIcon<MeshFilter>()), EditorStyles.boldLabel);
|
||||
if (pmaVertexColors != null) EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel);
|
||||
EditorGUILayout.PropertyField(tintBlack, TintBlackLabel);
|
||||
|
||||
// Optional fields. May be disabled in SkeletonRenderer.
|
||||
if (normals != null) EditorGUILayout.PropertyField(normals, NormalsLabel);
|
||||
if (tangents != null) EditorGUILayout.PropertyField(tangents, TangentsLabel);
|
||||
}
|
||||
|
||||
#if BUILT_IN_SPRITE_MASK_COMPONENT
|
||||
EditorGUILayout.Space();
|
||||
if (maskMaterialsNone.arraySize > 0 || maskMaterialsInside.arraySize > 0 || maskMaterialsOutside.arraySize > 0) {
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Mask Interaction Materials", SpineInspectorUtility.UnityIcon<SpriteMask>()), EditorStyles.boldLabel);
|
||||
bool differentMaskModesSelected = maskInteraction.hasMultipleDifferentValues;
|
||||
int activeMaskInteractionValue = differentMaskModesSelected ? -1 : maskInteraction.intValue;
|
||||
|
||||
bool ignoredParam = true;
|
||||
MaskMaterialsEditingField(ref setMaskNoneMaterialsQueued, ref ignoredParam, maskMaterialsNone, MaskMaterialsNoneLabel,
|
||||
differentMaskModesSelected, allowDelete: false, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.None);
|
||||
MaskMaterialsEditingField(ref setInsideMaskMaterialsQueued, ref deleteInsideMaskMaterialsQueued, maskMaterialsInside, MaskMaterialsInsideLabel,
|
||||
differentMaskModesSelected, allowDelete: true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleInsideMask);
|
||||
MaskMaterialsEditingField(ref setOutsideMaskMaterialsQueued, ref deleteOutsideMaskMaterialsQueued, maskMaterialsOutside, MaskMaterialsOutsideLabel,
|
||||
differentMaskModesSelected, allowDelete: true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleOutsideMask);
|
||||
}
|
||||
#endif
|
||||
using (new SpineInspectorUtility.LabelWidthScope()) {
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Physics Inheritance", SpineEditorUtilities.Icons.constraintPhysics), EditorStyles.boldLabel);
|
||||
|
||||
using (new GUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.LabelField(PhysicsPositionInheritanceFactorLabel, GUILayout.Width(EditorGUIUtility.labelWidth));
|
||||
int savedIndentLevel = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
EditorGUILayout.PropertyField(physicsPositionInheritanceFactor, GUIContent.none, GUILayout.MinWidth(60));
|
||||
EditorGUI.indentLevel = savedIndentLevel;
|
||||
}
|
||||
EditorGUILayout.PropertyField(physicsRotationInheritanceFactor, PhysicsRotationInheritanceFactorLabel);
|
||||
EditorGUILayout.PropertyField(physicsMovementRelativeTo, PhysicsMovementRelativeToLabel);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (valid && !isInspectingPrefab) {
|
||||
if (multi) {
|
||||
// Support multi-edit SkeletonUtility button.
|
||||
// EditorGUILayout.Space();
|
||||
// bool addSkeletonUtility = GUILayout.Button(buttonContent, GUILayout.Height(30));
|
||||
// foreach (UnityEngine.Object t in targets) {
|
||||
// Component component = t as Component;
|
||||
// if (addSkeletonUtility && component.GetComponent<SkeletonUtility>() == null)
|
||||
// component.gameObject.AddComponent<SkeletonUtility>();
|
||||
// }
|
||||
} else {
|
||||
Component component = (Component)target;
|
||||
if (component.GetComponent<SkeletonUtility>() == null) {
|
||||
if (SpineInspectorUtility.CenteredButton(SkeletonUtilityButtonContent, 21, true, 200f))
|
||||
component.gameObject.AddComponent<SkeletonUtility>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
protected void ApplyModifiedMeshParameters (SkeletonRenderer skeletonRenderer) {
|
||||
if (skeletonRenderer == null) return;
|
||||
if (!skeletonRenderer.valid)
|
||||
return;
|
||||
|
||||
if (!isInspectingPrefab) {
|
||||
if (wasInitParameterChanged) {
|
||||
wasInitParameterChanged = false;
|
||||
if (!Application.isPlaying) {
|
||||
skeletonRenderer.Initialize(true);
|
||||
skeletonRenderer.LateUpdate();
|
||||
requireRepaint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void SkeletonRootMotionParameter () {
|
||||
SkeletonRootMotionParameter(targets);
|
||||
}
|
||||
|
||||
public static void SkeletonRootMotionParameter (Object[] targets) {
|
||||
int rootMotionComponentCount = 0;
|
||||
foreach (UnityEngine.Object t in targets) {
|
||||
Component component = t as Component;
|
||||
if (component.GetComponent<SkeletonRootMotion>() != null) {
|
||||
++rootMotionComponentCount;
|
||||
}
|
||||
}
|
||||
bool allHaveRootMotion = rootMotionComponentCount == targets.Length;
|
||||
bool anyHaveRootMotion = rootMotionComponentCount > 0;
|
||||
|
||||
using (new GUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.PrefixLabel("Root Motion");
|
||||
|
||||
if (!allHaveRootMotion) {
|
||||
if (GUILayout.Button(SpineInspectorUtility.TempContent("Add Component", Icons.constraintTransform), GUILayout.MaxWidth(130), GUILayout.Height(18))) {
|
||||
foreach (UnityEngine.Object t in targets) {
|
||||
Component component = t as Component;
|
||||
if (component.GetComponent<SkeletonRootMotion>() == null) {
|
||||
component.gameObject.AddComponent<SkeletonRootMotion>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (anyHaveRootMotion) {
|
||||
if (GUILayout.Button(SpineInspectorUtility.TempContent("Remove Component", Icons.constraintTransform), GUILayout.MaxWidth(140), GUILayout.Height(18))) {
|
||||
foreach (UnityEngine.Object t in targets) {
|
||||
Component component = t as Component;
|
||||
SkeletonRootMotion rootMotionComponent = component.GetComponent<SkeletonRootMotion>();
|
||||
if (rootMotionComponent != null) {
|
||||
DestroyImmediate(rootMotionComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetSeparatorSlotNames (SkeletonRenderer skeletonRenderer, string[] newSlotNames) {
|
||||
FieldInfo field = SpineInspectorUtility.GetNonPublicField(typeof(SkeletonRenderer), SeparatorSlotNamesFieldName);
|
||||
field.SetValue(skeletonRenderer, newSlotNames);
|
||||
}
|
||||
|
||||
public static string[] GetSeparatorSlotNames (SkeletonRenderer skeletonRenderer) {
|
||||
FieldInfo field = SpineInspectorUtility.GetNonPublicField(typeof(SkeletonRenderer), SeparatorSlotNamesFieldName);
|
||||
return field.GetValue(skeletonRenderer) as string[];
|
||||
}
|
||||
|
||||
public static void SeparatorsField (SerializedProperty separatorSlotNames) {
|
||||
bool multi = separatorSlotNames.serializedObject.isEditingMultipleObjects;
|
||||
bool hasTerminalSlot = false;
|
||||
if (!multi) {
|
||||
ISkeletonComponent sr = separatorSlotNames.serializedObject.targetObject as ISkeletonComponent;
|
||||
Skeleton skeleton = sr.Skeleton;
|
||||
int lastSlot = skeleton.Slots.Count - 1;
|
||||
if (skeleton != null) {
|
||||
for (int i = 0, n = separatorSlotNames.arraySize; i < n; i++) {
|
||||
string slotName = separatorSlotNames.GetArrayElementAtIndex(i).stringValue;
|
||||
SlotData slot = skeleton.Data.FindSlot(slotName);
|
||||
int index = slot != null ? slot.Index : -1;
|
||||
if (index == 0 || index == lastSlot) {
|
||||
hasTerminalSlot = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string terminalSlotWarning = hasTerminalSlot ? " (!)" : "";
|
||||
|
||||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
|
||||
const string SeparatorsDescription = "Stored names of slots where the Skeleton's render will be split into different batches. This is used by separate components that split the render into different MeshRenderers or GameObjects.";
|
||||
if (separatorSlotNames.isExpanded) {
|
||||
EditorGUILayout.PropertyField(separatorSlotNames, SpineInspectorUtility.TempContent(separatorSlotNames.displayName + terminalSlotWarning, Icons.slotRoot, SeparatorsDescription), true);
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button("+", GUILayout.MaxWidth(28f), GUILayout.MaxHeight(15f))) {
|
||||
separatorSlotNames.arraySize++;
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
} else
|
||||
EditorGUILayout.PropertyField(separatorSlotNames, new GUIContent(separatorSlotNames.displayName + string.Format("{0} [{1}]", terminalSlotWarning, separatorSlotNames.arraySize), SeparatorsDescription), true);
|
||||
}
|
||||
}
|
||||
|
||||
public void MaskMaterialsEditingField (ref bool wasSetRequested, ref bool wasDeleteRequested,
|
||||
SerializedProperty maskMaterials, GUIContent label,
|
||||
bool differentMaskModesSelected, bool allowDelete, bool isActiveMaterial) {
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
|
||||
EditorGUILayout.LabelField(label, isActiveMaterial ? EditorStyles.boldLabel : EditorStyles.label, GUILayout.MinWidth(80f), GUILayout.MaxWidth(140));
|
||||
EditorGUILayout.LabelField(maskMaterials.hasMultipleDifferentValues ? "-" : maskMaterials.arraySize.ToString(), EditorStyles.miniLabel, GUILayout.Width(42f));
|
||||
|
||||
bool enableSetButton = differentMaskModesSelected || maskMaterials.arraySize == 0;
|
||||
bool enableClearButtons = differentMaskModesSelected || (maskMaterials.arraySize != 0 && !isActiveMaterial);
|
||||
|
||||
EditorGUI.BeginDisabledGroup(!enableSetButton);
|
||||
if (GUILayout.Button(SetMaterialButtonLabel, EditorStyles.miniButtonLeft, GUILayout.Width(46f))) {
|
||||
wasSetRequested = true;
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
EditorGUI.BeginDisabledGroup(!enableClearButtons);
|
||||
{
|
||||
if (GUILayout.Button(ClearMaterialButtonLabel, allowDelete ? EditorStyles.miniButtonMid : EditorStyles.miniButtonRight, GUILayout.Width(46f))) {
|
||||
maskMaterials.ClearArray();
|
||||
} else if (allowDelete && GUILayout.Button(DeleteMaterialButtonLabel, EditorStyles.miniButtonRight, GUILayout.Width(46f))) {
|
||||
wasDeleteRequested = true;
|
||||
}
|
||||
if (!allowDelete)
|
||||
GUILayout.Space(46f);
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
}
|
||||
|
||||
void HandleSkinChange () {
|
||||
if (!Application.isPlaying && Event.current.type == EventType.Layout && !initialSkinName.hasMultipleDifferentValues) {
|
||||
bool mismatchDetected = false;
|
||||
string newSkinName = initialSkinName.stringValue;
|
||||
foreach (UnityEngine.Object o in targets) {
|
||||
mismatchDetected |= UpdateIfSkinMismatch((SkeletonRenderer)o, newSkinName);
|
||||
}
|
||||
|
||||
if (mismatchDetected) {
|
||||
mismatchDetected = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool UpdateIfSkinMismatch (SkeletonRenderer skeletonRenderer, string componentSkinName) {
|
||||
if (!skeletonRenderer.valid || skeletonRenderer.EditorSkipSkinSync) return false;
|
||||
|
||||
Skin skin = skeletonRenderer.Skeleton.Skin;
|
||||
string skeletonSkinName = skin != null ? skin.Name : null;
|
||||
bool defaultCase = skin == null && string.IsNullOrEmpty(componentSkinName);
|
||||
bool fieldMatchesSkin = defaultCase || string.Equals(componentSkinName, skeletonSkinName, System.StringComparison.Ordinal);
|
||||
|
||||
if (!fieldMatchesSkin) {
|
||||
Skin skinToSet = string.IsNullOrEmpty(componentSkinName) ? null : skeletonRenderer.Skeleton.Data.FindSkin(componentSkinName);
|
||||
skeletonRenderer.Skeleton.SetSkin(skinToSet);
|
||||
skeletonRenderer.Skeleton.SetSlotsToSetupPose();
|
||||
|
||||
// Note: the UpdateIfSkinMismatch concept shall be replaced with e.g. an OnValidate based
|
||||
// solution or in a separate commit. The current solution does not repaint the Game view because
|
||||
// it is first applying values and in the next editor pass is calling this skin-changing method.
|
||||
if (skeletonRenderer is SkeletonAnimation)
|
||||
((SkeletonAnimation)skeletonRenderer).Update(0f);
|
||||
else if (skeletonRenderer is SkeletonMecanim)
|
||||
((SkeletonMecanim)skeletonRenderer).Update();
|
||||
|
||||
skeletonRenderer.LateUpdate();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AreAnyMaskMaterialsMissing () {
|
||||
#if BUILT_IN_SPRITE_MASK_COMPONENT
|
||||
foreach (UnityEngine.Object o in targets) {
|
||||
SkeletonRenderer component = (SkeletonRenderer)o;
|
||||
if (!component.valid)
|
||||
continue;
|
||||
if (SpineMaskUtilities.AreMaskMaterialsMissing(component))
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#if BUILT_IN_SPRITE_MASK_COMPONENT
|
||||
static void EditorSetMaskMaterials (SkeletonRenderer component, SpriteMaskInteraction maskType) {
|
||||
if (component == null) return;
|
||||
if (!SpineEditorUtilities.SkeletonDataAssetIsValid(component.SkeletonDataAsset)) return;
|
||||
SpineMaskUtilities.EditorInitMaskMaterials(component, component.maskMaterials, maskType);
|
||||
}
|
||||
|
||||
static void EditorDeleteMaskMaterials (SkeletonRenderer component, SpriteMaskInteraction maskType) {
|
||||
if (component == null) return;
|
||||
if (!SpineEditorUtilities.SkeletonDataAssetIsValid(component.SkeletonDataAsset)) return;
|
||||
SpineMaskUtilities.EditorDeleteMaskMaterials(component.maskMaterials, maskType);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0fc5db9788bce4418ad3252d43faa8a
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,148 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
[CustomEditor(typeof(SkeletonRootMotionBase))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonRootMotionBaseInspector : UnityEditor.Editor {
|
||||
protected SerializedProperty rootMotionBoneName;
|
||||
protected SerializedProperty transformPositionX;
|
||||
protected SerializedProperty transformPositionY;
|
||||
protected SerializedProperty transformRotation;
|
||||
protected SerializedProperty rootMotionScaleX;
|
||||
protected SerializedProperty rootMotionScaleY;
|
||||
protected SerializedProperty rootMotionScaleRotation;
|
||||
protected SerializedProperty rootMotionTranslateXPerY;
|
||||
protected SerializedProperty rootMotionTranslateYPerX;
|
||||
protected SerializedProperty rigidBody2D;
|
||||
protected SerializedProperty applyRigidbody2DGravity;
|
||||
protected SerializedProperty rigidBody;
|
||||
|
||||
protected GUIContent rootMotionBoneNameLabel;
|
||||
protected GUIContent transformPositionXLabel;
|
||||
protected GUIContent transformPositionYLabel;
|
||||
protected GUIContent transformRotationLabel;
|
||||
protected GUIContent rootMotionScaleXLabel;
|
||||
protected GUIContent rootMotionScaleYLabel;
|
||||
protected GUIContent rootMotionScaleRotationLabel;
|
||||
protected GUIContent rootMotionTranslateXPerYLabel;
|
||||
protected GUIContent rootMotionTranslateYPerXLabel;
|
||||
protected GUIContent rigidBody2DLabel;
|
||||
protected GUIContent applyRigidbody2DGravityLabel;
|
||||
protected GUIContent rigidBodyLabel;
|
||||
|
||||
protected virtual void OnEnable () {
|
||||
|
||||
rootMotionBoneName = serializedObject.FindProperty("rootMotionBoneName");
|
||||
transformPositionX = serializedObject.FindProperty("transformPositionX");
|
||||
transformPositionY = serializedObject.FindProperty("transformPositionY");
|
||||
transformRotation = serializedObject.FindProperty("transformRotation");
|
||||
rootMotionScaleX = serializedObject.FindProperty("rootMotionScaleX");
|
||||
rootMotionScaleY = serializedObject.FindProperty("rootMotionScaleY");
|
||||
rootMotionScaleRotation = serializedObject.FindProperty("rootMotionScaleRotation");
|
||||
rootMotionTranslateXPerY = serializedObject.FindProperty("rootMotionTranslateXPerY");
|
||||
rootMotionTranslateYPerX = serializedObject.FindProperty("rootMotionTranslateYPerX");
|
||||
rigidBody2D = serializedObject.FindProperty("rigidBody2D");
|
||||
applyRigidbody2DGravity = serializedObject.FindProperty("applyRigidbody2DGravity");
|
||||
rigidBody = serializedObject.FindProperty("rigidBody");
|
||||
|
||||
rootMotionBoneNameLabel = new UnityEngine.GUIContent("Root Motion Bone", "The bone to take the motion from.");
|
||||
transformPositionXLabel = new UnityEngine.GUIContent("X", "Root transform position (X)");
|
||||
transformPositionYLabel = new UnityEngine.GUIContent("Y", "Use the Y-movement of the bone.");
|
||||
transformRotationLabel = new UnityEngine.GUIContent("Rotation", "Use the rotation of the bone.");
|
||||
rootMotionScaleXLabel = new UnityEngine.GUIContent("Root Motion Scale (X)", "Scale applied to the horizontal root motion delta. Can be used for delta compensation to e.g. stretch a jump to the desired distance.");
|
||||
rootMotionScaleYLabel = new UnityEngine.GUIContent("Root Motion Scale (Y)", "Scale applied to the vertical root motion delta. Can be used for delta compensation to e.g. stretch a jump to the desired distance.");
|
||||
rootMotionScaleRotationLabel = new UnityEngine.GUIContent("Root Motion Scale (Rotation)", "Scale applied to the rotational root motion delta. Can be used for delta compensation to e.g. adjust an angled jump landing to the desired platform angle.");
|
||||
rootMotionTranslateXPerYLabel = new UnityEngine.GUIContent("Root Motion Translate (X)", "Added X translation per root motion Y delta. Can be used for delta compensation when scaling is not enough, to e.g. offset a horizontal jump to a vertically different goal.");
|
||||
rootMotionTranslateYPerXLabel = new UnityEngine.GUIContent("Root Motion Translate (Y)", "Added Y translation per root motion X delta. Can be used for delta compensation when scaling is not enough, to e.g. offset a horizontal jump to a vertically different goal.");
|
||||
rigidBody2DLabel = new UnityEngine.GUIContent("Rigidbody2D",
|
||||
"Optional Rigidbody2D: Assign a Rigidbody2D here if you want " +
|
||||
" to apply the root motion to the rigidbody instead of the Transform." +
|
||||
"\n\n" +
|
||||
"Note that animation and physics updates are not always in sync." +
|
||||
"Some jitter may result at certain framerates.");
|
||||
applyRigidbody2DGravityLabel = new UnityEngine.GUIContent("Apply Gravity",
|
||||
"Apply Rigidbody2D Gravity");
|
||||
rigidBodyLabel = new UnityEngine.GUIContent("Rigidbody",
|
||||
"Optional Rigidbody: Assign a Rigidbody here if you want " +
|
||||
" to apply the root motion to the rigidbody instead of the Transform." +
|
||||
"\n\n" +
|
||||
"Note that animation and physics updates are not always in sync." +
|
||||
"Some jitter may result at certain framerates.");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
MainPropertyFields();
|
||||
OptionalPropertyFields();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
protected virtual void MainPropertyFields () {
|
||||
EditorGUILayout.PropertyField(rootMotionBoneName, rootMotionBoneNameLabel);
|
||||
EditorGUILayout.PropertyField(transformPositionX, transformPositionXLabel);
|
||||
EditorGUILayout.PropertyField(transformPositionY, transformPositionYLabel);
|
||||
EditorGUILayout.PropertyField(transformRotation, transformRotationLabel);
|
||||
|
||||
EditorGUILayout.PropertyField(rootMotionScaleX, rootMotionScaleXLabel);
|
||||
EditorGUILayout.PropertyField(rootMotionScaleY, rootMotionScaleYLabel);
|
||||
EditorGUILayout.PropertyField(rootMotionScaleRotation, rootMotionScaleRotationLabel);
|
||||
|
||||
EditorGUILayout.PropertyField(rootMotionTranslateXPerY, rootMotionTranslateXPerYLabel);
|
||||
EditorGUILayout.PropertyField(rootMotionTranslateYPerX, rootMotionTranslateYPerXLabel);
|
||||
}
|
||||
|
||||
protected virtual void OptionalPropertyFields () {
|
||||
EditorGUILayout.PropertyField(rigidBody2D, rigidBody2DLabel);
|
||||
|
||||
if (rigidBody2D.objectReferenceValue != null || rigidBody2D.hasMultipleDifferentValues) {
|
||||
using (new SpineInspectorUtility.IndentScope())
|
||||
EditorGUILayout.PropertyField(applyRigidbody2DGravity, applyRigidbody2DGravityLabel);
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(rigidBody, rigidBodyLabel);
|
||||
DisplayWarnings();
|
||||
}
|
||||
|
||||
protected void DisplayWarnings () {
|
||||
bool usesRigidbodyPhysics = rigidBody.objectReferenceValue != null || rigidBody2D.objectReferenceValue != null;
|
||||
if (usesRigidbodyPhysics) {
|
||||
SkeletonRootMotionBase rootMotionComponent = (SkeletonRootMotionBase)serializedObject.targetObject;
|
||||
ISkeletonAnimation skeletonComponent = rootMotionComponent ? rootMotionComponent.TargetSkeletonAnimationComponent : null;
|
||||
if (skeletonComponent != null && skeletonComponent.UpdateTiming == UpdateTiming.InUpdate) {
|
||||
string warningMessage = "Skeleton component uses 'Advanced - Animation Update' mode 'In Update'.\n" +
|
||||
"When using a Rigidbody, 'In FixedUpdate' is recommended instead.";
|
||||
EditorGUILayout.HelpBox(warningMessage, MessageType.Warning, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2cba83baf6afdf44a996e40017c6325
|
||||
timeCreated: 1593175106
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,79 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
[CustomEditor(typeof(SkeletonRootMotion))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonRootMotionInspector : SkeletonRootMotionBaseInspector {
|
||||
protected SerializedProperty animationTrackFlags;
|
||||
protected GUIContent animationTrackFlagsLabel;
|
||||
|
||||
string[] TrackNames;
|
||||
|
||||
protected override void OnEnable () {
|
||||
base.OnEnable();
|
||||
|
||||
animationTrackFlags = serializedObject.FindProperty("animationTrackFlags");
|
||||
animationTrackFlagsLabel = new UnityEngine.GUIContent("Animation Tracks",
|
||||
"Animation tracks to apply root motion at. Defaults to the first" +
|
||||
" animation track (index 0).");
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
|
||||
base.MainPropertyFields();
|
||||
AnimationTracksPropertyField();
|
||||
|
||||
base.OptionalPropertyFields();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
protected void AnimationTracksPropertyField () {
|
||||
|
||||
if (TrackNames == null) {
|
||||
InitTrackNames();
|
||||
|
||||
}
|
||||
|
||||
animationTrackFlags.intValue = EditorGUILayout.MaskField(
|
||||
animationTrackFlagsLabel, animationTrackFlags.intValue, TrackNames);
|
||||
}
|
||||
|
||||
protected void InitTrackNames () {
|
||||
int numEntries = 32;
|
||||
TrackNames = new string[numEntries];
|
||||
for (int i = 0; i < numEntries; ++i) {
|
||||
TrackNames[i] = string.Format("Track {0}", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4836100aed984c4a9af11d39c63cb6b
|
||||
timeCreated: 1593183609
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,43 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2024, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using UnityEditor;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Icons = SpineEditorUtilities.Icons;
|
||||
|
||||
[CustomEditor(typeof(SkeletonSubmeshGraphic))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonGraphicSubmeshInspector : UnityEditor.Editor {
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
EditorGUILayout.HelpBox("This component is manged by the parent SkeletonGraphic component.", MessageType.None);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1bc35530b2335ef4da1dafa6214b6ccd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,542 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
#if UNITY_2019_2_OR_NEWER
|
||||
#define HINGE_JOINT_NEW_BEHAVIOUR
|
||||
#endif
|
||||
|
||||
using Spine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Icons = SpineEditorUtilities.Icons;
|
||||
|
||||
[CustomEditor(typeof(SkeletonUtilityBone)), CanEditMultipleObjects]
|
||||
public class SkeletonUtilityBoneInspector : UnityEditor.Editor {
|
||||
SerializedProperty mode, boneName, zPosition, position, rotation, scale, overrideAlpha, hierarchy, parentReference;
|
||||
GUIContent hierarchyLabel;
|
||||
|
||||
//multi selected flags
|
||||
bool containsFollows, containsOverrides, multiObject;
|
||||
|
||||
//single selected helpers
|
||||
SkeletonUtilityBone utilityBone;
|
||||
SkeletonUtility skeletonUtility;
|
||||
bool canCreateHingeChain = false;
|
||||
|
||||
Dictionary<Slot, List<BoundingBoxAttachment>> boundingBoxTable = new Dictionary<Slot, List<BoundingBoxAttachment>>();
|
||||
|
||||
void OnEnable () {
|
||||
mode = this.serializedObject.FindProperty("mode");
|
||||
boneName = this.serializedObject.FindProperty("boneName");
|
||||
zPosition = this.serializedObject.FindProperty("zPosition");
|
||||
position = this.serializedObject.FindProperty("position");
|
||||
rotation = this.serializedObject.FindProperty("rotation");
|
||||
scale = this.serializedObject.FindProperty("scale");
|
||||
overrideAlpha = this.serializedObject.FindProperty("overrideAlpha");
|
||||
hierarchy = this.serializedObject.FindProperty("hierarchy");
|
||||
hierarchyLabel = new GUIContent("Skeleton Utility Parent");
|
||||
parentReference = this.serializedObject.FindProperty("parentReference");
|
||||
|
||||
utilityBone = (SkeletonUtilityBone)target;
|
||||
skeletonUtility = utilityBone.hierarchy;
|
||||
EvaluateFlags();
|
||||
|
||||
if (!utilityBone.valid && skeletonUtility != null) {
|
||||
if (skeletonUtility.skeletonRenderer != null)
|
||||
skeletonUtility.skeletonRenderer.Initialize(false);
|
||||
if (skeletonUtility.skeletonGraphic != null)
|
||||
skeletonUtility.skeletonGraphic.Initialize(false);
|
||||
}
|
||||
|
||||
canCreateHingeChain = CanCreateHingeChain();
|
||||
boundingBoxTable.Clear();
|
||||
|
||||
if (multiObject) return;
|
||||
if (utilityBone.bone == null) return;
|
||||
|
||||
Skeleton skeleton = utilityBone.bone.Skeleton;
|
||||
int slotCount = skeleton.Slots.Count;
|
||||
Skin skin = skeleton.Skin;
|
||||
if (skeleton.Skin == null)
|
||||
skin = skeleton.Data.DefaultSkin;
|
||||
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
Slot slot = skeletonUtility.Skeleton.Slots.Items[i];
|
||||
if (slot.Bone == utilityBone.bone) {
|
||||
List<Skin.SkinEntry> slotAttachments = new List<Skin.SkinEntry>();
|
||||
int slotIndex = skeleton.Data.FindSlot(slot.Data.Name).Index;
|
||||
skin.GetAttachments(slotIndex, slotAttachments);
|
||||
|
||||
List<BoundingBoxAttachment> boundingBoxes = new List<BoundingBoxAttachment>();
|
||||
foreach (Skin.SkinEntry entry in slotAttachments) {
|
||||
BoundingBoxAttachment boundingBoxAttachment = entry.Attachment as BoundingBoxAttachment;
|
||||
if (boundingBoxAttachment != null)
|
||||
boundingBoxes.Add(boundingBoxAttachment);
|
||||
}
|
||||
|
||||
if (boundingBoxes.Count > 0)
|
||||
boundingBoxTable.Add(slot, boundingBoxes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EvaluateFlags () {
|
||||
if (Selection.objects.Length == 1) {
|
||||
containsFollows = utilityBone.mode == SkeletonUtilityBone.Mode.Follow;
|
||||
containsOverrides = utilityBone.mode == SkeletonUtilityBone.Mode.Override;
|
||||
} else {
|
||||
int boneCount = 0;
|
||||
foreach (Object o in Selection.objects) {
|
||||
GameObject go = o as GameObject;
|
||||
if (go != null) {
|
||||
SkeletonUtilityBone sub = go.GetComponent<SkeletonUtilityBone>();
|
||||
if (sub != null) {
|
||||
boneCount++;
|
||||
containsFollows |= (sub.mode == SkeletonUtilityBone.Mode.Follow);
|
||||
containsOverrides |= (sub.mode == SkeletonUtilityBone.Mode.Override);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
multiObject |= (boneCount > 1);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(mode);
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
containsOverrides = mode.enumValueIndex == 1;
|
||||
containsFollows = mode.enumValueIndex == 0;
|
||||
}
|
||||
|
||||
using (new EditorGUI.DisabledGroupScope(multiObject)) {
|
||||
string str = boneName.stringValue;
|
||||
if (str == "")
|
||||
str = "<None>";
|
||||
if (multiObject)
|
||||
str = "<Multiple>";
|
||||
|
||||
using (new GUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.PrefixLabel("Bone");
|
||||
if (GUILayout.Button(str, EditorStyles.popup)) {
|
||||
BoneSelectorContextMenu(str, ((SkeletonUtilityBone)target).hierarchy.Skeleton.Bones, "<None>", TargetBoneSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isOverrideMode = mode.enumValueIndex == 1;
|
||||
using (new EditorGUI.DisabledGroupScope(isOverrideMode))
|
||||
EditorGUILayout.PropertyField(zPosition);
|
||||
EditorGUILayout.PropertyField(position, new GUIContent("XY Position"));
|
||||
EditorGUILayout.PropertyField(rotation);
|
||||
EditorGUILayout.PropertyField(scale);
|
||||
|
||||
using (new EditorGUI.DisabledGroupScope(containsFollows)) {
|
||||
EditorGUILayout.PropertyField(overrideAlpha);
|
||||
EditorGUILayout.PropertyField(parentReference);
|
||||
EditorGUILayout.PropertyField(hierarchy, hierarchyLabel);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
using (new GUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.Space();
|
||||
using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || utilityBone.bone == null || utilityBone.bone.Children.Count == 0)) {
|
||||
if (GUILayout.Button(SpineInspectorUtility.TempContent("Add Child Bone", Icons.bone), GUILayout.MinWidth(120), GUILayout.Height(24)))
|
||||
BoneSelectorContextMenu("", utilityBone.bone.Children, "<Recursively>", SpawnChildBoneSelected);
|
||||
}
|
||||
using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || utilityBone.bone == null || containsOverrides)) {
|
||||
if (GUILayout.Button(SpineInspectorUtility.TempContent("Add Override", Icons.poseBones), GUILayout.MinWidth(120), GUILayout.Height(24)))
|
||||
SpawnOverride();
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
using (new GUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.Space();
|
||||
using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || !canCreateHingeChain)) {
|
||||
if (GUILayout.Button(SpineInspectorUtility.TempContent("Create 3D Hinge Chain", Icons.hingeChain), GUILayout.MinWidth(120), GUILayout.Height(24)))
|
||||
CreateHingeChain();
|
||||
if (GUILayout.Button(SpineInspectorUtility.TempContent("Create 2D Hinge Chain", Icons.hingeChain), GUILayout.MinWidth(120), GUILayout.Height(24)))
|
||||
CreateHingeChain2D();
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
using (new EditorGUI.DisabledGroupScope(multiObject || boundingBoxTable.Count == 0)) {
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Bounding Boxes", Icons.boundingBox), EditorStyles.boldLabel);
|
||||
|
||||
foreach (KeyValuePair<Slot, List<BoundingBoxAttachment>> entry in boundingBoxTable) {
|
||||
Slot slot = entry.Key;
|
||||
List<BoundingBoxAttachment> boundingBoxes = entry.Value;
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.LabelField(slot.Data.Name);
|
||||
EditorGUI.indentLevel++;
|
||||
{
|
||||
foreach (BoundingBoxAttachment box in boundingBoxes) {
|
||||
using (new GUILayout.HorizontalScope()) {
|
||||
GUILayout.Space(30);
|
||||
string buttonLabel = box.IsWeighted() ? box.Name + " (!)" : box.Name;
|
||||
if (GUILayout.Button(buttonLabel, GUILayout.Width(200))) {
|
||||
utilityBone.bone.Skeleton.UpdateWorldTransform(Skeleton.Physics.Update);
|
||||
Transform bbTransform = utilityBone.transform.Find("[BoundingBox]" + box.Name); // Use FindChild in older versions of Unity.
|
||||
if (bbTransform != null) {
|
||||
PolygonCollider2D originalCollider = bbTransform.GetComponent<PolygonCollider2D>();
|
||||
if (originalCollider != null)
|
||||
SkeletonUtility.SetColliderPointsLocal(originalCollider, slot, box);
|
||||
else
|
||||
SkeletonUtility.AddBoundingBoxAsComponent(box, slot, bbTransform.gameObject);
|
||||
} else {
|
||||
PolygonCollider2D newPolygonCollider = SkeletonUtility.AddBoundingBoxGameObject(null, box, slot, utilityBone.transform);
|
||||
bbTransform = newPolygonCollider.transform;
|
||||
}
|
||||
EditorGUIUtility.PingObject(bbTransform);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
BoneFollowerInspector.RecommendRigidbodyButton(utilityBone);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
static void BoneSelectorContextMenu (string current, ExposedList<Bone> bones, string topValue, GenericMenu.MenuFunction2 callback) {
|
||||
GenericMenu menu = new GenericMenu();
|
||||
|
||||
if (topValue != "")
|
||||
menu.AddItem(new GUIContent(topValue), current == topValue, callback, null);
|
||||
|
||||
for (int i = 0; i < bones.Count; i++)
|
||||
menu.AddItem(new GUIContent(bones.Items[i].Data.Name), bones.Items[i].Data.Name == current, callback, bones.Items[i]);
|
||||
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
void TargetBoneSelected (object obj) {
|
||||
if (obj == null) {
|
||||
boneName.stringValue = "";
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
} else {
|
||||
Bone bone = (Bone)obj;
|
||||
boneName.stringValue = bone.Data.Name;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
utilityBone.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnChildBoneSelected (object obj) {
|
||||
if (obj == null) {
|
||||
// Add recursively
|
||||
foreach (Bone bone in utilityBone.bone.Children) {
|
||||
GameObject go = skeletonUtility.SpawnBoneRecursively(bone, utilityBone.transform, utilityBone.mode, utilityBone.position, utilityBone.rotation, utilityBone.scale);
|
||||
SkeletonUtilityBone[] newUtilityBones = go.GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
foreach (SkeletonUtilityBone utilBone in newUtilityBones)
|
||||
SkeletonUtilityInspector.AttachIcon(utilBone);
|
||||
}
|
||||
} else {
|
||||
Bone bone = (Bone)obj;
|
||||
GameObject go = skeletonUtility.SpawnBone(bone, utilityBone.transform, utilityBone.mode, utilityBone.position, utilityBone.rotation, utilityBone.scale);
|
||||
SkeletonUtilityInspector.AttachIcon(go.GetComponent<SkeletonUtilityBone>());
|
||||
Selection.activeGameObject = go;
|
||||
EditorGUIUtility.PingObject(go);
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnOverride () {
|
||||
GameObject go = skeletonUtility.SpawnBone(utilityBone.bone, utilityBone.transform.parent, SkeletonUtilityBone.Mode.Override, utilityBone.position, utilityBone.rotation, utilityBone.scale);
|
||||
go.name = go.name + " [Override]";
|
||||
SkeletonUtilityInspector.AttachIcon(go.GetComponent<SkeletonUtilityBone>());
|
||||
Selection.activeGameObject = go;
|
||||
EditorGUIUtility.PingObject(go);
|
||||
}
|
||||
|
||||
bool CanCreateHingeChain () {
|
||||
if (utilityBone == null)
|
||||
return false;
|
||||
if (utilityBone.GetComponent<Rigidbody>() != null || utilityBone.GetComponent<Rigidbody2D>() != null)
|
||||
return false;
|
||||
if (utilityBone.bone != null && utilityBone.bone.Children.Count == 0)
|
||||
return false;
|
||||
|
||||
Rigidbody[] rigidbodies = utilityBone.GetComponentsInChildren<Rigidbody>();
|
||||
Rigidbody2D[] rigidbodies2D = utilityBone.GetComponentsInChildren<Rigidbody2D>();
|
||||
return rigidbodies.Length <= 0 && rigidbodies2D.Length <= 0;
|
||||
}
|
||||
|
||||
void CreateHingeChain2D () {
|
||||
SkeletonUtilityBone kinematicParentUtilityBone = utilityBone.transform.parent.GetComponent<SkeletonUtilityBone>();
|
||||
if (kinematicParentUtilityBone == null) {
|
||||
UnityEditor.EditorUtility.DisplayDialog("No parent SkeletonUtilityBone found!", "Please select the first physically moving chain node, having a parent GameObject with a SkeletonUtilityBone component attached.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
float mass = 10;
|
||||
const float rotationLimit = 20.0f;
|
||||
|
||||
SetSkeletonUtilityToFlipByRotation();
|
||||
|
||||
kinematicParentUtilityBone.mode = SkeletonUtilityBone.Mode.Follow;
|
||||
kinematicParentUtilityBone.position = kinematicParentUtilityBone.rotation = kinematicParentUtilityBone.scale = kinematicParentUtilityBone.zPosition = true;
|
||||
|
||||
GameObject commonParentObject = new GameObject(skeletonUtility.name + " HingeChain Parent " + utilityBone.name);
|
||||
ActivateBasedOnFlipDirection commonParentActivateOnFlip = commonParentObject.AddComponent<ActivateBasedOnFlipDirection>();
|
||||
commonParentActivateOnFlip.skeletonRenderer = skeletonUtility.skeletonRenderer;
|
||||
commonParentActivateOnFlip.skeletonGraphic = skeletonUtility.skeletonGraphic;
|
||||
|
||||
// HingeChain Parent
|
||||
// Needs to be on top hierarchy level (not attached to the moving skeleton at least) for physics to apply proper momentum.
|
||||
GameObject normalChainParentObject = new GameObject("HingeChain");
|
||||
normalChainParentObject.transform.SetParent(commonParentObject.transform);
|
||||
commonParentActivateOnFlip.activeOnNormalX = normalChainParentObject;
|
||||
|
||||
//FollowSkeletonUtilityRootRotation followRotationComponent = normalChainParentObject.AddComponent<FollowSkeletonUtilityRootRotation>();
|
||||
//followRotationComponent.reference = skeletonUtility.boneRoot;
|
||||
|
||||
// Follower Kinematic Rigidbody
|
||||
GameObject followerKinematicObject = new GameObject(kinematicParentUtilityBone.name + " Follower");
|
||||
followerKinematicObject.transform.parent = normalChainParentObject.transform;
|
||||
Rigidbody2D followerRigidbody = followerKinematicObject.AddComponent<Rigidbody2D>();
|
||||
followerRigidbody.mass = mass;
|
||||
followerRigidbody.isKinematic = true;
|
||||
followerKinematicObject.AddComponent<FollowLocationRigidbody2D>().reference = kinematicParentUtilityBone.transform;
|
||||
followerKinematicObject.transform.position = kinematicParentUtilityBone.transform.position;
|
||||
followerKinematicObject.transform.rotation = kinematicParentUtilityBone.transform.rotation;
|
||||
|
||||
// Child Bones
|
||||
SkeletonUtilityBone[] utilityBones = utilityBone.GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
Transform childBoneParentReference = followerKinematicObject.transform;
|
||||
for (int i = 0; i < utilityBones.Length; ++i) {
|
||||
SkeletonUtilityBone childBone = utilityBones[i];
|
||||
mass *= 0.75f;
|
||||
childBone.parentReference = (i == 0) ? kinematicParentUtilityBone.transform : childBoneParentReference;
|
||||
childBone.transform.SetParent(normalChainParentObject.transform, true); // we need a flat hierarchy of all Joint objects in Unity.
|
||||
AttachRigidbodyAndCollider2D(childBone);
|
||||
childBone.mode = SkeletonUtilityBone.Mode.Override;
|
||||
childBone.scale = childBone.position = childBone.zPosition = false;
|
||||
|
||||
HingeJoint2D joint = childBone.gameObject.AddComponent<HingeJoint2D>();
|
||||
joint.connectedBody = childBoneParentReference.GetComponent<Rigidbody2D>();
|
||||
joint.useLimits = true;
|
||||
ApplyJoint2DAngleLimits(joint, rotationLimit, childBoneParentReference, childBone.transform);
|
||||
|
||||
childBone.GetComponent<Rigidbody2D>().mass = mass;
|
||||
childBoneParentReference = childBone.transform;
|
||||
}
|
||||
|
||||
Duplicate2DHierarchyForFlippedChains(normalChainParentObject, commonParentActivateOnFlip, skeletonUtility.transform, rotationLimit);
|
||||
UnityEditor.Selection.activeGameObject = commonParentObject;
|
||||
}
|
||||
|
||||
void ApplyJoint2DAngleLimits (HingeJoint2D joint, float rotationLimit, Transform parentBone, Transform bone) {
|
||||
#if HINGE_JOINT_NEW_BEHAVIOUR
|
||||
float referenceAngle = (parentBone.eulerAngles.z - bone.eulerAngles.z + 360f) % 360f;
|
||||
float minAngle = referenceAngle - rotationLimit;
|
||||
float maxAngle = referenceAngle + rotationLimit;
|
||||
if (maxAngle > 270f) {
|
||||
minAngle -= 360f;
|
||||
maxAngle -= 360f;
|
||||
}
|
||||
if (minAngle < -90f) {
|
||||
minAngle += 360f;
|
||||
maxAngle += 360f;
|
||||
}
|
||||
#else
|
||||
float minAngle = -rotationLimit;
|
||||
float maxAngle = rotationLimit;
|
||||
#endif
|
||||
joint.limits = new JointAngleLimits2D {
|
||||
min = minAngle,
|
||||
max = maxAngle
|
||||
};
|
||||
}
|
||||
|
||||
void Duplicate2DHierarchyForFlippedChains (GameObject normalChainParentObject, ActivateBasedOnFlipDirection commonParentActivateOnFlip,
|
||||
Transform skeletonUtilityRoot, float rotationLimit) {
|
||||
|
||||
GameObject mirroredChain = GameObject.Instantiate(normalChainParentObject, normalChainParentObject.transform.position,
|
||||
normalChainParentObject.transform.rotation, commonParentActivateOnFlip.transform);
|
||||
mirroredChain.name = normalChainParentObject.name + " FlippedX";
|
||||
|
||||
commonParentActivateOnFlip.activeOnFlippedX = mirroredChain;
|
||||
|
||||
FollowLocationRigidbody2D followerKinematicObject = mirroredChain.GetComponentInChildren<FollowLocationRigidbody2D>();
|
||||
followerKinematicObject.followFlippedX = true;
|
||||
FlipBone2DHorizontal(followerKinematicObject.transform, skeletonUtilityRoot);
|
||||
|
||||
HingeJoint2D[] childBoneJoints = mirroredChain.GetComponentsInChildren<HingeJoint2D>();
|
||||
Transform prevRotatedChild = null;
|
||||
Transform parentTransformForAngles = followerKinematicObject.transform;
|
||||
for (int i = 0; i < childBoneJoints.Length; ++i) {
|
||||
HingeJoint2D joint = childBoneJoints[i];
|
||||
FlipBone2DHorizontal(joint.transform, skeletonUtilityRoot);
|
||||
ApplyJoint2DAngleLimits(joint, rotationLimit, parentTransformForAngles, joint.transform);
|
||||
|
||||
GameObject rotatedChild = GameObject.Instantiate(joint.gameObject, joint.transform, true);
|
||||
rotatedChild.name = joint.name + " rotated";
|
||||
Vector3 rotationEulerAngles = rotatedChild.transform.localEulerAngles;
|
||||
rotationEulerAngles.x = 180;
|
||||
rotatedChild.transform.localEulerAngles = rotationEulerAngles;
|
||||
DestroyImmediate(rotatedChild.GetComponent<HingeJoint2D>());
|
||||
DestroyImmediate(rotatedChild.GetComponent<BoxCollider2D>());
|
||||
DestroyImmediate(rotatedChild.GetComponent<Rigidbody2D>());
|
||||
|
||||
DestroyImmediate(joint.gameObject.GetComponent<SkeletonUtilityBone>());
|
||||
|
||||
if (i > 0) {
|
||||
SkeletonUtilityBone utilityBone = rotatedChild.GetComponent<SkeletonUtilityBone>();
|
||||
utilityBone.parentReference = prevRotatedChild;
|
||||
}
|
||||
prevRotatedChild = rotatedChild.transform;
|
||||
parentTransformForAngles = joint.transform;
|
||||
}
|
||||
|
||||
mirroredChain.SetActive(false);
|
||||
}
|
||||
|
||||
void FlipBone2DHorizontal (Transform bone, Transform mirrorPosition) {
|
||||
Vector3 position = bone.position;
|
||||
position.x = 2 * mirrorPosition.position.x - position.x; // = mirrorPosition + (mirrorPosition - bone.position)
|
||||
bone.position = position;
|
||||
|
||||
Vector3 boneZ = bone.forward;
|
||||
Vector3 boneX = bone.right;
|
||||
boneX.x *= -1;
|
||||
|
||||
bone.rotation = Quaternion.LookRotation(boneZ, Vector3.Cross(boneZ, boneX));
|
||||
}
|
||||
|
||||
void CreateHingeChain () {
|
||||
SkeletonUtilityBone kinematicParentUtilityBone = utilityBone.transform.parent.GetComponent<SkeletonUtilityBone>();
|
||||
if (kinematicParentUtilityBone == null) {
|
||||
UnityEditor.EditorUtility.DisplayDialog("No parent SkeletonUtilityBone found!", "Please select the first physically moving chain node, having a parent GameObject with a SkeletonUtilityBone component attached.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
SetSkeletonUtilityToFlipByRotation();
|
||||
|
||||
kinematicParentUtilityBone.mode = SkeletonUtilityBone.Mode.Follow;
|
||||
kinematicParentUtilityBone.position = kinematicParentUtilityBone.rotation = kinematicParentUtilityBone.scale = kinematicParentUtilityBone.zPosition = true;
|
||||
|
||||
// HingeChain Parent
|
||||
// Needs to be on top hierarchy level (not attached to the moving skeleton at least) for physics to apply proper momentum.
|
||||
GameObject chainParentObject = new GameObject(skeletonUtility.name + " HingeChain Parent " + utilityBone.name);
|
||||
FollowSkeletonUtilityRootRotation followRotationComponent = chainParentObject.AddComponent<FollowSkeletonUtilityRootRotation>();
|
||||
followRotationComponent.reference = skeletonUtility.boneRoot;
|
||||
|
||||
// Follower Kinematic Rigidbody
|
||||
GameObject followerKinematicObject = new GameObject(kinematicParentUtilityBone.name + " Follower");
|
||||
followerKinematicObject.transform.parent = chainParentObject.transform;
|
||||
Rigidbody followerRigidbody = followerKinematicObject.AddComponent<Rigidbody>();
|
||||
followerRigidbody.mass = 10;
|
||||
followerRigidbody.isKinematic = true;
|
||||
followerKinematicObject.AddComponent<FollowLocationRigidbody>().reference = kinematicParentUtilityBone.transform;
|
||||
followerKinematicObject.transform.position = kinematicParentUtilityBone.transform.position;
|
||||
followerKinematicObject.transform.rotation = kinematicParentUtilityBone.transform.rotation;
|
||||
|
||||
// Child Bones
|
||||
SkeletonUtilityBone[] utilityBones = utilityBone.GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
Transform childBoneParentReference = followerKinematicObject.transform;
|
||||
foreach (SkeletonUtilityBone childBone in utilityBones) {
|
||||
childBone.parentReference = childBoneParentReference;
|
||||
childBone.transform.SetParent(chainParentObject.transform, true); // we need a flat hierarchy of all Joint objects in Unity.
|
||||
AttachRigidbodyAndCollider(childBone);
|
||||
childBone.mode = SkeletonUtilityBone.Mode.Override;
|
||||
|
||||
HingeJoint joint = childBone.gameObject.AddComponent<HingeJoint>();
|
||||
joint.axis = Vector3.forward;
|
||||
joint.connectedBody = childBoneParentReference.GetComponent<Rigidbody>();
|
||||
joint.useLimits = true;
|
||||
joint.limits = new JointLimits {
|
||||
min = -20,
|
||||
max = 20
|
||||
};
|
||||
childBone.GetComponent<Rigidbody>().mass = childBoneParentReference.transform.GetComponent<Rigidbody>().mass * 0.75f;
|
||||
|
||||
childBoneParentReference = childBone.transform;
|
||||
}
|
||||
UnityEditor.Selection.activeGameObject = chainParentObject;
|
||||
}
|
||||
|
||||
void SetSkeletonUtilityToFlipByRotation () {
|
||||
if (!skeletonUtility.flipBy180DegreeRotation) {
|
||||
skeletonUtility.flipBy180DegreeRotation = true;
|
||||
Debug.Log("Set SkeletonUtility " + skeletonUtility.name + " to flip by rotation instead of negative scale (required).", skeletonUtility);
|
||||
}
|
||||
}
|
||||
|
||||
static void AttachRigidbodyAndCollider (SkeletonUtilityBone utilBone, bool enableCollider = false) {
|
||||
if (utilBone.GetComponent<Collider>() == null) {
|
||||
if (utilBone.bone.Data.Length == 0) {
|
||||
SphereCollider sphere = utilBone.gameObject.AddComponent<SphereCollider>();
|
||||
sphere.radius = 0.1f;
|
||||
sphere.enabled = enableCollider;
|
||||
} else {
|
||||
float length = utilBone.bone.Data.Length;
|
||||
BoxCollider box = utilBone.gameObject.AddComponent<BoxCollider>();
|
||||
box.size = new Vector3(length, length / 3f, 0.2f);
|
||||
box.center = new Vector3(length / 2f, 0, 0);
|
||||
box.enabled = enableCollider;
|
||||
}
|
||||
}
|
||||
utilBone.gameObject.AddComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
static void AttachRigidbodyAndCollider2D (SkeletonUtilityBone utilBone, bool enableCollider = false) {
|
||||
if (utilBone.GetComponent<Collider2D>() == null) {
|
||||
if (utilBone.bone.Data.Length == 0) {
|
||||
CircleCollider2D sphere = utilBone.gameObject.AddComponent<CircleCollider2D>();
|
||||
sphere.radius = 0.1f;
|
||||
sphere.enabled = enableCollider;
|
||||
} else {
|
||||
float length = utilBone.bone.Data.Length;
|
||||
BoxCollider2D box = utilBone.gameObject.AddComponent<BoxCollider2D>();
|
||||
box.size = new Vector3(length, length / 3f, 0.2f);
|
||||
box.offset = new Vector3(length / 2f, 0, 0);
|
||||
box.enabled = enableCollider;
|
||||
}
|
||||
}
|
||||
utilBone.gameObject.AddComponent<Rigidbody2D>();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3ae20b4bcc31f645afd6f5b64f82473
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,195 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
#define PUBLIC_SET_ICON_FOR_OBJECT
|
||||
#endif
|
||||
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
using Icons = SpineEditorUtilities.Icons;
|
||||
|
||||
[CustomEditor(typeof(SkeletonUtility))]
|
||||
public class SkeletonUtilityInspector : UnityEditor.Editor {
|
||||
|
||||
SkeletonUtility skeletonUtility;
|
||||
Skeleton skeleton;
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
SkeletonGraphic skeletonGraphic;
|
||||
|
||||
#if !NEW_PREFAB_SYSTEM
|
||||
bool isPrefab;
|
||||
#endif
|
||||
|
||||
readonly GUIContent SpawnHierarchyButtonLabel = new GUIContent("Spawn Hierarchy", Icons.skeleton);
|
||||
|
||||
void OnEnable () {
|
||||
skeletonUtility = (SkeletonUtility)target;
|
||||
skeletonRenderer = skeletonUtility.skeletonRenderer;
|
||||
skeletonGraphic = skeletonUtility.skeletonGraphic;
|
||||
skeleton = skeletonUtility.Skeleton;
|
||||
|
||||
if (skeleton == null) {
|
||||
if (skeletonRenderer != null) {
|
||||
skeletonRenderer.Initialize(false);
|
||||
skeletonRenderer.LateUpdate();
|
||||
} else if (skeletonGraphic != null) {
|
||||
skeletonGraphic.Initialize(false);
|
||||
skeletonGraphic.LateUpdate();
|
||||
}
|
||||
skeleton = skeletonUtility.Skeleton;
|
||||
}
|
||||
|
||||
if ((skeletonRenderer != null && !skeletonRenderer.valid) ||
|
||||
(skeletonGraphic != null && !skeletonGraphic.IsValid)) return;
|
||||
|
||||
#if !NEW_PREFAB_SYSTEM
|
||||
isPrefab |= PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
|
||||
#if !NEW_PREFAB_SYSTEM
|
||||
if (isPrefab) {
|
||||
GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
if ((skeletonRenderer != null && !skeletonRenderer.valid) ||
|
||||
(skeletonGraphic != null && !skeletonGraphic.IsValid)) {
|
||||
GUILayout.Label(new GUIContent("Spine Component invalid. Check SkeletonData asset.", Icons.warning));
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("boneRoot"), SpineInspectorUtility.TempContent("Skeleton Root"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("flipBy180DegreeRotation"), SpineInspectorUtility.TempContent("Flip by Rotation", null,
|
||||
"If true, Skeleton.ScaleX and Skeleton.ScaleY are followed " +
|
||||
"by 180 degree rotation. If false, negative Transform scale is used. " +
|
||||
"Note that using negative scale is consistent with previous behaviour (hence the default), " +
|
||||
"however causes serious problems with rigidbodies and physics. Therefore, it is recommended to " +
|
||||
"enable this parameter where possible. When creating hinge chains for a chain of skeleton bones " +
|
||||
"via SkeletonUtilityBone, it is mandatory to have this parameter enabled."));
|
||||
|
||||
bool hasRootBone = skeletonUtility.boneRoot != null;
|
||||
|
||||
if (!hasRootBone)
|
||||
EditorGUILayout.HelpBox("No hierarchy found. Use Spawn Hierarchy to generate GameObjects for bones.", MessageType.Info);
|
||||
|
||||
using (new EditorGUI.DisabledGroupScope(hasRootBone)) {
|
||||
if (SpineInspectorUtility.LargeCenteredButton(SpawnHierarchyButtonLabel))
|
||||
SpawnHierarchyContextMenu();
|
||||
}
|
||||
|
||||
if (hasRootBone) {
|
||||
if (SpineInspectorUtility.CenteredButton(new GUIContent("Remove Hierarchy"))) {
|
||||
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Remove Hierarchy");
|
||||
Undo.DestroyObjectImmediate(skeletonUtility.boneRoot.gameObject);
|
||||
skeletonUtility.boneRoot = null;
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
void SpawnHierarchyContextMenu () {
|
||||
GenericMenu menu = new GenericMenu();
|
||||
|
||||
menu.AddItem(new GUIContent("Follow all bones"), false, SpawnFollowHierarchy);
|
||||
menu.AddItem(new GUIContent("Follow (Root Only)"), false, SpawnFollowHierarchyRootOnly);
|
||||
menu.AddSeparator("");
|
||||
menu.AddItem(new GUIContent("Override all bones"), false, SpawnOverrideHierarchy);
|
||||
menu.AddItem(new GUIContent("Override (Root Only)"), false, SpawnOverrideHierarchyRootOnly);
|
||||
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
public static void AttachIcon (SkeletonUtilityBone boneComponent) {
|
||||
Skeleton skeleton = boneComponent.hierarchy.Skeleton;
|
||||
Texture2D icon = boneComponent.bone.Data.Length == 0 ? Icons.nullBone : Icons.boneNib;
|
||||
|
||||
foreach (IkConstraint c in skeleton.IkConstraints)
|
||||
if (c.Target == boneComponent.bone) {
|
||||
icon = Icons.constraintNib;
|
||||
break;
|
||||
}
|
||||
#if PUBLIC_SET_ICON_FOR_OBJECT
|
||||
EditorGUIUtility.SetIconForObject(boneComponent.gameObject, icon);
|
||||
#else
|
||||
typeof(EditorGUIUtility).InvokeMember("SetIconForObject", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, null, new object[2] {
|
||||
boneComponent.gameObject,
|
||||
icon
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
static void AttachIconsToChildren (Transform root) {
|
||||
if (root != null) {
|
||||
SkeletonUtilityBone[] utilityBones = root.GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
foreach (SkeletonUtilityBone utilBone in utilityBones)
|
||||
AttachIcon(utilBone);
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnFollowHierarchy () {
|
||||
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Hierarchy");
|
||||
Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Follow, true, true, true);
|
||||
AttachIconsToChildren(skeletonUtility.boneRoot);
|
||||
}
|
||||
|
||||
void SpawnFollowHierarchyRootOnly () {
|
||||
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Root");
|
||||
Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Follow, true, true, true);
|
||||
AttachIconsToChildren(skeletonUtility.boneRoot);
|
||||
}
|
||||
|
||||
void SpawnOverrideHierarchy () {
|
||||
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Hierarchy");
|
||||
Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Override, true, true, true);
|
||||
AttachIconsToChildren(skeletonUtility.boneRoot);
|
||||
}
|
||||
|
||||
void SpawnOverrideHierarchyRootOnly () {
|
||||
Undo.RegisterCompleteObjectUndo(skeletonUtility, "Spawn Root");
|
||||
Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Override, true, true, true);
|
||||
AttachIconsToChildren(skeletonUtility.boneRoot);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5b90df955eb8c2429ac67c8b2de6c5c
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,5 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfaea6b7e7f52bc46b8d1c3cb5e9eaa1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
Before Width: | Height: | Size: 529 B |
@ -1,92 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3fc714a0dc1cf6b4b959e073fff2844e
|
||||
timeCreated: 1508165143
|
||||
licenseType: Free
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 1024
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 1024
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 1024
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 1024
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 507 B |
@ -1,46 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68defdbc95b30a74a9ad396bfc9a2277
|
||||
TextureImporter:
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
Before Width: | Height: | Size: 581 B |
@ -1,53 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52b12ec801461494185a4d3dc66f3d1d
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 552 B |
@ -1,53 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d1be4ea889f3a14b864352fe49a1bde
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 289 B |
@ -1,92 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04ae56b3698d3e844844cfcef2f009e7
|
||||
timeCreated: 1494928093
|
||||
licenseType: Free
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 386 B |
@ -1,53 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8322793223a533a4ca8be6f430256dfc
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 411 B |
@ -1,53 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97a43f11e00735147a9dc3dff6d68191
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 225 B |
@ -1,47 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 955aed20030d0504b8a9c6934a5cb47a
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
Before Width: | Height: | Size: 482 B |
@ -1,92 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5fff1b5caee03642ab77c9984b4bb6a
|
||||
timeCreated: 1497479335
|
||||
licenseType: Free
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 540 B |
@ -1,92 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02822eb69e09dd947b434ab81e3d938f
|
||||
timeCreated: 1494878353
|
||||
licenseType: Free
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 752 B |
@ -1,53 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de1a4f5ad4bdf1a4ea072c4d59ba87d8
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 502 B |
@ -1,92 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1aae98dd56b14c4b8c25360000b7e9e
|
||||
timeCreated: 1494878353
|
||||
licenseType: Free
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 3.5 KiB |
@ -1,124 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10e534174824cb04e8a7ec21825f2827
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 471 B |
@ -1,92 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4709175437c21f64bab9b061f98a49fc
|
||||
timeCreated: 1494878353
|
||||
licenseType: Free
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 587 B |
@ -1,92 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed0736a1eb519ef42b4892d1db2426b3
|
||||
timeCreated: 1494878353
|
||||
licenseType: Free
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 359 B |
@ -1,53 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d226a80acc775714aa78b85e16a00e9b
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 596 B |
@ -1,47 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c2c6d283dcf3654baf40001c982891c
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
Before Width: | Height: | Size: 387 B |
@ -1,53 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b3a6f35bbaa8414eb51a344743ee641
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -3
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Before Width: | Height: | Size: 397 B |
@ -1,53 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a309a2e14638a204091b915126910f45
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|