Seven is the number.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

189 lines
5.6 KiB

using System;
using UnityEngine;
using UnityEngine.UI;
namespace LeTai.TrueShadow
{
[AddComponentMenu("")]
[ExecuteAlways]
public partial class ShadowRenderer : MonoBehaviour, ILayoutIgnorer, IMaterialModifier, IMeshModifier
{
public bool ignoreLayout => true;
internal CanvasRenderer CanvasRenderer { get; private set; }
TrueShadow shadow;
RectTransform rt;
RawImage graphic;
Texture shadowTexture;
public static void Initialize(TrueShadow shadow, ref ShadowRenderer renderer)
{
if (renderer && renderer.shadow == shadow)
{
renderer.gameObject.SetActive(true);
return;
}
var obj = new GameObject($"{shadow.gameObject.name}'s Shadow") {
#if LETAI_TRUESHADOW_DEBUG
hideFlags = DebugSettings.Instance.showObjects
? HideFlags.DontSave
: HideFlags.HideAndDontSave
#else
hideFlags = HideFlags.HideAndDontSave
#endif
};
#if LETAI_TRUESHADOW_DEBUG && UNITY_EDITOR
UnityEditor.SceneVisibilityManager.instance.DisablePicking(obj, true);
#endif
shadow.SetHierachyDirty();
var rt = obj.AddComponent<RectTransform>();
rt.anchorMin = Vector2.zero;
rt.anchorMax = Vector2.zero;
var graphic = obj.AddComponent<RawImage>();
graphic.raycastTarget = false;
graphic.color = shadow.Color;
renderer = obj.AddComponent<ShadowRenderer>();
renderer.shadow = shadow;
renderer.rt = rt;
renderer.graphic = graphic;
// renderer.RecreateGraphic(shadow.Baked ? GraphicType.Image : GraphicType.RawImage);
renderer.UpdateMaterial();
renderer.CanvasRenderer = obj.GetComponent<CanvasRenderer>();
renderer.CanvasRenderer.SetColor(shadow.IgnoreCasterColor ? Color.white : shadow.CanvasRenderer.GetColor());
renderer.CanvasRenderer.SetAlpha(shadow.CanvasRenderer.GetAlpha());
renderer.ReLayout();
}
public void UpdateMaterial()
{
var mat = shadow.BlendMode.GetMaterial();
graphic.material = mat ? mat : shadow.GetShadowRenderingNormalMaterial();
}
internal void ReLayout()
{
if (!isActiveAndEnabled)
return;
var casterRt = shadow.RectTransform;
if (!casterRt)
{
CanvasRenderer.SetAlpha(0);
return;
}
if (!shadowTexture)
{
CanvasRenderer.SetAlpha(0);
return;
}
var container = shadow.ShadowContainer;
var canvasScale = container?.Snapshot?.canvasScale ?? graphic.canvas.scaleFactor;
var shadowTexSize = new Vector2(shadowTexture.width, shadowTexture.height) / canvasScale;
rt.sizeDelta = shadowTexSize;
// pivot should be relative to the un-blurred part of the texture, not the whole mesh
var casterPivotLS = -(Vector2) shadow.SpriteMesh.bounds.min;
var padding = (container?.Padding ?? Mathf.CeilToInt(shadow.Size * canvasScale)) / canvasScale * Vector2.one;
var misalign = container?.PxMisalignmentAtMinLS ?? Vector2.zero;
rt.pivot = (casterPivotLS + padding + misalign) / shadowTexSize;
var canvasRelativeOffset = container?.Snapshot?.canvasRelativeOffset / canvasScale ?? shadow.Offset;
var offset = shadow.ShadowAsSibling
? shadow.Offset.WithZ(0)
: canvasRelativeOffset.WithZ(0);
rt.localPosition = shadow.ShadowAsSibling
? casterRt.localPosition + offset
: offset;
rt.localRotation = shadow.ShadowAsSibling ? casterRt.localRotation : Quaternion.identity;
rt.localScale = shadow.ShadowAsSibling ? casterRt.localScale : Vector3.one;
var color = shadow.Color;
if (shadow.UseCasterAlpha)
color.a *= shadow.Graphic.color.a;
graphic.color = color;
CanvasRenderer.SetColor(shadow.IgnoreCasterColor ? Color.white : shadow.CanvasRenderer.GetColor());
CanvasRenderer.SetAlpha(shadow.CanvasRenderer.GetAlpha());
graphic.Rebuild(CanvasUpdate.PreRender);
}
public void SetTexture(Texture texture)
{
shadowTexture = texture;
CanvasRenderer.SetTexture(texture);
graphic.texture = texture;
}
public void SetMaterialDirty()
{
graphic.SetMaterialDirty();
}
public void ModifyMesh(VertexHelper vertexHelper)
{
if (!shadow)
return;
shadow.ModifyShadowRendererMesh(vertexHelper);
}
public void ModifyMesh(Mesh mesh)
{
Debug.Assert(true, "This should only be called on old unsupported Unity version");
}
protected virtual void LateUpdate()
{
// Destroy events are not consistently called for some reason, have to poll
if (!shadow)
Dispose();
}
bool willBeDestroyed;
protected virtual void OnDestroy()
{
willBeDestroyed = true;
}
public void Dispose()
{
if (willBeDestroyed) return;
if (shadow && shadow.ShadowAsSibling)
{
// Destroy does not happen immediately. Want out of hierarchy.
gameObject.SetActive(false);
transform.SetParent(null);
}
#if UNITY_EDITOR
// This look redundant but is necessary!
if (!Application.isPlaying && !UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
DestroyImmediate(gameObject);
else if (Application.isPlaying)
Destroy(gameObject);
#else
Destroy(gameObject);
#endif
}
}
}