Browse Source

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

Remember player positioning when run from editor and Prevent multiple Atomic Player windows
JoshEngebretson 10 years ago
parent
commit
860ffb836c
29 changed files with 326 additions and 42 deletions
  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
 	PlayButton
 		bitmap play.png
 		bitmap play.png
 
 
+	StopButton
+		bitmap stop.png
+
 	PowerOffButton
 	PowerOffButton
 		bitmap power_off.png
 		bitmap power_off.png
 
 
@@ -171,7 +174,7 @@ elements
 	InspectorVectorAttrName
 	InspectorVectorAttrName
 		text-color #aaaaaa
 		text-color #aaaaaa
 		min-width 140
 		min-width 140
-		max-width 140		
+		max-width 140
 
 
 	InspectorTextAttrName
 	InspectorTextAttrName
 		padding 4
 		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
 definitions
-	menubutton		
+	menubutton
 		lp: height: 28, width: 28
 		lp: height: 28, width: 28
 		skin TBButton.uniformflat
 		skin TBButton.uniformflat
 TBLayout: distribution: gravity, spacing: 4
 TBLayout: distribution: gravity, spacing: 4
-	TBButton 
+	TBButton
 		@include definitions>menubutton
 		@include definitions>menubutton
-		TBSkinImage: skin: PlayButton
+		TBSkinImage: skin: PlayButton, id: skin_image
 		id maintoolbar_play
 		id maintoolbar_play
 	TBButton: toggle-mode: 1
 	TBButton: toggle-mode: 1
 		@include definitions>menubutton
 		@include definitions>menubutton

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

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

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

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

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

@@ -68,7 +68,14 @@ class Preferences {
         }
         }
         //Read file
         //Read file
         jsonFile = new Atomic.File(filePath, Atomic.FILE_READ);
         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) {
             if (!prefs.recentProjects) prefs.recentProjects = [""];
             if (!prefs.recentProjects) prefs.recentProjects = [""];
             this._prefs = prefs;
             this._prefs = prefs;
@@ -87,10 +94,26 @@ class Preferences {
             width = graphics.getWidth();
             width = graphics.getWidth();
             height = graphics.getHeight();
             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));
         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] {
     get recentProjects(): [string] {
         return this._prefs.recentProjects;
         return this._prefs.recentProjects;
     }
     }
@@ -100,9 +123,18 @@ class Preferences {
     }
     }
 }
 }
 
 
+interface WindowData {
+    x: number;
+    y: number;
+    width: number;
+    height: number;
+    monitor: number;
+}
+
 class PreferencesFormat {
 class PreferencesFormat {
     recentProjects: [string];
     recentProjects: [string];
-    window: { x: number, y: number, width: number, height: number };
+    editorWindow: WindowData;
+    playerWindow: WindowData;
 }
 }
 
 
 export = Preferences;
 export = Preferences;

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

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

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

@@ -7,6 +7,7 @@
 
 
 import EditorEvents = require("../editor/EditorEvents");
 import EditorEvents = require("../editor/EditorEvents");
 import EditorUI = require("./EditorUI");
 import EditorUI = require("./EditorUI");
