B:BD[
3.2503] → [
4.6737:14929]
#nullable enable
namespace TagFighter
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using TagFighter.Resources;
using UnityEngine;
[ProvideSourceInfo]
[Serializable]
public class EffectSystem : IEffectSystem
{
// ParticleSystem _rippleOutVfx;
[SerializeField] Effects.EffectColors? _colorMapping;
const string PulseMaterial = "Materials/PulseMaterial2";
class EffectRunner : MonoBehaviour
{
public GameObject? EffectObj;
public Material? Material;
public float PlayTime;
public void Run(GameObject effectObj, Material material, float playTime) {
EffectObj = effectObj;
Material = material;
PlayTime = playTime;
Material.SetFloat("_Phase", 0);
EffectObj.SetActive(true);
StartCoroutine(PlayEffect(material, PlayTime));
}
public IEnumerator PlayEffect(Material material, float playTime) {
float totalTime = 0;
float phase = 0;
while (phase < 0.98) {
totalTime += Time.deltaTime;
phase = totalTime / playTime;
material.SetFloat("_Phase", phase);
yield return null;
}
Destroy(EffectObj);
}
}
public EffectSystem() {
}
public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, IAreaOfEffect areaOfEffect) {
switch (areaOfEffect) {
case SingleTarget: ApplyTagsEffectSingle(); break;
case CircleArea aoe: ApplyTagsEffectRadius(tags, origin, direction, aoe); break;
case ConeArea aoe: ApplyTagsEffectCone(tags, origin, direction, aoe); break;
case PathArea aoe: ApplyTagsEffectPath(tags, origin, direction, aoe); break;
}
}
public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, EffectTarget effectLocation, IAreaOfEffect areaOfEffect) {
var directionVector = (effectLocation.Transform.position - origin.Transform.position).normalized;
directionVector.y = 0;
var direction = Quaternion.LookRotation(directionVector, Vector3.up);
ApplyTagsEffect(tags, origin, direction, areaOfEffect);
}
void ApplyTagsEffectSingle() {
Debug.Log("ApplyTagsEffectSingle");
}
void ApplyTagsEffectPath(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, PathArea areaOfEffect) {
var color = GetEffectColor(tags);
var mesh = CreateQuadMeshForUnit(origin.Transform, areaOfEffect.Width, areaOfEffect.Length);
// Add a new to clone the shared resource
Material material = new(UnityEngine.Resources.Load<Material>(PulseMaterial));
material.SetColor("_Color", color);
DisplayEffect(origin, direction, mesh, material);
}
void ApplyTagsEffectRadius(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, CircleArea areaOfEffect) {
var color = GetEffectColor(tags);
var mesh = CreateArcMeshForUnit(origin.Transform, 360, areaOfEffect.Radius);
// Add a new to clone the shared resource
Material material = new(UnityEngine.Resources.Load<Material>(PulseMaterial));
material.SetColor("_Color", color);
DisplayEffect(origin, direction, mesh, material);
}
void ApplyTagsEffectCone(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, ConeArea areaOfEffect) {
Debug.Log("ApplyTagsEffectCone");
var color = GetEffectColor(tags);
var mesh = CreateArcMeshForUnit(origin.Transform, areaOfEffect.Angle, areaOfEffect.Radius);
// Add a new to clone the shared resource
Material material = new(UnityEngine.Resources.Load<Material>(PulseMaterial));
material.SetColor("_Color", color);
DisplayEffect(origin, direction, mesh, material);
}
public Color GetEffectColor(IEnumerable<(Type, IUnit)> tags) {
Debug.Log("GetEffectColor");
var color = new Color();
Debug.Log($"GetEffectColor length {tags.Count()}");
if (_colorMapping != null) {
foreach (var tag in tags) {
Debug.Log("GetEffectColor tag");
if (_colorMapping.ContainsKey(tag.Item1)) {
Debug.Log("GetEffectColor mapping found");
var mappedColor = _colorMapping[tag.Item1];
// TODO: scale color by amount
color += mappedColor;
}
}
}
Debug.Log("GetEffectColor Finished");
return color;
}
public Mesh CreateArcMeshForUnit(Transform unit, float arc, float length, int numberOfVerticesInArc = 100) {
return CreateArcMesh(arc, length, numberOfVerticesInArc, Vector3.up);
}
public Mesh CreateQuadMeshForUnit(Transform unit, float width, float length) {
return CreateQuadMesh(width, length, Vector3.up);
}
void DisplayEffect(EffectOrigin originUnit, Quaternion direction, Mesh mesh, Material material) {
GameObject effectObj = new();
effectObj.SetActive(false);
effectObj.transform.position = originUnit.Transform.position;
effectObj.transform.rotation = direction;
var meshRenderer = effectObj.AddComponent<MeshRenderer>();
meshRenderer.sharedMaterial = material;
meshRenderer.shadowCastingMode = 0;
meshRenderer.receiveShadows = false;
var meshFilter = effectObj.AddComponent<MeshFilter>();
meshFilter.mesh = mesh;
effectObj.AddComponent<EffectRunner>();
var effectRunner = effectObj.GetComponent<EffectRunner>();
effectRunner.Run(effectObj, material, 1f);
}
public Mesh CreateArcMesh(float arc, float length, int numberOfVerticesInArc, Vector3 rotationAxis) {
var origin = Vector3.zero;
var direction = Vector3.forward;
Mesh mesh = new();
var n = numberOfVerticesInArc + 1;
var arcStep = arc / (n - 2);
var currentDegrees = -arc / 2;
var vertices = new Vector3[n];
var uv = new Vector2[n];
vertices[0] = origin;
uv[0] = origin;
for (var i = 1; i < n; i++) {
vertices[i] = Quaternion.AngleAxis(currentDegrees, rotationAxis) * direction * length;
uv[i] = new Vector2(0, 1);
//Debug.Log($"Current Degrees: {currentDegrees} -> {vertices[i]}");
currentDegrees += arcStep;
}
mesh.vertices = vertices;
mesh.uv = uv;
var tris = new int[(n - 2) * 3];
for (var i = 0; i < n - 2; i++) {
tris[i * 3] = 0;
tris[i * 3 + 1] = i + 1;
tris[i * 3 + 2] = i + 2;
}
mesh.triangles = tris;
var normals = new Vector3[n];
for (var i = 0; i < n; i++) {
normals[i] = rotationAxis;
}
mesh.normals = normals;
return mesh;
}
public Mesh CreateQuadMesh(float width, float length, Vector3 rotationAxis) {
Mesh mesh = new();
var origin = Vector3.zero;
// TODO: how to calculate local rotation? direction
var vertices
#nullable enable
namespace TagFighter
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using TagFighter.Resources;
using UnityEngine;
[ProvideSourceInfo]
[Serializable]
public class EffectSystem : IEffectSystem
{
// ParticleSystem _rippleOutVfx;
[SerializeField] Effects.EffectColors? _colorMapping;
const string PulseMaterial = "Materials/PulseMaterial2";
const string PhaseProperty = "_Phase";
const string ColorProperty = "_Color";
class EffectRunner : MonoBehaviour
{
public GameObject? EffectObj;
public Material? Material;
public float PlayTime;
public void Run(GameObject effectObj, Material material, float playTime) {
EffectObj = effectObj;
Material = material;
PlayTime = playTime;
Material.SetFloat(PhaseProperty, 0);
EffectObj.SetActive(true);
StartCoroutine(PlayEffect(material, PlayTime));
}
public IEnumerator PlayEffect(Material material, float playTime) {
float totalTime = 0;
float phase = 0;
while (phase < 0.98) {
totalTime += Time.deltaTime;
phase = totalTime / playTime;
material.SetFloat(PhaseProperty, phase);
yield return null;
}
Destroy(EffectObj);
}
}
public EffectSystem() {
}
public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, IAreaOfEffect areaOfEffect) {
switch (areaOfEffect) {
case SingleTarget: ApplyTagsEffectSingle(); break;
case CircleArea aoe: ApplyTagsEffectRadius(tags, origin, direction, aoe); break;
case ConeArea aoe: ApplyTagsEffectCone(tags, origin, direction, aoe); break;
case PathArea aoe: ApplyTagsEffectPath(tags, origin, direction, aoe); break;
}
}
public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, EffectTarget effectLocation, IAreaOfEffect areaOfEffect) {
var directionVector = (effectLocation.Transform.position - origin.Transform.position).normalized;
directionVector.y = 0;
var direction = Quaternion.LookRotation(directionVector, Vector3.up);
ApplyTagsEffect(tags, origin, direction, areaOfEffect);
}
void ApplyTagsEffectSingle() {
Debug.Log("ApplyTagsEffectSingle");
}
void ApplyTagsEffectPath(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, PathArea areaOfEffect) {
var color = GetEffectColor(tags);
var mesh = CreateQuadMeshForUnit(areaOfEffect.Width, areaOfEffect.Length);
// Add a new to clone the shared resource
Material material = new(UnityEngine.Resources.Load<Material>(PulseMaterial));
material.SetColor(ColorProperty, color);
DisplayEffect(origin, direction, mesh, material);
}
void ApplyTagsEffectRadius(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, CircleArea areaOfEffect) {
var color = GetEffectColor(tags);
var mesh = CreateArcMeshForUnit(360, areaOfEffect.Radius);
// Add a new to clone the shared resource
Material material = new(UnityEngine.Resources.Load<Material>(PulseMaterial));
material.SetColor(ColorProperty, color);
DisplayEffect(origin, direction, mesh, material);
}
void ApplyTagsEffectCone(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, ConeArea areaOfEffect) {
Debug.Log("ApplyTagsEffectCone");
var color = GetEffectColor(tags);
var mesh = CreateArcMeshForUnit(areaOfEffect.Angle, areaOfEffect.Radius);
// Add a new to clone the shared resource
Material material = new(UnityEngine.Resources.Load<Material>(PulseMaterial));
material.SetColor(ColorProperty, color);
DisplayEffect(origin, direction, mesh, material);
}
public Color GetEffectColor(IEnumerable<(Type, IUnit)> tags) {
Debug.Log("GetEffectColor");
var color = new Color();
Debug.Log($"GetEffectColor length {tags.Count()}");
if (_colorMapping != null) {
foreach (var tag in tags) {
Debug.Log("GetEffectColor tag");
if (_colorMapping.ContainsKey(tag.Item1)) {
Debug.Log("GetEffectColor mapping found");
var mappedColor = _colorMapping[tag.Item1];
// TODO: scale color by amount
color += mappedColor;
}
}
}
Debug.Log("GetEffectColor Finished");
return color;
}
public Mesh CreateArcMeshForUnit(float arc, float length, int numberOfVerticesInArc = 100) {
return CreateArcMesh(arc, length, numberOfVerticesInArc, Vector3.up);
}
public Mesh CreateQuadMeshForUnit(float width, float length) {
return CreateQuadMesh(width, length, Vector3.up);
}
void DisplayEffect(EffectOrigin originUnit, Quaternion direction, Mesh mesh, Material material) {
GameObject effectObj = new();
effectObj.SetActive(false);
effectObj.transform.position = originUnit.Transform.position;
effectObj.transform.rotation = direction;
var meshRenderer = effectObj.AddComponent<MeshRenderer>();
meshRenderer.sharedMaterial = material;
meshRenderer.shadowCastingMode = 0;
meshRenderer.receiveShadows = false;
var meshFilter = effectObj.AddComponent<MeshFilter>();
meshFilter.mesh = mesh;
effectObj.AddComponent<EffectRunner>();
var effectRunner = effectObj.GetComponent<EffectRunner>();
effectRunner.Run(effectObj, material, 1f);
}
public Mesh CreateArcMesh(float arc, float length, int numberOfVerticesInArc, Vector3 rotationAxis) {
var origin = Vector3.zero;
var direction = Vector3.forward;
Mesh mesh = new();
var n = numberOfVerticesInArc + 1;
var arcStep = arc / (n - 2);
var currentDegrees = -arc / 2;
var vertices = new Vector3[n];
var uv = new Vector2[n];
vertices[0] = origin;
uv[0] = origin;
for (var i = 1; i < n; i++) {
vertices[i] = Quaternion.AngleAxis(currentDegrees, rotationAxis) * direction * length;
uv[i] = new Vector2(0, 1);
//Debug.Log($"Current Degrees: {currentDegrees} -> {vertices[i]}");
currentDegrees += arcStep;
}
mesh.vertices = vertices;
mesh.uv = uv;
var tris = new int[(n - 2) * 3];
for (var i = 0; i < n - 2; i++) {
tris[i * 3] = 0;
tris[i * 3 + 1] = i + 1;
tris[i * 3 + 2] = i + 2;
}
mesh.triangles = tris;
var normals = new Vector3[n];
for (var i = 0; i < n; i++) {
normals[i] = rotationAxis;
}
mesh.normals = normals;
return mesh;
}
public Mesh CreateQuadMesh(float width, float length, Vector3 rotationAxis) {
Mesh mesh = new();
var origin = Vector3.zero;
// TODO: how to calculate local rotation? direction
var vertices