using BansheeEngine; namespace BansheeEditor { /// /// Displays in-game viewport in the editor. /// public class GameWindow : EditorWindow { private const int HeaderHeight = 20; private readonly AspectRatio[] aspectRatios = { new AspectRatio(16, 9), new AspectRatio(16, 10), new AspectRatio(5, 4), new AspectRatio(4, 3), new AspectRatio(3, 2) }; private int selectedAspectRatio = 0; private GUIRenderTexture renderTextureGUI; /// /// Opens the game window. /// [MenuItem("Windows/Game", ButtonModifier.CtrlAlt, ButtonCode.G, 6000)] private static void OpenGameWindow() { OpenWindow(); } /// /// Starts execution of the game in the game window. /// [MenuItem("Tools/Play", 9300)] [ToolbarItem("Play", ToolbarIcon.Play, "", 1800, true)] private static void Play() { if (EditorApplication.IsPaused) EditorApplication.IsPaused = false; else EditorApplication.IsPlaying = !EditorApplication.IsPlaying; } /// /// Pauses the execution of the game on the current frame. /// [MenuItem("Tools/Pause", 9299)] [ToolbarItem("Pause", ToolbarIcon.Pause, "", 1799)] private static void Pause() { EditorApplication.IsPaused = !EditorApplication.IsPaused; } /// /// Moves the execution of the game by one frame forward. /// [MenuItem("Tools/Step", 9298)] [ToolbarItem("Step", ToolbarIcon.Step, "", 1798)] private static void Step() { EditorApplication.FrameStep(); } /// protected override LocString GetDisplayName() { return new LocEdString("Game"); } private void OnInitialize() { GUILayoutY mainLayout = GUI.AddLayoutY(); string[] aspectRatioTitles = new string[aspectRatios.Length + 1]; aspectRatioTitles[0] = "Free"; for (int i = 0; i < aspectRatios.Length; i++) aspectRatioTitles[i + 1] = aspectRatios[i].width + ":" + aspectRatios[i].height; GUIListBoxField aspectField = new GUIListBoxField(aspectRatioTitles, new LocEdString("Aspect ratio")); aspectField.OnSelectionChanged += OnAspectRatioChanged; GUILayout buttonLayout = mainLayout.AddLayoutX(); buttonLayout.AddElement(aspectField); buttonLayout.AddFlexibleSpace(); renderTextureGUI = new GUIRenderTexture(null); GUILayoutY alignLayoutY = mainLayout.AddLayoutY(); alignLayoutY.AddFlexibleSpace(); GUILayoutX alignLayoutX = alignLayoutY.AddLayoutX(); alignLayoutX.AddFlexibleSpace(); alignLayoutX.AddElement(renderTextureGUI); alignLayoutX.AddFlexibleSpace(); alignLayoutY.AddFlexibleSpace(); UpdateRenderTexture(Width, Height); } private void OnDestroy() { EditorApplication.MainRenderTarget = null; } /// /// Creates or rebuilds the main render texture. Should be called at least once before using the /// game window. Should be called whenever the window is resized. /// /// Width of the scene render target, in pixels. /// Height of the scene render target, in pixels. private void UpdateRenderTexture(int width, int height) { width = MathEx.Max(20, width); height = MathEx.Max(20, height - HeaderHeight); if (selectedAspectRatio != 0) // 0 is free aspect { AspectRatio aspectRatio = aspectRatios[selectedAspectRatio - 1]; float aspectInv = aspectRatio.height/(float)aspectRatio.width; height = MathEx.RoundToInt(width*aspectInv); } RenderTexture2D renderTexture = new RenderTexture2D(PixelFormat.R8G8B8A8, width, height) {Priority = 1}; EditorApplication.MainRenderTarget = renderTexture; renderTextureGUI.RenderTexture = renderTexture; } /// /// Triggered when the user selects a new aspect ratio from the drop down box. /// /// Index of the aspect ratio the user selected. private void OnAspectRatioChanged(int idx) { selectedAspectRatio = idx; UpdateRenderTexture(Width, Height); } /// protected override void WindowResized(int width, int height) { UpdateRenderTexture(width, height - HeaderHeight); base.WindowResized(width, height); } /// /// Camera aspect ratio as numerator and denominator. /// struct AspectRatio { /// /// Creates a new object that holds the aspect ratio. /// /// Numerator of the aspect ratio. /// Denominator of the aspect ratio. public AspectRatio(int width, int height) { this.width = width; this.height = height; } public int width; public int height; } } }