Files

120 lines
3.1 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Toria.Game
{
[RequireComponent(typeof(CapsuleCollider))]
2026-08-03 15:28:37 +02:00
public class DitherFade : MonoBehaviour
{
2026-08-03 15:28:37 +02:00
public DitherFadeSettings settings;
public List<Renderer> targetRenderers;
public bool makeShadowClones = true;
[NonSerialized]
2026-08-03 15:28:37 +02:00
List<Material> fadeMaterials;
static RPGController player = null;
static new Camera camera = null;
[NonSerialized]
bool shouldHide = false;
void Start()
{
2026-08-03 15:28:37 +02:00
fadeMaterials = new List<Material>();
2026-08-03 15:28:37 +02:00
foreach (Renderer renderer in targetRenderers)
{
2026-08-03 15:28:37 +02:00
if (makeShadowClones)
MakeShadowClone(renderer);
Material[] mats = renderer.sharedMaterials.Select(m => Instantiate(m)).ToArray();
renderer.sharedMaterials = mats;
fadeMaterials.AddRange(mats);
}
}
void MakeShadowClone(Renderer renderer)
{
2026-08-03 15:28:37 +02:00
if (!renderer.TryGetComponent(out MeshFilter filter))
return;
2026-08-03 15:28:37 +02:00
GameObject shadowClone = new GameObject("Shadow clone");
shadowClone.transform.SetParent(renderer.transform);
shadowClone.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
shadowClone.transform.localScale = Vector3.one;
2026-08-03 15:28:37 +02:00
MeshRenderer shadowRenderer = shadowClone.AddComponent<MeshRenderer>();
MeshFilter shadowFilter = shadowClone.AddComponent<MeshFilter>();
shadowRenderer.sharedMaterials = renderer.sharedMaterials;
2026-08-03 15:28:37 +02:00
shadowRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;
shadowFilter.sharedMesh = filter.sharedMesh;
foreach (Component comp in shadowClone.GetComponents<Component>())
{
if (comp is not MeshRenderer && comp is not MeshFilter && comp is not Transform)
Destroy(comp);
}
2026-08-03 15:28:37 +02:00
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
}
void Update()
{
if (!player)
player = FindAnyObjectByType<RPGController>();
if (shouldHide)
{
2026-08-03 15:28:37 +02:00
Vector2 viewPortPoint = camera.WorldToViewportPoint(player.transform.position + Vector3.up * settings.verticalOffset);
float hideRadius = settings.GetHideRadius(player.transform, camera.transform);
2026-08-03 15:28:37 +02:00
foreach (Material mat in fadeMaterials)
{
mat.SetVector("_PlayerPosition", viewPortPoint);
2026-08-03 15:28:37 +02:00
mat.SetFloat("_HideRadius", hideRadius);
}
}
if (!camera)
camera = Camera.main;
if (!player || !camera)
return;
Vector3 playerPos = player.transform.position + Vector3.up;
Vector3 cameraPos = camera.transform.position;
Vector3 rayDir = (playerPos - cameraPos).normalized;
//move back the origin point so the raycast doesn't start from within a tree collider
RaycastHit[] hits = Physics.RaycastAll(cameraPos + rayDir * -100f, rayDir, float.PositiveInfinity, 1 << gameObject.layer, QueryTriggerInteraction.Collide);
for (int i = 0; i < hits.Length; i++)
{
if (hits[i].collider.gameObject == gameObject)
{
SetCutoutEnabled(true);
return;
}
}
SetCutoutEnabled(false);
}
void SetCutoutEnabled(bool enabled)
{
if (shouldHide == enabled)
return;
shouldHide = enabled;
2026-08-03 15:28:37 +02:00
foreach (Material mat in fadeMaterials)
mat.SetFloat("_ShouldHide", enabled ? 1 : 0);
}
}
}