Add support for bundling custom assets by GamePlugins

This commit is contained in:
Wojtek Figat
2021-07-20 16:32:55 +02:00
parent 88902bdb5d
commit 0794ab4ee5
5 changed files with 78 additions and 6 deletions

View File

@@ -26,6 +26,7 @@
#include "Engine/Scripting/ManagedCLR/MAssembly.h"
#include "Engine/Content/JsonAsset.h"
#include "Engine/Content/AssetReference.h"
#include "Engine/Scripting/MException.h"
#if PLATFORM_TOOLS_WINDOWS
#include "Platform/Windows/WindowsPlatformTools.h"
#include "Engine/Platform/Windows/WindowsPlatformSettings.h"
@@ -55,7 +56,7 @@ namespace GameCookerImpl
{
MMethod* Internal_OnEvent = nullptr;
MMethod* Internal_OnProgress = nullptr;
MMethod* Internal_CanDeployPlugin = nullptr;
MMethod* Internal_OnCollectAssets = nullptr;
bool IsRunning = false;
bool IsThreadRunning = false;
@@ -77,6 +78,7 @@ namespace GameCookerImpl
void CallEvent(GameCooker::EventType type);
void ReportProgress(const String& info, float totalProgress);
void OnCollectAssets(HashSet<Guid>& assets);
bool Build();
int32 ThreadFunction();
@@ -84,6 +86,7 @@ namespace GameCookerImpl
{
Internal_OnEvent = nullptr;
Internal_OnProgress = nullptr;
Internal_OnCollectAssets = nullptr;
}
}
@@ -91,6 +94,7 @@ using namespace GameCookerImpl;
Delegate<GameCooker::EventType> GameCooker::OnEvent;
Delegate<const String&, float> GameCooker::OnProgress;
Delegate<HashSet<Guid>&> GameCooker::OnCollectAssets;
const Char* ToString(const BuildPlatform platform)
{
@@ -415,6 +419,33 @@ void GameCookerImpl::ReportProgress(const String& info, float totalProgress)
ProgressValue = totalProgress;
}
void GameCookerImpl::OnCollectAssets(HashSet<Guid>& assets)
{
if (Internal_OnCollectAssets == nullptr)
{
auto c = GameCooker::GetStaticClass();
if (c)
Internal_OnCollectAssets = c->GetMethod("Internal_OnCollectAssets", 0);
ASSERT(GameCookerImpl::Internal_OnCollectAssets);
}
MCore::AttachThread();
MonoObject* exception = nullptr;
auto list = (MonoArray*)Internal_OnCollectAssets->Invoke(nullptr, nullptr, &exception);
if (exception)
{
MException ex(exception);
ex.Log(LogType::Error, TEXT("OnCollectAssets"));
}
if (list)
{
auto ids = MUtils::ToSpan<Guid>(list);
for (int32 i = 0; i < ids.Length(); i++)
assets.Add(ids[i]);
}
}
bool GameCookerImpl::Build()
{
CookingData& data = Data;
@@ -511,6 +542,7 @@ bool GameCookerService::Init()
{
auto editorAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly;
editorAssembly->Unloading.Bind(OnEditorAssemblyUnloading);
GameCooker::OnCollectAssets.Bind(OnCollectAssets);
return false;
}

View File

@@ -1,9 +1,7 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using FlaxEngine;
namespace FlaxEditor
@@ -80,6 +78,11 @@ namespace FlaxEditor
/// </summary>
public static event BuildProgressDelegate Progress;
/// <summary>
/// Occurs when building collects assets to cook.
/// </summary>
public static event Action<List<Guid>> CollectAssets;
/// <summary>
/// Gets the type of the platform from the game build platform type.
/// </summary>
@@ -96,6 +99,9 @@ namespace FlaxEditor
case BuildPlatform.XboxOne: return PlatformType.XboxOne;
case BuildPlatform.LinuxX64: return PlatformType.Linux;
case BuildPlatform.PS4: return PlatformType.PS4;
case BuildPlatform.AndroidARM64: return PlatformType.Android;
case BuildPlatform.XboxScarlett: return PlatformType.XboxScarlett;
case BuildPlatform.Switch: return PlatformType.Switch;
default: throw new ArgumentOutOfRangeException(nameof(buildPlatform), buildPlatform, null);
}
}
@@ -109,5 +115,23 @@ namespace FlaxEditor
{
Progress?.Invoke(info, totalProgress);
}
internal static Guid[] Internal_OnCollectAssets()
{
var list = new List<Guid>();
// Custom assets
CollectAssets?.Invoke(list);
// Plugin assets
foreach (var plugin in PluginManager.GamePlugins)
{
plugin.OnCollectAssets(list);
}
if (list.Count == 0)
return null;
return list.ToArray();
}
}
}

View File

@@ -61,13 +61,11 @@ public:
/// <summary>
/// Determines whether game building is running.
/// </summary>
/// <returns><c>true</c> if game building is running; otherwise, <c>false</c>.</returns>
API_PROPERTY() static bool IsRunning();
/// <summary>
/// Determines whether building cancel has been requested.
/// </summary>
/// <returns><c>true</c> if building cancel has been requested; otherwise, <c>false</c>.</returns>
API_PROPERTY() static bool IsCancelRequested();
/// <summary>
@@ -123,4 +121,9 @@ public:
/// Occurs when building game progress fires.
/// </summary>
static Delegate<const String&, float> OnProgress;
/// <summary>
/// Occurs when building collects assets to cook.
/// </summary>
static Delegate<HashSet<Guid>&> OnCollectAssets;
};

View File

@@ -101,6 +101,10 @@ bool DeployDataStep::Perform(CookingData& data)
if (data.Configuration != BuildConfiguration::Release)
data.AddRootEngineAsset(TEXT("Editor/Fonts/Roboto-Regular"));
// Register custom assets (eg. plugins)
data.StepProgress(TEXT("Deploying custom data"), 30);
GameCooker::OnCollectAssets(data.RootAssets);
// Register game assets
data.StepProgress(TEXT("Deploying game data"), 50);
auto& buildSettings = *BuildSettings::Get();

View File

@@ -11,5 +11,14 @@ namespace FlaxEngine
/// <seealso cref="FlaxEngine.Plugin" />
public abstract class GamePlugin : Plugin
{
#if FLAX_EDITOR
/// <summary>
/// Event called during game cooking in Editor to collect any assets that this plugin uses. Can be used to inject content for plugins.
/// </summary>
/// <param name="assets">The result assets list (always valid).</param>
public virtual void OnCollectAssets(System.Collections.Generic.List<System.Guid> assets)
{
}
#endif
}
}