Section 4. rdSpawnActor

Section 4.1. rdSpawnActor – Event Handlers

// [rdInst v1.35] Handles dragged in assets and setup
virtual void OnConstruction(const FTransform &Transform) override;

// [rdInst v1.35] spawns data if in proximity and registers the actor
virtual void BeginPlay() override;

// [rdInst v1.35] removes the actor from the register
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

// [rdInst v1.35] removes from the register and removes spawned objects
virtual void BeginDestroy() override;

// [rdInst v1.35] Overridable function to do custom spawning
void rdSpawnEvent();

// [rdInst v1.35] Overridable function to bake the custom spawning
void rdBakeEvent();

// [rdInst v1.50] Used to compile list of used assets for migrating and packaging
virtual void PreSave(const class ITargetPlatform* TargetPlatform);


Section 4.2. rdSpawnActor – Loading, Streaming and Spawning

// [rdInst v1.35] Spawns the Objects described in the list of items
virtual void rdSpawn();

// [rdInst v1.35] Removes all the Spawned Objects
virtual void rdClearSpawn();

// [rdInst v1.50] Gets the current SpawnDatas BakedDataAsset, note that this can be a duplicate when 'sharedDataAsset' is unticked
UrdBakedDataAsset* GetBakedDataAsset(bool bLoad=true);

// [rdInst v1.35] Clears the Baked Data
void rdClearBakedData();

// [rdInst v1.35] Sets the SpawnData to an existing BakedDataAsset
void SetBakedDataAsset(UrdBakedDataAsset* dataAsset);

// [rdInst v1.50] Synchronisly Loads the Baked Data and contained Assets
void rdBlockingLoad();

// [rdInst v1.50] Loads the Baked Data Asset and contained Assets in another thread
void rdAsyncLoad();

// [rdInst v1.50] Synchronisly loads the Assets referenced in the Baked/Unbaked Data
void rdBlockingLoadAssets();

// [rdInst v1.50] Loads all the Assets referenced in the Unbaked Data in another thread
void rdAsyncLoadAllAssets();
void rdAsyncLoadAllAssetsFinished();

// [rdInst v1.50] Loads all the Assets referenced in the Baked Data in another thread
void rdAsyncLoadAllBakedAssets();
void rdAsyncLoadAllBakedAssetsFinished();

// [rdInst v1.50] Loads the Assets referenced in the Baked Data marked as "To Load" in another thread
void rdAsyncLoadMarkedBakedAssets();
void rdAsyncLoadMarkedBakedAssetsFinished();

// [rdInst v1.50] Unloads the Spawn Baked Data
void rdUnloadData();

// [rdInst v1.50] Unloads all Assets (not used in the rest of the level) from this SpawnActor
void rdUnloadAllAssets();

// [rdInst v1.50] Unloads all marked Assets (not used in the rest of the level) from this SpawnActor
void rdUnloadMarkedAssets();

// [rdInst v1.50] Fully load all baked data and Asset data
void rdFullyLoad();

// [rdInst v1.50] Fully unload all baked data and Asset data
void rdFullyUnload();

// [rdInst v1.50] 
void rdSpawnNewlyStreamed();

// [rdInst v1.50] Returns the origin of the SpawnActor (center - half bounds) as a Transform
FTransform rdGetSpawnOriginTransform() const;

// [rdInst v1.50] Returns the origin of the SpawnActor (center - half bounds)
FVector rdGetSpawnOrigin() const;

// [rdInst v1.50] Returns the Distance at which to spawn objects when using the population spawn types
double rdGetSpawnDistance();

// [rdInst v1.50] Returns the Bounds of the Spawner Volume
const FBoxSphereBounds rdGetSpawnerBounds() const;

// [rdInst v1.50] Returns the BoundingBox of the Spawner Volume
const FBox rdGetSpawnerBoundingBox() const;

// [rdInst v1.50] Returns the Center of the Spawner Volume in World Space
const FVector rdGetSpawnerCenter() const;

// [rdInst v1.50] Returns the Size of the Spawner Volume in Unreal Units
const FVector rdGetSpawnerSize() const;

// [rdInst v1.50] Returns the Radius of the Spawner Volume in Unreal Units
const float rdGetSpawnerRadius() const;

// [rdInst v1.50] 
void ProcessStreamingObjects(float dist);

// [rdInst v1.50] Marks the SpawnActor ready to Spawn when possible
virtual void rdMarkForStreamIn(FrdBakedSpawnObjects& bso);

// [rdInst v1.50] Marks the SpawnActor ready to Despawn when possible
virtual void rdMarkForStreamOut(FrdBakedSpawnObjects& bso);

// [rdInst v1.50] Overridable function to do custom spawning
void rdSpawnEvent();

// [rdInst v1.50] Overridable function to bake the custom spawning
void rdBakeEvent();

// [rdInst v1.50] Add Instances you've spawned in Custom Spawners to this list
void rdAddSpawnedInstance(const FrdObjectPlacementData& placementData,int32 instance);

// [rdInst v1.50] Add Actors and Prefabs you've spawned in Custom Spawners to this list
void rdAddSpawnedActor(const FrdObjectPlacementData& placementData,AActor* actor);

// [rdInst v1.50] Add VFX you've spawned in Custom Spawners to this list
void rdAddSpawnedVFX(const FrdObjectPlacementData& placementData,UNiagaraComponent* vfx);

// [rdInst v1.50] Remove the Instance from the Spawn Actor specified by Instance Index
bool rdRemoveInstanceByIndex(const FName sid,int32 index);

// [rdInst v1.50] Remove the Instance from the Spawn Actor specified by Location
bool rdRemoveInstanceByLocation(const FName sid,const FVector& location);

// [rdInst v1.50] Remove the Actor from the Spawn Actor
bool rdRemoveActor(const AActor* actor);

// [rdInst v1.50] Remove the VFX from the Spawn Actor
bool rdRemoveVFX(const UNiagaraComponent* vfx);

// [rdInst v1.50] Remove the Instances from the Spawn Actor that fall within specified radius of the Location
int32 rdRemoveInstancesWithinRadius(const FName sid,const FVector& location,const float radius);

// [rdInst v1.50] Remove All Instances from the Spawn Actor that fall within specified radius of the Location
int32 rdRemoveAllInstancesWithinRadius(const FVector& location,const float radius);

// [rdInst v1.50] Remove All Objects from the Spawn Actor that fall within specified radius of the Location
int32 rdRemoveAllObjectsWithinRadius(const FVector& location,const float radius);

// [rdInst v1.50] Changes all Instances of Sid1 with Sid2 within the radius of the Location
int32 rdChangeInstancesWithinRadius(const FName sid1,const FName sid2,const FVector& location,const float radius);

// [rdInst v1.50] Changes all Instances of the Sid1 Array with the Sid2 Array within the radius of the Location
int32 rdChangeInstanceListWithinRadius(const TArray<FName>& sidList1,const TArray<FName> sidList22,const FVector& location,const float radius);

// [rdInst v1.50] Spawn the Object from the PlacementData at the transform
void rdSpawnObject(UPARAM(ref) FrdObjectPlacementData& placementData,const FTransform& transform);

// [rdInst v1.50] Updates the Placement Data from any DataAssets used
virtual void rdUpdateFromDataAssets();


Section 4.3. rdSpawnActor – Baking

// [rdInst v1.35] Bakes the spawn items into lists ready to be spawned very quickly
virtual void rdBakeSpawnData(const FrdSpawnData& bakeData);

// [rdInst v1.35] Bakes the spawn items into lists ready to be spawned very quickly
virtual void rdBakeSpawnData();

// [rdInst v1.35] Clears the Baked Data
virtual void rdClearBakedData();

// [rdInst v1.50] Add Objects to the Baked Data in Custom Spawners with this function
void rdAddBakedObject(const FrdObjectPlacementData& placementData,const FTransform& transform);

// [rdInst v1.50] Add Mesh Instances to the Baked Data in Custom Spawners with this function
void rdAddBakedInstance(const FrdObjectPlacementData& placementData,UStaticMesh* mesh,const FTransform& transform);

// [rdInst v1.50] Add Mesh Instances to the Baked Data in Custom Spawners with this function
void rdAddBakedInstanceX(const FrdObjectPlacementData& opd,const FName sid,const FTransform& t);

// [rdInst v1.50] Add Actors to the Baked Data in Custom Spawners with this function
void rdAddBakedActor(const FrdObjectPlacementData& placementData,UClass* actorClass,const FTransform& transform);

// [rdInst v1.50] Add VFX to the Baked Data in Custom Spawners with this function
void rdAddBakedVFX(const FrdObjectPlacementData& placementData,UNiagaraSystem* vfx,const FTransform& transform);

// [rdInst v1.50] Add Mesh Instances to the Baked Data in Custom Spawners or PCG nodes with this function
void rdAddBakedInstances(const FName sid,const TArray<FTransform>& t);


Section 4.4. rdSpawnActor – Utilities

// [rdInst v1.35] Does a SphereTrace, returning found actors and instances, if there is Baked data, it scans those transforms
void rdSphereTrace(const FVector location,float radius,TArray<AActor*>& actors,TArray<FrdInstanceItems>& instances,TArray<AActor*>& ignoreActors);

// [rdInst v1.35] Returns the Distance of the current spawnData (float in 4.27)
double rdGetSpawnDistance();

// [rdInst v1.35] Returns the Bounds of the Spawner Volume
const FBoxSphereBounds rdGetSpawnerBounds() const;

// [rdInst v1.35] Returns the BoundingBox of the Spawner Volume
const FBox rdGetSpawnerBoundingBox() const;

// [rdInst v1.35] Returns the Center of the Spawner Volume in World Space
const FVector rdGetSpawnerCenter() const;

// [rdInst v1.35] Returns the Size of the Spawner Volume in Unreal Units
const FVector rdGetSpawnerSize() const;

// [rdInst v1.50] Returns the Radius of the Spawner Volume in Unreal Units
const float rdGetSpawnerRadius() const;

// [rdInst v1.35] Set the Spawner to the same size as the landscape
void rdSnapToLandscape();

// [rdInst v1.50] Finds the landscape z position at 'loc', optionally ignoring physmats and fixing slopes
bool rdTraceToLandscape(const FrdObjectPlacementData& opd,const FTransform& transform,FTransform& outTransform,bool addToZ=false);

// [rdInst v1.50] Returns True if 'loc' is inside the NavMesh space or no NavMesh
bool rdIsOnNavMesh(const FVector& loc,const FVector& ext);

// [rdInst v1.50] Returns an Array of all PlacementData instances
TArray<FrdObjectPlacementData>& rdGetPlacementData();

// [rdInst v1.50] Returns the ProxyState Pointer (if exists) for the instance
UrdStateDataAsset* rdGetProxyState(const FName sid,int32 index);

// [rdInst v1.50] Returns an Array of all ProxyState Pointers
TArray<FrdProxyStateItem> rdGetAllProxyStates();

// [rdInst v1.50] Returns an Array of all ISMCs used
TArray<UInstancedStaticMeshComponent*> rdGetUsedISMCs();

// [rdInst v1.50] Returns an Array of all Meshes used
TArray<UStaticMesh*> rdGetUsedMeshes();

// [rdInst v1.50] Returns an Array of all SIDs used
TArray<FName> rdGetUsedSIDs();

// [rdInst v1.50] Returns an Array indices being used for the mesh in the SpawnActor
TArray<int32>& rdGetInstanceIndices(UStaticMesh* mesh);

// [rdInst v1.50] Returns an Array indices being used for the mesh in the SpawnStuffActor
TArray<int32>& rdGetInstanceIndicesX(const FName sid);


Section 4.5. rdSpawnActor – Data and Structures

// [rdInst v1.35] Drag Meshes from the content browser into this list in the editor to populate the spawn data
TArray<UStaticMesh*> dragInMeshes;

// [rdInst v1.35] Drag Actors from the content browser into this list in the editor to populate the spawn data
TArray<UObject*> dragInActors;

// [rdInst v1.35] Drag NiagaraSystems from the content browser into this list in the editor to populate the spawn data
TArray<UNiagaraSystem*> dragInVFX;

// [rdInst v1.35] Drag Actors in the level into this list in the editor to populate the spawn data
TArray<AActor*> dragInLiveActors;

// [rdInst v1.35] Object Data that gets spawned
TArray<FrdSpawnStuffData> spawnData={FrdSpawnStuffData()};

// [rdInst v1.35] Current SpawnData index (usually controlled by the scalability level)
int32 currentSpawnDataIndex=0;

// [rdInst v1.35] True when this SpawnActor has spawned
bool hasSpawned=false;

// [rdInst v1.35] non-zero when objects are still spawning with distributed spawns
uint8 isStillSpawning=0;

// [rdInst v1.35] Pointer to the Landscape
ALandscape* landscape=nullptr;

// [rdInst v1.35] Pointer to the Landscape
FVector4 landscapeScale=FVector4(0.0f,0.0f,1.0f,1.0f);

// [rdInst v1.35] Root Component
USceneComponent* popRootComponent=nullptr;

// [rdInst v1.35] Volume Box
UBoxComponent* volumeBox=nullptr;



// [rdInst v1.50] BakedData (rdSpawnActor) DataAsset
UCLASS(BlueprintType)
class RDINST_PLUGIN_API UrdBakedDataAsset : public UPrimaryDataAsset {
	GENERATED_BODY()
public:

	FPrimaryAssetId GetPrimaryAssetId() const override { return FPrimaryAssetId("rdInstBakedDataAssets",GetFName()); }

	// Array of BakedData
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdBakedData)
	TArray<FrdBakedSpawnObjects>	bakedData;

	// Bounds of the entire data
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdBakedData)
	FBoxSphereBounds				bounds;
};


// [rdInst v1.35] FrdSpawnData Structure
// The details of the spawn area and type, the rdSpawnActor has one of these, but when 
//   spawning SpawnPoints - just this struct is stored to avoid the need for unnecessary actors in the level
USTRUCT(BlueprintType)
struct FrdSpawnData {
	GENERATED_BODY()
public:

	// Array of object Placement types
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdSpawnActor)
	TArray<FrdObjectPlacementData> items;

	// The distance at which to spawn items, 0 = always spawn
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdSpawnActor)
	double				distance=0.0f;

	// The bounds of the spawn volume
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdSpawnActor,meta=(IgnoreForMemberInitializationTest))
	FBoxSphereBounds	bounds=FBoxSphereBounds();

	// The over-all density for the spawn data
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdSpawnActor)
	float				mainDensity=1.0f;

	// Width of the grid - the larger the value, the less populated 
	UPROPERTY(Category=rdSpawnActor,EditAnywhere,BlueprintReadWrite)
	float				gridWidth=1000.0f;

	// Height of the grid - the larger the value, the less populated 
	UPROPERTY(Category=rdSpawnActor,EditAnywhere,BlueprintReadWrite)
	float				gridHeight=1000.0f;

	// Splatmap to use for controlling the spawn data
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdSpawnActor)
	UTexture2D*			splatMap=nullptr;

	// Splatmap covers the entire Landscape
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdSpawnActor)
	bool				splatMapCoversLandscape=true;

	// Number of frames to split the spawning over
	UPROPERTY(Category=rdSpawnActor,EditAnywhere,BlueprintReadWrite)
	int32				distributeFrames=1;

	// Data stored by the baking process - do not touch  
	UPROPERTY(BlueprintReadWrite,Category=rdHidden)
	TSoftObjectPtr<UrdBakedDataAsset> bakedDataAsset=nullptr;

	// Data stored by the baking process - do not touch  
	UPROPERTY(BlueprintReadWrite,Category=rdHidden)
	TObjectPtr<UrdBakedDataAsset> bakedData=nullptr;

	// Number of frames to split the spawning over
	UPROPERTY(Category=rdSpawnActor,EditAnywhere,BlueprintReadWrite)
	int32				numBakedMeshes=0;

	// Number of frames to split the spawning over
	UPROPERTY(Category=rdSpawnActor,EditAnywhere,BlueprintReadWrite)
	int32				numBakedInstances=0;

	FVector				center;
};

