Download

Having trouble getting OnClicked/OnBeginCursorOver/OnEndCursorOver to work.

Been playing around with this for a few hours and still unsure why it’s not working.

I have a custom PlayerController class that handles all the input. Then, I have a function that casts the currently attached Pawn to my custom Camera class to call functions like MoveForward(). My Camera Pawn doesn’t care about or do anything with mouse clicks. Only movement.

My custom AActor class is what I want listening for OnClicked, OnBeginCursorOver, and OnEndCursorOver.

Here’s all the relevant code (I think).

GamePlayerController.h, inherits from APlayerController



UCLASS()
class GAME_API AGamePlayerController : public APlayerController
{
    GENERATED_BODY()

 public:
     AGamePlayerController();

     virtual void SetupInputComponent() override;

     void LeftMouseDown();
     void RightMouseDown();
     void RightMouseUp();

     void MoveForward(float value);
     void MoveRight(float value);
     void MoveUp(float value);
     void AddYaw(float value);
     void AddPitch(float value);

private:
    bool bRightMouseDown;
    float cursorX, cursorY;
    float centerX, centerY;
    void cacheCursor();
    void resetCursor();
    void setCursorToCenter();

    // Gets the currently attached pawn and casts it to AGameCamera
    class AGameCamera* getCamera();
};


GamePlayerController.cpp



AGamePlayerController::AGamePlayerController()
{
    this->bShowMouseCursor = true;
    this->bEnableClickEvents = true;
    this->bEnableMouseOverEvents = true;
}

void AGamePlayerController::SetupInputComponent()
{
    Super::SetupInputComponent();

    InputComponent->BindAction("LeftMouseDown", IE_Pressed, this, &AGamePlayerController::LeftMouseDown);
    InputComponent->BindAction("RightMouseDown", IE_Pressed, this, &AGamePlayerController::RightMouseDown);
    InputComponent->BindAction("RightMouseDown", IE_Released, this, &AGamePlayerController::RightMouseUp);
    InputComponent->BindAxis("MoveForward", this, &AGamePlayerController::MoveForward);
    InputComponent->BindAxis("MoveRight", this, &AGamePlayerController::MoveRight);
    InputComponent->BindAxis("MoveUp", this, &AGamePlayerController::MoveUp);
    InputComponent->BindAxis("Turn", this, &AGamePlayerController::AddYaw);
    InputComponent->BindAxis("LookUp", this, &AGamePlayerController::AddPitch);
}

// And here's a couple examples of callback functions I'm using. They're all about the same.
void AGamePlayerController::MoveForward(float value)
{
    if (value == 0.f)
        return;

    AGameCamera* camera = getCamera();
    if (camera == nullptr)
        return;

    camera->MoveForward(value);
}

// I'm currently line tracing on left mouse down as well.
// This was before I learned about OnClick/OnBeginHover/etc. My hope is to avoid this code at some point and rely only on the Mesh's handlers.
// Either way, right now this doesn't do anything more than the line trace and then draws debug stuff so I can see it working.
// And this does work, btw.
void AGamePlayerController::LeftMouseDown()
{
    FVector worldPos, worldDir;
    this->DeprojectMousePositionToWorld(worldPos, worldDir);

    UWorld* world = this->GetWorld();

    FVector startPos = worldPos + (worldDir * LINE_TRACE_START_OFFSET);
    FVector endPos = worldPos + (worldDir * LINE_TRACE_DISTANCE);

    FHitResult hitResult(ForceInit);
    bool hit = world->LineTraceSingleByChannel(
        hitResult,
        startPos,
        endPos,
        ECollisionChannel::ECC_Visibility);

    //if (hit)
    //    DrawDebugLine(world, startPos, endPos, FColor::Red, true, LINE_TRACE_DEBUG_TIME, (uint8)'\000', 1.1f);
    //    DrawDebugString(world, worldPos, GetDebugName(hitResult.GetActor()), NULL, FColor::Red, LINE_TRACE_DEBUG_TIME, true, 1.3f);
}


GameActor.h, inherits from AActor



UCLASS()
class GAME_API AGameActor : public AActor
{
    GENERATED_BODY()

public:    
    AGameActor();
    virtual void Tick(float DeltaTime) override;

    UPROPERTY(EditAnywhere)
    UStaticMeshComponent* Mesh;

    UFUNCTION()
    void OnClicked(UPrimitiveComponent* pComponent, FKey key);

    UFUNCTION()
    void OnMouseOverBegin(UPrimitiveComponent* pComponent);

    UFUNCTION()
    void OnMouseOverEnd(UPrimitiveComponent* pComponent);

protected:
    virtual void BeginPlay() override;
};


GameActor.cpp



AGameActor::AGameActor()
{
    PrimaryActorTick.bCanEverTick = true;

    Mesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
    Mesh->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
    Mesh->OnClicked.AddDynamic(this, &AGameActor::OnClicked);
    Mesh->OnBeginCursorOver.AddDynamic(this, &AGameActor::OnMouseOverBegin);
    Mesh->OnEndCursorOver.AddDynamic(this, &AGameActor::OnMouseOverEnd);
}

void AGameActor::OnClicked(UPrimitiveComponent* pComponent, FKey key)
{
    if (GEngine)
        GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, TEXT("CLICKED"));
}

void AGameActor::OnMouseOverBegin(UPrimitiveComponent* pComponent)
{
    if (GEngine)
        GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, TEXT("MOUSE OVER BEGIN"));
}

void AGameActor::OnMouseOverEnd(UPrimitiveComponent* pComponent)
{
    if (GEngine)
        GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Emerald, TEXT("MOUSE OVER END"));
}