using Cryville.Common; 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 dynprops = new List(); struct DynamicProperty { public Transform Anchor { get; set; } public SkinPropertyKey Key { get; set; } public PdtExpression Value { get; set; } } readonly List dynelems = new List(); 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 == 0) 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 == 0) 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(string.Format( "Trying to set property {0} but the component is not found", IdentifierManager.SharedInstance.Retrieve(key.Name) )); SkinProperty result; if (!comp.Properties.TryGetValue(key.Name, out result)) throw new ArgumentException(string.Format( "Property {0} not found on component", IdentifierManager.SharedInstance.Retrieve(key.Name) )); return result; } } }