Skip to content

Commit

Permalink
Expose batched overlapping functionality for actors and components
Browse files Browse the repository at this point in the history
  • Loading branch information
nxrighthere committed Oct 9, 2020
1 parent 2cc72a7 commit 6afb5a9
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 10 deletions.
14 changes: 14 additions & 0 deletions API/Actor-ForEachOverlappingActor-T-(Action-T-).md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
### [UnrealEngine.Framework](./UnrealEngine-Framework.md 'UnrealEngine.Framework').[Actor](./Actor.md 'UnrealEngine.Framework.Actor')
## Actor.ForEachOverlappingActor<T>(System.Action<T>) Method
Performs the specified action on each overlapping actor if any
```csharp
public void ForEachOverlappingActor<T>(System.Action<T> action);
```
#### Type parameters
<a name='UnrealEngine-Framework-Actor-ForEachOverlappingActor-T-(System-Action-T-)-T'></a>
`T`

#### Parameters
<a name='UnrealEngine-Framework-Actor-ForEachOverlappingActor-T-(System-Action-T-)-action'></a>
`action` [System.Action&lt;](https://docs.microsoft.com/en-us/dotnet/api/System.Action-1 'System.Action`1')[T](#UnrealEngine-Framework-Actor-ForEachOverlappingActor-T-(System-Action-T-)-T 'UnrealEngine.Framework.Actor.ForEachOverlappingActor&lt;T&gt;(System.Action&lt;T&gt;).T')[&gt;](https://docs.microsoft.com/en-us/dotnet/api/System.Action-1 'System.Action`1')

1 change: 1 addition & 0 deletions API/Actor.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Implements [System.IEquatable&lt;](https://docs.microsoft.com/en-us/dotnet/api/S
- [AddTag(string)](./Actor-AddTag(string).md 'UnrealEngine.Framework.Actor.AddTag(string)')
- [Destroy()](./Actor-Destroy().md 'UnrealEngine.Framework.Actor.Destroy()')
- [Equals(UnrealEngine.Framework.Actor)](./Actor-Equals(Actor).md 'UnrealEngine.Framework.Actor.Equals(UnrealEngine.Framework.Actor)')
- [ForEachOverlappingActor&lt;T&gt;(System.Action&lt;T&gt;)](./Actor-ForEachOverlappingActor-T-(Action-T-).md 'UnrealEngine.Framework.Actor.ForEachOverlappingActor&lt;T&gt;(System.Action&lt;T&gt;)')
- [GetBool(string, bool)](./Actor-GetBool(string_bool).md 'UnrealEngine.Framework.Actor.GetBool(string, bool)')
- [GetBounds(bool, System.Numerics.Vector3, System.Numerics.Vector3)](./Actor-GetBounds(bool_Vector3_Vector3).md 'UnrealEngine.Framework.Actor.GetBounds(bool, System.Numerics.Vector3, System.Numerics.Vector3)')
- [GetByte(string, byte)](./Actor-GetByte(string_byte).md 'UnrealEngine.Framework.Actor.GetByte(string, byte)')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
### [UnrealEngine.Framework](./UnrealEngine-Framework.md 'UnrealEngine.Framework').[PrimitiveComponent](./PrimitiveComponent.md 'UnrealEngine.Framework.PrimitiveComponent')
## PrimitiveComponent.ForEachOverlappingComponent&lt;T&gt;(System.Action&lt;T&gt;) Method
Performs the specified action on each overlapping component if any
```csharp
public void ForEachOverlappingComponent<T>(System.Action<T> action);
```
#### Type parameters
<a name='UnrealEngine-Framework-PrimitiveComponent-ForEachOverlappingComponent-T-(System-Action-T-)-T'></a>
`T`

#### Parameters
<a name='UnrealEngine-Framework-PrimitiveComponent-ForEachOverlappingComponent-T-(System-Action-T-)-action'></a>
`action` [System.Action&lt;](https://docs.microsoft.com/en-us/dotnet/api/System.Action-1 'System.Action`1')[T](#UnrealEngine-Framework-PrimitiveComponent-ForEachOverlappingComponent-T-(System-Action-T-)-T 'UnrealEngine.Framework.PrimitiveComponent.ForEachOverlappingComponent&lt;T&gt;(System.Action&lt;T&gt;).T')[&gt;](https://docs.microsoft.com/en-us/dotnet/api/System.Action-1 'System.Action`1')

1 change: 1 addition & 0 deletions API/PrimitiveComponent.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Derived
- [ClearMoveIgnoreActors()](./PrimitiveComponent-ClearMoveIgnoreActors().md 'UnrealEngine.Framework.PrimitiveComponent.ClearMoveIgnoreActors()')
- [ClearMoveIgnoreComponents()](./PrimitiveComponent-ClearMoveIgnoreComponents().md 'UnrealEngine.Framework.PrimitiveComponent.ClearMoveIgnoreComponents()')
- [CreateAndSetMaterialInstanceDynamic(int)](./PrimitiveComponent-CreateAndSetMaterialInstanceDynamic(int).md 'UnrealEngine.Framework.PrimitiveComponent.CreateAndSetMaterialInstanceDynamic(int)')
- [ForEachOverlappingComponent&lt;T&gt;(System.Action&lt;T&gt;)](./PrimitiveComponent-ForEachOverlappingComponent-T-(Action-T-).md 'UnrealEngine.Framework.PrimitiveComponent.ForEachOverlappingComponent&lt;T&gt;(System.Action&lt;T&gt;)')
- [GetDistanceToCollision(System.Numerics.Vector3, System.Numerics.Vector3)](./PrimitiveComponent-GetDistanceToCollision(Vector3_Vector3).md 'UnrealEngine.Framework.PrimitiveComponent.GetDistanceToCollision(System.Numerics.Vector3, System.Numerics.Vector3)')
- [GetMaterial(int)](./PrimitiveComponent-GetMaterial(int).md 'UnrealEngine.Framework.PrimitiveComponent.GetMaterial(int)')
- [GetPhysicsAngularVelocityInDegrees(System.Numerics.Vector3, string)](./PrimitiveComponent-GetPhysicsAngularVelocityInDegrees(Vector3_string).md 'UnrealEngine.Framework.PrimitiveComponent.GetPhysicsAngularVelocityInDegrees(System.Numerics.Vector3, string)')
Expand Down
Binary file modified Content/Tests/Tests.umap
Binary file not shown.
Binary file modified Content/Tests/Tests_BuiltData.uasset
Binary file not shown.
8 changes: 6 additions & 2 deletions Source/Managed/Framework/Codegen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace UnrealEngine.Framework {
// Automatically generated

internal static class Shared {
internal const int checksum = 0x296;
internal const int checksum = 0x298;
internal static Dictionary<int, IntPtr> userFunctions = new();
private const string dynamicTypesAssemblyName = "UnrealEngine.DynamicTypes";
private static readonly ModuleBuilder moduleBuilder = AssemblyBuilder.DefineDynamicAssembly(new(dynamicTypesAssemblyName), AssemblyBuilderAccess.RunAndCollect).DefineDynamicModule(dynamicTypesAssemblyName);
Expand All @@ -39,7 +39,7 @@ internal static class Shared {
private const TypeAttributes delegateTypeAttributes = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass;

internal static unsafe Dictionary<int, IntPtr> Load(IntPtr* events, IntPtr functions, Assembly pluginAssembly) {
int position = 0;
int position = 0;
IntPtr* buffer = (IntPtr*)functions;

unchecked {
Expand Down Expand Up @@ -268,6 +268,7 @@ internal static unsafe Dictionary<int, IntPtr> Load(IntPtr* events, IntPtr funct
Actor.isPendingKill = (delegate* unmanaged[Cdecl]<IntPtr, Bool>)actorFunctions[head++];
Actor.isRootComponentMovable = (delegate* unmanaged[Cdecl]<IntPtr, Bool>)actorFunctions[head++];
Actor.isOverlappingActor = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, Bool>)actorFunctions[head++];
Actor.forEachOverlappingActor = (delegate* unmanaged[Cdecl]<IntPtr, ref ObjectReference*, ref int, void>)actorFunctions[head++];
Actor.spawn = (delegate* unmanaged[Cdecl]<string, ActorType, IntPtr, IntPtr>)actorFunctions[head++];
Actor.destroy = (delegate* unmanaged[Cdecl]<IntPtr, Bool>)actorFunctions[head++];
Actor.rename = (delegate* unmanaged[Cdecl]<IntPtr, string, void>)actorFunctions[head++];
Expand Down Expand Up @@ -657,6 +658,7 @@ internal static unsafe Dictionary<int, IntPtr> Load(IntPtr* events, IntPtr funct

PrimitiveComponent.isGravityEnabled = (delegate* unmanaged[Cdecl]<IntPtr, Bool>)primitiveComponentFunctions[head++];
PrimitiveComponent.isOverlappingComponent = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, Bool>)primitiveComponentFunctions[head++];
PrimitiveComponent.forEachOverlappingComponent = (delegate* unmanaged[Cdecl]<IntPtr, ref ObjectReference*, ref int, void>)primitiveComponentFunctions[head++];
PrimitiveComponent.addAngularImpulseInDegrees = (delegate* unmanaged[Cdecl]<IntPtr, in Vector3, string, Bool, void>)primitiveComponentFunctions[head++];
PrimitiveComponent.addAngularImpulseInRadians = (delegate* unmanaged[Cdecl]<IntPtr, in Vector3, string, Bool, void>)primitiveComponentFunctions[head++];
PrimitiveComponent.addForce = (delegate* unmanaged[Cdecl]<IntPtr, in Vector3, string, Bool, void>)primitiveComponentFunctions[head++];
Expand Down Expand Up @@ -1450,6 +1452,7 @@ unsafe partial class Actor {
internal static delegate* unmanaged[Cdecl]<IntPtr, Bool> isPendingKill;
internal static delegate* unmanaged[Cdecl]<IntPtr, Bool> isRootComponentMovable;
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr, Bool> isOverlappingActor;
internal static delegate* unmanaged[Cdecl]<IntPtr, ref ObjectReference*, ref int, void> forEachOverlappingActor;
internal static delegate* unmanaged[Cdecl]<string, ActorType, IntPtr, IntPtr> spawn;
internal static delegate* unmanaged[Cdecl]<IntPtr, Bool> destroy;
internal static delegate* unmanaged[Cdecl]<IntPtr, string, void> rename;
Expand Down Expand Up @@ -1815,6 +1818,7 @@ unsafe partial class SpringArmComponent {
unsafe partial class PrimitiveComponent {
internal static delegate* unmanaged[Cdecl]<IntPtr, Bool> isGravityEnabled;
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr, Bool> isOverlappingComponent;
internal static delegate* unmanaged[Cdecl]<IntPtr, ref ObjectReference*, ref int, void> forEachOverlappingComponent;
internal static delegate* unmanaged[Cdecl]<IntPtr, in Vector3, string, Bool, void> addAngularImpulseInDegrees;
internal static delegate* unmanaged[Cdecl]<IntPtr, in Vector3, string, Bool, void> addAngularImpulseInRadians;
internal static delegate* unmanaged[Cdecl]<IntPtr, in Vector3, string, Bool, void> addForce;
Expand Down
40 changes: 40 additions & 0 deletions Source/Managed/Framework/Framework.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4315,6 +4315,26 @@ public bool IsOverlappingActor(Actor other) {
return isOverlappingActor(Pointer, other.Pointer);
}

/// <summary>
/// Performs the specified action on each overlapping actor if any
/// </summary>
public unsafe void ForEachOverlappingActor<T>(Action<T> action) where T : Actor {
if (action == null)
throw new ArgumentNullException(nameof(action));

ObjectReference* array = null;
int elements = 0;

forEachOverlappingActor(Pointer, ref array, ref elements);

for (int i = 0; i < elements; i++) {
T actor = array[i].ToActor<T>();

if (actor != null)
action(actor);
}
}

/// <summary>
/// Returns the unique ID of the actor, reused by the engine, only unique while the actor is alive
/// </summary>
Expand Down Expand Up @@ -8330,6 +8350,26 @@ public bool IsOverlappingComponent(PrimitiveComponent other) {
return isOverlappingComponent(Pointer, other.Pointer);
}

/// <summary>
/// Performs the specified action on each overlapping component if any
/// </summary>
public unsafe void ForEachOverlappingComponent<T>(Action<T> action) where T : PrimitiveComponent {
if (action == null)
throw new ArgumentNullException(nameof(action));

ObjectReference* array = null;
int elements = 0;

forEachOverlappingComponent(Pointer, ref array, ref elements);

for (int i = 0; i < elements; i++) {
T component = array[i].ToComponent<T>();

if (component != null)
action(component);
}
}

/// <summary>
/// Returns approximate mass in kilograms
/// </summary>
Expand Down
21 changes: 17 additions & 4 deletions Source/Managed/Tests/DynamicEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
namespace UnrealEngine.Tests {
public class DynamicEvents : ISystem {
private PlayerController playerController;
private TriggerBox triggerBox;
private BoxComponent triggerCollisionComponent;
private Actor leftActor;
private Actor rightActor;
private StaticMeshComponent leftStaticMeshComponent;
Expand All @@ -16,6 +18,8 @@ public class DynamicEvents : ISystem {

public DynamicEvents() {
playerController = World.GetFirstPlayerController();
triggerBox = new();
triggerCollisionComponent = triggerBox.GetComponent<BoxComponent>();
leftActor = new("LeftActor");
rightActor = new("RightActor");
leftStaticMeshComponent = new(leftActor, "LeftActorComponent", true);
Expand Down Expand Up @@ -47,13 +51,11 @@ public void OnBeginPlay() {

const float linesThickness = 3.0f;

TriggerBox triggerBox = new();
BoxComponent collisionComponent = triggerBox.GetComponent<BoxComponent>();
Vector3 collisionShape = new(200.0f, 200.0f, 200.0f);

collisionComponent.SetBoxExtent(collisionShape);
triggerCollisionComponent.SetBoxExtent(collisionShape);

Debug.DrawBox(collisionComponent.GetLocation(), collisionShape, Quaternion.Identity, Color.Aqua, true, thickness: linesThickness);
Debug.DrawBox(triggerCollisionComponent.GetLocation(), collisionShape, Quaternion.Identity, Color.Aqua, true, thickness: linesThickness);

leftActor.RegisterEvent(ActorEventType.OnActorBeginOverlap);
leftActor.RegisterEvent(ActorEventType.OnActorEndOverlap);
Expand Down Expand Up @@ -120,10 +122,21 @@ public void OnTick(float deltaTime) {

if (playerController.GetHitResultUnderCursor(CollisionChannel.WorldDynamic, ref hit))
Debug.AddOnScreenMessage(13, 3.0f, Color.CornflowerBlue, "Cursor hit " + hit.GetActor().Name);

triggerBox.ForEachOverlappingActor(OnTriggerOverlapActor);
triggerCollisionComponent.ForEachOverlappingComponent(OnTriggerOverlapComponent);
}

public void OnEndPlay() => Debug.ClearOnScreenMessages();

private Action<Actor> OnTriggerOverlapActor = (actor) => {
Debug.AddOnScreenMessage((int)(actor.ID % Int32.MaxValue), 3.0f, Color.Aqua, "Trigger box overlapped " + actor.Name);
};

private Action<StaticMeshComponent> OnTriggerOverlapComponent = (component) => {
Debug.AddOnScreenMessage((int)(component.ID % Int32.MaxValue), 3.0f, Color.Aquamarine, "Trigger collision component overlapped " + component.Name);
};

private void Translate(StaticMeshComponent staticMeshComponent, float direction) {
if (!stopTranslation) {
Vector3 currentLocation = default;
Expand Down
2 changes: 2 additions & 0 deletions Source/Native/Source/UnrealCLR/Private/UnrealCLR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ void UnrealCLR::Module::StartupModule() {
Shared::ActorFunctions[head++] = (void*)&UnrealCLRFramework::Actor::IsPendingKill;
Shared::ActorFunctions[head++] = (void*)&UnrealCLRFramework::Actor::IsRootComponentMovable;
Shared::ActorFunctions[head++] = (void*)&UnrealCLRFramework::Actor::IsOverlappingActor;
Shared::ActorFunctions[head++] = (void*)&UnrealCLRFramework::Actor::ForEachOverlappingActor;
Shared::ActorFunctions[head++] = (void*)&UnrealCLRFramework::Actor::Spawn;
Shared::ActorFunctions[head++] = (void*)&UnrealCLRFramework::Actor::Destroy;
Shared::ActorFunctions[head++] = (void*)&UnrealCLRFramework::Actor::Rename;
Expand Down Expand Up @@ -826,6 +827,7 @@ void UnrealCLR::Module::StartupModule() {

Shared::PrimitiveComponentFunctions[head++] = (void*)&UnrealCLRFramework::PrimitiveComponent::IsGravityEnabled;
Shared::PrimitiveComponentFunctions[head++] = (void*)&UnrealCLRFramework::PrimitiveComponent::IsOverlappingComponent;
Shared::PrimitiveComponentFunctions[head++] = (void*)&UnrealCLRFramework::PrimitiveComponent::ForEachOverlappingComponent;
Shared::PrimitiveComponentFunctions[head++] = (void*)&UnrealCLRFramework::PrimitiveComponent::AddAngularImpulseInDegrees;
Shared::PrimitiveComponentFunctions[head++] = (void*)&UnrealCLRFramework::PrimitiveComponent::AddAngularImpulseInRadians;
Shared::PrimitiveComponentFunctions[head++] = (void*)&UnrealCLRFramework::PrimitiveComponent::AddForce;
Expand Down
38 changes: 34 additions & 4 deletions Source/Native/Source/UnrealCLR/Private/UnrealCLRFramework.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1315,6 +1315,21 @@ namespace UnrealCLRFramework {
return Actor->IsOverlappingActor(Other);
}

void ForEachOverlappingActor(AActor* Actor, AActor** Array, int32* Elements) {
static TArray<AActor*> overlappingActors;

overlappingActors.Reset();

Actor->GetOverlappingActors(overlappingActors);

int32 elements = overlappingActors.Num();

if (elements > 0) {
*Array = reinterpret_cast<AActor*>(overlappingActors.GetData());
*Elements = elements;
}
}

AActor* Spawn(const char* Name, ActorType Type, UObject* Blueprint) {
AActor* actor = nullptr;

Expand Down Expand Up @@ -2575,6 +2590,21 @@ namespace UnrealCLRFramework {
return PrimitiveComponent->IsOverlappingComponent(Other);
}

void ForEachOverlappingComponent(UPrimitiveComponent* PrimitiveComponent, UPrimitiveComponent** Array, int32* Elements) {
static TArray<UPrimitiveComponent*> overlappingComponents;

overlappingComponents.Reset();

PrimitiveComponent->GetOverlappingComponents(overlappingComponents);

int32 elements = overlappingComponents.Num();

if (elements > 0) {
*Array = reinterpret_cast<UPrimitiveComponent*>(overlappingComponents.GetData());
*Elements = elements;
}
}

void AddAngularImpulseInDegrees(UPrimitiveComponent* PrimitiveComponent, const Vector3* Impulse, const char* BoneName, bool VelocityChange) {
UNREALCLR_SET_BONE_NAME(BoneName);

Expand Down Expand Up @@ -2746,25 +2776,25 @@ namespace UnrealCLRFramework {
PrimitiveComponent->SetPhysicsLinearVelocity(*Velocity, AddToCurrent, boneName);
}

static void SetPhysicsAngularVelocityInDegrees(UPrimitiveComponent* PrimitiveComponent, const Vector3* AngularVelocity, bool AddToCurrent, const char* BoneName) {
void SetPhysicsAngularVelocityInDegrees(UPrimitiveComponent* PrimitiveComponent, const Vector3* AngularVelocity, bool AddToCurrent, const char* BoneName) {
UNREALCLR_SET_BONE_NAME(BoneName);

PrimitiveComponent->SetPhysicsAngularVelocityInDegrees(*AngularVelocity, AddToCurrent, boneName);
}

static void SetPhysicsAngularVelocityInRadians(UPrimitiveComponent* PrimitiveComponent, const Vector3* AngularVelocity, bool AddToCurrent, const char* BoneName) {
void SetPhysicsAngularVelocityInRadians(UPrimitiveComponent* PrimitiveComponent, const Vector3* AngularVelocity, bool AddToCurrent, const char* BoneName) {
UNREALCLR_SET_BONE_NAME(BoneName);

PrimitiveComponent->SetPhysicsAngularVelocityInRadians(*AngularVelocity, AddToCurrent, boneName);
}

static void SetPhysicsMaxAngularVelocityInDegrees(UPrimitiveComponent* PrimitiveComponent, float MaxAngularVelocity, bool AddToCurrent, const char* BoneName) {
void SetPhysicsMaxAngularVelocityInDegrees(UPrimitiveComponent* PrimitiveComponent, float MaxAngularVelocity, bool AddToCurrent, const char* BoneName) {
UNREALCLR_SET_BONE_NAME(BoneName);

PrimitiveComponent->SetPhysicsMaxAngularVelocityInDegrees(MaxAngularVelocity, AddToCurrent, boneName);
}

static void SetPhysicsMaxAngularVelocityInRadians(UPrimitiveComponent* PrimitiveComponent, float MaxAngularVelocity, bool AddToCurrent, const char* BoneName) {
void SetPhysicsMaxAngularVelocityInRadians(UPrimitiveComponent* PrimitiveComponent, float MaxAngularVelocity, bool AddToCurrent, const char* BoneName) {
UNREALCLR_SET_BONE_NAME(BoneName);

PrimitiveComponent->SetPhysicsMaxAngularVelocityInRadians(MaxAngularVelocity, AddToCurrent, boneName);
Expand Down
2 changes: 2 additions & 0 deletions Source/Native/Source/UnrealCLR/Public/UnrealCLRFramework.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ namespace UnrealCLRFramework {
static bool IsPendingKill(AActor* Actor);
static bool IsRootComponentMovable(AActor* Actor);
static bool IsOverlappingActor(AActor* Actor, AActor* Other);
static void ForEachOverlappingActor(AActor* Actor, AActor** Array, int32* Elements);
static AActor* Spawn(const char* Name, ActorType Type, UObject* Blueprint);
static bool Destroy(AActor* Actor);
static void Rename(AActor* Actor, const char* Name);
Expand Down Expand Up @@ -866,6 +867,7 @@ namespace UnrealCLRFramework {
namespace PrimitiveComponent {
static bool IsGravityEnabled(UPrimitiveComponent* PrimitiveComponent);
static bool IsOverlappingComponent(UPrimitiveComponent* PrimitiveComponent, UPrimitiveComponent* Other);
static void ForEachOverlappingComponent(UPrimitiveComponent* PrimitiveComponent, UPrimitiveComponent** Array, int32* Elements);
static void AddAngularImpulseInDegrees(UPrimitiveComponent* PrimitiveComponent, const Vector3* Impulse, const char* BoneName, bool VelocityChange);
static void AddAngularImpulseInRadians(UPrimitiveComponent* PrimitiveComponent, const Vector3* Impulse, const char* BoneName, bool VelocityChange);
static void AddForce(UPrimitiveComponent* PrimitiveComponent, const Vector3* Force, const char* BoneName, bool AccelerationChange);
Expand Down

0 comments on commit 6afb5a9

Please sign in to comment.