/// <summary> /// <para>Retrieves a <see cref="Texture2D"/> from the cache for a <see cref="GameObject"/> using a <see cref="CameraSetup"/>.</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="CameraSetup"/>.</para> /// </returns> public static Texture2D GetTexture(CameraSetup 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 = AssetIconRenderer.RenderModel(target, cameraSetup, size, size); styleCache[path] = texture; } return(texture); }
private static float RecalculateMaxDistance(float maxDistance, Vector3 point, Vector3 boundsCenter, float aspect, CameraSetup 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>Attempts to draw an icon for an object.</para> /// </summary> /// <param name="rect">The <see cref="Rect"/> in which the item is drawn.</param> /// <param name="objectIcon">The target object to draw a graphic for.</param> /// <param name="style">A style used to modify the appearance of a graphic.</param> /// <param name="selected">Whether the graphic should be rendered with a selection tint.</param> public static void DrawObject(Rect rect, object objectIcon, CompiledStyleDefinition style = null, bool selected = false) { if (Event.current.type != EventType.Repaint) { return; } if (objectIcon == null) { return; } if (objectIcon.GetType() == typeof(AssetReference)) { var assetReference = (AssetReference)objectIcon; DrawObject(rect, assetReference.ObjectReference, style, selected); return; } var iconType = objectIcon.GetType(); if (typeof(Sprite).IsAssignableFrom(iconType)) { var spriteIcon = (Sprite)objectIcon; if (spriteIcon != null) { DrawSprite(rect, spriteIcon, style, selected); } } else if (typeof(Texture).IsAssignableFrom(iconType)) { var textureIcon = (Texture)objectIcon; if (textureIcon != null) { DrawTexture(rect, textureIcon, style, selected); } } else if (typeof(Color).IsAssignableFrom(iconType)) { var color = (Color)objectIcon; DrawColor(rect, color, style, selected); } else if (typeof(Color32).IsAssignableFrom(iconType)) { var color = (Color32)objectIcon; DrawColor(rect, color, style, selected); } else if (typeof(string).IsAssignableFrom(iconType)) { string iconText = (string)objectIcon; if (!string.IsNullOrEmpty(iconText)) { DrawText(rect, iconText, style, selected); } } else if (typeof(int).IsAssignableFrom(iconType)) { int iconText = (int)objectIcon; DrawText(rect, iconText.ToString(), style, selected); } else if (typeof(GameObject).IsAssignableFrom(iconType)) { var prefab = (GameObject)objectIcon; if (prefab != null) { var col = BackgroundColor; col = new Color(col.r, col.g, col.b, 0); var setup = new CameraSetup() { BackgroundColor = col, TransparentBackground = true, Orthographic = style.Projection == IconProjection.Orthographic, PreviewDirection = new Vector3(-1.0f, -1.0f, -1.0f) }; var thumbnail = RenderCache.GetTexture(setup, prefab); DrawTexture(rect, thumbnail, style, selected); } } else { throw new InvalidOperationException("Could not draw icon of type " + iconType); } }
/// <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="style">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, CameraSetup style, int width = 64, int height = 64) { if (model == null || model.Equals(null)) { return(null); } #if USE_PREVIEW_SCENE var previewObject = (GameObject)PrefabUtility.InstantiatePrefab(model, RenderCamera.scene); #else var previewObject = (GameObject)PrefabUtility.InstantiatePrefab(model); #endif previewObject.gameObject.hideFlags = HideFlags.HideAndDontSave; SetLayerRecursively(previewObject.transform); previewObject.SetActive(true); Texture2D result = null; style.ApplyToCamera(RenderCamera); try { var previewDir = previewObject.transform.rotation * style.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 (style.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 + style.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, style); point.x -= boundsSize.x; maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style); point.y -= boundsSize.y; maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style); point.x += boundsSize.x; maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style); point.z -= boundsSize.z; maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style); point.x -= boundsSize.x; maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style); point.y += boundsSize.y; maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style); point.x += boundsSize.x; maxDistance = RecalculateMaxDistance(maxDistance, point, boundsCenter, aspect, style); distance = (1f + style.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 (style.TransparentBackground) { GL.Clear(false, true, style.BackgroundColor); } RenderCamera.targetTexture = renderTex; RenderCamera.Render(); RenderCamera.targetTexture = null; var textureFormat = style.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 e) { Debug.LogException(e); } finally { UnityEngine.Object.DestroyImmediate(previewObject); } return(result); }