Initial Cross Platform Work

This commit is contained in:
2025-04-24 16:39:24 +02:00
parent dbffb7f316
commit 13c2869ba8
170 changed files with 18611 additions and 10292 deletions

View File

@ -1,64 +1,64 @@
/*
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/button.hpp>
namespace PD {
namespace UI7 {
void Button::HandleInput() {
/// Ensure to only check input once
if (inp_done) {
return;
}
/// Ensure it gets sed to false and stays if not pressed
pressed = false;
color = UI7Color_Button;
Assert(screen.get(), "Screen is not set up!");
if (screen->ScreenType() == Screen::Bottom) {
if (io->DragObject(this->GetID(), vec4(FinalPos(), size))) {
if (io->DragReleased) {
color = UI7Color_ButtonActive;
pressed = true;
} else {
color = UI7Color_ButtonHovered;
}
}
}
inp_done = true;
}
void Button::Draw() {
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
io->Ren->OnScreen(screen);
list->AddRectangle(FinalPos(), size, io->Theme->Get(color));
list->Layer(list->Layer() + 1);
list->AddText(FinalPos() + size * 0.5 - tdim * 0.5, label,
io->Theme->Get(UI7Color_Text));
list->Layer(list->Layer() - 1);
}
void Button::Update() {
Assert(io.get(), "Did you run Container::Init correctly?");
this->SetSize(tdim + io->FramePadding);
}
} // namespace UI7
/*
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/button.hpp>
namespace PD {
namespace UI7 {
PD_UI7_API void Button::HandleInput() {
/// Ensure to only check input once
if (inp_done) {
return;
}
/// Ensure it gets sed to false and stays if not pressed
pressed = false;
color = UI7Color_Button;
// Assert(screen.get(), "Screen is not set up!");
// if (screen->ScreenType() == Screen::Bottom) {
if (io->InputHandler->DragObject(this->GetID(), vec4(FinalPos(), size))) {
if (io->InputHandler->DragReleased) {
color = UI7Color_ButtonActive;
pressed = true;
} else {
color = UI7Color_ButtonHovered;
}
}
//}
inp_done = true;
}
PD_UI7_API void Button::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->AddRectangle(FinalPos(), size, io->Theme->Get(color));
list->Layer++;
list->AddText(FinalPos() + size * 0.5 - tdim * 0.5, label,
io->Theme->Get(UI7Color_Text));
list->Layer--;
}
PD_UI7_API void Button::Update() {
// Assert(io.get(), "Did you run Container::Init correctly?");
this->SetSize(tdim + io->FramePadding);
}
} // namespace UI7
} // namespace PD

View File

@ -1,66 +1,66 @@
/*
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/checkbox.hpp>
namespace PD {
namespace UI7 {
void Checkbox::HandleInput() {
/// Ensure to only check input once
if (inp_done) {
return;
}
color = UI7Color_FrameBackground;
/// 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 (io->DragObject(this->GetID(), vec4(FinalPos(), size))) {
if (io->DragReleased) {
color = UI7Color_FrameBackgroundHovered;
usr_ref = !usr_ref;
} else {
color = UI7Color_FrameBackgroundHovered;
}
}
}
inp_done = true;
}
void Checkbox::Draw() {
Assert(list.get() && io.get(), "Did you run Container::Init correctly?");
io->Ren->OnScreen(screen);
list->AddRectangle(FinalPos(), cbs, io->Theme->Get(color));
if (usr_ref) {
list->AddRectangle(FinalPos() + 2, cbs - 4,
io->Theme->Get(UI7Color_Checkmark));
}
list->AddText(FinalPos() + vec2(cbs.x() + io->ItemSpace.x(),
cbs.y() * 0.5 - tdim.y() * 0.5),
label, io->Theme->Get(UI7Color_Text));
}
void Checkbox::Update() {
Assert(io.get(), "Did you run Container::Init correctly?");
this->SetSize(cbs + vec2(tdim.x() + io->ItemSpace.x(), 0));
}
} // namespace UI7
/*
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/checkbox.hpp>
namespace PD {
namespace UI7 {
PD_UI7_API void Checkbox::HandleInput() {
/// Ensure to only check input once
if (inp_done) {
return;
}
color = UI7Color_FrameBackground;
/// 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 (io->InputHandler->DragObject(this->GetID(), vec4(FinalPos(), size))) {
if (io->InputHandler->DragReleased) {
color = UI7Color_FrameBackgroundHovered;
usr_ref = !usr_ref;
} else {
color = UI7Color_FrameBackgroundHovered;
}
}
//}
inp_done = true;
}
PD_UI7_API void Checkbox::Draw() {
// Assert(list.get() && io.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->AddRectangle(FinalPos(), cbs, io->Theme->Get(color));
if (usr_ref) {
list->AddRectangle(FinalPos() + 2, cbs - 4,
io->Theme->Get(UI7Color_Checkmark));
}
list->AddText(
FinalPos() + fvec2(cbs.x + io->ItemSpace.x, cbs.y * 0.5 - tdim.y * 0.5),
label, io->Theme->Get(UI7Color_Text));
}
PD_UI7_API void Checkbox::Update() {
// Assert(io.get(), "Did you run Container::Init correctly?");
this->SetSize(cbs + fvec2(tdim.x + io->ItemSpace.x, 0));
}
} // namespace UI7
} // namespace PD

View File

@ -1,65 +1,65 @@
/*
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>
#include <pd/ui7/container/label.hpp>
namespace PD {
namespace UI7 {
void ColorEdit::HandleInput() {
/// 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) {
is_shown = !is_shown;
}
}
}
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));
if (is_shown) {
if (!layout) {
layout = Layout::New(GetID(), io);
}
layout->AddObject(PD::New<Label>("Hello World!", io->Ren));
layout->Update();
io->RegisterDrawList(GetID(), layout->GetDrawList());
}
}
void ColorEdit::Update() {
Assert(io.get(), "Did you run Container::Init correctly?");
this->SetSize(vec2(tdim.x() + io->ItemSpace.x() + 20, 20));
}
} // namespace UI7
/*
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>
#include <pd/ui7/container/label.hpp>
namespace PD {
namespace UI7 {
PD_UI7_API void ColorEdit::HandleInput() {
/// 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->InputHandler->DragObject(this->GetID(), vec4(FinalPos(), size))) {
if (io->InputHandler->DragReleased) {
is_shown = !is_shown;
}
}
//}
inp_done = true;
}
PD_UI7_API void ColorEdit::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->AddRectangle(FinalPos(), fvec2(20, 20), *color_ref);
list->AddText(FinalPos() + fvec2(io->ItemSpace.x + 20, 0), label,
io->Theme->Get(UI7Color_Text));
if (is_shown) {
if (!layout) {
layout = Layout::New(GetID(), io);
}
layout->AddObject(PD::New<Label>("Hello World!", io));
layout->Update();
io->RegisterDrawList(GetID(), layout->GetDrawList());
}
}
PD_UI7_API void ColorEdit::Update() {
// Assert(io.get(), "Did you run Container::Init correctly?");
this->SetSize(fvec2(tdim.x + io->ItemSpace.x + 20, 20));
}
} // namespace UI7
} // namespace PD

View File

@ -21,19 +21,24 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/core/sys.hpp>
#include <pd/ui7/container/container.hpp>
namespace PD {
namespace UI7 {
void Container::HandleScrolling(vec2 scrolling, vec4 viewport) {
PD_UI7_API void Container::HandleScrolling(fvec2 scrolling, fvec4 viewport) {
if (last_use != 0 && Sys::GetTime() - last_use > 5000) {
rem = true;
}
last_use = Sys::GetTime();
pos -= vec2(0, scrolling.y());
pos -= fvec2(0, scrolling.y);
skippable = !LI::Renderer::InBox(
pos, size, vec4(viewport.xy(), viewport.xy() + viewport.zw()));
pos, size,
fvec4(viewport.x, viewport.y, viewport.x + viewport.z,
viewport.y + viewport.w));
}
PD_UI7_API void Container::HandleInternalInput() {
/** Requires Handle Scrolling First */
}
} // namespace UI7
} // namespace PD

View File

