void FSequencerObjectChangeListener::BroadcastPropertyChanged( FKeyPropertyParams KeyPropertyParams, bool bRequireAutoKey ) const
{
	const UStructProperty* StructProperty = Cast<const UStructProperty>(KeyPropertyParams.PropertyPath.Last());
	const UStructProperty* ParentStructProperty = nullptr;
	if (KeyPropertyParams.PropertyPath.Num() > 1)
	{
		ParentStructProperty = Cast<const UStructProperty>(KeyPropertyParams.PropertyPath[KeyPropertyParams.PropertyPath.Num() - 2]);
	}

	FPropertyChangedParams Params;
	Params.bRequireAutoKey = bRequireAutoKey;
	Params.ObjectsThatChanged = KeyPropertyParams.ObjectsToKey;
	Params.StructPropertyNameToKey = NAME_None;

	bool bFoundAndBroadcastedDelegate = false;
	if (ParentStructProperty)
	{
		Params.PropertyPath.Append(KeyPropertyParams.PropertyPath.GetData(), KeyPropertyParams.PropertyPath.Num() - 1);

		// 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())
		{
			if (!bRequireAutoKey)
			{
				Params.StructPropertyNameToKey = KeyPropertyParams.PropertyPath.Last()->GetFName();
			}
			bFoundAndBroadcastedDelegate = true;
			Delegate.Broadcast(Params);
		}
	}

	if (!bFoundAndBroadcastedDelegate)
	{
		Params.PropertyPath = KeyPropertyParams.PropertyPath;
		if (StructProperty)
		{
			ClassToPropertyChangedMap.FindRef(StructProperty->Struct->GetFName()).Broadcast(Params);
		}
		else
		{
			// the property in question is not a struct or an inner of the struct. See if it is directly keyable
			ClassToPropertyChangedMap.FindRef(KeyPropertyParams.PropertyPath.Last()->GetClass()->GetFName()).Broadcast(Params);
		}
	}
}
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);
			}
		}
	}
}