From 1d66b7179cb89d8623fc44201062c4d9f949c898 Mon Sep 17 00:00:00 2001 From: spatialfree Date: Tue, 14 Jul 2020 16:06:31 -0700 Subject: [PATCH] refactored save system to JSON --- Assets/AssetSpace/draft.json | 1 + .../{draft.pixelgon.meta => draft.json.meta} | 4 +- Assets/AssetSpace/draft.pixelgon | Bin 8716 -> 0 bytes Assets/AssetSpace/missile.json | 1 + ...issile.pixelgon.meta => missile.json.meta} | 4 +- Assets/AssetSpace/missile.pixelgon | Bin 7015 -> 0 bytes Assets/AssetSpace/spaceship.json | 1 + Assets/AssetSpace/spaceship.json.meta | 7 + Assets/Plugins/SimpleJSON.cs | 1317 +++++++++++++++++ Assets/Plugins/SimpleJSON.cs.meta | 11 + Assets/Plugins/SimpleJSONBinary.cs | 301 ++++ Assets/Plugins/SimpleJSONBinary.cs.meta | 11 + Assets/Plugins/SimpleJSONUnity.cs | 369 +++++ Assets/Plugins/SimpleJSONUnity.cs.meta | 11 + Assets/Scenes/Main.unity | 11 +- Assets/Scripts/AssetSpace.cs | 188 +-- 16 files changed, 2081 insertions(+), 156 deletions(-) create mode 100644 Assets/AssetSpace/draft.json rename Assets/AssetSpace/{draft.pixelgon.meta => draft.json.meta} (62%) delete mode 100644 Assets/AssetSpace/draft.pixelgon create mode 100644 Assets/AssetSpace/missile.json rename Assets/AssetSpace/{missile.pixelgon.meta => missile.json.meta} (62%) delete mode 100644 Assets/AssetSpace/missile.pixelgon create mode 100644 Assets/AssetSpace/spaceship.json create mode 100644 Assets/AssetSpace/spaceship.json.meta create mode 100644 Assets/Plugins/SimpleJSON.cs create mode 100644 Assets/Plugins/SimpleJSON.cs.meta create mode 100644 Assets/Plugins/SimpleJSONBinary.cs create mode 100644 Assets/Plugins/SimpleJSONBinary.cs.meta create mode 100644 Assets/Plugins/SimpleJSONUnity.cs create mode 100644 Assets/Plugins/SimpleJSONUnity.cs.meta diff --git a/Assets/AssetSpace/draft.json b/Assets/AssetSpace/draft.json new file mode 100644 index 0000000..4caf398 --- /dev/null +++ b/Assets/AssetSpace/draft.json @@ -0,0 +1 @@ +{"vectors":[{"x":0.0,"y":0.0,"z":0.0},{"x":-0.30000001192092898,"y":-0.30000001192092898,"z":0.0},{"x":-0.30000001192092898,"y":0.30000001192092898,"z":0.0},{"x":0.30000001192092898,"y":-0.4300000071525574,"z":0.0},{"x":0.0,"y":0.0,"z":0.0}],"quads":[1,2,3]} \ No newline at end of file diff --git a/Assets/AssetSpace/draft.pixelgon.meta b/Assets/AssetSpace/draft.json.meta similarity index 62% rename from Assets/AssetSpace/draft.pixelgon.meta rename to Assets/AssetSpace/draft.json.meta index 4862663..905d98b 100644 --- a/Assets/AssetSpace/draft.pixelgon.meta +++ b/Assets/AssetSpace/draft.json.meta @@ -1,6 +1,6 @@ fileFormatVersion: 2 -guid: 4b2183ce9a640ce46990e3029a03496a -DefaultImporter: +guid: ef37452489748cc4ca4bc9672b6f40e0 +TextScriptImporter: externalObjects: {} userData: assetBundleName: diff --git a/Assets/AssetSpace/draft.pixelgon b/Assets/AssetSpace/draft.pixelgon deleted file mode 100644 index a279ceac147d10142cc698c563a12ee6463998c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8716 zcmaLc30RcX9>?)Hf&xu95j06nxt5`32zg6j=1d^z#q1^}lBEb@m?$E$31~Q)5atSn zqN1SUiVNb#Fz1XTBDfMRDOu?dE=Ztld>U{XwCQhXGT zjY>+4pAa*^Jvb>cCVJwCsML_@Q=?*eY*I{2d+VZ3!-AtzqGCRs9&7#1AvtPd;`I0g z`yQjB;-e?TM5j%NjEM?Kjf+a~92NT4&jyVRv(8}sbh5K1);pCoo}t{?cl+O=HEI8c zvNQi@8|z{$g{87ITdjR>zJyoT^9!Yc?H5dMU)9-#%{WrUXy{)q4ggx@2)i10gv zbqFsYJdf~Ogy#^RMR*3`X@s>1zad=oVVK-9u3j{H_m-^2w&k;7e)_`m8t4ALlAW?) zt6yVw65$C#vpURgnJqs~=-72E*UzpIWxKs3JBIS32&>VWRfPWG+l+PXCd#mJ;U;zj z<&_8z6WT^PU>&J~(5HHf(R@Ebrrr)Su|p^~BRoi$mk=#2b`M3#)Mq3!5r%f(W~?lZ zloxbGd@sU1 zgl4b7e$L+KG@3V*%chj@PS4Xk*x!+xJ#J{(Zj_fG+(p>t9PRwCH7l)a?m+o=gvEr5 z>6*W0z2>(O#+k;N;vz4Ll%d|7ZAJMOgqsm=LbwrO5uxqT6RnTFfw0Z#Sda2`2n!Jw zAY6-Z4WaGC{dJJ@3F8-p>w+Jz5RQ}7oUKOrDugQu6P0|7EzcutbBb4>d^y5gLUVsN zL-5@rnzUr)s{7iurNhYbxau7|FF$~@uWZ=*87v23HlcpnyX6%liuw9#4QI;;dyTB+ z^UpZ&+7s8bY$?i@AY5!iWuzI(NXxAwEh21liWl0pY(3|f2p14e9#Jd&T^0#1$3n@n zY+LqG8!V-f#^Keul6_&r)@x=W%pla~g&I^@3yhbZtdwj%;p7WPwJNu{;_Ys$CHoxZ z^AOH$l|Sf8xt?(QkpN@JDSLUQ=tUEogYtBQpAoj%_t}JdoBWLr{Ox7a5M|9-C{II} zN_h8#mNz=2@T?u(I7=ba*IhM4=D*4#Sg?`JM0qm8BwIeO(NN*x$yI~gjVzI{v|A95 z2w0D0?OkN&LAALatPl$W|g+6V6b3ugu^fSaG(3B{N~5qIh&61ScKCEchz{x z$dl20T)Q_oi?MB4Q*ZD$dvJZ=A|sn>!`9c*6ok=){(Ej18s8bn&F7vmvdM&xm;1=Z zO+&Q7+bl-*Dat1yj3O-b;?i>LZEf7mLq_%q;oa>XvMDo`r(`L^Pegen!U=>MTx$4p zMIE@?yA~~rAnX>Nu8TO(K{^KP<18HI;}M1-9EWf$!jB2tJXL-~*po)Gw~jOhZT^z_fUxg8y{Yd}XQ^r|;_Q8t2O}IwSUFN}Dv5QLRWB&{dxUMC75|0u zcM*;te0|O)qoaDf^u9XQ#NHv)_w49b667jl)@5@x9OXd>|4HbzRPFaeva2)?UdGul z!a;VCG9pJM7kvM+WJ6K@Ho`!{!UDCQqq1g@PFZsZVS2x}c<_nsV$pGL$pTRBkMJ!* z>uzqh?WT^<6qIVJY;uzRU2-|&DAyv?pf&vnpJ_wFKK-it|QAR0`_~@|Eds_tS zMtJhTL9X&SBpTDI1$zPIZV0;)ItCozb-5M7XY>WZo+s?rekadztrYtU8wKlv^3Did z2}82?bDz=*5xlleFc-paDvP+K;HJh>6=7tZQ0|PdBVlO2c{1x`lZd=oF4%K~RVkUW zluOm{KyAyZ z48a)6RS2Ix`S*L3y{;SNmc~BXO8JFgPYB(jS4+2)9>RZVMW)HX*!$u#s?dWtp_NF=K7b*MeOq+~`y!RlL@B+#D&`HI!dPc!hA*(=w^gQ~6DK zMLF^fgtG5ixy-d*ObPu-u%A#~kI;hfGQvv;eAa$y$+rMS1!?i}EuFPZK`$R(`oW?fhD9*-2JQ_-KA6SKXWK`%+40 z$-Y5(4Z>4|&0NX7JjV>?o;g}fOsf%Ps z3HJr(@xrUCHO^1lNmh;WDuhQ6Rw6u%uma&Bgl2>X5tNjV;Vy(b5$-^^9bqxTZ3wp_+=6g3!c7P_A}m6<0pWUt>kt+qEI_yx z;TnYb2v;Lqg>WUpJcKI{E=QP)@N0x$A`TJUw_|n9k91r=z=yL1AZJ+!zd)FYFazOy!aly^byv=R#pgWvoU_jfx3nH< z9?It;)Ds3AdtWE?tNHN2gPhGF?B4L6uEgaNUNy;1$I?;$8N%5ppG6qnpwTt0$>b%) zJ2*>2c`Cvb!l#=*&pO+;tbu4&=M0yvkWD m%BLZWA?!20lWux1Ek84FA!kzwiuH#SzhQpcw|is9Y!smrPs8 z$S~0?waCm$?zk_gsJQQn8{&$J3WAFF`kbD}d7f|GdFIT_=g#lWIq!MzKVuRmlc`=m zj924m?4u7oySiMq;qms2_F+*&;+!eLK`}O`D=FDw?GSS75gZiewx_zCHmk$tPIboF zgM%X7@%E&Ia9c)n@-Umj>Tuibjf{)>_l!(Rx7ibu9mXf$G+RPyveVVDWt7dC6lYHw z85eK2MQ5bgTp>|0x6XC!H^7*K@$_$CM2x{?guCfO!xsM?G$M_z>5KWF?-&;o=^{gn z)ZduRW+QX^A?ozJaSbo5CA>;lLs(6Ch43=rCBiDgi-Z>l&l6S>o+CU?d4zKbea(Z24Ozo z4}{YRzbDKi{El!M;kSgjgx?T;P52ezmxNOZrx1QYIGONs!byY^2`3PaC(I%Ij4+#U z9O0*gpAcpdjwKvJIGS)2;m3p@5q?ORN%#TbNWu)lbixsYX@qXVR6-Y_lkk1Q6vAXe z2jOr+JK-?Gp@d0upqX^$5e1kBOun*zugs%}s5QY=JO85$4Z^B-LJqdddb|(xY>_*s?FqE(h;md?p zLP=;L>`eF)VJE^D311+5p71%sj)cz=K10}n@M*#j!uEv0gzX5QB7BmtE#VV{j}tyd z_$c8cgbx!wL>NTahOjkZE5eq94-&Q@e1Nby;r)d75#CGKjPM@9y9t{T1`^&ycqd^K z!p4MV!T^PnogPcRd9Dl{yVD~46<%APEn{W6)l?B6g&)Oz3GYxC96nCgjCNZ)#Om=z z3Ns^4$ovs?a@mSRDH>9|0iln=39ZUy-mn|8dEQ_tgu=iIk0l~)t_;f6CvT#7{SEl9 z@&@5`!fOgk^(qzURf;vLRHyLD)DX|8r45P-%|4o_rTA6C8ijRp+F8pMG?k;ew6=(9 zg^hPj(Ngx#)(ZR2(!>>tUnabya8+@w44u_irfd^dQKc|orLQM6Y?4+sXstzDr1%BG z^9sxLWk%}D%r%x-sjykbL@ldxfwrjcOii4l_*ud;3bXWPDA1ds)M$p&3aeB>VvT~F zqWDR|3WWs~m9n@;xXkWdFU1Lk)ot2ZbBhCH&=Eh2D5v;w!ea`J(slc{bVn67)Az`! z@6iHdkB(6MFkzWOuX-L*==DPfDSm)(zrrCy`^$>lf}-v@ewx^)uzHNc8k&=>1@0NI ziMRbkGsQO%ZlrjL!t`GLGIU-WOJU|>DK=1iJ>fcqntmI0(r-hDaT^vZ^y>Mw6kkKQ zTA^3ltWp?#EYWkm)pe~nVWB2gQhWvBa)kpk2YIG7snn)t&)38.Enumerator m_Object; + private List.Enumerator m_Array; + public bool IsValid { get { return type != Type.None; } } + public Enumerator(List.Enumerator aArrayEnum) + { + type = Type.Array; + m_Object = default(Dictionary.Enumerator); + m_Array = aArrayEnum; + } + public Enumerator(Dictionary.Enumerator aDictEnum) + { + type = Type.Object; + m_Object = aDictEnum; + m_Array = default(List.Enumerator); + } + public KeyValuePair Current + { + get + { + if (type == Type.Array) + return new KeyValuePair(string.Empty, m_Array.Current); + else if (type == Type.Object) + return m_Object.Current; + return new KeyValuePair(string.Empty, null); + } + } + public bool MoveNext() + { + if (type == Type.Array) + return m_Array.MoveNext(); + else if (type == Type.Object) + return m_Object.MoveNext(); + return false; + } + } + public struct ValueEnumerator + { + private Enumerator m_Enumerator; + public ValueEnumerator(List.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } + public ValueEnumerator(Dictionary.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } + public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } + public JSONNode Current { get { return m_Enumerator.Current.Value; } } + public bool MoveNext() { return m_Enumerator.MoveNext(); } + public ValueEnumerator GetEnumerator() { return this; } + } + public struct KeyEnumerator + { + private Enumerator m_Enumerator; + public KeyEnumerator(List.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } + public KeyEnumerator(Dictionary.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } + public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } + public string Current { get { return m_Enumerator.Current.Key; } } + public bool MoveNext() { return m_Enumerator.MoveNext(); } + public KeyEnumerator GetEnumerator() { return this; } + } + + public class LinqEnumerator : IEnumerator>, IEnumerable> + { + private JSONNode m_Node; + private Enumerator m_Enumerator; + internal LinqEnumerator(JSONNode aNode) + { + m_Node = aNode; + if (m_Node != null) + m_Enumerator = m_Node.GetEnumerator(); + } + public KeyValuePair Current { get { return m_Enumerator.Current; } } + object IEnumerator.Current { get { return m_Enumerator.Current; } } + public bool MoveNext() { return m_Enumerator.MoveNext(); } + + public void Dispose() + { + m_Node = null; + m_Enumerator = new Enumerator(); + } + + public IEnumerator> GetEnumerator() + { + return new LinqEnumerator(m_Node); + } + + public void Reset() + { + if (m_Node != null) + m_Enumerator = m_Node.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return new LinqEnumerator(m_Node); + } + } + + #endregion Enumerators + + #region common interface + + public static bool forceASCII = false; // Use Unicode by default + public static bool longAsString = false; // lazy creator creates a JSONString instead of JSONNumber + public static bool allowLineComments = true; // allow "//"-style comments at the end of a line + + public abstract JSONNodeType Tag { get; } + + public virtual JSONNode this[int aIndex] { get { return null; } set { } } + + public virtual JSONNode this[string aKey] { get { return null; } set { } } + + public virtual string Value { get { return ""; } set { } } + + public virtual int Count { get { return 0; } } + + public virtual bool IsNumber { get { return false; } } + public virtual bool IsString { get { return false; } } + public virtual bool IsBoolean { get { return false; } } + public virtual bool IsNull { get { return false; } } + public virtual bool IsArray { get { return false; } } + public virtual bool IsObject { get { return false; } } + + public virtual bool Inline { get { return false; } set { } } + + public virtual void Add(string aKey, JSONNode aItem) + { + } + public virtual void Add(JSONNode aItem) + { + Add("", aItem); + } + + public virtual JSONNode Remove(string aKey) + { + return null; + } + + public virtual JSONNode Remove(int aIndex) + { + return null; + } + + public virtual JSONNode Remove(JSONNode aNode) + { + return aNode; + } + + public virtual JSONNode Clone() + { + return null; + } + + public virtual IEnumerable Children + { + get + { + yield break; + } + } + + public IEnumerable DeepChildren + { + get + { + foreach (var C in Children) + foreach (var D in C.DeepChildren) + yield return D; + } + } + + public virtual bool HasKey(string aKey) + { + return false; + } + + public virtual JSONNode GetValueOrDefault(string aKey, JSONNode aDefault) + { + return aDefault; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + WriteToStringBuilder(sb, 0, 0, JSONTextMode.Compact); + return sb.ToString(); + } + + public virtual string ToString(int aIndent) + { + StringBuilder sb = new StringBuilder(); + WriteToStringBuilder(sb, 0, aIndent, JSONTextMode.Indent); + return sb.ToString(); + } + internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); + + public abstract Enumerator GetEnumerator(); + public IEnumerable> Linq { get { return new LinqEnumerator(this); } } + public KeyEnumerator Keys { get { return new KeyEnumerator(GetEnumerator()); } } + public ValueEnumerator Values { get { return new ValueEnumerator(GetEnumerator()); } } + + #endregion common interface + + #region typecasting properties + + + public virtual double AsDouble + { + get + { + double v = 0.0; + if (double.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out v)) + return v; + return 0.0; + } + set + { + Value = value.ToString(CultureInfo.InvariantCulture); + } + } + + public virtual int AsInt + { + get { return (int)AsDouble; } + set { AsDouble = value; } + } + + public virtual float AsFloat + { + get { return (float)AsDouble; } + set { AsDouble = value; } + } + + public virtual bool AsBool + { + get + { + bool v = false; + if (bool.TryParse(Value, out v)) + return v; + return !string.IsNullOrEmpty(Value); + } + set + { + Value = (value) ? "true" : "false"; + } + } + + public virtual long AsLong + { + get + { + long val = 0; + if (long.TryParse(Value, out val)) + return val; + return 0L; + } + set + { + Value = value.ToString(); + } + } + + public virtual JSONArray AsArray + { + get + { + return this as JSONArray; + } + } + + public virtual JSONObject AsObject + { + get + { + return this as JSONObject; + } + } + + + #endregion typecasting properties + + #region operators + + public static implicit operator JSONNode(string s) + { + return new JSONString(s); + } + public static implicit operator string(JSONNode d) + { + return (d == null) ? null : d.Value; + } + + public static implicit operator JSONNode(double n) + { + return new JSONNumber(n); + } + public static implicit operator double(JSONNode d) + { + return (d == null) ? 0 : d.AsDouble; + } + + public static implicit operator JSONNode(float n) + { + return new JSONNumber(n); + } + public static implicit operator float(JSONNode d) + { + return (d == null) ? 0 : d.AsFloat; + } + + public static implicit operator JSONNode(int n) + { + return new JSONNumber(n); + } + public static implicit operator int(JSONNode d) + { + return (d == null) ? 0 : d.AsInt; + } + + public static implicit operator JSONNode(long n) + { + if (longAsString) + return new JSONString(n.ToString()); + return new JSONNumber(n); + } + public static implicit operator long(JSONNode d) + { + return (d == null) ? 0L : d.AsLong; + } + + public static implicit operator JSONNode(bool b) + { + return new JSONBool(b); + } + public static implicit operator bool(JSONNode d) + { + return (d == null) ? false : d.AsBool; + } + + public static implicit operator JSONNode(KeyValuePair aKeyValue) + { + return aKeyValue.Value; + } + + public static bool operator ==(JSONNode a, object b) + { + if (ReferenceEquals(a, b)) + return true; + bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; + bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; + if (aIsNull && bIsNull) + return true; + return !aIsNull && a.Equals(b); + } + + public static bool operator !=(JSONNode a, object b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + return ReferenceEquals(this, obj); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + #endregion operators + + [ThreadStatic] + private static StringBuilder m_EscapeBuilder; + internal static StringBuilder EscapeBuilder + { + get + { + if (m_EscapeBuilder == null) + m_EscapeBuilder = new StringBuilder(); + return m_EscapeBuilder; + } + } + internal static string Escape(string aText) + { + var sb = EscapeBuilder; + sb.Length = 0; + if (sb.Capacity < aText.Length + aText.Length / 10) + sb.Capacity = aText.Length + aText.Length / 10; + foreach (char c in aText) + { + switch (c) + { + case '\\': + sb.Append("\\\\"); + break; + case '\"': + sb.Append("\\\""); + break; + case '\n': + sb.Append("\\n"); + break; + case '\r': + sb.Append("\\r"); + break; + case '\t': + sb.Append("\\t"); + break; + case '\b': + sb.Append("\\b"); + break; + case '\f': + sb.Append("\\f"); + break; + default: + if (c < ' ' || (forceASCII && c > 127)) + { + ushort val = c; + sb.Append("\\u").Append(val.ToString("X4")); + } + else + sb.Append(c); + break; + } + } + string result = sb.ToString(); + sb.Length = 0; + return result; + } + + private static JSONNode ParseElement(string token, bool quoted) + { + if (quoted) + return token; + string tmp = token.ToLower(); + if (tmp == "false" || tmp == "true") + return tmp == "true"; + if (tmp == "null") + return JSONNull.CreateOrGet(); + double val; + if (double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out val)) + return val; + else + return token; + } + + public static JSONNode Parse(string aJSON) + { + Stack stack = new Stack(); + JSONNode ctx = null; + int i = 0; + StringBuilder Token = new StringBuilder(); + string TokenName = ""; + bool QuoteMode = false; + bool TokenIsQuoted = false; + while (i < aJSON.Length) + { + switch (aJSON[i]) + { + case '{': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + stack.Push(new JSONObject()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '[': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + + stack.Push(new JSONArray()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '}': + case ']': + if (QuoteMode) + { + + Token.Append(aJSON[i]); + break; + } + if (stack.Count == 0) + throw new Exception("JSON Parse: Too many closing brackets"); + + stack.Pop(); + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + if (stack.Count > 0) + ctx = stack.Peek(); + break; + + case ':': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + TokenName = Token.ToString(); + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '"': + QuoteMode ^= true; + TokenIsQuoted |= QuoteMode; + break; + + case ',': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '\r': + case '\n': + break; + + case ' ': + case '\t': + if (QuoteMode) + Token.Append(aJSON[i]); + break; + + case '\\': + ++i; + if (QuoteMode) + { + char C = aJSON[i]; + switch (C) + { + case 't': + Token.Append('\t'); + break; + case 'r': + Token.Append('\r'); + break; + case 'n': + Token.Append('\n'); + break; + case 'b': + Token.Append('\b'); + break; + case 'f': + Token.Append('\f'); + break; + case 'u': + { + string s = aJSON.Substring(i + 1, 4); + Token.Append((char)int.Parse( + s, + System.Globalization.NumberStyles.AllowHexSpecifier)); + i += 4; + break; + } + default: + Token.Append(C); + break; + } + } + break; + case '/': + if (allowLineComments && !QuoteMode && i + 1 < aJSON.Length && aJSON[i + 1] == '/') + { + while (++i < aJSON.Length && aJSON[i] != '\n' && aJSON[i] != '\r') ; + break; + } + Token.Append(aJSON[i]); + break; + case '\uFEFF': // remove / ignore BOM (Byte Order Mark) + break; + + default: + Token.Append(aJSON[i]); + break; + } + ++i; + } + if (QuoteMode) + { + throw new Exception("JSON Parse: Quotation marks seems to be messed up."); + } + if (ctx == null) + return ParseElement(Token.ToString(), TokenIsQuoted); + return ctx; + } + + } + // End of JSONNode + + public partial class JSONArray : JSONNode + { + private List m_List = new List(); + private bool inline = false; + public override bool Inline + { + get { return inline; } + set { inline = value; } + } + + public override JSONNodeType Tag { get { return JSONNodeType.Array; } } + public override bool IsArray { get { return true; } } + public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); } + + public override JSONNode this[int aIndex] + { + get + { + if (aIndex < 0 || aIndex >= m_List.Count) + return new JSONLazyCreator(this); + return m_List[aIndex]; + } + set + { + if (value == null) + value = JSONNull.CreateOrGet(); + if (aIndex < 0 || aIndex >= m_List.Count) + m_List.Add(value); + else + m_List[aIndex] = value; + } + } + + public override JSONNode this[string aKey] + { + get { return new JSONLazyCreator(this); } + set + { + if (value == null) + value = JSONNull.CreateOrGet(); + m_List.Add(value); + } + } + + public override int Count + { + get { return m_List.Count; } + } + + public override void Add(string aKey, JSONNode aItem) + { + if (aItem == null) + aItem = JSONNull.CreateOrGet(); + m_List.Add(aItem); + } + + public override JSONNode Remove(int aIndex) + { + if (aIndex < 0 || aIndex >= m_List.Count) + return null; + JSONNode tmp = m_List[aIndex]; + m_List.RemoveAt(aIndex); + return tmp; + } + + public override JSONNode Remove(JSONNode aNode) + { + m_List.Remove(aNode); + return aNode; + } + + public override JSONNode Clone() + { + var node = new JSONArray(); + node.m_List.Capacity = m_List.Capacity; + foreach(var n in m_List) + { + if (n != null) + node.Add(n.Clone()); + else + node.Add(null); + } + return node; + } + + public override IEnumerable Children + { + get + { + foreach (JSONNode N in m_List) + yield return N; + } + } + + + internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) + { + aSB.Append('['); + int count = m_List.Count; + if (inline) + aMode = JSONTextMode.Compact; + for (int i = 0; i < count; i++) + { + if (i > 0) + aSB.Append(','); + if (aMode == JSONTextMode.Indent) + aSB.AppendLine(); + + if (aMode == JSONTextMode.Indent) + aSB.Append(' ', aIndent + aIndentInc); + m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); + } + if (aMode == JSONTextMode.Indent) + aSB.AppendLine().Append(' ', aIndent); + aSB.Append(']'); + } + } + // End of JSONArray + + public partial class JSONObject : JSONNode + { + private Dictionary m_Dict = new Dictionary(); + + private bool inline = false; + public override bool Inline + { + get { return inline; } + set { inline = value; } + } + + public override JSONNodeType Tag { get { return JSONNodeType.Object; } } + public override bool IsObject { get { return true; } } + + public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); } + + + public override JSONNode this[string aKey] + { + get + { + if (m_Dict.ContainsKey(aKey)) + return m_Dict[aKey]; + else + return new JSONLazyCreator(this, aKey); + } + set + { + if (value == null) + value = JSONNull.CreateOrGet(); + if (m_Dict.ContainsKey(aKey)) + m_Dict[aKey] = value; + else + m_Dict.Add(aKey, value); + } + } + + public override JSONNode this[int aIndex] + { + get + { + if (aIndex < 0 || aIndex >= m_Dict.Count) + return null; + return m_Dict.ElementAt(aIndex).Value; + } + set + { + if (value == null) + value = JSONNull.CreateOrGet(); + if (aIndex < 0 || aIndex >= m_Dict.Count) + return; + string key = m_Dict.ElementAt(aIndex).Key; + m_Dict[key] = value; + } + } + + public override int Count + { + get { return m_Dict.Count; } + } + + public override void Add(string aKey, JSONNode aItem) + { + if (aItem == null) + aItem = JSONNull.CreateOrGet(); + + if (aKey != null) + { + if (m_Dict.ContainsKey(aKey)) + m_Dict[aKey] = aItem; + else + m_Dict.Add(aKey, aItem); + } + else + m_Dict.Add(Guid.NewGuid().ToString(), aItem); + } + + public override JSONNode Remove(string aKey) + { + if (!m_Dict.ContainsKey(aKey)) + return null; + JSONNode tmp = m_Dict[aKey]; + m_Dict.Remove(aKey); + return tmp; + } + + public override JSONNode Remove(int aIndex) + { + if (aIndex < 0 || aIndex >= m_Dict.Count) + return null; + var item = m_Dict.ElementAt(aIndex); + m_Dict.Remove(item.Key); + return item.Value; + } + + public override JSONNode Remove(JSONNode aNode) + { + try + { + var item = m_Dict.Where(k => k.Value == aNode).First(); + m_Dict.Remove(item.Key); + return aNode; + } + catch + { + return null; + } + } + + public override JSONNode Clone() + { + var node = new JSONObject(); + foreach (var n in m_Dict) + { + node.Add(n.Key, n.Value.Clone()); + } + return node; + } + + public override bool HasKey(string aKey) + { + return m_Dict.ContainsKey(aKey); + } + + public override JSONNode GetValueOrDefault(string aKey, JSONNode aDefault) + { + JSONNode res; + if (m_Dict.TryGetValue(aKey, out res)) + return res; + return aDefault; + } + + public override IEnumerable Children + { + get + { + foreach (KeyValuePair N in m_Dict) + yield return N.Value; + } + } + + internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) + { + aSB.Append('{'); + bool first = true; + if (inline) + aMode = JSONTextMode.Compact; + foreach (var k in m_Dict) + { + if (!first) + aSB.Append(','); + first = false; + if (aMode == JSONTextMode.Indent) + aSB.AppendLine(); + if (aMode == JSONTextMode.Indent) + aSB.Append(' ', aIndent + aIndentInc); + aSB.Append('\"').Append(Escape(k.Key)).Append('\"'); + if (aMode == JSONTextMode.Compact) + aSB.Append(':'); + else + aSB.Append(" : "); + k.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); + } + if (aMode == JSONTextMode.Indent) + aSB.AppendLine().Append(' ', aIndent); + aSB.Append('}'); + } + + } + // End of JSONObject + + public partial class JSONString : JSONNode + { + private string m_Data; + + public override JSONNodeType Tag { get { return JSONNodeType.String; } } + public override bool IsString { get { return true; } } + + public override Enumerator GetEnumerator() { return new Enumerator(); } + + + public override string Value + { + get { return m_Data; } + set + { + m_Data = value; + } + } + + public JSONString(string aData) + { + m_Data = aData; + } + public override JSONNode Clone() + { + return new JSONString(m_Data); + } + + internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) + { + aSB.Append('\"').Append(Escape(m_Data)).Append('\"'); + } + public override bool Equals(object obj) + { + if (base.Equals(obj)) + return true; + string s = obj as string; + if (s != null) + return m_Data == s; + JSONString s2 = obj as JSONString; + if (s2 != null) + return m_Data == s2.m_Data; + return false; + } + public override int GetHashCode() + { + return m_Data.GetHashCode(); + } + } + // End of JSONString + + public partial class JSONNumber : JSONNode + { + private double m_Data; + + public override JSONNodeType Tag { get { return JSONNodeType.Number; } } + public override bool IsNumber { get { return true; } } + public override Enumerator GetEnumerator() { return new Enumerator(); } + + public override string Value + { + get { return m_Data.ToString(CultureInfo.InvariantCulture); } + set + { + double v; + if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out v)) + m_Data = v; + } + } + + public override double AsDouble + { + get { return m_Data; } + set { m_Data = value; } + } + public override long AsLong + { + get { return (long)m_Data; } + set { m_Data = value; } + } + + public JSONNumber(double aData) + { + m_Data = aData; + } + + public JSONNumber(string aData) + { + Value = aData; + } + + public override JSONNode Clone() + { + return new JSONNumber(m_Data); + } + + internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) + { + aSB.Append(Value); + } + private static bool IsNumeric(object value) + { + return value is int || value is uint + || value is float || value is double + || value is decimal + || value is long || value is ulong + || value is short || value is ushort + || value is sbyte || value is byte; + } + public override bool Equals(object obj) + { + if (obj == null) + return false; + if (base.Equals(obj)) + return true; + JSONNumber s2 = obj as JSONNumber; + if (s2 != null) + return m_Data == s2.m_Data; + if (IsNumeric(obj)) + return Convert.ToDouble(obj) == m_Data; + return false; + } + public override int GetHashCode() + { + return m_Data.GetHashCode(); + } + } + // End of JSONNumber + + public partial class JSONBool : JSONNode + { + private bool m_Data; + + public override JSONNodeType Tag { get { return JSONNodeType.Boolean; } } + public override bool IsBoolean { get { return true; } } + public override Enumerator GetEnumerator() { return new Enumerator(); } + + public override string Value + { + get { return m_Data.ToString(); } + set + { + bool v; + if (bool.TryParse(value, out v)) + m_Data = v; + } + } + public override bool AsBool + { + get { return m_Data; } + set { m_Data = value; } + } + + public JSONBool(bool aData) + { + m_Data = aData; + } + + public JSONBool(string aData) + { + Value = aData; + } + + public override JSONNode Clone() + { + return new JSONBool(m_Data); + } + + internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) + { + aSB.Append((m_Data) ? "true" : "false"); + } + public override bool Equals(object obj) + { + if (obj == null) + return false; + if (obj is bool) + return m_Data == (bool)obj; + return false; + } + public override int GetHashCode() + { + return m_Data.GetHashCode(); + } + } + // End of JSONBool + + public partial class JSONNull : JSONNode + { + static JSONNull m_StaticInstance = new JSONNull(); + public static bool reuseSameInstance = true; + public static JSONNull CreateOrGet() + { + if (reuseSameInstance) + return m_StaticInstance; + return new JSONNull(); + } + private JSONNull() { } + + public override JSONNodeType Tag { get { return JSONNodeType.NullValue; } } + public override bool IsNull { get { return true; } } + public override Enumerator GetEnumerator() { return new Enumerator(); } + + public override string Value + { + get { return "null"; } + set { } + } + public override bool AsBool + { + get { return false; } + set { } + } + + public override JSONNode Clone() + { + return CreateOrGet(); + } + + public override bool Equals(object obj) + { + if (object.ReferenceEquals(this, obj)) + return true; + return (obj is JSONNull); + } + public override int GetHashCode() + { + return 0; + } + + internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) + { + aSB.Append("null"); + } + } + // End of JSONNull + + internal partial class JSONLazyCreator : JSONNode + { + private JSONNode m_Node = null; + private string m_Key = null; + public override JSONNodeType Tag { get { return JSONNodeType.None; } } + public override Enumerator GetEnumerator() { return new Enumerator(); } + + public JSONLazyCreator(JSONNode aNode) + { + m_Node = aNode; + m_Key = null; + } + + public JSONLazyCreator(JSONNode aNode, string aKey) + { + m_Node = aNode; + m_Key = aKey; + } + + private T Set(T aVal) where T : JSONNode + { + if (m_Key == null) + m_Node.Add(aVal); + else + m_Node.Add(m_Key, aVal); + m_Node = null; // Be GC friendly. + return aVal; + } + + public override JSONNode this[int aIndex] + { + get { return new JSONLazyCreator(this); } + set { Set(new JSONArray()).Add(value); } + } + + public override JSONNode this[string aKey] + { + get { return new JSONLazyCreator(this, aKey); } + set { Set(new JSONObject()).Add(aKey, value); } + } + + public override void Add(JSONNode aItem) + { + Set(new JSONArray()).Add(aItem); + } + + public override void Add(string aKey, JSONNode aItem) + { + Set(new JSONObject()).Add(aKey, aItem); + } + + public static bool operator ==(JSONLazyCreator a, object b) + { + if (b == null) + return true; + return System.Object.ReferenceEquals(a, b); + } + + public static bool operator !=(JSONLazyCreator a, object b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + if (obj == null) + return true; + return System.Object.ReferenceEquals(this, obj); + } + + public override int GetHashCode() + { + return 0; + } + + public override int AsInt + { + get { Set(new JSONNumber(0)); return 0; } + set { Set(new JSONNumber(value)); } + } + + public override float AsFloat + { + get { Set(new JSONNumber(0.0f)); return 0.0f; } + set { Set(new JSONNumber(value)); } + } + + public override double AsDouble + { + get { Set(new JSONNumber(0.0)); return 0.0; } + set { Set(new JSONNumber(value)); } + } + + public override long AsLong + { + get + { + if (longAsString) + Set(new JSONString("0")); + else + Set(new JSONNumber(0.0)); + return 0L; + } + set + { + if (longAsString) + Set(new JSONString(value.ToString())); + else + Set(new JSONNumber(value)); + } + } + + public override bool AsBool + { + get { Set(new JSONBool(false)); return false; } + set { Set(new JSONBool(value)); } + } + + public override JSONArray AsArray + { + get { return Set(new JSONArray()); } + } + + public override JSONObject AsObject + { + get { return Set(new JSONObject()); } + } + internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) + { + aSB.Append("null"); + } + } + // End of JSONLazyCreator + + public static class JSON + { + public static JSONNode Parse(string aJSON) + { + return JSONNode.Parse(aJSON); + } + } +} diff --git a/Assets/Plugins/SimpleJSON.cs.meta b/Assets/Plugins/SimpleJSON.cs.meta new file mode 100644 index 0000000..f43bde5 --- /dev/null +++ b/Assets/Plugins/SimpleJSON.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 13180a8ebaa9dba4f8e4950ae8920385 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/SimpleJSONBinary.cs b/Assets/Plugins/SimpleJSONBinary.cs new file mode 100644 index 0000000..79b96e3 --- /dev/null +++ b/Assets/Plugins/SimpleJSONBinary.cs @@ -0,0 +1,301 @@ +//#define USE_SharpZipLib +/* * * * * + * This is an extension of the SimpleJSON framework to provide methods to + * serialize a JSON object tree into a compact binary format. Optionally the + * binary stream can be compressed with the SharpZipLib when using the define + * "USE_SharpZipLib" + * + * Those methods where originally part of the framework but since it's rarely + * used I've extracted this part into this seperate module file. + * + * You can use the define "SimpleJSON_ExcludeBinary" to selectively disable + * this extension without the need to remove the file from the project. + * + * If you want to use compression when saving to file / stream / B64 you have to include + * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and + * define "USE_SharpZipLib" at the top of the file + * + * + * The MIT License (MIT) + * + * Copyright (c) 2012-2017 Markus Göbel (Bunny83) + * + * 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; + +namespace SimpleJSON +{ +#if !SimpleJSON_ExcludeBinary + public abstract partial class JSONNode + { + public abstract void SerializeBinary(System.IO.BinaryWriter aWriter); + + public void SaveToBinaryStream(System.IO.Stream aData) + { + var W = new System.IO.BinaryWriter(aData); + SerializeBinary(W); + } + +#if USE_SharpZipLib + public void SaveToCompressedStream(System.IO.Stream aData) + { + using (var gzipOut = new ICSharpCode.SharpZipLib.BZip2.BZip2OutputStream(aData)) + { + gzipOut.IsStreamOwner = false; + SaveToBinaryStream(gzipOut); + gzipOut.Close(); + } + } + + public void SaveToCompressedFile(string aFileName) + { + + System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName); + using(var F = System.IO.File.OpenWrite(aFileName)) + { + SaveToCompressedStream(F); + } + } + public string SaveToCompressedBase64() + { + using (var stream = new System.IO.MemoryStream()) + { + SaveToCompressedStream(stream); + stream.Position = 0; + return System.Convert.ToBase64String(stream.ToArray()); + } + } + +#else + public void SaveToCompressedStream(System.IO.Stream aData) + { + throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); + } + + public void SaveToCompressedFile(string aFileName) + { + throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); + } + + public string SaveToCompressedBase64() + { + throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); + } +#endif + + public void SaveToBinaryFile(string aFileName) + { + System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName); + using (var F = System.IO.File.OpenWrite(aFileName)) + { + SaveToBinaryStream(F); + } + } + + public string SaveToBinaryBase64() + { + using (var stream = new System.IO.MemoryStream()) + { + SaveToBinaryStream(stream); + stream.Position = 0; + return System.Convert.ToBase64String(stream.ToArray()); + } + } + + public static JSONNode DeserializeBinary(System.IO.BinaryReader aReader) + { + JSONNodeType type = (JSONNodeType)aReader.ReadByte(); + switch (type) + { + case JSONNodeType.Array: + { + int count = aReader.ReadInt32(); + JSONArray tmp = new JSONArray(); + for (int i = 0; i < count; i++) + tmp.Add(DeserializeBinary(aReader)); + return tmp; + } + case JSONNodeType.Object: + { + int count = aReader.ReadInt32(); + JSONObject tmp = new JSONObject(); + for (int i = 0; i < count; i++) + { + string key = aReader.ReadString(); + var val = DeserializeBinary(aReader); + tmp.Add(key, val); + } + return tmp; + } + case JSONNodeType.String: + { + return new JSONString(aReader.ReadString()); + } + case JSONNodeType.Number: + { + return new JSONNumber(aReader.ReadDouble()); + } + case JSONNodeType.Boolean: + { + return new JSONBool(aReader.ReadBoolean()); + } + case JSONNodeType.NullValue: + { + return JSONNull.CreateOrGet(); + } + default: + { + throw new Exception("Error deserializing JSON. Unknown tag: " + type); + } + } + } + +#if USE_SharpZipLib + public static JSONNode LoadFromCompressedStream(System.IO.Stream aData) + { + var zin = new ICSharpCode.SharpZipLib.BZip2.BZip2InputStream(aData); + return LoadFromBinaryStream(zin); + } + public static JSONNode LoadFromCompressedFile(string aFileName) + { + using(var F = System.IO.File.OpenRead(aFileName)) + { + return LoadFromCompressedStream(F); + } + } + public static JSONNode LoadFromCompressedBase64(string aBase64) + { + var tmp = System.Convert.FromBase64String(aBase64); + var stream = new System.IO.MemoryStream(tmp); + stream.Position = 0; + return LoadFromCompressedStream(stream); + } +#else + public static JSONNode LoadFromCompressedFile(string aFileName) + { + throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); + } + + public static JSONNode LoadFromCompressedStream(System.IO.Stream aData) + { + throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); + } + + public static JSONNode LoadFromCompressedBase64(string aBase64) + { + throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON"); + } +#endif + + public static JSONNode LoadFromBinaryStream(System.IO.Stream aData) + { + using (var R = new System.IO.BinaryReader(aData)) + { + return DeserializeBinary(R); + } + } + + public static JSONNode LoadFromBinaryFile(string aFileName) + { + using (var F = System.IO.File.OpenRead(aFileName)) + { + return LoadFromBinaryStream(F); + } + } + + public static JSONNode LoadFromBinaryBase64(string aBase64) + { + var tmp = System.Convert.FromBase64String(aBase64); + var stream = new System.IO.MemoryStream(tmp); + stream.Position = 0; + return LoadFromBinaryStream(stream); + } + } + + public partial class JSONArray : JSONNode + { + public override void SerializeBinary(System.IO.BinaryWriter aWriter) + { + aWriter.Write((byte)JSONNodeType.Array); + aWriter.Write(m_List.Count); + for (int i = 0; i < m_List.Count; i++) + { + m_List[i].SerializeBinary(aWriter); + } + } + } + + public partial class JSONObject : JSONNode + { + public override void SerializeBinary(System.IO.BinaryWriter aWriter) + { + aWriter.Write((byte)JSONNodeType.Object); + aWriter.Write(m_Dict.Count); + foreach (string K in m_Dict.Keys) + { + aWriter.Write(K); + m_Dict[K].SerializeBinary(aWriter); + } + } + } + + public partial class JSONString : JSONNode + { + public override void SerializeBinary(System.IO.BinaryWriter aWriter) + { + aWriter.Write((byte)JSONNodeType.String); + aWriter.Write(m_Data); + } + } + + public partial class JSONNumber : JSONNode + { + public override void SerializeBinary(System.IO.BinaryWriter aWriter) + { + aWriter.Write((byte)JSONNodeType.Number); + aWriter.Write(m_Data); + } + } + + public partial class JSONBool : JSONNode + { + public override void SerializeBinary(System.IO.BinaryWriter aWriter) + { + aWriter.Write((byte)JSONNodeType.Boolean); + aWriter.Write(m_Data); + } + } + public partial class JSONNull : JSONNode + { + public override void SerializeBinary(System.IO.BinaryWriter aWriter) + { + aWriter.Write((byte)JSONNodeType.NullValue); + } + } + internal partial class JSONLazyCreator : JSONNode + { + public override void SerializeBinary(System.IO.BinaryWriter aWriter) + { + + } + } +#endif +} \ No newline at end of file diff --git a/Assets/Plugins/SimpleJSONBinary.cs.meta b/Assets/Plugins/SimpleJSONBinary.cs.meta new file mode 100644 index 0000000..204ea07 --- /dev/null +++ b/Assets/Plugins/SimpleJSONBinary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 739df7dcad852b2469ca1d80b2e36a1e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/SimpleJSONUnity.cs b/Assets/Plugins/SimpleJSONUnity.cs new file mode 100644 index 0000000..d6485a7 --- /dev/null +++ b/Assets/Plugins/SimpleJSONUnity.cs @@ -0,0 +1,369 @@ +#region License and information +/* * * * * + * + * Unity extension for the SimpleJSON framework. It does only work together with + * the SimpleJSON.cs + * It provides several helpers and conversion operators to serialize/deserialize + * common Unity types such as Vector2/3/4, Rect, RectOffset, Quaternion and + * Matrix4x4 as JSONObject or JSONArray. + * This extension will add 3 static settings to the JSONNode class: + * ( VectorContainerType, QuaternionContainerType, RectContainerType ) which + * control what node type should be used for serializing the given type. So a + * Vector3 as array would look like [12,32,24] and {"x":12, "y":32, "z":24} as + * object. + * + * + * The MIT License (MIT) + * + * Copyright (c) 2012-2017 Markus Göbel (Bunny83) + * + * 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. + * + * * * * */ + +#endregion License and information + +using UnityEngine; + +namespace SimpleJSON +{ + public enum JSONContainerType { Array, Object } + public partial class JSONNode + { + public static JSONContainerType VectorContainerType = JSONContainerType.Array; + public static JSONContainerType QuaternionContainerType = JSONContainerType.Array; + public static JSONContainerType RectContainerType = JSONContainerType.Array; + private static JSONNode GetContainer(JSONContainerType aType) + { + if (aType == JSONContainerType.Array) + return new JSONArray(); + return new JSONObject(); + } + + #region implicit conversion operators + public static implicit operator JSONNode(Vector2 aVec) + { + JSONNode n = GetContainer(VectorContainerType); + n.WriteVector2(aVec); + return n; + } + public static implicit operator JSONNode(Vector3 aVec) + { + JSONNode n = GetContainer(VectorContainerType); + n.WriteVector3(aVec); + return n; + } + public static implicit operator JSONNode(Vector4 aVec) + { + JSONNode n = GetContainer(VectorContainerType); + n.WriteVector4(aVec); + return n; + } + public static implicit operator JSONNode(Quaternion aRot) + { + JSONNode n = GetContainer(QuaternionContainerType); + n.WriteQuaternion(aRot); + return n; + } + public static implicit operator JSONNode(Rect aRect) + { + JSONNode n = GetContainer(RectContainerType); + n.WriteRect(aRect); + return n; + } + public static implicit operator JSONNode(RectOffset aRect) + { + JSONNode n = GetContainer(RectContainerType); + n.WriteRectOffset(aRect); + return n; + } + + public static implicit operator Vector2(JSONNode aNode) + { + return aNode.ReadVector2(); + } + public static implicit operator Vector3(JSONNode aNode) + { + return aNode.ReadVector3(); + } + public static implicit operator Vector4(JSONNode aNode) + { + return aNode.ReadVector4(); + } + public static implicit operator Quaternion(JSONNode aNode) + { + return aNode.ReadQuaternion(); + } + public static implicit operator Rect(JSONNode aNode) + { + return aNode.ReadRect(); + } + public static implicit operator RectOffset(JSONNode aNode) + { + return aNode.ReadRectOffset(); + } + #endregion implicit conversion operators + + #region Vector2 + public Vector2 ReadVector2(Vector2 aDefault) + { + if (IsObject) + return new Vector2(this["x"].AsFloat, this["y"].AsFloat); + if (IsArray) + return new Vector2(this[0].AsFloat, this[1].AsFloat); + return aDefault; + } + public Vector2 ReadVector2(string aXName, string aYName) + { + if (IsObject) + { + return new Vector2(this[aXName].AsFloat, this[aYName].AsFloat); + } + return Vector2.zero; + } + + public Vector2 ReadVector2() + { + return ReadVector2(Vector2.zero); + } + public JSONNode WriteVector2(Vector2 aVec, string aXName = "x", string aYName = "y") + { + if (IsObject) + { + Inline = true; + this[aXName].AsFloat = aVec.x; + this[aYName].AsFloat = aVec.y; + } + else if (IsArray) + { + Inline = true; + this[0].AsFloat = aVec.x; + this[1].AsFloat = aVec.y; + } + return this; + } + #endregion Vector2 + + #region Vector3 + public Vector3 ReadVector3(Vector3 aDefault) + { + if (IsObject) + return new Vector3(this["x"].AsFloat, this["y"].AsFloat, this["z"].AsFloat); + if (IsArray) + return new Vector3(this[0].AsFloat, this[1].AsFloat, this[2].AsFloat); + return aDefault; + } + public Vector3 ReadVector3(string aXName, string aYName, string aZName) + { + if (IsObject) + return new Vector3(this[aXName].AsFloat, this[aYName].AsFloat, this[aZName].AsFloat); + return Vector3.zero; + } + public Vector3 ReadVector3() + { + return ReadVector3(Vector3.zero); + } + public JSONNode WriteVector3(Vector3 aVec, string aXName = "x", string aYName = "y", string aZName = "z") + { + if (IsObject) + { + Inline = true; + this[aXName].AsFloat = aVec.x; + this[aYName].AsFloat = aVec.y; + this[aZName].AsFloat = aVec.z; + } + else if (IsArray) + { + Inline = true; + this[0].AsFloat = aVec.x; + this[1].AsFloat = aVec.y; + this[2].AsFloat = aVec.z; + } + return this; + } + #endregion Vector3 + + #region Vector4 + public Vector4 ReadVector4(Vector4 aDefault) + { + if (IsObject) + return new Vector4(this["x"].AsFloat, this["y"].AsFloat, this["z"].AsFloat, this["w"].AsFloat); + if (IsArray) + return new Vector4(this[0].AsFloat, this[1].AsFloat, this[2].AsFloat, this[3].AsFloat); + return aDefault; + } + public Vector4 ReadVector4() + { + return ReadVector4(Vector4.zero); + } + public JSONNode WriteVector4(Vector4 aVec) + { + if (IsObject) + { + Inline = true; + this["x"].AsFloat = aVec.x; + this["y"].AsFloat = aVec.y; + this["z"].AsFloat = aVec.z; + this["w"].AsFloat = aVec.w; + } + else if (IsArray) + { + Inline = true; + this[0].AsFloat = aVec.x; + this[1].AsFloat = aVec.y; + this[2].AsFloat = aVec.z; + this[3].AsFloat = aVec.w; + } + return this; + } + #endregion Vector4 + + #region Quaternion + public Quaternion ReadQuaternion(Quaternion aDefault) + { + if (IsObject) + return new Quaternion(this["x"].AsFloat, this["y"].AsFloat, this["z"].AsFloat, this["w"].AsFloat); + if (IsArray) + return new Quaternion(this[0].AsFloat, this[1].AsFloat, this[2].AsFloat, this[3].AsFloat); + return aDefault; + } + public Quaternion ReadQuaternion() + { + return ReadQuaternion(Quaternion.identity); + } + public JSONNode WriteQuaternion(Quaternion aRot) + { + if (IsObject) + { + Inline = true; + this["x"].AsFloat = aRot.x; + this["y"].AsFloat = aRot.y; + this["z"].AsFloat = aRot.z; + this["w"].AsFloat = aRot.w; + } + else if (IsArray) + { + Inline = true; + this[0].AsFloat = aRot.x; + this[1].AsFloat = aRot.y; + this[2].AsFloat = aRot.z; + this[3].AsFloat = aRot.w; + } + return this; + } + #endregion Quaternion + + #region Rect + public Rect ReadRect(Rect aDefault) + { + if (IsObject) + return new Rect(this["x"].AsFloat, this["y"].AsFloat, this["width"].AsFloat, this["height"].AsFloat); + if (IsArray) + return new Rect(this[0].AsFloat, this[1].AsFloat, this[2].AsFloat, this[3].AsFloat); + return aDefault; + } + public Rect ReadRect() + { + return ReadRect(new Rect()); + } + public JSONNode WriteRect(Rect aRect) + { + if (IsObject) + { + Inline = true; + this["x"].AsFloat = aRect.x; + this["y"].AsFloat = aRect.y; + this["width"].AsFloat = aRect.width; + this["height"].AsFloat = aRect.height; + } + else if (IsArray) + { + Inline = true; + this[0].AsFloat = aRect.x; + this[1].AsFloat = aRect.y; + this[2].AsFloat = aRect.width; + this[3].AsFloat = aRect.height; + } + return this; + } + #endregion Rect + + #region RectOffset + public RectOffset ReadRectOffset(RectOffset aDefault) + { + if (this is JSONObject) + return new RectOffset(this["left"].AsInt, this["right"].AsInt, this["top"].AsInt, this["bottom"].AsInt); + if (this is JSONArray) + return new RectOffset(this[0].AsInt, this[1].AsInt, this[2].AsInt, this[3].AsInt); + return aDefault; + } + public RectOffset ReadRectOffset() + { + return ReadRectOffset(new RectOffset()); + } + public JSONNode WriteRectOffset(RectOffset aRect) + { + if (IsObject) + { + Inline = true; + this["left"].AsInt = aRect.left; + this["right"].AsInt = aRect.right; + this["top"].AsInt = aRect.top; + this["bottom"].AsInt = aRect.bottom; + } + else if (IsArray) + { + Inline = true; + this[0].AsInt = aRect.left; + this[1].AsInt = aRect.right; + this[2].AsInt = aRect.top; + this[3].AsInt = aRect.bottom; + } + return this; + } + #endregion RectOffset + + #region Matrix4x4 + public Matrix4x4 ReadMatrix() + { + Matrix4x4 result = Matrix4x4.identity; + if (IsArray) + { + for (int i = 0; i < 16; i++) + { + result[i] = this[i].AsFloat; + } + } + return result; + } + public JSONNode WriteMatrix(Matrix4x4 aMatrix) + { + if (IsArray) + { + Inline = true; + for (int i = 0; i < 16; i++) + { + this[i].AsFloat = aMatrix[i]; + } + } + return this; + } + #endregion Matrix4x4 + } +} \ No newline at end of file diff --git a/Assets/Plugins/SimpleJSONUnity.cs.meta b/Assets/Plugins/SimpleJSONUnity.cs.meta new file mode 100644 index 0000000..a97e7b0 --- /dev/null +++ b/Assets/Plugins/SimpleJSONUnity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2661a71996161a247aaea5b3fa900cca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Main.unity b/Assets/Scenes/Main.unity index b801af2..e1e5c10 100644 --- a/Assets/Scenes/Main.unity +++ b/Assets/Scenes/Main.unity @@ -198,8 +198,13 @@ MonoBehaviour: twistCursor: {x: 0, y: 0, z: 0} stretchCursor: {x: 0, y: 0, z: 0} pixelgon: - vectors: [] - quads: + vectors: + - {x: 0, y: 0, z: 0} + - {x: -0.3, y: -0.3, z: 0} + - {x: -0.3, y: 0.3, z: 0} + - {x: 0.3, y: -0.43, z: 0} + - {x: 0, y: 0, z: 0} + quads: 010000000200000003000000 assetSpace: folderPath: C:/dofdev/Pixelgon/Assets/AssetSpace name: draft @@ -218,8 +223,6 @@ MonoBehaviour: cursorPos: {x: 0, y: 0, z: 0} indexQuad: 0 quad: - tris: - uvs: [] toolEraser: cursorPos: {x: 0, y: 0, z: 0} selected: diff --git a/Assets/Scripts/AssetSpace.cs b/Assets/Scripts/AssetSpace.cs index a09c7b4..63dfcbc 100644 --- a/Assets/Scripts/AssetSpace.cs +++ b/Assets/Scripts/AssetSpace.cs @@ -1,10 +1,9 @@ using UnityEngine; using System; using System.IO; -using System.Runtime.Serialization.Formatters.Binary; using System.Collections; using System.Collections.Generic; -using SerializableTypes; +using SimpleJSON; [Serializable] public class AssetSpace @@ -124,45 +123,59 @@ public class AssetSpace public void Save(Pixelgon pixelgon) { - string destination = folderPath + "/" + name + ".pixelgon"; - FileStream file; - - if (File.Exists(destination)) file = File.OpenWrite(destination); - else file = File.Create(destination); - - BinaryFormatter bf = new BinaryFormatter(); - FPixelgon fPixelgon = new FPixelgon(); - fPixelgon.vectors = new SVector3[pixelgon.vectors.Count]; - for (int i = 0; i < pixelgon.vectors.Count; i++) + // Cleanup Empty Vectors and re-index quads + int dup = 0; + for (int i = pixelgon.vectors.Count - 1; i >= 0; i--) { - SVector3 vec3 = pixelgon.vectors[i]; - fPixelgon.vectors[i] = vec3; + if (pixelgon.vectors[i] == Vector3.zero) + { + if (dup++ > 0) + { + for (int j = 0; j < pixelgon.quads.Count; j++) + { + if (pixelgon.quads[j] >= i) + { + pixelgon.quads[j]--; + } + } + + pixelgon.vectors.RemoveAt(i); + } + } + else + { + dup = 0; + } } - bf.Serialize(file, fPixelgon); - file.Close(); + + string destination = folderPath + "/" + name + ".json"; + File.WriteAllText(destination, JsonUtility.ToJson(pixelgon)); } public Pixelgon Load() { - string destination = folderPath + "/" + name + ".pixelgon"; - FileStream file; - - if (File.Exists(destination)) file = File.OpenRead(destination); - else + string destination = folderPath + "/" + name + ".json"; + if (!File.Exists(destination)) { Debug.LogError("File not found"); return null; } - BinaryFormatter bf = new BinaryFormatter(); - FPixelgon fPixelgon = (FPixelgon)bf.Deserialize(file); + JSONNode N = JSON.Parse(File.ReadAllText(destination)); + Pixelgon pixelgon = new Pixelgon(); - for (int i = 0; i < fPixelgon.vectors.Length; i++) + pixelgon.vectors.Clear(); + for (int i = 0; i < N["vectors"].Count; i++) { - Vector3 vec3 = fPixelgon.vectors[i]; - pixelgon.vectors.Add(vec3); + pixelgon.vectors.Add( + new Vector3(N["vectors"][i][0].AsFloat, N["vectors"][i][1].AsFloat, N["vectors"][i][2].AsFloat) + ); + } + pixelgon.quads.Clear(); + for (int i = 0; i < N["quads"].Count; i++) + { + pixelgon.quads.Add(N["quads"][i].AsInt); } - file.Close(); return pixelgon; } } @@ -173,125 +186,4 @@ public class Asset public Mesh mesh; public Vector3 pos; public Quaternion rot; -} - -[Serializable] -public class FAssetSpace -{ - // public class Placement - // { - // public SerializableVector3 pos - // } -} - -[Serializable] -public class FPixelgon -{ - public SVector3[] vectors; -} - -namespace SerializableTypes -{ - /// Serializable version of UnityEngine.Vector3. - [Serializable] - public struct SVector3 - { - public float x; - public float y; - public float z; - - public SVector3(float x, float y, float z) - { - this.x = x; - this.y = y; - this.z = z; - } - - public override string ToString() - => $"[x, y, z]"; - - public static implicit operator Vector3(SVector3 s) - => new Vector3(s.x, s.y, s.z); - - public static implicit operator SVector3(Vector3 v) - => new SVector3(v.x, v.y, v.z); - - - public static SVector3 operator +(SVector3 a, SVector3 b) - => new SVector3(a.x + b.x, a.y + b.y, a.z + b.z); - - public static SVector3 operator -(SVector3 a, SVector3 b) - => new SVector3(a.x - b.x, a.y - b.y, a.z - b.z); - - public static SVector3 operator -(SVector3 a) - => new SVector3(-a.x, -a.y, -a.z); - - public static SVector3 operator *(SVector3 a, float m) - => new SVector3(a.x * m, a.y * m, a.z * m); - - public static SVector3 operator *(float m, SVector3 a) - => new SVector3(a.x * m, a.y * m, a.z * m); - - public static SVector3 operator /(SVector3 a, float d) - => new SVector3(a.x / d, a.y / d, a.z / d); - } - - /// Serializable version of UnityEngine.Quaternion. - [Serializable] - public struct SQuaternion - { - public float x; - public float y; - public float z; - public float w; - - public SQuaternion(float x, float y, float z, float w) - { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - } - - public override string ToString() - => $"[{x}, {y}, {z}, {w}]"; - - public static implicit operator Quaternion(SQuaternion s) - => new Quaternion(s.x, s.y, s.z, s.w); - - public static implicit operator SQuaternion(Quaternion q) - => new SQuaternion(q.x, q.y, q.z, q.w); - } - - /// Serializable version of UnityEngine.Color32 without transparency. - [Serializable] - public struct SColor32 - { - public byte r; - public byte g; - public byte b; - - public SColor32(byte r, byte g, byte b) - { - this.r = r; - this.g = g; - this.b = b; - } - - public SColor32(Color32 c) - { - r = c.r; - g = c.g; - b = c.b; - } - - public override string ToString() - => $"[{r}, {g}, {b}]"; - - public static implicit operator Color32(SColor32 rValue) - => new Color32(rValue.r, rValue.g, rValue.b, a: byte.MaxValue); - - public static implicit operator SColor32(Color32 rValue) - => new SColor32(rValue.r, rValue.g, rValue.b); - } } \ No newline at end of file