Просмотр исходного кода

Merge pull request #451 from rsredsq/RED-EDITOR-375

Remember player positioning when run from editor and Prevent multiple Atomic Player windows
JoshEngebretson 10 лет назад
Родитель
Сommit
860ffb836c
29 измененных файлов с 326 добавлено и 42 удалено
  1. 4 1
      Resources/EditorData/AtomicEditor/editor/skin/skin.tb.txt
  2. BIN
      Resources/EditorData/AtomicEditor/editor/skin/stop.png
  3. 3 3
      Resources/EditorData/AtomicEditor/editor/ui/maintoolbar.tb.txt
  4. 8 2
      Script/AtomicEditor/editor/Editor.ts
  5. 1 0
      Script/AtomicEditor/editor/EditorEvents.ts
  6. 35 3
      Script/AtomicEditor/editor/Preferences.ts
  7. 15 3
      Script/AtomicEditor/ui/MainToolbar.ts
  8. 21 13
      Script/AtomicEditor/ui/Shortcuts.ts
  9. 2 2
      Script/AtomicEditor/ui/frames/menus/MainFrameMenu.ts
  10. 4 1
      Script/Packages/Atomic/Graphics.json
  11. 12 0
      Source/Atomic/Graphics/Direct3D11/D3D11Graphics.cpp
  12. 7 0
      Source/Atomic/Graphics/Direct3D11/D3D11Graphics.h
  13. 12 0
      Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp
  14. 7 0
      Source/Atomic/Graphics/Direct3D9/D3D9Graphics.h
  15. 12 0
      Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp
  16. 7 0
      Source/Atomic/Graphics/OpenGL/OGLGraphics.h
  17. 1 0
      Source/Atomic/UI/UI.cpp
  18. 16 2
      Source/AtomicEditor/Application/AEEditorApp.cpp
  19. 34 0
      Source/AtomicEditor/Application/AEEditorCommon.cpp
  20. 3 1
      Source/AtomicEditor/Application/AEEditorCommon.h
  21. 31 0
      Source/AtomicEditor/Application/AEPlayerApp.cpp
  22. 2 0
      Source/AtomicEditor/Application/AEPlayerApp.h
  23. 2 2
      Source/AtomicEditor/EditorMode/AEEditorEvents.h
  24. 26 5
      Source/AtomicEditor/EditorMode/AEEditorMode.cpp
  25. 5 2
      Source/AtomicEditor/EditorMode/AEEditorMode.h
  26. 2 2
      Source/AtomicEditor/Editors/SceneEditor3D/SceneEditor3D.cpp
  27. 36 0
      Source/AtomicEditor/PlayerMode/AEPlayerEvents.h
  28. 17 0
      Source/AtomicEditor/PlayerMode/AEPlayerMode.cpp
  29. 1 0
      Source/AtomicEditor/PlayerMode/AEPlayerMode.h

+ 4 - 1
Resources/EditorData/AtomicEditor/editor/skin/skin.tb.txt

@@ -78,6 +78,9 @@ elements
 	PlayButton
 		bitmap play.png
 
+	StopButton
+		bitmap stop.png
+
 	PowerOffButton
 		bitmap power_off.png
 
@@ -171,7 +174,7 @@ elements
 	InspectorVectorAttrName
 		text-color #aaaaaa
 		min-width 140
-		max-width 140		
+		max-width 140
 
 	InspectorTextAttrName
 		padding 4

BIN
Resources/EditorData/AtomicEditor/editor/skin/stop.png


+ 3 - 3
Resources/EditorData/AtomicEditor/editor/ui/maintoolbar.tb.txt

@@ -1,11 +1,11 @@
 definitions
-	menubutton		
+	menubutton
 		lp: height: 28, width: 28
 		skin TBButton.uniformflat
 TBLayout: distribution: gravity, spacing: 4
-	TBButton 
+	TBButton
 		@include definitions>menubutton
-		TBSkinImage: skin: PlayButton
+		TBSkinImage: skin: PlayButton, id: skin_image
 		id maintoolbar_play
 	TBButton: toggle-mode: 1
 		@include definitions>menubutton

+ 8 - 2
Script/AtomicEditor/editor/Editor.ts

