Refactor SkinPropertyKey.

This commit is contained in:
2023-01-27 15:31:51 +08:00
parent d0f0c8ce6d
commit feffbaa5a6
5 changed files with 161 additions and 85 deletions

View File

@@ -1,13 +1,8 @@
using Cryville.Common;
using Cryville.Common.Pdt;
using Cryville.Crtr.Browsing;
using Cryville.Crtr.Components;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
namespace Cryville.Crtr {
@@ -37,7 +32,6 @@ namespace Cryville.Crtr {
public class PdtSkin : SkinElement { }
[Binder(typeof(SkinElementBinder))]
public class SkinElement {
[ElementList]
public Dictionary<SkinSelectors, SkinElement> elements
@@ -67,36 +61,4 @@ namespace Cryville.Crtr {
}
}
}
public struct SkinPropertyKey {
public Type Component;
public int Name;
}
public class SkinElementBinder : EmptyBinder {
public override object ChangeType(object value, Type type, CultureInfo culture) {
if (value is string && type == typeof(SkinPropertyKey)) {
var cp = ((string)value).Split('.');
switch (cp.Length) {
case 1:
var key = cp[0];
if (key[0] == '*')
return new SkinPropertyKey { Component = GetComponentByName(key.Substring(1)) };
else
return new SkinPropertyKey { Component = typeof(TransformInterface), Name = IdentifierManager.SharedInstance.Request(key) };
case 2:
return new SkinPropertyKey { Component = GetComponentByName(cp[0]), Name = IdentifierManager.SharedInstance.Request(cp[1]) };
}
}
return base.ChangeType(value, type, culture);
}
static readonly char[] nssep = new char[]{':'};
Type GetComponentByName(string name) {
var nstuple = name.Split(nssep, 2);
var ns = nssep.Length == 2 ? nstuple[0] : "generic";
name = nssep.Length == 2 ? nstuple[1] : nstuple[0];
if (ns == "generic")
return GenericResources.Components[name];
throw new ArgumentException(string.Format("Component type {0} not found", name));
}
}
}

View File

