1/**************************************************************************/
2/* scene_tree.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef SCENE_TREE_H
32#define SCENE_TREE_H
33
34#include "core/os/main_loop.h"
35#include "core/os/thread_safe.h"
36#include "core/templates/paged_allocator.h"
37#include "core/templates/self_list.h"
38#include "scene/resources/mesh.h"
39
40#undef Window
41
42class PackedScene;
43class Node;
44class Window;
45class Material;
46class Mesh;
47class MultiplayerAPI;
48class SceneDebugger;
49class Tween;
50class Viewport;
51
52class SceneTreeTimer : public RefCounted {
53 GDCLASS(SceneTreeTimer, RefCounted);
54
55 double time_left = 0.0;
56 bool process_always = true;
57 bool process_in_physics = false;
58 bool ignore_time_scale = false;
59
60protected:
61 static void _bind_methods();
62
63public:
64 void set_time_left(double p_time);
65 double get_time_left() const;
66
67 void set_process_always(bool p_process_always);
68 bool is_process_always();
69
70 void set_process_in_physics(bool p_process_in_physics);
71 bool is_process_in_physics();
72
73 void set_ignore_time_scale(bool p_ignore);
74 bool is_ignore_time_scale();
75
76 void release_connections();
77
78 SceneTreeTimer();
79};
80
81class SceneTree : public MainLoop {
82 _THREAD_SAFE_CLASS_
83
84 GDCLASS(SceneTree, MainLoop);
85
86public:
87 typedef void (*IdleCallback)();
88
89private:
90 CallQueue::Allocator *process_group_call_queue_allocator = nullptr;
91
92 struct ProcessGroup {
93 CallQueue call_queue;
94 Vector<Node *> nodes;
95 Vector<Node *> physics_nodes;
96 bool node_order_dirty = true;
97 bool physics_node_order_dirty = true;
98 bool removed = false;
99 Node *owner = nullptr;
100 uint64_t last_pass = 0;
101 };
102
103 struct ProcessGroupSort {
104 _FORCE_INLINE_ bool operator()(const ProcessGroup *p_left, const ProcessGroup *p_right) const;
105 };
106
107 PagedAllocator<ProcessGroup, true> group_allocator; // Allocate groups on pages, to enhance cache usage.
108
109 LocalVector<ProcessGroup *> process_groups;
110 bool process_groups_dirty = true;
111 LocalVector<ProcessGroup *> local_process_group_cache; // Used when processing to group what needs to
112 uint64_t process_last_pass = 1;
113
114 ProcessGroup default_process_group;
115
116 bool node_threading_disabled = false;
117
118 struct Group {
119 Vector<Node *> nodes;
120 bool changed = false;
121 };
122
123 Window *root = nullptr;
124
125 uint64_t tree_version = 1;
126 double physics_process_time = 0.0;
127 double process_time = 0.0;
128 bool accept_quit = true;
129 bool quit_on_go_back = true;
130
131#ifdef DEBUG_ENABLED
132 bool debug_collisions_hint = false;
133 bool debug_paths_hint = false;
134 bool debug_navigation_hint = false;
135#endif
136 bool paused = false;
137 int root_lock = 0;
138
139 HashMap<StringName, Group> group_map;
140 bool _quit = false;
141
142 StringName tree_changed_name = "tree_changed";
143 StringName node_added_name = "node_added";
144 StringName node_removed_name = "node_removed";
145 StringName node_renamed_name = "node_renamed";
146
147 int64_t current_frame = 0;
148 int nodes_in_tree_count = 0;
149
150#ifdef TOOLS_ENABLED
151 Node *edited_scene_root = nullptr;
152#endif
153 struct UGCall {
154 StringName group;
155 StringName call;
156
157 static uint32_t hash(const UGCall &p_val) {
158 return p_val.group.hash() ^ p_val.call.hash();
159 }
160 bool operator==(const UGCall &p_with) const { return group == p_with.group && call == p_with.call; }
161 bool operator<(const UGCall &p_with) const { return group == p_with.group ? call < p_with.call : group < p_with.group; }
162 };
163
164 // Safety for when a node is deleted while a group is being called.
165
166 bool processing = false;
167 int nodes_removed_on_group_call_lock = 0;
168 HashSet<Node *> nodes_removed_on_group_call; // Skip erased nodes.
169
170 List<ObjectID> delete_queue;
171
172 HashMap<UGCall, Vector<Variant>, UGCall> unique_group_calls;
173 bool ugc_locked = false;
174 void _flush_ugc();
175
176 _FORCE_INLINE_ void _update_group_order(Group &g);
177
178 TypedArray<Node> _get_nodes_in_group(const StringName &p_group);
179
180 Node *current_scene = nullptr;
181 Node *prev_scene = nullptr;
182 Node *pending_new_scene = nullptr;
183
184 Color debug_collisions_color;
185 Color debug_collision_contact_color;
186 Color debug_paths_color;
187 float debug_paths_width = 1.0f;
188 Ref<ArrayMesh> debug_contact_mesh;
189 Ref<Material> debug_paths_material;
190 Ref<Material> collision_material;
191 int collision_debug_contacts;
192
193 void _flush_scene_change();
194
195 List<Ref<SceneTreeTimer>> timers;
196 List<Ref<Tween>> tweens;
197
198 ///network///
199
200 Ref<MultiplayerAPI> multiplayer;
201 HashMap<NodePath, Ref<MultiplayerAPI>> custom_multiplayers;
202 bool multiplayer_poll = true;
203
204 static SceneTree *singleton;
205 friend class Node;
206
207 void tree_changed();
208 void node_added(Node *p_node);
209 void node_removed(Node *p_node);
210 void node_renamed(Node *p_node);
211 void process_timers(double p_delta, bool p_physics_frame);
212 void process_tweens(double p_delta, bool p_physics_frame);
213
214 Group *add_to_group(const StringName &p_group, Node *p_node);
215 void remove_from_group(const StringName &p_group, Node *p_node);
216 void make_group_changed(const StringName &p_group);
217
218 void _process_group(ProcessGroup *p_group, bool p_physics);
219 void _process_groups_thread(uint32_t p_index, bool p_physics);
220 void _process(bool p_physics);
221
222 void _remove_process_group(Node *p_node);
223 void _add_process_group(Node *p_node);
224 void _remove_node_from_process_group(Node *p_node, Node *p_owner);
225 void _add_node_to_process_group(Node *p_node, Node *p_owner);
226
227 void _call_group_flags(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
228 void _call_group(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
229
230 void _flush_delete_queue();
231 // Optimization.
232 friend class CanvasItem;
233 friend class Node3D;
234 friend class Viewport;
235
236 SelfList<Node>::List xform_change_list;
237
238#ifdef DEBUG_ENABLED // No live editor in release build.
239 friend class LiveEditor;
240#endif
241
242 enum {
243 MAX_IDLE_CALLBACKS = 256
244 };
245
246 static IdleCallback idle_callbacks[MAX_IDLE_CALLBACKS];
247 static int idle_callback_count;
248 void _call_idle_callbacks();
249
250 void _main_window_focus_in();
251 void _main_window_close();
252 void _main_window_go_back();
253
254 enum CallInputType {
255 CALL_INPUT_TYPE_INPUT,
256 CALL_INPUT_TYPE_SHORTCUT_INPUT,
257 CALL_INPUT_TYPE_UNHANDLED_INPUT,
258 CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT,
259 };
260
261 //used by viewport
262 void _call_input_pause(const StringName &p_group, CallInputType p_call_type, const Ref<InputEvent> &p_input, Viewport *p_viewport);
263
264protected:
265 void _notification(int p_notification);
266 static void _bind_methods();
267
268public:
269 enum {
270 NOTIFICATION_TRANSFORM_CHANGED = 2000
271 };
272
273 enum GroupCallFlags {
274 GROUP_CALL_DEFAULT = 0,
275 GROUP_CALL_REVERSE = 1,
276 GROUP_CALL_DEFERRED = 2,
277 GROUP_CALL_UNIQUE = 4,
278 };
279
280 _FORCE_INLINE_ Window *get_root() const { return root; }
281
282 void call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount);
283 void notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification);
284 void set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value);
285
286 // `notify_group()` is immediate by default since Godot 4.0.
287 void notify_group(const StringName &p_group, int p_notification);
288 // `set_group()` is immediate by default since Godot 4.0.
289 void set_group(const StringName &p_group, const String &p_name, const Variant &p_value);
290
291 template <typename... VarArgs>
292 // `call_group()` is immediate by default since Godot 4.0.
293 void call_group(const StringName &p_group, const StringName &p_function, VarArgs... p_args) {
294 Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
295 const Variant *argptrs[sizeof...(p_args) + 1];
296 for (uint32_t i = 0; i < sizeof...(p_args); i++) {
297 argptrs[i] = &args[i];
298 }
299 call_group_flagsp(GROUP_CALL_DEFAULT, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
300 }
301
302 template <typename... VarArgs>
303 void call_group_flags(uint32_t p_flags, const StringName &p_group, const StringName &p_function, VarArgs... p_args) {
304 Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
305 const Variant *argptrs[sizeof...(p_args) + 1];
306 for (uint32_t i = 0; i < sizeof...(p_args); i++) {
307 argptrs[i] = &args[i];
308 }
309 call_group_flagsp(p_flags, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
310 }
311
312 void flush_transform_notifications();
313
314 virtual void initialize() override;
315
316 virtual bool physics_process(double p_time) override;
317 virtual bool process(double p_time) override;
318
319 virtual void finalize() override;
320
321 bool is_auto_accept_quit() const;
322 void set_auto_accept_quit(bool p_enable);
323
324 bool is_quit_on_go_back() const;
325 void set_quit_on_go_back(bool p_enable);
326
327 void quit(int p_exit_code = EXIT_SUCCESS);
328
329 _FORCE_INLINE_ double get_physics_process_time() const { return physics_process_time; }
330 _FORCE_INLINE_ double get_process_time() const { return process_time; }
331
332#ifdef TOOLS_ENABLED
333 bool is_node_being_edited(const Node *p_node) const;
334#else
335 bool is_node_being_edited(const Node *p_node) const { return false; }
336#endif
337
338 void set_pause(bool p_enabled);
339 bool is_paused() const;
340
341#ifdef DEBUG_ENABLED
342 void set_debug_collisions_hint(bool p_enabled);
343 bool is_debugging_collisions_hint() const;
344
345 void set_debug_paths_hint(bool p_enabled);
346 bool is_debugging_paths_hint() const;
347
348 void set_debug_navigation_hint(bool p_enabled);
349 bool is_debugging_navigation_hint() const;
350#else
351 void set_debug_collisions_hint(bool p_enabled) {}
352 bool is_debugging_collisions_hint() const { return false; }
353
354 void set_debug_paths_hint(bool p_enabled) {}
355 bool is_debugging_paths_hint() const { return false; }
356
357 void set_debug_navigation_hint(bool p_enabled) {}
358 bool is_debugging_navigation_hint() const { return false; }
359#endif
360
361 void set_debug_collisions_color(const Color &p_color);
362 Color get_debug_collisions_color() const;
363
364 void set_debug_collision_contact_color(const Color &p_color);
365 Color get_debug_collision_contact_color() const;
366
367 void set_debug_paths_color(const Color &p_color);
368 Color get_debug_paths_color() const;
369
370 void set_debug_paths_width(float p_width);
371 float get_debug_paths_width() const;
372
373 Ref<Material> get_debug_paths_material();
374 Ref<Material> get_debug_collision_material();
375 Ref<ArrayMesh> get_debug_contact_mesh();
376
377 int get_collision_debug_contact_count() { return collision_debug_contacts; }
378
379 int64_t get_frame() const;
380
381 int get_node_count() const;
382
383 void queue_delete(Object *p_object);
384
385 void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list);
386 Node *get_first_node_in_group(const StringName &p_group);
387 bool has_group(const StringName &p_identifier) const;
388
389 //void change_scene(const String& p_path);
390 //Node *get_loaded_scene();
391
392 void set_edited_scene_root(Node *p_node);
393 Node *get_edited_scene_root() const;
394
395 void set_current_scene(Node *p_scene);
396 Node *get_current_scene() const;
397 Error change_scene_to_file(const String &p_path);
398 Error change_scene_to_packed(const Ref<PackedScene> &p_scene);
399 Error reload_current_scene();
400 void unload_current_scene();
401
402 Ref<SceneTreeTimer> create_timer(double p_delay_sec, bool p_process_always = true, bool p_process_in_physics = false, bool p_ignore_time_scale = false);
403 Ref<Tween> create_tween();
404 TypedArray<Tween> get_processed_tweens();
405
406 //used by Main::start, don't use otherwise
407 void add_current_scene(Node *p_current);
408
409 static SceneTree *get_singleton() { return singleton; }
410
411 void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
412
413 //network API
414
415 Ref<MultiplayerAPI> get_multiplayer(const NodePath &p_for_path = NodePath()) const;
416 void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path = NodePath());
417 void set_multiplayer_poll_enabled(bool p_enabled);
418 bool is_multiplayer_poll_enabled() const;
419
420 static void add_idle_callback(IdleCallback p_callback);
421
422 void set_disable_node_threading(bool p_disable);
423 //default texture settings
424
425 SceneTree();
426 ~SceneTree();
427};
428
429VARIANT_ENUM_CAST(SceneTree::GroupCallFlags);
430
431#endif // SCENE_TREE_H
432