diff --git a/Editor/resources/Images/logo_white.png b/Editor/resources/Images/logo_white.png new file mode 100644 index 00000000..2d7621fd Binary files /dev/null and b/Editor/resources/Images/logo_white.png differ diff --git a/Editor/src/ComponentsPanel/BoxColliderPanel.h b/Editor/src/ComponentsPanel/BoxColliderPanel.h index 0aeaf3da..05ba27e5 100644 --- a/Editor/src/ComponentsPanel/BoxColliderPanel.h +++ b/Editor/src/ComponentsPanel/BoxColliderPanel.h @@ -20,9 +20,15 @@ public: ImGui::Text("Size"); ImGui::TableNextColumn(); - ImGuiHelper::DrawVec3("BoxSize", &component.Size); + ImGuiHelper::DrawVec3("BoxSize", &component.Size, 0.5f, 100.0, 0.01f); + component.Size = glm::abs(component.Size); + + component.Size.x = std::max(component.Size.x, 0.0001f); + component.Size.y = std::max(component.Size.y, 0.0001f); + component.Size.z = std::max(component.Size.z, 0.0001f); + ImGui::TableNextColumn(); - ComponentTableReset(component.Size, glm::vec3(1, 1, 1)); + ComponentTableReset(component.Size, glm::vec3(0.5f, 0.5f, 0.5f)); } ImGui::TableNextColumn(); { diff --git a/Editor/src/ComponentsPanel/CapsuleColliderPanel.h b/Editor/src/ComponentsPanel/CapsuleColliderPanel.h index 631a8410..b9b6678d 100644 --- a/Editor/src/ComponentsPanel/CapsuleColliderPanel.h +++ b/Editor/src/ComponentsPanel/CapsuleColliderPanel.h @@ -23,7 +23,8 @@ public: { ImGui::Text("Radius"); ImGui::TableNextColumn(); - ImGui::DragFloat("##Radius", &Radius); + ImGui::DragFloat("##Radius", &Radius, 0.01f, 0.001f); + Radius = std::max(Radius, 0.001f); ImGui::TableNextColumn(); ComponentTableReset(Radius, 0.5f) } @@ -31,8 +32,8 @@ public: { ImGui::Text("Height"); ImGui::TableNextColumn(); - - ImGui::DragFloat("##Height", &Height); + ImGui::DragFloat("##Height", &Height, 0.01f, 0.001f); + Height = std::max(Height, 0.001f); ImGui::TableNextColumn(); ComponentTableReset(Height, 1.0f) } diff --git a/Editor/src/ComponentsPanel/CylinderColliderPanel.h b/Editor/src/ComponentsPanel/CylinderColliderPanel.h new file mode 100644 index 00000000..ccf8468d --- /dev/null +++ b/Editor/src/ComponentsPanel/CylinderColliderPanel.h @@ -0,0 +1,43 @@ +#pragma once +#include "ComponentPanel.h" + +#include + +class CylinderColliderPanel : ComponentPanel +{ +public: + CylinderColliderPanel() = default; + + void Draw(Nuake::Entity entity) override + { + using namespace Nuake; + + if (!entity.HasComponent()) + { + return; + } + + auto& [Cylinder, Radius, Height, IsTrigger] = entity.GetComponent(); + BeginComponentTable(CYLINDER COLLIDER, CylinderColliderComponent) + { + { + ImGui::Text("Radius"); + ImGui::TableNextColumn(); + ImGui::DragFloat("##Radius", &Radius, 0.01f, 0.001f); + Radius = std::max(Radius, 0.001f); + ImGui::TableNextColumn(); + ComponentTableReset(Radius, 0.5f) + } + ImGui::TableNextColumn(); + { + ImGui::Text("Height"); + ImGui::TableNextColumn(); + ImGui::DragFloat("##Height", &Height, 0.01f, 0.0001f); + Height = std::max(Height, 0.001f); + ImGui::TableNextColumn(); + ComponentTableReset(Height, 1.0f) + } + } + EndComponentTable() + } +}; \ No newline at end of file diff --git a/Editor/src/ComponentsPanel/MeshColliderPanel.h b/Editor/src/ComponentsPanel/MeshColliderPanel.h index b0cd959f..bfbe5012 100644 --- a/Editor/src/ComponentsPanel/MeshColliderPanel.h +++ b/Editor/src/ComponentsPanel/MeshColliderPanel.h @@ -31,7 +31,10 @@ public: ImGui::Text("Model"); ImGui::TableNextColumn(); - ImGui::DragInt("##Submesh", &component.SubMesh, 0, 255); + int editorValue = component.SubMesh; + ImGui::DragInt("##Submesh", &editorValue, 0.1f, 0, 255); + component.SubMesh = editorValue; + ImGui::TableNextColumn(); ComponentTableReset(component.SubMesh, 0); } diff --git a/Editor/src/ComponentsPanel/RigidbodyPanel.h b/Editor/src/ComponentsPanel/RigidbodyPanel.h index 5b4b07b8..1803fbd4 100644 --- a/Editor/src/ComponentsPanel/RigidbodyPanel.h +++ b/Editor/src/ComponentsPanel/RigidbodyPanel.h @@ -20,7 +20,8 @@ public: ImGui::Text("Mass"); ImGui::TableNextColumn(); - ImGui::DragFloat("##Mass", &component.Mass, 0.1f, 0.1f); + ImGui::DragFloat("##Mass", &component.Mass, 0.01f, 0.1f); + component.Mass = std::max(component.Mass, 0.0f); ImGui::TableNextColumn(); ComponentTableReset(component.Mass, 0.0f); } diff --git a/Editor/src/ComponentsPanel/SphereColliderPanel.h b/Editor/src/ComponentsPanel/SphereColliderPanel.h index 0a92c5cd..5033b7db 100644 --- a/Editor/src/ComponentsPanel/SphereColliderPanel.h +++ b/Editor/src/ComponentsPanel/SphereColliderPanel.h @@ -19,7 +19,9 @@ public: { ImGui::Text("Size"); ImGui::TableNextColumn(); - ImGui::DragFloat("##Radius", &component.Radius); + ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f); + + component.Radius = std::max(component.Radius, 0.001f); ImGui::TableNextColumn(); ComponentTableReset(component.Radius, 0.5f); } diff --git a/Editor/src/Misc/GizmoDrawer.cpp b/Editor/src/Misc/GizmoDrawer.cpp index 3a9524ee..5ea50b5c 100644 --- a/Editor/src/Misc/GizmoDrawer.cpp +++ b/Editor/src/Misc/GizmoDrawer.cpp @@ -13,6 +13,10 @@ #include #include "src/Scene/Components/CapsuleColliderComponent.h" +#include +#include +#include + GizmoDrawer::GizmoDrawer() { @@ -29,7 +33,46 @@ GizmoDrawer::GizmoDrawer() mAxisLineBuffer->AddBuffer(*mAxisLineVertexBuffer, *vblayout); GenerateSphereGizmo(); - GenerateCapsuleGizmo(); + + // Box + const Color cubeColor = Color(1, 0, 0, 1); + std::vector mBoxVertices = + { + LineVertex{Vector3(-1.f, -1.f, -1.f), cubeColor}, + LineVertex{Vector3(1.0f, -1.f, -1.f), cubeColor}, + LineVertex{Vector3(-1.f, -1.f, 1.f), cubeColor}, + LineVertex{Vector3(1.0f, -1.f, 1.f), cubeColor}, + LineVertex{Vector3(-1.f, 1.f, -1.f), cubeColor}, + LineVertex{Vector3(1.0f, 1.f, -1.f), cubeColor}, + LineVertex{Vector3(-1.f, 1.f, 1.f), cubeColor}, + LineVertex{Vector3(1.0f, 1.f, 1.f), cubeColor}, + + LineVertex{Vector3(-1.f, -1.f, -1.f), cubeColor}, + LineVertex{Vector3(-1.0f, -1.f, 1.f), cubeColor}, + LineVertex{Vector3(1.f, -1.f, -1.f), cubeColor}, + LineVertex{Vector3(1.0f, -1.f, 1.f), cubeColor}, + LineVertex{Vector3(-1.f, 1.f, -1.f), cubeColor}, + LineVertex{Vector3(-1.0f, 1.f, 1.f), cubeColor}, + LineVertex{Vector3(1.f, 1.f, -1.f), cubeColor}, + LineVertex{Vector3(1.0f, 1.f, 1.f), cubeColor}, + + LineVertex{Vector3(-1.0f, -1.0f, -1.f), cubeColor}, + LineVertex{Vector3(-1.f, 1.0f, -1.f), cubeColor}, + LineVertex{Vector3(1.0f, -1.0f, -1.f), cubeColor}, + LineVertex{Vector3(1.f, 1.0f, -1.f), cubeColor}, + LineVertex{Vector3(-1.0f, -1.0f, 1.f), cubeColor}, + LineVertex{Vector3(-1.f, 1.0f, 1.f), cubeColor}, + LineVertex{Vector3(1.0f, -1.0f, 1.f), cubeColor}, + LineVertex{Vector3(1.0f, 1.0f, 1.f), cubeColor} + }; + + mBoxBuffer = CreateRef(); + mBoxBuffer->Bind(); + + mBoxVertexBuffer = CreateRef(mBoxVertices.data(), mBoxVertices.size() * sizeof(Nuake::LineVertex)); + + mBoxBuffer->AddBuffer(*mBoxVertexBuffer, *vblayout); + // Load gizmos ModelLoader loader; @@ -66,8 +109,9 @@ void GizmoDrawer::GenerateSphereGizmo() vert1 = Vector3(x, 0, z); vert2 = Vector3(x2, 0, z2); } - circleVertices.push_back(LineVertex{ vert1, Color(1.0, 0, 0.7, 1.0) }); - circleVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.7, 1.0) }); + + circleVertices.push_back(LineVertex{ vert1, Color(1.0, 0, 0.0, 1.0) }); + circleVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.0, 1.0) }); } mCircleBuffer = CreateRef(); @@ -81,101 +125,6 @@ void GizmoDrawer::GenerateSphereGizmo() mCircleBuffer->AddBuffer(*mCircleVertexBuffer, *vblayout); } -void GizmoDrawer::GenerateCapsuleGizmo() -{ - float height = 1.5f; - float radius = 0.5f; - - float halfHeight = height / 2.0f; - - float bottomCircleHeight = -halfHeight + radius; - float topCircleHeight = halfHeight - radius; - - // Generate circles - const float subDivision = 32.0f; - constexpr const float pi = glm::pi() * 4.0; - float increment = pi / subDivision; - for (int i = 0; i < subDivision * 2.0; i++) - { - float current = increment * (i); - float x = glm::cos(current) * radius; - float z = glm::sin(current) * radius; - - current = increment * (i + 1); - float x2 = glm::cos(current) * radius; - float z2 = glm::sin(current) * radius; - - Vector3 vert1, vert2; - if (i < subDivision) - { - vert1 = Vector3(x, topCircleHeight, z); - vert2 = Vector3(x2, topCircleHeight, z2); - } - else - { - vert1 = Vector3(x, bottomCircleHeight, z); - vert2 = Vector3(x2, bottomCircleHeight, z2); - } - - capsuleVertices.push_back(LineVertex{ vert1, Color(1.0, 0, 0.7, 1.0) }); - capsuleVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.7, 1.0) }); - } - - for (int i = 0; i < subDivision * 2.0; i++) - { - float current = increment * (i); - float x = glm::cos(current) * radius; - float z = glm::sin(current) * radius; - - current = increment * (i + 1); - float x2 = glm::cos(current) * radius; - float z2 = glm::sin(current) * radius; - - float heightOffset = topCircleHeight; - if (z < 0.0) - { - heightOffset = bottomCircleHeight; - } - - Vector3 vert1, vert2; - if (i < subDivision) - { - vert1 = Vector3(x, z + heightOffset, 0); - vert2 = Vector3(x2, z2 + heightOffset, 0); - } - else - { - vert1 = Vector3(0, z + heightOffset, x); - vert2 = Vector3(0, z2 + heightOffset, x2 ); - } - - capsuleVertices.push_back(LineVertex{ vert1, Color(1.0, 0, 0.7, 1.0) }); - capsuleVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.7, 1.0) }); - } - - capsuleVertices.push_back(LineVertex{ Vector3(radius, bottomCircleHeight, 0), Color(1.0, 0, 0.7, 1.0)}); - capsuleVertices.push_back(LineVertex{ Vector3(radius, topCircleHeight, 0), Color(1.0, 0, 0.7, 1.0) }); - - capsuleVertices.push_back(LineVertex{ Vector3(-radius, bottomCircleHeight, 0), Color(1.0, 0, 0.7, 1.0) }); - capsuleVertices.push_back(LineVertex{ Vector3(-radius, topCircleHeight, 0), Color(1.0, 0, 0.7, 1.0) }); - - capsuleVertices.push_back(LineVertex{ Vector3(0, bottomCircleHeight, radius), Color(1.0, 0, 0.7, 1.0) }); - capsuleVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, radius), Color(1.0, 0, 0.7, 1.0) }); - - capsuleVertices.push_back(LineVertex{ Vector3(0, bottomCircleHeight, -radius), Color(1.0, 0, 0.7, 1.0) }); - capsuleVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, -radius), Color(1.0, 0, 0.7, 1.0) }); - - mCapsuleBuffer = CreateRef(); - mCapsuleBuffer->Bind(); - - mCapsuleVertexBuffer = CreateRef(capsuleVertices.data(), capsuleVertices.size() * sizeof(Nuake::LineVertex)); - auto vblayout = CreateRef(); - vblayout->Push(3); - vblayout->Push(4); - - mCapsuleBuffer->AddBuffer(*mCapsuleVertexBuffer, *vblayout); -} - void GizmoDrawer::DrawGizmos(Ref scene) { using namespace Nuake; @@ -191,6 +140,23 @@ void GizmoDrawer::DrawGizmos(Ref scene) Nuake::RenderCommand::DrawLines(0, 6); } + glLineWidth(2.0f); + auto boxColliderView = scene->m_Registry.view(); + for (auto e : boxColliderView) + { + auto [transform, box] = scene->m_Registry.get(e); + + const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation()); + const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation); + + mLineShader->Bind(); + mLineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), transform.Translation) * rotationMatrix, box.Size)); + mLineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); + + mBoxBuffer->Bind(); + Nuake::RenderCommand::DrawLines(0, 26); + } + auto sphereColliderView = scene->m_Registry.view(); for (auto e : sphereColliderView) { @@ -206,15 +172,83 @@ void GizmoDrawer::DrawGizmos(Ref scene) auto capsuleColliderView = scene->m_Registry.view(); for (auto e : capsuleColliderView) { - auto [transform, capsule] = scene->m_Registry.get(e); + auto& [transform, capsule] = scene->m_Registry.get(e); + + const auto entityId = (uint32_t)e; + if (_CapsuleEntity.find(entityId) == _CapsuleEntity.end()) + { + _CapsuleEntity[entityId] = CreateScope(); + } + + _CapsuleEntity[entityId]->UpdateShape(capsule.Radius, capsule.Height); + + const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation()); + const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation); + mLineShader->Bind(); - mLineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), transform.Translation)); + mLineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), transform.Translation) * rotationMatrix); mLineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); - mCapsuleBuffer->Bind(); + _CapsuleEntity[entityId]->Bind(); Nuake::RenderCommand::DrawLines(0, 264); } + auto cylinderColliderView = scene->m_Registry.view(); + for (auto e : cylinderColliderView) + { + auto& [transform, cylinder] = scene->m_Registry.get(e); + + const auto entityId = (uint32_t)e; + if (_CylinderEntity.find(entityId) == _CylinderEntity.end()) + { + _CylinderEntity[entityId] = CreateScope(); + } + + _CylinderEntity[entityId]->UpdateShape(cylinder.Radius, cylinder.Height); + + const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation()); + const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation); + + mLineShader->Bind(); + mLineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), transform.Translation) * rotationMatrix); + mLineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); + + _CylinderEntity[entityId]->Bind(); + Nuake::RenderCommand::DrawLines(0, 264); + } + + auto meshColliderView = scene->m_Registry.view(); + for (auto e : meshColliderView) + { + auto& [transform, mesh, model] = scene->m_Registry.get(e); + + // Component has no mesh set. + if (!model.ModelResource) + { + continue; + } + + auto& resource = model.ModelResource; + + const auto& meshes = resource->GetMeshes(); + if (mesh.SubMesh >= meshes.size()) + { + continue; + } + + const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation()); + const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation); + + mLineShader->Bind(); + mLineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), transform.Translation) * rotationMatrix); + mLineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective()); + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + meshes[mesh.SubMesh]->Bind(); + meshes[mesh.SubMesh]->Draw(nullptr, false); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + auto flatShader = ShaderManager::GetShader("resources/Shaders/flat.shader"); flatShader->Bind(); flatShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform()); @@ -225,6 +259,7 @@ void GizmoDrawer::DrawGizmos(Ref scene) RenderCommand::Enable(RendererEnum::FACE_CULL); glCullFace(GL_BACK); + glLineWidth(1.0f); RenderList renderList; // Camera diff --git a/Editor/src/Misc/GizmoDrawer.h b/Editor/src/Misc/GizmoDrawer.h index c7fa213a..e16faafa 100644 --- a/Editor/src/Misc/GizmoDrawer.h +++ b/Editor/src/Misc/GizmoDrawer.h @@ -6,6 +6,10 @@ #include #include #include +#include + +#include "Gizmos/CapsuleGizmo.h" +#include "Gizmos/CylinderGizmo.h" using namespace Nuake; @@ -14,6 +18,9 @@ class GizmoDrawer private: std::map> _gizmos; + std::map> _CapsuleEntity; + std::map> _CylinderEntity; + const std::vector vertices { LineVertex {{10000.f, 0.0f, 0.0f}, {1.f, 0.f, 0.f, 1.f}}, @@ -27,9 +34,9 @@ private: Ref mCircleBuffer; Ref mCircleVertexBuffer; - std::vector capsuleVertices; - Ref mCapsuleBuffer; - Ref mCapsuleVertexBuffer; + std::vector mBoxVertices; + Ref mBoxBuffer; + Ref mBoxVertexBuffer; Ref mAxisLineBuffer; Ref mAxisLineVertexBuffer; @@ -37,7 +44,6 @@ private: Shader* mLineShader; void GenerateSphereGizmo(); - void GenerateCapsuleGizmo(); public: GizmoDrawer(); ~GizmoDrawer() = default; diff --git a/Editor/src/Misc/Gizmos/CapsuleGizmo.cpp b/Editor/src/Misc/Gizmos/CapsuleGizmo.cpp new file mode 100644 index 00000000..abb3fd4e --- /dev/null +++ b/Editor/src/Misc/Gizmos/CapsuleGizmo.cpp @@ -0,0 +1,122 @@ +#include "CapsuleGizmo.h" + +#include + +CapsuleGizmo::CapsuleGizmo() : + _Radius(0.0f), + _Height(0.0f) +{ +} + +void CapsuleGizmo::Bind() +{ + _CapsuleBuffer->Bind(); +} + +void CapsuleGizmo::UpdateShape(float radius, float height) +{ + if (_Radius == radius && _Height == height) + { + return; + } + + _Radius = radius; + _Height = height; + CreateMesh(); +} + +void CapsuleGizmo::CreateMesh() +{ + using namespace Nuake; + + _CapsuleVertices.clear(); + + const float halfHeight = _Height / 2.0f; + const float radius = _Radius; + const float bottomCircleHeight = -halfHeight + radius; + const float topCircleHeight = halfHeight - radius; + + // Generate circles + const float subDivision = 32.0f; + constexpr const float pi = glm::pi() * 4.0; + float increment = pi / subDivision; + for (int i = 0; i < subDivision * 2.0; i++) + { + float current = increment * (i); + float x = glm::cos(current) * radius; + float z = glm::sin(current) * radius; + + current = increment * (i + 1); + float x2 = glm::cos(current) * radius; + float z2 = glm::sin(current) * radius; + + Vector3 vert1, vert2; + if (i < subDivision) + { + vert1 = Vector3(x, topCircleHeight, z); + vert2 = Vector3(x2, topCircleHeight, z2); + } + else + { + vert1 = Vector3(x, bottomCircleHeight, z); + vert2 = Vector3(x2, bottomCircleHeight, z2); + } + + _CapsuleVertices.push_back(LineVertex{ vert1, Color(1.0, 0, 0.0, 1.0) }); + _CapsuleVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.0, 1.0) }); + } + + for (int i = 0; i < subDivision * 2.0; i++) + { + float current = increment * (i); + float x = glm::cos(current) * radius; + float z = glm::sin(current) * radius; + + current = increment * (i + 1); + float x2 = glm::cos(current) * radius; + float z2 = glm::sin(current) * radius; + + float heightOffset = topCircleHeight; + if (z < 0.0) + { + heightOffset = bottomCircleHeight; + } + + Vector3 vert1, vert2; + if (i < subDivision) + { + vert1 = Vector3(x, z + heightOffset, 0); + vert2 = Vector3(x2, z2 + heightOffset, 0); + } + else + { + vert1 = Vector3(0, z + heightOffset, x); + vert2 = Vector3(0, z2 + heightOffset, x2); + } + + _CapsuleVertices.push_back(LineVertex{ vert1, Color(1.0, 0, 0.0, 1.0) }); + _CapsuleVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.0, 1.0) }); + } + + _CapsuleVertices.push_back(LineVertex{ Vector3(radius, bottomCircleHeight, 0), Color(1.0, 0, 0.0, 1.0) }); + _CapsuleVertices.push_back(LineVertex{ Vector3(radius, topCircleHeight, 0), Color(1.0, 0, 0.0, 1.0) }); + + _CapsuleVertices.push_back(LineVertex{ Vector3(-radius, bottomCircleHeight, 0), Color(1.0, 0, 0.0, 1.0) }); + _CapsuleVertices.push_back(LineVertex{ Vector3(-radius, topCircleHeight, 0), Color(1.0, 0, 0.0, 1.0) }); + + _CapsuleVertices.push_back(LineVertex{ Vector3(0, bottomCircleHeight, radius), Color(1.0, 0, 0.0, 1.0) }); + _CapsuleVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, radius), Color(1.0, 0, 0.0, 1.0) }); + + _CapsuleVertices.push_back(LineVertex{ Vector3(0, bottomCircleHeight, -radius), Color(1.0, 0, 0.0, 1.0) }); + _CapsuleVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, -radius), Color(1.0, 0, 0.0, 1.0) }); + + _CapsuleBuffer = CreateRef(); + _CapsuleBuffer->Bind(); + + _CapsuleVertexBuffer = CreateRef(_CapsuleVertices.data(), _CapsuleVertices.size() * sizeof(Nuake::LineVertex)); + auto vblayout = CreateRef(); + vblayout->Push(3); + vblayout->Push(4); + + _CapsuleBuffer->AddBuffer(*_CapsuleVertexBuffer, *vblayout); +} \ No newline at end of file diff --git a/Editor/src/Misc/Gizmos/CapsuleGizmo.h b/Editor/src/Misc/Gizmos/CapsuleGizmo.h new file mode 100644 index 00000000..6bb825ea --- /dev/null +++ b/Editor/src/Misc/Gizmos/CapsuleGizmo.h @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include +#include + +#include + +class CapsuleGizmo +{ +private: + std::vector _CapsuleVertices; + Ref _CapsuleBuffer; + Ref _CapsuleVertexBuffer; + + float _Radius; + float _Height; + +public: + CapsuleGizmo(); + ~CapsuleGizmo() = default; + + void UpdateShape(float radius, float height); + void CreateMesh(); + void Bind(); +}; \ No newline at end of file diff --git a/Editor/src/Misc/Gizmos/CylinderGizmo.cpp b/Editor/src/Misc/Gizmos/CylinderGizmo.cpp new file mode 100644 index 00000000..dc86ce3d --- /dev/null +++ b/Editor/src/Misc/Gizmos/CylinderGizmo.cpp @@ -0,0 +1,90 @@ +#include "CylinderGizmo.h" + +#include + +CylinderGizmo::CylinderGizmo() : + _Radius(0.0f), + _Height(0.0f) +{ +} + +void CylinderGizmo::Bind() +{ + _CylinderBuffer->Bind(); +} + +void CylinderGizmo::UpdateShape(float radius, float height) +{ + if (_Radius == radius && _Height == height) + { + return; + } + + _Radius = radius; + _Height = height; + CreateMesh(); +} + +void CylinderGizmo::CreateMesh() +{ + using namespace Nuake; + + _CylinderVertices.clear(); + + const float halfHeight = _Height / 2.0f; + const float radius = _Radius; + const float bottomCircleHeight = -halfHeight; + const float topCircleHeight = halfHeight; + + // Generate circles + const float subDivision = 32.0f; + constexpr const float pi = glm::pi() * 4.0; + float increment = pi / subDivision; + for (int i = 0; i < subDivision * 2.0; i++) + { + float current = increment * (i); + float x = glm::cos(current) * radius; + float z = glm::sin(current) * radius; + + current = increment * (i + 1); + float x2 = glm::cos(current) * radius; + float z2 = glm::sin(current) * radius; + + Vector3 vert1, vert2; + if (i < subDivision) + { + vert1 = Vector3(x, topCircleHeight, z); + vert2 = Vector3(x2, topCircleHeight, z2); + } + else + { + vert1 = Vector3(x, bottomCircleHeight, z); + vert2 = Vector3(x2, bottomCircleHeight, z2); + } + + _CylinderVertices.push_back(LineVertex{ vert1, Color(1.0, 0, 0.0, 1.0) }); + _CylinderVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.0, 1.0) }); + } + + _CylinderVertices.push_back(LineVertex{ Vector3(radius, bottomCircleHeight, 0), Color(1.0, 0, 0.0, 1.0) }); + _CylinderVertices.push_back(LineVertex{ Vector3(radius, topCircleHeight, 0), Color(1.0, 0, 0.0, 1.0) }); + + _CylinderVertices.push_back(LineVertex{ Vector3(-radius, bottomCircleHeight, 0), Color(1.0, 0, 0.0, 1.0) }); + _CylinderVertices.push_back(LineVertex{ Vector3(-radius, topCircleHeight, 0), Color(1.0, 0, 0.0, 1.0) }); + + _CylinderVertices.push_back(LineVertex{ Vector3(0, bottomCircleHeight, radius), Color(1.0, 0, 0.0, 1.0) }); + _CylinderVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, radius), Color(1.0, 0, 0.0, 1.0) }); + + _CylinderVertices.push_back(LineVertex{ Vector3(0, bottomCircleHeight, -radius), Color(1.0, 0, 0.0, 1.0) }); + _CylinderVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, -radius), Color(1.0, 0, 0.0, 1.0) }); + + _CylinderBuffer = CreateRef(); + _CylinderBuffer->Bind(); + + _CylinderVertexBuffer = CreateRef(_CylinderVertices.data(), _CylinderVertices.size() * sizeof(Nuake::LineVertex)); + auto vblayout = CreateRef(); + vblayout->Push(3); + vblayout->Push(4); + + _CylinderBuffer->AddBuffer(*_CylinderVertexBuffer, *vblayout); +} \ No newline at end of file diff --git a/Editor/src/Misc/Gizmos/CylinderGizmo.h b/Editor/src/Misc/Gizmos/CylinderGizmo.h new file mode 100644 index 00000000..cecb7c6e --- /dev/null +++ b/Editor/src/Misc/Gizmos/CylinderGizmo.h @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include +#include + +#include + +class CylinderGizmo +{ +private: + std::vector _CylinderVertices; + Ref _CylinderBuffer; + Ref _CylinderVertexBuffer; + + float _Radius; + float _Height; + +public: + CylinderGizmo(); + ~CylinderGizmo() = default; + + void UpdateShape(float radius, float height); + void CreateMesh(); + void Bind(); +}; \ No newline at end of file diff --git a/Editor/src/Windows/EditorInterface.cpp b/Editor/src/Windows/EditorInterface.cpp index 5af71753..1731eddf 100644 --- a/Editor/src/Windows/EditorInterface.cpp +++ b/Editor/src/Windows/EditorInterface.cpp @@ -1219,7 +1219,6 @@ namespace Nuake { } ImGui::PopStyleVar(); ImGui::End(); - int corner2 = 1; diff --git a/Editor/src/Windows/EditorInterface.h b/Editor/src/Windows/EditorInterface.h index 8a50f5c3..57f5ac94 100644 --- a/Editor/src/Windows/EditorInterface.h +++ b/Editor/src/Windows/EditorInterface.h @@ -23,7 +23,7 @@ namespace Nuake bool m_DrawGrid = false; bool m_DrawAxis = true; bool m_ShowImGuiDemo = false; - bool m_DebugCollisions = false; + bool m_DebugCollisions = true; bool m_ShowOverlay = true; bool m_IsHoveringViewport = false; Vector2 m_ViewportPos = {0, 0}; @@ -59,5 +59,6 @@ namespace Nuake void Overlay(); bool ShouldDrawAxis() const { return m_DrawAxis; } + bool ShouldDrawCollision() const { return m_DebugCollisions; } }; } diff --git a/Editor/src/Windows/EditorSelectionPanel.cpp b/Editor/src/Windows/EditorSelectionPanel.cpp index 8409401b..639a8948 100644 --- a/Editor/src/Windows/EditorSelectionPanel.cpp +++ b/Editor/src/Windows/EditorSelectionPanel.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include EditorSelectionPanel::EditorSelectionPanel() @@ -60,7 +61,7 @@ void EditorSelectionPanel::Draw(EditorSelection selection) ResolveFile(selection.File); } - DrawFile(selection.File.get()); + DrawFile(selection.File); break; } case EditorSelectionType::Resource: @@ -102,6 +103,7 @@ void EditorSelectionPanel::DrawEntity(Nuake::Entity entity) mBoxColliderPanel.Draw(entity); mSphereColliderPanel.Draw(entity); mCapsuleColliderPanel.Draw(entity); + mCylinderColliderPanel.Draw(entity); mMeshColliderPanel.Draw(entity); mCharacterControllerPanel.Draw(entity); } @@ -126,8 +128,10 @@ void EditorSelectionPanel::DrawAddComponentMenu(Nuake::Entity entity) ImGui::Separator(); MenuItemComponent("Character Controller", Nuake::CharacterControllerComponent) MenuItemComponent("Rigid body", Nuake::RigidBodyComponent) + ImGui::Separator(); MenuItemComponent("Box collider", Nuake::BoxColliderComponent) MenuItemComponent("Capsule collider", Nuake::CapsuleColliderComponent) + MenuItemComponent("Cylinder collider", Nuake::CylinderColliderComponent) MenuItemComponent("Sphere collider", Nuake::SphereColliderComponent) MenuItemComponent("Mesh collider", Nuake::MeshColliderComponent) ImGui::Separator(); @@ -139,8 +143,7 @@ void EditorSelectionPanel::DrawAddComponentMenu(Nuake::Entity entity) } - -void EditorSelectionPanel::DrawFile(Nuake::File* file) +void EditorSelectionPanel::DrawFile(Ref file) { using namespace Nuake; if (file->GetExtension() == ".material") @@ -151,6 +154,10 @@ void EditorSelectionPanel::DrawFile(Nuake::File* file) { DrawProjectPanel(Nuake::Engine::GetProject()); } + if (file->GetExtension() == ".wren") + { + DrawWrenScriptPanel(CreateRef(file, true)); + } } void EditorSelectionPanel::DrawResource(Nuake::Resource resource) @@ -415,3 +422,23 @@ void EditorSelectionPanel::DrawProjectPanel(Ref project) ImGui::InputText("Trenchbroom Path", &project->TrenchbroomPath); } +void EditorSelectionPanel::DrawWrenScriptPanel(Ref wrenFile) +{ + auto filePath = wrenFile->GetFile()->GetAbsolutePath(); + std::string fileContent = Nuake::FileSystem::ReadFile(filePath, true); + + ImGui::Text("Content"); + ImGui::SameLine(ImGui::GetWindowWidth()-90); + if(ImGui::Button("Open...")) + { + Nuake::OS::OpenIn(filePath); + } + + ImGui::Separator(); + + ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetWindowWidth()); + ImGui::Text(fileContent.c_str(), ImGui::GetWindowWidth()); + + ImGui::PopTextWrapPos(); +} + diff --git a/Editor/src/Windows/EditorSelectionPanel.h b/Editor/src/Windows/EditorSelectionPanel.h index ff19422a..88b2cd7b 100644 --- a/Editor/src/Windows/EditorSelectionPanel.h +++ b/Editor/src/Windows/EditorSelectionPanel.h @@ -14,6 +14,7 @@ #include "../ComponentsPanel/RigidbodyPanel.h" #include "../ComponentsPanel/BoxColliderPanel.h" #include "../ComponentsPanel/CapsuleColliderPanel.h" +#include "../ComponentsPanel/CylinderColliderPanel.h" #include "../ComponentsPanel/SphereColliderPanel.h" #include "../ComponentsPanel/MeshColliderPanel.h" #include "../ComponentsPanel/CharacterControllerPanel.h" @@ -31,6 +32,7 @@ private: SphereColliderPanel mSphereColliderPanel; MeshColliderPanel mMeshColliderPanel; CapsuleColliderPanel mCapsuleColliderPanel; + CylinderColliderPanel mCylinderColliderPanel; CharacterControllerPanel mCharacterControllerPanel; @@ -46,11 +48,12 @@ public: void DrawEntity(Nuake::Entity entity); void DrawAddComponentMenu(Nuake::Entity entity); - void DrawFile(Nuake::File* file); + void DrawFile(Ref file); void DrawResource(Nuake::Resource resource); private: void ResolveFile(Ref file); void DrawMaterialPanel(Ref material); void DrawProjectPanel(Ref project); + void DrawWrenScriptPanel(Ref wrenFile); }; \ No newline at end of file diff --git a/Editor/src/Windows/FileSystemUI.cpp b/Editor/src/Windows/FileSystemUI.cpp index 3eb90511..1a07bf03 100644 --- a/Editor/src/Windows/FileSystemUI.cpp +++ b/Editor/src/Windows/FileSystemUI.cpp @@ -180,16 +180,29 @@ namespace Nuake { OS::ShowInFileExplorer(file->GetAbsolutePath()); } - - ImGui::Separator(); - - if (ImGui::MenuItem("Delete")) + + if(file->GetExtension() == ".wren") { - if(FileSystem::RemoveFile(file->GetAbsolutePath()) != 0) + ImGui::Separator(); + + if(ImGui::MenuItem("Open...")) { - Logger::Log("Failed to remove file: " + file->GetRelativePath(), CRITICAL); + OS::OpenIn(file->GetAbsolutePath()); + } + } + + if(file->GetExtension() != ".project") + { + ImGui::Separator(); + + if (ImGui::MenuItem("Delete")) + { + if(FileSystem::RemoveFile(file->GetAbsolutePath()) != 0) + { + Logger::Log("Failed to remove file: " + file->GetRelativePath(), CRITICAL); + } + RefreshFileBrowser(); } - RefreshFileBrowser(); } ImGui::EndPopup(); diff --git a/Nuake/src/Core/OS.cpp b/Nuake/src/Core/OS.cpp index 40721cda..a59ee64c 100644 --- a/Nuake/src/Core/OS.cpp +++ b/Nuake/src/Core/OS.cpp @@ -10,6 +10,11 @@ int OS::GetTime() return static_cast(std::chrono::system_clock::now().time_since_epoch().count()); } +void OS::OpenIn(const std::string& filePath) +{ + ShellExecuteA(nullptr, "open", filePath.c_str(), nullptr, nullptr, SW_SHOWDEFAULT); +} + void OS::ShowInFileExplorer(const std::string& filePath) { ShellExecuteA(nullptr, "open", "explorer.exe", ("/select," + std::string(filePath)).c_str(), nullptr, SW_SHOWDEFAULT); diff --git a/Nuake/src/Core/OS.h b/Nuake/src/Core/OS.h index c2fdbaf3..71f80d21 100644 --- a/Nuake/src/Core/OS.h +++ b/Nuake/src/Core/OS.h @@ -8,6 +8,7 @@ namespace Nuake { public: static int GetTime(); + static void OpenIn(const std::string& filePath); static void ShowInFileExplorer(const std::string& filePath); }; } diff --git a/Nuake/src/Core/Physics/PhysicsShapes.h b/Nuake/src/Core/Physics/PhysicsShapes.h index f21c28b3..49e3b167 100644 --- a/Nuake/src/Core/Physics/PhysicsShapes.h +++ b/Nuake/src/Core/Physics/PhysicsShapes.h @@ -49,6 +49,7 @@ namespace Nuake float Radius; float Height; public: + Capsule() = default; Capsule(float radius, float height) : Radius(radius), Height(height) diff --git a/Nuake/src/Rendering/Mesh/Mesh.cpp b/Nuake/src/Rendering/Mesh/Mesh.cpp index 1d847f44..fce1fcd5 100644 --- a/Nuake/src/Rendering/Mesh/Mesh.cpp +++ b/Nuake/src/Rendering/Mesh/Mesh.cpp @@ -91,6 +91,11 @@ namespace Nuake m_VertexArray->Unbind(); } + void Mesh::Bind() const + { + m_VertexArray->Bind(); + } + void Mesh::Draw(Shader* shader, bool bindMaterial) { if (bindMaterial) diff --git a/Nuake/src/Rendering/Mesh/Mesh.h b/Nuake/src/Rendering/Mesh/Mesh.h index 68458ca2..5e6ecaf1 100644 --- a/Nuake/src/Rendering/Mesh/Mesh.h +++ b/Nuake/src/Rendering/Mesh/Mesh.h @@ -25,6 +25,7 @@ namespace Nuake Ref GetMaterial() inline const; void SetMaterial(Ref material); + void Bind() const; void Draw(Shader* shader, bool bindMaterial = true); void DebugDraw(); diff --git a/Nuake/src/Scene/Components/CapsuleColliderComponent.h b/Nuake/src/Scene/Components/CapsuleColliderComponent.h index c6c482d0..359bf02f 100644 --- a/Nuake/src/Scene/Components/CapsuleColliderComponent.h +++ b/Nuake/src/Scene/Components/CapsuleColliderComponent.h @@ -7,7 +7,7 @@ namespace Nuake class CapsuleColliderComponent { public: - Ref Capsule; + Ref Capsule; float Radius = 0.5f; float Height = 1.0f; diff --git a/Nuake/src/Scene/Components/Components.h b/Nuake/src/Scene/Components/Components.h index 614f5c7d..8b40a93a 100644 --- a/Nuake/src/Scene/Components/Components.h +++ b/Nuake/src/Scene/Components/Components.h @@ -8,11 +8,15 @@ #include "CameraComponent.h" #include "ModelComponent.h" #include "QuakeMap.h" + #include "RigidbodyComponent.h" +#include "CharacterControllerComponent.h" + #include "SphereCollider.h" #include "MeshCollider.h" +#include "CylinderColliderComponent.h" #include "NativeScriptComponent.h" -#include "CharacterControllerComponent.h" + #include "ParentComponent.h" #include "NameComponent.h" #include "BoxCollider.h" diff --git a/Nuake/src/Scene/Components/CylinderColliderComponent.cpp b/Nuake/src/Scene/Components/CylinderColliderComponent.cpp new file mode 100644 index 00000000..58c905ed --- /dev/null +++ b/Nuake/src/Scene/Components/CylinderColliderComponent.cpp @@ -0,0 +1,24 @@ +#include "CylinderColliderComponent.h" +#include "src/Resource/Serializable.h" + +namespace Nuake +{ + json CylinderColliderComponent::Serialize() + { + BEGIN_SERIALIZE() + + j["IsTrigger"] = IsTrigger; + SERIALIZE_VAL(Radius) + SERIALIZE_VAL(Height) + END_SERIALIZE() + } + + bool CylinderColliderComponent::Deserialize(const std::string& str) + { + BEGIN_DESERIALIZE() + this->IsTrigger = j["IsTrigger"]; + this->Radius = j["Radius"]; + this->Height = j["Height"]; + return true; + } +} \ No newline at end of file diff --git a/Nuake/src/Scene/Components/CylinderColliderComponent.h b/Nuake/src/Scene/Components/CylinderColliderComponent.h new file mode 100644 index 00000000..54e9146e --- /dev/null +++ b/Nuake/src/Scene/Components/CylinderColliderComponent.h @@ -0,0 +1,20 @@ +#pragma once +#include "src/Core/Physics/PhysicsShapes.h" +#include "src/Core/Core.h" + +namespace Nuake +{ + class CylinderColliderComponent + { + public: + Ref Cylinder; + + float Radius = 0.5f; + float Height = 1.0f; + + bool IsTrigger = false; + + json Serialize(); + bool Deserialize(const std::string& str); + }; +} diff --git a/Nuake/src/Scene/Components/MeshCollider.h b/Nuake/src/Scene/Components/MeshCollider.h index c821d5b8..eaca94cc 100644 --- a/Nuake/src/Scene/Components/MeshCollider.h +++ b/Nuake/src/Scene/Components/MeshCollider.h @@ -6,7 +6,7 @@ namespace Nuake { class MeshColliderComponent { public: - int SubMesh = 0; + uint32_t SubMesh = 0; bool IsTrigger; Ref Shape; diff --git a/Nuake/src/Scene/Entities/Entity.cpp b/Nuake/src/Scene/Entities/Entity.cpp index e187c3a8..30c9583a 100644 --- a/Nuake/src/Scene/Entities/Entity.cpp +++ b/Nuake/src/Scene/Entities/Entity.cpp @@ -49,6 +49,8 @@ namespace Nuake SERIALIZE_OBJECT_REF_LBL("BoxColliderComponent", GetComponent()) if (HasComponent()) SERIALIZE_OBJECT_REF_LBL("CapsuleColliderComponent", GetComponent()) + if (HasComponent()) + SERIALIZE_OBJECT_REF_LBL("CylinderColliderComponent", GetComponent()) if (HasComponent()) SERIALIZE_OBJECT_REF_LBL("SphereColliderComponent", GetComponent()) if (HasComponent()) @@ -84,6 +86,7 @@ namespace Nuake DESERIALIZE_COMPONENT(CharacterControllerComponent) DESERIALIZE_COMPONENT(BoxColliderComponent) DESERIALIZE_COMPONENT(CapsuleColliderComponent) + DESERIALIZE_COMPONENT(CylinderColliderComponent) DESERIALIZE_COMPONENT(MeshColliderComponent) DESERIALIZE_COMPONENT(SphereColliderComponent) DESERIALIZE_COMPONENT(RigidBodyComponent) diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index 3979488f..ca524e05 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -95,7 +95,6 @@ namespace Nuake { Logger::Log("Init system"); if (!system->Init()) { - return false; } } diff --git a/Nuake/src/Scene/Systems/PhysicsSystem.cpp b/Nuake/src/Scene/Systems/PhysicsSystem.cpp index a1eecbd5..2f5e0ff7 100644 --- a/Nuake/src/Scene/Systems/PhysicsSystem.cpp +++ b/Nuake/src/Scene/Systems/PhysicsSystem.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace Nuake { @@ -174,6 +175,15 @@ namespace Nuake capsuleComponent.Capsule = CreateRef(radius, height); } + const auto cylinderView = m_Scene->m_Registry.view(); + for (auto entity : cylinderView) + { + auto& cylinderComponent = cylinderView.get(entity); + float radius = cylinderComponent.Radius; + float height = cylinderComponent.Height; + cylinderComponent.Cylinder = CreateRef(radius, height); + } + const auto sphereView = m_Scene->m_Registry.view(); for (auto entity : sphereView) { @@ -238,6 +248,17 @@ namespace Nuake PhysicsManager::Get().RegisterBody(rigidBody); } + if (ent.HasComponent()) + { + auto& cylinderComponent = ent.GetComponent(); + float radius = cylinderComponent.Radius; + float height = cylinderComponent.Height; + auto cylinderShape = CreateRef(radius, height); + + rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalRotation(), transform.GetGlobalTransform(), cylinderShape, ent); + PhysicsManager::Get().RegisterBody(rigidBody); + } + if (ent.HasComponent()) { float mass = rigidBodyComponent.Mass; diff --git a/Nuake/src/Scripting/WrenScript.cpp b/Nuake/src/Scripting/WrenScript.cpp index aadb1d8a..61bacc56 100644 --- a/Nuake/src/Scripting/WrenScript.cpp +++ b/Nuake/src/Scripting/WrenScript.cpp @@ -164,6 +164,11 @@ namespace Nuake WrenInterpretResult result = wrenCall(vm, handle); } + Ref WrenScript::GetFile() const + { + return mFile; + } + void WrenScript::SetScriptableEntityID(int id) { if (!m_HasCompiledSuccesfully) diff --git a/Nuake/src/Scripting/WrenScript.h b/Nuake/src/Scripting/WrenScript.h index 7a5c5009..8a3d03e8 100644 --- a/Nuake/src/Scripting/WrenScript.h +++ b/Nuake/src/Scripting/WrenScript.h @@ -40,6 +40,7 @@ namespace Nuake void RegisterMethod(const std::string& signature); void CallMethod(const std::string& signature); + Ref GetFile() const; void SetScriptableEntityID(int id); bool HasCompiledSuccesfully() const { return m_HasCompiledSuccesfully; }