diff options
40 files changed, 552 insertions, 477 deletions
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index cc3d5a1139..86c1002666 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -157,11 +157,11 @@ <member name="fog_height_enabled" type="bool" setter="set_fog_height_enabled" getter="is_fog_height_enabled" default="false"> Enables the fog height. </member> - <member name="fog_height_max" type="float" setter="set_fog_height_max" getter="get_fog_height_max" default="100.0"> - Maximum height of fog. + <member name="fog_height_max" type="float" setter="set_fog_height_max" getter="get_fog_height_max" default="0.0"> + The Y coordinate where the height fog will be the most intense. If this value is greater than [member fog_height_min], fog will be displayed from bottom to top. Otherwise, it will be displayed from top to bottom. </member> - <member name="fog_height_min" type="float" setter="set_fog_height_min" getter="get_fog_height_min" default="0.0"> - Minimum height of fog. + <member name="fog_height_min" type="float" setter="set_fog_height_min" getter="get_fog_height_min" default="10.0"> + The Y coordinate where the height fog will be the least intense. If this value is greater than [member fog_height_max], fog will be displayed from top to bottom. Otherwise, it will be displayed from bottom to top. </member> <member name="fog_sun_amount" type="float" setter="set_fog_sun_amount" getter="get_fog_sun_amount" default="0.0"> Amount of sun that affects the fog rendering. diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index c2b7901c05..62a7147e08 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -16,6 +16,7 @@ var subchild1 = tree.create_item(child1) subchild1.set_text(0, "Subchild1") [/codeblock] + To iterate over all the [TreeItem] objects in a [Tree] object, use [method TreeItem.get_next] and [method TreeItem.get_children] after getting the root through [get_root]. </description> <tutorials> </tutorials> diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index f60ca9675e..69a2295fc1 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -398,8 +398,8 @@ public: fog_transmit_enabled(true), fog_transmit_curve(1), fog_height_enabled(false), - fog_height_min(0), - fog_height_max(100), + fog_height_min(10), + fog_height_max(0), fog_height_curve(1) { } }; diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index b5e64b6162..3d09adcfeb 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -527,8 +527,8 @@ public: fog_transmit_enabled(true), fog_transmit_curve(1), fog_height_enabled(false), - fog_height_min(0), - fog_height_max(100), + fog_height_min(10), + fog_height_max(0), fog_height_curve(1) { } }; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index d81a1dbd77..7aa24c7476 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1427,11 +1427,10 @@ void EditorHelp::generate_doc() { void EditorHelp::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_READY: case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - _update_doc(); + _update_doc(); } break; default: break; } @@ -1573,7 +1572,6 @@ void EditorHelpBit::_notification(int p_what) { rich_text->add_color_override("selection_color", get_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); } break; - default: break; } } @@ -1603,6 +1601,10 @@ FindBar::FindBar() { search_text->connect("text_changed", this, "_search_text_changed"); search_text->connect("text_entered", this, "_search_text_entered"); + matches_label = memnew(Label); + add_child(matches_label); + matches_label->hide(); + find_prev = memnew(ToolButton); add_child(find_prev); find_prev->set_focus_mode(FOCUS_NONE); @@ -1613,9 +1615,9 @@ FindBar::FindBar() { find_next->set_focus_mode(FOCUS_NONE); find_next->connect("pressed", this, "_search_next"); - error_label = memnew(Label); - add_child(error_label); - error_label->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + Control *space = memnew(Control); + add_child(space); + space->set_custom_minimum_size(Size2(4, 0) * EDSCALE); hide_button = memnew(TextureButton); add_child(hide_button); @@ -1645,25 +1647,21 @@ void FindBar::popup_search() { void FindBar::_notification(int p_what) { - if (p_what == NOTIFICATION_READY) { - - find_prev->set_icon(get_icon("MoveUp", "EditorIcons")); - find_next->set_icon(get_icon("MoveDown", "EditorIcons")); - hide_button->set_normal_texture(get_icon("Close", "EditorIcons")); - hide_button->set_hover_texture(get_icon("Close", "EditorIcons")); - hide_button->set_pressed_texture(get_icon("Close", "EditorIcons")); - hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size()); - } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - - set_process_unhandled_input(is_visible_in_tree()); - } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - - find_prev->set_icon(get_icon("MoveUp", "EditorIcons")); - find_next->set_icon(get_icon("MoveDown", "EditorIcons")); - hide_button->set_normal_texture(get_icon("Close", "EditorIcons")); - hide_button->set_hover_texture(get_icon("Close", "EditorIcons")); - hide_button->set_pressed_texture(get_icon("Close", "EditorIcons")); - hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size()); + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + + find_prev->set_icon(get_icon("MoveUp", "EditorIcons")); + find_next->set_icon(get_icon("MoveDown", "EditorIcons")); + hide_button->set_normal_texture(get_icon("Close", "EditorIcons")); + hide_button->set_hover_texture(get_icon("Close", "EditorIcons")); + hide_button->set_pressed_texture(get_icon("Close", "EditorIcons")); + hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size()); + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + + set_process_unhandled_input(is_visible_in_tree()); + } break; } } @@ -1708,17 +1706,52 @@ bool FindBar::_search(bool p_search_previous) { prev_search = stext; if (ret) { - set_error(""); + _update_results_count(); } else { - set_error(stext.empty() ? "" : TTR("No Matches")); + results_count = 0; } + _update_matches_label(); return ret; } -void FindBar::set_error(const String &p_label) { +void FindBar::_update_results_count() { + + results_count = 0; + + String searched = search_text->get_text(); + if (searched.empty()) return; + + String full_text = rich_text_label->get_text(); + + int from_pos = 0; + + while (true) { + int pos = full_text.find(searched, from_pos); + if (pos == -1) + break; + + results_count++; + from_pos = pos + searched.length(); + } +} + +void FindBar::_update_matches_label() { + + if (results_count > 0) { + matches_label->show(); + + matches_label->add_color_override("font_color", Color(1, 1, 1)); + matches_label->set_text(vformat(TTR("Found %d match(es)."), results_count)); + } else if (search_text->get_text().empty()) { - error_label->set_text(p_label); + matches_label->hide(); + } else { + matches_label->show(); + + matches_label->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + matches_label->set_text(TTR("No Matches")); + } } void FindBar::_hide_bar() { diff --git a/editor/editor_help.h b/editor/editor_help.h index a50ab8a9f9..3824ba231e 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -49,18 +49,23 @@ class FindBar : public HBoxContainer { LineEdit *search_text; ToolButton *find_prev; ToolButton *find_next; - Label *error_label; + Label *matches_label; TextureButton *hide_button; String prev_search; RichTextLabel *rich_text_label; + int results_count; + void _show_search(); void _hide_bar(); void _search_text_changed(const String &p_text); void _search_text_entered(const String &p_text); + void _update_results_count(); + void _update_matches_label(); + void _update_size(); protected: @@ -72,8 +77,6 @@ protected: static void _bind_methods(); public: - void set_error(const String &p_label); - void set_rich_text_label(RichTextLabel *p_rich_text_label); void popup_search(); diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 203136a3f8..d1371a04b1 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -312,7 +312,8 @@ void EditorPropertyArray::update_property() { } else { //bye bye children of the box while (vbox->get_child_count() > 2) { - memdelete(vbox->get_child(2)); + vbox->get_child(2)->queue_delete(); // button still needed after pressed is called + vbox->remove_child(vbox->get_child(2)); } } diff --git a/editor/icons/icon_gizmo_c_p_u_particles.svg b/editor/icons/icon_gizmo_c_p_u_particles.svg new file mode 100644 index 0000000000..a6f0eaef5b --- /dev/null +++ b/editor/icons/icon_gizmo_c_p_u_particles.svg @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="128" + height="128" + version="1.1" + viewBox="0 0 128 128" + id="svg6" + sodipodi:docname="icon_gizmo_c_p_u_particles.svg" + inkscape:version="0.92.4 5da689c313, 2019-01-14"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1606" + inkscape:window-height="821" + id="namedview8" + showgrid="false" + inkscape:zoom="2.6074563" + inkscape:cx="101.29539" + inkscape:cy="83.191634" + inkscape:window-x="295" + inkscape:window-y="81" + inkscape:window-maximized="0" + inkscape:current-layer="svg6" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <path + style="display:inline;opacity:1;fill:#f7f5cf;fill-opacity:1;stroke:#b4b4b4;stroke-width:2.56380486;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 35.503779,1.2819066 c -3.570424,0 -6.435164,2.9483368 -6.435164,6.6019028 v 4.3900146 c 0,0.889114 0.169457,1.726301 0.478513,2.49893 H 19.465369 c -3.570424,0 -6.435167,2.931453 -6.435167,6.585021 v 7.969562 c -0.341543,-0.0568 -0.648813,-0.202614 -1.006525,-0.202614 H 7.7335674 c -3.5704232,0 -6.451665,2.948338 -6.451665,6.601904 v 3.224972 c 0,3.653568 2.8812418,6.585016 6.451665,6.585016 h 4.2901096 c 0.358169,0 0.664563,-0.14568 1.006525,-0.202618 V 83.83104 C 12.688659,83.77398 12.381388,83.628424 12.023677,83.628424 H 7.7335674 c -3.5704232,0 -6.451665,2.948332 -6.451665,6.601908 v 3.224971 c 0,3.653575 2.8812418,6.585017 6.451665,6.585017 h 4.2901096 c 0.358169,0 0.664563,-0.145692 1.006525,-0.202612 v 9.725542 c 0,3.6536 2.864743,6.60193 6.435167,6.60193 h 9.603246 v 3.951 c 0,3.65357 2.86474,6.60192 6.435164,6.60192 h 3.15158 c 3.57042,0 6.451663,-2.94836 6.451663,-6.60192 v -3.95104 h 37.224955 v 3.951 c 0,3.65358 2.86474,6.60193 6.435166,6.60193 h 3.151583 c 3.570418,0 6.451653,-2.94836 6.451653,-6.60193 v -3.951 h 10.725281 c 3.57043,0 6.45166,-2.94833 6.45166,-6.60191 v -9.607372 c 0.14985,0.0105 0.27643,0.0846 0.42899,0.0846 h 4.29014 c 3.5704,0 6.45165,-2.931432 6.45165,-6.585011 v -3.224992 c 0,-3.653565 -2.88125,-6.601906 -6.45165,-6.601906 h -4.29014 c -0.15231,0 -0.27938,0.07348 -0.42899,0.08472 V 45.452198 c 0.14985,0.01042 0.27643,0.08445 0.42899,0.08445 h 4.29014 c 3.5704,0 6.45165,-2.931451 6.45165,-6.585023 v -3.224986 c 0,-3.653566 -2.88125,-6.601906 -6.45165,-6.601906 h -4.29014 c -0.15231,0 -0.27938,0.07392 -0.42899,0.08446 v -7.851429 c 0,-3.653567 -2.88123,-6.585019 -6.45166,-6.585021 H 97.875379 c 0.309043,-0.772641 0.494982,-1.609791 0.494982,-2.498929 V 7.8838054 c 0,-3.6535651 -2.881246,-6.601903 -6.451662,-6.601903 h -3.15158 c -3.570428,0 -6.435167,2.9483379 -6.435167,6.601903 V 12.27382 c 0,0.889115 0.16948,1.726301 0.478507,2.49893 H 44.612011 c 0.309083,-0.772642 0.495011,-1.609792 0.495011,-2.49893 V 7.8838054 c 0,-3.6535651 -2.881243,-6.601903 -6.451663,-6.601903 z" + id="path4542" + inkscape:connector-curvature="0" /> + <path + style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke-width:8.54601765" + d="M 62.861474,21.661698 A 27.707285,31.502779 0 0 1 90.004671,47.07312 18.471523,18.901669 0 0 1 105.96058,65.764449 18.471523,18.901669 0 0 1 87.480108,84.658396 H 38.226348 A 18.471523,18.901669 0 0 1 19.762375,65.764449 18.471523,18.901669 0 0 1 35.685283,47.056234 27.707285,31.502779 0 0 1 62.861474,21.661698 Z" + id="path4540" + inkscape:connector-curvature="0" /> + <path + style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke-width:8.54601765" + d="m 38.226348,90.956369 a 6.1571744,6.3005562 0 0 1 6.154657,6.297979 6.1571744,6.3005562 0 0 1 -6.154657,6.314882 6.1571744,6.3005562 0 0 1 -6.154657,-6.314882 6.1571744,6.3005562 0 0 1 6.154657,-6.297979 z" + id="path4538" + inkscape:connector-curvature="0" /> + <path + style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke-width:8.54601765" + d="m 87.480108,90.956369 a 6.1571744,6.3005562 0 0 1 6.171159,6.297979 6.1571744,6.3005562 0 0 1 -6.171159,6.314882 6.1571744,6.3005562 0 0 1 -6.154656,-6.314882 6.1571744,6.3005562 0 0 1 6.154656,-6.297979 z" + id="path4536" + inkscape:connector-curvature="0" /> + <path + style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke-width:8.54601765" + d="m 62.861474,97.254348 a 6.1571744,6.3005562 0 0 1 6.154662,6.314882 6.1571744,6.3005562 0 0 1 -6.154662,6.29797 6.1571744,6.3005562 0 0 1 -6.154651,-6.29797 6.1571744,6.3005562 0 0 1 6.154651,-6.314882 z" + id="rect822" + inkscape:connector-curvature="0" /> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="Layer 1" + transform="translate(-0.35794507,-5.5049216)" /> +</svg> diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index b5231ce468..4a2295fab2 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -407,8 +407,6 @@ void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asse icon->set_texture(get_icon("DefaultProjectIcon", "EditorIcons")); host = p_download_url; sha256 = p_sha256_hash; - asset_installer->connect("confirmed", this, "_close"); - dismiss->set_normal_texture(get_icon("Close", "EditorIcons")); _make_request(); } @@ -416,9 +414,11 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_READY: { + // FIXME: The editor crashes if 'NOTICATION_THEME_CHANGED' is used. + case NOTIFICATION_ENTER_TREE: { add_style_override("panel", get_stylebox("panel", "TabContainer")); + dismiss->set_normal_texture(get_icon("Close", "EditorIcons")); } break; case NOTIFICATION_PROCESS: { @@ -571,6 +571,7 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { asset_installer = memnew(EditorAssetInstaller); add_child(asset_installer); + asset_installer->connect("confirmed", this, "_close"); prev_status = -1; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 16cc9978ee..ec391186c3 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -56,7 +56,7 @@ void ScriptEditorBase::_bind_methods() { ADD_SIGNAL(MethodInfo("request_open_script_at_line", PropertyInfo(Variant::OBJECT, "script"), PropertyInfo(Variant::INT, "line"))); ADD_SIGNAL(MethodInfo("request_save_history")); ADD_SIGNAL(MethodInfo("go_to_help", PropertyInfo(Variant::STRING, "what"))); - // TODO This signal is no use for VisualScript... + // TODO: This signal is no use for VisualScript. ADD_SIGNAL(MethodInfo("search_in_files_requested", PropertyInfo(Variant::STRING, "text"))); } @@ -205,11 +205,13 @@ void ScriptEditorQuickOpen::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - connect("confirmed", this, "_confirmed"); - search_box->set_right_icon(get_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); + FALLTHROUGH; + } + case NOTIFICATION_THEME_CHANGED: { + search_box->set_right_icon(get_icon("Search", "EditorIcons")); } break; case NOTIFICATION_EXIT_TREE: { disconnect("confirmed", this, "_confirmed"); @@ -242,6 +244,8 @@ ScriptEditorQuickOpen::ScriptEditorQuickOpen() { set_hide_on_ok(false); search_options->connect("item_activated", this, "_confirmed"); search_options->set_hide_root(true); + search_options->set_hide_folding(true); + search_options->add_constant_override("draw_guides", 1); } ///////////////////////////////// @@ -1420,15 +1424,25 @@ void ScriptEditor::_notification(int p_what) { } EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed"); + FALLTHROUGH; + } + case NOTIFICATION_THEME_CHANGED: { + help_search->set_icon(get_icon("HelpSearch", "EditorIcons")); site_search->set_icon(get_icon("Instance", "EditorIcons")); request_docs->set_icon(get_icon("Issue", "EditorIcons")); script_forward->set_icon(get_icon("Forward", "EditorIcons")); script_back->set_icon(get_icon("Back", "EditorIcons")); + members_overview_alphabeta_sort_button->set_icon(get_icon("Sort", "EditorIcons")); + filter_scripts->set_right_icon(get_icon("Search", "EditorIcons")); filter_methods->set_right_icon(get_icon("Search", "EditorIcons")); + + filename->add_style_override("normal", editor->get_gui_base()->get_stylebox("normal", "LineEdit")); + + recent_scripts->set_as_minsize(); } break; case NOTIFICATION_READY: { @@ -1451,20 +1465,6 @@ void ScriptEditor::_notification(int p_what) { _update_modified_scripts_for_external_editor(); } break; - case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - - help_search->set_icon(get_icon("HelpSearch", "EditorIcons")); - site_search->set_icon(get_icon("Instance", "EditorIcons")); - - script_forward->set_icon(get_icon("Forward", "EditorIcons")); - script_back->set_icon(get_icon("Back", "EditorIcons")); - - members_overview_alphabeta_sort_button->set_icon(get_icon("Sort", "EditorIcons")); - filename->add_style_override("normal", editor->get_gui_base()->get_stylebox("normal", "LineEdit")); - - recent_scripts->set_as_minsize(); - } break; - case CanvasItem::NOTIFICATION_VISIBILITY_CHANGED: { if (is_visible()) { diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 07303da2ff..284e0b3d97 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1572,7 +1572,9 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (has_color) { String line = tx->get_line(row); - color_line = row; + color_position.x = row; + color_position.y = col; + int begin = 0; int end = 0; bool valid = false; @@ -1612,10 +1614,15 @@ void ScriptTextEditor::_color_changed(const Color &p_color) { new_args = String("(" + rtos(p_color.r) + ", " + rtos(p_color.g) + ", " + rtos(p_color.b) + ", " + rtos(p_color.a) + ")"); } - String line = code_editor->get_text_edit()->get_line(color_line); - String new_line = line.replace(color_args, new_args); + String line = code_editor->get_text_edit()->get_line(color_position.x); + int color_args_pos = line.find(color_args, color_position.y); + String line_with_replaced_args = line; + line_with_replaced_args.erase(color_args_pos, color_args.length()); + line_with_replaced_args = line_with_replaced_args.insert(color_args_pos, new_args); + color_args = new_args; - code_editor->get_text_edit()->set_line(color_line, new_line); + code_editor->get_text_edit()->set_line(color_position.x, line_with_replaced_args); + code_editor->get_text_edit()->update(); } void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition) { @@ -1710,6 +1717,7 @@ ScriptTextEditor::ScriptTextEditor() { color_panel = memnew(PopupPanel); add_child(color_panel); color_picker = memnew(ColorPicker); + color_picker->set_deferred_mode(true); color_panel->add_child(color_picker); color_picker->connect("color_changed", this, "_color_changed"); @@ -1776,11 +1784,7 @@ ScriptTextEditor::ScriptTextEditor() { search_menu->get_popup()->add_separator(); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_in_files"), SEARCH_IN_FILES); search_menu->get_popup()->add_separator(); - search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_function"), SEARCH_LOCATE_FUNCTION); - search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE); - search_menu->get_popup()->add_separator(); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/contextual_help"), HELP_CONTEXTUAL); - search_menu->get_popup()->connect("id_pressed", this, "_edit_option"); edit_hb->add_child(edit_menu); @@ -1789,6 +1793,11 @@ ScriptTextEditor::ScriptTextEditor() { edit_hb->add_child(goto_menu); goto_menu->set_text(TTR("Go To")); goto_menu->set_switch_on_hover(true); + goto_menu->get_popup()->connect("id_pressed", this, "_edit_option"); + + goto_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_function"), SEARCH_LOCATE_FUNCTION); + goto_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE); + goto_menu->get_popup()->add_separator(); bookmarks_menu = memnew(PopupMenu); bookmarks_menu->set_name("Bookmarks"); @@ -1848,16 +1857,12 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KEY_MASK_ALT | KEY_DOWN); ED_SHORTCUT("script_text_editor/delete_line", TTR("Delete Line"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_K); - //leave these at zero, same can be accomplished with tab/shift-tab, including selection - //the next/previous in history shortcut in this case makes a lot more sene. + // Leave these at zero, same can be accomplished with tab/shift-tab, including selection. + // The next/previous in history shortcut in this case makes a lot more sense. ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), 0); ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), 0); ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD | KEY_K); - ED_SHORTCUT("script_text_editor/toggle_bookmark", TTR("Toggle Bookmark"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_B); - ED_SHORTCUT("script_text_editor/goto_next_bookmark", TTR("Go to Next Bookmark"), KEY_MASK_CMD | KEY_B); - ED_SHORTCUT("script_text_editor/goto_previous_bookmark", TTR("Go to Previous Bookmark"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B); - ED_SHORTCUT("script_text_editor/remove_all_bookmarks", TTR("Remove All Bookmarks"), 0); ED_SHORTCUT("script_text_editor/toggle_fold_line", TTR("Fold/Unfold Line"), KEY_MASK_ALT | KEY_F); ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), 0); ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0); @@ -1873,15 +1878,6 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent to Tabs"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_I); ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD | KEY_I); -#ifdef OSX_ENABLED - ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B); -#else - ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9); -#endif - ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F9); - ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Go to Next Breakpoint"), KEY_MASK_CMD | KEY_PERIOD); - ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Go to Previous Breakpoint"), KEY_MASK_CMD | KEY_COMMA); - ED_SHORTCUT("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F); #ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_MASK_CMD | KEY_G); @@ -1896,6 +1892,17 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F); #ifdef OSX_ENABLED + ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE); +#else + ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_ALT | KEY_F1); +#endif + + ED_SHORTCUT("script_text_editor/toggle_bookmark", TTR("Toggle Bookmark"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_B); + ED_SHORTCUT("script_text_editor/goto_next_bookmark", TTR("Go to Next Bookmark"), KEY_MASK_CMD | KEY_B); + ED_SHORTCUT("script_text_editor/goto_previous_bookmark", TTR("Go to Previous Bookmark"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B); + ED_SHORTCUT("script_text_editor/remove_all_bookmarks", TTR("Remove All Bookmarks"), 0); + +#ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KEY_MASK_CTRL | KEY_MASK_CMD | KEY_J); #else ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); @@ -1903,10 +1910,13 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/goto_line", TTR("Go to Line..."), KEY_MASK_CMD | KEY_L); #ifdef OSX_ENABLED - ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE); + ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B); #else - ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_ALT | KEY_F1); + ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9); #endif + ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F9); + ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Go to Next Breakpoint"), KEY_MASK_CMD | KEY_PERIOD); + ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Go to Previous Breakpoint"), KEY_MASK_CMD | KEY_COMMA); ScriptEditor::register_create_script_editor_function(create_editor); } diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index 4dbade472c..4b2307555b 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -81,7 +81,7 @@ class ScriptTextEditor : public ScriptEditorBase { PopupPanel *color_panel; ColorPicker *color_picker; - int color_line; + Vector2 color_position; String color_args; void _update_member_keywords(); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 37460c58ff..04820b8a8f 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -529,19 +529,19 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { void ShaderEditor::_update_bookmark_list() { - bookmarks_menu->get_popup()->clear(); + bookmarks_menu->clear(); - bookmarks_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_bookmark"), BOOKMARK_TOGGLE); - bookmarks_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/remove_all_bookmarks"), BOOKMARK_REMOVE_ALL); - bookmarks_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT); - bookmarks_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV); + bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_bookmark"), BOOKMARK_TOGGLE); + bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/remove_all_bookmarks"), BOOKMARK_REMOVE_ALL); + bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT); + bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV); Array bookmark_list = shader_editor->get_text_edit()->get_bookmarks_array(); if (bookmark_list.size() == 0) { return; } - bookmarks_menu->get_popup()->add_separator(); + bookmarks_menu->add_separator(); for (int i = 0; i < bookmark_list.size(); i++) { String line = shader_editor->get_text_edit()->get_line(bookmark_list[i]).strip_edges(); @@ -550,17 +550,17 @@ void ShaderEditor::_update_bookmark_list() { line = line.substr(0, 50); } - bookmarks_menu->get_popup()->add_item(String::num((int)bookmark_list[i] + 1) + " - \"" + line + "\""); - bookmarks_menu->get_popup()->set_item_metadata(bookmarks_menu->get_popup()->get_item_count() - 1, bookmark_list[i]); + bookmarks_menu->add_item(String::num((int)bookmark_list[i] + 1) + " - \"" + line + "\""); + bookmarks_menu->set_item_metadata(bookmarks_menu->get_item_count() - 1, bookmark_list[i]); } } void ShaderEditor::_bookmark_item_pressed(int p_idx) { if (p_idx < 4) { // Any item before the separator. - _menu_option(bookmarks_menu->get_popup()->get_item_id(p_idx)); + _menu_option(bookmarks_menu->get_item_id(p_idx)); } else { - shader_editor->goto_line(bookmarks_menu->get_popup()->get_item_metadata(p_idx)); + shader_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx)); } } @@ -649,16 +649,23 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace"), SEARCH_REPLACE); - search_menu->get_popup()->add_separator(); - search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE); search_menu->get_popup()->connect("id_pressed", this, "_menu_option"); - bookmarks_menu = memnew(MenuButton); - bookmarks_menu->set_text(TTR("Bookmarks")); - bookmarks_menu->set_switch_on_hover(true); + MenuButton *goto_menu = memnew(MenuButton); + goto_menu->set_text(TTR("Go To")); + goto_menu->set_switch_on_hover(true); + goto_menu->get_popup()->connect("id_pressed", this, "_menu_option"); + + goto_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE); + goto_menu->get_popup()->add_separator(); + + bookmarks_menu = memnew(PopupMenu); + bookmarks_menu->set_name("Bookmarks"); + goto_menu->get_popup()->add_child(bookmarks_menu); + goto_menu->get_popup()->add_submenu_item(TTR("Bookmarks"), "Bookmarks"); _update_bookmark_list(); bookmarks_menu->connect("about_to_show", this, "_update_bookmark_list"); - bookmarks_menu->get_popup()->connect("index_pressed", this, "_bookmark_item_pressed"); + bookmarks_menu->connect("index_pressed", this, "_bookmark_item_pressed"); help_menu = memnew(MenuButton); help_menu->set_text(TTR("Help")); @@ -670,7 +677,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { main_container->add_child(hbc); hbc->add_child(search_menu); hbc->add_child(edit_menu); - hbc->add_child(bookmarks_menu); + hbc->add_child(goto_menu); hbc->add_child(help_menu); hbc->add_style_override("panel", p_node->get_gui_base()->get_stylebox("ScriptEditorPanel", "EditorStyles")); main_container->add_child(shader_editor); diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 5d03c37dc4..8d3f4d4fe8 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -99,7 +99,7 @@ class ShaderEditor : public PanelContainer { MenuButton *edit_menu; MenuButton *search_menu; - MenuButton *bookmarks_menu; + PopupMenu *bookmarks_menu; MenuButton *help_menu; PopupMenu *context_menu; uint64_t idle; diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index d2b1cfc5af..58234ba954 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -5438,6 +5438,7 @@ void SpatialEditor::_register_all_gizmos() { add_gizmo_plugin(Ref<VehicleWheelSpatialGizmoPlugin>(memnew(VehicleWheelSpatialGizmoPlugin))); add_gizmo_plugin(Ref<VisibilityNotifierGizmoPlugin>(memnew(VisibilityNotifierGizmoPlugin))); add_gizmo_plugin(Ref<ParticlesGizmoPlugin>(memnew(ParticlesGizmoPlugin))); + add_gizmo_plugin(Ref<CPUParticlesGizmoPlugin>(memnew(CPUParticlesGizmoPlugin))); add_gizmo_plugin(Ref<ReflectionProbeGizmoPlugin>(memnew(ReflectionProbeGizmoPlugin))); add_gizmo_plugin(Ref<GIProbeGizmoPlugin>(memnew(GIProbeGizmoPlugin))); add_gizmo_plugin(Ref<BakedIndirectLightGizmoPlugin>(memnew(BakedIndirectLightGizmoPlugin))); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index dc22507f39..863cf75a93 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -211,6 +211,9 @@ void VisualShaderEditor::_update_options_menu() { if (!use_filter || add_options[i].name.findn(filter) != -1) { + if ((add_options[i].func != current_func && add_options[i].func != -1) || !_is_available(add_options[i].mode)) + continue; + if (prev_category != add_options[i].category) { if (category != NULL && item_count == 0) { memdelete(category); @@ -241,73 +244,53 @@ void VisualShaderEditor::_update_options_menu() { sub_category->set_collapsed(true); } } - if (sub_category != NULL) { - if ((add_options[i].func == current_func || add_options[i].func == -1) && _is_available(add_options[i].mode)) { - ++item_count2; - TreeItem *item = members->create_item(sub_category); - if (add_options[i].highend && low_driver) - item->set_custom_color(0, unsupported_color); - else if (add_options[i].highend) - item->set_custom_color(0, supported_color); - item->set_text(0, add_options[i].name); - if (is_first_item) { - item->select(0); - is_first_item = false; - } - switch (add_options[i].return_type) { - case VisualShaderNode::PORT_TYPE_SCALAR: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons")); - break; - case VisualShaderNode::PORT_TYPE_VECTOR: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons")); - break; - case VisualShaderNode::PORT_TYPE_BOOLEAN: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons")); - break; - case VisualShaderNode::PORT_TYPE_TRANSFORM: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons")); - break; - case VisualShaderNode::PORT_TYPE_COLOR: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Color", "EditorIcons")); - break; - default: - break; - } - item->set_meta("id", i); - } - } } else { - if (category != NULL) { - if ((add_options[i].func == current_func || add_options[i].func == -1) && _is_available(add_options[i].mode)) { - ++item_count; - TreeItem *item = members->create_item(category); - if (add_options[i].highend && low_driver) - item->set_custom_color(0, unsupported_color); - else if (add_options[i].highend) - item->set_custom_color(0, supported_color); - item->set_text(0, add_options[i].name); - switch (add_options[i].return_type) { - case VisualShaderNode::PORT_TYPE_SCALAR: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons")); - break; - case VisualShaderNode::PORT_TYPE_VECTOR: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons")); - break; - case VisualShaderNode::PORT_TYPE_BOOLEAN: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons")); - break; - case VisualShaderNode::PORT_TYPE_TRANSFORM: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons")); - break; - case VisualShaderNode::PORT_TYPE_COLOR: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Color", "EditorIcons")); - break; - default: - break; - } - item->set_meta("id", i); + sub_category = NULL; + } + + TreeItem *p_category = NULL; + + if (sub_category != NULL) { + p_category = sub_category; + ++item_count2; + } else if (category != NULL) { + p_category = category; + ++item_count; + } + + if (p_category != NULL) { + TreeItem *item = members->create_item(p_category); + if (add_options[i].highend && low_driver) + item->set_custom_color(0, unsupported_color); + 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; } } + switch (add_options[i].return_type) { + case VisualShaderNode::PORT_TYPE_SCALAR: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_VECTOR: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_TRANSFORM: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_COLOR: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Color", "EditorIcons")); + break; + default: + break; + } + item->set_meta("id", i); } prev_sub_category = add_options[i].sub_category; diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index dc2f098333..4e1c900ee4 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -256,16 +256,16 @@ void EditorQuickOpen::_confirmed() { void EditorQuickOpen::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - connect("confirmed", this, "_confirmed"); - search_box->set_right_icon(get_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); + FALLTHROUGH; + } + case NOTIFICATION_THEME_CHANGED: { + search_box->set_right_icon(get_icon("Search", "EditorIcons")); } break; case NOTIFICATION_EXIT_TREE: { - disconnect("confirmed", this, "_confirmed"); } break; } @@ -289,7 +289,6 @@ EditorQuickOpen::EditorQuickOpen() { VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); - //set_child_rect(vbc); search_box = memnew(LineEdit); vbc->add_margin_child(TTR("Search:"), search_box); search_box->connect("text_changed", this, "_text_changed"); @@ -302,6 +301,7 @@ EditorQuickOpen::EditorQuickOpen() { set_hide_on_ok(false); search_options->connect("item_activated", this, "_confirmed"); search_options->set_hide_root(true); + search_options->set_hide_folding(true); search_options->add_constant_override("draw_guides", 1); ei = "EditorIcons"; ot = "Object"; diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index cbfd0f3742..f7ba5e5e3c 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -36,6 +36,7 @@ #include "scene/3d/baked_lightmap.h" #include "scene/3d/collision_polygon.h" #include "scene/3d/collision_shape.h" +#include "scene/3d/cpu_particles.h" #include "scene/3d/gi_probe.h" #include "scene/3d/light.h" #include "scene/3d/listener.h" @@ -2415,6 +2416,33 @@ void VisibilityNotifierGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { //// +CPUParticlesGizmoPlugin::CPUParticlesGizmoPlugin() { + create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_icon("GizmoCPUParticles", "EditorIcons")); +} + +bool CPUParticlesGizmoPlugin::has_gizmo(Spatial *p_spatial) { + return Object::cast_to<CPUParticles>(p_spatial) != NULL; +} + +String CPUParticlesGizmoPlugin::get_name() const { + return "CPUParticles"; +} + +int CPUParticlesGizmoPlugin::get_priority() const { + return -1; +} + +bool CPUParticlesGizmoPlugin::is_selectable_when_hidden() const { + return true; +} + +void CPUParticlesGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + Ref<Material> icon = get_material("particles_icon", p_gizmo); + p_gizmo->add_unscaled_billboard(icon, 0.05); +} + +//// + ParticlesGizmoPlugin::ParticlesGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particles", Color(0.8, 0.7, 0.4)); create_material("particles_material", gizmo_color); diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index 3661df4bad..317ea0c570 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -249,6 +249,18 @@ public: VisibilityNotifierGizmoPlugin(); }; +class CPUParticlesGizmoPlugin : public EditorSpatialGizmoPlugin { + GDCLASS(CPUParticlesGizmoPlugin, EditorSpatialGizmoPlugin); + +public: + bool has_gizmo(Spatial *p_spatial); + String get_name() const; + int get_priority() const; + bool is_selectable_when_hidden() const; + void redraw(EditorSpatialGizmo *p_gizmo); + CPUParticlesGizmoPlugin(); +}; + class ParticlesGizmoPlugin : public EditorSpatialGizmoPlugin { GDCLASS(ParticlesGizmoPlugin, EditorSpatialGizmoPlugin); diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 1303c43944..9a25e788c7 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -898,6 +898,10 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } else if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_IS && tokenizer->get_token(1) == GDScriptTokenizer::TK_BUILT_IN_TYPE) { // 'is' operator with built-in type + if (!expr) { + _set_error("Expected identifier before 'is' operator"); + return NULL; + } OperatorNode *op = alloc_node<OperatorNode>(); op->op = OperatorNode::OP_IS_BUILTIN; op->arguments.push_back(expr); diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index f8d201b4ca..8c17bac3c9 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -115,7 +115,7 @@ void CSharpLanguage::init() { gdmono->initialize(); #if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) - // Generate bindings here, before loading assemblies. `initialize_load_assemblies` aborts + // Generate bindings here, before loading assemblies. 'initialize_load_assemblies' aborts // the applications if the api assemblies or the main tools assembly is missing, but this // is not a problem for BindingsGenerator as it only needs the tools project editor assembly. List<String> cmdline_args = OS::get_singleton()->get_cmdline_args(); @@ -123,7 +123,7 @@ void CSharpLanguage::init() { #endif #ifndef MONO_GLUE_ENABLED - print_line("Run this binary with `--generate-mono-glue path/to/modules/mono/glue`"); + print_line("Run this binary with '--generate-mono-glue path/to/modules/mono/glue'"); #endif gdmono->initialize_load_assemblies(); @@ -1036,6 +1036,7 @@ void CSharpLanguage::_load_scripts_metadata() { String old_json; Error ferr = read_all_file_utf8(scripts_metadata_path, old_json); + ERR_FAIL_COND(ferr != OK); Variant old_dict_var; @@ -1043,7 +1044,7 @@ void CSharpLanguage::_load_scripts_metadata() { int err_line; Error json_err = JSON::parse(old_json, old_dict_var, err_str, err_line); if (json_err != OK) { - ERR_PRINTS("Failed to parse metadata file: '" + err_str + "' (" + String::num_int64(err_line) + ")"); + ERR_PRINTS("Failed to parse metadata file: '" + err_str + "' (" + String::num_int64(err_line) + ")."); return; } @@ -1053,7 +1054,7 @@ void CSharpLanguage::_load_scripts_metadata() { print_verbose("Successfully loaded scripts metadata"); } else { if (!Engine::get_singleton()->is_editor_hint()) { - ERR_PRINT("Missing scripts metadata file"); + ERR_PRINT("Missing scripts metadata file."); } } } @@ -1768,12 +1769,8 @@ MonoObject *CSharpInstance::_internal_new_managed() { // Search the constructor first, to fail with an error if it's not found before allocating anything else. GDMonoMethod *ctor = script->script_class->get_method(CACHED_STRING_NAME(dotctor), 0); - if (ctor == NULL) { - ERR_PRINTS("Cannot create script instance because the class does not define a parameterless constructor: " + script->get_path()); - - ERR_EXPLAIN("Constructor not found"); - ERR_FAIL_V(NULL); - } + ERR_FAIL_NULL_V_MSG(ctor, NULL, + "Cannot create script instance because the class does not define a parameterless constructor: '" + script->get_path() + "'."); CSharpLanguage::get_singleton()->release_script_gchandle(gchandle); @@ -1792,8 +1789,7 @@ MonoObject *CSharpInstance::_internal_new_managed() { owner = NULL; - ERR_EXPLAIN("Failed to allocate memory for the object"); - ERR_FAIL_V(NULL); + ERR_FAIL_V_MSG(NULL, "Failed to allocate memory for the object."); } // Tie managed to unmanaged @@ -2233,7 +2229,7 @@ bool CSharpScript::_update_exports() { MonoObject *tmp_object = mono_object_new(mono_domain_get(), script_class->get_mono_ptr()); if (!tmp_object) { - ERR_PRINT("Failed to allocate temporary MonoObject"); + ERR_PRINT("Failed to allocate temporary MonoObject."); return false; } @@ -2241,12 +2237,8 @@ bool CSharpScript::_update_exports() { GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0); - if (ctor == NULL) { - ERR_PRINTS("Cannot construct temporary MonoObject because the class does not define a parameterless constructor: " + get_path()); - - ERR_EXPLAIN("Constructor not found"); - ERR_FAIL_V(NULL); - } + ERR_FAIL_NULL_V_MSG(ctor, NULL, + "Cannot construct temporary MonoObject because the class does not define a parameterless constructor: '" + get_path() + "'."); MonoException *ctor_exc = NULL; ctor->invoke(tmp_object, NULL, &ctor_exc); @@ -2399,7 +2391,7 @@ bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Ve arg.type = GDMonoMarshal::managed_to_variant_type(types[i]); if (arg.type == Variant::NIL) { - ERR_PRINTS("Unknown type of signal parameter: " + arg.name + " in " + p_class->get_full_name()); + ERR_PRINTS("Unknown type of signal parameter: '" + arg.name + "' in '" + p_class->get_full_name() + "'."); return false; } @@ -2427,7 +2419,7 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect if (p_member->is_static()) { if (p_member->has_attribute(CACHED_CLASS(ExportAttribute))) - ERR_PRINTS("Cannot export member because it is static: " + MEMBER_FULL_QUALIFIED_NAME(p_member)); + ERR_PRINTS("Cannot export member because it is static: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); return false; } @@ -2450,12 +2442,12 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect GDMonoProperty *property = static_cast<GDMonoProperty *>(p_member); if (!property->has_getter()) { if (exported) - ERR_PRINTS("Read-only property cannot be exported: " + MEMBER_FULL_QUALIFIED_NAME(p_member)); + ERR_PRINTS("Read-only property cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); return false; } if (!property->has_setter()) { if (exported) - ERR_PRINTS("Write-only property (without getter) cannot be exported: " + MEMBER_FULL_QUALIFIED_NAME(p_member)); + ERR_PRINTS("Write-only property (without getter) cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); return false; } } @@ -2474,16 +2466,15 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect String hint_string; if (variant_type == Variant::NIL) { - ERR_PRINTS("Unknown exported member type: " + MEMBER_FULL_QUALIFIED_NAME(p_member)); + ERR_PRINTS("Unknown exported member type: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); return false; } int hint_res = _try_get_member_export_hint(p_member, type, variant_type, /* allow_generics: */ true, hint, hint_string); - if (hint_res == -1) { - ERR_EXPLAIN("Error while trying to determine information about the exported member: " + MEMBER_FULL_QUALIFIED_NAME(p_member)); - ERR_FAIL_V(false); - } + ERR_FAIL_COND_V_MSG(hint_res == -1, false, + "Error while trying to determine information about the exported member: '" + + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); if (hint_res == 0) { hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)); @@ -2532,17 +2523,11 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage MonoObject *val_obj = mono_field_get_value_object(mono_domain_get(), field, NULL); - if (val_obj == NULL) { - ERR_EXPLAIN("Failed to get '" + enum_field_name + "' constant enum value"); - ERR_FAIL_V(-1); - } + ERR_FAIL_NULL_V_MSG(val_obj, -1, "Failed to get '" + enum_field_name + "' constant enum value."); bool r_error; uint64_t val = GDMonoUtils::unbox_enum_value(val_obj, enum_basetype, r_error); - if (r_error) { - ERR_EXPLAIN("Failed to unbox '" + enum_field_name + "' constant enum value"); - ERR_FAIL_V(-1); - } + ERR_FAIL_COND_V_MSG(r_error, -1, "Failed to unbox '" + enum_field_name + "' constant enum value."); if (val != (unsigned int)i) { uses_default_values = false; @@ -2577,17 +2562,11 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage PropertyHint elem_hint = PROPERTY_HINT_NONE; String elem_hint_string; - if (elem_variant_type == Variant::NIL) { - ERR_EXPLAIN("Unknown array element type"); - ERR_FAIL_V(-1); - } + ERR_FAIL_COND_V_MSG(elem_variant_type == Variant::NIL, -1, "Unknown array element type."); int hint_res = _try_get_member_export_hint(p_member, elem_type, elem_variant_type, /* allow_generics: */ false, elem_hint, elem_hint_string); - if (hint_res == -1) { - ERR_EXPLAIN("Error while trying to determine information about the array element type"); - ERR_FAIL_V(-1); - } + ERR_FAIL_COND_V_MSG(hint_res == -1, -1, "Error while trying to determine information about the array element type."); // Format: type/hint:hint_string r_hint_string = itos(elem_variant_type) + "/" + itos(elem_hint) + ":" + elem_hint_string; @@ -2775,7 +2754,7 @@ bool CSharpScript::can_instance() const { "Compile", ProjectSettings::get_singleton()->globalize_path(get_path())); } else { - ERR_PRINTS("Cannot add " + get_path() + " to the C# project because it could not be created."); + ERR_PRINTS("C# project could not be created; cannot add file: '" + get_path() + "'."); } } } @@ -2793,12 +2772,10 @@ bool CSharpScript::can_instance() const { if (extra_cond && !script_class) { if (GDMono::get_singleton()->get_project_assembly() == NULL) { // The project assembly is not loaded - ERR_EXPLAIN("Cannot instance script because the project assembly is not loaded. Script: " + get_path()); - ERR_FAIL_V(NULL); + ERR_FAIL_V_MSG(NULL, "Cannot instance script because the project assembly is not loaded. Script: '" + get_path() + "'."); } else { // The project assembly is loaded, but the class could not found - ERR_EXPLAIN("Cannot instance script because the class '" + name + "' could not be found. Script: " + get_path()); - ERR_FAIL_V(NULL); + ERR_FAIL_V_MSG(NULL, "Cannot instance script because the class '" + name + "' could not be found. Script: '" + get_path() + "'."); } } @@ -2820,14 +2797,12 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg // Search the constructor first, to fail with an error if it's not found before allocating anything else. GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), p_argcount); if (ctor == NULL) { - if (p_argcount == 0) { - String path = get_path(); - ERR_PRINTS("Cannot create script instance. The class '" + script_class->get_full_name() + - "' does not define a parameterless constructor." + (path.empty() ? String() : ". Path: " + path)); - } + ERR_FAIL_COND_V_MSG(p_argcount == 0, NULL, + "Cannot create script instance. The class '" + script_class->get_full_name() + + "' does not define a parameterless constructor." + + (get_path().empty() ? String() : " Path: '" + get_path() + "'.")); - ERR_EXPLAIN("Constructor not found"); - ERR_FAIL_V(NULL); + ERR_FAIL_V_MSG(NULL, "Constructor not found."); } Ref<Reference> ref; @@ -2878,8 +2853,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg p_owner->set_script_instance(NULL); r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL; - ERR_EXPLAIN("Failed to allocate memory for the object"); - ERR_FAIL_V(NULL); + ERR_FAIL_V_MSG(NULL, "Failed to allocate memory for the object."); } // Tie managed to unmanaged @@ -2950,8 +2924,8 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) { if (ScriptDebugger::get_singleton()) { CSharpLanguage::get_singleton()->debug_break_parse(get_path(), 0, "Script inherits from native type '" + native_name + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'"); } - ERR_EXPLAIN("Script inherits from native type '" + native_name + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'"); - ERR_FAIL_V(NULL); + ERR_FAIL_V_MSG(NULL, "Script inherits from native type '" + native_name + + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'."); } } @@ -3203,12 +3177,12 @@ int CSharpScript::get_member_line(const StringName &p_member) const { Error CSharpScript::load_source_code(const String &p_path) { Error ferr = read_all_file_utf8(p_path, source); - if (ferr != OK) { - if (ferr == ERR_INVALID_DATA) { - ERR_EXPLAIN("Script '" + p_path + "' contains invalid unicode (utf-8), so it was not loaded. Please ensure that scripts are saved in valid utf-8 unicode."); - } - ERR_FAIL_V(ferr); - } + + ERR_FAIL_COND_V_MSG(ferr != OK, ferr, + ferr == ERR_INVALID_DATA ? + "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded." + " Please ensure that scripts are saved in valid UTF-8 unicode." : + "Failed to read file: '" + p_path + "'."); #ifdef TOOLS_ENABLED source_changed_cache = true; @@ -3277,8 +3251,7 @@ RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p #ifdef DEBUG_ENABLED // User is responsible for thread attach/detach - ERR_EXPLAIN("Thread is not attached"); - CRASH_COND(mono_domain_get() == NULL); + CRASH_COND_MSG(mono_domain_get() == NULL, "Thread is not attached."); #endif #endif @@ -3345,8 +3318,7 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r "Compile", ProjectSettings::get_singleton()->globalize_path(p_path)); } else { - ERR_PRINTS("Failed to create C# project"); - ERR_PRINTS("Cannot add " + p_path + " to the C# project"); + ERR_PRINTS("C# project could not be created; cannot add file: '" + p_path + "'."); } } #endif diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 45037bf637..1888bb3cb9 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -279,7 +279,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf Vector<String> link_target_parts = link_target.split("."); if (link_target_parts.size() <= 0 || link_target_parts.size() > 2) { - ERR_PRINTS("Invalid reference format: " + tag); + ERR_PRINTS("Invalid reference format: '" + tag + "'."); xml_output.append("<c>"); xml_output.append(tag); @@ -375,7 +375,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append(target_enum_itype.proxy_name); // Includes nesting class if any xml_output.append("\"/>"); } else { - ERR_PRINTS("Cannot resolve enum reference in documentation: " + link_target); + ERR_PRINTS("Cannot resolve enum reference in documentation: '" + link_target + "'."); xml_output.append("<c>"); xml_output.append(link_target); @@ -424,7 +424,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append(target_iconst->proxy_name); xml_output.append("\"/>"); } else { - ERR_PRINTS("Cannot resolve global constant reference in documentation: " + link_target); + ERR_PRINTS("Cannot resolve global constant reference in documentation: '" + link_target + "'."); xml_output.append("<c>"); xml_output.append(link_target); @@ -464,7 +464,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append(target_iconst->proxy_name); xml_output.append("\"/>"); } else { - ERR_PRINTS("Cannot resolve constant reference in documentation: " + link_target); + ERR_PRINTS("Cannot resolve constant reference in documentation: '" + link_target + "'."); xml_output.append("<c>"); xml_output.append(link_target); @@ -534,7 +534,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append(target_itype->proxy_name); xml_output.append("\"/>"); } else { - ERR_PRINTS("Cannot resolve type reference in documentation: " + tag); + ERR_PRINTS("Cannot resolve type reference in documentation: '" + tag + "'."); xml_output.append("<c>"); xml_output.append(tag); @@ -812,7 +812,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { CRASH_COND(enum_class_name != "Variant"); // Hard-coded... - _log("Declaring global enum `%s` inside static class `%s`\n", enum_proxy_name.utf8().get_data(), enum_class_name.utf8().get_data()); + _log("Declaring global enum '%s' inside static class '%s'\n", enum_proxy_name.utf8().get_data(), enum_class_name.utf8().get_data()); p_output.append("\n" INDENT1 "public static partial class "); p_output.append(enum_class_name); @@ -1083,7 +1083,7 @@ Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { proj_err = generate_cs_core_project(core_proj_dir, core_compile_items); if (proj_err != OK) { - ERR_PRINT("Generation of the Core API C# project failed"); + ERR_PRINT("Generation of the Core API C# project failed."); return proj_err; } @@ -1094,7 +1094,7 @@ Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { proj_err = generate_cs_editor_project(editor_proj_dir, editor_compile_items); if (proj_err != OK) { - ERR_PRINT("Generation of the Editor API C# project failed"); + ERR_PRINT("Generation of the Editor API C# project failed."); return proj_err; } @@ -1112,7 +1112,7 @@ Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { // FIXME: There are some members that hide other inherited members. // - In the case of both members being the same kind, the new one must be declared -// explicitly as `new` to avoid the warning (and we must print a message about it). +// explicitly as 'new' to avoid the warning (and we must print a message about it). // - In the case of both members being of a different kind, then the new one must // be renamed to avoid the name collision (and we must print a warning about it). // - Csc warning e.g.: @@ -1186,7 +1186,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.append(obj_types[itype.base_name].proxy_name); output.append("\n"); } else { - ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name); + ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class '" + itype.name + "'."); return ERR_INVALID_DATA; } } @@ -1273,11 +1273,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) { const PropertyInterface &iprop = E->get(); Error prop_err = _generate_cs_property(itype, iprop, output); - if (prop_err != OK) { - ERR_EXPLAIN("Failed to generate property '" + iprop.cname.operator String() + - "' for class '" + itype.name + "'"); - ERR_FAIL_V(prop_err); - } + ERR_FAIL_COND_V_MSG(prop_err != OK, prop_err, + "Failed to generate property '" + iprop.cname.operator String() + + "' for class '" + itype.name + "'."); } } @@ -1340,10 +1338,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) { const MethodInterface &imethod = E->get(); Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output); - if (method_err != OK) { - ERR_EXPLAIN("Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'"); - ERR_FAIL_V(method_err); - } + ERR_FAIL_COND_V_MSG(method_err != OK, method_err, + "Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'."); } if (itype.is_singleton) { @@ -1626,7 +1622,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf if (p_imethod.is_deprecated) { if (p_imethod.deprecation_message.empty()) - WARN_PRINTS("An empty deprecation message is discouraged. Method: " + p_imethod.proxy_name); + WARN_PRINTS("An empty deprecation message is discouraged. Method: '" + p_imethod.proxy_name + "'."); p_output.append(MEMBER_BEGIN "[Obsolete(\""); p_output.append(p_imethod.deprecation_message); @@ -1708,8 +1704,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf Error BindingsGenerator::generate_glue(const String &p_output_dir) { bool dir_exists = DirAccess::exists(p_output_dir); - ERR_EXPLAIN("The output directory does not exist."); - ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH); + ERR_FAIL_COND_V_MSG(!dir_exists, ERR_FILE_BAD_PATH, "The output directory does not exist."); StringBuilder output; @@ -1742,10 +1737,8 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) { const MethodInterface &imethod = E->get(); Error method_err = _generate_glue_method(itype, imethod, output); - if (method_err != OK) { - ERR_EXPLAIN("Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'"); - ERR_FAIL_V(method_err); - } + ERR_FAIL_COND_V_MSG(method_err != OK, method_err, + "Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'."); } if (itype.is_singleton) { @@ -1879,8 +1872,7 @@ Error BindingsGenerator::_save_file(const String &p_path, const StringBuilder &p FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE); - ERR_EXPLAIN("Cannot open file: " + p_path); - ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE); + ERR_FAIL_COND_V_MSG(!file, ERR_FILE_CANT_WRITE, "Cannot open file: '" + p_path + "'."); file->store_string(p_content.as_string()); file->close(); @@ -2091,7 +2083,7 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placehol if (found) return found; - ERR_PRINTS(String() + "Type not found. Creating placeholder: " + p_typeref.cname.operator String()); + ERR_PRINTS(String() + "Type not found. Creating placeholder: '" + p_typeref.cname.operator String() + "'."); const Map<StringName, TypeInterface>::Element *match = placeholder_types.find(p_typeref.cname); @@ -2175,13 +2167,13 @@ void BindingsGenerator::_populate_object_type_interfaces() { } if (!ClassDB::is_class_exposed(type_cname)) { - _log("Ignoring type `%s` because it's not exposed\n", String(type_cname).utf8().get_data()); + _log("Ignoring type '%s' because it's not exposed\n", String(type_cname).utf8().get_data()); class_list.pop_front(); continue; } if (!ClassDB::is_class_enabled(type_cname)) { - _log("Ignoring type `%s` because it's not enabled\n", String(type_cname).utf8().get_data()); + _log("Ignoring type '%s' because it's not enabled\n", String(type_cname).utf8().get_data()); class_list.pop_front(); continue; } @@ -2240,7 +2232,7 @@ void BindingsGenerator::_populate_object_type_interfaces() { // Prevent the property and its enclosing type from sharing the same name if (iprop.proxy_name == itype.proxy_name) { - _log("Name of property `%s` is ambiguous with the name of its enclosing class `%s`. Renaming property to `%s_`\n", + _log("Name of property '%s' is ambiguous with the name of its enclosing class '%s'. Renaming property to '%s_'\n", iprop.proxy_name.utf8().get_data(), itype.proxy_name.utf8().get_data(), iprop.proxy_name.utf8().get_data()); iprop.proxy_name += "_"; @@ -2298,28 +2290,26 @@ void BindingsGenerator::_populate_object_type_interfaces() { imethod.is_vararg = m && m->is_vararg(); if (!m && !imethod.is_virtual) { - if (virtual_method_list.find(method_info)) { - // A virtual method without the virtual flag. This is a special case. - - // There is no method bind, so let's fallback to Godot's object.Call(string, params) - imethod.requires_object_call = true; - - // The method Object.free is registered as a virtual method, but without the virtual flag. - // This is because this method is not supposed to be overridden, but called. - // We assume the return type is void. - imethod.return_type.cname = name_cache.type_void; - - // Actually, more methods like this may be added in the future, - // which could actually will return something different. - // Let's put this to notify us if that ever happens. - if (itype.cname != name_cache.type_Object || imethod.name != "free") { - ERR_PRINTS("Notification: New unexpected virtual non-overridable method found.\n" - "We only expected Object.free, but found " + - itype.name + "." + imethod.name); - } - } else { - ERR_EXPLAIN("Missing MethodBind for non-virtual method: " + itype.name + "." + imethod.name); - ERR_FAIL(); + ERR_FAIL_COND_MSG(!virtual_method_list.find(method_info), + "Missing MethodBind for non-virtual method: '" + itype.name + "." + imethod.name + "'."); + + // A virtual method without the virtual flag. This is a special case. + + // There is no method bind, so let's fallback to Godot's object.Call(string, params) + imethod.requires_object_call = true; + + // The method Object.free is registered as a virtual method, but without the virtual flag. + // This is because this method is not supposed to be overridden, but called. + // We assume the return type is void. + imethod.return_type.cname = name_cache.type_void; + + // Actually, more methods like this may be added in the future, + // which could actually will return something different. + // Let's put this to notify us if that ever happens. + if (itype.cname != name_cache.type_Object || imethod.name != "free") { + ERR_PRINTS("Notification: New unexpected virtual non-overridable method found." + " We only expected Object.free, but found '" + + itype.name + "." + imethod.name + "'."); } } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { imethod.return_type.cname = return_info.class_name; @@ -2328,8 +2318,8 @@ void BindingsGenerator::_populate_object_type_interfaces() { imethod.return_type.cname = return_info.class_name; if (!imethod.is_virtual && ClassDB::is_parent_class(return_info.class_name, name_cache.type_Reference) && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE) { /* clang-format off */ - ERR_PRINTS("Return type is reference but hint is not " _STR(PROPERTY_HINT_RESOURCE_TYPE) "." - " Are you returning a reference type by pointer? Method: " + itype.name + "." + imethod.name); + ERR_PRINTS("Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." + " Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'."); /* clang-format on */ ERR_FAIL(); } @@ -2394,7 +2384,7 @@ void BindingsGenerator::_populate_object_type_interfaces() { // Prevent the method and its enclosing type from sharing the same name if (imethod.proxy_name == itype.proxy_name) { - _log("Name of method `%s` is ambiguous with the name of its enclosing class `%s`. Renaming method to `%s_`\n", + _log("Name of method '%s' is ambiguous with the name of its enclosing class '%s'. Renaming method to '%s_'\n", imethod.proxy_name.utf8().get_data(), itype.proxy_name.utf8().get_data(), imethod.proxy_name.utf8().get_data()); imethod.proxy_name += "_"; @@ -2880,8 +2870,7 @@ void BindingsGenerator::_populate_global_constants() { if (global_constants_count > 0) { Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope"); - ERR_EXPLAIN("Could not find `@GlobalScope` in DocData"); - CRASH_COND(!match); + CRASH_COND_MSG(!match, "Could not find '@GlobalScope' in DocData."); const DocData::ClassDoc &global_scope_doc = match->value(); @@ -2935,7 +2924,7 @@ void BindingsGenerator::_populate_global_constants() { // HARDCODED: The Error enum have the prefix 'ERR_' for everything except 'OK' and 'FAILED'. if (ienum.cname == name_cache.enum_Error) { if (prefix_length > 0) { // Just in case it ever changes - ERR_PRINTS("Prefix for enum 'Error' is not empty"); + ERR_PRINTS("Prefix for enum '" _STR(Error) "' is not empty."); } prefix_length = 1; // 'ERR_' @@ -3024,7 +3013,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) glue_dir_path = path_elem->get(); elem = elem->next(); } else { - ERR_PRINTS(generate_all_glue_option + ": No output directory specified (expected path to {GODOT_ROOT}/modules/mono/glue)"); + ERR_PRINTS(generate_all_glue_option + ": No output directory specified (expected path to '{GODOT_ROOT}/modules/mono/glue')."); } --options_left; @@ -3035,7 +3024,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) cs_dir_path = path_elem->get(); elem = elem->next(); } else { - ERR_PRINTS(generate_cs_glue_option + ": No output directory specified"); + ERR_PRINTS(generate_cs_glue_option + ": No output directory specified."); } --options_left; @@ -3046,7 +3035,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) cpp_dir_path = path_elem->get(); elem = elem->next(); } else { - ERR_PRINTS(generate_cpp_glue_option + ": No output directory specified"); + ERR_PRINTS(generate_cpp_glue_option + ": No output directory specified."); } --options_left; @@ -3061,20 +3050,20 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) if (glue_dir_path.length()) { if (bindings_generator.generate_glue(glue_dir_path) != OK) - ERR_PRINTS(generate_all_glue_option + ": Failed to generate the C++ glue"); + ERR_PRINTS(generate_all_glue_option + ": Failed to generate the C++ glue."); if (bindings_generator.generate_cs_api(glue_dir_path.plus_file("Managed/Generated")) != OK) - ERR_PRINTS(generate_all_glue_option + ": Failed to generate the C# API"); + ERR_PRINTS(generate_all_glue_option + ": Failed to generate the C# API."); } if (cs_dir_path.length()) { if (bindings_generator.generate_cs_api(cs_dir_path) != OK) - ERR_PRINTS(generate_cs_glue_option + ": Failed to generate the C# API"); + ERR_PRINTS(generate_cs_glue_option + ": Failed to generate the C# API."); } if (cpp_dir_path.length()) { if (bindings_generator.generate_glue(cpp_dir_path) != OK) - ERR_PRINTS(generate_cpp_glue_option + ": Failed to generate the C++ glue"); + ERR_PRINTS(generate_cpp_glue_option + ": Failed to generate the C++ glue."); } // Exit once done diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 8be51a6c55..6f0c297575 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -147,7 +147,7 @@ class BindingsGenerator { bool requires_object_call; /** - * Determines if the method visibility is `internal` (visible only to files in the same assembly). + * Determines if the method visibility is 'internal' (visible only to files in the same assembly). * Currently, we only use this for methods that are not meant to be exposed, * but are required by properties as getters or setters. * Methods that are not meant to be exposed are those that begin with underscore and are not virtual. diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp index d88b08c646..0e6c58c9d7 100644 --- a/modules/mono/editor/csharp_project.cpp +++ b/modules/mono/editor/csharp_project.cpp @@ -81,16 +81,14 @@ bool generate_api_solution(const String &p_solution_dir, const String &p_core_pr _GDMONO_SCOPE_DOMAIN_(temp_domain); - GDMonoAssembly *tools_project_editor_assembly = NULL; + GDMonoAssembly *tools_project_editor_asm = NULL; - if (!GDMono::get_singleton()->load_assembly("GodotTools.ProjectEditor", &tools_project_editor_assembly)) { - ERR_EXPLAIN("Failed to load assembly: 'GodotTools.ProjectEditor'"); - ERR_FAIL_V(false); - } + bool assembly_loaded = GDMono::get_singleton()->load_assembly(TOOLS_PROJECT_EDITOR_ASM_NAME, &tools_project_editor_asm); + ERR_FAIL_COND_V_MSG(!assembly_loaded, false, "Failed to load assembly: '" TOOLS_PROJECT_EDITOR_ASM_NAME "'."); return generate_api_solution_impl(p_solution_dir, p_core_proj_dir, p_core_compile_items, p_editor_proj_dir, p_editor_compile_items, - tools_project_editor_assembly); + tools_project_editor_asm); } } diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp index 020bb70a08..80a7335b1d 100644 --- a/modules/mono/editor/godotsharp_export.cpp +++ b/modules/mono/editor/godotsharp_export.cpp @@ -85,18 +85,12 @@ Error GodotSharpExport::get_assembly_dependencies(GDMonoAssembly *p_assembly, co } } - if (!ref_assembly) { - ERR_EXPLAIN("Cannot load assembly (refonly): " + ref_name); - ERR_FAIL_V(ERR_CANT_RESOLVE); - } + ERR_FAIL_COND_V_MSG(!ref_assembly, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'."); r_dependencies[ref_name] = ref_assembly->get_path(); Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies); - if (err != OK) { - ERR_EXPLAIN("Cannot load one of the dependencies for the assembly: " + ref_name); - ERR_FAIL_V(err); - } + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load one of the dependencies for the assembly: '" + ref_name + "'."); } return OK; @@ -113,8 +107,7 @@ Error GodotSharpExport::get_exported_assembly_dependencies(const String &p_proje bool load_success = GDMono::get_singleton()->load_assembly_from(p_project_dll_name, p_project_dll_src_path, &scripts_assembly, /* refonly: */ true); - ERR_EXPLAIN("Cannot load assembly (refonly): " + p_project_dll_name); - ERR_FAIL_COND_V(!load_success, ERR_CANT_RESOLVE); + ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + p_project_dll_name + "'."); Vector<String> search_dirs; GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_lib_dir); diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp index dfb652a7aa..dcb0ca5a80 100644 --- a/modules/mono/editor/script_class_parser.cpp +++ b/modules/mono/editor/script_class_parser.cpp @@ -162,8 +162,8 @@ ScriptClassParser::Token ScriptClassParser::get_token() { error = true; return TK_ERROR; } else if (code[idx] == begin_str) { - if (verbatim && code[idx + 1] == '"') { // `""` is verbatim string's `\"` - idx += 2; // skip next `"` as well + if (verbatim && code[idx + 1] == '"') { // '""' is verbatim string's '\"' + idx += 2; // skip next '"' as well continue; } @@ -590,7 +590,7 @@ Error ScriptClassParser::parse(const String &p_code) { name = String(value); } else if (tk == TK_CURLY_BRACKET_OPEN) { if (name.empty()) { - error_str = "Expected " + get_token_name(TK_IDENTIFIER) + " after keyword `struct`, found " + get_token_name(TK_CURLY_BRACKET_OPEN); + error_str = "Expected " + get_token_name(TK_IDENTIFIER) + " after keyword 'struct', found " + get_token_name(TK_CURLY_BRACKET_OPEN); error = true; return ERR_PARSE_ERROR; } @@ -657,12 +657,12 @@ Error ScriptClassParser::parse_file(const String &p_filepath) { String source; Error ferr = read_all_file_utf8(p_filepath, source); - if (ferr != OK) { - if (ferr == ERR_INVALID_DATA) { - ERR_EXPLAIN("File '" + p_filepath + "' contains invalid unicode (utf-8), so it was not loaded. Please ensure that scripts are saved in valid utf-8 unicode."); - } - ERR_FAIL_V(ferr); - } + + ERR_FAIL_COND_V_MSG(ferr != OK, ferr, + ferr == ERR_INVALID_DATA ? + "File '" + p_filepath + "' contains invalid unicode (UTF-8), so it was not loaded." + " Please ensure that scripts are saved in valid UTF-8 unicode." : + "Failed to read file: '" + p_filepath + "'."); return parse(source); } diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp index 7c30092855..27fd715f60 100644 --- a/modules/mono/glue/gd_glue.cpp +++ b/modules/mono/glue/gd_glue.cpp @@ -167,7 +167,7 @@ MonoObject *godot_icall_GD_str2var(MonoString *p_str) { int line; Error err = VariantParser::parse(&ss, ret, errs, line); if (err != OK) { - String err_str = "Parse error at line " + itos(line) + ": " + errs; + String err_str = "Parse error at line " + itos(line) + ": " + errs + "."; ERR_PRINTS(err_str); ret = err_str; } @@ -193,8 +193,7 @@ MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_object PoolByteArray barr; int len; Error err = encode_variant(var, NULL, len, p_full_objects); - ERR_EXPLAIN("Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."); - ERR_FAIL_COND_V(err != OK, NULL); + ERR_FAIL_COND_V_MSG(err != OK, NULL, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."); barr.resize(len); { diff --git a/modules/mono/godotsharp_defs.h b/modules/mono/godotsharp_defs.h index 4ad4088514..4c17a6ec9d 100644 --- a/modules/mono/godotsharp_defs.h +++ b/modules/mono/godotsharp_defs.h @@ -39,8 +39,8 @@ #define API_SOLUTION_NAME "GodotSharp" #define CORE_API_ASSEMBLY_NAME "GodotSharp" #define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor" -#define TOOLS_ASSEMBLY_NAME "GodotTools" -#define TOOLS_PROJECT_EDITOR_ASSEMBLY_NAME "GodotTools.ProjectEditor" +#define TOOLS_ASM_NAME "GodotTools" +#define TOOLS_PROJECT_EDITOR_ASM_NAME "GodotTools.ProjectEditor" #define BINDINGS_CLASS_NATIVECALLS "NativeCalls" #define BINDINGS_CLASS_NATIVECALLS_EDITOR "EditorNativeCalls" diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 45f79074be..ee1ecf3be7 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -265,7 +265,7 @@ void GDMono::initialize() { #ifdef WINDOWS_ENABLED if (assembly_rootdir.empty() || config_dir.empty()) { - ERR_PRINT("Cannot find Mono in the registry"); + ERR_PRINT("Cannot find Mono in the registry."); // Assertion: if they are not set, then they weren't found in the registry CRASH_COND(mono_reg_info.assembly_dir.length() > 0 || mono_reg_info.config_dir.length() > 0); } @@ -318,9 +318,7 @@ void GDMono::initialize() { #endif root_domain = mono_jit_init_version("GodotEngine.RootDomain", "v4.0.30319"); - - ERR_EXPLAIN("Mono: Failed to initialize runtime"); - ERR_FAIL_NULL(root_domain); + ERR_FAIL_NULL_MSG(root_domain, "Mono: Failed to initialize runtime."); GDMonoUtils::set_main_thread(GDMonoUtils::get_current_thread()); @@ -331,11 +329,11 @@ void GDMono::initialize() { print_verbose("Mono: Runtime initialized"); // mscorlib assembly MUST be present at initialization - ERR_EXPLAIN("Mono: Failed to load mscorlib assembly"); - ERR_FAIL_COND(!_load_corlib_assembly()); + bool corlib_loaded = _load_corlib_assembly(); + ERR_FAIL_COND_MSG(!corlib_loaded, "Mono: Failed to load mscorlib assembly."); - ERR_EXPLAIN("Mono: Failed to load scripts domain"); - ERR_FAIL_COND(_load_scripts_domain() != OK); + Error domain_load_err = _load_scripts_domain(); + ERR_FAIL_COND_MSG(domain_load_err != OK, "Mono: Failed to load scripts domain."); #ifdef DEBUG_ENABLED bool debugger_attached = _wait_for_debugger_msecs(500); @@ -351,8 +349,7 @@ void GDMono::initialize() { void GDMono::initialize_load_assemblies() { #ifndef MONO_GLUE_ENABLED - ERR_EXPLAIN("Mono: This binary was built with `mono_glue=no`; cannot load assemblies"); - CRASH_NOW(); + CRASH_NOW_MSG("Mono: This binary was built with 'mono_glue=no'; cannot load assemblies."); #endif // Load assemblies. The API and tools assemblies are required, @@ -361,10 +358,8 @@ void GDMono::initialize_load_assemblies() { _load_api_assemblies(); #if defined(TOOLS_ENABLED) - if (!_load_tools_assemblies()) { - ERR_EXPLAIN("Mono: Failed to load GodotTools assemblies"); - CRASH_NOW(); - } + bool tool_assemblies_loaded = _load_tools_assemblies(); + CRASH_COND_MSG(!tool_assemblies_loaded, "Mono: Failed to load '" TOOLS_ASM_NAME "' assemblies."); #endif // Load the project's main assembly. This doesn't necessarily need to succeed. @@ -428,12 +423,12 @@ void GDMono::_initialize_and_check_api_hashes() { #ifdef MONO_GLUE_ENABLED if (get_api_core_hash() != GodotSharpBindings::get_core_api_hash()) { - ERR_PRINT("Mono: Core API hash mismatch!"); + ERR_PRINT("Mono: Core API hash mismatch."); } #ifdef TOOLS_ENABLED if (get_api_editor_hash() != GodotSharpBindings::get_editor_api_hash()) { - ERR_PRINT("Mono: Editor API hash mismatch!"); + ERR_PRINT("Mono: Editor API hash mismatch."); } #endif // TOOLS_ENABLED #endif // MONO_GLUE_ENABLED @@ -579,7 +574,7 @@ bool GDMono::copy_prebuilt_api_assembly(APIAssembly::Type p_api_type) { memdelete(da); if (err != OK) { - ERR_PRINTS("Failed to create destination directory for the API assemblies. Error: " + itos(err)); + ERR_PRINTS("Failed to create destination directory for the API assemblies. Error: " + itos(err) + "."); return false; } } @@ -593,16 +588,16 @@ bool GDMono::copy_prebuilt_api_assembly(APIAssembly::Type p_api_type) { String xml_file = assembly_name + ".xml"; if (da->copy(src_dir.plus_file(xml_file), dst_dir.plus_file(xml_file)) != OK) - WARN_PRINTS("Failed to copy " + xml_file); + WARN_PRINTS("Failed to copy '" + xml_file + "'."); String pdb_file = assembly_name + ".pdb"; if (da->copy(src_dir.plus_file(pdb_file), dst_dir.plus_file(pdb_file)) != OK) - WARN_PRINTS("Failed to copy " + pdb_file); + WARN_PRINTS("Failed to copy '" + pdb_file + "'."); Error err = da->copy(assembly_src, assembly_dst); if (err != OK) { - ERR_PRINTS("Failed to copy " + assembly_file); + ERR_PRINTS("Failed to copy '" + assembly_file + "'."); return false; } @@ -617,11 +612,11 @@ String GDMono::update_api_assemblies_from_prebuilt() { #define FAIL_REASON(m_out_of_sync, m_prebuilt_exists) \ ( \ (m_out_of_sync ? \ - String("The assembly is invalidated") : \ - String("The assembly was not found")) + \ + String("The assembly is invalidated ") : \ + String("The assembly was not found ")) + \ (m_prebuilt_exists ? \ - String(" and the prebuilt assemblies are missing") : \ - String(" and we failed to copy the prebuilt assemblies"))) + String("and the prebuilt assemblies are missing.") : \ + String("and we failed to copy the prebuilt assemblies."))) bool api_assembly_out_of_sync = core_api_assembly_out_of_sync || editor_api_assembly_out_of_sync; @@ -755,29 +750,19 @@ void GDMono::_load_api_assemblies() { // update them from the prebuilt assemblies directory before trying to load them. // Shouldn't happen. The project manager loads the prebuilt API assemblies - if (Main::is_project_manager()) { - ERR_EXPLAIN("Failed to load one of the prebuilt API assemblies"); - CRASH_NOW(); - } + CRASH_COND_MSG(Main::is_project_manager(), "Failed to load one of the prebuilt API assemblies."); // 1. Unload the scripts domain - if (_unload_scripts_domain() != OK) { - ERR_EXPLAIN("Mono: Failed to unload scripts domain"); - CRASH_NOW(); - } + Error domain_unload_err = _unload_scripts_domain(); + CRASH_COND_MSG(domain_unload_err != OK, "Mono: Failed to unload scripts domain."); // 2. Update the API assemblies String update_error = update_api_assemblies_from_prebuilt(); - if (!update_error.empty()) { - ERR_EXPLAIN(update_error); - CRASH_NOW(); - } + CRASH_COND_MSG(!update_error.empty(), update_error); // 3. Load the scripts domain again - if (_load_scripts_domain() != OK) { - ERR_EXPLAIN("Mono: Failed to load scripts domain"); - CRASH_NOW(); - } + Error domain_load_err = _load_scripts_domain(); + CRASH_COND_MSG(domain_load_err != OK, "Mono: Failed to load scripts domain."); // 4. Try loading the updated assemblies if (!_try_load_api_assemblies()) { @@ -785,24 +770,22 @@ void GDMono::_load_api_assemblies() { if (_are_api_assemblies_out_of_sync()) { if (core_api_assembly_out_of_sync) { - ERR_PRINT("The assembly '" CORE_API_ASSEMBLY_NAME "' is out of sync"); + ERR_PRINT("The assembly '" CORE_API_ASSEMBLY_NAME "' is out of sync."); } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) { - ERR_PRINT("The loaded assembly '" CORE_API_ASSEMBLY_NAME "' is in sync, but the cache update failed"); + ERR_PRINT("The loaded assembly '" CORE_API_ASSEMBLY_NAME "' is in sync, but the cache update failed."); } if (editor_api_assembly_out_of_sync) { - ERR_PRINT("The assembly '" EDITOR_API_ASSEMBLY_NAME "' is out of sync"); + ERR_PRINT("The assembly '" EDITOR_API_ASSEMBLY_NAME "' is out of sync."); } CRASH_NOW(); } else { - ERR_EXPLAIN("Failed to load one of the API assemblies"); - CRASH_NOW(); + CRASH_NOW_MSG("Failed to load one of the API assemblies."); } } #else - ERR_EXPLAIN("Failed to load one of the API assemblies"); - CRASH_NOW(); + CRASH_NOW_MSG("Failed to load one of the API assemblies."); #endif } } @@ -813,8 +796,8 @@ bool GDMono::_load_tools_assemblies() { if (tools_assembly && tools_project_editor_assembly) return true; - bool success = load_assembly(TOOLS_ASSEMBLY_NAME, &tools_assembly) && - load_assembly(TOOLS_PROJECT_EDITOR_ASSEMBLY_NAME, &tools_project_editor_assembly); + bool success = load_assembly(TOOLS_ASM_NAME, &tools_assembly) && + load_assembly(TOOLS_PROJECT_EDITOR_ASM_NAME, &tools_project_editor_assembly); return success; } @@ -851,7 +834,7 @@ void GDMono::_install_trace_listener() { (DebuggingUtils_InstallTraceListener)debug_utils->get_method_thunk("InstallTraceListener"); install_func((MonoObject **)&exc); if (exc) { - ERR_PRINT("Failed to install System.Diagnostics.Trace listener"); + ERR_PRINT("Failed to install 'System.Diagnostics.Trace' listener."); GDMonoUtils::debug_print_unhandled_exception(exc); } #endif @@ -865,8 +848,7 @@ Error GDMono::_load_scripts_domain() { scripts_domain = GDMonoUtils::create_domain("GodotEngine.ScriptsDomain"); - ERR_EXPLAIN("Mono: Could not create scripts app domain"); - ERR_FAIL_NULL_V(scripts_domain, ERR_CANT_CREATE); + ERR_FAIL_NULL_V_MSG(scripts_domain, ERR_CANT_CREATE, "Mono: Could not create scripts app domain."); mono_domain_set(scripts_domain, true); @@ -885,7 +867,7 @@ Error GDMono::_unload_scripts_domain() { finalizing_scripts_domain = true; if (!mono_domain_finalize(scripts_domain, 2000)) { - ERR_PRINT("Mono: Domain finalization timeout"); + ERR_PRINT("Mono: Domain finalization timeout."); } finalizing_scripts_domain = false; @@ -911,7 +893,7 @@ Error GDMono::_unload_scripts_domain() { mono_domain_try_unload(domain, (MonoObject **)&exc); if (exc) { - ERR_PRINT("Exception thrown when unloading scripts domain"); + ERR_PRINT("Exception thrown when unloading scripts domain."); GDMonoUtils::debug_unhandled_exception(exc); return FAILED; } @@ -925,20 +907,14 @@ Error GDMono::reload_scripts_domain() { ERR_FAIL_COND_V(!runtime_initialized, ERR_BUG); if (scripts_domain) { - Error err = _unload_scripts_domain(); - if (err != OK) { - ERR_PRINT("Mono: Failed to unload scripts domain"); - return err; - } + Error domain_unload_err = _unload_scripts_domain(); + ERR_FAIL_COND_V_MSG(domain_unload_err != OK, domain_unload_err, "Mono: Failed to unload scripts domain."); } CSharpLanguage::get_singleton()->_on_scripts_domain_unloaded(); - Error err = _load_scripts_domain(); - if (err != OK) { - ERR_PRINT("Mono: Failed to load scripts domain"); - return err; - } + Error domain_load_err = _load_scripts_domain(); + ERR_FAIL_COND_V_MSG(domain_load_err != OK, domain_load_err, "Mono: Failed to load scripts domain."); // Load assemblies. The API and tools assemblies are required, // the application is aborted if these assemblies cannot be loaded. @@ -946,10 +922,8 @@ Error GDMono::reload_scripts_domain() { _load_api_assemblies(); #if defined(TOOLS_ENABLED) - if (!_load_tools_assemblies()) { - ERR_EXPLAIN("Mono: Failed to load GodotTools assemblies"); - CRASH_NOW(); - } + bool tools_assemblies_loaded = _load_tools_assemblies(); + CRASH_COND_MSG(!tools_assemblies_loaded, "Mono: Failed to load '" TOOLS_ASM_NAME "' assemblies."); #endif // Load the project's main assembly. Here, during hot-reloading, we do @@ -971,13 +945,13 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { String domain_name = mono_domain_get_friendly_name(p_domain); - print_verbose("Mono: Unloading domain `" + domain_name + "`..."); + print_verbose("Mono: Unloading domain '" + domain_name + "'..."); if (mono_domain_get() == p_domain) mono_domain_set(root_domain, true); if (!mono_domain_finalize(p_domain, 2000)) { - ERR_PRINT("Mono: Domain finalization timeout"); + ERR_PRINT("Mono: Domain finalization timeout."); } mono_gc_collect(mono_gc_max_generation()); @@ -988,7 +962,7 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { mono_domain_try_unload(p_domain, (MonoObject **)&exc); if (exc) { - ERR_PRINTS("Exception thrown when unloading domain `" + domain_name + "`"); + ERR_PRINTS("Exception thrown when unloading domain '" + domain_name + "'."); GDMonoUtils::debug_print_unhandled_exception(exc); return FAILED; } @@ -1105,7 +1079,7 @@ GDMono::~GDMono() { if (scripts_domain) { Error err = _unload_scripts_domain(); if (err != OK) { - ERR_PRINT("Mono: Failed to unload scripts domain"); + ERR_PRINT("Mono: Failed to unload scripts domain."); } } diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 761c7f6fcb..a82bb42731 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -151,14 +151,14 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, vo } { - // If we find the assembly here, we load it with `mono_assembly_load_from_full`, + // If we find the assembly here, we load it with 'mono_assembly_load_from_full', // which in turn invokes load hooks before returning the MonoAssembly to us. - // One of the load hooks is `load_aot_module`. This hook can end up calling preload hooks - // again for the same assembly in certain in certain circumstances (the `do_load_image` part). + // One of the load hooks is 'load_aot_module'. This hook can end up calling preload hooks + // again for the same assembly in certain in certain circumstances (the 'do_load_image' part). // If this is the case and we return NULL due to the no_search condition below, // it will result in an internal crash later on. Therefore we need to return the assembly we didn't - // get yet from `mono_assembly_load_from_full`. Luckily we have the image, which already got it. - // This must be done here. If done in search hooks, it would cause `mono_assembly_load_from_full` + // get yet from 'mono_assembly_load_from_full'. Luckily we have the image, which already got it. + // This must be done here. If done in search hooks, it would cause 'mono_assembly_load_from_full' // to think another MonoAssembly for this assembly was already loaded, making it delete its own, // when in fact both pointers were the same... This hooks thing is confusing. if (image_corlib_loading) { diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index 1c10d3c8eb..89a88fcfb2 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -165,8 +165,8 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base #ifdef DEBUG_ENABLED String fullname = method->get_ret_type_full_name() + " " + name + "(" + method->get_signature_desc(true) + ")"; - WARN_PRINTS("Method `" + fullname + "` is hidden by Godot API method. Should be `" + - method->get_full_name_no_class() + "`. In class `" + namespace_name + "." + class_name + "`."); + WARN_PRINTS("Method '" + fullname + "' is hidden by Godot API method. Should be '" + + method->get_full_name_no_class() + "'. In class '" + namespace_name + "." + class_name + "'."); #endif continue; } @@ -184,8 +184,8 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base if (m && m->get_name() != name) { // found String fullname = m->get_ret_type_full_name() + " " + name + "(" + m->get_signature_desc(true) + ")"; - WARN_PRINTS("Method `" + fullname + "` should be `" + m->get_full_name_no_class() + - "`. In class `" + namespace_name + "." + class_name + "`."); + WARN_PRINTS("Method '" + fullname + "' should be '" + m->get_full_name_no_class() + + "'. In class '" + namespace_name + "." + class_name + "'."); break; } diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index 3999658f93..7b8e6f89e9 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -219,16 +219,14 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } default: { - ERR_EXPLAIN(String() + "Attempted to convert Variant to a managed enum value of unmarshallable base type."); - ERR_FAIL(); + ERR_FAIL_MSG("Attempted to convert Variant to a managed enum value of unmarshallable base type."); } } break; } - ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + tclass->get_name()); - ERR_FAIL(); + ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + tclass->get_name() + "'."); } break; case MONO_TYPE_ARRAY: @@ -275,8 +273,7 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } - ERR_EXPLAIN(String() + "Attempted to convert Variant to a managed array of unmarshallable element type."); - ERR_FAIL(); + ERR_FAIL_MSG("Attempted to convert Variant to a managed array of unmarshallable element type."); } break; case MONO_TYPE_CLASS: { @@ -351,8 +348,7 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ } } - ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + type_class->get_name()); - ERR_FAIL(); + ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + type_class->get_name() + "'."); } break; case MONO_TYPE_OBJECT: { @@ -508,7 +504,7 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ } break; default: { - ERR_PRINTS(String() + "Attempted to set the value of a field of unexpected type encoding: " + itos(type.type_encoding)); + ERR_PRINTS("Attempted to set the value of a field of unexpected type encoding: " + itos(type.type_encoding) + "."); } break; } diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp index e50e3b0794..3324ecb3a8 100644 --- a/modules/mono/mono_gd/gd_mono_internals.cpp +++ b/modules/mono/mono_gd/gd_mono_internals.cpp @@ -48,7 +48,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { CRASH_COND(!unmanaged); - // All mono objects created from the managed world (e.g.: `new Player()`) + // All mono objects created from the managed world (e.g.: 'new Player()') // need to have a CSharpScript in order for their methods to be callable from the unmanaged side Reference *ref = Object::cast_to<Reference>(unmanaged); diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index a6e04e561d..5a0d728953 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -72,7 +72,7 @@ static void mono_log_callback(const char *log_domain, const char *log_level, con } if (fatal) { - ERR_PRINTS("Mono: FATAL ERROR, ABORTING! Logfile: " + GDMonoLog::get_singleton()->get_log_file_path() + "\n"); + ERR_PRINTS("Mono: FATAL ERROR, ABORTING! Logfile: '" + GDMonoLog::get_singleton()->get_log_file_path() + "'."); // Make sure to flush before aborting f->flush(); f->close(); @@ -90,8 +90,7 @@ bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) { DirAccessRef diraccess = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); ERR_FAIL_COND_V(!diraccess, false); Error logs_mkdir_err = diraccess->make_dir_recursive(p_logs_dir); - ERR_EXPLAIN("Failed to create mono logs directory"); - ERR_FAIL_COND_V(logs_mkdir_err != OK, false); + ERR_FAIL_COND_V_MSG(logs_mkdir_err != OK, false, "Failed to create mono logs directory."); } return true; @@ -131,7 +130,7 @@ void GDMonoLog::initialize() { CharString log_level = OS::get_singleton()->get_environment("GODOT_MONO_LOG_LEVEL").utf8(); if (log_level.length() != 0 && log_level_get_id(log_level.get_data()) == -1) { - ERR_PRINTS(String() + "Mono: Ignoring invalid log level (GODOT_MONO_LOG_LEVEL): " + log_level.get_data()); + ERR_PRINTS(String() + "Mono: Ignoring invalid log level (GODOT_MONO_LOG_LEVEL): '" + log_level.get_data() + "'."); log_level = CharString(); } @@ -160,7 +159,7 @@ void GDMonoLog::initialize() { log_file = FileAccess::open(log_file_path, FileAccess::WRITE); if (!log_file) { - ERR_PRINT("Mono: Cannot create log file"); + ERR_PRINT("Mono: Cannot create log file."); } } diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 42102ed835..7aac691102 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -276,7 +276,7 @@ String mono_to_utf8_string(MonoString *p_mono_string) { char *utf8 = mono_string_to_utf8_checked(p_mono_string, &error); if (!mono_error_ok(&error)) { - ERR_PRINTS(String("Failed to convert MonoString* to UTF-8: ") + mono_error_get_message(&error)); + ERR_PRINTS(String() + "Failed to convert MonoString* to UTF-8: '" + mono_error_get_message(&error) + "'."); mono_error_cleanup(&error); return String(); } @@ -474,8 +474,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return BOX_ENUM(enum_baseclass, val); } default: { - ERR_EXPLAIN(String() + "Attempted to convert Variant to a managed enum value of unmarshallable base type."); - ERR_FAIL_V(NULL); + ERR_FAIL_V_MSG(NULL, "Attempted to convert Variant to a managed enum value of unmarshallable base type."); } } } @@ -509,8 +508,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty if (array_type->eklass == CACHED_CLASS_RAW(Color)) return (MonoObject *)PoolColorArray_to_mono_array(p_var->operator PoolColorArray()); - ERR_EXPLAIN(String() + "Attempted to convert Variant to a managed array of unmarshallable element type."); - ERR_FAIL_V(NULL); + ERR_FAIL_V_MSG(NULL, "Attempted to convert Variant to a managed array of unmarshallable element type."); } break; case MONO_TYPE_CLASS: { @@ -695,9 +693,8 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty } break; } - ERR_EXPLAIN(String() + "Attempted to convert Variant to an unmarshallable managed type. Name: \'" + - p_type.type_class->get_name() + "\' Encoding: " + itos(p_type.type_encoding)); - ERR_FAIL_V(NULL); + ERR_FAIL_V_MSG(NULL, "Attempted to convert Variant to an unmarshallable managed type. Name: '" + + p_type.type_class->get_name() + "' Encoding: " + itos(p_type.type_encoding) + "."); } Variant mono_object_to_variant(MonoObject *p_obj) { @@ -809,8 +806,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) { if (array_type->eklass == CACHED_CLASS_RAW(Color)) return mono_array_to_PoolColorArray((MonoArray *)p_obj); - ERR_EXPLAIN(String() + "Attempted to convert a managed array of unmarshallable element type to Variant."); - ERR_FAIL_V(Variant()); + ERR_FAIL_V_MSG(Variant(), "Attempted to convert a managed array of unmarshallable element type to Variant."); } break; case MONO_TYPE_CLASS: { @@ -908,9 +904,8 @@ Variant mono_object_to_variant(MonoObject *p_obj) { } break; } - ERR_EXPLAIN(String() + "Attempted to convert an unmarshallable managed type to Variant. Name: \'" + - type.type_class->get_name() + "\' Encoding: " + itos(type.type_encoding)); - ERR_FAIL_V(Variant()); + ERR_FAIL_V_MSG(Variant(), "Attempted to convert an unmarshallable managed type to Variant. Name: '" + + type.type_class->get_name() + "' Encoding: " + itos(type.type_encoding) + "."); } MonoArray *Array_to_mono_array(const Array &p_array) { diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index 7afdfc8ac8..e385f4c601 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -52,14 +52,11 @@ namespace GDMonoUtils { MonoCache mono_cache; -#define CACHE_AND_CHECK(m_var, m_val) \ - { \ - CRASH_COND(m_var != NULL); \ - m_var = m_val; \ - if (!m_var) { \ - ERR_EXPLAIN("Mono Cache: Member " #m_var " is null"); \ - ERR_FAIL(); \ - } \ +#define CACHE_AND_CHECK(m_var, m_val) \ + { \ + CRASH_COND(m_var != NULL); \ + m_var = m_val; \ + ERR_FAIL_COND_MSG(!m_var, "Mono Cache: Member " #m_var " is null."); \ } #define CACHE_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_class, m_val) @@ -453,10 +450,9 @@ GDMonoClass *get_class_native_base(GDMonoClass *p_class) { } MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) { - if (!ClassDB::is_parent_class(p_object->get_class_name(), p_native)) { - ERR_EXPLAIN("Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'"); - ERR_FAIL_V(NULL); - } + bool parent_is_object_class = ClassDB::is_parent_class(p_object->get_class_name(), p_native); + ERR_FAIL_COND_V_MSG(!parent_is_object_class, NULL, + "Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'."); MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr()); ERR_FAIL_NULL_V(mono_object, NULL); diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index 54d73c971f..189ceaab1b 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -67,10 +67,8 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p Variant SignalAwaiterHandle::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { #ifdef DEBUG_ENABLED - if (conn_target_id && !ObjectDB::get_instance(conn_target_id)) { - ERR_EXPLAIN("Resumed after await, but class instance is gone"); - ERR_FAIL_V(Variant()); - } + ERR_FAIL_COND_V_MSG(conn_target_id && !ObjectDB::get_instance(conn_target_id), Variant(), + "Resumed after await, but class instance is gone."); #endif if (p_argcount < 1) { diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index 2b014c2a45..ae5a2cde81 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -55,10 +55,7 @@ int sfind(const String &p_text, int p_from) { for (int j = 0; j < src_len; j++) { int read_pos = i + j; - if (read_pos >= len) { - ERR_PRINT("read_pos >= len"); - return -1; - }; + ERR_FAIL_COND_V(read_pos >= len, -1); switch (j) { case 0: diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index e709bac377..ed5dd77f53 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -180,12 +180,12 @@ double Range::get_as_ratio() const { float value = CLAMP(get_value(), shared->min, shared->max); double v = Math::log(value) / Math::log((double)2); - return (v - exp_min) / (exp_max - exp_min); + return CLAMP((v - exp_min) / (exp_max - exp_min), 0, 1); } else { float value = CLAMP(get_value(), shared->min, shared->max); - return (value - get_min()) / (get_max() - get_min()); + return CLAMP((value - get_min()) / (get_max() - get_min()), 0, 1); } } diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 7c3867beaa..0f0974114f 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -1047,8 +1047,8 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_transmit_enabled"), "set_fog_transmit_enabled", "is_fog_transmit_enabled"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_transmit_curve", PROPERTY_HINT_EXP_EASING), "set_fog_transmit_curve", "get_fog_transmit_curve"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_height_enabled"), "set_fog_height_enabled", "is_fog_height_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_min", PROPERTY_HINT_RANGE, "-4000,4000,0.1"), "set_fog_height_min", "get_fog_height_min"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_max", PROPERTY_HINT_RANGE, "-4000,4000,0.1"), "set_fog_height_max", "get_fog_height_max"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_min", PROPERTY_HINT_RANGE, "-4000,4000,0.1,or_lesser,or_greater"), "set_fog_height_min", "get_fog_height_min"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_max", PROPERTY_HINT_RANGE, "-4000,4000,0.1,or_lesser,or_greater"), "set_fog_height_max", "get_fog_height_max"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_curve", PROPERTY_HINT_EXP_EASING), "set_fog_height_curve", "get_fog_height_curve"); ClassDB::bind_method(D_METHOD("set_tonemapper", "mode"), &Environment::set_tonemapper); @@ -1406,8 +1406,8 @@ Environment::Environment() : fog_transmit_curve = 1; fog_height_enabled = false; - fog_height_min = 0; - fog_height_max = 100; + fog_height_min = 10; + fog_height_max = 0; fog_height_curve = 1; set_fog_color(Color(0.5, 0.6, 0.7)); |