diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuSingleSelectGroup.cs b/Source/Editor/GUI/ContextMenu/ContextMenuSingleSelectGroup.cs
new file mode 100644
index 000000000..794729547
--- /dev/null
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuSingleSelectGroup.cs
@@ -0,0 +1,108 @@
+// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using FlaxEngine;
+using FlaxEngine.GUI;
+
+namespace FlaxEditor.GUI.ContextMenu
+{
+ ///
+ /// Context menu single select group.
+ ///
+ [HideInEditor]
+ class ContextMenuSingleSelectGroup
+ {
+ public struct SingleSelectGroupItem
+ {
+ public string text;
+ public U value;
+ public Action onSelected;
+ public List buttons;
+ }
+
+ private List _menus = new List();
+ private List> _items = new List>();
+ public Action OnSelectionChanged;
+
+ public SingleSelectGroupItem activeItem;
+
+ public ContextMenuSingleSelectGroup AddItem(string text, T value, Action onSelected = null)
+ {
+ var item = new SingleSelectGroupItem
+ {
+ text = text,
+ value = value,
+ onSelected = onSelected,
+ buttons = new List()
+ };
+ _items.Add(item);
+
+ foreach (var contextMenu in _menus)
+ AddItemToContextMenu(contextMenu, item);
+
+ return this;
+ }
+
+ public ContextMenuSingleSelectGroup AddItemsToContextMenu(ContextMenu contextMenu)
+ {
+ _menus.Add(contextMenu);
+
+ for (int i = 0; i < _items.Count; i++)
+ {
+ AddItemToContextMenu(contextMenu, _items[i]);
+ }
+
+ return this;
+ }
+
+ private void AddItemToContextMenu(ContextMenu contextMenu, SingleSelectGroupItem item)
+ {
+ var btn = contextMenu.AddButton(item.text, () =>
+ {
+ SetItemAsActive(item);
+ });
+
+ item.buttons.Add(btn);
+
+ if (item.Equals(activeItem))
+ {
+ btn.Checked = true;
+ }
+ }
+
+ private void DeselectAll()
+ {
+ foreach (var item in _items)
+ {
+ foreach (var btn in item.buttons) btn.Checked = false;
+ }
+ }
+
+ public void SetItemAsActive(T value)
+ {
+ var index = _items.FindIndex(x => x.value.Equals(value));
+
+ if (index == -1) return;
+
+ SetItemAsActive(_items[index]);
+ }
+
+ private void SetItemAsActive(SingleSelectGroupItem item)
+ {
+ DeselectAll();
+
+ var index = _items.IndexOf(item);
+ OnSelectionChanged?.Invoke(item.value);
+ item.onSelected?.Invoke();
+
+ foreach (var btn in item.buttons)
+ {
+ btn.Checked = true;
+ }
+
+ activeItem = item;
+ }
+ }
+}
diff --git a/Source/Editor/GUI/ToolStrip.cs b/Source/Editor/GUI/ToolStrip.cs
index 6a881281f..858e21b51 100644
--- a/Source/Editor/GUI/ToolStrip.cs
+++ b/Source/Editor/GUI/ToolStrip.cs
@@ -23,9 +23,14 @@ namespace FlaxEditor.GUI
public const int DefaultMarginH = 2;
///
- /// Event fired when button gets clicked.
+ /// Event fired when button gets clicked with the primary mouse button.
///
- public Action ButtonClicked;
+ public Action ButtonPrimaryClicked;
+
+ ///
+ /// Event fired when button gets clicked with the secondary mouse button.
+ ///
+ public Action ButtonSecondaryClicked;
///
/// Tries to get the last button.
@@ -91,7 +96,7 @@ namespace FlaxEditor.GUI
Parent = this,
};
if (onClick != null)
- button.Clicked += onClick;
+ button.PrimaryClicked += onClick;
return button;
}
@@ -110,7 +115,7 @@ namespace FlaxEditor.GUI
Parent = this,
};
if (onClick != null)
- button.Clicked += onClick;
+ button.PrimaryClicked += onClick;
return button;
}
@@ -128,7 +133,7 @@ namespace FlaxEditor.GUI
Parent = this,
};
if (onClick != null)
- button.Clicked += onClick;
+ button.PrimaryClicked += onClick;
return button;
}
@@ -141,9 +146,14 @@ namespace FlaxEditor.GUI
return AddChild(new ToolStripSeparator(ItemsHeight));
}
- internal void OnButtonClicked(ToolStripButton button)
+ internal void OnButtonPrimaryClicked(ToolStripButton button)
{
- ButtonClicked?.Invoke(button);
+ ButtonPrimaryClicked?.Invoke(button);
+ }
+
+ internal void OnButtonSecondaryClicked(ToolStripButton button)
+ {
+ ButtonSecondaryClicked?.Invoke(button);
}
///
diff --git a/Source/Editor/GUI/ToolStripButton.cs b/Source/Editor/GUI/ToolStripButton.cs
index 09a26b940..f8d032696 100644
--- a/Source/Editor/GUI/ToolStripButton.cs
+++ b/Source/Editor/GUI/ToolStripButton.cs
@@ -11,8 +11,12 @@ namespace FlaxEditor.GUI
///
///
[HideInEditor]
- public class ToolStripButton : Control
+ public partial class ToolStripButton : Control
{
+ // TODO: abstracted for potential future in-editor input configuration (ex. for left handed mouse users)
+ private const MouseButton PRIMARY_MOUSE_BUTTON = MouseButton.Left;
+ private const MouseButton SECONDARY_MOUSE_BUTTON = MouseButton.Right;
+
///
/// The default margin for button parts (icon, text, etc.).
///
@@ -20,12 +24,18 @@ namespace FlaxEditor.GUI
private SpriteHandle _icon;
private string _text;
- private bool _mouseDown;
+ private bool _primaryMouseDown;
+ private bool _secondaryMouseDown;
///
/// Event fired when user clicks the button.
///
- public Action Clicked;
+ public Action PrimaryClicked;
+
+ ///
+ /// Event fired when user clicks the button.
+ ///
+ public Action SecondaryClicked;
///
/// The checked state.
@@ -63,6 +73,11 @@ namespace FlaxEditor.GUI
}
}
+ ///
+ /// A reference to a context menu to raise when the secondary mouse button is pressed.
+ ///
+ public ContextMenu.ContextMenu ContextMenu;
+
///
/// Initializes a new instance of the class.
///
@@ -108,10 +123,11 @@ namespace FlaxEditor.GUI
var iconRect = new Rectangle(DefaultMargin, DefaultMargin, iconSize, iconSize);
var textRect = new Rectangle(DefaultMargin, 0, 0, Height);
bool enabled = EnabledInHierarchy;
+ bool mouseButtonDown = _primaryMouseDown || _secondaryMouseDown;
// Draw background
if (enabled && (IsMouseOver || IsNavFocused || Checked))
- Render2D.FillRectangle(clientRect, Checked ? style.BackgroundSelected : _mouseDown ? style.BackgroundHighlighted : (style.LightBackground * 1.3f));
+ Render2D.FillRectangle(clientRect, Checked ? style.BackgroundSelected : mouseButtonDown ? style.BackgroundHighlighted : (style.LightBackground * 1.3f));
// Draw icon
if (_icon.IsValid)
@@ -153,10 +169,18 @@ namespace FlaxEditor.GUI
///
public override bool OnMouseDown(Float2 location, MouseButton button)
{
- if (button == MouseButton.Left)
+ if (button == PRIMARY_MOUSE_BUTTON)
{
// Set flag
- _mouseDown = true;
+ _primaryMouseDown = true;
+
+ Focus();
+ return true;
+ }
+ else if (button == SECONDARY_MOUSE_BUTTON)
+ {
+ // Set flag
+ _secondaryMouseDown = true;
Focus();
return true;
@@ -168,16 +192,28 @@ namespace FlaxEditor.GUI
///
public override bool OnMouseUp(Float2 location, MouseButton button)
{
- if (button == MouseButton.Left && _mouseDown)
+ if (button == PRIMARY_MOUSE_BUTTON && _primaryMouseDown)
{
// Clear flag
- _mouseDown = false;
+ _primaryMouseDown = false;
// Fire events
if (AutoCheck)
Checked = !Checked;
- Clicked?.Invoke();
- (Parent as ToolStrip)?.OnButtonClicked(this);
+ PrimaryClicked?.Invoke();
+ (Parent as ToolStrip)?.OnButtonPrimaryClicked(this);
+
+ return true;
+ }
+ else if (button == SECONDARY_MOUSE_BUTTON && _secondaryMouseDown)
+ {
+ // Clear flag
+ _secondaryMouseDown = false;
+
+ SecondaryClicked?.Invoke();
+ (Parent as ToolStrip)?.OnButtonSecondaryClicked(this);
+
+ ContextMenu?.Show(this, new Float2(0, Height));
return true;
}
@@ -189,7 +225,8 @@ namespace FlaxEditor.GUI
public override void OnMouseLeave()
{
// Clear flag
- _mouseDown = false;
+ _primaryMouseDown = false;
+ _secondaryMouseDown = false;
base.OnMouseLeave();
}
@@ -198,7 +235,8 @@ namespace FlaxEditor.GUI
public override void OnLostFocus()
{
// Clear flag
- _mouseDown = false;
+ _primaryMouseDown = false;
+ _secondaryMouseDown = false;
base.OnLostFocus();
}
diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs
index 858ef2b1a..c41ccbec3 100644
--- a/Source/Editor/Modules/UIModule.cs
+++ b/Source/Editor/Modules/UIModule.cs
@@ -20,6 +20,8 @@ using FlaxEngine.GUI;
using FlaxEngine.Json;
using DockHintWindow = FlaxEditor.GUI.Docking.DockHintWindow;
using MasterDockPanel = FlaxEditor.GUI.Docking.MasterDockPanel;
+using FlaxEditor.Content.Settings;
+using static FlaxEditor.Options.InterfaceOptions;
namespace FlaxEditor.Modules
{
@@ -36,6 +38,9 @@ namespace FlaxEditor.Modules
private ContentStats _contentStats;
private bool _progressFailed;
+ ContextMenuSingleSelectGroup _numberOfClientsGroup = new ContextMenuSingleSelectGroup();
+ private Scene[] _scenesToReload;
+
private ContextMenuButton _menuFileSaveScenes;
private ContextMenuButton _menuFileCloseScenes;
private ContextMenuButton _menuFileGenerateScriptsProjectFiles;
@@ -54,7 +59,9 @@ namespace FlaxEditor.Modules
private ContextMenuButton _menuSceneAlignViewportWithActor;
private ContextMenuButton _menuScenePilotActor;
private ContextMenuButton _menuSceneCreateTerrain;
- private ContextMenuButton _menuGamePlay;
+ private ContextMenuButton _menuGamePlayGame;
+ private ContextMenuButton _menuGamePlayCurrentScenes;
+ private ContextMenuButton _menuGameStop;
private ContextMenuButton _menuGamePause;
private ContextMenuButton _menuToolsBuildScenes;
private ContextMenuButton _menuToolsBakeLightmaps;
@@ -74,6 +81,7 @@ namespace FlaxEditor.Modules
private ToolStripButton _toolStripRotate;
private ToolStripButton _toolStripScale;
private ToolStripButton _toolStripBuildScenes;
+ private ToolStripButton _toolStripCook;
private ToolStripButton _toolStripPlay;
private ToolStripButton _toolStripPause;
private ToolStripButton _toolStripStep;
@@ -351,6 +359,7 @@ namespace FlaxEditor.Modules
// Update window background
mainWindow.BackgroundColor = Style.Current.Background;
+ InitSharedMenus();
InitMainMenu(mainWindow);
InitToolstrip(mainWindow);
InitStatusBar(mainWindow);
@@ -466,6 +475,19 @@ namespace FlaxEditor.Modules
return dialog;
}
+ private void InitSharedMenus()
+ {
+ for (int i = 1; i <= 4; i++) _numberOfClientsGroup.AddItem(i.ToString(), i);
+
+ _numberOfClientsGroup.SetItemAsActive(Editor.Options.Options.Interface.NumberOfGameClientsToLaunch);
+ _numberOfClientsGroup.OnSelectionChanged = (value) =>
+ {
+ var options = Editor.Options.Options;
+ options.Interface.NumberOfGameClientsToLaunch = value;
+ Editor.Options.Apply(options);
+ };
+ }
+
private void InitMainMenu(RootControl mainWindow)
{
MainMenu = new MainMenu(mainWindow)
@@ -523,11 +545,19 @@ namespace FlaxEditor.Modules
MenuGame = MainMenu.AddButton("Game");
cm = MenuGame.ContextMenu;
cm.VisibleChanged += OnMenuGameShowHide;
- _menuGamePlay = cm.AddButton("Play", inputOptions.Play.ToString(), Editor.Simulation.RequestStartPlay);
+
+ _menuGamePlayGame = cm.AddButton("Play Game", PlayGame);
+ _menuGamePlayCurrentScenes = cm.AddButton("Play Current Scenes", inputOptions.Play.ToString(), PlayScenes);
+ _menuGameStop = cm.AddButton("Stop Game", Editor.Simulation.RequestStopPlay);
_menuGamePause = cm.AddButton("Pause", inputOptions.Pause.ToString(), Editor.Simulation.RequestPausePlay);
+
cm.AddSeparator();
- cm.AddButton("Cook & Run", Editor.Windows.GameCookerWin.BuildAndRun).LinkTooltip("Runs Game Cooker to build the game for this platform and runs the game after.");
- cm.AddButton("Run cooked game", Editor.Windows.GameCookerWin.RunCooked).LinkTooltip("Runs the game build from the last cooking output. Use Cook&Play or Game Cooker first.");
+ var numberOfClientsMenu = cm.AddChildMenu("Number of game clients");
+ _numberOfClientsGroup.AddItemsToContextMenu(numberOfClientsMenu.ContextMenu);
+
+ cm.AddSeparator();
+ cm.AddButton("Cook & Run", CookAndRun).LinkTooltip("Runs Game Cooker to build the game for this platform and runs the game after.");
+ cm.AddButton("Run cooked game", RunCookedGame).LinkTooltip("Runs the game build from the last cooking output. Use Cook&Play or Game Cooker first.");
// Tools
MenuTools = MainMenu.AddButton("Tools");
@@ -603,7 +633,7 @@ namespace FlaxEditor.Modules
_menuEditDuplicate.ShortKeys = inputOptions.Duplicate.ToString();
_menuEditSelectAll.ShortKeys = inputOptions.SelectAll.ToString();
_menuEditFind.ShortKeys = inputOptions.Search.ToString();
- _menuGamePlay.ShortKeys = inputOptions.Play.ToString();
+ _menuGamePlayCurrentScenes.ShortKeys = inputOptions.Play.ToString();
_menuGamePause.ShortKeys = inputOptions.Pause.ToString();
MainMenuShortcutKeysUpdated?.Invoke();
@@ -611,6 +641,8 @@ namespace FlaxEditor.Modules
private void InitToolstrip(RootControl mainWindow)
{
+ var inputOptions = Editor.Options.Options.Input;
+
ToolStrip = new ToolStrip(34.0f, MainMenu.Bottom)
{
Parent = mainWindow,
@@ -627,8 +659,34 @@ namespace FlaxEditor.Modules
ToolStrip.AddSeparator();
_toolStripBuildScenes = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Build64, Editor.BuildScenesOrCancel).LinkTooltip("Build scenes data - CSG, navmesh, static lighting, env probes - configurable via Build Actions in editor options (Ctrl+F10)");
ToolStrip.AddSeparator();
- _toolStripPlay = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Play64, Editor.Simulation.RequestPlayOrStopPlay).LinkTooltip("Start/Stop game (F5)");
- _toolStripPause = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Pause64, Editor.Simulation.RequestResumeOrPause).LinkTooltip("Pause/Resume game(F6)");
+
+ // build
+ _toolStripCook = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.BuildSettings128, CookAndRun).LinkTooltip("Cook and run");
+ _toolStripCook.ContextMenu = new ContextMenu();
+ _toolStripCook.ContextMenu.AddButton("Run cooked game", RunCookedGame);
+ _toolStripCook.ContextMenu.AddSeparator();
+ var numberOfClientsMenu = _toolStripCook.ContextMenu.AddChildMenu("Number of game clients");
+ _numberOfClientsGroup.AddItemsToContextMenu(numberOfClientsMenu.ContextMenu);
+
+ // play
+ _toolStripPlay = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Play64, OnPlayPressed).LinkTooltip("Play Game");
+ _toolStripPlay.ContextMenu = new ContextMenu();
+ ContextMenuChildMenu playSubMenu;
+
+ // play - button action
+ playSubMenu = _toolStripPlay.ContextMenu.AddChildMenu("Play button action");
+ var playActionGroup = new ContextMenuSingleSelectGroup();
+ playActionGroup.AddItem("Play Game", PlayAction.PlayGame);
+ playActionGroup.AddItem("Play Scenes", PlayAction.PlayScenes);
+ playActionGroup.AddItemsToContextMenu(playSubMenu.ContextMenu);
+ playActionGroup.SetItemAsActive(Editor.Options.Options.Interface.PlayButtonAction);
+ // important to add the handler after setting the initial item as active above or the editor will crash
+ playActionGroup.OnSelectionChanged = SetPlayAction;
+ // TODO: there are some holes in the syncing of these values
+ // - when changing in the editor, the options will be updated, but the options UI in-editor will not
+ // - when updating the value in the options UI, the value in the tool strip will not update (adding an options changed event handler results in a crash)
+
+ _toolStripPause = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Pause64, Editor.Simulation.RequestResumeOrPause).LinkTooltip($"Pause/Resume game({inputOptions.Pause.ToString()})");
_toolStripStep = (ToolStripButton)ToolStrip.AddButton(Editor.Icons.Skip64, Editor.Simulation.RequestPlayOneFrame).LinkTooltip("Step one frame in game");
UpdateToolstrip();
@@ -786,7 +844,9 @@ namespace FlaxEditor.Modules
var isPlayMode = Editor.StateMachine.IsPlayMode;
var canPlay = Level.IsAnySceneLoaded;
- _menuGamePlay.Enabled = !isPlayMode && canPlay;
+ _menuGamePlayGame.Enabled = !isPlayMode && canPlay;
+ _menuGamePlayCurrentScenes.Enabled = !isPlayMode && canPlay;
+ _menuGameStop.Enabled = isPlayMode && canPlay;
_menuGamePause.Enabled = isPlayMode && canPlay;
c.PerformLayout();
@@ -968,6 +1028,70 @@ namespace FlaxEditor.Modules
projectInfo.Save();
}
+ private void SetPlayAction(PlayAction newPlayAction)
+ {
+ var options = Editor.Options.Options;
+ options.Interface.PlayButtonAction = newPlayAction;
+ Editor.Options.Apply(options);
+ }
+
+ private void OnPlayPressed()
+ {
+ switch (Editor.Options.Options.Interface.PlayButtonAction)
+ {
+ case PlayAction.PlayGame:
+ if (Editor.IsPlayMode)
+ Editor.Simulation.RequestStopPlay();
+ else
+ PlayGame();
+ return;
+ case PlayAction.PlayScenes: PlayScenes(); return;
+ }
+ }
+
+ private void PlayGame()
+ {
+ var firstScene = GameSettings.Load().FirstScene;
+
+ if (firstScene == Guid.Empty)
+ {
+ if (Level.IsAnySceneLoaded) Editor.Simulation.RequestStartPlay();
+ return;
+ }
+
+ _scenesToReload = Level.Scenes;
+ Level.UnloadAllScenes();
+ Level.LoadScene(firstScene);
+
+ Editor.PlayModeEnd += OnPlayGameSceneEnding;
+ Editor.Simulation.RequestPlayOrStopPlay();
+ }
+
+ private void OnPlayGameSceneEnding()
+ {
+ Editor.PlayModeEnd -= OnPlayGameSceneEnding;
+
+ Level.UnloadAllScenes();
+
+ foreach (var scene in _scenesToReload)
+ Level.LoadScene(scene.ID);
+ }
+
+ private void PlayScenes()
+ {
+ Editor.Simulation.RequestPlayOrStopPlay();
+ }
+
+ private void CookAndRun()
+ {
+ Editor.Windows.GameCookerWin.BuildAndRun();
+ }
+
+ private void RunCookedGame()
+ {
+ Editor.Windows.GameCookerWin.RunCooked();
+ }
+
private void OnMainWindowClosing()
{
// Clear UI references (GUI cannot be used after window closing)
diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs
index acfb7f5e8..7d97fecd6 100644
--- a/Source/Editor/Options/InterfaceOptions.cs
+++ b/Source/Editor/Options/InterfaceOptions.cs
@@ -74,6 +74,21 @@ namespace FlaxEditor.Options
DockBottom = DockState.DockBottom
}
+ ///
+ /// Options for the action taken by the play button.
+ ///
+ public enum PlayAction
+ {
+ ///
+ /// Launches the game from the First Scene defined in the project settings.
+ ///
+ PlayGame,
+ ///
+ /// Launches the game using the scenes currently loaded in the editor.
+ ///
+ PlayScenes
+ }
+
///
/// Gets or sets the Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required.
///
@@ -196,30 +211,45 @@ namespace FlaxEditor.Options
[EditorDisplay("Play In-Editor", "Focus Game Window On Play"), EditorOrder(400), Tooltip("Determines whether auto-focus game window on play mode start.")]
public bool FocusGameWinOnPlay { get; set; } = true;
+ ///
+ /// Gets or sets a value indicating what action should be taken upon pressing the play button.
+ ///
+ [DefaultValue(PlayAction.PlayScenes)]
+ [EditorDisplay("Play In-Editor", "Play Button Action"), EditorOrder(410), Tooltip("Determines the action taken when the play button is pressed.")]
+ public PlayAction PlayButtonAction { get; set; } = PlayAction.PlayScenes;
+
+ ///
+ /// Gets or sets a value indicating the number of game clients to launch when building and/or running cooked game.
+ ///
+ [DefaultValue(1)]
+ [EditorDisplay("Cook & Run", "Number Of GameClients To Launch"), EditorOrder(500), Tooltip("Determines the number of game clients to launch when building and/or running cooked game.")]
+ [Range(1, 4)]
+ public int NumberOfGameClientsToLaunch = 1;
+
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont);
///
/// Gets or sets the title font for editor UI.
///
- [EditorDisplay("Fonts"), EditorOrder(500), Tooltip("The title font for editor UI.")]
+ [EditorDisplay("Fonts"), EditorOrder(600), Tooltip("The title font for editor UI.")]
public FontReference TitleFont { get; set; } = new FontReference(DefaultFont, 18);
///
/// Gets or sets the large font for editor UI.
///
- [EditorDisplay("Fonts"), EditorOrder(510), Tooltip("The large font for editor UI.")]
+ [EditorDisplay("Fonts"), EditorOrder(610), Tooltip("The large font for editor UI.")]
public FontReference LargeFont { get; set; } = new FontReference(DefaultFont, 14);
///
/// Gets or sets the medium font for editor UI.
///
- [EditorDisplay("Fonts"), EditorOrder(520), Tooltip("The medium font for editor UI.")]
+ [EditorDisplay("Fonts"), EditorOrder(620), Tooltip("The medium font for editor UI.")]
public FontReference MediumFont { get; set; } = new FontReference(DefaultFont, 9);
///
/// Gets or sets the small font for editor UI.
///
- [EditorDisplay("Fonts"), EditorOrder(530), Tooltip("The small font for editor UI.")]
+ [EditorDisplay("Fonts"), EditorOrder(630), Tooltip("The small font for editor UI.")]
public FontReference SmallFont { get; set; } = new FontReference(DefaultFont, 9);
}
}
diff --git a/Source/Editor/Windows/GameCookerWindow.cs b/Source/Editor/Windows/GameCookerWindow.cs
index f3fd753d1..f88fa36f5 100644
--- a/Source/Editor/Windows/GameCookerWindow.cs
+++ b/Source/Editor/Windows/GameCookerWindow.cs
@@ -110,14 +110,14 @@ namespace FlaxEditor.Windows
#if PLATFORM_WINDOWS
switch (BuildPlatform)
{
- case BuildPlatform.MacOSx64:
- case BuildPlatform.MacOSARM64:
- case BuildPlatform.iOSARM64:
- IsSupported = false;
- break;
- default:
- IsSupported = true;
- break;
+ case BuildPlatform.MacOSx64:
+ case BuildPlatform.MacOSARM64:
+ case BuildPlatform.iOSARM64:
+ IsSupported = false;
+ break;
+ default:
+ IsSupported = true;
+ break;
}
#elif PLATFORM_LINUX
switch (BuildPlatform)
@@ -160,17 +160,17 @@ namespace FlaxEditor.Windows
{
switch (BuildPlatform)
{
- case BuildPlatform.Windows32:
- case BuildPlatform.Windows64:
- case BuildPlatform.UWPx86:
- case BuildPlatform.UWPx64:
- case BuildPlatform.LinuxX64:
- case BuildPlatform.AndroidARM64:
- layout.Label("Use Flax Launcher and download the required package.", TextAlignment.Center);
- break;
- default:
- layout.Label("Engine source is required to target this platform.", TextAlignment.Center);
- break;
+ case BuildPlatform.Windows32:
+ case BuildPlatform.Windows64:
+ case BuildPlatform.UWPx86:
+ case BuildPlatform.UWPx64:
+ case BuildPlatform.LinuxX64:
+ case BuildPlatform.AndroidARM64:
+ layout.Label("Use Flax Launcher and download the required package.", TextAlignment.Center);
+ break;
+ default:
+ layout.Label("Engine source is required to target this platform.", TextAlignment.Center);
+ break;
}
}
else
@@ -272,43 +272,43 @@ namespace FlaxEditor.Windows
string name;
switch (_platform)
{
- case PlatformType.Windows:
- name = "Windows";
- break;
- case PlatformType.XboxOne:
- name = "Xbox One";
- break;
- case PlatformType.UWP:
- name = "Windows Store";
- layout.Label("UWP (Windows Store) platform has been deprecated and is no longer supported", TextAlignment.Center).Label.TextColor = Color.Red;
- break;
- case PlatformType.Linux:
- name = "Linux";
- break;
- case PlatformType.PS4:
- name = "PlayStation 4";
- break;
- case PlatformType.XboxScarlett:
- name = "Xbox Scarlett";
- break;
- case PlatformType.Android:
- name = "Android";
- break;
- case PlatformType.Switch:
- name = "Switch";
- break;
- case PlatformType.PS5:
- name = "PlayStation 5";
- break;
- case PlatformType.Mac:
- name = "Mac";
- break;
- case PlatformType.iOS:
- name = "iOS";
- break;
- default:
- name = Utilities.Utils.GetPropertyNameUI(_platform.ToString());
- break;
+ case PlatformType.Windows:
+ name = "Windows";
+ break;
+ case PlatformType.XboxOne:
+ name = "Xbox One";
+ break;
+ case PlatformType.UWP:
+ name = "Windows Store";
+ layout.Label("UWP (Windows Store) platform has been deprecated and is no longer supported", TextAlignment.Center).Label.TextColor = Color.Red;
+ break;
+ case PlatformType.Linux:
+ name = "Linux";
+ break;
+ case PlatformType.PS4:
+ name = "PlayStation 4";
+ break;
+ case PlatformType.XboxScarlett:
+ name = "Xbox Scarlett";
+ break;
+ case PlatformType.Android:
+ name = "Android";
+ break;
+ case PlatformType.Switch:
+ name = "Switch";
+ break;
+ case PlatformType.PS5:
+ name = "PlayStation 5";
+ break;
+ case PlatformType.Mac:
+ name = "Mac";
+ break;
+ case PlatformType.iOS:
+ name = "iOS";
+ break;
+ default:
+ name = Utilities.Utils.GetPropertyNameUI(_platform.ToString());
+ break;
}
var group = layout.Group(name);
@@ -659,16 +659,24 @@ namespace FlaxEditor.Windows
{
Editor.Log("Building and running");
GameCooker.GetCurrentPlatform(out var platform, out var buildPlatform, out var buildConfiguration);
- _buildingQueue.Enqueue(new QueueItem
+ var numberOfClients = Editor.Options.Options.Interface.NumberOfGameClientsToLaunch;
+
+ for (int i = 0; i < numberOfClients; i++)
{
- Target = new BuildTarget
+ var buildOptions = BuildOptions.AutoRun;
+ if (i > 0) buildOptions |= BuildOptions.NoCook;
+
+ _buildingQueue.Enqueue(new QueueItem
{
- Output = _buildTabProxy.PerPlatformOptions[platform].Output,
- Platform = buildPlatform,
- Mode = buildConfiguration,
- },
- Options = BuildOptions.AutoRun,
- });
+ Target = new BuildTarget
+ {
+ Output = _buildTabProxy.PerPlatformOptions[platform].Output,
+ Platform = buildPlatform,
+ Mode = buildConfiguration,
+ },
+ Options = buildOptions,
+ });
+ }
}
///
@@ -678,16 +686,21 @@ namespace FlaxEditor.Windows
{
Editor.Log("Running cooked build");
GameCooker.GetCurrentPlatform(out var platform, out var buildPlatform, out var buildConfiguration);
- _buildingQueue.Enqueue(new QueueItem
+ var numberOfClients = Editor.Options.Options.Interface.NumberOfGameClientsToLaunch;
+
+ for (int i = 0; i < numberOfClients; i++)
{
- Target = new BuildTarget
+ _buildingQueue.Enqueue(new QueueItem
{
- Output = _buildTabProxy.PerPlatformOptions[platform].Output,
- Platform = buildPlatform,
- Mode = buildConfiguration,
- },
- Options = BuildOptions.AutoRun | BuildOptions.NoCook,
- });
+ Target = new BuildTarget
+ {
+ Output = _buildTabProxy.PerPlatformOptions[platform].Output,
+ Platform = buildPlatform,
+ Mode = buildConfiguration,
+ },
+ Options = BuildOptions.AutoRun | BuildOptions.NoCook,
+ });
+ }
}
private void BuildTarget()
diff --git a/Source/Editor/Windows/Profiler/ProfilerWindow.cs b/Source/Editor/Windows/Profiler/ProfilerWindow.cs
index f5a5c6f86..b35641bf6 100644
--- a/Source/Editor/Windows/Profiler/ProfilerWindow.cs
+++ b/Source/Editor/Windows/Profiler/ProfilerWindow.cs
@@ -93,7 +93,7 @@ namespace FlaxEditor.Windows.Profiler
_liveRecordingButton = toolstrip.AddButton(editor.Icons.Play64);
_liveRecordingButton.LinkTooltip("Live profiling events recording");
_liveRecordingButton.AutoCheck = true;
- _liveRecordingButton.Clicked += () => _liveRecordingButton.Icon = LiveRecording ? editor.Icons.Stop64 : editor.Icons.Play64;
+ _liveRecordingButton.PrimaryClicked += () => _liveRecordingButton.Icon = LiveRecording ? editor.Icons.Stop64 : editor.Icons.Play64;
_clearButton = toolstrip.AddButton(editor.Icons.Rotate32, Clear);
_clearButton.LinkTooltip("Clear data");
toolstrip.AddSeparator();