Files
palladium/include/pd/ui7/menu.hpp
T

291 lines
9.1 KiB
C++
Raw Normal View History

2025-01-19 20:16:43 +01:00
#pragma once
/*
MIT License
2025-02-04 21:44:27 +01:00
Copyright (c) 2024 - 2025 René Amthor (tobid7)
2025-01-19 20:16:43 +01:00
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.
*/
2025-02-22 00:23:48 +01:00
#include <pd/drivers/hid.hpp>
#include <pd/core/tween.hpp>
2025-02-02 20:32:07 +01:00
#include <pd/ui7/containers.hpp>
2025-01-19 20:16:43 +01:00
#include <pd/ui7/drawlist.hpp>
2025-01-29 03:14:29 +01:00
#include <pd/ui7/flags.hpp>
#include <pd/ui7/id.hpp>
2025-01-19 20:16:43 +01:00
namespace PD {
namespace UI7 {
class Menu : public SmartCtor<Menu> {
public:
2025-02-28 19:49:24 +01:00
Menu(ID id, Theme::Ref tl, Hid::Ref h) {
theme = tl;
2025-01-29 03:14:29 +01:00
this->inp = h;
2025-01-19 20:16:43 +01:00
this->id = id;
2025-01-29 03:14:29 +01:00
this->name = id.GetName();
2025-01-19 20:16:43 +01:00
scrolling[0] = false;
scrolling[1] = false;
scrollbar[0] = false;
scrollbar[1] = false;
scroll_allowed[0] = false;
scroll_allowed[1] = false;
};
2025-01-29 03:14:29 +01:00
~Menu() {}
2025-02-28 19:49:24 +01:00
/// Objects ///
/// @brief Render a Simple Label
/// @param label The text to draw
2025-01-29 03:14:29 +01:00
void Label(const std::string& label);
2025-02-28 19:49:24 +01:00
/// @brief Render a Button
/// @param label The buttons text
/// @return if the button was pressed
2025-01-29 03:14:29 +01:00
bool Button(const std::string& label);
2025-02-28 19:49:24 +01:00
/// @brief Render a Checkbox
/// @param label Label of the Checkbox
/// @param v A value to update
2025-01-29 03:14:29 +01:00
void Checkbox(const std::string& label, bool& v);
2025-02-28 19:49:24 +01:00
/// @brief Render an Image
/// @param img Texture reference of the image
/// @param size a Custom Size if needed
2025-01-29 03:14:29 +01:00
void Image(Texture::Ref img, vec2 size = 0.f);
2025-02-28 19:49:24 +01:00
/// Basic API ///
/// @brief Add the Next object to the same line
2025-01-29 03:14:29 +01:00
void SameLine();
2025-02-28 19:49:24 +01:00
/// @brief Add a Separator Line
2025-01-29 03:14:29 +01:00
void Separator();
2025-02-28 19:49:24 +01:00
/// @brief Render a Separator Line with a Text
/// @todo determinate text position by current alignment
/// @param label The Text to show
2025-01-29 03:14:29 +01:00
void SeparatorText(const std::string& label);
2025-02-28 19:49:24 +01:00
/// @brief Put the last Added Object into the Joinlist
2025-02-02 20:32:07 +01:00
void Join();
2025-02-28 19:49:24 +01:00
/// @brief Add the Last element to the join list
/// and perform an alignment operation
/// @param a Alignment Oeration(s)
2025-02-17 22:20:30 +01:00
void JoinAlign(UI7Align a);
2025-02-28 19:49:24 +01:00
/// @brief Align the Last Object
/// @param a Alignment Operation
2025-02-17 22:20:30 +01:00
void AfterAlign(UI7Align a);
2025-02-28 19:49:24 +01:00
/// @brief Set a Temp alignment op for the next Object
/// @param a Alignment Operation
2025-02-17 22:20:30 +01:00
void NextAlign(UI7Align a) { tmpalign = a; }
2025-02-28 19:49:24 +01:00
/// @brief Align Every Single Object by this operationset
/// @param a Alignment
2025-02-17 22:20:30 +01:00
void PushAlignment(UI7Align a) { alignment = a; }
2025-02-28 19:49:24 +01:00
/// @brief Use default alignment
2025-02-17 22:20:30 +01:00
void PopAlignment() { alignment = UI7Align_Default; }
2025-02-28 19:49:24 +01:00
/// @brief Get a New Position depending on the Alignment
/// @param pos Current Position
/// @param size Object size
/// @param view Viewport [position and size]
/// @param a Alignment Operations
/// @return new position based on the alignment
2025-02-17 22:20:30 +01:00
static vec2 AlignPos(vec2 pos, vec2 size, vec4 view, UI7Align a);
2025-02-28 19:49:24 +01:00
/// @brief Returns a Reference to the theme
/// @return Reference to the base Theme of the context
Theme::Ref GetTheme() { return theme; }
/// @brief Directly return a Color by using the
/// m->ThemeColor(UI7Color_Text) for example
/// @param clr The Input UI7 Color
/// @return The 32bit color value
u32 ThemeColor(UI7Color clr) const { return theme->Get(clr); }
2025-01-29 03:14:29 +01:00
/// API for Custom Objects
2025-02-28 19:49:24 +01:00
/// @brief Handles the Position of Objects in Scrolling Menu
/// @note As Containers have their own FUnc to handle this, this
/// function is only useful to Render Live Objects whicch cannot be aligned
/// by the internal Alignment Api
/// @param pos position reference to write the new position to
/// @param size size of the Object
/// @return if the object can be skipped in rendering
2025-01-29 03:14:29 +01:00
bool HandleScrolling(vec2& pos, const vec2& size);
2025-02-28 19:49:24 +01:00
/// @brief Get the Cursor Position
/// @return Cursor Pos
2025-01-29 03:14:29 +01:00
vec2 Cursor() const { return cursor; }
2025-02-28 19:49:24 +01:00
/// @brief Set the Cursor position
/// @note The old Position can be restored with RestoreCursor
/// @param v New Position
2025-01-29 03:14:29 +01:00
void Cursor(const vec2& v) {
bcursor = cursor;
cursor = v;
}
2025-02-28 19:49:24 +01:00
/// @brief Restore to the last cursor Position
2025-01-29 03:14:29 +01:00
void RestoreCursor() {
cursor = bcursor;
bcursor = vec2();
}
2025-02-28 19:49:24 +01:00
/// @brief Return if a Vertical Scrollbar exists
2025-02-09 21:40:31 +01:00
bool HasVerticalScrollbar() { return scrollbar[1]; }
2025-02-28 19:49:24 +01:00
/// @brief Return if a Horizontal Scrollbar exists
2025-02-09 21:40:31 +01:00
bool HasHorizontalScrollbar() { return scrollbar[0]; }
2025-02-28 19:49:24 +01:00
/// @brief Get the Titlebar height
2025-02-09 21:40:31 +01:00
float TitleBarHeight() { return tbh; }
/// @brief Set a Custom Titlebar heigt
/// @note Could destroy some basic functionality
void TitleBarHeight(float v) { tbh = v; }
/// @brief Init the Cursor
/// @note Useful when using with a Custom TitlebarHeight
void CursorInit() { Cursor(vec2(5, tbh + 5)); }
2025-02-28 19:49:24 +01:00
/// @brief Move the Cursor for new Object
/// @param szs Size of the current Object
2025-02-09 21:40:31 +01:00
void CursorMove(const vec2& szs);
2025-02-28 19:49:24 +01:00
/// @brief Get the ViewArea of the Menu
2025-02-09 21:40:31 +01:00
vec4 ViewArea() const { return view_area; }
2025-02-28 19:49:24 +01:00
/// @brief Get the Main Area of the Menu
/// (only relevant for input)
2025-02-09 21:40:31 +01:00
vec4 MainArea() const { return main_area; }
2025-02-28 19:49:24 +01:00
/// @brief Set a MainArea for input
/// @param v Area where Objects can receive inputs
2025-02-09 21:40:31 +01:00
void MainArea(const vec4& v) { main_area = v; }
2025-02-28 19:49:24 +01:00
/// @brief Get The Scrolling offset
2025-02-09 21:40:31 +01:00
vec2 ScrollOffset() const { return scrolling_off; }
2025-02-28 19:49:24 +01:00
/// @brief Set a Scrolling offset
/// @param v Custom Scrolling offset
2025-02-17 22:20:30 +01:00
void ScrollOffset(const vec2& v) { scrolling_off = v; }
2025-02-28 19:49:24 +01:00
/// @brief Get the Current Scrollmodification value
2025-02-17 22:20:30 +01:00
vec2 ScrollMod() const { return scroll_mod; }
2025-02-28 19:49:24 +01:00
/// @brief Animated Scroll to Position
/// @param pos Destination Position
2025-02-09 21:40:31 +01:00
void ScrollTo(vec2 pos) {
scroll_anim.From(scrolling_off)
.To(pos)
.In(1.f)
.As(scroll_anim.EaseInOutSine);
}
2025-02-28 19:49:24 +01:00
/// @brief Check if Still in ScrollAnimation
2025-02-17 22:20:30 +01:00
bool IsAnimatedScroll() { return !scroll_anim.IsFinished(); }
2025-02-09 21:40:31 +01:00
2025-02-28 19:49:24 +01:00
/// Objects API ///
/// @brief Push an object to the current ListHandler
/// @param obj Object reference to use
/// @return Reference to the Object (from a time
/// where ObjectPush(Container::New()) was used)
2025-02-09 21:40:31 +01:00
Container::Ref ObjectPush(Container::Ref obj);
2025-02-28 19:49:24 +01:00
/// @brief Search for an Object by an id
/// @param id 32 Bit hash/id
/// @return the found Object or nullptr
2025-02-09 21:40:31 +01:00
Container::Ref FindIDObj(u32 id);
2025-01-29 03:14:29 +01:00
2025-02-28 19:49:24 +01:00
/// Draw Lists ///
/// @brief Background Layer Drawlist
2025-01-29 03:14:29 +01:00
DrawList::Ref BackList() { return back; }
2025-02-28 19:49:24 +01:00
/// @brief Setter for Background Layer Drawlist
2025-01-29 03:14:29 +01:00
void BackList(DrawList::Ref v) { back = v; }
2025-02-28 19:49:24 +01:00
/// @brief Main Layer Drawlist
2025-01-29 03:14:29 +01:00
DrawList::Ref MainList() { return main; }
2025-02-28 19:49:24 +01:00
/// @brief Setter for Main Layer Drawlist
2025-01-29 03:14:29 +01:00
void MainList(DrawList::Ref v) { main = v; }
2025-02-28 19:49:24 +01:00
/// @brief Foreground Layer Drawlist
2025-01-29 03:14:29 +01:00
DrawList::Ref FrontList() { return front; }
2025-02-28 19:49:24 +01:00
/// @brief Setter for Foreground Layer Drawlist
2025-01-29 03:14:29 +01:00
void FrontList(DrawList::Ref v) { front = v; }
2025-02-28 19:49:24 +01:00
/// Advanced ///
/// @brief Display Debug Labels of the Menu
2025-01-29 03:14:29 +01:00
void DebugLabels();
2025-02-28 19:49:24 +01:00
/// Uneditable Stuff ///
/// @brief Menu Name
2025-01-29 03:14:29 +01:00
std::string GetName() const { return name; }
2025-02-28 19:49:24 +01:00
/// @brief Menu ID [Hash of the Name]
2025-01-29 03:14:29 +01:00
u32 GetID() const { return id; }
2025-01-19 20:16:43 +01:00
private:
2025-01-29 03:14:29 +01:00
/// Advanced Handlers
void PreHandler(UI7MenuFlags flags);
void PostHandler();
/// Basic Settings
void BackupCursor(const vec2& v) { bcursor = v; }
vec2 SameLineCursor() const { return slcursor; }
void SameLineCursor(const vec2& v) { slcursor = v; }
void ViewArea(const vec4& v) { view_area = v; }
void ScrollMod(const vec2& v) { scroll_mod = v; }
2025-02-17 22:20:30 +01:00
UI7Align GetAlignment() {
if (tmpalign) {
auto t = tmpalign;
tmpalign = 0;
return t;
}
return alignment;
}
2025-01-29 03:14:29 +01:00
/// Internal Processing
void Update(float delta);
/// This ability is crazy useful
friend class Context;
/// Data
2025-02-17 22:20:30 +01:00
UI7Align alignment = UI7Align_Default;
UI7Align tmpalign = 0;
2025-01-29 03:14:29 +01:00
UI7MenuFlags flags = 0;
2025-01-19 20:16:43 +01:00
u32 id;
2025-01-29 03:14:29 +01:00
std::string name;
2025-01-19 20:16:43 +01:00
vec2 cursor;
vec2 bcursor;
vec2 slcursor;
vec4 view_area;
2025-02-09 21:40:31 +01:00
vec4 main_area;
2025-01-19 20:16:43 +01:00
vec2 scrolling_off;
bool scrolling[2];
vec2 scroll_mod;
float tbh;
bool scrollbar[2];
bool scroll_allowed[2];
bool has_touch;
2025-02-28 19:49:24 +01:00
Container::Ref tmp_parent;
2025-01-19 20:16:43 +01:00
2025-02-02 20:32:07 +01:00
/// Objects API
std::vector<Container::Ref> objects;
std::vector<Container::Ref> idobjs;
std::vector<Container*> join;
2025-02-03 16:15:37 +01:00
int count_btn = 0;
int count_cbx = 0;
2025-02-02 20:32:07 +01:00
2025-01-19 20:16:43 +01:00
// DrawLists
DrawList::Ref back;
DrawList::Ref main;
DrawList::Ref front;
vec2 max;
vec2 mouse;
vec2 bslpos;
vec2 last_size;
2025-01-29 03:14:29 +01:00
// Theme
2025-02-28 19:49:24 +01:00
Theme::Ref theme;
2025-01-29 03:14:29 +01:00
// Input Reference
Hid::Ref inp;
2025-02-09 21:40:31 +01:00
// Animations System
Tween<vec2> scroll_anim;
2025-01-19 20:16:43 +01:00
};
} // namespace UI7
} // namespace PD