• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javaandroidc++linuxc#objective-ccocoa誰得qtrubybathyscaphegamephpguicwindows翻訳pythonomegattwitterframeworkbtronarduinovb.net計画中(planning stage)directxpreviewertestゲームエンジンdom

Simple C++ UI framework and more...


コミットメタ情報

リビジョンe754b96647fc916a8d3dca9da10e0908e067be62 (tree)
日時2018-05-28 13:23:39
作者Starg <starg@user...>
コミッターStarg

ログメッセージ

WIP: implement widget and renderer

変更サマリ

差分

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,22 +8,19 @@ project(sirius)
88 set(SIRIUS_LIBRARY_TYPE "SHARED" CACHE STRING "Library kind")
99 set_property(CACHE SIRIUS_LIBRARY_TYPE PROPERTY STRINGS SHARED STATIC OBJECT)
1010
11-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/Debug/bin")
12-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release/bin")
13-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/RelWithDebInfo/bin")
14-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}/MinSizeRel/bin")
11+set(SIRIUS_USE_AVX2 "OFF" CACHE BOOL "Enable use of Intel AVX2 enhanced instructions")
1512
16-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/Debug/lib")
17-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release/lib")
18-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/RelWithDebInfo/lib")
19-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}/MinSizeRel/lib")
20-
21-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/Debug/lib")
22-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release/lib")
23-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/RelWithDebInfo/lib")
24-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}/MinSizeRel/lib")
13+if("${SIRIUS_USE_AVX2}")
14+ add_definitions(-DSIRIUS_X86_SIMD_LEVEL=SIRIUS_X86_SIMD_LEVEL_AVX2)
15+else()
16+ add_definitions(-DSIRIUS_X86_SIMD_LEVEL=SIRIUS_X86_SIMD_LEVEL_SSE42)
17+endif()
2518
2619 if(MSVC)
20+ if("${SIRIUS_USE_AVX2}")
21+ add_compile_options(/arch:AVX2)
22+ endif()
23+
2724 add_compile_options(/W4 /Zi /GS /fp:fast /permissive- /utf-8 /MP /Qspectre)
2825 add_compile_options(/wd4251) # class '%s' needs to have dll-interface to be used by clients of class '%s'
2926
@@ -40,7 +37,13 @@ if(MSVC)
4037 set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF /DEBUG:FASTLINK")
4138 set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF /DEBUG:FASTLINK")
4239 else()
43- add_compile_options(-Wall -Wextra -ffast-math -msse4.1)
40+ if("${SIRIUS_USE_AVX2}")
41+ add_definitions(-mavx2 -mfma)
42+ else()
43+ add_compile_options(-msse4.2)
44+ endif()
45+
46+ add_compile_options(-Wall -Wextra -ffast-math -msse4.2)
4447
4548 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
4649 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -flto")
--- a/include/sirius/renderer.hpp
+++ b/include/sirius/renderer.hpp
@@ -3,13 +3,7 @@
33
44 #pragma once
55
6-#include <cstddef>
7-#include <cstdint>
8-
9-#include <memory>
10-#include <string>
116 #include <string_view>
12-#include <vector>
137
148 #include "sirius/array_view.hpp"
159 #include "sirius/simpletypes.hpp"
@@ -17,214 +11,48 @@
1711 namespace Sirius
1812 {
1913
20-class Renderer;
21-class ChildRenderer;
22-
23-class RendererListener
14+enum class IconKind
2415 {
25-public:
26- virtual ~RendererListener() = default;
27-
28- virtual void OnCreateDevice(Renderer* /*pRenderer*/)
29- {
30- }
31-
32- virtual void OnDestroyDevice(Renderer* /*pRenderer*/)
33- {
34- }
35-
36- virtual void OnBeginDraw(Renderer* /*pRenderer*/)
37- {
38- }
39-
40- virtual void OnEndDraw(Renderer* /*pRenderer*/)
41- {
42- }
16+ Square,
17+ Circle,
18+ X,
19+ LeftTriangle,
20+ UpTriangle,
21+ RightTriangle,
22+ DownTriangle
4323 };
4424
45-class Paint
25+enum class FontStyle
4626 {
47-public:
48- Paint() = default;
49-
50- explicit Paint(const Color& c) : m_Color(c)
51- {
52- }
53-
54- Paint(const Color& c, float strokeWidth) : m_Color(c), m_StrokeWidth(strokeWidth)
55- {
56- }
57-
58- Paint(const Color& c, std::string_view fontName, float fontSize)
59- : m_Color(c), m_FontName(fontName), m_FontSize(fontSize)
60- {
61- }
62-
63- Paint(const Paint&) = default;
64- Paint& operator=(const Paint&) = default;
65- Paint(Paint&&) = default;
66- Paint& operator=(Paint&&) = default;
67- ~Paint() = default;
68-
69- const Color& GetColor() const
70- {
71- return m_Color;
72- }
73-
74- void SetColor(const Color& c)
75- {
76- m_Color = c;
77- }
78-
79- float GetStrokeWidth() const
80- {
81- return m_StrokeWidth;
82- }
83-
84- void SetStrokeWidth(float sw)
85- {
86- m_StrokeWidth = sw;
87- }
88-
89- std::string_view GetFontName() const
90- {
91- return m_FontName;
92- }
93-
94- void SetFontName(std::string_view fontName)
95- {
96- m_FontName = fontName;
97- }
98-
99- float GetFontSize() const
100- {
101- return m_FontSize;
102- }
103-
104- void SetFontSize(float fontSize)
105- {
106- m_FontSize = fontSize;
107- }
108-
109- float GetFontWeight() const
110- {
111- return m_FontWeight;
112- }
113-
114- void SetFontWeight(float weight)
115- {
116- m_FontWeight = weight;
117- }
118-
119- bool GetIsItalicFont() const
120- {
121- return m_IsItalicFont;
122- }
123-
124- void SetIsItalicFont(bool italic)
125- {
126- m_IsItalicFont = italic;
127- }
128-
129-private:
130- Color m_Color = {};
131- float m_StrokeWidth = 1.0f;
132- std::string m_FontName;
133- float m_FontSize = 12.0f;
134- float m_FontWeight = 1.0f;
135- bool m_IsItalicFont = false;
136-};
137-
138-enum class PixelFormat
139-{
140- A8R8G8B8
27+ Normal,
28+ Italic,
29+ Oblique
14130 };
14231
143-class Bitmap
32+enum class FontWeight
14433 {
145-public:
146- ~Bitmap() = default;
147-
148- virtual Vec2<std::uint32_t> GetSize() const = 0;
34+ Light,
35+ Regular,
36+ Bold
14937 };
15038
151-class SIRIUS_DLLEXPORT Renderer
39+class Renderer
15240 {
15341 public:
15442 virtual ~Renderer() = default;
15543
156- void BeginDraw();
157- void EndDraw();
44+ virtual void Translate(Vec2<float> v) = 0;
45+ virtual void PushClipRectAndOpacity(const Rect<float>& rect, float opacity) = 0;
46+ virtual void PopClipRectAndOpacity() = 0;
15847
15948 virtual void Clear(const Color& color) = 0;
160- virtual void DrawLine(Vec2<float> p1, Vec2<float> p2, const Paint& paint) = 0;
161- virtual void DrawRect(const Rect<float>& rect, const Paint& paint) = 0;
162- virtual void FillRect(const Rect<float>& rect, const Paint& paint) = 0;
163- virtual void DrawPolygon(ArrayView<Vec2<float>> points, const Paint& paint) = 0;
164- virtual void FillPolygon(ArrayView<Vec2<float>> points, const Paint& paint) = 0;
165-
166- virtual void DrawEllipse(const Rect<float>& boundRect, const Paint& paint) = 0;
167- void DrawEllipse(Vec2<float> center, float radiusX, float radiusY, const Paint& paint);
168- virtual void FillEllipse(const Rect<float>& boundRect, const Paint& paint) = 0;
169- void FillEllipse(Vec2<float> center, float radiusX, float radiusY, const Paint& paint);
170-
171- virtual void DrawArc(Vec2<float> center, float radius, float angleFrom, float angleTo, const Paint& paint) = 0;
172- virtual void FillArc(Vec2<float> center, float radius, float angleFrom, float angleTo, const Paint& paint) = 0;
173-
174- virtual void DrawBitmap(Bitmap* pBitmap, const Rect<float>& srcRect, const Rect<float>& destRect) = 0;
175- void DrawBitmap(const std::unique_ptr<Bitmap>& pBitmap, const Rect<float>& srcRect, const Rect<float>& destRect);
176-
177- virtual void DrawText(std::string_view text, const Rect<float>& rect, const Paint& paint) = 0;
178-
179- virtual Rect<float> GetClipRect() const = 0;
180- virtual void SetClipRect(const Rect<float>& rect) = 0;
181-
182- virtual Vec2<float> GetGlobalTranslation() const = 0;
183- virtual void SetGlobalTranslation(Vec2<float> globalTranslation) = 0;
184-
185- virtual std::unique_ptr<Bitmap> CreateBitmap(ArrayView<std::byte> buffer, Vec2<std::uint32_t> size, PixelFormat format) = 0;
186-
187- void AddListener(RendererListener* pListener);
188- void RemoveListener(RendererListener* pListener);
189- bool HasListener(RendererListener* pListener) const;
190-
191- void InvokeCreateDevice();
192- void InvokeDestroyDevice();
193-
194-protected:
195- virtual void OnBeginDraw()
196- {
197- }
198-
199- virtual void OnEndDraw()
200- {
201- }
202-
203-private:
204- std::vector<RendererListener*> m_Listeners;
205-};
206-
207-class AutoRestoreRendererStates
208-{
209-public:
210- explicit AutoRestoreRendererStates(Renderer& renderer)
211- : m_Renderer(renderer), m_OldClipRect(renderer.GetClipRect()), m_OldTranslation(renderer.GetGlobalTranslation())
212- {
213- }
214-
215- AutoRestoreRendererStates(const AutoRestoreRendererStates&) = delete;
216- AutoRestoreRendererStates& operator=(const AutoRestoreRendererStates&) = delete;
49+ virtual void DrawLine(Vec2<float> p0, Vec2<float> p1, float thickness, const Color& color) = 0;
50+ virtual void DrawRect(const Rect<float>& rect, float thickness, const Color& color) = 0;
51+ virtual void FillRect(const Rect<float>& rect, float thickness, const Color& color) = 0;
21752
218- ~AutoRestoreRendererStates()
219- {
220- m_Renderer.SetGlobalTranslation(m_OldTranslation);
221- m_Renderer.SetClipRect(m_OldClipRect);
222- }
53+ virtual void DrawIcon(IconKind icon, const Rect<float>& rect, const Color& foreColor, const Color& bgColor) = 0;
22354
224-private:
225- Renderer& m_Renderer;
226- Rect<float> m_OldClipRect;
227- Vec2<float> m_OldTranslation;
55+ virtual void DrawText(std::string_view text, const Rect<float>& rect, float fontSize, FontStyle fontStyle, FontWeight fontWeight, const Color& color) = 0;
22856 };
22957
23058 } // namespace Sirius
--- a/include/sirius/simpletypes.hpp
+++ b/include/sirius/simpletypes.hpp
@@ -162,6 +162,11 @@ struct Rect
162162 return Bottom - Top;
163163 }
164164
165+ constexpr Vec2<T> GetSize() const noexcept
166+ {
167+ return Vec2<T>(GetWidth(), GetHeight());
168+ }
169+
165170 constexpr Vec2<T> GetLeftTop() const noexcept
166171 {
167172 return Vec2<T>(Left, Top);
--- a/include/sirius/widget.hpp
+++ b/include/sirius/widget.hpp
@@ -8,6 +8,9 @@
88 #include <chrono>
99 #include <future>
1010 #include <memory>
11+#include <string>
12+#include <string_view>
13+#include <variant>
1114 #include <vector>
1215
1316 #include "sirius/event.hpp"
@@ -20,6 +23,87 @@ class UIManager;
2023 class Widget;
2124 class Renderer;
2225
26+enum class PointerKind
27+{
28+ Unknown,
29+ Mouse,
30+ Touch,
31+ Pen
32+};
33+
34+enum class MouseButtonKind
35+{
36+ Primary,
37+ Left = Primary,
38+ Secondary,
39+ Right = Secondary,
40+ Middle
41+};
42+
43+struct ModifierKeyState
44+{
45+ bool Alt : 1;
46+ bool Ctrl : 1;
47+ bool Shift : 1;
48+};
49+
50+enum class SpecialKey
51+{
52+ Enter,
53+ Esc,
54+ Up,
55+ Down,
56+ Left,
57+ Right,
58+ PageUp,
59+ PageDown,
60+ Home,
61+ End,
62+ Tab,
63+ Delete,
64+ BackSpace,
65+ Insert,
66+ F1,
67+ F2,
68+ F3,
69+ F4,
70+ F5,
71+ F6,
72+ F7,
73+ F8,
74+ F9,
75+ F10,
76+ F11,
77+ F12
78+};
79+
80+struct GravityDirection
81+{
82+ GravityDirection() : Left(true), Top(true), Right(false), Bottom(false)
83+ {
84+ }
85+
86+ GravityDirection(bool left, bool top, bool right, bool bottom)
87+ : Left(left), Top(top), Right(right), Bottom(bottom)
88+ {
89+ }
90+
91+ bool operator==(const GravityDirection& rhs) const
92+ {
93+ return Left == rhs.Left && Top == rhs.Top && Right == rhs.Right && Bottom == rhs.Bottom;
94+ }
95+
96+ bool operator!=(const GravityDirection& rhs) const
97+ {
98+ return !(*this == rhs);
99+ }
100+
101+ bool Left : 1;
102+ bool Top : 1;
103+ bool Right : 1;
104+ bool Bottom : 1;
105+};
106+
23107 namespace WidgetEvent
24108 {
25109
@@ -41,10 +125,14 @@ enum : EventID
41125 // Argument: ChildWidgetEventArgs
42126 ChildRemove,
43127
44- // widget's rect was changed
128+ // widget's rect has changed
45129 // Argument: none
46130 RectChanged,
47131
132+ // widget's child offset has changed
133+ // Argument: none
134+ ChildOffsetChanged,
135+
48136 // widget's opacity was changed
49137 // Argument: none
50138 OpacityChanged,
@@ -59,11 +147,39 @@ enum : EventID
59147
60148 // widget has gained focus
61149 // Argument: none
62- FocusSet,
150+ GotFocus,
63151
64152 // widget has lost focus
65153 // Argument: none
66- FocusKilled
154+ LostFocus,
155+
156+ // pointer was pressed
157+ // Argument: PointerEventArgs
158+ PointerDown,
159+
160+ // pointer was released
161+ // Argument: PointerEventArgs
162+ PointerUp,
163+
164+ // pointer was moved
165+ // Argument: PointerEventArgs
166+ PointerMove,
167+
168+ // wheel was moved
169+ // Argument: WheelEventArgs
170+ Wheel,
171+
172+ // key was pressed
173+ // Argument: KeyEventArgs
174+ KeyDown,
175+
176+ // key was released
177+ // Argument: KeyEventArgs
178+ KeyUp,
179+
180+ // some text was entered
181+ // Argument: TextEventArgs
182+ Text
67183 };
68184
69185 struct ChildWidgetEventArgs : EventArgs
@@ -75,34 +191,37 @@ struct ChildWidgetEventArgs : EventArgs
75191 std::weak_ptr<Widget> pChildWidget;
76192 };
77193
78-} // namespace WidgetEvent
79-
80-struct ModifierKeyState
194+struct PointerEventArgs : EventArgs
81195 {
82- bool Alt : 1;
83- bool Ctrl : 1;
84- bool Shift : 1;
196+ PointerKind Kind = PointerKind::Unknown;
197+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> ID;
198+ Vec2<float> Position;
199+ float Pressure = 1.0f;
200+ Vec2<float> Tilt;
201+ ModifierKeyState ModifierKeys{};
85202 };
86203
87-struct MouseButtonState
204+struct WheelEventArgs : EventArgs
88205 {
89- bool Left : 1;
90- bool Right : 1;
91- bool Middle : 1;
206+ Vec2<float> Position;
207+ Vec2<float> Delta;
208+ ModifierKeyState ModifierKeys{};
92209 };
93210
94-enum class MouseButtonKind
211+struct KeyEventArgs : EventArgs
95212 {
96- Left,
97- Right,
98- Middle
213+ std::variant<SpecialKey, char32_t> Key = U'\0';
214+ ModifierKeyState ModifierKeys{};
99215 };
100216
101-enum class SpecialKey
217+struct TextEventArgs : EventArgs
102218 {
103- Enter
219+ std::string Text;
220+ ModifierKeyState ModifierKeys{};
104221 };
105222
223+} // namespace WidgetEvent
224+
106225 class SIRIUS_DLLEXPORT Widget : public EventHandler, public std::enable_shared_from_this<Widget>, public EventInvokeUtility<Widget>
107226 {
108227 public:
@@ -141,9 +260,9 @@ public:
141260
142261 std::weak_ptr<Widget> GetRoot();
143262
144- std::shared_ptr<Widget> GetChild(std::size_t i) const
263+ std::shared_ptr<Widget> GetChild(std::size_t index) const
145264 {
146- return m_Children[i];
265+ return m_Children[index];
147266 }
148267
149268 std::size_t GetChildCount() const
@@ -151,9 +270,14 @@ public:
151270 return m_Children.size();
152271 }
153272
154- void AddChild(std::shared_ptr<Widget> pWidget);
155- void AddChild(std::shared_ptr<Widget> pWidget, Widget* pWInsertBeforeThisWidget);
156- void RemoveChild(Widget* pChild);
273+ std::vector<std::shared_ptr<Widget>> GetAllChildren() const
274+ {
275+ return m_Children;
276+ }
277+
278+ void AddChild(const std::shared_ptr<Widget>& pWidget);
279+ void AddChild(const std::shared_ptr<Widget>& pWidget, const std::shared_ptr<Widget>& pInsertBeforeThisWidget);
280+ void RemoveChild(const std::shared_ptr<Widget>& pChild);
157281
158282 // widget state
159283
@@ -177,8 +301,35 @@ public:
177301 return m_Rect;
178302 }
179303
304+ Vec2<float> GetPosition() const
305+ {
306+ return m_Rect.GetLeftTop();
307+ }
308+
309+ Vec2<float> GetSize() const
310+ {
311+ return m_Rect.GetSize();
312+ }
313+
180314 void SetRect(const Rect<float>& rect);
181315
316+ Vec2<float> GetChildOffset() const
317+ {
318+ return m_ChildOffset;
319+ }
320+
321+ void SetChildOffset(Vec2<float> offset);
322+
323+ bool GetAutoUpdateChildLayout() const
324+ {
325+ return !m_Flags.NoAutoUpdateChildLayout;
326+ }
327+
328+ void SetAutoUpdateChildLayout(bool b)
329+ {
330+ m_Flags.NoAutoUpdateChildLayout = !b;
331+ }
332+
182333 float GetOpacity() const
183334 {
184335 return m_Opacity;
@@ -186,6 +337,16 @@ public:
186337
187338 void SetOpacity(float opacity);
188339
340+ GravityDirection GetGravity() const
341+ {
342+ return m_Gravity;
343+ }
344+
345+ void SetGravity(const GravityDirection& g)
346+ {
347+ m_Gravity = g;
348+ }
349+
189350 bool GetWantFocus() const
190351 {
191352 return m_Flags.WantFocus;
@@ -213,41 +374,91 @@ public:
213374 bool IsFocused() const;
214375 bool SetFocus();
215376
216- // pt is in parent's coordinate
217- virtual std::shared_ptr<Widget> FindWidgetAt(Vec2<float> pt);
377+ // converts position (relative to this widget) to posiiton relative to the root widget
378+ Vec2<float> ConvertPosToRoot(Vec2<float> relativeToThis) const;
218379
219- virtual void InvokeRender(Renderer& renderer, bool renderFrontToBack = false);
380+ // converts position (relative to the root widget) to posiiton relative to this widget
381+ Vec2<float> ConvertPosFromRoot(Vec2<float> relativeToRoot) const;
382+
383+ // pos is relative to this widget
384+ virtual std::shared_ptr<Widget> FindWidgetAt(Vec2<float> pos);
385+ virtual std::shared_ptr<Widget> FindChildAt(Vec2<float> pos);
386+
387+ virtual void InvokeRender(Renderer& renderer);
220388 virtual void OnRender(Renderer& renderer);
221389
222390 // pt is in root coordinates
223- bool InvokeMouseDown(Vec2<float> pt, MouseButtonKind mouseButtonKind, ModifierKeyState modifierKeyState);
224- bool InvokeMouseUp(Vec2<float> pt, MouseButtonKind mouseButtonKind, ModifierKeyState modifierKeyState);
225- bool InvokeMouseMove(Vec2<float> pt, MouseButtonState mouseButtonState, ModifierKeyState modifierKeyState);
226-
227- bool InvokeTouchDown(std::uintptr_t id, Vec2<float> pt, ModifierKeyState modifierKeyState);
228- bool InvokeTouchUp(std::uintptr_t id, Vec2<float> pt, ModifierKeyState modifierKeyState);
229- bool InvokeTouchMove(std::uintptr_t id, Vec2<float> pt, ModifierKeyState modifierKeyState);
230- void InvokeTouchCancel(std::uintptr_t id);
231-
232- bool InvokePenDown(std::uintptr_t id, Vec2<float> pt, float pressure, float tiltX, float tiltY, MouseButtonKind mouseButtonKind, ModifierKeyState modifierKeyState);
233- bool InvokePenUp(std::uintptr_t id, Vec2<float> pt, float pressure, float tiltX, float tiltY, MouseButtonKind mouseButtonKind, ModifierKeyState modifierKeyState);
234- bool InvokePenMove(std::uintptr_t id, Vec2<float> pt, float pressure, float tiltX, float tiltY, MouseButtonState mouseButtonState, ModifierKeyState modifierKeyState);
235- void InvokePenCancel(std::uintptr_t id);
236-
237- bool InvokeWheel(Vec2<float> pt, float deltaX, float deltaY, ModifierKeyState modifierKeyState);
238- bool InvokeKeyDown(SpecialKey key, ModifierKeyState modifierKeyState);
239- bool InvokeKeyDown(char32_t key, ModifierKeyState modifierKeyState);
240- bool InvokeKeyUp(SpecialKey key, ModifierKeyState modifierKeyState);
241- bool InvokeKeyUp(char32_t key, ModifierKeyState modifierKeyState);
391+ void InvokePointerDown(
392+ PointerKind kind,
393+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
394+ Vec2<float> pt,
395+ ModifierKeyState modifierKeyState
396+ );
397+
398+ void InvokePointerDown(
399+ PointerKind kind,
400+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
401+ Vec2<float> pt,
402+ float pressure,
403+ Vec2<float> tilt,
404+ ModifierKeyState modifierKeyState
405+ );
406+
407+ void InvokePointerUp(
408+ PointerKind kind,
409+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
410+ Vec2<float> pt,
411+ ModifierKeyState modifierKeyState
412+ );
413+
414+ void InvokePointerUp(
415+ PointerKind kind,
416+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
417+ Vec2<float> pt,
418+ float pressure,
419+ Vec2<float> tilt,
420+ ModifierKeyState modifierKeyState
421+ );
422+
423+ void InvokePointerMove(
424+ PointerKind kind,
425+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
426+ Vec2<float> pt,
427+ ModifierKeyState modifierKeyState
428+ );
429+
430+ void InvokePointerMove(
431+ PointerKind kind,
432+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
433+ Vec2<float> pt,
434+ float pressure,
435+ Vec2<float> tilt,
436+ ModifierKeyState modifierKeyState
437+ );
438+
439+ void InvokeWheel(Vec2<float> pt, Vec2<float> delta, ModifierKeyState modifierKeyState);
440+ void InvokeKeyDown(SpecialKey key, ModifierKeyState modifierKeyState);
441+ void InvokeKeyDown(char32_t key, ModifierKeyState modifierKeyState);
442+ void InvokeKeyUp(SpecialKey key, ModifierKeyState modifierKeyState);
443+ void InvokeKeyUp(char32_t key, ModifierKeyState modifierKeyState);
444+ void InvokeText(std::string_view text, ModifierKeyState modifierKeyState);
242445
243446 private:
447+ void AutoUpdateChildLayout(Vec2<float> deltaSize);
448+
244449 std::vector<std::shared_ptr<Widget>>::iterator FindChild(Widget* pWidget);
245450 std::vector<std::shared_ptr<Widget>>::const_iterator FindChild(Widget* pWidget) const;
246451
452+ // pt is in root coordinates
453+ std::shared_ptr<Widget> FindPointerTarget(Vec2<float> pos);
454+ std::shared_ptr<Widget> FindWheelTarget(Vec2<float> pos);
455+ std::shared_ptr<Widget> FindKeyTarget();
456+
247457 struct WidgetStateFlags
248458 {
249459 bool IsVisible : 1;
250460 bool IsEnabled : 1;
461+ bool NoAutoUpdateChildLayout : 1;
251462 bool WantFocus : 1;
252463 bool IsFocusable : 1;
253464 };
@@ -256,8 +467,10 @@ private:
256467
257468 std::weak_ptr<Widget> m_pParent;
258469 std::vector<std::shared_ptr<Widget>> m_Children; // sorted in front to back order
470+ GravityDirection m_Gravity;
259471
260- Rect<float> m_Rect = {0.0f, 0.0f, 0.0f, 0.0f}; // in parent's coordinates
472+ Rect<float> m_Rect; // in parent's coordinates
473+ Vec2<float> m_ChildOffset;
261474 float m_Opacity = 1.0f; // [0.0f, 1.0f]
262475 WidgetStateFlags m_Flags = {};
263476 };
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -12,9 +12,9 @@ add_library(
1212 ../include/sirius/simpletypes.hpp
1313 ../include/sirius/uimanager.hpp
1414 ../include/sirius/widget.hpp
15+
1516 animation.cpp
1617 event.cpp
17- renderer.cpp
1818 widget.cpp
1919 )
2020
--- a/src/renderer.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
1-// Copyright 2018 Starg
2-// Distributed under the 3-Clause BSD License.
3-
4-#include "sirius/renderer.hpp"
5-
6-#include <cassert>
7-
8-#include <algorithm>
9-
10-namespace Sirius
11-{
12-
13-void Renderer::BeginDraw()
14-{
15- OnBeginDraw();
16-
17- for (auto&& p : m_Listeners)
18- {
19- p->OnBeginDraw(this);
20- }
21-}
22-
23-void Renderer::EndDraw()
24-{
25- for (auto&& p : m_Listeners)
26- {
27- p->OnEndDraw(this);
28- }
29-
30- OnEndDraw();
31-}
32-
33-void Renderer::AddListener(RendererListener* pListener)
34-{
35- assert(!HasListener(pListener));
36- m_Listeners.push_back(pListener);
37-}
38-
39-void Renderer::RemoveListener(RendererListener* pListener)
40-{
41- auto it = std::find(m_Listeners.begin(), m_Listeners.end(), pListener);
42-
43- if (it != m_Listeners.end())
44- {
45- m_Listeners.erase(it);
46- }
47-}
48-
49-bool Renderer::HasListener(RendererListener* pListener) const
50-{
51- auto it = std::find(m_Listeners.begin(), m_Listeners.end(), pListener);
52- return it != m_Listeners.end();
53-}
54-
55-void Renderer::InvokeCreateDevice()
56-{
57- for (auto&& p : m_Listeners)
58- {
59- p->OnCreateDevice(this);
60- }
61-}
62-
63-void Renderer::InvokeDestroyDevice()
64-{
65- for (auto&& p : m_Listeners)
66- {
67- p->OnDestroyDevice(this);
68- }
69-}
70-
71-void Renderer::DrawEllipse(Vec2<float> center, float radiusX, float radiusY, const Paint& paint)
72-{
73- DrawEllipse(
74- Rect<float>::FromPoints(Vec2<float>(center.X - radiusX, center.Y - radiusY), Vec2<float>(center.X + radiusX, center.Y + radiusY)),
75- paint
76- );
77-}
78-
79-void Renderer::FillEllipse(Vec2<float> center, float radiusX, float radiusY, const Paint& paint)
80-{
81- FillEllipse(
82- Rect<float>::FromPoints(Vec2<float>(center.X - radiusX, center.Y - radiusY), Vec2<float>(center.X + radiusX, center.Y + radiusY)),
83- paint
84- );
85-}
86-
87-void Renderer::DrawBitmap(const std::unique_ptr<Bitmap>& pBitmap, const Rect<float>& srcRect, const Rect<float>& destRect)
88-{
89- DrawBitmap(pBitmap.get(), srcRect, destRect);
90-}
91-
92-} // namespace Sirius
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -32,12 +32,12 @@ std::weak_ptr<Widget> Widget::GetRoot()
3232 return p;
3333 }
3434
35-void Widget::AddChild(std::shared_ptr<Widget> pWidget)
35+void Widget::AddChild(const std::shared_ptr<Widget>& pWidget)
3636 {
37- AddChild(std::move(pWidget), m_Children.empty() ? nullptr : m_Children.front().get());
37+ AddChild(pWidget, m_Children.empty() ? nullptr : m_Children.front());
3838 }
3939
40-void Widget::AddChild(std::shared_ptr<Widget> pWidget, Widget* pInsertBeforeThisWidget)
40+void Widget::AddChild(const std::shared_ptr<Widget>& pWidget, const std::shared_ptr<Widget>& pInsertBeforeThisWidget)
4141 {
4242 if (!pWidget)
4343 {
@@ -46,7 +46,7 @@ void Widget::AddChild(std::shared_ptr<Widget> pWidget, Widget* pInsertBeforeThis
4646
4747 if (pInsertBeforeThisWidget)
4848 {
49- auto it = FindChild(pInsertBeforeThisWidget);
49+ auto it = FindChild(pInsertBeforeThisWidget.get());
5050
5151 if (it == m_Children.end())
5252 {
@@ -61,23 +61,23 @@ void Widget::AddChild(std::shared_ptr<Widget> pWidget, Widget* pInsertBeforeThis
6161 }
6262
6363 pWidget->m_pParent = weak_from_this();
64- pWidget->InvokeEvent(WidgetEvent::Added, nullptr);
64+ pWidget->InvokeEvent(WidgetEvent::Added);
6565
6666 InvokeEvent(WidgetEvent::ChildAdded, WidgetEvent::ChildWidgetEventArgs(pWidget));
6767 }
6868
69-void Widget::RemoveChild(Widget* pChild)
69+void Widget::RemoveChild(const std::shared_ptr<Widget>& pChild)
7070 {
71- if (!pChild || FindChild(pChild) == m_Children.end())
71+ if (!pChild || FindChild(pChild.get()) == m_Children.end())
7272 {
7373 throw std::invalid_argument("Sirius::Widget::RemoveChild() : pWChild is not a child of this widget");
7474 }
7575
76- InvokeEvent(WidgetEvent::ChildRemove, WidgetEvent::ChildWidgetEventArgs(pChild->weak_from_this()));
77- pChild->InvokeEvent(WidgetEvent::Remove, nullptr);
76+ InvokeEvent(WidgetEvent::ChildRemove, WidgetEvent::ChildWidgetEventArgs(pChild));
77+ pChild->InvokeEvent(WidgetEvent::Remove);
7878
7979 // ChildRemove/Remove events might have added/removed another widget, so we have to find the child again.
80- auto it = FindChild(pChild);
80+ auto it = FindChild(pChild.get());
8181
8282 if (it != m_Children.end())
8383 {
@@ -92,7 +92,7 @@ void Widget::SetIsVisible(bool b)
9292 if (m_Flags.IsVisible != b)
9393 {
9494 m_Flags.IsVisible = b;
95- InvokeEvent(WidgetEvent::VisibilityChanged, nullptr);
95+ InvokeEvent(WidgetEvent::VisibilityChanged);
9696 }
9797 }
9898
@@ -101,16 +101,31 @@ void Widget::SetIsEnabled(bool b)
101101 if (m_Flags.IsEnabled != b)
102102 {
103103 m_Flags.IsEnabled = b;
104- InvokeEvent(WidgetEvent::EnabledOrDisabled, nullptr);
104+ InvokeEvent(WidgetEvent::EnabledOrDisabled);
105105 }
106106 }
107107
108108 void Widget::SetRect(const Rect<float>& rect)
109109 {
110- if (m_Rect != rect)
110+ auto oldRect = std::exchange(m_Rect, rect);
111+
112+ if (oldRect != rect)
113+ {
114+ InvokeEvent(WidgetEvent::RectChanged);
115+ }
116+
117+ if (oldRect.GetSize() != rect.GetSize())
118+ {
119+ AutoUpdateChildLayout(rect.GetSize() - oldRect.GetSize());
120+ }
121+}
122+
123+void Widget::SetChildOffset(Vec2<float> offset)
124+{
125+ if (m_ChildOffset != offset)
111126 {
112- m_Rect = rect;
113- InvokeEvent(WidgetEvent::RectChanged, nullptr);
127+ m_ChildOffset = offset;
128+ InvokeEvent(WidgetEvent::ChildOffsetChanged);
114129 }
115130 }
116131
@@ -121,7 +136,7 @@ void Widget::SetOpacity(float opacity)
121136 if (m_Opacity != clampedOpacity)
122137 {
123138 m_Opacity = clampedOpacity;
124- InvokeEvent(WidgetEvent::OpacityChanged, nullptr);
139+ InvokeEvent(WidgetEvent::OpacityChanged);
125140 }
126141 }
127142
@@ -152,64 +167,99 @@ bool Widget::SetFocus()
152167
153168 if (pOldFocus)
154169 {
155- pOldFocus->InvokeEvent(WidgetEvent::FocusKilled);
170+ pOldFocus->InvokeEvent(WidgetEvent::LostFocus);
156171 }
157172
158- InvokeEvent(WidgetEvent::FocusSet);
173+ InvokeEvent(WidgetEvent::GotFocus);
159174 GetUIManager().SetFocusedWidget(pWThis);
160175 return true;
161176 }
162177
163-std::shared_ptr<Widget> Widget::FindWidgetAt(Vec2<float> pt)
178+Vec2<float> Widget::ConvertPosToRoot(Vec2<float> relativeToThis) const
164179 {
165- auto rect = GetRect();
180+ if (auto pParent = m_pParent.lock())
181+ {
182+ return pParent->ConvertPosToRoot(GetPosition() + pParent->GetChildOffset() + relativeToThis);
183+ }
184+ else
185+ {
186+ return GetPosition() + relativeToThis;
187+ }
188+}
189+
190+Vec2<float> Widget::ConvertPosFromRoot(Vec2<float> relativeToRoot) const
191+{
192+ if (auto pParent = m_pParent.lock())
193+ {
194+ return pParent->ConvertPosFromRoot(relativeToRoot) - pParent->GetChildOffset() - GetPosition();
195+ }
196+ else
197+ {
198+ return relativeToRoot - GetPosition();
199+ }
200+}
166201
167- if (rect.Includes(pt))
202+std::shared_ptr<Widget> Widget::FindWidgetAt(Vec2<float> pos)
203+{
204+ if (!GetIsVisible())
168205 {
169- Vec2<float> childPoint(pt.X - rect.Left, pt.Y - rect.Top);
206+ return nullptr;
207+ }
170208
171- for (auto&& pChild : m_Children)
209+ if (0 <= pos.X && pos.X <= GetSize().X && 0 <= pos.Y && pos.Y <= GetSize().Y)
210+ {
211+ if (auto p = FindChildAt(pos))
172212 {
173- if (auto pAt = pChild->FindWidgetAt(childPoint))
174- {
175- return pAt;
176- }
213+ return p;
177214 }
215+ else
216+ {
217+ return shared_from_this();
218+ }
219+ }
220+ else
221+ {
222+ return nullptr;
223+ }
224+}
178225
179- return shared_from_this();
226+std::shared_ptr<Widget> Widget::FindChildAt(Vec2<float> pos)
227+{
228+ for (auto&& p : m_Children)
229+ {
230+ if (auto pChild = p->FindWidgetAt(pos + GetChildOffset() + p->GetPosition()))
231+ {
232+ return pChild;
233+ }
180234 }
181235
182236 return nullptr;
183237 }
184238
185-void Widget::InvokeRender(Renderer& renderer, bool renderFrontToBack /* = false */)
239+void Widget::InvokeRender(Renderer& renderer)
186240 {
187- auto pParent = m_pParent.lock();
188- assert(renderer.GetGlobalTranslation() == (pParent ? pParent->m_Rect.GetLeftTop() : Vec2<float>(0, 0)));
189-
190241 if (GetIsVisible())
191242 {
192- AutoRestoreRendererStates arrs(renderer);
193- Rect<float> rect = GetRect();
194- Rect<float> oldClipRect = renderer.GetClipRect();
195- renderer.SetClipRect(oldClipRect.Clip(rect.Translate(oldClipRect.GetLeftTop())));
196- renderer.SetGlobalTranslation(renderer.GetGlobalTranslation() + Vec2<float>(rect.Left, rect.Top));
243+ auto rect = GetRect();
244+ auto childOffset = GetChildOffset();
245+ renderer.PushClipRectAndOpacity(rect, GetOpacity());
246+ renderer.Translate(rect.GetLeftTop());
197247
198- auto renderChild = [&renderer, renderFrontToBack] (auto&& pWidget)
199- {
200- pWidget->InvokeRender(renderer, renderFrontToBack);
201- };
248+ OnRender(renderer);
202249
203- if (renderFrontToBack)
204- {
205- std::for_each(m_Children.begin(), m_Children.end(), renderChild);
206- OnRender(renderer);
207- }
208- else
209- {
210- OnRender(renderer);
211- std::for_each(m_Children.rbegin(), m_Children.rend(), renderChild);
212- }
250+ renderer.Translate(childOffset);
251+
252+ std::for_each(
253+ m_Children.rbegin(),
254+ m_Children.rend(),
255+ [&renderer] (auto&& pWidget)
256+ {
257+ pWidget->InvokeRender(renderer);
258+ }
259+ );
260+
261+ renderer.Translate(-(childOffset + rect.GetLeftTop()));
262+ renderer.PopClipRectAndOpacity();
213263 }
214264 }
215265
@@ -217,6 +267,246 @@ void Widget::OnRender(Renderer&)
217267 {
218268 }
219269
270+void Widget::InvokePointerDown(
271+ PointerKind kind,
272+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
273+ Vec2<float> pt,
274+ ModifierKeyState modifierKeyState
275+)
276+{
277+ InvokePointerDown(kind, id, pt, 1.0f, {}, modifierKeyState);
278+}
279+
280+void Widget::InvokePointerDown(
281+ PointerKind kind,
282+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
283+ Vec2<float> pt,
284+ float pressure,
285+ Vec2<float> tilt,
286+ ModifierKeyState modifierKeyState
287+)
288+{
289+ if (auto pWidget = FindPointerTarget(pt))
290+ {
291+ // pWidget->SetCapture();
292+ WidgetEvent::PointerEventArgs args;
293+ args.Kind = kind;
294+ args.ID = id;
295+ args.Position = pt;
296+ args.Pressure = pressure;
297+ args.Tilt = tilt;
298+ args.ModifierKeys = modifierKeyState;
299+
300+ pWidget->InvokeEvent(WidgetEvent::PointerDown, args);
301+ }
302+}
303+
304+void Widget::InvokePointerUp(
305+ PointerKind kind,
306+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
307+ Vec2<float> pt,
308+ ModifierKeyState modifierKeyState
309+)
310+{
311+ InvokePointerUp(kind, id, pt, 1.0f, {}, modifierKeyState);
312+}
313+
314+void Widget::InvokePointerUp(
315+ PointerKind kind,
316+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
317+ Vec2<float> pt,
318+ float pressure,
319+ Vec2<float> tilt,
320+ ModifierKeyState modifierKeyState
321+)
322+{
323+ if (auto pWidget = FindPointerTarget(pt))
324+ {
325+ // pWidget->ReleaseCapture();
326+ WidgetEvent::PointerEventArgs args;
327+ args.Kind = kind;
328+ args.ID = id;
329+ args.Position = pt;
330+ args.Pressure = pressure;
331+ args.Tilt = tilt;
332+ args.ModifierKeys = modifierKeyState;
333+
334+ pWidget->InvokeEvent(WidgetEvent::PointerUp, args);
335+ }
336+}
337+
338+void Widget::InvokePointerMove(
339+ PointerKind kind,
340+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
341+ Vec2<float> pt,
342+ ModifierKeyState modifierKeyState
343+)
344+{
345+ InvokePointerMove(kind, id, pt, 1.0f, {}, modifierKeyState);
346+}
347+
348+void Widget::InvokePointerMove(
349+ PointerKind kind,
350+ std::variant<std::monostate, MouseButtonKind, std::intptr_t> id,
351+ Vec2<float> pt,
352+ float pressure,
353+ Vec2<float> tilt,
354+ ModifierKeyState modifierKeyState
355+)
356+{
357+ if (auto pWidget = FindPointerTarget(pt))
358+ {
359+ WidgetEvent::PointerEventArgs args;
360+ args.Kind = kind;
361+ args.ID = id;
362+ args.Position = pt;
363+ args.Pressure = pressure;
364+ args.Tilt = tilt;
365+ args.ModifierKeys = modifierKeyState;
366+
367+ pWidget->InvokeEvent(WidgetEvent::PointerMove, args);
368+ }
369+}
370+
371+void Widget::InvokeWheel(Vec2<float> pt, Vec2<float> delta, ModifierKeyState modifierKeyState)
372+{
373+ if (auto pWidget = FindWheelTarget(pt))
374+ {
375+ WidgetEvent::WheelEventArgs args;
376+ args.Position = pt;
377+ args.Delta = delta;
378+ args.ModifierKeys = modifierKeyState;
379+
380+ pWidget->InvokeEvent(WidgetEvent::Wheel, args);
381+ }
382+}
383+
384+void Widget::InvokeKeyDown(SpecialKey key, ModifierKeyState modifierKeyState)
385+{
386+ if (auto pWidget = FindKeyTarget())
387+ {
388+ WidgetEvent::KeyEventArgs args;
389+ args.Key = key;
390+ args.ModifierKeys = modifierKeyState;
391+
392+ pWidget->InvokeEvent(WidgetEvent::KeyDown, args);
393+ }
394+}
395+
396+void Widget::InvokeKeyDown(char32_t key, ModifierKeyState modifierKeyState)
397+{
398+ if (auto pWidget = FindKeyTarget())
399+ {
400+ WidgetEvent::KeyEventArgs args;
401+ args.Key = key;
402+ args.ModifierKeys = modifierKeyState;
403+
404+ pWidget->InvokeEvent(WidgetEvent::KeyDown, args);
405+ }
406+}
407+
408+void Widget::InvokeKeyUp(SpecialKey key, ModifierKeyState modifierKeyState)
409+{
410+ if (auto pWidget = FindKeyTarget())
411+ {
412+ WidgetEvent::KeyEventArgs args;
413+ args.Key = key;
414+ args.ModifierKeys = modifierKeyState;
415+
416+ pWidget->InvokeEvent(WidgetEvent::KeyUp, args);
417+ }
418+}
419+
420+void Widget::InvokeKeyUp(char32_t key, ModifierKeyState modifierKeyState)
421+{
422+ if (auto pWidget = FindKeyTarget())
423+ {
424+ WidgetEvent::KeyEventArgs args;
425+ args.Key = key;
426+ args.ModifierKeys = modifierKeyState;
427+
428+ pWidget->InvokeEvent(WidgetEvent::KeyUp, args);
429+ }
430+}
431+
432+void Widget::InvokeText(std::string_view text, ModifierKeyState modifierKeyState)
433+{
434+ if (auto pWidget = FindKeyTarget())
435+ {
436+ WidgetEvent::TextEventArgs args;
437+ args.Text = text;
438+ args.ModifierKeys = modifierKeyState;
439+
440+ pWidget->InvokeEvent(WidgetEvent::Text, args);
441+ }
442+}
443+
444+void Widget::AutoUpdateChildLayout(Vec2<float> deltaSize)
445+{
446+ if (GetAutoUpdateChildLayout())
447+ {
448+ auto children = m_Children;
449+
450+ for (auto&& p : children)
451+ {
452+ auto rect = p->GetRect();
453+ auto g = p->GetGravity();
454+
455+ if (g.Left)
456+ {
457+ if (g.Right)
458+ {
459+ rect.Right += deltaSize.X;
460+ }
461+ else
462+ {
463+ // do nothing
464+ }
465+ }
466+ else
467+ {
468+ if (g.Right)
469+ {
470+ rect.Left += deltaSize.X;
471+ rect.Right += deltaSize.X;
472+ }
473+ else
474+ {
475+ rect.Left += deltaSize.X / 2.0f;
476+ rect.Right += deltaSize.X / 2.0f;
477+ }
478+ }
479+
480+ if (g.Top)
481+ {
482+ if (g.Bottom)
483+ {
484+ rect.Bottom += deltaSize.Y;
485+ }
486+ else
487+ {
488+ // do nothing
489+ }
490+ }
491+ else
492+ {
493+ if (g.Bottom)
494+ {
495+ rect.Top += deltaSize.Y;
496+ rect.Bottom += deltaSize.Y;
497+ }
498+ else
499+ {
500+ rect.Top += deltaSize.Y / 2.0f;
501+ rect.Bottom += deltaSize.Y / 2.0f;
502+ }
503+ }
504+
505+ p->SetRect(rect);
506+ }
507+ }
508+}
509+
220510 std::vector<std::shared_ptr<Widget>>::iterator Widget::FindChild(Widget* pWidget)
221511 {
222512 return std::find_if(
@@ -241,4 +531,33 @@ std::vector<std::shared_ptr<Widget>>::const_iterator Widget::FindChild(Widget* p
241531 );
242532 }
243533
534+std::shared_ptr<Widget> Widget::FindPointerTarget(Vec2<float> pos)
535+{
536+ if (auto pCaptured = GetUIManager().GetCapturedWidget().lock())
537+ {
538+ return pCaptured;
539+ }
540+ else
541+ {
542+ return FindWidgetAt(ConvertPosFromRoot(pos));
543+ }
544+}
545+
546+std::shared_ptr<Widget> Widget::FindWheelTarget(Vec2<float> pos)
547+{
548+ return FindWidgetAt(ConvertPosFromRoot(pos));
549+}
550+
551+std::shared_ptr<Widget> Widget::FindKeyTarget()
552+{
553+ if (auto pFocused = GetUIManager().GetFocusedWidget().lock())
554+ {
555+ return pFocused;
556+ }
557+ else
558+ {
559+ return shared_from_this();
560+ }
561+}
562+
244563 } // namespace Sirius