Nimbin[12]?SDL & Graphics / sdl_runtime_compiler / commits / fa0b493

sdl_runtime_compiler git · main

SDL3 game for running and compiling code at runtime

sdl3 c++ compiler dlopen cmake · first commit 2026-04-19 · last commit 2026-07-03 (3 months ago) · synced 3 days ago · upstream: git.ide3.de/hsnr/sdl-runtime-compiler

C++ 72.3% C 26.2%
git clone https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler.gitwget https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler/archive/sdl_runtime_compiler.tar.gz

Add Glyph cash for infowall With Claude

Christian Immanuel · 2026-06-10 12:40 · fa0b49321bc764c32484ef467732973433d92bf4

 src/levels/director.cpp   | 39 ++++++++++++++++++++--------------
 src/levels/director.hpp   |  6 +++---
 src/states/game_state.cpp | 14 +++++++------
 src/states/game_state.hpp |  5 +++--
 src/text/handler.cpp      |  7 +++++++
 src/text/handler.hpp      |  5 ++++-
 src/text/mesh.cpp         |  4 +++-
 src/wall/wall.cpp         | 53 ++++++++++++++++++++++++++++++++++-------------
 src/wall/wall.hpp         |  2 +-
 9 files changed, 92 insertions(+), 43 deletions(-)

diff --git a/src/levels/director.cpp b/src/levels/director.cpp
index 4e90f73..c83c65c 100644
--- a/src/levels/director.cpp
+++ b/src/levels/director.cpp
@@ -144,31 +144,40 @@ Director::teardown_Scene(GameContext& ctx)
 }
 
 
