// Fill out your copyright notice in the Description page of Project Settings. #include "Tangible.h" #include "TangibleManager.h" UlxTangible::UlxTangible() { Manager = nullptr; TangibleId = -1; CurrentActor = nullptr; ActorBlueprint = nullptr; NearAccordingToLuprex = false; NearAccordingToUnreal = false; } 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; } } void UlxTangible::UpdateAnimationQueue(std::string_view aq) { AnimTracker.Update(aq); int limit = 3; while (AnimTracker.IsChanged()) { if (limit == 0) break; limit -= 1; AnimTracker.ClearChanged(); IlxTangibleInterface::Execute_AnimationStateChanged(GetActor()); } } FVector UlxTangible::GetLocation() const { if (CurrentActor == nullptr) { return FVector(0,0,0); } else { return CurrentActor->GetActorLocation(); } } void UlxTangible::Destroy() { SetActorBlueprintClass(nullptr); Manager = nullptr; TangibleId = -1; CurrentActor = nullptr; ActorBlueprint = nullptr; AnimTracker.Clear(); NearAccordingToLuprex = false; NearAccordingToUnreal = false; } static UlxTangible *GetActorTangible(AActor *actor) { UlxTangibleComponent* comp = actor->GetComponentByClass(); 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); }