Tanoda
GameObjectPreview.cs
Go to the documentation of this file.
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using GILES;
5using GILES.Interface;
6using UnityEngine;
9using UnityEngine.UI;
10using UnityEngine.Video;
11using Object = UnityEngine.Object;
12
14{
15 const int PREVIEW_LAYER = 20;
16 const int PreviewWidth = 128;
17 const int PreviewHeight = 128;
18 private static readonly Quaternion CAMERA_VIEW_ANGLE = Quaternion.Euler(30f, -30f, 0f);
19 public GameObject asset;
20
21 public float cameraRotateSpeed = 50f;
22 private Quaternion cameraRotation = CAMERA_VIEW_ANGLE;
23 private RawImage previewComponent;
24 private bool doSpin = false;
25 private Texture2D previewImage;
26 private Light[] sceneLights;
27 private bool[] lightWasEnabled = null;
28 private GameObject instance;
29
30 private static Camera _previewCamera = null;
31 private static Camera previewCamera
32 {
33 get
34 {
35 var cam = PreviewCamerasHolder.instance.holderTransform.Find("Prefab Browser Asset Preview Camera");
36 if (cam)
37 {
38 _previewCamera = cam.GetComponent<Camera>();
39 }
40 else
41 {
42 _previewCamera = new GameObject().AddComponent<Camera>();
43 _previewCamera.gameObject.transform.SetParent(PreviewCamerasHolder.instance.holderTransform);
44 _previewCamera.gameObject.name = "Prefab Browser Asset Preview Camera";
45 _previewCamera.cullingMask = 1 << PREVIEW_LAYER;
46 _previewCamera.transform.localRotation = CAMERA_VIEW_ANGLE;
47 _previewCamera.nearClipPlane = 0.01f;
48 _previewCamera.gameObject.SetActive(false);
49 }
50
51 return _previewCamera;
52 }
53 }
54
55 private static RenderTexture _renderTexture;
56 private static RenderTexture renderTexture
57 {
58 get
59 {
60 if(_renderTexture == null)
61 {
62 _renderTexture = new RenderTexture(PreviewWidth, PreviewHeight, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Default);
63 _renderTexture.autoGenerateMips = false;
64 _renderTexture.useMipMap = false;
65 }
66
67 return _renderTexture;
68 }
69 }
70
71 private static Light _previewLightA = null;
72 private static Light previewLightA
73 {
74 get
75 {
76 if(_previewLightA == null)
77 {
78 GameObject go = new GameObject();
79 go.name = "Asset Preview Lighting";
80 go.transform.localRotation = Quaternion.Euler(15f, 330f, 0f);
81 _previewLightA = go.AddComponent<Light>();
82 _previewLightA.type = LightType.Directional;
83 _previewLightA.intensity = .5f;
84 }
85
86 return _previewLightA;
87 }
88 }
89
90 private static Light _previewLightB = null;
91 private static Light previewLightB
92 {
93 get
94 {
95 if(_previewLightB == null)
96 {
97 GameObject go = new GameObject();
98 go.name = "Asset Preview Lighting";
99 go.transform.localRotation = Quaternion.Euler(15f, 150f, 0f);
100 _previewLightB = go.AddComponent<Light>();
101 _previewLightB.type = LightType.Directional;
102 _previewLightB.intensity = .5f;
103 }
104
105 return _previewLightB;
106 }
107 }
108
109 private void Start()
110 {
111 if (!asset)
112 return;
113 Initialize();
114 }
115
116 public void ReInitialize()
117 {
118 //Debug.Log("ReInitializing...");
119 previewImage = null;
120 Destroy(gameObject.GetComponent<Mask>());
121 Destroy(gameObject.GetComponent<VerticalLayoutGroup>());
122 Destroy(gameObject.transform.GetChild(0).gameObject);
123 foreach (Transform child in gameObject.transform)
124 {
125 Destroy(child.gameObject);
126 }
127 Destroy(instance);
128
129 StartCoroutine(InitializeNextFrame());
130 }
131
132 private IEnumerator InitializeNextFrame()
133 {
134 yield return new WaitForEndOfFrame();
135 Initialize(true);
136 }
137
138 public void Initialize(bool reinitialize = false)
139 {
140 previewImage = new Texture2D(PreviewWidth, PreviewHeight);
141
142 foreach (Transform child in gameObject.transform)
143 {
144 Destroy(child.gameObject);
145 }
146
147 if(!SetupAndRenderPreview(previewImage))
148 {
149 pb_ObjectUtility.Destroy(previewImage);
150 previewImage = null;
151 }
152
153 gameObject.AddComponent<Mask>();
154 gameObject.AddComponent<VerticalLayoutGroup>();
155 Image image = gameObject.DemandComponent<Image>();
156 image.color = pb_GUIUtility.ITEM_BACKGROUND_COLOR;
157 image.sprite = null;
158 GameObject description = gameObject.AddChild();
159
160 if(previewImage != null)
161 {
162 previewComponent = description.AddComponent<RawImage>();
163 previewComponent.texture = previewImage;
164
165 }
166 else
167 {
168 if (asset.GetComponent<RawImage>())
169 {
170 previewComponent = description.AddComponent<RawImage>();
171 previewComponent.texture = asset.GetComponent<RawImage>().texture;
172 SizeToParent(previewComponent, 0.05f);
173 if (!reinitialize)
174 gameObject.AddComponent<DragAndDropItem>();
175 if (asset.GetComponent<VideoPlayer>())
176 RenderVideoPreview();
177 }
178 else
179 {
180 Text text = description.AddComponent<Text>();
181 text.font = pb_GUIUtility.DefaultFont();
182 text.alignment = TextAnchor.MiddleCenter;
183 text.text = asset.name;
184 }
185 }
186 }
187
188 public static Vector2 SizeToParent(RawImage image, float padding = 0) {
189 float w = 0, h = 0;
190 var parent = image.transform.parent.GetComponent<RectTransform>();
191 var imageTransform = image.GetComponent<RectTransform>();
192
193 // check if there is something to do
194 if (image.texture != null) {
195 if (!parent) return imageTransform.sizeDelta; //if we don't have a parent, just return our current width;
196 padding = 1 - padding;
197 float ratio = image.texture.width / (float)image.texture.height;
198 var bounds = new Rect(0, 0, parent.rect.width, parent.rect.height);
199 if (Mathf.RoundToInt(imageTransform.eulerAngles.z) % 180 == 90) {
200 //Invert the bounds if the image is rotated
201 bounds.size = new Vector2(bounds.height, bounds.width);
202 }
203 //Size by height first
204 h = bounds.height * padding;
205 w = h * ratio;
206 if (w > bounds.width * padding) { //If it doesn't fit, fallback to width;
207 w = bounds.width * padding;
208 h = w / ratio;
209 }
210 }
211 imageTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, w);
212 imageTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, h);
213 return imageTransform.sizeDelta;
214 }
215
216 void Update()
217 {
218 if(doSpin)
219 {
220 previewCamera.transform.RotateAround(Vector3.one * 100, Vector3.up, cameraRotateSpeed * Time.deltaTime);
221 RenderPreview();
222 }
223 }
224
225 public override void OnPointerEnter(PointerEventData eventData)
226 {
227 if(previewComponent == null)
228 return;
229
230
231 if (previewImage == null)
232 {
233 if (instance != null && instance.GetComponent<VideoPlayer>())
234 {
235 instance.SetActive(true);
236 instance.GetComponent<VideoPlayer>().Play();
237 }
238 }
239
240 if(!SetupPreviewRender())
241 return;
242
243 previewComponent.texture = renderTexture;
244
245 doSpin = true;
246 }
247
248 public override void OnPointerExit(PointerEventData eventData)
249 {
250 if (previewImage == null)
251 {
252 if (instance != null && instance.GetComponent<VideoPlayer>())
253 {
254 instance.GetComponent<VideoPlayer>().Pause();
255 instance.SetActive(false);
256 }
257 return;
258 }
259
260 if(previewComponent == null)
261 return;
262
263 doSpin = false;
264
265 cameraRotation = previewCamera.transform.localRotation;
266
267 RenderPreview();
268
269 previewImage.ReadPixels(new Rect(0,0,renderTexture.width,renderTexture.height), 0, 0);
270 previewImage.Apply();
271
272 previewComponent.texture = previewImage;
273
274 RenderTexture.active = null;
275
276 renderTexture.DiscardContents();
277 renderTexture.Release();
278
279 pb_ObjectUtility.Destroy(instance);
280 }
281
282 bool SetupAndRenderPreview(Texture2D texture)
283 {
284 if(!SetupPreviewRender())
285 return false;
286
287 RenderPreview();
288
289 texture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
290 texture.Apply();
291
292 RenderTexture.active = null;
293
294 renderTexture.DiscardContents();
295 renderTexture.Release();
296
297 pb_ObjectUtility.Destroy(instance);
298
299 return true;
300 }
301
302 bool SetupPreviewRender()
303 {
304 if (!asset)
305 OnAssetNull?.Invoke();
306
307 if(!asset || asset.GetComponentInChildren<Renderer>() == null) return false;
308
309 sceneLights = Object.FindObjectsOfType<Light>();
310 lightWasEnabled = new bool[sceneLights.Length];
311
312 instance = (GameObject) GameObject.Instantiate(asset, Vector3.one * 100, Quaternion.identity);
313
314 Renderer renderer = instance.GetComponentInChildren<Renderer>();
315
316 instance.transform.position -= renderer.bounds.center - (Vector3.one * 100);
317
318 MoveToLayer(instance.transform, PREVIEW_LAYER);
319
320 previewCamera.transform.localRotation = cameraRotation;
321
323 pb_AssetPreview.PrepareCamera(previewCamera, instance, PreviewWidth, PreviewHeight);
324
325 previewCamera.targetTexture = renderTexture;
326
327 return true;
328 }
329
330 void MoveToLayer(Transform root, int layer) {
331 root.gameObject.layer = layer;
332 foreach(Transform child in root)
333 MoveToLayer(child, layer);
334 }
335
336 void RenderPreview()
337 {
338 if (!asset)
339 OnAssetNull?.Invoke();
340
341 if (asset && asset.GetComponent<VideoPlayer>())
342 {
343 if (instance == null)
344 {
345 instance = (GameObject) GameObject.Instantiate(asset, Vector3.one * 100, Quaternion.identity);
346 MoveToLayer(instance.transform, PREVIEW_LAYER);
347 }
348 return;
349 }
350
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 RenderTexture.active = renderTexture;
359
360 instance.SetActive(true);
361
362 previewLightA.gameObject.SetActive(true);
363 previewLightB.gameObject.SetActive(true);
364
365 previewCamera.Render();
366
367 instance.SetActive(false);
368
369 previewLightA.gameObject.SetActive(false);
370 previewLightB.gameObject.SetActive(false);
371
372 if (sceneLights != null)
373 for(int i = 0; i < sceneLights.Length; i++)
374 {
375 sceneLights[i].enabled = lightWasEnabled[i];
376 }
377 }
378
379 public UnityEvent OnAssetNull = new UnityEvent();
380
381 private int _stopafterframe = 2;
382
383 void RenderVideoPreview()
384 {
385 if (asset.GetComponent<VideoPlayer>())
386 {
387 if (instance == null)
388 {
389 instance = (GameObject) GameObject.Instantiate(asset, Vector3.one * 100, Quaternion.identity);
390 MoveToLayer(instance.transform, PREVIEW_LAYER);
391 var video = instance.GetComponent<VideoPlayer>();
392 video.audioOutputMode = VideoAudioOutputMode.None;
393 video.sendFrameReadyEvents = true;
394 video.frameReady += Pb_PrefabBrowserItemButton_frameReady;
395 }
396 }
397 }
398
399 private void Pb_PrefabBrowserItemButton_frameReady(VideoPlayer source, long frameIdx)
400 {
401 _stopafterframe--;
402 if (_stopafterframe <= 0)
403 {
404 source.sendFrameReadyEvents = false;
405 source.frameReady -= Pb_PrefabBrowserItemButton_frameReady;
406 source.Stop();
407 instance.SetActive(false);
408 }
409 }
410}
UnityEngine.UI.Button Button
Definition: Pointer.cs:7
System.Drawing.Image Image
Definition: TestScript.cs:37
Drag and Drop item.
static Vector2 SizeToParent(RawImage image, float padding=0)
override void OnPointerEnter(PointerEventData eventData)
override void OnPointerExit(PointerEventData eventData)
void Initialize(bool reinitialize=false)
static PreviewCamerasHolder instance
UnityEngine.Object Object