-void
-Director::show_Details(GameContext& ctx) const
+void Director::show_Details(GameContext& ctx) const
 {
     if (!ctx.info_wall) return;
     Text::Handler& info = *ctx.info_wall;
 
-    if (_runner->is_Complete()) { info.clear(); return; }
+    if (_runner->is_Complete()) { info.clear(); _detail_built_for = nullptr; return; }
 
     const Level::Step* step = &_runner->get_Current();
-    const size_t tag = std::hash<const void*>{}(step) | 1;
-    if (info.view_Is(tag)) return;
-
-    info.clear();
 
-    const Scene::Data* key = &step->scene;
-    if (key != _detail_key) {
+    if (_detail_built_for != step) {
+        _detail_tokens.clear();
         const std::string& details = step->details;
-        _detail_lines = details.empty() ? DynArray<std::string>{}
-                                        : Text::wrap_String(details, 92);
-        _detail_key = key;
+        DynArray<std::string> lines =
+            details.empty() ? DynArray<std::string>{} : Text::wrap_String(details, 92);
+
+        float y = World::get_FloorY<float>() + 1.0f;
+        const Wall::Transform tf = Wall::get_Transform(Wall::Role::Info, World::get_BoxScale());
+        for (const std::string& line : lines) {
+            if (line.empty()) { y += ConfigWall::text_line_spacing; continue; }
+            Text::TokenPtr t = Text::make_Token(line, Text::Token::depth_wall, 0.003f,
+                                                tf.position, ConfigColor::white);
+            t->yaw = tf.yaw;
+            t->pos = tf.position;
+            t->pos.y = y;
+            t->set_ColorSource(Text::ColorSource::Static);
+            t->set_Color(ConfigColor::white);
+            _detail_tokens.push_back(std::move(t));
+            y += ConfigWall::text_line_spacing;
+        }
+        _detail_built_for = step;
     }
-    for (const std::string& line : _detail_lines)
-        if (!line.empty()) info.append_Line(line);
 
-    info.set_View(tag);
+    info.clear();
+    info.set_Borrowed(&_detail_tokens);
 }
 
 
diff --git a/src/levels/director.hpp b/src/levels/director.hpp
index ad883f3..5ae42ee 100644
--- a/src/levels/director.hpp
+++ b/src/levels/director.hpp
@@ -58,9 +58,9 @@ class Director
     StepLedger             _ledger;
     DynArray<StepPlate>    _step_plates;
     DynArray<GameObject*>  _step_scenery;
-    mutable const Level::Step*    _detail_shown_for { nullptr };
-    mutable const Scene::Data*    _detail_key       { nullptr };
-    mutable DynArray<std::string> _detail_lines;
+
+    mutable const Level::Step*       _detail_built_for { nullptr };
+    mutable DynArray<Text::TokenPtr> _detail_tokens;
 
     void spawn_Grants  (GameContext& ctx);
     void setup_Scene   (GameContext& ctx, const Scene::Data& scene);
diff --git a/src/states/game_state.cpp b/src/states/game_state.cpp
index 96482cc..9b0c08b 100644
--- a/src/states/game_state.cpp
+++ b/src/states/game_state.cpp
@@ -244,7 +244,7 @@ GameState::on_DropLast()
     if (!word) return;
     revert_ToSingle(word.get());
 
-    infowall_Clear();
+    //infowall_Clear();
 
     word->body.mode = PhysicsMode::Dynamic;
     word->body.vel  = { _ctx.camera->fwd.x * 1.5, 0.8, _ctx.camera->fwd.z * 1.5 };
@@ -254,7 +254,6 @@ GameState::on_DropLast()
     _anims_drop.push_back(std::move(drop));
 
     if (!_carried.empty()) {
-        lex_CarriedLine(_carried);
         Wall::show_TokenInfo(_info, _carried.last->word->text);
     } else
         _level_director->show_Details(_ctx);
@@ -272,7 +271,7 @@ GameState::on_ShootOne()
     if (!word) return false;
     revert_ToSingle(word.get());
 
-    infowall_Clear();
+    //infowall_Clear();
 
     _freelook_sys->state.active  = false;
     _freelook_sys->state.lerping = false;
@@ -287,7 +286,6 @@ GameState::on_ShootOne()
 
     if (!_carried.empty() && _carried.last && _carried.last->word) {
         Wall::show_TokenInfo(_info, _carried.last->word->text);
-        lex_CarriedLine(_carried);
     }
     else _level_director->show_Details(_ctx);
 
@@ -301,7 +299,7 @@ GameState::on_ShootAll()
 {
     if (_carried.empty()) return;
 
-    infowall_Clear();
+    //infowall_Clear();
 
     _freelook_sys->state.active  = false;
     _freelook_sys->state.lerping = false;
@@ -680,7 +678,11 @@ GameState::update(double dt, const GlRenderer* gl)
         carriedline_Update();
 
         _word_anim_sys->update(_anims_add, _anims_drop, _carried, _ctx.words, dt);
-        lex_CarriedLine(_carried);
+        if (_carried.size != _carried_last_size) {
+            if (_carried.size > 0)
+                lex_CarriedLine(_carried);
+            _carried_last_size = _carried.size;
+        }
 
         _pult_sys->  update(dt, *_ctx.camera);
         _plate_sys-> update(dt, *_ctx.player, _level_director->get_StepPlates());
diff --git a/src/states/game_state.hpp b/src/states/game_state.hpp
index 1edad80..318d00d 100644
--- a/src/states/game_state.hpp
+++ b/src/states/game_state.hpp
@@ -55,8 +55,9 @@ class GameState : public IState
     cpputils::unique_ptr<WordAiSystem>       _word_ai_sys;
 
 
-    double   _pick_cooldown  { 0.0 };
-    double   _shoot_cooldown { 0.0 };
+    size_t _carried_last_size { 0 };
+    double _pick_cooldown     { 0.0 };
+    double _shoot_cooldown    { 0.0 };
 
     std::string        _typing_last;
 
diff --git a/src/text/handler.cpp b/src/text/handler.cpp
index 9ee98e3..33fb39a 100644
--- a/src/text/handler.cpp
+++ b/src/text/handler.cpp
@@ -110,6 +110,8 @@ void Handler::clear()
     _label_off .clear();
     _label_text.clear();
     _view_tag = 0;
+    _borrowed = nullptr; _view_tag = 0;
+
     mark_Dirty();
 }
 
@@ -144,6 +146,7 @@ Handler::set_Lines(const DynArray<std::string>& lines)
 void
 Handler::append_Line(const std::string& text)
 {
+    //SPIKE("append_Line.detail");
     for (Line& l : _lines) {
         l.y += _line_height;
         for (TokenPtr& t : l.tokens) if (t) t->pos.y += _line_height;
@@ -160,6 +163,7 @@ Handler::append_Line(const std::string& text)
     ln.tokens.push_back(std::move(t));
 
     _lines.push_back(std::move(ln));
+    mark_Dirty();
 }
 
 
@@ -864,6 +868,9 @@ Handler::render(GlRenderer& gl, const Camera& cam, const Light& light) const
             if (l.num_right) l.num_right->draw(gl, cam, light);
         }
     }
+    if (_borrowed)
+        for (const TokenPtr& t : *_borrowed)
+            if (t) t->draw(gl, cam, light);
 }
 
 
diff --git a/src/text/handler.hpp b/src/text/handler.hpp
index 7658791..58697be 100644
--- a/src/text/handler.hpp
+++ b/src/text/handler.hpp
@@ -116,6 +116,8 @@ public:
     void kick          (size_t word_index, const Vec3& projectile_vel, const Vec3& normal);
     bool view_Is       (size_t tag) const { return tag != 0 && tag == _view_tag; }
     void set_View      (size_t tag)       { _view_tag = tag; }
+    void set_Borrowed  (const DynArray<TokenPtr>* borrowed) { _borrowed = borrowed; }
+    void clear_Borrowed() { _borrowed = nullptr; }
     bool is_Empty      () const { return _lines.empty() || _lines[0].tokens.empty(); }
     const DynArray<TokenPtr>&
          get_Words     () const;
@@ -136,7 +138,8 @@ private:
     double _append_y     { 0.0 };
     SDL_FColor _append_color { 0.45f, 0.45f, 0.45f, 1.0f };
 
