// Fill out your copyright notice in the Description page of Project Settings. #include "TangibleManager.h" #include "Tangible.h" #include "DebugPrint.h" #include "IntegrationGameModeBase.h" using namespace DebugPrint; using TanArray = UlxTangibleManager::TanArray; using IdArray = UlxTangibleManager::IdArray; UFunction *UlxTangibleManager::GetAnimationQueueChanged(UClass *uclass) { UFunction *result = uclass->FindFunctionByName(FName(TEXT("Animation Queue Changed"))); if (result == nullptr) return nullptr; if (result->ParmsSize != 0) return nullptr; return result; } UClass *UlxTangibleManager::GetTangibleClass(const FString &name) { if (name.IsEmpty()) { return nullptr; } if (name == TEXT("unknown")) { return nullptr; } FString path(TEXT("/Game/Tangibles/")); path += name; path += TCHAR('.'); path += name; path += TCHAR('_'); path += TCHAR('C'); UClass *result = LoadObject(nullptr, *path); if (result == nullptr) { UE_LOG(LogBlueprint, Error, TEXT("No such UClass: %s"), *path); return nullptr; } if (!result->IsChildOf(AActor::StaticClass())) { UE_LOG(LogBlueprint, Error, TEXT("UClass is not an actor: %s"), *path); return nullptr; } UFunction *aqchanged = GetAnimationQueueChanged(result); if (aqchanged == nullptr) { UE_LOG(LogBlueprint, Error, TEXT("UClass does not have 'Animation Queue Changed' function: %s"), *path); return nullptr; } return result; } UlxTangibleManager::UlxTangibleManager() { World = nullptr; PossessedTangible = nullptr; } void UlxTangibleManager::Init(UWorld* world, AIntegrationGameModeBase *gamemode) { World = world; GameMode = gamemode; } UlxTangible* UlxTangibleManager::GetTangible(int64 id) const { UlxTangible*const* p = IdToTangible.Find(id); if (p == nullptr) { return nullptr; } else { return *p; } } #pragma optimize("", off) UlxTangible* UlxTangibleManager::MakeTangible(int64 id) { check(id > 0); UlxTangible*& t = IdToTangible.FindOrAdd(id); if (t == nullptr) { t = NewObject(); t->Init(this, id); } return t; } void UlxTangibleManager::DeleteTangible(int64 id) { // IMPLEMENT ME } TanArray UlxTangibleManager::GetAllTangibles() const { TanArray result; result.SetNum(IdToTangible.Num()); int next = 0; for (auto& pair : IdToTangible) { result[next++] = pair.Value; } return result; } #pragma optimize("", off) void UlxTangibleManager::UpdateNearAccordingToLuprex(IdView near) { // Clear all the 'NearAccordingToLuprex' flags. for (const auto& pair : IdToTangible) { pair.Value->NearAccordingToLuprex = false; } // For every ID on the list, create it if it doesn't exist, // mark it, and return it. for (int64 id : near) { UlxTangible* tan = MakeTangible(id); tan->NearAccordingToLuprex = true; } } #pragma optimize("", off) void UlxTangibleManager::RecalcNearAccordingToUnreal(int64 player, double radius) { UlxTangible *p = GetTangible(player); check (p != nullptr); FVector playerpos = p->CurrentActor->GetActorLocation(); FName playerplane = p->Plane; double radiussq = radius * radius; for (const auto& pair : IdToTangible) { UlxTangible *tan = pair.Value; if (tan->Plane != playerplane) { tan->NearAccordingToUnreal = false; } else { FVector pos = tan->GetLocation(); double distsq = FVector::DistSquared(pos, playerpos); tan->NearAccordingToUnreal = (distsq <= radiussq); } } } void UlxTangibleManager::DeleteFarawayTangibles() { // Make a list of tangibles that need to be deleted. TanArray faraway; for (const auto& pair : IdToTangible) { UlxTangible *tan = pair.Value; if (!(tan->NearAccordingToLuprex || tan->NearAccordingToUnreal)) { faraway.Add(tan); } } for (UlxTangible *tan : faraway) { IdToTangible.Remove(tan->TangibleId); tan->Destroy(); // Remove the actor from the scene. } } IdArray UlxTangibleManager::GetIds(const TanArray &arr) { IdArray result; result.SetNum(arr.Num()); for (int i = 0; i < arr.Num(); i++) { result[i] = arr[i]->TangibleId; } return result; }