Fleshed out the module's base helper definitions

This commit is contained in:
Edward R. Gonzalez 2024-04-13 05:32:52 -04:00
parent 1ee21cbedc
commit 2757307287
20 changed files with 330 additions and 39 deletions

View File

@ -1,6 +1,6 @@
#include "GasaCharacter.h" #include "GasaCharacter.h"
#include "GasaLevelScriptActor.h" #include "Game/GasaLevelScriptActor.h"
#include "Camera/CameraComponent.h" #include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h" #include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h" #include "GameFramework/CharacterMovementComponent.h"

View File

@ -21,9 +21,15 @@ public:
namespace Gasa namespace Gasa
{ {
FORCEINLINE inline
UGasaGameInstance* GetGameInstance(UObject* Context) { UGasaGameInstance* GetGameInstance(UObject* Context)
// TODO(Ed): Do this with proper checks {
return Context->GetWorld()->GetGameInstance<UGasaGameInstance>(); UWorld* World = GEngine->GetWorldFromContextObject(Context, EGetWorldErrorMode::LogAndReturnNull);
if (World == nullptr)
{
Log("World is null... are you running in a proper context?", ELogV::Error);
return nullptr;
}
return Cast<UGasaGameInstance>(World->GetGameInstance());
} }
} }

View File

@ -0,0 +1,28 @@
#pragma once
#include "GameFramework/GameMode.h"
#include "GasaCommon.h"
#include "GasaGameMode.generated.h"
UCLASS(Blueprintable)
class GASA_API AGasaGameMode : public AGameMode
{
GENERATED_BODY()
public:
};
namespace Gasa
{
inline
AGasaGameMode* GetGameMode(UObject* Context)
{
UWorld* World = GEngine->GetWorldFromContextObject(Context, EGetWorldErrorMode::LogAndReturnNull);
if (World == nullptr)
{
Log("World is null... are you running in a proper context?", ELogV::Error);
return nullptr;
}
return Cast<AGasaGameMode>(World->GetAuthGameMode());
}
}

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "GameFramework/GameState.h" #include "GameFramework/GameState.h"
#include "GasaCommon.h" #include "GasaCommon.h"
#include "GasaGameState.generated.h" #include "GasaGameState.generated.h"
@ -31,8 +32,15 @@ public:
namespace Gasa namespace Gasa
{ {
FORCEINLINE inline
AGasaGameState* GetGameState(UObject* Context) { AGasaGameState* GetGameState(UObject* Context)
return Context->GetWorld()->GetGameState<AGasaGameState>(); {
UWorld* World = GEngine->GetWorldFromContextObject(Context, EGetWorldErrorMode::LogAndReturnNull);
if (World == nullptr)
{
Log("World is null... are you running in a proper context?", ELogV::Error);
return nullptr;
}
return Cast<AGasaGameState>(World->GetGameState());
} }
} }

View File

@ -1,22 +1,21 @@
#include "GasaLevelScriptActor.h" #include "GasaLevelScriptActor.h"
#include "GasaDevOptions.h" #include "GasaDevOptions.h"
#include "GasaGameplayTags.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "GasaLibrary.h"
void AGasaLevelScriptActor::BeginPlay() void AGasaLevelScriptActor::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
using namespace Gasa;
TArray<AActor*> TaggedActors; TArray<AActor*> TaggedActors;
UGameplayStatics::GetAllActorsWithTag(GetWorld(), Gasa::GetDevOptions()->Tag_GlobalPPV,TaggedActors); UGameplayStatics::GetAllActorsWithTag(GetWorld(), GetDevOptions()->Tag_GlobalPPV, TaggedActors);
for (AActor* Actor : TaggedActors) for (AActor* Actor : TaggedActors)
{ {
GlobalPPV = Cast<APostProcessVolume>(Actor); GlobalPPV = Cast<APostProcessVolume>(Actor);
APostProcessVolume* PPV = Gasa::GetLevelActor(this)->GlobalPPV; APostProcessVolume* PPV = GetLevelActor(this)->GlobalPPV;
UMaterialInstance* Blendable = Cast<UMaterialInstance>(PPV->Settings.WeightedBlendables.Array[0].Object); UMaterialInstance* Blendable = Cast<UMaterialInstance>(PPV->Settings.WeightedBlendables.Array[0].Object);
UMaterialInstanceDynamic* MID = UMaterialInstanceDynamic::Create(Blendable, this); UMaterialInstanceDynamic* MID = UMaterialInstanceDynamic::Create(Blendable, this);
PPV->Settings.WeightedBlendables.Array[0].Object = MID; PPV->Settings.WeightedBlendables.Array[0].Object = MID;

View File

@ -2,6 +2,8 @@
#include "Engine/LevelScriptActor.h" #include "Engine/LevelScriptActor.h"
#include "GasaCommon.h"
#include "GasaLevelScriptActor.generated.h" #include "GasaLevelScriptActor.generated.h"
UCLASS(Blueprintable) UCLASS(Blueprintable)
@ -21,7 +23,12 @@ namespace Gasa
{ {
inline inline
AGasaLevelScriptActor* GetLevelActor(UObject* Context, ULevel* OwnerLevel = nullptr) { AGasaLevelScriptActor* GetLevelActor(UObject* Context, ULevel* OwnerLevel = nullptr) {
UWorld* World = GEngine->GetWorldFromContextObjectChecked(Context); UWorld* World = GEngine->GetWorldFromContextObject(Context, EGetWorldErrorMode::LogAndReturnNull);
if (World == nullptr)
{
Log("World is null... are you running in a proper context?", ELogV::Error);
return nullptr;
}
return Cast<AGasaLevelScriptActor>(World->GetLevelScriptActor(OwnerLevel)); return Cast<AGasaLevelScriptActor>(World->GetLevelScriptActor(OwnerLevel));
} }
} }

View File

@ -72,3 +72,18 @@ public:
void Tick(float DeltaSeconds) override; void Tick(float DeltaSeconds) override;
#pragma endregion Actor #pragma endregion Actor
}; };
namespace Gasa
{
inline
AGasaPlayerController* GetPrimaryPlayerController(UObject* Context)
{
UWorld* World = GEngine->GetWorldFromContextObject(Context, EGetWorldErrorMode::LogAndReturnNull);
if (World == nullptr)
{
Log("World is null... are you running in a proper context?", ELogV::Error);
return nullptr;
}
return Cast<AGasaPlayerController>(World->GetFirstPlayerController());
}
}

