diff options
Diffstat (limited to 'editor')
25 files changed, 155 insertions, 182 deletions
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index ac8bef817b..6ed2cb9d9c 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -142,7 +142,7 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) bool found = text_editor->search(text, p_flags, p_from_line, p_from_col, line, col); if (found) { - if (!preserve_cursor) { + if (!preserve_cursor && !is_selection_only()) { text_editor->unfold_line(line); text_editor->cursor_set_line(line, false); text_editor->cursor_set_column(col + text.length(), false); diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index c4290b7cca..6befee090b 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -43,28 +43,34 @@ void EditorProfiler::_make_metric_ptrs(Metric &m) { } } +EditorProfiler::Metric EditorProfiler::_get_frame_metric(int index) { + return frame_metrics[(frame_metrics.size() + last_metric - (total_metrics - 1) + index) % frame_metrics.size()]; +} + void EditorProfiler::add_frame_metric(const Metric &p_metric, bool p_final) { ++last_metric; if (last_metric >= frame_metrics.size()) { last_metric = 0; } + total_metrics++; + if (total_metrics > frame_metrics.size()) { + total_metrics = frame_metrics.size(); + } + frame_metrics.write[last_metric] = p_metric; _make_metric_ptrs(frame_metrics.write[last_metric]); updating_frame = true; - cursor_metric_edit->set_max(frame_metrics[last_metric].frame_number); - cursor_metric_edit->set_min(MAX(frame_metrics[last_metric].frame_number - frame_metrics.size(), 0)); + clear_button->set_disabled(false); + cursor_metric_edit->set_editable(true); + cursor_metric_edit->set_max(p_metric.frame_number); + cursor_metric_edit->set_min(_get_frame_metric(0).frame_number); if (!seeking) { - cursor_metric_edit->set_value(frame_metrics[last_metric].frame_number); - if (hover_metric != -1) { - hover_metric++; - if (hover_metric >= frame_metrics.size()) { - hover_metric = 0; - } - } + cursor_metric_edit->set_value(p_metric.frame_number); } + updating_frame = false; if (frame_delay->is_stopped()) { @@ -83,6 +89,7 @@ void EditorProfiler::clear() { metric_size = CLAMP(metric_size, 60, 1024); frame_metrics.clear(); frame_metrics.resize(metric_size); + total_metrics = 0; last_metric = -1; variables->clear(); plot_sigs.clear(); @@ -93,6 +100,7 @@ void EditorProfiler::clear() { cursor_metric_edit->set_min(0); cursor_metric_edit->set_max(100); // Doesn't make much sense, but we can't have min == max. Doesn't hurt. cursor_metric_edit->set_value(0); + cursor_metric_edit->set_editable(false); updating_frame = false; hover_metric = -1; seeking = false; @@ -187,11 +195,8 @@ void EditorProfiler::_update_plot() { const bool use_self = display_time->get_selected() == DISPLAY_SELF_TIME; float highest = 0; - for (int i = 0; i < frame_metrics.size(); i++) { - const Metric &m = frame_metrics[i]; - if (!m.valid) { - continue; - } + for (int i = 0; i < total_metrics; i++) { + const Metric &m = _get_frame_metric(i); for (Set<StringName>::Element *E = plot_sigs.front(); E; E = E->next()) { const Map<StringName, Metric::Category *>::Element *F = m.category_ptrs.find(E->get()); @@ -220,78 +225,43 @@ void EditorProfiler::_update_plot() { int *column = columnv.ptrw(); - Map<StringName, int> plot_prev; - //Map<StringName,int> plot_max; + Map<StringName, int> prev_plots; - for (int i = 0; i < w; i++) { + for (int i = 0; i < total_metrics * w / frame_metrics.size() - 1; i++) { for (int j = 0; j < h * 4; j++) { column[j] = 0; } int current = i * frame_metrics.size() / w; - int next = (i + 1) * frame_metrics.size() / w; - if (next > frame_metrics.size()) { - next = frame_metrics.size(); - } - if (next == current) { - next = current + 1; //just because for loop must work - } for (Set<StringName>::Element *E = plot_sigs.front(); E; E = E->next()) { - int plot_pos = -1; + const Metric &m = _get_frame_metric(current); - for (int j = current; j < next; j++) { - //wrap - int idx = last_metric + 1 + j; - while (idx >= frame_metrics.size()) { - idx -= frame_metrics.size(); - } - - //get - const Metric &m = frame_metrics[idx]; - if (!m.valid) { - continue; //skip because invalid - } + float value = 0; - float value = 0; - - const Map<StringName, Metric::Category *>::Element *F = m.category_ptrs.find(E->get()); - if (F) { - value = F->get()->total_time; - } + const Map<StringName, Metric::Category *>::Element *F = m.category_ptrs.find(E->get()); + if (F) { + value = F->get()->total_time; + } - const Map<StringName, Metric::Category::Item *>::Element *G = m.item_ptrs.find(E->get()); - if (G) { - if (use_self) { - value = G->get()->self; - } else { - value = G->get()->total; - } + const Map<StringName, Metric::Category::Item *>::Element *G = m.item_ptrs.find(E->get()); + if (G) { + if (use_self) { + value = G->get()->self; + } else { + value = G->get()->total; } - - plot_pos = MAX(CLAMP(int(value * h / highest), 0, h - 1), plot_pos); } + int plot_pos = CLAMP(int(value * h / highest), 0, h - 1); + int prev_plot = plot_pos; - Map<StringName, int>::Element *H = plot_prev.find(E->get()); + Map<StringName, int>::Element *H = prev_plots.find(E->get()); if (H) { prev_plot = H->get(); H->get() = plot_pos; } else { - plot_prev[E->get()] = plot_pos; - } - - if (plot_pos == -1 && prev_plot == -1) { - //don't bother drawing - continue; - } - - if (prev_plot != -1 && plot_pos == -1) { - plot_pos = prev_plot; - } - - if (prev_plot == -1 && plot_pos != -1) { - prev_plot = plot_pos; + prev_plots[E->get()] = plot_pos; } plot_pos = h - plot_pos - 1; @@ -352,15 +322,13 @@ void EditorProfiler::_update_plot() { } void EditorProfiler::_update_frame() { - int cursor_metric = _get_cursor_index(); - - ERR_FAIL_INDEX(cursor_metric, frame_metrics.size()); + int cursor_metric = cursor_metric_edit->get_value() - _get_frame_metric(0).frame_number; updating_frame = true; variables->clear(); TreeItem *root = variables->create_item(); - const Metric &m = frame_metrics[cursor_metric]; + const Metric &m = _get_frame_metric(cursor_metric); int dtime = display_time->get_selected(); @@ -410,6 +378,7 @@ void EditorProfiler::_activate_pressed() { if (activate->is_pressed()) { activate->set_icon(get_theme_icon("Stop", "EditorIcons")); activate->set_text(TTR("Stop")); + _clear_pressed(); } else { activate->set_icon(get_theme_icon("Play", "EditorIcons")); activate->set_text(TTR("Start")); @@ -418,6 +387,7 @@ void EditorProfiler::_activate_pressed() { } void EditorProfiler::_clear_pressed() { + clear_button->set_disabled(true); clear(); _update_plot(); } @@ -430,30 +400,16 @@ void EditorProfiler::_notification(int p_what) { } void EditorProfiler::_graph_tex_draw() { - if (last_metric < 0) { + if (total_metrics == 0) { return; } if (seeking) { - int max_frames = frame_metrics.size(); - int frame = cursor_metric_edit->get_value() - (frame_metrics[last_metric].frame_number - max_frames + 1); - if (frame < 0) { - frame = 0; - } - - int cur_x = frame * graph->get_size().x / max_frames; - + int frame = cursor_metric_edit->get_value() - _get_frame_metric(0).frame_number; + int cur_x = (2 * frame + 1) * graph->get_size().x / (2 * frame_metrics.size()) + 1; graph->draw_line(Vector2(cur_x, 0), Vector2(cur_x, graph->get_size().y), Color(1, 1, 1, 0.8)); } - - if (hover_metric != -1 && frame_metrics[hover_metric].valid) { - int max_frames = frame_metrics.size(); - int frame = frame_metrics[hover_metric].frame_number - (frame_metrics[last_metric].frame_number - max_frames + 1); - if (frame < 0) { - frame = 0; - } - - int cur_x = frame * graph->get_size().x / max_frames; - + if (hover_metric > -1 && hover_metric < total_metrics) { + int cur_x = (2 * hover_metric + 1) * graph->get_size().x / (2 * frame_metrics.size()) + 1; graph->draw_line(Vector2(cur_x, 0), Vector2(cur_x, graph->get_size().y), Color(1, 1, 1, 0.4)); } } @@ -484,10 +440,10 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { if ( (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) || (mm.is_valid())) { - int x = me->get_position().x; + int x = me->get_position().x - 1; x = x * frame_metrics.size() / graph->get_size().width; - bool show_hover = x >= 0 && x < frame_metrics.size(); + hover_metric = x; if (x < 0) { x = 0; @@ -497,41 +453,11 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { x = frame_metrics.size() - 1; } - int metric = frame_metrics.size() - x - 1; - metric = last_metric - metric; - while (metric < 0) { - metric += frame_metrics.size(); - } - - if (show_hover) { - hover_metric = metric; - - } else { - hover_metric = -1; - } - if (mb.is_valid() || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { - //cursor_metric=x; updating_frame = true; - //metric may be invalid, so look for closest metric that is valid, this makes snap feel better - bool valid = false; - for (int i = 0; i < frame_metrics.size(); i++) { - if (frame_metrics[metric].valid) { - valid = true; - break; - } - - metric++; - if (metric >= frame_metrics.size()) { - metric = 0; - } - } - - if (valid) { - cursor_metric_edit->set_value(frame_metrics[metric].frame_number); - } - + if (x < total_metrics) + cursor_metric_edit->set_value(_get_frame_metric(x).frame_number); updating_frame = false; if (activate->is_pressed()) { @@ -552,24 +478,6 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { } } -int EditorProfiler::_get_cursor_index() const { - if (last_metric < 0) { - return 0; - } - if (!frame_metrics[last_metric].valid) { - return 0; - } - - int diff = (frame_metrics[last_metric].frame_number - cursor_metric_edit->get_value()); - - int idx = last_metric - diff; - while (idx < 0) { - idx += frame_metrics.size(); - } - - return idx; -} - void EditorProfiler::disable_seeking() { seeking = false; graph->update(); @@ -659,6 +567,7 @@ EditorProfiler::EditorProfiler() { clear_button = memnew(Button); clear_button->set_text(TTR("Clear")); clear_button->connect("pressed", callable_mp(this, &EditorProfiler::_clear_pressed)); + clear_button->set_disabled(true); hb->add_child(clear_button); hb->add_child(memnew(Label(TTR("Measure:")))); @@ -687,6 +596,8 @@ EditorProfiler::EditorProfiler() { cursor_metric_edit = memnew(SpinBox); cursor_metric_edit->set_h_size_flags(SIZE_FILL); + cursor_metric_edit->set_value(0); + cursor_metric_edit->set_editable(false); hb->add_child(cursor_metric_edit); cursor_metric_edit->connect("value_changed", callable_mp(this, &EditorProfiler::_cursor_metric_changed)); @@ -726,6 +637,7 @@ EditorProfiler::EditorProfiler() { int metric_size = CLAMP(int(EDITOR_DEF("debugger/profiler_frame_history_size", 600)), 60, 1024); frame_metrics.resize(metric_size); + total_metrics = 0; last_metric = -1; hover_metric = -1; diff --git a/editor/debugger/editor_profiler.h b/editor/debugger/editor_profiler.h index e16bde41f6..8880824b87 100644 --- a/editor/debugger/editor_profiler.h +++ b/editor/debugger/editor_profiler.h @@ -106,13 +106,13 @@ private: SpinBox *cursor_metric_edit; Vector<Metric> frame_metrics; + int total_metrics; int last_metric; int max_functions; bool updating_frame; - //int cursor_metric; int hover_metric; float graph_height; @@ -139,14 +139,14 @@ private: void _graph_tex_draw(); void _graph_tex_input(const Ref<InputEvent> &p_ev); - int _get_cursor_index() const; - Color _get_color_from_signature(const StringName &p_signature) const; void _cursor_metric_changed(double); void _combo_changed(int); + Metric _get_frame_metric(int index); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index a1ff87fe2e..23226ffa9b 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -123,7 +123,7 @@ void EditorHelpSearch::_notification(int p_what) { if (search->work()) { // Search done. - // Only point to the perfect match if it's a new search, and not just reopening a old one. + // Only point to the match if it's a new search, and not just reopening a old one. if (!old_search) { results_tree->ensure_cursor_is_visible(); } else { @@ -310,6 +310,7 @@ bool EditorHelpSearch::Runner::_phase_match_classes_init() { iterator_doc = EditorHelp::get_doc_data()->class_list.front(); matches.clear(); matched_item = nullptr; + match_highest_score = 0; return true; } @@ -460,16 +461,20 @@ bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String } void EditorHelpSearch::Runner::_match_item(TreeItem *p_item, const String &p_text) { - if (!matched_item) { - if (search_flags & SEARCH_CASE_SENSITIVE) { - if (p_text.casecmp_to(term) == 0) { - matched_item = p_item; - } - } else { - if (p_text.nocasecmp_to(term) == 0) { - matched_item = p_item; - } - } + float inverse_length = 1.f / float(p_text.length()); + + // Favor types where search term is a substring close to the start of the type. + float w = 0.5f; + int pos = p_text.findn(term); + float score = (pos > -1) ? 1.0f - w * MIN(1, 3 * pos * inverse_length) : MAX(0.f, .9f - w); + + // Favor shorter items: they resemble the search term more. + w = 0.1f; + score *= (1 - w) + w * (term.length() * inverse_length); + + if (match_highest_score == 0 || score > match_highest_score) { + matched_item = p_item; + match_highest_score = score; } } diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h index 0e236d523d..350a02315f 100644 --- a/editor/editor_help_search.h +++ b/editor/editor_help_search.h @@ -124,6 +124,7 @@ class EditorHelpSearch::Runner : public Reference { TreeItem *root_item = nullptr; Map<String, TreeItem *> class_items; TreeItem *matched_item = nullptr; + float match_highest_score = 0; bool _is_class_disabled_by_feature_profile(const StringName &p_class); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 9ca46cfcc0..055baeb81e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5892,6 +5892,8 @@ EditorNode::EditorNode() { EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,MeshLibrary,TileSet"); EDITOR_DEF("interface/inspector/default_color_picker_mode", 0); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW", PROPERTY_USAGE_DEFAULT)); + EDITOR_DEF("interface/inspector/default_color_picker_shape", (int32_t)ColorPicker::SHAPE_VHS_CIRCLE); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle", PROPERTY_USAGE_DEFAULT)); EDITOR_DEF("run/auto_save/save_before_running", true); theme_base = memnew(Control); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 064271fce8..eabcbacd9a 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -160,6 +160,10 @@ void EditorInterface::edit_resource(const Ref<Resource> &p_resource) { EditorNode::get_singleton()->edit_resource(p_resource); } +void EditorInterface::edit_node(Node *p_node) { + EditorNode::get_singleton()->edit_node(p_node); +} + void EditorInterface::open_scene_from_path(const String &scene_path) { if (EditorNode::get_singleton()->is_changing_scene()) { return; @@ -312,6 +316,7 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_base_control"), &EditorInterface::get_base_control); ClassDB::bind_method(D_METHOD("get_editor_scale"), &EditorInterface::get_editor_scale); ClassDB::bind_method(D_METHOD("edit_resource", "resource"), &EditorInterface::edit_resource); + ClassDB::bind_method(D_METHOD("edit_node", "node"), &EditorInterface::edit_node); ClassDB::bind_method(D_METHOD("open_scene_from_path", "scene_filepath"), &EditorInterface::open_scene_from_path); ClassDB::bind_method(D_METHOD("reload_scene_from_path", "scene_filepath"), &EditorInterface::reload_scene_from_path); ClassDB::bind_method(D_METHOD("play_main_scene"), &EditorInterface::play_main_scene); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index b0713c641b..67b163eabf 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -71,6 +71,7 @@ public: Control *get_editor_main_control(); void edit_resource(const Ref<Resource> &p_resource); + void edit_node(Node *p_node); void open_scene_from_path(const String &scene_path); void reload_scene_from_path(const String &scene_path); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index fa44239e32..4ea993af5b 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -2190,6 +2190,9 @@ void EditorPropertyColor::_picker_created() { } else if (default_color_mode == 2) { picker->get_picker()->set_raw_mode(true); } + + int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape"); + picker->get_picker()->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); } void EditorPropertyColor::_picker_opening() { diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 35cf330714..4c5c3af765 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1282,6 +1282,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("preset_bg", "ColorPicker", theme->get_icon("GuiMiniCheckerboard", "EditorIcons")); theme->set_icon("overbright_indicator", "ColorPicker", theme->get_icon("OverbrightIndicator", "EditorIcons")); theme->set_icon("bar_arrow", "ColorPicker", theme->get_icon("ColorPickerBarArrow", "EditorIcons")); + theme->set_icon("picker_cursor", "ColorPicker", theme->get_icon("PickerCursor", "EditorIcons")); theme->set_icon("bg", "ColorPickerButton", theme->get_icon("GuiMiniCheckerboard", "EditorIcons")); diff --git a/editor/icons/PickerCursor.svg b/editor/icons/PickerCursor.svg new file mode 100644 index 0000000000..88ee3f55ce --- /dev/null +++ b/editor/icons/PickerCursor.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 1a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5-5 5 5 0 0 1 5-5z" fill="#fff"/><path d="m8 3a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 5-5 5 5 0 0 0 -5-5zm-.0605469 1a4 4 0 0 1 .0605469 0 4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 3.9394531-4z"/></svg> diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 9041b815ca..4bb56beaeb 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1241,7 +1241,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m if (mesh.is_valid()) { mesh_node->set_mesh(mesh); for (int i = 0; i < mesh->get_surface_count(); i++) { - mesh_node->set_surface_material(i, src_mesh_node->get_surface_material(i)); + mesh_node->set_surface_override_material(i, src_mesh_node->get_surface_material(i)); } } } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index b678197037..f1c9cb120d 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -804,11 +804,15 @@ void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_n bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append) { bool still_selected = true; - if (p_append) { + if (p_append && !editor_selection->get_selected_node_list().is_empty()) { if (editor_selection->is_selected(item)) { // Already in the selection, remove it from the selected nodes editor_selection->remove_node(item); still_selected = false; + + if (editor_selection->get_selected_node_list().size() == 1) { + editor->push_item(editor_selection->get_selected_node_list()[0]); + } } else { // Add the item to the selection editor_selection->add_node(item); @@ -2589,6 +2593,9 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } _find_canvas_items_in_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems); + if (selitems.size() == 1 && editor_selection->get_selected_node_list().is_empty()) { + editor->push_item(selitems[0]); + } for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) { editor_selection->add_node(E->get()); } diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index f8932cd534..6f1f243444 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -93,7 +93,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, mesh = mesh->duplicate(); for (int j = 0; j < mesh->get_surface_count(); ++j) { - Ref<Material> mat = mi->get_surface_material(j); + Ref<Material> mat = mi->get_surface_override_material(j); if (mat.is_valid()) { mesh->surface_set_material(j, mat); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index cbe0133034..3df092bc13 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1279,7 +1279,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { clicked = ObjectID(); clicked_includes_current = false; - if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->get_control()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) { + if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->get_command()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) { /* HANDLE ROTATION */ if (get_selected_count() == 0) { break; //bye @@ -2215,6 +2215,12 @@ void Node3DEditorViewport::scale_cursor_distance(real_t scale) { cursor.distance = CLAMP(cursor.distance * scale, min_distance, max_distance); } + if (cursor.distance == max_distance || cursor.distance == min_distance) { + zoom_failed_attempts_count++; + } else { + zoom_failed_attempts_count = 0; + } + zoom_indicator_delay = ZOOM_FREELOOK_INDICATOR_DELAY_S; surface->update(); } @@ -2396,6 +2402,7 @@ void Node3DEditorViewport::_notification(int p_what) { zoom_indicator_delay -= delta; if (zoom_indicator_delay <= 0) { surface->update(); + zoom_limit_label->hide(); } } @@ -2535,6 +2542,8 @@ void Node3DEditorViewport::_notification(int p_what) { cpu_time += cpu_time_history[i]; } cpu_time /= FRAME_TIME_HISTORY; + // Prevent unrealistically low values. + cpu_time = MAX(0.01, cpu_time); gpu_time_history[gpu_time_history_index] = RS::get_singleton()->viewport_get_measured_render_time_gpu(viewport->get_viewport_rid()); gpu_time_history_index = (gpu_time_history_index + 1) % FRAME_TIME_HISTORY; @@ -2543,16 +2552,19 @@ void Node3DEditorViewport::_notification(int p_what) { gpu_time += gpu_time_history[i]; } gpu_time /= FRAME_TIME_HISTORY; + // Prevent division by zero for the FPS counter (and unrealistically low values). + // This limits the reported FPS to 100000. + gpu_time = MAX(0.01, gpu_time); // Color labels depending on performance level ("good" = green, "OK" = yellow, "bad" = red). // Middle point is at 15 ms. - cpu_time_label->set_text(vformat(TTR("CPU Time: %s ms"), String::num(cpu_time, 1))); + cpu_time_label->set_text(vformat(TTR("CPU Time: %s ms"), rtos(cpu_time).pad_decimals(1))); cpu_time_label->add_theme_color_override( "font_color", frame_time_gradient->get_color_at_offset( Math::range_lerp(cpu_time, 0, 30, 0, 1))); - gpu_time_label->set_text(vformat(TTR("GPU Time: %s ms"), String::num(gpu_time, 1))); + gpu_time_label->set_text(vformat(TTR("GPU Time: %s ms"), rtos(gpu_time).pad_decimals(1))); // Middle point is at 15 ms. gpu_time_label->add_theme_color_override( "font_color", @@ -2770,6 +2782,7 @@ void Node3DEditorViewport::_draw() { } else { // Show zoom + zoom_limit_label->set_visible(zoom_failed_attempts_count > 15); real_t min_distance = MAX(camera->get_near() * 4, ZOOM_FREELOOK_MIN); real_t max_distance = MIN(camera->get_far() / 4, ZOOM_FREELOOK_MAX); @@ -3647,9 +3660,9 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_top_level_transform) { AABB bounds; - const MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(p_parent); - if (mesh_instance) { - bounds = mesh_instance->get_aabb(); + const VisualInstance3D *visual_instance = Object::cast_to<VisualInstance3D>(p_parent); + if (visual_instance) { + bounds = visual_instance->get_aabb(); } for (int i = 0; i < p_parent->get_child_count(); i++) { @@ -4132,6 +4145,15 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito locked_label->set_text(TTR("View Rotation Locked")); locked_label->hide(); + zoom_limit_label = memnew(Label); + zoom_limit_label->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT); + zoom_limit_label->set_offset(Side::SIDE_TOP, -28 * EDSCALE); + zoom_limit_label->set_text(TTR("To zoom further, change the camera's clipping planes (View -> Settings...)")); + zoom_limit_label->set_name("ZoomLimitMessageLabel"); + zoom_limit_label->add_theme_color_override("font_color", Color(1, 1, 1, 1)); + zoom_limit_label->hide(); + surface->add_child(zoom_limit_label); + frame_time_gradient = memnew(Gradient); // The color is set when the theme changes. frame_time_gradient->add_point(0.5, Color()); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index ff4a941b06..70329f90c7 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -295,6 +295,7 @@ private: Label *info_label; Label *cinema_label; Label *locked_label; + Label *zoom_limit_label; VBoxContainer *top_right_vbox; ViewportRotationControl *rotation_control; @@ -418,6 +419,7 @@ private: void scale_freelook_speed(real_t scale); real_t zoom_indicator_delay; + int zoom_failed_attempts_count = 0; RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[4], scale_gizmo_instance[3], scale_plane_gizmo_instance[3]; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 3534809891..c982207224 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1721,6 +1721,9 @@ void ScriptTextEditor::_enable_code_editor() { color_picker->set_raw_mode(true); } + int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape"); + color_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); + quick_open = memnew(ScriptEditorQuickOpen); quick_open->connect("goto_line", callable_mp(this, &ScriptTextEditor::_goto_line)); add_child(quick_open); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 8f8a4b3054..ed3b746678 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -205,7 +205,7 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptCo ShaderLanguage sl; String calltip; - sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type, r_options, calltip); + sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type, r_options, calltip); get_text_editor()->set_code_hint(calltip); } @@ -219,7 +219,7 @@ void ShaderTextEditor::_validate_script() { ShaderLanguage sl; - Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type); + Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type); if (err != OK) { String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index ad60984ad1..404ef62eca 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -515,6 +515,8 @@ void Skeleton3DEditor::_joint_tree_selection_changed() { rest_editor->set_target(bone_path + "rest"); custom_pose_editor->set_target(bone_path + "custom_pose"); + _update_properties(); + pose_editor->set_visible(true); rest_editor->set_visible(true); custom_pose_editor->set_visible(true); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index b2fa9c540e..e5b8dfd464 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -3398,7 +3398,7 @@ void VisualShaderEditor::_update_preview() { ShaderLanguage sl; - Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type); + Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type); for (int i = 0; i < preview_text->get_line_count(); i++) { preview_text->set_line_as_marked(i, false); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index d3def86bd1..1e79bb81d1 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -296,7 +296,7 @@ private: String sp = _test_path(); if (sp != "") { // If the project name is empty or default, infer the project name from the selected folder name - if (project_name->get_text() == "" || project_name->get_text() == TTR("New Game Project")) { + if (project_name->get_text().strip_edges() == "" || project_name->get_text().strip_edges() == TTR("New Game Project")) { sp = sp.replace("\\", "/"); int lidx = sp.rfind("/"); @@ -380,16 +380,17 @@ private: } void _create_folder() { - if (project_name->get_text() == "" || created_folder_path != "" || project_name->get_text().ends_with(".") || project_name->get_text().ends_with(" ")) { - set_message(TTR("Invalid Project Name."), MESSAGE_WARNING); + const String project_name_no_edges = project_name->get_text().strip_edges(); + if (project_name_no_edges == "" || created_folder_path != "" || project_name_no_edges.ends_with(".")) { + set_message(TTR("Invalid project name."), MESSAGE_WARNING); return; } DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (d->change_dir(project_path->get_text()) == OK) { - if (!d->dir_exists(project_name->get_text())) { - if (d->make_dir(project_name->get_text()) == OK) { - d->change_dir(project_name->get_text()); + if (!d->dir_exists(project_name_no_edges)) { + if (d->make_dir(project_name_no_edges) == OK) { + d->change_dir(project_name_no_edges); String dir_str = d->get_current_dir(); project_path->set_text(dir_str); _path_text_changed(dir_str); @@ -415,7 +416,7 @@ private: _test_path(); - if (p_text == "") { + if (p_text.strip_edges() == "") { set_message(TTR("It would be a good idea to name your project."), MESSAGE_ERROR); } } @@ -442,7 +443,7 @@ private: set_message(vformat(TTR("Couldn't load project.godot in project path (error %d). It may be missing or corrupted."), err), MESSAGE_ERROR); } else { ProjectSettings::CustomMap edited_settings; - edited_settings["application/config/name"] = project_name->get_text(); + edited_settings["application/config/name"] = project_name->get_text().strip_edges(); if (current->save_custom(dir2.plus_file("project.godot"), edited_settings, Vector<String>(), true) != OK) { set_message(TTR("Couldn't edit project.godot in project path."), MESSAGE_ERROR); @@ -483,7 +484,7 @@ private: initial_settings["rendering/textures/vram_compression/import_etc2"] = false; initial_settings["rendering/textures/vram_compression/import_etc"] = true; } - initial_settings["application/config/name"] = project_name->get_text(); + initial_settings["application/config/name"] = project_name->get_text().strip_edges(); initial_settings["application/config/icon"] = "res://icon.png"; initial_settings["rendering/environment/defaults/default_environment"] = "res://default_env.tres"; diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 0a4f432e4a..1a010b9168 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -832,6 +832,9 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (default_color_mode == 2) { color_picker->set_raw_mode(true); } + + int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape"); + color_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); } color_picker->show(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index c62e9cbe5f..5e6ebc22a3 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -3095,6 +3095,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel edit_remote->set_h_size_flags(SIZE_EXPAND_FILL); edit_remote->set_text(TTR("Remote")); edit_remote->set_toggle_mode(true); + edit_remote->set_tooltip(TTR("If selected, the Remote scene tree dock will cause the project to stutter every time it updates.\nSwitch back to the Local scene tree dock to improve performance.")); edit_remote->connect("pressed", callable_mp(this, &SceneTreeDock::_remote_tree_selected)); edit_local = memnew(Button); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index b5e9aec854..ec37fa53b3 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -120,7 +120,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i } undo_redo->commit_action(); } else if (p_id == BUTTON_WARNING) { - String config_err = n->get_configuration_warning(); + String config_err = n->get_configuration_warnings_as_string(); if (config_err == String()) { return; } @@ -252,9 +252,9 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll if (can_rename) { //should be can edit.. - String warning = p_node->get_configuration_warning(); + String warning = p_node->get_configuration_warnings_as_string(); if (!warning.is_empty()) { - item->add_button(0, get_theme_icon("NodeWarning", "EditorIcons"), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + p_node->get_configuration_warning()); + item->add_button(0, get_theme_icon("NodeWarning", "EditorIcons"), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning); } int num_connections = p_node->get_persistent_signal_connection_count(); diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index 3be2136a20..81af4996ed 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -393,9 +393,10 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column TreeItem *ti = Object::cast_to<TreeItem>(p_item); ERR_FAIL_COND(!ti); + button_idx = p_idx; + if (ti->get_metadata(0) == "Common") { // Editing a Built-in action, which can have multiple bindings. - button_idx = p_idx; editing_action = true; current_action = ti->get_text(0); |