Nimbin[12]?SDL & Graphics / sdl_runtime_compiler / src/systems/carry_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/carry_system.cpp 4.1 KB · 186 lines raw
#include "carry_system.hpp"
#include "entities/camera.hpp"

namespace
Nimbin
{

bool
CarriedLine::empty() const
{
    return size == 0;
}


void
CarriedLine::push(Text::TokenPtr w)
{
    CarriedWordNodePtr node = cpputils::make_unique<CarriedWordNode>(std::move(w));
    node->prev = last;

    if (!first) {
        first = std::move(node);
        last  = first.get();
    }
    else {
        last->next = std::move(node);
        last       = last->next.get();
    }
    size++;
}


Text::TokenPtr
CarriedLine::pop_back()
{
    while (last && !last->word) {
        if (last->prev) {
            last = last->prev;
            last->next.reset();
        }
        else {
            first.reset();
            last = nullptr;
        }
        size--;
    }
    if (!last) return nullptr;

    Text::TokenPtr word = std::move(last->word);

    if (last->prev) {
        last = last->prev;
        last->next.reset();
    }
    else {
        first.reset();
        last = nullptr;
    }
    size--;
    return word;
}


Text::TokenPtr
CarriedLine::pop_front()
{
    if (!first) return nullptr;

    Text::TokenPtr word = std::move(first->word);

    if (first->next) {
        first       = std::move(first->next);
        first->prev = nullptr;
    }
    else {
        first.reset();
        last = nullptr;
    }

    size--;
    return word;
}


DynArray<CarriedWordNode*>
CarriedLine::nodes() const
{
    DynArray<CarriedWordNode*> result;
    for (CarriedWordNode* node = first.get(); node; node = node->next.get())
        result.push_back(node);
    return result;
}


DynArray<CarriedWordNode*> 
CarriedLine::reverse_nodes() const
{
    DynArray<CarriedWordNode*> result;
    for (CarriedWordNode* node = last; node; node = node->prev)
        result.push_back(node);
    return result;
}

void
CarriedLine::clear()
{
    first.reset();
    last = nullptr;
    size = 0;
}


void
CarriedLine::compact()
{
    DynArray<Text::TokenPtr> survivors;
    for (CarriedWordNode* node = first.get(); node; node = node->next.get())
        if (node->word) survivors.push_back(std::move(node->word));

    clear();
    for (Text::TokenPtr& w : survivors)
        push(std::move(w));
}



Vec3
CarriedLine::get_LineAnchor(const Camera& camera, double carry_dist)
{
    const Vec3& right = camera.right;
    const Vec3  up    = Math::cross(camera.right, camera.fwd);

    return {
        camera.pos.x + camera.fwd.x * carry_dist
                     + right.x * Config::Carry::hand_right - up.x * Config::Carry::hand_down,
        camera.pos.y + camera.fwd.y * carry_dist
                     + right.y * Config::Carry::hand_right - up.y * Config::Carry::hand_down,
        camera.pos.z + camera.fwd.z * carry_dist
                     + right.z * Config::Carry::hand_right - up.z * Config::Carry::hand_down
    };
}


DynArray<Vec3>
CarriedLine::get_SlotPosition(const Vec3& anchor,
                              const Vec3& right,
                              double carry_gap)
{
    DynArray<Vec3> positions;
    DynArray<CarriedWordNode*> nodes = reverse_nodes();

    if (nodes.empty()) return positions;

    double current_offset = 0.0;

    for (size_t i = 0; i < nodes.size(); i++) {
        if (!nodes[i]->word) continue;

        positions.push_back({
            anchor.x + right.x * current_offset,
            anchor.y + right.y * current_offset,
            anchor.z + right.z * current_offset
        });

        if (i + 1 < nodes.size() && nodes[i + 1]->word) {
            double half_extent_curr = 0.5,
                   half_extent_next = 0.5;

            if (nodes[i]->word->type == ObjectType::Text)
                half_extent_curr = static_cast<const Text::Token::Data&>(*nodes[i]->word).half_extent;
            else
                half_extent_curr = nodes[i]->word->shape.half_extents.x;

            if (nodes[i+1]->word->type == ObjectType::Text)
                half_extent_next = static_cast<const Text::Token::Data&>(*nodes[i+1]->word).half_extent;
            else
                half_extent_next = nodes[i+1]->word->shape.half_extents.x;

            current_offset -= (half_extent_curr + half_extent_next + carry_gap);
        }
    }

    return positions;
}

} // namespace Nimbin