//----------------------------------------------------------------------// // FBlackboardKeySelector //----------------------------------------------------------------------// void FBlackboardKeySelector::ResolveSelectedKey(const UBlackboardData& BlackboardAsset) { if (SelectedKeyName.IsNone() == false || !bNoneIsAllowedValue) { if (SelectedKeyName.IsNone() && !bNoneIsAllowedValue) { InitSelection(BlackboardAsset); } SelectedKeyID = BlackboardAsset.GetKeyID(SelectedKeyName); SelectedKeyType = BlackboardAsset.GetKeyType(SelectedKeyID); } }
void FBlackboardSelectorDetails::OnKeyComboChange(int32 Index) { if (KeyValues.IsValidIndex(Index)) { UBlackboardData* BlackboardAsset = CachedBlackboardAsset.Get(); if (BlackboardAsset) { const uint8 KeyID = BlackboardAsset->GetKeyID(KeyValues[Index]); const UObject* KeyClass = BlackboardAsset->GetKeyType(KeyID); MyKeyClassProperty->SetValue(KeyClass); MyKeyIDProperty->SetValue(KeyID); MyKeyNameProperty->SetValue(KeyValues[Index]); } } }
bool AAIController::InitializeBlackboard(UBlackboardComponent& BlackboardComp, UBlackboardData& BlackboardAsset) { check(BlackboardComp.GetOwner() == this); if (BlackboardComp.InitializeBlackboard(BlackboardAsset)) { // find the "self" key and set it to our pawn const FBlackboard::FKey SelfKey = BlackboardAsset.GetKeyID(FBlackboard::KeySelf); if (SelfKey != FBlackboard::InvalidKey) { BlackboardComp.SetValue<UBlackboardKeyType_Object>(SelfKey, GetPawn()); } OnUsingBlackBoard(&BlackboardComp, &BlackboardAsset); return true; } return false; }
bool UMyBlackboardComponent::PushBlackboard(UBlackboardData* NewAsset, TArray<struct FBlackboardKeySelector> &Params) { UAISystem* AISystem = UAISystem::GetCurrentSafe(GetWorld()); if (AISystem == nullptr) { return false; } //makes a copy of the blackboard //otherwise the data in the bb can be owerwritten by other calls or other instances UBlackboardData* NewAssetCopy = CopyBlackboardData(NewAsset); //save current bb on stack BBStack.Add(BlackboardAsset); UBlackboardData* OldAsset = BlackboardAsset; //and replace it by new bb BlackboardAsset = NewAssetCopy; bool bSuccess = true; const int32 NumKeys = NewAssetCopy->Keys.Num(); //make old bb parent of new bb NewAssetCopy->Parent = OldAsset; //update first key id accordingly NewAssetCopy->UpdateKeyIDs(); TArray<FBlackboardInitializationData> InitList; InitList.Reserve(NumKeys); //grow ValueOffsets to contain new bb offsets ValueOffsets.AddZeroed(NumKeys); for (int32 KeyIndex = 0; KeyIndex < NumKeys; KeyIndex++) { if (NewAssetCopy->Keys[KeyIndex].KeyType) { InitList.Add(FBlackboardInitializationData(KeyIndex + NewAssetCopy->GetFirstKeyID(), NewAssetCopy->Keys[KeyIndex].KeyType->GetValueSize())); } } // sort key values by memory size, so they can be packed better // it still won't protect against structures, that are internally misaligned (-> uint8, uint32) // but since all Engine level keys are good... InitList.Sort(FBlackboardInitializationData::FMemorySort()); uint16 MemoryOffset = 0; for (int32 Index = 0; Index < InitList.Num(); Index++) { ValueOffsets[InitList[Index].KeyID] = MemoryOffset + ValueMemory.Num(); MemoryOffset += InitList[Index].DataSize; } //grow ValueMemory to contain new bb data //(also allows memory for parameters, this is not really neaded, to improve...) ValueMemory.AddZeroed(MemoryOffset); // initialize memory for (int32 Index = 0; Index < InitList.Num(); Index++) { const FBlackboardEntry* KeyData = BlackboardAsset->GetKey(InitList[Index].KeyID); uint8* RawData = GetKeyRawData(InitList[Index].KeyID); KeyData->KeyType->Initialize(RawData); } int32 ParamIndex = 0; for (int32 KeyIndex = 0; KeyIndex < NumKeys && ParamIndex<Params.Num(); KeyIndex++) { //for each parameter if (NewAssetCopy->Keys[KeyIndex].KeyType&&NewAssetCopy->Keys[KeyIndex].EntryName.ToString().StartsWith("PARAM_")) { FBlackboard::FKey ParentKeyID = OldAsset->GetKeyID(Params[ParamIndex].SelectedKeyName); FBlackboard::FKey ChildKeyID = BlackboardAsset->GetKeyID(BlackboardAsset->Keys[KeyIndex].EntryName); if (ParentKeyID != FBlackboard::InvalidKey && ChildKeyID != FBlackboard::InvalidKey) { //redirect ValueOffset to the memory location of the actual argument ValueOffsets[ChildKeyID] = ValueOffsets[ParentKeyID]; //add observer to propagate notifications to actual argument observers DelegateHandles.Add(FMyKeyDelegate(ChildKeyID, RegisterObserver(ChildKeyID, this, FOnBlackboardChange::CreateLambda([this, ParentKeyID](const UBlackboardComponent& BComp, FBlackboard::FKey ChangedKeyID){ this->CallNotifyObservers(ParentKeyID); })))); ParamIndex++; } } } //saves number of parameters found ParamsNumStack.Add(ParamIndex); return bSuccess; }