Browse Source

Working on welcome screen, preferences

Josh Engebretson 10 years ago
parent
commit
a67b336372

+ 1 - 0
Script/AtomicEditor/tsconfig.json

@@ -26,6 +26,7 @@
         "./ui/ResourceFrame.ts",
         "./ui/ResourceFrame.ts",
         "./ui/ScriptWidget.ts",
         "./ui/ScriptWidget.ts",
         "./ui/UIEvents.ts",
         "./ui/UIEvents.ts",
+        "./ui/WelcomeFrame.ts",
         "./ui/inspector/ArrayEditWidget.ts",
         "./ui/inspector/ArrayEditWidget.ts",
         "./ui/inspector/ComponentInspector.ts",
         "./ui/inspector/ComponentInspector.ts",
         "./ui/inspector/CreateComponentButton.ts",
         "./ui/inspector/CreateComponentButton.ts",

+ 101 - 17
Script/AtomicEditor/ui/MainFrame.ts

@@ -1,5 +1,6 @@
 import ProjectFrame = require("./ProjectFrame");
 import ProjectFrame = require("./ProjectFrame");
 import ResourceFrame = require("./ResourceFrame");
 import ResourceFrame = require("./ResourceFrame");
+import WelcomeFrame = require("./WelcomeFrame");
 import InspectorFrame = require("./inspector/InspectorFrame");
 import InspectorFrame = require("./inspector/InspectorFrame");
 import HierarchyFrame = require("./HierarchyFrame");
 import HierarchyFrame = require("./HierarchyFrame");
 import MainToolbar = require("./MainToolbar");
 import MainToolbar = require("./MainToolbar");
@@ -12,16 +13,6 @@ import MainFrameMenu = require("./MainFrameMenu");
 
 
 class MainFrame extends ScriptWidget {
 class MainFrame extends ScriptWidget {
 
 
-    projectframe: ProjectFrame;
-    resourceframe: ResourceFrame;
-    inspectorframe: InspectorFrame;
-    hierarchyFrame: HierarchyFrame;
-    inspectorlayout: Atomic.UILayout;
-    mainToolbar: MainToolbar;
-    menu: MainFrameMenu;
-
-    private messagemodal: MessageModal.MessageModal = new MessageModal.MessageModal();
-
     constructor() {
     constructor() {
 
 
         super();
         super();
@@ -38,21 +29,107 @@ class MainFrame extends ScriptWidget {
         this.projectframe = new ProjectFrame(this);
         this.projectframe = new ProjectFrame(this);
         this.hierarchyFrame = new HierarchyFrame(this);
         this.hierarchyFrame = new HierarchyFrame(this);
 
 
+        this.welcomeFrame = new WelcomeFrame(this);
         this.resourceframe = new ResourceFrame(this);
         this.resourceframe = new ResourceFrame(this);
 
 
         this.mainToolbar = new MainToolbar(this.getWidget("maintoolbarcontainer"));
         this.mainToolbar = new MainToolbar(this.getWidget("maintoolbarcontainer"));
 
 
         this.menu = new MainFrameMenu();
         this.menu = new MainFrameMenu();
 
 
-        this.showInspectorFrame(true);
-
         this.subscribeToEvent(UIEvents.ResourceEditorChanged, (data) => this.handleResourceEditorChanged(data));
         this.subscribeToEvent(UIEvents.ResourceEditorChanged, (data) => this.handleResourceEditorChanged(data));
 
 
+        this.subscribeToEvent("ProjectLoaded", (data) => {
+          this.showResourceFrame(true);
+        });
+
+        this.showWelcomeFrame(true);
+
     }
     }
 
 
-    showInspectorFrame(show: boolean) {
+    frameVisible(frame: Atomic.UIWidget): boolean {
 
 
-        return;
+        var container = <Atomic.UILayout> this.getWidget("resourceviewcontainer");
+
+        var child = null;
+        for (child = container.firstChild; child; child = child.next) {
+            if (child == frame)
+                return true;
+        }
+
+        return false;
+    }
+
+    showResourceFrame(show: boolean) {
+
+        if (show && this.frameVisible(this.resourceframe))
+            return;
+
+        if (show && this.frameVisible(this.welcomeFrame))
+            this.showWelcomeFrame(false);
+
+        var container = <Atomic.UILayout> this.getWidget("resourceviewcontainer");
+
+        var child = null;
+
+        for (child = container.firstChild; child; child = child.next) {
+            if (child == this.resourceframe)
+                break;
+        }
+
+        if (show) {
+
+            this.showInspectorFrame(true);
+
+            if (!child) {
+                container.addChild(this.resourceframe);
+            }
+
+        }
+        else {
+
+            if (child)
+                container.removeChild(child);
+        }
+
+    }
+
+
+    showWelcomeFrame(show: boolean) {
+
+        if (show && this.frameVisible(this.welcomeFrame))
+            return;
+
+        if (show && this.frameVisible(this.resourceframe))
+            this.showResourceFrame(false);
+
+        var container = <Atomic.UILayout> this.getWidget("resourceviewcontainer");
+
+        var child = null;
+        for (child = container.firstChild; child; child = child.next) {
+            if (child == this.welcomeFrame)
+                break;
+        }
+
+        if (show) {
+
+            this.showInspectorFrame(false);
+
+            this.welcomeFrame.updateRecentProjects();
+
+            if (!child) {
+                container.addChild(this.welcomeFrame);
+            }
+
+        }
+        else {
+            if (child)
+                container.removeChild(child);
+        }
+
+    }
+
+
+    showInspectorFrame(show: boolean) {
 
 
         if (show) {
         if (show) {
 
 
@@ -66,7 +143,6 @@ class MainFrame extends ScriptWidget {
 
 
         }
         }
 
 
-
     }
     }
 
 
     onEventClick(target: Atomic.UIWidget, refid: string): boolean {
     onEventClick(target: Atomic.UIWidget, refid: string): boolean {
@@ -94,16 +170,24 @@ class MainFrame extends ScriptWidget {
 
 
         if (editor) {
         if (editor) {
 
 
-            this.showInspectorFrame(editor.requiresInspector());
+            //this.showInspectorFrame(editor.requiresInspector());
 
 
         } else {
         } else {
 
 
-            this.showInspectorFrame(false);
+            //this.showInspectorFrame(false);
 
 
         }
         }
 
 
     }
     }
 
 
+    projectframe: ProjectFrame;
+    resourceframe: ResourceFrame;
+    inspectorframe: InspectorFrame;
+    hierarchyFrame: HierarchyFrame;
+    welcomeFrame: WelcomeFrame;
+    inspectorlayout: Atomic.UILayout;
+    mainToolbar: MainToolbar;
+    menu: MainFrameMenu;
 
 
 }
 }
 
 

+ 74 - 0
Script/AtomicEditor/ui/WelcomeFrame.ts

@@ -0,0 +1,74 @@
+
+import EditorEvents = require("../editor/EditorEvents");
+import ScriptWidget = require("./ScriptWidget");
+
+class WelcomeFrame extends ScriptWidget {
+
+    constructor(parent: Atomic.UIWidget) {
+
+        super();
+
+        this.load("AtomicEditor/editor/ui/welcomeframe.tb.txt");
+
+        this.recentProjects = <Atomic.UISelectList> this.getWidget("recentprojects");
+        this.recentSource = new Atomic.UISelectItemSource();
+        this.gravity = Atomic.UI_GRAVITY_ALL;
+
+        this.subscribeToEvent("ProjectLoaded", (data) => {
+
+          Editor.getPreferences().registerRecentProject(data.ProjectPath);
+
+        })
+
+    }
+
+    handleWidgetEvent(ev: Atomic.UIWidgetEvent) {
+
+        if (ev.type == Atomic.UI_EVENT_TYPE_CLICK) {
+
+            var id = ev.target.id;
+
+            if (id == "recentprojects") {
+
+                var itemID = Number(this.recentProjects.selectedItemID);
+
+                if (itemID >= 0 && itemID < this.recent.length) {
+
+                    this.sendEvent(EditorEvents.LoadProject, { path: this.recent[itemID] });
+
+                }
+
+                return true;
+
+            }
+
+        }
+
+    }
+
+    updateRecentProjects() {
+
+        this.recentSource.clear();
+
+        // prune any that don't exist
+        Editor.getPreferences().updateRecentFiles();
+
+        this.recent = Editor.getPreferences().recentProjects;
+
+        for (var i in this.recent) {
+
+            this.recentSource.addItem(new Atomic.UISelectItem(this.recent[i], i))
+
+        }
+
+        this.recentProjects.source = this.recentSource;
+
+    }
+
+    recent: string[] = [];
+    recentProjects: Atomic.UISelectList;
+    recentSource: Atomic.UISelectItemSource;
+
+}
+
+export = WelcomeFrame;

+ 1 - 0
Script/TypeScript/Atomic.d.ts

@@ -7270,6 +7270,7 @@ declare module Atomic {
       constructor();
       constructor();
 
 
       addItem(item: UISelectItem): void;
       addItem(item: UISelectItem): void;
+      clear(): void;
 
 
    }
    }
 
 

+ 4 - 0
Script/TypeScript/AtomicWork.d.ts

@@ -97,6 +97,10 @@ declare module Atomic {
 
 
 }
 }
 
 
+declare module Editor {
+    export function getPreferences() : AEPreferences;
+}
+
 declare module ToolCore {
 declare module ToolCore {
     export function getToolEnvironment(): ToolEnvironment;
     export function getToolEnvironment(): ToolEnvironment;
     export function getToolSystem(): ToolSystem;
     export function getToolSystem(): ToolSystem;

+ 24 - 0
Script/TypeScript/Editor.d.ts

@@ -25,6 +25,30 @@ declare module Editor {
 //----------------------------------------------------
 //----------------------------------------------------
 
 
 
 
+   export class AEPreferences extends Atomic.AObject {
+
+      recentProjects: string[];
+      androidSDKPath: string;
+      antPath: string;
+      jDKRootPath: string;
+
+      // Construct.
+      constructor();
+
+      registerRecentProject(fullpath: string): void;
+      getRecentProjects(): string[];
+      setAndroidSDKPath(path: string): void;
+      setAntPath(path: string): void;
+      setJDKRootPath(path: string): void;
+      getAndroidSDKPath(): string;
+      getJDKRootPath(): string;
+      getAntPath(): string;
+      read(): void;
+      write(): void;
+      updateRecentFiles(write?: boolean): void;
+
+   }
+
    export class FileUtils extends Atomic.AObject {
    export class FileUtils extends Atomic.AObject {
 
 
       // Construct.
       // Construct.

+ 2 - 0
Source/Atomic/UI/UISelectItem.h

@@ -52,6 +52,8 @@ public:
 
 
     void AddItem(UISelectItem* item) { items_.Push(SharedPtr<UISelectItem>(item)); }
     void AddItem(UISelectItem* item) { items_.Push(SharedPtr<UISelectItem>(item)); }
 
 
+    void Clear() { items_.Clear(); }
+
     // caller's responsibility to clean up
     // caller's responsibility to clean up
     virtual tb::TBSelectItemSource* GetTBItemSource();
     virtual tb::TBSelectItemSource* GetTBItemSource();
 
 

+ 9 - 0
Source/AtomicEditorWork/Application/AEEditorApp.cpp

@@ -18,6 +18,7 @@
 #include <ToolCore/ToolEnvironment.h>
 #include <ToolCore/ToolEnvironment.h>
 
 
 #include "AEEditorApp.h"
 #include "AEEditorApp.h"
+#include "AEPreferences.h"
 
 
 // Move me
 // Move me
 #include <Atomic/Environment/Environment.h>
 #include <Atomic/Environment/Environment.h>
@@ -62,7 +63,9 @@ void AEEditorApp::Start()
 
 
     Javascript* javascript = new Javascript(context_);
     Javascript* javascript = new Javascript(context_);
     context_->RegisterSubsystem(javascript);
     context_->RegisterSubsystem(javascript);
+
     SubscribeToEvent(E_JSERROR, HANDLER(AEEditorApp, HandleJSError));
     SubscribeToEvent(E_JSERROR, HANDLER(AEEditorApp, HandleJSError));
+    SubscribeToEvent(E_EXITREQUESTED, HANDLER(AEEditorApp, HandleExitRequested));
 
 
     // Instantiate and register the Javascript subsystem
     // Instantiate and register the Javascript subsystem
     vm_ = javascript->InstantiateVM("MainVM");
     vm_ = javascript->InstantiateVM("MainVM");
@@ -92,6 +95,8 @@ void AEEditorApp::Setup()
 {
 {
     RegisterEnvironmentLibrary(context_);
     RegisterEnvironmentLibrary(context_);
 
 
+    context_->RegisterSubsystem(new AEPreferences(context_));
+
     FileSystem* filesystem = GetSubsystem<FileSystem>();
     FileSystem* filesystem = GetSubsystem<FileSystem>();
     ToolEnvironment* env = new ToolEnvironment(context_);
     ToolEnvironment* env = new ToolEnvironment(context_);
     context_->RegisterSubsystem(env);
     context_->RegisterSubsystem(env);
@@ -140,6 +145,10 @@ void AEEditorApp::Stop()
 
 
 }
 }
 
 
+void AEEditorApp::HandleExitRequested(StringHash eventType, VariantMap& eventData)
+{
+}
+
 void AEEditorApp::HandleJSError(StringHash eventType, VariantMap& eventData)
 void AEEditorApp::HandleJSError(StringHash eventType, VariantMap& eventData)
 {
 {
     using namespace JSError;
     using namespace JSError;

+ 3 - 0
Source/AtomicEditorWork/Application/AEEditorApp.h

@@ -13,6 +13,8 @@ namespace Atomic
 namespace AtomicEditor
 namespace AtomicEditor
 {
 {
 
 
+class AEPreferences;
+
 class AEEditorApp : public Application
 class AEEditorApp : public Application
 {
 {
     OBJECT(AEEditorApp);
     OBJECT(AEEditorApp);
@@ -30,6 +32,7 @@ public:
 
 
 private:
 private:
 
 
+    void HandleExitRequested(StringHash eventType, VariantMap& eventData);
     void HandleJSError(StringHash eventType, VariantMap& eventData);
     void HandleJSError(StringHash eventType, VariantMap& eventData);
 
 
     SharedPtr<JSVM> vm_;
     SharedPtr<JSVM> vm_;

+ 287 - 0
Source/AtomicEditorWork/Application/AEPreferences.cpp

@@ -0,0 +1,287 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#include "AtomicEditor.h"
+
+#include <rapidjson/document.h>
+#include "rapidjson/prettywriter.h"
+#include "rapidjson/filestream.h"
+
+#include <Atomic/Core/Context.h>
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+#include <Atomic/Graphics/Graphics.h>
+
+#include "AEEvents.h"
+#include "AEPreferences.h"
+
+using namespace rapidjson;
+
+namespace AtomicEditor
+{
+
+AEPreferences::AEPreferences(Context* context) :
+    Object(context)
+{
+    context->RegisterSubsystem(this);
+
+    SubscribeToEvent(E_EDITORSHUTDOWN, HANDLER(AEPreferences, HandleEditorShutdown));
+
+    Read();
+}
+
+AEPreferences::~AEPreferences()
+{
+
+}
+
+String AEPreferences::GetPreferencesFullPath()
+{
+    FileSystem* fs = GetSubsystem<FileSystem>();
+    String filepath = fs->GetAppPreferencesDir("AtomicEditor", "Preferences");
+    filepath += "prefs.json";
+    return filepath;
+}
+
+void AEPreferences::Clear()
+{
+    recentProjects_.Clear();
+}
+
+void AEPreferences::Read()
+{
+    rapidjson::Document document;
+
+    String filepath = GetPreferencesFullPath();
+
+    File jsonFile(context_, filepath);
+
+    if (!jsonFile.IsOpen())
+        return;
+
+    String json;
+    jsonFile.ReadText(json);
+
+    if (!json.Length())
+        return;
+
+    if (document.Parse<0>(json.CString()).HasParseError())
+    {
+        LOGERRORF("Could not parse JSON data from %s", filepath.CString());
+        return;
+    }
+
+    Clear();
+
+    const Value::Member* recent_files = document.FindMember("recent_files");
+    if (recent_files && recent_files->value.IsArray())
+    {
+        for (Value::ConstValueIterator itr = recent_files->value.Begin(); itr != recent_files->value.End(); itr++)
+        {
+             if (!(*itr).IsString())
+                 continue;
+
+            String path(itr->GetString());
+            recentProjects_.Push(path.CString());
+        }
+    }
+
+    const Value::Member* android_sdk_path = document.FindMember("android_sdk_path");
+    if (android_sdk_path && android_sdk_path->value.IsString())
+        androidSDKPath_ = android_sdk_path->value.GetString();
+
+    const Value::Member* jdk_root_path = document.FindMember("jdk_root_path");
+    if (jdk_root_path && jdk_root_path->value.IsString())
+        jdkRootPath_ = jdk_root_path->value.GetString();
+
+    const Value::Member* ant_path = document.FindMember("ant_path");
+    if (ant_path && ant_path->value.IsString())
+        antPath_ = ant_path->value.GetString();
+
+    UpdateRecentFiles(false);
+
+}
+
+void AEPreferences::Write()
+{
+    String filepath = GetPreferencesFullPath();
+
+    FILE* file = fopen(filepath.CString(), "w");
+
+    if (!file)
+        return;
+
+    Graphics* graphics = GetSubsystem<Graphics>();
+
+    IntVector2 pos(-1, -1);
+
+    int width = -1;
+    int height = -1;
+
+    if (graphics && !graphics->GetFullscreen())
+    {
+        pos = graphics->GetWindowPosition();
+        width = graphics->GetWidth();
+        height = graphics->GetHeight();
+    }
+
+    rapidjson::FileStream s(file);
+    rapidjson::PrettyWriter<rapidjson::FileStream> writer(s);
+
+    writer.StartObject();
+
+    // recent files
+    writer.String("recent_files");
+    writer.StartArray();
+    for (unsigned i = 0; i < recentProjects_.Size(); i++)
+        writer.String(recentProjects_[i].CString());
+    writer.EndArray();
+
+    writer.String("android_sdk_path");
+    writer.String(androidSDKPath_.CString());
+
+    writer.String("jdk_root_path");
+    writer.String(jdkRootPath_.CString());
+
+    writer.String("ant_path");
+    writer.String(antPath_.CString());
+
+    writer.String("window_pos_x");
+    writer.Int(pos.x_);
+    writer.String("window_pos_y");
+    writer.Int(pos.y_);
+    writer.String("window_width");
+    writer.Int(width);
+    writer.String("window_height");
+    writer.Int(height);
+
+    writer.EndObject();
+
+    fclose(file);
+
+}
+
+void AEPreferences::UpdateRecentFiles(bool write)
+{
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+    Vector<String> recentProjects;
+
+    for (unsigned i = 0; i < recentProjects_.Size(); i++)
+    {
+        String path = recentProjects_[i];
+
+        if (!fileSystem->FileExists(path))
+            continue;
+
+
+        recentProjects.Push(path);
+
+        if (recentProjects.Size() == 10)
+            break;
+    }
+
+    recentProjects_ = recentProjects;
+
+    if (write)
+        Write();
+}
+
+void AEPreferences::RegisterRecentProject(const String& fullpath)
+{
+    if (recentProjects_.Contains(fullpath))
+    {
+        recentProjects_.Remove(fullpath);
+    }
+
+    recentProjects_.Insert(0, fullpath);
+
+
+    UpdateRecentFiles();
+
+}
+
+bool AEPreferences::ReadStartupPrefs(Context *context, StartupPreferences& prefs)
+{
+
+    FileSystem* fileSystem = context->GetSubsystem<FileSystem>();
+    String filepath = fileSystem->GetAppPreferencesDir("AtomicEditor", "Preferences");
+    filepath += "prefs.json";
+
+    if (!fileSystem->FileExists(filepath))
+        return false;
+
+    SharedPtr<File> file(new File(context, filepath, FILE_READ));
+
+    if (!file->IsOpen())
+        return false;
+
+    String json;
+    file->ReadText(json);
+
+    if (!json.Length())
+        return false;
+
+    rapidjson::Document document;
+
+    if (document.Parse<0>(json.CString()).HasParseError())
+    {
+        return false;
+    }
+
+    bool success = true;
+
+    const Value::Member* imember = document.FindMember("window_pos_x");
+    if (imember && imember->value.IsInt())
+    {
+        prefs.windowPos.x_ = imember->value.GetInt();
+    }
+    else
+    {
+        success = false;
+    }
+
+    imember = document.FindMember("window_pos_y");
+    if (imember && imember->value.IsInt())
+    {
+        prefs.windowPos.y_ = imember->value.GetInt();
+    }
+    else
+    {
+        success = false;
+    }
+
+    imember = document.FindMember("window_width");
+    if (imember && imember->value.IsInt())
+    {
+        prefs.windowWidth = imember->value.GetInt();
+    }
+    else
+    {
+        success = false;
+    }
+
+    imember = document.FindMember("window_height");
+    if (imember && imember->value.IsInt())
+    {
+        prefs.windowHeight = imember->value.GetInt();
+    }
+    else
+    {
+        success = false;
+    }
+
+    if (prefs.windowHeight < 128 || prefs.windowWidth < 128)
+        return false;
+
+    return success;
+
+}
+
+void AEPreferences::HandleEditorShutdown(StringHash eventType, VariantMap& eventData)
+{
+    context_->RemoveSubsystem(GetType());
+}
+
+}

+ 68 - 0
Source/AtomicEditorWork/Application/AEPreferences.h

@@ -0,0 +1,68 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+#include <Atomic/IO/FileSystem.h>
+
+using namespace Atomic;
+
+namespace AtomicEditor
+{
+
+class AEPreferences : public Object
+{
+
+    OBJECT(AEPreferences);
+
+public:
+
+    struct StartupPreferences
+    {
+        IntVector2 windowPos;
+        int windowWidth;
+        int windowHeight;
+    };
+
+    /// Construct.
+    AEPreferences(Context* context);
+    /// Destruct.
+    ~AEPreferences();
+
+    void RegisterRecentProject(const String& fullpath);
+    const Vector<String>& GetRecentProjects() { return recentProjects_; }
+
+    void SetAndroidSDKPath(const String& path) { androidSDKPath_ = path; Write(); }
+    void SetAntPath(const String& path) { antPath_ = path; Write(); }
+    void SetJDKRootPath(const String& path) { jdkRootPath_ = path; Write(); }
+
+    String GetAndroidSDKPath() { return AddTrailingSlash(androidSDKPath_); }
+    String GetJDKRootPath() { return AddTrailingSlash(jdkRootPath_); }
+    String GetAntPath() { return AddTrailingSlash(antPath_); }
+
+    void Read();
+    void Write();
+
+    static bool ReadStartupPrefs(Context* context, StartupPreferences& prefs);
+
+    void UpdateRecentFiles(bool write = true);
+
+private:
+
+     void HandleEditorShutdown(StringHash eventType, VariantMap& eventData);
+
+    void Clear();
+    String GetPreferencesFullPath();
+
+    String androidSDKPath_;
+    String jdkRootPath_;
+    String antPath_;
+
+    String lastProjectFullPath_;
+    Vector<String> recentProjects_;    
+};
+
+
+}

+ 12 - 0
Source/AtomicEditorWork/Javascript/AEEditorJS.cpp

@@ -1,5 +1,6 @@
 
 
 #include <AtomicJS/Javascript/JSVM.h>
 #include <AtomicJS/Javascript/JSVM.h>
+#include "../Application/AEPreferences.h"
 
 
 using namespace Atomic;
 using namespace Atomic;
 
 
@@ -11,11 +12,22 @@ namespace Atomic
 namespace AtomicEditor
 namespace AtomicEditor
 {
 {
 
 
+static int Editor_GetPreferences(duk_context* ctx)
+{
+    JSVM* vm = JSVM::GetJSVM(ctx);
+    js_push_class_object_instance(ctx, vm->GetSubsystem<AEPreferences>(), "AEPreferences");
+    return 1;
+}
+
 void jsapi_init_editor(JSVM* vm)
 void jsapi_init_editor(JSVM* vm)
 {
 {
     duk_context* ctx = vm->GetJSContext();
     duk_context* ctx = vm->GetJSContext();
 
 
     duk_push_object(ctx);
     duk_push_object(ctx);
+
+    duk_push_c_function(ctx, Editor_GetPreferences, 0);
+    duk_put_prop_string(ctx, -2, "getPreferences");
+
     duk_put_global_string(ctx, "Editor");
     duk_put_global_string(ctx, "Editor");
 
 
     jsb_package_editor_init(vm);
     jsb_package_editor_init(vm);

+ 2 - 2
Source/AtomicJS/Packages/Editor/Editor.json

@@ -1,5 +1,5 @@
 {
 {
 	"name" : "Editor",
 	"name" : "Editor",
-	"sources" : ["Source/AtomicEditorWork/Utils", "Source/AtomicEditorWork/Editors", "Source/AtomicEditorWork/Editors/SceneEditor3D"],
-	"classes" : ["FileUtils", "ResourceEditor", "JSResourceEditor", "SceneEditor3D", "SceneView3D"]
+	"sources" : ["Source/AtomicEditorWork/Application", "Source/AtomicEditorWork/Utils", "Source/AtomicEditorWork/Editors", "Source/AtomicEditorWork/Editors/SceneEditor3D"],
+	"classes" : ["FileUtils", "AEPreferences", "ResourceEditor", "JSResourceEditor", "SceneEditor3D", "SceneView3D"]
 }
 }

+ 1 - 1
Source/ToolCore/Project/Project.cpp

@@ -117,7 +117,7 @@ bool Project::Load(const String& fullpath)
 
 
     if ( true /*result*/) {
     if ( true /*result*/) {
         VariantMap data;
         VariantMap data;
-        data[ProjectLoaded::P_PROJECTPATH] = projectPath_;
+        data[ProjectLoaded::P_PROJECTPATH] = projectFilePath_;
         SendEvent(E_PROJECTLOADED, data);
         SendEvent(E_PROJECTLOADED, data);
     }
     }
 
 

+ 15 - 1
Source/ToolCore/ToolSystem.cpp

@@ -42,7 +42,21 @@ ToolSystem::~ToolSystem()
 
 
 bool ToolSystem::LoadProject(const String& fullpath)
 bool ToolSystem::LoadProject(const String& fullpath)
 {
 {
-    String path = RemoveTrailingSlash(GetPath(AddTrailingSlash(fullpath)));
+
+    String pathName, fileName, ext;
+
+    SplitPath(fullpath, pathName, fileName, ext);
+
+    String path;
+
+    if (ext == ".atomic")
+    {
+        path = RemoveTrailingSlash(GetPath(AddTrailingSlash(pathName)));
+    }
+    else
+    {
+        path = RemoveTrailingSlash(GetPath(AddTrailingSlash(fullpath)));
+    }
 
 
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     cache->AddResourceDir(path, 0);
     cache->AddResourceDir(path, 0);