863 lines
No EOL
43 KiB
C++
863 lines
No EOL
43 KiB
C++
// Copyright 2020 Phyronnaz
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "GameFramework/Actor.h"
|
|
#include "Templates/SubclassOf.h"
|
|
#include "PhysicsEngine/BodyInstance.h"
|
|
#include "Components/PrimitiveComponent.h"
|
|
|
|
#include "VoxelEnums.h"
|
|
#include "VoxelIntBox.h"
|
|
#include "VoxelUtilities/VoxelMathUtilities.h"
|
|
#include "VoxelGenerators/VoxelGeneratorInit.h"
|
|
#include "VoxelGenerators/VoxelGeneratorPicker.h"
|
|
#include "VoxelWorldInterface.h"
|
|
#include "VoxelEditorDelegatesInterface.h"
|
|
#include "VoxelRender/VoxelMeshConfig.h"
|
|
#include "VoxelRender/VoxelLODMaterials.h"
|
|
#include "VoxelWorldCreateInfo.h"
|
|
#include "VoxelWorld.generated.h"
|
|
|
|
class UVoxelSpawnerConfig;
|
|
class UVoxelGeneratorCache;
|
|
class UVoxelWorldSaveObject;
|
|
class UVoxelWorldRootComponent;
|
|
class UVoxelLineBatchComponent;
|
|
class UVoxelMultiplayerInterface;
|
|
class UVoxelPlaceableItemManager;
|
|
class UVoxelMaterialCollectionBase;
|
|
class UVoxelProceduralMeshComponent;
|
|
class UVoxelPlaceableItemActorHelper;
|
|
class IVoxelPool;
|
|
class IVoxelRenderer;
|
|
class IVoxelLODManager;
|
|
class FVoxelData;
|
|
class FVoxelDebugManager;
|
|
class FVoxelEventManager;
|
|
class IVoxelSpawnerManager;
|
|
class FVoxelMultiplayerManager;
|
|
class FVoxelInstancedMeshManager;
|
|
class FVoxelToolRenderingManager;
|
|
struct FVoxelLODDynamicSettings;
|
|
struct FVoxelUncompressedWorldSave;
|
|
struct FVoxelRendererDynamicSettings;
|
|
enum class EVoxelTaskType : uint8;
|
|
|
|
/**
|
|
* Voxel World actor class
|
|
*/
|
|
UCLASS()
|
|
class VOXEL_API AVoxelWorld : public AVoxelWorldInterface, public IVoxelEditorDelegatesInterface
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
class FGameThreadTasks
|
|
{
|
|
public:
|
|
void AddTask(const TFunction<void()>& Task)
|
|
{
|
|
Tasks.Enqueue(Task);
|
|
}
|
|
|
|
private:
|
|
TQueue<TFunction<void()>, EQueueMode::Mpsc> Tasks;
|
|
|
|
void Flush();
|
|
|
|
friend AVoxelWorld;
|
|
};
|
|
|
|
public:
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnGenerateWorld);
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWorldLoaded);
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWorldDestroyed);
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnMaxFoliageInstancesReached);
|
|
|
|
// Called when generating the world, right after it's created
|
|
// Bind this to add data items, or to do something right after the world is created
|
|
UPROPERTY(BlueprintAssignable)
|
|
FOnGenerateWorld OnGenerateWorld;
|
|
|
|
UPROPERTY(BlueprintAssignable)
|
|
FOnWorldLoaded OnWorldLoaded;
|
|
|
|
// Called right before destroying the world. Use this if you want to save data
|
|
UPROPERTY(BlueprintAssignable)
|
|
FOnWorldDestroyed OnWorldDestroyed;
|
|
|
|
// Called when max foliage instances is reached
|
|
UPROPERTY(BlueprintAssignable)
|
|
FOnMaxFoliageInstancesReached OnMaxFoliageInstancesReached;
|
|
|
|
protected:
|
|
UPROPERTY(Category = "Voxel", VisibleAnywhere, BlueprintReadOnly)
|
|
TObjectPtr<UVoxelWorldRootComponent> WorldRoot;
|
|
|
|
UPROPERTY()
|
|
TObjectPtr<UVoxelLineBatchComponent> LineBatchComponent;
|
|
|
|
public:
|
|
UVoxelWorldRootComponent& GetWorldRoot() const { check(WorldRoot); return *WorldRoot; }
|
|
UVoxelLineBatchComponent& GetLineBatchComponent() const { check(LineBatchComponent); return *LineBatchComponent; }
|
|
|
|
public:
|
|
// Automatically loaded on creation
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Save", meta = (Recreate))
|
|
TObjectPtr<UVoxelWorldSaveObject> SaveObject = nullptr;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Save")
|
|
FString SaveFilePath;
|
|
|
|
// If true, will save the world to SaveFilePath each time it's saved to the save object
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Save")
|
|
bool bAutomaticallySaveToFile = false;
|
|
|
|
// If true, will add the current time & date to the filepath when saving
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Save")
|
|
bool bAppendDateToSavePath = false;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Bake")
|
|
bool bRecomputeNormalsBeforeBaking = false;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Bake")
|
|
TObjectPtr<UStaticMesh> BakedMeshTemplate = nullptr;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Bake")
|
|
TSubclassOf<UStaticMeshComponent> BakedMeshComponentTemplate;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Bake", meta = (RelativeToGameContentDir))
|
|
FFilePath BakedDataPath = { "/Game/VoxelStaticData" };
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Preview", meta = (Recreate, ClampMin = 1))
|
|
int32 NumberOfThreadsForPreview = 2;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Preview", meta = (Recreate))
|
|
bool bEnableFoliageInEditor = true;
|
|
|
|
// Turns this off if there's a significant lag when changing material properties
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Preview")
|
|
bool bAutomaticallyRefreshMaterials = true;
|
|
|
|
// Turns this off if there's a significant lag when changing foliage properties
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Preview")
|
|
bool bAutomaticallyRefreshFoliage = true;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Preview", meta = (DisplayName = "New Scale"))
|
|
FVector EditorOnly_NewScale = FVector(2, 2, 2);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Size of a voxel in cm
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - General", meta = (Recreate, ClampMin = 0.0001))
|
|
float VoxelSize = 100;
|
|
|
|
// Generator of this world
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - General", meta = (Recreate))
|
|
FVoxelGeneratorPicker Generator;
|
|
|
|
// Will be automatically created if not set
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - General", Instanced, meta = (Recreate))
|
|
TObjectPtr<UVoxelPlaceableItemManager> PlaceableItemManager = nullptr;
|
|
|
|
VOXEL_DEPRECATED(1.2, "Seeds are now regular generator parameters")
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - General", meta = (DisplayName = "Seeds (DEPRECATED)"))
|
|
TMap<FName, int32> Seeds;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - General")
|
|
bool bCreateWorldAutomatically = false;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - General", meta = (DisplayName = "Use camera if no invokers found"))
|
|
bool bUseCameraIfNoInvokersFound = false;
|
|
|
|
// Keep all the changes in memory to enable undo/redo. Can be expensive
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - General", meta = (Recreate))
|
|
bool bEnableUndoRedo = false;
|
|
|
|
// If true, the voxel world will try to stay near its original coordinates when rebasing, and will offset the voxel coordinates instead
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - General")
|
|
bool bEnableCustomWorldRebasing = false;
|
|
|
|
// If true, will merge asset actors in the scene on create.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - General")
|
|
bool bMergeAssetActors = true;
|
|
|
|
// If true, will merge disable edits boxes in the scene on create.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - General")
|
|
bool bMergeDisableEditsBoxes = true;
|
|
|
|
// Will hide voxel messages
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - General")
|
|
bool bDisableOnScreenMessages = false;
|
|
|
|
// Will disable all debug features
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - General")
|
|
bool bDisableDebugManager = false;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// WorldSizeInVoxel = RENDER_CHUNK_SIZE * 2^DataOctreeDepth.
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, AdvancedDisplay, Category = "Voxel - World Size", meta = (Recreate, ClampMin = 1, ClampMax = 26, UIMin = 1, UIMax = 26))
|
|
int32 RenderOctreeDepth = 10;
|
|
|
|
// Size of an edge of the world
|
|
UPROPERTY(EditAnywhere, Category = "Voxel - World Size", meta = (Recreate, ClampMin = 1, DisplayName = "World Size (in voxel)"))
|
|
uint32 WorldSizeInVoxel = FVoxelUtilities::GetSizeFromDepth<RENDER_CHUNK_SIZE>(10);
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - World Size", meta = (Recreate, InlineEditConditionToggle))
|
|
bool bUseCustomWorldBounds = false;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - World Size", meta = (Recreate, EditCondition = "bUseCustomWorldBounds"))
|
|
FVoxelIntBox CustomWorldBounds;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Chunks can't have a LOD strictly higher than this. Useful is background has a too low resolution.
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - LOD Settings", meta = (UpdateLODs, ClampMin = 0, ClampMax = 25, UIMin = 0, UIMax = 25))
|
|
int32 MaxLOD = FVoxelUtilities::ClampMesherDepth(32);
|
|
|
|
// Chunks can't have a LOD strictly lower than this. Useful when in space for instance, combined with a manual BP call to ApplyLODSettings
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - LOD Settings", meta = (UpdateLODs, ClampMin = 0, ClampMax = 25, UIMin = 0, UIMax = 25))
|
|
int32 MinLOD = 0;
|
|
|
|
// In world space. If invokers move by less than this distance LODs won't be updated
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - LOD Settings", meta = (UpdateLODs))
|
|
float InvokerDistanceThreshold = 100;
|
|
|
|
// Min delay between two LOD updates, in seconds
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - LOD Settings", meta = (RecreateRender, ClampMin = 0), DisplayName = "Min Delay Between LOD Updates")
|
|
float MinDelayBetweenLODUpdates = 0.1;
|
|
|
|
// If true, the LODs will be updated only once at start
|
|
// LODs can still be updated using ForceLODsUpdate or ApplyLODSettings
|
|
// For example, can be useful when used with a Max LOD of 0 for worlds that have the highest resolution LOD everywhere
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - LOD Settings", meta = (RecreateRender))
|
|
bool bConstantLOD = false;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials", meta = (Recreate /* also used by generator */))
|
|
EVoxelMaterialConfig MaterialConfig = EVoxelMaterialConfig::RGB;
|
|
|
|
// Only used if Material Config = RGB
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials", meta = (UpdateRenderer))
|
|
TObjectPtr<UMaterialInterface> VoxelMaterial = nullptr;
|
|
|
|
// The material collection to use in Single Index or Double Index material config
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials", meta = (UpdateRenderer))
|
|
TObjectPtr<UVoxelMaterialCollectionBase> MaterialCollection;
|
|
|
|
// Per LOD material overrides
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials|LOD", meta = (UpdateRenderer, DisplayName = "LOD Materials"))
|
|
TArray<FVoxelLODMaterials> LODMaterials;
|
|
|
|
// Per LOD material collections overrides
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials|LOD", meta = (UpdateRenderer, DisplayName = "LOD Material Collections"))
|
|
TArray<FVoxelLODMaterialCollections> LODMaterialCollections;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials|UVs", meta = (RecreateRender, DisplayName = "UV Config"))
|
|
EVoxelUVConfig UVConfig = EVoxelUVConfig::GlobalUVs;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials|UVs", meta = (RecreateRender, DisplayName = "UV Scale"))
|
|
float UVScale = 1;
|
|
|
|
// Normal config, only respected by Marching Cubes
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials|Normals", meta = (RecreateRender))
|
|
EVoxelNormalConfig NormalConfig = EVoxelNormalConfig::GradientNormal;
|
|
|
|
// Hardness settings for RGB
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials|Hardness", meta = (DisplayName = "RGB Hardness"))
|
|
EVoxelRGBHardness RGBHardness = EVoxelRGBHardness::FiveWayBlend;
|
|
|
|
// Material Index -> Hardness, for Single/Multi index, or RGB if Four/Five Way Blend
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Materials|Hardness")
|
|
TMap<FString, float> MaterialsHardness;
|
|
|
|
// If true, then in RGB mode additional vertices will be created to ensure that no colors are ever blended
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Materials", meta = (RecreateRender))
|
|
bool bHardColorTransitions = false;
|
|
|
|
// Only for Cubic mode. If true, the material index will be 3 x Index + 0 for top, 3 x Index + 1 for sides and 3 x Index + 2 for bottom
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Materials", meta = (RecreateRender))
|
|
bool bOneMaterialPerCubeSide = false;
|
|
|
|
// These materials won't be rendered nor have any collision
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Materials", meta = (RecreateRender))
|
|
TArray<uint8> HolesMaterials;
|
|
|
|
// Apply custom mesh settings per material index
|
|
// Will create more mesh components!
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Materials", meta = (RecreateRender))
|
|
TMap<uint8, FVoxelMeshConfig> MaterialsMeshConfigs;
|
|
|
|
// Use 16 bits float instead of 32 bits. Halves the UVs memory usage, but lower precision
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Materials", meta = (RecreateRender))
|
|
bool bHalfPrecisionCoordinates = false;
|
|
|
|
// If true, will interpolate the adjacent voxels colors to find the exact vertex color
|
|
// In SingleIndex, will interpolate DataA/B/C
|
|
// In MultiIndex, will interpolate Blend and Wetness
|
|
// Twice as expensive, as requires to make twice as many material queries!
|
|
// Might not look as great if the material outside of the voxel surface isn't set to something nice
|
|
// Only works with marching cubes for now
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Materials", meta = (RecreateRender))
|
|
bool bInterpolateColors = false;
|
|
|
|
// If true, will interpolate the adjacent voxels uvs to find the exact vertex uvs
|
|
// Twice as expensive, as requires to make twice as many material queries!
|
|
// Only works with marching cubes for now
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Materials", meta = (RecreateRender))
|
|
bool bInterpolateUVs = false;
|
|
|
|
// When ticked, will convert the color stored in the material (as a 4 bytes color) from sRGB to Linear
|
|
// However, since the target will still be 4 bytes, the conversion won't be perfect
|
|
// This is a limitation of vertex colors sadly
|
|
// NOTE: It is recommended to leave this off, and to tick bLinearColor when painting colors instead
|
|
// That way color operations are done in linear space, which is recommended
|
|
// NOTE: DO NOT enable in Multi Index, it will just mess up the blend parameters
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Materials", meta = (RecreateRender, DisplayName = "sRGB Colors"))
|
|
bool bSRGBColors = false;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
EVoxelRenderType RenderType = EVoxelRenderType::MarchingCubes;
|
|
|
|
// For marching cubes only
|
|
// If 0, will do nothing
|
|
// If above zero, will round the vertices positions to the nearest multiple of (1 / RenderSharpness)
|
|
// Visually, it will give a more "sharp" look, 1 being the sharpest, 2 3 etc being less and less sharp
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender, UIMin = 0, UIMax = 10, ClampMin = 0))
|
|
int32 RenderSharpness = 0;
|
|
|
|
// If true, a dynamic instance will be created for each chunk. Else, the material will be used directly
|
|
// Disable this if you want to use dynamic material instances as voxel world materials
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
bool bCreateMaterialInstances = true;
|
|
|
|
// Whether to dither chunks
|
|
// Requires CreateMaterialInstances
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender, EditCondition = bCreateMaterialInstances))
|
|
bool bDitherChunks = true;
|
|
|
|
// Dithering duration when changing LODs
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender, ClampMin = 0, EditCondition = bDitherChunks))
|
|
float ChunksDitheringDuration = 1;
|
|
|
|
// When enabled, the component will be rendering into the far shadow cascades (only for directional lights).
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
bool bCastFarShadow = false;
|
|
|
|
// Custom procedural mesh class to use
|
|
// Use this to override specific rendering settings such as cast shadows, render custom depth...
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
TSubclassOf<UVoxelProceduralMeshComponent> ProcMeshClass;
|
|
|
|
// Chunks with a LOD strictly higher than this won't be rendered
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (UpdateLODs, ClampMin = 0, ClampMax = 26, UIMin = 0, UIMax = 26))
|
|
int32 ChunksCullingLOD = FVoxelUtilities::ClampDepth<RENDER_CHUNK_SIZE>(32);
|
|
|
|
// Whether to render the world, or to just use it for collisions/navmesh
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (Recreate))
|
|
bool bRenderWorld = true;
|
|
|
|
// Will destroy any intermediate render data to free up memory
|
|
// Does not support any kind of updates
|
|
// Note: if MergeChunks is true, chunk meshes memory won't be cleared as it can't know if a new mesh will be added to the cluster
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
bool bStaticWorld = false;
|
|
|
|
// If true, the mesh indices will be sorted to improve GPU cache performance. Adds a cost to the async mesh building. If you don't see any perf difference, leave it off
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
bool bOptimizeIndices = false;
|
|
|
|
// Will generate distance fields on LOD 0 chunks
|
|
// Has a cost of around 1 ms per chunk (on async thread)
|
|
// Doesn't work with chunks merging or single/double index material config with different materials per chunk
|
|
// Requires UE 4.23+
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
bool bGenerateDistanceFields = false;
|
|
|
|
// Chunks with LOD <= this will have distance fields
|
|
// Be careful when increasing because of the memory usage caused by distance fields
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender, ClampMin = 0, ClampMax = 26, UIMin = 0, UIMax = 26, EditCondition = "bGenerateDistanceFields"))
|
|
int32 MaxDistanceFieldLOD = 4;
|
|
|
|
// By how many voxels to extend the chunks distance fields (on every side)
|
|
// This is needed so that distance fields nicely overlap
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender, ClampMin = 0, ClampMax = 32, UIMin = 0, UIMax = 8, EditCondition = "bGenerateDistanceFields"))
|
|
int32 DistanceFieldBoundsExtension = 4;
|
|
|
|
// By how much to divide the distance field resolution
|
|
// By default it'll be 32x32x32: if the divisor is 2, it'll be 16x16x16, if 4 8x8x8...
|
|
// Increasing this decreases quality of the distance field, but saves huge amount of VRAM
|
|
// NOTE: increasing this can lead to messy distance fields as some signs are messy
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender, ClampMin = 1, ClampMax = 32, UIMin = 1, UIMax = 8, EditCondition = "bGenerateDistanceFields"))
|
|
int32 DistanceFieldResolutionDivisor = 1;
|
|
|
|
/** Useful for reducing self shadowing from distance field methods when using world position offset to animate the mesh's vertices. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender, EditCondition = "bGenerateDistanceFields"))
|
|
float DistanceFieldSelfShadowBias = 0.f;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
bool bEnableTransitions = true;
|
|
|
|
// Will merge chunks together to reduce draw calls.
|
|
// Only merges chunks of the same LOD!
|
|
// Enabling this disables CreateMaterialInstances and DitherChunks.
|
|
// When turning this on, it is recommended to reduce the priority of the Mesh Merge category (eg set it to 0)
|
|
// Else mesh merge are done before meshing tasks, even if these meshing tasks would have made the merge invalid
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
bool bMergeChunks = false;
|
|
|
|
// Size in voxels of the clusters. Scales with LOD (eg if 64, for LOD 3 it will be 64 * 2 * 2 * 2 = 512)
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender, EditCondition = "bMergeChunks"))
|
|
int32 ChunksClustersSize = 64;
|
|
|
|
// If true, additional meshes with the normal chunk size will be spawned only for collisions & navmesh
|
|
// Recommended, as cooking collision for merged chunks takes forever
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender, EditCondition = "bMergeChunks"))
|
|
bool bDoNotMergeCollisionsAndNavmesh = true;
|
|
|
|
// Increases the chunks bounding boxes, useful when using tessellation
|
|
// Setting it to 0 can cause issues on flat worlds
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Rendering", meta = (RecreateRender))
|
|
float BoundsExtension = 100;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Spawners", meta = (RecreateSpawners))
|
|
TObjectPtr<UVoxelSpawnerConfig> SpawnerConfig;
|
|
|
|
// The chunk size, in voxels, of a single HISM component
|
|
// Lower = higher draw calls/object count
|
|
// Higher = more delay when building the occlusion tree
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Spawners", meta = (RecreateSpawners, DisplayName = "HISM Chunk Size"))
|
|
int32 HISMChunkSize = 2048;
|
|
|
|
// Only nearby instances have collisions
|
|
// Configure the distance using this
|
|
// In voxels!
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Spawners", meta = (RecreateSpawners, ClampMin = 0))
|
|
int32 SpawnersCollisionDistanceInVoxel = 64;
|
|
|
|
// If more instances than this are spawned, they will not be displayed
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Spawners", meta = (RecreateSpawners, ClampMin = 0))
|
|
int64 MaxNumberOfFoliageInstances = MAX_int32;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Collisions", meta = (RecreateRender))
|
|
bool bEnableCollisions = true;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Collisions", meta = (Recreate, EditCondition = bEnableCollisions, ShowOnlyInnerProperties))
|
|
FBodyInstance CollisionPresets;
|
|
|
|
// Whether to compute simple collision meshes or not
|
|
// Change this only if you want to use the voxel world as a rigidbody
|
|
// Simple collision won't match the geometry exactly
|
|
// Using simple collision is not less expensive than using complex collisions, as the convex hulls are far from optimized
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Collisions", meta = (Recreate, EditCondition = bEnableCollisions))
|
|
TEnumAsByte<ECollisionTraceFlag> CollisionTraceFlag = ECollisionTraceFlag::CTF_UseComplexAsSimple;
|
|
|
|
/**
|
|
* Determine whether a Character can step up onto this component.
|
|
* This controls whether they can try to step up on it when they bump in to it, not whether they can walk on it after landing on it.
|
|
* @see FWalkableSlopeOverride
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Collisions", meta = (Recreate, EditCondition = bEnableCollisions))
|
|
TEnumAsByte<ECanBeCharacterBase> CanCharacterStepUpOn = ECanBeCharacterBase(1); // ECB_Yes
|
|
|
|
/** Should 'Hit' events fire when this object collides during physics simulation. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Collisions|Events", meta = (Recreate, EditCondition = bEnableCollisions, DisplayName = "Simulation Generates Hit Events"))
|
|
bool bNotifyRigidBodyCollision = false;
|
|
|
|
/**
|
|
* If true, this component will generate overlap events when it is overlapping other components (eg Begin Overlap).
|
|
* Both components (this and the other) must have this enabled for overlap events to occur.
|
|
*
|
|
* @see [Overlap Events](https://docs.unrealengine.com/latest/INT/Engine/Physics/Collision/index.html#overlapandgenerateoverlapevents)
|
|
* @see UpdateOverlaps(), BeginComponentOverlap(), EndComponentOverlap()
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Collisions|Events", meta = (Recreate, EditCondition = bEnableCollisions))
|
|
bool bGenerateOverlapEvents = false;
|
|
|
|
// If false, use only invokers collisions settings
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Collisions|Visible Chunks", meta = (UpdateLODs, EditCondition = bEnableCollisions))
|
|
bool bComputeVisibleChunksCollisions = true;
|
|
|
|
// Max LOD to compute collisions on. Inclusive. If not 0 collisions won't be precise. Does not affect invokers
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Collisions|Visible Chunks", meta = (UpdateLODs, ClampMin = 0, ClampMax = 26, UIMin = 0, UIMax = 26, EditCondition = "bComputeVisibleChunksCollisions && bEnableCollisions"))
|
|
int32 VisibleChunksCollisionsMaxLOD = 5;
|
|
|
|
/** Allows you to override the PhysicalMaterial to use for simple collision on this body. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Collisions", meta = (Recreate, EditCondition = bEnableCollisions))
|
|
TObjectPtr<UPhysicalMaterial> PhysMaterialOverride = nullptr;
|
|
|
|
/** If true Continuous Collision Detection (CCD) will be used for this component */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Collisions", meta = (Recreate, EditCondition = bEnableCollisions))
|
|
bool bUseCCD = false;
|
|
|
|
// Number of convex hulls to create per chunk per axis for simple collisions
|
|
// More hulls = more precise collisions, but much more expensive physics
|
|
// You can check the result in the Player Collision view
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Collisions", meta = (RecreateRender, ClampMin = 1, ClampMax = 32, UIMin = 1, UIMax = 32, EditCondition = bEnableCollisions))
|
|
int32 NumConvexHullsPerAxis = 2;
|
|
|
|
// Clean collisions meshes when cooking them.
|
|
// Disabling this makes cooking collision slightly faster, but might lead to physx crashing in case of invalid geometry.
|
|
// Enable this if you are getting crashes in the physx code
|
|
// To check the performance improvements: voxel.LogCollisionCookingTimes 1
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Collisions", meta = (RecreateRender, EditCondition = bEnableCollisions))
|
|
bool bCleanCollisionMeshes = true;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Navmesh", meta = (RecreateRender))
|
|
bool bEnableNavmesh = false;
|
|
|
|
// If false, use only invokers navmesh settings
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Navmesh", meta = (UpdateLODs, EditCondition = bEnableNavmesh))
|
|
bool bComputeVisibleChunksNavmesh = true;
|
|
|
|
// Max LOD to compute navmesh on. Inclusive. Does not affect invokers
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Navmesh", meta = (UpdateLODs, ClampMin = 0, ClampMax = 26, UIMin = 0, UIMax = 26, EditCondition = "bEnableNavmesh && bComputeVisibleChunksNavmesh"))
|
|
int32 VisibleChunksNavmeshMaxLOD = 0;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// If you have more than one voxel world, set this to false and call CreateGlobalVoxelThreadPool at BeginPlay (for instance in your level blueprint)
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Performance")
|
|
bool bCreateGlobalPool = true;
|
|
|
|
// Number of threads allocated for the voxel background processing. Setting it too high may impact performance
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Performance", meta = (Recreate, ClampMin = 1, EditCondition = "bCreateGlobalPool"))
|
|
int32 NumberOfThreads = 2;
|
|
|
|
// Async tasks are sorted based on 2 values:
|
|
// - first, their priority category
|
|
// - then, their own priority (most of the time their distance from voxel invokers)
|
|
// Using priority categories, you can determine which tasks to compute first
|
|
// Setting 2 task type to the same category will allow to sort them only based on their distance from a voxel invoker
|
|
// eg, for foliage and meshing tasks: meshes will spawn at the same time as the foliage on top of them
|
|
// If you want to spawn the meshes slightly before foliage, you can offset the tasks own priorities using the PriorityOffsets below
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Performance", meta = (Recreate, EditCondition = "bCreateGlobalPool"))
|
|
TMap<EVoxelTaskType, int32> PriorityCategories;
|
|
|
|
// Allows to offset tasks own priorities
|
|
// Only useful for tasks that have the same priority category!
|
|
// Most values are in voxel
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Performance", meta = (Recreate, EditCondition = "bCreateGlobalPool"))
|
|
TMap<EVoxelTaskType, int32> PriorityOffsets;
|
|
|
|
// If true, won't recompute task priorities once they are queued
|
|
// If false, will recompute task priorities with the new voxel invoker positions every PriorityDuration seconds
|
|
// True: useful if you have many tasks
|
|
// False: useful if you want precise task scheduling, eg if you are moving relatively fast
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Performance", meta = (Recreate, EditCondition = "bCreateGlobalPool"))
|
|
bool bConstantPriorities = false;
|
|
|
|
// Only used if ConstantPriorities is false
|
|
// Time, in seconds, during which a task priority is valid and does not need to be recomputed
|
|
// Lowering this will increase async cost to recompute priorities, but will lead to more precise scheduling
|
|
// Increasing this will decreasing async cost to recompute priorities, but might lead to imprecise scheduling if the invokers are moving fast
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Performance", meta = (RecreateRender, ClampMin = 0, EditCondition = "!bConstantPriorities"))
|
|
float PriorityDuration = 0.5;
|
|
|
|
// Max time in milliseconds to spend on mesh updates per tick
|
|
// If this is too low world will generate very slowly
|
|
// If this is too high you will get lag spikes
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Performance", meta = (RecreateRender, ClampMin = 0.001))
|
|
float MeshUpdatesBudget = 1000;
|
|
|
|
// The rate at which events are fired (number of updates per seconds). Used for foliage spawning, foliage collision, binded BP events...
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Performance", meta = (RecreateRender, UIMin = 1, UIMax = 60))
|
|
float EventsTickRate = 15;
|
|
|
|
// Depth to which to subdivide the data octree on start
|
|
// Will create 8^X nodes, so keep low!
|
|
// Useful to avoid update tasks locking the entire octree
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Performance", meta = (Recreate, ClampMin = 0))
|
|
int32 DataOctreeInitialSubdivisionDepth = 4;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Is this world synchronized using the plugin multiplayer system?
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Multiplayer", meta = (Recreate))
|
|
bool bEnableMultiplayer = false;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Voxel - Multiplayer", meta = (Recreate, EditCondition = "bMultiplayer"))
|
|
TSubclassOf<UVoxelMultiplayerInterface> MultiplayerInterface;
|
|
|
|
// Number of sync per second
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Voxel - Multiplayer", meta = (Recreate, EditCondition = "bMultiplayer"))
|
|
float MultiplayerSyncRate = 15;
|
|
|
|
public:
|
|
AVoxelWorld();
|
|
|
|
public:
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General")
|
|
void CreateWorld(FVoxelWorldCreateInfo Info);
|
|
void CreateWorld() { CreateWorld({}); }
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General")
|
|
void DestroyWorld();
|
|
|
|
public:
|
|
IVoxelPool& GetPool() const { return *Pool; }
|
|
FVoxelData& GetData() const { return *Data; }
|
|
IVoxelLODManager& GetLODManager() const { return *LODManager; }
|
|
IVoxelRenderer& GetRenderer() const { return *Renderer; }
|
|
FVoxelDebugManager& GetDebugManager() const { return *DebugManager; }
|
|
FVoxelEventManager& GetEventManager() const { return *EventManager; }
|
|
FVoxelToolRenderingManager& GetToolRenderingManager() const { return *ToolRenderingManager; }
|
|
|
|
const UVoxelGeneratorCache& GetGeneratorCache() const { return *GeneratorCache; }
|
|
|
|
const TVoxelSharedPtr<FGameThreadTasks>& GetGameThreadTasks() const { return GameThreadTasks; }
|
|
const TVoxelSharedPtr<FVoxelData>& GetDataSharedPtr() const { return Data; }
|
|
const TVoxelSharedPtr<IVoxelLODManager>& GetLODManagerSharedPtr() const { return LODManager; }
|
|
const TVoxelSharedPtr<IVoxelPool>& GetPoolSharedPtr() const { return Pool; }
|
|
const TVoxelSharedRef<FIntVector>& GetWorldOffsetPtr() const { return WorldOffset; }
|
|
const TVoxelSharedRef<FVoxelRendererDynamicSettings>& GetRendererDynamicSettings() const { return RendererDynamicSettings; }
|
|
EVoxelPlayType GetPlayType() const { return PlayType; }
|
|
|
|
FVoxelIntBox GetWorldBounds() const;
|
|
FIntVector GetWorldOffset() const { return *WorldOffset; }
|
|
|
|
public:
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General")
|
|
void SetGeneratorObject(UVoxelGenerator* NewGenerator);
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General")
|
|
void SetGeneratorClass(TSubclassOf<UVoxelGenerator> NewGeneratorClass);
|
|
|
|
// Set the render octree depth
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|World Size")
|
|
void SetRenderOctreeDepth(int32 NewDepth);
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|World Size")
|
|
void SetWorldSize(int32 NewWorldSizeInVoxels);
|
|
void SetWorldSize(uint32 NewWorldSizeInVoxels);
|
|
|
|
public:
|
|
// Is this world created?
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General")
|
|
inline bool IsCreated() const { return bIsCreated; }
|
|
|
|
// Has the VoxelRenderer finished loading?
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General")
|
|
inline bool IsLoaded() const { return bIsLoaded; }
|
|
|
|
public:
|
|
/**
|
|
* Convert position from world space to voxel space
|
|
* @param Position Position in world space
|
|
* @param Rounding How to round
|
|
* @return Position in voxel space
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General|Coordinates", meta = (DisplayName = "World Position to Voxel", AdvancedDisplay = "Rounding"))
|
|
virtual FIntVector GlobalToLocal(const FVector& Position, EVoxelWorldCoordinatesRounding Rounding = EVoxelWorldCoordinatesRounding::RoundToNearest) const override final;
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General|Coordinates", meta = (DisplayName = "World Position to Voxel Float"))
|
|
FVector GlobalToLocalFloatBP(const FVector& Position) const;
|
|
virtual FVoxelVector GlobalToLocalFloat(const FVector& Position) const override final;
|
|
|
|
/**
|
|
* Convert position from voxel space to world space
|
|
* @param Position Position in voxel space
|
|
* @return Position in world space
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General|Coordinates", meta = (DisplayName = "Voxel Position to World"))
|
|
virtual FVector LocalToGlobal(const FIntVector& Position) const override final;
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General|Coordinates", meta = (DisplayName = "Voxel Position to World Float"))
|
|
FVector LocalToGlobalFloatBP(const FVector& Position) const;
|
|
virtual FVector LocalToGlobalFloat(const FVoxelVector& Position) const override final;
|
|
|
|
/**
|
|
* Get the 8 neighbors in voxel space of GlobalPosition
|
|
* @param GlobalPosition The position in world space
|
|
* @return The 8 neighbors in voxel space
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General|Coordinates")
|
|
TArray<FIntVector> GetNeighboringPositions(const FVector& GlobalPosition) const;
|
|
|
|
/**
|
|
* Set the voxel world voxel offset
|
|
* @param OffsetInVoxels Offset
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General")
|
|
void SetOffset(const FIntVector& OffsetInVoxels);
|
|
|
|
/**
|
|
* Add an offset to the world coordinate system (eg for rebasing)
|
|
* @param OffsetInVoxels Offset
|
|
* @param bMoveActor If false, the actor will keep its current position
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General")
|
|
void AddOffset(const FIntVector& OffsetInVoxels, bool bMoveActor = true);
|
|
|
|
// The generator cache allows to reuse generator objects
|
|
// This is required for DataItemActors to allow for smaller update when moving them
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General", DisplayName = "Get Generator Cache")
|
|
UVoxelGeneratorCache* K2_GetGeneratorCache() const { return GeneratorCache; }
|
|
|
|
// Used to init generators
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|General")
|
|
FVoxelGeneratorInit GetGeneratorInit() const;
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|Multiplayer")
|
|
UVoxelMultiplayerInterface* CreateMultiplayerInterfaceInstance();
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Voxel|Multiplayer")
|
|
UVoxelMultiplayerInterface* GetMultiplayerInterfaceInstance() const;
|
|
|
|
// Can be called at runtime
|
|
UFUNCTION(BlueprintCallable, Category="Voxel|Collision")
|
|
void SetCollisionResponseToChannel(ECollisionChannel Channel, ECollisionResponse NewResponse);
|
|
|
|
public:
|
|
//~ Begin AActor Interface
|
|
virtual void BeginPlay() override;
|
|
virtual void EndPlay(EEndPlayReason::Type EndPlayReason) override;
|
|
virtual void Tick(float DeltaTime) override;
|
|
virtual void ApplyWorldOffset(const FVector& InOffset, bool bWorldShift) override;
|
|
virtual void OnConstruction(const FTransform& Transform) override;
|
|
virtual void UnregisterAllComponents(bool bForReregister = false) override;
|
|
#if WITH_EDITOR
|
|
virtual bool ShouldTickIfViewportsOnly() const override;
|
|
#endif // WITH_EDITOR
|
|
//~ End AActor Interface
|
|
|
|
//~ Begin UObject Interface
|
|
virtual void BeginDestroy() override;
|
|
virtual void Serialize(FArchive& Ar) override;
|
|
virtual void PostLoad() override;
|
|
#if WITH_EDITOR
|
|
virtual void PreEditChange(FProperty* PropertyThatWillChange) override;
|
|
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
|
#endif // WITH_EDITOR
|
|
//~ End UObject Interface
|
|
|
|
void UpdateCollisionProfile();
|
|
|
|
private:
|
|
#if WITH_EDITORONLY_DATA
|
|
UPROPERTY(Transient)
|
|
TObjectPtr<AActor> VoxelWorldEditor;
|
|
#endif
|
|
|
|
UPROPERTY(Transient)
|
|
mutable TObjectPtr<UVoxelMultiplayerInterface> MultiplayerInterfaceInstance;
|
|
|
|
UPROPERTY(Transient)
|
|
TObjectPtr<UVoxelGeneratorCache> GeneratorCache = nullptr;
|
|
|
|
UPROPERTY(Transient)
|
|
TObjectPtr<UVoxelPlaceableItemActorHelper> PlaceableItemActorHelper = nullptr;
|
|
|
|
UPROPERTY()
|
|
bool bIsToggled = false;
|
|
|
|
bool bIsCreated = false;
|
|
bool bIsLoaded = false;
|
|
EVoxelPlayType PlayType = EVoxelPlayType::Game;
|
|
double TimeOfCreation = 0;
|
|
|
|
#if WITH_EDITOR
|
|
// Temporary variable set in PreEditChange to avoid re-registering proc meshes
|
|
bool bDisableComponentUnregister = false;
|
|
#endif
|
|
|
|
private:
|
|
TVoxelSharedPtr<FVoxelDebugManager> DebugManager;
|
|
TVoxelSharedPtr<FVoxelData> Data;
|
|
TVoxelSharedPtr<IVoxelPool> Pool;
|
|
TVoxelSharedPtr<IVoxelRenderer> Renderer;
|
|
TVoxelSharedPtr<IVoxelLODManager> LODManager;
|
|
TVoxelSharedPtr<FVoxelEventManager> EventManager;
|
|
TVoxelSharedPtr<FVoxelToolRenderingManager> ToolRenderingManager;
|
|
|
|
TVoxelSharedRef<FIntVector> WorldOffset = MakeVoxelShared<FIntVector>(FIntVector::ZeroValue);
|
|
TVoxelSharedRef<FVoxelLODDynamicSettings> LODDynamicSettings = TVoxelSharedPtr<FVoxelLODDynamicSettings>().ToSharedRef(); // else the VTABLE constructor doesn't compile...
|
|
TVoxelSharedRef<FVoxelRendererDynamicSettings> RendererDynamicSettings = TVoxelSharedPtr<FVoxelRendererDynamicSettings>().ToSharedRef();
|
|
|
|
TVoxelSharedPtr<FGameThreadTasks> GameThreadTasks;
|
|
|
|
private:
|
|
void OnWorldLoadedCallback();
|
|
|
|
TVoxelSharedRef<FVoxelDebugManager> CreateDebugManager() const;
|
|
TVoxelSharedRef<FVoxelData> CreateData() const;
|
|
TVoxelSharedRef<IVoxelPool> CreatePool() const;
|
|
TVoxelSharedRef<IVoxelRenderer> CreateRenderer() const;
|
|
TVoxelSharedRef<IVoxelLODManager> CreateLODManager() const;
|
|
TVoxelSharedPtr<FVoxelEventManager> CreateEventManager() const;
|
|
TVoxelSharedPtr<FVoxelToolRenderingManager> CreateToolRenderingManager() const;
|
|
|
|
void CreateWorldInternal(const FVoxelWorldCreateInfo& Info);
|
|
void DestroyWorldInternal();
|
|
void DestroyVoxelComponents();
|
|
|
|
public:
|
|
void LoadFromSaveObject();
|
|
void ApplyPlaceableItems();
|
|
|
|
void UpdateDynamicLODSettings() const;
|
|
void UpdateDynamicRendererSettings() const;
|
|
void ApplyCollisionSettingsToRoot() const;
|
|
|
|
void RecreateRender();
|
|
void RecreateSpawners();
|
|
void RecreateAll(const FVoxelWorldCreateInfo& Info);
|
|
|
|
#if WITH_EDITOR
|
|
FSimpleMulticastDelegate OnPropertyChanged;
|
|
FSimpleMulticastDelegate OnPropertyChanged_Interactive;
|
|
|
|
void Toggle();
|
|
void CreateInEditor(const FVoxelWorldCreateInfo& Info = {});
|
|
void SaveData();
|
|
void LoadFromSaveObjectEditor();
|
|
bool SaveToFile(const FString& Path, FText& Error);
|
|
bool LoadFromFile(const FString& Path, FText& Error);
|
|
FString GetDefaultFilePath() const;
|
|
|
|
//~ Begin IVoxelEditorDelegatesInterface Interface
|
|
virtual void OnPreSaveWorld(uint32 SaveFlags, UWorld* World) override;
|
|
virtual void OnPreBeginPIE(bool bIsSimulating) override;
|
|
virtual void OnEndPIE(bool bIsSimulating) override;
|
|
virtual void OnPrepareToCleanseEditorObject(UObject* Object) override;
|
|
virtual void OnPreExit() override;
|
|
virtual void OnApplyObjectToActor(UObject* Object, AActor* Actor) override;
|
|
//~ End IVoxelEditorDelegatesInterface Interface
|
|
#endif
|
|
};
|
|
|
|
#if WITH_EDITOR
|
|
class VOXEL_API IVoxelWorldEditor
|
|
{
|
|
public:
|
|
virtual ~IVoxelWorldEditor() = default;
|
|
|
|
virtual UVoxelWorldSaveObject* CreateSaveObject() = 0;
|
|
virtual UClass* GetVoxelWorldEditorClass() = 0;
|
|
virtual void RegisterTransaction(AVoxelWorld* VoxelWorld, FName Name) = 0;
|
|
|
|
public:
|
|
// Sets the voxel world editor implementation.*
|
|
static void SetVoxelWorldEditor(TSharedPtr<IVoxelWorldEditor> InVoxelWorldEditor);
|
|
inline static IVoxelWorldEditor* GetVoxelWorldEditor() { return VoxelWorldEditor.Get(); }
|
|
|
|
private:
|
|
// Ptr to interface to voxel editor operations.
|
|
static TSharedPtr<IVoxelWorldEditor> VoxelWorldEditor;
|
|
};
|
|
#endif |