From 1482e5e43fcb35830860a7cf0f819deaba76f438 Mon Sep 17 00:00:00 2001 From: jyelon Date: Tue, 5 Sep 2023 03:20:11 -0400 Subject: [PATCH] Lots of refactoring in IntegrationGameModeBase --- Source/Integration/DebugPrint.cpp | 56 +++++++++++++------ Source/Integration/DebugPrint.h | 7 +++ .../Integration/IntegrationGameModeBase.cpp | 54 +++++++++--------- Source/Integration/IntegrationGameModeBase.h | 5 +- Source/Integration/LockedWrapper.cpp | 23 +++++++- Source/Integration/LockedWrapper.h | 15 ++++- 6 files changed, 109 insertions(+), 51 deletions(-) diff --git a/Source/Integration/DebugPrint.cpp b/Source/Integration/DebugPrint.cpp index 6642cc51..4946020f 100644 --- a/Source/Integration/DebugPrint.cpp +++ b/Source/Integration/DebugPrint.cpp @@ -144,24 +144,6 @@ namespace DebugPrintControl { // ////////////////////////////////////////////////////////////// -void FConsoleOutput::Append(const FString& text) { - if (!text.IsEmpty()) { - Content += text; - Truncate(); - Dirty = true; - } -} - -void FConsoleOutput::AppendLine(const FString& text) { - int csize = Content.Len(); - if ((csize > 0) && (Content[csize - 1] != '\n')) { - Content += TEXT("\n"); - } - Content += text; - Content += TEXT("\n"); - Truncate(); - Dirty = true; -} void FConsoleOutput::Truncate() { int lines = 50; @@ -178,3 +160,41 @@ void FConsoleOutput::Truncate() { } } +bool FConsoleOutput::MaybeAppendNewline() { + int csize = Content.Len(); + if ((csize > 0) && (Content[csize - 1] != '\n')) { + Content += TEXT("\n"); + return true; + } + else { + return false; + } +} + +bool FConsoleOutput::MaybeAppendText(const FString& text) { + if (!text.IsEmpty()) { + Content += text; + return true; + } + else { + return false; + } +} + +void FConsoleOutput::Append(const FString& text) { + bool modified = MaybeAppendText(text); + if (modified) { + Dirty = true; + Truncate(); + } +} + +void FConsoleOutput::AppendLine(const FString& text) { + bool modified = MaybeAppendNewline(); + modified |= MaybeAppendText(text); + modified |= MaybeAppendNewline(); + if (modified) { + Dirty = true; + Truncate(); + } +} diff --git a/Source/Integration/DebugPrint.h b/Source/Integration/DebugPrint.h index 7bcfe4ae..8b219dad 100644 --- a/Source/Integration/DebugPrint.h +++ b/Source/Integration/DebugPrint.h @@ -121,6 +121,13 @@ private: // Truncate the console to a reasonable number of // lines. The length is hardwired. void Truncate(); + + // Add a newline if there isn't one. Returns true if it changed anything. + bool MaybeAppendNewline(); + + // Append text. Returns true if it changed anything. + bool MaybeAppendText(const FString& text); + public: // Append a line of text to the console. void Append(const FString& text); diff --git a/Source/Integration/IntegrationGameModeBase.cpp b/Source/Integration/IntegrationGameModeBase.cpp index a78eeaba..8b0f9c3a 100644 --- a/Source/Integration/IntegrationGameModeBase.cpp +++ b/Source/Integration/IntegrationGameModeBase.cpp @@ -65,46 +65,44 @@ void AIntegrationGameModeBase::ResetToInitialState() } -void AIntegrationGameModeBase::HandleLuprexConsoleOutput(FLockedWrapper &w) -{ - uint32_t ndata; const char* data; - w->get_outgoing(w.Get(), 0, &ndata, &data); - if (ndata == 0) return; - std::string_view src(data, ndata); - int consumed; - std::u16string cps = drvutil::utf8_to_ucs2(src, &consumed); - w->play_sent_outgoing(w.Get(), 0, consumed); - FString fs(cps.size(), (const UCS2CHAR*)(&cps[0])); - ConsoleOutput.Append(fs); -} +void AIntegrationGameModeBase::UpdateConsoleOutput() { + // Copy Luprex Stdout into the console. + FLockedWrapper lockedwrap(LockableWrapper); + ConsoleOutput.Append(lockedwrap.FetchStdout()); -void AIntegrationGameModeBase::Tick(float DeltaSeconds) -{ - Super::Tick(DeltaSeconds); - { - FLockedWrapper lockedwrap(LockableWrapper); - if (lockedwrap->engine != nullptr) - { - EngineSeconds += DeltaSeconds; - HandleLuprexConsoleOutput(lockedwrap); - } - } + // Copy Debugging Prints into the console. TArray prints = DebugPrintControl::GetStored(); for (const FString& fs : prints) { ConsoleOutput.AppendLine(fs); } - if (ConsoleOutput.IsDirty()) - { + + // If the Console text has changed, update the widget. + if (ConsoleOutput.IsDirty()) { ConsoleSetOutput(ConsoleOutput.Get()); ConsoleOutput.ClearDirty(); } - if (EngineSeconds >= NextThreadTrigger) +} + +void AIntegrationGameModeBase::MaybeTriggerUpdateTask(float deltaseconds) { + FLockedWrapper lockedwrap(LockableWrapper); + if (lockedwrap->engine != nullptr) { - LuprexUpdateTask.Trigger(); - NextThreadTrigger += 0.05; + EngineSeconds += deltaseconds; + if (EngineSeconds >= NextThreadTrigger) + { + LuprexUpdateTask.Trigger(); + NextThreadTrigger += 0.05; + } } } +void AIntegrationGameModeBase::Tick(float deltaseconds) +{ + Super::Tick(deltaseconds); + UpdateConsoleOutput(); + MaybeTriggerUpdateTask(deltaseconds); +} + void AIntegrationGameModeBase::ConsoleSendInput(const FString& fs) { FLockedWrapper w(LockableWrapper); diff --git a/Source/Integration/IntegrationGameModeBase.h b/Source/Integration/IntegrationGameModeBase.h index 0a6a177d..8952756f 100644 --- a/Source/Integration/IntegrationGameModeBase.h +++ b/Source/Integration/IntegrationGameModeBase.h @@ -44,7 +44,10 @@ public: TSubclassOf ClassTangibleActor; // Transfer console output from the Luprex engine to unreal. - void HandleLuprexConsoleOutput(FLockedWrapper &w); + void UpdateConsoleOutput(); + + // Trigger the update task, if enough time has passed. + void MaybeTriggerUpdateTask(float deltaseconds); // The run function is called by a background thread // to update luprex sockets and update luprex itself. diff --git a/Source/Integration/LockedWrapper.cpp b/Source/Integration/LockedWrapper.cpp index 1873c76f..a03ec642 100644 --- a/Source/Integration/LockedWrapper.cpp +++ b/Source/Integration/LockedWrapper.cpp @@ -1,6 +1,7 @@ #include "LockedWrapper.h" #include "DebugPrint.h" +#include "drvutil.hpp" void FLockedWrapper::InitWrapper() { if (Lockable.Wrapper.play_initialize != nullptr) { @@ -16,4 +17,24 @@ void FLockedWrapper::InitWrapper() { Lockable.Wrapper.hook_dprint(DebugPrint::DPrint); } } -} \ No newline at end of file +} + +FString FLockedWrapper::FetchStdout() { + if (Lockable.Wrapper.engine == nullptr) { + return FString(); + } + + uint32_t ndata; const char* data; + Lockable.Wrapper.get_outgoing(Get(), 0, &ndata, &data); + + if (ndata == 0) { + return FString(); + } + + std::string_view src(data, ndata); + int consumed; + std::u16string cps = drvutil::utf8_to_ucs2(src, &consumed); + Lockable.Wrapper.play_sent_outgoing(Get(), 0, consumed); + return FString(cps.size(), (const UCS2CHAR*)(&cps[0])); +} + diff --git a/Source/Integration/LockedWrapper.h b/Source/Integration/LockedWrapper.h index 57b1f640..2704cc05 100644 --- a/Source/Integration/LockedWrapper.h +++ b/Source/Integration/LockedWrapper.h @@ -33,9 +33,6 @@ public: Lockable.Mutex.Unlock(); } - // Initialize the engine wrapper if it's not already. - void InitWrapper(); - // Operator right arrow accesses the EngineWrapper. EngineWrapper* operator ->() { return &Lockable.Wrapper; @@ -47,4 +44,16 @@ public: EngineWrapper* Get() { return &Lockable.Wrapper; } + + // Initialize the engine wrapper if it's not already. + // + // All this does is open the DLL and hook up all + // the function pointers in the wrapper to point into + // the DLL. + // + void InitWrapper(); + + // Fetch Stdout as a string. + // + FString FetchStdout(); };