Skip to content

Commit

Permalink
Support reimport asset operation
Browse files Browse the repository at this point in the history
Merge branch 'support-reimport-asset-operation'
  • Loading branch information
mik14a committed May 15, 2018
2 parents 61cc92e + 15e49ad commit 43c2a18
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 9 deletions.
5 changes: 5 additions & 0 deletions Source/VOX4U/Public/Voxel.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ class VOX4U_API UVoxel : public UObject
UPROPERTY(EditDefaultsOnly, Category = Voxel)
TMap<FIntVector, uint8> Voxel;

#if WITH_EDITORONLY_DATA
UPROPERTY(EditAnywhere, Instanced, Category = Reimport)
class UAssetImportData* AssetImportData;
#endif

public:

UVoxel();
Expand Down
13 changes: 10 additions & 3 deletions Source/VOX4UEditor/Private/VOX4UEditor.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
// Copyright 2016 mik14a / Admix Network. All Rights Reserved.
// Copyright 2016-2018 mik14a / Admix Network. All Rights Reserved.

#include "VOX4UEditor.h"
#include "ThumbnailRendering/ThumbnailManager.h"
#include "AssetToolsModule.h"
#include "Voxel.h"
#include "VoxelThumbnailRenderer.h"
#include "VoxelAssetTypeActions.h"

#define LOCTEXT_NAMESPACE "FVOX4UEditorModule"

void FVOX4UEditorModule::StartupModule()
{
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
VoxelAssetTypeActions = MakeShareable(new FVoxelAssetTypeActions());
AssetTools.RegisterAssetTypeActions(VoxelAssetTypeActions.ToSharedRef());
UThumbnailManager::Get().RegisterCustomRenderer(UVoxel::StaticClass(), UVoxelThumbnailRenderer::StaticClass());
}

void FVOX4UEditorModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
if (FModuleManager::Get().IsModuleLoaded("AssetTools")) {
IAssetTools& AssetTools = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools").Get();
AssetTools.UnregisterAssetTypeActions(VoxelAssetTypeActions.ToSharedRef());
}
}

#undef LOCTEXT_NAMESPACE
Expand Down
3 changes: 2 additions & 1 deletion Source/VOX4UEditor/Private/Vox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ FVox::FVox()
* Create vox data from archive
* @param FArchive& Ar Read vox data from the archive
*/
FVox::FVox(FArchive& Ar, const UVoxImportOption* ImportOption)
FVox::FVox(const FString& Filename, FArchive& Ar, const UVoxImportOption* ImportOption)
{
this->Filename = Filename;
Import(Ar, ImportOption);
}

Expand Down
5 changes: 4 additions & 1 deletion Source/VOX4UEditor/Private/Vox.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ struct FVox
{
GENERATED_BODY()

/** Filename */
FString Filename;

/** Magic number ( 'V' 'O' 'X' 'space' ) and terminate */
ANSICHAR MagicNumber[5];
/** version number ( current version is 150 ) */
Expand All @@ -36,7 +39,7 @@ struct FVox
FVox();

/** Create vox data from archive */
FVox(FArchive& Ar, const UVoxImportOption* ImportOption);
FVox(const FString& Filename, FArchive& Ar, const UVoxImportOption* ImportOption);

/** Import vox data from archive */
bool Import(FArchive& Ar, const UVoxImportOption* ImportOption);
Expand Down
28 changes: 28 additions & 0 deletions Source/VOX4UEditor/Private/VoxAssetImportData.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2016-2018 mik14a / Admix Network. All Rights Reserved.

#include "VoxAssetImportData.h"

UVoxAssetImportData::UVoxAssetImportData()
: VoxImportType(EVoxImportType::StaticMesh)
, bImportXForward(true)
, bImportXYCenter(true)
, Scale(10.f)
{
}

void UVoxAssetImportData::ToVoxImportOption(UVoxImportOption& OutVoxImportOption)
{
OutVoxImportOption.VoxImportType = VoxImportType;
OutVoxImportOption.bImportXForward = bImportXForward;
OutVoxImportOption.bImportXYCenter = bImportXYCenter;
OutVoxImportOption.Scale = Scale;
OutVoxImportOption.BuildSettings.BuildScale3D = FVector(Scale);
}

void UVoxAssetImportData::FromVoxImportOption(const UVoxImportOption& VoxImportOption)
{
VoxImportType = VoxImportOption.VoxImportType;
bImportXForward = VoxImportOption.bImportXForward;
bImportXYCenter = VoxImportOption.bImportXYCenter;
Scale = VoxImportOption.Scale;
}
39 changes: 39 additions & 0 deletions Source/VOX4UEditor/Private/VoxAssetImportData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2016-2018 mik14a / Admix Network. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "EditorFramework/AssetImportData.h"
#include "VoxImportOption.h"
#include "VoxAssetImportData.generated.h"

/**
*
*/
UCLASS()
class UVoxAssetImportData : public UAssetImportData
{
GENERATED_BODY()

public:

EVoxImportType VoxImportType;

UPROPERTY(EditAnywhere, Category = Generic)
uint32 bImportXForward : 1;

UPROPERTY(EditAnywhere, Category = Generic)
uint32 bImportXYCenter : 1;

UPROPERTY(EditAnywhere, Category = Generic)
float Scale;

public:

UVoxAssetImportData();

void ToVoxImportOption(UVoxImportOption& OutVoxImportOption);

void FromVoxImportOption(const UVoxImportOption& VoxImportOption);

};
2 changes: 2 additions & 0 deletions Source/VOX4UEditor/Private/VoxImportOption.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,6 @@ class UVoxImportOption : public UObject

FMeshBuildSettings BuildSettings;

friend class UVoxAssetImportData;

};
32 changes: 32 additions & 0 deletions Source/VOX4UEditor/Private/VoxelAssetTypeActions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2016-2018 mik14a / Admix Network. All Rights Reserved.

