diff --git a/Content/TangibleActor.uasset b/Content/TangibleActor.uasset index 80484671..a13f4cdd 100644 --- a/Content/TangibleActor.uasset +++ b/Content/TangibleActor.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84fc90f15eb6e91880d390067a96949e0bd7990a8f90bb469049ddc505a07926 -size 142745 +oid sha256:05b62c5757100adf5d29b718f75d9f540e11267ca0aa8e03cd33d2676fea9b91 +size 142754 diff --git a/Source/Integration/IntegrationGameModeBase.cpp b/Source/Integration/IntegrationGameModeBase.cpp index 51dc3a63..04dfc472 100644 --- a/Source/Integration/IntegrationGameModeBase.cpp +++ b/Source/Integration/IntegrationGameModeBase.cpp @@ -3,12 +3,10 @@ #include "IntegrationGameModeBase.h" #include "lpx-drvutil.hpp" #include "DebugPrint.h" -#include "TangibleComponent.h" +#include "Tangible.h" #include "TangibleManager.h" -#include "TangibleInterface.h" #include "CommonTypes.h" #include "AnimQueue.h" -#include "IntegrationGameState.h" #include #include @@ -17,7 +15,7 @@ using namespace CommonTypes; AIntegrationGameModeBase::AIntegrationGameModeBase() { - TangibleManager = NewObject(); + TangibleManager = NewObject(); EngineSeconds = 0.0; NextThreadTrigger = 1.0; //PrimaryActorTick.bCanEverTick = true; // Probably wrong @@ -127,8 +125,9 @@ void AIntegrationGameModeBase::UpdateTangibles() { FlxLockedWrapper w(LockableWrapper); int64 actor = w.GetActor(); TangibleManager->SetPlayer(actor); - TangibleManager->SetNear(w.GetNear(actor, 100, 100, 100)); - for (int64 id : TangibleManager->GetNear()) { + IdView near = w.GetNear(actor, 100, 100, 100); + TangibleManager->SetNear(near); + for (int64 id : near) { TangibleManager->MakeTangible(id); } // Update animation queues of live tangibles. @@ -136,7 +135,7 @@ void AIntegrationGameModeBase::UpdateTangibles() { StringViewVec aqueues = w.GetAnimationQueues(tanids); for (int i = 0; i < tanids.Num(); i++) { uint64_t tanid = tanids[i]; - UTangibleComponent *t = TangibleManager->GetTangible(tanid); + UlxTangible *t = TangibleManager->GetTangible(tanid); t->AnimTracker.Update(aqueues[i]); TArray aborted = t->AnimTracker.GetAborted(); for (uint64 hash : aborted) { @@ -243,7 +242,7 @@ void AIntegrationGameModeBase::BeginPlay() } // Initialize the tangible manager. - TangibleManager = NewObject(); + TangibleManager = NewObject(); TangibleManager->Init(GetWorld(), ClassTangibleActor); } @@ -252,16 +251,3 @@ void AIntegrationGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) ResetToInitialState(); } -namespace IntegrationGameState { - - UTangibleManager* GetTangibleManager(AActor *actor) { - AGameModeBase* gmb = actor->GetWorld()->GetAuthGameMode(); - AIntegrationGameModeBase* igmb = Cast(gmb); - if (igmb == nullptr) { - return nullptr; - } else { - return igmb->TangibleManager; - } - } - -} // namespace IntegrationGameState diff --git a/Source/Integration/IntegrationGameModeBase.h b/Source/Integration/IntegrationGameModeBase.h index b6ec9d0f..da155315 100644 --- a/Source/Integration/IntegrationGameModeBase.h +++ b/Source/Integration/IntegrationGameModeBase.h @@ -57,7 +57,7 @@ public: virtual uint32 Run() override; UPROPERTY() - UTangibleManager *TangibleManager; + UlxTangibleManager *TangibleManager; // This stores the entire text currently visible in the console. FlxConsoleOutput ConsoleOutput; diff --git a/Source/Integration/IntegrationGameState.h b/Source/Integration/IntegrationGameState.h deleted file mode 100644 index 467cb881..00000000 --- a/Source/Integration/IntegrationGameState.h +++ /dev/null @@ -1,7 +0,0 @@ - -class UTangibleManager; - -namespace IntegrationGameState { - UTangibleManager* GetTangibleManager(AActor *actor); -} - diff --git a/Source/Integration/Tangible.cpp b/Source/Integration/Tangible.cpp new file mode 100644 index 00000000..c12838c9 --- /dev/null +++ b/Source/Integration/Tangible.cpp @@ -0,0 +1,81 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Tangible.h" +#include "TangibleManager.h" + +UlxTangible::UlxTangible() +{ +} + +void UlxTangible::Init(UlxTangibleManager* tm, int64 id) +{ + Manager = tm; + TangibleId = id; +} + +bool UlxTangible::BlueprintIsTangible(TSubclassOf bp) { + if (bp == nullptr) return true; + return bp->ImplementsInterface(UlxTangibleInterface::StaticClass()); +} + +void UlxTangible::SetActorBlueprintClass(TSubclassOf bp) { + // If we're already of the right class, do nothing. + if (ActorBlueprint == bp) { + return; + } + + // Sanity check the blueprint. Nullptr is allowed. + check(BlueprintIsTangible(bp)); + + // 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(); + } + + // Update the blueprint reference. + ActorBlueprint = bp; + + // Now create a new actor, unless the BP is nullptr. + if (ActorBlueprint != nullptr) { + // Create the actor. + FActorSpawnParameters params; + FVector location(0, 0, 0); + FRotator rotation(0, 0, 0); + UWorld* w = Manager->GetWorld(); + AActor* a = w->SpawnActor(ActorBlueprint, &location, &rotation, params); + + // Insert a TangibleComponent into the actor. + UActorComponent* ac = a->AddComponentByClass(UlxTangibleComponent::StaticClass(), false, FTransform::Identity, false); + UlxTangibleComponent* tc = Cast(ac); + check(tc != nullptr); + + // Make the tangible point to the actor and vice versa. + tc->Tangible = this; + CurrentActor = a; + } +} + +FString UlxTangible::GetTangiblePlane(AActor* actor) { + UlxTangibleComponent* comp = actor->GetComponentByClass(); + check(comp != nullptr); + return comp->Tangible->Plane; +} + +void UlxTangible::SetTangiblePlane(AActor* actor, const FString& plane) { + UlxTangibleComponent* comp = actor->GetComponentByClass(); + check(comp != nullptr); + comp->Tangible->Plane = plane; +} + diff --git a/Source/Integration/Tangible.h b/Source/Integration/Tangible.h new file mode 100644 index 00000000..5d5d4cbe --- /dev/null +++ b/Source/Integration/Tangible.h @@ -0,0 +1,139 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "AnimQueue.h" +#include "Tangible.generated.h" + + +class UlxTangibleManager; + +// This class does not need to be modified. +UINTERFACE(Blueprintable) +class UlxTangibleInterface : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + * IlxTangibleInterface + * + * This class implements the interface that an Actor must implement + * in order for that Actor to be usable as a Tangible. + * + */ + +class INTEGRATION_API IlxTangibleInterface +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + UFUNCTION(BlueprintImplementableEvent, Category = "Tangible Functionality") + bool StartAnimation(ElxAnimationMode mode, const FlxAnimationStep& step); + + UFUNCTION(BlueprintImplementableEvent, Category = "Tangible Functionality") + bool AbortAnimation(int64 hash); +}; + + + + +/** + * + * UlxTangible + * + * The Tangible stores all the data we need for a tangible, + * such as the animation queue and so forth. + * + * From time to time, a tangible can change its blueprint class. + * To do that, we have to delete and recreate the actor. This + * is all set up so that it is possible to do that. + * + * The tangible has a place to store an Actor pointer. This + * actor pointer is allowed to be nullptr, especially in the + * case that the blueprint hasn't been set yet. + * + * This also serves as a repository for blueprint functions + * that operate on tangible actors. + * + */ + +UCLASS() +class INTEGRATION_API UlxTangible : public UObject +{ + GENERATED_BODY() + +public: + UlxTangible(); + + // My Tangible Manager. + UPROPERTY() + TObjectPtr Manager; + + // The tangible ID. + UPROPERTY() + uint64 TangibleId; + + UPROPERTY() + TWeakObjectPtr CurrentActor; + + // The blueprint class of the actor. + UPROPERTY() + TSubclassOf ActorBlueprint; + + // Animation tracker + FlxAnimTracker AnimTracker; + + // Current Plane. + FString Plane; + + // True if luprex thinks this object is Near the player. + bool NearAccordingToLuprex; + +public: + void Init(UlxTangibleManager *tm, int64 id); + + static bool BlueprintIsTangible(TSubclassOf bp); + + void SetActorBlueprintClass(TSubclassOf bp); + + AActor* GetActor() const { return CurrentActor.Get(); } + +public: + UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = Luprex) + static FString GetTangiblePlane(AActor* target); + + UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = Luprex) + static void SetTangiblePlane(AActor* target, const FString& plane); +}; + + +/** + * + * UlxTangibleComponent + * + * The TangibleComponent holds a pointer to the Tangible. + * This is the only purpose it serves: to make it possible to + * have the Actor point to its corresponding Tangible. + * + * The TangibleComponent is procedurally inserted into the Actor. + * The TangibleComponent is not visible to blueprints. + * + */ + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class INTEGRATION_API UlxTangibleComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + UlxTangibleComponent() : Tangible(nullptr) {} + + // The actor that we're a part of. + UPROPERTY() + TWeakObjectPtr Tangible; +}; diff --git a/Source/Integration/TangibleComponent.cpp b/Source/Integration/TangibleComponent.cpp deleted file mode 100644 index c6b70c6b..00000000 --- a/Source/Integration/TangibleComponent.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "TangibleComponent.h" -#include "TangibleManager.h" - -UTangibleComponent::UTangibleComponent() -{ -} - -void UTangibleComponent::Init(UTangibleManager* tm, AActor* a, int64 id) -{ - TangibleManager = tm; - OwningActor = a; - TangibleId = id; -} - -FString UTangibleComponent::GetTangiblePlane(AActor* actor) { - UTangibleComponent* comp = actor->GetComponentByClass(); - check(comp != nullptr); - return comp->Plane; -} - -void UTangibleComponent::SetTangiblePlane(AActor* actor, const FString& plane) { - UTangibleComponent* comp = actor->GetComponentByClass(); - check(comp != nullptr); - comp->Plane = plane; -} - diff --git a/Source/Integration/TangibleComponent.h b/Source/Integration/TangibleComponent.h deleted file mode 100644 index c2bfd6d1..00000000 --- a/Source/Integration/TangibleComponent.h +++ /dev/null @@ -1,64 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" -#include "Components/ActorComponent.h" -#include "AnimQueue.h" -#include "TangibleComponent.generated.h" - -/* - * TangibleComponent - * - * The TangibleManager procedurally injects a TangibleComponent - * into the actor. This gives us a place to store tangible-specific - * actor properties, such as the tangible Id, the animation queue, - * and so forth. - * - * To cooperate the with the garbage collector, don't store pointers - * to TangibleComponents in data structures. Instead, store a pointer - * to the actor and then use GetComponentByClass to retrieve the - * TangibleComponent on demand. - * - */ - -class UTangibleManager; - -UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) -class INTEGRATION_API UTangibleComponent : public UActorComponent -{ - GENERATED_BODY() - -public: - UTangibleComponent(); - - // The tangible ID. - UPROPERTY() - uint64 TangibleId; - - // The actor that we're a part of. - UPROPERTY() - TWeakObjectPtr OwningActor; - - // Our tangible Manager. - UPROPERTY() - TWeakObjectPtr TangibleManager; - - // Animation tracker - FlxAnimTracker AnimTracker; - - // Current Plane. - FString Plane; - -public: - void Init(UTangibleManager* tm, AActor* a, int64 id); - - AActor* GetActor() const { return OwningActor.Get(); } - -public: - UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = Luprex) - static FString GetTangiblePlane(AActor* target); - - UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = Luprex) - static void SetTangiblePlane(AActor* target, const FString& plane); -}; diff --git a/Source/Integration/TangibleInterface.cpp b/Source/Integration/TangibleInterface.cpp deleted file mode 100644 index ae86e205..00000000 --- a/Source/Integration/TangibleInterface.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "TangibleInterface.h" - -// Add default functionality here for any IlxTangibleInterface functions that are not pure virtual. diff --git a/Source/Integration/TangibleInterface.h b/Source/Integration/TangibleInterface.h deleted file mode 100644 index 37a7f7cf..00000000 --- a/Source/Integration/TangibleInterface.h +++ /dev/null @@ -1,33 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" -#include "UObject/Interface.h" -#include "AnimQueue.h" -#include "TangibleInterface.generated.h" - -// This class does not need to be modified. -UINTERFACE(Blueprintable) -class UlxTangibleInterface : public UInterface -{ - GENERATED_BODY() -}; - -/** - * - */ -class INTEGRATION_API IlxTangibleInterface -{ - GENERATED_BODY() - - // Add interface functions to this class. This is the class that will be inherited to implement this interface. -public: - UFUNCTION(BlueprintImplementableEvent, Category = "Tangible Functionality") - bool StartAnimation(ElxAnimationMode mode, const FlxAnimationStep& step); - - UFUNCTION(BlueprintImplementableEvent, Category = "Tangible Functionality") - bool AbortAnimation(int64 hash); -}; - - diff --git a/Source/Integration/TangibleManager.cpp b/Source/Integration/TangibleManager.cpp index c98d58e3..30c4ff1e 100644 --- a/Source/Integration/TangibleManager.cpp +++ b/Source/Integration/TangibleManager.cpp @@ -2,73 +2,60 @@ #include "TangibleManager.h" -#include "TangibleInterface.h" -#include "IntegrationGameState.h" -#include "TangibleComponent.h" +#include "Tangible.h" #include "DebugPrint.h" using namespace DebugPrint; -UTangibleManager::UTangibleManager() { +UlxTangibleManager::UlxTangibleManager() { World = nullptr; ClassTangibleActor = nullptr; Player = 0; Near = IdView(); } -void UTangibleManager::Init(UWorld *world, UClass* tanact) { +void UlxTangibleManager::Init(UWorld* world, UClass* tanact) { World = world; ClassTangibleActor = tanact; Player = 0; Near = IdView(); } -UTangibleComponent *UTangibleManager::GetTangible(int64 id) { - AActor **p = IdToActor.Find(id); +UlxTangible* UlxTangibleManager::GetTangible(int64 id) { + UlxTangible** p = IdToTangible.Find(id); if (p == nullptr) { return nullptr; - } else { - AActor* a = *p; - UTangibleComponent* comp = a->FindComponentByClass(); - check(comp != nullptr); - return comp; + } + else { + return *p; } } -UTangibleComponent *UTangibleManager::MakeTangible(int64 id) { - AActor *& p = IdToActor.FindOrAdd(id); - if (p == nullptr) { - FActorSpawnParameters params; - FVector location(0, 0, 0); - FRotator rotation(0, 0, 0); - UWorld* w = GetWorld(); - AActor* a = w->SpawnActor(ClassTangibleActor, &location, &rotation, params); - check(a != nullptr); - check(a->GetClass()->ImplementsInterface(UlxTangibleInterface::StaticClass())); - // Insert a TangibleComponent into the actor. - UActorComponent* ac = a->AddComponentByClass(UTangibleComponent::StaticClass(), false, FTransform::Identity, false); - UTangibleComponent* tc = Cast(ac); - check(tc != nullptr); - tc->Init(this, a, id); - p = a; - return tc; - } else { - UTangibleComponent* comp = p->FindComponentByClass(); - check(comp != nullptr); - return comp; +UlxTangible* UlxTangibleManager::MakeTangible(int64 id) { + UlxTangible*& t = IdToTangible.FindOrAdd(id); + if (t == nullptr) { + t = NewObject(); + t->Init(this, id); + + // TODO: fix this. The blueprint needs to be assigned + // during animation queue parsing, based on the animation + // queue keyword 'bp'. + t->SetActorBlueprintClass(ClassTangibleActor); } + return t; } -void UTangibleManager::DeleteTangible(int64 id) { +void UlxTangibleManager::DeleteTangible(int64 id) { // IMPLEMENT ME } -UTangibleManager::IdArray UTangibleManager::GetLive() { +UlxTangibleManager::IdArray UlxTangibleManager::GetLive() { IdArray result; - result.SetNum(IdToActor.Num()); + result.SetNum(IdToTangible.Num()); int next = 0; - for (auto &pair : IdToActor) { + for (auto& pair : IdToTangible) { result[next++] = pair.Key; } return result; } + diff --git a/Source/Integration/TangibleManager.h b/Source/Integration/TangibleManager.h index 7e77b565..4a307540 100644 --- a/Source/Integration/TangibleManager.h +++ b/Source/Integration/TangibleManager.h @@ -5,11 +5,11 @@ #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "CommonTypes.h" -#include "TangibleComponent.h" +#include "Tangible.h" #include "TangibleManager.generated.h" UCLASS() -class INTEGRATION_API UTangibleManager : public UObject +class INTEGRATION_API UlxTangibleManager : public UObject { GENERATED_BODY() @@ -27,9 +27,9 @@ public: UPROPERTY() TSubclassOf ClassTangibleActor; - // Given a tangible ID, look up actor pointer (or NULL if actor was deleted) + // Given a tangible ID, look up the TangibleComponent of that actor. UPROPERTY() - TMap IdToActor; + TMap IdToTangible; // Player's tangible Id. int64 Player; @@ -38,7 +38,7 @@ public: IdView Near; public: - UTangibleManager(); + UlxTangibleManager(); // Initialize the tangible manager. // @@ -49,10 +49,10 @@ public: UWorld* GetWorld() const override { return World.Get(); } // Get the tangible if it exists, otherwise return NULL - UTangibleComponent* GetTangible(int64 id); + UlxTangible* GetTangible(int64 id); // Get the tangible if it exists, otherwise create it. - UTangibleComponent* MakeTangible(int64 id); + UlxTangible* MakeTangible(int64 id); // Delete the tangible. void DeleteTangible(int64 id);