Merge pull request #49997 from akien-mga/3.x-cherrypicks

This commit is contained in:
Rémi Verschelde 2021-06-29 14:56:18 +02:00 committed by GitHub
commit 48fe8da245
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 327 additions and 116 deletions

View File

@ -1740,6 +1740,7 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + "."); ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + "."); ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
ERR_FAIL_COND_MSG(write_lock.ptr(), "Cannot create image when it is locked."); ERR_FAIL_COND_MSG(write_lock.ptr(), "Cannot create image when it is locked.");
ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "Image format out of range, please see Image's Format enum.");
int mm = 0; int mm = 0;
int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
@ -1760,6 +1761,7 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma
ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0."); ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0.");
ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + "."); ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + ".");
ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + "."); ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + ".");
ERR_FAIL_INDEX_MSG(p_format, FORMAT_MAX, "Image format out of range, please see Image's Format enum.");
int mm; int mm;
int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);
@ -2113,6 +2115,8 @@ Error Image::decompress() {
} }
Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) { Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) {
ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode.");
ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source.");
switch (p_mode) { switch (p_mode) {
case COMPRESS_S3TC: { case COMPRESS_S3TC: {
ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE);
@ -2138,6 +2142,9 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_loss
ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE); ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
_image_compress_bptc_func(this, p_lossy_quality, p_source); _image_compress_bptc_func(this, p_lossy_quality, p_source);
} break; } break;
case COMPRESS_MAX: {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
} break;
} }
return OK; return OK;

View File

@ -124,6 +124,7 @@ public:
COMPRESS_SOURCE_SRGB, COMPRESS_SOURCE_SRGB,
COMPRESS_SOURCE_NORMAL, COMPRESS_SOURCE_NORMAL,
COMPRESS_SOURCE_LAYERED, COMPRESS_SOURCE_LAYERED,
COMPRESS_SOURCE_MAX,
}; };
//some functions provided by something else //some functions provided by something else
@ -304,7 +305,8 @@ public:
COMPRESS_PVRTC4, COMPRESS_PVRTC4,
COMPRESS_ETC, COMPRESS_ETC,
COMPRESS_ETC2, COMPRESS_ETC2,
COMPRESS_BPTC COMPRESS_BPTC,
COMPRESS_MAX,
}; };
Error compress(CompressMode p_mode = COMPRESS_S3TC, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7); Error compress(CompressMode p_mode = COMPRESS_S3TC, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7);

View File

@ -4,7 +4,7 @@
Class representing a cylindrical [PrimitiveMesh]. Class representing a cylindrical [PrimitiveMesh].
</brief_description> </brief_description>
<description> <description>
Class representing a cylindrical [PrimitiveMesh]. This class can be used to create cones by setting either the [member top_radius] or [member bottom_radius] properties to 0.0. Class representing a cylindrical [PrimitiveMesh]. This class can be used to create cones by setting either the [member top_radius] or [member bottom_radius] properties to [code]0.0[/code].
</description> </description>
<tutorials> <tutorials>
</tutorials> </tutorials>
@ -12,19 +12,19 @@
</methods> </methods>
<members> <members>
<member name="bottom_radius" type="float" setter="set_bottom_radius" getter="get_bottom_radius" default="1.0"> <member name="bottom_radius" type="float" setter="set_bottom_radius" getter="get_bottom_radius" default="1.0">
Bottom radius of the cylinder. Bottom radius of the cylinder. If set to [code]0.0[/code], the bottom faces will not be generated, resulting in a conic shape.
</member> </member>
<member name="height" type="float" setter="set_height" getter="get_height" default="2.0"> <member name="height" type="float" setter="set_height" getter="get_height" default="2.0">
Full height of the cylinder. Full height of the cylinder.
</member> </member>
<member name="radial_segments" type="int" setter="set_radial_segments" getter="get_radial_segments" default="64"> <member name="radial_segments" type="int" setter="set_radial_segments" getter="get_radial_segments" default="64">
Number of radial segments on the cylinder. Number of radial segments on the cylinder. Higher values result in a more detailed cylinder/cone at the cost of performance.
</member> </member>
<member name="rings" type="int" setter="set_rings" getter="get_rings" default="4"> <member name="rings" type="int" setter="set_rings" getter="get_rings" default="4">
Number of edge rings along the height of the cylinder. Number of edge rings along the height of the cylinder. Changing [member rings] does not have any visual impact unless a shader or procedural mesh tool is used to alter the vertex data. Higher values result in more subdivisions, which can be used to create smoother-looking effects with shaders or procedural mesh tools (at the cost of performance). When not altering the vertex data using a shader or procedural mesh tool, [member rings] should be kept to its default value.
</member> </member>
<member name="top_radius" type="float" setter="set_top_radius" getter="get_top_radius" default="1.0"> <member name="top_radius" type="float" setter="set_top_radius" getter="get_top_radius" default="1.0">
Top radius of the cylinder. Top radius of the cylinder. If set to [code]0.0[/code], the top faces will not be generated, resulting in a conic shape.
</member> </member>
</members> </members>
<constants> <constants>

View File

@ -450,6 +450,7 @@
</argument> </argument>
<description> <description>
Stores any Variant value in the file. If [code]full_objects[/code] is [code]true[/code], encoding objects is allowed (and can potentially include code). Stores any Variant value in the file. If [code]full_objects[/code] is [code]true[/code], encoding objects is allowed (and can potentially include code).
[b]Note:[/b] Not all properties are included. Only properties that are configured with the [constant PROPERTY_USAGE_STORAGE] flag set will be serialized. You can add a new usage flag to a property by overriding the [method Object._get_property_list] method in your class. You can also check how property usage is configured by calling [method Object._get_property_list]. See [enum PropertyUsageFlags] for the possible usage flags.
</description> </description>
</method> </method>
</methods> </methods>

View File

@ -48,7 +48,7 @@
If [code]true[/code], wraps the text inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text. If [code]true[/code], wraps the text inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text.
</member> </member>
<member name="clip_text" type="bool" setter="set_clip_text" getter="is_clipping_text" default="false"> <member name="clip_text" type="bool" setter="set_clip_text" getter="is_clipping_text" default="false">
If [code]true[/code], the Label only shows the text that fits inside its bounding rectangle. It also lets you scale the node down freely. If [code]true[/code], the Label only shows the text that fits inside its bounding rectangle and will clip text horizontally.
</member> </member>
<member name="lines_skipped" type="int" setter="set_lines_skipped" getter="get_lines_skipped" default="0"> <member name="lines_skipped" type="int" setter="set_lines_skipped" getter="get_lines_skipped" default="0">
The node ignores the first [code]lines_skipped[/code] lines before it starts to display text. The node ignores the first [code]lines_skipped[/code] lines before it starts to display text.

View File

@ -245,10 +245,12 @@
Icon set in [code].ico[/code] format used on Windows to set the game's icon. This is done automatically on start by calling [method OS.set_native_icon]. Icon set in [code].ico[/code] format used on Windows to set the game's icon. This is done automatically on start by calling [method OS.set_native_icon].
</member> </member>
<member name="application/run/disable_stderr" type="bool" setter="" getter="" default="false"> <member name="application/run/disable_stderr" type="bool" setter="" getter="" default="false">
If [code]true[/code], disables printing to standard error in an exported build. If [code]true[/code], disables printing to standard error. If [code]true[/code], this also hides error and warning messages printed by [method @GDScript.push_error] and [method @GDScript.push_warning]. See also [member application/run/disable_stdout].
Changes to this setting will only be applied upon restarting the application.
</member> </member>
<member name="application/run/disable_stdout" type="bool" setter="" getter="" default="false"> <member name="application/run/disable_stdout" type="bool" setter="" getter="" default="false">
If [code]true[/code], disables printing to standard output in an exported build. If [code]true[/code], disables printing to standard output. This is equivalent to starting the editor or project with the [code]--quiet[/code] command line argument. See also [member application/run/disable_stderr].
Changes to this setting will only be applied upon restarting the application.
</member> </member>
<member name="application/run/flush_stdout_on_print" type="bool" setter="" getter="" default="false"> <member name="application/run/flush_stdout_on_print" type="bool" setter="" getter="" default="false">
If [code]true[/code], flushes the standard output stream every time a line is printed. This affects both terminal logging and file logging. If [code]true[/code], flushes the standard output stream every time a line is printed. This affects both terminal logging and file logging.

View File

@ -1175,31 +1175,29 @@ public:
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale")); p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break; } break;
case Animation::TYPE_VALUE: { case Animation::TYPE_VALUE: {
if (!same_key_type) { if (same_key_type) {
break; Variant v = animation->track_get_key_value(first_track, first_key);
}
Variant v = animation->track_get_key_value(first_track, first_key); if (hint.type != Variant::NIL) {
PropertyInfo pi = hint;
pi.name = "value";
p_list->push_back(pi);
} else {
PropertyHint hint = PROPERTY_HINT_NONE;
String hint_string;
if (hint.type != Variant::NIL) { if (v.get_type() == Variant::OBJECT) {
PropertyInfo pi = hint; //could actually check the object property if exists..? yes i will!
pi.name = "value"; Ref<Resource> res = v;
p_list->push_back(pi); if (res.is_valid()) {
} else { hint = PROPERTY_HINT_RESOURCE_TYPE;
PropertyHint hint = PROPERTY_HINT_NONE; hint_string = res->get_class();
String hint_string; }
if (v.get_type() == Variant::OBJECT) {
//could actually check the object property if exists..? yes i will!
Ref<Resource> res = v;
if (res.is_valid()) {
hint = PROPERTY_HINT_RESOURCE_TYPE;
hint_string = res->get_class();
} }
}
if (v.get_type() != Variant::NIL) { if (v.get_type() != Variant::NIL) {
p_list->push_back(PropertyInfo(v.get_type(), "value", hint, hint_string)); p_list->push_back(PropertyInfo(v.get_type(), "value", hint, hint_string));
}
} }
} }

View File

@ -609,6 +609,7 @@ void EditorNode::_notification(int p_what) {
p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_icon("Instance", "EditorIcons")); p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_icon("Instance", "EditorIcons")); p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_REPORT_A_BUG), gui_base->get_icon("Instance", "EditorIcons")); p->set_item_icon(p->get_item_index(HELP_REPORT_A_BUG), gui_base->get_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_SUGGEST_A_FEATURE), gui_base->get_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_icon("Instance", "EditorIcons")); p->set_item_icon(p->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_icon("Instance", "EditorIcons")); p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_icon("Godot", "EditorIcons")); p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_icon("Godot", "EditorIcons"));
@ -1516,15 +1517,6 @@ void EditorNode::_save_scene(String p_file, int idx) {
return; return;
} }
// force creation of node path cache
// (hacky but needed for the tree to update properly)
Node *dummy_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
if (!dummy_scene) {
show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK"));
return;
}
memdelete(dummy_scene);
int flg = 0; int flg = 0;
if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources")) { if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources")) {
flg |= ResourceSaver::FLAG_COMPRESS; flg |= ResourceSaver::FLAG_COMPRESS;
@ -2803,6 +2795,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case HELP_REPORT_A_BUG: { case HELP_REPORT_A_BUG: {
OS::get_singleton()->shell_open("https://github.com/godotengine/godot/issues"); OS::get_singleton()->shell_open("https://github.com/godotengine/godot/issues");
} break; } break;
case HELP_SUGGEST_A_FEATURE: {
OS::get_singleton()->shell_open("https://github.com/godotengine/godot-proposals#readme");
} break;
case HELP_SEND_DOCS_FEEDBACK: { case HELP_SEND_DOCS_FEEDBACK: {
OS::get_singleton()->shell_open("https://github.com/godotengine/godot-docs/issues"); OS::get_singleton()->shell_open("https://github.com/godotengine/godot-docs/issues");
} break; } break;
@ -6364,6 +6359,7 @@ EditorNode::EditorNode() {
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Documentation")), HELP_DOCS); p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Questions & Answers")), HELP_QA); p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Questions & Answers")), HELP_QA);
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG); p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE);
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK); p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY); p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY);
p->add_separator(); p->add_separator();

View File

@ -200,6 +200,7 @@ private:
HELP_DOCS, HELP_DOCS,
HELP_QA, HELP_QA,
HELP_REPORT_A_BUG, HELP_REPORT_A_BUG,
HELP_SUGGEST_A_FEATURE,
HELP_SEND_DOCS_FEEDBACK, HELP_SEND_DOCS_FEEDBACK,
HELP_COMMUNITY, HELP_COMMUNITY,
HELP_ABOUT, HELP_ABOUT,

View File

@ -5844,7 +5844,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p = view_menu->get_popup(); p = view_menu->get_popup();
p->set_hide_on_checkable_item_selection(false); p->set_hide_on_checkable_item_selection(false);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_MASK_CTRL | KEY_G), SHOW_GRID); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_MASK_CMD | KEY_G), SHOW_GRID);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers")), SHOW_RULERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers")), SHOW_RULERS);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES);

View File

@ -6345,7 +6345,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
p->add_separator(); p->add_separator();
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN); p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN);
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid")), MENU_VIEW_GRID); p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid"), KEY_MASK_CMD + KEY_G), MENU_VIEW_GRID);
p->add_separator(); p->add_separator();
p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings...")), MENU_VIEW_CAMERA_SETTINGS); p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings...")), MENU_VIEW_CAMERA_SETTINGS);

View File

