internal static OESChunk Deserialize(OESFile file, BinaryReader br) { var tc = Encoding.ASCII.GetString(br.ReadBytes(4)).TrimEnd(' '); var id = br.ReadUInt32(); var dlen = br.ReadUInt32(); var cdlen = br.ReadUInt32(); var numChildren = br.ReadUInt32(); var epos = br.BaseStream.Position + dlen; OESChunk instance; switch (tc) { case "root": instance = new OESRoot(tc, id); break; case "mat": instance = new OESMaterial(tc, id); break; case "fx": instance = new OESEffect(tc, id); break; case "tex": instance = new OESTexture(tc, id); break; case "zone": instance = new OESZone(tc, id); break; case "regn": instance = new OESRegion(tc, id); break; case "char": instance = new OESCharacter(tc, id); break; case "obj": instance = new OESObject(tc, id); break; case "inst": instance = new OESInstance(tc, id); break; case "lit": instance = new OESLight(tc, id); break; case "skin": instance = new OESSkin(tc, id); break; case "mesh": instance = new OESStaticMesh(tc, id); break; case "aset": instance = new OESAnimationSet(tc, id); break; case "amsh": instance = new OESAnimatedMesh(tc, id); break; case "abuf": instance = new OESAnimationBuffer(tc, id); break; default: instance = new OESChunk(tc, id); break; } file.Add(instance); instance.OESFile = file; instance.DeserializeData(br); Debug.Assert(br.BaseStream.Position <= epos); br.BaseStream.Position = epos; for (var i = 0; i < numChildren; ++i) { instance.Add(Deserialize(file, br)); } Debug.Assert(br.BaseStream.Position == epos + cdlen); return(instance); }
static List <Material> FromSkin(OESSkin skin, ZipArchive zip) => skin.Find <OESMaterial>().Select(mat => { if (mat.Find <OESEffect>().Any(x => x.Name == "fire")) { return(null); // TODO: Unhack } return(new Material( (mat.Transparent ? MaterialFlag.Translucent : MaterialFlag.Normal) | (mat.AlphaMask ? MaterialFlag.Masked : MaterialFlag.Normal), mat.Find <OESEffect>().FirstOrDefault(x => x.Name == "animated")?.Get <uint>("speed") ?? 0, mat.Find <OESTexture>().Select(x => { using (var tzs = zip.GetEntry(x.Filename).Open()) return Png.Decode(tzs); }).ToArray() )); }).ToList();
static List <Material> FromSkin(OESSkin skin, ZipArchive zip) => skin.Find <OESMaterial>().Select(mat => { var effect = mat.Find <OESEffect>().FirstOrDefault(); effect = effect ?? new OESEffect("default"); var textures = mat.Find <OESTexture>().Select(x => { using (var tzs = zip.GetEntry(x.Filename)?.Open()) return(Png.Decode(Path.GetFileName(x.Filename), tzs)); }).ToArray(); switch (effect.Name) { case "default": case "animated": var aniSpeed = effect.Name == "animated" ? (uint)effect["speed"] / 1000f : 0; if (mat.Transparent) { return(mat.AlphaMask ? (Material) new ForwardDiffuseMaskedMaterial(textures, aniSpeed) : new ForwardDiffuseMaterial(textures, aniSpeed)); } else { return(mat.AlphaMask ? (Material) new DeferredDiffuseMaskedMaterial(textures, aniSpeed) : new DeferredDiffuseMaterial(textures, aniSpeed)); } case "diffuse+normal": return(new DeferredDiffuseNormalMaterial(textures)); case "fire": return(new FireMaterial()); default: throw new NotImplementedException($"Unknown OESEffect name: {effect.Name}"); } }).ToList();