Make it easier to create look-at widgets

This commit is contained in:
2025-04-15 15:48:33 -04:00
parent 3423c01807
commit c0160bdd19
8 changed files with 83 additions and 59 deletions

View File

@@ -37,6 +37,12 @@ enum class ElxSuccessOrError : uint8 {
Error,
};
UENUM(BlueprintType)
enum class ElxFoundOrNotFound : uint8 {
Found,
NotFound,
};
/////////////////////////////////////////////////////////////////
//
// This is a little parser that parses Lua function 'prototypes'.

View File

@@ -8,6 +8,7 @@
#include "TangibleManager.h"
#include "LuaCall.h"
#include "Blueprint/UserWidget.h"
#include "Blueprint/WidgetBlueprintLibrary.h"
#include "Kismet/GameplayStatics.h"
#include "CommonTypes.h"
@@ -26,6 +27,7 @@ ALuprexGameModeBase::ALuprexGameModeBase()
AssetLookup = nullptr;
PlayerId = 0;
EngineSeconds = 0.0;
MustCallLookAtChanged = false;
//PrimaryActorTick.bCanEverTick = true; // Probably wrong
//PrimaryActorTick.bTickEvenWhenPaused = true; // Probably wrong
//PrimaryActorTick.TickGroup = TG_PrePhysics; // Probably wrong
@@ -98,8 +100,8 @@ void ALuprexGameModeBase::ResetToInitialState()
PlayerId = 0;
// Clear the look-at state;
PreviousLookAt.Init();
CurrentLookAt.Init();
MustCallLookAtChanged = false;
// Reset the clocks.
EngineSeconds = 0.0;
@@ -347,12 +349,6 @@ ALuprexGameModeBase *ALuprexGameModeBase::FromContext(const UObject *context) {
return result;
}
bool ALuprexGameModeBase::IsLookAtChanged(const UObject *context) {
ALuprexGameModeBase *mode = FromContext(context);
return mode->CurrentLookAt.HitObjectHandle != mode->PreviousLookAt.HitObjectHandle;
}
void ALuprexGameModeBase::ClearLookAtWidget(const UObject *Context)
{
ALuprexGameModeBase *mode = FromContext(Context);
@@ -370,44 +366,57 @@ void ALuprexGameModeBase::SetLookAtWidget(const UObject *Context, UlxLookAtWidge
{
ClearLookAtWidget(Context);
}
if (!Widget->IsInViewport())
Mode->LookAtWidget = Widget;
}
UlxLookAtWidget *ALuprexGameModeBase::CreateLookAtWidgetByName(UObject *Context, const FString &BlueprintName,
ElxFoundOrNotFound &Result, bool ErrorIfNotFound, bool AddToViewport, bool SetLookAtWidget)
{
ALuprexGameModeBase *Mode = FromContext(Context);
Result = ElxFoundOrNotFound::NotFound;
auto Blueprint = UlxAssetLookup::GetLookAtWidgetByName(Context, BlueprintName, ErrorIfNotFound);
if (Blueprint == nullptr) return nullptr;
APlayerController *pc = Context->GetWorld()->GetFirstPlayerController();
UlxLookAtWidget *Widget = Cast<UlxLookAtWidget>(UWidgetBlueprintLibrary::Create(Context, Blueprint, pc));
check(Widget != nullptr);
if (AddToViewport)
{
Widget->AddToViewport(100);
}
Mode->LookAtWidget = Widget;
if (SetLookAtWidget)
{
Mode->SetLookAtWidget(Context, Widget);
}
Result = ElxFoundOrNotFound::Found;
return Widget;
}
void ALuprexGameModeBase::SetLookAt(const UObject *Context, const FHitResult &HitResult)
{
ALuprexGameModeBase *Mode = FromContext(Context);
if (Mode->CurrentLookAt.HitObjectHandle != HitResult.HitObjectHandle)
{
Mode->MustCallLookAtChanged = true;
}
Mode->CurrentLookAt = HitResult;
}
FVector2D ALuprexGameModeBase::GetLookAtPixel(const UObject *Context)
{
ALuprexGameModeBase *Mode = FromContext(Context);
APlayerController *pc = Context->GetWorld()->GetFirstPlayerController();
if (pc == nullptr) return FVector2D();
FVector2D ScreenPosition;
UGameplayStatics::ProjectWorldToScreen(pc, Mode->CurrentLookAt.Location, ScreenPosition, false);
return ScreenPosition;
}
FVector2D ALuprexGameModeBase::GetPreviousLookAtPixel(const UObject *Context)
{
ALuprexGameModeBase *Mode = FromContext(Context);
APlayerController *pc = Context->GetWorld()->GetFirstPlayerController();
if (pc == nullptr) return FVector2D();
FVector2D ScreenPosition;
UGameplayStatics::ProjectWorldToScreen(pc, Mode->PreviousLookAt.Location, ScreenPosition, false);
if (!UGameplayStatics::ProjectWorldToScreen(pc, Mode->CurrentLookAt.Location, ScreenPosition, false))
{
return FVector2D();
}
return ScreenPosition;
}
void ALuprexGameModeBase::UpdateLookAt() {
// Rotate the variables.
PreviousLookAt = CurrentLookAt;
CurrentLookAt.Init();
// Make sure the world is fully configured before we attempt to cast rays.
UlxTangible *possessed = TangibleManager->GetPossessedTangible();
if (possessed == nullptr) return;
@@ -421,8 +430,8 @@ void ALuprexGameModeBase::UpdateLookAt() {
CalculateLookAt(pc);
if (IsLookAtChanged(this)) {
ClearLookAtWidget(this);
if (MustCallLookAtChanged) {
MustCallLookAtChanged = false;
LookAtChanged();
}
}

View File

@@ -31,7 +31,7 @@ class INTEGRATION_API UlxLookAtWidget : public UUserWidget
public:
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Luprex|Look-At Detection")
void ReadLuaConfiguration(AActor *Place, UlxLuaValues *Config);
void ReadLuaConfiguration(UlxLuaValues *Config);
};
/**
@@ -79,24 +79,33 @@ public:
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
static FVector2D GetLookAtPixel(const UObject *Context);
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
static const FHitResult &GetPreviousLookAt(const UObject *Context) { return FromContext(Context)->PreviousLookAt; }
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
static const AActor *GetPreviousLookAtActor(const UObject *Context) { return FromContext(Context)->PreviousLookAt.GetActor(); }
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
static FVector2D GetPreviousLookAtPixel(const UObject *Context);
UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection")
static bool IsLookAtChanged(const UObject *Context);
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
static void SetLookAtWidget(const UObject *Context, UlxLookAtWidget *Widget);
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
static UlxLookAtWidget *GetLookAtWidget(const UObject *Context) { return FromContext(Context)->LookAtWidget; }
// Create a new Look-At Widget, given the blueprint's name.
//
// The prefix WB_ is added to the blueprint name, and the blueprint is
// searched for in the folder "Widgets".
//
// * If the specified blueprint is not found, execution continues
// on the "Not Found" pin.
//
// * If the flag "Error if Not Found" is true, and the widget blueprint
// is not found, logs an error.
//
// * If the flag "Add to Viewport" is true, the new widget is added
// to the viewport.
//
// * If the flag "Set Look at Widget" is true, the new widget is stored
// as the current look-at widget.
//
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Result", WorldContext = "Context"), Category = "Luprex|Look-At Detection")
static UlxLookAtWidget *CreateLookAtWidgetByName(UObject *Context, const FString &BlueprintName,
ElxFoundOrNotFound &Result, bool ErrorIfNotFound = true, bool AddToViewport = true, bool SetLookAtWidget = true);
UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection")
static void ClearLookAtWidget(const UObject *Context);
@@ -168,14 +177,12 @@ public:
UPROPERTY()
UlxTangibleManager *TangibleManager;
// The actor that the player was looking at, previous frame.
UPROPERTY()
FHitResult PreviousLookAt;
// The actor that the player is looking at, current frame.
UPROPERTY()
FHitResult CurrentLookAt;
bool MustCallLookAtChanged;
UPROPERTY()
UlxLookAtWidget *LookAtWidget;