//********************************** 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();
}
}
}
/** @} */
}