// Copyright 2020 Phyronnaz #include "VoxelSpawnersThumbnailRenderer.h" #include "VoxelSpawners/VoxelMeshSpawner.h" #include "VoxelSpawners/VoxelAssetSpawner.h" #include "VoxelSpawners/VoxelSpawnerGroup.h" #include "Engine/StaticMesh.h" #include "ThumbnailRendering/ThumbnailManager.h" #include "UnrealEdGlobals.h" #include "Editor/UnrealEdEngine.h" bool UVoxelMeshSpawnerThumbnailRenderer::CanVisualizeAsset(UObject* Object) { return Object->IsA(UVoxelMeshSpawner::StaticClass()) && CastChecked(Object)->Mesh; } void UVoxelMeshSpawnerThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* Target, FCanvas* Canvas , bool bAdditionalViewFamily) { UStaticMeshThumbnailRenderer::Draw(CastChecked(Object)->Mesh, X, Y, Width, Height, Target, Canvas , bAdditionalViewFamily); } /////////////////////////////////////////////////////////////////////////////// bool UVoxelAssetSpawnerThumbnailRenderer::CanVisualizeAsset(UObject* Object) { return Object->IsA(UVoxelAssetSpawner::StaticClass()) && CastChecked(Object)->Generator.IsValid(); } void UVoxelAssetSpawnerThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* Target, FCanvas* Canvas , bool bAdditionalViewFamily) { const auto& Generator = CastChecked(Object)->Generator; auto* GeneratorObject = Generator.GetObject(); if (GeneratorObject) { FThumbnailRenderingInfo* RenderInfo = GUnrealEd->GetThumbnailManager()->GetRenderingInfo(GeneratorObject); if (RenderInfo && RenderInfo->Renderer) { RenderInfo->Renderer->Draw(GeneratorObject, X, Y, Width, Height, Target, Canvas , bAdditionalViewFamily); } } } /////////////////////////////////////////////////////////////////////////////// auto& GetStaticStack() { static TArray Stack; return Stack; } template inline void DrawGroup(UObject* Object, const int32 Num, const int32 X, const int32 Y, const uint32 Width, const uint32 Height, T Lambda) { if (Width < 4 || Height < 4) { return; } if (GetStaticStack().Contains(Object)) { return; } GetStaticStack().Add(Object); if (Num <= 4) { const uint32 HalfWidth = Width / 2; const uint32 HalfHeight = Height / 2; const int32 MiddleX = X + HalfWidth; const int32 MiddleY = Y + HalfHeight; const uint32 SecondHalfWidth = Width - HalfWidth; const uint32 SecondHalfHeight = Height - HalfHeight; const TArray> Xs = {X, MiddleX, X, MiddleX}; const TArray> Ys = {Y, Y, MiddleY, MiddleY}; const TArray> Widths = {HalfWidth, SecondHalfWidth, HalfWidth, SecondHalfWidth}; const TArray> Heights = {HalfHeight, SecondHalfHeight, HalfHeight, SecondHalfHeight}; for (int32 Index = 0; Index < 4; Index++) { Lambda(Index, Xs[Index], Ys[Index], Widths[Index], Heights[Index]); } } else { const uint32 ThirdWidth = Width / 3; const uint32 ThirdHeight = Height / 3; const int32 OneThirdX = X + ThirdWidth; const int32 TwoThirdX = X + 2 * ThirdWidth; const int32 OneThirdY = Y + ThirdHeight; const int32 TwoThirdY = Y + 2 * ThirdHeight; const uint32 LastThirdWidth = Width - 2 * ThirdWidth; const uint32 LastThirdHeight = Height - 2 * ThirdHeight; const TArray> Xs = { X, OneThirdX, TwoThirdX, X, OneThirdX, TwoThirdX, X, OneThirdX, TwoThirdX }; const TArray> Ys = { Y, Y, Y, OneThirdY, OneThirdY, OneThirdY, TwoThirdY, TwoThirdY, TwoThirdY }; const TArray> Widths = { ThirdWidth, ThirdWidth, LastThirdWidth, ThirdWidth, ThirdWidth, LastThirdWidth, ThirdWidth, ThirdWidth, LastThirdWidth }; const TArray> Heights = { ThirdHeight,ThirdHeight,ThirdHeight, ThirdHeight,ThirdHeight,ThirdHeight, LastThirdHeight,LastThirdHeight,LastThirdHeight }; for (int32 Index = 0; Index < 9; Index++) { Lambda(Index, Xs[Index], Ys[Index], Widths[Index], Heights[Index]); } } ensure(GetStaticStack().Pop() == Object); } /////////////////////////////////////////////////////////////////////////////// bool UVoxelSpawnerGroupThumbnailRenderer::CanVisualizeAsset(UObject* Object) { return Object->IsA(UVoxelSpawnerGroup::StaticClass()) && CastChecked(Object)->Children.Num() > 0; } void UVoxelSpawnerGroupThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* Target, FCanvas* Canvas , bool bAdditionalViewFamily) { auto* Group = CastChecked(Object); auto& Children = Group->Children; DrawGroup(Object, Children.Num(), X, Y, Width, Height, [&](int32 Index, int32 NewX, int32 NewY, uint32 NewWidth, uint32 NewHeight) { if (Children.IsValidIndex(Index)) { UVoxelSpawner* Spawner = Children[Index].Spawner; if (Spawner) { FThumbnailRenderingInfo* RenderInfo = GUnrealEd->GetThumbnailManager()->GetRenderingInfo(Spawner); if (RenderInfo && RenderInfo->Renderer) { // TODO proper bAdditionalViewFamily RenderInfo->Renderer->Draw(Spawner, NewX, NewY, NewWidth, NewHeight, Target, Canvas , bAdditionalViewFamily); } } } }); } bool UVoxelMeshSpawnerGroupThumbnailRenderer::CanVisualizeAsset(UObject* Object) { return Object->IsA(UVoxelMeshSpawnerGroup::StaticClass()) && CastChecked(Object)->Meshes.Num() > 0; } /////////////////////////////////////////////////////////////////////////////// void UVoxelMeshSpawnerGroupThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* Target, FCanvas* Canvas , bool bAdditionalViewFamily) { auto* Group = CastChecked(Object); auto& Meshes = Group->Meshes; DrawGroup(Object, Meshes.Num(), X, Y, Width, Height, [&](int32 Index, int32 NewX, int32 NewY, uint32 NewWidth, uint32 NewHeight) { if (Meshes.IsValidIndex(Index)) { UStaticMesh* Mesh = Meshes[Index]; if (Mesh) { // TODO proper bAdditionalViewFamily UStaticMeshThumbnailRenderer::Draw(Mesh, NewX, NewY, NewWidth, NewHeight, Target, Canvas , bAdditionalViewFamily); } } }); }