Merge pull request #78838 from YuriSizov/4.0-cherrypicks

Cherry-picks for the 4.0 branch (future 4.0.4) - 2nd batch
This commit is contained in:
Rémi Verschelde 2023-06-30 13:44:09 +02:00 committed by GitHub
commit c8e0bd50c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
89 changed files with 875 additions and 453 deletions

View File

@ -5,18 +5,19 @@ body:
- type: markdown
attributes:
value: |
- Read our [CONTRIBUTING.md guide](https://github.com/godotengine/godot/blob/master/CONTRIBUTING.md#reporting-bugs) on reporting bugs.
- When reporting bugs, you'll make our life simpler (and the fix will come sooner) if you follow the guidelines in this template.
- Write a descriptive issue title above.
- Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported.
- The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
- Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported. If you don't find a relevant match or if you're unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/stable/about/release_policy.html).
- type: input
attributes:
label: Godot version
description: >
Specify the Git commit hash if using a development or non-official build.
Specify the Godot version, including the Git commit hash if using a development or non-official build.
If you use a custom build, please test if your issue is reproducible in official builds too.
placeholder: 3.3.stable, 4.0.dev (3041becc6)
placeholder: 3.5.stable, 4.0.dev (3041becc6)
validations:
required: true
@ -24,9 +25,12 @@ body:
attributes:
label: System information
description: |
Specify the OS version, and when relevant hardware information.
For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
placeholder: Windows 10, GLES3, Intel HD Graphics 620 (27.20.100.9616)
- Specify the OS version, and when relevant hardware information.
- For issues that are likely OS-specific and/or graphics-related, please specify the CPU model and architecture.
- For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
- **Bug reports not including the required information may be closed at the maintainers' discretion.** If in doubt, always include all the requested information; it's better to include too much information than not enough information.
- **Starting from Godot 4.1, you can copy this information to your clipboard by using *Help > Copy System Info* at the top of the editor window.**
placeholder: Windows 10 - Godot v4.0.3.stable - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 970 (nvidia, 510.85.02) - Intel Core i7-10700KF CPU @ 3.80GHz (16 Threads)
validations:
required: true
@ -52,8 +56,10 @@ body:
attributes:
label: Minimal reproduction project
description: |
A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
Required, unless the reproduction steps are trivial and don't require any project files to be followed. In this case, write "N/A" in the field.
Drag and drop a ZIP archive to upload it. **Do not select another field until the project is done uploading.**
- A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
- Required, unless the reproduction steps are trivial and don't require any project files to be followed. In this case, write "N/A" in the field.
- Drag and drop a ZIP archive to upload it. **Do not select another field until the project is done uploading.**
- **Note for C# users:** If your issue is *not* Mono-specific, please upload a minimal reproduction project written in GDScript or VisualScript. This will make it easier for contributors to reproduce the issue locally as not everyone has a Mono setup available.
- **If you've been asked by a maintainer to upload a minimal reproduction project, you *must* do so within 7 days.** Otherwise, your bug report will be closed as it'll be considered too difficult to diagnose.
validations:
required: true

View File

@ -103,8 +103,8 @@ jobs:
- name: Spell checks via codespell
if: github.event_name == 'pull_request' && env.CHANGED_FILES != ''
uses: codespell-project/actions-codespell@v1
uses: codespell-project/actions-codespell@v2
with:
skip: "./bin,./thirdparty,*.desktop,*.gen.*,*.po,*.pot,*.rc,./AUTHORS.md,./COPYRIGHT.txt,./DONORS.md,./core/input/gamecontrollerdb.txt,./core/string/locales.h,./editor/project_converter_3_to_4.cpp,./misc/scripts/codespell.sh,./platform/android/java/lib/src/com,./platform/web/node_modules,./platform/web/package-lock.json"
ignore_words_list: "curvelinear,doubleclick,expct,findn,gird,hel,inout,lod,nd,numer,ot,te,vai"
ignore_words_list: "curvelinear,doubleclick,expct,findn,gird,hel,inout,lod,mis,nd,numer,ot,te,vai"
path: ${{ env.CHANGED_FILES }}

View File

