CelticCraft/Plugins/VoxelFree/Source/Voxel/Public/VoxelTools/VoxelBlueprintLibrary.h

805 lines
31 KiB
C
Raw Normal View History

2023-07-03 16:17:13 +00:00
// Copyright 2020 Phyronnaz
#pragma once
#include "CoreMinimal.h"
#include "Engine/Texture2D.h"
#include "Templates/SubclassOf.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "VoxelIntBox.h"
#include "VoxelPaintMaterial.h"
#include "VoxelTexture.h"
#include "VoxelSpawners/VoxelInstancedMeshSettings.h"
#include "VoxelSpawners/VoxelSpawner.h"
#include "VoxelRender/VoxelToolRendering.h"
#include "VoxelUtilities/VoxelMaterialUtilities.h"
#include "VoxelBlueprintLibrary.generated.h"
enum class EVoxelTaskType : uint8;
class UVoxelHierarchicalInstancedStaticMeshComponent;
class AVoxelSpawnerActor;
class AVoxelWorld;
class APlayerState;
class AController;
class UStaticMesh;
DECLARE_DYNAMIC_DELEGATE_TwoParams(FVoxelOnChunkGenerationDynamicDelegate, AVoxelWorld*, World, FVoxelIntBox, Bounds);
DECLARE_DYNAMIC_DELEGATE_OneParam(FChunkDynamicDelegate, FVoxelIntBox, Bounds);
USTRUCT(BlueprintType)
struct FVoxelToolRenderingRef
{
GENERATED_BODY()
FVoxelToolRenderingId Id;
};
UENUM(BlueprintType)
enum class EVoxelMemoryUsageType : uint8
{
Total,
VoxelsDirtyValuesData,
VoxelsDirtyMaterialsData,
VoxelsCachedValuesData,
VoxelsCachedMaterialsData,
UndoRedo,
Multiplayer,
IntermediateBuffers,
MeshesIndices,
MeshesTessellationIndices,
MeshesVertices,
MeshesColors,
MeshesUVsAndTangents,
DataAssets,
HeightmapAssets,
UncompressedSaves,
CompressedSaves
};
UCLASS()
class VOXEL_API UVoxelBlueprintLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintPure, Category = "Voxel")
static bool IsVoxelPluginPro();
UFUNCTION(BlueprintCallable, Category = "Voxel", meta = (DefaultToSelf = "Object", AdvancedDisplay = "Object"))
static void RaiseInfo(FString Message, UObject* Object = nullptr);
UFUNCTION(BlueprintCallable, Category = "Voxel", meta = (DefaultToSelf = "Object", AdvancedDisplay = "Object"))
static void RaiseWarning(FString Message, UObject* Object = nullptr);
UFUNCTION(BlueprintCallable, Category = "Voxel", meta = (DefaultToSelf = "Object", AdvancedDisplay = "Object"))
static void RaiseError(FString Message, UObject* Object = nullptr);
// Returns the number of cores the CPU has. Ignores hyperthreading unless -usehyperthreading is passed as a command line argument.
UFUNCTION(BlueprintPure, Category = "Voxel")
static int32 NumberOfCores();
public:
// Get the current memory usage of different parts of the plugin
UFUNCTION(BlueprintPure, Category = "Voxel|Memory")
static float GetMemoryUsageInMB(EVoxelMemoryUsageType Type);
// Get the peak memory usage of different parts of the plugin
UFUNCTION(BlueprintPure, Category = "Voxel|Memory")
static float GetPeakMemoryUsageInMB(EVoxelMemoryUsageType Type);
UFUNCTION(BlueprintCallable, Category = "Voxel|Memory")
static void LogMemoryStats();
// Returns the memory used by positions and indices buffers in this voxel world
// Should give a rough estimate of how much memory is used for physics
UFUNCTION(BlueprintCallable, Category = "Voxel|Memory", meta = (DefaultToSelf = "World"))
static float GetEstimatedCollisionsMemoryUsageInMB(AVoxelWorld* World);
public:
/**
* Transform a box in global space to voxel space
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Helpers", meta = (DefaultToSelf = "World"))
static FVoxelIntBox TransformGlobalBoxToVoxelBox(AVoxelWorld* World, FBox Box);
/**
* Transform a box in voxel space to global space
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Helpers", meta = (DefaultToSelf = "World"))
static FBox TransformVoxelBoxToGlobalBox(AVoxelWorld* World, FVoxelIntBox Box);
public:
/**
* Iterate all voxel worlds in the scene, and return the first one that contains Position
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Helpers", meta = (WorldContext = "WorldContextObject"))
static AVoxelWorld* GetVoxelWorldContainingPosition(UObject* WorldContextObject, FVector Position);
/**
* Iterate all voxel worlds in the scene, and return all the ones that contains Position
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Helpers", meta = (WorldContext = "WorldContextObject"))
static TArray<AVoxelWorld*> GetAllVoxelWorldsContainingPosition(UObject* WorldContextObject, FVector Position);
/**
* Iterate all voxel worlds in the scene, and return the first one that overlaps Box
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Helpers", meta = (WorldContext = "WorldContextObject"))
static AVoxelWorld* GetVoxelWorldOverlappingBox(UObject* WorldContextObject, FBox Box);
/**
* Iterate all voxel worlds in the scene, and return all the ones that overlaps Box
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Helpers", meta = (WorldContext = "WorldContextObject"))
static TArray<AVoxelWorld*> GetAllVoxelWorldsOverlappingBox(UObject* WorldContextObject, FBox Box);
/**
* Iterate all voxel worlds in the scene, and return the first one that overlaps the actor bounding box
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Helpers", meta = (DefaultToSelf = "Actor"))
static AVoxelWorld* GetVoxelWorldOverlappingActor(AActor* Actor);
/**
* Iterate all voxel worlds in the scene, and return all the ones that overlaps the actor bounding box
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Helpers", meta = (DefaultToSelf = "Actor"))
static TArray<AVoxelWorld*> GetAllVoxelWorldsOverlappingActor(AActor* Actor);
public:
/**
* FVoxelInstancedMeshManager helpers
*/
public:
// Will replace instanced static mesh instances by actors
UFUNCTION(BlueprintCallable, Category = "Voxel|Spawners", meta = (DefaultToSelf = "World"))
static void SpawnVoxelSpawnerActorsInArea(
TArray<AVoxelSpawnerActor*>& OutActors,
AVoxelWorld* World,
FVoxelIntBox Bounds,
EVoxelSpawnerActorSpawnType SpawnType = EVoxelSpawnerActorSpawnType::OnlyFloating);
UFUNCTION(BlueprintCallable, Category = "Voxel|Spawners", meta = (DefaultToSelf = "World"))
static AVoxelSpawnerActor* SpawnVoxelSpawnerActorByInstanceIndex(
AVoxelWorld* World,
UVoxelHierarchicalInstancedStaticMeshComponent* Component,
int32 InstanceIndex);
/**
* Add instances to a voxel world foliage system
* @param World The voxel world
* @param Mesh The mesh to use
* @param Transforms The transforms, relative to the voxel world (but not in voxel space!)
* @param Colors The colors to send to the instance material (use GetVoxelMaterialFromPerInstanceRandom to get it)
* @param FloatingDetectionOffset Increase this if your foliage is enabling physics too soon
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Spawners", meta = (DefaultToSelf = "World", AdvancedDisplay = "FloatingDetectionOffset"))
static void AddInstances(
AVoxelWorld* World,
UStaticMesh* Mesh,
const TArray<FTransform>& Transforms,
const TArray<FLinearColor>& Colors,
FVoxelInstancedMeshSettings InstanceSettings,
FVoxelSpawnerActorSettings ActorSettings,
FVector FloatingDetectionOffset = FVector(0, 0, -10));
public:
/**
* IVoxelSpawnerManager helpers
*/
// Regenerate spawners in an aera
UFUNCTION(BlueprintCallable, Category = "Voxel|Spawners", meta = (DefaultToSelf = "World"))
static void RegenerateSpawners(AVoxelWorld* World, FVoxelIntBox Bounds);
// Mark spawners as dirty so that they don't get trash if they go out of scope
UFUNCTION(BlueprintCallable, Category = "Voxel|Spawners", meta = (DefaultToSelf = "World"))
static void MarkSpawnersDirty(AVoxelWorld* World, FVoxelIntBox Bounds);
UFUNCTION(BlueprintCallable, Category = "Voxel|Spawners", meta = (DefaultToSelf = "World"))
static FVoxelSpawnersSave GetSpawnersSave(AVoxelWorld* World);
UFUNCTION(BlueprintCallable, Category = "Voxel|Spawners", meta = (DefaultToSelf = "World"))
static void LoadFromSpawnersSave(AVoxelWorld* World, const FVoxelSpawnersSave& Save);
public:
/**
* FVoxelData helpers
*/
public:
// Undo last frame. bEnableUndoRedo must be true, and SaveFrame must have been called after any edits
// @return Success
UFUNCTION(BlueprintCallable, Category = "Voxel|UndoRedo", meta = (DefaultToSelf = "World"))
static bool Undo(AVoxelWorld* World, TArray<FVoxelIntBox>& OutUpdatedBounds);
static bool Undo(AVoxelWorld* World);
// Redo last undone frame. bEnableUndoRedo must be true, and SaveFrame must have been called after any edits
// @return Success
UFUNCTION(BlueprintCallable, Category = "Voxel|UndoRedo", meta = (DefaultToSelf = "World"))
static bool Redo(AVoxelWorld* World, TArray<FVoxelIntBox>& OutUpdatedBounds);
static bool Redo(AVoxelWorld* World);
// Save the edits since the last call to SaveFrame/Undo/Redo and clear the redo stack. bEnableUndoRedo must be true
UFUNCTION(BlueprintCallable, Category = "Voxel|UndoRedo", meta = (DefaultToSelf = "World"))
static void SaveFrame(AVoxelWorld* World);
// Clear all the frames. bEnableUndoRedo must be true
UFUNCTION(BlueprintCallable, Category = "Voxel|UndoRedo", meta = (DefaultToSelf = "World"))
static void ClearFrames(AVoxelWorld* World);
// Get the current history position
UFUNCTION(BlueprintPure, Category = "Voxel|UndoRedo", meta = (DefaultToSelf = "World"))
static int32 GetHistoryPosition(AVoxelWorld* World);
// Get the normal at Position using the density gradient. May differ from the mesh normal
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (Keywords = "gradient", DefaultToSelf = "World"))
static FVector GetNormal(AVoxelWorld* World, FIntVector Position);
// Get a custom float output value
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (DefaultToSelf = "World"))
static float GetFloatOutput(AVoxelWorld* World, FName Name, float X, float Y, float Z, float DefaultValue);
// Get a custom int32 output value
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (DefaultToSelf = "World"))
static int32 GetIntOutput(AVoxelWorld* World, FName Name, float X, float Y, float Z, int32 DefaultValue);
// Bounds of this world
UFUNCTION(BlueprintPure, Category = "Voxel|Data", meta = (DefaultToSelf = "World"))
static FVoxelIntBox GetBounds(AVoxelWorld* World);
// TODO: delegate to chunk creation to setup material
// Will cleanup the code there as well, as no need to manually call world gen thingy
// Clear all the data in the world, including items/assets
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (DefaultToSelf = "World", AdvancedDisplay = "bUpdateRender"))
static void ClearAllData(AVoxelWorld* World, bool bUpdateRender = true);
// Clear all the value data in the world
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (DefaultToSelf = "World", AdvancedDisplay = "bUpdateRender"))
static void ClearValueData(AVoxelWorld* World, bool bUpdateRender = true);
// Clear all the material data in the world
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (DefaultToSelf = "World", AdvancedDisplay = "bUpdateRender"))
static void ClearMaterialData(AVoxelWorld* World, bool bUpdateRender = true);
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (DefaultToSelf = "World", AdvancedDisplay = "bUpdateRender"))
static bool HasValueData(AVoxelWorld* World);
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (DefaultToSelf = "World", AdvancedDisplay = "bUpdateRender"))
static bool HasMaterialData(AVoxelWorld* World);
// Clear all the edited data in the world, excluding items/assets
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (DefaultToSelf = "World", AdvancedDisplay = "bUpdateRender"))
static void ClearDirtyData(AVoxelWorld* World, bool bUpdateRender = true);
// Scale the voxel world data. Will recreate the voxel world!
UFUNCTION(BlueprintCallable, Category = "Voxel|Data", meta = (DefaultToSelf = "World"))
static void ScaleData(AVoxelWorld* World, const FVector& Scale);
public:
/**
* IVoxelLODManager helpers
*/
public:
// Update the chunks overlapping Position
UFUNCTION(BlueprintCallable, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static void UpdatePosition(AVoxelWorld* World, FIntVector Position);
// Update the chunks overlapping Bounds.
UFUNCTION(BlueprintCallable, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static void UpdateBounds(AVoxelWorld* World, FVoxelIntBox Bounds);
// Update all the chunks
UFUNCTION(BlueprintCallable, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static void UpdateAll(AVoxelWorld* World);
// Call this after changing the voxel world LODs setting while created
UFUNCTION(BlueprintCallable, Category = "Voxel|Render", meta = (DefaultToSelf = "World", DisplayName = "Apply LOD Settings"))
static void ApplyLODSettings(AVoxelWorld* World);
/**
* Returns whether voxel collisions are enabled at Position
* @param World The voxel world
* @param Position The position to query, in world space if ConvertToVoxelSpace is true
* @param LOD The LOD at that position
* @param bConvertToVoxelSpace If true, the position will be converted to voxel space. Else it will be used directly
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Collisions", meta = (DefaultToSelf = "World", AdvancedDisplay = "bConvertToVoxelSpace"))
static bool AreCollisionsEnabled(AVoxelWorld* World, FVector Position, int32& LOD, bool bConvertToVoxelSpace = true);
public:
/**
* IVoxelRenderer helpers
*/
public:
// Number of mesh processing tasks not finished
UFUNCTION(BlueprintPure, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static int32 GetTaskCount(AVoxelWorld* World);
// Returns true if there are still mesh tasks queued
UFUNCTION(BlueprintPure, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static bool IsVoxelWorldMeshLoading(AVoxelWorld* World);
// Returns true if there are still foliage tasks queued
UFUNCTION(BlueprintPure, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static bool IsVoxelWorldFoliageLoading(AVoxelWorld* World);
// Call this after changing a voxel world VoxelMaterial/MaterialCollection to apply it
UFUNCTION(BlueprintCallable, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static void ApplyNewMaterials(AVoxelWorld* World);
// Call this to recreate the voxel world rendering entirely, keeping data intact
UFUNCTION(BlueprintCallable, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static void RecreateRender(AVoxelWorld* World);
// Call this to recreate the voxel world spawners
UFUNCTION(BlueprintCallable, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static void RecreateSpawners(AVoxelWorld* World);
// Call this to recreate the voxel world entirely, optionally keeping data intact by saving it
UFUNCTION(BlueprintCallable, Category = "Voxel|Render", meta = (DefaultToSelf = "World"))
static void Recreate(AVoxelWorld* World, bool bSaveData = true);
public:
/**
* FVoxelEventManager helpers
*/
public:
UFUNCTION(BlueprintCallable, Category = "Voxel|Proc Gen", meta = (DefaultToSelf = "World", AdvancedDisplay = "bFireExistingOnes"))
static void BindVoxelChunkEvents(
AVoxelWorld* World,
FChunkDynamicDelegate OnActivate,
FChunkDynamicDelegate OnDeactivate,
bool bFireExistingOnes = false,
int32 ChunkSize = 32,
int32 ActivationDistanceInChunks = 2);
UFUNCTION(BlueprintCallable, Category = "Voxel|Proc Gen", meta = (DefaultToSelf = "World", AdvancedDisplay = "bFireExistingOnes"))
static void BindVoxelGenerationEvent(
AVoxelWorld* World,
FChunkDynamicDelegate OnGenerate,
bool bFireExistingOnes = false,
int32 ChunkSize = 32,
int32 GenerationDistanceInChunks = 2);
public:
/**
* FVoxelToolRenderingManager helpers
*/
public:
UFUNCTION(BlueprintCallable, Category = "Voxel|Tool Rendering", meta = (DefaultToSelf = "World"))
static bool IsValidRef(AVoxelWorld* World, FVoxelToolRenderingRef Ref);
UFUNCTION(BlueprintCallable, Category = "Voxel|Tool Rendering", meta = (DefaultToSelf = "World"))
static FVoxelToolRenderingRef CreateToolRendering(AVoxelWorld* World);
UFUNCTION(BlueprintCallable, Category = "Voxel|Tool Rendering", meta = (DefaultToSelf = "World"))
static void DestroyToolRendering(AVoxelWorld* World, FVoxelToolRenderingRef Ref);
UFUNCTION(BlueprintCallable, Category = "Voxel|Tool Rendering", meta = (DefaultToSelf = "World"))
static void SetToolRenderingMaterial(AVoxelWorld* World, FVoxelToolRenderingRef Ref, UMaterialInterface* Material);
// Bounds: In world space
UFUNCTION(BlueprintCallable, Category = "Voxel|Tool Rendering", meta = (DefaultToSelf = "World"))
static void SetToolRenderingBounds(AVoxelWorld* World, FVoxelToolRenderingRef Ref, FBox Bounds);
UFUNCTION(BlueprintCallable, Category = "Voxel|Tool Rendering", meta = (DefaultToSelf = "World"))
static void SetToolRenderingEnabled(AVoxelWorld* World, FVoxelToolRenderingRef Ref, bool bEnabled = true);
public:
/**
* IVoxelPool helpers
*/
public:
/**
* Create the global voxel thread pool. Must not be already created.
* CreateWorldVoxelThreadPool is preferred, as pools will be per level
* @param NumberOfThreads At least 1
* @param bConstantPriorities If true won't recompute the tasks priorities once added. Useful if you have many tasks, but will give bad task scheduling when moving fast
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Threads", meta = (AdvancedDisplay = "PriorityCategoriesOverrides, PriorityOffsetsOverrides"))
static void CreateGlobalVoxelThreadPool(
const TMap<EVoxelTaskType, int32>& PriorityCategoriesOverrides,
const TMap<EVoxelTaskType, int32>& PriorityOffsetsOverrides,
int32 NumberOfThreads = 2,
bool bConstantPriorities = false);
// Destroy the global voxel thread pool
UFUNCTION(BlueprintCallable, Category = "Voxel|Threads")
static void DestroyGlobalVoxelThreadPool();
// Is the global voxel thread pool created?
UFUNCTION(BlueprintPure, Category = "Voxel|Threads")
static bool IsGlobalVoxelPoolCreated();
/**
* Create the voxel thread pool for a specific world. Must not be already created.
* @param NumberOfThreads At least 1
* @param bConstantPriorities If true won't recompute the tasks priorities once added. Useful if you have many tasks, but will give bad task scheduling when moving fast
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Threads", meta = (AdvancedDisplay = "PriorityCategoriesOverrides, PriorityOffsetsOverrides"))
static void CreateWorldVoxelThreadPool(
UWorld* World,
const TMap<EVoxelTaskType, int32>& PriorityCategoriesOverrides,
const TMap<EVoxelTaskType, int32>& PriorityOffsetsOverrides,
int32 NumberOfThreads = 2,
bool bConstantPriorities = false);
// Destroy the world voxel thread pool
UFUNCTION(BlueprintCallable, Category = "Voxel|Threads")
static void DestroyWorldVoxelThreadPool(UWorld* World);
// Is the global voxel thread pool created?
UFUNCTION(BlueprintPure, Category = "Voxel|Threads")
static bool IsWorldVoxelPoolCreated(UWorld* World);
public:
/**
* FVoxelIntBox helpers
*/
public:
/**
* Make IntBox from global position and radius
* @param Radius in cm
*/
UFUNCTION(BlueprintPure, Category = "Voxel|Utilities", meta = (DefaultToSelf = "World"))
static FVoxelIntBox MakeIntBoxFromGlobalPositionAndRadius(AVoxelWorld* World, FVector GlobalPosition, float Radius);
// eg if you want to cache all the data that's going to be used by render chunks when updating the world
UFUNCTION(BlueprintPure, Category = "Voxel|Utilities", meta = (DefaultToSelf = "World"))
static FVoxelIntBox GetRenderBoundsOverlappingDataBounds(AVoxelWorld* World, FVoxelIntBox DataBounds, int32 LOD = 0);
public:
/**
* FIntVector helpers
*/
public:
UFUNCTION(BlueprintPure, meta = (DisplayName = "IntVector + IntVector", CompactNodeTitle = "+", Keywords = "+ add plus"), Category = "Math|IntVector")
static FIntVector Add_IntVectorIntVector(FIntVector Left, FIntVector Right)
{
return Left + Right;
}
UFUNCTION(BlueprintPure, meta = (DisplayName = "IntVector - IntVector", CompactNodeTitle = "-", Keywords = "- subtract minus"), Category = "Math|IntVector")
static FIntVector Substract_IntVectorIntVector(FIntVector Left, FIntVector Right)
{
return Left - Right;
}
UFUNCTION(BlueprintPure, meta = (DisplayName = "IntVector * IntVector", CompactNodeTitle = "*", Keywords = "* multiply"), Category = "Math|IntVector")
static FIntVector Multiply_IntVectorIntVector(FIntVector Left, FIntVector Right)
{
return FIntVector(Left.X * Right.X, Left.Y * Right.Y, Left.Z * Right.Z);
}
UFUNCTION(BlueprintPure, meta = (DisplayName = "IntVector / int", CompactNodeTitle = "/", Keywords = "/ divide"), Category = "Math|IntVector")
static FIntVector Divide_IntVectorInt(FIntVector Left, int32 Right)
{
return Left / Right;
}
UFUNCTION(BlueprintPure, meta = (DisplayName = "IntVector * int", CompactNodeTitle = "*", Keywords = "* multiply"), Category = "Math|IntVector")
static FIntVector Multiply_IntVectorInt(FIntVector Left, int32 Right)
{
return Left * Right;
}
UFUNCTION(BlueprintPure, meta = (DisplayName = "int * IntVector", CompactNodeTitle = "*", Keywords = "* multiply"), Category = "Math|IntVector")
static FIntVector Multiply_IntIntVector(int32 Left, FIntVector Right)
{
return Right * Left;
}
UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Max"), Category = "Math|IntVector")
static int32 GetMax_Intvector(FIntVector Vector)
{
return Vector.GetMax();
}
UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Min"), Category = "Math|IntVector")
static int32 GetMin_Intvector(FIntVector Vector)
{
return Vector.GetMin();
}
public:
/**
* FVoxelPaintMaterial helpers
*/
public:
// Create from color
UFUNCTION(BlueprintPure, Category = "Voxel|Materials", DisplayName = "Create RGB Paint Material")
static FVoxelPaintMaterial CreateColorPaintMaterial(FVoxelPaintMaterialColor Color)
{
FVoxelPaintMaterial PaintMaterial;
PaintMaterial.Type = EVoxelPaintMaterialType::Color;
PaintMaterial.Color = Color;
return PaintMaterial;
}
/**
* Create paint material for 5 way blend
*/
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static FVoxelPaintMaterial CreateFiveWayBlendPaintMaterial(FVoxelPaintMaterialFiveWayBlend FiveWayBlend);
// Create for single index
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static FVoxelPaintMaterial CreateSingleIndexPaintMaterial(FVoxelPaintMaterialSingleIndex SingleIndex)
{
FVoxelPaintMaterial PaintMaterial;
PaintMaterial.Type = EVoxelPaintMaterialType::SingleIndex;
PaintMaterial.SingleIndex = SingleIndex;
return PaintMaterial;
}
// Create for multi index
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static FVoxelPaintMaterial CreateMultiIndexPaintMaterial(FVoxelPaintMaterialMultiIndex MultiIndex)
{
FVoxelPaintMaterial PaintMaterial;
PaintMaterial.Type = EVoxelPaintMaterialType::MultiIndex;
PaintMaterial.MultiIndex = MultiIndex;
return PaintMaterial;
}
// Create for multi index wetness
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static FVoxelPaintMaterial CreateMultiIndexWetnessPaintMaterial(FVoxelPaintMaterialMultiIndexWetness MultiIndexWetness)
{
FVoxelPaintMaterial PaintMaterial;
PaintMaterial.Type = EVoxelPaintMaterialType::MultiIndexWetness;
PaintMaterial.MultiIndexWetness = MultiIndexWetness;
return PaintMaterial;
}
// Create for multi index, setting the data directly
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static FVoxelPaintMaterial CreateMultiIndexRawPaintMaterial(FVoxelPaintMaterialMultiIndexRaw MultiIndexRaw)
{
FVoxelPaintMaterial PaintMaterial;
PaintMaterial.Type = EVoxelPaintMaterialType::MultiIndexRaw;
PaintMaterial.MultiIndexRaw = MultiIndexRaw;
return PaintMaterial;
}
// Create UV paint
UFUNCTION(BlueprintPure, Category = "Voxel|Materials", DisplayName = "Create UV Paint Material")
static FVoxelPaintMaterial CreateUVPaintMaterial(FVoxelPaintMaterialUV UV)
{
FVoxelPaintMaterial PaintMaterial;
PaintMaterial.Type = EVoxelPaintMaterialType::UV;
PaintMaterial.UV = UV;
return PaintMaterial;
}
// Apply a Paint Material to a Voxel Material
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static FVoxelMaterial ApplyPaintMaterial(FVoxelMaterial Material, FVoxelPaintMaterial PaintMaterial, float Strength = 1.f)
{
PaintMaterial.ApplyToMaterial(Material, Strength);
return Material;
}
public:
/**
* FVoxelMaterial helpers
*/
public:
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static FLinearColor GetColor(FVoxelMaterial Material)
{
return Material.GetLinearColor();
}
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static uint8 GetSingleIndex(FVoxelMaterial Material)
{
return Material.GetSingleIndex();
}
// If SortByStrength is true, Index 0 will have the highest strength, Index 1 the second highest etc
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static void GetMultiIndex(
FVoxelMaterial Material,
bool bSortByStrength,
float& Strength0, uint8& Index0,
float& Strength1, uint8& Index1,
float& Strength2, uint8& Index2,
float& Strength3, uint8& Index3,
float& Wetness);
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static FVector2D GetUV(FVoxelMaterial Material, int32 Channel)
{
return Material.GetUV_AsFloat(Channel);
}
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static void GetRawMaterial(
FVoxelMaterial Material,
uint8& R, uint8& G, uint8& B, uint8& A,
uint8& U0, uint8& V0,
uint8& U1, uint8& V1,
uint8& U2, uint8& V2,
uint8& U3, uint8& V3)
{
R = Material.Impl_GetR();
G = Material.Impl_GetG();
B = Material.Impl_GetB();
A = Material.Impl_GetA();
U0 = Material.Impl_GetU0();
V0 = Material.Impl_GetV0();
U1 = Material.Impl_GetU1();
V1 = Material.Impl_GetV1();
U2 = Material.Impl_GetU2();
V2 = Material.Impl_GetV2();
U3 = Material.Impl_GetU3();
V3 = Material.Impl_GetV3();
}
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static FVoxelMaterial MakeRawMaterial(
uint8 R, uint8 G, uint8 B, uint8 A,
uint8 U0, uint8 V0,
uint8 U1, uint8 V1,
uint8 U2, uint8 V2,
uint8 U3, uint8 V3)
{
FVoxelMaterial Material{ ForceInit };
Material.Impl_SetR(R);
Material.Impl_SetG(G);
Material.Impl_SetB(B);
Material.Impl_SetA(A);
Material.Impl_SetU0(U0);
Material.Impl_SetV0(V0);
Material.Impl_SetU1(U1);
Material.Impl_SetV1(V1);
Material.Impl_SetU2(U2);
Material.Impl_SetV2(V2);
Material.Impl_SetU3(U3);
Material.Impl_SetV3(V3);
return Material;
}
UFUNCTION(BlueprintPure, Category = "Voxel|Materials")
static int32 MakeMaterialMask(
bool R, bool G, bool B, bool A,
bool U0, bool V0,
bool U1, bool V1,
bool U2, bool V2,
bool U3, bool V3)
{
return
EVoxelMaterialMask::R * R |
EVoxelMaterialMask::G * G |
EVoxelMaterialMask::B * B |
EVoxelMaterialMask::A * A |
EVoxelMaterialMask::U0 * U0 |
EVoxelMaterialMask::U1 * U1 |
EVoxelMaterialMask::U2 * U2 |
EVoxelMaterialMask::U3 * U3 |
EVoxelMaterialMask::V0 * V0 |
EVoxelMaterialMask::V1 * V1 |
EVoxelMaterialMask::V2 * V2 |
EVoxelMaterialMask::V3 * V3;
}
public:
/**
* FVoxelTexture helpers
*/
public:
/**
* Will create Texture if null, and set it
* Returns Texture for convenience
*
* Texture will have the following config:
* Pixel format: PF_R32_FLOAT
* Compression settings: TC_HDR
* SRGB: false
* Filter: TF_Bilinear
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Voxel Texture")
static UTexture2D* CreateOrUpdateTextureFromVoxelFloatTexture(FVoxelFloatTexture VoxelTexture, UPARAM(ref) UTexture2D*& Texture)
{
FVoxelTextureUtilities::CreateOrUpdateUTexture2D(VoxelTexture.Texture, Texture);
return Texture;
}
/**
* Same as CreateOrUpdateTextureFromVoxelFloatTexture with nullptr in input
*
* Texture will have the following config:
* Pixel format: PF_R32_FLOAT
* Compression settings: TC_HDR
* SRGB: false
* Filter: TF_Bilinear
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Voxel Texture")
static UTexture2D* CreateTextureFromVoxelFloatTexture(FVoxelFloatTexture VoxelTexture)
{
UTexture2D* Texture = nullptr;
FVoxelTextureUtilities::CreateOrUpdateUTexture2D(VoxelTexture.Texture, Texture);
return Texture;
}
/**
* Creates a voxel float texture from the color channel of a texture
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Voxel Texture")
static FVoxelFloatTexture CreateVoxelFloatTextureFromTextureChannel(UTexture2D* Texture, EVoxelRGBA Channel)
{
return { FVoxelTextureUtilities::CreateFromTexture_Float(Texture, Channel) };
}
public:
/**
* Will create Texture if null, and set it
* Returns Texture for convenience
*
* Texture will have the following config:
* Pixel format: PF_B8G8R8A8
* Compression settings: TC_VectorDisplacementmap
* SRGB: false
* Filter: TF_Bilinear
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Voxel Texture")
static UTexture2D* CreateOrUpdateTextureFromVoxelColorTexture(FVoxelColorTexture VoxelTexture, UPARAM(ref) UTexture2D*& Texture)
{
FVoxelTextureUtilities::CreateOrUpdateUTexture2D(VoxelTexture.Texture, Texture);
return Texture;
}
/**
* Same as CreateOrUpdateTextureFromVoxelFloatTexture with nullptr in input
*
* Texture will have the following config:
* Pixel format: PF_B8G8R8A8
* Compression settings: TC_VectorDisplacementmap
* SRGB: false
* Filter: TF_Bilinear
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Voxel Texture")
static UTexture2D* CreateTextureFromVoxelColorTexture(FVoxelColorTexture VoxelTexture)
{
UTexture2D* Texture = nullptr;
FVoxelTextureUtilities::CreateOrUpdateUTexture2D(VoxelTexture.Texture, Texture);
return Texture;
}
/**
* Creates a voxel color texture by putting a float texture into a specific channel
* @param bNormalize If true, the float texture min value will be mapped to 0, and max value to 1
*/
UFUNCTION(BlueprintCallable, Category = "Voxel|Voxel Texture")
static FVoxelColorTexture CreateVoxelColorTextureFromVoxelFloatTexture(FVoxelFloatTexture Texture, EVoxelRGBA Channel, bool bNormalize = true)
{
return { FVoxelTextureUtilities::CreateColorTextureFromFloatTexture(Texture.Texture, Channel, bNormalize) };
}
public:
UFUNCTION(BlueprintPure, Category = "Voxel|Voxel Texture")
static FIntPoint GetVoxelFloatTextureSize(FVoxelFloatTexture Texture)
{
return { Texture.Texture.GetSizeX(), Texture.Texture.GetSizeY() };
}
UFUNCTION(BlueprintPure, Category = "Voxel|Voxel Texture")
static FIntPoint GetVoxelColorTextureSize(FVoxelColorTexture Texture)
{
return { Texture.Texture.GetSizeX(), Texture.Texture.GetSizeY() };
}
UFUNCTION(BlueprintPure, Category = "Voxel|Voxel Texture")
static bool IsVoxelFloatTextureValid(FVoxelFloatTexture Texture)
{
return FMath::Max(Texture.Texture.GetSizeX(), Texture.Texture.GetSizeY()) > 1;
}
UFUNCTION(BlueprintPure, Category = "Voxel|Voxel Texture")
static bool IsVoxelColorTextureValid(FVoxelFloatTexture Texture)
{
return FMath::Max(Texture.Texture.GetSizeX(), Texture.Texture.GetSizeY()) > 1;
}
public:
/**
* General helpers
*/
public:
UFUNCTION(BlueprintCallable, Category = "Voxel|Utilities")
static void AddNeighborsToSet(const TSet<FIntVector>& InSet, TSet<FIntVector>& OutSet);
};