Now echoing Luprex console messages to the Unreal Log as well. Had to make them warnings in order to make them more visible, which in turn meant I had to modify the BreakToDebugger system to be able to ignore these console messages.

This commit is contained in:
2026-06-10 17:20:45 -04:00
parent 0b5c47d8c7
commit f7e9305d64
11 changed files with 70 additions and 39 deletions

Binary file not shown.

View File

@@ -2,6 +2,7 @@
#include "BreakToDebugger.h"
#include "Blueprint/BlueprintExceptionInfo.h"
#include "Kismet2/KismetDebugUtilities.h"
#include "LuprexEditorSettings.h"
ELogVerbosity::Type FlxBreakToDebuggerOutputDevice::ConvertThreshold(ElxBreakToDebuggerThreshold Verbosity) {
switch (Verbosity) {
@@ -15,8 +16,8 @@ ELogVerbosity::Type FlxBreakToDebuggerOutputDevice::ConvertThreshold(ElxBreakToD
}
}
FlxBreakToDebuggerOutputDevice::FlxBreakToDebuggerOutputDevice(const ElxBreakToDebuggerThreshold &SensitivityRef)
: Sensitivity(SensitivityRef)
FlxBreakToDebuggerOutputDevice::FlxBreakToDebuggerOutputDevice()
: Settings(GetDefault<UlxEditorSettings>())
{
GLog->AddOutputDevice(this);
}
@@ -48,7 +49,7 @@ void FlxBreakToDebuggerOutputDevice::Serialize(const TCHAR* V, ELogVerbosity::Ty
{
// If the error isn't serious enough, do nothing.
//
if (Verbosity > ConvertThreshold(Sensitivity))
if (Verbosity > ConvertThreshold(Settings->BreakToDebuggerLogVerbosity))
{
return;
}
@@ -67,6 +68,13 @@ void FlxBreakToDebuggerOutputDevice::Serialize(const TCHAR* V, ELogVerbosity::Ty
UObject *TopObject = Frame->Object;
if (TopObject == nullptr) return;
// If the category is in the exclude list, do nothing.
//
if (Settings->BreakToDebuggerExcludeCategories.Contains(Category))
{
return;
}
// Notify the debugger that there's been an exception.
//
FBlueprintExceptionInfo ExceptionInfo(EBlueprintExceptionType::Breakpoint, FText::FromStringView(FStringView(V)));

View File

@@ -79,19 +79,15 @@ enum class ElxBreakToDebuggerThreshold : uint8 {
};
class UlxEditorSettings;
struct FlxBreakToDebuggerOutputDevice : public FOutputDevice
{
public:
// The constructor and destructor automatically register
// this output device with GLog.
//
// This struct doesn't store the sensitivity threshold.
// It relies on the LuprexGameMode class to do that, so
// that the threshold can be easily edited with the
// blueprint editor. This struct must be initialized
// with a reference to the threshold variable.
//
FlxBreakToDebuggerOutputDevice(const ElxBreakToDebuggerThreshold &SensitivityRef);
FlxBreakToDebuggerOutputDevice();
~FlxBreakToDebuggerOutputDevice();
// Inspect a log message.
@@ -109,5 +105,5 @@ public:
private:
static ELogVerbosity::Type ConvertThreshold(ElxBreakToDebuggerThreshold Verbosity);
const ElxBreakToDebuggerThreshold &Sensitivity;
const UlxEditorSettings *Settings = nullptr;
};

View File

@@ -2,3 +2,4 @@
DEFINE_LOG_CATEGORY(LogLuprex);
DEFINE_LOG_CATEGORY(LogLuprexIntegration);
DEFINE_LOG_CATEGORY(LogLuprexConsole);

View File

@@ -153,3 +153,7 @@ DECLARE_LOG_CATEGORY_EXTERN(LogLuprex, Display, All);
// Messages about the Luprex integration with Unreal.
//
DECLARE_LOG_CATEGORY_EXTERN(LogLuprexIntegration, Display, All);
// Messages from the Luprex console.
//
DECLARE_LOG_CATEGORY_EXTERN(LogLuprexConsole, Display, All);

View File

@@ -1 +1,7 @@
#include "LuprexEditorSettings.h"
#include "Common.h"
UlxEditorSettings::UlxEditorSettings()
{
BreakToDebuggerExcludeCategories.Add(LogLuprexConsole.GetCategoryName());
}

View File

@@ -25,6 +25,8 @@ class INTEGRATION_API UlxEditorSettings : public UDeveloperSettings
GENERATED_BODY()
public:
UlxEditorSettings();
virtual FName GetContainerName() const override { return TEXT("Editor"); }
virtual FName GetCategoryName() const override { return TEXT("Luprex"); }
virtual FName GetSectionName() const override { return TEXT("Settings"); }
@@ -39,5 +41,9 @@ public:
// severity, the blueprint debugger will automatically pause with a breakpoint.
UPROPERTY(Config, EditAnywhere, Category="Debugging Tools")
ElxBreakToDebuggerThreshold BreakToDebuggerLogVerbosity;
// Log categories in this set are excluded from BreakToDebugger triggering.
UPROPERTY(Config, EditAnywhere, Category="Debugging Tools")
TSet<FName> BreakToDebuggerExcludeCategories;
};

View File

@@ -238,7 +238,7 @@ void ALuprexGameModeBase::InitializeGlobalState()
// If somebody generates a log message that's severe enough, break to debugger.
BreakToDebuggerLogVerbosityDevice.Reset(
new FlxBreakToDebuggerOutputDevice(GetDefault<UlxEditorSettings>()->BreakToDebuggerLogVerbosity));
new FlxBreakToDebuggerOutputDevice());
}
void ALuprexGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason)

