Files
integration/Source/Integration/Tangible.cpp

140 lines
4.0 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "Tangible.h"
#include "TangibleManager.h"
#define DEFAULT_BLUEPRINT (TEXT("TangibleStaticMesh"))
UlxTangible::UlxTangible()
{
Manager = nullptr;
TangibleId = -1;
CurrentActor = nullptr;
ActorBlueprintName = TEXT("");
NearAccordingToLuprex = false;
NearAccordingToUnreal = false;
}
void UlxTangible::Init(UlxTangibleManager* tm, int64 id)
{
Manager = tm;
TangibleId = id;
}
void UlxTangible::SetActorBlueprint(const FString &name) {
// If we're already of the right class, do nothing.
if (ActorBlueprintName == name) {
return;
}
// Get the blueprint.
// If the blueprint doesn't exist, or doesn't implement
// TangibleInterface, then use the fallback blueprint.
UClass *blueprint = Manager->GetTangibleClass(name);
if ((!name.IsEmpty()) && (blueprint == nullptr)) {
blueprint = Manager->GetTangibleClass(DEFAULT_BLUEPRINT);
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<UlxTangibleComponent>();
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 name
ActorBlueprintName = name;
// Now create a new actor, unless the BP is nullptr.
if (blueprint != nullptr) {
// Create the actor.
FActorSpawnParameters params;
FVector location(0, 0, 0);
FRotator rotation(0, 0, 0);
UWorld* w = Manager->GetWorld();
AActor* a = w->SpawnActor(blueprint, &location, &rotation, params);
// Insert a TangibleComponent into the actor.
UActorComponent* ac = a->AddComponentByClass(UlxTangibleComponent::StaticClass(), false, FTransform::Identity, false);
UlxTangibleComponent* tc = Cast<UlxTangibleComponent>(ac);
check(tc != nullptr);
// Make the tangible point to the actor and vice versa.
tc->Tangible = this;
CurrentActor = a;
}
}
void UlxTangible::UpdateAnimationQueue(std::string_view aq) {
AnimTracker.Update(aq);
int limit = 3;
while (AnimTracker.IsChanged()) {
if (limit == 0) break;
limit -= 1;
AnimTracker.ClearChanged();
FString blueprint = AnimTracker.GetCurrentBlueprintName();
if (blueprint.IsEmpty()) blueprint = DEFAULT_BLUEPRINT;
SetActorBlueprint(blueprint);
IlxTangibleInterface::Execute_AnimationStateChanged(GetActor());
}
}
FVector UlxTangible::GetLocation() const {
if (CurrentActor == nullptr) {
return FVector(0,0,0);
} else {
return CurrentActor->GetActorLocation();
}
}
void UlxTangible::Destroy() {
SetActorBlueprint("");
Manager = nullptr;
TangibleId = -1;
CurrentActor = nullptr;
ActorBlueprintName = "";
AnimTracker.Clear();
NearAccordingToLuprex = false;
NearAccordingToUnreal = false;
}
static UlxTangible *GetActorTangible(AActor *actor) {
UlxTangibleComponent* comp = actor->GetComponentByClass<UlxTangibleComponent>();
check(comp != nullptr);
UlxTangible *result = comp->Tangible.Get();
check(result != nullptr);
return result;
}
void UlxTangible::GetCurrentAnimation(AActor *target, FlxAnimationStep &step) {
step = GetActorTangible(target)->AnimTracker.GetCurrentAnimation();
}
void UlxTangible::FinishedAnimation(AActor *target, const FlxAnimationStep &step, bool autoxyz, bool autofacing, bool autoplane) {
UlxTangible *tan = GetActorTangible(target);
if (autoxyz) step.AutoUpdateXYZ(target);
if (autofacing) step.AutoUpdateFacing(target);
if (autoplane) step.AutoUpdatePlane(&(tan->Plane));
tan->AnimTracker.FinishedAnimation(step.Hash);
}
FString UlxTangible::GetTangiblePlane(AActor* target) {
return GetActorTangible(target)->Plane.ToString();
}
void UlxTangible::SetTangiblePlane(AActor* target, const FString& plane) {
GetActorTangible(target)->Plane = FName(plane);
}