From fd453e6b3041ed0d6e4e84fface05abbeb90c9d0 Mon Sep 17 00:00:00 2001 From: jyelon Date: Wed, 2 Jul 2025 16:01:18 -0400 Subject: [PATCH] Fix bugs in animation queue handling, and add animation timeouts --- Content/Tangibles/TAN_Character.uasset | 4 +- Integration.code-workspace.tpl.json | 3 +- Source/Integration/AnimQueue.cpp | 100 ++++++++--- Source/Integration/AnimQueue.h | 22 ++- Source/Integration/LuprexGameModeBase.cpp | 7 + Source/Integration/Tangible.cpp | 191 ++++++++++++++-------- Source/Integration/Tangible.h | 13 ++ build.py | 11 +- luprex/cpp/core/lpxclient.cpp | 6 +- 9 files changed, 251 insertions(+), 106 deletions(-) diff --git a/Content/Tangibles/TAN_Character.uasset b/Content/Tangibles/TAN_Character.uasset index a4cefb4a..6aad5fa5 100644 --- a/Content/Tangibles/TAN_Character.uasset +++ b/Content/Tangibles/TAN_Character.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e23a73e194bab4dbd8a932d68238059beb5edae6d74e81f06dd310f23660996 -size 313663 +oid sha256:53c19d3abc7119c55a8126e6f5a6d34e0e6bf969f460333a9db98108f9b104f6 +size 309058 diff --git a/Integration.code-workspace.tpl.json b/Integration.code-workspace.tpl.json index df1f8baa..90f3a1ce 100644 --- a/Integration.code-workspace.tpl.json +++ b/Integration.code-workspace.tpl.json @@ -94,7 +94,7 @@ "body": { "name": "Server=[SERVER]", "request": "launch", - "program": "[UNREALENGINE]/Engine/Binaries/Linux/UnrealEditor-Linux-DebugGame", + "program": "[UNREALENGINE]/Engine/Binaries/Linux/UnrealEditor-Linux-[DEBUG]", "preLaunchTask": "python3 build.py c++", "args": [ "[INTEGRATION]/Integration.uproject", @@ -103,6 +103,7 @@ ], "cwd": "[INTEGRATION]", "type": "lldb", + "console": "integratedTerminal", "initCommands": [ "command script import [UNREALENGINE]/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py", "settings set target.inline-breakpoint-strategy always", diff --git a/Source/Integration/AnimQueue.cpp b/Source/Integration/AnimQueue.cpp index f5cb7548..dd0794d2 100644 --- a/Source/Integration/AnimQueue.cpp +++ b/Source/Integration/AnimQueue.cpp @@ -2,6 +2,7 @@ #include "AnimQueue.h" #include "UtilityLibrary.h" #include "GameFramework/Actor.h" +#include FlxAnimationStep::FlxAnimationStep(uint64 hash, std::string_view body) { Finished = false; @@ -140,7 +141,7 @@ void UlxAnimationStepLibrary::UnpackAnimationStep(bool &bChanged, FString &Actio FString UlxAnimationStepLibrary::AnimationStepDebugString(const FlxAnimationStep& step) { std::string_view body((const char*)(step.Body.GetData()), step.Body.Num()); - return FlxAnimationStepDecoder::DebugString(step.Finished, step.Finished, step.Hash, body); + return FlxAnimationStepDecoder::DebugString(step.Finished, step.Hash, body); } static FlxAnimationField FindAnimationFieldLL(const FlxAnimationStep& step, std::string_view name) { @@ -264,16 +265,15 @@ FlxAnimationField FlxAnimationStepDecoder::ReadField() { return result; } -FString FlxAnimationStepDecoder::DebugString(bool injectidle, bool persistentonly, uint64 hash, std::string_view body) { +FString FlxAnimationStepDecoder::DebugString(bool finished, uint64 hash, std::string_view body) { FString result; FlxAnimationStepDecoder decoder(body); result.Appendf(TEXT("Hash=%016llx"), hash); - if (injectidle) { - result.Appendf(TEXT(" action=idle")); + if (finished) { + result.Appendf(TEXT(" finished")); } while (!decoder.AtEOF()) { FlxAnimationField field = decoder.ReadField(); - if (persistentonly && !field.Persistent) continue; result.Append(TEXT(" ")); result.Append(FString(field.Name.size(), (const UTF8CHAR*)field.Name.data())); result.Append(field.Persistent ? TEXT("=") : TEXT(":")); @@ -317,16 +317,16 @@ FlxAnimQueueDecoder::FlxAnimQueueDecoder(std::string_view queue) : Decoder(queue ActualSize = Decoder.read_uint8(); } -FString FlxAnimQueueDecoder::DebugString(std::string_view queue) { - FString result; - FlxAnimQueueDecoder decoder(queue); - while (!decoder.AtEOF()) { - FlxAnimationStepView step = decoder.ReadStep(); - FString stepdebug = FlxAnimationStepDecoder::DebugString(false, false, step.Hash, step.Body); - result.Appendf(TEXT("%s\n"), *stepdebug); - } - return result; -} +// FString FlxAnimQueueDecoder::DebugString(std::string_view queue) { +// FString result; +// FlxAnimQueueDecoder decoder(queue); +// while (!decoder.AtEOF()) { +// FlxAnimationStepView step = decoder.ReadStep(); +// FString stepdebug = FlxAnimationStepDecoder::DebugString(false, step.Hash, step.Body); +// result.Appendf(TEXT("%s\n"), *stepdebug); +// } +// return result; +// } FlxAnimTracker::FlxAnimTracker() { Clear(); @@ -358,6 +358,30 @@ void FlxAnimTracker::SkipToEnd() { } } +const FlxAnimationStep *FlxAnimTracker::FirstUnfinished() const +{ + for (int i = 0; i < AQ.Num(); i++) { + if (!AQ[i].Finished) return &AQ[i]; + } + return nullptr; +} + +const FlxAnimationStep *FlxAnimTracker::LastFinished() const +{ + for (int i = AQ.Num() - 1; i >= 0; i--) { + if (AQ[i].Finished) return &AQ[i]; + } + return nullptr; +} + +const FlxAnimationStep *FlxAnimTracker::FindAnimation(uint64 hash) const +{ + for (int i = 0; i < AQ.Num(); i++) { + if (AQ[i].Hash == hash) return &AQ[i]; + } + return nullptr; +} + void FlxAnimTracker::Update(std::string_view encqueue) { check(!encqueue.empty()); @@ -409,14 +433,14 @@ void FlxAnimTracker::Update(std::string_view encqueue) { int32 nremove = (AQ.Num() - (matchingindex + 1)); check((nremove >= 0) && (nremove <= AQ.Num())); for (int32 i = 0; i < nremove; i++) { - AQ.PopLast(); + AQ.Pop(); } // Transfer the new animations onto the queue. // while (!newsteps.IsEmpty()) { FlxAnimationStepView step = newsteps.Pop(); - AQ.EmplaceLast(step.Hash, step.Body); + AQ.Emplace(step.Hash, step.Body); } // If there are too many animations in AQ, discard @@ -425,12 +449,15 @@ void FlxAnimTracker::Update(std::string_view encqueue) { // TODO: this is hardwired to keep 10. Instead, we // should keep the number specified in the queue. // - int limit = 10; - int ndiscard = AQ.Num() - limit; - if (ndiscard > 0) { - for (int i = 0; i < ndiscard; i++) { - AQ.PopFirst(); + const int limit = 10; + if (AQ.Num() > limit) + { + int offset = AQ.Num() - limit; + for (int i = 0; i < limit; i++) + { + AQ[i] = AQ[i + offset]; } + AQ.SetNum(limit); } // Autofinish up to one animation. @@ -450,6 +477,34 @@ void FlxAnimTracker::Update(std::string_view encqueue) { } } +FString FlxAnimTracker::DebugString() const +{ + FString Result; + if (Changed) + { + Result += TEXT("changed=true "); + } + else + { + Result += TEXT("changed=false "); + } + if (AutoFinish) + { + Result += TEXT("autofinish=true"); + } + else + { + Result += TEXT("autofinish=false"); + } + Result += TEXT("\n"); + for (int i = 0; i < AQ.Num(); i++) + { + Result += UlxAnimationStepLibrary::AnimationStepDebugString(AQ[i]); + Result += TEXT("\n"); + } + return Result; +} + void FlxAnimTracker::SetAutoFinish(const FString &action, const FVector &xyz) { AutoFinish = true; AutoFinishAction = action; @@ -486,3 +541,4 @@ FlxAnimationStep FlxAnimTracker::GetCurrentAnimation() { result.Hash += 1; return result; } + diff --git a/Source/Integration/AnimQueue.h b/Source/Integration/AnimQueue.h index ce4baf17..6159a367 100644 --- a/Source/Integration/AnimQueue.h +++ b/Source/Integration/AnimQueue.h @@ -197,7 +197,7 @@ public: // Convert an AnimQueue to an FString. // - static FString DebugString(std::string_view s); + // static FString DebugString(std::string_view s); }; //////////////////////////////////////////////// @@ -230,7 +230,7 @@ public: // Convert an AnimStep to an FString. // - static FString DebugString(bool injectidle, bool persistentonly, uint64 hash, std::string_view body); + static FString DebugString(bool finished, uint64 hash, std::string_view body); }; //////////////////////////////////////////////// @@ -251,7 +251,7 @@ public: // store the hashes, not the steps. The First element // of the queue is the oldest item. // - TDeque AQ; + TArray AQ; // True if something has recently changed. // @@ -319,6 +319,18 @@ public: // void SkipToEnd(); + // Return the first unfinished animation. + // + const FlxAnimationStep *FirstUnfinished() const; + + // Return the last finished animation. + // + const FlxAnimationStep *LastFinished() const; + + // Return the first animation with the specified hash. + // + const FlxAnimationStep *FindAnimation(uint64 hash) const; + // Clear the 'Changed' flag. // void ClearChanged() { Changed = false; } @@ -331,4 +343,8 @@ public: // The changed flag can only be set to false by 'ClearChanged,' above. // bool IsChanged() const { return Changed; } + + // Return a debug string for the entire animation tracker. + // + FString DebugString() const; }; \ No newline at end of file diff --git a/Source/Integration/LuprexGameModeBase.cpp b/Source/Integration/LuprexGameModeBase.cpp index bfa68433..b4e00b1a 100644 --- a/Source/Integration/LuprexGameModeBase.cpp +++ b/Source/Integration/LuprexGameModeBase.cpp @@ -155,6 +155,13 @@ void ALuprexGameModeBase::UpdateTangibles() { for (int i = 0; i < alltans.Num(); i++) { alltans[i]->UpdateAnimationQueue(allqueues[i]); } + // Debugging hook. + volatile bool printaqs = false; + if (printaqs) { + for (int i = 0; i < alltans.Num(); i++) { + UE_LOG(LogLuprex, Display, TEXT("\n--- AQ of %ld ---\n%s\n"), allids[i], *(alltans[i]->AnimTracker.DebugString())); + } + } } // This is where we run the blueprint code that updates animation // states. Be aware that the blueprint code could call back diff --git a/Source/Integration/Tangible.cpp b/Source/Integration/Tangible.cpp index 4687a66f..1f65e3af 100644 --- a/Source/Integration/Tangible.cpp +++ b/Source/Integration/Tangible.cpp @@ -23,7 +23,32 @@ void UlxTangible::Init(UlxTangibleManager* tm, int64 id) TangibleId = id; } -#pragma optimize("", off) +void UlxTangible::DeleteCurrentActor() +{ + if (CurrentActor == nullptr) return; + + // Remove the tangible component. This is probably + // unnecessary, but it makes it more likely that we'll + // catch bugs early. + UlxTangibleComponent* comp = CurrentActor->GetComponentByClass(); + if (comp != nullptr) { + comp->DestroyComponent(); + } + + // Now destroy the actor itself. According to various + // documents I've read online, it may be necessary to take + // further steps to delete the object. Not clear. + CurrentActor->Destroy(); + + // If this actor previously was posessed by a player controller, + // then it's not posessed anymore, because there is no actor any more. + if (Manager->PossessedTangible == this) { + Manager->PossessedTangible = nullptr; + }; + + CurrentActor = nullptr; +} + void UlxTangible::SetActorBlueprint(const FString &XName) { FString Name = XName.ToLower(); @@ -32,7 +57,6 @@ void UlxTangible::SetActorBlueprint(const FString &XName) { return; } - // Get the blueprint. UClass *blueprint = UlxAssetLookup::LoadTangibleBlueprintAsset(this, Name); if (blueprint == nullptr) { @@ -40,71 +64,50 @@ void UlxTangible::SetActorBlueprint(const FString &XName) { check(blueprint != nullptr); } - // If there's already an actor, delete it. - if (CurrentActor != nullptr) { - // Remove the tangible component. This is probably - // unnecessary, but it makes it more likely that we'll - // catch bugs early. - UlxTangibleComponent* comp = CurrentActor->GetComponentByClass(); - if (comp != nullptr) { - comp->DestroyComponent(); - } - - // Now destroy the actor itself. According to various - // documents I've read online, it may be necessary to take - // further steps to delete the object. Not clear. - CurrentActor->Destroy(); - - // If this actor previously was posessed by a player controller, - // then it's not posessed anymore, because there is no actor any more. - if (Manager->PossessedTangible == this) { - Manager->PossessedTangible = nullptr; - }; - } - // Update the blueprint name ActorBlueprintName = Name; - // Now create a new actor, unless the BP is nullptr. - if (blueprint != nullptr) { - UWorld* w = Manager->GetWorld(); - FActorSpawnParameters params; + // If there's already an actor, delete it. + DeleteCurrentActor(); - // Give the new actor a reasonable name. - params.Name = FName(*FString::Printf(TEXT("%s_%ld"), *Name, TangibleId)); + // Now create a new actor. + UWorld* w = Manager->GetWorld(); + FActorSpawnParameters params; - // Currently, the actor is spawned at (0,0,0), which is not good. - // We should spawn at the actor's current location. I'll get to it - // eventually. - FTransform transform; - transform.SetLocation(FVector(0,0,0)); - transform.SetRotation(FQuat(FRotator(0,0,0))); + // Give the new actor a reasonable name. + params.Name = FName(*FString::Printf(TEXT("%s_%ld"), *Name, TangibleId)); - // Create the actor at the specified location even if there's something in the way. - params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; - - // Normally, SpawnActor runs the BeginPlay entry point. We - // want to delay that until after we've had a chance to set - // up the TangibleComponent. - params.bDeferConstruction = true; - AActor* a = w->SpawnActor(blueprint, &transform, params); - check(a != nullptr); + // Currently, the actor is spawned at (0,0,0), which is not good. + // We should spawn at the actor's current location. I'll get to it + // eventually. + FTransform transform; + transform.SetLocation(FVector(0,0,0)); + transform.SetRotation(FQuat(FRotator(0,0,0))); - // Make sure the label and the name are the same. - a->SetActorLabel(params.Name.ToString()); + // Create the actor at the specified location even if there's something in the way. + params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + + // Normally, SpawnActor runs the BeginPlay entry point. We + // want to delay that until after we've had a chance to set + // up the TangibleComponent. + params.bDeferConstruction = true; + AActor* a = w->SpawnActor(blueprint, &transform, params); + check(a != nullptr); - // Insert a TangibleComponent into the actor. - // Link the actor to its tangible, and the tangible to its actor. - UActorComponent* ac = a->AddComponentByClass(UlxTangibleComponent::StaticClass(), false, FTransform::Identity, false); - UlxTangibleComponent* tc = Cast(ac); - check(tc != nullptr); - tc->Tangible = this; - CurrentActor = a; + // Make sure the label and the name are the same. + a->SetActorLabel(params.Name.ToString()); - // This executes the BeginPlay entry point. We have to do this here - // because we deferred it in SpawnActor. - a->FinishSpawning(transform, true); - } + // Insert a TangibleComponent into the actor. + // Link the actor to its tangible, and the tangible to its actor. + UActorComponent* ac = a->AddComponentByClass(UlxTangibleComponent::StaticClass(), false, FTransform::Identity, false); + UlxTangibleComponent* tc = Cast(ac); + check(tc != nullptr); + tc->Tangible = this; + CurrentActor = a; + + // This executes the BeginPlay entry point. We have to do this here + // because we deferred it in SpawnActor. + a->FinishSpawning(transform, true); } void UlxTangible::UpdateAnimationQueue(std::string_view aq) { @@ -113,6 +116,9 @@ void UlxTangible::UpdateAnimationQueue(std::string_view aq) { void UlxTangible::MaybeExecuteAnimStateChanged() { int limit = 3; + + bool AnyChange = AnimTracker.IsChanged(); + while (AnimTracker.IsChanged()) { if (limit == 0) break; limit -= 1; @@ -122,13 +128,47 @@ void UlxTangible::MaybeExecuteAnimStateChanged() { SetActorBlueprint(blueprint); AActor *actor = GetActor(); UFunction *aqchanged = actor->GetClass()->FindFunctionByName(FName(TEXT("Animation Queue Changed"))); - if (aqchanged != nullptr) { + if (aqchanged != nullptr) + { actor->ProcessEvent(aqchanged, nullptr); } } + + // Refresh the pending animation state. + double Now = GetWorld()->GetTimeSeconds(); + if (AnyChange) + { + const FlxAnimationStep *Unfinished = AnimTracker.FirstUnfinished(); + if (Unfinished == nullptr) + { + PendingAnimationHash = 0; + PendingAnimationTimeout = 0.0; + } + else if (Unfinished->Hash != PendingAnimationHash) + { + PendingAnimationHash = Unfinished->Hash; + PendingAnimationTimeout = Now + 10.0; + } + } + + // Implement the animation timeout. + if ((PendingAnimationHash != 0) && (Now > PendingAnimationTimeout)) + { + const FlxAnimationStep *Step = AnimTracker.FindAnimation(PendingAnimationHash); + if (Step != nullptr) + { + FString DS = UlxAnimationStepLibrary::AnimationStepDebugString(*Step); + UE_LOG(LogLuprex, Warning, TEXT("Timeout - blueprint didn't finish animation: %s"), *DS); + AnimTracker.FinishedAnimation(PendingAnimationHash); + } + AutoUpdatePosition(); + PendingAnimationHash = 0; + PendingAnimationTimeout = 0.0; + } } -FVector UlxTangible::GetLocation() const { +FVector UlxTangible::GetLocation() const +{ if (CurrentActor == nullptr) { return FVector(0,0,0); } else { @@ -136,8 +176,9 @@ FVector UlxTangible::GetLocation() const { } } -void UlxTangible::Destroy() { - SetActorBlueprint(""); +void UlxTangible::Destroy() +{ + DeleteCurrentActor(); Manager = nullptr; TangibleId = -1; CurrentActor = nullptr; @@ -147,14 +188,16 @@ void UlxTangible::Destroy() { NearAccordingToUnreal = false; } -UlxTangible *UlxTangible::GetActorTangibleQuiet(AActor *actor) { +UlxTangible *UlxTangible::GetActorTangibleQuiet(AActor *actor) +{ if (actor == nullptr) return nullptr; UlxTangibleComponent* comp = actor->GetComponentByClass(); if (comp == nullptr) return nullptr; return comp->Tangible.Get(); } -UlxTangible *UlxTangible::GetActorTangibleOrLog(AActor *actor) { +UlxTangible *UlxTangible::GetActorTangibleOrLog(AActor *actor) +{ UlxTangible *tan = GetActorTangibleQuiet(actor); if (tan == nullptr) { if (actor == nullptr) { @@ -175,18 +218,24 @@ void UlxTangible::GetCurrentAnimation(AActor *target, FlxAnimationStep &step) { step = tan->AnimTracker.GetCurrentAnimation(); } +void UlxTangible::AutoUpdatePosition() +{ + const FlxAnimationStep *Step = AnimTracker.LastFinished(); + if (Step != nullptr) + { + Step->AutoUpdateXYZ(GetActor()); + Step->AutoUpdateFacing(GetActor()); + Step->AutoUpdatePlane(&(this->Plane)); + } +} + void UlxTangible::FinishedAnimation(AActor *target, const FlxAnimationStep &step, bool AutoUpdate) { UlxTangible *tan = GetActorTangibleOrLog(target); if (tan == nullptr) return; - if (AutoUpdate) - { - step.AutoUpdateXYZ(target); - step.AutoUpdateFacing(target); - step.AutoUpdatePlane(&(tan->Plane)); - } tan->AnimTracker.FinishedAnimation(step.Hash); + if (AutoUpdate) tan->AutoUpdatePosition(); FString DebugString = UlxAnimationStepLibrary::AnimationStepDebugString(step); - UE_LOG(LogBlueprint, Display, TEXT("Animation Finished: %s"), *DebugString); + UE_LOG(LogLuprex, Display, TEXT("Animation Finished: %s"), *DebugString); } FString UlxTangible::GetTangiblePlane(AActor* target) { diff --git a/Source/Integration/Tangible.h b/Source/Integration/Tangible.h index 40653603..312fa1d9 100644 --- a/Source/Integration/Tangible.h +++ b/Source/Integration/Tangible.h @@ -57,6 +57,12 @@ public: // Animation tracker FlxAnimTracker AnimTracker; + // Animation that is waiting to be finished. + uint64 PendingAnimationHash; + + // When do we timeout the pending animation. + double PendingAnimationTimeout; + // Current Plane. FName Plane; @@ -66,6 +72,10 @@ public: // True if unreal thinks this object is Near the player. bool NearAccordingToUnreal; + // Delete the current actor. + // + void DeleteCurrentActor(); + public: // Initialize a new tangible. // @@ -122,6 +132,9 @@ public: static UlxTangible *GetActorTangibleQuiet(AActor *actor); static UlxTangible *GetActorTangibleOrLog(AActor *actor); + // Automatically update the tangible's XYZ, Plane, Facing. + // + void AutoUpdatePosition(); private: diff --git a/build.py b/build.py index 50246f5e..b85af31a 100755 --- a/build.py +++ b/build.py @@ -156,6 +156,7 @@ def autodetect_system_config(): config.DOT_EXE = ".exe" config.USER = "Unknown" config.BUILD_BAT = "Build.bat" + config.DEBUG = "DebugGame" else: config.OS = "Linux" config.DLL = "so" @@ -163,6 +164,7 @@ def autodetect_system_config(): config.DOT_EXE = "" config.USER = os.environ["USER"] config.BUILD_BAT = "Linux/Build.sh" + config.DEBUG = "DebugGame" return config @@ -170,13 +172,14 @@ def store_system_config_in_globals(config): """ Copy all the config data from the config object into global variables. """ - global OS,DLL,BAT,DOT_EXE,USER,BUILD_BAT,INTEGRATION,UNREALENGINE + global OS,DLL,BAT,DOT_EXE,USER,BUILD_BAT,DEBUG,INTEGRATION,UNREALENGINE OS = config.OS DLL = config.DLL BAT = config.BAT DOT_EXE = config.DOT_EXE USER = config.USER BUILD_BAT = config.BUILD_BAT + DEBUG = config.DEBUG INTEGRATION = config.INTEGRATION UNREALENGINE = config.UNREALENGINE @@ -278,7 +281,7 @@ def build_luprex_and_integration(): This builds our C++ code, and also UnrealEngine's C++ code. """ shell(f"{INTEGRATION}/luprex", "make all") - shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} DebugGame {INTEGRATION}/Integration.uproject") + shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} {DEBUG} {INTEGRATION}/Integration.uproject") # @@ -291,7 +294,7 @@ def build_intellisense_database_for_clangd(): based on clangd how to compile each source file. This also installs a .clangd file in the UnrealEngine directory. """ - mods1 = Path(f"{INTEGRATION}/Intermediate/Build/{OS}").rglob("UnrealEditor/DebugGame/**/Module.*.o.rsp") + mods1 = Path(f"{INTEGRATION}/Intermediate/Build/{OS}").rglob("UnrealEditor/{DEBUG}/**/Module.*.o.rsp") mods2 = Path(f"{UNREALENGINE}/Engine/Intermediate/Build/{OS}").rglob("UnrealEditor/Development/**/Module.*.o.rsp") mods = list(mods1) + list(mods2) clangs = list(Path(f"{UNREALENGINE}/Engine/Extras/ThirdPartyNotUE/SDKs").rglob("*-linux-gnu/bin/clang++")) @@ -333,7 +336,7 @@ def build_clean(): This code is underdeveloped. """ shell(f"{INTEGRATION}/luprex", "make clean") - shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} DebugGame {INTEGRATION}/Integration.uproject -clean") + shell(INTEGRATION, f"{UNREALENGINE}/Engine/Build/BatchFiles/{BUILD_BAT} -waitmutex IntegrationEditor {OS} {DEBUG} {INTEGRATION}/Integration.uproject -clean") Path(f"{INTEGRATION}/.vscode/compile_commands.json").unlink(missing_ok = True) # diff --git a/luprex/cpp/core/lpxclient.cpp b/luprex/cpp/core/lpxclient.cpp index cd280c89..55820d4f 100644 --- a/luprex/cpp/core/lpxclient.cpp +++ b/luprex/cpp/core/lpxclient.cpp @@ -179,7 +179,7 @@ public: } void change_actor_id(int64_t actor_id) { - stdostream() << "Actor ID changing: " << actor_id << std::endl; + util::dprint("Actor ID changing: ", actor_id); print_channeler_.reset(); actor_id_ = actor_id; set_visible_world_and_actor(world_.get(), actor_id_); @@ -257,7 +257,7 @@ public: break; } default: { - stdostream() << "Invalid event_access: " << int(kind) << std::endl; + util::dprint("Invalid event_access: ", int(kind)); } } } @@ -281,7 +281,7 @@ public: // Check for communication from server.. if (channel_ != nullptr) { if (channel_->closed()) { - stdostream() << "server closed connection: " << channel_->error() << std::endl; + util::dprint("server closed connection: ", channel_->error()); abandon_server(); } else { while (true) {