+import Preferences = require("editor/Preferences")
 
 
 class Shortcuts extends Atomic.ScriptObject {
 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);
         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() {
     invokeFormatCode() {
 
 
         var editor = EditorUI.getMainFrame().resourceframe.currentResourceEditor;
         var editor = EditorUI.getMainFrame().resourceframe.currentResourceEditor;
@@ -162,7 +170,7 @@ class Shortcuts extends Atomic.ScriptObject {
                 this.invokeFormatCode();
                 this.invokeFormatCode();
             }
             }
             else if (ev.key == Atomic.KEY_P) {
             else if (ev.key == Atomic.KEY_P) {
-                this.invokePlay();
+                this.invokePlayOrStopPlayer();
                 //if shift is pressed
                 //if shift is pressed
             } else if (ev.qualifiers & Atomic.QUAL_SHIFT) {
             } else if (ev.qualifiers & Atomic.QUAL_SHIFT) {
                 if (ev.key == Atomic.KEY_B) {
                 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") {
         } else if (target.id == "menu edit popup") {
 
 
             if (refid == "edit play") {
             if (refid == "edit play") {
-                EditorUI.getShortcuts().invokePlay();
+                EditorUI.getShortcuts().invokePlayOrStopPlayer();
                 return true;
                 return true;
             }
             }
 
 
             if (refid == "edit play debug") {
             if (refid == "edit play debug") {
-                EditorUI.getShortcuts().invokePlayDebug();
+                EditorUI.getShortcuts().invokePlayOrStopPlayer(true);
                 return true;
                 return true;
             }
             }
 
 

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

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

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

@@ -2781,4 +2781,16 @@ void RegisterGraphicsLibrary(Context* context)
     Zone::RegisterObject(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.
     /// Return maximum number of supported bones for skinning.
     static unsigned GetMaxBones() { return 128; }
     static unsigned GetMaxBones() { return 128; }
 
 
+    // ATOMIC BEGIN
+    /// Return the current monitor number
+    int GetCurrentMonitor();
+    /// Return the available monitors number
+    int GetMonitorsNumber();
+    // ATOMIC END
+
 private:
 private:
     /// Create the application window.
     /// Create the application window.
     bool OpenWindow(int width, int height, bool resizable, bool borderless);
     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);
     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.
     /// Return maximum number of supported bones for skinning.
     static unsigned GetMaxBones() { return 64; }
     static unsigned GetMaxBones() { return 64; }
 
 
+    // ATOMIC BEGIN
+    /// Return the current monitor number
+    int GetCurrentMonitor();
+    /// Return the available monitors number
+    int GetMonitorsNumber();
+    // ATOMIC END
+
 private:
 private:
     /// Set vertex buffer stream frequency.
     /// Set vertex buffer stream frequency.
     void SetStreamFrequency(unsigned index, unsigned 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);
     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.
     /// Return whether is using an OpenGL 3 context.
     static bool GetGL3Support() { return gl3Support; }
     static bool GetGL3Support() { return gl3Support; }
 
 
+    // ATOMIC BEGIN
+    /// Return the current monitor number
+    int GetCurrentMonitor();
+    /// Return the available monitors number
+    int GetMonitorsNumber();
+    // ATOMIC END
+
 private:
 private:
     /// Create the application window icon.
     /// Create the application window icon.
     void CreateWindowIcon();
     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_KEYUP, HANDLER(UI, HandleKeyUp));
     SubscribeToEvent(E_TEXTINPUT, HANDLER(UI, HandleTextInput));
     SubscribeToEvent(E_TEXTINPUT, HANDLER(UI, HandleTextInput));
     SubscribeToEvent(E_UPDATE, HANDLER(UI, HandleUpdate));
     SubscribeToEvent(E_UPDATE, HANDLER(UI, HandleUpdate));
+    SubscribeToEvent(E_SCREENMODE, HANDLER(UI, HandleScreenMode));
     SubscribeToEvent(SystemUI::E_CONSOLECLOSED, HANDLER(UI, HandleConsoleClosed));
     SubscribeToEvent(SystemUI::E_CONSOLECLOSED, HANDLER(UI, HandleConsoleClosed));
 
 
     SubscribeToEvent(E_TOUCHBEGIN, HANDLER(UI, HandleTouchBegin));
     SubscribeToEvent(E_TOUCHBEGIN, HANDLER(UI, HandleTouchBegin));

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

@@ -92,7 +92,7 @@ void AEEditorApp::Setup()
 
 
 #ifdef ATOMIC_DEV_BUILD
 #ifdef ATOMIC_DEV_BUILD
     engineParameters_["ResourcePrefixPath"] = "";
     engineParameters_["ResourcePrefixPath"] = "";
-    String resourcePaths = env->GetCoreDataDir() + ";" +  env->GetEditorDataDir();
+    String resourcePaths = env->GetCoreDataDir() + ";" + env->GetEditorDataDir();
     // for dev builds, add the compile editor scripts from artifacts
     // for dev builds, add the compile editor scripts from artifacts
     resourcePaths += ";" + env->GetRootSourceDir() + "Artifacts/Build/Resources/EditorData/";
     resourcePaths += ";" + env->GetRootSourceDir() + "Artifacts/Build/Resources/EditorData/";
     engineParameters_["ResourcePaths"] = resourcePaths;
     engineParameters_["ResourcePaths"] = resourcePaths;
@@ -102,14 +102,28 @@ void AEEditorApp::Setup()
     engineParameters_["ResourcePrefixPath"] = "../Resources";
     engineParameters_["ResourcePrefixPath"] = "../Resources";
 
 
 #else
 #else
-	engineParameters_["ResourcePrefixPath"] = filesystem->GetProgramDir() + "Resources";
+    engineParameters_["ResourcePrefixPath"] = filesystem->GetProgramDir() + "Resources";
 #endif
 #endif
 
 
     engineParameters_["ResourcePaths"] = "CoreData;EditorData";
     engineParameters_["ResourcePaths"] = "CoreData;EditorData";
 
 
 #endif // ATOMIC_DEV_BUILD
 #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()
 void AEEditorApp::Stop()

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

@@ -19,6 +19,8 @@
 #include <ToolCore/ToolSystem.h>
 #include <ToolCore/ToolSystem.h>
 #include <ToolCore/ToolEnvironment.h>
 #include <ToolCore/ToolEnvironment.h>
 
 
+#include <Atomic/IO/File.h>
+
 #ifdef ATOMIC_DOTNET
 #ifdef ATOMIC_DOTNET
 #include <AtomicNET/NETCore/NETHost.h>
 #include <AtomicNET/NETCore/NETHost.h>
 #include <AtomicNET/NETCore/NETCore.h>
 #include <AtomicNET/NETCore/NETCore.h>
@@ -150,4 +152,36 @@ void AEEditorCommon::Stop()
 #endif
 #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
 #pragma once
 
 
 #include <Atomic/Engine/Application.h>
 #include <Atomic/Engine/Application.h>
+#include <Atomic/Resource/JSONFile.h>
 
 
 using namespace Atomic;
 using namespace Atomic;
 
 
@@ -36,11 +37,12 @@ public:
 
 
 protected:
 protected:
 
 
+    bool ReadPreferences(String& path, JSONValue& prefs, const String& propertyName = "");
+    
     SharedPtr<JSVM> vm_;
     SharedPtr<JSVM> vm_;
 
 
 private:
 private:
 
 
-
 };
 };
 
 
 }
 }

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

