Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/config/engine.cpp
9973 views
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
#include "servers/rendering/rendering_device.h"
40
41
void Engine::set_physics_ticks_per_second(int p_ips) {
42
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
43
ips = p_ips;
44
}
45
46
int Engine::get_physics_ticks_per_second() const {
47
return ips;
48
}
49
50
void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
51
ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0.");
52
max_physics_steps_per_frame = p_max_physics_steps;
53
}
54
55
int Engine::get_max_physics_steps_per_frame() const {
56
return max_physics_steps_per_frame;
57
}
58
59
void Engine::set_physics_jitter_fix(double p_threshold) {
60
if (p_threshold < 0) {
61
p_threshold = 0;
62
}
63
physics_jitter_fix = p_threshold;
64
}
65
66
double Engine::get_physics_jitter_fix() const {
67
return physics_jitter_fix;
68
}
69
70
void Engine::set_max_fps(int p_fps) {
71
_max_fps = p_fps > 0 ? p_fps : 0;
72
73
RenderingDevice *rd = RenderingDevice::get_singleton();
74
if (rd) {
75
rd->_set_max_fps(_max_fps);
76
}
77
}
78
79
int Engine::get_max_fps() const {
80
return _max_fps;
81
}
82
83
void Engine::set_audio_output_latency(int p_msec) {
84
_audio_output_latency = p_msec > 1 ? p_msec : 1;
85
}
86
87
int Engine::get_audio_output_latency() const {
88
return _audio_output_latency;
89
}
90
91
void Engine::increment_frames_drawn() {
92
if (frame_server_synced) {
93
server_syncs++;
94
} else {
95
server_syncs = 0;
96
}
97
frame_server_synced = false;
98
99
frames_drawn++;
100
}
101
102
uint64_t Engine::get_frames_drawn() {
103
return frames_drawn;
104
}
105
106
void Engine::set_frame_delay(uint32_t p_msec) {
107
_frame_delay = p_msec;
108
}
109
110
uint32_t Engine::get_frame_delay() const {
111
return _frame_delay;
112
}
113
114
void Engine::set_time_scale(double p_scale) {
115
_time_scale = p_scale;
116
}
117
118
double Engine::get_time_scale() const {
119
return freeze_time_scale ? 0 : _time_scale;
120
}
121
122
double Engine::get_unfrozen_time_scale() const {
123
return _time_scale;
124
}
125
126
Dictionary Engine::get_version_info() const {
127
Dictionary dict;
128
dict["major"] = GODOT_VERSION_MAJOR;
129
dict["minor"] = GODOT_VERSION_MINOR;
130
dict["patch"] = GODOT_VERSION_PATCH;
131
dict["hex"] = GODOT_VERSION_HEX;
132
dict["status"] = GODOT_VERSION_STATUS;
133
dict["build"] = GODOT_VERSION_BUILD;
134
135
String hash = String(GODOT_VERSION_HASH);
136
dict["hash"] = hash.is_empty() ? String("unknown") : hash;
137
138
dict["timestamp"] = GODOT_VERSION_TIMESTAMP;
139
140
String stringver = String(dict["major"]) + "." + String(dict["minor"]);
141
if ((int)dict["patch"] != 0) {
142
stringver += "." + String(dict["patch"]);
143
}
144
stringver += "-" + String(dict["status"]) + " (" + String(dict["build"]) + ")";
145
dict["string"] = stringver;
146
147
return dict;
148
}
149
150
static Array array_from_info(const char *const *info_list) {
151
Array arr;
152
for (int i = 0; info_list[i] != nullptr; i++) {
153
arr.push_back(String::utf8(info_list[i]));
154
}
155
return arr;
156
}
157
158
static Array array_from_info_count(const char *const *info_list, int info_count) {
159
Array arr;
160
for (int i = 0; i < info_count; i++) {
161
arr.push_back(String::utf8(info_list[i]));
162
}
163
return arr;
164
}
165
166
Dictionary Engine::get_author_info() const {
167
Dictionary dict;
168
169
dict["lead_developers"] = array_from_info(AUTHORS_LEAD_DEVELOPERS);
170
dict["project_managers"] = array_from_info(AUTHORS_PROJECT_MANAGERS);
171
dict["founders"] = array_from_info(AUTHORS_FOUNDERS);
172
dict["developers"] = array_from_info(AUTHORS_DEVELOPERS);
173
174
return dict;
175
}
176
177
TypedArray<Dictionary> Engine::get_copyright_info() const {
178
TypedArray<Dictionary> components;
179
for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) {
180
const ComponentCopyright &cp_info = COPYRIGHT_INFO[component_index];
181
Dictionary component_dict;
182
component_dict["name"] = String::utf8(cp_info.name);
183
Array parts;
184
for (int i = 0; i < cp_info.part_count; i++) {
185
const ComponentCopyrightPart &cp_part = cp_info.parts[i];
186
Dictionary part_dict;
187
part_dict["files"] = array_from_info_count(cp_part.files, cp_part.file_count);
188
part_dict["copyright"] = array_from_info_count(cp_part.copyright_statements, cp_part.copyright_count);
189
part_dict["license"] = String::utf8(cp_part.license);
190
parts.push_back(part_dict);
191
}
192
component_dict["parts"] = parts;
193
194
components.push_back(component_dict);
195
}
196
return components;
197
}
198
199
Dictionary Engine::get_donor_info() const {
200
Dictionary donors;
201
donors["patrons"] = array_from_info(DONORS_PATRONS);
202
donors["platinum_sponsors"] = array_from_info(DONORS_SPONSORS_PLATINUM);
203
donors["gold_sponsors"] = array_from_info(DONORS_SPONSORS_GOLD);
204
donors["silver_sponsors"] = array_from_info(DONORS_SPONSORS_SILVER);
205
donors["diamond_members"] = array_from_info(DONORS_MEMBERS_DIAMOND);
206
donors["titanium_members"] = array_from_info(DONORS_MEMBERS_TITANIUM);
207
donors["platinum_members"] = array_from_info(DONORS_MEMBERS_PLATINUM);
208
donors["gold_members"] = array_from_info(DONORS_MEMBERS_GOLD);
209
return donors;
210
}
211
212
Dictionary Engine::get_license_info() const {
213
Dictionary licenses;
214
for (int i = 0; i < LICENSE_COUNT; i++) {
215
licenses[LICENSE_NAMES[i]] = LICENSE_BODIES[i];
216
}
217
return licenses;
218
}
219
220
String Engine::get_license_text() const {
221
return String(GODOT_LICENSE_TEXT);
222
}
223
224
String Engine::get_architecture_name() const {
225
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
226
return "x86_64";
227
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
228
return "x86_32";
229
#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
230
return "arm64";
231
#elif defined(__arm__) || defined(_M_ARM)
232
return "arm32";
233
#elif defined(__riscv)
234
return "rv64";
235
#elif defined(__powerpc64__)
236
return "ppc64";
237
#elif defined(__loongarch64)
238
return "loongarch64";
239
#elif defined(__wasm64__)
240
return "wasm64";
241
#elif defined(__wasm32__)
242
return "wasm32";
243
#endif
244
}
245
246
bool Engine::is_abort_on_gpu_errors_enabled() const {
247
return abort_on_gpu_errors;
248
}
249
250
int32_t Engine::get_gpu_index() const {
251
return gpu_idx;
252
}
253
254
bool Engine::is_validation_layers_enabled() const {
255
return use_validation_layers;
256
}
257
258
bool Engine::is_generate_spirv_debug_info_enabled() const {
259
return generate_spirv_debug_info;
260
}
261
262
bool Engine::is_extra_gpu_memory_tracking_enabled() const {
263
return extra_gpu_memory_tracking;
264
}
265
266
#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
267
bool Engine::is_accurate_breadcrumbs_enabled() const {
268
return accurate_breadcrumbs;
269
}
270
#endif
271
272
void Engine::set_print_to_stdout(bool p_enabled) {
273
CoreGlobals::print_line_enabled = p_enabled;
274
}
275
276
bool Engine::is_printing_to_stdout() const {
277
return CoreGlobals::print_line_enabled;
278
}
279
280
void Engine::set_print_error_messages(bool p_enabled) {
281
CoreGlobals::print_error_enabled = p_enabled;
282
}
283
284
bool Engine::is_printing_error_messages() const {
285
return CoreGlobals::print_error_enabled;
286
}
287
288
void Engine::print_header(const String &p_string) const {
289
if (_print_header) {
290
print_line(p_string);
291
}
292
}
293
294
void Engine::print_header_rich(const String &p_string) const {
295
if (_print_header) {
296
print_line_rich(p_string);
297
}
298
}
299
300
void Engine::add_singleton(const Singleton &p_singleton) {
301
ERR_FAIL_COND_MSG(singleton_ptrs.has(p_singleton.name), vformat("Can't register singleton '%s' because it already exists.", p_singleton.name));
302
singletons.push_back(p_singleton);
303
singleton_ptrs[p_singleton.name] = p_singleton.ptr;
304
}
305
306
Object *Engine::get_singleton_object(const StringName &p_name) const {
307
HashMap<StringName, Object *>::ConstIterator E = singleton_ptrs.find(p_name);
308
ERR_FAIL_COND_V_MSG(!E, nullptr, vformat("Failed to retrieve non-existent singleton '%s'.", p_name));
309
310
#ifdef TOOLS_ENABLED
311
if (!is_editor_hint() && is_singleton_editor_only(p_name)) {
312
ERR_FAIL_V_MSG(nullptr, vformat("Can't retrieve singleton '%s' outside of editor.", p_name));
313
}
314
#endif
315
316
return E->value;
317
}
318
319
bool Engine::is_singleton_user_created(const StringName &p_name) const {
320
ERR_FAIL_COND_V(!singleton_ptrs.has(p_name), false);
321
322
for (const Singleton &E : singletons) {
323
if (E.name == p_name && E.user_created) {
324
return true;
325
}
326
}
327
328
return false;
329
}
330
331
bool Engine::is_singleton_editor_only(const StringName &p_name) const {
332
ERR_FAIL_COND_V(!singleton_ptrs.has(p_name), false);
333
334
for (const Singleton &E : singletons) {
335
if (E.name == p_name && E.editor_only) {
336
return true;
337
}
338
}
339
340
return false;
341
}
342
343
void Engine::remove_singleton(const StringName &p_name) {
344
ERR_FAIL_COND(!singleton_ptrs.has(p_name));
345
346
for (List<Singleton>::Element *E = singletons.front(); E; E = E->next()) {
347
if (E->get().name == p_name) {
348
singletons.erase(E);
349
singleton_ptrs.erase(p_name);
350
return;
351
}
352
}
353
}
354
355
bool Engine::has_singleton(const StringName &p_name) const {
356
return singleton_ptrs.has(p_name);
357
}
358
359
void Engine::get_singletons(List<Singleton> *p_singletons) {
360
for (const Singleton &E : singletons) {
361
#ifdef TOOLS_ENABLED
362
if (!is_editor_hint() && E.editor_only) {
363
continue;
364
}
365
#endif
366
367
p_singletons->push_back(E);
368
}
369
}
370
371
String Engine::get_write_movie_path() const {
372
return write_movie_path;
373
}
374
375
void Engine::set_write_movie_path(const String &p_path) {
376
write_movie_path = p_path;
377
}
378
379
void Engine::set_shader_cache_path(const String &p_path) {
380
shader_cache_path = p_path;
381
}
382
String Engine::get_shader_cache_path() const {
383
return shader_cache_path;
384
}
385
386
Engine *Engine::get_singleton() {
387
return singleton;
388
}
389
390
bool Engine::notify_frame_server_synced() {
391
frame_server_synced = true;
392
return server_syncs > SERVER_SYNC_FRAME_COUNT_WARNING;
393
}
394
395
void Engine::set_freeze_time_scale(bool p_frozen) {
396
freeze_time_scale = p_frozen;
397
}
398
399
void Engine::set_embedded_in_editor(bool p_enabled) {
400
embedded_in_editor = p_enabled;
401
}
402
403
bool Engine::is_embedded_in_editor() const {
404
return embedded_in_editor;
405
}
406
407
Engine::Engine() {
408
singleton = this;
409
}
410
411
Engine::~Engine() {
412
if (singleton == this) {
413
singleton = nullptr;
414
}
415
}
416
417
Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr, const StringName &p_class_name) :
418
name(p_name),
419
ptr(p_ptr),
420
class_name(p_class_name) {
421
#ifdef DEBUG_ENABLED
422
RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
423
if (rc && !rc->is_referenced()) {
424
WARN_PRINT("You must use Ref<> to ensure the lifetime of a RefCounted object intended to be used as a singleton.");
425
}
426
#endif
427
}
428
429