AkiraPixelWind/Assets/ShadowCasterFlip.cs
2023-01-03 23:53:30 +08:00

86 lines
3.0 KiB
C#

using UnityEngine;
using UnityEngine.Experimental.Rendering.Universal;
using System.Reflection;
[ExecuteInEditMode]
public class ShadowCasterFlip : MonoBehaviour
{
[SerializeField] [HideInInspector] private bool flipX = false;
[SerializeField] [HideInInspector] private bool flipY = false;
private SpriteRenderer spriteRenderer;
private ShadowCaster2D shadowCaster;
private static BindingFlags accessFlagsPrivate = BindingFlags.NonPublic | BindingFlags.Instance;
private static FieldInfo meshField = typeof(ShadowCaster2D).GetField("m_Mesh", accessFlagsPrivate);
private static FieldInfo shapePathField = typeof(ShadowCaster2D).GetField("m_ShapePath", accessFlagsPrivate);
private static MethodInfo onEnableMethod = typeof(ShadowCaster2D).GetMethod("OnEnable", accessFlagsPrivate);
private static bool isInspector =>
#if UNITY_EDITOR
!UnityEditor.EditorApplication.isPlaying;
#else
false;
#endif
//Bounds bounds => GetComponent<Renderer>()?.bounds ?? GetComponent<Collider2D>()?.bounds ?? new Bounds(transform.position, Vector3.one);
private bool flipCaster(bool flipX, bool flipY)
{
if (!flipX && !flipY) return false;
var shapePath = shapePathField.GetValue(shadowCaster) as Vector3[];
var newShapePath = new Vector3[shapePath.Length];
int newStartIndex = 0;
float? lowestAvg = null;
for (int i = 0; i < shapePath.Length; i++)
{
shapePath[i].x = shapePath[i].x * (flipX ? -1 : 1);
shapePath[i].y = shapePath[i].y * (flipY ? -1 : 1);
var newAvg = (shapePath[i].x + shapePath[i].y) / 2;
if (lowestAvg == null || newAvg < lowestAvg)
{
newStartIndex = i;
lowestAvg = newAvg;
}
}
if (flipX != flipY) for (int i = 0, ni = newStartIndex; i < shapePath.Length; i++, ni--)
{
if (ni < 0) ni = shapePath.Length - 1;
newShapePath[i] = shapePath[ni];
}
else for (int i = 0, ni = newStartIndex; i < shapePath.Length; i++, ni++)
{
if (ni >= shapePath.Length) ni = 0;
newShapePath[i] = shapePath[ni];
}
shapePathField.SetValue(shadowCaster, newShapePath);
shadowCaster.enabled = false;
meshField.SetValue(shadowCaster, null);
shadowCaster.enabled = true;
return true;
}
#if UNITY_EDITOR
void Start()
{
if (isInspector)
{
spriteRenderer = GetComponent<SpriteRenderer>();
shadowCaster = GetComponent<UnityEngine.Experimental.Rendering.Universal.ShadowCaster2D>();
}
}
#endif
#if UNITY_EDITOR
void Update()
{
if (isInspector && flipCaster(flipX != spriteRenderer.flipX, flipY != spriteRenderer.flipY))
{
flipX = spriteRenderer.flipX;
flipY = spriteRenderer.flipY;
UnityEditor.EditorUtility.SetDirty(shadowCaster);
UnityEditor.EditorUtility.SetDirty(this);
}
}
#endif
}