mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
RenderSeparator update.
This commit is contained in:
parent
9254e18801
commit
46ee116ee3
@ -119,7 +119,7 @@ namespace Spine.Unity.MeshGeneration {
|
||||
startSlot = submeshStartSlotIndex,
|
||||
endSlot = i,
|
||||
firstVertexIndex = submeshFirstVertex,
|
||||
separatedBySlot = separatedBySlot
|
||||
forceSeparate = separatedBySlot
|
||||
}
|
||||
);
|
||||
|
||||
@ -147,7 +147,7 @@ namespace Spine.Unity.MeshGeneration {
|
||||
startSlot = submeshStartSlotIndex,
|
||||
endSlot = drawOrderCount,
|
||||
firstVertexIndex = submeshFirstVertex,
|
||||
separatedBySlot = false
|
||||
forceSeparate = false
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ namespace Spine.Unity.MeshGeneration {
|
||||
|
||||
// Vertex index offset. Used by submesh generation if part of a bigger mesh.
|
||||
public int firstVertexIndex;
|
||||
public bool separatedBySlot;
|
||||
public bool forceSeparate;
|
||||
|
||||
/// <summary>The number of slots in this SubmeshInstruction's range. Not necessarily the number of attachments.</summary>
|
||||
public int SlotCount { get { return endSlot - startSlot; } }
|
||||
|
||||
@ -36,10 +36,10 @@ using UnityEngine;
|
||||
using UnityEditor;
|
||||
using Spine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
[CustomEditor(typeof(SkeletonGraphic))]
|
||||
public class SkeletonGraphicInspector : Editor {
|
||||
public class SkeletonGraphicInspector : UnityEditor.Editor {
|
||||
SerializedProperty material_, color_;
|
||||
SerializedProperty skeletonDataAsset_, initialSkinName_;
|
||||
SerializedProperty startingAnimation_, startingLoop_, timeScale_, freeze_;
|
||||
@ -133,7 +133,7 @@ namespace Spine.Unity {
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Spine/SkeletonGraphic (UnityUI)", false, 10)]
|
||||
[MenuItem("GameObject/Spine/SkeletonGraphic (UnityUI)", false, 15)]
|
||||
static public void SkeletonGraphicCreateMenuItem () {
|
||||
var parentGameObject = Selection.activeObject as GameObject;
|
||||
var parentTransform = parentGameObject == null ? null : parentGameObject.GetComponent<RectTransform>();
|
||||
@ -149,7 +149,7 @@ namespace Spine.Unity {
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Spine/Instantiate (UnityUI)", false, 10)]
|
||||
[MenuItem("Assets/Spine/Instantiate (UnityUI)", false, 20)]
|
||||
static void InstantiateSkeletonGraphic () {
|
||||
Object[] arr = Selection.objects;
|
||||
foreach (Object o in arr) {
|
||||
@ -161,7 +161,7 @@ namespace Spine.Unity {
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Spine/Instantiate (UnityUI)", true, 10)]
|
||||
[MenuItem("Assets/Spine/Instantiate (UnityUI)", true, 20)]
|
||||
static bool ValidateInstantiateSkeletonGraphic () {
|
||||
Object[] arr = Selection.objects;
|
||||
|
||||
|
||||
@ -3,13 +3,13 @@ using System.Collections;
|
||||
using UnityEditor;
|
||||
using Spine.Unity;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
[CustomEditor(typeof(SkeletonPartsRenderer))]
|
||||
public class SkeletonRenderPartInspector : Editor {
|
||||
public class SkeletonRenderPartInspector : UnityEditor.Editor {
|
||||
SpineInspectorUtility.SerializedSortingProperties sortingProperties;
|
||||
|
||||
void OnEnable () {
|
||||
var component = target as Component;
|
||||
sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(component.GetComponent<MeshRenderer>());
|
||||
sortingProperties = new SpineInspectorUtility.SerializedSortingProperties((target as Component).GetComponent<MeshRenderer>());
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
@ -17,3 +17,5 @@ public class SkeletonRenderPartInspector : Editor {
|
||||
SpineInspectorUtility.SortingPropertyFields(sortingProperties, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,20 +1,22 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Spine.Unity {
|
||||
using Spine.Unity;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
[CustomEditor(typeof(SkeletonRenderSeparator))]
|
||||
public class SkeletonRenderSeparatorInspector : Editor {
|
||||
public class SkeletonRenderSeparatorInspector : UnityEditor.Editor {
|
||||
SkeletonRenderSeparator component;
|
||||
|
||||
// Properties
|
||||
SerializedProperty skeletonRenderer_, copyPropertyBlock_, copyMeshRendererFlags_, partsRenderers_;
|
||||
static bool partsRenderersExpanded = false;
|
||||
|
||||
// For separator field.
|
||||
SerializedObject skeletonRendererSerializedObject;
|
||||
SerializedProperty separatorNamesProp;
|
||||
bool separatorExpanded = true;
|
||||
System.Func<int, string, string, string> Plural = SpineInspectorUtility.Pluralize;
|
||||
static bool skeletonRendererExpanded = true;
|
||||
|
||||
void OnEnable () {
|
||||
if (component == null)
|
||||
@ -23,14 +25,28 @@ namespace Spine.Unity {
|
||||
skeletonRenderer_ = serializedObject.FindProperty("skeletonRenderer");
|
||||
copyPropertyBlock_ = serializedObject.FindProperty("copyPropertyBlock");
|
||||
copyMeshRendererFlags_ = serializedObject.FindProperty("copyMeshRendererFlags");
|
||||
|
||||
var partsRenderers = component.partsRenderers;
|
||||
partsRenderers_ = serializedObject.FindProperty("partsRenderers");
|
||||
partsRenderers_.isExpanded = true;
|
||||
partsRenderers_.isExpanded = partsRenderersExpanded || // last state
|
||||
partsRenderers.Contains(null) || // null items found
|
||||
partsRenderers.Count < 1 || // no parts renderers
|
||||
(skeletonRenderer_.objectReferenceValue != null && SkeletonRendererSeparatorCount + 1 > partsRenderers.Count); // not enough parts renderers
|
||||
}
|
||||
|
||||
int SkeletonRendererSeparatorCount {
|
||||
get {
|
||||
if (Application.isPlaying) {
|
||||
return component.SkeletonRenderer.separatorSlots.Count;
|
||||
} else {
|
||||
return separatorNamesProp == null ? 0 : separatorNamesProp.arraySize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
// TODO: Add Undo support
|
||||
var componentRenderers = component.partsRenderers;
|
||||
int separatorCount = 0;
|
||||
int totalParts;
|
||||
|
||||
bool componentEnabled = component.enabled;
|
||||
@ -42,6 +58,7 @@ namespace Spine.Unity {
|
||||
EditorGUILayout.PropertyField(copyPropertyBlock_);
|
||||
EditorGUILayout.PropertyField(copyMeshRendererFlags_);
|
||||
|
||||
// SkeletonRenderer Box
|
||||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
|
||||
// Fancy SkeletonRenderer foldout reference field
|
||||
{
|
||||
@ -52,14 +69,15 @@ namespace Spine.Unity {
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
if (component.SkeletonRenderer != null) {
|
||||
separatorExpanded = EditorGUI.Foldout(foldoutSkeletonRendererRect, separatorExpanded, "");
|
||||
skeletonRendererExpanded = EditorGUI.Foldout(foldoutSkeletonRendererRect, skeletonRendererExpanded, "");
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
int separatorCount = 0;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (component.SkeletonRenderer != null) {
|
||||
// SubmeshSeparators from SkeletonRenderer
|
||||
// Separators from SkeletonRenderer
|
||||
{
|
||||
bool skeletonRendererMismatch = skeletonRendererSerializedObject != null && skeletonRendererSerializedObject.targetObject != component.SkeletonRenderer;
|
||||
if (separatorNamesProp == null || skeletonRendererMismatch) {
|
||||
@ -71,21 +89,16 @@ namespace Spine.Unity {
|
||||
}
|
||||
|
||||
if (separatorNamesProp != null) {
|
||||
if (separatorExpanded) {
|
||||
if (skeletonRendererExpanded) {
|
||||
EditorGUI.indentLevel++;
|
||||
SkeletonRendererInspector.SeparatorsField(separatorNamesProp);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
if (Application.isPlaying)
|
||||
separatorCount = component.SkeletonRenderer.separatorSlots.Count;
|
||||
else
|
||||
separatorCount = separatorNamesProp.arraySize;
|
||||
|
||||
separatorCount = this.SkeletonRendererSeparatorCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (separatorCount == 0) {
|
||||
if (SkeletonRendererSeparatorCount == 0) {
|
||||
EditorGUILayout.HelpBox("Separators are empty. Change the size to 1 and choose a slot if you want the render to be separated.", MessageType.Info);
|
||||
}
|
||||
}
|
||||
@ -93,8 +106,8 @@ namespace Spine.Unity {
|
||||
skeletonRendererSerializedObject.ApplyModifiedProperties();
|
||||
|
||||
totalParts = separatorCount + 1;
|
||||
var counterStyle = separatorExpanded ? EditorStyles.label : EditorStyles.miniLabel;
|
||||
EditorGUILayout.LabelField(string.Format("{0}: separates into {1}.", Plural(separatorCount, "separator", "separators"), Plural(totalParts, "part", "parts") ), counterStyle);
|
||||
var counterStyle = skeletonRendererExpanded ? EditorStyles.label : EditorStyles.miniLabel;
|
||||
EditorGUILayout.LabelField(string.Format("{0}: separates into {1}.", SpineInspectorUtility.Pluralize(separatorCount, "separator", "separators"), SpineInspectorUtility.Pluralize(totalParts, "part", "parts") ), counterStyle);
|
||||
}
|
||||
|
||||
// Parts renderers
|
||||
@ -103,6 +116,11 @@ namespace Spine.Unity {
|
||||
EditorGUILayout.PropertyField(this.partsRenderers_, true);
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
// Null items warning
|
||||
bool nullItemsFound = componentRenderers.Contains(null);
|
||||
if (nullItemsFound)
|
||||
EditorGUILayout.HelpBox("Some items in the parts renderers list are null and may cause problems.\n\nYou can right-click on that element and choose 'Delete Array Element' to remove it.", MessageType.Warning);
|
||||
|
||||
// (Button) Match Separators count
|
||||
if (separatorNamesProp != null) {
|
||||
int currentRenderers = 0;
|
||||
@ -110,12 +128,10 @@ namespace Spine.Unity {
|
||||
if (r != null)
|
||||
currentRenderers++;
|
||||
}
|
||||
|
||||
int extraRenderersNeeded = totalParts - currentRenderers;
|
||||
if (component.enabled && component.SkeletonRenderer != null && extraRenderersNeeded > 0) {
|
||||
EditorGUILayout.HelpBox(string.Format("Insufficient parts renderers. Some parts will not be rendered."), MessageType.Warning);
|
||||
string addMissingLabel = string.Format("Add the missing renderer{1} ({0}) ", extraRenderersNeeded, SpineInspectorUtility.PluralThenS(extraRenderersNeeded));
|
||||
//var addMissingContentButtonContent = new GUIContent("Add", GUIUtility.)
|
||||
if (GUILayout.Button(addMissingLabel, GUILayout.Height(40f))) {
|
||||
AddPartsRenderer(extraRenderersNeeded);
|
||||
DetectOrphanedPartsRenderers(component);
|
||||
@ -123,6 +139,8 @@ namespace Spine.Unity {
|
||||
}
|
||||
}
|
||||
|
||||
if (partsRenderers_.isExpanded != partsRenderersExpanded) partsRenderersExpanded = partsRenderers_.isExpanded;
|
||||
if (partsRenderers_.isExpanded) {
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
// (Button) Destroy Renderers button
|
||||
if (componentRenderers.Count > 0) {
|
||||
@ -141,17 +159,18 @@ namespace Spine.Unity {
|
||||
}
|
||||
|
||||
// (Button) Add Part Renderer button
|
||||
if (GUILayout.Button("Add (1) Parts Renderer"))
|
||||
if (GUILayout.Button("Add Parts Renderer"))
|
||||
AddPartsRenderer(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
public void AddPartsRenderer (int count) {
|
||||
var componentRenderers = component.partsRenderers;
|
||||
bool emptyFound = componentRenderers.Exists(x => x == null);
|
||||
bool emptyFound = componentRenderers.Contains(null);
|
||||
if (emptyFound) {
|
||||
bool userClearEntries = EditorUtility.DisplayDialog("Empty entries found", "Null entries found. Do you want to remove null entries before adding the new renderer? ", "Clear Empty Entries", "Don't Clear");
|
||||
if (userClearEntries) componentRenderers.RemoveAll(x => x == null);
|
||||
@ -164,21 +183,18 @@ namespace Spine.Unity {
|
||||
EditorGUIUtility.PingObject(smr);
|
||||
|
||||
// increment renderer sorting order.
|
||||
if (index != 0) {
|
||||
var prev = componentRenderers[index - 1];
|
||||
if (prev != null) {
|
||||
if (index == 0) continue;
|
||||
var prev = componentRenderers[index - 1]; if (prev == null) continue;
|
||||
|
||||
var prevMeshRenderer = prev.GetComponent<MeshRenderer>();
|
||||
var currentMeshRenderer = smr.GetComponent<MeshRenderer>();
|
||||
if (prevMeshRenderer != null && currentMeshRenderer != null) {
|
||||
if (prevMeshRenderer == null || currentMeshRenderer == null) continue;
|
||||
|
||||
int prevSortingLayer = prevMeshRenderer.sortingLayerID;
|
||||
int prevSortingOrder = prevMeshRenderer.sortingOrder;
|
||||
|
||||
currentMeshRenderer.sortingLayerID = prevSortingLayer;
|
||||
currentMeshRenderer.sortingOrder = prevSortingOrder + SkeletonRenderSeparator.DefaultSortingOrderIncrement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -188,10 +204,9 @@ namespace Spine.Unity {
|
||||
|
||||
var orphans = new System.Collections.Generic.List<SkeletonPartsRenderer>();
|
||||
foreach (var r in children) {
|
||||
if (!component.partsRenderers.Contains(r)) {
|
||||
if (!component.partsRenderers.Contains(r))
|
||||
orphans.Add(r);
|
||||
}
|
||||
}
|
||||
|
||||
if (orphans.Count > 0) {
|
||||
if (EditorUtility.DisplayDialog("Destroy Submesh Renderers", "Unassigned renderers were found. Do you want to delete them? (These may belong to another Render Separator in the same hierarchy. If you don't have another Render Separator component in the children of this GameObject, it's likely safe to delete. Warning: This operation cannot be undone.)", "Delete", "Cancel")) {
|
||||
@ -202,7 +217,6 @@ namespace Spine.Unity {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region SkeletonRenderer Context Menu Item
|
||||
[MenuItem ("CONTEXT/SkeletonRenderer/Add Skeleton Render Separator")]
|
||||
static void AddRenderSeparatorComponent (MenuCommand cmd) {
|
||||
|
||||
@ -5,8 +5,8 @@ using Spine.Unity;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
[HelpURL("")]
|
||||
[ExecuteInEditMode]
|
||||
[HelpURL("https://github.com/pharan/spine-unity-docs/blob/master/SkeletonRenderSeparator.md")]
|
||||
public class SkeletonRenderSeparator : MonoBehaviour {
|
||||
public const int DefaultSortingOrderIncrement = 5;
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Spine.Unity {
|
||||
get { return skeletonRenderer; }
|
||||
set {
|
||||
if (skeletonRenderer != null)
|
||||
skeletonRenderer.GenerateMeshOverride -= SeparateSkeletonRender;
|
||||
skeletonRenderer.GenerateMeshOverride -= HandleRender;
|
||||
|
||||
skeletonRenderer = value;
|
||||
this.enabled = false; // Disable if nulled.
|
||||
@ -26,6 +26,7 @@ namespace Spine.Unity {
|
||||
|
||||
MeshRenderer mainMeshRenderer;
|
||||
public bool copyPropertyBlock = false;
|
||||
[Tooltip("Copies MeshRenderer flags into ")]
|
||||
public bool copyMeshRendererFlags = false;
|
||||
public List<Spine.Unity.SkeletonPartsRenderer> partsRenderers = new List<SkeletonPartsRenderer>();
|
||||
|
||||
@ -42,13 +43,28 @@ namespace Spine.Unity {
|
||||
if (block == null) block = new MaterialPropertyBlock();
|
||||
mainMeshRenderer = skeletonRenderer.GetComponent<MeshRenderer>();
|
||||
|
||||
skeletonRenderer.GenerateMeshOverride -= SeparateSkeletonRender;
|
||||
skeletonRenderer.GenerateMeshOverride += SeparateSkeletonRender;
|
||||
skeletonRenderer.GenerateMeshOverride -= HandleRender;
|
||||
skeletonRenderer.GenerateMeshOverride += HandleRender;
|
||||
|
||||
if (copyMeshRendererFlags) {
|
||||
bool useLightProbes = mainMeshRenderer.useLightProbes;
|
||||
bool receiveShadows = mainMeshRenderer.receiveShadows;
|
||||
|
||||
for (int i = 0; i < partsRenderers.Count; i++) {
|
||||
var currentRenderer = partsRenderers[i];
|
||||
if (currentRenderer == null) continue; // skip null items.
|
||||
|
||||
var mr = currentRenderer.MeshRenderer;
|
||||
mr.useLightProbes = useLightProbes;
|
||||
mr.receiveShadows = receiveShadows;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (skeletonRenderer == null) return;
|
||||
skeletonRenderer.GenerateMeshOverride -= SeparateSkeletonRender;
|
||||
skeletonRenderer.GenerateMeshOverride -= HandleRender;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
skeletonRenderer.LateUpdate();
|
||||
@ -60,7 +76,7 @@ namespace Spine.Unity {
|
||||
|
||||
MaterialPropertyBlock block;
|
||||
|
||||
void SeparateSkeletonRender (SkeletonRenderer.SmartMesh.Instruction instruction) {
|
||||
void HandleRender (SkeletonRenderer.SmartMesh.Instruction instruction) {
|
||||
int rendererCount = partsRenderers.Count;
|
||||
if (rendererCount <= 0) return;
|
||||
|
||||
@ -76,23 +92,10 @@ namespace Spine.Unity {
|
||||
var currentRenderer = partsRenderers[rendererIndex];
|
||||
bool skeletonRendererCalculateNormals = skeletonRenderer.calculateNormals;
|
||||
|
||||
bool useLightProbes = false;
|
||||
bool receiveShadows = false;
|
||||
|
||||
if (copyMeshRendererFlags) {
|
||||
useLightProbes = mainMeshRenderer.useLightProbes;
|
||||
receiveShadows = mainMeshRenderer.receiveShadows;
|
||||
}
|
||||
|
||||
for (int i = 0, start = 0; i <= lastSubmeshInstruction; i++) {
|
||||
if (submeshInstructionsItems[i].separatedBySlot) {
|
||||
if (submeshInstructionsItems[i].forceSeparate) {
|
||||
currentRenderer.RenderParts(instruction.submeshInstructions, start, i + 1);
|
||||
currentRenderer.MeshGenerator.GenerateNormals = skeletonRendererCalculateNormals;
|
||||
if (copyMeshRendererFlags) {
|
||||
var mr = currentRenderer.MeshRenderer;
|
||||
mr.useLightProbes = useLightProbes;
|
||||
mr.receiveShadows = receiveShadows;
|
||||
}
|
||||
if (copyPropertyBlock)
|
||||
currentRenderer.SetPropertyBlock(block);
|
||||
|
||||
@ -107,19 +110,13 @@ namespace Spine.Unity {
|
||||
} else if (i == lastSubmeshInstruction) {
|
||||
currentRenderer.RenderParts(instruction.submeshInstructions, start, i + 1);
|
||||
currentRenderer.MeshGenerator.GenerateNormals = skeletonRendererCalculateNormals;
|
||||
if (copyMeshRendererFlags) {
|
||||
var mr = currentRenderer.MeshRenderer;
|
||||
mr.useLightProbes = useLightProbes;
|
||||
mr.receiveShadows = receiveShadows;
|
||||
}
|
||||
if (copyPropertyBlock)
|
||||
currentRenderer.SetPropertyBlock(block);
|
||||
}
|
||||
}
|
||||
|
||||
// If too many renderers. Clear the rest.
|
||||
rendererIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Too many renderers. Clear the rest.
|
||||
if (rendererIndex < rendererCount - 1) {
|
||||
for (int i = rendererIndex; i < rendererCount; i++) {
|
||||
currentRenderer = partsRenderers[i];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user