diff options
Diffstat (limited to 'editor')
| -rw-r--r-- | editor/code_editor.cpp | 2 | ||||
| -rw-r--r-- | editor/debugger/editor_profiler.cpp | 196 | ||||
| -rw-r--r-- | editor/debugger/editor_profiler.h | 6 | ||||
| -rw-r--r-- | editor/editor_help_search.cpp | 27 | ||||
| -rw-r--r-- | editor/editor_help_search.h | 1 | ||||
| -rw-r--r-- | editor/editor_node.cpp | 30 | ||||
| -rw-r--r-- | editor/editor_plugin.cpp | 5 | ||||
| -rw-r--r-- | editor/editor_plugin.h | 1 | ||||
| -rw-r--r-- | editor/editor_properties.cpp | 3 | ||||
| -rw-r--r-- | editor/editor_themes.cpp | 1 | ||||
| -rw-r--r-- | editor/icons/PickerCursor.svg | 1 | ||||
| -rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 34 | ||||
| -rw-r--r-- | editor/plugins/node_3d_editor_plugin.h | 2 | ||||
| -rw-r--r-- | editor/plugins/script_text_editor.cpp | 3 | ||||
| -rw-r--r-- | editor/plugins/skeleton_3d_editor_plugin.cpp | 2 | ||||
| -rw-r--r-- | editor/project_manager.cpp | 27 | ||||
| -rw-r--r-- | editor/project_manager.h | 4 | ||||
| -rw-r--r-- | editor/property_editor.cpp | 3 | ||||
| -rw-r--r-- | editor/scene_tree_dock.cpp | 1 | ||||
| -rw-r--r-- | editor/scene_tree_editor.cpp | 6 | ||||
| -rw-r--r-- | editor/settings_config_dialog.cpp | 3 | 
21 files changed, 176 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 6a50976908..055baeb81e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -794,17 +794,27 @@ void EditorNode::_fs_changed() {  			}  			preset.unref();  		} +  		if (preset.is_null()) { -			export_error = vformat( -					"Invalid export preset name: %s. Make sure `export_presets.cfg` is present in the current directory.", -					preset_name); +			DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); +			if (da->file_exists("res://export_presets.cfg")) { +				export_error = vformat( +						"Invalid export preset name: %s.\nThe following presets were detected in this project's `export_presets.cfg`:\n\n", +						preset_name); +				for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); ++i) { +					// Write the preset name between double quotes since it needs to be written between quotes on the command line if it contains spaces. +					export_error += vformat("        \"%s\"\n", EditorExport::get_singleton()->get_export_preset(i)->get_name()); +				} +			} else { +				export_error = "This project doesn't have an `export_presets.cfg` file at its root.\nCreate an export preset from the \"Project > Export\" dialog and try again."; +			}  		} else {  			Ref<EditorExportPlatform> platform = preset->get_platform();  			const String export_path = export_defer.path.is_empty() ? preset->get_export_path() : export_defer.path;  			if (export_path.is_empty()) { -				export_error = vformat("Export preset '%s' doesn't have a default export path, and none was specified.", preset_name); +				export_error = vformat("Export preset \"%s\" doesn't have a default export path, and none was specified.", preset_name);  			} else if (platform.is_null()) { -				export_error = vformat("Export preset '%s' doesn't have a matching platform.", preset_name); +				export_error = vformat("Export preset \"%s\" doesn't have a matching platform.", preset_name);  			} else {  				Error err = OK;  				if (export_defer.pack_only) { // Only export .pck or .zip data pack. @@ -817,7 +827,7 @@ void EditorNode::_fs_changed() {  					String config_error;  					bool missing_templates;  					if (!platform->can_export(preset, config_error, missing_templates)) { -						ERR_PRINT(vformat("Cannot export project with preset '%s' due to configuration errors:\n%s", preset_name, config_error)); +						ERR_PRINT(vformat("Cannot export project with preset \"%s\" due to configuration errors:\n%s", preset_name, config_error));  						err = missing_templates ? ERR_FILE_NOT_FOUND : ERR_UNCONFIGURED;  					} else {  						err = platform->export_project(preset, export_defer.debug, export_path); @@ -827,13 +837,13 @@ void EditorNode::_fs_changed() {  					case OK:  						break;  					case ERR_FILE_NOT_FOUND: -						export_error = vformat("Project export failed for preset '%s', the export template appears to be missing.", preset_name); +						export_error = vformat("Project export failed for preset \"%s\". The export template appears to be missing.", preset_name);  						break;  					case ERR_FILE_BAD_PATH: -						export_error = vformat("Project export failed for preset '%s', the target path '%s' appears to be invalid.", preset_name, export_path); +						export_error = vformat("Project export failed for preset \"%s\". The target path \"%s\" appears to be invalid.", preset_name, export_path);  						break;  					default: -						export_error = vformat("Project export failed with error code %d for preset '%s'.", (int)err, preset_name); +						export_error = vformat("Project export failed with error code %d for preset \"%s\".", (int)err, preset_name);  						break;  				}  			} @@ -5882,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/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/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/project_manager.cpp b/editor/project_manager.cpp index 595110f7b3..d3def86bd1 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1031,7 +1031,7 @@ public:  	int get_project_count() const;  	void select_project(int p_index);  	void select_first_visible_project(); -	void erase_selected_projects(); +	void erase_selected_projects(bool p_delete_project_contents);  	Vector<Item> get_selected_projects() const;  	const Set<String> &get_selected_project_keys() const;  	void ensure_project_visible(int p_index); @@ -1686,7 +1686,7 @@ void ProjectList::toggle_select(int p_index) {  	item.control->update();  } -void ProjectList::erase_selected_projects() { +void ProjectList::erase_selected_projects(bool p_delete_project_contents) {  	if (_selected_project_keys.size() == 0) {  		return;  	} @@ -1697,6 +1697,10 @@ void ProjectList::erase_selected_projects() {  			EditorSettings::get_singleton()->erase("projects/" + item.project_key);  			EditorSettings::get_singleton()->erase("favorite_projects/" + item.project_key); +			if (p_delete_project_contents) { +				OS::get_singleton()->move_to_trash(item.path); +			} +  			memdelete(item.control);  			_projects.remove(i);  			--i; @@ -2217,7 +2221,7 @@ void ProjectManager::_rename_project() {  }  void ProjectManager::_erase_project_confirm() { -	_project_list->erase_selected_projects(); +	_project_list->erase_selected_projects(delete_project_contents->is_pressed());  	_update_project_buttons();  } @@ -2235,12 +2239,13 @@ void ProjectManager::_erase_project() {  	String confirm_message;  	if (selected_list.size() >= 2) { -		confirm_message = vformat(TTR("Remove %d projects from the list?\nThe project folders' contents won't be modified."), selected_list.size()); +		confirm_message = vformat(TTR("Remove %d projects from the list?"), selected_list.size());  	} else { -		confirm_message = TTR("Remove this project from the list?\nThe project folder's contents won't be modified."); +		confirm_message = TTR("Remove this project from the list?");  	} -	erase_ask->set_text(confirm_message); +	erase_ask_label->set_text(confirm_message); +	delete_project_contents->set_pressed(false);  	erase_ask->popup_centered();  } @@ -2665,6 +2670,16 @@ ProjectManager::ProjectManager() {  		erase_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_erase_project_confirm));  		add_child(erase_ask); +		VBoxContainer *erase_ask_vb = memnew(VBoxContainer); +		erase_ask->add_child(erase_ask_vb); + +		erase_ask_label = memnew(Label); +		erase_ask_vb->add_child(erase_ask_label); + +		delete_project_contents = memnew(CheckBox); +		delete_project_contents->set_text(TTR("Also delete project contents (no undo!)")); +		erase_ask_vb->add_child(delete_project_contents); +  		multi_open_ask = memnew(ConfirmationDialog);  		multi_open_ask->get_ok_button()->set_text(TTR("Edit"));  		multi_open_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_open_selected_projects)); diff --git a/editor/project_manager.h b/editor/project_manager.h index 49d672a8e5..d13315c022 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -67,7 +67,11 @@ class ProjectManager : public Control {  	FileDialog *scan_dir;  	ConfirmationDialog *language_restart_ask; +  	ConfirmationDialog *erase_ask; +	Label *erase_ask_label; +	CheckBox *delete_project_contents; +  	ConfirmationDialog *erase_missing_ask;  	ConfirmationDialog *multi_open_ask;  	ConfirmationDialog *multi_run_ask; 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); |