Prechádzať zdrojové kódy

Merge pull request #922 from AtomicGameEngine/JME-ATOMIC-AssetBuildConfiguration

Selective deployment configuration
JoshEngebretson 9 rokov pred
rodič
commit
ec68c357c2

+ 4 - 2
Source/Atomic/IO/File.cpp

@@ -43,7 +43,8 @@ static const wchar_t* openMode[] =
     L"rb",
     L"wb",
     L"r+b",
-    L"w+b"
+    L"w+b",
+    L"a+b"
 };
 #else
 static const char* openMode[] =
@@ -51,7 +52,8 @@ static const char* openMode[] =
     "rb",
     "wb",
     "r+b",
-    "w+b"
+    "w+b",
+    "a+b"
 };
 #endif
 

+ 3 - 1
Source/Atomic/IO/File.h

@@ -52,7 +52,9 @@ enum FileMode
 {
     FILE_READ = 0,
     FILE_WRITE,
-    FILE_READWRITE
+    FILE_READWRITE,
+    FILE_WRITE_UPDATE,
+    FILE_APPEND
 };
 
 class PackageFile;

+ 13 - 0
Source/Atomic/Resource/Configuration.cpp

@@ -62,6 +62,19 @@ namespace Atomic
         return value;
     }
 
+    void Configuration::GetArrayValue(const JSONArray & jarray, StringVector& value)
+    {
+        value.Clear();
+
+        for (JSONArray::ConstIterator it = jarray.Begin(); it != jarray.End(); it++)
+        {
+            if (it->IsString())
+            {
+                value.Push(it->GetString());
+            }
+        }
+
+    }
 
     Configuration::Configuration() :
         isLoaded_(false)

+ 1 - 3
Source/Atomic/Resource/Configuration.h

@@ -51,6 +51,7 @@ protected:
     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 void GetArrayValue(const JSONArray& jarray, StringVector& value);
 
     virtual bool LoadDesktopConfig(JSONValue root) { return true; };
 
@@ -61,6 +62,3 @@ private:
     bool isLoaded_;
 };
 }
-
-
-

+ 71 - 0
Source/ToolCore/Build/AssetBuildConfig.cpp

@@ -0,0 +1,71 @@
+//
+// 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 "../../Atomic/Core/Context.h"
+#include "../../Atomic/IO/Log.h"
+#include "../../Atomic/IO/File.h"
+#include "../../Atomic/IO/FileSystem.h"
+#include "../Atomic/Resource/JSONFile.h"
+#include "../../Atomic/Graphics/GraphicsDefs.h"
+#include "AssetBuildConfig.h"
+
+namespace Atomic
+{
+    AssetBuildConfig AssetBuildConfig::assetBuildConfig_;
+
+    bool AssetBuildConfig::LoadAssetBuildTagArray(const JSONArray& tags)
+    {
+        if (tags.Empty())
+            return false;
+
+        for (auto it = tags.Begin(); it < tags.End(); ++it)
+        {
+            const JSONObject& resourceTag = (*it).GetObject();
+
+            String tag = resourceTag["Tag"]->GetString();
+
+            const JSONArray& resources = resourceTag["Resources"]->GetArray();
+
+            StringVector value;
+            GetArrayValue(resources, value);
+            valueMap_[tag.CString()] = value;
+        }
+
+        return true;
+    }
+
+    bool AssetBuildConfig::LoadDesktopConfig(JSONValue root)
+    {
+        const JSONValue& assetBuildConfigRoot = root["AssetBuildConfig"];
+
+        if (!assetBuildConfigRoot.IsArray())
+            return false;
+
+        const JSONArray& assetTags = assetBuildConfigRoot.GetArray();
+
+        if (!assetTags.Empty())
+            LoadAssetBuildTagArray(assetTags);
+
+        return true;
+    }
+
+}

+ 54 - 0
Source/ToolCore/Build/AssetBuildConfig.h

@@ -0,0 +1,54 @@
+//
+// 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 "../../Atomic/Core/Variant.h"
+#include "../../Atomic/Resource/JSONValue.h"
+#include "../../Atomic/Resource/Configuration.h"
+
+namespace Atomic
+{
+    class Context;
+
+    class AssetBuildConfig :
+        Configuration
+    {
+
+    public:
+
+        static bool LoadFromFile(Context* context, const String& filename) { return assetBuildConfig_.Configuration::LoadFromFile(context, filename); }
+        static bool LoadFromJSON(const String& json) { return assetBuildConfig_.Configuration::LoadFromJSON(json); }
+
+        /// Apply the configuration to a setting variant map, values that exist will not be overriden
+        static void ApplyConfig(VariantMap& settings, bool overwrite = false) { return assetBuildConfig_.Configuration::ApplyConfig(settings, overwrite); }
+
+        static const bool IsLoaded() { return assetBuildConfig_.Configuration::IsLoaded(); }
+
+    private:
+
+        virtual bool LoadDesktopConfig(JSONValue root);
+        bool LoadAssetBuildTagArray(const JSONArray& tags);
+
+        static AssetBuildConfig assetBuildConfig_;
+    };
+}

+ 9 - 4
Source/ToolCore/Build/BuildAndroid.cpp

@@ -31,6 +31,7 @@
 #include "../Project/Project.h"
 #include "../Project/ProjectBuildSettings.h"
 #include "../Platform/PlatformAndroid.h"
+#include "../Assets/AssetDatabase.h"
 
 #include "AndroidProjectGenerator.h"
 
@@ -317,18 +318,22 @@ void BuildAndroid::Initialize()
 
     Vector<String> defaultResourcePaths;
     GetDefaultResourcePaths(defaultResourcePaths);
-    String projectResources = project->GetResourcePath();
+    
 
     for (unsigned i = 0; i < defaultResourcePaths.Size(); i++)
     {
         AddResourceDir(defaultResourcePaths[i]);
     }
+    BuildDefaultResourceEntries();
 
     // TODO: smart filtering of cache
-    AddResourceDir(project->GetProjectPath() + "Cache/");
-    AddResourceDir(projectResources);
+    String projectResources = project->GetResourcePath();
+    AddProjectResourceDir(projectResources);
+    AssetDatabase* db = GetSubsystem<AssetDatabase>();
+    String cachePath = db->GetCachePath();
+    AddProjectResourceDir(cachePath);
 
-    BuildResourceEntries();
+    BuildProjectResourceEntries();
 }
 
 void BuildAndroid::Build(const String& buildPath)

+ 280 - 35
Source/ToolCore/Build/BuildBase.cpp

@@ -23,29 +23,37 @@
 
 #include <Atomic/IO/Log.h>
 #include <Atomic/IO/FileSystem.h>
+#include <Atomic/Resource/JSONFile.h>
 
 #include "../Subprocess/SubprocessSystem.h"
 #include "../Project/Project.h"
 #include "../ToolEnvironment.h"
+#include "../Assets/Asset.h"
+#include "../Assets/AssetDatabase.h"
 
 #include "BuildSystem.h"
 #include "BuildEvents.h"
 #include "BuildBase.h"
 #include "ResourcePackager.h"
+#include "AssetBuildConfig.h"
 
 namespace ToolCore
 {
 
 BuildBase::BuildBase(Context * context, Project* project, PlatformID platform) : Object(context),
     platformID_(platform),
+    project_(project),
     containsMDL_(false),
-    buildFailed_(false)
+    buildFailed_(false),
+    assetBuildTag_(String::EMPTY),
+    fileIncludedResourcesLog_(nullptr)
 {
     if (UseResourcePackager())
         resourcePackager_ = new ResourcePackager(context, this);
 
-    project_ = project;
+    fileIncludedResourcesLog_ = new File(context_, "BuildIncludedResources.log", Atomic::FILE_WRITE);
 
+    ReadAssetBuildConfig();
 }
 
 BuildBase::~BuildBase()
@@ -54,6 +62,9 @@ BuildBase::~BuildBase()
     {
         delete resourceEntries_[i];
     }
+
+    fileIncludedResourcesLog_->Close();
+    delete fileIncludedResourcesLog_;
 }
 
 #ifdef ATOMIC_PLATFORM_WINDOWS
@@ -277,10 +288,8 @@ void BuildBase::FailBuild(const String& message)
 
     BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
     buildSystem->BuildComplete(platformID_, buildPath_, false, message);
-
 }
 
-
 void BuildBase::HandleSubprocessOutputEvent(StringHash eventType, VariantMap& eventData)
 {
     // E_SUBPROCESSOUTPUT
@@ -307,67 +316,279 @@ String BuildBase::GetSettingsDirectory()
     return project_->GetProjectPath() + "/Settings";
 }
 
-void BuildBase::ScanResourceDirectory(const String& resourceDir)
+void BuildBase::BuildDefaultResourceEntries()
 {
-    Vector<String> fileNames;
+    String buildLogOutput(String::EMPTY);
+
+    for (unsigned i = 0; i < resourceDirs_.Size(); i++)
+    {
+        String resourceDir = resourceDirs_[i];
+        fileIncludedResourcesLog_->WriteLine("\nBuildBase::BuildDefaultResourceEntries - Default resources being included from: " + resourceDir);
+
+        Vector<String> fileNames;
+        FileSystem* fileSystem = GetSubsystem<FileSystem>();
+        fileSystem->ScanDir(fileNames, resourceDir, "*.*", SCAN_FILES, true);
+
+        for (unsigned i = 0; i < fileNames.Size(); i++)
+        {
+            const String& filename = fileNames[i];
+
+            AddToResourcePackager(filename, resourceDir);
+        }
+    }
+}
+
+void BuildBase::BuildProjectResourceEntries()
+{
+    String buildLogOutput(String::EMPTY);
+
+    if (AssetBuildConfig::IsLoaded())
+    {
+        buildLogOutput += "\nBaseBuild::BuildProjectResourceEntries - ./Settings/AssetBuildConfig.json found. ";
+        if (!assetBuildTag_.Empty())
+        {
+            buildLogOutput += "Using build-tag parameter :  " + assetBuildTag_;
+            fileIncludedResourcesLog_->WriteLine(buildLogOutput);
+
+            BuildFilteredProjectResourceEntries();
+            return;
+        }
+        buildLogOutput += "No build-tag parameter used.";
+    }
+    buildLogOutput += "\nBaseBuild::BuildProjectResourceEntries - No custom asset include configuration being used - ";
+    buildLogOutput += "AssetBuildConfig.json not loaded, OR no build-tag parameter used.";
+    fileIncludedResourcesLog_->WriteLine(buildLogOutput);
+
+    BuildAllProjectResourceEntries();
+}
+
+void BuildBase::BuildAllProjectResourceEntries()
+{
+    for (unsigned i = 0; i < projectResourceDir_.Size(); i++)
+    {
+        String projectResourceDir = projectResourceDir_[i];
+        fileIncludedResourcesLog_->WriteLine("\nBuildBase::BuildAllProjectResourceEntries - Project resources being included from: " + projectResourceDir);
+
+        Vector<String> fileNamesInProject;
+        FileSystem* fileSystem = GetSubsystem<FileSystem>();
+        fileSystem->ScanDir(fileNamesInProject, projectResourceDir, "*.*", SCAN_FILES, true);
+
+        for (unsigned i = 0; i < fileNamesInProject.Size(); i++)
+        {
+            AddToResourcePackager(fileNamesInProject[i], projectResourceDir);
+        }
+    }
+}
+
+void BuildBase::BuildFilteredProjectResourceEntries()
+{
+    // Loading up the AssetBuildConfig.json,
+    // obtaining a list of files to include in the build.
+    VariantMap resourceTags;
+    AssetBuildConfig::ApplyConfig(resourceTags);
+    Vector<String> assetBuildConfigFiles;
+    VariantMap::ConstIterator itr = resourceTags.Begin();
+
+    while (itr != resourceTags.End())
+    {
+        if (itr->first_ == assetBuildTag_)
+        {
+            assetBuildConfigFiles = itr->second_.GetStringVector();
+            for (unsigned i = 0; i < assetBuildConfigFiles.Size(); ++i)
+            {
+                // remove case sensitivity
+                assetBuildConfigFiles[i] = assetBuildConfigFiles[i].ToLower();
+            }
+            break;
+        }
+
+        itr++;
+        if (itr == resourceTags.End())
+        {
+            LOGERRORF("BuildBase::BuildFilteredProjectResourceEntries - Asset build-tag \"%s\" not defined in ./Settings/AssetBuildConfig.json", assetBuildTag_.CString());
+        }
+    }
+
+    // find any folders defined in assetbuildconfig.json, and add the non-".asset" files in them.
     FileSystem* fileSystem = GetSubsystem<FileSystem>();
-    fileSystem->ScanDir(fileNames, resourceDir, "*.*", SCAN_FILES, true);
+    Vector<String> filesInFolderToAdd;
 
-    for (unsigned i = 0; i < fileNames.Size(); i++)
+    for (unsigned i = 0; i < assetBuildConfigFiles.Size(); ++i)
     {
-        const String& filename = fileNames[i];
+        String &filename = assetBuildConfigFiles[i];
 
-        for (unsigned j = 0; j < resourceEntries_.Size(); j++)
+        if (GetExtension(filename) == String::EMPTY &&
+            fileSystem->DirExists(project_->GetResourcePath() + filename))
         {
-            const BuildResourceEntry* entry = resourceEntries_[j];
+            // rename 'filename' to 'folder' for context
+            String folder(filename);
 
-            if (entry->packagePath_ == filename)
+            // add a trailing slash if not defined
+            if (folder.Back() != '/')
+                folder = AddTrailingSlash(folder);
+
+            Vector<String> filesInFolder;
+            fileSystem->ScanDir(filesInFolder, project_->GetResourcePath() + folder, "*.*", SCAN_FILES, true);
+            for (unsigned j = 0; j < filesInFolder.Size(); ++j)
             {
-                BuildWarn(ToString("Resource Path: %s already exists", filename.CString()));
-                continue;
+                String path = filesInFolder[j];
+
+                // not interested in .asset files for now, will be included later.
+                if (GetExtension(path) != ".asset")
+                {
+                    filesInFolderToAdd.Push(folder + path.ToLower());
+                }
             }
         }
+    }
+    // add the files defined using a folder in AssetBuildConfig.json
+    for (unsigned i = 0; i < filesInFolderToAdd.Size(); ++i)
+    {
+        assetBuildConfigFiles.Push(filesInFolderToAdd[i]);
+    }
 
-        if (!CheckIncludeResourceFile(resourceDir, filename))
-            continue;
+    // check if the files in AssetBuildConfig.json exist,
+    // as well as their corresponding .asset file
+    Vector<String> filesInResourceFolder;
+    Vector<String> resourceFilesToInclude;
+    fileSystem->ScanDir(filesInResourceFolder, project_->GetResourcePath(), "*.*", SCAN_FILES, true);
+    for (unsigned j = 0; j < filesInResourceFolder.Size(); ++j)
+    {
+        // don't want to checks to be case sensitive
+        filesInResourceFolder[j] = filesInResourceFolder[j].ToLower();
+    }
 
-        BuildResourceEntry* newEntry = new BuildResourceEntry;
+    for (unsigned i = 0; i < assetBuildConfigFiles.Size(); ++i)
+    {
+        // .asset file is of primary importance since we used it to identify the associated cached file.
+        // without the .asset file the resource is removed from being included in the build.
 
-// BEGIN LICENSE MANAGEMENT
-        if (GetExtension(filename) == ".mdl")
+        // don't want checks to be case sensitive
+        String &filename = assetBuildConfigFiles[i];
+        if (filesInResourceFolder.Contains(filename) &&
+            filesInResourceFolder.Contains(filename + ".asset"))
         {
-            containsMDL_ = true;
+            resourceFilesToInclude.Push(filename);
+            resourceFilesToInclude.Push(filename + ".asset");
+            continue;
         }
-// END LICENSE MANAGEMENT
+        fileIncludedResourcesLog_->WriteLine("File " + filename + " ignored since it does not have an associated .asset file");
+    }
 
-        newEntry->absolutePath_ = resourceDir + filename;
-        newEntry->resourceDir_ = resourceDir;
+    // add valid files included from the AssetBuildConfig.json
+    for (StringVector::ConstIterator it = resourceFilesToInclude.Begin(); it != resourceFilesToInclude.End(); ++it)
+    {
+        AddToResourcePackager(*it, project_->GetResourcePath());
+    }
 
-        newEntry->packagePath_ = filename;
+    // Get associated cache GUID from the asset file
+    Vector<String> filesWithGUIDtoInclude;
+
+    for (StringVector::Iterator it = resourceFilesToInclude.Begin(); it != resourceFilesToInclude.End(); ++it)
+    {
+        String &filename = *it;
+        if (GetExtension(*it) == ".asset")
+        {
+            SharedPtr<File> file(new File(context_, project_->GetResourcePath() + *it));
+            SharedPtr<JSONFile> json(new JSONFile(context_));
+            json->Load(*file);
+            file->Close();
 
-        resourceEntries_.Push(newEntry);
+            JSONValue root = json->GetRoot();
+            int test = root.Get("version").GetInt();
+            assert(root.Get("version").GetInt() == ASSET_VERSION);
 
-        //LOGINFOF("Adding resource: %s : %s", newEntry->absolutePath_.CString(), newEntry->packagePath_.CString());
+            String guid = root.Get("guid").GetString();
+            filesWithGUIDtoInclude.Push(guid);
+        }
     }
-}
 
-void BuildBase::BuildResourceEntries()
-{
-    for (unsigned i = 0; i < resourceDirs_.Size(); i++)
+    // Obtain files in cache folder,
+    // Check if the file contains the guid, and add it to the cacheFilesToInclude
+    Vector<String> filesInCacheFolder;
+    Vector<String> cacheFilesToInclude;
+    AssetDatabase* db = GetSubsystem<AssetDatabase>();
+    String cachePath = db->GetCachePath();
+    fileSystem->ScanDir(filesInCacheFolder, cachePath, "*.*", SCAN_FILES, false);
+    for (unsigned i = 0; i < filesWithGUIDtoInclude.Size(); ++i)
     {
-        ScanResourceDirectory(resourceDirs_[i]);
+        String &guid = filesWithGUIDtoInclude[i];
+        for (unsigned j = 0; j < filesInCacheFolder.Size(); ++j)
+        {
+            const String &filename = GetFileName(filesInCacheFolder[j]);
+            String &filenamePath = filesInCacheFolder[j];
+            if (filename.Contains(guid))
+            {
+                cacheFilesToInclude.Push(filesInCacheFolder[j]);
+                // do not continue...
+                // there might be multiple files with the same guid having an guid_animaiton extention.
+            }
+        }
     }
 
-    if (resourcePackager_.NotNull())
+    // include a texture file's cached .dds file when building in windows
+#ifdef ATOMIC_PLATFORM_DESKTOP
+    for (StringVector::ConstIterator it = resourceFilesToInclude.Begin(); it != resourceFilesToInclude.End(); ++it)
     {
-        for (unsigned i = 0; i < resourceEntries_.Size(); i++)
+        if (!CheckIncludeResourceFile(project_->GetResourcePath(), *it))
         {
-            BuildResourceEntry* entry = resourceEntries_[i];
-            resourcePackager_->AddResourceEntry(entry);
+            FileSystem* fileSystem = GetSubsystem<FileSystem>();
+            String associatedDDSpath = "DDS/" + *it + ".dds";
+            String compressedPath = cachePath + associatedDDSpath;
+            if (fileSystem->FileExists(compressedPath))
+            {
+                cacheFilesToInclude.Push(associatedDDSpath);
+            }
         }
+    }
+#endif
 
+    // Add the cache files to the resource packager
+    for (StringVector::ConstIterator it = cacheFilesToInclude.Begin(); it != cacheFilesToInclude.End(); ++it)
+    {
+        AddToResourcePackager(*it, cachePath);
     }
+}
 
+void BuildBase::AddToResourcePackager(const String& filename, const String& resourceDir)
+{
+    // Check if the file is already included in the resourceEntries_ list
+    for (unsigned j = 0; j < resourceEntries_.Size(); j++)
+    {
+        const BuildResourceEntry* entry = resourceEntries_[j];
+
+        if (entry->packagePath_ == filename)
+        {
+            BuildWarn(ToString("Resource Path: %s already exists", filename.CString()));
+            continue;
+        }
+    }
+
+    if (!CheckIncludeResourceFile(resourceDir, filename))
+    {
+        fileIncludedResourcesLog_->WriteLine(resourceDir + filename + " skipped because of file extention: " + GetExtension(filename));
+        return;
+    }
+
+    BuildResourceEntry* newEntry = new BuildResourceEntry;
+
+    // BEGIN LICENSE MANAGEMENT
+    if (GetExtension(filename) == ".mdl")
+    {
+        containsMDL_ = true;
+    }
+    // END LICENSE MANAGEMENT
+
+    newEntry->absolutePath_ = resourceDir + filename;
+    newEntry->resourceDir_ = resourceDir;
+    newEntry->packagePath_ = filename;
+
+    resourceEntries_.Push(newEntry);
+
+    assert(resourcePackager_.NotNull());
+    resourcePackager_->AddResourceEntry(newEntry);
+
+    fileIncludedResourcesLog_->WriteLine(newEntry->absolutePath_);
 }
 
 void BuildBase::GenerateResourcePackage(const String& resourcePackagePath)
@@ -381,5 +602,29 @@ void BuildBase::AddResourceDir(const String& dir)
     resourceDirs_.Push(dir);
 }
 
+void BuildBase::AddProjectResourceDir(const String& dir)
+{
+    assert(!projectResourceDir_.Contains(dir));
+    projectResourceDir_.Push(dir);
+}
+
+void BuildBase::ReadAssetBuildConfig()
+{
+    String projectPath = project_->GetProjectPath();
+    projectPath = RemoveTrailingSlash(projectPath);
+
+    String filename = projectPath + "Settings/AssetBuildConfig.json";
+
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+    if (!fileSystem->FileExists(filename))
+        return;
+
+    if (AssetBuildConfig::LoadFromFile(context_, filename))
+    {
+        VariantMap assetBuildConfig;
+        AssetBuildConfig::ApplyConfig(assetBuildConfig);
+    }
+}
+
 
 }

+ 26 - 3
Source/ToolCore/Build/BuildBase.h

@@ -26,6 +26,11 @@
 #include "BuildTypes.h"
 #include "../Platform/Platform.h"
 
+namespace Atomic
+{
+    class File;
+}
+
 using namespace Atomic;
 
 namespace ToolCore
@@ -55,6 +60,7 @@ public:
     // add in search order, first added is first searched
     // will warn on name conflicts
     void AddResourceDir(const String& dir);
+    void AddProjectResourceDir(const String& dir);
 
     void BuildLog(const String& message, bool sendEvent = true);
     void BuildWarn(const String& warning, bool sendEvent = true);
@@ -66,6 +72,10 @@ public:
     /// Converts subprocess output event to a buildoutput event
     void HandleSubprocessOutputEvent(StringHash eventType, VariantMap& eventData);
 
+    /// Asset build tag used by the assetbuildconfig.json file to identify the assets to that should be include
+    /// in the build. If no tag is specified, then all resources are included.
+    void SetAssetBuildTag(const String assetBuildTag) { assetBuildTag_ = assetBuildTag; }
+
 protected:
 
     bool BuildClean(const String& path);
@@ -78,7 +88,10 @@ protected:
 
     void GenerateResourcePackage(const String& resourcePackagePath);
 
-    void BuildResourceEntries();
+    void BuildDefaultResourceEntries();
+    void BuildProjectResourceEntries();
+
+    void AddToResourcePackager(const String& filename, const String& resourceDir);
 
     void GetDefaultResourcePaths(Vector<String>& paths);
     String GetSettingsDirectory();
@@ -89,7 +102,16 @@ protected:
     bool containsMDL_;
     bool buildFailed_;
 
+    /// AssetBuildConfiguraton's asset build tag reference
+    String assetBuildTag_;
+
+    /// Pointer to a file used to capture the resources included in the build
+    File *fileIncludedResourcesLog_;
+
+
 private:
+    void BuildFilteredProjectResourceEntries();
+    void BuildAllProjectResourceEntries();
 
     PlatformID platformID_;
 
@@ -97,11 +119,12 @@ private:
     Vector<String> buildWarnings_;
     Vector<String> buildErrors_;
 
-    void ScanResourceDirectory(const String& resourceDir);
-
     SharedPtr<Project> project_;
     SharedPtr<ResourcePackager> resourcePackager_;
     Vector<String> resourceDirs_;
+    Vector<String> projectResourceDir_;
+
+    void ReadAssetBuildConfig();
 
 };
 

+ 9 - 5
Source/ToolCore/Build/BuildIOS.cpp

@@ -28,6 +28,7 @@
 #include "../ToolEnvironment.h"
 #include "../Project/Project.h"
 #include "../Project/ProjectBuildSettings.h"
+#include "../Assets/AssetDatabase.h"
 
 #include "../Subprocess/SubprocessSystem.h"
 
@@ -149,19 +150,22 @@ void BuildIOS::Initialize()
 
     Vector<String> defaultResourcePaths;
     GetDefaultResourcePaths(defaultResourcePaths);
-    String projectResources = project->GetResourcePath();
+    
 
     for (unsigned i = 0; i < defaultResourcePaths.Size(); i++)
     {
         AddResourceDir(defaultResourcePaths[i]);
     }
+    BuildDefaultResourceEntries();
 
     // TODO: smart filtering of cache
-    AddResourceDir(project->GetProjectPath() + "Cache/");
-    AddResourceDir(projectResources);
-
-    BuildResourceEntries();
+    String projectResources = project->GetResourcePath();
+    AddProjectResourceDir(projectResources);
+    AssetDatabase* db = GetSubsystem<AssetDatabase>();
+    String cachePath = db->GetCachePath();
+    AddProjectResourceDir(cachePath);
 
+    BuildProjectResourceEntries();
 }
 
 void BuildIOS::RunConvertPList()

+ 8 - 5
Source/ToolCore/Build/BuildMac.cpp

@@ -53,19 +53,22 @@ void BuildMac::Initialize()
 
     Vector<String> defaultResourcePaths;
     GetDefaultResourcePaths(defaultResourcePaths);
-    String projectResources = project->GetResourcePath();
+    
 
     for (unsigned i = 0; i < defaultResourcePaths.Size(); i++)
     {
         AddResourceDir(defaultResourcePaths[i]);
     }
+    BuildDefaultResourceEntries();
 
     // TODO: smart filtering of cache
-    AddResourceDir(project->GetProjectPath() + "Cache/");
-    AddResourceDir(projectResources);
-
-    BuildResourceEntries();
+    String projectResources = project->GetResourcePath();
+    AddProjectResourceDir(projectResources);
+    AssetDatabase* db = GetSubsystem<AssetDatabase>();
+    String cachePath = db->GetCachePath();
+    AddProjectResourceDir(cachePath);
 
+    BuildProjectResourceEntries();
 }
 
 bool BuildMac::CheckIncludeResourceFile(const String& resourceDir, const String& fileName)

+ 9 - 4
Source/ToolCore/Build/BuildWeb.cpp

@@ -28,6 +28,7 @@
 #include "../ToolSystem.h"
 #include "../ToolEnvironment.h"
 #include "../Project/Project.h"
+#include "../Assets/AssetDatabase.h"
 
 #include "BuildEvents.h"
 #include "BuildSystem.h"
@@ -54,19 +55,23 @@ void BuildWeb::Initialize()
 
     Vector<String> defaultResourcePaths;
     GetDefaultResourcePaths(defaultResourcePaths);
-    String projectResources = project->GetResourcePath();
 
     for (unsigned i = 0; i < defaultResourcePaths.Size(); i++)
     {
         AddResourceDir(defaultResourcePaths[i]);
     }
+    BuildDefaultResourceEntries();
 
     // TODO: smart filtering of cache
-    AddResourceDir(project->GetProjectPath() + "Cache/");
-    AddResourceDir(projectResources);
+    String projectResources = project->GetResourcePath();
+    AddProjectResourceDir(projectResources);
+    AssetDatabase* db = GetSubsystem<AssetDatabase>();
+    String cachePath = db->GetCachePath();
+    AddProjectResourceDir(cachePath);
 
-    BuildResourceEntries();
+    BuildProjectResourceEntries();
 }
+
 void BuildWeb::Build(const String& buildPath)
 {
     ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();

+ 10 - 10
Source/ToolCore/Build/BuildWindows.cpp

@@ -49,24 +49,24 @@ BuildWindows::~BuildWindows()
 void BuildWindows::Initialize()
 {
     ToolSystem* tsystem = GetSubsystem<ToolSystem>();
-
     Project* project = tsystem->GetProject();
 
     Vector<String> defaultResourcePaths;
     GetDefaultResourcePaths(defaultResourcePaths);
-    String projectResources = project->GetResourcePath();
-
+    
     for (unsigned i = 0; i < defaultResourcePaths.Size(); i++)
     {
         AddResourceDir(defaultResourcePaths[i]);
     }
+    BuildDefaultResourceEntries();
+    
+    // Include the project resources and cache separately
+    AddProjectResourceDir(project->GetResourcePath());
+    AssetDatabase* db = GetSubsystem<AssetDatabase>();
+    String cachePath = db->GetCachePath();
+    AddProjectResourceDir(cachePath);
 
-    // TODO: smart filtering of cache
-    AddResourceDir(project->GetProjectPath() + "Cache/");
-    AddResourceDir(projectResources);
-
-    BuildResourceEntries();
-
+    BuildProjectResourceEntries();
 }
 
 bool BuildWindows::CheckIncludeResourceFile(const String& resourceDir, const String& fileName)
@@ -86,7 +86,7 @@ bool BuildWindows::CheckIncludeResourceFile(const String& resourceDir, const Str
         }
     }
     // #623 END TODO
-
+    
     return BuildBase::CheckIncludeResourceFile(resourceDir, fileName);
 }
 

+ 9 - 0
Source/ToolCore/Command/BuildCmd.cpp

@@ -28,6 +28,7 @@
 #include "../Project/Project.h"
 #include "../Build/BuildEvents.h"
 #include "../Build/BuildSystem.h"
+#include "../Build/AssetBuildConfig.h"
 
 #include "BuildCmd.h"
 #include <Poco/File.h>
@@ -49,6 +50,7 @@ bool BuildCmd::Parse(const Vector<String>& arguments, unsigned startIndex, Strin
 {
     String argument = arguments[startIndex].ToLower();
     String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
+    String tag = startIndex + 2 < arguments.Size() ? arguments[startIndex + 2] : String::EMPTY;
 
     if (argument != "build")
     {
@@ -63,6 +65,7 @@ bool BuildCmd::Parse(const Vector<String>& arguments, unsigned startIndex, Strin
     }
 
     buildPlatform_ = value.ToLower();
+    assetsBuildTag_ = tag.ToLower();
 
     return true;
 }
@@ -78,6 +81,8 @@ void BuildCmd::HandleBuildComplete(StringHash eventType, VariantMap& eventData)
 
 }
 
+
+
 void BuildCmd::Run()
 {
     LOGINFOF("Building project for: %s", buildPlatform_.CString());
@@ -103,6 +108,10 @@ void BuildCmd::Run()
 
     // create the build
     BuildBase* buildBase = platform->NewBuild(project);
+    if (!assetsBuildTag_.Empty())
+    {
+        buildBase->SetAssetBuildTag(assetsBuildTag_);
+    }
 
     // add it to the build system
     BuildSystem* buildSystem = GetSubsystem<BuildSystem>();

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

@@ -45,8 +45,10 @@ public:
 private:
 
     void HandleBuildComplete(StringHash eventType, VariantMap& eventData);
+    
 
     String buildPlatform_;
+    String assetsBuildTag_;
 
 };