diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 18fa7dce..c141daf6 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -1,4 +1,5 @@ + [/Script/EngineSettings.GameMapsSettings] GameDefaultMap=/Game/LpxLevel.LpxLevel GlobalDefaultGameMode=/Game/Luprex/lxGameMode.lxGameMode_C @@ -44,23 +45,23 @@ UIScaleCurve=(EditorCurveData=(Keys=((Time=480.000000,Value=0.444000),(Time=720. -Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Block),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision") +Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ") -+Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") +Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ") -+Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ") +Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.") -+Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ") ++Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ") +Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ") -+Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic"),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.") -+Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.") ++Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.") ++Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.") +Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors") +Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors") +Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.") +Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.") -+Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.") ++Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.") +Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.") +Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.") -+Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") -+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name="Clickable") ++Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name="LookAtDetection") -ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") -ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") -ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") @@ -79,4 +80,5 @@ UIScaleCurve=(EditorCurveData=(Keys=((Time=480.000000,Value=0.444000),(Time=720. +CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic") +CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") +CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn") ++CollisionChannelRedirects=(OldName="Clickable",NewName="LookAtDetection") diff --git a/Content/Luprex/lxGameMode.uasset b/Content/Luprex/lxGameMode.uasset index ed5cd998..a77cac3d 100644 --- a/Content/Luprex/lxGameMode.uasset +++ b/Content/Luprex/lxGameMode.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81eb6a9dc606e6b8475d823ca4c125bf509cb2ec08b0f71eff754d6fe1418f5a -size 156416 +oid sha256:79f17c44c9326d2ec6bcf58132d59b0600708dce86a9965d6fe1050b0e9690c6 +size 129807 diff --git a/Content/Luprex/lxUtilityMacroLibrary.uasset b/Content/Luprex/lxUtilityMacroLibrary.uasset index 39a7ba72..52205aea 100644 --- a/Content/Luprex/lxUtilityMacroLibrary.uasset +++ b/Content/Luprex/lxUtilityMacroLibrary.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e6e047d1baad2253fba8cb55b3e08ed58eb9d211fbf3a3211435a70cc6d9c213 -size 38482 +oid sha256:9cb531b158ececdb42ffb71eb803fd0ca428354d09beeb32535fea96336d8ac1 +size 32320 diff --git a/Content/Widgets/WB_Crosshair1.uasset b/Content/Widgets/WB_Crosshair1.uasset index 19d327f9..5663835e 100644 --- a/Content/Widgets/WB_Crosshair1.uasset +++ b/Content/Widgets/WB_Crosshair1.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43a108e773b4f87c83e6c318a97357e6af12ab269c5606ba6abc953e24f1ef67 -size 80101 +oid sha256:ab5a1cf39a7ce3ecdb6b2ab102d6109ac2eb5ab7f4422875d277a92475df5b90 +size 54933 diff --git a/Content/Widgets/WB_Hotkeys.uasset b/Content/Widgets/WB_Hotkeys.uasset index 6b86f9ca..aaecf1eb 100644 --- a/Content/Widgets/WB_Hotkeys.uasset +++ b/Content/Widgets/WB_Hotkeys.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:174590f11c780fd06aa29d3475a886b13c4ac843dbdabaecc480f912ae64ba96 -size 41205 +oid sha256:b4161ddd9f32beaffc9c89a49104a114b496e5a08430671aa11972f6e3c089fc +size 53013 diff --git a/Source/Integration/LuaCall.h b/Source/Integration/LuaCall.h index feb5ab35..e6d01194 100644 --- a/Source/Integration/LuaCall.h +++ b/Source/Integration/LuaCall.h @@ -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'. diff --git a/Source/Integration/LuprexGameModeBase.cpp b/Source/Integration/LuprexGameModeBase.cpp index 5f0d6bdf..8fd12497 100644 --- a/Source/Integration/LuprexGameModeBase.cpp +++ b/Source/Integration/LuprexGameModeBase.cpp @@ -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(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(); } } diff --git a/Source/Integration/LuprexGameModeBase.h b/Source/Integration/LuprexGameModeBase.h index 5459f806..50809e84 100644 --- a/Source/Integration/LuprexGameModeBase.h +++ b/Source/Integration/LuprexGameModeBase.h @@ -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;