bool FSequencerObjectChangeListener::IsTypeKeyable(const UClass& ObjectClass, const IPropertyHandle& PropertyHandle) const { const UProperty* Property = PropertyHandle.GetProperty(); const UStructProperty* StructProperty = Cast<const UStructProperty>(Property); const UStructProperty* ParentStructProperty = nullptr; const TSharedPtr<IPropertyHandle> ParentHandle = PropertyHandle.GetParentHandle(); if(ParentHandle->IsValidHandle()) { ParentStructProperty = Cast<const UStructProperty>(ParentHandle->GetProperty()); } FString PropertyVarName; bool bFound = false; if( StructProperty ) { bFound = FindPropertySetter( ObjectClass, StructProperty->Struct->GetFName(), StructProperty->GetName() ); } if( !bFound && ParentStructProperty ) { // If the property parent is a struct, see if this property parent can be keyed. (e.g R,G,B,A for a color) bFound = FindPropertySetter( ObjectClass, ParentStructProperty->Struct->GetFName(), ParentStructProperty->GetName() ); } if( !bFound ) { // the property in question is not a struct or an inner of the struct. See if it is directly keyable bFound = FindPropertySetter( ObjectClass, Property->GetClass()->GetFName(), Property->GetName() ); } return bFound; }
bool FDetailWidgetExtensionHandler::IsPropertyExtendable(const UClass* InObjectClass, const IPropertyHandle& InPropertyHandle) const { // TODO UMG make this work for multiple widgets. if ( InPropertyHandle.GetNumOuterObjects() == 1 ) { TArray<UObject*> Objects; InPropertyHandle.GetOuterObjects(Objects); // We don't allow bindings on the CDO. if ( Objects[0]->HasAnyFlags(RF_ClassDefaultObject) ) { return false; } UProperty* Property = InPropertyHandle.GetProperty(); FString DelegateName = Property->GetName() + "Delegate"; if ( UClass* ContainerClass = Cast<UClass>(Property->GetOuter()) ) { UDelegateProperty* DelegateProperty = FindField<UDelegateProperty>(ContainerClass, FName(*DelegateName)); if ( DelegateProperty ) { return true; } } } return false; }
void PropertyHandleToPropertyPath(const UClass* OwnerClass, const IPropertyHandle& InPropertyHandle, TArray<UProperty*>& PropertyPath) { PropertyPath.Add(InPropertyHandle.GetProperty()); TSharedPtr<IPropertyHandle> CurrentHandle = InPropertyHandle.GetParentHandle(); while (CurrentHandle.IsValid() && CurrentHandle->GetProperty() != nullptr) { PropertyPath.Insert(CurrentHandle->GetProperty(), 0); CurrentHandle = CurrentHandle->GetParentHandle(); } }
void FUMGDetailKeyframeHandler::OnKeyPropertyClicked(const IPropertyHandle& KeyedPropertyHandle) { TArray<UObject*> Objects; KeyedPropertyHandle.GetOuterObjects( Objects ); BlueprintEditor.Pin()->GetSequencer()->KeyProperty( Objects, KeyedPropertyHandle ); }
void FSequencerObjectChangeListener::OnPropertyChanged( const TArray<UObject*>& ChangedObjects, const IPropertyHandle& PropertyHandle, bool bRequireAutoKey ) const { bool bIsKeyable = false; for( UObject* Object : ChangedObjects ) { if( Object ) { bIsKeyable |= IsTypeKeyable( *Object->GetClass(), PropertyHandle ); } } if( bIsKeyable ) { const UProperty* Property = PropertyHandle.GetProperty(); const UStructProperty* StructProperty = Cast<const UStructProperty>(Property); const UStructProperty* ParentStructProperty = nullptr; TSharedPtr<IPropertyHandle> ParentHandle; ParentHandle = PropertyHandle.GetParentHandle(); if (ParentHandle->IsValidHandle()) { ParentStructProperty = Cast<const UStructProperty>(ParentHandle->GetProperty()); } FString PropertyVarName; // If not in auto-key allow partial keying of specific inner struct property values; FName InnerStructPropName = !bRequireAutoKey && ParentStructProperty ? Property->GetFName() : NAME_None; FKeyPropertyParams Params; Params.bRequireAutoKey = bRequireAutoKey; Params.ObjectsThatChanged = ChangedObjects; bool bFoundAndBroadcastedDelegate = false; if (ParentStructProperty) { Params.PropertyHandle = ParentHandle.Get(); Params.PropertyPath = ParentHandle->GeneratePathToProperty(); // If the property parent is a struct, see if this property parent can be keyed. (e.g R,G,B,A for a color) FOnAnimatablePropertyChanged Delegate = ClassToPropertyChangedMap.FindRef(ParentStructProperty->Struct->GetFName()); if (Delegate.IsBound()) { Params.InnerStructPropertyName = InnerStructPropName; bFoundAndBroadcastedDelegate = true; Delegate.Broadcast(Params); } } if (!bFoundAndBroadcastedDelegate) { if (StructProperty) { Params.PropertyHandle = &PropertyHandle; Params.PropertyPath = PropertyHandle.GeneratePathToProperty(); ClassToPropertyChangedMap.FindRef(StructProperty->Struct->GetFName()).Broadcast(Params); } else { Params.PropertyHandle = &PropertyHandle; Params.PropertyPath = PropertyHandle.GeneratePathToProperty(); // the property in question is not a struct or an inner of the struct. See if it is directly keyable ClassToPropertyChangedMap.FindRef(Property->GetClass()->GetFName()).Broadcast(Params); } } } }