Files
tiny_tackle_heroes/Assets/_Project/Scripts/Constants/Defense25DFacilityVisualConstants.cs
T
2026-09-28 11:07:17 +09:00

153 lines
7.1 KiB
C#

using System;
using BumpCombat.Defense;
using UnityEngine;
namespace BumpCombat.Constants
{
[Serializable]
public sealed class Defense25DFacilityEffectStyle
{
[SerializeField, Min(.001f)] private float targetDurationSeconds = .6f;
[SerializeField, Min(.001f)] private float groundScale = 1f;
[SerializeField, Min(.001f)] private float verticalScale = 1f;
[SerializeField] private float groundYOffset = .04f;
[SerializeField, Min(0f)] private float verticalHeight = .7f;
[SerializeField] private Color groundTint = Color.white;
[SerializeField] private Color verticalTint = Color.white;
public float TargetDurationSeconds => targetDurationSeconds;
public float GroundScale => groundScale;
public float VerticalScale => verticalScale;
public float GroundYOffset => groundYOffset;
public float VerticalHeight => verticalHeight;
public Color GroundTint => groundTint;
public Color VerticalTint => verticalTint;
internal bool TryValidate(string name, out string error)
{
if (!IsFinite(targetDurationSeconds) || targetDurationSeconds <= 0f
|| !IsFinite(groundScale) || groundScale <= 0f
|| !IsFinite(verticalScale) || verticalScale <= 0f
|| !IsFinite(groundYOffset) || !IsFinite(verticalHeight) || verticalHeight < 0f
|| !IsFinite(groundTint) || !IsFinite(verticalTint))
{
error = $"{name} has an invalid duration, layer transform, scale, or tint.";
return false;
}
error = null;
return true;
}
private static bool IsFinite(float value) => !float.IsNaN(value) && !float.IsInfinity(value);
private static bool IsFinite(Color color) => IsFinite(color.r) && IsFinite(color.g)
&& IsFinite(color.b) && IsFinite(color.a);
}
[CreateAssetMenu(menuName = "BumpCombat/Constants/Defense 2.5D Facility Visuals")]
public sealed class Defense25DFacilityVisualConstants : ScriptableObject
{
[SerializeField] private string impactWaveResourceKey = "Effects/Lightning/ImpactWave";
[SerializeField] private string meteorImpactResourceKey = "Effects/Fire/Meteor-Impact";
[SerializeField] private string imbuingResourceKey = "Effects/Support/Imbuing";
[SerializeField] private int groundSortingOrder = 13;
[SerializeField] private int verticalSortingOrder = 14;
[SerializeField] private Defense25DFacilityEffectStyle portalSpawn = new();
[SerializeField] private Defense25DFacilityEffectStyle portalBurst = new();
[SerializeField] private Defense25DFacilityEffectStyle homeSpawn = new();
[SerializeField] private Defense25DFacilityEffectStyle homeBurst = new();
[SerializeField] private Defense25DFacilityEffectStyle towerPadSpawn = new();
[SerializeField] private Defense25DFacilityEffectStyle towerUpgrade = new();
public string ImpactWaveResourceKey => impactWaveResourceKey;
public string MeteorImpactResourceKey => meteorImpactResourceKey;
public string ImbuingResourceKey => imbuingResourceKey;
public int GroundSortingOrder => groundSortingOrder;
public int VerticalSortingOrder => verticalSortingOrder;
public Defense25DFacilityEffectStyle PortalSpawn => portalSpawn;
public Defense25DFacilityEffectStyle PortalBurst => portalBurst;
public Defense25DFacilityEffectStyle HomeSpawn => homeSpawn;
public Defense25DFacilityEffectStyle HomeBurst => homeBurst;
public Defense25DFacilityEffectStyle TowerPadSpawn => towerPadSpawn;
public Defense25DFacilityEffectStyle TowerUpgrade => towerUpgrade;
public bool TryValidate(out string error)
{
if (!ValidateResource(impactWaveResourceKey, "ImpactWave", out error)
|| !ValidateResource(meteorImpactResourceKey, "Meteor-Impact", out error)
|| !ValidateResource(imbuingResourceKey, "Imbuing", out error))
return false;
if (!ValidateStyle(portalSpawn, nameof(portalSpawn), out error)
|| !ValidateStyle(portalBurst, nameof(portalBurst), out error)
|| !ValidateStyle(homeSpawn, nameof(homeSpawn), out error)
|| !ValidateStyle(homeBurst, nameof(homeBurst), out error)
|| !ValidateStyle(towerPadSpawn, nameof(towerPadSpawn), out error)
|| !ValidateStyle(towerUpgrade, nameof(towerUpgrade), out error))
return false;
error = null;
return true;
}
public bool TryGetPlaybackScale(string resourceKey, float targetDurationSeconds,
out float durationScale, out string error)
{
durationScale = 1f;
if (!IsFinite(targetDurationSeconds) || targetDurationSeconds <= 0f)
{
error = "A positive finite target duration is required.";
return false;
}
int expectedCount = DefenseTowerArt.ExpectedFrameCount(resourceKey);
Sprite[] frames = DefenseTowerArt.Load(resourceKey);
if (expectedCount <= 0 || frames == null || frames.Length != expectedCount)
{
error = $"Resource '{resourceKey}' resolved {frames?.Length ?? 0} frames; expected {expectedCount}.";
return false;
}
float sourceDuration = 0f;
for (int i = 0; i < frames.Length; i++)
sourceDuration += DefenseTowerArt.FrameSeconds(resourceKey, i);
if (!IsFinite(sourceDuration) || sourceDuration <= 0f)
{
error = $"Resource '{resourceKey}' has no positive authored frame duration.";
return false;
}
durationScale = targetDurationSeconds / sourceDuration;
error = null;
return true;
}
private static bool ValidateResource(string resourceKey, string displayName, out string error)
{
if (string.IsNullOrWhiteSpace(resourceKey))
{
error = $"{displayName} resource key is required.";
return false;
}
int expectedCount = DefenseTowerArt.ExpectedFrameCount(resourceKey);
Sprite[] frames = DefenseTowerArt.Load(resourceKey);
if (expectedCount <= 0 || frames == null || frames.Length != expectedCount)
{
error = $"{displayName} resource '{resourceKey}' resolved {frames?.Length ?? 0} frames; expected {expectedCount}.";
return false;
}
error = null;
return true;
}
private static bool ValidateStyle(Defense25DFacilityEffectStyle style, string name, out string error)
{
if (style == null)
{
error = $"{name} style is required.";
return false;
}
return style.TryValidate(name, out error);
}
private static bool IsFinite(float value) => !float.IsNaN(value) && !float.IsInfinity(value);
}
}