Browse Source

Merge pull request #1496 from AtomicGameEngine/JME-ATOMIC-1199

[ToolCore] Adding project cache clean/generate command, some refactoring
JoshEngebretson 8 years ago
parent
commit
fc5f4819f1

+ 5 - 33
Source/AtomicTool/AtomicTool.cpp

@@ -223,47 +223,19 @@ void AtomicTool::Start()
 
 
     if (cmd->RequiresProjectLoad())
     if (cmd->RequiresProjectLoad())
     {
     {
-        FileSystem* fileSystem = GetSubsystem<FileSystem>();
-
-        String projectPath = cmd->GetProjectPath();
-            
-        // default to current directly if command doesn't provide the path
-        if (!projectPath.Length())
-            projectPath = fileSystem->GetCurrentDir();
-
-        String projectFile;
-        if (projectPath.EndsWith(".atomic", false))
+        if (!cmd->LoadProject())
         {
         {
-            projectFile = projectPath;
-            projectPath = GetPath(projectPath);
-        }
-        else
-        {
-            Vector<String> projectFiles;
-            fileSystem->ScanDir(projectFiles, projectPath, "*.atomic", SCAN_FILES, false);
-            if (!projectFiles.Size())
-            {
-                ErrorExit(ToString("No .atomic project file in %s", projectPath.CString()));
-                return;
-            }
-            else if (projectFiles.Size() > 1)
-            {
-                ErrorExit(ToString("Multiple .atomic project files found in %s", projectPath.CString()));
-                return;
-            }
-            projectFile = projectPath + "/" + projectFiles[0];
+            ErrorExit(ToString("Failed to load project: %s", cmd->GetProjectPath().CString()));
+            return;
         }
         }
 
 
-        if (!tsystem->LoadProject(projectFile))
-        {
-            //ErrorExit(ToString("Failed to load project: %s", projectFile.CString()));
-            //return;
-        }
+        String projectPath = cmd->GetProjectPath();
 
 
         // Set the build path
         // Set the build path
         String buildFolder = projectPath + "/" + "Build";
         String buildFolder = projectPath + "/" + "Build";
         buildSystem->SetBuildPath(buildFolder);
         buildSystem->SetBuildPath(buildFolder);
 
 
+        FileSystem* fileSystem = GetSubsystem<FileSystem>();
         if (!fileSystem->DirExists(buildFolder))
         if (!fileSystem->DirExists(buildFolder))
         {
         {
             fileSystem->CreateDir(buildFolder);
             fileSystem->CreateDir(buildFolder);

+ 75 - 11
Source/ToolCore/Assets/AssetDatabase.cpp

@@ -44,7 +44,8 @@ namespace ToolCore
 
 
 AssetDatabase::AssetDatabase(Context* context) : Object(context),
 AssetDatabase::AssetDatabase(Context* context) : Object(context),
     assetScanDepth_(0),
     assetScanDepth_(0),
-    assetScanImport_(false)
+    assetScanImport_(false),
+    cacheEnabled_(true)
 {
 {
     SubscribeToEvent(E_LOADFAILED, ATOMIC_HANDLER(AssetDatabase, HandleResourceLoadFailed));
     SubscribeToEvent(E_LOADFAILED, ATOMIC_HANDLER(AssetDatabase, HandleResourceLoadFailed));
     SubscribeToEvent(E_PROJECTLOADED, ATOMIC_HANDLER(AssetDatabase, HandleProjectLoaded));
     SubscribeToEvent(E_PROJECTLOADED, ATOMIC_HANDLER(AssetDatabase, HandleProjectLoaded));
@@ -536,15 +537,10 @@ void AssetDatabase::HandleProjectLoaded(StringHash eventType, VariantMap& eventD
 
 
     ReadImportConfig();
     ReadImportConfig();
 
 
-    FileSystem* fs = GetSubsystem<FileSystem>();
-
-    if (!fs->DirExists(GetCachePath()))
-        fs->CreateDir(GetCachePath());
-
-    ResourceCache* cache = GetSubsystem<ResourceCache>();
-    cache->AddResourceDir(GetCachePath());
-
-    Scan();
+    if (cacheEnabled_)
+    {
+        InitCache();
+    }
 
 
     SubscribeToEvent(E_FILECHANGED, ATOMIC_HANDLER(AssetDatabase, HandleFileChanged));
     SubscribeToEvent(E_FILECHANGED, ATOMIC_HANDLER(AssetDatabase, HandleFileChanged));
 }
 }
@@ -594,7 +590,6 @@ void AssetDatabase::HandleResourceLoadFailed(StringHash eventType, VariantMap& e
     evData[AssetImportError::P_ERROR] = ToString("Asset %s Failed to Load", asset->path_.CString());
     evData[AssetImportError::P_ERROR] = ToString("Asset %s Failed to Load", asset->path_.CString());
     SendEvent(E_ASSETIMPORTERROR, evData);
     SendEvent(E_ASSETIMPORTERROR, evData);
 
 
-
 }
 }
 
 
 void AssetDatabase::HandleFileChanged(StringHash eventType, VariantMap& eventData)
 void AssetDatabase::HandleFileChanged(StringHash eventType, VariantMap& eventData)
@@ -704,4 +699,73 @@ void AssetDatabase::ReimportAllAssetsInDirectory(const String& directoryPath)
 }
 }
 
 
 
 
+bool AssetDatabase::InitCache()
+{
+    FileSystem* fs = GetSubsystem<FileSystem>();
+
+    if (!fs->DirExists(GetCachePath()))
+        fs->CreateDir(GetCachePath());
+
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    cache->AddResourceDir(GetCachePath());
+
+    Scan();
+
+    return true;
+}
+
+bool AssetDatabase::CleanCache()
+{
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+
+    String cachePath = GetCachePath();
+
+    if (fileSystem->DirExists(cachePath))
+    {
+        ATOMIC_LOGINFOF("Cleaning cache directory %s", cachePath.CString());
+
+        fileSystem->RemoveDir(cachePath, true);
+
+        if (fileSystem->DirExists(cachePath))
+        {
+            ATOMIC_LOGERRORF("Unable to remove cache directory %s", cachePath.CString());
+            return false;
+        }
+    }
+
+    fileSystem->CreateDir(cachePath);
+
+    if (!fileSystem->DirExists(cachePath))
+    {
+        ATOMIC_LOGERRORF("Unable to create cache directory %s", cachePath.CString());
+        return false;
+    }
+
+    return true;
+
+}
+
+bool AssetDatabase::GenerateCache(bool clean)
+{
+    ATOMIC_LOGINFO("Generating cache... hold on");
+
+    if (clean)
+    {
+        if (!CleanCache())
+            return false;
+    }
+
+    ReimportAllAssets();
+
+    ATOMIC_LOGINFO("Cache generated");
+
+    return true;
+
+}
+
+void AssetDatabase::SetCacheEnabled(bool cacheEnabled)
+{
+    cacheEnabled_ = cacheEnabled;
+}
+
 }
 }

+ 17 - 0
Source/ToolCore/Assets/AssetDatabase.h

@@ -51,6 +51,18 @@ public:
 
 
     String GetCachePath();
     String GetCachePath();
 
 
+    /// Get whether the asset cache is enabled
+    bool GetCacheEnabled() const { return cacheEnabled_; }
+
+    /// Set whether the asset cache is enabled 
+    void SetCacheEnabled(bool cacheEnabled);
+
+    /// Cleans the asset Cache folder by removing and recreating it
+    bool CleanCache();
+
+    /// Regenerates the asset cache, clean removes the Cache folder before generating
+    bool GenerateCache(bool clean = true);
+
     void DeleteAsset(Asset* asset);
     void DeleteAsset(Asset* asset);
 
 
     void Scan();
     void Scan();
@@ -85,6 +97,9 @@ private:
     bool ImportDirtyAssets();
     bool ImportDirtyAssets();
     void PreloadAssets();
     void PreloadAssets();
 
 
+    // internal method that initializes project asset cache
+    bool InitCache();
+
     // Update mapping of asset paths to cache file representations, by type
     // Update mapping of asset paths to cache file representations, by type
     void UpdateAssetCacheMap();
     void UpdateAssetCacheMap();
 
 
@@ -102,6 +117,8 @@ private:
     // Whether any asset was imported during scan
     // Whether any asset was imported during scan
     bool assetScanImport_;
     bool assetScanImport_;
 
 
+    bool cacheEnabled_;
+
 };
 };
 
 
 }
 }

+ 1 - 1
Source/ToolCore/Command/BindCmd.cpp

@@ -45,7 +45,7 @@ BindCmd::~BindCmd()
 
 
 }
 }
 
 
-bool BindCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+bool BindCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
 {
     String argument = arguments[startIndex].ToLower();
     String argument = arguments[startIndex].ToLower();
     sourceRootFolder_ = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
     sourceRootFolder_ = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;

+ 4 - 2
Source/ToolCore/Command/BindCmd.h

@@ -38,12 +38,14 @@ public:
     BindCmd(Context* context);
     BindCmd(Context* context);
     virtual ~BindCmd();
     virtual ~BindCmd();
 
 
-    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
-
     void Run();
     void Run();
 
 
     bool RequiresProjectLoad() { return false; }
     bool RequiresProjectLoad() { return false; }
 
 
+protected:
+
+    bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
 private:
 private:
 
 
     String sourceRootFolder_;
     String sourceRootFolder_;

+ 1 - 1
Source/ToolCore/Command/BuildCmd.cpp

@@ -46,7 +46,7 @@ BuildCmd::~BuildCmd()
 
 
 }
 }
 
 
-bool BuildCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+bool BuildCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
 {
     String argument = arguments[startIndex].ToLower();
     String argument = arguments[startIndex].ToLower();
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;

+ 4 - 2
Source/ToolCore/Command/BuildCmd.h

@@ -38,10 +38,12 @@ public:
     BuildCmd(Context* context);
     BuildCmd(Context* context);
     virtual ~BuildCmd();
     virtual ~BuildCmd();
 
 
-    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
-
     void Run();
     void Run();
 
 
+protected:
+
+    bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
 private:
 private:
 
 
     void HandleBuildComplete(StringHash eventType, VariantMap& eventData);
     void HandleBuildComplete(StringHash eventType, VariantMap& eventData);

+ 103 - 0
Source/ToolCore/Command/CacheCmd.cpp

@@ -0,0 +1,103 @@
+//
+// Copyright (c) 2014-2017 THUNDERBEAST GAMES LLC
+//
+// 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 <Atomic/Core/StringUtils.h>
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+
+#include "../Assets/AssetDatabase.h"
+#include "../ToolSystem.h"
+#include "../ToolEnvironment.h"
+#include "../Project/Project.h"
+#include "../Build/BuildEvents.h"
+#include "../Build/BuildSystem.h"
+
+#include "CacheCmd.h"
+
+namespace ToolCore
+{
+
+CacheCmd::CacheCmd(Context* context) : Command(context),
+    cleanCache_(false),
+    generateCache_(false)
+{
+    // We disable the AssetDatabase cache, as will be cleaning, regenerating, etc
+    GetSubsystem<AssetDatabase>()->SetCacheEnabled(false);
+}
+
+CacheCmd::~CacheCmd()
+{
+
+}
+
+bool CacheCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+{
+    for (unsigned i = startIndex; i < arguments.Size(); i++)
+    {
+        if (arguments[i].Length() > 1)
+        {
+            String argument = arguments[i].ToLower();
+
+            if (argument == "generate")
+            {
+                generateCache_ = true;
+                continue;
+            }
+
+            // process any argument/value pairs
+            if (arguments[i][0] != '-')
+                continue;
+
+            // eat additonal argument '-'
+            while (argument.StartsWith("-"))
+            {
+                argument.Erase(0);
+            }
+
+            String value = i + 1 < arguments.Size() ? arguments[i + 1] : String::EMPTY;
+
+            if (argument == "clean")
+                cleanCache_ = true;
+
+        }
+    }
+
+    return true;
+}
+
+void CacheCmd::Run()
+{
+    AssetDatabase* database = GetSubsystem<AssetDatabase>();
+    
+    if (generateCache_)
+    {
+        database->GenerateCache(cleanCache_);
+    }
+    else if (cleanCache_)
+    {
+        database->CleanCache();
+    }
+
+    Finished();
+}
+
+}

+ 69 - 0
Source/ToolCore/Command/CacheCmd.h

@@ -0,0 +1,69 @@
+//
+// Copyright (c) 2014-2017 THUNDERBEAST GAMES LLC
+//
+// 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 "Command.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+
+/// Command for cleaning and regenerating a Project resource cache
+class CacheCmd: public Command
+{
+
+    /// Example usage:
+    /// AtomicTool cache --clean --project C:\Path\To\MyProject (cleans cache folder)
+    /// AtomicTool cache generate --project C:\Path\To\MyProject (regenerates the project cache)
+    /// AtomicTool cache generate --clean --project C:\Path\To\MyProject (cleans and then regenerates the project cache)
+
+    ATOMIC_OBJECT(CacheCmd, Command)
+
+public:
+
+    CacheCmd(Context* context);
+    virtual ~CacheCmd();
+
+    void Run();
+
+protected:
+
+    bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
+private:
+
+    bool CreateCacheDirectory() const;
+    bool RemoveCacheDirectory() const;
+
+    bool CleanCache() const;
+
+    bool GenerateCache() const;
+
+    bool cleanCache_;
+    bool generateCache_;
+
+};
+
+}

+ 82 - 4
Source/ToolCore/Command/Command.cpp

@@ -20,6 +20,8 @@
 // THE SOFTWARE.
 // THE SOFTWARE.
 //
 //
 
 
+#include <Atomic/IO/Log.h>
+
 #include "../ToolSystem.h"
 #include "../ToolSystem.h"
 #include "../Project/Project.h"
 #include "../Project/Project.h"
 
 
@@ -39,12 +41,88 @@ Command::~Command()
 
 
 }
 }
 
 
-bool Command::Parse(const String& command)
+bool Command::LoadProject()
+{
+    if (!projectPath_.Length())
+        return false;
+
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+
+    // default to current directly if command doesn't provide the path
+    if (!projectPath_.Length())
+        projectPath_ = fileSystem->GetCurrentDir();
+
+    String projectFile;
+    if (projectPath_.EndsWith(".atomic", false))
+    {
+        projectFile = projectPath_;
+        projectPath_ = GetPath(projectPath_);
+    }
+    else
+    {
+        Vector<String> projectFiles;
+        fileSystem->ScanDir(projectFiles, projectPath_, "*.atomic", SCAN_FILES, false);
+        if (!projectFiles.Size())
+        {
+            ATOMIC_LOGERRORF("No .atomic project file in %s", projectPath_.CString());
+            return false;
+        }
+        else if (projectFiles.Size() > 1)
+        {
+            ATOMIC_LOGERRORF("Multiple .atomic project files found in %s", projectPath_.CString());
+            return false;
+        }
+        projectFile = projectPath_ + "/" + projectFiles[0];
+    }
+
+    ToolSystem* tsystem = GetSubsystem<ToolSystem>();
+
+    if (!tsystem->LoadProject(projectFile))
+    {
+        ATOMIC_LOGERRORF("Failed to load project: %s", projectFile.CString());
+        return false;
+    }
+
+    return true;
+
+}
+
+void Command::ParseCommonArguments(const Vector<String> &arguments, String &errorMsg)
+{
+    for (unsigned i = 0; i < arguments.Size(); ++i)
+    {
+        if (arguments[i].Length() > 1 && arguments[i][0] == '-')
+        {
+            String argument = arguments[i].Substring(1).ToLower();
+            String value = i + 1 < arguments.Size() ? arguments[i + 1] : String::EMPTY;
+
+            // eat additonal argument '-'
+            while (argument.StartsWith("-"))
+            {
+                argument.Erase(0);
+            }
+
+            if (argument == "project" && value.Length())
+            {
+                projectPath_ = value;
+            }
+        }
+    }
+
+}
+
+bool Command::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
 {
-    Vector<String> args = command.Split(' ');
-    String errorMsg;
+    errorMsg = String::EMPTY;
+
+    ParseCommonArguments(arguments, errorMsg);
+
+    if (errorMsg.Length())
+    {
+        return false;
+    }
 
 
-    return Parse(args, 0, errorMsg);
+    return ParseInternal(arguments, startIndex, errorMsg);
 }
 }
 
 
 void Command::Error(const String& errorMsg)
 void Command::Error(const String& errorMsg)

+ 15 - 6
Source/ToolCore/Command/Command.h

@@ -49,9 +49,8 @@ public:
     Command(Context* context);
     Command(Context* context);
     virtual ~Command();
     virtual ~Command();
 
 
-    bool Parse(const String& command);
-
-    virtual bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg) = 0;
+    /// Parse a command from given arguments and startIndex, return false on failure with errorMsg set
+    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
 
 
     virtual void Run() = 0;
     virtual void Run() = 0;
 
 
@@ -63,13 +62,23 @@ public:
 
 
     virtual bool RequiresProjectLoad() { return true; }
     virtual bool RequiresProjectLoad() { return true; }
 
 
-    virtual const String& GetProjectPath() const { return String::EMPTY; }
+    /// Loads project into ToolSystem returning true on success
+    bool LoadProject();
+
+    /// Returns the project path specified by the --project common argument
+    virtual const String& GetProjectPath() const { return projectPath_; }
 
 
     virtual bool RequiresLicenseValidation() { return false; }
     virtual bool RequiresLicenseValidation() { return false; }
 
 
-private:
+protected:
+
+    virtual bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg) = 0;
+
+    void ParseCommonArguments(const Vector<String>& arguments, String &errorMsg);
+
+    float timeOut_;    
 
 
-    float timeOut_;
+    String projectPath_;
 
 
 };
 };
 
 

+ 5 - 0
Source/ToolCore/Command/CommandParser.cpp

@@ -30,6 +30,7 @@
 #include "BindCmd.h"
 #include "BindCmd.h"
 #include "NETCmd.h"
 #include "NETCmd.h"
 #include "ProjectCmd.h"
 #include "ProjectCmd.h"
+#include "CacheCmd.h"
 
 
 namespace ToolCore
 namespace ToolCore
 {
 {
@@ -86,6 +87,10 @@ Command* CommandParser::Parse(const Vector<String>& arguments)
             {
             {
                 cmd = new ProjectCmd(context_);
                 cmd = new ProjectCmd(context_);
             }
             }
+            else if (argument == "cache")
+            {
+                cmd = new CacheCmd(context_);
+            }
 
 
         }
         }
 
 

+ 1 - 1
Source/ToolCore/Command/EditCmd.cpp

@@ -47,7 +47,7 @@ EditCmd::~EditCmd()
 
 
 }
 }
 
 
-bool EditCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+bool EditCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
 {
     String argument = arguments[startIndex].ToLower();
     String argument = arguments[startIndex].ToLower();
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;

+ 5 - 3
Source/ToolCore/Command/EditCmd.h

@@ -36,12 +36,14 @@ class EditCmd: public Command
 public:
 public:
 
 
     EditCmd(Context* context);
     EditCmd(Context* context);
-    virtual ~EditCmd();
-
-    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+    virtual ~EditCmd();    
 
 
     void Run();
     void Run();
 
 
+protected:
+
+    bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
 private:
 private:
 
 
     bool LaunchEditorProcess(const String& command, const Vector<String>& args, const String& initialDirectory);
     bool LaunchEditorProcess(const String& command, const Vector<String>& args, const String& initialDirectory);

+ 1 - 1
Source/ToolCore/Command/ImportCmd.cpp

@@ -48,7 +48,7 @@ ImportCmd::~ImportCmd()
 
 
 }
 }
 
 
-bool ImportCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+bool ImportCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
 {
     String argument = arguments[startIndex].ToLower();
     String argument = arguments[startIndex].ToLower();
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;

+ 4 - 1
Source/ToolCore/Command/ImportCmd.h

@@ -38,11 +38,14 @@ public:
     ImportCmd(Context* context);
     ImportCmd(Context* context);
     virtual ~ImportCmd();
     virtual ~ImportCmd();
 
 
-    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
     void Run();
     void Run();
 
 
     bool RequiresProjectLoad() { return true; }
     bool RequiresProjectLoad() { return true; }
 
 
+protected:
+
+    bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
 private:
 private:
 
 
     String assetFilename_;
     String assetFilename_;

+ 1 - 1
Source/ToolCore/Command/NETCmd.cpp

@@ -56,7 +56,7 @@ NETCmd::~NETCmd()
 
 
 }
 }
 
 
-bool NETCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+bool NETCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
 {
     String argument = arguments[startIndex].ToLower();
     String argument = arguments[startIndex].ToLower();
     command_ = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1].ToLower() : String::EMPTY;
     command_ = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1].ToLower() : String::EMPTY;

+ 4 - 5
Source/ToolCore/Command/NETCmd.h

@@ -42,23 +42,22 @@ public:
     NETCmd(Context* context);
     NETCmd(Context* context);
     virtual ~NETCmd();
     virtual ~NETCmd();
 
 
-    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
-
     void Run();
     void Run();
 
 
     bool RequiresProjectLoad() { return requiresProjectLoad_; }
     bool RequiresProjectLoad() { return requiresProjectLoad_; }
 
 
     const String& GetProjectPath() const { return projectPath_; }
     const String& GetProjectPath() const { return projectPath_; }
 
 
+protected:
+
+    bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
 private:
 private:
 
 
     void HandleNETBuildResult(StringHash eventType, VariantMap& eventData);
     void HandleNETBuildResult(StringHash eventType, VariantMap& eventData);
 
 
     String command_;
     String command_;
 
 
-    // genresources command
-    String projectPath_;
-
     // parse command
     // parse command
     String assemblyPath_;
     String assemblyPath_;
 
 

+ 1 - 1
Source/ToolCore/Command/NewProjectCmd.cpp

@@ -44,7 +44,7 @@ NewProjectCmd::~NewProjectCmd()
 
 
 }
 }
 
 
-bool NewProjectCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+bool NewProjectCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
 {
     String argument = arguments[startIndex].ToLower();
     String argument = arguments[startIndex].ToLower();
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;

+ 4 - 2
Source/ToolCore/Command/NewProjectCmd.h

@@ -38,12 +38,14 @@ public:
     NewProjectCmd(Context* context);
     NewProjectCmd(Context* context);
     virtual ~NewProjectCmd();
     virtual ~NewProjectCmd();
 
 
-    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
-
     void Run();
     void Run();
 
 
     bool RequiresProjectLoad() { return false; }
     bool RequiresProjectLoad() { return false; }
 
 
+protected:
+
+    bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
 private:
 private:
 
 
     String projectPath_;
     String projectPath_;

+ 1 - 1
Source/ToolCore/Command/PlayCmd.cpp

@@ -47,7 +47,7 @@ PlayCmd::~PlayCmd()
 
 
 }
 }
 
 
-bool PlayCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+bool PlayCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
 {
     String argument = arguments[startIndex].ToLower();
     String argument = arguments[startIndex].ToLower();
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;

+ 5 - 3
Source/ToolCore/Command/PlayCmd.h

@@ -36,12 +36,14 @@ class PlayCmd: public Command
 public:
 public:
 
 
     PlayCmd(Context* context);
     PlayCmd(Context* context);
-    virtual ~PlayCmd();
-
-    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+    virtual ~PlayCmd();    
 
 
     void Run();
     void Run();
 
 
+protected:
+
+    bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
+
 private:
 private:
 
 
     bool LaunchPlayerProcess(const String& command, const Vector<String>& args, const String& initialDirectory);
     bool LaunchPlayerProcess(const String& command, const Vector<String>& args, const String& initialDirectory);

+ 1 - 1
Source/ToolCore/Command/ProjectCmd.cpp

@@ -52,7 +52,7 @@ ProjectCmd::~ProjectCmd()
 }
 }
 
 
 // usage: project <projectPath> [cache (-clean)]
 // usage: project <projectPath> [cache (-clean)]
-bool ProjectCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
+bool ProjectCmd::ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
 {
     String argument = arguments[startIndex].ToLower();
     String argument = arguments[startIndex].ToLower();
     if (argument != "project")
     if (argument != "project")

+ 5 - 6
Source/ToolCore/Command/ProjectCmd.h

@@ -31,27 +31,26 @@ namespace ToolCore
 
 
 class ProjectCmd: public Command
 class ProjectCmd: public Command
 {
 {
-    ATOMIC_OBJECT(ProjectCmd, Command);
+    ATOMIC_OBJECT(ProjectCmd, Command)
 
 
 public:
 public:
 
 
     ProjectCmd(Context* context);
     ProjectCmd(Context* context);
     virtual ~ProjectCmd();
     virtual ~ProjectCmd();
 
 
-    bool Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
-
     void Run();
     void Run();
 
 
-    bool RequiresProjectLoad() { return requiresProjectLoad_; }
+    bool RequiresProjectLoad() { return requiresProjectLoad_; }    
+
+protected:
 
 
-    const String& GetProjectPath() const { return projectPath_; }
+    bool ParseInternal(const Vector<String>& arguments, unsigned startIndex, String& errorMsg);
 
 
 private:
 private:
 
 
     void HandleProjectBeginLoad(StringHash eventType, VariantMap& eventData);
     void HandleProjectBeginLoad(StringHash eventType, VariantMap& eventData);
     void HandleProjectLoaded(StringHash eventType, VariantMap& eventData);
     void HandleProjectLoaded(StringHash eventType, VariantMap& eventData);
 
 
-    String projectPath_;
     String command_;
     String command_;
     bool requiresProjectLoad_;
     bool requiresProjectLoad_;
     int options_;
     int options_;