Skip to content

Instantly share code, notes, and snippets.

@giacomelli
Last active January 25, 2022 13:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save giacomelli/ad9d4dcdb702d2d1edf0663628ca9608 to your computer and use it in GitHub Desktop.
Save giacomelli/ad9d4dcdb702d2d1edf0663628ca9608 to your computer and use it in GitHub Desktop.
using UnityEngine;
using UnityEditor;
/// <summary>
/// Scene preview data.
/// http://diegogiacomelli.com.br/unitytips-scene-preview-window
/// </summary>
public class ScenePreviewData
{
Texture2D _texture;
public ScenePreviewData(string scenePath, string texturePath)
{
ScenePath = scenePath;
TexturePath = texturePath;
}
public string ScenePath { get; private set; }
public string TexturePath { get; private set; }
public Texture2D Texture
{
get
{
return _texture ?? (_texture = AssetDatabase.LoadAssetAtPath<Texture2D>(TexturePath));
}
}
}
using System;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
/// <summary>
/// Scene preview screenshot.
/// http://diegogiacomelli.com.br/unitytips-scene-preview-window
/// </summary>
public static class ScenePreviewScreenshot
{
public static bool Capture(bool force = true)
{
var previewPath = ScenePreviewUtility.GetPreviewPath(SceneManager.GetActiveScene().name);
if (force || !File.Exists(previewPath))
{
var cam = Camera.main;
if (cam == null)
{
cam = UnityEngine.Object.FindObjectOfType<Camera>();
if (cam == null)
{
Debug.LogError("There is no Camera on the scene. Cannot take a screenshot.");
return false;
}
}
var size = GetGameWindowSize();
var width = (int)size.x;
var height = (int)size.y;
cam.targetTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32);
RenderTexture.active = cam.targetTexture;
cam.Render();
var tex = new Texture2D(width, height, TextureFormat.RGB24, false);
tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
cam.targetTexture = null;
tex.Apply();
byte[] bytes = tex.EncodeToPNG();
File.WriteAllBytes(previewPath, bytes);
AssetDatabase.ImportAsset(previewPath);
return true;
}
return false;
}
// http://answers.unity.com/answers/192818/view.html
static Vector2 GetGameWindowSize()
{
Type T = Type.GetType("UnityEditor.GameView,UnityEditor");
MethodInfo GetSizeOfMainGameView = T.GetMethod("GetSizeOfMainGameView", BindingFlags.NonPublic | BindingFlags.Static);
return (Vector2) GetSizeOfMainGameView.Invoke(null, null);
}
}
using System;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
/// <summary>
/// Scene preview utility.
/// http://diegogiacomelli.com.br/unitytips-scene-preview-window
/// </summary>
public static class ScenePreviewUtility
{
public static ScenePreviewData[] Data { get; private set; } = new ScenePreviewData[0];
public static bool ShowCaptureScreenshotButton { get; private set; }
public static void RefreshTextures(ScenePreviewWindow window)
{
// Get the selected SceneAsset previews.
var previewsPaths = Selection.objects
.Where(asset => asset is SceneAsset)
.Select(sceneAsset => new ScenePreviewData(AssetDatabase.GetAssetPath(sceneAsset), GetPreviewPath(((SceneAsset)sceneAsset).name)))
.OrderBy(n => n.TexturePath)
.ToList();
if (previewsPaths.Count == 1)
window.ShowTab();
// If there no SceneAsset selected, then show the current scene preview.
var activeScene = SceneManager.GetActiveScene();
var activeScenePreviewPath = GetPreviewPath(activeScene.name);
if (previewsPaths.Count == 0)
previewsPaths.Add(new ScenePreviewData(activeScene.path, activeScenePreviewPath));
ShowCaptureScreenshotButton = previewsPaths.Count == 1 && previewsPaths[0].TexturePath == activeScenePreviewPath;
// Loads the previews textures.
Data = previewsPaths
.Distinct()
.Where(item => item.Texture != null)
.ToArray();
window.Repaint();
}
public static string GetPreviewPath(string sceneName = null)
{
var folder = GetPreviewFolderRootedPath().Replace(Application.dataPath, string.Empty);
folder = $"Assets{folder}";
return String.IsNullOrEmpty(sceneName)
? folder
: Path.Combine(folder, $"{sceneName}.png");
}
private static string GetPreviewFolderRootedPath([CallerFilePath] string callerFilePath = null)
{
var folder = Path.Combine(Path.GetDirectoryName(callerFilePath), "Previews");
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
return folder.Replace(@"\", "/");
}
}
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
/// <summary>
/// Scene preview window.
/// http://diegogiacomelli.com.br/unitytips-scene-preview-window
/// </summary>
public class ScenePreviewWindow : EditorWindow
{
const float EditorMargin = 1;
const float PreviewMargin = 1;
const int Columns = 2;
const int CaptureScreenshotButtonHeight = 30;
const float SecondsToAutoCaptureScreenshot = 10f;
static GUIStyle _buttonStyle = new GUIStyle();
static ScenePreviewWindow _instance;
[MenuItem("Window/Scene Preview")]
public static void ShowWindow()
{
_instance = EditorWindow.GetWindow<ScenePreviewWindow>("Scene Preview");
}
[InitializeOnLoadMethod]
static void Initialize()
{
Selection.selectionChanged += HandleSelectionChange;
EditorApplication.playModeStateChanged += HandlePlayModeStateChanged;
EditorSceneManager.sceneOpened += HandleEditorSceneManagerSceneOpened;
}
void OnEnable()
{
_instance = this;
_buttonStyle.normal.background = null;
}
void OnDestroy()
{
Selection.selectionChanged -= HandleSelectionChange;
EditorApplication.playModeStateChanged -= HandlePlayModeStateChanged;
EditorSceneManager.sceneOpened -= HandleEditorSceneManagerSceneOpened;
_instance = null;
}
static void HandleSelectionChange()
{
if (_instance != null)
{
ScenePreviewUtility.RefreshTextures(_instance);
}
}
static void HandlePlayModeStateChanged(PlayModeStateChange playMode)
{
if (playMode == PlayModeStateChange.EnteredPlayMode && _instance != null)
{
EditorApplication.update += HandleUpdate;
HandleSelectionChange();
}
}
static void HandleEditorSceneManagerSceneOpened(Scene scene, OpenSceneMode mode)
{
HandleSelectionChange();
}
static void HandleUpdate()
{
if(Time.timeSinceLevelLoad > SecondsToAutoCaptureScreenshot)
{
EditorApplication.update -= HandleUpdate;
if (_instance != null && ScenePreviewScreenshot.Capture(false))
ScenePreviewUtility.RefreshTextures(_instance);
}
}
void OnGUI()
{
var rect = new Rect(EditorMargin, EditorMargin, Screen.width, position.height - EditorMargin * 2 - PreviewMargin - CaptureScreenshotButtonHeight - EditorMargin);
var data = ScenePreviewUtility.Data;
if (data.Length > 0)
{
var previewsCount = data.Length;
var height = (position.height - EditorMargin * 2 - (PreviewMargin * previewsCount) - CaptureScreenshotButtonHeight) / previewsCount;
var index = 0;
foreach (var item in data)
{
rect = new Rect(EditorMargin, index * (height + PreviewMargin), position.width, height);
if (GUI.Button(rect, string.Empty, _buttonStyle))
{
EditorSceneManager.OpenScene(item.ScenePath);
}
GUI.DrawTexture(rect, item.Texture, ScaleMode.ScaleToFit);
index++;
}
}
if (ScenePreviewUtility.ShowCaptureScreenshotButton &&
GUI.Button(new Rect(EditorMargin, rect.yMax + PreviewMargin, position.width - (EditorMargin * 2), CaptureScreenshotButtonHeight), "Capture screenshot"))
{
ScenePreviewScreenshot.Capture();
ScenePreviewUtility.RefreshTextures(this);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment