Browse Source

Editor C# Compilation (+1 squashed commit)
Squashed commits:
[56db337] C# code changes require manual recompilation in AtomicEditor #1236

JimMarlowe 9 years ago
parent
commit
4ab3f437a3

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

@@ -181,3 +181,11 @@ export interface UserPreferencesChangedEvent {
 
 export const WebViewLoadEnd = "WebViewLoadEnd";
 export const WebMessage = "WebMessage";
+
+// interface to pass modal error messages from core modules
+export const EditorModal = "EditorModal";
+export interface EditorModalEvent {
+    uiType: number;     // EDITOR_ERROR_MODAL, etc)
+    title: string;      // for modal errors, title text
+    message: string;    // for modal errors, error text
+}

+ 0 - 19
Script/AtomicEditor/hostExtensions/languageExtensions/CSharpLanguageExtension.ts

@@ -69,9 +69,6 @@ export default class CSharpLanguageExtension implements Editor.HostExtensions.Re
             menu.addItem(new Atomic.UIMenuItem("Generate Solution", `${this.name}.generatesolution`));
             menu.addItem(new Atomic.UIMenuItem("Package Resources", `${this.name}.packageresources`));
 
-            this.compileOnSaveMenuItem = new Atomic.UIMenuItem(`Compile on Save: ${isCompileOnSave ? "On" : "Off"}`, `${this.name}.compileonsave`);
-            menu.addItem(this.compileOnSaveMenuItem);
-
             this.menuCreated = true;
         }
 
@@ -135,15 +132,6 @@ export default class CSharpLanguageExtension implements Editor.HostExtensions.Re
             this.isNETProject = true;
         }
 
-        const isCompileOnSave = this.serviceRegistry.projectServices.getUserPreference(this.name, "CompileOnSave", false);
-
-        if (isCompileOnSave && ToolCore.netProjectSystem) {
-
-            // for now, only support compile on save when not using VS
-            if (!ToolCore.netProjectSystem.iDEAvailable)
-                ToolCore.netProjectSystem.buildAtomicProject();
-        }
-
     }
 
     /*** ProjectService implementation ****/
@@ -205,13 +193,6 @@ export default class CSharpLanguageExtension implements Editor.HostExtensions.Re
                 case "packageresources":
                     this.packageResources();
                     return true;
-                case "compileonsave":
-                    let isCompileOnSave = this.serviceRegistry.projectServices.getUserPreference(this.name, "CompileOnSave", false);
-                    // Toggle
-                    isCompileOnSave = !isCompileOnSave;
-                    this.serviceRegistry.projectServices.setUserPreference(this.name, "CompileOnSave", isCompileOnSave);
-                    this.compileOnSaveMenuItem.string = `Compile on Save: ${isCompileOnSave ? "On" : "Off"}`;
-                    return true;
             }
         }
     }

+ 4 - 0
Script/AtomicEditor/ui/EditorUI.ts

@@ -110,6 +110,10 @@ class EditorUI extends Atomic.ScriptObject {
     this.subscribeToEvent(EditorEvents.ModalError, (event:EditorEvents.ModalErrorEvent) => {
       this.showModalError(event.title, event.message);
     });
+    
+    this.subscribeToEvent(EditorEvents.EditorModal, (event:EditorEvents.EditorModalEvent) => {
+      this.showModalError(event.title, event.message);
+    });
 
   }
 

+ 10 - 0
Script/AtomicEditor/ui/Shortcuts.ts

@@ -40,6 +40,11 @@ class Shortcuts extends Atomic.ScriptObject {
     //this should be moved somewhere else...
     invokePlayOrStopPlayer(debug: boolean = false) {
         this.sendEvent(EditorEvents.SaveAllResources);
+
+        if ( ToolCore.netProjectSystem.solutionAvailable)   // are we a csharp project
+            if( ToolCore.netProjectSystem.buildAndRun() )   // do we need to rebuild?
+                return;  // if yes, return, the play event will be reissued after the rebuild
+      
         if (Atomic.editorMode.isPlayerEnabled()) {
             this.sendEvent("IPCPlayerExitRequest");
         } else {
@@ -216,6 +221,11 @@ class Shortcuts extends Atomic.ScriptObject {
     handleUIShortcut(ev: Atomic.UIShortcutEvent) {
 
         var cmdKey = this.cmdKeyDown();
+    
+        if ( !cmdKey && ev.qualifiers > 0 ) // check the event, the qualifier may have been programmitically set
+        {
+            cmdKey = ( ev.qualifiers == Atomic.QUAL_CTRL );
+        }
 
         if (cmdKey) {
 

+ 1 - 1
Script/Packages/ToolCore/ToolCore.json

@@ -4,7 +4,7 @@
 							 "Source/ToolCore/Import", "Source/ToolCore/Assets", "Source/ToolCore/License", "Source/ToolCore/Build",
 						 	 "Source/ToolCore/Subprocess", "Source/ToolCore/NETTools"],
 	"classes" : ["ToolEnvironment", "ToolSystem", "ToolPrefs", "SubprocessSystem", "Subprocess",
-								"Project", "ProjectFile", "Platform", "PlatformMac", "PlatformWeb",
+								"Project", "ProjectSettings", "ProjectFile", "Platform", "PlatformMac", "PlatformWeb",
 							 "PlatformWindows", "PlatformAndroid", "PlatformIOS", "PlatformLinux", "Command", "PlayCmd", "OpenAssetImporter",
 							 "Asset", "AssetDatabase", "AssetImporter", "AudioImporter", "ModelImporter", "MaterialImporter", "AnimationImportInfo",
 							 "PrefabImporter", "JavascriptImporter", "JSONImporter",

+ 113 - 0
Source/ToolCore/NETTools/NETProjectSystem.cpp

@@ -29,6 +29,10 @@
 #include <Atomic/IO/FileSystem.h>
 #include <Atomic/Resource/ResourceEvents.h>
 
+#include <Atomic/UI/UIEvents.h>
+#include <Atomic/Input/InputEvents.h>
+#include <AtomicEditor/EditorMode/AEEditorEvents.h>
+
 #include "../ToolSystem.h"
 #include "../ToolEnvironment.h"
 #include "../Assets/AssetEvents.h"
@@ -188,6 +192,19 @@ namespace ToolCore
 
             ATOMIC_LOGERRORF("\n%s\n", errorText.CString());
             ATOMIC_LOGERRORF("NETBuild Error for project");
+            
+            String myerror; // too much error for the dialog! scrape off just the error summary
+            unsigned where = errorText.Find("Errors:", 0, true);
+            if ( where != String::NPOS)
+                myerror = errorText.Substring (where, errorText.Length() - where);
+            else myerror = errorText; // failed to find summary, send the whole text
+            
+            using namespace AtomicEditor;
+            VariantMap errorData;
+            errorData[EditorModal::P_TYPE] = EDITOR_MODALERROR;
+            errorData[EditorModal::P_TITLE] = String("NETBuild Errors");
+            errorData[EditorModal::P_MESSAGE] = myerror;
+            SendEvent(E_EDITORMODAL, errorData);
         }
 
     }
@@ -421,6 +438,102 @@ namespace ToolCore
 
     }
 
+    /// handle the results of a recompile, and auto play the project if successful
+    void NETProjectSystem::HandleNETBuildPlay(StringHash eventType, VariantMap& eventData)
+    {
+        using namespace NETBuildResult;
+        
+        if (eventData[P_SUCCESS].GetBool())
+        {
+            ATOMIC_LOGINFOF("NETBuild Success for project, now playing.");
+            VariantMap shortcutData;  // encode a shortcut event to send a play
+            shortcutData[UIShortcut::P_KEY] = KEY_P;
+            shortcutData[UIShortcut::P_QUALIFIERS] = QUAL_CTRL;
+            SendEvent(E_UISHORTCUT, shortcutData);
+        }
+        else
+        {
+            const String& errorText = eventData[P_ERRORTEXT].GetString();
+
+            ATOMIC_LOGERRORF("\n%s\n", errorText.CString());
+            ATOMIC_LOGERRORF("NETBuild Error for project, will not play.");
+           
+            String myerror; // too much error for the dialog! scrape off just the error summary
+            unsigned where = errorText.Find("Errors:", 0, true);
+            if ( where != String::NPOS)
+                myerror = errorText.Substring (where, errorText.Length() - where);
+            else myerror = errorText; // failed to find summary, send the whole text
+            
+            using namespace AtomicEditor;
+            VariantMap errorData;
+            errorData[EditorModal::P_TYPE] = EDITOR_MODALERROR;
+            errorData[EditorModal::P_TITLE] = String("NETBuild Error for project");
+            errorData[EditorModal::P_MESSAGE] = myerror;
+            SendEvent(E_EDITORMODAL, errorData);
+        }
+
+    }
+
+    /// used to ensure the project can be run from the editor
+    bool NETProjectSystem::BuildAndRun()
+    {
+        bool shouldRebuild = CheckForRebuild();
+        if (shouldRebuild) 
+        {
+            FileSystem* fileSystem = GetSubsystem<FileSystem>();
+            if (!fileSystem->FileExists(solutionPath_))
+            {
+                if (!GenerateSolution())
+                {
+                    ATOMIC_LOGERRORF("NETProjectSystem::BuildAtomicProject - solutionPath does not exist: %s", solutionPath_.CString());
+                    return false;
+                }
+            }
+
+            Project* project = GetSubsystem<ToolSystem>()->GetProject();
+            NETBuildSystem* buildSystem = GetSubsystem<NETBuildSystem>();
+            if (buildSystem)
+            {
+                NETBuild* build = buildSystem->BuildAtomicProject(project);
+                if (build)
+                {
+                    build->SubscribeToEvent(E_NETBUILDRESULT, ATOMIC_HANDLER(NETProjectSystem, HandleNETBuildPlay));
+                }
+            }       
+        }
+        
+        return shouldRebuild;
+    }
+    
+    /// interrogate sources to see if any are dirty compared to the editor project.dll
+    bool NETProjectSystem::CheckForRebuild() 
+    {
+        FileSystem* fileSystem = GetSubsystem<FileSystem>();
+        AssetDatabase* db = GetSubsystem<AssetDatabase>();
+        Project* project = GetSubsystem<ToolSystem>()->GetProject();
+        unsigned dllTimestamp = 0;
+
+        String mydll = project->GetResourcePath() + project->GetProjectSettings()->GetName() + ".dll";
+        Asset* myasset = db->GetAssetByPath(mydll);
+        if (myasset)
+            dllTimestamp = myasset->GetFileTimestamp();  
+        else 
+            return true; // dll not there, needs to be built, or the sources dont compile, or some other error
+ 
+        int nn=0;
+        Asset* filex = NULL;
+        StringVector results;
+        String tdir = AddTrailingSlash(project->GetResourcePath());
+        fileSystem->ScanDir(results, tdir, "*.cs", SCAN_FILES, true);
+        for (nn=0; nn<results.Size(); nn++)
+        {
+            filex = db->GetAssetByPath(tdir + results[nn]);
+            if (filex && filex->GetFileTimestamp() > dllTimestamp )
+                return true;  // some file is younger or dirtier, dll needs to be rebuilt
+         }
+        return false; // the dll is up to date, no need to recompile
+    }
+    
     void NETProjectSystem::Initialize()
     {
         Clear();

+ 6 - 0
Source/ToolCore/NETTools/NETProjectSystem.h

@@ -68,11 +68,15 @@ namespace ToolCore
         bool GenerateSolution();
         bool GenerateResourcePak();
 
+        /// build csharp dll if sources are dirty and then run
+        bool BuildAndRun();
+        
     private:
 
         void HandleUpdate(StringHash eventType, VariantMap& eventData);
 
         void HandleNETBuildResult(StringHash eventType, VariantMap& eventData);
+        void HandleNETBuildPlay(StringHash eventType, VariantMap& eventData);
 
         void HandleFileChanged(StringHash eventType, VariantMap& eventData);
         void HandleResourceAdded(StringHash eventType, VariantMap& eventData);
@@ -89,6 +93,8 @@ namespace ToolCore
 
         void Clear();
         void Initialize();
+        /// interrogate sources to see if any are younger than the editor dll
+        bool CheckForRebuild();
 
         String idePath_;