using Cryville.Common; using Cryville.Common.Pdt; using Cryville.Crtr.Components; using System; using System.Collections.Generic; using System.Reflection; namespace Cryville.Crtr { public class SkinInterpreter : PdtInterpreter { public SkinInterpreter(string src, Binder binder) : base(src, binder) { } readonly List s = new List(); readonly HashSet a = new HashSet(); readonly List k = new List(2); protected override object InterpretKey(Type type) { if (typeof(SkinElement).IsAssignableFrom(type)) return InterpretSkinElementKey(); else if (typeof(AnimationSpan).IsAssignableFrom(type)) return InterpretAnimationSpanKey(); else return base.InterpretKey(type); } object InterpretSkinElementKey() { s.Clear(); a.Clear(); k.Clear(); bool invalidKeyFlag = false, compKeyFlag = false; while (true) { int pp = Position; switch (cc) { case '@': GetChar(); a.Add(GetIdentifier()); break; case '$': GetChar(); s.Add(new SkinSelector.CreateObject()); invalidKeyFlag = true; break; case '.': GetChar(); if (cc == '.') { GetChar(); s.Add(new SkinSelector.AtAnchor(GetIdentifier())); invalidKeyFlag = true; } else { var p3 = GetIdentifier(); s.Add(new SkinSelector.Anchor(p3)); if (!invalidKeyFlag) { if (k.Count != 1) invalidKeyFlag = true; else k.Add(p3); } } break; case '>': GetChar(); s.Add(new SkinSelector.Property(GetExp())); break; case ';': case ':': 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]) }; } else if (a.Contains("emit")) { if (k.Count != 1) throw new FormatException("Invalid effect name"); return new SkinPropertyKey.EmitEffect { 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 '}': throw new FormatException("Invalid token"); case '*': GetChar(); compKeyFlag = true; break; default: var p4 = GetIdentifier(); s.Add(new SkinSelector.ElementType(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"); } } object InterpretAnimationSpanKey() { if ((ct & 0x0040) != 0 || cc == ',') { float start = 0, end = 1; if (cc != ',') { start = float.Parse(GetNumber()); ws(); if (cc != ',') throw new FormatException("Invalid span format"); } GetChar(); ws(); if (cc != '{') end = float.Parse(GetNumber()); ws(); if (cc != '{') throw new FormatException("Invalid span format"); return new Clip(start, end); } k.Clear(); while (true) { int pp = Position; switch (cc) { case '.': GetChar(); if (k.Count != 1) throw new FormatException("Invalid key format"); k.Add(GetIdentifier()); break; case ';': case ':': switch (k.Count) { case 1: 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 '{': throw new FormatException("Invalid token"); case '}': throw new FormatException("Invalid token"); default: if (k.Count != 0) throw new FormatException("Invalid key format"); k.Add(GetIdentifier()); 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)); } } }