Browse Source

Merge pull request #560 from AtomicGameEngine/JME-ATOMIC-558

Engine configuration via JSON
JoshEngebretson 10 years ago
parent
commit
60e80f51a9

+ 314 - 0
Source/Atomic/Engine/EngineConfig.cpp

@@ -0,0 +1,314 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "../IO/File.h"
+#include "../Resource/JSONFile.h"
+#include "../Graphics/GraphicsDefs.h"
+#include "EngineConfig.h"
+
+namespace Atomic
+{
+
+VariantMap EngineConfig::engineConfig_;
+
+bool EngineConfig::GetBoolValue(const JSONValue& jvalue, bool defaultValue)
+{
+    bool value = defaultValue;
+
+    if (jvalue.IsBool())
+        value = jvalue.GetBool();
+
+    return value;
+}
+
+int EngineConfig::GetIntValue(const JSONValue& jvalue, int defaultValue)
+{
+    int value = defaultValue;
+
+    if (jvalue.IsNumber())
+        value = jvalue.GetInt();
+
+    return value;
+}
+
+String EngineConfig::GetStringValue(const JSONValue& jvalue, const String& defaultValue)
+{
+    String value = defaultValue;
+
+    if (jvalue.IsString())
+        value = jvalue.GetString();
+
+    return value;
+}
+
+bool EngineConfig::LoadEngineConfig(const JSONValue& jengine)
+{
+    if (!jengine.IsObject())
+        return false;
+
+    for (JSONObject::ConstIterator i = jengine.Begin(); i != jengine.End(); ++i)
+    {
+        String key = i->first_.ToLower();
+        const JSONValue& jvalue = i->second_;
+
+        if (key == "workerthreads")
+            engineConfig_["WorkerThreads"] = GetBoolValue(jvalue, true);
+        else if (key == "logquiet")
+            engineConfig_["LogQuiet"] = GetBoolValue(jvalue, false);
+        else if (key == "loglevel")
+            engineConfig_["LogLevel"] = GetIntValue(jvalue, 1);
+    }
+
+    return true;
+}
+
+bool EngineConfig::LoadGraphicsConfig(const JSONValue& jgraphics)
+{
+    if (!jgraphics.IsObject())
+        return false;
+
+    for (JSONObject::ConstIterator i = jgraphics.Begin(); i != jgraphics.End(); ++i)
+    {
+        String key = i->first_.ToLower();
+        const JSONValue& jvalue = i->second_;
+
+        if (key == "headless")
+            engineConfig_["Headless"] = GetBoolValue(jvalue, false);
+        else if (key == "framelimiter")
+            engineConfig_["FrameLimiter"] = GetBoolValue(jvalue, true);
+        else if (key == "flushgpu")
+            engineConfig_["FlushGPU"] = GetBoolValue(jvalue, false);
+        else if (key == "forcegl2")
+            engineConfig_["ForceGL2"] = GetBoolValue(jvalue, false);
+        else if (key == "orientations")
+            engineConfig_["Orientations"] = GetStringValue(jvalue, "LandscapeLeft LandscapeRight");
+        else if (key == "vsync")
+            engineConfig_["VSync"] = GetBoolValue(jvalue, false);
+        else if (key == "triplebuffer")
+            engineConfig_["TripleBuffer"] = GetBoolValue(jvalue, false);
+        else if (key == "multisample")
+            engineConfig_["Multisample"] = GetIntValue(jvalue, 1);
+        else if (key == "renderpath")
+        {
+            String renderPath = GetStringValue(jvalue, "forward").ToLower();
+
+            if (renderPath == "forward")
+                engineConfig_["RenderPath"] = "RenderPaths/Forward.xml";
+            else if (renderPath == "prepass")
+                engineConfig_["RenderPath"] = "RenderPaths/Prepass.xml";
+            else if (renderPath == "deferred")
+                engineConfig_["RenderPath"] = "RenderPaths/Deferred.xml";
+        }
+        else if (key == "shadows")
+            engineConfig_["Shadows"] = GetBoolValue(jvalue, true);
+        else if (key == "lowqualityshadows")
+            engineConfig_["LowQualityShadows"] = GetBoolValue(jvalue, false);
+        else if (key == "materialquality")
+        {
+            String quality = GetStringValue(jvalue, "high").ToLower();
+
+            if (quality == "high")
+                engineConfig_["MaterialQuality"] = QUALITY_HIGH;
+            else if (quality == "medium")
+                engineConfig_["MaterialQuality"] = QUALITY_MEDIUM;
+            else if (quality == "low")
+                engineConfig_["MaterialQuality"] = QUALITY_LOW;
+        }
+        else if (key == "texturequality")
+        {
+            String quality = GetStringValue(jvalue, "high").ToLower();
+
+            if (quality == "high")
+                engineConfig_["TextureQuality"] = QUALITY_HIGH;
+            else if (quality == "medium")
+                engineConfig_["TextureQuality"] = QUALITY_MEDIUM;
+            else if (quality == "low")
+                engineConfig_["TextureQuality"] = QUALITY_LOW;
+        }
+        else if (key == "texturefiltermode")
+        {
+            String mode = GetStringValue(jvalue, "trilinear").ToLower();
+
+            if (mode == "trilinear")
+                engineConfig_["TextureFilterMode"] = FILTER_TRILINEAR;
+            else if (mode == "bilinear")
+                engineConfig_["TextureFilterMode"] = FILTER_BILINEAR;
+            else if (mode == "nearest")
+                engineConfig_["TextureFilterMode"] = FILTER_NEAREST;
+            else if (mode == "anisotropic")
+                engineConfig_["TextureFilterMode"] = FILTER_ANISOTROPIC;
+        }
+        else if (key == "textureanisotropy")
+        {
+            engineConfig_["TextureAnisotropy"] = GetIntValue(jvalue, 4);
+        }
+
+
+    }
+
+    return true;
+}
+
+bool EngineConfig::LoadWindowConfig(const JSONValue& jwindow)
+{
+    if (!jwindow.IsObject())
+        return false;
+
+    for (JSONObject::ConstIterator i = jwindow.Begin(); i != jwindow.End(); ++i)
+    {
+        String key = i->first_.ToLower();
+        const JSONValue& jvalue = i->second_;
+
+        if (key == "title")
+            engineConfig_["WindowTitle"] = GetStringValue(jvalue, "Atomic");
+        else if (key == "fullscreen")
+            engineConfig_["FullScreen"] = GetBoolValue(jvalue, false);
+        else if (key == "borderless")
+            engineConfig_["Borderless"] = GetBoolValue(jvalue, false);
+        else if (key == "resizable")
+            engineConfig_["WindowResizable"] = GetBoolValue(jvalue, false);
+
+    }
+
+    return true;
+
+}
+
+bool EngineConfig::LoadSoundConfig(const JSONValue& jsound)
+{
+    if (!jsound.IsObject())
+        return false;
+
+    for (JSONObject::ConstIterator i = jsound.Begin(); i != jsound.End(); ++i)
+    {
+        String key = i->first_.ToLower();
+        const JSONValue& jvalue = i->second_;
+
+        if (key == "enabled")
+            engineConfig_["Sound"] = GetBoolValue(jvalue, true);
+        else if (key == "interpolation")
+            engineConfig_["SoundInterpolation"] = GetBoolValue(jvalue, true);
+        else if (key == "stereo")
+            engineConfig_["SoundStereo"] = GetBoolValue(jvalue, true);
+        else if (key == "bufferms")
+            engineConfig_["SoundBuffer"] = GetIntValue(jvalue, 100);
+        else if (key == "mixrate")
+            engineConfig_["SoundMixRate"] = GetIntValue(jvalue, 44100);
+
+    }
+
+    return true;
+
+}
+
+bool EngineConfig::LoadInputConfig(const JSONValue& jinput)
+{
+    if (!jinput.IsObject())
+        return false;
+
+    for (JSONObject::ConstIterator i = jinput.Begin(); i != jinput.End(); ++i)
+    {
+        String key = i->first_.ToLower();
+        const JSONValue& jvalue = i->second_;
+
+        if (key == "touchemulation")
+            engineConfig_["TouchEmulation"] = GetBoolValue(jvalue, false);
+    }
+
+    return true;
+
+}
+
+
+bool EngineConfig::LoadDesktopConfig(JSONValue root)
+{
+    const JSONValue& jdesktop = root["desktop"];
+
+    if (!jdesktop.IsObject())
+        return false;
+
+    const JSONValue& jengine = jdesktop["engine"];
+    if (jengine.IsObject())
+        LoadEngineConfig(jengine);
+
+    const JSONValue& jgraphics = jdesktop["graphics"];
+    if (jgraphics.IsObject())
+        LoadGraphicsConfig(jgraphics);
+
+    const JSONValue& jwindow = jdesktop["window"];
+    if (jwindow.IsObject())
+        LoadWindowConfig(jwindow);
+
+    const JSONValue& jsound = jdesktop["sound"];
+    if (jsound.IsObject())
+        LoadSoundConfig(jsound);
+
+    const JSONValue& jinput = jdesktop["input"];
+    if (jinput.IsObject())
+        LoadInputConfig(jinput);
+
+    return true;
+}
+
+bool EngineConfig::LoadFromJSON(const String& json)
+{
+    engineConfig_.Clear();
+
+    JSONValue jroot;
+
+    if (!JSONFile::ParseJSON(json, jroot))
+        return false;
+
+    if (!jroot.IsObject())
+        return false;
+
+    if (!LoadDesktopConfig(jroot))
+        return false;
+
+    return true;
+}
+
+bool EngineConfig::LoadFromFile(Context *context, const String& filename)
+{
+    SharedPtr<File> file(new File(context));
+
+    if (!file->Open(filename))
+        return false;
+
+    String json;
+    file->ReadText(json);
+
+    return LoadFromJSON(json);
+}
+
+void EngineConfig::ApplyConfig(VariantMap& settings)
+{
+    VariantMap::ConstIterator itr = engineConfig_.Begin();
+    while (itr != engineConfig_.End())
+    {
+        settings.InsertNew(itr->first_, itr->second_);
+        itr++;
+    }
+
+}
+
+}

+ 65 - 0
Source/Atomic/Engine/EngineConfig.h

@@ -0,0 +1,65 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "../Core/Variant.h"
+#include "../Resource/JSONValue.h"
+
+namespace Atomic
+{
+
+class Context;
+
+/// Atomic engine configuration
+class EngineConfig
+{
+
+public:
+
+    static bool LoadFromFile(Context* context, const String& filename);
+    static bool LoadFromJSON(const String& json);
+
+    /// Apply the configuration to a setting variant map, values that exist will not be overriden
+    static void ApplyConfig(VariantMap& settings);
+
+    static const VariantMap& GetConfig() { return engineConfig_; }
+
+private:
+
+    static bool LoadDesktopConfig(JSONValue root);
+    static bool LoadGraphicsConfig(const JSONValue& jgraphics);
+    static bool LoadWindowConfig(const JSONValue& jwindow);
+    static bool LoadSoundConfig(const JSONValue& jsound);
+    static bool LoadInputConfig(const JSONValue& jinput);
+
+    static bool GetBoolValue(const JSONValue& jvalue, bool defaultValue);
+    static int GetIntValue(const JSONValue& jvalue, int defaultValue);
+    static String GetStringValue(const JSONValue& jvalue, const String& defaultValue);
+
+    static bool LoadEngineConfig(const JSONValue& jengine);
+
+    static VariantMap engineConfig_;
+
+};
+
+}

+ 0 - 2
Source/Atomic/UI/UIWidget.cpp

@@ -20,8 +20,6 @@
 // THE SOFTWARE.
 // THE SOFTWARE.
 //
 //
 
 
-//--player --editor-resource-paths "/Users/josh/Dev/atomic/AtomicGameEngine/Data/AtomicPlayer/Resources/CoreData!/Users/josh/Dev/atomic/AtomicGameEngine/Data/AtomicPlayer/Resources/PlayerData!/Users/josh/Dev/atomic/AtomicExamples/UIExample/Resources"
-
 #include "../IO/Log.h"
 #include "../IO/Log.h"
 #include "../Input/InputEvents.h"
 #include "../Input/InputEvents.h"
 
 

+ 47 - 9
Source/AtomicEditor/Application/AEPlayerApp.cpp

@@ -7,6 +7,7 @@
 
 
 #include <Atomic/Atomic.h>
 #include <Atomic/Atomic.h>
 #include <Atomic/Engine/Engine.h>
 #include <Atomic/Engine/Engine.h>
+#include <Atomic/Engine/EngineConfig.h>
 #include <Atomic/IO/FileSystem.h>
 #include <Atomic/IO/FileSystem.h>
 #include <Atomic/IO/Log.h>
 #include <Atomic/IO/Log.h>
 #include <Atomic/IO/IOEvents.h>
 #include <Atomic/IO/IOEvents.h>
@@ -59,11 +60,12 @@ void AEPlayerApplication::Setup()
 {
 {
     AEEditorCommon::Setup();
     AEEditorCommon::Setup();
 
 
-    engine_->SetAutoExit(false);
+    // Read the engine configuration
+    ReadEngineConfig();
 
 
-    FileSystem* filesystem = GetSubsystem<FileSystem>();
+    engine_->SetAutoExit(false);
 
 
-    engineParameters_["WindowTitle"] = "AtomicPlayer";
+    engineParameters_.InsertNew("WindowTitle", "AtomicPlayer");
 
 
 #if (ATOMIC_PLATFORM_ANDROID)
 #if (ATOMIC_PLATFORM_ANDROID)
     engineParameters_["FullScreen"] = true;
     engineParameters_["FullScreen"] = true;
@@ -82,7 +84,7 @@ void AEPlayerApplication::Setup()
     engineParameters_["WindowHeight"] = 720;
     engineParameters_["WindowHeight"] = 720;
 #endif
 #endif
 
 
-    engineParameters_["LogLevel"] = LOG_DEBUG;
+    engineParameters_.InsertNew("LogLevel", LOG_DEBUG);
 
 
 #if ATOMIC_PLATFORM_WINDOWS || ATOMIC_PLATFORM_LINUX
 #if ATOMIC_PLATFORM_WINDOWS || ATOMIC_PLATFORM_LINUX
     engineParameters_["WindowIcon"] = "Images/AtomicLogo32.png";
     engineParameters_["WindowIcon"] = "Images/AtomicLogo32.png";
@@ -93,6 +95,8 @@ void AEPlayerApplication::Setup()
     engineParameters_["ResourcePrefixPath"] = "../Resources";
     engineParameters_["ResourcePrefixPath"] = "../Resources";
 #endif
 #endif
 
 
+    FileSystem* filesystem = GetSubsystem<FileSystem>();
+
     const Vector<String>& arguments = GetArguments();
     const Vector<String>& arguments = GetArguments();
 
 
     for (unsigned i = 0; i < arguments.Size(); ++i)
     for (unsigned i = 0; i < arguments.Size(); ++i)
@@ -114,9 +118,6 @@ void AEPlayerApplication::Setup()
             {
             {
                 engineParameters_["ResourcePrefixPath"] = "";
                 engineParameters_["ResourcePrefixPath"] = "";
 
 
-                // This works for a local dev build, --editor-resource-paths command below is for
-                // launching from AtomicEditor (IPC)
-
                 value = AddTrailingSlash(value);
                 value = AddTrailingSlash(value);
 
 
                 // check that cache exists
                 // check that cache exists
@@ -181,12 +182,49 @@ void AEPlayerApplication::Setup()
         }
         }
     }
     }
 
 
-
-
     // Use the script file name as the base name for the log file
     // Use the script file name as the base name for the log file
     engineParameters_["LogName"] = filesystem->GetAppPreferencesDir("AtomicPlayer", "Logs") + "AtomicPlayer.log";
     engineParameters_["LogName"] = filesystem->GetAppPreferencesDir("AtomicPlayer", "Logs") + "AtomicPlayer.log";
 }
 }
 
 
+void AEPlayerApplication::ReadEngineConfig()
+{
+    // find the project path from the command line args
+
+    String projectPath;
+    const Vector<String>& arguments = GetArguments();
+
+    for (unsigned i = 0; i < arguments.Size(); ++i)
+    {
+        if (arguments[i].Length() > 1)
+        {
+            String argument = arguments[i].ToLower();
+            String value = i + 1 < arguments.Size() ? arguments[i + 1] : String::EMPTY;
+
+            if (argument == "--project" && value.Length())
+            {
+                projectPath = AddTrailingSlash(value);
+                break;
+            }
+
+        }
+    }
+
+    if (!projectPath.Length())
+        return;
+
+    FileSystem* filesystem = GetSubsystem<FileSystem>();
+    String filename = projectPath + "Settings/Engine.json";
+
+    if (!filesystem->FileExists(filename))
+        return;
+
+    if (EngineConfig::LoadFromFile(context_, filename))
+    {
+        EngineConfig::ApplyConfig(engineParameters_);
+    }
+
+}
+
 void AEPlayerApplication::Start()
 void AEPlayerApplication::Start()
 {
 {
     AEEditorCommon::Start();
     AEEditorCommon::Start();

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

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

+ 0 - 2
Source/ToolCore/Command/PlayCmd.cpp

@@ -95,8 +95,6 @@ void PlayCmd::Run()
 
 
     Vector<String> vargs;
     Vector<String> vargs;
 
 
-    //String args = ToString("--editor-resource-paths \"%s\"", resourcePaths.CString());
-
     String args = ToString("--player --project \"%s\"", AddTrailingSlash(project->GetProjectPath()).CString());
     String args = ToString("--player --project \"%s\"", AddTrailingSlash(project->GetProjectPath()).CString());
 
 
     vargs = args.Split(' ');
     vargs = args.Split(' ');