Nimbin[12]?SDL & Graphics / sdl_runtime_compiler / src/wall/wall.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/wall.cpp 5.4 KB · 182 lines raw
#include <unordered_map>

#include "text/token.hpp"
#include "entities/world.hpp"
#include "text/handler.hpp"
#include "text/text.hpp"
#include "wall.hpp"

namespace
Nimbin
{
namespace
Wall
{


Role
role_Of(Position p)
{
    switch (p) {
        case Position::PosX: return Role::Program;
        case Position::NegX: return Role::Editor;
        case Position::PosZ: return Role::Info;
        case Position::NegZ: return Role::Compiler;
    }
    return Role::Program;
}


Position
position_Of(Role r)
{
    switch (r) {
        case Role::Program:  return Position::PosX;
        case Role::Editor:   return Position::NegX;
        case Role::Info:     return Position::PosZ;
        case Role::Compiler: return Position::NegZ;
    }
    return Position::PosX;
}


Vec3 inward_Normal(Wall::Position pos)
{
    switch (pos) {
        case Wall::Position::PosX: return { -1.0, 0.0,  0.0 };
        case Wall::Position::NegX: return {  1.0, 0.0,  0.0 };
        case Wall::Position::PosZ: return {  0.0, 0.0, -1.0 };
        case Wall::Position::NegZ: return {  0.0, 0.0,  1.0 };
    }
    return { 0.0, 0.0, 1.0 };
}


Transform
get_Transform(Role role, float world_scale)
{

    switch (position_Of(role)) {
        case Position::PosX:
            return { Position::PosX,
                     { world_scale - Config::Wall::text_offset, 0.0, 0.0 },
                     -SDL_PI_F * 0.5f };
        case Position::NegX:
            return { Position::NegX,
                     { -world_scale + Config::Wall::text_offset, 0.0, 0.0 },
                     SDL_PI_F * 0.5f };
        case Position::PosZ:
            return { Position::PosZ,
                     { 0.0, 0.0, world_scale - Config::Wall::text_offset },
                     SDL_PI_F };
        case Position::NegZ:
        default:
            return { Position::NegZ,
                     { 0.0, 0.0, -world_scale + Config::Wall::text_offset },
                     0.0f };
    }
}


Vec3
get_Position(Role role, float world_scale)
{
    return get_Transform(role, world_scale).position;
}


Drop
attach_ToNearestWall(Text::TokenPtr src)
{
    const double ws = World::get_BoxScale<double>();
    const double x  = src->pos.x;
    const double z  = src->pos.z;

    Vec3& he = src->shape.half_extents;

    const double dPX = ws - x;
    const double dNX = ws + x;
    const double dPZ = ws - z;
    const double dNZ = ws + z;

    Wall::Position wall_pos;
    float          yaw;

    const double wo = static_cast<double>(Config::Wall::text_offset);
    if (dPX <= dNX && dPX <= dPZ && dPX <= dNZ) { wall_pos = Wall::Position::PosX; src->pos.x =  ws - he.z - wo; yaw = -SDL_PI_F * 0.5f; }
    else if (dNX <= dPZ && dNX <= dNZ)          { wall_pos = Wall::Position::NegX; src->pos.x = -ws + he.z + wo; yaw =  SDL_PI_F * 0.5f; }
    else if (dPZ <= dNZ)                        { wall_pos = Wall::Position::PosZ; src->pos.z =  ws - he.z - wo; yaw =  SDL_PI_F;        }
    else                                        { wall_pos = Wall::Position::NegZ; src->pos.z = -ws + he.z + wo; yaw =  0.0f;            }

    src->yaw = yaw;

    return Drop{ Wall::role_Of(wall_pos), std::move(src) };
}


static std::unordered_map<std::string, DynArray<Text::TokenPtr>>
g_info_cache;

void
show_TokenInfo(Text::Handler& info, const std::string& token_text)
{
    auto it = g_info_cache.find(token_text);
    if (it == g_info_cache.end()) {
        Text::Token::Type        token_type  = Text::CppHighlight::classify_Word(token_text);
        Text::Token::Description description = Text::Token::get_Description(token_text, token_type);

        const std::string line1 = token_text + "  [" + Text::Token::get_TypeName(token_type) + "]";

        DynArray<std::string> lines;
        lines.push_back(line1);
        for (const std::string& w : Text::wrap_String(description.short_desc, 92))
            if (!w.empty()) lines.push_back(w);
        for (const std::string& w : Text::wrap_String(description.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 token = Text::make_Token(line, Text::Token::depth_wall, 0.003f,
                                                    tf.position, Config::Color::white);
            token->yaw   = tf.yaw;
            token->pos   = tf.position;
            token->pos.y = y;
            token->set_ColorSource(Text::ColorSource::Static);
            token->set_Color(Config::Color::white);
            toks.push_back(std::move(token));
            y += Config::Wall::text_line_spacing;
        }

        it = g_info_cache.emplace(token_text, std::move(toks)).first;
    }

    info.clear();
    info.set_Borrowed(&it->second);
}


float
tilt_TwardEye(const Vec3& text_pos, const Vec3& eye_pos)
{
    const double dx = eye_pos.x - text_pos.x;
    const double dy = eye_pos.y - text_pos.y;
    const double dz = eye_pos.z - text_pos.z;

    const double horiz = SDL_sqrt(dx*dx + dz*dz);
    if (horiz < 0.01) return 0.0f;

    double pitch = -SDL_atan2(dy, horiz);

    if (pitch >  static_cast<double>(Config::Wall::max_tilt)) pitch =  Config::Wall::max_tilt;
    if (pitch < -static_cast<double>(Config::Wall::max_tilt)) pitch = -Config::Wall::max_tilt;
    return static_cast<float>(pitch);
}


} // namespace Wall

} // namespace Nimbin