// [rdInst v1.35] FrdBakedSpawnObjects Structure
// Contains the type of object to create and a list of the transforms
USTRUCT(BlueprintType)
struct RDINST_PLUGIN_API FrdBakedSpawnObjects {
	GENERATED_BODY()
public:

	void rdAsyncLoadEntityAssets();
	void rdAsyncLoadEntityAssetsFinished();

	UPROPERTY(Category=rdBakedSpawnObjects,EditAnywhere)
	FName sid;

	UPROPERTY(Category=rdBakedSpawnObjects,EditAnywhere)
	UClass*			actorClass=nullptr;

	UPROPERTY(Category=rdBakedSpawnObjects,EditAnywhere,meta=(AssetBundles="BakedData"))
	FString			strProps;

	UPROPERTY(Category=rdBakedSpawnObjects,EditAnywhere)
	UNiagaraSystem*	vfx=nullptr;

	UPROPERTY(Category=rdBakedSpawnObjects,EditAnywhere)
	bool			pooled=false;

	UPROPERTY(Category=rdBakedSpawnObjects,EditAnywhere)
	int32			itemIndex=-1;

	UPROPERTY(Category=rdBakedSpawnObjects,EditAnywhere)
	TEnumAsByte<rdSpawnMode> spawnMode=rdSpawnMode::RDSPAWNMODE_DEFAULT;

	// Stream Distance - distance to stream this object in (-1 means use Actors default)
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="rdPlacement|SpawnMode")
	float streamDistance=-1;

	// Current Load State of this Baked Placement set
	UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category="rdPlacement|Streaming")
	TEnumAsByte<rdLoadState> loadState=rdLoadState::RDLOADSTATE_UNLOADED;

	// The Radius to spawn actors from the player when using rdSpawnMode::Local
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdBakedSpawnObjects)
	float localRadius=10000.0f;

	// The Distance to spawn actors within the View Frustum of the player when using rdSpawnMode::ViewFrustum
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdBakedSpawnObjects)
	float viewFrustumDistance=50000.0f;

	// The Extended area around the View Frustum (in degrees) to spawn when using rdSpawnMode::ViewFrustum
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=rdBakedSpawnObjects)
	float viewFrustumExtend=2.0f;

	UPROPERTY(EditDefaultsOnly,Category=rdBakedSpawnObjects)
	FrdGridArray transformMap;

	UPROPERTY(EditDefaultsOnly,Category=rdBakedSpawnObjects)
	FrdProxySetup proxy;
};

// [rdInst v1.50] FrdSpawnDataScanItem
USTRUCT(BlueprintType)
struct RDINST_PLUGIN_API FrdSpawnDataScanItem {
	GENERATED_BODY()
public:
	FrdSpawnDataScanItem() {}
	FrdSpawnDataScanItem(AActor* a,TArray<FrdSpawnData>& sd) : volume(a),spawnDataList(sd) {}

	AActor*					volume=nullptr;
	TArray<FrdSpawnData>	spawnDataList;
};