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:
commit
c8e0bd50c5
|
@ -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
|
||||
|
|
|
@ -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 }}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -115,6 +115,7 @@ private:
|
|||
// Constant
|
||||
float _hover_radius;
|
||||
float _tangents_length;
|
||||
float _gizmo_handle_scale = 1.0;
|
||||
};
|
||||
|
||||
class EditorInspectorPluginCurve : public EditorInspectorPlugin {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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 ®_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 ®_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 ®_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 ®_container) {
|
||||
Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<String> &lines, const RegExContainer ®_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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,8 +90,8 @@ class ProjectConverter3To4 {
|
|||
void rename_csharp_attributes(Vector<SourceLine> &source_lines, const RegExContainer ®_container);
|
||||
Vector<String> check_for_rename_csharp_attributes(Vector<String> &lines, const RegExContainer ®_container);
|
||||
|
||||
void rename_gdscript_keywords(Vector<SourceLine> &source_lines, const RegExContainer ®_container);
|
||||
Vector<String> check_for_rename_gdscript_keywords(Vector<String> &lines, const RegExContainer ®_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 ®_container);
|
||||
Vector<String> check_for_rename_input_map_scancode(Vector<String> &lines, const RegExContainer ®_container);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 |
|
@ -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 |
|
@ -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"
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="godot_editor_name_string">Godot Editor 4 (debug)</string>
|
||||
</resources>
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -44,6 +44,7 @@ private:
|
|||
|
||||
jobject _godot_view;
|
||||
|
||||
jmethodID _can_capture_pointer = 0;
|
||||
jmethodID _request_pointer_capture = 0;
|
||||
jmethodID _release_pointer_capture = 0;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <cmath>
|
||||
#endif
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
|
|
@ -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
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "xr_dependencies.h"
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// OpenXR paths and registry key locations
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue