void FBlackboardDecoratorDetails::OnKeyIDChanged() { CachedOperationType = EBlackboardKeyOperation::Basic; CachedKeyType = NULL; UBlackboardData* Blackboard = CachedBlackboardAsset.Get(); if (Blackboard == NULL) { return; } uint8 KeyID; FPropertyAccess::Result Result = KeyIDProperty->GetValue(KeyID); if (Result == FPropertyAccess::Success) { const FBlackboardEntry* KeyEntry = Blackboard->GetKey(KeyID); if(KeyEntry && KeyEntry->KeyType) { CachedKeyType = KeyEntry->KeyType->GetClass(); CachedOperationType = KeyEntry->KeyType->GetTestOperation(); } else { CachedKeyType = nullptr; CachedOperationType = 0; } } // special handling of enum type: cache all names for combo box (display names) UEnum* SelectedEnumType = NULL; if (CachedKeyType == UBlackboardKeyType_Enum::StaticClass()) { const FBlackboardEntry* EntryInfo = Blackboard->GetKey(KeyID); SelectedEnumType = ((UBlackboardKeyType_Enum*)(EntryInfo->KeyType))->EnumType; } else if (CachedKeyType == UBlackboardKeyType_NativeEnum::StaticClass()) { const FBlackboardEntry* EntryInfo = Blackboard->GetKey(KeyID); SelectedEnumType = ((UBlackboardKeyType_NativeEnum*)(EntryInfo->KeyType))->EnumType; } if (SelectedEnumType) { CachedCustomObjectType = SelectedEnumType; EnumPropValues.Reset(); if (CachedCustomObjectType) { for (int32 i = 0; i < CachedCustomObjectType->NumEnums() - 1; i++) { FString DisplayedName = CachedCustomObjectType->GetEnumText(i).ToString(); EnumPropValues.Add(DisplayedName); } } } }
//----------------------------------------------------------------------// // 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; }