#include #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(); 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(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> 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 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() + 1.0f; DynArray 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(Config::Wall::max_tilt)) pitch = Config::Wall::max_tilt; if (pitch < -static_cast(Config::Wall::max_tilt)) pitch = -Config::Wall::max_tilt; return static_cast(pitch); } } // namespace Wall } // namespace Nimbin