# Changes 0.2.9

- Litium Chenge Static Object to set instead of add layer
- Add UI7 Color Selector (Not done)
- Add NoClose flag as well as a is_shown address to set to close menus completly
- Add u32 input for nameless ui7 ids
- Add Debug Vertex/Index counters to DrawLists and IO
- Add an Anywhere Released bool to Input API to decide if object should always react or only if curser is inside its box
- Add Focused Menu System to Drag API to make sure to not care about the menu input process order
- Let Menus only have 1 Drawlist instead of 3
Put Close, Resize, Move, Collapse and Scroll into their own handlers
 - Add a DeadHeader color to make a visual diffrence between Menus and Focused Menu
 - Add a GetRef to Theme for Color edit
 - Fix DrawList Line not rendering if going out of screen
 - Clear All CLipRects after process DrawList
 - Fix SeparatorText glitch
 - Fix Typos
 - Add IO Input Support to Containers
This commit is contained in:
tobid7 2025-03-09 20:00:47 +01:00
parent 09b1937a8d
commit edf5f387ae
20 changed files with 514 additions and 224 deletions

View File

@ -52,7 +52,7 @@ execute_process(
)
# Set Project
project(palladium LANGUAGES C CXX VERSION 0.2.8)
project(palladium LANGUAGES C CXX VERSION 0.2.9)
option(PD_BUILD_TESTS "Sets if TestApp and TestBench get build" OFF)
@ -137,6 +137,7 @@ source/ui7/ui7.cpp
source/ui7/container/container.cpp
source/ui7/container/button.cpp
source/ui7/container/checkbox.cpp
source/ui7/container/coloredit.cpp
source/ui7/container/image.cpp
source/ui7/container/label.cpp)

View File

@ -33,10 +33,10 @@ make install
| pd-drivers | 0.2.4 | multi | pd-core |
| pd-lib3ds | 0.2.4 | 3ds | pd-core, pd-drivers |
| pd-net | 0.2.4 | 3ds | pd-core, pd-lib3ds |
| pd-lithium | 0.2.7 | 3ds | pd-core, pd-image pd-lib3ds, citro3d |
| pd-lithium | 0.2.9 | 3ds | pd-core, pd-image pd-lib3ds, citro3d |
| pd-sound | 0.2.4 | 3ds | pd-core, mpg123 |
| pd-overlays | 0.2.4 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium, pd-ui7 |
| pd-ui7 | 0.2.8 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium |
| pd-ui7 | 0.2.9 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium |
| pd-app | 0.2.4 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium |
## Credits

View File

