diff options
25 files changed, 409 insertions, 82 deletions
diff --git a/core/ustring.cpp b/core/ustring.cpp index 21696e2a55..3f5e198281 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -2150,7 +2150,7 @@ int64_t String::to_int(const CharType *p_str, int p_len) { if (integer > INT32_MAX / 10) { String number(""); str = p_str; - while (str != limit) { + while (*str && str != limit) { number += *(str++); } ERR_FAIL_V_MSG(sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index 56b4b21525..04deae6bf5 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -136,6 +136,15 @@ Returns the column's icon's maximum width. </description> </method> + <method name="get_icon_modulate" qualifiers="const"> + <return type="Color"> + </return> + <argument index="0" name="column" type="int"> + </argument> + <description> + Returns the [Color] modulating the column's icon. + </description> + </method> <method name="get_icon_region" qualifiers="const"> <return type="Rect2"> </return> @@ -464,6 +473,17 @@ Sets the given column's icon's maximum width. </description> </method> + <method name="set_icon_modulate"> + <return type="void"> + </return> + <argument index="0" name="column" type="int"> + </argument> + <argument index="1" name="modulate" type="Color"> + </argument> + <description> + Modulates the given column's icon with [code]modulate[/code]. + </description> + </method> <method name="set_icon_region"> <return type="void"> </return> diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 8e026b96ce..5c02d8096d 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -1570,7 +1570,7 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { pi.hint = PROPERTY_HINT_RANGE; - pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]); + pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]); } } break; diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 40574d8c77..afc63cc416 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -804,6 +804,15 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener code += "else\n"; code += _dump_node_code(cf_node->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } + } else if (cf_node->flow_op == SL::FLOW_OP_SWITCH) { + code += _mktab(p_level) + "switch (" + _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; + code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cf_node->flow_op == SL::FLOW_OP_CASE) { + code += _mktab(p_level) + "case " + _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ":\n"; + code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cf_node->flow_op == SL::FLOW_OP_DEFAULT) { + code += _mktab(p_level) + "default:\n"; + code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } else if (cf_node->flow_op == SL::FLOW_OP_DO) { code += _mktab(p_level); code += "do"; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index a54064e4c8..5f4acbc2de 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2247,7 +2247,7 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn pi.type = Variant::INT; if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { pi.hint = PROPERTY_HINT_RANGE; - pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]); + pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]) + "," + rtos(u.hint_range[2]); } } break; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 85ace4b4f0..0121d88f4d 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -801,6 +801,15 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener code += _mktab(p_level) + "else\n"; code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } + } else if (cfnode->flow_op == SL::FLOW_OP_SWITCH) { + code += _mktab(p_level) + "switch (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cfnode->flow_op == SL::FLOW_OP_CASE) { + code += _mktab(p_level) + "case " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ":\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cfnode->flow_op == SL::FLOW_OP_DEFAULT) { + code += _mktab(p_level) + "default:\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); } else if (cfnode->flow_op == SL::FLOW_OP_DO) { code += _mktab(p_level) + "do"; code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 84631f3e38..a729befe8e 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -63,7 +63,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory subdirectory_item->set_text(0, dname); subdirectory_item->set_icon(0, get_icon("Folder", "EditorIcons")); - subdirectory_item->set_icon_color(0, get_color("folder_icon_modulate", "FileDialog")); + subdirectory_item->set_icon_modulate(0, get_color("folder_icon_modulate", "FileDialog")); subdirectory_item->set_selectable(0, true); String lpath = p_dir->get_path(); subdirectory_item->set_metadata(0, lpath); @@ -214,7 +214,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo TreeItem *ti = tree->create_item(favorites); ti->set_text(0, text); ti->set_icon(0, icon); - ti->set_icon_color(0, color); + ti->set_icon_modulate(0, color); ti->set_tooltip(0, fave); ti->set_selectable(0, true); ti->set_metadata(0, fave); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 589964f620..c036a31ab5 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -41,6 +41,7 @@ #include "scene/gui/panel.h" #include "scene/main/viewport.h" #include "scene/resources/visual_shader_nodes.h" +#include "servers/visual/shader_types.h" Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) { @@ -229,6 +230,14 @@ void VisualShaderEditor::_update_custom_nodes() { } } +String VisualShaderEditor::_get_description(int p_idx) { + if (add_options[p_idx].highend) { + return TTR("(GLES3 only)") + " " + add_options[p_idx].description; // TODO: change it to (Vulkan Only) when its ready + } else { + return add_options[p_idx].description; + } +} + void VisualShaderEditor::_update_options_menu() { node_desc->set_text(""); @@ -332,11 +341,10 @@ void VisualShaderEditor::_update_options_menu() { else if (add_options[i].highend) item->set_custom_color(0, supported_color); item->set_text(0, add_options[i].name); - if (p_category == sub_category) { - if (is_first_item) { - item->select(0); - is_first_item = false; - } + if (is_first_item && use_filter) { + item->select(0); + node_desc->set_text(_get_description(i)); + is_first_item = false; } switch (add_options[i].return_type) { case VisualShaderNode::PORT_TYPE_SCALAR: @@ -1598,6 +1606,9 @@ void VisualShaderEditor::_notification(int p_what) { preview_text->add_color_override("symbol_color", symbol_color); preview_text->add_color_region("/*", "*/", comment_color, false); preview_text->add_color_region("//", "", comment_color, false); + + error_text->add_font_override("font", get_font("status_source", "EditorFonts")); + error_text->add_color_override("font_color", get_color("error_color", "Editor")); } tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Tools", "EditorIcons")); @@ -1926,11 +1937,7 @@ void VisualShaderEditor::_member_selected() { if (item != NULL && item->has_meta("id")) { members_dialog->get_ok()->set_disabled(false); - if (add_options[item->get_meta("id")].highend) { - node_desc->set_text(TTR("(GLES3 only)") + " " + add_options[item->get_meta("id")].description); // TODO: change it to (Vulkan Only) when its ready - } else { - node_desc->set_text(add_options[item->get_meta("id")].description); - } + node_desc->set_text(_get_description(item->get_meta("id"))); } else { members_dialog->get_ok()->set_disabled(true); node_desc->set_text(""); @@ -2052,11 +2059,44 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da void VisualShaderEditor::_show_preview_text() { preview_showed = !preview_showed; - preview_text->set_visible(preview_showed); + preview_vbox->set_visible(preview_showed); + if (preview_showed) { + if (pending_update_preview) { + _update_preview(); + pending_update_preview = false; + } + } } void VisualShaderEditor::_update_preview() { - preview_text->set_text(visual_shader->get_code()); + + if (!preview_showed) { + pending_update_preview = true; + return; + } + + String code = visual_shader->get_code(); + + preview_text->set_text(code); + + ShaderLanguage sl; + + Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_types()); + + for (int i = 0; i < preview_text->get_line_count(); i++) { + preview_text->set_line_as_marked(i, false); + } + if (err != OK) { + preview_text->set_line_as_marked(sl.get_error_line() - 1, true); + error_text->set_visible(true); + + String text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); + error_text->set_text(text); + shader_error = true; + } else { + error_text->set_visible(false); + shader_error = false; + } } void VisualShaderEditor::_bind_methods() { @@ -2127,6 +2167,8 @@ VisualShaderEditor::VisualShaderEditor() { ShaderLanguage::get_keyword_list(&keyword_list); preview_showed = false; + pending_update_preview = false; + shader_error = false; to_node = -1; to_slot = -1; @@ -2201,15 +2243,22 @@ VisualShaderEditor::VisualShaderEditor() { // PREVIEW PANEL /////////////////////////////////////// + preview_vbox = memnew(VBoxContainer); + preview_vbox->set_visible(preview_showed); + main_box->add_child(preview_vbox); preview_text = memnew(TextEdit); - main_box->add_child(preview_text); + preview_vbox->add_child(preview_text); preview_text->set_h_size_flags(SIZE_EXPAND_FILL); preview_text->set_v_size_flags(SIZE_EXPAND_FILL); - preview_text->set_visible(preview_showed); preview_text->set_custom_minimum_size(Size2(400 * EDSCALE, 0)); preview_text->set_syntax_coloring(true); + preview_text->set_show_line_numbers(true); preview_text->set_readonly(true); + error_text = memnew(Label); + preview_vbox->add_child(error_text); + error_text->set_visible(false); + /////////////////////////////////////// // SHADER NODES TREE /////////////////////////////////////// diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 1556c7cd43..cd5efc366b 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -70,7 +70,11 @@ class VisualShaderEditor : public VBoxContainer { PanelContainer *error_panel; Label *error_label; + bool pending_update_preview; + bool shader_error; + VBoxContainer *preview_vbox; TextEdit *preview_text; + Label *error_text; UndoRedo *undo_redo; Point2 saved_node_pos; @@ -154,6 +158,7 @@ class VisualShaderEditor : public VBoxContainer { void _show_preview_text(); void _update_preview(); + String _get_description(int p_idx); static VisualShaderEditor *singleton; diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj index f3ac353c0f..dcfdd83831 100644 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj @@ -11,6 +11,7 @@ <AssemblyName>GodotTools.BuildLogger</AssemblyName> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> + <LangVersion>7</LangVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj index f36b40f87c..24c7cb1573 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj @@ -8,6 +8,7 @@ <RootNamespace>GodotTools.Core</RootNamespace> <AssemblyName>GodotTools.Core</AssemblyName> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <LangVersion>7</LangVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotTools.IdeConnection.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotTools.IdeConnection.csproj index 84c08251ab..94e525715b 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotTools.IdeConnection.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotTools.IdeConnection.csproj @@ -11,6 +11,7 @@ <AssemblyName>GodotTools.IdeConnection</AssemblyName> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> + <LangVersion>7</LangVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj index 08b8ba3946..c745fe321b 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj @@ -9,6 +9,7 @@ <AssemblyName>GodotTools.ProjectEditor</AssemblyName> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <BaseIntermediateOutputPath>obj</BaseIntermediateOutputPath> + <LangVersion>7</LangVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 099c7fcb56..7da7cff933 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -359,7 +359,7 @@ namespace GodotTools aboutLabel.Text = "C# support in Godot Engine is in late alpha stage and, while already usable, " + "it is not meant for use in production.\n\n" + - "Projects can be exported to Linux, macOS and Windows, but not yet to mobile or web platforms. " + + "Projects can be exported to Linux, macOS, Windows and Android, but not yet to iOS, HTML5 or UWP. " + "Bugs and usability issues will be addressed gradually over future releases, " + "potentially including compatibility breaking changes as new features are implemented for a better overall C# experience.\n\n" + "If you experience issues with this Mono build, please report them on Godot's issue tracker with details about your system, MSBuild version, IDE, etc.:\n\n" + diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index e2d576caef..3c57900873 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -10,6 +10,7 @@ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath> <GodotApiConfiguration>Debug</GodotApiConfiguration> + <LangVersion>7</LangVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/NotifyAwaiter.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/NotifyAwaiter.cs index a3490fa89f..700b786752 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/NotifyAwaiter.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/NotifyAwaiter.cs @@ -51,7 +51,7 @@ namespace GodotTools.Utils { continuation = null; exception = null; - result = default; + result = default(T); IsCompleted = false; return this; } diff --git a/modules/mono/glue/Managed/Managed.csproj b/modules/mono/glue/Managed/Managed.csproj index ad55fe9539..c8eca71199 100644 --- a/modules/mono/glue/Managed/Managed.csproj +++ b/modules/mono/glue/Managed/Managed.csproj @@ -8,6 +8,7 @@ <RootNamespace>Managed</RootNamespace> <AssemblyName>Managed</AssemblyName> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <LangVersion>7</LangVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> <DebugSymbols>true</DebugSymbols> diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 0c096f0d97..9bc593ea3b 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -430,7 +430,7 @@ void FileDialog::update_file_list() { TreeItem *ti = tree->create_item(root); ti->set_text(0, dir_name); ti->set_icon(0, folder); - ti->set_icon_color(0, folder_color); + ti->set_icon_modulate(0, folder_color); Dictionary d; d["name"] = dir_name; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index f8c31121be..7d1895a67a 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -559,7 +559,7 @@ void TextEdit::_update_selection_mode_line() { click_select_held->start(); } -void TextEdit::_update_minimap_scroll() { +void TextEdit::_update_minimap_click() { Point2 mp = get_local_mouse_position(); int xmargin_end = get_size().width - cache.style_normal->get_margin(MARGIN_RIGHT); @@ -573,6 +573,13 @@ void TextEdit::_update_minimap_scroll() { int row; _get_minimap_mouse_row(Point2i(mp.x, mp.y), row); + if (row >= get_first_visible_line() && (row < get_last_visible_line() || row >= (text.size() - 1))) { + minimap_scroll_ratio = v_scroll->get_as_ratio(); + minimap_scroll_click_pos = mp.y; + can_drag_minimap = true; + return; + } + int wi; int first_line = row - num_lines_from_rows(row, 0, -get_visible_rows() / 2, wi) + 1; double delta = get_scroll_pos_for_line(first_line, wi) - get_v_scroll(); @@ -583,6 +590,17 @@ void TextEdit::_update_minimap_scroll() { } } +void TextEdit::_update_minimap_drag() { + + if (!can_drag_minimap) { + return; + } + + Point2 mp = get_local_mouse_position(); + double diff = (mp.y - minimap_scroll_click_pos) / _get_control_height(); + v_scroll->set_as_ratio(minimap_scroll_ratio + diff); +} + void TextEdit::_notification(int p_what) { switch (p_what) { @@ -899,12 +917,7 @@ void TextEdit::_notification(int p_what) { // calculate viewport size and y offset int viewport_height = (draw_amount - 1) * minimap_line_height; - int control_height = size.height; - control_height -= cache.style_normal->get_minimum_size().height; - if (h_scroll->is_visible_in_tree()) { - control_height -= h_scroll->get_size().height; - } - control_height -= viewport_height; + int control_height = _get_control_height() - viewport_height; int viewport_offset_y = round(get_scroll_pos_for_line(first_visible_line) * control_height) / ((v_scroll->get_max() <= minimap_visible_lines) ? (minimap_visible_lines - draw_amount) : (v_scroll->get_max() - draw_amount)); // calculate the first line. @@ -918,8 +931,7 @@ void TextEdit::_notification(int p_what) { int minimap_draw_amount = minimap_visible_lines + times_line_wraps(minimap_line + 1); // draw the minimap - Color viewport_color = cache.current_line_color; - viewport_color.a /= 2; + Color viewport_color = (cache.background_color.get_v() < 0.5) ? Color(1, 1, 1, 0.1) : Color(0, 0, 0, 0.1); VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), viewport_offset_y, cache.minimap_width, viewport_height), viewport_color); for (int i = 0; i < minimap_draw_amount; i++) { @@ -2071,12 +2083,7 @@ void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const // calculate viewport size and y offset int viewport_height = (draw_amount - 1) * minimap_line_height; - int control_height = get_size().height; - control_height -= cache.style_normal->get_minimum_size().height; - if (h_scroll->is_visible_in_tree()) { - control_height -= h_scroll->get_size().height; - } - control_height -= viewport_height; + int control_height = _get_control_height() - viewport_height; int viewport_offset_y = round(get_scroll_pos_for_line(first_visible_line) * control_height) / ((v_scroll->get_max() <= minimap_visible_lines) ? (minimap_visible_lines - draw_amount) : (v_scroll->get_max() - draw_amount)); // calculate the first line. @@ -2240,7 +2247,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { // minimap if (draw_minimap) { - _update_minimap_scroll(); + _update_minimap_click(); if (dragging_minimap) { return; } @@ -2363,6 +2370,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (mb->get_button_index() == BUTTON_LEFT) { dragging_minimap = false; dragging_selection = false; + can_drag_minimap = false; click_select_held->stop(); } @@ -2411,7 +2419,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { _reset_caret_blink_timer(); if (draw_minimap && !dragging_selection) { - _update_minimap_scroll(); + _update_minimap_drag(); } if (!dragging_minimap) { @@ -3506,6 +3514,10 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } break; case KEY_Z: { + if (readonly) { + break; + } + if (!k->get_command()) { scancode_handled = false; break; @@ -3518,6 +3530,10 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } break; case KEY_Y: { + if (readonly) { + break; + } + if (!k->get_command()) { scancode_handled = false; break; @@ -3992,7 +4008,7 @@ void TextEdit::_line_edited_from(int p_line) { if (syntax_highlighting_cache.size() > 0) { cache_size = syntax_highlighting_cache.back()->key(); - for (int i = p_line - 1; i < cache_size; i++) { + for (int i = p_line - 1; i <= cache_size; i++) { if (syntax_highlighting_cache.has(i)) { syntax_highlighting_cache.erase(i); } @@ -4019,23 +4035,21 @@ Size2 TextEdit::get_minimum_size() const { return cache.style_normal->get_minimum_size(); } -int TextEdit::get_visible_rows() const { +int TextEdit::_get_control_height() const { + int control_height = get_size().height; + control_height -= cache.style_normal->get_minimum_size().height; + if (h_scroll->is_visible_in_tree()) { + control_height -= h_scroll->get_size().height; + } + return control_height; +} - int total = get_size().height; - total -= cache.style_normal->get_minimum_size().height; - if (h_scroll->is_visible_in_tree()) - total -= h_scroll->get_size().height; - total /= get_row_height(); - return total; +int TextEdit::get_visible_rows() const { + return _get_control_height() / get_row_height(); } int TextEdit::_get_minimap_visible_rows() const { - int total = get_size().height; - total -= cache.style_normal->get_minimum_size().height; - if (h_scroll->is_visible_in_tree()) - total -= h_scroll->get_size().height; - total /= (minimap_char_size.y + minimap_line_spacing); - return total; + return _get_control_height() / (minimap_char_size.y + minimap_line_spacing); } int TextEdit::get_total_visible_rows() const { @@ -6126,10 +6140,7 @@ int TextEdit::get_last_visible_line_wrap_index() const { double TextEdit::get_visible_rows_offset() const { - double total = get_size().height; - total -= cache.style_normal->get_minimum_size().height; - if (h_scroll->is_visible_in_tree()) - total -= h_scroll->get_size().height; + double total = _get_control_height(); total /= (double)get_row_height(); total = total - floor(total); total = -CLAMP(total, 0.001, 1) + 1; @@ -6539,9 +6550,21 @@ void TextEdit::set_line(int line, String new_text) { } void TextEdit::insert_at(const String &p_text, int at) { - cursor_set_column(0); - cursor_set_line(at, false, true); _insert_text(at, 0, p_text + "\n"); + if (cursor.line >= at) { + // offset cursor when located after inserted line + ++cursor.line; + } + if (is_selection_active()) { + if (selection.from_line >= at) { + // offset selection when located after inserted line + ++selection.from_line; + ++selection.to_line; + } else if (selection.to_line >= at) { + // extend selection that includes inserted line + ++selection.to_line; + } + } } void TextEdit::set_show_line_numbers(bool p_show) { @@ -7019,6 +7042,9 @@ TextEdit::TextEdit() { scrolling = false; minimap_clicked = false; dragging_minimap = false; + can_drag_minimap = false; + minimap_scroll_ratio = 0; + minimap_scroll_click_pos = 0; dragging_selection = false; target_v_scroll = 0; v_scroll_speed = 80; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 889be3eaa5..9c568acd93 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -334,7 +334,10 @@ private: bool scrolling; bool dragging_selection; bool dragging_minimap; + bool can_drag_minimap; bool minimap_clicked; + double minimap_scroll_ratio; + double minimap_scroll_click_pos; float target_v_scroll; float v_scroll_speed; @@ -406,7 +409,8 @@ private: void _update_selection_mode_word(); void _update_selection_mode_line(); - void _update_minimap_scroll(); + void _update_minimap_click(); + void _update_minimap_drag(); void _scroll_up(real_t p_delta); void _scroll_down(real_t p_delta); @@ -418,6 +422,7 @@ private: //void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask); Size2 get_minimum_size() const; + int _get_control_height() const; int get_row_height() const; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6c8aa35e3c..b7451faad3 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -224,14 +224,14 @@ Rect2 TreeItem::get_icon_region(int p_column) const { return cells[p_column].icon_region; } -void TreeItem::set_icon_color(int p_column, const Color &p_icon_color) { +void TreeItem::set_icon_modulate(int p_column, const Color &p_modulate) { ERR_FAIL_INDEX(p_column, cells.size()); - cells.write[p_column].icon_color = p_icon_color; + cells.write[p_column].icon_color = p_modulate; _changed_notify(p_column); } -Color TreeItem::get_icon_color(int p_column) const { +Color TreeItem::get_icon_modulate(int p_column) const { ERR_FAIL_INDEX_V(p_column, cells.size(), Color()); return cells[p_column].icon_color; @@ -744,6 +744,9 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_icon_max_width", "column", "width"), &TreeItem::set_icon_max_width); ClassDB::bind_method(D_METHOD("get_icon_max_width", "column"), &TreeItem::get_icon_max_width); + ClassDB::bind_method(D_METHOD("set_icon_modulate", "column", "modulate"), &TreeItem::set_icon_modulate); + ClassDB::bind_method(D_METHOD("get_icon_modulate", "column"), &TreeItem::get_icon_modulate); + ClassDB::bind_method(D_METHOD("set_range", "column", "value"), &TreeItem::set_range); ClassDB::bind_method(D_METHOD("get_range", "column"), &TreeItem::get_range); ClassDB::bind_method(D_METHOD("set_range_config", "column", "min", "max", "step", "expr"), &TreeItem::set_range_config, DEFVAL(false)); @@ -1259,10 +1262,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 check_ofs.y += Math::floor((real_t)(item_rect.size.y - checked->get_height()) / 2); if (p_item->cells[i].checked) { - - checked->draw(ci, check_ofs, icon_col); + checked->draw(ci, check_ofs); } else { - unchecked->draw(ci, check_ofs, icon_col); + unchecked->draw(ci, check_ofs); } int check_w = checked->get_width() + cache.hseparation; @@ -1274,8 +1276,6 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 draw_item_rect(p_item->cells[i], item_rect, col, icon_col); - //font->draw( ci, text_pos, p_item->cells[i].text, col,item_rect.size.x-check_w ); - } break; case TreeItem::CELL_MODE_RANGE: { if (p_item->cells[i].text != "") { @@ -1305,18 +1305,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 font->draw(ci, text_pos, s, col, item_rect.size.x - downarrow->get_width()); - //? Point2i arrow_pos = item_rect.position; arrow_pos.x += item_rect.size.x - downarrow->get_width(); arrow_pos.y += Math::floor(((item_rect.size.y - downarrow->get_height())) / 2.0); - downarrow->draw(ci, arrow_pos, icon_col); + downarrow->draw(ci, arrow_pos); } else { Ref<Texture> updown = cache.updown; String valtext = String::num(p_item->cells[i].val, Math::range_step_decimals(p_item->cells[i].step)); - //String valtext = rtos( p_item->cells[i].val ); if (p_item->cells[i].suffix != String()) valtext += " " + p_item->cells[i].suffix; @@ -1330,7 +1328,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 updown_pos.x += item_rect.size.x - updown->get_width(); updown_pos.y += Math::floor(((item_rect.size.y - updown->get_height())) / 2.0); - updown->draw(ci, updown_pos, icon_col); + updown->draw(ci, updown_pos); } } break; @@ -1348,13 +1346,10 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 icon_ofs += item_rect.position; draw_texture_rect(p_item->cells[i].icon, Rect2(icon_ofs, icon_size), false, icon_col); - //p_item->cells[i].icon->draw(ci, icon_ofs); } break; case TreeItem::CELL_MODE_CUSTOM: { - //int option = (int)p_item->cells[i].val; - if (p_item->cells[i].custom_draw_obj) { Object *cdo = ObjectDB::get_instance(p_item->cells[i].custom_draw_obj); @@ -1429,10 +1424,6 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 arrow->draw(ci, p_pos + p_draw_ofs + Point2i(0, (label_h - arrow->get_height()) / 2) - cache.offset); } - //separator - //get_painter()->draw_fill_rect( Point2i(0,pos.y),Size2i(get_size().width,1),color( COLOR_TREE_GRID) ); - - //pos=p_pos; //reset pos } Point2 children_pos = p_pos; diff --git a/scene/gui/tree.h b/scene/gui/tree.h index b57923e24b..fdc6da5055 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -193,8 +193,8 @@ public: void set_icon_region(int p_column, const Rect2 &p_icon_region); Rect2 get_icon_region(int p_column) const; - void set_icon_color(int p_column, const Color &p_icon_color); - Color get_icon_color(int p_column) const; + void set_icon_modulate(int p_column, const Color &p_modulate); + Color get_icon_modulate(int p_column) const; void set_icon_max_width(int p_column, int p_max); int get_icon_max_width(int p_column) const; diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index 60fb3a3a95..6ba159ca0a 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -671,6 +671,7 @@ Body2DSW::Body2DSW() : angular_velocity = 0; biased_angular_velocity = 0; mass = 1; + inertia = 0; user_inertia = false; _inv_inertia = 0; _inv_mass = 1; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 1dd6699851..e9d85c7eb0 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -283,6 +283,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_CF_DO, "do" }, { TK_CF_SWITCH, "switch" }, { TK_CF_CASE, "case" }, + { TK_CF_DEFAULT, "default" }, { TK_CF_BREAK, "break" }, { TK_CF_CONTINUE, "continue" }, { TK_CF_RETURN, "return" }, @@ -3778,6 +3779,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui TkPos pos = _get_tkpos(); Token tk = _get_token(); + + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_SWITCH) { + if (tk.type != TK_CF_CASE && tk.type != TK_CF_DEFAULT && tk.type != TK_CURLY_BRACKET_CLOSE) { + _set_error("Switch may contains only case and default blocks"); + return ERR_PARSE_ERROR; + } + } + if (tk.type == TK_CURLY_BRACKET_CLOSE) { //end of block if (p_just_one) { _set_error("Unexpected '}'"); @@ -4132,6 +4141,183 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } else { _set_tkpos(pos); //rollback } + } else if (tk.type == TK_CF_SWITCH) { + // switch() {} + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after switch"); + return ERR_PARSE_ERROR; + } + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op = FLOW_OP_SWITCH; + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + if (n->get_datatype() != TYPE_INT) { + _set_error("Expected integer expression"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' after expression"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + if (tk.type != TK_CURLY_BRACKET_OPEN) { + _set_error("Expected '{' after switch statement"); + return ERR_PARSE_ERROR; + } + BlockNode *switch_block = alloc_node<BlockNode>(); + switch_block->block_type = BlockNode::BLOCK_TYPE_SWITCH; + switch_block->parent_block = p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(switch_block); + p_block->statements.push_back(cf); + + int prev_type = TK_CF_CASE; + while (true) { // Go-through multiple cases. + + if (_parse_block(switch_block, p_builtin_types, true, true, false) != OK) { + return ERR_PARSE_ERROR; + } + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_CF_CASE || tk.type == TK_CF_DEFAULT) { + if (prev_type == TK_CF_DEFAULT) { + if (tk.type == TK_CF_CASE) { + _set_error("Cases must be defined before default case."); + return ERR_PARSE_ERROR; + } else if (prev_type == TK_CF_DEFAULT) { + _set_error("Default case must be defined only once."); + return ERR_PARSE_ERROR; + } + } + prev_type = tk.type; + _set_tkpos(pos); + continue; + } else { + Set<int> constants; + for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates. + ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i]; + if (flow) { + if (flow->flow_op == FLOW_OP_CASE) { + ConstantNode *n2 = static_cast<ConstantNode *>(flow->expressions[0]); + if (!n2) { + return ERR_PARSE_ERROR; + } + if (n2->values.empty()) { + return ERR_PARSE_ERROR; + } + if (constants.has(n2->values[0].sint)) { + _set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'"); + return ERR_PARSE_ERROR; + } + constants.insert(n2->values[0].sint); + } else if (flow->flow_op == FLOW_OP_DEFAULT) { + continue; + } else { + return ERR_PARSE_ERROR; + } + } else { + return ERR_PARSE_ERROR; + } + } + break; + } + } + + } else if (tk.type == TK_CF_CASE) { + // case x : break; | return; + + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) { + _set_tkpos(pos); + return OK; + } + + if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { + _set_error("case must be placed within switch block"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + int sign = 1; + + if (tk.type == TK_OP_SUB) { + sign = -1; + tk = _get_token(); + } + + if (tk.type != TK_INT_CONSTANT) { + _set_error("Expected integer constant"); + return ERR_PARSE_ERROR; + } + + int constant = (int)tk.constant * sign; + + tk = _get_token(); + + if (tk.type != TK_COLON) { + _set_error("Expected ':'"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op = FLOW_OP_CASE; + + ConstantNode *n = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.sint = constant; + n->values.push_back(v); + n->datatype = TYPE_INT; + + BlockNode *case_block = alloc_node<BlockNode>(); + case_block->block_type = BlockNode::BLOCK_TYPE_CASE; + case_block->parent_block = p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(case_block); + p_block->statements.push_back(cf); + + Error err = _parse_block(case_block, p_builtin_types, false, true, false); + if (err) + return err; + + return OK; + + } else if (tk.type == TK_CF_DEFAULT) { + + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) { + _set_tkpos(pos); + return OK; + } + + if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { + _set_error("default must be placed within switch block"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type != TK_COLON) { + _set_error("Expected ':'"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op = FLOW_OP_DEFAULT; + + BlockNode *default_block = alloc_node<BlockNode>(); + default_block->block_type = BlockNode::BLOCK_TYPE_DEFAULT; + default_block->parent_block = p_block; + cf->blocks.push_back(default_block); + p_block->statements.push_back(cf); + + Error err = _parse_block(default_block, p_builtin_types, false, true, false); + if (err) + return err; + + return OK; + } else if (tk.type == TK_CF_DO || tk.type == TK_CF_WHILE) { // do {} while() // while() {} @@ -4299,6 +4485,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } p_block->statements.push_back(flow); + if (p_block->block_type == BlockNode::BLOCK_TYPE_CASE || p_block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) { + return OK; + } } else if (tk.type == TK_CF_DISCARD) { //check return type @@ -4345,9 +4534,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } p_block->statements.push_back(flow); + if (p_block->block_type == BlockNode::BLOCK_TYPE_CASE || p_block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) { + return OK; + } + } else if (tk.type == TK_CF_CONTINUE) { - if (!p_can_break) { + if (!p_can_continue) { //all is good _set_error("Continuing is not allowed here"); } diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 36c691c3ae..b71788513e 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -125,6 +125,7 @@ public: TK_CF_DO, TK_CF_SWITCH, TK_CF_CASE, + TK_CF_DEFAULT, TK_CF_BREAK, TK_CF_CONTINUE, TK_CF_RETURN, @@ -266,6 +267,8 @@ public: FLOW_OP_DO, FLOW_OP_BREAK, FLOW_OP_SWITCH, + FLOW_OP_CASE, + FLOW_OP_DEFAULT, FLOW_OP_CONTINUE, FLOW_OP_DISCARD }; @@ -420,6 +423,15 @@ public: FunctionNode *parent_function; BlockNode *parent_block; + enum BlockType { + BLOCK_TYPE_STANDART, + BLOCK_TYPE_SWITCH, + BLOCK_TYPE_CASE, + BLOCK_TYPE_DEFAULT, + }; + + int block_type; + struct Variable { DataType type; DataPrecision precision; @@ -436,6 +448,7 @@ public: Node(TYPE_BLOCK), parent_function(NULL), parent_block(NULL), + block_type(BLOCK_TYPE_STANDART), single_statement(false) {} }; |