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;
}
예제 #3
0
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);
			}
		}
	}
}