275 lines
7.9 KiB
C++
275 lines
7.9 KiB
C++
// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2016.
|
|
|
|
#include "FMODStudioPrivatePCH.h"
|
|
#include "FMODAssetTable.h"
|
|
#include "FMODEvent.h"
|
|
#include "FMODSnapshot.h"
|
|
#include "FMODSnapshotReverb.h"
|
|
#include "FMODBank.h"
|
|
#include "FMODBus.h"
|
|
#include "FMODVCA.h"
|
|
#include "FMODUtils.h"
|
|
#include "FMODSettings.h"
|
|
#include "FMODFileCallbacks.h"
|
|
#include "fmod_studio.hpp"
|
|
|
|
#if WITH_EDITOR
|
|
#include "AssetRegistryModule.h"
|
|
#endif
|
|
|
|
FFMODAssetTable::FFMODAssetTable()
|
|
: StudioSystem(nullptr)
|
|
{
|
|
}
|
|
|
|
FFMODAssetTable::~FFMODAssetTable()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
void FFMODAssetTable::Create()
|
|
{
|
|
Destroy();
|
|
|
|
// Create a sandbox system purely for loading and considering banks
|
|
verifyfmod(FMOD::Studio::System::create(&StudioSystem));
|
|
FMOD::System* lowLevelSystem = nullptr;
|
|
verifyfmod(StudioSystem->getLowLevelSystem(&lowLevelSystem));
|
|
verifyfmod(lowLevelSystem->setOutput(FMOD_OUTPUTTYPE_NOSOUND));
|
|
verifyfmod(lowLevelSystem->setFileSystem(FMODOpen, FMODClose, FMODRead, FMODSeek, 0, 0, 2048));
|
|
verifyfmod(StudioSystem->initialize(1, FMOD_STUDIO_INIT_ALLOW_MISSING_PLUGINS, FMOD_INIT_NORMAL, 0));
|
|
}
|
|
|
|
void FFMODAssetTable::Destroy()
|
|
{
|
|
if (StudioSystem != nullptr)
|
|
{
|
|
verifyfmod(StudioSystem->release());
|
|
}
|
|
StudioSystem = nullptr;
|
|
}
|
|
|
|
UFMODAsset* FFMODAssetTable::FindByName(const FString& Name)
|
|
{
|
|
TWeakObjectPtr<UFMODAsset>* FoundAsset = FullNameLookup.Find(Name);
|
|
if (FoundAsset)
|
|
{
|
|
return FoundAsset->Get();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void FFMODAssetTable::Refresh()
|
|
{
|
|
if (StudioSystem == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const UFMODSettings& Settings = *GetDefault<UFMODSettings>();
|
|
FString StringPath = Settings.GetMasterStringsBankPath();
|
|
|
|
UE_LOG(LogFMOD, Log, TEXT("Loading strings bank: %s"), *StringPath);
|
|
|
|
FMOD::Studio::Bank* StudioStringBank;
|
|
FMOD_RESULT StringResult = StudioSystem->loadBankFile(TCHAR_TO_UTF8(*StringPath), FMOD_STUDIO_LOAD_BANK_NORMAL, &StudioStringBank);
|
|
if (StringResult == FMOD_OK)
|
|
{
|
|
TArray<char> RawBuffer;
|
|
RawBuffer.SetNum(256); // Initial capacity
|
|
|
|
int Count = 0;
|
|
verifyfmod(StudioStringBank->getStringCount(&Count));
|
|
for (int StringIdx=0; StringIdx<Count; ++StringIdx)
|
|
{
|
|
FMOD_RESULT Result;
|
|
FMOD::Studio::ID Guid = {0};
|
|
while (true)
|
|
{
|
|
int ActualSize = 0;
|
|
Result = StudioStringBank->getStringInfo(StringIdx, &Guid, RawBuffer.GetData(), RawBuffer.Num(), &ActualSize);
|
|
if (Result == FMOD_ERR_TRUNCATED)
|
|
{
|
|
RawBuffer.SetNum(ActualSize);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
verifyfmod(Result);
|
|
FString AssetName(UTF8_TO_TCHAR(RawBuffer.GetData()));
|
|
FGuid AssetGuid = FMODUtils::ConvertGuid(Guid);
|
|
if (!AssetName.IsEmpty())
|
|
{
|
|
AddAsset(AssetGuid, AssetName);
|
|
}
|
|
}
|
|
verifyfmod(StudioStringBank->unload());
|
|
verifyfmod(StudioSystem->update());
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogFMOD, Warning, TEXT("Failed to load strings bank: %s"), *StringPath);
|
|
}
|
|
}
|
|
|
|
void FFMODAssetTable::AddAsset(const FGuid& AssetGuid, const FString& AssetFullName)
|
|
{
|
|
FString AssetPath = AssetFullName;
|
|
FString AssetType = "";
|
|
FString AssetShortName = "asset";
|
|
|
|
int DelimIndex;
|
|
if (AssetPath.FindChar(':', DelimIndex))
|
|
{
|
|
AssetType = AssetPath.Left(DelimIndex);
|
|
AssetPath = AssetPath.Right(AssetPath.Len() - DelimIndex - 1);
|
|
}
|
|
|
|
FString FormattedAssetType = "";
|
|
UClass* AssetClass = UFMODAsset::StaticClass();
|
|
if (AssetType.Equals(TEXT("event")))
|
|
{
|
|
FormattedAssetType = TEXT("Events");
|
|
AssetClass = UFMODEvent::StaticClass();
|
|
}
|
|
else if (AssetType.Equals(TEXT("snapshot")))
|
|
{
|
|
FormattedAssetType = TEXT("Snapshots");
|
|
AssetClass = UFMODSnapshot::StaticClass();
|
|
}
|
|
else if (AssetType.Equals(TEXT("bank")))
|
|
{
|
|
FormattedAssetType = TEXT("Banks");
|
|
AssetClass = UFMODBank::StaticClass();
|
|
}
|
|
else if (AssetType.Equals(TEXT("bus")))
|
|
{
|
|
FormattedAssetType = TEXT("Buses");
|
|
AssetClass = UFMODBus::StaticClass();
|
|
}
|
|
else if (AssetType.Equals(TEXT("vca")))
|
|
{
|
|
FormattedAssetType = TEXT("VCAs");
|
|
AssetClass = UFMODVCA::StaticClass();
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogFMOD, Warning, TEXT("Unknown asset type: %s"), *AssetType);
|
|
}
|
|
|
|
if (AssetPath.FindLastChar('/', DelimIndex))
|
|
{
|
|
AssetShortName = AssetPath.Right(AssetPath.Len() - DelimIndex - 1);
|
|
AssetPath = AssetPath.Left(AssetPath.Len() - AssetShortName.Len() - 1);
|
|
}
|
|
else
|
|
{
|
|
// No path part, all name
|
|
AssetShortName = AssetPath;
|
|
AssetPath = TEXT("");
|
|
}
|
|
|
|
if (AssetShortName.IsEmpty() || AssetShortName.Contains(TEXT(".strings")))
|
|
{
|
|
UE_LOG(LogFMOD, Log, TEXT("Skipping asset: %s"), *AssetFullName);
|
|
return;
|
|
}
|
|
|
|
AssetPath = AssetPath.Replace(TEXT(" "), TEXT("_"));
|
|
AssetShortName = AssetShortName.Replace(TEXT(" "), TEXT("_"));
|
|
|
|
const UFMODSettings& Settings = *GetDefault<UFMODSettings>();
|
|
|
|
FString FolderPath = Settings.ContentBrowserPrefix;
|
|
FolderPath += FormattedAssetType;
|
|
FolderPath += AssetPath;
|
|
|
|
FString AssetPackagePath = FolderPath + TEXT("/") + AssetShortName;
|
|
|
|
FName AssetPackagePathName(*AssetPackagePath);
|
|
|
|
TWeakObjectPtr<UFMODAsset>& ExistingNameAsset = NameMap.FindOrAdd(AssetPackagePathName);
|
|
TWeakObjectPtr<UFMODAsset>& ExistingGuidAsset = GuidMap.FindOrAdd(AssetGuid);
|
|
TWeakObjectPtr<UFMODAsset>& ExistingFullNameLookupAsset = FullNameLookup.FindOrAdd(AssetFullName);
|
|
|
|
UFMODAsset* AssetNameObject = ExistingNameAsset.Get();
|
|
if (AssetNameObject == nullptr)
|
|
{
|
|
UE_LOG(LogFMOD, Log, TEXT("Constructing asset: %s"), *AssetPackagePath);
|
|
|
|
UPackage* NewPackage = CreatePackage(NULL, *AssetPackagePath);
|
|
if (NewPackage)
|
|
{
|
|
#if ENGINE_MINOR_VERSION >= 10
|
|
NewPackage->SetPackageFlags(PKG_CompiledIn);
|
|
#else
|
|
NewPackage->PackageFlags |= PKG_CompiledIn;
|
|
#endif
|
|
|
|
AssetNameObject = NewObject<UFMODAsset>(NewPackage, AssetClass, FName(*AssetShortName), RF_Standalone | RF_Public /* | RF_Transient */);
|
|
AssetNameObject->AssetGuid = AssetGuid;
|
|
AssetNameObject->bShowAsAsset = true;
|
|
|
|
#if WITH_EDITOR
|
|
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
|
AssetRegistryModule.Get().AddPath(*FolderPath);
|
|
FAssetRegistryModule::AssetCreated(AssetNameObject);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogFMOD, Warning, TEXT("Failed to construct package for asset %s"), *AssetPackagePath);
|
|
}
|
|
|
|
if (AssetClass == UFMODSnapshot::StaticClass())
|
|
{
|
|
FString ReverbFolderPath = Settings.ContentBrowserPrefix;
|
|
ReverbFolderPath += TEXT("Reverbs");
|
|
ReverbFolderPath += AssetPath;
|
|
|
|
FString ReverbAssetPackagePath = ReverbFolderPath + TEXT("/") + AssetShortName;
|
|
|
|
UPackage* ReverbPackage = CreatePackage(NULL, *ReverbAssetPackagePath);
|
|
if (ReverbPackage)
|
|
{
|
|
#if ENGINE_MINOR_VERSION >= 10
|
|
ReverbPackage->SetPackageFlags(PKG_CompiledIn);
|
|
#else
|
|
ReverbPackage->PackageFlags |= PKG_CompiledIn;
|
|
#endif
|
|
UFMODSnapshotReverb* AssetReverb = NewObject<UFMODSnapshotReverb>(ReverbPackage, UFMODSnapshotReverb::StaticClass(), FName(*AssetShortName), RF_Standalone | RF_Public /* | RF_Transient */);
|
|
AssetReverb->AssetGuid = AssetGuid;
|
|
AssetReverb->bShowAsAsset = true;
|
|
|
|
#if WITH_EDITOR
|
|
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
|
AssetRegistryModule.Get().AddPath(*ReverbFolderPath);
|
|
FAssetRegistryModule::AssetCreated(AssetReverb);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
UFMODAsset* AssetGuidObject = ExistingGuidAsset.Get();
|
|
if (AssetGuidObject != nullptr && AssetGuidObject != AssetNameObject)
|
|
{
|
|
FString OldPath = AssetGuidObject->GetPathName();
|
|
UE_LOG(LogFMOD, Log, TEXT("Hiding old asset '%s'"), *OldPath);
|
|
|
|
// We had an asset with the same guid but it must have been renamed
|
|
// We just hide the old asset from the asset table
|
|
AssetGuidObject->bShowAsAsset = false;
|
|
|
|
#if WITH_EDITOR
|
|
FAssetRegistryModule::AssetRenamed(AssetNameObject, OldPath);
|
|
#endif
|
|
}
|
|
|
|
ExistingNameAsset = AssetNameObject;
|
|
ExistingGuidAsset = AssetNameObject;
|
|
ExistingFullNameLookupAsset = AssetNameObject;
|
|
}
|