diff --git a/CMakeLists.txt b/CMakeLists.txt
index c13b0c5..ee8e0e2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,7 @@ find_package(glm CONFIG REQUIRED)
find_package(Ktx CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
+find_package(unofficial-lunasvg CONFIG REQUIRED)
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
if(UNIX)
@@ -75,7 +76,9 @@ target_link_libraries(Engine PUBLIC KTX::ktx)
target_link_libraries(Engine PUBLIC nlohmann_json::nlohmann_json)
target_link_libraries(Engine PUBLIC crcpp)
target_link_libraries(Engine PUBLIC fmt::fmt)
+target_link_libraries(Engine PUBLIC unofficial::lunasvg::lunasvg)
target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator)
+
target_link_libraries(Engine PUBLIC slang)
if(APPLE)
target_link_libraries(Engine PUBLIC metal)
diff --git a/Seele.natvis b/Seele.natvis
index 53362e3..afc3c51 100644
--- a/Seele.natvis
+++ b/Seele.natvis
@@ -60,10 +60,10 @@
object
-
- UniquePtr {*handle}
+
+ OwningPtr {*pointer}
- handle
+ pointer
diff --git a/src/Editor/Asset/CMakeLists.txt b/src/Editor/Asset/CMakeLists.txt
index 42de029..240cb8f 100644
--- a/src/Editor/Asset/CMakeLists.txt
+++ b/src/Editor/Asset/CMakeLists.txt
@@ -8,5 +8,7 @@ target_sources(Editor
MaterialLoader.cpp
MeshLoader.h
MeshLoader.cpp
+ SVGLoader.h
+ SVGLoader.cpp
TextureLoader.h
- TextureLoader.cpp "../../../tests/Engine/UI/Element.cpp")
\ No newline at end of file
+ TextureLoader.cpp)
\ No newline at end of file
diff --git a/src/Editor/Asset/FontLoader.cpp b/src/Editor/Asset/FontLoader.cpp
index dd13f04..7291c82 100644
--- a/src/Editor/Asset/FontLoader.cpp
+++ b/src/Editor/Asset/FontLoader.cpp
@@ -31,45 +31,13 @@ void FontLoader::importAsset(FontImportArgs args) {
// in case of the space character there is no bitmap
// so we create a single pixel empty texture
void FontLoader::import(FontImportArgs args, PFontAsset asset) {
- FT_Library ft;
- FT_Error error = FT_Init_FreeType(&ft);
- assert(!error);
- FT_Face face;
- error = FT_New_Face(ft, args.filePath.string().c_str(), 0, &face);
- assert(!error);
- FT_Set_Pixel_Sizes(face, 0, 48);
- for (uint32 c = 0; c < 256; ++c) {
- if (FT_Load_Char(face, c, FT_LOAD_RENDER | FT_LOAD_COLOR)) {
- std::cout << "error loading " << (char)c << std::endl;
- continue;
- }
- FontAsset::Glyph& glyph = asset->glyphs[c];
- glyph.size = IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
- glyph.bearing = IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
- glyph.advance = face->glyph->advance.x;
- glyph.textureData.resize(glyph.size.x * glyph.size.y);
- if (glyph.textureData.size() == 0) {
- glyph.size.x = 1;
- glyph.size.y = 1;
- glyph.textureData.add(0);
- // load a single transparent pixel, so that we dont have to handle empty textures later
- } else {
- std::memcpy(glyph.textureData.data(), face->glyph->bitmap.buffer, glyph.textureData.size());
- }
- glyph.texture = graphics->createTexture2D(TextureCreateInfo{
- .sourceData =
- {
- .size = glyph.textureData.size(),
- .data = glyph.textureData.data(),
- },
- .format = Gfx::SE_FORMAT_R8_UNORM,
- .width = glyph.size.x,
- .height = glyph.size.y,
- .name = "FontGlyph",
- });
- }
- FT_Done_Face(face);
- FT_Done_FreeType(ft);
+ std::ifstream stream(args.filePath.c_str(), std::ios::binary | std::ios::ate);
+ Array ttfFile(stream.tellg());
+ stream.seekg(0);
+ stream.read((char*)ttfFile.data(), ttfFile.size());
+ asset->ttfFile = std::move(ttfFile);
+ asset->graphics = graphics;
+ asset->loadFace();
AssetRegistry::saveAsset(asset, FontAsset::IDENTIFIER, asset->getFolderPath(), asset->getName());
diff --git a/src/Editor/Asset/SVGLoader.cpp b/src/Editor/Asset/SVGLoader.cpp
new file mode 100644
index 0000000..b972b9f
--- /dev/null
+++ b/src/Editor/Asset/SVGLoader.cpp
@@ -0,0 +1,35 @@
+#include "SVGLoader.h"
+#include "Asset/SVGAsset.h"
+#include "Asset/AssetRegistry.h"
+#include
+
+using namespace Seele;
+
+SVGLoader::SVGLoader(Gfx::PGraphics graphic) {}
+
+SVGLoader::~SVGLoader() {}
+
+void SVGLoader::importAsset(SVGImportArgs args) {
+ std::filesystem::path assetPath = args.filePath.filename();
+ assetPath.replace_extension("asset");
+ OSVGAsset asset = new SVGAsset(args.importPath, assetPath.stem().string());
+ asset->setStatus(Asset::Status::Loading);
+ // the registry takes ownership, but we need to edit the reference
+ PSVGAsset ref = asset;
+ AssetRegistry::get().registerSVG(std::move(asset));
+ import(args, ref);
+}
+
+void SVGLoader::import(SVGImportArgs args, PSVGAsset asset) {
+ std::ifstream stream(args.filePath.c_str(), std::ios::binary | std::ios::ate);
+ Array svgFile(stream.tellg());
+ stream.seekg(0);
+ stream.read((char*)svgFile.data(), svgFile.size());
+ asset->document = lunasvg::Document::loadFromData(svgFile.data());
+ asset->data = std::move(svgFile);
+ asset->graphics = graphics;
+
+ AssetRegistry::saveAsset(asset, SVGAsset::IDENTIFIER, asset->getFolderPath(), asset->getName());
+
+ asset->setStatus(Asset::Status::Ready);
+}
diff --git a/src/Editor/Asset/SVGLoader.h b/src/Editor/Asset/SVGLoader.h
new file mode 100644
index 0000000..2e62445
--- /dev/null
+++ b/src/Editor/Asset/SVGLoader.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "Containers/List.h"
+#include "MinimalEngine.h"
+#include
+
+namespace Seele {
+DECLARE_REF(SVGAsset)
+DECLARE_NAME_REF(Gfx, Graphics)
+struct SVGImportArgs {
+ std::filesystem::path filePath;
+ std::string importPath;
+};
+class SVGLoader {
+ public:
+ SVGLoader(Gfx::PGraphics graphic);
+ ~SVGLoader();
+ void importAsset(SVGImportArgs args);
+
+ private:
+ void import(SVGImportArgs args, PSVGAsset asset);
+ Gfx::PGraphics graphics;
+};
+DECLARE_REF(SVGLoader)
+} // namespace Seele
\ No newline at end of file
diff --git a/src/Editor/Window/InspectorView.cpp b/src/Editor/Window/InspectorView.cpp
index e17c35f..06b22a9 100644
--- a/src/Editor/Window/InspectorView.cpp
+++ b/src/Editor/Window/InspectorView.cpp
@@ -11,8 +11,14 @@ using namespace Seele::Editor;
InspectorView::InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo)
: View(graphics, window, createInfo, "InspectorView"),
- uiSystem(new UI::System(new UI::Div(
- UI::Attributes{}, {new UI::Div({}, {new UI::Text("OtherTest")}), new UI::Text("Test")}))) {
+ uiSystem(new UI::System(
+ new UI::Div(UI::Attributes{}, {
+ new UI::Div({},
+ {
+ new UI::Text("OtherTestT"),
+ }),
+ new UI::Text("Test"),
+ }))) {
renderGraph.addPass(new UIPass(graphics, uiSystem));
renderGraph.setViewport(viewport);
renderGraph.createRenderPass();
diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp
index 04b0ecc..69e18b8 100644
--- a/src/Editor/main.cpp
+++ b/src/Editor/main.cpp
@@ -87,6 +87,9 @@ int main() {
AssetImporter::importFont(FontImportArgs{
.filePath = "./fonts/arial.ttf",
});
+ AssetImporter::importFont(FontImportArgs{
+ .filePath = "C:\\Windows\\Fonts\\Calibri.ttf",
+ });
AssetImporter::importMesh(MeshImportArgs{
.filePath = sourcePath / "import/models/cube.fbx",
});
diff --git a/src/Engine/Asset/AssetRegistry.cpp b/src/Engine/Asset/AssetRegistry.cpp
index 0aa02bf..2b563b4 100644
--- a/src/Engine/Asset/AssetRegistry.cpp
+++ b/src/Engine/Asset/AssetRegistry.cpp
@@ -5,6 +5,7 @@
#include "MaterialAsset.h"
#include "MaterialInstanceAsset.h"
#include "MeshAsset.h"
+#include "SVGAsset.h"
#include "TextureAsset.h"
#include "Window/WindowManager.h"
#include
@@ -46,6 +47,15 @@ PFontAsset AssetRegistry::findFont(std::string_view folderPath, std::string_view
return folder->fonts.at(std::string(filePath));
}
+PSVGAsset AssetRegistry::findSVG(std::string_view folderPath, std::string_view filePath) {
+ std::unique_lock l(get().assetLock);
+ AssetFolder* folder = get().assetRoot;
+ if (!folderPath.empty()) {
+ folder = get().getOrCreateFolder(folderPath);
+ }
+ return folder->svgs.at(std::string(filePath));
+}
+
PMaterialAsset AssetRegistry::findMaterial(std::string_view folderPath, std::string_view filePath) {
std::unique_lock l(get().assetLock);
AssetFolder* folder = get().assetRoot;
@@ -79,6 +89,11 @@ void AssetRegistry::registerFont(OFontAsset font) {
get().registerFontInternal(std::move(font));
}
+void AssetRegistry::registerSVG(OSVGAsset svg) {
+ std::unique_lock l(get().assetLock);
+ get().registerSVGInternal(std::move(svg));
+}
+
void AssetRegistry::registerMaterial(OMaterialAsset material) {
std::unique_lock l(get().assetLock);
get().registerMaterialInternal(std::move(material));
@@ -128,6 +143,9 @@ void AssetRegistry::loadAsset(ArchiveBuffer& buffer) {
case FontAsset::IDENTIFIER:
asset = PFontAsset(folder->fonts.at(name));
break;
+ case SVGAsset::IDENTIFIER:
+ asset = PSVGAsset(folder->svgs.at(name));
+ break;
default:
throw new std::logic_error("Unknown Identifier");
}
@@ -273,6 +291,10 @@ Pair AssetRegistry::peekAsset(ArchiveBuffer& buffer) {
folder->fonts[name] = new FontAsset(folderPath, name);
asset = PFontAsset(folder->fonts[name]);
break;
+ case SVGAsset::IDENTIFIER:
+ folder->svgs[name] = new SVGAsset(folderPath, name);
+ asset = PSVGAsset(folder->svgs[name]);
+ break;
default:
throw new std::logic_error("Unknown Identifier");
}
@@ -299,6 +321,9 @@ void AssetRegistry::saveFolder(const std::filesystem::path& folderPath, AssetFol
for (const auto& [name, font] : folder->fonts) {
saveAsset(PFontAsset(font), FontAsset::IDENTIFIER, folderPath, name);
}
+ for (const auto& [name, svg] : folder->svgs) {
+ saveAsset(PSVGAsset(svg), SVGAsset::IDENTIFIER, folderPath, name);
+ }
for (auto& [name, child] : folder->children) {
saveFolder(folderPath / name, child);
}
@@ -321,6 +346,11 @@ void AssetRegistry::registerFontInternal(OFontAsset font) {
folder->fonts[font->getName()] = std::move(font);
}
+void AssetRegistry::registerSVGInternal(OSVGAsset svg) {
+ AssetFolder* folder = getOrCreateFolder(svg->getFolderPath());
+ folder->svgs[svg->getName()] = std::move(svg);
+}
+
void AssetRegistry::registerMaterialInternal(OMaterialAsset material) {
AssetFolder* folder = getOrCreateFolder(material->getFolderPath());
folder->materials[material->getName()] = std::move(material);
diff --git a/src/Engine/Asset/AssetRegistry.h b/src/Engine/Asset/AssetRegistry.h
index c6bea59..e9a1424 100644
--- a/src/Engine/Asset/AssetRegistry.h
+++ b/src/Engine/Asset/AssetRegistry.h
@@ -10,6 +10,7 @@
namespace Seele {
DECLARE_REF(TextureAsset)
DECLARE_REF(FontAsset)
+DECLARE_REF(SVGAsset)
DECLARE_REF(MeshAsset)
DECLARE_REF(MaterialAsset)
DECLARE_REF(MaterialInstanceAsset)
@@ -24,12 +25,14 @@ class AssetRegistry {
static PMeshAsset findMesh(std::string_view folderPath, std::string_view filePath);
static PTextureAsset findTexture(std::string_view folderPath, std::string_view filePath);
static PFontAsset findFont(std::string_view folderPath, std::string_view name);
+ static PSVGAsset findSVG(std::string_view folderPath, std::string_view name);
static PMaterialAsset findMaterial(std::string_view folderPath, std::string_view filePath);
static PMaterialInstanceAsset findMaterialInstance(std::string_view folderPath, std::string_view filePath);
static void registerMesh(OMeshAsset mesh);
static void registerTexture(OTextureAsset texture);
static void registerFont(OFontAsset font);
+ static void registerSVG(OSVGAsset svg);
static void registerMaterial(OMaterialAsset material);
static void registerMaterialInstance(OMaterialInstanceAsset instance);
@@ -48,6 +51,7 @@ class AssetRegistry {
Map children;
Map textures;
Map fonts;
+ Map svgs;
Map meshes;
Map materials;
Map instances;
@@ -70,6 +74,7 @@ class AssetRegistry {
void registerMeshInternal(OMeshAsset mesh);
void registerTextureInternal(OTextureAsset texture);
void registerFontInternal(OFontAsset font);
+ void registerSVGInternal(OSVGAsset svg);
void registerMaterialInternal(OMaterialAsset material);
void registerMaterialInstanceInternal(OMaterialInstanceAsset instance);
diff --git a/src/Engine/Asset/CMakeLists.txt b/src/Engine/Asset/CMakeLists.txt
index b5b635a..24ecfd4 100644
--- a/src/Engine/Asset/CMakeLists.txt
+++ b/src/Engine/Asset/CMakeLists.txt
@@ -14,6 +14,8 @@ target_sources(Engine
MaterialInstanceAsset.cpp
MeshAsset.h
MeshAsset.cpp
+ SVGAsset.h
+ SVGAsset.cpp
TextureAsset.h
TextureAsset.cpp)
diff --git a/src/Engine/Asset/FontAsset.cpp b/src/Engine/Asset/FontAsset.cpp
index dd72d64..0acb33d 100644
--- a/src/Engine/Asset/FontAsset.cpp
+++ b/src/Engine/Asset/FontAsset.cpp
@@ -6,35 +6,61 @@ using namespace Seele;
FontAsset::FontAsset() {}
-FontAsset::FontAsset(std::string_view folderPath, std::string_view name) : Asset(folderPath, name) {}
-
-FontAsset::~FontAsset() {}
-
-void FontAsset::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, glyphs); }
-
-void FontAsset::load(ArchiveBuffer& buffer) { Serialization::load(buffer, glyphs); }
-
-void FontAsset::Glyph::save(ArchiveBuffer& buffer) const {
- Serialization::save(buffer, size);
- Serialization::save(buffer, bearing);
- Serialization::save(buffer, advance);
- Serialization::save(buffer, textureData);
+FontAsset::FontAsset(std::string_view folderPath, std::string_view name) : Asset(folderPath, name) {
+ FT_Error error = FT_Init_FreeType(&ft);
+ assert(!error);
}
-void FontAsset::Glyph::load(ArchiveBuffer& buffer) {
- Serialization::load(buffer, size);
- Serialization::load(buffer, bearing);
- Serialization::load(buffer, advance);
- Serialization::load(buffer, textureData);
- texture = buffer.getGraphics()->createTexture2D(TextureCreateInfo{
- .sourceData =
- {
- .size = textureData.size(),
- .data = textureData.data(),
- },
- .format = Gfx::SE_FORMAT_R8_UNORM,
- .width = size.x,
- .height = size.y,
- .name = "FontGlyph",
- });
+FontAsset::~FontAsset() {
+ FT_Done_Face(face);
+ FT_Done_FreeType(ft);
}
+
+void FontAsset::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, ttfFile); }
+
+void FontAsset::load(ArchiveBuffer& buffer) {
+ Serialization::load(buffer, ttfFile);
+ graphics = buffer.getGraphics();
+ loadFace();
+}
+
+void FontAsset::loadFace() {
+ FT_Error error = FT_New_Memory_Face(ft, ttfFile.data(), ttfFile.size(), 0, &face);
+ assert(!error);
+}
+
+void FontAsset::loadFontSize(uint32 fontSize) {
+ FT_Set_Pixel_Sizes(face, 0, fontSize);
+ fontSizes[fontSize].ascent = face->ascender;
+ fontSizes[fontSize].descent = face->descender;
+ fontSizes[fontSize].linegap = 0;
+ for (uint32 c = 0; c < 256; ++c) {
+ if (FT_Load_Char(face, c, FT_LOAD_RENDER | FT_LOAD_COLOR)) {
+ continue;
+ }
+ FontAsset::Glyph& glyph = fontSizes[fontSize].glyphs[c];
+ glyph.size = IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
+ glyph.bearing = IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
+ glyph.advance = face->glyph->advance.x;
+ glyph.textureData.resize(glyph.size.x * glyph.size.y);
+ if (glyph.textureData.size() == 0) {
+ glyph.size.x = 1;
+ glyph.size.y = 1;
+ glyph.textureData.add(0);
+ // load a single transparent pixel, so that we dont have to handle empty textures later
+ } else {
+ std::memcpy(glyph.textureData.data(), face->glyph->bitmap.buffer, glyph.textureData.size());
+ }
+ glyph.texture = graphics->createTexture2D(TextureCreateInfo{
+ .sourceData =
+ {
+ .size = glyph.textureData.size(),
+ .data = glyph.textureData.data(),
+ },
+ .format = Gfx::SE_FORMAT_R8_UNORM,
+ .width = glyph.size.x,
+ .height = glyph.size.y,
+ .name = "FontGlyph",
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/Engine/Asset/FontAsset.h b/src/Engine/Asset/FontAsset.h
index 19888cc..13ac6aa 100644
--- a/src/Engine/Asset/FontAsset.h
+++ b/src/Engine/Asset/FontAsset.h
@@ -1,11 +1,11 @@
#pragma once
#include "Asset.h"
#include "Containers/Map.h"
+#include "Graphics/Texture.h"
#include "Math/Math.h"
#include
namespace Seele {
-DECLARE_NAME_REF(Gfx, Texture2D)
class FontAsset : public Asset {
public:
static constexpr uint64 IDENTIFIER = 0x10;
@@ -24,10 +24,27 @@ class FontAsset : public Asset {
void save(ArchiveBuffer& buffer) const;
void load(ArchiveBuffer& buffer);
};
- const Glyph& getGlyphData(char c) const { return glyphs[c]; }
+ struct FontData {
+ int32 ascent;
+ int32 descent;
+ int32 linegap;
+ Map glyphs;
+ };
+ const Glyph& getGlyphData(char c, uint32 fontSize) {
+ if (!fontSizes.contains(fontSize))
+ loadFontSize(fontSize);
+ return fontSizes[fontSize].glyphs[c];
+ }
+ const FontData& getFontData(uint32 fontSize) { return fontSizes[fontSize]; }
+ void loadFace();
private:
- Map glyphs;
+ void loadFontSize(uint32 fontSize);
+ Gfx::PGraphics graphics;
+ FT_Library ft;
+ FT_Face face;
+ Array ttfFile;
+ Map fontSizes;
friend class FontLoader;
};
DECLARE_REF(FontAsset)
diff --git a/src/Engine/Asset/SVGAsset.cpp b/src/Engine/Asset/SVGAsset.cpp
new file mode 100644
index 0000000..d4d3473
--- /dev/null
+++ b/src/Engine/Asset/SVGAsset.cpp
@@ -0,0 +1,35 @@
+#include "SVGAsset.h"
+#include "Graphics/Graphics.h"
+
+using namespace Seele;
+
+SVGAsset::SVGAsset() {}
+
+SVGAsset::SVGAsset(std::string_view folderPath, std::string_view name) : Asset(folderPath, name) {}
+
+SVGAsset::~SVGAsset() {}
+
+void SVGAsset::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, data); }
+
+void SVGAsset::load(ArchiveBuffer& buffer) {
+ Serialization::load(buffer, data);
+ document = lunasvg::Document::loadFromData(data.data());
+}
+
+Gfx::PTexture2D SVGAsset::getTexture(UVector2 dimensions) {
+ auto viewbox = ViewBox{
+ .width = dimensions.x,
+ .height = dimensions.y,
+ };
+ if (!cachedTextures.contains(viewbox)) {
+ auto bitmap = document->renderToBitmap(viewbox.width, viewbox.height);
+ bitmap.convertToRGBA();
+ cachedTextures[viewbox] = graphics->createTexture2D(TextureCreateInfo{
+ .format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT,
+ .width = viewbox.width,
+ .height = viewbox.height,
+ .name = "SVGTexture",
+ });
+ }
+ return cachedTextures[viewbox];
+}
diff --git a/src/Engine/Asset/SVGAsset.h b/src/Engine/Asset/SVGAsset.h
new file mode 100644
index 0000000..7866c8c
--- /dev/null
+++ b/src/Engine/Asset/SVGAsset.h
@@ -0,0 +1,34 @@
+#pragma once
+#include "Asset.h"
+#include "Containers/Map.h"
+#include "Graphics/Texture.h"
+#include "Math/Math.h"
+#include
+
+namespace Seele {
+class SVGAsset : public Asset {
+ public:
+ static constexpr uint64 IDENTIFIER = 0x20;
+ SVGAsset();
+ SVGAsset(std::string_view folderPath, std::string_view name);
+ virtual ~SVGAsset();
+ virtual void save(ArchiveBuffer& buffer) const override;
+ virtual void load(ArchiveBuffer& buffer) override;
+
+ Gfx::PTexture2D getTexture(UVector2 viewbox);
+
+ private:
+ // workaround to make vector a map key, could be solved by either implementing
+ // comparison operators for vectors, or implementing a hash map
+ struct ViewBox {
+ uint32 width;
+ uint32 height;
+ constexpr std::strong_ordering operator<=>(const ViewBox& other) const = default;
+ };
+ Array data;
+ Gfx::PGraphics graphics;
+ std::unique_ptr document;
+ Map cachedTextures;
+ friend class SVGLoader;
+};
+} // namespace Seele
\ No newline at end of file
diff --git a/src/Engine/Graphics/RenderPass/UIPass.cpp b/src/Engine/Graphics/RenderPass/UIPass.cpp
index bde1100..b97d99c 100644
--- a/src/Engine/Graphics/RenderPass/UIPass.cpp
+++ b/src/Engine/Graphics/RenderPass/UIPass.cpp
@@ -55,7 +55,7 @@ void UIPass::beginFrame(const Component::Camera& cam) {
RenderPass::beginFrame(cam);
glyphs.clear();
usedTextures.clear();
- for (const auto& render : renderElements) {
+ for (auto& render : renderElements) {
float x = render.position.x;
float y = render.position.y;
if (render.text.empty()) {
@@ -69,9 +69,9 @@ void UIPass::beginFrame(const Component::Camera& cam) {
.z = render.level / 100.f,
});
} else {
- y = y + render.fontSize;
+ y = y + render.baseline;
for (uint32 c : render.text) {
- const FontAsset::Glyph& glyph = render.font->getGlyphData(c);
+ const FontAsset::Glyph& glyph = render.font->getGlyphData(c, render.fontSize);
Vector2 bearing = Vector2(glyph.bearing);
Vector2 size = Vector2(glyph.size);
float xpos = x + glyph.bearing.x;
@@ -160,7 +160,33 @@ void UIPass::createRenderPass() {
.colorAttachments = {colorAttachment},
.depthAttachment = depthAttachment,
};
- renderPass = graphics->createRenderPass(std::move(layout), {}, viewport, "TextPass");
+ Array dependency = {
+ {
+ .srcSubpass = ~0U,
+ .dstSubpass = 0,
+ .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
+ Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+ .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
+ Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+ .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+ Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+ Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ },
+ {
+ .srcSubpass = 0,
+ .dstSubpass = ~0U,
+ .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
+ Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+ .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
+ Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+ .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+ Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+ Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ },
+ };
+ renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport, "TextPass");
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "TextVertex",
diff --git a/src/Engine/Math/Vector.h b/src/Engine/Math/Vector.h
index 043aa66..4ad6cf8 100644
--- a/src/Engine/Math/Vector.h
+++ b/src/Engine/Math/Vector.h
@@ -45,4 +45,4 @@ void from_json(nlohmann::json& j, Vector& vec);
std::ostream& operator<<(std::ostream& stream, const Seele::Vector2& vector);
std::ostream& operator<<(std::ostream& stream, const Seele::Vector& vector);
std::ostream& operator<<(std::ostream& stream, const Seele::Vector4& vector);
-std::ostream& operator<<(std::ostream& stream, const Seele::Quaternion& vector);
+std::ostream& operator<<(std::ostream& stream, const Seele::Quaternion& vector);
\ No newline at end of file
diff --git a/src/Engine/UI/Element.h b/src/Engine/UI/Element.h
index 3f8a850..ef12cad 100644
--- a/src/Engine/UI/Element.h
+++ b/src/Engine/UI/Element.h
@@ -14,6 +14,7 @@ struct UIRender {
Vector backgroundColor;
Vector2 position;
Vector2 dimensions;
+ uint32 baseline;
uint32 z;
uint32 level;
};
@@ -45,14 +46,14 @@ class Element {
dimensions.x = parentSize.x * style.width / 100.0f;
}
+ for (auto& child : children) {
+ child->layout(maxDimensions - Vector2(style.marginLeft + style.marginRight, style.marginTop + style.marginBottom));
+ }
if (style.heightType == DimensionType::Pixel) {
dimensions.y = style.height;
} else if (style.heightType == DimensionType::Percent) {
dimensions.y = parentSize.y * style.height / 100.0f;
}
- for (auto& child : children) {
- child->layout(maxDimensions);
- }
switch (style.innerDisplay) {
case InnerDisplayType::Flow:
flowLayout();
@@ -71,15 +72,15 @@ class Element {
if (child->style.position == PositionType::Static || child->style.position == PositionType::Relative) {
// create a new line in case the element doesnt fit on the current one anymore,
// but keep in current line in case we are still at the start, as a new line wouldnt help here
- if (cursor.x + child->dimensions.x > dimensions.x - child->style.left && cursor.x != 0) {
+ if (cursor.x + child->dimensions.x > maxDimensions.x - child->style.left && cursor.x != 0) {
cursor.x = 0;
cursor.y += lineHeight;
+ lineHeight = 0;
}
// todo: border
child->position.x = cursor.x + child->style.marginLeft;
child->position.y = cursor.y + child->style.marginTop;
cursor.x = child->position.x + child->dimensions.x;
- cursor.y = child->position.y + child->dimensions.y;
// apply offsets after updating the cursor for relative elements
if (child->style.position == PositionType::Relative) {
child->position.x += child->style.left;
@@ -108,7 +109,7 @@ class Element {
dimensions.x = cursor.x + style.paddingRight;
}
if (style.heightType == DimensionType::Auto) {
- dimensions.y = cursor.y + style.paddingBottom;
+ dimensions.y = lineHeight + cursor.y + style.paddingBottom;
}
}
virtual Array render(Vector2 anchor, uint32 level) {
diff --git a/src/Engine/UI/Element/Div.h b/src/Engine/UI/Element/Div.h
index 995ab2a..986e40e 100644
--- a/src/Engine/UI/Element/Div.h
+++ b/src/Engine/UI/Element/Div.h
@@ -12,8 +12,6 @@ class Div : public Element {
virtual void applyStyle(Style parentStyle) override {
style = parentStyle;
style.outerDisplay = OuterDisplayType::Block;
- style.widthType = DimensionType::Percent;
- style.width = 100;
(classes::apply(style), ...);
}
private:
diff --git a/src/Engine/UI/Element/Text.h b/src/Engine/UI/Element/Text.h
index abefe4b..b53cb47 100644
--- a/src/Engine/UI/Element/Text.h
+++ b/src/Engine/UI/Element/Text.h
@@ -15,9 +15,9 @@ template class Text : public Element {
virtual void layout(UVector2 parentSize) override {
size_t cursor = 0;
for (uint32 i = 0; i < text.size() - 1; ++i) {
- dimensions.x += style.fontFamily->getGlyphData(text[i]).advance / 64.0f;
+ dimensions.x += style.fontFamily->getGlyphData(text[i], style.fontSize).advance / 64.0f;
}
- dimensions.x += style.fontFamily->getGlyphData(text[text.size() - 1]).size.x;
+ dimensions.x += style.fontFamily->getGlyphData(text[text.size() - 1], style.fontSize).size.x;
dimensions.y = style.fontSize;
}
virtual Array render(Vector2 anchor, uint32 level) override {
@@ -28,6 +28,7 @@ template class Text : public Element {
.fontSize = style.fontSize,
.position = position + anchor,
.dimensions = dimensions,
+ .baseline = style.fontSize * 3 / 4, // TODO: improve
.z = style.z,
.level = level,
},
diff --git a/src/Engine/UI/Style/Class.h b/src/Engine/UI/Style/Class.h
index eae7198..ea1e54f 100644
--- a/src/Engine/UI/Style/Class.h
+++ b/src/Engine/UI/Style/Class.h
@@ -1,7 +1,7 @@
#pragma once
+#include "Asset/AssetRegistry.h"
#include "MinimalEngine.h"
#include "Style.h"
-#include "Asset/AssetRegistry.h"
namespace Seele {
template
@@ -36,10 +36,73 @@ template struct FontClass {
};
using Font_Arial = FontClass<"arial">;
+using Font_Calibri = FontClass<"Calibri">;
+
+template struct FontSizeClass {
+ static void apply(UI::Style& s) {
+ s.fontSize = fontSize;
+ s.lineHeight = lineHeight;
+ }
+};
+
+using Text_XS = FontSizeClass<12, 16>;
+using Text_SM = FontSizeClass<14, 20>;
+using Text_Base = FontSizeClass<16, 24>;
+using Text_LG = FontSizeClass<18, 28>;
+using Text_XL = FontSizeClass<20, 28>;
+using Text_2XL = FontSizeClass<24, 32>;
+using Text_3XL = FontSizeClass<30, 36>;
+using Text_4XL = FontSizeClass<36, 40>;
+using Text_5XL = FontSizeClass<48, 48>;
+using Text_6XL = FontSizeClass<60, 60>;
+using Text_7XL = FontSizeClass<72, 72>;
+using Text_8XL = FontSizeClass<96, 96>;
+using Text_9XL = FontSizeClass<128, 128>;
template struct BackgroundColorClass {
static void apply(UI::Style& s) { s.backgroundColor = backgroundColor; }
};
using BG_Red = BackgroundColorClass;
+
+template struct MarginClass {
+ static void apply(UI::Style& s) {
+ if (ml != -1)
+ s.marginLeft = ml;
+ if (mr != -1)
+ s.marginRight = mr;
+ if (mt != -1)
+ s.marginTop = mt;
+ if (mb != -1)
+ s.marginBottom = mb;
+ }
+};
+#define DECLARE_MARGIN_CLASSES(x) \
+ using M_##x = MarginClass; \
+ using M_X##x = MarginClass; \
+ using M_Y##x = MarginClass<-1, -1, x, x>; \
+ using M_L##x = MarginClass; \
+ using M_R##x = MarginClass<-1, x, -1, -1>; \
+ using M_T##x = MarginClass<-1, -1, x, -1>; \
+ using M_B##x = MarginClass<-1, -1, -1, x>;
+
+DECLARE_MARGIN_CLASSES(0)
+DECLARE_MARGIN_CLASSES(1)
+DECLARE_MARGIN_CLASSES(2)
+DECLARE_MARGIN_CLASSES(3)
+DECLARE_MARGIN_CLASSES(4)
+DECLARE_MARGIN_CLASSES(5)
+DECLARE_MARGIN_CLASSES(6)
+DECLARE_MARGIN_CLASSES(7)
+DECLARE_MARGIN_CLASSES(8)
+DECLARE_MARGIN_CLASSES(9)
+DECLARE_MARGIN_CLASSES(10)
+DECLARE_MARGIN_CLASSES(11)
+DECLARE_MARGIN_CLASSES(12)
+DECLARE_MARGIN_CLASSES(14)
+DECLARE_MARGIN_CLASSES(16)
+DECLARE_MARGIN_CLASSES(20)
+DECLARE_MARGIN_CLASSES(24)
+
+
} // namespace Seele
\ No newline at end of file
diff --git a/src/Engine/UI/Style/Style.h b/src/Engine/UI/Style/Style.h
index c5b5e26..62878f2 100644
--- a/src/Engine/UI/Style/Style.h
+++ b/src/Engine/UI/Style/Style.h
@@ -39,10 +39,10 @@ struct Style {
Vector backgroundColor = Vector(1, 1, 1);
OuterDisplayType outerDisplay = OuterDisplayType::Inline;
InnerDisplayType innerDisplay = InnerDisplayType::Flow;
- PositionType position = PositionType::Relative;
+ PositionType position = PositionType::Static;
PFontAsset fontFamily;
- uint32 lineHeight = 48;
- uint32 fontSize = 48;
+ uint32 lineHeight = 12;
+ uint32 fontSize = 12;
uint32 fontWeight = 0;
uint32 paddingTop = 0;
uint32 paddingBottom = 0;
diff --git a/vcpkg.json b/vcpkg.json
index 290a6b6..9fc0b26 100644
--- a/vcpkg.json
+++ b/vcpkg.json
@@ -1,16 +1,17 @@
{
- "dependencies": [
- "assimp",
- "entt",
- "stb",
- "entt",
- "freetype",
- "glfw3",
- "glm",
- "ktx",
- "nlohmann-json",
- "fmt",
- "gtest",
- "vulkan-memory-allocator"
- ]
+ "dependencies": [
+ "assimp",
+ "entt",
+ "stb",
+ "entt",
+ "freetype",
+ "glfw3",
+ "glm",
+ "ktx",
+ "nlohmann-json",
+ "fmt",
+ "gtest",
+ "vulkan-memory-allocator",
+ "lunasvg"
+ ]
}
\ No newline at end of file