diff --git a/Nuake/src/Physics/DynamicWorld.cpp b/Nuake/src/Physics/DynamicWorld.cpp index bc92c39c..b3a5ee4c 100644 --- a/Nuake/src/Physics/DynamicWorld.cpp +++ b/Nuake/src/Physics/DynamicWorld.cpp @@ -554,7 +554,7 @@ namespace Nuake } } - std::vector DynamicWorld::Raycast(const Vector3& from, const Vector3& to) + std::vector DynamicWorld::Raycast(const Vector3& from, const Vector3& to) { // Create jolt ray const auto& fromJolt = JPH::Vec3(from.x, from.y, from.z); @@ -566,22 +566,24 @@ namespace Nuake _JoltPhysicsSystem->GetNarrowPhaseQuery().CastRay(ray, JPH::RayCastSettings(), collector); // Fetch results - std::vector raycastResults; + std::vector raycastResults; if (collector.HadHit()) { int num_hits = (int)collector.mHits.size(); JPH::BroadPhaseCastResult* results = collector.mHits.data(); - // Format result for (int i = 0; i < num_hits; ++i) { const float hitFraction = results[i].mFraction; const JPH::Vec3& hitPosition = ray.GetPointOnRay(results[i].mFraction); - - RaycastResult result + auto bodyId = static_cast(results[i].mBodyID); + auto layer = _JoltBodyInterface->GetObjectLayer(bodyId); + ShapeCastResult result { Vector3(hitPosition.GetX(), hitPosition.GetY(), hitPosition.GetZ()), - hitFraction + hitFraction, + Vector3(0, 0, 0), + layer }; raycastResults.push_back(std::move(result)); diff --git a/Nuake/src/Physics/DynamicWorld.h b/Nuake/src/Physics/DynamicWorld.h index 0b6f06d8..4d6fee8e 100644 --- a/Nuake/src/Physics/DynamicWorld.h +++ b/Nuake/src/Physics/DynamicWorld.h @@ -84,7 +84,7 @@ namespace Nuake void MoveAndSlideCharacterController(const Entity& entity, const Vector3& velocity); void AddForceToRigidBody(Entity& entity, const Vector3& force); - std::vector Raycast(const Vector3& from, const Vector3& to); + std::vector Raycast(const Vector3& from, const Vector3& to); std::vector CastShape(const Vector3& from, const Vector3& to, const Ref& shape); void StepSimulation(Timestep ts); void Clear(); diff --git a/Nuake/src/Physics/PhysicsManager.cpp b/Nuake/src/Physics/PhysicsManager.cpp index 87a41da0..7fe6ec46 100644 --- a/Nuake/src/Physics/PhysicsManager.cpp +++ b/Nuake/src/Physics/PhysicsManager.cpp @@ -42,7 +42,7 @@ namespace Nuake m_World->Clear(); } - std::vector PhysicsManager::Raycast(const Vector3& from, const Vector3& to) + std::vector PhysicsManager::Raycast(const Vector3& from, const Vector3& to) { return m_World->Raycast(from, to); } diff --git a/Nuake/src/Physics/PhysicsManager.h b/Nuake/src/Physics/PhysicsManager.h index 37745732..3907e0d3 100644 --- a/Nuake/src/Physics/PhysicsManager.h +++ b/Nuake/src/Physics/PhysicsManager.h @@ -50,7 +50,7 @@ namespace Nuake void Reset(); - std::vector Raycast(const Vector3& from, const Vector3& to); + std::vector Raycast(const Vector3& from, const Vector3& to); std::vector Shapecast(const Vector3& from, const Vector3& to, const Ref& shape); const std::vector GetCollisions(); diff --git a/Nuake/src/Physics/RaycastResult.h b/Nuake/src/Physics/RaycastResult.h index 995914bc..4b5a1aeb 100644 --- a/Nuake/src/Physics/RaycastResult.h +++ b/Nuake/src/Physics/RaycastResult.h @@ -10,6 +10,8 @@ namespace Nuake { Vector3 WorldPosition; float Fraction; + Vector3 ImpactNormal; + float Layer; }; struct ShapeCastResult diff --git a/Nuake/src/Scripting/Modules/SceneModule.h b/Nuake/src/Scripting/Modules/SceneModule.h index a96a35df..704997ac 100644 --- a/Nuake/src/Scripting/Modules/SceneModule.h +++ b/Nuake/src/Scripting/Modules/SceneModule.h @@ -282,21 +282,6 @@ namespace Nuake const auto& result = PhysicsManager::Get().GetWorld()->Raycast(from, to); - // We multiply by 3 since we have 3 floats per hit result: vector3. - wrenEnsureSlots(vm, static_cast(result.size() * 3)); - wrenSetSlotNewList(vm, 0); - - uint32_t index = 1; - for (auto& r : result) - { - wrenSetSlotDouble(vm, index, r.WorldPosition.x); - wrenSetSlotDouble(vm, index + 1, r.WorldPosition.y); - wrenSetSlotDouble(vm, index + 2, r.WorldPosition.z); - wrenInsertInList(vm, 0, -1, index); - wrenInsertInList(vm, 0, -1, index + 1); - wrenInsertInList(vm, 0, -1, index + 2); - index += 3; - } } static void MoveAndSlide(WrenVM* vm) diff --git a/Nuake/src/Scripting/NetModules/EngineNetAPI.cpp b/Nuake/src/Scripting/NetModules/EngineNetAPI.cpp index 4fa59477..6f81674f 100644 --- a/Nuake/src/Scripting/NetModules/EngineNetAPI.cpp +++ b/Nuake/src/Scripting/NetModules/EngineNetAPI.cpp @@ -73,6 +73,14 @@ namespace Nuake { return Coral::Array::New(results); } + Coral::Array Raycast(float fromX, float fromY, float fromZ, float toX, float toY, float toZ) + { + const Vector3 from = { fromX, fromY, fromZ }; + const Vector3 to = { toX, toY, toZ }; + auto hits = PhysicsManager::Get().Raycast(from, to); + return ConvertHitsToArray(hits); + } + Coral::Array ShapeCastCapsule(float fromX, float fromY, float fromZ, float toX, float toY, float toZ, CapsuleInternal capsuleInternal) { auto capsule = CreateRef(capsuleInternal.Radius, capsuleInternal.Height); @@ -104,6 +112,7 @@ namespace Nuake { RegisterMethod("Debug.DrawShapeCapsuleIcall", &DrawShapeCapsule); RegisterMethod("Debug.DrawShapeCylinderIcall", &DrawShapeCylinder); + RegisterMethod("Physic.RayCastIcall", &Raycast); RegisterMethod("Physic.ShapeCastCapsuleIcall", &ShapeCastCapsule); RegisterMethod("Physic.ShapeCastBoxIcall", &ShapeCastBox); } diff --git a/Nuake/src/Scripting/ScriptingEngineNet.cpp b/Nuake/src/Scripting/ScriptingEngineNet.cpp index e5c0bb49..2203bf9b 100644 --- a/Nuake/src/Scripting/ScriptingEngineNet.cpp +++ b/Nuake/src/Scripting/ScriptingEngineNet.cpp @@ -343,106 +343,109 @@ namespace Nuake } } - const std::string baseTypeName = std::string(type->GetBaseType().GetFullName()); - if (baseTypeName != "Nuake.Net.Entity") + if (type->GetBaseType()) { - continue; - } - - m_BaseEntityType = type->GetBaseType(); - - auto typeSplits = String::Split(type->GetFullName(), '.'); - std::string shortenedTypeName = typeSplits[typeSplits.size() - 1]; - - NetGameScriptObject gameScriptObject; - gameScriptObject.coralType = type; - gameScriptObject.exposedVars = std::vector(); - gameScriptObject.Base = baseTypeName; - for (auto& f : type->GetFields()) - { - for (auto& a : f.GetAttributes()) + const std::string baseTypeName = std::string(type->GetBaseType().GetFullName()); + if (baseTypeName != "Nuake.Net.Entity") { - if (a.GetType() == exposedFieldAttributeType) + continue; + } + + m_BaseEntityType = type->GetBaseType(); + + auto typeSplits = String::Split(type->GetFullName(), '.'); + std::string shortenedTypeName = typeSplits[typeSplits.size() - 1]; + + NetGameScriptObject gameScriptObject; + gameScriptObject.coralType = type; + gameScriptObject.exposedVars = std::vector(); + gameScriptObject.Base = baseTypeName; + for (auto& f : type->GetFields()) + { + for (auto& a : f.GetAttributes()) { - ExposedVar exposedVar; - exposedVar.Name = f.GetName(); - - auto typeName = f.GetType().GetFullName(); - ExposedVarTypes varType = ExposedVarTypes::Unsupported; - bool hasDefaultValue = a.GetFieldValue("HasDefaultvalue"); - if (typeName == "System.Single") + if (a.GetType() == exposedFieldAttributeType) { - varType = ExposedVarTypes::Float; + ExposedVar exposedVar; + exposedVar.Name = f.GetName(); - if (hasDefaultValue) + auto typeName = f.GetType().GetFullName(); + ExposedVarTypes varType = ExposedVarTypes::Unsupported; + bool hasDefaultValue = a.GetFieldValue("HasDefaultvalue"); + if (typeName == "System.Single") { - exposedVar.Value = a.GetFieldValue("DefaultValueInternalFloat"); - } - } - else if (typeName == "System.Double") - { - varType = ExposedVarTypes::Double; - } - else if (typeName == "System.String") - { - varType = ExposedVarTypes::String; + varType = ExposedVarTypes::Float; - if (hasDefaultValue) + if (hasDefaultValue) + { + exposedVar.Value = a.GetFieldValue("DefaultValueInternalFloat"); + } + } + else if (typeName == "System.Double") { - exposedVar.Value = a.GetFieldValue("DefaultValueInternalString"); + varType = ExposedVarTypes::Double; } - } - else if (typeName == "System.Boolean") - { - varType = ExposedVarTypes::Bool; - - if (hasDefaultValue) + else if (typeName == "System.String") { - exposedVar.Value = a.GetFieldValue("DefaultValueInternalBool"); + varType = ExposedVarTypes::String; + + if (hasDefaultValue) + { + exposedVar.Value = a.GetFieldValue("DefaultValueInternalString"); + } } - } - else if (typeName == "System.Numerics.Vector2") - { - varType = ExposedVarTypes::Vector2; - } - else if (typeName == "System.Numerics.Vector3") - { - varType = ExposedVarTypes::Vector3; - } - else if (typeName == "Nuake.Net.Entity") - { - varType = ExposedVarTypes::Entity; - } - else if (typeName == "Nuake.Net.Prefab") - { - varType = ExposedVarTypes::Prefab; - } + else if (typeName == "System.Boolean") + { + varType = ExposedVarTypes::Bool; - if (varType != ExposedVarTypes::Unsupported) - { - exposedVar.Type = varType; - gameScriptObject.exposedVars.push_back(exposedVar); - } + if (hasDefaultValue) + { + exposedVar.Value = a.GetFieldValue("DefaultValueInternalBool"); + } + } + else if (typeName == "System.Numerics.Vector2") + { + varType = ExposedVarTypes::Vector2; + } + else if (typeName == "System.Numerics.Vector3") + { + varType = ExposedVarTypes::Vector3; + } + else if (typeName == "Nuake.Net.Entity") + { + varType = ExposedVarTypes::Entity; + } + else if (typeName == "Nuake.Net.Prefab") + { + varType = ExposedVarTypes::Prefab; + } - Logger::Log("Exposed field detected: " + std::string(f.GetName()) + " of type " + std::string(f.GetType().GetFullName()) ); + if (varType != ExposedVarTypes::Unsupported) + { + exposedVar.Type = varType; + gameScriptObject.exposedVars.push_back(exposedVar); + } + + Logger::Log("Exposed field detected: " + std::string(f.GetName()) + " of type " + std::string(f.GetType().GetFullName())); + } } } - } - // Add to the brush map to retrieve when exporting FGD - if (isBrushScript) - { - gameScriptObject.Description = brushDescription; - gameScriptObject.isTrigger = isTrigger; - m_BrushEntityTypes[shortenedTypeName] = gameScriptObject; - } + // Add to the brush map to retrieve when exporting FGD + if (isBrushScript) + { + gameScriptObject.Description = brushDescription; + gameScriptObject.isTrigger = isTrigger; + m_BrushEntityTypes[shortenedTypeName] = gameScriptObject; + } - if (isPointScript) - { - gameScriptObject.Description = pointDescription; - m_PointEntityTypes[shortenedTypeName] = gameScriptObject; + if (isPointScript) + { + gameScriptObject.Description = pointDescription; + m_PointEntityTypes[shortenedTypeName] = gameScriptObject; + } + m_GameEntityTypes[shortenedTypeName] = gameScriptObject; } - m_GameEntityTypes[shortenedTypeName] = gameScriptObject; } } diff --git a/NuakeNet/src/Entity.cs b/NuakeNet/src/Entity.cs index 3c0320d2..f8b06dbc 100644 --- a/NuakeNet/src/Entity.cs +++ b/NuakeNet/src/Entity.cs @@ -88,8 +88,21 @@ namespace Nuake.Net } } - public string Target { get { unsafe { return EntityGetTargetIcall(ECSHandle); } }} + protected TransformComponent internalTransform; + public TransformComponent Transform + { + get + { + if(internalTransform == null) + { + internalTransform = GetComponent()!; + } + return internalTransform; + } + } + + public string Target { get { unsafe { return EntityGetTargetIcall(ECSHandle); } }} public int ID { get; set; } public int ECSHandle { get; set; } = -1; diff --git a/NuakeNet/src/Physic.cs b/NuakeNet/src/Physic.cs index cf20b474..c5a65219 100644 --- a/NuakeNet/src/Physic.cs +++ b/NuakeNet/src/Physic.cs @@ -9,6 +9,7 @@ using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using static Nuake.Net.Physic; namespace Nuake.Net { @@ -118,10 +119,36 @@ namespace Nuake.Net SENSORS = 5 } + internal static unsafe delegate*> RayCastIcall; internal static unsafe delegate*> ShapeCastBoxIcall; internal static unsafe delegate*> ShapeCastSphereIcall; internal static unsafe delegate*> ShapeCastCapsuleIcall; internal static unsafe delegate*> ShapeCastCylinderIcall; + + public static List RayCast(Vector3 from, Vector3 to) + { + List result = []; + unsafe + { + NativeArray resultICall = RayCastIcall(from.X, from.Y, from.Z, to.X, to.Y, to.Z); + for (int i = 0; i < resultICall.Length / 7; i++) + { + int index = i * 7; + ShapeCastResult shapeCastResult = new() + { + ImpactPosition = new Vector3(resultICall[index + 0], resultICall[index + 1], resultICall[index + 2]), + ImpactNormal = new Vector3(resultICall[index + 3], resultICall[index + 4], resultICall[index + 5]), + Fraction = resultICall[index + 6], + Layer = (Layers)resultICall[index + 7] + }; + + result.Add(shapeCastResult); + } + + return result; + } + } + public static List ShapeCast(Vector3 from, Vector3 to, Box box) { List result = [];