@@ -34,12 +34,12 @@ class Editor extends Atomic.ScriptObject {
 
         Editor.instance = this;
 
+        Preferences.getInstance().read();
+
         this.initUI();
 
         this.editorLicense = new EditorLicense();
 
-        Preferences.getInstance().read();
-
         EditorUI.initialize();
 
         this.playMode = new PlayMode();
@@ -53,6 +53,10 @@ class Editor extends Atomic.ScriptObject {
             this.handleProjectUnloaded(data)
         });
 
+        this.subscribeToEvent("IPCPlayerWindowChanged", (data) => {
+            Preferences.getInstance().savePlayerWindowData(data.posX, data.posY, data.width, data.height, data.monitor);
+        });
+
         this.subscribeToEvent("ExitRequested", (data) => this.handleExitRequested(data));
 
         this.subscribeToEvent("ProjectLoaded", (data) => {
@@ -118,6 +122,7 @@ class Editor extends Atomic.ScriptObject {
     }
 
     closeProject() {
+        this.sendEvent("IPCPlayerExitRequest");
         var system = ToolCore.getToolSystem();
 
         if (system.project) {
@@ -155,6 +160,7 @@ class Editor extends Atomic.ScriptObject {
 
     // event handling
     handleExitRequested(data) {
+        this.sendEvent("IPCPlayerExitRequest");
         this.exitRequested = true;
         this.closeAllResourceEditors();
     }

+ 1 - 0
Script/AtomicEditor/editor/EditorEvents.ts

@@ -14,6 +14,7 @@ export interface ModalErrorEvent {
 }
 
 export const PlayerStarted = "EditorPlayerStarted";
+export const PlayerStopped = "EditorPlayerStopped";
 export const PlayerLog = "EditorPlayerLog";
 export interface PlayerLogEvent {
 

+ 35 - 3
Script/AtomicEditor/editor/Preferences.ts

@@ -68,7 +68,14 @@ class Preferences {
         }
         //Read file
         jsonFile = new Atomic.File(filePath, Atomic.FILE_READ);
-        var prefs = <PreferencesFormat>JSON.parse(jsonFile.readText());
+        var prefs;
+        try {
+          prefs = <PreferencesFormat>JSON.parse(jsonFile.readText());
+        } catch (e){
+          console.log("Editor preference file invalid, regenerating default configuration");
+          prefs = null;
+          this.useDefaultConfig();
+        }
         if (prefs) {
             if (!prefs.recentProjects) prefs.recentProjects = [""];
             this._prefs = prefs;
@@ -87,10 +94,26 @@ class Preferences {
             width = graphics.getWidth();
             height = graphics.getHeight();
         }
-        this._prefs.window = { x: pos[0], y: pos[1], width: width, height: height };
+        this._prefs.editorWindow = { x: pos[0], y: pos[1], width: width, height: height, monitor: graphics.getCurrentMonitor() };
         jsonFile.writeString(JSON.stringify(this._prefs, null, 2));
     }
 
+    savePlayerWindowData(x, y, width, height, monitor) {
+        this._prefs.playerWindow = { x: x, y: y, width: width, height: height, monitor: monitor };
+    }
+
+    useDefaultConfig():void {
+        this._prefs = new PreferencesFormat();
+    }
+
+    get editorWindow():WindowData {
+        return this._prefs.editorWindow;
+    }
+
+    get playerWindow():WindowData {
+        return this._prefs.playerWindow;
+    }
+
     get recentProjects(): [string] {
         return this._prefs.recentProjects;
     }
@@ -100,9 +123,18 @@ class Preferences {
     }
 }
 
+interface WindowData {
+    x: number;
+    y: number;
+    width: number;
+    height: number;
+    monitor: number;
+}
+
 class PreferencesFormat {
     recentProjects: [string];
-    window: { x: number, y: number, width: number, height: number };
+    editorWindow: WindowData;
+    playerWindow: WindowData;
 }
 
 export = Preferences;

+ 15 - 3
Script/AtomicEditor/ui/MainToolbar.ts

@@ -6,6 +6,7 @@
 //
 
 import EditorUI = require("./EditorUI");
+import EditorEvents = require("../editor/EditorEvents");
 
 class MainToolbar extends Atomic.UIWidget {
 
@@ -13,6 +14,7 @@ class MainToolbar extends Atomic.UIWidget {
     rotateButton: Atomic.UIButton;
     scaleButton: Atomic.UIButton;
     axisButton: Atomic.UIButton;
+    playButton: Atomic.UIButton;
 
     constructor(parent: Atomic.UIWidget) {
 
@@ -26,13 +28,25 @@ class MainToolbar extends Atomic.UIWidget {
 
         this.axisButton = <Atomic.UIButton>this.getWidget("3d_axismode");
 
+        this.playButton = <Atomic.UIButton>this.getWidget("maintoolbar_play");
+
         this.translateButton.value = 1;
 
         parent.addChild(this);
 
         this.subscribeToEvent("GizmoAxisModeChanged", (ev) => this.handleGizmoAxisModeChanged(ev));
         this.subscribeToEvent("GizmoEditModeChanged", (ev) => this.handleGizmoEditModeChanged(ev));
+
         this.subscribeToEvent(this, "WidgetEvent", (data) => this.handleWidgetEvent(data));
+
+        this.subscribeToEvent(EditorEvents.PlayerStarted, (data) => {
+            var skin = <Atomic.UISkinImage> this.playButton.getWidget("skin_image");
+            skin.setSkinBg("StopButton");
+        });
+        this.subscribeToEvent(EditorEvents.PlayerStopped, (data) => {
+            var skin = <Atomic.UISkinImage> this.playButton.getWidget("skin_image");
+            skin.setSkinBg("PlayButton");
+        });
     }
 
     handleGizmoAxisModeChanged(ev: Editor.GizmoAxisModeChangedEvent) {
@@ -91,10 +105,8 @@ class MainToolbar extends Atomic.UIWidget {
                 return true;
 
             } else if (ev.target.id == "maintoolbar_play") {
-
-                EditorUI.getShortcuts().invokePlay();
+                EditorUI.getShortcuts().invokePlayOrStopPlayer();
                 return true;
-
             }
 
         }

+ 21 - 13
Script/AtomicEditor/ui/Shortcuts.ts

@@ -7,6 +7,7 @@
 
 import EditorEvents = require("../editor/EditorEvents");
 import EditorUI = require("./EditorUI");
+import Preferences = require("editor/Preferences")
 
 class Shortcuts extends Atomic.ScriptObject {
 
@@ -21,21 +22,28 @@ class Shortcuts extends Atomic.ScriptObject {
 
     }
 
-    invokePlay() {
-
-        this.sendEvent(EditorEvents.SaveAllResources);
-        Atomic.editorMode.playProject();
-
-    }
-
-    invokePlayDebug() {
-
+    //this should be moved somewhere else...
+    invokePlayOrStopPlayer(debug:boolean = false) {
         this.sendEvent(EditorEvents.SaveAllResources);
-        Atomic.editorMode.playProjectDebug();
-
+        if (Atomic.editorMode.isPlayerEnabled()) {
+            this.sendEvent("IPCPlayerExitRequest");
+        } else {
+            var playerWindow = Preferences.getInstance().playerWindow;
+            if (playerWindow) {
+                if ((playerWindow.monitor + 1) > Atomic.graphics.getMonitorsNumber()) {
+                    //will use default settings if monitor is not available
+                    var args = "--resizable";
+                    Atomic.editorMode.playProject(args, debug);
+                } else {
+                    var args = "--windowposx " + playerWindow.x + " --windowposy " + playerWindow.y + " --windowwidth " + playerWindow.width + " --windowheight " + playerWindow.height + " --resizable";
+                    Atomic.editorMode.playProject(args, debug);
+                }
+            } else {
+                Atomic.editorMode.playProject("", debug);
+            }
+        }
     }
 
-
     invokeFormatCode() {
 
         var editor = EditorUI.getMainFrame().resourceframe.currentResourceEditor;
@@ -162,7 +170,7 @@ class Shortcuts extends Atomic.ScriptObject {
                 this.invokeFormatCode();
             }
             else if (ev.key == Atomic.KEY_P) {
-                this.invokePlay();
+                this.invokePlayOrStopPlayer();
                 //if shift is pressed
             } else if (ev.qualifiers & Atomic.QUAL_SHIFT) {
                 if (ev.key == Atomic.KEY_B) {

+ 2 - 2
Script/AtomicEditor/ui/frames/menus/MainFrameMenu.ts

@@ -54,12 +54,12 @@ class MainFrameMenu extends Atomic.ScriptObject {
         } else if (target.id == "menu edit popup") {
 
             if (refid == "edit play") {
-                EditorUI.getShortcuts().invokePlay();
+                EditorUI.getShortcuts().invokePlayOrStopPlayer();
                 return true;
             }
 
             if (refid == "edit play debug") {
-                EditorUI.getShortcuts().invokePlayDebug();
+                EditorUI.getShortcuts().invokePlayOrStopPlayer(true);
                 return true;
             }
 

+ 4 - 1
Script/Packages/Atomic/Graphics.json

@@ -15,6 +15,9 @@
 		},
 		"Camera" : {
 			"SetOrthoSize" : ["float"]
+		},
+		"Graphics" : {
+			"SetWindowPosition" : ["int", "int"]
 		}
 
 	},
@@ -31,7 +34,7 @@
 		]
 
 	},
-	
+
 	"haxe_decl" : {
 		"Light" : [
 			"function getShadowCascade():Array<Float>;",

+ 12 - 0
Source/Atomic/Graphics/Direct3D11/D3D11Graphics.cpp

@@ -2781,4 +2781,16 @@ void RegisterGraphicsLibrary(Context* context)
     Zone::RegisterObject(context);
 }
 
+// ATOMIC BEGIN
+int Graphics::GetCurrentMonitor()
+{
+    return SDL_GetWindowDisplayIndex((SDL_Window*) this->GetSDLWindow());
+}
+
+int Graphics::GetMonitorsNumber()
+{
+    return SDL_GetNumVideoDisplays();
+}
+// ATOMIC END
+
 }

+ 7 - 0
Source/Atomic/Graphics/Direct3D11/D3D11Graphics.h

@@ -499,6 +499,13 @@ public:
     /// Return maximum number of supported bones for skinning.
     static unsigned GetMaxBones() { return 128; }
 
+    // ATOMIC BEGIN
+    /// Return the current monitor number
+    int GetCurrentMonitor();
+    /// Return the available monitors number
+    int GetMonitorsNumber();
+    // ATOMIC END
+
 private:
     /// Create the application window.
     bool OpenWindow(int width, int height, bool resizable, bool borderless);

+ 12 - 0
Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -2761,4 +2761,16 @@ void RegisterGraphicsLibrary(Context* context)
     Zone::RegisterObject(context);
 }
 
+// ATOMIC BEGIN
+int Graphics::GetCurrentMonitor()
+{
+    return SDL_GetWindowDisplayIndex((SDL_Window*) this->GetSDLWindow());
+}
+
+int Graphics::GetMonitorsNumber()
+{
+    return SDL_GetNumVideoDisplays();
+}
+// ATOMIC END
+
 }

+ 7 - 0
Source/Atomic/Graphics/Direct3D9/D3D9Graphics.h

@@ -493,6 +493,13 @@ public:
     /// Return maximum number of supported bones for skinning.
     static unsigned GetMaxBones() { return 64; }
 
+    // ATOMIC BEGIN
+    /// Return the current monitor number
+    int GetCurrentMonitor();
+    /// Return the available monitors number
+    int GetMonitorsNumber();
+    // ATOMIC END
+
 private:
     /// Set vertex buffer stream frequency.
     void SetStreamFrequency(unsigned index, unsigned frequency);

+ 12 - 0
Source/Atomic/Graphics/OpenGL/OGLGraphics.cpp

@@ -3296,4 +3296,16 @@ void RegisterGraphicsLibrary(Context* context)
     Zone::RegisterObject(context);
 }
 
+// ATOMIC BEGIN
+int Graphics::GetCurrentMonitor()
+{
+    return SDL_GetWindowDisplayIndex((SDL_Window*) this->GetSDLWindow());
+}
+
+int Graphics::GetMonitorsNumber()
+{
+    return SDL_GetNumVideoDisplays();
+}
+// ATOMIC END
+
 }

+ 7 - 0
Source/Atomic/Graphics/OpenGL/OGLGraphics.h

@@ -525,6 +525,13 @@ public:
     /// Return whether is using an OpenGL 3 context.
     static bool GetGL3Support() { return gl3Support; }
 
+    // ATOMIC BEGIN
+    /// Return the current monitor number
+    int GetCurrentMonitor();
+    /// Return the available monitors number
+    int GetMonitorsNumber();
+    // ATOMIC END
+
 private:
     /// Create the application window icon.
     void CreateWindowIcon();

+ 1 - 0
Source/Atomic/UI/UI.cpp

@@ -220,6 +220,7 @@ void UI::Initialize(const String& languageFile)
     SubscribeToEvent(E_KEYUP, HANDLER(UI, HandleKeyUp));
     SubscribeToEvent(E_TEXTINPUT, HANDLER(UI, HandleTextInput));
     SubscribeToEvent(E_UPDATE, HANDLER(UI, HandleUpdate));
+    SubscribeToEvent(E_SCREENMODE, HANDLER(UI, HandleScreenMode));
     SubscribeToEvent(SystemUI::E_CONSOLECLOSED, HANDLER(UI, HandleConsoleClosed));
 
     SubscribeToEvent(E_TOUCHBEGIN, HANDLER(UI, HandleTouchBegin));

+ 16 - 2
Source/AtomicEditor/Application/AEEditorApp.cpp

@@ -92,7 +92,7 @@ void AEEditorApp::Setup()
 
 #ifdef ATOMIC_DEV_BUILD
     engineParameters_["ResourcePrefixPath"] = "";
-    String resourcePaths = env->GetCoreDataDir() + ";" +  env->GetEditorDataDir();
+    String resourcePaths = env->GetCoreDataDir() + ";" + env->GetEditorDataDir();
     // for dev builds, add the compile editor scripts from artifacts
     resourcePaths += ";" + env->GetRootSourceDir() + "Artifacts/Build/Resources/EditorData/";
     engineParameters_["ResourcePaths"] = resourcePaths;
@@ -102,14 +102,28 @@ void AEEditorApp::Setup()
     engineParameters_["ResourcePrefixPath"] = "../Resources";
 
 #else
-	engineParameters_["ResourcePrefixPath"] = filesystem->GetProgramDir() + "Resources";
+    engineParameters_["ResourcePrefixPath"] = filesystem->GetProgramDir() + "Resources";
 #endif
 
     engineParameters_["ResourcePaths"] = "CoreData;EditorData";
 
 #endif // ATOMIC_DEV_BUILD
 
+    String prefsPath = filesystem->GetAppPreferencesDir("AtomicEditor", "Preferences");
+    prefsPath += "prefs.json";
 
+    JSONValue editorWindow;
+
+    if (ReadPreferences(prefsPath, editorWindow, "editorWindow"))
+    {
+        if (editorWindow.IsObject())
+        {
+            engineParameters_["WindowPositionX"] = editorWindow.Get("x").GetUInt();
+            engineParameters_["WindowPositionY"] = editorWindow.Get("y").GetUInt();
+            engineParameters_["WindowWidth"] = editorWindow.Get("width").GetUInt();
+            engineParameters_["WindowHeight"] = editorWindow.Get("height").GetUInt();
+        }
+    }
 }
 
 void AEEditorApp::Stop()

+ 34 - 0
Source/AtomicEditor/Application/AEEditorCommon.cpp

@@ -19,6 +19,8 @@
 #include <ToolCore/ToolSystem.h>
 #include <ToolCore/ToolEnvironment.h>
 
+#include <Atomic/IO/File.h>
+
 #ifdef ATOMIC_DOTNET
 #include <AtomicNET/NETCore/NETHost.h>
 #include <AtomicNET/NETCore/NETCore.h>
@@ -150,4 +152,36 @@ void AEEditorCommon::Stop()
 #endif
 }
 
+
+bool AEEditorCommon::ReadPreferences(String& path, JSONValue& prefs, const String& propertyName)
+{
+    if (!path.EndsWith(".json"))
+        path.Append(".json");
+
+    SharedPtr<File> file(new File(context_, path, FILE_READ));
+
+    SharedPtr<JSONFile> jsonFile(new JSONFile(context_));
+
+    if (!jsonFile->BeginLoad(*file))
+        return false;
+
+    JSONValue root = jsonFile->GetRoot();
+
+    if (propertyName.Length() > 0)
+    {
+        if (root.Contains(propertyName))
+        {
+            prefs = root.Get(propertyName);
+        }
+    }
+    else
+    {
+        prefs = root;
+    }
+
+    file->Close();
+
+    return true;
+}
+
 }

+ 3 - 1
Source/AtomicEditor/Application/AEEditorCommon.h

@@ -8,6 +8,7 @@
 #pragma once
 
 #include <Atomic/Engine/Application.h>
+#include <Atomic/Resource/JSONFile.h>
 
 using namespace Atomic;
 
@@ -36,11 +37,12 @@ public:
 
 protected:
 
+    bool ReadPreferences(String& path, JSONValue& prefs, const String& propertyName = "");
+    
     SharedPtr<JSVM> vm_;
 
 private:
 
-
 };
 
 }

+ 31 - 0
Source/AtomicEditor/Application/AEPlayerApp.cpp

@@ -31,6 +31,8 @@
 #include "../PlayerMode/AEPlayerMode.h"
 #include <AtomicPlayer/Player.h>
 
+#include "../PlayerMode/AEPlayerEvents.h"
+
 #include "AEPlayerApp.h"
 
 #include <Atomic/DebugNew.h>
@@ -57,6 +59,8 @@ void AEPlayerApplication::Setup()
 {
     AEEditorCommon::Setup();
 
+    engine_->SetAutoExit(false);
+
     FileSystem* filesystem = GetSubsystem<FileSystem>();
 
     engineParameters_["WindowTitle"] = "AtomicPlayer";
@@ -150,6 +154,26 @@ void AEPlayerApplication::Setup()
 #endif
 
             }
+            else if (argument == "--windowposx" && value.Length()) 
+            {
+                engineParameters_["WindowPositionX"] = atoi(value.CString());
+            }
+            else if (argument == "--windowposy" && value.Length())
+            {
+                engineParameters_["WindowPositionY"] = atoi(value.CString());
+            }
+            else if (argument == "--windowwidth" && value.Length())
+            {
+                engineParameters_["WindowWidth"] = atoi(value.CString());
+            }
+            else if (argument == "--windowheight" && value.Length())
+            {
+                engineParameters_["WindowHeight"] = atoi(value.CString());
+            }
+            else if (argument == "--resizable") 
+            {
+                engineParameters_["WindowResizable"] = true;
+            }
         }
     }
 
