RenderSeparator update.

This commit is contained in:
pharan 2016-03-24 00:35:19 +08:00
parent 9254e18801
commit 46ee116ee3
6 changed files with 114 additions and 101 deletions

View File

@ -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
}
);

View File

@ -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; } }

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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) {

View File

@ -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];