diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-01-23 21:57:31 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-01-23 21:57:31 -0500 |
| commit | e93eb289ca44e98967482ab80fd5329f85ccd03e (patch) | |
| tree | 4164b6d5b9ac2e40d18ec3eea52730c9f9606ccb /editor | |
| parent | 846a6e1185417ee3e187edc06ef327d180bf0d9b (diff) | |
pke: first-pass 2d overlay render pass scaffolding
Diffstat (limited to 'editor')
| -rw-r--r-- | editor/editor.cpp | 156 |
1 files changed, 150 insertions, 6 deletions
diff --git a/editor/editor.cpp b/editor/editor.cpp index a15c838..9f6b492 100644 --- a/editor/editor.cpp +++ b/editor/editor.cpp @@ -3,14 +3,20 @@ #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" #include "array.hpp" +#include "asset-manager.hpp" #include "camera.hpp" #include "ecs.hpp" #include "entities.hpp" +#include "font.hpp" #include "game-settings.hpp" #include "game.hpp" #include "imgui.h" #include "level.hpp" #include "math-helpers.hpp" +#include "msdf-atlas-gen/GlyphGeometry.h" +#include "msdf-atlas-gen/glyph-generators.h" +#include "msdf-atlas-gen/image-save.h" +#include "msdf-atlas-gen/types.h" #include "player-input.hpp" #include "plugins.hpp" #include "project.hpp" @@ -19,11 +25,14 @@ #include "vendor-tinyfiledialogs.h" #include "window.hpp" #include "pk.h" +#include "msdf-atlas-gen/msdf-atlas-gen.h" #include <GLFW/glfw3.h> #include <compare> +#include <cstdio> #include <filesystem> #include <future> +#include <glm/fwd.hpp> #include <regex> #ifdef WIN32 @@ -230,7 +239,7 @@ void PkeEditor_Tick(double delta) { if (focusedInst != nullptr) { const auto *grBinds = ECS_GetGrBinds(focusedInst->grBindsHandle); if (grBinds != nullptr) { - pkeDebugHitbox.instanceBuffer = grBinds->instanceBuffer; + pkeDebugHitbox.instanceBuffer = grBinds->instanceBD.buffer; pkeDebugHitbox.instanceStartingIndex = focusedInst->index; found = true; } @@ -706,6 +715,140 @@ void RecordImGuiEntityTypes() { ImGui::End(); } +void GenerateMTSDF(const Asset *a) { + std::error_code e; + std::filesystem::create_directory("./cache", e); + if (msdfgen::FreetypeHandle *ft = msdfgen::initializeFreetype()) { + // Load font file + if (msdfgen::FontHandle *font = msdfgen::loadFont(ft, a->basePath)) { + // Storage for glyph geometry and their coordinates in the atlas + std::vector<msdf_atlas::GlyphGeometry> glyphs; + // FontGeometry is a helper class that loads a set of glyphs from a single font. + // It can also be used to get additional font metrics, kerning information, etc. + msdf_atlas::FontGeometry fontGeometry(&glyphs); + // Load a set of character glyphs: + // The second argument can be ignored unless you mix different font sizes in one atlas. + // In the last argument, you can specify a charset other than ASCII. + // To load specific glyph indices, use loadGlyphs instead. + fontGeometry.loadCharset(font, 1.0, msdf_atlas::Charset::ASCII); + // Apply MSDF edge coloring. See edge-coloring.h for other coloring strategies. + const double maxCornerAngle = 3.0; + for (msdf_atlas::GlyphGeometry &glyph : glyphs) + glyph.edgeColoring(&msdfgen::edgeColoringInkTrap, maxCornerAngle, 0); + // TightAtlasPacker class computes the layout of the atlas. + msdf_atlas::TightAtlasPacker packer; + // Set atlas parameters: + // setDimensions or setDimensionsConstraint to find the best value + packer.setDimensionsConstraint(msdf_atlas::DimensionsConstraint::SQUARE); + // setScale for a fixed size or setMinimumScale to use the largest that fits + packer.setMinimumScale(24.0); + // setPixelRange or setUnitRange + packer.setPixelRange(2.0); + packer.setMiterLimit(1.0); + // Compute atlas layout - pack glyphs + packer.pack(glyphs.data(), glyphs.size()); + // Get final atlas dimensions + int width = 0, height = 0; + packer.getDimensions(width, height); + // The ImmediateAtlasGenerator class facilitates the generation of the atlas bitmap. + msdf_atlas::ImmediateAtlasGenerator< + float, // pixel type of buffer for individual glyphs depends on generator function + 4, // number of atlas color channels + &msdf_atlas::mtsdfGenerator, // function to generate bitmaps for individual glyphs + msdf_atlas::BitmapAtlasStorage<float, 4> // class that stores the atlas bitmap + // For example, a custom atlas storage class that stores it in VRAM can be used. + > generator(width, height); + // GeneratorAttributes can be modified to change the generator's default settings. + msdf_atlas::GeneratorAttributes attributes; + generator.setAttributes(attributes); + // generator.setThreadCount(4); + // Generate atlas bitmap + generator.generate(glyphs.data(), glyphs.size()); + // The atlas bitmap can now be retrieved via atlasStorage as a BitmapConstRef. + // The glyphs array (or fontGeometry) contains positioning data for typesetting text. + msdf_atlas::BitmapAtlasStorage<float, 4> storage = generator.atlasStorage(); + msdf_atlas::saveImage<4>(storage, msdf_atlas::ImageFormat::PNG, "cache/test-font.png", msdf_atlas::YDirection::TOP_DOWN); + + auto f = fopen("cache/test-font.glyphs", "w"); + pk_arr arr_glyphs = {}; + arr_glyphs.alignment = 8; + arr_glyphs.stride = sizeof(FontGlyphChar); + pk_arr_resize(&arr_glyphs, glyphs.size()); + FontGlyphChar *arr = reinterpret_cast<FontGlyphChar *>(arr_glyphs.data); + for (uint64_t i = 0; i < glyphs.size(); ++i) { + arr[i].unicode = glyphs[i].getCodepoint(); + glyphs[i].getBoxRect(arr[i].bounds.x, arr[i].bounds.y, arr[i].bounds.z, arr[i].bounds.a); + } + + fwrite(glyphs.data(), sizeof(msdf_atlas::GlyphGeometry) * glyphs.size(), 1, f); + fclose(f); + // _ = myProject::submitAtlasBitmapAndLayout(generator.atlasStorage(), glyphs); + // Cleanup + msdfgen::destroyFont(font); + } + msdfgen::deinitializeFreetype(ft); + } +} + +void RecordImGuiAssets() { + if (!ImGui::Begin("AssetList")) { + ImGui::End(); + return; + } + + static ImGuiTableFlags tableFlags{ + ImGuiTableFlags_Borders | + ImGuiTableFlags_RowBg + }; + if (ImGui::BeginTable("Assets", 7, tableFlags)) { + ImGui::TableSetupColumn("Controls"); + ImGui::TableSetupColumn("Type"); + ImGui::TableSetupColumn("Handle"); + ImGui::TableSetupColumn("Key"); + ImGui::TableSetupColumn("Data"); + ImGui::TableSetupColumn("Size"); + ImGui::TableSetupColumn("Ref Count"); + ImGui::TableHeadersRow(); + + pk_handle_bucket_index_T asset_bucket_count = AM_GetBucketCount(); + for (pk_handle_bucket_index_T b = 0; b < asset_bucket_count; ++b) { + pk_handle_item_index_T count; + auto *assets = AM_GetAssets(b, count); + ImGui::PushID(b); + for (pk_handle_item_index_T i = 0; i < count; ++i) { + const auto &asset = assets[i]; + if (asset.handle == EntityHandle_MAX) + continue; + ImGui::PushID(i); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + if ((asset.type & PKE_ASSET_TYPE_FONT) != PKE_ASSET_TYPE_UNSET) { + if (ImGui::Button("Create MTSDF")) { + GenerateMTSDF(&asset); + } + } + ImGui::TableSetColumnIndex(1); + ImGui::Text("%i", (uint8_t)asset.type); + ImGui::TableSetColumnIndex(2); + ImGui::Text("0x%08X 0x%08X", asset.handle.bucketIndex, asset.handle.itemIndex); + ImGui::TableSetColumnIndex(3); + ImGui::Text("%.16s", asset.key); + ImGui::TableSetColumnIndex(4); + ImGui::Text("%p", asset.ptr); + ImGui::TableSetColumnIndex(5); + ImGui::Text("%li", asset.size); + ImGui::TableSetColumnIndex(6); + ImGui::Text("%hhi", asset.referenceCount); + ImGui::PopID(); + } + ImGui::PopID(); + } + ImGui::EndTable(); + + } + ImGui::End(); +} + void RecordImGuiCameras() { CompInstance *activeInst = nullptr; // CompInstance *activeTargetInst = nullptr; @@ -1044,11 +1187,11 @@ void RecordImGui_CompGrBinds(bool readonly, CompGrBinds *component) { ImGui::InputScalar("IndexOffsets", ImGuiDataType_U64, &component->indexBD.offsets[0], nullptr, nullptr, nullptr, inputTextFlags); ImGui::InputScalar("IndexCount", ImGuiDataType_U32, &component->indexCount, nullptr, nullptr, nullptr, inputTextFlags); - if (component->instanceBuffer) - ImGui::InputScalar("VkInstanceBuffer", ImGuiDataType_U64, &component->instanceBuffer, nullptr, nullptr, "0x%016lX", ImGuiInputTextFlags_ReadOnly); - ImGui::InputScalar("InstanceFirstBinding", ImGuiDataType_U32, &component->instanceFirstBinding, nullptr, nullptr, nullptr, inputTextFlags); - ImGui::InputScalar("InstanceBindingCount", ImGuiDataType_U32, &component->instanceBindingCount, nullptr, nullptr, nullptr, inputTextFlags); - ImGui::InputScalar("InstanceOffsets", ImGuiDataType_U64, &component->instanceOffsets, nullptr, nullptr, nullptr, inputTextFlags); + if (component->instanceBD.buffer) + ImGui::InputScalar("VkInstanceBuffer", ImGuiDataType_U64, &component->instanceBD.buffer, nullptr, nullptr, "0x%016lX", ImGuiInputTextFlags_ReadOnly); + ImGui::InputScalar("InstanceFirstBinding", ImGuiDataType_U32, &component->instanceBD.firstBinding, nullptr, nullptr, nullptr, inputTextFlags); + ImGui::InputScalar("InstanceBindingCount", ImGuiDataType_U32, &component->instanceBD.bindingCount, nullptr, nullptr, nullptr, inputTextFlags); + ImGui::InputScalar("InstanceOffsets", ImGuiDataType_U64, &component->instanceBD.offsets[0], nullptr, nullptr, nullptr, inputTextFlags); ImGui::InputScalar("InstanceBufferMaxCount", ImGuiDataType_U32, &component->instanceBufferMaxCount, nullptr, nullptr, nullptr, ImGuiInputTextFlags_ReadOnly); ImGui::InputScalar("Instance Count", ImGuiDataType_U32, &component->instanceCounter, nullptr, nullptr, nullptr, ImGuiInputTextFlags_ReadOnly); @@ -1366,6 +1509,7 @@ void PkeEditor_RecordImGui() { RecordImGuiCameras(); RecordImGuiLevels(); RecordImGuiEntityTypes(); + RecordImGuiAssets(); Game_RecordImGui(); } } |