#include "VoxelAssetTypeActions.h"

FVoxelAssetTypeActions::FVoxelAssetTypeActions()
{
}

FText FVoxelAssetTypeActions::GetName() const
{
return NSLOCTEXT("VOX4U", "VoxelAssetTypeActionsName", "Voxel Asset Type Actions.");
}

UClass* FVoxelAssetTypeActions::GetSupportedClass() const
{
return UVoxel::StaticClass();
}

FColor FVoxelAssetTypeActions::GetTypeColor() const
{
return FColor::Cyan;
}

uint32 FVoxelAssetTypeActions::GetCategories()
{
return EAssetTypeCategories::Misc;
}

bool FVoxelAssetTypeActions::IsImportedAsset() const
{
return true;
}
23 changes: 23 additions & 0 deletions Source/VOX4UEditor/Private/VoxelAssetTypeActions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2016-2018 mik14a / Admix Network. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "AssetTypeActions_Base.h"

class FVoxelAssetTypeActions : public FAssetTypeActions_Base
{
public:
FVoxelAssetTypeActions();

virtual FText GetName() const override;

virtual UClass* GetSupportedClass() const override;

virtual FColor GetTypeColor() const override;

virtual uint32 GetCategories() override;

virtual bool IsImportedAsset() const override;

};
117 changes: 116 additions & 1 deletion Source/VOX4UEditor/Private/VoxelFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
#include "RawMesh.h"
#include "Vox.h"
#include "VoxImportOption.h"
#include "VoxAssetImportData.h"
#include "Voxel.h"

DEFINE_LOG_CATEGORY_STATIC(LogVoxelFactory, Log, All)

