Line data Source code
1 : /**
2 : Copyright (c) 2021 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef XENOLITH_SCENE_NODES_XLNODE_H_
25 : #define XENOLITH_SCENE_NODES_XLNODE_H_
26 :
27 : #include "XLNodeInfo.h"
28 : #include "XLComponent.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::xenolith {
31 :
32 : class Component;
33 : class Scene;
34 : class Scheduler;
35 : class InputListener;
36 : class Action;
37 : class ActionManager;
38 : class Director;
39 : class FrameContext;
40 :
41 : struct ActionStorage : public Ref {
42 : Vector<Rc<Action>> actionToStart;
43 :
44 : void addAction(Rc<Action> &&a);
45 : void removeAction(Action *a);
46 : void removeAllActions();
47 : void removeActionByTag(uint32_t);
48 : void removeAllActionsByTag(uint32_t);
49 : Action *getActionByTag(uint32_t);
50 : };
51 :
52 : class Node : public Ref {
53 : public:
54 : /* Nodes with transparent zOrder will not be added into zPath */
55 : static constexpr ZOrder ZOrderTransparent = ZOrder::min();
56 : static constexpr ZOrder ZOrderMax = ZOrder::max();
57 : static constexpr ZOrder ZOrderMin = ZOrder::min() + ZOrder(1);
58 :
59 : static bool isParent(Node *parent, Node *node);
60 : static Mat4 getChainNodeToParentTransform(Node *parent, Node *node, bool withParent);
61 : static Mat4 getChainParentToNodeTransform(Node *parent, Node *node, bool withParent);
62 :
63 : Node();
64 : virtual ~Node();
65 :
66 : virtual bool init();
67 :
68 : virtual void setLocalZOrder(ZOrder localZOrder);
69 142254 : virtual ZOrder getLocalZOrder() const { return _zOrder; }
70 :
71 : virtual void setScale(float scale);
72 : virtual void setScale(const Vec2 &);
73 : virtual void setScale(const Vec3 &);
74 : virtual void setScaleX(float scaleX);
75 : virtual void setScaleY(float scaleY);
76 : virtual void setScaleZ(float scaleZ);
77 :
78 8 : virtual const Vec3 & getScale() const { return _scale; }
79 :
80 : virtual void setPosition(const Vec2 &position);
81 : virtual void setPosition(const Vec3 &position);
82 : virtual void setPositionX(float);
83 : virtual void setPositionY(float);
84 : virtual void setPositionZ(float);
85 :
86 1034 : virtual const Vec3 & getPosition() const { return _position; }
87 :
88 : virtual void setSkewX(float skewX);
89 : virtual void setSkewY(float skewY);
90 :
91 2 : virtual const Vec2 & getSkew() const { return _skew; }
92 :
93 : /**
94 : * Sets the anchor point in percent.
95 : *
96 : * anchorPoint is the point around which all transformations and positioning manipulations take place.
97 : * It's like a pin in the node where it is "attached" to its parent.
98 : * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
99 : * But you can use values higher than (1,1) and lower than (0,0) too.
100 : * The default anchorPoint is (0.5,0.5), so it starts in the center of the node.
101 : * @note If node has a physics body, the anchor must be in the middle, you cann't change this to other value.
102 : *
103 : * @param anchorPoint The anchor point of node.
104 : */
105 : virtual void setAnchorPoint(const Vec2& anchorPoint);
106 14 : virtual const Vec2 & getAnchorPoint() const { return _anchorPoint; }
107 :
108 : /**
109 : * Sets the untransformed size of the node.
110 : *
111 : * The contentSize remains the same no matter the node is scaled or rotated.
112 : * All nodes has a size. Layer and Scene has the same size of the screen.
113 : *
114 : * @param contentSize The untransformed size of the node.
115 : */
116 : virtual void setContentSize(const Size2& contentSize);
117 3406 : virtual const Size2& getContentSize() const { return _contentSize; }
118 :
119 : virtual void setVisible(bool visible);
120 91715 : virtual bool isVisible() const { return _visible; }
121 :
122 : virtual void setRotation(float rotationInRadians);
123 : virtual void setRotation(const Vec3 & rotationInRadians);
124 : virtual void setRotation(const Quaternion & quat);
125 :
126 2 : virtual float getRotation() const { return _rotation.z; }
127 2 : virtual const Vec3 &getRotation3D() const { return _rotation; }
128 2 : virtual const Quaternion &getRotationQuat() const { return _rotationQuat; }
129 :
130 : template<typename N, typename ... Args>
131 16816 : auto addChild(N *child, Args &&... args) -> N * {
132 16816 : addChildNode(child, std::forward<Args>(args)...);
133 16816 : return child;
134 : }
135 :
136 : template<typename N, typename ... Args>
137 8328 : auto addChild(const Rc<N> &child, Args &&... args) -> N * {
138 8328 : addChildNode(child.get(), std::forward<Args>(args)...);
139 8328 : return child.get();
140 : }
141 :
142 : virtual void addChildNode(Node *child);
143 : virtual void addChildNode(Node *child, ZOrder localZOrder);
144 : virtual void addChildNode(Node *child, ZOrder localZOrder, uint64_t tag);
145 :
146 : virtual Node* getChildByTag(uint64_t tag) const;
147 :
148 2 : virtual const Vector<Rc<Node>>& getChildren() const { return _children; }
149 2 : virtual size_t getChildrenCount() const { return _children.size(); }
150 :
151 : virtual void setParent(Node *parent);
152 19458 : virtual Node *getParent() const { return _parent; }
153 :
154 : virtual void removeFromParent(bool cleanup = true);
155 : virtual void removeChild(Node *child, bool cleanup = true);
156 : virtual void removeChildByTag(uint64_t tag, bool cleanup = true);
157 : virtual void removeAllChildren(bool cleanup = true);
158 :
159 : virtual void reorderChild(Node *child, ZOrder localZOrder);
160 :
161 : /**
162 : * Sorts the children array once before drawing, instead of every time when a child is added or reordered.
163 : * This appraoch can improves the performance massively.
164 : * @note Don't call this manually unless a child added needs to be removed in the same frame.
165 : */
166 : virtual void sortAllChildren();
167 :
168 : template <typename A>
169 : auto runAction(A *action) -> A * {
170 : runActionObject(action);
171 : return action;
172 : }
173 :
174 : template <typename A>
175 : auto runAction(A *action, uint32_t tag) -> A * {
176 : runActionObject(action, tag);
177 : return action;
178 : }
179 :
180 : template <typename A>
181 595 : auto runAction(const Rc<A> &action) -> A * {
182 595 : runActionObject(action.get());
183 595 : return action.get();
184 : }
185 :
186 : template <typename A>
187 1021 : auto runAction(const Rc<A> &action, uint32_t tag) -> A * {
188 1021 : runActionObject(action.get(), tag);
189 1021 : return action.get();
190 : }
191 :
192 : void runActionObject(Action *);
193 : void runActionObject(Action *, uint32_t tag);
194 :
195 : void stopAllActions();
196 :
197 : void stopAction(Action *action);
198 : void stopActionByTag(uint32_t tag);
199 : void stopAllActionsByTag(uint32_t tag);
200 :
201 : Action* getActionByTag(uint32_t tag);
202 : size_t getNumberOfRunningActions() const;
203 :
204 :
205 : template <typename C>
206 : auto addComponent(C *component) -> C * {
207 : if (addComponentItem(component)) {
208 : return component;
209 : }
210 : return nullptr;
211 : }
212 :
213 : template <typename C>
214 774 : auto addComponent(const Rc<C> &component) -> C * {
215 774 : if (addComponentItem(component.get())) {
216 774 : return component.get();
217 : }
218 0 : return nullptr;
219 : }
220 :
221 : virtual bool addComponentItem(Component *);
222 : virtual bool removeComponent(Component *);
223 : virtual bool removeComponentByTag(uint64_t);
224 : virtual bool removeAllComponentByTag(uint64_t);
225 : virtual void removeAllComponents();
226 :
227 : template <typename T>
228 : T *getComponentByType() const;
229 :
230 : template <typename T>
231 : T *getComponentByType(uint32_t tag) const;
232 :
233 : template <typename C>
234 : auto addInputListener(C *component) -> C * {
235 : if (addInputListenerItem(component)) {
236 : return component;
237 : }
238 : return nullptr;
239 : }
240 :
241 : template <typename C>
242 96 : auto addInputListener(const Rc<C> &component) -> C * {
243 96 : if (addInputListenerItem(component.get())) {
244 96 : return component.get();
245 : }
246 0 : return nullptr;
247 : }
248 :
249 : virtual bool addInputListenerItem(InputListener *);
250 : virtual bool removeInputListener(InputListener *);
251 :
252 2 : virtual StringView getName() const { return _name; }
253 32 : virtual void setName(StringView str) { _name = str.str<Interface>(); }
254 :
255 2 : virtual const Value &getDataValue() const { return _dataValue; }
256 2 : virtual void setDataValue(Value &&val) { _dataValue = move(val); }
257 :
258 2 : virtual uint64_t getTag() const { return _tag; }
259 : virtual void setTag(uint64_t tag);
260 :
261 902 : virtual bool isRunning() const { return _running; }
262 :
263 : virtual void onEnter(Scene *);
264 : virtual void onExit();
265 :
266 : virtual void onContentSizeDirty();
267 : virtual void onTransformDirty(const Mat4 &);
268 : virtual void onGlobalTransformDirty(const Mat4 &);
269 : virtual void onReorderChildDirty();
270 :
271 : virtual void cleanup();
272 :
273 : virtual Rect getBoundingBox() const;
274 :
275 : virtual void resume();
276 : virtual void pause();
277 :
278 : virtual void update(const UpdateTime &time);
279 :
280 : virtual const Mat4& getNodeToParentTransform() const;
281 :
282 : virtual void setNodeToParentTransform(const Mat4& transform);
283 : virtual const Mat4& getParentToNodeTransform() const;
284 :
285 : virtual Mat4 getNodeToWorldTransform() const;
286 : virtual Mat4 getWorldToNodeTransform() const;
287 :
288 : Vec2 convertToNodeSpace(const Vec2& worldPoint) const;
289 : Vec2 convertToWorldSpace(const Vec2& nodePoint) const;
290 : Vec2 convertToNodeSpaceAR(const Vec2& worldPoint) const;
291 : Vec2 convertToWorldSpaceAR(const Vec2& nodePoint) const;
292 :
293 5425 : virtual bool isCascadeOpacityEnabled() const { return _cascadeOpacityEnabled; }
294 36277 : virtual bool isCascadeColorEnabled() const { return _cascadeColorEnabled; }
295 :
296 : virtual void setCascadeOpacityEnabled(bool cascadeOpacityEnabled);
297 : virtual void setCascadeColorEnabled(bool cascadeColorEnabled);
298 :
299 516 : virtual float getOpacity() const { return _realColor.a; }
300 5425 : virtual float getDisplayedOpacity() const { return _displayedColor.a; }
301 : virtual void setOpacity(float opacity);
302 : virtual void setOpacity(OpacityValue);
303 : virtual void updateDisplayedOpacity(float parentOpacity);
304 :
305 2078 : virtual Color4F getColor() const { return _realColor; }
306 4 : virtual Color4F getDisplayedColor() const { return _displayedColor; }
307 : virtual void setColor(const Color4F& color, bool withOpacity = false);
308 : virtual void updateDisplayedColor(const Color4F& parentColor);
309 :
310 4246 : virtual void setDepthIndex(float value) { _depthIndex = value; }
311 2 : virtual float getDepthIndex() const { return _depthIndex; }
312 :
313 : virtual void draw(FrameInfo &, NodeFlags flags);
314 :
315 : // visit on unsorted nodes, commit most of geometry changes
316 : // on this step, we process child-to-parent changes (like nodes, based on label's size)
317 : virtual bool visitGeometry(FrameInfo &, NodeFlags parentFlags);
318 :
319 : // visit on sorted nodes, push draw commands
320 : // on this step, we also process parent-to-child geometry changes
321 : virtual bool visitDraw(FrameInfo &, NodeFlags parentFlags);
322 :
323 : void scheduleUpdate();
324 : void unscheduleUpdate();
325 :
326 : virtual bool isTouched(const Vec2 &location, float padding = 0.0f);
327 : virtual bool isTouchedNodeSpace(const Vec2 &location, float padding = 0.0f);
328 :
329 : virtual void setOnEnterCallback(Function<void(Scene *)> &&);
330 : virtual void setOnExitCallback(Function<void()> &&);
331 : virtual void setOnContentSizeDirtyCallback(Function<void()> &&);
332 : virtual void setOnTransformDirtyCallback(Function<void(const Mat4 &)> &&);
333 : virtual void setOnReorderChildDirtyCallback(Function<void()> &&);
334 :
335 0 : float getInputDensity() const { return _inputDensity; }
336 :
337 : Scene *getScene() const { return _scene; }
338 426 : Director *getDirector() const { return _director; }
339 1575 : Scheduler *getScheduler() const { return _scheduler; }
340 : ActionManager *getActionManager() const { return _actionManager; }
341 569808 : FrameContext *getFrameContext() const { return _frameContext; }
342 :
343 : virtual float getMaxDepthIndex() const;
344 :
345 : virtual void retainFocus();
346 : virtual void releaseFocus();
347 : virtual void clearFocus();
348 :
349 2 : virtual uint32_t getFocus() const { return _focus; }
350 :
351 : protected:
352 : virtual void updateCascadeOpacity();
353 : virtual void disableCascadeOpacity();
354 : virtual void updateCascadeColor();
355 : virtual void disableCascadeColor();
356 324961 : virtual void updateColor() { }
357 :
358 : Mat4 transform(const Mat4 &parentTransform);
359 : virtual NodeFlags processParentFlags(FrameInfo &info, NodeFlags parentFlags);
360 :
361 : virtual void visitSelf(FrameInfo &, NodeFlags flags, bool visibleByCamera);
362 :
363 : virtual bool wrapVisit(FrameInfo &, NodeFlags flags, const Callback<void(NodeFlags, bool visible)> &, bool useContext);
364 :
365 : bool _is3d = false;
366 : bool _running = false;
367 : bool _visible = true;
368 : bool _scheduled = false;
369 : bool _paused = false;
370 :
371 : bool _cascadeColorEnabled = false;
372 : bool _cascadeOpacityEnabled = true;
373 :
374 : bool _contentSizeDirty = true;
375 : bool _reorderChildDirty = true;
376 : mutable bool _transformCacheDirty = true; // dynamic value
377 : mutable bool _transformInverseDirty = true; // dynamic value
378 : bool _transformDirty = true;
379 :
380 : String _name;
381 : Value _dataValue;
382 :
383 : uint64_t _tag = InvalidTag;
384 86291 : ZOrder _zOrder = ZOrder(0);
385 : uint32_t _focus = 0;
386 :
387 : Vec2 _skew;
388 : Vec2 _anchorPoint;
389 : Size2 _contentSize;
390 :
391 : Vec3 _position;
392 : Vec3 _scale = Vec3(1.0f, 1.0f, 1.0f);
393 : Vec3 _rotation;
394 : float _inputDensity = 1.0f;
395 : float _depthIndex = 0.0f;
396 :
397 : // to support HDR, we use float colors;
398 : Color4F _displayedColor = Color4F::WHITE;
399 : Color4F _realColor = Color4F::WHITE;
400 :
401 : Quaternion _rotationQuat;
402 :
403 : mutable Mat4 _transform = Mat4::IDENTITY;
404 : mutable Mat4 _inverse = Mat4::IDENTITY;
405 : Mat4 _modelViewTransform = Mat4::IDENTITY;
406 :
407 : Vector<Rc<Node>> _children;
408 : Node *_parent = nullptr;
409 :
410 : Function<void(Scene *)> _onEnterCallback;
411 : Function<void()> _onExitCallback;
412 : Function<void()> _onContentSizeDirtyCallback;
413 : Function<void(const Mat4 &)> _onTransformDirtyCallback;
414 : Function<void()> _onReorderChildDirtyCallback;
415 :
416 : Vector<Rc<Component>> _components;
417 : Vector<Rc<InputListener>> _inputEvents;
418 :
419 : Scene *_scene = nullptr;
420 : Director *_director = nullptr;
421 : Scheduler *_scheduler = nullptr;
422 : ActionManager *_actionManager = nullptr;
423 : FrameContext *_frameContext = nullptr;
424 :
425 : Rc<ActionStorage> _actionStorage;
426 : };
427 :
428 :
429 : template <typename T>
430 16639 : auto Node::getComponentByType() const -> T * {
431 17031 : for (auto &it : _components) {
432 392 : if (auto ret = dynamic_cast<T *>(it.get())) {
433 0 : return ret;
434 : }
435 : }
436 16639 : return nullptr;
437 : }
438 :
439 : template <typename T>
440 : auto Node::getComponentByType(uint32_t tag) const -> T * {
441 : for (auto &it : _components) {
442 : if (it->getFrameTag() == tag) {
443 : if (auto ret = dynamic_cast<T *>(it.get())) {
444 : return ret;
445 : }
446 : }
447 : }
448 : return nullptr;
449 : }
450 :
451 :
452 : }
453 :
454 : #endif /* XENOLITH_SCENE_NODES_XLNODE_H_ */
|