From aafcc41286773988381673557b7f92787c34ca78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Thu, 10 Aug 2023 19:55:45 +0200 Subject: [PATCH] Invoke on collision enter + start of attach child colliders to rigidbody + Changed default Namespace of ScriptCore to GlitchyEngine + Implicit Casts float2 <-> b2Vec2 + Entity constructor internal + Renamed RigidBody2D to Rigidbody2D (notice the B) + Basic Debug Draw actual 2D Colliders + Added Entity::GetParentWithComponent --- GlitchyEditor/src/EditorLayer.bf | 2 +- GlitchyEngine/src/Math/floatVector.bf | 8 + .../src/Scripting/Classes/Collision2D.bf | 14 + GlitchyEngine/src/Scripting/ScriptClass.bf | 30 ++ GlitchyEngine/src/Scripting/ScriptGlue.bf | 4 +- GlitchyEngine/src/Scripting/ScriptInstance.bf | 12 + GlitchyEngine/src/World/Entity.bf | 19 +- GlitchyEngine/src/World/Scene.bf | 277 ++++++++++++++++-- GlitchyEngine/src/World/SceneRenderer.bf | 3 + ScriptCore/Components/RigidBody2D.cs | 2 +- ScriptCore/Entity.cs | 6 +- ScriptCore/Physics/Collision2D.cs | 35 +++ ScriptCore/ScriptCore.csproj | 1 + 13 files changed, 373 insertions(+), 40 deletions(-) create mode 100644 GlitchyEngine/src/Scripting/Classes/Collision2D.bf create mode 100644 ScriptCore/Physics/Collision2D.cs diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index 97cda7e..c28ed01 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -405,7 +405,7 @@ namespace GlitchyEditor for (var (entity, transform, collider) in _activeScene.GetEntities()) { - Renderer2D.DrawRect(transform.WorldTransform * Matrix.Translation(collider.Offset.X, collider.Offset.Y, 0) * Matrix.Scaling(collider.Size.X * 2, collider.Size.Y * 2, 0)); + Renderer2D.DrawRect(transform.WorldTransform * Matrix.Translation(collider.Offset.X, collider.Offset.Y, 0) * Matrix.Scaling(collider.Size.X * 2, collider.Size.Y * 2, 0), .Green); } for (var (entity, transform, collider) in _activeScene.GetEntities()) diff --git a/GlitchyEngine/src/Math/floatVector.bf b/GlitchyEngine/src/Math/floatVector.bf index 7f0f57c..258e993 100644 --- a/GlitchyEngine/src/Math/floatVector.bf +++ b/GlitchyEngine/src/Math/floatVector.bf @@ -24,6 +24,14 @@ public struct float2 { return half2((half)value.X, (half)value.Y); } + + [Inline] +#unwarn + public static implicit operator Box2D.b2Vec2(in Self value) => *(Box2D.b2Vec2*)&value; + + [Inline] +#unwarn + public static implicit operator Self(in Box2D.b2Vec2 value) => *(Self*)&value; } [BonTarget] diff --git a/GlitchyEngine/src/Scripting/Classes/Collision2D.bf b/GlitchyEngine/src/Scripting/Classes/Collision2D.bf new file mode 100644 index 0000000..ad66aef --- /dev/null +++ b/GlitchyEngine/src/Scripting/Classes/Collision2D.bf @@ -0,0 +1,14 @@ +using System; +using GlitchyEngine.Core; + +namespace GlitchyEngine.Scripting.Classes; + +[Ordered, Packed] +struct Collision2D +{ + public UUID Entity; + public UUID OtherEntity; + + public UUID Rigidbody; + public UUID OtherRigidbody; +} diff --git a/GlitchyEngine/src/Scripting/ScriptClass.bf b/GlitchyEngine/src/Scripting/ScriptClass.bf index 64ab7aa..132ef9c 100644 --- a/GlitchyEngine/src/Scripting/ScriptClass.bf +++ b/GlitchyEngine/src/Scripting/ScriptClass.bf @@ -2,6 +2,7 @@ using Mono; using System; using GlitchyEngine.Core; using System.Collections; +using GlitchyEngine.Scripting.Classes; namespace GlitchyEngine.Scripting; @@ -287,6 +288,14 @@ class ScriptClass : SharpClass private OnCreateMethod _onCreate; private OnUpdateMethod _onUpdate; private OnDestroyMethod _onDestroy; + + private function [CallingConvention(.Cdecl)] MonoObject*(MonoObject* instance, Collision2D collision, MonoException** exception) _onCollisionEnter2D; + + //private OnCollisionEnter2DMethod _onCollisionEnter2D; + private OnDestroyMethod _onCollisionLeave2D; + private MonoMethod* _onCollisionEnter2DMethod; + + public bool HasCollisionEnter2D => _onCollisionEnter2D != null; /*public StringView Namespace => _namespace; public StringView ClassName => _className; @@ -303,6 +312,11 @@ class ScriptClass : SharpClass _onCreate = (OnCreateMethod)GetMethodThunk("OnCreate"); _onUpdate = (OnUpdateMethod)GetMethodThunk("OnUpdate", 1); _onDestroy = (OnDestroyMethod)GetMethodThunk("OnDestroy"); + + _onCollisionEnter2D = (.)GetMethodThunk("OnCollisionEnter2D", 1); + _onCollisionLeave2D = (OnDestroyMethod)GetMethodThunk("OnCollisionLeave2D"); + + _onCollisionEnter2DMethod = GetMethod("OnCollisionEnter2D", 1); } public void OnCreate(MonoObject* instance, out MonoException* exception) @@ -328,6 +342,22 @@ class ScriptClass : SharpClass if (_onDestroy != null) _onDestroy(instance, &exception); } + + public void OnCollisionEnter2D(MonoObject* instance, Collision2D collision, out MonoException* exception) + { + exception = null; + + // TODO: use method thunk + if (_onCollisionEnter2DMethod != null) + { +#unwarn + void*[1] args = .(&collision); + + Invoke(_onCollisionEnter2DMethod, instance, (.)&args); + } + // if (_onCollisionEnter2D != null) + // _onCollisionEnter2D(instance, collision, &exception); + } public MonoObject* CreateInstance(UUID uuid, out MonoException* exception) { diff --git a/GlitchyEngine/src/Scripting/ScriptGlue.bf b/GlitchyEngine/src/Scripting/ScriptGlue.bf index 4551dc5..bd72ea1 100644 --- a/GlitchyEngine/src/Scripting/ScriptGlue.bf +++ b/GlitchyEngine/src/Scripting/ScriptGlue.bf @@ -64,7 +64,7 @@ static class ScriptGlue s_RemoveComponentMethods.Clear(); RegisterComponent("GlitchyEngine.Transform"); - RegisterComponent("GlitchyEngine.RigidBody2D"); + RegisterComponent("GlitchyEngine.Rigidbody2D"); } [RegisterMethod] @@ -99,7 +99,7 @@ static class ScriptGlue } else { - Log.EngineLogger.AssertDebug(managedType != null, scope $"No C# component with name \"{{className}}\" found for Beef type \"{typeof(T)}\""); + Log.EngineLogger.AssertDebug(managedType != null, scope $"No C# component with name \"{className}\" found for Beef type \"{typeof(T)}\""); } } diff --git a/GlitchyEngine/src/Scripting/ScriptInstance.bf b/GlitchyEngine/src/Scripting/ScriptInstance.bf index 70aa425..e55871f 100644 --- a/GlitchyEngine/src/Scripting/ScriptInstance.bf +++ b/GlitchyEngine/src/Scripting/ScriptInstance.bf @@ -1,6 +1,7 @@ using Mono; using GlitchyEngine.Core; using System; +using GlitchyEngine.Scripting.Classes; namespace GlitchyEngine.Scripting; @@ -80,6 +81,17 @@ class ScriptInstance : RefCounter if (exception != null) ScriptEngine.HandleMonoException(exception, this); } + + public void InvokeOnCollisionEnter2D(Collision2D collision) + { + if (!_scriptClass.HasCollisionEnter2D) + return; + + _scriptClass.OnCollisionEnter2D(_instance, collision, let exception); + + if (exception != null) + ScriptEngine.HandleMonoException(exception, this); + } public T GetFieldValue(ScriptField field) { diff --git a/GlitchyEngine/src/World/Entity.bf b/GlitchyEngine/src/World/Entity.bf index 2b3e302..999e26d 100644 --- a/GlitchyEngine/src/World/Entity.bf +++ b/GlitchyEngine/src/World/Entity.bf @@ -91,7 +91,24 @@ namespace GlitchyEngine.World return _scene._ecsWorld.GetComponent(_entity); } - + + /// Returns this entity or the closest parent that has the given component. + public (Entity parent, T* component) GetParentWithComponent() where T: struct, new + { + Entity? walker = this; + + while (walker?.IsValid == true) + { + T* component = null; + if (walker?.TryGetComponent(out component) == true) + return (walker.Value, component); + + walker = walker?.Parent; + } + + return (.(), null); + } + public bool HasComponent() where T: struct, new { return _scene._ecsWorld.HasComponent(_entity); diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 4fcf308..94d6a20 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -6,6 +6,8 @@ using Box2D; using GlitchyEngine.Core; using GlitchyEngine.Content; using GlitchyEngine.Scripting; +using GlitchyEngine.Math; +using GlitchyEngine.Scripting.Classes; namespace GlitchyEngine.World { @@ -17,6 +19,8 @@ namespace GlitchyEngine.World internal EcsWorld _ecsWorld = new .() ~ delete _; internal b2World* _physicsWorld2D; + b2ContactListener _contactListener; + b2Draw draw = .(); private Dictionary _onComponentAddedHandlers = new .() ~ delete _; @@ -173,14 +177,143 @@ namespace GlitchyEngine.World public void OnSimulationStart() { - _physicsWorld2D = Box2D.World.Create(ref _gravity2D); + _physicsWorld2D = World.Create(ref _gravity2D); + + _contactListener = b2ContactListener(); + _contactListener.beginContactCallback = (contact, userData) => + { + // TODO: This is bare minimum! Later we need to take hierarchies into account. + // e.g. A is parent of B and B gets event -> A needs to get event too! + var fixtureA = Contact.GetFixtureA(contact); + var fixtureB = Contact.GetFixtureB(contact); + + var bodyA = Fixture.GetBody(fixtureA); + var bodyB = Fixture.GetBody(fixtureB); + + // Cast is obviously 64bit only + var colliderEntityHandleA = (EcsEntity)(uint)Fixture.GetUserData(fixtureA); + var colliderEntityHandleB = (EcsEntity)(uint)Fixture.GetUserData(fixtureB); + + Entity colliderEntityA = .(colliderEntityHandleA, ScriptEngine.Context); + Entity colliderEntityB = .(colliderEntityHandleB, ScriptEngine.Context); + + // Cast is obviously 64bit only + var rigidbodyEntityHandleA = (EcsEntity)(uint)Body.GetUserData(bodyA); + var rigidbodyEntityHandleB = (EcsEntity)(uint)Body.GetUserData(bodyB); + + Entity rigidbodyEntityA = .(rigidbodyEntityHandleA, ScriptEngine.Context); + Entity rigidbodyEntityB = .(rigidbodyEntityHandleB, ScriptEngine.Context); + + bool fireEventA = colliderEntityA.TryGetComponent(let scriptOfColliderA); + fireEventA |= rigidbodyEntityA.TryGetComponent(let scriptOfRigidbodyA); + + if (fireEventA) + { + Collision2D collision = .(); + collision.Entity = colliderEntityA.UUID; + collision.OtherEntity = colliderEntityB.UUID; + collision.Rigidbody = rigidbodyEntityA.UUID; + collision.OtherRigidbody = rigidbodyEntityB.UUID; + + scriptOfColliderA?.Instance?.InvokeOnCollisionEnter2D(collision); + scriptOfRigidbodyA?.Instance?.InvokeOnCollisionEnter2D(collision); + } + + bool fireEventB = colliderEntityB.TryGetComponent(let scriptOfColliderB); + fireEventB |= rigidbodyEntityB.TryGetComponent(let scriptOfRigidbodyB); + + if (fireEventB) + { + Collision2D collision = .(); + collision.Entity = colliderEntityB.UUID; + collision.OtherEntity = colliderEntityA.UUID; + collision.Rigidbody = rigidbodyEntityB.UUID; + collision.OtherRigidbody = rigidbodyEntityA.UUID; + + scriptOfColliderB?.Instance?.InvokeOnCollisionEnter2D(collision); + scriptOfRigidbodyB?.Instance?.InvokeOnCollisionEnter2D(collision); + } + }; + + World.SetContactListener(_physicsWorld2D, &_contactListener); + + draw.drawPolygonCallback = (vertices, vertexCount, color, userData) => + { + for (int i = 1; i < vertexCount; i++) + { + let start = vertices[i - 1]; + let end = vertices[i]; + + Renderer2D.DrawLine(float3(start.x, start.y, 0.0f), float3(end.x, end.y, 0.0f), *(ColorRGBA*)&color); + } + let start = vertices[vertexCount - 1]; + let end = vertices[0]; + + Renderer2D.DrawLine(float3(start.x, start.y, 0.0f), float3(end.x, end.y, 0.0f), *(ColorRGBA*)&color); + }; + draw.drawSolidPolygonCallback = (vertices, vertexCount, color, userData) => + { + for (int i = 1; i < vertexCount; i++) + { + let start = vertices[i - 1]; + let end = vertices[i]; + + Renderer2D.DrawLine(float3(start.x, start.y, 0.0f), float3(end.x, end.y, 0.0f), *(ColorRGBA*)&color); + } + let start = vertices[vertexCount - 1]; + let end = vertices[0]; + + Renderer2D.DrawLine(float3(start.x, start.y, 0.0f), float3(end.x, end.y, 0.0f), *(ColorRGBA*)&color); + }; + draw.drawCircleCallback = (center, radius, color, userData) => + { + Renderer2D.DrawCircle(center, radius.XX, *(ColorRGBA*)&color, 0.1f); + }; + draw.drawSolidCircleCallback = (center, radius, axis, color, userData) => + { + Renderer2D.DrawCircle(center, radius.XX, *(ColorRGBA*)&color); + }; + draw.drawSegmentCallback = (p1, p2, color, userData) => + { + }; + draw.drawPointCallback = (p, size, color, userData) => + { + }; + draw.drawTransformCallback = (xf, userData) => + { + }; + draw.userData = Internal.UnsafeCastToPtr(_physicsWorld2D); + + World.SetDebugDraw(_physicsWorld2D, &draw); + World.SetDebugDrawFlags(_physicsWorld2D, .e_shapeBit); + + InitPhysics2D(); + } + + private void InitPhysics2D() + { + // Initialize all Rigidbodies for (let (ecsHandle, rigidBody) in _ecsWorld.Enumerate()) { Entity entity = .(ecsHandle, this); InitializeRigidbody2D(entity, rigidBody); } + + for (let (ecsHandle, boxCollider) in _ecsWorld.Enumerate()) + { + Entity entity = .(ecsHandle, this); + + InitBoxCollider2D(entity, boxCollider); + } + + for (let (ecsHandle, circleCollider) in _ecsWorld.Enumerate()) + { + Entity entity = .(ecsHandle, this); + + InitCircleCollider2D(entity, circleCollider); + } } private void InitializeRigidbody2D(Entity entity, Rigidbody2DComponent* rigidBody) @@ -189,49 +322,117 @@ namespace GlitchyEngine.World b2BodyDef def = .(); def.type = GetBox2DBodyType(rigidBody.BodyType); + def.userData = (void*)(uint)entity.Handle; - // TODO: breaks with hierarchy - def.position = b2Vec2(transform.Position.X, transform.Position.Y); - def.angle = transform.RotationEuler.Z; + // TODO: check how stable this is + Matrix.Decompose(transform.WorldTransform, let worldPosition, let worldRotation, let worldScale); + float3 worldRotationEuler = Quaternion.ToEulerAngles(worldRotation); + + def.position = b2Vec2(worldPosition.X, worldPosition.Y); + def.angle = worldRotationEuler.Z; b2Body* body = Box2D.World.CreateBody(_physicsWorld2D, &def); Box2D.Body.SetFixedRotation(body, rigidBody.FixedRotation); rigidBody.RuntimeBody = body; + } - if (entity.TryGetComponent(let boxCollider)) + private Result FindParentWithRigidbody(Entity entity, out Entity walker, out Rigidbody2DComponent* rigidbody, out Matrix rigidbodyTransform) + { + walker = entity; + rigidbody = null; + rigidbodyTransform = .Identity; + + while (true) { - b2Shape* boxShape = Box2D.Shape.CreatePolygon(); - Box2D.Shape.PolygonSetAsBox(boxShape, boxCollider.Size.X * transform.Scale.X, boxCollider.Size.Y * transform.Scale.Y); - Box2D.Shape.PolygonSetAsBoxWithCenterAngle(boxShape, boxCollider.Size.X * transform.Scale.X, boxCollider.Size.Y * transform.Scale.Y, ref boxCollider.b2Offset, 0.0f); + // Found the parent with our beloved component + if (walker.TryGetComponent(out rigidbody) == true) + break; - b2FixtureDef fixtureDef = .(); - fixtureDef.shape = boxShape; - fixtureDef.density = boxCollider.Density; - fixtureDef.friction = boxCollider.Friction; - fixtureDef.restitution = boxCollider.Restitution; - fixtureDef.restitutionThreshold = boxCollider.RestitutionThreshold; + let parent = walker.Parent; - b2Fixture* fixture = Box2D.Body.CreateFixture(body, &fixtureDef); - boxCollider.RuntimeFixture = fixture; + // We need a rigid body + if (parent == null) + { + Log.ClientLogger.Warning($"Entity {entity.Name} ({entity.Handle}) has a collider but no parent with a rigid body!"); + return .Err; + } + + // Construct transform matrix from our local space to the rigidbody space + rigidbodyTransform = rigidbodyTransform * walker.Transform.LocalTransform; + + walker = parent.Value; } - if (entity.TryGetComponent(let circleCollider)) + return .Ok; + } + + private void InitBoxCollider2D(Entity entity, BoxCollider2DComponent* boxCollider) + { + if (FindParentWithRigidbody(entity, let entityWithRigidbody, let rigidbody, let parentToRigidbody) case .Err) + return; + + let localToWorld = entity.Transform.WorldTransform; + let worldToRigidbody = entityWithRigidbody.Transform.WorldTransform.Invert(); + + let boxShape = Box2D.Shape.CreatePolygon(); + + Box2D.b2Vec2[4] points = .( + .(-1, -1), + .( 1, -1), + .( 1, 1), + .(-1, 1)); + + for (int i < 4) { - b2Shape* circleShape = Box2D.Shape.CreateCircle(); - Box2D.Shape.CircleSetPosition(circleShape, ref circleCollider.b2Offset); - Box2D.Shape.SetRadius(circleShape, circleCollider.Radius); + points[i] = ((float2)points[i] * boxCollider.Size + boxCollider.Offset); - b2FixtureDef fixtureDef = .(); - fixtureDef.shape = circleShape; - fixtureDef.density = circleCollider.Density; - fixtureDef.friction = circleCollider.Friction; - fixtureDef.restitution = circleCollider.Restitution; - fixtureDef.restitutionThreshold = circleCollider.RestitutionThreshold; + if (entity == entityWithRigidbody) + points[i] = entity.Transform.Scale.XY * (float2)points[i]; - b2Fixture* fixture = Box2D.Body.CreateFixture(body, &fixtureDef); - circleCollider.RuntimeFixture = fixture; + points[i] = (worldToRigidbody * localToWorld * float4(points[i], 0, 1)).XY; } + + Shape.PolygonSet(boxShape, &points, 4); + + b2FixtureDef fixtureDef = .(); + fixtureDef.shape = boxShape; + fixtureDef.density = boxCollider.Density; + fixtureDef.friction = boxCollider.Friction; + fixtureDef.restitution = boxCollider.Restitution; + fixtureDef.restitutionThreshold = boxCollider.RestitutionThreshold; + fixtureDef.userData = (void*)(uint)entity.Handle; + + Log.EngineLogger.AssertDebug(rigidbody.RuntimeBody != null); + b2Fixture* fixture = Box2D.Body.CreateFixture(rigidbody.RuntimeBody, &fixtureDef); + boxCollider.RuntimeFixture = fixture; + } + + private void InitCircleCollider2D(Entity entity, CircleCollider2DComponent* circleCollider) + { + if (FindParentWithRigidbody(entity, let entityWithRigidbody, let rigidbody, let parentToRigidbody) case .Err) + return; + + let localToWorld = entity.Transform.WorldTransform; + let worldToRigidbody = entityWithRigidbody.Transform.WorldTransform.Invert(); + + b2Vec2 center = (worldToRigidbody * localToWorld * float4(circleCollider.b2Offset, 0, 1)).XY; + + b2Shape* circleShape = Box2D.Shape.CreateCircle(); + Box2D.Shape.CircleSetPosition(circleShape, center); + Box2D.Shape.SetRadius(circleShape, circleCollider.Radius); + + b2FixtureDef fixtureDef = .(); + fixtureDef.shape = circleShape; + fixtureDef.density = circleCollider.Density; + fixtureDef.friction = circleCollider.Friction; + fixtureDef.restitution = circleCollider.Restitution; + fixtureDef.restitutionThreshold = circleCollider.RestitutionThreshold; + fixtureDef.userData = (void*)(uint)entity.Handle; + + Log.EngineLogger.AssertDebug(rigidbody.RuntimeBody != null); + b2Fixture* fixture = Box2D.Body.CreateFixture(rigidbody.RuntimeBody, &fixtureDef); + circleCollider.RuntimeFixture = fixture; } public void OnSimulationStop() @@ -335,8 +536,24 @@ namespace GlitchyEngine.World b2Vec2 position = Box2D.Body.GetPosition(body); float angle = Box2D.Body.GetAngle(body); - transform.Position = .(position.x, position.y, transform.Position.Z); - transform.RotationEuler = .(transform.RotationEuler.XY, angle); + if (entity.Parent != null) + { + Matrix worldToParent = entity.Parent.Value.Transform.WorldTransform.Invert(); + + float4 newLocalPosition = worldToParent * float4(position, 0, 1); + transform.Position = float3(newLocalPosition.XY, transform.Position.Z); + + // TODO: when the parent of the rigidbody-entity is rotated, the rotation is applied wrong... + Matrix.Decompose(worldToParent, let p, var worldToParentRotation, let s); + Quaternion newLocalRotation = (worldToParentRotation * Quaternion.FromEulerAngles(0, 0, angle))..Normalize(); + // TODO: when the parent has rotation on X or Y everything breaks even more... + transform.Rotation = (newLocalRotation * Quaternion.FromEulerAngles(transform.RotationEuler.Y, transform.RotationEuler.X, 0))..Normalize(); + } + else + { + transform.Position = .(position.x, position.y, transform.Position.Z); + transform.RotationEuler = .(transform.RotationEuler.XY, angle); + } } } } diff --git a/GlitchyEngine/src/World/SceneRenderer.bf b/GlitchyEngine/src/World/SceneRenderer.bf index 9ac079f..e310b01 100644 --- a/GlitchyEngine/src/World/SceneRenderer.bf +++ b/GlitchyEngine/src/World/SceneRenderer.bf @@ -192,6 +192,9 @@ class SceneRenderer DrawDebug2D(); + if (Scene._physicsWorld2D != null) + Box2D.World.DebugDraw(Scene._physicsWorld2D); + Renderer2D.EndScene(); // Gamma correct composit target and draw it into viewport diff --git a/ScriptCore/Components/RigidBody2D.cs b/ScriptCore/Components/RigidBody2D.cs index d79fdc7..4b8c045 100644 --- a/ScriptCore/Components/RigidBody2D.cs +++ b/ScriptCore/Components/RigidBody2D.cs @@ -2,7 +2,7 @@ using GlitchyEngine.Math; namespace GlitchyEngine; -public class RigidBody2D : Component +public class Rigidbody2D : Component { /// /// Apply a force at a world point. diff --git a/ScriptCore/Entity.cs b/ScriptCore/Entity.cs index d8f6f2e..e28756e 100644 --- a/ScriptCore/Entity.cs +++ b/ScriptCore/Entity.cs @@ -15,17 +15,13 @@ internal struct EntityHandle public class Entity : EngineObject { - //private UUID _uuid; - - //public UUID UUID => _uuid; - /// /// Empty constructor not used. Do NOT USE! /// protected Entity() { } - private Entity(UUID uuid) + internal Entity(UUID uuid) { _uuid = uuid; } diff --git a/ScriptCore/Physics/Collision2D.cs b/ScriptCore/Physics/Collision2D.cs new file mode 100644 index 0000000..3017195 --- /dev/null +++ b/ScriptCore/Physics/Collision2D.cs @@ -0,0 +1,35 @@ +using System.Runtime.InteropServices; +using GlitchyEngine.Core; + +namespace GlitchyEngine.Physics; + +[StructLayout(LayoutKind.Sequential, Pack=1)] +public struct Collision2D +{ + private UUID _entity; + private UUID _otherEntity; + + private UUID _rigidbody; + private UUID _otherRigidbody; + + /// + /// Gets the Entity whose Collider takes part in the collision. + /// This entity is either the entity of the script instance receiving the event or a child of it. + /// + public Entity Entity => new(_entity); + /// + /// Gets the other Entity whose collider takes part in the collision. + /// + public Entity OtherEntity => new(_otherEntity); + + /// + /// Gets the rigidbody whose Collider takes part in the collision. + /// This Rigidbody is either a component of the entity whose script instance received the event or a parent of it. + /// + public Rigidbody2D Rigidbody => new() { Entity = Entity }; + + /// + /// Gets the other rigidbody whose Collider takes part in the collision. + /// + public Rigidbody2D OtherRigidbody => new() { Entity = OtherEntity }; +} diff --git a/ScriptCore/ScriptCore.csproj b/ScriptCore/ScriptCore.csproj index 402ac00..aa5eb63 100644 --- a/ScriptCore/ScriptCore.csproj +++ b/ScriptCore/ScriptCore.csproj @@ -5,6 +5,7 @@ latest true + GlitchyEngine