Compare commits
3 Commits
stable
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
dbffb7f316 | |||
6738fda55c | |||
35272687f6 |
@ -52,7 +52,7 @@ execute_process(
|
||||
)
|
||||
|
||||
# Set Project
|
||||
project(palladium LANGUAGES C CXX VERSION 0.3.0)
|
||||
project(palladium LANGUAGES C CXX VERSION 0.3.2)
|
||||
|
||||
option(PD_BUILD_TESTS "Sets if TestApp and TestBench get build" OFF)
|
||||
|
||||
@ -131,6 +131,7 @@ source/app/error.cpp)
|
||||
set(UI7_SRC
|
||||
source/ui7/drawlist.cpp
|
||||
source/ui7/io.cpp
|
||||
source/ui7/layout.cpp
|
||||
source/ui7/menu.cpp
|
||||
source/ui7/theme.cpp
|
||||
source/ui7/ui7.cpp
|
||||
@ -138,6 +139,7 @@ source/ui7/container/container.cpp
|
||||
source/ui7/container/button.cpp
|
||||
source/ui7/container/checkbox.cpp
|
||||
source/ui7/container/coloredit.cpp
|
||||
source/ui7/container/dragdata.cpp
|
||||
source/ui7/container/image.cpp
|
||||
source/ui7/container/label.cpp)
|
||||
|
||||
|
@ -36,7 +36,7 @@ make install
|
||||
| pd-lithium | 0.2.9 | 3ds | pd-core, pd-image pd-lib3ds, citro3d |
|
||||
| pd-sound | 0.2.4 | 3ds | pd-core, mpg123 |
|
||||
| pd-overlays | 0.2.4 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium, pd-ui7 |
|
||||
| pd-ui7 | 0.2.9 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium |
|
||||
| pd-ui7 | 0.3.1 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium |
|
||||
| pd-app | 0.2.4 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium |
|
||||
|
||||
## Credits
|
||||
|
@ -54,9 +54,8 @@ class Button : public Container {
|
||||
/**
|
||||
* Override for the Input Handler
|
||||
* @note This function is usally called by Menu::Update
|
||||
* @param inp Reference to the Input Handler
|
||||
*/
|
||||
void HandleInput(Hid::Ref inp) override;
|
||||
void HandleInput() override;
|
||||
/**
|
||||
* Override for the Rendering Handler
|
||||
* @note This function is usally called by Menu::Update
|
||||
|
@ -50,9 +50,8 @@ class Checkbox : public Container {
|
||||
/**
|
||||
* Override for the Input Handler
|
||||
* @note This function is usally called by Menu::Update
|
||||
* @param inp Reference to the Input Handler
|
||||
*/
|
||||
void HandleInput(Hid::Ref inp) override;
|
||||
void HandleInput() override;
|
||||
/**
|
||||
* Override for the Rendering Handler
|
||||
* @note This function is usally called by Menu::Update
|
||||
|
@ -25,6 +25,7 @@ SOFTWARE.
|
||||
|
||||
#include <pd/ui7/container/container.hpp>
|
||||
#include <pd/ui7/io.hpp>
|
||||
#include <pd/ui7/layout.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
@ -51,9 +52,8 @@ class ColorEdit : public Container {
|
||||
/**
|
||||
* Override for the Input Handler
|
||||
* @note This function is usally called by Menu::Update
|
||||
* @param inp Reference to the Input Handler
|
||||
*/
|
||||
void HandleInput(Hid::Ref inp) override;
|
||||
void HandleInput() override;
|
||||
/**
|
||||
* Override for the Rendering Handler
|
||||
* @note This function is usally called by Menu::Update
|
||||
@ -68,6 +68,8 @@ class ColorEdit : public Container {
|
||||
u32* color_ref = nullptr; ///< Color Reference
|
||||
u32 initial_color; ///< Initial Color
|
||||
std::string label; ///< Label of the Button
|
||||
Layout::Ref layout; ///< Layout to open
|
||||
bool is_shown = false; ///< AHow Layout Editor
|
||||
};
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -103,7 +103,7 @@ class Container : public SmartCtor<Container> {
|
||||
*/
|
||||
void HandleScrolling(vec2 scrolling, vec4 viewport);
|
||||
/** Template function for Input Handling */
|
||||
virtual void HandleInput(Hid::Ref inp) {}
|
||||
virtual void HandleInput() {}
|
||||
/** Tamplate function for Object rendering */
|
||||
virtual void Draw() {}
|
||||
/** Template function to update internal data (if needed) */
|
||||
|
90
include/pd/ui7/container/dragdata.hpp
Normal file
90
include/pd/ui7/container/dragdata.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2025 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/container.hpp>
|
||||
#include <pd/ui7/io.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
/**
|
||||
* DragData Object can take a datatype or a list
|
||||
* and modifys these by moving left or right when dragging
|
||||
*/
|
||||
template <typename T>
|
||||
class DragData : public Container {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param label Label of the Button
|
||||
* @param data Data reference (Supported types can be seen in dragdata.cpp)
|
||||
* @param num_elms Number of Array elements (for exaple with use ofvec4)
|
||||
* @param io IO Reference
|
||||
* @param min minimum number using Minimum limit
|
||||
* @param max Maximum number set by max limit by default
|
||||
* @param step To set the modifier for drag movement
|
||||
* @param precision for float and double to set precision
|
||||
*/
|
||||
DragData(const std::string& label, T* data, size_t num_elms, UI7::IO::Ref io,
|
||||
T min = std::numeric_limits<T>::min(),
|
||||
T max = std::numeric_limits<T>::max(), T step = 1,
|
||||
int precision = 1) {
|
||||
PD::Assert(data != nullptr, "Input Data Address is null!");
|
||||
this->label = label;
|
||||
this->data = data;
|
||||
this->elm_count = num_elms;
|
||||
this->min = min;
|
||||
this->max = max;
|
||||
this->step = step;
|
||||
this->precision = precision;
|
||||
this->tdim = io->Ren->GetTextDimensions(label);
|
||||
}
|
||||
~DragData() = default;
|
||||
|
||||
/**
|
||||
* Override for the Input Handler
|
||||
* @note This function is usally called by Menu::Update
|
||||
*/
|
||||
void HandleInput() override;
|
||||
/**
|
||||
* Override for the Rendering Handler
|
||||
* @note This function is usally called by Menu::Update
|
||||
* */
|
||||
void Draw() override;
|
||||
|
||||
/** Function to Update Size if framepadding changes */
|
||||
void Update() override;
|
||||
|
||||
private:
|
||||
vec2 tdim; ///< Text size
|
||||
std::string label; ///< Label of the Button
|
||||
T* data;
|
||||
size_t elm_count = 0;
|
||||
T min;
|
||||
T max;
|
||||
T step;
|
||||
int precision = 1;
|
||||
};
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -26,5 +26,6 @@ SOFTWARE.
|
||||
#include <pd/ui7/container/button.hpp>
|
||||
#include <pd/ui7/container/checkbox.hpp>
|
||||
#include <pd/ui7/container/coloredit.hpp>
|
||||
#include <pd/ui7/container/dragdata.hpp>
|
||||
#include <pd/ui7/container/image.hpp>
|
||||
#include <pd/ui7/container/label.hpp>
|
@ -25,6 +25,7 @@ SOFTWARE.
|
||||
|
||||
#include <pd/core/common.hpp>
|
||||
#include <pd/lithium/renderer.hpp>
|
||||
#include <pd/ui7/flags.hpp>
|
||||
#include <pd/ui7/theme.hpp>
|
||||
|
||||
namespace PD {
|
||||
@ -39,6 +40,15 @@ class DrawList : public SmartCtor<DrawList> {
|
||||
DrawList(LI::Renderer::Ref r) { ren = r; }
|
||||
~DrawList() = default;
|
||||
|
||||
/**
|
||||
* Draw a Rectangle (LINED)
|
||||
* @param pos position of the rect
|
||||
* @param size Size of the rect
|
||||
* @param clr Color of the rect
|
||||
* @param thickness Thickness of the lines
|
||||
*/
|
||||
void AddRect(const vec2& pos, const vec2& size, const UI7Color& clr,
|
||||
int thickness = 1);
|
||||
/**
|
||||
* Render a Rectangle
|
||||
* @param pos Position
|
||||
@ -48,12 +58,43 @@ class DrawList : public SmartCtor<DrawList> {
|
||||
void AddRectangle(vec2 pos, vec2 szs, const UI7Color& clr);
|
||||
/**
|
||||
* Render a Triangle
|
||||
* @param pos0 Position a
|
||||
* @param pos1 Position b
|
||||
* @param pos2 Position c
|
||||
* @param a Position a
|
||||
* @param b Position b
|
||||
* @param c Position c
|
||||
* @param clr Color
|
||||
* @param thickness Thickness of the lines
|
||||
*/
|
||||
void AddTriangle(const vec2& a, const vec2& b, const vec2& c,
|
||||
const UI7Color& clr, int thickness = 1);
|
||||
/**
|
||||
* Render a Filled Triangle
|
||||
* @param a Position a
|
||||
* @param b Position b
|
||||
* @param c Position c
|
||||
* @param clr Color
|
||||
*/
|
||||
void AddTriangle(vec2 pos0, vec2 pos1, vec2 pos2, const UI7Color& clr);
|
||||
void AddTriangleFilled(const vec2& a, const vec2& b, const vec2& c,
|
||||
const UI7Color& clr);
|
||||
|
||||
/**
|
||||
* Add a Lined Circle
|
||||
* @param pos Center position
|
||||
* @param rad radius of the circle
|
||||
* @param col Color of the Circle
|
||||
* @param num_segments Number of Segments (0 = auto)
|
||||
* @param thickness thickness of the line
|
||||
*/
|
||||
void AddCircle(const vec2& pos, float rad, UI7Color col, int num_segments = 0,
|
||||
int thickness = 1);
|
||||
/**
|
||||
* Add a Circle
|
||||
* @param pos Center position
|
||||
* @param rad radius of the circle
|
||||
* @param col Color of the Circle
|
||||
* @param num_segments Number of Segments (0 = auto)
|
||||
*/
|
||||
void AddCircleFilled(const vec2& pos, float rad, UI7Color col,
|
||||
int num_segments = 0);
|
||||
/**
|
||||
* Render a Text
|
||||
* @param pos Position
|
||||
@ -82,6 +123,24 @@ class DrawList : public SmartCtor<DrawList> {
|
||||
*/
|
||||
void AddLine(const vec2& a, const vec2& b, const UI7Color& clr, int t = 1);
|
||||
|
||||
/**
|
||||
* Take list of points and display it as a line on screen
|
||||
* @param points List of Positions
|
||||
* @param clr Color of the Line
|
||||
* @param flags Additional Flags (Close for go back to starting point)
|
||||
* @param thickness Thickness of the Line
|
||||
*/
|
||||
void AddPolyLine(const std::vector<vec2>& points, const UI7Color& clr,
|
||||
UI7DrawFlags flags = 0, int thickness = 1);
|
||||
/**
|
||||
* Take a List ofpoints and display it as Filled Shape
|
||||
* @note Keep in mind to setup the list of points clockwise
|
||||
* @param points List of Points
|
||||
* @param clr Color of the shape
|
||||
*/
|
||||
void AddConvexPolyFilled(const std::vector<vec2>& points,
|
||||
const UI7Color& clr);
|
||||
|
||||
/** Clear the Drawlist */
|
||||
void Clear();
|
||||
/** Process [Render] the Drawlist */
|
||||
@ -98,6 +157,61 @@ class DrawList : public SmartCtor<DrawList> {
|
||||
/** Setter fot the Layer */
|
||||
void Layer(int v) { layer = v; }
|
||||
|
||||
/** Path API */
|
||||
|
||||
/**
|
||||
* Function to reserve Memory to prevent overhead on
|
||||
* pusing a lot of points with PathNext
|
||||
* @param num_points Number of Positions you want to add
|
||||
*/
|
||||
void PathReserve(size_t num_points) {
|
||||
Path.reserve(Path.size() + num_points);
|
||||
}
|
||||
/**
|
||||
* Clear current Path
|
||||
* @note PathStroke and PathFill will automatically clear
|
||||
*/
|
||||
void PathClear() { Path.clear(); }
|
||||
/**
|
||||
* Add a Point to the Path
|
||||
* @note Keep in mind that this function is used for
|
||||
* setting the starting point
|
||||
* @param v Position to add
|
||||
*/
|
||||
void PathNext(const vec2& v) { Path.push_back(v); }
|
||||
/**
|
||||
* Path Stroke Create Line from point to point
|
||||
* @note For Primitives like Rect or Triangle mak sure to use
|
||||
* UI7DrawFlags_Close to add a line back to the starting point
|
||||
* @param clr Color od the line
|
||||
* @param thickness Thickness of the line
|
||||
* @param flags Additional Drawflags
|
||||
*/
|
||||
void PathStroke(const UI7Color& clr, int thickness = 1,
|
||||
UI7DrawFlags flags = 0) {
|
||||
AddPolyLine(Path, clr, flags, thickness);
|
||||
Path.clear();
|
||||
}
|
||||
/**
|
||||
* Fill a Path with a Color
|
||||
* @note **IMPORTANT: ** Paths need to be setup clockwise
|
||||
* to be rendered correctly
|
||||
* @param clr Fill Color
|
||||
*/
|
||||
void PathFill(const UI7Color& clr) {
|
||||
AddConvexPolyFilled(Path, clr);
|
||||
Path.clear();
|
||||
}
|
||||
|
||||
void PathArcToN(const vec2& c, float radius, float a_min, float a_max,
|
||||
int segments);
|
||||
/// @brief Create a Path Rect (uses to Positions instead of Pos/Size)
|
||||
/// @param a Top Left Position
|
||||
/// @param b Bottom Right Position
|
||||
/// @param rounding rounding
|
||||
/// @param flags DrawFlags (for special rounding rules)
|
||||
void PathRect(vec2 a, vec2 b, float rounding = 0.f, UI7DrawFlags flags = 0);
|
||||
|
||||
private:
|
||||
/** Base Layer offset (Internal Used) */
|
||||
int BaseLayer() const { return base; }
|
||||
@ -114,6 +228,7 @@ class DrawList : public SmartCtor<DrawList> {
|
||||
std::stack<vec4> clip_rects; ///< Stack containing Scissor Areas
|
||||
u32 num_vertices; ///< Number of Vertices
|
||||
u32 num_indices; ///< Number of Indices
|
||||
std::vector<vec2> Path;
|
||||
// Map for Auto Static Text
|
||||
std::unordered_map<u32, LI::StaticText::Ref> static_text;
|
||||
// List of Drawcommands generated
|
||||
|
@ -29,6 +29,10 @@ using UI7MenuFlags = unsigned int;
|
||||
using UI7Align = unsigned int;
|
||||
/** 32Bit Value to store Context (IO) flags */
|
||||
using UI7IOFlags = unsigned int;
|
||||
/** 32Bit Value for Layout Flags */
|
||||
using UI7LayoutFlags = unsigned int;
|
||||
/** 32Bit value for DrawFlags */
|
||||
using UI7DrawFlags = unsigned int;
|
||||
|
||||
/** Menu Flags */
|
||||
enum UI7MenuFlags_ {
|
||||
@ -48,6 +52,18 @@ enum UI7MenuFlags_ {
|
||||
UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling,
|
||||
};
|
||||
|
||||
/** UI7 Layout Flags */
|
||||
enum UI7LayoutFlags_ {
|
||||
UI7LayoutFlags_None = 0, ///< No Flags used
|
||||
UI7LayoutFlags_UseClipRect = 1 << 0, ///< Enable ClipRect
|
||||
};
|
||||
|
||||
enum UI7DrawFlags_ {
|
||||
UI7DrawFlags_None = 0,
|
||||
UI7DrawFlags_Close = 1 << 0, ///< Close a PolyLine
|
||||
UI7DrawFlags_AALines = 1 << 1, ///< Anti aliased Lines
|
||||
};
|
||||
|
||||
/** UI7 Context Flags */
|
||||
enum UI7IOFlags_ {
|
||||
UI7IOFlags_None = 0, ///< No Additional Config available
|
||||
|
@ -61,6 +61,7 @@ class IO : public SmartCtor<IO> {
|
||||
|
||||
float Framerate = 0.f;
|
||||
float Delta = 0.f;
|
||||
u64 LastTime = 0;
|
||||
TimeStats::Ref DeltaStats;
|
||||
Timer::Ref Time;
|
||||
Hid::Ref Inp;
|
||||
@ -69,6 +70,10 @@ class IO : public SmartCtor<IO> {
|
||||
vec2 MenuPadding = 5.f;
|
||||
vec2 FramePadding = 5.f;
|
||||
vec2 ItemSpace = vec2(5.f, 2.f);
|
||||
vec2 MinSliderDragSize = 10.f; // Min height (Vt) and Min Width (Hz)
|
||||
bool ShowMenuBorder = true;
|
||||
bool ShowFrameBorder = false; // not implemented yet
|
||||
float OverScrollMod = 0.15f;
|
||||
u64 DoubleClickTime = 500; // Milliseconds
|
||||
std::vector<std::pair<UI7::ID, DrawList::Ref>> DrawListRegestry;
|
||||
DrawList::Ref Back;
|
||||
|
120
include/pd/ui7/layout.hpp
Normal file
120
include/pd/ui7/layout.hpp
Normal file
@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2025 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/core/common.hpp>
|
||||
#include <pd/ui7/container/container.hpp>
|
||||
#include <pd/ui7/drawlist.hpp>
|
||||
#include <pd/ui7/flags.hpp>
|
||||
#include <pd/ui7/io.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
class Layout : public PD::SmartCtor<Layout> {
|
||||
public:
|
||||
Layout(const ID& id, IO::Ref io) : ID(id) {
|
||||
this->IO = io;
|
||||
DrawList = UI7::DrawList::New(io->Ren);
|
||||
Scrolling[0] = false;
|
||||
Scrolling[1] = false;
|
||||
CursorInit();
|
||||
Pos = vec2(0, 0);
|
||||
Size = vec2(320, 240);
|
||||
WorkRect = vec4(IO->MenuPadding, Size - (vec2(2) * IO->MenuPadding));
|
||||
}
|
||||
~Layout() = default;
|
||||
|
||||
const std::string& GetName() const { return ID.GetName(); }
|
||||
const UI7::ID& GetID() const { return this->ID; }
|
||||
|
||||
const vec2& GetPosition() const { return Pos; }
|
||||
void SetPosition(const vec2& v) { Pos = v; }
|
||||
const vec2& GetSize() const { return Size; }
|
||||
void SetSize(const vec2& v) { Size = v; }
|
||||
|
||||
UI7::DrawList::Ref GetDrawList() { return DrawList; }
|
||||
|
||||
void CursorInit();
|
||||
void SameLine();
|
||||
void CursorMove(const vec2& size);
|
||||
|
||||
bool ObjectWorkPos(vec2& movpos);
|
||||
|
||||
void AddObject(Container::Ref obj);
|
||||
Container::Ref FindObject(u32 id);
|
||||
void ClearIDObjects() { IDObjects.clear(); }
|
||||
|
||||
vec2 AlignPosition(vec2 pos, vec2 size, vec4 area, UI7Align alignment);
|
||||
|
||||
/** Get the Alignment for Current State */
|
||||
UI7Align GetAlignment() {
|
||||
/// if temp alignment is used then return it and
|
||||
/// reset tmpalign
|
||||
if (TempAlign) {
|
||||
auto t = TempAlign;
|
||||
TempAlign = 0;
|
||||
return t;
|
||||
}
|
||||
return Alignment;
|
||||
}
|
||||
|
||||
void SetAlign(UI7Align a) { Alignment = a; }
|
||||
void NextAlign(UI7Align a) { TempAlign = a; }
|
||||
|
||||
void Update();
|
||||
|
||||
private:
|
||||
friend class Menu;
|
||||
friend class Context;
|
||||
// Base Components
|
||||
UI7::ID ID;
|
||||
UI7::IO::Ref IO;
|
||||
UI7::DrawList::Ref DrawList;
|
||||
|
||||
// Positioning
|
||||
vec2 Pos;
|
||||
vec2 Size;
|
||||
UI7Align Alignment = UI7Align_Default;
|
||||
UI7Align TempAlign;
|
||||
|
||||
// Cursor
|
||||
vec2 Cursor;
|
||||
vec2 InitialCursorOffset;
|
||||
vec2 BackupCursor;
|
||||
vec2 SamelineCursor;
|
||||
vec2 BeforeSameLine;
|
||||
vec2 LastObjSize;
|
||||
vec2 MaxPosition;
|
||||
vec4 WorkRect;
|
||||
|
||||
// Scrolling
|
||||
vec2 ScrollOffset;
|
||||
bool Scrolling[2];
|
||||
|
||||
// Objects
|
||||
std::vector<Container::Ref> Objects;
|
||||
std::vector<Container::Ref> IDObjects;
|
||||
};
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -30,6 +30,7 @@ SOFTWARE.
|
||||
#include <pd/ui7/flags.hpp>
|
||||
#include <pd/ui7/id.hpp>
|
||||
#include <pd/ui7/io.hpp>
|
||||
#include <pd/ui7/layout.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
@ -47,12 +48,11 @@ class Menu : public SmartCtor<Menu> {
|
||||
this->id = id;
|
||||
this->name = id.GetName();
|
||||
/// Set Default Values here
|
||||
scrolling[0] = false;
|
||||
scrolling[1] = false;
|
||||
scrollbar[0] = false;
|
||||
scrollbar[1] = false;
|
||||
scroll_allowed[0] = false;
|
||||
scroll_allowed[1] = false;
|
||||
Layout = UI7::Layout::New(id, io);
|
||||
}
|
||||
~Menu() = default;
|
||||
|
||||
@ -88,6 +88,22 @@ class Menu : public SmartCtor<Menu> {
|
||||
* @param color Color reference to edit
|
||||
*/
|
||||
void ColorEdit(const std::string& label, u32* color);
|
||||
|
||||
void DragFloat(const std::string& label, float* data, size_t num_elms);
|
||||
template <typename T>
|
||||
void DragData(const std::string& label, T* data, size_t num_elms = 1,
|
||||
T min = std::numeric_limits<T>::min(),
|
||||
T max = std::numeric_limits<T>::max(), T step = 1,
|
||||
int precision = 1) {
|
||||
u32 id = Strings::FastHash("drd" + label + std::to_string((u32)data));
|
||||
Container::Ref r = Layout->FindObject(id);
|
||||
if (!r) {
|
||||
r = PD::New<UI7::DragData<T>>(label, data, num_elms, io, min, max, step,
|
||||
precision);
|
||||
r->SetID(id);
|
||||
}
|
||||
Layout->AddObject(r);
|
||||
}
|
||||
// Basic API
|
||||
|
||||
/**
|
||||
@ -102,7 +118,7 @@ class Menu : public SmartCtor<Menu> {
|
||||
void EndTreeNode();
|
||||
|
||||
/** Add the Next Objext to the same line */
|
||||
void SameLine();
|
||||
void SameLine() { Layout->SameLine(); }
|
||||
/** Add a Separator Line */
|
||||
void Separator();
|
||||
/**
|
||||
@ -128,23 +144,14 @@ class Menu : public SmartCtor<Menu> {
|
||||
* Set a Temp alignment op for the next Object
|
||||
* @param a Alignment Operation
|
||||
*/
|
||||
void NextAlign(UI7Align a) { tmpalign = a; }
|
||||
void NextAlign(UI7Align a) { Layout->NextAlign(a); }
|
||||
/**
|
||||
* Align Every Single Object by this operationset
|
||||
* @param a Alignment
|
||||
*/
|
||||
void PushAlignment(UI7Align a) { alignment = a; }
|
||||
void PushAlignment(UI7Align a) { Layout->SetAlign(a); }
|
||||
/** Use default alignment */
|
||||
void PopAlignment() { alignment = UI7Align_Default; }
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static vec2 AlignPos(vec2 pos, vec2 size, vec4 view, UI7Align a);
|
||||
void PopAlignment() { Layout->Alignment = UI7Align_Default; }
|
||||
/**
|
||||
* Returns a Reference to the theme
|
||||
* @return Reference to the base Theme of the context
|
||||
@ -166,35 +173,6 @@ class Menu : public SmartCtor<Menu> {
|
||||
|
||||
// API for Custom Objects
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
bool HandleScrolling(vec2& pos, const vec2& size);
|
||||
/**
|
||||
* Get the Cursor Position
|
||||
* @return Cursor Pos
|
||||
*/
|
||||
vec2 Cursor() const { return view_area.xy() + cursor; }
|
||||
/**
|
||||
* Set the Cursor position
|
||||
* @note The old Position can be restored with RestoreCursor
|
||||
* @param v New Position
|
||||
*/
|
||||
void Cursor(const vec2& v) {
|
||||
bcursor = cursor;
|
||||
cursor = v;
|
||||
}
|
||||
/** Restore to the last cursor Position */
|
||||
void RestoreCursor() {
|
||||
cursor = bcursor;
|
||||
bcursor = vec2();
|
||||
}
|
||||
/** Return if a Vertical Scrollbar exists */
|
||||
bool HasVerticalScrollbar() { return scrollbar[1]; }
|
||||
/** Return if a Horizontal Scrollbar exists */
|
||||
@ -206,43 +184,13 @@ class Menu : public SmartCtor<Menu> {
|
||||
* @note Could destroy some basic functionality
|
||||
*/
|
||||
void TitleBarHeight(float v) { tbh = v; }
|
||||
/**
|
||||
* Init the Cursor
|
||||
* @note Useful when using with a Custom TitlebarHeight
|
||||
*/
|
||||
void CursorInit() { Cursor(io->MenuPadding + vec2(0, tbh)); }
|
||||
/**
|
||||
* Move the Cursor for new Object
|
||||
* @param szs Size of the current Object
|
||||
*/
|
||||
void CursorMove(const vec2& szs);
|
||||
/** Get the ViewArea of the Menu */
|
||||
vec4 ViewArea() const { return view_area; }
|
||||
/**
|
||||
* Get the Main Area of the Menu
|
||||
* (only relevant for input)
|
||||
*/
|
||||
vec4 MainArea() const { return main_area; }
|
||||
/**
|
||||
* Set a MainArea for input
|
||||
* @param v Area where Objects can receive inputs
|
||||
*/
|
||||
void MainArea(const vec4& v) { main_area = v; }
|
||||
/** Get The Scrolling offset */
|
||||
vec2 ScrollOffset() const { return scrolling_off; }
|
||||
/**
|
||||
* Set a Scrolling offset
|
||||
* @param v Custom Scrolling offset
|
||||
*/
|
||||
void ScrollOffset(const vec2& v) { scrolling_off = v; }
|
||||
/** Get the Current Scrollmodification value */
|
||||
vec2 ScrollMod() const { return scroll_mod; }
|
||||
|
||||
/**
|
||||
* Animated Scroll to Position
|
||||
* @param pos Destination Position
|
||||
*/
|
||||
void ScrollTo(vec2 pos) {
|
||||
scroll_anim.From(scrolling_off)
|
||||
scroll_anim.From(Layout->ScrollOffset)
|
||||
.To(pos)
|
||||
.In(1.f)
|
||||
.As(scroll_anim.EaseInOutSine);
|
||||
@ -252,19 +200,6 @@ class Menu : public SmartCtor<Menu> {
|
||||
|
||||
// Objects API
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
Container::Ref ObjectPush(Container::Ref obj);
|
||||
/**
|
||||
* Search for an Object by an id
|
||||
* @param id 32 Bit hash/id
|
||||
* @return the found Object or nullptr
|
||||
*/
|
||||
Container::Ref FindIDObj(u32 id);
|
||||
/**
|
||||
* Create a Parent Container to move and edit all sub
|
||||
* instances at once
|
||||
@ -276,7 +211,8 @@ class Menu : public SmartCtor<Menu> {
|
||||
// Draw List
|
||||
|
||||
/** Get DrawList */
|
||||
DrawList::Ref GetDrawList() { return main; }
|
||||
DrawList::Ref GetDrawList() { return Layout->DrawList; }
|
||||
UI7::Layout::Ref GetLayout() { return Layout; }
|
||||
|
||||
// Advanced
|
||||
|
||||
@ -305,43 +241,6 @@ class Menu : public SmartCtor<Menu> {
|
||||
/** Handle things like scrolling */
|
||||
void PostHandler();
|
||||
|
||||
// Basic Settings
|
||||
|
||||
/**
|
||||
* Set Backup Cursor
|
||||
* @param v Position
|
||||
*/
|
||||
void BackupCursor(const vec2& v) { bcursor = v; }
|
||||
/** Get Sameline Cursor */
|
||||
vec2 SameLineCursor() const { return slcursor; }
|
||||
/**
|
||||
* Set Sameline Cursor
|
||||
* @param v Position
|
||||
*/
|
||||
void SameLineCursor(const vec2& v) { slcursor = v; }
|
||||
/**
|
||||
* Set View Area
|
||||
* @param v vec4 containing pos and size
|
||||
*/
|
||||
void ViewArea(const vec4& v) { view_area = v; }
|
||||
/**
|
||||
* Set Scroll Modification
|
||||
* @param v Mod
|
||||
*/
|
||||
void ScrollMod(const vec2& v) { scroll_mod = v; }
|
||||
|
||||
/** Get the Alignment for Current State */
|
||||
UI7Align GetAlignment() {
|
||||
/// if temp alignment is used then return it and
|
||||
/// reset tmpalign
|
||||
if (tmpalign) {
|
||||
auto t = tmpalign;
|
||||
tmpalign = 0;
|
||||
return t;
|
||||
}
|
||||
return alignment;
|
||||
}
|
||||
|
||||
/** Internal Processing */
|
||||
void Update(float delta);
|
||||
|
||||
@ -363,21 +262,9 @@ class Menu : public SmartCtor<Menu> {
|
||||
|
||||
// Data
|
||||
|
||||
// Default Alignment for all Objects
|
||||
UI7Align alignment = UI7Align_Default;
|
||||
UI7Align tmpalign = 0; ///< Temp Alignment [only used once]
|
||||
UI7MenuFlags flags = 0; ///< Menu Flags
|
||||
u32 id; ///< Menu ID
|
||||
std::string name; ///< Menu Name
|
||||
vec2 cursor; ///< Current Cursor Position
|
||||
vec2 icursoroff; ///< Initial Cursor Offset (Also in Newline)
|
||||
vec2 bcursor; ///< Backup Cursor
|
||||
vec2 slcursor; ///< Sameline Cursor
|
||||
vec4 view_area; ///< view Area (Position and Size)
|
||||
vec4 main_area; ///< Main Area [Input related]
|
||||
vec2 scrolling_off; ///< Scrolling Position
|
||||
bool scrolling[2]; ///< Is Hz or Vt Scrolling Enabled
|
||||
vec2 scroll_mod; ///< Scroll Modificator
|
||||
float tbh; ///< Titlebar height
|
||||
bool scrollbar[2]; ///< Is Hz or Vt Scrollbar rendered
|
||||
bool scroll_allowed[2]; ///< Is Hz or Vt Scrolling Alowed
|
||||
@ -389,21 +276,10 @@ class Menu : public SmartCtor<Menu> {
|
||||
|
||||
// Objects API
|
||||
|
||||
std::vector<Container::Ref> objects; ///< Current frame Objects
|
||||
std::vector<Container::Ref> idobjs; ///< Objects using an ID
|
||||
std::vector<Container*> join; ///< List of Combined Objects
|
||||
int count_btn = 0; ///< Count for Button ID Prefix
|
||||
int count_cbx = 0; ///< Cound for Checkbox ID Prefix
|
||||
|
||||
// DrawList
|
||||
|
||||
DrawList::Ref main; ///< Main Drawlist
|
||||
|
||||
vec2 max; ///< Max Position
|
||||
vec2 mouse; ///< Mouse/Touch Position
|
||||
vec2 bslpos; ///< Before Sameline Position
|
||||
vec2 last_size; ///< Last Object Size
|
||||
|
||||
UI7::IO::Ref io; ///< IO Reference
|
||||
|
||||
std::map<u32, bool> tree_nodes; ///< Map of Tree nodes
|
||||
@ -411,6 +287,12 @@ class Menu : public SmartCtor<Menu> {
|
||||
// Animations System
|
||||
|
||||
Tween<vec2> scroll_anim; ///< for Scroll to Animation
|
||||
|
||||
// Layout API
|
||||
PD::UI7::Layout::Ref Layout;
|
||||
|
||||
UI7Color clr_close_btn = UI7Color_FrameBackground;
|
||||
UI7Color clr_collapse_tri = UI7Color_FrameBackground;
|
||||
};
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -34,6 +34,7 @@ using UI7Color = PD::u32;
|
||||
/** Theme Color */
|
||||
enum UI7Color_ {
|
||||
UI7Color_Background, ///< UI7 Menu Background
|
||||
UI7Color_Border, ///< Menu/Frame Border Color
|
||||
UI7Color_Button, ///< UI7 Button Idle Color
|
||||
UI7Color_ButtonDead, ///< UI7 Disabled Button Color
|
||||
UI7Color_ButtonActive, ///< UI7 Pressed Button Color
|
||||
|
@ -37,7 +37,7 @@ SOFTWARE.
|
||||
* Major Minor Patch Build
|
||||
* 0x01010000 -> 1.1.0-0
|
||||
*/
|
||||
#define UI7_VERSION 0x00030000
|
||||
#define UI7_VERSION 0x00030200
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
|
@ -25,7 +25,7 @@ SOFTWARE.
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void Button::HandleInput(Hid::Ref inp) {
|
||||
void Button::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
|
@ -25,7 +25,7 @@ SOFTWARE.
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void Checkbox::HandleInput(Hid::Ref inp) {
|
||||
void Checkbox::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
|
@ -22,10 +22,11 @@ SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/coloredit.hpp>
|
||||
#include <pd/ui7/container/label.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void ColorEdit::HandleInput(Hid::Ref inp) {
|
||||
void ColorEdit::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
@ -34,6 +35,7 @@ void ColorEdit::HandleInput(Hid::Ref inp) {
|
||||
if (screen->ScreenType() == Screen::Bottom) {
|
||||
if (io->DragObject(this->GetID(), vec4(FinalPos(), size))) {
|
||||
if (io->DragReleased) {
|
||||
is_shown = !is_shown;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45,6 +47,14 @@ void ColorEdit::Draw() {
|
||||
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() {
|
||||
|
113
source/ui7/container/dragdata.cpp
Normal file
113
source/ui7/container/dragdata.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
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
|
||||
} // namespace PD
|
@ -26,40 +26,88 @@ SOFTWARE.
|
||||
|
||||
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;
|
||||
}
|
||||
auto rect = ren->CreateRect(pos, szs, 0.f);
|
||||
auto cmd = LI::Command::New();
|
||||
ren->UseTex();
|
||||
ren->SetupCommand(cmd);
|
||||
cmd->Layer(layer);
|
||||
if (!clip_rects.empty()) {
|
||||
cmd->SetScissorMode(LI::ScissorMode_Normal);
|
||||
cmd->ScissorRect(clip_rects.top());
|
||||
}
|
||||
ren->QuadCommand(cmd, rect, vec4(0.f, 1.f, 1.f, 0.f), clr);
|
||||
commands.push_back(std::make_pair(
|
||||
ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd));
|
||||
PathRect(pos, pos + szs);
|
||||
PathFill(clr);
|
||||
}
|
||||
|
||||
void DrawList::AddTriangle(vec2 pos0, vec2 pos1, vec2 pos2,
|
||||
const UI7Color& clr) {
|
||||
if (!ren->InBox(pos0, pos1, pos2, ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
auto cmd = LI::Command::New();
|
||||
void DrawList::AddTriangle(const vec2& a, const vec2& b, const vec2& c,
|
||||
const UI7Color& clr, int thickness) {
|
||||
ren->UseTex();
|
||||
ren->SetupCommand(cmd);
|
||||
cmd->Layer(layer);
|
||||
if (!clip_rects.empty()) {
|
||||
cmd->SetScissorMode(LI::ScissorMode_Normal);
|
||||
cmd->ScissorRect(clip_rects.top());
|
||||
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->TriangleCommand(cmd, pos0, pos1, pos2, clr);
|
||||
commands.push_back(std::make_pair(
|
||||
ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd));
|
||||
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,
|
||||
@ -123,16 +171,62 @@ void DrawList::AddLine(const vec2& a, const vec2& b, const UI7Color& clr,
|
||||
!ren->InBox(b, ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
auto line = ren->CreateLine(a, b, t);
|
||||
auto cmd = LI::Command::New();
|
||||
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));
|
||||
}
|
||||
|
@ -26,6 +26,10 @@ SOFTWARE.
|
||||
|
||||
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;
|
||||
|
118
source/ui7/layout.cpp
Normal file
118
source/ui7/layout.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
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
|
||||
} // namespace PD
|
@ -28,27 +28,20 @@ SOFTWARE.
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void UI7::Menu::Label(const std::string& label) {
|
||||
Container::Ref r = ObjectPush(PD::New<UI7::Label>(label, io->Ren));
|
||||
r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment()));
|
||||
CursorMove(r->GetSize());
|
||||
r->Init(io, main);
|
||||
r->HandleScrolling(scrolling_off, view_area);
|
||||
// Layout API
|
||||
auto r = PD::New<UI7::Label>(label, io->Ren);
|
||||
Layout->AddObject(r);
|
||||
}
|
||||
|
||||
bool UI7::Menu::Button(const std::string& label) {
|
||||
bool ret = false;
|
||||
u32 id = Strings::FastHash("btn" + label + std::to_string(count_btn++));
|
||||
Container::Ref r = FindIDObj(id);
|
||||
Container::Ref r = Layout->FindObject(id);
|
||||
if (!r) {
|
||||
r = PD::New<UI7::Button>(label, io);
|
||||
r->SetID(id);
|
||||
r->Init(io, main);
|
||||
}
|
||||
ObjectPush(r);
|
||||
r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment()));
|
||||
r->Update();
|
||||
CursorMove(r->GetSize());
|
||||
r->HandleScrolling(scrolling_off, view_area);
|
||||
Layout->AddObject(r);
|
||||
if (!r->Skippable()) {
|
||||
ret = std::static_pointer_cast<UI7::Button>(r)->IsPressed();
|
||||
}
|
||||
@ -57,40 +50,38 @@ bool UI7::Menu::Button(const std::string& label) {
|
||||
|
||||
void UI7::Menu::ColorEdit(const std::string& label, u32* color) {
|
||||
u32 id = Strings::FastHash("cle" + label + std::to_string(count_btn++));
|
||||
Container::Ref r = FindIDObj(id);
|
||||
Container::Ref r = Layout->FindObject(id);
|
||||
if (!r) {
|
||||
r = PD::New<UI7::ColorEdit>(label, color, io);
|
||||
r->SetID(id);
|
||||
r->Init(io, main);
|
||||
}
|
||||
ObjectPush(r);
|
||||
r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment()));
|
||||
r->Update();
|
||||
CursorMove(r->GetSize());
|
||||
r->HandleScrolling(scrolling_off, view_area);
|
||||
Layout->AddObject(r);
|
||||
}
|
||||
|
||||
void UI7::Menu::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);
|
||||
}
|
||||
|
||||
void UI7::Menu::Checkbox(const std::string& label, bool& v) {
|
||||
u32 id = Strings::FastHash("cbx" + label + std::to_string(count_cbx++));
|
||||
Container::Ref r = FindIDObj(id);
|
||||
Container::Ref r = Layout->FindObject(id);
|
||||
if (!r) {
|
||||
r = PD::New<UI7::Checkbox>(label, v, io);
|
||||
r->SetID(id);
|
||||
r->Init(io, main);
|
||||
}
|
||||
ObjectPush(r);
|
||||
r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment()));
|
||||
r->Update();
|
||||
CursorMove(r->GetSize());
|
||||
r->HandleScrolling(scrolling_off, view_area);
|
||||
Layout->AddObject(r);
|
||||
}
|
||||
|
||||
void UI7::Menu::Image(Texture::Ref img, vec2 size, LI::Rect uv) {
|
||||
Container::Ref r = ObjectPush(PD::New<UI7::Image>(img, size, uv));
|
||||
r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment()));
|
||||
CursorMove(r->GetSize());
|
||||
r->Init(io, main);
|
||||
r->HandleScrolling(scrolling_off, view_area);
|
||||
Container::Ref r = PD::New<UI7::Image>(img, size, uv);
|
||||
Layout->AddObject(r);
|
||||
}
|
||||
|
||||
void UI7::Menu::DebugLabels(Menu::Ref m, Menu::Ref t) {
|
||||
@ -105,10 +96,11 @@ void UI7::Menu::DebugLabels(Menu::Ref m, Menu::Ref t) {
|
||||
s << std::hex << std::setw(8) << std::setfill('0') << m->id;
|
||||
s << std::dec << "]";
|
||||
t->Label(s.str());
|
||||
t->Label(std::format("Max Size: {:.2f}, {:.2f}", m->max.x(), m->max.y()));
|
||||
t->Label(std::format("Max Size: {:.2f}, {:.2f}", m->Layout->MaxPosition.x(),
|
||||
m->Layout->MaxPosition.y()));
|
||||
t->Label(std::format("Pos: {:.2f}, {:.2f} Size: {:.2f}, {:.2f}",
|
||||
m->view_area.x(), m->view_area.y(), m->view_area.z(),
|
||||
m->view_area.w()));
|
||||
m->Layout->Pos.x(), m->Layout->Pos.y(),
|
||||
m->Layout->Size.x(), m->Layout->Size.y()));
|
||||
t->Label(std::format("Flags: {:#08x}", m->flags));
|
||||
t->Label(
|
||||
"Pre: " +
|
||||
@ -132,66 +124,31 @@ void UI7::Menu::Update(float delta) {
|
||||
TT::Scope st("MUPT_" + name);
|
||||
scroll_anim.Update(delta);
|
||||
if (!scroll_anim.IsFinished()) {
|
||||
scrolling_off = scroll_anim;
|
||||
Layout->ScrollOffset = scroll_anim;
|
||||
}
|
||||
if (!(flags & UI7MenuFlags_NoClipRect)) {
|
||||
main->PushClipRect(vec4(view_area.x() + io->MenuPadding[0],
|
||||
view_area.y() + tbh,
|
||||
view_area.x() + view_area.z() - io->MenuPadding[0],
|
||||
view_area.y() + view_area.w()));
|
||||
}
|
||||
main->Layer(10); // Render to Layer 10
|
||||
std::vector<int> tbr;
|
||||
for (int i = 0; i < (int)objects.size(); i++) {
|
||||
auto& it = objects[i];
|
||||
if (it->GetID() != 0 && !FindIDObj(it->GetID())) {
|
||||
idobjs.push_back(it);
|
||||
}
|
||||
if (!it->Skippable()) {
|
||||
if (scroll_mod[1] == 0.f) {
|
||||
it->HandleInput(io->Inp);
|
||||
}
|
||||
/// Unlock Input after to ensure nothing is checked twice
|
||||
it->UnlockInput();
|
||||
it->Draw();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < (int)idobjs.size(); i++) {
|
||||
if (idobjs[i]->Removable()) {
|
||||
tbr.push_back(i);
|
||||
}
|
||||
}
|
||||
for (auto it : tbr) {
|
||||
idobjs.erase(idobjs.begin() + it);
|
||||
Layout->DrawList->PushClipRect(
|
||||
vec4(Layout->Pos.x() + io->MenuPadding[0], Layout->Pos.y() + tbh,
|
||||
Layout->Pos.x() + Layout->Size.x() - io->MenuPadding[0],
|
||||
Layout->Pos.y() + Layout->Size.y()));
|
||||
}
|
||||
Layout->GetDrawList()->Layer(10);
|
||||
Layout->Update();
|
||||
if (!(flags & UI7MenuFlags_NoClipRect)) {
|
||||
main->PopClipRect();
|
||||
Layout->DrawList->PopClipRect();
|
||||
}
|
||||
this->objects.clear();
|
||||
PostScrollHandler();
|
||||
}
|
||||
|
||||
void UI7::Menu::CursorMove(const vec2& size) {
|
||||
last_size = size;
|
||||
slcursor = cursor + vec2(size[0] + io->ItemSpace[0], 0);
|
||||
if (bslpos[1]) {
|
||||
cursor = vec2(io->MenuPadding[0], cursor[1] + bslpos[1] + io->ItemSpace[1]);
|
||||
bslpos = vec2();
|
||||
} else {
|
||||
cursor = vec2(io->MenuPadding[0] + icursoroff[0],
|
||||
cursor[1] + size[1] + io->ItemSpace[1]);
|
||||
}
|
||||
max = vec2(slcursor[0], cursor[1]);
|
||||
}
|
||||
|
||||
void UI7::Menu::PreHandler(UI7MenuFlags flags) {
|
||||
TT::Scope st("MPRE_" + name);
|
||||
// No touch means no Input System
|
||||
UI7Color header = has_touch ? UI7Color_HeaderDead : UI7Color_Header;
|
||||
DrawList::Ref list = Layout->GetDrawList();
|
||||
// Check if menu can be focused for Selective Menu Input API
|
||||
vec4 newarea = view_area;
|
||||
vec4 newarea = vec4(Layout->Pos, Layout->Size);
|
||||
if (!is_open) {
|
||||
newarea = vec4(view_area.xy(), vec2(view_area.z(), tbh));
|
||||
newarea = vec4(Layout->Pos, vec2(Layout->Size.x(), tbh));
|
||||
}
|
||||
if (has_touch && io->Inp->IsDown(io->Inp->Touch) &&
|
||||
io->Ren->InBox(io->Inp->TouchPos(), newarea) &&
|
||||
@ -206,23 +163,17 @@ void UI7::Menu::PreHandler(UI7MenuFlags flags) {
|
||||
count_btn = 0;
|
||||
count_cbx = 0;
|
||||
tbh = 0.f;
|
||||
CursorInit();
|
||||
main_area = view_area;
|
||||
this->flags = flags;
|
||||
this->scrolling[0] = flags & UI7MenuFlags_HzScrolling;
|
||||
this->scrolling[1] = flags & UI7MenuFlags_VtScrolling;
|
||||
Layout->Scrolling[1] = flags & UI7MenuFlags_VtScrolling;
|
||||
has_touch = io->Ren->CurrentScreen()->ScreenType() == Screen::Bottom;
|
||||
if (!(flags & UI7MenuFlags_NoBackground) && is_open) {
|
||||
main->Layer(0);
|
||||
main->AddRectangle(view_area.xy() + vec2(0, tbh),
|
||||
view_area.zw() - vec2(0, tbh),
|
||||
io->Theme->Get(UI7Color_Background));
|
||||
}
|
||||
if (!(flags & UI7MenuFlags_NoTitlebar)) {
|
||||
// Title bar setup and Rendering
|
||||
tbh = io->Ren->TextScale() * 30.f;
|
||||
main->Layer(20);
|
||||
main->AddRectangle(view_area.xy(), vec2(view_area.z(), tbh),
|
||||
CollapseHandler();
|
||||
CloseButtonHandler();
|
||||
MoveHandler();
|
||||
list->Layer(20);
|
||||
list->AddRectangle(Layout->Pos, vec2(Layout->Size.x(), tbh),
|
||||
io->Theme->Get(header));
|
||||
vec2 tpos(io->MenuPadding[0],
|
||||
tbh * 0.5 - io->Ren->GetTextDimensions(name).y() * 0.5);
|
||||
@ -234,83 +185,127 @@ void UI7::Menu::PreHandler(UI7MenuFlags flags) {
|
||||
tpos = 0;
|
||||
tflags = LITextFlags_AlignMid;
|
||||
}
|
||||
main->Layer(main->Layer() + 1);
|
||||
list->Layer(list->Layer() + 1);
|
||||
if (!(flags & UI7MenuFlags_NoClipRect)) {
|
||||
int extra = is_shown != nullptr && !(flags & UI7MenuFlags_NoClose)
|
||||
? (20 + io->ItemSpace.x())
|
||||
: 0;
|
||||
main->PushClipRect(vec4(
|
||||
view_area.xy(),
|
||||
vec2(view_area.x() + view_area.z() - extra, view_area.y() + tbh)));
|
||||
Layout->DrawList->PushClipRect(
|
||||
vec4(Layout->Pos, vec2(Layout->Pos.x() + Layout->Size.x() - extra,
|
||||
Layout->Pos.y() + tbh)));
|
||||
}
|
||||
main->AddText(view_area.xy() + tpos, this->name,
|
||||
io->Theme->Get(UI7Color_Text), tflags,
|
||||
vec2(view_area.z(), tbh));
|
||||
list->AddText(Layout->Pos + tpos, this->name, io->Theme->Get(UI7Color_Text),
|
||||
tflags, vec2(Layout->Size.x(), tbh));
|
||||
if (!(flags & UI7MenuFlags_NoClipRect)) {
|
||||
main->PopClipRect();
|
||||
Layout->DrawList->PopClipRect();
|
||||
}
|
||||
main_area[1] = tbh;
|
||||
CursorInit();
|
||||
CollapseHandler();
|
||||
CloseButtonHandler();
|
||||
MoveHandler();
|
||||
|
||||
/// Close Button Rendering
|
||||
if (!(flags & UI7MenuFlags_NoClose) && is_shown) {
|
||||
vec2 cpos =
|
||||
vec2(Layout->Pos.x() + Layout->Size.x() - 12 - io->FramePadding.x(),
|
||||
Layout->Pos.y() + io->FramePadding.y());
|
||||
Layout->GetDrawList()->AddLine(cpos, cpos + 12,
|
||||
io->Theme->Get(clr_close_btn), 2);
|
||||
Layout->GetDrawList()->AddLine(cpos + vec2(0, 12), cpos + vec2(12, 0),
|
||||
io->Theme->Get(clr_close_btn), 2);
|
||||
}
|
||||
/// Collapse Triangle Rendering
|
||||
if (!(flags & UI7MenuFlags_NoCollapse)) {
|
||||
vec2 cpos = Layout->Pos + io->FramePadding;
|
||||
vec2 positions[2] = {
|
||||
vec2(12, 6),
|
||||
vec2(0, 12),
|
||||
};
|
||||
if (is_open) {
|
||||
float t = positions[0].y();
|
||||
positions[0].y() = positions[1].x();
|
||||
positions[1].x() = t;
|
||||
}
|
||||
Layout->GetDrawList()->AddTriangleFilled(
|
||||
cpos, cpos + positions[0], cpos + positions[1],
|
||||
io->Theme->Get(clr_collapse_tri));
|
||||
}
|
||||
Layout->WorkRect[1] = io->MenuPadding[1] + tbh;
|
||||
Layout->CursorInit();
|
||||
}
|
||||
if (!(flags & UI7MenuFlags_NoBackground) && is_open) {
|
||||
list->Layer(0);
|
||||
list->AddRectangle(Layout->Pos + vec2(0, tbh), Layout->Size - vec2(0, tbh),
|
||||
io->Theme->Get(UI7Color_Background));
|
||||
}
|
||||
if (io->ShowMenuBorder) {
|
||||
vec2 bsize = Layout->Size;
|
||||
if (!is_open) {
|
||||
bsize[1] = tbh;
|
||||
}
|
||||
list->Layer(20);
|
||||
list->AddRect(Layout->Pos, bsize, io->Theme->Get(UI7Color_Border));
|
||||
}
|
||||
// Add a clip Rect for Separators
|
||||
if (!(flags & UI7MenuFlags_NoClipRect)) {
|
||||
main->PushClipRect(vec4(view_area.x() + io->MenuPadding[0],
|
||||
view_area.y() + tbh,
|
||||
view_area.x() + view_area.z() - io->MenuPadding[0],
|
||||
view_area.y() + view_area.w()));
|
||||
Layout->DrawList->PushClipRect(
|
||||
vec4(Layout->Pos.x() + io->MenuPadding[0], Layout->Pos.y() + tbh,
|
||||
Layout->Pos.x() + Layout->Size.x() - io->MenuPadding[0],
|
||||
Layout->Pos.y() + Layout->Size.y()));
|
||||
}
|
||||
main->Layer(10);
|
||||
list->Layer(10);
|
||||
TT::Beg("MUSR_" + name);
|
||||
}
|
||||
|
||||
void UI7::Menu::PostHandler() {
|
||||
TT::Scope st("MPOS_" + name);
|
||||
TT::End("MUSR_" + name);
|
||||
// Remove the Clip Rect
|
||||
if (!(flags & UI7MenuFlags_NoClipRect)) {
|
||||
Layout->DrawList->PopClipRect();
|
||||
}
|
||||
ResizeHandler();
|
||||
if (scrolling[1]) {
|
||||
scroll_allowed[1] = (max[1] > view_area.w() - io->MenuPadding[1]);
|
||||
if (max[1] < view_area.w() - io->MenuPadding[1]) {
|
||||
scrolling_off[1] = 0.f;
|
||||
if (Layout->Scrolling[1]) {
|
||||
scroll_allowed[1] =
|
||||
(Layout->MaxPosition[1] > Layout->Size.y() - io->MenuPadding[1]);
|
||||
if (Layout->MaxPosition[1] < Layout->Size.y() - io->MenuPadding[1]) {
|
||||
Layout->ScrollOffset[1] = 0.f;
|
||||
}
|
||||
scrollbar[1] = scroll_allowed[1];
|
||||
|
||||
if (scrollbar[1]) {
|
||||
/// Setup Some Variables hare [they are self described]
|
||||
int screen_w = view_area.z();
|
||||
int screen_w = Layout->Size.x();
|
||||
int tsp = io->MenuPadding[1] + tbh;
|
||||
int slider_w = 4;
|
||||
int szs = view_area.w() - tsp - io->MenuPadding[1];
|
||||
int szs = Layout->Size.y() - tsp - io->MenuPadding[1];
|
||||
/// Actually dont have a Horizontal bar yet
|
||||
if (scrollbar[0]) szs -= slider_w - 2;
|
||||
int lslider_h = 20; // Dont go less heigt for the drag
|
||||
float slider_h = (szs - 4) * (float(szs - 4) / max[1]);
|
||||
int lslider_h =
|
||||
io->MinSliderDragSize.y(); // Dont go less heigt for the drag
|
||||
float slider_h = (szs - 4) * (float(szs - 4) / Layout->MaxPosition[1]);
|
||||
/// Visual Slider Height (How it looks in the end)
|
||||
int vslider_h = std::clamp(slider_h, float(lslider_h), float(szs - 4));
|
||||
|
||||
/// Check if we overscroll to the bottom and Auto scroll back...
|
||||
/// Probably schould use Tween ENgine here
|
||||
if (scrolling_off[1] > max[1] - view_area[3] && max[1] != 0.f &&
|
||||
max[1] >= view_area[3] - io->MenuPadding[1]) {
|
||||
scrolling_off[1] -= 3.f;
|
||||
if (scrolling_off[1] < max[1] - view_area[3]) {
|
||||
scrolling_off[1] = max[1] - view_area[3];
|
||||
if (Layout->ScrollOffset[1] > Layout->MaxPosition[1] - Layout->Size.y() &&
|
||||
Layout->MaxPosition[1] != 0.f &&
|
||||
Layout->MaxPosition[1] >= Layout->Size.y() - io->MenuPadding[1]) {
|
||||
Layout->ScrollOffset[1] -= io->OverScrollMod * io->Delta;
|
||||
if (Layout->ScrollOffset[1] <
|
||||
Layout->MaxPosition[1] - Layout->Size.y()) {
|
||||
Layout->ScrollOffset[1] = Layout->MaxPosition[1] - Layout->Size.y();
|
||||
}
|
||||
}
|
||||
|
||||
/// Do the Same as above just for Overscroll back to the top
|
||||
if (scrolling_off[1] < 0) {
|
||||
scrolling_off[1] += 3.f;
|
||||
if (scrolling_off[1] > 0) {
|
||||
scrolling_off[1] = 0;
|
||||
if (Layout->ScrollOffset[1] < 0) {
|
||||
Layout->ScrollOffset[1] += io->OverScrollMod * io->Delta;
|
||||
if (Layout->ScrollOffset[1] > 0) {
|
||||
Layout->ScrollOffset[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Effect
|
||||
if (scroll_mod[1] != 0) {
|
||||
scrolling_off[1] += scroll_mod[1];
|
||||
/*if (scroll_mod[1] != 0) {
|
||||
Layout->ScrollOffset[1] += scroll_mod[1];
|
||||
}
|
||||
if (scroll_mod[1] < 0.f) {
|
||||
scroll_mod[1] += 0.4f;
|
||||
@ -323,121 +318,92 @@ void UI7::Menu::PostHandler() {
|
||||
if (scroll_mod[1] < 0.f) {
|
||||
scroll_mod[1] = 0;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
UI7Color sldr_drag = UI7Color_Button;
|
||||
/// Slider Dragging????
|
||||
/// Probably need a new API for this
|
||||
if (has_touch &&
|
||||
io->DragObject(name + "sldr", vec4(view_area.x() + screen_w - 12,
|
||||
view_area.y() + tsp, 8, szs)) &&
|
||||
io->DragObject(name + "sldr", vec4(Layout->Pos.x() + screen_w - 12,
|
||||
Layout->Pos.y() + tsp, 8, szs)) &&
|
||||
!io->DragReleasedAW) {
|
||||
sldr_drag = UI7Color_ButtonHovered;
|
||||
float drag_center = vslider_h / 2.0f;
|
||||
float drag_pos = std::clamp(
|
||||
static_cast<float>(
|
||||
((io->DragPosition[1] - view_area.y()) - tsp - drag_center) /
|
||||
((io->DragPosition[1] - Layout->Pos.y()) - tsp - drag_center) /
|
||||
(szs - vslider_h - 4)),
|
||||
0.0f, 1.0f);
|
||||
|
||||
scrolling_off[1] = drag_pos * (max[1] - view_area.w());
|
||||
Layout->ScrollOffset[1] =
|
||||
drag_pos * (Layout->MaxPosition[1] - Layout->Size.y());
|
||||
}
|
||||
int srpos =
|
||||
tsp + std::clamp(float(szs - vslider_h - 4) *
|
||||
(scrolling_off[1] / (max[1] - view_area[3])),
|
||||
(Layout->ScrollOffset[1] /
|
||||
(Layout->MaxPosition[1] - Layout->Size.y())),
|
||||
0.f, float(szs - vslider_h - 4));
|
||||
|
||||
/// Rendering Stage
|
||||
main->Layer(20);
|
||||
main->AddRectangle(view_area.xy() + vec2(screen_w - 12, tsp),
|
||||
auto list = Layout->DrawList;
|
||||
list->Layer(20);
|
||||
list->AddRectangle(Layout->Pos + vec2(screen_w - 12, tsp),
|
||||
vec2(slider_w * 2, szs),
|
||||
io->Theme->Get(UI7Color_FrameBackground));
|
||||
main->AddRectangle(view_area.xy() + vec2(screen_w - 10, tsp + 2),
|
||||
list->AddRectangle(Layout->Pos + vec2(screen_w - 10, tsp + 2),
|
||||
vec2(slider_w, szs - 4),
|
||||
io->Theme->Get(UI7Color_FrameBackgroundHovered));
|
||||
main->AddRectangle(view_area.xy() + vec2(screen_w - 10, srpos + 2),
|
||||
list->AddRectangle(Layout->Pos + vec2(screen_w - 10, srpos + 2),
|
||||
vec2(slider_w, vslider_h), io->Theme->Get(sldr_drag));
|
||||
}
|
||||
}
|
||||
// Remove the Clip Rect
|
||||
if (!(flags & UI7MenuFlags_NoClipRect)) {
|
||||
main->PopClipRect();
|
||||
}
|
||||
}
|
||||
|
||||
void UI7::Menu::SameLine() {
|
||||
bslpos = last_size;
|
||||
cursor = slcursor;
|
||||
}
|
||||
|
||||
void UI7::Menu::Separator() {
|
||||
vec2 pos = Cursor();
|
||||
vec2 size = vec2(view_area.z() - (scrollbar[1] ? 24 : 10), 1);
|
||||
CursorMove(size);
|
||||
if (HandleScrolling(pos, size)) {
|
||||
vec2 pos = Layout->Cursor;
|
||||
vec2 size = vec2(Layout->Size.x() - (scrollbar[1] ? 24 : 10), 1);
|
||||
Layout->CursorMove(size);
|
||||
if (Layout->ObjectWorkPos(pos)) {
|
||||
return;
|
||||
}
|
||||
main->AddRectangle(pos, size, io->Theme->Get(UI7Color_TextDead));
|
||||
Layout->GetDrawList()->AddRectangle(Layout->Pos + pos, size,
|
||||
io->Theme->Get(UI7Color_TextDead));
|
||||
}
|
||||
|
||||
void UI7::Menu::SeparatorText(const std::string& label) {
|
||||
vec2 size = vec2(view_area.z() - (scrollbar[1] ? 24 : 10), 1);
|
||||
vec2 size = vec2(Layout->Size.x() - (scrollbar[1] ? 24 : 10), 1);
|
||||
vec2 tdim = io->Ren->GetTextDimensions(label);
|
||||
vec2 pos = Cursor();
|
||||
CursorMove(vec2(size.x(), tdim.y()));
|
||||
vec2 pos = Layout->Cursor;
|
||||
Layout->CursorMove(vec2(size.x(), tdim.y()));
|
||||
|
||||
if (HandleScrolling(pos, size)) {
|
||||
if (Layout->ObjectWorkPos(pos)) {
|
||||
return;
|
||||
}
|
||||
auto alignment = GetAlignment();
|
||||
vec2 rpos = AlignPos(pos, tdim, view_area, alignment);
|
||||
auto alignment = Layout->GetAlignment();
|
||||
vec2 rpos = Layout->AlignPosition(Layout->Pos + pos, tdim,
|
||||
vec4(Layout->Pos, Layout->Size), alignment);
|
||||
|
||||
if (!(alignment & UI7Align_Left)) {
|
||||
main->AddRectangle(
|
||||
rpos + vec2(-(rpos[0] - view_area[0] - io->MenuPadding[0]),
|
||||
Layout->GetDrawList()->AddRectangle(
|
||||
rpos + vec2(-(rpos[0] - Layout->Pos.x() - io->MenuPadding[0]),
|
||||
tdim.y() * 0.5),
|
||||
vec2(rpos[0] - view_area[0] - io->MenuPadding[0] - io->FramePadding[0],
|
||||
vec2(rpos[0] - Layout->Pos.x() - io->MenuPadding[0] -
|
||||
io->FramePadding[0],
|
||||
size.y()),
|
||||
io->Theme->Get(UI7Color_TextDead));
|
||||
}
|
||||
if (!(alignment & UI7Align_Right)) {
|
||||
main->AddRectangle(
|
||||
Layout->GetDrawList()->AddRectangle(
|
||||
rpos + vec2(tdim.x() + io->FramePadding[0], tdim.y() * 0.5),
|
||||
vec2(size.x() - (tdim.x() + io->FramePadding[0]), size.y()),
|
||||
io->Theme->Get(UI7Color_TextDead));
|
||||
}
|
||||
main->AddText(rpos, label, io->Theme->Get(UI7Color_Text), 0,
|
||||
vec2(view_area.z(), 20));
|
||||
}
|
||||
|
||||
bool UI7::Menu::HandleScrolling(vec2& pos, const vec2& size) {
|
||||
if (scrolling[1]) {
|
||||
pos -= vec2(0, scrolling_off.y());
|
||||
if (!io->Ren->InBox(
|
||||
pos, size, vec4(view_area.xy(), view_area.xy() + view_area.zw()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Container::Ref UI7::Menu::ObjectPush(Container::Ref obj) {
|
||||
this->objects.push_back(obj);
|
||||
obj->SetParent(this->tmp_parent);
|
||||
return obj;
|
||||
}
|
||||
|
||||
Container::Ref UI7::Menu::FindIDObj(u32 id) {
|
||||
for (auto& it : idobjs) {
|
||||
if (it->GetID() == id) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
Layout->GetDrawList()->AddText(rpos, label, io->Theme->Get(UI7Color_Text), 0,
|
||||
vec2(Layout->Size.x(), 20));
|
||||
}
|
||||
|
||||
void UI7::Menu::Join() {
|
||||
Assert(objects.size(), "Objects list is empty!");
|
||||
join.push_back(objects.back().get());
|
||||
Assert(Layout->Objects.size(), "Objects list is empty!");
|
||||
join.push_back(Layout->Objects.back().get());
|
||||
}
|
||||
|
||||
void UI7::Menu::JoinAlign(UI7Align a) {
|
||||
@ -454,10 +420,12 @@ void UI7::Menu::JoinAlign(UI7Align a) {
|
||||
}
|
||||
vec2 off;
|
||||
if (a & UI7Align_Center) {
|
||||
off[0] = (view_area[0] + view_area[2] * 0.5) - (spos[0] + szs[0] * 0.5);
|
||||
off[0] =
|
||||
(Layout->Pos.x() + Layout->Size.x() * 0.5) - (spos[0] + szs[0] * 0.5);
|
||||
}
|
||||
if (a & UI7Align_Mid) {
|
||||
off[1] = (view_area[1] + view_area[3] * 0.5) - (spos[1] + szs[1] * 0.5);
|
||||
off[1] =
|
||||
(Layout->Pos.y() + Layout->Size.y() * 0.5) - (spos[1] + szs[1] * 0.5);
|
||||
}
|
||||
for (auto it : join) {
|
||||
it->SetPos(it->GetPos() + off);
|
||||
@ -465,27 +433,16 @@ void UI7::Menu::JoinAlign(UI7Align a) {
|
||||
join.clear();
|
||||
}
|
||||
|
||||
vec2 UI7::Menu::AlignPos(vec2 pos, vec2 size, vec4 view, UI7Align a) {
|
||||
vec2 np = pos;
|
||||
if (a & UI7Align_Center) {
|
||||
np[0] = (view[0] + view[2] * 0.5) - ((pos[0] - view[0]) + size[0] * 0.5);
|
||||
}
|
||||
if (a & UI7Align_Mid) {
|
||||
np[1] = (view[1] + view[3] * 0.5) - ((pos[1] - view[1]) + size[1] * 0.5);
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
void UI7::Menu::AfterAlign(UI7Align a) {
|
||||
Container* ref = objects.back().get();
|
||||
Container* ref = Layout->Objects.back().get();
|
||||
vec2 p = ref->GetPos();
|
||||
vec2 s = ref->GetSize();
|
||||
vec2 np = p;
|
||||
if (a & UI7Align_Center) {
|
||||
np[0] = (view_area[0] + view_area[2] * 0.5) - (p[0] + s[0] * 0.5);
|
||||
np[0] = (Layout->Pos.x() + Layout->Size.x() * 0.5) - (p[0] + s[0] * 0.5);
|
||||
}
|
||||
if (a & UI7Align_Mid) {
|
||||
np[1] = (view_area[1] + view_area[3] * 0.5) - (p[1] + s[1] * 0.5);
|
||||
np[1] = (Layout->Pos.y() + Layout->Size.y() * 0.5) - (p[1] + s[1] * 0.5);
|
||||
}
|
||||
ref->SetPos(np);
|
||||
}
|
||||
@ -503,17 +460,17 @@ bool UI7::Menu::BeginTreeNode(const UI7::ID& id) {
|
||||
tree_nodes[(u32)id] = false;
|
||||
n = tree_nodes.find((u32)id);
|
||||
}
|
||||
vec2 pos = Cursor();
|
||||
vec2 pos = Layout->Cursor;
|
||||
vec2 tdim = io->Ren->GetTextDimensions(id.GetName());
|
||||
vec2 size = vec2(tdim.x() + 10 + io->ItemSpace[0], tdim.y());
|
||||
if (n->second) {
|
||||
icursoroff.x() += 10.f;
|
||||
Layout->InitialCursorOffset.x() += 10.f;
|
||||
}
|
||||
CursorMove(size);
|
||||
if (HandleScrolling(pos, size)) {
|
||||
Layout->CursorMove(size);
|
||||
if (Layout->ObjectWorkPos(pos)) {
|
||||
return n->second;
|
||||
}
|
||||
vec2 ts = pos + vec2(0, 3);
|
||||
vec2 ts = Layout->Pos + pos + vec2(0, 3);
|
||||
vec2 positions[2] = {
|
||||
vec2(10, 5),
|
||||
vec2(0, 10),
|
||||
@ -523,16 +480,19 @@ bool UI7::Menu::BeginTreeNode(const UI7::ID& id) {
|
||||
positions[0].y() = positions[1].x();
|
||||
positions[1].x() = t;
|
||||
}
|
||||
main->AddTriangle(ts, ts + positions[0], ts + positions[1],
|
||||
Layout->GetDrawList()->AddTriangleFilled(
|
||||
ts, ts + positions[0], ts + positions[1],
|
||||
io->Theme->Get(UI7Color_FrameBackground));
|
||||
main->AddText(pos + vec2(10 + io->ItemSpace[0], 0), id.GetName(),
|
||||
Layout->GetDrawList()->AddText(
|
||||
Layout->Pos + pos + vec2(10 + io->ItemSpace[0], 0), id.GetName(),
|
||||
io->Theme->Get(UI7Color_Text));
|
||||
if (has_touch && io->DragObject(name + id.GetName(), vec4(pos, size))) {
|
||||
if (has_touch &&
|
||||
io->DragObject(name + id.GetName(), vec4(Layout->Pos + pos, size))) {
|
||||
if (io->DragReleased) {
|
||||
n->second = !n->second;
|
||||
if (!n->second) {
|
||||
icursoroff.x() -= 10.f;
|
||||
cursor.x() -= 10;
|
||||
Layout->InitialCursorOffset.x() -= 10;
|
||||
Layout->Cursor.x() -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -540,30 +500,28 @@ bool UI7::Menu::BeginTreeNode(const UI7::ID& id) {
|
||||
}
|
||||
|
||||
void UI7::Menu::EndTreeNode() {
|
||||
icursoroff.x() -= 10.f;
|
||||
cursor.x() -= 10;
|
||||
if (icursoroff.x() < 0.f) {
|
||||
icursoroff.x() = 0.f;
|
||||
Layout->InitialCursorOffset.x() -= 10.f;
|
||||
Layout->Cursor.x() -= 10.f;
|
||||
if (Layout->InitialCursorOffset.x() < 0.f) {
|
||||
Layout->InitialCursorOffset.x() = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
void UI7::Menu::CloseButtonHandler() {
|
||||
// Close Logic
|
||||
if (!(flags & UI7MenuFlags_NoClose) && is_shown != nullptr) {
|
||||
vec2 cpos = vec2(view_area.x() + view_area.z() - 12 - io->FramePadding.x(),
|
||||
view_area.y() + io->FramePadding.y());
|
||||
vec2 cpos =
|
||||
vec2(Layout->Pos.x() + Layout->Size.x() - 12 - io->FramePadding.x(),
|
||||
Layout->Pos.y() + io->FramePadding.y());
|
||||
|
||||
UI7Color clr = UI7Color_FrameBackground;
|
||||
clr_close_btn = UI7Color_FrameBackground;
|
||||
if (has_touch &&
|
||||
io->DragObject(UI7::ID(name + "clse"), vec4(cpos, vec2(12)))) {
|
||||
if (io->DragReleased) {
|
||||
*is_shown = !(*is_shown);
|
||||
}
|
||||
clr = UI7Color_FrameBackgroundHovered;
|
||||
clr_close_btn = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
main->AddLine(cpos, cpos + 12, io->Theme->Get(clr), 2);
|
||||
main->AddLine(cpos + vec2(0, 12), cpos + vec2(12, 0), io->Theme->Get(clr),
|
||||
2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,18 +529,17 @@ void UI7::Menu::ResizeHandler() {
|
||||
if (!(flags & UI7MenuFlags_NoResize)) {
|
||||
if (has_touch &&
|
||||
io->DragObject(name + "rszs",
|
||||
vec4(view_area.xy() + view_area.zw() - 20, 20))) {
|
||||
vec2 szs = view_area.zw() + (io->DragPosition - io->DragLastPosition);
|
||||
vec4(Layout->Pos + Layout->Size - 20, 20))) {
|
||||
vec2 szs = Layout->Size + (io->DragPosition - io->DragLastPosition);
|
||||
if (szs.x() < 30) szs[0] = 30;
|
||||
if (szs.y() < 30) szs[1] = 30;
|
||||
view_area = vec4(view_area.xy(), szs);
|
||||
Layout->Size = szs;
|
||||
}
|
||||
// front->AddRectangle(view_area.xy() + view_area.zw() - 20, 20,
|
||||
// 0xffffffff); Not vidible dor some reason
|
||||
// int l = front->Layer();
|
||||
// front->Layer(l + 1);
|
||||
// front->AddTriangle(10, vec2(10, 0), vec2(10, 0), 0xffffffff);
|
||||
// front->Layer(l);
|
||||
Layout->DrawList->Layer(21);
|
||||
Layout->DrawList->AddTriangleFilled(Layout->Pos + Layout->Size,
|
||||
Layout->Pos + Layout->Size - vec2(0, 15),
|
||||
Layout->Pos + Layout->Size - vec2(15, 0),
|
||||
io->Theme->Get(UI7Color_FrameBackground));
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,13 +548,11 @@ void UI7::Menu::MoveHandler() {
|
||||
if (!(flags & UI7MenuFlags_NoMove)) {
|
||||
if (has_touch &&
|
||||
io->DragObject(name + "tmv",
|
||||
vec4(view_area.xy(), vec2(view_area.z(), tbh)))) {
|
||||
vec4(Layout->Pos, vec2(Layout->Size.x(), tbh)))) {
|
||||
if (io->DragDoubleRelease) {
|
||||
is_open = !is_open;
|
||||
}
|
||||
view_area =
|
||||
vec4(view_area.xy() + (io->DragPosition - io->DragLastPosition),
|
||||
view_area.zw());
|
||||
Layout->Pos = Layout->Pos + (io->DragPosition - io->DragLastPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -605,39 +560,29 @@ void UI7::Menu::MoveHandler() {
|
||||
void UI7::Menu::CollapseHandler() {
|
||||
// Collapse logic
|
||||
if (!(flags & UI7MenuFlags_NoCollapse)) {
|
||||
vec2 cpos = view_area.xy() + io->FramePadding;
|
||||
UI7Color clr = UI7Color_FrameBackground;
|
||||
vec2 cpos = Layout->Pos + io->FramePadding;
|
||||
clr_collapse_tri = UI7Color_FrameBackground;
|
||||
if (has_touch &&
|
||||
io->DragObject(UI7::ID(name + "clbse"), vec4(cpos, vec2(18, tbh)))) {
|
||||
if (io->DragReleased) {
|
||||
is_open = !is_open;
|
||||
}
|
||||
clr = UI7Color_FrameBackgroundHovered;
|
||||
clr_collapse_tri = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
vec2 positions[2] = {
|
||||
vec2(12, 6),
|
||||
vec2(0, 12),
|
||||
};
|
||||
if (is_open) {
|
||||
float t = positions[0].y();
|
||||
positions[0].y() = positions[1].x();
|
||||
positions[1].x() = t;
|
||||
}
|
||||
main->AddTriangle(cpos, cpos + positions[0], cpos + positions[1],
|
||||
io->Theme->Get(clr));
|
||||
}
|
||||
}
|
||||
|
||||
void UI7::Menu::PostScrollHandler() {
|
||||
if (has_touch && io->DragObject(id, view_area) && scrolling[1] &&
|
||||
flags & UI7MenuFlags_VtScrolling &&
|
||||
max[1] - view_area.w() + io->MenuPadding[1] > 0) {
|
||||
if (has_touch && io->DragObject(id, vec4(Layout->Pos, Layout->Size)) &&
|
||||
Layout->Scrolling[1] && flags & UI7MenuFlags_VtScrolling &&
|
||||
Layout->MaxPosition.y() - Layout->Size.y() + io->MenuPadding[1] > 0) {
|
||||
if (io->DragReleased) {
|
||||
scroll_mod = (io->DragPosition - io->DragLastPosition);
|
||||
// scroll_mod = (io->DragPosition - io->DragLastPosition);
|
||||
} else {
|
||||
scrolling_off[1] = std::clamp(
|
||||
scrolling_off[1] - (io->DragPosition.y() - io->DragLastPosition.y()),
|
||||
-40.f, (max[1] - view_area.w()) + 40.f);
|
||||
Layout->ScrollOffset[1] = std::clamp(
|
||||
Layout->ScrollOffset[1] -
|
||||
(io->DragPosition.y() - io->DragLastPosition.y()),
|
||||
-40.f, (Layout->MaxPosition.y() - Layout->Size.y()) + 40.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ namespace UI7 {
|
||||
void Theme::Default(Theme& theme) {
|
||||
theme.Set(UI7Color_Text, Color("#FFFFFFFF"));
|
||||
theme.Set(UI7Color_TextDead, Color("#AAAAAAFF"));
|
||||
theme.Set(UI7Color_Background, Color("#222222aa"));
|
||||
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"));
|
||||
@ -49,10 +50,11 @@ 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("#cbcbcbFF"));
|
||||
theme.Set(UI7Color_ButtonHovered, Color("#acacacFF"));
|
||||
theme.Set(UI7Color_Header, Color("#ddddddFF"));
|
||||
theme.Set(UI7Color_HeaderDead, Color("#cdcdcdFF"));
|
||||
theme.Set(UI7Color_Selector, Color("#222222FF"));
|
||||
|
@ -61,16 +61,13 @@ bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags, bool* show) {
|
||||
auto menu = this->menus.find(id);
|
||||
if (menu == this->menus.end()) {
|
||||
this->menus[id] = Menu::New(id, io);
|
||||
this->menus[id]->ViewArea(this->io->Ren->GetViewport());
|
||||
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;
|
||||
if (!this->current->main) {
|
||||
this->current->main = DrawList::New(io->Ren);
|
||||
}
|
||||
io->RegisterDrawList(id, this->current->main);
|
||||
io->RegisterDrawList(id, this->current->Layout->GetDrawList());
|
||||
this->current->PreHandler(flags);
|
||||
amenus.push_back(this->current->GetID());
|
||||
if (!this->current->is_open) {
|
||||
@ -98,11 +95,9 @@ void UI7::Context::EndMenu() {
|
||||
this->io->CurrentMenu = 0;
|
||||
}
|
||||
|
||||
void UI7::Context::Update(float delta) {
|
||||
void UI7::Context::Update(float) {
|
||||
TT::Scope st("UI7_Update");
|
||||
Assert(current == nullptr, "Still in a Menu!");
|
||||
this->io->Delta = delta;
|
||||
io->DeltaStats->Add(io->Delta * 1000);
|
||||
bool focused_exist = false;
|
||||
for (auto it : amenus) {
|
||||
auto m = menus[it];
|
||||
@ -212,14 +207,14 @@ void UI7::Context::MetricsMenu(bool* show) {
|
||||
for (auto& it : menus) {
|
||||
if (m->BeginTreeNode(it.second->name)) {
|
||||
m->Label("Name: " + it.second->name);
|
||||
m->Label("Pos: " + UI7DV2N(it.second->view_area.xy()));
|
||||
m->Label("Size: " + UI7DV2N(it.second->view_area.zw()));
|
||||
m->Label("Main Area: " + UI7DV4N(it.second->main_area));
|
||||
m->Label("Cursor: " + UI7DV2N(it.second->cursor));
|
||||
if (m->BeginTreeNode("ID Objects (" +
|
||||
std::to_string(it.second->idobjs.size()) +
|
||||
")")) {
|
||||
for (auto& jt : it.second->idobjs) {
|
||||
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();
|
||||
@ -261,36 +256,14 @@ void UI7::Context::StyleEditor(bool* show) {
|
||||
|
||||
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
|
||||
m->Separator();
|
||||
m->Label(std::format("MenuPadding: {}, {}", io->MenuPadding.x(),
|
||||
io->MenuPadding.y()));
|
||||
m->SameLine();
|
||||
if (m->Button("-")) {
|
||||
io->MenuPadding -= 1;
|
||||
}
|
||||
m->SameLine();
|
||||
if (m->Button("+")) {
|
||||
io->MenuPadding += 1;
|
||||
}
|
||||
m->Label(std::format("FramePadding: {}, {}", io->FramePadding.x(),
|
||||
io->FramePadding.y()));
|
||||
m->SameLine();
|
||||
if (m->Button("-")) {
|
||||
io->FramePadding -= 1;
|
||||
}
|
||||
m->SameLine();
|
||||
if (m->Button("+")) {
|
||||
io->FramePadding += 1;
|
||||
}
|
||||
m->Label(
|
||||
std::format("ItemSpace: {}, {}", io->ItemSpace.x(), io->ItemSpace.y()));
|
||||
m->SameLine();
|
||||
if (m->Button("-")) {
|
||||
io->ItemSpace -= 1;
|
||||
}
|
||||
m->SameLine();
|
||||
if (m->Button("+")) {
|
||||
io->ItemSpace += 1;
|
||||
}
|
||||
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());
|
||||
@ -301,22 +274,26 @@ void UI7::Context::StyleEditor(bool* show) {
|
||||
}
|
||||
/// Small trick to print without prefix
|
||||
#define ts(x) m->ColorEdit(std::string(#x).substr(9), &io->Theme->GetRef(x));
|
||||
ts(UI7Color_Background);
|
||||
ts(UI7Color_Button);
|
||||
ts(UI7Color_ButtonDead);
|
||||
ts(UI7Color_ButtonActive);
|
||||
ts(UI7Color_ButtonHovered);
|
||||
ts(UI7Color_Text);
|
||||
ts(UI7Color_TextDead);
|
||||
ts(UI7Color_Header);
|
||||
ts(UI7Color_HeaderDead);
|
||||
ts(UI7Color_Selector);
|
||||
ts(UI7Color_Checkmark);
|
||||
ts(UI7Color_FrameBackground);
|
||||
ts(UI7Color_FrameBackgroundHovered);
|
||||
ts(UI7Color_Progressbar);
|
||||
ts(UI7Color_ListEven);
|
||||
ts(UI7Color_ListOdd);
|
||||
#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();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user