@@ -204,9 +228,16 @@ void AEPlayerApplication::Start()
         }
     }
 
+    SubscribeToEvent(E_PLAYERQUIT, HANDLER(AEPlayerApplication, HandleQuit));
+
     return;
 }
 
+void AEPlayerApplication::HandleQuit(StringHash eventType, VariantMap& eventData)
+{
+    engine_->Exit();
+}
+
 void AEPlayerApplication::Stop()
 {
     AEEditorCommon::Stop();

+ 2 - 0
Source/AtomicEditor/Application/AEPlayerApp.h

@@ -41,6 +41,8 @@ private:
 
     void HandleLogMessage(StringHash eventType, VariantMap& eventData);
 
+    void HandleQuit(StringHash eventType, VariantMap& eventData);
+
     bool debugPlayer_;
 
 };

+ 2 - 2
Source/AtomicEditor/EditorMode/AEEditorEvents.h

@@ -63,13 +63,13 @@ EVENT(E_EDITORRESOURCEEDITORCHANGED, EditorResourceEditorChanged)
 
 
 // emitted once play has started
-EVENT(E_EDITORPLAYSTARTED, EditorPlayStarted)
+EVENT(E_EDITORPLAYERSTARTED, EditorPlayerStarted)
 {
     PARAM(P_MODE, Mode);    // uint (AEPlayerMode)
 }
 
 // emitted once play has stopped
