Tanoda
PreviewGenerator.cs
Go to the documentation of this file.
1using GILES;
2using System.Collections;
3using System.Collections.Generic;
4using System.Linq;
5using UnityEngine;
6using UnityEngine.UI;
7
8public class PreviewGenerator : MonoBehaviour
9{
10 public static PreviewGenerator Instance { get; private set; }
11 private const int PREVIEW_LAYER = 20;
12 private const int PREVIEW_VIDEO_LAYER = 21;
13 private static readonly Quaternion CAMERA_VIEW_ANGLE = Quaternion.Euler(30f, -30f, 0f);
14 private const int PreviewWidth = 200;
15 private const int PreviewHeight = 200;
16
17 public float cameraRotateSpeed = 50f;
18 private Quaternion cameraRotation = CAMERA_VIEW_ANGLE;
19 private Light[] sceneLights;
20 private bool[] lightWasEnabled = null;
21
22 private Camera _previewCamera = null;
23
24 private Camera previewCamera
25 {
26 get
27 {
28 if (_previewCamera == null)
29 {
30 var cam = PreviewCamerasHolder.instance.holderTransform.Find("Prefab Browser Asset Preview Camera");
31 if (cam)
32 {
33 _previewCamera = cam.GetComponent<Camera>();
34 }
35 else
36 {
37 _previewCamera = new GameObject().AddComponent<Camera>();
38 _previewCamera.gameObject.transform.SetParent(PreviewCamerasHolder.instance.holderTransform);
39 _previewCamera.gameObject.name = "Prefab Browser Asset Preview Camera";
40 _previewCamera.cullingMask = 1 << PREVIEW_LAYER;
41 //_previewCamera.clearFlags = CameraClearFlags.Depth;
42 _previewCamera.transform.localRotation = CAMERA_VIEW_ANGLE;
43 _previewCamera.nearClipPlane = 0.01f;
44 //_previewCamera.gameObject.SetActive(false);
45 }
46 }
47
48 return _previewCamera;
49 }
50 }
51
52 private static RenderTexture _renderTexture;
53
54 private static RenderTexture renderTexture
55 {
56 get
57 {
58 if (_renderTexture == null)
59 {
60 if (MiscLogicManager.instance.LowMemoryMode)
61 _renderTexture = new RenderTexture(128, 128, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Default);
62 else
63 _renderTexture = new RenderTexture(PreviewWidth, PreviewHeight, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Default);
64
65 _renderTexture.autoGenerateMips = false;
66 _renderTexture.useMipMap = false;
67 }
68
69 return _renderTexture;
70 }
71 }
72
73 private static Light _previewLightA = null;
74
75 private static Light previewLightA
76 {
77 get
78 {
79 if (_previewLightA == null)
80 {
81 GameObject go = new GameObject();
82 go.name = "Asset Preview Lighting";
83 go.transform.localRotation = Quaternion.Euler(15f, 330f, 0f);
84 _previewLightA = go.AddComponent<Light>();
85 _previewLightA.type = LightType.Directional;
86 _previewLightA.intensity = .5f;
87 }
88
89 return _previewLightA;
90 }
91 }
92
93 private static Light _previewLightB = null;
94
95 private static Light previewLightB
96 {
97 get
98 {
99 if (_previewLightB == null)
100 {
101 GameObject go = new GameObject();
102 go.name = "Asset Preview Lighting";
103 go.transform.localRotation = Quaternion.Euler(15f, 150f, 0f);
104 _previewLightB = go.AddComponent<Light>();
105 _previewLightB.type = LightType.Directional;
106 _previewLightB.intensity = .5f;
107 }
108
109 return _previewLightB;
110 }
111 }
112
113 private readonly Queue<Object[]> workQueue = new Queue<Object[]>();
114
115 private void Awake()
116 {
117 Instance = this;
118 }
119
120 public void AddWork(GameObject asset, RawImage t)
121 {
122 workQueue.Enqueue(new Object[] { asset, t });
123 }
124
125 System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
126 private Coroutine work = null;
127 public void StartWork()
128 {
129 if (work == null)
130 {
131 Debug.Log($"Preview generation started!");
132 Debug.Log($"{workQueue.Count} image to generate...");
133 if (workQueue.Count == 0) return;
134
135 work = StartCoroutine(Work());
136 sw.Start();
137 }
138 }
139
140 private IEnumerator Work()
141 {
142 while (workQueue.Count > 0)
143 {
144 LoadingManager.instance.SetLoading();
145 LoadingManager.instance.ShowWindow();
146 var job = workQueue.Dequeue();
147 RenderPreview((GameObject)job[0], (RawImage)job[1]);
148 yield return null;
149 }
150 sw.Stop();
151 Debug.Log($"Preview generation done in: {sw.ElapsedMilliseconds}ms");
152 yield return null;
153 sw.Reset();
154 work = null;
155 LoadingManager.instance.HideWindow(true);
156 }
157
158 private void MoveToLayer(Transform root, int layer)
159 {
160 root.gameObject.layer = layer;
161 foreach (Transform child in root)
162 MoveToLayer(child, layer);
163 }
164
165 private void RenderPreview(GameObject asset, RawImage previewComponent)
166 {
167 if (previewComponent == null)
168 {
169 Debug.LogWarning("previewComponent is NULL!");
170 return;
171 }
172 var instance = (GameObject)GameObject.Instantiate(asset, Vector3.one * 100, Quaternion.identity);
173 var colliders = instance.GetComponentsInChildren<Collider>();
174 foreach (var c in colliders)
175 {
176 Destroy(c);
177 }
178 Renderer renderer = instance.GetComponentInChildren<Renderer>();
179 if (!renderer)
180 {
181 Destroy(instance);
182 Debug.LogWarning("No renderer to preview");
183 return;
184 }
185 instance.transform.position -= renderer.bounds.center - (Vector3.one * 100);
186 instance.SetActive(true);
187 if (sceneLights != null)
188 for (int i = 0; i < sceneLights.Length; i++)
189 {
190 lightWasEnabled[i] = sceneLights[i].enabled;
191 sceneLights[i].enabled = false;
192 }
193
194 MoveToLayer(instance.transform, PREVIEW_LAYER);
195
196 previewCamera.gameObject.SetActive(true);
197
198 previewCamera.transform.localRotation = cameraRotation;
199 pb_AssetPreview.PrepareCamera(previewCamera, instance, PreviewWidth, PreviewHeight);
200
201 previewCamera.targetTexture = renderTexture;
202
203 RenderTexture.active = renderTexture;
204
205 instance.SetActive(true);
206
207 previewLightA.gameObject.SetActive(true);
208 previewLightB.gameObject.SetActive(true);
209 previewCamera.Render();
210
211 Texture2D previewImage;
212 if (MiscLogicManager.instance.LowMemoryMode)
213 previewImage = new Texture2D(128, 128);
214 else
215 previewImage = new Texture2D(PreviewWidth, PreviewHeight);
216 previewImage.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
217 previewImage.Apply();
218
219 previewComponent.texture = previewImage;
220
221 RenderTexture.active = null;
222
223 renderTexture.DiscardContents();
224 renderTexture.Release();
225 instance.SetActive(false);
226
227 previewLightA.gameObject.SetActive(false);
228 previewLightB.gameObject.SetActive(false);
229
230 if (sceneLights != null)
231 for (int i = 0; i < sceneLights.Length; i++)
232 {
233 sceneLights[i].enabled = lightWasEnabled[i];
234 }
235
236 Destroy(instance);
237 }
238
239 GameObject spinnyCache;
240 RawImage drawToThis;
241 byte modulo = 0;
242
243 private void Update()
244 {
245 if (!spinnyCache) return;
246 previewCamera?.transform.RotateAround(Vector3.one * 100, Vector3.up, cameraRotateSpeed * Time.deltaTime);
247
248 Renderer renderer = spinnyCache.GetComponentInChildren<Renderer>();
249 if (!renderer)
250 {
251 Destroy(spinnyCache);
252 return;
253 }
254 spinnyCache.SetActive(true);
255 if (sceneLights != null)
256 for (int i = 0; i < sceneLights.Length; i++)
257 {
258 lightWasEnabled[i] = sceneLights[i].enabled;
259 sceneLights[i].enabled = false;
260 }
261
262 MoveToLayer(spinnyCache.transform, PREVIEW_LAYER);
263
264 //previewCamera.transform.localRotation = cameraRotation;
265 pb_AssetPreview.PrepareCamera(previewCamera, spinnyCache, PreviewWidth, PreviewHeight);
266
267 previewCamera.gameObject.SetActive(true);
268 previewCamera.targetTexture = renderTexture;
269
270 RenderTexture.active = renderTexture;
271
272 spinnyCache.SetActive(true);
273
274 previewLightA.gameObject.SetActive(true);
275 previewLightB.gameObject.SetActive(true);
276 previewCamera.Render();
277
278 Texture2D previewImage;
279 if (MiscLogicManager.instance.LowMemoryMode)
280 previewImage = new Texture2D(128, 128);
281 else
282 previewImage = new Texture2D(PreviewWidth, PreviewHeight);
283
284 previewImage.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
285 previewImage.Apply();
286
287 drawToThis.texture = previewImage;
288
289 RenderTexture.active = null;
290
291 renderTexture.DiscardContents();
292 renderTexture.Release();
293 spinnyCache.SetActive(false);
294 previewLightA.gameObject.SetActive(false);
295 previewLightB.gameObject.SetActive(false);
296
297 if (sceneLights != null)
298 for (int i = 0; i < sceneLights.Length; i++)
299 {
300 sceneLights[i].enabled = lightWasEnabled[i];
301 }
302
303 modulo++;
304 if (modulo % 60 == 0)
305 Resources.UnloadUnusedAssets();
306 }
307
308 public void RenderSpin(GameObject asset, RawImage previewComponent)
309 {
310 if (!spinnyCache)
311 spinnyCache = (GameObject)GameObject.Instantiate(asset, Vector3.one * 100, Quaternion.identity);
312 else
313 {
314 if (!spinnyCache.name.Contains(asset.name))
315 {
316 var to_delete = spinnyCache;
317 Destroy(to_delete);
318 spinnyCache = (GameObject)GameObject.Instantiate(asset, Vector3.one * 100, Quaternion.identity);
319 }
320 }
321 Renderer renderer = spinnyCache.GetComponentInChildren<Renderer>();
322 if (!renderer)
323 {
324 Destroy(spinnyCache);
325 return;
326 }
327 spinnyCache.transform.position -= renderer.bounds.center - (Vector3.one * 100);
328 Destroy(spinnyCache.GetComponentInChildren<Collider>());
329 drawToThis = previewComponent;
330 }
331
332 public void NoMoreSpin()
333 {
334 Destroy(spinnyCache);
335 }
336
337 public GameObject tesztRenderGO;
338 [NaughtyAttributes.Button]
339 private void FileGenerationTeszt()
340 {
341 var instance = (GameObject)GameObject.Instantiate(tesztRenderGO, Vector3.one * 100, Quaternion.identity);
342 Destroy(instance.GetComponentInChildren<Collider>());
343 Renderer renderer = instance.GetComponentInChildren<Renderer>();
344 if (!renderer)
345 {
346 Destroy(instance);
347 return;
348 }
349 instance.transform.position -= renderer.bounds.center - (Vector3.one * 100);
350 instance.SetActive(true);
351 if (sceneLights != null)
352 for (int i = 0; i < sceneLights.Length; i++)
353 {
354 lightWasEnabled[i] = sceneLights[i].enabled;
355 sceneLights[i].enabled = false;
356 }
357
358 MoveToLayer(instance.transform, PREVIEW_LAYER);
359
360 previewCamera.transform.localRotation = cameraRotation;
361 pb_AssetPreview.PrepareCamera(previewCamera, instance, PreviewWidth, PreviewHeight);
362
363 previewCamera.targetTexture = renderTexture;
364
365 RenderTexture.active = renderTexture;
366
367 instance.SetActive(true);
368
369 previewLightA.gameObject.SetActive(true);
370 previewLightB.gameObject.SetActive(true);
371 var angle = 10;
372 var previewFile = new PreviewFile();
373 for (int i = 0; i < 360; i += angle)
374 {
375 previewCamera.Render();
376 Texture2D previewImage;
377 if (MiscLogicManager.instance.LowMemoryMode)
378 previewImage = new Texture2D(128, 128);
379 else
380 previewImage = new Texture2D(PreviewWidth, PreviewHeight);
381
382 previewImage.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
383 previewImage.Apply();
384
385 previewFile.AddFile($"{i / angle}.png", previewImage.EncodeToPNG());
386
387 RenderTexture.active = null;
388
389 renderTexture.DiscardContents();
390 renderTexture.Release();
391
392 previewCamera?.transform.RotateAround(Vector3.one * 100, Vector3.up, angle);
393 pb_AssetPreview.PrepareCamera(previewCamera, instance);
394
395 previewCamera.targetTexture = renderTexture;
396
397 RenderTexture.active = renderTexture;
398
399 }
400
401 Compress(".teszt\\teszt.pwf", previewFile.Data);
402 System.IO.File.WriteAllBytes(".teszt\\teszt_nc.pwf", previewFile.Data);
403
404 System.IO.File.WriteAllBytes(".teszt\\4.png", previewFile.GetFile(4));
405 instance.SetActive(false);
406
407 previewLightA.gameObject.SetActive(false);
408 previewLightB.gameObject.SetActive(false);
409
410 if (sceneLights != null)
411 for (int i = 0; i < sceneLights.Length; i++)
412 {
413 sceneLights[i].enabled = lightWasEnabled[i];
414 }
415
416 Destroy(instance);
417 }
418
419 public void Compress(string filename, byte[] byteArray)
420 {
421 byte[] compressedBytes;
422
423 using (var uncompressedStream = new System.IO.MemoryStream(byteArray))
424 {
425 using (var compressedStream = new System.IO.MemoryStream())
426 {
427 using (var compressorStream = new System.IO.Compression.GZipStream(compressedStream, System.IO.Compression.CompressionLevel.Fastest))
428 {
429 uncompressedStream.CopyTo(compressorStream);
430 }
431 compressedBytes = compressedStream.ToArray();
432 }
433 }
434
435 System.IO.File.WriteAllBytes(filename, compressedBytes);
436 }
437
438 public byte[] Decompress(string fileName)
439 {
440 byte[] decompressedBytes;
441 using (var compressedStream = new System.IO.MemoryStream(System.IO.File.ReadAllBytes(fileName)))
442 {
443 using (var decompressorStream = new System.IO.Compression.GZipStream(compressedStream, System.IO.Compression.CompressionMode.Decompress))
444 {
445 using (var decompressedStream = new System.IO.MemoryStream())
446 {
447 decompressorStream.CopyTo(decompressedStream);
448
449 decompressedBytes = decompressedStream.ToArray();
450 }
451 }
452 }
453 return decompressedBytes;
454 }
455
456 public class PreviewFile
457 {
458 /* Header:
459 * int - number of files
460 * int - length of file in bytes
461 * char[32] - filename
462 * byte[x] - file data
463 * (loop for each file)
464 */
465 public byte[] Data;
466
467 private int fileNumber;
468 public int FileNumber
469 {
470 get
471 {
472 if (fileNumber == 0)
473 {
474 fileNumber = System.BitConverter.ToInt32(Data, 0);
475 }
476 return fileNumber;
477 }
478 }
479
480 public PreviewFile(byte[] data)
481 {
482 Data = data;
483 }
484 public PreviewFile()
485 {
486 Data = new byte[4];
487 }
488 public void AddFile(string filename, byte[] data)
489 {
490 var list = Data.Skip(4).ToList();
491 list = System.BitConverter.GetBytes(fileNumber + 1).Concat(list).ToList();
492 list.AddRange(System.BitConverter.GetBytes(data.Length));
493 var bytename = System.Text.Encoding.UTF8.GetBytes(filename);
494 System.Array.Resize(ref bytename, 32);
495 list.AddRange(bytename);
496 list.AddRange(data);
497
498 Data = list.ToArray();
499 fileNumber++;
500 }
501
502 public byte[] GetFile(int index)
503 {
504 if (index >= FileNumber)
505 {
506 throw new System.IndexOutOfRangeException("File number smaller than requested index.");
507 }
508
509 var i = 0;
510 var list = Data.Skip(4).ToArray();
511 while (index != i)
512 {
513 var length = System.BitConverter.ToInt32(list, 0);
514 list = list.Skip(4 + 32 + length).ToArray();
515 i++;
516 }
517
518 {
519 var length = System.BitConverter.ToInt32(list, 0);
520 return list.Skip(4 + 32).Take(length).ToArray();
521 }
522 }
523
524 public byte[] GetFile(string name)
525 {
526 var i = 0;
527 var list = Data.Skip(4).ToArray();
528 while (list.Length > 0)
529 {
530 var length = System.BitConverter.ToInt32(list, 0);
531 var filename = System.BitConverter.ToString(list, 4, 32);
532 if (filename == name)
533 {
534 return list.Skip(4 + 32).Take(length).ToArray();
535 }
536 list = list.Skip(4 + 32 + length).ToArray();
537 i++;
538 }
539
540 return null;
541 }
542
543 }
544}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
static PreviewCamerasHolder instance
void AddFile(string filename, byte[] data)
byte[] Decompress(string fileName)
void AddWork(GameObject asset, RawImage t)
void RenderSpin(GameObject asset, RawImage previewComponent)
GameObject tesztRenderGO
static PreviewGenerator Instance
void Compress(string filename, byte[] byteArray)
UnityEngine.Object Object