FastEngine 0.9.3
A multiplayer oriented 2D engine made with Vulkan.
Loading...
Searching...
No Matches
C_guiElement.hpp
1/*
2 * Copyright 2024 Guillaume Guillet
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _FGE_C_GUIELEMENT_HPP_INCLUDED
18#define _FGE_C_GUIELEMENT_HPP_INCLUDED
19
20#include "FastEngine/fge_extern.hpp"
21#include "C_rect.hpp"
22#include "FastEngine/C_event.hpp"
23#include "FastEngine/C_tunnel.hpp"
24#include "FastEngine/graphic/C_renderTarget.hpp"
25#include <cstdint>
26
27#define FGE_GUI_ELEMENT_PRIORITY_LAST 0
28#define FGE_GUI_ELEMENT_PRIORITY_DEFAULT 50
29#define FGE_GUI_ELEMENT_PRIORITY_FIRST std::numeric_limits<fge::GuiElement::Priority>::max()
30#define FGE_SCENE_BAD_SID std::numeric_limits<fge::ObjectSid>::max()
31
32namespace fge
33{
34
35using ObjectSid = uint32_t;
36
37class ObjectData;
38using ObjectDataShared = std::shared_ptr<fge::ObjectData>;
39using ObjectDataWeak = std::weak_ptr<fge::ObjectData>;
40
41class GuiElement;
42class GuiElementHandler;
43
45{
46 fge::GuiElement* _prioritizedElement{nullptr};
47 bool _recursive{false};
48 std::size_t _index{0};
49 fge::Vector2f _mouseGuiPosition;
50 fge::Vector2i _mousePosition;
51 fge::GuiElementHandler* _handler{nullptr};
52 std::vector<fge::ObjectDataShared>* _keepAliveObject{nullptr};
53};
54
56{
57 enum class SizeModes
58 {
59 SIZE_FIXED,
60 SIZE_AUTO,
61 SIZE_DEFAULT = SIZE_AUTO
62 };
63
64 fge::Vector2f _fixedSize{0.0f, 0.0f};
65 fge::Vector2<fge::DynamicSize::SizeModes> _sizeMode{fge::DynamicSize::SizeModes::SIZE_DEFAULT,
66 fge::DynamicSize::SizeModes::SIZE_DEFAULT};
67 fge::Vector2f _offset{0.0f, 0.0f};
68
69 [[nodiscard]] inline fge::Vector2f getSize(fge::Vector2f const& position, fge::Vector2f const& targetSize) const
70 {
71 fge::Vector2f size{};
72
73 switch (this->_sizeMode.x)
74 {
75 case SizeModes::SIZE_FIXED:
76 size.x = this->_fixedSize.x;
77 break;
78 case SizeModes::SIZE_AUTO:
79 size.x = (targetSize.x - position.x) + this->_offset.x;
80 break;
81 default:
82 break;
83 }
84
85 switch (this->_sizeMode.y)
86 {
87 case SizeModes::SIZE_FIXED:
88 size.y = this->_fixedSize.y;
89 break;
90 case SizeModes::SIZE_AUTO:
91 size.y = (targetSize.y - position.y) + this->_offset.y;
92 break;
93 default:
94 break;
95 }
96
97 if (size.x < 0.0f)
98 {
99 size.x = 0.0f;
100 }
101 if (size.y < 0.0f)
102 {
103 size.y = 0.0f;
104 }
105
106 return size;
107 }
108};
109
119class FGE_API GuiElement
120{
121public:
122 using Priority = uint8_t;
123
124 GuiElement() = default;
125 explicit GuiElement(fge::GuiElement::Priority priority) :
126 _g_priority(priority)
127 {}
128 virtual ~GuiElement() = default;
129
137 [[nodiscard]] virtual bool isRecursive() const { return false; }
143 void setGuiScale(fge::Vector2f const& scale) { this->_g_scale = scale; }
149 [[nodiscard]] fge::Vector2f const& getGuiScale() const { return this->_g_scale; }
157 void setPriority(fge::GuiElement::Priority priority) const { this->_g_priority = priority; }
163 [[nodiscard]] fge::GuiElement::Priority getPriority() const { return this->_g_priority; }
172 [[nodiscard]] bool verifyPriority(fge::GuiElement* element) const
173 {
174 if (element == nullptr)
175 {
176 return true;
177 }
178 if (this->_g_priority > element->getPriority())
179 {
180 return true;
181 }
182 return false;
183 }
184
196 virtual void onGuiVerify(fge::Event const& evt, SDL_EventType evtType, fge::GuiElementContext& context) = 0;
197
206
207 static fge::CallbackHandler<fge::Vector2f const&> _onGlobalGuiScaleChange;
208 inline static void setGlobalGuiScale(fge::Vector2f const& scale)
209 {
210 fge::GuiElement::_GlobalGuiScale = scale;
211 fge::GuiElement::_onGlobalGuiScaleChange.call(scale);
212 }
213 inline static fge::Vector2f const& getGlobalGuiScale() { return fge::GuiElement::_GlobalGuiScale; }
214
215protected:
216 mutable fge::GuiElement::Priority _g_priority{FGE_GUI_ELEMENT_PRIORITY_DEFAULT};
217 fge::Vector2f _g_scale{1.0f, 1.0f};
218
219private:
220 static fge::Vector2f _GlobalGuiScale;
221};
222
224{
225public:
226 bool isRecursive() const final { return true; }
227};
228
234class FGE_API GuiElementHandler : public fge::Subscriber
235{
236public:
237 GuiElementHandler() = default;
238 GuiElementHandler(fge::Event& event, fge::RenderTarget const& target) :
239 g_event(&event),
240 g_target(&target)
241 {}
242 ~GuiElementHandler() override = default;
243
244 inline void setEvent(fge::Event& event) { this->g_event = &event; }
245 [[nodiscard]] inline fge::Event& getEvent() { return *this->g_event; }
246 [[nodiscard]] inline fge::Event const& getEvent() const { return *this->g_event; }
247 inline void setRenderTarget(fge::RenderTarget const& target) { this->g_target = &target; }
248 [[nodiscard]] inline fge::RenderTarget const& getRenderTarget() const { return *this->g_target; }
249
250 void setEventCallback();
251
252 void onMouseWheelScrolled(fge::Event const& evt, SDL_MouseWheelEvent const& arg);
253 void onMouseButtonPressed(fge::Event const& evt, SDL_MouseButtonEvent const& arg);
254 void onMouseButtonReleased(fge::Event const& evt, SDL_MouseButtonEvent const& arg);
255 void onMouseMoved(fge::Event const& evt, SDL_MouseMotionEvent const& arg);
256
257 void checkViewSize();
258
261 fge::Vector2f _lastSize{0.0f, 0.0f};
262
263private:
264 fge::Event* g_event{nullptr};
265 fge::RenderTarget const* g_target{nullptr};
266};
267
274{
275public:
276 GuiElementRectangle() = default;
277 GuiElementRectangle(fge::RectFloat const& rect, fge::GuiElement::Priority priority) :
278 fge::GuiElement(priority),
279 g_rect(rect)
280 {}
281 explicit GuiElementRectangle(fge::GuiElement::Priority priority) :
282 fge::GuiElement(priority)
283 {}
284 ~GuiElementRectangle() override = default;
285
286 void onGuiVerify([[maybe_unused]] fge::Event const& evt,
287 [[maybe_unused]] SDL_EventType evtType,
288 fge::GuiElementContext& context) override
289 {
290 if (this->verifyPriority(context._prioritizedElement))
291 {
292 fge::RectFloat rect{this->g_rect.getPosition(),
293 {this->g_rect._width * this->_g_scale.x, this->g_rect._height * this->_g_scale.y}};
294 if (rect.contains(context._mouseGuiPosition))
295 {
296 context._prioritizedElement = this;
297 }
298 }
299 }
300
301 void setRectangle(fge::RectFloat const& rect) { this->g_rect = rect; }
302 fge::RectFloat const& getRectangle() const { return this->g_rect; }
303
304private:
305 fge::RectFloat g_rect;
306};
307
314{
315public:
316 GuiElementDefault() = default;
317 explicit GuiElementDefault(fge::GuiElement::Priority priority) :
318 fge::GuiElement(priority)
319 {}
320 ~GuiElementDefault() override = default;
321
322 void onGuiVerify([[maybe_unused]] fge::Event const& evt,
323 [[maybe_unused]] SDL_EventType evtType,
324 fge::GuiElementContext& context) override
325 {
326 if (this->verifyPriority(context._prioritizedElement))
327 {
328 context._prioritizedElement = this;
329 }
330 }
331};
332
339{
340public:
341 GuiElementArray() = default;
342 explicit GuiElementArray(fge::GuiElement::Priority priority) :
343 fge::GuiElement(priority)
344 {}
345 ~GuiElementArray() override = default;
346
347 void onGuiVerify(fge::Event const& evt, SDL_EventType evtType, fge::GuiElementContext& context) override
348 {
349 if (context._recursive)
350 {
351 this->verifyRecursively(evt, evtType, context);
352 }
353 else
354 {
355 if (this->verifyPriority(context._prioritizedElement))
356 {
357 context._prioritizedElement = this;
358 }
359 }
360 }
361
363
364protected:
365 void verifyRecursively(fge::Event const& evt, SDL_EventType evtType, fge::GuiElementContext& context) const
366 {
367 fge::GuiElementContext context2{};
368 context2._mouseGuiPosition = context._mouseGuiPosition;
369 context2._mousePosition = context._mousePosition;
370 context2._handler = context._handler;
371 context2._keepAliveObject = context._keepAliveObject;
372
373 for (std::size_t i = 0; i < this->_elements.getGatesSize(); ++i)
374 {
375 context2._index = i;
376 this->_elements[i]->onGuiVerify(evt, evtType, context2);
377 }
378
379 if (context2._prioritizedElement != nullptr)
380 {
381 if (context2._prioritizedElement->isRecursive())
382 {
383 context2._recursive = true;
384 context2._prioritizedElement->onGuiVerify(evt, evtType, context2);
385 }
386 }
387
388 context._prioritizedElement = context2._prioritizedElement;
389 context._index = context2._index;
390 }
391};
392
393} // namespace fge
394
395#endif // _FGE_C_GUIELEMENT_HPP_INCLUDED
This class is used to handle callbacks in a safe way.
Definition C_callback.hpp:189
This class is a wrapper for SDL events.
Definition C_event.hpp:59
A GUI element that verify a list of GUI elements.
Definition C_guiElement.hpp:339
void onGuiVerify(fge::Event const &evt, SDL_EventType evtType, fge::GuiElementContext &context) override
Function called to verify if the element is hovered by the mouse.
Definition C_guiElement.hpp:347
A GUI element that does not any verification bounds of the mouse the mouse.
Definition C_guiElement.hpp:314
void onGuiVerify(fge::Event const &evt, SDL_EventType evtType, fge::GuiElementContext &context) override
Function called to verify if the element is hovered by the mouse.
Definition C_guiElement.hpp:322
A class to handle highest priority selection of GUI elements.
Definition C_guiElement.hpp:235
A GUI element that verify if the mouse is inside a rectangle.
Definition C_guiElement.hpp:274
void onGuiVerify(fge::Event const &evt, SDL_EventType evtType, fge::GuiElementContext &context) override
Function called to verify if the element is hovered by the mouse.
Definition C_guiElement.hpp:286
Definition C_guiElement.hpp:224
bool isRecursive() const final
Check if this GuiElement is recursive.
Definition C_guiElement.hpp:226
A base class for all GUI elements.
Definition C_guiElement.hpp:120
fge::Vector2f const & getGuiScale() const
Get the scale of the element.
Definition C_guiElement.hpp:149
fge::CallbackHandler< fge::Event const &, SDL_MouseMotionEvent const &, fge::GuiElementContext & > _onGuiMouseMoved
Callback called when the element is verified and the mouse is moved.
Definition C_guiElement.hpp:205
fge::CallbackHandler< fge::Event const &, SDL_MouseButtonEvent const &, fge::GuiElementContext & > _onGuiMouseButtonReleased
Callback called when the element is verified and a mouse button is released.
Definition C_guiElement.hpp:203
fge::CallbackHandler< fge::Event const &, SDL_MouseButtonEvent const &, fge::GuiElementContext & > _onGuiMouseButtonPressed
Callback called when the element is verified and the mouse is pressed.
Definition C_guiElement.hpp:201
virtual bool isRecursive() const
Check if this GuiElement is recursive.
Definition C_guiElement.hpp:137
void setPriority(fge::GuiElement::Priority priority) const
Set the priority of the element.
Definition C_guiElement.hpp:157
bool verifyPriority(fge::GuiElement *element) const
Verify if the priority of the element is higher than the given element.
Definition C_guiElement.hpp:172
fge::CallbackHandler< fge::Event const &, SDL_MouseWheelEvent const &, fge::GuiElementContext & > _onGuiMouseWheelScrolled
Callback called when the element is verified and the mouse wheel is scrolled.
Definition C_guiElement.hpp:199
virtual void onGuiVerify(fge::Event const &evt, SDL_EventType evtType, fge::GuiElementContext &context)=0
Function called to verify if the element is hovered by the mouse.
void setGuiScale(fge::Vector2f const &scale)
Set the scale of the element.
Definition C_guiElement.hpp:143
fge::GuiElement::Priority getPriority() const
Get the priority of the element.
Definition C_guiElement.hpp:163
Definition C_renderTarget.hpp:56
This class is a useful utility to "link" multiple objects around.
Definition C_subscription.hpp:150
Definition C_tunnel.hpp:30
Definition C_guiElement.hpp:56
Definition C_guiElement.hpp:45