Files
UnrealEngineUWP/Engine/Plugins/Runtime/SmartObjects/Source/SmartObjectsModule/Public/SmartObjectRuntime.h
yoan stamant 1cbe440fe2 [SmartObjects]
* Collection entry holds the Transform, Bounds and Index to the shared configuration. This removes the dependency on components being loaded to create runtime data for partitioned worlds.
* Removed commented references to SparseClassData since that approach won't be used (actor component not supported)
* Runtime data now points to a shared configuration from the collection instead of holding a copy
* Subsystem tracks components registered at runtime so the collection can be updated accordingly since those entries won't persist outside of loading range
* Moved most initialization code for the subsystem to the OnWorldComponentsUpdated callback since active level collection is set and actors from the persistent level registered.

[WorldPartitionBuilder]
* Added OnPartitionBuildStarted/OnPartitionBuildCompleted virtual methods
* New UWorldPartitionSmartObjectCollectionBuilder to build SmartObjectCollection in partitioned worlds

#preflight 61814a46fc786a0001447995
#jira UE-105113
#rb maxime.mercier

#ROBOMERGE-AUTHOR: yoan.stamant
#ROBOMERGE-COMMAND: FnMain
#ROBOMERGE-SOURCE: CL 18019580 in //UE5/Main/...
#ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v885-17909292)
#ROBOMERGE[STARSHIP]: UE5-Release-Engine-Staging Release-5.0
#ROBOMERGE[bot1]: Main

[CL 18019655 by yoan stamant in ue5-release-engine-test branch]
2021-11-02 11:12:43 -04:00

200 lines
6.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Delegates/DelegateCombinations.h"
#include "SmartObjectTypes.h"
#include "SmartObjectConfig.h"
#include "SmartObjectOctree.h"
#include "SmartObjectRuntime.generated.h"
/**
* Enumeration to represent the runtime state of a slot
*/
UENUM()
enum class ESmartObjectSlotState : uint8
{
Free,
Claimed,
Occupied,
MAX
};
/**
* Struct describing a reservation between a user and a smart object slot.
*/
USTRUCT()
struct SMARTOBJECTSMODULE_API FSmartObjectClaimHandle
{
GENERATED_BODY()
FSmartObjectClaimHandle(const FSmartObjectID InSmartObjectID, const FSmartObjectSlotIndex& InSlotIndex, const FSmartObjectUserID& InUser = {})
: SmartObjectID(InSmartObjectID), SlotIndex(InSlotIndex), UserID(InUser)
{}
FSmartObjectClaimHandle()
{}
bool operator==(const FSmartObjectClaimHandle& Other) const
{
return IsValid() && Other.IsValid()
&& SmartObjectID == Other.SmartObjectID
&& SlotIndex == Other.SlotIndex
&& UserID == Other.UserID;
}
FString Describe() const
{
return FString::Printf(TEXT("Object:%s Slot:%s User:%s"), *SmartObjectID.Describe(), *SlotIndex.Describe(), *UserID.Describe());
}
void Invalidate() { *this = InvalidHandle; }
bool IsValid() const
{
return SmartObjectID.IsValid()
&& SlotIndex.IsValid()
&& UserID.IsValid();
}
static const FSmartObjectClaimHandle InvalidHandle;
UPROPERTY(Transient)
FSmartObjectID SmartObjectID;
UPROPERTY(Transient)
FSmartObjectSlotIndex SlotIndex;
FSmartObjectUserID UserID;
};
/** Delegate to notify when a given slot gets invalidated and the interaction must be aborted */
DECLARE_DELEGATE_TwoParams(FOnSlotInvalidated, const FSmartObjectClaimHandle&, ESmartObjectSlotState /* Current State */);
/**
* Struct to store and manage state of a runtime instance associated to a given slot configuration
*/
USTRUCT()
struct FSmartObjectSlotRuntimeData
{
GENERATED_BODY()
public:
/* Provide default constructor to be able to compile template instantiation 'UScriptStruct::TCppStructOps<FSmartObjectSlotRuntimeData>' */
/* Also public to pass void 'UScriptStruct::TCppStructOps<FSmartObjectSlotRuntimeData>::ConstructForTests(void *)' */
FSmartObjectSlotRuntimeData() {}
protected:
/** Struct could have been nested inside the subsystem but not possible with USTRUCT */
friend class USmartObjectSubsystem;
friend struct FSmartObjectRuntime;
explicit FSmartObjectSlotRuntimeData(const FSmartObjectSlotIndex& InSlotIndex) : SlotIndex(InSlotIndex) {}
bool Claim(const FSmartObjectUserID& InUser);
FString Describe() const { return FString::Printf(TEXT("User:%s Slot:%s"), *User.Describe(), *SlotIndex.Describe()); }
static const FSmartObjectSlotRuntimeData InvalidSlot;
/** Current availability state of the slot */
ESmartObjectSlotState State = ESmartObjectSlotState::Free;
/** Id of the user that reserves or uses the slot */
FSmartObjectUserID User;
/** Index of the slot in the smart object config to which this runtime data is associated to */
FSmartObjectSlotIndex SlotIndex;
/** Delegate used to notify when a slot gets invalidated. See RegisterSlotInvalidationCallback */
FOnSlotInvalidated OnSlotInvalidatedDelegate;
};
/**
* Struct to store and manage state of a runtime instance associated to a given smart object configuration
*/
USTRUCT()
struct FSmartObjectRuntime
{
GENERATED_BODY()
public:
const FSmartObjectID& GetRegisteredID() const { return RegisteredID; }
const FTransform& GetTransform() const { return Transform; }
const FSmartObjectConfig& GetConfig() const { checkf(Config != nullptr, TEXT("Initialized from a valid reference from the constructor")); return *Config; }
/* Provide default constructor to be able to compile template instantiation 'UScriptStruct::TCppStructOps<FSmartObjectRuntime>' */
/* Also public to pass void 'UScriptStruct::TCppStructOps<FSmartObjectRuntime>::ConstructForTests(void *)' */
FSmartObjectRuntime() : SharedOctreeID(MakeShareable(new FSmartObjectOctreeID())) {}
private:
/** Struct could have been nested inside the subsystem but not possible with USTRUCT */
friend class USmartObjectSubsystem;
explicit FSmartObjectRuntime(const FSmartObjectConfig& Config);
const FGameplayTagContainer& GetTags() const { return Tags; }
void SetTransform(const FTransform& Value) { Transform = Value; }
void SetRegisteredID(const FSmartObjectID Value) { RegisteredID = Value; }
const FSmartObjectOctreeIDSharedRef& GetSharedOctreeID() const { return SharedOctreeID; }
void SetOctreeID(const FSmartObjectOctreeIDSharedRef Value) { SharedOctreeID = Value; }
const FBoxCenterAndExtent& GetBounds() const { return Bounds; }
void SetBounds(const FBox& Value) { Bounds = Value; }
FString Describe() const { return FString::Printf(TEXT("Instance using config \'%s\' Reg: %s"), *GetConfig().Describe(), *LexToString(SharedOctreeID->ID.IsValidId())); }
/**
* @param OutFreeSlots function will set 'false' at taken slots' indices
* @return the number of free slots found
*/
uint32 FindFreeSlots(TBitArray<>& OutFreeSlots) const;
/**
* Reserves the slot associated to the provided handle by marking it as 'claimed'.
* @param ClaimHandle Handle identifying a user/slot pair
* @return whether or not the slot was successfully claimed
*/
bool ClaimSlot(const FSmartObjectClaimHandle& ClaimHandle);
/**
* Mark an available slot as 'occupied'.
* @param ClaimHandle Handle identifying a user/slot pair
* @return whether or not the slot was successfully marked as 'occupied'
*/
bool UseSlot(const FSmartObjectClaimHandle& ClaimHandle);
/**
* Releases the slot associated to the provided handle by marking it as 'free'.
* The operation will ensure if the slot is not currently claimed or in use by the user associated to the handle.
* @param ClaimHandle A valid handle identifying a user/slot pair
* @param bAborted Indicates if the slot must be released because the slot has been invalidated by the system (e.g. unregistered object)
* @return whether or not the slot was successfully freed
*/
bool ReleaseSlot(const FSmartObjectClaimHandle& ClaimHandle, const bool bAborted);
/** Runtime data associated to each defined slot */
UPROPERTY()
TArray<FSmartObjectSlotRuntimeData> SlotsRuntimeData;
/** Associated smart object configuration */
const FSmartObjectConfig* Config = nullptr;
/** Instance specific transform */
FTransform Transform;
/** Instance specific bounds */
FBoxCenterAndExtent Bounds;
/** Tags applied to the current instance */
FGameplayTagContainer Tags;
/** RegisteredID != FSmartObject::InvalidID when registered with SmartObjectSubsystem */
FSmartObjectID RegisteredID;
/** Reference to the associated octree node ID */
FSmartObjectOctreeIDSharedRef SharedOctreeID;
};