Tangible creation and destruction in place
This commit is contained in:
@@ -210,8 +210,11 @@ FString FlxAnimQueueDecoder::DebugString(std::string_view queue) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FlxAnimTracker::FlxAnimTracker() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void FlxAnimTracker::Clear() {
|
||||
AQ.Empty();
|
||||
FirstSeqno = 0;
|
||||
HashToSeqno.Empty();
|
||||
|
||||
@@ -279,6 +279,10 @@ public:
|
||||
//
|
||||
FlxAnimTracker();
|
||||
|
||||
// Clear everything, reset to the initial state.
|
||||
//
|
||||
void Clear();
|
||||
|
||||
// Update from the specified animation queue.
|
||||
//
|
||||
// After the update is done, AQ will be a copy
|
||||
|
||||
@@ -109,42 +109,26 @@ void AIntegrationGameModeBase::MaybeTriggerUpdateTask(float deltaseconds) {
|
||||
}
|
||||
}
|
||||
|
||||
//#pragma optimize( "", off )
|
||||
//void SetLocal(UObject* obj, const char *name, int value) {
|
||||
// FString sname((const UTF8CHAR *)name);
|
||||
// FName nname(sname);
|
||||
// UClass* uclass = obj->GetClass();
|
||||
// FProperty* fprop = FindFProperty<FProperty>(uclass, nname);
|
||||
// FStructProperty* sprop = FindFProperty<FStructProperty>(uclass, nname);
|
||||
//}
|
||||
|
||||
|
||||
#pragma optimize("", off)
|
||||
|
||||
void AIntegrationGameModeBase::UpdateTangibles() {
|
||||
double radius = 1000.0; // Hardwired for now.
|
||||
using TanArray = UlxTangibleManager::TanArray;
|
||||
if (!Playing) return;
|
||||
FlxLockedWrapper w(LockableWrapper);
|
||||
int64 player = w.GetActor();
|
||||
TangibleManager->UpdateNear(w.GetNear(player, 100, 100, 100));
|
||||
IdView nearids = w.GetNear(player, radius, radius, radius);
|
||||
TangibleManager->UpdateNearAccordingToLuprex(nearids);
|
||||
TanArray alltans = TangibleManager->GetAllTangibles();
|
||||
IdArray allids = TangibleManager->GetIds(alltans);
|
||||
StringViewVec allqueues = w.GetAnimationQueues(allids);
|
||||
for (int i = 0; i < alltans.Num(); i++) {
|
||||
UlxTangible *t = alltans[i];
|
||||
t->AnimTracker.Update(allqueues[i]);
|
||||
TArray<uint64> aborted = t->AnimTracker.GetAborted();
|
||||
for (uint64 hash : aborted) {
|
||||
IlxTangibleInterface::Execute_AbortAnimation(t->GetActor(), hash);
|
||||
}
|
||||
FlxAnimationStep step;
|
||||
ElxAnimationMode mode = t->AnimTracker.GetNextStep(step);
|
||||
if (mode != ElxAnimationMode::INVALID) {
|
||||
bool started = IlxTangibleInterface::Execute_StartAnimation(t->GetActor(), mode, step);
|
||||
if (started) {
|
||||
t->AnimTracker.StartedStep(step.Hash);
|
||||
}
|
||||
}
|
||||
alltans[i]->UpdateAnimationQueue(allqueues[i]);
|
||||
}
|
||||
TangibleManager->RecalcNearAccordingToUnreal(player, radius);
|
||||
TangibleManager->DeleteFarawayTangibles();
|
||||
}
|
||||
|
||||
void AIntegrationGameModeBase::ConsoleSendInput(const FString& fs)
|
||||
|
||||
@@ -6,8 +6,12 @@
|
||||
|
||||
UlxTangible::UlxTangible()
|
||||
{
|
||||
Manager = nullptr;
|
||||
TangibleId = -1;
|
||||
CurrentActor = nullptr;
|
||||
ActorBlueprint = nullptr;
|
||||
NearAccordingToLuprex = false;
|
||||
NearAccordingToUnreal = false;
|
||||
}
|
||||
|
||||
void UlxTangible::Init(UlxTangibleManager* tm, int64 id)
|
||||
@@ -69,15 +73,50 @@ void UlxTangible::SetActorBlueprintClass(TSubclassOf<AActor> bp) {
|
||||
}
|
||||
}
|
||||
|
||||
void UlxTangible::UpdateAnimationQueue(std::string_view aq) {
|
||||
AnimTracker.Update(aq);
|
||||
TArray<uint64> aborted = AnimTracker.GetAborted();
|
||||
for (uint64 hash : aborted) {
|
||||
IlxTangibleInterface::Execute_AbortAnimation(GetActor(), hash);
|
||||
}
|
||||
FlxAnimationStep step;
|
||||
ElxAnimationMode mode = AnimTracker.GetNextStep(step);
|
||||
if (mode != ElxAnimationMode::INVALID) {
|
||||
bool started = IlxTangibleInterface::Execute_StartAnimation(GetActor(), mode, step);
|
||||
if (started) {
|
||||
AnimTracker.StartedStep(step.Hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
FString UlxTangible::GetTangiblePlane(AActor* actor) {
|
||||
UlxTangibleComponent* comp = actor->GetComponentByClass<UlxTangibleComponent>();
|
||||
check(comp != nullptr);
|
||||
return comp->Tangible->Plane;
|
||||
return comp->Tangible->Plane.ToString();
|
||||
}
|
||||
|
||||
void UlxTangible::SetTangiblePlane(AActor* actor, const FString& plane) {
|
||||
UlxTangibleComponent* comp = actor->GetComponentByClass<UlxTangibleComponent>();
|
||||
check(comp != nullptr);
|
||||
comp->Tangible->Plane = plane;
|
||||
comp->Tangible->Plane = FName(plane);
|
||||
}
|
||||
|
||||
|
||||
@@ -89,19 +89,83 @@ public:
|
||||
FlxAnimTracker AnimTracker;
|
||||
|
||||
// Current Plane.
|
||||
FString Plane;
|
||||
FName Plane;
|
||||
|
||||
// True if luprex thinks this object is Near the player.
|
||||
bool NearAccordingToLuprex;
|
||||
|
||||
// True if unreal thinks this object is Near the player.
|
||||
bool NearAccordingToUnreal;
|
||||
|
||||
public:
|
||||
// Initialize a new tangible.
|
||||
//
|
||||
// This links the tangible to its TangibleManager and
|
||||
// sets the tangible's ID.
|
||||
//
|
||||
void Init(UlxTangibleManager *tm, int64 id);
|
||||
|
||||
// Destroy a tangible.
|
||||
//
|
||||
// Delete the actor associated with the tangible, if any,
|
||||
// and clean up everything else.
|
||||
//
|
||||
void Destroy();
|
||||
|
||||
// Get the actor associated with this tangible.
|
||||
//
|
||||
// Note that this may return nullptr: it is valid for a
|
||||
// tangible to have no actor associated with it. This
|
||||
// is most commonly the case if the blueprint class of
|
||||
// the tangible is set to nullptr.
|
||||
//
|
||||
// Also bear in mind that if a tangible changes its blueprint
|
||||
// class, then the actor will have to be deleted and
|
||||
// recreated. In that case, GetActor will return a different
|
||||
// pointer than before the blueprint change.
|
||||
//
|
||||
AActor* GetActor() const { return CurrentActor.Get(); }
|
||||
|
||||
// Get the location of the tangible.
|
||||
//
|
||||
// Note that if the actor is nullptr, the location is always
|
||||
// at the origin.
|
||||
//
|
||||
FVector GetLocation() const;
|
||||
|
||||
// Check a blueprint class to see if it is valid as a Tangible.
|
||||
//
|
||||
// In order for a blueprint class to be used as a tangible,
|
||||
// it must implement the interface IlxTangibleInterface.
|
||||
// This function also returns true for nullptr.
|
||||
//
|
||||
static bool BlueprintIsTangible(TSubclassOf<AActor> bp);
|
||||
|
||||
// Change the blueprint class of the tangible.
|
||||
//
|
||||
// This requires the deletion and recreation of the Actor.
|
||||
// The blueprint class must satisfy 'BlueprintIsTangible' above.
|
||||
//
|
||||
// It is legal to pass in nullptr for the blueprint class.
|
||||
// Whenever the blueprint class is nullptr, the Actor is
|
||||
// also nullptr. Ie, a tangible will have no Actor associated
|
||||
// with it if its blueprint class is nullptr.
|
||||
//
|
||||
void SetActorBlueprintClass(TSubclassOf<AActor> bp);
|
||||
|
||||
AActor* GetActor() const { return CurrentActor.Get(); }
|
||||
// Update the animation queue from Luprex.
|
||||
//
|
||||
// This reads the animation queue, and then based on
|
||||
// what is new in the animation queue, it calls into
|
||||
// the Actor's TangibleInterface, calling methods such
|
||||
// as 'StartAnimation' and 'AbortAnimation' as necessary.
|
||||
//
|
||||
// If the animation queue specifies a blueprint change,
|
||||
// this function will eventually implement that by calling
|
||||
// SetActorBlueprintClass above. This is not implemented
|
||||
// yet.
|
||||
//
|
||||
void UpdateAnimationQueue(std::string_view aq);
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = Luprex)
|
||||
|
||||
@@ -28,6 +28,7 @@ UlxTangible* UlxTangibleManager::GetTangible(int64 id) const {
|
||||
}
|
||||
}
|
||||
|
||||
#pragma optimize("", off)
|
||||
UlxTangible* UlxTangibleManager::MakeTangible(int64 id) {
|
||||
UlxTangible*& t = IdToTangible.FindOrAdd(id);
|
||||
if (t == nullptr) {
|
||||
@@ -56,7 +57,8 @@ TanArray UlxTangibleManager::GetAllTangibles() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
void UlxTangibleManager::UpdateNear(IdView near) {
|
||||
#pragma optimize("", off)
|
||||
void UlxTangibleManager::UpdateNearAccordingToLuprex(IdView near) {
|
||||
// Clear all the 'NearAccordingToLuprex' flags.
|
||||
for (const auto& pair : IdToTangible) {
|
||||
pair.Value->NearAccordingToLuprex = false;
|
||||
@@ -69,6 +71,41 @@ void UlxTangibleManager::UpdateNear(IdView near) {
|
||||
}
|
||||
}
|
||||
|
||||
#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());
|
||||
|
||||
@@ -61,10 +61,21 @@ public:
|
||||
|
||||
// Update the 'NearAccordingToLuprex' flags.
|
||||
//
|
||||
// Also creates any tangibles that are in the near-list,
|
||||
// if they don't already exist.
|
||||
// Also creates stub tangibles for every Id in the list.
|
||||
//
|
||||
void UpdateNear(IdView near);
|
||||
void UpdateNearAccordingToLuprex(IdView near);
|
||||
|
||||
// Recalculate the 'NearAccordingToUnreal' flags.
|
||||
//
|
||||
void RecalcNearAccordingToUnreal(int64 player, double radius);
|
||||
|
||||
// Delete Far Tangibles.
|
||||
//
|
||||
// Any tangible whose 'NearAccordingToLuprex' and 'NearAccordingToUnreal'
|
||||
// flags are both false is deleted. You probably want to update both
|
||||
// flags by calling the two routines above before calling this.
|
||||
//
|
||||
void DeleteFarawayTangibles();
|
||||
|
||||
// Given an array of tangibles, return an array of tangible Ids.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user