@ -8,87 +8,10 @@
- [Contributing to Godot's translation](#contributing-to-godots-translation)
- [Communicating with developers](#communicating-with-developers)
**Please read the first section before reporting a bug!**
## Reporting bugs
The golden rule is to **always open *one* issue for *one* bug**. If you notice
several bugs and want to report them, make sure to create one new issue for
each of them.
If you're reporting a new bug, you'll make our life simpler (and the
fix will come sooner) by following these guidelines:
### Search first in the existing database
Issues are often reported several times by various users. It's good practice to
**search first in the [issue tracker](https://github.com/godotengine/godot/issues)
before reporting your issue**. If you don't find a relevant match or if you're
unsure, don't hesitate to **open a new issue**. The bugsquad will handle it
from there if it's a duplicate.
### Specify the platform
Godot runs on a large variety of platforms and operating systems and devices.
**In your bug reports, please always specify:**
- Operating system and version (e.g. Windows 10, macOS 10.15, Ubuntu 19.10)
- Godot version (e.g. 3.2, 3.1.2, or the Git commit hash if you're using a development branch)
For bugs that are likely OS-specific and/or graphics-related, please also specify:
- Device (CPU model including architecture, e.g. x86_64, arm64, etc.)
- GPU model (and the driver version in use if you know it)
**Bug reports not including the required information may be closed at the
maintainers' discretion.** If in doubt, always include all the requested
information; it's better to include too much information than not enough
information.
### Specify steps to reproduce
Many bugs can't be reproduced unless specific steps are taken. Please **specify
the exact steps** that must be taken to reproduce the condition, and try to
keep them as minimal as possible. If you're describing a procedure to follow
in the editor, don't hesitate to include screenshots.
Making your bug report easy to reproduce will make it easier for contributors
to fix the bug.
### Provide a simple example project
Sometimes, unexpected behavior can happen in your project. In such case,
understand that:
- What happens to you may not happen to other users.
- We can't take the time to look at your project, understand how it is set up
and then figure out why it's failing.
- On the contributors' end, recreating a test project from scratch takes valuable
time that can be saved by uploading a *minimal* project.
To speed up our work, **please upload a minimal project** that isolates
and reproduces the issue. This is always the **best way for us to fix it**.
We recommend attaching a ZIP file with the minimal project directly to the bug report,
by drag and dropping the file in the GitHub edition field. This ensures the file
can remain available for a long period of time. Only use third-party file hosts
if your ZIP file isn't accepted by GitHub because it's too large.
We recommend always attaching a minimal reproduction project, even if the issue
may seem simple to reproduce manually.
**Note for C# users:** If your issue is *not* .NET-specific, please upload a
minimal reproduction project written in GDScript.
This will make it easier for contributors to reproduce the issue
locally as not everyone has a .NET setup available.
**If you've been asked by a maintainer to upload a minimal reproduction project,
you *must* do so within 7 days.** Otherwise, your bug report will be closed as
it'll be considered too difficult to diagnose.
Now that you've read the guidelines, click the link below to create a
bug report:
- **[Report a bug](https://github.com/godotengine/godot/issues/new?assignees=&labels=&template=bug_report.yml)**
Report bugs [here](https://github.com/godotengine/godot/issues/new?assignees=&labels=&template=bug_report.yml).
Please follow the instructions in the template when you do.
## Proposing features or improvements

View File

@ -640,7 +640,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards, bool p_ignore_override) {
Error err = _setup(p_path, p_main_pack, p_upwards, p_ignore_override);
if (err == OK) {
if (err == OK && !p_ignore_override) {
String custom_settings = GLOBAL_GET("application/config/project_settings_override");
if (!custom_settings.is_empty()) {
_load_settings_text(custom_settings);

View File

@ -635,6 +635,10 @@
If [code]true[/code], increases the scrollbar touch area to improve usability on touchscreen devices.
[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
</member>
<member name="interface/touchscreen/scale_gizmo_handles" type="float" setter="" getter="">
Specify the multiplier to apply to the scale for the editor gizmo handles to improve usability on touchscreen devices.
[b]Note:[/b] Defaults to [code]1[/code] on non-touchscreen devices.
</member>
<member name="network/debug/remote_host" type="String" setter="" getter="">
The address to listen to when starting the remote debugger. This can be set to [code]0.0.0.0[/code] to allow external clients to connect to the remote debugger (instead of restricting the remote debugger to connections from [code]localhost[/code]).
</member>

View File

@ -179,8 +179,7 @@ typedef void (*DEBUGPROCARB)(GLenum source,
typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userParam);
void RasterizerGLES3::initialize() {
// NVIDIA suffixes all GPU model names with "/PCIe/SSE2" in OpenGL (but not Vulkan). This isn't necessary to display nowadays, so it can be trimmed.
print_line(vformat("OpenGL API %s - Compatibility - Using Device: %s - %s", RS::get_singleton()->get_video_adapter_api_version(), RS::get_singleton()->get_video_adapter_vendor(), RS::get_singleton()->get_video_adapter_name().trim_suffix("/PCIe/SSE2")));
print_line(vformat("OpenGL API %s - Compatibility - Using Device: %s - %s", RS::get_singleton()->get_video_adapter_api_version(), RS::get_singleton()->get_video_adapter_vendor(), RS::get_singleton()->get_video_adapter_name()));
}
void RasterizerGLES3::finalize() {

View File

@ -534,7 +534,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
if (skeleton->use_2d) {
for (int j = 0; j < bs; j++) {
if (skbones[0].size == Vector3()) {
if (skbones[j].size == Vector3(-1, -1, -1)) {
continue; //bone is unused
}
@ -561,7 +561,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
}
} else {
for (int j = 0; j < bs; j++) {
if (skbones[0].size == Vector3()) {
if (skbones[j].size == Vector3(-1, -1, -1)) {
continue; //bone is unused
}

View File

@ -328,11 +328,15 @@ uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) {
}
String Utilities::get_video_adapter_name() const {
return (const char *)glGetString(GL_RENDERER);
const String rendering_device_name = (const char *)glGetString(GL_RENDERER);
// NVIDIA suffixes all GPU model names with "/PCIe/SSE2" in OpenGL (but not Vulkan). This isn't necessary to display nowadays, so it can be trimmed.
return rendering_device_name.trim_suffix("/PCIe/SSE2");
}
String Utilities::get_video_adapter_vendor() const {
return (const char *)glGetString(GL_VENDOR);
const String rendering_device_vendor = (const char *)glGetString(GL_VENDOR);
// NVIDIA suffixes its vendor name with " Corporation". This is neither necessary to process nor display.
return rendering_device_vendor.trim_suffix(" Corporation");
}
RenderingDevice::DeviceType Utilities::get_video_adapter_type() const {

View File

@ -3647,7 +3647,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Don't care what is there.
description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Don't care what is there.
// TODO: What does this mean about the next usage (and thus appropriate dependency masks.
}
} break;
@ -5931,10 +5931,10 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer, uint32_t p_
ERR_FAIL_V_MSG(Vector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving.");
}
// Make sure no one is using the buffer -- the "false" gets us to the same command buffer as below.
_buffer_memory_barrier(buffer->buffer, 0, buffer->size, src_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, src_access_mask, VK_ACCESS_TRANSFER_READ_BIT, false);
// Make sure no one is using the buffer -- the "true" gets us to the same command buffer as below.
_buffer_memory_barrier(buffer->buffer, 0, buffer->size, src_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, src_access_mask, VK_ACCESS_TRANSFER_READ_BIT, true);
VkCommandBuffer command_buffer = frames[frame].setup_command_buffer;
VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
// Size of buffer to retrieve.
if (!p_size) {

View File

@ -122,24 +122,12 @@ void FindReplaceBar::unhandled_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
Ref<InputEventKey> k = p_event;
if (!k.is_valid() || !k->is_pressed()) {
return;
}
Control *focus_owner = get_viewport()->gui_get_focus_owner();
if (text_editor->has_focus() || (focus_owner && vbc_lineedit->is_ancestor_of(focus_owner))) {
bool accepted = true;
if (k.is_valid() && k->is_action_pressed(SNAME("ui_cancel"), false, true)) {
Control *focus_owner = get_viewport()->gui_get_focus_owner();
switch (k->get_keycode()) {
case Key::ESCAPE: {
_hide_bar();
} break;
default: {
accepted = false;
} break;
}
if (accepted) {
if (text_editor->has_focus() || (focus_owner && vbc_lineedit->is_ancestor_of(focus_owner))) {
_hide_bar();
accept_event();
}
}

View File

@ -1504,6 +1504,16 @@ void EditorFileSystem::_save_late_updated_files() {
}
Vector<String> EditorFileSystem::_get_dependencies(const String &p_path) {
// Avoid error spam on first opening of a not yet imported project by treating the following situation
// as a benign one, not letting the file open error happen: the resource is of an importable type but
// it has not been imported yet.
if (ResourceFormatImporter::get_singleton()->recognize_path(p_path)) {
const String &internal_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(p_path);
if (!internal_path.is_empty() && !FileAccess::exists(internal_path)) { // If path is empty (error), keep the code flow to the error.
return Vector<String>();
}
}
List<String> deps;
ResourceLoader::get_dependencies(p_path, &deps);

View File

@ -2567,22 +2567,10 @@ void FindBar::unhandled_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
if (k->is_pressed() && (rich_text_label->has_focus() || is_ancestor_of(get_viewport()->gui_get_focus_owner()))) {
bool accepted = true;
switch (k->get_keycode()) {
case Key::ESCAPE: {
_hide_bar();
} break;
default: {
accepted = false;
} break;
}
if (accepted) {
accept_event();
}
if (k.is_valid() && k->is_action_pressed(SNAME("ui_cancel"), false, true)) {
if (rich_text_label->has_focus() || is_ancestor_of(get_viewport()->gui_get_focus_owner())) {
_hide_bar();
accept_event();
}
}
}

View File

@ -592,6 +592,9 @@ void EditorProperty::add_focusable(Control *p_control) {
void EditorProperty::select(int p_focusable) {
bool already_selected = selected;
if (!selectable) {
return;
}
if (p_focusable >= 0) {
ERR_FAIL_INDEX(p_focusable, focusables.size());
@ -665,11 +668,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) {
mpos.x = get_size().x - mpos.x;
}
if (!selected && selectable) {
selected = true;
emit_signal(SNAME("selected"), property, -1);
queue_redraw();
}
select();
if (keying_rect.has_point(mpos)) {
accept_event();

View File

@ -42,25 +42,15 @@ void EditorLayoutsDialog::_line_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
if (!k->is_pressed()) {
return;
}
switch (k->get_keycode()) {
case Key::KP_ENTER:
case Key::ENTER: {
if (get_hide_on_ok()) {
hide();
}
ok_pressed();
set_input_as_handled();
} break;
case Key::ESCAPE: {
if (k->is_action_pressed(SNAME("ui_accept"), false, true)) {
if (get_hide_on_ok()) {
hide();
set_input_as_handled();
} break;
default:
break;
}
ok_pressed();
set_input_as_handled();
} else if (k->is_action_pressed(SNAME("ui_cancel"), false, true)) {
hide();
set_input_as_handled();
}
}
}

View File

@ -761,7 +761,9 @@ void EditorNode::_notification(int p_what) {
EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme") ||
EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") ||
EditorSettings::get_singleton()->check_changed_settings_in_group("filesystem/file_dialog/thumbnail_size") ||
EditorSettings::get_singleton()->check_changed_settings_in_group("run/output/font_size");
EditorSettings::get_singleton()->check_changed_settings_in_group("run/output/font_size") ||
EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") ||
EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles");
if (theme_changed) {
theme = create_custom_theme(theme_base->get_theme());
@ -836,6 +838,7 @@ void EditorNode::_notification(int p_what) {
help_menu->set_item_icon(help_menu->get_item_index(HELP_DOCS), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_QA), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_REPORT_A_BUG), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), gui_base->get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SUGGEST_A_FEATURE), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
help_menu->set_item_icon(help_menu->get_item_index(HELP_COMMUNITY), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
@ -3168,6 +3171,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case HELP_REPORT_A_BUG: {
OS::get_singleton()->shell_open("https://github.com/godotengine/godot/issues");
} break;
case HELP_COPY_SYSTEM_INFO: {
String info = _get_system_info();
DisplayServer::get_singleton()->clipboard_set(info);
} break;
case HELP_SUGGEST_A_FEATURE: {
OS::get_singleton()->shell_open("https://github.com/godotengine/godot-proposals#readme");
} break;
@ -4647,6 +4654,98 @@ void EditorNode::progress_end_task_bg(const String &p_task) {
singleton->progress_hb->end_task(p_task);
}
String EditorNode::_get_system_info() const {
String distribution_name = OS::get_singleton()->get_distribution_name();
if (distribution_name.is_empty()) {
distribution_name = OS::get_singleton()->get_name();
}
if (distribution_name.is_empty()) {
distribution_name = "Other";
}
const String distribution_version = OS::get_singleton()->get_version();
String godot_version = "Godot v" + String(VERSION_FULL_CONFIG);
if (String(VERSION_BUILD) != "official") {
String hash = String(VERSION_HASH);
hash = hash.is_empty() ? String("unknown") : vformat("(%s)", hash.left(9));
godot_version += " " + hash;
}
String driver_name = GLOBAL_GET("rendering/rendering_device/driver");
String rendering_method = GLOBAL_GET("rendering/renderer/rendering_method");
const String rendering_device_name = RenderingServer::get_singleton()->get_video_adapter_name();
RenderingDevice::DeviceType device_type = RenderingServer::get_singleton()->get_video_adapter_type();
String device_type_string;
switch (device_type) {
case RenderingDevice::DeviceType::DEVICE_TYPE_INTEGRATED_GPU:
device_type_string = "integrated";
break;
case RenderingDevice::DeviceType::DEVICE_TYPE_DISCRETE_GPU:
device_type_string = "dedicated";
break;
case RenderingDevice::DeviceType::DEVICE_TYPE_VIRTUAL_GPU:
device_type_string = "virtual";
break;
case RenderingDevice::DeviceType::DEVICE_TYPE_CPU:
device_type_string = "(software emulation on CPU)";
break;
case RenderingDevice::DeviceType::DEVICE_TYPE_OTHER:
case RenderingDevice::DeviceType::DEVICE_TYPE_MAX:
break; // Can't happen, but silences warning for DEVICE_TYPE_MAX
}
const Vector<String> video_adapter_driver_info = OS::get_singleton()->get_video_adapter_driver_info();
const String processor_name = OS::get_singleton()->get_processor_name();
const int processor_count = OS::get_singleton()->get_processor_count();
// Prettify
if (driver_name == "vulkan") {
driver_name = "Vulkan";
} else if (driver_name == "opengl3") {
driver_name = "GLES3";
}
if (rendering_method == "forward_plus") {
rendering_method = "Forward+";
} else if (rendering_method == "mobile") {
rendering_method = "Mobile";
} else if (rendering_method == "gl_compatibility") {
rendering_method = "Compatibility";
}
// Join info.
Vector<String> info;
info.push_back(godot_version);
if (!distribution_version.is_empty()) {
info.push_back(distribution_name + " " + distribution_version);
} else {
info.push_back(distribution_name);
}
info.push_back(vformat("%s (%s)", driver_name, rendering_method));
String graphics;
if (!device_type_string.is_empty()) {
graphics = device_type_string + " ";
}
graphics += rendering_device_name;
if (video_adapter_driver_info.size() == 2) { // This vector is always either of length 0 or 2.
String vad_name = video_adapter_driver_info[0];
String vad_version = video_adapter_driver_info[1]; // Version could be potentially empty on Linux/BSD.
if (!vad_version.is_empty()) {
graphics += vformat(" (%s; %s)", vad_name, vad_version);
} else {
graphics += vformat(" (%s)", vad_name);
}
}
info.push_back(graphics);
info.push_back(vformat("%s (%d Threads)", processor_name, processor_count));
return String(" - ").join(info);
}
Ref<Texture2D> EditorNode::_file_dialog_get_icon(const String &p_path) {
EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem_path(p_path.get_base_dir());
if (efsd) {
@ -7374,14 +7473,8 @@ EditorNode::EditorNode() {
project_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/project_settings", TTR("Project Settings..."), Key::NONE, TTR("Project Settings")), RUN_SETTINGS);
project_menu->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option));
vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel();
vcs_actions_menu->set_name("Version Control");
vcs_actions_menu->connect("index_pressed", callable_mp(this, &EditorNode::_version_control_menu_option));
project_menu->add_separator();
project_menu->add_child(vcs_actions_menu);
project_menu->add_submenu_item(TTR("Version Control"), "Version Control");
vcs_actions_menu->add_item(TTR("Create Version Control Metadata"), RUN_VCS_METADATA);
vcs_actions_menu->add_item(TTR("Version Control Settings"), RUN_VCS_SETTINGS);
project_menu->add_item(TTR("Version Control"), VCS_MENU);
project_menu->add_separator();
project_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/export", TTR("Export..."), Key::NONE, TTR("Export")), FILE_EXPORT_PROJECT);
@ -7501,6 +7594,8 @@ EditorNode::EditorNode() {
help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/q&a", TTR("Questions & Answers")), HELP_QA);
help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/copy_system_info", TTR("Copy System Info")), HELP_COPY_SYSTEM_INFO);
help_menu->set_item_tooltip(-1, TTR("Copies the system info as a single-line text into the clipboard."));
help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE);
help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/community", TTR("Community")), HELP_COMMUNITY);
@ -7974,6 +8069,15 @@ EditorNode::EditorNode() {
raise_bottom_panel_item(AnimationPlayerEditor::get_singleton());
add_editor_plugin(VersionControlEditorPlugin::get_singleton());
vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel();
vcs_actions_menu->set_name("Version Control");
vcs_actions_menu->connect("index_pressed", callable_mp(this, &EditorNode::_version_control_menu_option));
vcs_actions_menu->add_item(TTR("Create Version Control Metadata"), RUN_VCS_METADATA);
vcs_actions_menu->add_item(TTR("Version Control Settings"), RUN_VCS_SETTINGS);
project_menu->add_child(vcs_actions_menu);
project_menu->set_item_submenu(project_menu->get_item_index(VCS_MENU), "Version Control");
add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor)));
for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) {

View File

@ -199,6 +199,7 @@ private:
RUN_USER_DATA_FOLDER,
RELOAD_CURRENT_PROJECT,
RUN_PROJECT_MANAGER,
VCS_MENU,
RUN_VCS_METADATA,
RUN_VCS_SETTINGS,
SETTINGS_UPDATE_CONTINUOUSLY,
@ -229,6 +230,7 @@ private:
HELP_DOCS,
HELP_QA,
HELP_REPORT_A_BUG,
HELP_COPY_SYSTEM_INFO,
HELP_SUGGEST_A_FEATURE,
HELP_SEND_DOCS_FEEDBACK,
HELP_COMMUNITY,
@ -521,6 +523,8 @@ private:
static int plugin_init_callback_count;
static Vector<EditorNodeInitCallback> _init_callbacks;
String _get_system_info() const;
static void _dependency_error_report(void *ud, const String &p_path, const String &p_dep, const String &p_type) {
EditorNode *en = static_cast<EditorNode *>(ud);
if (!en->dependency_errors.has(p_path)) {

View File

@ -278,7 +278,7 @@ void EditorPropertyArray::update_property() {
size_slider = memnew(EditorSpinSlider);
size_slider->set_step(1);
size_slider->set_max(1000000);
size_slider->set_max(INT32_MAX);
size_slider->set_h_size_flags(SIZE_EXPAND_FILL);
size_slider->set_read_only(is_read_only());
size_slider->connect("value_changed", callable_mp(this, &EditorPropertyArray::_length_changed));

View File

@ -469,6 +469,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
set_restart_if_changed("interface/touchscreen/enable_long_press_as_right_click", true);
EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/touchscreen/enable_pan_and_scale_gestures", has_touchscreen_ui, "")
set_restart_if_changed("interface/touchscreen/enable_pan_and_scale_gestures", true);
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/touchscreen/scale_gizmo_handles", has_touchscreen_ui ? 3 : 1, "1,5,1")
// Scene tabs
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/scene_tabs/display_close_button", 1, "Never,If Tab Active,Always"); // TabBar::CloseButtonDisplayPolicy
@ -688,7 +689,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/tiles_editor/grid_color", Color(1.0, 0.5, 0.2, 0.5));
// Polygon editor
_initial_set("editors/polygon_editor/point_grab_radius", 8);
_initial_set("editors/polygon_editor/point_grab_radius", has_touchscreen_ui ? 32 : 8);
_initial_set("editors/polygon_editor/show_previous_outline", true);
// Animation

View File

@ -255,6 +255,28 @@ static Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float
return ImageTexture::create_from_image(img);
}
float get_gizmo_handle_scale(const String &gizmo_handle_name = "") {
const float scale_gizmo_handles_for_touch = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
if (scale_gizmo_handles_for_touch > 1.0f) {
// The names of the icons that require additional scaling.
static HashSet<StringName> gizmo_to_scale;
if (gizmo_to_scale.is_empty()) {
gizmo_to_scale.insert("EditorHandle");
gizmo_to_scale.insert("EditorHandleAdd");
gizmo_to_scale.insert("EditorHandleDisabled");
gizmo_to_scale.insert("EditorCurveHandle");
gizmo_to_scale.insert("EditorPathSharpHandle");
gizmo_to_scale.insert("EditorPathSmoothHandle");
}
if (gizmo_to_scale.has(gizmo_handle_name)) {
return EDSCALE * scale_gizmo_handles_for_touch;
}
}
return EDSCALE;
}
void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs = false) {
// Before we register the icons, we adjust their colors and saturation.
// Most icons follow the standard rules for color conversion to follow the editor
@ -314,22 +336,23 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme, f
for (int i = 0; i < editor_icons_count; i++) {
Ref<ImageTexture> icon;
if (accent_color_icons.has(editor_icons_names[i])) {
icon = editor_generate_icon(i, EDSCALE, 1.0, accent_color_map);
const String &editor_icon_name = editor_icons_names[i];
if (accent_color_icons.has(editor_icon_name)) {
icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), 1.0, accent_color_map);
} else {
float saturation = p_icon_saturation;
if (saturation_exceptions.has(editor_icons_names[i])) {
if (saturation_exceptions.has(editor_icon_name)) {
saturation = 1.0;
}
if (conversion_exceptions.has(editor_icons_names[i])) {
icon = editor_generate_icon(i, EDSCALE, saturation);
if (conversion_exceptions.has(editor_icon_name)) {
icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation);
} else {
icon = editor_generate_icon(i, EDSCALE, saturation, color_conversion_map);
icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation, color_conversion_map);
}
}
p_theme->set_icon(editor_icons_names[i], SNAME("EditorIcons"), icon);
p_theme->set_icon(editor_icon_name, SNAME("EditorIcons"), icon);
}
}
@ -395,6 +418,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Color base_color = EDITOR_GET("interface/theme/base_color");
float contrast = EDITOR_GET("interface/theme/contrast");
bool increase_scrollbar_touch_area = EDITOR_GET("interface/touchscreen/increase_scrollbar_touch_area");
const float gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
bool draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders");
float icon_saturation = EDITOR_GET("interface/theme/icon_saturation");
float relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity");
@ -592,6 +616,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("thumb_size", "Editor", thumb_size);
theme->set_constant("dark_theme", "Editor", dark_theme);
theme->set_constant("color_picker_button_height", "Editor", 28 * EDSCALE);
theme->set_constant("gizmo_handle_scale", "Editor", gizmo_handle_scale);
// Register editor icons.
// If the settings are comparable to the old theme, then just copy them over.
@ -607,8 +632,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const bool prev_dark_theme = (bool)p_theme->get_constant(SNAME("dark_theme"), SNAME("Editor"));
const Color prev_accent_color = p_theme->get_color(SNAME("accent_color"), SNAME("Editor"));
const float prev_icon_saturation = p_theme->get_color(SNAME("icon_saturation"), SNAME("Editor")).r;
const float prev_gizmo_handle_scale = (float)p_theme->get_constant(SNAME("gizmo_handle_scale"), SNAME("Editor"));
keep_old_icons = (Math::is_equal_approx(prev_scale, EDSCALE) &&
Math::is_equal_approx(prev_gizmo_handle_scale, gizmo_handle_scale) &&
prev_dark_theme == dark_theme &&
prev_accent_color == accent_color &&
prev_icon_saturation == icon_saturation);

View File

@ -434,6 +434,8 @@ void FileSystemDock::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
overwrite_dialog_scroll->add_theme_style_override("panel", get_theme_stylebox("panel", "Tree"));
if (is_visible_in_tree()) {
_update_display_mode(true);
}
@ -1686,10 +1688,10 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove
Vector<String> conflicting_items = _check_existing();
if (!conflicting_items.is_empty()) {
// Ask to do something.
overwrite_dialog->set_text(vformat(
TTR("The following files or folders conflict with items in the target location '%s':\n\n%s\n\nDo you wish to overwrite them?"),
to_move_path,
String("\n").join(conflicting_items)));
overwrite_dialog_header->set_text(vformat(
TTR("The following files or folders conflict with items in the target location '%s':"), to_move_path));
overwrite_dialog_file_list->set_text(String("\n").join(conflicting_items));
overwrite_dialog_footer->set_text(TTR("Do you wish to overwrite them?"));
overwrite_dialog->popup_centered();
return;
}
@ -3298,6 +3300,22 @@ FileSystemDock::FileSystemDock() {
add_child(overwrite_dialog);
overwrite_dialog->connect("confirmed", callable_mp(this, &FileSystemDock::_move_with_overwrite));
VBoxContainer *overwrite_dialog_vb = memnew(VBoxContainer);
overwrite_dialog->add_child(overwrite_dialog_vb);
overwrite_dialog_header = memnew(Label);
overwrite_dialog_vb->add_child(overwrite_dialog_header);
overwrite_dialog_scroll = memnew(ScrollContainer);
overwrite_dialog_vb->add_child(overwrite_dialog_scroll);
overwrite_dialog_scroll->set_custom_minimum_size(Vector2(400, 600) * EDSCALE);
overwrite_dialog_file_list = memnew(Label);
overwrite_dialog_scroll->add_child(overwrite_dialog_file_list);
overwrite_dialog_footer = memnew(Label);
overwrite_dialog_vb->add_child(overwrite_dialog_footer);
duplicate_dialog = memnew(ConfirmationDialog);
VBoxContainer *duplicate_dialog_vb = memnew(VBoxContainer);
duplicate_dialog->add_child(duplicate_dialog_vb);

View File

@ -151,7 +151,13 @@ private:
LineEdit *duplicate_dialog_text = nullptr;
ConfirmationDialog *make_dir_dialog = nullptr;
LineEdit *make_dir_dialog_text = nullptr;
ConfirmationDialog *overwrite_dialog = nullptr;
ScrollContainer *overwrite_dialog_scroll = nullptr;
Label *overwrite_dialog_header = nullptr;
Label *overwrite_dialog_footer = nullptr;
Label *overwrite_dialog_file_list = nullptr;
SceneCreateDialog *make_scene_dialog = nullptr;
ScriptCreateDialog *make_script_dialog = nullptr;
ShaderCreateDialog *make_shader_dialog = nullptr;

View File

@ -2413,7 +2413,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
}
}
if (k.is_valid() && k->is_pressed() && k->get_keycode() == Key::ESCAPE && drag_type == DRAG_NONE && tool == TOOL_SELECT) {
if (k.is_valid() && k->is_action_pressed(SNAME("ui_cancel"), false, true) && drag_type == DRAG_NONE && tool == TOOL_SELECT) {
// Unselect everything
editor_selection->clear();
viewport->queue_redraw();
@ -4589,7 +4589,11 @@ void CanvasItemEditor::_popup_callback(int p_op) {
} break;
case SKELETON_MAKE_BONES: {
HashMap<Node *, Object *> &selection = editor_selection->get_selection();
Node *editor_root = EditorNode::get_singleton()->get_edited_scene()->get_tree()->get_edited_scene_root();
Node *editor_root = get_tree()->get_edited_scene_root();
if (!editor_root || selection.is_empty()) {
return;
}
undo_redo->create_action(TTR("Create Custom Bone2D(s) from Node(s)"));
for (const KeyValue<Node *, Object *> &E : selection) {

View File

@ -33,6 +33,7 @@
#include "canvas_item_editor_plugin.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "scene/resources/capsule_shape_2d.h"
#include "scene/resources/circle_shape_2d.h"
@ -44,6 +45,10 @@
#include "scene/resources/world_boundary_shape_2d.h"
#include "scene/scene_string_names.h"
CollisionShape2DEditor::CollisionShape2DEditor() {
grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius");
}
void CollisionShape2DEditor::_node_removed(Node *p_node) {
if (p_node == node) {
node = nullptr;
@ -307,7 +312,7 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
if (mb->get_button_index() == MouseButton::LEFT) {
if (mb->is_pressed()) {
for (int i = 0; i < handles.size(); i++) {
if (xform.xform(handles[i]).distance_to(gpoint) < 8) {
if (xform.xform(handles[i]).distance_to(gpoint) < grab_threshold) {
edit_handle = i;
break;
@ -529,6 +534,12 @@ void CollisionShape2DEditor::_notification(int p_what) {
_shape_changed();
}
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
if (EditorSettings::get_singleton()->check_changed_settings_in_group("editors/polygon_editor/point_grab_radius")) {
grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius");
}
} break;
}
}

View File

@ -69,6 +69,7 @@ class CollisionShape2DEditor : public Control {
int shape_type = -1;
int edit_handle = -1;
bool pressed = false;
real_t grab_threshold = 8;
Variant original;
Transform2D original_transform;
Vector2 original_point;
@ -90,6 +91,8 @@ public:
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
void forward_canvas_draw_over_viewport(Control *p_overlay);
void edit(Node *p_node);
CollisionShape2DEditor();
};
class CollisionShape2DEditorPlugin : public EditorPlugin {

View File

@ -47,6 +47,7 @@ CurveEditor::CurveEditor() {
_tangents_length = 40;
_dragging = false;
_has_undo_data = false;
_gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
set_focus_mode(FOCUS_ALL);
set_clip_contents(true);
@ -103,6 +104,11 @@ void CurveEditor::_notification(int p_what) {
case NOTIFICATION_DRAW: {
_draw();
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles")) {
_gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
}
} break;
}
}
@ -395,7 +401,7 @@ int CurveEditor::get_point_at(Vector2 pos) const {
}
const Curve &curve = **_curve_ref;
const float true_hover_radius = Math::round(_hover_radius * EDSCALE);
const float true_hover_radius = Math::round(_hover_radius * _gizmo_handle_scale * EDSCALE);
const float r = true_hover_radius * true_hover_radius;
for (int i = 0; i < curve.get_point_count(); ++i) {
@ -415,14 +421,14 @@ CurveEditor::TangentIndex CurveEditor::get_tangent_at(Vector2 pos) const {
if (_selected_point != 0) {
Vector2 control_pos = get_tangent_view_pos(_selected_point, TANGENT_LEFT);
if (control_pos.distance_to(pos) < _hover_radius) {
if (control_pos.distance_to(pos) < _hover_radius * _gizmo_handle_scale) {
return TANGENT_LEFT;
}
}
if (_selected_point != _curve_ref->get_point_count() - 1) {
Vector2 control_pos = get_tangent_view_pos(_selected_point, TANGENT_RIGHT);
if (control_pos.distance_to(pos) < _hover_radius) {
if (control_pos.distance_to(pos) < _hover_radius * _gizmo_handle_scale) {
return TANGENT_RIGHT;
}
}
@ -560,7 +566,7 @@ Vector2 CurveEditor::get_tangent_view_pos(int i, TangentIndex tangent) const {
Vector2 point_pos = get_view_pos(_curve_ref->get_point_position(i));
Vector2 control_pos = get_view_pos(_curve_ref->get_point_position(i) + dir);
return point_pos + Math::round(_tangents_length * EDSCALE) * (control_pos - point_pos).normalized();
return point_pos + Math::round(_tangents_length * _gizmo_handle_scale * EDSCALE) * (control_pos - point_pos).normalized();
}
Vector2 CurveEditor::get_view_pos(Vector2 world_pos) const {
@ -705,13 +711,13 @@ void CurveEditor::_draw() {
if (i != 0) {
Vector2 control_pos = get_tangent_view_pos(i, TANGENT_LEFT);
draw_line(get_view_pos(pos), control_pos, tangent_color, Math::round(EDSCALE));
draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(Math::round(2 * EDSCALE)), tangent_color);
draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(Math::round(2 * _gizmo_handle_scale * EDSCALE)), tangent_color);
}
if (i != curve.get_point_count() - 1) {
Vector2 control_pos = get_tangent_view_pos(i, TANGENT_RIGHT);
draw_line(get_view_pos(pos), control_pos, tangent_color, Math::round(EDSCALE));
draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(Math::round(2 * EDSCALE)), tangent_color);
draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(Math::round(2 * _gizmo_handle_scale * EDSCALE)), tangent_color);
}
}
@ -734,7 +740,7 @@ void CurveEditor::_draw() {
for (int i = 0; i < curve.get_point_count(); ++i) {
Vector2 pos = curve.get_point_position(i);
draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(Math::round(3 * EDSCALE)), i == _selected_point ? selected_point_color : point_color);
draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(Math::round(3 * _gizmo_handle_scale * EDSCALE)), i == _selected_point ? selected_point_color : point_color);
// TODO Circles are prettier. Needs a fix! Or a texture
//draw_circle(pos, 2, point_color);
}
@ -744,7 +750,7 @@ void CurveEditor::_draw() {
if (_hover_point != -1) {
const Color hover_color = line_color;
Vector2 pos = curve.get_point_position(_hover_point);
draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(Math::round(_hover_radius * EDSCALE)), hover_color, false, Math::round(EDSCALE));
draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(Math::round(_hover_radius * _gizmo_handle_scale * EDSCALE)), hover_color, false, Math::round(EDSCALE));
}
// Help text

View File

@ -115,6 +115,7 @@ private:
// Constant
float _hover_radius;
float _tangents_length;
float _gizmo_handle_scale = 1.0;
};
class EditorInspectorPluginCurve : public EditorInspectorPlugin {

View File

@ -1735,6 +1735,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
frame_list = memnew(ItemList);
frame_list->set_v_size_flags(SIZE_EXPAND_FILL);
frame_list->set_icon_mode(ItemList::ICON_MODE_TOP);
frame_list->set_texture_filter(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
frame_list->set_max_columns(0);
frame_list->set_icon_mode(ItemList::ICON_MODE_TOP);
@ -1883,6 +1884,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_preview = memnew(TextureRect);
split_sheet_preview->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE);
split_sheet_preview->set_texture_filter(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
split_sheet_preview->set_mouse_filter(MOUSE_FILTER_PASS);
split_sheet_preview->connect("draw", callable_mp(this, &SpriteFramesEditor::_sheet_preview_draw));
split_sheet_preview->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_preview_input));

View File

@ -1827,19 +1827,13 @@ void ThemeItemEditorDialog::_edit_theme_item_gui_input(const Ref<InputEvent> &p_
return;
}
switch (k->get_keycode()) {
case Key::KP_ENTER:
case Key::ENTER: {
_confirm_edit_theme_item();
edit_theme_item_dialog->hide();
edit_theme_item_dialog->set_input_as_handled();
} break;
case Key::ESCAPE: {
edit_theme_item_dialog->hide();
edit_theme_item_dialog->set_input_as_handled();
} break;
default:
break;
if (k->is_action_pressed(SNAME("ui_accept"), false, true)) {
_confirm_edit_theme_item();
edit_theme_item_dialog->hide();
edit_theme_item_dialog->set_input_as_handled();
} else if (k->is_action_pressed(SNAME("ui_cancel"), false, true)) {
edit_theme_item_dialog->hide();
edit_theme_item_dialog->set_input_as_handled();
}
}
}

View File

@ -106,10 +106,11 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla
// Create tiles and alternatives, then copy their properties.
for (int alternative_index = 0; alternative_index < atlas_source->get_alternative_tiles_count(tile_mapping.key); alternative_index++) {
int alternative_id = atlas_source->get_alternative_tile_id(tile_mapping.key, alternative_index);
int changed_id = -1;
if (alternative_id == 0) {
merged->create_tile(tile_mapping.value, atlas_source->get_tile_size_in_atlas(tile_mapping.key));
} else {
merged->create_alternative_tile(tile_mapping.value, alternative_index);
changed_id = merged->create_alternative_tile(tile_mapping.value, alternative_index);
}
// Copy the properties.
@ -117,7 +118,7 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla
List<PropertyInfo> properties;
src_tile_data->get_property_list(&properties);
TileData *dst_tile_data = merged->get_tile_data(tile_mapping.value, alternative_id);
TileData *dst_tile_data = merged->get_tile_data(tile_mapping.value, changed_id == -1 ? alternative_id : changed_id);
for (PropertyInfo property : properties) {
if (!(property.usage & PROPERTY_USAGE_STORAGE)) {
continue;
@ -296,7 +297,7 @@ AtlasMergingDialog::AtlasMergingDialog() {
atlas_merging_atlases_list->set_fixed_icon_size(Size2(60, 60) * EDSCALE);
atlas_merging_atlases_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
atlas_merging_atlases_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
atlas_merging_atlases_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
atlas_merging_atlases_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
atlas_merging_atlases_list->set_custom_minimum_size(Size2(100, 200));
atlas_merging_atlases_list->set_select_mode(ItemList::SELECT_MULTI);
atlas_merging_atlases_list->connect("multi_selected", callable_mp(this, &AtlasMergingDialog::_update_texture).unbind(2));
@ -304,6 +305,7 @@ AtlasMergingDialog::AtlasMergingDialog() {
VBoxContainer *atlas_merging_right_panel = memnew(VBoxContainer);
atlas_merging_right_panel->set_h_size_flags(Control::SIZE_EXPAND_FILL);
atlas_merging_right_panel->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
atlas_merging_h_split_container->add_child(atlas_merging_right_panel);
// Settings.

View File

@ -942,7 +942,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
metadata_dialog->set_title(TTR("Create Version Control Metadata"));
metadata_dialog->set_min_size(Size2(200, 40));
metadata_dialog->get_ok_button()->connect(SNAME("pressed"), callable_mp(this, &VersionControlEditorPlugin::_create_vcs_metadata_files));
add_child(metadata_dialog);
get_editor_interface()->get_base_control()->add_child(metadata_dialog);
VBoxContainer *metadata_vb = memnew(VBoxContainer);
metadata_dialog->add_child(metadata_vb);
@ -971,7 +971,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
set_up_dialog->set_min_size(Size2(600, 100));
set_up_dialog->add_cancel_button("Cancel");
set_up_dialog->set_hide_on_ok(true);
add_child(set_up_dialog);
get_editor_interface()->get_base_control()->add_child(set_up_dialog);
Button *set_up_apply_button = set_up_dialog->get_ok_button();
set_up_apply_button->set_text(TTR("Apply"));

View File

@ -390,7 +390,7 @@ bool ProjectConverter3To4::convert() {
rename_gdscript_functions(source_lines, reg_container, false); // Require to additional rename.
rename_common(RenamesMap3To4::project_settings_renames, reg_container.project_settings_regexes, source_lines);
rename_gdscript_keywords(source_lines, reg_container);
rename_gdscript_keywords(source_lines, reg_container, false);
rename_common(RenamesMap3To4::gdscript_properties_renames, reg_container.gdscript_properties_regexes, source_lines);
rename_common(RenamesMap3To4::gdscript_signals_renames, reg_container.gdscript_signals_regexes, source_lines);
rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, source_lines);
@ -408,7 +408,7 @@ bool ProjectConverter3To4::convert() {
rename_gdscript_functions(source_lines, reg_container, true); // Require to do additional renames.
rename_common(RenamesMap3To4::project_settings_renames, reg_container.project_settings_regexes, source_lines);
rename_gdscript_keywords(source_lines, reg_container);
rename_gdscript_keywords(source_lines, reg_container, true);
rename_common(RenamesMap3To4::gdscript_properties_renames, reg_container.gdscript_properties_regexes, source_lines);
rename_common(RenamesMap3To4::gdscript_signals_renames, reg_container.gdscript_signals_regexes, source_lines);
rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, source_lines);
@ -572,7 +572,7 @@ bool ProjectConverter3To4::validate_conversion() {
changed_elements.append_array(check_for_rename_gdscript_functions(lines, reg_container, false));
changed_elements.append_array(check_for_rename_common(RenamesMap3To4::project_settings_renames, reg_container.project_settings_regexes, lines));
changed_elements.append_array(check_for_rename_gdscript_keywords(lines, reg_container));
changed_elements.append_array(check_for_rename_gdscript_keywords(lines, reg_container, false));
changed_elements.append_array(check_for_rename_common(RenamesMap3To4::gdscript_properties_renames, reg_container.gdscript_properties_regexes, lines));
changed_elements.append_array(check_for_rename_common(RenamesMap3To4::gdscript_signals_renames, reg_container.gdscript_signals_regexes, lines));
changed_elements.append_array(check_for_rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, lines));
@ -590,7 +590,7 @@ bool ProjectConverter3To4::validate_conversion() {
changed_elements.append_array(check_for_rename_gdscript_functions(lines, reg_container, true));
changed_elements.append_array(check_for_rename_common(RenamesMap3To4::project_settings_renames, reg_container.project_settings_regexes, lines));
changed_elements.append_array(check_for_rename_gdscript_keywords(lines, reg_container));
changed_elements.append_array(check_for_rename_gdscript_keywords(lines, reg_container, true));
changed_elements.append_array(check_for_rename_common(RenamesMap3To4::gdscript_properties_renames, reg_container.gdscript_properties_regexes, lines));
changed_elements.append_array(check_for_rename_common(RenamesMap3To4::gdscript_signals_renames, reg_container.gdscript_signals_regexes, lines));
changed_elements.append_array(check_for_rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, lines));
@ -863,22 +863,26 @@ bool ProjectConverter3To4::test_conversion(RegExContainer &reg_container) {
valid = valid && test_conversion_with_regex("Spatial.shader", "Spatial.shader", &ProjectConverter3To4::rename_classes, "classes", reg_container);
valid = valid && test_conversion_with_regex("Spatial.other", "Node3D.other", &ProjectConverter3To4::rename_classes, "classes", reg_container);
valid = valid && test_conversion_with_regex("\nonready", "\n@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("onready", "@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex(" onready", " onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\nexport", "\n@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\texport", "\t@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\texport_dialog", "\texport_dialog", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("export", "@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex(" export", " export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\nremote func", "\n\n@rpc(\"any_peer\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\nremotesync func", "\n\n@rpc(\"any_peer\", \"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\nsync func", "\n\n@rpc(\"any_peer\", \"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\nslave func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\npuppet func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\npuppetsync func", "\n\n@rpc(\"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\nmaster func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_with_regex("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(\"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
valid = valid && test_conversion_gdscript_builtin("\nonready", "\n@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("onready", "@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin(" onready", " onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\nexport", "\n@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\texport", "\t@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\texport_dialog", "\texport_dialog", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("export", "@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin(" export", " export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\n\nremote func", "\n\n@rpc(\"any_peer\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\n\nremote func", "\n\n@rpc(\\\"any_peer\\\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, true);
valid = valid && test_conversion_gdscript_builtin("\n\nremotesync func", "\n\n@rpc(\"any_peer\", \"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\n\nremotesync func", "\n\n@rpc(\\\"any_peer\\\", \\\"call_local\\\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, true);
valid = valid && test_conversion_gdscript_builtin("\n\nsync func", "\n\n@rpc(\"any_peer\", \"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\n\nsync func", "\n\n@rpc(\\\"any_peer\\\", \\\"call_local\\\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, true);
valid = valid && test_conversion_gdscript_builtin("\n\nslave func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\n\npuppet func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\n\npuppetsync func", "\n\n@rpc(\"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\n\npuppetsync func", "\n\n@rpc(\\\"call_local\\\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, true);
valid = valid && test_conversion_gdscript_builtin("\n\nmaster func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(\"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("var size: Vector2 = Vector2() setget set_function, get_function", "var size: Vector2 = Vector2(): get = get_function, set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("var size: Vector2 = Vector2() setget set_function, ", "var size: Vector2 = Vector2(): set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
@ -2442,7 +2446,15 @@ Vector<String> ProjectConverter3To4::check_for_rename_csharp_attributes(Vector<S
return found_renames;
}
void ProjectConverter3To4::rename_gdscript_keywords(Vector<SourceLine> &source_lines, const RegExContainer &reg_container) {
_FORCE_INLINE_ static String builtin_escape(const String &p_str, bool p_builtin) {
if (p_builtin) {
return p_str.replace("\"", "\\\"");
} else {
return p_str;
}
}
void ProjectConverter3To4::rename_gdscript_keywords(Vector<SourceLine> &source_lines, const RegExContainer &reg_container, bool builtin) {
static String error_message = "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n";
for (SourceLine &source_line : source_lines) {
@ -2462,13 +2474,13 @@ void ProjectConverter3To4::rename_gdscript_keywords(Vector<SourceLine> &source_l
line = reg_container.keyword_gdscript_onready.sub(line, "@onready", true);
}
if (line.contains("remote")) {
line = reg_container.keyword_gdscript_remote.sub(line, "@rpc(\"any_peer\") func", true);
line = reg_container.keyword_gdscript_remote.sub(line, builtin_escape("@rpc(\"any_peer\") func", builtin), true);
}
if (line.contains("remote")) {
line = reg_container.keyword_gdscript_remotesync.sub(line, "@rpc(\"any_peer\", \"call_local\") func", true);
line = reg_container.keyword_gdscript_remotesync.sub(line, builtin_escape("@rpc(\"any_peer\", \"call_local\") func", builtin), true);
}
if (line.contains("sync")) {
line = reg_container.keyword_gdscript_sync.sub(line, "@rpc(\"any_peer\", \"call_local\") func", true);
line = reg_container.keyword_gdscript_sync.sub(line, builtin_escape("@rpc(\"any_peer\", \"call_local\") func", builtin), true);
}
if (line.contains("slave")) {
line = reg_container.keyword_gdscript_slave.sub(line, "@rpc func", true);
@ -2477,19 +2489,19 @@ void ProjectConverter3To4::rename_gdscript_keywords(Vector<SourceLine> &source_l
line = reg_container.keyword_gdscript_puppet.sub(line, "@rpc func", true);
}
if (line.contains("puppet")) {
line = reg_container.keyword_gdscript_puppetsync.sub(line, "@rpc(\"call_local\") func", true);
line = reg_container.keyword_gdscript_puppetsync.sub(line, builtin_escape("@rpc(\"call_local\") func", builtin), true);
}
if (line.contains("master")) {
line = reg_container.keyword_gdscript_master.sub(line, error_message + "@rpc func", true);
}
if (line.contains("master")) {
line = reg_container.keyword_gdscript_mastersync.sub(line, error_message + "@rpc(\"call_local\") func", true);
line = reg_container.keyword_gdscript_mastersync.sub(line, error_message + builtin_escape("@rpc(\"call_local\") func", builtin), true);
}
}
}
}
Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<String> &lines, const RegExContainer &reg_container) {
Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<String> &lines, const RegExContainer &reg_container, bool builtin) {
Vector<String> found_renames;
int current_line = 1;
@ -2531,25 +2543,25 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S
if (line.contains("remote")) {
old = line;
line = reg_container.keyword_gdscript_remote.sub(line, "@rpc(\"any_peer\") func", true);
line = reg_container.keyword_gdscript_remote.sub(line, builtin_escape("@rpc(\"any_peer\") func", builtin), true);
if (old != line) {
found_renames.append(line_formatter(current_line, "remote func", "@rpc(\"any_peer\") func", line));
found_renames.append(line_formatter(current_line, "remote func", builtin_escape("@rpc(\"any_peer\") func", builtin), line));
}
}
if (line.contains("remote")) {
old = line;
line = reg_container.keyword_gdscript_remotesync.sub(line, "@rpc(\"any_peer\", \"call_local\")) func", true);
line = reg_container.keyword_gdscript_remotesync.sub(line, builtin_escape("@rpc(\"any_peer\", \"call_local\")) func", builtin), true);
if (old != line) {
found_renames.append(line_formatter(current_line, "remotesync func", "@rpc(\"any_peer\", \"call_local\")) func", line));
found_renames.append(line_formatter(current_line, "remotesync func", builtin_escape("@rpc(\"any_peer\", \"call_local\")) func", builtin), line));
}
}
if (line.contains("sync")) {
old = line;
line = reg_container.keyword_gdscript_sync.sub(line, "@rpc(\"any_peer\", \"call_local\")) func", true);
line = reg_container.keyword_gdscript_sync.sub(line, builtin_escape("@rpc(\"any_peer\", \"call_local\")) func", builtin), true);
if (old != line) {
found_renames.append(line_formatter(current_line, "sync func", "@rpc(\"any_peer\", \"call_local\")) func", line));
found_renames.append(line_formatter(current_line, "sync func", builtin_escape("@rpc(\"any_peer\", \"call_local\")) func", builtin), line));
}
}
@ -2571,9 +2583,9 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S
if (line.contains("puppet")) {
old = line;
line = reg_container.keyword_gdscript_puppetsync.sub(line, "@rpc(\"call_local\") func", true);
line = reg_container.keyword_gdscript_puppetsync.sub(line, builtin_escape("@rpc(\"call_local\") func", builtin), true);
if (old != line) {
found_renames.append(line_formatter(current_line, "puppetsync func", "@rpc(\"call_local\") func", line));
found_renames.append(line_formatter(current_line, "puppetsync func", builtin_escape("@rpc(\"call_local\") func", builtin), line));
}
}
@ -2587,9 +2599,9 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S
if (line.contains("master")) {
old = line;
line = reg_container.keyword_gdscript_master.sub(line, "@rpc(\"call_local\") func", true);
line = reg_container.keyword_gdscript_master.sub(line, builtin_escape("@rpc(\"call_local\") func", builtin), true);
if (old != line) {
found_renames.append(line_formatter(current_line, "mastersync func", "@rpc(\"call_local\") func", line));
found_renames.append(line_formatter(current_line, "mastersync func", builtin_escape("@rpc(\"call_local\") func", builtin), line));
}
}
}

View File

@ -90,8 +90,8 @@ class ProjectConverter3To4 {
void rename_csharp_attributes(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
Vector<String> check_for_rename_csharp_attributes(Vector<String> &lines, const RegExContainer &reg_container);
void rename_gdscript_keywords(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
Vector<String> check_for_rename_gdscript_keywords(Vector<String> &lines, const RegExContainer &reg_container);
void rename_gdscript_keywords(Vector<SourceLine> &r_source_lines, const RegExContainer &p_reg_container, bool p_builtin);
Vector<String> check_for_rename_gdscript_keywords(Vector<String> &r_lines, const RegExContainer &p_reg_container, bool p_builtin);
void rename_input_map_scancode(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
Vector<String> check_for_rename_input_map_scancode(Vector<String> &lines, const RegExContainer &reg_container);

View File

@ -3,6 +3,6 @@ SKIP_LIST="./.*,./**/.*,./bin,./thirdparty,*.desktop,*.gen.*,*.po,*.pot,*.rc,./A
SKIP_LIST+="./core/input/gamecontrollerdb.txt,./core/string/locales.h,./editor/renames_map_3_to_4.cpp,./misc/scripts/codespell.sh,"
SKIP_LIST+="./platform/android/java/lib/src/com,./platform/web/node_modules,./platform/web/package-lock.json,"
IGNORE_LIST="curvelinear,doubleclick,expct,findn,gird,hel,inout,lod,nd,numer,ot,te,vai"
IGNORE_LIST="curvelinear,doubleclick,expct,findn,gird,hel,inout,lod,mis,nd,numer,ot,te,vai"
codespell -w -q 3 -S "${SKIP_LIST}" -L "${IGNORE_LIST}" --builtin "clear,rare,en-GB_to_en-US"

View File

@ -311,6 +311,14 @@ void GDScriptEditorTranslationParserPlugin::_extract_from_call(GDScriptParser::C
}
}
}
if (p_call->callee && p_call->callee->type == GDScriptParser::Node::SUBSCRIPT) {
GDScriptParser::SubscriptNode *subscript_node = static_cast<GDScriptParser::SubscriptNode *>(p_call->callee);
if (subscript_node->base && subscript_node->base->type == GDScriptParser::Node::CALL) {
GDScriptParser::CallNode *call_node = static_cast<GDScriptParser::CallNode *>(subscript_node->base);
_extract_from_call(call_node);
}
}
}
void GDScriptEditorTranslationParserPlugin::_extract_fd_literals(GDScriptParser::ExpressionNode *p_expression) {

View File

@ -1532,7 +1532,10 @@ CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpS
instance->_reference_owner_unsafe();
}
p_script->instances.insert(p_owner);
{
MutexLock lock(CSharpLanguage::get_singleton()->get_script_instances_mutex());
p_script->instances.insert(p_owner);
}
return instance;
}

View File

@ -41,6 +41,12 @@ namespace GodotTools.Build
startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"]
= ((string)editorSettings.GetSetting("interface/editor/editor_language")).Replace('_', '-');
if (OperatingSystem.IsWindows())
{
startInfo.StandardOutputEncoding = Encoding.UTF8;
startInfo.StandardErrorEncoding = Encoding.UTF8;
}
// Needed when running from Developer Command Prompt for VS
RemovePlatformVariable(startInfo.EnvironmentVariables);
@ -105,6 +111,12 @@ namespace GodotTools.Build
startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"]
= ((string)editorSettings.GetSetting("interface/editor/editor_language")).Replace('_', '-');
if (OperatingSystem.IsWindows())
{
startInfo.StandardOutputEncoding = Encoding.UTF8;
startInfo.StandardErrorEncoding = Encoding.UTF8;
}
// Needed when running from Developer Command Prompt for VS
RemovePlatformVariable(startInfo.EnvironmentVariables);

View File

@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using JetBrains.Annotations;
using OS = GodotTools.Utils.OS;
@ -58,6 +59,11 @@ namespace GodotTools.Build
RedirectStandardOutput = true
};
if (OperatingSystem.IsWindows())
{
process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
}
process.StartInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"] = "en-US";
var lines = new List<string>();

View File

@ -103,7 +103,7 @@ namespace Godot.NativeInterop
{
try
{
if (NativeFuncs.godotsharp_internal_script_debugger_is_active())
if (NativeFuncs.godotsharp_internal_script_debugger_is_active().ToBool())
{
SendToScriptDebugger(e);
}
@ -122,7 +122,7 @@ namespace Godot.NativeInterop
{
try
{
if (NativeFuncs.godotsharp_internal_script_debugger_is_active())
if (NativeFuncs.godotsharp_internal_script_debugger_is_active().ToBool())
{
SendToScriptDebugger(e);
}

View File

@ -56,7 +56,7 @@ namespace Godot.NativeInterop
in godot_string p_file, int p_line, in godot_string p_err, in godot_string p_descr,
godot_bool p_warning, in DebuggingUtils.godot_stack_info_vector p_stack_info_vector);
internal static partial bool godotsharp_internal_script_debugger_is_active();
internal static partial godot_bool godotsharp_internal_script_debugger_is_active();
internal static partial IntPtr godotsharp_internal_object_get_associated_gchandle(IntPtr ptr);

View File

@ -1 +0,0 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55228 0-1 .44772-1 1v12c0 .55228.44772 1 1 1h12c.55228 0 1-.44772 1-1v-12c0-.55228-.44772-1-1-1zm1 2h10v8h-10zm3 1v2h2v-2zm2 2v2h2v2h2v-6h-2v2zm0 2h-2v-2h-2v4h4z" fill="#e0e0e0" fill-opacity=".99608"/></svg>

Before

Width:  |  Height:  |  Size: 307 B

View File

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M2 1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1zm1 2h10v8H3zm3 1v2h2V4zm2 2v2h2v2h2V4h-2v2zm0 2H6V6H4v4h4z" fill="#e0e0e0"/></svg>

After

Width:  |  Height:  |  Size: 244 B

View File

@ -56,7 +56,10 @@ if lib_arch_dir != "":
if env.dev_build:
lib_type_dir = "dev"
elif env.debug_features:
lib_type_dir = "debug"
if env.editor_build and env["store_release"]:
lib_type_dir = "release"
else:
lib_type_dir = "debug"
else: # Release
lib_type_dir = "release"

View File

@ -60,6 +60,7 @@ static AndroidGodotCodePair android_godot_code_pairs[] = {
{ AKEYCODE_DPAD_DOWN, Key::DOWN }, // (20) Directional Pad Down key.
{ AKEYCODE_DPAD_LEFT, Key::LEFT }, // (21) Directional Pad Left key.
{ AKEYCODE_DPAD_RIGHT, Key::RIGHT }, // (22) Directional Pad Right key.
{ AKEYCODE_DPAD_CENTER, Key::ENTER }, // (23) Directional Pad Center key.
{ AKEYCODE_VOLUME_UP, Key::VOLUMEUP }, // (24) Volume Up key.
{ AKEYCODE_VOLUME_DOWN, Key::VOLUMEDOWN }, // (25) Volume Down key.
{ AKEYCODE_POWER, Key::STANDBY }, // (26) Power key.

View File

@ -22,6 +22,8 @@ def can_build():
def get_opts():
from SCons.Variables import BoolVariable
return [
("ANDROID_SDK_ROOT", "Path to the Android SDK", get_env_android_sdk_root()),
(
@ -29,6 +31,7 @@ def get_opts():
'Target platform (android-<api>, e.g. "android-' + str(get_min_target_api()) + '")',
"android-" + str(get_min_target_api()),
),
BoolVariable("store_release", "Editor build for Google Play Store (for official builds only)", False),
]

View File

@ -135,14 +135,16 @@ ext.generateGodotLibraryVersion = { List<String> requiredKeys ->
String statusValue = map["status"]
if (statusValue == null) {
statusCode = 0
} else if (statusValue.startsWith("alpha")) {
} else if (statusValue.startsWith("dev")) {
statusCode = 1
} else if (statusValue.startsWith("beta")) {
} else if (statusValue.startsWith("alpha")) {
statusCode = 2
} else if (statusValue.startsWith("rc")) {
} else if (statusValue.startsWith("beta")) {
statusCode = 3
} else if (statusValue.startsWith("stable")) {
} else if (statusValue.startsWith("rc")) {
statusCode = 4
} else if (statusValue.startsWith("stable")) {
statusCode = 5
} else {
statusCode = 0
}

View File

@ -9,7 +9,7 @@ buildscript {
dependencies {
classpath libraries.androidGradlePlugin
classpath libraries.kotlinGradlePlugin
classpath 'io.github.gradle-nexus:publish-plugin:1.1.0'
classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
}
}
@ -38,9 +38,7 @@ ext {
supportedAbis = ["arm32", "arm64", "x86_32", "x86_64"]
supportedFlavors = ["editor", "template"]
supportedFlavorsBuildTypes = [
// The editor can't be used with target=release as debugging tools are then not
// included, and it would crash on errors instead of reporting them.
"editor": ["dev", "debug"],
"editor": ["dev", "debug", "release"],
"template": ["dev", "debug", "release"]
]
@ -54,6 +52,7 @@ ext {
def rootDir = "../../.."
def binDir = "$rootDir/bin/"
def androidEditorBuildsDir = "$binDir/android_editor_builds/"
def getSconsTaskName(String flavor, String buildType, String abi) {
return "compileGodotNativeLibs" + flavor.capitalize() + buildType.capitalize() + abi.capitalize()
@ -221,18 +220,46 @@ def isAndroidStudio() {
return sysProps != null && sysProps['idea.platform.prefix'] != null
}
task copyEditorDebugBinaryToBin(type: Copy) {
dependsOn ':editor:assembleDebug'
from('editor/build/outputs/apk/debug')
into(binDir)
include('android_editor.apk')
task copyEditorReleaseApkToBin(type: Copy) {
dependsOn ':editor:assembleRelease'
from('editor/build/outputs/apk/release')
into(androidEditorBuildsDir)
include('android_editor-release*.apk')
}
task copyEditorDevBinaryToBin(type: Copy) {
task copyEditorReleaseAabToBin(type: Copy) {
dependsOn ':editor:bundleRelease'
from('editor/build/outputs/bundle/release')
into(androidEditorBuildsDir)
include('android_editor-release*.aab')
}
task copyEditorDebugApkToBin(type: Copy) {
dependsOn ':editor:assembleDebug'
from('editor/build/outputs/apk/debug')
into(androidEditorBuildsDir)
include('android_editor-debug.apk')
}
task copyEditorDebugAabToBin(type: Copy) {
dependsOn ':editor:bundleDebug'
from('editor/build/outputs/bundle/debug')
into(androidEditorBuildsDir)
include('android_editor-debug.aab')
}
task copyEditorDevApkToBin(type: Copy) {
dependsOn ':editor:assembleDev'
from('editor/build/outputs/apk/dev')
into(binDir)
include('android_editor_dev.apk')
into(androidEditorBuildsDir)
include('android_editor-dev.apk')
}
task copyEditorDevAabToBin(type: Copy) {
dependsOn ':editor:bundleDev'
from('editor/build/outputs/bundle/dev')
into(androidEditorBuildsDir)
include('android_editor-dev.aab')
}
/**
@ -253,7 +280,8 @@ task generateGodotEditor {
&& targetLibs.isDirectory()
&& targetLibs.listFiles() != null
&& targetLibs.listFiles().length > 0) {
tasks += "copyEditor${target.capitalize()}BinaryToBin"
tasks += "copyEditor${target.capitalize()}ApkToBin"
tasks += "copyEditor${target.capitalize()}AabToBin"
}
}
@ -301,9 +329,11 @@ task cleanGodotEditor(type: Delete) {
// Delete the generated binary apks
delete("editor/build/outputs/apk")
// Delete the Godot editor apks in the Godot bin directory
delete("$binDir/android_editor.apk")
delete("$binDir/android_editor_dev.apk")
// Delete the generated aab binaries
delete("editor/build/outputs/bundle")
// Delete the Godot editor apks & aabs in the Godot bin directory
delete(androidEditorBuildsDir)
}
/**

View File

@ -13,22 +13,67 @@ dependencies {
}
ext {
// Build number added as a suffix to the version code, and incremented for each build/upload to
// the Google Play store.
// This should be reset on each stable release of Godot.
editorBuildNumber = 0
// Retrieve the build number from the environment variable; default to 0 if none is specified.
// The build number is added as a suffix to the version code for upload to the Google Play store.
getEditorBuildNumber = { ->
int buildNumber = 0
String versionStatus = System.getenv("GODOT_VERSION_STATUS")
if (versionStatus != null && !versionStatus.isEmpty()) {
try {
buildNumber = Integer.parseInt(versionStatus.replaceAll("[^0-9]", ""));
} catch (NumberFormatException ignored) {
buildNumber = 0
}
}
return buildNumber
}
// Value by which the Godot version code should be offset by to make room for the build number
editorBuildNumberOffset = 100
// Return the keystore file used for signing the release build.
getGodotKeystoreFile = { ->
def keyStore = System.getenv("GODOT_ANDROID_SIGN_KEYSTORE")
if (keyStore == null) {
return null
}
return file(keyStore)
}
// Return the key alias used for signing the release build.
getGodotKeyAlias = { ->
def kAlias = System.getenv("GODOT_ANDROID_KEYSTORE_ALIAS")
return kAlias
}
// Return the password for the key used for signing the release build.
getGodotSigningPassword = { ->
def signingPassword = System.getenv("GODOT_ANDROID_SIGN_PASSWORD")
return signingPassword
}
// Returns true if the environment variables contains the configuration for signing the release
// build.
hasReleaseSigningConfigs = { ->
def keystoreFile = getGodotKeystoreFile()
def keyAlias = getGodotKeyAlias()
def signingPassword = getGodotSigningPassword()
return keystoreFile != null && keystoreFile.isFile()
&& keyAlias != null && !keyAlias.isEmpty()
&& signingPassword != null && !signingPassword.isEmpty()
}
}
def generateVersionCode() {
int libraryVersionCode = getGodotLibraryVersionCode()
return (libraryVersionCode * editorBuildNumberOffset) + editorBuildNumber
return (libraryVersionCode * editorBuildNumberOffset) + getEditorBuildNumber()
}
def generateVersionName() {
String libraryVersionName = getGodotLibraryVersionName()
return libraryVersionName + ".$editorBuildNumber"
int buildNumber = getEditorBuildNumber()
return buildNumber == 0 ? libraryVersionName : libraryVersionName + ".$buildNumber"
}
android {
@ -45,6 +90,7 @@ android {
targetSdkVersion versions.targetSdk
missingDimensionStrategy 'products', 'editor'
setProperty("archivesBaseName", "android_editor")
}
compileOptions {
@ -56,6 +102,15 @@ android {
jvmTarget = versions.javaVersion
}
signingConfigs {
release {
storeFile getGodotKeystoreFile()
storePassword getGodotSigningPassword()
keyAlias getGodotKeyAlias()
keyPassword getGodotSigningPassword()
}
}
buildTypes {
dev {
initWith debug
@ -64,15 +119,14 @@ android {
debug {
initWith release
// Need to swap with the release signing config when this is ready for public release.
applicationIdSuffix ".debug"
signingConfig signingConfigs.debug
}
release {
// This buildtype is disabled below.
// The editor can't be used with target=release only, as debugging tools are then not
// included, and it would crash on errors instead of reporting them.
if (hasReleaseSigningConfigs()) {
signingConfig signingConfigs.release
}
}
}
@ -82,20 +136,4 @@ android {
doNotStrip '**/*.so'
}
}
// Disable 'release' buildtype.
// The editor can't be used with target=release only, as debugging tools are then not
// included, and it would crash on errors instead of reporting them.
variantFilter { variant ->
if (variant.buildType.name == "release") {
setIgnore(true)
}
}
applicationVariants.all { variant ->
variant.outputs.all { output ->
def suffix = variant.name == "dev" ? "_dev" : ""
output.outputFileName = "android_editor${suffix}.apk"
}
}
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="godot_editor_name_string">Godot Editor 4 (debug)</string>
</resources>

View File

@ -80,19 +80,11 @@ android {
release.jniLibs.srcDirs = ['libs/release']
// Editor jni library
editorRelease.jniLibs.srcDirs = ['libs/tools/release']
editorDebug.jniLibs.srcDirs = ['libs/tools/debug']
editorDev.jniLibs.srcDirs = ['libs/tools/dev']
}
// Disable 'editorRelease'.
// The editor can't be used with target=release as debugging tools are then not
// included, and it would crash on errors instead of reporting them.
variantFilter { variant ->
if (variant.name == "editorRelease") {
setIgnore(true)
}
}
libraryVariants.all { variant ->
def flavorName = variant.getFlavorName()
if (flavorName == null || flavorName == "") {
@ -105,9 +97,14 @@ android {
}
boolean devBuild = buildType == "dev"
boolean runTests = devBuild
boolean productionBuild = !devBuild
boolean storeRelease = buildType == "release"
def sconsTarget = flavorName
if (sconsTarget == "template") {
// Tests are not supported on template builds
runTests = false
switch (buildType) {
case "release":
sconsTarget += "_release"
@ -135,10 +132,10 @@ android {
def sconsExts = (org.gradle.internal.os.OperatingSystem.current().isWindows()
? [".bat", ".cmd", ".ps1", ".exe"]
: [""])
logger.lifecycle("Looking for $sconsName executable path")
logger.debug("Looking for $sconsName executable path")
for (ext in sconsExts) {
String sconsNameExt = sconsName + ext
logger.lifecycle("Checking $sconsNameExt")
logger.debug("Checking $sconsNameExt")
sconsExecutableFile = org.gradle.internal.os.OperatingSystem.current().findInPath(sconsNameExt)
if (sconsExecutableFile != null) {
// We're done!
@ -155,7 +152,7 @@ android {
if (sconsExecutableFile == null) {
throw new GradleException("Unable to find executable path for the '$sconsName' command.")
} else {
logger.lifecycle("Found executable path for $sconsName: ${sconsExecutableFile.absolutePath}")
logger.debug("Found executable path for $sconsName: ${sconsExecutableFile.absolutePath}")
}
for (String selectedAbi : selectedAbis) {
@ -167,7 +164,7 @@ android {
def taskName = getSconsTaskName(flavorName, buildType, selectedAbi)
tasks.create(name: taskName, type: Exec) {
executable sconsExecutableFile.absolutePath
args "--directory=${pathToRootDir}", "platform=android", "dev_mode=${devBuild}", "dev_build=${devBuild}", "target=${sconsTarget}", "arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors()
args "--directory=${pathToRootDir}", "platform=android", "store_release=${storeRelease}", "production=${productionBuild}", "dev_mode=${devBuild}", "dev_build=${devBuild}", "tests=${runTests}", "target=${sconsTarget}", "arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors()
}
// Schedule the tasks so the generated libs are present before the aar file is packaged.

View File

@ -166,8 +166,10 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
@Override
public void requestPointerCapture() {
super.requestPointerCapture();
inputHandler.onPointerCaptureChange(true);
if (canCapturePointer()) {
super.requestPointerCapture();
inputHandler.onPointerCaptureChange(true);
}
}
@Override

View File

@ -51,4 +51,8 @@ public interface GodotRenderView {
void configurePointerIcon(int pointerType, String imagePath, float hotSpotX, float hotSpotY);
void setPointerIcon(int pointerType);
default boolean canCapturePointer() {
return getInputHandler().canCapturePointer();
}
}

View File

@ -134,8 +134,10 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
@Override
public void requestPointerCapture() {
super.requestPointerCapture();
mInputHandler.onPointerCaptureChange(true);
if (canCapturePointer()) {
super.requestPointerCapture();
mInputHandler.onPointerCaptureChange(true);
}
}
@Override

View File

@ -227,35 +227,36 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
)
dragInProgress = false
}
return true
}
dragInProgress = true
val x = terminusEvent.x
val y = terminusEvent.y
if (terminusEvent.pointerCount >= 2 && panningAndScalingEnabled && !pointerCaptureInProgress) {
if (terminusEvent.pointerCount >= 2 && panningAndScalingEnabled && !pointerCaptureInProgress && !dragInProgress) {
GodotLib.pan(x, y, distanceX / 5f, distanceY / 5f)
} else {
} else if (!scaleInProgress){
dragInProgress = true
GodotInputHandler.handleMotionEvent(terminusEvent)
}
return true
}
override fun onScale(detector: ScaleGestureDetector): Boolean {
if (!panningAndScalingEnabled || pointerCaptureInProgress) {
if (!panningAndScalingEnabled || pointerCaptureInProgress || dragInProgress) {
return false
}
GodotLib.magnify(
detector.focusX,
detector.focusY,
detector.scaleFactor
)
if (detector.scaleFactor >= 0.8f && detector.scaleFactor != 1f && detector.scaleFactor <= 1.2f) {
GodotLib.magnify(
detector.focusX,
detector.focusY,
detector.scaleFactor
)
}
return true
}
override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
if (!panningAndScalingEnabled || pointerCaptureInProgress) {
if (!panningAndScalingEnabled || pointerCaptureInProgress || dragInProgress) {
return false
}
scaleInProgress = true

View File

@ -66,6 +66,11 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
private final ScaleGestureDetector scaleGestureDetector;
private final GodotGestureHandler godotGestureHandler;
/**
* Used to decide whether mouse capture can be enabled.
*/
private int lastSeenToolType = MotionEvent.TOOL_TYPE_UNKNOWN;
public GodotInputHandler(GodotRenderView godotView) {
final Context context = godotView.getView().getContext();
mRenderView = godotView;
@ -105,6 +110,10 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
return (source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || (source & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD || (source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD;
}
public boolean canCapturePointer() {
return lastSeenToolType == MotionEvent.TOOL_TYPE_MOUSE;
}
public void onPointerCaptureChange(boolean hasCapture) {
godotGestureHandler.onPointerCaptureChange(hasCapture);
}
@ -174,6 +183,8 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
}
public boolean onTouchEvent(final MotionEvent event) {
lastSeenToolType = event.getToolType(0);
this.scaleGestureDetector.onTouchEvent(event);
if (this.gestureDetector.onTouchEvent(event)) {
// The gesture detector has handled the event.
@ -198,6 +209,8 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
}
public boolean onGenericMotionEvent(MotionEvent event) {
lastSeenToolType = event.getToolType(0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && gestureDetector.onGenericMotionEvent(event)) {
// The gesture detector has handled the event.
return true;
@ -471,15 +484,27 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
}
static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float y, float deltaX, float deltaY, boolean doubleClick, boolean sourceMouseRelative) {
// Fix the buttonsMask
switch (eventAction) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// Zero-up the button state
buttonsMask = 0;
break;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (buttonsMask == 0) {
buttonsMask = MotionEvent.BUTTON_PRIMARY;
}
break;
}
// We don't handle ACTION_BUTTON_PRESS and ACTION_BUTTON_RELEASE events as they typically
// follow ACTION_DOWN and ACTION_UP events. As such, handling them would result in duplicate
// stream of events to the engine.
switch (eventAction) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// Zero-up the button state
buttonsMask = 0;
// FALL THROUGH
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_HOVER_ENTER:
case MotionEvent.ACTION_HOVER_EXIT:

View File

@ -49,6 +49,8 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
_request_pointer_capture = env->GetMethodID(_cls, "requestPointerCapture", "()V");
_release_pointer_capture = env->GetMethodID(_cls, "releasePointerCapture", "()V");
}
_can_capture_pointer = env->GetMethodID(_cls, "canCapturePointer", "()Z");
}
bool GodotJavaViewWrapper::can_update_pointer_icon() const {
@ -56,7 +58,16 @@ bool GodotJavaViewWrapper::can_update_pointer_icon() const {
}
bool GodotJavaViewWrapper::can_capture_pointer() const {
return _request_pointer_capture != nullptr && _release_pointer_capture != nullptr;
// We can capture the pointer if the other jni capture method ids are initialized,
// and GodotView#canCapturePointer() returns true.
if (_request_pointer_capture != nullptr && _release_pointer_capture != nullptr && _can_capture_pointer != nullptr) {
JNIEnv *env = get_jni_env();
ERR_FAIL_NULL_V(env, false);
return env->CallBooleanMethod(_godot_view, _can_capture_pointer);
}
return false;
}
void GodotJavaViewWrapper::request_pointer_capture() {

View File

@ -44,6 +44,7 @@ private:
jobject _godot_view;
jmethodID _can_capture_pointer = 0;
jmethodID _request_pointer_capture = 0;
jmethodID _release_pointer_capture = 0;

View File

@ -182,7 +182,7 @@ String OS_Android::get_name() const {
}
String OS_Android::get_system_property(const char *key) const {
static String value;
String value;
char value_str[PROP_VALUE_MAX];
if (__system_property_get(key, value_str)) {
value = String(value_str);
@ -230,20 +230,20 @@ String OS_Android::get_version() const {
"ro.potato.version", "ro.xtended.version", "org.evolution.version", "ro.corvus.version", "ro.pa.version",
"ro.crdroid.version", "ro.syberia.version", "ro.arrow.version", "ro.lineage.version" };
for (int i = 0; i < roms.size(); i++) {
static String rom_version = get_system_property(roms[i]);
String rom_version = get_system_property(roms[i]);
if (!rom_version.is_empty()) {
return rom_version;
}
}
static String mod_version = get_system_property("ro.modversion"); // Handles other Android custom ROMs.
String mod_version = get_system_property("ro.modversion"); // Handles other Android custom ROMs.
if (!mod_version.is_empty()) {
return mod_version;
}
// Handles stock Android.
static String sdk_version = get_system_property("ro.build.version.sdk_int");
static String build = get_system_property("ro.build.version.incremental");
String sdk_version = get_system_property("ro.build.version.sdk_int");
String build = get_system_property("ro.build.version.incremental");
if (!sdk_version.is_empty()) {
if (!build.is_empty()) {
return vformat("%s.%s", sdk_version, build);

View File

@ -74,6 +74,7 @@ void JoypadLinux::Joypad::reset() {
events.clear();
}
#ifdef UDEV_ENABLED
// This function is derived from SDL:
// https://github.com/libsdl-org/SDL/blob/main/src/core/linux/SDL_sandbox.c#L28-L45
static bool detect_sandbox() {
@ -93,6 +94,7 @@ static bool detect_sandbox() {
return false;
}
#endif // UDEV_ENABLED
JoypadLinux::JoypadLinux(Input *in) {
#ifdef UDEV_ENABLED

View File

@ -210,48 +210,54 @@ String OS_LinuxBSD::get_name() const {
}
String OS_LinuxBSD::get_systemd_os_release_info_value(const String &key) const {
static String info;
if (info.is_empty()) {
Ref<FileAccess> f = FileAccess::open("/etc/os-release", FileAccess::READ);
if (f.is_valid()) {
while (!f->eof_reached()) {
const String line = f->get_line();
if (line.find(key) != -1) {
return line.split("=")[1].strip_edges();
}
Ref<FileAccess> f = FileAccess::open("/etc/os-release", FileAccess::READ);
if (f.is_valid()) {
while (!f->eof_reached()) {
const String line = f->get_line();
if (line.find(key) != -1) {
String value = line.split("=")[1].strip_edges();
value = value.trim_prefix("\"");
return value.trim_suffix("\"");
}
}
}
return info;
return "";
}
String OS_LinuxBSD::get_distribution_name() const {
static String systemd_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string.
if (!systemd_name.is_empty()) {
return systemd_name;
static String distribution_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string.
if (!distribution_name.is_empty()) {
return distribution_name;
}
struct utsname uts; // returns a decent value for BSD family.
uname(&uts);
return uts.sysname;
distribution_name = uts.sysname;
return distribution_name;
}
String OS_LinuxBSD::get_version() const {
static String systemd_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string.
if (!systemd_version.is_empty()) {
return systemd_version;
static String release_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string.
if (!release_version.is_empty()) {
return release_version;
}
struct utsname uts; // returns a decent value for BSD family.
uname(&uts);
return uts.version;
release_version = uts.version;
return release_version;
}
Vector<String> OS_LinuxBSD::get_video_adapter_driver_info() const {
if (RenderingServer::get_singleton()->get_rendering_device() == nullptr) {
if (RenderingServer::get_singleton() == nullptr) {
return Vector<String>();
}
const String rendering_device_name = RenderingServer::get_singleton()->get_rendering_device()->get_device_name(); // e.g. `NVIDIA GeForce GTX 970`
const String rendering_device_vendor = RenderingServer::get_singleton()->get_rendering_device()->get_device_vendor_name(); // e.g. `NVIDIA`
static Vector<String> info;
if (!info.is_empty()) {
return info;
}
const String rendering_device_name = RenderingServer::get_singleton()->get_video_adapter_name(); // e.g. `NVIDIA GeForce GTX 970`
const String rendering_device_vendor = RenderingServer::get_singleton()->get_video_adapter_vendor(); // e.g. `NVIDIA`
const String card_name = rendering_device_name.trim_prefix(rendering_device_vendor).strip_edges(); // -> `GeForce GTX 970`
String vendor_device_id_mappings;
@ -315,8 +321,8 @@ Vector<String> OS_LinuxBSD::get_video_adapter_driver_info() const {
Vector<String> class_display_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_display_device_candidates, kernel_lit, dummys);
Vector<String> class_3d_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_3d_device_candidates, kernel_lit, dummys);
static String driver_name;
static String driver_version;
String driver_name;
String driver_version;
// Use first valid value:
for (const String &driver : class_3d_device_drivers) {
@ -336,7 +342,6 @@ Vector<String> OS_LinuxBSD::get_video_adapter_driver_info() const {
}
}
Vector<String> info;
info.push_back(driver_name);
String modinfo;

View File

@ -450,8 +450,7 @@ String OS_UWP::get_distribution_name() const {
String OS_UWP::get_version() const {
winrt::hstring df_version = VersionInfo().DeviceFamilyVersion();
static String version = String(winrt::to_string(df_version).c_str());
return version;
return String(winrt::to_string(df_version).c_str());
}
OS::DateTime OS_UWP::get_datetime(bool p_utc) const {

View File

@ -1070,6 +1070,10 @@ bool DisplayServerWeb::can_any_window_draw() const {
return true;
}
DisplayServer::VSyncMode DisplayServerWeb::window_get_vsync_mode(WindowID p_vsync_mode) const {
return DisplayServer::VSYNC_ENABLED;
}
void DisplayServerWeb::process_events() {
Input::get_singleton()->flush_buffered_events();
if (godot_js_input_gamepad_sample() == OK) {

View File

@ -213,6 +213,8 @@ public:
virtual bool can_any_window_draw() const override;
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
// events
virtual void process_events() override;

View File

@ -352,20 +352,25 @@ String OS_Windows::get_version() const {
}
Vector<String> OS_Windows::get_video_adapter_driver_info() const {
if (RenderingServer::get_singleton()->get_rendering_device() == nullptr) {
if (RenderingServer::get_singleton() == nullptr) {
return Vector<String>();
}
static Vector<String> info;
if (!info.is_empty()) {
return info;
}
REFCLSID clsid = CLSID_WbemLocator; // Unmarshaler CLSID
REFIID uuid = IID_IWbemLocator; // Interface UUID
IWbemLocator *wbemLocator = NULL; // to get the services
IWbemServices *wbemServices = NULL; // to get the class
IEnumWbemClassObject *iter = NULL;
IWbemClassObject *pnpSDriverObject[1]; // contains driver name, version, etc.
static String driver_name;
static String driver_version;
String driver_name;
String driver_version;
const String device_name = RenderingServer::get_singleton()->get_rendering_device()->get_device_name();
const String device_name = RenderingServer::get_singleton()->get_video_adapter_name();
if (device_name.is_empty()) {
return Vector<String>();
}
@ -439,7 +444,6 @@ Vector<String> OS_Windows::get_video_adapter_driver_info() const {
SAFE_RELEASE(wbemServices)
SAFE_RELEASE(iter)
Vector<String> info;
info.push_back(driver_name);
info.push_back(driver_version);

View File

@ -157,7 +157,6 @@ void AudioStreamPlayer2D::_update_panning() {
Vector2 global_pos = get_global_position();
HashSet<Viewport *> viewports = world_2d->get_viewports();
viewports.insert(get_viewport()); // TODO: This is a mediocre workaround for #50958. Remove when that bug is fixed!
volume_vector.resize(4);
volume_vector.write[0] = AudioFrame(0, 0);
@ -188,11 +187,11 @@ void AudioStreamPlayer2D::_update_panning() {
float dist = global_pos.distance_to(listener_in_global); // Distance to listener, or screen if none.
if (dist > max_distance) {
continue; //can't hear this sound in this viewport
continue; // Can't hear this sound in this viewport.
}
float multiplier = Math::pow(1.0f - dist / max_distance, attenuation);
multiplier *= Math::db_to_linear(volume_db); //also apply player volume!
multiplier *= Math::db_to_linear(volume_db); // Also apply player volume!
float pan = relative_to_listener.x / screen_size.x;
// Don't let the panning effect extend (too far) beyond the screen.
@ -206,7 +205,9 @@ void AudioStreamPlayer2D::_update_panning() {
float l = 1.0 - pan;
float r = pan;
volume_vector.write[0] = AudioFrame(l, r) * multiplier;
const AudioFrame &prev_sample = volume_vector[0];
AudioFrame new_sample = AudioFrame(l, r) * multiplier;
volume_vector.write[0] = AudioFrame(MAX(prev_sample[0], new_sample[0]), MAX(prev_sample[1], new_sample[1]));
}
for (const Ref<AudioStreamPlayback> &playback : stream_playbacks) {

View File

@ -378,15 +378,12 @@ uint64_t Skeleton3D::get_version() const {
}
void Skeleton3D::add_bone(const String &p_name) {
ERR_FAIL_COND(p_name.is_empty() || p_name.contains(":") || p_name.contains("/"));
for (int i = 0; i < bones.size(); i++) {
ERR_FAIL_COND(bones[i].name == p_name);
}
ERR_FAIL_COND(p_name.is_empty() || p_name.contains(":") || p_name.contains("/") || name_to_bone_index.has(p_name));
Bone b;
b.name = p_name;
bones.push_back(b);
name_to_bone_index.insert(p_name, bones.size() - 1);
process_order_dirty = true;
version++;
rest_dirty = true;
@ -395,13 +392,8 @@ void Skeleton3D::add_bone(const String &p_name) {
}
int Skeleton3D::find_bone(const String &p_name) const {
for (int i = 0; i < bones.size(); i++) {
if (bones[i].name == p_name) {
return i;
}
}
return -1;
const int *bone_index_ptr = name_to_bone_index.getptr(p_name);
return bone_index_ptr != nullptr ? *bone_index_ptr : -1;
}
String Skeleton3D::get_bone_name(int p_bone) const {
@ -409,17 +401,21 @@ String Skeleton3D::get_bone_name(int p_bone) const {
ERR_FAIL_INDEX_V(p_bone, bone_size, "");
return bones[p_bone].name;
}
void Skeleton3D::set_bone_name(int p_bone, const String &p_name) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
for (int i = 0; i < bone_size; i++) {
if (i != p_bone) {
ERR_FAIL_COND_MSG(bones[i].name == p_name, "Skeleton3D: '" + get_name() + "', bone name: '" + p_name + "' is already exist.");
}
const int *bone_index_ptr = name_to_bone_index.getptr(p_name);
if (bone_index_ptr != nullptr) {
ERR_FAIL_COND_MSG(*bone_index_ptr != p_bone, "Skeleton3D: '" + get_name() + "', bone name: '" + p_name + "' already exists.");
return; // No need to rename, the bone already has the given name.
}
name_to_bone_index.erase(bones[p_bone].name);
bones.write[p_bone].name = p_name;
name_to_bone_index.insert(p_name, p_bone);
version++;
}
@ -547,6 +543,7 @@ bool Skeleton3D::is_show_rest_only() const {
void Skeleton3D::clear_bones() {
bones.clear();
name_to_bone_index.clear();
process_order_dirty = true;
version++;
_make_dirty();

View File

@ -125,6 +125,7 @@ private:
bool process_order_dirty = false;
Vector<int> parentless_bones;
HashMap<String, int> name_to_bone_index;
void _make_dirty();
bool dirty = false;

View File

@ -1766,7 +1766,7 @@ void AnimationPlayer::set_current_animation(const String &p_anim) {
} else if (!is_playing()) {
play(p_anim);
} else if (playback.assigned != p_anim) {
float speed = get_playing_speed();
float speed = playback.current.speed_scale;
play(p_anim, -1.0, speed, signbit(speed));
} else {
// Same animation, do not replay from start
@ -1779,7 +1779,7 @@ String AnimationPlayer::get_current_animation() const {
void AnimationPlayer::set_assigned_animation(const String &p_anim) {
if (is_playing()) {
float speed = get_playing_speed();
float speed = playback.current.speed_scale;
play(p_anim, -1.0, speed, signbit(speed));
} else {
ERR_FAIL_COND_MSG(!animation_set.has(p_anim), vformat("Animation not found: %s.", p_anim));

View File

@ -561,13 +561,14 @@ void ColorPicker::_update_presets() {
#ifdef TOOLS_ENABLED
if (editor_settings) {
// Only load preset buttons when the only child is the add-preset button.
if (preset_container->get_child_count() == 1) {
for (int i = 0; i < preset_cache.size(); i++) {
_add_preset_button(preset_size, preset_cache[i]);
}
_notification(NOTIFICATION_VISIBILITY_CHANGED);
// Rebuild swatch color buttons, keeping the add-preset button in the first position.
for (int i = 1; i < preset_container->get_child_count(); i++) {
preset_container->get_child(i)->queue_free();
}
for (int i = 0; i < preset_cache.size(); i++) {
_add_preset_button(preset_size, preset_cache[i]);
}
_notification(NOTIFICATION_VISIBILITY_CHANGED);
}
#endif
}

View File

@ -39,7 +39,7 @@
void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> key = p_event;
if (close_on_escape && key.is_valid() && key->is_pressed() && key->get_keycode() == Key::ESCAPE) {
if (close_on_escape && key.is_valid() && key->is_action_pressed(SNAME("ui_cancel"), false, true)) {
_cancel_pressed();
}
}

View File

@ -1366,11 +1366,12 @@ void ItemList::_notification(int p_what) {
text_ofs += base_ofs;
text_ofs += items[i].rect_cache.position;
if (rtl) {
text_ofs.x = size.width - text_ofs.x - max_len;
}
float text_w = width - text_ofs.x;
items.write[i].text_buf->set_width(text_w);
items.write[i].text_buf->set_width(width - text_ofs.x);
if (rtl) {
text_ofs.x = size.width - width;
}
if (rtl) {
items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_RIGHT);

View File

@ -36,7 +36,7 @@
void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> key = p_event;
if (get_flag(FLAG_POPUP) && key.is_valid() && key->is_pressed() && key->get_keycode() == Key::ESCAPE) {
if (get_flag(FLAG_POPUP) && key.is_valid() && key->is_action_pressed(SNAME("ui_cancel"), false, true)) {
_close_pressed();
}
}

View File

@ -177,7 +177,7 @@ void ViewportTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_viewport_path_in_scene", "path"), &ViewportTexture::set_viewport_path_in_scene);
ClassDB::bind_method(D_METHOD("get_viewport_path_in_scene"), &ViewportTexture::get_viewport_path_in_scene);
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "SubViewport", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT), "set_viewport_path_in_scene", "get_viewport_path_in_scene");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Viewport", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT), "set_viewport_path_in_scene", "get_viewport_path_in_scene");
}
ViewportTexture::ViewportTexture() {
@ -544,6 +544,7 @@ void Viewport::_notification(int p_what) {
gui.mouse_in_viewport = false;
_drop_physics_mouseover();
_drop_mouse_over();
_gui_cancel_tooltip();
// When the mouse exits the viewport, we want to end mouse_over, but
// not mouse_focus, because, for example, we want to continue
// dragging a scrollbar even if the mouse has left the viewport.
@ -1080,6 +1081,10 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas);
}
if (world_2d.is_valid()) {
world_2d->remove_viewport(this);
}
if (p_world_2d.is_valid()) {
world_2d = p_world_2d;
} else {
@ -1087,6 +1092,7 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
world_2d = Ref<World2D>(memnew(World2D));
}
world_2d->register_viewport(this);
_update_audio_listener_2d();
if (is_inside_tree()) {
@ -2828,6 +2834,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
void Viewport::push_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
ERR_FAIL_COND(!is_inside_tree());
ERR_FAIL_COND(p_event.is_null());
if (disable_input) {
return;
@ -4155,6 +4162,7 @@ void Viewport::_validate_property(PropertyInfo &p_property) const {
Viewport::Viewport() {
world_2d = Ref<World2D>(memnew(World2D));
world_2d->register_viewport(this);
viewport = RenderingServer::get_singleton()->viewport_create();
texture_rid = RenderingServer::get_singleton()->viewport_get_texture(viewport);

View File

@ -695,6 +695,8 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeParticleAccelerator);
GDREGISTER_CLASS(VisualShaderNodeParticleEmit);
GDREGISTER_VIRTUAL_CLASS(Material);
GDREGISTER_CLASS(PlaceholderMaterial);
GDREGISTER_CLASS(ShaderMaterial);
GDREGISTER_ABSTRACT_CLASS(CanvasItem);
GDREGISTER_CLASS(CanvasTexture);
@ -802,11 +804,9 @@ void register_scene_types() {
GDREGISTER_CLASS(TubeTrailMesh);
GDREGISTER_CLASS(RibbonTrailMesh);
GDREGISTER_CLASS(PointMesh);
GDREGISTER_VIRTUAL_CLASS(Material);
GDREGISTER_ABSTRACT_CLASS(BaseMaterial3D);
GDREGISTER_CLASS(StandardMaterial3D);
GDREGISTER_CLASS(ORMMaterial3D);
GDREGISTER_CLASS(PlaceholderMaterial);
GDREGISTER_CLASS(ProceduralSkyMaterial);
GDREGISTER_CLASS(PanoramaSkyMaterial);
GDREGISTER_CLASS(PhysicalSkyMaterial);

View File

@ -82,6 +82,14 @@ PhysicsDirectSpaceState2D *World2D::get_direct_space_state() {
return PhysicsServer2D::get_singleton()->space_get_direct_state(get_space());
}
void World2D::register_viewport(Viewport *p_viewport) {
viewports.insert(p_viewport);
}
void World2D::remove_viewport(Viewport *p_viewport) {
viewports.erase(p_viewport);
}
World2D::World2D() {
canvas = RenderingServer::get_singleton()->canvas_create();
}

View File

@ -52,9 +52,6 @@ protected:
static void _bind_methods();
friend class Viewport;
void _register_viewport(Viewport *p_viewport);
void _remove_viewport(Viewport *p_viewport);
public:
RID get_canvas() const;
RID get_space() const;
@ -62,6 +59,9 @@ public:
PhysicsDirectSpaceState2D *get_direct_space_state();
void register_viewport(Viewport *p_viewport);
void remove_viewport(Viewport *p_viewport);
_FORCE_INLINE_ const HashSet<Viewport *> &get_viewports() { return viewports; }
World2D();

View File

@ -76,7 +76,7 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas
}
}
void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2D p_transform, RendererCanvasCull::Item *p_material_owner, RendererCanvasCull::Item **r_items, int &r_index, int p_z) {
void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2D p_transform, RendererCanvasCull::Item *p_material_owner, const Color &p_modulate, RendererCanvasCull::Item **r_items, int &r_index, int p_z) {
int child_item_count = p_canvas_item->child_items.size();
RendererCanvasCull::Item **child_items = p_canvas_item->child_items.ptrw();
for (int i = 0; i < child_item_count; i++) {
@ -87,6 +87,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
child_items[i]->ysort_xform = p_transform;
child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.columns[2]);
child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr;
child_items[i]->ysort_modulate = p_modulate;
child_items[i]->ysort_index = r_index;
child_items[i]->ysort_parent_abs_z_index = p_z;
@ -101,7 +102,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
r_index++;
if (child_items[i]->sort_y) {
_collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index, abs_z);
_collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], p_modulate * child_items[i]->modulate, r_items, r_index, abs_z);
}
}
}
@ -301,7 +302,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
if (allow_y_sort) {
if (ci->ysort_children_count == -1) {
ci->ysort_children_count = 0;
_collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count, p_z);
_collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), nullptr, ci->ysort_children_count, p_z);
}
child_item_count = ci->ysort_children_count + 1;
@ -310,14 +311,15 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
ci->ysort_parent_abs_z_index = parent_z;
child_items[0] = ci;
int i = 1;
_collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i, p_z);
_collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), child_items, i, p_z);
ci->ysort_xform = ci->xform.affine_inverse();
ci->ysort_modulate = Color(1, 1, 1, 1);
SortArray<Item *, ItemPtrSort> sorter;
sorter.sort(child_items, child_item_count);
for (i = 0; i < child_item_count; i++) {
_cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, canvas_cull_mask);
_cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, canvas_cull_mask);
}
} else {
RendererCanvasRender::Item *canvas_group_from = nullptr;

View File

@ -312,11 +312,21 @@ ALBEDO = vec3(1.0);
void Fog::free_fog_shader() {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
RD::get_singleton()->free(volumetric_fog.volume_ubo);
RD::get_singleton()->free(volumetric_fog.params_ubo);
material_storage->shader_free(volumetric_fog.default_shader);
material_storage->material_free(volumetric_fog.default_material);
if (volumetric_fog.process_shader_version.is_valid()) {
volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
}
if (volumetric_fog.volume_ubo.is_valid()) {
RD::get_singleton()->free(volumetric_fog.volume_ubo);
}
if (volumetric_fog.params_ubo.is_valid()) {
RD::get_singleton()->free(volumetric_fog.params_ubo);
}
if (volumetric_fog.default_shader.is_valid()) {
material_storage->shader_free(volumetric_fog.default_shader);
}
if (volumetric_fog.default_material.is_valid()) {
material_storage->material_free(volumetric_fog.default_material);
}
}
void Fog::FogShaderData::set_code(const String &p_code) {

View File

@ -3581,18 +3581,40 @@ void GI::init(SkyRD *p_sky) {
}
void GI::free() {
RD::get_singleton()->free(default_voxel_gi_buffer);
RD::get_singleton()->free(voxel_gi_lights_uniform);
RD::get_singleton()->free(sdfgi_ubo);
if (default_voxel_gi_buffer.is_valid()) {
RD::get_singleton()->free(default_voxel_gi_buffer);
}
if (voxel_gi_lights_uniform.is_valid()) {
RD::get_singleton()->free(voxel_gi_lights_uniform);
}
if (sdfgi_ubo.is_valid()) {
RD::get_singleton()->free(sdfgi_ubo);
}
voxel_gi_debug_shader.version_free(voxel_gi_debug_shader_version);
voxel_gi_shader.version_free(voxel_gi_lighting_shader_version);
shader.version_free(shader_version);
sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader);
sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader);
sdfgi_shader.direct_light.version_free(sdfgi_shader.direct_light_shader);
sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader);
sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader);
if (voxel_gi_debug_shader_version.is_valid()) {
voxel_gi_debug_shader.version_free(voxel_gi_debug_shader_version);
}
if (voxel_gi_lighting_shader_version.is_valid()) {
voxel_gi_shader.version_free(voxel_gi_lighting_shader_version);
}
if (shader_version.is_valid()) {
shader.version_free(shader_version);
}
if (sdfgi_shader.debug_probes_shader.is_valid()) {
sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader);
}
if (sdfgi_shader.debug_shader.is_valid()) {
sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader);
}
if (sdfgi_shader.direct_light_shader.is_valid()) {
sdfgi_shader.direct_light.version_free(sdfgi_shader.direct_light_shader);
}
if (sdfgi_shader.integrate_shader.is_valid()) {
sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader);
}
if (sdfgi_shader.preprocess_shader.is_valid()) {
sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader);
}
if (voxel_gi_lights) {
memdelete_arr(voxel_gi_lights);

View File

@ -964,7 +964,12 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
scene_data.z_far = p_camera_data->main_projection.get_z_far();
// this should be the same for all cameras..
scene_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
const float lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
// Also, take into account resolution scaling for the multiplier, since we have more leeway with quality
// degradation visibility. Conversely, allow upwards scaling, too, for increased mesh detail at high res.
const float scaling_3d_scale = GLOBAL_GET("rendering/scaling_3d/scale");
scene_data.lod_distance_multiplier = lod_distance_multiplier * (1.0 / scaling_3d_scale);
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
scene_data.screen_mesh_lod_threshold = 0.0;

View File

@ -627,7 +627,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
if (skeleton->use_2d) {
for (int j = 0; j < bs; j++) {
if (skbones[0].size == Vector3()) {
if (skbones[j].size == Vector3(-1, -1, -1)) {
continue; //bone is unused
}
@ -654,7 +654,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
}
} else {
for (int j = 0; j < bs; j++) {
if (skbones[0].size == Vector3()) {
if (skbones[j].size == Vector3(-1, -1, -1)) {
continue; //bone is unused
}

View File

@ -1153,8 +1153,8 @@ void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &
image = image->duplicate();
image->convert(tex->validated_format);
}
all_data_size += images[i]->get_data().size();
images.push_back(image);
all_data_size += image->get_data().size();
images.write[i] = image;
}
all_data.resize(all_data_size); //consolidate all data here

View File

@ -34,7 +34,6 @@
#include "core/object/worker_thread_pool.h"
#include "core/os/os.h"
#include "rendering_server_default.h"
#include "rendering_server_globals.h"
#include <new>

View File

@ -42,6 +42,7 @@
#include "servers/rendering/renderer_scene_occlusion_cull.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_method.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/storage/utilities.h"
#include "servers/xr/xr_interface.h"
@ -516,6 +517,29 @@ public:
} else if (p_dependency == instance->skeleton) {
singleton->instance_attach_skeleton(instance->self, RID());
} else {
// It's possible the same material is used in multiple slots,
// so we check whether we need to clear them all.
if (p_dependency == instance->material_override) {
singleton->instance_geometry_set_material_override(instance->self, RID());
}
if (p_dependency == instance->material_overlay) {
singleton->instance_geometry_set_material_overlay(instance->self, RID());
}
for (int i = 0; i < instance->materials.size(); i++) {
if (p_dependency == instance->materials[i]) {
singleton->instance_set_surface_override_material(instance->self, i, RID());
}
}
if (instance->base_type == RS::INSTANCE_PARTICLES) {
RID particle_material = RSG::particles_storage->particles_get_process_material(instance->base);
if (p_dependency == particle_material) {
RSG::particles_storage->particles_set_process_material(instance->base, RID());
}
}
// Even if no change is made we still need to call `_instance_queue_update`.
// This dependency could also be a result of the freed material being used
// by the mesh this mesh instance uses.
singleton->_instance_queue_update(instance, false, true);
}
}

View File

@ -693,6 +693,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
real_t width = 0.f;
int line_start = MAX(p_start, range.x);
int last_end = line_start;
int prev_safe_break = 0;
int last_safe_break = -1;
int word_count = 0;
@ -718,12 +719,18 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
end_pos -= l_gl[end_pos].count;
}
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
last_end = l_gl[end_pos].end;
}
trim_next = true;
} else {
lines.push_back(line_start);
lines.push_back(l_gl[last_safe_break].end);
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[last_safe_break].end);
last_end = l_gl[last_safe_break].end;
}
}
line_start = l_gl[last_safe_break].end;
prev_safe_break = last_safe_break + 1;
@ -751,12 +758,18 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
end_pos -= l_gl[end_pos].count;
}
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
last_end = l_gl[end_pos].end;
}
trim_next = false;
} else {
lines.push_back(line_start);
lines.push_back(l_gl[i].end);
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[i].end);
last_end = l_gl[i].end;
}
}
line_start = l_gl[i].end;
prev_safe_break = i + 1;
@ -812,6 +825,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
double width = 0.f;
int line_start = MAX(p_start, range.x);
int last_end = line_start;
int prev_safe_break = 0;
int last_safe_break = -1;
int word_count = 0;
@ -836,12 +850,18 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
end_pos -= l_gl[end_pos].count;
}
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
last_end = l_gl[end_pos].end;
}
trim_next = true;
} else {
lines.push_back(line_start);
lines.push_back(l_gl[last_safe_break].end);
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[last_safe_break].end);
last_end = l_gl[last_safe_break].end;
}
}
line_start = l_gl[last_safe_break].end;
prev_safe_break = last_safe_break + 1;
@ -863,11 +883,17 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
end_pos -= l_gl[end_pos].count;
}
trim_next = false;
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
last_end = l_gl[end_pos].end;
}
} else {
lines.push_back(line_start);
lines.push_back(l_gl[i].end);
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[i].end);
last_end = l_gl[i].end;
}
}
line_start = l_gl[i].end;
prev_safe_break = i + 1;

View File

@ -45,6 +45,7 @@
#include <cmath>
#endif
#include <cstdio>
#include <cstdint>
#include <cstdlib>
#include <list>
#include <map>

View File

@ -0,0 +1,12 @@
diff --git a/thirdparty/openxr/src/common/platform_utils.hpp b/thirdparty/openxr/src/common/platform_utils.hpp
index 85d5cdab10..2d870cfea7 100644
--- a/thirdparty/openxr/src/common/platform_utils.hpp
+++ b/thirdparty/openxr/src/common/platform_utils.hpp
@@ -11,6 +11,7 @@
#include "xr_dependencies.h"
#include <string>
+#include <stdint.h>
#include <stdlib.h>
// OpenXR paths and registry key locations

View File

@ -11,6 +11,7 @@
#include "xr_dependencies.h"
#include <string>
#include <stdint.h>
#include <stdlib.h>
// OpenXR paths and registry key locations

View File

@ -13,3 +13,26 @@ index 132bdcfb3e..925584cf52 100644
namespace VHACD {
//! Incremental Convex Hull algorithm (cf. http://cs.smith.edu/~orourke/books/ftp.html ).
enum ICHullError {
diff --git a/thirdparty/vhacd/inc/vhacdManifoldMesh.h b/thirdparty/vhacd/inc/vhacdManifoldMesh.h
index a48f53c5c5..5eed4e13aa 100644
--- a/thirdparty/vhacd/inc/vhacdManifoldMesh.h
+++ b/thirdparty/vhacd/inc/vhacdManifoldMesh.h
@@ -18,6 +18,11 @@ All rights reserved.
#include "vhacdCircularList.h"
#include "vhacdSArray.h"
#include "vhacdVector.h"
+
+// -- GODOT start --
+#include <cstdint>
+// -- GODOT end --
+
namespace VHACD {
class TMMTriangle;
class TMMEdge;
@@ -139,4 +144,4 @@ private:
friend class ICHull;
};
}
-#endif // VHACD_MANIFOLD_MESH_H
\ No newline at end of file
+#endif // VHACD_MANIFOLD_MESH_H

View File

@ -18,6 +18,11 @@ All rights reserved.
#include "vhacdCircularList.h"
#include "vhacdSArray.h"
#include "vhacdVector.h"
// -- GODOT start --
#include <cstdint>
// -- GODOT end --
namespace VHACD {
class TMMTriangle;
class TMMEdge;
@ -139,4 +144,4 @@ private:
friend class ICHull;
};
}
#endif // VHACD_MANIFOLD_MESH_H
#endif // VHACD_MANIFOLD_MESH_H