1 | /**************************************************************************/ |
2 | /* engine.cpp */ |
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 | #include "engine.h" |
32 | |
33 | #include "core/authors.gen.h" |
34 | #include "core/config/project_settings.h" |
35 | #include "core/donors.gen.h" |
36 | #include "core/license.gen.h" |
37 | #include "core/variant/typed_array.h" |
38 | #include "core/version.h" |
39 | |
40 | void Engine::set_physics_ticks_per_second(int p_ips) { |
41 | ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0." ); |
42 | ips = p_ips; |
43 | } |
44 | |
45 | int Engine::get_physics_ticks_per_second() const { |
46 | return ips; |
47 | } |
48 | |
49 | void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) { |
50 | ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0." ); |
51 | max_physics_steps_per_frame = p_max_physics_steps; |
52 | } |
53 | |
54 | int Engine::get_max_physics_steps_per_frame() const { |
55 | return max_physics_steps_per_frame; |
56 | } |
57 | |
58 | void Engine::set_physics_jitter_fix(double p_threshold) { |
59 | if (p_threshold < 0) { |
60 | p_threshold = 0; |
61 | } |
62 | physics_jitter_fix = p_threshold; |
63 | } |
64 | |
65 | double Engine::get_physics_jitter_fix() const { |
66 | return physics_jitter_fix; |
67 | } |
68 | |
69 | void Engine::set_max_fps(int p_fps) { |
70 | _max_fps = p_fps > 0 ? p_fps : 0; |
71 | } |
72 | |
73 | int Engine::get_max_fps() const { |
74 | return _max_fps; |
75 | } |
76 | |
77 | void Engine::set_audio_output_latency(int p_msec) { |
78 | _audio_output_latency = p_msec > 1 ? p_msec : 1; |
79 | } |
80 | |
81 | int Engine::get_audio_output_latency() const { |
82 | return _audio_output_latency; |
83 | } |
84 | |
85 | uint64_t Engine::get_frames_drawn() { |
86 | return frames_drawn; |
87 | } |
88 | |
89 | void Engine::set_frame_delay(uint32_t p_msec) { |
90 | _frame_delay = p_msec; |
91 | } |
92 | |
93 | uint32_t Engine::get_frame_delay() const { |
94 | return _frame_delay; |
95 | } |
96 | |
97 | void Engine::set_time_scale(double p_scale) { |
98 | _time_scale = p_scale; |
99 | } |
100 | |
101 | double Engine::get_time_scale() const { |
102 | return _time_scale; |
103 | } |
104 | |
105 | Dictionary Engine::get_version_info() const { |
106 | Dictionary dict; |
107 | dict["major" ] = VERSION_MAJOR; |
108 | dict["minor" ] = VERSION_MINOR; |
109 | dict["patch" ] = VERSION_PATCH; |
110 | dict["hex" ] = VERSION_HEX; |
111 | dict["status" ] = VERSION_STATUS; |
112 | dict["build" ] = VERSION_BUILD; |
113 | dict["year" ] = VERSION_YEAR; |
114 | |
115 | String hash = String(VERSION_HASH); |
116 | dict["hash" ] = hash.is_empty() ? String("unknown" ) : hash; |
117 | |
118 | String stringver = String(dict["major" ]) + "." + String(dict["minor" ]); |
119 | if ((int)dict["patch" ] != 0) { |
120 | stringver += "." + String(dict["patch" ]); |
121 | } |
122 | stringver += "-" + String(dict["status" ]) + " (" + String(dict["build" ]) + ")" ; |
123 | dict["string" ] = stringver; |
124 | |
125 | return dict; |
126 | } |
127 | |
128 | static Array array_from_info(const char *const *info_list) { |
129 | Array arr; |
130 | for (int i = 0; info_list[i] != nullptr; i++) { |
131 | arr.push_back(String::utf8(info_list[i])); |
132 | } |
133 | return arr; |
134 | } |
135 | |
136 | static Array array_from_info_count(const char *const *info_list, int info_count) { |
137 | Array arr; |
138 | for (int i = 0; i < info_count; i++) { |
139 | arr.push_back(String::utf8(info_list[i])); |
140 | } |
141 | return arr; |
142 | } |
143 | |
144 | Dictionary Engine::get_author_info() const { |
145 | Dictionary dict; |
146 | |
147 | dict["lead_developers" ] = array_from_info(AUTHORS_LEAD_DEVELOPERS); |
148 | dict["project_managers" ] = array_from_info(AUTHORS_PROJECT_MANAGERS); |
149 | dict["founders" ] = array_from_info(AUTHORS_FOUNDERS); |
150 | dict["developers" ] = array_from_info(AUTHORS_DEVELOPERS); |
151 | |
152 | return dict; |
153 | } |
154 | |
155 | TypedArray<Dictionary> Engine::get_copyright_info() const { |
156 | TypedArray<Dictionary> components; |
157 | for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) { |
158 | const ComponentCopyright &cp_info = COPYRIGHT_INFO[component_index]; |
159 | Dictionary component_dict; |
160 | component_dict["name" ] = String::utf8(cp_info.name); |
161 | Array parts; |
162 | for (int i = 0; i < cp_info.part_count; i++) { |
163 | const ComponentCopyrightPart &cp_part = cp_info.parts[i]; |
164 | Dictionary part_dict; |
165 | part_dict["files" ] = array_from_info_count(cp_part.files, cp_part.file_count); |
166 | part_dict["copyright" ] = array_from_info_count(cp_part.copyright_statements, cp_part.copyright_count); |
167 | part_dict["license" ] = String::utf8(cp_part.license); |
168 | parts.push_back(part_dict); |
169 | } |
170 | component_dict["parts" ] = parts; |
171 | |
172 | components.push_back(component_dict); |
173 | } |
174 | return components; |
175 | } |
176 | |
177 | Dictionary Engine::get_donor_info() const { |
178 | Dictionary donors; |
179 | donors["platinum_sponsors" ] = array_from_info(DONORS_SPONSOR_PLATINUM); |
180 | donors["gold_sponsors" ] = array_from_info(DONORS_SPONSOR_GOLD); |
181 | donors["silver_sponsors" ] = array_from_info(DONORS_SPONSOR_SILVER); |
182 | donors["bronze_sponsors" ] = array_from_info(DONORS_SPONSOR_BRONZE); |
183 | donors["mini_sponsors" ] = array_from_info(DONORS_SPONSOR_MINI); |
184 | donors["gold_donors" ] = array_from_info(DONORS_GOLD); |
185 | donors["silver_donors" ] = array_from_info(DONORS_SILVER); |
186 | donors["bronze_donors" ] = array_from_info(DONORS_BRONZE); |
187 | return donors; |
188 | } |
189 | |
190 | Dictionary Engine::get_license_info() const { |
191 | Dictionary licenses; |
192 | for (int i = 0; i < LICENSE_COUNT; i++) { |
193 | licenses[LICENSE_NAMES[i]] = LICENSE_BODIES[i]; |
194 | } |
195 | return licenses; |
196 | } |
197 | |
198 | String Engine::get_license_text() const { |
199 | return String(GODOT_LICENSE_TEXT); |
200 | } |
201 | |
202 | String Engine::get_architecture_name() const { |
203 | #if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) |
204 | return "x86_64" ; |
205 | |
206 | #elif defined(__i386) || defined(__i386__) || defined(_M_IX86) |
207 | return "x86_32" ; |
208 | |
209 | #elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) |
210 | return "arm64" ; |
211 | |
212 | #elif defined(__arm__) || defined(_M_ARM) |
213 | return "arm32" ; |
214 | |
215 | #elif defined(__riscv) |
216 | #if __riscv_xlen == 8 |
217 | return "rv64" ; |
218 | #else |
219 | return "riscv" ; |
220 | #endif |
221 | |
222 | #elif defined(__powerpc__) |
223 | #if defined(__powerpc64__) |
224 | return "ppc64" ; |
225 | #else |
226 | return "ppc" ; |
227 | #endif |
228 | |
229 | #elif defined(__wasm__) |
230 | #if defined(__wasm64__) |
231 | return "wasm64" ; |
232 | #elif defined(__wasm32__) |
233 | return "wasm32" ; |
234 | #endif |
235 | #endif |
236 | } |
237 | |
238 | bool Engine::is_abort_on_gpu_errors_enabled() const { |
239 | return abort_on_gpu_errors; |
240 | } |
241 | |
242 | int32_t Engine::get_gpu_index() const { |
243 | return gpu_idx; |
244 | } |
245 | |
246 | bool Engine::is_validation_layers_enabled() const { |
247 | return use_validation_layers; |
248 | } |
249 | |
250 | bool Engine::is_generate_spirv_debug_info_enabled() const { |
251 | return generate_spirv_debug_info; |
252 | } |
253 | |
254 | void Engine::set_print_error_messages(bool p_enabled) { |
255 | CoreGlobals::print_error_enabled = p_enabled; |
256 | } |
257 | |
258 | bool Engine::is_printing_error_messages() const { |
259 | return CoreGlobals::print_error_enabled; |
260 | } |
261 | |
262 | void Engine::add_singleton(const Singleton &p_singleton) { |
263 | ERR_FAIL_COND_MSG(singleton_ptrs.has(p_singleton.name), "Can't register singleton that already exists: " + String(p_singleton.name)); |
264 | singletons.push_back(p_singleton); |
265 | singleton_ptrs[p_singleton.name] = p_singleton.ptr; |
266 | } |
267 | |
268 | Object *Engine::get_singleton_object(const StringName &p_name) const { |
269 | HashMap<StringName, Object *>::ConstIterator E = singleton_ptrs.find(p_name); |
270 | ERR_FAIL_COND_V_MSG(!E, nullptr, "Failed to retrieve non-existent singleton '" + String(p_name) + "'." ); |
271 | return E->value; |
272 | } |
273 | |
274 | bool Engine::is_singleton_user_created(const StringName &p_name) const { |
275 | ERR_FAIL_COND_V(!singleton_ptrs.has(p_name), false); |
276 | |
277 | for (const Singleton &E : singletons) { |
278 | if (E.name == p_name && E.user_created) { |
279 | return true; |
280 | } |
281 | } |
282 | |
283 | return false; |
284 | } |
285 | void Engine::remove_singleton(const StringName &p_name) { |
286 | ERR_FAIL_COND(!singleton_ptrs.has(p_name)); |
287 | |
288 | for (List<Singleton>::Element *E = singletons.front(); E; E = E->next()) { |
289 | if (E->get().name == p_name) { |
290 | singletons.erase(E); |
291 | singleton_ptrs.erase(p_name); |
292 | return; |
293 | } |
294 | } |
295 | } |
296 | |
297 | bool Engine::has_singleton(const StringName &p_name) const { |
298 | return singleton_ptrs.has(p_name); |
299 | } |
300 | |
301 | void Engine::get_singletons(List<Singleton> *p_singletons) { |
302 | for (const Singleton &E : singletons) { |
303 | p_singletons->push_back(E); |
304 | } |
305 | } |
306 | |
307 | String Engine::get_write_movie_path() const { |
308 | return write_movie_path; |
309 | } |
310 | |
311 | void Engine::set_write_movie_path(const String &p_path) { |
312 | write_movie_path = p_path; |
313 | } |
314 | |
315 | void Engine::set_shader_cache_path(const String &p_path) { |
316 | shader_cache_path = p_path; |
317 | } |
318 | String Engine::get_shader_cache_path() const { |
319 | return shader_cache_path; |
320 | } |
321 | |
322 | Engine *Engine::singleton = nullptr; |
323 | |
324 | Engine *Engine::get_singleton() { |
325 | return singleton; |
326 | } |
327 | |
328 | Engine::Engine() { |
329 | singleton = this; |
330 | } |
331 | |
332 | Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr, const StringName &p_class_name) : |
333 | name(p_name), |
334 | ptr(p_ptr), |
335 | class_name(p_class_name) { |
336 | #ifdef DEBUG_ENABLED |
337 | RefCounted *rc = Object::cast_to<RefCounted>(p_ptr); |
338 | if (rc && !rc->is_referenced()) { |
339 | WARN_PRINT("You must use Ref<> to ensure the lifetime of a RefCounted object intended to be used as a singleton." ); |
340 | } |
341 | #endif |
342 | } |
343 | |