@ -1,113 +1,115 @@
/*
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/dragdata.hpp>
#include <pd/ui7/container/label.hpp>
#include <type_traits>
namespace PD {
namespace UI7 {
// Setup Supported Datatypes (Probably making this Object
// header only to not care about datatype support)
template class DragData<float>;
template class DragData<int>;
template class DragData<double>;
template class DragData<u8>;
template class DragData<u16>;
template class DragData<u32>;
template class DragData<u64>;
template <typename T>
void DragData<T>::HandleInput() {
/// Ensure to only check input once
if (inp_done) {
return;
}
Assert(screen.get(), "Screen is not set up!");
if (screen->ScreenType() == Screen::Bottom) {
float off_x = 0;
for (size_t i = 0; i < elm_count; i++) {
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", data[i], precision);
} else {
p = std::format("{}", data[i]);
}
vec2 tdim = io->Ren->GetTextDimensions(p);
// Unsafe but is the fastest solution
if (io->DragObject(
this->GetID() + i + 1,
vec4(FinalPos() + vec2(off_x, 0), tdim + io->FramePadding))) {
data[i] = std::clamp(T(data[i] + (step * (io->DragPosition[0] -
io->DragLastPosition[0]))),
this->min, this->max);
}
off_x += tdim.x() + io->ItemSpace.x() + io->FramePadding.x();
}
}
inp_done = true;
}
template <typename T>
void DragData<T>::Draw() {
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
io->Ren->OnScreen(screen);
float off_x = 0.f;
for (size_t i = 0; i < elm_count; i++) {
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", data[i], precision);
} else {
p = std::format("{}", data[i]);
}
vec2 td = io->Ren->GetTextDimensions(p);
list->AddRectangle(FinalPos() + vec2(off_x, 0), td + io->FramePadding,
io->Theme->Get(UI7Color_Button));
list->Layer(list->Layer() + 1);
list->AddText(FinalPos() + vec2(off_x, 0), p, io->Theme->Get(UI7Color_Text),
LITextFlags_AlignMid, td + io->FramePadding);
list->Layer(list->Layer() - 1);
off_x += td.x() + io->ItemSpace.x() + io->FramePadding.x();
}
list->AddText(FinalPos() + vec2(off_x, io->FramePadding.y() * 0.5), label,
io->Theme->Get(UI7Color_Text));
}
template <typename T>
void DragData<T>::Update() {
Assert(io.get(), "Did you run Container::Init correctly?");
// Probably need to find a faster solution (caching sizes calculated here)
float off_x = 0;
for (size_t i = 0; i < elm_count; i++) {
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", data[i], precision);
} else {
p = std::format("{}", data[i]);
}
vec2 tdim = io->Ren->GetTextDimensions(p);
off_x += tdim.x() + io->ItemSpace.x() + io->FramePadding.x();
}
this->SetSize(vec2(tdim.x() + off_x, tdim.y() + io->FramePadding.y()));
}
} // namespace UI7
/*
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/dragdata.hpp>
#include <pd/ui7/container/label.hpp>
#include <type_traits>
namespace PD {
namespace UI7 {
// Setup Supported Datatypes (Probably making this Object
// header only to not care about datatype support)
template class PD_UI7_API DragData<float>;
template class PD_UI7_API DragData<int>;
template class PD_UI7_API DragData<double>;
template class PD_UI7_API DragData<u8>;
template class PD_UI7_API DragData<u16>;
template class PD_UI7_API DragData<u32>;
template class PD_UI7_API DragData<u64>;
template <typename T>
PD_UI7_API void DragData<T>::HandleInput() {
/// Ensure to only check input once
if (inp_done) {
return;
}
// Assert(screen.get(), "Screen is not set up!");
// if (screen->ScreenType() == Screen::Bottom) {
float off_x = 0;
for (size_t i = 0; i < elm_count; i++) {
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", data[i], precision);
} else {
p = std::format("{}", data[i]);
}
vec2 tdim = io->Font->GetTextBounds(p, io->FontScale);
// Unsafe but is the fastest solution
if (io->InputHandler->DragObject(
this->GetID() + i + 1,
fvec4(FinalPos() + fvec2(off_x, 0), tdim + io->FramePadding))) {
data[i] = std::clamp(
T(data[i] + (step * (io->InputHandler->DragPosition.x -
io->InputHandler->DragLastPosition.x))),
this->min, this->max);
}
off_x += tdim.x + io->ItemSpace.x + io->FramePadding.x;
}
//}
inp_done = true;
}
template <typename T>
PD_UI7_API void DragData<T>::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
float off_x = 0.f;
for (size_t i = 0; i < elm_count; i++) {
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", data[i], precision);
} else {
p = std::format("{}", data[i]);
}
vec2 td = io->Font->GetTextBounds(p, io->FontScale);
list->AddRectangle(FinalPos() + fvec2(off_x, 0), td + io->FramePadding,
io->Theme->Get(UI7Color_Button));
list->Layer++;
list->AddText(FinalPos() + fvec2(off_x, 0), p,
io->Theme->Get(UI7Color_Text), LITextFlags_AlignMid,
td + io->FramePadding);
list->Layer--;
off_x += td.x + io->ItemSpace.x + io->FramePadding.x;
}
list->AddText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5), label,
io->Theme->Get(UI7Color_Text));
}
template <typename T>
PD_UI7_API void DragData<T>::Update() {
// Assert(io.get(), "Did you run Container::Init correctly?");
// Probably need to find a faster solution (caching sizes calculated here)
float off_x = 0;
for (size_t i = 0; i < elm_count; i++) {
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", data[i], precision);
} else {
p = std::format("{}", data[i]);
}
vec2 tdim = io->Font->GetTextBounds(p, io->FontScale);
off_x += tdim.x + io->ItemSpace.x + io->FramePadding.x;
}
this->SetSize(vec2(tdim.x + off_x, tdim.y + io->FramePadding.y));
}
} // namespace UI7
} // namespace PD

View File

@ -0,0 +1,33 @@
/*
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 <pd/ui7/container/dynobj.hpp>
namespace PD {
namespace UI7 {
PD_UI7_API void DynObj::Draw() { pRenFun(io, list, this); }
PD_UI7_API void DynObj::HandleInput() {}
PD_UI7_API void DynObj::Update() {}
} // namespace UI7
} // namespace PD

View File

@ -25,11 +25,13 @@ SOFTWARE.
namespace PD {
namespace UI7 {
void Image::Draw() {
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
Assert(img.get(), "Image is nullptr!");
io->Ren->OnScreen(screen);
PD_UI7_API void Image::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// Assert(img.get(), "Image is nullptr!");
// io->Ren->OnScreen(screen);
list->Layer++;
list->AddImage(FinalPos(), img, newsize, this->cuv);
list->Layer--;
}
} // namespace UI7
} // namespace PD

View File

@ -25,9 +25,9 @@ SOFTWARE.
namespace PD {
namespace UI7 {
void Label::Draw() {
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
io->Ren->OnScreen(screen);
PD_UI7_API void Label::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->AddText(FinalPos(), label, io->Theme->Get(UI7Color_Text));
}
} // namespace UI7

View File

@ -1,263 +1,288 @@
/*
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/core/strings.hpp>
#include <pd/ui7/drawlist.hpp>
namespace PD {
namespace UI7 {
void DrawList::PathArcToN(const vec2& c, float radius, float a_min, float a_max,
int segments) {
// Path.push_back(c);
PathReserve(segments + 1);
for (int i = 0; i < segments; i++) {
float a = a_min + ((float)i / (float)segments) * (a_max - a_min);
PathNext(vec2(c.x() + std::cos(a) * radius, c.y() + std::sin(a) * radius));
}
}
void DrawList::PathRect(vec2 a, vec2 b, float rounding, UI7DrawFlags flags) {
if (rounding == 0.f) {
PathNext(a);
PathNext(vec2(b.x(), a.y()));
PathNext(b);
PathNext(vec2(a.x(), b.y()));
} else {
PathArcToN(vec2(a.x() + rounding, a.y() + rounding), rounding, 4*6, 4*9, 21);
PathArcToN(vec2(b.x() - rounding, a.y() + rounding), rounding, 4*9, 4*12, 21);
PathArcToN(vec2(b.x() - rounding, b.y() - rounding), rounding, 4*0, 4*3, 21);
PathArcToN(vec2(a.x() + rounding, b.y() - rounding), rounding, 4*3, 4*6, 21);
}
}
void DrawList::AddRect(const vec2& pos, const vec2& size, const UI7Color& clr,
int thickness) {
if (!ren->InBox(pos, size, ren->GetViewport())) {
return;
}
ren->UseTex();
PathRect(pos, pos + size);
PathStroke(clr, thickness, UI7DrawFlags_Close);
}
void DrawList::AddRectangle(vec2 pos, vec2 szs, const UI7Color& clr) {
if (!ren->InBox(pos, szs, ren->GetViewport())) {
return;
}
ren->UseTex();
PathRect(pos, pos + szs);
PathFill(clr);
}
void DrawList::AddTriangle(const vec2& a, const vec2& b, const vec2& c,
const UI7Color& clr, int thickness) {
ren->UseTex();
PathNext(a);
PathNext(b);
PathNext(c);
PathStroke(clr, thickness, UI7DrawFlags_Close);
}
void DrawList::AddTriangleFilled(const vec2& a, const vec2& b, const vec2& c,
const UI7Color& clr) {
ren->UseTex();
PathNext(a);
PathNext(b);
PathNext(c);
PathFill(clr);
}
void DrawList::AddCircle(const vec2& pos, float rad, UI7Color col,
int num_segments, int thickness) {
if (num_segments <= 0) {
// Auto Segment
} else {
float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments;
PathArcToN(pos, rad, 0.f, am, num_segments);
}
ren->UseTex();
PathStroke(col, thickness, UI7DrawFlags_Close);
}
void DrawList::AddCircleFilled(const vec2& pos, float rad, UI7Color col,
int num_segments) {
if (num_segments <= 0) {
// Auto Segment
} else {
float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments;
PathArcToN(pos, rad, 0.f, am, num_segments);
}
ren->UseTex();
PathFill(col);
}
void DrawList::AddText(vec2 pos, const std::string& text, const UI7Color& clr,
LITextFlags flags, vec2 box) {
if (!ren->Font()) {
return;
}
u32 id = Strings::FastHash(text);
LI::StaticText::Ref e;
auto f = static_text.find(id);
if (static_text.find(id) == static_text.end()) {
e = LI::StaticText::New();
static_text[id] = e;
} else {
e = f->second;
}
if (!e->IsSetup() || e->Font() != ren->Font()) {
int l = ren->Layer();
ren->Layer(layer);
e->Setup(ren.get(), pos, clr, text, flags, box);
e->Font(ren->Font());
ren->Layer(l);
}
e->SetPos(pos);
e->SetColor(clr);
e->SetLayer(layer);
if (!clip_rects.empty()) {
e->SetScissorMode(LI::ScissorMode_Normal);
e->ScissorRect(clip_rects.top());
}
for (auto it : e->GetRawObject()->List()) {
this->commands.push_back(std::make_pair(
ren->CurrentScreen()->ScreenType() == Screen::Bottom, it));
}
e->GetRawObject()->ReCopy();
}
void DrawList::AddImage(vec2 pos, Texture::Ref img, vec2 size, LI::Rect uv) {
size = size == 0.f ? img->GetSize() : size;
uv = (uv.Top() == 0.0f && uv.Bot() == 0.0f) ? img->GetUV() : uv;
if (!ren->InBox(pos, size, ren->GetViewport())) {
return;
}
auto rect = ren->CreateRect(pos, size, 0.f);
auto cmd = LI::Command::New();
ren->UseTex(img);
ren->SetupCommand(cmd);
cmd->Layer(layer);
if (!clip_rects.empty()) {
cmd->SetScissorMode(LI::ScissorMode_Normal);
cmd->ScissorRect(clip_rects.top());
}
ren->QuadCommand(cmd, rect, uv, 0xffffffff);
commands.push_back(std::make_pair(
ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd));
}
void DrawList::AddLine(const vec2& a, const vec2& b, const UI7Color& clr,
int t) {
if (!ren->InBox(a, ren->GetViewport()) &&
!ren->InBox(b, ren->GetViewport())) {
return;
}
ren->UseTex();
PathNext(a);
PathNext(b);
PathStroke(clr, t);
}
// TODO: Don't render OOS
void DrawList::AddPolyLine(const std::vector<vec2>& points, const UI7Color& clr,
UI7DrawFlags flags, int thickness) {
if (points.size() < 2) {
return;
}
auto cmd = LI::Command::New();
ren->SetupCommand(cmd);
cmd->Layer(layer);
if (!clip_rects.empty()) {
cmd->SetScissorMode(LI::ScissorMode_Normal);
cmd->ScissorRect(clip_rects.top());
}
bool close = (flags & UI7DrawFlags_Close);
int num_points = close ? (int)points.size() : (int)points.size() - 1;
if (flags & UI7DrawFlags_AALines) {
// TODO: Find a way to draw less garbage looking lines
} else {
// Non antialiased lines look awful when rendering with thickness != 1
for (int i = 0; i < num_points; i++) {
int j = (i + 1) == (int)points.size() ? 0 : (i + 1);
auto line = ren->CreateLine(points[i], points[j], thickness);
ren->QuadCommand(cmd, line, vec4(0.f, 1.f, 1.f, 0.f), clr);
}
}
commands.push_back(std::make_pair(
ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd));
}
// TODO: Don't render OOS (Probably make it with a define as it
// would probably be faster to render out of screen than checking if
// it could be skipped)
void DrawList::AddConvexPolyFilled(const std::vector<vec2>& points,
const UI7Color& clr) {
if (points.size() < 3) {
return; // Need at least three points
}
auto cmd = LI::Command::New();
ren->SetupCommand(cmd);
cmd->Layer(layer);
if (!clip_rects.empty()) {
cmd->SetScissorMode(LI::ScissorMode_Normal);
cmd->ScissorRect(clip_rects.top());
}
for (int i = 2; i < (int)points.size(); i++) {
cmd->PushIndex(0).PushIndex(i).PushIndex(i - 1);
}
for (int i = 0; i < (int)points.size(); i++) {
cmd->PushVertex(LI::Vertex(points[i], vec2(0, 0), clr));
}
commands.push_back(std::make_pair(
ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd));
}
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;
std::vector<u32> rem;
for (auto it : static_text) {
if (!it.second->Used()) {
rem.push_back(it.first);
}
it.second->SetUnused();
}
for (auto& it : rem) {
static_text.erase(it);
}
while (!clip_rects.empty()) {
clip_rects.pop();
}
}
} // namespace UI7
/*
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/core/core.hpp>
#include <pd/ui7/drawlist.hpp>
#include <pd/ui7/io.hpp>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
namespace PD {
namespace UI7 {
PD_UI7_API void DrawList::PathArcToN(const fvec2& c, float radius, float a_min,
float a_max, int segments) {
// Path.push_back(c);
PathReserve(segments + 1);
for (int i = 0; i < segments; i++) {
float a = a_min + ((float)i / (float)segments) * (a_max - a_min);
PathNext(vec2(c.x + std::cos(a) * radius, c.y + std::sin(a) * radius));
}
}
PD_UI7_API void DrawList::PathRect(fvec2 a, fvec2 b, float rounding,
UI7DrawFlags flags) {
if (rounding == 0.f) {
PathNext(a);
PathNext(vec2(b.x, a.y));
PathNext(b);
PathNext(vec2(a.x, b.y));
} else {
PathArcToN(vec2(a.x + rounding, a.y + rounding), rounding, 4 * 6, 4 * 9,
21);
PathArcToN(vec2(b.x - rounding, a.y + rounding), rounding, 4 * 9, 4 * 12,
21);
PathArcToN(vec2(b.x - rounding, b.y - rounding), rounding, 4 * 0, 4 * 3,
21);
PathArcToN(vec2(a.x + rounding, b.y - rounding), rounding, 4 * 3, 4 * 6,
21);
}
}
PD_UI7_API void DrawList::AddRect(const fvec2& pos, const fvec2& size,
const UI7Color& clr, int thickness) {
PathRect(pos, pos + size);
PathStroke(clr, thickness, UI7DrawFlags_Close);
}
PD_UI7_API void DrawList::AddRectangle(fvec2 pos, fvec2 szs,
const UI7Color& clr) {
PathRect(pos, pos + szs);
PathFill(clr);
}
PD_UI7_API void DrawList::AddTriangle(const fvec2& a, const fvec2& b,
const fvec2& c, const UI7Color& clr,
int thickness) {
PathNext(a);
PathNext(b);
PathNext(c);
PathStroke(clr, thickness, UI7DrawFlags_Close);
}
PD_UI7_API void DrawList::AddTriangleFilled(const fvec2& a, const fvec2& b,
const fvec2& c,
const UI7Color& clr) {
PathNext(a);
PathNext(b);
PathNext(c);
PathFill(clr);
}
PD_UI7_API void DrawList::AddCircle(const fvec2& pos, float rad, UI7Color col,
int num_segments, int thickness) {
if (num_segments <= 0) {
// Auto Segment
} else {
float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments;
PathArcToN(pos, rad, 0.f, am, num_segments);
}
PathStroke(col, thickness, UI7DrawFlags_Close);
}
PD_UI7_API void DrawList::AddCircleFilled(const fvec2& pos, float rad,
UI7Color col, int num_segments) {
if (num_segments <= 0) {
// Auto Segment
} else {
float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments;
PathArcToN(pos, rad, 0.f, am, num_segments);
}
PathFill(col);
}
PD_UI7_API void DrawList::AddText(fvec2 pos, const std::string& text,
const UI7Color& clr, u32 flags, fvec2 box) {
Vec<LI::Command::Ref> cmds;
pIO->Font->CmdTextEx(cmds, pos, clr, pIO->FontScale, text, flags, box);
for (size_t i = 0; i < cmds.Size(); i++) {
ClipCmd(cmds[i]);
cmds[i]->Layer = Layer;
cmds[i]->Index = Commands.Size();
Commands.Add(cmds[i]);
}
// if (!IO->Ren->Font()) {
// return;
// }
// u32 id = Strings::FastHash(text);
// LI::StaticText::Ref e;
// auto f = static_text.find(id);
// if (static_text.find(id) == static_text.end()) {
// e = LI::StaticText::New();
// static_text[id] = e;
// } else {
// e = f->second;
// }
// if (!e->IsSetup() || e->Font() != IO->Ren->Font()) {
// int l = IO->Ren->Layer();
// IO->Ren->Layer(layer);
// e->Setup(ren.get(), pos, clr, text, flags, box);
// e->Font(IO->Ren->Font());
// IO->Ren->Layer(l);
// }
// e->SetPos(pos);
// e->SetColor(clr);
// e->SetLayer(layer);
// if (!clip_rects.empty()) {
// e->SetScissorMode(LI::ScissorMode_Normal);
// e->ScissorRect(clip_rects.top());
// }
// for (auto it : e->GetRawObject()->List()) {
// this->commands.push_back(std::make_pair(
// IO->Ren->CurrentScreen()->ScreenType() == Screen::Bottom, it));
// }
// e->GetRawObject()->ReCopy();
}
PD_UI7_API void DrawList::AddImage(fvec2 pos, LI::Texture::Ref img, fvec2 size,
LI::Rect uv) {
size = size == 0.f ? fvec2(img->GetSize().x, img->GetSize().y) : size;
uv = (uv.Top() == 0.0f && uv.Bot() == 0.0f) ? img->GetUV() : uv;
LI::Command::Ref cmd = LI::Command::New();
cmd->Layer = Layer;
cmd->Index = Commands.Size();
cmd->Tex = img;
auto r = LI::Renderer::PrimRect(pos, size);
LI::Renderer::CmdQuad(cmd, r, uv, 0xffffffff);
// auto rect = IO->Ren->CreateRect(pos, size, 0.f);
// auto cmd = LI::Command::New();
// IO->Ren->UseTex(img);
// IO->Ren->SetupCommand(cmd);
// cmd->Layer(layer);
// if (!clip_rects.empty()) {
// cmd->SetScissorMode(LI::ScissorMode_Normal);
// cmd->ScissorRect(clip_rects.top());
// }
// IO->Ren->QuadCommand(cmd, rect, uv, 0xffffffff);
// commands.push_back(std::make_pair(
// IO->Ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd));
}
PD_UI7_API void DrawList::AddLine(const fvec2& a, const fvec2& b,
const UI7Color& clr, int t) {
PathNext(a);
PathNext(b);
PathStroke(clr, t);
}
// TODO: Don't render OOS
PD_UI7_API void DrawList::AddPolyLine(const Vec<fvec2>& points,
const UI7Color& clr, UI7DrawFlags flags,
int thickness) {
if (points.Size() < 2) {
return;
}
auto cmd = LI::Command::New();
cmd->Index = Commands.Size();
cmd->Layer = Layer;
cmd->Tex = pIO->Ren->WhitePixel;
ClipCmd(cmd);
bool close = (flags & UI7DrawFlags_Close);
int num_points = close ? (int)points.Size() : (int)points.Size() - 1;
if (flags & UI7DrawFlags_AALines) {
// TODO: Find a way to draw less garbage looking lines
} else {
// Non antialiased lines look awful when rendering with thickness != 1
for (int i = 0; i < num_points; i++) {
int j = (i + 1) == (int)points.Size() ? 0 : (i + 1);
auto line = LI::Renderer::PrimLine(points[i], points[j], thickness);
LI::Renderer::CmdQuad(cmd, line, vec4(0.f, 1.f, 1.f, 0.f), clr);
}
}
Commands.Add(cmd);
}
PD_UI7_API void DrawList::ClipCmd(LI::Command::Ref cmd) {
if (!pClipRects.IsEmpty()) {
cmd->ScissorEnabled = true;
fvec4 sr = pClipRects.Top();
cmd->ScissorRect = ivec4(sr.x, sr.y, sr.z, sr.w);
}
}
// TODO: Don't render OOS (Probably make it with a define as it
// would probably be faster to render out of screen than checking if
// it could be skipped)
PD_UI7_API void DrawList::AddConvexPolyFilled(const Vec<fvec2>& points,
const UI7Color& clr) {
if (points.Size() < 3) {
return; // Need at least three points
}
auto cmd = LI::Command::New();
cmd->Index = Commands.Size();
cmd->Layer = Layer;
auto tex = CurrentTex;
if (!tex) {
tex = pIO->Ren->WhitePixel;
}
cmd->Tex = tex;
ClipCmd(cmd);
for (int i = 2; i < (int)points.Size(); i++) {
cmd->AppendIndex(0).AppendIndex(i).AppendIndex(i - 1);
}
for (int i = 0; i < (int)points.Size(); i++) {
cmd->AppendVertex(LI::Vertex(points[i], fvec2(0, 0), clr));
}
Commands.Add(cmd);
}
PD_UI7_API void DrawList::Clear() { Commands.Clear(); }
/** Process [Render] the Drawlist */
PD_UI7_API void DrawList::Process(LI::DrawList::Ref d) {
std::sort(Commands.Begin(), Commands.End(),
[](LI::Command::Ref a, LI::Command::Ref b) {
/** Advanced (for saving Drawcalls)
* - Probably could handle this by creating diffrent layers
* for texts and solid objectives
* if(a->Tex == b->Tex) { return a->Layer < b->Layer; }
* return a->Tex < b->Tex;
*/
/** Simple */
return a->Layer < b->Layer;
});
NumVertices = 0;
NumIndices = 0;
for (auto command = Commands.Begin(); command != Commands.End(); command++) {
// IO->Ren->OnScreen(IO->Ren->GetScreen(command.first));
(*command)->Layer = (*command)->Layer + Base;
d->AddCommand(*command);
NumVertices += (*command)->VertexBuffer.Size();
NumIndices += (*command)->IndexBuffer.Size();
}
Commands.Clear();
Layer = 0;
std::vector<u32> rem;
// for (auto it : static_text) {
// if (!it.second->Used()) {
// rem.push_back(it.first);
// }
// it.second->SetUnused();
// }
// for (auto& it : rem) {
// static_text.erase(it);
// }
pClipRects.Clear();
}
} // namespace UI7
} // namespace PD

View File

@ -1,42 +1,40 @@
/*
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/core/timetrace.hpp>
#include <pd/ui7/io.hpp>
namespace PD {
void UI7::IO::Update() {
u64 current = Sys::GetNanoTime();
Delta = static_cast<float>(current - LastTime) / 1000000.f;
LastTime = current;
DeltaStats->Add(Delta * 1000);
Time->Update();
DragTime->Update();
DragReleased = false;
DragReleasedAW = false;
DragDoubleRelease = false;
Framerate = 1000.f / Delta;
DrawListRegestry.clear();
RegisterDrawList("CtxBackList", Back);
}
/*
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/core/core.hpp>
#include <pd/ui7/io.hpp>
namespace PD {
PD_UI7_API void UI7::IO::Update() {
u64 current = Sys::GetNanoTime();
Delta = static_cast<float>(current - LastTime) / 1000000.f;
LastTime = current;
DeltaStats->Add(Delta * 1000);
Time->Update();
InputHandler->Update();
Framerate = 1000.f / Delta;
DrawListRegestry.Clear();
DrawListRegestry.PushFront(Pair<UI7::ID, DrawList::Ref>("CtxBackList", Back));
// RegisterDrawList("CtxBackList", Back);
}
} // namespace PD

View File

@ -1,118 +1,140 @@
/*
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/layout.hpp>
namespace PD {
namespace UI7 {
void Layout::CursorInit() { Cursor = WorkRect.xy(); }
void Layout::SameLine() {
BackupCursor = LastObjSize;
Cursor = SamelineCursor;
}
void Layout::CursorMove(const vec2& size) {
LastObjSize = size;
SamelineCursor = Cursor + vec2(size[0] + IO->ItemSpace[0], 0);
if (BeforeSameLine[1]) {
Cursor = vec2(IO->MenuPadding[0],
Cursor[1] + BeforeSameLine[1] + IO->ItemSpace[1]);
BeforeSameLine = 0.f;
} else {
Cursor = vec2(IO->MenuPadding[0] + InitialCursorOffset[0],
Cursor[1] + size[1] + IO->ItemSpace[1]);
}
// Logical Issue here as x should use a max check
MaxPosition = vec2(std::max(MaxPosition[0], SamelineCursor[0]), Cursor[1]);
}
bool Layout::ObjectWorkPos(vec2& movpos) {
if (Scrolling[1]) {
movpos[1] -= ScrollOffset[1];
if (!IO->Ren->InBox(movpos, LastObjSize,
vec4(WorkRect.xy(), WorkRect.xy() + WorkRect.zw()))) {
return true;
}
}
return false;
}
void Layout::AddObject(Container::Ref obj) {
obj->Init(IO, DrawList);
obj->SetPos(AlignPosition(Cursor, obj->GetSize(), WorkRect, GetAlignment()));
obj->Update();
CursorMove(obj->GetSize());
obj->HandleScrolling(ScrollOffset, WorkRect);
Objects.push_back(obj);
}
Container::Ref Layout::FindObject(u32 id) {
for (auto& it : IDObjects) {
if (it->GetID() == id) {
return it;
}
}
return nullptr;
}
vec2 Layout::AlignPosition(vec2 pos, vec2 size, vec4 area, UI7Align alignment) {
vec2 p = pos;
if (alignment & UI7Align_Center) {
p[0] = (area[0] + area[2]) * 0.5 - (pos[0] - area[0] + size[0] * 0.5);
} else if (alignment & UI7Align_Right) {
}
if (alignment & UI7Align_Mid) {
p[1] = (area[1] + area[3]) * 0.5 - (pos[1] - area[1] + size[1] * 0.5);
} else if (alignment & UI7Align_Bottom) {
}
return p;
}
void Layout::Update() {
for (auto& it : Objects) {
if (it->GetID() != 0 && !FindObject(it->GetID())) {
IDObjects.push_back(it);
}
if (!it->Skippable()) {
it->SetPos(it->GetPos() + Pos);
it->HandleInput();
it->UnlockInput();
it->Draw();
}
}
std::vector<size_t> tbr;
for (size_t i = 0; i < IDObjects.size(); i++) {
if (IDObjects[i]->Removable()) {
tbr.push_back(i);
}
}
for (auto& it : tbr) {
IDObjects.erase(IDObjects.begin() + it);
}
Objects.clear();
WorkRect = vec4(WorkRect.xy(), Size - IO->MenuPadding);
CursorInit();
}
} // namespace UI7
/*
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/layout.hpp>
namespace PD {
namespace UI7 {
PD_UI7_API void Layout::CursorInit() { Cursor = fvec2(WorkRect.x, WorkRect.y); }
PD_UI7_API void Layout::SameLine() {
BackupCursor = LastObjSize;
Cursor = SamelineCursor;
}
PD_UI7_API void Layout::CursorMove(const fvec2& size) {
LastObjSize = size;
SamelineCursor = Cursor + fvec2(size.x + IO->ItemSpace.x, 0);
if (BeforeSameLine.y) {
Cursor =
fvec2(IO->MenuPadding.x, Cursor.y + BeforeSameLine.y + IO->ItemSpace.y);
BeforeSameLine = 0.f;
} else {
Cursor = fvec2(IO->MenuPadding.x + InitialCursorOffset.x,
Cursor.y + size.y + IO->ItemSpace.y);
}
// Logical Issue here as x should use a max check
MaxPosition = fvec2(std::max(MaxPosition.x, SamelineCursor.x), Cursor.y);
}
PD_UI7_API bool Layout::ObjectWorkPos(fvec2& movpos) {
if (Scrolling[1]) {
movpos.y -= ScrollOffset.y;
if (!IO->Ren->InBox(movpos, LastObjSize,
fvec4(WorkRect.x, WorkRect.y, WorkRect.x + WorkRect.z,
WorkRect.y + WorkRect.w))) {
return true;
}
}
return false;
}
PD_UI7_API void Layout::AddObject(Container::Ref obj) {
obj->Init(IO, DrawList);
obj->SetPos(AlignPosition(Cursor, obj->GetSize(), WorkRect, GetAlignment()));
obj->Update();
CursorMove(obj->GetSize());
obj->HandleScrolling(ScrollOffset, WorkRect);
Objects.PushBack(obj);
}
PD_UI7_API void Layout::AddObjectEx(Container::Ref obj, u32 flags) {
obj->Init(IO, DrawList);
if (!(flags & 1)) {
obj->SetPos(
AlignPosition(Cursor, obj->GetSize(), WorkRect, GetAlignment()));
}
obj->Update();
if (!(flags & 1)) {
CursorMove(obj->GetSize());
}
if (!(flags & 2)) {
obj->HandleScrolling(ScrollOffset, WorkRect);
}
if (!(flags & 4)) {
Objects.PushFront(obj);
} else {
Objects.PushBack(obj);
}
}
PD_UI7_API Container::Ref Layout::FindObject(u32 id) {
for (auto& it : IDObjects) {
if (it->GetID() == id) {
return it;
}
}
return nullptr;
}
PD_UI7_API fvec2 Layout::AlignPosition(fvec2 pos, fvec2 size, fvec4 area,
UI7Align alignment) {
vec2 p = pos;
if (alignment & UI7Align_Center) {
p.x = (area.x + area.z) * 0.5 - (pos.x - area.x + size.x * 0.5);
} else if (alignment & UI7Align_Right) {
}
if (alignment & UI7Align_Mid) {
p.y = (area.y + area.w) * 0.5 - (pos.y - area.y + size.y * 0.5);
} else if (alignment & UI7Align_Bottom) {
}
return p;
}
PD_UI7_API void Layout::Update() {
for (auto& it : Objects) {
if (it->GetID() != 0 && !FindObject(it->GetID())) {
IDObjects.push_back(it);
}
if (!it->Skippable()) {
it->SetPos(it->GetPos() + Pos);
it->HandleInput();
it->UnlockInput();
it->Draw();
}
}
std::vector<size_t> tbr;
for (size_t i = 0; i < IDObjects.size(); i++) {
if (IDObjects[i]->Removable()) {
tbr.push_back(i);
}
}
for (auto& it : tbr) {
IDObjects.erase(IDObjects.begin() + it);
}
Objects.Clear();
WorkRect = fvec4(fvec2(WorkRect.x, WorkRect.y), Size - IO->MenuPadding);
CursorInit();
}
} // namespace UI7
} // namespace PD

File diff suppressed because it is too large Load Diff

269
source/ui7/remenu.cpp Normal file
View File

@ -0,0 +1,269 @@
/*
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 <pd/ui7/containers.hpp>
#include <pd/ui7/remenu.hpp>
namespace PD {
namespace UI7 {
PD_UI7_API void UI7::ReMenu::Label(const std::string& label) {
// Layout API
auto r = PD::New<UI7::Label>(label, pIO);
pLayout->AddObject(r);
}
PD_UI7_API bool UI7::ReMenu::Button(const std::string& label) {
bool ret = false;
u32 id = Strings::FastHash("btn" + label +
std::to_string(pLayout->Objects.Size()));
Container::Ref r = pLayout->FindObject(id);
if (!r) {
r = PD::New<UI7::Button>(label, pIO);
r->SetID(id);
}
pLayout->AddObject(r);
if (!r->Skippable()) {
ret = std::static_pointer_cast<UI7::Button>(r)->IsPressed();
}
return ret;
}
/*PD_UI7_API void UI7::ReMenu::DragFloat(const std::string& label, float* data,
size_t num_elms) {
u32 id = Strings::FastHash("dfl" + label + std::to_string(count_btn++));
Container::Ref r = Layout->FindObject(id);
if (!r) {
r = PD::New<UI7::DragData<float>>(label, data, num_elms, io);
r->SetID(id);
}
Layout->AddObject(r);
}*/
PD_UI7_API void UI7::ReMenu::Checkbox(const std::string& label, bool& v) {
u32 id = Strings::FastHash("cbx" + label +
std::to_string(pLayout->Objects.Size()));
Container::Ref r = pLayout->FindObject(id);
if (!r) {
r = PD::New<UI7::Checkbox>(label, v, pIO);
r->SetID(id);
}
pLayout->AddObject(r);
}
PD_UI7_API void UI7::ReMenu::Image(LI::Texture::Ref img, fvec2 size,
LI::Rect uv) {
Container::Ref r = PD::New<UI7::Image>(img, size, uv);
pLayout->AddObject(r);
}
PD_UI7_API void ReMenu::Separator() {
// Dynamic Objects are very simple...
Container::Ref r = PD::New<UI7::DynObj>(
[=, this](UI7::IO::Ref io, UI7::DrawList::Ref l, UI7::Container* self) {
l->AddRect(self->FinalPos(), self->GetSize(),
pIO->Theme->Get(UI7Color_TextDead));
});
// Set size before pushing (cause Cursor Move will require it)
r->SetSize(fvec2(pLayout->Size.x - 10, 1));
pLayout->AddObject(r);
}
PD_UI7_API void ReMenu::SeparatorText(const std::string& label) {
// Also note to use [=] instead of [&] to not undefined access label
Container::Ref r = PD::New<UI7::DynObj>(
[=, this](UI7::IO::Ref io, UI7::DrawList::Ref l, UI7::Container* self) {
fvec2 size = self->GetSize();
fvec2 tdim = io->Font->GetTextBounds(label, io->FontScale);
fvec2 pos = self->FinalPos();
auto align = pLayout->GetAlignment();
vec2 rpos = pLayout->AlignPosition(
pos, tdim, fvec4(pLayout->Pos, pLayout->Size), align);
if (!(align & UI7Align_Left)) {
l->AddRectangle(fvec2(rpos.x + io->FramePadding.x, tdim.y * 0.5),
fvec2(pos.x - rpos.x - io->MenuPadding.x, 1),
io->Theme->Get(UI7Color_TextDead));
}
if (!(align & UI7Align_Right)) {
l->AddRectangle(
pos + fvec2(tdim.x + io->FramePadding.x, tdim.y * 0.5),
fvec2(size.x - tdim.x - io->MenuPadding.x, 1),
io->Theme->Get(UI7Color_TextDead));
}
l->AddText(rpos, label, io->Theme->Get(UI7Color_Text), 0,
fvec2(pLayout->Size.x, self->GetSize().y));
});
// Set size before pushing (cause Cursor Move will require it)
r->SetSize(
fvec2(pLayout->Size.x - 10, pIO->Font->PixelHeight * pIO->FontScale));
pLayout->AddObject(r);
}
PD_UI7_API void ReMenu::HandleFocus() {
// Check if menu can be focused for Selective Menu Input API
vec4 newarea = fvec4(pLayout->Pos, pLayout->Size);
if (!pIsOpen) {
newarea = fvec4(pLayout->Pos, fvec2(pLayout->Size.x, TitleBarHeight));
}
if (pIO->Inp->IsDown(pIO->Inp->Touch) &&
pIO->Ren->InBox(pIO->Inp->TouchPos(), newarea) &&
!pIO->Ren->InBox(pIO->Inp->TouchPos(),
pIO->InputHandler->FocusedMenuRect)) {
pIO->InputHandler->FocusedMenu = pID;
}
if (pIO->InputHandler->FocusedMenu == pID) {
pIO->InputHandler->FocusedMenuRect = newarea;
}
}
PD_UI7_API void ReMenu::HandleScrolling() {}
PD_UI7_API void ReMenu::HandleTitlebarActions() {
// Collapse
if (!(Flags & UI7MenuFlags_NoCollapse)) {
vec2 cpos = pLayout->Pos + pIO->FramePadding;
// clr_collapse_tri = UI7Color_FrameBackground;
if (pIO->InputHandler->DragObject(UI7::ID(pID.GetName() + "clbse"),
fvec4(cpos, fvec2(18, TitleBarHeight)))) {
if (pIO->InputHandler->DragReleased) {
pIsOpen = !pIsOpen;
}
// clr_collapse_tri = UI7Color_FrameBackgroundHovered;
}
}
// Close Logic
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown != nullptr) {
vec2 cpos =
fvec2(pLayout->Pos.x + pLayout->Size.x - 12 - pIO->FramePadding.x,
pLayout->Pos.y + pIO->FramePadding.y);
// clr_close_btn = UI7Color_FrameBackground;
if (pIO->InputHandler->DragObject(UI7::ID(pID.GetName() + "clse"),
fvec4(cpos, fvec2(12)))) {
if (pIO->InputHandler->DragReleased) {
*pIsShown = !(*pIsShown);
}
// clr_close_btn = UI7Color_FrameBackgroundHovered;
}
}
// Menu Movement
if (!(Flags & UI7MenuFlags_NoMove)) {
if (pIO->InputHandler->DragObject(
pID.GetName() + "tmv",
fvec4(pLayout->Pos, fvec2(pLayout->Size.x, TitleBarHeight)))) {
if (pIO->InputHandler->DragDoubleRelease) {
pIsOpen = !pIsOpen;
}
pLayout->Pos = pLayout->Pos + (pIO->InputHandler->DragPosition -
pIO->InputHandler->DragLastPosition);
// Have no ViewPort Yet :(
// pLayout->Pos = std::clamp(pLayout->Pos, fvec2(10), fvec2(1270, 710));
}
}
}
PD_UI7_API void ReMenu::DrawBaseLayout() {
if (pIsOpen) {
Container::Ref r = PD::New<UI7::DynObj>(
[](UI7::IO::Ref io, UI7::DrawList::Ref l, UI7::Container* self) {
l->Layer = 0;
l->AddRectangle(self->FinalPos(), self->GetSize(),
io->Theme->Get(UI7Color_Background));
});
// Set size before pushing (cause Cursor Move will require it)
r->SetSize(
fvec2(pLayout->GetSize().x, pLayout->GetSize().y - TitleBarHeight));
r->SetPos(fvec2(0, TitleBarHeight));
pLayout->AddObjectEx(r, UI7LytAdd_NoCursorUpdate |
UI7LytAdd_NoScrollHandle | UI7LytAdd_Front);
}
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
Container::Ref r = PD::New<UI7::DynObj>(
[=, this](UI7::IO::Ref io, UI7::DrawList::Ref l, UI7::Container* self) {
l->Layer = 20;
/** Header Bar */
l->AddRectangle(self->FinalPos(), self->GetSize(),
io->Theme->Get(UI7Color_Header));
l->Layer = 21;
/** Inline if statement to shift the Text if collapse sym is shown */
/** What the hell is this code btw (didn't found a better way) */
l->AddText(self->FinalPos() +
fvec2(Flags & UI7MenuFlags_NoClose
? 0
: (TitleBarHeight - pIO->FramePadding.y * 2 +
(io->FramePadding.x * 2)),
0),
pID.GetName(), io->Theme->Get(UI7Color_Text));
});
r->SetSize(fvec2(pLayout->GetSize().x, TitleBarHeight));
r->SetPos(0);
pLayout->AddObjectEx(r,
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
/** Collapse Sym */
if (!(Flags & UI7MenuFlags_NoCollapse)) {
r = PD::New<UI7::DynObj>([=, this](UI7::IO::Ref io, UI7::DrawList::Ref l,
UI7::Container* self) {
/** This sym actually requires layer 21 (i dont know why) */
l->Layer = 21;
/**
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
*/
l->AddTriangleFilled(
self->FinalPos(),
self->FinalPos() +
fvec2(self->GetSize().x, pIsOpen ? 0 : self->GetSize().y * 0.5),
self->FinalPos() +
fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y),
io->Theme->Get(UI7Color_FrameBackground));
});
r->SetSize(TitleBarHeight - pIO->FramePadding.y * 2);
r->SetPos(pIO->FramePadding);
pLayout->AddObjectEx(r,
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
}
/** Close Sym (only shown if pIsShown is not nullptr) */
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) {
fvec2 size = TitleBarHeight - pIO->FramePadding.y * 2; // Fixed quad size
// Need to clamp this way as the math lib lacks a less and greater
// operator in vec2 (don't checked if it would make sense yet)
size.x = std::clamp(size.x, 5.f, std::numeric_limits<float>::max());
size.y = std::clamp(size.y, 5.f, std::numeric_limits<float>::max());
// Probably should fix the minsize to be locked on y
fvec2 cpos =
fvec2(pLayout->Pos.x + pLayout->Size.x - size.x - pIO->FramePadding.x,
pLayout->Pos.y + pIO->FramePadding.y);
pLayout->DrawList->AddLine(cpos, cpos + size,
pIO->Theme->Get(UI7Color_FrameBackground), 2);
pLayout->DrawList->AddLine(cpos + fvec2(0, size.y),
cpos + fvec2(size.x, 0),
pIO->Theme->Get(UI7Color_FrameBackground), 2);
}
}
}
PD_UI7_API void ReMenu::Update() {
HandleFocus();
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
HandleTitlebarActions();
}
DrawBaseLayout();
pLayout->Update();
}
} // namespace UI7
} // namespace PD

