feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -51,8 +51,8 @@ if env["brotli"] and env["builtin_brotli"]:
]
thirdparty_brotli_sources = [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
env_thirdparty.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
env.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_brotli_dir + "include"])
env.Prepend(CPPEXTPATH=[thirdparty_brotli_dir + "include"])
if env.get("use_ubsan") or env.get("use_asan") or env.get("use_tsan") or env.get("use_lsan") or env.get("use_msan"):
env_thirdparty.Append(CPPDEFINES=["BROTLI_BUILD_PORTABLE"])
@ -69,8 +69,8 @@ if env["builtin_clipper2"]:
]
thirdparty_clipper_sources = [thirdparty_clipper_dir + file for file in thirdparty_clipper_sources]
env_thirdparty.Prepend(CPPPATH=[thirdparty_clipper_dir + "include"])
env.Prepend(CPPPATH=[thirdparty_clipper_dir + "include"])
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_clipper_dir + "include"])
env.Prepend(CPPEXTPATH=[thirdparty_clipper_dir + "include"])
env_thirdparty.Append(CPPDEFINES=["CLIPPER2_ENABLED"])
env.Append(CPPDEFINES=["CLIPPER2_ENABLED"])
@ -94,9 +94,9 @@ if env["builtin_zlib"]:
]
thirdparty_zlib_sources = [thirdparty_zlib_dir + file for file in thirdparty_zlib_sources]
env_thirdparty.Prepend(CPPPATH=[thirdparty_zlib_dir])
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_zlib_dir])
# Needs to be available in main env too
env.Prepend(CPPPATH=[thirdparty_zlib_dir])
env.Prepend(CPPEXTPATH=[thirdparty_zlib_dir])
if env.dev_build:
env_thirdparty.Append(CPPDEFINES=["ZLIB_DEBUG"])
# Affects headers so it should also be defined for Godot code
@ -148,9 +148,9 @@ if env["builtin_zstd"]:
thirdparty_zstd_sources.append("decompress/huf_decompress_amd64.S")
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
env_thirdparty.Prepend(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
env_thirdparty.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
env.Prepend(CPPPATH=thirdparty_zstd_dir)
env.Prepend(CPPEXTPATH=thirdparty_zstd_dir)
# Also needed in main env includes will trigger warnings
env.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
@ -167,10 +167,9 @@ env.add_source_files(env.core_sources, "*.cpp")
# Generate disabled classes
def disabled_class_builder(target, source, env):
with methods.generated_wrapper(target) as file:
with methods.generated_wrapper(str(target[0])) as file:
for c in source[0].read():
cs = c.strip()
if cs != "":
if cs := c.strip():
file.write(f"#define ClassDB_Disable_{cs} 1\n")
@ -179,49 +178,51 @@ env.CommandNoCache("disabled_classes.gen.h", env.Value(env.disabled_classes), en
# Generate version info
def version_info_builder(target, source, env):
with methods.generated_wrapper(target) as file:
with methods.generated_wrapper(str(target[0])) as file:
file.write(
"""\
#define VERSION_SHORT_NAME "{short_name}"
#define VERSION_NAME "{name}"
#define VERSION_MAJOR {major}
#define VERSION_MINOR {minor}
#define VERSION_PATCH {patch}
#define VERSION_STATUS "{status}"
#define VERSION_BUILD "{build}"
#define VERSION_MODULE_CONFIG "{module_config}"
#define VERSION_WEBSITE "{website}"
#define VERSION_DOCS_BRANCH "{docs_branch}"
#define VERSION_DOCS_URL "https://docs.godotengine.org/en/" VERSION_DOCS_BRANCH
""".format(**env.version_info)
#define GODOT_VERSION_SHORT_NAME "{short_name}"
#define GODOT_VERSION_NAME "{name}"
#define GODOT_VERSION_MAJOR {major}
#define GODOT_VERSION_MINOR {minor}
#define GODOT_VERSION_PATCH {patch}
#define GODOT_VERSION_STATUS "{status}"
#define GODOT_VERSION_BUILD "{build}"
#define GODOT_VERSION_MODULE_CONFIG "{module_config}"
#define GODOT_VERSION_WEBSITE "{website}"
#define GODOT_VERSION_DOCS_BRANCH "{docs_branch}"
#define GODOT_VERSION_DOCS_URL "https://docs.godotengine.org/en/" GODOT_VERSION_DOCS_BRANCH
""".format(**source[0].read())
)
env.CommandNoCache("version_generated.gen.h", env.Value(env.version_info), env.Run(version_info_builder))
env.CommandNoCache(
"version_generated.gen.h",
env.Value(methods.get_version_info(env.module_version_string)),
env.Run(version_info_builder),
)
# Generate version hash
def version_hash_builder(target, source, env):
with methods.generated_wrapper(target) as file:
with methods.generated_wrapper(str(target[0])) as file:
file.write(
"""\
#include "core/version.h"
const char *const VERSION_HASH = "{git_hash}";
const uint64_t VERSION_TIMESTAMP = {git_timestamp};
""".format(**env.version_info)
const char *const GODOT_VERSION_HASH = "{git_hash}";
const uint64_t GODOT_VERSION_TIMESTAMP = {git_timestamp};
""".format(**source[0].read())
)
gen_hash = env.CommandNoCache(
"version_hash.gen.cpp", env.Value(env.version_info["git_hash"]), env.Run(version_hash_builder)
)
gen_hash = env.CommandNoCache("version_hash.gen.cpp", env.Value(methods.get_git_info()), env.Run(version_hash_builder))
env.add_source_files(env.core_sources, gen_hash)
# Generate AES256 script encryption key
def encryption_key_builder(target, source, env):
with methods.generated_wrapper(target) as file:
with methods.generated_wrapper(str(target[0])) as file:
file.write(
f"""\
#include "core/config/project_settings.h"
@ -251,30 +252,21 @@ env.add_source_files(env.core_sources, gen_encrypt)
# Certificates
env.Depends(
"#core/io/certs_compressed.gen.h",
["#thirdparty/certs/ca-certificates.crt", env.Value(env["builtin_certs"]), env.Value(env["system_certs_path"])],
)
env.CommandNoCache(
"#core/io/certs_compressed.gen.h",
"#thirdparty/certs/ca-certificates.crt",
["#thirdparty/certs/ca-certificates.crt", env.Value(env["builtin_certs"]), env.Value(env["system_certs_path"])],
env.Run(core_builders.make_certs_header),
)
# Authors
env.Depends("#core/authors.gen.h", "../AUTHORS.md")
env.CommandNoCache("#core/authors.gen.h", "../AUTHORS.md", env.Run(core_builders.make_authors_header))
env.CommandNoCache("#core/authors.gen.h", "#AUTHORS.md", env.Run(core_builders.make_authors_header))
# Donors
env.Depends("#core/donors.gen.h", "../DONORS.md")
env.CommandNoCache("#core/donors.gen.h", "../DONORS.md", env.Run(core_builders.make_donors_header))
env.CommandNoCache("#core/donors.gen.h", "#DONORS.md", env.Run(core_builders.make_donors_header))
# License
env.Depends("#core/license.gen.h", ["../COPYRIGHT.txt", "../LICENSE.txt"])
env.CommandNoCache(
"#core/license.gen.h",
["../COPYRIGHT.txt", "../LICENSE.txt"],
env.Run(core_builders.make_license_header),
"#core/license.gen.h", ["#COPYRIGHT.txt", "#LICENSE.txt"], env.Run(core_builders.make_license_header)
)
# Chain load SCsubs

View file

@ -125,17 +125,17 @@ double Engine::get_unfrozen_time_scale() const {
Dictionary Engine::get_version_info() const {
Dictionary dict;
dict["major"] = VERSION_MAJOR;
dict["minor"] = VERSION_MINOR;
dict["patch"] = VERSION_PATCH;
dict["hex"] = VERSION_HEX;
dict["status"] = VERSION_STATUS;
dict["build"] = VERSION_BUILD;
dict["major"] = GODOT_VERSION_MAJOR;
dict["minor"] = GODOT_VERSION_MINOR;
dict["patch"] = GODOT_VERSION_PATCH;
dict["hex"] = GODOT_VERSION_HEX;
dict["status"] = GODOT_VERSION_STATUS;
dict["build"] = GODOT_VERSION_BUILD;
String hash = String(VERSION_HASH);
String hash = String(GODOT_VERSION_HASH);
dict["hash"] = hash.is_empty() ? String("unknown") : hash;
dict["timestamp"] = VERSION_TIMESTAMP;
dict["timestamp"] = GODOT_VERSION_TIMESTAMP;
String stringver = String(dict["major"]) + "." + String(dict["minor"]);
if ((int)dict["patch"] != 0) {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef ENGINE_H
#define ENGINE_H
#pragma once
#include "core/os/main_loop.h"
#include "core/string/ustring.h"
@ -214,5 +213,3 @@ public:
Engine();
virtual ~Engine();
};
#endif // ENGINE_H

View file

@ -77,7 +77,7 @@ String ProjectSettings::get_imported_files_path() const {
// This is used by the project manager to provide the initial_settings for config/features.
const PackedStringArray ProjectSettings::get_required_features() {
PackedStringArray features;
features.append(VERSION_BRANCH);
features.append(GODOT_VERSION_BRANCH);
#ifdef REAL_T_IS_DOUBLE
features.append("Double Precision");
#endif
@ -92,9 +92,9 @@ const PackedStringArray ProjectSettings::_get_supported_features() {
#endif
// Allow pinning to a specific patch number or build type by marking
// them as supported. They're only used if the user adds them manually.
features.append(VERSION_BRANCH "." _MKSTR(VERSION_PATCH));
features.append(VERSION_FULL_CONFIG);
features.append(VERSION_FULL_BUILD);
features.append(GODOT_VERSION_BRANCH "." _MKSTR(GODOT_VERSION_PATCH));
features.append(GODOT_VERSION_FULL_CONFIG);
features.append(GODOT_VERSION_FULL_BUILD);
#ifdef RD_ENABLED
features.append("Forward Plus");
@ -173,7 +173,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
if (dir->change_dir(path) == OK) {
String cwd = dir->get_current_dir();
cwd = cwd.replace("\\", "/");
cwd = cwd.replace_char('\\', '/');
// Ensure that we end with a '/'.
// This is important to ensure that we do not wrongly localize the resource path
@ -208,7 +208,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
if (plocal[plocal.length() - 1] == '/') {
sep += 1;
}
return plocal + path.substr(sep, path.size() - sep);
return plocal + path.substr(sep);
}
}
@ -289,7 +289,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
remove_autoload(node_name);
}
} else if (p_name.operator String().begins_with("global_group/")) {
String group_name = p_name.operator String().get_slice("/", 1);
String group_name = p_name.operator String().get_slicec('/', 1);
if (global_groups.has(group_name)) {
remove_global_group(group_name);
}
@ -340,7 +340,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
}
add_autoload(autoload);
} else if (p_name.operator String().begins_with("global_group/")) {
String group_name = p_name.operator String().get_slice("/", 1);
String group_name = p_name.operator String().get_slicec('/', 1);
add_global_group(group_name, p_value);
}
}
@ -359,14 +359,14 @@ bool ProjectSettings::_get(const StringName &p_name, Variant &r_ret) const {
return true;
}
Variant ProjectSettings::get_setting_with_override(const StringName &p_name) const {
Variant ProjectSettings::get_setting_with_override_and_custom_features(const StringName &p_name, const Vector<String> &p_features) const {
_THREAD_SAFE_METHOD_
StringName name = p_name;
if (feature_overrides.has(name)) {
const LocalVector<Pair<StringName, StringName>> &overrides = feature_overrides[name];
for (uint32_t i = 0; i < overrides.size(); i++) {
if (OS::get_singleton()->has_feature(overrides[i].first)) { // Custom features are checked in OS.has_feature() already. No need to check twice.
if (p_features.has(String(overrides[i].first).to_lower())) {
if (props.has(overrides[i].second)) {
name = overrides[i].second;
break;
@ -376,12 +376,39 @@ Variant ProjectSettings::get_setting_with_override(const StringName &p_name) con
}
if (!props.has(name)) {
WARN_PRINT(vformat("Property not found: '%s'.", String(name)));
WARN_PRINT("Property not found: " + String(name));
return Variant();
}
return props[name].variant;
}
Variant ProjectSettings::get_setting_with_override(const StringName &p_name) const {
_THREAD_SAFE_METHOD_
const LocalVector<Pair<StringName, StringName>> *overrides = feature_overrides.getptr(p_name);
if (overrides) {
for (uint32_t i = 0; i < overrides->size(); i++) {
if (!OS::get_singleton()->has_feature((*overrides)[i].first)) {
continue;
}
// Custom features are checked in OS.has_feature() already. No need to check twice.
const RBMap<StringName, VariantContainer>::Element *override_prop = props.find((*overrides)[i].second);
if (override_prop) {
return override_prop->get().variant;
}
}
}
const RBMap<StringName, VariantContainer>::Element *prop = props.find(p_name);
if (!prop) {
WARN_PRINT(vformat("Property not found: '%s'.", p_name));
return Variant();
}
return prop->get().variant;
}
struct _VCSort {
String name;
Variant::Type type = Variant::VARIANT_MAX;
@ -564,7 +591,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
if (!OS::get_singleton()->get_resource_dir().is_empty()) {
// OS will call ProjectSettings->get_resource_path which will be empty if not overridden!
// If the OS would rather use a specific location, then it will not be empty.
resource_path = OS::get_singleton()->get_resource_dir().replace("\\", "/");
resource_path = OS::get_singleton()->get_resource_dir().replace_char('\\', '/');
if (!resource_path.is_empty() && resource_path[resource_path.length() - 1] == '/') {
resource_path = resource_path.substr(0, resource_path.length() - 1); // Chop end.
}
@ -685,7 +712,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
while (true) {
// Set the resource path early so things can be resolved when loading.
resource_path = current_dir;
resource_path = resource_path.replace("\\", "/"); // Windows path to Unix path just in case.
resource_path = resource_path.replace_char('\\', '/'); // Windows path to Unix path just in case.
err = _load_settings_text_or_binary(current_dir.path_join("project.godot"), current_dir.path_join("project.binary"));
if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
@ -770,8 +797,7 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) {
cs.resize(slen + 1);
cs[slen] = 0;
f->get_buffer((uint8_t *)cs.ptr(), slen);
String key;
key.parse_utf8(cs.ptr(), slen);
String key = String::utf8(cs.ptr(), slen);
uint32_t vlen = f->get_32();
Vector<uint8_t> d;
@ -1129,7 +1155,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
category = "";
} else {
category = category.substr(0, div);
name = name.substr(div + 1, name.size());
name = name.substr(div + 1);
}
save_props[category].push_back(name);
}
@ -1141,7 +1167,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
save_features += ",";
}
String f = p_custom_features[i].strip_edges().replace("\"", "");
String f = p_custom_features[i].strip_edges().remove_char('\"');
save_features += f;
}
@ -1408,6 +1434,7 @@ void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_setting", "name", "default_value"), &ProjectSettings::get_setting, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("get_setting_with_override", "name"), &ProjectSettings::get_setting_with_override);
ClassDB::bind_method(D_METHOD("get_global_class_list"), &ProjectSettings::get_global_class_list);
ClassDB::bind_method(D_METHOD("get_setting_with_override_and_custom_features", "name", "features"), &ProjectSettings::get_setting_with_override_and_custom_features);
ClassDB::bind_method(D_METHOD("set_order", "name", "position"), &ProjectSettings::set_order);
ClassDB::bind_method(D_METHOD("get_order", "name"), &ProjectSettings::get_order);
ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &ProjectSettings::set_initial_value);
@ -1434,8 +1461,8 @@ void ProjectSettings::_add_builtin_input_map() {
Array events;
// Convert list of input events into array
for (List<Ref<InputEvent>>::Element *I = E.value.front(); I; I = I->next()) {
events.push_back(I->get());
for (const Ref<InputEvent> &event : E.value) {
events.push_back(event);
}
Dictionary action;
@ -1488,6 +1515,9 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("application/config/auto_accept_quit", true);
GLOBAL_DEF("application/config/quit_on_go_back", true);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "accessibility/general/accessibility_support", PROPERTY_HINT_ENUM, "Auto (When Screen Reader is Running),Always Active,Disabled"), 0);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "accessibility/general/updates_per_second", PROPERTY_HINT_RANGE, "1,100,1"), 60);
// The default window size is tuned to:
// - Have a 16:9 aspect ratio,
// - Have both dimensions divisible by 8 to better play along with video recording,
@ -1497,9 +1527,10 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "display/window/size/mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen,Exclusive Fullscreen"), 0);
// Keep the enum values in sync with the `DisplayServer::SCREEN_` enum.
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "display/window/size/initial_position_type", PROPERTY_HINT_ENUM, "Absolute,Center of Primary Screen,Center of Other Screen,Center of Screen With Mouse Pointer,Center of Screen With Keyboard Focus"), 1);
// Keep the enum values in sync with the `Window::WINDOW_INITIAL_POSITION_` enum.
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "display/window/size/initial_position_type", PROPERTY_HINT_ENUM, "Absolute:0,Center of Primary Screen:1,Center of Other Screen:3,Center of Screen With Mouse Pointer:4,Center of Screen With Keyboard Focus:5"), 1);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::VECTOR2I, "display/window/size/initial_position"), Vector2i());
// Keep the enum values in sync with the `DisplayServer::SCREEN_` enum.
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "display/window/size/initial_screen", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), 0);
GLOBAL_DEF_BASIC("display/window/size/resizable", true);
@ -1509,6 +1540,8 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("display/window/size/extend_to_title", false);
GLOBAL_DEF("display/window/size/no_focus", false);
GLOBAL_DEF("display/window/size/sharp_corners", false);
GLOBAL_DEF("display/window/size/minimize_disabled", false);
GLOBAL_DEF("display/window/size/maximize_disabled", false);
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"), 0); // 8K resolution
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 0); // 8K resolution
@ -1543,8 +1576,13 @@ ProjectSettings::ProjectSettings() {
#else
custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Unsafe (deprecated),Safe,Separate");
#endif
#ifndef PHYSICS_2D_DISABLED
GLOBAL_DEF("physics/2d/run_on_separate_thread", false);
#endif // PHYSICS_2D_DISABLED
#ifndef PHYSICS_3D_DISABLED
GLOBAL_DEF("physics/3d/run_on_separate_thread", false);
#endif // PHYSICS_3D_DISABLED
GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "display/window/stretch/mode", PROPERTY_HINT_ENUM, "disabled,canvas_items,viewport"), "disabled");
GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "display/window/stretch/aspect", PROPERTY_HINT_ENUM, "ignore,keep,keep_width,keep_height,expand"), "keep");
@ -1612,6 +1650,8 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_long_press_as_right_click", false);
GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_pan_and_scale_gestures", false);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "input_devices/pointing/android/rotary_input_scroll_axis", PROPERTY_HINT_ENUM, "Horizontal,Vertical"), 1);
GLOBAL_DEF("input_devices/pointing/android/override_volume_buttons", false);
GLOBAL_DEF_BASIC("input_devices/pointing/android/disable_scroll_deadzone", false);
// These properties will not show up in the dialog. If you want to exclude whole groups, use add_hidden_prefix().
GLOBAL_DEF_INTERNAL("application/config/features", PackedStringArray());
@ -1620,6 +1660,19 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_INTERNAL("internationalization/locale/translations_pot_files", PackedStringArray());
GLOBAL_DEF_INTERNAL("internationalization/locale/translation_add_builtin_strings_to_pot", false);
#if !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
GLOBAL_DEF("navigation/world/map_use_async_iterations", true);
GLOBAL_DEF("navigation/avoidance/thread_model/avoidance_use_multiple_threads", true);
GLOBAL_DEF("navigation/avoidance/thread_model/avoidance_use_high_priority_threads", true);
GLOBAL_DEF("navigation/pathfinding/max_threads", 4);
GLOBAL_DEF("navigation/baking/use_crash_prevention_checks", true);
GLOBAL_DEF("navigation/baking/thread_model/baking_use_multiple_threads", true);
GLOBAL_DEF("navigation/baking/thread_model/baking_use_high_priority_threads", true);
#endif // !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
ProjectSettings::get_singleton()->add_hidden_prefix("input/");
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PROJECT_SETTINGS_H
#define PROJECT_SETTINGS_H
#pragma once
#include "core/object/class_db.h"
@ -194,6 +193,7 @@ public:
List<String> get_input_presets() const { return input_presets; }
Variant get_setting_with_override(const StringName &p_name) const;
Variant get_setting_with_override_and_custom_features(const StringName &p_name, const Vector<String> &p_features) const;
bool is_using_datapack() const;
bool is_project_loaded() const;
@ -243,5 +243,3 @@ Variant _GLOBAL_DEF(const PropertyInfo &p_info, const Variant &p_default, bool p
#define GLOBAL_DEF_RST_NOVAL_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true, true)
#define GLOBAL_DEF_INTERNAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, false, false, true)
#endif // PROJECT_SETTINGS_H

View file

@ -30,7 +30,7 @@
#ifndef DISABLE_DEPRECATED
namespace core_bind {
namespace CoreBind {
// Semaphore
@ -53,10 +53,12 @@ Dictionary OS::_execute_with_pipe_bind_compat_94434(const String &p_path, const
}
void OS::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("read_string_from_stdin", "buffer_size"), &OS::read_string_from_stdin);
ClassDB::bind_compatibility_method(D_METHOD("read_buffer_from_stdin", "buffer_size"), &OS::read_buffer_from_stdin);
ClassDB::bind_compatibility_method(D_METHOD("read_string_from_stdin"), &OS::_read_string_from_stdin_bind_compat_91201);
ClassDB::bind_compatibility_method(D_METHOD("execute_with_pipe", "path", "arguments"), &OS::_execute_with_pipe_bind_compat_94434);
}
} // namespace core_bind
} // namespace CoreBind
#endif // DISABLE_DEPRECATED

View file

@ -42,7 +42,7 @@
#include "core/os/thread_safe.h"
#include "core/variant/typed_array.h"
namespace core_bind {
namespace CoreBind {
////// ResourceLoader //////
@ -466,8 +466,8 @@ bool OS::is_restart_on_exit_set() const {
Vector<String> OS::get_restart_on_exit_arguments() const {
List<String> args = ::OS::get_singleton()->get_restart_on_exit_arguments();
Vector<String> args_vector;
for (List<String>::Element *E = args.front(); E; E = E->next()) {
args_vector.push_back(E->get());
for (const String &arg : args) {
args_vector.push_back(arg);
}
return args_vector;
@ -657,8 +657,8 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_system_font_path_for_text", "font_name", "text", "locale", "script", "weight", "stretch", "italic"), &OS::get_system_font_path_for_text, DEFVAL(String()), DEFVAL(String()), DEFVAL(400), DEFVAL(100), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
ClassDB::bind_method(D_METHOD("read_string_from_stdin", "buffer_size"), &OS::read_string_from_stdin);
ClassDB::bind_method(D_METHOD("read_buffer_from_stdin", "buffer_size"), &OS::read_buffer_from_stdin);
ClassDB::bind_method(D_METHOD("read_string_from_stdin", "buffer_size"), &OS::read_string_from_stdin, DEFVAL(1024));
ClassDB::bind_method(D_METHOD("read_buffer_from_stdin", "buffer_size"), &OS::read_buffer_from_stdin, DEFVAL(1024));
ClassDB::bind_method(D_METHOD("get_stdin_type"), &OS::get_stdin_type);
ClassDB::bind_method(D_METHOD("get_stdout_type"), &OS::get_stdout_type);
ClassDB::bind_method(D_METHOD("get_stderr_type"), &OS::get_stderr_type);
@ -806,13 +806,11 @@ Vector<Vector2> Geometry2D::get_closest_points_between_segments(const Vector2 &p
}
Vector2 Geometry2D::get_closest_point_to_segment(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
Vector2 s[2] = { p_a, p_b };
return ::Geometry2D::get_closest_point_to_segment(p_point, s);
return ::Geometry2D::get_closest_point_to_segment(p_point, p_a, p_b);
}
Vector2 Geometry2D::get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) {
Vector2 s[2] = { p_a, p_b };
return ::Geometry2D::get_closest_point_to_segment_uncapped(p_point, s);
return ::Geometry2D::get_closest_point_to_segment_uncapped(p_point, p_a, p_b);
}
bool Geometry2D::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const {
@ -1069,13 +1067,11 @@ Vector<Vector3> Geometry3D::get_closest_points_between_segments(const Vector3 &p
}
Vector3 Geometry3D::get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
Vector3 s[2] = { p_a, p_b };
return ::Geometry3D::get_closest_point_to_segment(p_point, s);
return ::Geometry3D::get_closest_point_to_segment(p_point, p_a, p_b);
}
Vector3 Geometry3D::get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) {
Vector3 s[2] = { p_a, p_b };
return ::Geometry3D::get_closest_point_to_segment_uncapped(p_point, s);
return ::Geometry3D::get_closest_point_to_segment_uncapped(p_point, p_a, p_b);
}
Vector3 Geometry3D::get_triangle_barycentric_coords(const Vector3 &p_point, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
@ -1241,6 +1237,9 @@ Vector<uint8_t> Marshalls::base64_to_raw(const String &p_str) {
}
String Marshalls::utf8_to_base64(const String &p_str) {
if (p_str.is_empty()) {
return String();
}
CharString cstr = p_str.utf8();
String ret = CryptoCore::b64_encode_str((unsigned char *)cstr.get_data(), cstr.length());
ERR_FAIL_COND_V(ret.is_empty(), ret);
@ -1340,6 +1339,7 @@ void Thread::_start_func(void *ud) {
// When the call returns, we will reference the thread again if possible.
ObjectID th_instance_id = t->get_instance_id();
Callable target_callable = t->target_callable;
String id = t->get_id();
t = Ref<Thread>();
Callable::CallError ce;
@ -1347,7 +1347,7 @@ void Thread::_start_func(void *ud) {
target_callable.callp(nullptr, 0, ret, ce);
// If script properly kept a reference to the thread, we should be able to re-reference it now
// (well, or if the call failed, since we had to break chains anyway because the outcome isn't known upfront).
t = Ref<Thread>(ObjectDB::get_instance(th_instance_id));
t = ObjectDB::get_ref<Thread>(th_instance_id);
if (t.is_valid()) {
t->ret = ret;
t->running.clear();
@ -1357,7 +1357,7 @@ void Thread::_start_func(void *ud) {
}
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_MSG(vformat("Could not call function '%s' to start thread %d: %s.", func_name, t->get_id(), Variant::get_callable_error_text(t->target_callable, nullptr, 0, ce)));
ERR_FAIL_MSG(vformat("Could not call function '%s' to start thread %s: %s.", func_name, id, Variant::get_callable_error_text(target_callable, nullptr, 0, ce)));
}
}
@ -1419,7 +1419,7 @@ void Thread::_bind_methods() {
BIND_ENUM_CONSTANT(PRIORITY_HIGH);
}
namespace special {
namespace Special {
////// ClassDB //////
@ -1438,8 +1438,8 @@ PackedStringArray ClassDB::get_class_list() const {
}
PackedStringArray ClassDB::get_inheriters_from_class(const StringName &p_class) const {
List<StringName> classes;
::ClassDB::get_inheriters_from_class(p_class, &classes);
LocalVector<StringName> classes;
::ClassDB::get_inheriters_from_class(p_class, classes);
PackedStringArray ret;
ret.resize(classes.size());
@ -1746,7 +1746,7 @@ void ClassDB::_bind_methods() {
BIND_ENUM_CONSTANT(API_NONE);
}
} // namespace special
} // namespace Special
////// Engine //////
@ -1876,8 +1876,8 @@ Vector<String> Engine::get_singleton_list() const {
List<::Engine::Singleton> singletons;
::Engine::get_singleton()->get_singletons(&singletons);
Vector<String> ret;
for (List<::Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
ret.push_back(E->get().name);
for (const ::Engine::Singleton &E : singletons) {
ret.push_back(E.name);
}
return ret;
}
@ -2190,4 +2190,4 @@ void EngineDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_breakpoints"), &EngineDebugger::clear_breakpoints);
}
} // namespace core_bind
} // namespace CoreBind

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CORE_BIND_H
#define CORE_BIND_H
#pragma once
#include "core/debugger/engine_profiler.h"
#include "core/io/resource_loader.h"
@ -42,7 +41,7 @@ class MainLoop;
template <typename T>
class TypedArray;
namespace core_bind {
namespace CoreBind {
class ResourceLoader : public Object {
GDCLASS(ResourceLoader, Object);
@ -458,7 +457,7 @@ public:
static void set_thread_safety_checks_enabled(bool p_enabled);
};
namespace special {
namespace Special {
class ClassDB : public Object {
GDCLASS(ClassDB, Object);
@ -524,7 +523,7 @@ public:
~ClassDB() {}
};
} // namespace special
} // namespace Special
class Engine : public Object {
GDCLASS(Engine, Object);
@ -652,23 +651,21 @@ public:
~EngineDebugger();
};
} // namespace core_bind
} // namespace CoreBind
VARIANT_ENUM_CAST(core_bind::ResourceLoader::ThreadLoadStatus);
VARIANT_ENUM_CAST(core_bind::ResourceLoader::CacheMode);
VARIANT_ENUM_CAST(CoreBind::ResourceLoader::ThreadLoadStatus);
VARIANT_ENUM_CAST(CoreBind::ResourceLoader::CacheMode);
VARIANT_BITFIELD_CAST(core_bind::ResourceSaver::SaverFlags);
VARIANT_BITFIELD_CAST(CoreBind::ResourceSaver::SaverFlags);
VARIANT_ENUM_CAST(core_bind::OS::RenderingDriver);
VARIANT_ENUM_CAST(core_bind::OS::SystemDir);
VARIANT_ENUM_CAST(core_bind::OS::StdHandleType);
VARIANT_ENUM_CAST(CoreBind::OS::RenderingDriver);
VARIANT_ENUM_CAST(CoreBind::OS::SystemDir);
VARIANT_ENUM_CAST(CoreBind::OS::StdHandleType);
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyBooleanOperation);
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyJoinType);
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyEndType);
VARIANT_ENUM_CAST(CoreBind::Geometry2D::PolyBooleanOperation);
VARIANT_ENUM_CAST(CoreBind::Geometry2D::PolyJoinType);
VARIANT_ENUM_CAST(CoreBind::Geometry2D::PolyEndType);
VARIANT_ENUM_CAST(core_bind::Thread::Priority);
VARIANT_ENUM_CAST(CoreBind::Thread::Priority);
VARIANT_ENUM_CAST(core_bind::special::ClassDB::APIType);
#endif // CORE_BIND_H
VARIANT_ENUM_CAST(CoreBind::Special::ClassDB::APIType);

View file

@ -1,171 +1,104 @@
"""Functions used to generate source files during build time"""
import zlib
from collections import OrderedDict
from io import TextIOWrapper
def escape_string(s):
def charcode_to_c_escapes(c):
rev_result = []
while c >= 256:
c, low = (c // 256, c % 256)
rev_result.append("\\%03o" % low)
rev_result.append("\\%03o" % c)
return "".join(reversed(rev_result))
result = ""
if isinstance(s, str):
s = s.encode("utf-8")
for c in s:
if not (32 <= c < 127) or c in (ord("\\"), ord('"')):
result += charcode_to_c_escapes(c)
else:
result += chr(c)
return result
import methods
def make_certs_header(target, source, env):
src = str(source[0])
dst = str(target[0])
with open(src, "rb") as f, open(dst, "w", encoding="utf-8", newline="\n") as g:
buf = f.read()
decomp_size = len(buf)
# Use maximum zlib compression level to further reduce file size
# (at the cost of initial build times).
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef CERTS_COMPRESSED_GEN_H\n")
g.write("#define CERTS_COMPRESSED_GEN_H\n")
buffer = methods.get_buffer(str(source[0]))
decomp_size = len(buffer)
buffer = methods.compress_buffer(buffer)
with methods.generated_wrapper(str(target[0])) as file:
# System certs path. Editor will use them if defined. (for package maintainers)
path = env["system_certs_path"]
g.write('#define _SYSTEM_CERTS_PATH "%s"\n' % str(path))
file.write('#define _SYSTEM_CERTS_PATH "{}"\n'.format(env["system_certs_path"]))
if env["builtin_certs"]:
# Defined here and not in env so changing it does not trigger a full rebuild.
g.write("#define BUILTIN_CERTS_ENABLED\n")
g.write("static const int _certs_compressed_size = " + str(len(buf)) + ";\n")
g.write("static const int _certs_uncompressed_size = " + str(decomp_size) + ";\n")
g.write("static const unsigned char _certs_compressed[] = {\n")
for i in range(len(buf)):
g.write("\t" + str(buf[i]) + ",\n")
g.write("};\n")
g.write("#endif // CERTS_COMPRESSED_GEN_H")
file.write(f"""\
#define BUILTIN_CERTS_ENABLED
inline constexpr int _certs_compressed_size = {len(buffer)};
inline constexpr int _certs_uncompressed_size = {decomp_size};
inline constexpr unsigned char _certs_compressed[] = {{
{methods.format_buffer(buffer, 1)}
}};
""")
def make_authors_header(target, source, env):
sections = [
"Project Founders",
"Lead Developer",
"Project Manager",
"Developers",
]
sections_id = [
"AUTHORS_FOUNDERS",
"AUTHORS_LEAD_DEVELOPERS",
"AUTHORS_PROJECT_MANAGERS",
"AUTHORS_DEVELOPERS",
]
SECTIONS = {
"Project Founders": "AUTHORS_FOUNDERS",
"Lead Developer": "AUTHORS_LEAD_DEVELOPERS",
"Project Manager": "AUTHORS_PROJECT_MANAGERS",
"Developers": "AUTHORS_DEVELOPERS",
}
buffer = methods.get_buffer(str(source[0]))
reading = False
src = str(source[0])
dst = str(target[0])
with open(src, "r", encoding="utf-8") as f, open(dst, "w", encoding="utf-8", newline="\n") as g:
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef AUTHORS_GEN_H\n")
g.write("#define AUTHORS_GEN_H\n")
reading = False
with methods.generated_wrapper(str(target[0])) as file:
def close_section():
g.write("\t0\n")
g.write("};\n")
file.write("\tnullptr,\n};\n\n")
for line in f:
if reading:
if line.startswith(" "):
g.write('\t"' + escape_string(line.strip()) + '",\n')
continue
if line.startswith("## "):
for line in buffer.decode().splitlines():
if line.startswith(" ") and reading:
file.write(f'\t"{methods.to_escaped_cstring(line).strip()}",\n')
elif line.startswith("## "):
if reading:
close_section()
reading = False
for section, section_id in zip(sections, sections_id):
if line.strip().endswith(section):
current_section = escape_string(section_id)
reading = True
g.write("const char *const " + current_section + "[] = {\n")
break
section = SECTIONS[line[3:].strip()]
if section:
file.write(f"inline constexpr const char *{section}[] = {{\n")
reading = True
if reading:
close_section()
g.write("#endif // AUTHORS_GEN_H\n")
def make_donors_header(target, source, env):
sections = [
"Patrons",
"Platinum sponsors",
"Gold sponsors",
"Silver sponsors",
"Diamond members",
"Titanium members",
"Platinum members",
"Gold members",
]
sections_id = [
"DONORS_PATRONS",
"DONORS_SPONSORS_PLATINUM",
"DONORS_SPONSORS_GOLD",
"DONORS_SPONSORS_SILVER",
"DONORS_MEMBERS_DIAMOND",
"DONORS_MEMBERS_TITANIUM",
"DONORS_MEMBERS_PLATINUM",
"DONORS_MEMBERS_GOLD",
]
SECTIONS = {
"Patrons": "DONORS_PATRONS",
"Platinum sponsors": "DONORS_SPONSORS_PLATINUM",
"Gold sponsors": "DONORS_SPONSORS_GOLD",
"Silver sponsors": "DONORS_SPONSORS_SILVER",
"Diamond members": "DONORS_MEMBERS_DIAMOND",
"Titanium members": "DONORS_MEMBERS_TITANIUM",
"Platinum members": "DONORS_MEMBERS_PLATINUM",
"Gold members": "DONORS_MEMBERS_GOLD",
}
buffer = methods.get_buffer(str(source[0]))
reading = False
src = str(source[0])
dst = str(target[0])
with open(src, "r", encoding="utf-8") as f, open(dst, "w", encoding="utf-8", newline="\n") as g:
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("#ifndef DONORS_GEN_H\n")
g.write("#define DONORS_GEN_H\n")
reading = False
with methods.generated_wrapper(str(target[0])) as file:
def close_section():
g.write("\t0\n")
g.write("};\n")
file.write("\tnullptr,\n};\n\n")
for line in f:
if reading >= 0:
if line.startswith(" "):
g.write('\t"' + escape_string(line.strip()) + '",\n')
continue
if line.startswith("## "):
for line in buffer.decode().splitlines():
if line.startswith(" ") and reading:
file.write(f'\t"{methods.to_escaped_cstring(line).strip()}",\n')
elif line.startswith("## "):
if reading:
close_section()
reading = False
for section, section_id in zip(sections, sections_id):
if line.strip().endswith(section):
current_section = escape_string(section_id)
reading = True
g.write("const char *const " + current_section + "[] = {\n")
break
section = SECTIONS.get(line[3:].strip())
if section:
file.write(f"inline constexpr const char *{section}[] = {{\n")
reading = True
if reading:
close_section()
g.write("#endif // DONORS_GEN_H\n")
def make_license_header(target, source, env):
src_copyright = str(source[0])
src_license = str(source[1])
dst = str(target[0])
class LicenseReader:
def __init__(self, license_file):
def __init__(self, license_file: TextIOWrapper):
self._license_file = license_file
self.line_num = 0
self.current = self.next_line()
@ -188,9 +121,7 @@ def make_license_header(target, source, env):
lines.append(self.current.strip())
return (tag, lines)
from collections import OrderedDict
projects: dict = OrderedDict()
projects = OrderedDict()
license_list = []
with open(src_copyright, "r", encoding="utf-8") as copyright_file:
@ -212,7 +143,7 @@ def make_license_header(target, source, env):
part = {}
reader.next_line()
data_list: list = []
data_list = []
for project in iter(projects.values()):
for part in project:
part["file_index"] = len(data_list)
@ -220,96 +151,76 @@ def make_license_header(target, source, env):
part["copyright_index"] = len(data_list)
data_list += part["Copyright"]
with open(dst, "w", encoding="utf-8", newline="\n") as f:
f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
f.write("#ifndef LICENSE_GEN_H\n")
f.write("#define LICENSE_GEN_H\n")
f.write("const char *const GODOT_LICENSE_TEXT =")
with open(src_license, "r", encoding="utf-8") as file:
license_text = file.read()
with open(src_license, "r", encoding="utf-8") as license_file:
for line in license_file:
escaped_string = escape_string(line.strip())
f.write('\n\t\t"' + escaped_string + '\\n"')
f.write(";\n\n")
with methods.generated_wrapper(str(target[0])) as file:
file.write(f"""\
inline constexpr const char *GODOT_LICENSE_TEXT = {{
{methods.to_raw_cstring(license_text)}
}};
f.write(
"struct ComponentCopyrightPart {\n"
"\tconst char *license;\n"
"\tconst char *const *files;\n"
"\tconst char *const *copyright_statements;\n"
"\tint file_count;\n"
"\tint copyright_count;\n"
"};\n\n"
)
struct ComponentCopyrightPart {{
const char *license;
const char *const *files;
const char *const *copyright_statements;
int file_count;
int copyright_count;
}};
f.write(
"struct ComponentCopyright {\n"
"\tconst char *name;\n"
"\tconst ComponentCopyrightPart *parts;\n"
"\tint part_count;\n"
"};\n\n"
)
struct ComponentCopyright {{
const char *name;
const ComponentCopyrightPart *parts;
int part_count;
}};
f.write("const char *const COPYRIGHT_INFO_DATA[] = {\n")
""")
file.write("inline constexpr const char *COPYRIGHT_INFO_DATA[] = {\n")
for line in data_list:
f.write('\t"' + escape_string(line) + '",\n')
f.write("};\n\n")
file.write(f'\t"{methods.to_escaped_cstring(line)}",\n')
file.write("};\n\n")
f.write("const ComponentCopyrightPart COPYRIGHT_PROJECT_PARTS[] = {\n")
file.write("inline constexpr ComponentCopyrightPart COPYRIGHT_PROJECT_PARTS[] = {\n")
part_index = 0
part_indexes = {}
for project_name, project in iter(projects.items()):
part_indexes[project_name] = part_index
for part in project:
f.write(
'\t{ "'
+ escape_string(part["License"][0])
+ '", '
+ "&COPYRIGHT_INFO_DATA["
+ str(part["file_index"])
+ "], "
+ "&COPYRIGHT_INFO_DATA["
+ str(part["copyright_index"])
+ "], "
+ str(len(part["Files"]))
+ ", "
+ str(len(part["Copyright"]))
+ " },\n"
file.write(
f'\t{{ "{methods.to_escaped_cstring(part["License"][0])}", '
+ f"&COPYRIGHT_INFO_DATA[{part['file_index']}], "
+ f"&COPYRIGHT_INFO_DATA[{part['copyright_index']}], "
+ f"{len(part['Files'])}, {len(part['Copyright'])} }},\n"
)
part_index += 1
f.write("};\n\n")
file.write("};\n\n")
f.write("const int COPYRIGHT_INFO_COUNT = " + str(len(projects)) + ";\n")
file.write(f"inline constexpr int COPYRIGHT_INFO_COUNT = {len(projects)};\n")
f.write("const ComponentCopyright COPYRIGHT_INFO[] = {\n")
file.write("inline constexpr ComponentCopyright COPYRIGHT_INFO[] = {\n")
for project_name, project in iter(projects.items()):
f.write(
'\t{ "'
+ escape_string(project_name)
+ '", '
+ "&COPYRIGHT_PROJECT_PARTS["
+ str(part_indexes[project_name])
+ "], "
+ str(len(project))
+ " },\n"
file.write(
f'\t{{ "{methods.to_escaped_cstring(project_name)}", '
+ f"&COPYRIGHT_PROJECT_PARTS[{part_indexes[project_name]}], "
+ f"{len(project)} }},\n"
)
f.write("};\n\n")
file.write("};\n\n")
f.write("const int LICENSE_COUNT = " + str(len(license_list)) + ";\n")
file.write(f"inline constexpr int LICENSE_COUNT = {len(license_list)};\n")
f.write("const char *const LICENSE_NAMES[] = {\n")
file.write("inline constexpr const char *LICENSE_NAMES[] = {\n")
for license in license_list:
f.write('\t"' + escape_string(license[0]) + '",\n')
f.write("};\n\n")
file.write(f'\t"{methods.to_escaped_cstring(license[0])}",\n')
file.write("};\n\n")
f.write("const char *const LICENSE_BODIES[] = {\n\n")
file.write("inline constexpr const char *LICENSE_BODIES[] = {\n\n")
for license in license_list:
to_raw = []
for line in license[1:]:
if line == ".":
f.write('\t"\\n"\n')
to_raw += [""]
else:
f.write('\t"' + escape_string(line) + '\\n"\n')
f.write('\t"",\n\n')
f.write("};\n\n")
f.write("#endif // LICENSE_GEN_H\n")
to_raw += [line]
file.write(f"{methods.to_raw_cstring(to_raw)},\n\n")
file.write("};\n\n")

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CORE_CONSTANTS_H
#define CORE_CONSTANTS_H
#pragma once
#include "core/string/string_name.h"
#include "core/templates/hash_map.h"
@ -47,5 +46,3 @@ public:
static bool is_global_enum(const StringName &p_enum);
static void get_enum_values(const StringName &p_enum, HashMap<StringName, int64_t> *p_values);
};
#endif // CORE_CONSTANTS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CORE_GLOBALS_H
#define CORE_GLOBALS_H
#pragma once
// Home for state needed from global functions
// that cannot be stored in Engine or OS due to e.g. circular includes
@ -40,5 +39,3 @@ public:
static bool print_line_enabled;
static bool print_error_enabled;
};
#endif // CORE_GLOBALS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CORE_STRING_NAMES_H
#define CORE_STRING_NAMES_H
#pragma once
#include "core/string/string_name.h"
@ -87,5 +86,3 @@ public:
};
#define CoreStringName(m_name) CoreStringNames::get_singleton()->m_name
#endif // CORE_STRING_NAMES_H

View file

@ -13,7 +13,7 @@ if is_builtin or not has_module:
# Use our headers for builtin or if the module is not going to be compiled.
# We decided not to depend on system mbedtls just for these few files that can
# be easily extracted.
env_crypto.Prepend(CPPPATH=["#thirdparty/mbedtls/include"])
env_crypto.Prepend(CPPEXTPATH=["#thirdparty/mbedtls/include"])
# MbedTLS core functions (for CryptoCore).
# If the mbedtls module is compiled we don't need to add the .c files with our

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef AES_CONTEXT_H
#define AES_CONTEXT_H
#pragma once
#include "core/crypto/crypto_core.h"
#include "core/object/ref_counted.h"
@ -64,5 +63,3 @@ public:
};
VARIANT_ENUM_CAST(AESContext::Mode);
#endif // AES_CONTEXT_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CRYPTO_H
#define CRYPTO_H
#pragma once
#include "core/crypto/hashing_context.h"
#include "core/io/resource.h"
@ -167,5 +166,3 @@ public:
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
virtual bool recognize(const Ref<Resource> &p_resource) const override;
};
#endif // CRYPTO_H

View file

@ -214,8 +214,8 @@ Error CryptoCore::AESContext::decrypt_cfb(size_t p_length, uint8_t p_iv[16], con
}
// CryptoCore
String CryptoCore::b64_encode_str(const uint8_t *p_src, int p_src_len) {
int b64len = p_src_len / 3 * 4 + 4 + 1;
String CryptoCore::b64_encode_str(const uint8_t *p_src, size_t p_src_len) {
size_t b64len = p_src_len / 3 * 4 + 4 + 1;
Vector<uint8_t> b64buff;
b64buff.resize(b64len);
uint8_t *w64 = b64buff.ptrw();
@ -225,27 +225,27 @@ String CryptoCore::b64_encode_str(const uint8_t *p_src, int p_src_len) {
return ret ? String() : (const char *)&w64[0];
}
Error CryptoCore::b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len) {
Error CryptoCore::b64_encode(uint8_t *r_dst, size_t p_dst_len, size_t *r_len, const uint8_t *p_src, size_t p_src_len) {
int ret = mbedtls_base64_encode(r_dst, p_dst_len, r_len, p_src, p_src_len);
return ret ? FAILED : OK;
}
Error CryptoCore::b64_decode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len) {
Error CryptoCore::b64_decode(uint8_t *r_dst, size_t p_dst_len, size_t *r_len, const uint8_t *p_src, size_t p_src_len) {
int ret = mbedtls_base64_decode(r_dst, p_dst_len, r_len, p_src, p_src_len);
return ret ? FAILED : OK;
}
Error CryptoCore::md5(const uint8_t *p_src, int p_src_len, unsigned char r_hash[16]) {
Error CryptoCore::md5(const uint8_t *p_src, size_t p_src_len, unsigned char r_hash[16]) {
int ret = mbedtls_md5_ret(p_src, p_src_len, r_hash);
return ret ? FAILED : OK;
}
Error CryptoCore::sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]) {
Error CryptoCore::sha1(const uint8_t *p_src, size_t p_src_len, unsigned char r_hash[20]) {
int ret = mbedtls_sha1_ret(p_src, p_src_len, r_hash);
return ret ? FAILED : OK;
}
Error CryptoCore::sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]) {
Error CryptoCore::sha256(const uint8_t *p_src, size_t p_src_len, unsigned char r_hash[32]) {
int ret = mbedtls_sha256_ret(p_src, p_src_len, r_hash, 0);
return ret ? FAILED : OK;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CRYPTO_CORE_H
#define CRYPTO_CORE_H
#pragma once
#include "core/object/ref_counted.h"
@ -107,13 +106,11 @@ public:
Error decrypt_cfb(size_t p_length, uint8_t p_iv[16], const uint8_t *p_src, uint8_t *r_dst);
};
static String b64_encode_str(const uint8_t *p_src, int p_src_len);
static Error b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len);
static Error b64_decode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len);
static String b64_encode_str(const uint8_t *p_src, size_t p_src_len);
static Error b64_encode(uint8_t *r_dst, size_t p_dst_len, size_t *r_len, const uint8_t *p_src, size_t p_src_len);
static Error b64_decode(uint8_t *r_dst, size_t p_dst_len, size_t *r_len, const uint8_t *p_src, size_t p_src_len);
static Error md5(const uint8_t *p_src, int p_src_len, unsigned char r_hash[16]);
static Error sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]);
static Error sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]);
static Error md5(const uint8_t *p_src, size_t p_src_len, unsigned char r_hash[16]);
static Error sha1(const uint8_t *p_src, size_t p_src_len, unsigned char r_hash[20]);
static Error sha256(const uint8_t *p_src, size_t p_src_len, unsigned char r_hash[32]);
};
#endif // CRYPTO_CORE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef HASHING_CONTEXT_H
#define HASHING_CONTEXT_H
#pragma once
#include "core/object/ref_counted.h"
@ -62,5 +61,3 @@ public:
};
VARIANT_ENUM_CAST(HashingContext::HashType);
#endif // HASHING_CONTEXT_H

View file

@ -36,8 +36,7 @@
#define CHECK_END(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)arr.size() > (uint32_t)expected, false, String("Malformed ") + what + " message from script debugger, message too long. Expected size: " + itos(expected) + ", actual size: " + itos(arr.size()))
Array DebuggerMarshalls::ScriptStackDump::serialize() {
Array arr;
arr.push_back(frames.size() * 3);
Array arr = { frames.size() * 3 };
for (const ScriptLanguage::StackInfo &frame : frames) {
arr.push_back(frame.file);
arr.push_back(frame.line);
@ -64,10 +63,7 @@ bool DebuggerMarshalls::ScriptStackDump::deserialize(const Array &p_arr) {
}
Array DebuggerMarshalls::ScriptStackVariable::serialize(int max_size) {
Array arr;
arr.push_back(name);
arr.push_back(type);
arr.push_back(value.get_type());
Array arr = { name, type, value.get_type() };
Variant var = value;
if (value.get_type() == Variant::OBJECT && value.get_validated_object() == nullptr) {
@ -99,20 +95,20 @@ bool DebuggerMarshalls::ScriptStackVariable::deserialize(const Array &p_arr) {
}
Array DebuggerMarshalls::OutputError::serialize() {
Array arr;
arr.push_back(hr);
arr.push_back(min);
arr.push_back(sec);
arr.push_back(msec);
arr.push_back(source_file);
arr.push_back(source_func);
arr.push_back(source_line);
arr.push_back(error);
arr.push_back(error_descr);
arr.push_back(warning);
unsigned int size = callstack.size();
Array arr = {
hr,
min,
sec, msec,
source_file,
source_func,
source_line,
error,
error_descr,
warning,
size * 3
};
const ScriptLanguage::StackInfo *r = callstack.ptr();
arr.push_back(size * 3);
for (int i = 0; i < callstack.size(); i++) {
arr.push_back(r[i].file);
arr.push_back(r[i].func);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DEBUGGER_MARSHALLS_H
#define DEBUGGER_MARSHALLS_H
#pragma once
#include "core/input/shortcut.h"
#include "core/object/script_language.h"
@ -73,5 +72,3 @@ struct DebuggerMarshalls {
static Array serialize_key_shortcut(const Ref<Shortcut> &p_shortcut);
static Ref<Shortcut> deserialize_key_shortcut(const Array &p_keys);
};
#endif // DEBUGGER_MARSHALLS_H

View file

@ -127,7 +127,7 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks,
singleton->poll_events(true);
}
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)()) {
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)()) {
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more.
if (p_uri.is_empty()) {
return;
@ -149,8 +149,7 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, co
singleton = memnew(RemoteDebugger(Ref<RemoteDebuggerPeer>(peer)));
script_debugger = memnew(ScriptDebugger);
// Notify editor of our pid (to allow focus stealing).
Array msg;
msg.push_back(OS::get_singleton()->get_process_id());
Array msg = { OS::get_singleton()->get_process_id() };
singleton->send_message("set_pid", msg);
}
if (!singleton) {
@ -160,13 +159,14 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, co
// There is a debugger, parse breakpoints.
ScriptDebugger *singleton_script_debugger = singleton->get_script_debugger();
singleton_script_debugger->set_skip_breakpoints(p_skip_breakpoints);
singleton_script_debugger->set_ignore_error_breaks(p_ignore_error_breaks);
for (int i = 0; i < p_breakpoints.size(); i++) {
const String &bp = p_breakpoints[i];
int sp = bp.rfind_char(':');
ERR_CONTINUE_MSG(sp == -1, vformat("Invalid breakpoint: '%s', expected file:line format.", bp));
singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp));
singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1).to_int(), bp.substr(0, sp));
}
allow_focus_steal_fn = p_allow_focus_steal_fn;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef ENGINE_DEBUGGER_H
#define ENGINE_DEBUGGER_H
#pragma once
#include "core/string/string_name.h"
#include "core/string/ustring.h"
@ -107,7 +106,7 @@ public:
_FORCE_INLINE_ static ScriptDebugger *get_script_debugger() { return script_debugger; }
static void initialize(const String &p_uri, bool p_skip_breakpoints, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)());
static void initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)());
static void deinitialize();
static void register_profiler(const StringName &p_name, const Profiler &p_profiler);
static void unregister_profiler(const StringName &p_name);
@ -140,5 +139,3 @@ public:
virtual ~EngineDebugger();
};
#endif // ENGINE_DEBUGGER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef ENGINE_PROFILER_H
#define ENGINE_PROFILER_H
#pragma once
#include "core/object/gdvirtual.gen.inc"
#include "core/object/ref_counted.h"
@ -59,5 +58,3 @@ public:
EngineProfiler() {}
virtual ~EngineProfiler();
};
#endif // ENGINE_PROFILER_H

View file

@ -242,7 +242,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
} else if (line.begins_with("br") || line.begins_with("break")) {
if (line.get_slice_count(" ") <= 1) {
const HashMap<int, HashSet<StringName>> &breakpoints = script_debugger->get_breakpoints();
if (breakpoints.size() == 0) {
if (breakpoints.is_empty()) {
print_line("No Breakpoints.");
continue;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef LOCAL_DEBUGGER_H
#define LOCAL_DEBUGGER_H
#pragma once
#include "core/debugger/engine_debugger.h"
#include "core/object/script_language.h"
@ -55,5 +54,3 @@ public:
LocalDebugger();
~LocalDebugger();
};
#endif // LOCAL_DEBUGGER_H

View file

@ -95,10 +95,7 @@ public:
};
Error RemoteDebugger::_put_msg(const String &p_message, const Array &p_data) {
Array msg;
msg.push_back(p_message);
msg.push_back(Thread::get_caller_id());
msg.push_back(p_data);
Array msg = { p_message, Thread::get_caller_id(), p_data };
Error err = peer->put_message(msg);
if (err != OK) {
n_messages_dropped++;
@ -235,9 +232,7 @@ void RemoteDebugger::flush_output() {
types.push_back(MESSAGE_TYPE_LOG);
}
Array arr;
arr.push_back(strings);
arr.push_back(types);
Array arr = { strings, types };
_put_msg("output", arr);
output_strings.clear();
}
@ -413,17 +408,25 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
}
ScriptLanguage *script_lang = script_debugger->get_break_language();
const String error_str = script_lang ? script_lang->debug_get_error() : "";
Array msg;
msg.push_back(p_can_continue);
msg.push_back(error_str);
ERR_FAIL_NULL(script_lang);
msg.push_back(script_lang->debug_get_stack_level_count() > 0);
msg.push_back(Thread::get_caller_id() == Thread::get_main_id() ? String(RTR("Main Thread")) : itos(Thread::get_caller_id()));
if (allow_focus_steal_fn) {
allow_focus_steal_fn();
const bool can_break = !(p_is_error_breakpoint && script_debugger->is_ignoring_error_breaks());
const String error_str = script_lang ? script_lang->debug_get_error() : "";
if (can_break) {
Array msg = {
p_can_continue,
error_str,
script_lang->debug_get_stack_level_count() > 0,
Thread::get_caller_id()
};
if (allow_focus_steal_fn) {
allow_focus_steal_fn();
}
send_message("debug_enter", msg);
} else {
ERR_PRINT(error_str);
return;
}
send_message("debug_enter", msg);
Input::MouseMode mouse_mode = Input::MOUSE_MODE_VISIBLE;
@ -507,8 +510,7 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
script_lang->debug_get_globals(&globals, &globals_vals);
ERR_FAIL_COND(globals.size() != globals_vals.size());
Array var_size;
var_size.push_back(local_vals.size() + member_vals.size() + globals_vals.size());
Array var_size = { local_vals.size() + member_vals.size() + globals_vals.size() };
send_message("stack_frame_vars", var_size);
_send_stack_vars(locals, local_vals, 0);
_send_stack_vars(members, member_vals, 1);
@ -530,6 +532,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
} else if (command == "set_skip_breakpoints") {
ERR_FAIL_COND(data.is_empty());
script_debugger->set_skip_breakpoints(data[0]);
} else if (command == "set_ignore_error_breaks") {
ERR_FAIL_COND(data.is_empty());
script_debugger->set_ignore_error_breaks(data[0]);
} else if (command == "evaluate") {
String expression_str = data[0];
int frame = data[1];
@ -669,6 +674,9 @@ Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bo
} else if (p_cmd == "set_skip_breakpoints") {
ERR_FAIL_COND_V(p_data.is_empty(), ERR_INVALID_DATA);
script_debugger->set_skip_breakpoints(p_data[0]);
} else if (p_cmd == "set_ignore_error_breaks") {
ERR_FAIL_COND_V(p_data.is_empty(), ERR_INVALID_DATA);
script_debugger->set_ignore_error_breaks(p_data[0]);
} else if (p_cmd == "break") {
script_debugger->debug(script_debugger->get_break_language());
} else {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef REMOTE_DEBUGGER_H
#define REMOTE_DEBUGGER_H
#pragma once
#include "core/debugger/debugger_marshalls.h"
#include "core/debugger/engine_debugger.h"
@ -122,5 +121,3 @@ public:
explicit RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer);
~RemoteDebugger();
};
#endif // REMOTE_DEBUGGER_H

View file

@ -96,7 +96,7 @@ void RemoteDebuggerPeerTCP::_write_out() {
while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED && tcp_client->wait(NetSocket::POLL_TYPE_OUT) == OK) {
uint8_t *buf = out_buf.ptrw();
if (out_left <= 0) {
if (out_queue.size() == 0) {
if (out_queue.is_empty()) {
break; // Nothing left to send
}
mutex.lock();

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef REMOTE_DEBUGGER_PEER_H
#define REMOTE_DEBUGGER_PEER_H
#pragma once
#include "core/io/stream_peer_tcp.h"
#include "core/object/ref_counted.h"
@ -92,5 +91,3 @@ public:
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream = Ref<StreamPeerTCP>());
~RemoteDebuggerPeerTCP();
};
#endif // REMOTE_DEBUGGER_PEER_H

View file

@ -58,7 +58,7 @@ void ScriptDebugger::remove_breakpoint(int p_line, const StringName &p_source) {
}
breakpoints[p_line].erase(p_source);
if (breakpoints[p_line].size() == 0) {
if (breakpoints[p_line].is_empty()) {
breakpoints.erase(p_line);
}
}
@ -79,6 +79,14 @@ bool ScriptDebugger::is_skipping_breakpoints() {
return skip_breakpoints;
}
void ScriptDebugger::set_ignore_error_breaks(bool p_ignore) {
ignore_error_breaks = p_ignore;
}
bool ScriptDebugger::is_ignoring_error_breaks() {
return ignore_error_breaks;
}
void ScriptDebugger::debug(ScriptLanguage *p_lang, bool p_can_continue, bool p_is_error_breakpoint) {
ScriptLanguage *prev = break_lang;
break_lang = p_lang;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef SCRIPT_DEBUGGER_H
#define SCRIPT_DEBUGGER_H
#pragma once
#include "core/object/script_language.h"
#include "core/string/string_name.h"
@ -40,6 +39,7 @@ class ScriptDebugger {
typedef ScriptLanguage::StackInfo StackInfo;
bool skip_breakpoints = false;
bool ignore_error_breaks = false;
HashMap<int, HashSet<StringName>> breakpoints;
@ -64,6 +64,8 @@ public:
ScriptLanguage *get_break_language() { return break_lang; }
void set_skip_breakpoints(bool p_skip_breakpoints);
bool is_skipping_breakpoints();
void set_ignore_error_breaks(bool p_ignore);
bool is_ignoring_error_breaks();
void insert_breakpoint(int p_line, const StringName &p_source);
void remove_breakpoint(int p_line, const StringName &p_source);
_ALWAYS_INLINE_ bool is_breakpoint(int p_line, const StringName &p_source) const {
@ -82,5 +84,3 @@ public:
Vector<StackInfo> get_error_stack_info() const;
ScriptDebugger() {}
};
#endif // SCRIPT_DEBUGGER_H

View file

@ -32,11 +32,11 @@
String DocData::get_default_value_string(const Variant &p_value) {
if (p_value.get_type() == Variant::ARRAY) {
return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace("\n", " ");
return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace_char('\n', ' ');
} else if (p_value.get_type() == Variant::DICTIONARY) {
return Variant(Dictionary(p_value, 0, StringName(), Variant(), 0, StringName(), Variant())).get_construct_string().replace("\n", " ");
return Variant(Dictionary(p_value, 0, StringName(), Variant(), 0, StringName(), Variant())).get_construct_string().replace_char('\n', ' ');
} else {
return p_value.get_construct_string().replace("\n", " ");
return p_value.get_construct_string().replace_char('\n', ' ');
}
}
@ -51,7 +51,7 @@ void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const Proper
} else if (p_retinfo.type == Variant::INT && p_retinfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
p_method.return_enum = p_retinfo.class_name;
if (p_method.return_enum.begins_with("_")) { //proxy class
p_method.return_enum = p_method.return_enum.substr(1, p_method.return_enum.length());
p_method.return_enum = p_method.return_enum.substr(1);
}
p_method.return_is_bitfield = p_retinfo.usage & PROPERTY_USAGE_CLASS_IS_BITFIELD;
p_method.return_type = "int";
@ -85,7 +85,7 @@ void DocData::argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const
} else if (p_arginfo.type == Variant::INT && p_arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
p_argument.enumeration = p_arginfo.class_name;
if (p_argument.enumeration.begins_with("_")) { //proxy class
p_argument.enumeration = p_argument.enumeration.substr(1, p_argument.enumeration.length());
p_argument.enumeration = p_argument.enumeration.substr(1);
}
p_argument.is_bitfield = p_arginfo.usage & PROPERTY_USAGE_CLASS_IS_BITFIELD;
p_argument.type = "int";
@ -136,11 +136,10 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met
return_doc_from_retinfo(p_method, p_methodinfo.return_val);
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = p_methodinfo.arguments.begin(); itr != p_methodinfo.arguments.end(); ++itr, ++i) {
for (int64_t i = 0; i < p_methodinfo.arguments.size(); ++i) {
DocData::ArgumentDoc argument;
argument_doc_from_arginfo(argument, *itr);
int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size());
argument_doc_from_arginfo(argument, p_methodinfo.arguments[i]);
int64_t default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size());
if (default_arg_index >= 0) {
Variant default_arg = p_methodinfo.default_arguments[default_arg_index];
argument.default_value = get_default_value_string(default_arg);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DOC_DATA_H
#define DOC_DATA_H
#pragma once
#include "core/io/xml_parser.h"
#include "core/variant/variant.h"
@ -115,7 +114,7 @@ public:
// Must be an operator or a constructor since there is no other overloading
if (name.left(8) == "operator") {
if (arguments.size() == p_method.arguments.size()) {
if (arguments.size() == 0) {
if (arguments.is_empty()) {
return false;
}
return arguments[0].type < p_method.arguments[0].type;
@ -127,7 +126,7 @@ public:
// - 1. Default constructor: Foo()
// - 2. Copy constructor: Foo(Foo)
// - 3+. Other constructors Foo(Bar, ...) based on first argument's name
if (arguments.size() == 0 || p_method.arguments.size() == 0) { // 1.
if (arguments.is_empty() || p_method.arguments.is_empty()) { // 1.
return arguments.size() < p_method.arguments.size();
}
if (arguments[0].type == return_type || p_method.arguments[0].type == p_method.return_type) { // 2.
@ -795,8 +794,8 @@ public:
if (p_dict.has("enums")) {
enums = p_dict["enums"];
}
for (int i = 0; i < enums.size(); i++) {
doc.enums[enums.get_key_at_index(i)] = EnumDoc::from_dict(enums.get_value_at_index(i));
for (const KeyValue<Variant, Variant> &kv : enums) {
doc.enums[kv.key] = EnumDoc::from_dict(kv.value);
}
Array properties;
@ -980,5 +979,3 @@ public:
static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo);
static void method_doc_from_methodinfo(DocData::MethodDoc &p_method, const MethodInfo &p_methodinfo, const String &p_desc);
};
#endif // DOC_DATA_H

View file

@ -30,6 +30,8 @@
#include "error_list.h"
#include <iterator>
const char *error_names[] = {
"OK", // OK
"Failed", // FAILED
@ -82,4 +84,4 @@ const char *error_names[] = {
"Printer on fire", // ERR_PRINTER_ON_FIRE
};
static_assert(sizeof(error_names) / sizeof(*error_names) == ERR_MAX);
static_assert(std::size(error_names) == ERR_MAX);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef ERROR_LIST_H
#define ERROR_LIST_H
#pragma once
/** Error List. Please never compare an error against FAILED
* Either do result != OK , or !result. This way, Error fail
@ -98,5 +97,3 @@ enum Error {
};
extern const char *error_names[];
#endif // ERROR_LIST_H

View file

@ -31,6 +31,7 @@
#include "error_macros.h"
#include "core/io/logger.h"
#include "core/object/object_id.h"
#include "core/os/os.h"
#include "core/string/ustring.h"
@ -187,7 +188,7 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
} else {
String node_name;
if (p_id.is_valid()) {
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_id));
Node *node = ObjectDB::get_instance<Node>(p_id);
if (node && node->is_inside_tree()) {
node_name = "\"" + String(node->get_path()) + "\"";
} else {

View file

@ -28,15 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef ERROR_MACROS_H
#define ERROR_MACROS_H
#pragma once
#include "core/object/object_id.h"
#include "core/typedefs.h"
#include <atomic> // We'd normally use safe_refcount.h, but that would cause circular includes.
#include <atomic> // IWYU pragma: keep // Used in macro. We'd normally use `safe_refcount.h`, but that would cause circular includes.
class String;
class ObjectID;
enum ErrorHandlerType {
ERR_HANDLER_ERROR,
@ -62,16 +61,16 @@ void add_error_handler(ErrorHandlerList *p_handler);
void remove_error_handler(const ErrorHandlerList *p_handler);
// Functions used by the error macros.
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_error_asap(const String &p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool fatal = false);
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false);
void _err_flush_stdout();
_NO_INLINE_ void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool fatal = false);
_NO_INLINE_ void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false);
_NO_INLINE_ void _err_flush_stdout();
void _physics_interpolation_warning(const char *p_function, const char *p_file, int p_line, ObjectID p_id, const char *p_warn_string);
@ -845,5 +844,3 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
#define PHYSICS_INTERPOLATION_WARNING(m_string) \
_physics_interpolation_warning(FUNCTION_STR, __FILE__, __LINE__, ObjectID(UINT64_MAX), m_string)
#endif // ERROR_MACROS_H

View file

@ -96,8 +96,7 @@ static String fix_doc_description(const String &p_bbcode) {
// Based on what EditorHelp does.
return p_bbcode.dedent()
.replace("\t", "")
.replace("\r", "")
.remove_chars("\t\r")
.strip_edges();
}
@ -107,16 +106,22 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
{
//header
Dictionary header;
header["version_major"] = VERSION_MAJOR;
header["version_minor"] = VERSION_MINOR;
#if VERSION_PATCH
header["version_patch"] = VERSION_PATCH;
header["version_major"] = GODOT_VERSION_MAJOR;
header["version_minor"] = GODOT_VERSION_MINOR;
#if GODOT_VERSION_PATCH
header["version_patch"] = GODOT_VERSION_PATCH;
#else
header["version_patch"] = 0;
#endif
header["version_status"] = VERSION_STATUS;
header["version_build"] = VERSION_BUILD;
header["version_full_name"] = VERSION_FULL_NAME;
header["version_status"] = GODOT_VERSION_STATUS;
header["version_build"] = GODOT_VERSION_BUILD;
header["version_full_name"] = GODOT_VERSION_FULL_NAME;
#if REAL_T_IS_DOUBLE
header["precision"] = "double";
#else
header["precision"] = "single";
#endif
api_dump["header"] = header;
}
@ -278,43 +283,43 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
#define REAL_MEMBER_OFFSET(type, member) \
{ \
type, \
member, \
"float", \
sizeof(float), \
"float", \
sizeof(float), \
"double", \
sizeof(double), \
"double", \
sizeof(double), \
member, \
"float", \
sizeof(float), \
"float", \
sizeof(float), \
"double", \
sizeof(double), \
"double", \
sizeof(double), \
}
#define INT32_MEMBER_OFFSET(type, member) \
{ \
type, \
member, \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
member, \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
}
#define INT32_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
{ \
type, \
member, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
}
#define REAL_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
@ -970,14 +975,14 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
Array values;
List<StringName> enum_constant_list;
ClassDB::get_enum_constants(class_name, F, &enum_constant_list, true);
for (List<StringName>::Element *G = enum_constant_list.front(); G; G = G->next()) {
for (const StringName &enum_constant : enum_constant_list) {
Dictionary d3;
d3["name"] = String(G->get());
d3["value"] = ClassDB::get_integer_constant(class_name, G->get());
d3["name"] = String(enum_constant);
d3["value"] = ClassDB::get_integer_constant(class_name, enum_constant);
if (p_include_docs) {
for (const DocData::ConstantDoc &constant_doc : class_doc->constants) {
if (constant_doc.name == G->get()) {
if (constant_doc.name == enum_constant) {
d3["description"] = fix_doc_description(constant_doc.description);
break;
}
@ -1048,9 +1053,8 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
}
Array arguments;
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = mi.arguments.begin(); itr != mi.arguments.end(); ++itr, ++i) {
const PropertyInfo &pinfo = *itr;
for (int64_t i = 0; i < mi.arguments.size(); ++i) {
const PropertyInfo &pinfo = mi.arguments[i];
Dictionary d3;
d3["name"] = pinfo.name;
@ -1175,11 +1179,10 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
Array arguments;
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = F.arguments.begin(); itr != F.arguments.end(); ++itr, ++i) {
for (int64_t i = 0; i < F.arguments.size(); ++i) {
Dictionary d3;
d3["name"] = itr->name;
d3["type"] = get_property_info_type_name(*itr);
d3["name"] = F.arguments[i].name;
d3["type"] = get_property_info_type_name(F.arguments[i]);
if (F.get_argument_meta(i) > 0) {
d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)F.get_argument_meta(i));
}
@ -1340,16 +1343,16 @@ static bool compare_value(const String &p_path, const String &p_field, const Var
} else if (p_old_value.get_type() == Variant::DICTIONARY && p_new_value.get_type() == Variant::DICTIONARY) {
Dictionary old_dict = p_old_value;
Dictionary new_dict = p_new_value;
for (const Variant &key : old_dict.keys()) {
if (!new_dict.has(key)) {
for (const KeyValue<Variant, Variant> &kv : old_dict) {
if (!new_dict.has(kv.key)) {
failed = true;
print_error(vformat("Validate extension JSON: Error: Field '%s': %s was removed.", p_path, key));
print_error(vformat("Validate extension JSON: Error: Field '%s': %s was removed.", p_path, kv.key));
continue;
}
if (p_allow_name_change && key == "name") {
if (p_allow_name_change && kv.key == "name") {
continue;
}
if (!compare_value(path, key, old_dict[key], new_dict[key], p_allow_name_change)) {
if (!compare_value(path, kv.key, kv.value, new_dict[kv.key], p_allow_name_change)) {
failed = true;
}
}
@ -1420,25 +1423,25 @@ static bool compare_dict_array(const Dictionary &p_old_api, const Dictionary &p_
bool optional = field.begins_with("*");
if (optional) {
// This is an optional field, but if exists it has to exist in both.
field = field.substr(1, field.length());
field = field.substr(1);
}
bool added = field.begins_with("+");
if (added) {
// Meaning this field must either exist or contents may not exist.
field = field.substr(1, field.length());
field = field.substr(1);
}
bool enum_values = field.begins_with("$");
if (enum_values) {
// Meaning this field is a list of enum values.
field = field.substr(1, field.length());
field = field.substr(1);
}
bool allow_name_change = field.begins_with("@");
if (allow_name_change) {
// Meaning that when structurally comparing the old and new value, the dictionary entry 'name' may change.
field = field.substr(1, field.length());
field = field.substr(1);
}
Variant old_value;
@ -1598,8 +1601,8 @@ Error GDExtensionAPIDump::validate_extension_json_file(const String &p_path) {
int major = header["version_major"];
int minor = header["version_minor"];
ERR_FAIL_COND_V_MSG(major != VERSION_MAJOR, ERR_INVALID_DATA, vformat("JSON API dump is for a different engine version (%d) than this one (%d)", major, VERSION_MAJOR));
ERR_FAIL_COND_V_MSG(minor > VERSION_MINOR, ERR_INVALID_DATA, vformat("JSON API dump is for a newer version of the engine: %d.%d", major, minor));
ERR_FAIL_COND_V_MSG(major != GODOT_VERSION_MAJOR, ERR_INVALID_DATA, vformat("JSON API dump is for a different engine version (%d) than this one (%d)", major, GODOT_VERSION_MAJOR));
ERR_FAIL_COND_V_MSG(minor > GODOT_VERSION_MINOR, ERR_INVALID_DATA, vformat("JSON API dump is for a newer version of the engine: %d.%d", major, minor));
}
bool failed = false;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EXTENSION_API_DUMP_H
#define EXTENSION_API_DUMP_H
#pragma once
#include "core/extension/gdextension.h"
@ -42,5 +41,3 @@ public:
static Error validate_extension_json_file(const String &p_path);
};
#endif
#endif // EXTENSION_API_DUMP_H

View file

@ -679,6 +679,13 @@ void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExte
memnew_placement(r_path, String(library_path));
}
void GDExtension::_register_get_classes_used_callback(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback) {
#ifdef TOOLS_ENABLED
GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
self->get_classes_used_callback = p_callback;
#endif
}
HashMap<StringName, GDExtensionInterfaceFunctionPtr> GDExtension::gdextension_interface_functions;
void GDExtension::register_interface_function(const StringName &p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer) {
@ -799,6 +806,7 @@ void GDExtension::initialize_gdextensions() {
register_interface_function("classdb_register_extension_class_signal", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_signal);
register_interface_function("classdb_unregister_extension_class", (GDExtensionInterfaceFunctionPtr)&GDExtension::_unregister_extension_class);
register_interface_function("get_library_path", (GDExtensionInterfaceFunctionPtr)&GDExtension::_get_library_path);
register_interface_function("editor_register_get_classes_used_callback", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_get_classes_used_callback);
}
void GDExtension::finalize_gdextensions() {
@ -1034,6 +1042,14 @@ void GDExtension::_untrack_instance(void *p_user_data, void *p_instance) {
extension->instances.erase(obj->get_instance_id());
}
PackedStringArray GDExtension::get_classes_used() const {
PackedStringArray ret;
if (get_classes_used_callback) {
get_classes_used_callback((GDExtensionTypePtr)&ret);
}
return ret;
}
Vector<StringName> GDExtensionEditorPlugins::extension_classes;
GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_add_plugin = nullptr;
GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_remove_plugin = nullptr;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_H
#define GDEXTENSION_H
#pragma once
#include "core/extension/gdextension_interface.h"
#include "core/extension/gdextension_loader.h"
@ -94,6 +93,7 @@ class GDExtension : public Resource {
static void _register_extension_class_signal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count);
static void _unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name);
static void _get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path);
static void _register_get_classes_used_callback(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback);
GDExtensionInitialization initialization;
int32_t level_initialized = -1;
@ -102,6 +102,7 @@ class GDExtension : public Resource {
bool is_reloading = false;
Vector<GDExtensionMethodBind *> invalid_methods;
Vector<ObjectID> instance_bindings;
GDExtensionEditorGetClassesUsedCallback get_classes_used_callback = nullptr;
static void _track_instance(void *p_user_data, void *p_instance);
static void _untrack_instance(void *p_user_data, void *p_instance);
@ -156,6 +157,8 @@ public:
void track_instance_binding(Object *p_object);
void untrack_instance_binding(Object *p_object);
PackedStringArray get_classes_used() const;
#endif
InitializationLevel get_minimum_library_initialization_level() const;
@ -226,5 +229,3 @@ public:
};
#endif // TOOLS_ENABLED
#endif // GDEXTENSION_H

View file

@ -241,11 +241,25 @@ GDExtensionInterfaceFunctionPtr gdextension_get_proc_address(const char *p_name)
return GDExtension::get_interface_function(p_name);
}
#ifndef DISABLE_DEPRECATED
static void gdextension_get_godot_version(GDExtensionGodotVersion *r_godot_version) {
r_godot_version->major = VERSION_MAJOR;
r_godot_version->minor = VERSION_MINOR;
r_godot_version->patch = VERSION_PATCH;
r_godot_version->string = VERSION_FULL_NAME;
r_godot_version->major = GODOT_VERSION_MAJOR;
r_godot_version->minor = GODOT_VERSION_MINOR;
r_godot_version->patch = GODOT_VERSION_PATCH;
r_godot_version->string = GODOT_VERSION_FULL_NAME;
}
#endif
static void gdextension_get_godot_version2(GDExtensionGodotVersion2 *r_godot_version) {
r_godot_version->major = GODOT_VERSION_MAJOR;
r_godot_version->minor = GODOT_VERSION_MINOR;
r_godot_version->patch = GODOT_VERSION_PATCH;
r_godot_version->hex = GODOT_VERSION_HEX;
r_godot_version->status = GODOT_VERSION_STATUS;
r_godot_version->build = GODOT_VERSION_BUILD;
r_godot_version->hash = GODOT_VERSION_HASH;
r_godot_version->timestamp = GODOT_VERSION_TIMESTAMP;
r_godot_version->string = GODOT_VERSION_FULL_NAME;
}
// Memory Functions
@ -858,84 +872,82 @@ static GDExtensionPtrUtilityFunction gdextension_variant_get_ptr_utility_functio
//string helpers
static void gdextension_string_new_with_latin1_chars(GDExtensionUninitializedStringPtr r_dest, const char *p_contents) {
memnew_placement(r_dest, String(p_contents));
String *dest = memnew_placement(r_dest, String);
dest->append_latin1(Span<char>(p_contents, p_contents ? strlen(p_contents) : 0));
}
static void gdextension_string_new_with_utf8_chars(GDExtensionUninitializedStringPtr r_dest, const char *p_contents) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf8(p_contents);
String *dest = memnew_placement(r_dest, String);
dest->append_utf8(p_contents);
}
static void gdextension_string_new_with_utf16_chars(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf16(p_contents);
String *dest = memnew_placement(r_dest, String);
dest->append_utf16(p_contents);
}
static void gdextension_string_new_with_utf32_chars(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents) {
memnew_placement(r_dest, String((const char32_t *)p_contents));
String *dest = memnew_placement(r_dest, String);
dest->append_utf32(Span(p_contents, p_contents ? strlen(p_contents) : 0));
}
static void gdextension_string_new_with_wide_chars(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents) {
if constexpr (sizeof(wchar_t) == 2) {
// wchar_t is 16 bit, parse.
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf16((const char16_t *)p_contents);
// wchar_t is 16 bit (UTF-16).
String *dest = memnew_placement(r_dest, String);
dest->append_utf16((const char16_t *)p_contents);
} else {
// wchar_t is 32 bit, copy.
memnew_placement(r_dest, String((const char32_t *)p_contents));
// wchar_t is 32 bit (UTF-32).
String *string = memnew_placement(r_dest, String);
string->append_utf32(Span((const char32_t *)p_contents, p_contents ? strlen(p_contents) : 0));
}
}
static void gdextension_string_new_with_latin1_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
memnew_placement(r_dest, String(p_contents, p_size));
String *dest = memnew_placement(r_dest, String);
dest->append_latin1(Span(p_contents, p_contents ? _strlen_clipped(p_contents, p_size) : 0));
}
static void gdextension_string_new_with_utf8_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf8(p_contents, p_size);
String *dest = memnew_placement(r_dest, String);
dest->append_utf8(p_contents, p_size);
}
static GDExtensionInt gdextension_string_new_with_utf8_chars_and_len2(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
return (GDExtensionInt)dest->parse_utf8(p_contents, p_size);
String *dest = memnew_placement(r_dest, String);
return (GDExtensionInt)dest->append_utf8(p_contents, p_size);
}
static void gdextension_string_new_with_utf16_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_char_count) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf16(p_contents, p_char_count);
String *dest = memnew_placement(r_dest, String);
dest->append_utf16(p_contents, p_char_count);
}
static GDExtensionInt gdextension_string_new_with_utf16_chars_and_len2(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_char_count, GDExtensionBool p_default_little_endian) {
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
return (GDExtensionInt)dest->parse_utf16(p_contents, p_char_count, p_default_little_endian);
String *dest = memnew_placement(r_dest, String);
return (GDExtensionInt)dest->append_utf16(p_contents, p_char_count, p_default_little_endian);
}
static void gdextension_string_new_with_utf32_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_char_count) {
memnew_placement(r_dest, String((const char32_t *)p_contents, p_char_count));
String *string = memnew_placement(r_dest, String);
string->append_utf32(Span(p_contents, p_contents ? _strlen_clipped(p_contents, p_char_count) : 0));
}
static void gdextension_string_new_with_wide_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_char_count) {
if constexpr (sizeof(wchar_t) == 2) {
// wchar_t is 16 bit, parse.
memnew_placement(r_dest, String);
String *dest = reinterpret_cast<String *>(r_dest);
dest->parse_utf16((const char16_t *)p_contents, p_char_count);
// wchar_t is 16 bit (UTF-16).
String *dest = memnew_placement(r_dest, String);
dest->append_utf16((const char16_t *)p_contents, p_char_count);
} else {
// wchar_t is 32 bit, copy.
memnew_placement(r_dest, String((const char32_t *)p_contents, p_char_count));
// wchar_t is 32 bit (UTF-32).
String *string = memnew_placement(r_dest, String);
string->append_utf32(Span((const char32_t *)p_contents, p_contents ? _strlen_clipped((const char32_t *)p_contents, p_char_count) : 0));
}
}
static GDExtensionInt gdextension_string_to_latin1_chars(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length) {
String *self = (String *)p_self;
CharString cs = self->ascii(true);
CharString cs = self->latin1();
GDExtensionInt len = cs.length();
if (r_text) {
const char *s_text = cs.ptr();
@ -1040,16 +1052,12 @@ static void gdextension_string_name_new_with_latin1_chars(GDExtensionUninitializ
}
static void gdextension_string_name_new_with_utf8_chars(GDExtensionUninitializedStringNamePtr r_dest, const char *p_contents) {
String tmp;
tmp.parse_utf8(p_contents);
String tmp = String::utf8(p_contents);
memnew_placement(r_dest, StringName(tmp));
}
static void gdextension_string_name_new_with_utf8_chars_and_len(GDExtensionUninitializedStringNamePtr r_dest, const char *p_contents, GDExtensionInt p_size) {
String tmp;
tmp.parse_utf8(p_contents, p_size);
String tmp = String::utf8(p_contents, p_size);
memnew_placement(r_dest, StringName(tmp));
}
@ -1543,11 +1551,8 @@ static void gdextension_placeholder_script_instance_update(GDExtensionScriptInst
properties_list.push_back(PropertyInfo::from_dict(d));
}
List<Variant> keys;
values.get_key_list(&keys);
for (const Variant &E : keys) {
values_map.insert(E, values[E]);
for (const KeyValue<Variant, Variant> &kv : values) {
values_map.insert(kv.key, kv.value);
}
placeholder->update(properties_list, values_map);
@ -1572,6 +1577,15 @@ static GDExtensionScriptInstancePtr gdextension_object_get_script_instance(GDExt
return script_instance_extension->instance;
}
static void gdextension_object_set_script_instance(GDExtensionObjectPtr p_object, GDExtensionScriptInstancePtr p_script_instance) {
ERR_FAIL_NULL(p_object);
Object *o = (Object *)p_object;
ScriptInstance *script_instance = (ScriptInstanceExtension *)p_script_instance;
o->set_script_instance(script_instance);
}
#ifndef DISABLE_DEPRECATED
static void gdextension_callable_custom_create(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo *p_custom_callable_info) {
memnew_placement(r_callable, Callable(memnew(CallableCustomExtension(p_custom_callable_info))));
@ -1666,7 +1680,10 @@ static void gdextension_editor_help_load_xml_from_utf8_chars(const char *p_data)
#define REGISTER_INTERFACE_FUNC(m_name) GDExtension::register_interface_function(#m_name, (GDExtensionInterfaceFunctionPtr) & gdextension_##m_name)
void gdextension_setup_interface() {
#ifndef DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(get_godot_version);
#endif // DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(get_godot_version2);
REGISTER_INTERFACE_FUNC(mem_alloc);
REGISTER_INTERFACE_FUNC(mem_realloc);
REGISTER_INTERFACE_FUNC(mem_free);
@ -1809,6 +1826,7 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(placeholder_script_instance_create);
REGISTER_INTERFACE_FUNC(placeholder_script_instance_update);
REGISTER_INTERFACE_FUNC(object_get_script_instance);
REGISTER_INTERFACE_FUNC(object_set_script_instance);
#ifndef DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(callable_custom_create);
#endif // DISABLE_DEPRECATED

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_INTERFACE_H
#define GDEXTENSION_INTERFACE_H
#pragma once
/* This is a C class header, you can copy it and use it directly in your own binders.
* Together with the JSON file, you should be able to generate any binder.
@ -401,6 +400,9 @@ typedef struct {
typedef void *GDExtensionClassLibraryPtr;
/* Passed a pointer to a PackedStringArray that should be filled with the classes that may be used by the GDExtension. */
typedef void (*GDExtensionEditorGetClassesUsedCallback)(GDExtensionTypePtr p_packed_string_array);
/* Method */
typedef enum {
@ -790,9 +792,22 @@ typedef struct {
const char *string;
} GDExtensionGodotVersion;
typedef struct {
uint32_t major;
uint32_t minor;
uint32_t patch;
uint32_t hex; // Full version encoded as hexadecimal with one byte (2 hex digits) per number (e.g. for "3.1.12" it would be 0x03010C)
const char *status; // (e.g. "stable", "beta", "rc1", "rc2")
const char *build; // (e.g. "custom_build")
const char *hash; // Full Git commit hash.
uint64_t timestamp; // Git commit date UNIX timestamp in seconds, or 0 if unavailable.
const char *string; // (e.g. "Godot v3.1.4.stable.official.mono")
} GDExtensionGodotVersion2;
/**
* @name get_godot_version
* @since 4.1
* @deprecated in Godot 4.5. Use `get_godot_version2` instead.
*
* Gets the Godot version that the GDExtension was loaded into.
*
@ -800,6 +815,16 @@ typedef struct {
*/
typedef void (*GDExtensionInterfaceGetGodotVersion)(GDExtensionGodotVersion *r_godot_version);
/**
* @name get_godot_version2
* @since 4.5
*
* Gets the Godot version that the GDExtension was loaded into.
*
* @param r_godot_version A pointer to the structure to write the version information into.
*/
typedef void (*GDExtensionInterfaceGetGodotVersion2)(GDExtensionGodotVersion2 *r_godot_version);
/* INTERFACE: Memory */
/**
@ -2721,6 +2746,17 @@ typedef void (*GDExtensionInterfacePlaceHolderScriptInstanceUpdate)(GDExtensionS
*/
typedef GDExtensionScriptInstanceDataPtr (*GDExtensionInterfaceObjectGetScriptInstance)(GDExtensionConstObjectPtr p_object, GDExtensionObjectPtr p_language);
/**
* @name object_set_script_instance
* @since 4.5
*
* Set the script instance data attached to this object.
*
* @param p_object A pointer to the Object.
* @param p_script_instance A pointer to the script instance data to attach to this object.
*/
typedef void (*GDExtensionInterfaceObjectSetScriptInstance)(GDExtensionObjectPtr p_object, GDExtensionScriptInstanceDataPtr p_script_instance);
/* INTERFACE: Callable */
/**
@ -3078,8 +3114,22 @@ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *
*/
typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size);
/**
* @name editor_register_get_classes_used_callback
* @since 4.5
*
* Registers a callback that Godot can call to get the list of all classes (from ClassDB) that may be used by the calling GDExtension.
*
* This is used by the editor to generate a build profile (in "Tools" > "Engine Compilation Configuration Editor..." > "Detect from project"),
* in order to recompile Godot with only the classes used.
* In the provided callback, the GDExtension should provide the list of classes that _may_ be used statically, thus the time of invocation shouldn't matter.
* If a GDExtension doesn't register a callback, Godot will assume that it could be using any classes.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_callback The callback to retrieve the list of classes used.
*/
typedef void (*GDExtensionInterfaceEditorRegisterGetClassesUsedCallback)(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback);
#ifdef __cplusplus
}
#endif
#endif // GDEXTENSION_INTERFACE_H

View file

@ -307,12 +307,12 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
bool compatible = true;
// Check version lexicographically.
if (VERSION_MAJOR != compatibility_minimum[0]) {
compatible = VERSION_MAJOR > compatibility_minimum[0];
} else if (VERSION_MINOR != compatibility_minimum[1]) {
compatible = VERSION_MINOR > compatibility_minimum[1];
if (GODOT_VERSION_MAJOR != compatibility_minimum[0]) {
compatible = GODOT_VERSION_MAJOR > compatibility_minimum[0];
} else if (GODOT_VERSION_MINOR != compatibility_minimum[1]) {
compatible = GODOT_VERSION_MINOR > compatibility_minimum[1];
} else {
compatible = VERSION_PATCH >= compatibility_minimum[2];
compatible = GODOT_VERSION_PATCH >= compatibility_minimum[2];
}
if (!compatible) {
ERR_PRINT(vformat("GDExtension only compatible with Godot version %d.%d.%d or later: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
@ -334,15 +334,15 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
}
compatible = true;
if (VERSION_MAJOR != compatibility_maximum[0]) {
compatible = VERSION_MAJOR < compatibility_maximum[0];
} else if (VERSION_MINOR != compatibility_maximum[1]) {
compatible = VERSION_MINOR < compatibility_maximum[1];
if (GODOT_VERSION_MAJOR != compatibility_maximum[0]) {
compatible = GODOT_VERSION_MAJOR < compatibility_maximum[0];
} else if (GODOT_VERSION_MINOR != compatibility_maximum[1]) {
compatible = GODOT_VERSION_MINOR < compatibility_maximum[1];
}
#if VERSION_PATCH
#if GODOT_VERSION_PATCH
// #if check to avoid -Wtype-limits warning when 0.
else {
compatible = VERSION_PATCH <= compatibility_maximum[2];
compatible = GODOT_VERSION_PATCH <= compatibility_maximum[2];
}
#endif

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_LIBRARY_LOADER_H
#define GDEXTENSION_LIBRARY_LOADER_H
#pragma once
#include <functional>
@ -38,6 +37,8 @@
#include "core/os/shared_object.h"
class GDExtensionLibraryLoader : public GDExtensionLoader {
GDSOFTCLASS(GDExtensionLibraryLoader, GDExtensionLoader);
friend class GDExtensionManager;
friend class GDExtension;
@ -81,5 +82,3 @@ public:
Error parse_gdextension_file(const String &p_path);
};
#endif // GDEXTENSION_LIBRARY_LOADER_H

View file

@ -28,14 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_LOADER_H
#define GDEXTENSION_LOADER_H
#pragma once
#include "core/object/ref_counted.h"
class GDExtension;
class GDExtensionLoader : public RefCounted {
GDSOFTCLASS(GDExtensionLoader, GDExtensionLoader);
public:
virtual Error open_library(const String &p_path) = 0;
virtual Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) = 0;
@ -44,5 +45,3 @@ public:
virtual bool has_library_changed() const = 0;
virtual bool library_exists() const = 0;
};
#endif // GDEXTENSION_LOADER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_MANAGER_H
#define GDEXTENSION_MANAGER_H
#pragma once
#include "core/extension/gdextension.h"
@ -92,5 +91,3 @@ public:
};
VARIANT_ENUM_CAST(GDExtensionManager::LoadStatus)
#endif // GDEXTENSION_MANAGER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GDEXTENSION_SPECIAL_COMPAT_HASHES_H
#define GDEXTENSION_SPECIAL_COMPAT_HASHES_H
#pragma once
#ifndef DISABLE_DEPRECATED
@ -58,5 +57,3 @@ public:
};
#endif // DISABLE_DEPRECATED
#endif // GDEXTENSION_SPECIAL_COMPAT_HASHES_H

View file

@ -1,55 +1,37 @@
import zlib
import methods
def run(target, source, env):
src = str(source[0])
dst = str(target[0])
with open(src, "rb") as f, open(dst, "w", encoding="utf-8", newline="\n") as g:
buf = f.read()
decomp_size = len(buf)
# Use maximum zlib compression level to further reduce file size
# (at the cost of initial build times).
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
g.write(
"""/* THIS FILE IS GENERATED DO NOT EDIT */
#ifndef GDEXTENSION_INTERFACE_DUMP_H
#define GDEXTENSION_INTERFACE_DUMP_H
buffer = methods.get_buffer(str(source[0]))
decomp_size = len(buffer)
buffer = methods.compress_buffer(buffer)
with methods.generated_wrapper(str(target[0])) as file:
file.write(f"""\
#ifdef TOOLS_ENABLED
#include "core/io/compression.h"
#include "core/io/file_access.h"
#include "core/string/ustring.h"
"""
)
inline constexpr int _gdextension_interface_data_compressed_size = {len(buffer)};
inline constexpr int _gdextension_interface_data_uncompressed_size = {decomp_size};
inline constexpr unsigned char _gdextension_interface_data_compressed[] = {{
{methods.format_buffer(buffer, 1)}
}};
g.write("static const int _gdextension_interface_data_compressed_size = " + str(len(buf)) + ";\n")
g.write("static const int _gdextension_interface_data_uncompressed_size = " + str(decomp_size) + ";\n")
g.write("static const unsigned char _gdextension_interface_data_compressed[] = {\n")
for i in range(len(buf)):
g.write("\t" + str(buf[i]) + ",\n")
g.write("};\n")
g.write(
"""
class GDExtensionInterfaceDump {
public:
static void generate_gdextension_interface_file(const String &p_path) {
Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
ERR_FAIL_COND_MSG(fa.is_null(), vformat("Cannot open file '%s' for writing.", p_path));
Vector<uint8_t> data;
data.resize(_gdextension_interface_data_uncompressed_size);
int ret = Compression::decompress(data.ptrw(), _gdextension_interface_data_uncompressed_size, _gdextension_interface_data_compressed, _gdextension_interface_data_compressed_size, Compression::MODE_DEFLATE);
ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
fa->store_buffer(data.ptr(), data.size());
};
};
class GDExtensionInterfaceDump {{
public:
static void generate_gdextension_interface_file(const String &p_path) {{
Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
ERR_FAIL_COND_MSG(fa.is_null(), vformat("Cannot open file '%s' for writing.", p_path));
Vector<uint8_t> data;
data.resize(_gdextension_interface_data_uncompressed_size);
int ret = Compression::decompress(data.ptrw(), _gdextension_interface_data_uncompressed_size, _gdextension_interface_data_compressed, _gdextension_interface_data_compressed_size, Compression::MODE_DEFLATE);
ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
fa->store_buffer(data.ptr(), data.size());
}};
}};
#endif // TOOLS_ENABLED
#endif // GDEXTENSION_INTERFACE_DUMP_H
"""
)
""")

View file

@ -119,10 +119,7 @@ def generate_ex_version(argcount, const=False, returns=False):
def run(target, source, env):
max_versions = 12
txt = """
#ifndef GDEXTENSION_WRAPPERS_GEN_H
#define GDEXTENSION_WRAPPERS_GEN_H
"""
txt = "#pragma once"
for i in range(max_versions + 1):
txt += "\n/* Extension Wrapper " + str(i) + " Arguments */\n"
@ -138,7 +135,5 @@ def run(target, source, env):
txt += generate_mod_version(i, True, False)
txt += generate_mod_version(i, True, True)
txt += "\n#endif\n"
with open(str(target[0]), "w", encoding="utf-8", newline="\n") as f:
f.write(txt)

View file

@ -28,12 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DEFAULT_CONTROLLER_MAPPINGS_H
#define DEFAULT_CONTROLLER_MAPPINGS_H
#pragma once
class DefaultControllerMappings {
public:
static const char *mappings[];
};
#endif // DEFAULT_CONTROLLER_MAPPINGS_H

View file

@ -219,7 +219,7 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S
continue;
}
String name = pi.name.substr(pi.name.find_char('/') + 1, pi.name.length());
String name = pi.name.substr(pi.name.find_char('/') + 1);
r_options->push_back(name.quote());
}
}
@ -1594,8 +1594,8 @@ void Input::parse_mapping(const String &p_mapping) {
continue;
}
String output = entry[idx].get_slice(":", 0).replace(" ", "");
String input = entry[idx].get_slice(":", 1).replace(" ", "");
String output = entry[idx].get_slicec(':', 0).remove_char(' ');
String input = entry[idx].get_slicec(':', 1).remove_char(' ');
if (output.length() < 1 || input.length() < 2) {
continue;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef INPUT_H
#define INPUT_H
#pragma once
#include "core/input/input_event.h"
#include "core/object/object.h"
@ -86,7 +85,7 @@ public:
typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event);
private:
BitField<MouseButtonMask> mouse_button_mask;
BitField<MouseButtonMask> mouse_button_mask = MouseButtonMask::NONE;
RBSet<Key> key_label_pressed;
RBSet<Key> physical_keys_pressed;
@ -403,5 +402,3 @@ public:
VARIANT_ENUM_CAST(Input::MouseMode);
VARIANT_ENUM_CAST(Input::CursorShape);
#endif // INPUT_H

View file

@ -2,18 +2,22 @@
from collections import OrderedDict
import methods
def make_default_controller_mappings(target, source, env):
dst = str(target[0])
with open(dst, "w", encoding="utf-8", newline="\n") as g:
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write('#include "core/typedefs.h"\n')
g.write('#include "core/input/default_controller_mappings.h"\n')
with methods.generated_wrapper(str(target[0])) as file:
file.write("""\
#include "core/input/default_controller_mappings.h"
#include "core/typedefs.h"
""")
# ensure mappings have a consistent order
platform_mappings: dict = OrderedDict()
for src_path in source:
with open(str(src_path), "r", encoding="utf-8") as f:
platform_mappings = OrderedDict()
for src_path in map(str, source):
with open(src_path, "r", encoding="utf-8") as f:
# read mapping file and skip header
mapping_file_lines = f.readlines()[2:]
@ -32,28 +36,28 @@ def make_default_controller_mappings(target, source, env):
line_parts = line.split(",")
guid = line_parts[0]
if guid in platform_mappings[current_platform]:
g.write(
file.write(
"// WARNING: DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format(
src_path, current_platform, platform_mappings[current_platform][guid]
)
)
platform_mappings[current_platform][guid] = line
platform_variables = {
"Linux": "#ifdef LINUXBSD_ENABLED",
"Windows": "#ifdef WINDOWS_ENABLED",
"Mac OS X": "#ifdef MACOS_ENABLED",
"Android": "#ifdef ANDROID_ENABLED",
"iOS": "#ifdef IOS_ENABLED",
"Web": "#ifdef WEB_ENABLED",
PLATFORM_VARIABLES = {
"Linux": "LINUXBSD",
"Windows": "WINDOWS",
"Mac OS X": "MACOS",
"Android": "ANDROID",
"iOS": "IOS",
"Web": "WEB",
}
g.write("const char* DefaultControllerMappings::mappings[] = {\n")
file.write("const char *DefaultControllerMappings::mappings[] = {\n")
for platform, mappings in platform_mappings.items():
variable = platform_variables[platform]
g.write("{}\n".format(variable))
variable = PLATFORM_VARIABLES[platform]
file.write(f"#ifdef {variable}_ENABLED\n")
for mapping in mappings.values():
g.write('\t"{}",\n'.format(mapping))
g.write("#endif\n")
file.write(f'\t"{mapping}",\n')
file.write(f"#endif // {variable}_ENABLED\n")
g.write("\tnullptr\n};\n")
file.write("\tnullptr\n};\n")

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef INPUT_ENUMS_H
#define INPUT_ENUMS_H
#pragma once
#include "core/error/error_macros.h"
@ -138,4 +137,10 @@ inline MouseButtonMask mouse_button_to_mask(MouseButton button) {
return MouseButtonMask(1 << ((int)button - 1));
}
#endif // INPUT_ENUMS_H
constexpr MouseButtonMask operator|(MouseButtonMask p_a, MouseButtonMask p_b) {
return static_cast<MouseButtonMask>(static_cast<int>(p_a) | static_cast<int>(p_b));
}
constexpr MouseButtonMask &operator|=(MouseButtonMask &p_a, MouseButtonMask p_b) {
return p_a = p_a | p_b;
}

View file

@ -230,7 +230,7 @@ void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModif
}
BitField<KeyModifierMask> InputEventWithModifiers::get_modifiers_mask() const {
BitField<KeyModifierMask> mask;
BitField<KeyModifierMask> mask = {};
if (is_ctrl_pressed()) {
mask.set_flag(KeyModifierMask::CTRL);
}
@ -385,11 +385,11 @@ bool InputEventKey::is_echo() const {
}
Key InputEventKey::get_keycode_with_modifiers() const {
return keycode | (int64_t)get_modifiers_mask();
return keycode | get_modifiers_mask();
}
Key InputEventKey::get_physical_keycode_with_modifiers() const {
return physical_keycode | (int64_t)get_modifiers_mask();
return physical_keycode | get_modifiers_mask();
}
Key InputEventKey::get_key_label_with_modifiers() const {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef INPUT_EVENT_H
#define INPUT_EVENT_H
#pragma once
#include "core/input/input_enums.h"
#include "core/io/resource.h"
@ -209,7 +208,7 @@ public:
class InputEventMouse : public InputEventWithModifiers {
GDCLASS(InputEventMouse, InputEventWithModifiers);
BitField<MouseButtonMask> button_mask;
BitField<MouseButtonMask> button_mask = MouseButtonMask::NONE;
Vector2 pos;
Vector2 global_pos;
@ -595,5 +594,3 @@ public:
InputEventShortcut();
};
#endif // INPUT_EVENT_H

View file

@ -47,6 +47,8 @@ void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(DEFAULT_DEADZONE));
ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action);
ClassDB::bind_method(D_METHOD("get_action_description", "action"), &InputMap::get_action_description);
ClassDB::bind_method(D_METHOD("action_set_deadzone", "action", "deadzone"), &InputMap::action_set_deadzone);
ClassDB::bind_method(D_METHOD("action_get_deadzone", "action"), &InputMap::action_get_deadzone);
ClassDB::bind_method(D_METHOD("action_add_event", "action", "event"), &InputMap::action_add_event);
@ -106,7 +108,7 @@ void InputMap::get_argument_options(const StringName &p_function, int p_idx, Lis
continue;
}
String name = pi.name.substr(pi.name.find_char('/') + 1, pi.name.length());
String name = pi.name.substr(pi.name.find_char('/') + 1);
r_options->push_back(name.quote());
}
}
@ -181,6 +183,25 @@ bool InputMap::has_action(const StringName &p_action) const {
return input_map.has(p_action);
}
String InputMap::get_action_description(const StringName &p_action) const {
ERR_FAIL_COND_V_MSG(!input_map.has(p_action), String(), suggest_actions(p_action));
String ret;
const List<Ref<InputEvent>> &inputs = input_map[p_action].inputs;
for (Ref<InputEventKey> iek : inputs) {
if (iek.is_valid()) {
if (!ret.is_empty()) {
ret += RTR(" or ");
}
ret += iek->as_text();
}
}
if (ret.is_empty()) {
ret = RTR("Action has no bound inputs");
}
return ret;
}
float InputMap::action_get_deadzone(const StringName &p_action) {
ERR_FAIL_COND_V_MSG(!input_map.has(p_action), 0.0f, suggest_actions(p_action));
@ -304,7 +325,7 @@ void InputMap::load_from_project_settings() {
continue;
}
String name = pi.name.substr(pi.name.find_char('/') + 1, pi.name.length());
String name = pi.name.substr(pi.name.find_char('/') + 1);
Dictionary action = GLOBAL_GET(pi.name);
float deadzone = action.has("deadzone") ? (float)action["deadzone"] : DEFAULT_DEADZONE;
@ -344,6 +365,7 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
{ "ui_cut", TTRC("Cut") },
{ "ui_copy", TTRC("Copy") },
{ "ui_paste", TTRC("Paste") },
{ "ui_focus_mode", TTRC("Toggle Tab Focus Mode") },
{ "ui_undo", TTRC("Undo") },
{ "ui_redo", TTRC("Redo") },
{ "ui_text_completion_query", TTRC("Completion Query") },
@ -397,17 +419,21 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
{ "ui_text_submit", TTRC("Submit Text") },
{ "ui_graph_duplicate", TTRC("Duplicate Nodes") },
{ "ui_graph_delete", TTRC("Delete Nodes") },
{ "ui_graph_follow_left", TTRC("Follow Input Port Connection") },
{ "ui_graph_follow_right", TTRC("Follow Output Port Connection") },
{ "ui_filedialog_up_one_level", TTRC("Go Up One Level") },
{ "ui_filedialog_refresh", TTRC("Refresh") },
{ "ui_filedialog_show_hidden", TTRC("Show Hidden") },
{ "ui_swap_input_direction ", TTRC("Swap Input Direction") },
{ "ui_unicode_start", TTRC("Start Unicode Character Input") },
{ "ui_colorpicker_delete_preset", TTRC("Toggle License Notices") },
{ "ui_accessibility_drag_and_drop", TTRC("Accessibility: Keyboard Drag and Drop") },
{ "", ""}
/* clang-format on */
};
String InputMap::get_builtin_display_name(const String &p_name) const {
int len = sizeof(_builtin_action_display_names) / sizeof(_BuiltinActionDisplayName);
constexpr int len = std::size(_builtin_action_display_names);
for (int i = 0; i < len; i++) {
if (_builtin_action_display_names[i].name == p_name) {
@ -487,6 +513,9 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
inputs.push_back(InputEventKey::create_reference(Key::END));
default_builtin_cache.insert("ui_end", inputs);
inputs = List<Ref<InputEvent>>();
default_builtin_cache.insert("ui_accessibility_drag_and_drop", inputs);
// ///// UI basic Shortcuts /////
inputs = List<Ref<InputEvent>>();
@ -499,6 +528,10 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
inputs.push_back(InputEventKey::create_reference(Key::INSERT | KeyModifierMask::CMD_OR_CTRL));
default_builtin_cache.insert("ui_copy", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::M | KeyModifierMask::CTRL));
default_builtin_cache.insert("ui_focus_mode", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::V | KeyModifierMask::CMD_OR_CTRL));
inputs.push_back(InputEventKey::create_reference(Key::INSERT | KeyModifierMask::SHIFT));
@ -772,6 +805,22 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE));
default_builtin_cache.insert("ui_graph_delete", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::LEFT | KeyModifierMask::CMD_OR_CTRL));
default_builtin_cache.insert("ui_graph_follow_left", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::LEFT | KeyModifierMask::ALT));
default_builtin_cache.insert("ui_graph_follow_left.macos", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::RIGHT | KeyModifierMask::CMD_OR_CTRL));
default_builtin_cache.insert("ui_graph_follow_right", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::RIGHT | KeyModifierMask::ALT));
default_builtin_cache.insert("ui_graph_follow_right.macos", inputs);
// ///// UI File Dialog Shortcuts /////
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE));
@ -789,6 +838,12 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
inputs.push_back(InputEventKey::create_reference(Key::QUOTELEFT | KeyModifierMask::CMD_OR_CTRL));
default_builtin_cache.insert("ui_swap_input_direction", inputs);
// ///// UI ColorPicker Shortcuts /////
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::X));
inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE));
default_builtin_cache.insert("ui_colorpicker_delete_preset", inputs);
return default_builtin_cache;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef INPUT_MAP_H
#define INPUT_MAP_H
#pragma once
#include "core/input/input_event.h"
#include "core/object/class_db.h"
@ -86,6 +85,8 @@ public:
void add_action(const StringName &p_action, float p_deadzone = DEFAULT_DEADZONE);
void erase_action(const StringName &p_action);
String get_action_description(const StringName &p_action) const;
float action_get_deadzone(const StringName &p_action);
void action_set_deadzone(const StringName &p_action, float p_deadzone);
void action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event);
@ -116,5 +117,3 @@ public:
InputMap();
~InputMap();
};
#endif // INPUT_MAP_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef SHORTCUT_H
#define SHORTCUT_H
#pragma once
#include "core/input/input_event.h"
#include "core/io/resource.h"
@ -55,5 +54,3 @@ public:
static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);
};
#endif // SHORTCUT_H

View file

@ -42,6 +42,12 @@
#include <brotli/decode.h>
#endif
// Caches for zstd.
static BinaryMutex mutex;
static ZSTD_DCtx *current_zstd_d_ctx = nullptr;
static bool current_zstd_long_distance_matching;
static int current_zstd_window_log_size;
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode) {
switch (p_mode) {
case MODE_BROTLI: {
@ -187,12 +193,22 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
return total;
} break;
case MODE_ZSTD: {
ZSTD_DCtx *dctx = ZSTD_createDCtx();
if (zstd_long_distance_matching) {
ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, zstd_window_log_size);
MutexLock lock(mutex);
if (!current_zstd_d_ctx || current_zstd_long_distance_matching != zstd_long_distance_matching || current_zstd_window_log_size != zstd_window_log_size) {
if (current_zstd_d_ctx) {
ZSTD_freeDCtx(current_zstd_d_ctx);
}
current_zstd_d_ctx = ZSTD_createDCtx();
if (zstd_long_distance_matching) {
ZSTD_DCtx_setParameter(current_zstd_d_ctx, ZSTD_d_windowLogMax, zstd_window_log_size);
}
current_zstd_long_distance_matching = zstd_long_distance_matching;
current_zstd_window_log_size = zstd_window_log_size;
}
int ret = ZSTD_decompressDCtx(dctx, p_dst, p_dst_max_size, p_src, p_src_size);
ZSTD_freeDCtx(dctx);
int ret = ZSTD_decompressDCtx(current_zstd_d_ctx, p_dst, p_dst_max_size, p_src, p_src_size);
return ret;
} break;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef COMPRESSION_H
#define COMPRESSION_H
#pragma once
#include "core/templates/vector.h"
#include "core/typedefs.h"
@ -56,5 +55,3 @@ public:
static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD);
static int decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode);
};
#endif // COMPRESSION_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CONFIG_FILE_H
#define CONFIG_FILE_H
#pragma once
#include "core/io/file_access.h"
#include "core/object/ref_counted.h"
@ -78,5 +77,3 @@ public:
Error save_encrypted(const String &p_path, const Vector<uint8_t> &p_key);
Error save_encrypted_pass(const String &p_path, const String &p_pass);
};
#endif // CONFIG_FILE_H

View file

@ -146,7 +146,7 @@ Error DirAccess::make_dir_recursive(const String &p_dir) {
full_dir = p_dir;
}
full_dir = full_dir.replace("\\", "/");
full_dir = full_dir.replace_char('\\', '/');
String base;
@ -336,7 +336,7 @@ Ref<DirAccess> DirAccess::create_temp(const String &p_prefix, bool p_keep, Error
uint32_t suffix_i = 0;
String path;
while (true) {
String datetime = Time::get_singleton()->get_datetime_string_from_system().replace("-", "").replace("T", "").replace(":", "");
String datetime = Time::get_singleton()->get_datetime_string_from_system().remove_chars("-T:");
datetime += itos(Time::get_singleton()->get_ticks_usec());
String suffix = datetime + (suffix_i > 0 ? itos(suffix_i) : "");
path = (p_prefix.is_empty() ? "" : p_prefix + "-") + suffix;
@ -626,6 +626,10 @@ bool DirAccess::is_case_sensitive(const String &p_path) const {
return true;
}
bool DirAccess::is_equivalent(const String &p_path_a, const String &p_path_b) const {
return p_path_a == p_path_b;
}
void DirAccess::_bind_methods() {
ClassDB::bind_static_method("DirAccess", D_METHOD("open", "path"), &DirAccess::_open);
ClassDB::bind_static_method("DirAccess", D_METHOD("get_open_error"), &DirAccess::get_open_error);
@ -671,6 +675,7 @@ void DirAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_include_hidden"), &DirAccess::get_include_hidden);
ClassDB::bind_method(D_METHOD("is_case_sensitive", "path"), &DirAccess::is_case_sensitive);
ClassDB::bind_method(D_METHOD("is_equivalent", "path_a", "path_b"), &DirAccess::is_equivalent);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_navigational"), "set_include_navigational", "get_include_navigational");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_hidden"), "set_include_hidden", "get_include_hidden");

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DIR_ACCESS_H
#define DIR_ACCESS_H
#pragma once
#include "core/object/ref_counted.h"
#include "core/string/ustring.h"
@ -169,10 +168,9 @@ public:
virtual bool is_case_sensitive(const String &p_path) const;
virtual bool is_bundle(const String &p_file) const { return false; }
virtual bool is_equivalent(const String &p_path_a, const String &p_path_b) const;
public:
DirAccess() {}
virtual ~DirAccess();
};
#endif // DIR_ACCESS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DTLS_SERVER_H
#define DTLS_SERVER_H
#pragma once
#include "core/io/net_socket.h"
#include "core/io/packet_peer_dtls.h"
@ -53,5 +52,3 @@ public:
DTLSServer() {}
};
#endif // DTLS_SERVER_H

View file

@ -104,7 +104,7 @@ Ref<FileAccess> FileAccess::create_temp(int p_mode_flags, const String &p_prefix
uint32_t suffix_i = 0;
String path;
while (true) {
String datetime = Time::get_singleton()->get_datetime_string_from_system().replace("-", "").replace("T", "").replace(":", "");
String datetime = Time::get_singleton()->get_datetime_string_from_system().remove_chars("-T:");
datetime += itos(Time::get_singleton()->get_ticks_usec());
String suffix = datetime + (suffix_i > 0 ? itos(suffix_i) : "");
path = TEMP_DIR.path_join((p_prefix.is_empty() ? "" : p_prefix + "-") + suffix + (extension.is_empty() ? "" : "." + extension));
@ -259,7 +259,7 @@ FileAccess::AccessType FileAccess::get_access_type() const {
String FileAccess::fix_path(const String &p_path) const {
// Helper used by file accesses that use a single filesystem.
String r_path = p_path.replace("\\", "/");
String r_path = p_path.replace_char('\\', '/');
switch (_access_type) {
case ACCESS_RESOURCES: {
@ -313,9 +313,15 @@ uint16_t FileAccess::get_16() const {
uint16_t data = 0;
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint16_t));
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
data = BSWAP16(data);
}
#else
if (big_endian) {
data = BSWAP16(data);
}
#endif
return data;
}
@ -324,9 +330,15 @@ uint32_t FileAccess::get_32() const {
uint32_t data = 0;
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint32_t));
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
data = BSWAP32(data);
}
#else
if (big_endian) {
data = BSWAP32(data);
}
#endif
return data;
}
@ -335,9 +347,15 @@ uint64_t FileAccess::get_64() const {
uint64_t data = 0;
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint64_t));
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
data = BSWAP64(data);
}
#else
if (big_endian) {
data = BSWAP64(data);
}
#endif
return data;
}
@ -429,7 +447,7 @@ class CharBuffer {
public:
_FORCE_INLINE_ CharBuffer() :
buffer(stack_buffer),
capacity(sizeof(stack_buffer) / sizeof(char)) {
capacity(std::size(stack_buffer)) {
}
_FORCE_INLINE_ void push_back(char c) {
@ -565,7 +583,7 @@ String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
w[len] = 0;
String s;
s.parse_utf8((const char *)w, len, p_skip_cr);
s.append_utf8((const char *)w, len, p_skip_cr);
return s;
}
@ -574,25 +592,43 @@ bool FileAccess::store_8(uint8_t p_dest) {
}
bool FileAccess::store_16(uint16_t p_dest) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_dest = BSWAP16(p_dest);
}
#else
if (big_endian) {
p_dest = BSWAP16(p_dest);
}
#endif
return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint16_t));
}
bool FileAccess::store_32(uint32_t p_dest) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_dest = BSWAP32(p_dest);
}
#else
if (big_endian) {
p_dest = BSWAP32(p_dest);
}
#endif
return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint32_t));
}
bool FileAccess::store_64(uint64_t p_dest) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_dest = BSWAP64(p_dest);
}
#else
if (big_endian) {
p_dest = BSWAP64(p_dest);
}
#endif
return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint64_t));
}
@ -629,8 +665,29 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
Ref<FileAccess> fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(fa.is_null(), 0, vformat("Cannot create FileAccess for path '%s'.", p_file));
uint64_t mt = fa->_get_modified_time(p_file);
return mt;
return fa->_get_modified_time(p_file);
}
uint64_t FileAccess::get_access_time(const String &p_file) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return 0;
}
Ref<FileAccess> fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'.");
return fa->_get_access_time(p_file);
}
int64_t FileAccess::get_size(const String &p_file) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return PackedData::get_singleton()->get_size(p_file);
}
Ref<FileAccess> fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(fa.is_null(), -1, "Cannot create FileAccess for path '" + p_file + "'.");
return fa->_get_size(p_file);
}
BitField<FileAccess::UnixPermissionFlags> FileAccess::get_unix_permissions(const String &p_file) {
@ -723,9 +780,7 @@ String FileAccess::get_pascal_string() {
get_buffer((uint8_t *)cs.ptr(), sl);
cs[sl] = 0;
String ret;
ret.parse_utf8(cs.ptr(), sl);
return ret;
return String::utf8(cs.ptr(), sl);
}
bool FileAccess::store_line(const String &p_line) {
@ -817,7 +872,7 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
}
String ret;
ret.parse_utf8((const char *)array.ptr(), array.size());
ret.append_utf8((const char *)array.ptr(), array.size());
return ret;
}
@ -931,7 +986,7 @@ void FileAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_float"), &FileAccess::get_float);
ClassDB::bind_method(D_METHOD("get_double"), &FileAccess::get_double);
ClassDB::bind_method(D_METHOD("get_real"), &FileAccess::get_real);
ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t>(FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t> (FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line);
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text, DEFVAL(false));
@ -950,7 +1005,7 @@ void FileAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("store_float", "value"), &FileAccess::store_float);
ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double);
ClassDB::bind_method(D_METHOD("store_real", "value"), &FileAccess::store_real);
ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), (bool(FileAccess::*)(const Vector<uint8_t> &)) & FileAccess::store_buffer);
ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), (bool (FileAccess::*)(const Vector<uint8_t> &))&FileAccess::store_buffer);
ClassDB::bind_method(D_METHOD("store_line", "line"), &FileAccess::store_line);
ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &FileAccess::store_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_string", "string"), &FileAccess::store_string);
@ -963,6 +1018,8 @@ void FileAccess::_bind_methods() {
ClassDB::bind_static_method("FileAccess", D_METHOD("file_exists", "path"), &FileAccess::exists);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_modified_time", "file"), &FileAccess::get_modified_time);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_access_time", "file"), &FileAccess::get_access_time);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_size", "file"), &FileAccess::get_size);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_unix_permissions", "file"), &FileAccess::get_unix_permissions);
ClassDB::bind_static_method("FileAccess", D_METHOD("set_unix_permissions", "file", "permissions"), &FileAccess::set_unix_permissions);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_H
#define FILE_ACCESS_H
#pragma once
#include "core/io/compression.h"
#include "core/math/math_defs.h"
@ -87,7 +86,11 @@ public:
typedef void (*FileCloseFailNotify)(const String &);
typedef Ref<FileAccess> (*CreateFunc)();
#ifdef BIG_ENDIAN_ENABLED
bool big_endian = true;
#else
bool big_endian = false;
#endif
bool real_is_double = false;
virtual BitField<UnixPermissionFlags> _get_unix_permissions(const String &p_file) = 0;
@ -105,6 +108,8 @@ protected:
virtual String fix_path(const String &p_path) const;
virtual Error open_internal(const String &p_path, int p_mode_flags) = 0; ///< open a file
virtual uint64_t _get_modified_time(const String &p_file) = 0;
virtual uint64_t _get_access_time(const String &p_file) = 0;
virtual int64_t _get_size(const String &p_file) = 0;
virtual void _set_access_type(AccessType p_access);
static FileCloseFailNotify close_fail_notify;
@ -239,6 +244,8 @@ public:
static CreateFunc get_create_func(AccessType p_access);
static bool exists(const String &p_name); ///< return true if a file exists
static uint64_t get_modified_time(const String &p_file);
static uint64_t get_access_time(const String &p_file);
static int64_t get_size(const String &p_file);
static BitField<FileAccess::UnixPermissionFlags> get_unix_permissions(const String &p_file);
static Error set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions);
@ -273,5 +280,3 @@ public:
VARIANT_ENUM_CAST(FileAccess::CompressionMode);
VARIANT_ENUM_CAST(FileAccess::ModeFlags);
VARIANT_BITFIELD_CAST(FileAccess::UnixPermissionFlags);
#endif // FILE_ACCESS_H

View file

@ -247,7 +247,11 @@ bool FileAccessCompressed::eof_reached() const {
}
uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
if (p_length == 0) {
return 0;
}
ERR_FAIL_NULL_V(p_dst, -1);
ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
@ -256,29 +260,38 @@ uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) con
return 0;
}
for (uint64_t i = 0; i < p_length; i++) {
p_dst[i] = read_ptr[read_pos];
read_pos++;
if (read_pos >= read_block_size) {
read_block++;
uint64_t dst_idx = 0;
while (true) {
// Copy over as much of our current block as possible.
const uint32_t copied_bytes_count = MIN(p_length - dst_idx, read_block_size - read_pos);
memcpy(p_dst + dst_idx, read_ptr + read_pos, copied_bytes_count);
dst_idx += copied_bytes_count;
read_pos += copied_bytes_count;
if (read_block < read_block_count) {
//read another block of compressed data
f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
int ret = Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
ERR_FAIL_COND_V_MSG(ret == -1, -1, "Compressed file is corrupt.");
read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
read_pos = 0;
} else {
read_block--;
at_end = true;
if (i + 1 < p_length) {
read_eof = true;
}
return i + 1;
}
if (dst_idx == p_length) {
// We're done! We read back all that was requested.
return p_length;
}
// We're not done yet; try reading the next block.
read_block++;
if (read_block >= read_block_count) {
// We're done! We read back the whole file.
read_block--;
at_end = true;
if (dst_idx + 1 < p_length) {
read_eof = true;
}
return dst_idx;
}
// Read the next block of compressed data.
f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
int ret = Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
ERR_FAIL_COND_V_MSG(ret == -1, -1, "Compressed file is corrupt.");
read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
read_pos = 0;
}
return p_length;
@ -332,6 +345,22 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
}
}
uint64_t FileAccessCompressed::_get_access_time(const String &p_file) {
if (f.is_valid()) {
return f->get_access_time(p_file);
} else {
return 0;
}
}
int64_t FileAccessCompressed::_get_size(const String &p_file) {
if (f.is_valid()) {
return f->get_size(p_file);
} else {
return -1;
}
}
BitField<FileAccess::UnixPermissionFlags> FileAccessCompressed::_get_unix_permissions(const String &p_file) {
if (f.is_valid()) {
return f->_get_unix_permissions(p_file);

View file

@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_COMPRESSED_H
#define FILE_ACCESS_COMPRESSED_H
#pragma once
#include "core/io/compression.h"
#include "core/io/file_access.h"
class FileAccessCompressed : public FileAccess {
GDSOFTCLASS(FileAccessCompressed, FileAccess);
Compression::Mode cmode = Compression::MODE_ZSTD;
bool writing = false;
uint64_t write_pos = 0;
@ -94,6 +94,8 @@ public:
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) override;
virtual uint64_t _get_access_time(const String &p_file) override;
virtual int64_t _get_size(const String &p_file) override;
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override;
@ -107,5 +109,3 @@ public:
FileAccessCompressed() {}
virtual ~FileAccessCompressed();
};
#endif // FILE_ACCESS_COMPRESSED_H

View file

@ -30,9 +30,17 @@
#include "file_access_encrypted.h"
#include "core/crypto/crypto_core.h"
#include "core/variant/variant.h"
CryptoCore::RandomGenerator *FileAccessEncrypted::_fae_static_rng = nullptr;
void FileAccessEncrypted::deinitialize() {
if (_fae_static_rng) {
memdelete(_fae_static_rng);
_fae_static_rng = nullptr;
}
}
Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic, const Vector<uint8_t> &p_iv) {
ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, vformat("Can't open file while another file from path '%s' is open.", file->get_path_absolute()));
ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
@ -48,9 +56,15 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u
key = p_key;
if (p_iv.is_empty()) {
iv.resize(16);
CryptoCore::RandomGenerator rng;
ERR_FAIL_COND_V_MSG(rng.init(), FAILED, "Failed to initialize random number generator.");
Error err = rng.get_random_bytes(iv.ptrw(), 16);
if (unlikely(!_fae_static_rng)) {
_fae_static_rng = memnew(CryptoCore::RandomGenerator);
if (_fae_static_rng->init() != OK) {
memdelete(_fae_static_rng);
_fae_static_rng = nullptr;
ERR_FAIL_V_MSG(FAILED, "Failed to initialize random number generator.");
}
}
Error err = _fae_static_rng->get_random_bytes(iv.ptrw(), 16);
ERR_FAIL_COND_V(err != OK, err);
} else {
ERR_FAIL_COND_V(p_iv.size() != 16, ERR_INVALID_PARAMETER);
@ -265,7 +279,27 @@ bool FileAccessEncrypted::file_exists(const String &p_name) {
}
uint64_t FileAccessEncrypted::_get_modified_time(const String &p_file) {
return 0;
if (file.is_valid()) {
return file->get_modified_time(p_file);
} else {
return 0;
}
}
uint64_t FileAccessEncrypted::_get_access_time(const String &p_file) {
if (file.is_valid()) {
return file->get_access_time(p_file);
} else {
return 0;
}
}
int64_t FileAccessEncrypted::_get_size(const String &p_file) {
if (file.is_valid()) {
return file->get_size(p_file);
} else {
return -1;
}
}
BitField<FileAccess::UnixPermissionFlags> FileAccessEncrypted::_get_unix_permissions(const String &p_file) {

View file

@ -28,14 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_ENCRYPTED_H
#define FILE_ACCESS_ENCRYPTED_H
#pragma once
#include "core/crypto/crypto_core.h"
#include "core/io/file_access.h"
#define ENCRYPTED_HEADER_MAGIC 0x43454447
class FileAccessEncrypted : public FileAccess {
GDSOFTCLASS(FileAccessEncrypted, FileAccess);
public:
enum Mode : int32_t {
MODE_READ,
@ -57,6 +59,8 @@ private:
void _close();
static CryptoCore::RandomGenerator *_fae_static_rng;
public:
Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true, const Vector<uint8_t> &p_iv = Vector<uint8_t>());
Error open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode);
@ -87,6 +91,8 @@ public:
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) override;
virtual uint64_t _get_access_time(const String &p_file) override;
virtual int64_t _get_size(const String &p_file) override;
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override;
@ -97,8 +103,8 @@ public:
virtual void close() override;
static void deinitialize();
FileAccessEncrypted() {}
~FileAccessEncrypted();
};
#endif // FILE_ACCESS_ENCRYPTED_H

View file

@ -28,12 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_MEMORY_H
#define FILE_ACCESS_MEMORY_H
#pragma once
#include "core/io/file_access.h"
class FileAccessMemory : public FileAccess {
GDSOFTCLASS(FileAccessMemory, FileAccess);
uint8_t *data = nullptr;
uint64_t length = 0;
mutable uint64_t pos = 0;
@ -66,6 +66,9 @@ public:
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
virtual uint64_t _get_access_time(const String &p_file) override { return 0; }
virtual int64_t _get_size(const String &p_file) override { return -1; }
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
@ -78,5 +81,3 @@ public:
FileAccessMemory() {}
};
#endif // FILE_ACCESS_MEMORY_H

View file

@ -264,7 +264,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
f->get_32(); // patch number, not used for validation.
ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, vformat("Pack version unsupported: %d.", version));
ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, vformat("Pack created with a newer version of the engine: %d.%d.", ver_major, ver_minor));
ERR_FAIL_COND_V_MSG(ver_major > GODOT_VERSION_MAJOR || (ver_major == GODOT_VERSION_MAJOR && ver_minor > GODOT_VERSION_MINOR), false, vformat("Pack created with a newer version of the engine: %d.%d.", ver_major, ver_minor));
uint32_t pack_flags = f->get_32();
uint64_t file_base = f->get_64();
@ -306,9 +306,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
f->get_buffer((uint8_t *)cs.ptr(), sl);
cs[sl] = 0;
String path;
path.parse_utf8(cs.ptr(), sl);
String path = String::utf8(cs.ptr(), sl);
uint64_t ofs = f->get_64();
uint64_t size = f->get_64();
uint8_t md5[16];
@ -550,7 +548,7 @@ String DirAccessPack::get_drive(int p_drive) {
}
PackedData::PackedDir *DirAccessPack::_find_dir(const String &p_dir) {
String nd = p_dir.replace("\\", "/");
String nd = p_dir.replace_char('\\', '/');
// Special handling since simplify_path() will forbid it
if (p_dir == "..") {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_PACK_H
#define FILE_ACCESS_PACK_H
#pragma once
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
@ -127,6 +126,8 @@ public:
_FORCE_INLINE_ Ref<FileAccess> try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path);
_FORCE_INLINE_ int64_t get_size(const String &p_path);
_FORCE_INLINE_ Ref<DirAccess> try_open_directory(const String &p_path);
_FORCE_INLINE_ bool has_directory(const String &p_path);
@ -156,6 +157,7 @@ public:
};
class FileAccessPack : public FileAccess {
GDSOFTCLASS(FileAccessPack, FileAccess);
PackedData::PackedFile pf;
mutable uint64_t pos;
@ -165,6 +167,8 @@ class FileAccessPack : public FileAccess {
Ref<FileAccess> f;
virtual Error open_internal(const String &p_path, int p_mode_flags) override;
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
virtual uint64_t _get_access_time(const String &p_file) override { return 0; }
virtual int64_t _get_size(const String &p_file) override { return -1; }
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
@ -200,6 +204,19 @@ public:
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
};
int64_t PackedData::get_size(const String &p_path) {
String simplified_path = p_path.simplify_path();
PathMD5 pmd5(simplified_path.md5_buffer());
HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5);
if (!E) {
return -1; // File not found.
}
if (E->value.offset == 0) {
return -1; // File was erased.
}
return E->value.size;
}
Ref<FileAccess> PackedData::try_open_path(const String &p_path) {
String simplified_path = p_path.simplify_path().trim_prefix("res://");
PathMD5 pmd5(simplified_path.md5_buffer());
@ -225,6 +242,7 @@ bool PackedData::has_directory(const String &p_path) {
}
class DirAccessPack : public DirAccess {
GDSOFTCLASS(DirAccessPack, DirAccess);
PackedData::PackedDir *current;
List<String> list_dirs;
@ -272,5 +290,3 @@ Ref<DirAccess> PackedData::try_open_directory(const String &p_path) {
}
return da;
}
#endif // FILE_ACCESS_PACK_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_ZIP_H
#define FILE_ACCESS_ZIP_H
#pragma once
#ifdef MINIZIP_ENABLED
@ -74,6 +73,7 @@ public:
};
class FileAccessZip : public FileAccess {
GDSOFTCLASS(FileAccessZip, FileAccess);
unzFile zfile = nullptr;
unz_file_info64 file_info;
@ -102,7 +102,9 @@ public:
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; } // todo
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
virtual uint64_t _get_access_time(const String &p_file) override { return 0; }
virtual int64_t _get_size(const String &p_file) override { return -1; }
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
@ -118,5 +120,3 @@ public:
};
#endif // MINIZIP_ENABLED
#endif // FILE_ACCESS_ZIP_H

View file

@ -70,10 +70,9 @@ Error HTTPClient::_request(Method p_method, const String &p_url, const Vector<St
String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
String query = "";
Array keys = p_dict.keys();
for (int i = 0; i < keys.size(); ++i) {
String encoded_key = String(keys[i]).uri_encode();
const Variant &value = p_dict[keys[i]];
for (const KeyValue<Variant, Variant> &kv : p_dict) {
String encoded_key = String(kv.key).uri_encode();
const Variant &value = kv.value;
switch (value.get_type()) {
case Variant::ARRAY: {
// Repeat the key with every values
@ -118,7 +117,7 @@ Dictionary HTTPClient::_get_response_headers_as_dictionary() {
continue;
}
String key = s.substr(0, sp).strip_edges();
String value = s.substr(sp + 1, s.length()).strip_edges();
String value = s.substr(sp + 1).strip_edges();
ret[key] = value;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H
#pragma once
#include "core/crypto/crypto.h"
#include "core/io/ip.h"
@ -205,5 +204,3 @@ public:
VARIANT_ENUM_CAST(HTTPClient::ResponseCode)
VARIANT_ENUM_CAST(HTTPClient::Method);
VARIANT_ENUM_CAST(HTTPClient::Status);
#endif // HTTP_CLIENT_H

View file

@ -50,13 +50,13 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, Ref<TLSOp
String host_lower = conn_host.to_lower();
if (host_lower.begins_with("http://")) {
conn_host = conn_host.substr(7, conn_host.length() - 7);
conn_host = conn_host.substr(7);
tls_options.unref();
} else if (host_lower.begins_with("https://")) {
if (tls_options.is_null()) {
tls_options = TLSOptions::client();
}
conn_host = conn_host.substr(8, conn_host.length() - 8);
conn_host = conn_host.substr(8);
}
ERR_FAIL_COND_V(tls_options.is_valid() && tls_options->is_server(), ERR_INVALID_PARAMETER);
@ -196,7 +196,7 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector<
// Should it add utf8 encoding?
}
if (add_uagent) {
request += "User-Agent: GodotEngine/" + String(VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")\r\n";
request += "User-Agent: GodotEngine/" + String(GODOT_VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")\r\n";
}
if (add_accept) {
request += "Accept: */*\r\n";
@ -483,8 +483,7 @@ Error HTTPClientTCP::poll() {
(rs >= 4 && response_str[rs - 4] == '\r' && response_str[rs - 3] == '\n' && response_str[rs - 2] == '\r' && response_str[rs - 1] == '\n')) {
// End of response, parse.
response_str.push_back(0);
String response;
response.parse_utf8((const char *)response_str.ptr(), response_str.size());
String response = String::utf8((const char *)response_str.ptr(), response_str.size());
Vector<String> responses = response.split("\n");
body_size = -1;
chunked = false;
@ -508,11 +507,11 @@ Error HTTPClientTCP::poll() {
continue;
}
if (s.begins_with("content-length:")) {
body_size = s.substr(s.find_char(':') + 1, s.length()).strip_edges().to_int();
body_size = s.substr(s.find_char(':') + 1).strip_edges().to_int();
body_left = body_size;
} else if (s.begins_with("transfer-encoding:")) {
String encoding = header.substr(header.find_char(':') + 1, header.length()).strip_edges();
String encoding = header.substr(header.find_char(':') + 1).strip_edges();
if (encoding == "chunked") {
chunked = true;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef HTTP_CLIENT_TCP_H
#define HTTP_CLIENT_TCP_H
#pragma once
#include "http_client.h"
@ -100,5 +99,3 @@ public:
void set_https_proxy(const String &p_host, int p_port) override;
HTTPClientTCP();
};
#endif // HTTP_CLIENT_TCP_H

View file

@ -31,7 +31,6 @@
#include "image.h"
#include "core/config/project_settings.h"
#include "core/error/error_list.h"
#include "core/error/error_macros.h"
#include "core/io/image_loader.h"
#include "core/io/resource_loader.h"
@ -89,11 +88,13 @@ SavePNGFunc Image::save_png_func = nullptr;
SaveJPGFunc Image::save_jpg_func = nullptr;
SaveEXRFunc Image::save_exr_func = nullptr;
SaveWebPFunc Image::save_webp_func = nullptr;
SaveDDSFunc Image::save_dds_func = nullptr;
SavePNGBufferFunc Image::save_png_buffer_func = nullptr;
SaveJPGBufferFunc Image::save_jpg_buffer_func = nullptr;
SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr;
SaveWebPBufferFunc Image::save_webp_buffer_func = nullptr;
SaveDDSBufferFunc Image::save_dds_buffer_func = nullptr;
// External loader function pointers.
@ -105,6 +106,7 @@ ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr;
ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_ktx_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_dds_mem_loader_func = nullptr;
// External VRAM compression function pointers.
@ -571,7 +573,7 @@ static bool _are_formats_compatible(Image::Format p_format0, Image::Format p_for
void Image::convert(Format p_new_format) {
ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_new_format));
if (data.size() == 0 || p_new_format == format) {
if (data.is_empty() || p_new_format == format) {
return;
}
@ -796,7 +798,7 @@ Image::Format Image::get_format() const {
}
static double _bicubic_interp_kernel(double x) {
x = ABS(x);
x = Math::abs(x);
double bc = 0;
@ -1139,7 +1141,7 @@ bool Image::is_size_po2() const {
}
void Image::resize_to_po2(bool p_square, Interpolation p_interpolation) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot resize in compressed image formats.");
int w = next_power_of_2(width);
int h = next_power_of_2(height);
@ -1158,7 +1160,7 @@ void Image::resize_to_po2(bool p_square, Interpolation p_interpolation) {
void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
ERR_FAIL_COND_MSG(data.is_empty(), "Cannot resize image before creating it, use set_data() first.");
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot resize in compressed image formats.");
bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */;
@ -1461,8 +1463,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
}
void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot crop in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot crop in compressed image formats.");
ERR_FAIL_COND_MSG(p_x < 0, "Start x position cannot be smaller than 0.");
ERR_FAIL_COND_MSG(p_y < 0, "Start y position cannot be smaller than 0.");
ERR_FAIL_COND_MSG(p_width <= 0, "Width of image must be greater than 0.");
@ -1515,7 +1516,7 @@ void Image::crop(int p_width, int p_height) {
}
void Image::rotate_90(ClockDirection p_direction) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot rotate in compressed image formats.");
ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width));
ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height));
@ -1633,7 +1634,7 @@ void Image::rotate_90(ClockDirection p_direction) {
}
void Image::rotate_180() {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot rotate in compressed image formats.");
ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width));
ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height));
@ -1667,7 +1668,7 @@ void Image::rotate_180() {
}
void Image::flip_y() {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot flip_y in compressed image formats.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
@ -1697,7 +1698,7 @@ void Image::flip_y() {
}
void Image::flip_x() {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_x in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot flip_x in compressed image formats.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
@ -1789,10 +1790,6 @@ int64_t Image::_get_dst_image_size(int p_width, int p_height, Format p_format, i
return size;
}
bool Image::_can_modify(Format p_format) const {
return !Image::is_format_compressed(p_format);
}
template <typename Component, int CC, bool renormalize,
void (*average_func)(Component &, const Component &, const Component &, const Component &, const Component &),
void (*renormalize_func)(Component *)>
@ -1926,7 +1923,7 @@ void Image::shrink_x2() {
memcpy(new_data.ptrw(), data.ptr() + ofs, new_size);
} else {
// Generate a mipmap and replace the original.
ERR_FAIL_COND(!_can_modify(format));
ERR_FAIL_COND(is_compressed());
new_data.resize((width / 2) * (height / 2) * get_format_pixel_size(format));
ERR_FAIL_COND(data.is_empty() || new_data.is_empty());
@ -1963,7 +1960,7 @@ void Image::normalize() {
}
Error Image::generate_mipmaps(bool p_renormalize) {
ERR_FAIL_COND_V_MSG(!_can_modify(format), ERR_UNAVAILABLE, "Cannot generate mipmaps in compressed or custom image formats.");
ERR_FAIL_COND_V_MSG(is_compressed(), ERR_UNAVAILABLE, "Cannot generate mipmaps from compressed image formats.");
ERR_FAIL_COND_V_MSG(format == FORMAT_RGBA4444, ERR_UNAVAILABLE, "Cannot generate mipmaps from RGBA4444 format.");
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
@ -2180,7 +2177,7 @@ void Image::clear_mipmaps() {
}
bool Image::is_empty() const {
return (data.size() == 0);
return (data.is_empty());
}
Vector<uint8_t> Image::get_data() const {
@ -2297,7 +2294,7 @@ void Image::initialize_data(const char **p_xpm) {
switch (status) {
case READING_HEADER: {
String line_str = line_ptr;
line_str.replace("\t", " ");
line_str.replace_char('\t', ' ');
size_width = line_str.get_slicec(' ', 0).to_int();
size_height = line_str.get_slicec(' ', 1).to_int();
@ -2441,47 +2438,75 @@ void Image::initialize_data(const char **p_xpm) {
}
bool Image::is_invisible() const {
if (format == FORMAT_L8 || format == FORMAT_RGB8 || format == FORMAT_RG8) {
return false;
}
int64_t len = data.size();
int w, h;
int64_t len;
_get_mipmap_offset_and_size(1, len, w, h);
if (len == 0) {
return true;
}
int w, h;
_get_mipmap_offset_and_size(1, len, w, h);
const uint8_t *r = data.ptr();
const unsigned char *data_ptr = r;
bool detected = false;
switch (format) {
case FORMAT_LA8: {
for (int i = 0; i < (len >> 1); i++) {
DETECT_NON_ALPHA(data_ptr[(i << 1) + 1]);
}
const int pixel_count = len / 2;
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
for (int i = 0; i < pixel_count; i++) {
if ((pixeldata[i] & 0xFF00) != 0) {
return false;
}
}
} break;
case FORMAT_RGBA8: {
for (int i = 0; i < (len >> 2); i++) {
DETECT_NON_ALPHA(data_ptr[(i << 2) + 3])
const int pixel_count = len / 4;
const uint32_t *pixeldata = reinterpret_cast<const uint32_t *>(data.ptr());
for (int i = 0; i < pixel_count; i++) {
if ((pixeldata[i] & 0xFF000000) != 0) {
return false;
}
}
} break;
case FORMAT_RGBA4444: {
const int pixel_count = len / 2;
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
case FORMAT_DXT3:
case FORMAT_DXT5: {
detected = true;
for (int i = 0; i < pixel_count; i++) {
if ((pixeldata[i] & 0x000F) != 0) {
return false;
}
}
} break;
case FORMAT_RGBAH: {
// The alpha mask accounts for the sign bit.
const int pixel_count = len / 4;
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
for (int i = 0; i < pixel_count; i += 4) {
if ((pixeldata[i + 3] & 0x7FFF) != 0) {
return false;
}
}
} break;
case FORMAT_RGBAF: {
// The alpha mask accounts for the sign bit.
const int pixel_count = len / 4;
const uint32_t *pixeldata = reinterpret_cast<const uint32_t *>(data.ptr());
for (int i = 0; i < pixel_count; i += 4) {
if ((pixeldata[i + 3] & 0x7FFFFFFF) != 0) {
return false;
}
}
} break;
default: {
// Formats that are compressed or don't support alpha channels are presumed to be visible.
return false;
}
}
return !detected;
// Every pixel has been checked, the image is invisible.
return true;
}
Image::AlphaMode Image::detect_alpha() const {
@ -2603,6 +2628,21 @@ Vector<uint8_t> Image::save_exr_to_buffer(bool p_grayscale) const {
return save_exr_buffer_func(Ref<Image>((Image *)this), p_grayscale);
}
Error Image::save_dds(const String &p_path) const {
if (save_dds_func == nullptr) {
return ERR_UNAVAILABLE;
}
return save_dds_func(p_path, Ref<Image>((Image *)this));
}
Vector<uint8_t> Image::save_dds_to_buffer() const {
if (save_dds_buffer_func == nullptr) {
return Vector<uint8_t>();
}
return save_dds_buffer_func(Ref<Image>((Image *)this));
}
Error Image::save_webp(const String &p_path, const bool p_lossy, const float p_quality) const {
if (save_webp_func == nullptr) {
return ERR_UNAVAILABLE;
@ -2682,6 +2722,19 @@ Error Image::decompress() {
return OK;
}
bool Image::can_decompress(const String &p_format_tag) {
if (p_format_tag == "astc") {
return _image_decompress_astc != nullptr;
} else if (p_format_tag == "bptc") {
return _image_decompress_bptc != nullptr;
} else if (p_format_tag == "etc2") {
return _image_decompress_etc2 != nullptr;
} else if (p_format_tag == "s3tc") {
return _image_decompress_bc != nullptr;
}
return false;
}
Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p_astc_format) {
ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode.");
ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source.");
@ -2863,7 +2916,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const P
ERR_FAIL_COND(dsize == 0);
ERR_FAIL_COND(srcdsize == 0);
ERR_FAIL_COND(format != p_src->format);
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot blit_rect in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot blit_rect in compressed image formats.");
Rect2i src_rect;
Rect2i dest_rect;
@ -3043,10 +3096,10 @@ void Image::_repeat_pixel_over_subsequent_memory(uint8_t *p_pixel, int p_pixel_s
}
void Image::fill(const Color &p_color) {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill in compressed image formats.");
uint8_t *dst_data_ptr = data.ptrw();
@ -3059,10 +3112,10 @@ void Image::fill(const Color &p_color) {
}
void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill rect in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill rect in compressed image formats.");
Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect.abs());
if (!r.has_area()) {
@ -3278,7 +3331,7 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
uint16_t rgba = 0;
rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31));
rgba |= uint16_t(CLAMP(p_color.g * 63.0, 0, 33)) << 5;
rgba |= uint16_t(CLAMP(p_color.g * 63.0, 0, 63)) << 5;
rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 11;
((uint16_t *)ptr)[ofs] = rgba;
@ -3366,7 +3419,7 @@ int64_t Image::get_data_size() const {
}
void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot adjust_bcs in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot adjust_bcs in compressed image formats.");
uint8_t *w = data.ptrw();
uint32_t pixel_size = get_format_pixel_size(format);
@ -3524,6 +3577,9 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("save_jpg_to_buffer", "quality"), &Image::save_jpg_to_buffer, DEFVAL(0.75));
ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false));
ClassDB::bind_method(D_METHOD("save_exr_to_buffer", "grayscale"), &Image::save_exr_to_buffer, DEFVAL(false));
ClassDB::bind_method(D_METHOD("save_dds", "path"), &Image::save_dds);
ClassDB::bind_method(D_METHOD("save_dds_to_buffer"), &Image::save_dds_to_buffer);
ClassDB::bind_method(D_METHOD("save_webp", "path", "lossy", "quality"), &Image::save_webp, DEFVAL(false), DEFVAL(0.75f));
ClassDB::bind_method(D_METHOD("save_webp_to_buffer", "lossy", "quality"), &Image::save_webp_to_buffer, DEFVAL(false), DEFVAL(0.75f));
@ -3577,6 +3633,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer);
ClassDB::bind_method(D_METHOD("load_bmp_from_buffer", "buffer"), &Image::load_bmp_from_buffer);
ClassDB::bind_method(D_METHOD("load_ktx_from_buffer", "buffer"), &Image::load_ktx_from_buffer);
ClassDB::bind_method(D_METHOD("load_dds_from_buffer", "buffer"), &Image::load_dds_from_buffer);
ClassDB::bind_method(D_METHOD("load_svg_from_buffer", "buffer", "scale"), &Image::load_svg_from_buffer, DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("load_svg_from_string", "svg_str", "scale"), &Image::load_svg_from_string, DEFVAL(1.0));
@ -3677,7 +3734,7 @@ void Image::normal_map_to_xy() {
}
Ref<Image> Image::rgbe_to_srgb() {
if (data.size() == 0) {
if (data.is_empty()) {
return Ref<Image>();
}
@ -3724,7 +3781,7 @@ Ref<Image> Image::get_image_from_mipmap(int p_mipmap) const {
}
void Image::bump_map_to_normal_map(float bump_scale) {
ERR_FAIL_COND(!_can_modify(format));
ERR_FAIL_COND(is_compressed());
clear_mipmaps();
convert(Image::FORMAT_RF);
@ -3799,7 +3856,7 @@ bool Image::detect_signed(bool p_include_mips) const {
}
void Image::srgb_to_linear() {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
@ -3830,7 +3887,7 @@ void Image::srgb_to_linear() {
}
void Image::linear_to_srgb() {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
@ -3861,7 +3918,7 @@ void Image::linear_to_srgb() {
}
void Image::premultiply_alpha() {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
@ -3883,7 +3940,7 @@ void Image::premultiply_alpha() {
}
void Image::fix_alpha_edges() {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
@ -4072,6 +4129,14 @@ Error Image::load_bmp_from_buffer(const Vector<uint8_t> &p_array) {
return _load_from_buffer(p_array, _bmp_mem_loader_func);
}
Error Image::load_dds_from_buffer(const Vector<uint8_t> &p_array) {
ERR_FAIL_NULL_V_MSG(
_dds_mem_loader_func,
ERR_UNAVAILABLE,
"The DDS module isn't enabled. Recompile the Godot editor or export template binary with the `module_dds_enabled=yes` SCons option.");
return _load_from_buffer(p_array, _dds_mem_loader_func);
}
Error Image::load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale) {
ERR_FAIL_NULL_V_MSG(
_svg_scalable_mem_loader_func,
@ -4266,10 +4331,10 @@ Dictionary Image::compute_image_metrics(const Ref<Image> p_compared_image, bool
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Dictionary result;
result["max"] = INFINITY;
result["mean"] = INFINITY;
result["mean_squared"] = INFINITY;
result["root_mean_squared"] = INFINITY;
result["max"] = Math::INF;
result["mean"] = Math::INF;
result["mean_squared"] = Math::INF;
result["root_mean_squared"] = Math::INF;
result["peak_snr"] = 0.0f;
ERR_FAIL_COND_V(p_compared_image.is_null(), result);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IMAGE_H
#define IMAGE_H
#pragma once
#include "core/io/resource.h"
#include "core/math/color.h"
@ -59,6 +58,9 @@ typedef Vector<uint8_t> (*SaveWebPBufferFunc)(const Ref<Image> &p_img, const boo
typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale);
typedef Vector<uint8_t> (*SaveEXRBufferFunc)(const Ref<Image> &p_img, bool p_grayscale);
typedef Error (*SaveDDSFunc)(const String &p_path, const Ref<Image> &p_img);
typedef Vector<uint8_t> (*SaveDDSBufferFunc)(const Ref<Image> &p_img);
class Image : public Resource {
GDCLASS(Image, Resource);
@ -186,10 +188,12 @@ public:
static SaveJPGFunc save_jpg_func;
static SaveEXRFunc save_exr_func;
static SaveWebPFunc save_webp_func;
static SaveDDSFunc save_dds_func;
static SavePNGBufferFunc save_png_buffer_func;
static SaveEXRBufferFunc save_exr_buffer_func;
static SaveJPGBufferFunc save_jpg_buffer_func;
static SaveWebPBufferFunc save_webp_buffer_func;
static SaveDDSBufferFunc save_dds_buffer_func;
// External loader function pointers.
@ -201,6 +205,7 @@ public:
static ImageMemLoadFunc _bmp_mem_loader_func;
static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func;
static ImageMemLoadFunc _ktx_mem_loader_func;
static ImageMemLoadFunc _dds_mem_loader_func;
// External VRAM compression function pointers.
@ -251,7 +256,6 @@ private:
_FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_width, int &r_height) const; // Get where the mipmap begins in data.
static int64_t _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1, int *r_mm_width = nullptr, int *r_mm_height = nullptr);
bool _can_modify(Format p_format) const;
_FORCE_INLINE_ void _get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest, Rect2i &r_clipped_src_rect, Rect2i &r_clipped_dest_rect) const;
@ -334,9 +338,11 @@ public:
static Ref<Image> load_from_file(const String &p_path);
Error save_png(const String &p_path) const;
Error save_jpg(const String &p_path, float p_quality = 0.75) const;
Error save_dds(const String &p_path) const;
Vector<uint8_t> save_png_to_buffer() const;
Vector<uint8_t> save_jpg_to_buffer(float p_quality = 0.75) const;
Vector<uint8_t> save_exr_to_buffer(bool p_grayscale = false) const;
Vector<uint8_t> save_dds_to_buffer() const;
Error save_exr(const String &p_path, bool p_grayscale = false) const;
Error save_webp(const String &p_path, const bool p_lossy = false, const float p_quality = 0.75f) const;
Vector<uint8_t> save_webp_to_buffer(const bool p_lossy = false, const float p_quality = 0.75f) const;
@ -373,6 +379,8 @@ public:
bool is_compressed() const;
static bool is_format_compressed(Format p_format);
static bool can_decompress(const String &p_format_tag);
void fix_alpha_edges();
void premultiply_alpha();
void srgb_to_linear();
@ -403,6 +411,7 @@ public:
Error load_tga_from_buffer(const Vector<uint8_t> &p_array);
Error load_bmp_from_buffer(const Vector<uint8_t> &p_array);
Error load_ktx_from_buffer(const Vector<uint8_t> &p_array);
Error load_dds_from_buffer(const Vector<uint8_t> &p_array);
Error load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale = 1.0);
Error load_svg_from_string(const String &p_svg_str, float scale = 1.0);
@ -442,5 +451,3 @@ VARIANT_ENUM_CAST(Image::UsedChannels)
VARIANT_ENUM_CAST(Image::AlphaMode)
VARIANT_ENUM_CAST(Image::RoughnessChannel)
VARIANT_ENUM_CAST(Image::ASTCFormat)
#endif // IMAGE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IMAGE_LOADER_H
#define IMAGE_LOADER_H
#pragma once
#include "core/core_bind.h"
#include "core/io/file_access.h"
@ -108,5 +107,3 @@ public:
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
};
#endif // IMAGE_LOADER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IP_H
#define IP_H
#pragma once
#include "core/io/ip_address.h"
#include "core/os/os.h"
@ -110,5 +109,3 @@ public:
VARIANT_ENUM_CAST(IP::Type);
VARIANT_ENUM_CAST(IP::ResolverStatus);
#endif // IP_H

View file

@ -148,7 +148,7 @@ void IPAddress::_parse_ipv6(const String &p_string) {
void IPAddress::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret) {
String ip;
if (p_start != 0) {
ip = p_string.substr(p_start, p_string.length() - p_start);
ip = p_string.substr(p_start);
} else {
ip = p_string;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IP_ADDRESS_H
#define IP_ADDRESS_H
#pragma once
#include "core/string/ustring.h"
@ -96,4 +95,6 @@ public:
IPAddress() { clear(); }
};
#endif // IP_ADDRESS_H
// Zero-constructing IPAddress initializes field, valid, and wildcard to 0 (and thus empty).
template <>
struct is_zero_constructible<IPAddress> : std::true_type {};

View file

@ -122,8 +122,7 @@ String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_
ERR_FAIL_COND_V_MSG(p_markers.has(d.id()), "\"{...}\"", "Converting circular structure to JSON.");
p_markers.insert(d.id());
List<Variant> keys;
d.get_key_list(&keys);
LocalVector<Variant> keys = d.get_key_list();
if (p_sort_keys) {
keys.sort_custom<StringLikeVariantOrder>();
@ -664,201 +663,96 @@ Variant JSON::_from_native(const Variant &p_variant, bool p_full_objects, int p_
case Variant::VECTOR2: {
const Vector2 v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
Array args = { v.x, v.y };
RETURN_ARGS;
} break;
case Variant::VECTOR2I: {
const Vector2i v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
Array args = { v.x, v.y };
RETURN_ARGS;
} break;
case Variant::RECT2: {
const Rect2 r = p_variant;
Array args;
args.push_back(r.position.x);
args.push_back(r.position.y);
args.push_back(r.size.width);
args.push_back(r.size.height);
Array args = { r.position.x, r.position.y, r.size.width, r.size.height };
RETURN_ARGS;
} break;
case Variant::RECT2I: {
const Rect2i r = p_variant;
Array args;
args.push_back(r.position.x);
args.push_back(r.position.y);
args.push_back(r.size.width);
args.push_back(r.size.height);
Array args = { r.position.x, r.position.y, r.size.width, r.size.height };
RETURN_ARGS;
} break;
case Variant::VECTOR3: {
const Vector3 v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
args.push_back(v.z);
Array args = { v.x, v.y, v.z };
RETURN_ARGS;
} break;
case Variant::VECTOR3I: {
const Vector3i v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
args.push_back(v.z);
Array args = { v.x, v.y, v.z };
RETURN_ARGS;
} break;
case Variant::TRANSFORM2D: {
const Transform2D t = p_variant;
Array args;
args.push_back(t[0].x);
args.push_back(t[0].y);
args.push_back(t[1].x);
args.push_back(t[1].y);
args.push_back(t[2].x);
args.push_back(t[2].y);
Array args = { t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y };
RETURN_ARGS;
} break;
case Variant::VECTOR4: {
const Vector4 v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
args.push_back(v.z);
args.push_back(v.w);
Array args = { v.x, v.y, v.z, v.w };
RETURN_ARGS;
} break;
case Variant::VECTOR4I: {
const Vector4i v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
args.push_back(v.z);
args.push_back(v.w);
Array args = { v.x, v.y, v.z, v.w };
RETURN_ARGS;
} break;
case Variant::PLANE: {
const Plane p = p_variant;
Array args;
args.push_back(p.normal.x);
args.push_back(p.normal.y);
args.push_back(p.normal.z);
args.push_back(p.d);
Array args = { p.normal.x, p.normal.y, p.normal.z, p.d };
RETURN_ARGS;
} break;
case Variant::QUATERNION: {
const Quaternion q = p_variant;
Array args;
args.push_back(q.x);
args.push_back(q.y);
args.push_back(q.z);
args.push_back(q.w);
Array args = { q.x, q.y, q.z, q.w };
RETURN_ARGS;
} break;
case Variant::AABB: {
const AABB aabb = p_variant;
Array args;
args.push_back(aabb.position.x);
args.push_back(aabb.position.y);
args.push_back(aabb.position.z);
args.push_back(aabb.size.x);
args.push_back(aabb.size.y);
args.push_back(aabb.size.z);
Array args = { aabb.position.x, aabb.position.y, aabb.position.z, aabb.size.x, aabb.size.y, aabb.size.z };
RETURN_ARGS;
} break;
case Variant::BASIS: {
const Basis b = p_variant;
Array args;
args.push_back(b.get_column(0).x);
args.push_back(b.get_column(0).y);
args.push_back(b.get_column(0).z);
args.push_back(b.get_column(1).x);
args.push_back(b.get_column(1).y);
args.push_back(b.get_column(1).z);
args.push_back(b.get_column(2).x);
args.push_back(b.get_column(2).y);
args.push_back(b.get_column(2).z);
Array args = { b.get_column(0).x, b.get_column(0).y, b.get_column(0).z,
b.get_column(1).x, b.get_column(1).y, b.get_column(1).z,
b.get_column(2).x, b.get_column(2).y, b.get_column(2).z };
RETURN_ARGS;
} break;
case Variant::TRANSFORM3D: {
const Transform3D t = p_variant;
Array args;
args.push_back(t.basis.get_column(0).x);
args.push_back(t.basis.get_column(0).y);
args.push_back(t.basis.get_column(0).z);
args.push_back(t.basis.get_column(1).x);
args.push_back(t.basis.get_column(1).y);
args.push_back(t.basis.get_column(1).z);
args.push_back(t.basis.get_column(2).x);
args.push_back(t.basis.get_column(2).y);
args.push_back(t.basis.get_column(2).z);
args.push_back(t.origin.x);
args.push_back(t.origin.y);
args.push_back(t.origin.z);
Array args = { t.basis.get_column(0).x, t.basis.get_column(0).y, t.basis.get_column(0).z,
t.basis.get_column(1).x, t.basis.get_column(1).y, t.basis.get_column(1).z,
t.basis.get_column(2).x, t.basis.get_column(2).y, t.basis.get_column(2).z,
t.origin.x, t.origin.y, t.origin.z };
RETURN_ARGS;
} break;
case Variant::PROJECTION: {
const Projection p = p_variant;
Array args;
args.push_back(p[0].x);
args.push_back(p[0].y);
args.push_back(p[0].z);
args.push_back(p[0].w);
args.push_back(p[1].x);
args.push_back(p[1].y);
args.push_back(p[1].z);
args.push_back(p[1].w);
args.push_back(p[2].x);
args.push_back(p[2].y);
args.push_back(p[2].z);
args.push_back(p[2].w);
args.push_back(p[3].x);
args.push_back(p[3].y);
args.push_back(p[3].z);
args.push_back(p[3].w);
Array args = { p[0].x, p[0].y, p[0].z, p[0].w,
p[1].x, p[1].y, p[1].z, p[1].w,
p[2].x, p[2].y, p[2].z, p[2].w,
p[3].x, p[3].y, p[3].z, p[3].w };
RETURN_ARGS;
} break;
case Variant::COLOR: {
const Color c = p_variant;
Array args;
args.push_back(c.r);
args.push_back(c.g);
args.push_back(c.b);
args.push_back(c.a);
Array args = { c.r, c.g, c.b, c.a };
RETURN_ARGS;
} break;
@ -922,12 +816,9 @@ Variant JSON::_from_native(const Variant &p_variant, bool p_full_objects, int p_
ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ret, "Variant is too deep. Bailing.");
List<Variant> keys;
dict.get_key_list(&keys);
for (const Variant &key : keys) {
args.push_back(_from_native(key, p_full_objects, p_depth + 1));
args.push_back(_from_native(dict[key], p_full_objects, p_depth + 1));
for (const KeyValue<Variant, Variant> &kv : dict) {
args.push_back(_from_native(kv.key, p_full_objects, p_depth + 1));
args.push_back(_from_native(kv.value, p_full_objects, p_depth + 1));
}
return ret;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef JSON_H
#define JSON_H
#pragma once
#include "core/io/resource.h"
#include "core/io/resource_loader.h"
@ -125,5 +124,3 @@ public:
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
virtual bool recognize(const Ref<Resource> &p_resource) const override;
};
#endif // JSON_H

View file

@ -36,10 +36,9 @@
#include "core/templates/rb_set.h"
#include "modules/modules_enabled.gen.h" // For regex.
#ifdef MODULE_REGEX_ENABLED
#include "modules/regex/regex.h"
#else
class RegEx : public RefCounted {};
#endif // MODULE_REGEX_ENABLED
#if defined(MINGW_ENABLED) || defined(_MSC_VER)
@ -156,7 +155,7 @@ void RotatedFileLogger::rotate_file() {
if (FileAccess::exists(base_path)) {
if (max_files > 1) {
String timestamp = Time::get_singleton()->get_datetime_string_from_system().replace(":", ".");
String timestamp = Time::get_singleton()->get_datetime_string_from_system().replace_char(':', '.');
String backup_name = base_path.get_basename() + timestamp;
if (!base_path.get_extension().is_empty()) {
backup_name += "." + base_path.get_extension();

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef LOGGER_H
#define LOGGER_H
#pragma once
#include "core/io/file_access.h"
#include "core/string/ustring.h"
@ -109,5 +108,3 @@ public:
virtual ~CompositeLogger();
};
#endif // LOGGER_H

View file

@ -107,7 +107,7 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r
ERR_FAIL_COND_V(strlen < 0 || strlen + pad > len, ERR_FILE_EOF);
String str;
ERR_FAIL_COND_V(str.parse_utf8((const char *)buf, strlen) != OK, ERR_INVALID_DATA);
ERR_FAIL_COND_V(str.append_utf8((const char *)buf, strlen) != OK, ERR_INVALID_DATA);
r_string = str;
// Add padding.
@ -1345,7 +1345,7 @@ static Error _encode_container_type(const ContainerType &p_type, uint8_t *&buf,
_encode_string(EncodedObjectAsID::get_class_static(), buf, r_len);
}
} else if (p_type.class_name != StringName()) {
_encode_string(p_full_objects ? p_type.class_name.operator String() : EncodedObjectAsID::get_class_static(), buf, r_len);
_encode_string(p_full_objects ? p_type.class_name : EncodedObjectAsID::get_class_static(), buf, r_len);
} else {
// No need to check `p_full_objects` since `class_name` should be non-empty for `builtin_type == Variant::OBJECT`.
if (buf) {
@ -1849,19 +1849,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
r_len += 4;
List<Variant> keys;
dict.get_key_list(&keys);
for (const Variant &key : keys) {
for (const KeyValue<Variant, Variant> &kv : dict) {
int len;
Error err = encode_variant(key, buf, len, p_full_objects, p_depth + 1);
Error err = encode_variant(kv.key, buf, len, p_full_objects, p_depth + 1);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
r_len += len;
if (buf) {
buf += len;
}
const Variant *value = dict.getptr(key);
const Variant *value = dict.getptr(kv.key);
ERR_FAIL_NULL_V(value, ERR_BUG);
err = encode_variant(*value, buf, len, p_full_objects, p_depth + 1);
ERR_FAIL_COND_V(err, err);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef MARSHALLS_H
#define MARSHALLS_H
#pragma once
#include "core/math/math_defs.h"
#include "core/object/ref_counted.h"
@ -226,5 +225,3 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects = false, int p_depth = 0);
Vector<float> vector3_to_float32_array(const Vector3 *vecs, size_t count);
#endif // MARSHALLS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef MISSING_RESOURCE_H
#define MISSING_RESOURCE_H
#pragma once
#include "core/io/resource.h"
@ -61,5 +60,3 @@ public:
MissingResource();
};
#endif // MISSING_RESOURCE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef NET_SOCKET_H
#define NET_SOCKET_H
#pragma once
#include "core/io/ip.h"
#include "core/object/ref_counted.h"
@ -79,5 +78,3 @@ public:
virtual ~NetSocket() {}
};
#endif // NET_SOCKET_H

View file

@ -268,14 +268,12 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
encode_uint32(TYPE_DICT, &tmpdata.write[pos + 0]);
encode_uint32(len, &tmpdata.write[pos + 4]);
List<Variant> keys;
d.get_key_list(&keys);
List<DictKey> sortk;
for (const Variant &key : keys) {
for (const KeyValue<Variant, Variant> &kv : d) {
DictKey dk;
dk.hash = key.hash();
dk.key = key;
dk.hash = kv.key.hash();
dk.key = kv.key;
sortk.push_back(dk);
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PACKED_DATA_CONTAINER_H
#define PACKED_DATA_CONTAINER_H
#pragma once
#include "core/io/resource.h"
@ -100,5 +99,3 @@ public:
PackedDataContainerRef() {}
};
#endif // PACKED_DATA_CONTAINER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PACKET_PEER_H
#define PACKET_PEER_H
#pragma once
#include "core/io/stream_peer.h"
#include "core/object/class_db.h"
@ -124,5 +123,3 @@ public:
int get_output_buffer_max_size() const;
PacketPeerStream();
};
#endif // PACKET_PEER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PACKET_PEER_DTLS_H
#define PACKET_PEER_DTLS_H
#pragma once
#include "core/crypto/crypto.h"
#include "core/io/packet_peer_udp.h"
@ -64,5 +63,3 @@ public:
};
VARIANT_ENUM_CAST(PacketPeerDTLS::Status);
#endif // PACKET_PEER_DTLS_H

View file

@ -105,18 +105,16 @@ Error PacketPeerUDP::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
return ERR_UNAVAILABLE;
}
/* Bogus GCC warning here:
* In member function 'int RingBuffer<T>::read(T*, int, bool) [with T = unsigned char]',
* inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:112:9,
* inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:99:7:
* Error: ./core/ring_buffer.h:68:46: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=]
* 68 | p_buf[dst++] = read[pos + i];
* | ~~~~~~~~~~~~~^~~~~~~
*/
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wstringop-overflow=0"
#endif
/* Bogus GCC warning here:
* In member function 'int RingBuffer<T>::read(T*, int, bool) [with T = unsigned char]',
* inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:112:9,
* inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:99:7:
* Error: ./core/ring_buffer.h:68:46: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=]
* 68 | p_buf[dst++] = read[pos + i];
* | ~~~~~~~~~~~~~^~~~~~~
*/
GODOT_GCC_WARNING_PUSH
GODOT_GCC_PRAGMA(GCC diagnostic warning "-Wstringop-overflow=0") // Can't "ignore" this for some reason.
uint32_t size = 0;
uint8_t ipv6[16] = {};
@ -129,9 +127,7 @@ Error PacketPeerUDP::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
*r_buffer = packet_buffer;
r_buffer_size = size;
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
GODOT_GCC_WARNING_POP
return OK;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PACKET_PEER_UDP_H
#define PACKET_PEER_UDP_H
#pragma once
#include "core/io/ip.h"
#include "core/io/net_socket.h"
@ -97,5 +96,3 @@ public:
PacketPeerUDP();
~PacketPeerUDP();
};
#endif // PACKET_PEER_UDP_H

Some files were not shown because too many files have changed in this diff Show more