How to override the tick function in a UserWidget

I have a widget that I want to be able to drag with the mouse. To do that I need to update the widget position every frame based on changes in the mouse position. To do that i need to override the tick function. I have already checked this UMG, overriding of UsingWidget.Tick and It has not helped. Here is my header

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "DragWindow.generated.h"

/**
 * 
 */
UCLASS()
class HELLOWORLDGODLL_API UDragWindow : public UUserWidget
{
	GENERATED_BODY()
protected: 
	UPROPERTY(BluePrintReadWrite, meta = (BindWidget))
		class UButton* DragBar;

	UPROPERTY(BluePrintReadWrite, meta = (BindWidget))
		class UTextBlock* Title;

public:

	// Called every frame
	virtual void OnMouseMove(FGeometry MyGeometry, FPointerEvent& MouseEvent);

	UFUNCTION(BlueprintCallable)
	void onButtonClicked();

	UFUNCTION(BlueprintCallable)
	void onButtonReleased();

	virtual void NativeConstruct() override;
	void SetTitle(FString title);

	virtual void Tick_Implementation(const FGeometry& geo, float deltaTime);
};

and my CPP

// Fill out your copyright notice in the Description page of Project Settings.

#include "Layout/Geometry.h"
#include "Components/Image.h"
#include "DragWindow.h"
#include "Components/Button.h"
#include <Components/TextBlock.h>	
#include <Runtime/Engine/Classes/Kismet/GameplayStatics.h>

bool isDragging;
float lastX;
float lastY;

void UDragWindow::OnMouseMove(FGeometry MyGeometry, FPointerEvent& MouseEvent) {
	float mouseX;
	float mouseY;
	UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetMousePosition(mouseX, mouseY);
	int diffx = mouseX - lastX;
	int diffy = mouseY - lastY;
	const FGeometry Geometry = this->GetCachedGeometry();
	float x = Geometry.AbsolutePosition.X + diffx;
	float y = Geometry.AbsolutePosition.Y + diffy;
	FVector2D NewPos = FVector2D(x, y);
	this->SetPositionInViewport(NewPos);
}

void UDragWindow::onButtonClicked() {
	UE_LOG(LogTemp, Warning, TEXT("clicked"));
	float mouseX;
	float mouseY;
	UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetMousePosition(mouseX, mouseY);
	lastX = mouseX;
	lastY = mouseY;
	isDragging = true;
}

void UDragWindow::onButtonReleased() {
	UE_LOG(LogTemp, Warning, TEXT("released"));
	isDragging = false;
}

void UDragWindow::NativeConstruct()
{
	UE_LOG(LogTemp, Warning, TEXT("built"));
	DragBar->OnPressed.AddDynamic(this, &UDragWindow::onButtonClicked);
	DragBar->OnReleased.AddDynamic(this, &UDragWindow::onButtonReleased);
}

void UDragWindow::SetTitle(FString title) {
	Title->SetText(FText::FromString(title));
}
void UDragWindow::Tick_Implementation(const FGeometry& geo, float deltaTime) {
	Super::Tick(geo, deltaTime);
	UE_LOG(LogTemp, Warning, TEXT("yahoo"));
	if (isDragging){
		float mouseX;
		float mouseY;
		UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetMousePosition(mouseX, mouseY);
		int diffx = mouseX - lastX;
		int diffy = mouseY - lastY;
		const FGeometry Geometry = this->GetCachedGeometry();
		float x = Geometry.AbsolutePosition.X + diffx;
		float y = Geometry.AbsolutePosition.Y + diffy;
		FVector2D NewPos = FVector2D(x, y);
		this->SetPositionInViewport(NewPos);
	}
}

I know my other code is likely wrong, but how do I get the Tick function to be called automatically?

.h:
void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;

.cpp:

void UMyWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
    Super::NativeTick(MyGeometry, InDeltaTime);
    // Your Stuff Goes Here
}

P.S. A bunch of stuff in UserWidget, when used in cpp, has the prefix Native; like NativeConstruct() etc. Respective non-native things will only work in blueprints.

1 Like

I am using a UMG with this CPP as a parent. Here are the updated files. This is still not calling Tick().

// Fill out your copyright notice in the Description page of Project Settings.

#include "Layout/Geometry.h"
#include "Components/Image.h"
#include "DragWindow.h"
#include "Components/Button.h"
#include <Components/TextBlock.h>	
#include <Runtime/Engine/Classes/Kismet/GameplayStatics.h>
#include "Runtime/Engine/Classes/GameFramework/PlayerController.h"

bool isDragging;
float lastX = 0;
float lastY = 0;

void UDragWindow::OnMouseMove(FGeometry MyGeometry, FPointerEvent& MouseEvent) {
	float mouseX = 0;
	float mouseY = 0;
	//UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetMousePosition(mouseX, mouseY);
	int diffx = mouseX - lastX;
	int diffy = mouseY - lastY;
	const FGeometry Geometry = this->GetCachedGeometry();
	float x = Geometry.AbsolutePosition.X + diffx;
	float y = Geometry.AbsolutePosition.Y + diffy;
	FVector2D NewPos = FVector2D(x, y);
	this->SetPositionInViewport(NewPos);
}

void UDragWindow::onButtonClicked() {
	UE_LOG(LogTemp, Warning, TEXT("clicked"));
	float mouseX = 0;
	float mouseY = 0;
	//UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetMousePosition(mouseX, mouseY);
	UE_LOG(LogTemp, Warning, TEXT("%start f:%f"), mouseX, mouseY)
	isDragging = true;
	FVector2D NewPos = FVector2D(lastX, lastY);
	this->SetPositionInViewport(NewPos);
	lastX = (float)mouseX;
	lastY = (float)mouseY;
}

void UDragWindow::onButtonReleased() {
	UE_LOG(LogTemp, Warning, TEXT("released"))
	float mouseX  = 0;
	float mouseY = 0;
	//UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetMousePosition(mouseX, mouseY);
	UE_LOG(LogTemp, Warning, TEXT("end %f:%f"), mouseX, mouseY);
	int diffx = lastX - mouseX;
	int diffy = lastY - mouseY;
	UE_LOG(LogTemp, Warning, TEXT("diff %f:%f"), diffx, diffy);
	const FGeometry Geometry = this->GetCachedGeometry();
	float x = Geometry.AbsolutePosition.X + diffx;
	float y = Geometry.AbsolutePosition.Y + diffy;
	UE_LOG(LogTemp, Warning, TEXT("post % f: % f"), x, y);
	FVector2D NewPos = FVector2D(x, y);
	this->SetPositionInViewport(NewPos);
	isDragging = false;
}

void UDragWindow::NativeConstruct()
{
	UE_LOG(LogTemp, Warning, TEXT("built"));
	DragBar->OnPressed.AddDynamic(this, &UDragWindow::onButtonClicked);
	DragBar->OnReleased.AddDynamic(this, &UDragWindow::onButtonReleased);
}

void UDragWindow::SetTitle(FString title) {
	Title->SetText(FText::FromString(title));
}
void UDragWindow::NativeTick(const FGeometry& MyGeometry, float deltaTime) {
	Super::NativeTick(MyGeometry, deltaTime);
	UE_LOG(LogTemp, Warning, TEXT("yahoo"));
	if (isDragging){
		float mouseX;
		float mouseY;
		UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetMousePosition(mouseX, mouseY);
		int diffx = mouseX - lastX;
		int diffy = mouseY - lastY;
		const FGeometry Geometry = this->GetCachedGeometry();
		float x = Geometry.AbsolutePosition.X + diffx;
		float y = Geometry.AbsolutePosition.Y + diffy;
		FVector2D NewPos = FVector2D(x, y);
		this->SetPositionInViewport(NewPos);
	}
}

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "DragWindow.generated.h"

/**
 * 
 */
UCLASS()
class HELLOWORLDGODLL_API UDragWindow : public UUserWidget
{
	GENERATED_BODY()
protected: 
	UPROPERTY(BluePrintReadWrite, meta = (BindWidget))
		class UButton* DragBar;

	UPROPERTY(BluePrintReadWrite, meta = (BindWidget))
		class UTextBlock* Title;

public:

	// Called every frame
	virtual void OnMouseMove(FGeometry MyGeometry, FPointerEvent& MouseEvent);

	UFUNCTION(BlueprintCallable)
	void onButtonClicked();

	UFUNCTION(BlueprintCallable)
	void onButtonReleased();

	virtual void NativeConstruct() override;
	void SetTitle(FString title);

	void NativeTick(const FGeometry& MyGeometry, float deltaTime) override;
};