// // 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 // #include #include #include #include // Move me to Engine #include #include #include #include #include #include #ifdef ATOMIC_DOTNET #include #include #include #endif #include "../Components/EditorComponents.h" #include "AEEditorCommon.h" namespace Atomic { void jsapi_init_atomicnet(JSVM* vm); } using namespace ToolCore; namespace ToolCore { extern void jsapi_init_toolcore(JSVM* vm); } namespace AtomicEditor { AEEditorCommon::AEEditorCommon(Context* context) : Application(context) { } void AEEditorCommon::Start() { ValidateWindow(); Input* input = GetSubsystem(); input->SetMouseVisible(true); Javascript* javascript = GetSubsystem(); vm_ = javascript->InstantiateVM("MainVM"); vm_->InitJSContext(); jsapi_init_toolcore(vm_); #ifdef ATOMIC_DOTNET jsapi_init_atomicnet(vm_); #endif } void AEEditorCommon::Setup() { #ifdef ATOMIC_3D RegisterEnvironmentLibrary(context_); #endif RegisterEditorComponentLibrary(context_); #ifdef ATOMIC_DOTNET RegisterNETScriptLibrary(context_); #endif // Register IPC system context_->RegisterSubsystem(new IPC(context_)); context_->RegisterSubsystem(new ScriptSystem(context_)); // Instantiate and register the Javascript subsystem Javascript* javascript = new Javascript(context_); context_->RegisterSubsystem(javascript); ToolEnvironment* env = new ToolEnvironment(context_); context_->RegisterSubsystem(env); #ifdef ATOMIC_DEV_BUILD if (!env->InitFromJSON()) { ErrorExit(ToString("Unable to initialize tool environment from %s", env->GetDevConfigFilename().CString())); return; } #else env->InitFromPackage(); #endif #ifdef ATOMIC_DOTNET // Instantiate and register the AtomicNET subsystem SharedPtr netCore (new NETCore(context_)); context_->RegisterSubsystem(netCore); String netCoreErrorMsg; NETHost::SetCoreCLRFilesAbsPath(env->GetNETCoreCLRAbsPath()); NETHost::SetCoreCLRTPAPaths(env->GetNETTPAPaths()); NETHost::SetCoreCLRAssemblyLoadPaths(env->GetNETAssemblyLoadPaths()); if (!netCore->Initialize(netCoreErrorMsg)) { LOGERRORF("NetCore: Unable to initialize! %s", netCoreErrorMsg.CString()); context_->RemoveSubsystem(NETCore::GetTypeStatic()); } else { } #endif ToolSystem* system = new ToolSystem(context_); context_->RegisterSubsystem(system); } void AEEditorCommon::Stop() { context_->RemoveSubsystem(); vm_ = 0; context_->RemoveSubsystem(); // make sure JSVM is really down and no outstanding refs // as if not, will hold on engine subsystems, which is bad assert(!JSVM::GetJSVM(0)); #ifdef ATOMIC_DOTNET NETCore* netCore = GetSubsystem(); if (netCore) { netCore->Shutdown(); context_->RemoveSubsystem(); } #endif } bool AEEditorCommon::CreateDefaultPreferences(String& path, JSONValue& prefs) { // Note there is some duplication here with the editor's // TypeScript preference code, this is due to the preferences for // the editor window needing to be available at window creation time // It could be better to split this all out to a native, scriptable // preferences object LOGINFOF("Creating default Atomic Editor preferences: %s", path.CString()); SharedPtr jsonFile(new JSONFile(context_)); JSONValue& root = jsonFile->GetRoot(); root.Clear(); root["recentProjects"] = JSONArray(); JSONValue editorWindow; GetDefaultWindowPreferences(editorWindow, true); JSONValue playerWindow; GetDefaultWindowPreferences(playerWindow, false); root["editorWindow"] = editorWindow; root["playerWindow"] = playerWindow; prefs = root; SavePreferences(prefs); return true; } bool AEEditorCommon::ReadPreferences() { FileSystem* fileSystem = GetSubsystem(); String path = GetPreferencesPath(); JSONValue prefs; LoadPreferences(prefs); if (!prefs.IsObject() || !prefs["editorWindow"].IsObject()) { if (!CreateDefaultPreferences(path, prefs)) return false; } JSONValue& editorWindow = prefs["editorWindow"]; engineParameters_["WindowPositionX"] = editorWindow["x"].GetUInt(); engineParameters_["WindowPositionY"] = editorWindow["y"].GetUInt(); engineParameters_["WindowWidth"] = editorWindow["width"].GetUInt(); engineParameters_["WindowHeight"] = editorWindow["height"].GetUInt(); engineParameters_["WindowMaximized"] = editorWindow["maximized"].GetBool(); return true; } void AEEditorCommon::ValidateWindow() { Graphics* graphics = GetSubsystem(); IntVector2 windowPosition = graphics->GetWindowPosition(); int monitors = graphics->GetNumMonitors(); IntVector2 maxResolution; for (int i = 0; i < monitors; i++) { IntVector2 monitorResolution = graphics->GetMonitorResolution(i); maxResolution += monitorResolution; } if (windowPosition.x_ >= maxResolution.x_ || windowPosition.y_ >= maxResolution.y_ ) { JSONValue prefs; if (!LoadPreferences(prefs)) return; bool editor = context_->GetEditorContext(); JSONValue window; GetDefaultWindowPreferences(window, editor); prefs[editor ? "editorWindow" : "playerWindow"] = window; //Setting the mode to 0 width/height will use engine defaults for window size and layout graphics->SetMode(0, 0); graphics->CenterWindow(); if (editor) { graphics->Maximize(); } SavePreferences(prefs); } } void AEEditorCommon::GetDefaultWindowPreferences(JSONValue& windowPrefs, bool maximized) { windowPrefs["x"] = 0; windowPrefs["y"] = 0; windowPrefs["width"] = 0; windowPrefs["height"] = 0; windowPrefs["monitor"] = 0; windowPrefs["maximized"] = maximized ? true : false; } String AEEditorCommon::GetPreferencesPath() { FileSystem* fileSystem = GetSubsystem(); String path = fileSystem->GetAppPreferencesDir("AtomicEditor", "Preferences"); path += "prefs.json"; return path; } bool AEEditorCommon::LoadPreferences(JSONValue& prefs) { FileSystem* fileSystem = GetSubsystem(); String path = GetPreferencesPath(); if (!fileSystem->FileExists(path)) { if (!CreateDefaultPreferences(path, prefs)) return false; } else { SharedPtr file(new File(context_, path, FILE_READ)); SharedPtr jsonFile(new JSONFile(context_)); if (!jsonFile->BeginLoad(*file)) { file->Close(); if (!CreateDefaultPreferences(path, prefs)) return false; } else { prefs = jsonFile->GetRoot(); } file->Close(); } return true; } bool AEEditorCommon::SavePreferences(JSONValue& prefs) { FileSystem* fileSystem = GetSubsystem(); String path = GetPreferencesPath(); SharedPtr file(new File(context_, path, FILE_WRITE)); SharedPtr jsonFile(new JSONFile(context_)); jsonFile->GetRoot() = prefs; if (!file->IsOpen()) { LOGERRORF("Unable to open Atomic Editor preferences for writing: %s", path.CString()); return false; } jsonFile->Save(*file, " "); file->Close(); return true; } }