2021-09-28 13:33:17 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "SmartObjectRuntime.h"
const FSmartObjectClaimHandle FSmartObjectClaimHandle : : InvalidHandle = { } ;
const FSmartObjectSlotRuntimeData FSmartObjectSlotRuntimeData : : InvalidSlot = { } ;
//----------------------------------------------------------------------//
// FSmartObjectRuntime
//----------------------------------------------------------------------//
2021-11-26 09:52:13 -05:00
FSmartObjectRuntime : : FSmartObjectRuntime ( const USmartObjectDefinition & InDefinition )
: Definition ( & InDefinition )
2021-09-28 13:33:17 -04:00
, SharedOctreeID ( MakeShareable ( new FSmartObjectOctreeID ( ) ) )
{
}
2021-11-29 11:23:00 -05:00
ESmartObjectSlotState FSmartObjectRuntime : : GetSlotState ( const uint32 SlotIndex ) const
{
for ( const FSmartObjectSlotRuntimeData & SlotRuntimeData : SlotsRuntimeData )
{
if ( SlotRuntimeData . SlotIndex = = SlotIndex )
{
return SlotRuntimeData . State ;
}
}
return ESmartObjectSlotState : : Free ;
}
2021-09-28 13:33:17 -04:00
uint32 FSmartObjectRuntime : : FindFreeSlots ( TBitArray < > & OutFreeSlots ) const
{
2021-11-26 12:55:06 -05:00
const int32 NumSlotDefinitions = GetDefinition ( ) . GetSlots ( ) . Num ( ) ;
2021-09-28 13:33:17 -04:00
// slots are considered free unless they are marked as being used in runtime slots
OutFreeSlots . Init ( /*Value=*/ true , NumSlotDefinitions ) ;
uint32 TakenSlots = 0 ;
2021-11-26 09:52:13 -05:00
// We may have less runtime slots than we have in the definition so we need to fetch the actual index from them.
2021-09-28 13:33:17 -04:00
for ( const FSmartObjectSlotRuntimeData & SlotRuntimeData : SlotsRuntimeData )
{
if ( OutFreeSlots . IsValidIndex ( SlotRuntimeData . SlotIndex ) & & SlotRuntimeData . State ! = ESmartObjectSlotState : : Free )
{
+ + TakenSlots ;
OutFreeSlots [ SlotRuntimeData . SlotIndex ] = false ;
}
}
return NumSlotDefinitions - TakenSlots ;
}
bool FSmartObjectRuntime : : ClaimSlot ( const FSmartObjectClaimHandle & ClaimHandle )
{
if ( ! ensureMsgf ( ClaimHandle . IsValid ( ) , TEXT ( " Attempting to claim using an invalid handle: %s " ) , * ClaimHandle . Describe ( ) ) )
{
return false ;
}
FSmartObjectSlotRuntimeData * ExistingEntry = SlotsRuntimeData . FindByPredicate (
[ ClaimHandle ] ( const FSmartObjectSlotRuntimeData & Entry ) { return Entry . SlotIndex = = ClaimHandle . SlotIndex ; } ) ;
2021-11-02 11:09:09 -04:00
FSmartObjectSlotRuntimeData & SlotRuntimeData = ExistingEntry ! = nullptr ? * ExistingEntry : SlotsRuntimeData . Add_GetRef ( FSmartObjectSlotRuntimeData ( ClaimHandle . SlotIndex ) ) ;
2021-09-28 13:33:17 -04:00
const bool bClaimed = SlotRuntimeData . Claim ( ClaimHandle . UserID ) ;
return bClaimed ;
}
bool FSmartObjectRuntime : : ReleaseSlot ( const FSmartObjectClaimHandle & ClaimHandle , const bool bAborted )
{
bool bRemoved = false ;
2021-11-26 09:52:13 -05:00
// The slot index in the handle refers to the index in the definition so we need to fetch it from the runtime data.
2021-09-28 13:33:17 -04:00
for ( int32 EntryIndex = 0 ; EntryIndex < SlotsRuntimeData . Num ( ) ; + + EntryIndex )
{
FSmartObjectSlotRuntimeData & SlotRuntimeData = SlotsRuntimeData [ EntryIndex ] ;
const ESmartObjectSlotState State = SlotRuntimeData . State ;
if ( SlotRuntimeData . SlotIndex ! = ClaimHandle . SlotIndex )
{
continue ;
}
if ( State ! = ESmartObjectSlotState : : Claimed & & State ! = ESmartObjectSlotState : : Occupied )
{
UE_LOG ( LogSmartObject , Error , TEXT ( " Expected slot state is 'Claimed' or 'Occupied' but current state is '%s'. Slot will not be released " ) ,
* UEnum : : GetValueAsString ( SlotRuntimeData . State ) ) ;
break ;
}
if ( ClaimHandle . UserID ! = SlotRuntimeData . User )
{
UE_LOG ( LogSmartObject , Error , TEXT ( " User '%s' is trying to release slot claimed or used by other user '%s'. Slot will not be released " ) ,
* ClaimHandle . UserID . Describe ( ) , * SlotRuntimeData . User . Describe ( ) ) ;
break ;
}
if ( bAborted )
{
const bool bFunctionWasExecuted = SlotRuntimeData . OnSlotInvalidatedDelegate . ExecuteIfBound ( ClaimHandle , SlotRuntimeData . State ) ;
UE_LOG ( LogSmartObject , Verbose , TEXT ( " Slot invalidated callback was%scalled for slot %s " ) , bFunctionWasExecuted ? TEXT ( " " ) : TEXT ( " not " ) , * SlotRuntimeData . Describe ( ) ) ;
}
SlotsRuntimeData . RemoveAtSwap ( EntryIndex , 1 , /*bAllowShrinking=*/ false ) ;
bRemoved = true ;
break ;
}
return bRemoved ;
}
bool FSmartObjectRuntime : : UseSlot ( const FSmartObjectClaimHandle & ClaimHandle )
{
if ( ! ensureMsgf ( ClaimHandle . IsValid ( ) , TEXT ( " A valid claim handle is required to use a slot: %s " ) , * ClaimHandle . Describe ( ) ) )
{
return false ;
}
2021-11-26 09:52:13 -05:00
// The slot index in the handle refers to the index in the definition so we need to fetch it from the runtime data.
2021-09-28 13:33:17 -04:00
for ( FSmartObjectSlotRuntimeData & SlotRuntimeData : SlotsRuntimeData )
{
if ( SlotRuntimeData . SlotIndex = = ClaimHandle . SlotIndex )
{
ensureMsgf ( SlotRuntimeData . User = = ClaimHandle . UserID , TEXT ( " Attempt to use slot %s from handle %s but already assigned to %s " )
, * SlotRuntimeData . Describe ( ) , * ClaimHandle . Describe ( ) , * SlotRuntimeData . User . Describe ( ) ) ;
SlotRuntimeData . State = ESmartObjectSlotState : : Occupied ;
return true ;
}
}
ensureMsgf ( false , TEXT ( " Should have been claimed first: %s " ) , * ClaimHandle . Describe ( ) ) ;
return false ;
}
//----------------------------------------------------------------------//
// FSmartObjectSlotRuntimeData
//----------------------------------------------------------------------//
bool FSmartObjectSlotRuntimeData : : Claim ( const FSmartObjectUserID & InUser )
{
if ( State = = ESmartObjectSlotState : : Free )
{
State = ESmartObjectSlotState : : Claimed ;
User = InUser ;
return true ;
}
return false ;
}