# Stage 2
- reAdd Text Shorting - make SpriteSheet part of SmartCtor - Add Some Gaussian Blur func (not functional for now) - Add Image Indexing functions and Reverse32 for (RGBA -> ABGR) - Add Transparency flag to Keyboard and Fix its Render Prder - Add UI7 Alignment API - Incldes PushAlignment (One way Alignment, JoinAlign, etc) - Make Setter for Scroll Offset public - Make Getter for ScrollMod Public - Add a Check if Menu is duing an animated scroll - Add FindMenu to Context for Modifications after Context::EndMenu - Fix Major Issue in Lithium InBox Function - Fix TextAlignRight and Add PerLine Text Shorting - Fix Screen being unused in Performance Overlay - Add Beta Slider Dragging - Dont Handle Inputs for Objects when scrolling - Add a MainArea to Not Handle Inputs outside of it - Simplefied some logic - TODO: - Write TextWrap Function - Add PerLine text Align - Track and Fix a lot of UI7 Bugs such as Alignment Issues etc
This commit is contained in:
@ -281,8 +281,8 @@ void Renderer::StaticText::SetPos(const vec2& pos) {
|
||||
void Renderer::StaticText::SetLayer(int layer) { text->ReLayer(layer); }
|
||||
|
||||
bool Renderer::InBox(const vec2& pos, const vec2& szs, const vec4& rect) {
|
||||
return (pos[0] < rect[2] || pos[1] < rect[3] || pos[0] + szs[0] > rect[0] ||
|
||||
pos[1] + szs[1] > rect[1]);
|
||||
return (pos[0] + szs[0] >= rect[0] && pos[1] + szs[1] >= rect[1] &&
|
||||
pos[0] <= rect[2] && pos[1] <= rect[3]);
|
||||
}
|
||||
|
||||
bool Renderer::InBox(const vec2& pos, const vec4& rect) {
|
||||
@ -398,7 +398,7 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
rpos = rbox * 0.5 - td * 0.5 + pos;
|
||||
}
|
||||
if (flags & LITextFlags_AlignRight) {
|
||||
rpos[0] = rbox[0] - td[0];
|
||||
rpos[0] = rpos[0] - td[0];
|
||||
}
|
||||
|
||||
std::vector<std::string> lines;
|
||||
@ -409,7 +409,13 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
}
|
||||
|
||||
for (auto& it : lines) {
|
||||
if (rpos[1] + off[1] + lh < 0) {
|
||||
if (flags & LITextFlags_Short) {
|
||||
vec2 tmp_dim;
|
||||
it = ShortText(it, box.x() - pos.x(), tmp_dim);
|
||||
}
|
||||
/// Well support OOS Rendering here as well
|
||||
/// Fixes UI7 Scroll back up bug
|
||||
if (rpos[1] + off[1] + lh < 0 && !(flags & LITextFlags_RenderOOS)) {
|
||||
off[1] += lh;
|
||||
continue;
|
||||
} else if (rpos[1] + off[1] > GetViewport().w() &&
|
||||
@ -468,6 +474,58 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
|
||||
vec4 Renderer::GetViewport() { return vec4(vec2(), screen->GetSize()); }
|
||||
|
||||
std::string Renderer::ShortText(const std::string& text, int maxlen,
|
||||
vec2& newsize) {
|
||||
vec2 cdim;
|
||||
if (flags & RenderFlags_TMS) {
|
||||
auto e = tms.find(text);
|
||||
if (e != tms.end()) {
|
||||
e->second.TimeCreated(Sys::GetTime());
|
||||
if (e->second.Optional()) {
|
||||
return e->second.Text();
|
||||
}
|
||||
cdim = e->second.Size();
|
||||
}
|
||||
}
|
||||
cdim = this->GetTextDimensions(text);
|
||||
if (cdim[0] < (float)maxlen) {
|
||||
return text;
|
||||
}
|
||||
std::string ext;
|
||||
/// Forgot why i called this var ending cause
|
||||
/// Its more a placeholder for removed content
|
||||
std::string ending = "...";
|
||||
std::string cpy = text;
|
||||
std::string res;
|
||||
size_t extension = text.find_last_of('.');
|
||||
if (extension != text.npos) {
|
||||
ext = text.substr(extension);
|
||||
cpy = text.substr(0, extension);
|
||||
maxlen -= GetTextDimensions(ext).x();
|
||||
}
|
||||
maxlen -= GetTextDimensions(ending).x();
|
||||
for (auto& it : cpy) {
|
||||
if (GetTextDimensions(res).x() > (float)maxlen) {
|
||||
res += ending;
|
||||
res += ext;
|
||||
newsize = GetTextDimensions(res);
|
||||
if (flags & RenderFlags_TMS) {
|
||||
auto& tmp = tms[text];
|
||||
tmp.Text(res);
|
||||
tmp.Size(newsize);
|
||||
tmp.TimeCreated(Sys::GetTime());
|
||||
tmp.Optional(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
res += it;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string Renderer::WrapText(const std::string& text, int maxlen,
|
||||
vec2& newsize) {}
|
||||
|
||||
vec2 Renderer::GetTextDimensions(const std::string& text) {
|
||||
if (!font) {
|
||||
// No font no size (oder so)
|
||||
|
88
source/maths/img_blur.cpp
Normal file
88
source/maths/img_blur.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 - 2025 tobid7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <pd/maths/img_blur.hpp>
|
||||
#include <pd/maths/img_convert.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace ImgBlur {
|
||||
std::vector<float> GaussianKernel(int r, float si) {
|
||||
/// Define radius as r to be shorter
|
||||
int size = 2 * r + 1;
|
||||
std::vector<float> kernel(size);
|
||||
float sum = 0.0f;
|
||||
|
||||
for (int i = -r; i <= r; i++) {
|
||||
kernel[i + r] = exp(-0.5f * (i * i) / (si * si));
|
||||
sum += kernel[i + r];
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
kernel[i] /= sum;
|
||||
}
|
||||
return kernel;
|
||||
}
|
||||
void GaussianBlur(std::vector<u8> &buf, int w, int h, float radius, float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
GaussianBlur(buf.data(), w, h, 4, radius, si, idxfn);
|
||||
}
|
||||
|
||||
void GaussianBlur(void *buf, int w, int h, int bpp, float radius, float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
if (bpp != 4 && bpp != 3) {
|
||||
return;
|
||||
}
|
||||
std::vector<float> kernel = GaussianKernel(radius, si);
|
||||
int hks = kernel.size() / 2;
|
||||
int end = w * h * bpp;
|
||||
std::vector<unsigned char> res((u8 *)buf, ((u8 *)buf) + end);
|
||||
ImgConvert::Reverse32(res, w, h);
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float r = 0.0f, g = 0.0f, b = 0.0f;
|
||||
for (int ky = -hks; ky <= hks; ky++) {
|
||||
for (int kx = -hks; kx <= hks; kx++) {
|
||||
int xoff = std::min(std::max(x + kx, 0), w - 1);
|
||||
int yoff = std::min(std::max(y + ky, 0), h - 1);
|
||||
int idx = idxfn(xoff, yoff, w) * 4;
|
||||
|
||||
float weight = kernel[ky + hks] * kernel[kx + hks];
|
||||
r += ((u8 *)buf)[idx] * weight;
|
||||
g += ((u8 *)buf)[idx + 1] * weight;
|
||||
b += ((u8 *)buf)[idx + 2] * weight;
|
||||
}
|
||||
}
|
||||
int idx = idxfn(x, y, w) * bpp;
|
||||
res[idx] = std::min(std::max(int(r), 0), 255);
|
||||
res[idx + 1] = std::min(std::max(int(g), 0), 255);
|
||||
res[idx + 2] = std::min(std::max(int(b), 0), 255);
|
||||
}
|
||||
}
|
||||
ImgConvert::Reverse32(res, w, h);
|
||||
std::memcpy(buf, res.data(), res.size());
|
||||
}
|
||||
} // namespace ImgBlur
|
||||
} // namespace PD
|
@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/maths/img.hpp>
|
||||
#include <pd/maths/img_convert.hpp>
|
||||
|
||||
namespace PD::ImgConvert {
|
||||
@ -38,4 +39,17 @@ void RGB24toRGBA32(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
}
|
||||
}
|
||||
}
|
||||
void Reverse32(std::vector<u8> &buf, const int &w, const int &h) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int i = Img::IndexDefault(x, y, w);
|
||||
u8 t0 = buf[i + 0];
|
||||
u8 t1 = buf[i + 1];
|
||||
buf[i + 0] = buf[i + 3];
|
||||
buf[i + 1] = buf[i + 2];
|
||||
buf[i + 3] = t0;
|
||||
buf[i + 2] = t1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace PD::ImgConvert
|
@ -531,8 +531,10 @@ void Keyboard::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) {
|
||||
/// Get the current start possition
|
||||
vec2 start = flymgr;
|
||||
// Draw head and Keyboard background
|
||||
ren->DrawRectSolid(
|
||||
vec2(0, start.y()), vec2(320, 125),
|
||||
PD::Color("#222222ff").a((flags & Flags_Transparency) ? 0xaa : 0xff));
|
||||
ren->DrawRectSolid(vec2(0, start.y()), vec2(320, 17), 0xaa000000);
|
||||
ren->DrawRectSolid(vec2(0, start.y()), vec2(320, 125), 0xaa222222);
|
||||
/// Grab the base layer and go one up for texts
|
||||
int l = ren->Layer();
|
||||
ren->Layer(l + 2);
|
||||
|
@ -32,7 +32,7 @@ void Performance::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) {
|
||||
if (*skill) {
|
||||
Kill();
|
||||
}
|
||||
ren->OnScreen(ren->GetScreen(false));
|
||||
ren->OnScreen(ren->GetScreen(*screen));
|
||||
ren->TextScale(0.6);
|
||||
vec2 pos;
|
||||
Line(pos, std::format("{:.1f} FPS / {:.2f}ms", 1000.f / delta, delta), ren);
|
||||
|
@ -16,13 +16,13 @@ void SettingsMenu::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) {
|
||||
auto m = ctx->GetCurrentMenu();
|
||||
m->SeparatorText("Library Info");
|
||||
m->Label(LibInfo::CompiledWith());
|
||||
m->AfterAlignCenter();
|
||||
m->AfterAlign(UI7Align_Center);
|
||||
m->Label(LibInfo::CxxVersion());
|
||||
m->AfterAlignCenter();
|
||||
m->AfterAlign(UI7Align_Center);
|
||||
m->Label("Version: " + LibInfo::Version() + "[" + LibInfo::Commit() + "]");
|
||||
m->AfterAlignCenter();
|
||||
m->AfterAlign(UI7Align_Center);
|
||||
m->Label("Build Time: " + LibInfo::BuildTime());
|
||||
m->AfterAlignCenter();
|
||||
m->AfterAlign(UI7Align_Center);
|
||||
ctx->EndMenu();
|
||||
}
|
||||
ren->OnScreen(ren->GetScreen(true));
|
||||
|
@ -32,9 +32,7 @@ void Container::HandleScrolling(vec2 scrolling, vec4 viewport) {
|
||||
}
|
||||
last_use = Sys::GetTime();
|
||||
pos -= vec2(0, scrolling.y());
|
||||
if (!LI::Renderer::InBox(pos, size, viewport)) {
|
||||
skippable = true;
|
||||
}
|
||||
skippable = !LI::Renderer::InBox(pos, size, viewport);
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -68,6 +68,7 @@ void DrawList::AddText(vec2 pos, const std::string& text, const UI7Color& clr,
|
||||
if (!e->second->IsSetup() || e->second->Font() != ren->Font()) {
|
||||
int l = ren->Layer();
|
||||
ren->Layer(base);
|
||||
/// Probably a simple ren.get() would handle the job too
|
||||
e->second->Setup(&(*ren), pos, clr, text, flags, box);
|
||||
e->second->Font(ren->Font());
|
||||
ren->Layer(l);
|
||||
|
@ -30,6 +30,7 @@ namespace UI7 {
|
||||
void UI7::Menu::Label(const std::string& label) {
|
||||
Container::Ref r =
|
||||
ObjectPush(PD::New<UI7::Label>(label, Cursor(), this->back->ren));
|
||||
r->SetPos(AlignPos(r->GetPos(), r->GetSize(), view_area, GetAlignment()));
|
||||
CursorMove(r->GetSize());
|
||||
r->Init(main->ren, main, linked_theme);
|
||||
r->HandleScrolling(scrolling_off, view_area);
|
||||
@ -45,7 +46,7 @@ bool UI7::Menu::Button(const std::string& label) {
|
||||
r->Init(main->ren, main, linked_theme);
|
||||
}
|
||||
ObjectPush(r);
|
||||
r->SetPos(Cursor());
|
||||
r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment()));
|
||||
CursorMove(r->GetSize());
|
||||
r->HandleScrolling(scrolling_off, view_area);
|
||||
if (!r->Skippable()) {
|
||||
@ -63,7 +64,7 @@ void UI7::Menu::Checkbox(const std::string& label, bool& v) {
|
||||
r->Init(main->ren, main, linked_theme);
|
||||
}
|
||||
ObjectPush(r);
|
||||
r->SetPos(Cursor());
|
||||
r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment()));
|
||||
CursorMove(r->GetSize());
|
||||
r->HandleScrolling(scrolling_off, view_area);
|
||||
}
|
||||
@ -71,6 +72,7 @@ void UI7::Menu::Checkbox(const std::string& label, bool& v) {
|
||||
void UI7::Menu::Image(Texture::Ref img, vec2 size) {
|
||||
Container::Ref r =
|
||||
ObjectPush(PD::New<UI7::Image>(img, Cursor(), this->back->ren, size));
|
||||
r->SetPos(AlignPos(r->GetPos(), r->GetSize(), view_area, GetAlignment()));
|
||||
CursorMove(r->GetSize());
|
||||
r->Init(main->ren, main, linked_theme);
|
||||
r->HandleScrolling(scrolling_off, view_area);
|
||||
@ -113,7 +115,9 @@ void UI7::Menu::Update(float delta) {
|
||||
idobjs.push_back(it);
|
||||
}
|
||||
if (!it->Skippable()) {
|
||||
it->HandleInput(inp);
|
||||
if (scroll_mod[1] == 0.f) {
|
||||
it->HandleInput(inp);
|
||||
}
|
||||
/// Unlock Input after to ensure nothing is checked twice
|
||||
it->UnlockInput();
|
||||
it->Draw();
|
||||
@ -262,6 +266,20 @@ void UI7::Menu::PostHandler() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Slider Dragging????
|
||||
/// Probably need a new API for this
|
||||
auto tp = inp->TouchPos();
|
||||
if (inp->IsHeld(inp->Touch) &&
|
||||
LI::Renderer::InBox(tp, vec4(screen_w - 12, tsp, 8, szs))) {
|
||||
float drag_center = vslider_h / 2.0f;
|
||||
float drag_pos =
|
||||
std::clamp(static_cast<float>((tp[1] - tsp - drag_center) /
|
||||
(szs - vslider_h - 4)),
|
||||
0.0f, 1.0f);
|
||||
|
||||
scrolling_off[1] = drag_pos * (max[1] - 240.f);
|
||||
}
|
||||
|
||||
int srpos =
|
||||
tsp + std::clamp(float(szs - vslider_h - 4) *
|
||||
(scrolling_off[1] / (max[1] - view_area[3])),
|
||||
@ -318,10 +336,8 @@ void UI7::Menu::SeparatorText(const std::string& label) {
|
||||
|
||||
bool UI7::Menu::HandleScrolling(vec2& pos, const vec2& size) {
|
||||
if (scrolling[1]) {
|
||||
vec2 p = pos;
|
||||
pos -= vec2(0, scrolling_off.y());
|
||||
if (pos.y() > view_area.w() ||
|
||||
(pos.y() + size.y() < tbh - 5 && p.y() > tbh)) {
|
||||
if (pos.y() > view_area.w() || (pos.y() + size.y() < view_area.y())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -347,22 +363,50 @@ void UI7::Menu::Join() {
|
||||
join.push_back(objects.back().get());
|
||||
}
|
||||
|
||||
void UI7::Menu::JoinOpHzCenter() {
|
||||
void UI7::Menu::JoinAlign(UI7Align a) {
|
||||
if (a == 0) {
|
||||
a = UI7Align_Default;
|
||||
}
|
||||
this->Join();
|
||||
float spos = join.front()->GetPos().x();
|
||||
float szs = join.back()->GetPos().x() + join.back()->GetSize().x() - spos;
|
||||
float off = (view_area.x() + view_area.z() * 0.5) - (spos + szs * 0.5);
|
||||
|
||||
vec2 spos = join.front()->GetPos();
|
||||
vec2 szs = join.back()->GetPos() + join.back()->GetSize() - spos;
|
||||
vec2 off;
|
||||
if (a & UI7Align_Center) {
|
||||
off[0] = (view_area[0] + view_area[2] * 0.5) - (spos[0] + szs[0] * 0.5);
|
||||
}
|
||||
if (a & UI7Align_Mid) {
|
||||
off[1] = (view_area[1] + view_area[3] * 0.5) - (spos[1] + szs[1] * 0.5);
|
||||
}
|
||||
for (auto it : join) {
|
||||
it->SetPos(it->GetPos() + vec2(off, 0.f));
|
||||
it->SetPos(it->GetPos() + off);
|
||||
}
|
||||
join.clear();
|
||||
}
|
||||
void UI7::Menu::AfterAlignCenter() {
|
||||
|
||||
vec2 UI7::Menu::AlignPos(vec2 pos, vec2 size, vec4 view, UI7Align a) {
|
||||
vec2 np = pos;
|
||||
if (a & UI7Align_Center) {
|
||||
np[0] = (view[0] + view[2] * 0.5) - (pos[0] + size[0] * 0.5);
|
||||
}
|
||||
if (a & UI7Align_Mid) {
|
||||
np[1] = (view[1] + view[3] * 0.5) - (pos[1] + size[1] * 0.5);
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
void UI7::Menu::AfterAlign(UI7Align a) {
|
||||
Container* ref = objects.back().get();
|
||||
vec2 p = ref->GetPos();
|
||||
vec2 s = ref->GetSize();
|
||||
float newx = (view_area.x() + view_area.z() * 0.5) - (p.x() + s.x() * 0.5);
|
||||
ref->SetPos(vec2(newx, p.y()));
|
||||
vec2 np = p;
|
||||
if (a & UI7Align_Center) {
|
||||
np[0] = (view_area[0] + view_area[2] * 0.5) - (p[0] + s[0] * 0.5);
|
||||
}
|
||||
if (a & UI7Align_Mid) {
|
||||
np[1] = (view_area[1] + view_area[3] * 0.5) - (p[1] + s[1] * 0.5);
|
||||
}
|
||||
ref->SetPos(np);
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -58,6 +58,14 @@ UI7::Menu::Ref UI7::Context::GetCurrentMenu() {
|
||||
return current;
|
||||
}
|
||||
|
||||
UI7::Menu::Ref UI7::Context::FindMenu(const ID& id) {
|
||||
auto e = this->menus.find(id);
|
||||
if (e != this->menus.end()) {
|
||||
return e->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UI7::Context::EndMenu() {
|
||||
this->current->PostHandler();
|
||||
this->current = nullptr;
|
||||
|
Reference in New Issue
Block a user