@@ -1,8 +1,5 @@
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;
@@ -38,14 +35,10 @@ namespace Cryville.Crtr {
ChartPlayer.etor.ContextTransform = rc.Transform;
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeInsert(rc.PropSrcs);
foreach (var p in rel.properties) {
if (p.Key.Name == 0)
rc.Transform.gameObject.AddComponent(p.Key.Component);
else {
ChartPlayer.etor.Evaluate(GetPropOp(ctx.WriteTransform, p.Key).Operator, p.Value);
if (!p.Value.IsConstant) dynprops.Add(
new DynamicProperty { Context = ctx, Key = p.Key, Value = p.Value }
);
}
p.Key.ExecuteStatic(state, ctx, p.Value);
if (p.Key.IsValueRequired && !p.Value.IsConstant) dynprops.Add(
new DynamicProperty { Context = ctx, Key = p.Key, Value = p.Value }
);
}
ChartPlayer.etor.ContextTransform = null;
foreach (var r in rel.elements) {
@@ -73,12 +66,7 @@ namespace Cryville.Crtr {
ChartPlayer.etor.ContextEvent = state.Container;
for (int i = 0; i < dynprops.Count; i++) {
DynamicProperty p = dynprops[i];
var psrcs = p.Context.ReadContext.PropSrcs;
if (psrcs != null) ChartPlayer.etor.ContextCascadeInsert(psrcs);
var prop = GetPropOp(p.Context.WriteTransform, p.Key);
if (state.CloneType > prop.UpdateCloneType) continue;
ChartPlayer.etor.Evaluate(prop.Operator, p.Value);
if (psrcs != null) ChartPlayer.etor.ContextCascadeDiscard();
p.Key.ExecuteDynamic(state, p.Context, p.Value);
}
for (int i = 0; i < dynelems.Count; i++) {
DynamicElement e = dynelems[i];
@@ -99,11 +87,7 @@ namespace Cryville.Crtr {
ChartPlayer.etor.ContextTransform = rc.Transform;
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeInsert(rc.PropSrcs);
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(ctx.WriteTransform, p.Key);
if (state.CloneType > prop.UpdateCloneType) continue;
ChartPlayer.etor.Evaluate(prop.Operator, p.Value);
p.Key.ExecuteDynamic(state, ctx, p.Value);
}
ChartPlayer.etor.ContextTransform = null;
foreach (var r in rel.elements) {
@@ -115,21 +99,6 @@ namespace Cryville.Crtr {
}
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeDiscard();
}
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;
}
}
public class SkinContext {
public Transform Transform { get; private set; }

View File

@@ -1,4 +1,6 @@
using Cryville.Common.Pdt;
using Cryville.Common;
using Cryville.Common.Pdt;
using Cryville.Crtr.Components;
using System;
using System.Collections.Generic;
using System.Reflection;
@@ -8,10 +10,11 @@ namespace Cryville.Crtr {
public SkinInterpreter(string src, Binder binder) : base(src, typeof(PdtSkin), binder) { }
readonly List<SkinSelector> s = new List<SkinSelector>();
readonly List<string> a = new List<string>();
readonly HashSet<string> a = new HashSet<string>();
readonly List<string> k = new List<string>(2);
protected override object InterpretKey(Type type) {
s.Clear(); a.Clear();
string key = "";
s.Clear(); a.Clear(); k.Clear();
bool invalidKeyFlag = false, compKeyFlag = false;
while (true) {
int pp = Position;
switch (cc) {
@@ -22,19 +25,22 @@ namespace Cryville.Crtr {
case '$':
GetChar();
s.Add(new SkinSelector.CreateObject());
key = null;
invalidKeyFlag = true;
break;
case '.':
GetChar();
if (cc == '.') {
GetChar();
s.Add(new SkinSelector.AtAnchor(GetIdentifier()));
key = null;
invalidKeyFlag = true;
}
else {
var p3 = GetIdentifier();
s.Add(new SkinSelector.Anchor(p3));
if (key != null) key += "." + p3;
if (!invalidKeyFlag) {
if (k.Count != 1) invalidKeyFlag = true;
else k.Add(p3);
}
}
break;
case '>':
@@ -43,24 +49,61 @@ namespace Cryville.Crtr {
break;
case ';':
case ':':
return key;
if (invalidKeyFlag) throw new FormatException("Invalid key format");
if (a.Contains("has")) {
if (k.Count != 1) throw new FormatException("Invalid anchor name");
return new SkinPropertyKey.CreateAnchor {
Name = IdentifierManager.SharedInstance.Request(k[0])
};
}
else if (a.Contains("at")) {
if (k.Count != 1) throw new FormatException("Invalid anchor name");
return new SkinPropertyKey.SetAnchor {
Name = IdentifierManager.SharedInstance.Request(k[0])
};
}
switch (k.Count) {
case 1:
if (compKeyFlag) return new SkinPropertyKey.CreateComponent {
Component = GetComponentByName(k[0])
};
else return new SkinPropertyKey.SetProperty {
Component = typeof(TransformInterface),
Name = IdentifierManager.SharedInstance.Request(k[0])
};
case 2:
return new SkinPropertyKey.SetProperty {
Component = GetComponentByName(k[0]),
Name = IdentifierManager.SharedInstance.Request(k[1])
};
default:
throw new FormatException("Unknown error"); // Unreachable
}
case '{':
return new SkinSelectors(s, a);
case '}':
return null;
case '*':
GetChar();
key += "*";
compKeyFlag = true;
break;
default:
var p4 = GetIdentifier();
s.Add(new SkinSelector.ElementType(p4));
if (key != null) key += p4;
if (!invalidKeyFlag) {
if (k.Count != 0) invalidKeyFlag = true;
else k.Add(p4);
}
break;
}
ws();
if (Position == pp) throw new FormatException("Invalid selector or key format");
}
}
static Type GetComponentByName(string name) {
Type result;
if (GenericResources.Components.TryGetValue(name, out result)) return result;
throw new ArgumentException(string.Format("Component type {0} not found", name));
}
}
}

View File

@@ -0,0 +1,91 @@
using Cryville.Common;
using Cryville.Common.Pdt;
using Cryville.Crtr.Components;
using Cryville.Crtr.Event;
using System;
using UnityEngine;
namespace Cryville.Crtr {
public abstract class SkinPropertyKey {
public abstract override string ToString();
public abstract bool IsValueRequired { get; }
public abstract void ExecuteStatic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp);
public abstract void ExecuteDynamic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp);
public class CreateComponent : SkinPropertyKey {
public Type Component { get; set; }
public override string ToString() {
return string.Format("*{0}", Component.Name);
}
public override bool IsValueRequired { get { return false; } }
public override void ExecuteStatic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp) {
ctx.ReadContext.Transform.gameObject.AddComponent(Component);
}
public override void ExecuteDynamic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp) {
throw new InvalidOperationException("Component creation in dynamic context is not allowed");
}
}
public class SetProperty : SkinPropertyKey {
public Type Component { get; set; }
public int Name { get; set; }
public override string ToString() {
return string.Format("{0}.{1}", Component.Name, IdentifierManager.SharedInstance.Retrieve(Name));
}
public override bool IsValueRequired { get { return true; } }
public override void ExecuteStatic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp) {
Execute(ctx, GetPropOp(ctx.WriteTransform).Operator, exp);
}
public override void ExecuteDynamic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp) {
var prop = GetPropOp(ctx.WriteTransform);
if (state.CloneType > prop.UpdateCloneType) return;
Execute(ctx, prop.Operator, exp);
}
void Execute(RuntimeSkinContext ctx, PdtOperator op, PdtExpression exp) {
var psrcs = ctx.ReadContext.PropSrcs;
if (psrcs != null) ChartPlayer.etor.ContextCascadeInsert(psrcs);
ChartPlayer.etor.Evaluate(op, exp);
if (psrcs != null) ChartPlayer.etor.ContextCascadeDiscard();
}
SkinProperty GetPropOp(Transform obj) {
var ctype = 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(Name)
));
SkinProperty result;
if (!comp.Properties.TryGetValue(Name, out result))
throw new InvalidOperationException(string.Format(
"Property {0} not found on component",
IdentifierManager.SharedInstance.Retrieve(Name)
));
return result;
}
}
public class CreateAnchor : SkinPropertyKey {
public int Name { get; set; }
public override string ToString() {
return string.Format("@has {0}", IdentifierManager.SharedInstance.Retrieve(Name));
}
public override bool IsValueRequired { get { return false; } }
public override void ExecuteStatic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp) {
// TODO
}
public override void ExecuteDynamic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp) {
throw new InvalidOperationException("Anchor creation in dynamic context is not allowed");
}
}
public class SetAnchor : SkinPropertyKey {
public int Name { get; set; }
public override string ToString() {
return string.Format("@at {0}", IdentifierManager.SharedInstance.Retrieve(Name));
}
public override bool IsValueRequired { get { return true; } }
public override void ExecuteStatic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp) {
// TODO
}
public override void ExecuteDynamic(ContainerState state, RuntimeSkinContext ctx, PdtExpression exp) {
// TODO
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 701f7f917dc59c540b105732747aeb67
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: