209 lines
7.2 KiB
C++
209 lines
7.2 KiB
C++
/*
|
|
* Copyright (c) <2021> Side Effects Software Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. The name of Side Effects Software may not be used to endorse or
|
|
* promote products derived from this software without specific prior
|
|
* written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE "AS IS" AND ANY EXPRESS
|
|
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
|
* NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "HoudiniAssetFactory.h"
|
|
|
|
#include "HoudiniEngineEditorPrivatePCH.h"
|
|
#include "HoudiniAsset.h"
|
|
|
|
#include "EditorFramework/AssetImportData.h"
|
|
#include "Misc/FileHelper.h"
|
|
#include "Internationalization/Internationalization.h"
|
|
|
|
#define LOCTEXT_NAMESPACE HOUDINI_LOCTEXT_NAMESPACE
|
|
|
|
UHoudiniAssetFactory::UHoudiniAssetFactory(const FObjectInitializer & ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
{
|
|
// This factory is responsible for manufacturing HoudiniEngine assets.
|
|
SupportedClass = UHoudiniAsset::StaticClass();
|
|
|
|
// This factory does not manufacture new objects from scratch.
|
|
bCreateNew = false;
|
|
|
|
// This factory will not open the editor for each new object.
|
|
bEditAfterNew = false;
|
|
|
|
// This factory will import objects from files.
|
|
bEditorImport = true;
|
|
|
|
// Factory does not import objects from text.
|
|
bText = false;
|
|
|
|
// Add supported formats.
|
|
Formats.Add(TEXT("otl;Houdini Engine Asset"));
|
|
Formats.Add(TEXT("otllc;Houdini Engine Limited Commercial Asset"));
|
|
Formats.Add(TEXT("otlnc;Houdini Engine Non-Commercial Asset"));
|
|
Formats.Add(TEXT("hda;Houdini Engine Asset"));
|
|
Formats.Add(TEXT("hdalc;Houdini Engine Limited Commercial Asset"));
|
|
Formats.Add(TEXT("hdanc;Houdini Engine Non-Commercial Asset"));
|
|
Formats.Add(TEXT("hdalibrary;Houdini Engine Expanded Asset"));
|
|
}
|
|
|
|
bool
|
|
UHoudiniAssetFactory::DoesSupportClass(UClass * Class)
|
|
{
|
|
return Class == SupportedClass;
|
|
}
|
|
|
|
FText
|
|
UHoudiniAssetFactory::GetDisplayName() const
|
|
{
|
|
return LOCTEXT("HoudiniAssetFactoryDescription", "Houdini Engine Asset");
|
|
}
|
|
|
|
UObject *
|
|
UHoudiniAssetFactory::FactoryCreateBinary(
|
|
UClass * InClass, UObject* InParent, FName InName, EObjectFlags Flags,
|
|
UObject * Context, const TCHAR * Type, const uint8 *& Buffer,
|
|
const uint8 * BufferEnd, FFeedbackContext * Warn )
|
|
{
|
|
// Broadcast notification that a new asset is being imported.
|
|
GEditor->GetEditorSubsystem<UImportSubsystem>()->BroadcastAssetPreImport(this, InClass, InParent, InName, Type);
|
|
|
|
// Create a new asset.
|
|
UHoudiniAsset * HoudiniAsset = NewObject< UHoudiniAsset >(InParent, InName, Flags);
|
|
HoudiniAsset->CreateAsset(Buffer, BufferEnd, UFactory::GetCurrentFilename());
|
|
|
|
// Create reimport information.
|
|
UAssetImportData * AssetImportData = HoudiniAsset->AssetImportData;
|
|
if (!AssetImportData)
|
|
{
|
|
AssetImportData = NewObject< UAssetImportData >(HoudiniAsset, UAssetImportData::StaticClass());
|
|
HoudiniAsset->AssetImportData = AssetImportData;
|
|
}
|
|
|
|
AssetImportData->Update(UFactory::GetCurrentFilename());
|
|
|
|
// Broadcast notification that the new asset has been imported.
|
|
GEditor->GetEditorSubsystem<UImportSubsystem>()->BroadcastAssetPostImport(this, HoudiniAsset);
|
|
|
|
return HoudiniAsset;
|
|
}
|
|
|
|
UObject*
|
|
UHoudiniAssetFactory::FactoryCreateFile(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms, FFeedbackContext* Warn, bool& bOutOperationCanceled)
|
|
{
|
|
// "houdini.hdalibrary" files (expanded hda / hda folder) need a special treatment,
|
|
// but ".hda" files can be loaded normally
|
|
FString FileExtension = FPaths::GetExtension(Filename);
|
|
if (FileExtension.Compare(TEXT("hdalibrary"), ESearchCase::IgnoreCase) != 0)
|
|
return Super::FactoryCreateFile(InClass, InParent, InName, Flags, Filename, Parms, Warn, bOutOperationCanceled);
|
|
|
|
// Make sure the file name is sections.list
|
|
FString NameOfFile = FPaths::GetBaseFilename(Filename);
|
|
if (NameOfFile.Compare(TEXT("houdini"), ESearchCase::IgnoreCase) != 0)
|
|
{
|
|
HOUDINI_LOG_ERROR(TEXT("Failed to load file '%s'. File is not a valid extended HDA."), *Filename);
|
|
return nullptr;
|
|
}
|
|
|
|
// Make sure that the proper .list file is loaded
|
|
FString PathToFile = FPaths::GetPath(Filename);
|
|
if (PathToFile.Find(TEXT(".hda")) != (PathToFile.Len() - 4))
|
|
{
|
|
HOUDINI_LOG_ERROR(TEXT("Failed to load file '%s'. File is not a valid extended HDA."), *Filename);
|
|
return nullptr;
|
|
}
|
|
|
|
FString NewFilename = PathToFile;
|
|
FString NewFileNameNoHDA = FPaths::GetBaseFilename(PathToFile);
|
|
FName NewIname = FName(*NewFileNameNoHDA);
|
|
FString NewFileExtension = FPaths::GetExtension(NewFilename);
|
|
|
|
// load as binary
|
|
TArray<uint8> Data;
|
|
if (!FFileHelper::LoadFileToArray(Data, *Filename))
|
|
{
|
|
HOUDINI_LOG_ERROR(TEXT("Failed to load file '%s' to array"), *Filename);
|
|
return nullptr;
|
|
}
|
|
|
|
Data.Add(0);
|
|
ParseParms(Parms);
|
|
const uint8* Ptr = &Data[0];
|
|
|
|
return FactoryCreateBinary(InClass, InParent, NewIname, Flags, nullptr, *NewFileExtension, Ptr, Ptr + Data.Num() - 1, Warn);
|
|
}
|
|
|
|
bool
|
|
UHoudiniAssetFactory::CanReimport(UObject * Obj, TArray< FString > & OutFilenames)
|
|
{
|
|
UHoudiniAsset * HoudiniAsset = Cast<UHoudiniAsset>(Obj);
|
|
if (HoudiniAsset)
|
|
{
|
|
UAssetImportData * AssetImportData = HoudiniAsset->AssetImportData;
|
|
if (AssetImportData)
|
|
OutFilenames.Add(AssetImportData->GetFirstFilename());
|
|
else
|
|
OutFilenames.Add(TEXT(""));
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
UHoudiniAssetFactory::SetReimportPaths(UObject * Obj, const TArray< FString > & NewReimportPaths)
|
|
{
|
|
UHoudiniAsset * HoudiniAsset = Cast< UHoudiniAsset >(Obj);
|
|
if (HoudiniAsset && (1 == NewReimportPaths.Num()))
|
|
HoudiniAsset->AssetImportData->UpdateFilenameOnly(NewReimportPaths[0]);
|
|
}
|
|
|
|
EReimportResult::Type
|
|
UHoudiniAssetFactory::Reimport(UObject * Obj)
|
|
{
|
|
UHoudiniAsset * HoudiniAsset = Cast< UHoudiniAsset >(Obj);
|
|
if (HoudiniAsset && HoudiniAsset->AssetImportData)
|
|
{
|
|
// Make sure file is valid and exists.
|
|
const FString & Filename = HoudiniAsset->AssetImportData->GetFirstFilename();
|
|
|
|
if (!Filename.Len() || IFileManager::Get().FileSize(*Filename) == INDEX_NONE)
|
|
return EReimportResult::Failed;
|
|
|
|
if (UFactory::StaticImportObject(
|
|
HoudiniAsset->GetClass(), HoudiniAsset->GetOuter(), *HoudiniAsset->GetName(),
|
|
RF_Public | RF_Standalone, *Filename, NULL, this))
|
|
{
|
|
HOUDINI_LOG_MESSAGE(TEXT("Houdini Asset reimported successfully."));
|
|
|
|
if (HoudiniAsset->GetOuter())
|
|
HoudiniAsset->GetOuter()->MarkPackageDirty();
|
|
else
|
|
HoudiniAsset->MarkPackageDirty();
|
|
|
|
return EReimportResult::Succeeded;
|
|
}
|
|
}
|
|
|
|
HOUDINI_LOG_MESSAGE(TEXT("Houdini Asset reimport has failed."));
|
|
return EReimportResult::Failed;
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE |