Beispiel #1
0
        /// <summary>
        /// <para>Retrieves a <see cref="Texture2D"/> from the cache for a <see cref="GameObject"/> using a <see cref="AssetIconsCameraSetup"/>.</para>
        /// </summary>
        /// <param name="cameraSetup">A camera setup to use when rendering the graphic.</param>
        /// <param name="target">A Prefab to render a graphic for.</param>
        /// <returns>
        /// <para>A <see cref="Texture2D"/> of the renedred <see cref="GameObject"/> with the <see cref="AssetIconsCameraSetup"/>.</para>
        /// </returns>
        public static Texture2D GetTexture(AssetIconsCameraSetup cameraSetup, GameObject target)
        {
            string path = AssetDatabase.GetAssetPath(target);

            Dictionary <string, Texture2D> styleCache;

            bool result = Renders.TryGetValue(cameraSetup, out styleCache);

            if (!result)
            {
                styleCache = new Dictionary <string, Texture2D>();
                Renders.Add(cameraSetup, styleCache);
            }

            Texture2D texture;

            result = styleCache.TryGetValue(path, out texture);

            if (!result || texture == null || texture.Equals(null))
            {
                int size = AssetIconsPreferences.PrefabResolution.Value;

                texture = AssetIconsRenderer.RenderModel(target, cameraSetup, size, size);

                styleCache[path] = texture;
            }

            return(texture);
        }
        private static float RecalculateMaxDistance(float maxDistance, Vector3 point, Vector3 boundsCenter, float aspect, AssetIconsCameraSetup style)
        {
            var intersectionPoint = ClosestPointOnPlane(projectionPlaneHorizontal, point);

            float horizontalDistance = projectionPlaneHorizontal.GetDistanceToPoint(point);
            float verticalDistance   = projectionPlaneVertical.GetDistanceToPoint(point);

            float halfFrustumHeight = Mathf.Max(verticalDistance, horizontalDistance / aspect);
            float distance          = halfFrustumHeight / Mathf.Tan(RenderCamera.fieldOfView * 0.5f * Mathf.Deg2Rad);

            float distanceToCenter = (intersectionPoint - style.PreviewDirection.normalized * distance - boundsCenter).sqrMagnitude;

            if (distanceToCenter > maxDistance)
            {
                maxDistance = distanceToCenter;
            }
            return(maxDistance);
        }
        /// <summary>
        /// <para>Creates a preview <see cref="Texture2D"/> of a model.</para>
        /// </summary>
        /// <param name="model">The object to render a preview of.</param>
        /// <param name="camera">The style to render the model with.</param>
        /// <param name="width">The width (in pixels) of the rendered <see cref="Texture2D"/>.</param>
        /// <param name="height">The height (in pixels) of the rendered <see cref="Texture2D"/>.</param>
        /// <returns>
        /// <para>A rendered preview <see cref="Texture2D"/>.</para>
        /// </returns>
        public static Texture2D RenderModel(GameObject model, AssetIconsCameraSetup camera, int width = 64, int height = 64)
        {
            if (model == null || model.Equals(null))
            {
                return(null);
            }

            GameObject previewObject;

#if USE_PREVIEW_SCENE
            if (!RenderCamera.scene.IsValid())
            {
                previewObject = (GameObject)PrefabUtility.InstantiatePrefab(model);
            }
            else
            {
                previewObject = (GameObject)PrefabUtility.InstantiatePrefab(model, RenderCamera.scene);
            }
#else
            previewObject = (GameObject)PrefabUtility.InstantiatePrefab(model);
#endif

            previewObject.gameObject.hideFlags = HideFlags.HideAndDontSave;
            SetLayerRecursively(previewObject.transform);
            previewObject.SetActive(true);

            Texture2D result = null;

            camera.ApplyToCamera(RenderCamera);

            try
            {
                var previewDir = previewObject.transform.rotation * camera.PreviewDirection.normalized;

                prefabRenderers.Clear();
                previewObject.GetComponentsInChildren(prefabRenderers);

                var  previewBounds = new Bounds();
                bool anyRenderers  = false;
                for (int i = 0; i < prefabRenderers.Count; i++)
                {
                    var renderer = prefabRenderers[i];
                    if (!renderer.enabled)
                    {
                        continue;
                    }

                    if (!anyRenderers)
                    {
                        previewBounds = renderer.bounds;
                        anyRenderers  = true;
                    }
                    else
                    {
                        previewBounds.Encapsulate(renderer.bounds);
                    }
                }

                if (!anyRenderers)
                {
                    return(null);
                }

                var boundsCenter  = previewBounds.center;
                var boundsExtents = previewBounds.extents;
                var boundsSize    = 2f * boundsExtents;

                float aspect = (float)width / height;
                RenderCamera.aspect             = aspect;
                RenderCamera.transform.rotation = Quaternion.LookRotation(previewDir, previewObject.transform.up);

                float distance;
                if (camera.Orthographic)
                {
                    RenderCamera.transform.position = boundsCenter;

                    minX = minY = Mathf.Infinity;
                    maxX = maxY = Mathf.NegativeInfinity;

                    var point = boundsCenter + boundsExtents;
                    ProjectBoundingBoxMinMax(point);
                    point.x -= boundsSize.x;
                    ProjectBoundingBoxMinMax(point);
                    point.y -= boundsSize.y;
                    ProjectBoundingBoxMinMax(point);
                    point.x += boundsSize.x;
                    ProjectBoundingBoxMinMax(point);
                    point.z -= boundsSize.z;
                    ProjectBoundingBoxMinMax(point);
                    point.x -= boundsSize.x;
                    ProjectBoundingBoxMinMax(point);
                    point.y += boundsSize.y;
                    ProjectBoundingBoxMinMax(point);
                    point.x += boundsSize.x;
                    ProjectBoundingBoxMinMax(point);

                    distance = boundsExtents.magnitude + 1f;
                    RenderCamera.orthographicSize = (1f + camera.Padding * 2f) * Mathf.Max(maxY - minY, (maxX - minX) / aspect) * 0.5f;
                }
                else
                {
                    projectionPlaneHorizontal = new Plane(RenderCamera.transform.up, boundsCenter);
                    projectionPlaneVertical   = new Plane(RenderCamera.transform.right, boundsCenter);

                    float maxDistance = Mathf.NegativeInfinity;

                    var point = boundsCenter + boundsExtents;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, camera);
                    point.x    -= boundsSize.x;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, camera);
                    point.y    -= boundsSize.y;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, camera);
                    point.x    += boundsSize.x;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, camera);
                    point.z    -= boundsSize.z;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, camera);
                    point.x    -= boundsSize.x;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, camera);
                    point.y    += boundsSize.y;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, camera);
                    point.x    += boundsSize.x;
                    maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, camera);

                    distance = (1f + camera.Padding * 2f) * Mathf.Sqrt(maxDistance);
                }

                RenderCamera.transform.position = boundsCenter - previewDir * distance;
                RenderCamera.farClipPlane       = distance * 4f;

                var temp      = RenderTexture.active;
                var renderTex = RenderTexture.GetTemporary(width, height, 16, RenderTextureFormat.ARGB32);
                RenderTexture.active = renderTex;

                if (camera.TransparentBackground)
                {
                    GL.Clear(false, true, camera.BackgroundColor);
                }

                RenderCamera.targetTexture = renderTex;

                RenderCamera.Render();
                RenderCamera.targetTexture = null;

                var textureFormat = camera.TransparentBackground ? TextureFormat.ARGB32 : TextureFormat.RGB24;

                result = new Texture2D(width, height, textureFormat, false)
                {
                    wrapMode   = TextureWrapMode.Clamp,
                    filterMode = FilterMode.Point
                };
                result.ReadPixels(new Rect(0, 0, width, height), 0, 0, false);
                result.Apply(false, true);

                RenderTexture.active = temp;
                RenderTexture.ReleaseTemporary(renderTex);
            }
            catch (Exception exception)
            {
                Debug.LogException(exception);
            }
            finally
            {
                try
                {
                    UnityEngine.Object.DestroyImmediate(previewObject);
                }
                catch (Exception destroyException)
                {
                    previewObject.SetActive(false);

                    AssetIconsLogger.LogException(destroyException);
                }
            }

            return(result);
        }