UVoxelFactory::UVoxelFactory(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
, ImportOption(nullptr)
Expand Down Expand Up @@ -67,7 +70,7 @@ UObject* UVoxelFactory::FactoryCreateBinary(UClass* InClass, UObject* InParent,
if (!bShowOption || ImportOption->GetImportOption(bImportAll)) {
bShowOption = !bImportAll;
FBufferReader Reader((void*)Buffer, BufferEnd - Buffer, false);
FVox Vox(Reader, ImportOption);
FVox Vox(GetCurrentFilename(), Reader, ImportOption);
switch (ImportOption->VoxImportType) {
case EVoxImportType::StaticMesh:
Result = CreateStaticMesh(InParent, InName, Flags, &Vox);
Expand All @@ -89,20 +92,120 @@ UObject* UVoxelFactory::FactoryCreateBinary(UClass* InClass, UObject* InParent,
return Result;
}

bool UVoxelFactory::CanReimport(UObject* Obj, TArray<FString>& OutFilenames)
{
UStaticMesh* StaticMesh = Cast<UStaticMesh>(Obj);
USkeletalMesh* SkeletalMesh = Cast<USkeletalMesh>(Obj);
UDestructibleMesh* DestructibleMesh = Cast<UDestructibleMesh>(Obj);
UVoxel* Voxel = Cast<UVoxel>(Obj);

const auto& AssetImportData = StaticMesh != nullptr ? StaticMesh->AssetImportData
: SkeletalMesh != nullptr ? SkeletalMesh->AssetImportData
: DestructibleMesh != nullptr ? DestructibleMesh->AssetImportData
: Voxel != nullptr ? Voxel->AssetImportData
: nullptr;
if (AssetImportData != nullptr) {
const auto& SourcePath = AssetImportData->GetFirstFilename();
FString Path, Filename, Extension;
FPaths::Split(SourcePath, Path, Filename, Extension);
if (Extension.Compare("vox", ESearchCase::IgnoreCase) == 0) {
AssetImportData->ExtractFilenames(OutFilenames);
return true;
}
}
return false;
}

void UVoxelFactory::SetReimportPaths(UObject* Obj, const TArray<FString>& NewReimportPaths)
{
UStaticMesh* StaticMesh = Cast<UStaticMesh>(Obj);
USkeletalMesh* SkeletalMesh = Cast<USkeletalMesh>(Obj);
UDestructibleMesh* DestructibleMesh = Cast<UDestructibleMesh>(Obj);
UVoxel* Voxel = Cast<UVoxel>(Obj);

const auto& AssetImportData = StaticMesh ? StaticMesh->AssetImportData
: SkeletalMesh ? SkeletalMesh->AssetImportData
: DestructibleMesh ? DestructibleMesh->AssetImportData
: Voxel ? Voxel->AssetImportData
: nullptr;
if (AssetImportData && ensure(NewReimportPaths.Num() == 1)) {
AssetImportData->UpdateFilenameOnly(NewReimportPaths[0]);
}
}

EReimportResult::Type UVoxelFactory::Reimport(UObject* Obj)
{
UStaticMesh* StaticMesh = Cast<UStaticMesh>(Obj);
USkeletalMesh* SkeletalMesh = Cast<USkeletalMesh>(Obj);
UDestructibleMesh* DestructibleMesh = Cast<UDestructibleMesh>(Obj);
UVoxel* Voxel = Cast<UVoxel>(Obj);

const auto& AssetImportData = StaticMesh ? Cast<UVoxAssetImportData>(StaticMesh->AssetImportData)
: SkeletalMesh ? Cast<UVoxAssetImportData>(SkeletalMesh->AssetImportData)
: DestructibleMesh ? Cast<UVoxAssetImportData>(DestructibleMesh->AssetImportData)
: Voxel ? Cast<UVoxAssetImportData>(Voxel->AssetImportData)
: nullptr;
if (!AssetImportData) {
return EReimportResult::Failed;
}

const auto& Filename = AssetImportData->GetFirstFilename();
if (!Filename.Len() || IFileManager::Get().FileSize(*Filename) == INDEX_NONE) {
return EReimportResult::Failed;
}

auto Result = EReimportResult::Failed;
auto OutCanceled = false;
AssetImportData->ToVoxImportOption(*ImportOption);
bShowOption = false;
if (ImportObject(Obj->GetClass(), Obj->GetOuter(), *Obj->GetName(), RF_Public | RF_Standalone, Filename, nullptr, OutCanceled) != nullptr) {
UE_LOG(LogVoxelFactory, Verbose, TEXT("Reimport successfully."));
AssetImportData->Update(Filename);
if (Obj->GetOuter()) {
Obj->GetOuter()->MarkPackageDirty();
} else {
Obj->MarkPackageDirty();
}
Result = EReimportResult::Succeeded;
} else {
if (OutCanceled) {
UE_LOG(LogVoxelFactory, Warning, TEXT("Reimport canceled."));
} else {
UE_LOG(LogVoxelFactory, Warning, TEXT("Reimport failed."));
}
Result = EReimportResult::Failed;
}
return Result;
}

UStaticMesh* UVoxelFactory::CreateStaticMesh(UObject* InParent, FName InName, EObjectFlags Flags, const FVox* Vox) const
{
UStaticMesh* StaticMesh = NewObject<UStaticMesh>(InParent, InName, Flags | RF_Public);
if (!StaticMesh->AssetImportData || !StaticMesh->AssetImportData->IsA<UVoxAssetImportData>()) {
auto AssetImportData = NewObject<UVoxAssetImportData>(StaticMesh);
AssetImportData->FromVoxImportOption(*ImportOption);
StaticMesh->AssetImportData = AssetImportData;
}

FRawMesh RawMesh;
Vox->CreateOptimizedRawMesh(RawMesh, ImportOption);
UMaterialInterface* Material = CreateMaterial(InParent, InName, Flags, Vox);
StaticMesh->StaticMaterials.Add(FStaticMaterial(Material));
BuildStaticMesh(StaticMesh, RawMesh);
StaticMesh->AssetImportData->Update(Vox->Filename);
return StaticMesh;
}

USkeletalMesh* UVoxelFactory::CreateSkeletalMesh(UObject* InParent, FName InName, EObjectFlags Flags, const FVox* Vox) const
{
USkeletalMesh* SkeletalMesh = NewObject<USkeletalMesh>(InParent, InName, Flags | RF_Public);
if (!SkeletalMesh->AssetImportData || !SkeletalMesh->AssetImportData->IsA<UVoxAssetImportData>()) {
auto AssetImportData = NewObject<UVoxAssetImportData>(SkeletalMesh);
AssetImportData->FromVoxImportOption(*ImportOption);
SkeletalMesh->AssetImportData = AssetImportData;
}

SkeletalMesh->AssetImportData->Update(Vox->Filename);
return SkeletalMesh;
}

Expand All @@ -116,6 +219,11 @@ USkeletalMesh* UVoxelFactory::CreateSkeletalMesh(UObject* InParent, FName InName
UDestructibleMesh* UVoxelFactory::CreateDestructibleMesh(UObject* InParent, FName InName, EObjectFlags Flags, const FVox* Vox) const
{
UDestructibleMesh* DestructibleMesh = NewObject<UDestructibleMesh>(InParent, InName, Flags | RF_Public);
if (!DestructibleMesh->AssetImportData || !DestructibleMesh->AssetImportData->IsA<UVoxAssetImportData>()) {
auto AssetImportData = NewObject<UVoxAssetImportData>(DestructibleMesh);
AssetImportData->FromVoxImportOption(*ImportOption);
DestructibleMesh->AssetImportData = AssetImportData;
}

FRawMesh RawMesh;
Vox->CreateOptimizedRawMesh(RawMesh, ImportOption);
Expand All @@ -137,13 +245,19 @@ UDestructibleMesh* UVoxelFactory::CreateDestructibleMesh(UObject* InParent, FNam
DestructibleMesh->SetupChunksFromStaticMeshes(FractureMeshes);
BuildDestructibleMeshFromFractureSettings(*DestructibleMesh, nullptr);
DestructibleMesh->SourceStaticMesh = nullptr;
DestructibleMesh->AssetImportData->Update(Vox->Filename);

return DestructibleMesh;
}

UVoxel* UVoxelFactory::CreateVoxel(UObject* InParent, FName InName, EObjectFlags Flags, const FVox* Vox) const
{
UVoxel* Voxel = NewObject<UVoxel>(InParent, InName, Flags | RF_Public);
if (!Voxel->AssetImportData || !Voxel->AssetImportData->IsA<UVoxAssetImportData>()) {
auto AssetImportData = NewObject<UVoxAssetImportData>(Voxel);
AssetImportData->FromVoxImportOption(*ImportOption);
Voxel->AssetImportData = AssetImportData;
}
Voxel->Size = Vox->Size;
TArray<uint8> Palette;
for (const auto& cell : Vox->Voxel) {
Expand Down Expand Up @@ -185,6 +299,7 @@ UVoxel* UVoxelFactory::CreateVoxel(UObject* InParent, FName InName, EObjectFlags
}
Voxel->bXYCenter = ImportOption->bImportXYCenter;
Voxel->CalcCellBounds();
Voxel->AssetImportData->Update(Vox->Filename);
return Voxel;
}

Expand Down
Loading

0 comments on commit 43c2a18

Please sign in to comment.