-EVENT(E_EDITORPLAYSTOPPED, EditorPlayStopped)
+EVENT(E_EDITORPLAYERSTOPPED, EditorPlayerStopped)
 {
 
 }

+ 26 - 5
Source/AtomicEditor/EditorMode/AEEditorMode.cpp

@@ -11,6 +11,8 @@
 #include <Atomic/IPC/IPCEvents.h>
 #include <Atomic/IPC/IPCBroker.h>
 
+#include <Atomic/Input/InputEvents.h>
+
 #include <ToolCore/ToolEnvironment.h>
 #include <ToolCore/ToolSystem.h>
 #include <ToolCore/License/LicenseSystem.h>
@@ -20,6 +22,8 @@
 
 #include <Atomic/UI/SystemUI/DebugHud.h>
 
+#include "../PlayerMode/AEPlayerEvents.h"
+
 #include "AEEditorMode.h"
 
 using namespace ToolCore;
@@ -31,6 +35,7 @@ EditorMode::EditorMode(Context* context) :
     Object(context)
 {
     SubscribeToEvent(E_IPCWORKERSTART, HANDLER(EditorMode, HandleIPCWorkerStarted));
+    SubscribeToEvent(E_IPCPLAYEREXITREQUEST, HANDLER(EditorMode, HandleIPCPlayerExitRequest));
 }
 
 EditorMode::~EditorMode()
@@ -55,7 +60,9 @@ void EditorMode::HandleIPCWorkerStarted(StringHash eventType, VariantMap& eventD
 
     playerBroker_->PostMessage(E_IPCINITIALIZE, startupData);
 
-    SendEvent("EditorPlayerStarted");
+    SendEvent(E_EDITORPLAYERSTARTED);
+
+    playerEnabled_ = true;
 
 }
 
@@ -63,8 +70,12 @@ void EditorMode::HandleIPCWorkerExit(StringHash eventType, VariantMap& eventData
 {
     //SendEvent(E_EDITORPLAYSTOP);
 
-    if ( eventData[IPCWorkerExit::P_BROKER] == playerBroker_)
+    if (eventData[IPCWorkerExit::P_BROKER] == playerBroker_) 
+    {
         playerBroker_ = 0;
+        playerEnabled_ = false;
+        SendEvent(E_EDITORPLAYERSTOPPED);
+    }
 }
 
 void EditorMode::HandleIPCWorkerLog(StringHash eventType, VariantMap& eventData)
@@ -87,7 +98,7 @@ void EditorMode::HandleIPCJSError(StringHash eventType, VariantMap& eventData)
 
 }
 
-bool EditorMode::PlayProject(bool debug)
+bool EditorMode::PlayProject(String addArgs, bool debug)
 {
     ToolEnvironment* env = GetSubsystem<ToolEnvironment>();
     ToolSystem* tsystem = GetSubsystem<ToolSystem>();
@@ -120,6 +131,9 @@ bool EditorMode::PlayProject(bool debug)
     if (debug)
         vargs.Insert(0, "--debug");
 
+    if (addArgs.Length() > 0)
+        vargs.Insert(0, addArgs.Split(' '));
+
     String dump;
     dump.Join(vargs, " ");
     LOGINFOF("Launching Broker %s %s", editorBinary.CString(), dump.CString());
@@ -138,9 +152,16 @@ bool EditorMode::PlayProject(bool debug)
 
 }
 
