Tanoda
GameObjectSerializer.cs
Go to the documentation of this file.
1using B83.MeshTools;
2using System.Collections.Generic;
3using System.IO;
4using System.Runtime.InteropServices;
5using UnityEngine;
6
7
8[System.Serializable]
9public struct MatData
10{
11 public int textureLength;
12 public Vector2 textureSize;
13 public TextureFormat textureFormat;
14 public byte[] texture;
15 public int metallicLength;
16 public Vector2 metallicSize;
17 public TextureFormat metallicFormat;
18 public byte[] metallic;
19 public int normalLength;
20 public Vector2 normalSize;
21 public TextureFormat normalFormat;
22 public byte[] normal;
23 public int occlusionLength;
24 public Vector2 occlusionSize;
25 public TextureFormat occlusionFormat;
26 public byte[] occlusion;
27 public float fMetallic, fSmoothness;
28 public Color color;
29}
30
31[System.Serializable]
32public struct GameObjectData
33{
34 //public short NameLength;
35 public string Name;
36 public byte Type;
37 public Vector3 Position;
38 public Vector3 Rotation;
39 public Vector3 Scale;
40 public int X, Y;
41 public int MeshLength;
42 public byte[] MeshData;
43 public short MaterialCount;
44 public List<MatData> Materials;
45 public short ChildrenCount;
46 public List<GameObjectData> Children;
47}
48
49
50public static class GameObjectSerializer
51{
52 public static byte[] SerializeGameObject(GameObject go, bool recursive = false)
53 {
54 using (var stream = new MemoryStream())
55 using (var writer = new BinaryWriter(stream))
56 {
57 writer.WriteGameObject(go, recursive);
58 return stream.ToArray();
59 }
60 }
61 public static GameObject DeserializeGameObject(byte[] array, Transform wrapper = null)
62 {
63 using (var stream = new MemoryStream(array))
64 using (var reader = new BinaryReader(stream))
65 {
66 return reader.ReadGameObject(wrapper);
67 }
68 }
69}
70
71public static class BinaryReaderWriterUnityExt
72{
73 public static T RbAaA<T>(byte[] data, int Adress) where T : struct
74 {
75 int ByteSize = 0;
76 ByteSize = Marshal.SizeOf(typeof(T)); // Get ByteSize Of DataType
77 byte[] buffer = new byte[ByteSize]; // Create A Buffer With Size Of ByteSize
78 System.Array.Copy(data, Adress, buffer, 0, buffer.Length);
79 return BATTY<T>(buffer); // Transform the ByteArray to The Desired DataType
80 }
81 private static T BATTY<T>(byte[] bytes) where T : struct
82 {
83 var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
84 try
85 {
86 return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
87 }
88 finally
89 {
90 handle.Free();
91 }
92 }
93 public static void WriteVector2(this BinaryWriter aWriter, Vector2 aVec)
94 {
95 aWriter.Write(aVec.x); aWriter.Write(aVec.y);
96 }
97 public static Vector2 ReadVector2(this BinaryReader aReader)
98 {
99 return new Vector2(aReader.ReadSingle(), aReader.ReadSingle());
100 }
101 public static void WriteVector3(this BinaryWriter aWriter, Vector3 aVec)
102 {
103 aWriter.Write(aVec.x); aWriter.Write(aVec.y); aWriter.Write(aVec.z);
104 }
105 public static Vector3 ReadVector3(this BinaryReader aReader)
106 {
107 return new Vector3(aReader.ReadSingle(), aReader.ReadSingle(), aReader.ReadSingle());
108 }
109 public static void WriteVector4(this BinaryWriter aWriter, Vector4 aVec)
110 {
111 aWriter.Write(aVec.x); aWriter.Write(aVec.y); aWriter.Write(aVec.z); aWriter.Write(aVec.w);
112 }
113 public static Vector4 ReadVector4(this BinaryReader aReader)
114 {
115 return new Vector4(aReader.ReadSingle(), aReader.ReadSingle(), aReader.ReadSingle(), aReader.ReadSingle());
116 }
117
118 public static void WriteColor(this BinaryWriter aWriter, Color aCol)
119 {
120 aWriter.Write(aCol.r); aWriter.Write(aCol.g); aWriter.Write(aCol.b); aWriter.Write(aCol.a);
121 }
122 public static Color ReadColor(this BinaryReader aReader)
123 {
124 return new Color(aReader.ReadSingle(), aReader.ReadSingle(), aReader.ReadSingle(), aReader.ReadSingle());
125 }
126
127 static GameObjectData GOtoGOD(GameObject go, bool recursive = false)
128 {
129 var god = new GameObjectData();
130 god.Name = go.name;
131 god.Type = go.GetComponent<MeshFilter>() ? (byte)0 : go.GetComponent<UnityEngine.UI.RawImage>() ? (byte)1 : (byte)255;
132 god.Position = go.transform.position;
133 god.Rotation = go.transform.eulerAngles;
134 god.Scale = go.transform.lossyScale;
135 god.X = 0;
136 god.Y = 0;
137 if (god.Type == 0)
138 {
139 var mf = go.GetComponent<MeshFilter>();
140 if (mf != null)
141 {
142 god.MeshData = MeshSerializer.SerializeMesh(mf.mesh);
143 god.MeshLength = god.MeshData.Length;
144 }
145 var mr = go.GetComponent<MeshRenderer>();
146 god.MaterialCount = 0;
147 if (mr != null)
148 {
149 god.MaterialCount = (short)mr.materials.Length;
150 var list = new List<MatData>();
151 for (int i = 0; i < mr.materials.Length; i++)
152 {
153 var mat = mr.materials[i];
154 var matData = new MatData();
155 if (mat.HasProperty("_MainTex"))
156 {
157 Texture2D texture2D = duplicateTexture((Texture2D)mat.GetTexture("_MainTex"));
158
159 matData.texture = (texture2D)?.GetRawTextureData();
160 if (texture2D)
161 matData.textureFormat = texture2D.format;
162 if (matData.texture != null)
163 {
164 matData.textureLength = matData.texture.Length;
165 matData.textureSize = new Vector2(texture2D.width, texture2D.height);
166 }
167 }
168 if (mat.HasProperty("_MetallicGlossMap"))
169 {
170 Texture2D texture2D = duplicateTexture((Texture2D)mat.GetTexture("_MetallicGlossMap"));
171 matData.metallic = (texture2D)?.GetRawTextureData();
172 if (texture2D)
173 matData.metallicFormat = texture2D.format;
174 if (matData.metallic != null)
175 {
176 matData.metallicLength = matData.metallic.Length;
177 matData.metallicSize = new Vector2(texture2D.width, texture2D.height);
178 }
179 }
180 if (mat.HasProperty("_BumpMap"))
181 {
182 Texture2D texture2D = duplicateTexture((Texture2D)mat.GetTexture("_BumpMap"));
183 matData.normal = (texture2D)?.GetRawTextureData();
184 if (texture2D)
185 matData.normalFormat = texture2D.format;
186 if (matData.normal != null)
187 {
188 matData.normalLength = matData.normal.Length;
189 matData.normalSize = new Vector2(texture2D.width, texture2D.height);
190 }
191 }
192 if (mat.HasProperty("_OcclusionMap"))
193 {
194 Texture2D texture2D = duplicateTexture((Texture2D)mat.GetTexture("_OcclusionMap"));
195 matData.occlusion = (texture2D)?.GetRawTextureData();
196 if (texture2D)
197 matData.occlusionFormat = texture2D.format;
198 if (matData.occlusion != null)
199 {
200 matData.occlusionLength = matData.occlusion.Length;
201 matData.occlusionSize = new Vector2(texture2D.width, texture2D.height);
202 }
203 }
204 if (mat.HasProperty("_Metallic"))
205 matData.fMetallic = mat.GetFloat("_Metallic");
206 if (mat.HasProperty("_Glossiness"))
207 matData.fSmoothness = mat.GetFloat("_Glossiness");
208 if (mat.HasProperty("_Color"))
209 matData.color = mat.GetColor("_Color");
210
211 list.Add(matData);
212 }
213 god.Materials = list;
214 }
215
216 }
217 if (god.Type == 1)
218 {
219 var ri = go.GetComponent<UnityEngine.UI.RawImage>();
220 god.X = ri.texture.width;
221 god.Y = ri.texture.height;
222 god.MeshData = duplicateTexture((Texture2D)ri.texture)?.GetRawTextureData();;
223 god.MeshLength = god.MeshData.Length;
224 god.MaterialCount = 0;
225 }
226 if (recursive)
227 {
228 god.ChildrenCount = (short)go.transform.childCount;
229 god.Children = new List<GameObjectData>();
230 if (go.transform.childCount > 0)
231 {
232 foreach (Transform child in go.transform)
233 {
234 god.Children.Add(GOtoGOD(child.gameObject, true));
235 }
236 }
237 }
238 else
239 {
240 god.ChildrenCount = 0;
241 god.Children = new List<GameObjectData>();
242 }
243 return god;
244 }
245
246 static GameObject GODtoGO(GameObjectData god, Transform wrapper = null)
247 {
248 var go = new GameObject();
249 if (wrapper)
250 go.transform.SetParent(wrapper, true);
251 go.name = god.Name;
252 go.transform.position = god.Position;
253 go.transform.eulerAngles = god.Rotation;
254 go.transform.localScale = god.Scale;
255 if (god.Type == 0) //MESH
256 {
257 var mf = go.AddComponent<MeshFilter>();
258 MeshSerializer.DeserializeMesh(god.MeshData, mf.mesh);
259 var mr = go.AddComponent<MeshRenderer>();
260 mr.materials = new Material[god.MaterialCount];
261 for (int i = 0; i < god.Materials.Count; i++)
262 {
263 var matData = god.Materials[i];
264
265 if (mr.materials[i].HasProperty("_MainTex"))
266 {
267 if (matData.texture != null && matData.texture.Length > 0)
268 {
269 var texture = new Texture2D((int)matData.textureSize.x, (int)matData.textureSize.y, matData.textureFormat, false);
270 texture.LoadRawTextureData(matData.texture);
271 texture.Apply();
272 mr.materials[i].SetTexture("_MainTex", texture);
273 }
274 }
275 if (mr.materials[i].HasProperty("_MetallicGlossMap"))
276 {
277 if (matData.metallic != null && matData.metallic.Length > 0)
278 {
279 var texture = new Texture2D((int)matData.metallicSize.x, (int)matData.metallicSize.y, matData.metallicFormat, false);
280 texture.LoadRawTextureData(matData.metallic);
281 texture.Apply();
282 mr.materials[i].SetTexture("_MetallicGlossMap", texture);
283 }
284 }
285 if (mr.materials[i].HasProperty("_BumpMap"))
286 {
287 if (matData.normal != null && matData.normal.Length > 0)
288 {
289 var texture = new Texture2D((int)matData.normalSize.x, (int)matData.normalSize.y, matData.normalFormat, false);
290 texture.LoadRawTextureData(matData.normal);
291 texture.Apply();
292 mr.materials[i].SetTexture("_BumpMap", texture);
293 }
294 }
295 if (mr.materials[i].HasProperty("_OcclusionMap"))
296 {
297 if (matData.occlusion != null && matData.occlusion.Length > 0)
298 {
299 var texture = new Texture2D((int)matData.occlusionSize.x, (int)matData.occlusionSize.y, matData.occlusionFormat, false);
300 texture.LoadRawTextureData(matData.occlusion);
301 texture.Apply();
302 mr.materials[i].SetTexture("_OcclusionMap", texture);
303 }
304 }
305 if (mr.materials[i].HasProperty("_Metallic"))
306 mr.materials[i].SetFloat("_Metallic", matData.fMetallic);
307 if (mr.materials[i].HasProperty("_Glossiness"))
308 mr.materials[i].SetFloat("_Glossiness", matData.fSmoothness);
309 if (mr.materials[i].HasProperty("_Color"))
310 mr.materials[i].SetColor("_Color", matData.color);
311 }
312 }
313
314 if (god.Type == 1) //IMAGE
315 {
316 var ri = go.AddComponent<UnityEngine.UI.RawImage>();
317 var texture = new Texture2D(god.X, god.Y);
318 texture.LoadRawTextureData(god.MeshData);
319 texture.Apply();
320 ri.texture = texture;
321 var canvas = go.AddComponent<Canvas>();
322 canvas.renderMode = RenderMode.WorldSpace;
323 var rt = go.GetComponent<RectTransform>();
324 rt.sizeDelta = Vector2.one;
325 }
326
327 foreach (var c in god.Children)
328 GODtoGO(c, go.transform);
329 Debug.Log($"serialized '{go.name}'");
330
331 return go;
332 }
333 public static void WriteGameObject(this BinaryWriter aWriter, GameObject aGo, bool recursive = false)
334 {
335 aWriter.WriteGameObjectData(GOtoGOD(aGo, recursive));
336 }
337 public static void WriteGameObjectData(this BinaryWriter aWriter, GameObjectData aGod)
338 {
339 //aWriter.Write(aGod.NameLength);
340 aWriter.Write(aGod.Name);
341 aWriter.Write(aGod.Type);
342 aWriter.WriteVector3(aGod.Position);
343 aWriter.WriteVector3(aGod.Rotation);
344 aWriter.WriteVector3(aGod.Scale);
345 aWriter.Write(aGod.X);
346 aWriter.Write(aGod.Y);
347 aWriter.Write(aGod.MeshLength);
348 if (aGod.MeshLength > 0)
349 aWriter.Write(aGod.MeshData);
350 aWriter.Write(aGod.MaterialCount);
351 if (aGod.MaterialCount != 0)
352 foreach (var mat in aGod.Materials)
353 aWriter.WriteMatData(mat);
354 aWriter.Write(aGod.ChildrenCount);
355 foreach (var child in aGod.Children)
356 aWriter.WriteGameObjectData(child);
357
358 }
359
360 static Texture2D duplicateTexture(Texture2D source)
361 {
362 if (source == null) return null;
363 RenderTexture renderTex = RenderTexture.GetTemporary(
364 source.width,
365 source.height,
366 0,
367 RenderTextureFormat.Default,
368 RenderTextureReadWrite.Linear);
369
370 Graphics.Blit(source, renderTex);
371 RenderTexture previous = RenderTexture.active;
372 RenderTexture.active = renderTex;
373 Texture2D readableText = new Texture2D(source.width, source.height);
374 readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
375 readableText.Apply();
376 RenderTexture.active = previous;
377 RenderTexture.ReleaseTemporary(renderTex);
378 return readableText;
379 }
380
381 public static GameObject ReadGameObject(this BinaryReader aReader, Transform wrapper = null)
382 {
383 return GODtoGO(aReader.ReadGameObjectData(), wrapper);
384 }
385 public static GameObjectData ReadGameObjectData(this BinaryReader aReader)
386 {
387 //var nameLength = aReader.ReadInt16();
388 var name = aReader.ReadString();
389 var type = aReader.ReadByte();
390 var pos = aReader.ReadVector3();
391 var rot = aReader.ReadVector3();
392 var scale = aReader.ReadVector3();
393 var x = aReader.ReadInt32();
394 var y = aReader.ReadInt32();
395 var meshLength = aReader.ReadInt32();
396 var mesh = aReader.ReadBytes(meshLength);
397 var materialCount = aReader.ReadInt16();
398 var matList = new List<MatData>();
399 for (int i = 0; i < materialCount; i++)
400 matList.Add(aReader.ReadMatData());
401 var childrenCount = aReader.ReadInt16();
402 var childList = new List<GameObjectData>();
403 for (int i = 0; (i < childrenCount); i++)
404 childList.Add(aReader.ReadGameObjectData());
405
406
407
408 return new GameObjectData()
409 {
410 Name = name,
411 Type = type,
412 Position = pos,
413 Rotation = rot,
414 Scale = scale,
415 X = x,
416 Y = y,
417 MeshLength = meshLength,
418 MeshData = mesh,
419 MaterialCount = materialCount,
420 Materials = matList,
421 ChildrenCount = childrenCount,
422 Children = childList
423 };
424 }
425 public static void WriteMatData(this BinaryWriter aWriter, MatData aMat)
426 {
427 aWriter.Write(aMat.textureLength);
428 aWriter.WriteVector2(aMat.textureSize);
429 aWriter.Write((int)aMat.textureFormat);
430 if (aMat.textureLength > 0)
431 aWriter.Write(aMat.texture);
432 aWriter.Write(aMat.metallicLength);
433 aWriter.WriteVector2(aMat.metallicSize);
434 aWriter.Write((int)aMat.metallicFormat);
435 if (aMat.metallicLength > 0)
436 aWriter.Write(aMat.metallic);
437 aWriter.Write(aMat.normalLength);
438 aWriter.WriteVector2(aMat.normalSize);
439 aWriter.Write((int)aMat.normalFormat);
440 if (aMat.normalLength > 0)
441 aWriter.Write(aMat.normal);
442 aWriter.Write(aMat.occlusionLength);
443 aWriter.WriteVector2(aMat.occlusionSize);
444 aWriter.Write((int)aMat.occlusionFormat);
445 if (aMat.occlusionLength > 0)
446 aWriter.Write(aMat.occlusion);
447 aWriter.Write(aMat.fMetallic);
448 aWriter.Write(aMat.fSmoothness);
449 aWriter.WriteColor(aMat.color);
450 }
451 public static MatData ReadMatData(this BinaryReader aReader)
452 {
453 var tL = aReader.ReadInt32();
454 var tS = aReader.ReadVector2();
455 var tF = (TextureFormat)aReader.ReadInt32(); // sizeof(TextureFormat) = 4
456 var t = aReader.ReadBytes(tL);
457 var mL = aReader.ReadInt32();
458 var mS = aReader.ReadVector2();
459 var mF = (TextureFormat)aReader.ReadInt32();
460 var m = aReader.ReadBytes(mL);
461 var nL = aReader.ReadInt32();
462 var nS = aReader.ReadVector2();
463 var nF = (TextureFormat)aReader.ReadInt32();
464 var n = aReader.ReadBytes(nL);
465 var oL = aReader.ReadInt32();
466 var oS = aReader.ReadVector2();
467 var oF = (TextureFormat)aReader.ReadInt32();
468 var o = aReader.ReadBytes(oL);
469 var mf = aReader.ReadSingle();
470 var sf = aReader.ReadSingle();
471 var c = aReader.ReadColor();
472
473 var aMat = new MatData()
474 {
475 textureLength = tL,
476 textureSize = tS,
477 textureFormat = tF,
478 texture = t,
479 metallicLength = mL,
480 metallicSize = mS,
481 metallicFormat = mF,
482 metallic = m,
483 normalLength = nL,
484 normalSize = nS,
485 normalFormat = nF,
486 normal = n,
487 occlusionLength = oL,
488 occlusionSize = oS,
489 occlusionFormat = oF,
490 occlusion = o,
491 fMetallic = mf,
492 fSmoothness = sf,
493 color = c
494 };
495 return aMat;
496 }
497
498 public static void WriteMatrix4x4(this BinaryWriter aWriter, Matrix4x4 aMat)
499 {
500 aWriter.Write(aMat.m00); aWriter.Write(aMat.m01); aWriter.Write(aMat.m02); aWriter.Write(aMat.m03);
501 aWriter.Write(aMat.m10); aWriter.Write(aMat.m11); aWriter.Write(aMat.m12); aWriter.Write(aMat.m13);
502 aWriter.Write(aMat.m20); aWriter.Write(aMat.m21); aWriter.Write(aMat.m22); aWriter.Write(aMat.m23);
503 aWriter.Write(aMat.m30); aWriter.Write(aMat.m31); aWriter.Write(aMat.m32); aWriter.Write(aMat.m33);
504 }
505 public static Matrix4x4 ReadMatrix4x4(this BinaryReader aReader)
506 {
507 var m = new Matrix4x4();
508 m.m00 = aReader.ReadSingle(); m.m01 = aReader.ReadSingle(); m.m02 = aReader.ReadSingle(); m.m03 = aReader.ReadSingle();
509 m.m10 = aReader.ReadSingle(); m.m11 = aReader.ReadSingle(); m.m12 = aReader.ReadSingle(); m.m13 = aReader.ReadSingle();
510 m.m20 = aReader.ReadSingle(); m.m21 = aReader.ReadSingle(); m.m22 = aReader.ReadSingle(); m.m23 = aReader.ReadSingle();
511 m.m30 = aReader.ReadSingle(); m.m31 = aReader.ReadSingle(); m.m32 = aReader.ReadSingle(); m.m33 = aReader.ReadSingle();
512 return m;
513 }
514
515 public static void WriteBoneWeight(this BinaryWriter aWriter, BoneWeight aWeight)
516 {
517 aWriter.Write(aWeight.boneIndex0); aWriter.Write(aWeight.weight0);
518 aWriter.Write(aWeight.boneIndex1); aWriter.Write(aWeight.weight1);
519 aWriter.Write(aWeight.boneIndex2); aWriter.Write(aWeight.weight2);
520 aWriter.Write(aWeight.boneIndex3); aWriter.Write(aWeight.weight3);
521 }
522 public static BoneWeight ReadBoneWeight(this BinaryReader aReader)
523 {
524 var w = new BoneWeight();
525 w.boneIndex0 = aReader.ReadInt32(); w.weight0 = aReader.ReadSingle();
526 w.boneIndex1 = aReader.ReadInt32(); w.weight1 = aReader.ReadSingle();
527 w.boneIndex2 = aReader.ReadInt32(); w.weight2 = aReader.ReadSingle();
528 w.boneIndex3 = aReader.ReadInt32(); w.weight3 = aReader.ReadSingle();
529 return w;
530 }
531}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
UnityEngine.Color Color
Definition: TestScript.cs:32
Definition: B83.Win32.cs:38
List< MatData > Materials
List< GameObjectData > Children
Vector2 textureSize
Vector2 occlusionSize
TextureFormat textureFormat
Vector2 metallicSize
TextureFormat normalFormat
TextureFormat occlusionFormat
Vector2 normalSize
TextureFormat metallicFormat