2021-09-20 20:20:06 +02:00

357 lines
8.1 KiB
C++

#include <std_include.hpp>
#include "element.hpp"
#include <utils/string.hpp>
#define fps_font game::R_RegisterFont("fonts/fira_mono_regular.ttf", 25)
namespace ui_scripting
{
namespace
{
uint64_t next_id;
float screen_max[2];
struct point
{
float x;
float y;
float f2;
float f3;
};
struct rectangle
{
point p0;
point p1;
point p2;
point p3;
};
std::unordered_map<std::string, std::string> font_map =
{
{"bank", "fonts/bank.ttf"},
{"fira_mono_bold", "fonts/fira_mono_bold.ttf"},
{"fira_mono_regular", "fonts/fira_mono_regular.ttf"},
{"defaultbold", "fonts/defaultbold.otf"},
{"objective", "fonts/defaultbold.otf"},
{"default", "fonts/default.otf"},
};
std::unordered_map<std::string, alignment> alignment_map =
{
{"left", alignment::start},
{"top", alignment::start},
{"center", alignment::middle},
{"right", alignment::end},
{"bottom", alignment::end},
};
float get_align_value(alignment align, float text_width, float w)
{
switch (align)
{
case (alignment::start):
return 0.f;
case (alignment::middle):
return (w / 2.f) - (text_width / 2.f);
case (alignment::end):
return w - text_width;
default:
return 0.f;
}
}
void draw_image(float x, float y, float w, float h, float* transform, float* color, game::Material* material)
{
game::rectangle rect;
rect.p0.x = x;
rect.p0.y = y;
rect.p0.f2 = 0.f;
rect.p0.f3 = 1.f;
rect.p1.x = x + w;
rect.p1.y = y;
rect.p1.f2 = 0.f;
rect.p1.f3 = 1.f;
rect.p2.x = x + w;
rect.p2.y = y + h;
rect.p2.f2 = 0.f;
rect.p2.f3 = 1.f;
rect.p3.x = x;
rect.p3.y = y + h;
rect.p3.f2 = 0.f;
rect.p3.f3 = 1.f;
game::R_DrawRectangle(&rect, transform[0], transform[1], transform[2], transform[3], color, material);
}
void check_resize()
{
screen_max[0] = game::ScrPlace_GetViewPlacement()->realViewportSize[0];
screen_max[1] = game::ScrPlace_GetViewPlacement()->realViewportSize[1];
}
float relative(float value)
{
return (value / 1920.f) * screen_max[0];
}
int relative(int value)
{
return (int)(((float)value / 1920.f) * screen_max[0]);
}
}
element::element()
: id(next_id++)
{
}
void element::set_horzalign(const std::string& value)
{
const auto lower = utils::string::to_lower(value);
if (alignment_map.find(lower) == alignment_map.end())
{
this->horzalign = alignment::start;
return;
}
const auto align = alignment_map[lower];
this->horzalign = align;
}
void element::set_vertalign(const std::string& value)
{
const auto lower = utils::string::to_lower(value);
if (alignment_map.find(lower) == alignment_map.end())
{
this->vertalign = alignment::start;
return;
}
const auto align = alignment_map[lower];
this->vertalign = align;
}
void element::set_text(const std::string& _text)
{
this->text = _text;
}
void element::set_font(const std::string& _font, const int _fontsize)
{
this->fontsize = _fontsize;
const auto lowercase = utils::string::to_lower(_font);
if (font_map.find(lowercase) == font_map.end())
{
this->font = "default";
}
else
{
this->font = lowercase;
}
}
void element::set_font(const std::string& _font)
{
const auto lowercase = utils::string::to_lower(_font);
if (font_map.find(lowercase) == font_map.end())
{
this->font = "default";
}
else
{
this->font = lowercase;
}
}
void element::set_text_offset(float _x, float _y)
{
this->text_offset[0] = _x;
this->text_offset[1] = _y;
}
void element::set_background_color(float r, float g, float b, float a)
{
this->background_color[0] = r;
this->background_color[1] = g;
this->background_color[2] = b;
this->background_color[3] = a;
}
void element::set_color(float r, float g, float b, float a)
{
this->color[0] = r;
this->color[1] = g;
this->color[2] = b;
this->color[3] = a;
}
void element::set_glow_color(float r, float g, float b, float a)
{
this->glow_color[0] = r;
this->glow_color[1] = g;
this->glow_color[2] = b;
this->glow_color[3] = a;
}
void element::set_border_material(const std::string& _material)
{
this->border_material = _material;
}
void element::set_border_color(float r, float g, float b, float a)
{
this->border_color[0] = r;
this->border_color[1] = g;
this->border_color[2] = b;
this->border_color[3] = a;
}
void element::set_border_width(float top)
{
this->border_width[0] = top;
this->border_width[1] = top;
this->border_width[2] = top;
this->border_width[3] = top;
}
void element::set_border_width(float top, float right)
{
this->border_width[0] = top;
this->border_width[1] = right;
this->border_width[2] = top;
this->border_width[3] = right;
}
void element::set_border_width(float top, float right, float bottom)
{
this->border_width[0] = top;
this->border_width[1] = right;
this->border_width[2] = bottom;
this->border_width[3] = bottom;
}
void element::set_border_width(float top, float right, float bottom, float left)
{
this->border_width[0] = top;
this->border_width[1] = right;
this->border_width[2] = bottom;
this->border_width[3] = left;
}
void element::set_slice(float left_percent, float top_percent, float right_percent, float bottom_percent)
{
this->slice[0] = left_percent;
this->slice[1] = top_percent;
this->slice[2] = right_percent;
this->slice[3] = bottom_percent;
}
void element::set_material(const std::string& _material)
{
this->material = _material;
}
void element::set_rect(const float _x, const float _y, const float _w, const float _h)
{
this->x = _x;
this->y = _y;
this->w = _w;
this->h = _h;
}
void element::render() const
{
check_resize();
if (this->background_color[3] > 0)
{
const auto background_material = game::Material_RegisterHandle(this->material.data());
draw_image(
relative(this->x) + relative(this->border_width[3]),
relative(this->y) + relative(this->border_width[0]),
relative(this->w),
relative(this->h),
(float*)this->slice,
(float*)this->background_color,
background_material
);
}
if (this->border_color[3] > 0)
{
const auto _border_material = game::Material_RegisterHandle(this->border_material.data());
draw_image(
relative(this->x),
relative(this->y),
relative(this->w) + relative(this->border_width[1]) + relative(this->border_width[3]),
relative(this->border_width[0]),
(float*)this->slice,
(float*)this->border_color,
_border_material
);
draw_image(
relative(this->x) + relative(this->border_width[3]) + relative(this->w),
relative(this->y) + relative(this->border_width[0]),
relative(this->border_width[1]),
relative(this->h),
(float*)this->slice,
(float*)this->border_color,
_border_material
);
draw_image(
relative(this->x),
relative(this->y) + relative(this->h) + relative(this->border_width[0]),
relative(this->w) + relative(this->border_width[1]) + relative(this->border_width[3]),
relative(this->border_width[2]),
(float*)this->slice,
(float*)this->border_color,
_border_material
);
draw_image(
relative(this->x),
relative(this->y) + relative(this->border_width[0]),
relative(this->border_width[3]),
relative(this->h),
(float*)this->slice,
(float*)this->border_color,
_border_material
);
}
if (!this->text.empty())
{
const auto fontname = font_map[this->font];
const auto _font = game::R_RegisterFont(fontname.data(), relative(this->fontsize));
const auto text_width = game::R_TextWidth(this->text.data(), 0x7FFFFFFF, _font);
auto _horzalign = get_align_value(this->horzalign, (float)text_width, relative(this->w));
auto _vertalign = get_align_value(this->vertalign, (float)relative(this->fontsize), relative(this->h));
game::CL_DrawTextPhysicalWithEffects(
this->text.data(),
0x7FFFFFFF,
_font,
relative(this->x) + relative(this->text_offset[0]) + _horzalign + relative(this->border_width[3]),
relative(this->y) + relative(this->text_offset[1]) + _vertalign + relative(this->fontsize) + relative(this->border_width[0]),
1.f, 1.f,
(float*)this->color, 0,
(float*)this->glow_color,
0, 0, 0, 0, 0, 0, 0
);
}
}
}