-bool EditorMode::PlayProjectDebug()
+void EditorMode::HandleIPCPlayerExitRequest(StringHash eventType, VariantMap& eventData)
+{
+    if (!playerBroker_) return;
+    VariantMap noEventData;
+    playerBroker_->PostMessage(E_EXITREQUESTED, noEventData);
+}
+
+bool EditorMode::IsPlayerEnabled()
 {
-    return PlayProject(true);
+    return playerEnabled_;
 }
 
 }

+ 5 - 2
Source/AtomicEditor/EditorMode/AEEditorMode.h

@@ -32,8 +32,8 @@ public:
     /// Destruct.
     virtual ~EditorMode();
 
-    bool PlayProject(bool debug = false);
-    bool PlayProjectDebug();
+    bool PlayProject(String addArgs = "", bool debug = false);
+    bool IsPlayerEnabled();
 
 private:
 
@@ -41,9 +41,12 @@ private:
     void HandleIPCJSError(StringHash eventType, VariantMap& eventData);
     void HandleIPCWorkerLog(StringHash eventType, VariantMap& eventData);
     void HandleIPCWorkerExit(StringHash eventType, VariantMap& eventData);
+    void HandleIPCPlayerExitRequest(StringHash eventType, VariantMap& eventData);
 
     SharedPtr<IPCBroker> playerBroker_;
 