@ -99,12 +99,12 @@ class StaticObject : public SmartCtor<StaticObject> {
}
/**
* Add the Layer by a specific number
* @param base_layer baselayer or number to add on top of the commands layer
* Assign a New Layer to all Objects
* @param layer new layer to set to all its commands
*/
void ReLayer(int base_layer) {
void ReLayer(int layer) {
for (auto& it : cpy) {
it->Layer(it->Layer() + base_layer);
it->Layer(layer);
}
}

View File

@ -0,0 +1,73 @@
#pragma once
/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (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 <pd/ui7/container/container.hpp>
#include <pd/ui7/io.hpp>
namespace PD {
namespace UI7 {
/**
* Color Editor (Creating a PopUP when clicking)
*/
class ColorEdit : public Container {
public:
/**
* Constructor
* @param label Label of the Button
* @param pos Base Position
* @param lr Reference to the Renderer
*/
ColorEdit(const std::string& label, u32* color, UI7::IO::Ref io) {
PD::Assert(color != nullptr, "Input Color Address is null!");
this->label = label;
this->color_ref = color;
this->initial_color = *color;
this->tdim = io->Ren->GetTextDimensions(label);
}
~ColorEdit() = default;
/**
* Override for the Input Handler
* @note This function is usally called by Menu::Update
* @param inp Reference to the Input Handler
*/
void HandleInput(Hid::Ref inp) override;
/**
* Override for the Rendering Handler
* @note This function is usally called by Menu::Update
* */
void Draw() override;
/** Function to Update Size if framepadding changes */
void Update() override;
private:
vec2 tdim; ///< Text size
u32* color_ref = nullptr; ///< Color Reference
u32 initial_color; ///< Initial Color
std::string label; ///< Label of the Button
};
} // namespace UI7
} // namespace PD

View File

@ -25,5 +25,6 @@ SOFTWARE.
#include <pd/ui7/container/button.hpp>
#include <pd/ui7/container/checkbox.hpp>
#include <pd/ui7/container/coloredit.hpp>
#include <pd/ui7/container/image.hpp>
#include <pd/ui7/container/label.hpp>

View File

@ -110,6 +110,8 @@ class DrawList : public SmartCtor<DrawList> {
int base; ///< Base Layer
LI::Renderer::Ref ren; ///< Renderer Reference
std::stack<vec4> clip_rects; ///< Stack containing Scissor Areas
u32 num_vertices; ///< Number of Vertices
u32 num_indices; ///< Number of Indices
// Map for Auto Static Text
std::unordered_map<u32, LI::StaticText::Ref> static_text;
// List of Drawcommands generated

View File

@ -42,6 +42,8 @@ enum UI7MenuFlags_ {
UI7MenuFlags_NoCollapse = 1 << 6, ///< Disable Menu Collapse
UI7MenuFlags_NoMove = 1 << 7, ///< Disable Menu Movement
UI7MenuFlags_NoResize = 1 << 8, ///< Disable Menu Resize
UI7MenuFlags_NoClose = 1 << 9, ///< Disable Close Button
UI7MenuFlags_NoScrollbar = 1 << 10, ///< Hide the Scrollbar
// Enable Horizontal and Vertical Scrolling
UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling,
};

View File

@ -50,6 +50,10 @@ class ID {
id = PD::Strings::FastHash(text);
name = text;
}
/**
* Use an ID as Input
*/
ID(u32 id) { this->id = id; }
~ID() = default;
/** Get The ID Initial Name */

View File

@ -49,8 +49,7 @@ class IO : public SmartCtor<IO> {
Ren = ren;
Back = UI7::DrawList::New(Ren);
Front = UI7::DrawList::New(Ren);
DrawListRegestry["CtxBackList"] = Back;
DrawListRegestry["CtxFrontList"] = Front;
RegisterDrawList("CtxBackList", Back);
DeltaStats = TimeStats::New(60);
};
~IO() = default;
@ -70,9 +69,11 @@ class IO : public SmartCtor<IO> {
vec2 MenuPadding = 5.f;
vec2 FramePadding = 5.f;
vec2 ItemSpace = vec2(5.f, 2.f);
std::map<UI7::ID, DrawList::Ref> DrawListRegestry;
std::vector<std::pair<UI7::ID, DrawList::Ref>> DrawListRegestry;
DrawList::Ref Back;
DrawList::Ref Front;
u32 NumVertices = 0; ///< Debug Vertices Num
u32 NumIndices = 0; ///< Debug Indices Num
// Layer Rules
int ContextBackLayer = 10;
@ -83,18 +84,21 @@ class IO : public SmartCtor<IO> {
// DrawListApi
void RegisterDrawList(const UI7::ID& id, DrawList::Ref v) {
DrawListRegestry[id] = v;
DrawListRegestry.push_back(std::make_pair(id, v));
}
// Input API
u32 FocusedMenu = 0;
vec4 FocusedMenuRect;
u32 CurrentMenu = 0;
u32 DraggedObject = 0;
vec2 DragSourcePos = 0;
vec2 DragPosition = 0;
vec2 DragLastPosition = 0;
vec4 DragDestination = 0;
Timer::Ref DragTime;
bool DragReleased = false;
bool DragReleased = false; ///< Drag Releaded in Box
bool DragReleasedAW = false; ///< Drag Released Anywhere
/** Check if an object is Dragged already */
bool IsObjectDragged() const { return DraggedObject != 0; }
/**
@ -105,6 +109,9 @@ class IO : public SmartCtor<IO> {
* @return if inputs to this objects are alowed or not
*/
bool DragObject(const UI7::ID& id, vec4 area) {
if (CurrentMenu != FocusedMenu) {
return false;
}
if (IsObjectDragged()) {
// Only block if the Dragged Object has a difrent id
if (DraggedObject != id) {
@ -136,7 +143,10 @@ class IO : public SmartCtor<IO> {
DragSourcePos = 0;
DragLastPosition = 0;
DragDestination = 0;
DragReleased = true; // Set Drag released to true (only one frame)
// Set Drag released to true (only one frame)
// and Only if still in Box
DragReleased = Ren->InBox(Inp->TouchPosLast(), area);
DragReleasedAW = true; // Advanced
// Ensure timer is paused
DragTime->Pause();
DragTime->Reset();

View File

@ -82,6 +82,12 @@ class Menu : public SmartCtor<Menu> {
*/
void Image(Texture::Ref img, vec2 size = 0.f);
/**
* Color Edit Object that opens a popup editor if clicked
* @param label Name of the Edit field
* @param color Color reference to edit
*/
void ColorEdit(const std::string& label, u32* color);
// Basic API
/**
@ -267,20 +273,10 @@ class Menu : public SmartCtor<Menu> {
/** Destory the parent container (if one active) */
void DestroyParent() { tmp_parent = nullptr; }
// Draw Lists
// Draw List
/** Background Layer Drawlist */
DrawList::Ref BackList() { return back; }
/** Setter for Background Layer Drawlist */
void BackList(DrawList::Ref v) { back = v; }
/** Main Layer Drawlist */
DrawList::Ref MainList() { return main; }
/** Setter for Main Layer Drawlist */
void MainList(DrawList::Ref v) { main = v; }
/** Foreground Layer Drawlist */
DrawList::Ref FrontList() { return front; }
/** Setter for Foreground Layer Drawlist */
void FrontList(DrawList::Ref v) { front = v; }
/** Get DrawList */
DrawList::Ref GetDrawList() { return main; }
// Advanced
@ -349,6 +345,19 @@ class Menu : public SmartCtor<Menu> {
/** Internal Processing */
void Update(float delta);
// Put some Buttons and functionality into its own functions
/** Handler of the Close Button (if exists) */
void CloseButtonHandler();
/** Handler of the Resize Dragging (lower right corner) */
void ResizeHandler();
/** Logic of the Titlebar Movement */
void MoveHandler();
/** Menu Collapse Button Handler */
void CollapseHandler();
/** Scroll Handler (Includes Slider Drag) */
void PostScrollHandler();
// This ability is crazy useful
friend class Context;
@ -374,6 +383,7 @@ class Menu : public SmartCtor<Menu> {
bool scroll_allowed[2]; ///< Is Hz or Vt Scrolling Alowed
bool has_touch; ///< Menu has touch (depends on screen)
bool is_open = true; ///< For Collapse Event
bool* is_shown = nullptr; ///< For Close Button
Container::Ref tmp_parent; ///< Parent Container (for better alignment etc)
@ -385,11 +395,9 @@ class Menu : public SmartCtor<Menu> {
int count_btn = 0; ///< Count for Button ID Prefix
int count_cbx = 0; ///< Cound for Checkbox ID Prefix
// DrawLists
// DrawList
DrawList::Ref back; ///< Background Drawlist
DrawList::Ref main; ///< Main Drawlist
DrawList::Ref front; ///< Foreground Drawlist
vec2 max; ///< Max Position
vec2 mouse; ///< Mouse/Touch Position

View File

@ -41,6 +41,7 @@ enum UI7Color_ {
UI7Color_Text, ///< UI7 Text Color
UI7Color_TextDead, ///< UI7 Dead Text Color
UI7Color_Header, ///< UI7 Menu Header Color
UI7Color_HeaderDead, ///< Inactive Header
UI7Color_Selector, ///< UI7 Selector Color
UI7Color_Checkmark, ///< UI7 Checkmark Color
UI7Color_FrameBackground, ///< UI7 Frame Background
@ -118,6 +119,20 @@ class Theme : public SmartCtor<Theme> {
return e->second;
}
/**
* [UNSAFE] to use
* Get the Color Ref of a Color ReferenceID
* @param c ReferenceID
*/
u32& GetRef(UI7Color c) {
auto e = theme.find(c);
if (e == theme.end()) {
static u32 noclr = 0x00000000;
return noclr;
}
return e->second;
}
/**
* Operator wrapper for get
* @param c Color ReferenceID

View File

@ -37,7 +37,7 @@ SOFTWARE.
* Major Minor Patch Build
* 0x01010000 -> 1.1.0-0
*/
#define UI7_VERSION 0x00020800
#define UI7_VERSION 0x00020900
namespace PD {
namespace UI7 {
@ -68,7 +68,7 @@ class Context : public SmartCtor<Context> {
* @return If the Menu was Created
* (useless as false results in an error screen)
*/
bool BeginMenu(const ID& id, UI7MenuFlags flags = 0);
bool BeginMenu(const ID& id, UI7MenuFlags flags = 0, bool* show = nullptr);
/**
* Get the Current Menu
* for example for auto m = ctx->GetCurrentMenu
@ -126,13 +126,13 @@ class Context : public SmartCtor<Context> {
// Debugging / Demo / About
/** About Menu */
void AboutMenu();
void AboutMenu(bool* show = nullptr);
/** Metrics */
void MetricsMenu();
void MetricsMenu(bool* show = nullptr);
/** Style Editor Menu (Includes Theme Editor) */
void StyleEditor();
void StyleEditor(bool* show = nullptr);
private:
// Used in Overlays

View File

@ -35,14 +35,13 @@ void Button::HandleInput(Hid::Ref inp) {
color = UI7Color_Button;
Assert(screen.get(), "Screen is not set up!");
if (screen->ScreenType() == Screen::Bottom) {
if (inp->IsHeld(inp->Touch) &&
LI::Renderer::InBox(inp->TouchPos(), vec4(FinalPos(), size))) {
color = UI7Color_ButtonHovered;
}
if (inp->IsUp(inp->Touch) &&
LI::Renderer::InBox(inp->TouchPosLast(), vec4(FinalPos(), size))) {
if (io->DragObject(this->GetID(), vec4(FinalPos(), size))) {
if (io->DragReleased) {
color = UI7Color_ButtonActive;
pressed = true;
} else {
color = UI7Color_ButtonHovered;
}
}
}
inp_done = true;

View File

@ -34,14 +34,13 @@ void Checkbox::HandleInput(Hid::Ref inp) {
/// Ensure it gets sed to false and stays if not pressed
Assert(screen.get(), "Screen is not set up!");
if (screen->ScreenType() == Screen::Bottom) {
if (inp->IsHeld(inp->Touch) &&
LI::Renderer::InBox(inp->TouchPos(), vec4(FinalPos(), size))) {
color = UI7Color_FrameBackgroundHovered;
}
if (inp->IsUp(inp->Touch) &&
LI::Renderer::InBox(inp->TouchPosLast(), vec4(FinalPos(), size))) {
if (io->DragObject(this->GetID(), vec4(FinalPos(), size))) {
if (io->DragReleased) {
color = UI7Color_FrameBackgroundHovered;
usr_ref = !usr_ref;
} else {
color = UI7Color_FrameBackgroundHovered;
}
}
}
inp_done = true;

View File

@ -0,0 +1,55 @@
/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (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 <pd/ui7/container/coloredit.hpp>
namespace PD {
namespace UI7 {
void ColorEdit::HandleInput(Hid::Ref inp) {
/// Ensure to only check input once
if (inp_done) {
return;
}
Assert(screen.get(), "Screen is not set up!");
if (screen->ScreenType() == Screen::Bottom) {
if (io->DragObject(this->GetID(), vec4(FinalPos(), size))) {
if (io->DragReleased) {
}
}
}
inp_done = true;
}
void ColorEdit::Draw() {
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
io->Ren->OnScreen(screen);
list->AddRectangle(FinalPos(), vec2(20, 20), *color_ref);
list->AddText(FinalPos() + vec2(io->ItemSpace.x() + 20, 0), label,
io->Theme->Get(UI7Color_Text));
}
void ColorEdit::Update() {
Assert(io.get(), "Did you run Container::Init correctly?");
this->SetSize(vec2(tdim.x() + io->ItemSpace.x() + 20, 20));
}
} // namespace UI7
} // namespace PD

View File

@ -34,7 +34,7 @@ void DrawList::AddRectangle(vec2 pos, vec2 szs, const UI7Color& clr) {
auto cmd = LI::Command::New();
ren->UseTex();
ren->SetupCommand(cmd);
cmd->Layer(base + layer);
cmd->Layer(layer);
if (!clip_rects.empty()) {
cmd->SetScissorMode(LI::ScissorMode_Normal);
cmd->ScissorRect(clip_rects.top());
@ -52,7 +52,7 @@ void DrawList::AddTriangle(vec2 pos0, vec2 pos1, vec2 pos2,
auto cmd = LI::Command::New();
ren->UseTex();
ren->SetupCommand(cmd);
cmd->Layer(base + layer);
cmd->Layer(layer);
if (!clip_rects.empty()) {
cmd->SetScissorMode(LI::ScissorMode_Normal);
cmd->ScissorRect(clip_rects.top());
@ -78,7 +78,7 @@ void DrawList::AddText(vec2 pos, const std::string& text, const UI7Color& clr,
}
if (!e->IsSetup() || e->Font() != ren->Font()) {
int l = ren->Layer();
ren->Layer(base);
ren->Layer(layer);
e->Setup(ren.get(), pos, clr, text, flags, box);
e->Font(ren->Font());
ren->Layer(l);
@ -124,7 +124,7 @@ void DrawList::AddImage(vec2 pos, Texture::Ref img, vec2 size) {
auto cmd = LI::Command::New();
ren->UseTex(img);
ren->SetupCommand(cmd);
cmd->Layer(base + layer);
cmd->Layer(layer);
if (!clip_rects.empty()) {
cmd->SetScissorMode(LI::ScissorMode_Normal);
cmd->ScissorRect(clip_rects.top());
@ -136,7 +136,7 @@ void DrawList::AddImage(vec2 pos, Texture::Ref img, vec2 size) {
void DrawList::AddLine(const vec2& a, const vec2& b, const UI7Color& clr,
int t) {
if (!ren->InBox(a, ren->GetViewport()) ||
if (!ren->InBox(a, ren->GetViewport()) &&
!ren->InBox(b, ren->GetViewport())) {
return;
}
@ -144,7 +144,7 @@ void DrawList::AddLine(const vec2& a, const vec2& b, const UI7Color& clr,
auto cmd = LI::Command::New();
ren->UseTex();
ren->SetupCommand(cmd);
cmd->Layer(base + layer);
cmd->Layer(layer);
if (!clip_rects.empty()) {
cmd->SetScissorMode(LI::ScissorMode_Normal);
cmd->ScissorRect(clip_rects.top());
@ -157,9 +157,14 @@ void DrawList::AddLine(const vec2& a, const vec2& b, const UI7Color& clr,
void DrawList::Clear() { commands.clear(); }
void DrawList::Process() {
num_vertices = 0;
num_indices = 0;
for (auto command : commands) {
ren->OnScreen(ren->GetScreen(command.first));
command.second->Layer(command.second->Layer() + base);
ren->PushCommand(command.second);
num_vertices += command.second->VertexList().size();
num_indices += command.second->IndexList().size();
}
commands.clear();
layer = 0;
@ -173,6 +178,9 @@ void DrawList::Process() {
for (auto& it : rem) {
static_text.erase(it);
}
while (!clip_rects.empty()) {
clip_rects.pop();
}
}
} // namespace UI7
} // namespace PD

View File

@ -29,6 +29,9 @@ void UI7::IO::Update() {
Time->Update();
DragTime->Update();
DragReleased = false;
DragReleasedAW = false;
Framerate = 1000.f / Delta;
DrawListRegestry.clear();
RegisterDrawList("CtxBackList", Back);
}
} // namespace PD

View File

@ -55,6 +55,21 @@ bool UI7::Menu::Button(const std::string& label) {
return ret;
}
void UI7::Menu::ColorEdit(const std::string& label, u32* color) {
u32 id = Strings::FastHash("cle" + label + std::to_string(count_btn++));
Container::Ref r = FindIDObj(id);
if (!r) {
r = PD::New<UI7::ColorEdit>(label, color, io);
r->SetID(id);
r->Init(io, main);
}
ObjectPush(r);
r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment()));
r->Update();
CursorMove(r->GetSize());
r->HandleScrolling(scrolling_off, view_area);
}
void UI7::Menu::Checkbox(const std::string& label, bool& v) {
u32 id = Strings::FastHash("cbx" + label + std::to_string(count_cbx++));
Container::Ref r = FindIDObj(id);
@ -125,6 +140,7 @@ void UI7::Menu::Update(float delta) {
view_area.x() + view_area.z() - io->MenuPadding[0],
view_area.y() + view_area.w()));
}
main->Layer(10); // Render to Layer 10
std::vector<int> tbr;
for (int i = 0; i < (int)objects.size(); i++) {
auto& it = objects[i];
@ -152,6 +168,7 @@ void UI7::Menu::Update(float delta) {
main->PopClipRect();
}
this->objects.clear();
PostScrollHandler();
}
void UI7::Menu::CursorMove(const vec2& size) {
@ -169,7 +186,23 @@ void UI7::Menu::CursorMove(const vec2& size) {
void UI7::Menu::PreHandler(UI7MenuFlags flags) {
TT::Scope st("MPRE_" + name);
TT::Beg("MUSR_" + name);
// No touch means no Input System
UI7Color header = has_touch ? UI7Color_HeaderDead : UI7Color_Header;
// Check if menu can be focused for Selective Menu Input API
vec4 newarea = view_area;
if (!is_open) {
newarea = vec4(view_area.xy(), vec2(view_area.z(), tbh));
}
if (has_touch && io->Inp->IsDown(io->Inp->Touch) &&
io->Ren->InBox(io->Inp->TouchPos(), newarea) &&
!io->Ren->InBox(io->Inp->TouchPos(), io->FocusedMenuRect)) {
io->FocusedMenu = id;
}
if (io->FocusedMenu == id) {
io->FocusedMenuRect = newarea;
header = UI7Color_Header;
}
// Resetup [updating] variables
count_btn = 0;
count_cbx = 0;
tbh = 0.f;
@ -178,63 +211,49 @@ void UI7::Menu::PreHandler(UI7MenuFlags flags) {
this->flags = flags;
this->scrolling[0] = flags & UI7MenuFlags_HzScrolling;
this->scrolling[1] = flags & UI7MenuFlags_VtScrolling;
has_touch = main->ren->CurrentScreen()->ScreenType() == Screen::Bottom;
has_touch = io->Ren->CurrentScreen()->ScreenType() == Screen::Bottom;
if (!(flags & UI7MenuFlags_NoBackground) && is_open) {
back->AddRectangle(view_area.xy() + vec2(0, tbh),
main->Layer(0);
main->AddRectangle(view_area.xy() + vec2(0, tbh),
view_area.zw() - vec2(0, tbh),
io->Theme->Get(UI7Color_Background));
}
if (!(flags & UI7MenuFlags_NoTitlebar)) {
// Title bar setup and Rendering
tbh = front->ren->TextScale() * 30.f;
front->AddRectangle(view_area.xy(), vec2(view_area.z(), tbh),
io->Theme->Get(UI7Color_Header));
tbh = io->Ren->TextScale() * 30.f;
main->Layer(20);
main->AddRectangle(view_area.xy(), vec2(view_area.z(), tbh),
io->Theme->Get(header));
vec2 tpos(io->MenuPadding[0],
tbh * 0.5 - front->ren->GetTextDimensions(name).y() * 0.5);
tbh * 0.5 - io->Ren->GetTextDimensions(name).y() * 0.5);
if (!(flags & UI7MenuFlags_NoCollapse)) {
tpos.x() += 18;
vec2 cpos = view_area.xy() + io->FramePadding;
UI7Color clr = UI7Color_FrameBackground;
if (has_touch &&
io->DragObject(UI7::ID(name + "clbse"), vec4(cpos, vec2(18, tbh)))) {
if (io->DragReleased) {
is_open = !is_open;
}
clr = UI7Color_FrameBackgroundHovered;
}
vec2 positions[2] = {
vec2(12, 6),
vec2(0, 12),
};
if (is_open) {
float t = positions[0].y();
positions[0].y() = positions[1].x();
positions[1].x() = t;
}
this->front->AddTriangle(cpos, cpos + positions[0], cpos + positions[1],
io->Theme->Get(clr));
tpos[0] += 18;
}
LITextFlags tflags = LITextFlags_None;
if (flags & UI7MenuFlags_CenterTitle) {
tpos = 0;
tflags = LITextFlags_AlignMid;
}
front->Layer(front->Layer() + 1);
front->AddText(view_area.xy() + tpos, this->name,
main->Layer(main->Layer() + 1);
if (!(flags & UI7MenuFlags_NoClipRect)) {
int extra = is_shown != nullptr && !(flags & UI7MenuFlags_NoClose)
? (20 + io->ItemSpace.x())
: 0;
main->PushClipRect(vec4(
view_area.xy(),
vec2(view_area.x() + view_area.z() - extra, view_area.y() + tbh)));
}
main->AddText(view_area.xy() + tpos, this->name,
io->Theme->Get(UI7Color_Text), tflags,
vec2(view_area.z(), tbh));
if (!(flags & UI7MenuFlags_NoClipRect)) {
main->PopClipRect();
}
main_area[1] = tbh;
CursorInit();
// Menu Movement
if (!(flags & UI7MenuFlags_NoMove)) {
if (has_touch &&
io->DragObject(name + "tmv", vec4(view_area.xy() + vec2(18, 0),
vec2(view_area.z(), tbh)))) {
view_area =
vec4(view_area.xy() + (io->DragPosition - io->DragLastPosition),
view_area.zw());
}
}
CollapseHandler();
CloseButtonHandler();
MoveHandler();
}
// Add a clip Rect for Separators
if (!(flags & UI7MenuFlags_NoClipRect)) {
@ -243,24 +262,14 @@ void UI7::Menu::PreHandler(UI7MenuFlags flags) {
view_area.x() + view_area.z() - io->MenuPadding[0],
view_area.y() + view_area.w()));
}
main->Layer(10);
TT::Beg("MUSR_" + name);
}
void UI7::Menu::PostHandler() {
TT::Scope st("MPOS_" + name);
if (!(flags & UI7MenuFlags_NoResize)) {
if (has_touch &&
io->DragObject(name + "rszs",
vec4(view_area.xy() + view_area.zw() - 20, 20))) {
view_area = vec4(view_area.xy(), view_area.zw() + (io->DragPosition -
io->DragLastPosition));
}
// front->AddRectangle(view_area.xy() + view_area.zw() - 20, 20,
// 0xffffffff); Not vidible dor some reason
int l = front->Layer();
front->Layer(l + 1);
front->AddTriangle(10, vec2(10, 0), vec2(10, 0), 0xffffffff);
front->Layer(l);
}
TT::End("MUSR_" + name);
ResizeHandler();
if (scrolling[1]) {
scroll_allowed[1] = (max[1] > view_area.w() - io->MenuPadding[1]);
if (max[1] < view_area.w() - io->MenuPadding[1]) {
@ -299,36 +308,6 @@ void UI7::Menu::PostHandler() {
}
}
/// Dont overscroll to much
if (scrolling_off[1] < -40 ||
scrolling_off[1] > max[1] - view_area[3] + 40) {
scroll_mod[1] = 0.f;
}
/// The pain :(
if (has_touch && !io->IsObjectDragged()) {
vec2 tpos = io->Inp->TouchPos();
if (io->Inp->IsDown(io->Inp->Touch)) {
mouse = tpos;
} else if (io->Inp->IsUp(io->Inp->Touch)) {
mouse = vec2();
}
if (io->Inp->IsHeld(io->Inp->Touch)) {
if (front->ren->InBox(tpos, vec4(view_area.xy() + main_area.xy(),
main_area.zw()))) {
if (scrolling_off[1] < max[1] - view_area[3] + 40 &&
scrolling_off[1] > -40) {
/// Cursor Mod
float cm = mouse[1] - tpos[1];
if (scroll_mod[1] <= 4.f && scroll_mod[1] >= -4.f && cm != 0) {
scroll_mod[1] = cm;
}
}
mouse = tpos;
}
}
}
/// Effect
if (scroll_mod[1] != 0) {
scrolling_off[1] += scroll_mod[1];
@ -351,15 +330,16 @@ void UI7::Menu::PostHandler() {
if (has_touch &&
io->DragObject(name + "sldr", vec4(view_area.x() + screen_w - 12,
view_area.y() + tsp, 8, szs)) &&
!io->DragReleased) {
!io->DragReleasedAW) {
sldr_drag = UI7Color_ButtonHovered;
float drag_center = vslider_h / 2.0f;
float drag_pos = std::clamp(
static_cast<float>((io->DragPosition[1] - tsp - drag_center) /
static_cast<float>(
((io->DragPosition[1] - view_area.y()) - tsp - drag_center) /
(szs - vslider_h - 4)),
0.0f, 1.0f);
scrolling_off[1] = drag_pos * (max[1] - 240.f);
scrolling_off[1] = drag_pos * (max[1] - view_area.w());
}
int srpos =
tsp + std::clamp(float(szs - vslider_h - 4) *
@ -367,13 +347,14 @@ void UI7::Menu::PostHandler() {
0.f, float(szs - vslider_h - 4));
/// Rendering Stage
front->AddRectangle(view_area.xy() + vec2(screen_w - 12, tsp),
main->Layer(20);
main->AddRectangle(view_area.xy() + vec2(screen_w - 12, tsp),
vec2(slider_w * 2, szs),
io->Theme->Get(UI7Color_FrameBackground));
front->AddRectangle(view_area.xy() + vec2(screen_w - 10, tsp + 2),
main->AddRectangle(view_area.xy() + vec2(screen_w - 10, tsp + 2),
vec2(slider_w, szs - 4),
io->Theme->Get(UI7Color_FrameBackgroundHovered));
front->AddRectangle(view_area.xy() + vec2(screen_w - 10, srpos + 2),
main->AddRectangle(view_area.xy() + vec2(screen_w - 10, srpos + 2),
vec2(slider_w, vslider_h), io->Theme->Get(sldr_drag));
}
}
@ -381,7 +362,6 @@ void UI7::Menu::PostHandler() {
if (!(flags & UI7MenuFlags_NoClipRect)) {
main->PopClipRect();
}
TT::End("MUSR_" + name);
}
void UI7::Menu::SameLine() {
@ -401,7 +381,7 @@ void UI7::Menu::Separator() {
void UI7::Menu::SeparatorText(const std::string& label) {
vec2 size = vec2(view_area.z() - (scrollbar[1] ? 24 : 10), 1);
vec2 tdim = this->back->ren->GetTextDimensions(label);
vec2 tdim = io->Ren->GetTextDimensions(label);
vec2 pos = Cursor();
CursorMove(vec2(size.x(), tdim.y()));
@ -409,30 +389,23 @@ void UI7::Menu::SeparatorText(const std::string& label) {
return;
}
auto alignment = GetAlignment();
vec2 rpos = AlignPos(pos, view_area.z() - (io->MenuPadding[0] * 2), view_area,
alignment); // RenderPos
/// Label pos for better overview
vec2 lpos = rpos;
if (alignment & UI7Align_Center) {
lpos += vec2(
(view_area.z() - (io->MenuPadding[0] * 2)) * 0.5 - tdim.x() * 0.5, 0);
} else if (alignment & UI7Align_Right) {
lpos = vec2(view_area.z() - (io->MenuPadding[0] * 2) - tdim.x(), rpos.y());
if (scrolling[1]) {
lpos.x() -= 8;
}
}
vec2 rpos = AlignPos(pos, tdim, view_area, alignment);
if (!(alignment & UI7Align_Left)) {
main->AddRectangle(rpos + vec2(0, tdim.y() * 0.5),
vec2(lpos.x() - rpos.x() - io->MenuPadding[0], size.y()),
main->AddRectangle(
rpos + vec2(-(rpos[0] - view_area[0] - io->MenuPadding[0]),
tdim.y() * 0.5),
vec2(rpos[0] - view_area[0] - io->MenuPadding[0] - io->FramePadding[0],
size.y()),
io->Theme->Get(UI7Color_TextDead));
}
if (!(alignment & UI7Align_Right)) {
main->AddRectangle(rpos + vec2(lpos.x() + tdim.x(), tdim.y() * 0.5),
vec2(size.x() - (lpos.x() + tdim.x()), size.y()),
main->AddRectangle(
rpos + vec2(tdim.x() + io->FramePadding[0], tdim.y() * 0.5),
vec2(size.x() - (tdim.x() + io->FramePadding[0]), size.y()),
io->Theme->Get(UI7Color_TextDead));
}
main->AddText(lpos, label, io->Theme->Get(UI7Color_Text), 0,
main->AddText(rpos, label, io->Theme->Get(UI7Color_Text), 0,
vec2(view_area.z(), 20));
}
@ -495,10 +468,10 @@ void UI7::Menu::JoinAlign(UI7Align a) {
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);
np[0] = (view[0] + view[2] * 0.5) - ((pos[0] - view[0]) + size[0] * 0.5);
}
if (a & UI7Align_Mid) {
np[1] = (view[1] + view[3] * 0.5) - (pos[1] + size[1] * 0.5);
np[1] = (view[1] + view[3] * 0.5) - ((pos[1] - view[1]) + size[1] * 0.5);
}
return np;
}
@ -572,5 +545,96 @@ void UI7::Menu::EndTreeNode() {
icursoroff.x() = 0.f;
}
}
void UI7::Menu::CloseButtonHandler() {
// Close Logic
if (!(flags & UI7MenuFlags_NoClose) && is_shown != nullptr) {
vec2 cpos = vec2(view_area.x() + view_area.z() - 12 - io->FramePadding.x(),
view_area.y() + io->FramePadding.y());
UI7Color clr = UI7Color_FrameBackground;
if (has_touch &&
io->DragObject(UI7::ID(name + "clse"), vec4(cpos, vec2(12)))) {
if (io->DragReleased) {
*is_shown = !(*is_shown);
}
clr = UI7Color_FrameBackgroundHovered;
}
main->AddLine(cpos, cpos + 12, io->Theme->Get(clr), 2);
main->AddLine(cpos + vec2(0, 12), cpos + vec2(12, 0), io->Theme->Get(clr),
2);
}
}
void UI7::Menu::ResizeHandler() {
if (!(flags & UI7MenuFlags_NoResize)) {
if (has_touch &&
io->DragObject(name + "rszs",
vec4(view_area.xy() + view_area.zw() - 20, 20))) {
vec2 szs = view_area.zw() + (io->DragPosition - io->DragLastPosition);
if (szs.x() < 30) szs[0] = 30;
if (szs.y() < 30) szs[1] = 30;
view_area = vec4(view_area.xy(), szs);
}
// front->AddRectangle(view_area.xy() + view_area.zw() - 20, 20,
// 0xffffffff); Not vidible dor some reason
// int l = front->Layer();
// front->Layer(l + 1);
// front->AddTriangle(10, vec2(10, 0), vec2(10, 0), 0xffffffff);
// front->Layer(l);
}
}
void UI7::Menu::MoveHandler() {
// Menu Movement
if (!(flags & UI7MenuFlags_NoMove)) {
if (has_touch &&
io->DragObject(name + "tmv",
vec4(view_area.xy(), vec2(view_area.z(), tbh)))) {
view_area =
vec4(view_area.xy() + (io->DragPosition - io->DragLastPosition),
view_area.zw());
}
}
}
void UI7::Menu::CollapseHandler() {
// Collapse logic
if (!(flags & UI7MenuFlags_NoCollapse)) {
vec2 cpos = view_area.xy() + io->FramePadding;
UI7Color clr = UI7Color_FrameBackground;
if (has_touch &&
io->DragObject(UI7::ID(name + "clbse"), vec4(cpos, vec2(18, tbh)))) {
if (io->DragReleased) {
is_open = !is_open;
}
clr = UI7Color_FrameBackgroundHovered;
}
vec2 positions[2] = {
vec2(12, 6),
vec2(0, 12),
};
if (is_open) {
float t = positions[0].y();
positions[0].y() = positions[1].x();
positions[1].x() = t;
}
main->AddTriangle(cpos, cpos + positions[0], cpos + positions[1],
io->Theme->Get(clr));
}
}
void UI7::Menu::PostScrollHandler() {
if (has_touch && io->DragObject(id, view_area) && scrolling[1] &&
flags & UI7MenuFlags_VtScrolling) {
if (io->DragReleased) {
scroll_mod = (io->DragPosition - io->DragLastPosition);
} else {
scrolling_off[1] = std::clamp(
scrolling_off[1] - (io->DragPosition.y() - io->DragLastPosition.y()),
-40.f, (max[1] - view_area.w()) + 40.f);
}
}
}
} // namespace UI7
} // namespace PD

View File

@ -35,6 +35,7 @@ void Theme::Default(Theme& theme) {
theme.Set(UI7Color_ButtonActive, Color("#2A2A2AFF"));
theme.Set(UI7Color_ButtonHovered, Color("#222222FF"));
theme.Set(UI7Color_Header, Color("#111111FF"));
theme.Set(UI7Color_HeaderDead, Color("#080808FF"));
theme.Set(UI7Color_Selector, Color("#222222FF"));
theme.Set(UI7Color_Checkmark, Color("#2A2A2AFF"));
theme.Set(UI7Color_FrameBackground, Color("#555555FF"));

View File

@ -45,10 +45,19 @@ std::string UI7::GetVersion(bool show_build) {
if (show_build) s << "-" << ((UI7_VERSION) & 0xFF);
return s.str();
}
bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags) {
bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags, bool* show) {
Assert(!this->current, "You are already in another Menu!");
Assert(std::find(amenus.begin(), amenus.end(), (u32)id) == amenus.end(),
"Menu Name Already used or\nContext::Update not called!");
if (show != nullptr) {
if (!(*show)) {
if (io->FocusedMenu == id) {
io->FocusedMenu = 0;
io->FocusedMenuRect = 0;
}
return false;
}
}
auto menu = this->menus.find(id);
if (menu == this->menus.end()) {
this->menus[id] = Menu::New(id, io);
@ -56,18 +65,12 @@ bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags) {
menu = this->menus.find(id);
}
this->current = menu->second;
if (!this->current->BackList()) {
this->current->BackList(DrawList::New(io->Ren));
io->RegisterDrawList(this->current->name + "back", this->current->back);
}
if (!this->current->MainList()) {
this->current->MainList(DrawList::New(io->Ren));
io->RegisterDrawList(this->current->name + "main", this->current->main);
}
if (!this->current->FrontList()) {
this->current->FrontList(DrawList::New(io->Ren));
io->RegisterDrawList(this->current->name + "front", this->current->front);
this->current->is_shown = show;
this->io->CurrentMenu = this->current->id;
if (!this->current->main) {
this->current->main = DrawList::New(io->Ren);
}
io->RegisterDrawList(id, this->current->main);
this->current->PreHandler(flags);
amenus.push_back(this->current->GetID());
if (!this->current->is_open) {
@ -92,6 +95,7 @@ UI7::Menu::Ref UI7::Context::FindMenu(const ID& id) {
void UI7::Context::EndMenu() {
this->current->PostHandler();
this->current = nullptr;
this->io->CurrentMenu = 0;
}
void UI7::Context::Update(float delta) {
@ -100,20 +104,37 @@ void UI7::Context::Update(float delta) {
this->io->Delta = delta;
io->DeltaStats->Add(io->Delta * 1000);
for (auto it : amenus) {
menus[it]->Update(io->Delta);
auto m = menus[it];
io->CurrentMenu = m->id;
m->Update(io->Delta);
io->CurrentMenu = 0;
}
int list = 1;
int list = 0;
u32 vtx_counter = 0;
u32 idx_counter = 0;
// Render the Focused Menu Last
std::sort(io->DrawListRegestry.begin(), io->DrawListRegestry.end(),
[&](const auto& a, const auto& b) {
return (a.first == io->FocusedMenu) <
(b.first == io->FocusedMenu);
});
// Register Front List as last element
io->RegisterDrawList("CtxFrontList", io->Front);
for (auto it : io->DrawListRegestry) {
it.second->BaseLayer(list * 10);
it.second->BaseLayer(list * 30);
it.second->Process();
vtx_counter += it.second->num_vertices;
idx_counter += it.second->num_indices;
list++;
}
io->NumIndices = idx_counter;
io->NumVertices = vtx_counter;
this->amenus.clear();
this->io->Update();
}
void UI7::Context::AboutMenu() {
if (this->BeginMenu("About UI7", UI7MenuFlags_Scrolling)) {
void UI7::Context::AboutMenu(bool* show) {
if (this->BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
auto m = this->GetCurrentMenu();
m->Label("Palladium - UI7 " + GetVersion());
@ -135,8 +156,8 @@ void UI7::Context::AboutMenu() {
}
}
void UI7::Context::MetricsMenu() {
if (this->BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling)) {
void UI7::Context::MetricsMenu(bool* show) {
if (this->BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
auto m = this->GetCurrentMenu();
m->Label("Palladium - UI7 " + GetVersion());
@ -145,11 +166,10 @@ void UI7::Context::MetricsMenu() {
std::format("Average {:.3f} ms/f ({:.1f} FPS)",
((float)io->DeltaStats->GetAverage() / 1000.f),
1000.f / ((float)io->DeltaStats->GetAverage() / 1000.f)));
m->Label(std::format("NumVertices: {}", io->NumVertices));
m->Label(std::format("NumIndices: {} -> {} Tris", io->NumIndices,
io->NumIndices / 3));
m->Label("Menus: " + std::to_string(menus.size()));
m->SeparatorText("Lithium");
m->Label(std::format("Vertices: {} Indices: {}", io->Ren->Vertices(),
io->Ren->Indices()));
m->Label("Triangles: " + std::to_string(io->Ren->Indices() / 3));
m->SeparatorText("TimeTrace");
if (m->BeginTreeNode("Traces (" +
std::to_string(Sys::GetTraceMap().size()) + ")")) {
@ -192,13 +212,19 @@ void UI7::Context::MetricsMenu() {
if (m->BeginTreeNode("DrawLists (" +
std::to_string(io->DrawListRegestry.size()) + ")")) {
for (auto& it : io->DrawListRegestry) {
m->Label(it.first.GetName());
if (m->BeginTreeNode(it.first.GetName())) {
m->Label("Vertices: " + std::to_string(it.second->num_vertices));
m->Label("Indices: " + std::to_string(it.second->num_indices));
m->Label("Base Layer: " + std::to_string(it.second->base));
m->EndTreeNode();
}
}
m->EndTreeNode();
}
m->Label("io->Time: " + Strings::FormatMillis(io->Time->Get()));
m->Label(std::format("io->Delta: {:.3f}", io->Delta));
m->Label(std::format("io->Framerate: {:.2f}", io->Framerate));
m->Label(UI7DHX32(io->FocusedMenu));
m->Label(UI7DHX32(io->DraggedObject));
m->Label(std::format("io->DragTime: {:.2f}s", io->DragTime->GetSeconds()));
m->Label(UI7DV4(io->DragDestination));
@ -209,8 +235,8 @@ void UI7::Context::MetricsMenu() {
}
}
void UI7::Context::StyleEditor() {
if (this->BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling)) {
void UI7::Context::StyleEditor(bool* show) {
if (this->BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) {
auto m = this->GetCurrentMenu();
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
@ -245,6 +271,25 @@ void UI7::Context::StyleEditor() {
if (m->Button("+")) {
io->ItemSpace += 1;
}
m->SeparatorText("Theme");
/// Small trick to print without prefix
#define ts(x) m->ColorEdit(std::string(#x).substr(9), &io->Theme->GetRef(x));
ts(UI7Color_Background);
ts(UI7Color_Button);
ts(UI7Color_ButtonDead);
ts(UI7Color_ButtonActive);
ts(UI7Color_ButtonHovered);
ts(UI7Color_Text);
ts(UI7Color_TextDead);
ts(UI7Color_Header);
ts(UI7Color_HeaderDead);
ts(UI7Color_Selector);
ts(UI7Color_Checkmark);
ts(UI7Color_FrameBackground);
ts(UI7Color_FrameBackgroundHovered);
ts(UI7Color_Progressbar);
ts(UI7Color_ListEven);
ts(UI7Color_ListOdd);
this->EndMenu();
}
}