111 lines
3.9 KiB
C#
111 lines
3.9 KiB
C#
using Cryville.Common.Pdt;
|
|
using Cryville.Crtr.Components;
|
|
using Cryville.Crtr.Event;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Profiling;
|
|
|
|
namespace Cryville.Crtr {
|
|
public class SkinContainer {
|
|
readonly PdtSkin skin;
|
|
readonly List<DynamicProperty> dynprops = new List<DynamicProperty>();
|
|
struct DynamicProperty {
|
|
public Transform Anchor { get; set; }
|
|
public SkinPropertyKey Key { get; set; }
|
|
public PdtExpression Value { get; set; }
|
|
}
|
|
readonly List<DynamicElement> dynelems = new List<DynamicElement>();
|
|
struct DynamicElement {
|
|
public Transform Anchor { get; set; }
|
|
public SkinSelectors Selectors { get; set; }
|
|
public SkinElement Element { get; set; }
|
|
}
|
|
public SkinContainer(PdtSkin _skin) {
|
|
skin = _skin;
|
|
}
|
|
public void MatchStatic(ContainerState context) {
|
|
dynprops.Clear(); dynelems.Clear();
|
|
ChartPlayer.etor.ContextState = context;
|
|
ChartPlayer.etor.ContextEvent = context.Container;
|
|
MatchStatic(skin, context, context.Handler.gogroup);
|
|
ChartPlayer.etor.ContextEvent = null;
|
|
ChartPlayer.etor.ContextState = null;
|
|
}
|
|
void MatchStatic(SkinElement rel, ContainerState context, Transform anchor = null) {
|
|
ChartPlayer.etor.ContextTransform = anchor;
|
|
foreach (var p in rel.properties) {
|
|
if (p.Key.Name == null)
|
|
anchor.gameObject.AddComponent(p.Key.Component);
|
|
else {
|
|
ChartPlayer.etor.Evaluate(GetPropOp(anchor, p.Key).Operator, p.Value);
|
|
if (!p.Value.IsConstant) dynprops.Add(
|
|
new DynamicProperty { Anchor = anchor, Key = p.Key, Value = p.Value }
|
|
);
|
|
}
|
|
}
|
|
ChartPlayer.etor.ContextTransform = null;
|
|
foreach (var r in rel.elements) {
|
|
try {
|
|
var new_anchor = r.Key.MatchStatic(context, anchor);
|
|
if (new_anchor != null) {
|
|
MatchStatic(r.Value, context, new_anchor);
|
|
}
|
|
}
|
|
catch (SelectorNotStaticException) {
|
|
dynelems.Add(
|
|
new DynamicElement { Anchor = anchor, Selectors = r.Key, Element = r.Value }
|
|
);
|
|
}
|
|
}
|
|
}
|
|
public void MatchDynamic(ContainerState context) {
|
|
if (dynprops.Count == 0 && dynelems.Count == 0) return;
|
|
Profiler.BeginSample("SkinContainer.MatchDynamic");
|
|
ChartPlayer.etor.ContextState = context;
|
|
ChartPlayer.etor.ContextEvent = context.Container;
|
|
for (int i = 0; i < dynprops.Count; i++) {
|
|
DynamicProperty p = dynprops[i];
|
|
var prop = GetPropOp(p.Anchor, p.Key);
|
|
if (context.CloneType > prop.UpdateCloneType) continue;
|
|
ChartPlayer.etor.Evaluate(prop.Operator, p.Value);
|
|
}
|
|
for (int i = 0; i < dynelems.Count; i++) {
|
|
DynamicElement e = dynelems[i];
|
|
var anchor = e.Selectors.MatchDynamic(context, e.Anchor);
|
|
if (anchor != null) MatchDynamic(e.Element, context, anchor);
|
|
}
|
|
ChartPlayer.etor.ContextEvent = null;
|
|
ChartPlayer.etor.ContextState = null;
|
|
Profiler.EndSample();
|
|
}
|
|
void MatchDynamic(SkinElement rel, ContainerState context, Transform anchor = null) {
|
|
ChartPlayer.etor.ContextTransform = anchor;
|
|
foreach (var p in rel.properties) {
|
|
if (p.Key.Name == null)
|
|
throw new InvalidOperationException("Component creation in dynamic context is not allowed");
|
|
var prop = GetPropOp(anchor, p.Key);
|
|
if (context.CloneType > prop.UpdateCloneType) continue;
|
|
ChartPlayer.etor.Evaluate(prop.Operator, p.Value);
|
|
}
|
|
ChartPlayer.etor.ContextTransform = null;
|
|
foreach (var r in rel.elements) {
|
|
if (!r.Key.IsUpdatable(context)) continue;
|
|
var new_anchor = r.Key.MatchDynamic(context, anchor);
|
|
if (new_anchor != null) {
|
|
MatchDynamic(r.Value, context, new_anchor);
|
|
}
|
|
}
|
|
}
|
|
SkinProperty GetPropOp(Transform obj, SkinPropertyKey key) {
|
|
var ctype = key.Component;
|
|
var comp = (SkinComponent)obj.GetComponent(ctype);
|
|
if (comp == null) throw new InvalidOperationException("Component instance not found");
|
|
SkinProperty result;
|
|
if (!comp.Properties.TryGetValue(key.Name, out result))
|
|
throw new ArgumentException(string.Format("Property {0} not found on component", key.Name));
|
|
return result;
|
|
}
|
|
}
|
|
}
|