+    bool playerEnabled_ = false;
+
 };
 
 }

+ 2 - 2
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditor3D.cpp

@@ -111,8 +111,8 @@ SceneEditor3D ::SceneEditor3D(Context* context, const String &fullpath, UITabCon
 
     SubscribeToEvent(scene_, E_SCENEEDITNODECREATED, HANDLER(SceneEditor3D, HandleSceneEditNodeCreated));
 
-    SubscribeToEvent(E_EDITORPLAYSTARTED, HANDLER(SceneEditor3D, HandlePlayStarted));
-    SubscribeToEvent(E_EDITORPLAYSTOPPED, HANDLER(SceneEditor3D, HandlePlayStopped));
+    SubscribeToEvent(E_EDITORPLAYERSTARTED, HANDLER(SceneEditor3D, HandlePlayStarted));
+    SubscribeToEvent(E_EDITORPLAYERSTOPPED, HANDLER(SceneEditor3D, HandlePlayStopped));
     SubscribeToEvent(scene_, E_SCENEEDITSCENEMODIFIED, HANDLER(SceneEditor3D, HandleSceneEditSceneModified));
 
 }

+ 36 - 0
Source/AtomicEditor/PlayerMode/AEPlayerEvents.h

@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+
+using namespace Atomic;
+
+namespace AtomicEditor
+{
+
+EVENT(E_IPCPLAYEREXITREQUEST, IPCPlayerExitRequest)
+{
+
+}
+
+EVENT(E_IPCPLAYERWINDOWCHANGED, IPCPlayerWindowChanged)
+{
+    PARAM(P_POSX, PosX);
+    PARAM(P_POSY, PosY);
+    PARAM(P_WIDTH, Width);
+    PARAM(P_HEIGHT, Height);
+    PARAM(P_MONITOR, Monitor);
+}
+
+EVENT(E_PLAYERQUIT, PlayerQuit)
+{
+
+}
+
+}

