//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// using System; using bs; namespace bs.Editor { /** @addtogroup Build * @{ */ /// /// Provides options for customizing and activating the build process which will output an executable of the game for a /// specific platform, as well as any required resources. /// [DefaultSize(500, 300)] internal sealed class BuildWindow : EditorWindow { private static readonly Color PLATFORM_BG_COLOR = new Color(33.0f / 255.0f, 33.0f / 255.0f, 33.0f / 255.0f); private PlatformType selectedPlatform; private GUIScrollArea optionsScrollArea; private ulong buildScheduledFrame = ulong.MaxValue; private GUIToggle[] platformButtons; /// /// Opens the build window if its not open already. /// [MenuItem("Tools/Build", ButtonModifier.CtrlAlt, ButtonCode.B, 9249)] private static void OpenBuildWindow() { OpenWindow(); } /// protected override LocString GetDisplayName() { return new LocEdString("Build"); } private void OnInitialize() { GUILayoutX splitLayout = GUI.AddLayoutX(); GUIPanel platformPanel = splitLayout.AddPanel(); GUIPanel platformForeground = platformPanel.AddPanel(); GUILayoutY platformLayout = platformForeground.AddLayoutY(); GUIPanel platformBackground = platformPanel.AddPanel(1); GUITexture background = new GUITexture(Builtin.WhiteTexture); background.SetTint(PLATFORM_BG_COLOR); splitLayout.AddSpace(5); GUILayoutY optionsLayout = splitLayout.AddLayoutY(); GUILabel platformsLabel = new GUILabel(new LocEdString("Platforms"), EditorStyles.LabelCentered); platformLayout.AddSpace(5); platformLayout.AddElement(platformsLabel); platformLayout.AddSpace(5); GUIToggleGroup platformToggleGroup = new GUIToggleGroup(); PlatformType[] availablePlatforms = BuildManager.AvailablePlatforms; platformButtons = new GUIToggle[availablePlatforms.Length]; for (int i = 0; i < availablePlatforms.Length; i++) { PlatformType currentPlatform = availablePlatforms[i]; bool isActive = currentPlatform == BuildManager.ActivePlatform; string platformName = Enum.GetName(typeof(PlatformType), currentPlatform); if (isActive) platformName += " (Active)"; GUIToggle platformToggle = new GUIToggle(new LocEdString(platformName), platformToggleGroup, EditorStyles.Button); platformToggle.OnToggled += x => OnSelectedPlatformChanged(currentPlatform, x); platformLayout.AddElement(platformToggle); platformButtons[i] = platformToggle; if (isActive) { platformToggle.Value = true; selectedPlatform = currentPlatform; } } platformLayout.AddFlexibleSpace(); GUIButton changePlatformBtn = new GUIButton(new LocEdString("Set active")); platformLayout.AddElement(changePlatformBtn); changePlatformBtn.OnClick += ChangeActivePlatform; platformBackground.AddElement(background); optionsScrollArea = new GUIScrollArea(); optionsLayout.AddElement(optionsScrollArea); GUIButton buildButton = new GUIButton(new LocEdString("Build")); optionsLayout.AddFlexibleSpace(); optionsLayout.AddElement(buildButton); buildButton.OnClick += TryStartBuild; BuildPlatformOptionsGUI(); } private void OnEditorUpdate() { if (buildScheduledFrame == Time.FrameIdx) { BuildManager.Build(); ProgressBar.Hide(); EditorApplication.OpenFolder(BuildManager.OutputFolder); DialogBox.Open(new LocEdString("Build complete"), new LocEdString("Build complete"), DialogBox.Type.OK); } } /// /// Changes the currently selected platform. Be aware that while platform is selected and you may build for it, /// it will not be made the active platform. /// /// Platform that was selected or deselected. /// True if the platform was selected, false otherwise. private void OnSelectedPlatformChanged(PlatformType type, bool selected) { if (selected) { selectedPlatform = type; BuildPlatformOptionsGUI(); } } /// /// Changes the currently active build platform. /// private void ChangeActivePlatform() { BuildManager.ActivePlatform = selectedPlatform; PlatformType[] availablePlatforms = BuildManager.AvailablePlatforms; for (int i = 0; i < availablePlatforms.Length; i++) { PlatformType currentPlatform = availablePlatforms[i]; bool isActive = currentPlatform == BuildManager.ActivePlatform; string platformName = Enum.GetName(typeof (PlatformType), currentPlatform); if (isActive) platformName += " (Active)"; platformButtons[i].SetContent(new LocEdString(platformName)); } } /// /// (Re)creates GUI with platform-specific options. /// private void BuildPlatformOptionsGUI() { optionsScrollArea.Layout.Clear(); GUILayout layout = optionsScrollArea.Layout; PlatformInfo platformInfo = BuildManager.GetPlatformInfo(selectedPlatform); GUILabel options = new GUILabel(new LocEdString("Platform options"), EditorStyles.LabelCentered); GUIResourceField sceneField = new GUIResourceField(typeof(Prefab), new LocEdString("Startup scene")); GUIToggleField debugToggle = new GUIToggleField(new LocEdString("Debug")); GUIToggleField fullscreenField = new GUIToggleField(new LocEdString("Fullscreen")); GUIIntField widthField = new GUIIntField(new LocEdString("Window width")); GUIIntField heightField = new GUIIntField(new LocEdString("Window height")); GUITextField definesField = new GUITextField(new LocEdString("Defines")); layout.AddSpace(5); layout.AddElement(options); layout.AddSpace(5); layout.AddElement(sceneField); layout.AddElement(debugToggle); layout.AddElement(fullscreenField); layout.AddElement(widthField); layout.AddElement(heightField); layout.AddSpace(5); layout.AddElement(definesField); layout.AddSpace(5); sceneField.ValueRef = platformInfo.MainScene; debugToggle.Value = platformInfo.Debug; definesField.Value = platformInfo.Defines; fullscreenField.Value = platformInfo.Fullscreen; widthField.Value = platformInfo.WindowedWidth; heightField.Value = platformInfo.WindowedHeight; if (platformInfo.Fullscreen) { widthField.Active = false; heightField.Active = false; } sceneField.OnChanged += x => platformInfo.MainScene = x.As(); debugToggle.OnChanged += x => platformInfo.Debug = x; definesField.OnChanged += x => platformInfo.Defines = x; fullscreenField.OnChanged += x => { widthField.Active = !x; heightField.Active = !x; platformInfo.Fullscreen = x; }; widthField.OnChanged += x => platformInfo.WindowedWidth = x; heightField.OnChanged += x => platformInfo.WindowedHeight = x; switch (platformInfo.Type) { case PlatformType.Windows: { WinPlatformInfo winPlatformInfo = (WinPlatformInfo) platformInfo; GUITextField titleField = new GUITextField(new LocEdString("Title")); layout.AddElement(titleField); layout.AddSpace(5); GUITextureField iconField = new GUITextureField(new LocEdString("Icon")); layout.AddElement(iconField); titleField.Value = winPlatformInfo.TitleText; iconField.TextureRef = winPlatformInfo.Icon; titleField.OnChanged += x => winPlatformInfo.TitleText = x; iconField.OnChanged += x => winPlatformInfo.Icon = x.As(); } break; } } /// /// Starts the build process for the currently selected platform. /// private void Build() { ProgressBar.Show(new LocEdString("Building..."), 0.0f); EditorApplication.SaveProject(); // HACK - Delay build one frame so that progress bar has a chance to show. Use coroutines here once implemented. buildScheduledFrame = Time.FrameIdx + 1; } /// /// Attempts to save the current scene, and keeps retrying if failed or until user cancels. /// private void TrySaveScene() { EditorApplication.SaveScene(Build, TrySaveScene); } /// /// Attempts to start the build process if user confirms. /// private void TryStartBuild() { Action dialogCallback = (result) => { if (result == DialogBox.ResultType.Yes) TrySaveScene(); else if (result == DialogBox.ResultType.No) Build(); }; if (EditorApplication.IsSceneModified()) { DialogBox.Open("Warning", "You current scene has modifications. Do you wish to save them first?", DialogBox.Type.YesNoCancel, dialogCallback); } else { Build(); } } } /** @} */ }