Refactor Shader uniform API + Added back NuakeUI

This commit is contained in:
Antoine Pilote
2024-09-09 20:55:51 -04:00
parent 5a0f7c06f0
commit aef5f65f75
87 changed files with 21929 additions and 478 deletions

6
.gitmodules vendored
View File

@@ -31,3 +31,9 @@
[submodule "Nuake/dependencies/yoga"]
path = Nuake/dependencies/yoga
url = https://github.com/facebook/yoga.git
[submodule "Nuake/dependencies/--force"]
path = Nuake/dependencies/--force
url = https://github.com/freetype/freetype.git
[submodule "Nuake/dependencies/freetype"]
path = Nuake/dependencies/freetype
url = https://github.com/freetype/freetype.git

Binary file not shown.

View File

@@ -7,6 +7,8 @@
#include <glad/glad.h>
#include "src/UI/NuakeUI.h"
#include "src/UI/UIInputManager.h"
void EditorApplication::OnInit()
{
@@ -71,6 +73,16 @@ void EditorApplication::OnInit()
}
});
NuakeUI::CanvasParser parser;
Ref<NuakeUI::Canvas> canvas = parser.Parse("test.html");
static MyInputManager inputManager(*m_Window);
canvas->SetInputManager(&inputManager);
canvas->ComputeLayout({1920, 1080});
canvas->Tick();
canvas->Draw();
PushLayer(CreateScope<EditorLayer>());
}

View File

@@ -189,10 +189,10 @@ void GizmoDrawer::DrawAxis(Ref<Scene> scene, bool occluded)
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
{
m_LineShader->Bind();
m_LineShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform1f("u_Opacity", occluded ? 0.1f : 0.5f);
m_LineShader->SetUniformVec4("u_Color", {0.0f, 0.0f, 0.0f, 0.0f});
m_LineShader->SetUniform("u_View", scene->m_EditorCamera->GetTransform());
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", occluded ? 0.1f : 0.5f);
m_LineShader->SetUniform("u_Color", {0.0f, 0.0f, 0.0f, 0.0f});
m_AxisLineBuffer->Bind();
glLineWidth(1.0f);
Nuake::RenderCommand::DrawLines(0, 6);
@@ -234,9 +234,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, box.Size));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, box.Size));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_BoxBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 26);
@@ -256,9 +256,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 0.9f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, volume.VolumeSize));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 0.9f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, volume.VolumeSize));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_BoxBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 26);
@@ -269,9 +269,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
{
auto [transform, sphere] = scene->m_Registry.get<TransformComponent, SphereColliderComponent>(e);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(sphere.Radius)));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(sphere.Radius)));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CircleBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 128);
@@ -290,14 +290,14 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
Vector3 globalPosition = Vector3(transform.GetGlobalTransform()[3]);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MaxDistance)));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MaxDistance)));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CircleBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 128);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MinDistance)));
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MinDistance)));
Nuake::RenderCommand::DrawLines(0, 128);
}
@@ -318,9 +318,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CapsuleGizmo[entityId]->Bind();
Nuake::RenderCommand::DrawLines(0, 264);
@@ -343,9 +343,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.0f);
m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.0f);
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CylinderGizmo[entityId]->Bind();
Nuake::RenderCommand::DrawLines(0, 264);
@@ -376,9 +376,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
gizmoPosition = glm::translate(gizmoPosition, { 0, -cylinderLength / 2.0, 0 });
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.0f);
m_LineShader->SetUniformMat4f("u_View", gizmoPosition);
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.0f);
m_LineShader->SetUniform("u_View", gizmoPosition);
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CylinderGizmo[entityId]->Bind();
Nuake::RenderCommand::DrawLines(0, 264);
@@ -419,9 +419,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
{
auto [transform, particle] = scene->m_Registry.get<TransformComponent, ParticleEmitterComponent>(e);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(particle.Radius)));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(particle.Radius)));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CircleBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 128);
@@ -450,8 +450,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
meshes[mesh.SubMesh]->Bind();
@@ -461,9 +461,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto flatShader = ShaderManager::GetShader("Resources/Shaders/flat.shader");
flatShader->Bind();
flatShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
flatShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
flatShader->SetUniform4f("u_Color", 0.5f, 0.5f, 0.5f, 1.0f);
flatShader->SetUniform("u_View", scene->m_EditorCamera->GetTransform());
flatShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
flatShader->SetUniform("u_Color", 0.5f, 0.5f, 0.5f, 1.0f);
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
RenderCommand::Enable(RendererEnum::FACE_CULL);
@@ -474,9 +474,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto gizmoShader = ShaderManager::GetShader("Resources/Shaders/gizmo.shader");
gizmoShader->Bind();
gizmoShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
gizmoShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
gizmoShader->SetUniform1f("u_Opacity", occluded ? 0.1f : 1.f);
gizmoShader->SetUniform("u_View", scene->m_EditorCamera->GetTransform());
gizmoShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
gizmoShader->SetUniform("u_Opacity", occluded ? 0.1f : 1.f);
RenderCommand::Disable(RendererEnum::FACE_CULL);
const Vector3& cameraPosition = scene->m_EditorCamera->GetTranslation();
@@ -487,8 +487,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto camView = scene->m_Registry.view<TransformComponent, CameraComponent>();
for (auto e : camView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/camera.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/camera.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transform, camera] = scene->m_Registry.get<TransformComponent, CameraComponent>(e);
auto initialTransform = transform.GetGlobalTransform();
@@ -527,8 +527,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
texturePath = "Resources/Gizmos/light.png";
}
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture(texturePath).get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture(texturePath).get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto initialTransform = transform.GetGlobalTransform();
Matrix4 particleTransform = initialTransform;
@@ -548,8 +548,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto characterControllerView = scene->m_Registry.view<TransformComponent, CharacterControllerComponent>();
for (auto e : characterControllerView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/player.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/player.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transform, characterControllerComponent] = scene->m_Registry.get<TransformComponent, CharacterControllerComponent>(e);
auto initialTransform = transform.GetGlobalTransform();
@@ -571,8 +571,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto boneView = scene->m_Registry.view<TransformComponent, BoneComponent>();
for (auto e : boneView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/bone.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/bone.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transform, boneComponent] = scene->m_Registry.get<TransformComponent, BoneComponent>(e);
auto initialTransform = transform.GetGlobalTransform();
@@ -593,8 +593,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto audioView = scene->m_Registry.view<TransformComponent, AudioEmitterComponent>();
for (auto e : audioView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/sound_emitter.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/sound_emitter.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transformComponent, audioEmitterComponent] = scene->m_Registry.get<TransformComponent, AudioEmitterComponent>(e);
auto initialTransform = transformComponent.GetGlobalTransform();
@@ -614,8 +614,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto rigidbodyView = scene->m_Registry.view<TransformComponent, RigidBodyComponent>();
for (auto e : rigidbodyView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/rigidbody.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/rigidbody.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transformComponent, rigidbodyComponent] = scene->m_Registry.get<TransformComponent, RigidBodyComponent>(e);
auto initialTransform = transformComponent.GetGlobalTransform();
@@ -635,8 +635,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto particleEmitterView = scene->m_Registry.view<TransformComponent, ParticleEmitterComponent>();
for (auto e : particleEmitterView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/particles.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/particles.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transformComponent, particleEmitter] = scene->m_Registry.get<TransformComponent, ParticleEmitterComponent>(e);
auto initialTransform = transformComponent.GetGlobalTransform();

View File

