123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- /******************************************************************************
- * Spine Runtimes License Agreement
- * Last updated January 1, 2020. Replaces all prior versions.
- *
- * Copyright (c) 2013-2020, 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
- #define SPINE_OPTIONAL_RENDEROVERRIDE
- using UnityEngine;
- using System.Collections.Generic;
- namespace Spine.Unity {
- #if NEW_PREFAB_SYSTEM
- [ExecuteAlways]
- #else
- [ExecuteInEditMode]
- #endif
- [HelpURL("http://esotericsoftware.com/spine-unity#SkeletonRenderSeparator")]
- public class SkeletonRenderSeparator : MonoBehaviour {
- public const int DefaultSortingOrderIncrement = 5;
- #region Inspector
- [SerializeField]
- protected SkeletonRenderer skeletonRenderer;
- public SkeletonRenderer SkeletonRenderer {
- get { return skeletonRenderer; }
- set {
- #if SPINE_OPTIONAL_RENDEROVERRIDE
- if (skeletonRenderer != null)
- skeletonRenderer.GenerateMeshOverride -= HandleRender;
- #endif
- skeletonRenderer = value;
- if (value == null)
- this.enabled = false;
- }
- }
- MeshRenderer mainMeshRenderer;
- public bool copyPropertyBlock = true;
- [Tooltip("Copies MeshRenderer flags into each parts renderer")]
- public bool copyMeshRendererFlags = true;
- public List<Spine.Unity.SkeletonPartsRenderer> partsRenderers = new List<SkeletonPartsRenderer>();
- #if UNITY_EDITOR
- void Reset () {
- if (skeletonRenderer == null)
- skeletonRenderer = GetComponent<SkeletonRenderer>();
- }
- #endif
- #endregion
- #region Callback Delegates
- /// <summary>OnMeshAndMaterialsUpdated is called at the end of LateUpdate after the Mesh and
- /// all materials have been updated.</summary>
- public event SkeletonRenderer.SkeletonRendererDelegate OnMeshAndMaterialsUpdated;
- #endregion
- #region Runtime Instantiation
- /// <summary>Adds a SkeletonRenderSeparator and child SkeletonPartsRenderer GameObjects to a given SkeletonRenderer.</summary>
- /// <returns>The to skeleton renderer.</returns>
- /// <param name="skeletonRenderer">The target SkeletonRenderer or SkeletonAnimation.</param>
- /// <param name="sortingLayerID">Sorting layer to be used for the parts renderers.</param>
- /// <param name="extraPartsRenderers">Number of additional SkeletonPartsRenderers on top of the ones determined by counting the number of separator slots.</param>
- /// <param name="sortingOrderIncrement">The integer to increment the sorting order per SkeletonPartsRenderer to separate them.</param>
- /// <param name="baseSortingOrder">The sorting order value of the first SkeletonPartsRenderer.</param>
- /// <param name="addMinimumPartsRenderers">If set to <c>true</c>, a minimum number of SkeletonPartsRenderer GameObjects (determined by separatorSlots.Count + 1) will be added.</param>
- public static SkeletonRenderSeparator AddToSkeletonRenderer (SkeletonRenderer skeletonRenderer, int sortingLayerID = 0, int extraPartsRenderers = 0, int sortingOrderIncrement = DefaultSortingOrderIncrement, int baseSortingOrder = 0, bool addMinimumPartsRenderers = true) {
- if (skeletonRenderer == null) {
- Debug.Log("Tried to add SkeletonRenderSeparator to a null SkeletonRenderer reference.");
- return null;
- }
- var srs = skeletonRenderer.gameObject.AddComponent<SkeletonRenderSeparator>();
- srs.skeletonRenderer = skeletonRenderer;
- skeletonRenderer.Initialize(false);
- int count = extraPartsRenderers;
- if (addMinimumPartsRenderers)
- count = extraPartsRenderers + skeletonRenderer.separatorSlots.Count + 1;
- var skeletonRendererTransform = skeletonRenderer.transform;
- var componentRenderers = srs.partsRenderers;
- for (int i = 0; i < count; i++) {
- var spr = SkeletonPartsRenderer.NewPartsRendererGameObject(skeletonRendererTransform, i.ToString());
- var mr = spr.MeshRenderer;
- mr.sortingLayerID = sortingLayerID;
- mr.sortingOrder = baseSortingOrder + (i * sortingOrderIncrement);
- componentRenderers.Add(spr);
- }
- srs.OnEnable();
- #if UNITY_EDITOR
- // Make sure editor updates properly in edit mode.
- if (!Application.isPlaying) {
- skeletonRenderer.enabled = false;
- skeletonRenderer.enabled = true;
- skeletonRenderer.LateUpdate();
- }
- #endif
- return srs;
- }
- /// <summary>Add a child SkeletonPartsRenderer GameObject to this SkeletonRenderSeparator.</summary>
- public SkeletonPartsRenderer AddPartsRenderer (int sortingOrderIncrement = DefaultSortingOrderIncrement, string name = null) {
- int sortingLayerID = 0;
- int sortingOrder = 0;
- if (partsRenderers.Count > 0) {
- var previous = partsRenderers[partsRenderers.Count - 1];
- var previousMeshRenderer = previous.MeshRenderer;
- sortingLayerID = previousMeshRenderer.sortingLayerID;
- sortingOrder = previousMeshRenderer.sortingOrder + sortingOrderIncrement;
- }
- if (string.IsNullOrEmpty(name))
- name = partsRenderers.Count.ToString();
- var spr = SkeletonPartsRenderer.NewPartsRendererGameObject(skeletonRenderer.transform, name);
- partsRenderers.Add(spr);
- var mr = spr.MeshRenderer;
- mr.sortingLayerID = sortingLayerID;
- mr.sortingOrder = sortingOrder;
- return spr;
- }
- #endregion
- public void OnEnable () {
- if (skeletonRenderer == null) return;
- if (copiedBlock == null) copiedBlock = new MaterialPropertyBlock();
- mainMeshRenderer = skeletonRenderer.GetComponent<MeshRenderer>();
- #if SPINE_OPTIONAL_RENDEROVERRIDE
- skeletonRenderer.GenerateMeshOverride -= HandleRender;
- skeletonRenderer.GenerateMeshOverride += HandleRender;
- #endif
- if (copyMeshRendererFlags) {
- var lightProbeUsage = mainMeshRenderer.lightProbeUsage;
- bool receiveShadows = mainMeshRenderer.receiveShadows;
- var reflectionProbeUsage = mainMeshRenderer.reflectionProbeUsage;
- var shadowCastingMode = mainMeshRenderer.shadowCastingMode;
- var motionVectorGenerationMode = mainMeshRenderer.motionVectorGenerationMode;
- var probeAnchor = mainMeshRenderer.probeAnchor;
- for (int i = 0; i < partsRenderers.Count; i++) {
- var currentRenderer = partsRenderers[i];
- if (currentRenderer == null) continue; // skip null items.
- var mr = currentRenderer.MeshRenderer;
- mr.lightProbeUsage = lightProbeUsage;
- mr.receiveShadows = receiveShadows;
- mr.reflectionProbeUsage = reflectionProbeUsage;
- mr.shadowCastingMode = shadowCastingMode;
- mr.motionVectorGenerationMode = motionVectorGenerationMode;
- mr.probeAnchor = probeAnchor;
- }
- }
- }
- public void OnDisable () {
- if (skeletonRenderer == null) return;
- #if SPINE_OPTIONAL_RENDEROVERRIDE
- skeletonRenderer.GenerateMeshOverride -= HandleRender;
- #endif
- skeletonRenderer.LateUpdate();
- foreach (var partsRenderer in partsRenderers) {
- if (partsRenderer != null)
- partsRenderer.ClearMesh();
- }
- }
- MaterialPropertyBlock copiedBlock;
- void HandleRender (SkeletonRendererInstruction instruction) {
- int rendererCount = partsRenderers.Count;
- if (rendererCount <= 0) return;
- if (copyPropertyBlock)
- mainMeshRenderer.GetPropertyBlock(copiedBlock);
- var settings = new MeshGenerator.Settings {
- addNormals = skeletonRenderer.addNormals,
- calculateTangents = skeletonRenderer.calculateTangents,
- immutableTriangles = false, // parts cannot do immutable triangles.
- pmaVertexColors = skeletonRenderer.pmaVertexColors,
- tintBlack = skeletonRenderer.tintBlack,
- useClipping = true,
- zSpacing = skeletonRenderer.zSpacing
- };
- var submeshInstructions = instruction.submeshInstructions;
- var submeshInstructionsItems = submeshInstructions.Items;
- int lastSubmeshInstruction = submeshInstructions.Count - 1;
- int rendererIndex = 0;
- var currentRenderer = partsRenderers[rendererIndex];
- for (int si = 0, start = 0; si <= lastSubmeshInstruction; si++) {
- if (currentRenderer == null)
- continue;
- if (submeshInstructionsItems[si].forceSeparate || si == lastSubmeshInstruction) {
- // Apply properties
- var meshGenerator = currentRenderer.MeshGenerator;
- meshGenerator.settings = settings;
- if (copyPropertyBlock)
- currentRenderer.SetPropertyBlock(copiedBlock);
- // Render
- currentRenderer.RenderParts(instruction.submeshInstructions, start, si + 1);
- start = si + 1;
- rendererIndex++;
- if (rendererIndex < rendererCount) {
- currentRenderer = partsRenderers[rendererIndex];
- } else {
- // Not enough renderers. Skip the rest of the instructions.
- break;
- }
- }
- }
- if (OnMeshAndMaterialsUpdated != null)
- OnMeshAndMaterialsUpdated(this.skeletonRenderer);
- // Clear extra renderers if they exist.
- for (; rendererIndex < rendererCount; rendererIndex++) {
- currentRenderer = partsRenderers[rendererIndex];
- if (currentRenderer != null)
- partsRenderers[rendererIndex].ClearMesh();
- }
- }
- }
- }
|