1 | /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ |
2 | /* If you are missing that file, acquire a complete release at teeworlds.com. */ |
3 | #ifndef GAME_CLIENT_UI_H |
4 | #define GAME_CLIENT_UI_H |
5 | |
6 | #include "lineinput.h" |
7 | #include "ui_rect.h" |
8 | |
9 | #include <engine/input.h> |
10 | #include <engine/textrender.h> |
11 | |
12 | #include <chrono> |
13 | #include <set> |
14 | #include <string> |
15 | #include <vector> |
16 | |
17 | class CScrollRegion; |
18 | class IClient; |
19 | class IGraphics; |
20 | class IKernel; |
21 | |
22 | enum class EEditState |
23 | { |
24 | NONE, |
25 | START, |
26 | EDITING, |
27 | END, |
28 | ONE_GO |
29 | }; |
30 | |
31 | template<typename T> |
32 | struct SEditResult |
33 | { |
34 | EEditState m_State; |
35 | T m_Value; |
36 | }; |
37 | |
38 | struct SUIAnimator |
39 | { |
40 | bool m_Active; |
41 | bool m_ScaleLabel; |
42 | bool m_RepositionLabel; |
43 | |
44 | std::chrono::nanoseconds m_Time; |
45 | float m_Value; |
46 | |
47 | float m_XOffset; |
48 | float m_YOffset; |
49 | float m_WOffset; |
50 | float m_HOffset; |
51 | }; |
52 | |
53 | class IScrollbarScale |
54 | { |
55 | public: |
56 | virtual float ToRelative(int AbsoluteValue, int Min, int Max) const = 0; |
57 | virtual int ToAbsolute(float RelativeValue, int Min, int Max) const = 0; |
58 | }; |
59 | class CLinearScrollbarScale : public IScrollbarScale |
60 | { |
61 | public: |
62 | float ToRelative(int AbsoluteValue, int Min, int Max) const override |
63 | { |
64 | return (AbsoluteValue - Min) / (float)(Max - Min); |
65 | } |
66 | int ToAbsolute(float RelativeValue, int Min, int Max) const override |
67 | { |
68 | return round_to_int(f: RelativeValue * (Max - Min) + Min + 0.1f); |
69 | } |
70 | }; |
71 | class CLogarithmicScrollbarScale : public IScrollbarScale |
72 | { |
73 | private: |
74 | int m_MinAdjustment; |
75 | |
76 | public: |
77 | CLogarithmicScrollbarScale(int MinAdjustment) |
78 | { |
79 | m_MinAdjustment = maximum(a: MinAdjustment, b: 1); // must be at least 1 to support Min == 0 with logarithm |
80 | } |
81 | float ToRelative(int AbsoluteValue, int Min, int Max) const override |
82 | { |
83 | if(Min < m_MinAdjustment) |
84 | { |
85 | AbsoluteValue += m_MinAdjustment; |
86 | Min += m_MinAdjustment; |
87 | Max += m_MinAdjustment; |
88 | } |
89 | return (std::log(x: AbsoluteValue) - std::log(x: Min)) / (float)(std::log(x: Max) - std::log(x: Min)); |
90 | } |
91 | int ToAbsolute(float RelativeValue, int Min, int Max) const override |
92 | { |
93 | int ResultAdjustment = 0; |
94 | if(Min < m_MinAdjustment) |
95 | { |
96 | Min += m_MinAdjustment; |
97 | Max += m_MinAdjustment; |
98 | ResultAdjustment = -m_MinAdjustment; |
99 | } |
100 | return round_to_int(f: std::exp(x: RelativeValue * (std::log(x: Max) - std::log(x: Min)) + std::log(x: Min))) + ResultAdjustment; |
101 | } |
102 | }; |
103 | |
104 | class IButtonColorFunction |
105 | { |
106 | public: |
107 | virtual ColorRGBA GetColor(bool Active, bool Hovered) const = 0; |
108 | }; |
109 | class CDarkButtonColorFunction : public IButtonColorFunction |
110 | { |
111 | public: |
112 | ColorRGBA GetColor(bool Active, bool Hovered) const override |
113 | { |
114 | if(Active) |
115 | return ColorRGBA(0.15f, 0.15f, 0.15f, 0.25f); |
116 | else if(Hovered) |
117 | return ColorRGBA(0.5f, 0.5f, 0.5f, 0.25f); |
118 | return ColorRGBA(0.0f, 0.0f, 0.0f, 0.25f); |
119 | } |
120 | }; |
121 | class CLightButtonColorFunction : public IButtonColorFunction |
122 | { |
123 | public: |
124 | ColorRGBA GetColor(bool Active, bool Hovered) const override |
125 | { |
126 | if(Active) |
127 | return ColorRGBA(1.0f, 1.0f, 1.0f, 0.4f); |
128 | else if(Hovered) |
129 | return ColorRGBA(1.0f, 1.0f, 1.0f, 0.6f); |
130 | return ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f); |
131 | } |
132 | }; |
133 | class CScrollBarColorFunction : public IButtonColorFunction |
134 | { |
135 | public: |
136 | ColorRGBA GetColor(bool Active, bool Hovered) const override |
137 | { |
138 | if(Active) |
139 | return ColorRGBA(0.9f, 0.9f, 0.9f, 1.0f); |
140 | else if(Hovered) |
141 | return ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); |
142 | return ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f); |
143 | } |
144 | }; |
145 | |
146 | class CUi; |
147 | |
148 | class CUIElement |
149 | { |
150 | friend class CUi; |
151 | |
152 | CUi *m_pUI; |
153 | |
154 | CUIElement(CUi *pUI, int RequestedRectCount) { Init(pUI, RequestedRectCount); } |
155 | |
156 | public: |
157 | struct SUIElementRect |
158 | { |
159 | CUIElement *m_pParent; |
160 | |
161 | public: |
162 | int m_UIRectQuadContainer; |
163 | STextContainerIndex m_UITextContainer; |
164 | |
165 | float m_X; |
166 | float m_Y; |
167 | float m_Width; |
168 | float m_Height; |
169 | float m_Rounding; |
170 | int m_Corners; |
171 | |
172 | std::string m_Text; |
173 | int m_ReadCursorGlyphCount; |
174 | |
175 | CTextCursor m_Cursor; |
176 | |
177 | ColorRGBA m_TextColor; |
178 | ColorRGBA m_TextOutlineColor; |
179 | |
180 | SUIElementRect(); |
181 | |
182 | ColorRGBA m_QuadColor; |
183 | |
184 | void Reset(); |
185 | void Draw(const CUIRect *pRect, ColorRGBA Color, int Corners, float Rounding); |
186 | }; |
187 | |
188 | protected: |
189 | CUi *Ui() const { return m_pUI; } |
190 | std::vector<SUIElementRect> m_vUIRects; |
191 | |
192 | public: |
193 | CUIElement() = default; |
194 | |
195 | void Init(CUi *pUI, int RequestedRectCount); |
196 | |
197 | SUIElementRect *Rect(size_t Index) |
198 | { |
199 | return &m_vUIRects[Index]; |
200 | } |
201 | |
202 | bool AreRectsInit() |
203 | { |
204 | return !m_vUIRects.empty(); |
205 | } |
206 | |
207 | void InitRects(int RequestedRectCount); |
208 | }; |
209 | |
210 | struct SLabelProperties |
211 | { |
212 | float m_MaxWidth = -1; |
213 | bool m_StopAtEnd = false; |
214 | bool m_EllipsisAtEnd = false; |
215 | bool m_EnableWidthCheck = true; |
216 | std::vector<STextColorSplit> m_vColorSplits = {}; |
217 | }; |
218 | |
219 | struct |
220 | { |
221 | int = 0; |
222 | bool = false; |
223 | bool = false; |
224 | bool = false; |
225 | bool = false; |
226 | int = IGraphics::CORNER_ALL; |
227 | float = 5.0f; |
228 | float = 0.0f; |
229 | ColorRGBA = ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f); |
230 | }; |
231 | |
232 | class CUIElementBase |
233 | { |
234 | private: |
235 | static CUi *s_pUI; |
236 | |
237 | public: |
238 | static void Init(CUi *pUI) { s_pUI = pUI; } |
239 | |
240 | IClient *Client() const; |
241 | IGraphics *Graphics() const; |
242 | IInput *Input() const; |
243 | ITextRender *TextRender() const; |
244 | CUi *Ui() const { return s_pUI; } |
245 | }; |
246 | |
247 | class CButtonContainer |
248 | { |
249 | }; |
250 | |
251 | struct SValueSelectorProperties |
252 | { |
253 | bool m_UseScroll = true; |
254 | int64_t m_Step = 1; |
255 | float m_Scale = 1.0f; |
256 | bool m_IsHex = false; |
257 | int m_HexPrefix = 6; |
258 | ColorRGBA m_Color = ColorRGBA(0.0f, 0.0f, 0.0f, 0.4f); |
259 | }; |
260 | |
261 | struct SProgressSpinnerProperties |
262 | { |
263 | float m_Progress = -1.0f; // between 0.0f and 1.0f, or negative for indeterminate progress |
264 | ColorRGBA m_Color = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); |
265 | int m_Segments = 64; |
266 | }; |
267 | |
268 | /** |
269 | * Type safe UI ID for popup menus. |
270 | */ |
271 | struct |
272 | { |
273 | }; |
274 | |
275 | struct |
276 | { |
277 | int = IGraphics::CORNER_ALL; |
278 | ColorRGBA = ColorRGBA(0.5f, 0.5f, 0.5f, 0.75f); |
279 | ColorRGBA = ColorRGBA(0.0f, 0.0f, 0.0f, 0.75f); |
280 | }; |
281 | |
282 | class CUi |
283 | { |
284 | public: |
285 | /** |
286 | * These enum values are returned by popup menu functions to specify the behavior. |
287 | */ |
288 | enum |
289 | { |
290 | /** |
291 | * The current popup menu will be kept open. |
292 | */ |
293 | = 0, |
294 | |
295 | /** |
296 | * The current popup menu will be closed. |
297 | */ |
298 | = 1, |
299 | |
300 | /** |
301 | * The current popup menu and all popup menus above it will be closed. |
302 | */ |
303 | POPUP_CLOSE_CURRENT_AND_DESCENDANTS = 2, |
304 | }; |
305 | |
306 | /** |
307 | * Callback that draws a popup menu. |
308 | * |
309 | * @param pContext The context object of the popup menu. |
310 | * @param View The UI rect where the popup menu's contents should be drawn. |
311 | * @param Active Whether this popup is active (the top-most popup). |
312 | * Only the active popup should handle key and mouse events. |
313 | * |
314 | * @return Value from the @link EPopupMenuFunctionResult @endlink enum. |
315 | */ |
316 | typedef EPopupMenuFunctionResult (*)(void *pContext, CUIRect View, bool Active); |
317 | |
318 | /** |
319 | * Callback that is called when one or more popups are closed. |
320 | */ |
321 | typedef std::function<void()> ; |
322 | |
323 | private: |
324 | bool m_Enabled; |
325 | |
326 | const void *m_pHotItem = nullptr; |
327 | const void *m_pActiveItem = nullptr; |
328 | const void *m_pLastActiveItem = nullptr; // only used internally to track active CLineInput |
329 | const void *m_pBecomingHotItem = nullptr; |
330 | const CScrollRegion *m_pHotScrollRegion = nullptr; |
331 | const CScrollRegion *m_pBecomingHotScrollRegion = nullptr; |
332 | bool m_ActiveItemValid = false; |
333 | |
334 | int m_ActiveButtonLogicButton = -1; |
335 | int m_ActiveDraggableButtonLogicButton = -1; |
336 | class CDoubleClickState |
337 | { |
338 | public: |
339 | const void *m_pLastClickedId = nullptr; |
340 | float m_LastClickTime = -1.0f; |
341 | vec2 m_LastClickPos = vec2(-1.0f, -1.0f); |
342 | }; |
343 | CDoubleClickState m_DoubleClickState; |
344 | const void *m_pLastEditingItem = nullptr; |
345 | float m_ActiveScrollbarOffset = 0.0f; |
346 | float m_ProgressSpinnerOffset = 0.0f; |
347 | class CValueSelectorState |
348 | { |
349 | public: |
350 | int m_Button = -1; |
351 | bool m_DidScroll = false; |
352 | float m_ScrollValue = 0.0f; |
353 | CLineInputNumber m_NumberInput; |
354 | const void *m_pLastTextId = nullptr; |
355 | }; |
356 | CValueSelectorState m_ActiveValueSelectorState; |
357 | |
358 | vec2 m_UpdatedMousePos = vec2(0.0f, 0.0f); // in window screen space |
359 | vec2 m_UpdatedMouseDelta = vec2(0.0f, 0.0f); // in window screen space |
360 | vec2 m_MousePos = vec2(0.0f, 0.0f); // in gui space |
361 | vec2 m_MouseDelta = vec2(0.0f, 0.0f); // in gui space |
362 | vec2 m_MouseWorldPos = vec2(-1.0f, -1.0f); // in world space |
363 | unsigned m_MouseButtons = 0; |
364 | unsigned m_LastMouseButtons = 0; |
365 | bool m_MouseSlow = false; |
366 | bool m_MouseLock = false; |
367 | const void *m_pMouseLockId = nullptr; |
368 | |
369 | unsigned m_HotkeysPressed = 0; |
370 | |
371 | CUIRect m_Screen; |
372 | |
373 | std::vector<CUIRect> m_vClips; |
374 | void UpdateClipping(); |
375 | |
376 | struct |
377 | { |
378 | static constexpr float = 1.0f; |
379 | static constexpr float = 4.0f; |
380 | |
381 | const SPopupMenuId *; |
382 | SPopupMenuProperties ; |
383 | CUIRect ; |
384 | void *; |
385 | FPopupMenuFunction ; |
386 | }; |
387 | std::vector<SPopupMenu> ; |
388 | FPopupMenuClosedCallback = nullptr; |
389 | |
390 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
391 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
392 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
393 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
394 | |
395 | IClient *m_pClient; |
396 | IGraphics *m_pGraphics; |
397 | IInput *m_pInput; |
398 | ITextRender *m_pTextRender; |
399 | |
400 | std::vector<CUIElement *> m_vpOwnUIElements; // ui elements maintained by CUi class |
401 | std::vector<CUIElement *> m_vpUIElements; |
402 | |
403 | public: |
404 | static const CLinearScrollbarScale ms_LinearScrollbarScale; |
405 | static const CLogarithmicScrollbarScale ms_LogarithmicScrollbarScale; |
406 | static const CDarkButtonColorFunction ms_DarkButtonColorFunction; |
407 | static const CLightButtonColorFunction ms_LightButtonColorFunction; |
408 | static const CScrollBarColorFunction ms_ScrollBarColorFunction; |
409 | |
410 | static const float ms_FontmodHeight; |
411 | |
412 | void Init(IKernel *pKernel); |
413 | IClient *Client() const { return m_pClient; } |
414 | IGraphics *Graphics() const { return m_pGraphics; } |
415 | IInput *Input() const { return m_pInput; } |
416 | ITextRender *TextRender() const { return m_pTextRender; } |
417 | |
418 | CUi(); |
419 | ~CUi(); |
420 | |
421 | enum EHotkey : unsigned |
422 | { |
423 | HOTKEY_ENTER = 1 << 0, |
424 | HOTKEY_ESCAPE = 1 << 1, |
425 | HOTKEY_UP = 1 << 2, |
426 | HOTKEY_DOWN = 1 << 3, |
427 | HOTKEY_DELETE = 1 << 4, |
428 | HOTKEY_TAB = 1 << 5, |
429 | HOTKEY_SCROLL_UP = 1 << 6, |
430 | HOTKEY_SCROLL_DOWN = 1 << 7, |
431 | HOTKEY_PAGE_UP = 1 << 8, |
432 | HOTKEY_PAGE_DOWN = 1 << 9, |
433 | HOTKEY_HOME = 1 << 10, |
434 | HOTKEY_END = 1 << 11, |
435 | }; |
436 | |
437 | void ResetUIElement(CUIElement &UIElement) const; |
438 | |
439 | CUIElement *GetNewUIElement(int RequestedRectCount); |
440 | |
441 | void AddUIElement(CUIElement *pElement); |
442 | void OnElementsReset(); |
443 | void OnWindowResize(); |
444 | void OnCursorMove(float X, float Y); |
445 | |
446 | void SetEnabled(bool Enabled) { m_Enabled = Enabled; } |
447 | bool Enabled() const { return m_Enabled; } |
448 | void Update(vec2 MouseWorldPos = vec2(-1.0f, -1.0f)); |
449 | void DebugRender(); |
450 | |
451 | vec2 MousePos() const { return m_MousePos; } |
452 | float MouseX() const { return m_MousePos.x; } |
453 | float MouseY() const { return m_MousePos.y; } |
454 | vec2 MouseDelta() const { return m_MouseDelta; } |
455 | float MouseDeltaX() const { return m_MouseDelta.x; } |
456 | float MouseDeltaY() const { return m_MouseDelta.y; } |
457 | vec2 MouseWorldPos() const { return m_MouseWorldPos; } |
458 | float MouseWorldX() const { return m_MouseWorldPos.x; } |
459 | float MouseWorldY() const { return m_MouseWorldPos.y; } |
460 | vec2 UpdatedMousePos() const { return m_UpdatedMousePos; } |
461 | vec2 UpdatedMouseDelta() const { return m_UpdatedMouseDelta; } |
462 | int MouseButton(int Index) const { return (m_MouseButtons >> Index) & 1; } |
463 | int MouseButtonClicked(int Index) const { return MouseButton(Index) && !((m_LastMouseButtons >> Index) & 1); } |
464 | bool CheckMouseLock() |
465 | { |
466 | if(m_MouseLock && ActiveItem() != m_pMouseLockId) |
467 | DisableMouseLock(); |
468 | return m_MouseLock; |
469 | } |
470 | void EnableMouseLock(const void *pId) |
471 | { |
472 | m_MouseLock = true; |
473 | m_pMouseLockId = pId; |
474 | } |
475 | void DisableMouseLock() { m_MouseLock = false; } |
476 | |
477 | void SetHotItem(const void *pId) { m_pBecomingHotItem = pId; } |
478 | void SetActiveItem(const void *pId) |
479 | { |
480 | m_ActiveItemValid = true; |
481 | m_pActiveItem = pId; |
482 | if(pId) |
483 | m_pLastActiveItem = pId; |
484 | } |
485 | bool CheckActiveItem(const void *pId) |
486 | { |
487 | if(m_pActiveItem == pId) |
488 | { |
489 | m_ActiveItemValid = true; |
490 | return true; |
491 | } |
492 | return false; |
493 | } |
494 | void SetHotScrollRegion(const CScrollRegion *pId) { m_pBecomingHotScrollRegion = pId; } |
495 | const void *HotItem() const { return m_pHotItem; } |
496 | const void *NextHotItem() const { return m_pBecomingHotItem; } |
497 | const void *ActiveItem() const { return m_pActiveItem; } |
498 | const CScrollRegion *HotScrollRegion() const { return m_pHotScrollRegion; } |
499 | |
500 | void StartCheck() { m_ActiveItemValid = false; } |
501 | void FinishCheck() |
502 | { |
503 | if(!m_ActiveItemValid && m_pActiveItem != nullptr) |
504 | { |
505 | SetActiveItem(nullptr); |
506 | m_pHotItem = nullptr; |
507 | m_pBecomingHotItem = nullptr; |
508 | } |
509 | } |
510 | |
511 | bool MouseInside(const CUIRect *pRect) const; |
512 | bool MouseInsideClip() const { return !IsClipped() || MouseInside(pRect: ClipArea()); } |
513 | bool MouseHovered(const CUIRect *pRect) const { return MouseInside(pRect) && MouseInsideClip(); } |
514 | void ConvertMouseMove(float *pX, float *pY, IInput::ECursorType CursorType) const; |
515 | void ResetMouseSlow() { m_MouseSlow = false; } |
516 | |
517 | bool ConsumeHotkey(EHotkey Hotkey); |
518 | void ClearHotkeys() { m_HotkeysPressed = 0; } |
519 | bool OnInput(const IInput::CEvent &Event); |
520 | |
521 | constexpr float ButtonColorMulActive() const { return 0.5f; } |
522 | constexpr float ButtonColorMulHot() const { return 1.5f; } |
523 | constexpr float ButtonColorMulDefault() const { return 1.0f; } |
524 | float ButtonColorMul(const void *pId); |
525 | |
526 | const CUIRect *Screen(); |
527 | void MapScreen(); |
528 | float PixelSize(); |
529 | |
530 | void ClipEnable(const CUIRect *pRect); |
531 | void ClipDisable(); |
532 | const CUIRect *ClipArea() const; |
533 | inline bool IsClipped() const { return !m_vClips.empty(); } |
534 | |
535 | int DoButtonLogic(const void *pId, int Checked, const CUIRect *pRect); |
536 | int DoDraggableButtonLogic(const void *pId, int Checked, const CUIRect *pRect, bool *pClicked, bool *pAbrupted); |
537 | bool DoDoubleClickLogic(const void *pId); |
538 | EEditState DoPickerLogic(const void *pId, const CUIRect *pRect, float *pX, float *pY); |
539 | void DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange, float ViewPortSize, float TotalSize, bool SmoothClamp = false, float ScrollSpeed = 10.0f) const; |
540 | static vec2 CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align, const float *pBiggestCharHeight = nullptr); |
541 | |
542 | void DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps = {}) const; |
543 | |
544 | void DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps = {}, int StrLen = -1, const CTextCursor *pReadCursor = nullptr) const; |
545 | void DoLabelStreamed(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps = {}, int StrLen = -1, const CTextCursor *pReadCursor = nullptr) const; |
546 | |
547 | /** |
548 | * Creates an input field. |
549 | * |
550 | * @see DoClearableEditBox |
551 | * |
552 | * @param pLineInput This pointer will be stored and written to on next user input. |
553 | * So you can not pass in a pointer that goes out of scope such as a local variable. |
554 | * Pass in either a member variable of the current class or a static variable. |
555 | * For example ```static CLineInputBuffered<IO_MAX_PATH_LENGTH> s_MyInput;``` |
556 | * @param pRect the UI rect it will attach to with a 2.0f margin |
557 | * @param FontSize Size of the font (`10.0f`, `12.0f` and `14.0f` are commonly used here) |
558 | * @param Corners Number of corners (default: `IGraphics::CORNER_ALL`) |
559 | * @param vColorSplits Sets color splits of the `CTextCursor` to allow multicolored text |
560 | * |
561 | * @return true if the value of the input field changed since the last call. |
562 | */ |
563 | bool DoEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const std::vector<STextColorSplit> &vColorSplits = {}); |
564 | |
565 | /** |
566 | * Creates an input field with a clear [x] button attached to it. |
567 | * |
568 | * @see DoEditBox |
569 | * |
570 | * @param pLineInput This pointer will be stored and written to on next user input. |
571 | * So you can not pass in a pointer that goes out of scope such as a local variable. |
572 | * Pass in either a member variable of the current class or a static variable. |
573 | * For example ```static CLineInputBuffered<IO_MAX_PATH_LENGTH> s_MyInput;``` |
574 | * @param pRect the UI rect it will attach to |
575 | * @param FontSize Size of the font (`10.0f`, `12.0f` and `14.0f` are commonly used here) |
576 | * @param Corners Number of corners (default: `IGraphics::CORNER_ALL`) |
577 | * @param vColorSplits Sets color splits of the `CTextCursor` to allow multicolored text |
578 | * |
579 | * @return true if the value of the input field changed since the last call. |
580 | */ |
581 | bool DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const std::vector<STextColorSplit> &vColorSplits = {}); |
582 | |
583 | int (CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props = {}); |
584 | // only used for popup menus |
585 | int (CButtonContainer *pButtonContainer, const char *pText, const CUIRect *pRect, float Size, int Align, float Padding = 0.0f, bool TransparentInactive = false, bool Enabled = true); |
586 | |
587 | // value selector |
588 | SEditResult<int64_t> DoValueSelectorWithState(const void *pId, const CUIRect *pRect, const char *pLabel, int64_t Current, int64_t Min, int64_t Max, const SValueSelectorProperties &Props = {}); |
589 | int64_t DoValueSelector(const void *pId, const CUIRect *pRect, const char *pLabel, int64_t Current, int64_t Min, int64_t Max, const SValueSelectorProperties &Props = {}); |
590 | |
591 | // scrollbars |
592 | enum |
593 | { |
594 | SCROLLBAR_OPTION_INFINITE = 1 << 0, |
595 | SCROLLBAR_OPTION_NOCLAMPVALUE = 1 << 1, |
596 | SCROLLBAR_OPTION_MULTILINE = 1 << 2, |
597 | }; |
598 | float DoScrollbarV(const void *pId, const CUIRect *pRect, float Current); |
599 | float DoScrollbarH(const void *pId, const CUIRect *pRect, float Current, const ColorRGBA *pColorInner = nullptr); |
600 | bool DoScrollbarOption(const void *pId, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, const IScrollbarScale *pScale = &ms_LinearScrollbarScale, unsigned Flags = 0u, const char *pSuffix = "" ); |
601 | |
602 | // progress bar |
603 | void RenderProgressBar(CUIRect ProgressBar, float Progress); |
604 | |
605 | // progress spinner |
606 | void RenderProgressSpinner(vec2 Center, float OuterRadius, const SProgressSpinnerProperties &Props = {}) const; |
607 | |
608 | // popup menu |
609 | void (const SPopupMenuId *pId, int X, int Y, int Width, int Height, void *pContext, FPopupMenuFunction pfnFunc, const SPopupMenuProperties &Props = {}); |
610 | void (); |
611 | void (const SPopupMenuId *pId, bool IncludeDescendants = false); |
612 | void (); |
613 | bool () const; |
614 | bool (const SPopupMenuId *pId) const; |
615 | bool () const; |
616 | void (FPopupMenuClosedCallback pfnCallback); |
617 | |
618 | struct : public SPopupMenuId |
619 | { |
620 | static constexpr float = 200.0f; |
621 | static constexpr float = 10.0f; |
622 | |
623 | CUi *; // set by CUi when popup is shown |
624 | char [1024]; |
625 | ColorRGBA ; |
626 | |
627 | void (class ITextRender *pTextRender); |
628 | void (); |
629 | }; |
630 | void (float X, float Y, SMessagePopupContext *pContext); |
631 | |
632 | struct : public SPopupMenuId |
633 | { |
634 | enum |
635 | { |
636 | = 0, |
637 | , |
638 | , |
639 | }; |
640 | static constexpr float = 200.0f; |
641 | static constexpr float = 10.0f; |
642 | static constexpr float = 12.0f; |
643 | static constexpr float = 5.0f; |
644 | |
645 | CUi *; // set by CUi when popup is shown |
646 | char [128]; |
647 | char [128]; |
648 | char [1024]; |
649 | EConfirmationResult ; |
650 | |
651 | CButtonContainer ; |
652 | CButtonContainer ; |
653 | |
654 | (); |
655 | void (); |
656 | void (); |
657 | }; |
658 | void (float X, float Y, SConfirmPopupContext *pContext); |
659 | |
660 | struct : public SPopupMenuId |
661 | { |
662 | CUi *; // set by CUi when popup is shown |
663 | CScrollRegion *; |
664 | SPopupMenuProperties ; |
665 | char [256]; |
666 | std::vector<std::string> ; |
667 | std::vector<CButtonContainer> ; |
668 | const std::string *; |
669 | int ; |
670 | float ; |
671 | float ; |
672 | float ; |
673 | float ; |
674 | float ; |
675 | float ; |
676 | bool ; |
677 | |
678 | (); |
679 | void (); |
680 | }; |
681 | void (float X, float Y, SSelectionPopupContext *pContext); |
682 | |
683 | struct : public SPopupMenuId |
684 | { |
685 | enum |
686 | { |
687 | = -1, |
688 | , |
689 | , |
690 | , |
691 | }; |
692 | |
693 | CUi *; // set by CUi when popup is shown |
694 | EColorPickerMode = MODE_UNSET; |
695 | bool = false; |
696 | unsigned int * = nullptr; // may be nullptr |
697 | ColorHSVA ; |
698 | ColorRGBA ; |
699 | ColorHSLA ; |
700 | // UI element IDs |
701 | const char = 0; |
702 | const char = 0; |
703 | const char [5] = {0}; |
704 | CButtonContainer [(int)MODE_HSLA + 1]; |
705 | EEditState ; |
706 | }; |
707 | void (float X, float Y, SColorPickerPopupContext *pContext); |
708 | |
709 | // dropdown menu |
710 | struct SDropDownState |
711 | { |
712 | SSelectionPopupContext ; |
713 | CUIElement m_UiElement; |
714 | CButtonContainer m_ButtonContainer; |
715 | bool m_Init = false; |
716 | }; |
717 | int DoDropDown(CUIRect *pRect, int CurSelection, const char **pStrs, int Num, SDropDownState &State); |
718 | }; |
719 | |
720 | #endif |
721 | |