Nimbin[12]?SDL & Graphics / sdl_runtime_compiler / src/wall/label.cpp

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
src/wall/label.cpp 4.7 KB · 131 lines raw
#include "entities/camera.hpp"
#include "rendering/gl_renderer.hpp"
#include "utils/config.hpp"
#include "wall/label.hpp"
#include "wall/wall.hpp"

namespace
Nimbin
{

// ── Label appearance ──────────────────────────────────────────────────────────

namespace {

static const char* label_Name(Wall::Role r)
{
    switch (r) {
        case Wall::Role::Program:  return "Program";
        case Wall::Role::Editor:   return "Editor";
        case Wall::Role::Info:     return "Info";
        case Wall::Role::Compiler: return "Compiler";
    }
    return "";
}

// Per-role tint — echoes the wall surface colors from wall_surfaces.cpp.
static SDL_FColor label_Color(Wall::Role r)
{
    switch (r) {
        case Wall::Role::Program:  return Config::Color::program_label;
        case Wall::Role::Editor:   return Config::Color::editor_label;
        case Wall::Role::Info:     return Config::Color::info_label;
        case Wall::Role::Compiler: return Config::Color::compiler_label;
    }
    return Config::Color::white;
}

} // namespace


// ── generate_All ─────────────────────────────────────────────────────────────

DynArray<Wall::Label>
Wall::Label::generate_All(float world_scale)
{
    DynArray<Wall::Label> labels;
    labels.reserve(4);

    const float label_y = -world_scale * 0.48f;

    // Pull slightly further from the wall so it floats in front of wall text.
    const double extra_offset = 2.5f;

    // Large scale so the name is readable from across the room.
    // depth is Text::Token::depth_wall * 4 for chunky, visible letters.
    const float label_scale = 0.012f;
    const float label_depth = Text::Token::depth_wall * 4.0f;

    for (uint8_t ri = 0; ri < 4; ++ri) {
        Wall::Role      role = static_cast<Wall::Role> (ri);
        Wall::Position  pos  = Wall::position_Of       (role);
        Wall::Transform tf   = Wall::get_Transform     (role, world_scale);

        Vec3 anch = tf.position;
        anch.y = static_cast<double>(label_y);

        switch (pos) {
            case Wall::Position::PosX: anch.x -= extra_offset; break;
            case Wall::Position::NegX: anch.x += extra_offset; break;
            case Wall::Position::PosZ: anch.z -= extra_offset; break;
            case Wall::Position::NegZ: anch.z += extra_offset; break;
        }

        Wall::Label wl;
        wl.role     = role;
        wl.anchor   = anch;
        wl.face_yaw = tf.yaw;

        wl.label.set_Style      (label_Color(role), label_depth, label_scale);
        wl.label.set_FaceCamera  (false);
        wl.label.set_FaceYaw    (tf.yaw);
        wl.label.set_Collidable (true);
        wl.label.set_Centre     (anch);
        wl.label.set_Text       (label_Name(role));

        labels.push_back        (std::move(wl));
    }

    return labels;
}


// ── on_Hit ───────────────────────────────────────────────────────────────────

void
Wall::Label::on_Hit(size_t word_index, const Vec3& projectile_vel)
{
    const Vec3 normal = Wall::inward_Normal(Wall::position_Of(role));
    label.kick(word_index, projectile_vel, normal);
}


// ── update ───────────────────────────────────────────────────────────────────

void
Wall::Label::update(double dt, const Camera& camera)
{
    // Positions + jiggle spring first. In non-facecam mode Text::Handler::update
    // forces every word's pitch to 0, so we must apply our eye-tilt AFTER it,
    // not before — otherwise the tilt gets clobbered. Pitch doesn't affect the
    // positions update() computes, so ordering it last is safe.
    label.update(dt, camera);

    // Tilt up/down toward the player's eye, clamped — identical to the
    // editor wall text tilt in wall.hpp::tilt_TwardEye. Shared anchor pitch
    // keeps the whole word reading as one rigid plane.
    const float pitch = Wall::tilt_TwardEye(anchor, camera.pos);
    for (const Text::TokenPtr& w : label.get_Words())
        if (w) w->pitch = pitch;
}


// ── draw ─────────────────────────────────────────────────────────────────────

void
Wall::Label::draw(GlRenderer& gl, const Camera& camera, const Light& light) const
{
    label.draw(gl, camera, light);
}

} // namespace Nimbin