Nimbin[12]?SDL & Graphics / sdl_runtime_compiler / src/systems/pult_system.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/systems/pult_system.cpp 5.5 KB · 194 lines raw
#include "entities/camera.hpp"
#include "entities/player.hpp"
#include "pult_system.hpp"
#include "rendering/gl_renderer.hpp"
#include "systems/physics_system.hpp"
#include "wall/label.hpp"
#include "wall/wall.hpp"

namespace
Nimbin
{

void
PultSystem::init(DynArray<GameObjectPtr>& scenery,
                 DynArray<PultButton*>&   buttons_out,
                 float                    world_scale)
{
    const float  floor_y = -world_scale;
    const float  pult_y  = floor_y + Pult::H;
    const double inset   = 3.0;
    const float  btn_dy  = Pult::H + 0.10f + 0.04f;
    const float  lane_1  = -5.5f;
    const float  lane_2  =  8.5f;
    const float  lane_3  =  5.5f;

    auto make_pult_pos = [&](Wall::Role role, float along) -> Vec3
    {
        const Wall::Transform wall = Wall::get_Transform(role, world_scale);

        switch (wall.wall_position) {
            case Wall::Position::PosX: return { wall.position.x - inset, pult_y, along };
            case Wall::Position::NegX: return { wall.position.x + inset, pult_y, along };
            case Wall::Position::PosZ: return { along, pult_y, wall.position.z - inset };
            case Wall::Position::NegZ:
            default:                   return { along, pult_y, wall.position.z + inset };
        }
    };

    auto spawn_pult = [&](const std::string& name,
                          Wall::Role role, float along) -> Pult*
    {
        auto owned = cpputils::make_unique<Pult>(name, make_pult_pos(role, along));
        Pult* raw  = owned.get();
        _pults.push_back(raw);
        scenery.push_back(std::move(owned));
        return raw;
    };

    auto add_btn = [&](Pult* pult, const std::string& lbl,
                       PultAction act, float dx, float dz)
    {
        Vec3 bpos {
            pult->pos.x + static_cast<double>(dx),
            pult->pos.y + static_cast<double>(btn_dy),
            pult->pos.z + static_cast<double>(dz)
        };

        auto owned   = cpputils::make_unique<PultButton>(lbl, act, bpos);
        PultButton* raw = owned.get();
        buttons_out.push_back(raw);
        pult->buttons.push_back(raw);
        scenery.push_back(std::move(owned));
    };

    Pult* scroll  = spawn_pult("Scroll",  Wall::Role::Editor,   lane_1);
    add_btn(scroll,  "UP",    PultAction::ScrollEditorUp,   0.0f, -0.42f);
    add_btn(scroll,  "DOWN",  PultAction::ScrollEditorDown, 0.0f,  0.42f);

    Pult* clr     = spawn_pult("Clear",   Wall::Role::Editor,   lane_2);
    add_btn(clr,     "CLEAR", PultAction::ClearEditor,      0.0f, 0.0f);

    Pult* compile = spawn_pult("Compile", Wall::Role::Compiler, lane_3);
    add_btn(compile, "BUILD", PultAction::Compile,          0.0f, 0.0f);

    Pult* run     = spawn_pult("Run",     Wall::Role::Program,  lane_2);
    add_btn(run,     "RUN",   PultAction::RunProgram,       0.0f, 0.0f);

    Pult* connp   = spawn_pult("Connect", Wall::Role::Program,  lane_3);
    add_btn(connp,   "CONN",  PultAction::ConnectProgram,   0.0f, 0.0f);
    _connect_program = connp;

    Pult* conne  = spawn_pult("Edit",     Wall::Role::Editor,   lane_3);
    add_btn(conne,   "EDIT", PultAction::ConnectEditor,     0.0f, 0.0f);
    _connect_editor  = conne;
}


std::optional<PultAction>
PultSystem::try_Activate(GameObject* obj, const DynArray<PultButton*>& buttons)
{
    if (!obj) return std::nullopt;

    for (PultButton* btn : buttons) {
        if (btn == obj) {
            btn->press();
            return btn->action;
        }
    }
    return std::nullopt;
}


std::optional<PultAction>
PultSystem::handle_ProjectileContact(const ProjectileContactEvent& ev,
                                     const DynArray<PultButton*>&  buttons)
{
    if (!ev.other) return std::nullopt;

    for (PultButton* btn : buttons) {
        if (!btn->pressed && btn == ev.other) {
            btn->press();
            return btn->action;
        }
    }
    return std::nullopt;
}


static bool
player_OnButton(const Player& p, const PultButton& b)
{
    constexpr double TOL = 0.10;

    const double hx = b.shape.half_extents.x;
    const double hy = b.shape.half_extents.y;
    const double hz = b.shape.half_extents.z;

    if (std::fabs(p.pos.x - b.pos.x) > hx + TOL) return false;
    if (std::fabs(p.pos.z - b.pos.z) > hz + TOL) return false;

    const double dy = p.pos.y - (b.pos.y + hy);
    return dy >= -0.10 && dy <= 1.8;
}


std::optional<PultAction>
PultSystem::handle_PlayerContact(const Player& player, const DynArray<PultButton*>&  buttons)
{
    std::optional<PultAction> fired;
    for (PultButton* btn : buttons) {
        const bool over = player_OnButton(player, *btn);

        if (over && !btn->player_on) {
            btn->press();
            if (!fired) fired = btn->action;
        }
        btn->player_on = over;
    }
    return fired;
}


void
PultSystem::update(double dt, const Camera& camera)
{
    for (Pult* p : _pults) {
        p->tick(dt);
        p->label.update(dt, camera);
    }
}


void
PultSystem::draw_Labels(GlRenderer& gl, const Camera& camera, const Light& light) const
{
    for (const Pult* p : _pults)
        p->label.draw(gl, camera, light);
}


DynArray<Text::Handler*>
PultSystem::get_Labels() const
{
    DynArray<Text::Handler*> out;
    out.reserve(_pults.size());

    for (Pult* p : _pults) out.push_back(&p->label);

    return out;
}

Vec3
PultSystem::get_ConnectProgramPos() const
{
    return _connect_program ? _connect_program->pos : Vec3{};
}

Vec3
PultSystem::get_ConnectEditorPos() const
{
    return _connect_editor ? _connect_editor->pos : Vec3{};
}

} // namespace Nimbin