mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 01:36:02 +08:00
[unity] Added RenderExistingMeshGraphic sample component similar to RenderExistingMesh.
This commit is contained in:
parent
7f2e4c1df7
commit
a0721dbf4b
@ -170,6 +170,11 @@
|
|||||||
- `Universal Render Pipeline/Spine/Skeleton Lit` shader now supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. The shader also provides a new material property `APV per Pixel` to either calculate APV lighting contribution per pixel (the default) or per vertex.
|
- `Universal Render Pipeline/Spine/Skeleton Lit` shader now supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. The shader also provides a new material property `APV per Pixel` to either calculate APV lighting contribution per pixel (the default) or per vertex.
|
||||||
- `Universal Render Pipeline/Spine/Sprite` shader now also supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. APV lighting contribution is automatically calculated per pixel.
|
- `Universal Render Pipeline/Spine/Sprite` shader now also supports [Adaptive Probe Volumes (APV)](https://docs.unity3d.com/6000.0/Documentation/Manual/urp/probevolumes-concept.html) introduced in Unity 6. APV lighting contribution is automatically calculated per pixel.
|
||||||
- All Spine Outline shaders, including the URP outline shaders, now provide an additional parameter `Fill`. Enable it to also fill the opaque area inside the outline with the outline color. Prevents a semi-transparent gap between outline and skeleton. Defaults to `disabled` to maintain existing behaviour.
|
- All Spine Outline shaders, including the URP outline shaders, now provide an additional parameter `Fill`. Enable it to also fill the opaque area inside the outline with the outline color. Prevents a semi-transparent gap between outline and skeleton. Defaults to `disabled` to maintain existing behaviour.
|
||||||
|
- Added example component `RenderExistingMeshGraphic` (similar to `RenderExistingMesh`) to render a `SkeletonGraphic` mesh again with different materials. This might be required by e.g. URP and SkeletonGraphic outline shaders skipping additional render passes. To add a second outline variant of your SkeletonGraphic:
|
||||||
|
1. Add a GameObject at the same hierarchy level as the reference SkeletonGraphic and move it before the reference SkeletonGraphic to render behind.
|
||||||
|
2. Add a `RenderExistingMeshGraphic` component.
|
||||||
|
3. In the `RenderExistingMeshGraphic` component Inspector at `Reference Skeleton Graphic` assign the original `SkeletonGraphic` object.
|
||||||
|
4. At `Replacement Material` assign e.g. the included _SkeletonGraphicDefaultOutline_ material to replace all materials with this material. Alternatively, if `Multiple CanvasRenderers` is enabled at the reference SkeletonGraphic, you can add entries to the `Replacement Materials` list and at each entry assign the original SkeletonGraphic material (e.g. _SkeletonGraphicDefault_) to be replaced and the respective `Replacement Material` (e.g. _SkeletonGraphicDefaultOutline_).
|
||||||
|
|
||||||
- **Breaking changes**
|
- **Breaking changes**
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,214 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Spine Runtimes License Agreement
|
||||||
|
* Last updated July 28, 2023. Replaces all prior versions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2025, 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Spine.Unity.Examples {
|
||||||
|
using MaterialReplacement = RenderExistingMesh.MaterialReplacement;
|
||||||
|
|
||||||
|
#if NEW_PREFAB_SYSTEM
|
||||||
|
[ExecuteAlways]
|
||||||
|
#else
|
||||||
|
[ExecuteInEditMode]
|
||||||
|
#endif
|
||||||
|
public class RenderExistingMeshGraphic : MonoBehaviour {
|
||||||
|
public SkeletonGraphic referenceSkeletonGraphic;
|
||||||
|
public Material replacementMaterial;
|
||||||
|
|
||||||
|
public MaterialReplacement[] replacementMaterials = new MaterialReplacement[0];
|
||||||
|
|
||||||
|
SkeletonSubmeshGraphic ownGraphic;
|
||||||
|
public List<SkeletonSubmeshGraphic> ownSubmeshGraphics;
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
private void Reset () {
|
||||||
|
Awake();
|
||||||
|
LateUpdate();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Awake () {
|
||||||
|
// subscribe to OnMeshAndMaterialsUpdated
|
||||||
|
if (referenceSkeletonGraphic) {
|
||||||
|
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||||
|
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated += UpdateOnCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
ownGraphic = this.GetComponent<SkeletonSubmeshGraphic>();
|
||||||
|
if (referenceSkeletonGraphic) {
|
||||||
|
if (referenceSkeletonGraphic.allowMultipleCanvasRenderers)
|
||||||
|
EnsureCanvasRendererCount(referenceSkeletonGraphic.canvasRenderers.Count);
|
||||||
|
else
|
||||||
|
SetupSubmeshGraphic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnDisable () {
|
||||||
|
if (referenceSkeletonGraphic) {
|
||||||
|
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnEnable () {
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
// handle disabled scene reload
|
||||||
|
if (Application.isPlaying) {
|
||||||
|
Awake();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (referenceSkeletonGraphic) {
|
||||||
|
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated -= UpdateOnCallback;
|
||||||
|
referenceSkeletonGraphic.OnMeshAndMaterialsUpdated += UpdateOnCallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupSubmeshGraphic () {
|
||||||
|
if (ownGraphic == null)
|
||||||
|
ownGraphic = this.gameObject.AddComponent<SkeletonSubmeshGraphic>();
|
||||||
|
|
||||||
|
ownGraphic.maskable = referenceSkeletonGraphic.maskable;
|
||||||
|
ownGraphic.canvasRenderer.cullTransparentMesh = referenceSkeletonGraphic.canvasRenderer.cullTransparentMesh;
|
||||||
|
ownGraphic.canvasRenderer.SetMaterial(replacementMaterial, referenceSkeletonGraphic.mainTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void EnsureCanvasRendererCount (int targetCount) {
|
||||||
|
if (ownSubmeshGraphics == null)
|
||||||
|
ownSubmeshGraphics = new List<SkeletonSubmeshGraphic>();
|
||||||
|
|
||||||
|
bool cullTransparentMesh = referenceSkeletonGraphic.canvasRenderer.cullTransparentMesh;
|
||||||
|
Vector2 pivot = referenceSkeletonGraphic.rectTransform.pivot;
|
||||||
|
|
||||||
|
int currentCount = ownSubmeshGraphics.Count;
|
||||||
|
for (int i = currentCount; i < targetCount; ++i) {
|
||||||
|
GameObject go = new GameObject(string.Format("Renderer{0}", i), typeof(RectTransform));
|
||||||
|
go.transform.SetParent(this.transform, false);
|
||||||
|
go.transform.localPosition = Vector3.zero;
|
||||||
|
CanvasRenderer canvasRenderer = go.AddComponent<CanvasRenderer>();
|
||||||
|
canvasRenderer.cullTransparentMesh = cullTransparentMesh;
|
||||||
|
SkeletonSubmeshGraphic submeshGraphic = go.AddComponent<SkeletonSubmeshGraphic>();
|
||||||
|
ownSubmeshGraphics.Add(submeshGraphic);
|
||||||
|
submeshGraphic.maskable = referenceSkeletonGraphic.maskable;
|
||||||
|
submeshGraphic.raycastTarget = false;
|
||||||
|
submeshGraphic.rectTransform.pivot = pivot;
|
||||||
|
submeshGraphic.rectTransform.anchorMin = Vector2.zero;
|
||||||
|
submeshGraphic.rectTransform.anchorMax = Vector2.one;
|
||||||
|
submeshGraphic.rectTransform.sizeDelta = Vector2.zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateCanvasRenderers () {
|
||||||
|
Mesh[] referenceMeshes = referenceSkeletonGraphic.MeshesMultipleCanvasRenderers.Items;
|
||||||
|
Material[] referenceMaterials = referenceSkeletonGraphic.MaterialsMultipleCanvasRenderers.Items;
|
||||||
|
Texture[] referenceTextures = referenceSkeletonGraphic.TexturesMultipleCanvasRenderers.Items;
|
||||||
|
|
||||||
|
int end = Math.Min(ownSubmeshGraphics.Count, referenceSkeletonGraphic.TexturesMultipleCanvasRenderers.Count);
|
||||||
|
|
||||||
|
for (int i = 0; i < end; i++) {
|
||||||
|
SkeletonSubmeshGraphic submeshGraphic = ownSubmeshGraphics[i];
|
||||||
|
CanvasRenderer reference = referenceSkeletonGraphic.canvasRenderers[i];
|
||||||
|
|
||||||
|
if (reference.gameObject.activeInHierarchy) {
|
||||||
|
Material usedMaterial = replacementMaterial != null ?
|
||||||
|
replacementMaterial : GetReplacementMaterialFor(referenceMaterials[i]);
|
||||||
|
if (usedMaterial == null)
|
||||||
|
usedMaterial = referenceMaterials[i];
|
||||||
|
usedMaterial = referenceSkeletonGraphic.GetModifiedMaterial(usedMaterial);
|
||||||
|
submeshGraphic.canvasRenderer.SetMaterial(usedMaterial, referenceTextures[i]);
|
||||||
|
submeshGraphic.canvasRenderer.SetMesh(referenceMeshes[i]);
|
||||||
|
submeshGraphic.gameObject.SetActive(true);
|
||||||
|
} else {
|
||||||
|
submeshGraphic.canvasRenderer.Clear();
|
||||||
|
submeshGraphic.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void DisableCanvasRenderers () {
|
||||||
|
for (int i = 0; i < ownSubmeshGraphics.Count; i++) {
|
||||||
|
SkeletonSubmeshGraphic submeshGraphic = ownSubmeshGraphics[i];
|
||||||
|
submeshGraphic.canvasRenderer.Clear();
|
||||||
|
submeshGraphic.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Material GetReplacementMaterialFor (Material originalMaterial) {
|
||||||
|
for (int i = 0; i < replacementMaterials.Length; ++i) {
|
||||||
|
MaterialReplacement entry = replacementMaterials[i];
|
||||||
|
if (entry.originalMaterial != null && entry.originalMaterial.shader == originalMaterial.shader)
|
||||||
|
return entry.replacementMaterial;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
void LateUpdate () {
|
||||||
|
if (!Application.isPlaying) {
|
||||||
|
UpdateMesh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void UpdateOnCallback (SkeletonGraphic g) {
|
||||||
|
UpdateMesh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateMesh () {
|
||||||
|
if (!referenceSkeletonGraphic) return;
|
||||||
|
|
||||||
|
if (referenceSkeletonGraphic.allowMultipleCanvasRenderers) {
|
||||||
|
EnsureCanvasRendererCount(referenceSkeletonGraphic.canvasRenderers.Count);
|
||||||
|
UpdateCanvasRenderers();
|
||||||
|
if (ownGraphic)
|
||||||
|
ownGraphic.canvasRenderer.Clear();
|
||||||
|
} else {
|
||||||
|
if (ownGraphic == null)
|
||||||
|
ownGraphic = this.gameObject.AddComponent<SkeletonSubmeshGraphic>();
|
||||||
|
|
||||||
|
DisableCanvasRenderers();
|
||||||
|
|
||||||
|
Material referenceMaterial = referenceSkeletonGraphic.materialForRendering;
|
||||||
|
Material usedMaterial = replacementMaterial != null ? replacementMaterial : GetReplacementMaterialFor(referenceMaterial);
|
||||||
|
if (usedMaterial == null)
|
||||||
|
usedMaterial = referenceMaterial;
|
||||||
|
usedMaterial = referenceSkeletonGraphic.GetModifiedMaterial(usedMaterial);
|
||||||
|
ownGraphic.canvasRenderer.SetMaterial(usedMaterial, referenceSkeletonGraphic.mainTexture);
|
||||||
|
Mesh mesh = referenceSkeletonGraphic.GetLastMesh();
|
||||||
|
ownGraphic.canvasRenderer.SetMesh(mesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ff6ce4ce6b9336a479c6bf5af81fa80a
|
||||||
@ -2,7 +2,7 @@
|
|||||||
"name": "com.esotericsoftware.spine.spine-unity-examples",
|
"name": "com.esotericsoftware.spine.spine-unity-examples",
|
||||||
"displayName": "spine-unity Runtime Examples",
|
"displayName": "spine-unity Runtime Examples",
|
||||||
"description": "This plugin provides example scenes and scripts for the spine-unity runtime.",
|
"description": "This plugin provides example scenes and scripts for the spine-unity runtime.",
|
||||||
"version": "4.2.37",
|
"version": "4.2.38",
|
||||||
"unity": "2018.3",
|
"unity": "2018.3",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Esoteric Software",
|
"name": "Esoteric Software",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user