mirror of
https://github.com/antopilo/Nuake.git
synced 2026-01-03 14:09:46 +03:00
Merge branch 'main' into feature/NK-138-nuake-runtime
# Conflicts: # Editor/Runtime.cpp
This commit is contained in:
BIN
Editor/resources/Models/Camera.glb
Normal file
BIN
Editor/resources/Models/Camera.glb
Normal file
Binary file not shown.
@@ -24,6 +24,8 @@ class Scene {
|
||||
return Light.new(id)
|
||||
} else if (component == "CharacterController") {
|
||||
return CharacterController.new(id)
|
||||
} else if (component == "RigidBody") {
|
||||
return RigidBody.new(id)
|
||||
} else if (component == "Camera") {
|
||||
return Camera.new(id)
|
||||
} else if (component == "Transform") {
|
||||
@@ -70,6 +72,31 @@ class Scene {
|
||||
foreign static IsCharacterControllerOnGround_(e)
|
||||
//foreign static IsOnGround_(e)
|
||||
|
||||
// RigidBody
|
||||
foreign static AddForce_(e, x, y, z)
|
||||
|
||||
// Physics
|
||||
static RayCast(from, to) {
|
||||
// Fetch results from physics manager, returns a list of floats
|
||||
// that we need to unpack into vector3
|
||||
var results = Scene.RayCast_(from.x, from.y, from.z, to.x, to.y, to.z)
|
||||
|
||||
var points = [] // Result array of vec3
|
||||
|
||||
var size = results.count / 3
|
||||
var i = 0
|
||||
while(i < size) {
|
||||
// size is base 1 while array is base 0, offset by 1
|
||||
var listIndex = i - 1
|
||||
points.add(Vector3.new(results[listIndex], results[listIndex + 1], results[listIndex + 2]))
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
return points
|
||||
}
|
||||
|
||||
foreign static RayCast_(fromX, fromY, fromZ, toX, toY, toZ)
|
||||
|
||||
foreign static TriggerGetOverlappingBodyCount_(e)
|
||||
foreign static TriggerGetOverlappingBodies_(e)
|
||||
|
||||
@@ -159,6 +186,16 @@ class CharacterController {
|
||||
}
|
||||
}
|
||||
|
||||
class RigidBody {
|
||||
construct new(id) {
|
||||
_entityId = id
|
||||
}
|
||||
|
||||
AddForce(force) {
|
||||
Scene.AddForce_(_entityId, force.x, force,y, force.z)
|
||||
}
|
||||
}
|
||||
|
||||
class Camera {
|
||||
construct new(id) {
|
||||
_entityId = id
|
||||
|
||||
@@ -23,7 +23,6 @@ void main()
|
||||
//T = normalize(T - dot(T, N) * N);
|
||||
//vec3 B = cross(N, T);
|
||||
|
||||
|
||||
vec3 T = normalize((u_Model * vec4(Tangent, 0.0f)).xyz);
|
||||
vec3 N = normalize((u_Model * vec4(Normal, 0.0f)).xyz);
|
||||
vec3 B = normalize((u_Model * vec4(Bitangent, 0.0f)).xyz);
|
||||
@@ -83,10 +82,17 @@ void main()
|
||||
// Albedo
|
||||
gAlbedo = vec4(m_AlbedoColor, 1.0);
|
||||
if (u_HasAlbedo == 1)
|
||||
gAlbedo.rgb = texture(m_Albedo, UV).rgb;
|
||||
{
|
||||
vec4 albedoSample = texture(m_Albedo, UV);
|
||||
gAlbedo.rgb = albedoSample.rgb * m_AlbedoColor.rgb;
|
||||
gAlbedo.a = albedoSample.a;
|
||||
|
||||
if (albedoSample.a < 0.1f)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
gAlbedo.rgb = texture(m_Albedo, UV).rgb * m_AlbedoColor.rgb;
|
||||
|
||||
// Material
|
||||
float finalMetalness = u_MetalnessValue;
|
||||
if (u_HasMetalness == 1)
|
||||
|
||||
@@ -8,6 +8,7 @@ out flat vec2 UV;
|
||||
out mat4 v_InvView;
|
||||
out mat4 v_InvProjection;
|
||||
out mat4 v_View;
|
||||
out mat4 v_Projection;
|
||||
|
||||
uniform mat4 u_View;
|
||||
uniform mat4 u_Projection;
|
||||
@@ -15,6 +16,7 @@ uniform mat4 u_Projection;
|
||||
void main()
|
||||
{
|
||||
v_View = u_View;
|
||||
v_Projection = u_Projection;
|
||||
v_InvView = inverse(u_View);
|
||||
v_InvProjection = inverse(u_Projection);
|
||||
|
||||
@@ -28,7 +30,6 @@ void main()
|
||||
uniform sampler2D u_Depth;
|
||||
uniform sampler2D u_Normal;
|
||||
uniform sampler2D u_Noise;
|
||||
|
||||
uniform int u_KernelSize = 64;
|
||||
|
||||
uniform vec3 u_Samples[64];
|
||||
@@ -39,13 +40,20 @@ uniform float u_Bias = 0.025f;
|
||||
uniform float u_Falloff = 0.0022;
|
||||
uniform float u_Area = 0.0075;
|
||||
uniform float u_Strength = 2.0f;
|
||||
|
||||
in vec2 UV;
|
||||
in mat4 v_View;
|
||||
in mat4 v_InvView;
|
||||
in mat4 v_InvProjection;
|
||||
in mat4 v_Projection;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
float linearize_depth(float d, float zNear, float zFar)
|
||||
{
|
||||
return zNear * zFar / (zFar + d * (zNear - zFar));
|
||||
}
|
||||
|
||||
vec3 WorldPosFromDepth(float depth)
|
||||
{
|
||||
float z = depth * 2.0 - 1.0;
|
||||
@@ -91,46 +99,54 @@ vec3 normal_from_depth(float depth, vec2 texcoords) {
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = texture(u_Depth, UV).r ;
|
||||
vec3 fragPos = ViewPosFromDepth(depth);
|
||||
float normalizedRadius = u_Radius;
|
||||
if(depth > 0.9999999f)
|
||||
float depth = texture(u_Depth, UV).r;
|
||||
if (depth > 0.9999999f)
|
||||
{
|
||||
FragColor = vec4(0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
vec3 goodNormal = normal_from_depth(depth, UV);
|
||||
vec3 normal = texture(u_Normal, UV).rgb * 2.0 - 1.0;
|
||||
vec4 normalT = v_View * vec4(normal, 1.0);
|
||||
normalT *= -1.0f;
|
||||
normal = normalT.xyz;
|
||||
normal = normalize(normal);
|
||||
normal = goodNormal;
|
||||
vec3 randomVec = texture(u_Noise, UV * u_NoiseScale).xyz;
|
||||
float radius_depth = normalizedRadius / depth;
|
||||
|
||||
const float SCALING_NEAR = 0.92;
|
||||
float depthScaler = (depth - SCALING_NEAR) / (1.0 - SCALING_NEAR);
|
||||
|
||||
const float minRadius = 0.05f;
|
||||
const float maxRadius = 1.2f;
|
||||
const float scalerPow = 1.8f;
|
||||
depthScaler = min(max(pow(depthScaler, scalerPow), minRadius), maxRadius);
|
||||
float scaledRadius = u_Radius * depthScaler;
|
||||
|
||||
vec3 fragPos = ViewPosFromDepth(depth);
|
||||
vec3 normal = texture(u_Normal, UV).xyz * 2.0 - 1.0;//normal_from_depth(depth, UV);
|
||||
normal.z *= -1.0f;
|
||||
// Remove translation from view;
|
||||
mat4 invView = v_InvView;
|
||||
invView[3] = vec4(0, 0, 0, 1);
|
||||
|
||||
normal = (invView * vec4(normal, 1.0f)).xyz;
|
||||
vec3 randomVec = texture(u_Noise, UV * u_NoiseScale).xyz;
|
||||
|
||||
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
|
||||
vec3 bitangent = cross(normal, tangent);
|
||||
mat3 TBN = mat3(tangent, bitangent, normal);
|
||||
|
||||
float occlusion = 0.0;
|
||||
vec3 position = vec3(UV, depth);
|
||||
|
||||
int skipped = 0;
|
||||
float rangeCheckC = 0.0f;
|
||||
for(int i=0; i < 64; i++)
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
vec3 ray = u_Radius * reflect(u_Samples[i], randomVec);
|
||||
vec3 hemi_ray = position + sign(dot(ray, normal)) * ray;
|
||||
|
||||
float sampleDepth = texture(u_Depth, hemi_ray.xy).r;
|
||||
float rangeCheck = smoothstep(0.0, 1.0, u_Radius * 0.8 / abs(depth - sampleDepth));
|
||||
float ao = hemi_ray.z >= sampleDepth + u_Bias ? 1.0 : 0.0;
|
||||
occlusion += ao * rangeCheck;
|
||||
rangeCheckC += rangeCheck;
|
||||
vec3 samplePos = TBN * u_Samples[i]; // generate a random point
|
||||
samplePos.z *= -1.0f;
|
||||
samplePos = fragPos + samplePos * scaledRadius;
|
||||
|
||||
vec4 offset = vec4(samplePos, 1.0); // make it a 4-vector
|
||||
offset = v_Projection * offset; // project on the near clipping plane
|
||||
offset.xyz /= offset.w; // perform perspective divide
|
||||
offset.xyz = offset.xyz * 0.5 + 0.5; // transform to (0,1) range
|
||||
float sampleDepth = texture(u_Depth, offset.xy).r;
|
||||
float rangeCheck = smoothstep(0.0, 1.0, scaledRadius / abs((samplePos.z) - sampleDepth));
|
||||
occlusion += (sampleDepth <= depth - u_Bias / 100.0 ? 1.0 : 0.0) * rangeCheck;
|
||||
}
|
||||
|
||||
|
||||
float ao = 1.0 - (occlusion / 64.0);
|
||||
rangeCheckC /= 64.0;
|
||||
|
||||
float finalAO = pow(ao, u_Strength);
|
||||
float finalAO = pow(ao, u_Strength * 100.0);
|
||||
FragColor = vec4(finalAO, finalAO, finalAO, 1.0);
|
||||
//FragColor = vec4(rangeCheckC, rangeCheckC, rangeCheckC, 1.0);
|
||||
|
||||
//FragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
@@ -36,7 +36,7 @@
|
||||
{ \
|
||||
delete boldFont; \
|
||||
ImGui::PopStyleVar(); \
|
||||
if (ImGui::BeginTable(#name, 3, ImGuiTableFlags_BordersInner)) \
|
||||
if (ImGui::BeginTable(#name, 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp)) \
|
||||
{ \
|
||||
ImGui::TableSetupColumn("name", 0, 0.25f); \
|
||||
ImGui::TableSetupColumn("set", 0, 0.65f); \
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
ImGui::Text("Color");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth());
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
ImGui::ColorEdit3("##lightcolor", &component.Color.r, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
|
||||
if (flagsHeaderOpened)
|
||||
{
|
||||
ImGui::BeginTable("##Flags", 3, ImGuiTableFlags_BordersInner);
|
||||
ImGui::BeginTable("##Flags", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp);
|
||||
{
|
||||
ImGui::TableSetupColumn("name", 0, 0.3f);
|
||||
ImGui::TableSetupColumn("set", 0, 0.6f);
|
||||
@@ -80,7 +80,7 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image1"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image1"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
@@ -118,7 +118,7 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image3"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image3"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
@@ -153,7 +153,7 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image2"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(1, 1, 1, 1), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image2"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(1, 1, 1, 1), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("Image files (*.png) | *.png | Image files (*.jpg) | *.jpg");
|
||||
if (texture != "")
|
||||
@@ -191,7 +191,7 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image4"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image4"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
@@ -229,7 +229,7 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image5"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image5"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
|
||||
88
Editor/src/ComponentsPanel/ParticleEmitterPanel.h
Normal file
88
Editor/src/ComponentsPanel/ParticleEmitterPanel.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/ParticleEmitterComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
class ParticleEmitterPanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
ParticleEmitterPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::ParticleEmitterComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::ParticleEmitterComponent>();
|
||||
BeginComponentTable(PARTICLE EMITTER, Nuake::ParticleEmitterComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Particle Color");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
ImGui::ColorEdit3("##lightcolor", &component.ParticleColor.r, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.ParticleColor, Nuake::Vector4(1, 1, 1, 1));
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Amount");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleAmount", &component.Amount, 0.1f, 0.0f, 500.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Amount, 10.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Rate");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleRate", &component.Rate, 0.1f, 0.0f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Rate, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Life");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleLife", &component.Life, 0.1f, 0.0f, 100.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Life, 5.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Gravity");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGuiHelper::DrawVec3("Gravity", &component.Gravity);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Gravity, Nuake::Vector3(0, -1, 0));
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Gravity Random");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##GravityRandom", &component.GravityRandom, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.GravityRandom, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Radius");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##ParticleRadius", &component.Radius, 0.01f, 0.0f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Radius, 1.0f);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
73
Editor/src/ComponentsPanel/SpritePanel.h
Normal file
73
Editor/src/ComponentsPanel/SpritePanel.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include <src/Core/FileSystem.h>
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/SpriteComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
|
||||
class SpritePanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
SpritePanel() = default;
|
||||
~SpritePanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::SpriteComponent>())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::SpriteComponent>();
|
||||
BeginComponentTable(SPRITE, Nuake::SpriteComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Sprite");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.SpritePath;
|
||||
ImGui::Button(path.empty() ? "Drag image" : component.SpritePath.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Image"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
|
||||
std::string fullPath = std::string(file, 512);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(std::move(fullPath));
|
||||
component.SpritePath = path;
|
||||
|
||||
component.LoadSprite();
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.LockYRotation, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Billboard");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##billboard", &component.Billboard);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Billboard, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Lock Y rotation");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##lockYRotation", &component.LockYRotation);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.LockYRotation, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <src/Scene/Components/CylinderColliderComponent.h>
|
||||
#include <src/Scene/Components/MeshCollider.h>
|
||||
#include <src/Scene/Components/ModelComponent.h>
|
||||
#include <src/Scene/Components/ParticleEmitterComponent.h>
|
||||
|
||||
|
||||
GizmoDrawer::GizmoDrawer()
|
||||
@@ -35,7 +36,7 @@ GizmoDrawer::GizmoDrawer()
|
||||
GenerateSphereGizmo();
|
||||
|
||||
// Box
|
||||
const Color cubeColor = Color(1, 0, 0, 1);
|
||||
const Color cubeColor = Color(1, 0, 0, 0.5f);
|
||||
std::vector<LineVertex> mBoxVertices =
|
||||
{
|
||||
LineVertex{Vector3(-1.f, -1.f, -1.f), cubeColor},
|
||||
@@ -110,8 +111,8 @@ void GizmoDrawer::GenerateSphereGizmo()
|
||||
vert2 = Vector3(x2, 0, z2);
|
||||
}
|
||||
|
||||
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) });
|
||||
circleVertices.push_back(LineVertex{ vert1, Color(1.0, 0, 0.0, 0.5) });
|
||||
circleVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.0, 0.5) });
|
||||
}
|
||||
|
||||
mCircleBuffer = CreateRef<Nuake::VertexArray>();
|
||||
@@ -217,6 +218,18 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene)
|
||||
Nuake::RenderCommand::DrawLines(0, 264);
|
||||
}
|
||||
|
||||
auto particleView = scene->m_Registry.view<TransformComponent, ParticleEmitterComponent>();
|
||||
for (auto e : particleView)
|
||||
{
|
||||
auto [transform, particle] = scene->m_Registry.get<TransformComponent, ParticleEmitterComponent>(e);
|
||||
mLineShader->Bind();
|
||||
mLineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), transform.Translation), Vector3(particle.Radius)));
|
||||
mLineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
|
||||
|
||||
mCircleBuffer->Bind();
|
||||
Nuake::RenderCommand::DrawLines(0, 128);
|
||||
}
|
||||
|
||||
auto meshColliderView = scene->m_Registry.view<TransformComponent, MeshColliderComponent, ModelComponent>();
|
||||
for (auto e : meshColliderView)
|
||||
{
|
||||
|
||||
@@ -62,8 +62,8 @@ void CapsuleGizmo::CreateMesh()
|
||||
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) });
|
||||
_CapsuleVertices.push_back(LineVertex{ vert1, Color(1.0, 0, 0.0, 0.5) });
|
||||
_CapsuleVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.0, 0.5) });
|
||||
}
|
||||
|
||||
for (int i = 0; i < subDivision * 2.0; i++)
|
||||
@@ -94,21 +94,21 @@ void CapsuleGizmo::CreateMesh()
|
||||
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{ vert1, Color(1.0, 0, 0.0, 0.5) });
|
||||
_CapsuleVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.0, 0.5) });
|
||||
}
|
||||
|
||||
_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, 0.5) });
|
||||
_CapsuleVertices.push_back(LineVertex{ Vector3(radius, topCircleHeight, 0), Color(1.0, 0, 0.0, 0.5) });
|
||||
|
||||
_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, 0.5) });
|
||||
_CapsuleVertices.push_back(LineVertex{ Vector3(-radius, topCircleHeight, 0), Color(1.0, 0, 0.0, 0.5) });
|
||||
|
||||
_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, 0.5) });
|
||||
_CapsuleVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, radius), Color(1.0, 0, 0.0, 0.5) });
|
||||
|
||||
_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, 0.5) });
|
||||
_CapsuleVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, -radius), Color(1.0, 0, 0.0, 0.5) });
|
||||
|
||||
_CapsuleBuffer = CreateRef<Nuake::VertexArray>();
|
||||
_CapsuleBuffer->Bind();
|
||||
|
||||
@@ -62,21 +62,21 @@ void CylinderGizmo::CreateMesh()
|
||||
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{ vert1, Color(1.0, 0, 0.0, 0.5) });
|
||||
_CylinderVertices.push_back(LineVertex{ vert2, Color(1.0, 0, 0.0, 0.5) });
|
||||
}
|
||||
|
||||
_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, 0.5) });
|
||||
_CylinderVertices.push_back(LineVertex{ Vector3(radius, topCircleHeight, 0), Color(1.0, 0, 0.0, 0.5) });
|
||||
|
||||
_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, 0.5) });
|
||||
_CylinderVertices.push_back(LineVertex{ Vector3(-radius, topCircleHeight, 0), Color(1.0, 0, 0.0, 0.5) });
|
||||
|
||||
_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, 0.5) });
|
||||
_CylinderVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, radius), Color(1.0, 0, 0.0, 0.5) });
|
||||
|
||||
_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, 0.5) });
|
||||
_CylinderVertices.push_back(LineVertex{ Vector3(0, topCircleHeight, -radius), Color(1.0, 0, 0.0, 0.5) });
|
||||
|
||||
_CylinderBuffer = CreateRef<Nuake::VertexArray>();
|
||||
_CylinderBuffer->Bind();
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#include "PopupHelper.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "regex"
|
||||
|
||||
|
||||
void PopupHelper::Confirmation(const std::string& id)
|
||||
void PopupHelper::OpenPopup(const std::string& id)
|
||||
{
|
||||
ImGui::TextWrapped(id.c_str());
|
||||
|
||||
ImGui::OpenPopup(id.c_str());
|
||||
}
|
||||
|
||||
bool PopupHelper::DefineDialog(const std::string& id, const std::string& text)
|
||||
bool PopupHelper::DefineConfirmationDialog(const std::string& id, const std::string& text)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
@@ -30,3 +30,56 @@ bool PopupHelper::DefineDialog(const std::string& id, const std::string& text)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PopupHelper::DefineTextDialog(const std::string& id, std::string& currentText)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||
|
||||
if (ImGui::BeginPopupModal(id.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize))
|
||||
{
|
||||
bool isSanitized = true;
|
||||
|
||||
char buffer[256];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
std::strncpy(buffer, currentText.c_str(), sizeof(buffer));
|
||||
if (ImGui::InputText("##label", buffer, sizeof(buffer)))
|
||||
{
|
||||
currentText = std::string(buffer);
|
||||
}
|
||||
|
||||
// returns false when there is a match, quirky
|
||||
if (!regex_match(buffer, std::regex("[^ \\ / :*? \"<>|]+")))
|
||||
{
|
||||
isSanitized = false;
|
||||
}
|
||||
|
||||
if (currentText.empty())
|
||||
{
|
||||
ImGui::TextColored(ImVec4(0.76, 0.45, 0.47, 1.0), "A file name can't be empty.");
|
||||
}
|
||||
else if (!isSanitized)
|
||||
{
|
||||
ImGui::TextColored(ImVec4(0.76, 0.45, 0.47, 1.0), "A file name can't contain any of the following characters: \\/:*?\"<>|");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("OK", ImVec2(120, 0)))
|
||||
{
|
||||
if (isSanitized)
|
||||
{
|
||||
result = true;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
ImGui::SetItemDefaultFocus();
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
class PopupHelper
|
||||
{
|
||||
public:
|
||||
static void Confirmation(const std::string& id);
|
||||
static bool DefineDialog(const std::string& id, const std::string& text);
|
||||
static void OpenPopup(const std::string& id);
|
||||
static bool DefineConfirmationDialog(const std::string& id, const std::string& text);
|
||||
static bool PopupHelper::DefineTextDialog(const std::string& id, std::string& currentText);
|
||||
};
|
||||
|
||||
@@ -16,18 +16,18 @@ public:
|
||||
for (int i = 0; i < numBus; i++)
|
||||
{
|
||||
const std::string busName = "Bus " + std::to_string(i);
|
||||
ImGui::BeginTable(busName.c_str(), 1, 0, ImVec2(300, ImGui::GetContentRegionAvail().y));
|
||||
|
||||
ImGui::TableSetupColumn(busName.c_str(), 0, 1.0f);
|
||||
ImGui::TableNextColumn ();
|
||||
ImGui::TableHeader(busName.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
const float height = ImGui::GetContentRegionAvail().y - 50;
|
||||
const std::string id = "##Volume" + std::to_string(i);
|
||||
ImGui::VSliderFloat(id.c_str(), ImVec2(50, height), &dummyVolume, -60.0f, 6.0f, "%.3dB", ImGuiSliderFlags_Logarithmic);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::EndTable();
|
||||
//ImGui::BeginTable(busName.c_str(), 1, 0, ImVec2(300, ImGui::GetContentRegionAvail().y));
|
||||
//
|
||||
//ImGui::TableSetupColumn(busName.c_str(), 0, 1.0f);
|
||||
//ImGui::TableNextColumn ();
|
||||
//ImGui::TableHeader(busName.c_str());
|
||||
//ImGui::TableNextColumn();
|
||||
//
|
||||
//const float height = ImGui::GetContentRegionAvail().y - 50;
|
||||
//const std::string id = "##Volume" + std::to_string(i);
|
||||
//ImGui::VSliderFloat(id.c_str(), ImVec2(50, height), &dummyVolume, -60.0f, 6.0f, "%.3dB", ImGuiSliderFlags_Logarithmic);
|
||||
//ImGui::TableNextColumn();
|
||||
//ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#include "../Misc/InterfaceFonts.h"
|
||||
|
||||
#include "WelcomeWindow.h"
|
||||
#include "LoadingSplash.h"
|
||||
|
||||
#include "src/Rendering/SceneRenderer.h"
|
||||
#include <dependencies/glfw/include/GLFW/glfw3.h>
|
||||
#include <src/Rendering/Buffers/Framebuffer.h>
|
||||
@@ -56,7 +58,6 @@ namespace Nuake {
|
||||
filesystem = new FileSystemUI(this);
|
||||
_WelcomeWindow = new WelcomeWindow(this);
|
||||
_audioWindow = new AudioWindow();
|
||||
m_EntitySelectionFramebuffer = CreateRef<FrameBuffer>(false, Vector2(1280, 720));
|
||||
}
|
||||
|
||||
void EditorInterface::Init()
|
||||
@@ -64,8 +65,8 @@ namespace Nuake {
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_AutoHideTabBar;
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->GetWorkPos());
|
||||
ImGui::SetNextWindowSize(viewport->GetWorkSize());
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
ImGui::SetNextWindowSize(viewport->Size);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
|
||||
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
|
||||
@@ -86,7 +87,7 @@ namespace Nuake {
|
||||
Overlay();
|
||||
ImGuizmo::BeginFrame();
|
||||
|
||||
float availWidth = ImGui::GetContentRegionAvailWidth();
|
||||
float availWidth = ImGui::GetContentRegionAvail().x;
|
||||
float windowWidth = ImGui::GetWindowWidth();
|
||||
|
||||
float used = windowWidth - availWidth;
|
||||
@@ -112,7 +113,7 @@ namespace Nuake {
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Dummy(ImVec2(ImGui::GetContentRegionAvailWidth() - 120, 30));
|
||||
ImGui::Dummy(ImVec2(ImGui::GetContentRegionAvail().x - 120, 30));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -124,7 +125,7 @@ namespace Nuake {
|
||||
ImGui::BeginChild("FPS", ImVec2(60, 30), false);
|
||||
|
||||
std::string text = std::to_string(fps) + " fps";
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvailWidth() / 1.25 - ImGui::CalcTextSize(text.c_str()).x
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x / 1.25 - ImGui::CalcTextSize(text.c_str()).x
|
||||
- ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 15 - (ImGui::CalcTextSize(text.c_str()).y) / 2.0);
|
||||
ImGui::Text(text.c_str());
|
||||
@@ -136,7 +137,7 @@ namespace Nuake {
|
||||
out.precision(2);
|
||||
out << std::fixed << frameTime;
|
||||
text = out.str() + " ms";
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvailWidth() / 1.25 - ImGui::CalcTextSize(text.c_str()).x
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x / 1.25 - ImGui::CalcTextSize(text.c_str()).x
|
||||
- ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 15 - (ImGui::CalcTextSize(text.c_str()).y) / 2.0);
|
||||
ImGui::Text(text.c_str());
|
||||
@@ -244,13 +245,17 @@ namespace Nuake {
|
||||
}
|
||||
}
|
||||
|
||||
m_IsViewportFocused = ImGui::IsWindowFocused();
|
||||
if (m_IsHoveringViewport && Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_2) && !ImGuizmo::IsUsing())
|
||||
if (m_IsHoveringViewport && !m_IsViewportFocused && Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_2))
|
||||
{
|
||||
ImGui::FocusWindow(ImGui::GetCurrentWindow());
|
||||
}
|
||||
|
||||
m_IsViewportFocused = ImGui::IsWindowFocused();
|
||||
|
||||
if (m_IsHoveringViewport && Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_1) && !ImGuizmo::IsUsing())
|
||||
{
|
||||
const auto windowPosNuake = Vector2(windowPos.x, windowPos.y);
|
||||
auto& gbuffer = Engine::GetCurrentScene()->mSceneRenderer->GetGBuffer();
|
||||
auto& gbuffer = Engine::GetCurrentScene()->m_SceneRenderer->GetGBuffer();
|
||||
auto pixelPos = Input::GetMousePosition() - windowPosNuake;
|
||||
pixelPos.y = gbuffer.GetSize().y - pixelPos.y; // imgui coords are inverted on the Y axis
|
||||
|
||||
@@ -258,7 +263,11 @@ namespace Nuake {
|
||||
|
||||
if (const int result = gbuffer.ReadPixel(3, pixelPos); result > 0)
|
||||
{
|
||||
Selection = EditorSelection(Entity{ (entt::entity)(result - 1), Engine::GetCurrentScene().get()});
|
||||
auto& ent = Entity{ (entt::entity)(result - 1), Engine::GetCurrentScene().get() };
|
||||
if (ent.IsValid())
|
||||
{
|
||||
Selection = EditorSelection(ent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -403,8 +412,18 @@ namespace Nuake {
|
||||
{
|
||||
Ref<Prefab> newPrefab = Prefab::CreatePrefabFromEntity(Selection.Entity);
|
||||
std::string savePath = FileDialog::SaveFile("*.prefab");
|
||||
newPrefab->SaveAs(savePath);
|
||||
Selection.Entity.AddComponent<PrefabComponent>().PrefabInstance = newPrefab;
|
||||
if (!String::EndsWith(savePath, ".prefab"))
|
||||
{
|
||||
savePath += ".prefab";
|
||||
}
|
||||
|
||||
if (!savePath.empty())
|
||||
{
|
||||
newPrefab->SaveAs(savePath);
|
||||
Selection.Entity.AddComponent<PrefabComponent>().PrefabInstance = newPrefab;
|
||||
FileSystem::Scan();
|
||||
FileSystemUI::m_CurrentDirectory = FileSystem::RootDirectory;
|
||||
}
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -446,7 +465,7 @@ namespace Nuake {
|
||||
if (ImGui::Begin("Environnement"))
|
||||
{
|
||||
BEGIN_COLLAPSE_HEADER(SKY);
|
||||
if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner))
|
||||
if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp))
|
||||
{
|
||||
ImGui::TableSetupColumn("name", 0, 0.3);
|
||||
ImGui::TableSetupColumn("set", 0, 0.6);
|
||||
@@ -611,7 +630,7 @@ namespace Nuake {
|
||||
END_COLLAPSE_HEADER()
|
||||
|
||||
BEGIN_COLLAPSE_HEADER(BLOOM)
|
||||
if (ImGui::BeginTable("BloomTable", 3, ImGuiTableFlags_BordersInner))
|
||||
if (ImGui::BeginTable("BloomTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp))
|
||||
{
|
||||
ImGui::TableSetupColumn("name", 0, 0.3);
|
||||
ImGui::TableSetupColumn("set", 0, 0.6);
|
||||
@@ -673,7 +692,7 @@ namespace Nuake {
|
||||
END_COLLAPSE_HEADER()
|
||||
|
||||
BEGIN_COLLAPSE_HEADER(VOLUMETRIC)
|
||||
if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner))
|
||||
if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp))
|
||||
{
|
||||
ImGui::TableSetupColumn("name", 0, 0.3);
|
||||
ImGui::TableSetupColumn("set", 0, 0.6);
|
||||
@@ -737,7 +756,7 @@ namespace Nuake {
|
||||
END_COLLAPSE_HEADER()
|
||||
|
||||
BEGIN_COLLAPSE_HEADER(SSAO)
|
||||
if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner))
|
||||
if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp))
|
||||
{
|
||||
ImGui::TableSetupColumn("name", 0, 0.3);
|
||||
ImGui::TableSetupColumn("set", 0, 0.6);
|
||||
@@ -828,7 +847,7 @@ namespace Nuake {
|
||||
END_COLLAPSE_HEADER()
|
||||
|
||||
BEGIN_COLLAPSE_HEADER(SSR)
|
||||
if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner))
|
||||
if (ImGui::BeginTable("EnvTable", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp))
|
||||
{
|
||||
ImGui::TableSetupColumn("name", 0, 0.3);
|
||||
ImGui::TableSetupColumn("set", 0, 0.6);
|
||||
@@ -836,7 +855,7 @@ namespace Nuake {
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
SSR* ssr = scene->mSceneRenderer->mSSR.get();
|
||||
SSR* ssr = scene->m_SceneRenderer->mSSR.get();
|
||||
{
|
||||
// Title
|
||||
ImGui::Text("SSR RayStep");
|
||||
@@ -1000,7 +1019,7 @@ namespace Nuake {
|
||||
if (ImGui::Begin(title.c_str()))
|
||||
{
|
||||
// Buttons to add and remove entity.
|
||||
if(ImGui::BeginChild("Buttons", ImVec2(ImGui::GetContentRegionAvailWidth(), 30), false))
|
||||
if(ImGui::BeginChild("Buttons", ImVec2(ImGui::GetContentRegionAvail().x, 30), false))
|
||||
{
|
||||
// Add entity.
|
||||
if (ImGui::Button(ICON_FA_PLUS, ImVec2(30, 30)))
|
||||
@@ -1020,10 +1039,10 @@ namespace Nuake {
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(26.f / 255.0f, 26.f / 255.0f, 26.f / 255.0f, 1));
|
||||
if (ImGui::BeginChild("Scene tree", ImGui::GetContentRegionAvail(), false))
|
||||
{
|
||||
if (ImGui::BeginTable("entity_table", 2, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_NoBordersInBody))
|
||||
if (ImGui::BeginTable("entity_table", 2, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_SizingStretchProp))
|
||||
{
|
||||
std::string icon = ICON_FA_EYE;
|
||||
ImGui::TableSetupColumn((" " + icon).c_str(), ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed, 16);
|
||||
ImGui::TableSetupColumn((" " + icon).c_str(), ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed, 32);
|
||||
ImGui::TableSetupColumn("Label", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentEnable);
|
||||
ImGui::TableHeadersRow();
|
||||
ImGui::TableNextRow();
|
||||
@@ -1364,7 +1383,7 @@ namespace Nuake {
|
||||
|
||||
Selection = EditorSelection();
|
||||
}
|
||||
if (ImGui::MenuItem("Open...", "CTRL+O"))
|
||||
if (ImGui::MenuItem("Open..."))
|
||||
{
|
||||
OpenProject();
|
||||
|
||||
@@ -1395,7 +1414,7 @@ namespace Nuake {
|
||||
Engine::LoadScene(Scene::New());
|
||||
Selection = EditorSelection();
|
||||
}
|
||||
if (ImGui::MenuItem("Open scene...", "CTRL+SHIFT+O"))
|
||||
if (ImGui::MenuItem("Open scene...", "CTRL+O"))
|
||||
{
|
||||
OpenScene();
|
||||
Selection = EditorSelection();
|
||||
@@ -1496,10 +1515,66 @@ namespace Nuake {
|
||||
}
|
||||
}
|
||||
|
||||
bool isLoadingProject = false;
|
||||
bool isLoadingProjectQueue = false;
|
||||
|
||||
int frameCount = 2;
|
||||
void EditorInterface::Draw()
|
||||
{
|
||||
Init();
|
||||
|
||||
if (isLoadingProjectQueue)
|
||||
{
|
||||
_WelcomeWindow->LoadQueuedProject();
|
||||
isLoadingProjectQueue = false;
|
||||
|
||||
auto& window = Window::Get();
|
||||
window->SetDecorated(true);
|
||||
window->SetSize({ 1900, 1000 });
|
||||
window->Center();
|
||||
frameCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
|
||||
{
|
||||
if(ImGui::IsKeyPressed(ImGuiKey_S))
|
||||
{
|
||||
Engine::GetProject()->Save();
|
||||
Engine::GetCurrentScene()->Save();
|
||||
|
||||
Selection = EditorSelection();
|
||||
}
|
||||
else if(ImGui::IsKeyPressed(ImGuiKey_O))
|
||||
{
|
||||
OpenScene();
|
||||
|
||||
Selection = EditorSelection();
|
||||
}
|
||||
else if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyPressed(ImGuiKey_S))
|
||||
{
|
||||
std::string savePath = FileDialog::SaveFile("*.project");
|
||||
Engine::GetProject()->SaveAs(savePath);
|
||||
|
||||
Selection = EditorSelection();
|
||||
}
|
||||
}
|
||||
|
||||
if (_WelcomeWindow->IsProjectQueued() && frameCount > 0)
|
||||
{
|
||||
// draw splash
|
||||
LoadingSplash::Get().Draw();
|
||||
|
||||
frameCount--;
|
||||
if (frameCount == 0)
|
||||
{
|
||||
isLoadingProjectQueue = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Engine::GetProject())
|
||||
{
|
||||
_WelcomeWindow->Draw();
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace Nuake
|
||||
ImGuizmo::MODE CurrentMode = ImGuizmo::WORLD;
|
||||
Ref<Material> m_SelectedMaterial;
|
||||
Ref<Directory> m_CurrentDirectory;
|
||||
Ref<FrameBuffer> m_EntitySelectionFramebuffer;
|
||||
|
||||
bool m_IsMaterialSelected = false;
|
||||
public:
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
#include "EditorSelectionPanel.h"
|
||||
#include "../Misc/ImGuiTextHelper.h"
|
||||
#include <src/Scene/Components/Components.h>
|
||||
@@ -9,16 +11,11 @@
|
||||
#include <Engine.h>
|
||||
|
||||
#include "src/Scene/Components/WrenScriptComponent.h"
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
|
||||
|
||||
EditorSelectionPanel::EditorSelectionPanel()
|
||||
{
|
||||
mTransformPanel = TransformPanel();
|
||||
mLightPanel = LightPanel();
|
||||
mScriptPanel = ScriptPanel();
|
||||
mQuakeMapPanel = QuakeMapPanel();
|
||||
mCameraPanel = CameraPanel();
|
||||
mRigidbodyPanel = RigidbodyPanel();
|
||||
mBoxColliderPanel = BoxColliderPanel();
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::ResolveFile(Ref<Nuake::File> file)
|
||||
@@ -92,12 +89,19 @@ void EditorSelectionPanel::DrawNone()
|
||||
|
||||
void EditorSelectionPanel::DrawEntity(Nuake::Entity entity)
|
||||
{
|
||||
if (!entity.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DrawAddComponentMenu(entity);
|
||||
|
||||
// Draw each component properties panels.
|
||||
mTransformPanel.Draw(entity);
|
||||
mLightPanel.Draw(entity);
|
||||
mScriptPanel.Draw(entity);
|
||||
mParticleEmitterPanel.Draw(entity);
|
||||
mSpritePanel.Draw(entity);
|
||||
mMeshPanel.Draw(entity);
|
||||
mQuakeMapPanel.Draw(entity);
|
||||
mCameraPanel.Draw(entity);
|
||||
@@ -127,6 +131,8 @@ void EditorSelectionPanel::DrawAddComponentMenu(Nuake::Entity entity)
|
||||
MenuItemComponent("Camera", Nuake::CameraComponent)
|
||||
MenuItemComponent("Light", Nuake::LightComponent)
|
||||
MenuItemComponent("Model", Nuake::ModelComponent)
|
||||
MenuItemComponent("Sprite", Nuake::SpriteComponent)
|
||||
MenuItemComponent("Particle Emitter", Nuake::ParticleEmitterComponent)
|
||||
ImGui::Separator();
|
||||
MenuItemComponent("Character Controller", Nuake::CharacterControllerComponent)
|
||||
MenuItemComponent("Rigid body", Nuake::RigidBodyComponent)
|
||||
@@ -243,7 +249,7 @@ void EditorSelectionPanel::DrawMaterialPanel(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image1"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image1"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
@@ -281,7 +287,7 @@ void EditorSelectionPanel::DrawMaterialPanel(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image3"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image3"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
@@ -316,7 +322,7 @@ void EditorSelectionPanel::DrawMaterialPanel(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image2"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(1, 1, 1, 1), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image2"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(1, 1, 1, 1), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("Image files (*.png) | *.png | Image files (*.jpg) | *.jpg");
|
||||
if (texture != "")
|
||||
@@ -351,7 +357,7 @@ void EditorSelectionPanel::DrawMaterialPanel(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image4"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image4"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
@@ -389,7 +395,7 @@ void EditorSelectionPanel::DrawMaterialPanel(Ref<Nuake::Material> material)
|
||||
textureID = TextureManager::Get()->GetTexture("default")->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image5"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2, 2), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image5"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
|
||||
@@ -18,8 +18,12 @@
|
||||
#include "../ComponentsPanel/SphereColliderPanel.h"
|
||||
#include "../ComponentsPanel/MeshColliderPanel.h"
|
||||
#include "../ComponentsPanel/CharacterControllerPanel.h"
|
||||
#include "../ComponentsPanel/SpritePanel.h"
|
||||
#include "../ComponentsPanel/ParticleEmitterPanel.h"
|
||||
|
||||
class EditorSelectionPanel {
|
||||
|
||||
class EditorSelectionPanel
|
||||
{
|
||||
private:
|
||||
TransformPanel mTransformPanel;
|
||||
LightPanel mLightPanel;
|
||||
@@ -33,8 +37,9 @@ private:
|
||||
MeshColliderPanel mMeshColliderPanel;
|
||||
CapsuleColliderPanel mCapsuleColliderPanel;
|
||||
CylinderColliderPanel mCylinderColliderPanel;
|
||||
|
||||
SpritePanel mSpritePanel;
|
||||
CharacterControllerPanel mCharacterControllerPanel;
|
||||
ParticleEmitterPanel mParticleEmitterPanel;
|
||||
|
||||
Ref<Nuake::File> currentFile;
|
||||
Ref<Nuake::Resource> selectedResource;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
#include "FileSystemUI.h"
|
||||
|
||||
#include <src/Vendors/imgui/imgui.h>
|
||||
@@ -30,6 +31,9 @@ namespace Nuake
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::string renameTempValue = "";
|
||||
|
||||
void FileSystemUI::EditorInterfaceDrawFiletree(Ref<Directory> dir)
|
||||
{
|
||||
ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_FramePadding;
|
||||
@@ -55,7 +59,7 @@ namespace Nuake
|
||||
}
|
||||
}
|
||||
|
||||
void FileSystemUI::DrawDirectory(Ref<Directory> directory)
|
||||
void FileSystemUI::DrawDirectory(Ref<Directory> directory, uint32_t drawId)
|
||||
{
|
||||
ImGui::PushFont(FontManager::GetFont(Icons));
|
||||
const char* icon = ICON_FA_FOLDER;
|
||||
@@ -65,6 +69,98 @@ namespace Nuake
|
||||
m_CurrentDirectory = directory;
|
||||
}
|
||||
|
||||
const std::string hoverMenuId = std::string("item_hover_menu") + std::to_string(drawId);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseReleased(1))
|
||||
{
|
||||
ImGui::OpenPopup(hoverMenuId.c_str());
|
||||
m_hasClickedOnFile = true;
|
||||
}
|
||||
|
||||
const std::string renameId = "Rename" + std::string("##") + hoverMenuId;
|
||||
bool shouldRename = false;
|
||||
|
||||
const std::string deleteId = "Delete" + std::string("##") + hoverMenuId;
|
||||
bool shouldDelete = false;
|
||||
|
||||
if (ImGui::BeginPopup(hoverMenuId.c_str()))
|
||||
{
|
||||
if (ImGui::MenuItem("Open"))
|
||||
{
|
||||
m_CurrentDirectory = directory;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginMenu("Copy"))
|
||||
{
|
||||
if (ImGui::MenuItem("Full Path"))
|
||||
{
|
||||
OS::CopyToClipboard(directory->fullPath);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Directory Name"))
|
||||
{
|
||||
OS::CopyToClipboard(String::Split(directory->name, '/')[0]);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Delete"))
|
||||
{
|
||||
shouldDelete = true;
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Rename"))
|
||||
{
|
||||
shouldRename = true;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Show in File Explorer"))
|
||||
{
|
||||
OS::OpenIn(directory->fullPath);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Rename Popup
|
||||
|
||||
if (shouldRename)
|
||||
{
|
||||
renameTempValue = directory->name;
|
||||
PopupHelper::OpenPopup(renameId);
|
||||
}
|
||||
|
||||
if (PopupHelper::DefineTextDialog(renameId, renameTempValue))
|
||||
{
|
||||
if (OS::RenameDirectory(directory, renameTempValue) != 0)
|
||||
{
|
||||
Logger::Log("Cannot rename directory: " + renameTempValue, "editor", CRITICAL);
|
||||
}
|
||||
RefreshFileBrowser();
|
||||
renameTempValue = "";
|
||||
}
|
||||
|
||||
// Delete Popup
|
||||
|
||||
if(shouldDelete)
|
||||
{
|
||||
PopupHelper::OpenPopup(deleteId);
|
||||
}
|
||||
|
||||
if(PopupHelper::DefineConfirmationDialog(deleteId, " Are you sure you want to delete the folder and all its children?\n This action cannot be undone, and all data within the folder \n will be permanently lost."))
|
||||
{
|
||||
if (FileSystem::DeleteFolder(directory->fullPath) != 0)
|
||||
{
|
||||
Logger::Log("Failed to remove directory: " + directory->name, "editor", CRITICAL);
|
||||
}
|
||||
RefreshFileBrowser();
|
||||
}
|
||||
|
||||
|
||||
ImGui::Text(directory->name.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
@@ -115,28 +211,42 @@ namespace Nuake
|
||||
{
|
||||
Editor->Selection = EditorSelection(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropSource())
|
||||
if (ImGui::BeginDragDropSource())
|
||||
{
|
||||
char pathBuffer[256];
|
||||
std::strncpy(pathBuffer, file->GetAbsolutePath().c_str(), sizeof(pathBuffer));
|
||||
std::string dragType;
|
||||
if (fileExtension == ".wren")
|
||||
{
|
||||
dragType = "_Script";
|
||||
}
|
||||
else if (fileExtension == ".map")
|
||||
{
|
||||
dragType = "_Map";
|
||||
}
|
||||
else if (fileExtension == ".obj" || fileExtension == ".mdl" || fileExtension == ".gltf" || fileExtension == ".md3" || fileExtension == ".fbx")
|
||||
{
|
||||
dragType = "_Model";
|
||||
}
|
||||
else if (fileExtension == ".interface")
|
||||
{
|
||||
dragType = "_Interface";
|
||||
}
|
||||
else if (fileExtension == ".prefab")
|
||||
{
|
||||
dragType = "_Prefab";
|
||||
}
|
||||
else if (fileExtension == ".png" || fileExtension == ".jpg")
|
||||
{
|
||||
dragType = "_Image";
|
||||
}
|
||||
|
||||
ImGui::SetDragDropPayload(dragType.c_str(), (void*)(pathBuffer), sizeof(pathBuffer));
|
||||
ImGui::Text(file->GetName().c_str());
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
}
|
||||
|
||||
const std::string hoverMenuId = std::string("item_hover_menu") + std::to_string(drawId);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseReleased(1))
|
||||
@@ -144,52 +254,100 @@ namespace Nuake
|
||||
ImGui::OpenPopup(hoverMenuId.c_str());
|
||||
m_hasClickedOnFile = true;
|
||||
}
|
||||
|
||||
|
||||
const std::string openSceneId = "Open Scene" + std::string("##") + hoverMenuId;
|
||||
bool shouldOpenScene = false;
|
||||
|
||||
const std::string renameId = "Rename" + std::string("##") + hoverMenuId;
|
||||
bool shouldRename = false;
|
||||
|
||||
const std::string deleteId = "Delete" + std::string("##") + hoverMenuId;
|
||||
bool shouldDelete = false;
|
||||
|
||||
if (ImGui::BeginPopup(hoverMenuId.c_str()))
|
||||
{
|
||||
if (ImGui::MenuItem("Show in File Explorer"))
|
||||
if (file->GetExtension() != ".scene")
|
||||
{
|
||||
OS::ShowInFileExplorer(file->GetAbsolutePath());
|
||||
}
|
||||
|
||||
if(file->GetExtension() == ".wren")
|
||||
{
|
||||
ImGui::Separator();
|
||||
|
||||
if(ImGui::MenuItem("Open..."))
|
||||
if (ImGui::MenuItem("Open in Editor"))
|
||||
{
|
||||
OS::OpenIn(file->GetAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
if(file->GetExtension() != ".project")
|
||||
else
|
||||
{
|
||||
if (ImGui::MenuItem("Load Scene"))
|
||||
{
|
||||
shouldOpenScene = true;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginMenu("Copy"))
|
||||
{
|
||||
if (ImGui::MenuItem("Full Path"))
|
||||
{
|
||||
OS::CopyToClipboard(file->GetAbsolutePath());
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("File Name"))
|
||||
{
|
||||
OS::CopyToClipboard(file->GetName());
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (file->GetExtension() != ".project")
|
||||
{
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Delete"))
|
||||
{
|
||||
if(FileSystem::RemoveFile(file->GetAbsolutePath()) != 0)
|
||||
{
|
||||
Logger::Log("Failed to remove file: " + file->GetRelativePath(), "editor", CRITICAL);
|
||||
}
|
||||
RefreshFileBrowser();
|
||||
shouldDelete = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 1, 1, 0.2f));
|
||||
ImGui::MenuItem("Delete");
|
||||
ImGui::PopStyleColor();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
ImGui::TextUnformatted("The file you're trying to delete is currently loaded by the game engine.");
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Rename"))
|
||||
{
|
||||
shouldRename = true;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Show in File Explorer"))
|
||||
{
|
||||
OS::ShowInFileExplorer(file->GetAbsolutePath());
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
const std::string openScene = "Open Scene" + std::string("##") + hoverMenuId;
|
||||
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
|
||||
{
|
||||
if (file->GetExtension() == ".scene")
|
||||
{
|
||||
PopupHelper::Confirmation(openScene);
|
||||
}
|
||||
shouldOpenScene = file->GetExtension() == ".scene";
|
||||
}
|
||||
|
||||
if (PopupHelper::DefineDialog(openScene, "Open the scene? \n Changes will not be saved."))
|
||||
// Open Scene Popup
|
||||
|
||||
if (shouldOpenScene)
|
||||
{
|
||||
PopupHelper::OpenPopup(openSceneId);
|
||||
}
|
||||
|
||||
if (PopupHelper::DefineConfirmationDialog(openSceneId, " Open the scene? \n Changes will not be saved."))
|
||||
{
|
||||
Ref<Scene> scene = Scene::New();
|
||||
const std::string projectPath = file->GetAbsolutePath();
|
||||
@@ -203,6 +361,41 @@ namespace Nuake
|
||||
Engine::LoadScene(scene);
|
||||
}
|
||||
|
||||
// Rename Popup
|
||||
|
||||
if (shouldRename)
|
||||
{
|
||||
renameTempValue = file->GetName();
|
||||
PopupHelper::OpenPopup(renameId);
|
||||
}
|
||||
|
||||
if (PopupHelper::DefineTextDialog(renameId, renameTempValue))
|
||||
{
|
||||
if(OS::RenameFile(file, renameTempValue) != 0)
|
||||
{
|
||||
Logger::Log("Cannot rename file: " + renameTempValue, "editor", CRITICAL);
|
||||
}
|
||||
RefreshFileBrowser();
|
||||
renameTempValue = "";
|
||||
}
|
||||
|
||||
// Delete Popup
|
||||
|
||||
if(shouldDelete)
|
||||
{
|
||||
PopupHelper::OpenPopup(deleteId);
|
||||
}
|
||||
|
||||
if(PopupHelper::DefineConfirmationDialog(deleteId, " Are you sure you want to delete the file?\n This action cannot be undone, and all data \n will be permanently lost."))
|
||||
{
|
||||
if (FileSystem::DeleteFileFromPath(file->GetAbsolutePath()) != 0)
|
||||
{
|
||||
Logger::Log("Failed to remove file: " + file->GetRelativePath(), "editor", CRITICAL);
|
||||
}
|
||||
RefreshFileBrowser();
|
||||
}
|
||||
|
||||
|
||||
ImGui::Text(file->GetName().c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
@@ -247,7 +440,7 @@ namespace Nuake
|
||||
path += ".material";
|
||||
}
|
||||
|
||||
if (path != "")
|
||||
if (!path.empty())
|
||||
{
|
||||
Ref<Material> material = CreateRef<Material>();
|
||||
material->IsEmbedded = false;
|
||||
@@ -353,8 +546,6 @@ namespace Nuake
|
||||
ImGui::EndChild();
|
||||
ImGui::SameLine();
|
||||
|
||||
avail = ImGui::GetContentRegionAvail();
|
||||
|
||||
std::vector<Ref<Directory>> paths = std::vector<Ref<Directory>>();
|
||||
|
||||
Ref<Directory> currentParent = m_CurrentDirectory;
|
||||
@@ -402,12 +593,13 @@ namespace Nuake
|
||||
}
|
||||
|
||||
const uint32_t numButtonAfterPathBrowser = 2;
|
||||
const uint32_t searchBarSize = 6;
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, colors[ImGuiCol_TitleBgCollapsed]);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
|
||||
ImGui::BeginChild("pathBrowser", ImVec2(ImGui::GetContentRegionAvailWidth() - (numButtonAfterPathBrowser * buttonWidth) - 4.0, 24));
|
||||
ImGui::BeginChild("pathBrowser", ImVec2((ImGui::GetContentRegionAvail().x - (numButtonAfterPathBrowser * buttonWidth * searchBarSize)) - 4.0, 24));
|
||||
for (int i = paths.size() - 1; i > 0; i--)
|
||||
{
|
||||
if (i != paths.size())
|
||||
@@ -431,13 +623,23 @@ namespace Nuake
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("/");
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginChild("searchBar", ImVec2(ImGui::GetContentRegionAvail().x - (numButtonAfterPathBrowser * buttonWidth), 24));
|
||||
char buffer[256];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
std::strncpy(buffer, m_searchKeyWord.c_str(), sizeof(buffer));
|
||||
if (ImGui::InputTextEx("##Search", "Asset search & filter ..", buffer, sizeof(buffer), ImVec2(ImGui::GetContentRegionAvail().x, 24), ImGuiInputTextFlags_EscapeClearsAll))
|
||||
{
|
||||
m_searchKeyWord = std::string(buffer);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -454,12 +656,13 @@ namespace Nuake
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(); // Button color
|
||||
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
ImGui::GetWindowDrawList()->AddLine(ImVec2(ImGui::GetCursorPosX(), ImGui::GetCursorPosY()), ImVec2(ImGui::GetContentRegionAvailWidth(), ImGui::GetCursorPosY()), IM_COL32(255, 0, 0, 255), 1.0f);
|
||||
ImGui::GetWindowDrawList()->AddLine(ImVec2(ImGui::GetCursorPosX(), ImGui::GetCursorPosY()), ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetCursorPosY()), IM_COL32(255, 0, 0, 255), 1.0f);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0));
|
||||
avail = ImGui::GetContentRegionAvail();
|
||||
@@ -489,13 +692,16 @@ namespace Nuake
|
||||
{
|
||||
for (Ref<Directory>& d : m_CurrentDirectory->Directories)
|
||||
{
|
||||
if (i + 1 % amount != 0)
|
||||
ImGui::TableNextColumn();
|
||||
else
|
||||
ImGui::TableNextRow();
|
||||
if(String::Sanitize(d->name).find(String::Sanitize(m_searchKeyWord)) != std::string::npos)
|
||||
{
|
||||
if (i + 1 % amount != 0)
|
||||
ImGui::TableNextColumn();
|
||||
else
|
||||
ImGui::TableNextRow();
|
||||
|
||||
DrawDirectory(d);
|
||||
i++;
|
||||
DrawDirectory(d, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,13 +709,16 @@ namespace Nuake
|
||||
{
|
||||
for (auto f : m_CurrentDirectory->Files)
|
||||
{
|
||||
if (i - 1 % amount != 0 || i == 1)
|
||||
ImGui::TableNextColumn();
|
||||
else
|
||||
ImGui::TableNextRow();
|
||||
if(String::Sanitize(f->GetName()).find(String::Sanitize(m_searchKeyWord)) != std::string::npos)
|
||||
{
|
||||
if (i - 1 % amount != 0 || i == 1)
|
||||
ImGui::TableNextColumn();
|
||||
else
|
||||
ImGui::TableNextRow();
|
||||
|
||||
DrawFile(f, i);
|
||||
i++;
|
||||
DrawFile(f, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Nuake {
|
||||
public:
|
||||
static Ref<Directory> m_CurrentDirectory;
|
||||
bool m_hasClickedOnFile;
|
||||
std::string m_searchKeyWord;
|
||||
|
||||
FileSystemUI(EditorInterface* editor)
|
||||
{
|
||||
@@ -24,7 +25,7 @@ namespace Nuake {
|
||||
void DrawDirectoryContent();
|
||||
void DrawFiletree();
|
||||
void EditorInterfaceDrawFiletree(Ref<Directory> dir);
|
||||
void DrawDirectory(Ref<Directory> directory);
|
||||
void DrawDirectory(Ref<Directory> directory, uint32_t drawId);
|
||||
bool EntityContainsItself(Entity source, Entity target);
|
||||
void DrawFile(Ref<File> file, uint32_t drawId);
|
||||
void DrawDirectoryExplorer();
|
||||
|
||||
51
Editor/src/Windows/LoadingSplash.cpp
Normal file
51
Editor/src/Windows/LoadingSplash.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "LoadingSplash.h"
|
||||
|
||||
#include "../Misc/InterfaceFonts.h"
|
||||
|
||||
#include <src/Core/Maths.h>
|
||||
#include "src/Window.h"
|
||||
|
||||
|
||||
#include <src/Vendors/imgui/imgui.h>
|
||||
|
||||
#include <dependencies/glfw/include/GLFW/glfw3.h>
|
||||
#include <src/Rendering/Textures/TextureManager.h>
|
||||
|
||||
|
||||
LoadingSplash::LoadingSplash()
|
||||
{
|
||||
_NuakeLogo = Nuake::TextureManager::Get()->GetTexture(NUAKE_LOGO_PATH);
|
||||
|
||||
Nuake::Window::Get()->SetDecorated(false);
|
||||
Nuake::Window::Get()->SetSize({ 640, 480 });
|
||||
Nuake::Window::Get()->Center();
|
||||
}
|
||||
|
||||
void LoadingSplash::Draw()
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
// Make viewport fullscreen
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
ImGui::SetNextWindowSize(viewport->Size);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(32.0f, 32.0f));
|
||||
ImGui::Begin("Welcome Screen", 0, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize);
|
||||
{
|
||||
// Draw Nuake logo
|
||||
{
|
||||
const Vector2 logoSize = _NuakeLogo->GetSize();
|
||||
const ImVec2 imguiSize = ImVec2(logoSize.x, logoSize.y);
|
||||
ImGui::Image((ImTextureID)_NuakeLogo->GetID(), imguiSize, ImVec2(0, 1), ImVec2(1, 0));
|
||||
}
|
||||
|
||||
ImGui::Text("LOADING SCENE...");
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
29
Editor/src/Windows/LoadingSplash.h
Normal file
29
Editor/src/Windows/LoadingSplash.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include <src/Core/Core.h>
|
||||
#include <src/Rendering/Textures/Texture.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class Texture;
|
||||
}
|
||||
|
||||
class LoadingSplash
|
||||
{
|
||||
private:
|
||||
const std::string NUAKE_LOGO_PATH = "resources/Images/logo_white.png";
|
||||
Ref<Nuake::Texture> _NuakeLogo;
|
||||
|
||||
public:
|
||||
static LoadingSplash& LoadingSplash::Get()
|
||||
{
|
||||
static LoadingSplash instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
LoadingSplash();
|
||||
~LoadingSplash() = default;
|
||||
|
||||
void Draw();
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include "WelcomeWindow.h"
|
||||
|
||||
#include <src/Vendors/imgui/imgui.h>
|
||||
@@ -59,10 +60,8 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool ProjectPreview::Deserialize(const std::string& str)
|
||||
bool ProjectPreview::Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE(str);
|
||||
|
||||
if (!j.contains("Path"))
|
||||
return false;
|
||||
|
||||
@@ -81,12 +80,37 @@ namespace Nuake
|
||||
_NuakeLogo = TextureManager::Get()->GetTexture(NUAKE_LOGO_PATH);
|
||||
}
|
||||
|
||||
void WelcomeWindow::LoadQueuedProject()
|
||||
{
|
||||
FileSystem::SetRootDirectory(FileSystem::GetParentPath(queuedProjectPath));
|
||||
auto project = Project::New();
|
||||
auto projectFileData = FileSystem::ReadFile(queuedProjectPath, true);
|
||||
try
|
||||
{
|
||||
project->Deserialize(nlohmann::json::parse(projectFileData));
|
||||
project->FullPath = queuedProjectPath;
|
||||
|
||||
Engine::LoadProject(project);
|
||||
|
||||
_Editor->filesystem->m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
|
||||
}
|
||||
catch (std::exception exception)
|
||||
{
|
||||
Logger::Log("Error loading project: " + queuedProjectPath, "editor", CRITICAL);
|
||||
Logger::Log(exception.what());
|
||||
return;
|
||||
}
|
||||
|
||||
queuedProjectPath = "";
|
||||
Engine::GetCurrentWindow()->SetTitle("Nuake Engine - Editing " + project->Name);
|
||||
}
|
||||
|
||||
void WelcomeWindow::Draw()
|
||||
{
|
||||
// Make viewport fullscreen
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->GetWorkPos());
|
||||
ImGui::SetNextWindowSize(viewport->GetWorkSize());
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
ImGui::SetNextWindowSize(viewport->Size);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
@@ -131,7 +155,7 @@ namespace Nuake
|
||||
}
|
||||
|
||||
const float itemHeight = 120.0f;
|
||||
if (ImGui::Button("Import an existing project", ImVec2(ImGui::GetContentRegionAvailWidth(), itemHeight)))
|
||||
if (ImGui::Button("Import an existing project", ImVec2(ImGui::GetContentRegionAvail().x, itemHeight)))
|
||||
{
|
||||
const std::string path = FileDialog::OpenFile("Project file |*.project");
|
||||
if (path != "" && String::EndsWith(path, ".project"))
|
||||
@@ -164,14 +188,14 @@ namespace Nuake
|
||||
|
||||
const std::string selectableName = "##" + std::to_string(itemIndex);
|
||||
const bool isSelected = SelectedProject == itemIndex;
|
||||
if (ImGui::Selectable(selectableName.c_str(), isSelected, ImGuiSelectableFlags_AllowItemOverlap, ImVec2(ImGui::GetContentRegionAvailWidth(), itemHeight)))
|
||||
if (ImGui::Selectable(selectableName.c_str(), isSelected, ImGuiSelectableFlags_AllowItemOverlap, ImVec2(ImGui::GetContentRegionAvail().x, itemHeight)))
|
||||
{
|
||||
SelectedProject = itemIndex;
|
||||
}
|
||||
|
||||
const ImVec2 padding = ImVec2(25.0f, 20.0f);
|
||||
const ImVec2 iconSize = ImVec2(100, 100);
|
||||
ImGui::SetCursorPos(padding / 2.0 + ImVec2(0, cursorYStart));
|
||||
ImGui::SetCursorPos(ImVec2(padding.x / 2.0, padding.y / 2.0) + ImVec2(0, cursorYStart));
|
||||
|
||||
ImGui::Image((ImTextureID)project.ProjectIcon->GetID(), iconSize, ImVec2(0, 1), ImVec2(1, 0));
|
||||
ImGui::SameLine();
|
||||
@@ -200,7 +224,7 @@ namespace Nuake
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::BeginChild("Controls", ImGui::GetContentRegionAvail(), false))
|
||||
{
|
||||
const ImVec2 buttonSize = ImVec2(ImGui::GetContentRegionAvailWidth(), buttonHeight);
|
||||
const ImVec2 buttonSize = ImVec2(ImGui::GetContentRegionAvail().x, buttonHeight);
|
||||
if (ImGui::Button("Create a new project", buttonSize))
|
||||
{
|
||||
std::string selectedProject = FileDialog::SaveFile("Project file\0*.project");
|
||||
@@ -249,31 +273,9 @@ namespace Nuake
|
||||
{
|
||||
assert(SelectedProject < std::size(_Projects));
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
SaveRecentFile();
|
||||
|
||||
std::string projectPath = _Projects[SelectedProject].Path;
|
||||
FileSystem::SetRootDirectory(FileSystem::GetParentPath(projectPath));
|
||||
|
||||
auto project = Project::New();
|
||||
auto projectFileData = FileSystem::ReadFile(projectPath, true);
|
||||
try
|
||||
{
|
||||
project->Deserialize(projectFileData);
|
||||
project->FullPath = projectPath;
|
||||
|
||||
Engine::LoadProject(project);
|
||||
|
||||
_Editor->filesystem->m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
|
||||
}
|
||||
catch (std::exception exception)
|
||||
{
|
||||
Logger::Log("Error loading project: " + projectPath, "editor", CRITICAL);
|
||||
Logger::Log(exception.what());
|
||||
}
|
||||
|
||||
Engine::GetCurrentWindow()->SetTitle("Nuake Engine - Editing " + project->Name);
|
||||
queuedProjectPath = _Projects[SelectedProject].Path;;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,7 +300,7 @@ namespace Nuake
|
||||
for (auto& project : j["Projects"])
|
||||
{
|
||||
auto projectPreview = ProjectPreview();
|
||||
projectPreview.Deserialize(project.dump());
|
||||
projectPreview.Deserialize(project);
|
||||
_Projects.push_back(projectPreview);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Nuake
|
||||
~ProjectPreview() = default;
|
||||
|
||||
json Serialize() override;
|
||||
bool Deserialize(const std::string& data) override;
|
||||
bool Deserialize(const json& j) override;
|
||||
|
||||
private:
|
||||
void ReadProjectFile();
|
||||
@@ -41,13 +41,15 @@ namespace Nuake
|
||||
|
||||
uint32_t SelectedProject = 0;
|
||||
std::vector<ProjectPreview> _Projects;
|
||||
|
||||
std::string queuedProjectPath;
|
||||
public:
|
||||
WelcomeWindow(Nuake::EditorInterface* editor);
|
||||
~WelcomeWindow() = default;
|
||||
|
||||
void Draw();
|
||||
|
||||
bool IsProjectQueued() const { return !queuedProjectPath.empty(); };
|
||||
void LoadQueuedProject();
|
||||
private:
|
||||
void DrawRecentProjectsSection();
|
||||
void DrawProjectItem(const uint32_t projectPreview);
|
||||
|
||||
@@ -53,22 +53,20 @@ namespace Nuake
|
||||
s_CurrentWindow->Update(s_TimeStep);
|
||||
|
||||
// Play mode update all the entities, Editor does not.
|
||||
if (Engine::IsPlayMode())
|
||||
{
|
||||
s_FixedUpdateDifference += s_TimeStep;
|
||||
|
||||
// Fixed update
|
||||
while (s_FixedUpdateDifference >= s_FixedUpdateRate)
|
||||
{
|
||||
s_CurrentWindow->FixedUpdate(s_FixedUpdateDifference);
|
||||
|
||||
s_FixedUpdateDifference -= s_FixedUpdateRate;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!Engine::IsPlayMode())
|
||||
{
|
||||
GetCurrentScene()->EditorUpdate(s_TimeStep);
|
||||
}
|
||||
|
||||
s_FixedUpdateDifference += s_TimeStep;
|
||||
|
||||
// Fixed update
|
||||
while (s_FixedUpdateDifference >= s_FixedUpdateRate)
|
||||
{
|
||||
s_CurrentWindow->FixedUpdate(s_FixedUpdateDifference);
|
||||
|
||||
s_FixedUpdateDifference -= s_FixedUpdateRate;
|
||||
}
|
||||
}
|
||||
|
||||
Input::Update();
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class JoltImplementation
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "src/Resource/Model.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
#include "src/Core/Core.h"
|
||||
|
||||
#include "src/Resource/Resource.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class Mesh;
|
||||
|
||||
class Model : Resource, ISerializable
|
||||
{
|
||||
private:
|
||||
std::vector<Ref<Mesh>> m_Meshes;
|
||||
|
||||
public:
|
||||
Model();
|
||||
~Model();
|
||||
|
||||
bool LoadModel(const std::string& path);
|
||||
|
||||
std::vector<Ref<Mesh>>& GetMeshes();
|
||||
|
||||
json Serialize() override;
|
||||
bool Deserialize(const std::string& data) override;
|
||||
};
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "ParticleEmitter.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
#include "src/Resource/Serializable.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class ParticleEmitter
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
json Serialize();
|
||||
bool Deserialize(const std::string& str);
|
||||
};
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "src/Scene/Entities/Entity.h"
|
||||
|
||||
namespace Nuake {
|
||||
class PrefabComponent
|
||||
{
|
||||
public:
|
||||
Ref<Prefab> PrefabInstance;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
Submodule Nuake/dependencies/JoltPhysics updated: 0e4865a345...b767673cd5
@@ -70,19 +70,15 @@ namespace Nuake
|
||||
|
||||
newDir->Parent = directory;
|
||||
ScanDirectory(newDir);
|
||||
|
||||
directory->Directories.push_back(newDir);
|
||||
}
|
||||
else if (entry.is_regular_file())
|
||||
{
|
||||
std::string absolutePath = entry.path().string();
|
||||
std::string name = entry.path().filename().string();
|
||||
std::string extension = entry.path().extension().string();
|
||||
std::filesystem::path currentPath = entry.path();
|
||||
std::string absolutePath = currentPath.string();
|
||||
std::string name = currentPath.filename().string();
|
||||
std::string extension = currentPath.extension().string();
|
||||
Ref<File> newFile = CreateRef<File>(directory, absolutePath, name, extension);
|
||||
//newFile->Type = entry.path().extension().string();
|
||||
//newFile->name = entry.path().filename().string();
|
||||
//newFile->Parent = directory;
|
||||
//newFile->fullPath = entry.path().string();
|
||||
directory->Files.push_back(newFile);
|
||||
}
|
||||
}
|
||||
@@ -173,11 +169,16 @@ namespace Nuake
|
||||
fileWriter.close();
|
||||
}
|
||||
|
||||
int FileSystem::RemoveFile(const std::string& path)
|
||||
int FileSystem::DeleteFileFromPath(const std::string& path)
|
||||
{
|
||||
return std::remove(path.c_str());
|
||||
}
|
||||
|
||||
int FileSystem::DeleteFolder(const std::string& path)
|
||||
{
|
||||
return std::filesystem::remove_all(path.c_str());
|
||||
}
|
||||
|
||||
Ref<Directory> FileSystem::GetFileTree()
|
||||
{
|
||||
return RootDirectory;
|
||||
|
||||
@@ -46,7 +46,8 @@ namespace Nuake
|
||||
static bool BeginWriteFile(const std::string path);
|
||||
static bool WriteLine(const std::string line);
|
||||
static void EndWriteFile();
|
||||
static int RemoveFile(const std::string& path);
|
||||
static int DeleteFileFromPath(const std::string& path);
|
||||
static int DeleteFolder(const std::string& path);
|
||||
};
|
||||
|
||||
class File
|
||||
|
||||
@@ -1,11 +1,41 @@
|
||||
#include "OS.h"
|
||||
#include "src/Window.h"
|
||||
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "GLFW/glfw3native.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <Windows.h>
|
||||
#include <chrono>
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
int OS::GetTime()
|
||||
void OS::CopyToClipboard(const std::string& value)
|
||||
{
|
||||
auto glob = GlobalAlloc(GMEM_FIXED, 512);
|
||||
memcpy(glob, value.data(), value.size());
|
||||
OpenClipboard(glfwGetWin32Window(Window::Get()->GetHandle()));
|
||||
EmptyClipboard();
|
||||
SetClipboardData(CF_TEXT, glob);
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
std::string OS::GetFromClipboard()
|
||||
{
|
||||
OpenClipboard(nullptr);
|
||||
HANDLE hData = GetClipboardData(CF_TEXT);
|
||||
|
||||
char* pszText = static_cast<char*>(GlobalLock(hData));
|
||||
std::string text(pszText);
|
||||
|
||||
GlobalUnlock(hData);
|
||||
CloseClipboard();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
int OS::GetTime()
|
||||
{
|
||||
return static_cast<int>(std::chrono::system_clock::now().time_since_epoch().count());
|
||||
}
|
||||
@@ -15,6 +45,25 @@ void OS::OpenIn(const std::string& filePath)
|
||||
ShellExecuteA(nullptr, "open", filePath.c_str(), nullptr, nullptr, SW_SHOWDEFAULT);
|
||||
}
|
||||
|
||||
int OS::RenameFile(const Ref<File>& file, const std::string& newName)
|
||||
{
|
||||
std::string extension = !String::EndsWith(newName, file->GetExtension().c_str()) ? file->GetExtension() : "";
|
||||
std::string newFilePath = file->GetParent()->fullPath + newName + extension;
|
||||
|
||||
std::error_code resultError;
|
||||
std::filesystem::rename(file->GetAbsolutePath().c_str(), newFilePath.c_str(), resultError);
|
||||
return resultError.value() == 0;
|
||||
}
|
||||
|
||||
int OS::RenameDirectory(const Ref<Directory>& dir, const std::string& newName)
|
||||
{
|
||||
std::string newDirPath = dir->Parent->fullPath + newName;
|
||||
|
||||
std::error_code resultError;
|
||||
std::filesystem::rename(dir->fullPath.c_str(), newDirPath.c_str(), resultError);
|
||||
return resultError.value() == 0;
|
||||
}
|
||||
|
||||
void OS::ShowInFileExplorer(const std::string& filePath)
|
||||
{
|
||||
ShellExecuteA(nullptr, "open", "explorer.exe", ("/select," + std::string(filePath)).c_str(), nullptr, SW_SHOWDEFAULT);
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "FileSystem.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class OS
|
||||
{
|
||||
public:
|
||||
static void CopyToClipboard(const std::string& value);
|
||||
static std::string GetFromClipboard();
|
||||
static int GetTime();
|
||||
static void OpenIn(const std::string& filePath);
|
||||
static int OS::RenameFile(const Ref<File>& file, const std::string& newName);
|
||||
static int OS::RenameDirectory(const Ref<Directory>& dir, const std::string& newName);
|
||||
static void ShowInFileExplorer(const std::string& filePath);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/Body/BodyActivationListener.h>
|
||||
#include <Jolt/Physics/Character/Character.h>
|
||||
#include <Jolt/Physics/Collision/RayCast.h>
|
||||
#include <Jolt/Physics/Collision/CastResult.h>
|
||||
|
||||
#include <dependencies/JoltPhysics/Jolt/Physics/Collision/CollisionCollectorImpl.h>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
@@ -157,7 +161,7 @@ namespace Nuake
|
||||
{
|
||||
public:
|
||||
// See: ContactListener
|
||||
virtual JPH::ValidateResult OnContactValidate(const JPH::Body& inBody1, const JPH::Body& inBody2, const JPH::CollideShapeResult& inCollisionResult) override
|
||||
virtual JPH::ValidateResult OnContactValidate(const JPH::Body& inBody1, const JPH::Body& inBody2, JPH::RVec3Arg inBaseOffset, const JPH::CollideShapeResult& inCollisionResult) override
|
||||
{
|
||||
//std::cout << "Contact validate callback" << std::endl;
|
||||
|
||||
@@ -187,16 +191,56 @@ namespace Nuake
|
||||
public:
|
||||
virtual void OnBodyActivated(const JPH::BodyID& inBodyID, JPH::uint64 inBodyUserData) override
|
||||
{
|
||||
std::cout << "A body got activated" << std::endl;
|
||||
//std::cout << "A body got activated" << std::endl;
|
||||
}
|
||||
|
||||
virtual void OnBodyDeactivated(const JPH::BodyID& inBodyID, JPH::uint64 inBodyUserData) override
|
||||
{
|
||||
std::cout << "A body went to sleep" << std::endl;
|
||||
//std::cout << "A body went to sleep" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class ObjectVsBroadPhaseLayerFilterImpl : public JPH::ObjectVsBroadPhaseLayerFilter
|
||||
{
|
||||
public:
|
||||
virtual bool ShouldCollide(JPH::ObjectLayer inLayer1, JPH::BroadPhaseLayer inLayer2) const override
|
||||
{
|
||||
switch (inLayer1)
|
||||
{
|
||||
case Layers::NON_MOVING:
|
||||
return inLayer2 == BroadPhaseLayers::MOVING;
|
||||
case Layers::MOVING:
|
||||
return true;
|
||||
default:
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ObjectLayerPairFilterImpl : public JPH::ObjectLayerPairFilter
|
||||
{
|
||||
public:
|
||||
virtual bool ShouldCollide(JPH::ObjectLayer inObject1, JPH::ObjectLayer inObject2) const override
|
||||
{
|
||||
switch (inObject1)
|
||||
{
|
||||
case Layers::NON_MOVING:
|
||||
return inObject2 == Layers::MOVING; // Non moving only collides with moving
|
||||
case Layers::MOVING:
|
||||
return true; // Moving collides with everything
|
||||
default:
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
BPLayerInterfaceImpl JoltBroadphaseLayerInterface = BPLayerInterfaceImpl();
|
||||
ObjectVsBroadPhaseLayerFilterImpl JoltObjectVSBroadphaseLayerFilter = ObjectVsBroadPhaseLayerFilterImpl();
|
||||
ObjectLayerPairFilterImpl JoltObjectVSObjectLayerFilter;
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
DynamicWorld::DynamicWorld() : _stepCount(0)
|
||||
@@ -204,13 +248,13 @@ namespace Nuake
|
||||
_registeredCharacters = std::map<uint32_t, JPH::Character*>();
|
||||
|
||||
// Initialize Jolt Physics
|
||||
const uint32_t MaxBodies = 1024;
|
||||
const uint32_t MaxBodies = 2048;
|
||||
const uint32_t NumBodyMutexes = 0;
|
||||
const uint32_t MaxBodyPairs = 1024;
|
||||
const uint32_t MaxContactConstraints = 1024;
|
||||
|
||||
_JoltPhysicsSystem = CreateRef<JPH::PhysicsSystem>();
|
||||
_JoltPhysicsSystem->Init(MaxBodies, NumBodyMutexes, MaxBodyPairs, MaxContactConstraints, JoltBroadphaseLayerInterface, MyBroadPhaseCanCollide, MyObjectCanCollide);
|
||||
_JoltPhysicsSystem->Init(MaxBodies, NumBodyMutexes, MaxBodyPairs, MaxContactConstraints, JoltBroadphaseLayerInterface, JoltObjectVSBroadphaseLayerFilter, JoltObjectVSObjectLayerFilter);
|
||||
|
||||
// A body activation listener gets notified when bodies activate and go to sleep
|
||||
// Note that this is called from a job so whatever you do here needs to be thread safe.
|
||||
@@ -231,7 +275,7 @@ namespace Nuake
|
||||
// Optional step: Before starting the physics simulation you can optimize the broad phase. This improves collision detection performance (it's pointless here because we only have 2 bodies).
|
||||
// You should definitely not call this every frame or when e.g. streaming in a new level section as it is an expensive operation.
|
||||
// Instead insert all new objects in batches instead of 1 at a time to keep the broad phase efficient.
|
||||
//_JoltPhysicsSystem->OptimizeBroadPhase();
|
||||
_JoltPhysicsSystem->OptimizeBroadPhase();
|
||||
const uint32_t availableThreads = std::thread::hardware_concurrency() - 1;
|
||||
_JoltJobSystem = new JPH::JobSystemThreadPool(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, availableThreads);
|
||||
}
|
||||
@@ -291,6 +335,7 @@ namespace Nuake
|
||||
settings->mFriction = cc->Friction;
|
||||
settings->mShape = GetJoltShape(cc->Shape);
|
||||
settings->mGravityFactor = 0.0f;
|
||||
settings->mSupportingVolume = JPH::Plane(JPH::Vec3::sAxisY(), -0.5f);
|
||||
|
||||
auto& joltPosition = JPH::Vec3(cc->Position.x, cc->Position.y, cc->Position.z);
|
||||
|
||||
@@ -298,7 +343,7 @@ namespace Nuake
|
||||
|
||||
// We need to add 180 degrees because our forward is -Z.
|
||||
const auto& yOffset = Vector3(0.0f, Rad(180.0), 0.0f);
|
||||
bodyRotation = glm::normalize(bodyRotation * Quat(yOffset));
|
||||
//bodyRotation = glm::normalize(bodyRotation * Quat(yOffset));
|
||||
|
||||
const auto& joltRotation = JPH::Quat(bodyRotation.x, bodyRotation.y, bodyRotation.z, bodyRotation.w);
|
||||
JPH::Character* character = new JPH::Character(settings, joltPosition, joltRotation, cc->GetEntity().GetID() , _JoltPhysicsSystem.get());
|
||||
@@ -316,6 +361,7 @@ namespace Nuake
|
||||
{
|
||||
auto& characterController = _registeredCharacters[entityHandle];
|
||||
const auto groundState = characterController->GetGroundState();
|
||||
|
||||
return groundState == JPH::CharacterBase::EGroundState::OnGround;
|
||||
}
|
||||
|
||||
@@ -323,20 +369,42 @@ namespace Nuake
|
||||
return false;
|
||||
}
|
||||
|
||||
RaycastResult DynamicWorld::Raycast(const Vector3& from, const Vector3& to)
|
||||
std::vector<RaycastResult> DynamicWorld::Raycast(const Vector3& from, const Vector3& to)
|
||||
{
|
||||
Vector3 localNorm = Vector3(0,0,0);
|
||||
|
||||
//Logger::Log("normal: x:" + std::to_string(localNorm.x) + " y:" + std::to_string(localNorm.y )+ "z: " + std::to_string(localNorm.z));
|
||||
// Create jolt ray
|
||||
const auto& fromJolt = JPH::Vec3(from.x, from.y, from.z);
|
||||
const auto& toDirectionJolt = JPH::Vec3(to.x - from.x, to.y - from.y, to.z - from.z);
|
||||
JPH::RRayCast ray { fromJolt, toDirectionJolt };
|
||||
JPH::AllHitCollisionCollector<JPH::CastRayCollector> collector;
|
||||
|
||||
// Map bullet result to dto.
|
||||
RaycastResult result{
|
||||
Vector3(0,0,0),
|
||||
Vector3(0,0,0),
|
||||
localNorm
|
||||
};
|
||||
JPH::RayCastResult result;
|
||||
_JoltPhysicsSystem->GetNarrowPhaseQuery().CastRay(ray, JPH::RayCastSettings(), collector);
|
||||
|
||||
return result;
|
||||
// Fetch results
|
||||
std::vector<RaycastResult> raycastResults;
|
||||
|
||||
if (collector.HadHit())
|
||||
{
|
||||
int num_hits = (int)collector.mHits.size();
|
||||
JPH::BroadPhaseCastResult* results = collector.mHits.data();
|
||||
|
||||
// Format result
|
||||
for (int i = 0; i < num_hits; ++i)
|
||||
{
|
||||
const float hitFraction = results[i].mFraction;
|
||||
const JPH::Vec3& hitPosition = ray.GetPointOnRay(results[i].mFraction);
|
||||
|
||||
RaycastResult result
|
||||
{
|
||||
Vector3(hitPosition.GetX(), hitPosition.GetY(), hitPosition.GetZ()),
|
||||
hitFraction
|
||||
};
|
||||
|
||||
raycastResults.push_back(std::move(result));
|
||||
}
|
||||
}
|
||||
|
||||
return raycastResults;
|
||||
}
|
||||
|
||||
void DynamicWorld::SyncEntitiesTranforms()
|
||||
@@ -415,30 +483,41 @@ namespace Nuake
|
||||
// Next step
|
||||
++_stepCount;
|
||||
|
||||
|
||||
// If you take larger steps than 1 / 60th of a second you need to do multiple collision steps in order to keep the simulation stable.
|
||||
// Do 1 collision step per 1 / 60th of a second (round up).
|
||||
int collisionSteps = 1;
|
||||
constexpr float minStepDuration = 1.0f / 90.0f;
|
||||
constexpr float minStepDuration = 1.0f / 30.0f;
|
||||
constexpr int maxStepCount = 32;
|
||||
|
||||
if(ts > minStepDuration)
|
||||
{
|
||||
Logger::Log("Large step detected: " + std::to_string(ts), "physics", WARNING);
|
||||
collisionSteps = static_cast<float>(ts) / minStepDuration;
|
||||
}
|
||||
|
||||
if (collisionSteps >= maxStepCount)
|
||||
{
|
||||
Logger::Log("Very large step detected: " + std::to_string(ts), "physics", WARNING);
|
||||
}
|
||||
|
||||
// Prevents having too many steps and running out of jobs
|
||||
collisionSteps = std::min(collisionSteps, maxStepCount);
|
||||
|
||||
// If you want more accurate step results you can do multiple sub steps within a collision step. Usually you would set this to 1.
|
||||
constexpr int subSteps = 1;
|
||||
|
||||
// Step the world
|
||||
_JoltPhysicsSystem->Update(ts, collisionSteps, subSteps, new JPH::TempAllocatorMalloc(), _JoltJobSystem);
|
||||
|
||||
for (auto& c : _registeredCharacters)
|
||||
try
|
||||
{
|
||||
c.second->PostSimulation(0.001);
|
||||
_JoltPhysicsSystem->Update(ts, collisionSteps, new JPH::TempAllocatorMalloc(), _JoltJobSystem);
|
||||
|
||||
for (auto& c : _registeredCharacters)
|
||||
{
|
||||
c.second->PostSimulation(0.05f);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::Log("Failed to run simulation update", "physics", CRITICAL);
|
||||
}
|
||||
|
||||
|
||||
SyncEntitiesTranforms();
|
||||
SyncCharactersTransforms();
|
||||
@@ -451,20 +530,22 @@ namespace Nuake
|
||||
if (!_registeredBodies.empty())
|
||||
{
|
||||
_JoltBodyInterface->RemoveBodies(reinterpret_cast<JPH::BodyID*>(_registeredBodies.data()), _registeredBodies.size());
|
||||
|
||||
_registeredBodies.clear();
|
||||
}
|
||||
|
||||
|
||||
if (!_registeredCharacters.empty())
|
||||
{
|
||||
for (auto& character : _registeredCharacters)
|
||||
{
|
||||
character.second->RemoveFromPhysicsSystem();
|
||||
}
|
||||
|
||||
_registeredCharacters.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicWorld::MoveAndSlideCharacterController(const Entity& entity, const Vector3 velocity)
|
||||
void DynamicWorld::MoveAndSlideCharacterController(const Entity& entity, const Vector3& velocity)
|
||||
{
|
||||
const uint32_t entityHandle = entity.GetHandle();
|
||||
if (_registeredCharacters.find(entityHandle) != _registeredCharacters.end())
|
||||
@@ -474,6 +555,23 @@ namespace Nuake
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicWorld::AddForceToRigidBody(const Entity& entity, const Vector3& force)
|
||||
{
|
||||
auto& bodyInterface = _JoltPhysicsSystem->GetBodyInterface();
|
||||
for (const auto& body : _registeredBodies)
|
||||
{
|
||||
auto bodyId = static_cast<JPH::BodyID>(body);
|
||||
auto entityId = static_cast<uint32_t>(bodyInterface.GetUserData(bodyId));
|
||||
if (entityId == entity.GetHandle())
|
||||
{
|
||||
bodyInterface.AddForce(bodyId, JPH::Vec3(force.x, force.y, force.z));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Logger::Log("Failed to add force to rigidbody. Body not found with id: " + std::to_string(entity.GetHandle()), "physics", WARNING);
|
||||
}
|
||||
|
||||
JPH::Ref<JPH::Shape> DynamicWorld::GetJoltShape(const Ref<PhysicShape> shape)
|
||||
{
|
||||
JPH::ShapeSettings::ShapeResult result;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Timestep.h"
|
||||
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
#include "Rigibody.h"
|
||||
#include "src/Core/Timestep.h"
|
||||
#include "src/Core/Core.h"
|
||||
#include <map>
|
||||
#include "RaycastResult.h"
|
||||
|
||||
@@ -10,7 +11,7 @@
|
||||
#include "CharacterController.h"
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
#include "src/Core/Core.h"
|
||||
|
||||
namespace JPH
|
||||
{
|
||||
class PhysicsSystem;
|
||||
@@ -32,7 +33,8 @@ namespace Nuake
|
||||
class MyContactListener;
|
||||
class MyBodyActivationListener;
|
||||
|
||||
namespace Physics {
|
||||
namespace Physics
|
||||
{
|
||||
class DynamicWorld
|
||||
{
|
||||
private:
|
||||
@@ -47,6 +49,7 @@ namespace Nuake
|
||||
|
||||
std::vector<uint32_t> _registeredBodies;
|
||||
std::map<uint32_t, JPH::Character*> _registeredCharacters;
|
||||
|
||||
public:
|
||||
DynamicWorld();
|
||||
|
||||
@@ -59,10 +62,10 @@ namespace Nuake
|
||||
void AddCharacterController(Ref<CharacterController> cc);
|
||||
bool IsCharacterGrounded(const Entity& entity);
|
||||
// This is going to be ugly. TODO: Find a better way that passing itself as a parameter
|
||||
void MoveAndSlideCharacterController(const Entity& entity, const Vector3 velocity);
|
||||
|
||||
void MoveAndSlideCharacterController(const Entity& entity, const Vector3& velocity);
|
||||
void AddForceToRigidBody(const Entity& entity, const Vector3& force);
|
||||
|
||||
RaycastResult Raycast(const Vector3& from, const Vector3& to);
|
||||
std::vector<RaycastResult> Raycast(const Vector3& from, const Vector3& to);
|
||||
void StepSimulation(Timestep ts);
|
||||
void Clear();
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Nuake
|
||||
m_World->Clear();
|
||||
}
|
||||
|
||||
RaycastResult PhysicsManager::Raycast(const Vector3& from, const Vector3& to)
|
||||
std::vector<RaycastResult> PhysicsManager::Raycast(const Vector3& from, const Vector3& to)
|
||||
{
|
||||
return m_World->Raycast(from, to);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Nuake
|
||||
|
||||
void Reset();
|
||||
|
||||
RaycastResult Raycast(const Vector3& from, const Vector3& to);
|
||||
std::vector<RaycastResult> Raycast(const Vector3& from, const Vector3& to);
|
||||
|
||||
void RegisterBody(Ref<Physics::RigidBody> rb);
|
||||
void RegisterGhostBody(Ref<GhostObject> rb);
|
||||
|
||||
@@ -5,16 +5,10 @@
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
namespace Physics
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// result object from raycast.
|
||||
struct RaycastResult {
|
||||
Vector3 WorldPoint;
|
||||
Vector3 LocalPoint;
|
||||
Vector3 Normal;
|
||||
struct RaycastResult
|
||||
{
|
||||
Vector3 WorldPosition;
|
||||
float Fraction;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace Nuake
|
||||
void SetShape(Ref<PhysicShape> shape);
|
||||
Ref<PhysicShape> GetShape() const { return _collisionShape; }
|
||||
Entity GetEntity() const { return _entity; }
|
||||
void AddForce(const Vector3& force);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "PhysicsShapes.h"
|
||||
#include "Rigibody.h"
|
||||
#include "../Core.h"
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Physics/PhysicsManager.h"
|
||||
|
||||
#include <glm/trigonometric.hpp>
|
||||
#include <src/Scene/Entities/Entity.h>
|
||||
|
||||
@@ -42,5 +44,10 @@ namespace Nuake
|
||||
{
|
||||
_entity = ent;
|
||||
}
|
||||
|
||||
void RigidBody::AddForce(const Vector3& force)
|
||||
{
|
||||
PhysicsManager::Get().GetWorld()->AddForceToRigidBody(_entity, force);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "String.h"
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
||||
namespace Nuake
|
||||
@@ -36,6 +37,19 @@ namespace Nuake
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string String::Sanitize(const std::string& keyword)
|
||||
{
|
||||
std::string sanitizedKeyword = keyword;
|
||||
|
||||
// Remove spaces, underscores, and hyphens using regex
|
||||
sanitizedKeyword = std::regex_replace(sanitizedKeyword, std::regex("[ _-]+"), "");
|
||||
|
||||
// Convert to lowercase
|
||||
std::transform(sanitizedKeyword.begin(), sanitizedKeyword.end(), sanitizedKeyword.begin(), ::tolower);
|
||||
|
||||
return sanitizedKeyword;
|
||||
}
|
||||
|
||||
std::vector<std::string> String::Split(const std::string& string, char delimiter)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Nuake
|
||||
static bool EndsWith(const std::string& string, const std::string& end);
|
||||
static bool IsDigit(const char& character);
|
||||
static std::string RemoveWhiteSpace(const std::string& string);
|
||||
static std::string Sanitize(const std::string& keyword);
|
||||
static std::vector<std::string> Split(const std::string& string, char delimiter);
|
||||
|
||||
static float ToFloat(const std::string& string);
|
||||
|
||||
@@ -111,21 +111,20 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Camera::Deserialize(const std::string& str)
|
||||
bool Camera::Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
j = j["CameraInstance"];
|
||||
this->m_Type = (CAMERA_TYPE)j["m_Type"];
|
||||
if(j.contains("Translation"))
|
||||
DESERIALIZE_VEC3(j["Translation"], Translation);
|
||||
auto& camJson = j["CameraInstance"];
|
||||
this->m_Type = (CAMERA_TYPE)camJson["m_Type"];
|
||||
if(camJson.contains("Translation"))
|
||||
DESERIALIZE_VEC3(camJson["Translation"], Translation);
|
||||
|
||||
//if (j.contains("Direction"))
|
||||
// DESERIALIZE_VEC3(j["Direction"], Direction);
|
||||
|
||||
this->AspectRatio = j["AspectRatio"];
|
||||
this->Fov = j["Fov"];
|
||||
this->Exposure = j["Exposure"];
|
||||
this->Speed = j["Speed"];
|
||||
this->AspectRatio = camJson["AspectRatio"];
|
||||
this->Fov = camJson["Fov"];
|
||||
this->Exposure = camJson["Exposure"];
|
||||
this->Speed = camJson["Speed"];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Nuake
|
||||
bool BoxFrustumCheck(const AABB& aabb);
|
||||
Frustum GetFrustum();
|
||||
json Serialize() override;
|
||||
bool Deserialize(const std::string& str) override;
|
||||
bool Deserialize(const json& j) override;
|
||||
|
||||
friend EditorCamera;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "src/Rendering/Buffers/VertexArray.h"
|
||||
#include "src/Rendering/Buffers/VertexBufferLayout.h"
|
||||
|
||||
#include <future>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
Mesh::Mesh() {}
|
||||
@@ -85,7 +87,6 @@ namespace Nuake
|
||||
bufferLayout.Push<float>(3); // Normal
|
||||
bufferLayout.Push<float>(3); // Tangent
|
||||
bufferLayout.Push<float>(3); // Bitangent
|
||||
bufferLayout.Push<float>(1); // Texture
|
||||
|
||||
m_VertexArray->AddBuffer(*m_VertexBuffer, bufferLayout);
|
||||
m_VertexArray->Unbind();
|
||||
@@ -150,12 +151,10 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Mesh::Deserialize(const std::string& str)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
|
||||
bool Mesh::Deserialize(const json& j)
|
||||
{
|
||||
m_Material = CreateRef<Material>();
|
||||
m_Material->Deserialize(j["Material"].dump());
|
||||
m_Material->Deserialize(j["Material"]);
|
||||
|
||||
m_Indices.reserve(j["Indices"].size());
|
||||
for (auto& i : j["Indices"])
|
||||
@@ -164,24 +163,26 @@ namespace Nuake
|
||||
}
|
||||
|
||||
std::vector<Vertex> vertices;
|
||||
for (auto& v : j["Vertices"])
|
||||
{
|
||||
Vertex vertex;
|
||||
|
||||
try {
|
||||
DESERIALIZE_VEC2(v["UV"], vertex.uv)
|
||||
|
||||
std::async(std::launch::async, [&]()
|
||||
{
|
||||
for (auto& v : j["Vertices"])
|
||||
{
|
||||
Vertex vertex;
|
||||
try {
|
||||
DESERIALIZE_VEC2(v["UV"], vertex.uv)
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
vertex.uv = { 0.0, 0.0 };
|
||||
}
|
||||
DESERIALIZE_VEC3(v["Position"], vertex.position)
|
||||
DESERIALIZE_VEC3(v["Normal"], vertex.normal)
|
||||
DESERIALIZE_VEC3(v["Tangent"], vertex.tangent)
|
||||
DESERIALIZE_VEC3(v["Bitangent"], vertex.bitangent)
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
vertex.uv = { 0.0, 0.0 };
|
||||
}
|
||||
DESERIALIZE_VEC3(v["Position"], vertex.position)
|
||||
DESERIALIZE_VEC3(v["Normal"], vertex.normal)
|
||||
|
||||
DESERIALIZE_VEC3(v["Tangent"], vertex.tangent)
|
||||
DESERIALIZE_VEC3(v["Bitangent"], vertex.bitangent)
|
||||
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
);
|
||||
|
||||
m_Vertices = vertices;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Nuake
|
||||
inline AABB GetAABB() const { return m_AABB; }
|
||||
|
||||
json Serialize() override;
|
||||
bool Deserialize(const std::string& str) override;
|
||||
bool Deserialize(const json& j) override;
|
||||
private:
|
||||
Ref<Material> m_Material = nullptr;
|
||||
std::vector<uint32_t> m_Indices;
|
||||
|
||||
@@ -129,14 +129,6 @@ namespace Nuake
|
||||
Renderer::DrawQuad(Matrix4(1.0));
|
||||
}
|
||||
_ssaoBlurFramebuffer->Unbind();
|
||||
|
||||
/*
|
||||
if (ImGui::Begin("SSAO debug"))
|
||||
{
|
||||
ImGui::Image((void*)(uintptr_t)(_ssaoFramebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->GetID()), ImGui::GetContentRegionAvail(), ImVec2(0, 1), ImVec2(1, 0));
|
||||
}
|
||||
ImGui::End();
|
||||
*/
|
||||
}
|
||||
|
||||
Ref<FrameBuffer> SSAO::GetOuput() const
|
||||
|
||||
@@ -27,11 +27,11 @@ namespace Nuake
|
||||
}
|
||||
|
||||
public:
|
||||
float Radius = 0.060f;
|
||||
float Bias = 0.00125f;
|
||||
float Radius = 0.997f;
|
||||
float Bias = 0.045f;
|
||||
float Area = 0.0075f;
|
||||
float Falloff = 0.002f;
|
||||
float Strength = 0.5f;
|
||||
float Strength = 0.2f;
|
||||
void Resize(const Vector2& size);
|
||||
SSAO();
|
||||
void Draw(FrameBuffer* gBuffer, const Matrix4& projection, const Matrix4& view);
|
||||
|
||||
@@ -36,15 +36,19 @@ namespace Nuake
|
||||
void Flush(Shader* shader, bool depthOnly = false)
|
||||
{
|
||||
shader->Bind();
|
||||
const uint32_t entityIdUniformLocation = shader->FindUniformLocation("u_EntityID");
|
||||
const uint32_t modelMatrixUniformLocation = shader->FindUniformLocation("u_Model");
|
||||
for (auto& i : m_RenderList)
|
||||
{
|
||||
if(!depthOnly)
|
||||
if (!depthOnly)
|
||||
{
|
||||
i.first->Bind(shader);
|
||||
}
|
||||
|
||||
for (auto& m : i.second)
|
||||
{
|
||||
shader->SetUniformMat4f("u_Model", m.transform);
|
||||
shader->SetUniform1i("u_EntityID", m.entityId + 1);
|
||||
shader->SetUniformMat4f(modelMatrixUniformLocation, m.transform);
|
||||
shader->SetUniform1i(entityIdUniformLocation, m.entityId + 1);
|
||||
m.Mesh->Draw(shader, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Nuake
|
||||
unsigned int depthFBO;
|
||||
|
||||
Ref<Mesh> Renderer::CubeMesh;
|
||||
Ref<Mesh> Renderer::QuadMesh;
|
||||
|
||||
Shader* Renderer::m_Shader;
|
||||
Shader* Renderer::m_SkyboxShader;
|
||||
@@ -62,13 +63,14 @@ namespace Nuake
|
||||
4, 5, 0, 0, 5, 1
|
||||
};
|
||||
|
||||
float QuadVertices[] = {
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
|
||||
std::vector<Vertex> QuadVertices
|
||||
{
|
||||
{ Vector3(-1.0f, -1.0f, 0.0f), Vector2(0, 0), Vector3(0, 0, -1) },
|
||||
{ Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, -1) },
|
||||
{ Vector3(-1.0f, 1.0f, 0.0f), Vector2(0.0f, 1.0f), Vector3(0, 0, -1) },
|
||||
{ Vector3(1.0f, -1.0f, 0.0f), Vector2(1.0f, 0.0f), Vector3(0, 0, -1) },
|
||||
{ Vector3(-1.0f, -1.0f, 0.0f), Vector2(0.0f, 0.0f), Vector3(0, 0, -1) },
|
||||
{ Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, -1) }
|
||||
};
|
||||
|
||||
|
||||
@@ -80,28 +82,17 @@ namespace Nuake
|
||||
|
||||
m_LightsUniformBuffer = CreateRef<UniformBuffer>(128);
|
||||
|
||||
Ref<Material> material = MaterialManager::Get()->GetMaterial("default");
|
||||
Ref<Material> defaultMaterial = CreateRef<Material>(Vector3{1, 1, 1});
|
||||
defaultMaterial->SetName("white");
|
||||
MaterialManager::Get()->RegisterMaterial(defaultMaterial);
|
||||
|
||||
CubeMesh = CreateRef<Mesh>();
|
||||
CubeMesh->AddSurface(CubeVertices, CubeIndices);
|
||||
CubeMesh->SetMaterial(material);
|
||||
// Cube buffer
|
||||
//CubeVertexArray = new VertexArray();
|
||||
//CubeVertexArray->Bind();
|
||||
//CubeVertexBuffer = new VertexBuffer(CubeVertices, sizeof(CubeVertices));
|
||||
//
|
||||
VertexBufferLayout vblayout = VertexBufferLayout();
|
||||
vblayout.Push<float>(3);
|
||||
//CubeVertexArray->AddBuffer(*CubeVertexBuffer, vblayout);
|
||||
CubeMesh->SetMaterial(defaultMaterial);
|
||||
|
||||
// Quad buffer
|
||||
QuadVertexArray = new VertexArray();
|
||||
QuadVertexArray->Bind();
|
||||
QuadVertexBuffer = new VertexBuffer(QuadVertices, sizeof(QuadVertices));
|
||||
|
||||
vblayout = VertexBufferLayout();
|
||||
vblayout.Push<float>(3);
|
||||
vblayout.Push<float>(2);
|
||||
QuadVertexArray->AddBuffer(*QuadVertexBuffer, vblayout);
|
||||
QuadMesh = CreateRef<Mesh>();
|
||||
QuadMesh->AddSurface(QuadVertices, { 0, 1, 2, 3, 4, 5 });
|
||||
QuadMesh->SetMaterial(defaultMaterial);
|
||||
}
|
||||
|
||||
void Renderer::LoadShaders()
|
||||
@@ -221,7 +212,7 @@ namespace Nuake
|
||||
m_DebugShader->SetUniformMat4f("u_Model", transform.GetGlobalTransform());
|
||||
m_DebugShader->SetUniform4f("u_Color", color.r, color.g, color.b, color.a);
|
||||
|
||||
CubeVertexArray->Bind();
|
||||
CubeMesh->Bind();
|
||||
RenderCommand::DrawArrays(0, 36);
|
||||
}
|
||||
|
||||
@@ -233,7 +224,7 @@ namespace Nuake
|
||||
|
||||
void Renderer::DrawQuad(Matrix4 transform)
|
||||
{
|
||||
QuadVertexArray->Bind();
|
||||
QuadMesh->Bind();
|
||||
RenderCommand::DrawArrays(0, 6);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Nuake
|
||||
{
|
||||
private:
|
||||
static RenderList m_RenderList;
|
||||
|
||||
public:
|
||||
static VertexArray* QuadVertexArray;
|
||||
static VertexBuffer* QuadVertexBuffer;
|
||||
@@ -51,6 +52,7 @@ namespace Nuake
|
||||
static Ref<UniformBuffer> m_LightsUniformBuffer;
|
||||
|
||||
static Ref<Mesh> CubeMesh;
|
||||
static Ref<Mesh> QuadMesh;
|
||||
|
||||
static void Init();
|
||||
static void LoadShaders();
|
||||
@@ -65,7 +67,6 @@ namespace Nuake
|
||||
|
||||
// Lights
|
||||
static std::vector<Light> m_Lights;
|
||||
static void RegisterLight(TransformComponent transform, LightComponent light);
|
||||
static void RegisterDeferredLight(TransformComponent transform, LightComponent light);
|
||||
|
||||
// Debug
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#include "SceneRenderer.h"
|
||||
#include "src/Rendering/Shaders/ShaderManager.h"
|
||||
|
||||
#include <src/Scene/Components/BSPBrushComponent.h>
|
||||
#include "src/Scene/Components/BSPBrushComponent.h"
|
||||
#include "src/Scene/Components/SpriteComponent.h"
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
|
||||
#include <GL\glew.h>
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
void SceneRenderer::Init()
|
||||
@@ -49,7 +53,14 @@ namespace Nuake
|
||||
mGBuffer->QueueResize(framebuffer.GetSize());
|
||||
GBufferPass(scene);
|
||||
|
||||
// SSAO
|
||||
const auto& sceneEnv = scene.GetEnvironment();
|
||||
sceneEnv->mSSAO->Resize(framebuffer.GetSize());
|
||||
sceneEnv->mSSAO->Draw(mGBuffer.get(), mProjection, mView);
|
||||
|
||||
mShadingBuffer->QueueResize(framebuffer.GetSize());
|
||||
ShadingPass(scene);
|
||||
|
||||
Ref<Texture> finalOutput = mShadingBuffer->GetTexture();
|
||||
if (scene.GetEnvironment()->BloomEnabled)
|
||||
{
|
||||
@@ -105,9 +116,7 @@ namespace Nuake
|
||||
|
||||
finalOutput = framebuffer.GetTexture();
|
||||
|
||||
// SSAO
|
||||
sceneEnv->mSSAO->Resize(framebuffer.GetSize());
|
||||
sceneEnv->mSSAO->Draw(mGBuffer.get(), mProjection, mView);
|
||||
|
||||
|
||||
// Copy final output to target framebuffer
|
||||
mToneMapBuffer->QueueResize(framebuffer.GetSize());
|
||||
@@ -139,11 +148,6 @@ namespace Nuake
|
||||
}
|
||||
framebuffer.Unbind();
|
||||
|
||||
|
||||
|
||||
mShadingBuffer->QueueResize(framebuffer.GetSize());
|
||||
ShadingPass(scene);
|
||||
|
||||
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
|
||||
Renderer::EndDraw();
|
||||
}
|
||||
@@ -198,9 +202,40 @@ namespace Nuake
|
||||
}
|
||||
}
|
||||
Renderer::Flush(shader, true);
|
||||
}
|
||||
|
||||
light.m_Framebuffers[i]->Unbind();
|
||||
auto spriteView = scene.m_Registry.view<TransformComponent, SpriteComponent, VisibilityComponent>();
|
||||
for (auto e : spriteView)
|
||||
{
|
||||
auto [transform, sprite, visibility] = spriteView.get<TransformComponent, SpriteComponent, VisibilityComponent>(e);
|
||||
|
||||
if (!visibility.Visible || !sprite.SpriteMesh)
|
||||
continue;
|
||||
|
||||
auto& finalQuadTransform = transform.GetGlobalTransform();
|
||||
if (sprite.Billboard)
|
||||
{
|
||||
finalQuadTransform = glm::inverse(mView);
|
||||
|
||||
if (sprite.LockYRotation)
|
||||
{
|
||||
// This locks the pitch rotation on the billboard, useful for trees, lamps, etc.
|
||||
finalQuadTransform[1] = Vector4(0, 1, 0, 0);
|
||||
finalQuadTransform[2] = Vector4(finalQuadTransform[2][0], 0, finalQuadTransform[2][2], 0);
|
||||
finalQuadTransform = finalQuadTransform;
|
||||
}
|
||||
|
||||
// Translation
|
||||
finalQuadTransform[3] = Vector4(transform.GetGlobalPosition(), 1.0f);
|
||||
|
||||
// Scale
|
||||
finalQuadTransform = glm::scale(finalQuadTransform, transform.GetGlobalScale());
|
||||
}
|
||||
|
||||
Renderer::SubmitMesh(sprite.SpriteMesh, finalQuadTransform, (uint32_t)e);
|
||||
}
|
||||
|
||||
Renderer::Flush(shader, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,16 +245,18 @@ namespace Nuake
|
||||
mGBuffer->Bind();
|
||||
mGBuffer->Clear();
|
||||
{
|
||||
// Init
|
||||
RenderCommand::Enable(RendererEnum::FACE_CULL);
|
||||
Shader* gBufferShader = ShaderManager::GetShader("resources/Shaders/gbuffer.shader");
|
||||
gBufferShader->Bind();
|
||||
gBufferShader->SetUniformMat4f("u_Projection", mProjection);
|
||||
gBufferShader->SetUniformMat4f("u_View", mView);
|
||||
|
||||
auto view = scene.m_Registry.view<TransformComponent, ModelComponent, ParentComponent, VisibilityComponent>();
|
||||
// Models
|
||||
auto view = scene.m_Registry.view<TransformComponent, ModelComponent, VisibilityComponent>();
|
||||
for (auto e : view)
|
||||
{
|
||||
auto [transform, mesh, parent, visibility] = view.get<TransformComponent, ModelComponent, ParentComponent, VisibilityComponent>(e);
|
||||
auto [transform, mesh, visibility] = view.get<TransformComponent, ModelComponent, VisibilityComponent>(e);
|
||||
|
||||
if (mesh.ModelResource && visibility.Visible)
|
||||
{
|
||||
@@ -234,10 +271,11 @@ namespace Nuake
|
||||
RenderCommand::Disable(RendererEnum::FACE_CULL);
|
||||
Renderer::Flush(gBufferShader, false);
|
||||
|
||||
auto quakeView = scene.m_Registry.view<TransformComponent, BSPBrushComponent, ParentComponent, VisibilityComponent>();
|
||||
// Quake BSPs
|
||||
auto quakeView = scene.m_Registry.view<TransformComponent, BSPBrushComponent, VisibilityComponent>();
|
||||
for (auto e : quakeView)
|
||||
{
|
||||
auto [transform, model, parent, visibility] = quakeView.get<TransformComponent, BSPBrushComponent, ParentComponent, VisibilityComponent>(e);
|
||||
auto [transform, model, visibility] = quakeView.get<TransformComponent, BSPBrushComponent, VisibilityComponent>(e);
|
||||
|
||||
if (model.IsTransparent || !visibility.Visible)
|
||||
continue;
|
||||
@@ -248,8 +286,72 @@ namespace Nuake
|
||||
}
|
||||
}
|
||||
Renderer::Flush(gBufferShader, false);
|
||||
|
||||
// Sprites
|
||||
auto spriteView = scene.m_Registry.view<TransformComponent, SpriteComponent, VisibilityComponent>();
|
||||
for (auto& e : spriteView)
|
||||
{
|
||||
auto [transform, sprite, visibility] = spriteView.get<TransformComponent, SpriteComponent, VisibilityComponent>(e);
|
||||
|
||||
if (!visibility.Visible || !sprite.SpriteMesh)
|
||||
continue;
|
||||
|
||||
auto& finalQuadTransform = transform.GetGlobalTransform();
|
||||
if (sprite.Billboard)
|
||||
{
|
||||
finalQuadTransform = glm::inverse(mView);
|
||||
|
||||
if (sprite.LockYRotation)
|
||||
{
|
||||
// This locks the pitch rotation on the billboard, useful for trees, lamps, etc.
|
||||
finalQuadTransform[1] = Vector4(0, 1, 0, 0);
|
||||
finalQuadTransform[2] = Vector4(finalQuadTransform[2][0], 0, finalQuadTransform[2][2], 0);
|
||||
finalQuadTransform = finalQuadTransform;
|
||||
}
|
||||
|
||||
// Translation
|
||||
finalQuadTransform[3] = Vector4(transform.GetGlobalPosition(), 1.0f);
|
||||
|
||||
// Scale
|
||||
finalQuadTransform = glm::scale(finalQuadTransform, transform.GetGlobalScale());
|
||||
}
|
||||
|
||||
Renderer::SubmitMesh(sprite.SpriteMesh, finalQuadTransform, (uint32_t)e);
|
||||
}
|
||||
Renderer::Flush(gBufferShader, false);
|
||||
|
||||
// Particles
|
||||
auto particleEmitterView = scene.m_Registry.view<TransformComponent, ParticleEmitterComponent, VisibilityComponent>();
|
||||
for (auto& e : particleEmitterView)
|
||||
{
|
||||
auto [transform, emitterComponent, visibility] = particleEmitterView.get<TransformComponent, ParticleEmitterComponent, VisibilityComponent>(e);
|
||||
|
||||
if (!visibility.Visible)
|
||||
continue;
|
||||
|
||||
Vector3 oldColor = Renderer::QuadMesh->GetMaterial()->data.m_AlbedoColor;
|
||||
auto initialTransform = transform.GetGlobalTransform();
|
||||
for (auto& p : emitterComponent.Emitter.Particles)
|
||||
{
|
||||
Matrix4 particleTransform = initialTransform;
|
||||
particleTransform = glm::inverse(mView);
|
||||
|
||||
// Translation
|
||||
const Vector3& particleGlobalPosition = transform.GetGlobalPosition() + p.Position;
|
||||
particleTransform[3] = Vector4(particleGlobalPosition, 1.0f);
|
||||
|
||||
// Scale
|
||||
particleTransform = glm::scale(particleTransform, transform.GetGlobalScale());
|
||||
|
||||
Renderer::QuadMesh->GetMaterial()->data.u_HasAlbedo = 0;
|
||||
Renderer::QuadMesh->GetMaterial()->data.m_AlbedoColor = p.Color;
|
||||
Renderer::SubmitMesh(Renderer::QuadMesh, particleTransform, (uint32_t)e);
|
||||
}
|
||||
|
||||
Renderer::Flush(gBufferShader, false);
|
||||
Renderer::QuadMesh->GetMaterial()->data.m_AlbedoColor = oldColor;
|
||||
}
|
||||
}
|
||||
mGBuffer->Unbind();
|
||||
}
|
||||
|
||||
void SceneRenderer::ShadingPass(Scene& scene)
|
||||
@@ -308,7 +410,6 @@ namespace Nuake
|
||||
|
||||
Renderer::DrawQuad(Matrix4());
|
||||
}
|
||||
mShadingBuffer->Unbind();
|
||||
}
|
||||
|
||||
void SceneRenderer::PostProcessPass(const Scene& scene)
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
#include "src/Rendering/Buffers/Framebuffer.h"
|
||||
#include "src/Rendering/PostFX/Bloom.h"
|
||||
#include "src/Rendering/PostFX/Volumetric.h"
|
||||
#include <src/Rendering/PostFX/SSR.h>
|
||||
#include "src/Rendering/PostFX/SSR.h"
|
||||
|
||||
namespace Nuake {
|
||||
class SceneRenderer {
|
||||
namespace Nuake
|
||||
{
|
||||
class SceneRenderer
|
||||
{
|
||||
public:
|
||||
void Init();
|
||||
void Cleanup();
|
||||
@@ -32,7 +34,7 @@ namespace Nuake {
|
||||
Scope<FrameBuffer> mShadingBuffer;
|
||||
Scope<FrameBuffer> mToneMapBuffer;
|
||||
|
||||
|
||||
private:
|
||||
void ShadowPass(Scene& scene);
|
||||
void GBufferPass(Scene& scene);
|
||||
void ShadingPass(Scene& scene);
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace Nuake
|
||||
|
||||
Source = newSource;
|
||||
ProgramId = newProgramId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bind the shader
|
||||
@@ -190,7 +192,7 @@ namespace Nuake
|
||||
int addr = glGetUniformLocation(ProgramId, uniform.c_str());
|
||||
|
||||
if (addr == -1)
|
||||
return addr;//std::cout << "Warning: uniform '" << uniform << "' doesn't exists!" << std::endl;
|
||||
return addr;
|
||||
else
|
||||
UniformCache[uniform] = addr;
|
||||
|
||||
@@ -250,7 +252,12 @@ namespace Nuake
|
||||
//ASSERT(addr != -1);
|
||||
|
||||
if (addr != -1)
|
||||
glUniform1i(addr, v0);
|
||||
SetUniform1i(addr, v0);
|
||||
}
|
||||
|
||||
void Shader::SetUniform1i(uint32_t location, int v0)
|
||||
{
|
||||
glUniform1i(location, v0);
|
||||
}
|
||||
|
||||
void Shader::SetUniform1iv(const std::string& name, int size, int* value)
|
||||
@@ -277,12 +284,19 @@ namespace Nuake
|
||||
glUniformMatrix3fv(addr, 1, GL_FALSE, &mat[0][0]);
|
||||
}
|
||||
|
||||
void Shader::SetUniformMat4f(const std::string& name, Matrix4 mat)
|
||||
void Shader::SetUniformMat4f(uint32_t location, const Matrix4& mat)
|
||||
{
|
||||
glUniformMatrix4fv(location, 1, GL_FALSE, &mat[0][0]);
|
||||
}
|
||||
|
||||
void Shader::SetUniformMat4f(const std::string& name, const Matrix4& mat)
|
||||
{
|
||||
int addr = FindUniformLocation(name);
|
||||
|
||||
if (addr != -1)
|
||||
glUniformMatrix4fv(addr, 1, GL_FALSE, &mat[0][0]);
|
||||
{
|
||||
SetUniformMat4f(addr, std::move(mat));
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::SetUniform1f(const std::string& name, float v0)
|
||||
|
||||
@@ -42,16 +42,20 @@ namespace Nuake
|
||||
void SetUniform1b(const std::string& name, bool v0);
|
||||
void SetUniformTex(const std::string& name, Texture* texture, unsigned int slot = 0);
|
||||
void SetUniform1i(const std::string& name, int v0);
|
||||
void SetUniform1i(uint32_t location, int v0);
|
||||
|
||||
void SetUniform1iv(const std::string& name, int size, int* value);
|
||||
void SetUniform1fv(const std::string& name, int size, float* value);
|
||||
void SetUniformMat3f(const std::string& name, Matrix3 mat);
|
||||
void SetUniformMat4f(const std::string& name, Matrix4 mat);
|
||||
|
||||
void SetUniformMat4f(uint32_t name, const Matrix4& mat);
|
||||
void SetUniformMat4f(const std::string& name, const Matrix4& mat);
|
||||
|
||||
int FindUniformLocation(std::string uniform);
|
||||
|
||||
private:
|
||||
ShaderSource ParseShader(const std::string& filePath);
|
||||
unsigned int CreateProgram(ShaderSource source);
|
||||
unsigned int Compile(unsigned int type, ShaderSource source);
|
||||
int FindUniformLocation(std::string uniform);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -68,9 +68,7 @@ namespace Nuake
|
||||
|
||||
data.m_AlbedoColor = Vector3{ albedoColor.r, albedoColor.g, albedoColor.b };
|
||||
|
||||
m_Name = "New material";
|
||||
|
||||
m_Albedo = m_DefaultAlbedo;
|
||||
m_Name = "default";
|
||||
}
|
||||
|
||||
Material::~Material() {}
|
||||
|
||||
@@ -128,10 +128,8 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str) override
|
||||
bool Deserialize(const json& j) override
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
|
||||
if (j.contains("Path"))
|
||||
{
|
||||
this->Path = j["Path"];
|
||||
|
||||
@@ -11,8 +11,6 @@ namespace Nuake
|
||||
class MaterialManager
|
||||
{
|
||||
private:
|
||||
const std::string DEFAULT_MATERIAL = "resources/Textures/default/Default.png";
|
||||
|
||||
static Ref<MaterialManager> s_Instance;
|
||||
|
||||
std::map<std::string, Ref<Material>> m_Materials;
|
||||
@@ -24,12 +22,12 @@ namespace Nuake
|
||||
|
||||
|
||||
public:
|
||||
const std::string DEFAULT_MATERIAL = "resources/Textures/default/Default.png";
|
||||
std::string CurrentlyBoundedMaterial = "";
|
||||
MaterialManager();
|
||||
|
||||
void LoadMaterials();
|
||||
|
||||
|
||||
void RegisterMaterial(Ref<Material> material);
|
||||
|
||||
Ref<Material> LoadMaterial(std::string path);
|
||||
|
||||
@@ -52,9 +52,8 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str) override
|
||||
bool Deserialize(const json& j) override
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
if (j.contains("Path"))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -3,15 +3,13 @@
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class Vertex
|
||||
struct Vertex
|
||||
{
|
||||
public:
|
||||
Vector3 position;
|
||||
Vector2 uv;
|
||||
Vector3 normal;
|
||||
Vector3 tangent;
|
||||
Vector3 bitangent;
|
||||
float texture;
|
||||
};
|
||||
|
||||
struct LineVertex
|
||||
|
||||
@@ -54,9 +54,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str) override
|
||||
bool Deserialize(const json& j) override
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
Name = j["Name"];
|
||||
Description = j["Description"];
|
||||
Visible = j["Visible"];
|
||||
@@ -101,9 +100,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str) override
|
||||
bool Deserialize(const json& j) override
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
Name = j["Name"];
|
||||
Description = j["Description"];
|
||||
Prefab = j["Prefab"];
|
||||
|
||||
@@ -39,15 +39,14 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
if (j.contains("BrushEntities"))
|
||||
{
|
||||
for (auto& brush : j["BrushEntities"])
|
||||
{
|
||||
FGDBrushEntity brushEntity = FGDBrushEntity();
|
||||
brushEntity.Deserialize(brush.dump());
|
||||
brushEntity.Deserialize(brush);
|
||||
BrushEntities.push_back(brushEntity);
|
||||
}
|
||||
}
|
||||
@@ -57,7 +56,7 @@ namespace Nuake {
|
||||
for (auto& point : j["PointEntities"])
|
||||
{
|
||||
FGDPointEntity pointEntity = FGDPointEntity();
|
||||
pointEntity.Deserialize(point.dump());
|
||||
pointEntity.Deserialize(point);
|
||||
PointEntities.push_back(pointEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,8 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Model::Deserialize(const std::string& str)
|
||||
bool Model::Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
if (j.contains("Path"))
|
||||
{
|
||||
this->IsEmbedded = true;
|
||||
@@ -63,7 +62,7 @@ namespace Nuake
|
||||
for (auto& m : j["Meshes"])
|
||||
{
|
||||
Ref<Mesh> mesh = CreateRef<Mesh>();
|
||||
mesh->Deserialize(m.dump());
|
||||
mesh->Deserialize(m);
|
||||
|
||||
m_Meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Nuake
|
||||
std::vector<Ref<Mesh>>& GetMeshes();
|
||||
|
||||
json Serialize() override;
|
||||
bool Deserialize(const std::string& data) override;
|
||||
bool Deserialize(const json& j) override;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -82,7 +82,6 @@ namespace Nuake
|
||||
for (uint32_t i = 0; i < mesh->mNumVertices; i++)
|
||||
{
|
||||
Vertex vertex;
|
||||
vertex.texture = 1.0f;
|
||||
|
||||
Vector3 current;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Nuake {
|
||||
if (FileSystem::FileExists(path, false))
|
||||
{
|
||||
std::string prefabTextContent = FileSystem::ReadFile(path);
|
||||
newPrefab->Deserialize(prefabTextContent);
|
||||
newPrefab->Deserialize(json::parse(prefabTextContent));
|
||||
}
|
||||
|
||||
return newPrefab;
|
||||
|
||||
@@ -60,22 +60,28 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
if (str == "")
|
||||
if (j == "")
|
||||
return false;
|
||||
|
||||
BEGIN_DESERIALIZE();
|
||||
Path = j["Path"];
|
||||
if (j.contains("Entities"))
|
||||
{
|
||||
return true;
|
||||
for (json e : j["Entities"])
|
||||
{
|
||||
Entity entity = Entity { Engine::GetCurrentScene()->m_Registry.create(), Engine::GetCurrentScene().get() };
|
||||
entity.Deserialize(e.dump());
|
||||
Entity entity = Engine::GetCurrentScene()->CreateEntity("-");
|
||||
auto& nameComponent = entity.GetComponent<NameComponent>();
|
||||
|
||||
int entityId = nameComponent.ID;
|
||||
entity.Deserialize(e);
|
||||
nameComponent.ID = entityId;
|
||||
|
||||
this->AddEntity(entity);
|
||||
}
|
||||
|
||||
// Set reference to the parent entity to children
|
||||
for (auto& e : Entities)
|
||||
{
|
||||
auto parentC = e.GetComponent<ParentComponent>();
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Nuake
|
||||
void Project::SaveAs(const std::string& FullPath)
|
||||
{
|
||||
json j = Serialize();
|
||||
std::string serialized_string = j.dump();
|
||||
std::string serialized_string = j.dump(4);
|
||||
|
||||
// TODO: Use file interface here...
|
||||
// Write to file.
|
||||
@@ -103,10 +103,8 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Project::Deserialize(const std::string& str)
|
||||
bool Project::Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
|
||||
if (!j.contains("Name") || !j.contains("Description"))
|
||||
return false;
|
||||
|
||||
@@ -118,7 +116,7 @@ namespace Nuake
|
||||
std::string path = j["EntityDefinition"];
|
||||
EntityDefinitionsFile = CreateRef<FGDFile>(path);
|
||||
std::string content = FileSystem::ReadFile(path, false);
|
||||
EntityDefinitionsFile->Deserialize(content);
|
||||
EntityDefinitionsFile->Deserialize(nlohmann::json::parse(content));
|
||||
}
|
||||
|
||||
if (j.contains("TrenchbroomPath"))
|
||||
@@ -140,7 +138,7 @@ namespace Nuake
|
||||
return true;
|
||||
|
||||
std::string sceneContent = FileSystem::ReadFile(scenePath, false);
|
||||
if (!DefaultScene->Deserialize(sceneContent))
|
||||
if (!DefaultScene->Deserialize(nlohmann::json::parse(sceneContent)))
|
||||
{
|
||||
Logger::Log("Error loading scene: " + scenePath, "project", CRITICAL);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,6 @@ namespace Nuake
|
||||
static Ref<Project> Load(std::string& path);
|
||||
|
||||
json Serialize() override;
|
||||
bool Deserialize(const std::string& str) override;
|
||||
bool Deserialize(const json& j) override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Nuake
|
||||
Ref<Material> material = CreateRef<Material>();
|
||||
material->ID = uuid;
|
||||
material->Path = path;
|
||||
material->Deserialize(j.dump());
|
||||
material->Deserialize(j);
|
||||
ResourceManager::RegisterResource(material);
|
||||
|
||||
return material;
|
||||
|
||||
@@ -19,6 +19,9 @@ using json = nlohmann::json;
|
||||
SERIALIZE_VEC3(v) \
|
||||
j[#v]["w"] = this->v.w;
|
||||
|
||||
#define DESERIALIZE_VEC4(v, p) \
|
||||
p = Vector4(v["x"], v["y"], v["z"], v["w"]);
|
||||
|
||||
#define DESERIALIZE_VEC3(v, p) \
|
||||
p = Vector3(v["x"], v["y"], v["z"]);
|
||||
|
||||
@@ -35,11 +38,11 @@ using json = nlohmann::json;
|
||||
#define BEGIN_DESERIALIZE() json j = json::parse(str);
|
||||
#define DESERIALIZE_COMPONENT(c) \
|
||||
if(j.contains(#c)) \
|
||||
AddComponent<c>().Deserialize(j[#c].dump());
|
||||
AddComponent<c>().Deserialize(j[#c]);
|
||||
|
||||
class ISerializable
|
||||
{
|
||||
public:
|
||||
virtual json Serialize() = 0;
|
||||
virtual bool Deserialize(const std::string& str) = 0;
|
||||
virtual bool Deserialize(const json& j) = 0;
|
||||
};
|
||||
|
||||
@@ -54,10 +54,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
|
||||
if (j.contains("IsSolid"))
|
||||
{
|
||||
IsSolid = j["IsSolid"];
|
||||
|
||||
@@ -12,10 +12,8 @@ struct VisibilityComponent
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(std::string str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
|
||||
if (j.contains("Visible"))
|
||||
{
|
||||
Visible = j["Visible"];
|
||||
|
||||
@@ -12,9 +12,8 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool BoxColliderComponent::Deserialize(const std::string& str)
|
||||
bool BoxColliderComponent::Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
this->IsTrigger = j["IsTrigger"];
|
||||
this->Size = Vector3(j["Size"]["x"], j["Size"]["y"], j["Size"]["z"]);
|
||||
return true;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Nuake {
|
||||
bool IsTrigger = false;
|
||||
|
||||
json Serialize();
|
||||
bool Deserialize(const std::string& str);
|
||||
bool Deserialize(const json& j);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(std::string str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
CameraInstance = CreateRef<Camera>();
|
||||
|
||||
return CameraInstance->Deserialize(str);
|
||||
return CameraInstance->Deserialize(j);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -13,9 +13,8 @@ namespace Nuake
|
||||
END_SERIALIZE()
|
||||
}
|
||||
|
||||
bool CapsuleColliderComponent::Deserialize(const std::string& str)
|
||||
bool CapsuleColliderComponent::Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE()
|
||||
this->IsTrigger = j["IsTrigger"];
|
||||
this->Radius = j["Radius"];
|
||||
this->Height = j["Height"];
|
||||
|
||||
@@ -15,6 +15,6 @@ namespace Nuake
|
||||
bool IsTrigger = false;
|
||||
|
||||
json Serialize();
|
||||
bool Deserialize(const std::string& str);
|
||||
bool Deserialize(const json& str);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,10 +23,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
|
||||
if (j.contains("Friction"))
|
||||
{
|
||||
Friction = j["Friction"];
|
||||
|
||||
@@ -20,5 +20,4 @@
|
||||
#include "ParentComponent.h"
|
||||
#include "NameComponent.h"
|
||||
#include "BoxCollider.h"
|
||||
#include "ParticleEmitter.h"
|
||||
#include "../Entities/Entity.h"
|
||||
|
||||
@@ -13,9 +13,8 @@ namespace Nuake
|
||||
END_SERIALIZE()
|
||||
}
|
||||
|
||||
bool CylinderColliderComponent::Deserialize(const std::string& str)
|
||||
bool CylinderColliderComponent::Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE()
|
||||
this->IsTrigger = j["IsTrigger"];
|
||||
this->Radius = j["Radius"];
|
||||
this->Height = j["Height"];
|
||||
|
||||
@@ -15,6 +15,6 @@ namespace Nuake
|
||||
bool IsTrigger = false;
|
||||
|
||||
json Serialize();
|
||||
bool Deserialize(const std::string& str);
|
||||
bool Deserialize(const json& j);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,10 +17,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
|
||||
if (j.contains("Interface"))
|
||||
SetInterface(j["Interface"]);
|
||||
|
||||
|
||||
@@ -168,9 +168,8 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(std::string str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
if (j.contains("Type"))
|
||||
Type = (LightType)j["Type"];
|
||||
if (j.contains("IsVolumetric"))
|
||||
|
||||
@@ -18,9 +18,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
this->IsTrigger = j["IsTrigger"];
|
||||
this->SubMesh = j["SubMesh"];
|
||||
return true;
|
||||
|
||||
@@ -27,16 +27,15 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
ModelPath = j["ModelPath"];
|
||||
ModelResource = CreateRef<Model>();
|
||||
|
||||
if (j.contains("ModelResource"))
|
||||
{
|
||||
auto& res = j["ModelResource"];
|
||||
ModelResource->Deserialize(res.dump());
|
||||
ModelResource->Deserialize(res);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -18,9 +18,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
Name = j["Name"];
|
||||
|
||||
if (j.contains("ID"))
|
||||
|
||||
@@ -41,9 +41,8 @@ namespace Nuake
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(std::string str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
this->HasParent = j["HasParent"];
|
||||
if (HasParent)
|
||||
{
|
||||
|
||||
32
Nuake/src/Scene/Components/ParticleEmitterComponent.cpp
Normal file
32
Nuake/src/Scene/Components/ParticleEmitterComponent.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
json ParticleEmitterComponent::Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VEC4(ParticleColor);
|
||||
SERIALIZE_VAL(Amount);
|
||||
SERIALIZE_VAL(Life);
|
||||
SERIALIZE_VAL(Rate);
|
||||
SERIALIZE_VEC3(Gravity);
|
||||
SERIALIZE_VAL(GravityRandom);
|
||||
SERIALIZE_VAL(Radius);
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool ParticleEmitterComponent::Deserialize(const json& j)
|
||||
{
|
||||
DESERIALIZE_VEC4(j["ParticleColor"], ParticleColor);
|
||||
Amount = j["Amount"];
|
||||
Life = j["Life"];
|
||||
if (j.contains("Rate"))
|
||||
{
|
||||
Rate = j["Rate"];
|
||||
}
|
||||
DESERIALIZE_VEC3(j["Gravity"], Gravity);
|
||||
GravityRandom = j["GravityRandom"];
|
||||
Radius = j["Radius"];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
34
Nuake/src/Scene/Components/ParticleEmitterComponent.h
Normal file
34
Nuake/src/Scene/Components/ParticleEmitterComponent.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
|
||||
#include "src/Scene/Systems/ParticleEmitter.h"
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class ParticleEmitterComponent
|
||||
{
|
||||
public:
|
||||
ParticleEmitterComponent() = default;
|
||||
~ParticleEmitterComponent() = default;
|
||||
|
||||
Color ParticleColor;
|
||||
float Amount;
|
||||
float Life = 1.0f;
|
||||
float Rate = 0.0f;
|
||||
|
||||
Vector3 Gravity;
|
||||
float GravityRandom;
|
||||
|
||||
// For now use a radius, later should use shape.
|
||||
float Radius;
|
||||
|
||||
ParticleEmitter Emitter;
|
||||
|
||||
public:
|
||||
json Serialize();
|
||||
bool Deserialize(const json& j);
|
||||
};
|
||||
}
|
||||
@@ -30,9 +30,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(std::string str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
if (j.contains("AutoRebuild"))
|
||||
{
|
||||
this->AutoRebuild = j["AutoRebuild"];
|
||||
|
||||
@@ -13,18 +13,18 @@ namespace Nuake {
|
||||
|
||||
Ref<Physics::RigidBody> RigidBodyComponent::GetRigidBody() const
|
||||
{
|
||||
return m_Rigidbody;
|
||||
return Rigidbody;
|
||||
}
|
||||
|
||||
void RigidBodyComponent::SyncTransformComponent(TransformComponent* tc)
|
||||
{
|
||||
if (!m_Rigidbody)
|
||||
if (!GetRigidBody())
|
||||
return;
|
||||
}
|
||||
|
||||
void RigidBodyComponent::SyncWithTransform(TransformComponent* tc)
|
||||
{
|
||||
if (!m_Rigidbody)
|
||||
if (!GetRigidBody())
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Nuake {
|
||||
{
|
||||
public:
|
||||
float Mass;
|
||||
Ref<Physics::RigidBody> m_Rigidbody;
|
||||
Ref<Physics::RigidBody> Rigidbody;
|
||||
|
||||
RigidBodyComponent();
|
||||
Ref<Physics::RigidBody> GetRigidBody() const;
|
||||
@@ -24,6 +24,7 @@ namespace Nuake {
|
||||
void DrawShape(TransformComponent* tc);
|
||||
void DrawEditor();
|
||||
|
||||
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
@@ -31,9 +32,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(std::string str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
Mass = j["Mass"];
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -19,9 +19,8 @@ namespace Nuake {
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const std::string& str)
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
BEGIN_DESERIALIZE();
|
||||
this->Radius = j["Radius"];
|
||||
this->IsTrigger = j["IsTrigger"];
|
||||
return true;
|
||||
|
||||
68
Nuake/src/Scene/Components/SpriteComponent.cpp
Normal file
68
Nuake/src/Scene/Components/SpriteComponent.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "SpriteComponent.h"
|
||||
|
||||
#include "src/Core/FileSystem.h"
|
||||
#include "src/Rendering/Textures/TextureManager.h"
|
||||
#include "src/Rendering/Textures/MaterialManager.h"
|
||||
#include "src/Rendering/Vertex.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
SpriteComponent::SpriteComponent() :
|
||||
Billboard(false),
|
||||
LockYRotation(false),
|
||||
SpritePath("")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool SpriteComponent::LoadSprite()
|
||||
{
|
||||
std::vector<Vertex> quadVertices =
|
||||
{
|
||||
{ Vector3(-1.0f, -1.0f, 0.0f), Vector2(0, 0), Vector3(0, 0, -1) },
|
||||
{ Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, -1) },
|
||||
{ Vector3(-1.0f, 1.0f, 0.0f), Vector2(0.0f, 1.0f), Vector3(0, 0, -1) },
|
||||
{ Vector3(1.0f, -1.0f, 0.0f), Vector2(1.0f, 0.0f), Vector3(0, 0, -1) },
|
||||
{ Vector3(-1.0f, -1.0f, 0.0f), Vector2(0.0f, 0.0f), Vector3(0, 0, -1) },
|
||||
{ Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, -1) }
|
||||
};
|
||||
|
||||
SpriteMesh = CreateRef<Mesh>();
|
||||
SpriteMesh->AddSurface(quadVertices, { 0, 1, 2, 3, 4, 5 });
|
||||
|
||||
auto& material = MaterialManager::Get()->GetMaterial(FileSystem::Root + SpritePath);
|
||||
SpriteMesh->SetMaterial(material);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
json SpriteComponent::Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VAL(Billboard)
|
||||
SERIALIZE_VAL(LockYRotation)
|
||||
SERIALIZE_VAL(SpritePath)
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool SpriteComponent::Deserialize(const json& j)
|
||||
{
|
||||
if (j.contains("Billboard"))
|
||||
{
|
||||
Billboard = j["Billboard"];
|
||||
}
|
||||
|
||||
if (j.contains("LockYRotation"))
|
||||
{
|
||||
LockYRotation = j["LockYRotation"];
|
||||
}
|
||||
|
||||
if (j.contains("SpritePath"))
|
||||
{
|
||||
SpritePath = j["SpritePath"];
|
||||
LoadSprite();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user