View File

@ -0,0 +1,3 @@
#include "GasaCommon.h"
DEFINE_LOG_CATEGORY(LogGasa);

View File

@ -26,7 +26,99 @@ class UCogWindowManager;
#pragma region Forwards #pragma region Forwards
class ACameraMount; class ACameraMount;
class AGasaCharacter; class AGasaCharacter;
class AGasaGameInstance;
class AGasaGameState;
class AGasaLevelScriptActor; class AGasaLevelScriptActor;
class AGasaPlayerController;
class UGasaDevOptions; class UGasaDevOptions;
#pragma endregion Forwards #pragma endregion Forwards
// Straight from the Engine
UENUM(BlueprintType)
enum class EGasaVerbosity : uint8
{
/** Not used */
NoLogging = 0,
/** Always prints a fatal error to console (and log file) and crashes (even if logging is disabled) */
// Fatal,
// Just use GASA_Fatal...
/**
* Prints an error to console (and log file).
* Commandlets and the editor collect and report errors. Error messages result in commandlet failure.
*/
Error = ELogVerbosity::Error,
/**
* Prints a warning to console (and log file).
* Commandlets and the editor collect and report warnings. Warnings can be treated as an error.
*/
Warning,
/** Prints a message to console (and log file) */
Display,
/** Prints a message to a log file (does not print to console) */
Log,
/**
* Prints a verbose message to a log file (if Verbose logging is enabled for the given category,
* usually used for detailed logging)
*/
Verbose,
/**
* Prints a verbose message to a log file (if VeryVerbose logging is enabled,
* usually used for detailed logging that would otherwise spam output)
*/
VeryVerbose,
};
DECLARE_LOG_CATEGORY_EXTERN(LogGasa, Log, All);
namespace Gasa
{
using ELogV = EGasaVerbosity;
//◞ ‸ ◟//
// Works for Unreal 5.4, Win64 MSVC (untested in other scenarios, for now)
inline
void Log( FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log
, FLogCategoryBase& Category = LogGasa
, bool DumpStack = false
, int32 Line = __builtin_LINE()
, const ANSICHAR* File = __builtin_FILE()
, const ANSICHAR* Func = __builtin_FUNCTION() )
{
#if !UE_BUILD_SHIPPING || !NO_LOGGING
ELogVerbosity::Type EngineVerbosity = (ELogVerbosity::Type) Verbosity;
static ::UE::Logging::Private::FStaticBasicLogDynamicData LOG_Dynamic;
static ::UE::Logging::Private::FStaticBasicLogRecord
LOG_Static(TEXT("%s -- %hs %hs(%d)"), File, Line, EngineVerbosity, LOG_Dynamic);
if ((EngineVerbosity & ::ELogVerbosity::VerbosityMask) <= ::ELogVerbosity::COMPILED_IN_MINIMUM_VERBOSITY)
{
if ((EngineVerbosity & ::ELogVerbosity::VerbosityMask) <= Category.GetVerbosity())
{
if ( ! Category.IsSuppressed(EngineVerbosity))
{
if (DumpStack)
FDebug::DumpStackTraceToLog(EngineVerbosity);
::UE::Logging::Private::BasicLog(Category, &LOG_Static, *Message, File, Func, Line);
}
}
}
#endif
}
}
#define GASA_Fatal(Message) UE_LOG( Gasa, Fatal, TEXT("%s -- %hs %hs(%d)"), *Message, __builtin_FILE(), __func__, __builtin_LINE() );
#define GASA_Error(Message) UE_LOG( Gasa, Error, TEXT("%s -- %hs %hs(%d)"), *Message, __builtin_File(), __func__, __builtin_LINE() );
#define GASA_Warning(Message) UE_LOG( Gasa, Warning, TEXT("%s -- %hs %hs(%d)"), *Message, __builtin_File(), __func__, __builtin_LINE() );
#define GASA_Display(Message) UE_LOG( Gasa, Display, TEXT("%s -- %hs %hs(%d)"), *Message, __builtin_File(), __func__, __builtin_LINE() );
#define GASA_Log(Message) UE_LOG( Gasa, Log, TEXT("%s -- %hs %hs(%d)"), *Message, __builtin_File(), __func__, __builtin_LINE() );
#define GASA_Verbose(Message) UE_LOG( Gasa, Verbose, TEXT("%s -- %hs %hs(%d)"), *Message, __builtin_File(), __func__, __builtin_LINE() );
#define GASA_VeryVerbose(Message) UE_LOG( Gasa, VeryVerbose, TEXT("%s -- %hs %hs(%d)"), *Message, __builtin_File(), __func__, __builtin_LINE() );