+ 17 - 0
Source/AtomicEditor/PlayerMode/AEPlayerMode.cpp

@@ -10,6 +10,7 @@
 #include <Atomic/Input/InputEvents.h>
 #include <Atomic/Core/ProcessUtils.h>
 #include <Atomic/Graphics/GraphicsEvents.h>
+#include <Atomic/Graphics/Graphics.h>
 #include <Atomic/Graphics/Camera.h>
 #include <Atomic/UI/SystemUI/DebugHud.h>
 #include <Atomic/UI/SystemUI/SystemUIEvents.h>
@@ -21,6 +22,8 @@
 #include <AtomicJS/Javascript/JSEvents.h>
 #include <AtomicJS/Javascript/JSIPCEvents.h>
 
+#include "AEPlayerEvents.h"
+
 #include "AEPlayerMode.h"
 
 #ifdef ATOMIC_PLATFORM_WINDOWS
@@ -43,6 +46,7 @@ PlayerMode::PlayerMode(Context* context) :
 
     SubscribeToEvent(E_LOGMESSAGE, HANDLER(PlayerMode, HandleLogMessage));
     SubscribeToEvent(E_JSERROR, HANDLER(PlayerMode, HandleJSError));
+    SubscribeToEvent(E_EXITREQUESTED, HANDLER(PlayerMode, HandleExitRequest));
 
     // BEGIN LICENSE MANAGEMENT
     SubscribeToEvent(E_BEGINVIEWRENDER, HANDLER(PlayerMode, HandleViewRender));
@@ -235,5 +239,18 @@ void PlayerMode::HandleViewRender(StringHash eventType, VariantMap& eventData)
 
 }
 
+void PlayerMode::HandleExitRequest(StringHash eventType, VariantMap& eventData)
+{
+    Graphics* graphics = GetSubsystem<Graphics>();
+    using namespace IPCPlayerWindowChanged;
+    VariantMap data;
+    data[P_POSX] = graphics->GetWindowPosition().x_;
+    data[P_POSY] = graphics->GetWindowPosition().y_;
+    data[P_WIDTH] = graphics->GetWidth();
+    data[P_HEIGHT] = graphics->GetHeight();
+    data[P_MONITOR] = graphics->GetCurrentMonitor();
+    ipc_->SendEventToBroker(E_IPCPLAYERWINDOWCHANGED, data);
+    SendEvent(E_PLAYERQUIT);
+}
 
 }

+ 1 - 0
Source/AtomicEditor/PlayerMode/AEPlayerMode.h

@@ -41,6 +41,7 @@ private:
     void HandleLogMessage(StringHash eventType, VariantMap& eventData);
     void HandleIPCInitialize(StringHash eventType, VariantMap& eventData);
     void HandleViewRender(StringHash eventType, VariantMap& eventData);
+    void HandleExitRequest(StringHash eventType, VariantMap& eventData);
 
 // BEGIN LICENSE MANAGEMENT
     void HandleMessageAck(StringHash eventType, VariantMap& eventData);