@ -103,17 +103,16 @@ void SpriteFramesEditor::_sheet_preview_draw() {
split_sheet_dialog->get_ok()->set_text(vformat(TTR("Add %d Frame(s)"), frames_selected.size())); split_sheet_dialog->get_ok()->set_text(vformat(TTR("Add %d Frame(s)"), frames_selected.size()));
} }
void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) { void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event; const Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
Size2i size = split_sheet_preview->get_size(); const Size2i size = split_sheet_preview->get_size();
int h = split_sheet_h->get_value(); const int h = split_sheet_h->get_value();
int v = split_sheet_v->get_value(); const int v = split_sheet_v->get_value();
int x = CLAMP(int(mb->get_position().x) * h / size.width, 0, h - 1); const int x = CLAMP(int(mb->get_position().x) * h / size.width, 0, h - 1);
int y = CLAMP(int(mb->get_position().y) * v / size.height, 0, v - 1); const int y = CLAMP(int(mb->get_position().y) * v / size.height, 0, v - 1);
int idx = h * y + x; const int idx = h * y + x;
if (mb->get_shift() && last_frame_selected >= 0) { if (mb->get_shift() && last_frame_selected >= 0) {
//select multiple //select multiple
@ -124,6 +123,9 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
} }
for (int i = from; i <= to; i++) { for (int i = from; i <= to; i++) {
// Prevent double-toggling the same frame when moving the mouse when the mouse button is still held.
frames_toggled_by_mouse_hover.insert(idx);
if (mb->get_control()) { if (mb->get_control()) {
frames_selected.erase(i); frames_selected.erase(i);
} else { } else {
@ -131,6 +133,9 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
} }
} }
} else { } else {
// Prevent double-toggling the same frame when moving the mouse when the mouse button is still held.
frames_toggled_by_mouse_hover.insert(idx);
if (frames_selected.has(idx)) { if (frames_selected.has(idx)) {
frames_selected.erase(idx); frames_selected.erase(idx);
} else { } else {
@ -141,6 +146,39 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
last_frame_selected = idx; last_frame_selected = idx;
split_sheet_preview->update(); split_sheet_preview->update();
} }
if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
frames_toggled_by_mouse_hover.clear();
}
const Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
// Select by holding down the mouse button on frames.
const Size2i size = split_sheet_preview->get_size();
const int h = split_sheet_h->get_value();
const int v = split_sheet_v->get_value();
const int x = CLAMP(int(mm->get_position().x) * h / size.width, 0, h - 1);
const int y = CLAMP(int(mm->get_position().y) * v / size.height, 0, v - 1);
const int idx = h * y + x;
if (!frames_toggled_by_mouse_hover.has(idx)) {
// Only allow toggling each tile once per mouse hold.
// Otherwise, the selection would constantly "flicker" in and out when moving the mouse cursor.
// The mouse button must be released before it can be toggled again.
frames_toggled_by_mouse_hover.insert(idx);
if (frames_selected.has(idx)) {
frames_selected.erase(idx);
} else {
frames_selected.insert(idx);
}
last_frame_selected = idx;
split_sheet_preview->update();
}
}
} }
void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) { void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) {

View File

@ -86,6 +86,7 @@ class SpriteFramesEditor : public HSplitContainer {
ToolButton *split_sheet_zoom_in; ToolButton *split_sheet_zoom_in;
EditorFileDialog *file_split_sheet; EditorFileDialog *file_split_sheet;
Set<int> frames_selected; Set<int> frames_selected;
Set<int> frames_toggled_by_mouse_hover;
int last_frame_selected; int last_frame_selected;
float scale_ratio; float scale_ratio;

View File

@ -1848,9 +1848,6 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
case KEY_ENTER: { case KEY_ENTER: {
_open_selected_projects_ask(); _open_selected_projects_ask();
} break; } break;
case KEY_DELETE: {
_erase_project();
} break;
case KEY_HOME: { case KEY_HOME: {
if (_project_list->get_project_count() > 0) { if (_project_list->get_project_count() > 0) {
_project_list->select_project(0); _project_list->select_project(0);
@ -2491,12 +2488,14 @@ ProjectManager::ProjectManager() {
Button *open = memnew(Button); Button *open = memnew(Button);
open->set_text(TTR("Edit")); open->set_text(TTR("Edit"));
open->set_shortcut(ED_SHORTCUT("project_manager/edit_project", TTR("Edit Project"), KEY_MASK_CMD | KEY_E));
tree_vb->add_child(open); tree_vb->add_child(open);
open->connect("pressed", this, "_open_selected_projects_ask"); open->connect("pressed", this, "_open_selected_projects_ask");
open_btn = open; open_btn = open;
Button *run = memnew(Button); Button *run = memnew(Button);
run->set_text(TTR("Run")); run->set_text(TTR("Run"));
run->set_shortcut(ED_SHORTCUT("project_manager/run_project", TTR("Run Project"), KEY_MASK_CMD | KEY_R));
tree_vb->add_child(run); tree_vb->add_child(run);
run->connect("pressed", this, "_run_project"); run->connect("pressed", this, "_run_project");
run_btn = run; run_btn = run;
@ -2505,6 +2504,7 @@ ProjectManager::ProjectManager() {
Button *scan = memnew(Button); Button *scan = memnew(Button);
scan->set_text(TTR("Scan")); scan->set_text(TTR("Scan"));
scan->set_shortcut(ED_SHORTCUT("project_manager/scan_projects", TTR("Scan Projects"), KEY_MASK_CMD | KEY_S));
tree_vb->add_child(scan); tree_vb->add_child(scan);
scan->connect("pressed", this, "_scan_projects"); scan->connect("pressed", this, "_scan_projects");
@ -2520,22 +2520,26 @@ ProjectManager::ProjectManager() {
Button *create = memnew(Button); Button *create = memnew(Button);
create->set_text(TTR("New Project")); create->set_text(TTR("New Project"));
create->set_shortcut(ED_SHORTCUT("project_manager/new_project", TTR("New Project"), KEY_MASK_CMD | KEY_N));
tree_vb->add_child(create); tree_vb->add_child(create);
create->connect("pressed", this, "_new_project"); create->connect("pressed", this, "_new_project");
Button *import = memnew(Button); Button *import = memnew(Button);
import->set_text(TTR("Import")); import->set_text(TTR("Import"));
import->set_shortcut(ED_SHORTCUT("project_manager/import_project", TTR("Import Project"), KEY_MASK_CMD | KEY_I));
tree_vb->add_child(import); tree_vb->add_child(import);
import->connect("pressed", this, "_import_project"); import->connect("pressed", this, "_import_project");
Button *rename = memnew(Button); Button *rename = memnew(Button);
rename->set_text(TTR("Rename")); rename->set_text(TTR("Rename"));
rename->set_shortcut(ED_SHORTCUT("project_manager/rename_project", TTR("Rename Project"), KEY_F2));
tree_vb->add_child(rename); tree_vb->add_child(rename);
rename->connect("pressed", this, "_rename_project"); rename->connect("pressed", this, "_rename_project");
rename_btn = rename; rename_btn = rename;
Button *erase = memnew(Button); Button *erase = memnew(Button);
erase->set_text(TTR("Remove")); erase->set_text(TTR("Remove"));
erase->set_shortcut(ED_SHORTCUT("project_manager/remove_project", TTR("Remove Project"), KEY_DELETE));
tree_vb->add_child(erase); tree_vb->add_child(erase);
erase->connect("pressed", this, "_erase_project"); erase->connect("pressed", this, "_erase_project");
erase_btn = erase; erase_btn = erase;

View File

@ -635,8 +635,6 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point,
r_normal = -p_camera->project_ray_normal(p_point); r_normal = -p_camera->project_ray_normal(p_point);
return true; return true;
} }
return false;
} }
if (collision_segments.size()) { if (collision_segments.size()) {
@ -687,8 +685,6 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point,
r_normal = -p_camera->project_ray_normal(p_point); r_normal = -p_camera->project_ray_normal(p_point);
return true; return true;
} }
return false;
} }
if (collision_mesh.is_valid()) { if (collision_mesh.is_valid()) {

View File

@ -187,7 +187,9 @@ Array GDScriptWorkspace::symbol(const Dictionary &p_params) {
E->get()->get_symbols().symbol_tree_as_list(E->key(), script_symbols); E->get()->get_symbols().symbol_tree_as_list(E->key(), script_symbols);
for (int i = 0; i < script_symbols.size(); ++i) { for (int i = 0; i < script_symbols.size(); ++i) {
if (query.is_subsequence_ofi(script_symbols[i].name)) { if (query.is_subsequence_ofi(script_symbols[i].name)) {
arr.push_back(script_symbols[i].to_json()); lsp::DocumentedSymbolInformation symbol = script_symbols[i];
symbol.location.uri = get_file_uri(symbol.location.uri);
arr.push_back(symbol.to_json());
} }
} }
} }

View File

@ -43,6 +43,10 @@ static void _compress_pvrtc4(Image *p_img) {
if (!img->is_size_po2() || img->get_width() != img->get_height()) { if (!img->is_size_po2() || img->get_width() != img->get_height()) {
make_mipmaps = img->has_mipmaps(); make_mipmaps = img->has_mipmaps();
img->resize_to_po2(true); img->resize_to_po2(true);
// Resizing can fail for some formats
if (!img->is_size_po2() || img->get_width() != img->get_height()) {
ERR_FAIL_MSG("Failed to resize the image for compression.");
}
} }
img->convert(Image::FORMAT_RGBA8); img->convert(Image::FORMAT_RGBA8);
if (!img->has_mipmaps() && make_mipmaps) { if (!img->has_mipmaps() && make_mipmaps) {

View File

@ -466,10 +466,11 @@ void VisualScriptPropertySelector::_item_selected() {
at_class = ClassDB::get_parent_class_nocheck(at_class); at_class = ClassDB::get_parent_class_nocheck(at_class);
} }
Map<String, DocData::ClassDoc>::Element *T = dd->class_list.find(class_type); Vector<String> functions = name.rsplit("/", false);
at_class = functions.size() > 3 ? functions[functions.size() - 2] : class_type;
Map<String, DocData::ClassDoc>::Element *T = dd->class_list.find(at_class);
if (T) { if (T) {
for (int i = 0; i < T->get().methods.size(); i++) { for (int i = 0; i < T->get().methods.size(); i++) {
Vector<String> functions = name.rsplit("/", false, 1);
if (T->get().methods[i].name == functions[functions.size() - 1]) { if (T->get().methods[i].name == functions[functions.size() - 1]) {
text = T->get().methods[i].description; text = T->get().methods[i].description;
} }

View File

@ -89,6 +89,9 @@
<member name="ca_chain" type="X509Certificate" setter="set_ca_chain" getter="get_ca_chain"> <member name="ca_chain" type="X509Certificate" setter="set_ca_chain" getter="get_ca_chain">
When using SSL (see [member private_key] and [member ssl_certificate]), you can set this to a valid [X509Certificate] to be provided as additional CA chain information during the SSL handshake. When using SSL (see [member private_key] and [member ssl_certificate]), you can set this to a valid [X509Certificate] to be provided as additional CA chain information during the SSL handshake.
</member> </member>
<member name="handshake_timeout" type="float" setter="set_handshake_timeout" getter="get_handshake_timeout" default="3.0">
The time in seconds before a pending client (i.e. a client that has not yet finished the HTTP handshake) is considered stale and forcefully disconnected.
</member>
<member name="private_key" type="CryptoKey" setter="set_private_key" getter="get_private_key"> <member name="private_key" type="CryptoKey" setter="set_private_key" getter="get_private_key">
When set to a valid [CryptoKey] (along with [member ssl_certificate]) will cause the server to require SSL instead of regular TCP (i.e. the [code]wss://[/code] protocol). When set to a valid [CryptoKey] (along with [member ssl_certificate]) will cause the server to require SSL instead of regular TCP (i.e. the [code]wss://[/code] protocol).
</member> </member>

View File

@ -43,9 +43,9 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto
_is_multiplayer = gd_mp_api; _is_multiplayer = gd_mp_api;
String host = p_url; String host = p_url;
String path = "/"; String path;
String scheme = ""; String scheme;
int port = 80; int port = 0;
Error err = p_url.parse_url(scheme, host, port, path); Error err = p_url.parse_url(scheme, host, port, path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url); ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
@ -56,6 +56,9 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto
if (port == 0) { if (port == 0) {
port = ssl ? 443 : 80; port = ssl ? 443 : 80;
} }
if (path.empty()) {
path = "/";
}
return connect_to_host(host, path, port, ssl, p_protocols, p_custom_headers); return connect_to_host(host, path, port, ssl, p_protocols, p_custom_headers);
} }

View File

@ -65,6 +65,10 @@ void WebSocketServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ca_chain"), &WebSocketServer::set_ca_chain); ClassDB::bind_method(D_METHOD("set_ca_chain"), &WebSocketServer::set_ca_chain);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "ca_chain", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", 0), "set_ca_chain", "get_ca_chain"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "ca_chain", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", 0), "set_ca_chain", "get_ca_chain");
ClassDB::bind_method(D_METHOD("get_handshake_timeout"), &WebSocketServer::get_handshake_timeout);
ClassDB::bind_method(D_METHOD("set_handshake_timeout", "timeout"), &WebSocketServer::set_handshake_timeout);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handshake_timeout"), "set_handshake_timeout", "get_handshake_timeout");
ADD_SIGNAL(MethodInfo("client_close_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason"))); ADD_SIGNAL(MethodInfo("client_close_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason")));
ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::BOOL, "was_clean_close"))); ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::BOOL, "was_clean_close")));
ADD_SIGNAL(MethodInfo("client_connected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "protocol"))); ADD_SIGNAL(MethodInfo("client_connected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "protocol")));
@ -108,6 +112,15 @@ void WebSocketServer::set_ca_chain(Ref<X509Certificate> p_ca_chain) {
ca_chain = p_ca_chain; ca_chain = p_ca_chain;
} }
float WebSocketServer::get_handshake_timeout() const {
return handshake_timeout / 1000.0;
}
void WebSocketServer::set_handshake_timeout(float p_timeout) {
ERR_FAIL_COND(p_timeout <= 0.0);
handshake_timeout = p_timeout * 1000;
}
NetworkedMultiplayerPeer::ConnectionStatus WebSocketServer::get_connection_status() const { NetworkedMultiplayerPeer::ConnectionStatus WebSocketServer::get_connection_status() const {
if (is_listening()) { if (is_listening()) {
return CONNECTION_CONNECTED; return CONNECTION_CONNECTED;

View File

@ -48,6 +48,7 @@ protected:
Ref<CryptoKey> private_key; Ref<CryptoKey> private_key;
Ref<X509Certificate> ssl_cert; Ref<X509Certificate> ssl_cert;
Ref<X509Certificate> ca_chain; Ref<X509Certificate> ca_chain;
uint32_t handshake_timeout = 3000;
public: public:
virtual void poll() = 0; virtual void poll() = 0;
@ -80,6 +81,9 @@ public:
Ref<X509Certificate> get_ca_chain() const; Ref<X509Certificate> get_ca_chain() const;
void set_ca_chain(Ref<X509Certificate> p_ca_chain); void set_ca_chain(Ref<X509Certificate> p_ca_chain);
float get_handshake_timeout() const;
void set_handshake_timeout(float p_timeout);
virtual Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) = 0; virtual Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) = 0;
WebSocketServer(); WebSocketServer();

View File

@ -158,6 +158,7 @@ bool WSLClient::_verify_headers(String &r_protocol) {
Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocols, const Vector<String> p_custom_headers) { Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(p_path.empty(), ERR_INVALID_PARAMETER);
_peer = Ref<WSLPeer>(memnew(WSLPeer)); _peer = Ref<WSLPeer>(memnew(WSLPeer));
IP_Address addr; IP_Address addr;

View File

@ -104,8 +104,8 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) {
return true; return true;
} }
Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols) { Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uint64_t p_timeout) {
if (OS::get_singleton()->get_ticks_msec() - time > WSL_SERVER_TIMEOUT) { if (OS::get_singleton()->get_ticks_msec() - time > p_timeout) {
return ERR_TIMEOUT; return ERR_TIMEOUT;
} }
if (use_ssl) { if (use_ssl) {
@ -197,7 +197,7 @@ void WSLServer::poll() {
List<Ref<PendingPeer>> remove_peers; List<Ref<PendingPeer>> remove_peers;
for (List<Ref<PendingPeer>>::Element *E = _pending.front(); E; E = E->next()) { for (List<Ref<PendingPeer>>::Element *E = _pending.front(); E; E = E->next()) {
Ref<PendingPeer> ppeer = E->get(); Ref<PendingPeer> ppeer = E->get();
Error err = ppeer->do_handshake(_protocols); Error err = ppeer->do_handshake(_protocols, handshake_timeout);
if (err == ERR_BUSY) { if (err == ERR_BUSY) {
continue; continue;
} else if (err != OK) { } else if (err != OK) {

View File

@ -40,8 +40,6 @@
#include "core/io/stream_peer_tcp.h" #include "core/io/stream_peer_tcp.h"
#include "core/io/tcp_server.h" #include "core/io/tcp_server.h"
#define WSL_SERVER_TIMEOUT 1000
class WSLServer : public WebSocketServer { class WSLServer : public WebSocketServer {
GDCIIMPL(WSLServer, WebSocketServer); GDCIIMPL(WSLServer, WebSocketServer);
@ -66,7 +64,7 @@ private:
PendingPeer(); PendingPeer();
Error do_handshake(const Vector<String> p_protocols); Error do_handshake(const Vector<String> p_protocols, uint64_t p_timeout);
}; };
int _in_buf_size; int _in_buf_size;

View File

@ -1910,7 +1910,7 @@ public:
err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true);
print_verbose(output); print_verbose(output);
if (err || rv != 0) { if (err || rv != 0) {
EditorNode::add_io_error("Could not install to device."); EditorNode::add_io_error("Could not install to device: " + output);
CLEANUP_AND_RETURN(ERR_CANT_CREATE); CLEANUP_AND_RETURN(ERR_CANT_CREATE);
} }

View File

@ -9,7 +9,7 @@ buildscript {
repositories { repositories {
google() google()
jcenter() mavenCentral()
//CHUNK_BUILDSCRIPT_REPOSITORIES_BEGIN //CHUNK_BUILDSCRIPT_REPOSITORIES_BEGIN
//CHUNK_BUILDSCRIPT_REPOSITORIES_END //CHUNK_BUILDSCRIPT_REPOSITORIES_END
} }
@ -25,9 +25,8 @@ apply plugin: 'com.android.application'
allprojects { allprojects {
repositories { repositories {
mavenCentral()
google() google()
jcenter() mavenCentral()
//CHUNK_ALLPROJECTS_REPOSITORIES_BEGIN //CHUNK_ALLPROJECTS_REPOSITORIES_BEGIN
//CHUNK_ALLPROJECTS_REPOSITORIES_END //CHUNK_ALLPROJECTS_REPOSITORIES_END

View File

@ -1,11 +1,11 @@
ext.versions = [ ext.versions = [
androidGradlePlugin: '4.0.1', androidGradlePlugin: '4.2.1',
compileSdk : 29, compileSdk : 29,
minSdk : 18, minSdk : 18,
targetSdk : 29, targetSdk : 29,
buildTools : '30.0.3', buildTools : '30.0.3',
supportCoreUtils : '1.0.0', supportCoreUtils : '1.0.0',
kotlinVersion : '1.4.10', kotlinVersion : '1.5.10',
v4Support : '1.0.0', v4Support : '1.0.0',
javaVersion : 1.8, javaVersion : 1.8,
ndkVersion : '21.4.7075529' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated. ndkVersion : '21.4.7075529' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated.

View File

@ -5,7 +5,7 @@ buildscript {
repositories { repositories {
google() google()
jcenter() mavenCentral()
} }
dependencies { dependencies {
classpath libraries.androidGradlePlugin classpath libraries.androidGradlePlugin
@ -16,7 +16,6 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
google() google()
jcenter()
mavenCentral() mavenCentral()
} }
} }

View File

@ -1,6 +1,6 @@
#Mon Sep 02 02:44:30 PDT 2019 #Wed Jun 23 23:42:22 PDT 2021
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip zipStoreBase=GRADLE_USER_HOME

View File

@ -136,8 +136,11 @@ public:
// Wrong protocol // Wrong protocol
ERR_FAIL_COND_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", "Invalid method or HTTP version."); ERR_FAIL_COND_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", "Invalid method or HTTP version.");
const String req_file = req[1].get_file(); const int query_index = req[1].find_char('?');
const String req_ext = req[1].get_extension(); const String path = (query_index == -1) ? req[1] : req[1].substr(0, query_index);
const String req_file = path.get_file();
const String req_ext = path.get_extension();
const String cache_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("web"); const String cache_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("web");
const String filepath = cache_path.plus_file(req_file); const String filepath = cache_path.plus_file(req_file);
@ -446,6 +449,7 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re
} }
config["canvasResizePolicy"] = p_preset->get("html/canvas_resize_policy"); config["canvasResizePolicy"] = p_preset->get("html/canvas_resize_policy");
config["experimentalVK"] = p_preset->get("html/experimental_virtual_keyboard"); config["experimentalVK"] = p_preset->get("html/experimental_virtual_keyboard");
config["focusCanvas"] = p_preset->get("html/focus_canvas_on_start");
config["gdnativeLibs"] = libs; config["gdnativeLibs"] = libs;
config["executable"] = p_name; config["executable"] = p_name;
config["args"] = args; config["args"] = args;
@ -648,6 +652,7 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "html/canvas_resize_policy", PROPERTY_HINT_ENUM, "None,Project,Adaptive"), 2)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "html/canvas_resize_policy", PROPERTY_HINT_ENUM, "None,Project,Adaptive"), 2));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/focus_canvas_on_start"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/experimental_virtual_keyboard"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/experimental_virtual_keyboard"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "progressive_web_app/enabled"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "progressive_web_app/enabled"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/offline_page", PROPERTY_HINT_FILE, "*.html"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/offline_page", PROPERTY_HINT_FILE, "*.html"), ""));

View File

@ -90,6 +90,14 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
* @default * @default
*/ */
args: [], args: [],
/**
* When enabled, the game canvas will automatically grab the focus when the engine starts.
*
* @memberof EngineConfig
* @type {boolean}
* @default
*/
focusCanvas: true,
/** /**
* When enabled, this will turn on experimental virtual keyboard support on mobile. * When enabled, this will turn on experimental virtual keyboard support on mobile.
* *
@ -238,6 +246,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
this.persistentPaths = parse('persistentPaths', this.persistentPaths); this.persistentPaths = parse('persistentPaths', this.persistentPaths);
this.persistentDrops = parse('persistentDrops', this.persistentDrops); this.persistentDrops = parse('persistentDrops', this.persistentDrops);
this.experimentalVK = parse('experimentalVK', this.experimentalVK); this.experimentalVK = parse('experimentalVK', this.experimentalVK);
this.focusCanvas = parse('focusCanvas', this.focusCanvas);
this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs); this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs);
this.fileSizes = parse('fileSizes', this.fileSizes); this.fileSizes = parse('fileSizes', this.fileSizes);
this.args = parse('args', this.args); this.args = parse('args', this.args);
@ -324,6 +333,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
'locale': locale, 'locale': locale,
'persistentDrops': this.persistentDrops, 'persistentDrops': this.persistentDrops,
'virtualKeyboard': this.experimentalVK, 'virtualKeyboard': this.experimentalVK,
'focusCanvas': this.focusCanvas,
'onExecute': this.onExecute, 'onExecute': this.onExecute,
'onExit': function (p_code) { 'onExit': function (p_code) {
cleanup(); // We always need to call the cleanup callback to free memory. cleanup(); // We always need to call the cleanup callback to free memory.

View File

@ -72,6 +72,9 @@ const GodotConfig = {
GodotConfig.persistent_drops = !!p_opts['persistentDrops']; GodotConfig.persistent_drops = !!p_opts['persistentDrops'];
GodotConfig.on_execute = p_opts['onExecute']; GodotConfig.on_execute = p_opts['onExecute'];
GodotConfig.on_exit = p_opts['onExit']; GodotConfig.on_exit = p_opts['onExit'];
if (p_opts['focusCanvas']) {
GodotConfig.canvas.focus();
}
}, },
locate_file: function (file) { locate_file: function (file) {

View File

@ -3295,6 +3295,12 @@ void OS_OSX::set_mouse_mode(MouseMode p_mode) {
ignore_warp = true; ignore_warp = true;
warp_events.clear(); warp_events.clear();
mouse_mode = p_mode; mouse_mode = p_mode;
if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
CursorShape p_shape = cursor_shape;
cursor_shape = OS::CURSOR_MAX;
set_cursor_shape(p_shape);
}
} }
OS::MouseMode OS_OSX::get_mouse_mode() const { OS::MouseMode OS_OSX::get_mouse_mode() const {

View File

@ -1056,19 +1056,19 @@ public:
// Capabilities // Capabilities
const char **basic = uwp_capabilities; const char **basic = uwp_capabilities;
while (*basic) { while (*basic) {
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*basic).camelcase_to_underscore(false)), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*basic)), false));
basic++; basic++;
} }
const char **uap = uwp_uap_capabilities; const char **uap = uwp_uap_capabilities;
while (*uap) { while (*uap) {
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*uap).camelcase_to_underscore(false)), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*uap)), false));
uap++; uap++;
} }
const char **device = uwp_device_capabilities; const char **device = uwp_device_capabilities;
while (*device) { while (*device) {
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*device).camelcase_to_underscore(false)), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*device)), false));
device++; device++;
} }
} }

View File

@ -310,7 +310,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
args.push_back(p_path); args.push_back(p_path);
#ifndef WINDOWS_ENABLED #ifndef WINDOWS_ENABLED
args.push_back("-out"); args.push_back("-out");
args.push_back(p_path); args.push_back(p_path + "_signed");
#endif #endif
String str; String str;
@ -326,6 +326,16 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
return FAILED; return FAILED;
} }
#ifndef WINDOWS_ENABLED
DirAccessRef tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
err = tmp_dir->remove(p_path);
ERR_FAIL_COND_V(err != OK, err);
err = tmp_dir->rename(p_path + "_signed", p_path);
ERR_FAIL_COND_V(err != OK, err);
#endif
return OK; return OK;
} }

View File

@ -575,7 +575,7 @@ void GraphNode::_connpos_update() {
continue; continue;
} }
Size2i size = c->get_combined_minimum_size(); Size2i size = c->get_rect().size;
int y = sb->get_margin(MARGIN_TOP) + vofs; int y = sb->get_margin(MARGIN_TOP) + vofs;
int h = size.y; int h = size.y;

View File

@ -221,43 +221,87 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F
double width_texture = 0.0; double width_texture = 0.0;
double first_section_size = 0.0; double first_section_size = 0.0;
double last_section_size = 0.0; double last_section_size = 0.0;
switch (mode) { switch (p_mode) {
case FILL_LEFT_TO_RIGHT: case FILL_LEFT_TO_RIGHT: {
case FILL_RIGHT_TO_LEFT: {
width_total = dst_rect.size.x; width_total = dst_rect.size.x;
width_texture = texture_size.x; width_texture = texture_size.x;
first_section_size = topleft.x; first_section_size = topleft.x;
last_section_size = bottomright.x; last_section_size = bottomright.x;
} break; } break;
case FILL_TOP_TO_BOTTOM: case FILL_RIGHT_TO_LEFT: {
case FILL_BOTTOM_TO_TOP: { width_total = dst_rect.size.x;
width_texture = texture_size.x;
// In contrast to `FILL_LEFT_TO_RIGHT`, `first_section_size` and `last_section_size` should switch value.
first_section_size = bottomright.x;
last_section_size = topleft.x;
} break;
case FILL_TOP_TO_BOTTOM: {
width_total = dst_rect.size.y; width_total = dst_rect.size.y;
width_texture = texture_size.y; width_texture = texture_size.y;
first_section_size = topleft.y; first_section_size = topleft.y;
last_section_size = bottomright.y; last_section_size = bottomright.y;
} break; } break;
case FILL_BOTTOM_TO_TOP: {
width_total = dst_rect.size.y;
width_texture = texture_size.y;
// Similar to `FILL_RIGHT_TO_LEFT`.
first_section_size = bottomright.y;
last_section_size = topleft.y;
} break;
case FILL_BILINEAR_LEFT_AND_RIGHT: { case FILL_BILINEAR_LEFT_AND_RIGHT: {
// TODO: Implement width_total = dst_rect.size.x;
width_texture = texture_size.x;
first_section_size = topleft.x;
last_section_size = bottomright.x;
} break; } break;
case FILL_BILINEAR_TOP_AND_BOTTOM: { case FILL_BILINEAR_TOP_AND_BOTTOM: {
// TODO: Implement width_total = dst_rect.size.y;
width_texture = texture_size.y;
first_section_size = topleft.y;
last_section_size = bottomright.y;
} break; } break;
case FILL_CLOCKWISE: case FILL_CLOCKWISE:
case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE: case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE:
case FILL_COUNTER_CLOCKWISE: { case FILL_COUNTER_CLOCKWISE: {
// Those modes are circular, not relevant for nine patch // Those modes are circular, not relevant for nine patch.
} break; } break;
case FILL_MODE_MAX:
break;
} }
double width_filled = width_total * p_ratio; double width_filled = width_total * p_ratio;
double middle_section_size = MAX(0.0, width_texture - first_section_size - last_section_size); double middle_section_size = MAX(0.0, width_texture - first_section_size - last_section_size);
middle_section_size *= MIN(1.0, (MAX(0.0, width_filled - first_section_size) / MAX(1.0, width_total - first_section_size - last_section_size))); // Maximum middle texture size.
last_section_size = MAX(0.0, last_section_size - (width_total - width_filled)); double max_middle_texture_size = middle_section_size;
first_section_size = MIN(first_section_size, width_filled);
width_texture = MIN(width_texture, first_section_size + middle_section_size + last_section_size);
switch (mode) { // Maximum real middle texture size.
double max_middle_real_size = MAX(0.0, width_total - (first_section_size + last_section_size));
switch (p_mode) {
case FILL_BILINEAR_LEFT_AND_RIGHT:
case FILL_BILINEAR_TOP_AND_BOTTOM: {
last_section_size = MAX(0.0, last_section_size - (width_total - width_filled) * 0.5);
first_section_size = MAX(0.0, first_section_size - (width_total - width_filled) * 0.5);
// When `width_filled` increases, `middle_section_size` only increases when either of `first_section_size` and `last_section_size` is zero.
// Also, it should always be smaller than or equal to `(width_total - (first_section_size + last_section_size))`.
double real_middle_size = width_filled - first_section_size - last_section_size;
middle_section_size *= MIN(max_middle_real_size, real_middle_size) / max_middle_real_size;
width_texture = MIN(width_texture, first_section_size + middle_section_size + last_section_size);
} break;
case FILL_MODE_MAX:
break;
default: {
middle_section_size *= MIN(1.0, (MAX(0.0, width_filled - first_section_size) / MAX(1.0, width_total - first_section_size - last_section_size)));
last_section_size = MAX(0.0, last_section_size - (width_total - width_filled));
first_section_size = MIN(first_section_size, width_filled);
width_texture = MIN(width_texture, first_section_size + middle_section_size + last_section_size);
}
}
switch (p_mode) {
case FILL_LEFT_TO_RIGHT: { case FILL_LEFT_TO_RIGHT: {
src_rect.size.x = width_texture; src_rect.size.x = width_texture;
dst_rect.size.x = width_filled; dst_rect.size.x = width_filled;
@ -287,16 +331,32 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F
bottomright.y = first_section_size; bottomright.y = first_section_size;
} break; } break;
case FILL_BILINEAR_LEFT_AND_RIGHT: { case FILL_BILINEAR_LEFT_AND_RIGHT: {
// TODO: Implement double center_mapped_from_real_width = (width_total * 0.5 - topleft.x) / max_middle_real_size * max_middle_texture_size + topleft.x;
double drift_from_unscaled_center = (src_rect.size.x * 0.5 - center_mapped_from_real_width) * (last_section_size - first_section_size) / (bottomright.x - topleft.x);
src_rect.position.x += center_mapped_from_real_width + drift_from_unscaled_center - width_texture * 0.5;
src_rect.size.x = width_texture;
dst_rect.position.x += (width_total - width_filled) * 0.5;
dst_rect.size.x = width_filled;
topleft.x = first_section_size;
bottomright.x = last_section_size;
} break; } break;
case FILL_BILINEAR_TOP_AND_BOTTOM: { case FILL_BILINEAR_TOP_AND_BOTTOM: {
// TODO: Implement double center_mapped_from_real_width = (width_total * 0.5 - topleft.y) / max_middle_real_size * max_middle_texture_size + topleft.y;
double drift_from_unscaled_center = (src_rect.size.y * 0.5 - center_mapped_from_real_width) * (last_section_size - first_section_size) / (bottomright.y - topleft.y);
src_rect.position.y += center_mapped_from_real_width + drift_from_unscaled_center - width_texture * 0.5;
src_rect.size.y = width_texture;
dst_rect.position.y += (width_total - width_filled) * 0.5;
dst_rect.size.y = width_filled;
topleft.y = first_section_size;
bottomright.y = last_section_size;
} break; } break;
case FILL_CLOCKWISE: case FILL_CLOCKWISE:
case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE: case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE:
case FILL_COUNTER_CLOCKWISE: { case FILL_COUNTER_CLOCKWISE: {
// Those modes are circular, not relevant for nine patch // Those modes are circular, not relevant for nine patch.
} break; } break;
case FILL_MODE_MAX:
break;
} }
} }
@ -310,19 +370,34 @@ void TextureProgress::_notification(int p_what) {
const float corners[12] = { -0.125, -0.375, -0.625, -0.875, 0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875 }; const float corners[12] = { -0.125, -0.375, -0.625, -0.875, 0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875 };
switch (p_what) { switch (p_what) {
case NOTIFICATION_DRAW: { case NOTIFICATION_DRAW: {
if (nine_patch_stretch && (mode == FILL_LEFT_TO_RIGHT || mode == FILL_RIGHT_TO_LEFT || mode == FILL_TOP_TO_BOTTOM || mode == FILL_BOTTOM_TO_TOP)) { if (nine_patch_stretch && (mode == FILL_LEFT_TO_RIGHT || mode == FILL_RIGHT_TO_LEFT || mode == FILL_TOP_TO_BOTTOM || mode == FILL_BOTTOM_TO_TOP || mode == FILL_BILINEAR_LEFT_AND_RIGHT || mode == FILL_BILINEAR_TOP_AND_BOTTOM)) {
if (under.is_valid()) { if (under.is_valid()) {
draw_nine_patch_stretched(under, FILL_LEFT_TO_RIGHT, 1.0, tint_under); draw_nine_patch_stretched(under, mode, 1.0, tint_under);
} }
if (progress.is_valid()) { if (progress.is_valid()) {
draw_nine_patch_stretched(progress, mode, get_as_ratio(), tint_progress); draw_nine_patch_stretched(progress, mode, get_as_ratio(), tint_progress);
} }
if (over.is_valid()) { if (over.is_valid()) {
draw_nine_patch_stretched(over, FILL_LEFT_TO_RIGHT, 1.0, tint_over); draw_nine_patch_stretched(over, mode, 1.0, tint_over);
} }
} else { } else {
if (under.is_valid()) { if (under.is_valid()) {
draw_texture(under, Point2(), tint_under); switch (mode) {
case FILL_CLOCKWISE:
case FILL_COUNTER_CLOCKWISE:
case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE: {
if (nine_patch_stretch) {
Rect2 region = Rect2(Point2(), get_size());
draw_texture_rect(under, region, false, tint_under);
} else {
draw_texture(under, Point2(), tint_under);
}
} break;
case FILL_MODE_MAX:
break;
default:
draw_texture(under, Point2(), tint_under);
}
} }
if (progress.is_valid()) { if (progress.is_valid()) {
Size2 s = progress->get_size(); Size2 s = progress->get_size();
@ -353,7 +428,7 @@ void TextureProgress::_notification(int p_what) {
float val = get_as_ratio() * rad_max_degrees / 360; float val = get_as_ratio() * rad_max_degrees / 360;
if (val == 1) { if (val == 1) {
Rect2 region = Rect2(Point2(), s); Rect2 region = Rect2(Point2(), s);
draw_texture_rect_region(progress, region, region, tint_progress); draw_texture_rect(progress, region, false, tint_progress);
} else if (val != 0) { } else if (val != 0) {
Array pts; Array pts;
float direction = mode == FILL_COUNTER_CLOCKWISE ? -1 : 1; float direction = mode == FILL_COUNTER_CLOCKWISE ? -1 : 1;
@ -416,12 +491,29 @@ void TextureProgress::_notification(int p_what) {
Rect2 region = Rect2(Point2(0, s.y / 2 - s.y * get_as_ratio() / 2), Size2(s.x, s.y * get_as_ratio())); Rect2 region = Rect2(Point2(0, s.y / 2 - s.y * get_as_ratio() / 2), Size2(s.x, s.y * get_as_ratio()));
draw_texture_rect_region(progress, region, region, tint_progress); draw_texture_rect_region(progress, region, region, tint_progress);
} break; } break;
case FILL_MODE_MAX:
break;
default: default:
draw_texture_rect_region(progress, Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y)), Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y)), tint_progress); draw_texture_rect_region(progress, Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y)), Rect2(Point2(), Size2(s.x * get_as_ratio(), s.y)), tint_progress);
} }
} }
if (over.is_valid()) { if (over.is_valid()) {
draw_texture(over, Point2(), tint_over); switch (mode) {
case FILL_CLOCKWISE:
case FILL_COUNTER_CLOCKWISE:
case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE: {
if (nine_patch_stretch) {
Rect2 region = Rect2(Point2(), get_size());
draw_texture_rect(over, region, false, tint_over);
} else {
draw_texture(over, Point2(), tint_over);
}
} break;
case FILL_MODE_MAX:
break;
default:
draw_texture(over, Point2(), tint_over);
}
} }
} }
@ -430,7 +522,7 @@ void TextureProgress::_notification(int p_what) {
} }
void TextureProgress::set_fill_mode(int p_fill) { void TextureProgress::set_fill_mode(int p_fill) {
ERR_FAIL_INDEX(p_fill, 9); ERR_FAIL_INDEX(p_fill, FILL_MODE_MAX);
mode = (FillMode)p_fill; mode = (FillMode)p_fill;
update(); update();
} }
@ -513,7 +605,7 @@ void TextureProgress::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_under", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_under_texture", "get_under_texture"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_under", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_under_texture", "get_under_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_over", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_over_texture", "get_over_texture"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_over", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_over_texture", "get_over_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_progress", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_progress_texture", "get_progress_texture"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_progress", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_progress_texture", "get_progress_texture");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fill_mode", PROPERTY_HINT_ENUM, "Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise,Bilinear (Left and Right),Bilinear (Top and Bottom), Clockwise and Counter Clockwise"), "set_fill_mode", "get_fill_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "fill_mode", PROPERTY_HINT_ENUM, "Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise,Bilinear (Left and Right),Bilinear (Top and Bottom),Clockwise and Counter Clockwise"), "set_fill_mode", "get_fill_mode");
ADD_GROUP("Tint", "tint_"); ADD_GROUP("Tint", "tint_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_under"), "set_tint_under", "get_tint_under"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_under"), "set_tint_under", "get_tint_under");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_over"), "set_tint_over", "get_tint_over"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "tint_over"), "set_tint_over", "get_tint_over");

View File

@ -54,7 +54,8 @@ public:
FILL_COUNTER_CLOCKWISE, FILL_COUNTER_CLOCKWISE,
FILL_BILINEAR_LEFT_AND_RIGHT, FILL_BILINEAR_LEFT_AND_RIGHT,
FILL_BILINEAR_TOP_AND_BOTTOM, FILL_BILINEAR_TOP_AND_BOTTOM,
FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE,
FILL_MODE_MAX,
}; };
void set_fill_mode(int p_fill); void set_fill_mode(int p_fill);

View File

@ -471,7 +471,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
StringName type = p_node->get_class(); StringName type = p_node->get_class();
Ref<Script> script = p_node->get_script(); Ref<Script> script = p_node->get_script();
if (script.is_valid()) { if (Engine::get_singleton()->is_editor_hint() && script.is_valid()) {
// Should be called in the editor only and not at runtime,
// otherwise it can cause problems because of missing instance state support.
script->update_exports(); script->update_exports();
} }
@ -893,6 +895,13 @@ Error SceneState::pack(Node *p_scene) {
node_paths.write[E->get()] = scene->get_path_to(E->key()); node_paths.write[E->get()] = scene->get_path_to(E->key());
} }
if (Engine::get_singleton()->is_editor_hint()) {
// Build node path cache
for (Map<Node *, int>::Element *E = node_map.front(); E; E = E->next()) {
node_path_cache[scene->get_path_to(E->key())] = E->get();
}
}
return OK; return OK;
} }
@ -927,10 +936,12 @@ Ref<SceneState> SceneState::_get_base_scene_state() const {
} }
int SceneState::find_node_by_path(const NodePath &p_node) const { int SceneState::find_node_by_path(const NodePath &p_node) const {
ERR_FAIL_COND_V_MSG(node_path_cache.size() == 0, -1, "This operation requires the node cache to have been built.");
if (!node_path_cache.has(p_node)) { if (!node_path_cache.has(p_node)) {
if (_get_base_scene_state().is_valid()) { if (_get_base_scene_state().is_valid()) {
int idx = _get_base_scene_state()->find_node_by_path(p_node); int idx = _get_base_scene_state()->find_node_by_path(p_node);
if (idx >= 0) { if (idx != -1) {
int rkey = _find_base_scene_node_remap_key(idx); int rkey = _find_base_scene_node_remap_key(idx);
if (rkey == -1) { if (rkey == -1) {
rkey = nodes.size() + base_scene_node_remap.size(); rkey = nodes.size() + base_scene_node_remap.size();

View File

@ -886,9 +886,9 @@ void CylinderMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CylinderMesh::set_rings); ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CylinderMesh::set_rings);
ClassDB::bind_method(D_METHOD("get_rings"), &CylinderMesh::get_rings); ClassDB::bind_method(D_METHOD("get_rings"), &CylinderMesh::get_rings);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "top_radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_top_radius", "get_top_radius"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "top_radius", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_top_radius", "get_top_radius");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bottom_radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_bottom_radius", "get_bottom_radius"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "bottom_radius", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_bottom_radius", "get_bottom_radius");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_rings", "get_rings"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_rings", "get_rings");
} }