View File

@ -1,19 +0,0 @@
#pragma once
#include "GameFramework/GameMode.h"
#include "GasaGameMode.generated.h"
UCLASS(Blueprintable)
class GASA_API AGasaGameMode : public AGameMode
{
GENERATED_BODY()
public:
};
namespace Gasa
{
FORCEINLINE
AGasaGameMode* GetGameMode(UObject* Context) {
return Context->GetWorld()->GetAuthGameMode<AGasaGameMode>();
}
}

View File

@ -1,9 +1,69 @@
#include "GasaLibrary.h" #include "GasaLibrary.h"
#include "GasaDevOptions.h" #include "GasaDevOptions.h"
#include "GasaLevelScriptActor.h" #include "Game/GasaLevelScriptActor.h"
#include "Engine/LevelScriptActor.h" #include "Engine/LevelScriptActor.h"
#include "Game/GasaGameInstance.h"
#include "Game/GasaGameMode.h"
#include "Game/GasaGameState.h"
#include "Game/GasaPlayerController.h"
#include "Kismet/KismetSystemLibrary.h"
UGasaDevOptions* UGasaLib::GetDevOptions(UObject* Context) { #pragma region Game
UGasaDevOptions* UGasaLib::GetGasaDevOptions(UObject* Context) {
return Gasa::GetMutDevOptions(); return Gasa::GetMutDevOptions();
} }
UGasaGameInstance* UGasaLib::GetGasaGameInstance(UObject* Context) {
return Gasa::GetGameInstance(Context);
}
AGasaGameMode* UGasaLib::GetGasaGameMode(UObject* Context) {
return Gasa::GetGameMode(Context);
}
AGasaGameState* UGasaLib::GetGasaGameState(UObject* Context) {
return Gasa::GetGameState(Context);
}
AGasaLevelScriptActor* UGasaLib::GetGasaLevelActor(UObject* Context) {
return Gasa::GetLevelActor(Context);
}
AGasaPlayerController* UGasaLib::GetPrimaryGasaPlayerController(UObject* Context) {
return Gasa::GetPrimaryPlayerController(Context);
}
#pragma endregion Game
#pragma region Logging
void UGasaLib::Log(UObject* Context, FString Message, EGasaVerbosity Verbosity, bool bPrintToScreen)
{
Gasa::Log(Message, Verbosity, LogGasa, false, 0, "", TCHAR_TO_ANSI( *Context->GetName() ));
if (bPrintToScreen)
{
if (GAreScreenMessagesEnabled)
{
if (GConfig && printToScreenDuration < 0)
{
GConfig->GetFloat(TEXT("Kismet"), TEXT("PrintStringDuration"), printToScreenDuration, GEngineIni);
}
GEngine->AddOnScreenDebugMessage((uint64)-1, printToScreenDuration, logRegularColor.ToFColor(true), Message);
}
else
{
UE_LOG(LogBlueprint, VeryVerbose, TEXT("Screen messages disabled (!GAreScreenMessagesEnabled). Cannot print to screen."));
}
}
};
// Protected
const FLinearColor UGasaLib::logRegularColor = FLinearColor(0.0, 0.66, 1.0);
float UGasaLib::printToScreenDuration = 10.0f;
#pragma endregion Logging
#pragma region Timing
// Protected
float UGasaLib::timingRate_Std = UGasaLib::_60Hz;
#pragma endregion Timing

