404 lines
14 KiB (Stored with Git LFS)
C#
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);
|
|
}
|
|
}
|
|
}
|
|
} |