@@ -31,6 +31,8 @@
 #include "../PlayerMode/AEPlayerMode.h"
 #include "../PlayerMode/AEPlayerMode.h"
 #include <AtomicPlayer/Player.h>
 #include <AtomicPlayer/Player.h>
 
 
+#include "../PlayerMode/AEPlayerEvents.h"
+
 #include "AEPlayerApp.h"
 #include "AEPlayerApp.h"
 
 
 #include <Atomic/DebugNew.h>
 #include <Atomic/DebugNew.h>
@@ -57,6 +59,8 @@ void AEPlayerApplication::Setup()
 {
 {
     AEEditorCommon::Setup();
     AEEditorCommon::Setup();
 
 
+    engine_->SetAutoExit(false);
+
     FileSystem* filesystem = GetSubsystem<FileSystem>();
     FileSystem* filesystem = GetSubsystem<FileSystem>();
 
 
     engineParameters_["WindowTitle"] = "AtomicPlayer";
     engineParameters_["WindowTitle"] = "AtomicPlayer";
@@ -150,6 +154,26 @@ void AEPlayerApplication::Setup()
 #endif
 #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;
     return;
 }
 }
 
 
+void AEPlayerApplication::HandleQuit(StringHash eventType, VariantMap& eventData)
+{
+    engine_->Exit();
+}
+
 void AEPlayerApplication::Stop()
 void AEPlayerApplication::Stop()
 {
 {
     AEEditorCommon::Stop();
     AEEditorCommon::Stop();

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

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

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

@@ -63,13 +63,13 @@ EVENT(E_EDITORRESOURCEEDITORCHANGED, EditorResourceEditorChanged)
 
 
 
 
 // emitted once play has started
 // emitted once play has started
-EVENT(E_EDITORPLAYSTARTED, EditorPlayStarted)
+EVENT(E_EDITORPLAYERSTARTED, EditorPlayerStarted)
 {
 {
     PARAM(P_MODE, Mode);    // uint (AEPlayerMode)
     PARAM(P_MODE, Mode);    // uint (AEPlayerMode)
 }
 }
 
 
 // emitted once play has stopped
 // 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/IPCEvents.h>
 #include <Atomic/IPC/IPCBroker.h>
 #include <Atomic/IPC/IPCBroker.h>
 
 
+#include <Atomic/Input/InputEvents.h>
+
 #include <ToolCore/ToolEnvironment.h>
 #include <ToolCore/ToolEnvironment.h>
 #include <ToolCore/ToolSystem.h>
 #include <ToolCore/ToolSystem.h>
 #include <ToolCore/License/LicenseSystem.h>
 #include <ToolCore/License/LicenseSystem.h>
@@ -20,6 +22,8 @@
 
 
 #include <Atomic/UI/SystemUI/DebugHud.h>
 #include <Atomic/UI/SystemUI/DebugHud.h>
 
 
+#include "../PlayerMode/AEPlayerEvents.h"
+
 #include "AEEditorMode.h"
 #include "AEEditorMode.h"
 
 
 using namespace ToolCore;
 using namespace ToolCore;
@@ -31,6 +35,7 @@ EditorMode::EditorMode(Context* context) :
     Object(context)
     Object(context)
 {
 {
     SubscribeToEvent(E_IPCWORKERSTART, HANDLER(EditorMode, HandleIPCWorkerStarted));
     SubscribeToEvent(E_IPCWORKERSTART, HANDLER(EditorMode, HandleIPCWorkerStarted));
+    SubscribeToEvent(E_IPCPLAYEREXITREQUEST, HANDLER(EditorMode, HandleIPCPlayerExitRequest));
 }
 }
 
 
 EditorMode::~EditorMode()
 EditorMode::~EditorMode()
@@ -55,7 +60,9 @@ void EditorMode::HandleIPCWorkerStarted(StringHash eventType, VariantMap& eventD
 
 
     playerBroker_->PostMessage(E_IPCINITIALIZE, startupData);
     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);
     //SendEvent(E_EDITORPLAYSTOP);
 
 
-    if ( eventData[IPCWorkerExit::P_BROKER] == playerBroker_)
+    if (eventData[IPCWorkerExit::P_BROKER] == playerBroker_) 
+    {
         playerBroker_ = 0;
         playerBroker_ = 0;
+        playerEnabled_ = false;
+        SendEvent(E_EDITORPLAYERSTOPPED);
+    }
 }
 }
 
 
 void EditorMode::HandleIPCWorkerLog(StringHash eventType, VariantMap& eventData)
 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>();
     ToolEnvironment* env = GetSubsystem<ToolEnvironment>();
     ToolSystem* tsystem = GetSubsystem<ToolSystem>();
     ToolSystem* tsystem = GetSubsystem<ToolSystem>();
@@ -120,6 +131,9 @@ bool EditorMode::PlayProject(bool debug)
     if (debug)
     if (debug)
         vargs.Insert(0, "--debug");
         vargs.Insert(0, "--debug");
 
 
+    if (addArgs.Length() > 0)
+        vargs.Insert(0, addArgs.Split(' '));
+
     String dump;
     String dump;
     dump.Join(vargs, " ");
     dump.Join(vargs, " ");
     LOGINFOF("Launching Broker %s %s", editorBinary.CString(), dump.CString());
     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.
     /// Destruct.
     virtual ~EditorMode();
     virtual ~EditorMode();
 
 
-    bool PlayProject(bool debug = false);
-    bool PlayProjectDebug();
+    bool PlayProject(String addArgs = "", bool debug = false);
+    bool IsPlayerEnabled();
 
 
 private:
 private:
 
 
@@ -41,9 +41,12 @@ private:
     void HandleIPCJSError(StringHash eventType, VariantMap& eventData);
     void HandleIPCJSError(StringHash eventType, VariantMap& eventData);
     void HandleIPCWorkerLog(StringHash eventType, VariantMap& eventData);
     void HandleIPCWorkerLog(StringHash eventType, VariantMap& eventData);
     void HandleIPCWorkerExit(StringHash eventType, VariantMap& eventData);
     void HandleIPCWorkerExit(StringHash eventType, VariantMap& eventData);
+    void HandleIPCPlayerExitRequest(StringHash eventType, VariantMap& eventData);
 
 
     SharedPtr<IPCBroker> playerBroker_;
     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(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));
     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/Input/InputEvents.h>
 #include <Atomic/Core/ProcessUtils.h>
 #include <Atomic/Core/ProcessUtils.h>
 #include <Atomic/Graphics/GraphicsEvents.h>
 #include <Atomic/Graphics/GraphicsEvents.h>
+#include <Atomic/Graphics/Graphics.h>
 #include <Atomic/Graphics/Camera.h>
 #include <Atomic/Graphics/Camera.h>
 #include <Atomic/UI/SystemUI/DebugHud.h>
 #include <Atomic/UI/SystemUI/DebugHud.h>
 #include <Atomic/UI/SystemUI/SystemUIEvents.h>
 #include <Atomic/UI/SystemUI/SystemUIEvents.h>
@@ -21,6 +22,8 @@
 #include <AtomicJS/Javascript/JSEvents.h>
 #include <AtomicJS/Javascript/JSEvents.h>
 #include <AtomicJS/Javascript/JSIPCEvents.h>
 #include <AtomicJS/Javascript/JSIPCEvents.h>
 
 
+#include "AEPlayerEvents.h"
+
 #include "AEPlayerMode.h"
 #include "AEPlayerMode.h"
 
 
 #ifdef ATOMIC_PLATFORM_WINDOWS
 #ifdef ATOMIC_PLATFORM_WINDOWS
@@ -43,6 +46,7 @@ PlayerMode::PlayerMode(Context* context) :
 
 
     SubscribeToEvent(E_LOGMESSAGE, HANDLER(PlayerMode, HandleLogMessage));
     SubscribeToEvent(E_LOGMESSAGE, HANDLER(PlayerMode, HandleLogMessage));
     SubscribeToEvent(E_JSERROR, HANDLER(PlayerMode, HandleJSError));
     SubscribeToEvent(E_JSERROR, HANDLER(PlayerMode, HandleJSError));
+    SubscribeToEvent(E_EXITREQUESTED, HANDLER(PlayerMode, HandleExitRequest));
 
 
     // BEGIN LICENSE MANAGEMENT
     // BEGIN LICENSE MANAGEMENT
     SubscribeToEvent(E_BEGINVIEWRENDER, HANDLER(PlayerMode, HandleViewRender));
     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 HandleLogMessage(StringHash eventType, VariantMap& eventData);
     void HandleIPCInitialize(StringHash eventType, VariantMap& eventData);
     void HandleIPCInitialize(StringHash eventType, VariantMap& eventData);
     void HandleViewRender(StringHash eventType, VariantMap& eventData);
     void HandleViewRender(StringHash eventType, VariantMap& eventData);
+    void HandleExitRequest(StringHash eventType, VariantMap& eventData);
 
 
 // BEGIN LICENSE MANAGEMENT
 // BEGIN LICENSE MANAGEMENT
     void HandleMessageAck(StringHash eventType, VariantMap& eventData);
     void HandleMessageAck(StringHash eventType, VariantMap& eventData);