View File

@@ -242,3 +242,8 @@ void UlxUtilityLibrary::ValidateLuaExpr(
Status = w.ValidateLuaExpr(Code, ErrorMessage);
}
void UlxUtilityLibrary::LogLuprexConsoleMessage(const FString &Message)
{
UE_LOG(LogLuprexConsole, Warning, TEXT("%s"), *Message);
}

View File

@@ -144,4 +144,9 @@ public:
//
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Utility")
static void ValidateLuaExpr(ElxLuaSyntaxCheck &Status, FString &ErrorMessage, UObject *context, const FString &Code);
// Log a message to the LogLuprexConsole category.
//
UFUNCTION(BlueprintCallable, Category = "Luprex|Utility")
static void LogLuprexConsoleMessage(const FString &Message);
};

View File

@@ -35,7 +35,7 @@ end
function login.init(self, config)
local player = global.get("nextplayer")
global.set("nextplayer", player + 1)
dprintf("login.init initializing %p, player %d", self, player)
printf("login.init initializing %p, player %d", self, player)
self.player = player
self.color={0,0,0,0,0,0,0,0,0,0,0,0}
self.kills=0
@@ -45,7 +45,7 @@ function login.init(self, config)
end
function login.startscanning()
dprintf("Scanning started. Actor=%p Place=%p", actor, place)
printf("Scanning started. Actor=%p Place=%p", actor, place)
while true do
login.onescan()
wait(1)
@@ -75,7 +75,7 @@ end
-- This gets called on the admin user. You can call login.init in here if you want.
function world.init(self, config)
dprint("world.init")
print("world.init")
global.set("nextplayer", 0)
tangible.build{class=roster, anim={plane="earth", xyz={2000,0,0} } }
tangible.build{class=cube, anim={plane="earth", xyz={500,-100,0}, mat_color={1,0,0}}}
@@ -89,7 +89,7 @@ function roster.init(self,config)
end
function world.buildpylon()
dprint("Building pylon")
print("Building pylon")
local radius=1000
tangible.build{class=pylon,plane="earth",xyz={math.random(-radius,radius),math.random(-radius,radius),0}}.color=math.random(1,12)
end
@@ -110,29 +110,29 @@ end
-- Four cases: Unnamed to new, Unnamed to existing, Named to new, Named to Existing
function playas(who)
dprintf("Playas %lP",place)
printf("Playas %lP",place)
if not actor.name and not place.character[who] then -- Unnamed to new
dprintf("Case 1: Naming this character "..who)
printf("Case 1: Naming this character "..who)
actor.name=who
tangible.keepactor(actor)
place.character[who]=actor
elseif actor.name and not place.character[who] then -- Named to new (Hard one)
dprintf("Case 2: Creating new character "..who)
dprintf("Case 2.0")
printf("Case 2: Creating new character "..who)
printf("Case 2.0")
local nc=tangible.build{class=login, anim={plane="earth", xyz={0,0,0} } }
dprintf("Case 2.1")
printf("Case 2.1")
nc.name=who
dprintf("Case 2.2")
printf("Case 2.2")
tangible.keepactor(nc)
dprintf("Case 2.3")
printf("Case 2.3")
place.character[who]=nc
dprintf("Case 2.4: ...Place is now "..place)
printf("Case 2.4: ...Place is now "..place)
tangible.redirect(actor,nc)
elseif not actor.name and place.character[who] then
dprintf("Case 3: Logging in from unnamed to existing character "..who)
printf("Case 3: Logging in from unnamed to existing character "..who)
tangible.redirect(actor,place.character[who])
elseif actor.name and place.character[who] then
dprintf("Case 4: Logging in from "..actor.name.." to existing character "..who)
printf("Case 4: Logging in from "..actor.name.." to existing character "..who)
tangible.redirect(actor,place.character[who])
end
end
@@ -144,24 +144,24 @@ function roster.lookmenu(add)
end
function cube.lookmenu(add)
add("Cube A", function () dprint("Doing Cube A") end)
add("Cube B", function () dprint("Doing Cube B") end)
add("Cube C", function () dprint("Doing Cube C") end)
add("Cube Hi", function () dprint("Doing Cube Hi") end)
add("Cube Bye", function () dprint("Doing Cube Bye") end)
add("Cube Yo", function () dprint("Doing Cube Yo") end)
add("Cube Z", function () dprint("Doing Cube Z") end)
add("Cube A", function () print("Doing Cube A") end)
add("Cube B", function () print("Doing Cube B") end)
add("Cube C", function () print("Doing Cube C") end)
add("Cube Hi", function () print("Doing Cube Hi") end)
add("Cube Bye", function () print("Doing Cube Bye") end)
add("Cube Yo", function () print("Doing Cube Yo") end)
add("Cube Z", function () print("Doing Cube Z") end)
end
function sphere.lookhotkeys(add)
add("FaceL", "Sphere Hi", function () dprint("Doing Sphere Hi") end)
add("FaceM", "Sphere Bye", function () dprint("Doing Sphere Bye") end)
add("FaceR", "Sphere Yo", function () dprint("Doing Sphere Yo") end)
add("FaceL", "Sphere Hi", function () print("Doing Sphere Hi") end)
add("FaceM", "Sphere Bye", function () print("Doing Sphere Bye") end)
add("FaceR", "Sphere Yo", function () print("Doing Sphere Yo") end)
end
function sphere.tick(foo)
dprint("Tick")
print("Tick")
end