Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement various Iterators #74

Merged
merged 4 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions SurrealEngine/Native/NActor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ void NActor::AutonomousPhysics(UObject* Self, float DeltaSeconds)

void NActor::BasedActors(UObject* Self, UObject* BaseClass, UObject*& Actor)
{
Frame::CreatedIterator = std::make_unique<BasedActorsIterator>(BaseClass, &Actor);
Frame::CreatedIterator = std::make_unique<BasedActorsIterator>(UObject::Cast<UActor>(Self), BaseClass, &Actor);
}

void NActor::ChildActors(UObject* Self, UObject* BaseClass, UObject*& Actor)
{
Frame::CreatedIterator = std::make_unique<ChildActorsIterator>(BaseClass, &Actor);
Frame::CreatedIterator = std::make_unique<ChildActorsIterator>(UObject::Cast<UActor>(Self), BaseClass, &Actor);
}

void NActor::ConsoleCommand(UObject* Self, const std::string& Command, std::string& ReturnValue)
Expand Down Expand Up @@ -388,7 +388,8 @@ void NActor::PlayerCanSeeMe(UObject* Self, BitfieldBool& ReturnValue)

void NActor::RadiusActors(UObject* Self, UObject* BaseClass, UObject*& Actor, float Radius, vec3* Loc)
{
Frame::CreatedIterator = std::make_unique<RadiusActorsIterator>(BaseClass, &Actor, Radius, Loc ? *Loc : UObject::Cast<UActor>(Self)->Location());
UActor* SelfActor = UObject::Cast<UActor>(Self);
Frame::CreatedIterator = std::make_unique<RadiusActorsIterator>(SelfActor, BaseClass, &Actor, Radius, Loc ? *Loc : SelfActor->Location());
}

