Files
crtr/Assets/Cryville/Crtr/Skin/SkinDefinition.cs

145 lines
3.5 KiB
C#

using Cryville.Common;
using Cryville.Common.Collections.Generic;
using Cryville.Common.Pdt;
using Cryville.Crtr.Extension;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Cryville.Crtr.Skin {
public class SkinDefinition : MetaInfo {
public const long CURRENT_FORMAT = 2;
[JsonRequired]
public long format;
public string @base;
[JsonRequired]
public string ruleset;
public List<string> frames = new();
[JsonIgnore]
public PdtSkin Root { get; private set; }
public void LoadPdt(DirectoryInfo dir) {
using StreamReader pdtreader = new(Path.Combine(dir.FullName, data + ".pdt"), Encoding.UTF8);
var src = pdtreader.ReadToEnd();
var interpreter = new SkinInterpreter(src, null);
var format = interpreter.GetFormatVersion();
if (format.Length == 1) {
Root = new PdtSkin {
elements = (SkinElement)new SkinInterpreter(src, new PdtBinder()).Interpret(typeof(SkinElement))
};
}
else {
Root = format[1] switch {
1 => (PdtSkin)new SkinInterpreter(src, new PdtBinder()).Interpret(typeof(PdtSkin)),
_ => throw new NotSupportedException("Unsupported skin format"),
};
}
}
}
public class PdtSkin {
public Dictionary<Identifier, AnimationSpan> animations
= new();
public Dictionary<Identifier, EffectDefinition> effects
= new();
public SkinElement elements;
public void Optimize(PdtEvaluator etor) {
foreach (var a in animations) {
a.Value.Optimize(etor);
}
foreach (var e in effects) {
var effect = e.Value;
etor.ContextCascadeInsert();
etor.ContextCascadeUpdate(EffectInstance._VAR_EFFECT_INDEX, PropSrc.Error);
foreach(var s in effect.states) {
etor.Optimize(s.Value.duration);
}
effect.elements.Optimize(etor);
etor.ContextCascadeDiscard();
}
elements.Optimize(etor);
}
}
public class SkinElement {
[ElementList]
public PairList<SkinSelectors, SkinElement> elements
= new();
[PropertyList]
public PairList<SkinPropertyKey, PdtExpression> properties
= new();
public bool IsDynamic {
get;
private set;
}
public void Optimize(PdtEvaluatorBase etor) {
IsDynamic = true;
foreach (var e in properties) {
etor.Optimize(e.Value);
if (!e.Value.IsConstant)
IsDynamic = true;
}
foreach (var e in elements) {
e.Key.Optimize(etor);
e.Value.Optimize(etor);
if (e.Value.IsDynamic)
IsDynamic = true;
}
}
}
public class EffectDefinition {
static readonly Identifier _ident_init = new("<init>");
#pragma warning disable IDE1006
public PdtExpression duration {
set {
if (!states.TryGetValue(_ident_init, out EffectState s))
throw new InvalidOperationException("Cannot set duration and states at the same time");
s.duration = value;
}
}
#pragma warning restore IDE1006
public Identifier init = _ident_init;
public Dictionary<Identifier, EffectState> states = new() {
{ _ident_init, new EffectState() { rewind = _ident_init } }
};
public SkinElement elements;
}
public class EffectState {
public PdtExpression duration;
public Identifier rewind;
public Identifier next;
}
public class AnimationSpan {
[ElementList]
public PairList<Clip, AnimationSpan> spans
= new();
[PropertyList]
public PairList<SkinPropertyKey, PdtExpression> properties
= new();
public void Optimize(PdtEvaluator etor) {
foreach (var p in properties) {
etor.Optimize(p.Value);
}
foreach (var e in spans) {
e.Value.Optimize(etor);
}
}
}
}