@@ -127,9 +127,9 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
// shader->Bind();
//
// auto cam = Engine::GetCurrentScene()->GetCurrentCamera();
// shader->SetUniformMat4f("u_View", view);
// shader->SetUniformMat4f("u_Projection", ortho);
// shader->SetUniformMat4f("u_Model", Matrix4(1.0f));
// shader->SetUniform("u_View", view);
// shader->SetUniform("u_Projection", ortho);
// shader->SetUniform("u_Model", Matrix4(1.0f));
// Renderer::SphereMesh->Draw(shader, true);
//}
//m_Framebuffer->Unbind();
@@ -143,15 +143,15 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
// RenderCommand::Disable(RendererEnum::FACE_CULL);
// auto shader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
// shader->Bind();
// shader->SetUniformVec3("u_EyePosition", Vector3(1, 0, 0));
// shader->SetUniform1i("LightCount", 0);
// shader->SetUniform("u_EyePosition", Vector3(1, 0, 0));
// shader->SetUniform("LightCount", 0);
// auto dir = Engine::GetCurrentScene()->GetEnvironment()->ProceduralSkybox->GetSunDirection();
// shader->SetUniform3f("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
// shader->SetUniform3f("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
// shader->SetUniform1i("u_DirectionalLight.Shadow", 0);
// shader->SetUniform1i("u_DisableSSAO", 1);
// shader->SetUniformMat4f("u_View", view);
// shader->SetUniformMat4f("u_Projection", ortho);
// shader->SetUniform("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
// shader->SetUniform("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
// shader->SetUniform("u_DirectionalLight.Shadow", 0);
// shader->SetUniform("u_DisableSSAO", 1);
// shader->SetUniform("u_View", view);
// shader->SetUniform("u_Projection", ortho);
//
// m_Framebuffer->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(5);
// m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->Bind(6);
@@ -159,11 +159,11 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
// m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT2)->Bind(8);
// m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT4)->Bind(10);
//
// shader->SetUniform1i("m_Depth", 5);
// shader->SetUniform1i("m_Albedo", 6);
// shader->SetUniform1i("m_Normal", 7);
// shader->SetUniform1i("m_Material", 8);
// shader->SetUniform1i("m_Emissive", 10);
// shader->SetUniform("m_Depth", 5);
// shader->SetUniform("m_Albedo", 6);
// shader->SetUniform("m_Normal", 7);
// shader->SetUniform("m_Material", 8);
// shader->SetUniform("m_Emissive", 10);
//
// Renderer::DrawQuad(Matrix4());
//}
@@ -215,9 +215,9 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
shader->Bind();
auto cam = Engine::GetCurrentScene()->GetCurrentCamera();
shader->SetUniformMat4f("u_View", view);
shader->SetUniformMat4f("u_Projection", ortho);
shader->SetUniformMat4f("u_Model", Matrix4(1.0f));
shader->SetUniform("u_View", view);
shader->SetUniform("u_Projection", ortho);
shader->SetUniform("u_Model", Matrix4(1.0f));
Ref<Material> material = ResourceLoader::LoadMaterial(path);
material->Bind(shader);
Renderer::SphereMesh->Draw(shader, false);
@@ -233,15 +233,15 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
RenderCommand::Disable(RendererEnum::FACE_CULL);
auto shader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
shader->Bind();
shader->SetUniformVec3("u_EyePosition", Vector3(1, 0, 0));
shader->SetUniform1i("LightCount", 0);
shader->SetUniform("u_EyePosition", Vector3(1, 0, 0));
shader->SetUniform("LightCount", 0);
auto dir = Engine::GetCurrentScene()->GetEnvironment()->ProceduralSkybox->GetSunDirection();
shader->SetUniform3f("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
shader->SetUniform3f("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
shader->SetUniform1i("u_DirectionalLight.Shadow", 0);
shader->SetUniform1i("u_DisableSSAO", 1);
shader->SetUniformMat4f("u_View", view);
shader->SetUniformMat4f("u_Projection", ortho);
shader->SetUniform("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
shader->SetUniform("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
shader->SetUniform("u_DirectionalLight.Shadow", 0);
shader->SetUniform("u_DisableSSAO", 1);
shader->SetUniform("u_View", view);
shader->SetUniform("u_Projection", ortho);
m_Framebuffer->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(5);
m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->Bind(6);
@@ -249,11 +249,11 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT2)->Bind(8);
m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT4)->Bind(10);
shader->SetUniform1i("m_Depth", 5);
shader->SetUniform1i("m_Albedo", 6);
shader->SetUniform1i("m_Normal", 7);
shader->SetUniform1i("m_Material", 8);
shader->SetUniform1i("m_Emissive", 10);
shader->SetUniform("m_Depth", 5);
shader->SetUniform("m_Albedo", 6);
shader->SetUniform("m_Normal", 7);
shader->SetUniform("m_Material", 8);
shader->SetUniform("m_Emissive", 10);
Renderer::DrawQuad(Matrix4());
}

5
Editor/test.html Normal file
View File

@@ -0,0 +1,5 @@
<div>
<div class="main">
<p>Hello</p>
</div>
</div>

View File

@@ -0,0 +1,84 @@
group "Dependencies"
project "Freetype"
location "freetype"
kind "StaticLib"
staticruntime "on"
language "C"
targetdir ("freetype/bin/" .. outputdir .. "/%{prj.name}")
objdir ("freetype/bin-obj/" .. outputdir .. "/%{prj.name}")
includedirs {
'freetype/include/',
'freetype/',
"freetype/include/config/"
}
defines { "FT2_BUILD_LIBRARY" }
files {
"freetype/src/autofit/autofit.c",
"freetype/src/base/ftbase.c",
"freetype/src/base/ftbbox.c",
"freetype/src/base/ftbdf.c",
"freetype/src/base/ftbitmap.c",
"freetype/src/base/ftcid.c",
"freetype/src/base/ftfstype.c",
"freetype/src/base/ftgasp.c",
"freetype/src/base/ftglyph.c",
"freetype/src/base/ftgxval.c",
"freetype/src/base/ftinit.c",
"freetype/src/base/ftmm.c",
"freetype/src/base/ftotval.c",
"freetype/src/base/ftpatent.c",
"freetype/src/base/ftpfr.c",
"freetype/src/base/ftstroke.c",
"freetype/src/base/ftsynth.c",
"freetype/src/base/ftsystem.c",
"freetype/src/base/fttype1.c",
"freetype/src/base/ftwinfnt.c",
"freetype/src/bdf/bdf.c",
"freetype/src/cache/ftcache.c",
"freetype/src/cff/cff.c",
"freetype/src/cid/type1cid.c",
"freetype/src/gzip/ftgzip.c",
"freetype/src/lzw/ftlzw.c",
"freetype/src/pcf/pcf.c",
"freetype/src/pfr/pfr.c",
"freetype/src/psaux/psaux.c",
"freetype/src/pshinter/pshinter.c",
"freetype/src/psnames/psmodule.c",
"freetype/src/raster/raster.c",
"freetype/src/sfnt/sfnt.c",
"freetype/src/smooth/smooth.c",
"freetype/src/truetype/truetype.c",
"freetype/src/type1/type1.c",
"freetype/src/type42/type42.c",
"freetype/src/winfonts/winfnt.c",
"freetype/src/winfonts/winfnt.c",
"freetype/src/sdf/sdf.c"
}
filter "system:windows"
systemversion "latest"
defines
{
}
filter "configurations:Debug"
files { "freetype/src/base/ftdebug.c" }
runtime "Debug"
symbols "on"
filter "configurations:Release"
files { "freetype/src/base/ftdebug.c" }
runtime "Release"
optimize "on"
filter "configurations:Dist"
files { "freetype/src/base/ftdebug.c" }
runtime "Release"
optimize "on"
group ""

View File

@@ -0,0 +1,79 @@
project '*'
includedirs {
'yoga/yoga/'
}
group "Dependencies"
project 'msdf-gen'
kind "StaticLib"
staticruntime "on"
warnings 'Off'
optimize 'Speed'
cppdialect "C++20"
includedirs {
'msdf-atlas-gen/include',
'freetype/include'
}
files {
'msdf-atlas-gen/msdfgen/*.h',
'msdf-atlas-gen/msdfgen/*.cpp',
'msdf-atlas-gen/msdfgen/*.hpp',
'msdf-atlas-gen/msdfgen/Core/*.h',
'msdf-atlas-gen/msdfgen/Core/*.hpp',
'msdf-atlas-gen/msdfgen/Core/*.cpp',
'msdf-atlas-gen/msdfgen/lib/*.cpp',
'msdf-atlas-gen/msdfgen/ext/*.h',
'msdf-atlas-gen/msdfgen/ext/*.cpp'
}
defines {
}
filter "configurations:Debug"
runtime "Debug"
symbols "on"
filter "configurations:Release"
runtime "Release"
optimize "on"
project 'msdf-atlas-gen'
kind "StaticLib"
staticruntime "on"
warnings 'Off'
optimize 'Speed'
cppdialect "C++20"
includedirs {
'msdf-atlas-gen/include',
'msdf-atlas-gen/msdfgen',
'msdf-atlas-gen/msdfgen/include'
}
files {
'msdf-atlas-gen/msdf-atlas-gen/*.h',
'msdf-atlas-gen/msdf-atlas-gen/*.cpp',
'msdf-atlas-gen/msdf-atlas-gen/*.hpp',
}
links {
'msdf-gen'
}
defines {
}
filter "configurations:Debug"
runtime "Debug"
symbols "on"
filter "configurations:Release"
runtime "Release"
optimize "on"
group ""

View File

@@ -18,6 +18,8 @@ project 'yoga'
files {
'yoga/yoga/*.cpp',
'yoga/yoga/*.h',
'yoga/yoga/**/*.cpp',
'yoga/yoga/**/*.h',
}
defines {

View File

@@ -115,7 +115,7 @@ namespace Nuake
void Mesh::DebugDraw()
{
Renderer::m_DebugShader->Bind();
Renderer::m_DebugShader->SetUniform4f("u_Color", 1.0f, 0.0f, 0.0f, 1.f);
Renderer::m_DebugShader->SetUniform("u_Color", 1.0f, 0.0f, 0.0f, 1.f);
m_VertexArray->Bind();
RenderCommand::DrawElements(RendererEnum::TRIANGLES, m_IndicesCount, RendererEnum::UINT, 0);

View File

@@ -110,7 +110,7 @@ namespace Nuake
void SkinnedMesh::DebugDraw()
{
Renderer::m_DebugShader->Bind();
Renderer::m_DebugShader->SetUniform4f("u_Color", 1.0f, 0.0f, 0.0f, 1.f);
Renderer::m_DebugShader->SetUniform("u_Color", 1.0f, 0.0f, 0.0f, 1.f);
m_VertexArray->Bind();
RenderCommand::DrawElements(RendererEnum::TRIANGLES, (int)m_Indices.size(), RendererEnum::UINT, 0);

View File

@@ -78,10 +78,10 @@ namespace Nuake
{
m_ThresholdFB->Clear();
shader->Bind();
shader->SetUniform1i("u_Stage", 0);
shader->SetUniform1f("u_Threshold", m_Threshold);
shader->SetUniform("u_Stage", 0);
shader->SetUniform("u_Threshold", m_Threshold);
m_Source->Bind(1);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform("u_Source", 1);
Renderer::DrawQuad(Matrix4());
}
@@ -91,13 +91,13 @@ namespace Nuake
m_DownSampleFB[i]->Bind();
m_DownSampleFB[i]->Clear();
shader->SetUniform1i("u_Stage", 1);
shader->SetUniform("u_Stage", 1);
Ref<Texture> downsampleTexture = i == 0 ? m_ThresholdFB->GetTexture() : m_DownSampleFB[i - 1]->GetTexture();
shader->SetUniformTex("u_Source", downsampleTexture.get(), 1);
shader->SetUniform("u_Source", downsampleTexture.get(), 1);
Vector2 size = i == 0 ? downsampleTexture->GetSize() : m_DownSampleFB[i]->GetTexture()->GetSize();
shader->SetUniformVec2("u_SourceSize", size);
shader->SetUniform("u_SourceSize", size);
Renderer::DrawQuad(Matrix4());
m_DownSampleFB[i]->Unbind();
@@ -109,13 +109,13 @@ namespace Nuake
m_HBlurFB[i]->Bind();
m_HBlurFB[i]->Clear();
shader->SetUniform1i("u_Stage", 2);
shader->SetUniform2f("u_BlurDirection", 0.0f, 1.0f);
shader->SetUniform("u_Stage", 2);
shader->SetUniform("u_BlurDirection", 0.0f, 1.0f);
Ref<Texture> blurTexture = m_DownSampleFB[m_Iteration - i - 1]->GetTexture();
blurTexture->Bind(1);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform2f("u_SourceSize", (float)blurTexture->GetWidth(), (float)blurTexture->GetHeight());
shader->SetUniform("u_Source", 1);
shader->SetUniform("u_SourceSize", (float)blurTexture->GetWidth(), (float)blurTexture->GetHeight());
Renderer::DrawQuad(Matrix4());
m_HBlurFB[i]->Unbind();
@@ -124,12 +124,12 @@ namespace Nuake
m_VBlurFB[i]->Bind();
m_VBlurFB[i]->Clear();
shader->SetUniform1i("u_Stage", 2);
shader->SetUniform2f("u_BlurDirection", 1.0f, 0.0f);
shader->SetUniform("u_Stage", 2);
shader->SetUniform("u_BlurDirection", 1.0f, 0.0f);
m_HBlurFB[i]->GetTexture()->Bind(1);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform2f("u_SourceSize", (float)m_HBlurFB[i]->GetTexture()->GetWidth(), (float)m_HBlurFB[i]->GetTexture()->GetHeight());
shader->SetUniform("u_Source", 1);
shader->SetUniform("u_SourceSize", (float)m_HBlurFB[i]->GetTexture()->GetWidth(), (float)m_HBlurFB[i]->GetTexture()->GetHeight());
Renderer::DrawQuad(Matrix4());
m_VBlurFB[i]->Unbind();
@@ -140,20 +140,20 @@ namespace Nuake
m_UpSampleFB[i]->Clear();
if (i == 0)
{
shader->SetUniform1i("u_Stage", 3);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform("u_Stage", 3);
shader->SetUniform("u_Source", 1);
m_VBlurFB[i]->GetTexture()->Bind(1);
}
if (i > 0)
{
shader->SetUniform1i("u_Stage", 4);
shader->SetUniform("u_Stage", 4);
m_VBlurFB[i]->GetTexture()->Bind(1);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform("u_Source", 1);
m_UpSampleFB[i - 1]->GetTexture()->Bind(2);
shader->SetUniform1i("u_Source2", 2);
shader->SetUniform2f("u_Source2Size", (float)m_UpSampleFB[i]->GetTexture()->GetWidth(), (float)m_UpSampleFB[i]->GetTexture()->GetHeight());
shader->SetUniform("u_Source2", 2);
shader->SetUniform("u_Source2Size", (float)m_UpSampleFB[i]->GetTexture()->GetWidth(), (float)m_UpSampleFB[i]->GetTexture()->GetHeight());
}
Renderer::DrawQuad(Matrix4());
m_UpSampleFB[i]->Unbind();
@@ -161,9 +161,9 @@ namespace Nuake
m_FinalFB->Bind();
m_FinalFB->Clear();
{
shader->SetUniform1i("u_Stage", 5);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform1i("u_Source2", 2);
shader->SetUniform("u_Stage", 5);
shader->SetUniform("u_Source", 1);
shader->SetUniform("u_Source2", 2);
m_UpSampleFB[m_Iteration - 1]->GetTexture()->Bind(1);
m_Source->Bind(2);
Renderer::DrawQuad(Matrix4());

View File

@@ -110,28 +110,28 @@ namespace Nuake
const auto& normalTexture = gBuffer->GetTexture(GL_COLOR_ATTACHMENT1);
Shader* shader = ShaderManager::GetShader("Resources/Shaders/ssao.shader");
shader->Bind();
shader->SetUniformMat4f("u_Projection", projection);
shader->SetUniformMat4f("u_View", view);
shader->SetUniformTex("u_Depth", depthTexture.get(), 2);
shader->SetUniformTex("u_Normal", normalTexture.get(), 3);
shader->SetUniformTex("u_Noise", _ssaoNoiseTexture.get(), 6);
shader->SetUniform1i("u_KernelSize", 64);
shader->SetUniform1f("u_Radius", Radius);
shader->SetUniform1f("u_Bias", Bias);
shader->SetUniform1f("u_Falloff", Falloff);
shader->SetUniform1f("u_Area", Area);
shader->SetUniform1f("u_Strength", Strength);
shader->SetUniformVec2("u_NoiseScale", Vector2(_size.x / 4, _size.y / 4) );
shader->SetUniform("u_Projection", projection);
shader->SetUniform("u_View", view);
shader->SetUniform("u_Depth", depthTexture.get(), 2);
shader->SetUniform("u_Normal", normalTexture.get(), 3);
shader->SetUniform("u_Noise", _ssaoNoiseTexture.get(), 6);
shader->SetUniform("u_KernelSize", 64);
shader->SetUniform("u_Radius", Radius);
shader->SetUniform("u_Bias", Bias);
shader->SetUniform("u_Falloff", Falloff);
shader->SetUniform("u_Area", Area);
shader->SetUniform("u_Strength", Strength);
shader->SetUniform("u_NoiseScale", Vector2(_size.x / 4, _size.y / 4) );
int i = 0;
for (const auto& k : _ssaoKernel)
{
const std::string& uniformName = "u_Samples[" + std::to_string(i) + "]";
shader->SetUniform3f(uniformName, k.x, k.y, k.z);
shader->SetUniform(uniformName, k.x, k.y, k.z);
i++;
}
//shader->SetUniform1fv("u_Samples", 64 * 3, (float*)&(_ssaoKernel.begin()));
//shader->SetUniformv("u_Samples", 64 * 3, (float*)&(_ssaoKernel.begin()));
Renderer::DrawQuad(Matrix4(1.0));
}
_ssaoFramebuffer->Unbind();
@@ -141,7 +141,7 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/blur.shader");
shader->Bind();
shader->SetUniformTex("u_Input", _ssaoFramebuffer->GetTexture().get(), 2);
shader->SetUniform("u_Input", _ssaoFramebuffer->GetTexture().get(), 2);
Renderer::DrawQuad(Matrix4(1.0));
}

View File

@@ -35,28 +35,28 @@ namespace Nuake {
mShader->Bind();
mShader->SetUniform1f("rayStep", RayStep);
mShader->SetUniform1i("iterationCount", IterationCount);
mShader->SetUniform1f("distanceBias", DistanceBias);
mShader->SetUniform1i("enableSSR", (int)1);
mShader->SetUniform1i("sampleCount", SampleCount);
mShader->SetUniform1i("isSamplingEnabled", SamplingEnabled);
mShader->SetUniform1i("isExponentialStepEnabled", ExpoStep);
mShader->SetUniform1i("isAdaptiveStepEnabled", AdaptiveStep);
mShader->SetUniform1i("isBinarySearchEnabled", BinarySearch);
mShader->SetUniform1i("debugDraw", DebugDraw);
mShader->SetUniform1f("samplingCoefficient", SampleingCoefficient);
mShader->SetUniformMat4f("view", view);
mShader->SetUniformMat4f("invView", glm::inverse(view));
mShader->SetUniformMat4f("proj", projection);
mShader->SetUniformMat4f("invProj", glm::inverse(projection));
mShader->SetUniform("rayStep", RayStep);
mShader->SetUniform("iterationCount", IterationCount);
mShader->SetUniform("distanceBias", DistanceBias);
mShader->SetUniform("enableSSR", (int)1);
mShader->SetUniform("sampleCount", SampleCount);
mShader->SetUniform("isSamplingEnabled", SamplingEnabled);
mShader->SetUniform("isExponentialStepEnabled", ExpoStep);
mShader->SetUniform("isAdaptiveStepEnabled", AdaptiveStep);
mShader->SetUniform("isBinarySearchEnabled", BinarySearch);
mShader->SetUniform("debugDraw", DebugDraw);
mShader->SetUniform("samplingCoefficient", SampleingCoefficient);
mShader->SetUniform("view", view);
mShader->SetUniform("invView", glm::inverse(view));
mShader->SetUniform("proj", projection);
mShader->SetUniform("invProj", glm::inverse(projection));
mShader->SetUniformTex("textureDepth", gBuffer->GetTexture(GL_DEPTH_ATTACHMENT).get(), 1);
mShader->SetUniformTex("textureNorm", gBuffer->GetTexture(GL_COLOR_ATTACHMENT1).get(), 2);
mShader->SetUniformTex("textureMetallic", gBuffer->GetTexture(GL_COLOR_ATTACHMENT2).get(), 3);
mShader->SetUniform("textureDepth", gBuffer->GetTexture(GL_DEPTH_ATTACHMENT).get(), 1);
mShader->SetUniform("textureNorm", gBuffer->GetTexture(GL_COLOR_ATTACHMENT1).get(), 2);
mShader->SetUniform("textureMetallic", gBuffer->GetTexture(GL_COLOR_ATTACHMENT2).get(), 3);
mShader->SetUniformTex("textureAlbedo", gBuffer->GetTexture(GL_COLOR_ATTACHMENT0).get(), 5);
mShader->SetUniformTex("textureFrame", previousFrame.get(), 7);
mShader->SetUniform("textureAlbedo", gBuffer->GetTexture(GL_COLOR_ATTACHMENT0).get(), 5);
mShader->SetUniform("textureFrame", previousFrame.get(), 7);
Renderer::DrawQuad(Matrix4());
}

View File

@@ -48,25 +48,25 @@ namespace Nuake {
auto cameraPosition = Vector3(view[3]);
Shader* volumetricShader = ShaderManager::GetShader("Resources/Shaders/volumetric.shader");
volumetricShader->Bind();
volumetricShader->SetUniformMat4f("u_Projection", projection);
volumetricShader->SetUniformMat4f("u_View", view);
volumetricShader->SetUniformTex("u_Depth", mDepth, 1);
volumetricShader->SetUniformVec3("u_CamPosition", camPos);
volumetricShader->SetUniform1i("u_StepCount", mStepCount);
volumetricShader->SetUniform1f("u_FogAmount", mFogAmount);
volumetricShader->SetUniform1i("u_LightCount", static_cast<int>(lights.size()));
volumetricShader->SetUniform1f("u_Exponant", mFogExponant);
volumetricShader->SetUniform("u_Projection", projection);
volumetricShader->SetUniform("u_View", view);
volumetricShader->SetUniform("u_Depth", mDepth, 1);
volumetricShader->SetUniform("u_CamPosition", camPos);
volumetricShader->SetUniform("u_StepCount", mStepCount);
volumetricShader->SetUniform("u_FogAmount", mFogAmount);
volumetricShader->SetUniform("u_LightCount", static_cast<int>(lights.size()));
volumetricShader->SetUniform("u_Exponant", mFogExponant);
for (uint16_t i = 0; i < lights.size(); i++)
{
LightComponent& light = lights[i];
std::string u_light = "u_Lights[" + std::to_string(i) + "].";
volumetricShader->SetUniformMat4f(u_light + "transform", light.mViewProjections[0]);
volumetricShader->SetUniformVec3(u_light + "color", light.Color);
volumetricShader->SetUniformVec3(u_light + "direction", light.GetDirection());
volumetricShader->SetUniform(u_light + "transform", light.mViewProjections[0]);
volumetricShader->SetUniform(u_light + "color", light.Color);
volumetricShader->SetUniform(u_light + "direction", light.GetDirection());
volumetricShader->SetUniformTex(u_light + "shadowmap", light.m_Framebuffers[0]->GetTexture(GL_DEPTH_ATTACHMENT).get(), 5 + i);
volumetricShader->SetUniform1f(u_light + "strength", light.Strength);
volumetricShader->SetUniform(u_light + "shadowmap", light.m_Framebuffers[0]->GetTexture(GL_DEPTH_ATTACHMENT).get(), 5 + i);
volumetricShader->SetUniform(u_light + "strength", light.Strength);
}
Renderer::DrawQuad();
@@ -79,8 +79,8 @@ namespace Nuake {
mFinalFramebuffer->Clear();
Shader* blurShader = ShaderManager::GetShader("Resources/Shaders/blur.shader");
blurShader->Bind();
//blurShader->SetUniformTex("u_Depth", mDepth, 1);
blurShader->SetUniformTex("u_Input", mVolumetricFramebuffer->GetTexture().get());
//blurShader->SetUniform("u_Depth", mDepth, 1);
blurShader->SetUniform("u_Input", mVolumetricFramebuffer->GetTexture().get());
Renderer::DrawQuad();
}

View File

@@ -58,10 +58,10 @@ namespace Nuake
{
if (!depthOnly)
{
shader->SetUniform1i(entityIdUniformLocation, m.entityId + 1);
shader->SetUniform(entityIdUniformLocation, m.entityId + 1);
}
shader->SetUniformMat4f(modelMatrixUniformLocation, m.transform);
shader->SetUniform(modelMatrixUniformLocation, m.transform);
m.mesh->Draw(shader, false);
}
}

View File

@@ -243,13 +243,13 @@ namespace Nuake
{
Shader* lineShader = ShaderManager::GetShader("Resources/Shaders/line.shader");
lineShader->Bind();
lineShader->SetUniformMat4f("u_Projection", camera->GetPerspective());
lineShader->SetUniformMat4f("u_View", camera->GetTransform());
lineShader->SetUniform("u_Projection", camera->GetPerspective());
lineShader->SetUniform("u_View", camera->GetTransform());
m_Shader->Bind();
m_Shader->SetUniformMat4f("u_Projection", camera->GetPerspective());
m_Shader->SetUniformMat4f("u_View", camera->GetTransform());
m_Shader->SetUniform3f("u_EyePosition", camera->GetTranslation().x, camera->GetTranslation().y, camera->GetTranslation().z);
m_Shader->SetUniform("u_Projection", camera->GetPerspective());
m_Shader->SetUniform("u_View", camera->GetTransform());
m_Shader->SetUniform("u_EyePosition", camera->GetTranslation().x, camera->GetTranslation().y, camera->GetTranslation().z);
}
int spotShadowMapCount = 0;
@@ -259,21 +259,21 @@ namespace Nuake
Shader* deferredShader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
deferredShader->Bind();
deferredShader->SetUniform1i("LightCount", 0);
deferredShader->SetUniform("LightCount", 0);
for (int i = 0; i < m_Lights.size(); i++)
{
const std::string uniformAccessor = "Lights[" + std::to_string(i) + "].";
deferredShader->SetUniform3f(uniformAccessor + "Position", 0, 0, 0);
deferredShader->SetUniform3f(uniformAccessor + "Color", 0, 0, 0);
deferredShader->SetUniform1i(uniformAccessor + "Type", -1);
deferredShader->SetUniform1i(uniformAccessor + "CastShadow", 0);
deferredShader->SetUniform1i(uniformAccessor + "ShadowMapID", -1);
deferredShader->SetUniform(uniformAccessor + "Position", 0, 0, 0);
deferredShader->SetUniform(uniformAccessor + "Color", 0, 0, 0);
deferredShader->SetUniform(uniformAccessor + "Type", -1);
deferredShader->SetUniform(uniformAccessor + "CastShadow", 0);
deferredShader->SetUniform(uniformAccessor + "ShadowMapID", -1);
}
for (int i = 0; i < 8; i++)
{
deferredShader->SetUniform1i("SpotShadowMaps[" + std::to_string(i) + "]", 0);
deferredShader->SetUniform("SpotShadowMaps[" + std::to_string(i) + "]", 0);
}
m_Lights.clear();
@@ -297,7 +297,7 @@ namespace Nuake
{
int shadowmapAmount = 0;
deferredShader->SetUniform1i("u_DirectionalLight.Shadow", light.CastShadows);
deferredShader->SetUniform("u_DirectionalLight.Shadow", light.CastShadows);
if (light.CastShadows)
{
@@ -305,16 +305,16 @@ namespace Nuake
{
light.m_Framebuffers[i]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(17 + i);
const uint32_t shadowMapId = shadowmapAmount + i;
deferredShader->SetUniform1i("ShadowMaps[" + std::to_string(shadowMapId) + "]", 17 + i);
deferredShader->SetUniform1i("u_DirectionalLight.ShadowMapsIDs[" + std::to_string(i) + "]", shadowMapId);
deferredShader->SetUniform1f("u_DirectionalLight.CascadeDepth[" + std::to_string(i) + "]", light.mCascadeSplitDepth[i]);
deferredShader->SetUniformMat4f("u_DirectionalLight.LightTransforms[" + std::to_string(i) + "]", light.mViewProjections[i]);
deferredShader->SetUniform("ShadowMaps[" + std::to_string(shadowMapId) + "]", 17 + i);
deferredShader->SetUniform("u_DirectionalLight.ShadowMapsIDs[" + std::to_string(i) + "]", shadowMapId);
deferredShader->SetUniform("u_DirectionalLight.CascadeDepth[" + std::to_string(i) + "]", light.mCascadeSplitDepth[i]);
deferredShader->SetUniform("u_DirectionalLight.LightTransforms[" + std::to_string(i) + "]", light.mViewProjections[i]);
}
}
deferredShader->SetUniform3f("u_DirectionalLight.Direction", direction.x, direction.y, direction.z);
deferredShader->SetUniform1i("u_DirectionalLight.Volumetric", light.IsVolumetric);
deferredShader->SetUniform3f("u_DirectionalLight.Color", light.Color.r * light.Strength, light.Color.g * light.Strength, light.Color.b * light.Strength);
deferredShader->SetUniform("u_DirectionalLight.Direction", direction.x, direction.y, direction.z);
deferredShader->SetUniform("u_DirectionalLight.Volumetric", light.IsVolumetric);
deferredShader->SetUniform("u_DirectionalLight.Color", light.Color.r * light.Strength, light.Color.g * light.Strength, light.Color.b * light.Strength);
shadowmapAmount += CSM_AMOUNT;
}
@@ -329,38 +329,38 @@ namespace Nuake
size_t idx = m_Lights.size();
const std::string uniformAccessor = "Lights[" + std::to_string(idx - 1) + "].";
deferredShader->SetUniform3f(uniformAccessor + "Position", pos.x, pos.y, pos.z);
deferredShader->SetUniform3f(uniformAccessor + "Color", light.Color.r * light.Strength, light.Color.g * light.Strength, light.Color.b * light.Strength);
deferredShader->SetUniform1i(uniformAccessor + "Type", static_cast<int>(light.Type));
deferredShader->SetUniform1i(uniformAccessor + "CastShadow", static_cast<int>(light.CastShadows));
deferredShader->SetUniform(uniformAccessor + "Position", pos.x, pos.y, pos.z);
deferredShader->SetUniform(uniformAccessor + "Color", light.Color.r * light.Strength, light.Color.g * light.Strength, light.Color.b * light.Strength);
deferredShader->SetUniform(uniformAccessor + "Type", static_cast<int>(light.Type));
deferredShader->SetUniform(uniformAccessor + "CastShadow", static_cast<int>(light.CastShadows));
if (light.Type == Spot)
{
direction = transform.GetGlobalRotation() * Vector3(0, 0, -1);
deferredShader->SetUniform3f(uniformAccessor + "Direction", direction.x, direction.y, direction.z);
deferredShader->SetUniform1f(uniformAccessor + "OuterAngle", glm::cos(Rad(light.OuterCutoff)));
deferredShader->SetUniform1f(uniformAccessor + "InnerAngle", glm::cos(Rad(light.Cutoff)));
deferredShader->SetUniform(uniformAccessor + "Direction", direction.x, direction.y, direction.z);
deferredShader->SetUniform(uniformAccessor + "OuterAngle", glm::cos(Rad(light.OuterCutoff)));
deferredShader->SetUniform(uniformAccessor + "InnerAngle", glm::cos(Rad(light.Cutoff)));
if (light.CastShadows && spotShadowMapCount < MaxSpotShadowMap)
{
int shadowMapTextureSlot = 21 + spotShadowMapCount;
deferredShader->SetUniform1i(uniformAccessor + "ShadowMapID", spotShadowMapCount);
deferredShader->SetUniformMat4f(uniformAccessor + "Transform", light.GetProjection() * glm::inverse(transform.GetGlobalTransform()));
deferredShader->SetUniform(uniformAccessor + "ShadowMapID", spotShadowMapCount);
deferredShader->SetUniform(uniformAccessor + "Transform", light.GetProjection() * glm::inverse(transform.GetGlobalTransform()));
light.m_Framebuffers[0]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(shadowMapTextureSlot);
deferredShader->SetUniform1i("SpotShadowMaps[" + std::to_string(spotShadowMapCount) + "]", shadowMapTextureSlot);
deferredShader->SetUniform("SpotShadowMaps[" + std::to_string(spotShadowMapCount) + "]", shadowMapTextureSlot);
spotShadowMapCount++;
}
}
else
{
deferredShader->SetUniform3f(uniformAccessor + "Direction", 0, 0, 0);
deferredShader->SetUniform1f(uniformAccessor + "OuterAngle", glm::cos(Rad(light.OuterCutoff)));
deferredShader->SetUniform1f(uniformAccessor + "InnerAngle", glm::cos(Rad(light.Cutoff)));
deferredShader->SetUniform1f(uniformAccessor + "ShadowMapID", -1);
deferredShader->SetUniform(uniformAccessor + "Direction", 0, 0, 0);
deferredShader->SetUniform(uniformAccessor + "OuterAngle", glm::cos(Rad(light.OuterCutoff)));
deferredShader->SetUniform(uniformAccessor + "InnerAngle", glm::cos(Rad(light.Cutoff)));
deferredShader->SetUniform(uniformAccessor + "ShadowMapID", -1);
}
deferredShader->SetUniform1i("LightCount", static_cast<int>(idx));
deferredShader->SetUniform("LightCount", static_cast<int>(idx));
}
m_LightsUniformBuffer->Bind();
@@ -370,8 +370,8 @@ namespace Nuake
{
Shader* shader = ShaderManager::GetShader("Resources/Shaders/line.shader");
shader->Bind();
shader->SetUniformMat4f("u_Model", transform);
shader->SetUniform4f("u_Color", color.r, color.g, color.b, color.a);
shader->SetUniform("u_Model", transform);
shader->SetUniform("u_Color", color.r, color.g, color.b, color.a);
std::vector<Vertex> vertices
{
@@ -394,14 +394,14 @@ namespace Nuake
{
//m_DebugShader->Bind();
//m_DebugShader->SetUniform4f("u_Color", color.r, color.g, color.b, color.a);
//m_DebugShader->SetUniform("u_Color", color.r, color.g, color.b, color.a);
}
void Renderer::DrawCube(TransformComponent transform, glm::vec4 color)
{
//glDisable(GL_DEPTH_TEST);
m_DebugShader->SetUniformMat4f("u_Model", transform.GetGlobalTransform());
m_DebugShader->SetUniform4f("u_Color", color.r, color.g, color.b, color.a);
m_DebugShader->SetUniform("u_Model", transform.GetGlobalTransform());
m_DebugShader->SetUniform("u_Color", color.r, color.g, color.b, color.a);
CubeMesh->Bind();
RenderCommand::DrawArrays(0, 36);

View File

@@ -50,7 +50,7 @@ namespace Nuake
glDisable(GL_CULL_FACE);
Projection = glm::ortho(0.f, size.x, size.y, 0.f, -1.f, 1000.0f);
UIShader->Bind();
UIShader->SetUniformMat4f("projection", Projection);
UIShader->SetUniform("projection", Projection);
}
void Renderer2D::DrawRect()
@@ -69,9 +69,9 @@ namespace Nuake
glm::decompose(transform, scale, rotation, translation, skew, perspective);
BeginDraw({ 1920.0f, 1080.0f });
UIShader->SetUniformMat4f("model", transform);
UIShader->SetUniform1f("u_border_radius", borderRadius);
UIShader->SetUniform2f("u_size", scale.x, scale.y);
UIShader->SetUniform("model", transform);
UIShader->SetUniform("u_border_radius", borderRadius);
UIShader->SetUniform("u_size", scale.x, scale.y);
glBindVertexArray(Renderer2D::VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
@@ -83,10 +83,10 @@ namespace Nuake
model = glm::translate(model, Vector3(position.x, position.y, 0.f));
model = glm::scale(model, Vector3(size.x, size.y, 1.f));
UIShader->SetUniformMat4f("model", model);
UIShader->SetUniform1f("u_BorderRadius", borderRadius);
UIShader->SetUniform2f("u_Size", size.x, size.y);
UIShader->SetUniform4f("u_BackgroundColor", color.r, color.g, color.b, color.a);
UIShader->SetUniform("model", model);
UIShader->SetUniform("u_BorderRadius", borderRadius);
UIShader->SetUniform("u_Size", size.x, size.y);
UIShader->SetUniform("u_BackgroundColor", color.r, color.g, color.b, color.a);
glBindVertexArray(Renderer2D::VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);

View File

@@ -156,6 +156,13 @@ namespace Nuake
mShadingBuffer->QueueResize(framebufferResolution);
ShadingPass(scene);
ImGui::SetNextWindowSize({ 1280, 720 });
if (ImGui::Begin("Shaded"))
{
ImGui::Image((void*)(mShadingBuffer->GetTexture()->GetID()), ImGui::GetContentRegionAvail(), { 0, 1 }, { 1, 0 });
}
ImGui::End();
// Blit depth buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, mGBuffer->GetRenderID());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mShadingBuffer->GetRenderID());
@@ -176,7 +183,7 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/copy.shader");
shader->Bind();
shader->SetUniformTex("u_Source", mShadingBuffer->GetTexture().get(), 0);
shader->SetUniform("u_Source", mShadingBuffer->GetTexture().get(), 0);
Renderer::DrawQuad();
}
framebuffer.Unbind();
@@ -217,8 +224,8 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/combine.shader");
shader->Bind();
shader->SetUniformTex("u_Source", finalOutput.get(), 0);
shader->SetUniformTex("u_Source2", sceneEnv->mVolumetric->GetFinalOutput().get(), 1);
shader->SetUniform("u_Source", finalOutput.get(), 0);
shader->SetUniform("u_Source2", sceneEnv->mVolumetric->GetFinalOutput().get(), 1);
Renderer::DrawQuad();
}
framebuffer.Unbind();
@@ -231,7 +238,7 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/copy.shader");
shader->Bind();
shader->SetUniformTex("u_Source", finalOutput.get(), 0);
shader->SetUniform("u_Source", finalOutput.get(), 0);
Renderer::DrawQuad();
}
}
@@ -246,9 +253,9 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/tonemap.shader");
shader->Bind();
shader->SetUniform1f("u_Exposure", sceneEnv->Exposure);
shader->SetUniform1f("u_Gamma", sceneEnv->Gamma);
shader->SetUniformTex("u_Source", finalOutput.get());
shader->SetUniform("u_Exposure", sceneEnv->Exposure);
shader->SetUniform("u_Gamma", sceneEnv->Gamma);
shader->SetUniform("u_Source", finalOutput.get());
Renderer::DrawQuad();
}
mToneMapBuffer->Unbind();
@@ -262,11 +269,11 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/outline.shader");
shader->Bind();
shader->SetUniform1i("u_EntityID", mOutlineEntityID == -1 ? -1 : mOutlineEntityID + 1);
shader->SetUniformTex("u_EntityTexture", mGBuffer->GetTexture(GL_COLOR_ATTACHMENT3).get(), 0);
shader->SetUniformVec4("u_OutlineColor", projectSettings.PrimaryColor);
shader->SetUniformTex("u_Depth", mGBuffer->GetTexture(GL_DEPTH_ATTACHMENT), 1);
shader->SetUniform1f("u_Radius", projectSettings.OutlineRadius * projectSettings.ResolutionScale);
shader->SetUniform("u_EntityID", mOutlineEntityID == -1 ? -1 : mOutlineEntityID + 1);
shader->SetUniform("u_EntityTexture", mGBuffer->GetTexture(GL_COLOR_ATTACHMENT3).get(), 0);
shader->SetUniform("u_OutlineColor", projectSettings.PrimaryColor);
shader->SetUniform("u_Depth", mGBuffer->GetTexture(GL_DEPTH_ATTACHMENT).get(), 1);
shader->SetUniform("u_Radius", projectSettings.OutlineRadius * projectSettings.ResolutionScale);
Renderer::DrawQuad();
}
mOutlineBuffer->Unbind();
@@ -277,8 +284,8 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/add.shader");
shader->Bind();
shader->SetUniformTex("u_Source", mToneMapBuffer->GetTexture().get(), 0);
shader->SetUniformTex("u_Source2", mOutlineBuffer->GetTexture().get(), 1);
shader->SetUniform("u_Source", mToneMapBuffer->GetTexture().get(), 0);
shader->SetUniform("u_Source2", mOutlineBuffer->GetTexture().get(), 1);
Renderer::DrawQuad();
}
framebuffer.Unbind();
@@ -289,7 +296,7 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/copy.shader");
shader->Bind();
shader->SetUniformTex("u_Source", framebuffer.GetTexture().get(), 1);
shader->SetUniform("u_Source", framebuffer.GetTexture().get(), 1);
Renderer::DrawQuad();
}
mToneMapBuffer->Unbind();
@@ -305,8 +312,8 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/combine.shader");
shader->Bind();
shader->SetUniformTex("u_Source", mToneMapBuffer->GetTexture().get(), 0);
shader->SetUniformTex("u_Source2", sceneEnv->mSSR->OutputFramebuffer->GetTexture().get(), 1);
shader->SetUniform("u_Source", mToneMapBuffer->GetTexture().get(), 0);
shader->SetUniform("u_Source2", sceneEnv->mSSR->OutputFramebuffer->GetTexture().get(), 1);
Renderer::DrawQuad();
}
framebuffer.Unbind();
@@ -319,7 +326,7 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/copy.shader");
shader->Bind();
shader->SetUniformTex("u_Source", mToneMapBuffer->GetTexture().get(), 0);
shader->SetUniform("u_Source", mToneMapBuffer->GetTexture().get(), 0);
Renderer::DrawQuad();
}
framebuffer.Unbind();
@@ -332,32 +339,32 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/dof.shader");
shader->Bind();
shader->SetUniform1f("focalDepth", sceneEnv->DOFFocalDepth);
shader->SetUniform1f("focalLength", sceneEnv->DOFFocalLength);
shader->SetUniform1f("fstop", sceneEnv->DOFFstop);
shader->SetUniform1i("showFocus", sceneEnv->DOFShowFocus);
shader->SetUniform1i("autofocus", sceneEnv->DOFAutoFocus);
shader->SetUniform1i("samples", sceneEnv->DOFSamples);
shader->SetUniform1i("manualdof", sceneEnv->DOFManualFocus);
shader->SetUniform1f("rings", static_cast<float>(sceneEnv->DOFrings));
shader->SetUniform1f("ndofstart", sceneEnv->DOFStart);
shader->SetUniform1f("ndofdist", sceneEnv->DOFDist);
shader->SetUniform1f("fdofstart", sceneEnv->DOFStart);
shader->SetUniform1f("fdofdist", sceneEnv->DOFDist);
shader->SetUniform1f("CoC", sceneEnv->DOFCoc);
shader->SetUniform1f("maxblur", sceneEnv->DOFMaxBlue);
shader->SetUniform1f("threshold", sceneEnv->DOFThreshold);
shader->SetUniform1f("gain", sceneEnv->DOFGain);
shader->SetUniform1f("bias", sceneEnv->DOFBias);
shader->SetUniform1f("fringe", sceneEnv->DOFFringe);
shader->SetUniform1f("namount", sceneEnv->DOFNAmmount);
shader->SetUniform1f("dbsize", sceneEnv->DOFDbSize);
shader->SetUniform1f("feather", sceneEnv->DOFFeather);
shader->SetUniform1f("u_Distortion", sceneEnv->BarrelDistortion);
shader->SetUniform1f("height", static_cast<float>(finalOutput->GetHeight()));
shader->SetUniform1f("width", static_cast<float>(finalOutput->GetWidth()));
shader->SetUniformTex("depthTex", mGBuffer->GetTexture(GL_DEPTH_ATTACHMENT).get(), 0);
shader->SetUniformTex("renderTex", finalOutput.get(), 1);
shader->SetUniform("focalDepth", sceneEnv->DOFFocalDepth);
shader->SetUniform("focalLength", sceneEnv->DOFFocalLength);
shader->SetUniform("fstop", sceneEnv->DOFFstop);
shader->SetUniform("showFocus", sceneEnv->DOFShowFocus);
shader->SetUniform("autofocus", sceneEnv->DOFAutoFocus);
shader->SetUniform("samples", sceneEnv->DOFSamples);
shader->SetUniform("manualdof", sceneEnv->DOFManualFocus);
shader->SetUniform("rings", static_cast<float>(sceneEnv->DOFrings));
shader->SetUniform("ndofstart", sceneEnv->DOFStart);
shader->SetUniform("ndofdist", sceneEnv->DOFDist);
shader->SetUniform("fdofstart", sceneEnv->DOFStart);
shader->SetUniform("fdofdist", sceneEnv->DOFDist);
shader->SetUniform("CoC", sceneEnv->DOFCoc);
shader->SetUniform("maxblur", sceneEnv->DOFMaxBlue);
shader->SetUniform("threshold", sceneEnv->DOFThreshold);
shader->SetUniform("gain", sceneEnv->DOFGain);
shader->SetUniform("bias", sceneEnv->DOFBias);
shader->SetUniform("fringe", sceneEnv->DOFFringe);
shader->SetUniform("namount", sceneEnv->DOFNAmmount);
shader->SetUniform("dbsize", sceneEnv->DOFDbSize);
shader->SetUniform("feather", sceneEnv->DOFFeather);
shader->SetUniform("u_Distortion", sceneEnv->BarrelDistortion);
shader->SetUniform("height", static_cast<float>(finalOutput->GetHeight()));
shader->SetUniform("width", static_cast<float>(finalOutput->GetWidth()));
shader->SetUniform("depthTex", mGBuffer->GetTexture(GL_DEPTH_ATTACHMENT).get(), 0);
shader->SetUniform("renderTex", finalOutput.get(), 1);
Renderer::DrawQuad();
}
mDOFBuffer->Unbind();
@@ -369,17 +376,17 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/barrel_distortion.shader");
shader->Bind();
shader->SetUniform1f("u_Distortion", sceneEnv->BarrelDistortion);
shader->SetUniform1f("u_DistortionEdge", sceneEnv->BarrelEdgeDistortion);
shader->SetUniform1f("u_Scale", sceneEnv->BarrelScale);
shader->SetUniform("u_Distortion", sceneEnv->BarrelDistortion);
shader->SetUniform("u_DistortionEdge", sceneEnv->BarrelEdgeDistortion);
shader->SetUniform("u_Scale", sceneEnv->BarrelScale);
if (sceneEnv->DOFEnabled)
{
shader->SetUniformTex("u_Source", mDOFBuffer->GetTexture().get(), 0);
shader->SetUniform("u_Source", mDOFBuffer->GetTexture().get(), 0);
}
else
{
shader->SetUniformTex("u_Source", finalOutput.get(), 0);
shader->SetUniform("u_Source", finalOutput.get(), 0);
}
@@ -393,7 +400,7 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/copy.shader");
shader->Bind();
shader->SetUniformTex("u_Source", mBarrelDistortionBuffer->GetTexture().get(), 0);
shader->SetUniform("u_Source", mBarrelDistortionBuffer->GetTexture().get(), 0);
Renderer::DrawQuad();
}
framebuffer.Unbind();
@@ -405,9 +412,9 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/vignette.shader");
shader->Bind();
shader->SetUniform1f("u_Intensity", sceneEnv->VignetteIntensity);
shader->SetUniform1f("u_Extend", sceneEnv->VignetteEnabled ? sceneEnv->VignetteExtend : 0.0f);
shader->SetUniformTex("u_Source", framebuffer.GetTexture().get(), 0);
shader->SetUniform("u_Intensity", sceneEnv->VignetteIntensity);
shader->SetUniform("u_Extend", sceneEnv->VignetteEnabled ? sceneEnv->VignetteExtend : 0.0f);
shader->SetUniform("u_Source", framebuffer.GetTexture().get(), 0);
Renderer::DrawQuad();
}
mVignetteBuffer->Unbind();
@@ -418,8 +425,8 @@ namespace Nuake
// Shader* shader = ShaderManager::GetShader("Resources/Shaders/add.shader");
// shader->Bind();
//
// shader->SetUniformTex("u_Source", mVignetteBuffer->GetTexture().get(), 0);
// shader->SetUniformTex("u_Source2", mOutlineBuffer->GetTexture().get(), 1);
// shader->SetUniform("u_Source", mVignetteBuffer->GetTexture().get(), 0);
// shader->SetUniform("u_Source2", mOutlineBuffer->GetTexture().get(), 1);
// Renderer::DrawQuad();
//}
//framebuffer.Unbind();
@@ -430,7 +437,7 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/copy.shader");
shader->Bind();
shader->SetUniformTex("u_Source", mVignetteBuffer->GetTexture().get(), 0);
shader->SetUniform("u_Source", mVignetteBuffer->GetTexture().get(), 0);
Renderer::DrawQuad();
}
framebuffer.Unbind();
@@ -449,9 +456,9 @@ namespace Nuake
// Shader* shader = ShaderManager::GetShader("Resources/Shaders/vignette.shader");
// shader->Bind();
//
// shader->SetUniform1f("u_Intensity", sceneEnv->VignetteIntensity);
// shader->SetUniform1f("u_Extend", sceneEnv->VignetteExtend);
// shader->SetUniformTex("u_Source", mBarrelDistortionBuffer->GetTexture().get(), 0);
// shader->SetUniform("u_Intensity", sceneEnv->VignetteIntensity);
// shader->SetUniform("u_Extend", sceneEnv->VignetteExtend);
// shader->SetUniform("u_Source", mBarrelDistortionBuffer->GetTexture().get(), 0);
// Renderer::DrawQuad();
//}
//mVignetteBuffer->Unbind();
@@ -535,7 +542,7 @@ namespace Nuake
light.m_Framebuffers[i]->Bind();
light.m_Framebuffers[i]->Clear();
{
shader->SetUniformMat4f("u_LightTransform", light.mViewProjections[i]);
shader->SetUniform("u_LightTransform", light.mViewProjections[i]);
for (auto e : meshView)
{
auto [transform, mesh, visibility] = meshView.get<TransformComponent, ModelComponent, VisibilityComponent>(e);
@@ -627,7 +634,7 @@ namespace Nuake
const Quat& globalRotation = glm::normalize(lightTransform.GetGlobalRotation());
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
shader->SetUniformMat4f("u_LightTransform", light.GetProjection() * glm::inverse(lightTransform.GetGlobalTransform()));
shader->SetUniform("u_LightTransform", light.GetProjection() * glm::inverse(lightTransform.GetGlobalTransform()));
for (auto e : meshView)
{
auto [transform, mesh, visibility] = meshView.get<TransformComponent, ModelComponent, VisibilityComponent>(e);
@@ -701,7 +708,7 @@ namespace Nuake
Shader* gBufferSkinnedMeshShader = ShaderManager::GetShader("Resources/Shaders/shadowMap_skinned.shader");
gBufferSkinnedMeshShader->Bind();
const uint32_t modelMatrixUniformLocation = gBufferSkinnedMeshShader->FindUniformLocation("u_Model");
gBufferSkinnedMeshShader->SetUniformMat4f(modelMatrixUniformLocation, Matrix4(1.0f));
gBufferSkinnedMeshShader->SetUniform(modelMatrixUniformLocation, Matrix4(1.0f));
auto skinnedView = scene.m_Registry.view<TransformComponent, SkinnedModelComponent, VisibilityComponent>();
for (auto l : view)
@@ -716,7 +723,7 @@ namespace Nuake
{
light.m_Framebuffers[i]->Bind();
{
gBufferSkinnedMeshShader->SetUniformMat4f("u_LightTransform", light.mViewProjections[i]);
gBufferSkinnedMeshShader->SetUniform("u_LightTransform", light.mViewProjections[i]);
for (auto e : skinnedView)
{
auto [transform, mesh, visibility] = skinnedView.get<TransformComponent, SkinnedModelComponent, VisibilityComponent>(e);
@@ -743,7 +750,7 @@ namespace Nuake
displayDepthShader->Bind();
GetGBuffer().GetTexture(GL_DEPTH_ATTACHMENT)->Bind(5);
displayDepthShader->SetUniform1i("u_Source", 5);
displayDepthShader->SetUniform("u_Source", 5);
RenderCommand::Disable(RendererEnum::DEPTH_TEST);
Renderer::DrawQuad(Matrix4(1.0f));
@@ -766,8 +773,8 @@ namespace Nuake
Shader* gBufferSkinnedMeshShader = ShaderManager::GetShader("Resources/Shaders/gbuffer_skinned.shader");
gBufferShader->Bind();
gBufferShader->SetUniformMat4f("u_Projection", mProjection);
gBufferShader->SetUniformMat4f("u_View", mView);
gBufferShader->SetUniform("u_Projection", mProjection);
gBufferShader->SetUniform("u_View", mView);
// Models
auto view = scene.m_Registry.view<TransformComponent, ModelComponent, VisibilityComponent>();
@@ -923,15 +930,15 @@ namespace Nuake
// Skinned mesh at the end because we switch shader
gBufferSkinnedMeshShader->Bind();
gBufferSkinnedMeshShader->SetUniformMat4f("u_Projection", mProjection);
gBufferSkinnedMeshShader->SetUniformMat4f("u_View", mView);
gBufferSkinnedMeshShader->SetUniform("u_Projection", mProjection);
gBufferSkinnedMeshShader->SetUniform("u_View", mView);
RenderCommand::Disable(RendererEnum::FACE_CULL);
// Skinned Models
const uint32_t entityIdUniformLocation = gBufferSkinnedMeshShader->FindUniformLocation("u_EntityID");
const uint32_t modelMatrixUniformLocation = gBufferSkinnedMeshShader->FindUniformLocation("u_Model");
gBufferSkinnedMeshShader->SetUniformMat4f(modelMatrixUniformLocation, Matrix4(1.0f));
gBufferSkinnedMeshShader->SetUniform(modelMatrixUniformLocation, Matrix4(1.0f));
auto skinnedModelView = scene.m_Registry.view<TransformComponent, SkinnedModelComponent, VisibilityComponent>();
for (auto e : skinnedModelView)
{
@@ -947,7 +954,7 @@ namespace Nuake
{
m->GetMaterial()->Bind(gBufferSkinnedMeshShader);
gBufferSkinnedMeshShader->SetUniform1i(entityIdUniformLocation, (uint32_t)e + 1);
gBufferSkinnedMeshShader->SetUniform(entityIdUniformLocation, (uint32_t)e + 1);
m->Draw(gBufferSkinnedMeshShader, true);
}
}
@@ -984,11 +991,11 @@ namespace Nuake
Shader* shadingShader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
shadingShader->Bind();
shadingShader->SetUniformMat4f("u_Projection", mProjection);
shadingShader->SetUniformMat4f("u_View", mView);
shadingShader->SetUniformVec3("u_EyePosition", scene.GetCurrentCamera()->Translation);
shadingShader->SetUniform1f("u_AmbientTerm", environment->AmbientTerm);
shadingShader->SetUniformTex("m_SSAO", scene.GetEnvironment()->mSSAO->GetOuput()->GetTexture().get(), 9);
shadingShader->SetUniform("u_Projection", mProjection);
shadingShader->SetUniform("u_View", mView);
shadingShader->SetUniform("u_EyePosition", scene.GetCurrentCamera()->Translation);
shadingShader->SetUniform("u_AmbientTerm", environment->AmbientTerm);
shadingShader->SetUniform("m_SSAO", scene.GetEnvironment()->mSSAO->GetOuput()->GetTexture().get(), 9);
Ref<Environment> env = scene.GetEnvironment();
@@ -1045,11 +1052,11 @@ namespace Nuake
mGBuffer->GetTexture(GL_COLOR_ATTACHMENT2)->Bind(8);
mGBuffer->GetTexture(GL_COLOR_ATTACHMENT4)->Bind(10);
shadingShader->SetUniform1i("m_Depth", 5);
shadingShader->SetUniform1i("m_Albedo", 6);
shadingShader->SetUniform1i("m_Normal", 7);
shadingShader->SetUniform1i("m_Material", 8);
shadingShader->SetUniform1i("m_Emissive", 10);
shadingShader->SetUniform("m_Depth", 5);
shadingShader->SetUniform("m_Albedo", 6);
shadingShader->SetUniform("m_Normal", 7);
shadingShader->SetUniform("m_Material", 8);
shadingShader->SetUniform("m_Emissive", 10);
RenderCommand::Disable(RendererEnum::FACE_CULL);
@@ -1073,15 +1080,15 @@ namespace Nuake
Shader* shader = ShaderManager::GetShader("Resources/Shaders/debugLine.shader");
shader->Bind();
shader->SetUniformMat4f("u_Projection", mProjection);
shader->SetUniformMat4f("u_View", mView);
shader->SetUniform("u_Projection", mProjection);
shader->SetUniform("u_View", mView);
bool depthTestState = true;
for (auto& l : mDebugLines)
{
shader->SetUniformVec4("u_Color", l.LineColor);
shader->SetUniformVec3("u_StartPos", l.Start);
shader->SetUniformVec3("u_EndPos", l.End);
shader->SetUniform("u_Color", l.LineColor);
shader->SetUniform("u_StartPos", l.Start);
shader->SetUniform("u_EndPos", l.End);
if (l.DepthTest)
{
@@ -1096,8 +1103,8 @@ namespace Nuake
shader = Nuake::ShaderManager::GetShader("Resources/Shaders/line.shader");
shader->Bind();
shader->SetUniform1f("u_Opacity", 0.5f);
shader->SetUniformMat4f("u_Projection", mProjection);
shader->SetUniform("u_Opacity", 0.5f);
shader->SetUniform("u_Projection", mProjection);
for (auto& shape : mDebugShapes)
{
@@ -1110,7 +1117,7 @@ namespace Nuake
RenderCommand::Disable(RendererEnum::DEPTH_TEST);
}
shader->SetUniformVec4("u_Color", shape.LineColor);
shader->SetUniform("u_Color", shape.LineColor);
glLineWidth(shape.Width);
Matrix4 view = mView;
@@ -1125,7 +1132,7 @@ namespace Nuake
view = glm::translate(view, shape.Position) * rotationMatrix;
view = glm::scale(view, reinterpret_cast<Physics::Box*>(shape.Shape.get())->GetSize());
shader->SetUniformMat4f("u_View", view);
shader->SetUniform("u_View", view);
mBoxGizmo->Bind();
RenderCommand::DrawLines(0, 26);
@@ -1138,7 +1145,7 @@ namespace Nuake
view = glm::translate(view, shape.Position) * rotationMatrix;
view = glm::scale(view, Vector3(reinterpret_cast<Physics::Sphere*>(shape.Shape.get())->GetRadius()));
shader->SetUniformMat4f("u_View", view);
shader->SetUniform("u_View", view);
mSphereGizmo->Bind();
RenderCommand::DrawLines(0, 128);
@@ -1151,7 +1158,7 @@ namespace Nuake
view = glm::translate(view, shape.Position) * rotationMatrix;
shader->SetUniformMat4f("u_View", view);
shader->SetUniform("u_View", view);
const Physics::Capsule* capsule = reinterpret_cast<Physics::Capsule*>(shape.Shape.get());
mCapsuleGizmo->UpdateShape(capsule->GetRadius(), capsule->GetHeight());
@@ -1168,7 +1175,7 @@ namespace Nuake
const Physics::Cylinder* cylinder = reinterpret_cast<Physics::Cylinder*>(shape.Shape.get());
shader->SetUniformMat4f("u_View", view);
shader->SetUniform("u_View", view);
mCylinderGizmo->Bind();
mCylinderGizmo->UpdateShape(cylinder->GetRadius(), cylinder->GetHeight());
@@ -1190,7 +1197,7 @@ namespace Nuake
if (auto entity = scene.GetEntity(child.Name); entity.GetHandle() != -1)
{
const std::string boneMatrixUniformName = "u_FinalBonesMatrice[" + std::to_string(child.Id) + "]";
shader->SetUniformMat4f(boneMatrixUniformName, child.FinalTransform);
shader->SetUniform(boneMatrixUniformName, child.FinalTransform);
}
SetSkeletonBoneTransformRecursive(scene, child, shader);

View File

@@ -20,7 +20,7 @@ namespace Nuake
!fileContent.empty())
{
Source = ParseShader(fileContent);
ProgramId = CreateProgram(Source);
programId = CreateProgram(Source);
return;
}
}
@@ -33,7 +33,7 @@ namespace Nuake
Path = filePath;
Source = ParseShader(content);
ProgramId = CreateProgram(Source);
programId = CreateProgram(Source);
}
bool Shader::Rebuild()
@@ -51,7 +51,7 @@ namespace Nuake
return false;
Source = newSource;
ProgramId = newProgramId;
programId = newProgramId;
return true;
}
@@ -59,7 +59,7 @@ namespace Nuake
// Bind the shader
void Shader::Bind() const
{
glUseProgram(ProgramId);
glUseProgram(programId);
}
// unbind the shader
@@ -220,7 +220,7 @@ namespace Nuake
{
if (UniformCache.find(uniform) == UniformCache.end())
{
int addr = glGetUniformLocation(ProgramId, uniform.c_str());
int addr = glGetUniformLocation(programId, uniform.c_str());
if (addr == -1)
return addr;
@@ -234,125 +234,166 @@ namespace Nuake
}
// Uniforms
void Shader::SetUniformVec4(const std::string& name, Vector4 vec)
void Shader::SetUniforms(const std::vector<UniformVariable>& uniforms)
{
SetUniform4f(name, vec.x, vec.y, vec.z, vec.w);
for (auto& u : uniforms)
{
std::string name = u.name;
auto type = u.type;
switch (type)
{
case UniformTypes::Float:
SetUniform(name, u.value.valueFloat);
break;
case UniformTypes::Int:
SetUniform(name, u.value.valueInt);
break;
case UniformTypes::Uint:
SetUniform(name, u.value.valueUInt);
break;
case UniformTypes::Vec2:
SetUniform(name, u.value.valueVec2);
break;
case UniformTypes::Vec3:
SetUniform(name, u.value.valueVec3);
break;
case UniformTypes::Vec4:
SetUniform(name, u.value.valueVec4);
break;
case UniformTypes::Mat3:
SetUniform(name, u.value.valueMat3);
break;
case UniformTypes::Mat4:
SetUniform(name, u.value.valueMat4);
break;
case UniformTypes::Sampler2D:
SetUniform(name, u.value.valueInt);
break;
}
}
}
void Shader::SetUniformVec3(const std::string& name, Vector3 vec)
{
SetUniform3f(name, vec.x, vec.y, vec.z);
}
void Shader::SetUniformVec2(const std::string& name, Vector2 vec)
{
SetUniform2f(name, vec.x, vec.y);
}
void Shader::SetUniform4f(const std::string& name, float v0, float v1, float v2, float v3)
void Shader::SetUniform(const std::string& name, float v0)
{
int addr = FindUniformLocation(name);
//ASSERT(addr != -1);
if (addr != -1)
glUniform4f(addr, v0, v1, v2, v3);
{
glUniform1f(addr, v0);
}
}
void Shader::SetUniform3f(const std::string& name, float v0, float v1, float v2)
void Shader::SetUniform(const std::string& name, int v0)
{
int addr = FindUniformLocation(name);
//ASSERT(addr != -1);
if (addr != -1)
glUniform3f(addr, v0, v1, v2);
glUniform1i(addr, v0);
}
void Shader::SetUniform2f(const std::string& name, float v0, float v1)
void Shader::SetUniform(const std::string& name, unsigned int v0)
{
int addr = FindUniformLocation(name);
//ASSERT(addr != -1);
if (addr != -1)
glUniform2f(addr, v0, v1);
glUniform1ui(addr, v0);
}
void Shader::SetUniform1i(const std::string& name, int v0)
void Shader::SetUniform(const std::string& name, Vector2 v0)
{
int addr = FindUniformLocation(name);
//ASSERT(addr != -1);
if (addr != -1)
SetUniform1i(addr, v0);
SetUniform(name, v0.x, v0.y);
}
void Shader::SetUniform1i(uint32_t location, int v0)
{
glUniform1i(location, v0);
}
void Shader::SetUniform1iv(const std::string& name, int size, int* value)
{
int addr = FindUniformLocation(name);
//ASSERT(addr != -1);
if (addr != -1)
glUniform1iv(addr, size, value);
}
void Shader::SetUniform1fv(const std::string& name, int size, float* value)
{
int addr = FindUniformLocation(name);
//ASSERT(addr != -1);
if (addr != -1)
glUniform1fv(addr, size, value);
}
void Shader::SetUniformMat3f(const std::string& name, Matrix3 mat)
{
int addr = FindUniformLocation(name);
//ASSERT(addr != -1);
if(addr != -1)
glUniformMatrix3fv(addr, 1, GL_FALSE, &mat[0][0]);
}
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)
void Shader::SetUniform(const std::string& name, float v0, float v1)
{
int addr = FindUniformLocation(name);
if (addr != -1)
{
SetUniformMat4f(addr, mat);
glUniform2f(addr, v0, v1);
}
}
void Shader::SetUniform1f(const std::string& name, float v0)
void Shader::SetUniform(const std::string& name, float v0, float v1, float v2)
{
int addr = FindUniformLocation(name);
//ASSERT(addr != -1);
if (addr != -1)
glUniform1f(addr, v0);
{
glUniform3f(addr, v0, v1, v2);
}
}
void Shader::SetUniformTex(const std::string& name, Texture* texture, unsigned int slot)
void Shader::SetUniform(const std::string& name, Vector3 v0)
{
//ASSERT(texture != nullptr);
SetUniform1i(name, slot);
texture->Bind(slot);
SetUniform(name, v0.x, v0.y, v0.z);
}
void Shader::SetUniformTex(const std::string& name, Ref<Texture> texture, unsigned int slot)
void Shader::SetUniform(const std::string& name, float v0, float v1, float v2, float v3)
{
//ASSERT(texture != nullptr);
int addr = FindUniformLocation(name);
SetUniform1i(name, slot);
if (addr != -1)
{
glUniform4f(addr, v0, v1, v2, v3);
}
}
void Shader::SetUniform(const std::string& name, Vector4 v0)
{
SetUniform(name, v0.x, v0.y, v0.z, v0.w);
}
void Shader::SetUniform(const std::string& name, Matrix3 v0)
{
int addr = FindUniformLocation(name);
if (addr != -1)
{
glUniformMatrix3fv(addr, 1, GL_FALSE, &v0[0][0]);
}
}
void Shader::SetUniform(const std::string& name, Matrix4 v0)
{
int addr = FindUniformLocation(name);
if (addr != -1)
{
glUniformMatrix4fv(addr, 1, GL_FALSE, &v0[0][0]);
}
}
void Shader::SetUniformv(const std::string & name, int size, int* value)
{
int addr = FindUniformLocation(name);
if (addr != -1)
{
glUniform1iv(addr, size, value);
}
}
void Shader::SetUniform(const std::string & name, int size, float* value)
{
int addr = FindUniformLocation(name);
if (addr != -1)
{
glUniform1fv(addr, size, value);
}
}
void Shader::SetUniform(const std::string& name, bool value)
{
SetUniform(name, value);
}
void Shader::SetUniform(uint32_t uniformSlot, int value)
{
glUniform1i(uniformSlot, value);
}
void Shader::SetUniform(uint32_t uniformSlot, Matrix4 value)
{
glUniformMatrix4fv(uniformSlot, 1, GL_FALSE, &value[0][0]);
}
void Shader::SetUniform(const std::string& uniformName, Texture* texture, uint32_t slot)
{
SetUniform(uniformName, slot);
texture->Bind(slot);
}
}

View File

@@ -18,41 +18,134 @@ namespace Nuake
std::string ComputeShader;
};
enum class UniformTypes
{
Int, Uint, Float, Bool, Vec2, Vec3, Vec4, Mat3, Mat4, Sampler2D
};
union UniformValue
{
float valueFloat;
int valueInt;
unsigned int valueUInt;
Vector2 valueVec2;
Vector3 valueVec3;
Vector4 valueVec4;
Matrix3 valueMat3;
Matrix4 valueMat4;
};
struct UniformVariable
{
std::string name;
UniformValue value;
UniformTypes type;
UniformVariable(const std::string& uniformName, float uniformValue)
{
name = uniformName;
value.valueFloat = uniformValue;
type = UniformTypes::Float;
}
UniformVariable(const std::string& uniformName, int uniformValue)
{
name = uniformName;
value.valueInt = uniformValue;
type = UniformTypes::Int;
}
UniformVariable(const std::string& uniformName, bool uniformValue)
{
name = uniformName;
value.valueInt = static_cast<int>(uniformValue);
type = UniformTypes::Int;
}
UniformVariable(const std::string& uniformName, Vector2 uniformValue)
{
name = uniformName;
value.valueVec2 = uniformValue;
type = UniformTypes::Vec2;
}
UniformVariable(const std::string& uniformName, Vector3 uniformValue)
{
name = uniformName;
value.valueVec3 = uniformValue;
type = UniformTypes::Vec3;
}
UniformVariable(const std::string& uniformName, Vector4 uniformValue)
{
name = uniformName;
value.valueVec4 = uniformValue;
type = UniformTypes::Vec4;
}
UniformVariable(const std::string& uniformName, Matrix3 uniformValue)
{
name = uniformName;
value.valueMat3 = uniformValue;
type = UniformTypes::Mat3;
}
UniformVariable(const std::string& uniformName, Matrix4 uniformValue)
{
name = uniformName;
value.valueMat4 = uniformValue;
type = UniformTypes::Mat4;
}
};
class Shader
{
public:
private:
uint32_t programId;
std::string Path;
ShaderSource Source;
unsigned int ProgramId;
std::unordered_map<std::string, int> UniformCache;
Shader(const std::string& filePath);
std::map<std::string, unsigned int> mUniforms;
std::map<std::string, UniformTypes> mUniformsType;
std::string mError = "";
public:
Shader(const std::string& filePath);
Shader(const std::string& path, const std::string& content);
bool Rebuild();
void Bind() const;
void Unbind() const;
void SetUniformVec4(const std::string& name, Vector4 vec);
void SetUniformVec3(const std::string& name, Vector3 vec);
void SetUniformVec2(const std::string& name, Vector2 vec);
void SetUniform4f(const std::string& name, float v0, float v1, float v2, float v3);
void SetUniform3f(const std::string& name, float v0, float v1, float v2);
void SetUniform2f(const std::string& name, float v0, float v1);
void SetUniform1f(const std::string& name, float v0);
void SetUniform1b(const std::string& name, bool v0);
void SetUniformTex(const std::string& name, Texture* texture, unsigned int slot = 0);
void SetUniformTex(const std::string& name, Ref<Texture> texture, unsigned int slot = 0);
void SetUniform1i(const std::string& name, int v0);
void SetUniform1i(uint32_t location, int v0);
std::map<std::string, UniformTypes> GetUniforms()
{
return mUniformsType;
}
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);
std::string GetError() const { return mError; }
void SetUniformMat4f(uint32_t name, const Matrix4& mat);
void SetUniformMat4f(const std::string& name, const Matrix4& mat);
void SetUniforms(const std::vector<UniformVariable>& uniforms);
void SetUniform(const std::string& name, float v0);
void SetUniform(const std::string& name, int v0);
void SetUniform(const std::string& name, unsigned int v0);
void SetUniform(const std::string& name, float v0, float v1);
void SetUniform(const std::string& name, Vector2 v0);
void SetUniform(const std::string& name, float v0, float v1, float v3);
void SetUniform(const std::string& name, Vector3 v0);
void SetUniform(const std::string& name, float v0, float v1, float v3, float v4);
void SetUniform(const std::string& name, Vector4 v0);
void SetUniform(const std::string& name, Matrix3 v0);
void SetUniform(const std::string& name, Matrix4 v0);
void SetUniformv(const std::string& name, int size, int* value);
void SetUniform(const std::string& name, int size, float* value);
void SetUniform(const std::string& name, bool value);
void SetUniform(uint32_t uniformSlot, int value);
void SetUniform(uint32_t uniformSlot, Matrix4 value);
void SetUniform(const std::string& name, Texture* texture, uint32_t slot);
int FindUniformLocation(std::string uniform);

View File

@@ -107,7 +107,7 @@ namespace Nuake
}
else
m_DefaultAlbedo->Bind(4);
shader->SetUniform1i("m_Albedo", 4);
shader->SetUniform("m_Albedo", 4);
// AO
if (m_AO != nullptr)
@@ -117,7 +117,7 @@ namespace Nuake
}
else
m_DefaultAO->Bind(5);
shader->SetUniform1i("m_AO", 5);
shader->SetUniform("m_AO", 5);
// Metallic
if (m_Metalness != nullptr) {
@@ -126,7 +126,7 @@ namespace Nuake
}
else
m_DefaultMetalness->Bind(6);
shader->SetUniform1i("m_Metalness", 6);
shader->SetUniform("m_Metalness", 6);
// Roughness
if (m_Roughness != nullptr) {
@@ -135,7 +135,7 @@ namespace Nuake
}
else
m_DefaultRoughness->Bind(7);
shader->SetUniform1i("m_Roughness", 7);
shader->SetUniform("m_Roughness", 7);
// Normal
if (m_Normal != nullptr) {
@@ -145,7 +145,7 @@ namespace Nuake
else
m_DefaultNormal->Bind(8);
shader->SetUniform1i("m_Normal", 8);
shader->SetUniform("m_Normal", 8);
// Displacement
if (m_Displacement != nullptr)
@@ -158,8 +158,8 @@ namespace Nuake
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UBOStructure), &data);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindBufferBase(GL_UNIFORM_BUFFER, 32, UBO);
//Renderer::m_Shader->SetUniform1i("m_Displacement", 9);
//Renderer::m_Shader->SetUniform1i("m_Displacement", 9);
//Renderer::m_Shader->SetUniform("m_Displacement", 9);
//Renderer::m_Shader->SetUniform("m_Displacement", 9);
}
void Material::SetupUniformBuffer()

View File

@@ -41,6 +41,24 @@ namespace Nuake
}
}
Texture::Texture(Vector2 size, void* data)
{
m_Width = size.x;
m_Height = size.y;
glGenTextures(1, &m_RendererId);
glBindTexture(GL_TEXTURE_2D, m_RendererId);
glGenerateMipmap(GL_TEXTURE_2D);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -1.0f);
glTexImage2D(GL_TEXTURE_2D, 0, (GLenum)GL_RGBA, size.x, size.y, 0, (GLenum)GL_RGBA, (GLenum)GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
Texture::Texture(Vector2 size, GLenum format, GLenum format2, GLenum format3, void* data)
{
m_RendererId = 0;

View File

@@ -30,7 +30,7 @@ namespace Nuake
public:
Texture(const std::string& path); // Load texture from file
Texture(unsigned char* data, int len); // Used to load texture from a memory buffer
Texture(Vector2 size, void* data);
Texture(Vector2 size, GLenum format, GLenum format2 = 0, GLenum format3 = 0, void* data = 0); // Used to load texture from memeory with known size
~Texture();

View File

@@ -34,7 +34,7 @@ namespace Nuake
template<typename T>
T& AddComponent()
{
T& component = m_Scene->m_Registry.emplace_or_replace <T>(m_EntityHandle);
T& component = m_Scene->m_Registry.emplace_or_replace<T>(m_EntityHandle);
return component;
}

View File

@@ -37,41 +37,41 @@ namespace Nuake
void ProceduralSky::Draw(Matrix4 projection, Matrix4 view) {
Shader* skyShader = ShaderManager::GetShader("Resources/Shaders/atmospheric_sky.shader");
skyShader->Bind();
skyShader->SetUniform1f("SurfaceRadius", SurfaceRadius);
skyShader->SetUniform1f("AtmosphereRadius", AtmosphereRadius);
skyShader->SetUniform1f("SunIntensity", SunIntensity);
skyShader->SetUniform("SurfaceRadius", SurfaceRadius);
skyShader->SetUniform("AtmosphereRadius", AtmosphereRadius);
skyShader->SetUniform("SunIntensity", SunIntensity);
skyShader->SetUniform3f("RayleighScattering",
skyShader->SetUniform("RayleighScattering",
RayleighScattering.r,
RayleighScattering.g,
RayleighScattering.b);
skyShader->SetUniform3f("MieScattering",
skyShader->SetUniform("MieScattering",
MieScattering.r,
MieScattering.g,
MieScattering.b);
skyShader->SetUniform3f("CenterPoint",
skyShader->SetUniform("CenterPoint",
CenterPoint.x,
CenterPoint.y,
CenterPoint.z);
skyShader->SetUniform3f("SunDirection",
skyShader->SetUniform("SunDirection",
SunDirection.x,
SunDirection.y,
SunDirection.z);
skyShader->SetUniformMat4f("Projection", projection);
skyShader->SetUniformMat4f("View", view);
skyShader->SetUniform("Projection", projection);
skyShader->SetUniform("View", view);
//glm::vec3 CamRight = cam->cameraRight;
//Renderer::m_ProceduralSkyShader->SetUniform3f("CamRight",
//Renderer::m_ProceduralSkyShader->SetUniform("CamRight",
// CamRight.x,
// CamRight.y,
// CamRight.z);
//
//glm::vec3 CamUp = cam->cameraUp;//glm::normalize(glm::cross(CameraDirection, CamRight));
//Renderer::m_ProceduralSkyShader->SetUniform3f("CamUp",
//Renderer::m_ProceduralSkyShader->SetUniform("CamUp",
// CamUp.x,
// CamUp.y,
// CamUp.z);

View File

@@ -75,26 +75,26 @@ namespace Nuake
m_Hdr->Bind(4);
Renderer::m_SkyboxShader->Bind();
m_Hdr->BindCubemap(5);
Renderer::m_SkyboxShader->SetUniformMat4f("projection", projection);
Renderer::m_SkyboxShader->SetUniformMat4f("view", view);
Renderer::m_SkyboxShader->SetUniform("projection", projection);
Renderer::m_SkyboxShader->SetUniform("view", view);
Renderer::m_SkyboxShader->SetUniform1i("isHDR", 0);
Renderer::m_SkyboxShader->SetUniform1i("equirectangularMap", 4);
Renderer::m_SkyboxShader->SetUniform1i("skybox", 5);
Renderer::m_SkyboxShader->SetUniform("isHDR", 0);
Renderer::m_SkyboxShader->SetUniform("equirectangularMap", 4);
Renderer::m_SkyboxShader->SetUniform("skybox", 5);
// ... set view and projection matrix
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glDepthMask(GL_TRUE);
//Renderer::m_Shader->SetUniform4f("u_AmbientColor", 1.0f, 1.0f, 1.0f, 1.0f);
//Renderer::m_Shader->SetUniform("u_AmbientColor", 1.0f, 1.0f, 1.0f, 1.0f);
}
void Skybox::Push()
{
m_Hdr->BindCubemap(5);
Renderer::m_Shader->SetUniform1i("u_IrradianceMap", 5);
Renderer::m_Shader->SetUniform("u_IrradianceMap", 5);
}
@@ -139,17 +139,17 @@ namespace Nuake
// convert HDR equirectangular environment map to cubemap equivalent
Renderer::m_SkyboxShader->Bind();
Renderer::m_SkyboxShader->SetUniformMat4f("projection", captureProjection);
Renderer::m_SkyboxShader->SetUniform1i("convulate", 0);
Renderer::m_SkyboxShader->SetUniform1i("isHDR", 1);
Renderer::m_SkyboxShader->SetUniform1i("equirectangularMap", 5);
Renderer::m_SkyboxShader->SetUniform("projection", captureProjection);
Renderer::m_SkyboxShader->SetUniform("convulate", 0);
Renderer::m_SkyboxShader->SetUniform("isHDR", 1);
Renderer::m_SkyboxShader->SetUniform("equirectangularMap", 5);
glActiveTexture(GL_TEXTURE0);
glViewport(0, 0, 512, 512); // don't forget to configure the viewport to the capture dimensions.
glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
for (unsigned int i = 0; i < 6; ++i)
{
Renderer::m_SkyboxShader->SetUniformMat4f("view", captureViews[i]);
Renderer::m_SkyboxShader->SetUniform("view", captureViews[i]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

View File

@@ -85,20 +85,20 @@ namespace Nuake {
m_HDRTexture->Bind(6);
Renderer::m_SkyboxShader->Bind();
Renderer::m_SkyboxShader->SetUniformMat4f("projection", projection);
Renderer::m_SkyboxShader->SetUniformMat4f("view", view);
Renderer::m_SkyboxShader->SetUniform1i("convulate", 0);
Renderer::m_SkyboxShader->SetUniform1i("prefilter", 0);
Renderer::m_SkyboxShader->SetUniform1i("isHDR", 0);
Renderer::m_SkyboxShader->SetUniform1i("equirectangularMap", 6);
Renderer::m_SkyboxShader->SetUniform1i("skybox", 5);
Renderer::m_SkyboxShader->SetUniform("projection", projection);
Renderer::m_SkyboxShader->SetUniform("view", view);
Renderer::m_SkyboxShader->SetUniform("convulate", 0);
Renderer::m_SkyboxShader->SetUniform("prefilter", 0);
Renderer::m_SkyboxShader->SetUniform("isHDR", 0);
Renderer::m_SkyboxShader->SetUniform("equirectangularMap", 6);
Renderer::m_SkyboxShader->SetUniform("skybox", 5);
// ... set view and projection matrix
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glDepthMask(GL_TRUE);
//Renderer::m_Shader->SetUniform4f("u_AmbientColor", 1.0f, 1.0f, 1.0f, 1.0f);
//Renderer::m_Shader->SetUniform("u_AmbientColor", 1.0f, 1.0f, 1.0f, 1.0f);
}
void SkyboxHDR::Push() {
@@ -112,13 +112,13 @@ namespace Nuake {
glActiveTexture(GL_TEXTURE0 + 3);
glBindTexture(GL_TEXTURE_2D, m_brdLut);
Renderer::m_Shader->SetUniform1i("u_IrradianceMap", 1);
Renderer::m_Shader->SetUniform1i("prefilterMap", 2);
Renderer::m_Shader->SetUniform1i("brdfLUT", 3);
Renderer::m_Shader->SetUniform("u_IrradianceMap", 1);
Renderer::m_Shader->SetUniform("prefilterMap", 2);
Renderer::m_Shader->SetUniform("brdfLUT", 3);
Renderer::m_DeferredShader->SetUniform1i("u_IrradianceMap", 1);
Renderer::m_DeferredShader->SetUniform1i("u_PrefilterMap", 2);
Renderer::m_DeferredShader->SetUniform1i("u_BrdfLUT", 3);
Renderer::m_DeferredShader->SetUniform("u_IrradianceMap", 1);
Renderer::m_DeferredShader->SetUniform("u_PrefilterMap", 2);
Renderer::m_DeferredShader->SetUniform("u_BrdfLUT", 3);
}
void SkyboxHDR::CreateHDRCubemap() {
@@ -160,11 +160,11 @@ namespace Nuake {
m_HDRTexture->Bind(5);
// convert HDR equirectangular environment map to cubemap equivalent
Renderer::m_SkyboxShader->Bind();
Renderer::m_SkyboxShader->SetUniformMat4f("projection", captureProjection);
Renderer::m_SkyboxShader->SetUniform1i("isHDR", 1);
Renderer::m_SkyboxShader->SetUniform1i("prefilter", 0);
Renderer::m_SkyboxShader->SetUniform1i("convulate", 0);
Renderer::m_SkyboxShader->SetUniform1i("equirectangularMap", 5);
Renderer::m_SkyboxShader->SetUniform("projection", captureProjection);
Renderer::m_SkyboxShader->SetUniform("isHDR", 1);
Renderer::m_SkyboxShader->SetUniform("prefilter", 0);
Renderer::m_SkyboxShader->SetUniform("convulate", 0);
Renderer::m_SkyboxShader->SetUniform("equirectangularMap", 5);
glActiveTexture(GL_TEXTURE0);
@@ -172,7 +172,7 @@ namespace Nuake {
glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
for (unsigned int i = 0; i < 6; ++i)
{
Renderer::m_SkyboxShader->SetUniformMat4f("view", captureViews[i]);
Renderer::m_SkyboxShader->SetUniform("view", captureViews[i]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, m_Cubemap, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -224,18 +224,18 @@ namespace Nuake {
glBindTexture(GL_TEXTURE_CUBE_MAP, m_Cubemap);
Renderer::m_SkyboxShader->Bind();
Renderer::m_SkyboxShader->SetUniformMat4f("projection", captureProjection);
Renderer::m_SkyboxShader->SetUniform1i("convulate", 1);
Renderer::m_SkyboxShader->SetUniform1i("prefilter", 0);
Renderer::m_SkyboxShader->SetUniform1i("isHDR", 0);
Renderer::m_SkyboxShader->SetUniform1i("equirectangularMap", 6);
Renderer::m_SkyboxShader->SetUniform1i("skybox", 5);
Renderer::m_SkyboxShader->SetUniform("projection", captureProjection);
Renderer::m_SkyboxShader->SetUniform("convulate", 1);
Renderer::m_SkyboxShader->SetUniform("prefilter", 0);
Renderer::m_SkyboxShader->SetUniform("isHDR", 0);
Renderer::m_SkyboxShader->SetUniform("equirectangularMap", 6);
Renderer::m_SkyboxShader->SetUniform("skybox", 5);
glViewport(0, 0, 32, 32); // don't forget to configure the viewport to the capture dimensions.
glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
for (unsigned int i = 0; i < 6; ++i)
{
Renderer::m_SkyboxShader->SetUniformMat4f("view", captureViews[i]);
Renderer::m_SkyboxShader->SetUniform("view", captureViews[i]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, m_ConvulatedCubemap, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -281,12 +281,12 @@ namespace Nuake {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
Renderer::m_SkyboxShader->Bind();
Renderer::m_SkyboxShader->SetUniformMat4f("projection", captureProjection);
Renderer::m_SkyboxShader->SetUniform1i("convulate", 0);
Renderer::m_SkyboxShader->SetUniform1i("prefilter", 1);
Renderer::m_SkyboxShader->SetUniform1i("isHDR", 0);
Renderer::m_SkyboxShader->SetUniform1i("equirectangularMap", 6);
Renderer::m_SkyboxShader->SetUniform1i("skybox", 5);
Renderer::m_SkyboxShader->SetUniform("projection", captureProjection);
Renderer::m_SkyboxShader->SetUniform("convulate", 0);
Renderer::m_SkyboxShader->SetUniform("prefilter", 1);
Renderer::m_SkyboxShader->SetUniform("isHDR", 0);
Renderer::m_SkyboxShader->SetUniform("equirectangularMap", 6);
Renderer::m_SkyboxShader->SetUniform("skybox", 5);
glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
unsigned int maxMipLevels = 5;
@@ -300,10 +300,10 @@ namespace Nuake {
glViewport(0, 0, mipWidth, mipHeight);
float roughness = (float)mip / (float)(maxMipLevels - 1);
Renderer::m_SkyboxShader->SetUniform1f("roughness", roughness);
Renderer::m_SkyboxShader->SetUniform("roughness", roughness);
for (unsigned int i = 0; i < 6; ++i)
{
Renderer::m_SkyboxShader->SetUniformMat4f("view", captureViews[i]);
Renderer::m_SkyboxShader->SetUniform("view", captureViews[i]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, m_SpecularCubemap, mip);

View File

@@ -0,0 +1,82 @@
#include "DataBindObject.h"
namespace NuakeUI
{
DataBindObject::DataBindObject(const std::string& name, int* value)
: Name(name), Data(value)
{
Type = DataBindType::Int;
}
DataBindObject::DataBindObject(const std::string& name, float* value)
: Name(name), Data(value)
{
Type = DataBindType::Float;
}
DataBindObject::DataBindObject(const std::string& name, bool* value)
: Name(name), Data(value)
{
Type = DataBindType::Bool;
}
DataBindObject::DataBindObject(const std::string& name, std::string* value)
: Name(name), Data(value)
{
Type = DataBindType::String;
}
DataBindObject::DataBindObject(const std::string& name, char* value)
: Name(name), Data(value)
{
Type = DataBindType::Char;
}
void DataBindObject::SetData(int* value)
{
Data = value;
}
void DataBindObject::SetData(bool* value)
{
Data = value;
}
void DataBindObject::SetData(std::string* value)
{
Data = value;
}
void DataBindObject::SetData(float* value)
{
Data = value;
}
void DataBindObject::SetData(char* value)
{
Data = value;
}
std::variant<int*, float*, bool*, std::string*, char*> DataBindObject::GetData()
{
return Data;
}
DataModel::DataModel(const std::string& name)
: Name(name)
{
}
bool DataModel::HasData(const std::string& dataName)
{
for (auto& dataBindObject : DataObjects)
{
if (dataBindObject.Name == dataName)
{
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,191 @@
#pragma once
#include <string>
#include <vector>
#include <memory>
#include <variant>
#include <cassert>
namespace NuakeUI
{
enum class DataBindType
{
Int, Float, Bool, String, Char
};
class DataBindObject
{
private:
DataBindType Type;
public:
std::string Name;
std::variant<int*, float*, bool*, std::string*, char*> Data;
DataBindObject(const std::string& name, int* data);
DataBindObject(const std::string& name, float* data);
DataBindObject(const std::string& name, bool* data);
DataBindObject(const std::string& name, std::string* data);
DataBindObject(const std::string& name, char* data);
void SetData(int* value);
void SetData(float* value);
void SetData(bool* value);
void SetData(std::string* value);
void SetData(char* value);
DataBindType GetType() const { return Type; }
std::variant<int*, float*, bool*, std::string*, char*> GetData();
};
class DataModel;
typedef std::shared_ptr<DataModel> DataModelPtr;
class DataModel
{
public:
std::vector<DataBindObject> DataObjects;
std::string Name;
static DataModelPtr New(const std::string& name)
{
return std::make_shared<DataModel>(name);
}
DataModel(const std::string& modelName);
~DataModel() = default;
void Bind(const std::string& dataName, int* data)
{
DataBindObject dataBindObject = DataBindObject(dataName, data);
DataObjects.push_back(dataBindObject);
}
void Bind(const std::string& dataName, float* data)
{
DataBindObject dataBindObject = DataBindObject(dataName, data);
DataObjects.push_back(dataBindObject);
}
void Bind(const std::string& dataName, bool* data)
{
DataBindObject dataBindObject = DataBindObject(dataName, data);
DataObjects.push_back(dataBindObject);
}
void Bind(const std::string& dataName, std::string* data)
{
DataBindObject dataBindObject = DataBindObject(dataName, data);
DataObjects.push_back(dataBindObject);
}
void Bind(const std::string& dataName, char* data)
{
DataBindObject dataBindObject = DataBindObject(dataName, data);
DataObjects.push_back(dataBindObject);
}
bool HasData(const std::string& dataName);
DataBindType GetDataType(const std::string dataName)
{
assert(HasData(dataName) && "Model has no data with that name");
for (auto& dataObject : DataObjects)
{
if (dataObject.Name == dataName)
{
return dataObject.GetType();
}
}
}
template<typename T>
T& GetData(const std::string& dataName)
{
assert(false && "Unsupported data type");
}
template<>
bool& GetData(const std::string& dataName)
{
assert(HasData(dataName) && "Model has no data with that name.");
for (auto& dataBindObject : DataObjects)
{
if (dataBindObject.Name == dataName)
{
return *std::get<bool*>(dataBindObject.GetData());
}
}
assert(false);
}
template<>
int& GetData(const std::string& dataName)
{
assert(HasData(dataName) && "Model has no data with that name.");
for (auto& dataBindObject : DataObjects)
{
if (dataBindObject.Name == dataName)
{
auto variant = dataBindObject.GetData();
int* data = std::get<int*>(variant);
return *data;
}
}
}
template<>
float& GetData(const std::string& dataName)
{
assert(HasData(dataName) && "Model has no data with that name.");
for (auto& dataBindObject : DataObjects)
{
if (dataBindObject.Name == dataName)
{
auto variant = dataBindObject.GetData();
float* data = std::get<float*>(variant);
return *data;
}
}
}
template<>
std::string& GetData(const std::string& dataName)
{
assert(HasData(dataName) && "Model has no data with that name.");
for (auto& dataBindObject : DataObjects)
{
if (dataBindObject.Name == dataName)
{
auto variant = dataBindObject.GetData();
std::string* data = std::get<std::string*>(variant);
return *data;
}
}
}
template<>
char& GetData(const std::string& dataName)
{
assert(HasData(dataName) && "Model has no data with that name.");
for (auto& dataBindObject : DataObjects)
{
if (dataBindObject.Name == dataName)
{
auto variant = dataBindObject.GetData();
char* data = std::get<char*>(variant);
return *data;
}
}
}
};
}

View File

@@ -0,0 +1,10 @@
#pragma once
namespace NuakeUI
{
enum class DataBindOperationType
{
If,
};
}

View File

@@ -0,0 +1,50 @@
#include "DataModelOperations.h"
#include <iostream>
namespace NuakeUI
{
DataModelOperation::DataModelOperation(const std::string& name, OperationType type, ComparaisonType compType)
{
Name = name;
Type = type;
CompType = compType;
}
DataModelOperationPtr DataModelOperation::New(const std::string& name, OperationType type, ComparaisonType compType)
{
return std::make_shared<DataModelOperation>(name, type, compType);
}
bool DataModelOperation::Compare(DataModelPtr object)
{
if (!object || !object->HasData(Name))
{
std::cout << "DataModel has no data named " << Name << std::endl;
return false;
}
DataBindType dataType = object->GetDataType(Name);
auto dataRight = Right;
switch (dataType)
{
case DataBindType::Bool:
return CompareLeftAndRight<bool>(object->GetData<bool>(Name), std::get<bool>(Right), CompType);
break;
case DataBindType::Int:
return CompareLeftAndRight<int>(object->GetData<int>(Name), std::get<int>(Right), CompType);
break;
case DataBindType::Float:
return CompareLeftAndRight<float>(object->GetData<float>(Name), std::get<float>(Right), CompType);
break;
case DataBindType::String:
return CompareLeftAndRight<std::string>(object->GetData<std::string>(Name), std::get<std::string>(Right), CompType);
break;
case DataBindType::Char:
return CompareLeftAndRight<char>(object->GetData<char>(Name), std::get<char>(Right), CompType);
break;
}
return false;
}
}

View File

@@ -0,0 +1,75 @@
#pragma once
#include "DataBindObject.h"
#include <string>
#include <variant>
namespace NuakeUI
{
enum class OperationType
{
If, IfClass
};
enum class ComparaisonType
{
Equal,
NotEqual,
GreaterOrEqual,
LessOrEqual,
Greater,
Less,
None
};
class DataModelOperation;
typedef std::shared_ptr<DataModelOperation> DataModelOperationPtr;
typedef std::vector<DataModelOperationPtr> DataModelOperationCollection;
class DataModelOperation
{
public:
std::string Name;
std::string ClassName;
OperationType Type;
ComparaisonType CompType;
std::variant<int, float, bool, std::string, char> Right;
static DataModelOperationPtr New(const std::string& name, OperationType type, ComparaisonType compType);
DataModelOperation(const std::string& name, OperationType type, ComparaisonType compType);
~DataModelOperation() = default;
template<typename T>
bool CompareLeftAndRight(const T& left, const T& right, const ComparaisonType& compType)
{
if (CompType == ComparaisonType::Equal)
{
return left == right;
}
else if (CompType == ComparaisonType::NotEqual)
{
return left != right;
}
else if (CompType == ComparaisonType::GreaterOrEqual)
{
return left >= right;
}
else if (CompType == ComparaisonType::LessOrEqual)
{
return left <= right;
}
else if (CompType == ComparaisonType::Greater)
{
return left > right;
}
else if (CompType == ComparaisonType::Less)
{
return left < right;
}
}
bool Compare(DataModelPtr object);
};
}

View File

@@ -0,0 +1,34 @@
#include "FileSystem.h"
#include <fstream>
#include <filesystem>
namespace NuakeUI
{
namespace FileSystem
{
bool FileExists(const std::string& path)
{
return std::filesystem::exists(path);
}
std::string ReadFile(const std::string& path)
{
if (!FileExists(path))
return "";
std::string fileContent;
std::string currentLine;
std::ifstream file(path);
while (getline(file, currentLine))
{
fileContent += currentLine + "\n";
}
file.close();
return fileContent;
}
}
}

11
Nuake/src/UI/FileSystem.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
#include <string>
namespace NuakeUI
{
namespace FileSystem
{
bool FileExists(const std::string& path);
std::string ReadFile(const std::string& path);
};
}

View File

@@ -0,0 +1,35 @@
#include "Font.h"
#include "../FileSystem.h"
namespace NuakeUI
{
std::shared_ptr<Font> Font::New(const std::string& path)
{
return std::make_shared<Font>(path);
}
Font::Font(const std::string& path)
{
mFreeTypeHandle = msdfgen::initializeFreetype();
Load(path);
}
Font::~Font()
{
msdfgen::destroyFont(mFontHandle);
}
bool Font::Load(const std::string& path)
{
bool exists = FileSystem::FileExists(path);
mFontHandle = msdfgen::loadFont(mFreeTypeHandle, path.c_str());
if (!mFontHandle)
return false;
msdfgen::FontMetrics metrics;
msdfgen::getFontMetrics(metrics, mFontHandle);
LineHeight = (float)metrics.lineHeight;
return true;
}
}

93
Nuake/src/UI/Font/Font.h Normal file
View File

@@ -0,0 +1,93 @@
#pragma once
#include <src/Core/Maths.h>
#include <msdf-atlas-gen/msdf-atlas-gen.h>
#include <msdfgen/ext/import-font.h>
#include <src/Rendering/Textures/Texture.h>
#include <string>
#include <memory>
using namespace Nuake;
namespace NuakeUI
{
struct CharPos
{
double left;
double right;
double top;
double bottom;
};
struct CharUV
{
Vector2 Pos;
Vector2 Size;
};
class Char
{
private:
unsigned int m_VBO;
unsigned int m_VAO;
public:
unsigned int Unicode;
float Advance;
CharPos PlaneBounds;
CharUV AtlasBounds;
Char() {};
Char(const unsigned int unicode, float advance, CharPos plane, CharUV atlas)
{
Unicode = unicode;
Advance = advance;
PlaneBounds = plane;
AtlasBounds = atlas;
}
CharUV GetAtlasUV(const Vector2& atlasSize)
{
return AtlasBounds;
}
};
class Font
{
public:
Font(const std::string& path);
Font() = default;
~Font();
float LineHeight = 0.f;
static std::shared_ptr<Font> New(const std::string& path);
msdfgen::FontHandle* GetFontHandle() const { return mFontHandle; }
void AddChar(const unsigned int unicode, float advance, CharPos plane, CharUV atlas)
{
this->Chars[unicode] = Char(unicode, advance, plane, atlas);
}
Char GetChar(unsigned int unicode)
{
if (Chars.find(unicode) != Chars.end())
return Chars[unicode];
return Char();
}
std::shared_ptr<Texture> mAtlas;
private:
std::string mFilePath;
msdfgen::FontHandle* mFontHandle;
msdfgen::FreetypeHandle* mFreeTypeHandle;
std::map<unsigned int, Char> Chars;
bool Load(const std::string& path);
};
}

View File

@@ -0,0 +1,171 @@
#pragma once
#include "Font.h"
#include <memory>
#include <string>
#include <src/Rendering/Textures/Texture.h>
#include <Dependencies/msdf-atlas-gen/msdfgen/core/BitmapRef.hpp>
typedef unsigned char byte;
namespace NuakeUI
{
// Config used by the atlas generator.
struct Config
{
msdf_atlas::ImageType imageType;
msdf_atlas::ImageFormat imageFormat;
msdf_atlas::YDirection yDirection;
int width, height;
double emSize;
double pxRange;
double angleThreshold;
double miterLimit;
void (*edgeColoring)(msdfgen::Shape&, double, unsigned long long);
bool expensiveColoring;
unsigned long long coloringSeed;
msdf_atlas::GeneratorAttributes generatorAttributes;
bool preprocessGeometry;
bool kerning;
int threadCount = 1;
};
class FontLoader
{
public:
static FontLoader& Get()
{
static FontLoader fontloader;
return fontloader;
}
template <typename T, typename S, int N, msdf_atlas::GeneratorFunction<S, N> GEN_FN>
static bool makeAtlas(const std::vector<msdf_atlas::GlyphGeometry>& glyphs,
const std::vector<msdf_atlas::FontGeometry>& fonts,
Config& config, std::shared_ptr<Font> font) {
// Create generator
msdf_atlas::ImmediateAtlasGenerator<S, N, GEN_FN, msdf_atlas::BitmapAtlasStorage<T, N> > generator(config.width, config.height);
// Setup generator settings
generator.setAttributes(config.generatorAttributes);
generator.setThreadCount(config.threadCount);
generator.generate(glyphs.data(), (int)glyphs.size());
// Create bitmap
msdfgen::BitmapConstRef<T, N> bitmap = (msdfgen::BitmapConstRef<T, N>) generator.atlasStorage();
// Creat1e Texture from bitmap
//msdf_atlas::exportJSON(fonts.data(), fonts.size(), config.emSize, config.pxRange, config.width, config.height, config.imageType, config.yDirection, "yayayayya.json", config.kerning);
font->mAtlas = std::make_shared<Texture>(Vector2(config.width, config.height), (void*)bitmap.pixels);
// Create Char structure
return true;
}
std::shared_ptr<Font> LoadFont(const std::string& path)
{
auto font = Font::New(path);
// Create atlas settings
Config config{};
config.pxRange = 3;
config.emSize = 0.0;
config.coloringSeed = 125155;
config.imageType = msdf_atlas::ImageType::MTSDF;
config.imageFormat = msdf_atlas::ImageFormat::UNSPECIFIED;
config.yDirection = msdf_atlas::YDirection::BOTTOM_UP;
config.edgeColoring = msdfgen::edgeColoringInkTrap;
config.kerning = true;
config.preprocessGeometry = false;
config.angleThreshold = 3.0;
config.miterLimit = 1.0;
config.generatorAttributes.scanlinePass = true;
config.generatorAttributes.config.overlapSupport = true;
// Load charset ASCII
std::vector<msdf_atlas::GlyphGeometry> glyphs;
std::vector<msdf_atlas::FontGeometry> fonts;
msdf_atlas::FontGeometry fontGeometry(&glyphs);
msdf_atlas::Charset charset = msdf_atlas::Charset::ASCII;
// Load Create charset
float fontScale = 36;
bool preprocess = false;
int loaded = fontGeometry.loadCharset(font->GetFontHandle(), fontScale, charset, config.preprocessGeometry, config.kerning);
fonts.push_back(fontGeometry);
if (glyphs.empty())
{
printf("Critical, Could not load font! \n");
}
// Create atlas params
msdf_atlas::TightAtlasPacker::DimensionsConstraint atlasSizeConstraint = msdf_atlas::TightAtlasPacker::DimensionsConstraint::MULTIPLE_OF_FOUR_SQUARE;
msdf_atlas::TightAtlasPacker atlasPacker;
atlasPacker.setDimensionsConstraint(atlasSizeConstraint);
msdf_atlas::ImageType imageType = msdf_atlas::ImageType::MTSDF;
atlasPacker.setPadding(imageType == msdf_atlas::ImageType::MSDF || imageType == msdf_atlas::ImageType::MTSDF ? 0 : -1);
atlasPacker.setPixelRange(config.pxRange);
atlasPacker.setUnitRange(config.emSize);
atlasPacker.setMiterLimit(config.miterLimit);
// Pack atlas
if (int remaining = atlasPacker.pack(glyphs.data(), (int)glyphs.size())) {
if (remaining < 0) {
printf("Critial - Failed to pack atlas");
}
else {
printf("Error: Could not fit %d out of %d glyphs into the atlas.\n", remaining, (int)glyphs.size());
}
}
// update atlast size
atlasPacker.getDimensions(config.width, config.height);
if (!(config.width > 0 && config.height > 0))
printf("Unable to determine atlas size.");
config.emSize = atlasPacker.getScale();
config.pxRange = atlasPacker.getPixelRange();
// Color the glyph
//unsigned long long glyphSeed = config.coloringSeed;
//for (msdf_atlas::GlyphGeometry& glyph : glyphs) {
// glyphSeed *= 6364136223846793005ull;
// glyph.edgeColoring(config.edgeColoring, config.angleThreshold, glyphSeed);
//}
msdf_atlas::Workload([&glyphs, &config](int i, int threadNo) -> bool {
unsigned long long glyphSeed = (6364136223846793005ull * (config.coloringSeed ^ i) + 1442695040888963407ull) * !!config.coloringSeed;
glyphs[i].edgeColoring(config.edgeColoring, config.angleThreshold, glyphSeed);
return true;
}, (int)glyphs.size()).finish(config.threadCount);
// Create bitmap and char structure
auto bitmap = makeAtlas<byte, float, 4, msdf_atlas::mtsdfGenerator>(glyphs, fonts, config, font);
for (auto& g : glyphs)
{
CharPos plane = {};
g.getQuadPlaneBounds(plane.left, plane.bottom, plane.right, plane.top);
CharUV box = {};
double x2, y2, z2, w2;
g.getQuadAtlasBounds(x2, y2, z2, w2);
box.Pos.x = (float)x2;
box.Pos.y = (float)y2;
box.Size.x = (float)z2;
box.Size.y = (float)w2;
font->AddChar(g.getCodepoint(), (float)g.getAdvance(), plane, box);
}
return font;
}
};
}

View File

@@ -0,0 +1,18 @@
#include "FontManager.h"
#include "FontLoader.h"
namespace NuakeUI
{
std::shared_ptr<Font> FontManager::GetFont(const std::string& font)
{
if (mFonts.find(font) == mFonts.end())
{
mFonts[font] = FontLoader::Get().LoadFont(font);
return mFonts[font];
}
else
{
return mFonts[font];
}
}
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include "Font.h"
#include <string>
#include <map>
#include <memory>
namespace NuakeUI
{
class FontManager
{
private:
std::map<std::string, std::shared_ptr<Font>> mFonts;
public:
static FontManager& Get() {
static FontManager fontManager;
return fontManager;
}
FontManager() {
mFonts = std::map<std::string, std::shared_ptr<Font>>();
}
std::shared_ptr<Font> GetFont(const std::string& font);
};
}

View File

@@ -0,0 +1,11 @@
#pragma once
namespace NuakeUI
{
class IController
{
public:
virtual void OnRegister() = 0;
virtual void OnUnregister() = 0;
};
}

View File

@@ -0,0 +1,8 @@
#include "InputManager.h"
namespace NuakeUI
{
float InputManager::ScrollX = 0.f;
float InputManager::ScrollY = 0.f;
std::stack<std::string> InputManager::InputStack = std::stack<std::string>();
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include <stack>
#include <string>
namespace NuakeUI
{
class InputManager
{
public:
static std::stack<std::string> InputStack;
static float ScrollX;
static float ScrollY;
virtual bool IsMouseInputDown() = 0;
virtual float GetMouseX() = 0;
virtual float GetMouseY() = 0;
virtual float GetScrollX() = 0;
virtual float GetScrollY() = 0;
virtual bool IsKeyPressed(uint32_t key) = 0;
static std::string ConsumeStack()
{
std::string item = InputStack.top();
InputStack.pop();
return item;
}
};
}

224
Nuake/src/UI/Inspector.h Normal file
View File

@@ -0,0 +1,224 @@
#pragma once
#include "Nodes/Canvas.h"
#include "Nodes/Text.h"
#include "Styles/StyleSheet.h"
#include <memory>
#include <Dependencies/NuakeRenderer/NuakeRenderer/NuakeRenderer.h>
namespace NuakeUI
{
std::shared_ptr<Node> mSelectedNode;
void DrawUI(std::shared_ptr<Node> node)
{
ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_FramePadding |
ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
// Highlight the selected node using a flag.
if (mSelectedNode == node)
base_flags |= ImGuiTreeNodeFlags_Selected;
// Appends the classes of the node next to the name
// Logic is only add [] if theres is a class and only add commans in between.
std::string nodeTitle = node->GetID();
nodeTitle = nodeTitle == "" ? node->GetType() : nodeTitle;
const int classAmount = node->Classes.size();
if (classAmount > 0)
{
nodeTitle += "[";
for (int i = 0; i < classAmount; i++)
{
nodeTitle += node->Classes[i];
if (i < classAmount - 1)
nodeTitle += ", ";
}
nodeTitle += "]";
}
const bool nodeOpen = ImGui::TreeNodeEx(nodeTitle.c_str(), base_flags);
// Select the if clicked
if (ImGui::IsItemClicked())
{
mSelectedNode = node;
}
// Draw the rest of th nodes recursively.
if (nodeOpen)
{
for (auto& c : node->GetChildrens())
DrawUI(c);
ImGui::TreePop();
}
}
static void DrawNodeEditor()
{
if (!mSelectedNode)
{
ImGui::Text("No node selected.");
return;
}
auto type = mSelectedNode->GetType();
ImGui::SliderFloat("Width", &mSelectedNode->ComputedStyle.Width.value, 0.f, 1920.0f);
ImGui::SliderFloat("Height", &mSelectedNode->ComputedStyle.Height.value, 0.0f, 1080.0f);
ImGui::SliderFloat("Max Width", &mSelectedNode->ComputedStyle.MaxWidth.value, 0.f, 1920.0f);
ImGui::SliderFloat("Max Height", &mSelectedNode->ComputedStyle.MaxHeight.value, 0.0f, 1080.0f);
ImGui::SliderFloat("Min Width", &mSelectedNode->ComputedStyle.MinWidth.value, 0.f, 1920.0f);
ImGui::SliderFloat("Min Height", &mSelectedNode->ComputedStyle.MinHeight.value, 0.0f, 1080.0f);
ImGui::SliderFloat("Padding Left", &mSelectedNode->ComputedStyle.PaddingLeft.value, 0.f, 1920.0f);
ImGui::SliderFloat("Padding Right", &mSelectedNode->ComputedStyle.PaddingRight.value, 0.0f, 1080.0f);
ImGui::SliderFloat("Padding Top", &mSelectedNode->ComputedStyle.PaddingTop.value, 0.f, 1920.0f);
ImGui::SliderFloat("Padding Bottom", &mSelectedNode->ComputedStyle.PaddingBottom.value, 0.0f, 1080.0f);
ImGui::SliderFloat("Margin Left", &mSelectedNode->ComputedStyle.MarginLeft.value, 0.f, 1920.0f);
ImGui::SliderFloat("Margin Right", &mSelectedNode->ComputedStyle.MarginRight.value, 0.0f, 1080.0f);
ImGui::SliderFloat("Margin Top", &mSelectedNode->ComputedStyle.MarginTop.value, 0.f, 1920.0f);
ImGui::SliderFloat("Margin Bottom", &mSelectedNode->ComputedStyle.MarginBottom.value, 0.0f, 1080.0f);
ImGui::SliderFloat("Flex Basis", &mSelectedNode->ComputedStyle.FlexBasis, 0.f, 1920.0f);
ImGui::SliderFloat("Flex Grow", &mSelectedNode->ComputedStyle.FlexGrow, 0.0f, 1080.0f);
ImGui::SliderFloat("Flex Shrink", &mSelectedNode->ComputedStyle.FlexShrink, 0.f, 1920.0f);
ImGui::SliderFloat("Font Size", &mSelectedNode->ComputedStyle.FontSize, 0.0f, 1080.0f);
ImGui::ColorEdit4("Background Color", (float*) &mSelectedNode->ComputedStyle.BackgroundColor);
ImGui::DragFloat("Border Size", &mSelectedNode->ComputedStyle.BorderSize, 1.f, 0.f);
ImGui::ColorEdit4("Border Color", (float*)&mSelectedNode->ComputedStyle.BorderColor);
ImGui::DragFloat("Font Size", &mSelectedNode->ComputedStyle.FontSize, 1.f, 0.f);
ImGui::ColorEdit4("Font Color", (float*)&mSelectedNode->ComputedStyle.FontColor);
}
static void DrawInspector(std::shared_ptr<Canvas> canvas)
{
NuakeRenderer::BeginImGuiFrame();
ImGui::ShowDemoWindow();
if (ImGui::Begin("Inspector"))
{
if (ImGui::BeginTabBar("MyTabBar"))
{
if (ImGui::BeginTabItem("Tree"))
{
const float treeWidth = ImGui::GetWindowContentRegionWidth();
const float availHeight = ImGui::GetContentRegionAvail().y;
const ImVec2 size = ImVec2(treeWidth * 0.5f, availHeight);
const ImVec2 size2 = ImVec2(treeWidth * 0.5f, availHeight);
if (ImGui::BeginChild("Tree", size))
{
DrawUI(canvas->GetRoot());
}
ImGui::EndChild();
ImGui::SameLine();
if (ImGui::BeginChild("Editor", size2))
{
DrawNodeEditor();
}
ImGui::EndChild();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("StyleSheet"))
{
if (ImGui::BeginChild("StyleSheetEditor", ImGui::GetContentRegionAvail()))
{
auto styleSheet = canvas->GetStyleSheet();
int ri = 0;
for (auto& r : styleSheet->Rules)
{
std::string imguiText = "";
for (int s = 0; s < r.Selector.size(); s++)
{
std::string selectorText = "";
auto& selector = r.Selector[s];
auto type = selector.Type;
if (type == StyleSelectorType::Id)
selectorText += "#";
else if (type == StyleSelectorType::Class)
selectorText += ".";
selectorText += selector.Value.c_str();
if (s < r.Selector.size() - 1)
selectorText += ", ";
imguiText += selectorText;
}
imguiText += " { ";
ImGui::Text(imguiText.c_str());
ImGui::Indent(8.f);
// Now the properties!
int i = 0;
for (auto& rule : r.Properties)
{
// Name
std::string propName = "UnknownProperty";
StyleProperties type = rule.first;
if (type == StyleProperties::Width) propName = "width: ";
else if (type == StyleProperties::Height) propName = "weight: ";
else if (type == StyleProperties::MinWidth) propName = "min-width: ";
else if (type == StyleProperties::MinHeight) propName = "min-height: ";
else if (type == StyleProperties::MaxWidth) propName = "max-width: ";
else if (type == StyleProperties::MaxHeight) propName = "max-height: ";
else if (type == StyleProperties::BackgroundColor) propName = "BackgroundColor: ";
ImGui::Text(propName.c_str());
ImGui::SameLine();
std::string valueText = "";
// value
PropValue& value = rule.second;
if (value.type == PropValueType::Percent)
{
valueText += std::to_string(value.value.Number);
valueText += "\%;";
}
else if (value.type == PropValueType::Pixel)
{
valueText += std::to_string(value.value.Number);
valueText += "px;";
}
else if (value.type == PropValueType::Color)
{
Color colorFloat = rule.second.value.Color / 255.f;
ImGui::ColorEdit4(("##colorEdit" + std::to_string(ri) + propName + std::to_string(i)).c_str(), &colorFloat.r);
rule.second.value.Color = colorFloat * 255.f;
}
else if (value.type == PropValueType::Auto)
{
valueText += "auto;";
}
i++;
ImGui::Text(valueText.c_str());
}
ImGui::Indent(-8.f);
ImGui::Text("}");
ri++;
}
}
ImGui::EndChild();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
}
ImGui::End();
NuakeRenderer::EndImGuiFrame();
}
}

View File

@@ -0,0 +1,49 @@
#include "Button.h"
#include "Text.h"
namespace NuakeUI
{
std::shared_ptr<Button> Button::New(const std::string& name, const std::string& label)
{
return std::make_shared<Button>(name, label);
}
Button::Button(const std::string& name, const std::string& label) :
Label(label)
{
ID = name;
//InsertChild(Text::New(ID + "lbl", Label));
}
void Button::UpdateInput(InputManager* inputManager)
{
float mx = inputManager->GetMouseX();
float my = inputManager->GetMouseY();
bool isHover = IsMouseHover(mx, my);
if (isHover)
{
bool isMouseDown = inputManager->IsMouseInputDown();
if (isMouseDown)
{
State = NodeState::Pressed;
}
else
{
if (State == NodeState::Pressed && !isMouseDown)
{
// Calling the click callback.
if (mHasCallback)
ClickCallback(*this);
}
State = NodeState::Hover;
}
}
else
{
State = NodeState::Idle;
}
for (auto& c : Childrens)
c->UpdateInput(inputManager);
}
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include "Node.h"
#include "../InputManager.h"
#include <string>
namespace NuakeUI
{
class Button;
typedef std::shared_ptr<Button> ButtonPtr;
class Button : public Node
{
private:
bool mHasBeenClicked = false;
bool mHasCallback = false;
public:
std::string Label = "";
Button(const std::string& name, const std::string& label);
~Button() {};
static ButtonPtr New(const std::string& name, const std::string& label);
std::function<void(Button&)> ClickCallback;
void UpdateInput(InputManager* inputManager) override;
void SetClickCallback(std::function<void(Button&)> callback)
{
mHasCallback = true;
ClickCallback = callback;
}
};
}

View File

@@ -0,0 +1,169 @@
#include "Canvas.h"
#include <yoga/Yoga.h>
#include <yoga/YGConfig.h>
#include "../Renderer.h"
#include "Node.h"
namespace NuakeUI
{
CanvasPtr Canvas::New()
{
return std::make_shared<Canvas>();
}
Canvas::Canvas() : mInputManager(nullptr), mDirty(false)
{
mYogaConfig = YGConfigNew();
}
Canvas::~Canvas()
{
YGConfigFree(mYogaConfig);
if (mRootNode)
{
YGNodeFreeRecursive(mRootNode->GetYogaNode());
}
}
void Canvas::Tick()
{
if (!mRootNode)
return;
mRootNode->UpdateInput(mInputManager);
mRootNode->Tick(mInputManager);
mInputManager->ScrollX = 0.f;
mInputManager->ScrollY = 0.f;
}
void Canvas::Draw()
{
if (!mRootNode)
return;
Renderer::Get().BeginDraw();
Renderer::Get().DrawNode(mRootNode, 0);
mRootNode->Draw(0);
}
void Canvas::ComputeLayout(Vector2 size)
{
if (!mRootNode)
return;
Renderer::Get().SetViewportSize(size);
float x, y;
x = mInputManager->GetMouseX();
y = mInputManager->GetMouseY();
auto root = mRootNode->GetYogaNode();
// Recompute the node tree.
if (mDirty)
ComputeStyle(mRootNode);
mRootNode->Calculate();
if (root)
YGNodeCalculateLayout(root, size.x, size.y, YGDirectionLTR);
}
void Canvas::ComputeStyle(NodePtr node)
{
for (auto& s : node->GetDataModelOperations())
{
if (s->Type != OperationType::IfClass)
continue;
if (auto dataModel = node->GetDataModel(); s->Compare(dataModel))
{
node->AddClass(s->ClassName);
}
else
{
node->RemoveClass(s->ClassName);
}
}
for (auto& rule : mStyleSheet->Rules)
{
bool respectSelector = true;
for (StyleSelector& selector : rule.Selector)
{
bool foundSelector = false;
if (selector.Type == StyleSelectorType::Class)
{
for (auto& c : node->Classes)
{
if (c == selector.Value)
foundSelector = true;
}
}
else if (selector.Type == StyleSelectorType::Pseudo)
{
if (selector.Value == "hover" && node->State == NodeState::Hover)
foundSelector = true;
if (selector.Value == "active" && node->State == NodeState::Pressed)
foundSelector = true;
}
else if (selector.Type == StyleSelectorType::Id)
{
if (node->GetID() == selector.Value)
foundSelector = true;
}
else if (selector.Type == StyleSelectorType::Tag)
{
if (selector.Value == node->GetType())
{
foundSelector = true;
}
}
if (!foundSelector)
respectSelector = false;
}
if (respectSelector)
node->ApplyStyleProperties(rule.Properties);
}
for (auto& c : node->GetChildrens())
{
ComputeStyle(c);
}
}
// Getters & Setters
NodePtr Canvas::GetRoot() const
{
return mRootNode;
}
void Canvas::SetRoot(NodePtr root)
{
mRootNode = root;
}
void Canvas::SetInputManager(InputManager* inputManager)
{
mInputManager = inputManager;
}
StyleSheetPtr Canvas::GetStyleSheet() const
{
return mStyleSheet;
}
void Canvas::SetStyleSheet(StyleSheetPtr styleSheet)
{
mDirty = true;
mStyleSheet = styleSheet;
}
}

View File

@@ -0,0 +1,55 @@
#pragma once
#include "Node.h"
#include "../InputManager.h"
#include "../Styles/StyleSheet.h"
#include <src/Core/Maths.h>
#include "yoga/YGConfig.h"
#include <memory>
namespace NuakeUI
{
class Canvas;
typedef std::shared_ptr<Canvas> CanvasPtr;
class Canvas
{
private:
YGConfigRef mYogaConfig;
std::string mFilePath = "";
InputManager* mInputManager;
StyleSheetPtr mStyleSheet;
NodePtr mRootNode;
bool mDirty;
public:
static CanvasPtr New();
Canvas();
~Canvas();
void Tick();
void Draw();
void ComputeLayout(Vector2 size);
void ComputeStyle(NodePtr node);
NodePtr GetRoot() const;
void SetRoot(NodePtr root);
void SetInputManager(InputManager* manager);
StyleSheetPtr GetStyleSheet() const;
void SetStyleSheet(StyleSheetPtr stylesheet);
template<class T>
bool FindNodeByID(const std::string& id, std::shared_ptr<T>& node)
{
if (!this->mRootNode->FindChildByID<T>(id, node))
return false;
return true;
}
};
}

599
Nuake/src/UI/Nodes/Node.cpp Normal file
View File

@@ -0,0 +1,599 @@
#include "Node.h"
#include "../Renderer.h"
#include "NodeState.h"
#include "../StringHelper.h"
#include <nanosvg.h>
#include <nanosvgrast.h>
namespace NuakeUI
{
NodePtr Node::New(const std::string id, const std::string& value)
{
return std::make_shared<Node>(id, value);
}
Node::Node(const std::string& id, const std::string& value) : ID(id)
{
InitializeNode();
YGNodeStyleSetFlexDirection(mNode, YGFlexDirection::YGFlexDirectionColumn);
}
std::string Node::GetID() const
{
return ID;
}
uint32_t Node::GetIndex() const
{
if (!Parent)
{
return -1;
}
uint32_t i = 0;
for (auto& c : Parent->GetChildrens())
{
if (c->mNode == mNode)
{
return i;
}
i++;
}
return -1;
}
YGNodeRef Node::GetYogaNode() const
{
return mNode;
}
std::string Node::GetType() const
{
return Type;
}
void Node::InitializeNode()
{
if (mHasBeenInitialized)
return;
mNode = YGNodeNew();
Childrens = std::vector<NodePtr>();
mHasBeenInitialized = true;
}
bool Node::HasBeenInitialized() const
{
return mHasBeenInitialized;
}
bool Node::HasDataModel() const
{
return mDataModel != nullptr;
}
DataModelPtr Node::GetDataModel() const
{
if (HasDataModel())
{
return mDataModel;
}
// Ask parent if they have a data model
if (Parent != nullptr)
{
return Parent->GetDataModel();
}
return nullptr;
}
void Node::SetDataModel(const DataModelPtr& dataModel)
{
mDataModel = dataModel;
}
float Node::GetScroll() const
{
return ScrollDelta;
}
DataModelOperationCollection& Node::GetDataModelOperations()
{
return mDataModelOperations;
}
void Node::AddDataModelOperation(DataModelOperationPtr& operation)
{
mDataModelOperations.push_back(operation);
}
void Node::Tick(InputManager* inputManager)
{
OnTick(inputManager);
for (auto& c : Childrens)
{
c->Tick(inputManager);
}
}
void Node::UpdateInput(InputManager* inputManager)
{
inputManager = inputManager;
float mx = inputManager->GetMouseX();
float my = inputManager->GetMouseY();
bool isHover = IsMouseHover(mx, my);
bool isMouseDown = inputManager->IsMouseInputDown();
if (State == NodeState::Clicked && !isMouseDown)
{
State = NodeState::Hover;
OnClickReleased(inputManager);
}
if (!isMouseDown)
{
if (!isHover)
{
if (State != NodeState::Idle)
{
OnMouseExit(inputManager);
}
State = NodeState::Idle;
}
else
{
if (State != NodeState::Hover)
{
OnMouseHover(inputManager);
}
State = NodeState::Hover;
}
}
// Grab focus
if (isHover && isMouseDown && State != NodeState::Clicked)
{
OnClick(inputManager);
State = NodeState::Clicked;
if (CanGrabFocus)
{
GrabFocus();
}
}
// Release focus
if (!isHover && isMouseDown && State != NodeState::Clicked)
{
if (HasFocus())
{
ReleaseFocus();
}
}
// Calculate total absolute height of all the childrens
float totalHeight = 0.0f;
for (const auto& c : Childrens)
{
float childrenBottom = c->ComputedPosition.y + ScrollDelta + c->ComputedSize.y;
if (childrenBottom > totalHeight)
{
totalHeight = childrenBottom;
}
}
// Calculate Max Scroll delta
float maxScrollDelta = 0.f;
if (totalHeight > ComputedSize.y)
{
maxScrollDelta = -(ComputedSize.y - totalHeight);
}
// Scroll the parent and keep the remainder.
float scroll = inputManager->GetScrollY();
bool isScrolled = std::abs(scroll) > 0.0f;
bool canScroll = ComputedStyle.Overflow == OverflowType::Scroll;
if (isScrolled && canScroll && isHover)
{
// Call node event
OnScroll(inputManager);
const float SCROLL_FORCE = 40.f;
const float scrollAmount = scroll * -SCROLL_FORCE;
const float newDelta = ScrollDelta + scrollAmount;
// This is what remains of the scrolling if we hit the limits to resolve to parent.
float remainder = 0.0f;
if (scrollAmount > .0f)
{
if (ScrollDelta < maxScrollDelta && newDelta >= maxScrollDelta)
{
remainder = newDelta + maxScrollDelta;
inputManager->ScrollY += scroll;
ScrollDelta = maxScrollDelta;
}
else if (newDelta <= maxScrollDelta)
{
ScrollDelta = newDelta;
inputManager->ScrollY += scroll;
}
}
else if(scrollAmount < .0f)
{
if(ScrollDelta > 0.f && newDelta <= 0.f)
{
remainder = newDelta + maxScrollDelta;
inputManager->ScrollY += scroll;
ScrollDelta = 0.f;
}
else if (newDelta >= 0.f)
{
ScrollDelta = newDelta;
inputManager->ScrollY += scroll;
}
}
}
if (ScrollDelta > maxScrollDelta)
{
ScrollDelta = maxScrollDelta;
}
for (auto& c : Childrens)
{
c->UpdateInput(inputManager);
}
}
void Node::Draw(int z)
{
z++;
ComputedZIndex = ComputedStyle.ZIndex + z;
if (ComputedStyle.Visibility == VisibilityType::Hidden)
{
return;
}
for (const NodePtr& c : Childrens)
{
bool failedOperation = false;
for (const auto& modelOp : c->GetDataModelOperations())
{
if (modelOp->Type == OperationType::If)
{
const DataModelPtr& model = c->GetDataModel();
if (model && !modelOp->Compare(model))
{
failedOperation = true;
}
}
}
bool isHidden = c->ComputedStyle.Visibility == VisibilityType::Hidden;
if (isHidden || failedOperation)
{
continue;
}
Renderer::Get().DrawNode(c, ComputedZIndex);
c->Draw(ComputedZIndex);
}
}
void Node::Calculate()
{
for (auto& c : Childrens)
{
c->Calculate();
}
}
bool Node::IsMouseHover(float x, float y)
{
YGNodeRef ygNode = GetYogaNode();
float parentScroll = 0.f;
if (Parent)
parentScroll = Parent->ScrollDelta;
float width = YGNodeLayoutGetWidth(ygNode);
float height = YGNodeLayoutGetHeight(ygNode);
float padding = YGNodeLayoutGetPadding(ygNode, YGEdgeLeft);
float left = YGNodeLayoutGetLeft(ygNode);
float top = YGNodeLayoutGetTop(ygNode) - parentScroll;
float parentLeft = 0.0f;
float parentTop = 0.0f;
auto parent = Parent;
if (parent)
{
parentLeft = parent->ComputedPosition.x;
parentTop = parent->ComputedPosition.y;
}
left += parentLeft;
top += parentTop;
bool isHover = x > left && x < left + width && y > top && y < top + height;
return isHover;
}
void Node::InsertChild(NodePtr child)
{
if (!mHasBeenInitialized)
InitializeNode();
child->Parent = this;
Childrens.push_back(child);
uint32_t index = (uint32_t)Childrens.size() - 1;
YGNodeInsertChild(this->mNode, child->GetYogaNode(), index);
}
Node* Node::mFocused = nullptr;
void Node::GrabFocus()
{
mFocused = this;
}
bool Node::HasFocus() const
{
return mFocused == this;
}
void Node::ReleaseFocus()
{
mFocused = nullptr;
}
void Node::ApplyStyleProperties(std::map<StyleProperties, PropValue> properties)
{
for (auto& p : properties)
{
StyleProperties prop = p.first;
PropValue value = p.second;
switch (prop)
{
LengthProp(Width)
LengthProp(Height)
LengthProp(MinHeight)
LengthProp(MinWidth)
LengthProp(MaxHeight)
LengthProp(MaxWidth)
LengthProp(MarginLeft)
LengthProp(MarginTop)
LengthProp(MarginRight)
LengthProp(MarginBottom)
LengthProp(PaddingLeft)
LengthProp(PaddingTop)
LengthProp(PaddingRight)
LengthProp(PaddingBottom)
case StyleProperties::Top:
ComputedStyle.Top = value.value.Number;
break;
case StyleProperties::Bottom:
ComputedStyle.Bottom = value.value.Number;
break;
case StyleProperties::Left:
ComputedStyle.Left = value.value.Number;
break;
case StyleProperties::Right:
ComputedStyle.Right = value.value.Number;
break;
EnumProp(Position)
EnumProp(AlignItems)
EnumPropEx(SelfAlign, AlignItemsType)
case StyleProperties::AspectRatio:
ComputedStyle.AspectRatio = value.value.Number;
break;
EnumProp(FlexDirection)
EnumProp(FlexWrap)
case StyleProperties::FlexBasis:
ComputedStyle.FlexBasis = value.value.Number;
break;
case StyleProperties::FlexGrow:
ComputedStyle.FlexGrow = value.value.Number;
break;
case StyleProperties::FlexShrink:
ComputedStyle.FlexShrink = value.value.Number;
break;
EnumProp(JustifyContent)
EnumProp(AlignContent)
EnumProp(LayoutDirection)
case StyleProperties::BorderSize:
ComputedStyle.BorderSize = std::clamp(value.value.Number, 0.f, ComputedSize.x / 2.0f);
break;
case StyleProperties::BorderRadius:
ComputedStyle.BorderRadius = value.value.Number;
break;
case StyleProperties::BorderColor:
ComputedStyle.BorderColor = value.value.Color / 255.f;
break;
case StyleProperties::BackgroundColor:
this->ComputedStyle.BackgroundColor = value.value.Color / 255.f;
break;
case StyleProperties::Color:
ComputedStyle.FontColor = value.value.Color / 255.f;
break;
case StyleProperties::TextAlign:
ComputedStyle.TextAlign = (TextAlignType)(value.value.Enum);
break;
case StyleProperties::Overflow:
ComputedStyle.Overflow = (OverflowType)value.value.Enum;
break;
case StyleProperties::FontSize:
ComputedStyle.FontSize = value.value.Number;
break;
case StyleProperties::Visibility:
ComputedStyle.Visibility = (VisibilityType)value.value.Enum;
break;
case StyleProperties::ZIndex:
ComputedStyle.ZIndex = value.value.Number;
break;
case StyleProperties::BackgroundImage:
{
if (ComputedStyle.BackgroundImage == nullptr)
{
if (StringHelper::EndsWith(value.string, ".svg"))
{
//NSVGimage* image = NULL;
//NSVGrasterizer* rast = NULL;
//unsigned char* img = NULL;
//
//int w, h;
//image = nsvgParseFromFile(value.string.c_str(), "px", 96.0f);
//if (image == NULL) {
// printf("Could not open SVG image.\n");
//
//}
//w = (int)image->width;
//h = (int)image->height;
//
//rast = nsvgCreateRasterizer();
//if (rast == NULL) {
// printf("Could not init rasterizer.\n");
//}
//
//img = (unsigned char*)malloc(w * h * 4);
//if (img == NULL) {
// printf("Could not alloc image buffer.\n");
//}
//
//nsvgRasterize(rast, image, 0, 0, 1, img, w, h, w * 4);
//
//auto texture = std::make_shared<Texture>(img, w * h * 4);
//ComputedStyle.BackgroundImage = texture;
//
//nsvgDeleteRasterizer(rast);
//nsvgDelete(image);
}
else
{
auto texture = std::make_shared<Texture>(value.string);
ComputedStyle.BackgroundImage = texture;
}
}
}
break;
}
}
SetLength(Width)
SetLength(Height)
if (ComputedStyle.Position == PositionType::Absolute)
{
if (ComputedStyle.Top != -1)
{
YGNodeStyleSetPosition(mNode, YGEdgeTop, ComputedStyle.Top);
}
if (ComputedStyle.Bottom != -1)
{
YGNodeStyleSetPosition(mNode, YGEdgeBottom, ComputedStyle.Bottom);
}
if (ComputedStyle.Left != -1)
{
YGNodeStyleSetPosition(mNode, YGEdgeLeft, ComputedStyle.Left);
}
if (ComputedStyle.Right != -1)
{
YGNodeStyleSetPosition(mNode, YGEdgeRight, ComputedStyle.Right);
}
}
SetLengthNoAuto(MaxWidth)
SetLengthNoAuto(MaxHeight)
SetLengthNoAuto(MinWidth)
SetLengthNoAuto(MinHeight)
SetLengthNoAuto(MaxWidth)
SetLengthNoAuto(MaxHeight)
SetLengthBorder(Margin, Left);
SetLengthBorder(Margin, Top);
SetLengthBorder(Margin, Right);
SetLengthBorder(Margin, Bottom);
SetLengthBorderNoAuto(Padding, Left);
SetLengthBorderNoAuto(Padding, Top);
SetLengthBorderNoAuto(Padding, Right);
SetLengthBorderNoAuto(Padding, Bottom);
if (ComputedStyle.Position == PositionType::Relative)
YGNodeStyleSetPositionType(mNode, YGPositionTypeRelative);
else if (ComputedStyle.Position == PositionType::Absolute)
YGNodeStyleSetPositionType(mNode, YGPositionTypeAbsolute);
if (ComputedStyle.FlexDirection == FlexDirectionType::Column)
YGNodeStyleSetFlexDirection(mNode, YGFlexDirectionColumn);
else if (ComputedStyle.FlexDirection == FlexDirectionType::ColumnReversed)
YGNodeStyleSetFlexDirection(mNode, YGFlexDirectionColumnReverse);
else if (ComputedStyle.FlexDirection == FlexDirectionType::Row)
YGNodeStyleSetFlexDirection(mNode, YGFlexDirectionRow);
else if (ComputedStyle.FlexDirection == FlexDirectionType::RowReversed)
YGNodeStyleSetFlexDirection(mNode, YGFlexDirectionRowReverse);
if (ComputedStyle.JustifyContent == JustifyContentType::FlexStart)
YGNodeStyleSetJustifyContent(mNode, YGJustifyFlexStart);
else if (ComputedStyle.JustifyContent == JustifyContentType::Center)
YGNodeStyleSetJustifyContent(mNode, YGJustifyCenter);
else if (ComputedStyle.JustifyContent == JustifyContentType::FlexEnd)
YGNodeStyleSetJustifyContent(mNode, YGJustifyFlexEnd);
else if (ComputedStyle.JustifyContent == JustifyContentType::SpaceAround)
YGNodeStyleSetJustifyContent(mNode, YGJustifySpaceAround);
else if (ComputedStyle.JustifyContent == JustifyContentType::SpaceBetween)
YGNodeStyleSetJustifyContent(mNode, YGJustifySpaceBetween);
else if (ComputedStyle.JustifyContent == JustifyContentType::SpaceEvenly)
YGNodeStyleSetJustifyContent(mNode, YGJustifySpaceEvenly);
if (ComputedStyle.AlignItems == AlignItemsType::FlexStart)
YGNodeStyleSetAlignItems(mNode, YGAlignFlexStart);
else if (ComputedStyle.AlignItems == AlignItemsType::Center)
YGNodeStyleSetAlignItems(mNode, YGAlignCenter);
else if (ComputedStyle.AlignItems == AlignItemsType::FlexEnd)
YGNodeStyleSetAlignItems(mNode, YGAlignFlexEnd);
else if (ComputedStyle.AlignItems == AlignItemsType::SpaceAround)
YGNodeStyleSetAlignItems(mNode, YGAlignSpaceAround);
else if (ComputedStyle.AlignItems == AlignItemsType::SpaceBetween)
YGNodeStyleSetAlignItems(mNode, YGAlignSpaceBetween);
else if (ComputedStyle.AlignItems == AlignItemsType::Stretch)
YGNodeStyleSetAlignItems(mNode, YGAlignStretch);
else if (ComputedStyle.AlignItems == AlignItemsType::Baseline)
YGNodeStyleSetAlignItems(mNode, YGAlignBaseline);
if (ComputedStyle.FlexDirection == FlexDirectionType::Row)
YGNodeStyleSetFlexDirection(mNode, YGFlexDirectionRow);
if (ComputedStyle.FlexDirection == FlexDirectionType::RowReversed)
YGNodeStyleSetFlexDirection(mNode, YGFlexDirectionRowReverse);
if (ComputedStyle.FlexDirection == FlexDirectionType::Column)
YGNodeStyleSetFlexDirection(mNode, YGFlexDirectionColumn);
if (ComputedStyle.FlexDirection == FlexDirectionType::ColumnReversed)
YGNodeStyleSetFlexDirection(mNode, YGFlexDirectionColumnReverse);
else if (ComputedStyle.AlignItems == AlignItemsType::Center)
YGNodeStyleSetAlignItems(mNode, YGAlignCenter);
else if (ComputedStyle.AlignItems == AlignItemsType::FlexEnd)
YGNodeStyleSetAlignItems(mNode, YGAlignFlexEnd);
else if (ComputedStyle.AlignItems == AlignItemsType::SpaceAround)
YGNodeStyleSetAlignItems(mNode, YGAlignSpaceAround);
else if (ComputedStyle.AlignItems == AlignItemsType::SpaceBetween)
YGNodeStyleSetAlignItems(mNode, YGAlignSpaceBetween);
else if (ComputedStyle.AlignItems == AlignItemsType::Stretch)
YGNodeStyleSetAlignItems(mNode, YGAlignStretch);
else if (ComputedStyle.AlignItems == AlignItemsType::Baseline)
YGNodeStyleSetAlignItems(mNode, YGAlignBaseline);
}
std::vector<NodePtr> Node::GetChildrens() const
{
return Childrens;
}
}

240
Nuake/src/UI/Nodes/Node.h Normal file
View File

@@ -0,0 +1,240 @@
#pragma once
#include "NodeState.h"
#include "../DataBinding/DataBindObject.h"
#include "../DataBinding/DataModelOperations.h"
#include "../Styles/StyleSheet.h"
#include "../Nodes/NodeStyle.h"
#include "../InputManager.h"
#include <src/Core/Maths.h>
#include <yoga/yoga.h>
#include <any>
#include <map>
#include <string>
#include <vector>
#define SetLength(name) \
if (ComputedStyle.##name.type == LengthType::Auto) \
YGNodeStyleSet##name##Auto(mNode); \
else if (ComputedStyle.##name.type == LengthType::Pixel) YGNodeStyleSet##name(mNode, ComputedStyle.##name.value); \
else if (ComputedStyle.##name.type == LengthType::Percentage) YGNodeStyleSet##name##Percent(mNode, ComputedStyle.##name.value); \
#define SetLengthBorder(name, border) \
if (ComputedStyle.##name##border.type == LengthType::Auto) \
YGNodeStyleSet##name##Auto(mNode, YGEdge##border); \
else if (ComputedStyle.##name##border.type == LengthType::Pixel) YGNodeStyleSet##name(mNode, YGEdge##border, ComputedStyle.##name##border.value); \
else if (ComputedStyle.##name##border.type == LengthType::Percentage) YGNodeStyleSet##name##Percent(mNode, YGEdge##border, ComputedStyle.##name##border.value); \
#define SetLengthBorderNoAuto(name, border) \
if (ComputedStyle.##name##border.type == LengthType::Pixel) YGNodeStyleSet##name(mNode, YGEdge##border, ComputedStyle.##name##border.value); \
else if (ComputedStyle.##name##border.type == LengthType::Percentage) YGNodeStyleSet##name##Percent(mNode, YGEdge##border, ComputedStyle.##name##border.value); \
#define SetLengthNoAuto(name) \
if (ComputedStyle.##name.type == LengthType::Pixel) YGNodeStyleSet##name(mNode, ComputedStyle.##name.value); \
else if (ComputedStyle.##name.type == LengthType::Percentage) YGNodeStyleSet##name##Percent(mNode, ComputedStyle.##name.value); \
#define EnumProp(name) EnumPropEx(name, ##name##Type)
#define EnumPropEx(name, enums) \
case StyleProperties::name: \
{ \
auto type = value.value.Enum; \
ComputedStyle.##name## = (##enums##)type; \
} \
break;\
#define LengthProp(name) \
case StyleProperties::name: \
{ \
switch (value.type) \
{ \
case PropValueType::Pixel: \
{ \
ComputedStyle.name.type = LengthType::Pixel; \
ComputedStyle.name.value = value.value.Number; \
} \
break; \
case PropValueType::Percent: \
{ \
ComputedStyle.name.type = LengthType::Percentage; \
ComputedStyle.name.value = value.value.Number; \
} \
break; \
case PropValueType::Auto: \
{ \
ComputedStyle.name.type = LengthType::Auto; \
} \
break; \
} \
} \
break; \
namespace NuakeUI
{
class Node;
typedef std::shared_ptr<Node> NodePtr;
class Renderer;
class CanvasParser;
class Node
{
friend CanvasParser;
friend Renderer;
private:
static Node* mFocused;
protected:
float ScrollDelta = 0.0f;
std::string ID = "";
std::string Type = "node";
Node* Parent = nullptr;
std::vector<NodePtr> Childrens = std::vector<NodePtr>();
YGNodeRef mNode;
DataModelOperationCollection mDataModelOperations;
DataModelPtr mDataModel;
bool mHasBeenInitialized = false;
void InitializeNode();
public:
bool CanGrabFocus = false;
std::any UserData;
NodeState State = NodeState::Idle;
std::vector<std::string> Classes = std::vector<std::string>();
Vector2 ComputedSize = { 0, 0 };
Vector2 ComputedPosition = { 0, 0 };
int32_t ComputedZIndex = 0;
NodeStyle ComputedStyle;
static NodePtr New(const std::string id, const std::string& value = "");
Node(const std::string& id, const std::string& value = "");
Node() = default;
~Node() = default;
bool HasBeenInitialized() const;
virtual void Draw(int z);
virtual void UpdateInput(InputManager* manager);
virtual void Tick(InputManager* manager);
virtual void Calculate();
virtual void OnMouseHover(InputManager* inputManager) {};
virtual void OnMouseExit(InputManager* inputManager) {};
virtual void OnClick(InputManager* inputManager) {};
virtual void OnTick(InputManager* manager) {};
virtual void OnClickReleased(InputManager* inputManager) {};
virtual void OnScroll(InputManager* inputManager) {};
bool HasFocus() const;
void GrabFocus();
void ReleaseFocus();
void ApplyStyleProperties(std::map<StyleProperties, PropValue> properties);
void AddClass(const std::string& c)
{
bool containClass = false;
for (auto& classe : Classes)
{
if (c == classe)
{
containClass = true;
}
}
if (!containClass)
{
Classes.push_back(c);
}
}
void RemoveClass(const std::string& c)
{
bool found = false;
int i = 0;
for (auto& cc : Classes)
{
if (cc == c)
{
found = true;
break;
}
i++;
}
if(found)
Classes.erase(Classes.begin() + i);
}
bool HasClass(const std::string& c) const
{
bool found = false;
for (auto& cc : Classes)
if (cc == c) found = true;
return found;
}
// Getter Setter
std::string GetType() const;
std::string GetID() const;
uint32_t GetIndex() const;
YGNodeRef GetYogaNode() const;
float GetScroll() const;
bool IsMouseHover(float x, float y);
bool HasDataModel() const;
DataModelPtr GetDataModel() const;
void SetDataModel(const DataModelPtr& dataModel);
DataModelOperationCollection& GetDataModelOperations();
void AddDataModelOperation(DataModelOperationPtr& operation);
std::vector<NodePtr> GetChildrens() const;
void InsertChild(NodePtr child);
template<class T>
std::shared_ptr<T> GetChild(unsigned int index)
{
assert(index < Childrens.size()); // No childrens.
return std::static_pointer_cast<T>(Childrens[index]);
}
template<class T>
std::shared_ptr<T> GetChildByID(const std::string& id)
{
assert(Childrens.size() > 0); // No childrens.
for (auto& c : Childrens)
{
if (c->ID == id)
return std::static_pointer_cast<T>(c);
}
assert(false); // Node not found.
}
template<class T>
bool FindChildByID(const std::string& id, std::shared_ptr<T>& node)
{
for (auto& c : Childrens)
{
if (c->ID == id)
{
node = std::static_pointer_cast<T>(c);
return true;
}
if (c->FindChildByID<T>(id, node))
return true;
}
return false;
}
};
}

View File

@@ -0,0 +1,8 @@
#pragma once
namespace NuakeUI {
enum class NodeState
{
Idle, Hover, Pressed, Clicked
};
}

View File

@@ -0,0 +1,66 @@
#pragma once
#include "../Styles/Style.h"
#include <src/Core/Maths.h>
#include <src/Rendering/Textures/Texture.h>
using namespace Nuake;
namespace NuakeUI
{
enum class LengthType
{
Percentage, Pixel, Auto
};
struct Length
{
float value = 1.f;
LengthType type = LengthType::Auto;
};
struct NodeStyle
{
Color BackgroundColor = Color(0, 0, 0, 0);
float BorderWidth = 0.f;
Length Width;
Length MinWidth;
Length MaxWidth;
Length Height;
Length MinHeight;
Length MaxHeight;
Length PaddingLeft = { 0.f, LengthType::Pixel };
Length PaddingTop = { 0.f, LengthType::Pixel };
Length PaddingRight = { 0.f, LengthType::Pixel };
Length PaddingBottom = { 0.f, LengthType::Pixel };
Length MarginLeft = { 0.f, LengthType::Pixel };
Length MarginTop = { 0.f, LengthType::Pixel };
Length MarginRight = { 0.f, LengthType::Pixel };
Length MarginBottom = { 0.f, LengthType::Pixel };
PositionType Position = PositionType::Relative;
AlignItemsType SelfAlign;
AlignItemsType AlignItems;
float AspectRatio;
FlexDirectionType FlexDirection;
FlexWrapType FlexWrap;
float FlexBasis;
float FlexGrow;
float FlexShrink;
JustifyContentType JustifyContent;
AlignContentType AlignContent;
LayoutDirectionType LayoutDirection;
float BorderSize = 0.f;
float BorderRadius = 0.f;
Color BorderColor = Color(0, 0, 0, 0);
float FontSize = 64.0f;
TextAlignType TextAlign = TextAlignType::Left;
Color FontColor = Color(1, 1, 1, 1);
OverflowType Overflow = OverflowType::Show;
VisibilityType Visibility = VisibilityType::Show;
std::shared_ptr<Texture> BackgroundImage = nullptr;
int32_t ZIndex = 0;
float Top = -1;
float Bottom = -1;
float Right = -1;
float Left = -1;
};
}

139
Nuake/src/UI/Nodes/Text.cpp Normal file
View File

@@ -0,0 +1,139 @@
#include "Text.h"
#include "../Renderer.h"
#include "src/Rendering/Renderer.h"
#include <sstream>
namespace NuakeUI
{
std::shared_ptr<Text> Text::New(const std::string& id, const std::string& text)
{
return std::make_shared<Text>(id, text);
}
Text::Text(const std::string& id, const std::string& text)
{
ID = id;
mNode = YGNodeNew();
mFont = Renderer::Get().mDefaultFont;
SetText(text);
float height = ((mFont->LineHeight) / 32.f) * ComputedStyle.FontSize * Lines.size();
YGNodeStyleSetHeight(mNode, height);
YGNodeStyleSetMinHeight(mNode, height);
YGNodeStyleSetMinWidth(mNode, CalculateWidth());
YGNodeStyleSetWidthPercent(mNode, 100.f);
}
void Text::SetText(const std::string& text)
{
Lines.clear();
// Split into lines
auto ss = std::stringstream{ text };
for (std::string line; std::getline(ss, line, '\n');)
Lines.push_back(line);
if(std::size(Lines) > 0)
Calculate();
}
void Text::Draw(int z)
{
const float width = YGNodeLayoutGetWidth(mNode);
const float height = YGNodeLayoutGetHeight(mNode);
ComputedSize = { width, height };
float x = YGNodeLayoutGetLeft(mNode);
float y = YGNodeLayoutGetTop(mNode);
// Centers the text in the line height.
y += (mFont->LineHeight / 64.0f) * (ComputedStyle.FontSize) / 2.0f;
x += YGNodeLayoutGetPadding(mNode, YGEdgeLeft);
y += YGNodeLayoutGetPadding(mNode, YGEdgeTop);
auto parent = Parent;
bool hasParent = parent != nullptr;
if (hasParent)
{
x += parent->ComputedPosition.x;
y += parent->ComputedPosition.y - parent->GetScroll();
}
Vector3 position = Vector3(x, y, z);
ComputedPosition = position;
if (ComputedStyle.TextAlign == TextAlignType::Center)
{ // We center the text horizontally.
position.x += (width / 2.0f) - CalculateWidth() / 2.0f;
}
else if (ComputedStyle.TextAlign == TextAlignType::Right)
{ // Aligns the line of the left
position.x += width - CalculateWidth();
}
// Scissor the parent bounding box.
bool hideOverflow = hasParent && Parent->ComputedStyle.Overflow == OverflowType::Hidden;
if (hideOverflow)
{
//glEnable(GL_SCISSOR_TEST);
int clipX = (int)Parent->ComputedPosition.x;
int clipY = (1080 - (int)Parent->ComputedPosition.y - (int)Parent->ComputedSize.y);
int clipWidth = (int)Parent->ComputedSize.x;
int clipHeight = (int)Parent->ComputedSize.y;
//glScissor(clipX, clipY, clipWidth, clipHeight);
}
const float lineYOffset = (mFont->LineHeight / 32.0f) * (ComputedStyle.FontSize);
// Draw each line and offset the Y of the position by the line height.
for(int i = 0; i < Lines.size(); i++)
{
// Draw the first line
Renderer::Get().DrawString(Lines[i], ComputedStyle, mFont, position);
// Update the Y position to the next line.
position.y += lineYOffset;
}
// Disable scissoring.
if (hideOverflow){}
//glDisable(GL_SCISSOR_TEST);
}
float Text::CalculateWidth()
{
// If theres no text, then assume it's 0;
if (Lines.size() == 0) return 0.f;
const float fontSize = ComputedStyle.FontSize / 64.f;
// Find the largest line.
float maxWidth = 0.f;
for (auto& l : Lines)
{
float textWidth = 0.f;
// Iterate over each character and add up the advance.
for (char const& c : l)
{
Char letter = mFont->GetChar((int)c);
textWidth += (letter.Advance);
}
if (textWidth > maxWidth)
maxWidth = textWidth;
}
// Scale the width by the font size.
return maxWidth * fontSize;
}
void Text::Calculate()
{
const float halfLineHeight = mFont->LineHeight / 32.f;
const float linesHeight = Lines.size() * ComputedStyle.FontSize;
YGNodeStyleSetHeight(mNode, halfLineHeight * linesHeight);
YGNodeStyleSetWidth(mNode, CalculateWidth());
}
}

32
Nuake/src/UI/Nodes/Text.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include "Node.h"
#include "../Font/Font.h"
#include <memory>
#include <string>
namespace NuakeUI
{
class Text;
typedef std::shared_ptr<Text> TextPtr;
class Text : public Node
{
public:
std::vector<std::string> Lines;
std::shared_ptr<Font> mFont;
static std::shared_ptr<Text> New(const std::string& id, const std::string& text);
Text(const std::string& id, const std::string& text);
~Text() = default;
void SetText(const std::string& text);
void Calculate() override;
void UpdateInput(InputManager* manager) override {};
void Draw(int z) override;
float CalculateWidth();
private:
};
}

View File

@@ -0,0 +1,90 @@
#pragma once
#include <NuakeUI/Nodes/Node.h>
#include <NuakeUI/Nodes/Text.h>
#include <memory>
namespace NuakeUI
{
class TextInput : public Node
{
private:
std::string Buffer = "";
TextPtr TextLabel;
uint32_t _cursorIdx = 0;
public:
static std::shared_ptr<TextInput> New(const std::string& id, const std::string& name)
{
return std::make_shared<TextInput>(id, name);
}
TextInput(const std::string& id, const std::string& name)
{
InitializeNode();
CanGrabFocus = true;
std::map<StyleProperties, PropValue> styles;
styles[StyleProperties::BackgroundColor] = Color(1.f, 0.f, 0.f, 255.f);
styles[StyleProperties::BorderColor] = Color(0.f, 255.f, 0.f, 255.f);
styles[StyleProperties::Height] = PropValue(PropValueType::Auto, 20.f);
styles[StyleProperties::BorderSize] = 2.0f;
ComputedStyle.BorderRadius = 4.0f;
ComputedStyle.BorderSize = 2.0f;
ComputedStyle.MaxWidth = { 200.f, LengthType::Pixel };
ComputedStyle.Overflow = OverflowType::Hidden;
styles[StyleProperties::PaddingLeft] = PropValue(PropValueType::Pixel, 8.f);
styles[StyleProperties::PaddingTop] = PropValue(PropValueType::Pixel, 4.f);
styles[StyleProperties::PaddingBottom] = PropValue(PropValueType::Pixel, 4.f);
styles[StyleProperties::PaddingRight] = PropValue(PropValueType::Pixel, 8.f);
ApplyStyleProperties(styles);
TextLabel = Text::New("textInput", "");
InsertChild(TextLabel);
}
~TextInput() = default;
virtual void OnTick(InputManager* inputManager) override
{
TextLabel->SetText(Buffer);
if (HasFocus())
{
if (std::size(inputManager->InputStack) > 0)
{
std::string result = inputManager->ConsumeStack();
if (result == "_backspace")
{
if (std::size(Buffer) > 0)
Buffer.erase(Buffer.end() - 1);
}
else
{
Buffer += result;
}
}
ComputedStyle.BorderSize = 2.0f;
}
else
{
ComputedStyle.BorderSize = 0.f;
}
}
virtual void OnClick(InputManager* inputManager) override
{
if (!HasFocus())
{
while (inputManager->InputStack.size() > 0)
{
inputManager->ConsumeStack();
}
}
}
};
}

4
Nuake/src/UI/NuakeUI.cpp Normal file
View File

@@ -0,0 +1,4 @@
namespace NuakeUI
{
}

51
Nuake/src/UI/NuakeUI.h Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
/*
Welcome to NuakeUI,
first of all thank you for using this library.
How to use:
1. Include this header file
2. Create a CanvasParser object and parse an xml file using the Parse method.
It returns a pointer to your canvas object.
3. Create an InputManager class that inherits from the InputManager.h interface.
4. Register the input manager on your canvas object returned by the Parse method of earlier with the SetInputManager method
5. Call the 3 follow methods in your main loop:
1. canvas->ComputeLayout(myWindowSize);
2. canvas->Tick();
3. canvas->Draw();
6. You are now rendering your UI.
Contribute:
If you wish to know more about the other features like DataModel binding, styling options,
Fragments, and responsive layouts, you should look at the ReadMe of the repository or look at the
demo projects which goes more in depth.
Original repository: https://github.com/antopilo/nuakeui
Demo repository: https://github.com/antopilo/nuakeuidemo
In case you have any feature requests, or encounter issues with the project.
Please fill them on the issues page on the repository.
Thank you,
antopilo
*/
#include "src/UI/Nodes/Button.h"
#include "src/UI/Renderer.h"
#include "Parsers/CanvasParser.h"
/*
TODO:
- FIX z-index mouse hover
- FIX mouse events when window not focused
- CSS Variables
- Color
- Units
- Make them global?
- CSS background image
- <div> Active state
- <svg> Tag? with nano svg
- Text overflow clipping not working
*/

View File

@@ -0,0 +1,289 @@
#include "CanvasParser.h"
#include "../Nodes/Canvas.h"
#include "../Nodes/Text.h"
#include "../Nodes/Button.h"
#include "../FileSystem.h"
#include "StyleSheetParser.h"
#include "../StringHelper.h"
#include <iostream>
#include <charconv>
namespace NuakeUI
{
CanvasParser::CanvasParser()
{
RegisterNodeType("div", Node::New);
RegisterNodeType("text", Text::New);
RegisterNodeType("button", Button::New);
}
void CanvasParser::RegisterNodeType(const std::string& name, refNew refConstructor)
{
NodeTypes[name] = refConstructor;
}
bool CanvasParser::HasNodeType(const std::string& name) const
{
return NodeTypes.find(name) != NodeTypes.end();
}
refNew CanvasParser::GetNodeType(const std::string& name) const
{
if (HasNodeType(name))
{
return NodeTypes.at(name);
}
return nullptr;
}
NodePtr CanvasParser::CreateNodeFromXML(tinyxml2::XMLElement* xml, const std::string& id)
{
NodePtr newNode;
std::string nodeId = id;
std::string type = xml->Value();
std::string text = xml->GetText() ? xml->GetText() : "";
if (HasNodeType(type))
{
newNode = GetNodeType(type)(nodeId, text);
newNode->Type = type;
if (!newNode->HasBeenInitialized())
{
newNode->InitializeNode();
}
}
return newNode;
}
void CanvasParser::AddClassesToNode(tinyxml2::XMLElement* e, NodePtr node)
{
auto classAttribute = e->FindAttribute("class");
if (!classAttribute)
return;
std::string strClasses = classAttribute->Value();
node->Classes = StringHelper::Split(strClasses, ' ');
}
void CanvasParser::WriteValueFromString(std::variant<int, float, bool, std::string, char>& var, const std::string& str)
{
// Determine type of value
if (str.find("'") != std::string::npos)
{
// Removing second bracket
const auto& stringSplit = StringHelper::Split(str, "'");
var = stringSplit[1];
}
else if (str.find(".") != std::string::npos)
{
const auto& begin = str.data();
const auto& end = begin + std::size(str);
float rightFloat;
std::from_chars(begin, end, rightFloat);
var = rightFloat;
}
else if (str.find("true") != std::string::npos)
{
var = true;
}
else if (str.find("false") != std::string::npos)
{
var = false;
}
else
{
const auto& begin = str.data();
const auto& end = begin + std::size(str);
int rightInt;
std::from_chars(begin, end, rightInt);
var = rightInt;
}
}
void CanvasParser::AddModelIfToNode(tinyxml2::XMLElement* e, NodePtr node)
{
if (auto modelIf = e->FindAttribute("if"); modelIf)
{
std::string ifCondition = modelIf->Value();
ifCondition = StringHelper::RemoveChar(ifCondition, ' ');
ComparaisonType compType = ComparaisonType::None;
std::vector<std::string> splits;
const std::vector<std::string> operators { "==", "!=", ">=", "<=", ">", "<" };
for (auto i = 0; i < std::size(operators); i++)
{
std::string operatorString = operators[i];
if (ifCondition.find(operatorString) != std::string::npos)
{
compType = (ComparaisonType)i;
splits = StringHelper::Split(ifCondition, operatorString);
}
}
if (std::size(splits) < 2 || compType == ComparaisonType::None)
return;
auto operation = DataModelOperation::New(splits[0], OperationType::If, compType);
WriteValueFromString(operation->Right, splits[1]);
node->AddDataModelOperation(operation);
}
}
void CanvasParser::AddModelClasses(tinyxml2::XMLElement* e, NodePtr node)
{
auto currentAttribute = e->FirstAttribute();
while (currentAttribute)
{
std::string attributeName = currentAttribute->Name();
if (attributeName == "modelClass")
{
std::string attributeValue = currentAttribute->Value();
auto attributeValueSplits = StringHelper::Split(attributeValue, ':');
if (std::size(attributeValueSplits) < 2)
continue;
std::string className = StringHelper::RemoveChar(attributeValueSplits[0], '[');
className = StringHelper::RemoveChar(className, ']');
ComparaisonType compType = ComparaisonType::None;
std::vector<std::string> splits;
// TODO: Move to another reusable method.
const std::vector<std::string> operators{ "==", "!=", ">=", "<=", ">", "<" };
for (auto i = 0; i < std::size(operators); i++)
{
std::string operatorString = operators[i];
std::string logicalExpression = attributeValueSplits[1];
if (logicalExpression.find(operatorString) != std::string::npos)
{
compType = (ComparaisonType)i;
splits = StringHelper::Split(logicalExpression, operatorString);
}
}
if (std::size(splits) < 2 || compType == ComparaisonType::None)
return;
std::string dataProp = StringHelper::RemoveChar(splits[0], ' ');
auto operation = DataModelOperation::New(dataProp, OperationType::IfClass, compType);
WriteValueFromString(operation->Right, StringHelper::RemoveChar(splits[1], ' '));
operation->ClassName = className;
node->AddDataModelOperation(operation);
}
currentAttribute = currentAttribute->Next();
}
}
void CanvasParser::ScanFragment(tinyxml2::XMLElement* e, NodePtr node)
{
// We have a <fragment> with a src path.
const std::string nodeType = e->Value();
if (nodeType == "fragment")
{
if (auto srcAttr = e->FindAttribute("src"); srcAttr)
{
std::string fragmentPath = _parsingPath + "/../" + srcAttr->Value();
if (FileSystem::FileExists(fragmentPath))
{
tinyxml2::XMLDocument doc;
if (tinyxml2::XMLError error = doc.LoadFile(fragmentPath.c_str()))
{
doc.PrintError();
}
auto firstNode = doc.FirstChildElement();
IterateOverElement(firstNode, node);
}
else
{
std::cout << "Fragment src attributes error. Cant find file at: " << fragmentPath << std::endl;
}
}
}
}
void CanvasParser::IterateOverElement(tinyxml2::XMLElement* e, NodePtr node)
{
tinyxml2::XMLElement* current = e;
while (current)
{
std::string id = "Node";
// Look if the node has an id.
auto idAttribute = current->FindAttribute("id");
if (idAttribute)
{
id = idAttribute->Value();
}
ScanFragment(current, node);
NodePtr newNode = CreateNodeFromXML(current, id);
if (newNode)
{
AddClassesToNode(current, newNode);
AddModelIfToNode(current, newNode);
AddModelClasses(current, newNode);
// Insert in the tree
node->InsertChild(newNode);
// Recursivity on the childs of the current node.
IterateOverElement(current->FirstChildElement(), newNode);
}
// Continue to the sibbling after going Depth first.
current = current->NextSiblingElement();
}
}
CanvasPtr CanvasParser::Parse(const std::string& path)
{
_parsingPath = path;
tinyxml2::XMLDocument doc;
if (tinyxml2::XMLError error = doc.LoadFile(path.c_str()))
{
doc.PrintError();
return nullptr;
}
CanvasPtr canvas = Canvas::New();
NodePtr root = Node::New("root");
auto firstNode = doc.FirstChildElement();
if (!firstNode)
{
return canvas;
}
// Look for stylesheet attribute in root.
auto styleSheet = firstNode->FindAttribute("stylesheet");
if (styleSheet)
{
std::string relativePath = path + "/../" + styleSheet->Value();
if (FileSystem::FileExists(relativePath))
{
auto styleSheet = StyleSheetParser::Get().Parse(relativePath);
canvas->SetStyleSheet(styleSheet);
}
}
IterateOverElement(firstNode, root);
canvas->SetRoot(root);
return canvas;
}
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include "../Nodes/Canvas.h"
#include <functional>
#include <memory>
#include <map>
#include <string>
#include <msdfgen/include/tinyxml2.h>
namespace NuakeUI
{
typedef std::function<NodePtr(std::string, std::string)> refNew;
class CanvasParser
{
private:
std::map<std::string, refNew> NodeTypes;
std::string _parsingPath;
public:
CanvasParser();
~CanvasParser() = default;
/// <summary>
/// Register a custom node type.
/// </summary>
/// <param name="name">XML tag</param>
/// <param name="refConstructor">pointer to method that returns a shared pointer.</param>
void RegisterNodeType(const std::string& name, refNew refConstructor);
bool HasNodeType(const std::string& name) const;
refNew GetNodeType(const std::string& name) const;
CanvasPtr Parse(const std::string& file);
private:
void ScanFragment(tinyxml2::XMLElement* e, NodePtr node);
void WriteValueFromString(std::variant<int, float, bool, std::string, char>& var, const std::string& str);
void IterateOverElement(tinyxml2::XMLElement* e, NodePtr node);
NodePtr CreateNodeFromXML(tinyxml2::XMLElement* xml, const std::string& id = "Node");
void AddClassesToNode(tinyxml2::XMLElement* e, NodePtr node);
void AddModelIfToNode(tinyxml2::XMLElement* e, NodePtr node);
void AddModelClasses(tinyxml2::XMLElement* e, NodePtr node);
};
}

View File

@@ -0,0 +1,374 @@
#include "StyleSheetParser.h"
#include <cassert>
#include <vector>
#include "../FileSystem.h"
#include <iostream>
namespace NuakeUI
{
std::shared_ptr<StyleSheet> StyleSheetParser::Parse(const std::string& path)
{
assert(FileSystem::FileExists(path));
_parsingPath = path;
std::string fileContent = FileSystem::ReadFile(path);
auto data = katana_parse(fileContent.c_str(), fileContent.length(), KatanaParserModeStylesheet);
auto styleSheet = StyleSheet::New();
// Print out errors.
if (data->errors.length > 0)
{
KatanaArray errors = data->errors;
for (uint32_t i = 0; i < errors.length; i++)
{
KatanaError* error = (KatanaError*)errors.data[i];
std::cout << "Failed to parse css file \"" + path + "\"." << std::endl;
std::cout << "Error is " << error->message << std::endl;
std::cout << "ERROR at line " + std::to_string(error->first_line) +
" : " + std::to_string(error->first_column) << std::endl;
}
return styleSheet;
}
else
{
ParseRules(data->stylesheet, styleSheet);
}
_visitedFiles.clear();
return styleSheet;
}
bool StyleSheetParser::FileAlreadyVisited(const std::string& path)
{
return std::find(_visitedFiles.begin(), _visitedFiles.end(), path) != _visitedFiles.end();
}
void StyleSheetParser::ParseRules(KatanaStylesheet* katanaStylesheet, StyleSheetPtr stylesheet)
{
// Import files first
auto imports = katanaStylesheet->imports;
for (uint32_t i = 0; i < imports.length; i++)
{
KatanaImportRule* importRule = static_cast<KatanaImportRule*>(imports.data[i]);
ParseImportRule(importRule, stylesheet);
}
// Parse generic rules
auto rules = katanaStylesheet->rules;
for (uint32_t i = 0; i < rules.length; i++)
{
KatanaRule* rule = (KatanaRule*)rules.data[i];
auto ruleType = rule->type;
switch (ruleType)
{
case KatanaRuleStyle: // Not sure if needed.
ParseStyleRule(rule, stylesheet);
break;
}
}
}
void StyleSheetParser::ParseImportRule(KatanaImportRule* rule, StyleSheetPtr styleSheet)
{
std::string path = rule->href;
if (FileAlreadyVisited(path))
{
std::cout << "Cyclic file import detected! " << "File is: " << path << std::endl;
return;
}
_visitedFiles.push_back(path);
if (!FileSystem::FileExists(path))
{
std::cout << "CSS Import rule error: Cannot find file: " << path << std::endl;
return;
}
std::string fileContent = FileSystem::ReadFile(path);
auto data = katana_parse(fileContent.c_str(), fileContent.length(), KatanaParserModeStylesheet);
if (data->errors.length > 0)
{
KatanaArray errors = data->errors;
for (uint32_t i = 0; i < errors.length; i++)
{
KatanaError* error = (KatanaError*)errors.data[i];
std::cout << "Failed to parse css file \"" + path + "\"." << std::endl;
std::cout << "Error is " << error->message << std::endl;
std::cout << "ERROR at line " + std::to_string(error->first_line) +
" : " + std::to_string(error->first_column) << std::endl;
}
return;
}
ParseRules(data->stylesheet, styleSheet);
}
StyleProperties GetPropFromString(const std::string& prop)
{
if (prop == "height") return StyleProperties::Height;
else if (prop == "max-height") return StyleProperties::MaxHeight;
else if (prop == "min-height") return StyleProperties::MinHeight;
else if (prop == "width") return StyleProperties::Width;
else if (prop == "max-width") return StyleProperties::MaxWidth;
else if (prop == "min-width") return StyleProperties::MinWidth;
else if (prop == "padding-left") return StyleProperties::PaddingLeft;
else if (prop == "padding-right") return StyleProperties::PaddingRight;
else if (prop == "padding-top") return StyleProperties::PaddingTop;
else if (prop == "padding-bottom") return StyleProperties::PaddingBottom;
else if (prop == "margin-left") return StyleProperties::MarginLeft;
else if (prop == "margin-right") return StyleProperties::MarginRight;
else if (prop == "margin-top") return StyleProperties::MarginTop;
else if (prop == "margin-bottom") return StyleProperties::MarginBottom;
else if (prop == "position") return StyleProperties::Position;
else if (prop == "align-items") return StyleProperties::AlignItems;
else if (prop == "self-align") return StyleProperties::SelfAlign;
else if (prop == "aspect-ratio") return StyleProperties::AspectRatio;
else if (prop == "flex-direction") return StyleProperties::FlexDirection;
else if (prop == "flex-wrap") return StyleProperties::FlexWrap;
else if (prop == "flex-basis") return StyleProperties::FlexBasis;
else if (prop == "flex-grow") return StyleProperties::FlexGrow;
else if (prop == "flex-shrink") return StyleProperties::FlexShrink;
else if (prop == "justify-content") return StyleProperties::JustifyContent;
else if (prop == "align-content") return StyleProperties::AlignContent;
else if (prop == "layout-direction") return StyleProperties::LayoutDirection;
else if (prop == "border-size") return StyleProperties::BorderSize;
else if (prop == "border-radius") return StyleProperties::BorderRadius;
else if (prop == "border-color") return StyleProperties::BorderColor;
else if (prop == "background-color") return StyleProperties::BackgroundColor;
else if (prop == "text-align") return StyleProperties::TextAlign;
else if (prop == "color") return StyleProperties::Color;
else if (prop == "overflow") return StyleProperties::Overflow;
else if (prop == "font-size") return StyleProperties::FontSize;
else if (prop == "visibility") return StyleProperties::Visibility;
else if (prop == "z-index") return StyleProperties::ZIndex;
else if (prop == "top") return StyleProperties::Top;
else if (prop == "bottom") return StyleProperties::Bottom;
else if (prop == "left") return StyleProperties::Left;
else if (prop == "right") return StyleProperties::Right;
else if (prop == "background-image") return StyleProperties::BackgroundImage;
return StyleProperties::None;
}
void StyleSheetParser::ParseStyleRule(KatanaRule* rule, StyleSheetPtr styleSheet)
{
auto styleRule = reinterpret_cast<KatanaStyleRule*>(rule);
std::string styleName = rule->name;
for (uint32_t s = 0; s < styleRule->selectors->length; s++)
{
auto styleSelector = std::vector<StyleSelector>();
// unsafe c-style void* in the array.
void* selectorData = styleRule->selectors->data[s];
auto selector = reinterpret_cast<KatanaSelector*>(selectorData);
while (selector)
{
auto match = selector->match; // tag, id or class
switch (match)
{
case KatanaSelectorMatchPseudoClass:
{
std::string matchPseudo = selector->data->value;
styleSelector.push_back({ StyleSelectorType::Pseudo, matchPseudo });
}
break;
case KatanaSelectorMatchTag:
{
std::string matchTag = selector->tag->local;
styleSelector.push_back({ StyleSelectorType::Tag, matchTag });
}
break;
case KatanaSelectorMatchId:
{
std::string matchId = selector->data->value;
styleSelector.push_back({ StyleSelectorType::Id, matchId });
}
break;
case KatanaSelectorMatchClass:
{
std::string matchClass = selector->data->value;
styleSelector.push_back({ StyleSelectorType::Class, matchClass });
}
break;
}
selector = selector->tagHistory;
}
// Added the new rule with selectors.
auto newRule = StyleRule(styleSelector);
// Now add the properties to the new rule.
for (uint32_t d = 0; d < styleRule->declarations->length; d++)
{
// unsafe c-style void* in the array.
void* declarationData = styleRule->declarations->data[d];
auto declaration = reinterpret_cast<KatanaDeclaration*>(declarationData);
// convert from string to property enum.
StyleProperties propType = GetPropFromString(declaration->property);
PropValue propValue{};
for (uint32_t v = 0; v < declaration->values->length; v++)
{
// unsafe c-style voir* in the array.
void* valueData = declaration->values->data[v];
KatanaValue* value = reinterpret_cast<KatanaValue*>(valueData);
switch (value->unit)
{
case KatanaValueUnit::KATANA_VALUE_STRING:
{
std::string stringValue = value->string;
if (propType == StyleProperties::BackgroundImage)
{
stringValue = _parsingPath + "/../" + stringValue;
}
propValue.string = stringValue;
propValue.type = PropValueType::String;
}
break;
case KatanaValueUnit::KATANA_VALUE_PERCENTAGE:
case KatanaValueUnit::KATANA_VALUE_PX:
{
propValue.value.Number = (float)value->fValue;
propValue.type = value->unit == KatanaValueUnit::KATANA_VALUE_PX ? PropValueType::Pixel : PropValueType::Percent;
}
break;
case KatanaValueUnit::KATANA_VALUE_PARSER_HEXCOLOR:
{
int r, g, b, a = 255;
int result = sscanf_s(value->string, "%02x%02x%02x%02x", &r, &g, &b, &a);
propValue.value.Color = Color(r, g, b, a);
propValue.type = PropValueType::Color;
}
break;
case KatanaValueUnit::KATANA_VALUE_UNKNOWN:
{
std::string valueStr = value->string;
}
break;
case KatanaValueUnit::KATANA_VALUE_NUMBER:
propValue.value.Number = (int)value->fValue;
break;
case KatanaValueUnit::KATANA_VALUE_IDENT:
{
std::string valueStr = value->string;
if (propType == StyleProperties::Position)
{
PositionType positionType = PositionType::Relative;
if (valueStr == "absolute")
propValue.value.Enum = (int)PositionType::Absolute;
}
if (propType == StyleProperties::AlignContent)
{
AlignContentType align;
if (valueStr == "flex-start") align = AlignContentType::FlexStart;
else if (valueStr == "center") align = AlignContentType::Center;
else if (valueStr == "flex-end") align = AlignContentType::FlexEnd;
else if (valueStr == "stretch") align = AlignContentType::Stretch;
else if (valueStr == "space-between") align = AlignContentType::SpaceBetween;
else if (valueStr == "space-around") align = AlignContentType::SpaceAround;
else align = AlignContentType::FlexStart;
propValue.type = PropValueType::Enum;
propValue.value.Enum = (int)align;
}
else if (propType == StyleProperties::AlignItems || propType == StyleProperties::SelfAlign)
{
AlignItemsType align;
if (valueStr == "flex-start") align = AlignItemsType::FlexStart;
else if (valueStr == "center") align = AlignItemsType::Center;
else if (valueStr == "flex-end") align = AlignItemsType::FlexEnd;
else if (valueStr == "stretch") align = AlignItemsType::Stretch;
else if (valueStr == "space-between") align = AlignItemsType::SpaceBetween;
else if (valueStr == "space-around") align = AlignItemsType::SpaceAround;
else align = AlignItemsType::FlexStart;
propValue.type = PropValueType::Enum;
propValue.value.Enum = (int)align;
}
else if (propType == StyleProperties::FlexDirection)
{
FlexDirectionType direction = FlexDirectionType::Row;
if (valueStr == "column") direction = FlexDirectionType::Column;
else if (valueStr == "row-reversed") direction = FlexDirectionType::RowReversed;
else if (valueStr == "column-reversed") direction = FlexDirectionType::ColumnReversed;
propValue.type = PropValueType::Enum;
propValue.value.Enum = (int)direction;
}
else if (propType == StyleProperties::FlexWrap)
{
FlexWrapType type = FlexWrapType::Wrap;
if (valueStr == "no-wrap") type = FlexWrapType::NoWrap;
else if (valueStr == "wrap-reversed") type = FlexWrapType::WrapReversed;
propValue.type = PropValueType::Enum;
propValue.value.Enum = (int)type;
}
else if (propType == StyleProperties::JustifyContent)
{
auto justify = JustifyContentType::FlexStart;
if (valueStr == "center") justify = JustifyContentType::Center;
else if (valueStr == "flex-end") justify = JustifyContentType::FlexEnd;
else if (valueStr == "space-around") justify = JustifyContentType::SpaceAround;
else if (valueStr == "space-between") justify = JustifyContentType::SpaceBetween;
else if (valueStr == "space-evenly") justify = JustifyContentType::SpaceEvenly;
propValue.type = PropValueType::Enum;
propValue.value.Enum = (int)justify;
}
else if (propType == StyleProperties::LayoutDirection)
{
auto direction = LayoutDirectionType::LTR;
if (valueStr == "RTL") direction = LayoutDirectionType::RTL;
propValue.type = PropValueType::Enum;
propValue.value.Enum = (int)direction;
}
else if (propType == StyleProperties::TextAlign)
{
auto align = TextAlignType::Left;
if (valueStr == "center") align = TextAlignType::Center;
if (valueStr == "right") align = TextAlignType::Right;
propValue.type = PropValueType::Enum;
propValue.value.Enum = (int)align;
}
else if (propType == StyleProperties::Overflow)
{
OverflowType overflow = OverflowType::Show;
if (valueStr == "hidden") overflow = OverflowType::Hidden;
else if (valueStr == "show") overflow = OverflowType::Show;
else if (valueStr == "scroll") overflow = OverflowType::Scroll;
propValue.type = PropValueType::Enum;
propValue.value.Enum = (int)overflow;
}
else if (propType == StyleProperties::Visibility)
{
VisibilityType visibility = VisibilityType::Show;
if (valueStr == "hidden") visibility = VisibilityType::Hidden;
propValue.type = PropValueType::Enum;
propValue.value.Enum = (int)visibility;
}
}
break;
}
}
newRule.SetProp(propType, propValue);
}
styleSheet->Rules.push_back(newRule);
}
}
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include "../Styles/StyleSheet.h"
#include <string>
#include <memory>
#include "../Vendors/katana-parser/katana.h"
namespace NuakeUI
{
class StyleSheetParser
{
public:
static StyleSheetParser& Get()
{
static StyleSheetParser parser;
return parser;
}
StyleSheetParser() = default;
~StyleSheetParser() = default;
std::shared_ptr<StyleSheet> Parse(const std::string& path);
private:
std::string _parsingPath;
std::vector<std::string> _visitedFiles;
bool FileAlreadyVisited(const std::string& path);
void ParseRules(KatanaStylesheet* katanaStylesheet, StyleSheetPtr stylesheet);
void ParseImportRule(KatanaImportRule* rule, StyleSheetPtr styleSheet);
void ParseStyleRule(KatanaRule* rule, StyleSheetPtr stylesheet);
};
}

206
Nuake/src/UI/Renderer.cpp Normal file
View File

@@ -0,0 +1,206 @@
#include "Renderer.h"
#include "src/Core/Maths.h"
#include "src/Rendering/Buffers/VertexBufferLayout.h"
#include "Font/Font.h"
#include "Font/FontManager.h"
#include "FileSystem.h"
namespace NuakeUI
{
struct Vertex {
Vector3 Position;
Vector2 UV;
};
std::shared_ptr<Font> Renderer::mDefaultFont;
Renderer::Renderer()
{
ReloadShaders();
mDefaultFont = FontManager::Get().GetFont("SourceSansPro-Regular.ttf");
const std::vector<Vertex> vertices = {
{ { 1.f, 1.f, 0.f }, {1.f, 0.f} },
{ { 1.f, 0.f, 0.f }, {1.f, 1.f} },
{ { 0.f, 1.f, 0.f }, {0.f, 0.f} },
{ { 1.f, 0.f, 0.f }, {1.f, 1.f} },
{ { 0.f, 0.f, 0.f }, {0.f, 1.f} },
{ { 0.f, 1.f, 0.f }, {0.f, 0.f} },
};
mVertexArray = std::make_shared<VertexArray>();
mVertexArray->Bind();
mVertexBuffer = std::make_shared<VertexBuffer>(vertices.data(), (unsigned int)(vertices.size() * sizeof(Vertex)));
auto vbl = VertexBufferLayout();
vbl.Push<float>(3); // Position
vbl.Push<float>(2); // UV
mVertexArray->AddBuffer(*mVertexBuffer, vbl);
mVertexArray->Unbind();
}
void Renderer::ReloadShaders()
{
// Rectangle Shader
std::string vertexSource = FileSystem::ReadFile("../resources/panel.vert.glsl");
std::string fragSource = FileSystem::ReadFile("../resources/panel.frag.glsl");
mShader = std::make_shared<Shader>(vertexSource, fragSource);
// SDF Shader
vertexSource = FileSystem::ReadFile("../resources/text.vert.glsl");
fragSource = FileSystem::ReadFile("../resources/text.frag.glsl");
mSDFShader = std::make_shared<Shader>(vertexSource, fragSource);
}
void Renderer::SetViewportSize(const Vector2& size)
{
mSize = size;
mView = glm::ortho(0.f, size.x, size.y, 0.f, -100.f, 100.0f);
}
void Renderer::BeginDraw()
{
int viewportW = (int)mSize.x;
int viewportH = (int)mSize.y;
//glViewport(0, 0, viewportW, viewportH);
}
void Renderer::DrawNode(std::shared_ptr<Node> node, int z)
{
//glEnable(GL_DEPTH_TEST);
float parentScroll = 0.f;
float parentPaddingRight = 0.f;
if (node->Parent)
{
parentScroll = node->Parent->ScrollDelta;
}
const YGNodeRef yogaNode = node->GetYogaNode();
const float width = YGNodeLayoutGetWidth(yogaNode) - parentPaddingRight;
const float height = YGNodeLayoutGetHeight(yogaNode);
const float padding = YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft);
const float margin = YGNodeLayoutGetMargin(yogaNode, YGEdgeLeft);
const float marginTop = YGNodeLayoutGetMargin(yogaNode, YGEdgeTop);
const float left = YGNodeLayoutGetLeft(yogaNode);
const float top = YGNodeLayoutGetTop(yogaNode) - parentScroll;
const float borderLeft = YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft);
float parentLeft = 0.f;
float parentTop = 0.f;
auto parent = node->Parent;
if (parent)
{
parentLeft = parent->ComputedPosition.x;
parentTop = parent->ComputedPosition.y;
}
node->ComputedSize = Vector2(width, height);
node->ComputedPosition = Vector2(left + parentLeft, top + parentTop);
Matrix4 transform = Matrix4(1.f);
transform = glm::translate(transform, Vector3(left + parentLeft, top + parentTop, z));
transform = glm::scale(transform, Vector3(width, height, 1.0f));
bool hasBackgroundImage = false;
if (node->ComputedStyle.BackgroundImage)
{
hasBackgroundImage = true;
node->ComputedStyle.BackgroundImage->Bind(0);
}
mShader->Bind();
//mShader->SetUniforms({
// { "u_Model", transform },
// { "u_Size", Vector2(width, height) },
// { "u_View", mView },
// { "u_Color", node->ComputedStyle.BackgroundColor },
// { "u_Border", node->ComputedStyle.BorderSize },
// { "u_BorderRadius", node->ComputedStyle.BorderRadius },
// { "u_BorderColor", node->ComputedStyle.BorderColor },
// { "u_BackgroundImage", 0 },
// { "u_HasBackgroundImage", hasBackgroundImage ? 1.f : 0.f}
//});
//bool hideOverflow = node->Parent != nullptr && node->Parent->ComputedStyle.Overflow == OverflowType::Hidden;
//if (hideOverflow)
//{
// glEnable(GL_SCISSOR_TEST);
// Vector2 parentPosition = node->Parent->ComputedPosition;
// Vector2 parentSize = node->Parent->ComputedSize;
// int scissorX = (int)parentPosition.x;
// int scissorY = 1080 - (int)(parentPosition.y - parentSize.y);
// int scissorW = (int)parentSize.x;
// int scissorH = (int)parentSize.y;
// glScissor(scissorX, scissorY, scissorW, scissorH);
//}
// TODO: Keep overflow until we get out of here
//mVertexArray->Bind();
//glDrawArrays(GL_TRIANGLES, 0, 6);
//mVertexArray->Unbind();
//mShader->Unbind();
//
//if (hideOverflow)
// glDisable(GL_SCISSOR_TEST);
}
void Renderer::DrawString(const std::string& string, NodeStyle& nodeStyle, std::shared_ptr<Font> font, Vector3 position)
{
//const float fontSize = nodeStyle.FontSize / 64.f;
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//mSDFShader->Bind();
//font->mAtlas->Bind(5);
//mSDFShader->SetUniforms({
// { "u_View", mView },
// { "u_Atlas", 5 },
// { "u_Scale", 1.0f},
// { "u_SDF_BorderSize", 0.0f},
// { "u_FontColor", nodeStyle.FontColor },
// { "u_PxRange", fontSize },
// { "u_SDF_BorderSize", {1.0, 1.0}}
//});
//
//mVertexArray->Bind();
//
//float advance = 0.0f;
//for (char const& c : string)
//{
// Char letter = font->GetChar((int)c);
//
// // Move the cursor
// Matrix4 model = Matrix4(1.f);
// model = glm::translate(model, position);
// model = glm::translate(model, Vector3(advance * fontSize, (-(letter.PlaneBounds.top) + (font->LineHeight)) * fontSize, 0));
//
// advance += (letter.Advance);
//
// // Scaling of the quad
// float scaleX = (float)(letter.PlaneBounds.right - letter.PlaneBounds.left);
// float scaleY = (float)(letter.PlaneBounds.top - letter.PlaneBounds.bottom);
// model = glm::scale(model, Vector3(scaleX * fontSize, scaleY * fontSize, 1.f));
//
// // Set Uniforms
// mSDFShader->SetUniforms({
// { "u_Model", model },
// { "u_TexturePos", Vector2(letter.AtlasBounds.Pos.x, letter.AtlasBounds.Pos.y) },
// { "u_TextureScale", Vector2(letter.AtlasBounds.Size.x, letter.AtlasBounds.Size.y) },
// });
//
//
// glDrawArrays(GL_TRIANGLES, 0, 6);
//}
//
//
//mVertexArray->Unbind();
}
}

47
Nuake/src/UI/Renderer.h Normal file
View File

@@ -0,0 +1,47 @@
#pragma once
#include <src/Rendering/Shaders/Shader.h>
#include <src/Rendering/Buffers/VertexBuffer.h>
#include <src/Rendering/Buffers/VertexArray.h>
#include "Nodes/Node.h"
#include "Nodes/Text.h"
#include "Font/Font.h"
#include <msdf-atlas-gen/msdf-atlas-gen.h>
#include <memory>
#include <string>
namespace NuakeUI
{
class Renderer
{
public:
static Renderer& Get() {
static Renderer instance;
return instance;
}
void SetViewportSize(const Vector2& size);
void BeginDraw();
void DrawNode(std::shared_ptr<Node> node, int z);
void DrawString(const std::string& string, NodeStyle& nodeStyle, std::shared_ptr<Font> font = mDefaultFont, Vector3 position = Vector3());
void DrawChar(std::shared_ptr<Font> font, int letter);
void DrawRect();
void ReloadShaders();
static std::shared_ptr<Font> mDefaultFont;
private:
Vector2 mSize;
Matrix4 mView;
Renderer();
~Renderer() = default;
std::shared_ptr<Shader> mShader;
std::shared_ptr<Shader> mSDFShader;
std::shared_ptr<VertexArray> mVertexArray;
std::shared_ptr<VertexBuffer> mVertexBuffer;
};
}

View File

@@ -0,0 +1,56 @@
#include "StringHelper.h"
#include <sstream>
#include <iostream>
namespace NuakeUI::StringHelper
{
std::vector<std::string> Split(std::string string, const char delimiter)
{
auto splittedString = std::vector<std::string>();
std::stringstream ss(string);
std::string element;
while (getline(ss, element, delimiter))
{
splittedString.push_back(element);
}
return splittedString;
}
std::string RemoveChar(std::string string, char character)
{
// remove space from string
string.erase(std::remove(string.begin(), string.end(), character), string.end());
return string;
}
std::vector<std::string> Split(std::string s, const std::string& delimiter)
{
auto splittedString = std::vector<std::string>();
std::vector<std::string> splits;
size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
splits.push_back(token);
s.erase(0, pos + delimiter.length());
}
splits.push_back(s);
return splits;
}
bool StartsWith(const std::string& str, const std::string& start)
{
return str.size() >= start.size() && 0 == str.compare(0, start.size(), start);
}
bool EndsWith(const std::string& str, const std::string& end)
{
return str.size() >= end.size() && 0 == str.compare(str.size() - end.size(), end.size(), end);
}
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <string>
#include <vector>
namespace NuakeUI
{
namespace StringHelper
{
/// <summary>
/// Splits a string into a vector of substrings.
/// </summary>
/// <param name="string">The string to be split</param>
/// <param name="delimiter">The token</param>
/// <returns></returns>
std::vector<std::string> Split(std::string string, const char delimiter);
std::string RemoveChar(std::string string, char character);
std::vector<std::string> Split(std::string s, const std::string& delimiter);
bool StartsWith(const std::string& str, const std::string& start);
bool EndsWith(const std::string& str, const std::string& end);
}
}

View File

@@ -0,0 +1,6 @@
#pragma once
namespace NuakeUI
{
}

View File

@@ -0,0 +1,6 @@
#include "StyleSheet.h"
namespace NuakeUI
{
}

View File

@@ -0,0 +1,139 @@
#pragma once
#include "../Nodes/NodeState.h"
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <src/Core/Maths.h>
using namespace Nuake;
namespace NuakeUI
{
enum class StyleProperties {
None, Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight,
Top, Bottom, Left, Right,
PaddingLeft, PaddingTop, PaddingRight, PaddingBottom,
MarginLeft, MarginTop, MarginRight, MarginBottom,
Position, AlignItems, SelfAlign,
AspectRatio, FlexDirection, FlexWrap, FlexBasis, FlexGrow, FlexShrink,
JustifyContent, AlignContent, LayoutDirection,
BorderSize, BorderRadius, BorderColor,
BackgroundColor, TextAlign, Color, Overflow, FontSize, Visibility, ZIndex,
BackgroundImage
};
enum class PositionType { Relative, Absolute };
enum class AlignItemsType { Auto, FlexStart, Center, FlexEnd, Stretch, Baseline, SpaceBetween, SpaceAround };
enum class FlexWrapType { NoWrap, Wrap, WrapReversed };
enum class JustifyContentType { FlexStart, FlexEnd, Center, SpaceBetween, SpaceAround, SpaceEvenly };
enum class FlexDirectionType { Row = 0, Column, RowReversed, ColumnReversed };
enum class AlignContentType { FlexStart, FlexEnd, Stretch, Center, SpaceBetween, SpaceAround };
enum class LayoutDirectionType { LTR = 2, RTL = 3 };
enum class TextAlignType
{
Left, Center, Right
};
enum class OverflowType { Show, Hidden, Scroll };
enum class VisibilityType {Show, Hidden};
// Style Values
enum class PropValueType { Pixel , Percent, Auto, Color, Enum, String };
union Value
{
float Number;
Color Color;
int Enum;
};
struct PropValue
{
PropValueType type;
Value value;
std::string string;
PropValue()
{
}
PropValue(PropValueType t, float f)
{
type = t;
value.Number = f;
}
PropValue(int i)
{
type = PropValueType::Enum;
value.Enum = i;
}
PropValue(Color c)
{
type = PropValueType::Color;
value.Color = c;
}
};
// Selector
enum class StyleSelectorType { Id, Class, Tag, Pseudo };
struct StyleSelector
{
StyleSelectorType Type;
std::string Value;
};
class StyleRule
{
public:
std::vector<StyleSelector> Selector;
std::map<StyleProperties, PropValue> Properties;
StyleRule(std::vector<StyleSelector> selector) : Selector(selector)
{
Properties = std::map<StyleProperties, PropValue>();
}
void SetProp(StyleProperties prop, PropValue value)
{
Properties[prop] = value;
}
PropValue GetProp(StyleProperties prop)
{
if (HasProp(prop))
return Properties[prop];
return PropValue();
}
bool HasProp(StyleProperties prop)
{
return Properties.find(prop) != Properties.end();
}
};
class StyleSheet;
typedef std::shared_ptr<StyleSheet> StyleSheetPtr;
class StyleSheet
{
public:
std::vector<StyleRule> Rules;
static StyleSheetPtr New()
{
return std::make_shared<StyleSheet>();
}
StyleSheet() = default;
~StyleSheet() = default;
};
}

View File

@@ -0,0 +1,3 @@
#include "UIInputManager.h"
using namespace Nuake;

View File

@@ -0,0 +1,89 @@
#pragma once
#include "InputManager.h"
#include <src/Window.h>
#include <iostream>
#include <GLFW/glfw3.h>
namespace Nuake
{
class MyInputManager : public NuakeUI::InputManager
{
public:
MyInputManager(Window& window)
{
mWindow = window.GetHandle();
glfwSetScrollCallback(mWindow, MyInputManager::scroll_callback);
glfwSetCharCallback(mWindow, MyInputManager::char_callback);
glfwSetKeyCallback(mWindow, MyInputManager::key_callback);
}
bool IsMouseInputDown() override
{
auto state = glfwGetMouseButton(mWindow, GLFW_MOUSE_BUTTON_1);
return state == GLFW_PRESS;
}
bool IsKeyPressed(uint32_t key) override
{
auto states = glfwGetKey(mWindow, key);
return states == GLFW_PRESS;
}
float GetMouseX() override
{
double xpos, ypos;
glfwGetCursorPos(mWindow, &xpos, &ypos);
return (float)xpos;
}
float GetMouseY() override
{
double xpos, ypos;
glfwGetCursorPos(mWindow, &xpos, &ypos);
return (float)ypos;
}
float GetScrollX() override
{
return ScrollX;
}
float GetScrollY() override
{
return ScrollY;
}
static void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
ScrollX = (float)xoffset;
ScrollY = (float)yoffset;
}
static void char_callback(GLFWwindow* window, unsigned int codepoint)
{
char c[5] = { 0x00,0x00,0x00,0x00,0x00 };
if (codepoint <= 0x7F) { c[0] = codepoint; }
else if (codepoint <= 0x7FF) { c[0] = (codepoint >> 6) + 192; c[1] = (codepoint & 63) + 128; }
else if (0xd800 <= codepoint && codepoint <= 0xdfff) {} //invalid block of utf8
else if (codepoint <= 0xFFFF) { c[0] = (codepoint >> 12) + 224; c[1] = ((codepoint >> 6) & 63) + 128; c[2] = (codepoint & 63) + 128; }
else if (codepoint <= 0x10FFFF) { c[0] = (codepoint >> 18) + 240; c[1] = ((codepoint >> 12) & 63) + 128; c[2] = ((codepoint >> 6) & 63) + 128; c[3] = (codepoint & 63) + 128; }
InputStack.push(c);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_BACKSPACE && (action == GLFW_REPEAT || action == GLFW_PRESS))
{
InputStack.push("_backspace");
}
}
private:
GLFWwindow* mWindow;
};
}

View File

@@ -0,0 +1,236 @@
//
// foundation.c
// Katana
//
// Created by QFish on 3/19/15.
// Copyright (c) 2015 QFish. All rights reserved.
//
#include "foundation.h"
#include "parser.h"
#include <string.h>
#include <stdbool.h>
#include <assert.h>
//#undef assert
//#define assert(x)
struct KatanaInternalParser;
const KatanaParserString kKatanaAsteriskString = {"*", 1};
static const size_t kDefaultStringBufferSize = 12;
static void maybe_resize_string(struct KatanaInternalParser* parser,
size_t additional_chars,
KatanaParserString* str) {
size_t new_length = str->length + additional_chars;
size_t new_capacity = str->capacity;
while (new_capacity < new_length) {
new_capacity *= 2;
}
if (new_capacity != str->capacity) {
char* new_data = katana_parser_allocate(parser, new_capacity);
memset(new_data, 0, str->length);
memcpy(new_data, str->data, str->length);
katana_parser_deallocate(parser, str->data);
str->data = new_data;
str->capacity = new_capacity;
}
}
void katana_string_init(struct KatanaInternalParser* parser,
KatanaParserString* output) {
output->data = katana_parser_allocate(parser, kDefaultStringBufferSize);
memset( output->data, 0, sizeof(kDefaultStringBufferSize) );
output->length = 0;
output->capacity = kDefaultStringBufferSize;
}
void katana_string_append_characters(struct KatanaInternalParser* parser,
const char* str, KatanaParserString* output)
{
size_t len = strlen(str);
maybe_resize_string(parser, len, output);
memcpy(output->data + output->length, str, len);
output->length += len;
}
void katana_string_prepend_characters(struct KatanaInternalParser* parser,
const char* str,
KatanaParserString* output)
{
size_t len = strlen(str);
size_t new_length = output->length + len;
char* new_data = katana_parser_allocate(parser, new_length);
memcpy(new_data, str, len);
memcpy(new_data+len, output->data, output->length);
katana_parser_deallocate(parser, output->data);
output->data = new_data;
output->length = new_length;
output->capacity = new_length;
}
void katana_string_append_string(struct KatanaInternalParser* parser,
KatanaParserString* str,
KatanaParserString* output) {
maybe_resize_string(parser, str->length, output);
memcpy(output->data + output->length, str->data, str->length);
output->length += str->length;
}
bool katana_string_has_prefix(const char* str, const char* prefix)
{
size_t pre_len = strlen(prefix);
size_t str_len = strlen(str);
return pre_len <= str_len && stricmp(prefix, str, pre_len);
}
void katana_string_to_lowercase(struct KatanaInternalParser* parser,
KatanaParserString* str)
{
if ( !str )
return;
// FIXME: @(QFish) the char* in string piece is const, to find a better way
char *c = (char*)str->data;
for (int i=0; i < str->length; i++) {
*c = tolower(*c);
c++;
}
}
const char* katana_string_to_characters(struct KatanaInternalParser * parser, const KatanaParserString* str)
{
assert(NULL != str);
if (NULL == str)
return NULL;
char* buffer = katana_parser_allocate(parser, sizeof(char) * (str->length + 1));
memcpy(buffer, str->data, str->length);
buffer[str->length] = '\0';
return buffer;
}
const char* katana_string_to_characters_with_prefix_char(struct KatanaInternalParser * parser, const KatanaParserString* str, const char prefix)
{
assert(str);
if (NULL == str)
return NULL;
char* buffer = katana_parser_allocate(parser, sizeof(char) * (str->length + 2));
memcpy((buffer + 1), str->data, str->length);
buffer[0] = prefix;
buffer[str->length] = '\0';
return buffer;
}
/**
* Array
*/
void katana_array_init(struct KatanaInternalParser* parser,
size_t initial_capacity, KatanaArray* array) {
array->length = 0;
array->capacity = (unsigned int)initial_capacity;
if (initial_capacity > 0) {
array->data = katana_parser_allocate(parser, sizeof(void*) * initial_capacity);
} else {
array->data = NULL;
}
}
void katana_array_destroy(struct KatanaInternalParser* parser,
KatanaArray* array) {
if (array->capacity > 0) {
katana_parser_deallocate(parser, array->data);
}
}
static void enlarge_array_if_full(struct KatanaInternalParser* parser,
KatanaArray* array) {
if (array->length >= array->capacity) {
if (array->capacity) {
size_t old_num_bytes = sizeof(void*) * array->capacity;
array->capacity *= 2;
size_t num_bytes = sizeof(void*) * array->capacity;
void** temp = katana_parser_allocate(parser, num_bytes);
memcpy(temp, array->data, old_num_bytes);
katana_parser_deallocate(parser, array->data);
array->data = temp;
} else {
// 0-capacity array; no previous array to deallocate.
array->capacity = 2;
array->data = katana_parser_allocate(parser, sizeof(void*) * array->capacity);
}
}
}
void katana_array_add(struct KatanaInternalParser* parser,
void* element, KatanaArray* array) {
enlarge_array_if_full(parser, array);
assert(array->data);
assert(array->length < array->capacity);
array->data[array->length++] = element;
}
void* katana_array_pop(struct KatanaInternalParser* parser,
KatanaArray* array) {
if (array->length == 0) {
return NULL;
}
return array->data[--array->length];
}
int katana_array_index_of(KatanaArray* array, void* element) {
for (int i = 0; i < array->length; ++i) {
if (array->data[i] == element) {
return i;
}
}
return -1;
}
void katana_array_insert_at(struct KatanaInternalParser* parser,
void* element, int index,
KatanaArray* array) {
assert(index >= 0);
assert(index <= array->length);
enlarge_array_if_full(parser, array);
++array->length;
memmove(&array->data[index + 1], &array->data[index],
sizeof(void*) * (array->length - index - 1));
array->data[index] = element;
}
void katana_array_remove(struct KatanaInternalParser* parser,
void* node, KatanaArray* array) {
int index = katana_array_index_of(array, node);
if (index == -1) {
return;
}
katana_array_remove_at(parser, index, array);
}
void* katana_array_remove_at(struct KatanaInternalParser* parser,
int index, KatanaArray* array) {
assert(index >= 0);
assert(index < array->length);
void* result = array->data[index];
memmove(&array->data[index], &array->data[index + 1],
sizeof(void*) * (array->length - index - 1));
--array->length;
return result;
}
/**
* An alloc / free method
*/
void* katana_parser_allocate(struct KatanaInternalParser* parser, size_t size) {
return parser->options->allocator(parser->options->userdata, size);
}
void katana_parser_deallocate(struct KatanaInternalParser* parser, void* ptr) {
parser->options->deallocator(parser->options->userdata, ptr);
}

View File

@@ -0,0 +1,129 @@
/**
* Copyright (c) 2015 QFish <im@qfi.sh>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __Katana__foundation__
#define __Katana__foundation__
#include <stdio.h>
#include <ctype.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "katana.h"
struct KatanaInternalParser;
/**
* Positon, for error debug
*/
typedef struct {
unsigned int line;
unsigned int column;
unsigned int offset;
} KatanaSourcePosition;
/**
* String
*/
typedef struct {
char* data;
size_t length;
size_t capacity;
} KatanaParserString;
extern const KatanaParserString kKatanaAsteriskString;
void katana_string_to_lowercase(struct KatanaInternalParser* parser, KatanaParserString* string);
// Initializes a new KatanaParserString.
void katana_string_init(struct KatanaInternalParser* parser, KatanaParserString* output);
// Appends some characters onto the end of the KatanaParserString.
void katana_string_append_characters(struct KatanaInternalParser* parser, const char* str, KatanaParserString* output);
// Prepends some characters at the start of the KatanaParserString.
void katana_string_prepend_characters(struct KatanaInternalParser* parser, const char* str, KatanaParserString* output);
// Transforms a KatanaParserString to characters.
const char* katana_string_to_characters(struct KatanaInternalParser * parser, const KatanaParserString* str);
// Transforms a KatanaParserString to characters with a char prepended at the start of the KatanaParserString.
const char* katana_string_to_characters_with_prefix_char(struct KatanaInternalParser * parser, const KatanaParserString* str, const char prefix);
// Appends a string onto the end of the KatanaParserString.
void katana_string_append_string(struct KatanaInternalParser* parser, KatanaParserString* str, KatanaParserString* output);
// Returns a bool value that indicates whether a given string matches the beginning characters of the receiver.
bool katana_string_has_prefix(const char* str, const char* prefix);
/**
* Number
*/
typedef struct {
KatanaParserString raw;
double val;
} KatanaParserNumber;
/**
* Array
*/
// Initializes a new KatanaArray with the specified initial capacity.
void katana_array_init(struct KatanaInternalParser* parser, size_t initial_capacity,
KatanaArray* array);
// Frees the memory used by an KatanaArray. Does not free the contained
// pointers, but you should free the pointers if necessary.
void katana_array_destroy(struct KatanaInternalParser* parser, KatanaArray* array);
// Adds a new element to an KatanaArray.
void katana_array_add(struct KatanaInternalParser* parser, void* element, KatanaArray* array);
// Removes and returns the element most recently added to the KatanaArray.
// Ownership is transferred to caller. Capacity is unchanged. If the array is
// empty, NULL is returned.
void* katana_array_pop(struct KatanaInternalParser* parser, KatanaArray* array);
// Inserts an element at a specific index. This is potentially O(N) time, but
// is necessary for some of the spec's behavior.
void katana_array_insert_at(struct KatanaInternalParser* parser, void* element, int index,
KatanaArray* array);
// Removes an element from the array, or does nothing if the element is not in
// the array.
void katana_array_remove(struct KatanaInternalParser* parser, void* element, KatanaArray* array);
// Removes and returns an element at a specific index. Note that this is
// potentially O(N) time and should be used sparingly.
void* katana_array_remove_at(struct KatanaInternalParser* parser, int index, KatanaArray* array);
/**
* An alloc / free method wrapper
*/
void* katana_parser_allocate(struct KatanaInternalParser* parser, size_t size);
void katana_parser_deallocate(struct KatanaInternalParser* parser, void* ptr);
#ifdef __cplusplus
}
#endif
#endif /* defined(__Katana__foundation__) */

View File

@@ -0,0 +1,549 @@
/**
* Copyright (c) 2015 QFish <im@qfi.sh>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// CSS Spec: http://www.w3.org/TR/css-syntax-3/
#ifndef __Katana__katana__
#define __Katana__katana__
#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define KATANA_ERROR_MESSAGE_SIZE 100
typedef enum {
KatanaRuleUnkown,
KatanaRuleStyle,
KatanaRuleImport,
KatanaRuleMedia,
KatanaRuleFontFace,
KatanaRuleSupports,
KatanaRuleKeyframes,
KatanaRuleCharset,
KatanaRuleHost,
} KatanaRuleType;
typedef enum {
KatanaMediaQueryRestrictorNone,
KatanaMediaQueryRestrictorOnly,
KatanaMediaQueryRestrictorNot,
} KatanaMediaQueryRestrictor;
typedef enum {
KatanaSelectorMatchUnknown = 0,
KatanaSelectorMatchTag, // Example: div
KatanaSelectorMatchId, // Example: #id
KatanaSelectorMatchClass, // example: .class
KatanaSelectorMatchPseudoClass, // Example: :nth-child(2)
KatanaSelectorMatchPseudoElement, // Example: ::first-line
KatanaSelectorMatchPagePseudoClass, // ??
KatanaSelectorMatchAttributeExact, // Example: E[foo="bar"]
KatanaSelectorMatchAttributeSet, // Example: E[foo]
KatanaSelectorMatchAttributeList, // Example: E[foo~="bar"]
KatanaSelectorMatchAttributeHyphen, // Example: E[foo|="bar"]
KatanaSelectorMatchAttributeContain, // css3: E[foo*="bar"]
KatanaSelectorMatchAttributeBegin, // css3: E[foo^="bar"]
KatanaSelectorMatchAttributeEnd, // css3: E[foo$="bar"]
KatanaSelectorMatchFirstAttribute = KatanaSelectorMatchAttributeExact,
} KatanaSelectorMatch;
typedef enum {
KatanaSelectorRelationSubSelector, // "No space" combinator
KatanaSelectorRelationDescendant, // "Space" combinator
KatanaSelectorRelationChild, // > combinator
KatanaSelectorRelationDirectAdjacent, // + combinator
KatanaSelectorRelationIndirectAdjacent, // ~ combinator
KatanaSelectorRelationShadowPseudo, // Special case of shadow DOM pseudo elements / shadow pseudo element
KatanaSelectorRelationShadowDeep // /shadow-deep/ combinator
} KatanaSelectorRelation;
typedef enum {
KatanaPseudoNotParsed,
KatanaPseudoUnknown,
KatanaPseudoEmpty,
KatanaPseudoFirstChild,
KatanaPseudoFirstOfType,
KatanaPseudoLastChild,
KatanaPseudoLastOfType,
KatanaPseudoOnlyChild,
KatanaPseudoOnlyOfType,
KatanaPseudoFirstLine,
KatanaPseudoFirstLetter,
KatanaPseudoNthChild,
KatanaPseudoNthOfType,
KatanaPseudoNthLastChild,
KatanaPseudoNthLastOfType,
KatanaPseudoLink,
KatanaPseudoVisited,
KatanaPseudoAny,
KatanaPseudoAnyLink,
KatanaPseudoAutofill,
KatanaPseudoHover,
KatanaPseudoDrag,
KatanaPseudoFocus,
KatanaPseudoActive,
KatanaPseudoChecked,
KatanaPseudoEnabled,
KatanaPseudoFullPageMedia,
KatanaPseudoDefault,
KatanaPseudoDisabled,
KatanaPseudoOptional,
KatanaPseudoRequired,
KatanaPseudoReadOnly,
KatanaPseudoReadWrite,
KatanaPseudoValid,
KatanaPseudoInvalid,
KatanaPseudoIndeterminate,
KatanaPseudoTarget,
KatanaPseudoBefore,
KatanaPseudoAfter,
KatanaPseudoBackdrop,
KatanaPseudoLang,
KatanaPseudoNot, // :not(selector), selector is Kind of KatanaSelector
KatanaPseudoResizer,
KatanaPseudoRoot,
KatanaPseudoScope,
KatanaPseudoScrollbar,
KatanaPseudoScrollbarButton,
KatanaPseudoScrollbarCorner,
KatanaPseudoScrollbarThumb,
KatanaPseudoScrollbarTrack,
KatanaPseudoScrollbarTrackPiece,
KatanaPseudoWindowInactive,
KatanaPseudoCornerPresent,
KatanaPseudoDecrement,
KatanaPseudoIncrement,
KatanaPseudoHorizontal,
KatanaPseudoVertical,
KatanaPseudoStart,
KatanaPseudoEnd,
KatanaPseudoDoubleButton,
KatanaPseudoSingleButton,
KatanaPseudoNoButton,
KatanaPseudoSelection,
KatanaPseudoLeftPage,
KatanaPseudoRightPage,
KatanaPseudoFirstPage,
KatanaPseudoFullScreen,
KatanaPseudoFullScreenDocument,
KatanaPseudoFullScreenAncestor,
KatanaPseudoInRange,
KatanaPseudoOutOfRange,
KatanaPseudoWebKitCustomElement,
KatanaPseudoCue,
KatanaPseudoFutureCue,
KatanaPseudoPastCue,
KatanaPseudoUnresolved,
KatanaPseudoContent,
KatanaPseudoHost,
KatanaPseudoHostContext,
KatanaPseudoShadow,
KatanaPseudoSpatialNavigationFocus,
KatanaPseudoListBox
} KatanaPseudoType;
typedef enum {
KatanaAttributeMatchTypeCaseSensitive,
KatanaAttributeMatchTypeCaseInsensitive,
} KatanaAttributeMatchType;
typedef enum {
KATANA_VALUE_UNKNOWN = 0,
KATANA_VALUE_NUMBER = 1,
KATANA_VALUE_PERCENTAGE = 2,
KATANA_VALUE_EMS = 3,
KATANA_VALUE_EXS = 4,
// double
KATANA_VALUE_PX = 5,
KATANA_VALUE_CM = 6,
KATANA_VALUE_MM = 7,
KATANA_VALUE_IN = 8,
KATANA_VALUE_PT = 9,
KATANA_VALUE_PC = 10,
KATANA_VALUE_DEG = 11,
KATANA_VALUE_RAD = 12,
KATANA_VALUE_GRAD = 13,
KATANA_VALUE_MS = 14,
KATANA_VALUE_S = 15,
KATANA_VALUE_HZ = 16,
KATANA_VALUE_KHZ = 17,
KATANA_VALUE_DIMENSION = 18,
KATANA_VALUE_STRING = 19,
KATANA_VALUE_URI = 20,
KATANA_VALUE_IDENT = 21,
KATANA_VALUE_ATTR = 22,
KATANA_VALUE_COUNTER = 23,
KATANA_VALUE_RECT = 24,
KATANA_VALUE_RGBCOLOR = 25,
KATANA_VALUE_VW = 26,
KATANA_VALUE_VH = 27,
KATANA_VALUE_VMIN = 28,
KATANA_VALUE_VMAX = 29,
KATANA_VALUE_DPPX = 30,
KATANA_VALUE_DPI = 31,
KATANA_VALUE_DPCM = 32,
KATANA_VALUE_FR = 33,
KATANA_VALUE_UNICODE_RANGE = 102,
KATANA_VALUE_PARSER_OPERATOR = 103,
KATANA_VALUE_PARSER_INTEGER = 104,
KATANA_VALUE_PARSER_HEXCOLOR = 105,
KATANA_VALUE_PARSER_FUNCTION = 0x100001,
KATANA_VALUE_PARSER_LIST = 0x100002,
KATANA_VALUE_PARSER_Q_EMS = 0x100003,
KATANA_VALUE_PARSER_IDENTIFIER = 106,
KATANA_VALUE_TURN = 107,
KATANA_VALUE_REMS = 108,
KATANA_VALUE_CHS = 109,
KATANA_VALUE_COUNTER_NAME = 110,
KATANA_VALUE_SHAPE = 111,
KATANA_VALUE_QUAD = 112,
KATANA_VALUE_CALC = 113,
KATANA_VALUE_CALC_PERCENTAGE_WITH_NUMBER = 114,
KATANA_VALUE_CALC_PERCENTAGE_WITH_LENGTH = 115,
KATANA_VALUE_VARIABLE_NAME = 116,
KATANA_VALUE_PROPERTY_ID = 117,
KATANA_VALUE_VALUE_ID = 118
} KatanaValueUnit;
//typedef enum {
// KATANA_VALUE_PARSER_OPERATOR = 0x100000,
// KATANA_VALUE_PARSER_FUNCTION = 0x100001,
// KATANA_VALUE_PARSER_LIST = 0x100002,
// KATANA_VALUE_PARSER_Q_EMS = 0x100003,
//} KatanaParserValueUnit;
typedef enum {
KatanaValueInvalid = 0,
KatanaValueInherit = 1,
KatanaValueInitial = 2,
KatanaValueNone = 3,
KatanaValueCustom = 0x100010,
} KatanaValueID;
typedef enum { KatanaParseError } KatanaErrorType;
typedef struct {
const char* local; // tag local name
const char* prefix; // namesapce identifier
const char* uri; // namesapce uri
} KatanaQualifiedName;
typedef struct {
/** Data elements. This points to a dynamically-allocated array of capacity
* elements, each a void* to the element itself, remember free each element.
*/
void** data;
/** Number of elements currently in the array. */
unsigned int length;
/** Current array capacity. */
unsigned int capacity;
} KatanaArray;
typedef struct {
const char* encoding;
KatanaArray /* KatanaRule */ rules;
KatanaArray /* KatanaImportRule */ imports;
} KatanaStylesheet;
typedef struct {
const char* name;
KatanaRuleType type;
} KatanaRule;
typedef struct {
KatanaRule base;
KatanaArray* /* KatanaSelector */ selectors;
KatanaArray* /* KatanaDeclaration */ declarations;
} KatanaStyleRule;
typedef struct {
const char* comment;
} KatanaComment; // unused for right
/**
* The `@font-face` at-rule.
*/
typedef struct {
KatanaRule base;
KatanaArray* /* KatanaDeclaration */ declarations;
} KatanaFontFaceRule;
/**
* The `@host` at-rule.
*/
typedef struct {
KatanaRule base;
KatanaArray* /* KatanaRule */ host;
} KatanaHostRule;
/**
* The `@import` at-rule.
*/
typedef struct {
KatanaRule base;
/**
* The part following `@import `
*/
const char* href;
/**
* The media list belonging to this import rule
*/
KatanaArray* /* KatanaMediaQuery* */ medias;
} KatanaImportRule;
/**
* The `@keyframes` at-rule.
* Spec: http://www.w3.org/TR/css3-animations/#keyframes
*/
typedef struct {
KatanaRule base;
/**
* The vendor prefix in `@keyframes`, or `undefined` if there is none.
*/
const char* name;
KatanaArray* /* KatanaKeyframe */ keyframes;
} KatanaKeyframesRule;
typedef struct {
KatanaArray* /* KatanaValue: `percentage`, `from`, `to` */ selectors;
KatanaArray* /* KatanaDeclaration */ declarations;
} KatanaKeyframe;
/**
* The `@media` at-rule.
*/
typedef struct {
KatanaRule base;
/**
* The part following `@media `
*/
KatanaArray* medias;
/**
* An `Array` of nodes with the types `rule`, `comment` and any of the
at-rule types.
*/
KatanaArray* /* KatanaRule */ rules;
} KatanaMediaRule;
/**
* Media Query Exp List
* Spec: http://www.w3.org/TR/mediaqueries-4/
*/
typedef struct {
KatanaMediaQueryRestrictor restrictor;
const char* type;
KatanaArray* expressions;
bool ignored;
} KatanaMediaQuery;
typedef struct {
const char* feature;
KatanaArray* values;
const char* raw;
} KatanaMediaQueryExp;
typedef struct {
const char* value;
union {
struct {
int a; // Used for :nth-*
int b; // Used for :nth-*
} nth;
KatanaAttributeMatchType attributeMatchType; // used for attribute selector (with value)
} bits;
KatanaQualifiedName* attribute;
const char* argument; // Used for :contains, :lang, :nth-*
KatanaArray* selectors; // Used for :any and :not
} KatanaSelectorRareData;
typedef struct KatanaSelector {
size_t specificity;
KatanaSelectorMatch match;
KatanaPseudoType pseudo;
KatanaSelectorRelation relation;
KatanaQualifiedName* tag;
KatanaSelectorRareData* data;
struct KatanaSelector* tagHistory;
} KatanaSelector;
unsigned katana_calc_specificity_for_selector(KatanaSelector* selector);
typedef struct {
// property name
const char* property;
// property value
KatanaArray* /* KatanaValue */ values;
const char* string;
// is this property marked important
bool important;
// origin css text of the property
const char* raw;
} KatanaDeclaration;
typedef struct {
const char* name;
KatanaArray* args;
} KatanaValueFunction;
typedef struct KatanaValue {
KatanaValueID id;
bool isInt;
union {
int iValue;
double fValue;
const char* string;
KatanaValueFunction* function;
KatanaArray* list;
};
KatanaValueUnit unit;
const char* raw;
} KatanaValue;
/**
* The `@charset` at-rule.
*/
typedef struct {
KatanaRule base;
/**
* The encoding information
*/
const char* encoding;
} KatanaCharsetRule;
typedef struct {
KatanaErrorType type;
int first_line;
int first_column;
int last_line;
int last_column;
char message[KATANA_ERROR_MESSAGE_SIZE];
} KatanaError;
// TODO: @document
// TODO: @page
// TODO: @supports
// TODO: custom-at-rule
/**
* Parser mode
*/
typedef enum KatanaParserMode {
// Normal CSS content used in External CSS files or Internal CSS, may include more than 1 css rules.
KatanaParserModeStylesheet,
// Single CSS rule like "@import", "selector{...}"
KatanaParserModeRule,
KatanaParserModeKeyframeRule,
KatanaParserModeKeyframeKeyList,
KatanaParserModeMediaList,
// CSS property value like "1px", "1em", "#eee"
KatanaParserModeValue,
// CSS selector like ".pages.active"
KatanaParserModeSelector,
// Inline stylesheet like "width: 20px; height: 20px;"
KatanaParserModeDeclarationList,
} KatanaParserMode;
typedef struct KatanaInternalOutput {
// Complete CSS string
KatanaStylesheet* stylesheet;
union {
// fragmental CSS string
KatanaRule* rule;
KatanaKeyframe* keyframe;
KatanaArray* keyframe_keys;
KatanaArray* values;
KatanaArray* medias;
KatanaArray* /* KatanaDeclaration */ declarations;
KatanaArray* selectors;
};
KatanaParserMode mode;
KatanaArray /* KatanaError */ errors;
} KatanaOutput;
/**
* Parse a complete or fragmental CSS string
*
* @param str Input CSS string
* @param len Length of the input CSS string
* @param mode Parser mode, depends on the input
*
* @return The result of parsing
*/
KatanaOutput* katana_parse(const char* str, size_t len, KatanaParserMode mode);
/**
* Parse a complete CSS file
*
* @param fp `FILE` point to the CSS file
*
* @return The result of parsing
*/
KatanaOutput* katana_parse_in(FILE* fp);
/**
* Free the output
*
* @param output The result of parsing
*/
void katana_destroy_output(KatanaOutput* output);
/**
* Print the formatted CSS string
*
* @param output The result of parsing
*
* @return The origin output
*/
KatanaOutput* katana_dump_output(KatanaOutput* output);
#ifdef __cplusplus
}
#endif
#endif /* defined(__Katana__katana__) */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,354 @@
#include "katana.tab.h"
/* Substitute the type names. */
#define YYSTYPE KATANASTYPE
#define YYLTYPE KATANALTYPE
#ifndef katanaHEADER_H
#define katanaHEADER_H 1
#define katanaIN_HEADER 1
// #line 6 "katana.lex.h"
#define YY_INT_ALIGNED short int
/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
#define YY_FLEX_SUBMINOR_VERSION 37
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
/* end standard C headers. */
/* flex integer type definitions */
#ifndef FLEXINT_H
#define FLEXINT_H
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
* if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
/* Limits of integral types. */
#ifndef INT8_MIN
#define INT8_MIN (-128)
#endif
#ifndef INT16_MIN
#define INT16_MIN (-32767-1)
#endif
#ifndef INT32_MIN
#define INT32_MIN (-2147483647-1)
#endif
#ifndef INT8_MAX
#define INT8_MAX (127)
#endif
#ifndef INT16_MAX
#define INT16_MAX (32767)
#endif
#ifndef INT32_MAX
#define INT32_MAX (2147483647)
#endif
#ifndef UINT8_MAX
#define UINT8_MAX (255U)
#endif
#ifndef UINT16_MAX
#define UINT16_MAX (65535U)
#endif
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST
#else /* ! __cplusplus */
/* C99 requires __STDC__ to be defined as 1. */
#if defined (__STDC__)
#define YY_USE_CONST
#endif /* defined (__STDC__) */
#endif /* ! __cplusplus */
#ifdef YY_USE_CONST
#define yyconst const
#else
#define yyconst
#endif
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
/* For convenience, these vars (plus the bison vars far below)
are macros in the reentrant scanner. */
#define yyin yyg->yyin_r
#define yyout yyg->yyout_r
#define yyextra yyg->yyextra_r
#define yyleng yyg->yyleng_r
#define yytext yyg->yytext_r
#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
#define yy_flex_debug yyg->yy_flex_debug_r
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
#define YY_BUF_SIZE 16384
#endif
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
{
FILE *yy_input_file;
char *yy_ch_buf; /* input buffer */
char *yy_buf_pos; /* current position in input buffer */
/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
yy_size_t yy_buf_size;
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
yy_size_t yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
* delete it.
*/
int yy_is_our_buffer;
/* Whether this is an "interactive" input source; if so, and
* if we're using stdio for input, then we want to use getc()
* instead of fread(), to make sure we stop fetching input after
* each newline.
*/
int yy_is_interactive;
/* Whether we're considered to be at the beginning of a line.
* If so, '^' rules will be active on the next match, otherwise
* not.
*/
int yy_at_bol;
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;
int yy_buffer_status;
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
void katanarestart (FILE *input_file ,yyscan_t yyscanner );
void katana_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
YY_BUFFER_STATE katana_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
void katana_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
void katana_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
void katanapush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
void katanapop_buffer_state (yyscan_t yyscanner );
YY_BUFFER_STATE katana_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
YY_BUFFER_STATE katana_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
YY_BUFFER_STATE katana_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
void *katanaalloc (yy_size_t ,yyscan_t yyscanner );
void *katanarealloc (void *,yy_size_t ,yyscan_t yyscanner );
void katanafree (void * ,yyscan_t yyscanner );
/* Begin user sect3 */
#define katanawrap(yyscanner) 1
#define YY_SKIP_YYWRAP
#define yytext_ptr yytext_r
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
#define INITIAL 0
#define mediaquery 1
#define supports 2
#endif
#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
* down here because we want the user's section 1 to have been scanned first.
* The user has a chance to override it with an option.
*/
#endif
#ifndef YY_EXTRA_TYPE
#define YY_EXTRA_TYPE void *
#endif
int katanalex_init (yyscan_t* scanner);
int katanalex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
int katanalex_destroy (yyscan_t yyscanner );
int katanaget_debug (yyscan_t yyscanner );
void katanaset_debug (int debug_flag ,yyscan_t yyscanner );
YY_EXTRA_TYPE katanaget_extra (yyscan_t yyscanner );
void katanaset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
FILE *katanaget_in (yyscan_t yyscanner );
void katanaset_in (FILE * in_str ,yyscan_t yyscanner );
FILE *katanaget_out (yyscan_t yyscanner );
void katanaset_out (FILE * out_str ,yyscan_t yyscanner );
yy_size_t katanaget_leng (yyscan_t yyscanner );
char *katanaget_text (yyscan_t yyscanner );
int katanaget_lineno (yyscan_t yyscanner );
void katanaset_lineno (int line_number ,yyscan_t yyscanner );
int katanaget_column (yyscan_t yyscanner );
void katanaset_column (int column_no ,yyscan_t yyscanner );
YYSTYPE * katanaget_lval (yyscan_t yyscanner );
void katanaset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
YYLTYPE *katanaget_lloc (yyscan_t yyscanner );
void katanaset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int katanawrap (yyscan_t yyscanner );
#else
extern int katanawrap (yyscan_t yyscanner );
#endif
#endif
#ifndef yytext_ptr
static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
#endif
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#define YY_READ_BUF_SIZE 8192
#endif
/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
extern int katanalex \
(YYSTYPE* yylval_param, YYLTYPE* yylloc, yyscan_t yyscanner, void* parser);
#define YY_DECL int katanalex \
(YYSTYPE * yylval_param, YYLTYPE* yylloc, yyscan_t yyscanner, void* parser)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
//#undef YY_NEW_FILE
#undef YY_FLUSH_BUFFER
#undef yy_set_bol
#undef yy_new_buffer
#undef yy_set_interactive
//#undef YY_DO_BEFORE_ACTION
#ifdef YY_DECL_IS_OURS
#undef YY_DECL_IS_OURS
#undef YY_DECL
#endif
// #line 346 "katana.lex.h"
#undef katanaIN_HEADER
#endif /* katanaHEADER_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_KATANA_KATANA_TAB_H_INCLUDED
# define YY_KATANA_KATANA_TAB_H_INCLUDED
/* Debug traces. */
#ifndef KATANADEBUG
# if defined YYDEBUG
#if YYDEBUG
# define KATANADEBUG 1
# else
# define KATANADEBUG 0
# endif
# else /* ! defined YYDEBUG */
# define KATANADEBUG 1
# endif /* ! defined YYDEBUG */
#endif /* ! defined KATANADEBUG */
#if KATANADEBUG
extern int katanadebug;
#endif
/* "%code requires" blocks. */
/*
* Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
* Copyright (C) 2008 Eric Seidel <eric@webkit.org>
* Copyright (C) 2012 Intel Corporation. All rights reserved.
* Copyright (C) 2015 QFish (im@qfi.sh)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "foundation.h"
#include "katana.h"
/* Token type. */
#ifndef KATANATOKENTYPE
# define KATANATOKENTYPE
enum katanatokentype
{
TOKEN_EOF = 0,
LOWEST_PREC = 258,
UNIMPORTANT_TOK = 259,
KATANA_CSS_SGML_CD = 260,
KATANA_CSS_WHITESPACE = 261,
KATANA_CSS_INCLUDES = 262,
KATANA_CSS_DASHMATCH = 263,
KATANA_CSS_BEGINSWITH = 264,
KATANA_CSS_ENDSWITH = 265,
KATANA_CSS_CONTAINS = 266,
KATANA_CSS_STRING = 267,
KATANA_CSS_IDENT = 268,
KATANA_CSS_NTH = 269,
KATANA_CSS_HEX = 270,
KATANA_CSS_IDSEL = 271,
KATANA_CSS_IMPORT_SYM = 272,
KATANA_CSS_PAGE_SYM = 273,
KATANA_CSS_MEDIA_SYM = 274,
KATANA_CSS_SUPPORTS_SYM = 275,
KATANA_CSS_FONT_FACE_SYM = 276,
KATANA_CSS_CHARSET_SYM = 277,
KATANA_CSS_NAMESPACE_SYM = 278,
KATANA_INTERNAL_DECLS_SYM = 279,
KATANA_INTERNAL_MEDIALIST_SYM = 280,
KATANA_INTERNAL_RULE_SYM = 281,
KATANA_INTERNAL_SELECTOR_SYM = 282,
KATANA_INTERNAL_VALUE_SYM = 283,
KATANA_INTERNAL_KEYFRAME_RULE_SYM = 284,
KATANA_INTERNAL_KEYFRAME_KEY_LIST_SYM = 285,
KATANA_INTERNAL_SUPPORTS_CONDITION_SYM = 286,
KATANA_CSS_KEYFRAMES_SYM = 287,
KATANA_CSS_ATKEYWORD = 288,
KATANA_CSS_IMPORTANT_SYM = 289,
KATANA_CSS_MEDIA_NOT = 290,
KATANA_CSS_MEDIA_ONLY = 291,
KATANA_CSS_MEDIA_AND = 292,
KATANA_CSS_MEDIA_OR = 293,
KATANA_CSS_SUPPORTS_NOT = 294,
KATANA_CSS_SUPPORTS_AND = 295,
KATANA_CSS_SUPPORTS_OR = 296,
KATANA_CSS_REMS = 297,
KATANA_CSS_CHS = 298,
KATANA_CSS_QEMS = 299,
KATANA_CSS_EMS = 300,
KATANA_CSS_EXS = 301,
KATANA_CSS_PXS = 302,
KATANA_CSS_CMS = 303,
KATANA_CSS_MMS = 304,
KATANA_CSS_INS = 305,
KATANA_CSS_PTS = 306,
KATANA_CSS_PCS = 307,
KATANA_CSS_DEGS = 308,
KATANA_CSS_RADS = 309,
KATANA_CSS_GRADS = 310,
KATANA_CSS_TURNS = 311,
KATANA_CSS_MSECS = 312,
KATANA_CSS_SECS = 313,
KATANA_CSS_HERTZ = 314,
KATANA_CSS_KHERTZ = 315,
KATANA_CSS_DIMEN = 316,
KATANA_CSS_INVALIDDIMEN = 317,
KATANA_CSS_PERCENTAGE = 318,
KATANA_CSS_FLOATTOKEN = 319,
KATANA_CSS_INTEGER = 320,
KATANA_CSS_VW = 321,
KATANA_CSS_VH = 322,
KATANA_CSS_VMIN = 323,
KATANA_CSS_VMAX = 324,
KATANA_CSS_DPPX = 325,
KATANA_CSS_DPI = 326,
KATANA_CSS_DPCM = 327,
KATANA_CSS_FR = 328,
KATANA_CSS_URI = 329,
KATANA_CSS_FUNCTION = 330,
KATANA_CSS_ANYFUNCTION = 331,
KATANA_CSS_CUEFUNCTION = 332,
KATANA_CSS_NOTFUNCTION = 333,
KATANA_CSS_CALCFUNCTION = 334,
KATANA_CSS_MINFUNCTION = 335,
KATANA_CSS_MAXFUNCTION = 336,
KATANA_CSS_HOSTFUNCTION = 337,
KATANA_CSS_HOSTCONTEXTFUNCTION = 338,
KATANA_CSS_UNICODERANGE = 339
};
#endif
/* Value type. */
#if ! defined KATANASTYPE && ! defined KATANASTYPE_IS_DECLARED
union KATANASTYPE
{
bool boolean;
char character;
int integer;
KatanaParserNumber number;
KatanaParserString string;
KatanaRule* rule;
// The content of the three below HeapVectors are guaranteed to be kept alive by
// the corresponding parsedRules, floatingMediaQueryExpList, and parsedKeyFrames
// lists
KatanaArray* ruleList;
KatanaArray* mediaQueryExpList;
KatanaArray* keyframeRuleList;
KatanaSelector* selector;
KatanaArray* selectorList;
// CSSSelector::MarginBoxType marginBox;
KatanaSelectorRelation relation;
KatanaAttributeMatchType attributeMatchType;
KatanaArray* mediaList;
KatanaMediaQuery* mediaQuery;
KatanaMediaQueryRestrictor mediaQueryRestrictor;
KatanaMediaQueryExp* mediaQueryExp;
KatanaValue* value;
KatanaArray* valueList;
KatanaKeyframe* keyframe;
KatanaSourcePosition* location;
};
typedef union KATANASTYPE KATANASTYPE;
# define KATANASTYPE_IS_TRIVIAL 1
# define KATANASTYPE_IS_DECLARED 1
#endif
/* Location type. */
#if ! defined KATANALTYPE && ! defined KATANALTYPE_IS_DECLARED
typedef struct KATANALTYPE KATANALTYPE;
struct KATANALTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
};
# define KATANALTYPE_IS_DECLARED 1
# define KATANALTYPE_IS_TRIVIAL 1
#endif
int katanaparse (void* scanner, struct KatanaInternalParser * parser);
#endif /* !YY_KATANA_KATANA_TAB_H_INCLUDED */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,250 @@
/**
* Copyright (c) 2015 QFish <im@qfi.sh>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __Katana__parser__
#define __Katana__parser__
#include <stdio.h>
#include <stdlib.h>
#include "katana.lex.h"
#ifdef __cplusplus
extern "C" {
#endif
#define KATANA_FELX_DEBUG 0
#define KATANA_BISON_DEBUG 0
#define KATANA_PARSER_DEBUG 0
#define KATANA_PARSER_LOG_ENABLE 0
struct KatanaInternalOutput;
struct KatanaInternalOptions;
typedef void* (*KatanaAllocatorFunction)(void* userdata, size_t size);
typedef void (*KatanaDeallocatorFunction)(void* userdata, void* ptr);
typedef struct KatanaInternalOptions {
KatanaAllocatorFunction allocator;
KatanaDeallocatorFunction deallocator;
void* userdata;
} KatanaOptions;
extern const KatanaOptions kKatanaDefaultOptions;
typedef struct KatanaInternalParser {
// Settings for this parse run.
const struct KatanaInternalOptions* options;
// Output for the parse.
struct KatanaInternalOutput* output;
// The flex tokenizer info
yyscan_t* scanner;
// The floating declarations
KatanaArray* parsed_declarations;
#if KATANA_PARSER_DEBUG
// The floating selectors
KatanaArray* parsed_selectors;
#endif // #if KATANA_PARSER_DEBUG
KatanaSourcePosition* position;
KatanaParserString default_namespace;
} KatanaParser;
KatanaArray* katana_new_array(KatanaParser* parser);
KatanaStylesheet* katana_new_stylesheet(KatanaParser* parser);
void katana_parser_reset_declarations(KatanaParser* parser);
void katana_add_namespace(KatanaParser* parser, KatanaParserString* prefix, KatanaParserString* uri);
KatanaRule* katana_new_font_face(KatanaParser* parser);
KatanaRule* katana_new_keyframes_rule(KatanaParser* parser, KatanaParserString* name, KatanaArray* keyframes, bool isPrefixed);
KatanaKeyframe* katana_new_keyframe(KatanaParser* parser, KatanaArray* selectors);
KatanaArray* katana_new_Keyframe_list(KatanaParser* parser);
void katana_keyframe_rule_list_add(KatanaParser* parser, KatanaKeyframe* keyframe, KatanaArray* list);
void katana_parser_clear_keyframes(KatanaParser* parser, KatanaArray* keyframes);
void katana_set_charset(KatanaParser* parser, KatanaParserString* charset);
KatanaRule* katana_new_import_rule(KatanaParser* parser, KatanaParserString* href, KatanaArray* media);
KatanaValue* katana_new_value(KatanaParser* parser);
KatanaValue* katana_new_dimension_value(KatanaParser* parser, KatanaParserNumber* value, KatanaValueUnit unit);
KatanaValue* katana_new_number_value(KatanaParser* parser, int sign, KatanaParserNumber* value, KatanaValueUnit unit);
KatanaValue* katana_new_operator_value(KatanaParser* parser, int value);
KatanaValue* katana_new_ident_value(KatanaParser* parser, KatanaParserString* value);
KatanaValue* katana_new_function_value(KatanaParser* parser, KatanaParserString* name, KatanaArray* args);
KatanaValue* katana_new_list_value(KatanaParser* parser, KatanaArray* list);
void katana_value_set_string(KatanaParser* parser, KatanaValue* value, KatanaParserString* string);
void katana_value_set_sign(KatanaParser* parser, KatanaValue* value, int sign);
KatanaArray* katana_new_value_list(KatanaParser* parser);
void katana_value_list_add(KatanaParser* parser, KatanaValue* value, KatanaArray* list);
void katana_value_list_insert(KatanaParser* parser, KatanaValue* value, int index, KatanaArray* list);
void katana_value_list_steal_values(KatanaParser* parser, KatanaArray* values, KatanaArray* list);
KatanaRule* katana_new_media_rule(KatanaParser* parser, KatanaArray* medias, KatanaArray* rules);
KatanaArray* katana_new_media_list(KatanaParser* parser);
void katana_media_list_add(KatanaParser* parser, KatanaMediaQuery* media_query, KatanaArray* medias);
KatanaMediaQuery* katana_new_media_query(KatanaParser* parser, KatanaMediaQueryRestrictor r, KatanaParserString *type, KatanaArray* exps);
// i.e. (min-width: 960px)
KatanaMediaQueryExp * katana_new_media_query_exp(KatanaParser* parser, KatanaParserString* feature, KatanaArray* values);
KatanaArray* katana_new_media_query_exp_list(KatanaParser* parser);
void katana_media_query_exp_list_add(KatanaParser* parser, KatanaMediaQueryExp* exp, KatanaArray* list);
KatanaArray* katana_new_rule_list(KatanaParser* parser);
KatanaArray* katana_rule_list_add(KatanaParser* parser, KatanaRule* rule, KatanaArray* rule_list);
KatanaRule* katana_new_style_rule(KatanaParser* parser, KatanaArray* selectors);
void katana_start_declaration(KatanaParser* parser);
void katana_end_declaration(KatanaParser* parser, bool flag, bool ended);
void katana_set_current_declaration(KatanaParser* parser, KatanaParserString* tag);
bool katana_new_declaration(KatanaParser* parser, KatanaParserString* name, bool important, KatanaArray* values);
void katana_parser_clear_declarations(KatanaParser* parser);
void katana_start_selector(KatanaParser* parser);
void katana_end_selector(KatanaParser* parser);
KatanaQualifiedName * katana_new_qualified_name(KatanaParser* parser, KatanaParserString* prefix, KatanaParserString* localName, KatanaParserString* uri);
KatanaSelector* katana_new_selector(KatanaParser* parser);
KatanaSelector* katana_sink_floating_selector(KatanaParser* parser, KatanaSelector* selector);
KatanaSelector* katana_rewrite_specifier_with_element_name(KatanaParser* parser, KatanaParserString* tag, KatanaSelector* specifier);
KatanaSelector* katana_rewrite_specifier_with_namespace_if_needed(KatanaParser* parser, KatanaSelector* specifier);
KatanaSelector* katana_rewrite_specifiers(KatanaParser* parser, KatanaSelector* specifiers, KatanaSelector* newSpecifier);
void katana_adopt_selector_list(KatanaParser* parser, KatanaArray* selectors, KatanaSelector* selector);
void katana_selector_append(KatanaParser* parser, KatanaSelector* selector, KatanaSelector* new_selector, KatanaSelectorRelation relation);
void katana_selector_insert(KatanaParser* parser, KatanaSelector* selector, KatanaSelector* new_selector, KatanaSelectorRelation before, KatanaSelectorRelation after);
void katana_selector_prepend_with_element_name(KatanaParser* parser, KatanaSelector* selector, KatanaParserString* tag);
KatanaArray* katana_new_selector_list(KatanaParser* parser);
KatanaArray* katana_reusable_selector_list(KatanaParser* parser);
void katana_selector_list_shink(KatanaParser* parser, int capacity, KatanaArray* list);
void katana_selector_list_add(KatanaParser* parser, KatanaSelector* selector, KatanaArray* list);
void katana_selector_set_value(KatanaParser* parser, KatanaSelector* selector, KatanaParserString* value);
void katana_selector_set_argument(KatanaParser* parser, KatanaSelector* selector, KatanaParserString* argument);
void katana_selector_set_argument_with_number(KatanaParser* parser, KatanaSelector* selector, int sign, KatanaParserNumber* value);
bool katana_parse_attribute_match_type(KatanaParser* parser, KatanaAttributeMatchType, KatanaParserString* attr);
bool katana_selector_is_simple(KatanaParser* parser, KatanaSelector* selector);
void katana_selector_extract_pseudo_type(KatanaSelector* selector);
void katana_add_rule(KatanaParser* parser, KatanaRule* rule);
void katana_start_rule(KatanaParser* parser);
void katana_end_rule(KatanaParser* parser, bool ended);
void katana_start_rule_header(KatanaParser* parser, KatanaRuleType type);
void katana_end_rule_header(KatanaParser* parser);
void katana_end_invalid_rule_header(KatanaParser* parser);
void katana_start_rule_body(KatanaParser* parser);
bool katana_string_is_function(KatanaParserString* string);
void katana_string_clear(KatanaParser* parser, KatanaParserString* string);
void katana_parse_internal_rule(KatanaParser* parser, KatanaRule* e);
void katana_parse_internal_keyframe_rule(KatanaParser* parser, KatanaKeyframe* e);
void katana_parse_internal_keyframe_key_list(KatanaParser* parser, KatanaArray* e);
void katana_parse_internal_value(KatanaParser* parser, KatanaArray* e);
void katana_parse_internal_media_list(KatanaParser* parser, KatanaArray* e);
void katana_parse_internal_declaration_list(KatanaParser* parser, bool e);
void katana_parse_internal_selector(KatanaParser* parser, KatanaArray* e);
// Bison error
void katanaerror(KATANALTYPE* yyloc, void* scanner, KatanaParser * parser, char*);
// Bison parser location
KatanaSourcePosition* katana_parser_current_location(KatanaParser* parser, KATANALTYPE* yylloc);
// Log
void katana_parser_log(KatanaParser* parser, const char * format, ...);
// Error
void katana_parser_resume_error_logging();
void katana_parser_report_error(KatanaParser* parser, KatanaSourcePosition* pos, const char *, ...);
// print
void katana_print(const char * format, ...);
void katana_print_stylesheet(KatanaParser* parser, KatanaStylesheet* sheet);
void katana_print_rule(KatanaParser* parser, KatanaRule* rule);
void katana_print_font_face_rule(KatanaParser* parser, KatanaFontFaceRule* rule);
void katana_print_import_rule(KatanaParser* parser, KatanaImportRule* rule);
void katana_print_media_query_exp(KatanaParser* parser, KatanaMediaQueryExp* exp);
void katana_print_media_query(KatanaParser* parser, KatanaMediaQuery* query);
void katana_print_media_list(KatanaParser* parser, KatanaArray* medias);
void katana_print_media_rule(KatanaParser* parser, KatanaMediaRule* rule);
void katana_print_keyframes_rule(KatanaParser* parser, KatanaKeyframesRule* rule);
void katana_print_keyframe(KatanaParser* parser, KatanaKeyframe* keyframe);
void katana_print_style_rule(KatanaParser* parser, KatanaStyleRule* rule);
void katana_print_selector(KatanaParser* parser, KatanaSelector* selector);
void katana_print_selector_list(KatanaParser* parser, KatanaArray* selectors);
void katana_print_declaration(KatanaParser* parser, KatanaDeclaration* decl);
void katana_print_declaration_list(KatanaParser* parser, KatanaArray* declarations);
void katana_print_value_list(KatanaParser* parser, KatanaArray* values);
#ifdef __cplusplus
}
#endif
#endif /* defined(__Katana__parser__) */

View File

@@ -0,0 +1,658 @@
/**
* Copyright (c) 2015 QFish <im@qfi.sh>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "selector.h"
#include <string.h>
#include <assert.h>
#undef assert
#define assert(x)
// Refs:
// http://www.w3.org/TR/css3-selectors/
//
static KatanaPseudoType name_to_pseudo_type(const char* name, bool hasArguments);
bool katana_selector_crosses_tree_scopes(const KatanaSelector* selector)
{
// TODO: To be supported
return false;
}
// bool katana_is_attribute_selector(const KatanaSelector* selector)
// {
// return selector->match == KatanaSelectorMatchAttributeExact
// || selector->match == KatanaSelectorMatchAttributeSet
// || selector->match == KatanaSelectorMatchAttributeList
// || selector->match == KatanaSelectorMatchAttributeHyphen
// || selector->match == KatanaSelectorMatchAttributeContain
// || selector->match == KatanaSelectorMatchAttributeBegin
// || selector->match == KatanaSelectorMatchAttributeEnd;
// }
KatanaPseudoType katana_parse_pseudo_type(const char* name, bool hasArguments)
{
KatanaPseudoType pseudoType = name_to_pseudo_type(name, hasArguments);
if (pseudoType != KatanaPseudoUnknown)
return pseudoType;
if (katana_string_has_prefix(name, "-webkit-"))
return KatanaPseudoWebKitCustomElement;
return KatanaPseudoUnknown;
}
void katana_selector_extract_pseudo_type(KatanaSelector* selector)
{
if (selector->pseudo == KatanaPseudoNotParsed)
selector->pseudo = KatanaPseudoUnknown;
if (selector->match != KatanaSelectorMatchPseudoClass && selector->match != KatanaSelectorMatchPseudoElement && selector->match != KatanaSelectorMatchPagePseudoClass)
return;
bool hasArguments = (NULL != selector->data->argument) || (NULL != selector->data->selectors);
selector->pseudo = katana_parse_pseudo_type(selector->data->value, hasArguments);
bool element = false; // pseudo-element
bool compat = false; // single colon compatbility mode
bool isPagePseudoClass = false; // Page pseudo-class
switch (selector->pseudo) {
case KatanaPseudoAfter:
case KatanaPseudoBefore:
case KatanaPseudoFirstLetter:
case KatanaPseudoFirstLine:
compat = true;
case KatanaPseudoBackdrop:
case KatanaPseudoCue:
case KatanaPseudoResizer:
case KatanaPseudoScrollbar:
case KatanaPseudoScrollbarCorner:
case KatanaPseudoScrollbarButton:
case KatanaPseudoScrollbarThumb:
case KatanaPseudoScrollbarTrack:
case KatanaPseudoScrollbarTrackPiece:
case KatanaPseudoSelection:
case KatanaPseudoWebKitCustomElement:
case KatanaPseudoContent:
case KatanaPseudoShadow:
element = true;
break;
case KatanaPseudoUnknown:
case KatanaPseudoEmpty:
case KatanaPseudoFirstChild:
case KatanaPseudoFirstOfType:
case KatanaPseudoLastChild:
case KatanaPseudoLastOfType:
case KatanaPseudoOnlyChild:
case KatanaPseudoOnlyOfType:
case KatanaPseudoNthChild:
case KatanaPseudoNthOfType:
case KatanaPseudoNthLastChild:
case KatanaPseudoNthLastOfType:
case KatanaPseudoLink:
case KatanaPseudoVisited:
case KatanaPseudoAny:
case KatanaPseudoAnyLink:
case KatanaPseudoAutofill:
case KatanaPseudoHover:
case KatanaPseudoDrag:
case KatanaPseudoFocus:
case KatanaPseudoActive:
case KatanaPseudoChecked:
case KatanaPseudoEnabled:
case KatanaPseudoFullPageMedia:
case KatanaPseudoDefault:
case KatanaPseudoDisabled:
case KatanaPseudoOptional:
case KatanaPseudoRequired:
case KatanaPseudoReadOnly:
case KatanaPseudoReadWrite:
case KatanaPseudoScope:
case KatanaPseudoValid:
case KatanaPseudoInvalid:
case KatanaPseudoIndeterminate:
case KatanaPseudoTarget:
case KatanaPseudoLang:
case KatanaPseudoNot:
case KatanaPseudoRoot:
case KatanaPseudoWindowInactive:
case KatanaPseudoCornerPresent:
case KatanaPseudoDecrement:
case KatanaPseudoIncrement:
case KatanaPseudoHorizontal:
case KatanaPseudoVertical:
case KatanaPseudoStart:
case KatanaPseudoEnd:
case KatanaPseudoDoubleButton:
case KatanaPseudoSingleButton:
case KatanaPseudoNoButton:
case KatanaPseudoNotParsed:
case KatanaPseudoFullScreen:
case KatanaPseudoFullScreenDocument:
case KatanaPseudoFullScreenAncestor:
case KatanaPseudoInRange:
case KatanaPseudoOutOfRange:
case KatanaPseudoFutureCue:
case KatanaPseudoPastCue:
case KatanaPseudoHost:
case KatanaPseudoHostContext:
case KatanaPseudoUnresolved:
case KatanaPseudoSpatialNavigationFocus:
case KatanaPseudoListBox:
break;
case KatanaPseudoFirstPage:
case KatanaPseudoLeftPage:
case KatanaPseudoRightPage:
isPagePseudoClass = true;
break;
}
bool matchPagePseudoClass = (selector->match == KatanaSelectorMatchPagePseudoClass);
if (matchPagePseudoClass != isPagePseudoClass)
selector->pseudo = KatanaPseudoUnknown;
else if (selector->match == KatanaSelectorMatchPseudoClass && element) {
if (!compat)
selector->pseudo = KatanaPseudoUnknown;
else
selector->match = KatanaSelectorMatchPseudoElement;
} else if (selector->match == KatanaSelectorMatchPseudoElement && !element)
selector->pseudo = KatanaPseudoUnknown;
}
bool katana_selector_matches_pseudo_element(KatanaSelector* selector)
{
if (selector->pseudo == KatanaPseudoUnknown)
katana_selector_extract_pseudo_type(selector);
return selector->match == KatanaSelectorMatchPseudoElement;
}
bool katana_selector_is_custom_pseudo_element(KatanaSelector* selector)
{
return selector->match == KatanaSelectorMatchPseudoElement && selector->pseudo == KatanaPseudoWebKitCustomElement;
}
bool katana_selector_is_direct_adjacent(KatanaSelector* selector)
{
return selector->relation == KatanaSelectorRelationDirectAdjacent || selector->relation == KatanaSelectorRelationIndirectAdjacent;
}
bool katana_selector_is_adjacent(KatanaSelector* selector)
{
return selector->relation == KatanaSelectorRelationDirectAdjacent;
}
bool katana_selector_is_shadow(KatanaSelector* selector)
{
return selector->relation == KatanaSelectorRelationShadowPseudo || selector->relation == KatanaSelectorRelationShadowDeep;
}
bool katana_selector_is_sibling(KatanaSelector* selector)
{
katana_selector_extract_pseudo_type(selector);
KatanaPseudoType type = selector->pseudo;
return selector->relation == KatanaSelectorRelationDirectAdjacent
|| selector->relation == KatanaSelectorRelationIndirectAdjacent
|| type == KatanaPseudoEmpty
|| type == KatanaPseudoFirstChild
|| type == KatanaPseudoFirstOfType
|| type == KatanaPseudoLastChild
|| type == KatanaPseudoLastOfType
|| type == KatanaPseudoOnlyChild
|| type == KatanaPseudoOnlyOfType
|| type == KatanaPseudoNthChild
|| type == KatanaPseudoNthOfType
|| type == KatanaPseudoNthLastChild
|| type == KatanaPseudoNthLastOfType;
}
bool katana_selector_is_attribute(const KatanaSelector* selector)
{
return selector->match >= KatanaSelectorMatchFirstAttribute;
}
bool katana_selector_is_content_pseudo_element(KatanaSelector* selector)
{
katana_selector_extract_pseudo_type(selector);
return selector->match == KatanaSelectorMatchPseudoElement && selector->pseudo == KatanaPseudoContent;
}
bool katana_selector_is_shadow_pseudo_element(KatanaSelector* selector)
{
return selector->match == KatanaSelectorMatchPseudoElement
&& selector->pseudo == KatanaPseudoShadow;
}
bool katana_selector_is_host_pseudo_class(KatanaSelector* selector)
{
return selector->match == KatanaSelectorMatchPseudoClass && (selector->pseudo == KatanaPseudoHost || selector->pseudo == KatanaPseudoHostContext);
}
bool katana_selector_is_tree_boundary_crossing(KatanaSelector* selector)
{
katana_selector_extract_pseudo_type(selector);
return selector->match == KatanaSelectorMatchPseudoClass && (selector->pseudo == KatanaPseudoHost || selector->pseudo == KatanaPseudoHostContext);
}
bool katana_selector_is_insertion_point_crossing(KatanaSelector* selector)
{
katana_selector_extract_pseudo_type(selector);
return (selector->match == KatanaSelectorMatchPseudoClass && selector->pseudo == KatanaPseudoHostContext)
|| (selector->match == KatanaSelectorMatchPseudoElement && selector->pseudo == KatanaPseudoContent);
}
KatanaParserString* katana_build_relation_selector_string(KatanaParser* parser, const char* relation, KatanaParserString* string, KatanaParserString* next, KatanaSelector* tagHistory)
{
if ( NULL != relation ) {
katana_string_prepend_characters(parser, relation, string);
}
if ( NULL != next ) {
katana_string_append_string(parser, next, string);
}
KatanaParserString * result = katana_selector_to_string(parser, tagHistory, (KatanaParserString*)string);
katana_parser_deallocate(parser, (void*) string->data);
katana_parser_deallocate(parser, (void*) string);
return result;
}
KatanaParserString* katana_selector_to_string(KatanaParser* parser, KatanaSelector* selector, KatanaParserString* next)
{
KatanaParserString* string = katana_parser_allocate(parser, sizeof(KatanaParserString));
katana_string_init(parser, string);
bool tag_is_implicit = true;
if (selector->match == KatanaSelectorMatchTag && tag_is_implicit)
{
if ( NULL == selector->tag->prefix )
katana_string_append_characters(parser, selector->tag->local, string);
else {
katana_string_append_characters(parser, selector->tag->prefix, string);
katana_string_append_characters(parser, "|", string);
katana_string_append_characters(parser, selector->tag->local, string);
}
}
const KatanaSelector* cs = selector;
while (true) {
if (cs->match == KatanaSelectorMatchId) {
katana_string_append_characters(parser, "#", string);
katana_string_append_characters(parser, cs->data->value, string);
} else if (cs->match == KatanaSelectorMatchClass) {
katana_string_append_characters(parser, ".", string);
katana_string_append_characters(parser, cs->data->value, string);
} else if (cs->match == KatanaSelectorMatchPseudoClass || cs->match == KatanaSelectorMatchPagePseudoClass) {
katana_string_append_characters(parser, ":", string);
katana_string_append_characters(parser, cs->data->value, string);
switch (cs->pseudo) {
case KatanaPseudoAny:
case KatanaPseudoNot:
case KatanaPseudoHost:
case KatanaPseudoHostContext: {
if ( cs->data->selectors ) {
KatanaArray* sels = cs->data->selectors;
for (size_t i=0; i<sels->length; i++) {
KatanaParserString* str = katana_selector_to_string(parser, sels->data[i], NULL);
katana_string_append_string(parser, str, string);
katana_parser_deallocate(parser, (void*) str->data);
katana_parser_deallocate(parser, (void*) str);
if ( i != sels->length -1 ) {
katana_string_append_characters(parser, ", ", string);
}
}
katana_string_append_characters(parser, ")", string);
}
}
break;
case KatanaPseudoLang:
case KatanaPseudoNthChild:
case KatanaPseudoNthLastChild:
case KatanaPseudoNthOfType:
case KatanaPseudoNthLastOfType: {
katana_string_append_characters(parser, cs->data->argument, string);
katana_string_append_characters(parser, ")", string);
}
break;
default:
break;
}
} else if (cs->match == KatanaSelectorMatchPseudoElement) {
katana_string_append_characters(parser, "::", string);
katana_string_append_characters(parser, cs->data->value, string);
} else if (katana_selector_is_attribute(cs)) {
katana_string_append_characters(parser, "[", string);
if (NULL != cs->data->attribute->prefix) {
katana_string_append_characters(parser, cs->data->attribute->prefix, string);
katana_string_append_characters(parser, "|", string);
}
katana_string_append_characters(parser, cs->data->attribute->local, string);
switch (cs->match) {
case KatanaSelectorMatchAttributeExact:
katana_string_append_characters(parser, "=", string);
break;
case KatanaSelectorMatchAttributeSet:
katana_string_append_characters(parser, "]", string);
break;
case KatanaSelectorMatchAttributeList:
katana_string_append_characters(parser, "~=", string);
break;
case KatanaSelectorMatchAttributeHyphen:
katana_string_append_characters(parser, "|=", string);
break;
case KatanaSelectorMatchAttributeBegin:
katana_string_append_characters(parser, "^=", string);
break;
case KatanaSelectorMatchAttributeEnd:
katana_string_append_characters(parser, "$=", string);
break;
case KatanaSelectorMatchAttributeContain:
katana_string_append_characters(parser, "*=", string);
break;
default:
break;
}
if (cs->match != KatanaSelectorMatchAttributeSet) {
katana_string_append_characters(parser, "\"", string);
katana_string_append_characters(parser, cs->data->value, string);
katana_string_append_characters(parser, "\"", string);
if (cs->data->bits.attributeMatchType == KatanaAttributeMatchTypeCaseInsensitive)
katana_string_append_characters(parser, " i", string);
katana_string_append_characters(parser, "]", string);
}
}
if (cs->relation != KatanaSelectorRelationSubSelector || !cs->tagHistory)
break;
cs = cs->tagHistory;
}
KatanaSelector* tagHistory = cs->tagHistory;
if ( NULL != tagHistory ) {
switch (cs->relation) {
case KatanaSelectorRelationDescendant:
{
return katana_build_relation_selector_string(parser, " ", string, next, tagHistory);
}
case KatanaSelectorRelationChild:
{
return katana_build_relation_selector_string(parser, " > ", string, next, tagHistory);
}
case KatanaSelectorRelationShadowDeep:
{
return katana_build_relation_selector_string(parser, " /deep/ ", string, next, tagHistory);
}
case KatanaSelectorRelationDirectAdjacent:
{
return katana_build_relation_selector_string(parser, " + ", string, next, tagHistory);
}
case KatanaSelectorRelationIndirectAdjacent:
{
return katana_build_relation_selector_string(parser, " ~ ", string, next, tagHistory);
}
case KatanaSelectorRelationSubSelector:
{
return NULL;
}
case KatanaSelectorRelationShadowPseudo:
{
return katana_build_relation_selector_string(parser, NULL, string, next, tagHistory);
}
}
}
if ( NULL != next ) {
katana_string_append_string(parser, (KatanaParserString*)next, string);
}
return (KatanaParserString*)string;
}
unsigned calc_specificity_for_one_selector(const KatanaSelector* selector)
{
switch ( selector->match ) {
case KatanaSelectorMatchId:
return 0x10000;
case KatanaSelectorMatchPseudoClass:
case KatanaSelectorMatchAttributeExact:
case KatanaSelectorMatchClass:
case KatanaSelectorMatchAttributeSet:
case KatanaSelectorMatchAttributeList:
case KatanaSelectorMatchAttributeHyphen:
case KatanaSelectorMatchPseudoElement:
case KatanaSelectorMatchAttributeContain:
case KatanaSelectorMatchAttributeBegin:
case KatanaSelectorMatchAttributeEnd:
return 0x100;
case KatanaSelectorMatchTag:
return !stricmp(selector->tag->local, "*") ? 0 : 1;
case KatanaSelectorMatchUnknown:
case KatanaSelectorMatchPagePseudoClass:
return 0;
}
return 0;
}
unsigned katana_calc_specificity_for_selector(KatanaSelector* selector)
{
if ( NULL == selector ) {
return 0;
}
static const unsigned idMask = 0xff0000;
static const unsigned classMask = 0xff00;
static const unsigned elementMask = 0xff;
unsigned total = 0;
unsigned temp = 0;
for (const KatanaSelector * next = selector; next; next = next->tagHistory)
{
temp = total + calc_specificity_for_one_selector(next);
if ((temp & idMask) < (total & idMask))
total |= idMask;
else if ((temp & classMask) < (total & classMask))
total |= classMask;
else if ((temp & elementMask) < (total & elementMask))
total |= elementMask;
else
total = temp;
}
return total;
}
// Could be made smaller and faster by replacing pointer with an
// offset into a string buffer and making the bit fields smaller but
// that could not be maintained by hand.
typedef struct {
const char* string;
unsigned type:8;
} KatanaNameToPseudoStruct;
// These tables should be kept sorted.
const static KatanaNameToPseudoStruct kPseudoTypeWithoutArgumentsMap[] = {
{"-internal-list-box", KatanaPseudoListBox},
{"-internal-media-controls-cast-button", KatanaPseudoWebKitCustomElement},
{"-internal-media-controls-overlay-cast-button", KatanaPseudoWebKitCustomElement},
{"-internal-spatial-navigation-focus", KatanaPseudoSpatialNavigationFocus},
{"-webkit-any-link", KatanaPseudoAnyLink},
{"-webkit-autofill", KatanaPseudoAutofill},
{"-webkit-drag", KatanaPseudoDrag},
{"-webkit-full-page-media", KatanaPseudoFullPageMedia},
{"-webkit-full-screen", KatanaPseudoFullScreen},
{"-webkit-full-screen-ancestor", KatanaPseudoFullScreenAncestor},
{"-webkit-full-screen-document", KatanaPseudoFullScreenDocument},
{"-webkit-resizer", KatanaPseudoResizer},
{"-webkit-scrollbar", KatanaPseudoScrollbar},
{"-webkit-scrollbar-button", KatanaPseudoScrollbarButton},
{"-webkit-scrollbar-corner", KatanaPseudoScrollbarCorner},
{"-webkit-scrollbar-thumb", KatanaPseudoScrollbarThumb},
{"-webkit-scrollbar-track", KatanaPseudoScrollbarTrack},
{"-webkit-scrollbar-track-piece", KatanaPseudoScrollbarTrackPiece},
{"active", KatanaPseudoActive},
{"after", KatanaPseudoAfter},
{"backdrop", KatanaPseudoBackdrop},
{"before", KatanaPseudoBefore},
{"checked", KatanaPseudoChecked},
{"content", KatanaPseudoContent},
{"corner-present", KatanaPseudoCornerPresent},
{"cue", KatanaPseudoWebKitCustomElement},
{"decrement", KatanaPseudoDecrement},
{"default", KatanaPseudoDefault},
{"disabled", KatanaPseudoDisabled},
{"double-button", KatanaPseudoDoubleButton},
{"empty", KatanaPseudoEmpty},
{"enabled", KatanaPseudoEnabled},
{"end", KatanaPseudoEnd},
{"first", KatanaPseudoFirstPage},
{"first-child", KatanaPseudoFirstChild},
{"first-letter", KatanaPseudoFirstLetter},
{"first-line", KatanaPseudoFirstLine},
{"first-of-type", KatanaPseudoFirstOfType},
{"focus", KatanaPseudoFocus},
{"future", KatanaPseudoFutureCue},
{"horizontal", KatanaPseudoHorizontal},
{"host", KatanaPseudoHost},
{"hover", KatanaPseudoHover},
{"in-range", KatanaPseudoInRange},
{"increment", KatanaPseudoIncrement},
{"indeterminate", KatanaPseudoIndeterminate},
{"invalid", KatanaPseudoInvalid},
{"last-child", KatanaPseudoLastChild},
{"last-of-type", KatanaPseudoLastOfType},
{"left", KatanaPseudoLeftPage},
{"link", KatanaPseudoLink},
{"no-button", KatanaPseudoNoButton},
{"only-child", KatanaPseudoOnlyChild},
{"only-of-type", KatanaPseudoOnlyOfType},
{"optional", KatanaPseudoOptional},
{"out-of-range", KatanaPseudoOutOfRange},
{"past", KatanaPseudoPastCue},
{"read-only", KatanaPseudoReadOnly},
{"read-write", KatanaPseudoReadWrite},
{"required", KatanaPseudoRequired},
{"right", KatanaPseudoRightPage},
{"root", KatanaPseudoRoot},
{"scope", KatanaPseudoScope},
{"selection", KatanaPseudoSelection},
{"shadow", KatanaPseudoShadow},
{"single-button", KatanaPseudoSingleButton},
{"start", KatanaPseudoStart},
{"target", KatanaPseudoTarget},
{"unresolved", KatanaPseudoUnresolved},
{"valid", KatanaPseudoValid},
{"vertical", KatanaPseudoVertical},
{"visited", KatanaPseudoVisited},
{"window-inactive", KatanaPseudoWindowInactive},
};
const static KatanaNameToPseudoStruct kPseudoTypeWithArgumentsMap[] = {
{"-webkit-any(", KatanaPseudoAny},
{"cue(", KatanaPseudoCue},
{"host(", KatanaPseudoHost},
{"host-context(", KatanaPseudoHostContext},
{"lang(", KatanaPseudoLang},
{"not(", KatanaPseudoNot},
{"nth-child(", KatanaPseudoNthChild},
{"nth-last-child(", KatanaPseudoNthLastChild},
{"nth-last-of-type(", KatanaPseudoNthLastOfType},
{"nth-of-type(", KatanaPseudoNthOfType},
};
static const KatanaNameToPseudoStruct* lower_bound(const KatanaNameToPseudoStruct *map,
size_t count, const char* key);
static KatanaPseudoType name_to_pseudo_type(const char* name, bool hasArguments)
{
if (NULL == name)
return KatanaPseudoUnknown;
const KatanaNameToPseudoStruct* pseudoTypeMap;
size_t count;
if (hasArguments) {
pseudoTypeMap = kPseudoTypeWithArgumentsMap;
count = sizeof(kPseudoTypeWithArgumentsMap) / sizeof(KatanaNameToPseudoStruct);
} else {
pseudoTypeMap = kPseudoTypeWithoutArgumentsMap;
count = sizeof(kPseudoTypeWithoutArgumentsMap) / sizeof(KatanaNameToPseudoStruct);
}
const KatanaNameToPseudoStruct* match = lower_bound(pseudoTypeMap, count, name);
if ( match == (pseudoTypeMap + count)
|| 0 != stricmp(match->string, name) )
return KatanaPseudoUnknown;
return match->type;
}
static const KatanaNameToPseudoStruct* lower_bound(const KatanaNameToPseudoStruct *array,
size_t size, const char* key) {
const KatanaNameToPseudoStruct* it;
const KatanaNameToPseudoStruct* first = array;
size_t count = size, step;
while (count > 0) {
it = first;
step = count / 2;
it += step;
if (strncmp(it->string, key, strlen(key)) < 0) {
first = ++it;
count -= step + 1;
} else count = step;
}
return first;
}
#if KATANA_PARSER_DEBUG
void test_lower_bound()
{
const KatanaNameToPseudoStruct* pseudoTypeMap;
size_t count;
pseudoTypeMap = kPseudoTypeWithArgumentsMap;
count = sizeof(kPseudoTypeWithArgumentsMap) / sizeof(KatanaNameToPseudoStruct);
for ( size_t i = 0; i < count; i++ ) {
const KatanaNameToPseudoStruct* res = lower_bound(pseudoTypeMap, count, pseudoTypeMap[i].string);
assert(pseudoTypeMap[i].type == res->type);
}
pseudoTypeMap = kPseudoTypeWithoutArgumentsMap;
count = sizeof(kPseudoTypeWithoutArgumentsMap) / sizeof(KatanaNameToPseudoStruct);
for ( size_t i = 0; i < count; i++ ) {
const KatanaNameToPseudoStruct* res = lower_bound(pseudoTypeMap, count, pseudoTypeMap[i].string);
assert(pseudoTypeMap[i].type == res->type);
}
}
#endif // #if KATANA_PARSER_DEBUG

View File

@@ -0,0 +1,54 @@
/**
* Copyright (c) 2015 QFish <im@qfi.sh>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __Katana__selector__
#define __Katana__selector__
#include <stdio.h>
#include "katana.h"
#include "parser.h"
#ifdef __cplusplus
extern "C" {
#endif
KatanaParserString* katana_selector_to_string(KatanaParser* parser, KatanaSelector* selector, KatanaParserString* next);
bool katana_selector_crosses_tree_scopes(const KatanaSelector* selector);
bool katana_selector_matches_pseudo_element(KatanaSelector* selector);
bool katana_selector_is_custom_pseudo_element(KatanaSelector* selector);
bool katana_selector_is_direct_adjacent(KatanaSelector* selector);
bool katana_selector_is_adjacent(KatanaSelector* selector);
bool katana_selector_is_shadow(KatanaSelector* selector);
bool katana_selector_is_sibling(KatanaSelector* selector);
bool katana_selector_is_attribute(const KatanaSelector* selector);
bool katana_selector_is_content_pseudo_element(KatanaSelector* selector);
bool katana_selector_is_shadow_pseudo_element(KatanaSelector* selector);
bool katana_selector_is_host_pseudo_class(KatanaSelector* selector);
bool katana_selector_is_tree_boundary_crossing(KatanaSelector* selector);
bool katana_selector_is_insertion_point_crossing(KatanaSelector* selector);
#ifdef __cplusplus
}
#endif
#endif /* defined(__Katana__selector__) */

View File

@@ -0,0 +1,304 @@
/**
* Copyright (c) 2015 QFish <im@qfi.sh>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <assert.h>
#include "tokenizer.h"
#include "katana.tab.h"
#include "katana.lex.h"
#include "parser.h"
#include "foundation.h"
#undef assert
#define assert(x)
static inline double katana_characters_to_double(const char* data, size_t length, bool* ok);
static inline bool katana_is_html_space(char c);
static inline char* katana_normalize_text(yy_size_t* length, char *origin_text, yy_size_t origin_length, int tok);
#ifdef KATANA_FELX_DEBUG
#if KATANA_FELX_DEBUG
static char * katana_token_string(int tok);
#endif // #if KATANA_FELX_DEBUG
#endif // #ifdef KATANA_FELX_DEBUG
/**
* A hook function of flex, processing tokens which will be passed to bison
*
* @param yylval the medium for flex and bison
* @param yyscanner flex state
* @param tok the type of token
*
* @return the type of token
*/
int katana_tokenize(KATANASTYPE* lval , KATANALTYPE* loc, yyscan_t scanner, KatanaParser* parser, int tok)
{
char* origin_text = katanaget_text(scanner);
yy_size_t len = 0;
char* text = katana_normalize_text(&len, origin_text, katanaget_leng(scanner), tok);
#ifdef KATANA_FELX_DEBUG
#if KATANA_FELX_DEBUG
if ( tok == KATANA_CSS_WHITESPACE ) {
katana_parser_log(parser, "【%30s】=>【%30s】: %s", "", "", katana_token_string(tok));
} else {
katana_parser_log(parser, "【%30s】=>【%30s】: %s", origin_text, text, katana_token_string(tok));
}
#endif // #if KATANA_FELX_DEBUG
#endif // #ifdef KATANA_FELX_DEBUG
yy_size_t length = len;
switch ( tok ) {
case KATANA_CSS_INCLUDES:
case KATANA_CSS_DASHMATCH:
case KATANA_CSS_BEGINSWITH:
case KATANA_CSS_ENDSWITH:
case KATANA_CSS_CONTAINS:
break;
case KATANA_CSS_STRING:
case KATANA_CSS_IDENT:
case KATANA_CSS_NTH:
case KATANA_CSS_HEX:
case KATANA_CSS_IDSEL:
case KATANA_CSS_DIMEN:
case KATANA_CSS_INVALIDDIMEN:
case KATANA_CSS_URI:
case KATANA_CSS_FUNCTION:
case KATANA_CSS_ANYFUNCTION:
case KATANA_CSS_CUEFUNCTION:
case KATANA_CSS_NOTFUNCTION:
case KATANA_CSS_CALCFUNCTION:
case KATANA_CSS_MINFUNCTION:
case KATANA_CSS_MAXFUNCTION:
case KATANA_CSS_HOSTFUNCTION:
case KATANA_CSS_HOSTCONTEXTFUNCTION:
case KATANA_CSS_UNICODERANGE:
{
lval->string.data = text;
lval->string.length = length;
}
break;
case KATANA_CSS_IMPORT_SYM:
case KATANA_CSS_PAGE_SYM:
case KATANA_CSS_MEDIA_SYM:
case KATANA_CSS_SUPPORTS_SYM:
case KATANA_CSS_FONT_FACE_SYM:
case KATANA_CSS_CHARSET_SYM:
case KATANA_CSS_NAMESPACE_SYM:
// case KATANA_CSS_VIEWPORT_RULE_SYM:
case KATANA_INTERNAL_DECLS_SYM:
case KATANA_INTERNAL_MEDIALIST_SYM:
case KATANA_INTERNAL_RULE_SYM:
case KATANA_INTERNAL_SELECTOR_SYM:
case KATANA_INTERNAL_VALUE_SYM:
case KATANA_INTERNAL_KEYFRAME_RULE_SYM:
case KATANA_INTERNAL_KEYFRAME_KEY_LIST_SYM:
case KATANA_INTERNAL_SUPPORTS_CONDITION_SYM:
case KATANA_CSS_KEYFRAMES_SYM:
break;
case KATANA_CSS_QEMS:
length--;
case KATANA_CSS_GRADS:
case KATANA_CSS_TURNS:
length--;
case KATANA_CSS_DEGS:
case KATANA_CSS_RADS:
case KATANA_CSS_KHERTZ:
case KATANA_CSS_REMS:
length--;
case KATANA_CSS_MSECS:
case KATANA_CSS_HERTZ:
case KATANA_CSS_EMS:
case KATANA_CSS_EXS:
case KATANA_CSS_PXS:
case KATANA_CSS_CMS:
case KATANA_CSS_MMS:
case KATANA_CSS_INS:
case KATANA_CSS_PTS:
case KATANA_CSS_PCS:
length--;
case KATANA_CSS_SECS:
case KATANA_CSS_PERCENTAGE:
length--;
case KATANA_CSS_FLOATTOKEN:
lval->number.val = katana_characters_to_double(text, length, NULL);
lval->number.raw.data = text;
lval->number.raw.length = len;
break;
case KATANA_CSS_INTEGER:
lval->number.val = (int)katana_characters_to_double(text, length, NULL);
lval->number.raw.data = text;
lval->number.raw.length = len;
break;
default:
break;
}
return tok;
}
/**
* Format token
*
* @param length
* @param origin_text original text from the flex
* @param origin_length formatted length
* @param tok
*
* @return normalized text
*/
static inline char* katana_normalize_text(yy_size_t* length, char *origin_text, yy_size_t origin_length, int tok)
{
char * start = origin_text;
yy_size_t l = origin_length;
switch ( tok ) {
case KATANA_CSS_STRING:
l--;
/* nobreak */
case KATANA_CSS_HEX:
case KATANA_CSS_IDSEL:
start++;
l--;
break;
case KATANA_CSS_URI:
// "url("{w}{string}{w}")"
// "url("{w}{url}{w}")"
// strip "url(" and ")"
start += 4;
l -= 5;
// strip {w}
while (l && katana_is_html_space(*start)) {
++start;
--l;
}
while (l && katana_is_html_space(start[l - 1]))
--l;
if (l && (*start == '"' || *start == '\'')) {
assert(l >= 2 && start[l - 1] == *start);
++start;
l -= 2;
}
break;
default:
break;
}
*length = l;
return start;
}
double katana_characters_to_double(const char* data, size_t length, bool* ok)
{
if (!length) {
if (ok)
*ok = false;
return 0.0;
}
char* bytes = malloc(sizeof(char) * (length + 1));
for (unsigned i = 0; i < length; ++i)
bytes[i] = data[i] < 0x7F ? data[i] : '?';
bytes[length] = '\0';
char* end;
double val = strtod(bytes, &end);
if (ok)
*ok = (end == 0 || *end == '\0');
free(bytes);
return val;
}
#ifdef KATANA_FELX_DEBUG
#if KATANA_FELX_DEBUG
static char * katana_token_table[] = {
"TOKEN_EOF", "LOWEST_PREC", "UNIMPORTANT_TOK",
"KATANA_CSS_SGML_CD", "KATANA_CSS_WHITESPACE", "KATANA_CSS_INCLUDES",
"KATANA_CSS_DASHMATCH", "KATANA_CSS_BEGINSWITH", "KATANA_CSS_ENDSWITH",
"KATANA_CSS_CONTAINS", "KATANA_CSS_STRING", "KATANA_CSS_IDENT",
"KATANA_CSS_NTH", "KATANA_CSS_HEX", "KATANA_CSS_IDSEL", "KATANA_CSS_IMPORT_SYM", "KATANA_CSS_PAGE_SYM",
"KATANA_CSS_MEDIA_SYM", "KATANA_CSS_SUPPORTS_SYM",
"KATANA_CSS_FONT_FACE_SYM", "KATANA_CSS_CHARSET_SYM",
"KATANA_CSS_NAMESPACE_SYM", "KATANA_INTERNAL_DECLS_SYM",
"KATANA_INTERNAL_MEDIALIST_SYM", "KATANA_INTERNAL_RULE_SYM",
"KATANA_INTERNAL_SELECTOR_SYM", "KATANA_INTERNAL_VALUE_SYM",
"KATANA_INTERNAL_KEYFRAME_RULE_SYM",
"KATANA_INTERNAL_KEYFRAME_KEY_LIST_SYM",
"KATANA_INTERNAL_SUPPORTS_CONDITION_SYM", "KATANA_CSS_KEYFRAMES_SYM",
"KATANA_CSS_ATKEYWORD", "KATANA_CSS_IMPORTANT_SYM",
"KATANA_CSS_MEDIA_NOT", "KATANA_CSS_MEDIA_ONLY", "KATANA_CSS_MEDIA_AND",
"KATANA_CSS_MEDIA_OR", "KATANA_CSS_SUPPORTS_NOT",
"KATANA_CSS_SUPPORTS_AND", "KATANA_CSS_SUPPORTS_OR", "KATANA_CSS_REMS",
"KATANA_CSS_CHS", "KATANA_CSS_QEMS", "KATANA_CSS_EMS", "KATANA_CSS_EXS",
"KATANA_CSS_PXS", "KATANA_CSS_CMS", "KATANA_CSS_MMS", "KATANA_CSS_INS",
"KATANA_CSS_PTS", "KATANA_CSS_PCS", "KATANA_CSS_DEGS", "KATANA_CSS_RADS",
"KATANA_CSS_GRADS", "KATANA_CSS_TURNS", "KATANA_CSS_MSECS",
"KATANA_CSS_SECS", "KATANA_CSS_HERTZ", "KATANA_CSS_KHERTZ",
"KATANA_CSS_DIMEN", "KATANA_CSS_INVALIDDIMEN", "KATANA_CSS_PERCENTAGE",
"KATANA_CSS_FLOATTOKEN", "KATANA_CSS_INTEGER", "KATANA_CSS_VW",
"KATANA_CSS_VH", "KATANA_CSS_VMIN", "KATANA_CSS_VMAX", "KATANA_CSS_DPPX",
"KATANA_CSS_DPI", "KATANA_CSS_DPCM", "KATANA_CSS_FR", "KATANA_CSS_URI",
"KATANA_CSS_FUNCTION", "KATANA_CSS_ANYFUNCTION",
"KATANA_CSS_CUEFUNCTION", "KATANA_CSS_NOTFUNCTION",
"KATANA_CSS_CALCFUNCTION", "KATANA_CSS_MINFUNCTION",
"KATANA_CSS_MAXFUNCTION", "KATANA_CSS_HOSTFUNCTION",
"KATANA_CSS_HOSTCONTEXTFUNCTION", "KATANA_CSS_UNICODERANGE" };
static char * katana_token_string(int tok)
{
if (tok > 257)
{
return katana_token_table[tok-257];
}
else if ( 0 == tok )
{
return katana_token_table[0];
}
else
{
char* unicode = malloc(2);
unicode[0] = (char)tok;
unicode[1] = '\0';
return unicode;
}
}
#endif // #if KATANA_FELX_DEBUG
#endif // #ifdef KATANA_FELX_DEBUG
inline bool katana_is_html_space(char c)
{
return c <= ' ' && (c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f');
}
//inline int katana_to_ascii_hex_value(char c)
//{
// // ASSERT(isASCIIHexDigit(c));
// return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF;
//}
//inline bool katana_is_ascii_hex_digit(char c)
//{
// return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
//}

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) 2015 QFish <im@qfi.sh>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __Katana__tokenizer__
#define __Katana__tokenizer__
#include <stdio.h>
#include "katana.lex.h"
#include "katana.tab.h"
#include "parser.h"
#ifdef __cplusplus
extern "C" {
#endif
int katana_tokenize(KATANASTYPE* lval , KATANALTYPE* loc, yyscan_t scanner, KatanaParser* parser, int tok);
#ifdef __cplusplus
}
#endif
#endif /* defined(__Katana__tokenizer__) */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -58,6 +58,8 @@ group "Dependencies"
include "Nuake/dependencies/recastnavigation_p5.lua"
include "Nuake/dependencies/tracy_p5.lua"
include "Nuake/dependencies/yoga_p5.lua"
include "Nuake/dependencies/msdf-atlas-gen_p5.lua"
include "Nuake/dependencies/freetype_p5.lua"
group ""
include "NuakeNet/premake5.lua"
@@ -164,8 +166,13 @@ project "Nuake"
"%{prj.name}/dependencies/recastnavigation/DetourCrowd/Include",
"%{prj.name}/dependencies/recastnavigation/DetourTileCache/Include",
"%{prj.name}/dependencies/recastnavigation/Recast/Include",
"%{prj.name}/dependencies/yoga",
"%{prj.name}/dependencies/msdf-atlas-gen",
"%{prj.name}/dependencies/msdf-atlas-gen/msdfgen",
"%{prj.name}/dependencies/msdf-atlas-gen/msdfgen/include",
"%{prj.name}/dependencies/freetype/include",
"%{prj.name}/../Nuake/dependencies/tracy/public/tracy",
}
links
@@ -381,6 +388,7 @@ project "Editor"
{
"%{prj.name}/../Nuake",
"%{prj.name}/../Nuake/src/Vendors",
"%{prj.name}/../Nuake/src/Vendors/nanosvg",
"%{prj.name}/../Nuake/dependencies/glad/include",
"%{prj.name}/../Nuake/dependencies/glfw/include",
"%{prj.name}/../Nuake/dependencies/assimp/include",
@@ -394,8 +402,13 @@ project "Editor"
"%{prj.name}/../Nuake/dependencies/recastnavigation/DetourCrowd/Include",
"%{prj.name}/../Nuake/dependencies/recastnavigation/DetourTileCache/Include",
"%{prj.name}/../Nuake/dependencies/recastnavigation/Recast/Include",
"%{prj.name}/../Nuake/dependencies/yoga",
"%{prj.name}/../Nuake/dependencies/msdf-atlas-gen",
"%{prj.name}/../Nuake/dependencies/msdf-atlas-gen/msdfgen",
"%{prj.name}/../Nuake/dependencies/msdf-atlas-gen/msdfgen/include",
"%{prj.name}/../Nuake/dependencies/freetype/include",
"%{prj.name}/../Nuake/dependencies/tracy/public/tracy",
}
libdirs
@@ -406,7 +419,8 @@ project "Editor"
"%{prj.name}/../Nuake/src/Vendors/wren/src/include",
"%{prj.name}/../Nuake/dependencies/JoltPhysics/bin/%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}/JoltPhysics/",
"%{prj.name}/../Nuake/dependencies/soloud/bin/%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}",
"%{prj.name}/../Nuake/dependencies/Coral/NetCore/"
"%{prj.name}/../Nuake/dependencies/Coral/NetCore/",
"%{prj.name}/../Nuake/dependencies/freetype/bin/%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}/Freetype"
}
links
@@ -424,7 +438,10 @@ project "Editor"
"DetourTileCache",
"Recast",
"tracy",
"yoga"
"yoga",
"msdf-gen",
"msdf-atlas-gen",
"Freetype"
}
defines {