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 | vec2 m_UpdatedMousePos = vec2(0.0f, 0.0f); |
335 | vec2 m_UpdatedMouseDelta = vec2(0.0f, 0.0f); |
336 | float m_MouseX, m_MouseY; // in gui space |
337 | float m_MouseDeltaX, m_MouseDeltaY; // in gui space |
338 | float m_MouseWorldX, m_MouseWorldY; // in world space |
339 | unsigned m_MouseButtons; |
340 | unsigned m_LastMouseButtons; |
341 | bool m_MouseSlow = false; |
342 | bool m_MouseLock = false; |
343 | const void *m_pMouseLockId = nullptr; |
344 | |
345 | unsigned m_HotkeysPressed = 0; |
346 | |
347 | CUIRect m_Screen; |
348 | |
349 | std::vector<CUIRect> m_vClips; |
350 | void UpdateClipping(); |
351 | |
352 | bool m_ValueSelectorTextMode = false; |
353 | |
354 | struct |
355 | { |
356 | static constexpr float = 1.0f; |
357 | static constexpr float = 4.0f; |
358 | |
359 | const SPopupMenuId *; |
360 | SPopupMenuProperties ; |
361 | CUIRect ; |
362 | void *; |
363 | FPopupMenuFunction ; |
364 | }; |
365 | std::vector<SPopupMenu> ; |
366 | FPopupMenuClosedCallback = nullptr; |
367 | |
368 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
369 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
370 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
371 | static CUi::EPopupMenuFunctionResult (void *pContext, CUIRect View, bool Active); |
372 | |
373 | IClient *m_pClient; |
374 | IGraphics *m_pGraphics; |
375 | IInput *m_pInput; |
376 | ITextRender *m_pTextRender; |
377 | |
378 | std::vector<CUIElement *> m_vpOwnUIElements; // ui elements maintained by CUi class |
379 | std::vector<CUIElement *> m_vpUIElements; |
380 | |
381 | public: |
382 | static const CLinearScrollbarScale ms_LinearScrollbarScale; |
383 | static const CLogarithmicScrollbarScale ms_LogarithmicScrollbarScale; |
384 | static const CDarkButtonColorFunction ms_DarkButtonColorFunction; |
385 | static const CLightButtonColorFunction ms_LightButtonColorFunction; |
386 | static const CScrollBarColorFunction ms_ScrollBarColorFunction; |
387 | |
388 | static const float ms_FontmodHeight; |
389 | |
390 | void Init(IKernel *pKernel); |
391 | IClient *Client() const { return m_pClient; } |
392 | IGraphics *Graphics() const { return m_pGraphics; } |
393 | IInput *Input() const { return m_pInput; } |
394 | ITextRender *TextRender() const { return m_pTextRender; } |
395 | |
396 | CUi(); |
397 | ~CUi(); |
398 | |
399 | enum EHotkey : unsigned |
400 | { |
401 | HOTKEY_ENTER = 1 << 0, |
402 | HOTKEY_ESCAPE = 1 << 1, |
403 | HOTKEY_UP = 1 << 2, |
404 | HOTKEY_DOWN = 1 << 3, |
405 | HOTKEY_DELETE = 1 << 4, |
406 | HOTKEY_TAB = 1 << 5, |
407 | HOTKEY_SCROLL_UP = 1 << 6, |
408 | HOTKEY_SCROLL_DOWN = 1 << 7, |
409 | HOTKEY_PAGE_UP = 1 << 8, |
410 | HOTKEY_PAGE_DOWN = 1 << 9, |
411 | HOTKEY_HOME = 1 << 10, |
412 | HOTKEY_END = 1 << 11, |
413 | }; |
414 | |
415 | void ResetUIElement(CUIElement &UIElement) const; |
416 | |
417 | CUIElement *GetNewUIElement(int RequestedRectCount); |
418 | |
419 | void AddUIElement(CUIElement *pElement); |
420 | void OnElementsReset(); |
421 | void OnWindowResize(); |
422 | void OnCursorMove(float X, float Y); |
423 | |
424 | void SetEnabled(bool Enabled) { m_Enabled = Enabled; } |
425 | bool Enabled() const { return m_Enabled; } |
426 | void Update(); |
427 | void Update(float MouseX, float MouseY, float MouseDeltaX, float MouseDeltaY, float MouseWorldX, float MouseWorldY); |
428 | void DebugRender(); |
429 | |
430 | float MouseDeltaX() const { return m_MouseDeltaX; } |
431 | float MouseDeltaY() const { return m_MouseDeltaY; } |
432 | float MouseX() const { return m_MouseX; } |
433 | float MouseY() const { return m_MouseY; } |
434 | vec2 MousePos() const { return vec2(m_MouseX, m_MouseY); } |
435 | float MouseWorldX() const { return m_MouseWorldX; } |
436 | float MouseWorldY() const { return m_MouseWorldY; } |
437 | int MouseButton(int Index) const { return (m_MouseButtons >> Index) & 1; } |
438 | int MouseButtonClicked(int Index) const { return MouseButton(Index) && !((m_LastMouseButtons >> Index) & 1); } |
439 | int MouseButtonReleased(int Index) const { return ((m_LastMouseButtons >> Index) & 1) && !MouseButton(Index); } |
440 | bool CheckMouseLock() |
441 | { |
442 | if(m_MouseLock && ActiveItem() != m_pMouseLockId) |
443 | DisableMouseLock(); |
444 | return m_MouseLock; |
445 | } |
446 | void EnableMouseLock(const void *pId) |
447 | { |
448 | m_MouseLock = true; |
449 | m_pMouseLockId = pId; |
450 | } |
451 | void DisableMouseLock() { m_MouseLock = false; } |
452 | |
453 | void SetHotItem(const void *pId) { m_pBecomingHotItem = pId; } |
454 | void SetActiveItem(const void *pId) |
455 | { |
456 | m_ActiveItemValid = true; |
457 | m_pActiveItem = pId; |
458 | if(pId) |
459 | m_pLastActiveItem = pId; |
460 | } |
461 | bool CheckActiveItem(const void *pId) |
462 | { |
463 | if(m_pActiveItem == pId) |
464 | { |
465 | m_ActiveItemValid = true; |
466 | return true; |
467 | } |
468 | return false; |
469 | } |
470 | void SetHotScrollRegion(const CScrollRegion *pId) { m_pBecomingHotScrollRegion = pId; } |
471 | const void *HotItem() const { return m_pHotItem; } |
472 | const void *NextHotItem() const { return m_pBecomingHotItem; } |
473 | const void *ActiveItem() const { return m_pActiveItem; } |
474 | const CScrollRegion *HotScrollRegion() const { return m_pHotScrollRegion; } |
475 | |
476 | void StartCheck() { m_ActiveItemValid = false; } |
477 | void FinishCheck() |
478 | { |
479 | if(!m_ActiveItemValid && m_pActiveItem != nullptr) |
480 | { |
481 | SetActiveItem(nullptr); |
482 | m_pHotItem = nullptr; |
483 | m_pBecomingHotItem = nullptr; |
484 | } |
485 | } |
486 | |
487 | bool MouseInside(const CUIRect *pRect) const; |
488 | bool MouseInsideClip() const { return !IsClipped() || MouseInside(pRect: ClipArea()); } |
489 | bool MouseHovered(const CUIRect *pRect) const { return MouseInside(pRect) && MouseInsideClip(); } |
490 | void ConvertMouseMove(float *pX, float *pY, IInput::ECursorType CursorType) const; |
491 | void ResetMouseSlow() { m_MouseSlow = false; } |
492 | |
493 | bool ConsumeHotkey(EHotkey Hotkey); |
494 | void ClearHotkeys() { m_HotkeysPressed = 0; } |
495 | bool OnInput(const IInput::CEvent &Event); |
496 | |
497 | constexpr float ButtonColorMulActive() const { return 0.5f; } |
498 | constexpr float ButtonColorMulHot() const { return 1.5f; } |
499 | constexpr float ButtonColorMulDefault() const { return 1.0f; } |
500 | float ButtonColorMul(const void *pId); |
501 | |
502 | const CUIRect *Screen(); |
503 | void MapScreen(); |
504 | float PixelSize(); |
505 | |
506 | void ClipEnable(const CUIRect *pRect); |
507 | void ClipDisable(); |
508 | const CUIRect *ClipArea() const; |
509 | inline bool IsClipped() const { return !m_vClips.empty(); } |
510 | |
511 | int DoButtonLogic(const void *pId, int Checked, const CUIRect *pRect); |
512 | int DoDraggableButtonLogic(const void *pId, int Checked, const CUIRect *pRect, bool *pClicked, bool *pAbrupted); |
513 | EEditState DoPickerLogic(const void *pId, const CUIRect *pRect, float *pX, float *pY); |
514 | void DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange, float ViewPortSize, float TotalSize, bool SmoothClamp = false, float ScrollSpeed = 10.0f) const; |
515 | static vec2 CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align, const float *pBiggestCharHeight = nullptr); |
516 | |
517 | void DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps = {}) const; |
518 | |
519 | 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; |
520 | 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; |
521 | |
522 | /** |
523 | * Creates an input field. |
524 | * |
525 | * @see DoClearableEditBox |
526 | * |
527 | * @param pLineInput This pointer will be stored and written to on next user input. |
528 | * So you can not pass in a pointer that goes out of scope such as a local variable. |
529 | * Pass in either a member variable of the current class or a static variable. |
530 | * For example ```static CLineInputBuffered<IO_MAX_PATH_LENGTH> s_MyInput;``` |
531 | * @param pRect the UI rect it will attach to with a 2.0f margin |
532 | * @param FontSize Size of the font (`10.0f`, `12.0f` and `14.0f` are commonly used here) |
533 | * @param Corners Number of corners (default: `IGraphics::CORNER_ALL`) |
534 | * @param vColorSplits Sets color splits of the `CTextCursor` to allow multicolored text |
535 | * |
536 | * @return true if the value of the input field changed since the last call. |
537 | */ |
538 | bool DoEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const std::vector<STextColorSplit> &vColorSplits = {}); |
539 | |
540 | /** |
541 | * Creates an input field with a clear [x] button attached to it. |
542 | * |
543 | * @see DoEditBox |
544 | * |
545 | * @param pLineInput This pointer will be stored and written to on next user input. |
546 | * So you can not pass in a pointer that goes out of scope such as a local variable. |
547 | * Pass in either a member variable of the current class or a static variable. |
548 | * For example ```static CLineInputBuffered<IO_MAX_PATH_LENGTH> s_MyInput;``` |
549 | * @param pRect the UI rect it will attach to |
550 | * @param FontSize Size of the font (`10.0f`, `12.0f` and `14.0f` are commonly used here) |
551 | * @param Corners Number of corners (default: `IGraphics::CORNER_ALL`) |
552 | * @param vColorSplits Sets color splits of the `CTextCursor` to allow multicolored text |
553 | * |
554 | * @return true if the value of the input field changed since the last call. |
555 | */ |
556 | bool DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const std::vector<STextColorSplit> &vColorSplits = {}); |
557 | |
558 | int (CUIElement &UIElement, const CButtonContainer *pId, const std::function<const char *()> &GetTextLambda, const CUIRect *pRect, const SMenuButtonProperties &Props = {}); |
559 | // only used for popup menus |
560 | int (CButtonContainer *pButtonContainer, const char *pText, const CUIRect *pRect, float Size, int Align, float Padding = 0.0f, bool TransparentInactive = false, bool Enabled = true); |
561 | |
562 | // value selector |
563 | 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 = {}); |
564 | int64_t DoValueSelector(const void *pId, const CUIRect *pRect, const char *pLabel, int64_t Current, int64_t Min, int64_t Max, const SValueSelectorProperties &Props = {}); |
565 | bool IsValueSelectorTextMode() const { return m_ValueSelectorTextMode; } |
566 | void SetValueSelectorTextMode(bool TextMode) { m_ValueSelectorTextMode = TextMode; } |
567 | |
568 | // scrollbars |
569 | enum |
570 | { |
571 | SCROLLBAR_OPTION_INFINITE = 1 << 0, |
572 | SCROLLBAR_OPTION_NOCLAMPVALUE = 1 << 1, |
573 | SCROLLBAR_OPTION_MULTILINE = 1 << 2, |
574 | }; |
575 | float DoScrollbarV(const void *pId, const CUIRect *pRect, float Current); |
576 | float DoScrollbarH(const void *pId, const CUIRect *pRect, float Current, const ColorRGBA *pColorInner = nullptr); |
577 | 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 = "" ); |
578 | |
579 | // progress spinner |
580 | void RenderProgressSpinner(vec2 Center, float OuterRadius, const SProgressSpinnerProperties &Props = {}) const; |
581 | |
582 | // popup menu |
583 | void (const SPopupMenuId *pId, int X, int Y, int Width, int Height, void *pContext, FPopupMenuFunction pfnFunc, const SPopupMenuProperties &Props = {}); |
584 | void (); |
585 | void (const SPopupMenuId *pId, bool IncludeDescendants = false); |
586 | void (); |
587 | bool () const; |
588 | bool (const SPopupMenuId *pId) const; |
589 | bool () const; |
590 | void (FPopupMenuClosedCallback pfnCallback); |
591 | |
592 | struct : public SPopupMenuId |
593 | { |
594 | static constexpr float = 200.0f; |
595 | static constexpr float = 10.0f; |
596 | |
597 | CUi *; // set by CUi when popup is shown |
598 | char [1024]; |
599 | ColorRGBA ; |
600 | |
601 | void (class ITextRender *pTextRender); |
602 | void (); |
603 | }; |
604 | void (float X, float Y, SMessagePopupContext *pContext); |
605 | |
606 | struct : public SPopupMenuId |
607 | { |
608 | enum |
609 | { |
610 | = 0, |
611 | , |
612 | , |
613 | }; |
614 | static constexpr float = 200.0f; |
615 | static constexpr float = 10.0f; |
616 | static constexpr float = 12.0f; |
617 | static constexpr float = 5.0f; |
618 | |
619 | CUi *; // set by CUi when popup is shown |
620 | char [128]; |
621 | char [128]; |
622 | char [1024]; |
623 | EConfirmationResult ; |
624 | |
625 | CButtonContainer ; |
626 | CButtonContainer ; |
627 | |
628 | (); |
629 | void (); |
630 | void (); |
631 | }; |
632 | void (float X, float Y, SConfirmPopupContext *pContext); |
633 | |
634 | struct : public SPopupMenuId |
635 | { |
636 | CUi *; // set by CUi when popup is shown |
637 | CScrollRegion *; |
638 | SPopupMenuProperties ; |
639 | char [256]; |
640 | std::vector<std::string> ; |
641 | std::vector<CButtonContainer> ; |
642 | const std::string *; |
643 | int ; |
644 | float ; |
645 | float ; |
646 | float ; |
647 | float ; |
648 | float ; |
649 | float ; |
650 | bool ; |
651 | |
652 | (); |
653 | void (); |
654 | }; |
655 | void (float X, float Y, SSelectionPopupContext *pContext); |
656 | |
657 | struct : public SPopupMenuId |
658 | { |
659 | enum |
660 | { |
661 | = -1, |
662 | , |
663 | , |
664 | , |
665 | }; |
666 | |
667 | CUi *; // set by CUi when popup is shown |
668 | EColorPickerMode = MODE_UNSET; |
669 | bool = false; |
670 | unsigned int * = nullptr; // may be nullptr |
671 | ColorHSVA ; |
672 | ColorRGBA ; |
673 | ColorHSLA ; |
674 | // UI element IDs |
675 | const char = 0; |
676 | const char = 0; |
677 | const char [5] = {0}; |
678 | CButtonContainer [(int)MODE_HSLA + 1]; |
679 | EEditState ; |
680 | }; |
681 | void (float X, float Y, SColorPickerPopupContext *pContext); |
682 | |
683 | // dropdown menu |
684 | struct SDropDownState |
685 | { |
686 | SSelectionPopupContext ; |
687 | CUIElement m_UiElement; |
688 | CButtonContainer m_ButtonContainer; |
689 | bool m_Init = false; |
690 | }; |
691 | int DoDropDown(CUIRect *pRect, int CurSelection, const char **pStrs, int Num, SDropDownState &State); |
692 | }; |
693 | |
694 | #endif |
695 | |