-    DynArray<std::string> _status;
+    DynArray<std::string>     _status;
+    const DynArray<TokenPtr>* _borrowed { nullptr };
 
     size_t _view_tag { 0 };          // identity of currently-materialised info-wall content; 0 = none
 
diff --git a/src/text/mesh.cpp b/src/text/mesh.cpp
index 0a09299..5dfb2b6 100644
--- a/src/text/mesh.cpp
+++ b/src/text/mesh.cpp
@@ -328,6 +328,8 @@ acquire_Glyph(FT_Face face, uint32_t ch, float scale)
     GlyphKey key{ ch, (int)SDL_lround((double)scale * 1e7) };
     auto it = g_glyphs.find(key);
     if (it != g_glyphs.end()) return &it->second;
+    // SDL_Log("GLYPH MISS '%c' scale_q=%d (cache=%zu)", (char)ch, key.scale_q, g_glyphs.size());
+
 
     GlyphMesh gm;
     FT_UInt gi = FT_Get_Char_Index(face, (FT_ULong)ch);
@@ -359,7 +361,7 @@ bool
 TextMesh::build(const std::string& font_path,
                 const std::string& text, int size, float /*depth*/, float scale)
 {
-    // SPIKE("mesh.build");
+    SPIKE("mesh.build");
     verts.clear(); tris.clear(); is_front.clear(); vertex_normals.clear();
 
     FT_Face face = acquire_Face(font_path, size);
diff --git a/src/wall/wall.cpp b/src/wall/wall.cpp
index e7b0696..d26c0d0 100644
--- a/src/wall/wall.cpp
+++ b/src/wall/wall.cpp
@@ -1,6 +1,9 @@
+#include <unordered_map>
+
 #include "text/token.hpp"
 #include "entities/world.hpp"
 #include "text/handler.hpp"
+#include "text/text.hpp"
 #include "wall.hpp"
 
 namespace Wall
@@ -107,25 +110,47 @@ namespace Wall
     }
 
 
+    static std::unordered_map<std::string, DynArray<Text::TokenPtr>> g_info_cache;
+
     void
     show_TokenInfo(::Text::Handler& info, const std::string& token_text)
     {
-        const size_t tag = std::hash<std::string>{}(token_text) | 1;
-        if (info.view_Is(tag)) return;
+        auto it = g_info_cache.find(token_text);
+        if (it == g_info_cache.end()) {
+            Text::Token::Type        tt = Text::CppHighlight::classify_Word(token_text);
+            Text::Token::Description d  = Text::Token::get_Description(token_text, tt);
+
+            const std::string line1 = token_text + "  [" + Text::Token::get_TypeName(tt) + "]";
+
+            DynArray<std::string> lines;
+            lines.push_back(line1);
+            for (const std::string& w : Text::wrap_String(d.short_desc, 92))
+                if (!w.empty()) lines.push_back(w);
+            for (const std::string& w : Text::wrap_String(d.long_desc, 92))
+                if (!w.empty()) lines.push_back(w);
+
+            const Wall::Transform tf =
+                Wall::get_Transform(Wall::Role::Info, World::get_BoxScale());
+            float y = World::get_FloorY<float>() + 1.0f;
+
+            DynArray<Text::TokenPtr> toks;
+            for (const std::string& line : lines) {
+                Text::TokenPtr t = Text::make_Token(line, Text::Token::depth_wall, 0.003f,
+                                                    tf.position, ConfigColor::white);
+                t->yaw   = tf.yaw;
+                t->pos   = tf.position;
+                t->pos.y = y;
+                t->set_ColorSource(Text::ColorSource::Static);
+                t->set_Color(ConfigColor::white);
+                toks.push_back(std::move(t));
+                y += ConfigWall::text_line_spacing;
+            }
+
+            it = g_info_cache.emplace(token_text, std::move(toks)).first;
+        }
 
         info.clear();
-
-        Text::Token::Type tt = Text::CppHighlight::classify_Word(token_text);
-        Text::Token::Description d  = Text::Token::get_Description(token_text, tt);
-
-        const std::string line1 = token_text + "  [" + Text::Token::get_TypeName(tt) + "]";
-        const std::string line2 = d.short_desc;
-        const std::string line3 = d.long_desc;
-
-        for (const std::string& line : { line1, line2, line3 })
-            if (!line.empty()) info.append_Line(line);
-
-        info.set_View(tag);
+        info.set_Borrowed(&it->second);
     }
 
 
diff --git a/src/wall/wall.hpp b/src/wall/wall.hpp
index 0d22e68..4ca0c64 100644
--- a/src/wall/wall.hpp
+++ b/src/wall/wall.hpp
@@ -26,7 +26,7 @@ namespace Wall
     Vec3     inward_Normal (Wall::Position pos);
 
     Drop  attach_ToNearestWall(Text::TokenPtr src);
-    void  show_TokenInfo      (::Text::Handler& info, const std::string& token_text);
+    void  show_TokenInfo      (Text::Handler& info, const std::string& token_text);
     float tilt_TwardEye       (const Vec3& text_pos, const Vec3& eye_pos);
 
     struct Transform