diff --git a/Source/Integration/IntegrationGameModeBase.cpp b/Source/Integration/IntegrationGameModeBase.cpp index 8b0f9c3a..94ed00b5 100644 --- a/Source/Integration/IntegrationGameModeBase.cpp +++ b/Source/Integration/IntegrationGameModeBase.cpp @@ -19,6 +19,7 @@ AIntegrationGameModeBase::AIntegrationGameModeBase() SetActorTickEnabled(true); SetActorTickInterval(0.0f); DebugPrintControl::EnableCollection(); + ResetToInitialState(); } AIntegrationGameModeBase::~AIntegrationGameModeBase() @@ -39,6 +40,8 @@ uint32 AIntegrationGameModeBase::Run() { void AIntegrationGameModeBase::ResetToInitialState() { + Playing = false; + // Shut down the thread LuprexUpdateTask.Shutdown(); @@ -68,7 +71,9 @@ void AIntegrationGameModeBase::ResetToInitialState() void AIntegrationGameModeBase::UpdateConsoleOutput() { // Copy Luprex Stdout into the console. FLockedWrapper lockedwrap(LockableWrapper); - ConsoleOutput.Append(lockedwrap.FetchStdout()); + if (Playing) { + ConsoleOutput.Append(lockedwrap.FetchStdout()); + } // Copy Debugging Prints into the console. TArray prints = DebugPrintControl::GetStored(); @@ -84,6 +89,7 @@ void AIntegrationGameModeBase::UpdateConsoleOutput() { } void AIntegrationGameModeBase::MaybeTriggerUpdateTask(float deltaseconds) { + if (!Playing) return; FLockedWrapper lockedwrap(LockableWrapper); if (lockedwrap->engine != nullptr) { @@ -96,11 +102,15 @@ void AIntegrationGameModeBase::MaybeTriggerUpdateTask(float deltaseconds) { } } -void AIntegrationGameModeBase::Tick(float deltaseconds) -{ - Super::Tick(deltaseconds); - UpdateConsoleOutput(); - MaybeTriggerUpdateTask(deltaseconds); +void AIntegrationGameModeBase::UpdateTangibles() { + if (!Playing) return; + FLockedWrapper w(LockableWrapper); + int64 actor = w.GetActor(); + TangibleManager.SetActor(actor); + TangibleManager.SetNear(w.GetNear(actor, 100, 100, 100)); + for (int64 id : TangibleManager.GetNear()) { + TangibleManager.MakeTangible(id); + } } void AIntegrationGameModeBase::ConsoleSendInput(const FString& fs) @@ -120,6 +130,15 @@ void AIntegrationGameModeBase::ConsoleSendInput(const FString& fs) } } + +void AIntegrationGameModeBase::Tick(float deltaseconds) +{ + Super::Tick(deltaseconds); + UpdateConsoleOutput(); + UpdateTangibles(); + MaybeTriggerUpdateTask(deltaseconds); +} + void AIntegrationGameModeBase::BeginPlay() { Super::BeginPlay(); @@ -164,24 +183,22 @@ void AIntegrationGameModeBase::BeginPlay() { DPrint(w->error); } - else - { + if (w->engine != nullptr) { DPrint("Luprex initialize success"); + Playing = true; } } // If we successfully created a luprex engine, create a socket system and a worker thread. - if (w->engine != nullptr) - { + if (Playing) { Sockets.Reset(FLpxSockets::Create(w)); std::string error = Sockets->GetError(); check(error.empty()); LuprexUpdateTask.Startup(this); } - // Create a tangible. + // Initialize the tangible manager. TangibleManager.Init(GetWorld(), ClassTangibleActor); - TangibleManager.MakeTangible(123); } void AIntegrationGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) diff --git a/Source/Integration/IntegrationGameModeBase.h b/Source/Integration/IntegrationGameModeBase.h index 8952756f..c621594b 100644 --- a/Source/Integration/IntegrationGameModeBase.h +++ b/Source/Integration/IntegrationGameModeBase.h @@ -46,6 +46,9 @@ public: // Transfer console output from the Luprex engine to unreal. void UpdateConsoleOutput(); + // Update the tangibles according to what Luprex tells us. + void UpdateTangibles(); + // Trigger the update task, if enough time has passed. void MaybeTriggerUpdateTask(float deltaseconds); @@ -69,6 +72,10 @@ public: // Luprex socket system. Aside from construction, only touched by Luprex thread. TUniquePtr Sockets; + // True if 'BeginPlay' has been successfully completed. + // + bool Playing; + // Amount of elapsed time. float EngineSeconds; diff --git a/Source/Integration/LockedWrapper.cpp b/Source/Integration/LockedWrapper.cpp index a03ec642..440b2086 100644 --- a/Source/Integration/LockedWrapper.cpp +++ b/Source/Integration/LockedWrapper.cpp @@ -20,10 +20,6 @@ void FLockedWrapper::InitWrapper() { } FString FLockedWrapper::FetchStdout() { - if (Lockable.Wrapper.engine == nullptr) { - return FString(); - } - uint32_t ndata; const char* data; Lockable.Wrapper.get_outgoing(Get(), 0, &ndata, &data); @@ -38,3 +34,13 @@ FString FLockedWrapper::FetchStdout() { return FString(cps.size(), (const UCS2CHAR*)(&cps[0])); } +int64 FLockedWrapper::GetActor() { + return Lockable.Wrapper.get_actor_id(Get()); +} + +FLockedWrapper::IdList FLockedWrapper::GetNear(int64 id, double rx, double ry, double rz) { + uint32 size; + int64* data; + Lockable.Wrapper.get_tangibles_near(Get(), id, rx, ry, rz, &size, &data); + return IdList(data, size); +} diff --git a/Source/Integration/LockedWrapper.h b/Source/Integration/LockedWrapper.h index 2704cc05..bf97a79d 100644 --- a/Source/Integration/LockedWrapper.h +++ b/Source/Integration/LockedWrapper.h @@ -22,6 +22,8 @@ class FLockedWrapper { private: FLockableWrapper& Lockable; + using IdList = TArrayView; + public: // The constructor of the FLockedWrapper claims the mutex. FLockedWrapper(FLockableWrapper& w) : Lockable(w) { @@ -56,4 +58,16 @@ public: // Fetch Stdout as a string. // FString FetchStdout(); + + // Get the current Actor ID. + // + int64 GetActor(); + + // Get the list of tangibles near the actor. + // + // This function is fast but not free. You should fetch this + // once per frame and then store the IdList somewhere (like + // in the TangibleManager, for example). + // + IdList GetNear(int64 id, double rx, double ry, double rz); }; diff --git a/Source/Integration/TangibleManager.cpp b/Source/Integration/TangibleManager.cpp index 6950625f..333f8962 100644 --- a/Source/Integration/TangibleManager.cpp +++ b/Source/Integration/TangibleManager.cpp @@ -5,9 +5,18 @@ using AActorPtr = AActor*; +FTangibleManager::FTangibleManager() { + World = nullptr; + ClassTangibleActor = nullptr; + Actor = 0; + Near = IdList(); +} + void FTangibleManager::Init(UWorld *world, UClass* tanact) { World = world; ClassTangibleActor = tanact; + Actor = 0; + Near = IdList(); } AActorPtr FTangibleManager::GetTangible(int64 id) { @@ -23,8 +32,8 @@ AActorPtr FTangibleManager::GetTangible(int64 id) { AActorPtr FTangibleManager::MakeTangible(int64 id) { AActorPtr& p = IdToActor.FindOrAdd(id); if (p == nullptr) { - FVector location; - FRotator rotation; + FVector location(0,0,0); + FRotator rotation(0, 0, 0); FActorSpawnParameters params; p = World->SpawnActor(ClassTangibleActor, &location, &rotation, params); check(p != nullptr); @@ -36,4 +45,3 @@ AActorPtr FTangibleManager::MakeTangible(int64 id) { void FTangibleManager::DeleteTangible(int64 id) { // IMPLEMENT ME } - diff --git a/Source/Integration/TangibleManager.h b/Source/Integration/TangibleManager.h index 6b358af5..4d89ad63 100644 --- a/Source/Integration/TangibleManager.h +++ b/Source/Integration/TangibleManager.h @@ -13,6 +13,8 @@ USTRUCT() struct INTEGRATION_API FTangibleManager { GENERATED_BODY() +public: + using IdList = TArrayView; public: // A pointer to the UWorld. @@ -25,8 +27,16 @@ public: // Given a tangible ID, look up actor pointer (or NULL if actor was deleted) UPROPERTY() TMap IdToActor; - + + // Actor tangible Id. + int64 Actor; + + // Tangibles near the actor. + IdList Near; + public: + FTangibleManager(); + // Initialize the tangible manager. // void Init(UWorld *world, UClass* tanact); @@ -39,4 +49,15 @@ public: // Delete the tangible. void DeleteTangible(int64 id); + + // Get/Set the Id of the actor. + // + int64 GetActor() const { return Actor; }; + void SetActor(int64 id) { Actor = id; } + + // Get/Set the list of tangibles near the player. + // + IdList GetNear() const { return Near; } + void SetNear(IdList near) { Near = near; } }; +