diff options
409 files changed, 8434 insertions, 43018 deletions
diff --git a/.github/workflows/android_builds.yml b/.github/workflows/android_builds.yml index b24a36beef..2dad253288 100644 --- a/.github/workflows/android_builds.yml +++ b/.github/workflows/android_builds.yml @@ -6,7 +6,7 @@ env: GODOT_BASE_BRANCH: master SCONSFLAGS: platform=android verbose=yes warnings=extra werror=yes debug_symbols=no --jobs=2 module_text_server_fb_enabled=yes SCONS_CACHE_LIMIT: 4096 - ANDROID_NDK_VERSION: 21.1.6352462 + ANDROID_NDK_VERSION: 21.4.7075529 jobs: android-template: @@ -29,7 +29,7 @@ jobs: with: java-version: 8 - - name: Install Android NDK r21 + - name: Install Android NDK run: | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install 'ndk;${{env.ANDROID_NDK_VERSION}}' diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index 0982d768d6..b4bbaaacb1 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -144,7 +144,7 @@ jobs: scons --version # We should always be explicit with our flags usage here since it's gonna be sure to always set those flags - # [Workaround] SwiftShader doesn't support tesselation, so we skip Godot check about it + # [Workaround] SwiftShader doesn't support tessellation, so we skip Godot check about it - name: Compilation env: SCONS_CACHE: ${{github.workspace}}/.scons_cache/ diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml index b7cc127226..d1db449ab0 100644 --- a/.github/workflows/windows_builds.yml +++ b/.github/workflows/windows_builds.yml @@ -46,7 +46,7 @@ jobs: - name: Configuring Python packages run: | python -c "import sys; print(sys.version)" - python -m pip install scons pywin32 + python -m pip install scons python --version scons --version @@ -102,7 +102,7 @@ jobs: - name: Configuring Python packages run: | python -c "import sys; print(sys.version)" - python -m pip install scons pywin32 + python -m pip install scons python --version scons --version @@ -7,7 +7,7 @@ support of generous donors. The ways to donate to the project, as well as details on how the funds are used, are described on [Godot's website](https://godotengine.org/donate). -The following is a list of the current monthly donors, to be have their +The following is a list of the current monthly donors, who will have their generous deed immortalized in the next stable release of Godot Engine. ## Platinum sponsors diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 84d8d0d4d3..2f5d7cb081 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -1259,6 +1259,7 @@ String _File::get_path_absolute() const { void _File::seek(int64_t p_position) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); + ERR_FAIL_COND_MSG(p_position < 0, "Seek position must be a positive integer."); f->seek(p_position); } @@ -1267,12 +1268,12 @@ void _File::seek_end(int64_t p_position) { f->seek_end(p_position); } -int64_t _File::get_position() const { +uint64_t _File::get_position() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_position(); } -int64_t _File::get_len() const { +uint64_t _File::get_len() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_len(); } @@ -1317,7 +1318,7 @@ real_t _File::get_real() const { return f->get_real(); } -Vector<uint8_t> _File::get_buffer(int p_length) const { +Vector<uint8_t> _File::get_buffer(int64_t p_length) const { Vector<uint8_t> data; ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use."); @@ -1330,8 +1331,7 @@ Vector<uint8_t> _File::get_buffer(int p_length) const { ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements."); uint8_t *w = data.ptrw(); - int len = f->get_buffer(&w[0], p_length); - ERR_FAIL_COND_V(len < 0, Vector<uint8_t>()); + int64_t len = f->get_buffer(&w[0], p_length); if (len < p_length) { data.resize(len); @@ -1344,7 +1344,7 @@ String _File::get_as_text() const { ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use."); String text; - size_t original_pos = f->get_position(); + uint64_t original_pos = f->get_position(); f->seek(0); String l = get_line(); @@ -1473,7 +1473,7 @@ void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim void _File::store_buffer(const Vector<uint8_t> &p_buffer) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); - int len = p_buffer.size(); + uint64_t len = p_buffer.size(); if (len == 0) { return; } @@ -1721,9 +1721,9 @@ bool _Directory::dir_exists(String p_dir) { return d->dir_exists(p_dir); } -int _Directory::get_space_left() { - ERR_FAIL_COND_V_MSG(!is_open(), 0, "Directory must be opened before use."); - return d->get_space_left() / 1024 * 1024; //return value in megabytes, given binding is int +uint64_t _Directory::get_space_left() { + ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use."); + return d->get_space_left() / 1024 * 1024; // Truncate to closest MiB. } Error _Directory::copy(String p_from, String p_to) { diff --git a/core/core_bind.h b/core/core_bind.h index 3920116ca4..8bd96d8268 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -390,8 +390,8 @@ public: void seek(int64_t p_position); // Seek to a given position. void seek_end(int64_t p_position = 0); // Seek from the end of file. - int64_t get_position() const; // Get position in the file. - int64_t get_len() const; // Get size of the file. + uint64_t get_position() const; // Get position in the file. + uint64_t get_len() const; // Get size of the file. bool eof_reached() const; // Reading passed EOF. @@ -406,7 +406,7 @@ public: Variant get_var(bool p_allow_objects = false) const; - Vector<uint8_t> get_buffer(int p_length) const; // Get an array of bytes. + Vector<uint8_t> get_buffer(int64_t p_length) const; // Get an array of bytes. String get_line() const; Vector<String> get_csv_line(const String &p_delim = ",") const; String get_as_text() const; @@ -486,7 +486,7 @@ public: bool file_exists(String p_file); bool dir_exists(String p_dir); - int get_space_left(); + uint64_t get_space_left(); Error copy(String p_from, String p_to); Error rename(String p_from, String p_to); diff --git a/core/core_constants.cpp b/core/core_constants.cpp index f40928350a..a0a41015dc 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -161,7 +161,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(KEY_PAGEUP); BIND_CORE_ENUM_CONSTANT(KEY_PAGEDOWN); BIND_CORE_ENUM_CONSTANT(KEY_SHIFT); - BIND_CORE_ENUM_CONSTANT(KEY_CONTROL); + BIND_CORE_ENUM_CONSTANT(KEY_CTRL); BIND_CORE_ENUM_CONSTANT(KEY_META); BIND_CORE_ENUM_CONSTANT(KEY_ALT); BIND_CORE_ENUM_CONSTANT(KEY_CAPSLOCK); diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp index 1dd7e268a5..ab368471e4 100644 --- a/core/debugger/local_debugger.cpp +++ b/core/debugger/local_debugger.cpp @@ -183,7 +183,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { print_line("Error: Unknown option " + key); } else { // Allow explicit tab character - String value = key_value.right(value_pos + 1).replace("\\t", "\t"); + String value = key_value.substr(value_pos + 1).replace("\\t", "\t"); options[key] = value; } @@ -348,7 +348,7 @@ Pair<String, int> LocalDebugger::to_breakpoint(const String &p_line) { } breakpoint.first = script_debugger->breakpoint_find_source(breakpoint_part.left(last_colon).strip_edges()); - breakpoint.second = breakpoint_part.right(last_colon).strip_edges().to_int(); + breakpoint.second = breakpoint_part.substr(last_colon).strip_edges().to_int(); return breakpoint; } diff --git a/core/input/input.cpp b/core/input/input.cpp index 2304c05bf8..6eafec087d 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -1262,16 +1262,16 @@ void Input::parse_mapping(String p_mapping) { } else if (output[0] == '-') { output_range = NEGATIVE_HALF_AXIS; } - output = output.right(1); + output = output.substr(1); } JoyAxisRange input_range = FULL_AXIS; if (input[0] == '+') { input_range = POSITIVE_HALF_AXIS; - input = input.right(1); + input = input.substr(1); } else if (input[0] == '-') { input_range = NEGATIVE_HALF_AXIS; - input = input.right(1); + input = input.substr(1); } bool invert_axis = false; if (input[input.length() - 1] == '~') { @@ -1299,11 +1299,11 @@ void Input::parse_mapping(String p_mapping) { switch (input[0]) { case 'b': binding.inputType = TYPE_BUTTON; - binding.input.button = input.right(1).to_int(); + binding.input.button = input.substr(1).to_int(); break; case 'a': binding.inputType = TYPE_AXIS; - binding.input.axis.axis = input.right(1).to_int(); + binding.input.axis.axis = input.substr(1).to_int(); binding.input.axis.range = input_range; binding.input.axis.invert = invert_axis; break; @@ -1312,7 +1312,7 @@ void Input::parse_mapping(String p_mapping) { String(entry[idx] + "\nInvalid hat input: " + input)); binding.inputType = TYPE_HAT; binding.input.hat.hat = input.substr(1, 1).to_int(); - binding.input.hat.hat_mask = static_cast<HatMask>(input.right(3).to_int()); + binding.input.hat.hat_mask = static_cast<HatMask>(input.substr(3).to_int()); break; default: ERR_CONTINUE_MSG(true, String(entry[idx] + "\nUnrecognised input string: " + input)); diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 46629d742e..6f063c217f 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -147,66 +147,66 @@ bool InputEventWithModifiers::is_storing_command() const { return store_command; } -void InputEventWithModifiers::set_shift(bool p_enabled) { - shift = p_enabled; +void InputEventWithModifiers::set_shift_pressed(bool p_enabled) { + shift_pressed = p_enabled; } -bool InputEventWithModifiers::get_shift() const { - return shift; +bool InputEventWithModifiers::is_shift_pressed() const { + return shift_pressed; } -void InputEventWithModifiers::set_alt(bool p_enabled) { - alt = p_enabled; +void InputEventWithModifiers::set_alt_pressed(bool p_enabled) { + alt_pressed = p_enabled; } -bool InputEventWithModifiers::get_alt() const { - return alt; +bool InputEventWithModifiers::is_alt_pressed() const { + return alt_pressed; } -void InputEventWithModifiers::set_control(bool p_enabled) { - control = p_enabled; +void InputEventWithModifiers::set_ctrl_pressed(bool p_enabled) { + ctrl_pressed = p_enabled; } -bool InputEventWithModifiers::get_control() const { - return control; +bool InputEventWithModifiers::is_ctrl_pressed() const { + return ctrl_pressed; } -void InputEventWithModifiers::set_metakey(bool p_enabled) { - meta = p_enabled; +void InputEventWithModifiers::set_meta_pressed(bool p_enabled) { + meta_pressed = p_enabled; } -bool InputEventWithModifiers::get_metakey() const { - return meta; +bool InputEventWithModifiers::is_meta_pressed() const { + return meta_pressed; } -void InputEventWithModifiers::set_command(bool p_enabled) { - command = p_enabled; +void InputEventWithModifiers::set_command_pressed(bool p_enabled) { + command_pressed = p_enabled; } -bool InputEventWithModifiers::get_command() const { - return command; +bool InputEventWithModifiers::is_command_pressed() const { + return command_pressed; } void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModifiers *event) { - set_alt(event->get_alt()); - set_shift(event->get_shift()); - set_control(event->get_control()); - set_metakey(event->get_metakey()); + set_alt_pressed(event->is_alt_pressed()); + set_shift_pressed(event->is_shift_pressed()); + set_ctrl_pressed(event->is_ctrl_pressed()); + set_meta_pressed(event->is_meta_pressed()); } String InputEventWithModifiers::as_text() const { Vector<String> mod_names; - if (get_control()) { - mod_names.push_back(find_keycode_name(KEY_CONTROL)); + if (is_ctrl_pressed()) { + mod_names.push_back(find_keycode_name(KEY_CTRL)); } - if (get_shift()) { + if (is_shift_pressed()) { mod_names.push_back(find_keycode_name(KEY_SHIFT)); } - if (get_alt()) { + if (is_alt_pressed()) { mod_names.push_back(find_keycode_name(KEY_ALT)); } - if (get_metakey()) { + if (is_meta_pressed()) { mod_names.push_back(find_keycode_name(KEY_META)); } @@ -225,27 +225,27 @@ void InputEventWithModifiers::_bind_methods() { ClassDB::bind_method(D_METHOD("set_store_command", "enable"), &InputEventWithModifiers::set_store_command); ClassDB::bind_method(D_METHOD("is_storing_command"), &InputEventWithModifiers::is_storing_command); - ClassDB::bind_method(D_METHOD("set_alt", "enable"), &InputEventWithModifiers::set_alt); - ClassDB::bind_method(D_METHOD("get_alt"), &InputEventWithModifiers::get_alt); + ClassDB::bind_method(D_METHOD("set_alt_pressed", "pressed"), &InputEventWithModifiers::set_alt_pressed); + ClassDB::bind_method(D_METHOD("is_alt_pressed"), &InputEventWithModifiers::is_alt_pressed); - ClassDB::bind_method(D_METHOD("set_shift", "enable"), &InputEventWithModifiers::set_shift); - ClassDB::bind_method(D_METHOD("get_shift"), &InputEventWithModifiers::get_shift); + ClassDB::bind_method(D_METHOD("set_shift_pressed", "pressed"), &InputEventWithModifiers::set_shift_pressed); + ClassDB::bind_method(D_METHOD("is_shift_pressed"), &InputEventWithModifiers::is_shift_pressed); - ClassDB::bind_method(D_METHOD("set_control", "enable"), &InputEventWithModifiers::set_control); - ClassDB::bind_method(D_METHOD("get_control"), &InputEventWithModifiers::get_control); + ClassDB::bind_method(D_METHOD("set_ctrl_pressed", "pressed"), &InputEventWithModifiers::set_ctrl_pressed); + ClassDB::bind_method(D_METHOD("is_ctrl_pressed"), &InputEventWithModifiers::is_ctrl_pressed); - ClassDB::bind_method(D_METHOD("set_metakey", "enable"), &InputEventWithModifiers::set_metakey); - ClassDB::bind_method(D_METHOD("get_metakey"), &InputEventWithModifiers::get_metakey); + ClassDB::bind_method(D_METHOD("set_meta_pressed", "pressed"), &InputEventWithModifiers::set_meta_pressed); + ClassDB::bind_method(D_METHOD("is_meta_pressed"), &InputEventWithModifiers::is_meta_pressed); - ClassDB::bind_method(D_METHOD("set_command", "enable"), &InputEventWithModifiers::set_command); - ClassDB::bind_method(D_METHOD("get_command"), &InputEventWithModifiers::get_command); + ClassDB::bind_method(D_METHOD("set_command_pressed", "pressed"), &InputEventWithModifiers::set_command_pressed); + ClassDB::bind_method(D_METHOD("is_command_pressed"), &InputEventWithModifiers::is_command_pressed); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "store_command"), "set_store_command", "is_storing_command"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alt"), "set_alt", "get_alt"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shift"), "set_shift", "get_shift"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "control"), "set_control", "get_control"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta"), "set_metakey", "get_metakey"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "command"), "set_command", "get_command"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alt_pressed"), "set_alt_pressed", "is_alt_pressed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shift_pressed"), "set_shift_pressed", "is_shift_pressed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ctrl_pressed"), "set_ctrl_pressed", "is_ctrl_pressed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta_pressed"), "set_meta_pressed", "is_meta_pressed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "command_pressed"), "set_command_pressed", "is_command_pressed"); } void InputEventWithModifiers::_validate_property(PropertyInfo &property) const { @@ -253,18 +253,18 @@ void InputEventWithModifiers::_validate_property(PropertyInfo &property) const { // If we only want to Store "Command". #ifdef APPLE_STYLE_KEYS // Don't store "Meta" on Mac. - if (property.name == "meta") { + if (property.name == "meta_pressed") { property.usage ^= PROPERTY_USAGE_STORAGE; } #else - // Don't store "Control". - if (property.name == "control") { + // Don't store "Ctrl". + if (property.name == "ctrl_pressed") { property.usage ^= PROPERTY_USAGE_STORAGE; } #endif } else { - // We don't want to store command, only control or meta (on mac). - if (property.name == "command") { + // We don't want to store command, only ctrl or meta (on mac). + if (property.name == "command_pressed") { property.usage ^= PROPERTY_USAGE_STORAGE; } } @@ -314,16 +314,16 @@ bool InputEventKey::is_echo() const { uint32_t InputEventKey::get_keycode_with_modifiers() const { uint32_t sc = keycode; - if (get_control()) { + if (is_ctrl_pressed()) { sc |= KEY_MASK_CTRL; } - if (get_alt()) { + if (is_alt_pressed()) { sc |= KEY_MASK_ALT; } - if (get_shift()) { + if (is_shift_pressed()) { sc |= KEY_MASK_SHIFT; } - if (get_metakey()) { + if (is_meta_pressed()) { sc |= KEY_MASK_META; } @@ -332,16 +332,16 @@ uint32_t InputEventKey::get_keycode_with_modifiers() const { uint32_t InputEventKey::get_physical_keycode_with_modifiers() const { uint32_t sc = physical_keycode; - if (get_control()) { + if (is_ctrl_pressed()) { sc |= KEY_MASK_CTRL; } - if (get_alt()) { + if (is_alt_pressed()) { sc |= KEY_MASK_ALT; } - if (get_shift()) { + if (is_shift_pressed()) { sc |= KEY_MASK_SHIFT; } - if (get_metakey()) { + if (is_meta_pressed()) { sc |= KEY_MASK_META; } @@ -372,16 +372,16 @@ String InputEventKey::to_string() { String kc = ""; String physical = "false"; if (keycode == 0) { - kc = itos(physical_keycode) + " " + keycode_get_string(physical_keycode); + kc = itos(physical_keycode) + " (" + keycode_get_string(physical_keycode) + ")"; physical = "true"; } else { - kc = itos(keycode) + " " + keycode_get_string(keycode); + kc = itos(keycode) + " (" + keycode_get_string(keycode) + ")"; } String mods = InputEventWithModifiers::as_text(); - mods = mods == "" ? TTR("None") : mods; + mods = mods == "" ? TTR("none") : mods; - return vformat("InputEventKey: keycode=%s mods=%s physical=%s pressed=%s echo=%s", kc, mods, physical, p, e); + return vformat("InputEventKey: keycode=%s, mods=%s, physical=%s, pressed=%s, echo=%s", kc, mods, physical, p, e); } Ref<InputEventKey> InputEventKey::create_reference(uint32_t p_keycode) { @@ -391,19 +391,19 @@ Ref<InputEventKey> InputEventKey::create_reference(uint32_t p_keycode) { ie->set_unicode(p_keycode & KEY_CODE_MASK); if (p_keycode & KEY_MASK_SHIFT) { - ie->set_shift(true); + ie->set_shift_pressed(true); } if (p_keycode & KEY_MASK_ALT) { - ie->set_alt(true); + ie->set_alt_pressed(true); } if (p_keycode & KEY_MASK_CTRL) { - ie->set_control(true); + ie->set_ctrl_pressed(true); } if (p_keycode & KEY_MASK_CMD) { - ie->set_command(true); + ie->set_command_pressed(true); } if (p_keycode & KEY_MASK_META) { - ie->set_metakey(true); + ie->set_meta_pressed(true); } return ie; @@ -667,11 +667,11 @@ String InputEventMouseButton::to_string() { } String mods = InputEventWithModifiers::as_text(); - mods = mods == "" ? TTR("None") : mods; + mods = mods == "" ? TTR("none") : mods; // Work around the fact vformat can only take 5 substitutions but 6 need to be passed. - String index_and_mods = vformat("button_index=%s mods=%s", button_index, mods); - return vformat("InputEventMouseButton: %s pressed=%s position=(%s) button_mask=%s double_click=%s", index_and_mods, p, String(get_position()), itos(get_button_mask()), d); + String index_and_mods = vformat("button_index=%s, mods=%s", button_index, mods); + return vformat("InputEventMouseButton: %s, pressed=%s, position=(%s), button_mask=%d, double_click=%s", index_and_mods, p, String(get_position()), get_button_mask(), d); } void InputEventMouseButton::_bind_methods() { @@ -780,7 +780,9 @@ String InputEventMouseMotion::to_string() { break; } - return "InputEventMouseMotion : button_mask=" + button_mask_string + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + "), pressure=(" + rtos(get_pressure()) + "), tilt=(" + String(get_tilt()) + ")"; + // Work around the fact vformat can only take 5 substitutions but 6 need to be passed. + String mask_and_position = vformat("button_mask=%s, position=(%s)", button_mask_string, String(get_position())); + return vformat("InputEventMouseMotion: %s, relative=(%s), speed=(%s), pressure=%.2f, tilt=(%s)", mask_and_position, String(get_relative()), String(get_speed()), get_pressure(), String(get_tilt())); } bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) { @@ -801,19 +803,19 @@ bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) { return false; } - if (get_shift() != motion->get_shift()) { + if (is_shift_pressed() != motion->is_shift_pressed()) { return false; } - if (get_control() != motion->get_control()) { + if (is_ctrl_pressed() != motion->is_ctrl_pressed()) { return false; } - if (get_alt() != motion->get_alt()) { + if (is_alt_pressed() != motion->is_alt_pressed()) { return false; } - if (get_metakey() != motion->get_metakey()) { + if (is_meta_pressed() != motion->is_meta_pressed()) { return false; } @@ -918,11 +920,11 @@ static const char *_joy_axis_descriptions[JOY_AXIS_MAX] = { String InputEventJoypadMotion::as_text() const { String desc = axis < JOY_AXIS_MAX ? RTR(_joy_axis_descriptions[axis]) : TTR("Unknown Joypad Axis"); - return vformat(TTR("Joypad Motion on Axis %s (%s) with Value %s"), itos(axis), desc, String(Variant(axis_value))); + return vformat(TTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value); } String InputEventJoypadMotion::to_string() { - return "InputEventJoypadMotion : axis=" + itos(axis) + ", axis_value=" + String(Variant(axis_value)); + return vformat("InputEventJoypadMotion: axis=%d, axis_value=%.2f", axis, axis_value); } void InputEventJoypadMotion::_bind_methods() { @@ -1033,7 +1035,8 @@ String InputEventJoypadButton::as_text() const { } String InputEventJoypadButton::to_string() { - return "InputEventJoypadButton : button_index=" + itos(button_index) + ", pressed=" + (pressed ? "true" : "false") + ", pressure=" + String(Variant(pressure)); + String p = pressed ? "true" : "false"; + return vformat("InputEventJoypadButton: button_index=%d, pressed=%s, pressure=%.2f", button_index, p, pressure); } Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(int p_btn_index) { @@ -1104,7 +1107,8 @@ String InputEventScreenTouch::as_text() const { } String InputEventScreenTouch::to_string() { - return "InputEventScreenTouch : index=" + itos(index) + ", pressed=" + (pressed ? "true" : "false") + ", position=(" + String(get_position()) + ")"; + String p = pressed ? "true" : "false"; + return vformat("InputEventScreenTouch: index=%d, pressed=%s, position=(%s)", index, p, String(get_position())); } void InputEventScreenTouch::_bind_methods() { @@ -1177,7 +1181,7 @@ String InputEventScreenDrag::as_text() const { } String InputEventScreenDrag::to_string() { - return "InputEventScreenDrag : index=" + itos(index) + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + ")"; + return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), speed=(%s)", index, String(get_position()), String(get_relative()), String(get_speed())); } void InputEventScreenDrag::_bind_methods() { @@ -1264,7 +1268,8 @@ String InputEventAction::as_text() const { } String InputEventAction::to_string() { - return "InputEventAction : action=" + action + ", pressed=(" + (pressed ? "true" : "false"); + String p = pressed ? "true" : "false"; + return vformat("InputEventAction: action=\"%s\", pressed=%s", action, p); } void InputEventAction::_bind_methods() { @@ -1331,7 +1336,7 @@ String InputEventMagnifyGesture::as_text() const { } String InputEventMagnifyGesture::to_string() { - return "InputEventMagnifyGesture : factor=" + rtos(get_factor()) + ", position=(" + String(get_position()) + ")"; + return vformat("InputEventMagnifyGesture: factor=%.2f, position=(%s)", factor, String(get_position())); } void InputEventMagnifyGesture::_bind_methods() { @@ -1371,7 +1376,7 @@ String InputEventPanGesture::as_text() const { } String InputEventPanGesture::to_string() { - return "InputEventPanGesture : delta=(" + String(get_delta()) + "), position=(" + String(get_position()) + ")"; + return vformat("InputEventPanGesture: delta=(%s), position=(%s)", String(get_delta()), String(get_position())); } void InputEventPanGesture::_bind_methods() { @@ -1452,7 +1457,7 @@ String InputEventMIDI::as_text() const { } String InputEventMIDI::to_string() { - return vformat("InputEvenMIDI: channel=%s message=%s pitch=%s velocity=%s pressure=%s", itos(channel), itos(message), itos(pitch), itos(velocity), itos(pressure)); + return vformat("InputEventMIDI: channel=%d, message=%d, pitch=%d, velocity=%d, pressure=%d", channel, message, pitch, velocity, pressure); } void InputEventMIDI::_bind_methods() { diff --git a/core/input/input_event.h b/core/input/input_event.h index 5a33ee7b9c..eed0d79326 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -170,21 +170,21 @@ class InputEventWithModifiers : public InputEventFromWindow { bool store_command = true; - bool shift = false; - bool alt = false; + bool shift_pressed = false; + bool alt_pressed = false; #ifdef APPLE_STYLE_KEYS union { - bool command; - bool meta = false; //< windows/mac key + bool command_pressed; + bool meta_pressed = false; //< windows/mac key }; - bool control = false; + bool ctrl_pressed = false; #else union { - bool command; //< windows/mac key - bool control = false; + bool command_pressed; //< windows/mac key + bool ctrl_pressed = false; }; - bool meta = false; //< windows/mac key + bool meta_pressed = false; //< windows/mac key #endif protected: @@ -195,20 +195,20 @@ public: void set_store_command(bool p_enabled); bool is_storing_command() const; - void set_shift(bool p_enabled); - bool get_shift() const; + void set_shift_pressed(bool p_pressed); + bool is_shift_pressed() const; - void set_alt(bool p_enabled); - bool get_alt() const; + void set_alt_pressed(bool p_pressed); + bool is_alt_pressed() const; - void set_control(bool p_enabled); - bool get_control() const; + void set_ctrl_pressed(bool p_pressed); + bool is_ctrl_pressed() const; - void set_metakey(bool p_enabled); - bool get_metakey() const; + void set_meta_pressed(bool p_pressed); + bool is_meta_pressed() const; - void set_command(bool p_enabled); - bool get_command() const; + void set_command_pressed(bool p_pressed); + bool is_command_pressed() const; void set_modifiers_from_event(const InputEventWithModifiers *event); diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 7421909650..424509eb47 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -166,7 +166,7 @@ void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent ERR_FAIL_COND_MSG(p_event.is_null(), "It's not a reference to a valid InputEvent object."); ERR_FAIL_COND_MSG(!input_map.has(p_action), _suggest_actions(p_action)); if (_find_event(input_map[p_action], p_event, true)) { - return; // Already addded. + return; // Already added. } input_map[p_action].inputs.push_back(p_event); diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index b2440629e3..efcaa80fc5 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -32,7 +32,7 @@ #include "core/string/print_string.h" -void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, int p_block_size) { +void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, uint32_t p_block_size) { magic = p_magic.ascii().get_data(); if (magic.length() > 4) { magic = magic.substr(0, 4); @@ -67,10 +67,10 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) { ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted."); } read_total = f->get_32(); - int bc = (read_total / block_size) + 1; - int acc_ofs = f->get_position() + bc * 4; - int max_bs = 0; - for (int i = 0; i < bc; i++) { + uint32_t bc = (read_total / block_size) + 1; + uint64_t acc_ofs = f->get_position() + bc * 4; + uint32_t max_bs = 0; + for (uint32_t i = 0; i < bc; i++) { ReadBlock rb; rb.offset = acc_ofs; rb.csize = f->get_32(); @@ -148,15 +148,15 @@ void FileAccessCompressed::close() { f->store_32(cmode); //write compression mode 4 f->store_32(block_size); //write block size 4 f->store_32(write_max); //max amount of data written 4 - int bc = (write_max / block_size) + 1; + uint32_t bc = (write_max / block_size) + 1; - for (int i = 0; i < bc; i++) { + for (uint32_t i = 0; i < bc; i++) { f->store_32(0); //compressed sizes, will update later } Vector<int> block_sizes; - for (int i = 0; i < bc; i++) { - int bl = i == (bc - 1) ? write_max % block_size : block_size; + for (uint32_t i = 0; i < bc; i++) { + uint32_t bl = i == (bc - 1) ? write_max % block_size : block_size; uint8_t *bp = &write_ptr[i * block_size]; Vector<uint8_t> cblock; @@ -168,7 +168,7 @@ void FileAccessCompressed::close() { } f->seek(16); //ok write block sizes - for (int i = 0; i < bc; i++) { + for (uint32_t i = 0; i < bc; i++) { f->store_32(block_sizes[i]); } f->seek_end(); @@ -190,8 +190,9 @@ bool FileAccessCompressed::is_open() const { return f != nullptr; } -void FileAccessCompressed::seek(size_t p_position) { +void FileAccessCompressed::seek(uint64_t p_position) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); + if (writing) { ERR_FAIL_COND(p_position > write_max); @@ -204,7 +205,7 @@ void FileAccessCompressed::seek(size_t p_position) { } else { at_end = false; read_eof = false; - int block_idx = p_position / block_size; + uint32_t block_idx = p_position / block_size; if (block_idx != read_block) { read_block = block_idx; f->seek(read_blocks[read_block].offset); @@ -227,7 +228,7 @@ void FileAccessCompressed::seek_end(int64_t p_position) { } } -size_t FileAccessCompressed::get_position() const { +uint64_t FileAccessCompressed::get_position() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); if (writing) { return write_pos; @@ -236,7 +237,7 @@ size_t FileAccessCompressed::get_position() const { } } -size_t FileAccessCompressed::get_len() const { +uint64_t FileAccessCompressed::get_len() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); if (writing) { return write_max; @@ -285,9 +286,8 @@ uint8_t FileAccessCompressed::get_8() const { return ret; } -int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) 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); - ERR_FAIL_COND_V(p_length < 0, -1); ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use."); ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode."); @@ -296,7 +296,7 @@ int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const { return 0; } - for (int i = 0; i < p_length; i++) { + for (uint64_t i = 0; i < p_length; i++) { p_dst[i] = read_ptr[read_pos]; read_pos++; if (read_pos >= read_block_size) { diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h index 118d05ea57..d8a81c2417 100644 --- a/core/io/file_access_compressed.h +++ b/core/io/file_access_compressed.h @@ -37,34 +37,34 @@ class FileAccessCompressed : public FileAccess { Compression::Mode cmode = Compression::MODE_ZSTD; bool writing = false; - uint32_t write_pos = 0; + uint64_t write_pos = 0; uint8_t *write_ptr = nullptr; uint32_t write_buffer_size = 0; - uint32_t write_max = 0; + uint64_t write_max = 0; uint32_t block_size = 0; mutable bool read_eof = false; mutable bool at_end = false; struct ReadBlock { - int csize; - int offset; + uint32_t csize; + uint64_t offset; }; mutable Vector<uint8_t> comp_buffer; uint8_t *read_ptr = nullptr; - mutable int read_block = 0; - int read_block_count = 0; - mutable int read_block_size = 0; - mutable int read_pos = 0; + mutable uint32_t read_block = 0; + uint32_t read_block_count = 0; + mutable uint32_t read_block_size = 0; + mutable uint64_t read_pos = 0; Vector<ReadBlock> read_blocks; - uint32_t read_total = 0; + uint64_t read_total = 0; String magic = "GCMP"; mutable Vector<uint8_t> buffer; FileAccess *f = nullptr; public: - void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, int p_block_size = 4096); + void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, uint32_t p_block_size = 4096); Error open_after_magic(FileAccess *p_base); @@ -72,15 +72,15 @@ public: virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open - virtual void seek(size_t p_position); ///< seek to a given position + virtual void seek(uint64_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual size_t get_position() const; ///< get position in the file - virtual size_t get_len() const; ///< get size of the file + virtual uint64_t get_position() const; ///< get position in the file + virtual uint64_t get_len() const; ///< get size of the file virtual bool eof_reached() const; ///< reading passed EOF virtual uint8_t get_8() const; ///< get a byte - virtual int get_buffer(uint8_t *p_dst, int p_length) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; virtual Error get_error() const; ///< get last error diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 13377a3a25..9a6bee7348 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -70,13 +70,13 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8 base = p_base->get_position(); ERR_FAIL_COND_V(p_base->get_len() < base + length, ERR_FILE_CORRUPT); - uint32_t ds = length; + uint64_t ds = length; if (ds % 16) { ds += 16 - (ds % 16); } data.resize(ds); - uint32_t blen = p_base->get_buffer(data.ptrw(), ds); + uint64_t blen = p_base->get_buffer(data.ptrw(), ds); ERR_FAIL_COND_V(blen != ds, ERR_FILE_CORRUPT); { @@ -141,7 +141,7 @@ void FileAccessEncrypted::release() { void FileAccessEncrypted::_release() { if (writing) { Vector<uint8_t> compressed; - size_t len = data.size(); + uint64_t len = data.size(); if (len % 16) { len += 16 - (len % 16); } @@ -198,9 +198,9 @@ String FileAccessEncrypted::get_path_absolute() const { } } -void FileAccessEncrypted::seek(size_t p_position) { - if (p_position > (size_t)data.size()) { - p_position = data.size(); +void FileAccessEncrypted::seek(uint64_t p_position) { + if (p_position > get_len()) { + p_position = get_len(); } pos = p_position; @@ -208,14 +208,14 @@ void FileAccessEncrypted::seek(size_t p_position) { } void FileAccessEncrypted::seek_end(int64_t p_position) { - seek(data.size() + p_position); + seek(get_len() + p_position); } -size_t FileAccessEncrypted::get_position() const { +uint64_t FileAccessEncrypted::get_position() const { return pos; } -size_t FileAccessEncrypted::get_len() const { +uint64_t FileAccessEncrypted::get_len() const { return data.size(); } @@ -225,7 +225,7 @@ bool FileAccessEncrypted::eof_reached() const { uint8_t FileAccessEncrypted::get_8() const { ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode."); - if (pos >= data.size()) { + if (pos >= get_len()) { eofed = true; return 0; } @@ -235,13 +235,12 @@ uint8_t FileAccessEncrypted::get_8() const { return b; } -int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const { +uint64_t FileAccessEncrypted::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - ERR_FAIL_COND_V(p_length < 0, -1); ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode."); - int to_copy = MIN(p_length, data.size() - pos); - for (int i = 0; i < to_copy; i++) { + uint64_t to_copy = MIN(p_length, get_len() - pos); + for (uint64_t i = 0; i < to_copy; i++) { p_dst[i] = data[pos++]; } @@ -256,16 +255,16 @@ Error FileAccessEncrypted::get_error() const { return eofed ? ERR_FILE_EOF : OK; } -void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) { +void FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode."); - if (pos < data.size()) { - for (int i = 0; i < p_length; i++) { + if (pos < get_len()) { + for (uint64_t i = 0; i < p_length; i++) { store_8(p_src[i]); } - } else if (pos == data.size()) { + } else if (pos == get_len()) { data.resize(pos + p_length); - for (int i = 0; i < p_length; i++) { + for (uint64_t i = 0; i < p_length; i++) { data.write[pos + i] = p_src[i]; } pos += p_length; @@ -281,10 +280,10 @@ void FileAccessEncrypted::flush() { void FileAccessEncrypted::store_8(uint8_t p_dest) { ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode."); - if (pos < data.size()) { + if (pos < get_len()) { data.write[pos] = p_dest; pos++; - } else if (pos == data.size()) { + } else if (pos == get_len()) { data.push_back(p_dest); pos++; } diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index 969052d04f..8bea8c2585 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -47,10 +47,10 @@ private: Vector<uint8_t> key; bool writing = false; FileAccess *file = nullptr; - size_t base = 0; - size_t length = 0; + uint64_t base = 0; + uint64_t length = 0; Vector<uint8_t> data; - mutable int pos = 0; + mutable uint64_t pos = 0; mutable bool eofed = false; bool use_magic = true; @@ -68,21 +68,21 @@ public: virtual String get_path() const; /// returns the path for the current open file virtual String get_path_absolute() const; /// returns the absolute path for the current open file - virtual void seek(size_t p_position); ///< seek to a given position + virtual void seek(uint64_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual size_t get_position() const; ///< get position in the file - virtual size_t get_len() const; ///< get size of the file + virtual uint64_t get_position() const; ///< get position in the file + virtual uint64_t get_len() const; ///< get size of the file virtual bool eof_reached() const; ///< reading passed EOF virtual uint8_t get_8() const; ///< get a byte - virtual int get_buffer(uint8_t *p_dst, int p_length) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; virtual Error get_error() const; ///< get last error virtual void flush(); virtual void store_8(uint8_t p_dest); ///< store a byte - virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes virtual bool file_exists(const String &p_name); ///< return true if a file exists diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index af155a77a8..14e24d6668 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -71,7 +71,7 @@ bool FileAccessMemory::file_exists(const String &p_name) { return files && (files->find(name) != nullptr); } -Error FileAccessMemory::open_custom(const uint8_t *p_data, int p_len) { +Error FileAccessMemory::open_custom(const uint8_t *p_data, uint64_t p_len) { data = (uint8_t *)p_data; length = p_len; pos = 0; @@ -102,7 +102,7 @@ bool FileAccessMemory::is_open() const { return data != nullptr; } -void FileAccessMemory::seek(size_t p_position) { +void FileAccessMemory::seek(uint64_t p_position) { ERR_FAIL_COND(!data); pos = p_position; } @@ -112,12 +112,12 @@ void FileAccessMemory::seek_end(int64_t p_position) { pos = length + p_position; } -size_t FileAccessMemory::get_position() const { +uint64_t FileAccessMemory::get_position() const { ERR_FAIL_COND_V(!data, 0); return pos; } -size_t FileAccessMemory::get_len() const { +uint64_t FileAccessMemory::get_len() const { ERR_FAIL_COND_V(!data, 0); return length; } @@ -136,13 +136,12 @@ uint8_t FileAccessMemory::get_8() const { return ret; } -int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const { +uint64_t FileAccessMemory::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - ERR_FAIL_COND_V(p_length < 0, -1); ERR_FAIL_COND_V(!data, -1); - int left = length - pos; - int read = MIN(p_length, left); + uint64_t left = length - pos; + uint64_t read = MIN(p_length, left); if (read < p_length) { WARN_PRINT("Reading less data than requested"); @@ -168,9 +167,9 @@ void FileAccessMemory::store_8(uint8_t p_byte) { data[pos++] = p_byte; } -void FileAccessMemory::store_buffer(const uint8_t *p_src, int p_length) { - int left = length - pos; - int write = MIN(p_length, left); +void FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) { + uint64_t left = length - pos; + uint64_t write = MIN(p_length, left); if (write < p_length) { WARN_PRINT("Writing less data than requested"); } diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h index 0e3b0ad7b1..cc589dc259 100644 --- a/core/io/file_access_memory.h +++ b/core/io/file_access_memory.h @@ -35,8 +35,8 @@ class FileAccessMemory : public FileAccess { uint8_t *data = nullptr; - int length = 0; - mutable int pos = 0; + uint64_t length = 0; + mutable uint64_t pos = 0; static FileAccess *create(); @@ -44,27 +44,27 @@ public: static void register_file(String p_name, Vector<uint8_t> p_data); static void cleanup(); - virtual Error open_custom(const uint8_t *p_data, int p_len); ///< open a file + virtual Error open_custom(const uint8_t *p_data, uint64_t p_len); ///< open a file virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open - virtual void seek(size_t p_position); ///< seek to a given position + virtual void seek(uint64_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position); ///< seek from the end of file - virtual size_t get_position() const; ///< get position in the file - virtual size_t get_len() const; ///< get size of the file + virtual uint64_t get_position() const; ///< get position in the file + virtual uint64_t get_len() const; ///< get size of the file virtual bool eof_reached() const; ///< reading passed EOF virtual uint8_t get_8() const; ///< get a byte - virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes virtual Error get_error() const; ///< get last error virtual void flush(); virtual void store_8(uint8_t p_byte); ///< store a byte - virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes virtual bool file_exists(const String &p_name); ///< return true if a file exists diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index 4cc73bcd22..dedd5523ed 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -126,7 +126,7 @@ void FileAccessNetworkClient::_thread_func() { if (status != OK) { fa->_respond(0, Error(status)); } else { - uint64_t len = get_64(); + int64_t len = get_64(); fa->_respond(len, Error(status)); } @@ -135,7 +135,7 @@ void FileAccessNetworkClient::_thread_func() { } break; case FileAccessNetwork::RESPONSE_DATA: { int64_t offset = get_64(); - uint32_t len = get_32(); + int32_t len = get_32(); Vector<uint8_t> block; block.resize(len); @@ -219,13 +219,13 @@ FileAccessNetworkClient::~FileAccessNetworkClient() { thread.wait_to_finish(); } -void FileAccessNetwork::_set_block(int p_offset, const Vector<uint8_t> &p_block) { - int page = p_offset / page_size; +void FileAccessNetwork::_set_block(uint64_t p_offset, const Vector<uint8_t> &p_block) { + int32_t page = p_offset / page_size; ERR_FAIL_INDEX(page, pages.size()); if (page < pages.size() - 1) { ERR_FAIL_COND(p_block.size() != page_size); } else { - ERR_FAIL_COND((p_block.size() != (int)(total_size % page_size))); + ERR_FAIL_COND((uint64_t)p_block.size() != total_size % page_size); } { @@ -240,7 +240,7 @@ void FileAccessNetwork::_set_block(int p_offset, const Vector<uint8_t> &p_block) } } -void FileAccessNetwork::_respond(size_t p_len, Error p_status) { +void FileAccessNetwork::_respond(uint64_t p_len, Error p_status) { DEBUG_PRINT("GOT RESPONSE - len: " + itos(p_len) + " status: " + itos(p_status)); response = p_status; if (response != OK) { @@ -248,7 +248,7 @@ void FileAccessNetwork::_respond(size_t p_len, Error p_status) { } opened = true; total_size = p_len; - int pc = ((total_size - 1) / page_size) + 1; + int32_t pc = ((total_size - 1) / page_size) + 1; pages.resize(pc); } @@ -307,8 +307,9 @@ bool FileAccessNetwork::is_open() const { return opened; } -void FileAccessNetwork::seek(size_t p_position) { +void FileAccessNetwork::seek(uint64_t p_position) { ERR_FAIL_COND_MSG(!opened, "File must be opened before use."); + eof_flag = p_position > total_size; if (p_position >= total_size) { @@ -322,12 +323,12 @@ void FileAccessNetwork::seek_end(int64_t p_position) { seek(total_size + p_position); } -size_t FileAccessNetwork::get_position() const { +uint64_t FileAccessNetwork::get_position() const { ERR_FAIL_COND_V_MSG(!opened, 0, "File must be opened before use."); return pos; } -size_t FileAccessNetwork::get_len() const { +uint64_t FileAccessNetwork::get_len() const { ERR_FAIL_COND_V_MSG(!opened, 0, "File must be opened before use."); return total_size; } @@ -343,7 +344,7 @@ uint8_t FileAccessNetwork::get_8() const { return v; } -void FileAccessNetwork::_queue_page(int p_page) const { +void FileAccessNetwork::_queue_page(int32_t p_page) const { if (p_page >= pages.size()) { return; } @@ -354,7 +355,7 @@ void FileAccessNetwork::_queue_page(int p_page) const { FileAccessNetworkClient::BlockRequest br; br.id = id; - br.offset = size_t(p_page) * page_size; + br.offset = (uint64_t)p_page * page_size; br.size = page_size; nc->block_requests.push_back(br); pages.write[p_page].queued = true; @@ -365,11 +366,9 @@ void FileAccessNetwork::_queue_page(int p_page) const { } } -int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { +uint64_t FileAccessNetwork::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - ERR_FAIL_COND_V(p_length < 0, -1); - //bool eof=false; if (pos + p_length > total_size) { eof_flag = true; } @@ -377,18 +376,16 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { p_length = total_size - pos; } - //FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; - uint8_t *buff = last_page_buff; - for (int i = 0; i < p_length; i++) { - int page = pos / page_size; + for (uint64_t i = 0; i < p_length; i++) { + int32_t page = pos / page_size; if (page != last_page) { buffer_mutex.lock(); if (pages[page].buffer.is_empty()) { waiting_on_page = page; - for (int j = 0; j < read_ahead; j++) { + for (int32_t j = 0; j < read_ahead; j++) { _queue_page(page + j); } buffer_mutex.unlock(); @@ -396,10 +393,9 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { page_sem.wait(); DEBUG_PRINT("done"); } else { - for (int j = 0; j < read_ahead; j++) { + for (int32_t j = 0; j < read_ahead; j++) { _queue_page(page + j); } - //queue pages buffer_mutex.unlock(); } diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index 1f5de3e5dd..4810cca195 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -40,9 +40,9 @@ class FileAccessNetwork; class FileAccessNetworkClient { struct BlockRequest { - int id; + int32_t id; uint64_t offset; - int size; + int32_t size; }; List<BlockRequest> block_requests; @@ -54,17 +54,17 @@ class FileAccessNetworkClient { Mutex blockrequest_mutex; Map<int, FileAccessNetwork *> accesses; Ref<StreamPeerTCP> client; - int last_id = 0; - int lockcount = 0; + int32_t last_id = 0; + int32_t lockcount = 0; Vector<uint8_t> block; void _thread_func(); static void _thread_func(void *s); - void put_32(int p_32); + void put_32(int32_t p_32); void put_64(int64_t p_64); - int get_32(); + int32_t get_32(); int64_t get_64(); void lock_mutex(); void unlock_mutex(); @@ -86,15 +86,15 @@ class FileAccessNetwork : public FileAccess { Semaphore page_sem; Mutex buffer_mutex; bool opened = false; - size_t total_size; - mutable size_t pos = 0; - int id; + uint64_t total_size; + mutable uint64_t pos = 0; + int32_t id; mutable bool eof_flag = false; - mutable int last_page = -1; + mutable int32_t last_page = -1; mutable uint8_t *last_page_buff = nullptr; - int page_size; - int read_ahead; + int32_t page_size; + int32_t read_ahead; mutable int waiting_on_page = -1; @@ -110,9 +110,9 @@ class FileAccessNetwork : public FileAccess { uint64_t exists_modtime; friend class FileAccessNetworkClient; - void _queue_page(int p_page) const; - void _respond(size_t p_len, Error p_status); - void _set_block(int p_offset, const Vector<uint8_t> &p_block); + void _queue_page(int32_t p_page) const; + void _respond(uint64_t p_len, Error p_status); + void _set_block(uint64_t p_offset, const Vector<uint8_t> &p_block); public: enum Command { @@ -134,15 +134,15 @@ public: virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open - virtual void seek(size_t p_position); ///< seek to a given position + virtual void seek(uint64_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual size_t get_position() const; ///< get position in the file - virtual size_t get_len() const; ///< get size of the file + virtual uint64_t get_position() const; ///< get position in the file + virtual uint64_t get_len() const; ///< get size of the file virtual bool eof_reached() const; ///< reading passed EOF virtual uint8_t get_8() const; ///< get a byte - virtual int get_buffer(uint8_t *p_dst, int p_length) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; virtual Error get_error() const; ///< get last error diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index e24dc40166..3e1c51b733 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -36,7 +36,7 @@ #include <stdio.h> -Error PackedData::add_pack(const String &p_path, bool p_replace_files, size_t p_offset) { +Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) { for (int i = 0; i < sources.size(); i++) { if (sources[i]->try_open_pack(p_path, p_replace_files, p_offset)) { return OK; @@ -46,17 +46,16 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, size_t p_ return ERR_FILE_UNRECOGNIZED; } -void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted) { - PathMD5 pmd5(path.md5_buffer()); - //printf("adding path %s, %lli, %lli\n", path.utf8().get_data(), pmd5.a, pmd5.b); +void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted) { + PathMD5 pmd5(p_path.md5_buffer()); bool exists = files.has(pmd5); PackedFile pf; pf.encrypted = p_encrypted; - pf.pack = pkg_path; - pf.offset = ofs; - pf.size = size; + pf.pack = p_pkg_path; + pf.offset = p_ofs; + pf.size = p_size; for (int i = 0; i < 16; i++) { pf.md5[i] = p_md5[i]; } @@ -68,7 +67,7 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o if (!exists) { //search for dir - String p = path.replace_first("res://", ""); + String p = p_path.replace_first("res://", ""); PackedDir *cd = root; if (p.find("/") != -1) { //in a subdir @@ -87,7 +86,7 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o } } } - String filename = path.get_file(); + String filename = p_path.get_file(); // Don't add as a file if the path points to a directory if (!filename.is_empty()) { cd->files.insert(filename); @@ -126,7 +125,7 @@ PackedData::~PackedData() { ////////////////////////////////////////////////////////////////// -bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset) { +bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { return false; @@ -261,7 +260,7 @@ bool FileAccessPack::is_open() const { return f->is_open(); } -void FileAccessPack::seek(size_t p_position) { +void FileAccessPack::seek(uint64_t p_position) { if (p_position > pf.size) { eof = true; } else { @@ -276,11 +275,11 @@ void FileAccessPack::seek_end(int64_t p_position) { seek(pf.size + p_position); } -size_t FileAccessPack::get_position() const { +uint64_t FileAccessPack::get_position() const { return pos; } -size_t FileAccessPack::get_len() const { +uint64_t FileAccessPack::get_len() const { return pf.size; } @@ -298,18 +297,17 @@ uint8_t FileAccessPack::get_8() const { return f->get_8(); } -int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const { +uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - ERR_FAIL_COND_V(p_length < 0, -1); if (eof) { return 0; } - uint64_t to_read = p_length; + int64_t to_read = p_length; if (to_read + pos > pf.size) { eof = true; - to_read = int64_t(pf.size) - int64_t(pos); + to_read = (int64_t)pf.size - (int64_t)pos; } pos += p_length; @@ -342,7 +340,7 @@ void FileAccessPack::store_8(uint8_t p_dest) { ERR_FAIL(); } -void FileAccessPack::store_buffer(const uint8_t *p_src, int p_length) { +void FileAccessPack::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL(); } @@ -549,7 +547,7 @@ Error DirAccessPack::remove(String p_name) { return ERR_UNAVAILABLE; } -size_t DirAccessPack::get_space_left() { +uint64_t DirAccessPack::get_space_left() { return 0; } diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 955108f455..e47c9ea543 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -112,13 +112,13 @@ private: public: void add_pack_source(PackSource *p_source); - void add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource + void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource void set_disabled(bool p_disabled) { disabled = p_disabled; } _FORCE_INLINE_ bool is_disabled() const { return disabled; } static PackedData *get_singleton() { return singleton; } - Error add_pack(const String &p_path, bool p_replace_files, size_t p_offset); + Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset); _FORCE_INLINE_ FileAccess *try_open_path(const String &p_path); _FORCE_INLINE_ bool has_path(const String &p_path); @@ -132,21 +132,21 @@ public: class PackSource { public: - virtual bool try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset) = 0; + virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) = 0; virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0; virtual ~PackSource() {} }; class PackedSourcePCK : public PackSource { public: - virtual bool try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset); + virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset); virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file); }; class FileAccessPack : public FileAccess { PackedData::PackedFile pf; - mutable size_t pos; + mutable uint64_t pos; mutable bool eof; uint64_t off; @@ -160,16 +160,16 @@ public: virtual void close(); virtual bool is_open() const; - virtual void seek(size_t p_position); + virtual void seek(uint64_t p_position); virtual void seek_end(int64_t p_position = 0); - virtual size_t get_position() const; - virtual size_t get_len() const; + virtual uint64_t get_position() const; + virtual uint64_t get_len() const; virtual bool eof_reached() const; virtual uint8_t get_8() const; - virtual int get_buffer(uint8_t *p_dst, int p_length) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; virtual void set_endian_swap(bool p_swap); @@ -178,7 +178,7 @@ public: virtual void flush(); virtual void store_8(uint8_t p_dest); - virtual void store_buffer(const uint8_t *p_src, int p_length); + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); virtual bool file_exists(const String &p_name); @@ -243,7 +243,7 @@ public: virtual Error rename(String p_from, String p_to); virtual Error remove(String p_name); - size_t get_space_left(); + uint64_t get_space_left(); virtual String get_filesystem_type() const; diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index dbedb5254f..304e24ee90 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -67,7 +67,7 @@ static long godot_tell(voidpf opaque, voidpf stream) { static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) { FileAccess *f = (FileAccess *)stream; - int pos = offset; + uint64_t pos = offset; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR: pos = f->get_position() + offset; @@ -144,8 +144,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const { return pkg; } -bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset = 0) { - //printf("opening zip pack %s, %i, %i\n", p_name.utf8().get_data(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz")); +bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset = 0) { // load with offset feature only supported for PCK files ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Invalid PCK data. Note that loading files with a non-zero offset isn't supported with ZIP archives."); @@ -265,8 +264,9 @@ bool FileAccessZip::is_open() const { return zfile != nullptr; } -void FileAccessZip::seek(size_t p_position) { +void FileAccessZip::seek(uint64_t p_position) { ERR_FAIL_COND(!zfile); + unzSeekCurrentFile(zfile, p_position); } @@ -275,12 +275,12 @@ void FileAccessZip::seek_end(int64_t p_position) { unzSeekCurrentFile(zfile, get_len() + p_position); } -size_t FileAccessZip::get_position() const { +uint64_t FileAccessZip::get_position() const { ERR_FAIL_COND_V(!zfile, 0); return unztell(zfile); } -size_t FileAccessZip::get_len() const { +uint64_t FileAccessZip::get_len() const { ERR_FAIL_COND_V(!zfile, 0); return file_info.uncompressed_size; } @@ -297,17 +297,17 @@ uint8_t FileAccessZip::get_8() const { return ret; } -int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const { +uint64_t FileAccessZip::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - ERR_FAIL_COND_V(p_length < 0, -1); ERR_FAIL_COND_V(!zfile, -1); + at_eof = unzeof(zfile); if (at_eof) { return 0; } - int read = unzReadCurrentFile(zfile, p_dst, p_length); + int64_t read = unzReadCurrentFile(zfile, p_dst, p_length); ERR_FAIL_COND_V(read < 0, read); - if (read < p_length) { + if ((uint64_t)read < p_length) { at_eof = true; } return read; diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index 8559f871ce..91bdaafb68 100644 --- a/core/io/file_access_zip.h +++ b/core/io/file_access_zip.h @@ -67,7 +67,7 @@ public: bool file_exists(String p_name) const; - virtual bool try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset); + virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset); FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file); static ZipArchive *get_singleton(); @@ -87,20 +87,21 @@ public: virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open - virtual void seek(size_t p_position); ///< seek to a given position + virtual void seek(uint64_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual size_t get_position() const; ///< get position in the file - virtual size_t get_len() const; ///< get size of the file + virtual uint64_t get_position() const; ///< get position in the file + virtual uint64_t get_len() const; ///< get size of the file virtual bool eof_reached() const; ///< reading passed EOF virtual uint8_t get_8() const; ///< get a byte - virtual int get_buffer(uint8_t *p_dst, int p_length) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; virtual Error get_error() const; ///< get last error virtual void flush(); virtual void store_8(uint8_t p_dest); ///< store a byte + virtual bool file_exists(const String &p_name); ///< return true if a file exists virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 8414ee7c0c..fda4083804 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -843,7 +843,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p if (property_id == UINT16_MAX && p_from->get_script_instance()) { property_id = p_from->get_script_instance()->get_rset_property_id(p_name); } - ERR_FAIL_COND_MSG(property_id == UINT16_MAX, "Unable to take the `property_id` for the property:" + p_name + ". this can happen only if this property is not marked as `remote`."); + ERR_FAIL_COND_MSG(property_id == UINT16_MAX, "Unable to take the `property_id` for the property:" + p_name + ". This can only happen if this property is not marked as `remote`."); if (property_id <= UINT8_MAX) { // The ID fits in 1 byte diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index a0697ca18b..4fe22e57d8 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -236,7 +236,7 @@ Error PCKPacker::flush(bool p_verbose) { } while (to_write > 0) { - int read = src->get_buffer(buf, MIN(to_write, buf_max)); + uint64_t read = src->get_buffer(buf, MIN(to_write, buf_max)); ftmp->store_buffer(buf, read); to_write -= read; } diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index c4eb2a20bb..50c9b2371a 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1157,8 +1157,8 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons save_ustring(fw, get_ustring(f)); //type - size_t md_ofs = f->get_position(); - size_t importmd_ofs = f->get_64(); + uint64_t md_ofs = f->get_position(); + uint64_t importmd_ofs = f->get_64(); fw->store_64(0); //metadata offset for (int i = 0; i < 14; i++) { diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 040e55b9db..b942c30086 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -867,7 +867,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem continue; } - String l = res_remaps[i].right(split + 1).strip_edges(); + String l = res_remaps[i].substr(split + 1).strip_edges(); if (l == locale) { // Exact match. new_path = res_remaps[i].left(split); break; diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index a1f8e79adc..f3ce2319e3 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -75,7 +75,7 @@ void XMLParser::_parse_closing_xml_element() { ++P; const char *pBeginClose = P; - while (*P != '>') { + while (*P && *P != '>') { ++P; } @@ -83,7 +83,10 @@ void XMLParser::_parse_closing_xml_element() { #ifdef DEBUG_XML print_line("XML CLOSE: " + node_name); #endif - ++P; + + if (*P) { + ++P; + } } void XMLParser::_ignore_definition() { @@ -91,11 +94,14 @@ void XMLParser::_ignore_definition() { char *F = P; // move until end marked with '>' reached - while (*P != '>') { + while (*P && *P != '>') { ++P; } node_name.parse_utf8(F, P - F); - ++P; + + if (*P) { + ++P; + } } bool XMLParser::_parse_cdata() { @@ -113,6 +119,7 @@ bool XMLParser::_parse_cdata() { } if (!*P) { + node_name = ""; return true; } @@ -131,10 +138,9 @@ bool XMLParser::_parse_cdata() { } if (cDataEnd) { - node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin)); - } else { - node_name = ""; + cDataEnd = P; } + node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin)); #ifdef DEBUG_XML print_line("XML CDATA: " + node_name); #endif @@ -146,24 +152,45 @@ void XMLParser::_parse_comment() { node_type = NODE_COMMENT; P += 1; - char *pCommentBegin = P; + char *pEndOfInput = data + length; + char *pCommentBegin; + char *pCommentEnd; - int count = 1; - - // move until end of comment reached - while (count) { - if (*P == '>') { - --count; - } else if (*P == '<') { - ++count; + if (P + 1 < pEndOfInput && P[0] == '-' && P[1] == '-') { + // Comment, use '-->' as end. + pCommentBegin = P + 2; + for (pCommentEnd = pCommentBegin; pCommentEnd + 2 < pEndOfInput; pCommentEnd++) { + if (pCommentEnd[0] == '-' && pCommentEnd[1] == '-' && pCommentEnd[2] == '>') { + break; + } + } + if (pCommentEnd + 2 < pEndOfInput) { + P = pCommentEnd + 3; + } else { + P = pCommentEnd = pEndOfInput; + } + } else { + // Like document type definition, match angle brackets. + pCommentBegin = P; + + int count = 1; + while (*P && count) { + if (*P == '>') { + --count; + } else if (*P == '<') { + ++count; + } + ++P; } - ++P; + if (count) { + pCommentEnd = P; + } else { + pCommentEnd = P - 1; + } } - P -= 3; - node_name = String::utf8(pCommentBegin + 2, (int)(P - pCommentBegin - 2)); - P += 3; + node_name = String::utf8(pCommentBegin, (int)(pCommentEnd - pCommentBegin)); #ifdef DEBUG_XML print_line("XML COMMENT: " + node_name); #endif @@ -178,14 +205,14 @@ void XMLParser::_parse_opening_xml_element() { const char *startName = P; // find end of element - while (*P != '>' && !_is_white_space(*P)) { + while (*P && *P != '>' && !_is_white_space(*P)) { ++P; } const char *endName = P; // find attributes - while (*P != '>') { + while (*P && *P != '>') { if (_is_white_space(*P)) { ++P; } else { @@ -195,10 +222,14 @@ void XMLParser::_parse_opening_xml_element() { // read the attribute names const char *attributeNameBegin = P; - while (!_is_white_space(*P) && *P != '=') { + while (*P && !_is_white_space(*P) && *P != '=') { ++P; } + if (!*P) { + break; + } + const char *attributeNameEnd = P; ++P; @@ -209,7 +240,7 @@ void XMLParser::_parse_opening_xml_element() { } if (!*P) { // malformatted xml file - return; + break; } const char attributeQuoteChar = *P; @@ -221,12 +252,10 @@ void XMLParser::_parse_opening_xml_element() { ++P; } - if (!*P) { // malformatted xml file - return; - } - const char *attributeValueEnd = P; - ++P; + if (*P) { + ++P; + } Attribute attr; attr.name = String::utf8(attributeNameBegin, @@ -258,7 +287,9 @@ void XMLParser::_parse_opening_xml_element() { print_line("XML OPEN: " + node_name); #endif - ++P; + if (*P) { + ++P; + } } void XMLParser::_parse_current_node() { @@ -270,10 +301,6 @@ void XMLParser::_parse_current_node() { ++P; } - if (!*P) { - return; - } - if (P - start > 0) { // we found some text, store it if (_set_text(start, P)) { @@ -281,6 +308,10 @@ void XMLParser::_parse_current_node() { } } + if (!*P) { + return; + } + ++P; // based on current token, parse and report next element diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp index fe46868dd0..e0e491dc85 100644 --- a/core/io/zip_io.cpp +++ b/core/io/zip_io.cpp @@ -68,7 +68,7 @@ long zipio_tell(voidpf opaque, voidpf stream) { long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) { FileAccess *f = *(FileAccess **)opaque; - int pos = offset; + uint64_t pos = offset; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR: pos = f->get_position() + offset; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 50299902eb..037378b9d7 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -109,7 +109,7 @@ bool Basis::is_diagonal() const { } bool Basis::is_rotation() const { - return Math::is_equal_approx(determinant(), 1, UNIT_EPSILON) && is_orthogonal(); + return Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON) && is_orthogonal(); } #ifdef MATH_CHECKS diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index c0d7649b65..3389407e72 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -275,8 +275,8 @@ public: static _ALWAYS_INLINE_ double db2linear(double p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); } static _ALWAYS_INLINE_ float db2linear(float p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); } - static _ALWAYS_INLINE_ double round(double p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); } - static _ALWAYS_INLINE_ float round(float p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); } + static _ALWAYS_INLINE_ double round(double p_val) { return ::round(p_val); } + static _ALWAYS_INLINE_ float round(float p_val) { return ::roundf(p_val); } static _ALWAYS_INLINE_ int64_t wrapi(int64_t value, int64_t min, int64_t max) { int64_t range = max - min; @@ -311,20 +311,20 @@ public: static float random(float from, float to); static int random(int from, int to); - static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) { + static _ALWAYS_INLINE_ bool is_equal_approx(float a, float b) { // Check for exact equality first, required to handle "infinity" values. if (a == b) { return true; } // Then check for approximate equality. - real_t tolerance = CMP_EPSILON * abs(a); + float tolerance = CMP_EPSILON * abs(a); if (tolerance < CMP_EPSILON) { tolerance = CMP_EPSILON; } return abs(a - b) < tolerance; } - static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b, real_t tolerance) { + static _ALWAYS_INLINE_ bool is_equal_approx(float a, float b, float tolerance) { // Check for exact equality first, required to handle "infinity" values. if (a == b) { return true; @@ -333,7 +333,33 @@ public: return abs(a - b) < tolerance; } - static _ALWAYS_INLINE_ bool is_zero_approx(real_t s) { + static _ALWAYS_INLINE_ bool is_zero_approx(float s) { + return abs(s) < CMP_EPSILON; + } + + static _ALWAYS_INLINE_ bool is_equal_approx(double a, double b) { + // Check for exact equality first, required to handle "infinity" values. + if (a == b) { + return true; + } + // Then check for approximate equality. + double tolerance = CMP_EPSILON * abs(a); + if (tolerance < CMP_EPSILON) { + tolerance = CMP_EPSILON; + } + return abs(a - b) < tolerance; + } + + static _ALWAYS_INLINE_ bool is_equal_approx(double a, double b, double tolerance) { + // Check for exact equality first, required to handle "infinity" values. + if (a == b) { + return true; + } + // Then check for approximate equality. + return abs(a - b) < tolerance; + } + + static _ALWAYS_INLINE_ bool is_zero_approx(double s) { return abs(s) < CMP_EPSILON; } @@ -358,28 +384,10 @@ public: return u.d; } - //this function should be as fast as possible and rounding mode should not matter + // This function should be as fast as possible and rounding mode should not matter. static _ALWAYS_INLINE_ int fast_ftoi(float a) { - static int b; - -#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603) || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // windows 8 phone? - b = (int)((a > 0.0) ? (a + 0.5) : (a - 0.5)); - -#elif defined(_MSC_VER) && _MSC_VER < 1800 - __asm fld a __asm fistp b - /*#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) - // use AT&T inline assembly style, document that - // we use memory as output (=m) and input (m) - __asm__ __volatile__ ( - "flds %1 \n\t" - "fistpl %0 \n\t" - : "=m" (b) - : "m" (a));*/ - -#else - b = lrintf(a); //assuming everything but msvc 2012 or earlier has lrint -#endif - return b; + // Assuming every supported compiler has `lrint()`. + return lrintf(a); } static _ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h) { diff --git a/core/math/quat.cpp b/core/math/quat.cpp index 6f13e04027..3982a0b993 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -87,7 +87,7 @@ Quat Quat::normalized() const { } bool Quat::is_normalized() const { - return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); //use less epsilon + return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); //use less epsilon } Quat Quat::inverse() const { diff --git a/core/math/quat.h b/core/math/quat.h index 9db914fe52..d9b130c050 100644 --- a/core/math/quat.h +++ b/core/math/quat.h @@ -28,14 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -// Circular dependency between Vector3 and Basis :/ -#include "core/math/vector3.h" - #ifndef QUAT_H #define QUAT_H #include "core/math/math_defs.h" #include "core/math/math_funcs.h" +#include "core/math/vector3.h" #include "core/string/ustring.h" class Quat { diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 5129ed336e..46a08b53ab 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -59,7 +59,7 @@ Vector2 Vector2::normalized() const { bool Vector2::is_normalized() const { // use length_squared() instead of length() to avoid sqrt(), makes it more stringent. - return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); + return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); } real_t Vector2::distance_to(const Vector2 &p_vector2) const { diff --git a/core/math/vector3.h b/core/math/vector3.h index b47c3cc916..adfc52566f 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -423,7 +423,7 @@ Vector3 Vector3::normalized() const { bool Vector3::is_normalized() const { // use length_squared() instead of length() to avoid sqrt(), makes it more stringent. - return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); + return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); } Vector3 Vector3::inverse() const { diff --git a/core/object/object.cpp b/core/object/object.cpp index 413f917518..a8b2c4a939 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -1345,7 +1345,7 @@ void Object::_disconnect(const StringName &p_signal, const Callable &p_callable, if (!s) { bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal) || (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)); - ERR_FAIL_COND_MSG(signal_is_valid, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. signal: '" + p_signal + "', callable: '" + p_callable + "'."); + ERR_FAIL_COND_MSG(signal_is_valid, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. Signal: '" + p_signal + "', callable: '" + p_callable + "'."); } ERR_FAIL_COND_MSG(!s, vformat("Disconnecting nonexistent signal '%s' in %s.", p_signal, to_string())); diff --git a/core/os/dir_access.h b/core/os/dir_access.h index 7f0bcd372d..ec738d30d5 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -87,7 +87,7 @@ public: virtual bool is_readable(String p_dir) { return true; }; virtual bool is_writable(String p_dir) { return true; }; static bool exists(String p_dir); - virtual size_t get_space_left() = 0; + virtual uint64_t get_space_left() = 0; Error copy_dir(String p_from, String p_to, int p_chmod_flags = -1); virtual Error copy(String p_from, String p_to, int p_chmod_flags = -1); diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index ad234c2d49..d00d0ac5bb 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -367,10 +367,10 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const { return strings; } -int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const { +uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - ERR_FAIL_COND_V(p_length < 0, -1); - int i = 0; + + uint64_t i = 0; for (i = 0; i < p_length && !eof_reached(); i++) { p_dst[i] = get_8(); } @@ -380,11 +380,11 @@ int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const { String FileAccess::get_as_utf8_string() const { Vector<uint8_t> sourcef; - int len = get_len(); + uint64_t len = get_len(); sourcef.resize(len + 1); uint8_t *w = sourcef.ptrw(); - int r = get_buffer(w, len); + uint64_t r = get_buffer(w, len); ERR_FAIL_COND_V(r != len, String()); w[len] = 0; @@ -550,8 +550,8 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_ store_line(line); } -void FileAccess::store_buffer(const uint8_t *p_src, int p_length) { - for (int i = 0; i < p_length; i++) { +void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) { + for (uint64_t i = 0; i < p_length; i++) { store_8(p_src[i]); } } @@ -601,7 +601,7 @@ String FileAccess::get_md5(const String &p_file) { unsigned char step[32768]; while (true) { - int br = f->get_buffer(step, 32768); + uint64_t br = f->get_buffer(step, 32768); if (br > 0) { ctx.update(step, br); } @@ -629,7 +629,7 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) { unsigned char step[32768]; while (true) { - int br = f->get_buffer(step, 32768); + uint64_t br = f->get_buffer(step, 32768); if (br > 0) { ctx.update(step, br); } @@ -658,7 +658,7 @@ String FileAccess::get_sha256(const String &p_file) { unsigned char step[32768]; while (true) { - int br = f->get_buffer(step, 32768); + uint64_t br = f->get_buffer(step, 32768); if (br > 0) { ctx.update(step, br); } diff --git a/core/os/file_access.h b/core/os/file_access.h index 1c78204c1d..f9749c0fd1 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -93,10 +93,10 @@ public: virtual String get_path() const { return ""; } /// returns the path for the current open file virtual String get_path_absolute() const { return ""; } /// returns the absolute path for the current open file - virtual void seek(size_t p_position) = 0; ///< seek to a given position - virtual void seek_end(int64_t p_position = 0) = 0; ///< seek from the end of file - virtual size_t get_position() const = 0; ///< get position in the file - virtual size_t get_len() const = 0; ///< get size of the file + virtual void seek(uint64_t p_position) = 0; ///< seek to a given position + virtual void seek_end(int64_t p_position = 0) = 0; ///< seek from the end of file with negative offset + virtual uint64_t get_position() const = 0; ///< get position in the file + virtual uint64_t get_len() const = 0; ///< get size of the file virtual bool eof_reached() const = 0; ///< reading passed EOF @@ -109,7 +109,7 @@ public: virtual double get_double() const; virtual real_t get_real() const; - virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes virtual String get_line() const; virtual String get_token() const; virtual Vector<String> get_csv_line(const String &p_delim = ",") const; @@ -142,7 +142,7 @@ public: virtual void store_pascal_string(const String &p_string); virtual String get_pascal_string(); - virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes virtual bool file_exists(const String &p_name) = 0; ///< return true if a file exists diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index 4b2cafd8fe..4c5f0b5220 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -60,7 +60,7 @@ static const _KeyCodeText _keycodes[] = { {KEY_PAGEUP ,"PageUp"}, {KEY_PAGEDOWN ,"PageDown"}, {KEY_SHIFT ,"Shift"}, - {KEY_CONTROL ,"Control"}, + {KEY_CTRL ,"Ctrl"}, #ifdef OSX_ENABLED {KEY_META ,"Command"}, #else @@ -314,7 +314,7 @@ bool keycode_has_unicode(uint32_t p_keycode) { case KEY_PAGEUP: case KEY_PAGEDOWN: case KEY_SHIFT: - case KEY_CONTROL: + case KEY_CTRL: case KEY_META: case KEY_ALT: case KEY_CAPSLOCK: @@ -401,7 +401,7 @@ String keycode_get_string(uint32_t p_code) { codestr += "+"; } if (p_code & KEY_MASK_CTRL) { - codestr += find_keycode_name(KEY_CONTROL); + codestr += find_keycode_name(KEY_CTRL); codestr += "+"; } if (p_code & KEY_MASK_META) { diff --git a/core/os/keyboard.h b/core/os/keyboard.h index f6fe5fc070..33f9213c4e 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -68,7 +68,7 @@ enum Key { KEY_PAGEUP = SPKEY | 0x13, KEY_PAGEDOWN = SPKEY | 0x14, KEY_SHIFT = SPKEY | 0x15, - KEY_CONTROL = SPKEY | 0x16, + KEY_CTRL = SPKEY | 0x16, KEY_META = SPKEY | 0x17, KEY_ALT = SPKEY | 0x18, KEY_CAPSLOCK = SPKEY | 0x19, diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index bdb66526a4..3c1afc7f2c 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -3382,14 +3382,14 @@ String String::format(const Variant &values, String placeholder) const { if (value_arr.size() == 2) { Variant v_key = value_arr[0]; String key = v_key; - if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") { + if (key.left(1) == "\"" && key.right(1) == "\"") { key = key.substr(1, key.length() - 2); } Variant v_val = value_arr[1]; String val = v_val; - if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") { + if (val.left(1) == "\"" && val.right(1) == "\"") { val = val.substr(1, val.length() - 2); } @@ -3401,7 +3401,7 @@ String String::format(const Variant &values, String placeholder) const { Variant v_val = values_arr[i]; String val = v_val; - if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") { + if (val.left(1) == "\"" && val.right(1) == "\"") { val = val.substr(1, val.length() - 2); } @@ -3421,11 +3421,11 @@ String String::format(const Variant &values, String placeholder) const { String key = E->get(); String val = d[E->get()]; - if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") { + if (key.left(1) == "\"" && key.right(1) == "\"") { key = key.substr(1, key.length() - 2); } - if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") { + if (val.left(1) == "\"" && val.right(1) == "\"") { val = val.substr(1, val.length() - 2); } @@ -3529,6 +3529,10 @@ String String::repeat(int p_count) const { } String String::left(int p_pos) const { + if (p_pos < 0) { + p_pos = length() + p_pos; + } + if (p_pos <= 0) { return ""; } @@ -3541,15 +3545,19 @@ String String::left(int p_pos) const { } String String::right(int p_pos) const { - if (p_pos >= length()) { - return ""; + if (p_pos < 0) { + p_pos = length() + p_pos; } if (p_pos <= 0) { + return ""; + } + + if (p_pos >= length()) { return *this; } - return substr(p_pos, (length() - p_pos)); + return substr(length() - p_pos); } char32_t String::unicode_at(int p_idx) const { diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h index 7d33d85cd6..fb791f8c0c 100644 --- a/core/variant/variant_internal.h +++ b/core/variant/variant_internal.h @@ -43,18 +43,21 @@ public: v->type = p_type; switch (p_type) { - case Variant::AABB: - init_aabb(v); + case Variant::STRING: + init_string(v); break; case Variant::TRANSFORM2D: init_transform2d(v); break; + case Variant::AABB: + init_aabb(v); + break; + case Variant::BASIS: + init_basis(v); + break; case Variant::TRANSFORM: init_transform(v); break; - case Variant::STRING: - init_string(v); - break; case Variant::STRING_NAME: init_string_name(v); break; @@ -192,6 +195,10 @@ public: v->type = GetTypeInfo<T>::VARIANT_TYPE; } + // Should be in the same order as Variant::Type for consistency. + // Those primitive and vector types don't need an `init_` method: + // Nil, bool, float, Vector2/i, Rect2/i, Vector3/i, Plane, Quat, Color, RID. + // Object is a special case, handled via `object_assign_null`. _FORCE_INLINE_ static void init_string(Variant *v) { memnew_placement(v->_data._mem, String); v->type = Variant::STRING; diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index af66a11fe5..e210fa8808 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1393,7 +1393,7 @@ <constant name="KEY_SHIFT" value="16777237" enum="Key"> Shift key. </constant> - <constant name="KEY_CONTROL" value="16777238" enum="Key"> + <constant name="KEY_CTRL" value="16777238" enum="Key"> Control key. </constant> <constant name="KEY_META" value="16777239" enum="Key"> diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index a1e522d146..f7a116b934 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -60,8 +60,8 @@ <member name="audio_bus_override" type="bool" setter="set_audio_bus_override" getter="is_overriding_audio_bus" default="false"> If [code]true[/code], the area's audio bus overrides the default audio bus. </member> - <member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="98.0"> - The area's gravity intensity (ranges from -1024 to 1024). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction. + <member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="980.0"> + The area's gravity intensity (in pixels per second squared). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction. </member> <member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale" default="0.0"> The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance. @@ -107,7 +107,7 @@ </description> </signal> <signal name="area_shape_entered"> - <argument index="0" name="area_id" type="int"> + <argument index="0" name="area_rid" type="RID"> </argument> <argument index="1" name="area" type="Area2D"> </argument> @@ -124,7 +124,7 @@ </description> </signal> <signal name="area_shape_exited"> - <argument index="0" name="area_id" type="int"> + <argument index="0" name="area_rid" type="RID"> </argument> <argument index="1" name="area" type="Area2D"> </argument> @@ -157,7 +157,7 @@ </description> </signal> <signal name="body_shape_entered"> - <argument index="0" name="body_id" type="int"> + <argument index="0" name="body_rid" type="RID"> </argument> <argument index="1" name="body" type="Node2D"> </argument> @@ -174,7 +174,7 @@ </description> </signal> <signal name="body_shape_exited"> - <argument index="0" name="body_id" type="int"> + <argument index="0" name="body_rid" type="RID"> </argument> <argument index="1" name="body" type="Node2D"> </argument> diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index e69a89a836..108387823b 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -59,7 +59,7 @@ If [code]true[/code], the area's audio bus overrides the default audio bus. </member> <member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="9.8"> - The area's gravity intensity (ranges from -1024 to 1024). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction. + The area's gravity intensity (in meters per second squared). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction. </member> <member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale" default="0.0"> The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance. @@ -117,7 +117,7 @@ </description> </signal> <signal name="area_shape_entered"> - <argument index="0" name="area_id" type="int"> + <argument index="0" name="area_rid" type="RID"> </argument> <argument index="1" name="area" type="Area3D"> </argument> @@ -134,7 +134,7 @@ </description> </signal> <signal name="area_shape_exited"> - <argument index="0" name="area_id" type="int"> + <argument index="0" name="area_rid" type="RID"> </argument> <argument index="1" name="area" type="Area3D"> </argument> @@ -167,7 +167,7 @@ </description> </signal> <signal name="body_shape_entered"> - <argument index="0" name="body_id" type="int"> + <argument index="0" name="body_rid" type="RID"> </argument> <argument index="1" name="body" type="Node3D"> </argument> @@ -184,7 +184,7 @@ </description> </signal> <signal name="body_shape_exited"> - <argument index="0" name="body_id" type="int"> + <argument index="0" name="body_rid" type="RID"> </argument> <argument index="1" name="body" type="Node3D"> </argument> diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 624b51e463..879b61a880 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -333,14 +333,14 @@ [gdscript] # Will evaluate to `true`. if 2 in [2, 4, 6, 8]: - print("Containes!") + print("Contains!") [/gdscript] [csharp] // As there is no "in" keyword in C#, you have to use Contains var array = new Godot.Collections.Array{2, 4, 6, 8}; if (array.Contains(2)) { - GD.Print("Containes!"); + GD.Print("Contains!"); } [/csharp] [/codeblocks] diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml index aa9f99a31e..9e70978db8 100644 --- a/doc/classes/CPUParticles2D.xml +++ b/doc/classes/CPUParticles2D.xml @@ -199,7 +199,7 @@ <member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta" default="true"> If [code]true[/code], results in fractional delta calculation which has a smoother particles display effect. </member> - <member name="gravity" type="Vector2" setter="set_gravity" getter="get_gravity" default="Vector2( 0, 98 )"> + <member name="gravity" type="Vector2" setter="set_gravity" getter="get_gravity" default="Vector2( 0, 980 )"> Gravity applied to every particle. </member> <member name="hue_variation" type="float" setter="set_param" getter="get_param" default="0.0"> diff --git a/doc/classes/CharFXTransform.xml b/doc/classes/CharFXTransform.xml index 850098f741..7b57dc05f8 100644 --- a/doc/classes/CharFXTransform.xml +++ b/doc/classes/CharFXTransform.xml @@ -37,7 +37,7 @@ The position offset the character will be drawn with (in pixels). </member> <member name="outline" type="bool" setter="set_outline" getter="is_outline" default="false"> - If [code]ture[/code], FX transform is called for outline drawing. Setting this property won't affect drawing. + If [code]true[/code], FX transform is called for outline drawing. Setting this property won't affect drawing. </member> <member name="range" type="Vector2i" setter="set_range" getter="get_range" default="Vector2i( 0, 0 )"> Absolute character range in the string, corresponding to the glyph. Setting this property won't affect drawing. diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index c0f918a01f..a9a230b78f 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -462,10 +462,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns a color from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code]. + Returns a color from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code]. [codeblocks] [gdscript] func _ready(): @@ -485,10 +485,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns a constant from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code]. + Returns a constant from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code]. </description> </method> <method name="get_theme_font" qualifiers="const"> @@ -496,10 +496,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns a font from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code]. + Returns a font from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code]. </description> </method> <method name="get_theme_font_size" qualifiers="const"> @@ -507,10 +507,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns a font size from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]type[/code]. + Returns a font size from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code]. </description> </method> <method name="get_theme_icon" qualifiers="const"> @@ -518,10 +518,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns an icon from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code]. + Returns an icon from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code]. </description> </method> <method name="get_theme_stylebox" qualifiers="const"> @@ -529,10 +529,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns a [StyleBox] from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code]. + Returns a [StyleBox] from assigned [Theme] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code]. </description> </method> <method name="get_tooltip" qualifiers="const"> @@ -593,10 +593,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns [code]true[/code] if [Color] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme]. + Returns [code]true[/code] if [Color] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme]. </description> </method> <method name="has_theme_color_override" qualifiers="const"> @@ -613,10 +613,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns [code]true[/code] if constant with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme]. + Returns [code]true[/code] if constant with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme]. </description> </method> <method name="has_theme_constant_override" qualifiers="const"> @@ -633,10 +633,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns [code]true[/code] if font with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme]. + Returns [code]true[/code] if font with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme]. </description> </method> <method name="has_theme_font_override" qualifiers="const"> @@ -653,10 +653,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns [code]true[/code] if font size with given [code]name[/code] and associated with [Control] of given [code]type[/code] exists in assigned [Theme]. + Returns [code]true[/code] if font size with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme]. </description> </method> <method name="has_theme_font_size_override" qualifiers="const"> @@ -673,10 +673,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns [code]true[/code] if icon with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme]. + Returns [code]true[/code] if icon with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme]. </description> </method> <method name="has_theme_icon_override" qualifiers="const"> @@ -693,10 +693,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns [code]true[/code] if [StyleBox] with given [code]name[/code] and associated with [Control] of given [code]node_type[/code] exists in assigned [Theme]. + Returns [code]true[/code] if [StyleBox] with given [code]name[/code] and associated with [Control] of given [code]theme_type[/code] exists in assigned [Theme]. </description> </method> <method name="has_theme_stylebox_override" qualifiers="const"> @@ -1173,7 +1173,12 @@ Tells the parent [Container] nodes how they should resize and place the node on the Y axis. Use one of the [enum SizeFlags] constants to change the flags. See the constants to learn what each does. </member> <member name="theme" type="Theme" setter="set_theme" getter="get_theme"> - Changing this property replaces the current [Theme] resource this node and all its [Control] children use. + The [Theme] resource this node and all its [Control] children use. If a child node has its own [Theme] resource set, theme items are merged with child's definitions having higher priority. + </member> + <member name="theme_custom_type" type="StringName" setter="set_theme_custom_type" getter="get_theme_custom_type" default="@"""> + The type name used by this [Control] to look up its own theme items. By default, the class name of the node is used (e.g. [code]Button[/code] for the [Button] control), as well as the class names of all parent classes (in order of inheritance). Setting this property gives the highest priority to the type of the specified name, then falls back on the class names. + [b]Note:[/b] To look up [Control]'s own items use various [code]get_theme_*[/code] methods without specifying [code]theme_type[/code]. + [b]Note:[/b] Theme items are looked for in the tree order, from branch to root, where each [Control] node is checked for its [member theme] property. The earliest match against any type/class name is returned. The project-level Theme and the default Theme are checked last. </member> </members> <signals> diff --git a/doc/classes/EditorResourcePicker.xml b/doc/classes/EditorResourcePicker.xml new file mode 100644 index 0000000000..30c73daa77 --- /dev/null +++ b/doc/classes/EditorResourcePicker.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="EditorResourcePicker" inherits="HBoxContainer" version="4.0"> + <brief_description> + Godot editor's control for selecting [Resource] type properties. + </brief_description> + <description> + This [Control] node is used in the editor's Inspector dock to allow editing of [Resource] type properties. It provides options for creating, loading, saving and converting resources. Can be used with [EditorInspectorPlugin] to recreate the same behavior. + [b]Note:[/b] This [Control] does not include any editor for the resource, as editing is controlled by the Inspector dock itself or sub-Inspectors. + </description> + <tutorials> + </tutorials> + <methods> + <method name="can_drop_data_fw" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="position" type="Vector2"> + </argument> + <argument index="1" name="data" type="Variant"> + </argument> + <argument index="2" name="from" type="Control"> + </argument> + <description> + </description> + </method> + <method name="drop_data_fw"> + <return type="void"> + </return> + <argument index="0" name="position" type="Vector2"> + </argument> + <argument index="1" name="data" type="Variant"> + </argument> + <argument index="2" name="from" type="Control"> + </argument> + <description> + </description> + </method> + <method name="get_allowed_types" qualifiers="const"> + <return type="PackedStringArray"> + </return> + <description> + Returns a list of all allowed types and subtypes corresponding to the [member base_type]. If the [member base_type] is empty, an empty list is returned. + </description> + </method> + <method name="get_drag_data_fw"> + <return type="Variant"> + </return> + <argument index="0" name="position" type="Vector2"> + </argument> + <argument index="1" name="from" type="Control"> + </argument> + <description> + </description> + </method> + <method name="handle_menu_selected" qualifiers="virtual"> + <return type="void"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + This virtual method can be implemented to handle context menu items not handled by default. See [method set_create_options]. + </description> + </method> + <method name="set_create_options" qualifiers="virtual"> + <return type="void"> + </return> + <argument index="0" name="menu_node" type="Object"> + </argument> + <description> + This virtual method is called when updating the context menu of [EditorResourcePicker]. Implement this method to override the "New ..." items with your own options. [code]menu_node[/code] is a reference to the [PopupMenu] node. + [b]Note:[/b] Implement [method handle_menu_selected] to handle these custom items. + </description> + </method> + <method name="set_toggle_pressed"> + <return type="void"> + </return> + <argument index="0" name="pressed" type="bool"> + </argument> + <description> + Sets the toggle mode state for the main button. Works only if [member toggle_mode] is set to [code]true[/code]. + </description> + </method> + </methods> + <members> + <member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default=""""> + The base type of allowed resource types. Can be a comma-separated list of several options. + </member> + <member name="editable" type="bool" setter="set_editable" getter="is_editable" default="true"> + If [code]true[/code], the value can be selected and edited. + </member> + <member name="edited_resource" type="Resource" setter="set_edited_resource" getter="get_edited_resource"> + The edited resource value. + </member> + <member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode" default="false"> + If [code]true[/code], the main button with the resource preview works in the toggle mode. Use [method set_toggle_pressed] to manually set the state. + </member> + </members> + <signals> + <signal name="resource_changed"> + <argument index="0" name="resource" type="Resource"> + </argument> + <description> + Emitted when the value of the edited resource was changed. + </description> + </signal> + <signal name="resource_selected"> + <argument index="0" name="resource" type="Resource"> + </argument> + <description> + Emitted when the resource value was set and user clicked to edit it. + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/doc/classes/EditorScriptPicker.xml b/doc/classes/EditorScriptPicker.xml new file mode 100644 index 0000000000..8334676d92 --- /dev/null +++ b/doc/classes/EditorScriptPicker.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="EditorScriptPicker" inherits="EditorResourcePicker" version="4.0"> + <brief_description> + Godot editor's control for selecting the [code]script[/code] property of a [Node]. + </brief_description> + <description> + Similar to [EditorResourcePicker] this [Control] node is used in the editor's Inspector dock, but only to edit the [code]script[/code] property of a [Node]. Default options for creating new resources of all possible subtypes are replaced with dedicated buttons that open the "Attach Node Script" dialog. Can be used with [EditorInspectorPlugin] to recreate the same behavior. + [b]Note:[/b] You must set the [member script_owner] for the custom context menu items to work. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <members> + <member name="script_owner" type="Node" setter="set_script_owner" getter="get_script_owner"> + The owner [Node] of the script property that holds the edited resource. + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml index 381f4fae04..f2c5a00640 100644 --- a/doc/classes/EditorSpinSlider.xml +++ b/doc/classes/EditorSpinSlider.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="EditorSpinSlider" inherits="Range" version="4.0"> <brief_description> + Godot editor's control for editing numertic values. </brief_description> <description> + This [Control] node is used in the editor's Inspector dock to allow editing of numeric values. Can be used with [EditorInspectorPlugin] to recreate the same behavior. </description> <tutorials> </tutorials> diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index aae3126c0f..82ba45f11a 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -40,7 +40,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Returns the color of the input connection [code]idx[/code]. + Returns the [Color] of the input connection [code]idx[/code]. </description> </method> <method name="get_connection_input_count"> @@ -74,7 +74,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Returns the color of the output connection [code]idx[/code]. + Returns the [Color] of the output connection [code]idx[/code]. </description> </method> <method name="get_connection_output_count"> @@ -117,7 +117,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Returns the color set to [code]idx[/code] left (input) slot. + Returns the left (input) [Color] of the slot [code]idx[/code]. </description> </method> <method name="get_slot_color_right" qualifiers="const"> @@ -126,7 +126,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Returns the color set to [code]idx[/code] right (output) slot. + Returns the right (output) [Color] of the slot [code]idx[/code]. </description> </method> <method name="get_slot_type_left" qualifiers="const"> @@ -135,7 +135,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Returns the (integer) type of left (input) [code]idx[/code] slot. + Returns the left (input) type of the slot [code]idx[/code]. </description> </method> <method name="get_slot_type_right" qualifiers="const"> @@ -144,7 +144,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Returns the (integer) type of right (output) [code]idx[/code] slot. + Returns the right (output) type of the slot [code]idx[/code]. </description> </method> <method name="is_slot_enabled_left" qualifiers="const"> @@ -153,7 +153,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Returns [code]true[/code] if left (input) slot [code]idx[/code] is enabled, [code]false[/code] otherwise. + Returns [code]true[/code] if left (input) side of the slot [code]idx[/code] is enabled. </description> </method> <method name="is_slot_enabled_right" qualifiers="const"> @@ -162,7 +162,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> - Returns [code]true[/code] if right (output) slot [code]idx[/code] is enabled, [code]false[/code] otherwise. + Returns [code]true[/code] if right (output) side of the slot [code]idx[/code] is enabled. </description> </method> <method name="set_opentype_feature"> @@ -204,6 +204,73 @@ [code]color_left[/code]/[code]right[/code] is the tint of the port's icon on this side. [code]custom_left[/code]/[code]right[/code] is a custom texture for this side's port. [b]Note:[/b] This method only sets properties of the slot. To create the slot, add a [Control]-derived child to the GraphNode. + Individual properties can be set using one of the [code]set_slot_*[/code] methods. You must enable at least one side of the slot to do so. + </description> + </method> + <method name="set_slot_color_left"> + <return type="void"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="color_left" type="Color"> + </argument> + <description> + Sets the [Color] of the left (input) side of the slot [code]idx[/code] to [code]color_left[/code]. + </description> + </method> + <method name="set_slot_color_right"> + <return type="void"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="color_right" type="Color"> + </argument> + <description> + Sets the [Color] of the right (output) side of the slot [code]idx[/code] to [code]color_right[/code]. + </description> + </method> + <method name="set_slot_enabled_left"> + <return type="void"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="enable_left" type="bool"> + </argument> + <description> + Toggles the left (input) side of the slot [code]idx[/code]. If [code]enable_left[/code] is [code]true[/code], a port will appear on the left side and the slot will be able to be connected from this side. + </description> + </method> + <method name="set_slot_enabled_right"> + <return type="void"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="enable_right" type="bool"> + </argument> + <description> + Toggles the right (output) side of the slot [code]idx[/code]. If [code]enable_right[/code] is [code]true[/code], a port will appear on the right side and the slot will be able to be connected from this side. + </description> + </method> + <method name="set_slot_type_left"> + <return type="void"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="type_left" type="int"> + </argument> + <description> + Sets the left (input) type of the slot [code]idx[/code] to [code]type_left[/code]. + </description> + </method> + <method name="set_slot_type_right"> + <return type="void"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="type_right" type="int"> + </argument> + <description> + Sets the right (output) type of the slot [code]idx[/code] to [code]type_right[/code]. </description> </method> </methods> diff --git a/doc/classes/InputEventWithModifiers.xml b/doc/classes/InputEventWithModifiers.xml index dd782209e5..3beea7f9a0 100644 --- a/doc/classes/InputEventWithModifiers.xml +++ b/doc/classes/InputEventWithModifiers.xml @@ -12,23 +12,23 @@ <methods> </methods> <members> - <member name="alt" type="bool" setter="set_alt" getter="get_alt" default="false"> + <member name="alt_pressed" type="bool" setter="set_alt_pressed" getter="is_alt_pressed" default="false"> State of the [kbd]Alt[/kbd] modifier. </member> - <member name="command" type="bool" setter="set_command" getter="get_command" default="false"> + <member name="command_pressed" type="bool" setter="set_command_pressed" getter="is_command_pressed" default="false"> State of the [kbd]Cmd[/kbd] modifier. </member> - <member name="control" type="bool" setter="set_control" getter="get_control" default="false"> + <member name="ctrl_pressed" type="bool" setter="set_ctrl_pressed" getter="is_ctrl_pressed" default="false"> State of the [kbd]Ctrl[/kbd] modifier. </member> - <member name="meta" type="bool" setter="set_metakey" getter="get_metakey" default="false"> + <member name="meta_pressed" type="bool" setter="set_meta_pressed" getter="is_meta_pressed" default="false"> State of the [kbd]Meta[/kbd] modifier. </member> - <member name="shift" type="bool" setter="set_shift" getter="get_shift" default="false"> + <member name="shift_pressed" type="bool" setter="set_shift_pressed" getter="is_shift_pressed" default="false"> State of the [kbd]Shift[/kbd] modifier. </member> <member name="store_command" type="bool" setter="set_store_command" getter="is_storing_command" default="true"> - If [code]true[/code], pressing [kbd]Cmd[/kbd] on macOS or [kbd]Ctrl[/kbd] on all other platforms will both be serialized as [member command]. If [code]false[/code], those same keys will be serialized as [member meta] on macOS and [member control] on all other platforms. + If [code]true[/code], pressing [kbd]Cmd[/kbd] on macOS or [kbd]Ctrl[/kbd] on all other platforms will both be serialized as [member command_pressed]. If [code]false[/code], those same keys will be serialized as [member meta_pressed] on macOS and [member ctrl_pressed] on all other platforms. This aids with cross-platform compatibility when developing e.g. on Windows for macOS, or vice-versa. </member> </members> diff --git a/doc/classes/JavaScript.xml b/doc/classes/JavaScript.xml index c707a72ee8..e6d74eeb21 100644 --- a/doc/classes/JavaScript.xml +++ b/doc/classes/JavaScript.xml @@ -11,6 +11,24 @@ <link title="Exporting for the Web: Calling JavaScript from script">https://docs.godotengine.org/en/latest/getting_started/workflow/export/exporting_for_web.html#calling-javascript-from-script</link> </tutorials> <methods> + <method name="create_callback"> + <return type="JavaScriptObject"> + </return> + <argument index="0" name="callable" type="Callable"> + </argument> + <description> + Creates a reference to a [Callable] that can be used as a callback by JavaScript. The reference must be kept until the callback happens, or it won't be called at all. See [JavaScriptObject] for usage. + </description> + </method> + <method name="create_object" qualifiers="vararg"> + <return type="Variant"> + </return> + <argument index="0" name="object" type="String"> + </argument> + <description> + Creates a new JavaScript object using the [code]new[/code] constructor. The [code]object[/code] must a valid property of the JavaScript [code]window[/code]. See [JavaScriptObject] for usage. + </description> + </method> <method name="eval"> <return type="Variant"> </return> @@ -23,6 +41,15 @@ If [code]use_global_execution_context[/code] is [code]true[/code], the code will be evaluated in the global execution context. Otherwise, it is evaluated in the execution context of a function within the engine's runtime environment. </description> </method> + <method name="get_interface"> + <return type="JavaScriptObject"> + </return> + <argument index="0" name="interface" type="String"> + </argument> + <description> + Returns an interface to a JavaScript object that can be used by scripts. The [code]interface[/code] must be a valid property of the JavaScript [code]window[/code]. The callback must accept a single [Array] argument, which will contain the JavaScript [code]arguments[/code]. See [JavaScriptObject] for usage. + </description> + </method> </methods> <constants> </constants> diff --git a/doc/classes/JavaScriptObject.xml b/doc/classes/JavaScriptObject.xml new file mode 100644 index 0000000000..a9e9c77e89 --- /dev/null +++ b/doc/classes/JavaScriptObject.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="JavaScriptObject" inherits="Reference" version="4.0"> + <brief_description> + A wrapper class for native JavaScript objects. + </brief_description> + <description> + JavaScriptObject is used to interact with JavaScript objects retrieved or created via [method JavaScript.get_interface], [method JavaScript.create_object], or [method JavaScript.create_callback]. + Example: + [codeblock] + extends Node + + var _my_js_callback = JavaScript.create_callback(self, "myCallback") # This reference must be kept + var console = JavaScript.get_interface("console") + + func _init(): + var buf = JavaScript.create_object("ArrayBuffer", 10) # new ArrayBuffer(10) + print(buf) # prints [JavaScriptObject:OBJECT_ID] + var uint8arr = JavaScript.create_object("Uint8Array", buf) # new Uint8Array(buf) + uint8arr[1] = 255 + prints(uint8arr[1], uint8arr.byteLength) # prints 255 10 + console.log(uint8arr) # prints in browser console "Uint8Array(10) [ 0, 255, 0, 0, 0, 0, 0, 0, 0, 0 ]" + + # Equivalent of JavaScript: Array.from(uint8arr).forEach(myCallback) + JavaScript.get_interface("Array").from(uint8arr).forEach(_my_js_callback) + + func myCallback(args): + # Will be called with the parameters passed to the "forEach" callback + # [0, 0, [JavaScriptObject:1173]] + # [255, 1, [JavaScriptObject:1173]] + # ... + # [0, 9, [JavaScriptObject:1180]] + print(args) + [/codeblock] + Note: Only available in the "HTML5" platform. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/MeshDataTool.xml b/doc/classes/MeshDataTool.xml index db7a3187f0..3c679047a0 100644 --- a/doc/classes/MeshDataTool.xml +++ b/doc/classes/MeshDataTool.xml @@ -15,7 +15,7 @@ mdt.create_from_surface(mesh, 0) for i in range(mdt.get_vertex_count()): var vertex = mdt.get_vertex(i) - # In this example we extend the mesh by one unit, which results in seperated faces as it is flat shaded. + # In this example we extend the mesh by one unit, which results in separated faces as it is flat shaded. vertex += mdt.get_vertex_normal(i) # Save your change. mdt.set_vertex(i, vertex) @@ -33,7 +33,7 @@ for (var i = 0; i < mdt.GetVertexCount(); i++) { Vector3 vertex = mdt.GetVertex(i); - // In this example we extend the mesh by one unit, which results in seperated faces as it is flat shaded. + // In this example we extend the mesh by one unit, which results in separated faces as it is flat shaded. vertex += mdt.GetVertexNormal(i); // Save your change. mdt.SetVertex(i, vertex); diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml index eed0ec8d7e..988fb72267 100644 --- a/doc/classes/Node2D.xml +++ b/doc/classes/Node2D.xml @@ -154,7 +154,7 @@ If [code]true[/code], the node's Z index is relative to its parent's Z index. If this node's Z index is 2 and its parent's effective Z index is 3, then this node's effective Z index will be 2 + 3 = 5. </member> <member name="z_index" type="int" setter="set_z_index" getter="get_z_index" default="0"> - Z index. Controls the order in which the nodes render. A node with a higher Z index will display in front of others. + Z index. Controls the order in which the nodes render. A node with a higher Z index will display in front of others. Must be between [constant RenderingServer.CANVAS_ITEM_Z_MIN] and [constant RenderingServer.CANVAS_ITEM_Z_MAX] (inclusive). </member> </members> <constants> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index cb95deb9a0..05826ecbf0 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -357,7 +357,7 @@ </return> <description> Returns the current UNIX epoch timestamp in seconds. - [b]Important:[/b] This is the system clock that the user can manully set. [b]Never use[/b] this method for precise time calculation since its results are also subject to automatic adjustments by the operating system. [b]Always use[/b] [method get_ticks_usec] or [method get_ticks_msec] for precise time calculation instead, since they are guaranteed to be monotonic (i.e. never decrease). + [b]Important:[/b] This is the system clock that the user can manually set. [b]Never use[/b] this method for precise time calculation since its results are also subject to automatic adjustments by the operating system. [b]Always use[/b] [method get_ticks_usec] or [method get_ticks_msec] for precise time calculation instead, since they are guaranteed to be monotonic (i.e. never decrease). </description> </method> <method name="get_unix_time_from_datetime" qualifiers="const"> diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 229facd08b..cfa4215fd4 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -1018,6 +1018,15 @@ Activates or deactivates the 2D physics engine. </description> </method> + <method name="set_collision_iterations"> + <return type="void"> + </return> + <argument index="0" name="iterations" type="int"> + </argument> + <description> + Sets the amount of iterations for calculating velocities of colliding bodies. The greater the amount, the more accurate the collisions, but with a performance loss. + </description> + </method> <method name="shape_get_data" qualifiers="const"> <return type="Variant"> </return> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index d38c3fc0d8..24d4a8a46e 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -6,7 +6,7 @@ <description> Contains global variables accessible from everywhere. Use [method get_setting], [method set_setting] or [method has_setting] to access them. Variables stored in [code]project.godot[/code] are also loaded into ProjectSettings, making this object very useful for reading custom game configuration options. When naming a Project Settings property, use the full path to the setting including the category. For example, [code]"application/config/name"[/code] for the project name. Category and property names can be viewed in the Project Settings dialog. - [b]Feature tags:[/b] Project settings can be overriden for specific platforms and configurations (debug, release, ...) using [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url]. + [b]Feature tags:[/b] Project settings can be overridden for specific platforms and configurations (debug, release, ...) using [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url]. [b]Overriding:[/b] Any project setting can be overridden by creating a file named [code]override.cfg[/code] in the project's root directory. This can also be used in exported projects by placing this file in the same directory as the project binary. Overriding will still take the base project settings' [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url] in account. Therefore, make sure to [i]also[/i] override the setting with the desired feature tags if you want them to override base project settings on all platforms and configurations. </description> <tutorials> @@ -1201,17 +1201,17 @@ The default angular damp in 2D. [b]Note:[/b] Good values are in the range [code]0[/code] to [code]1[/code]. At value [code]0[/code] objects will keep moving with the same velocity. Values greater than [code]1[/code] will aim to reduce the velocity to [code]0[/code] in less than a second e.g. a value of [code]2[/code] will aim to reduce the velocity to [code]0[/code] in half a second. A value equal to or greater than the physics frame rate ([member ProjectSettings.physics/common/physics_fps], [code]60[/code] by default) will bring the object to a stop in one iteration. </member> - <member name="physics/2d/default_gravity" type="int" setter="" getter="" default="98"> - The default gravity strength in 2D. + <member name="physics/2d/default_gravity" type="float" setter="" getter="" default="980.0"> + The default gravity strength in 2D (in pixels per second squared). [b]Note:[/b] This property is only read when the project starts. To change the default gravity at runtime, use the following code sample: [codeblocks] [gdscript] - # Set the default gravity strength to 98. - PhysicsServer2D.area_set_param(get_viewport().find_world_2d().space, PhysicsServer2D.AREA_PARAM_GRAVITY, 98) + # Set the default gravity strength to 980. + PhysicsServer2D.area_set_param(get_viewport().find_world_2d().space, PhysicsServer2D.AREA_PARAM_GRAVITY, 980) [/gdscript] [csharp] - // Set the default gravity strength to 98. - PhysicsServer2D.AreaSetParam(GetViewport().FindWorld2d().Space, PhysicsServer2D.AreaParameter.Gravity, 98); + // Set the default gravity strength to 980. + PhysicsServer2D.AreaSetParam(GetViewport().FindWorld2d().Space, PhysicsServer2D.AreaParameter.Gravity, 980); [/csharp] [/codeblocks] </member> @@ -1254,7 +1254,7 @@ [b]Note:[/b] Good values are in the range [code]0[/code] to [code]1[/code]. At value [code]0[/code] objects will keep moving with the same velocity. Values greater than [code]1[/code] will aim to reduce the velocity to [code]0[/code] in less than a second e.g. a value of [code]2[/code] will aim to reduce the velocity to [code]0[/code] in half a second. A value equal to or greater than the physics frame rate ([member ProjectSettings.physics/common/physics_fps], [code]60[/code] by default) will bring the object to a stop in one iteration. </member> <member name="physics/3d/default_gravity" type="float" setter="" getter="" default="9.8"> - The default gravity strength in 3D. + The default gravity strength in 3D (in meters per second squared). [b]Note:[/b] This property is only read when the project starts. To change the default gravity at runtime, use the following code sample: [codeblocks] [gdscript] diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index ed375a8b1e..a37ebb2dd5 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -193,7 +193,7 @@ </description> </signal> <signal name="body_shape_entered"> - <argument index="0" name="body_id" type="int"> + <argument index="0" name="body_rid" type="RID"> </argument> <argument index="1" name="body" type="Node"> </argument> @@ -210,7 +210,7 @@ </description> </signal> <signal name="body_shape_exited"> - <argument index="0" name="body_id" type="int"> + <argument index="0" name="body_rid" type="RID"> </argument> <argument index="1" name="body" type="Node"> </argument> diff --git a/doc/classes/RigidBody3D.xml b/doc/classes/RigidBody3D.xml index 1c6c8852a9..2ee8e2697c 100644 --- a/doc/classes/RigidBody3D.xml +++ b/doc/classes/RigidBody3D.xml @@ -103,7 +103,7 @@ [b]Note:[/b] The result of this test is not immediate after moving objects. For performance, list of collisions is updated once per frame and before the physics step. Consider using signals instead. </description> </method> - <method name="get_inverse_inertia_tensor"> + <method name="get_inverse_inertia_tensor" qualifiers="const"> <return type="Basis"> </return> <description> @@ -217,7 +217,7 @@ </description> </signal> <signal name="body_shape_entered"> - <argument index="0" name="body_id" type="int"> + <argument index="0" name="body_rid" type="RID"> </argument> <argument index="1" name="body" type="Node"> </argument> @@ -235,7 +235,7 @@ </description> </signal> <signal name="body_shape_exited"> - <argument index="0" name="body_id" type="int"> + <argument index="0" name="body_rid" type="RID"> </argument> <argument index="1" name="body" type="Node"> </argument> diff --git a/doc/classes/ScriptEditorBase.xml b/doc/classes/ScriptEditorBase.xml index ee498de302..e5c4c32450 100644 --- a/doc/classes/ScriptEditorBase.xml +++ b/doc/classes/ScriptEditorBase.xml @@ -18,6 +18,13 @@ Adds a [EditorSyntaxHighlighter] to the open script. </description> </method> + <method name="get_base_editor" qualifiers="const"> + <return type="Control"> + </return> + <description> + Returns the underlying [Control] used for editing scripts. This can be either [CodeEdit] (for text scripts) or [GraphEdit] (for visual scripts). + </description> + </method> </methods> <signals> <signal name="edited_script_changed"> diff --git a/doc/classes/StreamPeer.xml b/doc/classes/StreamPeer.xml index a1b858acf6..f120103916 100644 --- a/doc/classes/StreamPeer.xml +++ b/doc/classes/StreamPeer.xml @@ -4,7 +4,7 @@ Abstraction and base class for stream-based protocols. </brief_description> <description> - StreamPeer is an abstraction and base class for stream-based protocols (such as TCP or UNIX sockets). It provides an API for sending and receiving data through streams as raw data or strings. + StreamPeer is an abstraction and base class for stream-based protocols (such as TCP). It provides an API for sending and receiving data through streams as raw data or strings. </description> <tutorials> </tutorials> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 416438e648..a81defa16c 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -397,7 +397,12 @@ <argument index="0" name="position" type="int"> </argument> <description> - Returns a number of characters from the left of the string. + Returns a number of characters from the left of the string. If negative [code]position[/code] is used, the characters are counted downwards from [String]'s length. + Examples: + [codeblock] + print("sample text".left(3)) #prints "sam" + print("sample text".left(-3)) #prints "sample t" + [/codeblock] </description> </method> <method name="length" qualifiers="const"> @@ -669,7 +674,12 @@ <argument index="0" name="position" type="int"> </argument> <description> - Returns the right side of the string from a given position. + Returns a number of characters from the right of the string. If negative [code]position[/code] is used, the characters are counted downwards from [String]'s length. + Examples: + [codeblock] + print("sample text".right(3)) #prints "ext" + print("sample text".right(-3)) #prints "ple text" + [/codeblock] </description> </method> <method name="rpad" qualifiers="const"> diff --git a/doc/classes/SubViewport.xml b/doc/classes/SubViewport.xml index b6e9eda1d1..f54f22d6fa 100644 --- a/doc/classes/SubViewport.xml +++ b/doc/classes/SubViewport.xml @@ -25,7 +25,7 @@ <member name="render_target_update_mode" type="int" setter="set_update_mode" getter="get_update_mode" enum="SubViewport.UpdateMode" default="2"> The update mode when the sub-viewport is used as a render target. </member> - <member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i( 0, 0 )"> + <member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i( 512, 512 )"> The width and height of the sub-viewport. </member> <member name="size_2d_override" type="Vector2i" setter="set_size_2d_override" getter="get_size_2d_override" default="Vector2i( 0, 0 )"> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 088bcd1c3c..b97728ccd4 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -5,6 +5,7 @@ </brief_description> <description> TextEdit is meant for editing large, multiline text. It also has facilities for editing code, such as syntax highlighting support and multiple levels of undo/redo. + [b]Note:[/b] When holding down [kbd]Alt[/kbd], the vertical scroll wheel will scroll 5 times as fast as it would normally do. This also works in the Godot script editor. </description> <tutorials> </tutorials> @@ -282,6 +283,13 @@ Returns the selection end line. </description> </method> + <method name="get_visible_line_count" qualifiers="const"> + <return type="int"> + </return> + <description> + Returns the number of visible lines, including wrapped text. + </description> + </method> <method name="get_word_under_cursor" qualifiers="const"> <return type="String"> </return> @@ -714,10 +722,10 @@ If [code]true[/code], read-only mode is enabled. Existing text cannot be modified and new text cannot be added. </member> <member name="scroll_horizontal" type="int" setter="set_h_scroll" getter="get_h_scroll" default="0"> - If there is a horizontal scrollbar this determines the current horizontal scroll value in pixels. + If there is a horizontal scrollbar, this determines the current horizontal scroll value in pixels. </member> <member name="scroll_vertical" type="float" setter="set_v_scroll" getter="get_v_scroll" default="0.0"> - If there is a vertical scrollbar this determines the current vertical scroll value in line numbers, starting at 0 for the top line. + If there is a vertical scrollbar, this determines the current vertical scroll value in line numbers, starting at 0 for the top line. </member> <member name="selecting_enabled" type="bool" setter="set_selecting_enabled" getter="is_selecting_enabled" default="true"> If [code]true[/code], text can be selected. diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml index 3173dddb42..7448697df3 100644 --- a/doc/classes/Theme.xml +++ b/doc/classes/Theme.xml @@ -23,10 +23,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Clears the [Color] at [code]name[/code] if the theme has [code]node_type[/code]. + Clears the [Color] at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="clear_constant"> @@ -34,10 +34,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Clears the constant at [code]name[/code] if the theme has [code]node_type[/code]. + Clears the constant at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="clear_font"> @@ -45,10 +45,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Clears the [Font] at [code]name[/code] if the theme has [code]node_type[/code]. + Clears the [Font] at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="clear_font_size"> @@ -56,10 +56,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Clears the font size [code]name[/code] if the theme has [code]node_type[/code]. + Clears the font size [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="clear_icon"> @@ -67,10 +67,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Clears the icon at [code]name[/code] if the theme has [code]node_type[/code]. + Clears the icon at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="clear_stylebox"> @@ -78,10 +78,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Clears [StyleBox] at [code]name[/code] if the theme has [code]node_type[/code]. + Clears [StyleBox] at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="clear_theme_item"> @@ -91,10 +91,10 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <description> - Clears the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]node_type[/code]. + Clears the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="copy_default_theme"> @@ -118,19 +118,19 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns the [Color] at [code]name[/code] if the theme has [code]node_type[/code]. + Returns the [Color] at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="get_color_list" qualifiers="const"> <return type="PackedStringArray"> </return> - <argument index="0" name="node_type" type="String"> + <argument index="0" name="theme_type" type="String"> </argument> <description> - Returns all the [Color]s as a [PackedStringArray] filled with each [Color]'s name, for use in [method get_color], if the theme has [code]node_type[/code]. + Returns all the [Color]s as a [PackedStringArray] filled with each [Color]'s name, for use in [method get_color], if the theme has [code]theme_type[/code]. </description> </method> <method name="get_color_type_list" qualifiers="const"> @@ -145,19 +145,19 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns the constant at [code]name[/code] if the theme has [code]node_type[/code]. + Returns the constant at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="get_constant_list" qualifiers="const"> <return type="PackedStringArray"> </return> - <argument index="0" name="node_type" type="String"> + <argument index="0" name="theme_type" type="String"> </argument> <description> - Returns all the constants as a [PackedStringArray] filled with each constant's name, for use in [method get_constant], if the theme has [code]node_type[/code]. + Returns all the constants as a [PackedStringArray] filled with each constant's name, for use in [method get_constant], if the theme has [code]theme_type[/code]. </description> </method> <method name="get_constant_type_list" qualifiers="const"> @@ -172,19 +172,19 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns the [Font] at [code]name[/code] if the theme has [code]node_type[/code]. + Returns the [Font] at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="get_font_list" qualifiers="const"> <return type="PackedStringArray"> </return> - <argument index="0" name="node_type" type="String"> + <argument index="0" name="theme_type" type="String"> </argument> <description> - Returns all the [Font]s as a [PackedStringArray] filled with each [Font]'s name, for use in [method get_font], if the theme has [code]node_type[/code]. + Returns all the [Font]s as a [PackedStringArray] filled with each [Font]'s name, for use in [method get_font], if the theme has [code]theme_type[/code]. </description> </method> <method name="get_font_size" qualifiers="const"> @@ -192,19 +192,19 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns the font size at [code]name[/code] if the theme has [code]node_type[/code]. + Returns the font size at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="get_font_size_list" qualifiers="const"> <return type="PackedStringArray"> </return> - <argument index="0" name="node_type" type="String"> + <argument index="0" name="theme_type" type="String"> </argument> <description> - Returns all the font sizes as a [PackedStringArray] filled with each font size name, for use in [method get_font_size], if the theme has [code]node_type[/code]. + Returns all the font sizes as a [PackedStringArray] filled with each font size name, for use in [method get_font_size], if the theme has [code]theme_type[/code]. </description> </method> <method name="get_font_size_type_list" qualifiers="const"> @@ -226,19 +226,19 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns the icon [Texture2D] at [code]name[/code] if the theme has [code]node_type[/code]. + Returns the icon [Texture2D] at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="get_icon_list" qualifiers="const"> <return type="PackedStringArray"> </return> - <argument index="0" name="node_type" type="String"> + <argument index="0" name="theme_type" type="String"> </argument> <description> - Returns all the icons as a [PackedStringArray] filled with each [Texture2D]'s name, for use in [method get_icon], if the theme has [code]node_type[/code]. + Returns all the icons as a [PackedStringArray] filled with each [Texture2D]'s name, for use in [method get_icon], if the theme has [code]theme_type[/code]. </description> </method> <method name="get_icon_type_list" qualifiers="const"> @@ -253,21 +253,21 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns the [StyleBox] at [code]name[/code] if the theme has [code]node_type[/code]. - Valid [code]name[/code]s may be found using [method get_stylebox_list]. Valid [code]node_type[/code]s may be found using [method get_stylebox_type_list]. + Returns the [StyleBox] at [code]name[/code] if the theme has [code]theme_type[/code]. + Valid [code]name[/code]s may be found using [method get_stylebox_list]. Valid [code]theme_type[/code]s may be found using [method get_stylebox_type_list]. </description> </method> <method name="get_stylebox_list" qualifiers="const"> <return type="PackedStringArray"> </return> - <argument index="0" name="node_type" type="String"> + <argument index="0" name="theme_type" type="String"> </argument> <description> - Returns all the [StyleBox]s as a [PackedStringArray] filled with each [StyleBox]'s name, for use in [method get_stylebox], if the theme has [code]node_type[/code]. - Valid [code]node_type[/code]s may be found using [method get_stylebox_type_list]. + Returns all the [StyleBox]s as a [PackedStringArray] filled with each [StyleBox]'s name, for use in [method get_stylebox], if the theme has [code]theme_type[/code]. + Valid [code]theme_type[/code]s may be found using [method get_stylebox_type_list]. </description> </method> <method name="get_stylebox_type_list" qualifiers="const"> @@ -284,11 +284,11 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <description> - Returns the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]node_type[/code]. - Valid [code]name[/code]s may be found using [method get_theme_item_list] or a data type specific method. Valid [code]node_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method. + Returns the theme item of [code]data_type[/code] at [code]name[/code] if the theme has [code]theme_type[/code]. + Valid [code]name[/code]s may be found using [method get_theme_item_list] or a data type specific method. Valid [code]theme_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method. </description> </method> <method name="get_theme_item_list" qualifiers="const"> @@ -296,11 +296,11 @@ </return> <argument index="0" name="data_type" type="int" enum="Theme.DataType"> </argument> - <argument index="1" name="node_type" type="String"> + <argument index="1" name="theme_type" type="String"> </argument> <description> - Returns all the theme items of [code]data_type[/code] as a [PackedStringArray] filled with each theme items's name, for use in [method get_theme_item] or a data type specific method, if the theme has [code]node_type[/code]. - Valid [code]node_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method. + Returns all the theme items of [code]data_type[/code] as a [PackedStringArray] filled with each theme items's name, for use in [method get_theme_item] or a data type specific method, if the theme has [code]theme_type[/code]. + Valid [code]theme_type[/code]s may be found using [method get_theme_item_type_list] or a data type specific method. </description> </method> <method name="get_theme_item_type_list" qualifiers="const"> @@ -324,11 +324,11 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns [code]true[/code] if [Color] with [code]name[/code] is in [code]node_type[/code]. - Returns [code]false[/code] if the theme does not have [code]node_type[/code]. + Returns [code]true[/code] if [Color] with [code]name[/code] is in [code]theme_type[/code]. + Returns [code]false[/code] if the theme does not have [code]theme_type[/code]. </description> </method> <method name="has_constant" qualifiers="const"> @@ -336,11 +336,11 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns [code]true[/code] if constant with [code]name[/code] is in [code]node_type[/code]. - Returns [code]false[/code] if the theme does not have [code]node_type[/code]. + Returns [code]true[/code] if constant with [code]name[/code] is in [code]theme_type[/code]. + Returns [code]false[/code] if the theme does not have [code]theme_type[/code]. </description> </method> <method name="has_font" qualifiers="const"> @@ -348,11 +348,11 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns [code]true[/code] if [Font] with [code]name[/code] is in [code]node_type[/code]. - Returns [code]false[/code] if the theme does not have [code]node_type[/code]. + Returns [code]true[/code] if [Font] with [code]name[/code] is in [code]theme_type[/code]. + Returns [code]false[/code] if the theme does not have [code]theme_type[/code]. </description> </method> <method name="has_font_size" qualifiers="const"> @@ -360,11 +360,11 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns [code]true[/code] if font size with [code]name[/code] is in [code]node_type[/code]. - Returns [code]false[/code] if the theme does not have [code]node_type[/code]. + Returns [code]true[/code] if font size with [code]name[/code] is in [code]theme_type[/code]. + Returns [code]false[/code] if the theme does not have [code]theme_type[/code]. </description> </method> <method name="has_icon" qualifiers="const"> @@ -372,11 +372,11 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns [code]true[/code] if icon [Texture2D] with [code]name[/code] is in [code]node_type[/code]. - Returns [code]false[/code] if the theme does not have [code]node_type[/code]. + Returns [code]true[/code] if icon [Texture2D] with [code]name[/code] is in [code]theme_type[/code]. + Returns [code]false[/code] if the theme does not have [code]theme_type[/code]. </description> </method> <method name="has_stylebox" qualifiers="const"> @@ -384,11 +384,11 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <description> - Returns [code]true[/code] if [StyleBox] with [code]name[/code] is in [code]node_type[/code]. - Returns [code]false[/code] if the theme does not have [code]node_type[/code]. + Returns [code]true[/code] if [StyleBox] with [code]name[/code] is in [code]theme_type[/code]. + Returns [code]false[/code] if the theme does not have [code]theme_type[/code]. </description> </method> <method name="has_theme_item" qualifiers="const"> @@ -398,11 +398,11 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <description> - Returns [code]true[/code] if a theme item of [code]data_type[/code] with [code]name[/code] is in [code]node_type[/code]. - Returns [code]false[/code] if the theme does not have [code]node_type[/code]. + Returns [code]true[/code] if a theme item of [code]data_type[/code] with [code]name[/code] is in [code]theme_type[/code]. + Returns [code]false[/code] if the theme does not have [code]theme_type[/code]. </description> </method> <method name="rename_color"> @@ -412,10 +412,10 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <description> - Renames the [Color] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + Renames the [Color] at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails. </description> </method> <method name="rename_constant"> @@ -425,10 +425,10 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <description> - Renames the constant at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + Renames the constant at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails. </description> </method> <method name="rename_font"> @@ -438,10 +438,10 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <description> - Renames the [Font] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + Renames the [Font] at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails. </description> </method> <method name="rename_font_size"> @@ -451,10 +451,10 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <description> - Renames the font size [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + Renames the font size [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails. </description> </method> <method name="rename_icon"> @@ -464,10 +464,10 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <description> - Renames the icon at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + Renames the icon at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails. </description> </method> <method name="rename_stylebox"> @@ -477,10 +477,10 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <description> - Renames [StyleBox] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + Renames [StyleBox] at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails. </description> </method> <method name="rename_theme_item"> @@ -492,10 +492,10 @@ </argument> <argument index="2" name="name" type="StringName"> </argument> - <argument index="3" name="node_type" type="StringName"> + <argument index="3" name="theme_type" type="StringName"> </argument> <description> - Renames the theme item of [code]data_type[/code] at [code]old_name[/code] to [code]name[/code] if the theme has [code]node_type[/code]. If [code]name[/code] is already taken, this method fails. + Renames the theme item of [code]data_type[/code] at [code]old_name[/code] to [code]name[/code] if the theme has [code]theme_type[/code]. If [code]name[/code] is already taken, this method fails. </description> </method> <method name="set_color"> @@ -503,13 +503,13 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <argument index="2" name="color" type="Color"> </argument> <description> - Sets the theme's [Color] to [code]color[/code] at [code]name[/code] in [code]node_type[/code]. - Creates [code]node_type[/code] if the theme does not have it. + Sets the theme's [Color] to [code]color[/code] at [code]name[/code] in [code]theme_type[/code]. + Creates [code]theme_type[/code] if the theme does not have it. </description> </method> <method name="set_constant"> @@ -517,13 +517,13 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <argument index="2" name="constant" type="int"> </argument> <description> - Sets the theme's constant to [code]constant[/code] at [code]name[/code] in [code]node_type[/code]. - Creates [code]node_type[/code] if the theme does not have it. + Sets the theme's constant to [code]constant[/code] at [code]name[/code] in [code]theme_type[/code]. + Creates [code]theme_type[/code] if the theme does not have it. </description> </method> <method name="set_font"> @@ -531,13 +531,13 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <argument index="2" name="font" type="Font"> </argument> <description> - Sets the theme's [Font] to [code]font[/code] at [code]name[/code] in [code]node_type[/code]. - Creates [code]node_type[/code] if the theme does not have it. + Sets the theme's [Font] to [code]font[/code] at [code]name[/code] in [code]theme_type[/code]. + Creates [code]theme_type[/code] if the theme does not have it. </description> </method> <method name="set_font_size"> @@ -545,13 +545,13 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <argument index="2" name="font_size" type="int"> </argument> <description> - Sets the theme's font size to [code]font_size[/code] at [code]name[/code] in [code]node_type[/code]. - Creates [code]node_type[/code] if the theme does not have it. + Sets the theme's font size to [code]font_size[/code] at [code]name[/code] in [code]theme_type[/code]. + Creates [code]theme_type[/code] if the theme does not have it. </description> </method> <method name="set_icon"> @@ -559,13 +559,13 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <argument index="2" name="texture" type="Texture2D"> </argument> <description> - Sets the theme's icon [Texture2D] to [code]texture[/code] at [code]name[/code] in [code]node_type[/code]. - Creates [code]node_type[/code] if the theme does not have it. + Sets the theme's icon [Texture2D] to [code]texture[/code] at [code]name[/code] in [code]theme_type[/code]. + Creates [code]theme_type[/code] if the theme does not have it. </description> </method> <method name="set_stylebox"> @@ -573,13 +573,13 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="node_type" type="StringName"> + <argument index="1" name="theme_type" type="StringName"> </argument> <argument index="2" name="texture" type="StyleBox"> </argument> <description> - Sets theme's [StyleBox] to [code]stylebox[/code] at [code]name[/code] in [code]node_type[/code]. - Creates [code]node_type[/code] if the theme does not have it. + Sets theme's [StyleBox] to [code]stylebox[/code] at [code]name[/code] in [code]theme_type[/code]. + Creates [code]theme_type[/code] if the theme does not have it. </description> </method> <method name="set_theme_item"> @@ -589,14 +589,14 @@ </argument> <argument index="1" name="name" type="StringName"> </argument> - <argument index="2" name="node_type" type="StringName"> + <argument index="2" name="theme_type" type="StringName"> </argument> <argument index="3" name="value" type="Variant"> </argument> <description> - Sets the theme item of [code]data_type[/code] to [code]value[/code] at [code]name[/code] in [code]node_type[/code]. + Sets the theme item of [code]data_type[/code] to [code]value[/code] at [code]name[/code] in [code]theme_type[/code]. Does nothing if the [code]value[/code] type does not match [code]data_type[/code]. - Creates [code]node_type[/code] if the theme does not have it. + Creates [code]theme_type[/code] if the theme does not have it. </description> </method> </methods> diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index ff68a017a1..2015b1f1cd 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -20,7 +20,7 @@ <method name="add_source"> <return type="int"> </return> - <argument index="0" name="atlas_source_id_override" type="TileSetAtlasSource"> + <argument index="0" name="atlas_source_id_override" type="TileSetSource"> </argument> <argument index="1" name="arg1" type="int" default="-1"> </argument> diff --git a/doc/classes/TileSetScenesCollectionSource.xml b/doc/classes/TileSetScenesCollectionSource.xml new file mode 100644 index 0000000000..1a00eb51c0 --- /dev/null +++ b/doc/classes/TileSetScenesCollectionSource.xml @@ -0,0 +1,155 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="TileSetScenesCollectionSource" inherits="TileSetSource" version="4.0"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="create_scene_tile"> + <return type="int"> + </return> + <argument index="0" name="packed_scene" type="PackedScene"> + </argument> + <argument index="1" name="id_override" type="int" default="-1"> + </argument> + <description> + </description> + </method> + <method name="get_alternative_tile_id" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="atlas_coords" type="Vector2i"> + </argument> + <argument index="1" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_alternative_tiles_count" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="atlas_coords" type="Vector2i"> + </argument> + <description> + </description> + </method> + <method name="get_next_scene_tile_id" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_scene_tile_display_placeholder" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_scene_tile_id"> + <return type="int"> + </return> + <argument index="0" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_scene_tile_scene" qualifiers="const"> + <return type="PackedScene"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_scene_tiles_count"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_tile_id" qualifiers="const"> + <return type="Vector2i"> + </return> + <argument index="0" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_tiles_count" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="has_alternative_tile" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="atlas_coords" type="Vector2i"> + </argument> + <argument index="1" name="alternative_tile" type="int"> + </argument> + <description> + </description> + </method> + <method name="has_scene_tile_id"> + <return type="bool"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="has_tile" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="atlas_coords" type="Vector2i"> + </argument> + <description> + </description> + </method> + <method name="remove_scene_tile"> + <return type="void"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_scene_tile_display_placeholder"> + <return type="void"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="display_placeholder" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_scene_tile_id"> + <return type="void"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="new_id" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_scene_tile_scene"> + <return type="void"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="packed_scene" type="PackedScene"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index a09f1bf470..27b26801f3 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -30,7 +30,7 @@ } [/csharp] [/codeblocks] - To iterate over all the [TreeItem] objects in a [Tree] object, use [method TreeItem.get_next] and [method TreeItem.get_children] after getting the root through [method get_root]. You can use [method Object.free] on a [TreeItem] to remove it from the [Tree]. + To iterate over all the [TreeItem] objects in a [Tree] object, use [method TreeItem.get_next] and [method TreeItem.get_first_child] after getting the root through [method get_root]. You can use [method Object.free] on a [TreeItem] to remove it from the [Tree]. </description> <tutorials> </tutorials> diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index add23c2ce6..7d37580504 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -63,6 +63,16 @@ Removes all OpenType features. </description> </method> + <method name="create_child"> + <return type="TreeItem"> + </return> + <argument index="0" name="idx" type="int" default="-1"> + </argument> + <description> + Creates an item and adds it as a child. + The new item will be inserted as position [code]idx[/code] (the default value [code]-1[/code] means the last position), or it will be the last child if [code]idx[/code] is higher than the child count. + </description> + </method> <method name="deselect"> <return type="void"> </return> @@ -123,11 +133,28 @@ Returns the column's cell mode. </description> </method> - <method name="get_children"> + <method name="get_child"> <return type="TreeItem"> </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + Returns a child item by its index (see [method get_child_count]). This method is often used for iterating all children of an item. + Negative indices access the children from the last one. + </description> + </method> + <method name="get_child_count"> + <return type="int"> + </return> <description> - Returns the TreeItem's first child item or a null object if there is none. + Returns the number of child items. + </description> + </method> + <method name="get_children"> + <return type="Array"> + </return> + <description> + Returns an array of references to the item's children. </description> </method> <method name="get_custom_bg_color" qualifiers="const"> @@ -157,6 +184,13 @@ Returns [code]true[/code] if [code]expand_right[/code] is set. </description> </method> + <method name="get_first_child"> + <return type="TreeItem"> + </return> + <description> + Returns the TreeItem's first child. + </description> + </method> <method name="get_icon" qualifiers="const"> <return type="Texture2D"> </return> @@ -193,6 +227,13 @@ Returns the icon [Texture2D] region as [Rect2]. </description> </method> + <method name="get_index"> + <return type="int"> + </return> + <description> + Returns the node's order in the tree. For example, if called on the first child item the position is [code]0[/code]. + </description> + </method> <method name="get_language" qualifiers="const"> <return type="String"> </return> @@ -342,6 +383,13 @@ Returns the given column's tooltip. </description> </method> + <method name="get_tree"> + <return type="Tree"> + </return> + <description> + Returns the [Tree] that owns this TreeItem. + </description> + </method> <method name="is_button_disabled" qualifiers="const"> <return type="bool"> </return> @@ -397,18 +445,24 @@ Returns [code]true[/code] if column [code]column[/code] is selected. </description> </method> - <method name="move_to_bottom"> + <method name="move_after"> <return type="void"> </return> + <argument index="0" name="item" type="Object"> + </argument> <description> - Moves this TreeItem to the bottom in the [Tree] hierarchy. + Moves this TreeItem right after the given [code]item[/code]. + [b]Note:[/b] You can't move to the root or move the root. </description> </method> - <method name="move_to_top"> + <method name="move_before"> <return type="void"> </return> + <argument index="0" name="item" type="Object"> + </argument> <description> - Moves this TreeItem to the top in the [Tree] hierarchy. + Moves this TreeItem right before the given [code]item[/code]. + [b]Note:[/b] You can't move to the root or move the root. </description> </method> <method name="remove_child"> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index b99a251a11..37709753bc 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -45,7 +45,7 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> </description> @@ -55,7 +55,7 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> </description> @@ -65,10 +65,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns the [Font] at [code]name[/code] if the theme has [code]type[/code]. + Returns the [Font] at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="get_theme_font_size" qualifiers="const"> @@ -76,10 +76,10 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns the font size at [code]name[/code] if the theme has [code]type[/code]. + Returns the font size at [code]name[/code] if the theme has [code]theme_type[/code]. </description> </method> <method name="get_theme_icon" qualifiers="const"> @@ -87,7 +87,7 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> </description> @@ -97,7 +97,7 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> </description> @@ -119,7 +119,7 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> </description> @@ -129,7 +129,7 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> </description> @@ -139,11 +139,11 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns [code]true[/code] if [Font] with [code]name[/code] is in [code]type[/code]. - Returns [code]false[/code] if the theme does not have [code]type[/code]. + Returns [code]true[/code] if [Font] with [code]name[/code] is in [code]theme_type[/code]. + Returns [code]false[/code] if the theme does not have [code]theme_type[/code]. </description> </method> <method name="has_theme_font_size" qualifiers="const"> @@ -151,11 +151,11 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> - Returns [code]true[/code] if font size with [code]name[/code] is in [code]type[/code]. - Returns [code]false[/code] if the theme does not have [code]type[/code]. + Returns [code]true[/code] if font size with [code]name[/code] is in [code]theme_type[/code]. + Returns [code]false[/code] if the theme does not have [code]theme_type[/code]. </description> </method> <method name="has_theme_icon" qualifiers="const"> @@ -163,7 +163,7 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> </description> @@ -173,7 +173,7 @@ </return> <argument index="0" name="name" type="StringName"> </argument> - <argument index="1" name="type" type="StringName" default=""""> + <argument index="1" name="theme_type" type="StringName" default=""""> </argument> <description> </description> @@ -340,6 +340,8 @@ </member> <member name="theme" type="Theme" setter="set_theme" getter="get_theme"> </member> + <member name="theme_custom_type" type="StringName" setter="set_theme_custom_type" getter="get_theme_custom_type" default="@"""> + </member> <member name="title" type="String" setter="set_title" getter="get_title" default=""""> </member> <member name="transient" type="bool" setter="set_transient" getter="is_transient" default="false"> diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 1a27c54757..8f20a3472c 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -554,6 +554,7 @@ public: RID particles_allocate() override { return RID(); } void particles_initialize(RID p_rid) override {} + void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {} void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {} void particles_set_emitting(RID p_particles, bool p_emitting) override {} void particles_set_amount(RID p_particles, int p_amount) override {} diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index ded6bbc53e..41554bc93f 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -37,7 +37,7 @@ #include <string.h> Error ImageLoaderPNG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { - const size_t buffer_size = f->get_len(); + const uint64_t buffer_size = f->get_len(); Vector<uint8_t> file_buffer; Error err = file_buffer.resize(buffer_size); if (err) { diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 22151b60c1..3323da5db4 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -406,7 +406,7 @@ Error DirAccessUnix::remove(String p_path) { } } -size_t DirAccessUnix::get_space_left() { +uint64_t DirAccessUnix::get_space_left() { #ifndef NO_STATVFS struct statvfs vfs; if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) { diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index 54f4a5c312..12994a6b76 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -79,7 +79,7 @@ public: virtual Error rename(String p_path, String p_new_path); virtual Error remove(String p_path); - virtual size_t get_space_left(); + virtual uint64_t get_space_left(); virtual String get_filesystem_type() const; diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 4c08380dd0..de9a7867ee 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -184,11 +184,11 @@ String FileAccessUnix::get_path_absolute() const { return path; } -void FileAccessUnix::seek(size_t p_position) { +void FileAccessUnix::seek(uint64_t p_position) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); last_error = OK; - if (fseek(f, p_position, SEEK_SET)) { + if (fseeko(f, p_position, SEEK_SET)) { check_errors(); } } @@ -196,15 +196,15 @@ void FileAccessUnix::seek(size_t p_position) { void FileAccessUnix::seek_end(int64_t p_position) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); - if (fseek(f, p_position, SEEK_END)) { + if (fseeko(f, p_position, SEEK_END)) { check_errors(); } } -size_t FileAccessUnix::get_position() const { +uint64_t FileAccessUnix::get_position() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); - long pos = ftell(f); + int64_t pos = ftello(f); if (pos < 0) { check_errors(); ERR_FAIL_V(0); @@ -212,15 +212,15 @@ size_t FileAccessUnix::get_position() const { return pos; } -size_t FileAccessUnix::get_len() const { +uint64_t FileAccessUnix::get_len() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); - long pos = ftell(f); + int64_t pos = ftello(f); ERR_FAIL_COND_V(pos < 0, 0); - ERR_FAIL_COND_V(fseek(f, 0, SEEK_END), 0); - long size = ftell(f); + ERR_FAIL_COND_V(fseeko(f, 0, SEEK_END), 0); + int64_t size = ftello(f); ERR_FAIL_COND_V(size < 0, 0); - ERR_FAIL_COND_V(fseek(f, pos, SEEK_SET), 0); + ERR_FAIL_COND_V(fseeko(f, pos, SEEK_SET), 0); return size; } @@ -239,11 +239,11 @@ uint8_t FileAccessUnix::get_8() const { return b; } -int FileAccessUnix::get_buffer(uint8_t *p_dst, int p_length) const { +uint64_t FileAccessUnix::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - ERR_FAIL_COND_V(p_length < 0, -1); ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use."); - int read = fread(p_dst, 1, p_length, f); + + uint64_t read = fread(p_dst, 1, p_length, f); check_errors(); return read; }; @@ -262,10 +262,10 @@ void FileAccessUnix::store_8(uint8_t p_dest) { ERR_FAIL_COND(fwrite(&p_dest, 1, 1, f) != 1); } -void FileAccessUnix::store_buffer(const uint8_t *p_src, int p_length) { +void FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); ERR_FAIL_COND(!p_src); - ERR_FAIL_COND((int)fwrite(p_src, 1, p_length, f) != p_length); + ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length); } bool FileAccessUnix::file_exists(const String &p_path) { diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 998fad7909..6aa3e1529f 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -61,21 +61,21 @@ public: virtual String get_path() const; /// returns the path for the current open file virtual String get_path_absolute() const; /// returns the absolute path for the current open file - virtual void seek(size_t p_position); ///< seek to a given position + virtual void seek(uint64_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual size_t get_position() const; ///< get position in the file - virtual size_t get_len() const; ///< get size of the file + virtual uint64_t get_position() const; ///< get position in the file + virtual uint64_t get_len() const; ///< get size of the file virtual bool eof_reached() const; ///< reading passed EOF virtual uint8_t get_8() const; ///< get a byte - virtual int get_buffer(uint8_t *p_dst, int p_length) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; virtual Error get_error() const; ///< get last error virtual void flush(); virtual void store_8(uint8_t p_dest); ///< store a byte - virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes virtual bool file_exists(const String &p_path); ///< return true if a file exists diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 4649cee17f..38455bdbed 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -529,7 +529,7 @@ Error VulkanContext::_check_capabilities() { device_features_func(gpu, &device_features); multiview_capabilities.is_supported = multiview_features.multiview; - // For now we ignore if multiview is available in geometry and tesselation as we do not currently support those + // For now we ignore if multiview is available in geometry and tessellation as we do not currently support those } // check extended properties diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 2c9f28717d..55f9e6de17 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -198,7 +198,7 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) { if (_get_root_string() == "") { int p = current_dir.find(":"); if (p != -1) { - return current_dir.right(p + 1); + return current_dir.substr(p + 1); } } return current_dir; @@ -325,14 +325,15 @@ FileType DirAccessWindows::get_file_type(const String& p_file) const { } */ -size_t DirAccessWindows::get_space_left() { + +uint64_t DirAccessWindows::get_space_left() { uint64_t bytes = 0; if (!GetDiskFreeSpaceEx(nullptr, (PULARGE_INTEGER)&bytes, nullptr, nullptr)) { return 0; } //this is either 0 or a value in bytes. - return (size_t)bytes; + return bytes; } String DirAccessWindows::get_filesystem_type() const { diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h index 7f10023470..553d5c4701 100644 --- a/drivers/windows/dir_access_windows.h +++ b/drivers/windows/dir_access_windows.h @@ -78,8 +78,7 @@ public: virtual Error rename(String p_path, String p_new_path); virtual Error remove(String p_path); - //virtual FileType get_file_type() const; - size_t get_space_left(); + uint64_t get_space_left(); virtual String get_filesystem_type() const; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index b1b3fc9092..0f52c70482 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -193,10 +193,11 @@ bool FileAccessWindows::is_open() const { return (f != nullptr); } -void FileAccessWindows::seek(size_t p_position) { +void FileAccessWindows::seek(uint64_t p_position) { ERR_FAIL_COND(!f); + last_error = OK; - if (fseek(f, p_position, SEEK_SET)) { + if (_fseeki64(f, p_position, SEEK_SET)) { check_errors(); } prev_op = 0; @@ -204,28 +205,27 @@ void FileAccessWindows::seek(size_t p_position) { void FileAccessWindows::seek_end(int64_t p_position) { ERR_FAIL_COND(!f); - if (fseek(f, p_position, SEEK_END)) { + if (_fseeki64(f, p_position, SEEK_END)) { check_errors(); } prev_op = 0; } -size_t FileAccessWindows::get_position() const { - size_t aux_position = 0; - aux_position = ftell(f); - if (!aux_position) { +uint64_t FileAccessWindows::get_position() const { + int64_t aux_position = _ftelli64(f); + if (aux_position < 0) { check_errors(); } return aux_position; } -size_t FileAccessWindows::get_len() const { +uint64_t FileAccessWindows::get_len() const { ERR_FAIL_COND_V(!f, 0); - size_t pos = get_position(); - fseek(f, 0, SEEK_END); - int size = get_position(); - fseek(f, pos, SEEK_SET); + uint64_t pos = get_position(); + _fseeki64(f, 0, SEEK_END); + uint64_t size = get_position(); + _fseeki64(f, pos, SEEK_SET); return size; } @@ -252,17 +252,17 @@ uint8_t FileAccessWindows::get_8() const { return b; } -int FileAccessWindows::get_buffer(uint8_t *p_dst, int p_length) const { +uint64_t FileAccessWindows::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - ERR_FAIL_COND_V(p_length < 0, -1); ERR_FAIL_COND_V(!f, -1); + if (flags == READ_WRITE || flags == WRITE_READ) { if (prev_op == WRITE) { fflush(f); } prev_op = READ; } - int read = fread(p_dst, 1, p_length, f); + uint64_t read = fread(p_dst, 1, p_length, f); check_errors(); return read; }; @@ -292,7 +292,7 @@ void FileAccessWindows::store_8(uint8_t p_dest) { fwrite(&p_dest, 1, 1, f); } -void FileAccessWindows::store_buffer(const uint8_t *p_src, int p_length) { +void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) { ERR_FAIL_COND(!f); if (flags == READ_WRITE || flags == WRITE_READ) { if (prev_op == READ) { diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index 507e0b2c20..008c69de66 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -56,21 +56,21 @@ public: virtual String get_path() const; /// returns the path for the current open file virtual String get_path_absolute() const; /// returns the absolute path for the current open file - virtual void seek(size_t p_position); ///< seek to a given position + virtual void seek(uint64_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual size_t get_position() const; ///< get position in the file - virtual size_t get_len() const; ///< get size of the file + virtual uint64_t get_position() const; ///< get position in the file + virtual uint64_t get_len() const; ///< get size of the file virtual bool eof_reached() const; ///< reading passed EOF virtual uint8_t get_8() const; ///< get a byte - virtual int get_buffer(uint8_t *p_dst, int p_length) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; virtual Error get_error() const; ///< get last error virtual void flush(); virtual void store_8(uint8_t p_dest); ///< store a byte - virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes + virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes virtual bool file_exists(const String &p_name); ///< return true if a file exists diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index c0d5716c4e..d195561a85 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -63,7 +63,7 @@ static const char *_joy_axis_descriptions[JOY_AXIS_MAX * 2] = { String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_event) { ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEvent"); - // Joypad motion events will display slighlty differently than what the event->as_text() provides. See #43660. + // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660. Ref<InputEventJoypadMotion> jpmotion = p_event; if (jpmotion.is_valid()) { String desc = TTR("Unknown Joypad Axis"); @@ -97,11 +97,11 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) { if (mod.is_valid()) { show_mods = true; - mod_checkboxes[MOD_ALT]->set_pressed(mod->get_alt()); - mod_checkboxes[MOD_SHIFT]->set_pressed(mod->get_shift()); - mod_checkboxes[MOD_COMMAND]->set_pressed(mod->get_command()); - mod_checkboxes[MOD_CONTROL]->set_pressed(mod->get_control()); - mod_checkboxes[MOD_META]->set_pressed(mod->get_metakey()); + mod_checkboxes[MOD_ALT]->set_pressed(mod->is_alt_pressed()); + mod_checkboxes[MOD_SHIFT]->set_pressed(mod->is_shift_pressed()); + mod_checkboxes[MOD_COMMAND]->set_pressed(mod->is_command_pressed()); + mod_checkboxes[MOD_CTRL]->set_pressed(mod->is_ctrl_pressed()); + mod_checkboxes[MOD_META]->set_pressed(mod->is_meta_pressed()); store_command_checkbox->set_pressed(mod->is_storing_command()); } @@ -122,9 +122,9 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) { // Update selected item in input list for keys, joybuttons and joyaxis only (since the mouse cannot be "listened" for). if (k.is_valid() || joyb.is_valid() || joym.is_valid()) { - TreeItem *category = input_list_tree->get_root()->get_children(); + TreeItem *category = input_list_tree->get_root()->get_first_child(); while (category) { - TreeItem *input_item = category->get_children(); + TreeItem *input_item = category->get_first_child(); // has_type this should be always true, unless the tree structure has been misconfigured. bool has_type = input_item->get_parent()->has_meta("__type"); @@ -384,15 +384,15 @@ void InputEventConfigurationDialog::_mod_toggled(bool p_checked, int p_index) { } if (p_index == 0) { - ie->set_alt(p_checked); + ie->set_alt_pressed(p_checked); } else if (p_index == 1) { - ie->set_shift(p_checked); + ie->set_shift_pressed(p_checked); } else if (p_index == 2) { - ie->set_command(p_checked); + ie->set_command_pressed(p_checked); } else if (p_index == 3) { - ie->set_control(p_checked); + ie->set_ctrl_pressed(p_checked); } else if (p_index == 4) { - ie->set_metakey(p_checked); + ie->set_meta_pressed(p_checked); } _set_event(ie); @@ -413,7 +413,7 @@ void InputEventConfigurationDialog::_store_command_toggled(bool p_checked) { mod_checkboxes[MOD_COMMAND]->show(); mod_checkboxes[MOD_COMMAND]->set_text("Meta (Command)"); #else - mod_checkboxes[MOD_CONTROL]->hide(); + mod_checkboxes[MOD_CTRL]->hide(); mod_checkboxes[MOD_COMMAND]->show(); mod_checkboxes[MOD_COMMAND]->set_text("Control (Command)"); @@ -421,7 +421,7 @@ void InputEventConfigurationDialog::_store_command_toggled(bool p_checked) { } else { // If not, hide Command, show Control and Meta. mod_checkboxes[MOD_COMMAND]->hide(); - mod_checkboxes[MOD_CONTROL]->show(); + mod_checkboxes[MOD_CTRL]->show(); mod_checkboxes[MOD_META]->show(); } } @@ -469,11 +469,11 @@ void InputEventConfigurationDialog::_input_list_item_selected() { } // Maintain modifier state from checkboxes - k->set_alt(mod_checkboxes[MOD_ALT]->is_pressed()); - k->set_shift(mod_checkboxes[MOD_SHIFT]->is_pressed()); - k->set_command(mod_checkboxes[MOD_COMMAND]->is_pressed()); - k->set_control(mod_checkboxes[MOD_CONTROL]->is_pressed()); - k->set_metakey(mod_checkboxes[MOD_META]->is_pressed()); + k->set_alt_pressed(mod_checkboxes[MOD_ALT]->is_pressed()); + k->set_shift_pressed(mod_checkboxes[MOD_SHIFT]->is_pressed()); + k->set_command_pressed(mod_checkboxes[MOD_COMMAND]->is_pressed()); + k->set_ctrl_pressed(mod_checkboxes[MOD_CTRL]->is_pressed()); + k->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed()); k->set_store_command(store_command_checkbox->is_pressed()); _set_event(k); @@ -484,11 +484,11 @@ void InputEventConfigurationDialog::_input_list_item_selected() { mb.instance(); mb->set_button_index(idx); // Maintain modifier state from checkboxes - mb->set_alt(mod_checkboxes[MOD_ALT]->is_pressed()); - mb->set_shift(mod_checkboxes[MOD_SHIFT]->is_pressed()); - mb->set_command(mod_checkboxes[MOD_COMMAND]->is_pressed()); - mb->set_control(mod_checkboxes[MOD_CONTROL]->is_pressed()); - mb->set_metakey(mod_checkboxes[MOD_META]->is_pressed()); + mb->set_alt_pressed(mod_checkboxes[MOD_ALT]->is_pressed()); + mb->set_shift_pressed(mod_checkboxes[MOD_SHIFT]->is_pressed()); + mb->set_command_pressed(mod_checkboxes[MOD_COMMAND]->is_pressed()); + mb->set_ctrl_pressed(mod_checkboxes[MOD_CTRL]->is_pressed()); + mb->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed()); mb->set_store_command(store_command_checkbox->is_pressed()); _set_event(mb); @@ -731,7 +731,7 @@ void ActionMapEditor::_add_action_pressed() { void ActionMapEditor::_add_action(const String &p_name) { if (p_name == "" || !_is_action_name_valid(p_name)) { - show_message(TTR("Invalid action name. it cannot be.is_empty()() nor contain '/', ':', '=', '\\' or '\"'")); + show_message(TTR("Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or '\"'")); return; } @@ -756,7 +756,7 @@ void ActionMapEditor::_action_edited() { if (new_name == "" || !_is_action_name_valid(new_name)) { ti->set_text(0, old_name); - show_message(TTR("Invalid action name. it cannot be.is_empty()() nor contain '/', ':', '=', '\\' or '\"'")); + show_message(TTR("Invalid action name. It cannot be empty nor contain '/', ':', '=', '\\' or '\"'")); return; } diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h index fb097ddfdd..aff3e6e957 100644 --- a/editor/action_map_editor.h +++ b/editor/action_map_editor.h @@ -78,11 +78,11 @@ private: MOD_ALT, MOD_SHIFT, MOD_COMMAND, - MOD_CONTROL, + MOD_CTRL, MOD_META, MOD_MAX }; - String mods[MOD_MAX] = { "Alt", "Shift", "Command", "Control", "Meta" }; + String mods[MOD_MAX] = { "Alt", "Shift", "Command", "Ctrl", "Metakey" }; CheckBox *mod_checkboxes[MOD_MAX]; CheckBox *store_command_checkbox; diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 67b52bf0ca..63ffab6727 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -619,7 +619,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { float v_zoom_orig = v_zoom; - if (mb->get_command()) { + if (mb->is_command_pressed()) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); } else { if (v_zoom < 100000) { @@ -632,7 +632,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { float v_zoom_orig = v_zoom; - if (mb->get_command()) { + if (mb->is_command_pressed()) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); } else { if (v_zoom > 0.000001) { @@ -691,9 +691,9 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { //first check point //command makes it ignore the main point, so control point editors can be force-edited //path 2D editing in the 3D and 2D editors works the same way - if (!mb->get_command()) { + if (!mb->is_command_pressed()) { if (edit_points[i].point_rect.has_point(mb->get_position())) { - if (mb->get_shift()) { + if (mb->is_shift_pressed()) { //add to selection if (selection.has(i)) { selection.erase(i); @@ -743,7 +743,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } //insert new point - if (mb->get_command() && mb->get_position().x >= timeline->get_name_limit() && mb->get_position().x < get_size().width - timeline->get_buttons_width()) { + if (mb->is_command_pressed() && mb->get_position().x >= timeline->get_name_limit() && mb->get_position().x < get_size().width - timeline->get_buttons_width()) { Array new_point; new_point.resize(5); @@ -961,7 +961,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { if (box_selecting_attempt && mm.is_valid()) { if (!box_selecting) { box_selecting = true; - box_selecting_add = mm->get_shift(); + box_selecting_add = mm->is_shift_pressed(); } box_selection_to = mm->get_position(); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 89f77f3c77..9d5811dcbd 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -2662,7 +2662,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } if (key_idx != -1) { - if (mb->get_command() || mb->get_shift()) { + if (mb->is_command_pressed() || mb->is_shift_pressed()) { if (editor->is_key_selected(track, key_idx)) { emit_signal("deselect_key", key_idx); } else { @@ -4028,7 +4028,7 @@ bool AnimationTrackEditor::is_selection_active() const { } bool AnimationTrackEditor::is_snap_enabled() const { - return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL); + return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(KEY_CTRL); } void AnimationTrackEditor::_update_tracks() { @@ -4959,12 +4959,12 @@ void AnimationTrackEditor::_box_selection_draw() { void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); scroll->accept_event(); } - if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); scroll->accept_event(); } @@ -4980,7 +4980,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { for (int i = 0; i < track_edits.size(); i++) { Rect2 local_rect = box_select_rect; local_rect.position -= track_edits[i]->get_global_position(); - track_edits[i]->append_to_selection(local_rect, mb->get_command()); + track_edits[i]->append_to_selection(local_rect, mb->is_command_pressed()); } if (_get_track_selected() == -1 && track_edits.size() > 0) { //minimal hack to make shortcuts work @@ -5010,7 +5010,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { } if (!box_selection->is_visible_in_tree()) { - if (!mm->get_command() && !mm->get_shift()) { + if (!mm->is_command_pressed() && !mm->is_shift_pressed()) { _clear_selection(); } box_selection->show(); @@ -5216,7 +5216,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { track_clipboard.clear(); TreeItem *root = track_copy_select->get_root(); if (root) { - TreeItem *it = root->get_children(); + TreeItem *it = root->get_first_child(); while (it) { Dictionary md = it->get_metadata(0); int idx = md["track_idx"]; @@ -5602,7 +5602,7 @@ void AnimationTrackEditor::_show_imported_anim_warning() { } void AnimationTrackEditor::_select_all_tracks_for_copy() { - TreeItem *track = track_copy_select->get_root()->get_children(); + TreeItem *track = track_copy_select->get_root()->get_first_child(); if (!track) { return; } @@ -5616,7 +5616,7 @@ void AnimationTrackEditor::_select_all_tracks_for_copy() { track = track->get_next(); } - track = track_copy_select->get_root()->get_children(); + track = track_copy_select->get_root()->get_first_child(); while (track) { track->set_checked(0, !all_selected); track = track->get_next(); @@ -5681,7 +5681,7 @@ void AnimationTrackEditor::_pick_track_select_recursive(TreeItem *p_item, const p_select_candidates.push_back(node); } - TreeItem *c = p_item->get_children(); + TreeItem *c = p_item->get_first_child(); while (c) { _pick_track_select_recursive(c, p_filter, p_select_candidates); diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index ae79299331..54c1e89d1e 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -1091,7 +1091,7 @@ void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) { if (len_resizing && mm.is_valid()) { len_resizing_rel += mm->get_relative().x; - len_resizing_start = mm->get_shift(); + len_resizing_start = mm->is_shift_pressed(); update(); accept_event(); return; @@ -1100,7 +1100,7 @@ void AnimationTrackEditTypeAudio::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && get_default_cursor_shape() == CURSOR_HSIZE) { len_resizing = true; - len_resizing_start = mb->get_shift(); + len_resizing_start = mb->is_shift_pressed(); len_resizing_from_px = mb->get_position().x; len_resizing_rel = 0; update(); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 1c62c3d3e1..12e78c3120 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -726,7 +726,7 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_command()) { + if (mb->is_pressed() && mb->is_command_pressed()) { if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { _zoom_in(); } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { @@ -1012,7 +1012,7 @@ void CodeTextEditor::convert_indent_to_spaces() { if (cursor_line == i && cursor_column > j) { cursor_column += indent_size - 1; } - line = line.left(j) + indent + line.right(j + 1); + line = line.left(j) + indent + line.substr(j + 1); } j++; } @@ -1056,7 +1056,7 @@ void CodeTextEditor::convert_indent_to_tabs() { if (cursor_line == i && cursor_column > j) { cursor_column -= indent_size; } - line = line.left(j - indent_size) + "\t" + line.right(j + 1); + line = line.left(j - indent_size) + "\t" + line.substr(j + 1); j = 0; space_count = -1; } @@ -1114,7 +1114,7 @@ void CodeTextEditor::convert_case(CaseStyle p_case) { new_line = text_editor->get_line(i).left(begin_col) + new_line; } if (i == end) { - new_line = new_line + text_editor->get_line(i).right(end_col); + new_line = new_line + text_editor->get_line(i).substr(end_col); } text_editor->set_line(i, new_line); } diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 0c1fb6fe4d..511c2a48cc 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -655,7 +655,7 @@ void ConnectionsDock::_disconnect_all() { return; } - TreeItem *child = item->get_children(); + TreeItem *child = item->get_first_child(); String signalName = item->get_metadata(0).operator Dictionary()["name"]; undo_redo->create_action(vformat(TTR("Disconnect all from signal: '%s'"), signalName)); diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 1d95161e6c..7493cc2a8d 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -220,7 +220,7 @@ void ScriptEditorDebugger::_file_selected(const String &p_file) { file->store_csv_line(headers); if (vmem_tree->get_root()) { - TreeItem *ti = vmem_tree->get_root()->get_children(); + TreeItem *ti = vmem_tree->get_root()->get_first_child(); while (ti) { Vector<String> values; values.resize(vmem_tree->get_columns()); @@ -1319,7 +1319,7 @@ bool ScriptEditorDebugger::is_skip_breakpoints() { void ScriptEditorDebugger::_error_activated() { TreeItem *selected = error_tree->get_selected(); - TreeItem *ci = selected->get_children(); + TreeItem *ci = selected->get_first_child(); if (ci) { selected->set_collapsed(!selected->is_collapsed()); } @@ -1341,7 +1341,7 @@ void ScriptEditorDebugger::_expand_errors_list() { return; } - TreeItem *item = root->get_children(); + TreeItem *item = root->get_first_child(); while (item) { item->set_collapsed(false); item = item->get_next(); @@ -1354,7 +1354,7 @@ void ScriptEditorDebugger::_collapse_errors_list() { return; } - TreeItem *item = root->get_children(); + TreeItem *item = root->get_first_child(); while (item) { item->set_collapsed(true); item = item->get_next(); @@ -1403,7 +1403,7 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) { int rpad_len = text.length(); text = type + text + ti->get_text(1) + "\n"; - TreeItem *ci = ti->get_children(); + TreeItem *ci = ti->get_first_child(); while (ci) { text += " " + ci->get_text(0).rpad(rpad_len) + ci->get_text(1) + "\n"; ci = ci->get_next(); @@ -1419,7 +1419,7 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) { } // We only need the first child here (C++ source stack trace). - TreeItem *ci = ti->get_children(); + TreeItem *ci = ti->get_first_child(); // Parse back the `file:line @ method()` string. const Vector<String> file_line_number = ci->get_text(1).split("@")[0].strip_edges().split(":"); ERR_FAIL_COND_MSG(file_line_number.size() < 2, "Incorrect C++ source stack trace file:line format (please report)."); diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 57d44ca56c..c085205f63 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -725,8 +725,8 @@ void OrphanResourcesDialog::_find_to_delete(TreeItem *p_item, List<String> &path paths.push_back(p_item->get_metadata(0)); } - if (p_item->get_children()) { - _find_to_delete(p_item->get_children(), paths); + if (p_item->get_first_child()) { + _find_to_delete(p_item->get_first_child(), paths); } p_item = p_item->get_next(); diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 2d29076476..9dcd550f5c 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -45,8 +45,8 @@ void EditorAssetInstaller::_update_subitems(TreeItem *p_item, bool p_check, bool p_item->set_checked(0, false); } - if (p_item->get_children()) { - _update_subitems(p_item->get_children(), p_check); + if (p_item->get_first_child()) { + _update_subitems(p_item->get_first_child(), p_check); } if (!p_first && p_item->get_next()) { @@ -60,7 +60,7 @@ void EditorAssetInstaller::_uncheck_parent(TreeItem *p_item) { } bool any_checked = false; - TreeItem *item = p_item->get_children(); + TreeItem *item = p_item->get_first_child(); while (item) { if (item->is_checked(0)) { any_checked = true; diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index e7934bed0a..466ca70130 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -312,7 +312,7 @@ void EditorAudioBus::_volume_changed(float p_normalized) { const float p_db = this->_normalized_volume_to_scaled_db(p_normalized); - if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { // Snap the value when holding Ctrl for easier editing. // To do so, it needs to be converted back to normalized volume (as the slider uses that unit). slider->set_value(_scaled_db_to_normalized_volume(Math::round(p_db))); @@ -372,7 +372,7 @@ float EditorAudioBus::_scaled_db_to_normalized_volume(float db) { void EditorAudioBus::_show_value(float slider_value) { float db; - if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { // Display the correct (snapped) value when holding Ctrl db = Math::round(_normalized_volume_to_scaled_db(slider_value)); } else { diff --git a/editor/editor_builders.py b/editor/editor_builders.py index 86c5c87a68..ff0daa86ff 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -53,7 +53,7 @@ def make_fonts_header(target, source, env): g.write("#ifndef _EDITOR_FONTS_H\n") g.write("#define _EDITOR_FONTS_H\n") - # saving uncompressed, since freetype will reference from memory pointer + # Saving uncompressed, since FreeType will reference from memory pointer. for i in range(len(source)): with open(source[i], "rb") as f: buf = f.read() diff --git a/editor/editor_data.h b/editor/editor_data.h index 2ece94d6a3..df6ba9d0c9 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -167,7 +167,7 @@ public: EditorPlugin *get_editor_plugin(int p_idx); UndoRedo &get_undo_redo(); - void add_undo_redo_inspector_hook_callback(Callable p_callable); // Callbacks shoud have 4 args: (Object* undo_redo, Object *modified_object, String property, Varian new_value) + void add_undo_redo_inspector_hook_callback(Callable p_callable); // Callbacks should have 4 args: (Object* undo_redo, Object *modified_object, String property, Variant new_value) void remove_undo_redo_inspector_hook_callback(Callable p_callable); const Vector<Callable> get_undo_redo_inspector_hook_callback(); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index a368a9618e..b3755bef80 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -1222,12 +1222,12 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c } for (int i = 0; i < pd.file_ofs.size(); i++) { - int string_len = pd.file_ofs[i].path_utf8.length(); - int pad = _get_pad(4, string_len); + uint32_t string_len = pd.file_ofs[i].path_utf8.length(); + uint32_t pad = _get_pad(4, string_len); fhead->store_32(string_len + pad); fhead->store_buffer((const uint8_t *)pd.file_ofs[i].path_utf8.get_data(), string_len); - for (int j = 0; j < pad; j++) { + for (uint32_t j = 0; j < pad; j++) { fhead->store_8(0); } @@ -1269,8 +1269,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c uint8_t buf[bufsize]; while (true) { - int got = ftmp->get_buffer(buf, bufsize); - if (got <= 0) { + uint64_t got = ftmp->get_buffer(buf, bufsize); + if (got == 0) { break; } f->store_buffer(buf, got); @@ -1280,13 +1280,13 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c if (p_embed) { // Ensure embedded data ends at a 64-bit multiple - int64_t embed_end = f->get_position() - embed_pos + 12; - int pad = embed_end % 8; - for (int i = 0; i < pad; i++) { + uint64_t embed_end = f->get_position() - embed_pos + 12; + uint64_t pad = embed_end % 8; + for (uint64_t i = 0; i < pad; i++) { f->store_8(0); } - int64_t pck_size = f->get_position() - pck_start_pos; + uint64_t pck_size = f->get_position() - pck_start_pos; f->store_64(pck_size); f->store_32(PACK_HEADER_MAGIC); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 495bdd42f7..69663b9ed9 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -506,7 +506,7 @@ bool EditorFileSystem::_update_scan_actions() { case ItemAction::ACTION_DIR_ADD: { int idx = 0; for (int i = 0; i < ia.dir->subdirs.size(); i++) { - if (ia.new_dir->name < ia.dir->subdirs[i]->name) { + if (ia.new_dir->name.naturalnocasecmp_to(ia.dir->subdirs[i]->name) < 0) { break; } idx++; @@ -528,7 +528,7 @@ bool EditorFileSystem::_update_scan_actions() { case ItemAction::ACTION_FILE_ADD: { int idx = 0; for (int i = 0; i < ia.dir->files.size(); i++) { - if (ia.new_file->file < ia.dir->files[i]->file) { + if (ia.new_file->file.naturalnocasecmp_to(ia.dir->files[i]->file) < 0) { break; } idx++; @@ -713,7 +713,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess int idx2 = 0; for (int i = 0; i < p_dir->subdirs.size(); i++) { - if (efd->name < p_dir->subdirs[i]->name) { + if (efd->name.naturalnocasecmp_to(p_dir->subdirs[i]->name) < 0) { break; } idx2++; @@ -1245,7 +1245,7 @@ bool EditorFileSystem::_find_file(const String &p_file, EditorFileSystemDirector int idx2 = 0; for (int j = 0; j < fs->get_subdir_count(); j++) { - if (efsd->name < fs->get_subdir(j)->get_name()) { + if (efsd->name.naturalnocasecmp_to(fs->get_subdir(j)->get_name()) < 0) { break; } idx2++; @@ -1481,7 +1481,7 @@ void EditorFileSystem::update_file(const String &p_file) { String file_name = p_file.get_file(); for (int i = 0; i < fs->files.size(); i++) { - if (file_name < fs->files[i]->file) { + if (p_file.naturalnocasecmp_to(fs->files[i]->file) < 0) { break; } idx++; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 6039f64b7c..3f94f43710 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -475,7 +475,7 @@ void EditorHelp::_update_doc() { String linktxt = (cd.tutorials[i].title.is_empty()) ? link : DTR(cd.tutorials[i].title); const int seppos = linktxt.find("//"); if (seppos != -1) { - linktxt = link.right(seppos + 2); + linktxt = link.substr(seppos + 2); } class_desc->push_color(symbol_color); diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 23226ffa9b..b93ffa9321 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -334,7 +334,7 @@ bool EditorHelpSearch::Runner::_phase_match_classes() { for (int i = 0; i < class_doc.methods.size(); i++) { String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower(); if (method_name.find(term) > -1 || - (term.begins_with(".") && method_name.begins_with(term.right(1))) || + (term.begins_with(".") && method_name.begins_with(term.substr(1))) || (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) || (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) { match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i])); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 5bb3c8b4d0..29cc4c3c46 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1809,12 +1809,12 @@ void EditorInspector::update_tree() { basename = group + "/" + basename; } - String name = (basename.find("/") != -1) ? basename.right(basename.rfind("/") + 1) : basename; + String name = (basename.find("/") != -1) ? basename.substr(basename.rfind("/") + 1) : basename; if (capitalize_paths) { int dot = name.find("."); if (dot != -1) { - String ov = name.right(dot); + String ov = name.substr(dot); name = name.substr(0, dot); name = name.capitalize(); name += ov; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 7c485d53c5..469fb41406 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -376,7 +376,7 @@ EditorLog::EditorLog() { collapse_button = memnew(Button); collapse_button->set_flat(true); collapse_button->set_focus_mode(FOCUS_NONE); - collapse_button->set_tooltip(TTR("Collapse duplicate messages into one log entry. Shows number of occurences.")); + collapse_button->set_tooltip(TTR("Collapse duplicate messages into one log entry. Shows number of occurrences.")); collapse_button->set_toggle_mode(true); collapse_button->set_pressed(false); collapse_button->connect("toggled", callable_mp(this, &EditorLog::_set_collapse)); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 61b17a7247..72963012d6 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -82,6 +82,7 @@ #include "editor/editor_log.h" #include "editor/editor_plugin.h" #include "editor/editor_properties.h" +#include "editor/editor_resource_picker.h" #include "editor/editor_resource_preview.h" #include "editor/editor_run_native.h" #include "editor/editor_run_script.h" @@ -3093,10 +3094,11 @@ void EditorNode::remove_editor_plugin(EditorPlugin *p_editor, bool p_config_chan if (p_config_changed) { p_editor->disable_plugin(); } - singleton->editor_plugins_over->get_plugins_list().erase(p_editor); + singleton->editor_plugins_over->remove_plugin(p_editor); + singleton->editor_plugins_force_over->remove_plugin(p_editor); + singleton->editor_plugins_force_input_forwarding->remove_plugin(p_editor); singleton->remove_child(p_editor); singleton->editor_data.remove_editor_plugin(p_editor); - singleton->get_editor_plugins_force_input_forwarding()->remove_plugin(p_editor); } void EditorNode::_update_addon_config() { @@ -3165,7 +3167,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, // Errors in the script cause the base_type to be an empty string. if (String(script->get_instance_base_type()) == "") { - show_warning(vformat(TTR("Unable to load addon script from path: '%s'. This might be due to a code error in that script. \nDisabling the addon at '%s' to prevent further errors."), script_path, p_addon)); + show_warning(vformat(TTR("Unable to load addon script from path: '%s'. This might be due to a code error in that script.\nDisabling the addon at '%s' to prevent further errors."), script_path, p_addon)); _remove_plugin_from_enabled(p_addon); return; } @@ -3757,6 +3759,8 @@ void EditorNode::register_editor_types() { ClassDB::register_class<ScriptCreateDialog>(); ClassDB::register_class<EditorFeatureProfile>(); ClassDB::register_class<EditorSpinSlider>(); + ClassDB::register_class<EditorResourcePicker>(); + ClassDB::register_class<EditorScriptPicker>(); ClassDB::register_class<EditorSceneImporterMesh>(); ClassDB::register_class<EditorSceneImporterMeshNode3D>(); @@ -5288,7 +5292,7 @@ void EditorNode::_file_access_close_error_notify(const String &p_str) { void EditorNode::reload_scene(const String &p_path) { /* - * No longer necesary since scenes now reset and reload their internal resource if needed. + * No longer necessary since scenes now reset and reload their internal resource if needed. //first of all, reload internal textures, materials, meshes, etc. as they might have changed on disk List<Ref<Resource>> cached; diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index ee55ec4c0b..7beff4147d 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -2384,426 +2384,64 @@ EditorPropertyRID::EditorPropertyRID() { ////////////// RESOURCE ////////////////////// -void EditorPropertyResource::_file_selected(const String &p_path) { - RES res = ResourceLoader::load(p_path); - - ERR_FAIL_COND_MSG(res.is_null(), "Cannot load resource from path '" + p_path + "'."); - - List<PropertyInfo> prop_list; - get_edited_object()->get_property_list(&prop_list); - String property_types; - - for (List<PropertyInfo>::Element *E = prop_list.front(); E; E = E->next()) { - if (E->get().name == get_edited_property() && (E->get().hint & PROPERTY_HINT_RESOURCE_TYPE)) { - property_types = E->get().hint_string; - } - } - if (!property_types.is_empty()) { - bool any_type_matches = false; - const Vector<String> split_property_types = property_types.split(","); - for (int i = 0; i < split_property_types.size(); ++i) { - if (res->is_class(split_property_types[i])) { - any_type_matches = true; - break; - } - } - - if (!any_type_matches) { - EditorNode::get_singleton()->show_warning(vformat(TTR("The selected resource (%s) does not match any type expected for this property (%s)."), res->get_class(), property_types)); - } +void EditorPropertyResource::_resource_selected(const RES &p_resource) { + if (use_sub_inspector) { + bool unfold = !get_edited_object()->editor_is_section_unfolded(get_edited_property()); + get_edited_object()->editor_set_section_unfold(get_edited_property(), unfold); + update_property(); + } else { + emit_signal("resource_selected", get_edited_property(), p_resource); } - - emit_changed(get_edited_property(), res); - update_property(); } -void EditorPropertyResource::_menu_option(int p_which) { - //scene_tree->popup_scenetree_dialog(); - switch (p_which) { - case OBJ_MENU_LOAD: { - if (!file) { - file = memnew(EditorFileDialog); - file->connect("file_selected", callable_mp(this, &EditorPropertyResource::_file_selected)); - add_child(file); - } - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); - String type = base_type; - - List<String> extensions; - for (int i = 0; i < type.get_slice_count(","); i++) { - ResourceLoader::get_recognized_extensions_for_type(type.get_slice(",", i), &extensions); - } - - Set<String> valid_extensions; - for (List<String>::Element *E = extensions.front(); E; E = E->next()) { - valid_extensions.insert(E->get()); - } - - file->clear_filters(); - for (Set<String>::Element *E = valid_extensions.front(); E; E = E->next()) { - file->add_filter("*." + E->get() + " ; " + E->get().to_upper()); - } - - file->popup_file_dialog(); - } break; - - case OBJ_MENU_EDIT: { - RES res = get_edited_object()->get(get_edited_property()); +void EditorPropertyResource::_resource_changed(const RES &p_resource) { + // Make visual script the correct type. + Ref<Script> s = p_resource; + if (get_edited_object() && s.is_valid()) { + s->call("set_instance_base_type", get_edited_object()->get_class()); + } - if (!res.is_null()) { - emit_signal("resource_selected", get_edited_property(), res); - } - } break; - case OBJ_MENU_CLEAR: { + // Prevent the creation of invalid ViewportTextures when possible. + Ref<ViewportTexture> vpt = p_resource; + if (vpt.is_valid()) { + Resource *r = Object::cast_to<Resource>(get_edited_object()); + if (r && r->get_path().is_resource_file()) { + EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on resources saved as a file.\nResource needs to belong to a scene.")); emit_changed(get_edited_property(), RES()); update_property(); - - } break; - - case OBJ_MENU_MAKE_UNIQUE: { - RES res_orig = get_edited_object()->get(get_edited_property()); - if (res_orig.is_null()) { - return; - } - - List<PropertyInfo> property_list; - res_orig->get_property_list(&property_list); - List<Pair<String, Variant>> propvalues; - - for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) { - Pair<String, Variant> p; - PropertyInfo &pi = E->get(); - if (pi.usage & PROPERTY_USAGE_STORAGE) { - p.first = pi.name; - p.second = res_orig->get(pi.name); - } - - propvalues.push_back(p); - } - - String orig_type = res_orig->get_class(); - - Object *inst = ClassDB::instance(orig_type); - - Ref<Resource> res = Ref<Resource>(Object::cast_to<Resource>(inst)); - - ERR_FAIL_COND(res.is_null()); - - for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) { - Pair<String, Variant> &p = E->get(); - res->set(p.first, p.second); - } - - emit_changed(get_edited_property(), res); - update_property(); - - } break; - - case OBJ_MENU_SAVE: { - RES res = get_edited_object()->get(get_edited_property()); - if (res.is_null()) { - return; - } - EditorNode::get_singleton()->save_resource(res); - } break; - - case OBJ_MENU_COPY: { - RES res = get_edited_object()->get(get_edited_property()); - - EditorSettings::get_singleton()->set_resource_clipboard(res); - - } break; - case OBJ_MENU_PASTE: { - RES res = EditorSettings::get_singleton()->get_resource_clipboard(); - emit_changed(get_edited_property(), res); - update_property(); - - } break; - case OBJ_MENU_NEW_SCRIPT: { - if (Object::cast_to<Node>(get_edited_object())) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(get_edited_object()), false); - } - - } break; - case OBJ_MENU_EXTEND_SCRIPT: { - if (Object::cast_to<Node>(get_edited_object())) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(get_edited_object()), true); - } - - } break; - case OBJ_MENU_SHOW_IN_FILE_SYSTEM: { - RES res = get_edited_object()->get(get_edited_property()); - - FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock(); - file_system_dock->navigate_to_path(res->get_path()); - // Ensure that the FileSystem dock is visible. - TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); - tab_container->set_current_tab(file_system_dock->get_index()); - } break; - default: { - RES res = get_edited_object()->get(get_edited_property()); - - if (p_which >= CONVERT_BASE_ID) { - int to_type = p_which - CONVERT_BASE_ID; - - Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(res); - - ERR_FAIL_INDEX(to_type, conversions.size()); - - Ref<Resource> new_res = conversions[to_type]->convert(res); - - emit_changed(get_edited_property(), new_res); - update_property(); - break; - } - ERR_FAIL_COND(inheritors_array.is_empty()); - - String intype = inheritors_array[p_which - TYPE_BASE_ID]; - - if (intype == "ViewportTexture") { - Resource *r = Object::cast_to<Resource>(get_edited_object()); - if (r && r->get_path().is_resource_file()) { - EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on resources saved as a file.\nResource needs to belong to a scene.")); - return; - } - - if (r && !r->is_local_to_scene()) { - EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on this resource because it's not set as local to scene.\nPlease switch on the 'local to scene' property on it (and all resources containing it up to a node).")); - return; - } - - if (!scene_tree) { - scene_tree = memnew(SceneTreeDialog); - Vector<StringName> valid_types; - valid_types.push_back("Viewport"); - scene_tree->get_scene_tree()->set_valid_types(valid_types); - scene_tree->get_scene_tree()->set_show_enabled_subscene(true); - add_child(scene_tree); - scene_tree->connect("selected", callable_mp(this, &EditorPropertyResource::_viewport_selected)); - scene_tree->set_title(TTR("Pick a Viewport")); - } - scene_tree->popup_scenetree_dialog(); - - return; - } - - Variant obj; - - if (ScriptServer::is_global_class(intype)) { - obj = ClassDB::instance(ScriptServer::get_global_class_native_base(intype)); - if (obj) { - Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(intype)); - if (script.is_valid()) { - ((Object *)obj)->set_script(script); - } - } - } else { - obj = ClassDB::instance(intype); - } - - if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); - } - - Resource *resp = Object::cast_to<Resource>(obj); - ERR_BREAK(!resp); - if (get_edited_object() && base_type != String() && base_type == "Script") { - //make visual script the right type - resp->call("set_instance_base_type", get_edited_object()->get_class()); - } - - res = RES(resp); - emit_changed(get_edited_property(), res); - update_property(); - - } break; - } -} - -void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj) { - RES p = get_edited_object()->get(get_edited_property()); - if (p.is_valid() && p->get_instance_id() == p_obj) { - String type = p->get_class_name(); - - if (ClassDB::is_parent_class(type, "Script")) { - assign->set_text(p->get_path().get_file()); return; } - if (p_preview.is_valid()) { - preview->set_offset(SIDE_LEFT, assign->get_icon()->get_width() + assign->get_theme_stylebox("normal")->get_default_margin(SIDE_LEFT) + get_theme_constant("hseparation", "Button")); - if (type == "GradientTexture") { - preview->set_stretch_mode(TextureRect::STRETCH_SCALE); - assign->set_custom_minimum_size(Size2(1, 1)); - } else { - preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; - assign->set_custom_minimum_size(Size2(1, thumbnail_size)); - } - preview->set_texture(p_preview); - assign->set_text(""); - } - } -} - -void EditorPropertyResource::_update_menu_items() { - //////////////////// UPDATE MENU ////////////////////////// - RES res = get_edited_object()->get(get_edited_property()); - - menu->clear(); - - if (get_edited_property() == "script" && base_type == "Script" && Object::cast_to<Node>(get_edited_object())) { - menu->add_icon_item(get_theme_icon("ScriptCreate", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT); - menu->add_icon_item(get_theme_icon("ScriptExtend", "EditorIcons"), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT); - menu->add_separator(); - } else if (base_type != "") { - int idx = 0; - - Vector<EditorData::CustomType> custom_resources; - - if (EditorNode::get_editor_data().get_custom_types().has("Resource")) { - custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; - } - - for (int i = 0; i < base_type.get_slice_count(","); i++) { - String base = base_type.get_slice(",", i); - - Set<String> valid_inheritors; - valid_inheritors.insert(base); - List<StringName> inheritors; - ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors); - - for (int j = 0; j < custom_resources.size(); j++) { - inheritors.push_back(custom_resources[j].name); - } - - List<StringName>::Element *E = inheritors.front(); - while (E) { - valid_inheritors.insert(E->get()); - E = E->next(); - } - - List<StringName> global_classes; - ScriptServer::get_global_class_list(&global_classes); - E = global_classes.front(); - while (E) { - if (EditorNode::get_editor_data().script_class_is_parent(E->get(), base_type)) { - valid_inheritors.insert(E->get()); - } - E = E->next(); - } - - for (Set<String>::Element *F = valid_inheritors.front(); F; F = F->next()) { - const String &t = F->get(); - - bool is_custom_resource = false; - Ref<Texture2D> icon; - if (!custom_resources.is_empty()) { - for (int j = 0; j < custom_resources.size(); j++) { - if (custom_resources[j].name == t) { - is_custom_resource = true; - if (custom_resources[j].icon.is_valid()) { - icon = custom_resources[j].icon; - } - break; - } - } - } - - if (!is_custom_resource && !(ScriptServer::is_global_class(t) || ClassDB::can_instance(t))) { - continue; - } - - inheritors_array.push_back(t); - - if (!icon.is_valid()) { - icon = get_theme_icon(has_theme_icon(t, "EditorIcons") ? t : "Object", "EditorIcons"); - } - - int id = TYPE_BASE_ID + idx; - menu->add_icon_item(icon, vformat(TTR("New %s"), t), id); - - idx++; - } - } - - if (menu->get_item_count()) { - menu->add_separator(); - } - } - - menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD); - - if (!res.is_null()) { - menu->add_icon_item(get_theme_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT); - menu->add_icon_item(get_theme_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR); - menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); - menu->add_icon_item(get_theme_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE); - RES r = res; - if (r.is_valid() && r->get_path().is_resource_file()) { - menu->add_separator(); - menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM); - } - } - - RES cb = EditorSettings::get_singleton()->get_resource_clipboard(); - bool paste_valid = false; - if (cb.is_valid()) { - if (base_type == "") { - paste_valid = true; - } else { - for (int i = 0; i < base_type.get_slice_count(","); i++) { - if (ClassDB::is_parent_class(cb->get_class(), base_type.get_slice(",", i))) { - paste_valid = true; - break; - } - } + if (r && !r->is_local_to_scene()) { + EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on this resource because it's not set as local to scene.\nPlease switch on the 'local to scene' property on it (and all resources containing it up to a node).")); + emit_changed(get_edited_property(), RES()); + update_property(); + return; } } - if (!res.is_null() || paste_valid) { - menu->add_separator(); + emit_changed(get_edited_property(), p_resource); + update_property(); - if (!res.is_null()) { - menu->add_item(TTR("Copy"), OBJ_MENU_COPY); - } + // Automatically suggest setting up the path for a ViewportTexture. + if (vpt.is_valid() && vpt->get_viewport_path_in_scene().is_empty()) { + if (!scene_tree) { + scene_tree = memnew(SceneTreeDialog); + scene_tree->set_title(TTR("Pick a Viewport")); - if (paste_valid) { - menu->add_item(TTR("Paste"), OBJ_MENU_PASTE); - } - } + Vector<StringName> valid_types; + valid_types.push_back("Viewport"); + scene_tree->get_scene_tree()->set_valid_types(valid_types); + scene_tree->get_scene_tree()->set_show_enabled_subscene(true); - if (!res.is_null()) { - Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(res); - if (conversions.size()) { - menu->add_separator(); + add_child(scene_tree); + scene_tree->connect("selected", callable_mp(this, &EditorPropertyResource::_viewport_selected)); } - for (int i = 0; i < conversions.size(); i++) { - String what = conversions[i]->converts_to(); - Ref<Texture2D> icon; - if (has_theme_icon(what, "EditorIcons")) { - icon = get_theme_icon(what, "EditorIcons"); - } else { - icon = get_theme_icon(what, "Resource"); - } - menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i); - } + scene_tree->popup_scenetree_dialog(); } } -void EditorPropertyResource::_update_menu() { - _update_menu_items(); - - Rect2 gt = edit->get_screen_rect(); - menu->set_as_minsize(); - int ms = menu->get_contents_minimum_size().width; - Vector2 popup_pos = gt.position + gt.size - Vector2(ms, 0); - menu->set_position(popup_pos); - menu->popup(); -} - void EditorPropertyResource::_sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool) { emit_signal("property_keyed_with_value", String(get_edited_property()) + ":" + p_property, p_value, false); } @@ -2816,24 +2454,11 @@ void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) { emit_signal("object_id_selected", get_edited_property(), p_id); } -void EditorPropertyResource::_button_input(const Ref<InputEvent> &p_event) { - Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { - _update_menu_items(); - Vector2 pos = get_screen_position() + mb->get_position(); - //pos = assign->get_global_transform().xform(pos); - menu->set_as_minsize(); - menu->set_position(pos); - menu->popup(); - } - } -} - void EditorPropertyResource::_open_editor_pressed() { RES res = get_edited_object()->get(get_edited_property()); if (res.is_valid()) { - EditorNode::get_singleton()->call_deferred("edit_item_resource", res); //may clear the editor so do it deferred + // May clear the editor so do it deferred. + EditorNode::get_singleton()->call_deferred("edit_item_resource", res); } } @@ -2843,28 +2468,28 @@ void EditorPropertyResource::_fold_other_editors(Object *p_self) { } RES res = get_edited_object()->get(get_edited_property()); - if (!res.is_valid()) { return; } + bool use_editor = false; for (int i = 0; i < EditorNode::get_editor_data().get_editor_plugin_count(); i++) { EditorPlugin *ep = EditorNode::get_editor_data().get_editor_plugin(i); if (ep->handles(res.ptr())) { use_editor = true; + break; } } - if (!use_editor) { return; } - bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); opened_editor = false; + bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); if (unfolded) { - //refold - assign->set_pressed(false); + // Refold. + resource_picker->set_toggle_pressed(false); get_edited_object()->editor_set_section_unfold(get_edited_property(), false); update_property(); } @@ -2876,6 +2501,7 @@ void EditorPropertyResource::_update_property_bg() { } updating_theme = true; + if (sub_inspector != nullptr) { int count_subinspectors = 0; Node *n = get_parent(); @@ -2905,12 +2531,60 @@ void EditorPropertyResource::_update_property_bg() { updating_theme = false; update(); } + +void EditorPropertyResource::_viewport_selected(const NodePath &p_path) { + Node *to_node = get_node(p_path); + if (!Object::cast_to<Viewport>(to_node)) { + EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!")); + return; + } + + Ref<ViewportTexture> vt; + vt.instance(); + vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node)); + vt->setup_local_to_scene(); + + emit_changed(get_edited_property(), vt); + update_property(); +} + +void EditorPropertyResource::setup(Object *p_object, const String &p_path, const String &p_base_type) { + if (resource_picker) { + resource_picker->disconnect("resource_selected", callable_mp(this, &EditorPropertyResource::_resource_selected)); + resource_picker->disconnect("resource_changed", callable_mp(this, &EditorPropertyResource::_resource_changed)); + memdelete(resource_picker); + } + + if (p_path == "script" && p_base_type == "Script" && Object::cast_to<Node>(p_object)) { + EditorScriptPicker *script_picker = memnew(EditorScriptPicker); + script_picker->set_script_owner(Object::cast_to<Node>(p_object)); + resource_picker = script_picker; + } else { + resource_picker = memnew(EditorResourcePicker); + } + + resource_picker->set_base_type(p_base_type); + resource_picker->set_editable(true); + resource_picker->set_h_size_flags(SIZE_EXPAND_FILL); + add_child(resource_picker); + + resource_picker->connect("resource_selected", callable_mp(this, &EditorPropertyResource::_resource_selected)); + resource_picker->connect("resource_changed", callable_mp(this, &EditorPropertyResource::_resource_changed)); + + for (int i = 0; i < resource_picker->get_child_count(); i++) { + Button *b = Object::cast_to<Button>(resource_picker->get_child(i)); + if (b) { + add_focusable(b); + } + } +} + void EditorPropertyResource::update_property() { RES res = get_edited_object()->get(get_edited_property()); if (use_sub_inspector) { - if (res.is_valid() != assign->is_toggle_mode()) { - assign->set_toggle_mode(res.is_valid()); + if (res.is_valid() != resource_picker->is_toggle_mode()) { + resource_picker->set_toggle_mode(res.is_valid()); } if (res.is_valid() && get_edited_object()->editor_is_section_unfolded(get_edited_property())) { @@ -2935,7 +2609,7 @@ void EditorPropertyResource::update_property() { set_bottom_editor(sub_inspector_vbox); sub_inspector_vbox->add_child(sub_inspector); - assign->set_pressed(true); + resource_picker->set_toggle_pressed(true); bool use_editor = false; for (int i = 0; i < EditorNode::get_editor_data().get_editor_plugin_count(); i++) { @@ -2946,7 +2620,7 @@ void EditorPropertyResource::update_property() { } if (use_editor) { - //open editor directly and hide other open of these + // Open editor directly and hide other such editors which are currently open. _open_editor_pressed(); if (is_inside_tree()) { get_tree()->call_deferred("call_group", "_editor_resource_properties", "_fold_other_editors", this); @@ -2967,102 +2641,18 @@ void EditorPropertyResource::update_property() { memdelete(sub_inspector_vbox); sub_inspector = nullptr; sub_inspector_vbox = nullptr; + if (opened_editor) { EditorNode::get_singleton()->hide_top_editors(); opened_editor = false; } + _update_property_bg(); } } } - preview->set_texture(Ref<Texture2D>()); - if (res == RES()) { - assign->set_icon(Ref<Texture2D>()); - assign->set_text(TTR("[empty]")); - assign->set_custom_minimum_size(Size2(1, 1)); - } else { - assign->set_icon(EditorNode::get_singleton()->get_object_icon(res.operator->(), "Object")); - - if (res->get_name() != String()) { - assign->set_text(res->get_name()); - } else if (res->get_path().is_resource_file()) { - assign->set_text(res->get_path().get_file()); - assign->set_tooltip(res->get_path()); - } else { - assign->set_text(res->get_class()); - } - - if (res->get_path().is_resource_file()) { - assign->set_tooltip(res->get_path()); - } - - //preview will override the above, so called at the end - EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_resource_preview", res->get_instance_id()); - } -} - -void EditorPropertyResource::_resource_selected() { - RES res = get_edited_object()->get(get_edited_property()); - - if (res.is_null()) { - edit->set_pressed(true); - _update_menu(); - return; - } - - if (use_sub_inspector) { - bool unfold = !get_edited_object()->editor_is_section_unfolded(get_edited_property()); - get_edited_object()->editor_set_section_unfold(get_edited_property(), unfold); - update_property(); - } else { - emit_signal("resource_selected", get_edited_property(), res); - } -} - -void EditorPropertyResource::setup(const String &p_base_type) { - base_type = p_base_type; -} - -void EditorPropertyResource::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - if (updating_theme) { - return; - } - Ref<Texture2D> t = get_theme_icon("select_arrow", "Tree"); - edit->set_icon(t); - _update_property_bg(); - } - - if (p_what == NOTIFICATION_DRAG_BEGIN) { - if (_is_drop_valid(get_viewport()->gui_get_drag_data())) { - dropping = true; - assign->update(); - } - } - - if (p_what == NOTIFICATION_DRAG_END) { - if (dropping) { - dropping = false; - assign->update(); - } - } -} - -void EditorPropertyResource::_viewport_selected(const NodePath &p_path) { - Node *to_node = get_node(p_path); - if (!Object::cast_to<Viewport>(to_node)) { - EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!")); - return; - } - - Ref<ViewportTexture> vt; - vt.instance(); - vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node)); - vt->setup_local_to_scene(); - - emit_changed(get_edited_property(), vt); - update_property(); + resource_picker->set_edited_resource(res); } void EditorPropertyResource::collapse_all_folding() { @@ -3077,204 +2667,29 @@ void EditorPropertyResource::expand_all_folding() { } } -void EditorPropertyResource::_button_draw() { - if (dropping) { - Color color = get_theme_color("accent_color", "Editor"); - assign->draw_rect(Rect2(Point2(), assign->get_size()), color, false); - } -} - -Variant EditorPropertyResource::get_drag_data_fw(const Point2 &p_point, Control *p_from) { - RES res = get_edited_object()->get(get_edited_property()); - if (res.is_valid()) { - return EditorNode::get_singleton()->drag_resource(res, p_from); - } - - return Variant(); -} - -bool EditorPropertyResource::_is_drop_valid(const Dictionary &p_drag_data) const { - Vector<String> allowed_types = base_type.split(","); - int size = allowed_types.size(); - for (int i = 0; i < size; i++) { - String at = allowed_types[i].strip_edges(); - if (at == "StandardMaterial3D") { - allowed_types.append("Texture2D"); - } else if (at == "ShaderMaterial") { - allowed_types.append("Shader"); - } else if (at == "Font") { - allowed_types.append("FontData"); - } - } - - Dictionary drag_data = p_drag_data; - - Ref<Resource> res; - if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { - ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); - res = se->get_edited_resource(); - } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { - res = drag_data["resource"]; - } - - if (res.is_valid()) { - for (int i = 0; i < allowed_types.size(); i++) { - String at = allowed_types[i].strip_edges(); - if (ClassDB::is_parent_class(res->get_class(), at)) { - return true; - } - } - } - - if (drag_data.has("type") && String(drag_data["type"]) == "files") { - Vector<String> files = drag_data["files"]; - - if (files.size() == 1) { - String file = files[0]; - String ftype = EditorFileSystem::get_singleton()->get_file_type(file); - - if (ftype != "") { - for (int i = 0; i < allowed_types.size(); i++) { - String at = allowed_types[i].strip_edges(); - if (ClassDB::is_parent_class(ftype, at)) { - return true; - } - } - } - } - } - - return false; -} - -bool EditorPropertyResource::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { - return _is_drop_valid(p_data); +void EditorPropertyResource::set_use_sub_inspector(bool p_enable) { + use_sub_inspector = p_enable; } -void EditorPropertyResource::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { - ERR_FAIL_COND(!_is_drop_valid(p_data)); - - Dictionary drag_data = p_data; - - Ref<Resource> res; - if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { - ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); - res = se->get_edited_resource(); - } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { - res = drag_data["resource"]; - } - - if (!res.is_valid() && drag_data.has("type") && String(drag_data["type"]) == "files") { - Vector<String> files = drag_data["files"]; - - if (files.size() == 1) { - String file = files[0]; - res = ResourceLoader::load(file); - } - } - - if (res.is_valid()) { - bool need_convert = true; - - Vector<String> allowed_types = base_type.split(","); - for (int i = 0; i < allowed_types.size(); i++) { - String at = allowed_types[i].strip_edges(); - if (ClassDB::is_parent_class(res->get_class(), at)) { - need_convert = false; - break; - } - } - - if (need_convert) { - for (int i = 0; i < allowed_types.size(); i++) { - String at = allowed_types[i].strip_edges(); - if (at == "StandardMaterial3D" && ClassDB::is_parent_class(res->get_class(), "Texture2D")) { - Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D); - mat->set_texture(StandardMaterial3D::TextureParam::TEXTURE_ALBEDO, res); - res = mat; - break; - } - - if (at == "ShaderMaterial" && ClassDB::is_parent_class(res->get_class(), "Shader")) { - Ref<ShaderMaterial> mat = memnew(ShaderMaterial); - mat->set_shader(res); - res = mat; - break; - } - - if (at == "Font" && ClassDB::is_parent_class(res->get_class(), "FontData")) { - Ref<Font> font = memnew(Font); - font->add_data(res); - res = font; - break; - } +void EditorPropertyResource::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + if (!updating_theme) { + _update_property_bg(); } - } - - emit_changed(get_edited_property(), res); - update_property(); - return; + } break; } } -void EditorPropertyResource::set_use_sub_inspector(bool p_enable) { - use_sub_inspector = p_enable; -} - void EditorPropertyResource::_bind_methods() { - ClassDB::bind_method(D_METHOD("_resource_preview"), &EditorPropertyResource::_resource_preview); - ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &EditorPropertyResource::get_drag_data_fw); - ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &EditorPropertyResource::can_drop_data_fw); - ClassDB::bind_method(D_METHOD("drop_data_fw"), &EditorPropertyResource::drop_data_fw); ClassDB::bind_method(D_METHOD("_open_editor_pressed"), &EditorPropertyResource::_open_editor_pressed); ClassDB::bind_method(D_METHOD("_fold_other_editors"), &EditorPropertyResource::_fold_other_editors); } EditorPropertyResource::EditorPropertyResource() { - opened_editor = false; - sub_inspector = nullptr; - sub_inspector_vbox = nullptr; use_sub_inspector = bool(EDITOR_GET("interface/inspector/open_resources_in_current_inspector")); - HBoxContainer *hbc = memnew(HBoxContainer); - add_child(hbc); - assign = memnew(Button); - assign->set_flat(true); - assign->set_h_size_flags(SIZE_EXPAND_FILL); - assign->set_clip_text(true); - assign->connect("pressed", callable_mp(this, &EditorPropertyResource::_resource_selected)); - assign->set_drag_forwarding(this); - assign->connect("draw", callable_mp(this, &EditorPropertyResource::_button_draw)); - hbc->add_child(assign); - add_focusable(assign); - - preview = memnew(TextureRect); - preview->set_expand(true); - preview->set_anchors_and_offsets_preset(PRESET_WIDE); - preview->set_offset(SIDE_TOP, 1); - preview->set_offset(SIDE_BOTTOM, -1); - preview->set_offset(SIDE_RIGHT, -1); - // This is required to draw the focus outline in front of the preview, rather than behind. - preview->set_draw_behind_parent(true); - assign->add_child(preview); - assign->connect("gui_input", callable_mp(this, &EditorPropertyResource::_button_input)); - - menu = memnew(PopupMenu); - add_child(menu); - edit = memnew(Button); - edit->set_flat(true); - edit->set_toggle_mode(true); - menu->connect("id_pressed", callable_mp(this, &EditorPropertyResource::_menu_option)); - menu->connect("popup_hide", callable_mp((BaseButton *)edit, &BaseButton::set_pressed), varray(false)); - edit->connect("pressed", callable_mp(this, &EditorPropertyResource::_update_menu)); - hbc->add_child(edit); - edit->connect("gui_input", callable_mp(this, &EditorPropertyResource::_button_input)); - add_focusable(edit); - - file = nullptr; - scene_tree = nullptr; - dropping = false; - add_to_group("_editor_resource_properties"); } @@ -3751,7 +3166,7 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } break; case Variant::OBJECT: { EditorPropertyResource *editor = memnew(EditorPropertyResource); - editor->setup(p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource"); + editor->setup(p_object, p_path, p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource"); if (p_hint == PROPERTY_HINT_RESOURCE_TYPE) { String open_in_new = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 07a1e72319..07f496f54d 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -33,6 +33,7 @@ #include "editor/create_dialog.h" #include "editor/editor_inspector.h" +#include "editor/editor_resource_picker.h" #include "editor/editor_spin_slider.h" #include "editor/property_selector.h" #include "editor/scene_tree_editor.h" @@ -599,64 +600,26 @@ public: class EditorPropertyResource : public EditorProperty { GDCLASS(EditorPropertyResource, EditorProperty); - enum MenuOption { - OBJ_MENU_LOAD = 0, - OBJ_MENU_EDIT = 1, - OBJ_MENU_CLEAR = 2, - OBJ_MENU_MAKE_UNIQUE = 3, - OBJ_MENU_SAVE = 4, - OBJ_MENU_COPY = 5, - OBJ_MENU_PASTE = 6, - OBJ_MENU_NEW_SCRIPT = 7, - OBJ_MENU_EXTEND_SCRIPT = 8, - OBJ_MENU_SHOW_IN_FILE_SYSTEM = 9, - TYPE_BASE_ID = 100, - CONVERT_BASE_ID = 1000 + EditorResourcePicker *resource_picker = nullptr; + SceneTreeDialog *scene_tree = nullptr; - }; - - Button *assign; - TextureRect *preview; - Button *edit; - PopupMenu *menu; - EditorFileDialog *file; - Vector<String> inheritors_array; - EditorInspector *sub_inspector; - VBoxContainer *sub_inspector_vbox; - - bool use_sub_inspector; - bool dropping; - String base_type; + bool use_sub_inspector = false; + EditorInspector *sub_inspector = nullptr; + VBoxContainer *sub_inspector_vbox = nullptr; + bool updating_theme = false; + bool opened_editor = false; - SceneTreeDialog *scene_tree; + void _resource_selected(const RES &p_resource); + void _resource_changed(const RES &p_resource); - void _file_selected(const String &p_path); - void _menu_option(int p_which); - void _resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj); - void _resource_selected(); void _viewport_selected(const NodePath &p_path); - void _update_menu_items(); - - void _update_menu(); - void _sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool); void _sub_inspector_resource_selected(const RES &p_resource, const String &p_property); void _sub_inspector_object_id_selected(int p_id); - void _button_draw(); - Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); - bool _is_drop_valid(const Dictionary &p_drag_data) const; - bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; - void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); - - void _button_input(const Ref<InputEvent> &p_event); void _open_editor_pressed(); void _fold_other_editors(Object *p_self); - - bool opened_editor; - - bool updating_theme = false; void _update_property_bg(); protected: @@ -665,7 +628,7 @@ protected: public: virtual void update_property() override; - void setup(const String &p_base_type); + void setup(Object *p_object, const String &p_path, const String &p_base_type); void collapse_all_folding() override; void expand_all_folding() override; diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index fb2980c948..3bc29856f1 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -902,7 +902,7 @@ void EditorPropertyDictionary::update_property() { } else { EditorPropertyResource *editor = memnew(EditorPropertyResource); - editor->setup("Resource"); + editor->setup(object.ptr(), prop_name, "Resource"); prop = editor; } diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp new file mode 100644 index 0000000000..086afde07c --- /dev/null +++ b/editor/editor_resource_picker.cpp @@ -0,0 +1,862 @@ +/*************************************************************************/ +/* editor_resource_picker.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "editor_resource_picker.h" + +#include "editor/editor_resource_preview.h" +#include "editor_node.h" +#include "editor_scale.h" +#include "editor_settings.h" +#include "filesystem_dock.h" + +void EditorResourcePicker::_update_resource() { + preview_rect->set_texture(Ref<Texture2D>()); + assign_button->set_custom_minimum_size(Size2(1, 1)); + + if (edited_resource == RES()) { + assign_button->set_icon(Ref<Texture2D>()); + assign_button->set_text(TTR("[empty]")); + } else { + assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object")); + + if (edited_resource->get_name() != String()) { + assign_button->set_text(edited_resource->get_name()); + } else if (edited_resource->get_path().is_resource_file()) { + assign_button->set_text(edited_resource->get_path().get_file()); + assign_button->set_tooltip(edited_resource->get_path()); + } else { + assign_button->set_text(edited_resource->get_class()); + } + + if (edited_resource->get_path().is_resource_file()) { + assign_button->set_tooltip(edited_resource->get_path()); + } + + // Preview will override the above, so called at the end. + EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id()); + } +} + +void EditorResourcePicker::_update_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj) { + if (!edited_resource.is_valid() || edited_resource->get_instance_id() != p_obj) { + return; + } + + String type = edited_resource->get_class_name(); + if (ClassDB::is_parent_class(type, "Script")) { + assign_button->set_text(edited_resource->get_path().get_file()); + return; + } + + if (p_preview.is_valid()) { + preview_rect->set_offset(SIDE_LEFT, assign_button->get_icon()->get_width() + assign_button->get_theme_stylebox("normal")->get_default_margin(SIDE_LEFT) + get_theme_constant("hseparation", "Button")); + + if (type == "GradientTexture") { + preview_rect->set_stretch_mode(TextureRect::STRETCH_SCALE); + assign_button->set_custom_minimum_size(Size2(1, 1)); + } else { + preview_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); + int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); + thumbnail_size *= EDSCALE; + assign_button->set_custom_minimum_size(Size2(1, thumbnail_size)); + } + + preview_rect->set_texture(p_preview); + assign_button->set_text(""); + } +} + +void EditorResourcePicker::_resource_selected() { + if (edited_resource.is_null()) { + edit_button->set_pressed(true); + _update_menu(); + return; + } + + emit_signal("resource_selected", edited_resource); +} + +void EditorResourcePicker::_file_selected(const String &p_path) { + RES loaded_resource = ResourceLoader::load(p_path); + ERR_FAIL_COND_MSG(loaded_resource.is_null(), "Cannot load resource from path '" + p_path + "'."); + + if (base_type != "") { + bool any_type_matches = false; + + for (int i = 0; i < base_type.get_slice_count(","); i++) { + String base = base_type.get_slice(",", i); + if (loaded_resource->is_class(base)) { + any_type_matches = true; + break; + } + } + + if (!any_type_matches) { + EditorNode::get_singleton()->show_warning(vformat(TTR("The selected resource (%s) does not match any type expected for this property (%s)."), loaded_resource->get_class(), base_type)); + return; + } + } + + edited_resource = loaded_resource; + emit_signal("resource_changed", edited_resource); + _update_resource(); +} + +void EditorResourcePicker::_update_menu() { + _update_menu_items(); + + Rect2 gt = edit_button->get_screen_rect(); + edit_menu->set_as_minsize(); + int ms = edit_menu->get_contents_minimum_size().width; + Vector2 popup_pos = gt.position + gt.size - Vector2(ms, 0); + edit_menu->set_position(popup_pos); + edit_menu->popup(); +} + +void EditorResourcePicker::_update_menu_items() { + edit_menu->clear(); + + // Add options for creating specific subtypes of the base resource type. + set_create_options(edit_menu); + + // Add an option to load a resource from a file. + edit_menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD); + + // Add options for changing existing value of the resource. + if (edited_resource.is_valid()) { + edit_menu->add_icon_item(get_theme_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT); + edit_menu->add_icon_item(get_theme_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR); + edit_menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); + edit_menu->add_icon_item(get_theme_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE); + + if (edited_resource->get_path().is_resource_file()) { + edit_menu->add_separator(); + edit_menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM); + } + } + + // Add options to copy/paste resource. + RES cb = EditorSettings::get_singleton()->get_resource_clipboard(); + bool paste_valid = false; + if (cb.is_valid()) { + if (base_type == "") { + paste_valid = true; + } else { + for (int i = 0; i < base_type.get_slice_count(","); i++) { + if (ClassDB::is_parent_class(cb->get_class(), base_type.get_slice(",", i))) { + paste_valid = true; + break; + } + } + } + } + + if (edited_resource.is_valid() || paste_valid) { + edit_menu->add_separator(); + + if (edited_resource.is_valid()) { + edit_menu->add_item(TTR("Copy"), OBJ_MENU_COPY); + } + + if (paste_valid) { + edit_menu->add_item(TTR("Paste"), OBJ_MENU_PASTE); + } + } + + // Add options to convert existing resource to another type of resource. + if (edited_resource.is_valid()) { + Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(edited_resource); + if (conversions.size()) { + edit_menu->add_separator(); + } + for (int i = 0; i < conversions.size(); i++) { + String what = conversions[i]->converts_to(); + Ref<Texture2D> icon; + if (has_theme_icon(what, "EditorIcons")) { + icon = get_theme_icon(what, "EditorIcons"); + } else { + icon = get_theme_icon(what, "Resource"); + } + + edit_menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i); + } + } +} + +void EditorResourcePicker::_edit_menu_cbk(int p_which) { + switch (p_which) { + case OBJ_MENU_LOAD: { + List<String> extensions; + for (int i = 0; i < base_type.get_slice_count(","); i++) { + String base = base_type.get_slice(",", i); + ResourceLoader::get_recognized_extensions_for_type(base, &extensions); + } + + Set<String> valid_extensions; + for (List<String>::Element *E = extensions.front(); E; E = E->next()) { + valid_extensions.insert(E->get()); + } + + file_dialog->clear_filters(); + for (Set<String>::Element *E = valid_extensions.front(); E; E = E->next()) { + file_dialog->add_filter("*." + E->get() + " ; " + E->get().to_upper()); + } + + file_dialog->popup_file_dialog(); + } break; + + case OBJ_MENU_EDIT: { + if (edited_resource.is_valid()) { + emit_signal("resource_selected", edited_resource); + } + } break; + + case OBJ_MENU_CLEAR: { + edited_resource = RES(); + emit_signal("resource_changed", edited_resource); + _update_resource(); + } break; + + case OBJ_MENU_MAKE_UNIQUE: { + if (edited_resource.is_null()) { + return; + } + + List<PropertyInfo> property_list; + edited_resource->get_property_list(&property_list); + List<Pair<String, Variant>> propvalues; + for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) { + Pair<String, Variant> p; + PropertyInfo &pi = E->get(); + if (pi.usage & PROPERTY_USAGE_STORAGE) { + p.first = pi.name; + p.second = edited_resource->get(pi.name); + } + + propvalues.push_back(p); + } + + String orig_type = edited_resource->get_class(); + Object *inst = ClassDB::instance(orig_type); + Ref<Resource> unique_resource = Ref<Resource>(Object::cast_to<Resource>(inst)); + ERR_FAIL_COND(unique_resource.is_null()); + + for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) { + Pair<String, Variant> &p = E->get(); + unique_resource->set(p.first, p.second); + } + + edited_resource = unique_resource; + emit_signal("resource_changed", edited_resource); + _update_resource(); + } break; + + case OBJ_MENU_SAVE: { + if (edited_resource.is_null()) { + return; + } + EditorNode::get_singleton()->save_resource(edited_resource); + } break; + + case OBJ_MENU_COPY: { + EditorSettings::get_singleton()->set_resource_clipboard(edited_resource); + } break; + + case OBJ_MENU_PASTE: { + edited_resource = EditorSettings::get_singleton()->get_resource_clipboard(); + emit_signal("resource_changed", edited_resource); + _update_resource(); + } break; + + case OBJ_MENU_SHOW_IN_FILE_SYSTEM: { + FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock(); + file_system_dock->navigate_to_path(edited_resource->get_path()); + + // Ensure that the FileSystem dock is visible. + TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); + tab_container->set_current_tab(file_system_dock->get_index()); + } break; + + default: { + // Allow subclasses to handle their own options first, only then fallback on the default branch logic. + if (handle_menu_selected(p_which)) { + break; + } + + if (p_which >= CONVERT_BASE_ID) { + int to_type = p_which - CONVERT_BASE_ID; + Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(edited_resource); + ERR_FAIL_INDEX(to_type, conversions.size()); + + edited_resource = conversions[to_type]->convert(edited_resource); + emit_signal("resource_changed", edited_resource); + _update_resource(); + break; + } + + ERR_FAIL_COND(inheritors_array.is_empty()); + + String intype = inheritors_array[p_which - TYPE_BASE_ID]; + Variant obj; + + if (ScriptServer::is_global_class(intype)) { + obj = ClassDB::instance(ScriptServer::get_global_class_native_base(intype)); + if (obj) { + Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(intype)); + if (script.is_valid()) { + ((Object *)obj)->set_script(script); + } + } + } else { + obj = ClassDB::instance(intype); + } + + if (!obj) { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } + + Resource *resp = Object::cast_to<Resource>(obj); + ERR_BREAK(!resp); + + edited_resource = RES(resp); + emit_signal("resource_changed", edited_resource); + _update_resource(); + } break; + } +} + +void EditorResourcePicker::set_create_options(Object *p_menu_node) { + // If a subclass implements this method, use it to replace all create items. + if (get_script_instance() && get_script_instance()->has_method("set_create_options")) { + get_script_instance()->call("set_create_options", p_menu_node); + return; + } + + // By default provide generic "New ..." options. + if (base_type != "") { + int idx = 0; + + Set<String> allowed_types; + _get_allowed_types(false, &allowed_types); + + Vector<EditorData::CustomType> custom_resources; + if (EditorNode::get_editor_data().get_custom_types().has("Resource")) { + custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; + } + + for (Set<String>::Element *E = allowed_types.front(); E; E = E->next()) { + const String &t = E->get(); + + bool is_custom_resource = false; + Ref<Texture2D> icon; + if (!custom_resources.is_empty()) { + for (int j = 0; j < custom_resources.size(); j++) { + if (custom_resources[j].name == t) { + is_custom_resource = true; + if (custom_resources[j].icon.is_valid()) { + icon = custom_resources[j].icon; + } + break; + } + } + } + + if (!is_custom_resource && !(ScriptServer::is_global_class(t) || ClassDB::can_instance(t))) { + continue; + } + + inheritors_array.push_back(t); + + if (!icon.is_valid()) { + icon = get_theme_icon(has_theme_icon(t, "EditorIcons") ? t : "Object", "EditorIcons"); + } + + int id = TYPE_BASE_ID + idx; + edit_menu->add_icon_item(icon, vformat(TTR("New %s"), t), id); + + idx++; + } + + if (edit_menu->get_item_count()) { + edit_menu->add_separator(); + } + } +} + +bool EditorResourcePicker::handle_menu_selected(int p_which) { + if (get_script_instance() && get_script_instance()->has_method("handle_menu_selected")) { + return get_script_instance()->call("handle_menu_selected", p_which); + } + + return false; +} + +void EditorResourcePicker::_button_draw() { + if (dropping) { + Color color = get_theme_color("accent_color", "Editor"); + assign_button->draw_rect(Rect2(Point2(), assign_button->get_size()), color, false); + } +} + +void EditorResourcePicker::_button_input(const Ref<InputEvent> &p_event) { + if (!editable) { + return; + } + + Ref<InputEventMouseButton> mb = p_event; + + if (mb.is_valid()) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + _update_menu_items(); + + Vector2 pos = get_screen_position() + mb->get_position(); + edit_menu->set_as_minsize(); + edit_menu->set_position(pos); + edit_menu->popup(); + } + } +} + +void EditorResourcePicker::_get_allowed_types(bool p_with_convert, Set<String> *p_vector) const { + Vector<String> allowed_types = base_type.split(","); + int size = allowed_types.size(); + + List<StringName> global_classes; + ScriptServer::get_global_class_list(&global_classes); + + for (int i = 0; i < size; i++) { + String base = allowed_types[i].strip_edges(); + p_vector->insert(base); + + List<StringName> inheriters; + + ClassDB::get_inheriters_from_class(base, &inheriters); + for (List<StringName>::Element *E = inheriters.front(); E; E = E->next()) { + p_vector->insert(E->get()); + } + + for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) { + if (EditorNode::get_editor_data().script_class_is_parent(E->get(), base)) { + p_vector->insert(E->get()); + } + } + + if (p_with_convert) { + if (base == "StandardMaterial3D") { + p_vector->insert("Texture2D"); + } else if (base == "ShaderMaterial") { + p_vector->insert("Shader"); + } else if (base == "Font") { + p_vector->insert("FontData"); + } + } + } + + if (EditorNode::get_editor_data().get_custom_types().has("Resource")) { + Vector<EditorData::CustomType> custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; + + for (int i = 0; i < custom_resources.size(); i++) { + p_vector->insert(custom_resources[i].name); + } + } +} + +bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const { + if (base_type.is_empty()) { + return true; + } + + Dictionary drag_data = p_drag_data; + + Ref<Resource> res; + if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { + ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); + res = se->get_edited_resource(); + } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { + res = drag_data["resource"]; + } + + Set<String> allowed_types; + _get_allowed_types(true, &allowed_types); + + if (res.is_valid() && _is_type_valid(res->get_class(), allowed_types)) { + return true; + } + + if (res.is_valid() && res->get_script()) { + StringName custom_class = EditorNode::get_singleton()->get_object_custom_type_name(res->get_script()); + if (_is_type_valid(custom_class, allowed_types)) { + return true; + } + } + + if (drag_data.has("type") && String(drag_data["type"]) == "files") { + Vector<String> files = drag_data["files"]; + + if (files.size() == 1) { + String file = files[0]; + + String file_type = EditorFileSystem::get_singleton()->get_file_type(file); + if (file_type != "" && _is_type_valid(file_type, allowed_types)) { + return true; + } + } + } + + return false; +} + +bool EditorResourcePicker::_is_type_valid(const String p_type_name, Set<String> p_allowed_types) const { + for (Set<String>::Element *E = p_allowed_types.front(); E; E = E->next()) { + String at = E->get().strip_edges(); + if (p_type_name == at || ClassDB::is_parent_class(p_type_name, at) || EditorNode::get_editor_data().script_class_is_parent(p_type_name, at)) { + return true; + } + } + + return false; +} + +Variant EditorResourcePicker::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + if (edited_resource.is_valid()) { + return EditorNode::get_singleton()->drag_resource(edited_resource, p_from); + } + + return Variant(); +} + +bool EditorResourcePicker::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + return editable && _is_drop_valid(p_data); +} + +void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + ERR_FAIL_COND(!_is_drop_valid(p_data)); + + Dictionary drag_data = p_data; + + Ref<Resource> dropped_resource; + if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { + ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); + dropped_resource = se->get_edited_resource(); + } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { + dropped_resource = drag_data["resource"]; + } + + if (!dropped_resource.is_valid() && drag_data.has("type") && String(drag_data["type"]) == "files") { + Vector<String> files = drag_data["files"]; + + if (files.size() == 1) { + String file = files[0]; + dropped_resource = ResourceLoader::load(file); + } + } + + if (dropped_resource.is_valid()) { + Set<String> allowed_types; + _get_allowed_types(false, &allowed_types); + + // If the accepted dropped resource is from the extended list, it requires conversion. + if (!_is_type_valid(dropped_resource->get_class(), allowed_types)) { + for (Set<String>::Element *E = allowed_types.front(); E; E = E->next()) { + String at = E->get().strip_edges(); + + if (at == "StandardMaterial3D" && ClassDB::is_parent_class(dropped_resource->get_class(), "Texture2D")) { + Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D); + mat->set_texture(StandardMaterial3D::TextureParam::TEXTURE_ALBEDO, dropped_resource); + dropped_resource = mat; + break; + } + + if (at == "ShaderMaterial" && ClassDB::is_parent_class(dropped_resource->get_class(), "Shader")) { + Ref<ShaderMaterial> mat = memnew(ShaderMaterial); + mat->set_shader(dropped_resource); + dropped_resource = mat; + break; + } + + if (at == "Font" && ClassDB::is_parent_class(dropped_resource->get_class(), "FontData")) { + Ref<Font> font = memnew(Font); + font->add_data(dropped_resource); + dropped_resource = font; + break; + } + } + } + + edited_resource = dropped_resource; + emit_signal("resource_changed", edited_resource); + _update_resource(); + } +} + +void EditorResourcePicker::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update_resource_preview"), &EditorResourcePicker::_update_resource_preview); + ClassDB::bind_method(D_METHOD("get_drag_data_fw", "position", "from"), &EditorResourcePicker::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("can_drop_data_fw", "position", "data", "from"), &EditorResourcePicker::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("drop_data_fw", "position", "data", "from"), &EditorResourcePicker::drop_data_fw); + + ClassDB::bind_method(D_METHOD("set_base_type", "base_type"), &EditorResourcePicker::set_base_type); + ClassDB::bind_method(D_METHOD("get_base_type"), &EditorResourcePicker::get_base_type); + ClassDB::bind_method(D_METHOD("get_allowed_types"), &EditorResourcePicker::get_allowed_types); + ClassDB::bind_method(D_METHOD("set_edited_resource", "resource"), &EditorResourcePicker::set_edited_resource); + ClassDB::bind_method(D_METHOD("get_edited_resource"), &EditorResourcePicker::get_edited_resource); + ClassDB::bind_method(D_METHOD("set_toggle_mode", "enable"), &EditorResourcePicker::set_toggle_mode); + ClassDB::bind_method(D_METHOD("is_toggle_mode"), &EditorResourcePicker::is_toggle_mode); + ClassDB::bind_method(D_METHOD("set_toggle_pressed", "pressed"), &EditorResourcePicker::set_toggle_pressed); + ClassDB::bind_method(D_METHOD("set_editable", "enable"), &EditorResourcePicker::set_editable); + ClassDB::bind_method(D_METHOD("is_editable"), &EditorResourcePicker::is_editable); + + ClassDB::add_virtual_method(get_class_static(), MethodInfo("set_create_options", PropertyInfo(Variant::OBJECT, "menu_node"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo("handle_menu_selected", PropertyInfo(Variant::INT, "id"))); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type"), "set_base_type", "get_base_type"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource", 0), "set_edited_resource", "get_edited_resource"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode"); + + ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); + ADD_SIGNAL(MethodInfo("resource_changed", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); +} + +void EditorResourcePicker::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + _update_resource(); + [[fallthrough]]; + } + case NOTIFICATION_THEME_CHANGED: { + edit_button->set_icon(get_theme_icon("select_arrow", "Tree")); + } break; + + case NOTIFICATION_DRAW: { + draw_style_box(get_theme_stylebox("bg", "Tree"), Rect2(Point2(), get_size())); + } break; + + case NOTIFICATION_DRAG_BEGIN: { + if (editable && _is_drop_valid(get_viewport()->gui_get_drag_data())) { + dropping = true; + assign_button->update(); + } + } break; + + case NOTIFICATION_DRAG_END: { + if (dropping) { + dropping = false; + assign_button->update(); + } + } break; + } +} + +void EditorResourcePicker::set_base_type(const String &p_base_type) { + base_type = p_base_type; + + // There is a possibility that the new base type is conflicting with the existing value. + // Keep the value, but warn the user that there is a potential mistake. + if (!base_type.is_empty() && edited_resource.is_valid()) { + Set<String> allowed_types; + _get_allowed_types(true, &allowed_types); + + StringName custom_class; + bool is_custom = false; + if (edited_resource->get_script()) { + custom_class = EditorNode::get_singleton()->get_object_custom_type_name(edited_resource->get_script()); + is_custom = _is_type_valid(custom_class, allowed_types); + } + + if (!is_custom && !_is_type_valid(edited_resource->get_class(), allowed_types)) { + String class_str = (custom_class == StringName() ? edited_resource->get_class() : vformat("%s (%s)", custom_class, edited_resource->get_class())); + WARN_PRINT(vformat("Value mismatch between the new base type of this EditorResourcePicker, '%s', and the type of the value it already has, '%s'.", base_type, class_str)); + } + } +} + +String EditorResourcePicker::get_base_type() const { + return base_type; +} + +Vector<String> EditorResourcePicker::get_allowed_types() const { + Set<String> allowed_types; + _get_allowed_types(false, &allowed_types); + + Vector<String> types; + types.resize(allowed_types.size()); + + int i = 0; + String *w = types.ptrw(); + for (Set<String>::Element *E = allowed_types.front(); E; E = E->next(), i++) { + w[i] = E->get(); + } + + return types; +} + +void EditorResourcePicker::set_edited_resource(RES p_resource) { + if (!p_resource.is_valid()) { + edited_resource = RES(); + _update_resource(); + return; + } + + if (!base_type.is_empty()) { + Set<String> allowed_types; + _get_allowed_types(true, &allowed_types); + + StringName custom_class; + bool is_custom = false; + if (p_resource->get_script()) { + custom_class = EditorNode::get_singleton()->get_object_custom_type_name(p_resource->get_script()); + is_custom = _is_type_valid(custom_class, allowed_types); + } + + if (!is_custom && !_is_type_valid(p_resource->get_class(), allowed_types)) { + String class_str = (custom_class == StringName() ? p_resource->get_class() : vformat("%s (%s)", custom_class, p_resource->get_class())); + ERR_FAIL_MSG(vformat("Failed to set a resource of the type '%s' because this EditorResourcePicker only accepts '%s' and its derivatives.", class_str, base_type)); + } + } + + edited_resource = p_resource; + _update_resource(); +} + +RES EditorResourcePicker::get_edited_resource() { + return edited_resource; +} + +void EditorResourcePicker::set_toggle_mode(bool p_enable) { + assign_button->set_toggle_mode(p_enable); +} + +bool EditorResourcePicker::is_toggle_mode() const { + return assign_button->is_toggle_mode(); +} + +void EditorResourcePicker::set_toggle_pressed(bool p_pressed) { + if (!is_toggle_mode()) { + return; + } + + assign_button->set_pressed(p_pressed); +} + +void EditorResourcePicker::set_editable(bool p_editable) { + editable = p_editable; + assign_button->set_disabled(!editable); + edit_button->set_visible(editable); +} + +bool EditorResourcePicker::is_editable() const { + return editable; +} + +EditorResourcePicker::EditorResourcePicker() { + assign_button = memnew(Button); + assign_button->set_flat(true); + assign_button->set_h_size_flags(SIZE_EXPAND_FILL); + assign_button->set_clip_text(true); + assign_button->connect("pressed", callable_mp(this, &EditorResourcePicker::_resource_selected)); + assign_button->set_drag_forwarding(this); + assign_button->connect("draw", callable_mp(this, &EditorResourcePicker::_button_draw)); + add_child(assign_button); + + preview_rect = memnew(TextureRect); + preview_rect->set_expand(true); + preview_rect->set_anchors_and_offsets_preset(PRESET_WIDE); + preview_rect->set_offset(SIDE_TOP, 1); + preview_rect->set_offset(SIDE_BOTTOM, -1); + preview_rect->set_offset(SIDE_RIGHT, -1); + assign_button->add_child(preview_rect); + assign_button->connect("gui_input", callable_mp(this, &EditorResourcePicker::_button_input)); + + edit_menu = memnew(PopupMenu); + add_child(edit_menu); + edit_button = memnew(Button); + edit_button->set_flat(true); + edit_button->set_toggle_mode(true); + edit_menu->connect("id_pressed", callable_mp(this, &EditorResourcePicker::_edit_menu_cbk)); + edit_menu->connect("popup_hide", callable_mp((BaseButton *)edit_button, &BaseButton::set_pressed), varray(false)); + edit_button->connect("pressed", callable_mp(this, &EditorResourcePicker::_update_menu)); + add_child(edit_button); + edit_button->connect("gui_input", callable_mp(this, &EditorResourcePicker::_button_input)); + + file_dialog = memnew(EditorFileDialog); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); + add_child(file_dialog); + file_dialog->connect("file_selected", callable_mp(this, &EditorResourcePicker::_file_selected)); +} + +void EditorScriptPicker::set_create_options(Object *p_menu_node) { + PopupMenu *menu_node = Object::cast_to<PopupMenu>(p_menu_node); + if (!menu_node) { + return; + } + + menu_node->add_icon_item(get_theme_icon("ScriptCreate", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT); + menu_node->add_icon_item(get_theme_icon("ScriptExtend", "EditorIcons"), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT); + menu_node->add_separator(); +} + +bool EditorScriptPicker::handle_menu_selected(int p_which) { + switch (p_which) { + case OBJ_MENU_NEW_SCRIPT: { + if (script_owner) { + EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(script_owner, false); + } + return true; + } + + case OBJ_MENU_EXTEND_SCRIPT: { + if (script_owner) { + EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(script_owner, true); + } + return true; + } + } + + return false; +} + +void EditorScriptPicker::set_script_owner(Node *p_owner) { + script_owner = p_owner; +} + +Node *EditorScriptPicker::get_script_owner() const { + return script_owner; +} + +void EditorScriptPicker::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_script_owner", "owner_node"), &EditorScriptPicker::set_script_owner); + ClassDB::bind_method(D_METHOD("get_script_owner"), &EditorScriptPicker::get_script_owner); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "script_owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_script_owner", "get_script_owner"); +} + +EditorScriptPicker::EditorScriptPicker() { +} diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h new file mode 100644 index 0000000000..20fafe1780 --- /dev/null +++ b/editor/editor_resource_picker.h @@ -0,0 +1,141 @@ +/*************************************************************************/ +/* editor_resource_picker.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef EDITOR_RESOURCE_PICKER_H +#define EDITOR_RESOURCE_PICKER_H + +#include "editor_file_dialog.h" +#include "scene/gui/box_container.h" +#include "scene/gui/button.h" +#include "scene/gui/popup_menu.h" +#include "scene/gui/texture_rect.h" + +class EditorResourcePicker : public HBoxContainer { + GDCLASS(EditorResourcePicker, HBoxContainer); + + String base_type; + RES edited_resource; + + bool editable = true; + bool dropping = false; + + Vector<String> inheritors_array; + + Button *assign_button; + TextureRect *preview_rect; + Button *edit_button; + EditorFileDialog *file_dialog; + + enum MenuOption { + OBJ_MENU_LOAD, + OBJ_MENU_EDIT, + OBJ_MENU_CLEAR, + OBJ_MENU_MAKE_UNIQUE, + OBJ_MENU_SAVE, + OBJ_MENU_COPY, + OBJ_MENU_PASTE, + OBJ_MENU_SHOW_IN_FILE_SYSTEM, + + TYPE_BASE_ID = 100, + CONVERT_BASE_ID = 1000, + }; + + PopupMenu *edit_menu; + + void _update_resource(); + void _update_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj); + + void _resource_selected(); + void _file_selected(const String &p_path); + + void _update_menu(); + void _update_menu_items(); + void _edit_menu_cbk(int p_which); + + void _button_draw(); + void _button_input(const Ref<InputEvent> &p_event); + + void _get_allowed_types(bool p_with_convert, Set<String> *p_vector) const; + bool _is_drop_valid(const Dictionary &p_drag_data) const; + bool _is_type_valid(const String p_type_name, Set<String> p_allowed_types) const; + + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + void set_base_type(const String &p_base_type); + String get_base_type() const; + Vector<String> get_allowed_types() const; + + void set_edited_resource(RES p_resource); + RES get_edited_resource(); + + void set_toggle_mode(bool p_enable); + bool is_toggle_mode() const; + void set_toggle_pressed(bool p_pressed); + + void set_editable(bool p_editable); + bool is_editable() const; + + virtual void set_create_options(Object *p_menu_node); + virtual bool handle_menu_selected(int p_which); + + EditorResourcePicker(); +}; + +class EditorScriptPicker : public EditorResourcePicker { + GDCLASS(EditorScriptPicker, EditorResourcePicker); + + enum ExtraMenuOption { + OBJ_MENU_NEW_SCRIPT = 10, + OBJ_MENU_EXTEND_SCRIPT = 11 + }; + + Node *script_owner = nullptr; + +protected: + static void _bind_methods(); + +public: + virtual void set_create_options(Object *p_menu_node) override; + virtual bool handle_menu_selected(int p_which) override; + + void set_script_owner(Node *p_owner); + Node *get_script_owner() const; + + EditorScriptPicker(); +}; + +#endif // EDITOR_RESOURCE_PICKER_H diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp index f81c87be9e..7532f1c796 100644 --- a/editor/editor_sectioned_inspector.cpp +++ b/editor/editor_sectioned_inspector.cpp @@ -135,7 +135,7 @@ void SectionedInspector::_section_selected() { } selected_category = sections->get_selected()->get_metadata(0); - filter->set_section(selected_category, sections->get_selected()->get_children() == nullptr); + filter->set_section(selected_category, sections->get_selected()->get_first_child() == nullptr); inspector->set_property_prefix(selected_category + "/"); } @@ -187,8 +187,8 @@ void SectionedInspector::edit(Object *p_object) { TreeItem *first_item = sections->get_root(); if (first_item) { - while (first_item->get_children()) { - first_item = first_item->get_children(); + while (first_item->get_first_child()) { + first_item = first_item->get_first_child(); } first_item->select(0); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index aba14df812..0868c31c45 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1656,10 +1656,10 @@ Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p ie->set_unicode(p_keycode & KEY_CODE_MASK); ie->set_keycode(p_keycode & KEY_CODE_MASK); - ie->set_shift(bool(p_keycode & KEY_MASK_SHIFT)); - ie->set_alt(bool(p_keycode & KEY_MASK_ALT)); - ie->set_control(bool(p_keycode & KEY_MASK_CTRL)); - ie->set_metakey(bool(p_keycode & KEY_MASK_META)); + ie->set_shift_pressed(bool(p_keycode & KEY_MASK_SHIFT)); + ie->set_alt_pressed(bool(p_keycode & KEY_MASK_ALT)); + ie->set_ctrl_pressed(bool(p_keycode & KEY_MASK_CTRL)); + ie->set_meta_pressed(bool(p_keycode & KEY_MASK_META)); } if (!EditorSettings::get_singleton()) { diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index dba53a9708..942a2d35ab 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -96,7 +96,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { if (mm.is_valid()) { if (grabbing_spinner_attempt) { double diff_x = mm->get_relative().x; - if (mm->get_shift() && grabbing_spinner) { + if (mm->is_shift_pressed() && grabbing_spinner) { diff_x *= 0.1; } grabbing_spinner_dist_cache += diff_x; @@ -115,7 +115,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { pre_grab_value = get_max(); } - if (mm->get_control()) { + if (mm->is_ctrl_pressed()) { // If control was just pressed, don't make the value do a huge jump in magnitude. if (grabbing_spinner_dist_cache != 0) { pre_grab_value += grabbing_spinner_dist_cache * get_step(); diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp index d80003a12a..b04e518b0b 100644 --- a/editor/fileserver/editor_file_server.cpp +++ b/editor/fileserver/editor_file_server.cpp @@ -230,8 +230,7 @@ void EditorFileServer::_subthread_start(void *s) { cd->files[id]->seek(offset); Vector<uint8_t> buf; buf.resize(blocklen); - int read = cd->files[id]->get_buffer(buf.ptrw(), blocklen); - ERR_CONTINUE(read < 0); + uint32_t read = cd->files[id]->get_buffer(buf.ptrw(), blocklen); print_verbose("GET BLOCK - offset: " + itos(offset) + ", blocklen: " + itos(blocklen)); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 7ecfc5d520..a21a33a44a 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -180,12 +180,12 @@ Vector<String> FileSystemDock::_compute_uncollapsed_paths() { Vector<String> uncollapsed_paths; TreeItem *root = tree->get_root(); if (root) { - TreeItem *favorites_item = root->get_children(); + TreeItem *favorites_item = root->get_first_child(); if (!favorites_item->is_collapsed()) { uncollapsed_paths.push_back(favorites_item->get_metadata(0)); } - TreeItem *resTree = root->get_children()->get_next(); + TreeItem *resTree = root->get_first_child()->get_next(); if (resTree) { Vector<TreeItem *> needs_check; needs_check.push_back(resTree); @@ -193,7 +193,7 @@ Vector<String> FileSystemDock::_compute_uncollapsed_paths() { while (needs_check.size()) { if (!needs_check[0]->is_collapsed()) { uncollapsed_paths.push_back(needs_check[0]->get_metadata(0)); - TreeItem *child = needs_check[0]->get_children(); + TreeItem *child = needs_check[0]->get_first_child(); while (child) { needs_check.push_back(child); child = child->get_next(); @@ -464,7 +464,7 @@ void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_s return; } - TreeItem *favorites_item = tree->get_root()->get_children(); + TreeItem *favorites_item = tree->get_root()->get_first_child(); if (selected->get_parent() == favorites_item && !String(selected->get_metadata(0)).ends_with("/")) { // Go to the favorites if we click in the favorites and the path has changed. path = "Favorites"; @@ -860,7 +860,6 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { file_list.push_back(fi); } } - file_list.sort(); } // Sort the file list if needed. @@ -1644,7 +1643,7 @@ Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) { // Build a list of selected items with the active one at the first position. Vector<String> selected_strings; - TreeItem *favorites_item = tree->get_root()->get_children(); + TreeItem *favorites_item = tree->get_root()->get_first_child(); TreeItem *active_selected = tree->get_selected(); if (active_selected && active_selected != favorites_item) { selected_strings.push_back(active_selected->get_metadata(0)); @@ -1700,7 +1699,7 @@ void FileSystemDock::_tree_rmb_option(int p_option) { while (needs_check.size()) { needs_check[0]->set_collapsed(is_collapsed); - TreeItem *child = needs_check[0]->get_children(); + TreeItem *child = needs_check[0]->get_first_child(); while (child) { needs_check.push_back(child); child = child->get_next(); @@ -2062,13 +2061,13 @@ Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) // Check if the first selected is in favorite. TreeItem *selected = tree->get_next_selected(tree->get_root()); while (selected) { - TreeItem *favorites_item = tree->get_root()->get_children(); + TreeItem *favorites_item = tree->get_root()->get_first_child(); if (selected == favorites_item) { // The "Favorites" item is not draggable. return Variant(); } - bool is_favorite = selected->get_parent() != nullptr && tree->get_root()->get_children() == selected->get_parent(); + bool is_favorite = selected->get_parent() != nullptr && tree->get_root()->get_first_child() == selected->get_parent(); all_favorites &= is_favorite; all_not_favorites &= !is_favorite; selected = tree->get_next_selected(selected); @@ -2114,7 +2113,7 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da } int drop_section = tree->get_drop_section_at_position(p_point); - TreeItem *favorites_item = tree->get_root()->get_children(); + TreeItem *favorites_item = tree->get_root()->get_first_child(); TreeItem *resources_item = favorites_item->get_next(); @@ -2190,7 +2189,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, int drop_position; Vector<String> files = drag_data["files"]; - TreeItem *favorites_item = tree->get_root()->get_children(); + TreeItem *favorites_item = tree->get_root()->get_first_child(); TreeItem *resources_item = favorites_item->get_next(); if (ti == favorites_item) { @@ -2264,7 +2263,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, } } if (!to_move.is_empty()) { - if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { for (int i = 0; i < to_move.size(); i++) { String new_path; String new_path_base; @@ -2328,10 +2327,10 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori int section = tree->get_drop_section_at_position(p_point); if (ti) { // Check the favorites first. - if (ti == tree->get_root()->get_children() && section >= 0) { + if (ti == tree->get_root()->get_first_child() && section >= 0) { target_favorites = true; return; - } else if (ti->get_parent() == tree->get_root()->get_children()) { + } else if (ti->get_parent() == tree->get_root()->get_first_child()) { target_favorites = true; return; } else { @@ -2347,7 +2346,7 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori return; } } else { - if (ti->get_parent() != tree->get_root()->get_children()) { + if (ti->get_parent() != tree->get_root()->get_first_child()) { // Not in the favorite section. if (fpath != "res://") { // We drop between two files @@ -2735,12 +2734,12 @@ MenuButton *FileSystemDock::_create_file_menu_button() { PopupMenu *p = button->get_popup(); p->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_sort_popup)); - p->add_radio_check_item("Sort by Name (Ascending)", FILE_SORT_NAME); - p->add_radio_check_item("Sort by Name (Descending)", FILE_SORT_NAME_REVERSE); - p->add_radio_check_item("Sort by Type (Ascending)", FILE_SORT_TYPE); - p->add_radio_check_item("Sort by Type (Descending)", FILE_SORT_TYPE_REVERSE); - p->add_radio_check_item("Sort by Last Modified", FILE_SORT_MODIFIED_TIME); - p->add_radio_check_item("Sort by First Modified", FILE_SORT_MODIFIED_TIME_REVERSE); + p->add_radio_check_item(TTR("Sort by Name (Ascending)"), FILE_SORT_NAME); + p->add_radio_check_item(TTR("Sort by Name (Descending)"), FILE_SORT_NAME_REVERSE); + p->add_radio_check_item(TTR("Sort by Type (Ascending)"), FILE_SORT_TYPE); + p->add_radio_check_item(TTR("Sort by Type (Descending)"), FILE_SORT_TYPE_REVERSE); + p->add_radio_check_item(TTR("Sort by Last Modified"), FILE_SORT_MODIFIED_TIME); + p->add_radio_check_item(TTR("Sort by First Modified"), FILE_SORT_MODIFIED_TIME_REVERSE); p->set_item_checked(file_sort, true); return button; } diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index baaa5d21bf..d9b956ed08 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -530,7 +530,7 @@ void FindInFilesDialog::_on_replace_text_entered(String text) { void FindInFilesDialog::_on_folder_selected(String path) { int i = path.find("://"); if (i != -1) { - path = path.right(i + 3); + path = path.substr(i + 3); } _folder_line_edit->set_text(path); } @@ -840,7 +840,7 @@ void FindInFilesPanel::_on_replace_all_clicked() { String fpath = file_item->get_metadata(0); Vector<Result> locations; - for (TreeItem *item = file_item->get_children(); item; item = item->get_next()) { + for (TreeItem *item = file_item->get_first_child(); item; item = item->get_next()) { if (!item->is_checked(0)) { continue; } @@ -934,7 +934,7 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector<Result> continue; } - line = line.left(repl_begin) + new_text + line.right(repl_end); + line = line.left(repl_begin) + new_text + line.substr(repl_end); // keep an offset in case there are successive replaces in the same line offset += new_text.length() - (repl_end - repl_begin); } diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index f2a110ca03..d8e5a05c5d 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -52,7 +52,7 @@ void GroupDialog::_group_selected() { selected_group = groups->get_selected()->get_text(0); _load_nodes(scene_tree->get_edited_scene_root()); - group_empty->set_visible(!remove_node_root->get_children()); + group_empty->set_visible(!remove_node_root->get_first_child()); } void GroupDialog::_load_nodes(Node *p_current) { @@ -217,7 +217,7 @@ void GroupDialog::_group_renamed() { } const String name = renamed_group->get_text(0).strip_edges(); - for (TreeItem *E = groups_root->get_children(); E; E = E->get_next()) { + for (TreeItem *E = groups_root->get_first_child(); E; E = E->get_next()) { if (E != renamed_group && E->get_text(0) == name) { renamed_group->set_text(0, selected_group); error->set_text(TTR("Group name already exists.")); @@ -274,7 +274,7 @@ void GroupDialog::_rename_group_item(const String &p_old_name, const String &p_n selected_group = p_new_name; - for (TreeItem *E = groups_root->get_children(); E; E = E->get_next()) { + for (TreeItem *E = groups_root->get_first_child(); E; E = E->get_next()) { if (E->get_text(0) == p_old_name) { E->set_text(0, p_new_name); return; @@ -351,7 +351,7 @@ void GroupDialog::_delete_group_item(const String &p_name) { selected_group = ""; } - for (TreeItem *E = groups_root->get_children(); E; E = E->get_next()) { + for (TreeItem *E = groups_root->get_first_child(); E; E = E->get_next()) { if (E->get_text(0) == p_name) { groups_root->remove_child(E); return; diff --git a/editor/import/resource_importer_image.cpp b/editor/import/resource_importer_image.cpp index 26c6a8462b..fa6ce5fc89 100644 --- a/editor/import/resource_importer_image.cpp +++ b/editor/import/resource_importer_image.cpp @@ -75,7 +75,7 @@ Error ResourceImporterImage::import(const String &p_source_file, const String &p ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file from path '" + p_source_file + "'."); - size_t len = f->get_len(); + uint64_t len = f->get_len(); Vector<uint8_t> data; data.resize(len); diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 48340ac242..488c124c28 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -339,7 +339,7 @@ void SceneImportSettings::_update_scene() { material_tree->clear(); mesh_tree->clear(); - //hiden roots + //hidden roots material_tree->create_item(); mesh_tree->create_item(); diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 80d0a7db60..e6f7ec1fbf 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -266,7 +266,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) { if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { - if (mb->get_control() || mb->get_shift() || mb->get_alt()) { + if (mb->is_ctrl_pressed() || mb->is_shift_pressed() || mb->is_alt_pressed()) { return false; } @@ -399,7 +399,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint))); //Move the point in a single axis. Should only work when editing a polygon and while holding shift. - if (mode == MODE_EDIT && mm->get_shift()) { + if (mode == MODE_EDIT && mm->is_shift_pressed()) { Vector2 old_point = pre_move_edit.get(selected_point.vertex); if (ABS(cpoint.x - old_point.x) > ABS(cpoint.y - old_point.y)) { cpoint.y = old_point.y; diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 612a8f30a4..e459d2f756 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -1222,10 +1222,10 @@ void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { ERR_FAIL_COND(p_ev.is_null()); Ref<InputEventKey> k = p_ev; - if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo() && !k->get_alt() && !k->get_control() && !k->get_metakey()) { + if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo() && !k->is_alt_pressed() && !k->is_ctrl_pressed() && !k->is_meta_pressed()) { switch (k->get_keycode()) { case KEY_A: { - if (!k->get_shift()) { + if (!k->is_shift_pressed()) { _play_bw_from_pressed(); } else { _play_bw_pressed(); @@ -1237,7 +1237,7 @@ void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { accept_event(); } break; case KEY_D: { - if (!k->get_shift()) { + if (!k->is_shift_pressed()) { _play_from_pressed(); } else { _play_pressed(); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index a9709bbb16..c915276d3a 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -124,7 +124,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } // select node or push a field inside - if (mb.is_valid() && !mb->get_shift() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_shift_pressed() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { selected_transition_from = StringName(); selected_transition_to = StringName(); selected_node = StringName(); @@ -237,7 +237,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } //connect nodes - if (mb.is_valid() && ((tool_select->is_pressed() && mb->get_shift()) || tool_connect->is_pressed()) && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { + if (mb.is_valid() && ((tool_select->is_pressed() && mb->is_shift_pressed()) || tool_connect->is_pressed()) && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { for (int i = node_rects.size() - 1; i >= 0; i--) { //inverse to draw order if (node_rects[i].node.has_point(mb->get_position())) { //select node since nothing else was selected connecting = true; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 91022ccb2c..21bff41498 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -332,7 +332,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; - bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CTRL); // Smart snap using the canvas position Vector2 output = p_target; @@ -460,7 +460,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig } float CanvasItemEditor::snap_angle(float p_target, float p_start) const { - if (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) && snap_rotation_step != 0) { + if (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CTRL)) && snap_rotation_step != 0) { if (snap_relative) { return Math::snapped(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset + (p_start - (int)(p_start / snap_rotation_step) * snap_rotation_step); } else { @@ -481,11 +481,11 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { } if (k.is_valid()) { - if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT) { + if (k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT) { viewport->update(); } - if (k->is_pressed() && !k->get_control() && !k->is_echo()) { + if (k->is_pressed() && !k->is_ctrl_pressed() && !k->is_echo()) { if ((grid_snap_active || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) { // Multiply the grid size grid_step_multiplier = MIN(grid_step_multiplier + 1, 12); @@ -1269,12 +1269,12 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bool p_already_accepted) { Ref<InputEventMouseButton> b = p_event; if (b.is_valid() && !p_already_accepted) { - const bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->get_control(); + const bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->is_ctrl_pressed(); if (pan_on_scroll) { // Perform horizontal scrolling first so we can check for Shift being held. if (b->is_pressed() && - (b->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP))) { + (b->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || (b->is_shift_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP))) { // Pan left view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); @@ -1282,7 +1282,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo } if (b->is_pressed() && - (b->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN))) { + (b->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT || (b->is_shift_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN))) { // Pan right view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); @@ -1389,7 +1389,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid() && !p_already_accepted) { // If control key pressed, then zoom instead of pan - if (pan_gesture->get_control()) { + if (pan_gesture->is_ctrl_pressed()) { const float factor = pan_gesture->get_delta().y; zoom_widget->set_zoom_by_increments(1); @@ -1574,7 +1574,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { // Start rotation if (drag_type == DRAG_NONE) { if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { - if ((b->get_command() && !b->get_alt() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { + if ((b->is_command_pressed() && !b->is_alt_pressed() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { List<CanvasItem *> selection = _get_edited_canvas_items(); // Remove not movable nodes @@ -1740,7 +1740,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { Vector2 new_anchor = xform.xform(snap_point(previous_anchor + (drag_to - drag_from), SNAP_GRID | SNAP_OTHER_NODES, SNAP_NODE_PARENT | SNAP_NODE_SIDES | SNAP_NODE_CENTER, control)); new_anchor = _position_to_anchor(control, new_anchor).snapped(Vector2(0.001, 0.001)); - bool use_single_axis = m->get_shift(); + bool use_single_axis = m->is_shift_pressed(); Vector2 drag_vector = xform.xform(drag_to) - xform.xform(drag_from); bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x); @@ -1888,8 +1888,8 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { //Reset state canvas_item->_edit_set_state(se->undo_state); - bool uniform = m->get_shift(); - bool symmetric = m->get_alt(); + bool uniform = m->is_shift_pressed(); + bool symmetric = m->is_alt_pressed(); Rect2 local_rect = canvas_item->_edit_get_rect(); float aspect = local_rect.get_size().y / local_rect.get_size().x; @@ -2028,7 +2028,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { // Drag resize handles if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && ((b->get_alt() && b->get_control()) || tool == TOOL_SCALE)) { + if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && ((b->is_alt_pressed() && b->is_ctrl_pressed()) || tool == TOOL_SCALE)) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; @@ -2074,8 +2074,8 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { Transform2D unscaled_transform = (transform * parent_xform * canvas_item->_edit_get_transform()).orthonormalized(); Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform; - bool uniform = m->get_shift(); - bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool uniform = m->is_shift_pressed(); + bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL); Point2 drag_from_local = simple_xform.xform(drag_from); Point2 drag_to_local = simple_xform.xform(drag_to); @@ -2167,7 +2167,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_NONE) { //Start moving the nodes if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { - if ((b->get_alt() && !b->get_control()) || tool == TOOL_MOVE) { + if ((b->is_alt_pressed() && !b->is_ctrl_pressed()) || tool == TOOL_MOVE) { List<CanvasItem *> selection = _get_edited_canvas_items(); drag_selection.clear(); @@ -2235,7 +2235,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { new_pos.x = previous_pos.x; } - bool single_axis = m->get_shift(); + bool single_axis = m->is_shift_pressed(); if (single_axis) { if (ABS(new_pos.x - previous_pos.x) > ABS(new_pos.y - previous_pos.y)) { new_pos.y = previous_pos.y; @@ -2244,7 +2244,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } } - bool force_no_IK = m->get_alt(); + bool force_no_IK = m->is_alt_pressed(); int index = 0; for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); @@ -2335,8 +2335,8 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { _restore_canvas_item_state(drag_selection, true); - bool move_local_base = k->get_alt(); - bool move_local_base_rotated = k->get_control() || k->get_metakey(); + bool move_local_base = k->is_alt_pressed(); + bool move_local_base_rotated = k->is_ctrl_pressed() || k->is_meta_pressed(); Vector2 dir; if (k->get_keycode() == KEY_UP) { @@ -2348,12 +2348,12 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } else if (k->get_keycode() == KEY_RIGHT) { dir += Vector2(1, 0); } - if (k->get_shift()) { + if (k->is_shift_pressed()) { dir *= grid_step * Math::pow(2.0, grid_step_multiplier); } drag_to += dir; - if (k->get_shift()) { + if (k->is_shift_pressed()) { drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier)); } @@ -2442,18 +2442,18 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_NONE) { if (b.is_valid() && - ((b->get_button_index() == MOUSE_BUTTON_RIGHT && b->get_alt() && tool == TOOL_SELECT) || + ((b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_alt_pressed() && tool == TOOL_SELECT) || (b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_LIST_SELECT))) { // Popup the selection menu list Point2 click = transform.affine_inverse().xform(b->get_position()); - _get_canvas_items_at_pos(click, selection_results, b->get_alt() && tool != TOOL_LIST_SELECT); + _get_canvas_items_at_pos(click, selection_results, b->is_alt_pressed() && tool != TOOL_LIST_SELECT); if (selection_results.size() == 1) { CanvasItem *item = selection_results[0].item; selection_results.clear(); - _select_click_on_item(item, click, b->get_shift()); + _select_click_on_item(item, click, b->is_shift_pressed()); return true; } else if (!selection_results.is_empty()) { @@ -2497,14 +2497,14 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path); } - selection_menu_additive_selection = b->get_shift(); + selection_menu_additive_selection = b->is_shift_pressed(); selection_menu->set_position(get_screen_transform().xform(b->get_position())); selection_menu->popup(); return true; } } - if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->get_control()) { + if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_ctrl_pressed()) { add_node_menu->set_position(get_global_transform().xform(get_local_mouse_position())); add_node_menu->set_size(Vector2(1, 1)); add_node_menu->popup(); @@ -2540,7 +2540,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { if (!canvas_item) { // Start a box selection - if (!b->get_shift()) { + if (!b->is_shift_pressed()) { // Clear the selection if not additive editor_selection->clear(); viewport->update(); @@ -2552,7 +2552,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { box_selecting_to = drag_from; return true; } else { - bool still_selected = _select_click_on_item(canvas_item, click, b->get_shift()); + bool still_selected = _select_click_on_item(canvas_item, click, b->is_shift_pressed()); // Start dragging if (still_selected) { // Drag the node(s) if requested @@ -3574,7 +3574,7 @@ void CanvasItemEditor::_draw_selection() { } // Draw the move handles - bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL); bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT); if (tool == TOOL_MOVE && show_transformation_gizmos) { if (_is_node_movable(canvas_item)) { diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp index b50a497ccf..252e5c68a0 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp @@ -175,7 +175,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con case MODE_EDIT: { if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { - if (mb->get_control()) { + if (mb->is_ctrl_pressed()) { if (poly.size() < 3) { undo_redo->create_action(TTR("Edit Poly")); undo_redo->add_undo_method(node, "set_polygon", poly); @@ -317,7 +317,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con Vector2 cpoint(spoint.x, spoint.y); - if (snap_ignore && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (snap_ignore && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) { snap_ignore = false; } diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index db999f50ab..7a38fd2bd5 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -168,8 +168,8 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { // Snap to "round" coordinates when holding Ctrl. // Be more precise when holding Shift as well. float snap_threshold; - if (mm.get_control()) { - snap_threshold = mm.get_shift() ? 0.025 : 0.1; + if (mm.is_ctrl_pressed()) { + snap_threshold = mm.is_shift_pressed() ? 0.025 : 0.1; } else { snap_threshold = 0.0; } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 81f1852fba..ba39ce3aed 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -85,10 +85,10 @@ void ViewportRotationControl::_notification(int p_what) { axis_menu_options.clear(); axis_menu_options.push_back(Node3DEditorViewport::VIEW_RIGHT); axis_menu_options.push_back(Node3DEditorViewport::VIEW_TOP); - axis_menu_options.push_back(Node3DEditorViewport::VIEW_FRONT); + axis_menu_options.push_back(Node3DEditorViewport::VIEW_REAR); axis_menu_options.push_back(Node3DEditorViewport::VIEW_LEFT); axis_menu_options.push_back(Node3DEditorViewport::VIEW_BOTTOM); - axis_menu_options.push_back(Node3DEditorViewport::VIEW_REAR); + axis_menu_options.push_back(Node3DEditorViewport::VIEW_FRONT); axis_colors.clear(); axis_colors.push_back(get_theme_color("axis_x_color", "Editor")); @@ -309,7 +309,7 @@ void Node3DEditorViewport::_update_camera(float p_interp_delta) { bool manipulated = Input::get_singleton()->get_mouse_button_mask() & (2 | 4); manipulated |= Input::get_singleton()->is_key_pressed(KEY_SHIFT); manipulated |= Input::get_singleton()->is_key_pressed(KEY_ALT); - manipulated |= Input::get_singleton()->is_key_pressed(KEY_CONTROL); + manipulated |= Input::get_singleton()->is_key_pressed(KEY_CTRL); float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia); float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia); @@ -794,22 +794,22 @@ static int _get_key_modifier_setting(const String &p_property) { case 3: return KEY_META; case 4: - return KEY_CONTROL; + return KEY_CTRL; } return 0; } static int _get_key_modifier(Ref<InputEventWithModifiers> e) { - if (e->get_shift()) { + if (e->is_shift_pressed()) { return KEY_SHIFT; } - if (e->get_alt()) { + if (e->is_alt_pressed()) { return KEY_ALT; } - if (e->get_control()) { - return KEY_CONTROL; + if (e->is_ctrl_pressed()) { + return KEY_CTRL; } - if (e->get_metakey()) { + if (e->is_meta_pressed()) { return KEY_META; } return 0; @@ -1024,7 +1024,7 @@ bool Node3DEditorViewport ::_is_node_locked(const Node *p_node) { } void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) { - _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->get_shift()); + _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->is_shift_pressed()); Node *scene = editor->get_edited_scene(); @@ -1037,7 +1037,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) { } } - clicked_wants_append = b->get_shift(); + clicked_wants_append = b->is_shift_pressed(); if (selection_results.size() == 1) { clicked = selection_results[0].item->get_instance_id(); @@ -1149,7 +1149,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } if (_edit.mode == TRANSFORM_NONE && b->is_pressed()) { - if (b->get_alt()) { + if (b->is_alt_pressed()) { if (nav_scheme == NAVIGATION_MAYA) { break; } @@ -1234,7 +1234,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { case MOUSE_BUTTON_LEFT: { if (b->is_pressed()) { NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); - if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->get_alt()) { + if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->is_alt_pressed()) { break; } @@ -1262,7 +1262,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { int handle = -1; Vector3 point; Vector3 normal; - bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, b->get_shift()); + bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, b->is_shift_pressed()); if (inters && handle != -1) { _edit.gizmo = seg; _edit.gizmo_handle = handle; @@ -1279,7 +1279,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { clicked = ObjectID(); clicked_includes_current = false; - if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->get_command()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) { + if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) { /* HANDLE ROTATION */ if (get_selected_count() == 0) { break; //bye @@ -1314,11 +1314,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { int gizmo_handle = -1; - clicked = _select_ray(b->get_position(), b->get_shift(), clicked_includes_current, &gizmo_handle, b->get_shift()); + clicked = _select_ray(b->get_position(), b->is_shift_pressed(), clicked_includes_current, &gizmo_handle, b->is_shift_pressed()); //clicking is always deferred to either move or release - clicked_wants_append = b->get_shift(); + clicked_wants_append = b->is_shift_pressed(); if (clicked.is_null()) { if (!clicked_wants_append) { @@ -1441,13 +1441,13 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { set_message(n + ": " + String(v)); } else if (m->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { - if (nav_scheme == NAVIGATION_MAYA && m->get_alt()) { + if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) { nav_mode = NAVIGATION_ORBIT; - } else if (nav_scheme == NAVIGATION_MODO && m->get_alt() && m->get_shift()) { + } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed() && m->is_shift_pressed()) { nav_mode = NAVIGATION_PAN; - } else if (nav_scheme == NAVIGATION_MODO && m->get_alt() && m->get_control()) { + } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed() && m->is_ctrl_pressed()) { nav_mode = NAVIGATION_ZOOM; - } else if (nav_scheme == NAVIGATION_MODO && m->get_alt()) { + } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed()) { nav_mode = NAVIGATION_ORBIT; } else { if (clicked.is_valid()) { @@ -1831,7 +1831,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } } else if ((m->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) || freelook_active) { - if (nav_scheme == NAVIGATION_MAYA && m->get_alt()) { + if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) { nav_mode = NAVIGATION_ZOOM; } else if (freelook_active) { nav_mode = NAVIGATION_LOOK; @@ -1924,7 +1924,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } else if (nav_scheme == NAVIGATION_MAYA) { - if (pan_gesture->get_alt()) { + if (pan_gesture->is_alt_pressed()) { nav_mode = NAVIGATION_PAN; } } @@ -2053,7 +2053,7 @@ void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const real_t pan_speed = 1 / 150.0; int pan_speed_modifier = 10; - if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift()) { + if (nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) { pan_speed *= pan_speed_modifier; } @@ -2078,7 +2078,7 @@ void Node3DEditorViewport::_nav_zoom(Ref<InputEventWithModifiers> p_event, const real_t zoom_speed = 1 / 80.0; int zoom_speed_modifier = 10; - if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift()) { + if (nav_scheme == NAVIGATION_MAYA && p_event->is_shift_pressed()) { zoom_speed *= zoom_speed_modifier; } @@ -6204,7 +6204,7 @@ void Node3DEditor::_unhandled_key_input(Ref<InputEvent> p_event) { return; } - snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CTRL); } void Node3DEditor::_sun_environ_settings_pressed() { diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 84b4516452..208abeb87f 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -89,7 +89,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { // Check for point movement start (for point + in/out controls). if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { - if (mode == MODE_EDIT && !mb->get_shift() && dist_to_p < grab_threshold) { + if (mode == MODE_EDIT && !mb->is_shift_pressed() && dist_to_p < grab_threshold) { // Points can only be moved in edit mode. action = ACTION_MOVING_POINT; @@ -149,7 +149,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for point creation. - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && ((mb->is_command_pressed() && mode == MODE_EDIT) || mode == MODE_CREATE)) { Ref<Curve2D> curve = node->get_curve(); undo_redo->create_action(TTR("Add Point to Curve")); diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 47bd1114d2..8c73294723 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -316,7 +316,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref set_handle_clicked(false); } - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->get_control()))) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->is_ctrl_pressed()))) { //click into curve, break it down Vector<Vector3> v3a = c->tessellate(); int idx = 0; diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 470d897dcc..6d82685c05 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -613,11 +613,11 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } if (uv_move_current == UV_MODE_EDIT_POINT) { - if (mb->get_shift() && mb->get_command()) { + if (mb->is_shift_pressed() && mb->is_command_pressed()) { uv_move_current = UV_MODE_SCALE; - } else if (mb->get_shift()) { + } else if (mb->is_shift_pressed()) { uv_move_current = UV_MODE_MOVE; - } else if (mb->get_command()) { + } else if (mb->is_command_pressed()) { uv_move_current = UV_MODE_ROTATE; } } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 8c4c5a3461..1147267ce0 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -218,6 +218,8 @@ Ref<EditorSyntaxHighlighter> EditorPlainTextSyntaxHighlighter::_create() const { /*** SCRIPT EDITOR ****/ void ScriptEditorBase::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_base_editor"), &ScriptEditorBase::get_base_editor); + ADD_SIGNAL(MethodInfo("name_changed")); ADD_SIGNAL(MethodInfo("edited_script_changed")); ADD_SIGNAL(MethodInfo("request_help", PropertyInfo(Variant::STRING, "topic"))); @@ -337,13 +339,13 @@ void ScriptEditorQuickOpen::_update_search() { if ((search_box->get_text() == "" || file.findn(search_box->get_text()) != -1)) { TreeItem *ti = search_options->create_item(root); ti->set_text(0, file); - if (root->get_children() == ti) { + if (root->get_first_child() == ti) { ti->select(0); } } } - get_ok_button()->set_disabled(root->get_children() == nullptr); + get_ok_button()->set_disabled(root->get_first_child() == nullptr); } void ScriptEditorQuickOpen::_confirmed() { @@ -1501,6 +1503,9 @@ void ScriptEditor::_notification(int p_what) { filename->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("normal", "LineEdit")); recent_scripts->set_as_minsize(); + + _update_script_colors(); + _update_script_names(); } break; case NOTIFICATION_READY: { @@ -1675,7 +1680,7 @@ struct _ScriptEditorItemData { if (sort_key == id.sort_key) { return index < id.index; } else { - return sort_key < id.sort_key; + return sort_key.naturalnocasecmp_to(id.sort_key) < 0; } } else { return category < id.category; @@ -2279,8 +2284,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra void ScriptEditor::save_current_script() { ScriptEditorBase *current = _get_current_editor(); - - if (_test_script_times_on_disk()) { + if (!current || _test_script_times_on_disk()) { return; } diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 570ebfba4e..9ae63b7c4f 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -163,6 +163,8 @@ public: virtual Control *get_edit_menu() = 0; virtual void clear_edit_menu() = 0; + virtual Control *get_base_editor() const = 0; + virtual void validate() = 0; ScriptEditorBase() {} diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index edf540bf48..25755cc6cc 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1402,6 +1402,10 @@ void ScriptTextEditor::set_tooltip_request_func(String p_method, Object *p_obj) void ScriptTextEditor::set_debugger_active(bool p_active) { } +Control *ScriptTextEditor::get_base_editor() const { + return code_editor->get_text_editor(); +} + Variant ScriptTextEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { return Variant(); } diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index 17abfcf4cc..f79abc60ab 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -233,6 +233,8 @@ public: virtual void clear_edit_menu() override; static void register_editor(); + virtual Control *get_base_editor() const override; + virtual void validate() override; ScriptTextEditor(); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index bd6dac7490..551d1c027a 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -115,7 +115,7 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) { int idx = h * y + x; - if (mb->get_shift() && last_frame_selected >= 0) { + if (mb->is_shift_pressed() && last_frame_selected >= 0) { //select multiple int from = idx; int to = last_frame_selected; @@ -124,7 +124,7 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) { } for (int i = from; i <= to; i++) { - if (mb->get_control()) { + if (mb->is_ctrl_pressed()) { frames_selected.erase(i); } else { frames_selected.insert(i); @@ -150,11 +150,11 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) { // Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer // to allow performing this action anywhere, even if the cursor isn't // hovering the texture in the workspace. - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->is_ctrl_pressed()) { _sheet_zoom_in(); // Don't scroll up after zooming in. accept_event(); - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->is_ctrl_pressed()) { _sheet_zoom_out(); // Don't scroll down after zooming out. accept_event(); @@ -513,7 +513,7 @@ void SpriteFramesEditor::_animation_select() { if (frames->has_animation(edited_anim)) { double value = anim_speed->get_line_edit()->get_text().to_float(); - if (!Math::is_equal_approx(value, frames->get_animation_speed(edited_anim))) { + if (!Math::is_equal_approx(value, (double)frames->get_animation_speed(edited_anim))) { _animation_fps_changed(value); } } @@ -694,11 +694,11 @@ void SpriteFramesEditor::_tree_input(const Ref<InputEvent> &p_event) { const Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->is_ctrl_pressed()) { _zoom_in(); // Don't scroll up after zooming in. accept_event(); - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->is_ctrl_pressed()) { _zoom_out(); // Don't scroll down after zooming out. accept_event(); @@ -954,7 +954,7 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da if (String(d["type"]) == "files") { Vector<String> files = d["files"]; - if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { _prepare_sprite_sheet(files[0]); } else { _file_load_request(files, at_pos); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 2b8bfe067d..e6fb2710ae 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -171,6 +171,10 @@ void TextEditor::add_callback(const String &p_function, PackedStringArray p_args void TextEditor::set_debugger_active(bool p_active) { } +Control *TextEditor::get_base_editor() const { + return code_editor->get_text_editor(); +} + Array TextEditor::get_breakpoints() { return Array(); } diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index c066d51b18..abb75cc9d8 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -142,6 +142,8 @@ public: virtual void validate() override; + virtual Control *get_base_editor() const override; + static void register_editor(); TextEditor(); diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 7b927ad98b..62ecdb8c32 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -331,7 +331,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) { if (E->get().has_point(point)) { rect = E->get(); - if (Input::get_singleton()->is_key_pressed(KEY_CONTROL) && !(Input::get_singleton()->is_key_pressed(KEY_SHIFT | KEY_ALT))) { + if (Input::get_singleton()->is_key_pressed(KEY_CTRL) && !(Input::get_singleton()->is_key_pressed(KEY_SHIFT | KEY_ALT))) { Rect2 r; if (node_sprite) { r = node_sprite->get_region_rect(); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 0f7468bead..f1c73f99dc 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -321,7 +321,7 @@ void ThemeItemImportTree::_toggle_type_items(bool p_collapse) { return; } - TreeItem *type_node = root->get_children(); + TreeItem *type_node = root->get_first_child(); while (type_node) { type_node->set_collapsed(p_collapse); type_node = type_node->get_next(); @@ -491,7 +491,7 @@ void ThemeItemImportTree::_tree_item_edited() { } void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_select_with_data) { - TreeItem *child_item = p_root_item->get_children(); + TreeItem *child_item = p_root_item->get_first_child(); while (child_item) { child_item->set_checked(IMPORT_ITEM, true); if (p_select_with_data) { @@ -505,7 +505,7 @@ void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_sel } void ThemeItemImportTree::_deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely) { - TreeItem *child_item = p_root_item->get_children(); + TreeItem *child_item = p_root_item->get_first_child(); while (child_item) { child_item->set_checked(IMPORT_ITEM_DATA, false); if (p_deselect_completely) { @@ -527,7 +527,7 @@ void ThemeItemImportTree::_update_parent_items(TreeItem *p_root_item) { bool any_checked = false; bool any_checked_with_data = false; - TreeItem *child_item = parent_item->get_children(); + TreeItem *child_item = parent_item->get_first_child(); while (child_item) { if (child_item->is_checked(IMPORT_ITEM)) { any_checked = true; diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 4f7eabac24..6e82951d3d 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -41,7 +41,7 @@ #include "editor/editor_scale.h" void TileAtlasView::_gui_input(const Ref<InputEvent> &p_event) { - bool ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL); Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { @@ -195,9 +195,9 @@ void TileAtlasView::_base_tiles_root_control_gui_input(const Ref<InputEvent> &p_ if (mm.is_valid()) { Transform2D xform = base_tiles_drawing_root->get_transform().affine_inverse(); Vector2i coords = get_atlas_tile_coords_at_pos(xform.xform(mm->get_position())); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { coords = tile_set_atlas_source->get_tile_at_coords(coords); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { base_tiles_root_control->set_tooltip(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: 0"), source_id, coords)); } } @@ -215,7 +215,7 @@ void TileAtlasView::_draw_base_tiles() { for (int x = 0; x < grid_size.x; x++) { for (int y = 0; y < grid_size.y; y++) { Vector2i coords = Vector2i(x, y); - if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) { Rect2i rect = Rect2i(texture_region_size * coords + margins, texture_region_size); base_tiles_draw->draw_texture_rect_region(texture, rect, rect); } @@ -229,17 +229,23 @@ void TileAtlasView::_draw_base_tiles() { rect.set_end(Vector2i(texture->get_size().x, margins.y)); base_tiles_draw->draw_texture_rect_region(texture, rect, rect); // Bottom - rect.position = Vector2i(0, margins.y + (grid_size.y * texture_region_size.y)); - rect.set_end(texture->get_size()); - base_tiles_draw->draw_texture_rect_region(texture, rect, rect); + int bottom_border = margins.y + (grid_size.y * texture_region_size.y); + if (bottom_border < texture->get_size().y) { + rect.position = Vector2i(0, bottom_border); + rect.set_end(texture->get_size()); + base_tiles_draw->draw_texture_rect_region(texture, rect, rect); + } // Left rect.position = Vector2i(0, margins.y); rect.set_end(Vector2i(margins.x, margins.y + (grid_size.y * texture_region_size.y))); base_tiles_draw->draw_texture_rect_region(texture, rect, rect); // Right. - rect.position = Vector2i(margins.x + (grid_size.x * texture_region_size.x), margins.y); - rect.set_end(Vector2i(texture->get_size().x, margins.y + (grid_size.y * texture_region_size.y))); - base_tiles_draw->draw_texture_rect_region(texture, rect, rect); + int right_border = margins.x + (grid_size.x * texture_region_size.x); + if (right_border < texture->get_size().x) { + rect.position = Vector2i(right_border, margins.y); + rect.set_end(Vector2i(texture->get_size().x, margins.y + (grid_size.y * texture_region_size.y))); + base_tiles_draw->draw_texture_rect_region(texture, rect, rect); + } // Draw actual tiles, using their properties (modulation, etc...) for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) { @@ -249,7 +255,7 @@ void TileAtlasView::_draw_base_tiles() { Vector2i offset_pos = (margins + (atlas_coords * texture_region_size) + tile_set_atlas_source->get_tile_texture_region(atlas_coords).size / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, 0)); // Draw the tile. - TileSetAtlasPluginRendering::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0); + TileSetPluginAtlasRendering::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0); } } } @@ -268,7 +274,7 @@ void TileAtlasView::_draw_base_tiles_texture_grid() { for (int y = 0; y < grid_size.y; y++) { Vector2i origin = margins + (Vector2i(x, y) * (texture_region_size + separation)); Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y)); - if (base_tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) { if (base_tile_coords == Vector2i(x, y)) { // Draw existing tile. Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(base_tile_coords); @@ -299,7 +305,7 @@ void TileAtlasView::_draw_base_tiles_dark() { Vector2i origin = margins + (Vector2i(x, y) * (texture_region_size + separation)); Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y)); - if (base_tile_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (base_tile_coords == TileSetSource::INVALID_ATLAS_COORDS) { // Draw the grid. base_tiles_dark->draw_rect(Rect2i(origin, texture_region_size), Color(0.0, 0.0, 0.0, 0.5), true); } @@ -331,7 +337,7 @@ void TileAtlasView::_alternative_tiles_root_control_gui_input(const Ref<InputEve Vector3i coords3 = get_alternative_tile_at_pos(xform.xform(mm->get_position())); Vector2i coords = Vector2i(coords3.x, coords3.y); int alternative_id = coords3.z; - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && alternative_id != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative_id != TileSetSource::INVALID_TILE_ALTERNATIVE) { alternative_tiles_root_control->set_tooltip(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: %d"), source_id, coords, alternative_id)); } } @@ -364,7 +370,7 @@ void TileAtlasView::_draw_alternatives() { } // Draw the tile. - TileSetAtlasPluginRendering::draw_tile(alternatives_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, alternative_id); + TileSetPluginAtlasRendering::draw_tile(alternatives_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, alternative_id); // Increment the x position. current_pos.x += transposed ? texture_region.size.y : texture_region.size.x; @@ -464,7 +470,7 @@ Vector2i TileAtlasView::get_atlas_tile_coords_at_pos(const Vector2 p_pos) const return ret; } - return TileSetAtlasSource::INVALID_ATLAS_COORDS; + return TileSetSource::INVALID_ATLAS_COORDS; } void TileAtlasView::_update_alternative_tiles_rect_cache() { @@ -506,7 +512,7 @@ Vector3i TileAtlasView::get_alternative_tile_at_pos(const Vector2 p_pos) const { } } - return Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + return Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE); } Rect2i TileAtlasView::get_alternative_tile_rect(const Vector2i p_coords, int p_alternative_tile) { diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 0b674bec39..d2665a3a2b 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -166,7 +166,7 @@ void TileDataTerrainsEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform Vector<String> components = String(p_property).split("/", true); if (components[0] == "terrain_mode" || components[0] == "terrain" || components[0] == "terrains_peering_bit") { - TileSetAtlasPluginTerrain::draw_terrains(p_canvas_item, p_transform, p_tile_set, tile_data); + TileSetPluginAtlasTerrain::draw_terrains(p_canvas_item, p_transform, p_tile_set, tile_data); } } diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 5937472e2b..80ba396936 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -32,6 +32,7 @@ #include "tiles_editor_plugin.h" +#include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" #include "editor/plugins/canvas_item_editor_plugin.h" @@ -55,7 +56,7 @@ void TileMapEditorTilesPlugin::_notification(int p_what) { picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons")); erase_button->set_icon(get_theme_icon("Eraser", "EditorIcons")); - missing_texture_texture = get_theme_icon("TileSet", "EditorIcons"); + missing_atlas_texture_icon = get_theme_icon("TileSet", "EditorIcons"); break; case NOTIFICATION_VISIBILITY_CHANGED: _stop_dragging(); @@ -64,9 +65,8 @@ void TileMapEditorTilesPlugin::_notification(int p_what) { void TileMapEditorTilesPlugin::tile_set_changed() { _update_fix_selected_and_hovered(); - _update_bottom_panel(); _update_tile_set_sources_list(); - _update_atlas_view(); + _update_bottom_panel(); } void TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled(bool p_pressed) { @@ -146,19 +146,38 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { for (int i = 0; i < tile_set->get_source_count(); i++) { int source_id = tile_set->get_source_id(i); - // TODO: handle with virtual functions TileSetSource *source = *tile_set->get_source(source_id); + + Ref<Texture2D> texture; + String item_text; + + // Atlas source. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { - Ref<Texture2D> texture = atlas_source->get_texture(); + texture = atlas_source->get_texture(); if (texture.is_valid()) { - sources_list->add_item(vformat("%s - (id:%d)", texture->get_path().get_file(), source_id), texture); + item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id); } else { - sources_list->add_item(vformat("No Texture Atlas Source - (id:%d)", source_id), missing_texture_texture); + item_text = vformat("No Texture Atlas Source (id:%d)", source_id); } - } else { - sources_list->add_item(vformat("Unknown Type Source - (id:%d)", source_id), missing_texture_texture); } + + // Scene collection source. + TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); + if (scene_collection_source) { + texture = get_theme_icon("PackedScene", "EditorIcons"); + item_text = vformat(TTR("Scene Collection Source (id:%d)"), source_id); + } + + // Use default if not valid. + if (item_text.is_empty()) { + item_text = vformat(TTR("Unknown Type Source (id:%d)"), source_id); + } + if (!texture.is_valid()) { + texture = missing_atlas_texture_icon; + } + + sources_list->add_item(item_text, texture); sources_list->set_item_metadata(i, source_id); } @@ -176,7 +195,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { TilesEditor::get_singleton()->set_atlas_sources_lists_current(sources_list->get_current()); } -void TileMapEditorTilesPlugin::_update_atlas_view() { +void TileMapEditorTilesPlugin::_update_bottom_panel() { // Update the atlas display. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { @@ -185,39 +204,161 @@ void TileMapEditorTilesPlugin::_update_atlas_view() { Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { - tile_atlas_view->hide(); return; } int source_index = sources_list->get_current(); if (source_index >= 0 && source_index < sources_list->get_item_count()) { + atlas_sources_split_container->show(); + missing_source_label->hide(); + int source_id = sources_list->get_item_metadata(source_index); TileSetSource *source = *tile_set->get_source(source_id); TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); + if (atlas_source) { - tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id); tile_atlas_view->show(); + scene_tiles_list->hide(); + invalid_source_label->hide(); + _update_atlas_view(); + } else if (scenes_collection_source) { + tile_atlas_view->hide(); + scene_tiles_list->show(); + invalid_source_label->hide(); + _update_scenes_collection_view(); + } else { + tile_atlas_view->hide(); + scene_tiles_list->hide(); + invalid_source_label->show(); } } else { + atlas_sources_split_container->hide(); + missing_source_label->show(); + tile_atlas_view->hide(); + scene_tiles_list->hide(); + invalid_source_label->hide(); } +} - // Synchronize atlas view. - TilesEditor::get_singleton()->synchronize_atlas_view(tile_atlas_view); +void TileMapEditorTilesPlugin::_update_atlas_view() { + TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); + if (!tile_map) { + return; + } + Ref<TileSet> tile_set = tile_map->get_tileset(); + if (!tile_set.is_valid()) { + return; + } + + int source_id = sources_list->get_item_metadata(sources_list->get_current()); + TileSetSource *source = *tile_set->get_source(source_id); + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + ERR_FAIL_COND(!atlas_source); + + tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id); + TilesEditor::get_singleton()->synchronize_atlas_view(tile_atlas_view); tile_atlas_control->update(); } -void TileMapEditorTilesPlugin::_update_bottom_panel() { +void TileMapEditorTilesPlugin::_update_scenes_collection_view() { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { return; } + Ref<TileSet> tile_set = tile_map->get_tileset(); + if (!tile_set.is_valid()) { + return; + } + + int source_id = sources_list->get_item_metadata(sources_list->get_current()); + TileSetSource *source = *tile_set->get_source(source_id); + TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); + ERR_FAIL_COND(!scenes_collection_source); + + // Clear the list. + scene_tiles_list->clear(); + + // Rebuild the list. + for (int i = 0; i < scenes_collection_source->get_scene_tiles_count(); i++) { + int scene_id = scenes_collection_source->get_scene_tile_id(i); + + Ref<PackedScene> scene = scenes_collection_source->get_scene_tile_scene(scene_id); + + int item_index = 0; + if (scene.is_valid()) { + item_index = scene_tiles_list->add_item(vformat("%s (path:%s id:%d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id)); + Variant udata = i; + EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata); + } else { + item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon("PackedScene", "EditorIcons")); + } + scene_tiles_list->set_item_metadata(item_index, scene_id); - // Update the tabs. - missing_source_label->set_visible(tile_set.is_valid() && tile_set->get_source_count() == 0); - atlas_sources_split_container->set_visible(tile_set.is_valid() && tile_set->get_source_count() > 0); + // Check if in selection. + if (tile_set_selection.has(TileMapCell(source_id, Vector2i(), scene_id))) { + scene_tiles_list->select(item_index, false); + } + } + + // Icon size update. + int int_size = int(EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size")) * EDSCALE; + scene_tiles_list->set_fixed_icon_size(Vector2(int_size, int_size)); +} + +void TileMapEditorTilesPlugin::_scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud) { + int index = p_ud; + + if (index >= 0 && index < scene_tiles_list->get_item_count()) { + scene_tiles_list->set_item_icon(index, p_preview); + } +} + +void TileMapEditorTilesPlugin::_scenes_list_multi_selected(int p_index, bool p_selected) { + TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); + if (!tile_map) { + return; + } + + Ref<TileSet> tile_set = tile_map->get_tileset(); + if (!tile_set.is_valid()) { + return; + } + + // Add or remove the Tile form the selection. + int scene_id = scene_tiles_list->get_item_metadata(p_index); + int source_id = sources_list->get_item_metadata(sources_list->get_current()); + TileSetSource *source = *tile_set->get_source(source_id); + TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); + ERR_FAIL_COND(!scenes_collection_source); + + TileMapCell selected = TileMapCell(source_id, Vector2i(), scene_id); + + // Clear the selection if shift is not pressed. + if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + tile_set_selection.clear(); + } + + if (p_selected) { + tile_set_selection.insert(selected); + } else { + if (tile_set_selection.has(selected)) { + tile_set_selection.erase(selected); + } + } + + _update_selection_pattern_from_tileset_selection(); +} + +void TileMapEditorTilesPlugin::_scenes_list_nothing_selected() { + scene_tiles_list->deselect_all(); + tile_set_selection.clear(); + tile_map_selection.clear(); + selection_pattern->clear(); + _update_selection_pattern_from_tileset_selection(); } bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { @@ -257,7 +398,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p if (!tile_map_selection.is_empty()) { undo_redo->create_action(TTR("Delete tiles")); for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get())); } undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection()); @@ -288,7 +429,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p if (!tile_map_selection.is_empty()) { undo_redo->create_action(TTR("Delete tiles")); for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get())); } undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection()); @@ -357,14 +498,14 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p // Pressed if (tool_buttons_group->get_pressed_button() == select_tool_button) { drag_start_mouse_pos = mpos; - if (tile_map_selection.has(tile_map->world_to_map(drag_start_mouse_pos)) && !mb->get_shift()) { + if (tile_map_selection.has(tile_map->world_to_map(drag_start_mouse_pos)) && !mb->is_shift_pressed()) { // Move the selection drag_type = DRAG_TYPE_MOVE; drag_modified.clear(); for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { Vector2i coords = E->get(); drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords))); - tile_map->set_cell(coords, -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + tile_map->set_cell(coords, -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); } } else { // Select tiles @@ -460,14 +601,14 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Draw the selection. if (is_visible_in_tree() && tool_buttons_group->get_pressed_button() == select_tool_button) { // In select mode, we only draw the current selection if we are modifying it (pressing control or shift). - if (drag_type == DRAG_TYPE_MOVE || (drag_type == DRAG_TYPE_SELECT && !Input::get_singleton()->is_key_pressed(KEY_CONTROL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + if (drag_type == DRAG_TYPE_MOVE || (drag_type == DRAG_TYPE_SELECT && !Input::get_singleton()->is_key_pressed(KEY_CTRL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { // Do nothing } else { tile_map->draw_cells_outline(p_overlay, tile_map_selection, Color(0.0, 0.0, 1.0), xform); } } - // handle the preview of the tiles to be placed. + // Handle the preview of the tiles to be placed. if (is_visible_in_tree() && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered. Map<Vector2i, TileMapCell> preview; Rect2i drawn_grid_rect; @@ -583,11 +724,10 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Draw the preview. for (Map<Vector2i, TileMapCell>::Element *E = preview.front(); E; E = E->next()) { + Vector2i size = tile_set->get_tile_size(); + Vector2 position = tile_map->map_to_world(E->key()) - size / 2; + Rect2 cell_region = xform.xform(Rect2(position, size)); if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) { - Vector2i size = tile_set->get_tile_size(); - Vector2 position = tile_map->map_to_world(E->key()) - size / 2; - Rect2 cell_region = xform.xform(Rect2(position, size)); - tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0, 0.5), true); } else { if (tile_set->has_source(E->get().source_id)) { @@ -629,12 +769,10 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Draw the tile. p_overlay->draw_texture_rect_region(atlas_source->get_texture(), dest_rect, source_rect, modulate * Color(1.0, 1.0, 1.0, 0.5), transpose, tile_set->is_uv_clipping()); + } else { + tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0, 0.5), true); } } else { - Vector2i size = tile_set->get_tile_size(); - Vector2 position = tile_map->map_to_world(E->key()) - size / 2; - Rect2 cell_region = xform.xform(Rect2(position, size)); - tile_set->draw_tile_shape(p_overlay, cell_region, Color(0.0, 0.0, 0.0, 0.5), true); } } @@ -669,7 +807,9 @@ TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(const TileMapPattern *p_ TileSetSource *source = *tile_set->get_source(source_id); TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { - sum += Object::cast_to<TileData>(atlas_source->get_tile_data(atlas_coords, alternative_tile))->get_probability(); + TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(atlas_coords, alternative_tile)); + ERR_FAIL_COND_V(!tile_data, TileMapCell()); + sum += tile_data->get_probability(); } else { sum += 1.0; } @@ -698,7 +838,7 @@ TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(const TileMapPattern *p_ return TileMapCell(); } -Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2i p_to_mouse_pos) { +Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { return Map<Vector2i, TileMapCell>(); @@ -711,7 +851,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_ // Get or create the pattern. TileMapPattern erase_pattern; - erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern; Map<Vector2i, TileMapCell> output; @@ -763,7 +903,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start // Get or create the pattern. TileMapPattern erase_pattern; - erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern; // Compute the offset to align things to the bottom or right. @@ -814,7 +954,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i // Get or create the pattern. TileMapPattern erase_pattern; - erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern; Map<Vector2i, TileMapCell> output; @@ -930,14 +1070,14 @@ void TileMapEditorTilesPlugin::_stop_dragging() { undo_redo->create_action(TTR("Change selection")); undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection()); - if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT) && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT) && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) { tile_map_selection.clear(); } Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos) - tile_map->world_to_map(drag_start_mouse_pos)).abs(); for (int x = rect.position.x; x <= rect.get_end().x; x++) { for (int y = rect.position.y; y <= rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); - if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { if (tile_map_selection.has(coords)) { tile_map_selection.erase(coords); } @@ -1090,8 +1230,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { hovered_tile.source_id = -1; - hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS); - hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); + hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; tile_set_selection.clear(); tile_map_selection.clear(); selection_pattern->clear(); @@ -1101,8 +1241,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { Ref<TileSet> tile_set = tile_map->get_tileset(); if (!tile_set.is_valid()) { hovered_tile.source_id = -1; - hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS); - hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); + hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; tile_set_selection.clear(); tile_map_selection.clear(); selection_pattern->clear(); @@ -1112,8 +1252,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { int source_index = sources_list->get_current(); if (source_index < 0 || source_index >= sources_list->get_item_count()) { hovered_tile.source_id = -1; - hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS); - hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); + hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; tile_set_selection.clear(); tile_map_selection.clear(); selection_pattern->clear(); @@ -1128,8 +1268,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { !tile_set->get_source(hovered_tile.source_id)->has_tile(hovered_tile.get_atlas_coords()) || !tile_set->get_source(hovered_tile.source_id)->has_alternative_tile(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile)) { hovered_tile.source_id = -1; - hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS); - hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); + hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; } // Selection if needed. @@ -1187,6 +1327,7 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection( per_source[E->get().source_id].push_back(&(E->get())); } + int vertical_offset = 0; for (Map<int, List<const TileMapCell *>>::Element *E_source = per_source.front(); E_source; E_source = E_source->next()) { // Per source. List<const TileMapCell *> unorganized; @@ -1199,24 +1340,21 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection( // Organize using coordinates. for (List<const TileMapCell *>::Element *E_cell = E_source->get().front(); E_cell; E_cell = E_cell->next()) { const TileMapCell *current = E_cell->get(); - if (organized_pattern.has(current->get_atlas_coords())) { - if (current->alternative_tile < organized_pattern[current->get_atlas_coords()]->alternative_tile) { - unorganized.push_back(organized_pattern[current->get_atlas_coords()]); - organized_pattern[current->get_atlas_coords()] = current; - } else { - unorganized.push_back(current); - } - } else { + if (current->alternative_tile == 0) { organized_pattern[current->get_atlas_coords()] = current; + } else { + unorganized.push_back(current); } } // Compute the encompassing rect for the organized pattern. Map<Vector2i, const TileMapCell *>::Element *E_cell = organized_pattern.front(); - encompassing_rect_coords = Rect2i(E_cell->key(), Vector2i(1, 1)); - for (; E_cell; E_cell = E_cell->next()) { - encompassing_rect_coords.expand_to(E_cell->key() + Vector2i(1, 1)); - encompassing_rect_coords.expand_to(E_cell->key()); + if (E_cell) { + encompassing_rect_coords = Rect2i(E_cell->key(), Vector2i(1, 1)); + for (; E_cell; E_cell = E_cell->next()) { + encompassing_rect_coords.expand_to(E_cell->key() + Vector2i(1, 1)); + encompassing_rect_coords.expand_to(E_cell->key()); + } } } else { // Add everything unorganized. @@ -1227,12 +1365,15 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection( // Now add everything to the output pattern. for (Map<Vector2i, const TileMapCell *>::Element *E_cell = organized_pattern.front(); E_cell; E_cell = E_cell->next()) { - selection_pattern->set_cell(E_cell->key() - encompassing_rect_coords.position, E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile); + selection_pattern->set_cell(E_cell->key() - encompassing_rect_coords.position + Vector2i(0, vertical_offset), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile); } Vector2i organized_size = selection_pattern->get_size(); + int unorganized_index = 0; for (List<const TileMapCell *>::Element *E_cell = unorganized.front(); E_cell; E_cell = E_cell->next()) { - selection_pattern->set_cell(Vector2(organized_size.x, 0), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile); + selection_pattern->set_cell(Vector2(organized_size.x + unorganized_index, vertical_offset), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile); + unorganized_index++; } + vertical_offset += MAX(organized_size.y, 1); } CanvasItemEditor::get_singleton()->update_viewport(); } @@ -1246,7 +1387,7 @@ void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern( tile_set_selection.insert(TileMapCell(selection_pattern->get_cell_source_id(coords), selection_pattern->get_cell_atlas_coords(coords), selection_pattern->get_cell_alternative_tile(coords))); } } - _update_atlas_view(); + _update_bottom_panel(); } void TileMapEditorTilesPlugin::_tile_atlas_control_draw() { @@ -1283,7 +1424,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() { } // Draw the hovered tile. - if (hovered_tile.get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) { + if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) { tile_atlas_control->draw_rect(atlas->get_tile_texture_region(hovered_tile.get_atlas_coords()), Color(1.0, 1.0, 1.0), false); } @@ -1299,7 +1440,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() { for (int x = region.position.x; x < region.get_end().x; x++) { for (int y = region.position.y; y < region.get_end().y; y++) { Vector2i tile = atlas->get_tile_at_coords(Vector2i(x, y)); - if (tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (tile != TileSetSource::INVALID_ATLAS_COORDS) { to_draw.insert(tile); } } @@ -1313,8 +1454,8 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() { void TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited() { hovered_tile.source_id = -1; - hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS); - hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); + hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; tile_set_dragging_selection = false; tile_atlas_control->update(); } @@ -1347,12 +1488,12 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven // Update the hovered tile hovered_tile.source_id = source_id; - hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS); - hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); + hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position()); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { coords = atlas->get_tile_at_coords(coords); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { hovered_tile.set_atlas_coords(coords); hovered_tile.alternative_tile = 0; } @@ -1369,12 +1510,12 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven if (mb->is_pressed()) { // Pressed tile_set_dragging_selection = true; tile_set_drag_start_mouse_pos = tile_atlas_control->get_local_mouse_position(); - if (!mb->get_shift()) { + if (!mb->is_shift_pressed()) { tile_set_selection.clear(); } - if (hovered_tile.get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0) { - if (mb->get_shift() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0))) { + if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0) { + if (mb->is_shift_pressed() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0))) { tile_set_selection.erase(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0)); } else { tile_set_selection.insert(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0)); @@ -1383,24 +1524,24 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven _update_selection_pattern_from_tileset_selection(); } else { // Released if (tile_set_dragging_selection) { - if (!mb->get_shift()) { + if (!mb->is_shift_pressed()) { tile_set_selection.clear(); } // Compute the covered area. Vector2i start_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_set_drag_start_mouse_pos); Vector2i end_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position()); - if (start_tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && end_tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (start_tile != TileSetSource::INVALID_ATLAS_COORDS && end_tile != TileSetSource::INVALID_ATLAS_COORDS) { Rect2i region = Rect2i(start_tile, end_tile - start_tile).abs(); region.size += Vector2i(1, 1); // To update the selection, we copy the selected/not selected status of the tiles we drag from. Vector2i start_coords = atlas->get_tile_at_coords(start_tile); - if (mb->get_shift() && start_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && !tile_set_selection.has(TileMapCell(source_id, start_coords, 0))) { + if (mb->is_shift_pressed() && start_coords != TileSetSource::INVALID_ATLAS_COORDS && !tile_set_selection.has(TileMapCell(source_id, start_coords, 0))) { // Remove from the selection. for (int x = region.position.x; x < region.get_end().x; x++) { for (int y = region.position.y; y < region.get_end().y; y++) { Vector2i tile_coords = atlas->get_tile_at_coords(Vector2i(x, y)); - if (tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_selection.has(TileMapCell(source_id, tile_coords, 0))) { + if (tile_coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_selection.has(TileMapCell(source_id, tile_coords, 0))) { tile_set_selection.erase(TileMapCell(source_id, tile_coords, 0)); } } @@ -1410,7 +1551,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven for (int x = region.position.x; x < region.get_end().x; x++) { for (int y = region.position.y; y < region.get_end().y; y++) { Vector2i tile_coords = atlas->get_tile_at_coords(Vector2i(x, y)); - if (tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (tile_coords != TileSetSource::INVALID_ATLAS_COORDS) { tile_set_selection.insert(TileMapCell(source_id, tile_coords, 0)); } } @@ -1453,7 +1594,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() { // Draw the selection. for (Set<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { - if (E->get().source_id == source_id && E->get().get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && E->get().alternative_tile > 0) { + if (E->get().source_id == source_id && E->get().get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && E->get().alternative_tile > 0) { Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E->get().get_atlas_coords(), E->get().alternative_tile); if (rect != Rect2i()) { alternative_tiles_control->draw_rect(rect, Color(0.2, 0.2, 1.0), false); @@ -1462,7 +1603,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() { } // Draw hovered tile. - if (hovered_tile.get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) { + if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) { Rect2i rect = tile_atlas_view->get_alternative_tile_rect(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile); if (rect != Rect2i()) { alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false); @@ -1472,8 +1613,8 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() { void TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited() { hovered_tile.source_id = -1; - hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS); - hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); + hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; tile_set_dragging_selection = false; alternative_tiles_control->update(); } @@ -1506,12 +1647,12 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<In // Update the hovered tile hovered_tile.source_id = source_id; - hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS); - hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); + hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; Vector3i alternative_coords = tile_atlas_view->get_alternative_tile_at_pos(alternative_tiles_control->get_local_mouse_position()); Vector2i coords = Vector2i(alternative_coords.x, alternative_coords.y); int alternative = alternative_coords.z; - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative != TileSetSource::INVALID_TILE_ALTERNATIVE) { hovered_tile.set_atlas_coords(coords); hovered_tile.alternative_tile = alternative; } @@ -1526,12 +1667,12 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<In if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (mb->is_pressed()) { // Pressed // Left click pressed. - if (!mb->get_shift()) { + if (!mb->is_shift_pressed()) { tile_set_selection.clear(); } - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) { - if (mb->get_shift() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile))) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) { + if (mb->is_shift_pressed() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile))) { tile_set_selection.erase(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile)); } else { tile_set_selection.insert(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile)); @@ -1565,13 +1706,14 @@ TypedArray<Vector2i> TileMapEditorTilesPlugin::_get_tile_map_selection() const { void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id) { tile_map_id = p_tile_map_id; - // Clean the selection. + // Clear the selection. tile_set_selection.clear(); tile_map_selection.clear(); selection_pattern->clear(); } void TileMapEditorTilesPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileMapEditorTilesPlugin::_scene_thumbnail_done); ClassDB::bind_method(D_METHOD("_set_tile_map_selection", "selection"), &TileMapEditorTilesPlugin::_set_tile_map_selection); ClassDB::bind_method(D_METHOD("_get_tile_map_selection"), &TileMapEditorTilesPlugin::_get_tile_map_selection); } @@ -1718,20 +1860,20 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { sources_list->set_h_size_flags(SIZE_EXPAND_FILL); sources_list->set_stretch_ratio(0.25); sources_list->set_custom_minimum_size(Size2i(70, 0) * EDSCALE); + sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1)); - sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_atlas_view).unbind(1)); + sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_bottom_panel).unbind(1)); sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current)); sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list)); - //sources_list->set_drag_forwarding(this); atlas_sources_split_container->add_child(sources_list); + // Tile atlas source. tile_atlas_view = memnew(TileAtlasView); tile_atlas_view->set_h_size_flags(SIZE_EXPAND_FILL); tile_atlas_view->set_v_size_flags(SIZE_EXPAND_FILL); tile_atlas_view->set_texture_grid_visible(false); tile_atlas_view->set_tile_shape_grid_visible(false); tile_atlas_view->connect("transform_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_view_transform)); - //tile_atlas_view->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_view), varray(tile_atlas_view)); atlas_sources_split_container->add_child(tile_atlas_view); tile_atlas_control = memnew(Control); @@ -1746,6 +1888,27 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { alternative_tiles_control->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input)); tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control); + // Scenes collection source. + scene_tiles_list = memnew(ItemList); + scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL); + scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL); + scene_tiles_list->set_drag_forwarding(this); + scene_tiles_list->set_select_mode(ItemList::SELECT_MULTI); + scene_tiles_list->connect("multi_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_multi_selected)); + scene_tiles_list->connect("nothing_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_nothing_selected)); + scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); + atlas_sources_split_container->add_child(scene_tiles_list); + + // Invalid source label. + invalid_source_label = memnew(Label); + invalid_source_label->set_text(TTR("Invalid source selected.")); + invalid_source_label->set_h_size_flags(SIZE_EXPAND_FILL); + invalid_source_label->set_v_size_flags(SIZE_EXPAND_FILL); + invalid_source_label->set_align(Label::ALIGN_CENTER); + invalid_source_label->set_valign(Label::VALIGN_CENTER); + invalid_source_label->hide(); + atlas_sources_split_container->add_child(invalid_source_label); + _update_bottom_panel(); } @@ -2147,7 +2310,7 @@ Set<TileMapEditorTerrainsPlugin::Constraint> TileMapEditorTerrainsPlugin::_get_c Map<int, int> terrain_count; - // Count the number of occurences per terrain. + // Count the number of occurrences per terrain. Map<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits(); for (Map<Vector2i, TileSet::CellNeighbor>::Element *E_overlapping = overlapping_terrain_bits.front(); E_overlapping; E_overlapping = E_overlapping->next()) { if (!p_to_replace.has(E_overlapping->key())) { @@ -2165,7 +2328,7 @@ Set<TileMapEditorTerrainsPlugin::Constraint> TileMapEditorTerrainsPlugin::_get_c } } - // Get the terrain with the max number of occurences. + // Get the terrain with the max number of occurrences. int max = 0; int max_terrain = -1; for (Map<int, int>::Element *E_terrain_count = terrain_count.front(); E_terrain_count; E_terrain_count = E_terrain_count->next()) { @@ -2231,7 +2394,7 @@ Map<Vector2i, TileMapEditorTerrainsPlugin::TerrainsTilePattern> TileMapEditorTer per_cell_acceptable_tiles[E->get()] = _get_valid_terrains_tile_patterns_for_constraints(p_terrain_set, E->get(), constraints); } - // Ouput map. + // Output map. Map<Vector2i, TerrainsTilePattern> output; // Add all positions to a set. @@ -2450,7 +2613,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map output[E->key()] = _get_random_tile_from_pattern(p_terrain_set, E->get()); } - // Override the WFC results to make sure at least the painted tiles are acutally painted. + // Override the WFC results to make sure at least the painted tiles are actually painted. for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) { output[E_to_paint->key()] = _get_random_tile_from_pattern(p_terrain_set, E_to_paint->get()); } @@ -2587,7 +2750,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> } if (need_tree_item_switch) { - for (tree_item = terrains_tree->get_root()->get_children(); tree_item; tree_item = tree_item->get_next_visible()) { + for (tree_item = terrains_tree->get_root()->get_first_child(); tree_item; tree_item = tree_item->get_next_visible()) { Dictionary metadata_dict = tree_item->get_metadata(0); if (metadata_dict.has("terrain_set") && metadata_dict.has("terrain_id")) { int terrain_set = metadata_dict["terrain_set"]; @@ -2771,8 +2934,8 @@ void TileMapEditorTerrainsPlugin::_update_terrains_cache() { TileMapCell empty_cell; empty_cell.source_id = -1; - empty_cell.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS); - empty_cell.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + empty_cell.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); + empty_cell.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; per_terrain_terrains_tile_patterns_tiles[i][empty_pattern].insert(empty_cell); } } diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h index f780686b82..a1fb9af3ef 100644 --- a/editor/plugins/tiles/tile_map_editor.h +++ b/editor/plugins/tiles/tile_map_editor.h @@ -58,7 +58,7 @@ private: ObjectID tile_map_id; virtual void edit(ObjectID p_tile_map_id) override; - // Toolbar. + ///// Toolbar ///// HBoxContainer *toolbar; Ref<ButtonGroup> tool_buttons_group; @@ -84,7 +84,7 @@ private: void _update_toolbar(); - // Tilemap editing. + ///// Tilemap editing. ///// bool has_mouse = false; void _mouse_exited_viewport(); @@ -105,12 +105,12 @@ private: Map<Vector2i, TileMapCell> drag_modified; TileMapCell _pick_random_tile(const TileMapPattern *p_pattern); - Map<Vector2i, TileMapCell> _draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2i p_to_mouse_pos); - Map<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_mouse_pos, Vector2i p_end_mouse_pos); + Map<Vector2i, TileMapCell> _draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos); + Map<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_cell, Vector2i p_end_cell); Map<Vector2i, TileMapCell> _draw_bucket_fill(Vector2i p_coords, bool p_contiguous); void _stop_dragging(); - // Selection system. + ///// Selection system. ///// Set<Vector2i> tile_map_selection; TileMapPattern *tile_map_clipboard = memnew(TileMapPattern); TileMapPattern *selection_pattern = memnew(TileMapPattern); @@ -124,22 +124,24 @@ private: void _update_tileset_selection_from_selection_pattern(); void _update_fix_selected_and_hovered(); - // Bottom panel. - bool tile_set_dragging_selection = false; - Vector2i tile_set_drag_start_mouse_pos; - + ///// Bottom panel. ////. Label *missing_source_label; - HSplitContainer *atlas_sources_split_container; + Label *invalid_source_label; ItemList *sources_list; - TileAtlasView *tile_atlas_view; - Ref<Texture2D> missing_texture_texture; + + Ref<Texture2D> missing_atlas_texture_icon; void _update_tile_set_sources_list(); - void _update_atlas_view(); void _update_bottom_panel(); + // Atlas sources. TileMapCell hovered_tile; + TileAtlasView *tile_atlas_view; + HSplitContainer *atlas_sources_split_container; + + bool tile_set_dragging_selection = false; + Vector2i tile_set_drag_start_mouse_pos; Control *tile_atlas_control; void _tile_atlas_control_mouse_exited(); @@ -151,6 +153,16 @@ private: void _tile_alternatives_control_mouse_exited(); void _tile_alternatives_control_gui_input(const Ref<InputEvent> &p_event); + void _update_atlas_view(); + + // Scenes collection sources. + ItemList *scene_tiles_list; + + void _update_scenes_collection_view(); + void _scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud); + void _scenes_list_multi_selected(int p_index, bool p_selected); + void _scenes_list_nothing_selected(); + // Update callback virtual void tile_set_changed() override; diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 69abbb29f1..b6e1a318cb 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -53,10 +53,10 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::set_id(int p_id) { if (source_id == p_id) { return; } - ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet atlas source ID. Another atlas source exists with id %d.", p_id)); + ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet Atlas Source ID. Another source exists with id %d.", p_id)); int previous_source = source_id; - source_id = p_id; // source_id must be updated before, because it's used by the atlas source list update. + source_id = p_id; // source_id must be updated before, because it's used by the source list update. tile_set->set_source_id(previous_source, p_id); emit_signal("changed", "id"); } @@ -126,7 +126,7 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::edit(Ref<TileSet> } // -- Proxy object used by the tile inspector -- -bool TileSetAtlasSourceEditor::TileProxyObject::_set(const StringName &p_name, const Variant &p_value) { +bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_name, const Variant &p_value) { if (!tile_set_atlas_source) { return false; } @@ -152,9 +152,9 @@ bool TileSetAtlasSourceEditor::TileProxyObject::_set(const StringName &p_name, c return true; } else if (alternative == 0 && p_name == "size_in_atlas") { Vector2i as_vector2i = Vector2i(p_value); - ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, TileSetAtlasSource::INVALID_ATLAS_COORDS, as_vector2i), false); + ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i), false); - tile_set_atlas_source->move_tile_in_atlas(coords, TileSetAtlasSource::INVALID_ATLAS_COORDS, as_vector2i); + tile_set_atlas_source->move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i); emit_signal("changed", "size_in_atlas"); return true; } else if (alternative > 0 && p_name == "alternative_id") { @@ -197,7 +197,7 @@ bool TileSetAtlasSourceEditor::TileProxyObject::_set(const StringName &p_name, c return any_valid; } -bool TileSetAtlasSourceEditor::TileProxyObject::_get(const StringName &p_name, Variant &r_ret) const { +bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_get(const StringName &p_name, Variant &r_ret) const { if (!tile_set_atlas_source) { return false; } @@ -237,7 +237,7 @@ bool TileSetAtlasSourceEditor::TileProxyObject::_get(const StringName &p_name, V return false; } -void TileSetAtlasSourceEditor::TileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const { +void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const { if (!tile_set_atlas_source) { return; } @@ -310,12 +310,11 @@ void TileSetAtlasSourceEditor::TileProxyObject::_get_property_list(List<Property } } -void TileSetAtlasSourceEditor::TileProxyObject::edit(TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id, Set<TileSelection> p_tiles) { +void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles) { ERR_FAIL_COND(!p_tile_set_atlas_source); - ERR_FAIL_COND(p_source_id < 0); ERR_FAIL_COND(p_tiles.is_empty()); for (Set<TileSelection>::Element *E = p_tiles.front(); E; E = E->next()) { - ERR_FAIL_COND(E->get().tile == TileSetAtlasSource::INVALID_ATLAS_COORDS); + ERR_FAIL_COND(E->get().tile == TileSetSource::INVALID_ATLAS_COORDS); ERR_FAIL_COND(E->get().alternative < 0); } @@ -333,7 +332,6 @@ void TileSetAtlasSourceEditor::TileProxyObject::edit(TileSetAtlasSource *p_tile_ } tile_set_atlas_source = p_tile_set_atlas_source; - source_id = p_source_id; tiles = Set<TileSelection>(p_tiles); // Connect to changes. @@ -352,7 +350,7 @@ void TileSetAtlasSourceEditor::TileProxyObject::edit(TileSetAtlasSource *p_tile_ notify_property_list_changed(); } -void TileSetAtlasSourceEditor::TileProxyObject::_bind_methods() { +void TileSetAtlasSourceEditor::AtlasTileProxyObject::_bind_methods() { ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what"))); } @@ -391,12 +389,12 @@ void TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles() { // Fix hovered. if (!tile_set_atlas_source->has_tile(hovered_base_tile_coords)) { - hovered_base_tile_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS; + hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS; } Vector2i coords = Vector2i(hovered_alternative_tile_coords.x, hovered_alternative_tile_coords.y); int alternative = hovered_alternative_tile_coords.z; if (!tile_set_atlas_source->has_tile(coords) || !tile_set_atlas_source->has_alternative_tile(coords, alternative)) { - hovered_alternative_tile_coords = Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE); } } @@ -405,7 +403,7 @@ void TileSetAtlasSourceEditor::_update_tile_inspector() { // Update the proxy object. if (has_atlas_tile_selected) { - tile_proxy_object->edit(tile_set_atlas_source, tile_set_atlas_source_id, selection); + tile_proxy_object->edit(tile_set_atlas_source, selection); } // Update visibility. @@ -486,7 +484,7 @@ void TileSetAtlasSourceEditor::_update_toolbar() { } void TileSetAtlasSourceEditor::_tile_atlas_control_mouse_exited() { - hovered_base_tile_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS; + hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS; tile_atlas_control->update(); tile_atlas_control_unscaled->update(); tile_atlas_view->update(); @@ -514,7 +512,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven if (selection.size() == 1) { // Change the cursor depending on the hovered thing. TileSelection selected = selection.front()->get(); - if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selected.alternative == 0) { + if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) { Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position(); Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile); Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile); @@ -560,7 +558,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords); for (int i = 0; i < line.size(); i++) { - if (tile_set_atlas_source->get_tile_at_coords(line[i]) == TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (tile_set_atlas_source->get_tile_at_coords(line[i]) == TileSetSource::INVALID_ATLAS_COORDS) { tile_set_atlas_source->create_tile(line[i]); drag_modified_tiles.insert(line[i]); } @@ -576,7 +574,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords); for (int i = 0; i < line.size(); i++) { Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(line[i]); - if (base_tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) { drag_modified_tiles.insert(base_tile_coords); } } @@ -662,17 +660,17 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven // Remove a first tile. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { coords = tile_set_atlas_source->get_tile_at_coords(coords); } - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { drag_modified_tiles.insert(coords); } } else { - if (mb->get_shift()) { + if (mb->is_shift_pressed()) { // Create a big tile. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) { // Setup the dragging info, only if we start on an empty tile. drag_type = DRAG_TYPE_CREATE_BIG_TILE; drag_start_mouse_pos = mouse_local_pos; @@ -692,7 +690,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven // Create a first tile if needed. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) { tile_set_atlas_source->create_tile(coords); drag_modified_tiles.insert(coords); } @@ -707,10 +705,10 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven drag_start_mouse_pos = mouse_local_pos; drag_last_mouse_pos = drag_start_mouse_pos; } else { - if (mb->get_shift()) { + if (mb->is_shift_pressed()) { // Create a big tile. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) { // Setup the dragging info, only if we start on an empty tile. drag_type = DRAG_TYPE_CREATE_BIG_TILE; drag_start_mouse_pos = mouse_local_pos; @@ -732,7 +730,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven drag_type = DRAG_TYPE_NONE; if (selection.size() == 1) { TileSelection selected = selection.front()->get(); - if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selected.alternative == 0) { + if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) { Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile); Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile); Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom(); @@ -771,17 +769,17 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven // Selecting then dragging a tile. if (drag_type == DRAG_TYPE_NONE) { - TileSelection selected = { TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE }; + TileSelection selected = { TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE }; Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { coords = tile_set_atlas_source->get_tile_at_coords(coords); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { selected = { coords, 0 }; } } - bool shift = mb->get_shift(); - if (!shift && selection.size() == 1 && selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selection.has(selected)) { + bool shift = mb->is_shift_pressed(); + if (!shift && selection.size() == 1 && selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) { // Start move dragging. drag_type = DRAG_TYPE_MOVE_TILE; drag_start_mouse_pos = mouse_local_pos; @@ -812,13 +810,13 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven // Right click pressed. TileSelection selected = { tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos), 0 }; - if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) { selected.tile = tile_set_atlas_source->get_tile_at_coords(selected.tile); } // Set the selection if needed. if (selection.size() <= 1) { - if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) { undo_redo->create_action(TTR("Select tiles")); undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array()); selection.clear(); @@ -831,15 +829,15 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven } // Pops up the correct menu, depending on whether we have a tile or not. - if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selection.has(selected)) { + if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) { // We have a tile. menu_option_coords = selected.tile; menu_option_alternative = 0; base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i())); - } else if (hovered_base_tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + } else if (hovered_base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) { // We don't have a tile, but can create one. menu_option_coords = hovered_base_tile_coords; - menu_option_alternative = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + menu_option_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE; empty_base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i())); } } else { @@ -902,7 +900,7 @@ void TileSetAtlasSourceEditor::_end_dragging() { for (int x = area.get_position().x; x < area.get_end().x; x++) { for (int y = area.get_position().y; y < area.get_end().y; y++) { Vector2i coords = Vector2i(x, y); - if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) { undo_redo->add_do_method(tile_set_atlas_source, "create_tile", coords); undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", coords); } @@ -923,7 +921,7 @@ void TileSetAtlasSourceEditor::_end_dragging() { for (int x = area.get_position().x; x < area.get_end().x; x++) { for (int y = area.get_position().y; y < area.get_end().y; y++) { Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y)); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { to_delete.insert(coords); } } @@ -964,8 +962,8 @@ void TileSetAtlasSourceEditor::_end_dragging() { case DRAG_TYPE_RECT_SELECT: { Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos); Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position()); - ERR_FAIL_COND(start_base_tiles_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS); - ERR_FAIL_COND(new_base_tiles_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS); + ERR_FAIL_COND(start_base_tiles_coords == TileSetSource::INVALID_ATLAS_COORDS); + ERR_FAIL_COND(new_base_tiles_coords == TileSetSource::INVALID_ATLAS_COORDS); Rect2i region = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs(); region.size += Vector2i(1, 1); @@ -977,7 +975,7 @@ void TileSetAtlasSourceEditor::_end_dragging() { bool add_to_selection = true; if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { Vector2i coords = tile_set_atlas_source->get_tile_at_coords(start_base_tiles_coords); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { if (selection.has({ coords, 0 })) { add_to_selection = false; } @@ -991,7 +989,7 @@ void TileSetAtlasSourceEditor::_end_dragging() { for (int y = region.position.y; y < region.get_end().y; y++) { Vector2i coords = Vector2i(x, y); coords = tile_set_atlas_source->get_tile_at_coords(coords); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { if (add_to_selection && !selection.has({ coords, 0 })) { selection.insert({ coords, 0 }); } else if (!add_to_selection && selection.has({ coords, 0 })) { @@ -1243,7 +1241,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { for (int x = area.get_position().x; x < area.get_end().x; x++) { for (int y = area.get_position().y; y < area.get_end().y; y++) { Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y)); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { to_paint.insert(coords); } } @@ -1266,7 +1264,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { for (int x = area.get_position().x; x < area.get_end().x; x++) { for (int y = area.get_position().y; y < area.get_end().y; y++) { Vector2i coords = Vector2i(x, y); - if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) { Vector2i origin = margins + (coords * (tile_size + separation)); tile_atlas_control->draw_rect(Rect2i(origin, tile_size), Color(1.0, 1.0, 1.0), false); } @@ -1290,7 +1288,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size(); if (hovered_base_tile_coords.x >= 0 && hovered_base_tile_coords.y >= 0 && hovered_base_tile_coords.x < grid_size.x && hovered_base_tile_coords.y < grid_size.y) { Vector2i hovered_tile = tile_set_atlas_source->get_tile_at_coords(hovered_base_tile_coords); - if (hovered_tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (hovered_tile != TileSetSource::INVALID_ATLAS_COORDS) { // Draw existing hovered tile. tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(hovered_tile), Color(1.0, 1.0, 1.0), false); } else { @@ -1349,7 +1347,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In selection.clear(); TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) }; - if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) { selection.insert(selected); } @@ -1364,7 +1362,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In selection.clear(); TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) }; - if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) { selection.insert(selected); } @@ -1387,7 +1385,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In } void TileSetAtlasSourceEditor::_tile_alternatives_control_mouse_exited() { - hovered_alternative_tile_coords = Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE); tile_atlas_control->update(); tile_atlas_control_unscaled->update(); alternative_tiles_control->update(); @@ -1399,7 +1397,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() { if (tools_button_group->get_pressed_button() == tool_select_button) { // Draw hovered tile. Vector2i coords = Vector2(hovered_alternative_tile_coords.x, hovered_alternative_tile_coords.y); - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, hovered_alternative_tile_coords.z); if (rect != Rect2i()) { alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false); @@ -1441,7 +1439,7 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo #define ADD_UNDO(obj, property) undo_redo->add_undo_property(obj, property, tile_data->get(property)); - TileProxyObject *tile_data = Object::cast_to<TileProxyObject>(p_edited); + AtlasTileProxyObject *tile_data = Object::cast_to<AtlasTileProxyObject>(p_edited); if (tile_data) { Vector<String> components = String(p_property).split("/", true, 2); if (components.size() == 2 && components[1] == "shapes_count") { @@ -1518,7 +1516,7 @@ void TileSetAtlasSourceEditor::_auto_create_tiles() { for (int x = 0; x < grid_size.x; x++) { // Check if we have a tile at the coord Vector2i coords = Vector2i(x, y); - if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) { // Check if the texture is empty at the given coords. Rect2i region = Rect2i(margins + (coords * (texture_region_size + separation)), texture_region_size); bool is_opaque = false; @@ -1673,7 +1671,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_inspector_label->hide(); middle_vbox_container->add_child(tile_inspector_label); - tile_proxy_object = memnew(TileProxyObject(this)); + tile_proxy_object = memnew(AtlasTileProxyObject(this)); tile_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view).unbind(1)); tile_inspector = memnew(EditorInspector); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index ff68aa8288..70f2cdbe01 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -45,8 +45,8 @@ class TileSetAtlasSourceEditor : public HBoxContainer { private: // A class to store which tiles are selected. struct TileSelection { - Vector2i tile = TileSetAtlasSource::INVALID_ATLAS_COORDS; - int alternative = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + Vector2i tile = TileSetSource::INVALID_ATLAS_COORDS; + int alternative = TileSetSource::INVALID_TILE_ALTERNATIVE; bool operator<(const TileSelection &p_other) const { if (tile == p_other.tile) { @@ -80,14 +80,13 @@ private: }; // -- Proxy object for a tile, needed by the inspector -- - class TileProxyObject : public Object { - GDCLASS(TileProxyObject, Object); + class AtlasTileProxyObject : public Object { + GDCLASS(AtlasTileProxyObject, Object); private: TileSetAtlasSourceEditor *tiles_set_atlas_source_editor; TileSetAtlasSource *tile_set_atlas_source = nullptr; - int source_id; Set<TileSelection> tiles = Set<TileSelection>(); protected: @@ -99,10 +98,10 @@ private: public: // Update the proxyed object. - void edit(TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id = -1, Set<TileSelection> p_tiles = Set<TileSelection>()); + void edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles = Set<TileSelection>()); - TileProxyObject(TileSetAtlasSourceEditor *p_tiles_editor_source_tab) { - tiles_set_atlas_source_editor = p_tiles_editor_source_tab; + AtlasTileProxyObject(TileSetAtlasSourceEditor *p_tiles_set_atlas_source_editor) { + tiles_set_atlas_source_editor = p_tiles_set_atlas_source_editor; } }; @@ -115,7 +114,7 @@ private: bool tile_set_atlas_source_changed_needs_update = false; // -- Inspector -- - TileProxyObject *tile_proxy_object; + AtlasTileProxyObject *tile_proxy_object; Label *tile_inspector_label; EditorInspector *tile_inspector; String selected_property; @@ -175,7 +174,7 @@ private: ADVANCED_AUTO_REMOVE_TILES, }; Vector2i menu_option_coords; - int menu_option_alternative = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + int menu_option_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE; void _menu_option(int p_option); // Tool buttons. @@ -198,7 +197,7 @@ private: Array _get_selection_as_array(); // A control on the tile atlas to draw and handle input events. - Vector2i hovered_base_tile_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS; + Vector2i hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS; PopupMenu *base_tile_popup_menu; PopupMenu *empty_base_tile_popup_menu; @@ -213,7 +212,7 @@ private: void _tile_atlas_view_transform_changed(); // A control over the alternative tiles. - Vector3i hovered_alternative_tile_coords = Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + Vector3i hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE); PopupMenu *alternative_tile_popup_menu; Control *alternative_tiles_control; diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index 8a5890e9a4..05ebe408a5 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -76,7 +76,7 @@ void TileSetEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, C tile_set_atlas_source_editor->init_source(); } - // Update the selected source (thus trigerring an update). + // Update the selected source (thus triggering an update). _update_atlas_sources_list(source_id); } } @@ -140,20 +140,39 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) { for (int i = 0; i < tile_set->get_source_count(); i++) { int source_id = tile_set->get_source_id(i); - // TODO: handle with virtual functions TileSetSource *source = *tile_set->get_source(source_id); + + Ref<Texture2D> texture; + String item_text; + + // Atlas source. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { - Ref<Texture2D> texture = atlas_source->get_texture(); + texture = atlas_source->get_texture(); if (texture.is_valid()) { - sources_list->add_item(vformat("%s - (id:%d)", texture->get_path().get_file(), source_id), texture); + item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id); } else { - sources_list->add_item(vformat("No texture atlas source - (id:%d)", source_id), missing_texture_texture); + item_text = vformat(TTR("No Texture Atlas Source (id:%d)"), source_id); } - } else { - sources_list->add_item(vformat("Unknown type source - (id:%d)", source_id), missing_texture_texture); } - sources_list->set_item_metadata(sources_list->get_item_count() - 1, source_id); + + // Scene collection source. + TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); + if (scene_collection_source) { + texture = get_theme_icon("PackedScene", "EditorIcons"); + item_text = vformat(TTR("Scene Collection Source (id:%d)"), source_id); + } + + // Use default if not valid. + if (item_text.is_empty()) { + item_text = vformat(TTR("Unknown Type Source (id:%d)"), source_id); + } + if (!texture.is_valid()) { + texture = missing_texture_texture; + } + + sources_list->add_item(item_text, texture); + sources_list->set_item_metadata(i, source_id); } // Set again the current selected item if needed. @@ -193,35 +212,63 @@ void TileSetEditor::_source_selected(int p_source_index) { if (p_source_index >= 0) { int source_id = sources_list->get_item_metadata(p_source_index); TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(*tile_set->get_source(source_id)); + TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(*tile_set->get_source(source_id)); if (atlas_source) { - tile_set_atlas_source_editor->edit(*tile_set, atlas_source, source_id); no_source_selected_label->hide(); + tile_set_atlas_source_editor->edit(*tile_set, atlas_source, source_id); tile_set_atlas_source_editor->show(); + tile_set_scenes_collection_source_editor->hide(); + } else if (scenes_collection_source) { + no_source_selected_label->hide(); + tile_set_atlas_source_editor->hide(); + tile_set_scenes_collection_source_editor->edit(*tile_set, scenes_collection_source, source_id); + tile_set_scenes_collection_source_editor->show(); } else { no_source_selected_label->show(); tile_set_atlas_source_editor->hide(); + tile_set_scenes_collection_source_editor->hide(); } } else { no_source_selected_label->show(); tile_set_atlas_source_editor->hide(); + tile_set_scenes_collection_source_editor->hide(); } } -void TileSetEditor::_source_add_pressed() { +void TileSetEditor::_source_add_id_pressed(int p_id_pressed) { ERR_FAIL_COND(!tile_set.is_valid()); - int source_id = tile_set->get_next_source_id(); + switch (p_id_pressed) { + case 0: { + int source_id = tile_set->get_next_source_id(); - Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource); + Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource); - // Add a new source. - undo_redo->create_action(TTR("Add atlas source")); - undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id); - undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size()); - undo_redo->add_undo_method(*tile_set, "remove_source", source_id); - undo_redo->commit_action(); + // Add a new source. + undo_redo->create_action(TTR("Add atlas source")); + undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id); + undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size()); + undo_redo->add_undo_method(*tile_set, "remove_source", source_id); + undo_redo->commit_action(); + + _update_atlas_sources_list(source_id); + } break; + case 1: { + int source_id = tile_set->get_next_source_id(); + + Ref<TileSetScenesCollectionSource> scene_collection_source = memnew(TileSetScenesCollectionSource); - _update_atlas_sources_list(source_id); + // Add a new source. + undo_redo->create_action(TTR("Add atlas source")); + undo_redo->add_do_method(*tile_set, "add_source", scene_collection_source, source_id); + undo_redo->add_undo_method(*tile_set, "remove_source", source_id); + undo_redo->commit_action(); + + _update_atlas_sources_list(source_id); + } break; + default: + ERR_FAIL(); + } } void TileSetEditor::_source_delete_pressed() { @@ -434,6 +481,7 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) { } tile_set_atlas_source_editor->hide(); + tile_set_scenes_collection_source_editor->hide(); no_source_selected_label->show(); } @@ -464,6 +512,7 @@ TileSetEditor::TileSetEditor() { sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected)); sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current)); sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list)); + sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); sources_list->set_drag_forwarding(this); split_container_left_side->add_child(sources_list); @@ -477,11 +526,19 @@ TileSetEditor::TileSetEditor() { sources_delete_button->connect("pressed", callable_mp(this, &TileSetEditor::_source_delete_pressed)); sources_bottom_actions->add_child(sources_delete_button); - sources_add_button = memnew(Button); + sources_add_button = memnew(MenuButton); sources_add_button->set_flat(true); - sources_add_button->connect("pressed", callable_mp(this, &TileSetEditor::_source_add_pressed)); + sources_add_button->get_popup()->add_item(TTR("Atlas")); + sources_add_button->get_popup()->add_item(TTR("Scenes Collection")); + sources_add_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetEditor::_source_add_id_pressed)); sources_bottom_actions->add_child(sources_add_button); + // Right side container. + VBoxContainer *split_container_right_side = memnew(VBoxContainer); + split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL); + split_container_right_side->set_v_size_flags(SIZE_EXPAND_FILL); + split_container->add_child(split_container_right_side); + // No source selected. no_source_selected_label = memnew(Label); no_source_selected_label->set_text(TTR("No TileSet source selected. Select or create a TileSet source.")); @@ -489,16 +546,24 @@ TileSetEditor::TileSetEditor() { no_source_selected_label->set_v_size_flags(SIZE_EXPAND_FILL); no_source_selected_label->set_align(Label::ALIGN_CENTER); no_source_selected_label->set_valign(Label::VALIGN_CENTER); - split_container->add_child(no_source_selected_label); + split_container_right_side->add_child(no_source_selected_label); // Atlases editor. tile_set_atlas_source_editor = memnew(TileSetAtlasSourceEditor); tile_set_atlas_source_editor->set_h_size_flags(SIZE_EXPAND_FILL); tile_set_atlas_source_editor->set_v_size_flags(SIZE_EXPAND_FILL); tile_set_atlas_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list)); - split_container->add_child(tile_set_atlas_source_editor); + split_container_right_side->add_child(tile_set_atlas_source_editor); tile_set_atlas_source_editor->hide(); + // Scenes collection editor. + tile_set_scenes_collection_source_editor = memnew(TileSetScenesCollectionSourceEditor); + tile_set_scenes_collection_source_editor->set_h_size_flags(SIZE_EXPAND_FILL); + tile_set_scenes_collection_source_editor->set_v_size_flags(SIZE_EXPAND_FILL); + tile_set_scenes_collection_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list)); + split_container_right_side->add_child(tile_set_scenes_collection_source_editor); + tile_set_scenes_collection_source_editor->hide(); + // Registers UndoRedo inspector callback. EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetEditor::_undo_redo_inspector_callback)); } diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h index c4aebb40a2..d508c04319 100644 --- a/editor/plugins/tiles/tile_set_editor.h +++ b/editor/plugins/tiles/tile_set_editor.h @@ -35,6 +35,7 @@ #include "scene/resources/tile_set.h" #include "tile_data_editors.h" #include "tile_set_atlas_source_editor.h" +#include "tile_set_scenes_collection_source_editor.h" class TileSetEditor : public VBoxContainer { GDCLASS(TileSetEditor, VBoxContainer); @@ -47,6 +48,7 @@ private: Label *no_source_selected_label; TileSetAtlasSourceEditor *tile_set_atlas_source_editor; + TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor; UndoRedo *undo_redo = EditorNode::get_undo_redo(); @@ -64,11 +66,11 @@ private: // -- Sources management -- Button *sources_delete_button; - Button *sources_add_button; + MenuButton *sources_add_button; ItemList *sources_list; Ref<Texture2D> missing_texture_texture; void _source_selected(int p_source_index); - void _source_add_pressed(); + void _source_add_id_pressed(int p_id_pressed); void _source_delete_pressed(); void _tile_set_changed(); diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp new file mode 100644 index 0000000000..568d4ca8d7 --- /dev/null +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -0,0 +1,511 @@ +/*************************************************************************/ +/* tile_set_scenes_collection_source_editor.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "tile_set_scenes_collection_source_editor.h" + +#include "editor/editor_resource_preview.h" +#include "editor/editor_scale.h" +#include "editor/editor_settings.h" + +#include "scene/gui/item_list.h" + +#include "core/core_string_names.h" + +void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::set_id(int p_id) { + ERR_FAIL_COND(p_id < 0); + if (source_id == p_id) { + return; + } + ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet Scenes Collection source ID. Another TileSet source exists with id %d.", p_id)); + + int previous_source = source_id; + source_id = p_id; // source_id must be updated before, because it's used by the source list update. + tile_set->set_source_id(previous_source, p_id); + emit_signal("changed", "id"); +} + +int TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id() { + return source_id; +} + +bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_set(const StringName &p_name, const Variant &p_value) { + bool valid = false; + tile_set_scenes_collection_source->set(p_name, p_value, &valid); + if (valid) { + emit_signal("changed", String(p_name).utf8().get_data()); + } + return valid; +} + +bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_get(const StringName &p_name, Variant &r_ret) const { + if (!tile_set_scenes_collection_source) { + return false; + } + bool valid = false; + r_ret = tile_set_scenes_collection_source->get(p_name, &valid); + return valid; +} + +void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_bind_methods() { + // -- Shape and layout -- + ClassDB::bind_method(D_METHOD("set_id", "id"), &TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::set_id); + ClassDB::bind_method(D_METHOD("get_id"), &TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id"); + + ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what"))); +} + +void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id) { + ERR_FAIL_COND(!p_tile_set.is_valid()); + ERR_FAIL_COND(!p_tile_set_scenes_collection_source); + ERR_FAIL_COND(p_source_id < 0); + ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source); + + // Disconnect to changes. + if (tile_set_scenes_collection_source) { + tile_set_scenes_collection_source->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed)); + } + + tile_set = p_tile_set; + tile_set_scenes_collection_source = p_tile_set_scenes_collection_source; + source_id = p_source_id; + + // Connect to changes. + if (tile_set_scenes_collection_source) { + if (!tile_set_scenes_collection_source->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) { + tile_set_scenes_collection_source->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed)); + } + } + + notify_property_list_changed(); +} + +// -- Proxy object used by the tile inspector -- +bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_set(const StringName &p_name, const Variant &p_value) { + if (!tile_set_scenes_collection_source) { + return false; + } + + if (p_name == "id") { + int as_int = int(p_value); + ERR_FAIL_COND_V(as_int < 0, false); + ERR_FAIL_COND_V(tile_set_scenes_collection_source->has_scene_tile_id(as_int), false); + tile_set_scenes_collection_source->set_scene_tile_id(scene_id, as_int); + scene_id = as_int; + emit_signal("changed", "id"); + for (int i = 0; i < tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_count(); i++) { + if (int(tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_metadata(i)) == scene_id) { + tile_set_scenes_collection_source_editor->scene_tiles_list->select(i); + break; + } + } + return true; + } else if (p_name == "scene") { + tile_set_scenes_collection_source->set_scene_tile_scene(scene_id, p_value); + emit_signal("changed", "scene"); + return true; + } else if (p_name == "display_placeholder") { + tile_set_scenes_collection_source->set_scene_tile_display_placeholder(scene_id, p_value); + emit_signal("changed", "display_placeholder"); + return true; + } + + return false; +} + +bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_get(const StringName &p_name, Variant &r_ret) const { + if (!tile_set_scenes_collection_source) { + return false; + } + + if (p_name == "id") { + r_ret = scene_id; + return true; + } else if (p_name == "scene") { + r_ret = tile_set_scenes_collection_source->get_scene_tile_scene(scene_id); + return true; + } else if (p_name == "display_placeholder") { + r_ret = tile_set_scenes_collection_source->get_scene_tile_display_placeholder(scene_id); + return true; + } + + return false; +} + +void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const { + if (!tile_set_scenes_collection_source) { + return; + } + + p_list->push_back(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_NONE, "")); + p_list->push_back(PropertyInfo(Variant::OBJECT, "scene", PROPERTY_HINT_RESOURCE_TYPE, "PackedScene")); + p_list->push_back(PropertyInfo(Variant::BOOL, "display_placeholder", PROPERTY_HINT_NONE, "")); +} + +void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::edit(TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_scene_id) { + ERR_FAIL_COND(!p_tile_set_scenes_collection_source); + ERR_FAIL_COND(!p_tile_set_scenes_collection_source->has_scene_tile_id(p_scene_id)); + + tile_set_scenes_collection_source = p_tile_set_scenes_collection_source; + scene_id = p_scene_id; + + notify_property_list_changed(); +} + +void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_bind_methods() { + ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what"))); +} + +void TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed(String p_what) { + if (p_what == "id") { + emit_signal("source_id_changed", scenes_collection_source_proxy_object->get_id()); + } +} + +void TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed() { + tile_set_scenes_collection_source_changed_needs_update = true; +} + +void TileSetScenesCollectionSourceEditor::_scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud) { + int index = p_ud; + + if (index >= 0 && index < scene_tiles_list->get_item_count()) { + scene_tiles_list->set_item_icon(index, p_preview); + } +} + +void TileSetScenesCollectionSourceEditor::_scenes_list_item_activated(int p_index) { + Ref<PackedScene> packed_scene = tile_set_scenes_collection_source->get_scene_tile_scene(scene_tiles_list->get_item_metadata(p_index)); + if (packed_scene.is_valid()) { + EditorNode::get_singleton()->open_request(packed_scene->get_path()); + } +} + +void TileSetScenesCollectionSourceEditor::_source_add_pressed() { + int scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id(); + undo_redo->create_action(TTR("Add a Scene Tile")); + undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", Ref<PackedScene>(), scene_id); + undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id); + undo_redo->commit_action(); + _update_scenes_list(); + _update_action_buttons(); + _update_tile_inspector(); +} + +void TileSetScenesCollectionSourceEditor::_source_delete_pressed() { + Vector<int> selected_indices = scene_tiles_list->get_selected_items(); + ERR_FAIL_COND(selected_indices.size() <= 0); + int scene_id = scene_tiles_list->get_item_metadata(selected_indices[0]); + + undo_redo->create_action(TTR("Remove a Scene Tile")); + undo_redo->add_do_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id); + undo_redo->add_undo_method(tile_set_scenes_collection_source, "create_scene_tile", tile_set_scenes_collection_source->get_scene_tile_scene(scene_id), scene_id); + undo_redo->commit_action(); + _update_scenes_list(); + _update_action_buttons(); + _update_tile_inspector(); +} + +void TileSetScenesCollectionSourceEditor::_update_source_inspector() { + // Update the proxy object. + scenes_collection_source_proxy_object->edit(tile_set, tile_set_scenes_collection_source, tile_set_source_id); +} + +void TileSetScenesCollectionSourceEditor::_update_tile_inspector() { + Vector<int> selected_indices = scene_tiles_list->get_selected_items(); + bool has_atlas_tile_selected = (selected_indices.size() > 0); + + // Update the proxy object. + if (has_atlas_tile_selected) { + int scene_id = scene_tiles_list->get_item_metadata(selected_indices[0]); + tile_proxy_object->edit(tile_set_scenes_collection_source, scene_id); + } + + // Update visibility. + tile_inspector_label->set_visible(has_atlas_tile_selected); + tile_inspector->set_visible(has_atlas_tile_selected); +} + +void TileSetScenesCollectionSourceEditor::_update_action_buttons() { + Vector<int> selected_indices = scene_tiles_list->get_selected_items(); + scene_tile_delete_button->set_disabled(selected_indices.size() <= 0); +} + +void TileSetScenesCollectionSourceEditor::_update_scenes_list() { + if (!tile_set_scenes_collection_source) { + return; + } + + // Get the previously selected id. + Vector<int> selected_indices = scene_tiles_list->get_selected_items(); + int old_selected_scene_id = (selected_indices.size() > 0) ? int(scene_tiles_list->get_item_metadata(selected_indices[0])) : -1; + + // Clear the list. + scene_tiles_list->clear(); + + // Rebuild the list. + int to_reselect = -1; + for (int i = 0; i < tile_set_scenes_collection_source->get_scene_tiles_count(); i++) { + int scene_id = tile_set_scenes_collection_source->get_scene_tile_id(i); + + Ref<PackedScene> scene = tile_set_scenes_collection_source->get_scene_tile_scene(scene_id); + + int item_index = 0; + if (scene.is_valid()) { + item_index = scene_tiles_list->add_item(vformat("%s (path:%s id:%d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id)); + Variant udata = i; + EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata); + } else { + item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon("PackedScene", "EditorIcons")); + } + scene_tiles_list->set_item_metadata(item_index, scene_id); + + if (old_selected_scene_id >= 0 && scene_id == old_selected_scene_id) { + to_reselect = i; + } + } + + // Reselect if needed. + if (to_reselect >= 0) { + scene_tiles_list->select(to_reselect); + } + + // Icon size update. + int int_size = int(EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size")) * EDSCALE; + scene_tiles_list->set_fixed_icon_size(Vector2(int_size, int_size)); +} + +void TileSetScenesCollectionSourceEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: + scene_tile_add_button->set_icon(get_theme_icon("Add", "EditorIcons")); + scene_tile_delete_button->set_icon(get_theme_icon("Remove", "EditorIcons")); + _update_scenes_list(); + break; + case NOTIFICATION_INTERNAL_PROCESS: + if (tile_set_scenes_collection_source_changed_needs_update) { + // Update everything. + _update_source_inspector(); + _update_scenes_list(); + _update_action_buttons(); + _update_tile_inspector(); + tile_set_scenes_collection_source_changed_needs_update = false; + } + break; + case NOTIFICATION_VISIBILITY_CHANGED: + // Update things just in case. + _update_scenes_list(); + _update_action_buttons(); + break; + default: + break; + } +} + +void TileSetScenesCollectionSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id) { + ERR_FAIL_COND(!p_tile_set.is_valid()); + ERR_FAIL_COND(!p_tile_set_scenes_collection_source); + ERR_FAIL_COND(p_source_id < 0); + ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source); + + if (p_tile_set == tile_set && p_tile_set_scenes_collection_source == tile_set_scenes_collection_source && p_source_id == tile_set_source_id) { + return; + } + + // Remove listener for old objects. + if (tile_set_scenes_collection_source) { + tile_set_scenes_collection_source->disconnect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed)); + } + + // Change the edited object. + tile_set = p_tile_set; + tile_set_scenes_collection_source = p_tile_set_scenes_collection_source; + tile_set_source_id = p_source_id; + + // Add the listener again. + if (tile_set_scenes_collection_source) { + tile_set_scenes_collection_source->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed)); + } + + // Update everything. + _update_source_inspector(); + _update_scenes_list(); + _update_action_buttons(); + _update_tile_inspector(); +} + +void TileSetScenesCollectionSourceEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + if (!can_drop_data_fw(p_point, p_data, p_from)) { + return; + } + + if (p_from == scene_tiles_list) { + // Handle dropping a texture in the list of atlas resources. + int scene_id = -1; + Dictionary d = p_data; + Vector<String> files = d["files"]; + for (int i = 0; i < files.size(); i++) { + Ref<PackedScene> resource = ResourceLoader::load(files[i]); + if (resource.is_valid()) { + scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id(); + undo_redo->create_action(TTR("Add a Scene Tile")); + undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", resource, scene_id); + undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id); + undo_redo->commit_action(); + } + } + + _update_scenes_list(); + _update_action_buttons(); + _update_tile_inspector(); + } +} + +bool TileSetScenesCollectionSourceEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + if (p_from == scene_tiles_list) { + Dictionary d = p_data; + + if (!d.has("type")) { + return false; + } + + // Check if we have a Texture2D. + if (String(d["type"]) == "files") { + Vector<String> files = d["files"]; + + if (files.size() == 0) { + return false; + } + + for (int i = 0; i < files.size(); i++) { + String file = files[i]; + String ftype = EditorFileSystem::get_singleton()->get_file_type(file); + + if (!ClassDB::is_parent_class(ftype, "PackedScene")) { + return false; + } + } + + return true; + } + } + return false; +} + +void TileSetScenesCollectionSourceEditor::_bind_methods() { + ADD_SIGNAL(MethodInfo("source_id_changed", PropertyInfo(Variant::INT, "source_id"))); + + ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileSetScenesCollectionSourceEditor::_scene_thumbnail_done); + ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &TileSetScenesCollectionSourceEditor::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("drop_data_fw"), &TileSetScenesCollectionSourceEditor::drop_data_fw); +} + +TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { + // -- Right side -- + HSplitContainer *split_container_right_side = memnew(HSplitContainer); + split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL); + add_child(split_container_right_side); + + // Middle panel. + ScrollContainer *middle_panel = memnew(ScrollContainer); + middle_panel->set_enable_h_scroll(false); + middle_panel->set_custom_minimum_size(Size2i(200, 0) * EDSCALE); + split_container_right_side->add_child(middle_panel); + + VBoxContainer *middle_vbox_container = memnew(VBoxContainer); + middle_vbox_container->set_h_size_flags(SIZE_EXPAND_FILL); + middle_panel->add_child(middle_vbox_container); + + // Scenes collection source inspector. + scenes_collection_source_inspector_label = memnew(Label); + scenes_collection_source_inspector_label->set_text(TTR("Scenes collection properties:")); + middle_vbox_container->add_child(scenes_collection_source_inspector_label); + + scenes_collection_source_proxy_object = memnew(TileSetScenesCollectionProxyObject()); + scenes_collection_source_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed)); + + scenes_collection_source_inspector = memnew(EditorInspector); + scenes_collection_source_inspector->set_undo_redo(undo_redo); + scenes_collection_source_inspector->set_enable_v_scroll(false); + scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object); + middle_vbox_container->add_child(scenes_collection_source_inspector); + + // Tile inspector. + tile_inspector_label = memnew(Label); + tile_inspector_label->set_text(TTR("Tile properties:")); + tile_inspector_label->hide(); + middle_vbox_container->add_child(tile_inspector_label); + + tile_proxy_object = memnew(SceneTileProxyObject(this)); + tile_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_scenes_list).unbind(1)); + tile_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1)); + + tile_inspector = memnew(EditorInspector); + tile_inspector->set_undo_redo(undo_redo); + tile_inspector->set_enable_v_scroll(false); + tile_inspector->edit(tile_proxy_object); + tile_inspector->set_use_folding(true); + middle_vbox_container->add_child(tile_inspector); + + // Scenes list. + VBoxContainer *right_vbox_container = memnew(VBoxContainer); + split_container_right_side->add_child(right_vbox_container); + + scene_tiles_list = memnew(ItemList); + scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL); + scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL); + scene_tiles_list->set_drag_forwarding(this); + scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_tile_inspector).unbind(1)); + scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1)); + scene_tiles_list->connect("item_activated", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_list_item_activated)); + scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); + right_vbox_container->add_child(scene_tiles_list); + + HBoxContainer *scenes_bottom_actions = memnew(HBoxContainer); + right_vbox_container->add_child(scenes_bottom_actions); + + scene_tile_add_button = memnew(Button); + scene_tile_add_button->set_flat(true); + scene_tile_add_button->connect("pressed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_source_add_pressed)); + scenes_bottom_actions->add_child(scene_tile_add_button); + + scene_tile_delete_button = memnew(Button); + scene_tile_delete_button->set_flat(true); + scene_tile_delete_button->set_disabled(true); + scene_tile_delete_button->connect("pressed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_source_delete_pressed)); + scenes_bottom_actions->add_child(scene_tile_delete_button); +} + +TileSetScenesCollectionSourceEditor::~TileSetScenesCollectionSourceEditor() { + memdelete(scenes_collection_source_proxy_object); + memdelete(tile_proxy_object); +} diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h new file mode 100644 index 0000000000..195aa79bc4 --- /dev/null +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h @@ -0,0 +1,139 @@ +/*************************************************************************/ +/* tile_set_scenes_collection_source_editor.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TILE_SET_SCENES_COLLECTION_SOURCE_EDITOR_H +#define TILE_SET_SCENES_COLLECTION_SOURCE_EDITOR_H + +#include "editor/editor_node.h" +#include "scene/gui/box_container.h" +#include "scene/resources/tile_set.h" + +class TileSetScenesCollectionSourceEditor : public HBoxContainer { + GDCLASS(TileSetScenesCollectionSourceEditor, HBoxContainer); + +private: + // -- Proxy object for an atlas source, needed by the inspector -- + class TileSetScenesCollectionProxyObject : public Object { + GDCLASS(TileSetScenesCollectionProxyObject, Object); + + private: + Ref<TileSet> tile_set; + TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr; + int source_id = -1; + + protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + static void _bind_methods(); + + public: + void set_id(int p_id); + int get_id(); + + void edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id); + }; + + // -- Proxy object for a tile, needed by the inspector -- + class SceneTileProxyObject : public Object { + GDCLASS(SceneTileProxyObject, Object); + + private: + TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor; + + TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr; + int source_id; + int scene_id; + + protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + + static void _bind_methods(); + + public: + // Update the proxyed object. + void edit(TileSetScenesCollectionSource *p_tile_set_atlas_source, int p_scene_id); + + SceneTileProxyObject(TileSetScenesCollectionSourceEditor *p_tiles_set_scenes_collection_source_editor) { + tile_set_scenes_collection_source_editor = p_tiles_set_scenes_collection_source_editor; + } + }; + +private: + Ref<TileSet> tile_set; + TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr; + int tile_set_source_id = -1; + + UndoRedo *undo_redo = EditorNode::get_undo_redo(); + + bool tile_set_scenes_collection_source_changed_needs_update = false; + + // Source inspector. + TileSetScenesCollectionProxyObject *scenes_collection_source_proxy_object; + Label *scenes_collection_source_inspector_label; + EditorInspector *scenes_collection_source_inspector; + + // Tile inspector. + SceneTileProxyObject *tile_proxy_object; + Label *tile_inspector_label; + EditorInspector *tile_inspector; + + ItemList *scene_tiles_list; + Button *scene_tile_add_button; + Button *scene_tile_delete_button; + + void _tile_set_scenes_collection_source_changed(); + void _scenes_collection_source_proxy_object_changed(String p_what); + void _scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud); + void _scenes_list_item_activated(int p_index); + + void _source_add_pressed(); + void _source_delete_pressed(); + + // Update methods. + void _update_source_inspector(); + void _update_tile_inspector(); + void _update_scenes_list(); + void _update_action_buttons(); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id); + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + TileSetScenesCollectionSourceEditor(); + ~TileSetScenesCollectionSourceEditor(); +}; + +#endif diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index 0af3b936cb..75a944e910 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -180,7 +180,7 @@ void VersionControlEditorPlugin::_stage_selected() { staged_files_count = 0; TreeItem *root = stage_files->get_root(); if (root) { - TreeItem *file_entry = root->get_children(); + TreeItem *file_entry = root->get_first_child(); while (file_entry) { if (file_entry->is_checked(0)) { EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0)); @@ -207,7 +207,7 @@ void VersionControlEditorPlugin::_stage_all() { staged_files_count = 0; TreeItem *root = stage_files->get_root(); if (root) { - TreeItem *file_entry = root->get_children(); + TreeItem *file_entry = root->get_first_child(); while (file_entry) { EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0)); file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor")); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 1d4c23fee6..18a1e7f693 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -729,7 +729,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { CodeEdit *expression_box = memnew(CodeEdit); Ref<CodeHighlighter> expression_syntax_highlighter; expression_syntax_highlighter.instance(); - expression_node->set_control(expression_box, 0); + expression_node->set_ctrl_pressed(expression_box, 0); node->add_child(expression_box); register_expression_edit(p_id, expression_box); @@ -1584,7 +1584,7 @@ void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(node.ptr()); Control *text_box = nullptr; if (!expression_node.is_null()) { - text_box = expression_node->get_control(0); + text_box = expression_node->is_ctrl_pressed(0); if (text_box) { text_box->set_custom_minimum_size(Size2(0, 0)); } @@ -2427,7 +2427,7 @@ void VisualShaderEditor::_convert_constants_to_uniforms(bool p_vice_versa) { for (Set<int>::Element *E = current_set.front(); E; E = E->next()) { int node_id = E->get(); Ref<VisualShaderNode> node = visual_shader->get_node(type_id, node_id); - bool catched = false; + bool caught = false; Variant var; // float @@ -2436,112 +2436,112 @@ void VisualShaderEditor::_convert_constants_to_uniforms(bool p_vice_versa) { if (float_const.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeFloatConstant", "VisualShaderNodeFloatUniform"); var = float_const->get_constant(); - catched = true; + caught = true; } } else { Ref<VisualShaderNodeFloatUniform> float_uniform = Object::cast_to<VisualShaderNodeFloatUniform>(node.ptr()); if (float_uniform.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeFloatUniform", "VisualShaderNodeFloatConstant"); var = float_uniform->get_default_value(); - catched = true; + caught = true; } } // int - if (!catched) { + if (!caught) { if (!p_vice_versa) { Ref<VisualShaderNodeIntConstant> int_const = Object::cast_to<VisualShaderNodeIntConstant>(node.ptr()); if (int_const.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeIntConstant", "VisualShaderNodeIntUniform"); var = int_const->get_constant(); - catched = true; + caught = true; } } else { Ref<VisualShaderNodeIntUniform> int_uniform = Object::cast_to<VisualShaderNodeIntUniform>(node.ptr()); if (int_uniform.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeIntUniform", "VisualShaderNodeIntConstant"); var = int_uniform->get_default_value(); - catched = true; + caught = true; } } } // boolean - if (!catched) { + if (!caught) { if (!p_vice_versa) { Ref<VisualShaderNodeBooleanConstant> boolean_const = Object::cast_to<VisualShaderNodeBooleanConstant>(node.ptr()); if (boolean_const.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeBooleanConstant", "VisualShaderNodeBooleanUniform"); var = boolean_const->get_constant(); - catched = true; + caught = true; } } else { Ref<VisualShaderNodeBooleanUniform> boolean_uniform = Object::cast_to<VisualShaderNodeBooleanUniform>(node.ptr()); if (boolean_uniform.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeBooleanUniform", "VisualShaderNodeBooleanConstant"); var = boolean_uniform->get_default_value(); - catched = true; + caught = true; } } } // vec3 - if (!catched) { + if (!caught) { if (!p_vice_versa) { Ref<VisualShaderNodeVec3Constant> vec3_const = Object::cast_to<VisualShaderNodeVec3Constant>(node.ptr()); if (vec3_const.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeVec3Constant", "VisualShaderNodeVec3Uniform"); var = vec3_const->get_constant(); - catched = true; + caught = true; } } else { Ref<VisualShaderNodeVec3Uniform> vec3_uniform = Object::cast_to<VisualShaderNodeVec3Uniform>(node.ptr()); if (vec3_uniform.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeVec3Uniform", "VisualShaderNodeVec3Constant"); var = vec3_uniform->get_default_value(); - catched = true; + caught = true; } } } // color - if (!catched) { + if (!caught) { if (!p_vice_versa) { Ref<VisualShaderNodeColorConstant> color_const = Object::cast_to<VisualShaderNodeColorConstant>(node.ptr()); if (color_const.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeColorConstant", "VisualShaderNodeColorUniform"); var = color_const->get_constant(); - catched = true; + caught = true; } } else { Ref<VisualShaderNodeColorUniform> color_uniform = Object::cast_to<VisualShaderNodeColorUniform>(node.ptr()); if (color_uniform.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeColorUniform", "VisualShaderNodeColorConstant"); var = color_uniform->get_default_value(); - catched = true; + caught = true; } } } // transform - if (!catched) { + if (!caught) { if (!p_vice_versa) { Ref<VisualShaderNodeTransformConstant> transform_const = Object::cast_to<VisualShaderNodeTransformConstant>(node.ptr()); if (transform_const.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeTransformConstant", "VisualShaderNodeTransformUniform"); var = transform_const->get_constant(); - catched = true; + caught = true; } } else { Ref<VisualShaderNodeTransformUniform> transform_uniform = Object::cast_to<VisualShaderNodeTransformUniform>(node.ptr()); if (transform_uniform.is_valid()) { _replace_node(type_id, node_id, "VisualShaderNodeTransformUniform", "VisualShaderNodeTransformConstant"); var = transform_uniform->get_default_value(); - catched = true; + caught = true; } } } - ERR_CONTINUE(!catched); + ERR_CONTINUE(!caught); int preview_port = node->get_output_port_for_preview(); if (!p_vice_versa) { @@ -2762,10 +2762,10 @@ void VisualShaderEditor::_notification(int p_what) { // collapse tree by default - TreeItem *category = members->get_root()->get_children(); + TreeItem *category = members->get_root()->get_first_child(); while (category) { category->set_collapsed(true); - TreeItem *sub_category = category->get_children(); + TreeItem *sub_category = category->get_first_child(); while (sub_category) { sub_category->set_collapsed(true); sub_category = sub_category->get_next(); @@ -3210,14 +3210,14 @@ void VisualShaderEditor::_member_cancel() { } void VisualShaderEditor::_tools_menu_option(int p_idx) { - TreeItem *category = members->get_root()->get_children(); + TreeItem *category = members->get_root()->get_first_child(); switch (p_idx) { case EXPAND_ALL: while (category) { category->set_collapsed(false); - TreeItem *sub_category = category->get_children(); + TreeItem *sub_category = category->get_first_child(); while (sub_category) { sub_category->set_collapsed(false); sub_category = sub_category->get_next(); @@ -3231,7 +3231,7 @@ void VisualShaderEditor::_tools_menu_option(int p_idx) { while (category) { category->set_collapsed(true); - TreeItem *sub_category = category->get_children(); + TreeItem *sub_category = category->get_first_child(); while (sub_category) { sub_category->set_collapsed(true); sub_category = sub_category->get_next(); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 3ede50320a..9b99372735 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -795,7 +795,7 @@ void ProjectExportDialog::_tree_changed() { } void ProjectExportDialog::_check_dir_recursive(TreeItem *p_dir, bool p_checked) { - for (TreeItem *child = p_dir->get_children(); child; child = child->get_next()) { + for (TreeItem *child = p_dir->get_first_child(); child; child = child->get_next()) { String path = child->get_metadata(0); child->set_checked(0, p_checked); @@ -818,7 +818,7 @@ void ProjectExportDialog::_refresh_parent_checks(TreeItem *p_item) { } bool checked = true; - for (TreeItem *child = parent->get_children(); child; child = child->get_next()) { + for (TreeItem *child = parent->get_first_child(); child; child = child->get_next()) { checked = checked && child->is_checked(0); if (!checked) { break; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 2b75144ac7..49a6d28dc1 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -100,7 +100,6 @@ private: FileDialog *fdialog_install; String zip_path; String zip_title; - String zip_root; AcceptDialog *dialog_error; String fav_dir; @@ -201,9 +200,7 @@ private: char fname[16384]; ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - String fname_str = String(fname); - if (fname_str.ends_with("project.godot")) { - zip_root = fname_str.substr(0, fname_str.rfind("project.godot")); + if (String(fname).ends_with("project.godot")) { break; } @@ -524,7 +521,24 @@ private: return; } + // Find the zip_root + String zip_root; int ret = unzGoToFirstFile(pkg); + while (ret == UNZ_OK) { + unz_file_info info; + char fname[16384]; + unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); + + String name = fname; + if (name.ends_with("project.godot")) { + zip_root = name.substr(0, name.rfind("project.godot")); + break; + } + + ret = unzGoToNextFile(pkg); + } + + ret = unzGoToFirstFile(pkg); Vector<String> failed_files; @@ -1740,7 +1754,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) { const Item &clicked_project = _projects[clicked_index]; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { - if (mb->get_shift() && _selected_project_keys.size() > 0 && _last_clicked != "" && clicked_project.project_key != _last_clicked) { + if (mb->is_shift_pressed() && _selected_project_keys.size() > 0 && _last_clicked != "" && clicked_project.project_key != _last_clicked) { int anchor_index = -1; for (int i = 0; i < _projects.size(); ++i) { const Item &p = _projects[i]; @@ -1752,7 +1766,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) { CRASH_COND(anchor_index == -1); select_range(anchor_index, clicked_index); - } else if (mb->get_control()) { + } else if (mb->is_ctrl_pressed()) { toggle_select(clicked_index); } else { @@ -1762,7 +1776,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) { emit_signal(SIGNAL_SELECTION_CHANGED); - if (!mb->get_control() && mb->is_double_click()) { + if (!mb->is_ctrl_pressed() && mb->is_double_click()) { emit_signal(SIGNAL_PROJECT_ASK_OPEN); } } @@ -1937,7 +1951,7 @@ void ProjectManager::_unhandled_key_input(const Ref<InputEvent> &p_ev) { } break; case KEY_UP: { - if (k->get_shift()) { + if (k->is_shift_pressed()) { break; } @@ -1951,7 +1965,7 @@ void ProjectManager::_unhandled_key_input(const Ref<InputEvent> &p_ev) { break; } case KEY_DOWN: { - if (k->get_shift()) { + if (k->is_shift_pressed()) { break; } @@ -1964,7 +1978,7 @@ void ProjectManager::_unhandled_key_input(const Ref<InputEvent> &p_ev) { } break; case KEY_F: { - if (k->get_command()) { + if (k->is_command_pressed()) { this->search_box->grab_focus(); } else { keycode_handled = false; @@ -2124,8 +2138,8 @@ void ProjectManager::_run_project_confirm() { const String &selected = selected_list[i].project_key; String path = EditorSettings::get_singleton()->get("projects/" + selected); - // `.right(6)` on `IMPORTED_FILES_PATH` strips away the leading "res://". - if (!DirAccess::exists(path.plus_file(ProjectSettings::IMPORTED_FILES_PATH.right(6)))) { + // `.substr(6)` on `IMPORTED_FILES_PATH` strips away the leading "res://". + if (!DirAccess::exists(path.plus_file(ProjectSettings::IMPORTED_FILES_PATH.substr(6)))) { run_error_diag->set_text(TTR("Can't run project: Assets need to be imported.\nPlease edit the project to trigger the initial import.")); run_error_diag->popup_centered(); continue; diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index da798962e5..bf31be536c 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -52,7 +52,7 @@ void PropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) { search_box->accept_event(); TreeItem *root = search_options->get_root(); - if (!root->get_children()) { + if (!root->get_first_child()) { break; } @@ -150,7 +150,7 @@ void PropertySelector::_update_search() { for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { if (E->get().usage == PROPERTY_USAGE_CATEGORY) { - if (category && category->get_children() == nullptr) { + if (category && category->get_first_child() == nullptr) { memdelete(category); //old category was unused } category = search_options->create_item(root); @@ -192,7 +192,7 @@ void PropertySelector::_update_search() { item->set_selectable(0, true); } - if (category && category->get_children() == nullptr) { + if (category && category->get_first_child() == nullptr) { memdelete(category); //old category was unused } } else { @@ -225,7 +225,7 @@ void PropertySelector::_update_search() { for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) { if (E->get().name.begins_with("*")) { - if (category && category->get_children() == nullptr) { + if (category && category->get_first_child() == nullptr) { memdelete(category); //old category was unused } category = search_options->create_item(root); @@ -316,12 +316,12 @@ void PropertySelector::_update_search() { } } - if (category && category->get_children() == nullptr) { + if (category && category->get_first_child() == nullptr) { memdelete(category); //old category was unused } } - get_ok_button()->set_disabled(root->get_children() == nullptr); + get_ok_button()->set_disabled(root->get_first_child() == nullptr); } void PropertySelector::_confirmed() { diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index 7f720d65d0..e8e13bab21 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -102,7 +102,7 @@ void EditorQuickOpen::_update_search() { ti->set_icon(0, *icons.lookup_ptr(entries[i].path.get_extension())); } - TreeItem *to_select = root->get_children(); + TreeItem *to_select = root->get_first_child(); to_select->select(0); to_select->set_as_cursor(0); search_options->scroll_to_item(to_select); @@ -170,7 +170,7 @@ void EditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) { if (allow_multi_select) { TreeItem *root = search_options->get_root(); - if (!root->get_children()) { + if (!root->get_first_child()) { break; } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 4068a102df..349e05b47b 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1833,7 +1833,7 @@ bool SceneTreeDock::_is_collapsed_recursive(TreeItem *p_item) const { TreeItem *item = needs_check.back()->get(); needs_check.pop_back(); - TreeItem *child = item->get_children(); + TreeItem *child = item->get_first_child(); is_branch_collapsed = item->is_collapsed() && child; if (is_branch_collapsed) { @@ -1857,7 +1857,7 @@ void SceneTreeDock::_set_collapsed_recursive(TreeItem *p_item, bool p_collapsed) item->set_collapsed(p_collapsed); - TreeItem *child = item->get_children(); + TreeItem *child = item->get_first_child(); while (child) { to_collapse.push_back(child); child = child->get_next(); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index d0bf83eb2d..6f9b0ae873 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -699,7 +699,7 @@ TreeItem *SceneTreeEditor::_find(TreeItem *p_node, const NodePath &p_path) { return p_node; } - TreeItem *children = p_node->get_children(); + TreeItem *children = p_node->get_first_child(); while (children) { TreeItem *n = _find(children, p_path); if (n) { @@ -883,7 +883,7 @@ void SceneTreeEditor::_update_selection(TreeItem *item) { item->deselect(0); } - TreeItem *c = item->get_children(); + TreeItem *c = item->get_first_child(); while (c) { _update_selection(c); diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index 541ec224b9..4cdf820877 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -235,8 +235,8 @@ void EditorSettingsDialog::_update_shortcuts() { // Before clearing the tree, take note of which categories are collapsed so that this state can be maintained when the tree is repopulated. Map<String, bool> collapsed; - if (shortcuts->get_root() && shortcuts->get_root()->get_children()) { - for (TreeItem *item = shortcuts->get_root()->get_children(); item; item = item->get_next()) { + if (shortcuts->get_root() && shortcuts->get_root()->get_first_child()) { + for (TreeItem *item = shortcuts->get_root()->get_first_child(); item; item = item->get_next()) { collapsed[item->get_text(0)] = item->is_collapsed(); } } @@ -380,7 +380,7 @@ void EditorSettingsDialog::_update_shortcuts() { // remove sections with no shortcuts for (Map<String, TreeItem *>::Element *E = sections.front(); E; E = E->next()) { TreeItem *section = E->get(); - if (section->get_children() == nullptr) { + if (section->get_first_child() == nullptr) { root->remove_child(section); } } diff --git a/editor/translations/af.po b/editor/translations/af.po index c528e2a063..887b7983eb 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -2590,7 +2590,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -3006,6 +3006,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5266,16 +5270,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/ar.po b/editor/translations/ar.po index 52c609055c..a93fc9a473 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -2568,7 +2568,7 @@ msgstr "غير قادر علي تØميل النص البرمجي للإضاÙØ© #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "غير قادر علي تØميل النص البرمجي الإضاÙب من المسار: '%s' يبدو أن Ø´ÙÙرة " @@ -3018,6 +3018,10 @@ msgid "About" msgstr "Øول" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "تشغيل المشروع." @@ -5233,18 +5237,9 @@ msgstr "" "[0.0ØŒ1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "تم تجميع Ù…Øرر Godot دون دعم لتتبع الأشعة. لا يمكن بناء خرائط الإضاءة." #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/az.po b/editor/translations/az.po index 266e51d7fe..1dcbe3a7a5 100644 --- a/editor/translations/az.po +++ b/editor/translations/az.po @@ -2512,7 +2512,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2918,6 +2918,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5072,16 +5076,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/bg.po b/editor/translations/bg.po index 6f0b756ce1..4005ff2090 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -2457,7 +2457,7 @@ msgstr "Ðе може да Ñе зареди добавката-Ñкрипт Ð¾Ñ #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Ðе може да Ñе зареди добавката-Ñкрипт от: „%s“. Изглежда има грешка в кода. " @@ -2886,6 +2886,10 @@ msgid "About" msgstr "ОтноÑно" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "ПуÑкане на проекта." @@ -5065,18 +5069,9 @@ msgstr "" "принадлежат на квадратната облаÑÑ‚ [0.0,1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Редакторът на Godot е бил компилиран без поддръжка за траÑиране на лъчи. Ðе " "могат да Ñе изпичат карти на оÑветеноÑÑ‚." diff --git a/editor/translations/bn.po b/editor/translations/bn.po index d47fbe367c..5192cd4164 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -2655,7 +2655,7 @@ msgstr "%s হতে সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ তà§à¦²à¦¤à§‡/লোডে ঠ#, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "'%s' পাথ বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦° করে অà§à¦¯à¦¾à¦¡-অন সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ লোড করা সমà§à¦à¦¬ হয়নি। সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿà¦Ÿà¦¿ টà§à¦² মোডে নেই।" @@ -3136,6 +3136,10 @@ msgid "About" msgstr "সমà§à¦¬à¦¨à§à¦§à§‡" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "পà§à¦°à¦•à¦²à§à¦ªà¦Ÿà¦¿ চালান।" @@ -5550,16 +5554,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/br.po b/editor/translations/br.po index ab03bb5425..dfab47a0e2 100644 --- a/editor/translations/br.po +++ b/editor/translations/br.po @@ -2457,7 +2457,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2863,6 +2863,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5017,16 +5021,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/ca.po b/editor/translations/ca.po index 4086771705..3346449af2 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -2561,7 +2561,7 @@ msgstr "Error carregant l'Script complement des del camÃ: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "No es pot carregar l'script d'addon des del camÃ: '%s' Sembla que hi ha un " @@ -3017,6 +3017,10 @@ msgid "About" msgstr "Quant a" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Reprodueix el projecte." @@ -5285,16 +5289,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/cs.po b/editor/translations/cs.po index b0d92db7a0..b37f9a6a3f 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -2550,7 +2550,7 @@ msgstr "Nelze naÄÃst skript rozÅ¡ÃÅ™enà z cesty: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Nelze naÄÃst skript rozÅ¡ÃÅ™enà z cesty: '%s'. Zdá se, že se v kódu nacházà " @@ -2994,6 +2994,10 @@ msgid "About" msgstr "O aplikaci" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Spustit projekt." @@ -5215,18 +5219,9 @@ msgstr "" "Ätvercové oblasti [0.0, 1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Godot byl sestaven bez podpory ray tracingu, svÄ›telné mapy nelze zapéct." diff --git a/editor/translations/da.po b/editor/translations/da.po index 64e6e1c517..3cb65a5d82 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -2639,7 +2639,7 @@ msgstr "Kan ikke indlæse addon script fra stien: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Kan ikke indlæse tilføjelse script fra sti: '%s' Der ser ud til at være en " @@ -3102,6 +3102,10 @@ msgid "About" msgstr "Om" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Spil dit projekt." @@ -5406,16 +5410,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/de.po b/editor/translations/de.po index 4bfa2e5796..1c6136ff6f 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -72,8 +72,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-05-03 21:29+0000\n" -"Last-Translator: Günther Bohn <ciscouser@gmx.de>\n" +"PO-Revision-Date: 2021-05-14 20:34+0000\n" +"Last-Translator: So Wieso <sowieso@dukun.de>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot/de/>\n" "Language: de\n" @@ -2617,14 +2617,14 @@ msgid "Unable to load addon script from path: '%s'." msgstr "Erweiterungsskript konnte nicht geladen werden: ‚%s‘." #: editor/editor_node.cpp -#, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" -"Erweiterungsskript konnte nicht von folgendem Pfad geladen werden: ‚%s‘. Es " -"scheint ein Fehler im Quellcode zu sein. Bitte Syntax überprüfen." +"Erweiterungsskript auf folgendem Pfad konnte nicht geladen werden: ‚%s‘. Es " +"scheint ein Fehler in dessen Quellcode zu sein.\n" +"Die Erweiterung ‚%s‘ wird deaktiviert um weitere Fehler zu verhindern." #: editor/editor_node.cpp msgid "" @@ -3075,6 +3075,10 @@ msgid "About" msgstr "Ãœber" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Projekt abspielen." @@ -5312,20 +5316,11 @@ msgstr "" "Kanals im Bereich von 0.0 bis 1.0 liegen." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" -"Diese Godot-Version wurde ohne Raytracing-Unterstützung erstellt, Lightmaps " +"Der Godot-Editor wurde ohne Raytracing-Unterstützung erstellt; Lightmaps " "können damit nicht gebacken werden." #: editor/plugins/baked_lightmap_editor_plugin.cpp @@ -13333,6 +13328,18 @@ msgid "Constants cannot be modified." msgstr "Konstanten können nicht verändert werden." #~ msgid "" +#~ "Godot editor was built without ray tracing support; lightmaps can't be " +#~ "baked.\n" +#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta " +#~ "emulation on Godot.app in the application settings\n" +#~ "then restart the editor." +#~ msgstr "" +#~ "Der Godot-Editor wurde ohne Raytracing-Unterstützung gebaut; Lightmaps " +#~ "können nicht gebacken werden.\n" +#~ "Nutzer eines Macs basierend auf Apple Silicon sollten Rosetta-Emulation " +#~ "in den Anwendungseinstellungen aktivieren und den Editor neu starten." + +#~ msgid "" #~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0." #~ msgstr "" #~ "InterpolatedCamera ist veraltet und wird in Godot 4.0 entfernt werden." diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index 2483cd1ed4..5ffb9f106d 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -2435,7 +2435,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2841,6 +2841,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -4995,16 +4999,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/el.po b/editor/translations/el.po index bbd2148968..591ad55930 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -2560,7 +2560,7 @@ msgstr "ΑδÏνατη η φόÏτωση δÎσμης ενεÏγειών Ï€ÏÎ¿Ï #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Αποτυχία φόÏτωσης δÎσμης ενεÏγειών Ï€ÏοσθÎτου από τη διαδÏομή: '%s'. Φαίνεται " @@ -3015,6 +3015,10 @@ msgid "About" msgstr "Σχετικά" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "ΑναπαÏαγωγή του ÎÏγου." @@ -5257,16 +5261,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/eo.po b/editor/translations/eo.po index b03935e346..4bb0dcbeae 100644 --- a/editor/translations/eo.po +++ b/editor/translations/eo.po @@ -2518,7 +2518,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2950,6 +2950,10 @@ msgid "About" msgstr "Pri" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Stari la projekton." @@ -5126,16 +5130,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/es.po b/editor/translations/es.po index 15c577a9c8..643fb16a57 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -2614,7 +2614,7 @@ msgstr "No se pudo cargar el script addon desde la ruta: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "No se puede cargar el script de addon desde la ruta: '%s' Parece que hay un " @@ -3068,6 +3068,10 @@ msgid "About" msgstr "Acerca de" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Reproducir el proyecto." @@ -5312,18 +5316,9 @@ msgstr "" "están contenidos dentro de la región cuadrangular [0,0,1,0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "El editor de Godot se construyó sin soporte de trazado de rayos, los " "lightmaps no pueden ser bakeados." diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index 524f628f6c..5441d3def1 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -2567,7 +2567,7 @@ msgstr "No se pudo cargar el script de addon desde la ruta: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "No se pudo cargar el script de addon desde la ruta: '%s' Parece haber un " @@ -3019,6 +3019,10 @@ msgid "About" msgstr "Acerca de" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Reproducir el proyecto." @@ -5262,18 +5266,9 @@ msgstr "" "contenidos dentro de la región cuadrada [0,0,1,0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "El editor de Godot se compiló sin soporte de ray tracing, los lightmaps no " "pueden ser bakeados." diff --git a/editor/translations/et.po b/editor/translations/et.po index cd60a34dc2..e4b33e89a0 100644 --- a/editor/translations/et.po +++ b/editor/translations/et.po @@ -2484,7 +2484,7 @@ msgstr "Lisa-skripti ei olnud võimalik laadida teelt: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Lisa-skripti ei olnud võimalik laadida teelt: '%s'. Tundub, et koodis on " @@ -2897,6 +2897,10 @@ msgid "About" msgstr "Teave" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Mängi projekti." @@ -5054,16 +5058,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/eu.po b/editor/translations/eu.po index 6dc3f5645f..26f1c1a3bd 100644 --- a/editor/translations/eu.po +++ b/editor/translations/eu.po @@ -2450,7 +2450,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2856,6 +2856,10 @@ msgid "About" msgstr "Honi buruz" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5018,16 +5022,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/fa.po b/editor/translations/fa.po index e2acd6a256..54cf408469 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -2492,7 +2492,7 @@ msgstr "امکان بارگیری اسکریپت اÙزونه از مسیر وج #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2907,6 +2907,10 @@ msgid "About" msgstr "درباره" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "اجرای پروژه." @@ -5207,16 +5211,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/fi.po b/editor/translations/fi.po index 81688234f2..912e0f14f4 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -16,7 +16,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-04-22 14:40+0000\n" +"PO-Revision-Date: 2021-05-18 10:00+0000\n" "Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n" "Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/" "godot/fi/>\n" @@ -2539,14 +2539,14 @@ msgid "Unable to load addon script from path: '%s'." msgstr "Virhe ladattaessa lisäosaa polusta: '%s'." #: editor/editor_node.cpp -#, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" -"Virhe ladattaessa lisäosaa polusta: '%s'. Koodissa vaikuttaa olevan virhe, " -"ole hyvä ja tarkista syntaksi." +"Lisäosaskriptin lataus ei onnistunut polusta: '%s'. Tämä saattaa johtua " +"koodivirheestä skriptissä.\n" +"Lisäosa '%s' poistetaan käytöstä tulevien virheiden estämiseksi." #: editor/editor_node.cpp msgid "" @@ -2985,6 +2985,10 @@ msgid "About" msgstr "Tietoja" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Käynnistä projekti." @@ -5218,18 +5222,9 @@ msgstr "" "välisen neliön alueella." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Godot-editori on käännetty ilman ray tracing -tukea, joten lightmappeja ei " "voi kehittää." @@ -13174,6 +13169,19 @@ msgid "Constants cannot be modified." msgstr "Vakioita ei voi muokata." #~ msgid "" +#~ "Godot editor was built without ray tracing support; lightmaps can't be " +#~ "baked.\n" +#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta " +#~ "emulation on Godot.app in the application settings\n" +#~ "then restart the editor." +#~ msgstr "" +#~ "Godot-editori on käännetty ilman ray tracing -tukea, joten lightmappeja " +#~ "ei voi kehittää.\n" +#~ "Jos käytät Apple Silicon -pohjaista Mac-tietokonetta, yritä pakottaa " +#~ "Rosetta-emulaatio Godot.app:iin sovelluksen asetuksissa\n" +#~ "ja käynnistä sitten editori uudestaan." + +#~ msgid "" #~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0." #~ msgstr "" #~ "InterpolatedCamera on vanhentunut ja poistetaan Godot 4.0 versiossa." diff --git a/editor/translations/fil.po b/editor/translations/fil.po index 8798d8034f..525dc19561 100644 --- a/editor/translations/fil.po +++ b/editor/translations/fil.po @@ -2450,7 +2450,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2856,6 +2856,10 @@ msgid "About" msgstr "Tungkol" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5013,16 +5017,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/fr.po b/editor/translations/fr.po index 0e71b3ea89..95af6d8a20 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -2634,14 +2634,14 @@ msgstr "" "Impossible de charger le script de l’extension depuis le chemin : « %s »." #: editor/editor_node.cpp -#, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" -"Impossible de charger le script de l’extension depuis le chemin : « %s ». Il " -"semble y avoir une erreur dans le code, merci de vérifier la syntaxe." +"Impossible de charger le script de l’extension depuis le chemin : « %s ». " +"Cela peut être dû à une erreur de programmation dans ce script.\n" +"L'extension « %s » a été désactivée pour prévenir de nouvelles erreures." #: editor/editor_node.cpp msgid "" @@ -3092,6 +3092,10 @@ msgid "About" msgstr "À propos" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "Soutenir le développement de Godot" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Lancer le projet." @@ -3198,7 +3202,7 @@ msgstr "" "personnalisé à l'exportation (ajout de modules, modification du fichier " "AndroidManifest.xml, etc.).\n" "Notez que pour faire des compilations personnalisées au lieu d'utiliser des " -"APKs pré-construits, l'option \"Use Custom Build\" doit être activée dans le " +"APKs préconstruits, l'option \"Use Custom Build\" doit être activée dans le " "Preset d'exportation Android." #: editor/editor_node.cpp @@ -5338,20 +5342,10 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -#, fuzzy -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "L'éditeur Godot a été compilé sans support du ray tracing, les lightmaps ne " -"peuvent pas être pré-calculées." +"peuvent pas être précalculées." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Bake Lightmaps" @@ -5359,7 +5353,7 @@ msgstr "Précalculer les lightmaps" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Select lightmap bake file:" -msgstr "Sélectionnez le fichier de pré-calcul de lightmap :" +msgstr "Sélectionnez le fichier de précalcul de lightmap :" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -11809,7 +11803,7 @@ msgstr "" #: modules/lightmapper_cpu/lightmapper_cpu.cpp msgid "Begin Bake" -msgstr "Commencer le pré-calcul" +msgstr "Commencer le précalcul" #: modules/lightmapper_cpu/lightmapper_cpu.cpp msgid "Preparing data structures" diff --git a/editor/translations/ga.po b/editor/translations/ga.po index 134331d7bf..cbecefd928 100644 --- a/editor/translations/ga.po +++ b/editor/translations/ga.po @@ -2445,7 +2445,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2851,6 +2851,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5010,16 +5014,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/gl.po b/editor/translations/gl.po index 816b4234fa..0e30715772 100644 --- a/editor/translations/gl.po +++ b/editor/translations/gl.po @@ -2544,7 +2544,7 @@ msgstr "" #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Non se puido cargar Script de caracterÃstica adicional (Addon) na ruta: " @@ -2993,6 +2993,10 @@ msgid "About" msgstr "Acerca De" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Reproduce o proxecto." @@ -5181,16 +5185,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/he.po b/editor/translations/he.po index 831c34978c..bb16512835 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -2544,7 +2544,7 @@ msgstr "×œ× × ×™×ª×Ÿ לטעון סקריפט הרחבה ×ž× ×ª×™×‘: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "×œ× × ×™×ª×Ÿ לטעון סקריפט הרחבה ×ž× ×ª×™×‘: '%s' × ×¨××” שיש שגי××” בקוד, ×× × ×‘×“×•×§ ×ת " @@ -2980,6 +2980,10 @@ msgid "About" msgstr "על ×ודות" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "הרצת המיז×." @@ -5230,16 +5234,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/hi.po b/editor/translations/hi.po index d10b2e81c0..cf1ab6d57a 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -2522,7 +2522,7 @@ msgstr "पथ से à¤à¤¡à¤‘न सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ लोड करà #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "रासà¥à¤¤à¥‡ से à¤à¤¡à¤‘न सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ लोड करने में असमरà¥à¤¥: '% à¤à¤¸' कोड में गड़बड़ी लगती है, कृपया सिंटेकà¥à¤¸ की " @@ -2961,6 +2961,10 @@ msgid "About" msgstr "के बारे में" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "पà¥à¤°à¥‹à¤œà¥‡à¤•à¥à¤Ÿ चलाà¤à¤‚।" @@ -5152,16 +5156,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/hr.po b/editor/translations/hr.po index 7fec3f22ac..a78a4f01c3 100644 --- a/editor/translations/hr.po +++ b/editor/translations/hr.po @@ -2457,7 +2457,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2863,6 +2863,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5024,16 +5028,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/hu.po b/editor/translations/hu.po index ff223c33d3..76aaf2da96 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -2564,7 +2564,7 @@ msgstr "Nem sikerült az addon szkript betöltése a következÅ‘ útvonalról: ' #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Nem lehet betölteni az addon szkriptet a(z) '%s' útvonalról. Úgy tűnik, hiba " @@ -3009,6 +3009,10 @@ msgid "About" msgstr "Névjegy" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Projekt futtatása." @@ -5203,16 +5207,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/id.po b/editor/translations/id.po index a53c0a385a..13ce1dba23 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -2564,7 +2564,7 @@ msgstr "Tidak bisa memuat script addon dari lokasi: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Tidak dapat memuat script addon dari path: '%s' Mungkin ada kesalahan dalam " @@ -3011,6 +3011,10 @@ msgid "About" msgstr "Tentang" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Mainkan proyek." @@ -5231,18 +5235,9 @@ msgstr "" "persegi [0.0,1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Editor Godot di-build tanpa dukungan ray tracing, sehingga lightmaps tidak " "dapat di-bake." diff --git a/editor/translations/is.po b/editor/translations/is.po index 92b71ba410..693a6f9397 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -2482,7 +2482,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2891,6 +2891,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5066,16 +5070,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/it.po b/editor/translations/it.po index c98565ba1b..e087489c94 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -2609,7 +2609,7 @@ msgstr "" #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Impossibile caricare uno script aggiuntivo dal percorso: \"%s\" Sembra " @@ -3060,6 +3060,10 @@ msgid "About" msgstr "Informazioni su Godot" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Esegui il progetto." @@ -5301,18 +5305,9 @@ msgstr "" "all'interno nella regione [0.0,1.0] quadra." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Godot Editor è stato costruito senza il supporto per il ray tracing, quindi " "il baking delle lightmaps non è possibile." diff --git a/editor/translations/ja.po b/editor/translations/ja.po index 138cee8cb3..3e03c04b72 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -2565,7 +2565,7 @@ msgstr "パス '%s' ã‹ã‚‰ã‚¢ãƒ‰ã‚ªãƒ³ã‚¹ã‚¯ãƒªãƒ—トをèªè¾¼ã‚ã¾ã›ã‚“。" #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "パス '%s' ã‹ã‚‰ã‚¢ãƒ‰ã‚ªãƒ³ã‚¹ã‚¯ãƒªãƒ—トをèªã¿è¾¼ã‚ã¾ã›ã‚“。コードã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚‹å¯èƒ½æ€§" @@ -3013,6 +3013,10 @@ msgid "About" msgstr "概è¦" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "プãƒã‚¸ã‚§ã‚¯ãƒˆã‚’実行。" @@ -5239,18 +5243,9 @@ msgstr "" "ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。" #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "GodotエディタãŒãƒ¬ã‚¤ãƒˆãƒ¬ãƒ¼ã‚·ãƒ³ã‚°ã«å¯¾å¿œã›ãšã«ãƒ“ルドã•ã‚Œã¦ãŠã‚Šã€ãƒ©ã‚¤ãƒˆãƒžãƒƒãƒ—ã®ãƒ™" "イクãŒã§ãã¾ã›ã‚“。" diff --git a/editor/translations/ka.po b/editor/translations/ka.po index a2972e9c1e..fd1f34ae59 100644 --- a/editor/translations/ka.po +++ b/editor/translations/ka.po @@ -2562,7 +2562,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2975,6 +2975,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5192,16 +5196,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/km.po b/editor/translations/km.po index 25785c2415..3d0c4b2f9d 100644 --- a/editor/translations/km.po +++ b/editor/translations/km.po @@ -2441,7 +2441,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2847,6 +2847,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5001,16 +5005,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/ko.po b/editor/translations/ko.po index 287df00aab..604479435e 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -26,7 +26,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-05-03 06:13+0000\n" +"PO-Revision-Date: 2021-05-18 10:00+0000\n" "Last-Translator: Myeongjin Lee <aranet100@gmail.com>\n" "Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/" "godot/ko/>\n" @@ -2544,14 +2544,14 @@ msgid "Unable to load addon script from path: '%s'." msgstr "ë‹¤ìŒ ê²½ë¡œì—ì„œ ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 ì—†ìŒ: '%s'." #: editor/editor_node.cpp -#, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" -"ë‹¤ìŒ ê²½ë¡œì—ì„œ ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 ì—†ìŒ: '%s' ì½”ë“œì— ì˜¤ë¥˜ê°€ 있는 것 ê°™" -"습니다. ë¬¸ë²•ì„ í™•ì¸í•´ë³´ì„¸ìš”." +"ë‹¤ìŒ ê²½ë¡œì—ì„œ ì• ë“œì˜¨ 스í¬ë¦½íŠ¸ë¥¼ 불러올 수 ì—†ìŒ: '%s' 해당 스í¬ë¦½íŠ¸ì˜ ì½”ë“œì— " +"오류가 있는 것 같습니다.\n" +"추가 오류를 ë°©ì§€í•˜ë ¤ë©´ '%s'ì—ì„œ ì• ë“œì˜¨ì„ ë¹„í™œì„±í™”í•˜ì„¸ìš”." #: editor/editor_node.cpp msgid "" @@ -2991,6 +2991,10 @@ msgid "About" msgstr "ì •ë³´" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "프로ì 트를 실행합니다." @@ -5203,21 +5207,12 @@ msgstr "" "ì–´ 있는지 확ì¸í•´ì£¼ì„¸ìš”." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" -"Godot 편집기가 ë ˆì´ íŠ¸ë ˆì´ì‹± ì§€ì› ì—†ì´ ë¹Œë“œë˜ì–´ 있어, ë¼ì´íŠ¸ë§µì´ 구워질 수 ì—†" -"습니다." +"Godot 편집기는 ë ˆì´ íŠ¸ë ˆì´ì‹± ì§€ì› ì—†ì´ ë¹Œë“œë˜ì—ˆìœ¼ë©° ë¼ì´íŠ¸ë§µì€ 구울 수 없습니" +"다." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Bake Lightmaps" @@ -13057,6 +13052,19 @@ msgid "Constants cannot be modified." msgstr "ìƒìˆ˜ëŠ” ìˆ˜ì •í• ìˆ˜ 없습니다." #~ msgid "" +#~ "Godot editor was built without ray tracing support; lightmaps can't be " +#~ "baked.\n" +#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta " +#~ "emulation on Godot.app in the application settings\n" +#~ "then restart the editor." +#~ msgstr "" +#~ "Godot 편집기는 ë ˆì´ íŠ¸ë ˆì´ì‹± ì§€ì› ì—†ì´ ë¹Œë“œë˜ì—ˆìœ¼ë©° ë¼ì´íŠ¸ë§µì€ 구울 수 ì—†" +#~ "습니다.\n" +#~ "Apple Silicon ê¸°ë°˜ì˜ Macì„ ì‚¬ìš© ì¤‘ì¸ ê²½ìš°, ì• í”Œë¦¬ì¼€ì´ì…˜ ì„¤ì •ì—ì„œ Godot.app" +#~ "ì˜ Rosetta ì—ë®¬ë ˆì´ì…˜ ê°•ì œë¡œ\n" +#~ "ì‹œë„í•˜ê³ ë‚˜ì„œ 편집기를 다시 시작하세요." + +#~ msgid "" #~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0." #~ msgstr "" #~ "InterpolatedCamera는 ë” ì´ìƒ 사용ë˜ì§€ 않으며 Godot 4.0ì—ì„œ ì œê±°ë©ë‹ˆë‹¤." diff --git a/editor/translations/lt.po b/editor/translations/lt.po index 6fdb5257d3..6dad903aac 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -2514,7 +2514,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2927,6 +2927,10 @@ msgid "About" msgstr "Apie" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5160,16 +5164,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/lv.po b/editor/translations/lv.po index 832a099a1c..3333b65210 100644 --- a/editor/translations/lv.po +++ b/editor/translations/lv.po @@ -2487,7 +2487,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2893,6 +2893,10 @@ msgid "About" msgstr "Par" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5053,16 +5057,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/mi.po b/editor/translations/mi.po index f3726999ff..780599c2da 100644 --- a/editor/translations/mi.po +++ b/editor/translations/mi.po @@ -2433,7 +2433,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2839,6 +2839,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -4993,16 +4997,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/mk.po b/editor/translations/mk.po index 1c2910404c..01dbc3ed02 100644 --- a/editor/translations/mk.po +++ b/editor/translations/mk.po @@ -2440,7 +2440,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2846,6 +2846,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5000,16 +5004,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/ml.po b/editor/translations/ml.po index ca6259e4d2..b03638aded 100644 --- a/editor/translations/ml.po +++ b/editor/translations/ml.po @@ -2445,7 +2445,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2851,6 +2851,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5008,16 +5012,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/mr.po b/editor/translations/mr.po index 1f44ad0b6a..d7a76e3f10 100644 --- a/editor/translations/mr.po +++ b/editor/translations/mr.po @@ -2440,7 +2440,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2846,6 +2846,10 @@ msgid "About" msgstr "आमचà¥à¤¯à¤¾ बदà¥à¤¦à¤²" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5000,16 +5004,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/ms.po b/editor/translations/ms.po index d2cc1c47d9..3798405050 100644 --- a/editor/translations/ms.po +++ b/editor/translations/ms.po @@ -2552,7 +2552,7 @@ msgstr "Tidak dapat memuatkan skrip addon dari laluan: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Tidak dapat memuat skrip addon dari laluan: '%s' Nampaknya terdapat ralat " @@ -3030,6 +3030,10 @@ msgid "About" msgstr "Tentang" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp #, fuzzy msgid "Play the project." msgstr "Main projek." @@ -5345,16 +5349,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/nb.po b/editor/translations/nb.po index b0d147350a..39f45f5ae5 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -2641,7 +2641,7 @@ msgstr "Kan ikke laste addon-skript fra bane: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Kunne ikke laste tillegsskript fra sti: '%s' Script er ikke i verktøymodus." @@ -3103,6 +3103,10 @@ msgid "About" msgstr "Om" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Spill prosjektet." @@ -5445,16 +5449,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/nl.po b/editor/translations/nl.po index d28d0fbb55..32b3ff9117 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -2590,7 +2590,7 @@ msgstr "Volgend script kon niet geladen worden: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Script kon niet geladen worden van het pad: '%s'. Er lijkt een fout in de " @@ -3039,6 +3039,10 @@ msgid "About" msgstr "Over" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Speel het project." @@ -5274,16 +5278,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/or.po b/editor/translations/or.po index 7dfd981fba..8e40eb4b04 100644 --- a/editor/translations/or.po +++ b/editor/translations/or.po @@ -2439,7 +2439,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2845,6 +2845,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -4999,16 +5003,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/pl.po b/editor/translations/pl.po index 2ed4d52cc0..483d572041 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -2575,7 +2575,7 @@ msgstr "Nie można zaÅ‚adować skryptu dodatku z Å›cieżki: \"%s\"." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Nie można zaÅ‚adować skryptu dodatku ze Å›cieżki: \"%s\" W kodzie znajduje siÄ™ " @@ -3022,6 +3022,10 @@ msgid "About" msgstr "O silniku" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Uruchom projekt." @@ -5253,18 +5257,9 @@ msgstr "" "mieszczÄ… siÄ™ w kwadratowym obszarze [0.0, 1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Godot zostaÅ‚ zbudowany bez wsparcia ray tracingu, mapy Å›wiatÅ‚a nie mogÄ… być " "wypalone." diff --git a/editor/translations/pr.po b/editor/translations/pr.po index a59c7226f2..a0a9719128 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -2520,7 +2520,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2937,6 +2937,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5169,16 +5173,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/pt.po b/editor/translations/pt.po index 21fe589473..99f9934e1c 100644 --- a/editor/translations/pt.po +++ b/editor/translations/pt.po @@ -2553,7 +2553,7 @@ msgstr "Incapaz de carregar script addon do caminho: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Incapaz de carregar script addon do caminho: '%s' Parece haver um erro no " @@ -3002,6 +3002,10 @@ msgid "About" msgstr "Sobre" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Executa o projeto." @@ -5231,18 +5235,9 @@ msgstr "" "contidos na região quadrada [0.0,1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Editor Godot foi compilado sem suporte para ray tracing, lightmaps não podem " "ser consolidados." diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index 9f9138e20a..25cdec4f49 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -2653,7 +2653,7 @@ msgstr "" #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Não foi possÃvel localizar a área do script para o complemento do plugin em: " @@ -3102,6 +3102,10 @@ msgid "About" msgstr "Sobre" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Roda o projeto." @@ -5341,18 +5345,9 @@ msgstr "" "contidos na região quadrada [0.0,1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "O editor Godot foi construÃdo sem suporte à ray tracing, os lightmaps não " "podem ser bakeados." diff --git a/editor/translations/ro.po b/editor/translations/ro.po index fdf99eda10..d2ecad4c74 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -2560,7 +2560,7 @@ msgstr "Nu a putut fi încărcat scriptul add-on din calea: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Imposibil de încărcat scriptul addon din cale: '%s' Se pare că există o " @@ -3011,6 +3011,10 @@ msgid "About" msgstr "Despre" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Rulează proiectul." @@ -5240,16 +5244,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/ru.po b/editor/translations/ru.po index a0f20328ee..dfda002c17 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -2628,7 +2628,7 @@ msgstr "Ðе удалоÑÑŒ загрузить Ñкрипт из иÑточниР#, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Ðевозможно загрузить Ñкрипт аддона из иÑточника: «%s». Ð’ коде еÑÑ‚ÑŒ ошибка, " @@ -3075,6 +3075,10 @@ msgid "About" msgstr "О Godot Engine" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "ЗапуÑтить проект." @@ -5304,18 +5308,9 @@ msgstr "" "находÑÑ‚ÑÑ Ð² квадратной облаÑти [0.0,1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Редактор Godot был Ñобран без поддержки траÑÑировки лучей, карты оÑÐ²ÐµÑ‰ÐµÐ½Ð¸Ñ " "невозможно запечь." diff --git a/editor/translations/si.po b/editor/translations/si.po index f3d3a7039f..7bc9066904 100644 --- a/editor/translations/si.po +++ b/editor/translations/si.po @@ -2465,7 +2465,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2871,6 +2871,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5039,16 +5043,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/sk.po b/editor/translations/sk.po index af44e0eac1..3bb1bce542 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -2534,7 +2534,7 @@ msgstr "Nepodarilo sa naÄÃtaÅ¥ addon script z cesty: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Nepodarilo sa nájsÅ¥ addon script z cesty: '%s' Vyzerá to tak že by mohol byÅ¥ " @@ -2980,6 +2980,10 @@ msgid "About" msgstr "O nás" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "SpustiÅ¥ projekt." @@ -5200,16 +5204,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/sl.po b/editor/translations/sl.po index 8e005a05db..fd38959e1d 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -2647,7 +2647,7 @@ msgstr "Ni mogoÄe naložiti dodatno skripto iz poti: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Ni mogoÄe naložiti dodatno skripto iz poti: '%s' Skripta ni v naÄinu orodje." @@ -3114,6 +3114,10 @@ msgid "About" msgstr "O Programu" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Zaženi projekt." @@ -5438,16 +5442,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/sq.po b/editor/translations/sq.po index f95143dfce..abf3243545 100644 --- a/editor/translations/sq.po +++ b/editor/translations/sq.po @@ -2589,7 +2589,7 @@ msgstr "I paaftë të ngarkojë shkrimin e shtojcës nga rruga: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "I paaftë të ngarkojë shkrimin e shtojcës nga rruga: '%s' Me sa duket është " @@ -3052,6 +3052,10 @@ msgid "About" msgstr "Rreth" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Luaj projektin." @@ -5288,16 +5292,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index bc417703cc..6518f9b2bd 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -2764,7 +2764,7 @@ msgstr "ÐеуÑпех при учитавању Ñкриптице додатк #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "ÐеуÑпех при учитавању Ñкриптице додатка Ñа путем „%s“. Скриптица није у " @@ -3242,6 +3242,10 @@ msgid "About" msgstr "О" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Покрени пројекат." @@ -5703,16 +5707,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po index 5f0a7bb237..b646003e1a 100644 --- a/editor/translations/sr_Latn.po +++ b/editor/translations/sr_Latn.po @@ -2478,7 +2478,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2886,6 +2886,10 @@ msgid "About" msgstr "O nama / O Godou" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5063,16 +5067,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/sv.po b/editor/translations/sv.po index cf330e6223..7253693a74 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -2600,7 +2600,7 @@ msgstr "Kunde inte ladda addon script frÃ¥n sökväg: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Kunde inte ladda addon script frÃ¥n sökväg: '%s' Skript är inte i " @@ -3036,6 +3036,10 @@ msgid "About" msgstr "Om" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Spela projektet." @@ -5298,16 +5302,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/ta.po b/editor/translations/ta.po index 375dbacff3..9107c43f7c 100644 --- a/editor/translations/ta.po +++ b/editor/translations/ta.po @@ -2469,7 +2469,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2877,6 +2877,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5048,16 +5052,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/te.po b/editor/translations/te.po index 41850d2d56..c983fbe90e 100644 --- a/editor/translations/te.po +++ b/editor/translations/te.po @@ -2442,7 +2442,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2848,6 +2848,10 @@ msgid "About" msgstr "à°—à±à°°à°¿à°‚à°šà°¿" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5002,16 +5006,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/th.po b/editor/translations/th.po index 38ef19e80c..24b007b891 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -2517,7 +2517,7 @@ msgstr "ไม่สามารถโหลดสคริปต์จาà¸: ' #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "ไม่สามารถโหลดสคริปต์ส่วนเสริมจาà¸: '%s' เหมืà¸à¸™à¸§à¹ˆà¸²à¸ˆà¸°à¹€à¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดขึ้นในโค้ด " @@ -2951,6 +2951,10 @@ msgid "About" msgstr "เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "เล่นโปรเจà¸à¸•à¹Œ" @@ -5141,18 +5145,9 @@ msgid "" msgstr "mesh บางส่วนไม่ถูà¸à¸•à¹‰à¸à¸‡ ตรวจสà¸à¸šà¹ƒà¸«à¹‰à¹à¸™à¹ˆà¹ƒà¸ˆà¸§à¹ˆà¸²à¸„่า UV2 à¸à¸¢à¸¹à¹ˆà¹ƒà¸™à¸žà¸·à¹‰à¸™à¸—ี่สี่เหลี่ยม [0.0,1.0]" #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "ตัวà¹à¸à¹‰à¹„ข Godot ถูà¸à¸ªà¸£à¹‰à¸²à¸‡à¹‚ดยไม่ได้สนับสนุน Ray Tracing ดังนั้นจึงไม่สามารถปั้น Lightmap ได้" diff --git a/editor/translations/tr.po b/editor/translations/tr.po index e49efb20b5..43c8aa9e52 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -2591,7 +2591,7 @@ msgstr "Yoldaki eklenti betiÄŸi yüklenemedi: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "'%s' adresindeki eklenti betik yüklenemiyor. Kodun içinde bir hata var gibi " @@ -3038,6 +3038,10 @@ msgid "About" msgstr "Hakkında" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Projeti oynat." @@ -5269,18 +5273,9 @@ msgstr "" "içerdiÄŸinden emin olun." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Godot editör ışın yansıma desteÄŸi olmadan derlenmiÅŸ, ışık haritaları " "piÅŸirilemez." diff --git a/editor/translations/tzm.po b/editor/translations/tzm.po index 7980101d8a..a28dce76f9 100644 --- a/editor/translations/tzm.po +++ b/editor/translations/tzm.po @@ -2440,7 +2440,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2846,6 +2846,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5000,16 +5004,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/uk.po b/editor/translations/uk.po index 576ebc4433..251c85a8ba 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -20,7 +20,7 @@ msgid "" msgstr "" "Project-Id-Version: Ukrainian (Godot Engine)\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-04-22 14:40+0000\n" +"PO-Revision-Date: 2021-05-14 20:34+0000\n" "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/" "godot/uk/>\n" @@ -2556,14 +2556,14 @@ msgid "Unable to load addon script from path: '%s'." msgstr "Ðеможливо завантажити Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ñкрипт зі шлÑху: '%s'." #: editor/editor_node.cpp -#, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" -"Ðеможливо завантажити Ñкрипт Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð· шлÑху «%s». ЗдаєтьÑÑ, у коді Ñ” " -"помилка, будь лаÑка, перевірте ÑинтакÑиÑ." +"Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ додатковий Ñкрипт з такою адреÑою: «%s». Причиною " +"може бути помилка у коді цього Ñкрипту.\n" +"Вимикаємо додаток у «%s», щоб запобігти подальшим помилкам." #: editor/editor_node.cpp msgid "" @@ -3010,6 +3010,10 @@ msgid "About" msgstr "Про" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "ЗапуÑтити проєкт." @@ -5247,18 +5251,9 @@ msgstr "" "потраплÑÑŽÑ‚ÑŒ до квадратної облаÑÑ‚Ñ– [0.0,1.0]." #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Редактор Godot було зібрано без підтримки траÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ñ–Ð². Карти " "оÑÐ²Ñ–Ñ‚Ð»ÐµÐ½Ð½Ñ Ð½Ðµ вдаÑÑ‚ÑŒÑÑ Ð¿Ð¾Ð±ÑƒÐ´ÑƒÐ²Ð°Ñ‚Ð¸." @@ -13235,6 +13230,19 @@ msgid "Constants cannot be modified." msgstr "Сталі не можна змінювати." #~ msgid "" +#~ "Godot editor was built without ray tracing support; lightmaps can't be " +#~ "baked.\n" +#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta " +#~ "emulation on Godot.app in the application settings\n" +#~ "then restart the editor." +#~ msgstr "" +#~ "Редактор Godot було зібрано без підтримки траÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ñ–Ð²; мапи " +#~ "оÑÐ²Ñ–Ñ‚Ð»ÐµÐ½Ð½Ñ Ñтворити не вдаÑÑ‚ÑŒÑÑ.\n" +#~ "Якщо ви кориÑтуєтеÑÑ Mac на оÑнові Apple Silicon, Ñпробуйте примуÑово " +#~ "вÑтановити емулÑцію Rosetta Ð´Ð»Ñ Godot.app у параметрах програми,\n" +#~ "а потім перезапуÑÑ‚Ñ–Ñ‚ÑŒ редактор." + +#~ msgid "" #~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0." #~ msgstr "" #~ "InterpolatedCamera вважаєтьÑÑ Ð·Ð°Ñтарілою, Ñ—Ñ— буде вилучено у Godot 4.0." diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index d71c823f96..32a88830cb 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -2490,7 +2490,7 @@ msgstr "" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -2900,6 +2900,10 @@ msgid "About" msgstr "" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "" @@ -5106,16 +5110,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/vi.po b/editor/translations/vi.po index b1a6984df9..3939ac7a4d 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -2535,7 +2535,7 @@ msgstr "Không thể tải tệp addon từ Ä‘Æ°á»ng dẫn: '%s'." #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" "Không thể nạp tệp lệnh bổ trợ từ Ä‘Æ°á»ng dẫn: '%s' Có vẻ có lá»—i trong mã, hãy " @@ -2971,6 +2971,10 @@ msgid "About" msgstr "Vá» chúng tôi" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "Chạy dá»± án." @@ -5172,16 +5176,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index 57d34e4b6f..3b528525e1 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -82,8 +82,8 @@ msgid "" msgstr "" "Project-Id-Version: Chinese (Simplified) (Godot Engine)\n" "POT-Creation-Date: 2018-01-20 12:15+0200\n" -"PO-Revision-Date: 2021-04-26 22:32+0000\n" -"Last-Translator: qjyqjyqjyqjy <qjyqjyqjyqjy@sina.com.cn>\n" +"PO-Revision-Date: 2021-05-16 03:32+0000\n" +"Last-Translator: Haoyu Qiu <timothyqiu32@gmail.com>\n" "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hans/>\n" "Language: zh_CN\n" @@ -2564,12 +2564,13 @@ msgid "Unable to load addon script from path: '%s'." msgstr "æ— æ³•ä»Žè·¯å¾„ “%s†ä¸åŠ è½½åŠ è½½é¡¹è„šæœ¬ã€‚" #: editor/editor_node.cpp -#, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." -msgstr "æ— æ³•ä»Žè·¯å¾„ “%sâ€ åŠ è½½åŠ è½½é¡¹è„šæœ¬ï¼šè„šæœ¬ä¼¼ä¹Žæœ‰ä»£ç 错误,请检查其è¯æ³•ã€‚" +msgstr "" +"æ— æ³•ä»Žè·¯å¾„â€œ%sâ€åŠ è½½åŠ è½½é¡¹è„šæœ¬ï¼šè¯¥è„šæœ¬å¯èƒ½æœ‰ä»£ç 错误。\n" +"ç¦ç”¨åŠ 载项“%sâ€å¯é˜»æ¢å…¶è¿›ä¸€æ¥æŠ¥é”™ã€‚" #: editor/editor_node.cpp msgid "" @@ -2995,6 +2996,10 @@ msgid "About" msgstr "关于" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "è¿è¡Œæ¤é¡¹ç›®ã€‚" @@ -5184,19 +5189,10 @@ msgid "" msgstr "æŸäº›ç½‘æ ¼æ— æ•ˆã€‚ç¡®ä¿UV2通é“值包å«åœ¨[0.0,1.0]平方区域内。" #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." -msgstr "Godot编辑器是在没有光线跟踪支æŒçš„æƒ…å†µä¸‹æž„å»ºçš„ï¼Œå…‰ç…§è´´å›¾æ— æ³•çƒ˜ç„™ã€‚" +"Godot editor was built without ray tracing support, lightmaps can't be baked." +msgstr "Godot 编辑器是在没有光线跟踪支æŒçš„æƒ…å†µä¸‹æž„å»ºçš„ï¼›æ— æ³•çƒ˜ç„™å…‰ç…§è´´å›¾ã€‚" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Bake Lightmaps" @@ -12935,6 +12931,18 @@ msgid "Constants cannot be modified." msgstr "ä¸å…许修改常é‡ã€‚" #~ msgid "" +#~ "Godot editor was built without ray tracing support; lightmaps can't be " +#~ "baked.\n" +#~ "If you are using an Apple Silicon-based Mac, try forcing Rosetta " +#~ "emulation on Godot.app in the application settings\n" +#~ "then restart the editor." +#~ msgstr "" +#~ "Godot 编辑器是在没有光线跟踪支æŒçš„æƒ…å†µä¸‹æž„å»ºçš„ï¼›æ— æ³•çƒ˜ç„™å…‰ç…§è´´å›¾ã€‚\n" +#~ "å¦‚æžœä½ ä½¿ç”¨çš„æ˜¯åŸºäºŽ Apple Silicon çš„ Mac,å¯ä»¥å°è¯•åœ¨åº”用设置ä¸è®© Godot.app " +#~ "强制使用 Rosetta 模拟\n" +#~ "并é‡å¯ç¼–辑器。" + +#~ msgid "" #~ "InterpolatedCamera has been deprecated and will be removed in Godot 4.0." #~ msgstr "InterpolatedCamera 已废弃,将在 Godot 4.0 ä¸åˆ 除。" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index 7f181fe4be..2350817f1f 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -2610,7 +2610,7 @@ msgstr "載入å—形出ç¾éŒ¯èª¤" #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "" @@ -3059,6 +3059,10 @@ msgid "About" msgstr "關於" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "é‹è¡Œå°ˆæ¡ˆ" @@ -5395,16 +5399,7 @@ msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" #: editor/plugins/baked_lightmap_editor_plugin.cpp diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index f5f0feb333..a24b8831d2 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -2516,7 +2516,7 @@ msgstr "無法自路徑「%sã€è¼‰å…¥æ“´å……腳本。" #, fuzzy msgid "" "Unable to load addon script from path: '%s'. This might be due to a code " -"error in that script. \n" +"error in that script.\n" "Disabling the addon at '%s' to prevent further errors." msgstr "無法自路徑「%sã€è¼‰å…¥æ“´å……腳本。å¯èƒ½ç‚ºç¨‹å¼ç¢¼ä¸æœ‰éŒ¯èª¤ï¼Œè«‹æª¢æŸ¥èªžæ³•ã€‚" @@ -2944,6 +2944,10 @@ msgid "About" msgstr "關於" #: editor/editor_node.cpp +msgid "Support Godot Development" +msgstr "" + +#: editor/editor_node.cpp msgid "Play the project." msgstr "執行該專案。" @@ -5133,18 +5137,9 @@ msgid "" msgstr "éƒ¨åˆ†ç¶²æ ¼ç„¡æ•ˆã€‚è«‹ç¢ºä¿ UV2 通é“的值ä½æ–¼ [0.0,1.0] 矩形內。" #: editor/plugins/baked_lightmap_editor_plugin.cpp -msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be " -"baked.\n" -"If you are using an Apple Silicon-based Mac, try forcing Rosetta emulation " -"on Godot.app in the application settings\n" -"then restart the editor." -msgstr "" - -#: editor/plugins/baked_lightmap_editor_plugin.cpp #, fuzzy msgid "" -"Godot editor was built without ray tracing support; lightmaps can't be baked." +"Godot editor was built without ray tracing support, lightmaps can't be baked." msgstr "" "Godot 編輯器在建制時未啟用光線追蹤 (Ray Tracing) 支æ´ï¼Œç„¡æ³•çƒ˜ç„™å…‰ç…§åœ–。" diff --git a/misc/dist/html/service-worker.js b/misc/dist/html/service-worker.js index f8dee8cd5b..063e40a6cb 100644 --- a/misc/dist/html/service-worker.js +++ b/misc/dist/html/service-worker.js @@ -1,6 +1,6 @@ // This service worker is required to expose an exported Godot project as a // Progressive Web App. It provides an offline fallback page telling the user -// that they need an Internet conneciton to run the project if desired. +// that they need an Internet connection to run the project if desired. // Incrementing CACHE_VERSION will kick off the install event and force // previously cached resources to be updated from the network. const CACHE_VERSION = "@GODOT_VERSION@"; diff --git a/misc/dist/osx/editor.entitlements b/misc/dist/osx/editor.entitlements new file mode 100644 index 0000000000..5496f65dcc --- /dev/null +++ b/misc/dist/osx/editor.entitlements @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>com.apple.security.device.audio-input</key> + <true/> + <key>com.apple.security.device.camera</key> + <true/> + <key>com.apple.security.cs.disable-library-validation</key> + <true/> +</dict> +</plist> diff --git a/misc/dist/osx/editor_mono.entitlements b/misc/dist/osx/editor_mono.entitlements new file mode 100644 index 0000000000..c61c287652 --- /dev/null +++ b/misc/dist/osx/editor_mono.entitlements @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>com.apple.security.cs.allow-dyld-environment-variables</key> + <true/> + <key>com.apple.security.cs.allow-jit</key> + <true/> + <key>com.apple.security.cs.allow-unsigned-executable-memory</key> + <true/> + <key>com.apple.security.cs.disable-library-validation</key> + <true/> + <key>com.apple.security.device.audio-input</key> + <true/> + <key>com.apple.security.device.camera</key> + <true/> +</dict> +</plist> diff --git a/misc/scripts/check_ci_log.py b/misc/scripts/check_ci_log.py index f2cdf95c7b..56c32b154c 100755 --- a/misc/scripts/check_ci_log.py +++ b/misc/scripts/check_ci_log.py @@ -53,11 +53,11 @@ if file_contents.find("ObjectDB instances leaked at exit") != -1: # execution of project if file_contents.find("Assertion failed") != -1: - print("ERROR: Assertion failed in project, check exectution log for more info") + print("ERROR: Assertion failed in project, check execution log for more info") sys.exit(1) # For now Godot leaks a lot of rendering stuff so for now we just show info -# about it and this needs to be reenabled after fixing this memory leaks. +# about it and this needs to be re-enabled after fixing this memory leaks. if file_contents.find("were leaked") != -1 or file_contents.find("were never freed") != -1: print("WARNING: Memory leak was found") diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index f22ff29349..271cb03c9f 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -144,7 +144,7 @@ </argument> <description> Sets the timeout parameters for a peer. The timeout parameters control how and when a peer will timeout from a failure to acknowledge reliable traffic. Timeout values are expressed in milliseconds. - The [code]timeout_limit[/code] is a factor that, multiplied by a value based on the avarage round trip time, will determine the timeout limit for a reliable packet. When that limit is reached, the timeout will be doubled, and the peer will be disconnected if that limit has reached [code]timeout_min[/code]. The [code]timeout_max[/code] parameter, on the other hand, defines a fixed timeout for which any packet must be acknowledged or the peer will be dropped. + The [code]timeout_limit[/code] is a factor that, multiplied by a value based on the average round trip time, will determine the timeout limit for a reliable packet. When that limit is reached, the timeout will be doubled, and the peer will be disconnected if that limit has reached [code]timeout_min[/code]. The [code]timeout_max[/code] parameter, on the other hand, defines a fixed timeout for which any packet must be acknowledged or the peer will be dropped. </description> </method> </methods> diff --git a/modules/fbx/README.md b/modules/fbx/README.md index 2a2f186463..69a50d4bea 100644 --- a/modules/fbx/README.md +++ b/modules/fbx/README.md @@ -15,7 +15,7 @@ functionality. If anything we should give this parser back to assimp at some poi # Updating assimp fbx parser -Don't. it's not possible the code is rewritten in many areas to remove thirdparty deps and various bugs are fixed. +Don't. It's not possible the code is rewritten in many areas to remove thirdparty deps and various bugs are fixed. Many days were put into rewriting the parser to use safe code and safe memory accessors. diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp index 304d1598f6..349bcaeeaa 100644 --- a/modules/fbx/data/fbx_mesh_data.cpp +++ b/modules/fbx/data/fbx_mesh_data.cpp @@ -945,7 +945,7 @@ void FBXMeshData::triangulate_polygon(SurfaceData *surface, const Vector<int> &p for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) { TPPLPoly &tp = I->get(); - ERR_FAIL_COND_MSG(tp.GetNumPoints() != 3, "The triangulator retuned more points, how this is possible?"); + ERR_FAIL_COND_MSG(tp.GetNumPoints() != 3, "The triangulator returned more points, how this is possible?"); // Find Index for (int i = 2; i >= 0; i -= 1) { const Vector2 vertex = tp.GetPoint(i); diff --git a/modules/fbx/data/fbx_mesh_data.h b/modules/fbx/data/fbx_mesh_data.h index 575f833584..c4eaa7d170 100644 --- a/modules/fbx/data/fbx_mesh_data.h +++ b/modules/fbx/data/fbx_mesh_data.h @@ -156,7 +156,7 @@ private: /// [0, 2, 1, 3, 4] /// The negative values are computed using this formula: `(-value) - 1` /// - /// Returns the vertex index from the poligon vertex. + /// Returns the vertex index from the polygon vertex. /// Returns -1 if `p_index` is invalid. int get_vertex_from_polygon_vertex(const std::vector<int> &p_face_indices, int p_index) const; diff --git a/modules/fbx/editor_scene_importer_fbx.cpp b/modules/fbx/editor_scene_importer_fbx.cpp index ccbea21541..58bc450e9d 100644 --- a/modules/fbx/editor_scene_importer_fbx.cpp +++ b/modules/fbx/editor_scene_importer_fbx.cpp @@ -1056,7 +1056,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene( //print_verbose("[doc] node animation path: " + node_path); } } else { - // note: this could actually be unsafe this means we should be careful about continuing here, if we see bizzare effects later we should disable this. + // note: this could actually be unsafe this means we should be careful about continuing here, if we see bizarre effects later we should disable this. // I am not sure if this is unsafe or not, testing will tell us this. print_error("[doc] invalid fbx target detected for this track"); continue; diff --git a/modules/fbx/fbx_parser/FBXDocument.cpp b/modules/fbx/fbx_parser/FBXDocument.cpp index bb85d6ff7c..89c69d2ee8 100644 --- a/modules/fbx/fbx_parser/FBXDocument.cpp +++ b/modules/fbx/fbx_parser/FBXDocument.cpp @@ -487,7 +487,7 @@ const std::vector<const AnimationStack *> &Document::AnimationStacks() const { const AnimationStack *stack = lazy->Get<AnimationStack>(); ERR_CONTINUE_MSG(!stack, "invalid ptr to AnimationStack - conversion failure"); - // We push back the weak reference :) to keep things simple, as ownership is on the parser side so it wont be cleaned up. + // We push back the weak reference :) to keep things simple, as ownership is on the parser side so it won't be cleaned up. animationStacksResolved.push_back(stack); } diff --git a/modules/fbx/fbx_parser/FBXDocument.h b/modules/fbx/fbx_parser/FBXDocument.h index 9664cd763a..e01e0471aa 100644 --- a/modules/fbx/fbx_parser/FBXDocument.h +++ b/modules/fbx/fbx_parser/FBXDocument.h @@ -699,7 +699,7 @@ private: typedef std::vector<int64_t> KeyTimeList; typedef std::vector<float> KeyValueList; -/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */ +/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */ class AnimationCurve : public Object { public: AnimationCurve(uint64_t id, const ElementPtr element, const std::string &name, const Document &doc); diff --git a/modules/fbx/fbx_parser/FBXMeshGeometry.cpp b/modules/fbx/fbx_parser/FBXMeshGeometry.cpp index a28e7565c6..2cc25a0690 100644 --- a/modules/fbx/fbx_parser/FBXMeshGeometry.cpp +++ b/modules/fbx/fbx_parser/FBXMeshGeometry.cpp @@ -125,7 +125,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const ElementPtr element, const std::str ScopePtr sc = element->Compound(); ERR_FAIL_COND_MSG(sc == nullptr, "failed to read geometry, prevented crash"); - ERR_FAIL_COND_MSG(!HasElement(sc, "Vertices"), "Detected mesh with no vertexes, didn't populate the mesh"); + ERR_FAIL_COND_MSG(!HasElement(sc, "Vertices"), "Detected mesh with no vertices, didn't populate the mesh"); // must have Mesh elements: const ElementPtr Vertices = GetRequiredElement(sc, "Vertices", element); @@ -140,7 +140,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const ElementPtr element, const std::str ParseVectorDataArray(m_vertices, Vertices); ParseVectorDataArray(m_face_indices, PolygonVertexIndex); - ERR_FAIL_COND_MSG(m_vertices.empty(), "mesh with no vertexes in FBX file, did you mean to delete it?"); + ERR_FAIL_COND_MSG(m_vertices.empty(), "mesh with no vertices in FBX file, did you mean to delete it?"); ERR_FAIL_COND_MSG(m_face_indices.empty(), "mesh has no faces, was this intended?"); // Retrieve layer elements, for all of the mesh @@ -278,7 +278,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const ElementPtr element, const std::str } } // As the algorithm above, this check is useless. Because the first - // ever vertex is always considered the begining of a polygon. + // ever vertex is always considered the beginning of a polygon. ERR_FAIL_COND_MSG(found_it == false, "Was not possible to find the first vertex of this polygon. FBX file is corrupted."); } else { @@ -418,7 +418,7 @@ MeshGeometry::MappingData<T> MeshGeometry::resolve_vertex_data_array( // parse data into array ParseVectorDataArray(tempData.data, GetRequiredElement(source, dataElementName)); - // index array wont always exist + // index array won't always exist const ElementPtr element = GetOptionalElement(source, indexDataElementName); if (element) { ParseVectorDataArray(tempData.index, element); diff --git a/modules/fbx/fbx_parser/FBXMeshGeometry.h b/modules/fbx/fbx_parser/FBXMeshGeometry.h index 05493c4aec..c9b25f008d 100644 --- a/modules/fbx/fbx_parser/FBXMeshGeometry.h +++ b/modules/fbx/fbx_parser/FBXMeshGeometry.h @@ -122,7 +122,7 @@ typedef std::vector<int> MatIndexArray; /// ## Map Type: /// * None The mapping is undetermined. /// * ByVertex There will be one mapping coordinate for each surface control point/vertex (ControlPoint is a vertex). -/// * If you have direct reference type verticies[x] +/// * If you have direct reference type vertices[x] /// * If you have IndexToDirect reference type the UV /// * ByPolygonVertex There will be one mapping coordinate for each vertex, for every polygon of which it is a part. This means that a vertex will have as many mapping coordinates as polygons of which it is a part. (Sorted by polygon, referencing vertex) /// * ByPolygon There can be only one mapping coordinate for the whole polygon. @@ -186,7 +186,7 @@ public: /// Returns -1 if the vertices doesn't form an edge. Vertex order, doesn't // matter. static int get_edge_id(const std::vector<Edge> &p_map, int p_vertex_a, int p_vertex_b); - // Retuns the edge point bu that ID, or the edge with -1 vertices if the + // Returns the edge point bu that ID, or the edge with -1 vertices if the // id is not valid. static Edge get_edge(const std::vector<Edge> &p_map, int p_id); diff --git a/modules/fbx/tools/import_utils.cpp b/modules/fbx/tools/import_utils.cpp index c87dd1fd3a..368aa09a75 100644 --- a/modules/fbx/tools/import_utils.cpp +++ b/modules/fbx/tools/import_utils.cpp @@ -128,7 +128,7 @@ Transform get_unscaled_transform(const Transform &p_initial, real_t p_scale) { } Vector3 get_poly_normal(const std::vector<Vector3> &p_vertices) { - ERR_FAIL_COND_V_MSG(p_vertices.size() < 3, Vector3(0, 0, 0), "At least 3 vertices are necesary"); + ERR_FAIL_COND_V_MSG(p_vertices.size() < 3, Vector3(0, 0, 0), "At least 3 vertices are necessary"); // Using long double to make sure that normal is computed for even really tiny objects. typedef long double ldouble; ldouble x = 0.0; diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp index 31e6a81975..a0d7fbf726 100644 --- a/modules/gdnative/pluginscript/pluginscript_script.cpp +++ b/modules/gdnative/pluginscript/pluginscript_script.cpp @@ -441,10 +441,10 @@ Error PluginScript::load_source_code(const String &p_path) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); ERR_FAIL_COND_V_MSG(err, err, "Cannot open file '" + p_path + "'."); - int len = f->get_len(); + uint64_t len = f->get_len(); sourcef.resize(len + 1); uint8_t *w = sourcef.ptrw(); - int r = f->get_buffer(w, len); + uint64_t r = f->get_buffer(w, len); f->close(); memdelete(f); ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN); diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp index f2fb0a2fdc..1b7838846f 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -47,11 +47,7 @@ godot_int GDAPI godot_videodecoder_file_read(void *ptr, uint8_t *buf, int buf_si // if file exists if (file) { - long bytes_read = file->get_buffer(buf, buf_size); - // No bytes to read => EOF - if (bytes_read == 0) { - return 0; - } + int64_t bytes_read = file->get_buffer(buf, buf_size); return bytes_read; } return -1; @@ -62,41 +58,35 @@ int64_t GDAPI godot_videodecoder_file_seek(void *ptr, int64_t pos, int whence) { FileAccess *file = reinterpret_cast<FileAccess *>(ptr); if (file) { - size_t len = file->get_len(); + int64_t len = file->get_len(); switch (whence) { case SEEK_SET: { - // Just for explicitness - size_t new_pos = static_cast<size_t>(pos); - if (new_pos > len) { + if (pos > len) { return -1; } - file->seek(new_pos); - pos = static_cast<int64_t>(file->get_position()); - return pos; + file->seek(pos); + return file->get_position(); } break; case SEEK_CUR: { // Just in case it doesn't exist - if (pos < 0 && (size_t)-pos > file->get_position()) { + if (pos < 0 && -pos > (int64_t)file->get_position()) { return -1; } - pos = pos + static_cast<int>(file->get_position()); - file->seek(pos); - pos = static_cast<int64_t>(file->get_position()); - return pos; + file->seek(file->get_position() + pos); + return file->get_position(); } break; case SEEK_END: { // Just in case something goes wrong - if ((size_t)-pos > len) { + if (-pos > len) { return -1; } file->seek_end(pos); - pos = static_cast<int64_t>(file->get_position()); - return pos; + return file->get_position(); } break; default: { // Only 4 possible options, hence default = AVSEEK_SIZE // Asks to return the length of file - return static_cast<int64_t>(len); + return len; } break; } } diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp index 2513c62b6a..41306f0687 100644 --- a/modules/gdnavigation/nav_map.cpp +++ b/modules/gdnavigation/nav_map.cpp @@ -112,7 +112,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p } } - // Check for trival cases + // Check for trivial cases if (!begin_poly || !end_poly) { return Vector<Vector3>(); } diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 859c1acde9..2896420239 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -481,7 +481,7 @@ void GDScript::_update_doc() { methods[i].return_val.class_name = _get_gdscript_reference_class_name(Object::cast_to<GDScript>(return_type.script_type)); } - // Change class name if argumetn is script reference. + // Change class name if argument is script reference. for (int j = 0; j < fn->get_argument_count(); j++) { GDScriptDataType arg_type = fn->get_argument_type(j); if (arg_type.kind == GDScriptDataType::GDSCRIPT) { @@ -1045,10 +1045,10 @@ Error GDScript::load_source_code(const String &p_path) { ERR_FAIL_COND_V(err, err); } - int len = f->get_len(); + uint64_t len = f->get_len(); sourcef.resize(len + 1); uint8_t *w = sourcef.ptrw(); - int r = f->get_buffer(w, len); + uint64_t r = f->get_buffer(w, len); f->close(); memdelete(f); ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN); diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 17ae52f3ab..7b04959227 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -2078,9 +2078,23 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa mark_node_unsafe(p_call); return; } - reduce_expression(subscript->base); + if (subscript->attribute == nullptr) { + // Invalid call. Error already sent in parser. + p_call->set_datatype(call_type); + mark_node_unsafe(p_call); + return; + } - base_type = subscript->base->get_datatype(); + GDScriptParser::IdentifierNode *base_id = nullptr; + if (subscript->base->type == GDScriptParser::Node::IDENTIFIER) { + base_id = static_cast<GDScriptParser::IdentifierNode *>(subscript->base); + } + if (base_id && GDScriptParser::get_builtin_type(base_id->name) < Variant::VARIANT_MAX) { + base_type = make_builtin_meta_type(GDScriptParser::get_builtin_type(base_id->name)); + } else { + reduce_expression(subscript->base); + base_type = subscript->base->get_datatype(); + } } else { // Invalid call. Error already sent in parser. // TODO: Could check if Callable here too. diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 0da99ccee3..ea34a2ca2d 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -129,12 +129,6 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type int idx = temporaries.size(); pool.push_back(idx); temporaries.push_back(new_temp); - - // First time using this, so adjust to the proper type. - if (temp_type != Variant::NIL) { - Address addr(Address::TEMPORARY, idx, p_type); - write_type_adjust(addr, temp_type); - } } int slot = pool.front()->get(); pool.pop_front(); @@ -189,8 +183,12 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() { append(GDScriptFunction::OPCODE_END, 0); for (int i = 0; i < temporaries.size(); i++) { + int stack_index = i + max_locals + RESERVED_STACK; for (int j = 0; j < temporaries[i].bytecode_indices.size(); j++) { - opcodes.write[temporaries[i].bytecode_indices[j]] = (i + max_locals + RESERVED_STACK) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); + opcodes.write[temporaries[i].bytecode_indices[j]] = stack_index | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); + } + if (temporaries[i].type != Variant::NIL) { + function->temporary_slots[stack_index] = temporaries[i].type; } } @@ -1017,6 +1015,56 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, append(Variant::get_validated_builtin_method(p_type, p_method)); } +void GDScriptByteCodeGenerator::write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) { + bool is_validated = false; + + // Check if all types are correct. + if (Variant::is_builtin_method_vararg(p_type, p_method)) { + is_validated = true; // Vararg works fine with any argument, since they can be any type. + } else if (p_arguments.size() == Variant::get_builtin_method_argument_count(p_type, p_method)) { + bool all_types_exact = true; + for (int i = 0; i < p_arguments.size(); i++) { + if (!IS_BUILTIN_TYPE(p_arguments[i], Variant::get_builtin_method_argument_type(p_type, p_method, i))) { + all_types_exact = false; + break; + } + } + + is_validated = all_types_exact; + } + + if (!is_validated) { + // Perform regular call. + append(GDScriptFunction::OPCODE_CALL_BUILTIN_STATIC, p_arguments.size() + 1); + for (int i = 0; i < p_arguments.size(); i++) { + append(p_arguments[i]); + } + append(p_target); + append(p_type); + append(p_method); + append(p_arguments.size()); + return; + } + + if (p_target.mode == Address::TEMPORARY) { + Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method); + Variant::Type temp_type = temporaries[p_target.address].type; + if (result_type != temp_type) { + write_type_adjust(p_target, result_type); + } + } + + append(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size()); + + for (int i = 0; i < p_arguments.size(); i++) { + append(p_arguments[i]); + } + append(Address()); // No base since it's static. + append(p_target); + append(p_arguments.size()); + append(Variant::get_validated_builtin_method(p_type, p_method)); +} + void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) { append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL_METHOD_BIND : GDScriptFunction::OPCODE_CALL_METHOD_BIND_RET, 2 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index c060476f39..f8c05fea83 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -461,6 +461,7 @@ public: virtual void write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) override; virtual void write_call_gdscript_utility(const Address &p_target, GDScriptUtilityFunctions::FunctionPtr p_function, const Vector<Address> &p_arguments) override; virtual void write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) override; + virtual void write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) override; virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override; virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override; virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override; diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index 113d36be98..6aa76703f1 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -153,9 +153,9 @@ String GDScriptCache::get_source_code(const String &p_path) { ERR_FAIL_COND_V(err, ""); } - int len = f->get_len(); + uint64_t len = f->get_len(); source_file.resize(len + 1); - int r = f->get_buffer(source_file.ptrw(), len); + uint64_t r = f->get_buffer(source_file.ptrw(), len); f->close(); ERR_FAIL_COND_V(r != len, ""); source_file.write[len] = 0; diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h index ae9a8ede5e..399c9d6de7 100644 --- a/modules/gdscript/gdscript_codegen.h +++ b/modules/gdscript/gdscript_codegen.h @@ -122,6 +122,7 @@ public: virtual void write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) = 0; virtual void write_call_gdscript_utility(const Address &p_target, GDScriptUtilityFunctions::FunctionPtr p_function, const Vector<Address> &p_arguments) = 0; virtual void write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) = 0; + virtual void write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) = 0; virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0; virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0; virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 37ce8ae2cb..4ac9864d4f 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -537,39 +537,44 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(call->callee); if (subscript->is_attribute) { - GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base); - if (r_error) { - return GDScriptCodeGenerator::Address(); - } - if (within_await) { - gen->write_call_async(result, base, call->function_name, arguments); - } else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) { - // Native method, use faster path. - StringName class_name; - if (base.type.kind == GDScriptDataType::NATIVE) { - class_name = base.type.native_type; - } else { - class_name = base.type.native_type == StringName() ? base.type.script_type->get_instance_base_type() : base.type.native_type; + // May be static built-in method call. + if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) < Variant::VARIANT_MAX) { + gen->write_call_builtin_type_static(result, GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name), subscript->attribute->name, arguments); + } else { + GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base); + if (r_error) { + return GDScriptCodeGenerator::Address(); } - if (ClassDB::class_exists(class_name) && ClassDB::has_method(class_name, call->function_name)) { - MethodBind *method = ClassDB::get_method(class_name, call->function_name); - if (_have_exact_arguments(method, arguments)) { - // Exact arguments, use ptrcall. - gen->write_call_ptrcall(result, base, method, arguments); + if (within_await) { + gen->write_call_async(result, base, call->function_name, arguments); + } else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) { + // Native method, use faster path. + StringName class_name; + if (base.type.kind == GDScriptDataType::NATIVE) { + class_name = base.type.native_type; + } else { + class_name = base.type.native_type == StringName() ? base.type.script_type->get_instance_base_type() : base.type.native_type; + } + if (ClassDB::class_exists(class_name) && ClassDB::has_method(class_name, call->function_name)) { + MethodBind *method = ClassDB::get_method(class_name, call->function_name); + if (_have_exact_arguments(method, arguments)) { + // Exact arguments, use ptrcall. + gen->write_call_ptrcall(result, base, method, arguments); + } else { + // Not exact arguments, but still can use method bind call. + gen->write_call_method_bind(result, base, method, arguments); + } } else { - // Not exact arguments, but still can use method bind call. - gen->write_call_method_bind(result, base, method, arguments); + gen->write_call(result, base, call->function_name, arguments); } + } else if (base.type.has_type && base.type.kind == GDScriptDataType::BUILTIN) { + gen->write_call_builtin_type(result, base, base.type.builtin_type, call->function_name, arguments); } else { gen->write_call(result, base, call->function_name, arguments); } - } else if (base.type.has_type && base.type.kind == GDScriptDataType::BUILTIN) { - gen->write_call_builtin_type(result, base, base.type.builtin_type, call->function_name, arguments); - } else { - gen->write_call(result, base, call->function_name, arguments); - } - if (base.mode == GDScriptCodeGenerator::Address::TEMPORARY) { - gen->pop_temporary(); + if (base.mode == GDScriptCodeGenerator::Address::TEMPORARY) { + gen->pop_temporary(); + } } } else { _set_error("Cannot call something that isn't a function.", call->callee); @@ -966,6 +971,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code } else { gen->write_set(prev_base, key, assigned); } + if (key.mode == GDScriptCodeGenerator::Address::TEMPORARY) { + gen->pop_temporary(); + } if (assigned.mode == GDScriptCodeGenerator::Address::TEMPORARY) { gen->pop_temporary(); } diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index 789af57b4c..eee713aa45 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -397,7 +397,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += DADDR(1 + argc); text += " = "; - text += "<unkown type>("; + text += "<unknown type>("; for (int i = 0; i < argc; i++) { if (i > 0) { text += ", "; @@ -542,6 +542,28 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { incr = 5 + argc; } break; + case OPCODE_CALL_BUILTIN_STATIC: { + Variant::Type type = (Variant::Type)_code_ptr[ip + 1 + instr_var_args]; + int argc = _code_ptr[ip + 3 + instr_var_args]; + + text += "call built-in method static "; + text += DADDR(1 + argc); + text += " = "; + text += Variant::get_type_name(type); + text += "."; + text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]].operator String(); + text += "("; + + for (int i = 0; i < argc; i++) { + if (i > 0) { + text += ", "; + } + text += DADDR(1 + i); + } + text += ")"; + + incr += 5 + argc; + } break; case OPCODE_CALL_PTRCALL_NO_RETURN: { text += "call-ptrcall (no return) "; @@ -666,7 +688,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { int argc = _code_ptr[ip + 1 + instr_var_args]; text += DADDR(1 + argc) + " = "; - text += "<unkown function>"; + text += "<unknown function>"; text += "("; for (int i = 0; i < argc; i++) { diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 6ae825d2bd..504c7414f6 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -741,6 +741,7 @@ static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite, ScriptCodeCompletionOption option; if (p_suite->locals[i].type == GDScriptParser::SuiteNode::Local::CONSTANT) { option = ScriptCodeCompletionOption(p_suite->locals[i].name, ScriptCodeCompletionOption::KIND_CONSTANT); + option.default_value = p_suite->locals[i].constant->initializer->reduced_value; } else { option = ScriptCodeCompletionOption(p_suite->locals[i].name, ScriptCodeCompletionOption::KIND_VARIABLE); } @@ -2872,7 +2873,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co StringName parent = ClassDB::get_parent_class(class_name); if (parent != StringName()) { if (String(parent).begins_with("_")) { - base_type.native_type = String(parent).right(1); + base_type.native_type = String(parent).substr(1); } else { base_type.native_type = parent; } @@ -3066,7 +3067,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol // proxy class remove the underscore. if (r_result.class_name.begins_with("_")) { - r_result.class_name = r_result.class_name.right(1); + r_result.class_name = r_result.class_name.substr(1); } return OK; } diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 70b62ced6d..26b8809337 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -263,6 +263,7 @@ public: OPCODE_CALL_SELF_BASE, OPCODE_CALL_METHOD_BIND, OPCODE_CALL_METHOD_BIND_RET, + OPCODE_CALL_BUILTIN_STATIC, // ptrcall have one instruction per return type. OPCODE_CALL_PTRCALL_NO_RETURN, OPCODE_CALL_PTRCALL_BOOL, @@ -496,6 +497,8 @@ private: Vector<GDScriptDataType> argument_types; GDScriptDataType return_type; + Map<int, Variant::Type> temporary_slots; + #ifdef TOOLS_ENABLED Vector<StringName> arg_names; Vector<Variant> default_arg_values; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index f9027c3a87..b61b469fbc 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -1173,7 +1173,7 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() { consume(GDScriptTokenizer::Token::BRACE_CLOSE, R"(Expected closing "}" for enum.)"); #ifdef TOOLS_ENABLED - // Enum values documentaion. + // Enum values documentation. for (int i = 0; i < enum_node->values.size(); i++) { if (i == enum_node->values.size() - 1) { // If close bracket is same line as last value. diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 4757ec6ca9..56b0f6db83 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -152,6 +152,44 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const return err_text; } +void (*type_init_function_table[])(Variant *) = { + nullptr, // NIL (shouldn't be called). + &VariantInitializer<bool>::init, // BOOL. + &VariantInitializer<int64_t>::init, // INT. + &VariantInitializer<double>::init, // FLOAT. + &VariantInitializer<String>::init, // STRING. + &VariantInitializer<Vector2>::init, // VECTOR2. + &VariantInitializer<Vector2i>::init, // VECTOR2I. + &VariantInitializer<Rect2>::init, // RECT2. + &VariantInitializer<Rect2i>::init, // RECT2I. + &VariantInitializer<Vector3>::init, // VECTOR3. + &VariantInitializer<Vector3i>::init, // VECTOR3I. + &VariantInitializer<Transform2D>::init, // TRANSFORM2D. + &VariantInitializer<Plane>::init, // PLANE. + &VariantInitializer<Quat>::init, // QUAT. + &VariantInitializer<AABB>::init, // AABB. + &VariantInitializer<Basis>::init, // BASIS. + &VariantInitializer<Transform>::init, // TRANSFORM. + &VariantInitializer<Color>::init, // COLOR. + &VariantInitializer<StringName>::init, // STRING_NAME. + &VariantInitializer<NodePath>::init, // NODE_PATH. + &VariantInitializer<RID>::init, // RID. + &VariantTypeAdjust<Object *>::adjust, // OBJECT. + &VariantInitializer<Callable>::init, // CALLABLE. + &VariantInitializer<Signal>::init, // SIGNAL. + &VariantInitializer<Dictionary>::init, // DICTIONARY. + &VariantInitializer<Array>::init, // ARRAY. + &VariantInitializer<PackedByteArray>::init, // PACKED_BYTE_ARRAY. + &VariantInitializer<PackedInt32Array>::init, // PACKED_INT32_ARRAY. + &VariantInitializer<PackedInt64Array>::init, // PACKED_INT64_ARRAY. + &VariantInitializer<PackedFloat32Array>::init, // PACKED_FLOAT32_ARRAY. + &VariantInitializer<PackedFloat64Array>::init, // PACKED_FLOAT64_ARRAY. + &VariantInitializer<PackedStringArray>::init, // PACKED_STRING_ARRAY. + &VariantInitializer<PackedVector2Array>::init, // PACKED_VECTOR2_ARRAY. + &VariantInitializer<PackedVector3Array>::init, // PACKED_VECTOR3_ARRAY. + &VariantInitializer<PackedColorArray>::init, // PACKED_COLOR_ARRAY. +}; + #if defined(__GNUC__) #define OPCODES_TABLE \ static const void *switch_table_ops[] = { \ @@ -196,6 +234,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const &&OPCODE_CALL_SELF_BASE, \ &&OPCODE_CALL_METHOD_BIND, \ &&OPCODE_CALL_METHOD_BIND_RET, \ + &&OPCODE_CALL_BUILTIN_STATIC, \ &&OPCODE_CALL_PTRCALL_NO_RETURN, \ &&OPCODE_CALL_PTRCALL_BOOL, \ &&OPCODE_CALL_PTRCALL_INT, \ @@ -491,6 +530,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script)); + for (const Map<int, Variant::Type>::Element *E = temporary_slots.front(); E; E = E->next()) { + type_init_function_table[E->get()](&stack[E->key()]); + } + String err_text; #ifdef DEBUG_ENABLED @@ -1573,6 +1616,51 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } DISPATCH_OPCODE; + OPCODE(OPCODE_CALL_BUILTIN_STATIC) { + CHECK_SPACE(4 + instr_arg_count); + + ip += instr_arg_count; + + GD_ERR_BREAK(_code_ptr[ip + 1] < 0 || _code_ptr[ip + 1] >= Variant::VARIANT_MAX); + Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 1]; + + int methodname_idx = _code_ptr[ip + 2]; + GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count); + const StringName *methodname = &_global_names_ptr[methodname_idx]; + + int argc = _code_ptr[ip + 3]; + GD_ERR_BREAK(argc < 0); + + GET_INSTRUCTION_ARG(ret, argc); + + const Variant **argptrs = const_cast<const Variant **>(instruction_args); + +#ifdef DEBUG_ENABLED + uint64_t call_time = 0; + + if (GDScriptLanguage::get_singleton()->profiling) { + call_time = OS::get_singleton()->get_ticks_usec(); + } +#endif + + Callable::CallError err; + Variant::call_static(builtin_type, *methodname, argptrs, argc, *ret, err); + +#ifdef DEBUG_ENABLED + if (GDScriptLanguage::get_singleton()->profiling) { + function_call_time += OS::get_singleton()->get_ticks_usec() - call_time; + } + + if (err.error != Callable::CallError::CALL_OK) { + err_text = _get_call_error(err, "static function '" + methodname->operator String() + "' in type '" + Variant::get_type_name(builtin_type) + "'", argptrs); + OPCODE_BREAK; + } +#endif + + ip += 4; + } + DISPATCH_OPCODE; + #ifdef DEBUG_ENABLED #define OPCODE_CALL_PTR(m_type) \ OPCODE(OPCODE_CALL_PTRCALL_##m_type) { \ @@ -1882,7 +1970,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #ifdef DEBUG_ENABLED if (err.error != Callable::CallError::CALL_OK) { // TODO: Add this information in debug. - String methodstr = "<unkown function>"; + String methodstr = "<unknown function>"; if (dst->get_type() == Variant::STRING) { // Call provided error string. err_text = "Error calling GDScript utility function '" + methodstr + "': " + String(*dst); diff --git a/modules/gdscript/tests/gdscript_test_runner_suite.h b/modules/gdscript/tests/gdscript_test_runner_suite.h index 136907b316..8fd77239cd 100644 --- a/modules/gdscript/tests/gdscript_test_runner_suite.h +++ b/modules/gdscript/tests/gdscript_test_runner_suite.h @@ -48,6 +48,27 @@ TEST_SUITE("[Modules][GDScript]") { } } +TEST_CASE("[Modules][GDScript] Load source code dynamically and run it") { + Ref<GDScript> gdscript = memnew(GDScript); + gdscript->set_source_code(R"( +extends Reference + +func _init(): + set_meta("result", 42) +)"); + // A spurious `Condition "err" is true` message is printed (despite parsing being successful and returning `OK`). + // Silence it. + ERR_PRINT_OFF; + const Error error = gdscript->reload(); + ERR_PRINT_ON; + CHECK_MESSAGE(error == OK, "The script should parse successfully."); + + // Run the script by assigning it to a reference-counted object. + Ref<Reference> reference = memnew(Reference); + reference->set_script(gdscript); + CHECK_MESSAGE(int(reference->get_meta("result")) == 42, "The script should assign object metadata successfully."); +} + } // namespace GDScriptTests #endif // GDSCRIPT_TEST_RUNNER_SUITE_H diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp index 36da64bbaa..8ad5cdacad 100644 --- a/modules/gdscript/tests/test_gdscript.cpp +++ b/modules/gdscript/tests/test_gdscript.cpp @@ -215,7 +215,7 @@ void test(TestType p_type) { init_language(fa->get_path_absolute().get_base_dir()); Vector<uint8_t> buf; - int flen = fa->get_len(); + uint64_t flen = fa->get_len(); buf.resize(fa->get_len() + 1); fa->get_buffer(buf.ptrw(), flen); buf.write[flen] = 0; diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index e67e29f7b4..b3fa17bfb5 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -664,7 +664,7 @@ static Vector<uint8_t> _parse_base64_uri(const String &uri) { int start = uri.find(","); ERR_FAIL_COND_V(start == -1, Vector<uint8_t>()); - CharString substr = uri.right(start + 1).ascii(); + CharString substr = uri.substr(start + 1).ascii(); int strlen = substr.length(); @@ -3031,8 +3031,11 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat } } - ERR_FAIL_COND_V_MSG(img.is_null(), ERR_FILE_CORRUPT, - vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype)); + if (img.is_null()) { + ERR_PRINT(vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype)); + state->images.push_back(Ref<Texture2D>()); + continue; + } Ref<ImageTexture> t; t.instance(); @@ -4387,6 +4390,9 @@ bool GLTFDocument::_skins_are_same(const Ref<Skin> skin_a, const Ref<Skin> skin_ if (skin_a->get_bind_bone(i) != skin_b->get_bind_bone(i)) { return false; } + if (skin_a->get_bind_name(i) != skin_b->get_bind_name(i)) { + return false; + } Transform a_xform = skin_a->get_bind_pose(i); Transform b_xform = skin_b->get_bind_pose(i); @@ -5975,13 +5981,15 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo const GLTFSkinIndex skin_i = node->skin; Map<GLTFNodeIndex, Node *>::Element *mi_element = state->scene_nodes.find(node_i); + ERR_CONTINUE_MSG(mi_element == nullptr, vformat("Unable to find node %d", node_i)); + EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(mi_element->get()); - ERR_FAIL_COND(mi == nullptr); + ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to EditorSceneImporterMeshNode3D", node_i, mi_element->get()->get_class_name())); const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton; Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i]; Skeleton3D *skeleton = gltf_skeleton->godot_skeleton; - ERR_FAIL_COND(skeleton == nullptr); + ERR_CONTINUE_MSG(skeleton == nullptr, vformat("Unable to find Skeleton for node %d skin %d", node_i, skin_i)); mi->get_parent()->remove_child(mi); skeleton->add_child(mi); diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 74ae45a46e..813b4b9689 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -615,13 +615,13 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && (mb->get_command() || mb->get_shift())) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && (mb->is_command_pressed() || mb->is_shift_pressed())) { if (mb->is_pressed()) { floor->set_value(floor->get_value() + mb->get_factor()); } return true; // Eaten. - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && (mb->get_command() || mb->get_shift())) { + } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && (mb->is_command_pressed() || mb->is_shift_pressed())) { if (mb->is_pressed()) { floor->set_value(floor->get_value() - mb->get_factor()); } @@ -630,7 +630,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In if (mb->is_pressed()) { Node3DEditorViewport::NavigationScheme nav_scheme = (Node3DEditorViewport::NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); - if ((nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA || nav_scheme == Node3DEditorViewport::NAVIGATION_MODO) && mb->get_alt()) { + if ((nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA || nav_scheme == Node3DEditorViewport::NAVIGATION_MODO) && mb->is_alt_pressed()) { input_action = INPUT_NONE; } else if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { bool can_edit = (node && node->get_mesh_library().is_valid()); @@ -638,10 +638,10 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In _do_paste(); input_action = INPUT_NONE; _update_paste_indicator(); - } else if (mb->get_shift() && can_edit) { + } else if (mb->is_shift_pressed() && can_edit) { input_action = INPUT_SELECT; last_selection = selection; - } else if (mb->get_command() && can_edit) { + } else if (mb->is_command_pressed() && can_edit) { input_action = INPUT_PICK; } else { input_action = INPUT_PAINT; @@ -732,7 +732,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In } } - if (k->get_shift() && selection.active && input_action != INPUT_PASTE) { + if (k->is_shift_pressed() && selection.active && input_action != INPUT_PASTE) { if (k->get_keycode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) { selection.click[edit_axis]--; _validate_selection(); @@ -749,7 +749,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid()) { - if (pan_gesture->get_alt() && (pan_gesture->get_command() || pan_gesture->get_shift())) { + if (pan_gesture->is_alt_pressed() && (pan_gesture->is_command_pressed() || pan_gesture->is_shift_pressed())) { const real_t delta = pan_gesture->get_delta().y * 0.5; accumulated_floor_delta += delta; int step = 0; @@ -810,7 +810,7 @@ void GridMapEditor::_mesh_library_palette_input(const Ref<InputEvent> &p_ie) { const Ref<InputEventMouseButton> mb = p_ie; // Zoom in/out using Ctrl + mouse wheel - if (mb.is_valid() && mb->is_pressed() && mb->get_command()) { + if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed()) { if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { size_slider->set_value(size_slider->get_value() + 0.2); } diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp index 7daf6a3a57..18beff41d8 100644 --- a/modules/jpg/image_loader_jpegd.cpp +++ b/modules/jpg/image_loader_jpegd.cpp @@ -105,7 +105,7 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p Error ImageLoaderJPG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { Vector<uint8_t> src_image; - int src_image_len = f->get_len(); + uint64_t src_image_len = f->get_len(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); src_image.resize(src_image_len); diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp index 987306af2a..4a42e9af0d 100644 --- a/modules/mbedtls/crypto_mbedtls.cpp +++ b/modules/mbedtls/crypto_mbedtls.cpp @@ -58,7 +58,7 @@ Error CryptoKeyMbedTLS::load(String p_path, bool p_public_only) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot open CryptoKeyMbedTLS file '" + p_path + "'."); - int flen = f->get_len(); + uint64_t flen = f->get_len(); out.resize(flen + 1); f->get_buffer(out.ptrw(), flen); out.write[flen] = 0; // string terminator @@ -146,7 +146,7 @@ Error X509CertificateMbedTLS::load(String p_path) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot open X509CertificateMbedTLS file '" + p_path + "'."); - int flen = f->get_len(); + uint64_t flen = f->get_len(); out.resize(flen + 1); f->get_buffer(out.ptrw(), flen); out.write[flen] = 0; // string terminator diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp index afd26fb79e..96cce49c86 100644 --- a/modules/minimp3/resource_importer_mp3.cpp +++ b/modules/minimp3/resource_importer_mp3.cpp @@ -79,7 +79,7 @@ Error ResourceImporterMP3::import(const String &p_source_file, const String &p_s ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); - size_t len = f->get_len(); + uint64_t len = f->get_len(); Vector<uint8_t> data; data.resize(len); diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index ffb04bfd37..b6a7a7579c 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -368,7 +368,7 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin "}\n"; // Replaces all spaces in p_class_name with underscores to prevent - // erronous C# Script templates from being generated when the object name + // invalid C# Script templates from being generated when the object name // has spaces in it. String class_name_no_spaces = p_class_name.replace(" ", "_"); String base_class_name = get_base_class_name(p_base_class_name, class_name_no_spaces); diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index 43de77005e..5d53394658 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -170,10 +170,10 @@ Error read_all_file_utf8(const String &p_path, String &r_content) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'."); - int len = f->get_len(); + uint64_t len = f->get_len(); sourcef.resize(len + 1); uint8_t *w = sourcef.ptrw(); - int r = f->get_buffer(w, len); + uint64_t r = f->get_buffer(w, len); f->close(); memdelete(f); ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN); diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml index 38c5138482..a12412a9cd 100644 --- a/modules/opensimplex/doc_classes/NoiseTexture.xml +++ b/modules/opensimplex/doc_classes/NoiseTexture.xml @@ -31,6 +31,9 @@ <member name="noise" type="OpenSimplexNoise" setter="set_noise" getter="get_noise"> The [OpenSimplexNoise] instance used to generate the noise. </member> + <member name="noise_offset" type="Vector2" setter="set_noise_offset" getter="get_noise_offset" default="Vector2( 0, 0 )"> + An offset used to specify the noise space coordinate of the top left corner of the generated noise. This value is ignored if [member seamless] is enabled. + </member> <member name="seamless" type="bool" setter="set_seamless" getter="get_seamless" default="false"> Whether the texture can be tiled without visible seams or not. Seamless textures take longer to generate. [b]Note:[/b] Seamless noise has a lower contrast compared to non-seamless noise. This is due to the way noise uses higher dimensions for generating seamless noise. diff --git a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml index ad82f87213..2fdbd61ee7 100644 --- a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml +++ b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml @@ -31,8 +31,10 @@ </argument> <argument index="1" name="height" type="int"> </argument> + <argument index="2" name="noise_offset" type="Vector2" default="Vector2( 0, 0 )"> + </argument> <description> - Generate a noise image in [constant Image.FORMAT_L8] format with the requested [code]width[/code] and [code]height[/code], based on the current noise parameters. + Generate a noise image in [constant Image.FORMAT_L8] format with the requested [code]width[/code] and [code]height[/code], based on the current noise parameters. If [code]noise_offset[/code] is specified, then the offset value is used as the coordinates of the top-left corner of the generated noise. </description> </method> <method name="get_noise_1d" qualifiers="const"> diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp index 7272d32fac..9e0155da94 100644 --- a/modules/opensimplex/noise_texture.cpp +++ b/modules/opensimplex/noise_texture.cpp @@ -52,6 +52,9 @@ void NoiseTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise); ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise); + ClassDB::bind_method(D_METHOD("set_noise_offset", "noise_offset"), &NoiseTexture::set_noise_offset); + ClassDB::bind_method(D_METHOD("get_noise_offset"), &NoiseTexture::get_noise_offset); + ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless); ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless); @@ -71,6 +74,7 @@ void NoiseTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normal_map"), "set_as_normal_map", "is_normal_map"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "noise_offset"), "set_noise_offset", "get_noise_offset"); } void NoiseTexture::_validate_property(PropertyInfo &property) const { @@ -130,7 +134,7 @@ Ref<Image> NoiseTexture::_generate_texture() { if (seamless) { image = ref_noise->get_seamless_image(size.x); } else { - image = ref_noise->get_image(size.x, size.y); + image = ref_noise->get_image(size.x, size.y, noise_offset); } if (as_normal_map) { @@ -198,6 +202,14 @@ void NoiseTexture::set_height(int p_height) { _queue_update(); } +void NoiseTexture::set_noise_offset(Vector2 p_noise_offset) { + if (noise_offset == p_noise_offset) { + return; + } + noise_offset = p_noise_offset; + _queue_update(); +} + void NoiseTexture::set_seamless(bool p_seamless) { if (p_seamless == seamless) { return; @@ -245,6 +257,10 @@ int NoiseTexture::get_height() const { return size.y; } +Vector2 NoiseTexture::get_noise_offset() const { + return noise_offset; +} + RID NoiseTexture::get_rid() const { if (!texture.is_valid()) { texture = RS::get_singleton()->texture_2d_placeholder_create(); diff --git a/modules/opensimplex/noise_texture.h b/modules/opensimplex/noise_texture.h index 6983ae18fe..20a53bb58b 100644 --- a/modules/opensimplex/noise_texture.h +++ b/modules/opensimplex/noise_texture.h @@ -56,6 +56,7 @@ private: Ref<OpenSimplexNoise> noise; Vector2i size = Vector2i(512, 512); + Vector2 noise_offset; bool seamless = false; bool as_normal_map = false; float bump_strength = 8.0; @@ -79,6 +80,9 @@ public: void set_width(int p_width); void set_height(int p_height); + void set_noise_offset(Vector2 p_noise_offset); + Vector2 get_noise_offset() const; + void set_seamless(bool p_seamless); bool get_seamless(); diff --git a/modules/opensimplex/open_simplex_noise.cpp b/modules/opensimplex/open_simplex_noise.cpp index 3773946112..f0a8867284 100644 --- a/modules/opensimplex/open_simplex_noise.cpp +++ b/modules/opensimplex/open_simplex_noise.cpp @@ -96,7 +96,7 @@ void OpenSimplexNoise::set_lacunarity(float p_lacunarity) { emit_changed(); } -Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) const { +Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height, const Vector2 &p_noise_offset) const { Vector<uint8_t> data; data.resize(p_width * p_height); @@ -104,7 +104,7 @@ Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) const { for (int i = 0; i < p_height; i++) { for (int j = 0; j < p_width; j++) { - float v = get_noise_2d(j, i); + float v = get_noise_2d(float(j) + p_noise_offset.x, float(i) + p_noise_offset.y); v = v * 0.5 + 0.5; // Normalize [0..1] wd8[(i * p_width + j)] = uint8_t(CLAMP(v * 255.0, 0, 255)); } @@ -161,7 +161,7 @@ void OpenSimplexNoise::_bind_methods() { ClassDB::bind_method(D_METHOD("set_lacunarity", "lacunarity"), &OpenSimplexNoise::set_lacunarity); ClassDB::bind_method(D_METHOD("get_lacunarity"), &OpenSimplexNoise::get_lacunarity); - ClassDB::bind_method(D_METHOD("get_image", "width", "height"), &OpenSimplexNoise::get_image); + ClassDB::bind_method(D_METHOD("get_image", "width", "height", "noise_offset"), &OpenSimplexNoise::get_image, DEFVAL(Vector2())); ClassDB::bind_method(D_METHOD("get_seamless_image", "size"), &OpenSimplexNoise::get_seamless_image); ClassDB::bind_method(D_METHOD("get_noise_1d", "x"), &OpenSimplexNoise::get_noise_1d); diff --git a/modules/opensimplex/open_simplex_noise.h b/modules/opensimplex/open_simplex_noise.h index 847c157409..bb50c523d2 100644 --- a/modules/opensimplex/open_simplex_noise.h +++ b/modules/opensimplex/open_simplex_noise.h @@ -75,7 +75,7 @@ public: void set_lacunarity(float p_lacunarity); float get_lacunarity() const { return lacunarity; } - Ref<Image> get_image(int p_width, int p_height) const; + Ref<Image> get_image(int p_width, int p_height, const Vector2 &p_noise_offset = Vector2()) const; Ref<Image> get_seamless_image(int p_size) const; float get_noise_1d(float x) const; diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp index ec1c30783a..17380001f5 100644 --- a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp @@ -79,7 +79,7 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file '" + p_source_file + "'."); - size_t len = f->get_len(); + uint64_t len = f->get_len(); Vector<uint8_t> data; data.resize(len); diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index 6ce3e4b4b3..24fe654946 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -140,7 +140,7 @@ Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, const char *p } Error ImageLoaderSVG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { - uint32_t size = f->get_len(); + uint64_t size = f->get_len(); Vector<uint8_t> src_image; src_image.resize(size + 1); uint8_t *src_w = src_image.ptrw(); diff --git a/modules/text_server_adv/dynamic_font_adv.cpp b/modules/text_server_adv/dynamic_font_adv.cpp index 326af7f0ee..faeb83f920 100644 --- a/modules/text_server_adv/dynamic_font_adv.cpp +++ b/modules/text_server_adv/dynamic_font_adv.cpp @@ -66,7 +66,7 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size( ERR_FAIL_V_MSG(nullptr, "Cannot open font file '" + font_path + "'."); } - size_t len = f->get_len(); + uint64_t len = f->get_len(); font_mem_cache.resize(len); f->get_buffer(font_mem_cache.ptrw(), len); font_mem = font_mem_cache.ptr(); diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 8b8b6b7cd3..361852547f 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -181,7 +181,7 @@ bool TextServerAdvanced::load_support_data(const String &p_filename) { UErrorCode err = U_ZERO_ERROR; // ICU data found. - size_t len = f->get_len(); + uint64_t len = f->get_len(); icu_data = (uint8_t *)memalloc(len); f->get_buffer(icu_data, len); f->close(); diff --git a/modules/text_server_fb/dynamic_font_fb.cpp b/modules/text_server_fb/dynamic_font_fb.cpp index dec1d6f83f..406f60b6f5 100644 --- a/modules/text_server_fb/dynamic_font_fb.cpp +++ b/modules/text_server_fb/dynamic_font_fb.cpp @@ -65,7 +65,7 @@ DynamicFontDataFallback::DataAtSize *DynamicFontDataFallback::get_data_for_size( ERR_FAIL_V_MSG(nullptr, "Cannot open font file '" + font_path + "'."); } - size_t len = f->get_len(); + uint64_t len = f->get_len(); font_mem_cache.resize(len); f->get_buffer(font_mem_cache.ptrw(), len); font_mem = font_mem_cache.ptr(); diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp index ef53661557..52b92ee930 100644 --- a/modules/tga/image_loader_tga.cpp +++ b/modules/tga/image_loader_tga.cpp @@ -226,9 +226,9 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { Vector<uint8_t> src_image; - int src_image_len = f->get_len(); + uint64_t src_image_len = f->get_len(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); - ERR_FAIL_COND_V(src_image_len < (int)sizeof(tga_header_s), ERR_FILE_CORRUPT); + ERR_FAIL_COND_V(src_image_len < (int64_t)sizeof(tga_header_s), ERR_FILE_CORRUPT); src_image.resize(src_image_len); Error err = OK; diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 54f5b3f424..7b421bdc16 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -58,7 +58,7 @@ int VideoStreamPlaybackTheora::buffer_data() { #else - int bytes = file->get_buffer((uint8_t *)buffer, 4096); + uint64_t bytes = file->get_buffer((uint8_t *)buffer, 4096); ogg_sync_wrote(&oy, bytes); return (bytes); @@ -176,7 +176,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { thread_eof = false; //pre-fill buffer int to_read = ring_buffer.space_left(); - int read = file->get_buffer(read_buffer.ptr(), to_read); + uint64_t read = file->get_buffer(read_buffer.ptr(), to_read); ring_buffer.write(read_buffer.ptr(), read); thread.start(_streaming_thread, this); @@ -632,8 +632,8 @@ void VideoStreamPlaybackTheora::_streaming_thread(void *ud) { //just fill back the buffer if (!vs->thread_eof) { int to_read = vs->ring_buffer.space_left(); - if (to_read) { - int read = vs->file->get_buffer(vs->read_buffer.ptr(), to_read); + if (to_read > 0) { + uint64_t read = vs->file->get_buffer(vs->read_buffer.ptr(), to_read); vs->ring_buffer.write(vs->read_buffer.ptr(), read); vs->thread_eof = vs->file->eof_reached(); } diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp index 47214e6974..cfb75fb93b 100644 --- a/modules/tinyexr/image_loader_tinyexr.cpp +++ b/modules/tinyexr/image_loader_tinyexr.cpp @@ -37,7 +37,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { Vector<uint8_t> src_image; - int src_image_len = f->get_len(); + uint64_t src_image_len = f->get_len(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); src_image.resize(src_image_len); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index dc400982e8..7432440603 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -1168,11 +1168,11 @@ void VisualScriptEditor::_member_selected() { selected = ti->get_metadata(0); - if (ti->get_parent() == members->get_root()->get_children()) { + if (ti->get_parent() == members->get_root()->get_first_child()) { #ifdef OSX_ENABLED bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_META); #else - bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL); #endif if (held_ctrl) { ERR_FAIL_COND(!script->has_function(selected)); @@ -1214,7 +1214,7 @@ void VisualScriptEditor::_member_edited() { TreeItem *root = members->get_root(); - if (ti->get_parent() == root->get_children()) { + if (ti->get_parent() == root->get_first_child()) { selected = new_name; int node_id = script->get_function_node_id(name); @@ -1255,7 +1255,7 @@ void VisualScriptEditor::_member_edited() { return; // Or crash because it will become invalid. } - if (ti->get_parent() == root->get_children()->get_next()) { + if (ti->get_parent() == root->get_first_child()->get_next()) { selected = new_name; undo_redo->create_action(TTR("Rename Variable")); undo_redo->add_do_method(script.ptr(), "rename_variable", name, new_name); @@ -1271,7 +1271,7 @@ void VisualScriptEditor::_member_edited() { return; // Or crash because it will become invalid. } - if (ti->get_parent() == root->get_children()->get_next()->get_next()) { + if (ti->get_parent() == root->get_first_child()->get_next()->get_next()) { selected = new_name; undo_redo->create_action(TTR("Rename Signal")); undo_redo->add_do_method(script.ptr(), "rename_custom_signal", name, new_name); @@ -1405,7 +1405,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt if (ti->get_parent() == root) { //main buttons - if (ti == root->get_children()) { + if (ti == root->get_first_child()) { // Add function, this one uses menu. if (p_button == 1) { @@ -1442,7 +1442,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt return; // Or crash because it will become invalid. } - if (ti == root->get_children()->get_next()) { + if (ti == root->get_first_child()->get_next()) { // Add variable. String name = _validate_name("new_variable"); selected = name; @@ -1458,7 +1458,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt return; // Or crash because it will become invalid. } - if (ti == root->get_children()->get_next()->get_next()) { + if (ti == root->get_first_child()->get_next()->get_next()) { // Add variable. String name = _validate_name("new_signal"); selected = name; @@ -1473,7 +1473,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt undo_redo->commit_action(); return; // Or crash because it will become invalid. } - } else if (ti->get_parent() == root->get_children()) { + } else if (ti->get_parent() == root->get_first_child()) { selected = ti->get_text(0); function_name_edit->set_position(Input::get_singleton()->get_mouse_position() - Vector2(60, -10)); function_name_edit->popup(); @@ -1841,13 +1841,13 @@ void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) { TreeItem *ti = members->get_selected(); if (ti) { TreeItem *root = members->get_root(); - if (ti->get_parent() == root->get_children()) { + if (ti->get_parent() == root->get_first_child()) { member_type = MEMBER_FUNCTION; } - if (ti->get_parent() == root->get_children()->get_next()) { + if (ti->get_parent() == root->get_first_child()->get_next()) { member_type = MEMBER_VARIABLE; } - if (ti->get_parent() == root->get_children()->get_next()->get_next()) { + if (ti->get_parent() == root->get_first_child()->get_next()->get_next()) { member_type = MEMBER_SIGNAL; } member_name = ti->get_text(0); @@ -1864,7 +1864,7 @@ void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> btn = p_event; if (btn.is_valid() && btn->is_double_click()) { TreeItem *ti = members->get_selected(); - if (ti && ti->get_parent() == members->get_root()->get_children()) { // to check if it's a function + if (ti && ti->get_parent() == members->get_root()->get_first_child()) { // to check if it's a function _center_on_node(script->get_function_node_id(ti->get_metadata(0))); } } @@ -1946,13 +1946,13 @@ Variant VisualScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f Dictionary dd; TreeItem *root = members->get_root(); - if (it->get_parent() == root->get_children()) { + if (it->get_parent() == root->get_first_child()) { dd["type"] = "visual_script_function_drag"; dd["function"] = type; - } else if (it->get_parent() == root->get_children()->get_next()) { + } else if (it->get_parent() == root->get_first_child()->get_next()) { dd["type"] = "visual_script_variable_drag"; dd["variable"] = type; - } else if (it->get_parent() == root->get_children()->get_next()->get_next()) { + } else if (it->get_parent() == root->get_first_child()->get_next()->get_next()) { dd["type"] = "visual_script_signal_drag"; dd["signal"] = type; @@ -2070,7 +2070,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da #ifdef OSX_ENABLED bool use_set = Input::get_singleton()->is_key_pressed(KEY_META); #else - bool use_set = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool use_set = Input::get_singleton()->is_key_pressed(KEY_CTRL); #endif Vector2 ofs = graph->get_scroll_ofs() + p_point; if (graph->is_using_snap()) { @@ -2258,7 +2258,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da #ifdef OSX_ENABLED bool use_node = Input::get_singleton()->is_key_pressed(KEY_META); #else - bool use_node = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool use_node = Input::get_singleton()->is_key_pressed(KEY_CTRL); #endif Array nodes = d["nodes"]; @@ -2341,7 +2341,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da #ifdef OSX_ENABLED bool use_get = Input::get_singleton()->is_key_pressed(KEY_META); #else - bool use_get = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool use_get = Input::get_singleton()->is_key_pressed(KEY_CTRL); #endif if (!node || Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { @@ -2710,6 +2710,10 @@ void VisualScriptEditor::set_debugger_active(bool p_active) { } } +Control *VisualScriptEditor::get_base_editor() const { + return graph; +} + void VisualScriptEditor::set_tooltip_request_func(String p_method, Object *p_obj) { } @@ -4111,7 +4115,7 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { Ref<Texture2D> edit_icon = Control::get_theme_icon("Edit", "EditorIcons"); - if (ti->get_parent() == root->get_children()) { + if (ti->get_parent() == root->get_first_child()) { member_type = MEMBER_FUNCTION; member_name = ti->get_text(0); member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); @@ -4121,7 +4125,7 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { return; } - if (ti->get_parent() == root->get_children()->get_next()) { + if (ti->get_parent() == root->get_first_child()->get_next()) { member_type = MEMBER_VARIABLE; member_name = ti->get_text(0); member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); @@ -4131,7 +4135,7 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { return; } - if (ti->get_parent() == root->get_children()->get_next()->get_next()) { + if (ti->get_parent() == root->get_first_child()->get_next()->get_next()) { member_type = MEMBER_SIGNAL; member_name = ti->get_text(0); member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index fc9a2df60f..ef3a5d11c0 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -320,6 +320,8 @@ public: virtual bool can_lose_focus_on_node_selection() override { return false; } virtual void validate() override; + virtual Control *get_base_editor() const override; + static void register_editor(); static void free_clipboard(); diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index 862cac5c67..93e14f60d0 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -59,7 +59,7 @@ void VisualScriptPropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) { search_box->accept_event(); TreeItem *root = search_options->get_root(); - if (!root->get_children()) { + if (!root->get_first_child()) { break; } @@ -265,7 +265,7 @@ void VisualScriptPropertySelector::_update_search() { item->set_metadata(2, connecting); } - if (category && category->get_children() == nullptr) { + if (category && category->get_first_child() == nullptr) { memdelete(category); //old category was unused } } @@ -310,7 +310,7 @@ void VisualScriptPropertySelector::_update_search() { found = true; } - get_ok_button()->set_disabled(root->get_children() == nullptr); + get_ok_button()->set_disabled(root->get_first_child() == nullptr); } void VisualScriptPropertySelector::create_visualscript_item(const String &name, TreeItem *const root, const String &search_input, const String &text) { diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp index a6b64b342e..15bf9dbf2d 100644 --- a/modules/webm/video_stream_webm.cpp +++ b/modules/webm/video_stream_webm.cpp @@ -62,10 +62,10 @@ public: virtual int Read(long long pos, long len, unsigned char *buf) { if (file) { - if (file->get_position() != (size_t)pos) { + if (file->get_position() != (uint64_t)pos) { file->seek(pos); } - if (file->get_buffer(buf, len) == len) { + if (file->get_buffer(buf, len) == (uint64_t)len) { return 0; } } @@ -74,7 +74,7 @@ public: virtual int Length(long long *total, long long *available) { if (file) { - const size_t len = file->get_len(); + const uint64_t len = file->get_len(); if (total) { *total = len; } diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp index 6e62840a3e..d7e88d76b1 100644 --- a/modules/webp/image_loader_webp.cpp +++ b/modules/webp/image_loader_webp.cpp @@ -147,7 +147,7 @@ static Ref<Image> _webp_mem_loader_func(const uint8_t *p_png, int p_size) { Error ImageLoaderWEBP::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { Vector<uint8_t> src_image; - int src_image_len = f->get_len(); + uint64_t src_image_len = f->get_len(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); src_image.resize(src_image_len); diff --git a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml index e21dee8eff..3b53892a3d 100644 --- a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml +++ b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml @@ -48,7 +48,7 @@ Valid [code]options[/code] are: [codeblock] { - "negotiated": true, # When set to true (default off), means the channel is negotiated out of band. "id" must be set too. data_channel_received will not be called. + "negotiated": true, # When set to true (default off), means the channel is negotiated out of band. "id" must be set too. "data_channel_received" will not be called. "id": 1, # When "negotiated" is true this value must also be set to the same value on both peer. # Only one of maxRetransmits and maxPacketLifeTime can be specified, not both. They make the channel unreliable (but also better at real time). diff --git a/modules/webxr/doc_classes/WebXRInterface.xml b/modules/webxr/doc_classes/WebXRInterface.xml index 2407d44496..9b3a063ef5 100644 --- a/modules/webxr/doc_classes/WebXRInterface.xml +++ b/modules/webxr/doc_classes/WebXRInterface.xml @@ -7,7 +7,7 @@ WebXR is an open standard that allows creating VR and AR applications that run in the web browser. As such, this interface is only available when running in an HTML5 export. WebXR supports a wide range of devices, from the very capable (like Valve Index, HTC Vive, Oculus Rift and Quest) down to the much less capable (like Google Cardboard, Oculus Go, GearVR, or plain smartphones). - Since WebXR is based on Javascript, it makes extensive use of callbacks, which means that [WebXRInterface] is forced to use signals, where other AR/VR interfaces would instead use functions that return a result immediately. This makes [WebXRInterface] quite a bit more complicated to intialize than other AR/VR interfaces. + Since WebXR is based on Javascript, it makes extensive use of callbacks, which means that [WebXRInterface] is forced to use signals, where other AR/VR interfaces would instead use functions that return a result immediately. This makes [WebXRInterface] quite a bit more complicated to initialize than other AR/VR interfaces. Here's the minimum code required to start an immersive VR session: [codeblock] extends Node3D diff --git a/platform/android/android_keys_utils.h b/platform/android/android_keys_utils.h index e0ee2888c0..6d25a366a4 100644 --- a/platform/android/android_keys_utils.h +++ b/platform/android/android_keys_utils.h @@ -127,8 +127,8 @@ static _WinTranslatePair _ak_to_keycode[] = { { KEY_BACKSLASH, AKEYCODE_BACKSLASH }, { KEY_BRACKETLEFT, AKEYCODE_LEFT_BRACKET }, { KEY_BRACKETRIGHT, AKEYCODE_RIGHT_BRACKET }, - { KEY_CONTROL, AKEYCODE_CTRL_LEFT }, - { KEY_CONTROL, AKEYCODE_CTRL_RIGHT }, + { KEY_CTRL, AKEYCODE_CTRL_LEFT }, + { KEY_CTRL, AKEYCODE_CTRL_RIGHT }, { KEY_UNKNOWN, 0 } }; /* diff --git a/platform/android/detect.py b/platform/android/detect.py index 2a80a3c45b..1b6af8662e 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -250,7 +250,7 @@ def configure(env): env["RANLIB"] = tools_path + "/ranlib" env["AS"] = tools_path + "/as" - common_opts = ["-fno-integrated-as", "-gcc-toolchain", gcc_toolchain_path] + common_opts = ["-gcc-toolchain", gcc_toolchain_path] # Compile flags @@ -285,6 +285,9 @@ def configure(env): ) env.Append(CPPDEFINES=["NO_STATVFS", "GLES_ENABLED"]) + if get_platform(env["ndk_platform"]) >= 24: + env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)]) + env["neon_enabled"] = False if env["android_arch"] == "x86": target_opts = ["-target", "i686-none-linux-android"] diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp index f8ac29c738..0bae090702 100644 --- a/platform/android/dir_access_jandroid.cpp +++ b/platform/android/dir_access_jandroid.cpp @@ -201,8 +201,7 @@ String DirAccessJAndroid::get_filesystem_type() const { return "APK"; } -//FileType get_file_type() const; -size_t DirAccessJAndroid::get_space_left() { +uint64_t DirAccessJAndroid::get_space_left() { return 0; } diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h index fed468d051..fe87644fe2 100644 --- a/platform/android/dir_access_jandroid.h +++ b/platform/android/dir_access_jandroid.h @@ -76,8 +76,7 @@ public: virtual String get_filesystem_type() const; - //virtual FileType get_file_type() const; - size_t get_space_left(); + uint64_t get_space_left(); static void setup(jobject p_io); diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 7a32184139..f46dcf58dc 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -36,8 +36,6 @@ #include "java_godot_wrapper.h" #include "os_android.h" -#include <android/input.h> - #if defined(VULKAN_ENABLED) #include "drivers/vulkan/rendering_device_vulkan.h" #include "platform/android/vulkan/vulkan_context_android.h" @@ -51,7 +49,7 @@ DisplayServerAndroid *DisplayServerAndroid::get_singleton() { bool DisplayServerAndroid::has_feature(Feature p_feature) const { switch (p_feature) { //case FEATURE_CONSOLE_WINDOW: - //case FEATURE_CURSOR_SHAPE: + case FEATURE_CURSOR_SHAPE: //case FEATURE_CUSTOM_CURSOR_SHAPE: //case FEATURE_GLOBAL_MENU: //case FEATURE_HIDPI: @@ -490,10 +488,10 @@ void DisplayServerAndroid::process_joy_event(DisplayServerAndroid::JoypadEvent p } void DisplayServerAndroid::_set_key_modifier_state(Ref<InputEventWithModifiers> ev) { - ev->set_shift(shift_mem); - ev->set_alt(alt_mem); - ev->set_metakey(meta_mem); - ev->set_control(control_mem); + ev->set_shift_pressed(shift_mem); + ev->set_alt_pressed(alt_mem); + ev->set_meta_pressed(meta_mem); + ev->set_ctrl_pressed(control_mem); } void DisplayServerAndroid::process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed) { @@ -528,7 +526,7 @@ void DisplayServerAndroid::process_key_event(int p_keycode, int p_scancode, int if (keycode == KEY_ALT) { alt_mem = p_pressed; } - if (keycode == KEY_CONTROL) { + if (keycode == KEY_CTRL) { control_mem = p_pressed; } if (keycode == KEY_META) { @@ -829,6 +827,12 @@ void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) { return; } + if (p_mode == MouseMode::MOUSE_MODE_HIDDEN) { + OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(CURSOR_TYPE_NULL); + } else { + cursor_set_shape(cursor_shape); + } + if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) { OS_Android::get_singleton()->get_godot_java()->get_godot_view()->request_pointer_capture(); } else { @@ -870,3 +874,19 @@ int DisplayServerAndroid::_android_button_mask_to_godot_button_mask(int android_ return godot_button_mask; } + +void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) { + if (cursor_shape == p_shape) { + return; + } + + cursor_shape = p_shape; + + if (mouse_mode == MouseMode::MOUSE_MODE_VISIBLE || mouse_mode == MouseMode::MOUSE_MODE_CONFINED) { + OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(android_cursors[cursor_shape]); + } +} + +DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const { + return cursor_shape; +} diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index b9d1641656..53c768f406 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -70,6 +70,28 @@ private: int buttons_state; + // https://developer.android.com/reference/android/view/PointerIcon + // mapping between Godot's cursor shape to Android's' + int android_cursors[CURSOR_MAX] = { + 1000, //CURSOR_ARROW + 1008, //CURSOR_IBEAM + 1002, //CURSOR_POINTIN + 1007, //CURSOR_CROSS + 1004, //CURSOR_WAIT + 1004, //CURSOR_BUSY + 1021, //CURSOR_DRAG + 1021, //CURSOR_CAN_DRO + 1000, //CURSOR_FORBIDD (no corresponding icon in Android's icon so fallback to default) + 1015, //CURSOR_VSIZE + 1014, //CURSOR_HSIZE + 1017, //CURSOR_BDIAGSI + 1016, //CURSOR_FDIAGSI + 1020, //CURSOR_MOVE + 1015, //CURSOR_VSPLIT + 1014, //CURSOR_HSPLIT + 1003, //CURSOR_HELP + }; + const int CURSOR_TYPE_NULL = 0; MouseMode mouse_mode; bool keep_screen_on; @@ -78,6 +100,8 @@ private: Point2 hover_prev_pos; // needed to calculate the relative position on hover events Point2 scroll_prev_pos; // needed to calculate the relative position on scroll events + CursorShape cursor_shape = CursorShape::CURSOR_ARROW; + #if defined(VULKAN_ENABLED) VulkanContextAndroid *context_vulkan; RenderingDeviceVulkan *rendering_device_vulkan; @@ -180,6 +204,9 @@ public: void process_joy_event(JoypadEvent p_event); void process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed); + virtual void cursor_set_shape(CursorShape p_shape); + virtual CursorShape cursor_get_shape() const; + void mouse_set_mode(MouseMode p_mode); MouseMode mouse_get_mode() const; diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp index 705891713f..900d4d9b20 100644 --- a/platform/android/file_access_android.cpp +++ b/platform/android/file_access_android.cpp @@ -71,8 +71,9 @@ bool FileAccessAndroid::is_open() const { return a != nullptr; } -void FileAccessAndroid::seek(size_t p_position) { +void FileAccessAndroid::seek(uint64_t p_position) { ERR_FAIL_COND(!a); + AAsset_seek(a, p_position, SEEK_SET); pos = p_position; if (pos > len) { @@ -89,11 +90,11 @@ void FileAccessAndroid::seek_end(int64_t p_position) { pos = len + p_position; } -size_t FileAccessAndroid::get_position() const { +uint64_t FileAccessAndroid::get_position() const { return pos; } -size_t FileAccessAndroid::get_len() const { +uint64_t FileAccessAndroid::get_len() const { return len; } @@ -113,11 +114,10 @@ uint8_t FileAccessAndroid::get_8() const { return byte; } -int FileAccessAndroid::get_buffer(uint8_t *p_dst, int p_length) const { +uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const { ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - ERR_FAIL_COND_V(p_length < 0, -1); - off_t r = AAsset_read(a, p_dst, p_length); + int r = AAsset_read(a, p_dst, p_length); if (pos + p_length > len) { eof = true; diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h index 56010c918a..9b0f85089d 100644 --- a/platform/android/file_access_android.h +++ b/platform/android/file_access_android.h @@ -40,8 +40,8 @@ class FileAccessAndroid : public FileAccess { static FileAccess *create_android(); mutable AAsset *a = nullptr; - mutable size_t len = 0; - mutable size_t pos = 0; + mutable uint64_t len = 0; + mutable uint64_t pos = 0; mutable bool eof = false; public: @@ -51,15 +51,15 @@ public: virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open - virtual void seek(size_t p_position); ///< seek to a given position + virtual void seek(uint64_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual size_t get_position() const; ///< get position in the file - virtual size_t get_len() const; ///< get size of the file + virtual uint64_t get_position() const; ///< get position in the file + virtual uint64_t get_len() const; ///< get size of the file virtual bool eof_reached() const; ///< reading passed EOF virtual uint8_t get_8() const; ///< get a byte - virtual int get_buffer(uint8_t *p_dst, int p_length) const; + virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; virtual Error get_error() const; ///< get last error diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index 63c91561ff..b3ee55ea64 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -44,11 +44,15 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.PixelFormat; import android.opengl.GLSurfaceView; +import android.os.Build; import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.PointerIcon; import android.view.SurfaceView; +import androidx.annotation.Keep; + /** * A simple GLSurfaceView sub-class that demonstrate how to perform * OpenGL ES 2.0 rendering into a GL Surface. Note the following important @@ -72,6 +76,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView private final GodotInputHandler inputHandler; private final GestureDetector detector; private final GodotRenderer godotRenderer; + private PointerIcon pointerIcon; public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, boolean p_use_32_bits, boolean p_use_debug_opengl) { @@ -83,6 +88,9 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView this.inputHandler = new GodotInputHandler(this); this.detector = new GestureDetector(context, new GodotGestureHandler(this)); this.godotRenderer = new GodotRenderer(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + pointerIcon = PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT); + } init(xrMode, false, 16, 0); } @@ -149,6 +157,21 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView return inputHandler.onGenericMotionEvent(event); } + /** + * called from JNI to change pointer icon + */ + @Keep + public void setPointerIcon(int pointerType) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType); + } + } + + @Override + public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) { + return pointerIcon; + } + private void init(XRMode xrMode, boolean translucent, int depth, int stencil) { setPreserveEGLContextOnPause(true); setFocusableInTouchMode(true); diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java index 2047c88070..ac333dd827 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java @@ -47,4 +47,6 @@ public interface GodotRenderView { abstract public void onBackPressed(); abstract public GodotInputHandler getInputHandler(); + + abstract public void setPointerIcon(int pointerType); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java index 2e59dbc0d0..169c6cf770 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java @@ -37,17 +37,22 @@ import org.godotengine.godot.vulkan.VkSurfaceView; import android.annotation.SuppressLint; import android.content.Context; +import android.os.Build; import android.view.GestureDetector; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.PointerIcon; import android.view.SurfaceView; +import androidx.annotation.Keep; + public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView { private final Godot godot; private final GodotInputHandler mInputHandler; private final GestureDetector mGestureDetector; private final VkRenderer mRenderer; + private PointerIcon pointerIcon; public GodotVulkanRenderView(Context context, Godot godot) { super(context); @@ -56,7 +61,9 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV mInputHandler = new GodotInputHandler(this); mGestureDetector = new GestureDetector(context, new GodotGestureHandler(this)); mRenderer = new VkRenderer(); - + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + pointerIcon = PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT); + } setFocusableInTouchMode(true); startRenderer(mRenderer); } @@ -124,6 +131,21 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV return mInputHandler.onGenericMotionEvent(event); } + /** + * called from JNI to change pointer icon + */ + @Keep + public void setPointerIcon(int pointerType) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType); + } + } + + @Override + public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) { + return pointerIcon; + } + @Override public void onResume() { super.onResume(); diff --git a/platform/android/java_godot_view_wrapper.cpp b/platform/android/java_godot_view_wrapper.cpp index 6b5e44f371..837d2aeced 100644 --- a/platform/android/java_godot_view_wrapper.cpp +++ b/platform/android/java_godot_view_wrapper.cpp @@ -43,6 +43,7 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) { if (android_get_device_api_level() >= __ANDROID_API_O__) { _request_pointer_capture = env->GetMethodID(_cls, "requestPointerCapture", "()V"); _release_pointer_capture = env->GetMethodID(_cls, "releasePointerCapture", "()V"); + _set_pointer_icon = env->GetMethodID(_cls, "setPointerIcon", "(I)V"); } } @@ -64,6 +65,15 @@ void GodotJavaViewWrapper::release_pointer_capture() { } } +void GodotJavaViewWrapper::set_pointer_icon(int pointer_type) { + if (_set_pointer_icon != 0) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + + env->CallVoidMethod(_godot_view, _set_pointer_icon, pointer_type); + } +} + GodotJavaViewWrapper::~GodotJavaViewWrapper() { JNIEnv *env = get_jni_env(); ERR_FAIL_COND(env == nullptr); diff --git a/platform/android/java_godot_view_wrapper.h b/platform/android/java_godot_view_wrapper.h index bfb4369fb8..da547d8118 100644 --- a/platform/android/java_godot_view_wrapper.h +++ b/platform/android/java_godot_view_wrapper.h @@ -45,12 +45,14 @@ private: jmethodID _request_pointer_capture = 0; jmethodID _release_pointer_capture = 0; + jmethodID _set_pointer_icon = 0; public: GodotJavaViewWrapper(jobject godot_view); void request_pointer_capture(); void release_pointer_capture(); + void set_pointer_icon(int pointer_type); ~GodotJavaViewWrapper(); }; diff --git a/platform/iphone/godot_app_delegate.m b/platform/iphone/godot_app_delegate.m index 3ce9bffc79..6c433c5c3c 100644 --- a/platform/iphone/godot_app_delegate.m +++ b/platform/iphone/godot_app_delegate.m @@ -56,7 +56,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil; [services addObject:service]; } -// UIApplicationDelegate documantation can be found here: https://developer.apple.com/documentation/uikit/uiapplicationdelegate +// UIApplicationDelegate documentation can be found here: https://developer.apple.com/documentation/uikit/uiapplicationdelegate // MARK: Window diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index a760e36982..d68ab7f7c9 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -6,7 +6,7 @@ javascript_files = [ "audio_driver_javascript.cpp", "display_server_javascript.cpp", "http_client_javascript.cpp", - "javascript_eval.cpp", + "javascript_singleton.cpp", "javascript_main.cpp", "os_javascript.cpp", "api/javascript_tools_editor_plugin.cpp", @@ -26,7 +26,7 @@ sys_env.AddJSLibraries( if env["tools"]: sys_env.AddJSLibraries(["js/libs/library_godot_editor_tools.js"]) if env["javascript_eval"]: - sys_env.AddJSLibraries(["js/libs/library_godot_eval.js"]) + sys_env.AddJSLibraries(["js/libs/library_godot_javascript_singleton.js"]) for lib in sys_env["JS_LIBS"]: sys_env.Append(LINKFLAGS=["--js-library", lib]) @@ -47,6 +47,7 @@ if env["gdnative_enabled"]: sys_env.Append(LINKFLAGS=["-s", "MAIN_MODULE=1"]) sys_env.Append(CCFLAGS=["-s", "EXPORT_ALL=1"]) sys_env.Append(LINKFLAGS=["-s", "EXPORT_ALL=1"]) + sys_env.Append(LINKFLAGS=["-s", "WARN_ON_UNDEFINED_SYMBOLS=0"]) # Force exporting the standard library (printf, malloc, etc.) sys_env["ENV"]["EMCC_FORCE_STDLIBS"] = "libc,libc++,libc++abi" # The main emscripten runtime, with exported standard libraries. diff --git a/platform/javascript/api/api.cpp b/platform/javascript/api/api.cpp index 2f7bde065f..039ce815e4 100644 --- a/platform/javascript/api/api.cpp +++ b/platform/javascript/api/api.cpp @@ -30,13 +30,14 @@ #include "api.h" #include "core/config/engine.h" -#include "javascript_eval.h" +#include "javascript_singleton.h" #include "javascript_tools_editor_plugin.h" static JavaScript *javascript_eval; void register_javascript_api() { JavaScriptToolsEditorPlugin::initialize(); + ClassDB::register_virtual_class<JavaScriptObject>(); ClassDB::register_virtual_class<JavaScript>(); javascript_eval = memnew(JavaScript); Engine::get_singleton()->add_singleton(Engine::Singleton("JavaScript", javascript_eval)); @@ -61,10 +62,41 @@ JavaScript::~JavaScript() {} void JavaScript::_bind_methods() { ClassDB::bind_method(D_METHOD("eval", "code", "use_global_execution_context"), &JavaScript::eval, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_interface", "interface"), &JavaScript::get_interface); + ClassDB::bind_method(D_METHOD("create_callback", "callable"), &JavaScript::create_callback); + { + MethodInfo mi; + mi.name = "create_object"; + mi.arguments.push_back(PropertyInfo(Variant::STRING, "object")); + ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "create_object", &JavaScript::_create_object_bind, mi); + } } #if !defined(JAVASCRIPT_ENABLED) || !defined(JAVASCRIPT_EVAL_ENABLED) Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) { return Variant(); } + +Ref<JavaScriptObject> JavaScript::get_interface(const String &p_interface) { + return Ref<JavaScriptObject>(); +} + +Ref<JavaScriptObject> JavaScript::create_callback(const Callable &p_callable) { + return Ref<JavaScriptObject>(); +} + +Variant JavaScript::_create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + if (p_argcount < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 0; + return Ref<JavaScriptObject>(); + } + if (p_args[0]->get_type() != Variant::STRING) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::STRING; + return Ref<JavaScriptObject>(); + } + return Ref<JavaScriptObject>(); +} #endif diff --git a/platform/javascript/api/javascript_eval.h b/platform/javascript/api/javascript_singleton.h index 24f7648ed9..45e9950acb 100644 --- a/platform/javascript/api/javascript_eval.h +++ b/platform/javascript/api/javascript_singleton.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* javascript_eval.h */ +/* javascript_singleton.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,10 +28,21 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef JAVASCRIPT_EVAL_H -#define JAVASCRIPT_EVAL_H +#ifndef JAVASCRIPT_SINGLETON_H +#define JAVASCRIPT_SINGLETON_H #include "core/object/class_db.h" +#include "core/object/reference.h" + +class JavaScriptObject : public Reference { +private: + GDCLASS(JavaScriptObject, Reference); + +protected: + virtual bool _set(const StringName &p_name, const Variant &p_value) { return false; } + virtual bool _get(const StringName &p_name, Variant &r_ret) const { return false; } + virtual void _get_property_list(List<PropertyInfo> *p_list) const {} +}; class JavaScript : public Object { private: @@ -44,10 +55,13 @@ protected: public: Variant eval(const String &p_code, bool p_use_global_exec_context = false); + Ref<JavaScriptObject> get_interface(const String &p_interface); + Ref<JavaScriptObject> create_callback(const Callable &p_callable); + Variant _create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); static JavaScript *get_singleton(); JavaScript(); ~JavaScript(); }; -#endif // JAVASCRIPT_EVAL_H +#endif // JAVASCRIPT_SINGLETON_H diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp index 7a2c2b2335..015440f5be 100644 --- a/platform/javascript/api/javascript_tools_editor_plugin.cpp +++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp @@ -79,7 +79,7 @@ void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, z return; } Vector<uint8_t> data; - int len = f->get_len(); + uint64_t len = f->get_len(); data.resize(len); f->get_buffer(data.ptrw(), len); f->close(); diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index 736a8a9a34..dae0b5f7e7 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -120,10 +120,10 @@ void DisplayServerJavaScript::request_quit_callback() { template <typename T> void DisplayServerJavaScript::dom2godot_mod(T *emscripten_event_ptr, Ref<InputEventWithModifiers> godot_event) { - godot_event->set_shift(emscripten_event_ptr->shiftKey); - godot_event->set_alt(emscripten_event_ptr->altKey); - godot_event->set_control(emscripten_event_ptr->ctrlKey); - godot_event->set_metakey(emscripten_event_ptr->metaKey); + godot_event->set_shift_pressed(emscripten_event_ptr->shiftKey); + godot_event->set_alt_pressed(emscripten_event_ptr->altKey); + godot_event->set_ctrl_pressed(emscripten_event_ptr->ctrlKey); + godot_event->set_meta_pressed(emscripten_event_ptr->metaKey); } Ref<InputEventKey> DisplayServerJavaScript::setup_key_event(const EmscriptenKeyboardEvent *emscripten_event) { @@ -455,10 +455,10 @@ EM_BOOL DisplayServerJavaScript::wheel_callback(int p_event_type, const Emscript ev->set_position(input->get_mouse_position()); ev->set_global_position(ev->get_position()); - ev->set_shift(input->is_key_pressed(KEY_SHIFT)); - ev->set_alt(input->is_key_pressed(KEY_ALT)); - ev->set_control(input->is_key_pressed(KEY_CONTROL)); - ev->set_metakey(input->is_key_pressed(KEY_META)); + ev->set_shift_pressed(input->is_key_pressed(KEY_SHIFT)); + ev->set_alt_pressed(input->is_key_pressed(KEY_ALT)); + ev->set_ctrl_pressed(input->is_key_pressed(KEY_CTRL)); + ev->set_meta_pressed(input->is_key_pressed(KEY_META)); if (p_event->deltaY < 0) ev->set_button_index(MOUSE_BUTTON_WHEEL_UP); @@ -536,7 +536,7 @@ bool DisplayServerJavaScript::screen_is_touchscreen(int p_screen) const { return godot_js_display_touchscreen_is_available(); } -// Virtual Keybaord +// Virtual Keyboard void DisplayServerJavaScript::vk_input_text_callback(const char *p_text, int p_cursor) { DisplayServerJavaScript *ds = DisplayServerJavaScript::get_singleton(); if (!ds || ds->input_text_callback.is_null()) { diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 951d86d09e..e398072312 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -170,8 +170,8 @@ public: while (true) { uint8_t bytes[4096]; - int read = f->get_buffer(bytes, 4096); - if (read < 1) { + uint64_t read = f->get_buffer(bytes, 4096); + if (read == 0) { break; } err = peer->put_data(bytes, read); diff --git a/platform/javascript/javascript_eval.cpp b/platform/javascript/javascript_eval.cpp deleted file mode 100644 index cb19dd20d4..0000000000 --- a/platform/javascript/javascript_eval.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************/ -/* javascript_eval.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef JAVASCRIPT_EVAL_ENABLED - -#include "api/javascript_eval.h" -#include "emscripten.h" - -extern "C" { -union js_eval_ret { - uint32_t b; - double d; - char *s; -}; - -extern int godot_js_eval(const char *p_js, int p_use_global_ctx, union js_eval_ret *p_union_ptr, void *p_byte_arr, void *p_byte_arr_write, void *(*p_callback)(void *p_ptr, void *p_ptr2, int p_len)); -} - -void *resize_PackedByteArray_and_open_write(void *p_arr, void *r_write, int p_len) { - PackedByteArray *arr = (PackedByteArray *)p_arr; - VectorWriteProxy<uint8_t> *write = (VectorWriteProxy<uint8_t> *)r_write; - arr->resize(p_len); - *write = arr->write; - return arr->ptrw(); -} - -Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) { - union js_eval_ret js_data; - PackedByteArray arr; - VectorWriteProxy<uint8_t> arr_write; - - Variant::Type return_type = static_cast<Variant::Type>(godot_js_eval(p_code.utf8().get_data(), p_use_global_exec_context, &js_data, &arr, &arr_write, resize_PackedByteArray_and_open_write)); - - switch (return_type) { - case Variant::BOOL: - return js_data.b; - case Variant::FLOAT: - return js_data.d; - case Variant::STRING: { - String str = String::utf8(js_data.s); - free(js_data.s); // Must free the string allocated in JS. - return str; - } - case Variant::PACKED_BYTE_ARRAY: - arr_write = VectorWriteProxy<uint8_t>(); - return arr; - default: - return Variant(); - } -} - -#endif // JAVASCRIPT_EVAL_ENABLED diff --git a/platform/javascript/javascript_singleton.cpp b/platform/javascript/javascript_singleton.cpp new file mode 100644 index 0000000000..67908a18da --- /dev/null +++ b/platform/javascript/javascript_singleton.cpp @@ -0,0 +1,338 @@ +/*************************************************************************/ +/* javascript_singleton.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef JAVASCRIPT_EVAL_ENABLED + +#include "api/javascript_singleton.h" +#include "emscripten.h" + +extern "C" { +typedef union { + int64_t i; + double r; + void *p; +} godot_js_wrapper_ex; + +typedef int (*GodotJSWrapperVariant2JSCallback)(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock); +typedef void (*GodotJSWrapperFreeLockCallback)(void **p_lock, int p_type); +extern int godot_js_wrapper_interface_get(const char *p_name); +extern int godot_js_wrapper_object_call(int p_id, const char *p_method, void **p_args, int p_argc, GodotJSWrapperVariant2JSCallback p_variant2js_callback, godot_js_wrapper_ex *p_cb_rval, void **p_lock, GodotJSWrapperFreeLockCallback p_lock_callback); +extern int godot_js_wrapper_object_get(int p_id, godot_js_wrapper_ex *p_val, const char *p_prop); +extern int godot_js_wrapper_object_getvar(int p_id, int p_type, godot_js_wrapper_ex *p_val); +extern int godot_js_wrapper_object_setvar(int p_id, int p_key_type, godot_js_wrapper_ex *p_key_ex, int p_val_type, godot_js_wrapper_ex *p_val_ex); +extern void godot_js_wrapper_object_set(int p_id, const char *p_name, int p_type, godot_js_wrapper_ex *p_val); +extern void godot_js_wrapper_object_unref(int p_id); +extern int godot_js_wrapper_create_cb(void *p_ref, void (*p_callback)(void *p_ref, int p_arg_id, int p_argc)); +extern int godot_js_wrapper_create_object(const char *p_method, void **p_args, int p_argc, GodotJSWrapperVariant2JSCallback p_variant2js_callback, godot_js_wrapper_ex *p_cb_rval, void **p_lock, GodotJSWrapperFreeLockCallback p_lock_callback); +}; + +class JavaScriptObjectImpl : public JavaScriptObject { +private: + friend class JavaScript; + + int _js_id = 0; + Callable _callable; + + static int _variant2js(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock); + static void _free_lock(void **p_lock, int p_type); + static Variant _js2variant(int p_type, godot_js_wrapper_ex *p_val); + static void *_alloc_variants(int p_size); + static void _callback(void *p_ref, int p_arg_id, int p_argc); + +protected: + bool _set(const StringName &p_name, const Variant &p_value) override; + bool _get(const StringName &p_name, Variant &r_ret) const override; + void _get_property_list(List<PropertyInfo> *p_list) const override; + +public: + Variant getvar(const Variant &p_key, bool *r_valid = nullptr) const override; + void setvar(const Variant &p_key, const Variant &p_value, bool *r_valid = nullptr) override; + Variant call(const StringName &p_method, const Variant **p_args, int p_argc, Callable::CallError &r_error) override; + JavaScriptObjectImpl() {} + JavaScriptObjectImpl(int p_id) { _js_id = p_id; } + ~JavaScriptObjectImpl() { + if (_js_id) { + godot_js_wrapper_object_unref(_js_id); + } + } +}; + +bool JavaScriptObjectImpl::_set(const StringName &p_name, const Variant &p_value) { + ERR_FAIL_COND_V_MSG(!_js_id, false, "Invalid JS instance"); + const String name = p_name; + godot_js_wrapper_ex exchange; + void *lock = nullptr; + const Variant *v = &p_value; + int type = _variant2js((const void **)&v, 0, &exchange, &lock); + godot_js_wrapper_object_set(_js_id, name.utf8().get_data(), type, &exchange); + if (lock) { + _free_lock(&lock, type); + } + return true; +} + +bool JavaScriptObjectImpl::_get(const StringName &p_name, Variant &r_ret) const { + ERR_FAIL_COND_V_MSG(!_js_id, false, "Invalid JS instance"); + const String name = p_name; + godot_js_wrapper_ex exchange; + int type = godot_js_wrapper_object_get(_js_id, &exchange, name.utf8().get_data()); + r_ret = _js2variant(type, &exchange); + return true; +} + +Variant JavaScriptObjectImpl::getvar(const Variant &p_key, bool *r_valid) const { + if (r_valid) { + *r_valid = false; + } + godot_js_wrapper_ex exchange; + void *lock = nullptr; + const Variant *v = &p_key; + int prop_type = _variant2js((const void **)&v, 0, &exchange, &lock); + int type = godot_js_wrapper_object_getvar(_js_id, prop_type, &exchange); + if (lock) { + _free_lock(&lock, prop_type); + } + if (type < 0) { + return Variant(); + } + if (r_valid) { + *r_valid = true; + } + return _js2variant(type, &exchange); +} + +void JavaScriptObjectImpl::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid) { + if (r_valid) { + *r_valid = false; + } + godot_js_wrapper_ex kex, vex; + void *klock = nullptr; + void *vlock = nullptr; + const Variant *kv = &p_key; + const Variant *vv = &p_value; + int ktype = _variant2js((const void **)&kv, 0, &kex, &klock); + int vtype = _variant2js((const void **)&vv, 0, &vex, &vlock); + int ret = godot_js_wrapper_object_setvar(_js_id, ktype, &kex, vtype, &vex); + if (klock) { + _free_lock(&klock, ktype); + } + if (vlock) { + _free_lock(&vlock, vtype); + } + if (ret == 0 && r_valid) { + *r_valid = true; + } +} + +void JavaScriptObjectImpl::_get_property_list(List<PropertyInfo> *p_list) const { +} + +void JavaScriptObjectImpl::_free_lock(void **p_lock, int p_type) { + ERR_FAIL_COND_MSG(*p_lock == nullptr, "No lock to free!"); + const Variant::Type type = (Variant::Type)p_type; + switch (type) { + case Variant::STRING: { + CharString *cs = (CharString *)(*p_lock); + memdelete(cs); + *p_lock = nullptr; + } break; + default: + ERR_FAIL_MSG("Unknown lock type to free. Likely a bug."); + } +} + +Variant JavaScriptObjectImpl::_js2variant(int p_type, godot_js_wrapper_ex *p_val) { + Variant::Type type = (Variant::Type)p_type; + switch (type) { + case Variant::BOOL: + return Variant((bool)p_val->i); + case Variant::INT: + return p_val->i; + case Variant::FLOAT: + return p_val->r; + case Variant::STRING: { + String out((const char *)p_val->p); + free(p_val->p); + return out; + } + case Variant::OBJECT: { + return memnew(JavaScriptObjectImpl(p_val->i)); + } + default: + return Variant(); + } +} + +int JavaScriptObjectImpl::_variant2js(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock) { + const Variant **args = (const Variant **)p_args; + const Variant *v = args[p_pos]; + Variant::Type type = v->get_type(); + switch (type) { + case Variant::BOOL: + r_val->i = v->operator bool() ? 1 : 0; + break; + case Variant::INT: { + const int64_t tmp = v->operator int64_t(); + if (tmp >= 1 << 31) { + r_val->r = (double)tmp; + return Variant::FLOAT; + } + r_val->i = v->operator int64_t(); + } break; + case Variant::FLOAT: + r_val->r = v->operator real_t(); + break; + case Variant::STRING: { + CharString *cs = memnew(CharString(v->operator String().utf8())); + r_val->p = (void *)cs->get_data(); + *p_lock = (void *)cs; + } break; + case Variant::OBJECT: { + JavaScriptObject *js_obj = Object::cast_to<JavaScriptObject>(v->operator Object *()); + r_val->i = js_obj != nullptr ? ((JavaScriptObjectImpl *)js_obj)->_js_id : 0; + } break; + default: + break; + } + return type; +} + +Variant JavaScriptObjectImpl::call(const StringName &p_method, const Variant **p_args, int p_argc, Callable::CallError &r_error) { + godot_js_wrapper_ex exchange; + const String method = p_method; + void *lock = nullptr; + const int type = godot_js_wrapper_object_call(_js_id, method.utf8().get_data(), (void **)p_args, p_argc, &_variant2js, &exchange, &lock, &_free_lock); + r_error.error = Callable::CallError::CALL_OK; + if (type < 0) { + r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; + return Variant(); + } + return _js2variant(type, &exchange); +} + +void JavaScriptObjectImpl::_callback(void *p_ref, int p_args_id, int p_argc) { + const JavaScriptObjectImpl *obj = (JavaScriptObjectImpl *)p_ref; + ERR_FAIL_COND_MSG(obj->_callable.is_null(), "JavaScript callback failed."); + Vector<const Variant *> argp; + Array arg_arr; + for (int i = 0; i < p_argc; i++) { + godot_js_wrapper_ex exchange; + exchange.i = i; + int type = godot_js_wrapper_object_getvar(p_args_id, Variant::INT, &exchange); + arg_arr.push_back(_js2variant(type, &exchange)); + } + Variant arg = arg_arr; + const Variant *argv[1] = { &arg }; + Callable::CallError err; + Variant ret; + obj->_callable.call(argv, 1, ret, err); +} + +Ref<JavaScriptObject> JavaScript::create_callback(const Callable &p_callable) { + Ref<JavaScriptObjectImpl> out = memnew(JavaScriptObjectImpl); + out->_callable = p_callable; + out->_js_id = godot_js_wrapper_create_cb(out.ptr(), JavaScriptObjectImpl::_callback); + return out; +} + +Ref<JavaScriptObject> JavaScript::get_interface(const String &p_interface) { + int js_id = godot_js_wrapper_interface_get(p_interface.utf8().get_data()); + ERR_FAIL_COND_V_MSG(!js_id, Ref<JavaScriptObject>(), "No interface '" + p_interface + "' registered."); + return Ref<JavaScriptObject>(memnew(JavaScriptObjectImpl(js_id))); +} + +Variant JavaScript::_create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + if (p_argcount < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 0; + return Ref<JavaScriptObject>(); + } + if (p_args[0]->get_type() != Variant::STRING) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::STRING; + return Ref<JavaScriptObject>(); + } + godot_js_wrapper_ex exchange; + const String object = *p_args[0]; + void *lock = nullptr; + const Variant **args = p_argcount > 1 ? &p_args[1] : nullptr; + const int type = godot_js_wrapper_create_object(object.utf8().get_data(), (void **)args, p_argcount - 1, &JavaScriptObjectImpl::_variant2js, &exchange, &lock, &JavaScriptObjectImpl::_free_lock); + r_error.error = Callable::CallError::CALL_OK; + if (type < 0) { + r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; + return Ref<JavaScriptObject>(); + } + return JavaScriptObjectImpl::_js2variant(type, &exchange); +} + +extern "C" { +union js_eval_ret { + uint32_t b; + double d; + char *s; +}; + +extern int godot_js_eval(const char *p_js, int p_use_global_ctx, union js_eval_ret *p_union_ptr, void *p_byte_arr, void *p_byte_arr_write, void *(*p_callback)(void *p_ptr, void *p_ptr2, int p_len)); +} + +void *resize_PackedByteArray_and_open_write(void *p_arr, void *r_write, int p_len) { + PackedByteArray *arr = (PackedByteArray *)p_arr; + VectorWriteProxy<uint8_t> *write = (VectorWriteProxy<uint8_t> *)r_write; + arr->resize(p_len); + *write = arr->write; + return arr->ptrw(); +} + +Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) { + union js_eval_ret js_data; + PackedByteArray arr; + VectorWriteProxy<uint8_t> arr_write; + + Variant::Type return_type = static_cast<Variant::Type>(godot_js_eval(p_code.utf8().get_data(), p_use_global_exec_context, &js_data, &arr, &arr_write, resize_PackedByteArray_and_open_write)); + + switch (return_type) { + case Variant::BOOL: + return js_data.b; + case Variant::FLOAT: + return js_data.d; + case Variant::STRING: { + String str = String::utf8(js_data.s); + free(js_data.s); // Must free the string allocated in JS. + return str; + } + case Variant::PACKED_BYTE_ARRAY: + arr_write = VectorWriteProxy<uint8_t>(); + return arr; + default: + return Variant(); + } +} +#endif // JAVASCRIPT_EVAL_ENABLED diff --git a/platform/javascript/js/libs/library_godot_audio.js b/platform/javascript/js/libs/library_godot_audio.js index ac4055516c..45c3a3fe2e 100644 --- a/platform/javascript/js/libs/library_godot_audio.js +++ b/platform/javascript/js/libs/library_godot_audio.js @@ -59,7 +59,7 @@ const GodotAudio = { } onstatechange(state); }; - ctx.onstatechange(); // Immeditately notify state. + ctx.onstatechange(); // Immediately notify state. // Update computed latency GodotAudio.interval = setInterval(function () { let computed_latency = 0; diff --git a/platform/javascript/js/libs/library_godot_eval.js b/platform/javascript/js/libs/library_godot_eval.js deleted file mode 100644 index 9ab392b813..0000000000 --- a/platform/javascript/js/libs/library_godot_eval.js +++ /dev/null @@ -1,86 +0,0 @@ -/*************************************************************************/ -/* library_godot_eval.js */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -const GodotEval = { - godot_js_eval__deps: ['$GodotRuntime'], - godot_js_eval__sig: 'iiiiiii', - godot_js_eval: function (p_js, p_use_global_ctx, p_union_ptr, p_byte_arr, p_byte_arr_write, p_callback) { - const js_code = GodotRuntime.parseString(p_js); - let eval_ret = null; - try { - if (p_use_global_ctx) { - // indirect eval call grants global execution context - const global_eval = eval; // eslint-disable-line no-eval - eval_ret = global_eval(js_code); - } else { - eval_ret = eval(js_code); // eslint-disable-line no-eval - } - } catch (e) { - GodotRuntime.error(e); - } - - switch (typeof eval_ret) { - case 'boolean': - GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'i32'); - return 1; // BOOL - - case 'number': - GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'double'); - return 3; // REAL - - case 'string': - GodotRuntime.setHeapValue(p_union_ptr, GodotRuntime.allocString(eval_ret), '*'); - return 4; // STRING - - case 'object': - if (eval_ret === null) { - break; - } - - if (ArrayBuffer.isView(eval_ret) && !(eval_ret instanceof Uint8Array)) { - eval_ret = new Uint8Array(eval_ret.buffer); - } else if (eval_ret instanceof ArrayBuffer) { - eval_ret = new Uint8Array(eval_ret); - } - if (eval_ret instanceof Uint8Array) { - const func = GodotRuntime.get_func(p_callback); - const bytes_ptr = func(p_byte_arr, p_byte_arr_write, eval_ret.length); - HEAPU8.set(eval_ret, bytes_ptr); - return 20; // POOL_BYTE_ARRAY - } - break; - - // no default - } - return 0; // NIL - }, -}; - -mergeInto(LibraryManager.library, GodotEval); diff --git a/platform/javascript/js/libs/library_godot_javascript_singleton.js b/platform/javascript/js/libs/library_godot_javascript_singleton.js new file mode 100644 index 0000000000..09ef4a1a5d --- /dev/null +++ b/platform/javascript/js/libs/library_godot_javascript_singleton.js @@ -0,0 +1,333 @@ +/*************************************************************************/ +/* library_godot_eval.js */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +const GodotJSWrapper = { + + $GodotJSWrapper__deps: ['$GodotRuntime', '$IDHandler'], + $GodotJSWrapper__postset: 'GodotJSWrapper.proxies = new Map();', + $GodotJSWrapper: { + proxies: null, + + MyProxy: function (val) { + const id = IDHandler.add(this); + GodotJSWrapper.proxies.set(val, id); + let refs = 1; + this.ref = function () { + refs++; + }; + this.unref = function () { + refs--; + if (refs === 0) { + IDHandler.remove(id); + GodotJSWrapper.proxies.delete(val); + } + }; + this.get_val = function () { + return val; + }; + this.get_id = function () { + return id; + }; + }, + + get_proxied: function (val) { + const id = GodotJSWrapper.proxies.get(val); + if (id === undefined) { + const proxy = new GodotJSWrapper.MyProxy(val); + return proxy.get_id(); + } + IDHandler.get(id).ref(); + return id; + }, + + get_proxied_value: function (id) { + const proxy = IDHandler.get(id); + if (proxy === undefined) { + return undefined; + } + return proxy.get_val(); + }, + + variant2js: function (type, val) { + switch (type) { + case 0: + return null; + case 1: + return !!GodotRuntime.getHeapValue(val, 'i64'); + case 2: + return GodotRuntime.getHeapValue(val, 'i64'); + case 3: + return GodotRuntime.getHeapValue(val, 'double'); + case 4: + return GodotRuntime.parseString(GodotRuntime.getHeapValue(val, '*')); + case 21: // OBJECT + return GodotJSWrapper.get_proxied_value(GodotRuntime.getHeapValue(val, 'i64')); + default: + return undefined; + } + }, + + js2variant: function (p_val, p_exchange) { + if (p_val === undefined || p_val === null) { + return 0; // NIL + } + const type = typeof (p_val); + if (type === 'boolean') { + GodotRuntime.setHeapValue(p_exchange, p_val, 'i64'); + return 1; // BOOL + } else if (type === 'number') { + if (Number.isInteger(p_val)) { + GodotRuntime.setHeapValue(p_exchange, p_val, 'i64'); + return 2; // INT + } + GodotRuntime.setHeapValue(p_exchange, p_val, 'double'); + return 3; // REAL + } else if (type === 'string') { + const c_str = GodotRuntime.allocString(p_val); + GodotRuntime.setHeapValue(p_exchange, c_str, '*'); + return 4; // STRING + } + const id = GodotJSWrapper.get_proxied(p_val); + GodotRuntime.setHeapValue(p_exchange, id, 'i64'); + return 21; + }, + }, + + godot_js_wrapper_interface_get__sig: 'ii', + godot_js_wrapper_interface_get: function (p_name) { + const name = GodotRuntime.parseString(p_name); + if (typeof (window[name]) !== 'undefined') { + return GodotJSWrapper.get_proxied(window[name]); + } + return 0; + }, + + godot_js_wrapper_object_get__sig: 'iiii', + godot_js_wrapper_object_get: function (p_id, p_exchange, p_prop) { + const obj = GodotJSWrapper.get_proxied_value(p_id); + if (obj === undefined) { + return 0; + } + if (p_prop) { + const prop = GodotRuntime.parseString(p_prop); + try { + return GodotJSWrapper.js2variant(obj[prop], p_exchange); + } catch (e) { + GodotRuntime.error(`Error getting variable ${prop} on object`, obj); + return 0; // NIL + } + } + return GodotJSWrapper.js2variant(obj, p_exchange); + }, + + godot_js_wrapper_object_set__sig: 'viiii', + godot_js_wrapper_object_set: function (p_id, p_name, p_type, p_exchange) { + const obj = GodotJSWrapper.get_proxied_value(p_id); + if (obj === undefined) { + return; + } + const name = GodotRuntime.parseString(p_name); + try { + obj[name] = GodotJSWrapper.variant2js(p_type, p_exchange); + } catch (e) { + GodotRuntime.error(`Error setting variable ${name} on object`, obj); + } + }, + + godot_js_wrapper_object_call__sig: 'iiiiiiiii', + godot_js_wrapper_object_call: function (p_id, p_method, p_args, p_argc, p_convert_callback, p_exchange, p_lock, p_free_lock_callback) { + const obj = GodotJSWrapper.get_proxied_value(p_id); + if (obj === undefined) { + return -1; + } + const method = GodotRuntime.parseString(p_method); + const convert = GodotRuntime.get_func(p_convert_callback); + const freeLock = GodotRuntime.get_func(p_free_lock_callback); + const args = new Array(p_argc); + for (let i = 0; i < p_argc; i++) { + const type = convert(p_args, i, p_exchange, p_lock); + const lock = GodotRuntime.getHeapValue(p_lock, '*'); + args[i] = GodotJSWrapper.variant2js(type, p_exchange); + if (lock) { + freeLock(p_lock, type); + } + } + try { + const res = obj[method](...args); + return GodotJSWrapper.js2variant(res, p_exchange); + } catch (e) { + GodotRuntime.error(`Error calling method ${method} on:`, obj, 'error:', e); + return -1; + } + }, + + godot_js_wrapper_object_unref__sig: 'vi', + godot_js_wrapper_object_unref: function (p_id) { + const proxy = IDHandler.get(p_id); + if (proxy !== undefined) { + proxy.unref(); + } + }, + + godot_js_wrapper_create_cb__sig: 'vii', + godot_js_wrapper_create_cb: function (p_ref, p_func) { + const func = GodotRuntime.get_func(p_func); + let id = 0; + const cb = function () { + if (!GodotJSWrapper.get_proxied_value(id)) { + return; + } + const args = Array.from(arguments); + func(p_ref, GodotJSWrapper.get_proxied(args), args.length); + }; + id = GodotJSWrapper.get_proxied(cb); + return id; + }, + + godot_js_wrapper_object_getvar__sig: 'iiii', + godot_js_wrapper_object_getvar: function (p_id, p_type, p_exchange) { + const obj = GodotJSWrapper.get_proxied_value(p_id); + if (obj === undefined) { + return -1; + } + const prop = GodotJSWrapper.variant2js(p_type, p_exchange); + if (prop === undefined || prop === null) { + return -1; + } + try { + return GodotJSWrapper.js2variant(obj[prop], p_exchange); + } catch (e) { + GodotRuntime.error(`Error getting variable ${prop} on object`, obj, e); + return -1; + } + }, + + godot_js_wrapper_object_setvar__sig: 'iiiiii', + godot_js_wrapper_object_setvar: function (p_id, p_key_type, p_key_ex, p_val_type, p_val_ex) { + const obj = GodotJSWrapper.get_proxied_value(p_id); + if (obj === undefined) { + return -1; + } + const key = GodotJSWrapper.variant2js(p_key_type, p_key_ex); + try { + obj[key] = GodotJSWrapper.variant2js(p_val_type, p_val_ex); + return 0; + } catch (e) { + GodotRuntime.error(`Error setting variable ${key} on object`, obj); + return -1; + } + }, + + godot_js_wrapper_create_object__sig: 'iiiiiiii', + godot_js_wrapper_create_object: function (p_object, p_args, p_argc, p_convert_callback, p_exchange, p_lock, p_free_lock_callback) { + const name = GodotRuntime.parseString(p_object); + if (typeof (window[name]) === 'undefined') { + return -1; + } + const convert = GodotRuntime.get_func(p_convert_callback); + const freeLock = GodotRuntime.get_func(p_free_lock_callback); + const args = new Array(p_argc); + for (let i = 0; i < p_argc; i++) { + const type = convert(p_args, i, p_exchange, p_lock); + const lock = GodotRuntime.getHeapValue(p_lock, '*'); + args[i] = GodotJSWrapper.variant2js(type, p_exchange); + if (lock) { + freeLock(p_lock, type); + } + } + try { + const res = new window[name](...args); + return GodotJSWrapper.js2variant(res, p_exchange); + } catch (e) { + GodotRuntime.error(`Error calling constructor ${name} with args:`, args, 'error:', e); + return -1; + } + }, +}; + +autoAddDeps(GodotJSWrapper, '$GodotJSWrapper'); +mergeInto(LibraryManager.library, GodotJSWrapper); + +const GodotEval = { + godot_js_eval__deps: ['$GodotRuntime'], + godot_js_eval__sig: 'iiiiiii', + godot_js_eval: function (p_js, p_use_global_ctx, p_union_ptr, p_byte_arr, p_byte_arr_write, p_callback) { + const js_code = GodotRuntime.parseString(p_js); + let eval_ret = null; + try { + if (p_use_global_ctx) { + // indirect eval call grants global execution context + const global_eval = eval; // eslint-disable-line no-eval + eval_ret = global_eval(js_code); + } else { + eval_ret = eval(js_code); // eslint-disable-line no-eval + } + } catch (e) { + GodotRuntime.error(e); + } + + switch (typeof eval_ret) { + case 'boolean': + GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'i32'); + return 1; // BOOL + + case 'number': + GodotRuntime.setHeapValue(p_union_ptr, eval_ret, 'double'); + return 3; // REAL + + case 'string': + GodotRuntime.setHeapValue(p_union_ptr, GodotRuntime.allocString(eval_ret), '*'); + return 4; // STRING + + case 'object': + if (eval_ret === null) { + break; + } + + if (ArrayBuffer.isView(eval_ret) && !(eval_ret instanceof Uint8Array)) { + eval_ret = new Uint8Array(eval_ret.buffer); + } else if (eval_ret instanceof ArrayBuffer) { + eval_ret = new Uint8Array(eval_ret); + } + if (eval_ret instanceof Uint8Array) { + const func = GodotRuntime.get_func(p_callback); + const bytes_ptr = func(p_byte_arr, p_byte_arr_write, eval_ret.length); + HEAPU8.set(eval_ret, bytes_ptr); + return 20; // POOL_BYTE_ARRAY + } + break; + + // no default + } + return 0; // NIL + }, +}; + +mergeInto(LibraryManager.library, GodotEval); diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 1876960c57..ee59537ee0 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -363,6 +363,7 @@ def configure(env): env.Prepend(CPPPATH=["#platform/linuxbsd"]) env.Append(CPPDEFINES=["X11_ENABLED", "UNIX_ENABLED"]) + env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)]) env.Append(CPPDEFINES=["VULKAN_ENABLED"]) if not env["builtin_vulkan"]: diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index be69b2e5da..b50b5f3479 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -2166,10 +2166,10 @@ static Atom pick_target_from_atoms(Display *p_disp, Atom p_t1, Atom p_t2, Atom p } void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state) { - state->set_shift((p_x11_state & ShiftMask)); - state->set_control((p_x11_state & ControlMask)); - state->set_alt((p_x11_state & Mod1Mask /*|| p_x11_state&Mod5Mask*/)); //altgr should not count as alt - state->set_metakey((p_x11_state & Mod4Mask)); + state->set_shift_pressed((p_x11_state & ShiftMask)); + state->set_ctrl_pressed((p_x11_state & ControlMask)); + state->set_alt_pressed((p_x11_state & Mod1Mask /*|| p_x11_state&Mod5Mask*/)); //altgr should not count as alt + state->set_meta_pressed((p_x11_state & Mod4Mask)); } unsigned int DisplayServerX11::_get_mouse_button_state(unsigned int p_x11_button, int p_x11_type) { @@ -2281,7 +2281,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, //make it consistent across platforms. k->set_keycode(KEY_TAB); k->set_physical_keycode(KEY_TAB); - k->set_shift(true); + k->set_shift_pressed(true); } Input::get_singleton()->accumulate_input_event(k); @@ -2409,20 +2409,20 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, //make it consistent across platforms. k->set_keycode(KEY_TAB); k->set_physical_keycode(KEY_TAB); - k->set_shift(true); + k->set_shift_pressed(true); } //don't set mod state if modifier keys are released by themselves //else event.is_action() will not work correctly here if (!k->is_pressed()) { if (k->get_keycode() == KEY_SHIFT) { - k->set_shift(false); - } else if (k->get_keycode() == KEY_CONTROL) { - k->set_control(false); + k->set_shift_pressed(false); + } else if (k->get_keycode() == KEY_CTRL) { + k->set_ctrl_pressed(false); } else if (k->get_keycode() == KEY_ALT) { - k->set_alt(false); + k->set_alt_pressed(false); } else if (k->get_keycode() == KEY_META) { - k->set_metakey(false); + k->set_meta_pressed(false); } } diff --git a/platform/linuxbsd/key_mapping_x11.cpp b/platform/linuxbsd/key_mapping_x11.cpp index f9f612fa74..74257a7e61 100644 --- a/platform/linuxbsd/key_mapping_x11.cpp +++ b/platform/linuxbsd/key_mapping_x11.cpp @@ -61,8 +61,8 @@ static _XTranslatePair _xkeysym_to_keycode[] = { { XK_Shift_L, KEY_SHIFT }, { XK_Shift_R, KEY_SHIFT }, { XK_Shift_Lock, KEY_SHIFT }, - { XK_Control_L, KEY_CONTROL }, - { XK_Control_R, KEY_CONTROL }, + { XK_Control_L, KEY_CTRL }, + { XK_Control_R, KEY_CTRL }, { XK_Meta_L, KEY_META }, { XK_Meta_R, KEY_META }, { XK_Alt_L, KEY_ALT }, @@ -213,7 +213,7 @@ static _TranslatePair _scancode_to_keycode[] = { { KEY_BRACELEFT, 0x22 }, { KEY_BRACERIGHT, 0x23 }, { KEY_ENTER, 0x24 }, - { KEY_CONTROL, 0x25 }, + { KEY_CTRL, 0x25 }, { KEY_A, 0x26 }, { KEY_S, 0x27 }, { KEY_D, 0x28 }, @@ -272,7 +272,7 @@ static _TranslatePair _scancode_to_keycode[] = { { KEY_F11, 0x5F }, { KEY_F12, 0x60 }, { KEY_KP_ENTER, 0x68 }, - { KEY_CONTROL, 0x69 }, + { KEY_CTRL, 0x69 }, { KEY_KP_DIVIDE, 0x6A }, { KEY_PRINT, 0x6B }, { KEY_ALT, 0x6C }, diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 09e1f9461c..e7d3c9552e 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -164,7 +164,12 @@ bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) { String OS_LinuxBSD::get_config_path() const { if (has_environment("XDG_CONFIG_HOME")) { - return get_environment("XDG_CONFIG_HOME"); + if (get_environment("XDG_CONFIG_HOME").is_abs_path()) { + return get_environment("XDG_CONFIG_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.config` or `.` per the XDG Base Directory specification."); + return has_environment("HOME") ? get_environment("HOME").plus_file(".config") : "."; + } } else if (has_environment("HOME")) { return get_environment("HOME").plus_file(".config"); } else { @@ -174,7 +179,12 @@ String OS_LinuxBSD::get_config_path() const { String OS_LinuxBSD::get_data_path() const { if (has_environment("XDG_DATA_HOME")) { - return get_environment("XDG_DATA_HOME"); + if (get_environment("XDG_DATA_HOME").is_abs_path()) { + return get_environment("XDG_DATA_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.local/share` or `get_config_path()` per the XDG Base Directory specification."); + return has_environment("HOME") ? get_environment("HOME").plus_file(".local/share") : get_config_path(); + } } else if (has_environment("HOME")) { return get_environment("HOME").plus_file(".local/share"); } else { @@ -184,7 +194,12 @@ String OS_LinuxBSD::get_data_path() const { String OS_LinuxBSD::get_cache_path() const { if (has_environment("XDG_CACHE_HOME")) { - return get_environment("XDG_CACHE_HOME"); + if (get_environment("XDG_CACHE_HOME").is_abs_path()) { + return get_environment("XDG_CACHE_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.cache` or `get_config_path()` per the XDG Base Directory specification."); + return has_environment("HOME") ? get_environment("HOME").plus_file(".cache") : get_config_path(); + } } else if (has_environment("HOME")) { return get_environment("HOME").plus_file(".cache"); } else { diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 473ae95036..a9e9aa889a 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -66,10 +66,10 @@ static bool ignore_momentum_scroll = false; static void _get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> r_state) { - r_state->set_shift((p_osx_state & NSEventModifierFlagShift)); - r_state->set_control((p_osx_state & NSEventModifierFlagControl)); - r_state->set_alt((p_osx_state & NSEventModifierFlagOption)); - r_state->set_metakey((p_osx_state & NSEventModifierFlagCommand)); + r_state->set_shift_pressed((p_osx_state & NSEventModifierFlagShift)); + r_state->set_ctrl_pressed((p_osx_state & NSEventModifierFlagControl)); + r_state->set_alt_pressed((p_osx_state & NSEventModifierFlagOption)); + r_state->set_meta_pressed((p_osx_state & NSEventModifierFlagCommand)); } static Vector2i _get_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPoint p_locationInWindow) { @@ -1133,10 +1133,10 @@ static int translateKey(unsigned int key) { /* 38 */ KEY_SHIFT, /* 39 */ KEY_CAPSLOCK, /* 3a */ KEY_ALT, - /* 3b */ KEY_CONTROL, + /* 3b */ KEY_CTRL, /* 3c */ KEY_SHIFT, /* 3d */ KEY_ALT, - /* 3e */ KEY_CONTROL, + /* 3e */ KEY_CTRL, /* 3f */ KEY_UNKNOWN, /* Function */ /* 40 */ KEY_UNKNOWN, /* F17 */ /* 41 */ KEY_KP_PERIOD, @@ -3467,7 +3467,7 @@ void DisplayServerOSX::set_native_icon(const String &p_filename) { ERR_FAIL_COND(!f); Vector<uint8_t> data; - uint32_t len = f->get_len(); + uint64_t len = f->get_len(); data.resize(len); f->get_buffer((uint8_t *)&data.write[0], len); memdelete(f); diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index 51204bc8f6..a7868efaa8 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -312,7 +312,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_ } int ofs = data.size(); - uint32_t len = f->get_len(); + uint64_t len = f->get_len(); data.resize(data.size() + len + 8); f->get_buffer(&data.write[ofs + 8], len); memdelete(f); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index e6feda5a9b..e199ea1b0d 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -188,8 +188,14 @@ MainLoop *OS_OSX::get_main_loop() const { } String OS_OSX::get_config_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. if (has_environment("XDG_CONFIG_HOME")) { - return get_environment("XDG_CONFIG_HOME"); + if (get_environment("XDG_CONFIG_HOME").is_abs_path()) { + return get_environment("XDG_CONFIG_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Library/Application Support` or `.` per the XDG Base Directory specification."); + return has_environment("HOME") ? get_environment("HOME").plus_file("Library/Application Support") : "."; + } } else if (has_environment("HOME")) { return get_environment("HOME").plus_file("Library/Application Support"); } else { @@ -198,16 +204,28 @@ String OS_OSX::get_config_path() const { } String OS_OSX::get_data_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. if (has_environment("XDG_DATA_HOME")) { - return get_environment("XDG_DATA_HOME"); + if (get_environment("XDG_DATA_HOME").is_abs_path()) { + return get_environment("XDG_DATA_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification."); + return get_config_path(); + } } else { return get_config_path(); } } String OS_OSX::get_cache_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. if (has_environment("XDG_CACHE_HOME")) { - return get_environment("XDG_CACHE_HOME"); + if (get_environment("XDG_CACHE_HOME").is_abs_path()) { + return get_environment("XDG_CACHE_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Libary/Caches` or `get_config_path()` per the XDG Base Directory specification."); + return has_environment("HOME") ? get_environment("HOME").plus_file("Library/Caches") : get_config_path(); + } } else if (has_environment("HOME")) { return get_environment("HOME").plus_file("Library/Caches"); } else { diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 2314a392cc..435f829c9b 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -565,9 +565,9 @@ void OS_UWP::process_key_events() { Ref<InputEventKey> key_event; key_event.instance(); - key_event->set_alt(kev.alt); - key_event->set_shift(kev.shift); - key_event->set_control(kev.control); + key_event->set_alt_pressed(kev.alt); + key_event->set_shift_pressed(kev.shift); + key_event->set_ctrl_pressed(kev.control); key_event->set_echo(kev.echo); key_event->set_keycode(kev.keycode); key_event->set_physical_keycode(kev.physical_keycode); diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 4b859da340..0dd02b4888 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -1966,9 +1966,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm.instance(); mm->set_window_id(window_id); - mm->set_control(control_mem); - mm->set_shift(shift_mem); - mm->set_alt(alt_mem); + mm->set_ctrl_pressed(control_mem); + mm->set_shift_pressed(shift_mem); + mm->set_alt_pressed(alt_mem); mm->set_pressure((raw->data.mouse.ulButtons & RI_MOUSE_LEFT_BUTTON_DOWN) ? 1.0f : 0.0f); @@ -2062,9 +2062,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA Ref<InputEventMouseMotion> mm; mm.instance(); mm->set_window_id(window_id); - mm->set_control(GetKeyState(VK_CONTROL) < 0); - mm->set_shift(GetKeyState(VK_SHIFT) < 0); - mm->set_alt(alt_mem); + mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0); + mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0); + mm->set_alt_pressed(alt_mem); mm->set_pressure(windows[window_id].last_pressure); mm->set_tilt(windows[window_id].last_tilt); @@ -2205,9 +2205,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_tilt(Vector2((float)pen_info.tiltX / 90, (float)pen_info.tiltY / 90)); } - mm->set_control(GetKeyState(VK_CONTROL) < 0); - mm->set_shift(GetKeyState(VK_SHIFT) < 0); - mm->set_alt(alt_mem); + mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0); + mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0); + mm->set_alt_pressed(alt_mem); mm->set_button_mask(last_button_state); @@ -2300,9 +2300,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA Ref<InputEventMouseMotion> mm; mm.instance(); mm->set_window_id(window_id); - mm->set_control((wParam & MK_CONTROL) != 0); - mm->set_shift((wParam & MK_SHIFT) != 0); - mm->set_alt(alt_mem); + mm->set_ctrl_pressed((wParam & MK_CONTROL) != 0); + mm->set_shift_pressed((wParam & MK_SHIFT) != 0); + mm->set_alt_pressed(alt_mem); if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) { // Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not updated recently. @@ -2477,10 +2477,10 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } } - mb->set_control((wParam & MK_CONTROL) != 0); - mb->set_shift((wParam & MK_SHIFT) != 0); - mb->set_alt(alt_mem); - //mb->get_alt()=(wParam&MK_MENU)!=0; + mb->set_ctrl_pressed((wParam & MK_CONTROL) != 0); + mb->set_shift_pressed((wParam & MK_SHIFT) != 0); + mb->set_alt_pressed(alt_mem); + //mb->is_alt_pressed()=(wParam&MK_MENU)!=0; if (mb->is_pressed()) last_button_state |= (1 << (mb->get_button_index() - 1)); else @@ -2835,17 +2835,17 @@ void DisplayServerWindows::_process_key_events() { k.instance(); k->set_window_id(ke.window_id); - k->set_shift(ke.shift); - k->set_alt(ke.alt); - k->set_control(ke.control); - k->set_metakey(ke.meta); + k->set_shift_pressed(ke.shift); + k->set_alt_pressed(ke.alt); + k->set_ctrl_pressed(ke.control); + k->set_meta_pressed(ke.meta); k->set_pressed(true); k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam)); k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))); k->set_unicode(unicode); if (k->get_unicode() && gr_mem) { - k->set_alt(false); - k->set_control(false); + k->set_alt_pressed(false); + k->set_ctrl_pressed(false); } if (k->get_unicode() < 32) @@ -2862,10 +2862,10 @@ void DisplayServerWindows::_process_key_events() { k.instance(); k->set_window_id(ke.window_id); - k->set_shift(ke.shift); - k->set_alt(ke.alt); - k->set_control(ke.control); - k->set_metakey(ke.meta); + k->set_shift_pressed(ke.shift); + k->set_alt_pressed(ke.alt); + k->set_ctrl_pressed(ke.control); + k->set_meta_pressed(ke.meta); k->set_pressed(ke.uMsg == WM_KEYDOWN); @@ -2900,8 +2900,8 @@ void DisplayServerWindows::_process_key_events() { k->set_unicode(unicode); } if (k->get_unicode() && gr_mem) { - k->set_alt(false); - k->set_control(false); + k->set_alt_pressed(false); + k->set_ctrl_pressed(false); } if (k->get_unicode() < 32) diff --git a/platform/windows/key_mapping_windows.cpp b/platform/windows/key_mapping_windows.cpp index 3312c91932..c367c69826 100644 --- a/platform/windows/key_mapping_windows.cpp +++ b/platform/windows/key_mapping_windows.cpp @@ -47,7 +47,7 @@ static _WinTranslatePair _vk_to_keycode[] = { { KEY_SHIFT, VK_SHIFT }, //(0x10) - { KEY_CONTROL, VK_CONTROL }, //(0x11) + { KEY_CTRL, VK_CONTROL }, //(0x11) { KEY_ALT, VK_MENU }, //(0x12) @@ -166,8 +166,8 @@ static _WinTranslatePair _vk_to_keycode[] = { { KEY_SCROLLLOCK, VK_SCROLL }, // (0x91) { KEY_SHIFT, VK_LSHIFT }, // (0xA0) { KEY_SHIFT, VK_RSHIFT }, // (0xA1) - { KEY_CONTROL, VK_LCONTROL }, // (0xA2) - { KEY_CONTROL, VK_RCONTROL }, // (0xA3) + { KEY_CTRL, VK_LCONTROL }, // (0xA2) + { KEY_CTRL, VK_RCONTROL }, // (0xA3) { KEY_MENU, VK_LMENU }, // (0xA4) { KEY_MENU, VK_RMENU }, // (0xA5) @@ -265,7 +265,7 @@ static _WinTranslatePair _scancode_to_keycode[] = { { KEY_BRACELEFT, 0x1A }, { KEY_BRACERIGHT, 0x1B }, { KEY_ENTER, 0x1C }, - { KEY_CONTROL, 0x1D }, + { KEY_CTRL, 0x1D }, { KEY_A, 0x1E }, { KEY_S, 0x1F }, { KEY_D, 0x20 }, diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index f517190a89..e0259882b0 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -631,8 +631,14 @@ MainLoop *OS_Windows::get_main_loop() const { } String OS_Windows::get_config_path() const { - if (has_environment("XDG_CONFIG_HOME")) { // unlikely, but after all why not? - return get_environment("XDG_CONFIG_HOME"); + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. + if (has_environment("XDG_CONFIG_HOME")) { + if (get_environment("XDG_CONFIG_HOME").is_abs_path()) { + return get_environment("XDG_CONFIG_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `%APPDATA%` or `.` per the XDG Base Directory specification."); + return has_environment("APPDATA") ? get_environment("APPDATA") : "."; + } } else if (has_environment("APPDATA")) { return get_environment("APPDATA"); } else { @@ -641,16 +647,28 @@ String OS_Windows::get_config_path() const { } String OS_Windows::get_data_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. if (has_environment("XDG_DATA_HOME")) { - return get_environment("XDG_DATA_HOME"); + if (get_environment("XDG_DATA_HOME").is_abs_path()) { + return get_environment("XDG_DATA_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification."); + return get_config_path(); + } } else { return get_config_path(); } } String OS_Windows::get_cache_path() const { + // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well. if (has_environment("XDG_CACHE_HOME")) { - return get_environment("XDG_CACHE_HOME"); + if (get_environment("XDG_CACHE_HOME").is_abs_path()) { + return get_environment("XDG_CACHE_HOME"); + } else { + WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `%TEMP%` or `get_config_path()` per the XDG Base Directory specification."); + return has_environment("TEMP") ? get_environment("TEMP") : get_config_path(); + } } else if (has_environment("TEMP")) { return get_environment("TEMP"); } else { diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 9dfdd7bd0e..597693aa6a 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -118,7 +118,7 @@ void Area2D::_body_enter_tree(ObjectID p_id) { E->get().in_tree = true; emit_signal(SceneStringNames::get_singleton()->body_entered, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); } } @@ -132,7 +132,7 @@ void Area2D::_body_exit_tree(ObjectID p_id) { E->get().in_tree = false; emit_signal(SceneStringNames::get_singleton()->body_exited, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); } } @@ -154,6 +154,7 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i if (body_in) { if (!E) { E = body_map.insert(objid, BodyState()); + E->get().rid = p_body; E->get().rc = 0; E->get().in_tree = node && node->is_inside_tree(); if (node) { @@ -170,7 +171,7 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i } if (!node || E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape); } } else { @@ -192,7 +193,7 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i } } if (!node || in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_area_shape); } } @@ -211,7 +212,7 @@ void Area2D::_area_enter_tree(ObjectID p_id) { E->get().in_tree = true; emit_signal(SceneStringNames::get_singleton()->area_entered, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); } } @@ -225,7 +226,7 @@ void Area2D::_area_exit_tree(ObjectID p_id) { E->get().in_tree = false; emit_signal(SceneStringNames::get_singleton()->area_exited, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); } } @@ -246,6 +247,7 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i if (area_in) { if (!E) { E = area_map.insert(objid, AreaState()); + E->get().rid = p_area; E->get().rc = 0; E->get().in_tree = node && node->is_inside_tree(); if (node) { @@ -262,7 +264,7 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i } if (!node || E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->area_shape_entered, objid, node, p_area_shape, p_self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, node, p_area_shape, p_self_shape); } } else { @@ -284,7 +286,7 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i } } if (!node || in_tree) { - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, objid, obj, p_area_shape, p_self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, obj, p_area_shape, p_self_shape); } } @@ -315,7 +317,7 @@ void Area2D::_clear_monitoring() { } for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->key(), node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); } emit_signal(SceneStringNames::get_singleton()->body_exited, obj); @@ -343,7 +345,7 @@ void Area2D::_clear_monitoring() { } for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->key(), node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); } emit_signal(SceneStringNames::get_singleton()->area_exited, obj); @@ -532,13 +534,13 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout); ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"))); ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"))); - ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"))); ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"))); @@ -551,7 +553,7 @@ void Area2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_vec"), "set_gravity_vector", "get_gravity_vector"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-1024,1024,0.001"), "set_gravity", "get_gravity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-4096,4096,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); @@ -568,7 +570,7 @@ void Area2D::_bind_methods() { Area2D::Area2D() : CollisionObject2D(PhysicsServer2D::get_singleton()->area_create(), true) { - set_gravity(98); + set_gravity(980); set_gravity_vector(Vector2(0, 1)); set_monitoring(true); set_monitorable(true); diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index d6fcb2c2a5..2c29e4660d 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -83,6 +83,7 @@ private: }; struct BodyState { + RID rid; int rc = 0; bool in_tree = false; VSet<ShapePair> shapes; @@ -114,6 +115,7 @@ private: }; struct AreaState { + RID rid; int rc = 0; bool in_tree = false; VSet<AreaShapePair> shapes; diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index ba34a0f45d..92b8be77cf 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -169,7 +169,7 @@ private: Vector<Color> emission_colors; int emission_point_count = 0; - Vector2 gravity = Vector2(0, 98); + Vector2 gravity = Vector2(0, 980); void _update_internal(); void _particles_process(float p_delta); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 3f2f6d6b1c..4f52f62e99 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -165,7 +165,7 @@ void RigidBody2D::_body_enter_tree(ObjectID p_id) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); } contact_monitor->locked = false; @@ -186,13 +186,13 @@ void RigidBody2D::_body_exit_tree(ObjectID p_id) { emit_signal(SceneStringNames::get_singleton()->body_exited, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); } contact_monitor->locked = false; } -void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape) { +void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { bool body_in = p_status == 1; ObjectID objid = p_instance; @@ -207,6 +207,7 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap if (body_in) { if (!E) { E = contact_monitor->body_map.insert(objid, BodyState()); + E->get().rid = p_body; //E->get().rc=0; E->get().in_scene = node && node->is_inside_tree(); if (node) { @@ -225,7 +226,7 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap } if (E->get().in_scene) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_local_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape); } } else { @@ -249,12 +250,13 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap contact_monitor->body_map.erase(E); } if (node && in_scene) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, node, p_body_shape, p_local_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, node, p_body_shape, p_local_shape); } } } struct _RigidBody2DInOut { + RID rid; ObjectID id; int shape = 0; int local_shape = 0; @@ -311,6 +313,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { //put the ones to add for (int i = 0; i < state->get_contact_count(); i++) { + RID rid = state->get_contact_collider(i); ObjectID obj = state->get_contact_collider_id(i); int local_shape = state->get_contact_local_shape(i); int shape = state->get_contact_collider_shape(i); @@ -319,6 +322,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(obj); if (!E) { + toadd[toadd_count].rid = rid; toadd[toadd_count].local_shape = local_shape; toadd[toadd_count].id = obj; toadd[toadd_count].shape = shape; @@ -329,6 +333,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { ShapePair sp(shape, local_shape); int idx = E->get().shapes.find(sp); if (idx == -1) { + toadd[toadd_count].rid = rid; toadd[toadd_count].local_shape = local_shape; toadd[toadd_count].id = obj; toadd[toadd_count].shape = shape; @@ -344,6 +349,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { for (Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { for (int i = 0; i < E->get().shapes.size(); i++) { if (!E->get().shapes[i].tagged) { + toremove[toremove_count].rid = E->get().rid; toremove[toremove_count].body_id = E->key(); toremove[toremove_count].pair = E->get().shapes[i]; toremove_count++; @@ -354,13 +360,13 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { //process removals for (int i = 0; i < toremove_count; i++) { - _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); + _body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); } //process additions for (int i = 0; i < toadd_count; i++) { - _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape); + _body_inout(1, toadd[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape); } contact_monitor->locked = false; @@ -755,8 +761,8 @@ void RigidBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "applied_force"), "set_applied_force", "get_applied_force"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "applied_torque"), "set_applied_torque", "get_applied_torque"); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("sleeping_state_changed")); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index e0fc0766bc..47d55d11fa 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -140,10 +140,12 @@ private: } }; struct RigidBody2D_RemoveAction { + RID rid; ObjectID body_id; ShapePair pair; }; struct BodyState { + RID rid; //int rc; bool in_scene = false; VSet<ShapePair> shapes; @@ -158,7 +160,7 @@ private: void _body_enter_tree(ObjectID p_id); void _body_exit_tree(ObjectID p_id); - void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape); + void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape); void _direct_state_changed(Object *p_state); bool _test_motion(const Vector2 &p_motion, bool p_infinite_inertia = true, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>()); diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 0afead0863..188f8d300d 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -64,13 +64,13 @@ int TileMapPattern::get_cell_source_id(const Vector2i &p_coords) const { } Vector2i TileMapPattern::get_cell_atlas_coords(const Vector2i &p_coords) const { - ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetAtlasSource::INVALID_ATLAS_COORDS); + ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetSource::INVALID_ATLAS_COORDS); return pattern[p_coords].get_atlas_coords(); } int TileMapPattern::get_cell_alternative_tile(const Vector2i &p_coords) const { - ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetSource::INVALID_TILE_ALTERNATIVE); return pattern[p_coords].alternative_tile; } @@ -113,7 +113,7 @@ void TileMapPattern::clear() { }; void TileMapPattern::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(-1), DEFVAL(TileSetAtlasSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetAtlasSource::INVALID_TILE_ALTERNATIVE)); + ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(-1), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE)); ClassDB::bind_method(D_METHOD("has_cell", "coords"), &TileMapPattern::has_cell); ClassDB::bind_method(D_METHOD("remove_cell", "coords"), &TileMapPattern::remove_cell); ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMapPattern::get_cell_source_id); @@ -520,12 +520,12 @@ void TileMap::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i Vector2i atlas_coords = p_atlas_coords; int alternative_tile = p_alternative_tile; - if ((source_id == -1 || atlas_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) && - (source_id != -1 || atlas_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE)) { + if ((source_id == -1 || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) && + (source_id != -1 || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) { WARN_PRINT("Setting a cell a cell as empty requires both source_id, atlas_coord and alternative_tile to be set to their respective \"invalid\" values. Values were thus changes accordingly."); source_id = -1; - atlas_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS; - alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + atlas_coords = TileSetSource::INVALID_ATLAS_COORDS; + alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; } if (!E && source_id == -1) { @@ -602,7 +602,7 @@ Vector2i TileMap::get_cell_atlas_coords(const Vector2i &p_coords) const { const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords); if (!E) { - return TileSetAtlasSource::INVALID_ATLAS_COORDS; + return TileSetSource::INVALID_ATLAS_COORDS; } return E->get().get_atlas_coords(); @@ -613,7 +613,7 @@ int TileMap::get_cell_alternative_tile(const Vector2i &p_coords) const { const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords); if (!E) { - return TileSetAtlasSource::INVALID_TILE_ALTERNATIVE; + return TileSetSource::INVALID_TILE_ALTERNATIVE; } return E->get().alternative_tile; @@ -721,7 +721,7 @@ void TileMap::fix_invalid_tiles() { for (Map<Vector2i, TileMapCell>::Element *E = tile_map.front(); E; E = E->next()) { TileSetSource *source = *tile_set->get_source(E->get().source_id); if (!source || !source->has_tile(E->get().get_atlas_coords()) || !source->has_alternative_tile(E->get().get_atlas_coords(), E->get().alternative_tile)) { - set_cell(E->key(), -1, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + set_cell(E->key(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); } } } @@ -1716,7 +1716,7 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_quadrant_size", "size"), &TileMap::set_quadrant_size); ClassDB::bind_method(D_METHOD("get_quadrant_size"), &TileMap::get_quadrant_size); - ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMap::set_cell, DEFVAL(-1), DEFVAL(TileSetAtlasSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetAtlasSource::INVALID_TILE_ALTERNATIVE)); + ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMap::set_cell, DEFVAL(-1), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE)); ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMap::get_cell_source_id); ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMap::get_cell_atlas_coords); ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMap::get_cell_alternative_tile); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index e9dbccbdb9..2703e1980e 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -48,7 +48,7 @@ union TileMapCell { }; uint64_t _u64t; - TileMapCell(int p_source_id = -1, Vector2i p_atlas_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) { + TileMapCell(int p_source_id = -1, Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE) { source_id = p_source_id; set_atlas_coords(p_atlas_coords); alternative_tile = p_alternative_tile; @@ -112,16 +112,19 @@ struct TileMapQuadrant { // Debug. RID debug_canvas_item; - // Rendering + // Rendering. List<RID> canvas_items; List<RID> occluders; // Physics. List<RID> bodies; - // Navigation + // Navigation. Map<Vector2i, Vector<RID>> navigation_regions; + // Scenes. + Map<Vector2i, String> scenes; + void operator=(const TileMapQuadrant &q) { coords = q.coords; debug_canvas_item = q.debug_canvas_item; @@ -248,7 +251,7 @@ public: void set_quadrant_size(int p_size); int get_quadrant_size() const; - void set_cell(const Vector2i &p_coords, int p_source_id = -1, const Vector2i p_atlas_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE); + void set_cell(const Vector2i &p_coords, int p_source_id = -1, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE); int get_cell_source_id(const Vector2i &p_coords) const; Vector2i get_cell_atlas_coords(const Vector2i &p_coords) const; int get_cell_alternative_tile(const Vector2i &p_coords) const; diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index e187e06308..44708cddff 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -118,7 +118,7 @@ void Area3D::_body_enter_tree(ObjectID p_id) { E->get().in_tree = true; emit_signal(SceneStringNames::get_singleton()->body_entered, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); } } @@ -132,7 +132,7 @@ void Area3D::_body_exit_tree(ObjectID p_id) { E->get().in_tree = false; emit_signal(SceneStringNames::get_singleton()->body_exited, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); } } @@ -154,6 +154,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i if (body_in) { if (!E) { E = body_map.insert(objid, BodyState()); + E->get().rid = p_body; E->get().rc = 0; E->get().in_tree = node && node->is_inside_tree(); if (node) { @@ -170,7 +171,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i } if (E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape); } } else { @@ -192,7 +193,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i } } if (node && in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_area_shape); } } @@ -224,7 +225,7 @@ void Area3D::_clear_monitoring() { } for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->key(), node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].area_shape); } emit_signal(SceneStringNames::get_singleton()->body_exited, node); @@ -253,7 +254,7 @@ void Area3D::_clear_monitoring() { } for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->key(), node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); } emit_signal(SceneStringNames::get_singleton()->area_exited, obj); @@ -298,7 +299,7 @@ void Area3D::_area_enter_tree(ObjectID p_id) { E->get().in_tree = true; emit_signal(SceneStringNames::get_singleton()->area_entered, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); } } @@ -312,7 +313,7 @@ void Area3D::_area_exit_tree(ObjectID p_id) { E->get().in_tree = false; emit_signal(SceneStringNames::get_singleton()->area_exited, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_id, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->get().rid, node, E->get().shapes[i].area_shape, E->get().shapes[i].self_shape); } } @@ -334,6 +335,7 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i if (area_in) { if (!E) { E = area_map.insert(objid, AreaState()); + E->get().rid = p_area; E->get().rc = 0; E->get().in_tree = node && node->is_inside_tree(); if (node) { @@ -350,7 +352,7 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i } if (!node || E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->area_shape_entered, objid, node, p_area_shape, p_self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, node, p_area_shape, p_self_shape); } } else { @@ -372,7 +374,7 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i } } if (!node || in_tree) { - emit_signal(SceneStringNames::get_singleton()->area_shape_exited, objid, obj, p_area_shape, p_self_shape); + emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, obj, p_area_shape, p_self_shape); } } @@ -582,13 +584,13 @@ void Area3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area3D::set_reverb_uniformity); ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area3D::get_reverb_uniformity); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); - ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"))); ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"))); @@ -601,7 +603,7 @@ void Area3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_vec"), "set_gravity_vector", "get_gravity_vector"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_gravity", "get_gravity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-32,32,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h index 9605a937af..5b8d612717 100644 --- a/scene/3d/area_3d.h +++ b/scene/3d/area_3d.h @@ -83,6 +83,7 @@ private: }; struct BodyState { + RID rid; int rc = 0; bool in_tree = false; VSet<ShapePair> shapes; @@ -114,6 +115,7 @@ private: }; struct AreaState { + RID rid; int rc = 0; bool in_tree = false; VSet<AreaShapePair> shapes; diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index 4d7fc29f15..6505fb1ee8 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -454,7 +454,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { mmi->set_multimesh(baker.create_debug_multimesh()); add_child(mmi); #ifdef TOOLS_ENABLED - if (get_tree()->get_edited_scene_root() == this) { + if (is_inside_tree() && get_tree()->get_edited_scene_root() == this) { mmi->set_owner(this); } else { mmi->set_owner(get_owner()); diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp index 628b823f89..2d59461ff0 100644 --- a/scene/3d/gpu_particles_collision_3d.cpp +++ b/scene/3d/gpu_particles_collision_3d.cpp @@ -653,7 +653,7 @@ void GPUParticlesCollisionHeightField::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096,8192"), "set_resolution", "get_resolution"); ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "WhenMoved,Always"), "set_update_mode", "get_update_mode"); - ADD_GROUP("Folow Camera", "follow_camera_"); + ADD_GROUP("Follow Camera", "follow_camera_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_camera_enabled"), "set_follow_camera_mode", "is_follow_camera_mode_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "follow_camera_push_ratio", PROPERTY_HINT_RANGE, "0.01,1,0.01"), "set_follow_camera_push_ratio", "get_follow_camera_push_ratio"); diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index 27d5487a1a..c495f68890 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -427,7 +427,7 @@ void MeshInstance3D::create_debug_tangents() { add_child(mi); #ifdef TOOLS_ENABLED - if (this == get_tree()->get_edited_scene_root()) { + if (is_inside_tree() && this == get_tree()->get_edited_scene_root()) { mi->set_owner(this); } else { mi->set_owner(get_owner()); diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index dd1a797568..e895d18604 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -178,7 +178,7 @@ void RigidBody3D::_body_enter_tree(ObjectID p_id) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); } contact_monitor->locked = false; @@ -199,13 +199,13 @@ void RigidBody3D::_body_exit_tree(ObjectID p_id) { emit_signal(SceneStringNames::get_singleton()->body_exited, node); for (int i = 0; i < E->get().shapes.size(); i++) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_id, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->get().rid, node, E->get().shapes[i].body_shape, E->get().shapes[i].local_shape); } contact_monitor->locked = false; } -void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape) { +void RigidBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { bool body_in = p_status == 1; ObjectID objid = p_instance; @@ -220,6 +220,7 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap if (body_in) { if (!E) { E = contact_monitor->body_map.insert(objid, BodyState()); + E->get().rid = p_body; //E->get().rc=0; E->get().in_tree = node && node->is_inside_tree(); if (node) { @@ -236,7 +237,7 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap } if (E->get().in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_entered, objid, node, p_body_shape, p_local_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape); } } else { @@ -260,12 +261,13 @@ void RigidBody3D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap contact_monitor->body_map.erase(E); } if (node && in_tree) { - emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_local_shape); + emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_local_shape); } } } struct _RigidBodyInOut { + RID rid; ObjectID id; int shape = 0; int local_shape = 0; @@ -314,6 +316,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { //put the ones to add for (int i = 0; i < state->get_contact_count(); i++) { + RID rid = state->get_contact_collider(i); ObjectID obj = state->get_contact_collider_id(i); int local_shape = state->get_contact_local_shape(i); int shape = state->get_contact_collider_shape(i); @@ -322,6 +325,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.find(obj); if (!E) { + toadd[toadd_count].rid = rid; toadd[toadd_count].local_shape = local_shape; toadd[toadd_count].id = obj; toadd[toadd_count].shape = shape; @@ -332,6 +336,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { ShapePair sp(shape, local_shape); int idx = E->get().shapes.find(sp); if (idx == -1) { + toadd[toadd_count].rid = rid; toadd[toadd_count].local_shape = local_shape; toadd[toadd_count].id = obj; toadd[toadd_count].shape = shape; @@ -347,6 +352,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { for (Map<ObjectID, BodyState>::Element *E = contact_monitor->body_map.front(); E; E = E->next()) { for (int i = 0; i < E->get().shapes.size(); i++) { if (!E->get().shapes[i].tagged) { + toremove[toremove_count].rid = E->get().rid; toremove[toremove_count].body_id = E->key(); toremove[toremove_count].pair = E->get().shapes[i]; toremove_count++; @@ -357,13 +363,13 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { //process removals for (int i = 0; i < toremove_count; i++) { - _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); + _body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); } //process additions for (int i = 0; i < toadd_count; i++) { - _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape); + _body_inout(1, toremove[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape); } contact_monitor->locked = false; @@ -511,7 +517,7 @@ Vector3 RigidBody3D::get_angular_velocity() const { return angular_velocity; } -Basis RigidBody3D::get_inverse_inertia_tensor() { +Basis RigidBody3D::get_inverse_inertia_tensor() const { return inverse_inertia_tensor; } @@ -745,8 +751,8 @@ void RigidBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("sleeping_state_changed")); @@ -1952,6 +1958,8 @@ void PhysicalBone3D::_notification(int p_what) { if (parent_skeleton) { if (-1 != bone_id) { parent_skeleton->unbind_physical_bone_from_bone(bone_id); + parent_skeleton->unbind_child_node_from_bone(bone_id, this); + bone_id = -1; } } parent_skeleton = nullptr; diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 21afe66861..818ff97730 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -137,10 +137,12 @@ protected: } }; struct RigidBody3D_RemoveAction { + RID rid; ObjectID body_id; ShapePair pair; }; struct BodyState { + RID rid; //int rc; bool in_tree = false; VSet<ShapePair> shapes; @@ -155,7 +157,7 @@ protected: void _body_enter_tree(ObjectID p_id); void _body_exit_tree(ObjectID p_id); - void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape); + void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape); virtual void _direct_state_changed(Object *p_state); void _notification(int p_what); @@ -181,7 +183,7 @@ public: void set_angular_velocity(const Vector3 &p_velocity); Vector3 get_angular_velocity() const override; - Basis get_inverse_inertia_tensor(); + Basis get_inverse_inertia_tensor() const; void set_gravity_scale(real_t p_gravity_scale); real_t get_gravity_scale() const; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index fdee136b82..9ccb2886e1 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -84,6 +84,57 @@ void ColorPicker::_notification(int p_what) { } } +Ref<Shader> ColorPicker::wheel_shader; +Ref<Shader> ColorPicker::circle_shader; + +void ColorPicker::init_shaders() { + wheel_shader.instance(); + wheel_shader->set_code( + "shader_type canvas_item;" + "const float TAU = 6.28318530718;" + "void fragment() {" + " float x = UV.x - 0.5;" + " float y = UV.y - 0.5;" + " float a = atan(y, x);" + " x += 0.001;" + " y += 0.001;" + " float b = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);" + " x -= 0.002;" + " float b2 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);" + " y -= 0.002;" + " float b3 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);" + " x += 0.002;" + " float b4 = float(sqrt(x * x + y * y) < 0.5) * float(sqrt(x * x + y * y) > 0.42);" + " COLOR = vec4(clamp((abs(fract(((a - TAU) / TAU) + vec3(3.0, 2.0, 1.0) / 3.0) * 6.0 - 3.0) - 1.0), 0.0, 1.0), (b + b2 + b3 + b4) / 4.00);" + "}"); + + circle_shader.instance(); + circle_shader->set_code( + "shader_type canvas_item;" + "const float TAU = 6.28318530718;" + "uniform float v = 1.0;" + "void fragment() {" + " float x = UV.x - 0.5;" + " float y = UV.y - 0.5;" + " float a = atan(y, x);" + " x += 0.001;" + " y += 0.001;" + " float b = float(sqrt(x * x + y * y) < 0.5);" + " x -= 0.002;" + " float b2 = float(sqrt(x * x + y * y) < 0.5);" + " y -= 0.002;" + " float b3 = float(sqrt(x * x + y * y) < 0.5);" + " x += 0.002;" + " float b4 = float(sqrt(x * x + y * y) < 0.5);" + " COLOR = vec4(mix(vec3(1.0), clamp(abs(fract(vec3((a - TAU) / TAU) + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - vec3(3.0)) - vec3(1.0), 0.0, 1.0), ((float(sqrt(x * x + y * y)) * 2.0)) / 1.0) * vec3(v), (b + b2 + b3 + b4) / 4.00);" + "}"); +} + +void ColorPicker::finish_shaders() { + wheel_shader.unref(); + circle_shader.unref(); +} + void ColorPicker::set_focus_on_line_edit() { c_text->call_deferred("grab_focus"); } @@ -1165,14 +1216,8 @@ ColorPicker::ColorPicker() : hb_edit->add_child(wheel_edit); wheel_mat.instance(); - circle_mat.instance(); - - Ref<Shader> wheel_shader(memnew(Shader)); - wheel_shader->set_code("shader_type canvas_item;const float TAU=6.28318530718;void fragment(){float x=UV.x-0.5;float y=UV.y-0.5;float a=atan(y,x);x+=0.001;y+=0.001;float b=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);x-=0.002;float b2=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);y-=0.002;float b3=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);x+=0.002;float b4=float(sqrt(x*x+y*y)<0.5)*float(sqrt(x*x+y*y)>0.42);COLOR=vec4(clamp((abs(fract(((a-TAU)/TAU)+vec3(3.0,2.0,1.0)/3.0)*6.0-3.0)-1.0),0.0,1.0),(b+b2+b3+b4)/4.00);}"); wheel_mat->set_shader(wheel_shader); - - Ref<Shader> circle_shader(memnew(Shader)); - circle_shader->set_code("shader_type canvas_item;const float TAU=6.28318530718;uniform float v=1.0;void fragment(){float x=UV.x-0.5;float y=UV.y-0.5;float a=atan(y,x);x+=0.001;y+=0.001;float b=float(sqrt(x*x+y*y)<0.5);x-=0.002;float b2=float(sqrt(x*x+y*y)<0.5);y-=0.002;float b3=float(sqrt(x*x+y*y)<0.5);x+=0.002;float b4=float(sqrt(x*x+y*y)<0.5);COLOR=vec4(mix(vec3(1.0),clamp(abs(fract(vec3((a-TAU)/TAU)+vec3(1.0,2.0/3.0,1.0/3.0))*6.0-vec3(3.0))-vec3(1.0),0.0,1.0),((float(sqrt(x*x+y*y))*2.0))/1.0)*vec3(v),(b+b2+b3+b4)/4.00);}"); + circle_mat.instance(); circle_mat->set_shader(circle_shader); MarginContainer *wheel_margin(memnew(MarginContainer)); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 400074e6e9..14113467d0 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -56,6 +56,9 @@ public: }; private: + static Ref<Shader> wheel_shader; + static Ref<Shader> circle_shader; + Control *screen = nullptr; Control *uv_edit = memnew(Control); Control *w_edit = memnew(Control); @@ -128,6 +131,9 @@ protected: static void _bind_methods(); public: + static void init_shaders(); + static void finish_shaders(); + void set_edit_alpha(bool p_show); bool is_editing_alpha() const; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index ce5eef93aa..83abd02b40 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -168,6 +168,12 @@ Size2 Control::_edit_get_minimum_size() const { } #endif +void Control::accept_event() { + if (is_inside_tree()) { + get_viewport()->_gui_accept_event(); + } +} + void Control::set_custom_minimum_size(const Size2 &p_custom) { if (p_custom == data.custom_minimum_size) { return; @@ -765,32 +771,27 @@ Size2 Control::get_minimum_size() const { } template <class T> -bool Control::_find_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, T &r_ret, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_node_type) { - // try with custom themes +T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { + ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, T(), "At least one theme type must be specified."); + + // First, look through each control or window node in the branch, until no valid parent can be found. + // For each control iterate through its inheritance chain and see if p_name exists in any of them. Control *theme_owner = p_theme_owner; Window *theme_owner_window = p_theme_owner_window; while (theme_owner || theme_owner_window) { - StringName class_name = p_node_type; - - while (class_name != StringName()) { - if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) { - r_ret = (theme_owner->data.theme.operator->()->*get_func)(p_name, class_name); - return true; + for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) { + if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E->get())) { + return theme_owner->data.theme->get_theme_item(p_data_type, p_name, E->get()); } - if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) { - r_ret = (theme_owner_window->theme.operator->()->*get_func)(p_name, class_name); - return true; + if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E->get())) { + return theme_owner_window->theme->get_theme_item(p_data_type, p_name, E->get()); } - - class_name = ClassDB::get_parent_class_nocheck(class_name); } Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); - Control *parent_c = Object::cast_to<Control>(parent); - if (parent_c) { theme_owner = parent_c->data.theme_owner; theme_owner_window = parent_c->data.theme_owner_window; @@ -805,33 +806,47 @@ bool Control::_find_theme_item(Control *p_theme_owner, Window *p_theme_owner_win } } } - return false; + + // Secondly, check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) { + if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E->get())) { + return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E->get()); + } + } + } + + // Lastly, fall back on the items defined in the default Theme, if they exist. + for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) { + if (Theme::get_default()->has_theme_item(p_data_type, p_name, E->get())) { + return Theme::get_default()->get_theme_item(p_data_type, p_name, E->get()); + } + } + // If they don't exist, use any type to return the default/empty value. + return Theme::get_default()->get_theme_item(p_data_type, p_name, p_theme_types[0]); } -bool Control::_has_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_node_type) { - // try with custom themes +bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { + ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, false, "At least one theme type must be specified."); + + // First, look through each control or window node in the branch, until no valid parent can be found. + // For each control iterate through its inheritance chain and see if p_name exists in any of them. Control *theme_owner = p_theme_owner; Window *theme_owner_window = p_theme_owner_window; while (theme_owner || theme_owner_window) { - StringName class_name = p_node_type; - - while (class_name != StringName()) { - if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) { + for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) { + if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E->get())) { return true; } - if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) { + if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E->get())) { return true; } - - class_name = ClassDB::get_parent_class_nocheck(class_name); } Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); - Control *parent_c = Object::cast_to<Control>(parent); - if (parent_c) { theme_owner = parent_c->data.theme_owner; theme_owner_window = parent_c->data.theme_owner_window; @@ -846,179 +861,112 @@ bool Control::_has_theme_item(Control *p_theme_owner, Window *p_theme_owner_wind } } } - return false; -} -Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { - const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); - if (tex) { - return *tex; + // Secondly, check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) { + if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E->get())) { + return true; + } } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return get_icons(data.theme_owner, data.theme_owner_window, p_name, type); + // Lastly, fall back on the items defined in the default Theme, if they exist. + for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) { + if (Theme::get_default()->has_theme_item(p_data_type, p_name, E->get())) { + return true; + } + } + return false; } -Ref<Texture2D> Control::get_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - Ref<Texture2D> icon; - - if (_find_theme_item(p_theme_owner, p_theme_owner_window, icon, &Theme::get_icon, &Theme::has_icon, p_name, p_node_type)) { - return icon; +void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (data.theme_custom_type != StringName()) { + p_list->push_back(data.theme_custom_type); + } + Theme::get_type_dependencies(get_class_name(), p_list); + } else { + Theme::get_type_dependencies(p_theme_type, p_list); } +} - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_icon(p_name, p_node_type)) { - return Theme::get_project_default()->get_icon(p_name, p_node_type); +Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); + if (tex) { + return *tex; } } - return Theme::get_default()->get_icon(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<Ref<Texture2D>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types); } -Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { const Ref<StyleBox> *style = data.style_override.getptr(p_name); if (style) { return *style; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return get_styleboxs(data.theme_owner, data.theme_owner_window, p_name, type); -} - -Ref<StyleBox> Control::get_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - Ref<StyleBox> stylebox; - - if (_find_theme_item(p_theme_owner, p_theme_owner_window, stylebox, &Theme::get_stylebox, &Theme::has_stylebox, p_name, p_node_type)) { - return stylebox; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_stylebox(p_name, p_node_type)) { - return Theme::get_project_default()->get_stylebox(p_name, p_node_type); - } - } - - return Theme::get_default()->get_stylebox(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<Ref<StyleBox>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types); } -Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { const Ref<Font> *font = data.font_override.getptr(p_name); if (font) { return *font; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return get_fonts(data.theme_owner, data.theme_owner_window, p_name, type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<Ref<Font>>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types); } -int Control::get_theme_font_size(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { const int *font_size = data.font_size_override.getptr(p_name); if (font_size) { return *font_size; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return get_font_sizes(data.theme_owner, data.theme_owner_window, p_name, type); -} - -Ref<Font> Control::get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - Ref<Font> font; - - if (_find_theme_item(p_theme_owner, p_theme_owner_window, font, &Theme::get_font, &Theme::has_font, p_name, p_node_type)) { - return font; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_font(p_name, p_node_type)) { - return Theme::get_project_default()->get_font(p_name, p_node_type); - } - } - - return Theme::get_default()->get_font(p_name, p_node_type); -} - -int Control::get_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - int font_size; - - if (_find_theme_item(p_theme_owner, p_theme_owner_window, font_size, &Theme::get_font_size, &Theme::has_font_size, p_name, p_node_type)) { - return font_size; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_font_size(p_name, p_node_type)) { - return Theme::get_project_default()->get_font_size(p_name, p_node_type); - } - } - - return Theme::get_default()->get_font_size(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types); } -Color Control::get_theme_color(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +Color Control::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { const Color *color = data.color_override.getptr(p_name); if (color) { return *color; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return get_colors(data.theme_owner, data.theme_owner_window, p_name, type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<Color>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types); } -Color Control::get_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - Color color; - - if (_find_theme_item(p_theme_owner, p_theme_owner_window, color, &Theme::get_color, &Theme::has_color, p_name, p_node_type)) { - return color; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_color(p_name, p_node_type)) { - return Theme::get_project_default()->get_color(p_name, p_node_type); - } - } - return Theme::get_default()->get_color(p_name, p_node_type); -} - -int Control::get_theme_constant(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { const int *constant = data.constant_override.getptr(p_name); if (constant) { return *constant; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return get_constants(data.theme_owner, data.theme_owner_window, p_name, type); -} - -int Control::get_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - int constant; - - if (_find_theme_item(p_theme_owner, p_theme_owner_window, constant, &Theme::get_constant, &Theme::has_constant, p_name, p_node_type)) { - return constant; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_constant(p_name, p_node_type)) { - return Theme::get_project_default()->get_constant(p_name, p_node_type); - } - } - return Theme::get_default()->get_constant(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return get_theme_item_in_types<int>(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types); } bool Control::has_theme_icon_override(const StringName &p_name) const { @@ -1051,154 +999,76 @@ bool Control::has_theme_constant_override(const StringName &p_name) const { return constant != nullptr; } -bool Control::has_theme_icon(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { if (has_theme_icon_override(p_name)) { return true; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return has_icons(data.theme_owner, data.theme_owner_window, p_name, type); -} - -bool Control::has_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_icon, p_name, p_node_type)) { - return true; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_color(p_name, p_node_type)) { - return true; - } - } - return Theme::get_default()->has_icon(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types); } -bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { if (has_theme_stylebox_override(p_name)) { return true; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return has_styleboxs(data.theme_owner, data.theme_owner_window, p_name, type); -} - -bool Control::has_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_stylebox, p_name, p_node_type)) { - return true; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_stylebox(p_name, p_node_type)) { - return true; - } - } - return Theme::get_default()->has_stylebox(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types); } -bool Control::has_theme_font(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { if (has_theme_font_override(p_name)) { return true; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return has_fonts(data.theme_owner, data.theme_owner_window, p_name, type); -} - -bool Control::has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_font, p_name, p_node_type)) { - return true; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_font(p_name, p_node_type)) { - return true; - } - } - return Theme::get_default()->has_font(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types); } -bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { if (has_theme_font_size_override(p_name)) { return true; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return has_font_sizes(data.theme_owner, data.theme_owner_window, p_name, type); -} - -bool Control::has_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_font_size, p_name, p_node_type)) { - return true; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_font_size(p_name, p_node_type)) { - return true; - } - } - return Theme::get_default()->has_font_size(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types); } -bool Control::has_theme_color(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +bool Control::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { if (has_theme_color_override(p_name)) { return true; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return has_colors(data.theme_owner, data.theme_owner_window, p_name, type); -} - -bool Control::has_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_color, p_name, p_node_type)) { - return true; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_color(p_name, p_node_type)) { - return true; - } - } - return Theme::get_default()->has_color(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types); } -bool Control::has_theme_constant(const StringName &p_name, const StringName &p_node_type) const { - if (p_node_type == StringName() || p_node_type == get_class_name()) { +bool Control::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { if (has_theme_constant_override(p_name)) { return true; } } - StringName type = p_node_type ? p_node_type : get_class_name(); - - return has_constants(data.theme_owner, data.theme_owner_window, p_name, p_node_type); -} - -bool Control::has_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) { - if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_constant, p_name, p_node_type)) { - return true; - } - - if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_constant(p_name, p_node_type)) { - return true; - } - } - return Theme::get_default()->has_constant(p_name, p_node_type); + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types); } Rect2 Control::get_parent_anchorable_rect() const { @@ -2171,16 +2041,19 @@ void Control::set_theme(const Ref<Theme> &p_theme) { } } -void Control::accept_event() { - if (is_inside_tree()) { - get_viewport()->_gui_accept_event(); - } -} - Ref<Theme> Control::get_theme() const { return data.theme; } +void Control::set_theme_custom_type(const StringName &p_theme_type) { + data.theme_custom_type = p_theme_type; + _propagate_theme_changed(this, data.theme_owner, data.theme_owner_window); +} + +StringName Control::get_theme_custom_type() const { + return data.theme_custom_type; +} + void Control::set_tooltip(const String &p_tooltip) { data.tooltip = p_tooltip; update_configuration_warnings(); @@ -2499,9 +2372,9 @@ bool Control::is_text_field() const { return false; } -Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_node_type, const Array &p_args, const String p_text) const { +Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const { Vector<Vector2i> ret; - switch (p_node_type) { + switch (p_theme_type) { case STRUCTURED_TEXT_URI: { int prev = 0; for (int i = 0; i < p_text.length(); i++) { @@ -2811,6 +2684,9 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Control::set_theme); ClassDB::bind_method(D_METHOD("get_theme"), &Control::get_theme); + ClassDB::bind_method(D_METHOD("set_theme_custom_type", "theme_type"), &Control::set_theme_custom_type); + ClassDB::bind_method(D_METHOD("get_theme_custom_type"), &Control::get_theme_custom_type); + ClassDB::bind_method(D_METHOD("add_theme_icon_override", "name", "texture"), &Control::add_theme_icon_override); ClassDB::bind_method(D_METHOD("add_theme_stylebox_override", "name", "stylebox"), &Control::add_theme_style_override); ClassDB::bind_method(D_METHOD("add_theme_font_override", "name", "font"), &Control::add_theme_font_override); @@ -2825,12 +2701,12 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_theme_color_override", "name"), &Control::remove_theme_color_override); ClassDB::bind_method(D_METHOD("remove_theme_constant_override", "name"), &Control::remove_theme_constant_override); - ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "node_type"), &Control::get_theme_icon, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "node_type"), &Control::get_theme_stylebox, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_font", "name", "node_type"), &Control::get_theme_font, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_font_size", "name", "node_type"), &Control::get_theme_font_size, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_color", "name", "node_type"), &Control::get_theme_color, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "node_type"), &Control::get_theme_constant, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "theme_type"), &Control::get_theme_icon, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "theme_type"), &Control::get_theme_stylebox, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_font", "name", "theme_type"), &Control::get_theme_font, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_font_size", "name", "theme_type"), &Control::get_theme_font_size, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_color", "name", "theme_type"), &Control::get_theme_color, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "theme_type"), &Control::get_theme_constant, DEFVAL("")); ClassDB::bind_method(D_METHOD("has_theme_icon_override", "name"), &Control::has_theme_icon_override); ClassDB::bind_method(D_METHOD("has_theme_stylebox_override", "name"), &Control::has_theme_stylebox_override); @@ -2839,12 +2715,12 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("has_theme_color_override", "name"), &Control::has_theme_color_override); ClassDB::bind_method(D_METHOD("has_theme_constant_override", "name"), &Control::has_theme_constant_override); - ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "node_type"), &Control::has_theme_icon, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "node_type"), &Control::has_theme_stylebox, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_font", "name", "node_type"), &Control::has_theme_font, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_font_size", "name", "node_type"), &Control::has_theme_font_size, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_color", "name", "node_type"), &Control::has_theme_color, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "node_type"), &Control::has_theme_constant, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "theme_type"), &Control::has_theme_icon, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "theme_type"), &Control::has_theme_stylebox, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_font", "name", "theme_type"), &Control::has_theme_font, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_font_size", "name", "theme_type"), &Control::has_theme_font_size, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_color", "name", "theme_type"), &Control::has_theme_color, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "theme_type"), &Control::has_theme_constant, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_parent_control"), &Control::get_parent_control); @@ -2958,8 +2834,9 @@ void Control::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_h_size_flags", "get_h_size_flags"); ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_v_size_flags", "get_v_size_flags"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,20,0.01,or_greater"), "set_stretch_ratio", "get_stretch_ratio"); - ADD_GROUP("Theme", ""); + ADD_GROUP("Theme", "theme_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_custom_type"), "set_theme_custom_type", "get_theme_custom_type"); ADD_GROUP("", ""); BIND_ENUM_CONSTANT(FOCUS_NONE); diff --git a/scene/gui/control.h b/scene/gui/control.h index 1f397df589..a05025c32d 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -201,6 +201,8 @@ private: Ref<Theme> theme; Control *theme_owner = nullptr; Window *theme_owner_window = nullptr; + StringName theme_custom_type; + String tooltip; CursorShape default_cursor = CURSOR_ARROW; @@ -258,23 +260,9 @@ private: static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true); template <class T> - _FORCE_INLINE_ static bool _find_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, T &, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_node_type); - - _FORCE_INLINE_ static bool _has_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_node_type); - - static Ref<Texture2D> get_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static Ref<StyleBox> get_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static Ref<Font> get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static int get_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static Color get_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static int get_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - - static bool has_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static bool has_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static bool has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static bool has_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static bool has_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); - static bool has_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName()); + static T get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types); + static bool has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types); + _FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const; protected: virtual void add_child_notify(Node *p_child) override; @@ -282,7 +270,7 @@ protected: //virtual void _window_gui_input(InputEvent p_event); - virtual Vector<Vector2i> structured_text_parser(StructuredTextParser p_node_type, const Array &p_args, const String p_text) const; + virtual Vector<Vector2i> structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const; bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; @@ -415,6 +403,9 @@ public: void set_theme(const Ref<Theme> &p_theme); Ref<Theme> get_theme() const; + void set_theme_custom_type(const StringName &p_theme_type); + StringName get_theme_custom_type() const; + void set_h_size_flags(int p_flags); int get_h_size_flags() const; @@ -466,12 +457,12 @@ public: void remove_theme_color_override(const StringName &p_name); void remove_theme_constant_override(const StringName &p_name); - Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_node_type = StringName()) const; - Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_node_type = StringName()) const; - Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_node_type = StringName()) const; - int get_theme_font_size(const StringName &p_name, const StringName &p_node_type = StringName()) const; - Color get_theme_color(const StringName &p_name, const StringName &p_node_type = StringName()) const; - int get_theme_constant(const StringName &p_name, const StringName &p_node_type = StringName()) const; + Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + int get_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + Color get_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + int get_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const; bool has_theme_icon_override(const StringName &p_name) const; bool has_theme_stylebox_override(const StringName &p_name) const; @@ -480,12 +471,12 @@ public: bool has_theme_color_override(const StringName &p_name) const; bool has_theme_constant_override(const StringName &p_name) const; - bool has_theme_icon(const StringName &p_name, const StringName &p_node_type = StringName()) const; - bool has_theme_stylebox(const StringName &p_name, const StringName &p_node_type = StringName()) const; - bool has_theme_font(const StringName &p_name, const StringName &p_node_type = StringName()) const; - bool has_theme_font_size(const StringName &p_name, const StringName &p_node_type = StringName()) const; - bool has_theme_color(const StringName &p_name, const StringName &p_node_type = StringName()) const; - bool has_theme_constant(const StringName &p_name, const StringName &p_node_type = StringName()) const; + bool has_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const; /* TOOLTIP */ diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 5409b44b9e..806039d7ac 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -105,7 +105,7 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { switch (k->get_keycode()) { case KEY_H: { - if (k->get_command()) { + if (k->is_command_pressed()) { set_show_hidden_files(!show_hidden_files); } else { handled = false; @@ -589,8 +589,8 @@ void FileDialog::update_file_list() { files.pop_front(); } - if (tree->get_root() && tree->get_root()->get_children() && tree->get_selected() == nullptr) { - tree->get_root()->get_children()->select(0); + if (tree->get_root() && tree->get_root()->get_first_child() && tree->get_selected() == nullptr) { + tree->get_root()->get_first_child()->select(0); } } diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index ebefb2938f..7278ca6e94 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -127,7 +127,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { } //Hold alt key to duplicate selected color - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->get_alt()) { + if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->is_alt_pressed()) { int x = mb->get_position().x; grabbed = _get_point_from_pos(x); @@ -236,9 +236,9 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) { // Snap to "round" coordinates if holding Ctrl. // Be more precise if holding Shift as well - if (mm->get_control()) { - newofs = Math::snapped(newofs, mm->get_shift() ? 0.025 : 0.1); - } else if (mm->get_shift()) { + if (mm->is_ctrl_pressed()) { + newofs = Math::snapped(newofs, mm->is_shift_pressed() ? 0.025 : 0.1); + } else if (mm->is_shift_pressed()) { // Snap to nearest point if holding just Shift const float snap_threshold = 0.03; float smallest_ofs = snap_threshold; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 06c9cf1b63..5a4dacd897 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1091,7 +1091,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { // Snapping can be toggled temporarily by holding down Ctrl. // This is done here as to not toggle the grid when holding down Ctrl. - if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(KEY_CTRL)) { const int snap = get_snap(); pos = pos.snapped(Vector2(snap, snap)); } @@ -1174,7 +1174,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { } if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && dragging) { - if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CTRL)) { //deselect current node for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); @@ -1238,7 +1238,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { dragging = true; drag_accum = Vector2(); just_selected = !gn->is_selected(); - if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) { for (int i = 0; i < get_child_count(); i++) { GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i)); if (o_gn) { @@ -1275,7 +1275,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { box_selecting = true; box_selecting_from = b->get_position(); - if (b->get_control()) { + if (b->is_ctrl_pressed()) { box_selection_mode_additive = true; previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1286,7 +1286,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { previous_selected.push_back(gn2); } - } else if (b->get_shift()) { + } else if (b->is_shift_pressed()) { box_selection_mode_additive = false; previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1322,9 +1322,9 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { minimap->update(); } - if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CTRL)) { set_zoom_custom(zoom * ZOOM_SCALE, b->get_position()); - } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CTRL)) { set_zoom_custom(zoom / ZOOM_SCALE, b->get_position()); } else if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 7d5c53effe..1ca54a16ae 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -228,7 +228,7 @@ void GraphNode::_resort() { } stretch_avail += stretch_diff - sb->get_margin(SIDE_BOTTOM) - sb->get_margin(SIDE_TOP); //available stretch space. - /** Second, pass sucessively to discard elements that can't be stretched, this will run while stretchable + /** Second, pass successively to discard elements that can't be stretched, this will run while stretchable elements exist */ while (stretch_ratio_total > 0) { // first of all, don't even be here if no stretchable objects exist @@ -459,7 +459,7 @@ void GraphNode::_shape() { } void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right) { - ERR_FAIL_COND(p_idx < 0); + ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set slot with p_idx (%d) lesser than zero.", p_idx)); if (!p_enable_left && p_type_left == 0 && p_color_left == Color(1, 1, 1, 1) && !p_enable_right && p_type_right == 0 && p_color_right == Color(1, 1, 1, 1) && @@ -503,6 +503,26 @@ bool GraphNode::is_slot_enabled_left(int p_idx) const { return slot_info[p_idx].enable_left; } +void GraphNode::set_slot_enabled_left(int p_idx, bool p_enable_left) { + ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set enable_left for the slot with p_idx (%d) lesser than zero.", p_idx)); + + slot_info[p_idx].enable_left = p_enable_left; + update(); + connpos_dirty = true; + + emit_signal("slot_updated", p_idx); +} + +void GraphNode::set_slot_type_left(int p_idx, int p_type_left) { + ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set type_left for the slot '%d' because it hasn't been enabled.", p_idx)); + + slot_info[p_idx].type_left = p_type_left; + update(); + connpos_dirty = true; + + emit_signal("slot_updated", p_idx); +} + int GraphNode::get_slot_type_left(int p_idx) const { if (!slot_info.has(p_idx)) { return 0; @@ -510,6 +530,16 @@ int GraphNode::get_slot_type_left(int p_idx) const { return slot_info[p_idx].type_left; } +void GraphNode::set_slot_color_left(int p_idx, const Color &p_color_left) { + ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set color_left for the slot '%d' because it hasn't been enabled.", p_idx)); + + slot_info[p_idx].color_left = p_color_left; + update(); + connpos_dirty = true; + + emit_signal("slot_updated", p_idx); +} + Color GraphNode::get_slot_color_left(int p_idx) const { if (!slot_info.has(p_idx)) { return Color(1, 1, 1, 1); @@ -524,6 +554,26 @@ bool GraphNode::is_slot_enabled_right(int p_idx) const { return slot_info[p_idx].enable_right; } +void GraphNode::set_slot_enabled_right(int p_idx, bool p_enable_right) { + ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set enable_right for the slot with p_idx (%d) lesser than zero.", p_idx)); + + slot_info[p_idx].enable_right = p_enable_right; + update(); + connpos_dirty = true; + + emit_signal("slot_updated", p_idx); +} + +void GraphNode::set_slot_type_right(int p_idx, int p_type_right) { + ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set type_right for the slot '%d' because it hasn't been enabled.", p_idx)); + + slot_info[p_idx].type_right = p_type_right; + update(); + connpos_dirty = true; + + emit_signal("slot_updated", p_idx); +} + int GraphNode::get_slot_type_right(int p_idx) const { if (!slot_info.has(p_idx)) { return 0; @@ -531,6 +581,16 @@ int GraphNode::get_slot_type_right(int p_idx) const { return slot_info[p_idx].type_right; } +void GraphNode::set_slot_color_right(int p_idx, const Color &p_color_right) { + ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set color_right for the slot '%d' because it hasn't been enabled.", p_idx)); + + slot_info[p_idx].color_right = p_color_right; + update(); + connpos_dirty = true; + + emit_signal("slot_updated", p_idx); +} + Color GraphNode::get_slot_color_right(int p_idx) const { if (!slot_info.has(p_idx)) { return Color(1, 1, 1, 1); @@ -891,11 +951,23 @@ void GraphNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_slot", "idx", "enable_left", "type_left", "color_left", "enable_right", "type_right", "color_right", "custom_left", "custom_right"), &GraphNode::set_slot, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>())); ClassDB::bind_method(D_METHOD("clear_slot", "idx"), &GraphNode::clear_slot); ClassDB::bind_method(D_METHOD("clear_all_slots"), &GraphNode::clear_all_slots); + ClassDB::bind_method(D_METHOD("is_slot_enabled_left", "idx"), &GraphNode::is_slot_enabled_left); + ClassDB::bind_method(D_METHOD("set_slot_enabled_left", "idx", "enable_left"), &GraphNode::set_slot_enabled_left); + + ClassDB::bind_method(D_METHOD("set_slot_type_left", "idx", "type_left"), &GraphNode::set_slot_type_left); ClassDB::bind_method(D_METHOD("get_slot_type_left", "idx"), &GraphNode::get_slot_type_left); + + ClassDB::bind_method(D_METHOD("set_slot_color_left", "idx", "color_left"), &GraphNode::set_slot_color_left); ClassDB::bind_method(D_METHOD("get_slot_color_left", "idx"), &GraphNode::get_slot_color_left); + ClassDB::bind_method(D_METHOD("is_slot_enabled_right", "idx"), &GraphNode::is_slot_enabled_right); + ClassDB::bind_method(D_METHOD("set_slot_enabled_right", "idx", "enable_right"), &GraphNode::set_slot_enabled_right); + + ClassDB::bind_method(D_METHOD("set_slot_type_right", "idx", "type_right"), &GraphNode::set_slot_type_right); ClassDB::bind_method(D_METHOD("get_slot_type_right", "idx"), &GraphNode::get_slot_type_right); + + ClassDB::bind_method(D_METHOD("set_slot_color_right", "idx", "color_right"), &GraphNode::set_slot_color_right); ClassDB::bind_method(D_METHOD("get_slot_color_right", "idx"), &GraphNode::get_slot_color_right); ClassDB::bind_method(D_METHOD("set_position_offset", "offset"), &GraphNode::set_position_offset); diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index 1bc54dddb7..c70f616b47 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -113,11 +113,23 @@ public: void set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left = Ref<Texture2D>(), const Ref<Texture2D> &p_custom_right = Ref<Texture2D>()); void clear_slot(int p_idx); void clear_all_slots(); + bool is_slot_enabled_left(int p_idx) const; + void set_slot_enabled_left(int p_idx, bool p_enable_left); + + void set_slot_type_left(int p_idx, int p_type_left); int get_slot_type_left(int p_idx) const; + + void set_slot_color_left(int p_idx, const Color &p_color_left); Color get_slot_color_left(int p_idx) const; + bool is_slot_enabled_right(int p_idx) const; + void set_slot_enabled_right(int p_idx, bool p_enable_right); + + void set_slot_type_right(int p_idx, int p_type_right); int get_slot_type_right(int p_idx) const; + + void set_slot_color_right(int p_idx, const Color &p_color_right); Color get_slot_color_right(int p_idx) const; void set_title(const String &p_title); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 0bdae2b118..150980b2e9 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -581,11 +581,11 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { if (closest != -1) { int i = closest; - if (select_mode == SELECT_MULTI && items[i].selected && mb->get_command()) { + if (select_mode == SELECT_MULTI && items[i].selected && mb->is_command_pressed()) { deselect(i); emit_signal("multi_selected", i, false); - } else if (select_mode == SELECT_MULTI && mb->get_shift() && current >= 0 && current < items.size() && current != i) { + } else if (select_mode == SELECT_MULTI && mb->is_shift_pressed() && current >= 0 && current < items.size() && current != i) { int from = current; int to = i; if (i < current) { @@ -603,7 +603,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { emit_signal("item_rmb_selected", i, get_local_mouse_position()); } } else { - if (!mb->is_double_click() && !mb->get_command() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (!mb->is_double_click() && !mb->is_command_pressed() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) { defer_select_single = i; return; } @@ -613,7 +613,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { } else { bool selected = items[i].selected; - select(i, select_mode == SELECT_SINGLE || !mb->get_command()); + select(i, select_mode == SELECT_SINGLE || !mb->is_command_pressed()); if (!selected || allow_reselect) { if (select_mode == SELECT_SINGLE) { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index bfd739788f..98dd9f624b 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -250,11 +250,11 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { return; } - shift_selection_check_pre(b->get_shift()); + shift_selection_check_pre(b->is_shift_pressed()); set_caret_at_pixel_pos(b->get_position().x); - if (b->get_shift()) { + if (b->is_shift_pressed()) { selection_fill_at_caret(); selection.creating = true; @@ -442,9 +442,9 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { // Cursor Movement k = k->duplicate(); - bool shift_pressed = k->get_shift(); + bool shift_pressed = k->is_shift_pressed(); // Remove shift or else actions will not match. Use above variable for selection. - k->set_shift(false); + k->set_shift_pressed(false); if (k->is_action("ui_text_caret_word_left", true)) { _move_caret_left(shift_pressed, true); @@ -490,7 +490,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { // Allow unicode handling if: // * No Modifiers are pressed (except shift) - bool allow_unicode_handling = !(k->get_command() || k->get_control() || k->get_alt() || k->get_metakey()); + bool allow_unicode_handling = !(k->is_command_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); if (allow_unicode_handling && editable && k->get_unicode() >= 32) { // Handle Unicode (if no modifiers active) diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 44df8eafdc..2100707d2d 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1282,16 +1282,16 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo if (code == 0) { code = k->get_unicode(); } - if (k->get_control()) { + if (k->is_ctrl_pressed()) { code |= KEY_MASK_CTRL; } - if (k->get_alt()) { + if (k->is_alt_pressed()) { code |= KEY_MASK_ALT; } - if (k->get_metakey()) { + if (k->is_meta_pressed()) { code |= KEY_MASK_META; } - if (k->get_shift()) { + if (k->is_shift_pressed()) { code |= KEY_MASK_SHIFT; } } diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 67dcf458b0..46db4a3c2f 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -98,7 +98,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { if (mb.is_valid()) { if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { // only horizontal is enabled, scroll horizontally - if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) { + if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) { h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb->get_factor()); } else if (v_scroll->is_visible_in_tree()) { v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8 * mb->get_factor()); @@ -107,7 +107,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { // only horizontal is enabled, scroll horizontally - if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->get_shift())) { + if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) { h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb->get_factor()); } else if (v_scroll->is_visible()) { v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8 * mb->get_factor()); diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index 6cbc5890ce..471b26be75 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -127,7 +127,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->is_command_pressed()) { if (scrolling_enabled && buttons_visible) { if (offset > 0) { offset--; @@ -136,7 +136,7 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { } } - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) { + if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->is_command_pressed()) { if (scrolling_enabled && buttons_visible) { if (missing_right) { offset++; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index c924f89709..e305c6210d 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2914,17 +2914,25 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } if (mb->is_pressed()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->get_command()) { - if (mb->get_shift()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->is_command_pressed()) { + if (mb->is_shift_pressed()) { h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); + } else if (mb->is_alt_pressed()) { + // Scroll 5 times as fast as normal (like in Visual Studio Code). + _scroll_up(15 * mb->get_factor()); } else if (v_scroll->is_visible()) { + // Scroll 3 lines. _scroll_up(3 * mb->get_factor()); } } - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->get_command()) { - if (mb->get_shift()) { + if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->is_command_pressed()) { + if (mb->is_shift_pressed()) { h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor())); + } else if (mb->is_alt_pressed()) { + // Scroll 5 times as fast as normal (like in Visual Studio Code). + _scroll_down(15 * mb->get_factor()); } else if (v_scroll->is_visible()) { + // Scroll 3 lines. _scroll_down(3 * mb->get_factor()); } } @@ -2977,7 +2985,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { cursor_set_line(row, false, false); cursor_set_column(col); - if (mb->get_shift() && (cursor.column != prev_col || cursor.line != prev_line)) { + if (mb->is_shift_pressed() && (cursor.column != prev_col || cursor.line != prev_line)) { if (!selection.active) { selection.active = true; selection.selecting_mode = SelectionMode::SELECTION_MODE_POINTER; @@ -3073,7 +3081,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } else { if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { - if (mb->get_command() && highlighted_word != String()) { + if (mb->is_command_pressed() && highlighted_word != String()) { int row, col; _get_mouse_pos(Point2i(mpos.x, mpos.y), row, col); @@ -3116,7 +3124,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { mpos.x = get_size().x - mpos.x; } if (select_identifiers_enabled) { - if (!dragging_minimap && !dragging_selection && mm->get_command() && mm->get_button_mask() == 0) { + if (!dragging_minimap && !dragging_selection && mm->is_command_pressed() && mm->get_button_mask() == 0) { String new_word = get_word_at_pos(mpos); if (new_word != highlighted_word) { emit_signal("symbol_validate", new_word); @@ -3165,7 +3173,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { #ifdef OSX_ENABLED if (k->get_keycode() == KEY_META) { #else - if (k->get_keycode() == KEY_CONTROL) { + if (k->get_keycode() == KEY_CTRL) { #endif if (select_identifiers_enabled) { if (k->is_pressed() && !dragging_minimap && !dragging_selection) { @@ -3183,7 +3191,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } // If a modifier has been pressed, and nothing else, return. - if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) { + if (k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) { return; } @@ -3191,7 +3199,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { // Allow unicode handling if: // * No Modifiers are pressed (except shift) - bool allow_unicode_handling = !(k->get_command() || k->get_control() || k->get_alt() || k->get_metakey()); + bool allow_unicode_handling = !(k->is_command_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); // Save here for insert mode, just in case it is cleared in the following section. bool had_selection = selection.active; @@ -3436,9 +3444,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { // CURSOR MOVEMENT k = k->duplicate(); - bool shift_pressed = k->get_shift(); + bool shift_pressed = k->is_shift_pressed(); // Remove shift or else actions will not match. Use above variable for selection. - k->set_shift(false); + k->set_shift_pressed(false); // CURSOR MOVEMENT - LEFT, RIGHT. if (k->is_action("ui_text_caret_word_left", true)) { @@ -6845,6 +6853,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_line_count"), &TextEdit::get_line_count); ClassDB::bind_method(D_METHOD("get_text"), &TextEdit::get_text); ClassDB::bind_method(D_METHOD("get_line", "line"), &TextEdit::get_line); + ClassDB::bind_method(D_METHOD("get_visible_line_count"), &TextEdit::get_total_visible_rows); ClassDB::bind_method(D_METHOD("set_line", "line", "new_text"), &TextEdit::set_line); ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &TextEdit::set_structured_text_bidi_override); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 7028d7aed4..2f78736a12 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -47,36 +47,6 @@ #include <limits.h> -void TreeItem::move_to_top() { - if (!parent || parent->children == this) { - return; //already on top - } - TreeItem *prev = get_prev(); - prev->next = next; - next = parent->children; - parent->children = this; -} - -void TreeItem::move_to_bottom() { - if (!parent || !next) { - return; - } - - TreeItem *prev = get_prev(); - TreeItem *last = next; - while (last->next) { - last = last->next; - } - - if (prev) { - prev->next = next; - } else { - parent->children = next; - } - last->next = this; - next = nullptr; -} - Size2 TreeItem::Cell::get_icon_size() const { if (icon.is_null()) { return Size2(); @@ -118,6 +88,54 @@ void TreeItem::_cell_deselected(int p_cell) { tree->item_deselected(p_cell, this); } +void TreeItem::_change_tree(Tree *p_tree) { + if (p_tree == tree) { + return; + } + + TreeItem *c = first_child; + while (c) { + c->_change_tree(p_tree); + c = c->next; + } + + if (tree && tree->root == this) { + tree->root = nullptr; + } + + if (tree && tree->popup_edited_item == this) { + tree->popup_edited_item = nullptr; + tree->pressing_for_editor = false; + } + + if (tree && tree->cache.hover_item == this) { + tree->cache.hover_item = nullptr; + } + + if (tree && tree->selected_item == this) { + tree->selected_item = nullptr; + } + + if (tree && tree->drop_mode_over == this) { + tree->drop_mode_over = nullptr; + } + + if (tree && tree->single_select_defer == this) { + tree->single_select_defer = nullptr; + } + + if (tree && tree->edited_item == this) { + tree->edited_item = nullptr; + tree->pressing_for_editor = false; + } + + tree = p_tree; + + if (tree) { + cells.resize(tree->columns.size()); + } +} + /* cell mode */ void TreeItem::set_cell_mode(int p_column, TreeCellMode p_mode) { ERR_FAIL_INDEX(p_column, cells.size()); @@ -427,19 +445,73 @@ int TreeItem::get_custom_minimum_height() const { return custom_min_height; } +/* Item manipulation */ + +TreeItem *TreeItem::create_child(int p_idx) { + TreeItem *ti = memnew(TreeItem(tree)); + if (tree) { + ti->cells.resize(tree->columns.size()); + } + + TreeItem *l_prev = nullptr; + TreeItem *c = first_child; + int idx = 0; + + while (c) { + if (idx++ == p_idx) { + c->prev = ti; + ti->next = c; + break; + } + l_prev = c; + c = c->next; + } + + if (l_prev) { + l_prev->next = ti; + ti->prev = l_prev; + if (!children_cache.is_empty()) { + if (ti->next) { + children_cache.insert(p_idx, ti); + } else { + children_cache.append(ti); + } + } + } else { + first_child = ti; + if (!children_cache.is_empty()) { + children_cache.insert(0, ti); + } + } + + ti->parent = this; + + return ti; +} + +Tree *TreeItem::get_tree() { + return tree; +} + TreeItem *TreeItem::get_next() { return next; } TreeItem *TreeItem::get_prev() { - if (!parent || parent->children == this) { - return nullptr; + if (prev) { + return prev; } - TreeItem *prev = parent->children; - while (prev && prev->next != this) { - prev = prev->next; + if (!parent || parent->first_child == this) { + return nullptr; } + // This is an edge case + TreeItem *l_prev = parent->first_child; + while (l_prev && l_prev->next != this) { + l_prev = l_prev->next; + } + + prev = l_prev; return prev; } @@ -448,8 +520,8 @@ TreeItem *TreeItem::get_parent() { return parent; } -TreeItem *TreeItem::get_children() { - return children; +TreeItem *TreeItem::get_first_child() { + return first_child; } TreeItem *TreeItem::get_prev_visible(bool p_wrap) { @@ -475,10 +547,10 @@ TreeItem *TreeItem::get_prev_visible(bool p_wrap) { } } else { current = prev; - while (!current->collapsed && current->children) { + while (!current->collapsed && current->first_child) { //go to the very end - current = current->children; + current = current->first_child; while (current->next) { current = current->next; } @@ -491,8 +563,8 @@ TreeItem *TreeItem::get_prev_visible(bool p_wrap) { TreeItem *TreeItem::get_next_visible(bool p_wrap) { TreeItem *current = this; - if (!current->collapsed && current->children) { - current = current->children; + if (!current->collapsed && current->first_child) { + current = current->first_child; } else if (current->next) { current = current->next; @@ -515,24 +587,136 @@ TreeItem *TreeItem::get_next_visible(bool p_wrap) { return current; } -void TreeItem::remove_child(TreeItem *p_item) { +TreeItem *TreeItem::get_child(int p_idx) { + _create_children_cache(); + ERR_FAIL_INDEX_V(p_idx, children_cache.size(), nullptr); + return children_cache.get(p_idx); +} + +int TreeItem::get_child_count() { + _create_children_cache(); + return children_cache.size(); +} + +Array TreeItem::get_children() { + int size = get_child_count(); + Array arr; + arr.resize(size); + for (int i = 0; i < size; i++) { + arr[i] = children_cache[i]; + } + + return arr; +} + +int TreeItem::get_index() { + int idx = 0; + TreeItem *c = this; + + while (c) { + c = c->get_prev(); + idx++; + } + return idx - 1; +} + +void TreeItem::move_before(TreeItem *p_item) { ERR_FAIL_NULL(p_item); - TreeItem **c = &children; + ERR_FAIL_COND(is_root); + ERR_FAIL_COND(!p_item->parent); - while (*c) { - if ((*c) == p_item) { - TreeItem *aux = *c; + if (p_item == this) { + return; + } - *c = (*c)->next; + TreeItem *p = p_item->parent; + while (p) { + ERR_FAIL_COND_MSG(p == this, "Can't move to a descendant"); + p = p->parent; + } - aux->parent = nullptr; - return; - } + Tree *old_tree = tree; + _unlink_from_tree(); + _change_tree(p_item->tree); - c = &(*c)->next; + parent = p_item->parent; + + TreeItem *item_prev = p_item->get_prev(); + if (item_prev) { + item_prev->next = this; + parent->children_cache.clear(); + } else { + parent->first_child = this; + parent->children_cache.insert(0, this); } - ERR_FAIL(); + prev = item_prev; + next = p_item; + p_item->prev = this; + + if (old_tree && old_tree != tree) { + old_tree->update(); + } + + if (tree) { + tree->update(); + } +} + +void TreeItem::move_after(TreeItem *p_item) { + ERR_FAIL_NULL(p_item); + ERR_FAIL_COND(is_root); + ERR_FAIL_COND(!p_item->parent); + + if (p_item == this) { + return; + } + + TreeItem *p = p_item->parent; + while (p) { + ERR_FAIL_COND_MSG(p == this, "Can't move to a descendant"); + p = p->parent; + } + + Tree *old_tree = tree; + _unlink_from_tree(); + _change_tree(p_item->tree); + + if (p_item->next) { + p_item->next->prev = this; + } + parent = p_item->parent; + prev = p_item; + next = p_item->next; + p_item->next = this; + + if (next) { + parent->children_cache.clear(); + } else { + parent->children_cache.append(this); + } + + if (old_tree && old_tree != tree) { + old_tree->update(); + } + + if (tree) { + tree->update(); + } +} + +void TreeItem::remove_child(TreeItem *p_item) { + ERR_FAIL_NULL(p_item); + ERR_FAIL_COND(p_item->parent != this); + + p_item->_unlink_from_tree(); + p_item->prev = nullptr; + p_item->next = nullptr; + p_item->parent = nullptr; + + if (tree) { + tree->update(); + } } void TreeItem::set_selectable(int p_column, bool p_selectable) { @@ -785,7 +969,7 @@ void recursive_call_aux(TreeItem *p_item, const StringName &p_method, const Vari return; } p_item->call(p_method, p_args, p_argcount, r_error); - TreeItem *c = p_item->get_children(); + TreeItem *c = p_item->get_first_child(); while (c) { recursive_call_aux(c, p_method, p_args, p_argcount, r_error); c = c->get_next(); @@ -855,16 +1039,6 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_custom_minimum_height", "height"), &TreeItem::set_custom_minimum_height); ClassDB::bind_method(D_METHOD("get_custom_minimum_height"), &TreeItem::get_custom_minimum_height); - ClassDB::bind_method(D_METHOD("get_next"), &TreeItem::get_next); - ClassDB::bind_method(D_METHOD("get_prev"), &TreeItem::get_prev); - ClassDB::bind_method(D_METHOD("get_parent"), &TreeItem::get_parent); - ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children); - - ClassDB::bind_method(D_METHOD("get_next_visible", "wrap"), &TreeItem::get_next_visible, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("get_prev_visible", "wrap"), &TreeItem::get_prev_visible, DEFVAL(false)); - - ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child); - ClassDB::bind_method(D_METHOD("set_selectable", "column", "selectable"), &TreeItem::set_selectable); ClassDB::bind_method(D_METHOD("is_selectable", "column"), &TreeItem::is_selectable); @@ -895,19 +1069,38 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_button_disabled", "column", "button_idx", "disabled"), &TreeItem::set_button_disabled); ClassDB::bind_method(D_METHOD("is_button_disabled", "column", "button_idx"), &TreeItem::is_button_disabled); - ClassDB::bind_method(D_METHOD("set_expand_right", "column", "enable"), &TreeItem::set_expand_right); - ClassDB::bind_method(D_METHOD("get_expand_right", "column"), &TreeItem::get_expand_right); - ClassDB::bind_method(D_METHOD("set_tooltip", "column", "tooltip"), &TreeItem::set_tooltip); ClassDB::bind_method(D_METHOD("get_tooltip", "column"), &TreeItem::get_tooltip); ClassDB::bind_method(D_METHOD("set_text_align", "column", "text_align"), &TreeItem::set_text_align); ClassDB::bind_method(D_METHOD("get_text_align", "column"), &TreeItem::get_text_align); - ClassDB::bind_method(D_METHOD("move_to_top"), &TreeItem::move_to_top); - ClassDB::bind_method(D_METHOD("move_to_bottom"), &TreeItem::move_to_bottom); + + ClassDB::bind_method(D_METHOD("set_expand_right", "column", "enable"), &TreeItem::set_expand_right); + ClassDB::bind_method(D_METHOD("get_expand_right", "column"), &TreeItem::get_expand_right); ClassDB::bind_method(D_METHOD("set_disable_folding", "disable"), &TreeItem::set_disable_folding); ClassDB::bind_method(D_METHOD("is_folding_disabled"), &TreeItem::is_folding_disabled); + ClassDB::bind_method(D_METHOD("create_child", "idx"), &TreeItem::create_child, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("get_tree"), &TreeItem::get_tree); + + ClassDB::bind_method(D_METHOD("get_next"), &TreeItem::get_next); + ClassDB::bind_method(D_METHOD("get_prev"), &TreeItem::get_prev); + ClassDB::bind_method(D_METHOD("get_parent"), &TreeItem::get_parent); + ClassDB::bind_method(D_METHOD("get_first_child"), &TreeItem::get_first_child); + + ClassDB::bind_method(D_METHOD("get_next_visible", "wrap"), &TreeItem::get_next_visible, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_prev_visible", "wrap"), &TreeItem::get_prev_visible, DEFVAL(false)); + + ClassDB::bind_method(D_METHOD("get_child", "idx"), &TreeItem::get_child); + ClassDB::bind_method(D_METHOD("get_child_count"), &TreeItem::get_child_count); + ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children); + ClassDB::bind_method(D_METHOD("get_index"), &TreeItem::get_index); + + ClassDB::bind_method(D_METHOD("move_before", "item"), &TreeItem::_move_before); + ClassDB::bind_method(D_METHOD("move_after", "item"), &TreeItem::_move_after); + + ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child); + { MethodInfo mi; mi.name = "call_recursive"; @@ -932,7 +1125,7 @@ void TreeItem::_bind_methods() { } void TreeItem::clear_children() { - TreeItem *c = children; + TreeItem *c = first_child; while (c) { TreeItem *aux = c; c = c->get_next(); @@ -940,56 +1133,18 @@ void TreeItem::clear_children() { memdelete(aux); } - children = nullptr; + first_child = nullptr; }; TreeItem::TreeItem(Tree *p_tree) { tree = p_tree; - collapsed = false; - disable_folding = false; - custom_min_height = 0; - - parent = nullptr; // parent item - next = nullptr; // next in list - children = nullptr; //child items } TreeItem::~TreeItem() { + _unlink_from_tree(); + prev = nullptr; clear_children(); - - if (parent) { - parent->remove_child(this); - } - - if (tree && tree->root == this) { - tree->root = nullptr; - } - - if (tree && tree->popup_edited_item == this) { - tree->popup_edited_item = nullptr; - tree->pressing_for_editor = false; - } - - if (tree && tree->cache.hover_item == this) { - tree->cache.hover_item = nullptr; - } - - if (tree && tree->selected_item == this) { - tree->selected_item = nullptr; - } - - if (tree && tree->drop_mode_over == this) { - tree->drop_mode_over = nullptr; - } - - if (tree && tree->single_select_defer == this) { - tree->single_select_defer = nullptr; - } - - if (tree && tree->edited_item == this) { - tree->edited_item = nullptr; - tree->pressing_for_editor = false; - } + _change_tree(nullptr); } /**********************************************/ @@ -1116,7 +1271,7 @@ int Tree::get_item_height(TreeItem *p_item) const { if (!p_item->collapsed) { /* if not collapsed, check the children */ - TreeItem *c = p_item->children; + TreeItem *c = p_item->first_child; while (c) { height += get_item_height(c); @@ -1263,7 +1418,7 @@ void Tree::update_item_cache(TreeItem *p_item) { update_item_cell(p_item, i); } - TreeItem *c = p_item->children; + TreeItem *c = p_item->first_child; while (c) { update_item_cache(c); c = c->next; @@ -1430,7 +1585,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (drop_mode_flags && drop_mode_over == p_item) { Rect2 r = cell_rect; - bool has_parent = p_item->get_children() != nullptr; + bool has_parent = p_item->get_first_child() != nullptr; if (rtl) { r.position.x = get_size().width - r.position.x - r.size.x; } @@ -1626,7 +1781,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } } - if (!p_item->disable_folding && !hide_folding && p_item->children) { //has children, draw the guide box + if (!p_item->disable_folding && !hide_folding && p_item->first_child) { //has children, draw the guide box Ref<Texture2D> arrow; @@ -1656,7 +1811,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (!p_item->collapsed) { /* if not collapsed, check the children */ - TreeItem *c = p_item->children; + TreeItem *c = p_item->first_child; int prev_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y; @@ -1666,7 +1821,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 int parent_ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin); Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs; - if (c->get_children() != nullptr) { + if (c->get_first_child() != nullptr) { root_pos -= Point2i(cache.arrow->get_width(), 0); } @@ -1723,8 +1878,8 @@ int Tree::_count_selected_items(TreeItem *p_from) const { } } - if (p_from->get_children()) { - count += _count_selected_items(p_from->get_children()); + if (p_from->get_first_child()) { + count += _count_selected_items(p_from->get_first_child()); } if (p_from->get_next()) { @@ -1812,7 +1967,7 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c *r_in_range = false; } - TreeItem *c = p_current->children; + TreeItem *c = p_current->first_child; while (c) { select_single_item(p_selected, c, p_col, p_prev, r_in_range, p_current->is_collapsed() || p_force_deselect); @@ -1839,7 +1994,6 @@ void Tree::_range_click_timeout() { click_handled = false; Ref<InputEventMouseButton> mb; mb.instance(); - ; propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case) blocked++; @@ -1879,7 +2033,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool } if (!p_item->disable_folding && !hide_folding && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) { - if (p_item->children) { + if (p_item->first_child) { p_item->set_collapsed(!p_item->is_collapsed()); } @@ -1926,7 +2080,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool x -= cache.hseparation; } - if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_children()) { + if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_first_child()) { p_item->set_collapsed(!p_item->is_collapsed()); return -1; //collapse/uncollapse because nothing can be done with item } @@ -1971,7 +2125,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool return -1; } - if (select_mode == SELECT_MULTI && p_mod->get_command() && c.selectable) { + if (select_mode == SELECT_MULTI && p_mod->is_command_pressed() && c.selectable) { if (!c.selected || p_button == MOUSE_BUTTON_RIGHT) { p_item->select(col); emit_signal("multi_selected", p_item, col, true); @@ -1988,7 +2142,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool } else { if (c.selectable) { - if (select_mode == SELECT_MULTI && p_mod->get_shift() && selected_item && selected_item != p_item) { + if (select_mode == SELECT_MULTI && p_mod->is_shift_pressed() && selected_item && selected_item != p_item) { bool inrange = false; select_single_item(p_item, root, col, selected_item, &inrange); @@ -2164,7 +2318,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool if (!p_item->collapsed) { /* if not collapsed, check the children */ - TreeItem *c = p_item->children; + TreeItem *c = p_item->first_child; while (c) { int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, p_double_click, c, p_button, p_mod); @@ -2270,7 +2424,7 @@ void Tree::popup_select(int p_option) { void Tree::_go_left() { if (selected_col == 0) { - if (selected_item->get_children() != nullptr && !selected_item->is_collapsed()) { + if (selected_item->get_first_child() != nullptr && !selected_item->is_collapsed()) { selected_item->set_collapsed(true); } else { if (columns.size() == 1) { // goto parent with one column @@ -2298,7 +2452,7 @@ void Tree::_go_left() { void Tree::_go_right() { if (selected_col == (columns.size() - 1)) { - if (selected_item->get_children() != nullptr && selected_item->is_collapsed()) { + if (selected_item->get_first_child() != nullptr && selected_item->is_collapsed()) { selected_item->set_collapsed(false); } else if (selected_item->get_next_visible()) { selected_col = 0; @@ -2406,7 +2560,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { Ref<InputEventKey> k = p_event; - bool is_command = k.is_valid() && k->get_command(); + bool is_command = k.is_valid() && k->is_command_pressed(); if (p_event->is_action("ui_right") && p_event->is_pressed()) { if (!cursor_can_exit_tree) { accept_event(); @@ -2415,9 +2569,9 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { if (!selected_item || select_mode == SELECT_ROW || selected_col > (columns.size() - 1)) { return; } - if (k.is_valid() && k->get_alt()) { + if (k.is_valid() && k->is_alt_pressed()) { selected_item->set_collapsed(false); - TreeItem *next = selected_item->get_children(); + TreeItem *next = selected_item->get_first_child(); while (next && next != selected_item->next) { next->set_collapsed(false); next = next->get_next_visible(); @@ -2434,9 +2588,9 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { return; } - if (k.is_valid() && k->get_alt()) { + if (k.is_valid() && k->is_alt_pressed()) { selected_item->set_collapsed(true); - TreeItem *next = selected_item->get_children(); + TreeItem *next = selected_item->get_first_child(); while (next && next != selected_item->next) { next->set_collapsed(true); next = next->get_next_visible(); @@ -2564,7 +2718,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { if (!k->is_pressed()) { return; } - if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) { + if (k->is_command_pressed() || (k->is_shift_pressed() && k->get_unicode() == 0) || k->is_meta_pressed()) { return; } if (!root) { @@ -2834,7 +2988,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { break; } } - if (!root || (!root->get_children() && hide_root)) { + if (!root || (!root->get_first_child() && hide_root)) { if (b->get_button_index() == MOUSE_BUTTON_RIGHT && allow_rmb_select) { emit_signal("empty_tree_rmb_selected", get_local_mouse_position()); } @@ -2880,7 +3034,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { } if (b->get_button_index() == MOUSE_BUTTON_LEFT) { - if (get_item_at_position(b->get_position()) == nullptr && !b->get_shift() && !b->get_control() && !b->get_command()) { + if (get_item_at_position(b->get_position()) == nullptr && !b->is_shift_pressed() && !b->is_ctrl_pressed() && !b->is_command_pressed()) { emit_signal("nothing_selected"); } } @@ -3269,38 +3423,15 @@ TreeItem *Tree::create_item(TreeItem *p_parent, int p_idx) { TreeItem *ti = nullptr; if (p_parent) { - // Append or insert a new item to the given parent. - ti = memnew(TreeItem(this)); - ERR_FAIL_COND_V(!ti, nullptr); - ti->cells.resize(columns.size()); - - TreeItem *prev = nullptr; - TreeItem *c = p_parent->children; - int idx = 0; - - while (c) { - if (idx++ == p_idx) { - ti->next = c; - break; - } - prev = c; - c = c->next; - } - - if (prev) { - prev->next = ti; - } else { - p_parent->children = ti; - } - ti->parent = p_parent; - + ERR_FAIL_COND_V_MSG(p_parent->tree != this, nullptr, "A different tree owns the given parent"); + ti = p_parent->create_child(p_idx); } else { if (!root) { // No root exists, make the given item the new root. ti = memnew(TreeItem(this)); ERR_FAIL_COND_V(!ti, nullptr); ti->cells.resize(columns.size()); - + ti->is_root = true; root = ti; } else { // Root exists, append or insert to root. @@ -3321,8 +3452,8 @@ TreeItem *Tree::get_last_item() { while (last) { if (last->next) { last = last->next; - } else if (last->children) { - last = last->children; + } else if (last->first_child) { + last = last->first_child; } else { break; } @@ -3491,8 +3622,8 @@ TreeItem *Tree::get_next_selected(TreeItem *p_item) { if (!p_item) { p_item = root; } else { - if (p_item->children) { - p_item = p_item->children; + if (p_item->first_child) { + p_item = p_item->first_child; } else if (p_item->next) { p_item = p_item->next; @@ -3561,7 +3692,7 @@ int Tree::get_column_width(int p_column) const { void Tree::propagate_set_columns(TreeItem *p_item) { p_item->cells.resize(columns.size()); - TreeItem *c = p_item->get_children(); + TreeItem *c = p_item->get_first_child(); while (c) { propagate_set_columns(c); c = c->next; @@ -3611,8 +3742,8 @@ int Tree::get_item_offset(TreeItem *p_item) const { ofs += cache.vseparation; } - if (it->children && !it->collapsed) { - it = it->children; + if (it->first_child && !it->collapsed) { + it = it->first_child; } else if (it->next) { it = it->next; @@ -3935,7 +4066,7 @@ TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_ return nullptr; // do not try children, it's collapsed } - TreeItem *n = p_item->get_children(); + TreeItem *n = p_item->get_first_child(); while (n) { int ch; TreeItem *r = _find_item_at_pos(n, pos, r_column, ch, section); @@ -4334,6 +4465,8 @@ Tree::Tree() { set_mouse_filter(MOUSE_FILTER_STOP); set_clip_contents(true); + + update_cache(); } Tree::~Tree() { diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 6d36f0df7f..9dbfd93082 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -122,14 +122,18 @@ private: Vector<Cell> cells; - bool collapsed; // won't show children - bool disable_folding; - int custom_min_height; + bool collapsed = false; // won't show children + bool disable_folding = false; + int custom_min_height = 0; - TreeItem *parent; // parent item - TreeItem *next; // next in list - TreeItem *children; //child items - Tree *tree; //tree (for reference) + TreeItem *parent = nullptr; // parent item + TreeItem *prev = nullptr; // previous in list + TreeItem *next = nullptr; // next in list + TreeItem *first_child = nullptr; + + Vector<TreeItem *> children_cache; + bool is_root = false; // for tree root + Tree *tree; // tree (for reference) TreeItem(Tree *p_tree); @@ -138,9 +142,40 @@ private: void _cell_selected(int p_cell); void _cell_deselected(int p_cell); + void _change_tree(Tree *p_tree); + + _FORCE_INLINE_ void _create_children_cache() { + if (children_cache.is_empty()) { + TreeItem *c = first_child; + while (c) { + children_cache.append(c); + c = c->next; + } + } + } + + _FORCE_INLINE_ void _unlink_from_tree() { + TreeItem *p = get_prev(); + if (p) { + p->next = next; + } + if (next) { + next->prev = p; + } + if (parent) { + if (!parent->children_cache.is_empty()) { + parent->children_cache.remove(get_index()); + } + if (parent->first_child == this) { + parent->first_child = next; + } + } + } + protected: static void _bind_methods(); - //bind helpers + + // Bind helpers Dictionary _get_range_config(int p_column) { Dictionary d; double min = 0.0, max = 0.0, step = 0.0; @@ -156,6 +191,13 @@ protected: remove_child(Object::cast_to<TreeItem>(p_child)); } + void _move_before(Object *p_item) { + move_before(Object::cast_to<TreeItem>(p_item)); + } + void _move_after(Object *p_item) { + move_after(Object::cast_to<TreeItem>(p_item)); + } + Variant _call_recursive_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); public: @@ -234,16 +276,6 @@ public: void set_custom_minimum_height(int p_height); int get_custom_minimum_height() const; - TreeItem *get_prev(); - TreeItem *get_next(); - TreeItem *get_parent(); - TreeItem *get_children(); - - TreeItem *get_prev_visible(bool p_wrap = false); - TreeItem *get_next_visible(bool p_wrap = false); - - void remove_child(TreeItem *p_item); - void set_selectable(int p_column, bool p_selectable); bool is_selectable(int p_column) const; @@ -269,22 +301,43 @@ public: void set_tooltip(int p_column, const String &p_tooltip); String get_tooltip(int p_column) const; - void clear_children(); - void set_text_align(int p_column, TextAlign p_align); TextAlign get_text_align(int p_column) const; void set_expand_right(int p_column, bool p_enable); bool get_expand_right(int p_column) const; - void move_to_top(); - void move_to_bottom(); - void set_disable_folding(bool p_disable); bool is_folding_disabled() const; + /* Item manipulation */ + + TreeItem *create_child(int p_idx = -1); + + Tree *get_tree(); + + TreeItem *get_prev(); + TreeItem *get_next(); + TreeItem *get_parent(); + TreeItem *get_first_child(); + + TreeItem *get_prev_visible(bool p_wrap = false); + TreeItem *get_next_visible(bool p_wrap = false); + + TreeItem *get_child(int p_idx); + int get_child_count(); + Array get_children(); + int get_index(); + + void move_before(TreeItem *p_item); + void move_after(TreeItem *p_item); + + void remove_child(TreeItem *p_item); + void call_recursive(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error); + void clear_children(); + ~TreeItem(); }; diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index fa98a10a26..d594c6c8b6 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -1414,7 +1414,7 @@ CanvasItem::~CanvasItem() { /////////////////////////////////////////////////////////////////// void CanvasTexture::set_diffuse_texture(const Ref<Texture2D> &p_diffuse) { - ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_diffuse.ptr()) != nullptr, "Cant self-assign a CanvasTexture"); + ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_diffuse.ptr()) != nullptr, "Can't self-assign a CanvasTexture"); diffuse_texture = p_diffuse; RID tex_rid = diffuse_texture.is_valid() ? diffuse_texture->get_rid() : RID(); @@ -1426,7 +1426,7 @@ Ref<Texture2D> CanvasTexture::get_diffuse_texture() const { } void CanvasTexture::set_normal_texture(const Ref<Texture2D> &p_normal) { - ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_normal.ptr()) != nullptr, "Cant self-assign a CanvasTexture"); + ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_normal.ptr()) != nullptr, "Can't self-assign a CanvasTexture"); normal_texture = p_normal; RID tex_rid = normal_texture.is_valid() ? normal_texture->get_rid() : RID(); RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_NORMAL, tex_rid); @@ -1436,7 +1436,7 @@ Ref<Texture2D> CanvasTexture::get_normal_texture() const { } void CanvasTexture::set_specular_texture(const Ref<Texture2D> &p_specular) { - ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_specular.ptr()) != nullptr, "Cant self-assign a CanvasTexture"); + ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_specular.ptr()) != nullptr, "Can't self-assign a CanvasTexture"); specular_texture = p_specular; RID tex_rid = specular_texture.is_valid() ? specular_texture->get_rid() : RID(); RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_SPECULAR, tex_rid); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 387af3703b..3e08f86fc9 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1267,7 +1267,7 @@ void SceneTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled"); ADD_SIGNAL(MethodInfo("tree_changed")); - ADD_SIGNAL(MethodInfo("tree_process_mode_changed")); //editor only signal, but due to API hash it cant be removed in run-time + ADD_SIGNAL(MethodInfo("tree_process_mode_changed")); //editor only signal, but due to API hash it can't be removed in run-time ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index b94a818b06..62e1223fb0 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -617,10 +617,10 @@ void Viewport::_process_picking() { mm->set_device(InputEvent::DEVICE_ID_INTERNAL); mm->set_global_position(physics_last_mousepos); mm->set_position(physics_last_mousepos); - mm->set_alt(physics_last_mouse_state.alt); - mm->set_shift(physics_last_mouse_state.shift); - mm->set_control(physics_last_mouse_state.control); - mm->set_metakey(physics_last_mouse_state.meta); + mm->set_alt_pressed(physics_last_mouse_state.alt); + mm->set_shift_pressed(physics_last_mouse_state.shift); + mm->set_ctrl_pressed(physics_last_mouse_state.control); + mm->set_meta_pressed(physics_last_mouse_state.meta); mm->set_button_mask(physics_last_mouse_state.mouse_mask); physics_picking_events.push_back(mm); } @@ -641,10 +641,10 @@ void Viewport::_process_picking() { physics_has_last_mousepos = true; physics_last_mousepos = pos; - physics_last_mouse_state.alt = mm->get_alt(); - physics_last_mouse_state.shift = mm->get_shift(); - physics_last_mouse_state.control = mm->get_control(); - physics_last_mouse_state.meta = mm->get_metakey(); + physics_last_mouse_state.alt = mm->is_alt_pressed(); + physics_last_mouse_state.shift = mm->is_shift_pressed(); + physics_last_mouse_state.control = mm->is_ctrl_pressed(); + physics_last_mouse_state.meta = mm->is_meta_pressed(); physics_last_mouse_state.mouse_mask = mm->get_button_mask(); } @@ -656,10 +656,10 @@ void Viewport::_process_picking() { physics_has_last_mousepos = true; physics_last_mousepos = pos; - physics_last_mouse_state.alt = mb->get_alt(); - physics_last_mouse_state.shift = mb->get_shift(); - physics_last_mouse_state.control = mb->get_control(); - physics_last_mouse_state.meta = mb->get_metakey(); + physics_last_mouse_state.alt = mb->is_alt_pressed(); + physics_last_mouse_state.shift = mb->is_shift_pressed(); + physics_last_mouse_state.control = mb->is_ctrl_pressed(); + physics_last_mouse_state.meta = mb->is_meta_pressed(); if (mb->is_pressed()) { physics_last_mouse_state.mouse_mask |= (1 << (mb->get_button_index() - 1)); @@ -676,10 +676,10 @@ void Viewport::_process_picking() { Ref<InputEventKey> k = ev; if (k.is_valid()) { //only for mask - physics_last_mouse_state.alt = k->get_alt(); - physics_last_mouse_state.shift = k->get_shift(); - physics_last_mouse_state.control = k->get_control(); - physics_last_mouse_state.meta = k->get_metakey(); + physics_last_mouse_state.alt = k->is_alt_pressed(); + physics_last_mouse_state.shift = k->is_shift_pressed(); + physics_last_mouse_state.control = k->is_ctrl_pressed(); + physics_last_mouse_state.meta = k->is_meta_pressed(); continue; } @@ -2402,10 +2402,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Control *from = gui.key_focus ? gui.key_focus : nullptr; //hmm //keyboard focus - //if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) { + //if (from && p_event->is_pressed() && !p_event->is_alt_pressed() && !p_event->is_meta_pressed() && !p_event->key->is_command_pressed()) { Ref<InputEventKey> k = p_event; //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/right/etc> is handled here when it shouldn't be. - bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey()); + bool mods = k.is_valid() && (k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_shift_pressed() || k->is_meta_pressed()); if (from && p_event->is_pressed()) { Control *next = nullptr; diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 2e88e1251d..a55df4fbc2 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -231,7 +231,7 @@ private: Transform2D global_canvas_transform; Transform2D stretch_transform; - Size2i size; + Size2i size = Size2i(512, 512); Size2i size_2d_override; bool size_allocated = false; bool use_xr = false; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index bacb0030bb..b7bc2a83c5 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1169,64 +1169,96 @@ Ref<Theme> Window::get_theme() const { return theme; } -Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::get_icons(theme_owner, theme_owner_window, p_name, type); +void Window::set_theme_custom_type(const StringName &p_theme_type) { + theme_custom_type = p_theme_type; + Control::_propagate_theme_changed(this, theme_owner, theme_owner_window); } -Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::get_styleboxs(theme_owner, theme_owner_window, p_name, type); +StringName Window::get_theme_custom_type() const { + return theme_custom_type; } -Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::get_fonts(theme_owner, theme_owner_window, p_name, type); +void Window::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_custom_type) { + if (theme_custom_type != StringName()) { + p_list->push_back(theme_custom_type); + } + Theme::get_type_dependencies(get_class_name(), p_list); + } else { + Theme::get_type_dependencies(p_theme_type, p_list); + } +} + +Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::get_theme_item_in_types<Ref<Texture2D>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types); } -int Window::get_theme_font_size(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::get_font_sizes(theme_owner, theme_owner_window, p_name, type); +Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::get_theme_item_in_types<Ref<StyleBox>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types); } -Color Window::get_theme_color(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::get_colors(theme_owner, theme_owner_window, p_name, type); +Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::get_theme_item_in_types<Ref<Font>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types); } -int Window::get_theme_constant(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::get_constants(theme_owner, theme_owner_window, p_name, type); +int Window::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::get_theme_item_in_types<int>(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types); } -bool Window::has_theme_icon(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::has_icons(theme_owner, theme_owner_window, p_name, type); +Color Window::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::get_theme_item_in_types<Color>(theme_owner, theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types); } -bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::has_styleboxs(theme_owner, theme_owner_window, p_name, type); +int Window::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::get_theme_item_in_types<int>(theme_owner, theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types); } -bool Window::has_theme_font(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::has_fonts(theme_owner, theme_owner_window, p_name, type); +bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types); } -bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::has_font_sizes(theme_owner, theme_owner_window, p_name, type); +bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types); } -bool Window::has_theme_color(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::has_colors(theme_owner, theme_owner_window, p_name, type); +bool Window::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types); } -bool Window::has_theme_constant(const StringName &p_name, const StringName &p_type) const { - StringName type = p_type ? p_type : get_class_name(); - return Control::has_constants(theme_owner, theme_owner_window, p_name, type); +bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types); +} + +bool Window::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types); +} + +bool Window::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + List<StringName> theme_types; + _get_theme_type_dependencies(p_theme_type, &theme_types); + return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types); } Rect2i Window::get_parent_rect() const { @@ -1382,19 +1414,22 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme); ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme); - ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "type"), &Window::get_theme_icon, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "type"), &Window::get_theme_stylebox, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_font", "name", "type"), &Window::get_theme_font, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_font_size", "name", "type"), &Window::get_theme_font_size, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_color", "name", "type"), &Window::get_theme_color, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "type"), &Window::get_theme_constant, DEFVAL("")); + ClassDB::bind_method(D_METHOD("set_theme_custom_type", "theme_type"), &Window::set_theme_custom_type); + ClassDB::bind_method(D_METHOD("get_theme_custom_type"), &Window::get_theme_custom_type); + + ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "theme_type"), &Window::get_theme_icon, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "theme_type"), &Window::get_theme_stylebox, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_font", "name", "theme_type"), &Window::get_theme_font, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_font_size", "name", "theme_type"), &Window::get_theme_font_size, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_color", "name", "theme_type"), &Window::get_theme_color, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "theme_type"), &Window::get_theme_constant, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "type"), &Window::has_theme_icon, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "type"), &Window::has_theme_stylebox, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_font", "name", "type"), &Window::has_theme_font, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_font_size", "name", "type"), &Window::has_theme_font_size, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_color", "name", "type"), &Window::has_theme_color, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "type"), &Window::has_theme_constant, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "theme_type"), &Window::has_theme_icon, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "theme_type"), &Window::has_theme_stylebox, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_font", "name", "theme_type"), &Window::has_theme_font, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_font_size", "name", "theme_type"), &Window::has_theme_font_size, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_color", "name", "theme_type"), &Window::has_theme_color, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "theme_type"), &Window::has_theme_constant, DEFVAL("")); ClassDB::bind_method(D_METHOD("set_layout_direction", "direction"), &Window::set_layout_direction); ClassDB::bind_method(D_METHOD("get_layout_direction"), &Window::get_layout_direction); @@ -1428,8 +1463,9 @@ void Window::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,CanvasItems,Viewport"), "set_content_scale_mode", "get_content_scale_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,KeepWidth,KeepHeight,Expand"), "set_content_scale_aspect", "get_content_scale_aspect"); - ADD_GROUP("Theme", ""); + ADD_GROUP("Theme", "theme_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_custom_type"), "set_theme_custom_type", "get_theme_custom_type"); ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"))); diff --git a/scene/main/window.h b/scene/main/window.h index 38846ed00e..494c386606 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -130,6 +130,7 @@ private: Ref<Theme> theme; Control *theme_owner = nullptr; Window *theme_owner_window = nullptr; + StringName theme_custom_type; Viewport *embedder = nullptr; @@ -241,6 +242,10 @@ public: void set_theme(const Ref<Theme> &p_theme); Ref<Theme> get_theme() const; + void set_theme_custom_type(const StringName &p_theme_type); + StringName get_theme_custom_type() const; + _FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const; + Size2 get_contents_minimum_size() const; void grab_focus(); @@ -252,19 +257,19 @@ public: Rect2i get_usable_parent_rect() const; - Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const; - Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const; - Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const; - int get_theme_font_size(const StringName &p_name, const StringName &p_type = StringName()) const; - Color get_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const; - int get_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const; - - bool has_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_theme_font_size(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const; + Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + int get_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + Color get_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + int get_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + + bool has_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_font_size(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const; Rect2i get_parent_rect() const; virtual DisplayServer::WindowID get_window_id() const override; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 5b5eb946f0..b9c1659fd1 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -657,6 +657,7 @@ void register_scene_types() { ClassDB::register_class<TileSet>(); ClassDB::register_virtual_class<TileSetSource>(); ClassDB::register_class<TileSetAtlasSource>(); + ClassDB::register_class<TileSetScenesCollectionSource>(); ClassDB::register_class<TileData>(); ClassDB::register_class<TileMap>(); ClassDB::register_class<ParallaxBackground>(); @@ -979,6 +980,7 @@ void register_scene_types() { // Always make the default theme to avoid invalid default font/icon/style in the given theme. if (RenderingServer::get_singleton()) { make_default_theme(default_theme_hidpi, font); + ColorPicker::init_shaders(); // RenderingServer needs to exist for this to succeed. } if (theme_path != String()) { @@ -1035,5 +1037,6 @@ void unregister_scene_types() { ParticlesMaterial::finish_shaders(); CanvasItemMaterial::finish_shaders(); + ColorPicker::finish_shaders(); SceneStringNames::free(); } diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index e9bfac3653..0ffeb8a5bf 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -38,7 +38,7 @@ void BitMap::create(const Size2 &p_size) { width = p_size.width; height = p_size.height; - bitmask.resize(((width * height) / 8) + 1); + bitmask.resize((((width * height) - 1) / 8) + 1); memset(bitmask.ptrw(), 0, bitmask.size()); } diff --git a/scene/resources/default_theme/SCsub b/scene/resources/default_theme/SCsub index fc61250247..0fb6bb2c62 100644 --- a/scene/resources/default_theme/SCsub +++ b/scene/resources/default_theme/SCsub @@ -2,4 +2,16 @@ Import("env") +import os +import os.path +from platform_methods import run_in_subprocess +import default_theme_builders + env.add_source_files(env.scene_sources, "*.cpp") + +env.Depends("#scene/resources/default_theme/default_font.gen.h", "#thirdparty/fonts/OpenSans_SemiBold.ttf") +env.CommandNoCache( + "#scene/resources/default_theme/default_font.gen.h", + "#thirdparty/fonts/OpenSans_SemiBold.ttf", + run_in_subprocess(default_theme_builders.make_fonts_header), +) diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 7c00c6d146..b671ee4644 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -30,15 +30,12 @@ #include "default_theme.h" -#include "scene/resources/theme.h" - #include "core/os/os.h" -#include "theme_data.h" - -#include "font_hidpi.inc" -#include "font_lodpi.inc" - +#include "default_font.gen.h" +#include "scene/resources/font.h" +#include "scene/resources/theme.h" #include "servers/text_server.h" +#include "theme_data.h" typedef Map<const void *, Ref<ImageTexture>> TexCacheMap; @@ -128,38 +125,6 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false, return texture; } -static Ref<FontData> make_font(int p_height, int p_ascent, int p_charcount, const int *p_char_rects, int p_kerning_count, const int *p_kernings, int p_w, int p_h, const unsigned char *p_img) { - Ref<FontData> font(memnew(FontData)); - font->new_bitmap(p_height, p_ascent, p_height); - - Ref<Image> image = memnew(Image(p_img)); - Ref<ImageTexture> tex = memnew(ImageTexture); - tex->create_from_image(image); - - font->bitmap_add_texture(tex); - - for (int i = 0; i < p_charcount; i++) { - const int *c = &p_char_rects[i * 8]; - - int chr = c[0]; - Rect2 frect; - frect.position.x = c[1]; - frect.position.y = c[2]; - frect.size.x = c[3]; - frect.size.y = c[4]; - Point2 align(c[6], c[5]); - int advance = c[7]; - - font->bitmap_add_char(chr, 0, frect, align, advance); - } - - for (int i = 0; i < p_kerning_count; i++) { - font->bitmap_add_kerning_pair(p_kernings[i * 3 + 0], p_kernings[i * 3 + 1], p_kernings[i * 3 + 2]); - } - - return font; -} - static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { Ref<StyleBox> style(memnew(StyleBoxEmpty)); @@ -1024,18 +989,25 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) { Ref<StyleBox> default_style; Ref<Texture2D> default_icon; Ref<Font> default_font; - int default_font_size = 14; + int default_font_size = 16; if (p_font.is_valid()) { + // Use the custom font defined in the Project Settings. default_font = p_font; - } else if (p_hidpi) { - Ref<FontData> font_data = make_font(_hidpi_font_height, _hidpi_font_ascent, _hidpi_font_charcount, &_hidpi_font_charrects[0][0], _hidpi_font_kerning_pair_count, &_hidpi_font_kerning_pairs[0][0], _hidpi_font_img_width, _hidpi_font_img_height, _hidpi_font_img_data); - default_font.instance(); - default_font->add_data(font_data); } else { - Ref<FontData> font_data = make_font(_lodpi_font_height, _lodpi_font_ascent, _lodpi_font_charcount, &_lodpi_font_charrects[0][0], _lodpi_font_kerning_pair_count, &_lodpi_font_kerning_pairs[0][0], _lodpi_font_img_width, _lodpi_font_img_height, _lodpi_font_img_data); - default_font.instance(); - default_font->add_data(font_data); + // Use the default DynamicFont (separate from the editor font). + // The default DynamicFont is chosen to have a small file size since it's + // embedded in both editor and export template binaries. + Ref<Font> dynamic_font; + dynamic_font.instance(); + + Ref<FontData> dynamic_font_data; + dynamic_font_data.instance(); + dynamic_font_data->load_memory(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size, "ttf", default_font_size); + dynamic_font->add_data(dynamic_font_data); + + default_font = dynamic_font; } + Ref<Font> large_font = default_font; fill_default_theme(t, default_font, large_font, default_icon, default_style, p_hidpi ? 2.0 : 1.0); diff --git a/scene/resources/default_theme/default_theme_builders.py b/scene/resources/default_theme/default_theme_builders.py new file mode 100644 index 0000000000..0455d6d246 --- /dev/null +++ b/scene/resources/default_theme/default_theme_builders.py @@ -0,0 +1,40 @@ +"""Functions used to generate source files during build time + +All such functions are invoked in a subprocess on Windows to prevent build flakiness. + +""" +import os +import os.path +from platform_methods import subprocess_main + + +def make_fonts_header(target, source, env): + dst = target[0] + + g = open(dst, "w", encoding="utf-8") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef _DEFAULT_FONTS_H\n") + g.write("#define _DEFAULT_FONTS_H\n") + + # Saving uncompressed, since FreeType will reference from memory pointer. + for i in range(len(source)): + with open(source[i], "rb") as f: + buf = f.read() + + name = os.path.splitext(os.path.basename(source[i]))[0] + + g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n") + g.write("static const unsigned char _font_" + name + "[] = {\n") + for j in range(len(buf)): + g.write("\t" + str(buf[j]) + ",\n") + + g.write("};\n") + + g.write("#endif") + + g.close() + + +if __name__ == "__main__": + subprocess_main(globals()) diff --git a/scene/resources/default_theme/font_hidpi.inc b/scene/resources/default_theme/font_hidpi.inc deleted file mode 100644 index 4860149e6b..0000000000 --- a/scene/resources/default_theme/font_hidpi.inc +++ /dev/null @@ -1,25463 +0,0 @@ -/* clang-format off */ -static const int _hidpi_font_height=25; -static const int _hidpi_font_ascent=19; -static const int _hidpi_font_charcount=191; -static const int _hidpi_font_charrects[191][8]={ -/* charidx , ofs_x, ofs_y, size_x, size_y, valign, halign, advance */ -{192,63,23,16,23,-4,-1,15}, -{224,184,182,10,19,0,1,13}, -{64,98,2,18,19,2,1,21}, -{96,159,234,5,4,0,5,14}, -{160,0,0,0,0,19,0,6}, -{32,0,0,0,0,19,0,6}, -{33,2,249,3,17,2,2,6}, -{193,83,25,16,23,-4,-1,15}, -{225,92,160,10,19,0,1,13}, -{65,163,23,16,17,2,-1,15}, -{161,246,236,3,17,6,2,6}, -{97,142,190,10,13,6,1,13}, -{162,67,214,9,17,2,2,13}, -{98,242,136,11,18,1,2,14}, -{194,103,25,16,23,-4,-1,15}, -{226,106,160,10,19,0,1,13}, -{66,122,146,11,17,2,2,15}, -{34,226,203,8,6,2,1,10}, -{35,189,44,14,17,2,1,16}, -{163,62,166,11,17,2,1,13}, -{195,123,23,16,23,-4,-1,15}, -{227,134,167,10,19,0,1,13}, -{67,209,65,12,17,2,1,14}, -{99,225,186,9,13,6,1,11}, -{228,170,182,10,18,1,1,13}, -{100,227,143,11,18,1,1,14}, -{196,23,23,16,22,-3,-1,15}, -{36,2,179,10,20,1,2,13}, -{68,193,65,12,17,2,2,16}, -{164,176,65,13,12,5,0,13}, -{37,120,2,18,17,2,1,20}, -{69,41,222,9,17,2,2,13}, -{165,98,99,12,17,2,1,13}, -{197,43,23,16,21,-2,-1,15}, -{229,16,179,10,20,-1,1,13}, -{101,189,109,11,13,6,1,13}, -{38,183,23,16,17,2,1,17}, -{70,54,222,9,17,2,2,12}, -{198,75,2,19,17,2,-1,20}, -{102,202,212,8,18,1,1,8}, -{166,44,268,2,24,1,6,13}, -{230,142,2,18,13,6,1,20}, -{71,2,71,14,17,2,1,17}, -{167,176,160,10,18,1,0,12}, -{199,146,94,12,23,2,1,14}, -{103,159,67,13,19,6,0,13}, -{231,212,189,9,19,6,1,11}, -{39,30,271,3,6,2,1,5}, -{72,130,99,12,17,2,2,17}, -{104,162,160,10,18,1,2,14}, -{200,238,186,9,23,-4,2,13}, -{40,46,243,7,21,2,1,7}, -{232,2,156,11,19,0,1,13}, -{168,68,235,7,3,1,4,14}, -{73,106,209,8,17,2,0,9}, -{169,230,2,17,17,2,1,20}, -{105,222,232,4,18,1,1,6}, -{201,28,222,9,23,-4,2,13}, -{41,130,238,6,21,2,0,7}, -{233,197,126,11,19,0,1,13}, -{202,93,209,9,23,-4,2,13}, -{74,13,225,7,22,2,-2,7}, -{234,167,137,11,19,0,1,13}, -{42,82,120,12,11,1,0,13}, -{170,100,236,6,8,2,1,8}, -{106,110,237,6,24,1,-1,6}, -{171,144,121,11,10,8,0,12}, -{43,2,119,12,12,5,1,13}, -{203,80,209,9,22,-3,2,13}, -{107,32,177,11,18,1,2,12}, -{235,77,166,11,18,1,1,13}, -{75,74,77,13,17,2,2,14}, -{44,230,213,4,6,16,1,6}, -{172,204,109,11,7,10,1,13}, -{236,204,234,5,19,0,0,6}, -{204,130,211,8,23,-4,0,9}, -{108,23,271,3,18,1,2,6}, -{76,86,188,10,17,2,2,12}, -{173,140,238,6,2,12,1,8}, -{45,120,237,6,2,12,1,8}, -{109,208,2,18,13,6,2,22}, -{205,178,205,8,23,-4,0,9}, -{237,213,234,5,19,0,2,6}, -{77,143,19,16,17,2,2,21}, -{46,9,251,3,3,16,2,6}, -{110,100,183,10,13,6,2,14}, -{206,154,207,8,23,-4,0,9}, -{238,238,213,8,19,0,-1,6}, -{174,2,23,17,17,2,1,20}, -{78,91,78,13,17,2,2,18}, -{175,18,125,12,2,-1,0,12}, -{111,162,90,12,13,6,1,14}, -{207,118,211,8,22,-3,0,9}, -{239,24,249,7,18,1,0,6}, -{79,203,23,15,17,2,1,18}, -{47,120,167,10,17,2,-1,9}, -{176,166,207,8,8,2,1,10}, -{112,212,143,11,19,6,2,14}, -{240,18,103,12,18,1,1,14}, -{208,171,44,14,17,2,0,16}, -{80,128,190,10,17,2,2,14}, -{48,234,115,11,17,2,1,13}, -{177,66,127,12,14,5,1,13}, -{113,182,126,11,19,6,1,14}, -{241,30,199,10,19,0,2,14}, -{81,97,52,15,22,2,1,18}, -{209,142,67,13,23,-4,2,18}, -{49,57,243,7,17,2,2,13}, -{178,190,206,8,10,2,0,8}, -{114,142,207,8,13,6,2,10}, -{242,242,87,12,19,0,1,14}, -{210,59,50,15,23,-4,1,18}, -{82,82,99,12,17,2,2,14}, -{50,2,135,11,17,2,1,13}, -{179,35,249,7,10,2,0,8}, -{115,72,188,10,13,6,0,11}, -{243,226,92,12,19,0,1,14}, -{211,40,49,15,23,-4,1,18}, -{83,129,125,11,17,2,0,13}, -{51,17,135,11,17,2,1,13}, -{180,168,219,5,4,0,5,14}, -{116,214,212,8,16,3,0,8}, -{244,194,86,12,19,0,1,14}, -{212,21,49,15,23,-4,1,18}, -{84,66,106,12,17,2,0,13}, -{52,125,78,13,17,2,0,13}, -{53,32,156,11,17,2,1,13}, -{85,50,106,12,17,2,2,17}, -{181,204,166,10,19,6,2,14}, -{117,198,189,10,13,6,2,14}, -{245,178,86,12,19,0,1,14}, -{213,2,44,15,23,-4,1,18}, -{54,47,156,11,17,2,1,13}, -{86,222,23,15,17,2,-1,14}, -{246,241,65,12,18,1,1,14}, -{214,116,52,15,22,-3,1,18}, -{182,34,131,12,21,1,1,16}, -{118,135,50,14,13,6,-1,12}, -{55,62,145,11,17,2,1,13}, -{87,2,2,22,17,2,-1,21}, -{119,28,2,20,13,6,-1,18}, -{215,114,125,11,11,5,1,13}, -{247,210,92,12,10,6,0,13}, -{183,16,251,3,3,9,2,6}, -{56,77,145,11,17,2,1,13}, -{88,225,44,14,17,2,-1,13}, -{216,78,52,15,19,1,1,18}, -{248,98,120,12,15,5,1,14}, -{120,50,127,12,13,6,0,12}, -{184,150,234,5,6,19,0,5}, -{89,207,44,14,17,2,-1,13}, -{121,153,44,14,19,6,-1,12}, -{217,225,65,12,23,-4,2,17}, -{249,44,199,10,19,0,2,14}, -{57,92,139,11,17,2,1,13}, -{185,177,232,5,10,2,0,8}, -{218,2,92,12,23,-4,2,17}, -{250,156,184,10,19,0,2,14}, -{90,232,165,10,17,2,1,13}, -{122,148,167,10,13,6,1,11}, -{58,37,263,3,13,6,2,6}, -{186,90,236,6,8,2,1,8}, -{219,34,104,12,23,-4,2,17}, -{123,2,224,7,21,2,1,9}, -{91,186,232,5,21,2,2,7}, -{251,58,191,10,19,0,2,14}, -{59,238,236,4,16,6,1,6}, -{187,47,177,11,10,8,1,12}, -{188,164,2,18,17,2,0,18}, -{252,190,149,10,18,1,2,14}, -{124,50,268,2,24,1,6,13}, -{220,114,99,12,22,-3,2,17}, -{92,137,146,11,17,2,-1,9}, -{60,159,121,11,12,5,1,13}, -{189,186,2,18,17,2,0,18}, -{253,56,77,14,25,0,-1,12}, -{221,20,76,14,23,-4,-1,13}, -{125,79,235,7,21,2,1,9}, -{93,195,234,5,21,2,0,7}, -{61,152,137,11,6,8,1,13}, -{190,52,2,19,17,2,0,18}, -{222,114,188,10,17,2,2,14}, -{254,219,115,11,24,1,2,14}, -{62,174,109,11,12,5,1,13}, -{94,108,78,13,11,2,0,13}, -{126,107,140,11,5,8,1,13}, -{223,17,156,11,18,1,2,14}, -{191,15,203,9,18,6,0,10}, -{255,38,76,14,24,1,-1,12}, -{63,2,203,9,17,2,0,10}, -{95,218,166,10,2,21,0,10}, -}; -static const int _hidpi_font_kerning_pair_count=0; -static const int _hidpi_font_kerning_pairs[1][3]={ -{0,0,0} -}; -static const int _hidpi_font_img_width=256; -static const int _hidpi_font_img_height=512; -static const int _hidpi_font_img_data_size=25255; -static const unsigned char _hidpi_font_img_data[25255]={ -137, -80, -78, -71, -13, -10, -26, -10, -0, -0, -0, -13, -73, -72, -68, -82, -0, -0, -1, -0, -0, -0, -2, -0, -8, -6, -0, -0, -0, -109, -154, -178, -251, -0, -0, -32, -0, -73, -68, -65, -84, -120, -156, -236, -157, -119, -184, -38, -53, -245, -199, -51, -84, -165, -55, -1, -21, -16, -41, -34, -42, -130, -98, -23, -1, -21, -20, -84, -108, -40, -138, -138, -10, -34, -40, -86, -148, -159, -216, -11, -34, -138, -130, -162, -40, -32, -160, -128, -160, -2, -162, -32, -162, -34, -34, -29, -145, -142, -235, -210, -219, -210, -151, -14, -219, -251, -231, -247, -199, -57, -97, -114, -231, -205, -204, -100, -102, -50, -239, -189, -119, -111, -190, -207, -179, -207, -221, -55, -57, -57, -147, -153, -73, -206, -36, -39, -167, -24, -147, -144, -144, -144, -144, -144, -144, -48, -129, -1, -172, -75, -142, -45, -74, -104, -158, -231, -208, -188, -176, -132, -230, -85, -14, -205, -58, -158, -250, -245, -156, -250, -103, -121, -234, -95, -237, -212, -239, -225, -169, -95, -25, -88, -160, -245, -235, -122, -234, -55, -5, -78, -0, -238, -5, -230, -2, -83, -128, -95, -2, -107, -149, -244, -119, -105, -224, -22, -224, -65, -96, -37, -31, -77, -8, -128, -143, -211, -0, -129, -60, -215, -1, -190, -8, -156, -15, -220, -13, -204, -1, -30, -7, -38, -1, -63, -3, -182, -12, -228, -243, -33, -224, -102, -109, -255, -63, -224, -109, -21, -180, -235, -3, -179, -244, -249, -173, -88, -195, -119, -109, -224, -43, -192, -101, -192, -19, -250, -188, -239, -5, -126, -3, -108, -160, -52, -27, -0, -191, -7, -30, -86, -190, -215, -0, -159, -0, -150, -168, -224, -187, -42, -112, -172, -62, -170, -211, -42, -232, -26, -189, -187, -62, -248, -42, -175, -235, -244, -255, -239, -211, -103, -49, -67, -223, -211, -133, -246, -89, -3, -75, -0, -159, -5, -174, -211, -231, -240, -36, -240, -79, -224, -117, -117, -253, -214, -246, -43, -105, -251, -127, -1, -143, -0, -243, -245, -239, -185, -192, -103, -234, -222, -85, -16, -128, -27, -244, -134, -246, -45, -169, -255, -164, -51, -134, -247, -41, -161, -249, -138, -214, -79, -174, -184, -206, -205, -74, -243, -126, -79, -221, -33, -206, -53, -78, -247, -212, -239, -164, -117, -55, -150, -240, -254, -43, -48, -93, -7, -225, -87, -129, -95, -1, -139, -128, -127, -149, -208, -127, -65, -249, -125, -188, -172, -191, -33, -0, -174, -5, -22, -2, -151, -56, -253, -191, -86, -127, -15, -252, -171, -225, -245, -52, -224, -251, -192, -108, -229, -115, -43, -112, -6, -112, -52, -112, -18, -112, -149, -94, -11, -224, -52, -96, -149, -10, -94, -175, -215, -251, -183, -130, -240, -126, -29, -60, -94, -225, -1, -156, -165, -124, -119, -14, -184, -231, -43, -149, -118, -1, -112, -35, -112, -5, -50, -209, -1, -30, -211, -107, -63, -166, -191, -239, -214, -241, -101, -251, -125, -98, -9, -207, -247, -2, -83, -129, -187, -128, -153, -84, -79, -212, -224, -119, -215, -35, -95, -144, -9, -253, -85, -253, -255, -125, -250, -126, -158, -212, -223, -139, -128, -157, -245, -61, -161, -215, -191, -70, -251, -128, -190, -139, -87, -215, -92, -99, -39, -224, -81, -100, -194, -31, -13, -236, -14, -188, -93, -255, -30, -173, -229, -143, -80, -33, -216, -131, -0, -28, -166, -157, -250, -75, -73, -253, -105, -136, -148, -159, -11, -156, -82, -66, -115, -142, -242, -56, -164, -226, -58, -63, -87, -154, -35, -60, -117, -183, -235, -96, -189, -18, -145, -164, -79, -43, -212, -31, -170, -109, -127, -90, -194, -123, -85, -96, -181, -66, -217, -121, -192, -116, -15, -237, -26, -136, -164, -254, -47, -21, -95, -164, -58, -0, -175, -209, -62, -253, -85, -127, -91, -120, -87, -82, -53, -188, -214, -0, -254, -173, -237, -79, -1, -94, -80, -66, -183, -46, -240, -107, -165, -187, -17, -88, -181, -132, -238, -79, -74, -179, -137, -254, -126, -169, -254, -62, -201, -67, -251, -110, -247, -62, -2, -250, -250, -38, -224, -115, -238, -243, -70, -190, -158, -71, -58, -131, -127, -33, -176, -139, -83, -255, -34, -100, -34, -2, -188, -215, -195, -243, -64, -224, -183, -192, -234, -84, -76, -212, -166, -239, -174, -71, -190, -22, -243, -129, -15, -58, -229, -203, -33, -31, -35, -128, -121, -200, -234, -235, -237, -133, -235, -92, -163, -245, -103, -84, -240, -255, -178, -62, -195, -31, -0, -43, -148, -208, -172, -0, -28, -172, -116, -95, -174, -235, -115, -213, -205, -236, -168, -29, -122, -18, -88, -178, -80, -183, -4, -34, -133, -174, -212, -127, -15, -120, -218, -47, -67, -46, -217, -182, -171, -184, -206, -59, -148, -102, -114, -161, -124, -11, -45, -63, -94, -111, -24, -224, -45, -5, -154, -171, -181, -188, -86, -218, -33, -95, -210, -215, -35, -203, -211, -223, -122, -234, -127, -161, -188, -222, -80, -199, -171, -230, -58, -191, -85, -62, -239, -208, -223, -22, -141, -4, -0, -176, -20, -178, -66, -152, -15, -236, -22, -216, -102, -95, -189, -214, -159, -75, -234, -239, -5, -110, -45, -148, -221, -9, -220, -89, -40, -91, -1, -184, -7, -249, -154, -61, -183, -73, -191, -61, -215, -92, -203, -121, -6, -199, -121, -234, -247, -215, -186, -127, -212, -240, -129, -242, -137, -218, -250, -221, -197, -228, -235, -220, -231, -209, -158, -186, -45, -156, -250, -67, -61, -245, -239, -209, -186, -7, -75, -120, -239, -132, -76, -234, -93, -245, -247, -18, -192, -222, -200, -252, -155, -137, -204, -199, -75, -128, -79, -107, -253, -110, -74, -223, -110, -37, -128, -72, -173, -57, -218, -169, -87, -20, -234, -236, -151, -227, -112, -231, -33, -109, -82, -160, -217, -74, -203, -103, -0, -203, -86, -92, -103, -37, -29, -228, -139, -128, -213, -157, -242, -3, -180, -253, -135, -145, -175, -11, -192, -145, -78, -253, -202, -122, -131, -243, -40, -145, -134, -14, -173, -139, -127, -22, -251, -3, -188, -0, -89, -186, -122, -39, -78, -40, -128, -103, -32, -43, -162, -251, -80, -161, -233, -92, -183, -169, -0, -248, -134, -182, -251, -124, -195, -118, -118, -121, -249, -90, -79, -221, -60, -224, -226, -66, -217, -165, -192, -220, -66, -217, -143, -149, -199, -87, -155, -92, -187, -162, -79, -115, -149, -223, -174, -158, -186, -55, -106, -221, -35, -53, -60, -192, -51, -81, -187, -190, -187, -152, -124, -157, -119, -61, -48, -233, -128, -167, -59, -245, -59, -120, -234, -55, -211, -186, -5, -37, -109, -31, -6, -14, -114, -202, -78, -82, -250, -169, -250, -255, -211, -149, -230, -215, -14, -205, -193, -200, -118, -160, -157, -78, -0, -81, -42, -0, -236, -95, -40, -255, -63, -251, -66, -129, -15, -234, -255, -247, -46, -208, -216, -1, -124, -86, -192, -117, -46, -85, -218, -119, -56, -101, -215, -35, -66, -97, -45, -125, -0, -179, -129, -123, -157, -122, -187, -255, -191, -48, -128, -255, -14, -200, -222, -235, -8, -109, -115, -80, -161, -254, -108, -100, -114, -108, -92, -199, -171, -230, -58, -86, -231, -241, -93, -167, -204, -34, -88, -0, -32, -66, -241, -9, -100, -133, -147, -57, -229, -203, -34, -203, -192, -201, -136, -112, -158, -141, -124, -193, -207, -36, -95, -214, -219, -47, -141, -111, -75, -53, -157, -130, -206, -1, -217, -98, -76, -115, -126, -111, -142, -12, -252, -27, -128, -165, -27, -244, -121, -73, -68, -241, -117, -18, -162, -220, -186, -31, -152, -166, -207, -53, -4, -11, -107, -248, -131, -127, -162, -118, -122, -119, -49, -249, -58, -247, -178, -89, -77, -253, -139, -61, -117, -27, -217, -74, -79, -221, -199, -16, -37, -228, -242, -250, -251, -189, -74, -122, -5, -35, -63, -154, -203, -0, -43, -59, -191, -87, -64, -4, -192, -103, -66, -239, -161, -120, -97, -59, -209, -255, -81, -40, -63, -91, -203, -159, -173, -255, -0, -126, -87, -160, -57, -79, -203, -63, -29, -112, -157, -111, -43, -237, -161, -250, -219, -158, -48, -92, -234, -208, -252, -93, -203, -94, -170, -191, -237, -254, -255, -107, -13, -239, -233, -66, -224, -9, -231, -183, -221, -234, -252, -184, -9, -31, -15, -223, -37, -16, -125, -197, -66, -224, -57, -78, -185, -69, -19, -1, -176, -151, -182, -249, -136, -83, -182, -52, -114, -2, -0, -162, -80, -60, -4, -89, -129, -221, -173, -101, -175, -117, -104, -239, -3, -174, -247, -240, -189, -137, -193, -45, -192, -20, -84, -137, -10, -100, -228, -58, -135, -109, -27, -244, -119, -13, -70, -42, -1, -255, -131, -40, -94, -127, -10, -28, -228, -60, -131, -235, -40, -81, -132, -82, -175, -12, -133, -194, -68, -141, -241, -238, -98, -242, -117, -238, -115, -163, -166, -245, -84, -11, -128, -243, -25, -185, -250, -253, -135, -146, -110, -19, -208, -167, -163, -129, -115, -155, -220, -135, -219, -120, -115, -189, -208, -12, -244, -107, -64, -190, -183, -191, -201, -161, -187, -13, -184, -207, -249, -189, -44, -185, -214, -218, -251, -48, -10, -215, -121, -173, -210, -94, -166, -191, -191, -172, -191, -247, -115, -104, -62, -165, -101, -223, -208, -223, -118, -192, -189, -162, -130, -239, -42, -133, -223, -75, -34, -95, -182, -71, -244, -247, -82, -246, -183, -75, -11, -124, -196, -55, -48, -106, -238, -225, -237, -218, -230, -239, -133, -242, -90, -120, -120, -157, -170, -85, -207, -112, -202, -172, -48, -62, -13, -88, -202, -41, -63, -89, -203, -95, -228, -148, -93, -12, -60, -238, -225, -251, -59, -165, -45, -42, -1, -79, -214, -223, -123, -235, -239, -19, -244, -119, -208, -145, -33, -162, -167, -1, -81, -150, -61, -167, -80, -151, -57, -183, -218, -90, -191, -82, -124, -31, -177, -222, -93, -13, -223, -117, -17, -1, -118, -135, -62, -131, -59, -145, -15, -79, -153, -2, -206, -34, -182, -0, -120, -20, -248, -168, -243, -219, -30, -253, -45, -89, -164, -245, -180, -221, -157, -154, -237, -85, -85, -227, -12, -120, -64, -251, -181, -149, -150, -109, -173, -191, -143, -112, -232, -236, -121, -234, -70, -250, -123, -91, -253, -125, -91, -224, -117, -150, -66, -148, -141, -115, -144, -47, -157, -61, -62, -219, -208, -161, -89, -95, -203, -46, -66, -20, -122, -243, -245, -193, -84, -157, -33, -207, -65, -142, -204, -190, -11, -124, -29, -153, -24, -0, -7, -107, -253, -167, -245, -247, -167, -156, -54, -175, -64, -246, -85, -115, -66, -7, -145, -182, -179, -171, -162, -119, -21, -202, -45, -130, -143, -1, -145, -163, -190, -187, -10, -101, -147, -148, -207, -250, -37, -215, -93, -199, -41, -59, -135, -194, -190, -94, -203, -95, -137, -124, -161, -167, -144, -31, -3, -46, -68, -236, -45, -158, -129, -28, -211, -61, -166, -255, -15, -62, -50, -212, -247, -0, -126, -77, -254, -218, -206, -51, -104, -183, -20, -53, -222, -137, -26, -229, -221, -85, -241, -5, -254, -172, -207, -224, -12, -228, -163, -100, -79, -90, -6, -148, -200, -14, -47, -136, -47, -0, -22, -48, -242, -212, -96, -62, -30, -197, -123, -201, -53, -223, -14, -204, -15, -161, -45, -99, -240, -27, -237, -151, -253, -242, -126, -71, -127, -191, -199, -161, -249, -144, -150, -125, -76, -127, -219, -37, -253, -207, -27, -92, -231, -207, -218, -230, -213, -200, -222, -107, -146, -135, -102, -178, -214, -109, -163, -180, -127, -168, -225, -121, -16, -114, -44, -54, -83, -7, -197, -100, -196, -152, -102, -73, -228, -136, -240, -17, -68, -215, -176, -148, -210, -175, -141, -104, -202, -247, -68, -20, -87, -161, -131, -104, -35, -29, -40, -247, -227, -124, -157, -181, -206, -162, -201, -22, -224, -73, -224, -170, -66, -217, -108, -224, -81, -15, -237, -85, -202, -127, -69, -167, -236, -106, -28, -125, -73, -129, -254, -29, -200, -23, -110, -174, -254, -221, -89, -203, -237, -123, -222, -75, -127, -255, -81, -127, -23, -87, -11, -3, -103, -246, -228, -202, -226, -55, -122, -234, -236, -106, -14, -224, -114, -28, -157, -70, -19, -104, -251, -211, -244, -255, -49, -223, -93, -41, -95, -96, -53, -224, -85, -5, -250, -243, -128, -89, -21, -188, -160, -255, -21, -192, -195, -200, -60, -8, -57, -154, -108, -191, -2, -80, -6, -86, -201, -247, -47, -253, -125, -1, -131, -26, -251, -117, -148, -230, -4, -135, -6, -26, -28, -65, -144, -75, -222, -163, -245, -239, -119, -60, -52, -7, -219, -235, -232, -223, -214, -6, -59, -192, -79, -148, -199, -14, -250, -123, -25, -68, -25, -249, -91, -253, -253, -212, -192, -8, -224, -101, -245, -17, -85, -104, -34, -0, -230, -1, -255, -46, -148, -61, -12, -60, -89, -40, -179, -43, -39, -236, -96, -32, -63, -189, -105, -162, -189, -182, -43, -182, -127, -163, -19, -20, -255, -145, -225, -20, -10, -71, -134, -90, -110, -183, -99, -167, -0, -203, -104, -89, -134, -28, -69, -205, -70, -116, -2, -183, -43, -205, -177, -192, -154, -78, -219, -117, -16, -163, -178, -183, -54, -232, -111, -180, -119, -87, -197, -183, -132, -230, -122, -60, -31, -39, -231, -186, -16, -95, -0, -92, -200, -72, -29, -128, -213, -135, -189, -38, -224, -158, -142, -166, -196, -240, -45, -8, -192, -154, -200, -132, -159, -142, -44, -207, -103, -162, -230, -142, -5, -186, -219, -144, -189, -210, -82, -250, -210, -231, -160, -90, -203, -192, -235, -108, -162, -55, -53, -189, -108, -194, -0, -175, -211, -186, -25, -250, -119, -253, -150, -247, -180, -49, -50, -201, -254, -238, -148, -253, -18, -217, -195, -46, -167, -191, -131, -6, -17, -114, -66, -241, -168, -62, -35, -223, -18, -223, -162, -137, -0, -152, -138, -163, -99, -209, -178, -127, -41, -159, -173, -156, -178, -143, -146, -91, -211, -109, -168, -101, -86, -87, -50, -112, -228, -86, -114, -173, -101, -144, -85, -210, -124, -28, -237, -180, -62, -31, -223, -137, -129, -111, -107, -177, -141, -211, -143, -135, -145, -21, -136, -181, -250, -187, -9, -153, -228, -47, -39, -223, -42, -44, -210, -255, -91, -59, -17, -8, -80, -22, -235, -181, -162, -189, -187, -58, -190, -30, -154, -207, -107, -223, -119, -42, -169, -183, -136, -45, -0, -246, -98, -228, -41, -128, -181, -25, -248, -15, -176, -70, -129, -118, -25, -231, -255, -246, -20, -224, -115, -229, -119, -30, -0, -114, -43, -165, -119, -234, -95, -159, -33, -131, -213, -3, -216, -115, -221, -198, -154, -71, -114, -141, -246, -192, -87, -70, -235, -151, -116, -6, -214, -45, -109, -238, -69, -249, -156, -137, -12, -248, -23, -232, -239, -79, -40, -223, -13, -28, -154, -160, -65, -4, -236, -81, -117, -191, -206, -75, -111, -34, -0, -46, -213, -254, -173, -224, -148, -189, -81, -7, -223, -147, -136, -117, -221, -73, -58, -96, -63, -141, -28, -25, -94, -139, -216, -100, -204, -210, -246, -75, -85, -93, -195, -225, -251, -53, -223, -59, -37, -224, -200, -176, -80, -183, -53, -114, -108, -252, -48, -50, -177, -111, -68, -108, -57, -220, -99, -169, -231, -32, -71, -177, -119, -34, -203, -244, -25, -218, -239, -131, -128, -181, -3, -251, -27, -237, -221, -85, -241, -245, -212, -127, -82, -235, -247, -172, -224, -97, -17, -91, -0, -44, -135, -8, -204, -239, -57, -101, -118, -203, -246, -16, -162, -8, -62, -22, -177, -113, -113, -143, -116, -127, -160, -207, -102, -229, -34, -207, -70, -64, -108, -209, -33, -215, -56, -15, -44, -215, -200, -245, -0, -182, -99, -251, -249, -120, -141, -54, -200, -5, -212, -207, -157, -178, -186, -179, -234, -245, -43, -248, -217, -229, -239, -46, -37, -245, -22, -77, -4, -192, -129, -218, -230, -125, -133, -242, -183, -34, -75, -208, -185, -136, -118, -126, -119, -45, -223, -17, -89, -98, -63, -170, -207, -127, -117, -63, -231, -129, -235, -108, -128, -8, -140, -187, -41, -104, -182, -41, -63, -50, -108, -45, -120, -187, -34, -246, -187, -171, -226, -91, -168, -255, -54, -34, -120, -223, -226, -171, -31, -6, -128, -119, -225, -152, -82, -35, -91, -172, -61, -80, -161, -140, -163, -220, -213, -250, -15, -40, -253, -59, -99, -92, -252, -245, -250, -128, -158, -64, -164, -224, -128, -101, -17, -185, -30, -224, -113, -253, -251, -34, -31, -175, -209, -4, -178, -130, -248, -175, -246, -209, -213, -97, -124, -222, -243, -15, -228, -220, -250, -243, -148, -120, -129, -33, -90, -103, -144, -229, -153, -215, -104, -198, -25, -136, -77, -4, -192, -198, -250, -66, -175, -43, -227, -27, -3, -192, -223, -180, -111, -239, -242, -212, -149, -29, -25, -54, -222, -91, -199, -64, -236, -119, -87, -199, -215, -169, -251, -37, -34, -12, -159, -223, -215, -189, -133, -2, -57, -201, -90, -8, -124, -143, -146, -237, -53, -176, -60, -242, -193, -94, -8, -124, -61, -214, -133, -151, -33, -223, -119, -95, -86, -65, -119, -155, -210, -220, -19, -229, -194, -145, -65, -110, -96, -227, -245, -112, -44, -208, -214, -14, -118, -114, -101, -228, -193, -53, -124, -160, -161, -55, -32, -185, -213, -226, -81, -116, -112, -78, -170, -232, -151, -221, -71, -122, -45, -53, -41, -63, -50, -12, -114, -89, -141, -141, -216, -239, -46, -132, -47, -114, -252, -55, -19, -248, -166, -71, -200, -120, -173, -253, -250, -6, -178, -18, -120, -28, -249, -232, -28, -137, -232, -129, -222, -174, -127, -143, -212, -242, -199, -136, -241, -229, -47, -92, -248, -47, -250, -160, -190, -87, -65, -99, -245, -0, -199, -70, -189, -120, -4, -32, -230, -181, -15, -34, -190, -221, -181, -95, -213, -186, -65, -132, -120, -146, -205, -70, -246, -229, -165, -198, -78, -4, -160, -164, -221, -178, -228, -74, -196, -243, -241, -216, -246, -59, -180, -27, -0, -95, -168, -187, -39, -135, -126, -69, -68, -203, -63, -139, -234, -237, -205, -187, -144, -189, -252, -92, -253, -235, -221, -230, -244, -141, -216, -239, -46, -148, -111, -205, -107, -251, -68, -219, -251, -233, -10, -96, -21, -228, -56, -251, -2, -100, -219, -183, -64, -255, -94, -128, -184, -47, -119, -219, -243, -39, -140, -13, -168, -16, -248, -57, -178, -237, -2, -57, -29, -248, -27, -112, -34, -162, -4, -252, -7, -98, -246, -91, -42, -72, -134, -216, -87, -23, -63, -11, -160, -255, -180, -219, -96, -24, -125, -76, -72, -24, -151, -0, -158, -139, -24, -96, -93, -128, -44, -197, -231, -32, -202, -175, -135, -16, -37, -208, -143, -40, -24, -172, -140, -66, -31, -93, -220, -75, -141, -193, -15, -35, -143, -72, -147, -0, -72, -72, -24, -207, -208, -121, -188, -8, -177, -182, -132, -10, -35, -21, -68, -97, -188, -8, -81, -212, -37, -1, -48, -70, -16, -93, -209, -148, -48, -225, -144, -25, -99, -206, -214, -255, -191, -167, -130, -238, -125, -74, -219, -41, -254, -66, -194, -144, -64, -79, -65, -8, -17, -207, -182, -219, -172, -210, -2, -177, -197, -190, -3, -245, -78, -107, -201, -115, -51, -196, -230, -124, -134, -46, -153, -91, -251, -248, -147, -219, -217, -79, -199, -241, -204, -155, -104, -32, -204, -235, -204, -194, -6, -111, -185, -171, -130, -246, -74, -29, -67, -79, -5, -141, -109, -208, -151, -23, -58, -215, -218, -60, -180, -93, -129, -199, -43, -16, -95, -135, -169, -228, -78, -101, -127, -35, -192, -189, -182, -132, -223, -106, -72, -28, -192, -75, -17, -165, -226, -60, -253, -123, -9, -240, -37, -234, -143, -34, -215, -38, -183, -164, -172, -220, -202, -57, -207, -108, -33, -129, -198, -83, -157, -64, -143, -65, -8, -201, -157, -72, -94, -171, -191, -109, -20, -161, -217, -29, -250, -123, -57, -162, -28, -219, -6, -241, -138, -187, -168, -3, -175, -231, -234, -139, -4, -79, -128, -141, -197, -9, -58, -8, -207, -67, -142, -152, -78, -67, -237, -22, -16, -123, -254, -251, -2, -218, -91, -108, -130, -24, -43, -129, -199, -85, -27, -57, -177, -0, -241, -98, -124, -81, -11, -1, -240, -67, -231, -90, -3, -22, -169, -1, -237, -183, -39, -87, -170, -62, -138, -152, -45, -91, -19, -229, -133, -148, -152, -249, -86, -240, -123, -55, -185, -237, -11, -136, -149, -227, -21, -228, -71, -226, -232, -24, -26, -112, -148, -42, -240, -185, -64, -105, -75, -143, -148, -149, -206, -250, -195, -92, -208, -164, -159, -173, -64, -207, -65, -8, -25, -92, -1, -172, -130, -172, -0, -188, -65, -70, -3, -121, -206, -68, -221, -82, -129, -93, -240, -4, -0, -109, -200, -111, -75, -196, -0, -106, -33, -240, -242, -46, -188, -10, -124, -215, -36, -183, -173, -184, -162, -3, -31, -87, -155, -30, -100, -79, -95, -194, -231, -56, -228, -88, -112, -50, -178, -63, -183, -251, -249, -89, -192, -49, -1, -237, -45, -54, -35, -247, -24, -253, -145, -135, -206, -70, -204, -253, -8, -121, -188, -137, -208, -208, -232, -75, -34, -167, -30, -211, -244, -223, -3, -4, -172, -78, -10, -60, -236, -170, -238, -120, -52, -52, -28, -114, -218, -98, -45, -88, -7, -252, -92, -42, -120, -237, -72, -30, -150, -254, -116, -10, -199, -193, -136, -233, -243, -239, -181, -126, -14, -21, -95, -119, -114, -31, -142, -74, -75, -75, -228, -200, -18, -28, -55, -232, -94, -192, -96, -16, -66, -23, -179, -16, -5, -206, -103, -28, -250, -110, -65, -8, -35, -1, -89, -94, -158, -133, -216, -166, -159, -67, -64, -200, -176, -0, -158, -91, -234, -96, -187, -33, -70, -31, -149, -231, -81, -250, -44, -31, -160, -16, -68, -163, -1, -143, -23, -33, -66, -196, -78, -136, -25, -148, -216, -178, -7, -240, -154, -10, -124, -64, -255, -255, -98, -68, -56, -63, -137, -172, -10, -188, -121, -20, -10, -237, -45, -182, -32, -143, -111, -119, -135, -135, -110, -146, -78, -134, -149, -112, -2, -101, -6, -246, -241, -205, -74, -126, -166, -254, -3, -216, -177, -225, -125, -218, -85, -231, -75, -10, -229, -91, -218, -137, -26, -200, -231, -105, -200, -105, -7, -72, -0, -151, -210, -83, -15, -228, -216, -22, -196, -124, -219, -43, -176, -24, -185, -13, -240, -90, -209, -146, -111, -127, -250, -93, -254, -227, -15, -66, -8, -178, -23, -62, -10, -248, -3, -185, -27, -234, -199, -28, -154, -110, -65, -8, -35, -0, -177, -129, -182, -152, -6, -60, -111, -180, -250, -82, -6, -196, -51, -110, -33, -178, -116, -108, -28, -46, -92, -121, -172, -133, -44, -55, -167, -33, -49, -20, -94, -167, -2, -224, -142, -144, -9, -235, -225, -23, -228, -60, -84, -209, -254, -41, -1, -160, -191, -109, -190, -135, -45, -29, -154, -77, -181, -236, -116, -253, -221, -84, -0, -216, -136, -203, -123, -34, -113, -242, -0, -126, -223, -176, -159, -214, -225, -236, -205, -133, -114, -203, -47, -200, -215, -129, -220, -77, -126, -54, -142, -123, -115, -9, -173, -13, -63, -14, -78, -220, -75, -15, -221, -133, -74, -243, -141, -146, -250, -175, -107, -125, -231, -143, -90, -37, -40, -4, -33, -212, -50, -128, -41, -206, -239, -151, -105, -217, -121, -78, -89, -227, -32, -132, -68, -80, -234, -20, -248, -117, -218, -35, -14, -3, -136, -85, -221, -84, -2, -179, -249, -148, -240, -184, -10, -49, -211, -117, -93, -120, -95, -138, -36, -155, -184, -170, -170, -109, -31, -240, -8, -0, -235, -208, -244, -125, -135, -198, -110, -13, -172, -67, -75, -176, -0, -64, -172, -23, -103, -34, -75, -238, -103, -32, -138, -183, -121, -200, -106, -52, -56, -139, -19, -121, -20, -235, -243, -200, -99, -31, -108, -71, -190, -143, -31, -240, -139, -40, -225, -99, -151, -246, -65, -39, -25, -228, -1, -86, -142, -175, -160, -177, -219, -185, -107, -75, -234, -109, -24, -252, -214, -91, -189, -32, -80, -8, -66, -168, -101, -69, -1, -176, -162, -150, -253, -175, -64, -215, -40, -8, -97, -204, -9, -75, -132, -61, -162, -135, -103, -84, -1, -53, -214, -209, -246, -126, -61, -2, -192, -78, -238, -91, -28, -154, -155, -144, -85, -202, -114, -5, -154, -16, -1, -96, -221, -174, -255, -233, -148, -89, -103, -166, -143, -85, -181, -45, -240, -121, -22, -185, -75, -249, -49, -200, -170, -98, -17, -34, -76, -62, -217, -128, -143, -93, -225, -4, -133, -78, -39, -143, -140, -52, -16, -172, -213, -161, -113, -183, -1, -235, -23, -234, -108, -26, -189, -133, -192, -51, -67, -251, -217, -10, -20, -66, -16, -105, -217, -83, -2, -0, -241, -79, -182, -46, -194, -71, -20, -232, -130, -67, -16, -197, -158, -176, -68, -216, -35, -122, -120, -142, -249, -21, -69, -76, -180, -189, -223, -162, -0, -208, -178, -91, -181, -108, -115, -103, -178, -255, -214, -169, -111, -34, -0, -172, -150, -124, -79, -167, -236, -35, -90, -214, -104, -73, -76, -158, -245, -200, -226, -82, -52, -218, -116, -3, -30, -118, -11, -252, -161, -64, -250, -221, -148, -254, -177, -26, -58, -187, -13, -216, -183, -80, -254, -89, -45, -111, -125, -170, -21, -12, -10, -65, -8, -181, -12, -68, -82, -90, -205, -181, -125, -112, -69, -23, -202, -224, -32, -132, -68, -158, -176, -68, -216, -35, -22, -248, -141, -249, -21, -69, -76, -126, -93, -238, -215, -233, -131, -43, -0, -108, -70, -167, -3, -157, -255, -239, -228, -212, -7, -9, -0, -68, -155, -110, -191, -210, -110, -234, -177, -149, -17, -165, -222, -34, -2, -163, -67, -33, -43, -9, -155, -142, -204, -226, -7, -33, -109, -11, -124, -172, -246, -191, -54, -111, -162, -210, -239, -172, -244, -149, -115, -131, -124, -27, -80, -76, -224, -114, -190, -150, -183, -14, -172, -26, -12, -202, -87, -0, -51, -16, -39, -148, -187, -245, -1, -108, -224, -105, -219, -100, -5, -16, -109, -194, -18, -105, -143, -88, -224, -57, -230, -87, -20, -49, -249, -117, -185, -95, -167, -15, -174, -0, -176, -154, -245, -155, -17, -229, -228, -99, -140, -12, -89, -21, -42, -0, -108, -146, -153, -129, -112, -93, -136, -203, -46, -192, -55, -107, -120, -44, -137, -28, -117, -218, -113, -252, -85, -36, -145, -137, -205, -90, -244, -253, -2, -189, -53, -104, -242, -70, -182, -70, -142, -134, -33, -60, -109, -91, -232, -10, -224, -153, -200, -50, -127, -33, -170, -92, -68, -242, -46, -44, -64, -4, -221, -64, -22, -237, -232, -160, -16, -132, -80, -203, -32, -223, -2, -216, -24, -248, -190, -140, -42, -65, -65, -8, -137, -60, -97, -137, -180, -71, -44, -240, -28, -211, -43, -138, -30, -248, -181, -190, -95, -114, -108, -81, -40, -191, -195, -169, -59, -182, -80, -23, -42, -0, -110, -161, -30, -183, -214, -240, -176, -123, -240, -135, -113, -210, -217, -35, -81, -150, -236, -209, -160, -171, -176, -252, -165, -150, -121, -147, -131, -32, -138, -92, -8, -215, -1, -212, -102, -202, -118, -104, -47, -82, -218, -143, -235, -239, -143, -234, -239, -139, -235, -218, -70, -1, -133, -32, -132, -90, -6, -35, -149, -128, -231, -107, -217, -235, -157, -178, -224, -32, -132, -68, -158, -176, -68, -220, -35, -106, -219, -49, -191, -162, -136, -201, -175, -235, -253, -146, -163, -40, -0, -126, -228, -212, -109, -87, -168, -171, -21, -0, -200, -17, -39, -200, -87, -187, -44, -171, -144, -13, -36, -91, -229, -128, -100, -163, -18, -15, -164, -178, -71, -12, -122, -158, -18, -2, -72, -102, -170, -57, -136, -197, -160, -215, -148, -156, -60, -55, -95, -232, -41, -128, -205, -204, -60, -144, -32, -213, -67, -251, -25, -165, -61, -189, -208, -246, -179, -33, -215, -234, -12, -252, -65, -8, -97, -164, -0, -216, -18, -89, -146, -92, -75, -30, -146, -58, -56, -8, -33, -113, -149, -58, -207, -33, -210, -30, -209, -105, -59, -30, -86, -20, -49, -183, -80, -157, -238, -151, -28, -69, -1, -96, -195, -166, -77, -101, -48, -203, -116, -136, -0, -176, -6, -83, -135, -87, -208, -252, -76, -105, -142, -170, -160, -177, -177, -3, -183, -45, -169, -127, -51, -121, -54, -43, -123, -74, -240, -195, -10, -126, -239, -83, -154, -57, -52, -179, -3, -120, -123, -21, -173, -210, -219, -109, -192, -147, -200, -92, -156, -174, -99, -248, -217, -117, -109, -163, -129, -193, -32, -132, -224, -8, -0, -45, -179, -22, -78, -31, -163, -65, -16, -66, -34, -79, -88, -34, -236, -17, -61, -237, -198, -244, -138, -162, -7, -126, -81, -239, -55, -6, -16, -19, -93, -59, -25, -95, -89, -65, -103, -29, -100, -30, -163, -36, -19, -53, -146, -238, -28, -224, -43, -21, -124, -118, -37, -199, -29, -84, -68, -31, -210, -190, -221, -165, -180, -191, -43, -163, -83, -90, -107, -102, -124, -19, -225, -74, -85, -187, -13, -248, -162, -254, -173, -204, -157, -216, -11, -232, -41, -8, -97, -236, -9, -75, -132, -61, -98, -129, -223, -115, -24, -227, -43, -138, -152, -252, -250, -184, -223, -24, -32, -143, -91, -88, -107, -157, -71, -190, -196, -247, -186, -33, -147, -39, -253, -152, -173, -207, -206, -205, -175, -184, -30, -146, -123, -241, -225, -194, -152, -57, -160, -230, -154, -111, -34, -63, -13, -56, -133, -193, -188, -136, -235, -145, -7, -87, -157, -67, -133, -16, -243, -240, -182, -219, -128, -251, -245, -111, -183, -216, -254, -109, -65, -15, -65, -8, -137, -56, -97, -137, -180, -71, -44, -240, -28, -15, -43, -138, -152, -91, -168, -232, -247, -27, -3, -228, -113, -40, -107, -175, -77, -110, -121, -120, -102, -73, -253, -74, -136, -167, -168, -197, -124, -228, -52, -203, -245, -228, -91, -136, -108, -57, -118, -116, -198, -204, -64, -134, -170, -2, -223, -119, -21, -120, -220, -166, -215, -113, -189, -1, -167, -226, -232, -202, -2, -239, -253, -89, -136, -224, -69, -255, -174, -83, -223, -170, -39, -16, -49, -8, -33, -145, -39, -44, -145, -246, -136, -5, -250, -49, -189, -162, -232, -129, -95, -212, -251, -141, -1, -100, -91, -99, -221, -118, -7, -142, -155, -61, -244, -214, -207, -96, -30, -37, -177, -27, -144, -204, -86, -159, -68, -20, -216, -54, -174, -197, -99, -136, -99, -219, -161, -56, -161, -191, -145, -109, -133, -61, -234, -251, -118, -205, -181, -215, -64, -132, -232, -101, -72, -152, -54, -27, -174, -237, -98, -100, -101, -209, -54, -94, -134, -77, -102, -251, -239, -122, -234, -113, -2, -34, -78, -88, -34, -238, -17, -29, -218, -49, -191, -162, -136, -201, -175, -143, -251, -77, -72, -240, -34, -246, -132, -37, -226, -30, -209, -161, -27, -15, -43, -138, -152, -91, -168, -232, -247, -155, -144, -224, -69, -236, -9, -75, -196, -61, -162, -210, -140, -249, -21, -69, -76, -126, -125, -220, -111, -66, -66, -41, -98, -78, -88, -250, -217, -35, -142, -249, -21, -69, -76, -126, -125, -220, -111, -194, -4, -3, -225, -231, -154, -209, -39, -108, -108, -196, -20, -80, -74, -19, -123, -203, -19, -155, -95, -212, -251, -13, -1, -162, -48, -179, -86, -119, -165, -249, -246, -144, -252, -136, -32, -182, -250, -107, -84, -208, -21, -177, -16, -57, -206, -187, -4, -177, -247, -95, -181, -97, -255, -214, -82, -62, -39, -20, -202, -47, -3, -30, -172, -104, -183, -10, -185, -210, -240, -131, -21, -116, -239, -82, -154, -39, -129, -85, -60, -245, -43, -146, -219, -44, -236, -81, -193, -103, -71, -165, -185, -135, -190, -3, -240, -208, -49, -96, -228, -120, -0, -227, -96, -69, -17, -147, -95, -31, -247, -27, -10, -242, -179, -241, -42, -75, -187, -131, -148, -230, -212, -26, -94, -22, -54, -247, -226, -127, -200, -163, -254, -160, -99, -118, -32, -155, -117, -5, -191, -237, -181, -221, -23, -157, -178, -12, -217, -86, -253, -179, -166, -237, -183, -181, -109, -105, -92, -65, -114, -205, -254, -129, -21, -52, -86, -72, -60, -130, -39, -211, -51, -18, -142, -204, -190, -223, -119, -135, -222, -91, -107, -208, -49, -96, -228, -68, -5, -241, -87, -20, -67, -255, -98, -247, -1, -36, -98, -51, -136, -243, -210, -64, -40, -50, -96, -9, -242, -120, -123, -111, -170, -225, -101, -81, -52, -65, -222, -20, -248, -179, -214, -45, -160, -196, -4, -216, -195, -239, -11, -218, -102, -123, -167, -204, -70, -50, -174, -244, -182, -100, -228, -42, -224, -205, -158, -122, -27, -69, -107, -186, -111, -98, -23, -104, -109, -223, -127, -229, -169, -179, -130, -198, -155, -216, -53, -58, -232, -24, -48, -114, -34, -130, -200, -95, -216, -216, -252, -70, -27, -136, -89, -44, -120, -108, -227, -129, -29, -180, -110, -10, -53, -153, -145, -203, -4, -128, -214, -101, -192, -201, -90, -127, -23, -97, -137, -69, -143, -87, -250, -181, -157, -178, -119, -106, -217, -71, -3, -218, -219, -201, -57, -224, -17, -75, -190, -242, -25, -136, -150, -236, -161, -93, -151, -220, -7, -96, -43, -167, -124, -67, -196, -154, -113, -38, -195, -178, -206, -164, -99, -192, -200, -132, -132, -34, -200, -191, -180, -103, -120, -234, -78, -209, -186, -111, -5, -240, -41, -21, -0, -90, -191, -6, -185, -147, -207, -7, -2, -248, -93, -13, -60, -84, -40, -179, -118, -23, -181, -81, -131, -24, -185, -10, -112, -3, -162, -174, -163, -2, -124, -22, -129, -31, -77, -96, -95, -229, -243, -63, -59, -7, -201, -205, -189, -27, -133, -224, -31, -115, -32, -82, -60, -123, -135, -95, -148, -56, -251, -9, -195, -1, -226, -33, -103, -93, -110, -215, -116, -202, -87, -213, -242, -133, -192, -122, -1, -124, -42, -5, -128, -210, -216, -128, -156, -94, -167, -29, -90, -160, -166, -79, -118, -21, -112, -170, -83, -102, -19, -122, -252, -180, -238, -158, -156, -54, -75, -2, -215, -104, -187, -47, -145, -235, -6, -38, -19, -176, -154, -137, -2, -58, -166, -61, -42, -225, -25, -45, -158, -189, -195, -179, -83, -156, -125, -82, -26, -176, -74, -32, -91, -16, -235, -82, -91, -186, -5, -1, -54, -82, -154, -218, -173, -7, -185, -59, -243, -126, -78, -153, -77, -144, -113, -118, -85, -91, -135, -222, -162, -74, -0, -236, -175, -52, -94, -227, -40, -224, -88, -253, -119, -186, -210, -93, -227, -148, -29, -139, -172, -32, -30, -118, -203, -106, -250, -100, -87, -1, -11, -144, -37, -251, -242, -200, -137, -204, -28, -26, -186, -244, -34, -122, -131, -133, -58, -71, -238, -69, -182, -4, -175, -107, -194, -163, -53, -136, -148, -246, -168, -192, -51, -106, -60, -123, -229, -25, -35, -206, -254, -132, -73, -3, -214, -22, -228, -138, -169, -82, -37, -36, -240, -93, -165, -249, -99, -0, -191, -173, -149, -246, -122, -167, -204, -10, -226, -247, -214, -180, -173, -68, -129, -214, -134, -227, -122, -162, -134, -167, -141, -219, -183, -135, -83, -182, -188, -142, -173, -63, -212, -221, -79, -129, -151, -93, -5, -28, -65, -190, -218, -109, -101, -73, -73, -110, -215, -1, -240, -235, -54, -60, -218, -92, -52, -90, -218, -163, -66, -187, -232, -241, -236, -137, -16, -103, -95, -249, -244, -146, -6, -172, -112, -141, -12, -9, -38, -81, -171, -87, -33, -242, -234, -139, -142, -201, -88, -201, -163, -233, -122, -143, -33, -245, -222, -166, -40, -77, -80, -134, -40, -242, -208, -90, -47, -37, -87, -92, -62, -140, -19, -59, -176, -164, -157, -181, -122, -180, -184, -214, -41, -187, -164, -64, -107, -39, -246, -188, -26, -158, -7, -40, -157, -187, -119, -183, -1, -77, -188, -201, -58, -42, -120, -217, -85, -192, -44, -125, -38, -243, -105, -169, -180, -3, -246, -113, -238, -179, -113, -0, -211, -54, -23, -140, -154, -246, -104, -60, -129, -142, -105, -192, -60, -147, -118, -46, -98, -172, -113, -1, -226, -137, -182, -159, -62, -175, -223, -214, -240, -9, -89, -125, -61, -68, -33, -204, -86, -13, -207, -78, -201, -88, -129, -101, -144, -179, -105, -240, -8, -124, -224, -245, -90, -231, -61, -222, -43, -225, -249, -121, -109, -115, -32, -185, -178, -205, -27, -135, -175, -164, -189, -69, -213, -22, -224, -163, -74, -83, -25, -172, -22, -9, -171, -182, -0, -120, -154, -83, -182, -167, -182, -13, -118, -119, -119, -218, -126, -219, -233, -95, -171, -47, -55, -226, -225, -249, -48, -162, -245, -159, -133, -108, -71, -106, -117, -35, -157, -64, -15, -105, -143, -38, -2, -60, -147, -246, -14, -157, -180, -247, -144, -251, -118, -131, -124, -201, -189, -249, -223, -148, -79, -211, -213, -87, -168, -87, -98, -231, -100, -172, -192, -225, -122, -221, -95, -120, -234, -236, -17, -90, -169, -129, -143, -167, -205, -106, -58, -206, -46, -35, -95, -254, -7, -235, -131, -2, -5, -128, -205, -72, -52, -201, -83, -231, -238, -245, -31, -211, -177, -236, -150, -93, -171, -109, -255, -68, -192, -254, -191, -192, -123, -21, -167, -127, -175, -14, -109, -87, -224, -113, -168, -182, -255, -46, -121, -124, -197, -147, -218, -240, -106, -114, -209, -232, -105, -143, -148, -46, -218, -146, -54, -38, -175, -24, -40, -76, -218, -211, -128, -13, -11, -245, -27, -147, -235, -24, -230, -80, -72, -78, -233, -208, -181, -89, -125, -221, -194, -144, -142, -106, -201, -141, -89, -30, -193, -209, -68, -35, -123, -101, -235, -132, -84, -106, -226, -91, -194, -243, -68, -125, -127, -139, -128, -203, -26, -182, -181, -168, -18, -0, -231, -42, -205, -128, -209, -26, -45, -16, -187, -127, -21, -109, -55, -66, -86, -144, -15, -34, -38, -194, -107, -144, -219, -6, -116, -218, -238, -214, -93, -184, -143, -180, -71, -209, -20, -138, -49, -121, -41, -191, -78, -194, -132, -145, -147, -246, -119, -120, -38, -45, -240, -33, -173, -183, -198, -60, -215, -151, -208, -181, -93, -125, -5, -229, -180, -139, -1, -228, -24, -10, -156, -21, -31, -240, -97, -45, -107, -52, -129, -181, -173, -221, -138, -64, -243, -112, -102, -22, -101, -118, -0, -27, -147, -167, -219, -42, -53, -9, -38, -87, -72, -126, -163, -80, -254, -16, -112, -121, -147, -62, -53, -233, -95, -77, -91, -27, -219, -97, -31, -167, -236, -123, -90, -118, -126, -219, -62, -133, -92, -56, -106, -218, -35, -226, -230, -81, -143, -170, -156, -36, -130, -48, -33, -159, -180, -179, -240, -56, -174, -32, -146, -251, -97, -29, -136, -111, -35, -159, -180, -3, -138, -50, -198, -199, -234, -235, -255, -244, -154, -238, -57, -183, -253, -202, -238, -21, -202, -199, -105, -187, -190, -182, -157, -14, -172, -208, -176, -173, -133, -207, -18, -240, -233, -228, -138, -194, -201, -84, -175, -166, -62, -169, -116, -174, -80, -123, -166, -150, -5, -47, -251, -155, -244, -175, -166, -157, -213, -167, -220, -204, -200, -248, -133, -171, -146, -27, -26, -213, -70, -24, -110, -5, -34, -166, -61, -34, -162, -66, -49, -38, -47, -165, -137, -34, -76, -28, -26, -239, -209, -23, -121, -84, -216, -159, -233, -111, -27, -231, -221, -183, -36, -109, -187, -250, -42, -85, -90, -18, -127, -197, -244, -76, -125, -110, -51, -145, -176, -213, -107, -33, -194, -173, -109, -68, -98, -155, -246, -186, -241, -68, -115, -250, -239, -102, -36, -90, -2, -216, -22, -184, -82, -235, -102, -81, -51, -1, -129, -159, -43, -237, -115, -157, -50, -155, -29, -168, -117, -64, -78, -95, -255, -2, -218, -44, -129, -132, -41, -3, -143, -179, -15, -240, -45, -173, -187, -145, -62, -182, -126, -68, -76, -123, -68, -68, -133, -98, -100, -94, -49, -5, -147, -157, -180, -251, -123, -234, -172, -119, -217, -221, -232, -215, -141, -138, -44, -49, -180, -95, -125, -61, -94, -82, -223, -215, -113, -174, -53, -73, -221, -25, -216, -91, -255, -127, -98, -72, -219, -2, -159, -165, -16, -129, -4, -240, -178, -22, -237, -45, -236, -49, -224, -181, -228, -46, -211, -32, -199, -203, -175, -8, -224, -115, -62, -98, -155, -146, -57, -101, -246, -196, -230, -13, -77, -251, -229, -233, -95, -19, -1, -176, -151, -182, -185, -180, -164, -126, -37, -36, -38, -39, -120, -18, -157, -116, -6, -17, -211, -30, -17, -113, -73, -27, -153, -87, -76, -97, -226, -157, -180, -200, -215, -209, -166, -198, -122, -171, -83, -110, -245, -1, -143, -122, -120, -181, -93, -125, -45, -240, -212, -245, -118, -156, -75, -158, -24, -227, -120, -224, -239, -250, -255, -70, -19, -5, -57, -86, -180, -167, -10, -23, -52, -105, -235, -240, -40, -98, -54, -114, -234, -114, -38, -240, -113, -2, -35, -24, -33, -123, -253, -127, -23, -202, -78, -80, -158, -149, -227, -35, -176, -127, -65, -2, -0, -153, -220, -86, -89, -92, -149, -233, -200, -206, -185, -135, -136, -173, -240, -38, -98, -218, -35, -34, -42, -20, -35, -243, -138, -41, -76, -188, -147, -150, -252, -216, -230, -228, -66, -121, -213, -150, -169, -237, -234, -107, -154, -167, -174, -183, -227, -92, -68, -184, -216, -112, -241, -179, -144, -175, -120, -169, -128, -113, -218, -173, -132, -40, -64, -175, -32, -183, -41, -120, -130, -0, -15, -199, -132, -126, -225, -186, -93, -254, -69, -255, -190, -57, -100, -224, -24, -99, -172, -239, -243, -233, -30, -18, -235, -86, -121, -119, -96, -63, -108, -128, -145, -103, -246, -204, -203, -122, -118, -133, -106, -120, -175, -212, -191, -62, -11, -193, -233, -250, -247, -233, -182, -0, -241, -28, -219, -215, -24, -243, -152, -49, -166, -184, -135, -92, -174, -208, -206, -197, -3, -250, -119, -221, -192, -126, -217, -120, -241, -119, -121, -234, -172, -146, -241, -156, -44, -203, -30, -242, -212, -63, -133, -44, -203, -30, -53, -198, -88, -251, -251, -218, -19, -133, -44, -203, -230, -24, -99, -78, -49, -198, -172, -105, -228, -190, -79, -200, -178, -44, -228, -136, -108, -145, -49, -102, -101, -99, -204, -22, -198, -152, -101, -140, -140, -181, -151, -100, -89, -118, -71, -64, -219, -132, -30, -225, -10, -128, -51, -140, -76, -178, -101, -141, -49, -135, -213, -180, -251, -137, -145, -1, -125, -179, -49, -230, -175, -158, -122, -155, -81, -40, -200, -218, -204, -24, -51, -75, -255, -250, -194, -28, -197, -228, -21, -83, -152, -216, -201, -181, -142, -49, -198, -32, -75, -232, -99, -140, -49, -75, -26, -99, -246, -203, -178, -172, -24, -74, -202, -78, -218, -251, -61, -188, -174, -214, -191, -161, -89, -100, -172, -64, -242, -153, -81, -199, -20, -114, -3, -200, -178, -236, -19, -89, -142, -111, -7, -182, -153, -145, -101, -217, -58, -89, -150, -45, -147, -101, -217, -74, -89, -150, -189, -61, -203, -178, -59, -3, -251, -151, -208, -35, -158, -18, -0, -89, -150, -205, -53, -198, -124, -220, -24, -179, -208, -24, -179, -43, -21, -105, -143, -140, -49, -187, -25, -99, -230, -26, -99, -62, -146, -101, -217, -66, -15, -223, -25, -250, -119, -57, -79, -157, -15, -85, -95, -199, -152, -188, -98, -10, -19, -59, -249, -236, -196, -217, -215, -200, -228, -59, -47, -203, -50, -95, -54, -88, -75, -119, -165, -167, -174, -237, -234, -107, -192, -175, -222, -196, -21, -114, -9, -139, -57, -70, -68, -94, -201, -178, -236, -28, -99, -204, -123, -141, -49, -79, -24, -99, -118, -49, -198, -76, -193, -73, -123, -100, -100, -201, -185, -171, -49, -230, -65, -99, -204, -142, -89, -150, -149, -125, -101, -218, -46, -105, -125, -95, -199, -152, -188, -98, -10, -147, -127, -232, -223, -29, -16, -141, -243, -119, -140, -8, -150, -189, -139, -132, -1, -91, -166, -54, -171, -175, -27, -77, -46, -56, -92, -196, -20, -114, -227, -2, -136, -157, -197, -41, -148, -28, -143, -33, -217, -129, -254, -136, -39, -100, -151, -214, -23, -209, -58, -200, -40, -18, -196, -117, -111, -224, -31, -192, -125, -136, -237, -197, -52, -228, -136, -239, -135, -56, -14, -113, -37, -237, -59, -185, -168, -211, -209, -249, -203, -50, -233, -148, -246, -136, -184, -10, -197, -152, -188, -98, -158, -116, -44, -67, -158, -196, -209, -42, -210, -6, -142, -4, -149, -182, -54, -83, -44, -205, -146, -78, -206, -162, -228, -152, -139, -136, -199, -185, -227, -5, -58, -232, -209, -231, -252, -101, -224, -6, -125, -39, -147, -145, -99, -189, -83, -181, -222, -39, -48, -125, -199, -138, -173, -130, -140, -34, -169, -207, -111, -119, -218, -77, -69, -20, -159, -55, -146, -91, -38, -86, -230, -112, -164, -163, -139, -58, -29, -157, -191, -162, -128, -136, -121, -212, -35, -243, -138, -38, -76, -180, -126, -123, -231, -197, -78, -7, -54, -45, -212, -55, -202, -20, -75, -120, -210, -201, -109, -43, -120, -68, -19, -114, -49, -64, -216, -241, -226, -234, -192, -33, -136, -127, -195, -92, -202, -225, -245, -55, -64, -162, -232, -252, -202, -161, -187, -29, -17, -162, -147, -157, -178, -83, -40, -113, -55, -118, -104, -90, -7, -25, -5, -94, -64, -46, -124, -255, -11, -108, -83, -168, -95, -11, -137, -16, -84, -155, -48, -148, -14, -46, -234, -68, -112, -254, -234, -12, -34, -230, -81, -143, -204, -43, -154, -48, -81, -154, -103, -146, -219, -3, -128, -56, -108, -220, -197, -160, -197, -93, -112, -166, -88, -6, -87, -95, -11, -201, -133, -204, -69, -212, -251, -40, -68, -21, -114, -129, -60, -90, -135, -144, -215, -251, -181, -95, -205, -219, -129, -99, -128, -163, -129, -91, -157, -231, -119, -55, -226, -33, -87, -122, -239, -228, -246, -242, -199, -49, -210, -97, -201, -90, -28, -126, -161, -162, -173, -69, -171, -32, -163, -74, -99, -45, -16, -175, -37, -66, -204, -126, -58, -186, -168, -143, -58, -136, -152, -71, -61, -22, -47, -34, -10, -19, -165, -57, -70, -105, -14, -71, -246, -138, -255, -209, -151, -22, -37, -83, -172, -115, -29, -43, -184, -102, -2, -149, -186, -16, -34, -11, -185, -192, -254, -29, -71, -203, -16, -242, -192, -79, -245, -250, -255, -194, -49, -224, -65, -246, -237, -103, -107, -93, -109, -48, -76, -100, -245, -48, -3, -88, -190, -80, -158, -33, -1, -54, -7, -220, -130, -29, -26, -139, -86, -65, -70, -201, -45, -63, -33, -32, -136, -232, -132, -1, -17, -243, -168, -199, -226, -69, -92, -193, -180, -2, -146, -66, -189, -215, -220, -121, -200, -18, -215, -46, -103, -47, -5, -158, -94, -65, -27, -85, -200, -5, -246, -175, -117, -8, -121, -114, -147, -224, -29, -61, -117, -111, -214, -186, -255, -5, -244, -97, -54, -37, -201, -57, -144, -85, -209, -204, -138, -182, -22, -173, -130, -140, -34, -43, -22, -40, -49, -227, -29, -22, -144, -109, -198, -65, -136, -192, -155, -129, -8, -247, -255, -34, -65, -74, -26, -101, -75, -50, -192, -243, -145, -101, -213, -165, -200, -87, -109, -46, -98, -111, -125, -35, -98, -6, -250, -57, -28, -39, -138, -10, -62, -209, -242, -168, -199, -226, -69, -68, -193, -52, -44, -32, -49, -16, -173, -91, -241, -5, -84, -36, -153, -32, -162, -144, -11, -236, -91, -107, -231, -20, -242, -61, -255, -102, -158, -186, -205, -180, -110, -150, -175, -109, -129, -246, -118, -68, -219, -62, -32, -28, -17, -13, -252, -109, -21, -109, -67, -4, -64, -105, -144, -81, -157, -112, -0, -223, -173, -235, -103, -9, -239, -5, -250, -111, -243, -10, -154, -45, -108, -39, -75, -234, -95, -69, -110, -101, -57, -11, -9, -117, -126, -13, -249, -202, -229, -30, -42, -2, -210, -184, -140, -150, -71, -150, -116, -118, -223, -185, -0, -89, -94, -93, -142, -104, -87, -109, -148, -88, -232, -224, -49, -53, -218, -32, -162, -96, -26, -22, -16, -51, -95, -27, -101, -168, -50, -172, -58, -227, -68, -200, -145, -231, -196, -27, -176, -68, -36, -79, -206, -225, -59, -210, -45, -210, -218, -40, -58, -199, -48, -210, -149, -214, -78, -220, -210, -12, -63, -206, -243, -168, -18, -0, -165, -65, -70, -157, -231, -252, -209, -186, -126, -118, -184, -126, -169, -0, -64, -20, -125, -246, -68, -234, -199, -56, -66, -16, -153, -207, -214, -235, -241, -14, -10, -91, -164, -34, -163, -21, -201, -195, -33, -61, -12, -124, -134, -194, -210, -1, -89, -98, -110, -143, -68, -62, -45, -93, -138, -38, -244, -3, -96, -23, -2, -61, -240, -232, -81, -200, -21, -132, -72, -41, -159, -170, -129, -171, -245, -214, -49, -104, -50, -78, -0, -77, -36, -169, -198, -127, -237, -164, -174, -233, -75, -230, -240, -1, -249, -96, -157, -236, -180, -135, -138, -175, -115, -224, -4, -44, -13, -50, -74, -67, -103, -174, -150, -215, -175, -18, -0, -214, -255, -165, -204, -147, -48, -67, -20, -211, -0, -159, -173, -234, -136, -117, -150, -185, -135, -228, -168, -145, -80, -1, -70, -162, -42, -225, -103, -157, -0, -88, -93, -39, -44, -136, -128, -186, -65, -133, -129, -221, -26, -76, -193, -73, -217, -85, -194, -227, -56, -165, -253, -13, -162, -140, -189, -17, -89, -6, -223, -164, -191, -109, -236, -127, -239, -185, -122, -224, -4, -252, -168, -210, -12, -4, -25, -37, -63, -254, -251, -112, -85, -63, -43, -120, -119, -21, -0, -151, -106, -213, -167, -42, -218, -127, -86, -105, -46, -40, -35, -120, -137, -211, -145, -237, -189, -68, -9, -9, -10, -29, -39, -139, -16, -101, -211, -92, -10, -49, -7, -28, -186, -74, -1, -160, -52, -171, -146, -123, -125, -46, -64, -244, -18, -55, -35, -231, -230, -171, -5, -244, -229, -173, -192, -31, -40, -183, -4, -92, -22, -73, -178, -234, -141, -242, -27, -56, -1, -171, -130, -140, -90, -219, -139, -218, -4, -174, -29, -174, -95, -37, -0, -108, -44, -132, -82, -215, -108, -224, -141, -101, -2, -204, -18, -28, -166, -4, -215, -182, -185, -137, -16, -208, -33, -149, -23, -49, -76, -28, -19, -162, -193, -25, -180, -223, -210, -191, -139, -86, -90, -155, -0, -0, -32, -0, -73, -68, -65, -84, -222, -140, -196, -129, -2, -224, -215, -136, -206, -105, -167, -254, -122, -92, -142, -192, -9, -88, -21, -100, -212, -218, -94, -84, -166, -18, -239, -120, -253, -42, -1, -96, -149, -195, -85, -39, -86, -175, -84, -154, -1, -119, -116, -75, -96, -247, -254, -223, -111, -115, -19, -33, -160, -67, -42, -47, -122, -48, -113, -108, -34, -144, -234, -94, -18, -178, -207, -178, -3, -225, -34, -156, -56, -243, -139, -35, -156, -231, -241, -108, -242, -0, -40, -3, -105, -189, -3, -5, -192, -44, -228, -200, -106, -83, -106, -50, -3, -247, -129, -128, -119, -91, -25, -100, -20, -120, -175, -214, -45, -4, -158, -23, -251, -250, -74, -83, -37, -0, -108, -164, -160, -170, -24, -150, -219, -41, -205, -64, -64, -154, -34, -147, -221, -155, -222, -64, -8, -232, -152, -202, -139, -30, -76, -28, -105, -32, -144, -2, -6, -137, -53, -104, -249, -175, -237, -99, -5, -143, -78, -138, -51, -15, -253, -174, -74, -94, -155, -89, -55, -128, -215, -55, -156, -126, -174, -82, -65, -103, -177, -62, -185, -130, -236, -6, -10, -203, -240, -144, -123, -97, -164, -25, -175, -139, -25, -136, -113, -85, -109, -134, -223, -46, -168, -122, -183, -4, -4, -25, -69, -140, -150, -172, -53, -227, -165, -64, -168, -179, -89, -237, -245, -29, -154, -42, -1, -112, -145, -86, -149, -42, -248, -144, -99, -123, -128, -139, -203, -8, -236, -50, -194, -171, -201, -44, -121, -65, -193, -241, -210, -137, -148, -202, -43, -22, -104, -40, -144, -106, -6, -137, -53, -55, -189, -3, -40, -117, -171, -45, -60, -186, -214, -138, -179, -2, -173, -59, -248, -158, -164, -194, -62, -32, -128, -151, -107, -107, -0, -97, -2, -96, -83, -253, -125, -158, -254, -254, -92, -129, -174, -78, -9, -248, -2, -68, -121, -103, -147, -97, -62, -162, -255, -30, -103, -100, -98, -149, -248, -113, -240, -6, -239, -165, -117, -144, -81, -36, -196, -184, -85, -92, -94, -173, -109, -151, -40, -208, -108, -4, -236, -27, -114, -125, -15, -77, -149, -0, -176, -153, -150, -188, -222, -185, -140, -60, -5, -248, -82, -217, -5, -172, -34, -225, -35, -37, -245, -151, -56, -255, -174, -45, -235, -204, -120, -1, -13, -5, -82, -217, -75, -34, -15, -142, -249, -32, -37, -138, -176, -2, -143, -40, -138, -51, -135, -246, -51, -74, -106, -99, -244, -253, -40, -228, -126, -60, -124, -150, -67, -180, -230, -247, -146, -159, -41, -135, -8, -128, -23, -235, -239, -23, -35, -10, -188, -199, -113, -194, -164, -215, -12, -220, -237, -17, -205, -255, -21, -192, -11, -61, -245, -43, -146, -39, -30, -237, -197, -89, -169, -112, -47, -93, -131, -140, -190, -9, -57, -102, -181, -120, -20, -49, -198, -185, -66, -199, -90, -217, -115, -240, -142, -173, -2, -77, -213, -115, -92, -158, -252, -35, -240, -115, -156, -179, -126, -125, -175, -246, -136, -244, -94, -74, -86, -167, -6, -152, -164, -68, -7, -4, -220, -104, -163, -37, -106, -27, -32, -103, -216, -118, -223, -95, -154, -117, -6, -217, -159, -129, -76, -168, -129, -248, -252, -17, -251, -51, -240, -146, -144, -189, -223, -66, -228, -203, -235, -205, -250, -83, -194, -227, -91, -250, -183, -181, -226, -76, -233, -86, -68, -4, -207, -253, -200, -82, -245, -106, -228, -75, -245, -172, -22, -247, -247, -11, -189, -228, -62, -206, -96, -13, -17, -0, -238, -243, -56, -82, -203, -142, -114, -202, -170, -6, -174, -61, -254, -219, -164, -226, -58, -171, -42, -77, -111, -238, -172, -12, -162, -85, -144, -81, -229, -181, -18, -226, -130, -124, -62, -178, -181, -156, -175, -255, -30, -68, -44, -56, -7, -188, -52, -125, -207, -210, -67, -83, -183, -146, -122, -33, -185, -11, -243, -108, -68, -240, -216, -241, -128, -94, -191, -60, -2, -51, -249, -126, -216, -191, -71, -8, -236, -12, -121, -134, -84, -128, -15, -86, -240, -120, -151, -210, -60, -89, -54, -208, -200, -205, -85, -171, -150, -203, -7, -41, -205, -169, -101, -52, -49, -80, -124, -73, -136, -82, -101, -46, -34, -164, -182, -109, -200, -163, -179, -226, -76, -233, -236, -209, -212, -167, -244, -247, -219, -245, -247, -145, -13, -239, -109, -7, -109, -247, -111, -196, -239, -192, -42, -70, -155, -10, -128, -53, -144, -21, -192, -83, -102, -173, -53, -99, -197, -46, -153, -253, -95, -37, -243, -212, -22, -1, -96, -177, -141, -31, -232, -60, -239, -82, -171, -76, -224, -13, -74, -227, -11, -78, -99, -105, -86, -65, -236, -254, -255, -139, -40, -85, -103, -34, -102, -202, -223, -163, -238, -227, -232, -92, -0, -106, -150, -197, -117, -3, -148, -60, -67, -170, -215, -57, -67, -105, -46, -86, -154, -3, -43, -104, -182, -81, -26, -111, -230, -89, -100, -159, -102, -67, -96, -15, -76, -36, -165, -137, -178, -146, -112, -7, -60, -226, -170, -57, -29, -249, -250, -15, -36, -113, -168, -184, -134, -69, -12, -197, -217, -154, -218, -135, -187, -112, -252, -220, -17, -201, -63, -143, -64, -67, -46, -196, -16, -231, -126, -229, -181, -161, -150, -89, -115, -239, -70, -2, -64, -203, -173, -178, -233, -124, -253, -253, -162, -178, -123, -33, -223, -95, -123, -93, -117, -145, -252, -5, -151, -43, -205, -183, -67, -238, -103, -60, -130, -124, -245, -253, -241, -10, -26, -155, -197, -168, -116, -78, -197, -232, -200, -191, -157, -65, -89, -234, -74, -90, -55, -64, -25, -185, -10, -24, -8, -195, -68, -158, -108, -114, -58, -53, -74, -43, -100, -95, -10, -254, -0, -31, -246, -203, -53, -133, -138, -227, -35, -34, -172, -36, -156, -1, -191, -3, -185, -208, -241, -133, -247, -170, -186, -23, -139, -78, -138, -51, -165, -177, -246, -221, -123, -22, -202, -173, -253, -124, -80, -54, -89, -114, -47, -183, -61, -156, -50, -171, -124, -107, -35, -0, -150, -210, -241, -3, -240, -30, -36, -194, -141, -247, -94, -16, -197, -153, -93, -162, -254, -27, -217, -171, -254, -16, -248, -37, -162, -217, -182, -10, -201, -83, -41, -9, -230, -177, -56, -128, -60, -148, -252, -85, -248, -79, -25, -50, -242, -172, -65, -223, -235, -179, -35, -27, -146, -31, -7, -222, -141, -56, -64, -12, -228, -109, -67, -60, -143, -234, -6, -168, -93, -5, -252, -203, -83, -103, -39, -100, -173, -194, -10, -248, -130, -210, -14, -4, -192, -68, -60, -221, -160, -230, -248, -139, -56, -43, -9, -139, -251, -116, -130, -44, -212, -191, -193, -137, -49, -28, -30, -173, -21, -103, -90, -191, -33, -242, -149, -190, -181, -120, -63, -206, -96, -89, -72, -141, -247, -23, -185, -121, -235, -31, -11, -229, -22, -141, -5, -128, -214, -89, -55, -222, -41, -228, -57, -0, -203, -238, -101, -19, -100, -251, -121, -51, -34, -12, -22, -32, -219, -194, -73, -136, -99, -207, -152, -241, -200, -236, -11, -136, -223, -131, -13, -44, -115, -56, -206, -156, -67, -244, -60, -86, -183, -242, -8, -53, -102, -209, -49, -58, -243, -60, -242, -37, -9, -58, -208, -110, -38, -207, -229, -126, -47, -206, -241, -76, -5, -31, -119, -21, -176, -165, -83, -190, -14, -34, -217, -103, -81, -227, -43, -174, -244, -171, -35, -75, -248, -249, -56, -171, -18, -68, -57, -52, -71, -7, -250, -122, -1, -124, -58, -173, -36, -156, -231, -49, -21, -73, -189, -101, -87, -12, -247, -16, -232, -107, -237, -155, -52, -52, -84, -156, -105, -189, -141, -80, -227, -77, -37, -134, -228, -5, -4, -143, -208, -116, -104, -214, -215, -65, -119, -63, -133, -85, -152, -211, -207, -86, -2, -64, -235, -255, -162, -245, -7, -215, -141, -149, -97, -129, -6, -49, -15, -128, -79, -59, -247, -88, -233, -121, -25, -3, -58, -166, -108, -112, -22, -87, -137, -103, -221, -121, -31, -167, -16, -102, -172, -207, -206, -44, -1, -188, -31, -89, -122, -77, -33, -151, -204, -51, -144, -227, -134, -115, -244, -197, -122, -163, -172, -58, -124, -236, -42, -192, -205, -40, -107, -7, -196, -79, -27, -244, -231, -183, -218, -102, -63, -167, -236, -83, -90, -118, -118, -85, -91, -135, -190, -211, -74, -194, -25, -12, -175, -210, -223, -75, -147, -71, -112, -13, -50, -70, -242, -77, -26, -154, -43, -206, -182, -68, -4, -240, -13, -148, -11, -171, -140, -92, -136, -15, -28, -95, -233, -251, -189, -72, -249, -248, -148, -144, -22, -93, -4, -192, -198, -228, -74, -82, -239, -189, -244, -1, -58, -132, -39, -115, -120, -188, -72, -199, -250, -52, -253, -55, -3, -120, -65, -191, -61, -55, -6, -217, -46, -253, -28, -57, -29, -153, -173, -215, -189, -30, -217, -34, -4, -127, -249, -233, -24, -89, -56, -26, -200, -87, -1, -11, -144, -101, -235, -242, -200, -249, -234, -28, -224, -217, -13, -248, -216, -60, -238, -215, -59, -101, -246, -38, -223, -27, -200, -163, -211, -74, -162, -100, -242, -110, -66, -46, -181, -107, -61, -193, -202, -38, -13, -205, -20, -103, -255, -12, -185, -111, -100, -255, -13, -112, -174, -167, -206, -250, -200, -123, -67, -144, -59, -253, -108, -45, -0, -148, -230, -71, -14, -221, -176, -4, -192, -113, -180, -12, -79, -166, -237, -215, -66, -162, -20, -77, -3, -94, -13, -188, -14, -153, -136, -119, -16, -176, -98, -29, -11, -160, -99, -100, -225, -216, -157, -177, -171, -128, -35, -200, -151, -85, -71, -213, -183, -28, -224, -99, -61, -174, -94, -138, -216, -140, -131, -196, -44, -8, -86, -14, -209, -97, -37, -81, -54, -224, -201, -181, -179, -79, -226, -248, -179, -55, -228, -17, -172, -56, -139, -1, -242, -227, -183, -91, -116, -114, -20, -255, -89, -88, -215, -92, -95, -88, -116, -239, -189, -20, -104, -86, -162, -194, -0, -166, -15, -208, -33, -60, -153, -182, -185, -10, -89, -245, -190, -216, -41, -123, -41, -114, -218, -226, -203, -196, -52, -38, -65, -135, -200, -194, -177, -59, -98, -87, -1, -179, -244, -193, -206, -175, -155, -40, -37, -124, -172, -185, -227, -129, -228, -246, -234, -63, -110, -200, -163, -245, -74, -162, -106, -192, -3, -103, -105, -221, -37, -84, -236, -51, -107, -120, -4, -43, -206, -186, -130, -22, -232, -163, -31, -37, -125, -235, -20, -215, -142, -14, -225, -201, -22, -55, -48, -86, -34, -11, -147, -175, -2, -0, -126, -221, -146, -199, -106, -200, -190, -200, -42, -35, -161, -197, -190, -140, -150, -43, -137, -154, -201, -187, -38, -249, -146, -235, -235, -109, -120, -104, -253, -152, -80, -156, -57, -253, -44, -221, -2, -244, -116, -221, -56, -113, -237, -18, -226, -129, -14, -62, -252, -14, -143, -85, -156, -65, -245, -234, -14, -125, -57, -17, -57, -149, -88, -4, -92, -214, -146, -71, -171, -149, -68, -192, -228, -125, -155, -214, -207, -167, -100, -201, -21, -192, -99, -84, -20, -103, -158, -126, -12, -93, -0, -16, -41, -174, -29, -221, -87, -16, -209, -34, -235, -34, -167, -103, -181, -122, -135, -26, -30, -157, -231, -95, -39, -208, -193, -135, -191, -192, -167, -114, -240, -7, -242, -216, -202, -225, -243, -177, -150, -60, -90, -173, -36, -66, -250, -143, -232, -57, -64, -246, -214, -3, -131, -52, -144, -199, -208, -21, -103, -158, -62, -140, -134, -0, -232, -28, -215, -142, -142, -43, -136, -174, -237, -61, -252, -126, -5, -124, -38, -148, -190, -132, -71, -163, -249, -71, -228, -208, -224, -157, -124, -248, -11, -188, -106, -7, -127, -0, -15, -187, -55, -158, -142, -199, -64, -169, -1, -159, -206, -43, -137, -150, -215, -13, -17, -0, -67, -87, -156, -121, -250, -208, -73, -0, -208, -34, -65, -38, -29, -227, -218, -209, -113, -5, -209, -181, -125, -31, -104, -58, -255, -136, -189, -133, -34, -162, -15, -127, -36, -1, -96, -253, -238, -143, -237, -216, -151, -206, -43, -137, -4, -63, -104, -153, -32, -147, -142, -113, -237, -232, -184, -130, -232, -218, -190, -15, -52, -153, -127, -99, -81, -128, -21, -59, -216, -73, -0, -32, -71, -101, -119, -42, -143, -114, -183, -198, -48, -94, -81, -86, -18, -9, -35, -65, -135, -4, -153, -116, -140, -107, -71, -247, -21, -68, -140, -21, -72, -40, -46, -41, -187, -70, -91, -208, -82, -128, -141, -139, -35, -19, -68, -67, -127, -168, -49, -102, -125, -99, -204, -133, -89, -150, -117, -61, -143, -181, -38, -180, -167, -100, -89, -54, -163, -35, -175, -4, -35, -3, -204, -24, -115, -130, -49, -102, -101, -99, -204, -117, -198, -152, -173, -179, -44, -27, -225, -186, -154, -101, -217, -131, -198, -24, -111, -10, -117, -99, -204, -52, -99, -204, -106, -198, -152, -42, -129, -188, -162, -67, -91, -132, -205, -204, -124, -99, -69, -123, -123, -252, -235, -91, -6, -119, -109, -191, -192, -24, -19, -154, -26, -172, -52, -79, -97, -7, -216, -128, -170, -222, -116, -112, -89, -150, -129, -56, -136, -189, -220, -24, -243, -110, -99, -204, -207, -70, -16, -16, -33, -61, -81, -21, -28, -233, -23, -180, -2, -64, -246, -194, -215, -171, -212, -178, -251, -154, -39, -232, -152, -175, -128, -136, -43, -137, -132, -28, -116, -76, -144, -73, -199, -184, -118, -116, -95, -65, -116, -143, -172, -27, -1, -180, -84, -226, -209, -53, -52, -120, -200, -4, -237, -34, -0, -154, -2, -73, -188, -121, -47, -185, -2, -233, -76, -2, -114, -17, -214, -240, -92, -134, -60, -60, -210, -5, -145, -186, -106, -121, -23, -49, -23, -217, -147, -253, -3, -248, -24, -53, -6, -42, -228, -129, -39, -75, -51, -225, -146, -251, -51, -84, -126, -105, -104, -17, -66, -189, -235, -251, -167, -99, -130, -76, -58, -198, -181, -163, -99, -100, -220, -174, -237, -99, -128, -14, -74, -60, -186, -10, -176, -174, -3, -96, -172, -130, -158, -86, -18, -158, -235, -88, -216, -184, -114, -87, -58, -215, -3, -9, -128, -82, -26, -45, -150, -220, -142, -224, -94, -252, -57, -232, -151, -32, -87, -174, -13, -228, -209, -43, -208, -54, -14, -161, -222, -245, -253, -211, -61, -65, -102, -167, -184, -118, -116, -95, -65, -116, -143, -172, -59, -72, -255, -107, -2, -143, -1, -233, -126, -138, -209, -77, -128, -117, -29, -0, -99, -21, -244, -176, -146, -40, -185, -206, -192, -243, -67, -38, -237, -174, -228, -19, -242, -59, -21, -237, -109, -30, -123, -240, -231, -160, -183, -2, -226, -22, -106, -98, -231, -211, -34, -132, -122, -215, -247, -79, -199, -4, -153, -202, -163, -117, -92, -59, -186, -175, -32, -186, -71, -214, -29, -108, -115, -51, -112, -116, -32, -109, -215, -83, -140, -110, -2, -172, -235, -0, -152, -232, -168, -122, -126, -192, -207, -180, -174, -74, -193, -100, -128, -15, -41, -221, -149, -158, -186, -127, -104, -221, -39, -98, -246, -219, -225, -223, -233, -253, -211, -49, -65, -166, -195, -167, -85, -92, -59, -186, -175, -32, -186, -71, -214, -237, -118, -223, -93, -79, -33, -186, -9, -176, -174, -3, -192, -211, -153, -115, -129, -29, -156, -178, -231, -33, -174, -154, -222, -32, -22, -227, -29, -85, -207, -15, -137, -173, -0, -48, -167, -134, -135, -171, -160, -220, -202, -41, -223, -4, -49, -90, -122, -136, -158, -50, -50, -119, -125, -255, -116, -76, -144, -25, -3, -116, -140, -140, -219, -181, -125, -199, -190, -119, -181, -131, -232, -38, -192, -186, -14, -128, -2, -221, -1, -228, -246, -203, -23, -35, -89, -135, -23, -34, -231, -238, -223, -174, -106, -235, -240, -24, -106, -68, -150, -174, -168, -122, -126, -72, -104, -105, -0, -223, -241, -85, -145, -214, -222, -247, -31, -157, -50, -251, -242, -170, -2, -150, -116, -58, -197, -233, -250, -254, -233, -152, -32, -51, -22, -232, -18, -25, -55, -66, -251, -14, -253, -238, -124, -10, -65, -23, -1, -214, -117, -0, -120, -104, -119, -33, -247, -59, -7, -177, -189, -175, -205, -244, -170, -109, -71, -37, -34, -75, -23, -84, -61, -63, -36, -200, -37, -4, -68, -47, -66, -226, -251, -63, -132, -8, -204, -231, -34, -49, -225, -166, -233, -75, -172, -90, -2, -119, -157, -192, -93, -219, -119, -74, -144, -57, -209, -65, -164, -83, -8, -218, -10, -176, -88, -2, -0, -216, -131, -60, -28, -213, -125, -136, -115, -203, -44, -100, -9, -91, -27, -189, -135, -150, -17, -89, -136, -247, -5, -12, -66, -69, -251, -162, -18, -112, -119, -68, -186, -47, -162, -66, -186, -23, -120, -89, -147, -231, -159, -144, -103, -254, -169, -140, -236, -210, -245, -253, -69, -184, -255, -78, -9, -50, -39, -58, -232, -225, -20, -34, -4, -125, -88, -2, -46, -105, -140, -153, -103, -140, -217, -205, -136, -165, -221, -124, -36, -212, -213, -89, -198, -152, -223, -0, -87, -102, -89, -54, -165, -162, -253, -95, -141, -49, -153, -49, -102, -171, -44, -203, -38, -25, -99, -12, -176, -181, -49, -230, -116, -173, -43, -219, -131, -217, -64, -28, -3, -97, -149, -3, -225, -211, -190, -190, -86, -255, -94, -103, -140, -153, -25, -200, -231, -56, -96, -166, -49, -102, -89, -99, -204, -6, -70, -172, -219, -102, -24, -99, -246, -200, -178, -204, -171, -160, -241, -224, -23, -198, -152, -47, -25, -99, -62, -102, -140, -121, -208, -24, -179, -200, -24, -211, -40, -248, -73, -7, -84, -221, -235, -242, -198, -152, -50, -1, -115, -134, -49, -230, -14, -35, -247, -124, -28, -176, -125, -150, -101, -179, -122, -232, -223, -226, -138, -63, -25, -99, -94, -103, -140, -249, -160, -41, -90, -233, -25, -81, -226, -105, -157, -49, -198, -252, -37, -250, -213, -187, -126, -65, -2, -248, -31, -170, -77, -91, -103, -243, -173, -225, -31, -189, -255, -33, -60, -61, -180, -69, -60, -66, -96, -96, -70, -242, -48, -221, -85, -240, -234, -67, -186, -222, -127, -140, -231, -71, -135, -4, -153, -19, -29, -140, -242, -41, -132, -33, -82, -122, -162, -138, -182, -171, -144, -159, -21, -15, -229, -28, -222, -67, -51, -12, -1, -224, -110, -1, -206, -215, -178, -61, -170, -218, -58, -244, -59, -50, -50, -9, -171, -197, -181, -78, -153, -55, -19, -81, -215, -251, -143, -245, -252, -104, -153, -32, -179, -41, -144, -60, -123, -219, -118, -228, -241, -44, -228, -136, -246, -118, -196, -86, -227, -17, -36, -188, -155, -55, -55, -132, -182, -9, -70, -139, -254, -140, -218, -41, -132, -33, -82, -122, -34, -224, -53, -136, -214, -255, -110, -228, -107, -48, -93, -95, -254, -231, -145, -68, -15, -0, -159, -247, -180, -27, -85, -45, -118, -9, -125, -45, -207, -42, -90, -224, -37, -200, -158, -248, -65, -90, -72, -237, -174, -215, -247, -208, -12, -229, -249, -209, -34, -65, -102, -83, -144, -107, -205, -91, -9, -2, -196, -215, -222, -42, -222, -166, -33, -147, -237, -86, -231, -57, -120, -141, -182, -24, -41, -160, -203, -254, -61, -25, -58, -198, -60, -252, -71, -229, -20, -194, -16, -33, -61, -17, -240, -85, -242, -164, -33, -211, -148, -151, -43, -193, -30, -208, -191, -255, -240, -180, -29, -51, -3, -184, -9, -207, -58, -90, -36, -42, -12, -192, -192, -190, -206, -195, -99, -92, -111, -1, -74, -218, -188, -4, -249, -154, -109, -90, -79, -29, -14, -196, -165, -251, -23, -228, -99, -43, -88, -16, -32, -2, -234, -30, -109, -247, -45, -70, -230, -86, -220, -1, -249, -104, -65, -131, -172, -79, -5, -254, -151, -52, -121, -70, -99, -2, -116, -76, -79, -68, -126, -68, -177, -200, -243, -80, -159, -142, -8, -7, -139, -123, -60, -237, -199, -220, -0, -14, -225, -89, -71, -11, -60, -83, -7, -212, -2, -60, -145, -112, -10, -180, -227, -126, -11, -224, -105, -243, -7, -29, -19, -231, -19, -89, -8, -40, -255, -53, -17, -239, -57, -107, -136, -84, -43, -8, -128, -47, -42, -173, -55, -115, -18, -240, -93, -173, -255, -83, -203, -62, -141, -63, -1, -96, -204, -83, -3, -176, -85, -122, -34, -242, -208, -216, -165, -81, -127, -129, -19, -44, -111, -79, -221, -152, -27, -192, -33, -60, -67, -104, -129, -175, -105, -221, -69, -33, -215, -141, -125, -125, -135, -102, -52, -4, -192, -187, -17, -223, -4, -128, -107, -67, -219, -53, -5, -242, -85, -223, -159, -124, -149, -89, -42, -8, -128, -11, -149, -198, -107, -181, -136, -232, -49, -0, -166, -182, -236, -203, -248, -20, -0, -198, -24, -67, -203, -244, -68, -72, -104, -109, -128, -247, -87, -208, -188, -85, -105, -230, -122, -234, -198, -220, -0, -142, -53, -1, -145, -21, -208, -93, -90, -255, -65, -95, -251, -62, -175, -239, -208, -12, -93, -0, -56, -109, -47, -5, -158, -104, -218, -174, -197, -117, -150, -5, -62, -129, -56, -67, -129, -223, -110, -222, -245, -210, -172, -194, -194, -150, -125, -24, -55, -2, -96, -192, -14, -32, -203, -178, -59, -141, -49, -109, -76, -111, -173, -146, -235, -222, -10, -154, -39, -245, -239, -99, -45, -248, -143, -91, -100, -89, -54, -27, -241, -243, -255, -157, -49, -230, -71, -192, -153, -197, -104, -57, -17, -48, -211, -200, -57, -125, -85, -228, -87, -107, -137, -57, -148, -40, -72, -136, -99, -16, -70, -108, -7, -182, -52, -198, -252, -97, -24, -215, -213, -107, -90, -248, -140, -146, -236, -88, -253, -175, -233, -231, -89, -124, -222, -24, -51, -16, -80, -213, -17, -10, -27, -103, -89, -118, -91, -27, -198, -192, -134, -198, -152, -111, -24, -99, -182, -55, -198, -172, -110, -196, -78, -228, -76, -99, -204, -1, -89, -150, -61, -220, -174, -187, -17, -64, -190, -244, -218, -165, -130, -230, -195, -74, -243, -119, -79, -221, -152, -251, -130, -133, -240, -28, -43, -32, -210, -41, -78, -228, -62, -205, -64, -180, -245, -83, -144, -227, -182, -222, -130, -81, -34, -91, -128, -47, -57, -227, -112, -10, -176, -15, -176, -172, -135, -214, -58, -222, -148, -154, -221, -246, -212, -71, -139, -141, -90, -182, -127, -41, -185, -158, -110, -6, -146, -241, -218, -42, -65, -239, -35, -32, -75, -118, -111, -32, -79, -89, -253, -199, -10, -154, -191, -41, -205, -94, -158, -186, -174, -2, -32, -186, -29, -195, -56, -19, -0, -157, -79, -113, -198, -35, -16, -37, -224, -247, -200, -109, -76, -110, -70, -204, -175, -75, -173, -92, -201, -93, -111, -191, -48, -228, -190, -182, -22, -0, -136, -89, -185, -77, -113, -127, -2, -42, -76, -129, -149, -17, -69, -43, -104, -114, -217, -81, -1, -114, -220, -99, -207, -102, -191, -138, -35, -121, -145, -125, -217, -119, -156, -23, -52, -224, -210, -26, -65, -0, -68, -255, -2, -142, -51, -1, -208, -233, -20, -103, -188, -1, -57, -6, -252, -57, -249, -23, -112, -18, -226, -118, -93, -25, -44, -69, -219, -238, -167, -109, -174, -199, -19, -125, -169, -47, -116, -20, -0, -111, -215, -182, -247, -2, -79, -43, -212, -45, -79, -158, -154, -238, -85, -49, -59, -124, -24, -13, -98, -160, -3, -31, -32, -63, -49, -152, -129, -156, -32, -92, -77, -254, -117, -190, -7, -120, -97, -73, -219, -174, -2, -32, -250, -23, -112, -60, -9, -0, -99, -186, -157, -226, -140, -55, -144, -127, -108, -174, -4, -222, -233, -123, -231, -21, -109, -87, -64, -182, -8, -32, -17, -162, -54, -44, -212, -63, -7, -81, -36, -238, -80, -198, -163, -101, -159, -187, -8, -0, -43, -192, -189, -246, -36, -228, -89, -169, -126, -208, -189, -167, -57, -83, -104, -24, -195, -28, -9, -252, -113, -4, -249, -41, -130, -141, -106, -250, -29, -186, -231, -155, -175, -18, -0, -209, -191, -128, -93, -5, -0, -34, -248, -162, -41, -153, -144, -124, -134, -223, -167, -58, -55, -94, -171, -83, -156, -241, -6, -196, -123, -238, -205, -29, -218, -111, -70, -126, -50, -3, -242, -5, -157, -66, -110, -4, -4, -145, -227, -80, -56, -124, -159, -131, -28, -143, -90, -171, -65, -155, -190, -252, -45, -21, -109, -255, -163, -109, -119, -43, -169, -223, -93, -235, -207, -139, -221, -225, -232, -73, -12, -74, -174, -213, -121, -15, -79, -228, -47, -96, -4, -1, -112, -59, -208, -72, -219, -203, -96, -88, -232, -39, -245, -30, -190, -133, -44, -119, -103, -0, -207, -106, -211, -159, -190, -129, -68, -93, -62, -7, -103, -27, -230, -43, -107, -200, -115, -91, -34, -71, -112, -118, -120, -175, -12, -124, -5, -89, -69, -76, -67, -140, -181, -30, -211, -201, -246, -157, -216, -2, -211, -25, -79, -63, -212, -191, -247, -1, -151, -147, -7, -3, -5, -143, -153, -188, -182, -181, -202, -77, -239, -252, -32, -143, -22, -52, -96, -100, -215, -181, -195, -195, -18, -0, -177, -124, -17, -162, -125, -1, -35, -8, -128, -127, -211, -32, -76, -54, -254, -176, -208, -147, -28, -1, -6, -112, -112, -155, -190, -12, -3, -120, -150, -169, -190, -178, -64, -94, -219, -34, -198, -60, -208, -99, -28, -254, -97, -194, -121, -135, -115, -113, -98, -99, -32, -219, -83, -27, -247, -97, -30, -158, -120, -10, -228, -186, -14, -111, -206, -5, -224, -101, -90, -31, -239, -88, -115, -200, -2, -96, -92, -107, -177, -129, -53, -144, -200, -174, -155, -57, -101, -167, -227, -152, -147, -34, -169, -179, -190, -136, -39, -203, -43, -213, -97, -161, -63, -224, -12, -158, -41, -140, -193, -116, -102, -228, -71, -188, -215, -160, -10, -96, -95, -89, -0, -31, -119, -226, -207, -70, -236, -253, -215, -239, -181, -243, -67, -130, -243, -14, -189, -193, -93, -200, -79, -201, -14, -241, -212, -217, -188, -138, -155, -149, -180, -125, -177, -214, -183, -50, -94, -50, -192, -15, -8, -199, -59, -91, -93, -164, -250, -250, -227, -90, -139, -141, -248, -194, -91, -220, -141, -164, -117, -190, -88, -255, -29, -73, -174, -116, -2, -216, -201, -211, -222, -27, -22, -26, -241, -37, -176, -86, -150, -118, -25, -232, -93, -38, -142, -22, -128, -205, -145, -47, -212, -116, -244, -235, -229, -43, -171, -225, -225, -78, -252, -39, -16, -93, -199, -154, -253, -247, -126, -120, -112, -222, -255, -219, -74, -234, -109, -236, -200, -171, -61, -117, -118, -107, -91, -183, -2, -8, -13, -92, -51, -192, -224, -19, -12, -186, -53, -162, -147, -178, -88, -254, -186, -138, -155, -11, -66, -73, -31, -198, -173, -22, -27, -17, -0, -255, -208, -254, -22, -149, -73, -211, -181, -236, -106, -100, -63, -60, -224, -111, -142, -39, -44, -52, -178, -234, -177, -225, -192, -143, -5, -246, -213, -255, -15, -100, -215, -85, -250, -205, -41, -28, -17, -57, -117, -75, -81, -227, -75, -142, -104, -199, -191, -174, -207, -221, -26, -241, -60, -140, -8, -177, -239, -80, -208, -150, -107, -155, -149, -200, -205, -110, -63, -92, -86, -86, -113, -77, -119, -226, -79, -69, -4, -225, -74, -85, -109, -198, -43, -156, -241, -80, -246, -21, -127, -189, -214, -15, -152, -76, -35, -250, -2, -168, -215, -1, -60, -16, -187, -195, -65, -91, -0, -36, -40, -100, -240, -191, -10, -62, -139, -133, -22, -27, -145, -230, -243, -16, -79, -184, -218, -88, -254, -228, -214, -105, -175, -119, -202, -108, -172, -247, -91, -144, -179, -222, -29, -244, -183, -47, -44, -244, -11, -17, -69, -214, -63, -138, -66, -0, -88, -26, -217, -142, -204, -161, -228, -156, -24, -81, -62, -222, -172, -252, -23, -234, -4, -190, -18, -39, -136, -7, -254, -132, -26, -43, -147, -135, -50, -255, -112, -89, -89, -201, -53, -237, -196, -191, -3, -209, -239, -120, -133, -87, -23, -32, -31, -149, -243, -200, -181, -237, -23, -163, -43, -88, -116, -75, -217, -128, -215, -154, -228, -202, -234, -43, -90, -244, -197, -98, -227, -146, -250, -170, -220, -133, -54, -102, -96, -153, -3, -147, -61, -5, -184, -172, -105, -191, -234, -58, -60, -20, -29, -64, -87, -32, -57, -7, -64, -190, -164, -3, -86, -96, -200, -23, -208, -126, -101, -75, -61, -22, -11, -109, -26, -217, -65, -56, -237, -94, -128, -172, -100, -78, -1, -206, -70, -4, -153, -87, -234, -59, -109, -70, -132, -133, -70, -142, -169, -230, -32, -66, -228, -101, -90, -246, -170, -138, -1, -178, -52, -112, -134, -214, -63, -37, -4, -16, -45, -252, -153, -90, -126, -22, -37, -123, -113, -224, -120, -165, -185, -141, -66, -4, -102, -196, -200, -235, -8, -74, -162, -58, -35, -38, -170, -179, -25, -185, -5, -24, -40, -243, -180, -179, -58, -143, -219, -145, -21, -104, -84, -1, -64, -158, -72, -3, -100, -251, -228, -70, -37, -250, -50, -170, -88, -107, -192, -239, -40, -135, -215, -128, -30, -39, -160, -189, -133, -55, -232, -13, -249, -87, -252, -113, -79, -221, -33, -90, -119, -120, -73, -219, -95, -104, -125, -101, -240, -216, -54, -29, -30, -47, -2, -96, -57, -96, -178, -246, -249, -32, -79, -253, -247, -181, -110, -18, -129, -201, -53, -218, -220, -63, -226, -249, -103, -83, -124, -109, -79, -254, -213, -190, -145, -234, -243, -123, -27, -157, -230, -77, -192, -211, -28, -30, -95, -118, -104, -42, -195, -66, -35, -66, -224, -207, -74, -115, -54, -242, -37, -254, -171, -254, -46, -157, -252, -218, -214, -158, -62, -148, -250, -114, -212, -220, -183, -253, -2, -185, -74, -192, -129, -178, -66, -155, -101, -17, -123, -125, -171, -31, -153, -138, -184, -244, -118, -222, -2, -0, -27, -147, -199, -39, -252, -63, -84, -177, -140, -108, -171, -62, -70, -174, -84, -11, -245, -11, -121, -185, -182, -121, -156, -246, -167, -66, -22, -239, -40, -169, -255, -148, -214, -95, -229, -169, -179, -249, -29, -239, -163, -218, -18, -208, -171, -95, -104, -5, -101, -56, -46, -4, -128, -49, -198, -0, -155, -34, -75, -180, -69, -192, -118, -78, -249, -246, -90, -54, -29, -216, -164, -1, -191, -198, -247, -79, -158, -6, -236, -78, -29, -108, -25, -112, -131, -150, -253, -178, -162, -221, -83, -97, -161, -129, -159, -234, -255, -207, -199, -49, -109, -37, -32, -44, -52, -242, -197, -183, -66, -192, -218, -199, -87, -78, -126, -109, -103, -151, -182, -91, -85, -209, -213, -240, -176, -249, -15, -126, -86, -85, -230, -105, -183, -52, -34, -44, -236, -22, -228, -9, -196, -22, -162, -181, -18, -144, -60, -8, -173, -215, -48, -134, -60, -54, -69, -168, -0, -184, -17, -17, -80, -91, -118, -232, -147, -197, -175, -74, -234, -207, -211, -250, -31, -150, -212, -91, -189, -220, -111, -200, -125, -1, -86, -4, -78, -213, -242, -235, -9, -48, -133, -110, -210, -225, -237, -232, -43, -8, -97, -79, -0, -62, -168, -15, -99, -42, -178, -175, -93, -139, -124, -217, -87, -26, -171, -160, -132, -23, -52, -23, -0, -107, -35, -58, -140, -253, -157, -178, -143, -35, -91, -148, -117, -42, -218, -89, -5, -223, -221, -136, -176, -122, -12, -88, -215, -169, -15, -78, -78, -137, -40, -243, -236, -201, -193, -163, -192, -138, -1, -253, -182, -118, -24, -165, -9, -76, -3, -120, -44, -139, -40, -57, -247, -170, -42, -171, -104, -111, -147, -169, -218, -213, -207, -44, -125, -150, -235, -183, -232, -203, -53, -202, -99, -159, -146, -250, -157, -155, -8, -128, -24, -112, -4, -192, -2, -36, -252, -155, -187, -42, -249, -63, -173, -155, -75, -137, -169, -48, -162, -31, -179, -39, -65, -51, -16, -161, -100, -149, -230, -143, -83, -19, -113, -106, -204, -67, -7, -192, -62, -136, -1, -141, -61, -18, -244, -162, -134, -143, -205, -85, -127, -142, -254, -131, -22, -123, -35, -109, -55, -44, -59, -136, -21, -200, -21, -103, -224, -40, -123, -104, -16, -22, -154, -145, -219, -0, -43, -4, -254, -130, -19, -162, -173, -164, -157, -141, -90, -52, -15, -89, -138, -46, -89, -69, -223, -39, -116, -66, -188, -19, -81, -66, -66, -11, -67, -32, -242, -16, -97, -222, -184, -126, -136, -94, -163, -118, -44, -197, -132, -243, -110, -109, -170, -239, -7, -24, -180, -4, -172, -212, -57, -33, -31, -152, -35, -17, -191, -154, -185, -250, -247, -215, -140, -119, -91, -9, -125, -233, -127, -28, -152, -233, -57, -30, -66, -20, -84, -15, -213, -189, -52, -100, -15, -125, -157, -211, -246, -42, -234, -151, -192, -163, -106, -7, -161, -125, -248, -142, -115, -141, -89, -72, -44, -192, -38, -201, -45, -93, -69, -224, -25, -200, -222, -240, -116, -253, -93, -41, -4, -180, -173, -213, -23, -128, -8, -163, -175, -50, -202, -103, -241, -192, -155, -105, -24, -74, -77, -219, -217, -108, -197, -175, -40, -169, -223, -216, -222, -104, -5, -143, -198, -97, -195, -107, -250, -100, -241, -44, -100, -165, -243, -31, -100, -91, -58, -29, -9, -83, -22, -111, -255, -62, -222, -64, -158, -65, -183, -12, -159, -80, -186, -79, -84, -189, -52, -135, -159, -155, -92, -116, -239, -0, -250, -78, -118, -16, -93, -1, -60, -3, -249, -106, -205, -5, -14, -70, -150, -228, -51, -144, -37, -222, -36, -234, -211, -99, -219, -163, -62, -244, -239, -210, -78, -185, -141, -201, -119, -38, -213, -66, -96, -9, -125, -110, -246, -204, -25, -29, -248, -63, -165, -143, -100, -20, -61, -130, -124, -5, -89, -22, -195, -114, -51, -123, -131, -37, -245, -173, -194, -134, -215, -244, -201, -98, -192, -158, -98, -194, -131, -220, -12, -178, -12, -193, -2, -0, -241, -182, -122, -2, -209, -218, -46, -68, -246, -211, -165, -251, -239, -10, -62, -48, -188, -45, -192, -114, -58, -201, -127, -212, -178, -253, -243, -145, -125, -224, -83, -147, -223, -169, -91, -10, -9, -216, -50, -147, -18, -75, -50, -15, -253, -206, -228, -138, -73, -16, -5, -221, -184, -177, -204, -35, -95, -1, -238, -89, -82, -255, -182, -50, -1, -64, -79, -97, -195, -157, -103, -217, -42, -34, -80, -239, -64, -236, -217, -191, -133, -72, -187, -39, -145, -165, -231, -36, -36, -81, -65, -165, -253, -57, -34, -81, -15, -71, -52, -222, -51, -144, -51, -224, -155, -144, -4, -151, -181, -222, -107, -228, -202, -141, -78, -2, -0, -88, -18, -49, -246, -0, -49, -30, -178, -231, -167, -23, -208, -80, -67, -170, -237, -198, -211, -41, -200, -243, -139, -147, -223, -169, -91, -146, -22, -74, -34, -36, -144, -171, -221, -79, -7, -217, -79, -140, -5, -144, -159, -164, -120, -243, -232, -145, -155, -150, -251, -4, -64, -47, -97, -195, -199, -180, -0, -0, -62, -68, -190, -108, -90, -128, -236, -123, -220, -165, -224, -245, -128, -55, -224, -164, -78, -124, -155, -16, -100, -14, -98, -185, -118, -143, -83, -246, -48, -53, -199, -111, -140, -76, -37, -238, -67, -168, -0, -248, -166, -210, -79, -66, -52, -208, -203, -146, -107, -184, -191, -214, -240, -153, -192, -56, -18, -0, -125, -193, -62, -115, -224, -161, -209, -238, -75, -40, -16, -97, -104, -141, -171, -246, -41, -212, -189, -7, -81, -118, -226, -27, -75, -244, -20, -54, -220, -25, -203, -209, -5, -64, -103, -222, -58, -137, -231, -81, -56, -127, -5, -94, -65, -254, -117, -246, -102, -168, -37, -143, -199, -254, -49, -70, -122, -177, -61, -31, -57, -170, -128, -18, -73, -236, -208, -186, -46, -175, -173, -4, -0, -146, -78, -124, -1, -34, -76, -94, -236, -148, -111, -174, -101, -243, -9, -76, -209, -173, -237, -146, -0, -48, -198, -0, -175, -213, -103, -49, -16, -206, -61, -160, -109, -48, -2, -120, -185, -122, -157, -218, -96, -29, -228, -71, -171, -144, -251, -222, -219, -165, -189, -253, -138, -251, -4, -64, -47, -97, -195, -157, -118, -99, -82, -0, -44, -65, -121, -184, -174, -189, -148, -249, -93, -21, -109, -189, -91, -4, -224, -29, -218, -182, -210, -79, -153, -145, -222, -114, -62, -84, -10, -0, -100, -223, -118, -135, -210, -250, -108, -214, -247, -215, -186, -219, -9, -56, -23, -215, -54, -227, -206, -14, -162, -15, -56, -239, -255, -198, -22, -109, -67, -114, -233, -93, -66, -141, -160, -5, -94, -132, -108, -45, -167, -233, -191, -25, -20, -76, -150, -75, -218, -189, -13, -249, -162, -91, -109, -251, -127, -128, -247, -2, -235, -218, -129, -229, -105, -99, -87, -14, -215, -117, -233, -179, -135, -111, -183, -73, -58, -74, -188, -173, -70, -20, -96, -94, -139, -182, -219, -106, -219, -1, -251, -230, -2, -221, -239, -171, -231, -127, -173, -0, -56, -73, -233, -46, -194, -179, -215, -71, -132, -148, -85, -106, -157, -232, -169, -247, -157, -2, -148, -253, -235, -124, -10, -128, -8, -151, -179, -144, -175, -205, -28, -68, -195, -124, -8, -125, -38, -128, -44, -239, -203, -230, -200, -113, -215, -43, -139, -207, -14, -177, -162, -180, -95, -196, -74, -3, -164, -30, -251, -183, -22, -114, -44, -57, -13, -89, -229, -189, -14, -17, -0, -119, -0, -107, -181, -228, -185, -161, -29, -88, -158, -186, -81, -9, -27, -222, -5, -125, -11, -0, -187, -231, -169, -74, -250, -81, -214, -214, -58, -41, -84, -42, -144, -24, -233, -79, -223, -88, -0, -116, -5, -67, -180, -3, -32, -95, -141, -128, -124, -149, -110, -38, -215, -129, -220, -71, -3, -115, -229, -24, -32, -119, -50, -2, -153, -100, -215, -33, -138, -96, -55, -205, -247, -31, -168, -8, -181, -221, -115, -255, -174, -66, -86, -136, -238, -182, -238, -165, -72, -76, -191, -1, -187, -249, -64, -158, -27, -217, -27, -243, -212, -141, -74, -216, -240, -46, -112, -222, -211, -6, -125, -48, -183, -17, -71, -143, -9, -164, -95, -6, -217, -255, -255, -4, -81, -4, -94, -67, -137, -39, -89, -161, -221, -215, -201, -21, -135, -69, -244, -42, -0, -134, -5, -228, -43, -187, -72, -39, -252, -7, -200, -205, -65, -159, -129, -216, -254, -163, -19, -208, -231, -209, -248, -74, -224, -159, -200, -215, -111, -22, -98, -26, -252, -85, -224, -185, -14, -205, -218, -192, -111, -27, -246, -105, -69, -36, -54, -222, -121, -200, -22, -105, -58, -162, -15, -186, -15, -49, -40, -122, -87, -135, -251, -13, -70, -219, -107, -180, -236, -87, -149, -0, -24, -149, -176, -225, -93, -224, -60, -198, -117, -128, -93, -16, -33, -22, -20, -112, -180, -142, -241, -115, -144, -37, -234, -2, -2, -150, -23, -133, -119, -58, -9, -177, -121, -14, -126, -136, -136, -100, -63, -88, -7, -222, -223, -201, -221, -124, -23, -23, -1, -96, -183, -42, -62, -143, -197, -101, -201, -245, -24, -239, -241, -212, -91, -69, -230, -181, -140, -52, -74, -1, -81, -182, -94, -133, -76, -220, -57, -195, -185, -155, -122, -16, -73, -7, -208, -67, -191, -170, -4, -192, -168, -132, -13, -239, -2, -103, -28, -88, -147, -241, -224, -128, -163, -85, -76, -151, -6, -46, -211, -198, -65, -241, -198, -145, -175, -215, -36, -196, -1, -103, -33, -114, -58, -112, -8, -29, -44, -201, -22, -51, -1, -112, -183, -222, -207, -75, -74, -234, -109, -16, -144, -147, -61, -117, -39, -1, -207, -116, -126, -111, -4, -124, -67, -5, -194, -60, -196, -208, -231, -92, -26, -156, -116, -140, -7, -16, -217, -36, -87, -121, -150, -10, -0, -173, -111, -21, -54, -92, -203, -175, -211, -255, -55, -10, -253, -221, -165, -207, -78, -159, -230, -225, -56, -189, -17, -16, -112, -180, -234, -130, -191, -210, -134, -151, -208, -98, -255, -135, -44, -107, -191, -174, -23, -190, -159, -246, -57, -209, -22, -39, -1, -96, -207, -159, -159, -81, -82, -111, -143, -220, -90, -37, -143, -92, -220, -64, -15, -38, -185, -202, -183, -82, -0, -40, -77, -227, -176, -225, -202, -114, -22, -178, -53, -131, -24, -95, -226, -128, -62, -59, -188, -27, -7, -28, -45, -187, -216, -193, -218, -224, -150, -178, -193, -218, -160, -227, -214, -56, -231, -172, -150, -237, -163, -11, -0, -26, -160, -130, -199, -70, -136, -95, -249, -125, -200, -210, -252, -126, -196, -87, -187, -84, -202, -234, -64, -2, -120, -126, -73, -253, -139, -180, -62, -118, -246, -224, -113, -7, -122, -50, -201, -237, -19, -206, -176, -105, -28, -250, -59, -128, -119, -136, -0, -104, -28, -112, -212, -71, -252, -37, -37, -190, -31, -71, -193, -212, -22, -228, -199, -136, -173, -34, -150, -106, -219, -216, -2, -96, -114, -205, -191, -59, -170, -250, -140, -28, -157, -89, -203, -201, -153, -136, -38, -223, -250, -102, -79, -163, -124, -137, -111, -51, -188, -120, -29, -148, -200, -5, -111, -212, -88, -248, -248, -49, -27, -89, -214, -158, -137, -196, -81, -240, -154, -74, -3, -171, -43, -237, -28, -58, -126, -12, -26, -246, -185, -23, -147, -220, -62, -225, -60, -219, -56, -95, -226, -145, -109, -67, -4, -128, -215, -220, -155, -138, -128, -163, -69, -66, -43, -41, -30, -2, -54, -109, -218, -201, -18, -158, -219, -40, -207, -39, -91, -182, -135, -33, -111, -1, -16, -255, -7, -128, -95, -148, -212, -159, -171, -245, -167, -161, -70, -80, -136, -242, -200, -122, -222, -157, -91, -210, -110, -31, -173, -191, -31, -71, -72, -32, -118, -10, -159, -33, -15, -85, -85, -105, -55, -209, -226, -126, -44, -174, -37, -87, -188, -93, -67, -110, -231, -15, -162, -120, -245, -230, -216, -67, -124, -206, -1, -190, -26, -179, -95, -53, -125, -238, -197, -36, -183, -79, -56, -207, -178, -251, -151, -120, -176, -109, -136, -0, -40, -139, -191, -88, -26, -112, -212, -37, -218, -133, -220, -123, -46, -90, -66, -76, -242, -0, -8, -173, -242, -150, -105, -219, -161, -9, -0, -196, -51, -239, -17, -125, -22, -94, -215, -77, -114, -31, -253, -77, -10, -229, -207, -215, -242, -178, -149, -195, -146, -72, -188, -62, -144, -109, -195, -69, -200, -23, -248, -78, -189, -158, -77, -144, -50, -37, -242, -61, -89, -108, -81, -40, -95, -18, -216, -155, -252, -248, -213, -123, -228, -135, -156, -206, -128, -40, -49, -135, -18, -44, -132, -158, -76, -114, -251, -132, -211, -167, -198, -161, -191, -29, -154, -98, -36, -227, -75, -16, -235, -197, -245, -44, -243, -138, -235, -54, -10, -56, -234, -198, -155, -219, -193, -24, -115, -146, -49, -102, -166, -49, -102, -199, -44, -203, -130, -82, -104, -107, -219, -115, -145, -44, -48, -43, -23, -202, -215, -0, -14, -52, -198, -88, -103, -12, -175, -47, -193, -24, -196, -158, -198, -152, -213, -141, -49, -103, -100, -89, -118, -123, -9, -205, -52, -253, -187, -160, -80, -190, -72, -255, -122, -95, -112, -150, -101, -11, -141, -49, -59, -25, -99, -190, -96, -140, -153, -108, -140, -121, -153, -49, -102, -107, -99, -204, -29, -198, -152, -237, -140, -49, -147, -148, -244, -250, -86, -61, -111, -136, -44, -203, -22, -102, -89, -246, -75, -99, -204, -63, -181, -104, -235, -18, -186, -107, -140, -49, -151, -25, -99, -214, -53, -198, -120, -131, -90, -246, -0, -59, -158, -254, -107, -140, -185, -180, -226, -95, -235, -80, -216, -200, -138, -237, -54, -59, -118, -129, -85, -145, -237, -223, -192, -41, -76, -67, -148, -29, -197, -206, -210, -191, -222, -0, -177, -72, -68, -160, -191, -25, -99, -94, -175, -180, -55, -27, -99, -54, -50, -198, -156, -106, -140, -217, -55, -224, -186, -235, -151, -148, -91, -157, -147, -127, -60, -147, -239, -95, -167, -82, -189, -55, -30, -152, -196, -142, -244, -89, -132, -40, -109, -254, -135, -124, -209, -236, -87, -101, -1, -78, -116, -219, -166, -80, -30, -67, -89, -1, -32, -190, -240, -246, -248, -231, -213, -21, -116, -39, -42, -205, -247, -10, -229, -54, -241, -99, -144, -209, -148, -135, -175, -221, -215, -182, -142, -205, -87, -194, -215, -194, -187, -178, -67, -18, -143, -0, -28, -86, -193, -99, -87, -165, -137, -151, -129, -182, -2, -12, -193, -36, -23, -209, -107, -0, -188, -86, -127, -219, -232, -187, -179, -91, -242, -179, -104, -19, -250, -187, -117, -36, -99, -231, -186, -173, -2, -142, -54, -209, -138, -159, -230, -105, -187, -35, -162, -13, -159, -132, -156, -151, -206, -71, -20, -97, -147, -17, -43, -194, -78, -193, -10, -245, -186, -195, -18, -0, -187, -233, -245, -42, -147, -122, -34, -203, -49, -235, -37, -249, -83, -96, -3, -242, -173, -206, -245, -180, -8, -158, -161, -47, -218, -186, -46, -87, -230, -17, -104, -193, -219, -98, -64, -0, -32, -250, -7, -27, -64, -99, -192, -0, -201, -161, -91, -218, -185, -103, -175, -227, -88, -76, -48, -4, -147, -92, -6, -87, -0, -171, -32, -43, -128, -83, -90, -242, -179, -104, -19, -250, -187, -117, -36, -99, -231, -186, -173, -2, -142, -38, -152, -167, -30, -150, -141, -72, -91, -107, -254, -138, -72, -236, -171, -25, -137, -95, -2, -171, -180, -188, -190, -245, -186, -59, -191, -77, -251, -26, -222, -3, -2, -0, -49, -217, -222, -20, -56, -70, -235, -254, -76, -137, -18, -208, -105, -99, -227, -22, -30, -25, -187, -143, -158, -107, -141, -103, -147, -220, -198, -95, -98, -58, -68, -50, -214, -226, -7, -201, -117, -72, -141, -3, -142, -78, -120, -32, -209, -111, -64, -108, -31, -106, -163, -7, -233, -132, -189, -23, -145, -186, -214, -113, -230, -6, -26, -154, -136, -34, -193, -59, -191, -170, -124, -102, -81, -178, -124, -236, -2, -170, -113, -17, -162, -195, -169, -156, -252, -202, -231, -89, -200, -57, -246, -116, -122, -142, -19, -200, -248, -54, -201, -109, -252, -37, -166, -67, -36, -99, -45, -254, -147, -254, -63, -5, -28, -109, -3, -114, -119, -225, -79, -214, -208, -45, -1, -252, -86, -105, -47, -70, -52, -255, -203, -34, -73, -61, -158, -64, -116, -31, -7, -86, -180, -255, -53, -146, -190, -235, -207, -72, -8, -116, -27, -12, -229, -1, -122, -74, -126, -234, -12, -76, -247, -24, -240, -74, -36, -142, -224, -2, -189, -247, -215, -4, -242, -58, -89, -121, -125, -174, -143, -190, -22, -174, -213, -202, -36, -55, -128, -175, -133, -111, -34, -214, -90, -9, -6, -240, -109, -28, -250, -155, -8, -145, -140, -19, -90, -2, -241, -51, -7, -9, -95, -86, -153, -58, -140, -220, -162, -235, -66, -10, -81, -118, -145, -175, -210, -157, -90, -255, -145, -146, -246, -199, -32, -147, -126, -1, -114, -212, -117, -33, -98, -244, -210, -219, -23, -213, -25, -124, -190, -99, -192, -143, -146, -7, -80, -173, -253, -154, -146, -43, -202, -110, -33, -96, -213, -208, -21, -180, -48, -201, -13, -224, -217, -183, -0, -104, -28, -250, -155, -142, -145, -140, -163, -0, -241, -40, -67, -59, -28, -108, -245, -165, -15, -237, -24, -68, -241, -247, -184, -182, -191, -9, -113, -96, -241, -90, -197, -105, -187, -189, -169, -135, -215, -168, -166, -192, -103, -101, -100, -207, -120, -33, -50, -169, -230, -107, -31, -130, -246, -170, -228, -201, -52, -106, -181, -239, -228, -169, -175, -203, -94, -148, -205, -225, -55, -102, -236, -249, -157, -103, -89, -119, -10, -16, -116, -164, -134, -172, -36, -96, -12, -45, -191, -155, -192, -121, -30, -125, -9, -128, -198, -161, -191, -233, -16, -201, -56, -26, -144, -244, -67, -54, -209, -96, -80, -54, -29, -196, -44, -214, -218, -184, -207, -69, -20, -105, -215, -144, -47, -211, -230, -1, -59, -149, -180, -253, -134, -210, -84, -29, -63, -86, -30, -169, -33, -150, -134, -110, -84, -225, -7, -181, -221, -20, -224, -204, -128, -254, -111, -138, -44, -219, -103, -19, -32, -244, -200, -29, -122, -188, -209, -142, -129, -103, -107, -253, -88, -114, -203, -173, -19, -0, -31, -209, -250, -89, -190, -122, -15, -253, -158, -74, -223, -202, -191, -99, -180, -49, -4, -1, -208, -88, -219, -78, -135, -72, -198, -81, -1, -108, -73, -30, -87, -255, -229, -1, -244, -103, -105, -191, -46, -99, -100, -64, -209, -229, -200, -143, -46, -38, -151, -180, -181, -254, -203, -94, -205, -103, -192, -181, -55, -35, -183, -202, -251, -13, -133, -227, -41, -2, -180, -199, -228, -49, -7, -74, -147, -119, -22, -232, -173, -75, -175, -247, -235, -135, -88, -84, -2, -220, -20, -118, -23, -253, -35, -64, -0, -216, -19, -136, -202, -216, -141, -14, -253, -211, -17, -47, -189, -133, -244, -17, -133, -166, -103, -140, -81, -1, -208, -58, -146, -113, -116, -168, -16, -120, -0, -184, -33, -128, -214, -106, -47, -7, -98, -229, -145, -155, -144, -122, -191, -134, -192, -41, -90, -223, -202, -186, -140, -252, -88, -165, -84, -233, -86, -211, -126, -29, -125, -176, -139, -8, -244, -208, -34, -63, -175, -189, -157, -130, -177, -16, -98, -19, -97, -87, -80, -251, -151, -241, -24, -54, -2, -4, -128, -117, -253, -190, -188, -1, -79, -123, -228, -116, -104, -188, -158, -14, -7, -99, -81, -0, -104, -251, -170, -72, -198, -95, -71, -21, -198, -109, -120, -247, -134, -154, -135, -121, -144, -214, -253, -179, -164, -237, -249, -90, -95, -187, -210, -240, -180, -125, -177, -182, -157, -66, -77, -242, -203, -10, -30, -118, -50, -255, -185, -65, -155, -21, -201, -189, -250, -64, -190, -132, -55, -50, -50, -161, -233, -25, -4, -158, -93, -3, -107, -146, -167, -231, -190, -34, -176, -77, -211, -16, -217, -22, -69, -37, -96, -6, -236, -65, -174, -129, -174, -205, -226, -235, -180, -125, -46, -185, -239, -200, -114, -161, -237, -106, -250, -215, -118, -226, -108, -139, -124, -76, -110, -211, -73, -50, -3, -49, -170, -58, -20, -143, -14, -170, -102, -204, -142, -154, -0, -80, -30, -222, -72, -198, -90, -119, -93, -155, -228, -11, -222, -105, -0, -0, -32, -0, -73, -68, -65, -84, -126, -245, -10, -223, -77, -35, -103, -184, -54, -55, -252, -109, -192, -179, -75, -218, -94, -175, -52, -222, -250, -154, -235, -30, -168, -109, -127, -210, -178, -223, -171, -146, -235, -41, -26, -69, -250, -69, -172, -226, -246, -65, -142, -207, -30, -211, -9, -244, -40, -18, -179, -239, -169, -88, -127, -129, -188, -142, -210, -62, -60, -0, -60, -39, -128, -190, -113, -136, -108, -231, -29, -185, -199, -128, -151, -147, -103, -16, -6, -57, -222, -107, -154, -61, -233, -47, -218, -246, -227, -77, -218, -85, -244, -175, -205, -210, -217, -21, -134, -183, -35, -177, -18, -239, -33, -55, -157, -29, -88, -29, -86, -93, -143, -252, -195, -50, -42, -2, -96, -84, -65, -139, -240, -75, -197, -155, -70, -190, -12, -54, -106, -203, -239, -168, -176, -140, -115, -6, -224, -13, -228, -122, -135, -25, -136, -34, -241, -48, -96, -227, -138, -182, -214, -183, -250, -3, -136, -34, -240, -92, -228, -4, -194, -102, -214, -221, -151, -81, -138, -100, -27, -10, -36, -86, -194, -66, -237, -119, -173, -7, -38, -45, -67, -100, -227, -199, -34, -114, -161, -181, -107, -203, -254, -91, -151, -220, -255, -182, -105, -239, -233, -95, -27, -1, -96, -141, -176, -182, -43, -148, -175, -130, -152, -118, -15, -40, -107, -201, -133, -195, -139, -60, -117, -54, -151, -197, -216, -250, -210, -246, -13, -90, -134, -95, -42, -190, -60, -242, -188, -238, -181, -54, -220, -192, -57, -74, -251, -24, -18, -84, -99, -50, -249, -30, -26, -68, -8, -121, -191, -46, -228, -86, -98, -135, -32, -95, -224, -123, -144, -47, -210, -69, -228, -10, -147, -191, -50, -138, -185, -238, -235, -128, -108, -29, -166, -2, -91, -6, -210, -71, -15, -145, -61, -22, -208, -81, -0, -216, -49, -251, -170, -6, -109, -236, -24, -123, -183, -167, -238, -232, -9, -39, -0, -232, -16, -126, -201, -35, -0, -172, -86, -62, -40, -35, -47, -158, -76, -61, -192, -243, -200, -45, -206, -22, -1, -219, -122, -104, -158, -112, -234, -191, -228, -78, -116, -196, -108, -210, -30, -13, -214, -166, -7, -79, -24, -93, -116, -20, -0, -214, -131, -114, -26, -18, -200, -165, -54, -89, -8, -185, -221, -199, -21, -56, -33, -235, -17, -109, -187, -213, -196, -79, -40, -1, -208, -58, -252, -146, -71, -0, -156, -161, -191, -255, -71, -71, -175, -54, -135, -215, -217, -158, -58, -171, -184, -250, -105, -73, -91, -107, -100, -84, -233, -217, -151, -48, -250, -112, -198, -208, -250, -72, -120, -178, -43, -244, -67, -242, -36, -178, -69, -169, -212, -209, -0, -7, -56, -60, -230, -35, -137, -76, -94, -91, -65, -255, -26, -103, -252, -204, -64, -156, -186, -172, -201, -241, -183, -24, -35, -218, -118, -2, -17, -227, -66, -173, -195, -47, -57, -253, -176, -2, -96, -53, -196, -198, -29, -100, -41, -254, -77, -90, -46, -195, -145, -99, -53, -240, -251, -79, -91, -205, -185, -55, -12, -54, -98, -224, -3, -53, -161, -200, -144, -213, -198, -137, -200, -82, -124, -62, -178, -31, -191, -4, -201, -224, -227, -205, -136, -172, -237, -90, -5, -147, -64, -146, -119, -124, -13, -81, -194, -77, -211, -107, -78, -69, -132, -221, -86, -177, -219, -141, -7, -56, -99, -200, -166, -115, -191, -27, -217, -130, -218, -119, -60, -159, -146, -248, -12, -192, -203, -144, -45, -228, -99, -200, -135, -234, -50, -135, -223, -241, -192, -178, -37, -237, -222, -128, -156, -66, -77, -67, -38, -252, -53, -168, -249, -54, -37, -218, -246, -226, -88, -47, -212, -133, -132, -236, -170, -132, -167, -93, -85, -46, -5, -107, -143, -210, -42, -212, -94, -241, -66, -173, -195, -47, -249, -30, -10, -162, -37, -255, -6, -121, -128, -131, -179, -129, -167, -181, -232, -151, -245, -128, -26, -8, -208, -128, -40, -42, -161, -160, -252, -113, -234, -159, -161, -245, -165, -89, -109, -17, -187, -118, -235, -140, -51, -23, -209, -67, -184, -105, -209, -75, -99, -236, -211, -50, -152, -4, -185, -185, -245, -124, -228, -20, -228, -42, -242, -237, -204, -2, -224, -245, -49, -219, -85, -244, -227, -45, -218, -54, -232, -232, -209, -211, -126, -64, -168, -35, -19, -174, -18, -37, -188, -44, -230, -3, -187, -56, -229, -171, -59, -247, -93, -182, -58, -181, -31, -155, -55, -59, -101, -219, -144, -7, -118, -245, -174, -16, -219, -192, -233, -103, -83, -1, -112, -82, -200, -191, -6, -253, -88, -146, -252, -4, -173, -117, -176, -29, -151, -97, -235, -140, -168, -53, -15, -101, -11, -114, -79, -168, -160, -228, -34, -133, -246, -239, -212, -182, -183, -122, -234, -172, -17, -145, -247, -1, -144, -11, -143, -187, -43, -248, -219, -243, -252, -75, -113, -204, -128, -17, -171, -172, -255, -171, -233, -91, -171, -96, -18, -136, -78, -229, -211, -56, -206, -63, -136, -213, -164, -221, -151, -150, -5, -20, -109, -213, -174, -162, -31, -246, -20, -197, -187, -234, -83, -154, -181, -17, -99, -171, -199, -245, -126, -183, -208, -242, -221, -128, -251, -60, -244, -239, -69, -242, -44, -22, -255, -253, -81, -175, -229, -181, -52, -116, -198, -208, -81, -158, -58, -235, -7, -255, -96, -73, -91, -43, -192, -87, -45, -148, -111, -169, -229, -211, -124, -237, -218, -160, -102, -172, -183, -182, -31, -104, -209, -15, -107, -185, -121, -55, -45, -62, -172, -62, -134, -173, -195, -47, -85, -61, -20, -173, -183, -166, -177, -222, -244, -226, -53, -188, -173, -153, -241, -64, -116, -94, -29, -108, -32, -202, -203, -1, -15, -62, -224, -251, -90, -95, -154, -43, -143, -124, -133, -210, -58, -99, -75, -44, -144, -123, -36, -54, -90, -210, -181, -105, -135, -100, -199, -93, -132, -28, -161, -121, -151, -200, -74, -119, -28, -178, -23, -159, -172, -244, -139, -244, -255, -179, -8, -207, -21, -185, -20, -249, -87, -220, -235, -106, -237, -140, -161, -1, -111, -57, -242, -92, -9, -197, -248, -139, -182, -222, -58, -103, -125, -177, -80, -190, -154, -150, -63, -28, -210, -207, -16, -140, -5, -1, -128, -196, -143, -176, -10, -238, -82, -225, -221, -148, -105, -235, -240, -75, -1, -2, -96, -11, -173, -247, -45, -227, -255, -12, -236, -4, -172, -84, -40, -127, -22, -185, -121, -234, -116, -96, -125, -79, -219, -165, -200, -61, -168, -46, -70, -181, -191, -136, -117, -219, -222, -200, -228, -94, -68, -197, -241, -144, -211, -247, -129, -243, -224, -97, -131, -138, -156, -245, -177, -219, -1, -63, -214, -38, -3, -57, -10, -11, -116, -83, -129, -15, -232, -255, -95, -140, -172, -2, -108, -154, -171, -160, -212, -220, -136, -82, -13, -224, -156, -10, -26, -139, -1, -165, -113, -221, -196, -66, -44, -231, -108, -252, -201, -19, -201, -117, -81, -54, -191, -197, -9, -33, -253, -12, -188, -151, -210, -177, -94, -215, -207, -136, -125, -248, -182, -94, -230, -26, -98, -185, -99, -211, -33, -252, -146, -251, -80, -244, -101, -63, -203, -169, -91, -154, -220, -34, -112, -96, -175, -233, -180, -93, -132, -68, -215, -185, -158, -145, -250, -136, -71, -41, -217, -227, -107, -251, -231, -147, -239, -217, -231, -33, -123, -120, -55, -88, -68, -229, -254, -200, -161, -107, -44, -0, -104, -153, -179, -14, -17, -92, -31, -68, -142, -57, -39, -33, -210, -124, -58, -185, -86, -186, -108, -160, -183, -106, -231, -225, -179, -28, -121, -32, -144, -245, -234, -250, -26, -194, -179, -162, -253, -75, -245, -189, -60, -65, -197, -177, -176, -59, -134, -60, -117, -33, -105, -188, -94, -67, -190, -202, -88, -132, -40, -74, -23, -33, -218, -253, -213, -187, -220, -67, -204, -126, -70, -184, -254, -51, -201, -21, -163, -241, -130, -165, -210, -33, -252, -146, -251, -80, -156, -23, -112, -51, -98, -16, -100, -39, -243, -130, -146, -182, -111, -67, -162, -235, -220, -138, -44, -43, -109, -176, -135, -203, -144, -211, -131, -218, -224, -154, -136, -178, -239, -80, -229, -49, -87, -219, -159, -77, -64, -242, -72, -167, -239, -141, -4, -0, -237, -141, -166, -214, -36, -247, -165, -183, -207, -197, -70, -82, -182, -171, -25, -159, -18, -169, -85, -187, -146, -62, -216, -253, -227, -233, -77, -238, -185, -41, -144, -152, -131, -54, -198, -226, -110, -53, -180, -79, -141, -33, -79, -93, -240, -196, -2, -94, -133, -172, -28, -109, -148, -235, -203, -112, -18, -170, -118, -69, -172, -126, -118, -184, -190, -141, -223, -248, -215, -62, -152, -119, -201, -136, -138, -62, -128, -189, -244, -161, -79, -67, -36, -255, -20, -100, -153, -223, -200, -214, -190, -111, -144, -107, -240, -189, -168, -105, -219, -197, -104, -234, -55, -90, -55, -21, -49, -58, -121, -186, -83, -87, -165, -69, -110, -213, -174, -164, -255, -255, -85, -242, -202, -47, -8, -29, -143, -29, -17, -229, -31, -4, -164, -238, -114, -199, -144, -167, -174, -241, -196, -66, -78, -15, -78, -213, -102, -165, -91, -143, -166, -168, -233, -103, -175, -17, -123, -128, -23, -34, -130, -127, -1, -125, -69, -101, -166, -135, -240, -75, -99, -17, -136, -143, -194, -105, -206, -11, -61, -71, -127, -159, -134, -39, -244, -121, -161, -109, -23, -163, -41, -187, -106, -24, -8, -23, -70, -158, -67, -209, -39, -0, -90, -181, -243, -208, -110, -173, -164, -33, -110, -222, -173, -143, -29, -17, -197, -164, -13, -150, -26, -178, -138, -171, -154, -88, -173, -190, -172, -136, -16, -128, -192, -32, -39, -129, -60, -45, -124, -62, -4, -189, -70, -236, -33, -63, -181, -57, -186, -15, -254, -19, -18, -85, -47, -180, -162, -77, -23, -163, -41, -123, -234, -176, -173, -167, -206, -38, -21, -241, -9, -128, -86, -237, -60, -180, -246, -171, -248, -169, -0, -218, -182, -199, -149, -79, -71, -182, -128, -224, -177, -181, -47, -105, -211, -74, -0, -32, -142, -103, -251, -81, -80, -18, -35, -129, -91, -191, -172, -205, -188, -193, -104, -218, -192, -233, -167, -207, -135, -224, -136, -190, -4, -0, -121, -66, -145, -25, -44, -38, -31, -225, -49, -129, -150, -2, -160, -139, -209, -148, -221, -175, -31, -135, -42, -216, -116, -176, -238, -69, -133, -50, -175, -109, -187, -2, -143, -103, -145, -39, -109, -25, -240, -191, -104, -112, -255, -149, -199, -142, -136, -98, -20, -224, -196, -6, -60, -45, -154, -10, -128, -45, -156, -182, -83, -145, -149, -235, -21, -228, -43, -166, -57, -56, -6, -66, -93, -225, -92, -171, -232, -67, -240, -46, -122, -138, -216, -163, -239, -217, -234, -127, -190, -21, -147, -247, -168, -163, -234, -197, -7, -180, -253, -56, -18, -94, -123, -153, -170, -178, -138, -246, -75, -59, -215, -127, -126, -29, -189, -211, -174, -139, -209, -212, -78, -133, -1, -123, -53, -185, -13, -198, -126, -168, -34, -54, -86, -187, -2, -15, -107, -47, -255, -243, -208, -123, -45, -225, -83, -122, -236, -136, -36, -191, -180, -39, -58, -193, -9, -82, -170, -198, -1, -213, -2, -96, -57, -224, -115, -250, -188, -109, -92, -134, -199, -16, -229, -227, -49, -68, -202, -112, -237, -233, -39, -228, -62, -4, -174, -242, -124, -126, -221, -123, -104, -113, -205, -143, -40, -255, -7, -0, -111, -78, -193, -113, -139, -170, -23, -31, -208, -214, -198, -19, -60, -162, -170, -172, -162, -253, -122, -206, -245, -87, -171, -163, -119, -218, -117, -202, -89, -135, -248, -155, -95, -142, -40, -11, -167, -33, -166, -172, -239, -214, -186, -147, -203, -6, -80, -219, -118, -90, -239, -166, -245, -10, -18, -118, -180, -56, -118, -116, -38, -195, -121, -248, -45, -2, -127, -0, -172, -27, -246, -164, -198, -30, -156, -241, -178, -23, -114, -234, -51, -15, -17, -118, -135, -33, -6, -58, -255, -139, -41, -0, -144, -237, -148, -85, -56, -119, -10, -186, -210, -244, -194, -0, -199, -55, -108, -179, -153, -14, -208, -25, -192, -5, -84, -4, -243, -40, -92, -167, -173, -0, -88, -150, -124, -105, -180, -91, -89, -89, -69, -123, -155, -171, -189, -209, -30, -145, -33, -228, -172, -139, -13, -36, -104, -10, -4, -154, -11, -211, -254, -184, -50, -4, -193, -126, -251, -99, -13, -206, -61, -84, -218, -79, -68, -188, -222, -87, -236, -24, -101, -152, -113, -45, -90, -10, -128, -203, -145, -229, -247, -54, -136, -86, -253, -162, -192, -235, -180, -18, -0, -218, -254, -121, -136, -192, -153, -137, -6, -201, -240, -149, -121, -218, -109, -133, -236, -229, -231, -18, -96, -47, -80, -104, -59, -30, -115, -214, -89, -135, -153, -218, -156, -135, -74, -31, -237, -216, -113, -113, -130, -51, -94, -135, -18, -9, -153, -60, -206, -228, -221, -52, -216, -106, -182, -189, -216, -26, -136, -59, -166, -53, -222, -88, -136, -44, -233, -206, -69, -114, -215, -85, -38, -59, -208, -9, -103, -131, -23, -238, -2, -76, -15, -184, -102, -39, -1, -160, -60, -62, -172, -60, -110, -69, -77, -138, -125, -101, -37, -215, -125, -130, -234, -116, -232, -3, -171, -3, -198, -89, -206, -58, -114, -167, -168, -187, -8, -252, -138, -16, -233, -216, -113, -113, -67, -140, -241, -218, -242, -122, -149, -136, -113, -161, -13, -200, -227, -243, -89, -239, -170, -39, -201, -205, -14, -161, -102, -201, -139, -104, -96, -207, -66, -206, -154, -207, -1, -46, -108, -112, -131, -27, -21, -202, -215, -118, -38, -217, -55, -107, -120, -216, -201, -126, -39, -185, -103, -222, -64, -89, -201, -117, -91, -61, -92, -122, -202, -89, -215, -7, -144, -92, -132, -0, -95, -105, -208, -38, -202, -177, -99, -108, -208, -62, -6, -67, -171, -140, -87, -30, -62, -222, -241, -58, -238, -1, -252, -93, -111, -236, -100, -228, -11, -7, -226, -219, -157, -33, -129, -53, -190, -10, -172, -80, -195, -99, -115, -228, -120, -100, -38, -226, -156, -83, -27, -103, -223, -247, -64, -245, -250, -54, -237, -118, -93, -86, -160, -231, -233, -75, -157, -141, -134, -127, -246, -149, -245, -1, -250, -203, -89, -119, -157, -254, -191, -113, -100, -28, -15, -191, -213, -180, -253, -156, -38, -3, -159, -8, -199, -142, -125, -128, -246, -49, -24, -26, -103, -188, -42, -225, -179, -216, -10, -0, -251, -213, -127, -174, -254, -134, -134, -58, -128, -150, -215, -29, -241, -64, -17, -205, -179, -21, -70, -103, -81, -177, -100, -101, -164, -194, -239, -163, -101, -101, -227, -9, -218, -239, -89, -136, -9, -46, -52, -136, -140, -19, -185, -31, -157, -143, -29, -27, -92, -43, -56, -47, -2, -45, -99, -48, -40, -109, -163, -140, -87, -37, -60, -22, -91, -1, -96, -131, -118, -188, -64, -127, -15, -91, -0, -172, -171, -191, -173, -179, -195, -21, -212, -156, -121, -146, -31, -249, -29, -85, -85, -54, -158, -224, -60, -143, -198, -145, -113, -122, -232, -75, -235, -99, -199, -134, -215, -105, -148, -23, -161, -227, -181, -130, -51, -94, -77, -40, -144, -107, -125, -207, -71, -210, -101, -5, -11, -0, -58, -56, -141, -56, -3, -126, -37, -242, -175, -222, -109, -132, -217, -143, -239, -133, -232, -26, -150, -169, -42, -27, -79, -112, -158, -71, -227, -200, -56, -227, -17, -52, -204, -139, -176, -56, -3, -120, -1, -146, -165, -249, -78, -68, -7, -243, -32, -178, -157, -252, -70, -9, -125, -20, -189, -134, -101, -182, -22, -185, -59, -171, -53, -105, -60, -139, -138, -104, -49, -158, -142, -180, -113, -26, -65, -7, -192, -251, -201, -131, -58, -116, -138, -36, -60, -158, -225, -8, -128, -198, -145, -113, -198, -35, -104, -144, -23, -161, -203, -135, -102, -172, -3, -9, -125, -103, -183, -225, -243, -17, -155, -11, -155, -113, -219, -235, -250, -75, -36, -189, -134, -203, -112, -5, -196, -189, -213, -77, -181, -253, -40, -146, -130, -107, -224, -40, -205, -105, -215, -58, -86, -157, -35, -0, -102, -59, -215, -236, -100, -170, -218, -7, -144, -147, -141, -63, -170, -144, -156, -141, -40, -58, -39, -35, -22, -96, -3, -251, -73, -231, -94, -26, -125, -213, -156, -118, -141, -34, -227, -180, -189, -222, -120, -2, -237, -131, -169, -142, -105, -193, -129, -164, -147, -183, -167, -71, -191, -64, -77, -168, -17, -5, -252, -22, -84, -40, -178, -137, -160, -215, -240, -49, -93, -74, -59, -243, -8, -249, -106, -224, -54, -26, -90, -63, -17, -16, -171, -206, -25, -184, -23, -0, -219, -59, -15, -98, -224, -11, -56, -90, -0, -118, -37, -95, -157, -216, -140, -173, -55, -145, -167, -151, -58, -204, -211, -166, -171, -0, -104, -27, -118, -122, -113, -22, -0, -109, -189, -19, -27, -11, -142, -182, -239, -193, -161, -9, -94, -206, -147, -39, -208, -253, -119, -248, -211, -24, -209, -62, -190, -94, -67, -59, -116, -60, -34, -157, -172, -251, -107, -35, -229, -19, -1, -177, -234, -138, -15, -26, -201, -84, -11, -226, -71, -62, -38, -220, -30, -201, -131, -78, -126, -169, -80, -190, -58, -240, -73, -60, -130, -177, -237, -132, -108, -59, -240, -34, -92, -207, -98, -158, -14, -166, -179, -245, -93, -84, -157, -194, -52, -254, -178, -182, -189, -191, -154, -123, -168, -243, -78, -108, -44, -56, -186, -244, -147, -134, -203, -121, -68, -225, -13, -99, -196, -110, -196, -24, -51, -242, -20, -0, -216, -68, -127, -151, -133, -116, -110, -29, -171, -206, -247, -160, -201, -67, -72, -159, -67, -172, -160, -135, -35, -175, -217, -52, -181, -182, -53, -138, -121, -69, -131, -107, -88, -12, -91, -0, -88, -204, -67, -38, -227, -57, -192, -158, -148, -196, -246, -115, -232, -109, -214, -224, -171, -16, -133, -156, -197, -69, -148, -164, -254, -102, -20, -190, -172, -37, -253, -104, -27, -76, -181, -84, -112, -116, -120, -15, -141, -151, -243, -228, -199, -171, -3, -17, -164, -70, -13, -218, -161, -227, -245, -255, -214, -231, -218, -151, -157, -167, -83, -172, -58, -223, -131, -70, -190, -172, -54, -208, -231, -126, -145, -239, -171, -77, -106, -109, -187, -2, -186, -140, -26, -115, -104, -167, -141, -197, -176, -5, -64, -217, -68, -190, -20, -207, -177, -170, -175, -159, -72, -210, -137, -221, -201, -183, -56, -7, -148, -244, -117, -216, -95, -214, -40, -65, -81, -29, -126, -85, -110, -205, -109, -223, -67, -227, -229, -60, -185, -123, -121, -155, -15, -76, -41, -66, -121, -89, -134, -199, -2, -219, -162, -199, -103, -202, -227, -120, -36, -20, -180, -205, -246, -251, -27, -79, -187, -78, -78, -35, -101, -15, -26, -209, -7, -44, -66, -190, -190, -47, -109, -116, -51, -229, -215, -106, -155, -90, -251, -185, -228, -89, -102, -108, -222, -185, -186, -120, -122, -22, -163, -182, -5, -96, -112, -34, -127, -183, -73, -63, -117, -76, -0, -220, -212, -240, -30, -250, -248, -178, -182, -254, -208, -208, -206, -173, -185, -109, -63, -27, -47, -231, -201, -87, -77, -219, -54, -104, -99, -97, -5, -126, -55, -7, -33, -135, -225, -28, -242, -227, -192, -69, -78, -249, -36, -60, -103, -243, -116, -116, -26, -169, -121, -208, -54, -118, -253, -77, -68, -8, -132, -64, -135, -212, -218, -200, -151, -237, -235, -140, -60, -33, -249, -95, -217, -75, -115, -104, -70, -93, -7, -64, -197, -68, -174, -105, -183, -187, -29, -19, -13, -239, -161, -143, -47, -107, -219, -96, -170, -93, -221, -154, -155, -246, -179, -241, -114, -30, -177, -244, -132, -6, -89, -172, -171, -222, -91, -43, -32, -190, -241, -127, -67, -150, -222, -118, -73, -50, -13, -56, -29, -217, -67, -150, -37, -88, -28, -147, -78, -35, -125, -1, -9, -172, -241, -254, -194, -160, -218, -217, -67, -215, -234, -5, -117, -24, -120, -165, -215, -163, -98, -34, -215, -180, -219, -77, -235, -158, -40, -233, -235, -48, -191, -172, -109, -131, -169, -182, -21, -28, -109, -251, -217, -102, -57, -127, -176, -182, -57, -191, -65, -155, -210, -247, -22, -5, -202, -252, -248, -0, -186, -49, -233, -52, -210, -55, -244, -30, -109, -16, -200, -41, -158, -250, -126, -95, -80, -131, -235, -81, -49, -145, -107, -218, -157, -160, -117, -255, -242, -212, -13, -251, -203, -218, -54, -152, -106, -91, -193, -81, -213, -207, -23, -87, -180, -107, -179, -156, -95, -151, -60, -143, -193, -33, -56, -241, -26, -145, -20, -110, -187, -86, -244, -111, -212, -5, -192, -208, -156, -70, -186, -160, -237, -192, -171, -225, -249, -82, -109, -214, -232, -203, -218, -7, -170, -174, -71, -245, -68, -30, -104, -135, -56, -84, -125, -158, -92, -119, -240, -78, -79, -187, -62, -190, -172, -85, -19, -171, -109, -48, -213, -182, -130, -195, -222, -187, -47, -252, -247, -59, -42, -218, -53, -94, -206, -107, -187, -247, -145, -219, -220, -204, -67, -156, -192, -102, -233, -239, -255, -120, -232, -75, -223, -119, -20, -40, -243, -227, -3, -105, -135, -226, -52, -210, -5, -53, -3, -175, -106, -192, -110, -128, -132, -151, -222, -160, -80, -254, -52, -114, -39, -150, -43, -43, -174, -55, -106, -2, -128, -176, -137, -108, -97, -149, -73, -215, -49, -50, -6, -196, -129, -37, -215, -107, -251, -101, -109, -59, -177, -218, -6, -83, -109, -43, -56, -172, -137, -173, -47, -252, -247, -209, -21, -237, -26, -47, -231, -157, -182, -155, -35, -185, -13, -239, -65, -182, -18, -51, -144, -147, -167, -15, -121, -104, -7, -222, -247, -98, -5, -106, -34, -215, -208, -208, -17, -194, -121, -96, -93, -194, -78, -63, -128, -104, -121, -175, -36, -15, -213, -52, -11, -216, -186, -226, -122, -195, -22, -0, -77, -39, -114, -17, -179, -144, -19, -143, -147, -80, -159, -251, -146, -118, -109, -191, -172, -173, -38, -150, -214, -55, -254, -208, -208, -94, -112, -216, -163, -204, -98, -248, -239, -247, -144, -239, -243, -125, -237, -26, -47, -231, -219, -192, -243, -222, -6, -16, -227, -58, -189, -130, -134, -185, -231, -11, -109, -27, -57, -66, -56, -207, -165, -75, -216, -233, -71, -145, -175, -198, -227, -136, -31, -192, -49, -192, -38, -53, -215, -27, -182, -0, -176, -8, -157, -200, -173, -250, -73, -251, -47, -107, -171, -137, -213, -5, -180, -19, -28, -175, -113, -238, -195, -134, -255, -182, -17, -160, -190, -133, -90, -250, -149, -92, -175, -209, -114, -190, -229, -61, -89, -196, -57, -6, -28, -13, -208, -49, -247, -60, -13, -28, -33, -156, -7, -54, -148, -164, -142, -109, -39, -214, -176, -175, -215, -161, -93, -219, -47, -107, -235, -137, -53, -108, -0, -111, -64, -220, -227, -167, -105, -191, -174, -65, -183, -60, -168, -0, -172, -104, -27, -188, -156, -111, -217, -183, -161, -142, -175, -94, -64, -156, -220, -243, -65, -142, -16, -73, -0, -196, -109, -167, -109, -219, -230, -55, -104, -61, -177, -198, -27, -144, -128, -172, -179, -233, -47, -65, -73, -52, -59, -128, -149, -129, -207, -34, -182, -223, -143, -35, -75, -151, -59, -145, -163, -174, -210, -188, -238, -5, -30, -63, -69, -246, -63, -191, -8, -164, -239, -148, -123, -190, -9, -70, -81, -0, -148, -46, -209, -208, -8, -202, -145, -175, -55, -52, -1, -144, -80, -15, -196, -106, -116, -145, -10, -188, -82, -33, -64, -190, -69, -216, -190, -170, -204, -169, -139, -46, -0, -174, -115, -152, -62, -142, -132, -8, -179, -150, -128, -15, -17, -96, -3, -79, -238, -241, -52, -51, -74, -167, -34, -162, -70, -0, -148, -30, -63, -69, -184, -94, -21, -62, -223, -195, -245, -146, -0, -24, -67, -0, -222, -77, -158, -133, -250, -218, -10, -186, -187, -138, -239, -193, -87, -230, -212, -69, -23, -0, -123, -0, -63, -193, -201, -59, -142, -36, -147, -188, -64, -47, -116, -106, -0, -143, -35, -145, -229, -78, -200, -254, -29, -90, -68, -191, -173, -153, -200, -85, -202, -188, -86, -199, -79, -139, -59, -22, -87, -1, -64, -131, -64, -163, -67, -234, -207, -165, -148, -88, -84, -106, -189, -61, -213, -90, -167, -170, -204, -169, -27, -206, -123, -3, -94, -168, -23, -122, -44, -50, -95, -104, -17, -253, -182, -131, -0, -104, -125, -252, -180, -56, -99, -49, -22, -0, -149, -129, -70, -145, -232, -87, -7, -33, -39, -37, -115, -144, -237, -238, -161, -212, -132, -190, -111, -216, -135, -157, -145, -21, -192, -1, -122, -141, -210, -108, -201, -72, -252, -5, -112, -76, -238, -125, -101, -78, -221, -208, -4, -192, -202, -118, -178, -70, -230, -107, -209, -40, -250, -109, -7, -1, -48, -244, -227, -167, -197, -25, -250, -184, -46, -215, -255, -175, -173, -19, -238, -110, -68, -195, -127, -123, -69, -187, -224, -88, -12, -200, -10, -244, -100, -100, -85, -248, -36, -240, -59, -2, -130, -196, -16, -16, -104, -84, -199, -195, -34, -36, -120, -201, -151, -201, -147, -167, -252, -182, -142, -127, -40, -144, -143, -217, -124, -228, -68, -228, -103, -84, -56, -180, -33, -39, -6, -211, -234, -202, -156, -58, -139, -126, -143, -1, -17, -141, -45, -212, -36, -208, -68, -206, -203, -33, -48, -96, -165, -115, -3, -141, -162, -223, -118, -16, -0, -227, -230, -248, -105, -60, -64, -159, -219, -61, -72, -26, -180, -41, -250, -123, -33, -162, -60, -190, -180, -164, -77, -112, -44, -6, -157, -252, -54, -83, -213, -249, -72, -128, -218, -121, -200, -74, -174, -82, -8, -16, -16, -104, -20, -73, -152, -242, -170, -66, -217, -121, -68, -254, -208, -133, -2, -241, -124, -189, -163, -174, -204, -169, -171, -69, -140, -78, -173, -64, -238, -240, -241, -165, -26, -218, -87, -148, -77, -218, -154, -27, -104, -20, -253, -214, -105, -215, -38, -160, -68, -47, -199, -79, -180, -76, -87, -165, -180, -65, -95, -68, -242, -56, -141, -62, -188, -172, -77, -191, -187, -64, -175, -59, -31, -17, -164, -255, -3, -222, -132, -38, -74, -197, -241, -11, -112, -232, -27, -197, -98, -64, -143, -17, -113, -50, -60, -35, -66, -124, -62, -112, -82, -79, -247, -116, -61, -48, -169, -15, -222, -227, -14, -72, -162, -208, -203, -245, -37, -92, -74, -69, -22, -92, -196, -2, -236, -159, -74, -91, -155, -161, -69, -219, -88, -180, -141, -126, -59, -148, -227, -188, -16, -208, -62, -93, -85, -163, -232, -68, -72, -172, -185, -67, -157, -103, -240, -123, -224, -67, -68, -136, -149, -208, -20, -78, -31, -30, -194, -217, -82, -85, -208, -55, -138, -197, -160, -207, -99, -96, -43, -1, -252, -133, -10, -101, -90, -91, -32, -62, -19, -139, -128, -157, -98, -243, -30, -119, -64, -210, -45, -93, -175, -47, -248, -106, -52, -174, -89, -5, -189, -85, -162, -205, -2, -158, -31, -120, -141, -86, -19, -121, -140, -10, -128, -198, -233, -170, -104, -25, -157, -72, -219, -90, -84, -42, -128, -60, -253, -170, -92, -153, -208, -192, -191, -194, -233, -195, -103, -171, -232, -218, -66, -251, -112, -139, -167, -252, -12, -60, -251, -98, -58, -172, -144, -144, -192, -174, -243, -129, -61, -99, -222, -195, -184, -5, -18, -204, -16, -224, -6, -106, -164, -59, -146, -4, -19, -100, -73, -61, -96, -176, -80, -209, -174, -15, -1, -16, -253, -60, -191, -47, -208, -45, -58, -81, -168, -0, -104, -180, -50, -161, -129, -127, -133, -211, -135, -94, -146, -175, -146, -7, -134, -117, -21, -196, -47, -71, -156, -144, -188, -71, -210, -180, -88, -33, -1, -223, -70, -20, -140, -111, -9, -236, -215, -146, -218, -230, -38, -196, -232, -237, -33, -42, -182, -122, -228, -130, -125, -131, -50, -154, -49, -7, -242, -176, -87, -219, -212, -208, -109, -133, -44, -155, -230, -1, -219, -53, -188, -70, -91, -1, -48, -225, -207, -243, -27, -8, -128, -54, -43, -147, -32, -255, -138, -170, -247, -87, -66, -223, -232, -11, -13, -172, -135, -248, -22, -44, -2, -206, -5, -206, -68, -4, -218, -163, -192, -179, -107, -174, -85, -251, -124, -116, -34, -255, -82, -39, -114, -208, -170, -85, -219, -125, -67, -121, -47, -66, -244, -70, -183, -0, -191, -175, -160, -183, -31, -211, -198, -201, -68, -201, -243, -100, -222, -83, -65, -211, -40, -194, -117, -232, -133, -237, -36, -27, -80, -230, -20, -232, -78, -87, -186, -111, -182, -184, -70, -233, -0, -98, -140, -156, -231, -59, -125, -44, -53, -89, -174, -24, -212, -79, -33, -70, -95, -74, -174, -217, -203, -25, -48, -1, -254, -21, -85, -239, -175, -162, -77, -163, -47, -52, -34, -4, -78, -35, -215, -145, -156, -74, -128, -89, -122, -200, -243, -65, -182, -18, -51, -129, -111, -34, -251, -127, -247, -95, -105, -106, -58, -242, -120, -153, -95, -112, -202, -202, -66, -174, -175, -134, -156, -70, -52, -122, -78, -78, -251, -255, -105, -91, -111, -162, -91, -90, -68, -184, -142, -10, -231, -230, -26, -101, -12, -210, -182, -165, -3, -136, -49, -114, -158, -239, -244, -177, -106, -9, -105, -17, -124, -30, -75, -0, -2, -251, -53, -106, -198, -59, -85, -239, -175, -65, -219, -190, -4, -88, -45, -255, -154, -199, -255, -137, -138, -118, -214, -205, -183, -46, -148, -252, -81, -228, -113, -1, -138, -152, -26, -112, -15, -171, -146, -155, -226, -15, -196, -23, -164, -131, -14, -201, -69, -87, -103, -28, -59, -1, -163, -90, -9, -214, -224, -96, -99, -204, -91, -141, -49, -47, -55, -198, -220, -13, -220, -108, -140, -89, -195, -24, -179, -158, -49, -230, -219, -198, -152, -47, -27, -99, -158, -214, -150, -57, -34, -205, -247, -51, -198, -236, -229, -20, -79, -7, -238, -50, -198, -252, -57, -203, -178, -50, -251, -253, -221, -179, -44, -187, -174, -225, -229, -174, -51, -198, -244, -226, -55, -161, -247, -49, -191, -164, -250, -229, -89, -150, -85, -234, -25, -22, -119, -100, -89, -214, -56, -225, -12, -146, -164, -198, -158, -134, -205, -171, -33, -127, -194, -24, -115, -184, -49, -102, -127, -253, -253, -75, -45, -51, -198, -152, -233, -1, -151, -219, -198, -24, -147, -25, -99, -174, -206, -178, -204, -103, -202, -252, -87, -173, -223, -42, -203, -178, -73, -218, -191, -173, -141, -49, -167, -107, -93, -187, -163, -97, -100, -95, -52, -27, -56, -60, -128, -246, -30, -149, -80, -3, -38, -187, -1, -109, -75, -191, -32, -140, -210, -121, -190, -182, -63, -217, -233, -219, -44, -196, -168, -228, -94, -253, -253, -231, -138, -251, -8, -254, -154, -181, -105, -211, -166, -61, -13, -150, -220, -52, -223, -163, -151, -190, -191, -88, -253, -111, -139, -62, -248, -35, -123, -255, -219, -125, -15, -39, -176, -47, -141, -158, -19, -98, -57, -8, -145, -34, -8, -53, -185, -176, -117, -65, -172, -61, -107, -69, -156, -127, -64, -38, -224, -250, -78, -249, -166, -136, -107, -240, -238, -189, -118, -54, -50, -144, -100, -36, -22, -135, -224, -164, -196, -2, -214, -199, -227, -206, -217, -102, -176, -117, -29, -160, -77, -219, -135, -210, -211, -76, -96, -180, -26, -216, -109, -250, -63, -22, -248, -3, -63, -208, -127, -22, -71, -217, -178, -192, -190, -52, -21, -0, -183, -234, -191, -202, -208, -120, -209, -65, -179, -21, -192, -218, -136, -253, -183, -197, -253, -228, -81, -97, -64, -189, -253, -198, -11, -200, -163, -231, -94, -220, -160, -77, -227, -193, -214, -117, -128, -54, -109, -223, -7, -253, -48, -5, -0, -13, -61, -251, -186, -62, -223, -64, -222, -161, -167, -31, -173, -159, -83, -95, -125, -114, -177, -68, -177, -32, -203, -178, -189, -179, -44, -123, -122, -150, -101, -159, -169, -107, -156, -101, -217, -84, -35, -123, -141, -195, -141, -49, -83, -140, -236, -197, -151, -48, -198, -92, -108, -140, -249, -156, -49, -102, -219, -166, -29, -26, -101, -88, -101, -75, -173, -9, -239, -68, -71, -150, -227, -182, -33, -92, -238, -0, -99, -204, -242, -198, -152, -169, -198, -152, -104, -65, -84, -18, -186, -43, -1, -77, -150, -101, -15, -25, -99, -62, -171, -255, -198, -59, -236, -17, -211, -141, -45, -218, -94, -75, -201, -118, -176, -141, -194, -41, -65, -128, -216, -34, -124, -220, -136, -2, -109, -199, -44, -203, -238, -26, -229, -46, -45, -86, -24, -90, -72, -174, -50, -32, -249, -6, -239, -48, -34, -225, -175, -204, -178, -204, -119, -228, -81, -171, -212, -43, -78, -178, -54, -109, -140, -49, -118, -207, -239, -77, -131, -94, -131, -54, -26, -253, -36, -52, -234, -241, -27, -99, -204, -195, -198, -152, -183, -182, -56, -101, -73, -168, -193, -168, -11, -0, -211, -108, -121, -215, -102, -146, -53, -105, -51, -199, -136, -16, -88, -174, -142, -208, -131, -49, -117, -12, -184, -184, -32, -203, -178, -168, -193, -52, -19, -2, -129, -132, -8, -251, -15, -240, -120, -143, -215, -168, -13, -220, -160, -116, -67, -81, -180, -33, -102, -179, -0, -123, -213, -83, -15, -183, -111, -218, -238, -29, -12, -106, -233, -63, -136, -115, -90, -17, -227, -122, -125, -42, -209, -198, -59, -255, -166, -10, -55, -52, -206, -4, -145, -82, -220, -199, -232, -147, -139, -1, -37, -160, -50, -220, -223, -24, -243, -43, -99, -204, -43, -141, -49, -247, -55, -232, -64, -211, -7, -110, -151, -119, -219, -141, -145, -229, -221, -213, -250, -119, -151, -74, -170, -81, -0, -98, -216, -115, -134, -49, -230, -11, -78, -241, -251, -141, -49, -39, -25, -99, -134, -103, -254, -153, -208, -20, -183, -234, -223, -49, -55, -166, -140, -41, -17, -0, -198, -152, -125, -245, -239, -39, -178, -44, -123, -97, -9, -77, -103, -100, -89, -182, -105, -150, -101, -107, -103, -89, -118, -117, -61, -245, -80, -96, -195, -65, -189, -17, -248, -46, -35, -227, -179, -173, -5, -188, -125, -148, -250, -101, -178, -44, -91, -144, -149, -99, -66, -91, -245, -89, -216, -21, -146, -83, -180, -127, -200, -10, -169, -103, -28, -235, -244, -229, -102, -196, -132, -189, -214, -20, -120, -84, -225, -124, -209, -155, -250, -246, -143, -153, -37, -93, -219, -62, -145, -59, -56, -129, -156, -61, -223, -64, -30, -154, -42, -74, -150, -214, -190, -159, -87, -215, -235, -141, -197, -247, -25, -192, -115, -40, -17, -147, -28, -158, -161, -91, -128, -12, -216, -95, -199, -209, -108, -196, -122, -213, -27, -50, -109, -88, -125, -114, -81, -167, -4, -12, -138, -239, -215, -4, -208, -74, -59, -63, -76, -236, -98, -140, -249, -146, -49, -102, -79, -99, -204, -250, -198, -24, -171, -132, -186, -195, -24, -83, -26, -213, -53, -161, -30, -192, -59, -140, -49, -110, -34, -213, -253, -129, -179, -140, -49, -167, -103, -89, -214, -41, -22, -95, -150, -101, -11, -140, -216, -198, -143, -41, -100, -89, -134, -17, -255, -149, -131, -71, -187, -47, -62, -140, -230, -41, -192, -176, -142, -205, -26, -181, -201, -178, -108, -190, -49, -230, -123, -198, -152, -239, -57, -194, -106, -165, -44, -203, -234, -28, -56, -142, -163, -36, -33, -74, -150, -101, -91, -213, -180, -93, -236, -65, -174, -195, -112, -241, -126, -253, -247, -114, -99, -76, -218, -198, -140, -2, -70, -83, -0, -12, -235, -216, -44, -198, -81, -91, -101, -108, -63, -69, -155, -229, -236, -132, -17, -26, -99, -245, -11, -221, -20, -139, -155, -125, -198, -128, -0, -96, -100, -18, -133, -97, -186, -249, -134, -160, -141, -208, -104, -211, -198, -24, -19, -246, -178, -59, -14, -136, -94, -117, -0, -125, -46, -185, -19, -22, -51, -0, -203, -3, -47, -3, -254, -165, -10, -133, -191, -53, -104, -27, -172, -212, -25, -150, -210, -172, -111, -69, -214, -88, -71, -27, -165, -24, -45, -237, -12, -198, -2, -144, -0, -26, -199, -106, -191, -79, -243, -212, -15, -96, -52, -250, -233, -244, -103, -105, -228, -68, -224, -78, -26, -4, -240, -232, -179, -67, -22, -55, -2, -95, -1, -130, -131, -106, -36, -1, -48, -254, -209, -70, -96, -140, -21, -0, -239, -69, -162, -83, -221, -133, -68, -225, -169, -18, -0, -87, -17, -51, -115, -78, -75, -0, -27, -58, -125, -26, -181, -227, -101, -215, -14, -224, -127, -70, -246, -202, -235, -25, -99, -94, -104, -196, -60, -55, -97, -130, -160, -15, -59, -3, -224, -37, -200, -209, -151, -215, -156, -151, -6, -97, -200, -107, -176, -185, -49, -230, -95, -198, -152, -16, -107, -187, -247, -103, -89, -182, -149, -79, -199, -226, -147, -124, -109, -251, -76, -189, -11, -243, -221, -198, -152, -43, -141, -49, -119, -26, -99, -46, -15, -232, -119, -255, -0, -86, -68, -242, -145, -1, -252, -179, -65, -187, -224, -175, -109, -197, -87, -166, -234, -161, -7, -243, -239, -210, -70, -219, -5, -199, -210, -71, -76, -152, -255, -3, -236, -209, -228, -26, -19, -5, -192, -31, -144, -184, -118, -231, -251, -132, -0, -13, -194, -144, -55, -184, -38, -84, -175, -0, -74, -207, -202, -201, -227, -56, -218, -73, -238, -27, -139, -65, -125, -166, -38, -57, -233, -152, -5, -176, -142, -243, -176, -86, -10, -108, -19, -60, -217, -28, -218, -54, -65, -52, -135, -33, -0, -130, -99, -233, -147, -39, -79, -1, -248, -98, -13, -223, -37, -144, -40, -67, -143, -35, -65, -83, -14, -68, -98, -204, -21, -233, -62, -15, -92, -134, -132, -230, -126, -20, -248, -59, -240, -188, -38, -247, -48, -86, -128, -100, -198, -61, -205, -190, -239, -18, -154, -160, -48, -228, -13, -174, -9, -45, -5, -128, -67, -91, -23, -146, -174, -178, -207, -4, -250, -184, -116, -5, -18, -54, -124, -54, -240, -75, -79, -221, -47, -144, -237, -208, -79, -219, -48, -182, -216, -176, -33, -125, -223, -58, -128, -94, -133, -134, -182, -107, -20, -75, -31, -201, -42, -3, -240, -64, -13, -223, -47, -34, -81, -139, -191, -160, -255, -230, -227, -137, -62, -139, -164, -146, -62, -20, -120, -63, -176, -59, -146, -120, -226, -162, -10, -190, -149, -202, -36, -74, -80, -255, -36, -226, -1, -73, -45, -87, -26, -98, -142, -128, -48, -228, -13, -174, -5, -61, -11, -128, -186, -62, -19, -144, -156, -180, -105, -159, -74, -218, -219, -240, -125, -3, -238, -235, -78, -221, -147, -109, -24, -55, -234, -88, -147, -201, -214, -132, -214, -211, -166, -20, -49, -174, -211, -6, -192, -243, -235, -6, -139, -210, -93, -11, -252, -213, -249, -253, -87, -60, -166, -197, -158, -118, -135, -81, -145, -177, -150, -26, -101, -18, -178, -162, -25, -248, -231, -161, -179, -193, -80, -127, -94, -211, -159, -208, -231, -191, -51, -178, -2, -56, -64, -175, -57, -20, -43, -74, -237, -78, -239, -2, -32, -6, -154, -244, -169, -164, -253, -145, -200, -10, -224, -23, -158, -58, -187, -58, -56, -178, -247, -142, -53, -153, -108, -195, -154, -152, -195, -66, -232, -96, -65, -210, -79, -29, -230, -252, -62, -12, -24, -176, -179, -64, -146, -178, -254, -12, -177, -29, -159, -129, -198, -134, -175, -224, -107, -87, -0, -141, -226, -193, -123, -248, -172, -6, -220, -167, -183, -242, -158, -10, -186, -80, -129, -50, -3, -89, -229, -76, -209, -251, -25, -138, -82, -121, -34, -9, -128, -24, -24, -11, -1, -65, -38, -10, -22, -153, -145, -150, -112, -101, -158, -152, -191, -49, -18, -19, -254, -48, -99, -204, -100, -99, -204, -206, -250, -207, -11, -53, -93, -30, -136, -162, -212, -20, -89, -150, -61, -134, -164, -150, -250, -147, -49, -230, -112, -224, -239, -89, -150, -13, -88, -41, -102, -89, -22, -116, -60, -156, -101, -217, -10, -93, -251, -52, -150, -225, -8, -135, -141, -139, -113, -17, -171, -234, -198, -26, -202, -6, -161, -117, -2, -170, -76, -13, -150, -208, -8, -183, -24, -99, -54, -113, -126, -63, -207, -228, -190, -226, -46, -182, -54, -198, -28, -159, -101, -217, -215, -178, -44, -251, -189, -49, -102, -152, -97, -161, -207, -48, -198, -220, -100, -140, -89, -219, -24, -19, -39, -207, -92, -194, -168, -0, -248, -152, -174, -46, -94, -92, -69, -87, -38, -0, -172, -212, -122, -83, -192, -133, -92, -30, -115, -3, -251, -183, -56, -225, -169, -136, -73, -192, -186, -21, -116, -71, -27, -99, -182, -3, -246, -3, -246, -51, -198, -108, -103, -114, -95, -113, -23, -119, -24, -99, -182, -69, -148, -128, -223, -51, -198, -188, -173, -174, -3, -177, -150, -146, -234, -185, -102, -253, -233, -247, -41, -188, -219, -113, -1, -181, -91, -40, -221, -194, -76, -32, -172, -84, -248, -27, -14, -196, -178, -202, -226, -250, -26, -218, -245, -148, -110, -33, -1, -199, -134, -14, -223, -96, -141, -126, -0, -207, -159, -43, -207, -63, -4, -208, -238, -66, -158, -179, -109, -149, -166, -215, -42, -225, -121, -182, -242, -59, -23, -209, -14, -15, -152, -206, -34, -126, -225, -223, -36, -63, -6, -252, -14, -254, -99, -192, -215, -144, -251, -142, -159, -13, -236, -90, -183, -23, -141, -185, -151, -68, -108, -65, -108, -142, -197, -215, -117, -229, -55, -86, -208, -228, -25, -17, -118, -10, -80, -202, -47, -244, -90, -49, -223, -155, -135, -247, -55, -149, -119, -80, -218, -115, -31, -131, -119, -2, -23, -227, -81, -84, -57, -52, -75, -3, -39, -233, -133, -74, -143, -170, -10, -109, -106, -209, -176, -159, -59, -107, -179, -251, -129, -213, -43, -232, -50, -68, -35, -237, -34, -150, -0, -120, -58, -98, -62, -125, -99, -155, -123, -136, -112, -253, -168, -3, -9, -248, -183, -242, -59, -48, -6, -191, -177, -128, -38, -207, -136, -197, -67, -0, -28, -162, -188, -223, -87, -69, -87, -170, -4, -204, -178, -236, -12, -51, -232, -191, -109, -153, -223, -103, -140, -185, -215, -136, -217, -240, -218, -70, -162, -233, -238, -23, -210, -177, -152, -238, -148, -72, -250, -114, -155, -193, -232, -179, -89, -150, -61, -90, -66, -183, -188, -145, -96, -30, -239, -50, -18, -247, -111, -99, -211, -102, -105, -84, -142, -21, -140, -49, -47, -50, -242, -60, -102, -26, -89, -198, -143, -103, -156, -103, -140, -121, -181, -49, -166, -242, -28, -59, -97, -76, -35, -104, -11, -208, -118, -143, -55, -199, -136, -221, -245, -211, -140, -49, -103, -25, -99, -94, -155, -249, -51, -152, -246, -141, -221, -141, -49, -207, -52, -198, -220, -108, -140, -249, -99, -5, -221, -95, -140, -76, -254, -11, -141, -236, -189, -99, -251, -116, -159, -98, -140, -249, -128, -17, -13, -250, -218, -89, -150, -85, -42, -94, -198, -1, -172, -0, -171, -210, -105, -36, -140, -50, -144, -179, -126, -128, -123, -60, -213, -43, -234, -223, -74, -1, -208, -234, -24, -48, -203, -178, -32, -11, -193, -62, -129, -36, -77, -180, -230, -183, -135, -168, -2, -171, -12, -63, -54, -198, -220, -99, -140, -249, -120, -150, -101, -243, -104, -224, -233, -24, -208, -143, -149, -141, -49, -175, -215, -159, -95, -201, -178, -172, -77, -82, -145, -177, -134, -135, -244, -239, -26, -163, -218, -139, -132, -58, -188, -74, -255, -254, -213, -83, -103, -39, -254, -138, -158, -186, -167, -48, -158, -237, -0, -94, -105, -140, -217, -192, -200, -145, -165, -215, -76, -215, -34, -203, -178, -179, -140, -172, -84, -44, -150, -46, -163, -109, -129, -167, -38, -73, -150, -101, -247, -70, -228, -59, -154, -120, -68, -255, -174, -54, -170, -189, -72, -40, -5, -176, -170, -17, -175, -93, -99, -140, -249, -181, -135, -164, -217, -22, -0, -152, -171, -203, -137, -168, -174, -137, -52, -243, -174, -219, -20, -201, -208, -123, -175, -246, -103, -10, -146, -173, -216, -103, -225, -182, -173, -254, -189, -34, -32, -94, -95, -159, -88, -172, -66, -68, -41, -150, -209, -191, -211, -70, -181, -23, -9, -85, -216, -198, -200, -216, -187, -186, -100, -251, -221, -120, -11, -48, -221, -24, -179, -186, -137, -255, -210, -223, -102, -140, -89, -214, -136, -146, -236, -82, -35, -82, -235, -185, -70, -246, -238, -69, -28, -98, -196, -16, -230, -116, -35, -6, -41, -27, -26, -73, -12, -185, -145, -49, -230, -141, -5, -218, -109, -244, -239, -121, -145, -251, -155, -144, -191, -155, -135, -71, -181, -23, -139, -57, -58, -42, -196, -223, -160, -127, -15, -45, -169, -111, -188, -5, -152, -102, -74, -4, -0, -226, -110, -248, -97, -99, -204, -113, -89, -150, -237, -19, -90, -167, -56, -203, -72, -236, -187, -201, -250, -123, -178, -145, -32, -8, -87, -122, -104, -63, -100, -228, -185, -60, -117, -244, -8, -60, -215, -248, -77, -93, -173, -143, -245, -120, -215, -184, -143, -69, -88, -247, -227, -74, -15, -199, -113, -138, -147, -81, -223, -133, -113, -30, -120, -117, -71, -35, -6, -123, -167, -150, -212, -55, -51, -4, -2, -174, -211, -45, -192, -241, -158, -186, -16, -183, -195, -168, -202, -47, -224, -105, -192, -235, -17, -191, -235, -223, -122, -234, -109, -178, -142, -183, -182, -224, -109, -209, -217, -14, -0, -216, -76, -121, -205, -235, -202, -171, -67, -31, -162, -158, -39, -3, -103, -41, -191, -178, -175, -203, -184, -3, -30, -84, -208, -14, -197, -14, -160, -79, -56, -91, -250, -202, -36, -36, -197, -45, -128, -49, -254, -45, -192, -137, -70, -190, -242, -191, -241, -212, -157, -96, -140, -249, -168, -254, -141, -130, -194, -131, -63, -215, -24, -227, -139, -184, -99, -39, -175, -247, -236, -127, -136, -216, -65, -255, -250, -236, -250, -199, -29, -144, -19, -146, -109, -245, -231, -57, -163, -216, -149, -168, -8, -89, -110, -147, -91, -161, -214, -158, -18, -85, -241, -27, -11, -161, -195, -179, -44, -91, -182, -158, -202, -1, -226, -159, -14, -61, -89, -127, -53, -145, -138, -192, -14, -136, -133, -223, -17, -218, -230, -32, -15, -205, -227, -90, -183, -181, -143, -71, -96, -95, -58, -173, -0, -16, -147, -93, -139, -82, -143, -189, -190, -17, -243, -139, -131, -248, -32, -128, -132, -189, -90, -166, -190, -197, -226, -131, -38, -171, -132, -197, -14, -72, -8, -104, -144, -204, -192, -125, -240, -111, -53, -72, -129, -11, -241, -68, -147, -1, -110, -85, -126, -141, -179, -174, -70, -20, -0, -143, -33, -230, -210, -239, -236, -194, -167, -43, -34, -11, -128, -75, -149, -215, -119, -99, -244, -45, -97, -108, -35, -116, -11, -48, -20, -0, -171, -100, -89, -246, -132, -243, -123, -73, -99, -204, -51, -140, -63, -71, -225, -253, -70, -78, -7, -188, -17, -103, -135, -129, -44, -203, -22, -171, -115, -114, -196, -113, -228, -53, -70, -18, -194, -44, -54, -251, -255, -132, -114, -184, -166, -192, -211, -10, -127, -71, -3, -83, -129, -51, -144, -212, -220, -95, -55, -198, -92, -96, -100, -130, -255, -202, -67, -107, -247, -107, -111, -240, -212, -77, -24, -48, -210, -243, -176, -52, -238, -94, -0, -159, -149, -141, -49, -71, -233, -207, -207, -186, -130, -56, -97, -2, -128, -220, -125, -176, -151, -36, -5, -33, -203, -84, -224, -32, -196, -163, -110, -38, -18, -106, -106, -50, -18, -76, -115, -32, -40, -6, -240, -70, -229, -55, -151, -134, -153, -107, -98, -109, -1, -198, -2, -128, -183, -235, -189, -60, -94, -79, -93, -201, -199, -134, -131, -111, -30, -67, -46, -97, -252, -3, -216, -87, -7, -192, -182, -61, -241, -143, -182, -79, -85, -126, -203, -34, -145, -87, -1, -118, -107, -217, -151, -113, -43, -0, -128, -187, -145, -248, -245, -243, -244, -94, -14, -24, -237, -62, -37, -140, -99, -144, -135, -16, -10, -201, -174, -210, -134, -127, -84, -1, -160, -60, -247, -87, -158, -147, -98, -241, -28, -47, -64, -148, -160, -243, -144, -64, -158, -95, -247, -173, -146, -18, -18, -198, -12, -122, -18, -0, -43, -34, -201, -51, -0, -106, -67, -103, -37, -36, -36, -140, -18, -250, -16, -0, -202, -247, -67, -202, -247, -238, -241, -188, -164, -79, -72, -24, -85, -32, -94, -119, -179, -129, -195, -235, -169, -91, -241, -15, -22, -0, -84, -164, -60, -42, -161, -63, -82, -121, -255, -174, -123, -79, -19, -18, -38, -32, -200, -109, -250, -123, -57, -254, -105, -40, -0, -122, -241, -47, -72, -72, -72, -24, -9, -215, -14, -224, -68, -35, -161, -190, -134, -146, -194, -169, -6, -39, -24, -233, -75, -52, -255, -130, -132, -132, -132, -81, -68, -95, -58, -128, -132, -132, -132, -132, -132, -132, -132, -137, -0, -93, -69, -148, -165, -3, -111, -156, -84, -36, -33, -97, -34, -99, -220, -165, -126, -74, -72, -72, -136, -135, -36, -0, -18, -18, -38, -48, -122, -21, -0, -85, -138, -63, -231, -168, -111, -251, -62, -251, -144, -144, -144, -80, -142, -209, -92, -1, -60, -92, -248, -155, -144, -144, -48, -100, -140, -5, -1, -240, -72, -177, -194, -177, -74, -60, -98, -200, -125, -74, -72, -152, -80, -24, -77, -1, -96, -39, -190, -111, -5, -176, -155, -145, -192, -140, -31, -30, -94, -119, -18, -18, -38, -30, -70, -123, -5, -48, -61, -203, -178, -185, -158, -58, -107, -149, -232, -139, -66, -156, -144, -144, -16, -9, -163, -153, -27, -240, -97, -227, -89, -254, -27, -99, -76, -150, -101, -123, -27, -99, -246, -30, -110, -119, -18, -18, -18, -162, -98, -152, -230, -191, -201, -16, -40, -33, -161, -57, -146, -29, -64, -66, -194, -4, -70, -18, -0, -9, -9, -19, -24, -73, -0, -36, -36, -76, -96, -36, -1, -144, -144, -48, -129, -145, -4, -64, -66, -194, -4, -198, -184, -19, -0, -73, -219, -159, -144, -16, -15, -227, -78, -0, -36, -36, -36, -196, -67, -18, -0, -9, -9, -19, -24, -73, -0, -36, -36, -76, -96, -36, -1, -144, -144, -48, -117, -14, -169, -49, -0, -0, -2, -74, -73, -68, -65, -84, -129, -145, -4, -64, -66, -194, -4, -70, -175, -206, -64, -89, -150, -101, -125, -242, -79, -72, -72, -232, -134, -180, -2, -72, -72, -152, -192, -72, -2, -32, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -225, -255, -219, -131, -3, -2, -0, -0, -0, -0, -33, -253, -95, -221, -17, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -208, -17, -112, -180, -144, -16, -164, -2, -78, -0, -0, -0, -0, -73, -69, -78, -68, -174, -66, -96, -130, -}; -/* clang-format on */ diff --git a/scene/resources/default_theme/font_lodpi.inc b/scene/resources/default_theme/font_lodpi.inc deleted file mode 100644 index d2f5851224..0000000000 --- a/scene/resources/default_theme/font_lodpi.inc +++ /dev/null @@ -1,13117 +0,0 @@ -/* clang-format off */ -static const int _lodpi_font_height=14; -static const int _lodpi_font_ascent=11; -static const int _lodpi_font_charcount=191; -static const int _lodpi_font_charrects[191][8]={ -/* charidx , ofs_x, ofs_y, size_x, size_y, valign, halign, advance */ -{64,72,34,10,11,1,1,12}, -{224,85,180,5,11,0,1,7}, -{192,32,16,11,13,-2,-1,9}, -{96,2,216,3,2,0,3,8}, -{160,0,0,0,0,11,0,4}, -{32,0,0,0,0,11,0,4}, -{33,65,234,2,10,1,1,4}, -{225,112,169,5,11,0,1,7}, -{193,17,16,11,13,-2,-1,9}, -{161,2,222,2,11,3,1,4}, -{65,2,16,11,10,1,-1,9}, -{97,76,188,5,8,3,1,7}, -{98,102,165,6,11,0,1,8}, -{226,72,143,6,11,0,1,7}, -{194,113,2,11,13,-2,-1,9}, -{66,46,109,7,10,1,1,9}, -{162,12,136,6,10,1,1,8}, -{34,49,187,5,4,1,1,6}, -{35,78,66,8,10,1,0,9}, -{163,22,167,6,10,1,1,8}, -{195,53,2,11,14,-3,-1,9}, -{227,2,155,6,12,-1,1,7}, -{67,68,115,7,10,1,1,8}, -{99,40,179,5,8,3,1,7}, -{228,121,169,5,11,0,1,7}, -{196,98,2,11,13,-2,-1,9}, -{36,102,137,6,12,0,1,8}, -{100,82,150,6,11,0,1,8}, -{68,90,66,8,10,1,1,10}, -{164,14,79,8,7,3,0,8}, -{37,2,30,10,10,1,1,12}, -{69,29,191,5,10,1,1,7}, -{165,79,98,7,10,1,0,8}, -{229,20,196,5,12,-1,1,7}, -{197,83,2,11,12,-1,-1,9}, -{101,32,124,6,8,3,1,8}, -{38,67,49,9,10,1,1,10}, -{70,101,105,6,10,1,1,7}, -{198,21,2,12,10,1,-1,12}, -{166,95,228,2,14,0,3,7}, -{102,2,201,5,11,0,0,4}, -{230,58,34,10,8,3,1,12}, -{71,66,65,8,10,1,1,10}, -{231,2,186,5,11,3,1,7}, -{199,57,97,7,13,1,1,8}, -{103,13,107,7,11,3,1,7}, -{167,112,131,6,11,0,0,7}, -{39,119,219,2,4,1,1,3}, -{72,54,65,8,10,1,1,10}, -{232,62,143,6,11,0,1,8}, -{200,47,195,5,13,-2,1,7}, -{40,93,212,4,12,1,1,4}, -{104,72,158,6,11,0,1,8}, -{168,77,217,4,2,0,2,8}, -{73,38,191,5,10,1,0,5}, -{169,44,34,10,10,1,1,12}, -{233,52,142,6,11,0,1,8}, -{201,56,197,5,13,-2,1,7}, -{41,51,226,3,12,1,0,4}, -{105,109,213,3,11,0,0,4}, -{106,101,213,4,14,0,-1,4}, -{74,92,195,5,13,1,-2,3}, -{202,65,202,5,13,-2,1,7}, -{42,108,80,7,6,0,0,8}, -{170,29,205,4,5,1,0,5}, -{234,12,181,6,11,0,1,8}, -{171,22,181,5,6,4,1,7}, -{43,101,94,7,7,3,0,8}, -{107,112,92,7,11,0,1,7}, -{203,83,200,5,13,-2,1,7}, -{235,2,171,6,11,0,1,8}, -{75,102,66,8,10,1,1,8}, -{44,107,231,2,3,9,1,4}, -{172,2,104,7,4,6,0,8}, -{108,113,228,2,11,0,1,4}, -{204,101,196,5,13,-2,0,5}, -{236,30,214,3,11,0,0,4}, -{76,22,124,6,10,1,1,7}, -{173,16,229,3,2,7,1,5}, -{45,123,201,3,2,7,1,5}, -{109,68,2,11,8,3,1,13}, -{205,11,211,5,13,-2,0,5}, -{237,37,214,3,11,0,1,4}, -{77,62,20,10,10,1,1,12}, -{46,101,231,2,2,9,1,4}, -{110,111,107,6,8,3,1,8}, -{206,20,212,5,13,-2,0,5}, -{238,11,196,5,11,0,-1,4}, -{174,30,33,10,10,1,1,12}, -{78,2,79,8,10,1,1,10}, -{175,35,111,7,1,-1,0,7}, -{111,102,153,6,8,3,1,8}, -{207,119,184,5,13,-2,0,5}, -{239,69,219,4,11,0,0,4}, -{79,41,66,9,10,1,1,11}, -{47,90,105,7,10,1,-1,5}, -{176,61,219,4,4,1,1,6}, -{112,32,150,6,11,3,1,8}, -{240,82,165,6,11,0,1,8}, -{208,86,33,9,10,1,0,10}, -{80,52,128,6,10,1,1,8}, -{48,42,135,6,10,1,1,8}, -{177,46,97,7,8,3,0,8}, -{113,22,152,6,11,3,1,8}, -{241,2,112,6,12,-1,1,8}, -{81,15,59,9,13,1,1,11}, -{209,74,80,8,14,-3,1,10}, -{49,45,212,4,10,1,2,8}, -{178,58,187,5,6,1,0,5}, -{114,85,217,4,8,3,1,5}, -{210,2,62,9,13,-2,1,11}, -{242,62,165,6,11,0,1,8}, -{82,35,97,7,10,1,1,8}, -{50,57,114,7,10,1,1,8}, -{179,53,214,4,6,1,0,5}, -{115,112,146,6,8,3,0,7}, -{211,106,49,9,13,-2,1,11}, -{243,52,172,6,11,0,1,8}, -{83,24,96,7,10,1,0,7}, -{51,22,138,6,10,1,1,8}, -{180,9,228,3,2,0,3,8}, -{116,67,188,5,10,1,0,5}, -{212,93,49,9,13,-2,1,11}, -{244,42,164,6,11,0,1,8}, -{84,13,93,7,10,1,0,7}, -{52,24,110,7,10,1,1,8}, -{53,92,119,6,10,1,1,8}, -{85,114,66,8,10,1,1,10}, -{213,2,44,9,14,-3,1,11}, -{117,42,123,6,8,3,1,8}, -{181,2,140,6,11,3,1,8}, -{245,12,165,6,12,-1,1,8}, -{54,82,121,6,10,1,1,8}, -{86,76,18,10,10,1,-1,8}, -{246,72,173,6,11,0,1,8}, -{214,80,49,9,13,-2,1,11}, -{182,68,98,7,13,0,1,9}, -{118,15,47,9,8,3,-1,7}, -{55,72,129,6,10,1,1,8}, -{87,2,2,15,10,1,-1,13}, -{119,37,2,12,8,3,-1,10}, -{247,90,94,7,7,3,0,8}, -{215,2,93,7,7,3,0,8}, -{183,77,223,2,2,5,1,4}, -{56,62,129,6,10,1,1,8}, -{88,90,19,10,10,1,-1,8}, -{216,99,33,9,12,0,1,11}, -{248,2,128,6,8,3,1,8}, -{120,119,80,7,8,3,0,7}, -{184,116,212,3,3,11,0,3}, -{89,28,65,9,10,1,-1,7}, -{217,38,80,8,13,-2,1,10}, -{249,52,157,6,11,0,1,8}, -{121,112,33,9,11,3,-1,7}, -{57,12,122,6,10,1,1,8}, -{185,23,229,3,6,1,0,5}, -{218,26,79,8,13,-2,1,10}, -{250,42,149,6,11,0,1,8}, -{90,32,136,6,10,1,1,8}, -{122,112,119,6,8,3,1,7}, -{58,89,229,2,8,3,1,4}, -{186,37,205,4,5,1,0,5}, -{219,50,80,8,13,-2,1,10}, -{91,58,227,3,12,1,1,4}, -{123,103,180,5,12,1,0,5}, -{251,12,150,6,11,0,1,8}, -{59,71,234,2,9,3,1,4}, -{187,31,181,5,6,4,1,7}, -{188,16,33,10,10,1,0,10}, -{124,83,229,2,14,0,3,7}, -{220,62,79,8,13,-2,1,10}, -{252,92,133,6,11,0,1,8}, -{92,97,80,7,10,1,-1,5}, -{60,92,153,6,7,3,1,8}, -{189,47,20,11,10,1,0,10}, -{253,28,47,9,14,0,-1,7}, -{221,54,48,9,13,-2,-1,7}, -{93,44,226,3,12,1,0,4}, -{125,110,196,5,12,1,0,5}, -{61,79,112,7,5,4,0,8}, -{190,104,19,10,10,1,0,10}, -{222,32,165,6,10,1,1,8}, -{254,102,119,6,14,0,1,8}, -{62,112,158,6,7,3,1,8}, -{94,86,80,7,6,1,0,7}, -{126,62,158,6,3,5,1,8}, -{223,82,135,6,11,0,1,8}, -{255,41,48,9,14,0,-1,7}, -{191,94,180,5,11,3,0,6}, -{63,74,202,5,10,1,0,6}, -{95,92,148,6,1,12,0,6}, -}; -static const int _lodpi_font_kerning_pair_count=0; -static const int _lodpi_font_kerning_pairs[1][3]={ -{0,0,0}, -}; -static const int _lodpi_font_img_width=128; -static const int _lodpi_font_img_height=256; -static const int _lodpi_font_img_data_size=12909; -static const unsigned char _lodpi_font_img_data[12909]={ -137, -80, -78, -71, -13, -10, -26, -10, -0, -0, -0, -13, -73, -72, -68, -82, -0, -0, -0, -128, -0, -0, -1, -0, -8, -6, -0, -0, -0, -123, -249, -126, -167, -0, -0, -32, -0, -73, -68, -65, -84, -120, -156, -237, -157, -119, -184, -30, -85, -181, -255, -191, -59, -128, -8, -210, -155, -82, -77, -232, -221, -2, -210, -164, -132, -26, -154, -5, -164, -131, -63, -224, -98, -65, -4, -68, -46, -8, -42, -23, -84, -80, -41, -94, -16, -21, -17, -197, -10, -22, -80, -17, -21, -4, -5, -65, -16, -41, -42, -185, -116, -19, -106, -128, -80, -46, -32, -33, -148, -208, -18, -62, -191, -63, -214, -122, -115, -230, -204, -217, -51, -179, -103, -222, -121, -223, -115, -146, -123, -190, -207, -115, -158, -51, -101, -237, -50, -243, -174, -217, -123, -237, -213, -182, -52, -138, -81, -140, -98, -20, -2, -150, -3, -222, -0, -54, -207, -93, -255, -32, -134, -247, -231, -174, -111, -237, -244, -203, -38, -212, -61, -31, -48, -149, -2, -68, -232, -87, -242, -91, -107, -102, -174, -253, -28, -184, -58, -115, -190, -178, -211, -172, -88, -243, -57, -199, -84, -220, -7, -216, -17, -184, -21, -120, -21, -184, -23, -216, -9, -56, -192, -143, -103, -0, -55, -1, -235, -36, -180, -245, -117, -224, -122, -224, -244, -58, -125, -244, -178, -247, -0, -239, -4, -222, -13, -220, -85, -179, -236, -55, -253, -57, -190, -89, -69, -59, -251, -101, -132, -16, -30, -151, -116, -171, -164, -157, -114, -52, -59, -74, -186, -94, -210, -118, -185, -235, -59, -73, -250, -123, -8, -225, -137, -132, -62, -237, -39, -233, -113, -73, -11, -248, -249, -206, -126, -188, -64, -230, -218, -108, -132, -16, -30, -145, -116, -175, -164, -205, -252, -129, -230, -149, -180, -161, -164, -21, -129, -133, -156, -108, -115, -73, -147, -67, -8, -143, -150, -53, -12, -28, -9, -76, -3, -206, -4, -198, -74, -186, -49, -161, -191, -103, -75, -58, -76, -210, -242, -178, -103, -191, -88, -210, -17, -146, -118, -151, -52, -78, -210, -51, -146, -190, -157, -80, -207, -102, -33, -132, -45, -37, -109, -157, -64, -155, -199, -204, -204, -241, -172, -212, -66, -192, -119, -37, -45, -41, -105, -13, -73, -75, -251, -121, -114, -225, -19, -128, -137, -185, -107, -15, -1, -59, -3, -255, -202, -93, -191, -11, -248, -108, -98, -189, -119, -2, -251, -250, -49, -64, -158, -153, -98, -101, -206, -1, -206, -247, -227, -109, -128, -75, -129, -31, -117, -70, -34, -224, -188, -20, -14, -7, -110, -241, -209, -226, -76, -224, -57, -224, -136, -10, -122, -128, -79, -100, -206, -215, -205, -247, -217, -71, -136, -23, -18, -218, -190, -223, -203, -222, -93, -69, -59, -34, -0, -172, -159, -29, -214, -129, -53, -128, -71, -252, -120, -42, -176, -188, -31, -175, -232, -15, -182, -118, -66, -157, -59, -1, -143, -250, -87, -92, -135, -1, -62, -216, -121, -113, -192, -89, -192, -97, -192, -65, -192, -185, -126, -237, -110, -114, -211, -82, -65, -61, -165, -67, -126, -132, -30, -96, -219, -204, -249, -88, -191, -54, -54, -115, -109, -115, -24, -58, -117, -69, -234, -186, -12, -248, -53, -240, -251, -58, -125, -240, -178, -59, -121, -187, -249, -17, -185, -167, -101, -59, -95, -252, -193, -126, -124, -100, -230, -43, -252, -17, -112, -144, -31, -127, -28, -184, -47, -177, -190, -107, -128, -207, -100, -206, -135, -160, -160, -220, -162, -192, -107, -254, -255, -62, -76, -46, -88, -14, -120, -16, -88, -204, -239, -45, -146, -216, -135, -228, -23, -226, -116, -155, -103, -206, -59, -12, -176, -66, -230, -90, -37, -3, -0, -227, -128, -151, -252, -99, -121, -41, -203, -64, -137, -125, -238, -134, -121, -26, -151, -21, -112, -54, -112, -177, -31, -255, -1, -216, -211, -143, -247, -7, -46, -244, -227, -75, -129, -175, -37, -212, -245, -110, -224, -5, -96, -177, -204, -53, -252, -7, -121, -115, -231, -175, -164, -252, -77, -192, -129, -192, -29, -153, -107, -119, -0, -7, -3, -55, -212, -120, -166, -228, -23, -210, -34, -3, -156, -14, -252, -218, -143, -47, -1, -78, -171, -209, -223, -198, -204, -211, -45, -227, -9, -216, -22, -19, -154, -22, -0, -158, -7, -22, -247, -235, -111, -5, -30, -199, -36, -250, -231, -201, -173, -22, -10, -234, -250, -121, -236, -139, -39, -97, -10, -240, -242, -39, -3, -55, -0, -95, -201, -92, -59, -195, -25, -227, -164, -196, -58, -106, -189, -144, -54, -24, -192, -25, -251, -25, -96, -15, -63, -223, -195, -207, -11, -153, -61, -87, -190, -27, -230, -105, -92, -182, -83, -193, -188, -206, -0, -31, -7, -110, -206, -221, -187, -29, -27, -9, -158, -162, -122, -57, -53, -22, -27, -166, -215, -206, -126, -237, -53, -25, -96, -75, -167, -223, -44, -115, -109, -187, -252, -181, -138, -58, -106, -189, -144, -150, -24, -224, -64, -255, -72, -22, -240, -243, -55, -3, -211, -129, -3, -19, -250, -219, -152, -121, -186, -101, -188, -108, -69, -63, -195, -164, -231, -47, -230, -174, -127, -205, -191, -190, -31, -36, -212, -113, -54, -240, -219, -200, -117, -72, -156, -2, -186, -69, -107, -47, -164, -126, -187, -127, -39, -142, -91, -18, -202, -118, -195, -60, -141, -203, -230, -43, -218, -219, -59, -252, -222, -220, -245, -9, -126, -253, -3, -21, -229, -23, -7, -94, -4, -198, -71, -238, -13, -65, -173, -206, -213, -64, -107, -47, -164, -94, -155, -239, -1, -102, -97, -43, -168, -236, -200, -183, -154, -95, -223, -176, -162, -124, -55, -204, -211, -184, -236, -92, -137, -225, -120, -33, -216, -106, -233, -55, -5, -247, -46, -5, -126, -88, -82, -182, -49, -243, -116, -203, -120, -115, -29, -134, -227, -133, -0, -75, -2, -47, -3, -91, -21, -220, -223, -214, -239, -47, -89, -112, -191, -27, -230, -105, -92, -118, -174, -196, -156, -246, -66, -186, -97, -158, -110, -25, -111, -174, -195, -232, -11, -105, -1, -116, -163, -78, -180, -242, -75, -1, -255, -11, -252, -180, -102, -185, -159, -123, -185, -165, -154, -180, -59, -138, -150, -64, -55, -234, -68, -43, -127, -5, -166, -195, -175, -171, -139, -159, -7, -51, -163, -254, -161, -73, -187, -163, -104, -1, -116, -171, -78, -156, -139, -1, -44, -3, -188, -14, -108, -19, -185, -183, -131, -223, -91, -102, -56, -250, -214, -4, -69, -95, -231, -39, -36, -93, -233, -182, -246, -63, -250, -121, -50, -186, -153, -62, -186, -157, -122, -122, -141, -16, -194, -83, -146, -174, -146, -180, -103, -228, -246, -158, -146, -254, -228, -52, -131, -0, -44, -136, -57, -121, -124, -46, -114, -239, -72, -191, -183, -96, -228, -222, -217, -152, -129, -238, -62, -224, -204, -204, -245, -177, -152, -133, -54, -201, -32, -150, -12, -90, -208, -158, -117, -51, -125, -212, -41, -235, -194, -222, -143, -129, -215, -114, -215, -43, -95, -142, -51, -217, -171, -184, -173, -35, -119, -239, -77, -192, -211, -80, -104, -169, -220, -215, -229, -148, -121, -50, -215, -230, -245, -50, -251, -148, -180, -185, -30, -102, -28, -219, -58, -115, -109, -99, -204, -79, -97, -221, -130, -50, -107, -250, -180, -184, -46, -240, -104, -230, -250, -133, -192, -167, -138, -218, -106, -12, -186, -212, -158, -117, -51, -125, -212, -45, -11, -252, -2, -179, -77, -204, -200, -93, -175, -124, -57, -206, -0, -55, -147, -113, -254, -200, -220, -219, -3, -184, -177, -132, -1, -22, -244, -119, -180, -77, -230, -218, -118, -217, -247, -86, -210, -238, -199, -128, -39, -129, -101, -157, -129, -31, -6, -62, -86, -81, -230, -58, -103, -174, -143, -248, -249, -187, -48, -103, -147, -55, -149, -149, -107, -4, -186, -212, -158, -49, -12, -150, -44, -96, -102, -230, -56, -233, -229, -248, -51, -29, -79, -206, -224, -229, -247, -254, -0, -28, -81, -196, -0, -78, -243, -35, -220, -57, -197, -207, -207, -3, -126, -148, -216, -223, -95, -96, -190, -130, -127, -0, -126, -145, -88, -102, -89, -224, -223, -126, -252, -39, -220, -195, -170, -85, -208, -189, -30, -123, -88, -44, -89, -57, -6, -72, -122, -57, -206, -0, -219, -98, -243, -235, -26, -153, -235, -203, -3, -255, -196, -220, -208, -202, -24, -96, -59, -124, -26, -240, -191, -167, -200, -120, -18, -85, -180, -189, -48, -54, -69, -61, -69, -197, -28, -142, -59, -189, -2, -107, -97, -158, -85, -219, -99, -14, -171, -1, -27, -253, -94, -43, -43, -95, -11, -116, -169, -61, -99, -152, -44, -89, -29, -6, -200, -188, -156, -147, -128, -73, -216, -240, -26, -157, -10, -156, -1, -182, -195, -124, -14, -190, -156, -185, -254, -121, -224, -112, -191, -87, -198, -0, -99, -128, -199, -156, -81, -182, -246, -31, -52, -105, -201, -235, -31, -218, -116, -108, -154, -27, -178, -154, -200, -209, -222, -130, -9, -128, -119, -2, -239, -243, -231, -219, -14, -88, -221, -127, -175, -25, -101, -229, -147, -65, -11, -218, -51, -134, -201, -146, -5, -204, -244, -47, -162, -243, -114, -54, -197, -28, -90, -22, -3, -166, -23, -148, -233, -48, -192, -106, -206, -40, -99, -188, -142, -187, -49, -107, -102, -41, -3, -120, -29, -103, -96, -186, -142, -179, -73, -116, -253, -118, -198, -254, -23, -240, -73, -224, -88, -108, -4, -90, -168, -186, -164, -4, -236, -7, -252, -17, -152, -31, -184, -26, -120, -27, -240, -122, -74, -217, -158, -131, -97, -182, -100, -117, -94, -78, -238, -218, -4, -224, -138, -2, -122, -112, -199, -20, -76, -224, -219, -22, -24, -143, -207, -201, -137, -12, -240, -14, -108, -249, -54, -25, -88, -191, -170, -143, -94, -230, -76, -224, -42, -103, -182, -121, -128, -127, -0, -149, -46, -230, -216, -202, -228, -126, -44, -86, -224, -28, -6, -166, -202, -153, -85, -101, -251, -2, -134, -209, -146, -149, -125, -57, -153, -107, -155, -2, -215, -82, -108, -121, -203, -50, -192, -161, -216, -114, -242, -2, -96, -123, -191, -86, -201, -0, -78, -119, -59, -112, -123, -21, -157, -211, -110, -9, -60, -75, -38, -152, -5, -243, -196, -126, -149, -204, -210, -176, -160, -236, -81, -192, -5, -126, -252, -47, -108, -138, -155, -228, -207, -49, -188, -90, -83, -134, -217, -146, -149, -125, -57, -126, -190, -13, -112, -17, -176, -112, -73, -153, -44, -3, -44, -14, -252, -219, -95, -236, -24, -191, -150, -196, -0, -169, -0, -222, -2, -60, -64, -68, -166, -193, -228, -144, -7, -129, -183, -20, -148, -93, -4, -147, -55, -198, -70, -238, -141, -140, -17, -96, -184, -16, -123, -57, -206, -48, -247, -101, -190, -146, -141, -34, -229, -102, -51, -128, -159, -255, -146, -140, -11, -92, -219, -12, -48, -226, -1, -108, -229, -28, -122, -47, -176, -113, -230, -250, -242, -152, -144, -212, -174, -202, -113, -20, -35, -11, -152, -20, -190, -13, -166, -139, -191, -46, -115, -253, -7, -192, -145, -195, -217, -183, -81, -244, -1, -216, -154, -244, -45, -192, -66, -248, -210, -9, -211, -63, -223, -75, -47, -84, -142, -163, -24, -89, -192, -140, -20, -29, -6, -120, -222, -175, -93, -78, -137, -113, -195, -105, -26, -27, -100, -156, -110, -39, -204, -0, -116, -149, -255, -93, -6, -76, -232, -254, -137, -134, -31, -12, -198, -12, -44, -170, -233, -68, -42, -236, -5, -5, -117, -189, -189, -224, -250, -82, -190, -138, -200, -135, -245, -111, -130, -197, -101, -44, -157, -218, -192, -13, -153, -41, -224, -111, -216, -154, -248, -159, -152, -150, -107, -136, -108, -144, -41, -215, -141, -65, -230, -100, -224, -123, -89, -9, -31, -88, -218, -175, -149, -70, -254, -212, -101, -28, -111, -107, -50, -240, -138, -255, -159, -0, -124, -26, -51, -204, -60, -5, -156, -75, -196, -28, -155, -41, -191, -14, -240, -83, -23, -56, -159, -198, -150, -157, -167, -149, -49, -184, -255, -240, -157, -24, -136, -177, -192, -7, -48, -101, -213, -223, -139, -218, -194, -116, -254, -223, -243, -118, -94, -5, -166, -248, -52, -252, -34, -176, -92, -65, -153, -139, -240, -24, -206, -204, -181, -115, -113, -187, -74, -18, -128, -205, -48, -201, -249, -126, -96, -139, -140, -76, -16, -149, -13, -34, -229, -107, -25, -100, -128, -93, -24, -80, -186, -128, -169, -70, -31, -7, -142, -245, -107, -223, -43, -250, -65, -155, -48, -14, -102, -194, -125, -15, -182, -228, -251, -152, -127, -145, -147, -176, -105, -110, -37, -255, -0, -162, -241, -142, -192, -110, -254, -110, -246, -194, -109, -19, -152, -99, -200, -119, -252, -171, -142, -46, -55, -253, -185, -182, -203, -93, -91, -8, -91, -242, -157, -16, -161, -95, -10, -19, -184, -127, -131, -41, -153, -22, -1, -54, -192, -84, -228, -143, -20, -49, -27, -3, -150, -200, -5, -253, -124, -126, -44, -186, -107, -151, -24, -125, -37, -128, -125, -112, -229, -2, -17, -217, -160, -160, -76, -45, -131, -12, -230, -50, -182, -148, -31, -131, -169, -53, -87, -195, -194, -211, -23, -244, -31, -244, -178, -72, -185, -44, -227, -172, -4, -252, -197, -31, -246, -119, -126, -173, -144, -113, -50, -117, -204, -139, -105, -24, -63, -150, -185, -182, -7, -240, -112, -132, -118, -172, -191, -252, -149, -10, -234, -186, -144, -140, -45, -33, -119, -111, -8, -3, -248, -245, -207, -17, -201, -250, -1, -252, -183, -51, -229, -152, -28, -237, -3, -152, -138, -250, -11, -5, -237, -4, -103, -170, -255, -231, -231, -123, -249, -199, -52, -79, -140, -190, -20, -152, -86, -237, -94, -92, -181, -73, -68, -54, -40, -40, -151, -55, -200, -148, -90, -171, -24, -156, -238, -5, -224, -67, -192, -113, -152, -110, -188, -163, -140, -185, -42, -82, -46, -203, -56, -191, -195, -244, -241, -99, -112, -61, -64, -9, -227, -172, -128, -133, -188, -61, -236, -127, -49, -188, -17, -41, -247, -117, -224, -56, -63, -94, -13, -83, -27, -79, -197, -134, -230, -21, -48, -245, -245, -189, -145, -114, -67, -144, -185, -247, -65, -224, -229, -72, -153, -201, -157, -182, -252, -124, -93, -76, -167, -177, -165, -191, -155, -59, -242, -101, -50, -180, -159, -7, -174, -241, -227, -203, -129, -83, -139, -104, -75, -1, -124, -138, -140, -93, -27, -147, -7, -182, -198, -101, -131, -146, -114, -121, -131, -76, -169, -181, -42, -194, -0, -87, -96, -115, -241, -58, -153, -235, -49, -6, -200, -150, -123, -14, -88, -61, -66, -19, -43, -247, -103, -204, -211, -104, -17, -103, -24, -176, -16, -184, -172, -237, -97, -136, -233, -25, -251, -34, -215, -246, -227, -107, -128, -195, -252, -248, -85, -44, -98, -122, -12, -240, -74, -164, -92, -39, -16, -118, -167, -124, -221, -192, -238, -192, -139, -145, -50, -175, -0, -123, -249, -241, -188, -152, -12, -118, -150, -159, -239, -89, -244, -46, -253, -254, -114, -152, -208, -183, -14, -230, -151, -184, -70, -17, -109, -33, -252, -229, -60, -202, -96, -93, -245, -32, -217, -160, -162, -124, -178, -181, -202, -127, -240, -37, -253, -24, -167, -61, -16, -56, -207, -175, -45, -69, -252, -75, -206, -51, -192, -106, -17, -154, -24, -3, -188, -4, -236, -234, -199, -227, -188, -205, -83, -202, -158, -199, -105, -95, -102, -96, -110, -125, -9, -120, -59, -54, -26, -130, -141, -150, -139, -3, -79, -23, -148, -133, -248, -20, -240, -37, -224, -214, -200, -245, -87, -24, -200, -199, -112, -2, -54, -34, -116, -204, -227, -123, -17, -25, -53, -114, -229, -127, -135, -77, -191, -133, -31, -106, -207, -64, -77, -107, -21, -102, -219, -254, -185, -31, -119, -24, -32, -96, -158, -50, -155, -96, -115, -249, -16, -199, -208, -28, -227, -252, -22, -243, -34, -26, -195, -192, -180, -80, -196, -56, -147, -176, -233, -226, -173, -216, -84, -112, -163, -51, -208, -222, -206, -16, -239, -5, -118, -143, -148, -123, -9, -88, -212, -143, -31, -194, -134, -227, -29, -176, -17, -96, -25, -44, -140, -254, -226, -130, -103, -28, -194, -0, -94, -230, -73, -224, -63, -35, -244, -147, -49, -47, -165, -245, -48, -33, -117, -211, -204, -189, -227, -129, -59, -99, -237, -228, -222, -41, -184, -235, -88, -95, -65, -3, -107, -21, -240, -85, -44, -16, -36, -43, -205, -47, -133, -45, -45, -79, -46, -40, -147, -101, -156, -149, -176, -37, -224, -52, -60, -137, -85, -9, -227, -108, -143, -205, -253, -211, -129, -111, -97, -67, -236, -209, -126, -237, -117, -108, -78, -143, -249, -7, -78, -196, -163, -156, -177, -161, -123, -138, -63, -215, -4, -224, -127, -48, -225, -108, -229, -130, -190, -130, -77, -1, -11, -96, -242, -194, -1, -152, -176, -118, -13, -145, -21, -18, -230, -91, -112, -15, -54, -141, -158, -150, -185, -62, -143, -51, -71, -244, -157, -100, -232, -118, -114, -134, -45, -52, -130, -245, -4, -116, -97, -173, -242, -31, -244, -10, -108, -202, -184, -218, -143, -75, -151, -47, -77, -24, -167, -41, -128, -255, -44, -98, -224, -132, -178, -89, -60, -143, -45, -169, -143, -2, -230, -43, -160, -95, -6, -147, -222, -95, -198, -150, -172, -11, -99, -115, -250, -149, -206, -116, -67, -150, -129, -206, -28, -11, -97, -194, -232, -93, -192, -25, -77, -250, -58, -199, -161, -9, -227, -52, -108, -103, -62, -255, -98, -127, -69, -198, -117, -219, -127, -172, -86, -29, -51, -177, -21, -204, -115, -152, -101, -242, -49, -76, -168, -155, -234, -35, -86, -52, -84, -206, -71, -150, -87, -188, -220, -15, -128, -249, -219, -236, -147, -168, -25, -218, -53, -55, -194, -153, -224, -211, -152, -84, -62, -13, -243, -29, -120, -0, -23, -88, -91, -110, -43, -26, -31, -208, -55, -144, -203, -172, -73, -196, -109, -122, -20, -115, -15, -98, -95, -247, -254, -146, -54, -240, -227, -219, -36, -213, -138, -238, -29, -197, -28, -142, -58, -67, -190, -207, -89, -175, -145, -243, -184, -193, -194, -157, -94, -45, -154, -183, -114, -180, -141, -194, -200, -71, -209, -3, -48, -216, -18, -213, -17, -64, -190, -77, -137, -73, -17, -211, -174, -125, -35, -119, -237, -219, -20, -172, -141, -35, -229, -107, -133, -145, -211, -48, -139, -246, -40, -163, -85, -128, -1, -75, -212, -165, -12, -88, -162, -214, -243, -31, -248, -62, -92, -25, -18, -41, -183, -11, -166, -194, -237, -228, -2, -126, -147, -11, -73, -61, -177, -233, -99, -214, -183, -14, -3, -36, -121, -227, -122, -185, -36, -70, -195, -20, -66, -19, -49, -69, -204, -237, -84, -104, -63, -115, -101, -107, -51, -39, -53, -82, -187, -231, -202, -181, -203, -208, -152, -37, -234, -94, -114, -22, -36, -76, -203, -54, -153, -98, -139, -215, -60, -62, -98, -236, -226, -231, -187, -59, -35, -69, -95, -52, -109, -57, -48, -244, -8, -152, -54, -243, -84, -96, -9, -76, -115, -152, -148, -19, -217, -203, -214, -98, -78, -224, -187, -152, -86, -114, -117, -76, -135, -145, -156, -218, -189, -238, -200, -153, -82, -225, -32, -75, -84, -238, -222, -241, -101, -28, -141, -41, -102, -126, -230, -199, -191, -161, -192, -108, -153, -161, -175, -229, -192, -208, -132, -105, -176, -168, -160, -105, -228, -220, -176, -49, -83, -247, -179, -37, -35, -218, -11, -25, -102, -222, -139, -2, -61, -255, -92, -7, -50, -150, -168, -200, -189, -82, -67, -4, -102, -38, -157, -142, -185, -135, -205, -160, -192, -118, -158, -161, -175, -237, -192, -80, -151, -105, -252, -254, -137, -152, -118, -44, -100, -174, -221, -70, -196, -25, -35, -115, -255, -39, -152, -61, -98, -2, -166, -149, -59, -172, -236, -89, -188, -76, -19, -217, -169, -47, -101, -146, -209, -13, -3, -56, -205, -95, -49, -15, -153, -63, -150, -209, -57, -109, -109, -7, -134, -134, -76, -179, -136, -127, -237, -239, -243, -243, -157, -177, -136, -227, -178, -128, -145, -245, -48, -211, -246, -27, -192, -222, -9, -207, -82, -91, -118, -234, -87, -153, -90, -192, -116, -205, -199, -23, -220, -75, -177, -68, -29, -236, -47, -46, -150, -58, -37, -70, -95, -203, -129, -161, -9, -211, -100, -218, -185, -193, -143, -255, -74, -193, -52, -231, -247, -223, -235, -12, -115, -54, -166, -233, -251, -25, -3, -206, -41, -135, -19, -113, -200, -160, -129, -236, -212, -175, -50, -181, -128, -37, -130, -190, -47, -210, -64, -146, -37, -170, -65, -123, -181, -29, -24, -234, -50, -141, -211, -45, -236, -95, -253, -103, -49, -169, -57, -26, -126, -229, -180, -119, -0, -95, -242, -227, -149, -24, -112, -200, -92, -206, -153, -237, -195, -145, -50, -181, -101, -167, -126, -149, -169, -133, -204, -16, -115, -21, -230, -138, -148, -181, -68, -117, -63, -196, -196, -219, -172, -229, -192, -208, -132, -105, -188, -220, -113, -24, -134, -216, -224, -115, -116, -47, -2, -187, -101, -206, -87, -198, -28, -100, -94, -0, -190, -95, -80, -166, -246, -212, -217, -175, -50, -41, -200, -238, -26, -246, -140, -164, -77, -36, -77, -145, -244, -39, -73, -255, -150, -101, -8, -123, -80, -182, -251, -85, -161, -67, -104, -23, -248, -158, -164, -237, -37, -37, -165, -109, -245, -157, -205, -174, -148, -116, -150, -108, -199, -178, -201, -137, -237, -116, -148, -82, -67, -210, -215, -231, -112, -163, -164, -227, -176, -101, -220, -56, -73, -155, -202, -118, -239, -154, -79, -210, -180, -196, -182, -230, -40, -204, -155, -61, -241, -45, -224, -62, -218, -199, -246, -103, -74, -154, -33, -233, -162, -26, -101, -190, -39, -233, -119, -170, -215, -207, -212, -32, -207, -131, -36, -125, -93, -198, -248, -11, -73, -154, -36, -233, -11, -146, -110, -146, -116, -45, -240, -74, -8, -33, -191, -130, -152, -34, -41, -234, -16, -226, -215, -239, -143, -92, -239, -87, -153, -222, -131, -226, -165, -73, -52, -89, -34, -93, -58, -48, -208, -192, -235, -133, -129, -93, -63, -86, -173, -211, -86, -98, -221, -181, -101, -167, -126, -149, -233, -57, -40, -95, -154, -60, -64, -102, -179, -168, -76, -153, -218, -14, -12, -45, -48, -77, -47, -25, -160, -182, -236, -212, -175, -50, -61, -7, -189, -94, -154, -12, -212, -215, -91, -175, -151, -46, -145, -25, -5, -31, -167, -190, -82, -167, -167, -101, -154, -62, -80, -82, -198, -110, -122, -189, -52, -25, -197, -240, -128, -196, -140, -221, -244, -104, -105, -50, -138, -254, -97, -222, -216, -197, -16, -194, -44, -73, -71, -181, -80, -127, -123, -73, -12, -71, -209, -19, -12, -50, -37, -82, -223, -216, -48, -69, -229, -75, -147, -41, -249, -139, -52, -180, -210, -213, -133, -11, -125, -177, -168, -156, -194, -220, -63, -152, -47, -195, -49, -152, -63, -192, -75, -152, -98, -232, -110, -160, -141, -143, -97, -100, -163, -66, -162, -47, -146, -76, -171, -150, -38, -255, -85, -208, -86, -19, -43, -93, -45, -230, -172, -203, -0, -254, -227, -95, -135, -5, -101, -236, -224, -140, -250, -86, -224, -253, -177, -122, -114, -253, -122, -202, -143, -151, -6, -30, -47, -233, -79, -7, -149, -201, -34, -98, -253, -199, -98, -45, -175, -35, -30, -195, -56, -147, -248, -30, -6, -105, -201, -174, -104, -102, -160, -40, -91, -154, -220, -73, -65, -6, -76, -106, -90, -233, -26, -50, -103, -93, -6, -56, -14, -75, -252, -80, -107, -4, -2, -118, -197, -147, -81, -98, -219, -202, -71, -211, -220, -123, -127, -146, -147, -69, -228, -251, -15, -124, -25, -27, -153, -138, -114, -4, -212, -122, -222, -14, -178, -83, -192, -174, -146, -190, -239, -243, -255, -108, -132, -16, -222, -144, -169, -106, -135, -108, -22, -25, -81, -31, -79, -147, -116, -151, -164, -151, -36, -109, -17, -66, -24, -18, -1, -235, -229, -158, -151, -244, -223, -146, -58, -43, -136, -207, -74, -58, -35, -132, -240, -66, -65, -63, -63, -43, -233, -85, -73, -31, -10, -33, -220, -30, -66, -120, -62, -132, -112, -167, -108, -131, -134, -55, -36, -125, -166, -160, -92, -29, -236, -39, -233, -188, -6, -42, -239, -13, -36, -77, -140, -28, -199, -240, -122, -8, -225, -149, -16, -194, -148, -16, -194, -111, -37, -109, -37, -105, -41, -73, -71, -151, -53, -0, -28, -42, -105, -15, -73, -59, -250, -187, -107, -31, -180, -36, -209, -99, -86, -186, -137, -249, -145, -36, -66, -87, -199, -74, -215, -196, -122, -86, -138, -8, -253, -12, -96, -191, -148, -103, -116, -250, -231, -252, -111, -38, -102, -44, -26, -116, -92, -208, -159, -58, -201, -34, -240, -175, -247, -3, -62, -250, -69, -115, -4, -37, -212, -159, -60, -2, -180, -133, -79, -75, -90, -69, -210, -37, -148, -36, -67, -242, -175, -253, -12, -73, -95, -145, -116, -122, -8, -225, -165, -146, -58, -223, -46, -233, -161, -130, -123, -15, -122, -123, -49, -236, -44, -105, -129, -220, -223, -206, -69, -93, -146, -217, -38, -102, -163, -140, -97, -66, -8, -139, -133, -16, -22, -147, -244, -164, -164, -181, -252, -248, -127, -37, -173, -238, -199, -169, -184, -167, -164, -255, -235, -75, -250, -153, -108, -116, -28, -146, -189, -164, -13, -100, -25, -96, -138, -90, -48, -54, -132, -16, -238, -149, -89, -248, -222, -144, -84, -149, -201, -58, -213, -74, -215, -20, -157, -33, -119, -246, -95, -73, -159, -30, -148, -148, -207, -53, -80, -198, -48, -194, -118, -20, -39, -132, -48, -21, -75, -224, -52, -203, -13, -106, -117, -48, -70, -210, -172, -130, -123, -235, -203, -166, -166, -147, -128, -229, -107, -214, -155, -220, -120, -7, -151, -73, -58, -36, -63, -116, -251, -249, -193, -146, -46, -77, -173, -52, -132, -240, -247, -16, -194, -110, -33, -132, -170, -60, -182, -169, -86, -186, -41, -234, -189, -37, -236, -18, -73, -135, -146, -145, -176, -203, -24, -198, -135, -249, -127, -73, -90, -214, -143, -39, -75, -90, -174, -51, -53, -212, -104, -247, -157, -94, -54, -134, -11, -93, -86, -184, -72, -210, -79, -200, -172, -154, -34, -152, -37, -51, -91, -231, -241, -38, -229, -70, -182, -44, -178, -12, -112, -170, -19, -95, -73, -70, -162, -151, -116, -185, -211, -69, -51, -104, -245, -9, -173, -49, -103, -9, -206, -144, -9, -175, -127, -194, -178, -164, -45, -138, -173, -74, -162, -95, -158, -15, -243, -231, -72, -58, -209, -143, -207, -148, -116, -82, -102, -106, -168, -4, -102, -49, -253, -152, -108, -152, -47, -195, -103, -36, -173, -36, -233, -216, -18, -154, -123, -37, -189, -59, -114, -125, -35, -191, -151, -212, -161, -254, -24, -27, -6, -218, -75, -178, -210, -209, -204, -122, -86, -91, -40, -194, -188, -154, -191, -137, -101, -5, -155, -233, -130, -225, -189, -20, -236, -235, -227, -237, -79, -240, -227, -203, -40, -217, -234, -206, -251, -83, -39, -89, -196, -160, -254, -99, -233, -239, -95, -6, -54, -200, -211, -250, -253, -61, -48, -167, -217, -3, -253, -119, -124, -27, -112, -144, -11, -165, -251, -23, -245, -107, -142, -65, -191, -153, -51, -177, -79, -79, -116, -218, -247, -227, -183, -149, -208, -102, -145, -146, -44, -98, -8, -3, -99, -241, -23, -147, -41, -78, -43, -255, -62, -44, -132, -253, -101, -103, -222, -155, -129, -15, -117, -243, -140, -163, -24, -197, -40, -70, -49, -138, -185, -31, -62, -231, -220, -157, -159, -147, -42, -132, -166, -43, -124, -94, -126, -210, -231, -230, -239, -2, -151, -39, -180, -53, -98, -66, -181, -105, -24, -110, -62, -183, -32, -175, -9, -92, -84, -210, -49, -53, -202, -63, -41, -105, -89, -73, -107, -75, -90, -75, -210, -91, -252, -90, -21, -46, -144, -45, -125, -134, -4, -90, -228, -65, -162, -119, -82, -174, -76, -157, -144, -235, -236, -26, -185, -72, -33, -83, -214, -86, -85, -184, -249, -10, -152, -89, -121, -205, -18, -154, -206, -190, -73, -235, -213, -108, -187, -52, -112, -21, -203, -99, -124, -117, -238, -218, -159, -201, -236, -175, -148, -189, -1, -240, -31, -46, -161, -142, -203, -92, -47, -27, -1, -30, -3, -86, -201, -156, -47, -82, -213, -169, -186, -32, -209, -59, -41, -67, -223, -56, -228, -58, -177, -254, -90, -57, -148, -128, -243, -49, -251, -72, -105, -194, -12, -108, -207, -133, -115, -203, -104, -156, -110, -33, -6, -194, -213, -254, -234, -255, -3, -17, -203, -171, -255, -30, -15, -2, -255, -225, -231, -135, -96, -206, -186, -67, -173, -174, -206, -0, -91, -250, -131, -93, -158, -185, -94, -198, -0, -79, -144, -73, -146, -136, -173, -207, -163, -241, -244, -116, -107, -175, -110, -25, -77, -251, -131, -237, -228, -185, -178, -191, -167, -231, -128, -35, -74, -104, -215, -240, -23, -62, -63, -102, -30, -127, -103, -9, -237, -70, -216, -154, -189, -106, -131, -141, -19, -48, -179, -245, -79, -49, -31, -138, -159, -98, -9, -58, -190, -88, -64, -191, -137, -223, -127, -167, -255, -31, -178, -231, -67, -135, -16, -108, -139, -182, -133, -176, -112, -168, -78, -170, -215, -50, -6, -248, -1, -150, -174, -117, -49, -255, -241, -127, -82, -244, -197, -121, -253, -117, -236, -243, -181, -126, -160, -6, -244, -181, -250, -147, -185, -95, -39, -135, -210, -175, -128, -143, -250, -241, -190, -68, -82, -216, -230, -232, -255, -9, -28, -94, -65, -179, -8, -182, -165, -252, -49, -216, -212, -114, -180, -159, -23, -250, -49, -96, -142, -39, -51, -136, -56, -232, -228, -31, -38, -184, -13, -255, -40, -73, -103, -71, -135, -138, -193, -120, -171, -164, -103, -100, -170, -198, -251, -100, -115, -104, -105, -110, -128, -26, -152, -39, -210, -191, -54, -233, -107, -193, -25, -230, -110, -111, -39, -123, -189, -136, -193, -54, -148, -244, -46, -13, -132, -189, -93, -36, -105, -53, -96, -147, -146, -102, -206, -145, -52, -36, -93, -109, -22, -238, -15, -48, -77, -246, -27, -29, -44, -179, -190, -78, -171, -240, -99, -24, -39, -233, -89, -255, -63, -8, -209, -23, -22, -66, -248, -181, -44, -69, -220, -41, -42, -49, -36, -132, -16, -118, -9, -33, -28, -18, -66, -88, -38, -132, -240, -182, -16, -194, -193, -33, -132, -29, -203, -30, -96, -14, -71, -29, -33, -249, -84, -73, -167, -116, -12, -98, -238, -88, -243, -21, -73, -101, -177, -18, -191, -144, -244, -54, -42, -118, -17, -149, -180, -177, -164, -137, -33, -132, -95, -74, -186, -69, -210, -123, -139, -8, -49, -175, -171, -237, -36, -189, -71, -210, -14, -120, -198, -244, -24, -225, -160, -33, -17, -203, -160, -253, -60, -182, -189, -74, -215, -115, -116, -131, -41, -96, -36, -210, -215, -18, -146, -155, -0, -115, -205, -251, -101, -75, -117, -45, -137, -201, -105, -157, -233, -124, -79, -63, -95, -162, -67, -83, -56, -100, -134, -16, -30, -146, -244, -85, -73, -95, -106, -163, -51, -115, -9, -238, -151, -116, -190, -164, -111, -245, -176, -141, -115, -37, -189, -159, -130, -13, -162, -106, -226, -219, -146, -238, -8, -33, -252, -74, -146, -124, -196, -184, -211, -175, -75, -170, -158, -51, -191, -38, -11, -19, -111, -3, -141, -236, -213, -61, -68, -147, -254, -204, -39, -233, -68, -73, -235, -119, -190, -170, -182, -17, -66, -184, -95, -210, -181, -50, -51, -113, -183, -117, -237, -29, -66, -152, -144, -187, -182, -67, -8, -97, -246, -86, -128, -217, -252, -0, -33, -132, -112, -117, -142, -248, -245, -16, -194, -58, -33, -132, -50, -71, -132, -84, -212, -181, -87, -215, -253, -129, -234, -210, -55, -177, -159, -215, -21, -146, -155, -226, -28, -73, -31, -197, -115, -47, -206, -21, -160, -166, -189, -26, -83, -209, -126, -62, -114, -253, -11, -46, -141, -119, -75, -95, -183, -63, -121, -25, -233, -114, -44, -151, -208, -248, -54, -101, -128, -185, -26, -212, -176, -87, -55, -248, -129, -106, -59, -68, -212, -236, -79, -158, -1, -90, -21, -146, -71, -17, -65, -157, -31, -168, -9, -125, -205, -190, -12, -89, -53, -96, -46, -237, -79, -14, -39, -3, -120, -191, -54, -175, -166, -76, -171, -108, -173, -252, -57, -17, -71, -68, -74, -208, -74, -71, -70, -32, -10, -24, -96, -62, -204, -130, -58, -231, -51, -0, -176, -10, -166, -99, -222, -193, -207, -183, -33, -183, -143, -95, -134, -182, -179, -207, -222, -26, -222, -129, -181, -41, -216, -119, -111, -20, -67, -129, -109, -170, -149, -36, -88, -99, -6, -173, -168, -219, -152, -223, -111, -117, -4, -216, -210, -153, -224, -243, -254, -127, -124, -5, -253, -88, -239, -64, -235, -169, -87, -230, -102, -164, -254, -248, -78, -75, -217, -135, -149, -101, -0, -204, -225, -244, -38, -114, -41, -117, -235, -118, -238, -24, -175, -52, -154, -53, -52, -71, -155, -196, -0, -88, -46, -225, -171, -49, -227, -197, -19, -152, -141, -255, -255, -252, -94, -68, -41, -72, -101, -0, -44, -136, -247, -55, -192, -239, -105, -178, -103, -176, -87, -182, -149, -127, -249, -157, -72, -217, -237, -43, -232, -83, -25, -224, -70, -44, -217, -243, -50, -152, -229, -234, -160, -146, -135, -129, -129, -125, -252, -206, -1, -22, -79, -232, -119, -233, -48, -233, -52, -75, -97, -142, -34, -83, -177, -56, -200, -135, -40, -216, -45, -188, -23, -192, -220, -192, -99, -136, -109, -33, -123, -97, -1, -237, -175, -34, -180, -96, -91, -204, -125, -195, -191, -254, -232, -182, -244, -41, -29, -28, -135, -205, -249, -219, -248, -249, -22, -126, -190, -86, -73, -153, -84, -6, -120, -153, -34, -35, -196, -96, -58, -48, -223, -249, -133, -49, -251, -248, -157, -120, -26, -250, -132, -114, -101, -95, -201, -34, -152, -59, -245, -213, -152, -235, -215, -226, -254, -124, -177, -212, -175, -11, -3, -23, -224, -210, -125, -22, -17, -218, -107, -129, -255, -206, -93, -59, -25, -207, -77, -156, -187, -62, -134, -220, -62, -197, -254, -55, -36, -225, -21, -38, -92, -118, -238, -131, -5, -169, -188, -153, -8, -147, -251, -253, -142, -7, -212, -16, -121, -173, -22, -200, -24, -57, -252, -188, -40, -104, -177, -115, -63, -149, -1, -238, -33, -205, -219, -5, -6, -175, -181, -247, -7, -42, -85, -209, -9, -12, -112, -10, -230, -189, -84, -24, -172, -154, -161, -61, -39, -247, -187, -79, -194, -116, -10, -147, -34, -180, -91, -96, -211, -90, -103, -43, -219, -249, -253, -163, -121, -127, -69, -27, -109, -203, -0, -191, -194, -188, -160, -174, -168, -83, -119, -215, -168, -193, -0, -59, -99, -27, -62, -92, -71, -137, -61, -60, -194, -0, -31, -6, -162, -193, -150, -212, -27, -38, -239, -166, -98, -19, -139, -12, -237, -99, -185, -250, -238, -242, -235, -81, -135, -81, -44, -215, -241, -201, -126, -124, -176, -51, -123, -233, -143, -64, -15, -86, -1, -216, -200, -245, -16, -240, -233, -148, -122, -91, -65, -42, -3, -56, -237, -234, -152, -144, -50, -139, -200, -208, -235, -52, -48, -48, -5, -108, -140, -165, -145, -249, -66, -1, -109, -157, -97, -242, -21, -96, -159, -88, -61, -17, -218, -153, -53, -25, -96, -19, -204, -71, -112, -17, -108, -47, -225, -131, -83, -218, -105, -11, -29, -6, -240, -227, -205, -49, -5, -216, -187, -250, -213, -120, -237, -101, -32, -182, -15, -79, -52, -214, -63, -242, -53, -31, -153, -88, -39, -148, -15, -147, -175, -144, -176, -249, -131, -211, -78, -175, -195, -0, -126, -239, -114, -76, -250, -158, -74, -36, -206, -175, -151, -200, -50, -128, -159, -127, -5, -155, -182, -10, -19, -110, -12, -43, -176, -164, -75, -209, -52, -39, -254, -48, -219, -249, -241, -223, -129, -66, -239, -155, -220, -8, -112, -169, -143, -26, -69, -35, -192, -36, -224, -115, -137, -253, -251, -83, -42, -3, -48, -48, -250, -228, -177, -66, -74, -91, -35, -10, -184, -85, -43, -134, -46, -235, -93, -10, -51, -208, -44, -141, -249, -200, -95, -6, -252, -174, -128, -54, -203, -0, -187, -97, -75, -209, -162, -68, -83, -117, -100, -128, -51, -177, -249, -177, -242, -235, -196, -146, -80, -61, -156, -194, -0, -126, -61, -59, -13, -237, -196, -156, -170, -13, -37, -190, -76, -89, -180, -5, -6, -88, -28, -219, -170, -165, -147, -71, -231, -18, -10, -162, -104, -115, -12, -16, -48, -225, -45, -233, -203, -173, -232, -195, -210, -152, -167, -243, -223, -176, -53, -243, -34, -216, -178, -183, -72, -22, -121, -51, -176, -1, -176, -97, -25, -3, -208, -197, -8, -224, -12, -254, -40, -17, -165, -77, -65, -157, -253, -183, -55, -116, -30, -176, -143, -237, -205, -102, -0, -63, -255, -48, -45, -37, -143, -4, -150, -7, -190, -143, -133, -176, -205, -194, -76, -185, -215, -38, -148, -235, -201, -8, -128, -229, -58, -40, -202, -163, -56, -187, -174, -236, -95, -74, -189, -173, -2, -155, -103, -135, -36, -71, -192, -180, -121, -127, -241, -151, -217, -193, -227, -100, -156, -13, -71, -50, -128, -139, -129, -75, -18, -105, -43, -133, -64, -191, -63, -136, -121, -43, -104, -87, -199, -150, -197, -149, -35, -97, -66, -155, -187, -96, -59, -156, -206, -192, -130, -86, -214, -79, -233, -67, -87, -192, -134, -244, -147, -252, -248, -68, -224, -250, -158, -55, -218, -34, -176, -41, -33, -41, -223, -94, -42, -3, -212, -108, -255, -44, -160, -112, -151, -148, -154, -12, -48, -25, -155, -170, -150, -193, -132, -225, -222, -255, -22, -206, -109, -219, -250, -241, -182, -68, -244, -217, -125, -232, -67, -22, -47, -99, -243, -233, -197, -84, -107, -47, -255, -138, -173, -48, -62, -153, -216, -78, -171, -12, -128, -89, -236, -166, -1, -91, -149, -208, -68, -81, -64, -247, -137, -204, -249, -142, -64, -81, -178, -205, -40, -154, -90, -228, -238, -151, -244, -65, -31, -242, -63, -168, -226, -44, -87, -131, -128, -205, -233, -80, -18, -35, -87, -19, -157, -60, -128, -111, -147, -101, -50, -93, -82, -210, -144, -85, -64, -22, -33, -132, -45, -66, -8, -27, -133, -16, -206, -105, -169, -15, -117, -177, -159, -164, -199, -66, -8, -215, -85, -208, -197, -114, -28, -198, -144, -117, -96, -125, -81, -182, -215, -81, -111, -225, -67, -206, -52, -204, -106, -55, -145, -4, -205, -19, -176, -32, -166, -217, -123, -190, -136, -1, -48, -189, -122, -244, -47, -66, -59, -100, -152, -196, -36, -235, -178, -132, -147, -195, -14, -204, -101, -173, -116, -244, -169, -57, -5, -100, -149, -64, -155, -199, -70, -138, -50, -148, -186, -29, -3, -99, -60, -164, -105, -16, -66, -8, -255, -196, -214, -212, -107, -132, -16, -30, -76, -108, -235, -51, -178, -221, -184, -10, -99, -223, -66, -8, -141, -184, -23, -83, -254, -140, -149, -237, -36, -86, -103, -7, -178, -174, -128, -57, -204, -68, -87, -18, -49, -87, -122, -44, -50, -119, -13, -73, -63, -233, -109, -207, -26, -130, -26, -177, -239, -88, -122, -179, -14, -158, -164, -68, -213, -138, -45, -193, -158, -192, -148, -66, -111, -180, -49, -5, -20, -76, -147, -23, -208, -212, -25, -162, -89, -31, -138, -76, -188, -209, -37, -27, -233, -57, -0, -250, -54, -2, -228, -101, -128, -253, -101, -25, -175, -37, -11, -14, -141, -166, -112, -1, -206, -145, -101, -239, -92, -213, -255, -206, -85, -121, -34, -201, -175, -74, -58, -199, -179, -139, -183, -105, -174, -236, -204, -147, -11, -75, -26, -47, -11, -234, -248, -122, -164, -191, -27, -98, -186, -250, -233, -88, -130, -234, -139, -40, -73, -233, -150, -138, -16, -194, -27, -249, -84, -180, -153, -148, -180, -249, -62, -44, -41, -105, -47, -101, -194, -178, -70, -28, -72, -116, -211, -242, -121, -121, -163, -204, -249, -38, -20, -164, -71, -197, -52, -111, -143, -227, -198, -9, -231, -218, -182, -70, -128, -188, -12, -176, -63, -240, -108, -132, -246, -66, -204, -81, -99, -101, -108, -13, -126, -45, -5, -121, -253, -157, -62, -201, -123, -136, -30, -169, -207, -135, -5, -222, -239, -36, -165, -2, -102, -207, -62, -210, -143, -23, -244, -23, -28, -141, -104, -5, -110, -192, -44, -84, -171, -250, -31, -152, -255, -126, -87, -201, -143, -11, -24, -224, -96, -224, -177, -132, -178, -239, -163, -216, -32, -85, -199, -123, -168, -214, -20, -48, -162, -225, -47, -52, -73, -169, -224, -95, -252, -173, -152, -243, -196, -67, -88, -166, -176, -168, -22, -176, -232, -11, -1, -254, -210, -66, -127, -59, -234, -210, -69, -49, -143, -230, -251, -129, -51, -19, -202, -126, -130, -72, -184, -152, -223, -75, -246, -30, -154, -171, -224, -47, -180, -43, -165, -66, -141, -118, -218, -22, -2, -103, -98, -185, -120, -78, -166, -98, -83, -73, -44, -5, -206, -125, -192, -199, -11, -238, -39, -123, -15, -205, -85, -240, -23, -185, -109, -230, -188, -182, -68, -89, -163, -157, -182, -20, -65, -117, -219, -158, -199, -71, -182, -223, -80, -224, -146, -69, -13, -239, -161, -134, -125, -56, -44, -50, -26, -198, -18, -85, -64, -66, -192, -7, -240, -59, -76, -86, -153, -138, -9, -184, -93, -233, -1, -94, -173, -83, -184, -9, -90, -10, -53, -175, -13, -76, -192, -253, -129, -164, -197, -101, -123, -239, -148, -189, -168, -94, -10, -113, -75, -73, -186, -66, -82, -214, -219, -169, -82, -110, -41, -66, -8, -97, -182, -3, -42, -240, -99, -21, -107, -12, -163, -152, -123, -226, -207, -75, -224, -95, -251, -119, -100, -75, -214, -9, -33, -132, -178, -253, -143, -166, -168, -120, -11, -151, -170, -118, -86, -150, -229, -1, -218, -82, -166, -150, -30, -31, -66, -184, -41, -71, -182, -148, -164, -7, -61, -17, -68, -107, -0, -54, -147, -244, -33, -89, -194, -206, -100, -212, -182, -5, -96, -82, -242, -143, -128, -127, -99, -10, -160, -202, -8, -162, -17, -128, -111, -200, -244, -4, -71, -200, -146, -48, -117, -86, -36, -177, -156, -124, -127, -144, -37, -103, -168, -229, -219, -135, -101, -50, -189, -78, -54, -122, -76, -144, -237, -115, -116, -103, -132, -116, -41, -217, -222, -66, -41, -216, -4, -19, -204, -103, -96, -249, -0, -163, -242, -141, -143, -110, -223, -146, -244, -213, -16, -194, -163, -117, -250, -157, -173, -100, -208, -156, -83, -36, -3, -0, -223, -193, -44, -106, -171, -57, -205, -35, -192, -1, -141, -26, -237, -65, -255, -74, -202, -198, -240, -145, -8, -109, -45, -239, -161, -76, -185, -255, -194, -54, -131, -172, -218, -45, -237, -50, -204, -59, -234, -53, -76, -63, -242, -109, -34, -153, -70, -188, -127, -183, -97, -190, -23, -107, -98, -130, -235, -23, -10, -234, -60, -212, -239, -247, -126, -87, -117, -239, -244, -142, -153, -243, -143, -18, -89, -46, -22, -9, -55, -5, -117, -158, -128, -229, -3, -126, -26, -56, -151, -226, -141, -20, -187, -82, -123, -166, -130, -6, -222, -67, -88, -46, -130, -74, -247, -53, -44, -115, -215, -170, -216, -82, -123, -107, -204, -97, -245, -194, -8, -29, -120, -138, -87, -63, -255, -52, -241, -76, -39, -75, -98, -163, -241, -46, -169, -207, -215, -21, -48, -117, -234, -123, -51, -231, -59, -0, -67, -146, -20, -166, -50, -0, -176, -31, -166, -88, -90, -23, -88, -9, -83, -28, -197, -180, -110, -125, -99, -128, -38, -192, -252, -29, -191, -136, -133, -179, -189, -128, -69, -233, -84, -42, -187, -176, -61, -25, -103, -68, -174, -67, -38, -95, -32, -166, -188, -26, -34, -164, -99, -35, -114, -105, -6, -210, -50, -52, -241, -7, -184, -94, -210, -17, -62, -52, -190, -93, -182, -251, -103, -179, -128, -68, -195, -17, -146, -190, -22, -66, -184, -43, -132, -240, -136, -76, -151, -191, -103, -23, -245, -13, -23, -22, -146, -180, -181, -164, -221, -36, -173, -40, -233, -101, -153, -141, -164, -10, -243, -73, -122, -170, -224, -222, -152, -220, -113, -140, -225, -63, -42, -105, -51, -6, -150, -130, -83, -233, -165, -91, -186, -127, -165, -87, -98, -246, -128, -59, -157, -235, -159, -137, -208, -165, -142, -0, -207, -50, -20, -67, -76, -208, -145, -17, -96, -251, -17, -54, -2, -188, -64, -38, -0, -22, -83, -31, -199, -70, -198, -227, -125, -180, -91, -26, -139, -198, -190, -15, -56, -37, -66, -7, -158, -103, -216, -207, -143, -161, -7, -251, -25, -204, -230, -48, -76, -175, -125, -134, -255, -32, -79, -99, -33, -221, -135, -228, -11, -132, -16, -30, -9, -33, -236, -24, -66, -88, -40, -132, -176, -158, -164, -87, -148, -186, -45, -89, -113, -31, -246, -209, -96, -207, -151, -216, -136, -242, -146, -6, -123, -187, -172, -17, -171, -44, -195, -68, -179, -48, -19, -244, -55, -72, -8, -49, -111, -1, -119, -201, -190, -252, -14, -22, -146, -121, -232, -228, -241, -30, -217, -40, -58, -85, -210, -121, -146, -126, -36, -41, -154, -233, -91, -210, -145, -152, -0, -184, -150, -164, -195, -212, -75, -63, -2, -224, -63, -157, -27, -215, -198, -50, -91, -19, -99, -128, -72, -185, -137, -192, -137, -145, -235, -169, -35, -192, -45, -120, -112, -101, -5, -221, -13, -152, -6, -111, -25, -76, -58, -159, -28, -27, -1, -188, -221, -78, -124, -225, -38, -152, -106, -247, -231, -17, -186, -113, -88, -166, -243, -206, -30, -192, -151, -18, -217, -159, -55, -50, -58, -81, -208, -238, -129, -152, -13, -97, -75, -108, -133, -116, -3, -240, -157, -170, -231, -42, -121, -94, -128, -207, -96, -246, -141, -151, -177, -125, -7, -122, -23, -118, -134, -5, -54, -30, -229, -199, -215, -96, -214, -176, -91, -34, -116, -243, -99, -238, -226, -75, -98, -142, -35, -83, -137, -108, -221, -86, -131, -1, -246, -194, -156, -80, -62, -4, -172, -136, -229, -5, -216, -45, -66, -247, -78, -103, -182, -87, -48, -139, -229, -174, -37, -12, -144, -141, -45, -56, -0, -152, -22, -161, -187, -25, -11, -169, -30, -135, -229, -71, -250, -5, -112, -107, -132, -110, -213, -220, -223, -215, -40, -112, -148, -193, -150, -130, -79, -97, -82, -249, -15, -169, -200, -253, -95, -6, -127, -142, -118, -114, -255, -36, -54, -56, -29, -147, -52, -183, -193, -252, -214, -118, -45, -120, -113, -27, -97, -107, -216, -255, -197, -162, -124, -242, -251, -237, -118, -232, -146, -24, -192, -105, -63, -130, -133, -99, -205, -116, -134, -250, -84, -23, -207, -145, -103, -128, -168, -137, -24, -155, -179, -179, -50, -197, -150, -84, -24, -191, -48, -91, -194, -20, -122, -104, -43, -200, -180, -149, -204, -0, -152, -60, -52, -209, -71, -138, -169, -36, -140, -168, -177, -74, -166, -97, -67, -231, -141, -152, -37, -240, -3, -68, -156, -43, -106, -212, -7, -67, -163, -91, -74, -211, -184, -180, -129, -76, -187, -139, -49, -32, -100, -157, -29, -161, -251, -33, -240, -107, -204, -58, -184, -16, -230, -49, -84, -234, -41, -12, -236, -141, -41, -137, -122, -174, -66, -175, -201, -0, -79, -98, -250, -152, -69, -177, -216, -198, -241, -77, -26, -252, -7, -22, -230, -220, -217, -135, -230, -104, -224, -239, -181, -43, -26, -168, -47, -134, -82, -151, -237, -54, -144, -105, -107, -38, -230, -171, -112, -10, -241, -173, -89, -231, -199, -194, -179, -158, -197, -134, -236, -243, -168, -222, -0, -234, -22, -224, -179, -45, -244, -177, -213, -157, -202, -188, -190, -243, -233, -38, -132, -14, -248, -148, -191, -184, -253, -49, -65, -240, -1, -224, -208, -110, -59, -215, -111, -248, -51, -164, -200, -30, -187, -251, -151, -179, -157, -63, -251, -179, -148, -7, -107, -116, -146, -47, -44, -217, -66, -31, -239, -200, -48, -192, -237, -45, -212, -55, -30, -115, -209, -159, -142, -109, -47, -91, -223, -153, -5, -203, -171, -251, -15, -127, -17, -211, -128, -47, -85, -125, -17, -253, -4, -22, -45, -124, -154, -247, -237, -25, -34, -137, -161, -157, -46, -149, -1, -38, -147, -209, -239, -99, -94, -66, -49, -227, -77, -231, -254, -111, -40, -217, -129, -12, -203, -104, -50, -209, -153, -228, -206, -70, -195, -112, -67, -120, -123, -7, -249, -135, -123, -11, -240, -219, -126, -53, -12, -53, -247, -186, -43, -168, -99, -8, -34, -116, -7, -99, -235, -250, -119, -97, -110, -107, -79, -1, -187, -23, -212, -151, -194, -0, -47, -98, -38, -212, -206, -249, -86, -68, -20, -55, -126, -111, -21, -159, -82, -10, -179, -112, -249, -87, -253, -77, -204, -135, -240, -43, -64, -212, -220, -235, -253, -107, -85, -165, -141, -9, -180, -59, -249, -241, -102, -244, -58, -56, -6, -56, -28, -19, -174, -240, -161, -39, -105, -79, -191, -130, -186, -242, -14, -149, -151, -17, -9, -156, -196, -150, -166, -95, -204, -156, -159, -76, -68, -7, -94, -131, -1, -174, -196, -214, -254, -227, -176, -117, -251, -31, -129, -95, -23, -208, -126, -11, -184, -170, -162, -190, -89, -157, -175, -30, -19, -66, -135, -232, -247, -51, -253, -171, -197, -0, -20, -120, -92, -103, -238, -159, -238, -31, -196, -193, -192, -73, -192, -53, -101, -244, -93, -193, -27, -121, -209, -135, -156, -21, -176, -124, -193, -155, -69, -232, -222, -135, -101, -5, -123, -17, -27, -182, -47, -7, -86, -175, -168, -123, -107, -108, -41, -51, -54, -114, -111, -42, -153, -204, -223, -152, -222, -160, -177, -39, -141, -247, -253, -82, -6, -166, -148, -11, -137, -236, -78, -234, -95, -244, -139, -84, -88, -219, -178, -63, -44, -230, -36, -251, -199, -42, -58, -63, -239, -154, -1, -156, -102, -87, -76, -249, -4, -137, -249, -144, -26, -1, -83, -194, -156, -154, -64, -247, -117, -224, -8, -76, -149, -185, -10, -54, -135, -22, -174, -42, -48, -85, -244, -109, -192, -87, -10, -238, -191, -204, -96, -159, -197, -109, -129, -215, -154, -61, -69, -79, -60, -184, -94, -0, -0, -18, -40, -73, -68, -65, -84, -251, -200, -49, -192, -115, -192, -7, -170, -232, -252, -188, -200, -239, -98, -69, -76, -178, -159, -226, -101, -30, -163, -64, -238, -201, -149, -251, -36, -53, -118, -111, -205, -218, -2, -82, -57, -115, -13, -73, -149, -203, -195, -16, -194, -81, -33, -132, -111, -134, -16, -38, -133, -16, -30, -144, -237, -23, -92, -54, -2, -252, -135, -108, -31, -194, -175, -22, -220, -207, -247, -101, -94, -73, -175, -87, -245, -99, -152, -48, -70, -233, -190, -121, -69, -116, -157, -60, -74, -239, -147, -244, -188, -164, -93, -36, -253, -45, -79, -132, -173, -253, -247, -195, -54, -201, -88, -92, -182, -181, -221, -16, -5, -94, -17, -154, -40, -52, -130, -226, -102, -201, -40, -48, -231, -142, -119, -201, -12, -30, -81, -243, -40, -230, -17, -115, -138, -164, -207, -135, -16, -138, -180, -113, -79, -203, -28, -58, -59, -88, -212, -175, -141, -68, -156, -45, -233, -187, -192, -191, -66, -8, -249, -101, -94, -146, -81, -75, -182, -41, -247, -255, -132, -16, -238, -4, -8, -33, -220, -86, -210, -222, -161, -50, -195, -82, -144, -52, -81, -210, -190, -181, -123, -92, -99, -104, -186, -139, -136, -249, -178, -164, -78, -48, -1, -233, -28, -10, -220, -165, -176, -181, -235, -109, -148, -44, -59, -49, -161, -237, -212, -204, -249, -233, -84, -11, -102, -125, -219, -166, -62, -55, -5, -4, -151, -47, -254, -26, -161, -75, -53, -106, -77, -192, -220, -237, -30, -197, -150, -150, -221, -229, -1, -174, -243, -0, -126, -94, -196, -0, -31, -193, -92, -164, -14, -192, -92, -167, -86, -195, -118, -167, -140, -213, -185, -152, -207, -101, -31, -196, -116, -253, -223, -143, -208, -140, -245, -249, -189, -116, -183, -76, -204, -104, -244, -12, -166, -60, -121, -47, -166, -175, -56, -168, -162, -204, -21, -88, -58, -150, -40, -99, -81, -99, -107, -122, -42, -182, -164, -143, -188, -191, -9, -192, -16, -239, -99, -18, -141, -90, -78, -59, -47, -102, -163, -152, -137, -41, -121, -26, -219, -72, -42, -17, -121, -128, -66, -135, -11, -44, -140, -60, -187, -12, -188, -60, -70, -151, -43, -179, -47, -145, -120, -60, -44, -173, -203, -101, -164, -133, -87, -127, -145, -1, -69, -213, -233, -116, -153, -24, -153, -196, -173, -233, -73, -216, -146, -62, -55, -2, -108, -134, -105, -23, -155, -121, -232, -14, -173, -251, -57, -10, -140, -115, -173, -193, -31, -32, -235, -236, -121, -120, -17, -3, -228, -202, -36, -41, -130, -176, -244, -48, -49, -171, -92, -20, -245, -159, -96, -80, -157, -149, -78, -166, -109, -35, -199, -0, -19, -177, -81, -114, -136, -215, -113, -141, -250, -254, -11, -27, -233, -222, -234, -117, -157, -69, -36, -99, -121, -107, -240, -7, -200, -206, -77, -15, -116, -243, -67, -248, -215, -250, -78, -44, -213, -250, -54, -36, -6, -110, -118, -11, -18, -157, -76, -157, -54, -197, -27, -121, -127, -76, -203, -247, -146, -255, -47, -220, -168, -185, -77, -96, -166, -246, -71, -49, -211, -251, -27, -254, -28, -27, -20, -208, -110, -129, -5, -235, -118, -204, -193, -73, -50, -90, -190, -18, -48, -109, -219, -11, -192, -189, -152, -121, -177, -27, -6, -184, -16, -211, -78, -189, -234, -204, -244, -101, -250, -16, -54, -141, -237, -154, -113, -72, -230, -124, -15, -224, -225, -8, -93, -170, -55, -242, -54, -152, -60, -180, -4, -182, -81, -228, -255, -244, -250, -25, -34, -125, -168, -210, -4, -62, -132, -237, -243, -180, -24, -150, -225, -116, -124, -147, -70, -160, -124, -111, -251, -57, -2, -164, -59, -153, -38, -49, -74, -174, -204, -22, -68, -92, -179, -107, -246, -47, -41, -9, -86, -174, -76, -21, -3, -60, -5, -28, -219, -77, -191, -134, -8, -129, -35, -21, -84, -44, -237, -48, -129, -105, -111, -42, -132, -202, -26, -140, -50, -214, -135, -227, -39, -241, -189, -4, -122, -241, -92, -221, -0, -19, -176, -103, -0, -127, -198, -183, -252, -105, -82, -73, -45, -6, -160, -98, -89, -84, -179, -221, -221, -72, -136, -129, -115, -250, -170, -165, -93, -170, -147, -105, -42, -163, -252, -5, -243, -143, -92, -15, -91, -218, -165, -134, -163, -245, -53, -112, -5, -147, -181, -78, -195, -150, -151, -69, -94, -198, -173, -53, -86, -185, -44, -170, -81, -23, -152, -67, -106, -101, -12, -92, -98, -125, -169, -78, -166, -169, -140, -50, -3, -247, -247, -119, -134, -25, -145, -12, -144, -105, -247, -195, -20, -152, -181, -251, -221, -145, -249, -177, -180, -104, -51, -48, -97, -235, -253, -177, -23, -226, -12, -144, -18, -3, -55, -104, -132, -42, -123, -193, -36, -56, -153, -214, -96, -148, -251, -49, -211, -243, -242, -62, -26, -140, -40, -6, -192, -4, -191, -15, -99, -182, -128, -37, -48, -79, -237, -59, -122, -217, -96, -210, -15, -129, -217, -165, -31, -194, -188, -84, -214, -197, -252, -214, -138, -24, -32, -37, -6, -46, -153, -1, -106, -60, -75, -10, -163, -124, -8, -243, -25, -124, -12, -83, -198, -12, -73, -1, -231, -116, -89, -134, -159, -236, -140, -92, -217, -63, -204, -185, -101, -136, -74, -155, -193, -129, -58, -207, -98, -190, -141, -177, -228, -147, -139, -98, -102, -247, -23, -48, -129, -242, -58, -224, -29, -169, -239, -160, -54, -106, -48, -192, -36, -50, -91, -190, -224, -169, -81, -10, -234, -203, -154, -121, -63, -16, -123, -201, -189, -96, -128, -54, -17, -97, -248, -127, -149, -245, -15, -155, -62, -47, -246, -15, -99, -136, -241, -134, -193, -129, -58, -107, -251, -113, -235, -62, -154, -85, -94, -176, -221, -248, -4, -142, -211, -224, -144, -177, -178, -140, -24, -43, -103, -142, -87, -171, -160, -29, -169, -216, -87, -150, -12, -243, -158, -16, -194, -93, -146, -138, -108, -6, -203, -97, -17, -67, -151, -72, -250, -173, -164, -117, -67, -8, -67, -34, -151, -36, -29, -144, -169, -239, -30, -89, -130, -201, -131, -218, -238, -244, -160, -31, -152, -92, -170, -88, -73, -55, -118, -81, -247, -171, -210, -32, -179, -241, -204, -18, -218, -38, -49, -112, -35, -45, -141, -91, -42, -195, -79, -150, -180, -130, -164, -119, -135, -16, -126, -26, -203, -197, -236, -88, -89, -210, -3, -185, -250, -74, -61, -170, -154, -160, -81, -170, -216, -28, -138, -126, -136, -71, -52, -248, -203, -46, -203, -187, -115, -129, -164, -203, -100, -182, -236, -107, -20, -73, -247, -170, -116, -59, -122, -45, -43, -95, -139, -72, -101, -248, -141, -100, -161, -227, -119, -96, -22, -213, -162, -140, -34, -111, -104, -112, -90, -221, -222, -123, -104, -167, -12, -249, -46, -104, -84, -26, -141, -128, -207, -97, -42, -229, -53, -49, -147, -241, -173, -37, -50, -64, -74, -58, -180, -36, -59, -186, -211, -86, -90, -249, -48, -255, -132, -231, -177, -37, -232, -62, -152, -4, -253, -229, -46, -250, -119, -87, -86, -136, -164, -66, -149, -142, -121, -55, -95, -238, -178, -210, -144, -20, -59, -216, -166, -22, -71, -103, -206, -163, -129, -58, -88, -112, -75, -212, -70, -80, -11, -36, -26, -61, -82, -127, -8, -76, -177, -242, -83, -204, -64, -113, -63, -190, -45, -125, -132, -46, -245, -5, -39, -219, -209, -83, -0, -156, -138, -5, -184, -238, -131, -249, -213, -191, -72, -36, -147, -119, -141, -254, -229, -25, -126, -98, -74, -255, -128, -77, -137, -120, -241, -2, -135, -248, -123, -235, -8, -129, -209, -64, -29, -76, -11, -120, -15, -150, -0, -59, -26, -167, -153, -4, -18, -141, -30, -77, -127, -8, -138, -87, -11, -73, -47, -56, -21, -249, -250, -138, -218, -109, -90, -95, -9, -93, -158, -225, -119, -239, -178, -221, -128, -237, -199, -52, -141, -138, -64, -29, -108, -201, -184, -191, -51, -242, -119, -128, -101, -155, -182, -219, -169, -176, -107, -163, -71, -164, -206, -126, -41, -70, -122, -193, -0, -71, -210, -239, -157, -185, -26, -0, -120, -19, -150, -243, -32, -57, -197, -111, -214, -43, -120, -182, -209, -67, -182, -11, -70, -95, -247, -192, -29, -225, -56, -92, -210, -33, -178, -93, -73, -158, -144, -229, -228, -27, -49, -192, -100, -158, -3, -36, -221, -46, -233, -53, -153, -160, -89, -187, -146, -70, -70, -143, -145, -134, -30, -141, -0, -61, -79, -162, -221, -20, -216, -74, -98, -18, -230, -86, -215, -60, -7, -51, -13, -141, -30, -253, -6, -245, -157, -51, -187, -74, -38, -229, -245, -245, -60, -137, -118, -83, -96, -78, -60, -155, -54, -45, -159, -21, -42, -30, -151, -180, -49, -150, -219, -174, -112, -99, -167, -130, -78, -52, -94, -163, -250, -11, -78, -205, -36, -242, -93, -89, -14, -222, -53, -36, -45, -77, -220, -10, -217, -11, -125, -65, -146, -60, -132, -37, -153, -56, -20, -216, -147, -72, -242, -199, -58, -72, -21, -62, -67, -8, -219, -68, -242, -17, -55, -106, -48, -201, -232, -225, -180, -201, -155, -75, -37, -180, -155, -204, -0, -137, -245, -181, -173, -47, -72, -158, -82, -176, -112, -181, -89, -152, -175, -193, -184, -46, -159, -35, -137, -1, -134, -5, -46, -9, -175, -236, -12, -240, -28, -112, -68, -1, -221, -170, -192, -245, -152, -110, -225, -62, -96, -255, -8, -77, -7, -165, -105, -221, -72, -183, -142, -181, -173, -47, -168, -195, -0, -151, -96, -145, -193, -151, -23, -140, -78, -117, -219, -237, -139, -3, -106, -109, -164, -14, -249, -152, -139, -210, -165, -88, -36, -238, -22, -192, -187, -35, -52, -144, -150, -214, -173, -85, -235, -88, -13, -134, -74, -102, -128, -12, -205, -130, -152, -71, -111, -227, -47, -216, -219, -61, -154, -68, -79, -169, -190, -33, -245, -197, -57, -237, -12, -96, -231, -138, -250, -96, -112, -86, -175, -253, -137, -103, -39, -155, -157, -198, -206, -207, -63, -77, -119, -83, -79, -219, -12, -181, -16, -230, -15, -240, -44, -166, -8, -186, -22, -248, -65, -23, -245, -65, -13, -79, -41, -170, -125, -37, -219, -201, -75, -84, -231, -197, -249, -67, -140, -175, -168, -47, -207, -0, -69, -105, -221, -166, -147, -9, -65, -195, -28, -71, -186, -201, -98, -214, -54, -67, -157, -137, -169, -208, -215, -240, -247, -114, -15, -5, -89, -66, -18, -235, -131, -4, -79, -169, -204, -253, -42, -95, -201, -234, -188, -68, -41, -92, -82, -231, -197, -213, -96, -128, -148, -180, -110, -211, -128, -236, -246, -40, -221, -166, -177, -107, -155, -161, -166, -228, -126, -176, -131, -40, -200, -18, -146, -88, -31, -12, -94, -126, -70, -61, -165, -186, -69, -158, -91, -178, -38, -204, -89, -5, -101, -146, -236, -212, -12, -172, -34, -254, -140, -185, -92, -149, -249, -3, -252, -65, -210, -51, -178, -188, -185, -23, -73, -138, -249, -184, -223, -39, -219, -242, -165, -131, -85, -84, -226, -56, -82, -53, -36, -170, -125, -115, -235, -91, -101, -90, -194, -14, -158, -145, -45, -73, -219, -66, -52, -91, -56, -9, -70, -188, -50, -154, -65, -15, -29, -66, -88, -63, -132, -112, -91, -8, -97, -98, -8, -161, -200, -175, -44, -233, -197, -133, -16, -58, -46, -214, -219, -134, -16, -230, -13, -33, -148, -229, -34, -216, -222, -105, -198, -133, -16, -78, -8, -33, -196, -50, -127, -156, -39, -233, -176, -206, -212, -35, -233, -147, -178, -77, -160, -138, -112, -129, -164, -159, -73, -42, -218, -233, -35, -153, -161, -18, -231, -207, -71, -37, -45, -151, -57, -31, -39, -115, -254, -232, -6, -41, -158, -82, -79, -200, -156, -104, -86, -148, -169, -240, -99, -106, -234, -20, -26, -137, -180, -88, -185, -84, -59, -245, -252, -62, -140, -149, -234, -165, -243, -50, -64, -9, -93, -178, -117, -44, -5, -36, -154, -91, -157, -182, -114, -254, -4, -190, -128, -173, -96, -58, -66, -219, -100, -42, -194, -215, -43, -250, -135, -183, -187, -38, -176, -22, -240, -32, -240, -153, -138, -50, -149, -70, -188, -66, -26, -210, -99, -229, -82, -237, -212, -251, -49, -32, -20, -205, -78, -182, -156, -240, -236, -93, -129, -244, -229, -93, -219, -12, -53, -63, -38, -8, -62, -225, -245, -157, -22, -107, -183, -70, -125, -175, -99, -91, -249, -150, -102, -11, -39, -33, -114, -41, -133, -70, -164, -7, -85, -38, -189, -56, -10, -208, -232, -109, -212, -0, -195, -164, -47, -24, -46, -144, -96, -196, -75, -161, -17, -137, -177, -114, -35, -29, -140, -112, -125, -65, -219, -32, -193, -136, -87, -70, -147, -223, -147, -38, -101, -231, -142, -145, -142, -182, -189, -105, -251, -226, -158, -221, -5, -82, -140, -120, -213, -52, -36, -198, -202, -245, -27, -62, -4, -127, -25, -91, -103, -191, -72, -197, -14, -89, -140, -112, -125, -65, -219, -32, -193, -136, -151, -66, -35, -18, -99, -229, -250, -13, -224, -40, -108, -101, -50, -1, -75, -56, -89, -149, -76, -42, -105, -149, -82, -163, -253, -70, -12, -69, -130, -169, -25, -115, -72, -189, -39, -161, -174, -9, -254, -129, -150, -230, -17, -232, -26, -212, -216, -185, -131, -132, -240, -112, -224, -91, -153, -227, -111, -84, -220, -31, -162, -253, -243, -235, -183, -147, -176, -33, -99, -134, -62, -121, -121, -151, -88, -95, -35, -134, -34, -205, -212, -188, -31, -80, -169, -43, -192, -18, -64, -156, -76, -127, -54, -191, -170, -6, -105, -89, -179, -182, -0, -206, -247, -227, -205, -128, -239, -69, -104, -190, -207, -64, -98, -165, -243, -137, -120, -182, -96, -75, -160, -104, -218, -213, -130, -190, -13, -155, -190, -160, -87, -240, -15, -109, -124, -63, -219, -236, -26, -152, -143, -218, -134, -249, -227, -28, -205, -134, -157, -57, -221, -143, -127, -31, -161, -121, -53, -59, -4, -247, -27, -77, -24, -138, -244, -24, -139, -13, -128, -202, -116, -183, -206, -0, -133, -155, -89, -116, -131, -70, -95, -6, -105, -105, -216, -230, -41, -56, -46, -163, -139, -169, -139, -31, -80, -205, -45, -209, -219, -68, -8, -129, -16, -194, -151, -66, -8, -139, -251, -223, -137, -37, -241, -124, -29, -164, -169, -94, -165, -93, -53, -120, -197, -50, -8, -152, -95, -193, -129, -50, -27, -77, -105, -254, -162, -146, -58, -90, -221, -158, -166, -142, -198, -112, -171, -204, -20, -48, -123, -58, -200, -209, -124, -31, -216, -210, -143, -207, -39, -226, -64, -129, -69, -20, -61, -142, -185, -91, -173, -74, -65, -86, -210, -145, -10, -10, -84, -175, -192, -58, -152, -215, -210, -129, -37, -101, -193, -164, -247, -198, -35, -32, -169, -219, -211, -144, -184, -220, -162, -70, -118, -45, -50, -187, -112, -17, -17, -22, -169, -16, -18, -253, -250, -60, -152, -38, -110, -42, -166, -208, -24, -178, -153, -196, -72, -3, -105, -234, -217, -75, -171, -158, -5, -179, -104, -30, -139, -41, -233, -150, -232, -93, -143, -149, -190, -220, -98, -4, -106, -12, -201, -8, -138, -20, -8, -141, -62, -143, -79, -194, -86, -57, -189, -203, -185, -171, -100, -245, -236, -244, -148, -121, -29, -203, -23, -12, -176, -69, -131, -126, -108, -130, -173, -253, -241, -81, -180, -216, -199, -144, -196, -229, -22, -137, -217, -181, -250, -9, -127, -200, -45, -242, -199, -57, -154, -77, -129, -5, -48, -199, -147, -194, -36, -74, -88, -142, -223, -117, -75, -238, -167, -216, -223, -83, -212, -179, -47, -146, -152, -151, -209, -127, -192, -241, -41, -180, -145, -178, -99, -189, -124, -212, -16, -151, -21, -2, -87, -151, -84, -232, -114, -148, -193, -100, -89, -86, -139, -87, -178, -127, -77, -58, -215, -34, -158, -245, -191, -252, -241, -108, -132, -16, -110, -10, -33, -188, -44, -105, -99, -21, -36, -190, -192, -172, -109, -71, -75, -90, -172, -164, -173, -20, -1, -47, -69, -61, -123, -147, -164, -99, -48, -185, -102, -107, -224, -240, -146, -54, -123, -15, -18, -151, -91, -140, -64, -141, -33, -150, -24, -105, -217, -252, -113, -132, -110, -83, -204, -89, -51, -186, -247, -31, -3, -123, -238, -60, -133, -201, -28, -165, -31, -4, -197, -2, -94, -138, -122, -118, -101, -44, -170, -231, -37, -76, -183, -80, -168, -134, -247, -169, -235, -44, -26, -200, -1, -85, -35, -64, -150, -240, -30, -224, -184, -196, -74, -187, -218, -235, -151, -8, -34, -52, -233, -243, -87, -90, -155, -219, -96, -49, -244, -11, -39, -244, -173, -208, -157, -155, -97, -200, -28, -138, -233, -11, -254, -66, -131, -152, -196, -58, -12, -208, -183, -229, -150, -119, -104, -208, -190, -194, -5, -116, -105, -157, -79, -107, -243, -101, -204, -148, -59, -201, -255, -162, -158, -74, -9, -12, -80, -41, -224, -141, -36, -84, -189, -195, -172, -226, -229, -44, -153, -99, -227, -143, -37, -45, -33, -233, -247, -254, -215, -43, -188, -222, -79, -217, -33, -132, -208, -86, -82, -169, -141, -36, -237, -229, -123, -249, -172, -221, -82, -157, -195, -134, -217, -66, -96, -8, -97, -86, -8, -225, -216, -16, -194, -10, -178, -132, -77, -61, -223, -233, -123, -14, -69, -227, -32, -218, -57, -6, -192, -210, -68, -182, -119, -105, -177, -254, -74, -25, -192, -233, -42, -167, -0, -90, -206, -8, -134, -109, -206, -176, -101, -201, -253, -228, -32, -218, -132, -182, -160, -197, -192, -216, -130, -54, -234, -77, -163, -192, -95, -49, -19, -232, -39, -11, -238, -39, -101, -9, -199, -76, -161, -215, -3, -167, -71, -238, -181, -38, -3, -144, -184, -239, -79, -42, -48, -111, -222, -51, -129, -69, -128, -229, -170, -75, -116, -213, -86, -33, -3, -84, -49, -54, -166, -71, -184, -25, -216, -190, -164, -254, -77, -48, -33, -29, -103, -216, -238, -130, -77, -169, -145, -37, -28, -183, -153, -3, -255, -136, -220, -75, -226, -252, -218, -220, -91, -94, -87, -210, -22, -114, -152, -13, -99, -18, -230, -149, -219, -120, -107, -218, -196, -62, -149, -49, -64, -41, -99, -99, -91, -218, -126, -25, -75, -233, -51, -242, -224, -35, -197, -117, -196, -13, -69, -173, -48, -0, -17, -148, -212, -85, -26, -59, -55, -28, -72, -125, -15, -37, -229, -199, -151, -61, -115, -207, -224, -29, -239, -54, -244, -185, -235, -41, -32, -181, -158, -145, -138, -34, -6, -32, -81, -7, -50, -34, -25, -128, -52, -93, -121, -229, -151, -75, -194, -252, -149, -242, -5, -213, -25, -37, -218, -0, -53, -236, -239, -101, -253, -175, -98, -254, -12, -205, -235, -192, -129, -64, -163, -101, -110, -62, -89, -244, -78, -88, -182, -203, -87, -129, -235, -155, -84, -168, -4, -93, -121, -136, -32, -66, -115, -115, -8, -97, -5, -191, -189, -124, -8, -97, -200, -198, -201, -53, -176, -179, -6, -187, -187, -247, -18, -41, -1, -182, -173, -32, -132, -48, -69, -210, -30, -50, -29, -78, -101, -36, -114, -229, -71, -128, -237, -85, -123, -18, -182, -9, -65, -97, -182, -201, -178, -17, -32, -71, -215, -122, -194, -201, -72, -63, -170, -70, -146, -202, -81, -194, -233, -170, -178, -143, -125, -17, -91, -33, -188, -132, -173, -148, -186, -86, -2, -181, -48, -2, -44, -129, -153, -231, -143, -37, -109, -251, -219, -78, -220, -226, -154, -157, -107, -121, -129, -104, -5, -73, -215, -132, -16, -166, -135, -16, -158, -80, -3, -208, -255, -132, -147, -93, -127, -221, -164, -101, -31, -123, -70, -22, -145, -252, -14, -89, -100, -241, -144, -200, -228, -126, -79, -55, -146, -214, -145, -237, -168, -126, -86, -8, -225, -153, -42, -226, -16, -194, -164, -206, -223, -144, -155, -88, -98, -35, -112, -75, -88, -89, -69, -101, -35, -0, -125, -212, -149, -167, -124, -221, -189, -248, -81, -48, -7, -214, -162, -93, -77, -146, -133, -210, -22, -70, -128, -174, -133, -192, -172, -42, -120, -23, -63, -220, -221, -213, -193, -77, -177, -145, -164, -175, -135, -16, -238, -84, -129, -93, -29, -248, -33, -112, -35, -22, -199, -119, -66, -228, -254, -246, -126, -255, -111, -180, -227, -14, -93, -58, -74, -52, -96, -146, -247, -72, -122, -168, -224, -222, -235, -41, -126, -18, -12, -56, -210, -118, -19, -101, -212, -110, -144, -106, -217, -151, -157, -74, -71, -194, -46, -91, -192, -124, -254, -127, -94, -226, -249, -128, -110, -195, -20, -29, -75, -2, -255, -172, -232, -71, -233, -23, -87, -99, -148, -72, -250, -114, -125, -100, -123, -30, -216, -175, -97, -91, -203, -96, -94, -73, -39, -97, -171, -155, -104, -230, -175, -170, -17, -0, -155, -255, -191, -65, -133, -207, -66, -45, -164, -50, -64, -69, -29, -41, -206, -16, -159, -192, -66, -157, -174, -35, -238, -80, -49, -37, -118, -92, -208, -223, -210, -47, -183, -6, -3, -164, -102, -43, -189, -25, -248, -97, -23, -253, -153, -142, -169, -113, -175, -39, -18, -43, -145, -161, -171, -98, -128, -23, -48, -231, -150, -230, -249, -129, -11, -30, -160, -231, -217, -41, -49, -149, -236, -155, -253, -75, -24, -178, -124, -193, -166, -134, -37, -48, -245, -237, -109, -93, -182, -85, -249, -117, -215, -100, -128, -153, -148, -251, -18, -116, -173, -152, -162, -109, -29, -126, -141, -134, -251, -197, -0, -231, -96, -6, -167, -223, -19, -223, -36, -114, -107, -76, -6, -184, -145, -76, -166, -172, -134, -109, -165, -142, -18, -165, -52, -53, -218, -234, -169, -117, -175, -167, -232, -23, -3, -140, -52, -212, -249, -114, -49, -69, -217, -222, -37, -245, -204, -81, -12, -208, -52, -52, -44, -201, -178, -54, -135, -33, -73, -122, -87, -181, -228, -61, -95, -183, -83, -192, -136, -7, -213, -89, -41, -91, -217, -89, -188, -162, -15, -251, -249, -124, -220, -181, -16, -212, -214, -151, -91, -103, -42, -1, -62, -6, -252, -185, -219, -54, -11, -234, -190, -24, -184, -164, -23, -117, -167, -52, -222, -218, -206, -226, -37, -109, -28, -136, -45, -55, -95, -109, -145, -1, -250, -102, -85, -196, -18, -99, -79, -163, -100, -163, -7, -239, -199, -195, -192, -123, -234, -220, -243, -251, -189, -241, -232, -162, -69, -87, -109, -74, -60, -94, -170, -166, -24, -103, -176, -85, -48, -75, -216, -16, -6, -192, -118, -61, -123, -8, -243, -2, -62, -51, -161, -47, -201, -95, -110, -27, -240, -175, -191, -52, -49, -68, -83, -6, -160, -194, -163, -171, -107, -80, -189, -62, -77, -181, -101, -23, -122, -188, -144, -232, -188, -225, -109, -196, -24, -96, -77, -175, -127, -93, -224, -209, -212, -103, -235, -23, -176, -192, -208, -115, -170, -41, -251, -136, -178, -47, -50, -71, -151, -106, -167, -46, -165, -105, -3, -69, -12, -224, -247, -174, -195, -242, -23, -124, -164, -151, -125, -104, -2, -204, -234, -250, -209, -4, -58, -40, -214, -184, -22, -222, -171, -131, -236, -23, -118, -128, -164, -159, -43, -109, -227, -230, -86, -80, -244, -16, -109, -60, -92, -8, -97, -43, -73, -235, -75, -58, -173, -155, -122, -98, -160, -194, -233, -195, -251, -191, -62, -166, -210, -126, -58, -82, -197, -210, -50, -235, -226, -176, -99, -118, -96, -72, -8, -97, -150, -164, -163, -74, -104, -231, -24, -0, -43, -134, -16, -30, -149, -25, -163, -26, -167, -108, -47, -65, -138, -211, -199, -143, -37, -157, -44, -41, -230, -21, -20, -100, -73, -183, -135, -29, -35, -198, -65, -178, -101, -252, -10, -184, -79, -210, -197, -138, -4, -111, -96, -18, -255, -195, -46, -40, -78, -136, -220, -47, -253, -194, -19, -179, -170, -255, -44, -132, -240, -235, -16, -66, -76, -216, -251, -183, -164, -158, -239, -108, -78, -66, -130, -173, -178, -20, -238, -115, -44, -66, -8, -27, -87, -144, -156, -39, -105, -127, -73, -79, -75, -186, -66, -150, -218, -61, -139, -54, -220, -186, -162, -123, -47, -59, -110, -147, -57, -150, -244, -26, -209, -80, -249, -44, -230, -74, -6, -72, -192, -24, -217, -143, -60, -83, -17, -205, -94, -8, -33, -187, -55, -112, -211, -31, -170, -76, -155, -120, -165, -164, -126, -164, -154, -171, -100, -128, -236, -222, -193, -147, -128, -189, -122, -222, -165, -22, -225, -14, -163, -77, -172, -133, -31, -151, -244, -11, -73, -87, -169, -32, -190, -175, -45, -41, -187, -0, -23, -72, -90, -145, -18, -115, -112, -75, -72, -103, -0, -89, -186, -182, -170, -117, -247, -38, -146, -110, -240, -211, -235, -138, -214, -248, -35, -29, -33, -132, -203, -67, -8, -111, -247, -29, -74, -174, -168, -91, -30, -184, -149, -72, -196, -83, -141, -246, -159, -147, -116, -156, -164, -83, -154, -214, -145, -216, -206, -86, -77, -125, -59, -27, -131, -26, -182, -236, -94, -46, -3, -187, -69, -197, -26, -124, -34, -112, -107, -147, -178, -13, -250, -176, -89, -183, -245, -164, -54, -54, -29, -88, -186, -47, -141, -205, -1, -24, -78, -38, -196, -92, -225, -198, -99, -187, -169, -22, -186, -231, -183, -129, -172, -16, -56, -70, -115, -192, -254, -0, -48, -160, -167, -207, -7, -148, -0, -127, -146, -116, -73, -8, -225, -59, -125, -239, -88, -187, -120, -80, -210, -235, -146, -142, -239, -219, -16, -142, -5, -60, -12, -91, -74, -214, -84, -96, -134, -144, -29, -178, -140, -144, -185, -183, -9, -102, -101, -91, -40, -114, -111, -54, -18, -219, -25, -246, -105, -168, -31, -200, -239, -24, -18, -29, -1, -24, -65, -14, -32, -238, -172, -17, -219, -86, -78, -33, -132, -155, -37, -61, -37, -105, -136, -199, -174, -99, -130, -122, -31, -26, -150, -12, -103, -178, -174, -77, -207, -221, -48, -107, -18, -3, -168, -100, -15, -190, -178, -47, -203, -231, -178, -31, -3, -209, -31, -172, -71, -248, -179, -236, -135, -142, -225, -181, -94, -230, -37, -42, -250, -65, -49, -155, -192, -196, -94, -181, -219, -13, -146, -100, -128, -16, -194, -78, -37, -117, -148, -77, -27, -231, -200, -18, -77, -237, -89, -191, -107, -141, -113, -155, -164, -227, -187, -173, -36, -22, -176, -218, -5, -222, -144, -134, -238, -250, -57, -18, -208, -181, -16, -24, -141, -51, -27, -184, -183, -143, -36, -1, -63, -174, -223, -181, -198, -120, -70, -150, -237, -108, -196, -32, -132, -240, -238, -58, -244, -190, -196, -36, -132, -176, -97, -238, -250, -169, -146, -246, -13, -33, -188, -189, -173, -190, -205, -113, -171, -128, -4, -228, -183, -182, -157, -19, -81, -212, -255, -117, -36, -253, -178, -205, -134, -178, -230, -224, -57, -253, -165, -117, -176, -148, -70, -136, -173, -189, -10, -69, -239, -188, -100, -196, -120, -151, -164, -99, -218, -236, -195, -220, -104, -14, -126, -135, -76, -14, -72, -134, -11, -111, -255, -47, -114, -125, -68, -9, -111, -158, -48, -163, -219, -13, -169, -7, -161, -47, -12, -80, -177, -115, -120, -219, -216, -70, -102, -228, -169, -131, -55, -36, -197, -182, -100, -107, -69, -120, -115, -219, -65, -97, -144, -235, -112, -98, -142, -51, -7, -251, -50, -43, -154, -116, -194, -173, -107, -43, -202, -150, -173, -117, -240, -134, -164, -151, -242, -23, -235, -10, -111, -37, -24, -177, -211, -235, -28, -199, -0, -146, -94, -46, -185, -247, -37, -73, -159, -117, -107, -91, -12, -111, -2, -222, -28, -209, -5, -204, -82, -124, -4, -104, -5, -69, -140, -228, -186, -147, -5, -134, -115, -191, -133, -57, -142, -1, -202, -132, -213, -16, -194, -206, -21, -197, -255, -216, -33, -205, -93, -143, -142, -0, -255, -23, -48, -199, -49, -64, -83, -84, -172, -114, -138, -100, -128, -57, -2, -221, -172, -224, -230, -198, -85, -64, -19, -204, -82, -100, -4, -0, -78, -165, -96, -71, -180, -185, -5, -255, -103, -70, -128, -50, -132, -16, -22, -45, -184, -213, -186, -226, -101, -20, -35, -16, -20, -196, -252, -187, -103, -211, -26, -53, -234, -105, -197, -186, -215, -79, -140, -142, -0, -134, -34, -141, -92, -173, -108, -105, -115, -145, -54, -117, -20, -163, -24, -197, -40, -70, -49, -138, -81, -140, -98, -20, -163, -24, -197, -40, -70, -49, -138, -81, -140, -98, -20, -163, -24, -197, -40, -70, -49, -138, -81, -204, -37, -248, -255, -129, -51, -157, -250, -111, -139, -157, -153, -0, -0, -0, -0, -73, -69, -78, -68, -174, -66, -96, -130, -}; -/* clang-format on */ diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index c3d84aeda2..64b43f82c6 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -1133,7 +1133,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { Vector3 normal_left, normal_right; normal_left = Vector3(-size.y, size.x * left_to_right, 0.0); - normal_right = Vector3(size.y, size.x * left_to_right, 0.0); + normal_right = Vector3(size.y, size.x * (1.0 - left_to_right), 0.0); normal_left.normalize(); normal_right.normalize(); diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index f2751b7604..2414704a57 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -978,7 +978,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) } wf->store_32(0); //string table size, will not be in use - size_t ext_res_count_pos = wf->get_position(); + uint64_t ext_res_count_pos = wf->get_position(); wf->store_32(0); //zero ext resources, still parsing them @@ -1041,7 +1041,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) //now, save resources to a separate file, for now - size_t sub_res_count_pos = wf->get_position(); + uint64_t sub_res_count_pos = wf->get_position(); wf->store_32(0); //zero sub resources, still parsing them String temp_file = p_path + ".temp"; @@ -1050,8 +1050,8 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) return ERR_CANT_OPEN; } - Vector<size_t> local_offsets; - Vector<size_t> local_pointers_pos; + Vector<uint64_t> local_offsets; + Vector<uint64_t> local_pointers_pos; while (next_tag.name == "sub_resource" || next_tag.name == "resource") { String type; @@ -1089,7 +1089,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) wf->store_64(0); //temp local offset bs_save_unicode_string(wf2, type); - size_t propcount_ofs = wf2->get_position(); + uint64_t propcount_ofs = wf2->get_position(); wf2->store_32(0); int prop_count = 0; @@ -1159,7 +1159,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) local_offsets.push_back(wf2->get_position()); bs_save_unicode_string(wf2, "PackedScene"); - size_t propcount_ofs = wf2->get_position(); + uint64_t propcount_ofs = wf2->get_position(); wf2->store_32(0); int prop_count = 0; @@ -1185,7 +1185,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) wf2->close(); - size_t offset_from = wf->get_position(); + uint64_t offset_from = wf->get_position(); wf->seek(sub_res_count_pos); //plus one because the saved one wf->store_32(local_offsets.size()); diff --git a/scene/resources/text_file.cpp b/scene/resources/text_file.cpp index cf07003720..b71909b6bb 100644 --- a/scene/resources/text_file.cpp +++ b/scene/resources/text_file.cpp @@ -55,10 +55,10 @@ Error TextFile::load_text(const String &p_path) { ERR_FAIL_COND_V_MSG(err, err, "Cannot open TextFile '" + p_path + "'."); - int len = f->get_len(); + uint64_t len = f->get_len(); sourcef.resize(len + 1); uint8_t *w = sourcef.ptrw(); - int r = f->get_buffer(w, len); + uint64_t r = f->get_buffer(w, len); f->close(); memdelete(f); ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 624eae0411..1b2176d30a 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -335,7 +335,7 @@ Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit //mipmaps need to be read independently, they will be later combined Vector<Ref<Image>> mipmap_images; - int total_size = 0; + uint64_t total_size = 0; bool first = true; diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index e8b203417e..786a96501a 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -36,11 +36,11 @@ void Theme::_emit_theme_changed() { emit_changed(); } -Vector<String> Theme::_get_icon_list(const String &p_node_type) const { +Vector<String> Theme::_get_icon_list(const String &p_theme_type) const { Vector<String> ilret; List<StringName> il; - get_icon_list(p_node_type, &il); + get_icon_list(p_theme_type, &il); ilret.resize(il.size()); int i = 0; @@ -66,11 +66,11 @@ Vector<String> Theme::_get_icon_type_list() const { return ilret; } -Vector<String> Theme::_get_stylebox_list(const String &p_node_type) const { +Vector<String> Theme::_get_stylebox_list(const String &p_theme_type) const { Vector<String> ilret; List<StringName> il; - get_stylebox_list(p_node_type, &il); + get_stylebox_list(p_theme_type, &il); ilret.resize(il.size()); int i = 0; @@ -96,11 +96,11 @@ Vector<String> Theme::_get_stylebox_type_list() const { return ilret; } -Vector<String> Theme::_get_font_list(const String &p_node_type) const { +Vector<String> Theme::_get_font_list(const String &p_theme_type) const { Vector<String> ilret; List<StringName> il; - get_font_list(p_node_type, &il); + get_font_list(p_theme_type, &il); ilret.resize(il.size()); int i = 0; @@ -126,11 +126,11 @@ Vector<String> Theme::_get_font_type_list() const { return ilret; } -Vector<String> Theme::_get_font_size_list(const String &p_node_type) const { +Vector<String> Theme::_get_font_size_list(const String &p_theme_type) const { Vector<String> ilret; List<StringName> il; - get_font_size_list(p_node_type, &il); + get_font_size_list(p_theme_type, &il); ilret.resize(il.size()); int i = 0; @@ -156,11 +156,11 @@ Vector<String> Theme::_get_font_size_type_list() const { return ilret; } -Vector<String> Theme::_get_color_list(const String &p_node_type) const { +Vector<String> Theme::_get_color_list(const String &p_theme_type) const { Vector<String> ilret; List<StringName> il; - get_color_list(p_node_type, &il); + get_color_list(p_theme_type, &il); ilret.resize(il.size()); int i = 0; @@ -186,11 +186,11 @@ Vector<String> Theme::_get_color_type_list() const { return ilret; } -Vector<String> Theme::_get_constant_list(const String &p_node_type) const { +Vector<String> Theme::_get_constant_list(const String &p_theme_type) const { Vector<String> ilret; List<StringName> il; - get_constant_list(p_node_type, &il); + get_constant_list(p_theme_type, &il); ilret.resize(il.size()); int i = 0; @@ -216,20 +216,20 @@ Vector<String> Theme::_get_constant_type_list() const { return ilret; } -Vector<String> Theme::_get_theme_item_list(DataType p_data_type, const String &p_node_type) const { +Vector<String> Theme::_get_theme_item_list(DataType p_data_type, const String &p_theme_type) const { switch (p_data_type) { case DATA_TYPE_COLOR: - return _get_color_list(p_node_type); + return _get_color_list(p_theme_type); case DATA_TYPE_CONSTANT: - return _get_constant_list(p_node_type); + return _get_constant_list(p_theme_type); case DATA_TYPE_FONT: - return _get_font_list(p_node_type); + return _get_font_list(p_theme_type); case DATA_TYPE_FONT_SIZE: - return _get_font_size_list(p_node_type); + return _get_font_size_list(p_theme_type); case DATA_TYPE_ICON: - return _get_icon_list(p_node_type); + return _get_icon_list(p_theme_type); case DATA_TYPE_STYLEBOX: - return _get_stylebox_list(p_node_type); + return _get_stylebox_list(p_theme_type); case DATA_TYPE_MAX: break; // Can't happen, but silences warning. } @@ -278,19 +278,19 @@ bool Theme::_set(const StringName &p_name, const Variant &p_value) { if (sname.find("/") != -1) { String type = sname.get_slicec('/', 1); - String node_type = sname.get_slicec('/', 0); + String theme_type = sname.get_slicec('/', 0); String name = sname.get_slicec('/', 2); if (type == "icons") { - set_icon(name, node_type, p_value); + set_icon(name, theme_type, p_value); } else if (type == "styles") { - set_stylebox(name, node_type, p_value); + set_stylebox(name, theme_type, p_value); } else if (type == "fonts") { - set_font(name, node_type, p_value); + set_font(name, theme_type, p_value); } else if (type == "colors") { - set_color(name, node_type, p_value); + set_color(name, theme_type, p_value); } else if (type == "constants") { - set_constant(name, node_type, p_value); + set_constant(name, theme_type, p_value); } else { return false; } @@ -306,31 +306,31 @@ bool Theme::_get(const StringName &p_name, Variant &r_ret) const { if (sname.find("/") != -1) { String type = sname.get_slicec('/', 1); - String node_type = sname.get_slicec('/', 0); + String theme_type = sname.get_slicec('/', 0); String name = sname.get_slicec('/', 2); if (type == "icons") { - if (!has_icon(name, node_type)) { + if (!has_icon(name, theme_type)) { r_ret = Ref<Texture2D>(); } else { - r_ret = get_icon(name, node_type); + r_ret = get_icon(name, theme_type); } } else if (type == "styles") { - if (!has_stylebox(name, node_type)) { + if (!has_stylebox(name, theme_type)) { r_ret = Ref<StyleBox>(); } else { - r_ret = get_stylebox(name, node_type); + r_ret = get_stylebox(name, theme_type); } } else if (type == "fonts") { - if (!has_font(name, node_type)) { + if (!has_font(name, theme_type)) { r_ret = Ref<Font>(); } else { - r_ret = get_font(name, node_type); + r_ret = get_font(name, theme_type); } } else if (type == "colors") { - r_ret = get_color(name, node_type); + r_ret = get_color(name, theme_type); } else if (type == "constants") { - r_ret = get_constant(name, node_type); + r_ret = get_constant(name, theme_type); } else { return false; } @@ -477,17 +477,17 @@ void Theme::set_default_font_size(int p_font_size) { default_font_size = p_font_size; } -void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture2D> &p_icon) { - bool new_value = !icon_map.has(p_node_type) || !icon_map[p_node_type].has(p_name); +void Theme::set_icon(const StringName &p_name, const StringName &p_theme_type, const Ref<Texture2D> &p_icon) { + bool new_value = !icon_map.has(p_theme_type) || !icon_map[p_theme_type].has(p_name); - if (icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) { - icon_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); + if (icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) { + icon_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } - icon_map[p_node_type][p_name] = p_icon; + icon_map[p_theme_type][p_name] = p_icon; if (p_icon.is_valid()) { - icon_map[p_node_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); + icon_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); } if (new_value) { @@ -496,64 +496,64 @@ void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, co } } -Ref<Texture2D> Theme::get_icon(const StringName &p_name, const StringName &p_node_type) const { - if (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) { - return icon_map[p_node_type][p_name]; +Ref<Texture2D> Theme::get_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) { + return icon_map[p_theme_type][p_name]; } else { return default_icon; } } -bool Theme::has_icon(const StringName &p_name, const StringName &p_node_type) const { - return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()); +bool Theme::has_icon(const StringName &p_name, const StringName &p_theme_type) const { + return (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()); } -bool Theme::has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const { - return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name)); +bool Theme::has_icon_nocheck(const StringName &p_name, const StringName &p_theme_type) const { + return (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name)); } -void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot rename the icon '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(icon_map[p_node_type].has(p_name), "Cannot rename the icon '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); - ERR_FAIL_COND_MSG(!icon_map[p_node_type].has(p_old_name), "Cannot rename the icon '" + String(p_old_name) + "' because it does not exist."); +void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!icon_map.has(p_theme_type), "Cannot rename the icon '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(icon_map[p_theme_type].has(p_name), "Cannot rename the icon '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!icon_map[p_theme_type].has(p_old_name), "Cannot rename the icon '" + String(p_old_name) + "' because it does not exist."); - icon_map[p_node_type][p_name] = icon_map[p_node_type][p_old_name]; - icon_map[p_node_type].erase(p_old_name); + icon_map[p_theme_type][p_name] = icon_map[p_theme_type][p_old_name]; + icon_map[p_theme_type].erase(p_old_name); notify_property_list_changed(); emit_changed(); } -void Theme::clear_icon(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot clear the icon '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(!icon_map[p_node_type].has(p_name), "Cannot clear the icon '" + String(p_name) + "' because it does not exist."); +void Theme::clear_icon(const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!icon_map.has(p_theme_type), "Cannot clear the icon '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!icon_map[p_theme_type].has(p_name), "Cannot clear the icon '" + String(p_name) + "' because it does not exist."); - if (icon_map[p_node_type][p_name].is_valid()) { - icon_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); + if (icon_map[p_theme_type][p_name].is_valid()) { + icon_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } - icon_map[p_node_type].erase(p_name); + icon_map[p_theme_type].erase(p_name); notify_property_list_changed(); emit_changed(); } -void Theme::get_icon_list(StringName p_node_type, List<StringName> *p_list) const { +void Theme::get_icon_list(StringName p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - if (!icon_map.has(p_node_type)) { + if (!icon_map.has(p_theme_type)) { return; } const StringName *key = nullptr; - while ((key = icon_map[p_node_type].next(key))) { + while ((key = icon_map[p_theme_type].next(key))) { p_list->push_back(*key); } } -void Theme::add_icon_type(const StringName &p_node_type) { - icon_map[p_node_type] = HashMap<StringName, Ref<Texture2D>>(); +void Theme::add_icon_type(const StringName &p_theme_type) { + icon_map[p_theme_type] = HashMap<StringName, Ref<Texture2D>>(); } void Theme::get_icon_type_list(List<StringName> *p_list) const { @@ -565,17 +565,17 @@ void Theme::get_icon_type_list(List<StringName> *p_list) const { } } -void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style) { - bool new_value = !style_map.has(p_node_type) || !style_map[p_node_type].has(p_name); +void Theme::set_stylebox(const StringName &p_name, const StringName &p_theme_type, const Ref<StyleBox> &p_style) { + bool new_value = !style_map.has(p_theme_type) || !style_map[p_theme_type].has(p_name); - if (style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()) { - style_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); + if (style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) { + style_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } - style_map[p_node_type][p_name] = p_style; + style_map[p_theme_type][p_name] = p_style; if (p_style.is_valid()) { - style_map[p_node_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); + style_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); } if (new_value) { @@ -584,64 +584,64 @@ void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type emit_changed(); } -Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_node_type) const { - if (style_map.has(p_node_type) && style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()) { - return style_map[p_node_type][p_name]; +Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) { + return style_map[p_theme_type][p_name]; } else { return default_style; } } -bool Theme::has_stylebox(const StringName &p_name, const StringName &p_node_type) const { - return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()); +bool Theme::has_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + return (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()); } -bool Theme::has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const { - return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name)); +bool Theme::has_stylebox_nocheck(const StringName &p_name, const StringName &p_theme_type) const { + return (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name)); } -void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot rename the stylebox '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(style_map[p_node_type].has(p_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); - ERR_FAIL_COND_MSG(!style_map[p_node_type].has(p_old_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because it does not exist."); +void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!style_map.has(p_theme_type), "Cannot rename the stylebox '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(style_map[p_theme_type].has(p_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!style_map[p_theme_type].has(p_old_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because it does not exist."); - style_map[p_node_type][p_name] = style_map[p_node_type][p_old_name]; - style_map[p_node_type].erase(p_old_name); + style_map[p_theme_type][p_name] = style_map[p_theme_type][p_old_name]; + style_map[p_theme_type].erase(p_old_name); notify_property_list_changed(); emit_changed(); } -void Theme::clear_stylebox(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot clear the stylebox '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(!style_map[p_node_type].has(p_name), "Cannot clear the stylebox '" + String(p_name) + "' because it does not exist."); +void Theme::clear_stylebox(const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!style_map.has(p_theme_type), "Cannot clear the stylebox '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!style_map[p_theme_type].has(p_name), "Cannot clear the stylebox '" + String(p_name) + "' because it does not exist."); - if (style_map[p_node_type][p_name].is_valid()) { - style_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); + if (style_map[p_theme_type][p_name].is_valid()) { + style_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } - style_map[p_node_type].erase(p_name); + style_map[p_theme_type].erase(p_name); notify_property_list_changed(); emit_changed(); } -void Theme::get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const { +void Theme::get_stylebox_list(StringName p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - if (!style_map.has(p_node_type)) { + if (!style_map.has(p_theme_type)) { return; } const StringName *key = nullptr; - while ((key = style_map[p_node_type].next(key))) { + while ((key = style_map[p_theme_type].next(key))) { p_list->push_back(*key); } } -void Theme::add_stylebox_type(const StringName &p_node_type) { - style_map[p_node_type] = HashMap<StringName, Ref<StyleBox>>(); +void Theme::add_stylebox_type(const StringName &p_theme_type) { + style_map[p_theme_type] = HashMap<StringName, Ref<StyleBox>>(); } void Theme::get_stylebox_type_list(List<StringName> *p_list) const { @@ -653,17 +653,17 @@ void Theme::get_stylebox_type_list(List<StringName> *p_list) const { } } -void Theme::set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font) { - bool new_value = !font_map.has(p_node_type) || !font_map[p_node_type].has(p_name); +void Theme::set_font(const StringName &p_name, const StringName &p_theme_type, const Ref<Font> &p_font) { + bool new_value = !font_map.has(p_theme_type) || !font_map[p_theme_type].has(p_name); - if (font_map[p_node_type][p_name].is_valid()) { - font_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); + if (font_map[p_theme_type][p_name].is_valid()) { + font_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } - font_map[p_node_type][p_name] = p_font; + font_map[p_theme_type][p_name] = p_font; if (p_font.is_valid()) { - font_map[p_node_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); + font_map[p_theme_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); } if (new_value) { @@ -672,9 +672,9 @@ void Theme::set_font(const StringName &p_name, const StringName &p_node_type, co } } -Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_node_type) const { - if (font_map.has(p_node_type) && font_map[p_node_type].has(p_name) && font_map[p_node_type][p_name].is_valid()) { - return font_map[p_node_type][p_name]; +Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_theme_type) const { + if (font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) { + return font_map[p_theme_type][p_name]; } else if (default_theme_font.is_valid()) { return default_theme_font; } else { @@ -682,55 +682,55 @@ Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_node_typ } } -bool Theme::has_font(const StringName &p_name, const StringName &p_node_type) const { - return ((font_map.has(p_node_type) && font_map[p_node_type].has(p_name) && font_map[p_node_type][p_name].is_valid()) || default_theme_font.is_valid()); +bool Theme::has_font(const StringName &p_name, const StringName &p_theme_type) const { + return ((font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) || default_theme_font.is_valid()); } -bool Theme::has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const { - return (font_map.has(p_node_type) && font_map[p_node_type].has(p_name)); +bool Theme::has_font_nocheck(const StringName &p_name, const StringName &p_theme_type) const { + return (font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name)); } -void Theme::rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot rename the font '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(font_map[p_node_type].has(p_name), "Cannot rename the font '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); - ERR_FAIL_COND_MSG(!font_map[p_node_type].has(p_old_name), "Cannot rename the font '" + String(p_old_name) + "' because it does not exist."); +void Theme::rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!font_map.has(p_theme_type), "Cannot rename the font '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(font_map[p_theme_type].has(p_name), "Cannot rename the font '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!font_map[p_theme_type].has(p_old_name), "Cannot rename the font '" + String(p_old_name) + "' because it does not exist."); - font_map[p_node_type][p_name] = font_map[p_node_type][p_old_name]; - font_map[p_node_type].erase(p_old_name); + font_map[p_theme_type][p_name] = font_map[p_theme_type][p_old_name]; + font_map[p_theme_type].erase(p_old_name); notify_property_list_changed(); emit_changed(); } -void Theme::clear_font(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot clear the font '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(!font_map[p_node_type].has(p_name), "Cannot clear the font '" + String(p_name) + "' because it does not exist."); +void Theme::clear_font(const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!font_map.has(p_theme_type), "Cannot clear the font '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!font_map[p_theme_type].has(p_name), "Cannot clear the font '" + String(p_name) + "' because it does not exist."); - if (font_map[p_node_type][p_name].is_valid()) { - font_map[p_node_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); + if (font_map[p_theme_type][p_name].is_valid()) { + font_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } - font_map[p_node_type].erase(p_name); + font_map[p_theme_type].erase(p_name); notify_property_list_changed(); emit_changed(); } -void Theme::get_font_list(StringName p_node_type, List<StringName> *p_list) const { +void Theme::get_font_list(StringName p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - if (!font_map.has(p_node_type)) { + if (!font_map.has(p_theme_type)) { return; } const StringName *key = nullptr; - while ((key = font_map[p_node_type].next(key))) { + while ((key = font_map[p_theme_type].next(key))) { p_list->push_back(*key); } } -void Theme::add_font_type(const StringName &p_node_type) { - font_map[p_node_type] = HashMap<StringName, Ref<Font>>(); +void Theme::add_font_type(const StringName &p_theme_type) { + font_map[p_theme_type] = HashMap<StringName, Ref<Font>>(); } void Theme::get_font_type_list(List<StringName> *p_list) const { @@ -742,10 +742,10 @@ void Theme::get_font_type_list(List<StringName> *p_list) const { } } -void Theme::set_font_size(const StringName &p_name, const StringName &p_node_type, int p_font_size) { - bool new_value = !font_size_map.has(p_node_type) || !font_size_map[p_node_type].has(p_name); +void Theme::set_font_size(const StringName &p_name, const StringName &p_theme_type, int p_font_size) { + bool new_value = !font_size_map.has(p_theme_type) || !font_size_map[p_theme_type].has(p_name); - font_size_map[p_node_type][p_name] = p_font_size; + font_size_map[p_theme_type][p_name] = p_font_size; if (new_value) { notify_property_list_changed(); @@ -753,9 +753,9 @@ void Theme::set_font_size(const StringName &p_name, const StringName &p_node_typ } } -int Theme::get_font_size(const StringName &p_name, const StringName &p_node_type) const { - if (font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name) && (font_size_map[p_node_type][p_name] > 0)) { - return font_size_map[p_node_type][p_name]; +int Theme::get_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (font_size_map.has(p_theme_type) && font_size_map[p_theme_type].has(p_name) && (font_size_map[p_theme_type][p_name] > 0)) { + return font_size_map[p_theme_type][p_name]; } else if (default_theme_font_size > 0) { return default_theme_font_size; } else { @@ -763,51 +763,51 @@ int Theme::get_font_size(const StringName &p_name, const StringName &p_node_type } } -bool Theme::has_font_size(const StringName &p_name, const StringName &p_node_type) const { - return ((font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name) && (font_size_map[p_node_type][p_name] > 0)) || (default_theme_font_size > 0)); +bool Theme::has_font_size(const StringName &p_name, const StringName &p_theme_type) const { + return ((font_size_map.has(p_theme_type) && font_size_map[p_theme_type].has(p_name) && (font_size_map[p_theme_type][p_name] > 0)) || (default_theme_font_size > 0)); } -bool Theme::has_font_size_nocheck(const StringName &p_name, const StringName &p_node_type) const { - return (font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name)); +bool Theme::has_font_size_nocheck(const StringName &p_name, const StringName &p_theme_type) const { + return (font_size_map.has(p_theme_type) && font_size_map[p_theme_type].has(p_name)); } -void Theme::rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!font_size_map.has(p_node_type), "Cannot rename the font size '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(font_size_map[p_node_type].has(p_name), "Cannot rename the font size '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); - ERR_FAIL_COND_MSG(!font_size_map[p_node_type].has(p_old_name), "Cannot rename the font size '" + String(p_old_name) + "' because it does not exist."); +void Theme::rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!font_size_map.has(p_theme_type), "Cannot rename the font size '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(font_size_map[p_theme_type].has(p_name), "Cannot rename the font size '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!font_size_map[p_theme_type].has(p_old_name), "Cannot rename the font size '" + String(p_old_name) + "' because it does not exist."); - font_size_map[p_node_type][p_name] = font_size_map[p_node_type][p_old_name]; - font_size_map[p_node_type].erase(p_old_name); + font_size_map[p_theme_type][p_name] = font_size_map[p_theme_type][p_old_name]; + font_size_map[p_theme_type].erase(p_old_name); notify_property_list_changed(); emit_changed(); } -void Theme::clear_font_size(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!font_size_map.has(p_node_type), "Cannot clear the font size '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(!font_size_map[p_node_type].has(p_name), "Cannot clear the font size '" + String(p_name) + "' because it does not exist."); +void Theme::clear_font_size(const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!font_size_map.has(p_theme_type), "Cannot clear the font size '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!font_size_map[p_theme_type].has(p_name), "Cannot clear the font size '" + String(p_name) + "' because it does not exist."); - font_size_map[p_node_type].erase(p_name); + font_size_map[p_theme_type].erase(p_name); notify_property_list_changed(); emit_changed(); } -void Theme::get_font_size_list(StringName p_node_type, List<StringName> *p_list) const { +void Theme::get_font_size_list(StringName p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - if (!font_size_map.has(p_node_type)) { + if (!font_size_map.has(p_theme_type)) { return; } const StringName *key = nullptr; - while ((key = font_size_map[p_node_type].next(key))) { + while ((key = font_size_map[p_theme_type].next(key))) { p_list->push_back(*key); } } -void Theme::add_font_size_type(const StringName &p_node_type) { - font_size_map[p_node_type] = HashMap<StringName, int>(); +void Theme::add_font_size_type(const StringName &p_theme_type) { + font_size_map[p_theme_type] = HashMap<StringName, int>(); } void Theme::get_font_size_type_list(List<StringName> *p_list) const { @@ -819,10 +819,10 @@ void Theme::get_font_size_type_list(List<StringName> *p_list) const { } } -void Theme::set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color) { - bool new_value = !color_map.has(p_node_type) || !color_map[p_node_type].has(p_name); +void Theme::set_color(const StringName &p_name, const StringName &p_theme_type, const Color &p_color) { + bool new_value = !color_map.has(p_theme_type) || !color_map[p_theme_type].has(p_name); - color_map[p_node_type][p_name] = p_color; + color_map[p_theme_type][p_name] = p_color; if (new_value) { notify_property_list_changed(); @@ -830,59 +830,59 @@ void Theme::set_color(const StringName &p_name, const StringName &p_node_type, c } } -Color Theme::get_color(const StringName &p_name, const StringName &p_node_type) const { - if (color_map.has(p_node_type) && color_map[p_node_type].has(p_name)) { - return color_map[p_node_type][p_name]; +Color Theme::get_color(const StringName &p_name, const StringName &p_theme_type) const { + if (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name)) { + return color_map[p_theme_type][p_name]; } else { return Color(); } } -bool Theme::has_color(const StringName &p_name, const StringName &p_node_type) const { - return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name)); +bool Theme::has_color(const StringName &p_name, const StringName &p_theme_type) const { + return (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name)); } -bool Theme::has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const { - return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name)); +bool Theme::has_color_nocheck(const StringName &p_name, const StringName &p_theme_type) const { + return (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name)); } -void Theme::rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot rename the color '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(color_map[p_node_type].has(p_name), "Cannot rename the color '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); - ERR_FAIL_COND_MSG(!color_map[p_node_type].has(p_old_name), "Cannot rename the color '" + String(p_old_name) + "' because it does not exist."); +void Theme::rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!color_map.has(p_theme_type), "Cannot rename the color '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(color_map[p_theme_type].has(p_name), "Cannot rename the color '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!color_map[p_theme_type].has(p_old_name), "Cannot rename the color '" + String(p_old_name) + "' because it does not exist."); - color_map[p_node_type][p_name] = color_map[p_node_type][p_old_name]; - color_map[p_node_type].erase(p_old_name); + color_map[p_theme_type][p_name] = color_map[p_theme_type][p_old_name]; + color_map[p_theme_type].erase(p_old_name); notify_property_list_changed(); emit_changed(); } -void Theme::clear_color(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot clear the color '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(!color_map[p_node_type].has(p_name), "Cannot clear the color '" + String(p_name) + "' because it does not exist."); +void Theme::clear_color(const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!color_map.has(p_theme_type), "Cannot clear the color '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!color_map[p_theme_type].has(p_name), "Cannot clear the color '" + String(p_name) + "' because it does not exist."); - color_map[p_node_type].erase(p_name); + color_map[p_theme_type].erase(p_name); notify_property_list_changed(); emit_changed(); } -void Theme::get_color_list(StringName p_node_type, List<StringName> *p_list) const { +void Theme::get_color_list(StringName p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - if (!color_map.has(p_node_type)) { + if (!color_map.has(p_theme_type)) { return; } const StringName *key = nullptr; - while ((key = color_map[p_node_type].next(key))) { + while ((key = color_map[p_theme_type].next(key))) { p_list->push_back(*key); } } -void Theme::add_color_type(const StringName &p_node_type) { - color_map[p_node_type] = HashMap<StringName, Color>(); +void Theme::add_color_type(const StringName &p_theme_type) { + color_map[p_theme_type] = HashMap<StringName, Color>(); } void Theme::get_color_type_list(List<StringName> *p_list) const { @@ -894,9 +894,9 @@ void Theme::get_color_type_list(List<StringName> *p_list) const { } } -void Theme::set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant) { - bool new_value = !constant_map.has(p_node_type) || !constant_map[p_node_type].has(p_name); - constant_map[p_node_type][p_name] = p_constant; +void Theme::set_constant(const StringName &p_name, const StringName &p_theme_type, int p_constant) { + bool new_value = !constant_map.has(p_theme_type) || !constant_map[p_theme_type].has(p_name); + constant_map[p_theme_type][p_name] = p_constant; if (new_value) { notify_property_list_changed(); @@ -904,59 +904,59 @@ void Theme::set_constant(const StringName &p_name, const StringName &p_node_type } } -int Theme::get_constant(const StringName &p_name, const StringName &p_node_type) const { - if (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name)) { - return constant_map[p_node_type][p_name]; +int Theme::get_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name)) { + return constant_map[p_theme_type][p_name]; } else { return 0; } } -bool Theme::has_constant(const StringName &p_name, const StringName &p_node_type) const { - return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name)); +bool Theme::has_constant(const StringName &p_name, const StringName &p_theme_type) const { + return (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name)); } -bool Theme::has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const { - return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name)); +bool Theme::has_constant_nocheck(const StringName &p_name, const StringName &p_theme_type) const { + return (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name)); } -void Theme::rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot rename the constant '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(constant_map[p_node_type].has(p_name), "Cannot rename the constant '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); - ERR_FAIL_COND_MSG(!constant_map[p_node_type].has(p_old_name), "Cannot rename the constant '" + String(p_old_name) + "' because it does not exist."); +void Theme::rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!constant_map.has(p_theme_type), "Cannot rename the constant '" + String(p_old_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(constant_map[p_theme_type].has(p_name), "Cannot rename the constant '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists."); + ERR_FAIL_COND_MSG(!constant_map[p_theme_type].has(p_old_name), "Cannot rename the constant '" + String(p_old_name) + "' because it does not exist."); - constant_map[p_node_type][p_name] = constant_map[p_node_type][p_old_name]; - constant_map[p_node_type].erase(p_old_name); + constant_map[p_theme_type][p_name] = constant_map[p_theme_type][p_old_name]; + constant_map[p_theme_type].erase(p_old_name); notify_property_list_changed(); emit_changed(); } -void Theme::clear_constant(const StringName &p_name, const StringName &p_node_type) { - ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot clear the constant '" + String(p_name) + "' because the node type '" + String(p_node_type) + "' does not exist."); - ERR_FAIL_COND_MSG(!constant_map[p_node_type].has(p_name), "Cannot clear the constant '" + String(p_name) + "' because it does not exist."); +void Theme::clear_constant(const StringName &p_name, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!constant_map.has(p_theme_type), "Cannot clear the constant '" + String(p_name) + "' because the node type '" + String(p_theme_type) + "' does not exist."); + ERR_FAIL_COND_MSG(!constant_map[p_theme_type].has(p_name), "Cannot clear the constant '" + String(p_name) + "' because it does not exist."); - constant_map[p_node_type].erase(p_name); + constant_map[p_theme_type].erase(p_name); notify_property_list_changed(); emit_changed(); } -void Theme::get_constant_list(StringName p_node_type, List<StringName> *p_list) const { +void Theme::get_constant_list(StringName p_theme_type, List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - if (!constant_map.has(p_node_type)) { + if (!constant_map.has(p_theme_type)) { return; } const StringName *key = nullptr; - while ((key = constant_map[p_node_type].next(key))) { + while ((key = constant_map[p_theme_type].next(key))) { p_list->push_back(*key); } } -void Theme::add_constant_type(const StringName &p_node_type) { - constant_map[p_node_type] = HashMap<StringName, int>(); +void Theme::add_constant_type(const StringName &p_theme_type) { + constant_map[p_theme_type] = HashMap<StringName, int>(); } void Theme::get_constant_type_list(List<StringName> *p_list) const { @@ -968,63 +968,63 @@ void Theme::get_constant_type_list(List<StringName> *p_list) const { } } -void Theme::set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value) { +void Theme::set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type, const Variant &p_value) { switch (p_data_type) { case DATA_TYPE_COLOR: { ERR_FAIL_COND_MSG(p_value.get_type() != Variant::COLOR, "Theme item's data type (Color) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); Color color_value = p_value; - set_color(p_name, p_node_type, color_value); + set_color(p_name, p_theme_type, color_value); } break; case DATA_TYPE_CONSTANT: { ERR_FAIL_COND_MSG(p_value.get_type() != Variant::INT, "Theme item's data type (int) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); int constant_value = p_value; - set_constant(p_name, p_node_type, constant_value); + set_constant(p_name, p_theme_type, constant_value); } break; case DATA_TYPE_FONT: { ERR_FAIL_COND_MSG(p_value.get_type() != Variant::OBJECT, "Theme item's data type (Object) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); Ref<Font> font_value = Object::cast_to<Font>(p_value.get_validated_object()); - set_font(p_name, p_node_type, font_value); + set_font(p_name, p_theme_type, font_value); } break; case DATA_TYPE_FONT_SIZE: { ERR_FAIL_COND_MSG(p_value.get_type() != Variant::INT, "Theme item's data type (int) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); int font_size_value = p_value; - set_font_size(p_name, p_node_type, font_size_value); + set_font_size(p_name, p_theme_type, font_size_value); } break; case DATA_TYPE_ICON: { ERR_FAIL_COND_MSG(p_value.get_type() != Variant::OBJECT, "Theme item's data type (Object) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); Ref<Texture2D> icon_value = Object::cast_to<Texture2D>(p_value.get_validated_object()); - set_icon(p_name, p_node_type, icon_value); + set_icon(p_name, p_theme_type, icon_value); } break; case DATA_TYPE_STYLEBOX: { ERR_FAIL_COND_MSG(p_value.get_type() != Variant::OBJECT, "Theme item's data type (Object) does not match Variant's type (" + Variant::get_type_name(p_value.get_type()) + ")."); Ref<StyleBox> stylebox_value = Object::cast_to<StyleBox>(p_value.get_validated_object()); - set_stylebox(p_name, p_node_type, stylebox_value); + set_stylebox(p_name, p_theme_type, stylebox_value); } break; case DATA_TYPE_MAX: break; // Can't happen, but silences warning. } } -Variant Theme::get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const { +Variant Theme::get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const { switch (p_data_type) { case DATA_TYPE_COLOR: - return get_color(p_name, p_node_type); + return get_color(p_name, p_theme_type); case DATA_TYPE_CONSTANT: - return get_constant(p_name, p_node_type); + return get_constant(p_name, p_theme_type); case DATA_TYPE_FONT: - return get_font(p_name, p_node_type); + return get_font(p_name, p_theme_type); case DATA_TYPE_FONT_SIZE: - return get_font_size(p_name, p_node_type); + return get_font_size(p_name, p_theme_type); case DATA_TYPE_ICON: - return get_icon(p_name, p_node_type); + return get_icon(p_name, p_theme_type); case DATA_TYPE_STYLEBOX: - return get_stylebox(p_name, p_node_type); + return get_stylebox(p_name, p_theme_type); case DATA_TYPE_MAX: break; // Can't happen, but silences warning. } @@ -1032,20 +1032,20 @@ Variant Theme::get_theme_item(DataType p_data_type, const StringName &p_name, co return Variant(); } -bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const { +bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const { switch (p_data_type) { case DATA_TYPE_COLOR: - return has_color(p_name, p_node_type); + return has_color(p_name, p_theme_type); case DATA_TYPE_CONSTANT: - return has_constant(p_name, p_node_type); + return has_constant(p_name, p_theme_type); case DATA_TYPE_FONT: - return has_font(p_name, p_node_type); + return has_font(p_name, p_theme_type); case DATA_TYPE_FONT_SIZE: - return has_font_size(p_name, p_node_type); + return has_font_size(p_name, p_theme_type); case DATA_TYPE_ICON: - return has_icon(p_name, p_node_type); + return has_icon(p_name, p_theme_type); case DATA_TYPE_STYLEBOX: - return has_stylebox(p_name, p_node_type); + return has_stylebox(p_name, p_theme_type); case DATA_TYPE_MAX: break; // Can't happen, but silences warning. } @@ -1053,20 +1053,20 @@ bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const return false; } -bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const { +bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const { switch (p_data_type) { case DATA_TYPE_COLOR: - return has_color_nocheck(p_name, p_node_type); + return has_color_nocheck(p_name, p_theme_type); case DATA_TYPE_CONSTANT: - return has_constant_nocheck(p_name, p_node_type); + return has_constant_nocheck(p_name, p_theme_type); case DATA_TYPE_FONT: - return has_font_nocheck(p_name, p_node_type); + return has_font_nocheck(p_name, p_theme_type); case DATA_TYPE_FONT_SIZE: - return has_font_size_nocheck(p_name, p_node_type); + return has_font_size_nocheck(p_name, p_theme_type); case DATA_TYPE_ICON: - return has_icon_nocheck(p_name, p_node_type); + return has_icon_nocheck(p_name, p_theme_type); case DATA_TYPE_STYLEBOX: - return has_stylebox_nocheck(p_name, p_node_type); + return has_stylebox_nocheck(p_name, p_theme_type); case DATA_TYPE_MAX: break; // Can't happen, but silences warning. } @@ -1074,100 +1074,100 @@ bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_nam return false; } -void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) { +void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type) { switch (p_data_type) { case DATA_TYPE_COLOR: - rename_color(p_old_name, p_name, p_node_type); + rename_color(p_old_name, p_name, p_theme_type); break; case DATA_TYPE_CONSTANT: - rename_constant(p_old_name, p_name, p_node_type); + rename_constant(p_old_name, p_name, p_theme_type); break; case DATA_TYPE_FONT: - rename_font(p_old_name, p_name, p_node_type); + rename_font(p_old_name, p_name, p_theme_type); break; case DATA_TYPE_FONT_SIZE: - rename_font_size(p_old_name, p_name, p_node_type); + rename_font_size(p_old_name, p_name, p_theme_type); break; case DATA_TYPE_ICON: - rename_icon(p_old_name, p_name, p_node_type); + rename_icon(p_old_name, p_name, p_theme_type); break; case DATA_TYPE_STYLEBOX: - rename_stylebox(p_old_name, p_name, p_node_type); + rename_stylebox(p_old_name, p_name, p_theme_type); break; case DATA_TYPE_MAX: break; // Can't happen, but silences warning. } } -void Theme::clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) { +void Theme::clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) { switch (p_data_type) { case DATA_TYPE_COLOR: - clear_color(p_name, p_node_type); + clear_color(p_name, p_theme_type); break; case DATA_TYPE_CONSTANT: - clear_constant(p_name, p_node_type); + clear_constant(p_name, p_theme_type); break; case DATA_TYPE_FONT: - clear_font(p_name, p_node_type); + clear_font(p_name, p_theme_type); break; case DATA_TYPE_FONT_SIZE: - clear_font_size(p_name, p_node_type); + clear_font_size(p_name, p_theme_type); break; case DATA_TYPE_ICON: - clear_icon(p_name, p_node_type); + clear_icon(p_name, p_theme_type); break; case DATA_TYPE_STYLEBOX: - clear_stylebox(p_name, p_node_type); + clear_stylebox(p_name, p_theme_type); break; case DATA_TYPE_MAX: break; // Can't happen, but silences warning. } } -void Theme::get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const { +void Theme::get_theme_item_list(DataType p_data_type, StringName p_theme_type, List<StringName> *p_list) const { switch (p_data_type) { case DATA_TYPE_COLOR: - get_color_list(p_node_type, p_list); + get_color_list(p_theme_type, p_list); break; case DATA_TYPE_CONSTANT: - get_constant_list(p_node_type, p_list); + get_constant_list(p_theme_type, p_list); break; case DATA_TYPE_FONT: - get_font_list(p_node_type, p_list); + get_font_list(p_theme_type, p_list); break; case DATA_TYPE_FONT_SIZE: - get_font_size_list(p_node_type, p_list); + get_font_size_list(p_theme_type, p_list); break; case DATA_TYPE_ICON: - get_icon_list(p_node_type, p_list); + get_icon_list(p_theme_type, p_list); break; case DATA_TYPE_STYLEBOX: - get_stylebox_list(p_node_type, p_list); + get_stylebox_list(p_theme_type, p_list); break; case DATA_TYPE_MAX: break; // Can't happen, but silences warning. } } -void Theme::add_theme_item_type(DataType p_data_type, const StringName &p_node_type) { +void Theme::add_theme_item_type(DataType p_data_type, const StringName &p_theme_type) { switch (p_data_type) { case DATA_TYPE_COLOR: - add_color_type(p_node_type); + add_color_type(p_theme_type); break; case DATA_TYPE_CONSTANT: - add_constant_type(p_node_type); + add_constant_type(p_theme_type); break; case DATA_TYPE_FONT: - add_font_type(p_node_type); + add_font_type(p_theme_type); break; case DATA_TYPE_FONT_SIZE: - add_font_size_type(p_node_type); + add_font_size_type(p_theme_type); break; case DATA_TYPE_ICON: - add_icon_type(p_node_type); + add_icon_type(p_theme_type); break; case DATA_TYPE_STYLEBOX: - add_stylebox_type(p_node_type); + add_stylebox_type(p_theme_type); break; case DATA_TYPE_MAX: break; // Can't happen, but silences warning. @@ -1340,56 +1340,66 @@ void Theme::get_type_list(List<StringName> *p_list) const { } } +void Theme::get_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) { + ERR_FAIL_NULL(p_list); + + StringName class_name = p_theme_type; + while (class_name != StringName()) { + p_list->push_back(class_name); + class_name = ClassDB::get_parent_class_nocheck(class_name); + } +} + void Theme::reset_state() { clear(); } void Theme::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_icon", "name", "node_type", "texture"), &Theme::set_icon); - ClassDB::bind_method(D_METHOD("get_icon", "name", "node_type"), &Theme::get_icon); - ClassDB::bind_method(D_METHOD("has_icon", "name", "node_type"), &Theme::has_icon); - ClassDB::bind_method(D_METHOD("rename_icon", "old_name", "name", "node_type"), &Theme::rename_icon); - ClassDB::bind_method(D_METHOD("clear_icon", "name", "node_type"), &Theme::clear_icon); - ClassDB::bind_method(D_METHOD("get_icon_list", "node_type"), &Theme::_get_icon_list); + ClassDB::bind_method(D_METHOD("set_icon", "name", "theme_type", "texture"), &Theme::set_icon); + ClassDB::bind_method(D_METHOD("get_icon", "name", "theme_type"), &Theme::get_icon); + ClassDB::bind_method(D_METHOD("has_icon", "name", "theme_type"), &Theme::has_icon); + ClassDB::bind_method(D_METHOD("rename_icon", "old_name", "name", "theme_type"), &Theme::rename_icon); + ClassDB::bind_method(D_METHOD("clear_icon", "name", "theme_type"), &Theme::clear_icon); + ClassDB::bind_method(D_METHOD("get_icon_list", "theme_type"), &Theme::_get_icon_list); ClassDB::bind_method(D_METHOD("get_icon_type_list"), &Theme::_get_icon_type_list); - ClassDB::bind_method(D_METHOD("set_stylebox", "name", "node_type", "texture"), &Theme::set_stylebox); - ClassDB::bind_method(D_METHOD("get_stylebox", "name", "node_type"), &Theme::get_stylebox); - ClassDB::bind_method(D_METHOD("has_stylebox", "name", "node_type"), &Theme::has_stylebox); - ClassDB::bind_method(D_METHOD("rename_stylebox", "old_name", "name", "node_type"), &Theme::rename_stylebox); - ClassDB::bind_method(D_METHOD("clear_stylebox", "name", "node_type"), &Theme::clear_stylebox); - ClassDB::bind_method(D_METHOD("get_stylebox_list", "node_type"), &Theme::_get_stylebox_list); + ClassDB::bind_method(D_METHOD("set_stylebox", "name", "theme_type", "texture"), &Theme::set_stylebox); + ClassDB::bind_method(D_METHOD("get_stylebox", "name", "theme_type"), &Theme::get_stylebox); + ClassDB::bind_method(D_METHOD("has_stylebox", "name", "theme_type"), &Theme::has_stylebox); + ClassDB::bind_method(D_METHOD("rename_stylebox", "old_name", "name", "theme_type"), &Theme::rename_stylebox); + ClassDB::bind_method(D_METHOD("clear_stylebox", "name", "theme_type"), &Theme::clear_stylebox); + ClassDB::bind_method(D_METHOD("get_stylebox_list", "theme_type"), &Theme::_get_stylebox_list); ClassDB::bind_method(D_METHOD("get_stylebox_type_list"), &Theme::_get_stylebox_type_list); - ClassDB::bind_method(D_METHOD("set_font", "name", "node_type", "font"), &Theme::set_font); - ClassDB::bind_method(D_METHOD("get_font", "name", "node_type"), &Theme::get_font); - ClassDB::bind_method(D_METHOD("has_font", "name", "node_type"), &Theme::has_font); - ClassDB::bind_method(D_METHOD("rename_font", "old_name", "name", "node_type"), &Theme::rename_font); - ClassDB::bind_method(D_METHOD("clear_font", "name", "node_type"), &Theme::clear_font); - ClassDB::bind_method(D_METHOD("get_font_list", "node_type"), &Theme::_get_font_list); + ClassDB::bind_method(D_METHOD("set_font", "name", "theme_type", "font"), &Theme::set_font); + ClassDB::bind_method(D_METHOD("get_font", "name", "theme_type"), &Theme::get_font); + ClassDB::bind_method(D_METHOD("has_font", "name", "theme_type"), &Theme::has_font); + ClassDB::bind_method(D_METHOD("rename_font", "old_name", "name", "theme_type"), &Theme::rename_font); + ClassDB::bind_method(D_METHOD("clear_font", "name", "theme_type"), &Theme::clear_font); + ClassDB::bind_method(D_METHOD("get_font_list", "theme_type"), &Theme::_get_font_list); ClassDB::bind_method(D_METHOD("get_font_type_list"), &Theme::_get_font_type_list); - ClassDB::bind_method(D_METHOD("set_font_size", "name", "node_type", "font_size"), &Theme::set_font_size); - ClassDB::bind_method(D_METHOD("get_font_size", "name", "node_type"), &Theme::get_font_size); - ClassDB::bind_method(D_METHOD("has_font_size", "name", "node_type"), &Theme::has_font_size); - ClassDB::bind_method(D_METHOD("rename_font_size", "old_name", "name", "node_type"), &Theme::rename_font_size); - ClassDB::bind_method(D_METHOD("clear_font_size", "name", "node_type"), &Theme::clear_font_size); - ClassDB::bind_method(D_METHOD("get_font_size_list", "node_type"), &Theme::_get_font_size_list); + ClassDB::bind_method(D_METHOD("set_font_size", "name", "theme_type", "font_size"), &Theme::set_font_size); + ClassDB::bind_method(D_METHOD("get_font_size", "name", "theme_type"), &Theme::get_font_size); + ClassDB::bind_method(D_METHOD("has_font_size", "name", "theme_type"), &Theme::has_font_size); + ClassDB::bind_method(D_METHOD("rename_font_size", "old_name", "name", "theme_type"), &Theme::rename_font_size); + ClassDB::bind_method(D_METHOD("clear_font_size", "name", "theme_type"), &Theme::clear_font_size); + ClassDB::bind_method(D_METHOD("get_font_size_list", "theme_type"), &Theme::_get_font_size_list); ClassDB::bind_method(D_METHOD("get_font_size_type_list"), &Theme::_get_font_size_type_list); - ClassDB::bind_method(D_METHOD("set_color", "name", "node_type", "color"), &Theme::set_color); - ClassDB::bind_method(D_METHOD("get_color", "name", "node_type"), &Theme::get_color); - ClassDB::bind_method(D_METHOD("has_color", "name", "node_type"), &Theme::has_color); - ClassDB::bind_method(D_METHOD("rename_color", "old_name", "name", "node_type"), &Theme::rename_color); - ClassDB::bind_method(D_METHOD("clear_color", "name", "node_type"), &Theme::clear_color); - ClassDB::bind_method(D_METHOD("get_color_list", "node_type"), &Theme::_get_color_list); + ClassDB::bind_method(D_METHOD("set_color", "name", "theme_type", "color"), &Theme::set_color); + ClassDB::bind_method(D_METHOD("get_color", "name", "theme_type"), &Theme::get_color); + ClassDB::bind_method(D_METHOD("has_color", "name", "theme_type"), &Theme::has_color); + ClassDB::bind_method(D_METHOD("rename_color", "old_name", "name", "theme_type"), &Theme::rename_color); + ClassDB::bind_method(D_METHOD("clear_color", "name", "theme_type"), &Theme::clear_color); + ClassDB::bind_method(D_METHOD("get_color_list", "theme_type"), &Theme::_get_color_list); ClassDB::bind_method(D_METHOD("get_color_type_list"), &Theme::_get_color_type_list); - ClassDB::bind_method(D_METHOD("set_constant", "name", "node_type", "constant"), &Theme::set_constant); - ClassDB::bind_method(D_METHOD("get_constant", "name", "node_type"), &Theme::get_constant); - ClassDB::bind_method(D_METHOD("has_constant", "name", "node_type"), &Theme::has_constant); - ClassDB::bind_method(D_METHOD("rename_constant", "old_name", "name", "node_type"), &Theme::rename_constant); - ClassDB::bind_method(D_METHOD("clear_constant", "name", "node_type"), &Theme::clear_constant); - ClassDB::bind_method(D_METHOD("get_constant_list", "node_type"), &Theme::_get_constant_list); + ClassDB::bind_method(D_METHOD("set_constant", "name", "theme_type", "constant"), &Theme::set_constant); + ClassDB::bind_method(D_METHOD("get_constant", "name", "theme_type"), &Theme::get_constant); + ClassDB::bind_method(D_METHOD("has_constant", "name", "theme_type"), &Theme::has_constant); + ClassDB::bind_method(D_METHOD("rename_constant", "old_name", "name", "theme_type"), &Theme::rename_constant); + ClassDB::bind_method(D_METHOD("clear_constant", "name", "theme_type"), &Theme::clear_constant); + ClassDB::bind_method(D_METHOD("get_constant_list", "theme_type"), &Theme::_get_constant_list); ClassDB::bind_method(D_METHOD("get_constant_type_list"), &Theme::_get_constant_type_list); ClassDB::bind_method(D_METHOD("clear"), &Theme::clear); @@ -1400,12 +1410,12 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("set_default_font_size", "font_size"), &Theme::set_default_theme_font_size); ClassDB::bind_method(D_METHOD("get_default_font_size"), &Theme::get_default_theme_font_size); - ClassDB::bind_method(D_METHOD("set_theme_item", "data_type", "name", "node_type", "value"), &Theme::set_theme_item); - ClassDB::bind_method(D_METHOD("get_theme_item", "data_type", "name", "node_type"), &Theme::get_theme_item); - ClassDB::bind_method(D_METHOD("has_theme_item", "data_type", "name", "node_type"), &Theme::has_theme_item); - ClassDB::bind_method(D_METHOD("rename_theme_item", "data_type", "old_name", "name", "node_type"), &Theme::rename_theme_item); - ClassDB::bind_method(D_METHOD("clear_theme_item", "data_type", "name", "node_type"), &Theme::clear_theme_item); - ClassDB::bind_method(D_METHOD("get_theme_item_list", "data_type", "node_type"), &Theme::_get_theme_item_list); + ClassDB::bind_method(D_METHOD("set_theme_item", "data_type", "name", "theme_type", "value"), &Theme::set_theme_item); + ClassDB::bind_method(D_METHOD("get_theme_item", "data_type", "name", "theme_type"), &Theme::get_theme_item); + ClassDB::bind_method(D_METHOD("has_theme_item", "data_type", "name", "theme_type"), &Theme::has_theme_item); + ClassDB::bind_method(D_METHOD("rename_theme_item", "data_type", "old_name", "name", "theme_type"), &Theme::rename_theme_item); + ClassDB::bind_method(D_METHOD("clear_theme_item", "data_type", "name", "theme_type"), &Theme::clear_theme_item); + ClassDB::bind_method(D_METHOD("get_theme_item_list", "data_type", "theme_type"), &Theme::_get_theme_item_list); ClassDB::bind_method(D_METHOD("get_theme_item_type_list", "data_type"), &Theme::_get_theme_item_type_list); ClassDB::bind_method(D_METHOD("get_type_list"), &Theme::_get_type_list); diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 7e887b6343..4de1f065e1 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -62,20 +62,20 @@ private: HashMap<StringName, HashMap<StringName, Color>> color_map; HashMap<StringName, HashMap<StringName, int>> constant_map; - Vector<String> _get_icon_list(const String &p_node_type) const; + Vector<String> _get_icon_list(const String &p_theme_type) const; Vector<String> _get_icon_type_list() const; - Vector<String> _get_stylebox_list(const String &p_node_type) const; + Vector<String> _get_stylebox_list(const String &p_theme_type) const; Vector<String> _get_stylebox_type_list() const; - Vector<String> _get_font_list(const String &p_node_type) const; + Vector<String> _get_font_list(const String &p_theme_type) const; Vector<String> _get_font_type_list() const; - Vector<String> _get_font_size_list(const String &p_node_type) const; + Vector<String> _get_font_size_list(const String &p_theme_type) const; Vector<String> _get_font_size_type_list() const; - Vector<String> _get_color_list(const String &p_node_type) const; + Vector<String> _get_color_list(const String &p_theme_type) const; Vector<String> _get_color_type_list() const; - Vector<String> _get_constant_list(const String &p_node_type) const; + Vector<String> _get_constant_list(const String &p_theme_type) const; Vector<String> _get_constant_type_list() const; - Vector<String> _get_theme_item_list(DataType p_data_type, const String &p_node_type) const; + Vector<String> _get_theme_item_list(DataType p_data_type, const String &p_theme_type) const; Vector<String> _get_theme_item_type_list(DataType p_data_type) const; Vector<String> _get_type_list() const; @@ -116,77 +116,78 @@ public: void set_default_theme_font_size(int p_font_size); int get_default_theme_font_size() const; - void set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture2D> &p_icon); - Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_node_type) const; - bool has_icon(const StringName &p_name, const StringName &p_node_type) const; - bool has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const; - void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); - void clear_icon(const StringName &p_name, const StringName &p_node_type); - void get_icon_list(StringName p_node_type, List<StringName> *p_list) const; - void add_icon_type(const StringName &p_node_type); + void set_icon(const StringName &p_name, const StringName &p_theme_type, const Ref<Texture2D> &p_icon); + Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_theme_type) const; + bool has_icon(const StringName &p_name, const StringName &p_theme_type) const; + bool has_icon_nocheck(const StringName &p_name, const StringName &p_theme_type) const; + void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); + void clear_icon(const StringName &p_name, const StringName &p_theme_type); + void get_icon_list(StringName p_theme_type, List<StringName> *p_list) const; + void add_icon_type(const StringName &p_theme_type); void get_icon_type_list(List<StringName> *p_list) const; - void set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style); - Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_node_type) const; - bool has_stylebox(const StringName &p_name, const StringName &p_node_type) const; - bool has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const; - void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); - void clear_stylebox(const StringName &p_name, const StringName &p_node_type); - void get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const; - void add_stylebox_type(const StringName &p_node_type); + void set_stylebox(const StringName &p_name, const StringName &p_theme_type, const Ref<StyleBox> &p_style); + Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_theme_type) const; + bool has_stylebox(const StringName &p_name, const StringName &p_theme_type) const; + bool has_stylebox_nocheck(const StringName &p_name, const StringName &p_theme_type) const; + void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); + void clear_stylebox(const StringName &p_name, const StringName &p_theme_type); + void get_stylebox_list(StringName p_theme_type, List<StringName> *p_list) const; + void add_stylebox_type(const StringName &p_theme_type); void get_stylebox_type_list(List<StringName> *p_list) const; - void set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font); - Ref<Font> get_font(const StringName &p_name, const StringName &p_node_type) const; - bool has_font(const StringName &p_name, const StringName &p_node_type) const; - bool has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const; - void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); - void clear_font(const StringName &p_name, const StringName &p_node_type); - void get_font_list(StringName p_node_type, List<StringName> *p_list) const; - void add_font_type(const StringName &p_node_type); + void set_font(const StringName &p_name, const StringName &p_theme_type, const Ref<Font> &p_font); + Ref<Font> get_font(const StringName &p_name, const StringName &p_theme_type) const; + bool has_font(const StringName &p_name, const StringName &p_theme_type) const; + bool has_font_nocheck(const StringName &p_name, const StringName &p_theme_type) const; + void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); + void clear_font(const StringName &p_name, const StringName &p_theme_type); + void get_font_list(StringName p_theme_type, List<StringName> *p_list) const; + void add_font_type(const StringName &p_theme_type); void get_font_type_list(List<StringName> *p_list) const; - void set_font_size(const StringName &p_name, const StringName &p_node_type, int p_font_size); - int get_font_size(const StringName &p_name, const StringName &p_node_type) const; - bool has_font_size(const StringName &p_name, const StringName &p_node_type) const; - bool has_font_size_nocheck(const StringName &p_name, const StringName &p_node_type) const; - void rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); - void clear_font_size(const StringName &p_name, const StringName &p_node_type); - void get_font_size_list(StringName p_node_type, List<StringName> *p_list) const; - void add_font_size_type(const StringName &p_node_type); + void set_font_size(const StringName &p_name, const StringName &p_theme_type, int p_font_size); + int get_font_size(const StringName &p_name, const StringName &p_theme_type) const; + bool has_font_size(const StringName &p_name, const StringName &p_theme_type) const; + bool has_font_size_nocheck(const StringName &p_name, const StringName &p_theme_type) const; + void rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); + void clear_font_size(const StringName &p_name, const StringName &p_theme_type); + void get_font_size_list(StringName p_theme_type, List<StringName> *p_list) const; + void add_font_size_type(const StringName &p_theme_type); void get_font_size_type_list(List<StringName> *p_list) const; - void set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color); - Color get_color(const StringName &p_name, const StringName &p_node_type) const; - bool has_color(const StringName &p_name, const StringName &p_node_type) const; - bool has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const; - void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); - void clear_color(const StringName &p_name, const StringName &p_node_type); - void get_color_list(StringName p_node_type, List<StringName> *p_list) const; - void add_color_type(const StringName &p_node_type); + void set_color(const StringName &p_name, const StringName &p_theme_type, const Color &p_color); + Color get_color(const StringName &p_name, const StringName &p_theme_type) const; + bool has_color(const StringName &p_name, const StringName &p_theme_type) const; + bool has_color_nocheck(const StringName &p_name, const StringName &p_theme_type) const; + void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); + void clear_color(const StringName &p_name, const StringName &p_theme_type); + void get_color_list(StringName p_theme_type, List<StringName> *p_list) const; + void add_color_type(const StringName &p_theme_type); void get_color_type_list(List<StringName> *p_list) const; - void set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant); - int get_constant(const StringName &p_name, const StringName &p_node_type) const; - bool has_constant(const StringName &p_name, const StringName &p_node_type) const; - bool has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const; - void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); - void clear_constant(const StringName &p_name, const StringName &p_node_type); - void get_constant_list(StringName p_node_type, List<StringName> *p_list) const; - void add_constant_type(const StringName &p_node_type); + void set_constant(const StringName &p_name, const StringName &p_theme_type, int p_constant); + int get_constant(const StringName &p_name, const StringName &p_theme_type) const; + bool has_constant(const StringName &p_name, const StringName &p_theme_type) const; + bool has_constant_nocheck(const StringName &p_name, const StringName &p_theme_type) const; + void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); + void clear_constant(const StringName &p_name, const StringName &p_theme_type); + void get_constant_list(StringName p_theme_type, List<StringName> *p_list) const; + void add_constant_type(const StringName &p_theme_type); void get_constant_type_list(List<StringName> *p_list) const; - void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value); - Variant get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; - bool has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; - bool has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const; - void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type); - void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type); - void get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const; - void add_theme_item_type(DataType p_data_type, const StringName &p_node_type); + void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type, const Variant &p_value); + Variant get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const; + bool has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const; + bool has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const; + void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_theme_type); + void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type); + void get_theme_item_list(DataType p_data_type, StringName p_theme_type, List<StringName> *p_list) const; + void add_theme_item_type(DataType p_data_type, const StringName &p_theme_type); void get_theme_item_type_list(DataType p_data_type, List<StringName> *p_list) const; void get_type_list(List<StringName> *p_list) const; + static void get_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list); void copy_default_theme(); void copy_theme(const Ref<Theme> &p_other); diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index c4b8a56f54..3f6f5bb5fe 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -106,15 +106,15 @@ void TileSet::_compute_next_source_id() { } // Sources management -int TileSet::add_source(Ref<TileSetAtlasSource> p_tile_atlas_source, int p_atlas_source_id_override) { - ERR_FAIL_COND_V(!p_tile_atlas_source.is_valid(), -1); +int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source_id_override) { + ERR_FAIL_COND_V(!p_tile_set_source.is_valid(), -1); ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), -1, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override)); int new_source_id = p_atlas_source_id_override >= 0 ? p_atlas_source_id_override : next_source_id; - sources[new_source_id] = p_tile_atlas_source; + sources[new_source_id] = p_tile_set_source; source_ids.append(new_source_id); source_ids.sort(); - p_tile_atlas_source->set_tile_set(this); + p_tile_set_source->set_tile_set(this); _compute_next_source_id(); sources[new_source_id]->connect("changed", callable_mp(this, &TileSet::_source_changed)); @@ -668,8 +668,8 @@ void TileSet::reset_state() { custom_data_layers.clear(); } -const Vector2i TileSetAtlasSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1); -const int TileSetAtlasSource::INVALID_TILE_ALTERNATIVE = -1; +const Vector2i TileSetSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1); +const int TileSetSource::INVALID_TILE_ALTERNATIVE = -1; #ifndef DISABLE_DEPRECATED void TileSet::compatibility_conversion() { @@ -835,7 +835,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { } else if (what == "tile_mode") { ctd->tile_mode = p_value; } else if (what.left(9) == "autotile") { - what = what.right(9); + what = what.substr(9); if (what == "bitmask_mode") { ctd->autotile_bitmask_mode = p_value; } else if (what == "icon_coordinate") { @@ -1086,7 +1086,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { return true; } } else if (components.size() == 2 && components[0] == "sources" && components[1].is_valid_integer()) { - // Create atlas if it does not exists. + // Create source only if it does not exists. int source_id = components[1].to_int(); if (!has_source(source_id)) { @@ -1399,10 +1399,11 @@ void TileSet::_bind_methods() { TileSet::TileSet() { // Instanciatie and list all plugins. - tile_set_plugins_vector.append(memnew(TileSetAtlasPluginRendering)); - tile_set_plugins_vector.append(memnew(TileSetAtlasPluginPhysics)); - tile_set_plugins_vector.append(memnew(TileSetAtlasPluginTerrain)); - tile_set_plugins_vector.append(memnew(TileSetAtlasPluginNavigation)); + tile_set_plugins_vector.append(memnew(TileSetPluginAtlasRendering)); + tile_set_plugins_vector.append(memnew(TileSetPluginAtlasPhysics)); + tile_set_plugins_vector.append(memnew(TileSetPluginAtlasTerrain)); + tile_set_plugins_vector.append(memnew(TileSetPluginAtlasNavigation)); + tile_set_plugins_vector.append(memnew(TileSetPluginScenesCollections)); } TileSet::~TileSet() { @@ -1530,13 +1531,13 @@ bool TileSetAtlasSource::_set(const StringName &p_name, const Variant &p_value) // Compute the vector2i if we have coordinates. Vector<String> coords_split = components[0].split(":"); - Vector2i coords = TileSetAtlasSource::INVALID_ATLAS_COORDS; + Vector2i coords = TileSetSource::INVALID_ATLAS_COORDS; if (coords_split.size() == 2 && coords_split[0].is_valid_integer() && coords_split[1].is_valid_integer()) { coords = Vector2i(coords_split[0].to_int(), coords_split[1].to_int()); } // Properties. - if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != TileSetSource::INVALID_ATLAS_COORDS) { // Create the tile if needed. if (!has_tile(coords)) { create_tile(coords); @@ -1549,7 +1550,7 @@ bool TileSetAtlasSource::_set(const StringName &p_name, const Variant &p_value) tiles[coords].next_alternative_id = p_value; } else if (components[1].is_valid_integer()) { int alternative_id = components[1].to_int(); - if (alternative_id != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) { + if (alternative_id != TileSetSource::INVALID_TILE_ALTERNATIVE) { // Create the alternative if needed ? if (!has_alternative_tile(coords, alternative_id)) { create_alternative_tile(coords, alternative_id); @@ -1594,7 +1595,7 @@ bool TileSetAtlasSource::_get(const StringName &p_name, Variant &r_ret) const { return true; } else if (components[1].is_valid_integer()) { int alternative_id = components[1].to_int(); - if (alternative_id != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE && tiles[coords].alternatives.has(alternative_id)) { + if (alternative_id != TileSetSource::INVALID_TILE_ALTERNATIVE && tiles[coords].alternatives.has(alternative_id)) { if (components.size() >= 3) { bool valid; r_ret = tiles[coords].alternatives[alternative_id]->get(components[2], &valid); @@ -1745,7 +1746,7 @@ int TileSetAtlasSource::get_tiles_count() const { } Vector2i TileSetAtlasSource::get_tile_id(int p_index) const { - ERR_FAIL_INDEX_V(p_index, tiles_ids.size(), TileSetAtlasSource::INVALID_ATLAS_COORDS); + ERR_FAIL_INDEX_V(p_index, tiles_ids.size(), TileSetSource::INVALID_ATLAS_COORDS); return tiles_ids[p_index]; } @@ -1798,7 +1799,7 @@ bool TileSetAtlasSource::can_move_tile_in_atlas(Vector2i p_atlas_coords, Vector2 for (int x = new_rect.position.x; x < new_rect.get_end().x; x++) { for (int y = new_rect.position.y; y < new_rect.get_end().y; y++) { Vector2i coords = get_tile_at_coords(Vector2i(x, y)); - if (coords != p_atlas_coords && coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) { + if (coords != p_atlas_coords && coords != TileSetSource::INVALID_ATLAS_COORDS) { return false; } } @@ -1880,7 +1881,7 @@ void TileSetAtlasSource::clear_tiles_outside_texture() { int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_id_override) { ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords))); - ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && (tiles[p_atlas_coords].alternatives.has(p_alternative_id_override) || tiles[p_atlas_coords].alternatives.has(p_alternative_id_override)), -1, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override)); + ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && tiles[p_atlas_coords].alternatives.has(p_alternative_id_override), -1, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override)); int new_alternative_id = p_alternative_id_override >= 0 ? p_alternative_id_override : tiles[p_atlas_coords].next_alternative_id; @@ -2034,6 +2035,202 @@ void TileSetAtlasSource::_compute_next_alternative_id(const Vector2i p_atlas_coo }; } +/////////////////////////////// TileSetScenesCollectionSource ////////////////////////////////////// + +void TileSetScenesCollectionSource::_compute_next_alternative_id() { + while (scenes.has(next_scene_id)) { + next_scene_id = (next_scene_id % 1073741823) + 1; // 2 ** 30 + }; +} + +int TileSetScenesCollectionSource::get_tiles_count() const { + return 1; +} + +Vector2i TileSetScenesCollectionSource::get_tile_id(int p_tile_index) const { + ERR_FAIL_COND_V(p_tile_index != 0, TileSetSource::INVALID_ATLAS_COORDS); + return Vector2i(); +} + +bool TileSetScenesCollectionSource::has_tile(Vector2i p_atlas_coords) const { + return p_atlas_coords == Vector2i(); +} + +int TileSetScenesCollectionSource::get_alternative_tiles_count(const Vector2i p_atlas_coords) const { + return scenes_ids.size(); +} + +int TileSetScenesCollectionSource::get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const { + ERR_FAIL_COND_V(p_atlas_coords != Vector2i(), TileSetSource::INVALID_TILE_ALTERNATIVE); + ERR_FAIL_INDEX_V(p_index, scenes_ids.size(), TileSetSource::INVALID_TILE_ALTERNATIVE); + + return scenes_ids[p_index]; +} + +bool TileSetScenesCollectionSource::has_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) const { + ERR_FAIL_COND_V(p_atlas_coords != Vector2i(), false); + return scenes.has(p_alternative_tile); +} + +int TileSetScenesCollectionSource::create_scene_tile(Ref<PackedScene> p_packed_scene, int p_id_override) { + ERR_FAIL_COND_V_MSG(p_id_override >= 0 && scenes.has(p_id_override), -1, vformat("Cannot create scene tile. Another scene tile exists with id %d.", p_id_override)); + + int new_scene_id = p_id_override >= 0 ? p_id_override : next_scene_id; + + scenes[new_scene_id] = SceneData(); + scenes_ids.append(new_scene_id); + scenes_ids.sort(); + set_scene_tile_scene(new_scene_id, p_packed_scene); + _compute_next_alternative_id(); + + emit_signal("changed"); + + return new_scene_id; +} + +void TileSetScenesCollectionSource::set_scene_tile_id(int p_id, int p_new_id) { + ERR_FAIL_COND(p_new_id < 0); + ERR_FAIL_COND(!has_scene_tile_id(p_id)); + ERR_FAIL_COND(has_scene_tile_id(p_new_id)); + + scenes[p_new_id] = SceneData(); + scenes[p_new_id] = scenes[p_id]; + scenes_ids.append(p_new_id); + scenes_ids.sort(); + + _compute_next_alternative_id(); + + scenes.erase(p_id); + scenes_ids.erase(p_id); + + emit_signal("changed"); +} + +void TileSetScenesCollectionSource::set_scene_tile_scene(int p_id, Ref<PackedScene> p_packed_scene) { + ERR_FAIL_COND(!scenes.has(p_id)); + if (p_packed_scene.is_valid()) { + // Make sure we have a root node. Supposed to be at 0 index because find_node_by_path() does not seem to work. + ERR_FAIL_COND(!p_packed_scene->get_state().is_valid()); + ERR_FAIL_COND(p_packed_scene->get_state()->get_node_count() < 1); + + // Check if it extends CanvasItem. + String type = p_packed_scene->get_state()->get_node_type(0); + bool extends_correct_class = ClassDB::is_parent_class(type, "Control") || ClassDB::is_parent_class(type, "Node2D"); + ERR_FAIL_COND_MSG(!extends_correct_class, vformat("Invalid PackedScene for TileSetScenesCollectionSource: %s. Root node should extend Control or Node2D.", p_packed_scene->get_path())); + + scenes[p_id].scene = p_packed_scene; + } else { + scenes[p_id].scene = Ref<PackedScene>(); + } + emit_signal("changed"); +} + +Ref<PackedScene> TileSetScenesCollectionSource::get_scene_tile_scene(int p_id) const { + ERR_FAIL_COND_V(!scenes.has(p_id), Ref<PackedScene>()); + return scenes[p_id].scene; +} + +void TileSetScenesCollectionSource::set_scene_tile_display_placeholder(int p_id, bool p_display_placeholder) { + ERR_FAIL_COND(!scenes.has(p_id)); + + scenes[p_id].display_placeholder = p_display_placeholder; + + emit_signal("changed"); +} + +bool TileSetScenesCollectionSource::get_scene_tile_display_placeholder(int p_id) const { + ERR_FAIL_COND_V(!scenes.has(p_id), false); + return scenes[p_id].display_placeholder; +} + +void TileSetScenesCollectionSource::remove_scene_tile(int p_id) { + ERR_FAIL_COND(!scenes.has(p_id)); + + scenes.erase(p_id); + scenes_ids.erase(p_id); + emit_signal("changed"); +} + +int TileSetScenesCollectionSource::get_next_scene_tile_id() const { + return next_scene_id; +} + +bool TileSetScenesCollectionSource::_set(const StringName &p_name, const Variant &p_value) { + Vector<String> components = String(p_name).split("/", true, 2); + + if (components.size() >= 2 && components[0] == "scenes" && components[1].is_valid_integer()) { + int scene_id = components[1].to_int(); + if (components.size() >= 3 && components[2] == "scene") { + if (has_scene_tile_id(scene_id)) { + set_scene_tile_scene(scene_id, p_value); + } else { + create_scene_tile(p_value, scene_id); + } + return true; + } else if (components.size() >= 3 && components[2] == "display_placeholder") { + if (!has_scene_tile_id(scene_id)) { + create_scene_tile(p_value, scene_id); + } + + return true; + } + } + + return false; +} + +bool TileSetScenesCollectionSource::_get(const StringName &p_name, Variant &r_ret) const { + Vector<String> components = String(p_name).split("/", true, 2); + + if (components.size() >= 2 && components[0] == "scenes" && components[1].is_valid_integer() && scenes.has(components[1].to_int())) { + if (components.size() >= 3 && components[2] == "scene") { + r_ret = scenes[components[1].to_int()].scene; + return true; + } else if (components.size() >= 3 && components[2] == "display_placeholder") { + r_ret = scenes[components[1].to_int()].scene; + return true; + } + } + + return false; +} + +void TileSetScenesCollectionSource::_get_property_list(List<PropertyInfo> *p_list) const { + for (int i = 0; i < scenes_ids.size(); i++) { + p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("scenes/%d/scene", scenes_ids[i]), PROPERTY_HINT_RESOURCE_TYPE, "TileSetScenesCollectionSource")); + + PropertyInfo property_info = PropertyInfo(Variant::BOOL, vformat("scenes/%d/display_placeholder", scenes_ids[i])); + if (scenes[scenes_ids[i]].display_placeholder == false) { + property_info.usage ^= PROPERTY_USAGE_STORAGE; + } + p_list->push_back(property_info); + } +} + +void TileSetScenesCollectionSource::_bind_methods() { + // Base tiles + ClassDB::bind_method(D_METHOD("get_tiles_count"), &TileSetScenesCollectionSource::get_tiles_count); + ClassDB::bind_method(D_METHOD("get_tile_id", "index"), &TileSetScenesCollectionSource::get_tile_id); + ClassDB::bind_method(D_METHOD("has_tile", "atlas_coords"), &TileSetScenesCollectionSource::has_tile); + + // Alternative tiles + ClassDB::bind_method(D_METHOD("get_alternative_tiles_count", "atlas_coords"), &TileSetScenesCollectionSource::get_alternative_tiles_count); + ClassDB::bind_method(D_METHOD("get_alternative_tile_id", "atlas_coords", "index"), &TileSetScenesCollectionSource::get_alternative_tile_id); + ClassDB::bind_method(D_METHOD("has_alternative_tile", "atlas_coords", "alternative_tile"), &TileSetScenesCollectionSource::has_alternative_tile); + + ClassDB::bind_method(D_METHOD("get_scene_tiles_count"), &TileSetScenesCollectionSource::get_scene_tiles_count); + ClassDB::bind_method(D_METHOD("get_scene_tile_id", "index"), &TileSetScenesCollectionSource::get_scene_tile_id); + ClassDB::bind_method(D_METHOD("has_scene_tile_id", "id"), &TileSetScenesCollectionSource::has_scene_tile_id); + ClassDB::bind_method(D_METHOD("create_scene_tile", "packed_scene", "id_override"), &TileSetScenesCollectionSource::create_scene_tile, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("set_scene_tile_id", "id", "new_id"), &TileSetScenesCollectionSource::set_scene_tile_id); + ClassDB::bind_method(D_METHOD("set_scene_tile_scene", "id", "packed_scene"), &TileSetScenesCollectionSource::set_scene_tile_scene); + ClassDB::bind_method(D_METHOD("get_scene_tile_scene", "id"), &TileSetScenesCollectionSource::get_scene_tile_scene); + ClassDB::bind_method(D_METHOD("set_scene_tile_display_placeholder", "id", "display_placeholder"), &TileSetScenesCollectionSource::set_scene_tile_display_placeholder); + ClassDB::bind_method(D_METHOD("get_scene_tile_display_placeholder", "id"), &TileSetScenesCollectionSource::get_scene_tile_display_placeholder); + ClassDB::bind_method(D_METHOD("remove_scene_tile", "id"), &TileSetScenesCollectionSource::remove_scene_tile); + ClassDB::bind_method(D_METHOD("get_next_scene_tile_id"), &TileSetScenesCollectionSource::get_next_scene_tile_id); +} + /////////////////////////////// TileData ////////////////////////////////////// void TileData::set_tile_set(const TileSet *p_tile_set) { @@ -2834,10 +3031,10 @@ void TileData::_bind_methods() { ADD_SIGNAL(MethodInfo("changed")); } -/////////////////////////////// TileSetAtlasPluginTerrain ////////////////////////////////////// +/////////////////////////////// TileSetPluginAtlasTerrain ////////////////////////////////////// // --- PLUGINS --- -void TileSetAtlasPluginTerrain::_draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { +void TileSetPluginAtlasTerrain::_draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { Rect2 bit_rect; bit_rect.size = Vector2(p_size) / 3; switch (p_bit) { @@ -2872,7 +3069,7 @@ void TileSetAtlasPluginTerrain::_draw_square_corner_or_side_terrain_bit(CanvasIt p_canvas_item->draw_rect(bit_rect, p_color); } -void TileSetAtlasPluginTerrain::_draw_square_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { +void TileSetPluginAtlasTerrain::_draw_square_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { PackedColorArray color_array; color_array.push_back(p_color); @@ -2919,7 +3116,7 @@ void TileSetAtlasPluginTerrain::_draw_square_corner_terrain_bit(CanvasItem *p_ca } } -void TileSetAtlasPluginTerrain::_draw_square_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { +void TileSetPluginAtlasTerrain::_draw_square_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { PackedColorArray color_array; color_array.push_back(p_color); @@ -2958,7 +3155,7 @@ void TileSetAtlasPluginTerrain::_draw_square_side_terrain_bit(CanvasItem *p_canv } } -void TileSetAtlasPluginTerrain::_draw_isometric_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { +void TileSetPluginAtlasTerrain::_draw_isometric_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { PackedColorArray color_array; color_array.push_back(p_color); @@ -3021,7 +3218,7 @@ void TileSetAtlasPluginTerrain::_draw_isometric_corner_or_side_terrain_bit(Canva } } -void TileSetAtlasPluginTerrain::_draw_isometric_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { +void TileSetPluginAtlasTerrain::_draw_isometric_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { PackedColorArray color_array; color_array.push_back(p_color); @@ -3068,7 +3265,7 @@ void TileSetAtlasPluginTerrain::_draw_isometric_corner_terrain_bit(CanvasItem *p } } -void TileSetAtlasPluginTerrain::_draw_isometric_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { +void TileSetPluginAtlasTerrain::_draw_isometric_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit) { PackedColorArray color_array; color_array.push_back(p_color); @@ -3107,7 +3304,7 @@ void TileSetAtlasPluginTerrain::_draw_isometric_side_terrain_bit(CanvasItem *p_c } } -void TileSetAtlasPluginTerrain::_draw_half_offset_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { +void TileSetPluginAtlasTerrain::_draw_half_offset_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { PackedColorArray color_array; color_array.push_back(p_color); @@ -3272,7 +3469,7 @@ void TileSetAtlasPluginTerrain::_draw_half_offset_corner_or_side_terrain_bit(Can } } -void TileSetAtlasPluginTerrain::_draw_half_offset_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { +void TileSetPluginAtlasTerrain::_draw_half_offset_corner_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { PackedColorArray color_array; color_array.push_back(p_color); @@ -3383,7 +3580,7 @@ void TileSetAtlasPluginTerrain::_draw_half_offset_corner_terrain_bit(CanvasItem } } -void TileSetAtlasPluginTerrain::_draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { +void TileSetPluginAtlasTerrain::_draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis) { PackedColorArray color_array; color_array.push_back(p_color); @@ -3498,7 +3695,7 @@ void TileSetAtlasPluginTerrain::_draw_half_offset_side_terrain_bit(CanvasItem *p } \ } -void TileSetAtlasPluginTerrain::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data) { +void TileSetPluginAtlasTerrain::draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data) { ERR_FAIL_COND(!p_tile_set); ERR_FAIL_COND(!p_tile_data); @@ -3632,9 +3829,9 @@ void TileSetAtlasPluginTerrain::draw_terrains(CanvasItem *p_canvas_item, Transfo RenderingServer::get_singleton()->canvas_item_add_set_transform(p_canvas_item->get_canvas_item(), Transform2D()); } -/////////////////////////////// TileSetAtlasPluginRendering ////////////////////////////////////// +/////////////////////////////// TileSetPluginAtlasRendering ////////////////////////////////////// -void TileSetAtlasPluginRendering::tilemap_notification(TileMap *p_tile_map, int p_what) { +void TileSetPluginAtlasRendering::tilemap_notification(TileMap *p_tile_map, int p_what) { switch (p_what) { case CanvasItem::NOTIFICATION_VISIBILITY_CHANGED: { bool visible = p_tile_map->is_visible_in_tree(); @@ -3672,7 +3869,7 @@ void TileSetAtlasPluginRendering::tilemap_notification(TileMap *p_tile_map, int } } -void TileSetAtlasPluginRendering::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation) { +void TileSetPluginAtlasRendering::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation) { ERR_FAIL_COND(!p_tile_set.is_valid()); ERR_FAIL_COND(!p_tile_set->has_source(p_atlas_source_id)); ERR_FAIL_COND(!p_tile_set->get_source(p_atlas_source_id)->has_tile(p_atlas_coords)); @@ -3687,6 +3884,12 @@ void TileSetAtlasPluginRendering::draw_tile(RID p_canvas_item, Vector2i p_positi return; } + // Check if we are in the texture, return otherwise. + Vector2i grid_size = atlas_source->get_atlas_grid_size(); + if (p_atlas_coords.x >= grid_size.x || p_atlas_coords.y >= grid_size.y) { + return; + } + // Get tile data. TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(p_atlas_coords, p_alternative_tile)); @@ -3724,7 +3927,7 @@ void TileSetAtlasPluginRendering::draw_tile(RID p_canvas_item, Vector2i p_positi } } -void TileSetAtlasPluginRendering::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) { +void TileSetPluginAtlasRendering::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) { ERR_FAIL_COND(!p_tile_map); ERR_FAIL_COND(!p_tile_map->is_inside_tree()); Ref<TileSet> tile_set = p_tile_map->get_tileset(); @@ -3858,14 +4061,14 @@ void TileSetAtlasPluginRendering::update_dirty_quadrants(TileMap *p_tile_map, Se } } -void TileSetAtlasPluginRendering::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { +void TileSetPluginAtlasRendering::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { Ref<TileSet> tile_set = p_tile_map->get_tileset(); ERR_FAIL_COND(!tile_set.is_valid()); quadrant_order_dirty = true; } -void TileSetAtlasPluginRendering::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { +void TileSetPluginAtlasRendering::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { // Free the canvas items. for (List<RID>::Element *E = p_quadrant->canvas_items.front(); E; E = E->next()) { RenderingServer::get_singleton()->free(E->get()); @@ -3879,9 +4082,60 @@ void TileSetAtlasPluginRendering::cleanup_quadrant(TileMap *p_tile_map, TileMapQ p_quadrant->occluders.clear(); } -/////////////////////////////// TileSetAtlasPluginPhysics ////////////////////////////////////// +void TileSetPluginAtlasRendering::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { + Ref<TileSet> tile_set = p_tile_map->get_tileset(); + ERR_FAIL_COND(!tile_set.is_valid()); + + if (!Engine::get_singleton()->is_editor_hint()) { + return; + } + + // Draw a placeholder for scenes needing one. + RenderingServer *rs = RenderingServer::get_singleton(); + Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size()); + for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) { + const TileMapCell &c = p_tile_map->get_cell(E_cell->get()); -void TileSetAtlasPluginPhysics::tilemap_notification(TileMap *p_tile_map, int p_what) { + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + continue; + } + + TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); + if (atlas_source) { + Vector2i grid_size = atlas_source->get_atlas_grid_size(); + if (!atlas_source->get_texture().is_valid() || c.get_atlas_coords().x >= grid_size.x || c.get_atlas_coords().y >= grid_size.y) { + // Generate a random color from the hashed values of the tiles. + Array to_hash; + to_hash.push_back(c.source_id); + to_hash.push_back(c.get_atlas_coords()); + to_hash.push_back(c.alternative_tile); + uint32_t hash = RandomPCG(to_hash.hash()).rand(); + + Color color; + color = color.from_hsv( + (float)((hash >> 24) & 0xFF) / 256.0, + Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0), + Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0), + 0.8); + + // Draw a placeholder tile. + Transform2D xform; + xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos); + rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform); + rs->canvas_item_add_circle(p_quadrant->debug_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); + } + } + } + } +} + +/////////////////////////////// TileSetPluginAtlasPhysics ////////////////////////////////////// + +void TileSetPluginAtlasPhysics::tilemap_notification(TileMap *p_tile_map, int p_what) { switch (p_what) { case CanvasItem::NOTIFICATION_TRANSFORM_CHANGED: { // Update the bodies transforms. @@ -3905,7 +4159,7 @@ void TileSetAtlasPluginPhysics::tilemap_notification(TileMap *p_tile_map, int p_ } } -void TileSetAtlasPluginPhysics::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) { +void TileSetPluginAtlasPhysics::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) { ERR_FAIL_COND(!p_tile_map); ERR_FAIL_COND(!p_tile_map->is_inside_tree()); Ref<TileSet> tile_set = p_tile_map->get_tileset(); @@ -3971,7 +4225,7 @@ void TileSetAtlasPluginPhysics::update_dirty_quadrants(TileMap *p_tile_map, Self } } -void TileSetAtlasPluginPhysics::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { +void TileSetPluginAtlasPhysics::create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { Ref<TileSet> tile_set = p_tile_map->get_tileset(); ERR_FAIL_COND(!tile_set.is_valid()); @@ -4016,7 +4270,7 @@ void TileSetAtlasPluginPhysics::create_quadrant(TileMap *p_tile_map, TileMapQuad } } -void TileSetAtlasPluginPhysics::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { +void TileSetPluginAtlasPhysics::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { // Remove a quadrant. for (int body_index = 0; body_index < p_quadrant->bodies.size(); body_index++) { PhysicsServer2D::get_singleton()->free(p_quadrant->bodies[body_index]); @@ -4024,7 +4278,7 @@ void TileSetAtlasPluginPhysics::cleanup_quadrant(TileMap *p_tile_map, TileMapQua p_quadrant->bodies.clear(); } -void TileSetAtlasPluginPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { +void TileSetPluginAtlasPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { // Draw the debug collision shapes. Ref<TileSet> tile_set = p_tile_map->get_tileset(); ERR_FAIL_COND(!tile_set.is_valid()); @@ -4071,9 +4325,9 @@ void TileSetAtlasPluginPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMap } }; -/////////////////////////////// TileSetAtlasPluginNavigation ////////////////////////////////////// +/////////////////////////////// TileSetPluginAtlasNavigation ////////////////////////////////////// -void TileSetAtlasPluginNavigation::tilemap_notification(TileMap *p_tile_map, int p_what) { +void TileSetPluginAtlasNavigation::tilemap_notification(TileMap *p_tile_map, int p_what) { switch (p_what) { case CanvasItem::NOTIFICATION_TRANSFORM_CHANGED: { if (p_tile_map->is_inside_tree()) { @@ -4098,7 +4352,7 @@ void TileSetAtlasPluginNavigation::tilemap_notification(TileMap *p_tile_map, int } } -void TileSetAtlasPluginNavigation::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) { +void TileSetPluginAtlasNavigation::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) { ERR_FAIL_COND(!p_tile_map); ERR_FAIL_COND(!p_tile_map->is_inside_tree()); Ref<TileSet> tile_set = p_tile_map->get_tileset(); @@ -4169,7 +4423,7 @@ void TileSetAtlasPluginNavigation::update_dirty_quadrants(TileMap *p_tile_map, S } } -void TileSetAtlasPluginNavigation::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { +void TileSetPluginAtlasNavigation::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { // Clear navigation shapes in the quadrant. for (Map<Vector2i, Vector<RID>>::Element *E = p_quadrant->navigation_regions.front(); E; E = E->next()) { for (int i = 0; i < E->get().size(); i++) { @@ -4183,7 +4437,7 @@ void TileSetAtlasPluginNavigation::cleanup_quadrant(TileMap *p_tile_map, TileMap p_quadrant->navigation_regions.clear(); } -void TileSetAtlasPluginNavigation::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { +void TileSetPluginAtlasNavigation::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { // Draw the debug collision shapes. Ref<TileSet> tile_set = p_tile_map->get_tileset(); ERR_FAIL_COND(!tile_set.is_valid()); @@ -4240,11 +4494,129 @@ void TileSetAtlasPluginNavigation::draw_quadrant_debug(TileMap *p_tile_map, Tile Vector<Color> colors; colors.push_back(random_variation_color); - RS::get_singleton()->canvas_item_add_polygon(p_quadrant->debug_canvas_item, vertices, colors); + rs->canvas_item_add_polygon(p_quadrant->debug_canvas_item, vertices, colors); + } + } + } + } + } + } +} + +/////////////////////////////// TileSetPluginScenesCollections ////////////////////////////////////// + +void TileSetPluginScenesCollections::update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) { + Ref<TileSet> tile_set = p_tile_map->get_tileset(); + ERR_FAIL_COND(!tile_set.is_valid()); + + SelfList<TileMapQuadrant> *q_list_element = r_dirty_quadrant_list.first(); + while (q_list_element) { + TileMapQuadrant &q = *q_list_element->self(); + + // Clear the scenes. + for (Map<Vector2i, String>::Element *E = q.scenes.front(); E; E = E->next()) { + Node *node = p_tile_map->get_node(E->get()); + if (node) { + node->queue_delete(); + } + } + + q.scenes.clear(); + + // Recreate the scenes. + for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) { + const TileMapCell &c = p_tile_map->get_cell(E_cell->get()); + + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + continue; + } + + TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); + if (scenes_collection_source) { + Ref<PackedScene> packed_scene = scenes_collection_source->get_scene_tile_scene(c.alternative_tile); + if (packed_scene.is_valid()) { + Node *scene = packed_scene->instance(); + p_tile_map->add_child(scene); + Control *scene_as_control = Object::cast_to<Control>(scene); + Node2D *scene_as_node2d = Object::cast_to<Node2D>(scene); + if (scene_as_control) { + scene_as_control->set_position(p_tile_map->map_to_world(E_cell->get()) + scene_as_control->get_position()); + } else if (scene_as_node2d) { + Transform2D xform; + xform.set_origin(p_tile_map->map_to_world(E_cell->get())); + scene_as_node2d->set_transform(xform * scene_as_node2d->get_transform()); } + q.scenes[E_cell->get()] = scene->get_name(); } } } } + + q_list_element = q_list_element->next(); + } +} + +void TileSetPluginScenesCollections::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { + // Clear the scenes. + for (Map<Vector2i, String>::Element *E = p_quadrant->scenes.front(); E; E = E->next()) { + Node *node = p_tile_map->get_node(E->get()); + if (node) { + node->queue_delete(); + } + } + + p_quadrant->scenes.clear(); +} + +void TileSetPluginScenesCollections::draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) { + Ref<TileSet> tile_set = p_tile_map->get_tileset(); + ERR_FAIL_COND(!tile_set.is_valid()); + + if (!Engine::get_singleton()->is_editor_hint()) { + return; + } + + // Draw a placeholder for scenes needing one. + RenderingServer *rs = RenderingServer::get_singleton(); + Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size()); + for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) { + const TileMapCell &c = p_tile_map->get_cell(E_cell->get()); + + TileSetSource *source; + if (tile_set->has_source(c.source_id)) { + source = *tile_set->get_source(c.source_id); + + if (!source->has_tile(c.get_atlas_coords()) || !source->has_alternative_tile(c.get_atlas_coords(), c.alternative_tile)) { + continue; + } + + TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); + if (scenes_collection_source) { + if (!scenes_collection_source->get_scene_tile_scene(c.alternative_tile).is_valid() || scenes_collection_source->get_scene_tile_display_placeholder(c.alternative_tile)) { + // Generate a random color from the hashed values of the tiles. + Array to_hash; + to_hash.push_back(c.source_id); + to_hash.push_back(c.alternative_tile); + uint32_t hash = RandomPCG(to_hash.hash()).rand(); + + Color color; + color = color.from_hsv( + (float)((hash >> 24) & 0xFF) / 256.0, + Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0), + Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0), + 0.8); + + // Draw a placeholder tile. + Transform2D xform; + xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos); + rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform); + rs->canvas_item_add_circle(p_quadrant->debug_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); + } + } + } } } diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 20cf183a20..ae80299d85 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -57,10 +57,10 @@ class TileData; // Forward-declare the plugins. class TileSetPlugin; -class TileSetAtlasPluginRendering; -class TileSetAtlasPluginPhysics; -class TileSetAtlasPluginNavigation; -class TileSetAtlasPluginTerrain; +class TileSetPluginAtlasRendering; +class TileSetPluginAtlasPhysics; +class TileSetPluginAtlasNavigation; +class TileSetPluginAtlasTerrain; class TileSet : public Resource { GDCLASS(TileSet, Resource); @@ -264,7 +264,7 @@ public: int get_next_source_id() const; int get_source_count() const; int get_source_id(int p_index) const; - int add_source(Ref<TileSetAtlasSource> p_tile_atlas_source, int p_source_id_override = -1); + int add_source(Ref<TileSetSource> p_tile_set_source, int p_source_id_override = -1); void set_source_id(int p_source_id, int p_new_id); void remove_source(int p_source_id); bool has_source(int p_source_id) const; @@ -338,6 +338,9 @@ protected: const TileSet *tile_set = nullptr; public: + static const Vector2i INVALID_ATLAS_COORDS; // Vector2i(-1, -1); + static const int INVALID_TILE_ALTERNATIVE; // -1; + // Not exposed. virtual void set_tile_set(const TileSet *p_tile_set); virtual void notify_tile_data_properties_should_change(){}; @@ -358,9 +361,6 @@ class TileSetAtlasSource : public TileSetSource { GDCLASS(TileSetAtlasSource, TileSetSource); public: - static const Vector2i INVALID_ATLAS_COORDS; // Vector2i(-1, -1); - static const int INVALID_TILE_ALTERNATIVE; // -1; - struct TileAlternativesData { Vector2i size_in_atlas = Vector2i(1, 1); Vector2i texture_offset; @@ -443,6 +443,52 @@ public: ~TileSetAtlasSource(); }; +class TileSetScenesCollectionSource : public TileSetSource { + GDCLASS(TileSetScenesCollectionSource, TileSetSource); + +private: + struct SceneData { + Ref<PackedScene> scene; + bool display_placeholder = false; + }; + Vector<int> scenes_ids; + Map<int, SceneData> scenes; + int next_scene_id = 1; + + void _compute_next_alternative_id(); + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + + static void _bind_methods(); + +public: + // Tiles. + int get_tiles_count() const override; + Vector2i get_tile_id(int p_tile_index) const override; + bool has_tile(Vector2i p_atlas_coords) const override; + + // Alternative tiles. + int get_alternative_tiles_count(const Vector2i p_atlas_coords) const override; + int get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const override; + bool has_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) const override; + + // Scenes sccessors. Lot are similar to "Alternative tiles". + int get_scene_tiles_count() { return get_alternative_tiles_count(Vector2i()); } + int get_scene_tile_id(int p_index) { return get_alternative_tile_id(Vector2i(), p_index); }; + bool has_scene_tile_id(int p_id) { return has_alternative_tile(Vector2i(), p_id); }; + int create_scene_tile(Ref<PackedScene> p_packed_scene = Ref<PackedScene>(), int p_id_override = -1); + void set_scene_tile_id(int p_id, int p_new_id); + void set_scene_tile_scene(int p_id, Ref<PackedScene> p_packed_scene); + Ref<PackedScene> get_scene_tile_scene(int p_id) const; + void set_scene_tile_display_placeholder(int p_id, bool p_packed_scene); + bool get_scene_tile_display_placeholder(int p_id) const; + void remove_scene_tile(int p_id); + int get_next_scene_tile_id() const; +}; + class TileData : public Object { GDCLASS(TileData, Object); @@ -572,8 +618,8 @@ public: virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant){}; }; -class TileSetAtlasPluginRendering : public TileSetPlugin { - GDCLASS(TileSetAtlasPluginRendering, TileSetPlugin); +class TileSetPluginAtlasRendering : public TileSetPlugin { + GDCLASS(TileSetPluginAtlasRendering, TileSetPlugin); private: static constexpr float fp_adjust = 0.00001; @@ -585,13 +631,14 @@ public: virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) override; virtual void create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override; virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override; + virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override; // Other. static void draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0)); }; -class TileSetAtlasPluginTerrain : public TileSetPlugin { - GDCLASS(TileSetAtlasPluginTerrain, TileSetPlugin); +class TileSetPluginAtlasTerrain : public TileSetPlugin { + GDCLASS(TileSetPluginAtlasTerrain, TileSetPlugin); private: static void _draw_square_corner_or_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit); @@ -607,13 +654,11 @@ private: static void _draw_half_offset_side_terrain_bit(CanvasItem *p_canvas_item, Color p_color, Vector2i p_size, TileSet::CellNeighbor p_bit, float p_overlap, TileSet::TileOffsetAxis p_offset_axis); public: - //virtual void tilemap_notification(const TileMap * p_tile_map, int p_what); - static void draw_terrains(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, const TileData *p_tile_data); }; -class TileSetAtlasPluginPhysics : public TileSetPlugin { - GDCLASS(TileSetAtlasPluginPhysics, TileSetPlugin); +class TileSetPluginAtlasPhysics : public TileSetPlugin { + GDCLASS(TileSetPluginAtlasPhysics, TileSetPlugin); public: // Tilemap updates @@ -624,14 +669,23 @@ public: virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override; }; -class TileSetAtlasPluginNavigation : public TileSetPlugin { - GDCLASS(TileSetAtlasPluginNavigation, TileSetPlugin); +class TileSetPluginAtlasNavigation : public TileSetPlugin { + GDCLASS(TileSetPluginAtlasNavigation, TileSetPlugin); public: // Tilemap updates virtual void tilemap_notification(TileMap *p_tile_map, int p_what) override; virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) override; - //virtual void create_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override; + virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override; + virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override; +}; + +class TileSetPluginScenesCollections : public TileSetPlugin { + GDCLASS(TileSetPluginScenesCollections, TileSetPlugin); + +public: + // Tilemap updates + virtual void update_dirty_quadrants(TileMap *p_tile_map, SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) override; virtual void cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override; virtual void draw_quadrant_debug(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) override; }; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index b810f9562e..da29f2ebd8 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -3148,11 +3148,11 @@ int VisualShaderNodeGroupBase::get_free_output_port_id() const { return output_ports.size(); } -void VisualShaderNodeGroupBase::set_control(Control *p_control, int p_index) { +void VisualShaderNodeGroupBase::set_ctrl_pressed(Control *p_control, int p_index) { controls[p_index] = p_control; } -Control *VisualShaderNodeGroupBase::get_control(int p_index) { +Control *VisualShaderNodeGroupBase::is_ctrl_pressed(int p_index) { ERR_FAIL_COND_V(!controls.has(p_index), nullptr); return controls[p_index]; } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 8af0fc9e44..841672294e 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -255,7 +255,8 @@ public: virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const = 0; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + // If no output is connected, the output var passed will be empty. If no input is connected and input is NIL, the input var passed will be empty. + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const = 0; virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const; @@ -610,8 +611,8 @@ public: int get_free_input_port_id() const; int get_free_output_port_id() const; - void set_control(Control *p_control, int p_index); - Control *get_control(int p_index); + void set_ctrl_pressed(Control *p_control, int p_index); + Control *is_ctrl_pressed(int p_index); void set_editable(bool p_enabled); bool is_editable() const; diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 594a494cf1..d3397fad6f 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -74,7 +74,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_constant(float p_value); float get_constant() const; @@ -104,7 +104,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_constant(int p_value); int get_constant() const; @@ -134,7 +134,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_constant(bool p_value); bool get_constant() const; @@ -164,7 +164,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_constant(Color p_value); Color get_constant() const; @@ -194,7 +194,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_constant(Vector3 p_value); Vector3 get_constant() const; @@ -224,7 +224,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_constant(Transform p_value); Transform get_constant() const; @@ -280,7 +280,7 @@ public: virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_source(Source p_source); Source get_source() const; @@ -323,7 +323,7 @@ public: virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_texture(Ref<CurveTexture> p_value); Ref<CurveTexture> get_texture() const; @@ -360,7 +360,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_source(Source p_source); Source get_source() const; @@ -455,7 +455,7 @@ public: virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_source(Source p_source); Source get_source() const; @@ -512,7 +512,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_operator(Operator p_op); Operator get_operator() const; @@ -554,7 +554,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_operator(Operator p_op); Operator get_operator() const; @@ -601,7 +601,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_operator(Operator p_op); Operator get_operator() const; @@ -647,7 +647,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_operator(Operator p_op); Operator get_operator() const; @@ -690,7 +690,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_operator(Operator p_op); Operator get_operator() const; @@ -733,7 +733,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_operator(Operator p_op); Operator get_operator() const; @@ -804,7 +804,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_function(Function p_func); Function get_function() const; @@ -846,7 +846,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_function(Function p_func); Function get_function() const; @@ -920,7 +920,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_function(Function p_func); Function get_function() const; @@ -961,7 +961,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_function(Function p_func); Function get_function() const; @@ -1002,7 +1002,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_function(Function p_func); Function get_function() const; @@ -1032,7 +1032,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeDotProduct(); }; @@ -1055,7 +1055,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVectorLen(); }; @@ -1078,7 +1078,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeDeterminant(); }; @@ -1118,7 +1118,7 @@ public: virtual Vector<StringName> get_editable_properties() const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeClamp(); }; @@ -1155,7 +1155,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_function(Function p_func); Function get_function() const; @@ -1195,7 +1195,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_function(Function p_func); Function get_function() const; @@ -1225,7 +1225,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeFaceForward(); }; @@ -1248,7 +1248,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeOuterProduct(); }; @@ -1288,7 +1288,7 @@ public: virtual Vector<StringName> get_editable_properties() const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeStep(); }; @@ -1330,7 +1330,7 @@ public: virtual Vector<StringName> get_editable_properties() const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeSmoothStep(); }; @@ -1355,7 +1355,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVectorDistance(); }; @@ -1378,7 +1378,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVectorRefract(); }; @@ -1418,7 +1418,7 @@ public: virtual Vector<StringName> get_editable_properties() const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeMix(); }; @@ -1443,7 +1443,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVectorCompose(); }; @@ -1464,7 +1464,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeTransformCompose(); }; @@ -1487,7 +1487,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVectorDecompose(); }; @@ -1508,7 +1508,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeTransformDecompose(); }; @@ -1550,7 +1550,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; virtual bool is_show_prop_names() const override; virtual bool is_use_prop_slots() const override; @@ -1616,7 +1616,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; virtual bool is_show_prop_names() const override; virtual bool is_use_prop_slots() const override; @@ -1673,7 +1673,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; virtual bool is_show_prop_names() const override; virtual bool is_use_prop_slots() const override; @@ -1716,7 +1716,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; virtual bool is_show_prop_names() const override; @@ -1758,7 +1758,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; virtual bool is_show_prop_names() const override; virtual bool is_use_prop_slots() const override; @@ -1801,7 +1801,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; virtual bool is_show_prop_names() const override; virtual bool is_use_prop_slots() const override; @@ -1858,7 +1858,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; virtual bool is_code_generated() const override; @@ -1895,7 +1895,7 @@ public: virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeTextureUniformTriplanar(); }; @@ -1918,7 +1918,7 @@ public: virtual String get_input_port_default_hint(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeTexture2DArrayUniform(); }; @@ -1941,7 +1941,7 @@ public: virtual String get_input_port_default_hint(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeTexture3DUniform(); }; @@ -1964,7 +1964,7 @@ public: virtual String get_input_port_default_hint(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeCubemapUniform(); }; @@ -2092,7 +2092,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_function(Function p_func); Function get_function() const; @@ -2153,7 +2153,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_comparison_type(ComparisonType p_type); ComparisonType get_comparison_type() const; @@ -2201,7 +2201,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; void set_op_type(OpType p_type); OpType get_op_type() const; diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index ccdc5bebd0..0a0742753f 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -357,7 +357,7 @@ World2D::World2D() { // Create and configure space2D to be more friendly with pixels than meters space = PhysicsServer2D::get_singleton()->space_create(); PhysicsServer2D::get_singleton()->space_set_active(space, true); - PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98)); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 980.0)); PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1))); PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/2d/default_linear_damp", 0.1)); ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 425546e5ca..1c2dca0259 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -1237,6 +1237,10 @@ void PhysicsServer2DSW::set_active(bool p_active) { active = p_active; }; +void PhysicsServer2DSW::set_collision_iterations(int p_iterations) { + iterations = p_iterations; +}; + void PhysicsServer2DSW::init() { doing_sync = false; last_step = 0.001; diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h index efa0784245..f1eb78a776 100644 --- a/servers/physics_2d/physics_server_2d_sw.h +++ b/servers/physics_2d/physics_server_2d_sw.h @@ -288,6 +288,8 @@ public: virtual void end_sync() override; virtual void finish() override; + virtual void set_collision_iterations(int p_iterations) override; + virtual bool is_flushing_queries() const override { return flushing_queries; } int get_process_info(ProcessInfo p_info) override; diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h index 88ac742e40..c776641699 100644 --- a/servers/physics_2d/physics_server_2d_wrap_mt.h +++ b/servers/physics_2d/physics_server_2d_wrap_mt.h @@ -303,6 +303,7 @@ public: FUNC1(free, RID); FUNC1(set_active, bool); + FUNC1(set_collision_iterations, int); virtual void init() override; virtual void step(real_t p_step) override; diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp index 9d5448dbfa..fcac0587b2 100644 --- a/servers/physics_3d/collision_solver_3d_sat.cpp +++ b/servers/physics_3d/collision_solver_3d_sat.cpp @@ -690,7 +690,7 @@ public: Vector3 axis = (p_point_B - p_point_A); real_t depth = axis.length(); - // Filter out bogus directions with a treshold and re-testing axis. + // Filter out bogus directions with a threshold and re-testing axis. if (separator->best_depth - depth > 0.001) { separator->test_axis(axis / depth); } diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 384179f2c3..7c5761cc61 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -675,6 +675,8 @@ void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_active", "active"), &PhysicsServer2D::set_active); + ClassDB::bind_method(D_METHOD("set_collision_iterations", "iterations"), &PhysicsServer2D::set_collision_iterations); + ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer2D::get_process_info); BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index a5cf3f3a46..f2836961f2 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -589,6 +589,8 @@ public: virtual bool is_flushing_queries() const = 0; + virtual void set_collision_iterations(int iterations) = 0; + enum ProcessInfo { INFO_ACTIVE_OBJECTS, INFO_COLLISION_PAIRS, diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index f7ed0205af..c96c541461 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -749,7 +749,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; actions.global_buffer_array_variable = "global_variables.data"; - actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs"; + actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs"; compiler.initialize(actions); } diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index 24ac85bb35..3a000bd06e 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -1280,6 +1280,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } else if (mnode->assign_expression != nullptr) { code += "="; code += _dump_node_code(mnode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false); + } else if (mnode->call_expression != nullptr) { + code += "."; + code += _dump_node_code(mnode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false); } } break; } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 1d67a3f1df..e09b8f15be 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -662,7 +662,7 @@ void main() { #endif #ifdef ALPHA_ANTIALIASING_EDGE_USED -// If alpha scissor is used, we must further the edge threshold, otherwise we wont get any edge feather +// If alpha scissor is used, we must further the edge threshold, otherwise we won't get any edge feather #ifdef ALPHA_SCISSOR_USED alpha_antialiasing_edge = clamp(alpha_scissor_threshold + alpha_antialiasing_edge, 0.0, 1.0); #endif diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index b38b8d803d..d488c99b6d 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -622,7 +622,7 @@ void main() { #endif #ifdef ALPHA_ANTIALIASING_EDGE_USED -// If alpha scissor is used, we must further the edge threshold, otherwise we wont get any edge feather +// If alpha scissor is used, we must further the edge threshold, otherwise we won't get any edge feather #ifdef ALPHA_SCISSOR_USED alpha_antialiasing_edge = clamp(alpha_scissor_threshold + alpha_antialiasing_edge, 0.0, 1.0); #endif diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index a61b04afc8..930ac0df70 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -845,7 +845,7 @@ public: RID_PtrOwner<Instance, true> instance_owner; - uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecesary on clustered + uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecessary on clustered virtual RID instance_allocate(); virtual void instance_initialize(RID p_rid); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index f7be6c6c60..9ac2c1918f 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -322,7 +322,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_ Vector2 point = clip_rect.position + clip_rect.size * signs[j]; if (sign_cmp == light_dir_sign) { - //both point in same direction, plot offseted + //both point in same direction, plot offsetted points[point_count++] = point + light_dir * cull_distance; } else if (sign_cmp.x == light_dir_sign.x || sign_cmp.y == light_dir_sign.y) { int next_j = (j + 1) % 4; diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index d86c44a206..27bded9810 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -982,7 +982,7 @@ public: enum InitialAction { INITIAL_ACTION_CLEAR, //start rendering and clear the whole framebuffer (region or not) (supply params) INITIAL_ACTION_CLEAR_REGION, //start rendering and clear the framebuffer in the specified region (supply params) - INITIAL_ACTION_CLEAR_REGION_CONTINUE, //countinue rendering and clear the framebuffer in the specified region (supply params) + INITIAL_ACTION_CLEAR_REGION_CONTINUE, //continue rendering and clear the framebuffer in the specified region (supply params) INITIAL_ACTION_KEEP, //start rendering, but keep attached color texture contents (depth will be cleared) INITIAL_ACTION_DROP, //start rendering, ignore what is there, just write above it INITIAL_ACTION_CONTINUE, //continue rendering (framebuffer must have been left in "continue" state as final action previously) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index a81306b97d..e92940b31a 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -3186,7 +3186,7 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const { switch (p_node->type) { case Node::TYPE_OPERATOR: { OperatorNode *op_node = (OperatorNode *)p_node; - for (int i = (1 ? op_node->op == OP_CALL : 0); i < op_node->arguments.size(); i++) { + for (int i = int(op_node->op == OP_CALL); i < op_node->arguments.size(); i++) { if (!_check_node_constness(op_node->arguments[i])) { return false; } @@ -4301,8 +4301,15 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } mn->assign_expression = assign_expression; } else if (tk.type == TK_PERIOD) { - _set_error("Nested array length() is not yet implemented"); - return nullptr; + completion_class = TAG_ARRAY; + p_block->block_tag = SubClassTag::TAG_ARRAY; + Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info); + p_block->block_tag = SubClassTag::TAG_GLOBAL; + if (!call_expression) { + return nullptr; + } + mn->datatype = call_expression->get_datatype(); + mn->call_expression = call_expression; } else if (tk.type == TK_BRACKET_OPEN) { Node *index_expression = _parse_and_reduce_expression(p_block, p_function_info); if (!index_expression) { diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index e00f4dce19..cdedc5edbb 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -546,6 +546,7 @@ public: Node *owner = nullptr; Node *index_expression = nullptr; Node *assign_expression = nullptr; + Node *call_expression = nullptr; bool has_swizzling_duplicates = false; virtual DataType get_datatype() const { return datatype; } diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 49990407e3..a9601fd661 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -873,10 +873,10 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } else if (i == RS::ARRAY_BONES) { switch (p_arrays[i].get_type()) { case Variant::PACKED_INT32_ARRAY: { - Vector<Vector3> vertexes = p_arrays[RS::ARRAY_VERTEX]; + Vector<Vector3> vertices = p_arrays[RS::ARRAY_VERTEX]; Vector<int32_t> bones = p_arrays[i]; int32_t bone_8_group_count = bones.size() / (ARRAY_WEIGHTS_SIZE * 2); - int32_t vertex_count = vertexes.size(); + int32_t vertex_count = vertices.size(); if (vertex_count == bone_8_group_count) { format |= RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS; } diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 8b03565291..daed612b02 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -987,7 +987,7 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, while (i < ranges.size()) { int j = i + 1; while (j < ranges.size()) { - if (Math::is_equal_approx(ranges[i].y, ranges[j].x, UNIT_EPSILON)) { + if (Math::is_equal_approx(ranges[i].y, ranges[j].x, (real_t)UNIT_EPSILON)) { ranges.write[i].y = ranges[j].y; ranges.remove(j); continue; diff --git a/tests/test_color.h b/tests/test_color.h index eb8d7dcbd4..ad4a7cd3f2 100644 --- a/tests/test_color.h +++ b/tests/test_color.h @@ -101,13 +101,13 @@ TEST_CASE("[Color] Reading methods") { const Color dark_blue = Color(0, 0, 0.5, 0.4); CHECK_MESSAGE( - Math::is_equal_approx(dark_blue.get_h(), 240 / 360.0), + Math::is_equal_approx(dark_blue.get_h(), 240.0f / 360.0f), "The returned HSV hue should match the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(dark_blue.get_s(), 1), + Math::is_equal_approx(dark_blue.get_s(), 1.0f), "The returned HSV saturation should match the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(dark_blue.get_v(), 0.5), + Math::is_equal_approx(dark_blue.get_v(), 0.5f), "The returned HSV value should match the expected value."); } diff --git a/tests/test_curve.h b/tests/test_curve.h index 019941a7ce..3055cfd97b 100644 --- a/tests/test_curve.h +++ b/tests/test_curve.h @@ -83,13 +83,13 @@ TEST_CASE("[Curve] Custom curve with free tangents") { Math::is_equal_approx(curve->interpolate(-0.1), 0), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.1), 0.352), + Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.352), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.4), 0.352), + Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.352), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.7), 0.896), + Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.896), "Custom free curve should return the expected value at offset 0.1."); CHECK_MESSAGE( Math::is_equal_approx(curve->interpolate(1), 1), @@ -102,13 +102,13 @@ TEST_CASE("[Curve] Custom curve with free tangents") { Math::is_equal_approx(curve->interpolate_baked(-0.1), 0), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.1), 0.352), + Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.352), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.4), 0.352), + Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.352), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.7), 0.896), + Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.896), "Custom free curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( Math::is_equal_approx(curve->interpolate_baked(1), 1), @@ -172,13 +172,13 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { Math::is_equal_approx(curve->interpolate(-0.1), 0), "Custom linear curve should return the expected value at offset -0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.1), 0.4), + Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.4), "Custom linear curve should return the expected value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.4), 0.4), + Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.4), "Custom linear curve should return the expected value at offset 0.4."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.7), 0.8), + Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.8), "Custom linear curve should return the expected value at offset 0.7."); CHECK_MESSAGE( Math::is_equal_approx(curve->interpolate(1), 1), @@ -191,13 +191,13 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { Math::is_equal_approx(curve->interpolate_baked(-0.1), 0), "Custom linear curve should return the expected baked value at offset -0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.1), 0.4), + Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.4), "Custom linear curve should return the expected baked value at offset 0.1."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.4), 0.4), + Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.4), "Custom linear curve should return the expected baked value at offset 0.4."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.7), 0.8), + Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8), "Custom linear curve should return the expected baked value at offset 0.7."); CHECK_MESSAGE( Math::is_equal_approx(curve->interpolate_baked(1), 1), @@ -210,10 +210,10 @@ TEST_CASE("[Curve] Custom curve with linear tangents") { curve->remove_point(10); ERR_PRINT_ON; CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate(0.7), 0.8), + Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.8), "Custom free curve should return the expected value at offset 0.7 after removing point at invalid index 10."); CHECK_MESSAGE( - Math::is_equal_approx(curve->interpolate_baked(0.7), 0.8), + Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8), "Custom free curve should return the expected baked value at offset 0.7 after removing point at invalid index 10."); } } // namespace TestCurve diff --git a/tests/test_expression.h b/tests/test_expression.h index 0ef60d1a19..cb1d29389f 100644 --- a/tests/test_expression.h +++ b/tests/test_expression.h @@ -83,42 +83,42 @@ TEST_CASE("[Expression] Floating-point arithmetic") { expression.parse("-123.456") == OK, "Float identity should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), -123.456), + Math::is_equal_approx(double(expression.execute()), -123.456), "Float identity should return the expected result."); CHECK_MESSAGE( expression.parse("2.0 + 3.0") == OK, "Float addition should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), 5), + Math::is_equal_approx(double(expression.execute()), 5), "Float addition should return the expected result."); CHECK_MESSAGE( expression.parse("3.0 / 10") == OK, "Float / integer division should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), 0.3), + Math::is_equal_approx(double(expression.execute()), 0.3), "Float / integer division should return the expected result."); CHECK_MESSAGE( expression.parse("3 / 10.0") == OK, "Basic integer / float division should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), 0.3), + Math::is_equal_approx(double(expression.execute()), 0.3), "Basic integer / float division should return the expected result."); CHECK_MESSAGE( expression.parse("3.0 / 10.0") == OK, "Float / float division should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), 0.3), + Math::is_equal_approx(double(expression.execute()), 0.3), "Float / float division should return the expected result."); CHECK_MESSAGE( expression.parse("2.5 * (6.0 + 14.25) / 2.0 - 5.12345") == OK, "Float multiplication-addition-subtraction-division should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), 20.18905), + Math::is_equal_approx(double(expression.execute()), 20.18905), "Float multiplication-addition-subtraction-division should return the expected result."); } @@ -129,7 +129,7 @@ TEST_CASE("[Expression] Scientific notation") { expression.parse("2.e5") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), 200'000), + Math::is_equal_approx(double(expression.execute()), 200'000), "The expression should return the expected result."); // The middle "e" is ignored here. @@ -137,14 +137,14 @@ TEST_CASE("[Expression] Scientific notation") { expression.parse("2e5") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), 25), + Math::is_equal_approx(double(expression.execute()), 25), "The expression should return the expected result."); CHECK_MESSAGE( expression.parse("2e.5") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), 2), + Math::is_equal_approx(double(expression.execute()), 2), "The expression should return the expected result."); } @@ -176,14 +176,14 @@ TEST_CASE("[Expression] Built-in functions") { expression.parse("snapped(sin(0.5), 0.01)") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(float(expression.execute()), 0.48), + Math::is_equal_approx(double(expression.execute()), 0.48), "`snapped(sin(0.5), 0.01)` should return the expected result."); CHECK_MESSAGE( expression.parse("pow(2.0, -2500)") == OK, "The expression should parse successfully."); CHECK_MESSAGE( - Math::is_zero_approx(float(expression.execute())), + Math::is_zero_approx(double(expression.execute())), "`pow(2.0, -2500)` should return the expected result (asymptotically zero)."); } @@ -410,7 +410,7 @@ TEST_CASE("[Expression] Unusual expressions") { "The expression should parse successfully."); ERR_PRINT_OFF; CHECK_MESSAGE( - Math::is_inf(float(expression.execute())), + Math::is_inf(double(expression.execute())), "`-25.4 / 0` should return inf."); ERR_PRINT_ON; diff --git a/tests/test_geometry_2d.h b/tests/test_geometry_2d.h index c9313f3625..32d4114a1c 100644 --- a/tests/test_geometry_2d.h +++ b/tests/test_geometry_2d.h @@ -50,7 +50,7 @@ TEST_CASE("[Geometry2D] Point in circle") { CHECK(Geometry2D::is_point_in_circle(Vector2(7, -42), Vector2(4, -40), 3.7)); CHECK_FALSE(Geometry2D::is_point_in_circle(Vector2(7, -42), Vector2(4, -40), 3.5)); - // This tests points on the edge of the circle. They are treated as beeing inside the circle. + // This tests points on the edge of the circle. They are treated as being inside the circle. // In `is_point_in_triangle` and `is_point_in_polygon` they are treated as being outside, so in order the make // the behaviour consistent this may change in the future (see issue #44717 and PR #44274). CHECK(Geometry2D::is_point_in_circle(Vector2(1.0, 0.0), Vector2(0, 0), 1.0)); @@ -65,7 +65,7 @@ TEST_CASE("[Geometry2D] Point in triangle") { CHECK(Geometry2D::is_point_in_triangle(Vector2(-3, -2.5), Vector2(-1, -4), Vector2(-3, -2), Vector2(-5, -4))); CHECK_FALSE(Geometry2D::is_point_in_triangle(Vector2(0, 0), Vector2(1, 4), Vector2(3, 2), Vector2(5, 4))); - // This tests points on the edge of the triangle. They are treated as beeing outside the triangle. + // This tests points on the edge of the triangle. They are treated as being outside the triangle. // In `is_point_in_circle` they are treated as being inside, so in order the make // the behaviour consistent this may change in the future (see issue #44717 and PR #44274). CHECK_FALSE(Geometry2D::is_point_in_triangle(Vector2(1, 1), Vector2(-1, 1), Vector2(0, -1), Vector2(1, 1))); @@ -95,7 +95,7 @@ TEST_CASE("[Geometry2D] Point in polygon") { CHECK(Geometry2D::is_point_in_polygon(Vector2(370, 55), p)); CHECK(Geometry2D::is_point_in_polygon(Vector2(-160, 190), p)); - // This tests points on the edge of the polygon. They are treated as beeing outside the polygon. + // This tests points on the edge of the polygon. They are treated as being outside the polygon. // In `is_point_in_circle` they are treated as being inside, so in order the make // the behaviour consistent this may change in the future (see issue #44717 and PR #44274). CHECK_FALSE(Geometry2D::is_point_in_polygon(Vector2(68, 112), p)); @@ -227,7 +227,7 @@ TEST_CASE("[Geometry2D] Polygon intersection") { CHECK(r[0][2].is_equal_approx(Point2(160.52632, 92.63157))); } - SUBCASE("[Geometry2D] Intersection with one polygon beeing completly inside the other polygon") { + SUBCASE("[Geometry2D] Intersection with one polygon being completely inside the other polygon") { b.push_back(Point2(80, 100)); b.push_back(Point2(50, 50)); b.push_back(Point2(150, 50)); diff --git a/tests/test_json.h b/tests/test_json.h index e652a8fced..f1cb4799dc 100644 --- a/tests/test_json.h +++ b/tests/test_json.h @@ -80,7 +80,7 @@ TEST_CASE("[JSON] Parsing single data types") { err_line == 0, "Parsing an integer number as JSON should parse successfully."); CHECK_MESSAGE( - Math::is_equal_approx(result, 123'456), + (int)result == 123'456, "Parsing an integer number as JSON should return the expected value."); json.parse("0.123456", result, err_str, err_line); @@ -155,7 +155,7 @@ TEST_CASE("[JSON] Parsing objects (dictionaries)") { dictionary["bugs"] == Variant(), "The parsed JSON should contain the expected values."); CHECK_MESSAGE( - Math::is_equal_approx(Dictionary(dictionary["apples"])["blue"], -20), + (int)Dictionary(dictionary["apples"])["blue"] == -20, "The parsed JSON should contain the expected values."); CHECK_MESSAGE( dictionary["empty_object"].hash() == Dictionary().hash(), diff --git a/tests/test_main.cpp b/tests/test_main.cpp index d06d604532..67fb38aa86 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -74,8 +74,10 @@ #include "test_shader_lang.h" #include "test_string.h" #include "test_text_server.h" +#include "test_translation.h" #include "test_validate_testing.h" #include "test_variant.h" +#include "test_vector.h" #include "test_xml_parser.h" #include "modules/modules_tests.gen.h" diff --git a/tests/test_math.cpp b/tests/test_math.cpp index 26c2aa2088..85cfdf7d2c 100644 --- a/tests/test_math.cpp +++ b/tests/test_math.cpp @@ -529,7 +529,7 @@ MainLoop *test() { ERR_FAIL_COND_V_MSG(!fa, nullptr, "Could not open file: " + test); Vector<uint8_t> buf; - int flen = fa->get_len(); + uint64_t flen = fa->get_len(); buf.resize(fa->get_len() + 1); fa->get_buffer(buf.ptrw(), flen); buf.write[flen] = 0; diff --git a/tests/test_physics_2d.cpp b/tests/test_physics_2d.cpp index 25b2871890..a9e2e92b34 100644 --- a/tests/test_physics_2d.cpp +++ b/tests/test_physics_2d.cpp @@ -320,7 +320,7 @@ public: ps->space_set_active(space, true); ps->set_active(true); ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, Vector2(0, 1)); - ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, 98); + ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, 980); { RID vp = vs->viewport_create(); diff --git a/tests/test_rect2.h b/tests/test_rect2.h index b94a8b7d05..821aa69970 100644 --- a/tests/test_rect2.h +++ b/tests/test_rect2.h @@ -144,7 +144,7 @@ TEST_CASE("[Rect2] Absolute coordinates") { "abs() should return the expected Rect2."); } -TEST_CASE("[Rect2] Intersecton") { +TEST_CASE("[Rect2] Intersection") { CHECK_MESSAGE( Rect2(0, 100, 1280, 720).intersection(Rect2(0, 300, 100, 100)).is_equal_approx(Rect2(0, 300, 100, 100)), "intersection() with fully enclosed Rect2 should return the expected result."); @@ -312,19 +312,19 @@ TEST_CASE("[Rect2i] Basic setters") { TEST_CASE("[Rect2i] Area getters") { CHECK_MESSAGE( - Math::is_equal_approx(Rect2i(0, 100, 1280, 720).get_area(), 921'600), + Rect2i(0, 100, 1280, 720).get_area() == 921'600, "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Rect2i(0, 100, -1280, -720).get_area(), 921'600), + Rect2i(0, 100, -1280, -720).get_area() == 921'600, "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Rect2i(0, 100, 1280, -720).get_area(), -921'600), + Rect2i(0, 100, 1280, -720).get_area() == -921'600, "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_equal_approx(Rect2i(0, 100, -1280, 720).get_area(), -921'600), + Rect2i(0, 100, -1280, 720).get_area() == -921'600, "get_area() should return the expected value."); CHECK_MESSAGE( - Math::is_zero_approx(Rect2i(0, 100, 0, 720).get_area()), + Rect2i(0, 100, 0, 720).get_area() == 0, "get_area() should return the expected value."); CHECK_MESSAGE( diff --git a/tests/test_string.h b/tests/test_string.h index 486c17dbbd..6e214574af 100644 --- a/tests/test_string.h +++ b/tests/test_string.h @@ -299,6 +299,7 @@ TEST_CASE("[String] hex_encode_buffer") { TEST_CASE("[String] Substr") { String s = "Killer Baby"; CHECK(s.substr(3, 4) == "ler "); + CHECK(s.substr(3) == "ler Baby"); } TEST_CASE("[String] Find") { @@ -1252,8 +1253,10 @@ TEST_CASE("[String] Trim") { TEST_CASE("[String] Right/Left") { String s = "aaaTestbbb"; // ^ - CHECK(s.right(6) == "tbbb"); + CHECK(s.right(6) == "estbbb"); + CHECK(s.right(-6) == "tbbb"); CHECK(s.left(6) == "aaaTes"); + CHECK(s.left(-6) == "aaaT"); } TEST_CASE("[String] Repeat") { diff --git a/tests/test_translation.h b/tests/test_translation.h new file mode 100644 index 0000000000..52ff49bf9b --- /dev/null +++ b/tests/test_translation.h @@ -0,0 +1,150 @@ +/*************************************************************************/ +/* test_translation.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEST_TRANSLATION_H +#define TEST_TRANSLATION_H + +#include "core/string/optimized_translation.h" +#include "core/string/translation.h" +#include "core/string/translation_po.h" + +#include "thirdparty/doctest/doctest.h" + +namespace TestTranslation { + +TEST_CASE("[Translation] Messages") { + Ref<Translation> translation = memnew(Translation); + translation->set_locale("fr"); + translation->add_message("Hello", "Bonjour"); + CHECK(translation->get_message("Hello") == "Bonjour"); + + translation->erase_message("Hello"); + // The message no longer exists, so it returns an empty string instead. + CHECK(translation->get_message("Hello") == ""); + + List<StringName> messages; + translation->get_message_list(&messages); + CHECK(translation->get_message_count() == 0); + CHECK(messages.size() == 0); + + translation->add_message("Hello2", "Bonjour2"); + translation->add_message("Hello3", "Bonjour3"); + messages.clear(); + translation->get_message_list(&messages); + CHECK(translation->get_message_count() == 2); + CHECK(messages.size() == 2); + // Messages are stored in a Map, don't assume ordering. + CHECK(messages.find("Hello2")); + CHECK(messages.find("Hello3")); +} + +TEST_CASE("[TranslationPO] Messages with context") { + Ref<TranslationPO> translation = memnew(TranslationPO); + translation->set_locale("fr"); + translation->add_message("Hello", "Bonjour"); + translation->add_message("Hello", "Salut", "friendly"); + CHECK(translation->get_message("Hello") == "Bonjour"); + CHECK(translation->get_message("Hello", "friendly") == "Salut"); + CHECK(translation->get_message("Hello", "nonexistent_context") == ""); + + // Only remove the message for the default context, not the "friendly" context. + translation->erase_message("Hello"); + // The message no longer exists, so it returns an empty string instead. + CHECK(translation->get_message("Hello") == ""); + CHECK(translation->get_message("Hello", "friendly") == "Salut"); + CHECK(translation->get_message("Hello", "nonexistent_context") == ""); + + List<StringName> messages; + translation->get_message_list(&messages); + + // `get_message_count()` takes all contexts into account. + CHECK(translation->get_message_count() == 1); + // Only the default context is taken into account. + // Since "Hello" is now only present in a non-default context, it is not counted in the list of messages. + CHECK(messages.size() == 0); + + translation->add_message("Hello2", "Bonjour2"); + translation->add_message("Hello2", "Salut2", "friendly"); + translation->add_message("Hello3", "Bonjour3"); + messages.clear(); + translation->get_message_list(&messages); + + // `get_message_count()` takes all contexts into account. + CHECK(translation->get_message_count() == 4); + // Only the default context is taken into account. + CHECK(messages.size() == 2); + // Messages are stored in a Map, don't assume ordering. + CHECK(messages.find("Hello2")); + CHECK(messages.find("Hello3")); +} + +TEST_CASE("[TranslationPO] Plural messages") { + Ref<TranslationPO> translation = memnew(TranslationPO); + translation->set_locale("fr"); + translation->set_plural_rule("Plural-Forms: nplurals=2; plural=(n >= 2);"); + CHECK(translation->get_plural_forms() == 2); + + PackedStringArray plurals; + plurals.push_back("Il y a %d pomme"); + plurals.push_back("Il y a %d pommes"); + translation->add_plural_message("There are %d apples", plurals); + ERR_PRINT_OFF; + // This is invalid, as the number passed to `get_plural_message()` may not be negative. + CHECK(vformat(translation->get_plural_message("There are %d apples", "", -1), -1) == ""); + ERR_PRINT_ON; + CHECK(vformat(translation->get_plural_message("There are %d apples", "", 0), 0) == "Il y a 0 pomme"); + CHECK(vformat(translation->get_plural_message("There are %d apples", "", 1), 1) == "Il y a 1 pomme"); + CHECK(vformat(translation->get_plural_message("There are %d apples", "", 2), 2) == "Il y a 2 pommes"); +} + +TEST_CASE("[OptimizedTranslation] Generate from Translation and read messages") { + Ref<Translation> translation = memnew(Translation); + translation->set_locale("fr"); + translation->add_message("Hello", "Bonjour"); + translation->add_message("Hello2", "Bonjour2"); + translation->add_message("Hello3", "Bonjour3"); + + Ref<OptimizedTranslation> optimized_translation = memnew(OptimizedTranslation); + optimized_translation->generate(translation); + CHECK(optimized_translation->get_message("Hello") == "Bonjour"); + CHECK(optimized_translation->get_message("Hello2") == "Bonjour2"); + CHECK(optimized_translation->get_message("Hello3") == "Bonjour3"); + CHECK(optimized_translation->get_message("DoesNotExist") == ""); + + List<StringName> messages; + // `get_message_list()` can't return the list of messages stored in an OptimizedTranslation. + optimized_translation->get_message_list(&messages); + CHECK(optimized_translation->get_message_count() == 0); + CHECK(messages.size() == 0); +} + +} // namespace TestTranslation + +#endif // TEST_TRANSLATION_H diff --git a/tests/test_vector.h b/tests/test_vector.h new file mode 100644 index 0000000000..02c56e59f6 --- /dev/null +++ b/tests/test_vector.h @@ -0,0 +1,496 @@ +/*************************************************************************/ +/* test_vector.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TEST_VECTOR_H +#define TEST_VECTOR_H + +#include "core/templates/vector.h" + +#include "tests/test_macros.h" + +namespace TestVector { + +TEST_CASE("[Vector] Push back and append") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + // Alias for `push_back`. + vector.append(4); + + CHECK(vector[0] == 0); + CHECK(vector[1] == 1); + CHECK(vector[2] == 2); + CHECK(vector[3] == 3); + CHECK(vector[4] == 4); +} + +TEST_CASE("[Vector] Append array") { + Vector<int> vector; + vector.push_back(1); + vector.push_back(2); + + Vector<int> vector_other; + vector_other.push_back(128); + vector_other.push_back(129); + vector.append_array(vector_other); + + CHECK(vector.size() == 4); + CHECK(vector[0] == 1); + CHECK(vector[1] == 2); + CHECK(vector[2] == 128); + CHECK(vector[3] == 129); +} + +TEST_CASE("[Vector] Insert") { + Vector<int> vector; + vector.insert(0, 2); + vector.insert(0, 8); + vector.insert(2, 5); + vector.insert(1, 5); + vector.insert(0, -2); + + CHECK(vector.size() == 5); + CHECK(vector[0] == -2); + CHECK(vector[1] == 8); + CHECK(vector[2] == 5); + CHECK(vector[3] == 2); + CHECK(vector[4] == 5); +} + +TEST_CASE("[Vector] Ordered insert") { + Vector<int> vector; + vector.ordered_insert(2); + vector.ordered_insert(8); + vector.ordered_insert(5); + vector.ordered_insert(5); + vector.ordered_insert(-2); + + CHECK(vector.size() == 5); + CHECK(vector[0] == -2); + CHECK(vector[1] == 2); + CHECK(vector[2] == 5); + CHECK(vector[3] == 5); + CHECK(vector[4] == 8); +} + +TEST_CASE("[Vector] Insert + Ordered insert") { + Vector<int> vector; + vector.ordered_insert(2); + vector.ordered_insert(8); + vector.insert(0, 5); + vector.ordered_insert(5); + vector.insert(1, -2); + + CHECK(vector.size() == 5); + CHECK(vector[0] == 5); + CHECK(vector[1] == -2); + CHECK(vector[2] == 2); + CHECK(vector[3] == 5); + CHECK(vector[4] == 8); +} + +TEST_CASE("[Vector] Fill large array and modify it") { + Vector<int> vector; + vector.resize(1'000'000); + vector.fill(0x60d07); + + vector.write[200] = 0; + CHECK(vector.size() == 1'000'000); + CHECK(vector[0] == 0x60d07); + CHECK(vector[200] == 0); + CHECK(vector[499'999] == 0x60d07); + CHECK(vector[999'999] == 0x60d07); + vector.remove(200); + CHECK(vector[200] == 0x60d07); + + vector.clear(); + CHECK(vector.size() == 0); +} + +TEST_CASE("[Vector] Copy creation") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + Vector<int> vector_other = Vector<int>(vector); + vector_other.remove(0); + CHECK(vector_other[0] == 1); + CHECK(vector_other[1] == 2); + CHECK(vector_other[2] == 3); + CHECK(vector_other[3] == 4); + + // Make sure the original vector isn't modified. + CHECK(vector[0] == 0); + CHECK(vector[1] == 1); + CHECK(vector[2] == 2); + CHECK(vector[3] == 3); + CHECK(vector[4] == 4); +} + +TEST_CASE("[Vector] Duplicate") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + Vector<int> vector_other = vector.duplicate(); + vector_other.remove(0); + CHECK(vector_other[0] == 1); + CHECK(vector_other[1] == 2); + CHECK(vector_other[2] == 3); + CHECK(vector_other[3] == 4); + + // Make sure the original vector isn't modified. + CHECK(vector[0] == 0); + CHECK(vector[1] == 1); + CHECK(vector[2] == 2); + CHECK(vector[3] == 3); + CHECK(vector[4] == 4); +} + +TEST_CASE("[Vector] Get, set") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + CHECK(vector.get(0) == 0); + CHECK(vector.get(1) == 1); + vector.set(2, 256); + CHECK(vector.get(2) == 256); + CHECK(vector.get(3) == 3); + + ERR_PRINT_OFF; + // Invalid (but should not crash): setting out of bounds. + vector.set(6, 500); + ERR_PRINT_ON; + + CHECK(vector.get(4) == 4); +} + +TEST_CASE("[Vector] To byte array") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(-1); + vector.push_back(2008); + vector.push_back(999999999); + + Vector<uint8_t> byte_array = vector.to_byte_array(); + CHECK(byte_array.size() == 16); + // vector[0] + CHECK(byte_array[0] == 0); + CHECK(byte_array[1] == 0); + CHECK(byte_array[2] == 0); + CHECK(byte_array[3] == 0); + + // vector[1] + CHECK(byte_array[4] == 255); + CHECK(byte_array[5] == 255); + CHECK(byte_array[6] == 255); + CHECK(byte_array[7] == 255); + + // vector[2] + CHECK(byte_array[8] == 216); + CHECK(byte_array[9] == 7); + CHECK(byte_array[10] == 0); + CHECK(byte_array[11] == 0); + + // vector[3] + CHECK(byte_array[12] == 255); + CHECK(byte_array[13] == 201); + CHECK(byte_array[14] == 154); + CHECK(byte_array[15] == 59); +} + +TEST_CASE("[Vector] Subarray") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + Vector<int> subarray1 = vector.subarray(1, 2); + CHECK(subarray1.size() == 2); + CHECK(subarray1[0] == 1); + CHECK(subarray1[1] == 2); + + Vector<int> subarray2 = vector.subarray(1, -1); + CHECK(subarray2.size() == 4); + CHECK(subarray2[0] == 1); + CHECK(subarray2[1] == 2); + CHECK(subarray2[2] == 3); + CHECK(subarray2[3] == 4); + + Vector<int> subarray3 = vector.subarray(-2, -1); + CHECK(subarray3.size() == 2); + CHECK(subarray3[0] == 3); + CHECK(subarray3[1] == 4); + + Vector<int> subarray4 = vector.subarray(-3, 3); + CHECK(subarray4.size() == 2); + CHECK(subarray4[0] == 2); + CHECK(subarray4[1] == 3); +} + +TEST_CASE("[Vector] Find, has") { + Vector<int> vector; + vector.push_back(3); + vector.push_back(1); + vector.push_back(4); + vector.push_back(0); + vector.push_back(2); + + CHECK(vector[0] == 3); + CHECK(vector[1] == 1); + CHECK(vector[2] == 4); + CHECK(vector[3] == 0); + CHECK(vector[4] == 2); + + CHECK(vector.find(0) == 3); + CHECK(vector.find(1) == 1); + CHECK(vector.find(2) == 4); + CHECK(vector.find(3) == 0); + CHECK(vector.find(4) == 2); + + CHECK(vector.find(-1) == -1); + CHECK(vector.find(5) == -1); + + CHECK(vector.has(0)); + CHECK(vector.has(1)); + CHECK(vector.has(2)); + CHECK(vector.has(3)); + CHECK(vector.has(4)); + + CHECK(!vector.has(-1)); + CHECK(!vector.has(5)); +} + +TEST_CASE("[Vector] Remove") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + vector.remove(0); + + CHECK(vector[0] == 1); + CHECK(vector[1] == 2); + CHECK(vector[2] == 3); + CHECK(vector[3] == 4); + + vector.remove(2); + + CHECK(vector[0] == 1); + CHECK(vector[1] == 2); + CHECK(vector[2] == 4); + + vector.remove(1); + + CHECK(vector[0] == 1); + CHECK(vector[1] == 4); + + vector.remove(0); + + CHECK(vector[0] == 4); +} + +TEST_CASE("[Vector] Remove and find") { + Vector<int> vector; + vector.push_back(0); + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + + CHECK(vector.size() == 5); + + vector.remove(0); + + CHECK(vector.size() == 4); + + CHECK(vector.find(0) == -1); + CHECK(vector.find(1) != -1); + CHECK(vector.find(2) != -1); + CHECK(vector.find(3) != -1); + CHECK(vector.find(4) != -1); + + vector.remove(vector.find(3)); + + CHECK(vector.size() == 3); + + CHECK(vector.find(3) == -1); + CHECK(vector.find(1) != -1); + CHECK(vector.find(2) != -1); + CHECK(vector.find(4) != -1); + + vector.remove(vector.find(2)); + + CHECK(vector.size() == 2); + + CHECK(vector.find(2) == -1); + CHECK(vector.find(1) != -1); + CHECK(vector.find(4) != -1); + + vector.remove(vector.find(4)); + + CHECK(vector.size() == 1); + + CHECK(vector.find(4) == -1); + CHECK(vector.find(1) != -1); + + vector.remove(0); + + CHECK(vector.is_empty()); + CHECK(vector.size() == 0); +} + +TEST_CASE("[Vector] Erase") { + Vector<int> vector; + vector.push_back(1); + vector.push_back(3); + vector.push_back(0); + vector.push_back(2); + vector.push_back(4); + + CHECK(vector.find(2) == 3); + + vector.erase(2); + + CHECK(vector.find(2) == -1); + CHECK(vector.size() == 4); +} + +TEST_CASE("[Vector] Size, resize, reserve") { + Vector<int> vector; + CHECK(vector.is_empty()); + CHECK(vector.size() == 0); + + vector.resize(10); + + CHECK(vector.size() == 10); + + vector.resize(5); + + CHECK(vector.size() == 5); + + vector.remove(0); + vector.remove(0); + vector.remove(0); + + CHECK(vector.size() == 2); + + vector.clear(); + + CHECK(vector.size() == 0); + CHECK(vector.is_empty()); + + vector.push_back(0); + vector.push_back(0); + vector.push_back(0); + + CHECK(vector.size() == 3); + + vector.push_back(0); + + CHECK(vector.size() == 4); +} + +TEST_CASE("[Vector] Sort") { + Vector<int> vector; + vector.push_back(2); + vector.push_back(8); + vector.push_back(-4); + vector.push_back(5); + vector.sort(); + + CHECK(vector.size() == 4); + CHECK(vector[0] == -4); + CHECK(vector[1] == 2); + CHECK(vector[2] == 5); + CHECK(vector[3] == 8); +} + +TEST_CASE("[Vector] Sort custom") { + Vector<String> vector; + vector.push_back("world"); + vector.push_back("World"); + vector.push_back("Hello"); + vector.push_back("10Hello"); + vector.push_back("12Hello"); + vector.push_back("01Hello"); + vector.push_back("1Hello"); + vector.push_back(".Hello"); + vector.sort_custom<NaturalNoCaseComparator>(); + + CHECK(vector.size() == 8); + CHECK(vector[0] == ".Hello"); + CHECK(vector[1] == "01Hello"); + CHECK(vector[2] == "1Hello"); + CHECK(vector[3] == "10Hello"); + CHECK(vector[4] == "12Hello"); + CHECK(vector[5] == "Hello"); + CHECK(vector[6] == "world"); + CHECK(vector[7] == "World"); +} + +TEST_CASE("[Vector] Operators") { + Vector<int> vector; + vector.push_back(2); + vector.push_back(8); + vector.push_back(-4); + vector.push_back(5); + + Vector<int> vector_other; + vector_other.push_back(2); + vector_other.push_back(8); + vector_other.push_back(-4); + vector_other.push_back(5); + + CHECK(vector == vector_other); + + vector_other.push_back(10); + CHECK(vector != vector_other); +} + +} // namespace TestVector + +#endif // TEST_VECTOR_H diff --git a/thirdparty/README.md b/thirdparty/README.md index c6d8d06ee5..1e7d990dda 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -72,7 +72,7 @@ Files extracted from upstream: - All cpp files listed in `modules/raycast/godot_update_embree.py` - All header files in the directories listed in `modules/raycast/godot_update_embree.py` -The `modules/raycast/godot_update_embree.py`script can be used to pull the +The `modules/raycast/godot_update_embree.py` script can be used to pull the relevant files from the latest Embree-aarch64 release and apply some automatic changes. Some changes have been made in order to remove exceptions and fix minor build errors. @@ -137,6 +137,10 @@ Files extracted from upstream source: * Upstream: https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/ * Version: ? (pre-2014 commit when DroidSansJapanese.ttf was obsoleted) * License: Apache 2.0 +- `OpenSans_SemiBold.ttf`: + * Upstream: https://fonts.google.com/specimen/Open+Sans + * Version: 1.10 (downloaded from Google Fonts in February 2021) + * License: Apache 2.0 - `Tamsyn*.png`: * Upstream: http://www.fial.com/~scott/tamsyn-font/ * Version: 1.11 (2015) diff --git a/thirdparty/fonts/OpenSans_SemiBold.ttf b/thirdparty/fonts/OpenSans_SemiBold.ttf Binary files differnew file mode 100644 index 0000000000..54e7059cf3 --- /dev/null +++ b/thirdparty/fonts/OpenSans_SemiBold.ttf |