// Copyright 2020 Phyronnaz #pragma once #include "CoreMinimal.h" #include "VoxelValue.h" #include "VoxelMaterial.h" #include "VoxelIntBox.h" #include "Templates/SubclassOf.h" #include "VoxelGenerators/VoxelGenerator.h" struct FVoxelItemStack; struct FVoxelGeneratorInit; class UMaterialInstanceDynamic; template struct TVoxelRange; template class TVoxelQueryZone; /** * A FVoxelGeneratorInstance is a constant object created by a UVoxelGenerator */ class VOXEL_API FVoxelGeneratorInstance : public TVoxelSharedFromThis { public: template using TOutputFunctionPtr = T(FVoxelGeneratorInstance::*)(v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; template using TRangeOutputFunctionPtr = TVoxelRange(FVoxelGeneratorInstance::*)(const FVoxelIntBox& Bounds, int32 LOD, const FVoxelItemStack& Items) const; struct FBaseFunctionPtrs { TOutputFunctionPtr Value; TOutputFunctionPtr Material; TRangeOutputFunctionPtr ValueRange; }; struct FCustomFunctionPtrs { TMap> Float; TMap> Int; TMap> Color; TMap> FloatRange; }; public: FVoxelGeneratorInstance( TSubclassOf Class, const UVoxelGenerator* Object, const FBaseFunctionPtrs& BasePtrs, const FCustomFunctionPtrs& CustomPtrs) : Class(Class) , Object(Object) , BasePtrs(BasePtrs) , CustomPtrs(CustomPtrs) { check(Class); check(BasePtrs.Value); check(BasePtrs.Material); check(BasePtrs.ValueRange); } virtual ~FVoxelGeneratorInstance() = default; public: // Used for serialization const TSubclassOf Class; const TSoftObjectPtr Object; const FBaseFunctionPtrs BasePtrs; const FCustomFunctionPtrs CustomPtrs; template const TMap>& GetOutputsPtrMap() const; template const TMap>& GetOutputsRangesPtrMap() const; public: //~ Begin FVoxelGeneratorInstance Interface // Initialization virtual void Init(const FVoxelGeneratorInit& InitStruct) {} // Called before a chunk is computed // Needs to be thread safe! // EXPERIMENTAL virtual void InitArea(const FVoxelIntBox& Bounds, int32 LOD) {} // Will be called on every chunk material instance // Can be used eg to pass a texture per chunk // EXPERIMENTAL virtual void SetupMaterialInstance(int32 ChunkLOD, const FVoxelIntBox& ChunkBounds, UMaterialInstanceDynamic* Instance) {} // You should implement a fast version of that function, called every time a chunk is updated virtual void GetValues (TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const = 0; // This function is only called when a chunk material is edited for the first time. Fine to leave as default virtual void GetMaterials(TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const = 0; // World up vector at position (must be normalized). Used for spawners virtual FVector GetUpVector(v_flt X, v_flt Y, v_flt Z) const = 0; //~ End FVoxelGeneratorInstance Interface public: v_flt GetValue(v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; FVoxelMaterial GetMaterial(v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; TVoxelRange GetValueRange(const FVoxelIntBox& Bounds, int32 LOD, const FVoxelItemStack& Items) const; template T Get(v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; template void Get(TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const; template T Get(const FIntVector& P, int32 LOD, const FVoxelItemStack& Items) const; template FVector GetUpVector(const TVector& P) const; template T GetCustomOutput(T DefaultValue, FName Name, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; template T GetCustomOutput(T DefaultValue, FName Name, const U& P, int32 LOD, const FVoxelItemStack& Items) const; template TVoxelRange GetCustomOutputRange(TVoxelRange DefaultValue, FName Name, const FVoxelIntBox& Bounds, int32 LOD, const FVoxelItemStack& Items) const; }; class VOXEL_API FVoxelTransformableGeneratorInstance : public FVoxelGeneratorInstance { public: template using TOutputFunctionPtr_Transform = T(FVoxelTransformableGeneratorInstance::*)(const FTransform& LocalToWorld, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; template using TRangeOutputFunctionPtr_Transform = TVoxelRange(FVoxelTransformableGeneratorInstance::*)(const FTransform& LocalToWorld, const FVoxelIntBox& WorldBounds, int32 LOD, const FVoxelItemStack& Items) const; struct FBaseFunctionPtrs_Transform { TOutputFunctionPtr_Transform Value; TOutputFunctionPtr_Transform Material; TRangeOutputFunctionPtr_Transform ValueRange; }; struct FCustomFunctionPtrs_Transform { TMap> Float; TMap> Int; TMap> Color; TMap> FloatRange; }; public: FVoxelTransformableGeneratorInstance( TSubclassOf Class, const UVoxelTransformableGenerator* Object, const FBaseFunctionPtrs& BasePtrs, const FCustomFunctionPtrs& CustomPtrs, const FBaseFunctionPtrs_Transform& BasePtrs_Transform, const FCustomFunctionPtrs_Transform& CustomPtrs_Transform) : FVoxelGeneratorInstance(Class, Object, BasePtrs, CustomPtrs) , BasePtrs_Transform(BasePtrs_Transform) , CustomPtrs_Transform(CustomPtrs_Transform) { check(BasePtrs_Transform.Value); check(BasePtrs_Transform.Material); check(BasePtrs_Transform.ValueRange); if (auto* GeneratorWithBounds = Cast(Object)) { GeneratorBounds = GeneratorWithBounds->GetBounds(); } } bool HasBounds() const { return GeneratorBounds.IsSet(); } FVoxelIntBox GetBounds() const { return GeneratorBounds.GetValue(); } private: TOptional GeneratorBounds; public: const FBaseFunctionPtrs_Transform BasePtrs_Transform; const FCustomFunctionPtrs_Transform CustomPtrs_Transform; template const TMap>& GetOutputsPtrMap_Transform() const; template const TMap>& GetOutputsRangesPtrMap_Transform() const; //~ Begin FVoxelTransformableGeneratorInstance Interface virtual void GetValues_Transform (const FTransform& LocalToWorld, TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const = 0; virtual void GetMaterials_Transform(const FTransform& LocalToWorld, TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const = 0; //~ End FVoxelTransformableGeneratorInstance Interface public: v_flt GetValue_Transform(const FTransform& LocalToWorld, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; FVoxelMaterial GetMaterial_Transform(const FTransform& LocalToWorld, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; TVoxelRange GetValueRange_Transform(const FTransform& LocalToWorld, const FVoxelIntBox& WorldBounds, int32 LOD, const FVoxelItemStack& Items) const; template T Get_Transform(const FTransform& LocalToWorld, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; template void Get_Transform(const FTransform& LocalToWorld, TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const; template T Get_Transform(const FTransform& LocalToWorld, const FIntVector& P, int32 LOD, const FVoxelItemStack& Items) const; template T GetCustomOutput_Transform(const FTransform& LocalToWorld, T DefaultValue, FName Name, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const; template TVoxelRange GetCustomOutputRange_Transform(const FTransform& LocalToWorld, TVoxelRange DefaultValue, FName Name, const FVoxelIntBox& Bounds, int32 LOD, const FVoxelItemStack& Items) const; }; VOXEL_DEPRECATED(1.2, "Please use FVoxelGeneratorInstance instead of FVoxelWorldGeneratorInstance.") typedef FVoxelGeneratorInstance FVoxelWorldGeneratorInstance; VOXEL_DEPRECATED(1.2, "Please use FVoxelTransformableGeneratorInstance instead of FVoxelTransformableWorldGeneratorInstance.") typedef FVoxelTransformableGeneratorInstance FVoxelTransformableWorldGeneratorInstance;