View File

@ -15,9 +15,101 @@ class GASA_API UGasaLib : public UBlueprintFunctionLibrary
public: public:
#pragma region Game #pragma region Game
UFUNCTION(BlueprintCallable, Category="Gasa|Game", BlueprintPure, meta=(WorldContext="Context"))
static UGasaDevOptions* GetGasaDevOptions(UObject* Context);
UFUNCTION(BlueprintCallable, Category="Gasa|Game", BlueprintPure, meta=(WorldContext="Context")) UFUNCTION(BlueprintCallable, Category="Gasa|Game", BlueprintPure, meta=(WorldContext="Context"))
static UGasaDevOptions* GetDevOptions(UObject* Context); static UGasaGameInstance* GetGasaGameInstance(UObject* Context);
#pragma endregion Game
};
UFUNCTION(BlueprintCallable, Category="Gasa|Game", BlueprintPure, meta=(WorldContext="Context"))
static AGasaGameMode* GetGasaGameMode(UObject* Context);
UFUNCTION(BlueprintCallable, Category="Gasa|Game", BlueprintPure, meta=(WorldContext="Context"))
static AGasaGameState* GetGasaGameState(UObject* Context);
UFUNCTION(BlueprintCallable, Category="Gasa|Game", BlueprintPure, meta=(WorldContext="Context"))
static AGasaLevelScriptActor* GetGasaLevelActor(UObject* Context);
UFUNCTION(BlueprintCallable, Category="Gasa|Game", BlueprintPure, meta=(WorldContext="Context"))
static AGasaPlayerController* GetPrimaryGasaPlayerController(UObject* Context);
#pragma endregion Game
#pragma region Logging
UFUNCTION(BlueprintCallable, Category="Gasa|Logging", meta=(WorldContext="Context", DisplayName="Log Gasa", AdvancedDisplay="bPrintToScreen", DevelopmentOnly))
static void Log( UObject* Context, FString Message, EGasaVerbosity Verbosity = EGasaVerbosity::Log, bool bPrintOnScreen = false);
static const FLinearColor logRegularColor;
static float printToScreenDuration;
#pragma endregion Logging
#pragma region Timing
public:
static constexpr float _24Hz = .042f;
static constexpr float _30Hz = .033f;
static constexpr float _42Hz = .024f;
static constexpr float _45Hz = .022f;
static constexpr float _50Hz = .020f;
static constexpr float _60Hz = .016f;
static constexpr float _72Hz = .014f;
static constexpr float _80Hz = .013f;
static constexpr float _90Hz = .011f;
static constexpr float _100Hz = .010f;
static constexpr float _120Hz = .083f;
static constexpr float _240Hz = .004f;
static constexpr float _480Hz = .002f;
// Constant Rates
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "24 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_24Hz () { return _24Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "30 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_30Hz () { return _30Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "42 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_42Hz () { return _42Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "50 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_50Hz () { return _50Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "60 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_60Hz () { return _60Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "72 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_72Hz () { return _72Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "80 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_80Hz () { return _80Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "90 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_90Hz () { return _90Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "100 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_100Hz() { return _100Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "120 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_120Hz() { return _120Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "240 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BP_Clock_240Hz() { return _240Hz; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "480 Hz", CallableWithoutWorldContext))
static FORCEINLINE float BPClock_480Hz() { return _480Hz; }
// Standard Timing
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "Time Rate", CallableWithoutWorldContext))
static FORCEINLINE float GetStd_Timerate () { return timingRate_Std; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "Quarter Time Rate", CallableWithoutWorldContext))
static FORCEINLINE float GetStd_Timerate_Quarter() { return timingRate_Std / 4.0f; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "Half Time Rate", CallableWithoutWorldContext))
static FORCEINLINE float GetStd_Timerate_Half () { return timingRate_Std / 2.0f; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "2X Time Rate", CallableWithoutWorldContext))
static FORCEINLINE float GetStd_Timerate_2X () { return timingRate_Std * 2.0f; }
UFUNCTION(BlueprintPure, Category = "Timing", Meta = (DisplayName = "4X Time Rate", CallableWithoutWorldContext))
static FORCEINLINE float GetStd_Timerate_4X () { return timingRate_Std * 2.0f; }
UFUNCTION(BlueprintCallable, Category = "Timing", Meta = (DisplayName = "Set Time Rate"))
static void SetStd_Timerate(float _rateDesired)
{
// Not the best check.. if inconsistency arises, use the a rigorous one.
if (_rateDesired >= _24Hz)
{
timingRate_Std = _rateDesired;
}
}
protected:
static float timingRate_Std;
#pragma endregion Timing
};