void NActor::SetBase(UObject* Self, UObject* NewBase)
Expand Down Expand Up @@ -463,7 +464,7 @@ void NActor::Subtract_ColorColor(const Color& A, const Color& B, Color& ReturnVa

void NActor::TouchingActors(UObject* Self, UObject* BaseClass, UObject*& Actor)
{
Frame::CreatedIterator = std::make_unique<TouchingActorsIterator>(BaseClass, &Actor);
Frame::CreatedIterator = std::make_unique<TouchingActorsIterator>(UObject::TryCast<UActor>(Self), BaseClass, &Actor);
}

void NActor::Trace(UObject* Self, vec3& HitLocation, vec3& HitNormal, const vec3& TraceEnd, vec3* TraceStart, BitfieldBool* bTraceActors, vec3* Extent, UObject*& ReturnValue)
Expand Down Expand Up @@ -494,7 +495,7 @@ void NActor::VisibleActors(UObject* Self, UObject* BaseClass, UObject*& Actor, f
{
UActor* SelfActor = UObject::Cast<UActor>(Self);
Frame::CreatedIterator = std::make_unique<VisibleActorsIterator>(
BaseClass, &Actor,
SelfActor, BaseClass, &Actor,
Radius ? *Radius : SelfActor->CollisionRadius(),
Loc ? *Loc : SelfActor->Location());
}
Expand Down
140 changes: 123 additions & 17 deletions SurrealEngine/VM/Iterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "Engine.h"
#include "UObject/ULevel.h"
#include "UObject/UActor.h"
#include "Collision/OverlapCylinderLevel.h"

AllObjectsIterator::AllObjectsIterator(UObject* BaseClass, UObject** ReturnValue, NameString MatchTag) : BaseClass(BaseClass), ReturnValue(ReturnValue), MatchTag(MatchTag)
{
Expand All @@ -27,7 +28,7 @@ bool AllObjectsIterator::Next()

/////////////////////////////////////////////////////////////////////////////

BasedActorsIterator::BasedActorsIterator(UObject* BaseClass, UObject** Actor) : BaseClass(BaseClass), Actor(Actor)
BasedActorsIterator::BasedActorsIterator(UActor* Caller, UObject* BaseClass, UObject** Actor) : BaseClass(BaseClass), Actor(Actor)
{
engine->LogUnimplemented("Actor.BasedActors");
}
Expand All @@ -39,62 +40,147 @@ bool BasedActorsIterator::Next()

/////////////////////////////////////////////////////////////////////////////

ChildActorsIterator::ChildActorsIterator(UObject* BaseClass, UObject** Actor) : BaseClass(BaseClass), Actor(Actor)
ChildActorsIterator::ChildActorsIterator(UActor* Caller, UObject* BaseClass, UObject** Actor) : BaseClass(BaseClass), Actor(Actor)
{
engine->LogUnimplemented("Actor.ChildActors");
for (UActor* levelActor : engine->Level->Actors)
{
if (levelActor->Owner() == Caller && levelActor->IsA(BaseClass->Name))
ChildActors.push_back(levelActor);
}

iterator = ChildActors.begin();
}

bool ChildActorsIterator::Next()
{
return false;
if (iterator == ChildActors.end())
return false;

*Actor = *iterator;
iterator++;

return *Actor;
}

/////////////////////////////////////////////////////////////////////////////

RadiusActorsIterator::RadiusActorsIterator(UObject* BaseClass, UObject** Actor, float Radius, vec3 Location) : BaseClass(BaseClass), Actor(Actor), Radius(Radius), Location(Location)
RadiusActorsIterator::RadiusActorsIterator(UActor* Caller, UObject* BaseClass, UObject** Actor, float Radius, vec3 Location) : BaseClass(BaseClass), Actor(Actor), Radius(Radius), Location(Location)
{
engine->LogUnimplemented("Actor.RadiusActors");
for (UActor* levelActor : engine->Level->Actors)
{
if (levelActor->IsA(BaseClass->Name) && length(levelActor->Location() - Location) <= Radius)
RadiusActors.push_back(levelActor);
}

iterator = RadiusActors.begin();
}

bool RadiusActorsIterator::Next()
{
return false;
if (iterator == RadiusActors.end())
return false;

*Actor = *iterator;
iterator++;

return *Actor;
}

/////////////////////////////////////////////////////////////////////////////

TouchingActorsIterator::TouchingActorsIterator(UObject* BaseClass, UObject** Actor) : BaseClass(BaseClass), Actor(Actor)
TouchingActorsIterator::TouchingActorsIterator(UActor* Caller, UObject* BaseClass, UObject** outActor) : BaseClass(BaseClass), outActor(outActor)
{
engine->LogUnimplemented("Actor.TouchingActors");
OverlapCylinderLevel collisionTester;

CollisionHitList hitList = collisionTester.TestOverlap(Caller->XLevel(), Caller->Location(), Caller->CollisionHeight(),
Caller->CollisionRadius(), true, false, false);

for (auto& hit : hitList)
{
// Only allow the Actors of type BaseClass
if (hit.Actor->IsA(BaseClass->Name))
TouchingActors.push_back(hit.Actor);
}

iterator = TouchingActors.begin();
}

bool TouchingActorsIterator::Next()
{
return false;
if (iterator == TouchingActors.end())
return false;

*outActor = *iterator;
iterator++;

return *outActor;
}

/////////////////////////////////////////////////////////////////////////////

TraceActorsIterator::TraceActorsIterator(UObject* BaseClass, UObject** Actor, vec3* HitLoc, vec3* HitNorm, const vec3& End, const vec3& Start, const vec3& Extent) : BaseClass(BaseClass), Actor(Actor), HitLoc(HitLoc), HitNorm(HitNorm), End(End), Start(Start), Extent(Extent)
{
engine->LogUnimplemented("Actor.TraceActors");
UActor* BaseActor = UObject::TryCast<UActor>(BaseClass);

vec3 startPoint = Start;

UActor* tracedActor = UObject::TryCast<UActor>(BaseActor->Trace(*HitLoc, *HitNorm, End, startPoint, true, Extent));

do {
if (tracedActor)
{
// Only allow the Actors of type BaseClass
if (tracedActor->IsA(BaseClass->Name))
tracedActors.push_back({ tracedActor, *HitLoc, *HitNorm });
startPoint = *HitLoc; // Make hit location the start point for the next trace
tracedActor = UObject::TryCast<UActor>(tracedActor->Trace(*HitLoc, *HitNorm, End, startPoint, true, Extent));
}
} while (tracedActor);

iterator = tracedActors.begin();
}

bool TraceActorsIterator::Next()
{
return false;
if (iterator == tracedActors.end())
return false;

*Actor = iterator->tracedActor;
*HitLoc = iterator->HitLoc;
*HitNorm = iterator->HitNorm;
iterator++;

return *Actor;
}

/////////////////////////////////////////////////////////////////////////////

VisibleActorsIterator::VisibleActorsIterator(UObject* BaseClass, UObject** Actor, float Radius, const vec3& Location) : BaseClass(BaseClass), Actor(Actor), Radius(Radius), Location(Location)
VisibleActorsIterator::VisibleActorsIterator(UActor* Caller, UObject* BaseClass, UObject** Actor, float Radius, const vec3& Location) : BaseClass(BaseClass), Actor(Actor), Radius(Radius), Location(Location)
{
engine->LogUnimplemented("Actor.VisibleActor");
for (auto levelActor : engine->Level->Actors)
{
// Our checks:
// * Whether the actor we're dealing with is not hidden and is the class of BaseClass
// * Then whether the distance of the actor from our given Location is no more than Radius
if (!levelActor->bHidden() && levelActor->IsA(BaseClass->Name) &&
length(levelActor->Location() - Location) <= Radius && Caller->FastTrace(levelActor->Location(), Location))
{
VisibleActors.push_back(levelActor);
}
}

iterator = VisibleActors.begin();
}

bool VisibleActorsIterator::Next()
{
return false;
if (iterator == VisibleActors.end())
return false;

*Actor = *iterator;
iterator++;

return *Actor;
}

/////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -123,10 +209,30 @@ bool VisibleCollidingActorsIterator::Next()

ZoneActorsIterator::ZoneActorsIterator(UZoneInfo* zone, UObject* BaseClass, UObject** Actor) : Zone(zone), BaseClass(BaseClass), Actor(Actor)
{
engine->LogUnimplemented("ZoneInfo.ZoneActors");
int zoneNum = zone->BspInfo.Node->Zone1;

if (engine->Level->Model->Zones[zoneNum].ZoneActor != zone)
zoneNum = zone->BspInfo.Node->Zone0;

for (UActor* levelActor : engine->Level->Actors)
{
if ((levelActor->BspInfo.Node->Zone1 == zoneNum || levelActor->BspInfo.Node->Zone0 == zoneNum)
&& levelActor->IsA(BaseClass->Name))
{
ZoneActors.push_back(levelActor);
}
}

iterator = ZoneActors.begin();
}

bool ZoneActorsIterator::Next()
{
return false;
if (iterator == ZoneActors.end())
return false;

*Actor = *iterator;
iterator++;

return *Actor;
}
39 changes: 33 additions & 6 deletions SurrealEngine/VM/Iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,47 +31,57 @@ class AllObjectsIterator : public Iterator
class BasedActorsIterator : public Iterator
{
public:
BasedActorsIterator(UObject* BaseClass, UObject** Actor);
BasedActorsIterator(UActor* Caller, UObject* BaseClass, UObject** Actor);
bool Next() override;

UObject* BaseClass = nullptr;
UObject** Actor = nullptr;
size_t index = 0;
};

// An Iterator for iterating through all child actors of a given actor (e.g. due to being spawned by them)
class ChildActorsIterator : public Iterator
{
public:
ChildActorsIterator(UObject* BaseClass, UObject** Actor);
ChildActorsIterator(UActor* Caller, UObject* BaseClass, UObject** Actor);
bool Next() override;

UObject* BaseClass = nullptr;
UObject** Actor = nullptr;
size_t index = 0;

std::vector<UActor*> ChildActors;
std::vector<UActor*>::iterator iterator;
};

class RadiusActorsIterator : public Iterator
{
public:
RadiusActorsIterator(UObject* BaseClass, UObject** Actor, float Radius, vec3 Location);
RadiusActorsIterator(UActor* Caller, UObject* BaseClass, UObject** Actor, float Radius, vec3 Location);
bool Next() override;

UObject* BaseClass = nullptr;
UObject** Actor = nullptr;
float Radius = 0.0f;
vec3 Location;
size_t index = 0;

std::vector<UActor*> RadiusActors;
std::vector<UActor*>::iterator iterator;
};

class TouchingActorsIterator : public Iterator
{
public:
TouchingActorsIterator(UObject* BaseClass, UObject** Actor);
TouchingActorsIterator(UActor* Caller, UObject* BaseClass, UObject** outActor);
bool Next() override;

UObject* BaseClass = nullptr;
UObject** Actor = nullptr;
UObject** outActor = nullptr;
size_t index = 0;

std::vector<UActor*> TouchingActors;
std::vector<UActor*>::iterator iterator;
};

class TraceActorsIterator : public Iterator
Expand All @@ -88,19 +98,32 @@ class TraceActorsIterator : public Iterator
vec3 Start = vec3(0.0f);
vec3 Extent = vec3(0.0f);
size_t index = 0;

struct TraceInfo
{
UActor* tracedActor;
vec3 HitLoc;
vec3 HitNorm;
};

std::vector<TraceInfo> tracedActors;
std::vector<TraceInfo>::iterator iterator;
};

class VisibleActorsIterator : public Iterator
{
public:
VisibleActorsIterator(UObject* BaseClass, UObject** Actor, float Radius, const vec3& Location);
VisibleActorsIterator(UActor* Caller, UObject* BaseClass, UObject** Actor, float Radius, const vec3& Location);
bool Next() override;

UObject* BaseClass = nullptr;
UObject** Actor = nullptr;
float Radius = 0.0f;
vec3 Location = vec3(0.0f);
size_t index = 0;

std::vector<UActor*> VisibleActors;
std::vector<UActor*>::iterator iterator;
};

class VisibleCollidingActorsIterator : public Iterator
Expand All @@ -118,6 +141,7 @@ class VisibleCollidingActorsIterator : public Iterator
std::vector<UActor*> HitActors;
};

// Iterator for iterating through all actors in a given Zone
class ZoneActorsIterator : public Iterator
{
public:
Expand All @@ -128,4 +152,7 @@ class ZoneActorsIterator : public Iterator
UObject* BaseClass = nullptr;
UObject** Actor = nullptr;
size_t index = 0;

std::vector<UActor*> ZoneActors;
std::vector<UActor*>::iterator iterator;
};