From fd9e2ce409210e351ee40d3c600fa5c9af0868c8 Mon Sep 17 00:00:00 2001 From: PopSlime Date: Thu, 17 Nov 2022 17:19:31 +0800 Subject: [PATCH] Add frame list in skin data structure. Remove Cocos2d Plist support. --- Assets/Cryville/Common/Plist.meta | 9 - Assets/Cryville/Common/Plist/PlistConvert.cs | 49 - .../Common/Plist/PlistConvert.cs.meta | 12 - Assets/Cryville/Crtr/ChartPlayer.cs | 40 +- Assets/Cryville/Crtr/Cocos2dFrames.cs | 176 ---- .../Cryville/Crtr/Components/SpritePlane.cs | 2 +- Assets/Cryville/Crtr/Skin.cs | 2 + Assets/Cryville/Crtr/SpriteFrame.cs | 109 +++ ...os2dFrames.cs.meta => SpriteFrame.cs.meta} | 0 Assets/PlistCS.meta | 9 - Assets/PlistCS/Src.meta | 9 - Assets/PlistCS/Src/Plist.cs | 838 ------------------ Assets/PlistCS/Src/Plist.cs.meta | 12 - 13 files changed, 127 insertions(+), 1140 deletions(-) delete mode 100644 Assets/Cryville/Common/Plist.meta delete mode 100644 Assets/Cryville/Common/Plist/PlistConvert.cs delete mode 100644 Assets/Cryville/Common/Plist/PlistConvert.cs.meta delete mode 100644 Assets/Cryville/Crtr/Cocos2dFrames.cs create mode 100644 Assets/Cryville/Crtr/SpriteFrame.cs rename Assets/Cryville/Crtr/{Cocos2dFrames.cs.meta => SpriteFrame.cs.meta} (100%) delete mode 100644 Assets/PlistCS.meta delete mode 100644 Assets/PlistCS/Src.meta delete mode 100644 Assets/PlistCS/Src/Plist.cs delete mode 100644 Assets/PlistCS/Src/Plist.cs.meta diff --git a/Assets/Cryville/Common/Plist.meta b/Assets/Cryville/Common/Plist.meta deleted file mode 100644 index 7990dfd..0000000 --- a/Assets/Cryville/Common/Plist.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 925f95cb7c6644a4695b2701d42e1ea2 -folderAsset: yes -timeCreated: 1606989037 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Cryville/Common/Plist/PlistConvert.cs b/Assets/Cryville/Common/Plist/PlistConvert.cs deleted file mode 100644 index c0566c2..0000000 --- a/Assets/Cryville/Common/Plist/PlistConvert.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; - -namespace Cryville.Common.Plist { - public class PlistConvert { - public static T Deserialize(string file) { - return (T)Deserialize(typeof(T), PlistCS.Plist.readPlist(file)); - } - - public static object Deserialize(Type type, object obj, Binder binder = null) { - if (binder == null) - binder = BinderAttribute.CreateBinderOfType(type); - if (obj is IList) { - var lobj = (List)obj; - foreach (var i in lobj) { - throw new NotImplementedException(); // TODO - } - } - else if (obj is IDictionary) { - var dobj = (Dictionary)obj; - if (typeof(IDictionary).IsAssignableFrom(type)) { - var result = (IDictionary)ReflectionHelper.InvokeEmptyConstructor(type); - var it = type.GetGenericArguments()[1]; - foreach (var i in dobj) { - var value = Deserialize(it, i.Value, binder); - result.Add(i.Key, value); - } - return result; - } - else { - var result = ReflectionHelper.InvokeEmptyConstructor(type); - foreach (var i in dobj) { - var imis = type.GetMember(i.Key); - if (imis.Length == 0) continue; - var imi = imis[0]; - var it = ReflectionHelper.GetMemberType(imi); - var value = Deserialize(it, i.Value, binder); - ReflectionHelper.SetValue(imi, result, value, binder); - } - return result; - } - } - else return obj; - throw new Exception(); // TODO - } - } -} diff --git a/Assets/Cryville/Common/Plist/PlistConvert.cs.meta b/Assets/Cryville/Common/Plist/PlistConvert.cs.meta deleted file mode 100644 index 3d43254..0000000 --- a/Assets/Cryville/Common/Plist/PlistConvert.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 3bc71e8b62d4022409aa5518bbf3a7d8 -timeCreated: 1608801352 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Cryville/Crtr/ChartPlayer.cs b/Assets/Cryville/Crtr/ChartPlayer.cs index bb20bce..571c21a 100644 --- a/Assets/Cryville/Crtr/ChartPlayer.cs +++ b/Assets/Cryville/Crtr/ChartPlayer.cs @@ -1,7 +1,6 @@ #define BUILD using Cryville.Common; -using Cryville.Common.Plist; using Cryville.Crtr.Config; using Cryville.Crtr.Event; using Newtonsoft.Json; @@ -26,8 +25,7 @@ namespace Cryville.Crtr { Ruleset ruleset; PdtRuleset pruleset; Dictionary texs; - public static Dictionary frames; - List plists; + public static Dictionary frames; readonly Queue texLoadQueue = new Queue(); #if UNITY_5_4_OR_NEWER @@ -353,6 +351,13 @@ namespace Cryville.Crtr { string.Format("{0}/skins/{1}/{2}/.umgs", Game.GameDataPath, rulesetFile.Directory.Name, _rscfg.generic.Skin) ); if (!skinFile.Exists) throw new FileNotFoundException("Skin not found\nPlease specify an available skin in the config"); + using (StreamReader reader = new StreamReader(skinFile.FullName, Encoding.UTF8)) { + skin = JsonConvert.DeserializeObject(reader.ReadToEnd(), new JsonSerializerSettings() { + MissingMemberHandling = MissingMemberHandling.Error + }); + if (skin.format != 1) throw new FormatException("Invalid skin file version"); + } + loadThread = new Thread(new ParameterizedThreadStart(Load)); loadThread.Start(new LoadInfo() { chartFile = chartFile, @@ -363,10 +368,10 @@ namespace Cryville.Crtr { Logger.Log("main", 0, "Load/MainThread", "Loading textures..."); texloadtimer = new diag::Stopwatch(); texloadtimer.Start(); + frames = new Dictionary(); texs = new Dictionary(); - var flist = skinFile.Directory.GetFiles("*.png"); - foreach (FileInfo f in flist) { - texLoadQueue.Enqueue(f.FullName); + foreach (var f in skin.frames) { + texLoadQueue.Enqueue(Path.Combine(skinFile.Directory.FullName, f)); } } @@ -375,13 +380,12 @@ namespace Cryville.Crtr { diag::Stopwatch timer = new diag::Stopwatch(); timer.Reset(); timer.Start(); Logger.Log("main", 0, "Load/Prehandle", "Prehandling (iteration 3)"); - foreach (var i in plists) i.Init(texs); foreach (var t in texs) { if (frames.ContainsKey(t.Key)) { Logger.Log("main", 3, "Load/Prehandle", "Duplicated texture name: {0}", t.Key); continue; } - var f = new Cocos2dFrames.Frame(t.Value); + var f = new SpriteFrame(t.Value); f.Init(); frames.Add(t.Key, f); } @@ -559,23 +563,9 @@ namespace Cryville.Crtr { void LoadSkin(FileInfo file) { DirectoryInfo dir = file.Directory; Logger.Log("main", 0, "Load/WorkerThread", "Loading skin: {0}", file); - using (StreamReader reader = new StreamReader(file.FullName, Encoding.UTF8)) { - skin = JsonConvert.DeserializeObject(reader.ReadToEnd(), new JsonSerializerSettings() { - MissingMemberHandling = MissingMemberHandling.Error - }); - if (skin.format != 1) throw new FormatException("Invalid skin file version"); - skin.LoadPdt(dir); - pskin = skin.Root; - pskin.Optimize(etor); - } - plists = new List(); - frames = new Dictionary(); - foreach (FileInfo f in file.Directory.GetFiles("*.plist")) { - var pobj = PlistConvert.Deserialize(f.FullName); - plists.Add(pobj); - foreach (var i in pobj.frames) - frames.Add(StringUtils.TrimExt(i.Key), i.Value); - } + skin.LoadPdt(dir); + pskin = skin.Root; + pskin.Optimize(etor); } #endregion } diff --git a/Assets/Cryville/Crtr/Cocos2dFrames.cs b/Assets/Cryville/Crtr/Cocos2dFrames.cs deleted file mode 100644 index 873f5e8..0000000 --- a/Assets/Cryville/Crtr/Cocos2dFrames.cs +++ /dev/null @@ -1,176 +0,0 @@ -using Cryville.Common; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.Text.RegularExpressions; -using UnityEngine; - -namespace Cryville.Crtr { - [BinderAttribute(typeof(Cocos2dFramesBinder))] - public class Cocos2dFrames { - public Metadata metadata; - public class Metadata { - public int format; - public Vector2 size; - public string textureFileName; - } - - public Dictionary frames; - public class Frame { -#pragma warning disable IDE1006 - Rect _frame; - public Rect frame { - get { return _frame; } - set { _frame = value; } - } - public Rect textureRect { - get { return _frame; } - set { _frame = value; } - } - - bool _rotated = false; - public bool rotated { - get { return _rotated; } - set { _rotated = value; } - } - public bool textureRotated { - get { return _rotated; } - set { _rotated = value; } - } -#pragma warning restore IDE1006 - - public Vector2 offset; - - public Rect sourceColorRect; - public Vector2 sourceSize; - private Rect _uv; - private Vector2[] cuv; - public Rect UV { - get { - return _uv; - } - private set { - _uv = value; - float x0 = Mathf.Min(_uv.xMin, _uv.xMax); - float x1 = Mathf.Max(_uv.xMin, _uv.xMax); - float y0 = Mathf.Min(_uv.yMin, _uv.yMax); - float y1 = Mathf.Max(_uv.yMin, _uv.yMax); - if (_rotated) cuv = new Vector2[]{ - new Vector2(x0, y1), - new Vector2(x1, y0), - new Vector2(x0, y0), - new Vector2(x1, y1), - }; - else cuv = new Vector2[]{ - new Vector2(x0, y0), - new Vector2(x1, y1), - new Vector2(x1, y0), - new Vector2(x0, y1), - }; - } - } - public Vector2 GetUV(Vector2 uv) { - return GetUV(uv.x, uv.y); - } - public Vector2 GetUV(float u, float v) { - Vector2 uv00 = cuv[0], uv11 = cuv[1], - uv10 = cuv[2], uv01 = cuv[3]; - return (1 - u - v) * uv00 - + u * uv10 - + v * uv01 - + u * v * (uv00 + uv11 - uv10 - uv01); - } - public Texture2D Texture { - get; - private set; - } - public Vector2 Size { - get { - return new Vector2(Texture.width, Texture.height); - } - } - - public void Init() { - if (Texture == null) - throw new InvalidOperationException(); // TODO - _frame = new Rect(Vector2.zero, Size); - var w = _frame.width; - var h = _frame.height; - float x = _frame.x / w; - float y = 1 - _frame.y / h; - float tw = (_rotated ? _frame.height : _frame.width) / w; - float th = (_rotated ? _frame.width : _frame.height) / h; - if (_rotated) UV = new Rect(x, y, tw, -th); - else UV = new Rect(x, y, tw, -th); - } - - public void Init(int w, int h, Texture2D _base) { - if (Texture != null) - throw new InvalidOperationException(); // TODO - Texture = _base; - float x = _frame.x / w; - float y = 1 - _frame.y / h; - float tw = (_rotated ? _frame.height : _frame.width) / w; - float th = (_rotated ? _frame.width : _frame.height) / h; - if (_rotated) UV = new Rect(x, y, tw, -th); - else UV = new Rect(x, y, tw, -th); - } - public Frame() { } - public Frame(Texture2D tex) { - Texture = tex; - } - } - - Texture2D _base; - - public void Init(Dictionary texs) { - _base = texs[StringUtils.TrimExt(metadata.textureFileName)]; - var w = (int)metadata.size.x; - var h = (int)metadata.size.y; - if (w == 0 || h == 0) { - w = _base.width; - h = _base.height; - } - foreach (var f in frames) { - f.Value.Init(w, h, _base); - } - } - } - - public class Cocos2dFramesBinder : EmptyBinder { - public override object ChangeType(object value, Type type, CultureInfo culture) { - if (value is string) { - var str = (string)value; - if (type == typeof(Rect)) { - var m = Regex.Match(str, @"^{({.*?}),({.*?})}$"); - var p = (Vector2)ChangeType(m.Groups[1].Value, typeof(Vector2), culture); - var s = (Vector2)ChangeType(m.Groups[2].Value, typeof(Vector2), culture); - return new Rect(p, s); - } - else if (type == typeof(Vector2)) { - var m = Regex.Match(str, @"^{(.*?),(.*?)}$"); - var w = float.Parse(m.Groups[1].Value); - var h = float.Parse(m.Groups[2].Value); - return new Vector2(w, h); - } - } - else if (typeof(IDictionary).IsAssignableFrom(value.GetType())) { - var dict = (IDictionary)value; - if (type == typeof(Rect)) { - var x = float.Parse((string)dict["x"]); - var y = float.Parse((string)dict["y"]); - var w = float.Parse((string)dict["w"]); - var h = float.Parse((string)dict["h"]); - return new Rect(x, y, w, h); - } - else if (type == typeof(Vector2)) { - var w = float.Parse((string)dict["w"]); - var h = float.Parse((string)dict["h"]); - return new Vector2(w, h); - } - } - return base.ChangeType(value, type, culture); - } - } -} diff --git a/Assets/Cryville/Crtr/Components/SpritePlane.cs b/Assets/Cryville/Crtr/Components/SpritePlane.cs index 1658bca..903a49f 100644 --- a/Assets/Cryville/Crtr/Components/SpritePlane.cs +++ b/Assets/Cryville/Crtr/Components/SpritePlane.cs @@ -5,7 +5,7 @@ using Logger = Cryville.Common.Logger; namespace Cryville.Crtr.Components { public class SpriteInfo { public string FrameName; - public Cocos2dFrames.Frame Frame { + public SpriteFrame Frame { get; private set; } diff --git a/Assets/Cryville/Crtr/Skin.cs b/Assets/Cryville/Crtr/Skin.cs index 7b1df73..52bd1b1 100644 --- a/Assets/Cryville/Crtr/Skin.cs +++ b/Assets/Cryville/Crtr/Skin.cs @@ -23,6 +23,8 @@ namespace Cryville.Crtr { [JsonRequired] public string pdt; + public List frames = new List(); + [JsonIgnore] public PdtSkin Root { get; private set; } diff --git a/Assets/Cryville/Crtr/SpriteFrame.cs b/Assets/Cryville/Crtr/SpriteFrame.cs new file mode 100644 index 0000000..1455edb --- /dev/null +++ b/Assets/Cryville/Crtr/SpriteFrame.cs @@ -0,0 +1,109 @@ +using System; +using UnityEngine; + +namespace Cryville.Crtr { + public class SpriteFrame { +#pragma warning disable IDE1006 + Rect _frame; + public Rect frame { + get { return _frame; } + set { _frame = value; } + } + public Rect textureRect { + get { return _frame; } + set { _frame = value; } + } + + bool _rotated = false; + public bool rotated { + get { return _rotated; } + set { _rotated = value; } + } + public bool textureRotated { + get { return _rotated; } + set { _rotated = value; } + } +#pragma warning restore IDE1006 + + public Vector2 offset; + + public Rect sourceColorRect; + public Vector2 sourceSize; + private Rect _uv; + private Vector2[] cuv; + public Rect UV { + get { + return _uv; + } + private set { + _uv = value; + float x0 = Mathf.Min(_uv.xMin, _uv.xMax); + float x1 = Mathf.Max(_uv.xMin, _uv.xMax); + float y0 = Mathf.Min(_uv.yMin, _uv.yMax); + float y1 = Mathf.Max(_uv.yMin, _uv.yMax); + if (_rotated) cuv = new Vector2[]{ + new Vector2(x0, y1), + new Vector2(x1, y0), + new Vector2(x0, y0), + new Vector2(x1, y1), + }; + else cuv = new Vector2[]{ + new Vector2(x0, y0), + new Vector2(x1, y1), + new Vector2(x1, y0), + new Vector2(x0, y1), + }; + } + } + public Vector2 GetUV(Vector2 uv) { + return GetUV(uv.x, uv.y); + } + public Vector2 GetUV(float u, float v) { + Vector2 uv00 = cuv[0], uv11 = cuv[1], + uv10 = cuv[2], uv01 = cuv[3]; + return (1 - u - v) * uv00 + + u * uv10 + + v * uv01 + + u * v * (uv00 + uv11 - uv10 - uv01); + } + public Texture2D Texture { + get; + private set; + } + public Vector2 Size { + get { + return new Vector2(Texture.width, Texture.height); + } + } + + public void Init() { + if (Texture == null) + throw new InvalidOperationException(); // TODO + _frame = new Rect(Vector2.zero, Size); + var w = _frame.width; + var h = _frame.height; + float x = _frame.x / w; + float y = 1 - _frame.y / h; + float tw = (_rotated ? _frame.height : _frame.width) / w; + float th = (_rotated ? _frame.width : _frame.height) / h; + if (_rotated) UV = new Rect(x, y, tw, -th); + else UV = new Rect(x, y, tw, -th); + } + + public void Init(int w, int h, Texture2D _base) { + if (Texture != null) + throw new InvalidOperationException(); // TODO + Texture = _base; + float x = _frame.x / w; + float y = 1 - _frame.y / h; + float tw = (_rotated ? _frame.height : _frame.width) / w; + float th = (_rotated ? _frame.width : _frame.height) / h; + if (_rotated) UV = new Rect(x, y, tw, -th); + else UV = new Rect(x, y, tw, -th); + } + public SpriteFrame() { } + public SpriteFrame(Texture2D tex) { + Texture = tex; + } + } +} diff --git a/Assets/Cryville/Crtr/Cocos2dFrames.cs.meta b/Assets/Cryville/Crtr/SpriteFrame.cs.meta similarity index 100% rename from Assets/Cryville/Crtr/Cocos2dFrames.cs.meta rename to Assets/Cryville/Crtr/SpriteFrame.cs.meta diff --git a/Assets/PlistCS.meta b/Assets/PlistCS.meta deleted file mode 100644 index 693bf1e..0000000 --- a/Assets/PlistCS.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 71d5ddaf108e0014c98c206ed5135ded -folderAsset: yes -timeCreated: 1605077401 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/PlistCS/Src.meta b/Assets/PlistCS/Src.meta deleted file mode 100644 index cc424b6..0000000 --- a/Assets/PlistCS/Src.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 8f21b229422310b40a4d539f7319bd1f -folderAsset: yes -timeCreated: 1605077401 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/PlistCS/Src/Plist.cs b/Assets/PlistCS/Src/Plist.cs deleted file mode 100644 index 441bc9d..0000000 --- a/Assets/PlistCS/Src/Plist.cs +++ /dev/null @@ -1,838 +0,0 @@ -// -// PlistCS Property List (plist) serialization and parsing library. -// -// https://github.com/animetrics/PlistCS -// -// Copyright (c) 2011 Animetrics Inc. (marc@animetrics.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Xml; - -namespace PlistCS { - public static class Plist { - private static List offsetTable = new List(); - private static List objectTable = new List(); - private static int refCount; - private static int objRefSize; - private static int offsetByteSize; - private static long offsetTableOffset; - - #region Public Functions - - public static object readPlist(string path) { - using (FileStream f = new FileStream(path, FileMode.Open, FileAccess.Read)) { - return readPlist(f, plistType.Auto); - } - } - - public static object readPlistSource(string source) { - return readPlist(System.Text.Encoding.UTF8.GetBytes(source)); - } - - public static object readPlist(byte[] data) { - using (var memory = new MemoryStream(data)) { - return readPlist(memory, plistType.Auto); - } - } - - public static plistType getPlistType(Stream stream) { - byte[] magicHeader = new byte[8]; - stream.Read(magicHeader, 0, 8); - - if (BitConverter.ToInt64(magicHeader, 0) == 3472403351741427810) { - return plistType.Binary; - } - else { - return plistType.Xml; - } - } - - public static object readPlist(Stream stream, plistType type) { - if (type == plistType.Auto) { - type = getPlistType(stream); - stream.Seek(0, SeekOrigin.Begin); - } - - if (type == plistType.Binary) { - using (BinaryReader reader = new BinaryReader(stream)) { - byte[] data = reader.ReadBytes((int)reader.BaseStream.Length); - return readBinary(data); - } - } - else { - XmlDocument xml = new XmlDocument(); - xml.XmlResolver = null; - xml.Load(stream); - return readXml(xml); - } - } - - public static void writeXml(object value, string path) { - using (StreamWriter writer = new StreamWriter(path)) { - writer.Write(writeXml(value)); - } - } - - public static void writeXml(object value, Stream stream) { - using (StreamWriter writer = new StreamWriter(stream)) { - writer.Write(writeXml(value)); - } - } - - public static string writeXml(object value) { - using (MemoryStream ms = new MemoryStream()) { - XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); - xmlWriterSettings.Encoding = new System.Text.UTF8Encoding(false); - xmlWriterSettings.ConformanceLevel = ConformanceLevel.Document; - xmlWriterSettings.Indent = true; - - using (XmlWriter xmlWriter = XmlWriter.Create(ms, xmlWriterSettings)) { - xmlWriter.WriteStartDocument(); - //xmlWriter.WriteComment("DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" " + "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\""); - xmlWriter.WriteDocType("plist", "-//Apple Computer//DTD PLIST 1.0//EN", "http://www.apple.com/DTDs/PropertyList-1.0.dtd", null); - xmlWriter.WriteStartElement("plist"); - xmlWriter.WriteAttributeString("version", "1.0"); - compose(value, xmlWriter); - xmlWriter.WriteEndElement(); - xmlWriter.WriteEndDocument(); - xmlWriter.Flush(); - return Encoding.UTF8.GetString(ms.ToArray()); - } - } - } - - public static void writeBinary(object value, string path) { - using (BinaryWriter writer = new BinaryWriter(new FileStream(path, FileMode.Create))) { - writer.Write(writeBinary(value)); - } - } - - public static void writeBinary(object value, Stream stream) { - using (BinaryWriter writer = new BinaryWriter(stream)) { - writer.Write(writeBinary(value)); - } - } - - public static byte[] writeBinary(object value) { - offsetTable.Clear(); - objectTable.Clear(); - refCount = 0; - objRefSize = 0; - offsetByteSize = 0; - offsetTableOffset = 0; - - //Do not count the root node, subtract by 1 - int totalRefs = countObject(value) - 1; - - refCount = totalRefs; - - objRefSize = RegulateNullBytes(BitConverter.GetBytes(refCount)).Length; - - composeBinary(value); - - writeBinaryString("bplist00", false); - - offsetTableOffset = (long)objectTable.Count; - - offsetTable.Add(objectTable.Count - 8); - - offsetByteSize = RegulateNullBytes(BitConverter.GetBytes(offsetTable[offsetTable.Count - 1])).Length; - - List offsetBytes = new List(); - - offsetTable.Reverse(); - - for (int i = 0; i < offsetTable.Count; i++) { - offsetTable[i] = objectTable.Count - offsetTable[i]; - byte[] buffer = RegulateNullBytes(BitConverter.GetBytes(offsetTable[i]), offsetByteSize); - Array.Reverse(buffer); - offsetBytes.AddRange(buffer); - } - - objectTable.AddRange(offsetBytes); - - objectTable.AddRange(new byte[6]); - objectTable.Add(Convert.ToByte(offsetByteSize)); - objectTable.Add(Convert.ToByte(objRefSize)); - - var a = BitConverter.GetBytes((long)totalRefs + 1); - Array.Reverse(a); - objectTable.AddRange(a); - - objectTable.AddRange(BitConverter.GetBytes((long)0)); - a = BitConverter.GetBytes(offsetTableOffset); - Array.Reverse(a); - objectTable.AddRange(a); - - return objectTable.ToArray(); - } - - #endregion - - #region Private Functions - - private static object readXml(XmlDocument xml) { - XmlNode rootNode = xml.DocumentElement.ChildNodes[0]; - return parse(rootNode); - } - - private static object readBinary(byte[] data) { - offsetTable.Clear(); - List offsetTableBytes = new List(); - objectTable.Clear(); - refCount = 0; - objRefSize = 0; - offsetByteSize = 0; - offsetTableOffset = 0; - - List bList = new List(data); - - List trailer = bList.GetRange(bList.Count - 32, 32); - - parseTrailer(trailer); - - objectTable = bList.GetRange(0, (int)offsetTableOffset); - - offsetTableBytes = bList.GetRange((int)offsetTableOffset, bList.Count - (int)offsetTableOffset - 32); - - parseOffsetTable(offsetTableBytes); - - return parseBinary(0); - } - - private static Dictionary parseDictionary(XmlNode node) { - XmlNodeList children = node.ChildNodes; - if (children.Count % 2 != 0) { - throw new DataMisalignedException("Dictionary elements must have an even number of child nodes"); - } - - Dictionary dict = new Dictionary(); - - for (int i = 0; i < children.Count; i += 2) { - XmlNode keynode = children[i]; - XmlNode valnode = children[i + 1]; - - if (keynode.Name != "key") { - throw new ApplicationException("expected a key node"); - } - - object result = parse(valnode); - - if (result != null) { - dict.Add(keynode.InnerText, result); - } - } - - return dict; - } - - private static List parseArray(XmlNode node) { - List array = new List(); - - foreach (XmlNode child in node.ChildNodes) { - object result = parse(child); - if (result != null) { - array.Add(result); - } - } - - return array; - } - - private static void composeArray(List value, XmlWriter writer) { - writer.WriteStartElement("array"); - foreach (object obj in value) { - compose(obj, writer); - } - writer.WriteEndElement(); - } - - private static object parse(XmlNode node) { - switch (node.Name) { - case "dict": - return parseDictionary(node); - case "array": - return parseArray(node); - case "string": - return node.InnerText; - case "integer": - // int result; - //int.TryParse(node.InnerText, System.Globalization.NumberFormatInfo.InvariantInfo, out result); - return Convert.ToInt32(node.InnerText, System.Globalization.NumberFormatInfo.InvariantInfo); - case "real": - return Convert.ToDouble(node.InnerText, System.Globalization.NumberFormatInfo.InvariantInfo); - case "false": - return false; - case "true": - return true; - case "null": - return null; - case "date": - return XmlConvert.ToDateTime(node.InnerText, XmlDateTimeSerializationMode.Utc); - case "data": - return Convert.FromBase64String(node.InnerText); - } - - throw new ApplicationException(String.Format("Plist Node `{0}' is not supported", node.Name)); - } - - private static void compose(object value, XmlWriter writer) { - - if (value == null || value is string) { - writer.WriteElementString("string", value as string); - } - else if (value is int || value is long) { - writer.WriteElementString("integer", ((int)value).ToString(System.Globalization.NumberFormatInfo.InvariantInfo)); - } - else if (value is System.Collections.Generic.Dictionary || - value.GetType().ToString().StartsWith("System.Collections.Generic.Dictionary`2[System.String")) { - //Convert to Dictionary - Dictionary dic = value as Dictionary; - if (dic == null) { - dic = new Dictionary(); - IDictionary idic = (IDictionary)value; - foreach (var key in idic.Keys) { - dic.Add(key.ToString(), idic[key]); - } - } - writeDictionaryValues(dic, writer); - } - else if (value is List) { - composeArray((List)value, writer); - } - else if (value is byte[]) { - writer.WriteElementString("data", Convert.ToBase64String((Byte[])value)); - } - else if (value is float || value is double) { - writer.WriteElementString("real", ((double)value).ToString(System.Globalization.NumberFormatInfo.InvariantInfo)); - } - else if (value is DateTime) { - DateTime time = (DateTime)value; - string theString = XmlConvert.ToString(time, XmlDateTimeSerializationMode.Utc); - writer.WriteElementString("date", theString);//, "yyyy-MM-ddTHH:mm:ssZ")); - } - else if (value is bool) { - writer.WriteElementString(value.ToString().ToLower(), ""); - } - else { - throw new Exception(String.Format("Value type '{0}' is unhandled", value.GetType().ToString())); - } - } - - private static void writeDictionaryValues(Dictionary dictionary, XmlWriter writer) { - writer.WriteStartElement("dict"); - foreach (string key in dictionary.Keys) { - object value = dictionary[key]; - writer.WriteElementString("key", key); - compose(value, writer); - } - writer.WriteEndElement(); - } - - private static int countObject(object value) { - int count = 0; - switch (value.GetType().ToString()) { - case "System.Collections.Generic.Dictionary`2[System.String,System.Object]": - Dictionary dict = (Dictionary)value; - foreach (string key in dict.Keys) { - count += countObject(dict[key]); - } - count += dict.Keys.Count; - count++; - break; - case "System.Collections.Generic.List`1[System.Object]": - List list = (List)value; - foreach (object obj in list) { - count += countObject(obj); - } - count++; - break; - default: - count++; - break; - } - return count; - } - - private static byte[] writeBinaryDictionary(Dictionary dictionary) { - List buffer = new List(); - List header = new List(); - List refs = new List(); - for (int i = dictionary.Count - 1; i >= 0; i--) { - var o = new object[dictionary.Count]; - dictionary.Values.CopyTo(o, 0); - composeBinary(o[i]); - offsetTable.Add(objectTable.Count); - refs.Add(refCount); - refCount--; - } - for (int i = dictionary.Count - 1; i >= 0; i--) { - var o = new string[dictionary.Count]; - dictionary.Keys.CopyTo(o, 0); - composeBinary(o[i]);//); - offsetTable.Add(objectTable.Count); - refs.Add(refCount); - refCount--; - } - - if (dictionary.Count < 15) { - header.Add(Convert.ToByte(0xD0 | Convert.ToByte(dictionary.Count))); - } - else { - header.Add(0xD0 | 0xf); - header.AddRange(writeBinaryInteger(dictionary.Count, false)); - } - - - foreach (int val in refs) { - byte[] refBuffer = RegulateNullBytes(BitConverter.GetBytes(val), objRefSize); - Array.Reverse(refBuffer); - buffer.InsertRange(0, refBuffer); - } - - buffer.InsertRange(0, header); - - - objectTable.InsertRange(0, buffer); - - return buffer.ToArray(); - } - - private static byte[] composeBinaryArray(List objects) { - List buffer = new List(); - List header = new List(); - List refs = new List(); - - for (int i = objects.Count - 1; i >= 0; i--) { - composeBinary(objects[i]); - offsetTable.Add(objectTable.Count); - refs.Add(refCount); - refCount--; - } - - if (objects.Count < 15) { - header.Add(Convert.ToByte(0xA0 | Convert.ToByte(objects.Count))); - } - else { - header.Add(0xA0 | 0xf); - header.AddRange(writeBinaryInteger(objects.Count, false)); - } - - foreach (int val in refs) { - byte[] refBuffer = RegulateNullBytes(BitConverter.GetBytes(val), objRefSize); - Array.Reverse(refBuffer); - buffer.InsertRange(0, refBuffer); - } - - buffer.InsertRange(0, header); - - objectTable.InsertRange(0, buffer); - - return buffer.ToArray(); - } - - private static byte[] composeBinary(object obj) { - byte[] value; - switch (obj.GetType().ToString()) { - case "System.Collections.Generic.Dictionary`2[System.String,System.Object]": - value = writeBinaryDictionary((Dictionary)obj); - return value; - - case "System.Collections.Generic.List`1[System.Object]": - value = composeBinaryArray((List)obj); - return value; - - case "System.Byte[]": - value = writeBinaryByteArray((byte[])obj); - return value; - - case "System.Double": - value = writeBinaryDouble((double)obj); - return value; - - case "System.Int32": - value = writeBinaryInteger((int)obj, true); - return value; - - case "System.String": - value = writeBinaryString((string)obj, true); - return value; - - case "System.DateTime": - value = writeBinaryDate((DateTime)obj); - return value; - - case "System.Boolean": - value = writeBinaryBool((bool)obj); - return value; - - default: - return new byte[0]; - } - } - - public static byte[] writeBinaryDate(DateTime obj) { - List buffer = new List(RegulateNullBytes(BitConverter.GetBytes(PlistDateConverter.ConvertToAppleTimeStamp(obj)), 8)); - buffer.Reverse(); - buffer.Insert(0, 0x33); - objectTable.InsertRange(0, buffer); - return buffer.ToArray(); - } - - public static byte[] writeBinaryBool(bool obj) { - List buffer = new List(new byte[1] { (bool)obj ? (byte)9 : (byte)8 }); - objectTable.InsertRange(0, buffer); - return buffer.ToArray(); - } - - private static byte[] writeBinaryInteger(int value, bool write) { - List buffer = new List(BitConverter.GetBytes((long)value)); - buffer = new List(RegulateNullBytes(buffer.ToArray())); - while (buffer.Count != Math.Pow(2, Math.Log(buffer.Count) / Math.Log(2))) - buffer.Add(0); - int header = 0x10 | (int)(Math.Log(buffer.Count) / Math.Log(2)); - - buffer.Reverse(); - - buffer.Insert(0, Convert.ToByte(header)); - - if (write) - objectTable.InsertRange(0, buffer); - - return buffer.ToArray(); - } - - private static byte[] writeBinaryDouble(double value) { - List buffer = new List(RegulateNullBytes(BitConverter.GetBytes(value), 4)); - while (buffer.Count != Math.Pow(2, Math.Log(buffer.Count) / Math.Log(2))) - buffer.Add(0); - int header = 0x20 | (int)(Math.Log(buffer.Count) / Math.Log(2)); - - buffer.Reverse(); - - buffer.Insert(0, Convert.ToByte(header)); - - objectTable.InsertRange(0, buffer); - - return buffer.ToArray(); - } - - private static byte[] writeBinaryByteArray(byte[] value) { - List buffer = new List(value); - List header = new List(); - if (value.Length < 15) { - header.Add(Convert.ToByte(0x40 | Convert.ToByte(value.Length))); - } - else { - header.Add(0x40 | 0xf); - header.AddRange(writeBinaryInteger(buffer.Count, false)); - } - - buffer.InsertRange(0, header); - - objectTable.InsertRange(0, buffer); - - return buffer.ToArray(); - } - - private static byte[] writeBinaryString(string value, bool head) { - List buffer = new List(); - List header = new List(); - foreach (char chr in value.ToCharArray()) - buffer.Add(Convert.ToByte(chr)); - - if (head) { - if (value.Length < 15) { - header.Add(Convert.ToByte(0x50 | Convert.ToByte(value.Length))); - } - else { - header.Add(0x50 | 0xf); - header.AddRange(writeBinaryInteger(buffer.Count, false)); - } - } - - buffer.InsertRange(0, header); - - objectTable.InsertRange(0, buffer); - - return buffer.ToArray(); - } - - private static byte[] RegulateNullBytes(byte[] value) { - return RegulateNullBytes(value, 1); - } - - private static byte[] RegulateNullBytes(byte[] value, int minBytes) { - Array.Reverse(value); - List bytes = new List(value); - for (int i = 0; i < bytes.Count; i++) { - if (bytes[i] == 0 && bytes.Count > minBytes) { - bytes.Remove(bytes[i]); - i--; - } - else - break; - } - - if (bytes.Count < minBytes) { - int dist = minBytes - bytes.Count; - for (int i = 0; i < dist; i++) - bytes.Insert(0, 0); - } - - value = bytes.ToArray(); - Array.Reverse(value); - return value; - } - - private static void parseTrailer(List trailer) { - offsetByteSize = BitConverter.ToInt32(RegulateNullBytes(trailer.GetRange(6, 1).ToArray(), 4), 0); - objRefSize = BitConverter.ToInt32(RegulateNullBytes(trailer.GetRange(7, 1).ToArray(), 4), 0); - byte[] refCountBytes = trailer.GetRange(12, 4).ToArray(); - Array.Reverse(refCountBytes); - refCount = BitConverter.ToInt32(refCountBytes, 0); - byte[] offsetTableOffsetBytes = trailer.GetRange(24, 8).ToArray(); - Array.Reverse(offsetTableOffsetBytes); - offsetTableOffset = BitConverter.ToInt64(offsetTableOffsetBytes, 0); - } - - private static void parseOffsetTable(List offsetTableBytes) { - for (int i = 0; i < offsetTableBytes.Count; i += offsetByteSize) { - byte[] buffer = offsetTableBytes.GetRange(i, offsetByteSize).ToArray(); - Array.Reverse(buffer); - offsetTable.Add(BitConverter.ToInt32(RegulateNullBytes(buffer, 4), 0)); - } - } - - private static object parseBinaryDictionary(int objRef) { - Dictionary buffer = new Dictionary(); - List refs = new List(); - int refCount = 0; - - int refStartPosition; - refCount = getCount(offsetTable[objRef], out refStartPosition); - - - if (refCount < 15) - refStartPosition = offsetTable[objRef] + 1; - else - refStartPosition = offsetTable[objRef] + 2 + RegulateNullBytes(BitConverter.GetBytes(refCount), 1).Length; - - for (int i = refStartPosition; i < refStartPosition + refCount * 2 * objRefSize; i += objRefSize) { - byte[] refBuffer = objectTable.GetRange(i, objRefSize).ToArray(); - Array.Reverse(refBuffer); - refs.Add(BitConverter.ToInt32(RegulateNullBytes(refBuffer, 4), 0)); - } - - for (int i = 0; i < refCount; i++) { - buffer.Add((string)parseBinary(refs[i]), parseBinary(refs[i + refCount])); - } - - return buffer; - } - - private static object parseBinaryArray(int objRef) { - List buffer = new List(); - List refs = new List(); - int refCount = 0; - - int refStartPosition; - refCount = getCount(offsetTable[objRef], out refStartPosition); - - - if (refCount < 15) - refStartPosition = offsetTable[objRef] + 1; - else - //The following integer has a header aswell so we increase the refStartPosition by two to account for that. - refStartPosition = offsetTable[objRef] + 2 + RegulateNullBytes(BitConverter.GetBytes(refCount), 1).Length; - - for (int i = refStartPosition; i < refStartPosition + refCount * objRefSize; i += objRefSize) { - byte[] refBuffer = objectTable.GetRange(i, objRefSize).ToArray(); - Array.Reverse(refBuffer); - refs.Add(BitConverter.ToInt32(RegulateNullBytes(refBuffer, 4), 0)); - } - - for (int i = 0; i < refCount; i++) { - buffer.Add(parseBinary(refs[i])); - } - - return buffer; - } - - private static int getCount(int bytePosition, out int newBytePosition) { - byte headerByte = objectTable[bytePosition]; - byte headerByteTrail = Convert.ToByte(headerByte & 0xf); - int count; - if (headerByteTrail < 15) { - count = headerByteTrail; - newBytePosition = bytePosition + 1; - } - else - count = (int)parseBinaryInt(bytePosition + 1, out newBytePosition); - return count; - } - - private static object parseBinary(int objRef) { - byte header = objectTable[offsetTable[objRef]]; - switch (header & 0xF0) { - case 0: { - //If the byte is - //0 return null - //9 return true - //8 return false - return (objectTable[offsetTable[objRef]] == 0) ? (object)null : ((objectTable[offsetTable[objRef]] == 9) ? true : false); - } - case 0x10: { - return parseBinaryInt(offsetTable[objRef]); - } - case 0x20: { - return parseBinaryReal(offsetTable[objRef]); - } - case 0x30: { - return parseBinaryDate(offsetTable[objRef]); - } - case 0x40: { - return parseBinaryByteArray(offsetTable[objRef]); - } - case 0x50://String ASCII - { - return parseBinaryAsciiString(offsetTable[objRef]); - } - case 0x60://String Unicode - { - return parseBinaryUnicodeString(offsetTable[objRef]); - } - case 0xD0: { - return parseBinaryDictionary(objRef); - } - case 0xA0: { - return parseBinaryArray(objRef); - } - } - throw new Exception("This type is not supported"); - } - - public static object parseBinaryDate(int headerPosition) { - byte[] buffer = objectTable.GetRange(headerPosition + 1, 8).ToArray(); - Array.Reverse(buffer); - double appleTime = BitConverter.ToDouble(buffer, 0); - DateTime result = PlistDateConverter.ConvertFromAppleTimeStamp(appleTime); - return result; - } - - private static object parseBinaryInt(int headerPosition) { - int output; - return parseBinaryInt(headerPosition, out output); - } - - private static object parseBinaryInt(int headerPosition, out int newHeaderPosition) { - byte header = objectTable[headerPosition]; - int byteCount = (int)Math.Pow(2, header & 0xf); - byte[] buffer = objectTable.GetRange(headerPosition + 1, byteCount).ToArray(); - Array.Reverse(buffer); - //Add one to account for the header byte - newHeaderPosition = headerPosition + byteCount + 1; - return BitConverter.ToInt32(RegulateNullBytes(buffer, 4), 0); - } - - private static object parseBinaryReal(int headerPosition) { - byte header = objectTable[headerPosition]; - int byteCount = (int)Math.Pow(2, header & 0xf); - byte[] buffer = objectTable.GetRange(headerPosition + 1, byteCount).ToArray(); - Array.Reverse(buffer); - - return BitConverter.ToDouble(RegulateNullBytes(buffer, 8), 0); - } - - private static object parseBinaryAsciiString(int headerPosition) { - int charStartPosition; - int charCount = getCount(headerPosition, out charStartPosition); - - var buffer = objectTable.GetRange(charStartPosition, charCount); - return buffer.Count > 0 ? Encoding.ASCII.GetString(buffer.ToArray()) : string.Empty; - } - - private static object parseBinaryUnicodeString(int headerPosition) { - int charStartPosition; - int charCount = getCount(headerPosition, out charStartPosition); - charCount = charCount * 2; - - byte[] buffer = new byte[charCount]; - byte one, two; - - for (int i = 0; i < charCount; i += 2) { - one = objectTable.GetRange(charStartPosition + i, 1)[0]; - two = objectTable.GetRange(charStartPosition + i + 1, 1)[0]; - - if (BitConverter.IsLittleEndian) { - buffer[i] = two; - buffer[i + 1] = one; - } - else { - buffer[i] = one; - buffer[i + 1] = two; - } - } - - return Encoding.Unicode.GetString(buffer); - } - - private static object parseBinaryByteArray(int headerPosition) { - int byteStartPosition; - int byteCount = getCount(headerPosition, out byteStartPosition); - return objectTable.GetRange(byteStartPosition, byteCount).ToArray(); - } - - #endregion - } - - public enum plistType { - Auto, Binary, Xml - } - - public static class PlistDateConverter { - public static long timeDifference = 978307200; - - public static long GetAppleTime(long unixTime) { - return unixTime - timeDifference; - } - - public static long GetUnixTime(long appleTime) { - return appleTime + timeDifference; - } - - public static DateTime ConvertFromAppleTimeStamp(double timestamp) { - DateTime origin = new DateTime(2001, 1, 1, 0, 0, 0, 0); - return origin.AddSeconds(timestamp); - } - - public static double ConvertToAppleTimeStamp(DateTime date) { - DateTime begin = new DateTime(2001, 1, 1, 0, 0, 0, 0); - TimeSpan diff = date - begin; - return Math.Floor(diff.TotalSeconds); - } - } -} diff --git a/Assets/PlistCS/Src/Plist.cs.meta b/Assets/PlistCS/Src/Plist.cs.meta deleted file mode 100644 index 5d47c9f..0000000 --- a/Assets/PlistCS/Src/Plist.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: da665e46f8c2b5b46ad8e3bf5cd34007 -timeCreated: 1605077404 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: