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/Scripting/ManagedCLR/MAssembly.h"
#include "Engine/Content/JsonAsset.h" #include "Engine/Content/JsonAsset.h"
#include "Engine/Content/AssetReference.h" #include "Engine/Content/AssetReference.h"
#include "Engine/Scripting/MException.h"
#if PLATFORM_TOOLS_WINDOWS #if PLATFORM_TOOLS_WINDOWS
#include "Platform/Windows/WindowsPlatformTools.h" #include "Platform/Windows/WindowsPlatformTools.h"
#include "Engine/Platform/Windows/WindowsPlatformSettings.h" #include "Engine/Platform/Windows/WindowsPlatformSettings.h"
@@ -55,7 +56,7 @@ namespace GameCookerImpl
{ {
MMethod* Internal_OnEvent = nullptr; MMethod* Internal_OnEvent = nullptr;
MMethod* Internal_OnProgress = nullptr; MMethod* Internal_OnProgress = nullptr;
MMethod* Internal_CanDeployPlugin = nullptr; MMethod* Internal_OnCollectAssets = nullptr;
bool IsRunning = false; bool IsRunning = false;
bool IsThreadRunning = false; bool IsThreadRunning = false;
@@ -77,6 +78,7 @@ namespace GameCookerImpl
void CallEvent(GameCooker::EventType type); void CallEvent(GameCooker::EventType type);
void ReportProgress(const String& info, float totalProgress); void ReportProgress(const String& info, float totalProgress);
void OnCollectAssets(HashSet<Guid>& assets);
bool Build(); bool Build();
int32 ThreadFunction(); int32 ThreadFunction();
@@ -84,6 +86,7 @@ namespace GameCookerImpl
{ {
Internal_OnEvent = nullptr; Internal_OnEvent = nullptr;
Internal_OnProgress = nullptr; Internal_OnProgress = nullptr;
Internal_OnCollectAssets = nullptr;
} }
} }
@@ -91,6 +94,7 @@ using namespace GameCookerImpl;
Delegate<GameCooker::EventType> GameCooker::OnEvent; Delegate<GameCooker::EventType> GameCooker::OnEvent;
Delegate<const String&, float> GameCooker::OnProgress; Delegate<const String&, float> GameCooker::OnProgress;
Delegate<HashSet<Guid>&> GameCooker::OnCollectAssets;
const Char* ToString(const BuildPlatform platform) const Char* ToString(const BuildPlatform platform)
{ {
@@ -415,6 +419,33 @@ void GameCookerImpl::ReportProgress(const String& info, float totalProgress)
ProgressValue = 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() bool GameCookerImpl::Build()
{ {
CookingData& data = Data; CookingData& data = Data;
@@ -511,6 +542,7 @@ bool GameCookerService::Init()
{ {
auto editorAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; auto editorAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly;
editorAssembly->Unloading.Bind(OnEditorAssemblyUnloading); editorAssembly->Unloading.Bind(OnEditorAssemblyUnloading);
GameCooker::OnCollectAssets.Bind(OnCollectAssets);
return false; return false;
} }

View File

@@ -1,9 +1,7 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System; using System;
using System.Linq; using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using FlaxEngine; using FlaxEngine;
namespace FlaxEditor namespace FlaxEditor
@@ -80,6 +78,11 @@ namespace FlaxEditor
/// </summary> /// </summary>
public static event BuildProgressDelegate Progress; public static event BuildProgressDelegate Progress;
/// <summary>
/// Occurs when building collects assets to cook.
/// </summary>
public static event Action<List<Guid>> CollectAssets;
/// <summary> /// <summary>
/// Gets the type of the platform from the game build platform type. /// Gets the type of the platform from the game build platform type.
/// </summary> /// </summary>
@@ -96,6 +99,9 @@ namespace FlaxEditor
case BuildPlatform.XboxOne: return PlatformType.XboxOne; case BuildPlatform.XboxOne: return PlatformType.XboxOne;
case BuildPlatform.LinuxX64: return PlatformType.Linux; case BuildPlatform.LinuxX64: return PlatformType.Linux;
case BuildPlatform.PS4: return PlatformType.PS4; 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); default: throw new ArgumentOutOfRangeException(nameof(buildPlatform), buildPlatform, null);
} }
} }
@@ -109,5 +115,23 @@ namespace FlaxEditor
{ {
Progress?.Invoke(info, totalProgress); 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> /// <summary>
/// Determines whether game building is running. /// Determines whether game building is running.
/// </summary> /// </summary>
/// <returns><c>true</c> if game building is running; otherwise, <c>false</c>.</returns>
API_PROPERTY() static bool IsRunning(); API_PROPERTY() static bool IsRunning();
/// <summary> /// <summary>
/// Determines whether building cancel has been requested. /// Determines whether building cancel has been requested.
/// </summary> /// </summary>
/// <returns><c>true</c> if building cancel has been requested; otherwise, <c>false</c>.</returns>
API_PROPERTY() static bool IsCancelRequested(); API_PROPERTY() static bool IsCancelRequested();
/// <summary> /// <summary>
@@ -123,4 +121,9 @@ public:
/// Occurs when building game progress fires. /// Occurs when building game progress fires.
/// </summary> /// </summary>
static Delegate<const String&, float> OnProgress; 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) if (data.Configuration != BuildConfiguration::Release)
data.AddRootEngineAsset(TEXT("Editor/Fonts/Roboto-Regular")); 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 // Register game assets
data.StepProgress(TEXT("Deploying game data"), 50); data.StepProgress(TEXT("Deploying game data"), 50);
auto& buildSettings = *BuildSettings::Get(); auto& buildSettings = *BuildSettings::Get();

View File

@@ -11,5 +11,14 @@ namespace FlaxEngine
/// <seealso cref="FlaxEngine.Plugin" /> /// <seealso cref="FlaxEngine.Plugin" />
public abstract class GamePlugin : 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
} }
} }