What is the right way to call a control rig user event from c++?

Hi all :slight_smile:

We are working on a rigging picker for Control Rig, and we want it to be able to execute Control Rig user events. Currently, our code collects a list of user events that start with the prefix PICKER_ and attempts to trigger them. Here’s what we have so far:

void UKhaosControlRigPickerWidget::OnActorSelectionChanged(const TArray<UObject*>& SelectedObjects, bool bIsActorSelectionChanged)
{
    // Find first selected actor with a control rig.
    TSet<UControlRig*> ControlRigs;
    for (UObject* SelectedObject : SelectedObjects)
    {
        AActor* SelectedActor = Cast<AActor>(SelectedObject);
        if (!SelectedActor || !IsValid(SelectedActor))
        {
            continue;
        }

        TArray<USkeletalMeshComponent*> SkeletalMeshComponents;
        SelectedActor->GetComponents(USkeletalMeshComponent::StaticClass(), SkeletalMeshComponents);
        for (USkeletalMeshComponent* SkeletalMeshComponent : SkeletalMeshComponents)
        {
            TArray<UControlRig*> OwnedControlRigs = UControlRig::FindControlRigs(SkeletalMeshComponent, nullptr /* optionally filter by class */);
            for (UControlRig* ControlRig : OwnedControlRigs)
            {
                if (ControlRig->IsModularRig())
                {
                    auto ModularRig = Cast<UModularRig>(ControlRig);
                    for (const auto& Module : ModularRig->Modules)
                    {
                        ControlRigs.Add(Module.GetRig());
                    }
                }
                else
                {
                    ControlRigs.Add(ControlRig);
                }
            }
        }
    }

    // Build action list.
    TArray<UKhaosControlRigPickerAction*> PickerActions;
    for (UControlRig* ControlRig : ControlRigs)
    {
        PickerActions.Append(GetPickerActionsForControlRig(ControlRig));
    }

    K2_OnControlRigSelectionChanged(PickerActions);
}

TArray<UKhaosControlRigPickerAction*> UKhaosControlRigPickerWidget::GetPickerActionsForControlRig(UControlRig* const ControlRig)
{
    if (!ensure(ControlRig))
    {
        return {};
    }

    if (!ensure(!ControlRig->IsModularRig()))
    {
        return {};
    }

    TArray<UKhaosControlRigPickerAction*> Actions;

    // All user events prefixed with PICKER_ will be automatically registered as picker actions.
    const TArray<FName> EventNames = ControlRig->GetSupportedEvents();
    for (const FName& EventName : EventNames)
    {
        if (EventName.ToString().StartsWith("PICKER_"))
        {
            auto Action = NewObject<UKhaosControlRigPickerAction>(this);
            Action->Name = FText::FromString(FString::Printf(TEXT("%s (%s)"), *EventName.ToString(), *ControlRig->GetFName().ToString()));
            Action->Tooltip = FText::FromString(FString::Printf(TEXT("Execute '%s' user event."), *ControlRig->GetFName().ToString()));
            Action->ActionDelegate.BindLambda([ControlRig, EventName]() {
                ControlRig->Execute_Internal(EventName);
            });

            Actions.Add(Action);
        }
    }

    return Actions;
}

We are facing some issues when trying to invoke events on control rig inside modular rigs. Specifically, calling both Execute_Internal and ExecuteEvent seems to be very hit or miss.

For example, on our 4-armed character it only works on 2. It is always the same 2.. Which i find a little odd?

I would like to know this as well.