View File

@ -1,69 +1,69 @@
/*
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/core/color.hpp>
#include <pd/ui7/theme.hpp>
namespace PD {
namespace UI7 {
void Theme::Default(Theme& theme) {
theme.Set(UI7Color_Text, Color("#FFFFFFFF"));
theme.Set(UI7Color_TextDead, Color("#AAAAAAFF"));
theme.Set(UI7Color_Background, Color("#222222ff"));
theme.Set(UI7Color_Border, Color("#999999ff"));
theme.Set(UI7Color_Button, Color("#111111FF"));
theme.Set(UI7Color_ButtonDead, Color("#080808FF"));
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"));
theme.Set(UI7Color_FrameBackgroundHovered, Color("#777777FF"));
theme.Set(UI7Color_Progressbar, Color("#00FF00FF"));
theme.Set(UI7Color_ListEven, Color("#CCCCCCFF"));
theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF"));
}
void Theme::Flashbang(Theme& theme) {
theme.Set(UI7Color_Text, Color("#000000FF"));
theme.Set(UI7Color_TextDead, Color("#333333FF"));
theme.Set(UI7Color_Background, Color("#eeeeeeFF"));
theme.Set(UI7Color_Border, Color("#777777ff"));
theme.Set(UI7Color_Button, Color("#ccccccFF"));
theme.Set(UI7Color_ButtonDead, Color("#bbbbbbFF"));
theme.Set(UI7Color_ButtonActive, Color("#ccccccFF"));
theme.Set(UI7Color_ButtonHovered, Color("#acacacFF"));
theme.Set(UI7Color_Header, Color("#ddddddFF"));
theme.Set(UI7Color_HeaderDead, Color("#cdcdcdFF"));
theme.Set(UI7Color_Selector, Color("#222222FF"));
theme.Set(UI7Color_Checkmark, Color("#ccccccFF"));
theme.Set(UI7Color_FrameBackground, Color("#aaaaaaFF"));
theme.Set(UI7Color_FrameBackgroundHovered, Color("#909090FF"));
theme.Set(UI7Color_Progressbar, Color("#00FF00FF"));
theme.Set(UI7Color_ListEven, Color("#CCCCCCFF"));
theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF"));
}
} // namespace UI7
/*
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/core/core.hpp>
#include <pd/ui7/theme.hpp>
namespace PD {
namespace UI7 {
PD_UI7_API void Theme::Default(Theme& theme) {
theme.Set(UI7Color_Text, Color("#FFFFFFFF"));
theme.Set(UI7Color_TextDead, Color("#AAAAAAFF"));
theme.Set(UI7Color_Background, Color("#222222ff"));
theme.Set(UI7Color_Border, Color("#999999ff"));
theme.Set(UI7Color_Button, Color("#111111FF"));
theme.Set(UI7Color_ButtonDead, Color("#080808FF"));
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"));
theme.Set(UI7Color_FrameBackgroundHovered, Color("#777777FF"));
theme.Set(UI7Color_Progressbar, Color("#00FF00FF"));
theme.Set(UI7Color_ListEven, Color("#CCCCCCFF"));
theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF"));
}
PD_UI7_API void Theme::Flashbang(Theme& theme) {
theme.Set(UI7Color_Text, Color("#000000FF"));
theme.Set(UI7Color_TextDead, Color("#333333FF"));
theme.Set(UI7Color_Background, Color("#eeeeeeFF"));
theme.Set(UI7Color_Border, Color("#777777ff"));
theme.Set(UI7Color_Button, Color("#ccccccFF"));
theme.Set(UI7Color_ButtonDead, Color("#bbbbbbFF"));
theme.Set(UI7Color_ButtonActive, Color("#ccccccFF"));
theme.Set(UI7Color_ButtonHovered, Color("#acacacFF"));
theme.Set(UI7Color_Header, Color("#ddddddFF"));
theme.Set(UI7Color_HeaderDead, Color("#cdcdcdFF"));
theme.Set(UI7Color_Selector, Color("#222222FF"));
theme.Set(UI7Color_Checkmark, Color("#ccccccFF"));
theme.Set(UI7Color_FrameBackground, Color("#aaaaaaFF"));
theme.Set(UI7Color_FrameBackgroundHovered, Color("#909090FF"));
theme.Set(UI7Color_Progressbar, Color("#00FF00FF"));
theme.Set(UI7Color_ListEven, Color("#CCCCCCFF"));
theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF"));
}
} // namespace UI7
} // namespace PD

View File

@ -1,300 +1,367 @@
/*
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/core/timetrace.hpp>
#include <pd/ui7/ui7.hpp>
// Helpers
#define UI7DV4(x) \
std::format("{}: [{:.2f}, {:.2f}, {:.2f}, {:.2f}]", #x, x[0], x[1], x[2], \
x[3])
#define UI7DV4N(x) \
std::format("[{:.2f}, {:.2f}, {:.2f}, {:.2f}]", x[0], x[1], x[2], x[3])
#define UI7DV2(x) std::format("{}: [{:.2f}, {:.2f}]", #x, x[0], x[1])
#define UI7DV2N(x) std::format("[{:.2f}, {:.2f}]", x[0], x[1])
#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x)
#define UI7DTF(x) PD::Strings::FormatNanos(x)
namespace PD {
std::string UI7::GetVersion(bool show_build) {
std::stringstream s;
s << ((UI7_VERSION >> 24) & 0xFF) << ".";
s << ((UI7_VERSION >> 16) & 0xFF) << ".";
s << ((UI7_VERSION >> 8) & 0xFF);
if (show_build) s << "-" << ((UI7_VERSION) & 0xFF);
return s.str();
}
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);
this->menus[id]->Layout->SetSize(io->Ren->GetViewport().zw());
menu = this->menus.find(id);
}
this->current = menu->second;
this->current->is_shown = show;
this->io->CurrentMenu = this->current->id;
io->RegisterDrawList(id, this->current->Layout->GetDrawList());
this->current->PreHandler(flags);
amenus.push_back(this->current->GetID());
if (!this->current->is_open) {
this->current = nullptr;
}
return this->current != nullptr;
}
UI7::Menu::Ref UI7::Context::GetCurrentMenu() {
Assert(current != nullptr, "Not in a Menu!");
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;
this->io->CurrentMenu = 0;
}
void UI7::Context::Update(float) {
TT::Scope st("UI7_Update");
Assert(current == nullptr, "Still in a Menu!");
bool focused_exist = false;
for (auto it : amenus) {
auto m = menus[it];
io->CurrentMenu = m->id;
m->Update(io->Delta);
io->CurrentMenu = 0;
if (it == io->FocusedMenu) {
focused_exist = true;
}
}
if (!focused_exist) {
io->FocusedMenu = 0;
io->FocusedMenuRect = 0;
}
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 * 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(bool* show) {
if (this->BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
auto m = this->GetCurrentMenu();
m->Label("Palladium - UI7 " + GetVersion());
m->Separator();
m->Label("(c) 2023-2025 René Amthor");
m->Label("UI7 is licensed under the MIT License.");
m->Label("See LICENSE for more information.");
static bool show_build;
m->Checkbox("Show Build Info", show_build);
if (show_build) {
m->SeparatorText("Build Info");
m->Label("Full Version -> " + GetVersion(true));
m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t)));
m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(LI::Vertex)));
m->Label("__cplusplus -> " + std::to_string(__cplusplus));
m->Label("Compiler -> " + LibInfo::CompiledWith());
}
this->EndMenu();
}
}
void UI7::Context::MetricsMenu(bool* show) {
if (this->BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
auto m = this->GetCurrentMenu();
m->Label("Palladium - UI7 " + GetVersion());
m->Separator();
m->Label(
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()));
if (m->BeginTreeNode("Font")) {
for (u32 i = 0; i <= 0x00ff; i++) {
auto& c = io->Ren->Font()->GetCodepoint(i);
if (!c.invalid()) {
m->Image(c.tex(), c.size(), c.uv());
if ((i % 15) != 0 || i == 0) {
m->SameLine();
}
}
}
m->EndTreeNode();
}
m->SeparatorText("TimeTrace");
if (m->BeginTreeNode("Traces (" +
std::to_string(Sys::GetTraceMap().size()) + ")")) {
for (auto& it : Sys::GetTraceMap()) {
if (m->BeginTreeNode(it.second->GetID())) {
m->Label("Diff: " + UI7DTF(it.second->GetLastDiff()));
m->Label("Protocol Len: " +
std::to_string(it.second->GetProtocol()->GetLen()));
m->Label("Average: " +
UI7DTF(it.second->GetProtocol()->GetAverage()));
m->Label("Min: " + UI7DTF(it.second->GetProtocol()->GetMin()));
m->Label("Max: " + UI7DTF(it.second->GetProtocol()->GetMax()));
m->EndTreeNode();
}
}
m->EndTreeNode();
}
m->SeparatorText("IO");
if (m->BeginTreeNode("Menus (" + std::to_string(menus.size()) + ")")) {
for (auto& it : menus) {
if (m->BeginTreeNode(it.second->name)) {
m->Label("Name: " + it.second->name);
m->Label("Pos: " + UI7DV2N(it.second->Layout->GetPosition()));
m->Label("Size: " + UI7DV2N(it.second->Layout->GetSize()));
m->Label("Work Rect: " + UI7DV4N(it.second->Layout->WorkRect));
m->Label("Cursor: " + UI7DV2N(it.second->Layout->Cursor));
if (m->BeginTreeNode(
"ID Objects (" +
std::to_string(it.second->Layout->IDObjects.size()) + ")")) {
for (auto& jt : it.second->Layout->IDObjects) {
m->Label(UI7DHX32(jt->GetID()));
}
m->EndTreeNode();
}
m->EndTreeNode();
}
}
m->EndTreeNode();
}
if (m->BeginTreeNode("DrawLists (" +
std::to_string(io->DrawListRegestry.size()) + ")")) {
for (auto& it : io->DrawListRegestry) {
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));
m->Label(UI7DV2(io->DragSourcePos));
m->Label(UI7DV2(io->DragPosition));
m->Label(UI7DV2(io->DragLastPosition));
this->EndMenu();
}
}
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");
m->Separator();
m->DragData("MenuPadding", (float*)&io->MenuPadding, 2, 0.f, 100.f);
m->DragData("FramePadding", (float*)&io->FramePadding, 2, 0.f, 100.f);
m->DragData("ItemSpace", (float*)&io->ItemSpace, 2, 0.f, 100.f);
m->DragData("MinSliderSize", (float*)&io->MinSliderDragSize, 2, 1.f, 100.f);
m->DragData("OverScroll Modifier", &io->OverScrollMod, 1, 0.01f,
std::numeric_limits<float>::max(), 0.01f, 2);
m->Checkbox("Menu Border", io->ShowMenuBorder);
m->Checkbox("Frame Border", io->ShowFrameBorder);
m->SeparatorText("Theme");
if (m->Button("Dark")) {
UI7::Theme::Default(*io->Theme.get());
}
m->SameLine();
if (m->Button("Flashbang")) {
UI7::Theme::Flashbang(*io->Theme.get());
}
/// Small trick to print without prefix
#define ts(x) m->ColorEdit(std::string(#x).substr(9), &io->Theme->GetRef(x));
#define ts2(x) \
m->DragData(std::string(#x).substr(9), (u8*)&io->Theme->GetRef(x), 4, (u8)0, \
(u8)255);
ts2(UI7Color_Background);
ts2(UI7Color_Border);
ts2(UI7Color_Button);
ts2(UI7Color_ButtonDead);
ts2(UI7Color_ButtonActive);
ts2(UI7Color_ButtonHovered);
ts2(UI7Color_Text);
ts2(UI7Color_TextDead);
ts2(UI7Color_Header);
ts2(UI7Color_HeaderDead);
ts2(UI7Color_Selector);
ts2(UI7Color_Checkmark);
ts2(UI7Color_FrameBackground);
ts2(UI7Color_FrameBackgroundHovered);
ts2(UI7Color_Progressbar);
ts2(UI7Color_ListEven);
ts2(UI7Color_ListOdd);
this->EndMenu();
}
}
/*
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/core/core.hpp>
#include <pd/ui7/ui7.hpp>
// Helpers
std::string _UI7DV4(PD::vec4<float> v) {
return std::format("[{:.2f}, {:.2f}, {:.2f}, {:.2f}]", v.x, v.y, v.z, v.w);
}
std::string _UI7DV2(PD::vec2<float> v) {
return std::format("[{:.2f}, {:.2f}]", v.x, v.y);
}
#define UI7DV4(x) #x ": " + _UI7DV4(x)
#define UI7DV4N(x) _UI7DV4(x)
#define UI7DV2(x) #x ": " + _UI7DV2(x)
#define UI7DV2N(x) _UI7DV2(x)
#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x)
#define UI7DTF(x) PD::Strings::FormatNanos(x)
namespace PD {
PD_UI7_API std::string UI7::GetVersion(bool show_build) {
std::stringstream s;
s << ((UI7_VERSION >> 24) & 0xFF) << ".";
s << ((UI7_VERSION >> 16) & 0xFF) << ".";
s << ((UI7_VERSION >> 8) & 0xFF);
if (show_build) s << "-" << ((UI7_VERSION) & 0xFF);
return s.str();
}
PD_UI7_API 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->InputHandler->FocusedMenu == id) {
io->InputHandler->FocusedMenu = 0;
io->InputHandler->FocusedMenuRect = 0;
}
return false;
}
}
auto menu = this->menus.find(id);
if (menu == this->menus.end()) {
this->menus[id] = Menu::New(id, io);
// this->menus[id]->Layout->SetSize(io->Ren->GetViewport().zw());
menu = this->menus.find(id);
}
this->current = menu->second;
this->current->is_shown = show;
this->io->InputHandler->CurrentMenu = this->current->id;
io->RegisterDrawList(id, this->current->Layout->GetDrawList());
this->current->PreHandler(flags);
amenus.push_back(this->current->GetID());
if (!this->current->is_open) {
this->current = nullptr;
}
return this->current != nullptr;
}
PD_UI7_API UI7::Menu::Ref UI7::Context::GetCurrentMenu() {
// Assert(current != nullptr, "Not in a Menu!");
return current;
}
PD_UI7_API 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;
}
PD_UI7_API void UI7::Context::EndMenu() {
this->current->PostHandler();
this->current = nullptr;
this->io->InputHandler->CurrentMenu = 0;
}
PD_UI7_API bool UI7::Context::DoMenuEx(
const UI7::ID& id, UI7MenuFlags flags,
std::function<void(UI7::ReMenu::Ref m)> f) {
if (!Current) {
Current = ReMenu::New(id, io);
}
// Current->pIsShown = show;
io->InputHandler->CurrentMenu = Current->pID;
io->RegisterDrawList(id, Current->pLayout->GetDrawList());
if (Current->pIsOpen) {
f(Current);
}
return Current != nullptr;
}
PD_UI7_API void UI7::Context::Update(float) {
TT::Scope st("UI7_Update");
// Assert(current == nullptr, "Still in a Menu!");
if (!io->InputHandler->FocusedMenu && amenus.size() > 0) {
io->InputHandler->FocusedMenu = amenus[amenus.size() - 1];
}
bool focused_exist = false;
if (aml.size() == 0) {
aml = amenus;
} else {
std::vector<size_t> tbr;
for (size_t i = 0; i < aml.size(); i++) {
if (std::find(amenus.begin(), amenus.end(), aml[i]) == amenus.end()) {
tbr.push_back(i);
}
}
for (auto& it : tbr) {
aml.erase(aml.begin() + it);
}
}
for (auto& it : amenus) {
if (std::find(aml.begin(), aml.end(), it) == aml.end()) {
aml.push_back(it);
}
}
auto ptf = std::find(aml.begin(), aml.end(), io->InputHandler->FocusedMenu);
if (ptf != aml.end() && ptf != aml.begin()) {
std::rotate(aml.begin(), ptf, ptf + 1);
}
for (auto it : aml) {
auto m = menus[it];
io->InputHandler->CurrentMenu = m->id;
m->Update(io->Delta);
io->InputHandler->CurrentMenu = 0;
if (it == io->InputHandler->FocusedMenu) {
focused_exist = true;
}
}
io->InputHandler->CurrentMenu = Current->pID;
Current->Update();
/*if (!focused_exist && io->CurrentMenu != Current->pID) {
io->FocusedMenu = 0;
io->FocusedMenuRect = 0;
}*/
int list = 0;
u32 vtx_counter = 0;
u32 idx_counter = 0;
// Register Front List as last element
io->RegisterDrawList("CtxFrontList", io->Front);
// io->DrawListRegestry.Reverse();
for (auto it : io->DrawListRegestry) {
it.Second->Base = list * 30;
it.Second->Process(io->pRDL);
vtx_counter += it.Second->NumVertices;
idx_counter += it.Second->NumIndices;
list++;
}
io->Ren->RegisterDrawList(io->pRDL);
io->NumIndices = idx_counter;
io->NumVertices = vtx_counter;
this->amenus.clear();
this->io->Update();
}
PD_UI7_API void UI7::Context::AboutMenu(bool* show) {
if (this->BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
auto m = this->GetCurrentMenu();
m->Label("Palladium - UI7 " + GetVersion());
m->Separator();
m->Label("(c) 2023-2025 René Amthor");
m->Label("UI7 is licensed under the MIT License.");
m->Label("See LICENSE for more information.");
static bool show_build;
m->Checkbox("Show Build Info", show_build);
if (show_build) {
m->SeparatorText("Build Info");
m->Label("Full Version -> " + GetVersion(true));
m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t)));
m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(LI::Vertex)));
m->Label("__cplusplus -> " + std::to_string(__cplusplus));
m->Label("Compiler -> " + LibInfo::CompiledWith());
}
this->EndMenu();
}
}
PD_UI7_API void UI7::Context::MetricsMenu(bool* show) {
if (this->BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
auto m = this->GetCurrentMenu();
m->Label("Palladium - UI7 " + GetVersion());
m->Separator();
m->Label(
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()));
/*if (m->BeginTreeNode("Font")) {
for (u32 i = 0; i <= 0x00ff; i++) {
auto& c = io->Ren->Font()->GetCodepoint(i);
if (!c.invalid()) {
m->Image(c.tex(), c.size(), c.uv());
if ((i % 15) != 0 || i == 0) {
m->SameLine();
}
}
}
m->EndTreeNode();
}*/
m->SeparatorText("TimeTrace");
if (m->BeginTreeNode("Traces (" +
std::to_string(Sys::GetTraceMap().size()) + ")")) {
for (auto& it : Sys::GetTraceMap()) {
if (m->BeginTreeNode(it.second->GetID())) {
m->Label("Diff: " + UI7DTF(it.second->GetLastDiff()));
m->Label("Protocol Len: " +
std::to_string(it.second->GetProtocol()->GetLen()));
m->Label("Average: " +
UI7DTF(it.second->GetProtocol()->GetAverage()));
m->Label("Min: " + UI7DTF(it.second->GetProtocol()->GetMin()));
m->Label("Max: " + UI7DTF(it.second->GetProtocol()->GetMax()));
m->EndTreeNode();
}
}
m->EndTreeNode();
}
m->SeparatorText("IO");
if (m->BeginTreeNode("Menus (" + std::to_string(menus.size()) + ")")) {
for (auto& it : menus) {
if (m->BeginTreeNode(it.second->name)) {
m->Label("Name: " + it.second->name);
/*m->Label("Pos: " + UI7DV2N(it.second->Layout->GetPosition()));
m->Label("Size: " + UI7DV2N(it.second->Layout->GetSize()));
m->Label("Work Rect: " + UI7DV4N(it.second->Layout->WorkRect));
m->Label("Cursor: " + UI7DV2N(it.second->Layout->Cursor));*/
if (m->BeginTreeNode(
"ID Objects (" +
std::to_string(it.second->Layout->IDObjects.size()) + ")")) {
for (auto& jt : it.second->Layout->IDObjects) {
m->Label(UI7DHX32(jt->GetID()));
}
m->EndTreeNode();
}
m->EndTreeNode();
}
}
m->EndTreeNode();
}
if (m->BeginTreeNode("Active Menus (" + std::to_string(aml.size()) + ")")) {
for (auto& it : aml) {
if (m->BeginTreeNode(menus[it]->name)) {
m->Label("Name: " + menus[it]->name);
/*m->Label("Pos: " + UI7DV2N(it.second->Layout->Pos));
m->Label("Size: " + UI7DV2N(it.second->Layout->GetSize()));
m->Label("Work Rect: " + UI7DV4N(it.second->Layout->WorkRect));
m->Label("Cursor: " + UI7DV2N(it.second->Layout->Cursor));*/
if (m->BeginTreeNode(
"ID Objects (" +
std::to_string(menus[it]->Layout->IDObjects.size()) + ")")) {
for (auto& jt : menus[it]->Layout->IDObjects) {
m->Label(UI7DHX32(jt->GetID()));
}
m->EndTreeNode();
}
m->EndTreeNode();
}
}
m->EndTreeNode();
}
if (m->BeginTreeNode("DrawLists (" +
std::to_string(io->DrawListRegestry.Size()) + ")")) {
for (auto& it : io->DrawListRegestry) {
if (m->BeginTreeNode(it.First.GetName())) {
m->Label("Vertices: " + std::to_string(it.Second->NumVertices));
m->Label("Indices: " + std::to_string(it.Second->NumIndices));
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->InputHandler->FocusedMenu));
m->Label(UI7DHX32(io->InputHandler->DraggedObject));
m->Label(std::format("io->DragTime: {:.2f}s",
io->InputHandler->DragTime->GetSeconds()));
m->Label(UI7DV4(io->InputHandler->DragDestination));
m->Label(UI7DV2(io->InputHandler->DragSourcePos));
m->Label(UI7DV2(io->InputHandler->DragPosition));
m->Label(UI7DV2(io->InputHandler->DragLastPosition));
this->EndMenu();
}
}
PD_UI7_API 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");
m->Separator();
m->DragData("MenuPadding", (float*)&io->MenuPadding, 2, 0.f, 100.f);
m->DragData("FramePadding", (float*)&io->FramePadding, 2, 0.f, 100.f);
m->DragData("ItemSpace", (float*)&io->ItemSpace, 2, 0.f, 100.f);
m->DragData("MinSliderSize", (float*)&io->MinSliderDragSize, 2, 1.f, 100.f);
m->DragData("OverScroll Modifier", &io->OverScrollMod, 1, 0.01f,
std::numeric_limits<float>::max(), 0.01f, 2);
m->Checkbox("Menu Border", io->ShowMenuBorder);
m->Checkbox("Frame Border", io->ShowFrameBorder);
m->SeparatorText("Theme");
if (m->Button("Dark")) {
UI7::Theme::Default(*io->Theme.get());
}
m->SameLine();
if (m->Button("Flashbang")) {
UI7::Theme::Flashbang(*io->Theme.get());
}
/// Small trick to print without prefix
#define ts(x) m->ColorEdit(std::string(#x).substr(9), &io->Theme->GetRef(x));
#define ts2(x) \
m->DragData(std::string(#x).substr(9), (u8*)&io->Theme->GetRef(x), 4, (u8)0, \
(u8)255);
ts2(UI7Color_Background);
ts2(UI7Color_Border);
ts2(UI7Color_Button);
ts2(UI7Color_ButtonDead);
ts2(UI7Color_ButtonActive);
ts2(UI7Color_ButtonHovered);
ts2(UI7Color_Text);
ts2(UI7Color_TextDead);
ts2(UI7Color_Header);
ts2(UI7Color_HeaderDead);
ts2(UI7Color_Selector);
ts2(UI7Color_Checkmark);
ts2(UI7Color_FrameBackground);
ts2(UI7Color_FrameBackgroundHovered);
ts2(UI7Color_Progressbar);
ts2(UI7Color_ListEven);
ts2(UI7Color_ListOdd);
this->EndMenu();
}
}
} // namespace PD