add 2D physics (use box2d), fixed some little bugs
This commit is contained in:
@ -4,6 +4,10 @@
|
||||
|
||||
#include "EditorLayer.h"
|
||||
#include "ImGuizmo.h"
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <filesystem>
|
||||
|
||||
#include "glm/gtx/matrix_decompose.hpp"
|
||||
#include "Prism/Core/Input.h"
|
||||
#include "Prism/Renderer/Renderer2D.h"
|
||||
#include "Prism/Script/ScriptEngine.h"
|
||||
@ -12,97 +16,131 @@ namespace Prism
|
||||
{
|
||||
enum class PropertyFlag
|
||||
{
|
||||
None = 0, ColorProperty = 1
|
||||
None = 0, ColorProperty = 1, SliderProperty = 2, DragProperty = 4
|
||||
};
|
||||
|
||||
static std::tuple<glm::vec3, glm::quat, glm::vec3> GetTransformDecomposition(const glm::mat4& transform)
|
||||
{
|
||||
glm::vec3 scale, translation, skew;
|
||||
glm::vec4 perspective;
|
||||
glm::quat orientation;
|
||||
glm::decompose(transform, scale, orientation, translation, skew, perspective);
|
||||
|
||||
return { translation, orientation, scale };
|
||||
}
|
||||
|
||||
bool Property(const std::string& name, bool& value)
|
||||
{
|
||||
ImGui::Text(name.c_str());
|
||||
ImGui::NextColumn();
|
||||
ImGui::PushItemWidth(-1);
|
||||
const std::string id = "##" + name;
|
||||
const bool result = ImGui::Checkbox(id.c_str(), &value);
|
||||
const bool isChanged = ImGui::Checkbox(id.c_str(), &value);
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::NextColumn();
|
||||
|
||||
return result;
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
void Property(const std::string& name, float& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None)
|
||||
bool Property(const std::string& name, float& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None)
|
||||
{
|
||||
ImGui::Text(name.c_str());
|
||||
ImGui::NextColumn();
|
||||
ImGui::PushItemWidth(-1);
|
||||
|
||||
const std::string id = "##" + name;
|
||||
ImGui::SliderFloat(id.c_str(), &value, min, max);
|
||||
|
||||
bool isChanged = false;
|
||||
if (flags == PropertyFlag::SliderProperty)
|
||||
isChanged = ImGui::SliderFloat(id.c_str(), &value, min, max);
|
||||
else
|
||||
isChanged = ImGui::DragFloat(id.c_str(), &value, 1.0f, min, max);
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::NextColumn();
|
||||
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
|
||||
void Property(const std::string& name, glm::vec3& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None)
|
||||
bool Property(const std::string& name, glm::vec3& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None)
|
||||
{
|
||||
ImGui::Text(name.c_str());
|
||||
ImGui::NextColumn();
|
||||
ImGui::PushItemWidth(-1);
|
||||
|
||||
std::string id = "##" + name;
|
||||
if ((int)flags & (int)PropertyFlag::ColorProperty)
|
||||
ImGui::ColorEdit3(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs);
|
||||
bool isChanged = false;
|
||||
if (flags == PropertyFlag::ColorProperty)
|
||||
isChanged = ImGui::ColorEdit3(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs);
|
||||
else if (flags == PropertyFlag::SliderProperty)
|
||||
isChanged = ImGui::SliderFloat3(id.c_str(), glm::value_ptr(value), min, max);
|
||||
else
|
||||
ImGui::SliderFloat3(id.c_str(), glm::value_ptr(value), min, max);
|
||||
isChanged = ImGui::DragFloat3(id.c_str(), glm::value_ptr(value), 1.0f, min, max);
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::NextColumn();
|
||||
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
void Property(const std::string& name, glm::vec3& value, PropertyFlag flags)
|
||||
bool Property(const std::string& name, glm::vec3& value, PropertyFlag flags)
|
||||
{
|
||||
Property(name, value, -1.0f, 1.0f, flags);
|
||||
return Property(name, value, -1.0f, 1.0f, flags);
|
||||
}
|
||||
|
||||
|
||||
void Property(const std::string& name, glm::vec4& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None)
|
||||
bool Property(const std::string& name, glm::vec4& value, const float min = -1.0f, const float max = 1.0f, PropertyFlag flags = PropertyFlag::None)
|
||||
{
|
||||
ImGui::Text(name.c_str());
|
||||
ImGui::NextColumn();
|
||||
ImGui::PushItemWidth(-1);
|
||||
|
||||
std::string id = "##" + name;
|
||||
if ((int)flags & (int)PropertyFlag::ColorProperty)
|
||||
ImGui::ColorEdit4(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs);
|
||||
bool isChanged = false;
|
||||
|
||||
if (flags == PropertyFlag::ColorProperty)
|
||||
isChanged = ImGui::ColorEdit4(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs);
|
||||
else if (flags == PropertyFlag::SliderProperty)
|
||||
isChanged = ImGui::SliderFloat4(id.c_str(), glm::value_ptr(value), min, max);
|
||||
else
|
||||
ImGui::SliderFloat4(id.c_str(), glm::value_ptr(value), min, max);
|
||||
isChanged = ImGui::DragFloat4(id.c_str(), glm::value_ptr(value), 1.0f, min, max);
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::NextColumn();
|
||||
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
void Property(const std::string& name, glm::vec4& value, const PropertyFlag flags)
|
||||
bool Property(const std::string& name, glm::vec4& value, const PropertyFlag flags)
|
||||
{
|
||||
Property(name, value, -1.0f, 1.0f, flags);
|
||||
return Property(name, value, -1.0f, 1.0f, flags);
|
||||
}
|
||||
|
||||
|
||||
void Property(const std::string& name, glm::vec2& value, const float min, const float max, PropertyFlag flags)
|
||||
bool Property(const std::string& name, glm::vec2& value, const float min, const float max, PropertyFlag flags)
|
||||
{
|
||||
ImGui::Text(name.c_str());
|
||||
ImGui::NextColumn();
|
||||
ImGui::PushItemWidth(-1);
|
||||
|
||||
const std::string id = "##" + name;
|
||||
ImGui::SliderFloat2(id.c_str(), glm::value_ptr(value), min, max);
|
||||
bool isChanged = false;
|
||||
if (flags == PropertyFlag::SliderProperty)
|
||||
isChanged = ImGui::SliderFloat2(id.c_str(), glm::value_ptr(value), min, max);
|
||||
else
|
||||
isChanged = ImGui::DragFloat2(id.c_str(), glm::value_ptr(value), 1.0f, min, max);
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::NextColumn();
|
||||
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
void Property(const std::string& name, glm::vec2& value, const PropertyFlag flags)
|
||||
bool Property(const std::string& name, glm::vec2& value, const PropertyFlag flags)
|
||||
{
|
||||
Property(name, value, -1.0f, 1.0f, flags);
|
||||
return Property(name, value, -1.0f, 1.0f, flags);
|
||||
}
|
||||
|
||||
|
||||
@ -139,7 +177,7 @@ namespace Prism
|
||||
m_SceneHierarchyPanel = CreateScope<SceneHierarchyPanel>(m_EditorScene);
|
||||
m_SceneHierarchyPanel->SetSelectionChangedCallback(std::bind(&EditorLayer::SelectEntity, this, std::placeholders::_1));
|
||||
m_SceneHierarchyPanel->SetEntityDeletedCallback(std::bind(&EditorLayer::OnEntityDeleted, this, std::placeholders::_1));
|
||||
|
||||
UpdateWindowTitle("untitled Scene");
|
||||
}
|
||||
|
||||
void EditorLayer::OnDetach()
|
||||
@ -152,7 +190,7 @@ namespace Prism
|
||||
{
|
||||
case SceneState::Edit:
|
||||
{
|
||||
if (m_ViewportPanelFocused)
|
||||
// if (m_ViewportPanelFocused)
|
||||
m_EditorCamera.OnUpdate(deltaTime);
|
||||
|
||||
m_EditorScene->OnRenderEditor(deltaTime, m_EditorCamera);
|
||||
@ -167,7 +205,7 @@ namespace Prism
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
if (m_SelectionContext.size() && false)
|
||||
if (!m_SelectionContext.empty() && false)
|
||||
{
|
||||
auto& selection = m_SelectionContext[0];
|
||||
|
||||
@ -182,6 +220,25 @@ namespace Prism
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_SelectionContext.empty())
|
||||
{
|
||||
auto& selection = m_SelectionContext[0];
|
||||
|
||||
if (selection.Entity.HasComponent<BoxCollider2DComponent>())
|
||||
{
|
||||
const auto& size = selection.Entity.GetComponent<BoxCollider2DComponent>().Size;
|
||||
auto [translation, rotationQuat, scale] = GetTransformDecomposition(selection.Entity.GetComponent<TransformComponent>().Transform);
|
||||
const glm::vec3 rotation = glm::eulerAngles(rotationQuat);
|
||||
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
auto viewProj = m_EditorCamera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
Renderer2D::DrawRotatedQuad({ translation.x, translation.y }, size * 2.0f, glm::degrees(rotation.z), { 1.0f, 0.0f, 1.0f, 1.0f });
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -209,7 +266,6 @@ namespace Prism
|
||||
void EditorLayer::OnImGuiRender()
|
||||
{
|
||||
|
||||
#if ENABLE_DOCKSPACE
|
||||
|
||||
static bool p_open = true;
|
||||
static bool opt_fullscreen = true;
|
||||
@ -284,6 +340,9 @@ namespace Prism
|
||||
SceneSerializer serializer(newScene);
|
||||
serializer.Deserialize(filepath);
|
||||
m_EditorScene = newScene;
|
||||
std::filesystem::path path = filepath;
|
||||
UpdateWindowTitle(path.filename().string());
|
||||
|
||||
m_SceneHierarchyPanel->SetContext(m_EditorScene);
|
||||
ScriptEngine::SetSceneContext(m_EditorScene);
|
||||
|
||||
@ -297,28 +356,82 @@ namespace Prism
|
||||
std::string filepath = app.SaveFile(R"(Scene file (*.hsc)*.hsc)");
|
||||
SceneSerializer serializer(m_EditorScene);
|
||||
serializer.Serialize(filepath);
|
||||
|
||||
std::filesystem::path path = filepath;
|
||||
UpdateWindowTitle(path.filename().string());
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
/*
|
||||
if (ImGui::MenuItem("Reload C# Assembly"))
|
||||
ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll");
|
||||
*/
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Exit"))
|
||||
p_open = false;
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Script"))
|
||||
{
|
||||
if (ImGui::MenuItem("Reload C# Assembly"))
|
||||
ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll");
|
||||
|
||||
ImGui::MenuItem("Reload assembly on play", nullptr, &m_ReloadScriptOnPlay);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
m_SceneHierarchyPanel->OnImGuiRender();
|
||||
|
||||
ImGui::Begin("Materials");
|
||||
|
||||
if (!m_SelectionContext.empty())
|
||||
{
|
||||
Entity selectedEntity = m_SelectionContext.front().Entity;
|
||||
if (selectedEntity.HasComponent<MeshComponent>())
|
||||
{
|
||||
Ref<Mesh> mesh = selectedEntity.GetComponent<MeshComponent>().Mesh;
|
||||
if (mesh)
|
||||
{
|
||||
const auto& materials = mesh->GetMaterials();
|
||||
static uint32_t selectedMaterialIndex = 0;
|
||||
for (uint32_t i = 0; i < materials.size(); i++)
|
||||
{
|
||||
const auto& materialInstance = materials[i];
|
||||
|
||||
ImGuiTreeNodeFlags node_flags = (selectedMaterialIndex == i ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_Leaf;
|
||||
bool opened = ImGui::TreeNodeEx((void*)(&materialInstance), node_flags, "%s", materialInstance->GetName().c_str());
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
selectedMaterialIndex = i;
|
||||
}
|
||||
if (opened)
|
||||
ImGui::TreePop();
|
||||
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (selectedMaterialIndex < materials.size())
|
||||
{
|
||||
ImGui::Text("Shader: %s", materials[selectedMaterialIndex]->GetShader()->GetName().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
|
||||
|
||||
ScriptEngine::OnImGuiRender();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
#endif
|
||||
|
||||
// Editor Panel ------------------------------------------------------------------------------
|
||||
ImGui::Begin("Model");
|
||||
@ -338,13 +451,30 @@ namespace Prism
|
||||
ImGui::AlignTextToFramePadding();
|
||||
|
||||
auto& light = m_EditorScene->GetLight();
|
||||
Property("Light Direction", light.Direction);
|
||||
Property("Light Direction", light.Direction, PropertyFlag::SliderProperty);
|
||||
Property("Light Radiance", light.Radiance, PropertyFlag::ColorProperty);
|
||||
Property("Light Multiplier", light.Multiplier, 0.0f, 5.0f);
|
||||
Property("Exposure", m_EditorCamera.GetExposure(), 0.0f, 5.0f);
|
||||
Property("Light Multiplier", light.Multiplier, 0.0f, 5.0f, PropertyFlag::SliderProperty);
|
||||
Property("Exposure", m_EditorCamera.GetExposure(), 0.0f, 5.0f, PropertyFlag::SliderProperty);
|
||||
|
||||
Property("Radiance Prefiltering", m_RadiancePrefilter);
|
||||
Property("Env Map Rotation", m_EnvMapRotation, -360.0f, 360.0f);
|
||||
Property("Env Map Rotation", m_EnvMapRotation, -360.0f, 360.0f, PropertyFlag::SliderProperty);
|
||||
|
||||
if (m_SceneState == SceneState::Edit)
|
||||
{
|
||||
float physics2DGravity = m_EditorScene->GetPhysics2DGravity();
|
||||
if (Property("Gravity", physics2DGravity, -10000.0f, 10000.0f, PropertyFlag::DragProperty))
|
||||
{
|
||||
m_EditorScene->SetPhysics2DGravity(physics2DGravity);
|
||||
}
|
||||
}
|
||||
else if (m_SceneState == SceneState::Play)
|
||||
{
|
||||
float physics2DGravity = m_RuntimeScene->GetPhysics2DGravity();
|
||||
if (Property("Gravity", physics2DGravity, -10000.0f, 10000.0f, PropertyFlag::DragProperty))
|
||||
{
|
||||
m_RuntimeScene->SetPhysics2DGravity(physics2DGravity);
|
||||
}
|
||||
}
|
||||
|
||||
if (Property("Show Bounding Boxes", m_UIShowBoundingBoxes))
|
||||
ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop);
|
||||
@ -732,7 +862,8 @@ namespace Prism
|
||||
bool EditorLayer::OnMouseButtonPressedEvent(MouseButtonPressedEvent& e)
|
||||
{
|
||||
auto [mx, my] = Input::GetMousePosition();
|
||||
if (e.GetMouseButton() == PM_MOUSE_BUTTON_LEFT && !Input::IsKeyPressed(KeyCode::LEFT_ALT) && !ImGuizmo::IsOver())
|
||||
|
||||
if (e.GetMouseButton() == PM_MOUSE_BUTTON_LEFT && !Input::IsKeyPressed(KeyCode::LEFT_ALT) && !ImGuizmo::IsOver() && m_SceneState != SceneState::Play)
|
||||
{
|
||||
auto [mouseX, mouseY] = GetMouseViewportSpace();
|
||||
if (mouseX > -1.0f && mouseX < 1.0f && mouseY > -1.0f && mouseY < 1.0f)
|
||||
@ -809,6 +940,13 @@ namespace Prism
|
||||
m_EditorScene->SetSelectedEntity(entity);
|
||||
}
|
||||
|
||||
void EditorLayer::UpdateWindowTitle(const std::string &sceneName)
|
||||
{
|
||||
|
||||
const std::string title = sceneName + " - Prism - " + Application::GetPlatformName() + " (" + Application::GetConfigurationName() + ")";
|
||||
Application::Get().GetWindow().SetTitle(title);
|
||||
}
|
||||
|
||||
std::pair<float, float> EditorLayer::GetMouseViewportSpace() const
|
||||
{
|
||||
auto [mx, my] = ImGui::GetMousePos(); // Input::GetMousePosition();
|
||||
@ -866,6 +1004,9 @@ namespace Prism
|
||||
|
||||
m_SceneState = SceneState::Play;
|
||||
|
||||
if (m_ReloadScriptOnPlay)
|
||||
ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll");
|
||||
|
||||
m_RuntimeScene = Ref<Scene>::Create();
|
||||
m_EditorScene->CopyTo(m_RuntimeScene);
|
||||
|
||||
|
||||
@ -28,6 +28,8 @@ namespace Prism
|
||||
|
||||
void ShowBoundingBoxes(bool show, bool onTop = false);
|
||||
void SelectEntity(Entity entity);
|
||||
|
||||
void UpdateWindowTitle(const std::string& sceneName);
|
||||
private:
|
||||
std::pair<float, float> GetMouseViewportSpace() const;
|
||||
std::pair<glm::vec3, glm::vec3> CastRay(float mx, float my);
|
||||
@ -49,6 +51,7 @@ namespace Prism
|
||||
|
||||
Ref<Scene> m_ActiveScene;
|
||||
Ref<Scene> m_RuntimeScene, m_EditorScene;
|
||||
bool m_ReloadScriptOnPlay = false;
|
||||
|
||||
EditorCamera m_EditorCamera;
|
||||
|
||||
|
||||
BIN
Editor/assets/meshes/Cube1m.fbx
Normal file
BIN
Editor/assets/meshes/Cube1m.fbx
Normal file
Binary file not shown.
Binary file not shown.
174
Editor/assets/scenes/Physics2DTest.hsc
Normal file
174
Editor/assets/scenes/Physics2DTest.hsc
Normal file
@ -0,0 +1,174 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetPath: assets/env/pink_sunrise_4k.hdr
|
||||
Light:
|
||||
Direction: [-0.787, -0.73299998, 1]
|
||||
Radiance: [1, 1, 1]
|
||||
Multiplier: 0.514999986
|
||||
Entities:
|
||||
- Entity: 15861629587505754
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-18.2095661, 39.2518234, 0]
|
||||
Rotation: [0.967056513, 0, 0, -0.254561812]
|
||||
Scale: [4.47999525, 4.47999525, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.24000001, 2.24000001]
|
||||
- Entity: 15223077898852293773
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [5.37119865, 43.8762894, 0]
|
||||
Rotation: [0.977883637, 0, 0, -0.209149718]
|
||||
Scale: [4.47999668, 4.47999668, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.24000001, 2.24000001]
|
||||
- Entity: 2157107598622182863
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-7.60411549, 44.1442184, 0]
|
||||
Rotation: [0.989285827, 0, 0, 0.145991713]
|
||||
Scale: [4.47999287, 4.47999287, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 0.5
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.24000001, 2.24000001]
|
||||
- Entity: 8080964283681139153
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-0.739211679, 37.7653275, 0]
|
||||
Rotation: [0.956475914, 0, 0, -0.291811317]
|
||||
Scale: [5, 2, 2]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 0.25
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.5, 1]
|
||||
- Entity: 1352995477042327524
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-8.32969856, 30.4078159, 0]
|
||||
Rotation: [0.781595349, 0, 0, 0.623785794]
|
||||
Scale: [14.000001, 4.47999334, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 3
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [7, 2.24000001]
|
||||
- Entity: 935615878363259513
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [6.88031197, 31.942337, 0]
|
||||
Rotation: [0.986578286, 0, 0, 0.163288936]
|
||||
Scale: [4.47999954, 4.47999954, 4.48000002]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [2.24000001, 2.24000001]
|
||||
- Entity: 14057422478420564497
|
||||
TagComponent:
|
||||
Tag: Player
|
||||
TransformComponent:
|
||||
Position: [0, 22.774044, 0]
|
||||
Rotation: [0.942591429, 0, 0, -0.333948225]
|
||||
Scale: [6.00000048, 6.00000048, 4.48000002]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.PlayerCube
|
||||
StoredFields:
|
||||
- Name: HorizontalForce
|
||||
Type: 1
|
||||
Data: 10
|
||||
- Name: VerticalForce
|
||||
Type: 1
|
||||
Data: 10
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Sphere1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
CircleCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Radius: 3
|
||||
- Entity: 1289165777996378215
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [50, 1, 50]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.Sink
|
||||
StoredFields:
|
||||
- Name: SinkSpeed
|
||||
Type: 1
|
||||
Data: 0
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 0
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [25, 0.5]
|
||||
- Entity: 5178862374589434728
|
||||
TagComponent:
|
||||
Tag: Camera
|
||||
TransformComponent:
|
||||
Position: [0, 25, 79.75]
|
||||
Rotation: [0.995602965, -0.0936739072, 0, 0]
|
||||
Scale: [1, 0.999999821, 0.999999821]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.BasicController
|
||||
StoredFields:
|
||||
- Name: Speed
|
||||
Type: 1
|
||||
Data: 12
|
||||
CameraComponent:
|
||||
Camera: some camera data...
|
||||
Primary: true
|
||||
- Entity: 3948844418381294888
|
||||
TagComponent:
|
||||
Tag: Box
|
||||
TransformComponent:
|
||||
Position: [-1.48028564, 49.5945244, -2.38418579e-07]
|
||||
Rotation: [0.977883637, 0, 0, -0.209149733]
|
||||
Scale: [1.99999976, 1.99999976, 2]
|
||||
MeshComponent:
|
||||
AssetPath: assets/meshes/Cube1m.fbx
|
||||
RigidBody2DComponent:
|
||||
BodyType: 1
|
||||
Mass: 1
|
||||
BoxCollider2DComponent:
|
||||
Offset: [0, 0]
|
||||
Size: [1, 1]
|
||||
54
ExampleApp/Src/PlayerCube.cs
Normal file
54
ExampleApp/Src/PlayerCube.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Prism;
|
||||
|
||||
namespace Example
|
||||
{
|
||||
class PlayerCube : Entity
|
||||
{
|
||||
public float HorizontalForce = 10.0f;
|
||||
public float VerticalForce = 10.0f;
|
||||
|
||||
private RigidBody2DComponent m_PhysicsBody;
|
||||
private MaterialInstance m_MeshMaterial;
|
||||
|
||||
void OnCreate()
|
||||
{
|
||||
m_PhysicsBody = GetComponent<RigidBody2DComponent>();
|
||||
|
||||
MeshComponent meshComponent = GetComponent<MeshComponent>();
|
||||
m_MeshMaterial = meshComponent.Mesh.GetMaterial(0);
|
||||
m_MeshMaterial.Set("u_Metalness", 0.0f);
|
||||
}
|
||||
|
||||
void OnUpdate(float ts)
|
||||
{
|
||||
if (Input.IsKeyPressed(KeyCode.D))
|
||||
m_PhysicsBody.ApplyLinearImpulse(new Vec2(HorizontalForce, 0), new Vec2(), true);
|
||||
else if (Input.IsKeyPressed(KeyCode.A))
|
||||
m_PhysicsBody.ApplyLinearImpulse(new Vec2(-HorizontalForce, 0), new Vec2(), true);
|
||||
|
||||
if (Input.IsKeyPressed(KeyCode.Space))
|
||||
m_PhysicsBody.ApplyLinearImpulse(new Vec2(0, VerticalForce), new Vec2(0, -10), true);
|
||||
|
||||
Vec3 color = new Vec3(0.8f, 0.8f, 0.8f);
|
||||
if (Input.IsKeyPressed(KeyCode.Q))
|
||||
color = new Vec3(0.0f, 1.0f, 0.0f);
|
||||
|
||||
m_MeshMaterial.Set("u_AlbedoColor", color);
|
||||
|
||||
if (Input.IsKeyPressed(KeyCode.R))
|
||||
{
|
||||
Mat4 transform = GetTransform();
|
||||
transform.Translation = new Vec3(0.0f);
|
||||
SetTransform(transform);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
26
ExampleApp/Src/RandomColor.cs
Normal file
26
ExampleApp/Src/RandomColor.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Prism;
|
||||
|
||||
namespace Example
|
||||
{
|
||||
class RandomColor : Entity
|
||||
{
|
||||
void OnCreate()
|
||||
{
|
||||
Random random = new Random();
|
||||
|
||||
MeshComponent meshComponent = GetComponent<MeshComponent>();
|
||||
MaterialInstance material = meshComponent.Mesh.GetMaterial(0);
|
||||
float r = (float)random.NextDouble();
|
||||
float g = (float)random.NextDouble();
|
||||
float b = (float)random.NextDouble();
|
||||
material.Set("u_AlbedoColor", new Vec3(r, g, b));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -57,6 +57,10 @@ namespace Prism
|
||||
SetVec3_Native(m_UnmanagedInstance, uniform, ref value);
|
||||
}
|
||||
|
||||
public void Set(string uniform, Vec4 value)
|
||||
{
|
||||
SetVec4_Native(m_UnmanagedInstance, uniform, ref value);
|
||||
}
|
||||
|
||||
public void SetTexture(string uniform, Texture2D texture)
|
||||
{
|
||||
@ -82,6 +86,8 @@ namespace Prism
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern void SetVec3_Native(IntPtr unmanagedInstance, string uniform, ref Vec3 value);
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern void SetVec4_Native(IntPtr unmanagedInstance, string uniform, ref Vec4 value);
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern void SetTexture_Native(IntPtr unmanagedInstance, string uniform, IntPtr texture);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,10 +71,10 @@ namespace Prism
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern IntPtr GetMesh_Native(ulong entityID);
|
||||
internal static extern IntPtr GetMesh_Native(ulong entityID);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern void SetMesh_Native(ulong entityID, IntPtr unmanagedInstance);
|
||||
internal static extern void SetMesh_Native(ulong entityID, IntPtr unmanagedInstance);
|
||||
|
||||
}
|
||||
|
||||
@ -92,4 +92,15 @@ namespace Prism
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public class RigidBody2DComponent : Component
|
||||
{
|
||||
public void ApplyLinearImpulse(Vec2 impulse, Vec2 offset, bool wake)
|
||||
{
|
||||
ApplyLinearImpulse_Native(Entity.ID, ref impulse, ref offset, wake);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void ApplyLinearImpulse_Native(ulong entityID, ref Vec2 impulse, ref Vec2 offset, bool wake);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,6 @@ set(LINK_LIBRARIES_PRIVATE
|
||||
tinyFileDialogs
|
||||
FastNoise
|
||||
yaml-cpp
|
||||
box2d
|
||||
)
|
||||
|
||||
set(LINK_LIBRARIES_PUBLIC
|
||||
@ -63,6 +62,7 @@ set(LINK_LIBRARIES_PUBLIC
|
||||
glm
|
||||
EnTT::EnTT
|
||||
mono
|
||||
box2d
|
||||
)
|
||||
|
||||
# link library opengl
|
||||
|
||||
@ -227,4 +227,12 @@ namespace Prism
|
||||
{
|
||||
return (float)glfwGetTime();
|
||||
}
|
||||
|
||||
const char * Application::GetConfigurationName() {
|
||||
return "Debug"; // TODO: to support Release string
|
||||
}
|
||||
|
||||
const char * Application::GetPlatformName() {
|
||||
return "windows x64"; // TODO: to support linux platform
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,11 +44,15 @@ namespace Prism
|
||||
|
||||
void PushLayer(Layer* layer);
|
||||
void PushOverlay(Layer* layer);
|
||||
|
||||
float GetTime() const; // TODO: should impl in platform
|
||||
|
||||
static const char* GetConfigurationName();
|
||||
static const char* GetPlatformName();
|
||||
private:
|
||||
bool OnWindowResize(const WindowResizeEvent& e);
|
||||
bool OnWindowClose(WindowCloseEvent& e);
|
||||
|
||||
float GetTime() const; // TODO: should impl in platform
|
||||
private:
|
||||
TimeStep m_TimeStep;
|
||||
float m_LastFrameTime = 0.0f;
|
||||
|
||||
@ -47,6 +47,9 @@ namespace Prism
|
||||
|
||||
static Window* Create(const WindowProps& props);
|
||||
|
||||
virtual const std::string& GetTitle() const = 0;
|
||||
virtual void SetTitle(const std::string& title) = 0;
|
||||
|
||||
virtual void* GetNativeWindow() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@ -65,6 +65,11 @@ namespace Prism
|
||||
return { (float)x, (float)y };
|
||||
}
|
||||
|
||||
void WindowsWindow::SetTitle(const std::string &title) {
|
||||
m_Data.Title = title;
|
||||
glfwSetWindowTitle(m_Window, m_Data.Title.c_str());
|
||||
}
|
||||
|
||||
void WindowsWindow::Init(const WindowProps& props)
|
||||
{
|
||||
m_Data.Title = props.Title;
|
||||
|
||||
@ -27,6 +27,9 @@ namespace Prism
|
||||
virtual std::pair<uint32_t, uint32_t> GetSize() const override { return { m_Data.Width, m_Data.Height }; }
|
||||
virtual std::pair<float, float> GetWindowPos() const override;
|
||||
|
||||
virtual const std::string& GetTitle() const override { return m_Data.Title; }
|
||||
virtual void SetTitle(const std::string& title) override;
|
||||
|
||||
inline void* GetNativeWindow() const override { return m_Window; }
|
||||
|
||||
private:
|
||||
|
||||
@ -122,13 +122,14 @@ namespace Prism
|
||||
}
|
||||
}
|
||||
|
||||
MaterialInstance::MaterialInstance(const Ref<Material>& material)
|
||||
: m_Material(material)
|
||||
MaterialInstance::MaterialInstance(const Ref<Material> &material, const std::string &name)
|
||||
: m_Material(material), m_Name(name)
|
||||
{
|
||||
m_Material->m_MaterialInstances.insert(this);
|
||||
AllocateStorage();
|
||||
}
|
||||
|
||||
|
||||
MaterialInstance::~MaterialInstance()
|
||||
{
|
||||
m_Material->m_MaterialInstances.erase(this);
|
||||
|
||||
@ -87,7 +87,7 @@ namespace Prism
|
||||
{
|
||||
friend class Material;
|
||||
public:
|
||||
MaterialInstance(const Ref<Material>& material);
|
||||
MaterialInstance(const Ref<Material>& material, const std::string& name = "");
|
||||
virtual ~MaterialInstance();
|
||||
|
||||
static Ref<MaterialInstance> Create(const Ref<Material>& material);
|
||||
@ -128,7 +128,8 @@ namespace Prism
|
||||
bool GetFlag(MaterialFlag flag) const { return (uint32_t)flag & m_Material->m_MaterialFlags; }
|
||||
void SetFlag(MaterialFlag flag, bool value = true);
|
||||
|
||||
Ref<Shader >GetShader() { return m_Material->m_Shader; }
|
||||
Ref<Shader> GetShader() const { return m_Material->m_Shader; }
|
||||
const std::string& GetName() const { return m_Name; }
|
||||
private:
|
||||
void AllocateStorage();
|
||||
void OnShaderReloaded();
|
||||
@ -136,6 +137,7 @@ namespace Prism
|
||||
void OnMaterialValueUpdated(ShaderUniformDeclaration* decl);
|
||||
private:
|
||||
Ref<Material> m_Material;
|
||||
std::string m_Name;
|
||||
|
||||
Buffer m_VSUniformStorageBuffer;
|
||||
Buffer m_PSUniformStorageBuffer;
|
||||
|
||||
@ -259,7 +259,7 @@ namespace Prism
|
||||
auto aiMaterial = scene->mMaterials[i];
|
||||
auto aiMaterialName = aiMaterial->GetName();
|
||||
|
||||
auto mi = Ref<MaterialInstance>::Create(m_BaseMaterial);
|
||||
auto mi = Ref<MaterialInstance>::Create(m_BaseMaterial, aiMaterialName.data);
|
||||
m_Materials[i] = mi;
|
||||
|
||||
PM_MESH_LOG(" {0} (Index = {1})", aiMaterialName.data, i);
|
||||
@ -690,9 +690,8 @@ namespace Prism
|
||||
PM_CORE_ASSERT(NextPositionIndex < nodeAnim->mNumPositionKeys);
|
||||
float DeltaTime = (float)(nodeAnim->mPositionKeys[NextPositionIndex].mTime - nodeAnim->mPositionKeys[PositionIndex].mTime);
|
||||
float Factor = (animationTime - (float)nodeAnim->mPositionKeys[PositionIndex].mTime) / DeltaTime;
|
||||
if (Factor < 0.0f)
|
||||
Factor = 0.0f;
|
||||
PM_CORE_ASSERT(Factor <= 1.0f, "Factor must be below 1.0f");
|
||||
Factor = glm::clamp(Factor, 0.0f, 1.0f);
|
||||
const aiVector3D& Start = nodeAnim->mPositionKeys[PositionIndex].mValue;
|
||||
const aiVector3D& End = nodeAnim->mPositionKeys[NextPositionIndex].mValue;
|
||||
aiVector3D Delta = End - Start;
|
||||
@ -714,9 +713,8 @@ namespace Prism
|
||||
PM_CORE_ASSERT(NextRotationIndex < nodeAnim->mNumRotationKeys);
|
||||
float DeltaTime = (float)(nodeAnim->mRotationKeys[NextRotationIndex].mTime - nodeAnim->mRotationKeys[RotationIndex].mTime);
|
||||
float Factor = (animationTime - (float)nodeAnim->mRotationKeys[RotationIndex].mTime) / DeltaTime;
|
||||
if (Factor < 0.0f)
|
||||
Factor = 0.0f;
|
||||
PM_CORE_ASSERT(Factor <= 1.0f, "Factor must be below 1.0f");
|
||||
Factor = glm::clamp(Factor, 0.0f, 1.0f);
|
||||
const aiQuaternion& StartRotationQ = nodeAnim->mRotationKeys[RotationIndex].mValue;
|
||||
const aiQuaternion& EndRotationQ = nodeAnim->mRotationKeys[NextRotationIndex].mValue;
|
||||
auto q = aiQuaternion();
|
||||
@ -739,9 +737,8 @@ namespace Prism
|
||||
PM_CORE_ASSERT(nextIndex < nodeAnim->mNumScalingKeys);
|
||||
float deltaTime = (float)(nodeAnim->mScalingKeys[nextIndex].mTime - nodeAnim->mScalingKeys[index].mTime);
|
||||
float factor = (animationTime - (float)nodeAnim->mScalingKeys[index].mTime) / deltaTime;
|
||||
if (factor < 0.0f)
|
||||
factor = 0.0f;
|
||||
PM_CORE_ASSERT(factor <= 1.0f, "Factor must be below 1.0f");
|
||||
factor = glm::clamp(factor, 0.0f, 1.0f);
|
||||
const auto& start = nodeAnim->mScalingKeys[index].mValue;
|
||||
const auto& end = nodeAnim->mScalingKeys[nextIndex].mValue;
|
||||
auto delta = end - start;
|
||||
|
||||
@ -378,7 +378,7 @@ namespace Prism
|
||||
* glm::rotate(glm::mat4(1.0f), glm::radians(rotation), { 0.0f, 0.0f, 1.0f })
|
||||
* glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f });
|
||||
|
||||
for (uint32_t i = 1; i < 4; i++)
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPositions[i];
|
||||
s_Data.QuadVertexBufferPtr->Color = color;
|
||||
@ -426,7 +426,7 @@ namespace Prism
|
||||
* glm::rotate(glm::mat4(1.0f), glm::radians(rotation), { 0.0f, 0.0f, 1.0f })
|
||||
* glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f });
|
||||
|
||||
for (uint32_t i = 1; i < 4; i++)
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPositions[i];
|
||||
s_Data.QuadVertexBufferPtr->Color = color;
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "SceneCamera.h"
|
||||
#include "box2d/id.h"
|
||||
#include "glm/glm.hpp"
|
||||
#include "Prism/Core/Ref.h"
|
||||
#include "Prism/Core/UUID.h"
|
||||
@ -101,6 +102,46 @@ namespace Prism
|
||||
SpriteRendererComponent(const SpriteRendererComponent& other)
|
||||
: Color(other.Color), Texture(other.Texture), TilingFactor(other.TilingFactor) {}
|
||||
};
|
||||
|
||||
struct RigidBody2DComponent
|
||||
{
|
||||
enum class Type { Static, Dynamic, Kinematic };
|
||||
Type BodyType;
|
||||
float Mass = 1.0f;
|
||||
|
||||
// Storage for BodyID (box2d version 3.0^ use handle to resolve this)
|
||||
b2BodyId RuntimeBodyID = b2_nullBodyId;
|
||||
|
||||
RigidBody2DComponent() = default;
|
||||
RigidBody2DComponent(const RigidBody2DComponent& other)
|
||||
: BodyType(other.BodyType), Mass(other.Mass) {}
|
||||
};
|
||||
|
||||
struct BoxCollider2DComponent
|
||||
{
|
||||
glm::vec2 Offset = { 0.0f,0.0f };
|
||||
glm::vec2 Size = { 1.0f, 1.0f };
|
||||
|
||||
// Storage for runtime
|
||||
// void* RuntimeFixture = nullptr;
|
||||
|
||||
BoxCollider2DComponent() = default;
|
||||
BoxCollider2DComponent(const BoxCollider2DComponent& other)
|
||||
: Offset(other.Offset), Size(other.Size) {}
|
||||
};
|
||||
|
||||
struct CircleCollider2DComponent
|
||||
{
|
||||
glm::vec2 Offset = { 0.0f,0.0f };
|
||||
float Radius = 1.0f;
|
||||
|
||||
// Storage for runtime
|
||||
// void* RuntimeFixture = nullptr;
|
||||
|
||||
CircleCollider2DComponent() = default;
|
||||
CircleCollider2DComponent(const CircleCollider2DComponent& other)
|
||||
: Offset(other.Offset), Radius(other.Radius) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -40,6 +40,12 @@ namespace Prism
|
||||
return m_Scene->m_Registry.storage<T>().contains(m_EntityHandle);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RemoveComponent() const {
|
||||
if (HasComponent<T>())
|
||||
m_Scene->m_Registry.remove<T>(m_EntityHandle);
|
||||
}
|
||||
|
||||
glm::mat4& Transform() { return m_Scene->m_Registry.get<TransformComponent>(m_EntityHandle); }
|
||||
const glm::mat4& Transform() const { return m_Scene->m_Registry.get<TransformComponent>(m_EntityHandle); }
|
||||
|
||||
|
||||
@ -8,6 +8,11 @@
|
||||
#include "Entity.h"
|
||||
#include "Prism/Renderer/SceneRenderer.h"
|
||||
#include "Prism/Script/ScriptEngine.h"
|
||||
#include <box2d/box2d.h>
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/matrix_decompose.hpp>
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -20,6 +25,18 @@ namespace Prism
|
||||
UUID SceneID;
|
||||
};
|
||||
|
||||
struct Box2DWorldComponent
|
||||
{
|
||||
b2WorldId World;
|
||||
|
||||
Box2DWorldComponent() = default;
|
||||
Box2DWorldComponent(const b2Vec2& gravity) {
|
||||
b2WorldDef worldDef = b2DefaultWorldDef();
|
||||
worldDef.gravity = gravity;
|
||||
World = b2CreateWorld(&worldDef);
|
||||
}
|
||||
};
|
||||
|
||||
void OnTransformConstruct(entt::registry& registry, entt::entity entity)
|
||||
{
|
||||
// HZ_CORE_TRACE("Transform Component constructed!");
|
||||
@ -38,6 +55,16 @@ namespace Prism
|
||||
ScriptEngine::InitScriptEntity(scene->m_EntityIDMap.at(entityID));
|
||||
}
|
||||
|
||||
static std::tuple<glm::vec3, glm::quat, glm::vec3> GetTransformDecomposition(const glm::mat4& transform)
|
||||
{
|
||||
glm::vec3 scale, translation, skew;
|
||||
glm::vec4 perspective;
|
||||
glm::quat orientation;
|
||||
glm::decompose(transform, scale, orientation, translation, skew, perspective);
|
||||
|
||||
return { translation, orientation, scale };
|
||||
}
|
||||
|
||||
Environment Environment::Load(const std::string& filepath)
|
||||
{
|
||||
auto [radiance, irradiance] = SceneRenderer::CreateEnvironmentMap(filepath);
|
||||
@ -52,6 +79,8 @@ namespace Prism
|
||||
|
||||
m_SceneEntity = m_Registry.create();
|
||||
m_Registry.emplace<SceneComponent>(m_SceneEntity, m_SceneID);
|
||||
// TODO: Obviously not necessary in all cases
|
||||
m_Registry.emplace<Box2DWorldComponent>(m_SceneEntity, b2Vec2{ 0.0f, -9.8f });
|
||||
|
||||
s_ActiveScenes[m_SceneID] = this;
|
||||
|
||||
@ -85,6 +114,36 @@ namespace Prism
|
||||
ScriptEngine::OnUpdateEntity(m_SceneID, entityID, ts);
|
||||
}
|
||||
}
|
||||
|
||||
// Box2D physics
|
||||
|
||||
auto sceneView = m_Registry.view<Box2DWorldComponent>();
|
||||
auto& box2DWorld = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
|
||||
int32_t velocityIterations = 6;
|
||||
int32_t positionIterations = 2;
|
||||
// box2DWorld->Step(ts, velocityIterations, positionIterations);
|
||||
b2World_Step(box2DWorld, ts, positionIterations);
|
||||
|
||||
{
|
||||
auto view = m_Registry.view<RigidBody2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& transform = e.Transform();
|
||||
const auto& rb2d = e.GetComponent<RigidBody2DComponent>();
|
||||
|
||||
const auto& position = b2Body_GetPosition(rb2d.RuntimeBodyID);
|
||||
auto [translation, rotationQuat, scale] = GetTransformDecomposition(transform);
|
||||
glm::vec3 rotation = glm::eulerAngles(rotationQuat);
|
||||
|
||||
float angle = b2Rot_GetAngle(b2Body_GetRotation(rb2d.RuntimeBodyID));
|
||||
|
||||
transform = glm::translate(glm::mat4(1.0f), { position.x, position.y, transform[3].z }) *
|
||||
glm::toMat4(glm::quat({ rotation.x, rotation.y, angle })) *
|
||||
glm::scale(glm::mat4(1.0f), scale);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Scene::OnRenderRuntime(TimeStep ts)
|
||||
@ -191,7 +250,7 @@ namespace Prism
|
||||
void Scene::OnRuntimeStart()
|
||||
{
|
||||
ScriptEngine::SetSceneContext(this);
|
||||
|
||||
{
|
||||
auto view = m_Registry.view<ScriptComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
@ -199,6 +258,96 @@ namespace Prism
|
||||
if (ScriptEngine::ModuleExists(e.GetComponent<ScriptComponent>().ModuleName))
|
||||
ScriptEngine::InstantiateEntityClass(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Box2D physics
|
||||
auto sceneView = m_Registry.view<Box2DWorldComponent>();
|
||||
auto& world = m_Registry.get<Box2DWorldComponent>(sceneView.front()).World;
|
||||
{
|
||||
auto view = m_Registry.view<RigidBody2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& transform = e.Transform();
|
||||
auto& rigidBody2D = m_Registry.get<RigidBody2DComponent>(entity);
|
||||
|
||||
b2BodyDef bodyDef = b2DefaultBodyDef();
|
||||
if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Static)
|
||||
bodyDef.type = b2_staticBody;
|
||||
else if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Dynamic)
|
||||
bodyDef.type = b2_dynamicBody;
|
||||
else if (rigidBody2D.BodyType == RigidBody2DComponent::Type::Kinematic)
|
||||
bodyDef.type = b2_kinematicBody;
|
||||
bodyDef.position = {transform[3].x, transform[3].y};
|
||||
|
||||
auto [translation, rotationQuat, scale] = GetTransformDecomposition(transform);
|
||||
float rotationZ = glm::eulerAngles(rotationQuat).z;
|
||||
bodyDef.rotation = b2Rot{cos(rotationZ), sin(rotationZ)};
|
||||
|
||||
rigidBody2D.RuntimeBodyID = b2CreateBody(world, &bodyDef);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
auto view = m_Registry.view<BoxCollider2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& transform = e.Transform();
|
||||
|
||||
auto& boxCollider2D = m_Registry.get<BoxCollider2DComponent>(entity);
|
||||
if (e.HasComponent<RigidBody2DComponent>())
|
||||
{
|
||||
const auto& rigidBody2D = e.GetComponent<RigidBody2DComponent>();
|
||||
PM_CORE_ASSERT(b2Body_IsValid(rigidBody2D.RuntimeBodyID));
|
||||
|
||||
b2BodyId bodyId = rigidBody2D.RuntimeBodyID;
|
||||
|
||||
b2Polygon boxShape = b2MakeOffsetBox(boxCollider2D.Size.x, boxCollider2D.Size.y, {boxCollider2D.Offset.x,boxCollider2D.Offset.y}, {1.0f, 0.0f});
|
||||
|
||||
b2ShapeDef shapeDef = b2DefaultShapeDef();
|
||||
shapeDef.density = 1.0f;
|
||||
shapeDef.material.friction = 1.0f;
|
||||
|
||||
b2CreatePolygonShape(bodyId, &shapeDef, &boxShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto view = m_Registry.view<CircleCollider2DComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& transform = e.Transform();
|
||||
|
||||
auto& circleCollider2D = m_Registry.get<CircleCollider2DComponent>(entity);
|
||||
if (e.HasComponent<RigidBody2DComponent>())
|
||||
{
|
||||
auto& rigidBody2D = e.GetComponent<RigidBody2DComponent>();
|
||||
PM_CORE_ASSERT(b2Body_IsValid(rigidBody2D.RuntimeBodyID));
|
||||
|
||||
b2BodyId bodyId = rigidBody2D.RuntimeBodyID;
|
||||
|
||||
b2Vec2 centor = {circleCollider2D.Offset.x, circleCollider2D.Offset.y};
|
||||
|
||||
b2Circle circleShape{
|
||||
.center = centor,
|
||||
.radius = circleCollider2D.Radius
|
||||
};
|
||||
|
||||
b2ShapeDef shapeDef = b2DefaultShapeDef();
|
||||
|
||||
shapeDef.density = 1.0f;
|
||||
shapeDef.material.friction = 1.0f;
|
||||
|
||||
b2CreateCircleShape(bodyId, &shapeDef, &circleShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_IsPlaying = true;
|
||||
}
|
||||
@ -310,6 +459,9 @@ namespace Prism
|
||||
CopyComponentIfExists<ScriptComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<CameraComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<SpriteRendererComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<RigidBody2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<BoxCollider2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<CircleCollider2DComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
}
|
||||
|
||||
void Scene::CopyTo(Ref<Scene>& target)
|
||||
@ -337,10 +489,14 @@ namespace Prism
|
||||
CopyComponent<ScriptComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<CameraComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<SpriteRendererComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<RigidBody2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<BoxCollider2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<CircleCollider2DComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
|
||||
const auto& entityInstanceMap = ScriptEngine::GetEntityInstanceMap();
|
||||
if (entityInstanceMap.find(target->GetUUID()) != entityInstanceMap.end())
|
||||
ScriptEngine::CopyEntityScriptData(target->GetUUID(), m_SceneID);
|
||||
target->SetPhysics2DGravity(GetPhysics2DGravity());
|
||||
}
|
||||
|
||||
Ref<Scene> Scene::GetScene(const UUID& uuid)
|
||||
@ -351,6 +507,17 @@ namespace Prism
|
||||
return {};
|
||||
}
|
||||
|
||||
float Scene::GetPhysics2DGravity() const
|
||||
{
|
||||
const auto gravity = b2World_GetGravity(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World);
|
||||
return gravity.y;
|
||||
}
|
||||
|
||||
void Scene::SetPhysics2DGravity(const float gravity)
|
||||
{
|
||||
b2World_SetGravity(m_Registry.get<Box2DWorldComponent>(m_SceneEntity).World, {0.0f, gravity});
|
||||
}
|
||||
|
||||
|
||||
void Scene::DestroyEntity(Entity entity)
|
||||
{
|
||||
|
||||
@ -87,6 +87,9 @@ namespace Prism
|
||||
|
||||
static Ref<Scene> GetScene(const UUID& uuid);
|
||||
|
||||
float GetPhysics2DGravity() const;
|
||||
void SetPhysics2DGravity(float gravity);
|
||||
|
||||
// Editor-specific
|
||||
void SetSelectedEntity(entt::entity entity) { m_SelectedEntity = entity; }
|
||||
|
||||
|
||||
@ -268,7 +268,7 @@ namespace Prism
|
||||
out << YAML::Key << "CameraComponent";
|
||||
out << YAML::BeginMap; // CameraComponent
|
||||
|
||||
auto cameraComponent = entity.GetComponent<CameraComponent>();
|
||||
const auto& cameraComponent = entity.GetComponent<CameraComponent>();
|
||||
out << YAML::Key << "Camera" << YAML::Value << "some camera data...";
|
||||
out << YAML::Key << "Primary" << YAML::Value << cameraComponent.Primary;
|
||||
|
||||
@ -280,7 +280,7 @@ namespace Prism
|
||||
out << YAML::Key << "SpriteRendererComponent";
|
||||
out << YAML::BeginMap; // SpriteRendererComponent
|
||||
|
||||
auto spriteRendererComponent = entity.GetComponent<SpriteRendererComponent>();
|
||||
const auto& spriteRendererComponent = entity.GetComponent<SpriteRendererComponent>();
|
||||
out << YAML::Key << "Color" << YAML::Value << spriteRendererComponent.Color;
|
||||
if (spriteRendererComponent.Texture)
|
||||
out << YAML::Key << "TextureAssetPath" << YAML::Value << "path/to/asset";
|
||||
@ -289,6 +289,42 @@ namespace Prism
|
||||
out << YAML::EndMap; // SpriteRendererComponent
|
||||
}
|
||||
|
||||
if (entity.HasComponent<RigidBody2DComponent>())
|
||||
{
|
||||
out << YAML::Key << "RigidBody2DComponent";
|
||||
out << YAML::BeginMap; // RigidBody2DComponent
|
||||
|
||||
const auto& rigidbody2DComponent = entity.GetComponent<RigidBody2DComponent>();
|
||||
out << YAML::Key << "BodyType" << YAML::Value << (int)rigidbody2DComponent.BodyType;
|
||||
out << YAML::Key << "Mass" << YAML::Value << rigidbody2DComponent.Mass;
|
||||
|
||||
out << YAML::EndMap; // RigidBody2DComponent
|
||||
}
|
||||
|
||||
if (entity.HasComponent<BoxCollider2DComponent>())
|
||||
{
|
||||
out << YAML::Key << "BoxCollider2DComponent";
|
||||
out << YAML::BeginMap; // BoxCollider2DComponent
|
||||
|
||||
const auto& boxCollider2DComponent = entity.GetComponent<BoxCollider2DComponent>();
|
||||
out << YAML::Key << "Offset" << YAML::Value << boxCollider2DComponent.Offset;
|
||||
out << YAML::Key << "Size" << YAML::Value << boxCollider2DComponent.Size;
|
||||
|
||||
out << YAML::EndMap; // BoxCollider2DComponent
|
||||
}
|
||||
|
||||
if (entity.HasComponent<CircleCollider2DComponent>())
|
||||
{
|
||||
out << YAML::Key << "CircleCollider2DComponent";
|
||||
out << YAML::BeginMap; // CircleCollider2DComponent
|
||||
|
||||
const auto& circleCollider2DComponent = entity.GetComponent<CircleCollider2DComponent>();
|
||||
out << YAML::Key << "Offset" << YAML::Value << circleCollider2DComponent.Offset;
|
||||
out << YAML::Key << "Radius" << YAML::Value << circleCollider2DComponent.Radius;
|
||||
|
||||
out << YAML::EndMap; // CircleCollider2DComponent
|
||||
}
|
||||
|
||||
out << YAML::EndMap; // Entity
|
||||
}
|
||||
|
||||
@ -470,8 +506,7 @@ namespace Prism
|
||||
}
|
||||
}
|
||||
|
||||
auto meshComponent = entity["MeshComponent"];
|
||||
if (meshComponent)
|
||||
if (auto meshComponent = entity["MeshComponent"])
|
||||
{
|
||||
std::string meshPath = meshComponent["AssetPath"].as<std::string>();
|
||||
// TEMP (because script creates mesh component...)
|
||||
@ -481,8 +516,7 @@ namespace Prism
|
||||
PM_CORE_INFO(" Mesh Asset Path: {0}", meshPath);
|
||||
}
|
||||
|
||||
auto cameraComponent = entity["CameraComponent"];
|
||||
if (cameraComponent)
|
||||
if (auto cameraComponent = entity["CameraComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<CameraComponent>();
|
||||
component.Camera = SceneCamera();
|
||||
@ -491,8 +525,7 @@ namespace Prism
|
||||
PM_CORE_INFO(" Primary Camera: {0}", component.Primary);
|
||||
}
|
||||
|
||||
auto spriteRendererComponent = entity["SpriteRendererComponent"];
|
||||
if (spriteRendererComponent)
|
||||
if (auto spriteRendererComponent = entity["SpriteRendererComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<SpriteRendererComponent>();
|
||||
component.Color = spriteRendererComponent["Color"].as<glm::vec4>();
|
||||
@ -500,6 +533,27 @@ namespace Prism
|
||||
|
||||
PM_CORE_INFO(" SpriteRendererComponent present.");
|
||||
}
|
||||
|
||||
if (auto rigidBody2DComponent = entity["RigidBody2DComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<RigidBody2DComponent>();
|
||||
component.BodyType = (RigidBody2DComponent::Type)rigidBody2DComponent["BodyType"].as<int>();
|
||||
component.Mass = rigidBody2DComponent["Mass"].as<float>();
|
||||
}
|
||||
|
||||
if (auto boxCollider2DComponent = entity["BoxCollider2DComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<BoxCollider2DComponent>();
|
||||
component.Offset = boxCollider2DComponent["Offset"].as<glm::vec2>();
|
||||
component.Size = boxCollider2DComponent["Size"].as<glm::vec2>();
|
||||
}
|
||||
|
||||
if (auto circleCollider2DComponent = entity["CircleCollider2DComponent"])
|
||||
{
|
||||
auto& component = deserializedEntity.AddComponent<CircleCollider2DComponent>();
|
||||
component.Offset = circleCollider2DComponent["Offset"].as<glm::vec2>();
|
||||
component.Radius = circleCollider2DComponent["Radius"].as<float>();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -38,6 +38,8 @@ namespace Prism
|
||||
Component_RegisterType(ScriptComponent);
|
||||
Component_RegisterType(CameraComponent);
|
||||
Component_RegisterType(SpriteRendererComponent);
|
||||
Component_RegisterType(RigidBody2DComponent);
|
||||
Component_RegisterType(BoxCollider2DComponent);
|
||||
}
|
||||
|
||||
void ScriptEngineRegistry::RegisterAll()
|
||||
@ -56,6 +58,8 @@ namespace Prism
|
||||
|
||||
mono_add_internal_call("Prism.Input::IsKeyPressed_Native", (const void*)Prism::Script::Prism_Input_IsKeyPressed);
|
||||
|
||||
mono_add_internal_call("Prism.RigidBody2DComponent::ApplyLinearImpulse_Native", (const void*)Prism::Script::Prism_RigidBody2DComponent_ApplyLinearImpulse);
|
||||
|
||||
mono_add_internal_call("Prism.Texture2D::Constructor_Native", (const void*)Prism::Script::Prism_Texture2D_Constructor);
|
||||
mono_add_internal_call("Prism.Texture2D::Destructor_Native", (const void*)Prism::Script::Prism_Texture2D_Destructor);
|
||||
mono_add_internal_call("Prism.Texture2D::SetData_Native", (const void*)Prism::Script::Prism_Texture2D_SetData);
|
||||
@ -66,7 +70,8 @@ namespace Prism
|
||||
|
||||
mono_add_internal_call("Prism.MaterialInstance::Destructor_Native", (const void*)Prism::Script::Prism_MaterialInstance_Destructor);
|
||||
mono_add_internal_call("Prism.MaterialInstance::SetFloat_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetFloat);
|
||||
mono_add_internal_call("Prism.MaterialInstance::SetVector3_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetVector3);
|
||||
mono_add_internal_call("Prism.MaterialInstance::SetVec3_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetVector3);
|
||||
mono_add_internal_call("Prism.MaterialInstance::SetVec4_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetVector4);
|
||||
mono_add_internal_call("Prism.MaterialInstance::SetTexture_Native", (const void*)Prism::Script::Prism_MaterialInstance_SetTexture);
|
||||
|
||||
mono_add_internal_call("Prism.Mesh::Constructor_Native", (const void*)Prism::Script::Prism_Mesh_Constructor);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "ScriptWarppers.h"
|
||||
|
||||
#include "ScriptEngine.h"
|
||||
#include "box2d/box2d.h"
|
||||
#include "mono/metadata/metadata.h"
|
||||
#include "mono/metadata/object.h"
|
||||
#include "mono/metadata/reflection.h"
|
||||
@ -131,6 +132,22 @@ namespace Prism { namespace Script {
|
||||
meshComponent.Mesh = inMesh ? *inMesh : nullptr;
|
||||
}
|
||||
|
||||
void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, glm::vec2 *impulse, glm::vec2 *offset, bool wake)
|
||||
{
|
||||
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
|
||||
PM_CORE_ASSERT(scene, "No active scene!");
|
||||
const auto& entityMap = scene->GetEntityMap();
|
||||
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
|
||||
|
||||
Entity entity = entityMap.at(entityID);
|
||||
PM_CORE_ASSERT(entity.HasComponent<RigidBody2DComponent>());
|
||||
auto& component = entity.GetComponent<RigidBody2DComponent>();
|
||||
|
||||
b2BodyId body = component.RuntimeBodyID;
|
||||
|
||||
b2Body_ApplyLinearImpulse(body, *(const b2Vec2*)impulse, b2Body_GetWorldCenterOfMass(body) + *(const b2Vec2*)offset, wake);
|
||||
}
|
||||
|
||||
Ref<Mesh>* Prism_Mesh_Constructor(MonoString* filepath)
|
||||
{
|
||||
return new Ref<Mesh>(new Mesh(mono_string_to_utf8(filepath)));
|
||||
@ -233,6 +250,12 @@ namespace Prism { namespace Script {
|
||||
instance->Set(mono_string_to_utf8(uniform), *value);
|
||||
}
|
||||
|
||||
void Prism_MaterialInstance_SetVector4(Ref<MaterialInstance> *_this, MonoString *uniform, glm::vec4 *value)
|
||||
{
|
||||
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this;
|
||||
instance->Set(mono_string_to_utf8(uniform), *value);
|
||||
}
|
||||
|
||||
void Prism_MaterialInstance_SetTexture(Ref<MaterialInstance>* _this, MonoString* uniform, Ref<Texture2D>* texture)
|
||||
{
|
||||
Ref<MaterialInstance>& instance = *(Ref<MaterialInstance>*)_this;
|
||||
|
||||
@ -32,6 +32,9 @@ namespace Prism { namespace Script {
|
||||
void* Prism_MeshComponent_GetMesh(uint64_t entityID);
|
||||
void Prism_MeshComponent_SetMesh(uint64_t entityID, Ref<Mesh>* inMesh);
|
||||
|
||||
// 2D Physic
|
||||
void Prism_RigidBody2DComponent_ApplyLinearImpulse(uint64_t entityID, glm::vec2* impulse, glm::vec2* offset, bool wake);
|
||||
|
||||
// Renderer
|
||||
// Texture2D
|
||||
void* Prism_Texture2D_Constructor(uint32_t width, uint32_t height);
|
||||
@ -46,6 +49,7 @@ namespace Prism { namespace Script {
|
||||
void Prism_MaterialInstance_Destructor(Ref<MaterialInstance>* _this);
|
||||
void Prism_MaterialInstance_SetFloat(Ref<MaterialInstance>* _this, MonoString* uniform, float value);
|
||||
void Prism_MaterialInstance_SetVector3(Ref<MaterialInstance>* _this, MonoString* uniform, glm::vec3* value);
|
||||
void Prism_MaterialInstance_SetVector4(Ref<MaterialInstance>* _this, MonoString* uniform, glm::vec4* value);
|
||||
void Prism_MaterialInstance_SetTexture(Ref<MaterialInstance>* _this, MonoString* uniform, Ref<Texture2D>* texture);
|
||||
|
||||
// Mesh
|
||||
|
||||
Reference in New Issue
Block a user