// Copyright Epic Games, Inc. All Rights Reserved. #include "PoseSearch/Chooser/PoseSearchChooserColumn.h" #include "ChooserIndexArray.h" #include "ChooserPropertyAccess.h" #include "IChooserParameterBool.h" #include "IChooserParameterFloat.h" #include "ChooserTrace.h" #include "PoseSearch/PoseSearchLibrary.h" #include "PoseSearch/PoseSearchDatabase.h" #if WITH_EDITOR #include "StructUtils/PropertyBag.h" #endif bool FPoseHistoryContextProperty::GetValue(FChooserEvaluationContext& Context, FPoseHistoryReference& OutResult) const { const FPoseHistoryReference* Reference; if (Binding.GetValuePtr(Context, Reference)) { OutResult = *Reference; return true; } return false; } FPoseSearchColumn::FPoseSearchColumn() { } #if WITH_EDITOR void FPoseSearchColumn::AutoPopulate(int32 RowIndex, UObject* OutputObject) { if (RowValues.IsValidIndex(RowIndex)) { RowValues[RowIndex].ResultAsset = Cast(OutputObject); } } bool FPoseSearchColumn::EditorTestFilter(int32 RowIndex) const { // todo: not sure how to do editor display for pose search weights (might need to make a copy of the pose history struct) return true; } float FPoseSearchColumn::EditorTestCost(int32 RowIndex) const { // todo: not sure how to do editor display for pose search weights (might need to make a copy of the pose history struct) return 0.0f; } #endif bool FPoseSearchColumn::HasFilters() const { return true; } void FPoseSearchColumn::Filter(FChooserEvaluationContext& Context, const FChooserIndexArray& IndexListIn, FChooserIndexArray& IndexListOut) const { TArray> AssetsToSearch; for (const FChooserIndexArray::FIndexData& IndexData : IndexListIn) { AssetsToSearch.Add(RowValues[IndexData.Index].ResultAsset); } FPoseHistoryReference PoseHistoryReference; if (const FChooserParameterPoseHistoryBase* PoseHistoryParameter = InputValue.GetPtr()) { if (PoseHistoryParameter->GetValue(Context, PoseHistoryReference)) { if (const UE::PoseSearch::IPoseHistory* PoseHistory = PoseHistoryReference.PoseHistory.Get()) { FPoseSearchContinuingProperties ContinuingProperties; FPoseSearchFutureProperties Future; const UE::PoseSearch::FSearchResult SearchResult = UPoseSearchLibrary::MotionMatch( MakeArrayView(&Context, 1), MakeArrayView(&UE::PoseSearch::DefaultRole, 1), MakeArrayView(&PoseHistory, 1), AssetsToSearch, ContinuingProperties, Future, FPoseSearchEvent()); if (const UE::PoseSearch::FSearchIndexAsset* SearchIndexAsset = SearchResult.GetSearchIndexAsset()) { const UPoseSearchDatabase* Database = SearchResult.Database.Get(); if (const FPoseSearchDatabaseAnimationAssetBase* DatabaseAnimationAssetBase = Database->GetDatabaseAnimationAsset(*SearchIndexAsset)) { const UObject* Result = DatabaseAnimationAssetBase->GetAnimationAsset(); int Index; if (AssetsToSearch.Find(Result, Index)) { IndexListOut.Push(IndexListIn[Index]); if (const FChooserParameterFloatBase* StartTime = OutputStartTime.GetPtr()) { StartTime->SetValue(Context, SearchResult.AssetTime); } if (const FChooserParameterFloatBase* Cost = OutputCost.GetPtr()) { Cost->SetValue(Context, SearchResult.PoseCost); } if (const FChooserParameterBoolBase* Mirror = OutputMirror.GetPtr()) { Mirror->SetValue(Context, SearchIndexAsset->IsMirrored()); } } } } } } } if (IndexListOut.IsEmpty()) { // if nothing passed the pose match, or if PoseHistory was not found, then ignore pose matching and just pass through everything IndexListOut = IndexListIn; // set some reasonable defaults for our other outputs in the passthrough case if (const FChooserParameterFloatBase* StartTime = OutputStartTime.GetPtr()) { StartTime->SetValue(Context, 0.0); } if (const FChooserParameterFloatBase* Cost = OutputCost.GetPtr()) { // set an arbitrary "high" cost value so that cost threshold implementations can still wait for the pose search to find a good match Cost->SetValue(Context, 100.0); } if (const FChooserParameterBoolBase* Mirror = OutputMirror.GetPtr()) { Mirror->SetValue(Context, false); } } } #if WITH_EDITOR void FPoseSearchColumn::AddToDetails(FInstancedPropertyBag& PropertyBag, int32 ColumnIndex, int32 RowIndex) { FText DisplayName = NSLOCTEXT("PoseSearchColumn","Pose Search", "Pose Search"); FName PropertyName("RowData", ColumnIndex); FPropertyBagPropertyDesc PropertyDesc(PropertyName, EPropertyBagPropertyType::Struct, FChooserPoseSearchRowData::StaticStruct()); PropertyDesc.MetaData.Add(FPropertyBagPropertyDescMetaData("DisplayName", DisplayName.ToString())); PropertyBag.AddProperties({PropertyDesc}); PropertyBag.SetValueStruct(PropertyName, RowValues[RowIndex]); } void FPoseSearchColumn::SetFromDetails(FInstancedPropertyBag& PropertyBag, int32 ColumnIndex, int32 RowIndex) { FName PropertyName("RowData", ColumnIndex); TValueOrError Result = PropertyBag.GetValueStruct(PropertyName, FChooserPoseSearchRowData::StaticStruct()); if (FStructView* StructView = Result.TryGetValue()) { RowValues[RowIndex] = StructView->Get(); } } #endif