ProjectDDD/Assets/_Datas/SLShared/SLUnity/UnitSytem/UI/UIUnit.cs
2025-06-17 20:47:57 +09:00

404 lines
14 KiB (Stored with Git LFS)
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.UI;
namespace Superlazy.UI
{
[RequireComponent(typeof(RawImage))]
public class SLUIUnit : SLUIComponent
{
public bool useRawUnit = false;
public string unitBind = "UnitBind";
public string renderCamPreset = "Default";
public string bindingAction;
public string bindingEffects;
private SLUIUnitObject unitObject;
private string currentUnitBind;
private RawImage rawImage;
protected override void Validate()
{
rawImage = GetComponent<RawImage>();
rawImage.color = Color.clear;
}
protected override void Init()
{
}
public void Update()
{
if (unitObject == null) return;
unitObject.Update();
}
protected override void Enable()
{
SLGame.AddNotify(bindParent.BindPath.CombinePath(unitBind), OnChange);
if (string.IsNullOrEmpty(bindingAction) == false)
{
SLGame.AddNotify(bindParent.BindPath.CombinePath(bindingAction), OnChange);
}
if (string.IsNullOrEmpty(bindingEffects) == false)
{
SLGame.AddNotify(bindParent.BindPath.CombinePath(bindingEffects), OnChange);
}
}
protected override void Disable()
{
RemoveUnit();
SLGame.RemoveNotify(bindParent.BindPath.CombinePath(unitBind), OnChange);
if (string.IsNullOrEmpty(bindingAction) == false)
{
SLGame.RemoveNotify(bindParent.BindPath.CombinePath(bindingAction), OnChange);
}
if (string.IsNullOrEmpty(bindingEffects) == false)
{
SLGame.RemoveNotify(bindParent.BindPath.CombinePath(bindingEffects), OnChange);
}
}
private void OnChange()
{
if (bindParent.Active == false) return;
var sessionRoot = SLGame.SessionGet(bindParent.BindPath);
if (sessionRoot == false) return; // TEMP: 세션루트가 삭제되었지만, 삭제되되기전 코루틴 처리가 있을 수 있음
if (currentUnitBind != SLGame.SessionGet(bindParent.BindPath.CombinePath(unitBind)))
{
RemoveUnit();
if (useRawUnit)
{
AddUnit(unitBind);
}
else if (SLGame.SessionGet(bindParent.BindPath.CombinePath(unitBind)) != false)
{
AddUnit(SLGame.SessionGet(bindParent.BindPath.CombinePath(unitBind)));
}
}
if (unitObject != null && string.IsNullOrEmpty(bindingAction) == false && SLGame.SessionGet(bindParent.BindPath.CombinePath(bindingAction)))
{
var action = SLGame.SessionGet(bindParent.BindPath.CombinePath(bindingAction));
unitObject.SetAction(action);
SLGame.SessionGet(bindParent.BindPath).Set(bindingAction, false);
}
if (unitObject != null && string.IsNullOrEmpty(bindingEffects) == false && SLGame.SessionGet(bindParent.BindPath.CombinePath(bindingEffects)))
{
var effects = SLGame.SessionGet(bindParent.BindPath.CombinePath(bindingEffects));
unitObject.MakeEffects(effects);
SLGame.SessionGet(bindParent.BindPath).Set(bindingEffects, false);
}
}
public void AddUnit(string bind)
{
if (SLSystem.Data["Units"].HasChild(bind) == false) return;
currentUnitBind = bind;
unitObject = SLUIUnitObject.MakeSLUIUnitObject(renderCamPreset, currentUnitBind);
rawImage.texture = unitObject.texture;
rawImage.color = Color.white;
}
public void RemoveUnit()
{
if (unitObject == null) return;
rawImage.texture = null;
rawImage.color = Color.clear;
SLUIUnitObject.RemoveSLUIUnitObject(unitObject);
unitObject = null;
currentUnitBind = null;
}
}
public class SLUIUnitObject : IZoneView
{
private static int unitHandle = 0;
public Transform root;
public Transform unitRoot;
public Camera cam;
public Texture texture;
public int handle;
public bool useLightMap;
public float outline;
private UnitView unit;
private readonly string baseAction;
private readonly string settingID;
public Vector2 WorldOffset => Vector2.zero;
public float WorldScale => 1;
public bool UseSceneLight => useLightMap;
public float Outline => outline;
public int Layer => LayerMask.NameToLayer("SLUIUnit");
public Transform Root => unitRoot;
public SLEntity Entity => SLGame.Session["UIUnit"][handle];
public float WorldHeight => 0;
public SLEntity EntityView => SLGame.Session["UIUnit"][handle];
private static Dictionary<string, Queue<SLUIUnitObject>> unused;
private readonly List<string> effects = new List<string>();
public static SLUIUnitObject MakeSLUIUnitObject(string renderCamPreset, string currentUnitBind)
{
SLUIUnitObject inst;
if (unused == null || unused.ContainsKey(renderCamPreset) == false || unused[renderCamPreset].Count == 0)
{
inst = new SLUIUnitObject(renderCamPreset, unitHandle);
unitHandle += 1;
}
else
{
inst = unused[renderCamPreset].Dequeue();
}
inst.Init(currentUnitBind);
return inst;
}
public static void RemoveSLUIUnitObject(SLUIUnitObject unitObject)
{
unused ??= new Dictionary<string, Queue<SLUIUnitObject>>();
if (unused.ContainsKey(unitObject.settingID) == false)
{
unused.Add(unitObject.settingID, new Queue<SLUIUnitObject>());
}
unitObject.Destroy();
unused[unitObject.settingID].Enqueue(unitObject);
}
public SLUIUnitObject(string renderCamPreset, int unitHandle)
{
settingID = renderCamPreset;
var setting = SLSystem.Data["SLUIUnitCameraSettings"][settingID];
handle = unitHandle;
root = new GameObject($"SLUI{unitHandle}").transform;
root.SetParent(SLUIRoot.t, false);
root.localPosition = 10 * unitHandle * Vector3.right;
unitRoot = new GameObject("UnitRoot").transform;
unitRoot.SetParent(root, false);
unitRoot.localPosition = Vector3.zero;
var resolution = 2048;
if (setting["Resolution"])
{
resolution = setting["Resolution"];
}
var renderTexture = new RenderTexture(resolution, resolution, 16, RenderTextureFormat.ARGB32);
renderTexture.Create();
texture = renderTexture;
var go = new GameObject("UnitCamera");
go.transform.SetParent(root, false);
cam = go.AddComponent<Camera>();
cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = Vector4.zero;
cam.useOcclusionCulling = true;
var cameraData = go.AddComponent<UniversalAdditionalCameraData>();
cameraData.antialiasing = AntialiasingMode.SubpixelMorphologicalAntiAliasing;
cameraData.antialiasingQuality = AntialiasingQuality.High;
cameraData.volumeLayerMask = LayerMask.GetMask("SLUIUnit");
cam.targetTexture = renderTexture;
cam.cullingMask = LayerMask.GetMask("SLUIUnit");
baseAction = setting["BaseAction"];
cam.orthographic = setting["Projection"] == "Orthographic";
if (cam.orthographic)
{
cam.orthographicSize = setting["Size"];
}
else
{
cam.fieldOfView = setting["fieldOfView"];
}
cameraData.renderPostProcessing = setting["PostProcessing"];
useLightMap = setting["UseLightMap"];
outline = setting["Outline"];
}
private void Init(string currentUnitBind)
{
root.gameObject.SetActive(true);
var setting = SLSystem.Data["SLUIUnitCameraSettings"][settingID];
SLGame.Session["UIUnit"][handle] = SLSystem.Data["Units"][currentUnitBind].Override();
var unitEntity = SLGame.Session["UIUnit"][handle];
var action = baseAction;
if (setting["TriggerAction"])
{
action = setting["TriggerAction"];
}
unitEntity["CurrentAction"] = unitEntity.GetAction(action);
unitEntity["Handle"] = "Unit";
if (setting["AttachEffects"])
{
unitEntity["AttachEffects"] = setting["AttachEffects"];
}
unit = UnitView.MakeUnit(this, SLGame.Session["UIUnit"][handle]);
unitRoot.localRotation = Quaternion.Euler(setting["UnitAngle"].ToVector3());
var uiUnitOffset = setting["UIUnitCustom"] ? new Vector3(0, -unit.Entity["UIUnitHeight"], 0) : Vector3.zero;
if (setting["UIUnitCustom"])
{
if (unit.Entity["UIUnitScale"])
{
unit.transform.localScale = unit.Entity["UIUnitScale"].ToVector3();
}
if (unit.Entity["UIUnitRotation"])
{
unit.Entity["Forward"] = (Quaternion.Euler(unit.Entity["UIUnitRotation"].ToVector3()) * Vector3.forward).ToEntity();
}
}
cam.transform.localPosition = setting["CameraOffset"].ToVector3();
cam.transform.LookAt(unit.transform.position + setting["UnitOffset"].ToVector3() + uiUnitOffset, Vector3.up);
foreach (var effect in effects)
{
EffectView.RemoveEffect(effect);
}
effects.Clear();
}
private void Destroy()
{
UnitView.RemoveUnit(unit);
unit = null;
SLGame.Session["UIUnit"][handle] = false;
root.gameObject.SetActive(false);
}
public void Update()
{
if (unit.Entity["CurrentAction"]["Frame"])
{
var currentAction = unit.Entity["CurrentAction"];
int oldFrame = currentAction["OldFrame"];
currentAction["CurrentFrame"] += Time.deltaTime * 60;
if (unit.Entity["CurrentAction"].HasChild("Messages"))
{
var frameDiff = currentAction["CurrentFrame"] - oldFrame;
for (var i = 1; i <= frameDiff; i++)
{
var frame = i + oldFrame;
if (currentAction.HasChild("Loop") && currentAction.HasChild("Frame") && frame > currentAction["Frame"])
{
int actionFrame = currentAction["Frame"];
currentAction["MessageIndex"] = 1;
currentAction["OldFrame"] -= actionFrame;
currentAction["CurrentFrame"] -= actionFrame;
frame -= actionFrame;
oldFrame -= actionFrame;
}
while (currentAction["Messages"].HasChild(currentAction["MessageIndex"])
&& currentAction["Messages"][currentAction["MessageIndex"]]["Frame"] == frame)
{
var messageContext = currentAction["Messages"][currentAction["MessageIndex"]];
unit.SendMessage(messageContext["Message"], messageContext, SendMessageOptions.DontRequireReceiver);
currentAction["MessageIndex"] += 1;
}
}
}
currentAction["OldFrame"] = currentAction["CurrentFrame"];
if (currentAction.HasChild("Loop") == false && unit.Entity["CurrentAction"]["CurrentFrame"] >= unit.Entity["CurrentAction"]["Frame"])
{
SetAction(baseAction);
}
}
}
public UnitView GetUnit(int handle)
{
return unit;
}
public void SetAction(string action)
{
unit.Entity["CurrentAction"] = false;
string actionID;
if (unit.Entity["Actions"][action])
{
unit.Entity["CurrentAction"] = SLSystem.Data["Actions"][unit.Entity["Actions"][action]].Override();
actionID = unit.Entity["Actions"][action];
}
else if (unit.Entity["CommonAction"] && SLSystem.Data["CommonActions"][action])
{
unit.Entity["CurrentAction"] = SLSystem.Data["Actions"][SLSystem.Data["CommonActions"][action]].Override();
actionID = SLSystem.Data["CommonActions"][action];
}
else
{
return;
}
unit.Entity["CurrentAction"]["MessageIndex"] = 1;
unit.Entity["CurrentAction"]["CurrentFrame"] = 0;
unit.Entity["CurrentAction"]["OldFrame"] = 0;
unit.Entity["CurrentAction"]["ActionID"] = actionID;
}
public void MakeEffects(SLEntity effects)
{
foreach (var effect in this.effects)
{
EffectView.RemoveEffect(effect);
}
this.effects.Clear();
if (effects["Clear"]) return;
foreach (var effect in effects)
{
this.effects.Add(effect["EffectID"]);
unit.SendMessage("Effect", effect, SendMessageOptions.DontRequireReceiver);
}
}
}
}