// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/GameModeBase.h" #include "lpx-enginewrapper.hpp" #include "StringDecoder.h" #include "TangibleManager.h" #include "AssetLookup.h" #include "LuprexSockets.h" #include "TriggeredTask.h" #include "BlueprintErrors.h" #include "Blueprint/UserWidget.h" #include "Widgets/CommonActivatableWidgetContainer.h" #include "CommonActivatableWidget.h" #include "LuprexGameModeBase.generated.h" class UlxLuaValues; UCLASS(BlueprintType) class INTEGRATION_API UlxLuaWidget : public UCommonActivatableWidget { GENERATED_BODY() public: UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Luprex|Miscellaneous") void ReadLuaConfiguration(UlxLuaValues *Config); }; /** * */ UCLASS(BlueprintType) class INTEGRATION_API ALuprexGameModeBase : public AGameModeBase, public FRunnable { GENERATED_BODY() public: ALuprexGameModeBase(); ~ALuprexGameModeBase(); virtual void BeginPlay() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason); // Delete all the state created in BeginPlay. That // includes: the Luprex engine, the thread, and the socket state. void ResetToInitialState(); // Initialize the Luprex DLL, and do other global initialization. void InitializeGlobalState(); // Send prints into Unreal, for display on the virtual console. UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Miscellaneous") void ConsoleAddOutput(const FString& text); UFUNCTION(BlueprintCallable, Category = "Luprex|Miscellaneous") int64 GetPlayerId(); UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection") static void SetLookAt(const UObject *Context, const FHitResult &HitResult); UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection") static const FHitResult &GetLookAt(const UObject *Context) { return FromContext(Context)->CurrentLookAt; } UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection") static const AActor *GetLookAtActor(const UObject *Context) { return FromContext(Context)->CurrentLookAt.GetActor(); } UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"),Category = "Luprex|Look-At Detection") static FVector2D GetLookAtPixel(const UObject *Context); UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection") static void SetLookAtChanged(const UObject* Context); // // Look-At Related Events // UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Look-At Detection") void CalculateLookAt(APlayerController *PlayerController); UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Look-At Detection") void LookAtChanged(); // Assemble a lua call. Note that this is the lowest-level interface. // These functions are wrapped by the functions in UlxLuaCallLibrary, // and those in turn are wrapped by the K2Node "LuaInvoke" and "LuaProbe". // // At this level, the process of calling Lua is: // // * Use LuaCallBegin // * Get the lua call buffer: // - add a class name // - add a function name // - add function parameters // * Use LuaCallEnd. // * Process any return values in the UlxLuaValues array. // FlxStreamBuffer &LuaCallBegin() { LuaCallBuffer.clear(); return LuaCallBuffer; } FlxStreamBuffer &LuaCallGetBuffer() { return LuaCallBuffer; } UlxLuaValues *LuaCallEnd(AccessKind kind); UlxLuaValues *LuaCallEnd(AccessKind kind, int64 place_id); UlxLuaValues *LuaCallEnd(AccessKind kind, AActor *place); void LuaCallClear() { LuaCallBuffer.clear(); } // Validate some lua code. Returns an error message. // If the lua is well-formed, the error message is the // empty string. The syntax of the code is checked using // an otherwise empty lua interpreter, so this is purely // a syntax check. // FString ValidateLuaExpr(const FString &Code); // Invoke some lua code. // void InvokeLuaExpr(const FString &Code); // Get the Asset Lookup table. const UlxAssetLookup *GetAssetLookup() const { return AssetLookup; } // Transfer console output from the Luprex engine to unreal. void UpdateConsoleOutput(); // Update the tangibles according to what Luprex tells us. // This also includes calling 'AnimationQueueChanged' on all // tangibles that have been changed. void UpdateTangibles(); // Look for a tangible whose ID is equal to the current actor ID. // Tell the player controller to possess that tangible. void UpdatePossessedTangible(); // Call 'CalculateLookAt', but only if everything is valid. // It is up to the blueprint code to actually determine what we're looking at. void UpdateLookAt(); // Pre-tick and post-tick functions. void OnWorldPreActorTick(UWorld* InWorld, ELevelTick InLevelTick, float InDeltaSeconds); void OnWorldPostActorTick(UWorld* InWorld, ELevelTick InLevelTick, float InDeltaSeconds); // The run function is called by a background thread // to update luprex sockets and update luprex itself. virtual uint32 Run() override; // Get the current Luprex Game Mode Base, given a Context object. static ALuprexGameModeBase *FromContext(const UObject *Context); // Asset Lookup by Name. UPROPERTY() UlxAssetLookup *AssetLookup; UPROPERTY() UlxTangibleManager *TangibleManager; // The actor that the player is looking at, current frame. UPROPERTY() FHitResult CurrentLookAt; bool MustCallLookAtChanged; // The sensitivity level at which a log message triggers a debugger breakpoint. UPROPERTY(EditAnywhere, Category="Debugging Tools") ElxLogVerbosity BreakToDebuggerLogVerbosity; // The Luprex EngineWrapper, with a Mutex to protect it. // To access it, construct a FlxLockedWrapper. FlxLockableWrapper LockableWrapper; // The Lua Call Assembly Buffer. FlxStreamBuffer LuaCallBuffer; // This utility runs the luprex update and socket update in a thread. FTriggeredTask LuprexUpdateTask; // Luprex socket system. Aside from construction, only touched by Luprex thread. TUniquePtr Sockets; // True if 'BeginPlay' has been successfully completed. bool Playing; // This is always true unless you use the debugger to set it to false. bool TickEnabled; // Current Player ID int64 PlayerId; // Amount of elapsed time since BeginPlay. float EngineSeconds; // When do we next rotate the cube. float NextRotateCube; // These allow us to pre-tick and post-tick. FDelegateHandle OnWorldPreActorTickHandle; FDelegateHandle OnWorldPostActorTickHandle; // The device that implements BreakToDebuggerLogVerbosity, above. TUniquePtr BreakToDebuggerLogVerbosityDevice; };