diff --git a/Source/Integration/IntegrationGameModeBase.cpp b/Source/Integration/IntegrationGameModeBase.cpp index cab1292e..51dc3a63 100644 --- a/Source/Integration/IntegrationGameModeBase.cpp +++ b/Source/Integration/IntegrationGameModeBase.cpp @@ -3,11 +3,12 @@ #include "IntegrationGameModeBase.h" #include "lpx-drvutil.hpp" #include "DebugPrint.h" -#include "Tangible.h" +#include "TangibleComponent.h" #include "TangibleManager.h" #include "TangibleInterface.h" #include "CommonTypes.h" #include "AnimQueue.h" +#include "IntegrationGameState.h" #include #include @@ -119,11 +120,13 @@ void AIntegrationGameModeBase::MaybeTriggerUpdateTask(float deltaseconds) { // FStructProperty* sprop = FindFProperty(uclass, nname); //} +#pragma optimize("", off) + void AIntegrationGameModeBase::UpdateTangibles() { if (!Playing) return; FlxLockedWrapper w(LockableWrapper); int64 actor = w.GetActor(); - TangibleManager->SetActor(actor); + TangibleManager->SetPlayer(actor); TangibleManager->SetNear(w.GetNear(actor, 100, 100, 100)); for (int64 id : TangibleManager->GetNear()) { TangibleManager->MakeTangible(id); @@ -133,19 +136,16 @@ void AIntegrationGameModeBase::UpdateTangibles() { StringViewVec aqueues = w.GetAnimationQueues(tanids); for (int i = 0; i < tanids.Num(); i++) { uint64_t tanid = tanids[i]; - std::string_view aqueue = aqueues[i]; - UlxTangible* t = TangibleManager->GetTangible(tanid); - check(t != nullptr); - t->AnimTracker.Update(aqueue); - + UTangibleComponent *t = TangibleManager->GetTangible(tanid); + t->AnimTracker.Update(aqueues[i]); TArray aborted = t->AnimTracker.GetAborted(); for (uint64 hash : aborted) { - IlxTangibleInterface::Execute_AbortAnimation(t->Actor, hash); + IlxTangibleInterface::Execute_AbortAnimation(t->GetActor(), hash); } FlxAnimationStep step; ElxAnimationMode mode = t->AnimTracker.GetNextStep(step); if (mode != ElxAnimationMode::INVALID) { - bool started = IlxTangibleInterface::Execute_StartAnimation(t->Actor, mode, step); + bool started = IlxTangibleInterface::Execute_StartAnimation(t->GetActor(), mode, step); if (started) { t->AnimTracker.StartedStep(step.Hash); } @@ -252,4 +252,16 @@ 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/IntegrationGameState.h b/Source/Integration/IntegrationGameState.h new file mode 100644 index 00000000..467cb881 --- /dev/null +++ b/Source/Integration/IntegrationGameState.h @@ -0,0 +1,7 @@ + +class UTangibleManager; + +namespace IntegrationGameState { + UTangibleManager* GetTangibleManager(AActor *actor); +} + diff --git a/Source/Integration/SampleActorComponent.cpp b/Source/Integration/SampleActorComponent.cpp new file mode 100644 index 00000000..b5142a32 --- /dev/null +++ b/Source/Integration/SampleActorComponent.cpp @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SampleActorComponent.h" + +// Sets default values for this component's properties +USampleActorComponent::USampleActorComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = true; + + // ... +} + + +// Called when the game starts +void USampleActorComponent::BeginPlay() +{ + Super::BeginPlay(); + + // ... + +} + + +// Called every frame +void USampleActorComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // ... +} + diff --git a/Source/Integration/SampleActorComponent.h b/Source/Integration/SampleActorComponent.h new file mode 100644 index 00000000..fe00ca06 --- /dev/null +++ b/Source/Integration/SampleActorComponent.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "SampleActorComponent.generated.h" + + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class INTEGRATION_API USampleActorComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + // Sets default values for this component's properties + USampleActorComponent(); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + +}; diff --git a/Source/Integration/Tangible.cpp b/Source/Integration/Tangible.cpp deleted file mode 100644 index 094c20c7..00000000 --- a/Source/Integration/Tangible.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "Tangible.h" - diff --git a/Source/Integration/Tangible.h b/Source/Integration/Tangible.h deleted file mode 100644 index 590d03b8..00000000 --- a/Source/Integration/Tangible.h +++ /dev/null @@ -1,31 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" -#include "UObject/NoExportTypes.h" -#include "AnimQueue.h" -#include "TangibleInterface.h" -#include "Tangible.generated.h" - -/** - * - */ -UCLASS() -class INTEGRATION_API UlxTangible : public UObject -{ - GENERATED_BODY() - -public: - UPROPERTY() - AActor* Actor; - - FlxAnimTracker AnimTracker; - - FString Plane; - - void Init(AActor* a, const FString &plane) { - Actor = a; - Plane = plane; - } -}; diff --git a/Source/Integration/TangibleComponent.cpp b/Source/Integration/TangibleComponent.cpp new file mode 100644 index 00000000..8a4f9210 --- /dev/null +++ b/Source/Integration/TangibleComponent.cpp @@ -0,0 +1,16 @@ +// 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; + Actor = a; + TangibleId = id; +} diff --git a/Source/Integration/TangibleComponent.h b/Source/Integration/TangibleComponent.h new file mode 100644 index 00000000..4a0a432d --- /dev/null +++ b/Source/Integration/TangibleComponent.h @@ -0,0 +1,56 @@ +// 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 Actor; + + // Our tangible Manager. + UPROPERTY() + TWeakObjectPtr TangibleManager; + + // Animation tracker + FlxAnimTracker AnimTracker; + + // Current Plane. + FString Plane; + + void Init(UTangibleManager* tm, AActor* a, int64 id); + + AActor* GetActor() const { return Actor.Get(); } +}; diff --git a/Source/Integration/TangibleInterface.h b/Source/Integration/TangibleInterface.h index 89f9c4e7..37a7f7cf 100644 --- a/Source/Integration/TangibleInterface.h +++ b/Source/Integration/TangibleInterface.h @@ -29,3 +29,5 @@ public: UFUNCTION(BlueprintImplementableEvent, Category = "Tangible Functionality") bool AbortAnimation(int64 hash); }; + + diff --git a/Source/Integration/TangibleManager.cpp b/Source/Integration/TangibleManager.cpp index 06a07c18..c98d58e3 100644 --- a/Source/Integration/TangibleManager.cpp +++ b/Source/Integration/TangibleManager.cpp @@ -3,6 +3,8 @@ #include "TangibleManager.h" #include "TangibleInterface.h" +#include "IntegrationGameState.h" +#include "TangibleComponent.h" #include "DebugPrint.h" using namespace DebugPrint; @@ -10,39 +12,51 @@ using namespace DebugPrint; UTangibleManager::UTangibleManager() { World = nullptr; ClassTangibleActor = nullptr; - Actor = 0; + Player = 0; Near = IdView(); } void UTangibleManager::Init(UWorld *world, UClass* tanact) { World = world; ClassTangibleActor = tanact; - Actor = 0; + Player = 0; Near = IdView(); } -UlxTangible *UTangibleManager::GetTangible(int64 id) { - UlxTangible **p = IdToTangible.Find(id); +UTangibleComponent *UTangibleManager::GetTangible(int64 id) { + AActor **p = IdToActor.Find(id); if (p == nullptr) { return nullptr; } else { - return *p; + AActor* a = *p; + UTangibleComponent* comp = a->FindComponentByClass(); + check(comp != nullptr); + return comp; } } -UlxTangible *UTangibleManager::MakeTangible(int64 id) { - UlxTangible *& p = IdToTangible.FindOrAdd(id); +UTangibleComponent *UTangibleManager::MakeTangible(int64 id) { + AActor *& p = IdToActor.FindOrAdd(id); if (p == nullptr) { - FVector location(0,0,0); - FRotator rotation(0, 0, 0); FActorSpawnParameters params; - AActor* a = World->SpawnActor(ClassTangibleActor, &location, &rotation, 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())); - p = NewObject(); - p->Init(a, TEXT("")); + // 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; } - return p; } void UTangibleManager::DeleteTangible(int64 id) { @@ -51,10 +65,10 @@ void UTangibleManager::DeleteTangible(int64 id) { UTangibleManager::IdArray UTangibleManager::GetLive() { IdArray result; - result.SetNum(IdToTangible.Num()); + result.SetNum(IdToActor.Num()); int next = 0; - for (auto &pair : IdToTangible) { + for (auto &pair : IdToActor) { result[next++] = pair.Key; } return result; -} \ No newline at end of file +} diff --git a/Source/Integration/TangibleManager.h b/Source/Integration/TangibleManager.h index 60f305b5..7e77b565 100644 --- a/Source/Integration/TangibleManager.h +++ b/Source/Integration/TangibleManager.h @@ -5,7 +5,7 @@ #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "CommonTypes.h" -#include "Tangible.h" +#include "TangibleComponent.h" #include "TangibleManager.generated.h" UCLASS() @@ -18,19 +18,21 @@ public: using IdArray = CommonTypes::IdArray; using IdView = CommonTypes::IdView; - // A pointer to the UWorld. - UWorld* World; + // A pointer to our world. + UPROPERTY() + TWeakObjectPtr World; - // A pointer to uclass TangibleActor. + // A pointer to uclass TangibleActor. This is the class + // of actors that we create (for now). UPROPERTY() TSubclassOf ClassTangibleActor; // Given a tangible ID, look up actor pointer (or NULL if actor was deleted) UPROPERTY() - TMap IdToTangible; + TMap IdToActor; - // Actor tangible Id. - int64 Actor; + // Player's tangible Id. + int64 Player; // Tangibles near the actor. IdView Near; @@ -42,19 +44,23 @@ public: // void Init(UWorld *world, UClass* tanact); + // Get a pointer to our world. + // + UWorld* GetWorld() const override { return World.Get(); } + // Get the tangible if it exists, otherwise return NULL - UlxTangible* GetTangible(int64 id); + UTangibleComponent* GetTangible(int64 id); // Get the tangible if it exists, otherwise create it. - UlxTangible* MakeTangible(int64 id); + UTangibleComponent* MakeTangible(int64 id); // 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; } + int64 GetPlayer() const { return Player; }; + void SetPlayer(int64 id) { Player = id; } // Get/Set the list of tangibles near the player, according to Luprex. //