diff options
49 files changed, 576 insertions, 220 deletions
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 77decc107d..0eef0ee79f 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -176,6 +176,22 @@ bool FileAccessEncrypted::is_open() const {  	return file != NULL;  } +String FileAccessEncrypted::get_path() const { + +	if (file) +		return file->get_path(); +	else +		return ""; +} + +String FileAccessEncrypted::get_path_absolute() const { + +	if (file) +		return file->get_path_absolute(); +	else +		return ""; +} +  void FileAccessEncrypted::seek(size_t p_position) {  	if (p_position > (size_t)data.size()) diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index d779a150ac..c3be0f7de8 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -60,6 +60,9 @@ public:  	virtual void close(); ///< close a file  	virtual bool is_open() const; ///< true when file is open +	virtual String get_path() const; /// returns the path for the current open file +	virtual String get_path_absolute() const; /// returns the absolute path for the current open file +  	virtual void seek(size_t p_position); ///< seek to a given position  	virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file  	virtual size_t get_position() const; ///< get position in the file diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index cc414c26af..96878c86b4 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -1432,11 +1432,11 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste  				}  			} -			bool clear_skeleton_buffer = !storage->config.float_texture_supported; +			bool clear_skeleton_buffer = storage->config.use_skeleton_software;  			if (p_skeleton) { -				if (storage->config.float_texture_supported) { +				if (!storage->config.use_skeleton_software) {  					//use float texture workflow  					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);  					glBindTexture(GL_TEXTURE_2D, p_skeleton->tex_id); @@ -2452,7 +2452,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,  			if (skeleton) {  				state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, true); -				state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, !storage->config.float_texture_supported); +				state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, storage->config.use_skeleton_software);  			} else {  				state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, false);  				state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, false); diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 5c02d8096d..0379aee561 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -2432,7 +2432,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:  	// from surface->data.  	// if USE_SKELETON_SOFTWARE is active -	if (!config.float_texture_supported) { +	if (config.use_skeleton_software) {  		// if this geometry is used specifically for skinning  		if (p_format & (VS::ARRAY_FORMAT_BONES | VS::ARRAY_FORMAT_WEIGHTS))  			surface->data = array; @@ -3514,7 +3514,7 @@ void RasterizerStorageGLES2::skeleton_allocate(RID p_skeleton, int p_bones, bool  	skeleton->size = p_bones;  	skeleton->use_2d = p_2d_skeleton; -	if (config.float_texture_supported) { +	if (!config.use_skeleton_software) {  		glActiveTexture(GL_TEXTURE0);  		glBindTexture(GL_TEXTURE_2D, skeleton->tex_id); @@ -3699,7 +3699,7 @@ void RasterizerStorageGLES2::_update_skeleton_transform_buffer(const PoolVector<  void RasterizerStorageGLES2::update_dirty_skeletons() { -	if (!config.float_texture_supported) +	if (config.use_skeleton_software)  		return;  	glActiveTexture(GL_TEXTURE0); @@ -5751,9 +5751,14 @@ void RasterizerStorageGLES2::initialize() {  	frame.current_rt = NULL;  	frame.clear_request = false; +	glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &config.max_vertex_texture_image_units);  	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);  	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); +	// the use skeleton software path should be used if either float texture is not supported, +	// OR max_vertex_texture_image_units is zero +	config.use_skeleton_software = (config.float_texture_supported == false) || (config.max_vertex_texture_image_units == 0); +  	shaders.copy.init();  	shaders.cubemap_filter.init();  	bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx"); diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index d139697b86..e6cdcac59f 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -60,7 +60,9 @@ public:  		bool shrink_textures_x2;  		bool use_fast_texture_filter; +		bool use_skeleton_software; +		int max_vertex_texture_image_units;  		int max_texture_image_units;  		int max_texture_size; diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index 195db7c45f..aa967115da 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -144,11 +144,11 @@ void main() {  #elif defined(USE_ASYM_PANO)  	// When an asymmetrical projection matrix is used (applicable for stereoscopic rendering i.e. VR) we need to do this calculation per fragment to get a perspective correct result. -	// Note that we're ignoring the x-offset for IPD, with Z sufficiently in the distance it becomes neglectible, as a result we could probably just set cube_normal.z to -1. +	// Asymmetrical projection means the center of projection is no longer in the center of the screen but shifted.  	// The Matrix[2][0] (= asym_proj.x) and Matrix[2][1] (= asym_proj.z) values are what provide the right shift in the image.  	vec3 cube_normal; -	cube_normal.z = -1000000.0; +	cube_normal.z = -1.0;  	cube_normal.x = (cube_normal.z * (-uv_interp.x - asym_proj.x)) / asym_proj.y;  	cube_normal.y = (cube_normal.z * (-uv_interp.y - asym_proj.z)) / asym_proj.a;  	cube_normal = mat3(sky_transform) * mat3(pano_transform) * cube_normal; diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 6728f60e06..9194da654c 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -929,13 +929,6 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {  				undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, 1);  			} -			// 6-(undo) reinsert overlapped keys -			for (List<AnimMoveRestore>::Element *E = to_restore.front(); E; E = E->next()) { - -				AnimMoveRestore &amr = E->get(); -				undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, 1); -			} -  			undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);  			undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation); diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 2180742bbb..a6328ea50f 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -378,6 +378,7 @@ float EditorAudioBus::_scaled_db_to_normalized_volume(float db) {  void EditorAudioBus::_show_value(float slider_value) {  	String text = vformat("%10.1f dB", _normalized_volume_to_scaled_db(slider_value)); +	slider->set_tooltip(text);  	audio_value_preview_label->set_text(text);  	Vector2 slider_size = slider->get_size();  	Vector2 slider_position = slider->get_global_position(); @@ -773,7 +774,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {  	is_master = p_is_master;  	hovering_drop = false; -	set_tooltip(TTR("Audio Bus, Drag and Drop to rearrange.")); +	set_tooltip(TTR("Drag & drop to rearrange."));  	VBoxContainer *vb = memnew(VBoxContainer);  	add_child(vb); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index e6df00b48c..24ed0ecfd0 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -30,6 +30,7 @@  #include "editor_help.h" +#include "core/os/input.h"  #include "core/os/keyboard.h"  #include "doc_data_compressed.gen.h"  #include "editor/plugins/script_editor_plugin.h" @@ -1807,5 +1808,9 @@ void FindBar::_search_text_changed(const String &p_text) {  void FindBar::_search_text_entered(const String &p_text) { -	search_next(); +	if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { +		search_prev(); +	} else { +		search_next(); +	}  } diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index af79c21f85..27e61362ed 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -338,10 +338,15 @@ bool EditorHelpSearch::Runner::_phase_match_classes() {  			if (search_flags & SEARCH_METHODS)  				for (int i = 0; i < class_doc.methods.size(); i++) {  					String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower(); -					if (method_name.find(term) > -1 || -							(term.begins_with(".") && method_name.begins_with(term.right(1))) || -							(term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) || -							(term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) +					String aux_term = (search_flags & SEARCH_CASE_SENSITIVE) ? term : term.to_lower(); + +					if (aux_term.begins_with(".")) +						aux_term = aux_term.right(1); + +					if (aux_term.ends_with("(")) +						aux_term = aux_term.left(aux_term.length() - 1).strip_edges(); + +					if (aux_term.is_subsequence_of(method_name))  						match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i]));  				}  			if (search_flags & SEARCH_SIGNALS) @@ -431,9 +436,9 @@ bool EditorHelpSearch::Runner::_phase_select_match() {  bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String &p_string) const {  	if (search_flags & SEARCH_CASE_SENSITIVE) -		return p_string.find(p_term) > -1; +		return p_term.is_subsequence_of(p_string);  	else -		return p_string.findn(p_term) > -1; +		return p_term.is_subsequence_ofi(p_string);  }  void EditorHelpSearch::Runner::_match_item(TreeItem *p_item, const String &p_text) { diff --git a/editor/editor_network_profiler.cpp b/editor/editor_network_profiler.cpp index b90fe96cee..8482c4e38a 100644 --- a/editor/editor_network_profiler.cpp +++ b/editor/editor_network_profiler.cpp @@ -43,9 +43,15 @@ void EditorNetworkProfiler::_bind_methods() {  void EditorNetworkProfiler::_notification(int p_what) { -	if (p_what == NOTIFICATION_ENTER_TREE) { +	if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {  		activate->set_icon(get_icon("Play", "EditorIcons"));  		clear_button->set_icon(get_icon("Clear", "EditorIcons")); +		incoming_bandwidth_text->set_right_icon(get_icon("ArrowDown", "EditorIcons")); +		outgoing_bandwidth_text->set_right_icon(get_icon("ArrowUp", "EditorIcons")); + +		// This needs to be done here to set the faded color when the profiler is first opened +		incoming_bandwidth_text->add_color_override("font_color_uneditable", get_color("font_color", "Editor") * Color(1, 1, 1, 0.5)); +		outgoing_bandwidth_text->add_color_override("font_color_uneditable", get_color("font_color", "Editor") * Color(1, 1, 1, 0.5));  	}  } @@ -113,6 +119,14 @@ void EditorNetworkProfiler::set_bandwidth(int p_incoming, int p_outgoing) {  	incoming_bandwidth_text->set_text(vformat(TTR("%s/s"), String::humanize_size(p_incoming)));  	outgoing_bandwidth_text->set_text(vformat(TTR("%s/s"), String::humanize_size(p_outgoing))); + +	// Make labels more prominent when the bandwidth is greater than 0 to attract user attention +	incoming_bandwidth_text->add_color_override( +			"font_color_uneditable", +			get_color("font_color", "Editor") * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5)); +	outgoing_bandwidth_text->add_color_override( +			"font_color_uneditable", +			get_color("font_color", "Editor") * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5));  }  bool EditorNetworkProfiler::is_profiling() { @@ -139,27 +153,32 @@ EditorNetworkProfiler::EditorNetworkProfiler() {  	hb->add_spacer();  	Label *lb = memnew(Label); -	lb->set_text("Down "); +	lb->set_text(TTR("Down"));  	hb->add_child(lb);  	incoming_bandwidth_text = memnew(LineEdit);  	incoming_bandwidth_text->set_editable(false); -	incoming_bandwidth_text->set_custom_minimum_size(Size2(100, 0)); +	incoming_bandwidth_text->set_custom_minimum_size(Size2(120, 0) * EDSCALE);  	incoming_bandwidth_text->set_align(LineEdit::Align::ALIGN_RIGHT); -	incoming_bandwidth_text->set_text("0.0 B/s");  	hb->add_child(incoming_bandwidth_text); +	Control *down_up_spacer = memnew(Control); +	down_up_spacer->set_custom_minimum_size(Size2(30, 0) * EDSCALE); +	hb->add_child(down_up_spacer); +  	lb = memnew(Label); -	lb->set_text("Up "); +	lb->set_text(TTR("Up"));  	hb->add_child(lb);  	outgoing_bandwidth_text = memnew(LineEdit);  	outgoing_bandwidth_text->set_editable(false); -	outgoing_bandwidth_text->set_custom_minimum_size(Size2(100, 0)); +	outgoing_bandwidth_text->set_custom_minimum_size(Size2(120, 0) * EDSCALE);  	outgoing_bandwidth_text->set_align(LineEdit::Align::ALIGN_RIGHT); -	outgoing_bandwidth_text->set_text("0.0 B/s");  	hb->add_child(outgoing_bandwidth_text); +	// Set initial texts in the incoming/outgoing bandwidth labels +	set_bandwidth(0, 0); +  	counters_display = memnew(Tree);  	counters_display->set_custom_minimum_size(Size2(300, 0) * EDSCALE);  	counters_display->set_v_size_flags(SIZE_EXPAND_FILL); @@ -169,7 +188,7 @@ EditorNetworkProfiler::EditorNetworkProfiler() {  	counters_display->set_column_titles_visible(true);  	counters_display->set_column_title(0, TTR("Node"));  	counters_display->set_column_expand(0, true); -	counters_display->set_column_min_width(0, 60); +	counters_display->set_column_min_width(0, 60 * EDSCALE);  	counters_display->set_column_title(1, TTR("Incoming RPC"));  	counters_display->set_column_expand(1, false);  	counters_display->set_column_min_width(1, 120 * EDSCALE); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 30fb561fbe..f456cf7233 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -922,16 +922,29 @@ EditorPropertyFloat::EditorPropertyFloat() {  void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { -	Ref<InputEventMouseButton> mb = p_ev; -	if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { -		preset->set_global_position(easing_draw->get_global_transform().xform(mb->get_position())); -		preset->popup(); -	} -	if (mb.is_valid() && mb->is_doubleclick() && mb->get_button_index() == BUTTON_LEFT) { -		_setup_spin(); +	const Ref<InputEventMouseButton> mb = p_ev; +	if (mb.is_valid()) { +		if (mb->is_doubleclick() && mb->get_button_index() == BUTTON_LEFT) { +			_setup_spin(); +		} + +		if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { +			preset->set_global_position(easing_draw->get_global_transform().xform(mb->get_position())); +			preset->popup(); + +			// Ensure the easing doesn't appear as being dragged +			dragging = false; +			easing_draw->update(); +		} + +		if (mb->get_button_index() == BUTTON_LEFT) { +			dragging = mb->is_pressed(); +			// Update to display the correct dragging color +			easing_draw->update(); +		}  	} -	Ref<InputEventMouseMotion> mm = p_ev; +	const Ref<InputEventMouseMotion> mm = p_ev;  	if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { @@ -969,13 +982,19 @@ void EditorPropertyEasing::_draw_easing() {  	Rect2 r(Point2(), s);  	r = r.grow(3); -	int points = 48; +	const int points = 48;  	float prev = 1.0; -	float exp = get_edited_object()->get(get_edited_property()); +	const float exp = get_edited_object()->get(get_edited_property()); -	Ref<Font> f = get_font("font", "Label"); -	Color color = get_color("font_color", "Label"); +	const Ref<Font> f = get_font("font", "Label"); +	const Color font_color = get_color("font_color", "Label"); +	Color line_color; +	if (dragging) { +		line_color = get_color("accent_color", "Editor"); +	} else { +		line_color = get_color("font_color", "Label") * Color(1, 1, 1, 0.9); +	}  	Vector<Point2> lines;  	for (int i = 1; i <= points; i++) { @@ -983,7 +1002,7 @@ void EditorPropertyEasing::_draw_easing() {  		float ifl = i / float(points);  		float iflp = (i - 1) / float(points); -		float h = 1.0 - Math::ease(ifl, exp); +		const float h = 1.0 - Math::ease(ifl, exp);  		if (flip) {  			ifl = 1.0 - ifl; @@ -995,8 +1014,8 @@ void EditorPropertyEasing::_draw_easing() {  		prev = h;  	} -	easing_draw->draw_multiline(lines, color, 1.0, true); -	f->draw(ci, Point2(10, 10 + f->get_ascent()), String::num(exp, 2), color); +	easing_draw->draw_multiline(lines, line_color, 1.0, true); +	f->draw(ci, Point2(10, 10 + f->get_ascent()), String::num(exp, 2), font_color);  }  void EditorPropertyEasing::update_property() { @@ -1033,6 +1052,9 @@ void EditorPropertyEasing::_spin_value_changed(double p_value) {  void EditorPropertyEasing::_spin_focus_exited() {  	spin->hide(); +	// Ensure the easing doesn't appear as being dragged +	dragging = false; +	easing_draw->update();  }  void EditorPropertyEasing::setup(bool p_full, bool p_flip) { @@ -1095,6 +1117,7 @@ EditorPropertyEasing::EditorPropertyEasing() {  	spin->hide();  	add_child(spin); +	dragging = false;  	flip = false;  	full = false;  } diff --git a/editor/editor_properties.h b/editor/editor_properties.h index adf7779dc4..b8d6aa00c2 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -311,6 +311,7 @@ class EditorPropertyEasing : public EditorProperty {  	EditorSpinSlider *spin;  	bool setting; +	bool dragging;  	bool full;  	bool flip; diff --git a/editor/icons/icon_arrow_down.svg b/editor/icons/icon_arrow_down.svg new file mode 100644 index 0000000000..49a93e6e28 --- /dev/null +++ b/editor/icons/icon_arrow_down.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3.002a1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l2.293 2.293h-4.5859c-.55228 0-1 .4477-1 1s.44772 1 1 1h4.5859l-2.293 2.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l4-4a1.0001 1.0001 0 0 0 0-1.4141l-4-4a1 1 0 0 0 -.7207-.29102z" fill="#e0e0e0" fill-opacity=".99608" transform="matrix(0 1 -1 0 16.0021 -.00004)"/></svg>
\ No newline at end of file diff --git a/editor/icons/icon_arrow_up.svg b/editor/icons/icon_arrow_up.svg new file mode 100644 index 0000000000..9bf19a6a12 --- /dev/null +++ b/editor/icons/icon_arrow_up.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.00008 1049.4022a1 1 0 0 0 .69336-.291 1 1 0 0 0 0-1.4141l-2.293-2.293h4.5859c.55228 0 1-.4477 1-1s-.44772-1-1-1h-4.5859l2.293-2.293a1 1 0 0 0 0-1.4141 1 1 0 0 0 -1.4141 0l-4 4a1.0001 1.0001 0 0 0 0 1.4141l4 4a1 1 0 0 0 .7207.291z" fill="#e0e0e0" fill-opacity=".99608" transform="matrix(0 1 -1 0 1052.4021 -.00004)"/></svg>
\ No newline at end of file diff --git a/editor/icons/icon_bus_vu_db.svg b/editor/icons/icon_bus_vu_db.svg deleted file mode 100644 index 236e41e1f5..0000000000 --- a/editor/icons/icon_bus_vu_db.svg +++ /dev/null @@ -1,12 +0,0 @@ -<svg width="32" height="128" version="1.1" viewBox="0 0 32 128" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<defs> -<linearGradient id="a" x1="16" x2="16" y2="128" gradientUnits="userSpaceOnUse"> -<stop stop-color="#ff7a7a" offset="0"/> -<stop stop-color="#e1dc7a" offset=".5"/> -<stop stop-color="#66ff9e" offset="1"/> -</linearGradient> -</defs> -<g transform="translate(0 -924.36)"> -<path transform="translate(0 924.36)" d="m1.5 0c-0.831 0-1.5 0.669-1.5 1.5 0 0.831 0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5 0-0.831-0.669-1.5-1.5-1.5h-2zm0 7c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm22.5 3.75c-1.5 0-3 1.3056-3 3.25-0.01912 1.3523 2.0191 1.3523 2 0 0-1.0556 0.5-1.25 1-1.25s1 0.19444 1 1.25c0 0.59157-0.35893 1.156-1.1914 1.8633-0.83248 0.70724-2.0616 1.4518-3.3574 2.3008-0.82974 0.54516-0.44398 1.8356 0.54883 1.8359h5c1.3523 0.01912 1.3523-2.0191 0-2h-1.7852c0.28375-0.20667 0.63106-0.39443 0.88867-0.61328 1.0302-0.87519 1.8965-1.9783 1.8965-3.3867 0-1.9444-1.5-3.25-3-3.25zm-7.0293 0.25195c-0.14519 0.0037-0.28782 0.03907-0.41797 0.10352l-2 1c-1.1924 0.59646-0.29787 2.3855 0.89453 1.7891l0.55273-0.27539v5.3809c-0.01913 1.3523 2.0191 1.3523 2 0v-7c-9.16e-4 -0.56314-0.4664-1.0145-1.0293-0.99805zm-15.471 2.998c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm0 7c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm21.5 3c-0.554 0-1 0.446-1 1v1 2h-0.92969c-0.02343-8.24e-4 -0.046882-8.24e-4 -0.070312 0-1.0702 0-2.0626 0.57318-2.5977 1.5-0.5351 0.92681-0.5351 2.0732 0 3 0.5351 0.92681 1.5275 1.5 2.5977 1.5h2c0.554 0 1-0.446 1-1v-8c0-0.554-0.446-1-1-1zm4 0c-0.554 0-1 0.446-1 1v8c0 0.554 0.446 1 1 1h2c1.0702 0 2.0626-0.57319 2.5977-1.5 0.5351-0.92682 0.5351-2.0732 0-3-0.10504-0.18193-0.23173-0.34698-0.36914-0.5 0.1378-0.15331 0.26385-0.31764 0.36914-0.5 0.5351-0.92682 0.5351-2.0732 0-3-0.5351-0.92682-1.5275-1.5-2.5977-1.5h-2zm-14 1c-1.6447 0-3 1.3553-3 3v3c0 1.6447 1.3553 3 3 3s3-1.3553 3-3v-3c0-1.6447-1.3553-3-3-3zm15 1h1c0.35887 0 0.6858 0.18921 0.86523 0.5 0.17944 0.31079 0.17944 0.68921 0 1-0.17943 0.31079-0.50636 0.5-0.86523 0.5h-0.070312-0.92969v-2zm-15 1c0.5713 0 1 0.4287 1 1v3c0 0.5713-0.4287 1-1 1s-1-0.4287-1-1v-3c0-0.5713 0.4287-1 1-1zm-11.5 1c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm19.5 2h1v2h-0.92969c-0.02343-8.24e-4 -0.046882-8.24e-4 -0.070312 0-0.35887 0-0.6858-0.18921-0.86523-0.5-0.17944-0.31079-0.17944-0.68921 0-1 0.17943-0.31079 0.50636-0.5 0.86523-0.5zm7 0h1c0.35887 0 0.6858 0.18921 0.86523 0.5 0.17944 0.31079 0.17944 0.68921 0 1-0.17943 0.31079-0.50636 0.5-0.86523 0.5h-1v-2zm-26.5 5c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm22.5 2.75c-1.5 0-3 1.3056-3 3.25-0.01912 1.3523 2.0191 1.3523 2 0 0-1.0556 0.5-1.25 1-1.25s1 0.19444 1 1.25c0 0.59157-0.35893 1.156-1.1914 1.8633-0.83248 0.70724-2.0616 1.4518-3.3574 2.3008-0.82974 0.54516-0.44398 1.8356 0.54883 1.8359h5c1.3523 0.01913 1.3523-2.0191 0-2h-1.7852c0.28375-0.20667 0.63106-0.39443 0.88867-0.61328 1.0302-0.87519 1.8965-1.9783 1.8965-3.3867 0-1.9444-1.5-3.25-3-3.25zm-7.0293 0.25195c-0.14519 0.0037-0.28782 0.03907-0.41797 0.10352l-2 1c-1.1924 0.59646-0.29787 2.3855 0.89453 1.7891l0.55273-0.27539v5.3809c-0.01913 1.3523 2.0191 1.3523 2 0v-7c-9.16e-4 -0.56314-0.4664-1.0145-1.0293-0.99805zm-15.471 3.998c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 1v2h3v-2h-3zm-7 6c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm15.986 3.75c-1.5 0-3 1.3056-3 3.25-0.01913 1.3523 2.0191 1.3523 2 0 0-1.0556 0.5-1.25 1-1.25s1 0.19444 1 1.25c0 0.59157-0.35893 1.156-1.1914 1.8633s-2.0616 1.4518-3.3574 2.3008c-0.82974 0.54516-0.44398 1.8356 0.54883 1.8359h5c1.3523 0.01913 1.3523-2.0191 0-2h-1.7871c0.2841-0.20689 0.63273-0.39419 0.89062-0.61328 1.0302-0.87519 1.8965-1.9783 1.8965-3.3867 0-1.9444-1.5-3.25-3-3.25zm7.0469 0.23828c-0.36561-0.0093-0.70715 0.18167-0.89062 0.49805l-3 5c-0.39877 0.66633 0.080888 1.5131 0.85742 1.5137h3v1c-0.01912 1.3523 2.0191 1.3523 2 0v-2c-5.5e-5 -0.55226-0.44774-0.99994-1-1h-2.2324l2.0898-3.4844c0.40768-0.65656-0.05163-1.5077-0.82422-1.5273zm-23.533 3.0117c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 2v2h3v-2h-3zm-7.5 5c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm24.547 4.9961c-0.12355-0.0037-0.24673 0.01547-0.36328 0.05664 0 0-0.98349 0.3331-1.8906 1.2402-0.90714 0.90717-1.793 2.457-1.793 4.707-6.13e-4 0.07218 0.006604 0.14421 0.021484 0.21484 0.11389 1.5445 1.4072 2.7852 2.9785 2.7852 1.645 0 3-1.355 3-3 0-1.645-1.355-3-3-3-0.01533 0-0.029642 0.003706-0.044922 0.003906 0.084-0.10099 0.16695-0.21188 0.25195-0.29688 0.59286-0.59287 1.1094-0.75781 1.1094-0.75781 1.0726-0.33926 0.85487-1.9171-0.26953-1.9531zm-9.0605 0.005859c-1.0407 0.006928-2.0405 0.55674-2.584 1.498a1 1 0 0 0 0.36523 1.3672 1 1 0 0 0 1.3672 -0.36719c0.24596-0.42602 0.74477-0.6077 1.207-0.43945 0.46226 0.16824 0.728 0.62882 0.64258 1.1133-0.085422 0.48445-0.49245 0.82617-0.98438 0.82617a1 1 0 0 0 -1 1 1 1 0 0 0 1 1c0.49193 0 0.89896 0.34368 0.98438 0.82812 0.085422 0.48446-0.18032 0.94508-0.64258 1.1133-0.46226 0.1683-0.96107-0.015436-1.207-0.44141-0.27644-0.47871-0.88884-0.6423-1.3672-0.36523-0.47752 0.27639-0.64095 0.88733-0.36523 1.3652 0.72462 1.2553 2.2612 1.816 3.623 1.3203 1.3618-0.4956 2.1813-1.9126 1.9297-3.3398-0.1003-0.56884-0.37254-1.0676-0.74023-1.4746 0.37098-0.40777 0.63937-0.91234 0.74023-1.4844 0.25166-1.4272-0.56786-2.8442-1.9297-3.3398-0.34046-0.12392-0.69218-0.182-1.0391-0.17969zm-15.486 1.998c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 2v2h3v-2h-3zm16 1c0.56413 0 1 0.43587 1 1s-0.43587 1-1 1-1-0.43587-1-1 0.43587-1 1-1zm-23.5 4c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm16.533 3.9883c-0.36561-0.0093-0.70715 0.18167-0.89062 0.49805l-3 5c-0.39877 0.66633 0.080888 1.5131 0.85742 1.5137h3v1c-0.01912 1.3523 2.0191 1.3523 2 0v-2c-5.5e-5 -0.55226-0.44774-0.99994-1-1h-2.2324l2.0898-3.4844c0.40768-0.65656-0.05163-1.5077-0.82422-1.5273zm6.9668 0.011719c-1.645 0-3 1.355-3 3 0 0.769 0.30369 1.4666 0.78711 2-0.48282 0.53332-0.78711 1.2315-0.78711 2 0 1.645 1.355 3 3 3s3-1.355 3-3c0-0.76846-0.30429-1.4667-0.78711-2 0.48342-0.53345 0.78711-1.231 0.78711-2 0-1.645-1.355-3-3-3zm0 2c0.56413 0 1 0.4359 1 1 0 0.5642-0.43587 1-1 1s-1-0.4358-1-1c0-0.5641 0.43587-1 1-1zm-23.5 1c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 2v2h3v-2h-3zm16 1c0.56413 0 1 0.4359 1 1 0 0.5642-0.43587 1-1 1s-1-0.4358-1-1c0-0.5641 0.43587-1 1-1zm-23.5 4c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm16.447 3.9824c-0.08995 0.0063-0.17865 0.024647-0.26367 0.054687 0 0-0.98349 0.33509-1.8906 1.2422-0.90714 0.9068-1.793 2.457-1.793 4.707-6.13e-4 0.0722 0.006604 0.14421 0.021484 0.21484 0.11389 1.5445 1.4072 2.7852 2.9785 2.7852 1.645 0 3-1.355 3-3 0-1.6451-1.355-3-3-3-0.01533 0-0.029642 0.003706-0.044922 0.003906 0.084-0.10099 0.16695-0.21187 0.25195-0.29688 0.59286-0.5929 1.1094-0.75781 1.1094-0.75781 1.0726-0.33926 0.85487-1.9171-0.26953-1.9531-0.03318-0.0017-0.066429-0.0017-0.099609 0zm7.0527 0.017578c-1.6447 0-3 1.3553-3 3v3c0 1.6447 1.3553 3 3 3s3-1.3553 3-3v-3c0-1.6447-1.3553-3-3-3zm0 2c0.5713 0 1 0.4287 1 1v3c0 0.5713-0.4287 1-1 1s-1-0.4287-1-1v-3c0-0.5713 0.4287-1 1-1zm-23.5 1c-0.831 0-1.5 0.669-1.5 1.5 0 0.831 0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5 0-0.831-0.669-1.5-1.5-1.5h-2zm15.5 1.9863c0.56413 0 1 0.4358 1 1 0 0.5641-0.43587 1-1 1s-1-0.4359-1-1c0-0.5642 0.43587-1 1-1zm-8 0.013672v2h3v-2h-3zm-7.5 5c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm22.5 3.75c-1.5 0-3 1.3056-3 3.25-0.01912 1.3523 2.0191 1.3523 2 0 0-1.0555 0.5-1.25 1-1.25s1 0.1945 1 1.25c0 0.5916-0.35893 1.1561-1.1914 1.8633-0.83248 0.7072-2.0616 1.4518-3.3574 2.3008-0.82975 0.54515-0.44398 1.8356 0.54883 1.8359h5c1.3523 0.0191 1.3523-2.0191 0-2h-1.7852c0.28375-0.2066 0.63106-0.39438 0.88867-0.61328 1.0302-0.8751 1.8965-1.9782 1.8965-3.3867 0-1.9444-1.5-3.25-3-3.25zm-10 0.25c-1.3523-0.0191-1.3523 2.0191 0 2h3.3828l-3.2773 6.5527c-0.59596 1.1926 1.1931 2.0871 1.7891 0.89454l4-8c0.33239-0.66495-0.15113-1.4472-0.89453-1.4473h-5zm-12.5 3c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 2v2h3v-2h-3zm-7.5 5c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5z" fill="url(#a)"/> -</g> -</svg> diff --git a/editor/icons/icon_camera_texture.svg b/editor/icons/icon_camera_texture.svg new file mode 100644 index 0000000000..5629487451 --- /dev/null +++ b/editor/icons/icon_camera_texture.svg @@ -0,0 +1,5 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0,1036.4)" d="m2 1c-0.55228 0-1 0.44772-1 1v12c0 0.55228 0.44772 1 1 1h12c0.55228 0 1-0.44772 1-1v-12c0-0.55228-0.44772-1-1-1h-12zm1 2h10v8h-10v-8zm5.8184 1.0039c-0.85534 9.758e-4 -1.5654 0.66069-1.6289 1.5137-0.30036-0.27229-0.69029-0.4234-1.0957-0.42383-0.90315 0-1.6367 0.73162-1.6367 1.6348 9.732e-4 0.69217 0.43922 1.3103 1.0918 1.541v1.1855c0 0.30198 0.24293 0.54492 0.54492 0.54492h3.2695c0.30199 0 0.54492-0.24294 0.54492-0.54492v-0.54492l1.6367 1.0898v-3.2715l-1.6367 1.0918v-0.96484c0.34606-0.30952 0.54406-0.75251 0.54492-1.2168 0-0.90315-0.73162-1.6348-1.6348-1.6348z" fill="#e0e0e0" fill-opacity=".99608"/> +</g> +</svg> diff --git a/editor/icons/icon_clipped_camera.svg b/editor/icons/icon_clipped_camera.svg new file mode 100644 index 0000000000..dd26abc638 --- /dev/null +++ b/editor/icons/icon_clipped_camera.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m6.5 12v4h3v-1h-2v-3zm-1 0h-2c-0.5 0-1 0.5-1 1v2c-0.01829 0.53653 0.5 1 1 1h2v-1h-2v-2h2zm4-12c-1.5691 0.0017903-2.8718 1.2125-2.9883 2.7773-0.55103-0.49952-1.268-0.77655-2.0117-0.77734-1.6569 0-3 1.3431-3 3 0.00179 1.2698 0.80282 2.4009 2 2.8242v2.1758c0 0.554 0.44599 1 1 1h6c0.55401 0 1-0.446 1-1v-1l3 2v-6l-3 2v-1.7695c0.63486-0.56783 0.99842-1.3788 1-2.2305 0-1.6569-1.3431-3-3-3zm1 12v4h1v-1h1c0.55228 0 1-0.44772 1-1v-1c0-0.55228-0.44775-0.99374-1-1h-1zm1 1h1v1h-1z" fill="#fc9c9c"/> +</svg> diff --git a/editor/icons/icon_height_map_shape.svg b/editor/icons/icon_height_map_shape.svg new file mode 100644 index 0000000000..09d129a273 --- /dev/null +++ b/editor/icons/icon_height_map_shape.svg @@ -0,0 +1,12 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<defs> +<linearGradient id="a" x1="8" x2="8" y1="8" y2="11" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68b6ff" offset="0"/> +<stop stop-color="#a2d2ff" offset="1"/> +</linearGradient> +</defs> +<g transform="translate(0,-1)"> +<path transform="translate(0,-1033.4)" d="m1 1044.4 7 3 7-3-7-3z" fill="#a2d2ff" fill-rule="evenodd"/> +<path d="m3 11c1-1 2-2 2-4s1-3 3-3 3 1 3 3 1 3 2 4z" fill="url(#a)"/> +</g> +</svg> diff --git a/editor/icons/icon_interpolated_camera.svg b/editor/icons/icon_interpolated_camera.svg index 7a33c64ca2..24b4832105 100644 --- a/editor/icons/icon_interpolated_camera.svg +++ b/editor/icons/icon_interpolated_camera.svg @@ -1,5 +1,5 @@  <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">  <g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m9 0a3 3 0 0 0 -2.9883 2.7773 3 3 0 0 0 -2.0117 -0.77734 3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8242v2.1758c0 0.554 0.44599 1 1 1h6c0.55401 0 1-0.446 1-1v-1l3 2v-6l-3 2v-1.7695a3 3 0 0 0 1 -2.2305 3 3 0 0 0 -3 -3zm-6 12v4h1v-4h-1zm3 0v4h1v-1h1a1 1 0 0 0 1 -1v-1a1 1 0 0 0 -1 -1h-1-1zm5 0a1 1 0 0 0 -1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1 -1v-2a1 1 0 0 0 -1 -1h-1zm-4 1h1v1h-1v-1zm4 0h1v2h-1v-2z" fill="#fc9c9c"/> +<path transform="translate(0,1036.4)" d="m9.5 4e-5c-1.5691 0.0017903-2.8718 1.2125-2.9883 2.7773-0.55103-0.49952-1.268-0.77655-2.0117-0.77734-1.6569 0-3 1.3431-3 3 0.00179 1.2698 0.80282 2.4009 2 2.8242v2.1758c0 0.554 0.44599 1 1 1h6c0.55401 0 0.9853-0.4462 1-1v-1l3 2v-6l-3 2v-1.7695c0.63486-0.56783 0.99842-1.3788 1-2.2305 0-1.6569-1.3431-3-3-3zm-6 12v4h1v-4zm3 0v4h1v-1h1c0.55228 0 1-0.44772 1-1v-1c0-0.55228-0.44824-1.024-1-1h-1zm5 0c-0.55228 0-1 0.44772-1 1v2c0 0.55228 0.44772 1 1 1h1c0.55228 0 1-0.44772 1-1v-2c0-0.55228-0.44772-1-1-1zm-4 1h1v1h-1zm4 0h1v2h-1z" fill="#fc9c9c"/>  </g>  </svg> diff --git a/editor/icons/icon_mesh_texture.svg b/editor/icons/icon_mesh_texture.svg new file mode 100644 index 0000000000..a877877c36 --- /dev/null +++ b/editor/icons/icon_mesh_texture.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m3 1c-1.1046 0-2 0.89543-2 2 5.649e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35663-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.65e-4 1.3735-0.38169 1.7305-1h6.541c0.35663 0.61771 1.0152 0.99874 1.7285 1 1.1046 0 2-0.89543 2-2 1.01e-4 -0.72747-0.39481-1.3976-1.0312-1.75h0.03125v-6.5215c0.61771-0.35663 0.99874-1.0152 1-1.7285 0-1.1046-0.89543-2-2-2-0.71397 5.648e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35663-0.61771-1.0152-0.99874-1.7285-1zm1.7266 3h0.6875 5.168 0.68945c0.17478 0.30301 0.42598 0.55488 0.72852 0.73047v0.68359 5.1719 0.68555c-0.30301 0.17478-0.55488 0.42598-0.73047 0.72852h-0.68359-5.1719-0.68555c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-0.6875l-0.0039062 0.003907v-5.8574c0.30302-0.17478 0.55488-0.42598 0.73047-0.72852zm4.0859 2.25v0.70117h-0.8125v0.69922h-1.625v0.69922h-0.8125v0.69922h-0.8125v0.70117h1.625 1.625 1.625 1.625v-1.4004h-0.8125v-1.3984h-0.8125v-0.70117h-0.8125z" fill="#e0e0e0" fill-opacity=".99608"/> +</svg> diff --git a/editor/icons/icon_rich_text_effect.svg b/editor/icons/icon_rich_text_effect.svg new file mode 100644 index 0000000000..c2705ad8c4 --- /dev/null +++ b/editor/icons/icon_rich_text_effect.svg @@ -0,0 +1,6 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<g> +<path d="m1 1v2h7v-2zm9 0v2h5v-2zm-9 4v2h11v-2zm0 4v2h4v-2zm6 0v2h1c-0.044949-0.094701-0.088906-0.20229-0.125-0.3418-0.077717-0.30039-0.10439-0.81722 0.16406-1.293 0.081489-0.1441 0.18202-0.26127 0.28906-0.36523zm-6 4v2h8.2812c-0.066517-0.011548-0.1231-0.014758-0.20117-0.037109-0.30195-0.08645-0.76491-0.33245-1.0352-0.80664-0.23366-0.4121-0.24101-0.84933-0.18945-1.1562z" fill="#e0e0e0"/> +<path d="m12.216 8.598a0.53334 3.2001 0 0 0-0.50976 2.2754 3.2001 0.53334 30 0 0-2.2656-0.71484 3.2001 0.53334 30 0 0 1.75 1.6016 0.53334 3.2001 60 0 0-1.7461 1.5996 0.53334 3.2001 60 0 0 2.2578-0.71094 0.53334 3.2001 0 0 0 0.51367 2.3496 0.53334 3.2001 0 0 0 0.51367-2.3516 3.2001 0.53334 30 0 0 2.2539 0.71094 3.2001 0.53334 30 0 0-1.7441-1.5977 0.53334 3.2001 60 0 0 1.748-1.5996 0.53334 3.2001 60 0 0-2.2617 0.71484 0.53334 3.2001 0 0 0-0.50977-2.2773z" fill="#cea4f1" stroke-width="1.0667"/> +</g> +</svg> diff --git a/editor/icons/icon_skeleton_i_k.svg b/editor/icons/icon_skeleton_i_k.svg new file mode 100644 index 0000000000..851023ab4d --- /dev/null +++ b/editor/icons/icon_skeleton_i_k.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m6 2a4 4 0 0 0-4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 0.26562v0.001953h4v-0.001953a2 2 0 0 0 1-0.26562 2 2 0 0 0 1-1.7324v-3.5469a4 4 0 0 0 2-3.4531 4 4 0 0 0-4-4h-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm-4 2h2v1h-2v-1zm-2 2h1v1h1v-1h1 1v1h1v-1h1v0.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-0.86914z" fill="#e0e0e0"/> +</svg> diff --git a/editor/icons/icon_soft_body.svg b/editor/icons/icon_soft_body.svg index 9930026b61..2c907df847 100644 --- a/editor/icons/icon_soft_body.svg +++ b/editor/icons/icon_soft_body.svg @@ -1,56 +1 @@ -<?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="16" -   height="16" -   version="1.1" -   viewBox="0 0 16 16" -   id="svg2" -   inkscape:version="0.91 r13725" -   sodipodi:docname="icon_soft_body.svg"> -  <metadata -     id="metadata14"> -    <rdf:RDF> -      <cc:Work -         rdf:about=""> -        <dc:format>image/svg+xml</dc:format> -        <dc:type -           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> -      </cc:Work> -    </rdf:RDF> -  </metadata> -  <defs -     id="defs12" /> -  <sodipodi:namedview -     pagecolor="#ffffff" -     bordercolor="#666666" -     borderopacity="1" -     objecttolerance="10" -     gridtolerance="10" -     guidetolerance="10" -     inkscape:pageopacity="0" -     inkscape:pageshadow="2" -     inkscape:window-width="1920" -     inkscape:window-height="1027" -     id="namedview10" -     showgrid="false" -     inkscape:zoom="18.792233" -     inkscape:cx="2.8961304" -     inkscape:cy="4.3816933" -     inkscape:window-x="-8" -     inkscape:window-y="-8" -     inkscape:window-maximized="1" -     inkscape:current-layer="svg2" /> -  <path -     style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;fill-rule:nonzero;stroke:none;stroke-width:1.42799997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" -     d="m 2.3447105,1.6091897 c -0.011911,1.9816766 -1.4168958,3.9344766 0,5.9495986 1.4168957,2.0151221 0,6.6693597 0,6.6693597 l 10.9510055,0 c 0,0 1.780829,-4.4523824 0,-6.489075 -1.780829,-2.0366925 -0.183458,-4.119112 0,-6.1298833 z m 1.8894067,0.7549031 7.4390658,0 c -0.431995,1.5996085 -1.62289,4.0426807 0,5.3749802 1.622888,1.3322996 0,5.887932 0,5.887932 l -7.4390658,0 c 0,0 1.3903413,-4.3680495 0,-5.9780743 -1.3903412,-1.6100247 -0.3951213,-3.7149271 0,-5.2848379 z" -     id="rect4142" -     inkscape:connector-curvature="0" -     sodipodi:nodetypes="czcczcccczcczc" /> -</svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1s-3 5 0 7-1 7-1 7h13s3-6 0-8 1-6 1-6zm2 2h7s-2 3 1 5 0 5 0 5h-7s2-4-1-6 0-4 0-4z" fill="#fc9c9c" fill-opacity=".996078"/></svg>
\ No newline at end of file diff --git a/editor/icons/icon_spring_arm.svg b/editor/icons/icon_spring_arm.svg new file mode 100644 index 0000000000..0700966369 --- /dev/null +++ b/editor/icons/icon_spring_arm.svg @@ -0,0 +1,6 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m8 14 6-6" fill="none" stroke="#fc9c9c" stroke-width="2"/> +<path d="m2 2 7 7" fill="none" stroke="#fc9c9c" stroke-width="2"/> +<path d="m10 9h-6" fill="none" stroke="#fc9c9c" stroke-width="2"/> +<path d="m9 9v-5" fill="none" stroke="#fc9c9c" stroke-width="2"/> +</svg> diff --git a/editor/icons/icon_style_box_line.svg b/editor/icons/icon_style_box_line.svg new file mode 100644 index 0000000000..28f2eec6c0 --- /dev/null +++ b/editor/icons/icon_style_box_line.svg @@ -0,0 +1,11 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0 1036.4)" d="m13.303 1c-0.4344 0-0.86973 0.16881-1.2012 0.50586l-1.4688 1.4941h4.3418c0.082839-0.52789-0.072596-1.0872-0.47266-1.4941-0.33144-0.33705-0.76482-0.50586-1.1992-0.50586z" fill="#ff7070"/> +<path transform="translate(0 1036.4)" d="m10.633 3-1.9668 2h4.8008l1.0352-1.0527c0.2628-0.2673 0.41824-0.60049 0.47266-0.94727h-4.3418z" fill="#ffeb70"/> +<path transform="translate(0,1036.4)" d="m8.666 5-1.9648 2h2.8809c0.25686-0.33847 0.49465-0.66934 0.68555-1 0.33885-0.5859 0.95098-0.96109 1.627-0.99609 0.44399-0.023642 0.86385 0.115 1.2188 0.35547l0.35352-0.35938h-4.8008z" fill="#9dff70"/> +</g> +<path d="m1.2617 13c-0.08284 0.52789 0.072596 1.0872 0.47266 1.4941 0.33144 0.33705 0.76484 0.50586 1.1992 0.50586 0.4344 0 0.8697-0.16881 1.2012-0.50586l1.4688-1.4941h-4.3418zm7.9219 0c0.41312 1.1628 1.5119 2 2.8164 2s2.4033-0.83718 2.8164-2h-5.6328z" fill="#ff70ac"/> +<path d="m2.7695 11-1.0352 1.0527c-0.2628 0.2673-0.41824 0.60049-0.47266 0.94727h4.3418l1.4238-1.4473c0.020288-0.18998 0.04923-0.37542 0.089844-0.55273h-4.3477zm6.4609 0c-0.13656 0.32585-0.23047 0.65576-0.23047 1 0 0.35235 0.072014 0.68593 0.18359 1h5.6328c0.11158-0.31407 0.18359-0.64765 0.18359-1 0-0.34424-0.093909-0.67415-0.23047-1h-5.5391z" fill="#9f70ff"/> +<path d="m4.7363 9-1.9668 2h4.3477c0.17955-0.78395 0.54577-1.4354 0.9375-2h-3.3184zm5.8281 0c-0.55248 0.69003-1.0583 1.3421-1.334 2h5.5391c-0.2757-0.65786-0.78149-1.31-1.334-2h-2.8711z" fill="#70deff"/> +<path d="m6.7012 7-1.9648 2h3.3184c0.14116-0.20345 0.28508-0.40233 0.42383-0.58398 0.38601-0.5053 0.7635-0.96796 1.1035-1.416h-2.8809zm5.2988 0c-0.43047 0.7456-0.94456 1.3867-1.4355 2h2.8711c-0.49104-0.6133-1.0051-1.2544-1.4355-2z" fill="#70ffb9"/> +</svg> diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 3b300a7ad5..073e6f74e9 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1532,93 +1532,98 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data  void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {  	Ref<InputEventMouseButton> mb = ev; +	Ref<InputEventKey> k = ev; +	Point2 local_pos; +	bool create_menu = false; -	if (mb.is_valid()) { - -		if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { -			int col, row; -			TextEdit *tx = code_editor->get_text_edit(); -			tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); -			Vector2 mpos = mb->get_global_position() - tx->get_global_position(); - -			tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); -			if (tx->is_right_click_moving_caret()) { -				if (tx->is_selection_active()) { +	TextEdit *tx = code_editor->get_text_edit(); +	if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { +		local_pos = mb->get_global_position() - tx->get_global_position(); +		create_menu = true; +	} else if (k.is_valid() && k->get_scancode() == KEY_MENU) { +		local_pos = tx->_get_cursor_pixel_pos(); +		create_menu = true; +	} -					int from_line = tx->get_selection_from_line(); -					int to_line = tx->get_selection_to_line(); -					int from_column = tx->get_selection_from_column(); -					int to_column = tx->get_selection_to_column(); +	if (create_menu) { +		int col, row; +		tx->_get_mouse_pos(local_pos, row, col); -					if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) { -						// Right click is outside the selected text -						tx->deselect(); -					} -				} -				if (!tx->is_selection_active()) { -					tx->cursor_set_line(row, true, false); -					tx->cursor_set_column(col); +		tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); +		if (tx->is_right_click_moving_caret()) { +			if (tx->is_selection_active()) { +				int from_line = tx->get_selection_from_line(); +				int to_line = tx->get_selection_to_line(); +				int from_column = tx->get_selection_from_column(); +				int to_column = tx->get_selection_to_column(); + +				if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) { +					// Right click is outside the selected text +					tx->deselect();  				}  			} +			if (!tx->is_selection_active()) { +				tx->cursor_set_line(row, true, false); +				tx->cursor_set_column(col); +			} +		} -			String word_at_mouse = tx->get_word_at_pos(mpos); -			if (word_at_mouse == "") -				word_at_mouse = tx->get_word_under_cursor(); -			if (word_at_mouse == "") -				word_at_mouse = tx->get_selection_text(); +		String word_at_pos = tx->get_word_at_pos(local_pos); +		if (word_at_pos == "") +			word_at_pos = tx->get_word_under_cursor(); +		if (word_at_pos == "") +			word_at_pos = tx->get_selection_text(); -			bool has_color = (word_at_mouse == "Color"); -			bool foldable = tx->can_fold(row) || tx->is_folded(row); -			bool open_docs = false; -			bool goto_definition = false; +		bool has_color = (word_at_pos == "Color"); +		bool foldable = tx->can_fold(row) || tx->is_folded(row); +		bool open_docs = false; +		bool goto_definition = false; -			if (word_at_mouse.is_resource_file()) { +		if (word_at_pos.is_resource_file()) { +			open_docs = true; +		} else { +			Node *base = get_tree()->get_edited_scene_root(); +			if (base) { +				base = _find_node_for_script(base, base, script); +			} +			ScriptLanguage::LookupResult result; +			if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_pos, script->get_path(), base, result) == OK) {  				open_docs = true; -			} else { - -				Node *base = get_tree()->get_edited_scene_root(); -				if (base) { -					base = _find_node_for_script(base, base, script); -				} -				ScriptLanguage::LookupResult result; -				if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_mouse, script->get_path(), base, result) == OK) { -					open_docs = true; -				}  			} +		} -			if (has_color) { -				String line = tx->get_line(row); -				color_position.x = row; -				color_position.y = col; - -				int begin = 0; -				int end = 0; -				bool valid = false; -				for (int i = col; i < line.length(); i++) { -					if (line[i] == '(') { -						begin = i; -						continue; -					} else if (line[i] == ')') { -						end = i + 1; -						valid = true; -						break; -					} +		if (has_color) { +			String line = tx->get_line(row); +			color_position.x = row; +			color_position.y = col; + +			int begin = 0; +			int end = 0; +			bool valid = false; +			for (int i = col; i < line.length(); i++) { +				if (line[i] == '(') { +					begin = i; +					continue; +				} else if (line[i] == ')') { +					end = i + 1; +					valid = true; +					break;  				} -				if (valid) { -					color_args = line.substr(begin, end - begin); -					String stripped = color_args.replace(" ", "").replace("(", "").replace(")", ""); -					Vector<float> color = stripped.split_floats(","); -					if (color.size() > 2) { -						float alpha = color.size() > 3 ? color[3] : 1.0f; -						color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha)); -					} -					color_panel->set_position(get_global_transform().xform(get_local_mouse_position())); -				} else { -					has_color = false; +			} +			if (valid) { +				color_args = line.substr(begin, end - begin); +				String stripped = color_args.replace(" ", "").replace("(", "").replace(")", ""); +				Vector<float> color = stripped.split_floats(","); +				if (color.size() > 2) { +					float alpha = color.size() > 3 ? color[3] : 1.0f; +					color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));  				} +				color_panel->set_position(get_global_transform().xform(local_pos)); +			} else { +				has_color = false;  			} -			_make_context_menu(tx->is_selection_active(), has_color, foldable, open_docs, goto_definition);  		} +		_make_context_menu(tx->is_selection_active(), has_color, foldable, open_docs, goto_definition, local_pos);  	}  } @@ -1643,7 +1648,7 @@ void ScriptTextEditor::_color_changed(const Color &p_color) {  	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) { +void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos) {  	context_menu->clear();  	context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO); @@ -1680,7 +1685,7 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p  			context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR);  	} -	context_menu->set_position(get_global_transform().xform(get_local_mouse_position())); +	context_menu->set_position(get_global_transform().xform(p_pos));  	context_menu->set_size(Vector2(1, 1));  	context_menu->popup();  } diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index 38c6da5c33..0ea8726ecc 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -169,7 +169,7 @@ protected:  	void _edit_option(int p_op);  	void _edit_option_toggle_inline_comment(); -	void _make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition); +	void _make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos);  	void _text_edit_gui_input(const Ref<InputEvent> &ev);  	void _color_changed(const Color &p_color); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index e81c97d5dd..df3e23a9e9 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -523,9 +523,16 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {  					tx->cursor_set_column(col);  				}  			} -			_make_context_menu(tx->is_selection_active()); +			_make_context_menu(tx->is_selection_active(), get_local_mouse_position());  		}  	} + +	Ref<InputEventKey> k = ev; +	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_MENU) { +		TextEdit *tx = shader_editor->get_text_edit(); +		_make_context_menu(tx->is_selection_active(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos())); +		context_menu->grab_focus(); +	}  }  void ShaderEditor::_update_bookmark_list() { @@ -565,7 +572,7 @@ void ShaderEditor::_bookmark_item_pressed(int p_idx) {  	}  } -void ShaderEditor::_make_context_menu(bool p_selection) { +void ShaderEditor::_make_context_menu(bool p_selection, Vector2 p_position) {  	context_menu->clear();  	if (p_selection) { @@ -585,7 +592,7 @@ void ShaderEditor::_make_context_menu(bool p_selection) {  	context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);  	context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_bookmark"), BOOKMARK_TOGGLE); -	context_menu->set_position(get_global_transform().xform(get_local_mouse_position())); +	context_menu->set_position(get_global_transform().xform(p_position));  	context_menu->set_size(Vector2(1, 1));  	context_menu->popup();  } diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 8d3f4d4fe8..ca9f489713 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -122,7 +122,7 @@ class ShaderEditor : public PanelContainer {  protected:  	void _notification(int p_what);  	static void _bind_methods(); -	void _make_context_menu(bool p_selection); +	void _make_context_menu(bool p_selection, Vector2 p_position);  	void _text_edit_gui_input(const Ref<InputEvent> &ev);  	void _update_bookmark_list(); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index d91de6cbf6..394122d91d 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -464,9 +464,11 @@ void SpriteFramesEditor::_animation_select() {  	if (updating)  		return; -	double value = anim_speed->get_line_edit()->get_text().to_double(); -	if (!Math::is_equal_approx(value, frames->get_animation_speed(edited_anim))) -		_animation_fps_changed(value); +	if (frames->has_animation(edited_anim)) { +		double value = anim_speed->get_line_edit()->get_text().to_double(); +		if (!Math::is_equal_approx(value, frames->get_animation_speed(edited_anim))) +			_animation_fps_changed(value); +	}  	TreeItem *selected = animations->get_selected();  	ERR_FAIL_COND(!selected); @@ -548,6 +550,7 @@ void SpriteFramesEditor::_animation_name_edited() {  	undo_redo->commit_action();  } +  void SpriteFramesEditor::_animation_add() {  	String name = "New Anim"; @@ -578,13 +581,21 @@ void SpriteFramesEditor::_animation_add() {  	undo_redo->commit_action();  	animations->grab_focus();  } +  void SpriteFramesEditor::_animation_remove() { +  	if (updating)  		return;  	if (!frames->has_animation(edited_anim))  		return; +	delete_dialog->set_text(TTR("Delete Animation?")); +	delete_dialog->popup_centered_minsize(); +} + +void SpriteFramesEditor::_animation_remove_confirmed() { +  	undo_redo->create_action(TTR("Remove Animation"));  	undo_redo->add_do_method(frames, "remove_animation", edited_anim);  	undo_redo->add_undo_method(frames, "add_animation", edited_anim); @@ -598,6 +609,8 @@ void SpriteFramesEditor::_animation_remove() {  	undo_redo->add_do_method(this, "_update_library");  	undo_redo->add_undo_method(this, "_update_library"); +	edited_anim = StringName(); +  	undo_redo->commit_action();  } @@ -743,7 +756,9 @@ Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f  	if (frame.is_null())  		return Variant(); -	return EditorNode::get_singleton()->drag_resource(frame, p_from); +	Dictionary drag_data = EditorNode::get_singleton()->drag_resource(frame, p_from); +	drag_data["frame"] = idx; // store the frame, incase we want to reorder frames inside 'drop_data_fw' +	return drag_data;  }  bool SpriteFramesEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { @@ -753,8 +768,9 @@ bool SpriteFramesEditor::can_drop_data_fw(const Point2 &p_point, const Variant &  	if (!d.has("type"))  		return false; +	// reordering frames  	if (d.has("from") && (Object *)(d["from"]) == tree) -		return false; +		return true;  	if (String(d["type"]) == "resource" && d.has("resource")) {  		RES r = d["resource"]; @@ -806,13 +822,31 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da  		Ref<Texture> texture = r;  		if (texture.is_valid()) { - -			undo_redo->create_action(TTR("Add Frame")); -			undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, at_pos == -1 ? -1 : at_pos); -			undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) : at_pos); -			undo_redo->add_do_method(this, "_update_library"); -			undo_redo->add_undo_method(this, "_update_library"); -			undo_redo->commit_action(); +			bool reorder = false; +			if (d.has("from") && (Object *)(d["from"]) == tree) +				reorder = true; + +			if (reorder) { //drop is from reordering frames +				int from_frame = -1; +				if (d.has("frame")) +					from_frame = d["frame"]; + +				undo_redo->create_action(TTR("Move Frame")); +				undo_redo->add_do_method(frames, "remove_frame", edited_anim, from_frame == -1 ? frames->get_frame_count(edited_anim) : from_frame); +				undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, at_pos == -1 ? -1 : at_pos); +				undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) - 1 : at_pos); +				undo_redo->add_undo_method(frames, "add_frame", edited_anim, texture, from_frame); +				undo_redo->add_do_method(this, "_update_library"); +				undo_redo->add_undo_method(this, "_update_library"); +				undo_redo->commit_action(); +			} else { +				undo_redo->create_action(TTR("Add Frame")); +				undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, at_pos == -1 ? -1 : at_pos); +				undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) : at_pos); +				undo_redo->add_do_method(this, "_update_library"); +				undo_redo->add_undo_method(this, "_update_library"); +				undo_redo->commit_action(); +			}  		}  	} @@ -840,6 +874,7 @@ void SpriteFramesEditor::_bind_methods() {  	ClassDB::bind_method(D_METHOD("_animation_name_edited"), &SpriteFramesEditor::_animation_name_edited);  	ClassDB::bind_method(D_METHOD("_animation_add"), &SpriteFramesEditor::_animation_add);  	ClassDB::bind_method(D_METHOD("_animation_remove"), &SpriteFramesEditor::_animation_remove); +	ClassDB::bind_method(D_METHOD("_animation_remove_confirmed"), &SpriteFramesEditor::_animation_remove_confirmed);  	ClassDB::bind_method(D_METHOD("_animation_loop_changed"), &SpriteFramesEditor::_animation_loop_changed);  	ClassDB::bind_method(D_METHOD("_animation_fps_changed"), &SpriteFramesEditor::_animation_fps_changed);  	ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &SpriteFramesEditor::get_drag_data_fw); @@ -870,7 +905,6 @@ SpriteFramesEditor::SpriteFramesEditor() {  	new_anim = memnew(ToolButton);  	new_anim->set_tooltip(TTR("New Animation"));  	hbc_animlist->add_child(new_anim); -	new_anim->set_h_size_flags(SIZE_EXPAND_FILL);  	new_anim->connect("pressed", this, "_animation_add");  	remove_anim = memnew(ToolButton); @@ -926,7 +960,7 @@ SpriteFramesEditor::SpriteFramesEditor() {  	paste->set_tooltip(TTR("Paste"));  	hbc->add_child(paste); -	hbc->add_spacer(false); +	hbc->add_child(memnew(VSeparator));  	empty = memnew(ToolButton);  	empty->set_tooltip(TTR("Insert Empty (Before)")); @@ -987,6 +1021,10 @@ SpriteFramesEditor::SpriteFramesEditor() {  	edited_anim = "default"; +	delete_dialog = memnew(ConfirmationDialog); +	add_child(delete_dialog); +	delete_dialog->connect("confirmed", this, "_animation_remove_confirmed"); +  	split_sheet_dialog = memnew(ConfirmationDialog);  	add_child(split_sheet_dialog);  	VBoxContainer *split_sheet_vb = memnew(VBoxContainer); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index d64431cde7..f20b54f910 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -73,6 +73,8 @@ class SpriteFramesEditor : public HSplitContainer {  	StringName edited_anim; +	ConfirmationDialog *delete_dialog; +  	ConfirmationDialog *split_sheet_dialog;  	ScrollContainer *splite_sheet_scroll;  	TextureRect *split_sheet_preview; @@ -98,6 +100,7 @@ class SpriteFramesEditor : public HSplitContainer {  	void _animation_name_edited();  	void _animation_add();  	void _animation_remove(); +	void _animation_remove_confirmed();  	void _animation_loop_changed();  	void _animation_fps_changed(double p_value); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 89e419ede8..d0320bcd8b 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -30,6 +30,7 @@  #include "text_editor.h" +#include "core/os/keyboard.h"  #include "editor_node.h"  void TextEditor::add_syntax_highlighter(SyntaxHighlighter *p_highlighter) { @@ -577,13 +578,21 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {  			}  			if (!mb->is_pressed()) { -				_make_context_menu(tx->is_selection_active(), can_fold, is_folded); +				_make_context_menu(tx->is_selection_active(), can_fold, is_folded, get_local_mouse_position());  			}  		}  	} + +	Ref<InputEventKey> k = ev; +	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_MENU) { +		TextEdit *tx = code_editor->get_text_edit(); +		int line = tx->cursor_get_line(); +		_make_context_menu(tx->is_selection_active(), tx->can_fold(line), tx->is_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos())); +		context_menu->grab_focus(); +	}  } -void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded) { +void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position) {  	context_menu->clear();  	if (p_selection) { @@ -609,7 +618,7 @@ void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is  	if (p_can_fold || p_is_folded)  		context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_fold_line"), EDIT_TOGGLE_FOLD_LINE); -	context_menu->set_position(get_global_transform().xform(get_local_mouse_position())); +	context_menu->set_position(get_global_transform().xform(p_position));  	context_menu->set_size(Vector2(1, 1));  	context_menu->popup();  } diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index c8b49a61e0..7d441a187d 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -101,7 +101,7 @@ protected:  	void _notification(int p_what);  	void _edit_option(int p_op); -	void _make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded); +	void _make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position);  	void _text_edit_gui_input(const Ref<InputEvent> &ev);  	Map<String, SyntaxHighlighter *> highlighters; diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index f1e9420799..edc14ccf71 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -1043,6 +1043,84 @@ void ProjectSettingsEditor::_copy_to_platform_about_to_show() {  	}  } +Variant ProjectSettingsEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + +	TreeItem *selected = input_editor->get_selected(); +	if (!selected || selected->get_parent() != input_editor->get_root()) +		return Variant(); + +	String name = selected->get_text(0); +	VBoxContainer *vb = memnew(VBoxContainer); +	HBoxContainer *hb = memnew(HBoxContainer); +	Label *label = memnew(Label(name)); +	hb->set_modulate(Color(1, 1, 1, 1.0f)); +	hb->add_child(label); +	vb->add_child(hb); +	set_drag_preview(vb); + +	Dictionary drag_data; +	drag_data["type"] = "nodes"; + +	input_editor->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); + +	return drag_data; +} + +bool ProjectSettingsEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + +	Dictionary d = p_data; +	if (!d.has("type") || d["type"] != "nodes") +		return false; + +	TreeItem *selected = input_editor->get_selected(); +	TreeItem *item = input_editor->get_item_at_position(p_point); +	if (!selected || !item || item->get_parent() == selected) +		return false; + +	return true; +} + +void ProjectSettingsEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + +	if (!can_drop_data_fw(p_point, p_data, p_from)) +		return; + +	TreeItem *selected = input_editor->get_selected(); +	TreeItem *item = input_editor->get_item_at_position(p_point); +	TreeItem *target = item->get_parent() == input_editor->get_root() ? item : item->get_parent(); + +	String selected_name = "input/" + selected->get_text(0); +	int old_order = ProjectSettings::get_singleton()->get_order(selected_name); +	String target_name = "input/" + target->get_text(0); +	int target_order = ProjectSettings::get_singleton()->get_order(target_name); + +	int order = old_order; +	bool is_below = target_order > old_order; +	TreeItem *iterator = is_below ? selected->get_next() : selected->get_prev(); + +	undo_redo->create_action(TTR("Moved Input Action Event")); +	while (iterator != target) { + +		String iterator_name = "input/" + iterator->get_text(0); +		int iterator_order = ProjectSettings::get_singleton()->get_order(iterator_name); +		undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", iterator_name, order); +		undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", iterator_name, iterator_order); +		order = iterator_order; +		iterator = is_below ? iterator->get_next() : iterator->get_prev(); +	} + +	undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", target_name, order); +	undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", selected_name, target_order); +	undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", target_name, target_order); +	undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", selected_name, old_order); + +	undo_redo->add_do_method(this, "_update_actions"); +	undo_redo->add_undo_method(this, "_update_actions"); +	undo_redo->add_do_method(this, "_settings_changed"); +	undo_redo->add_undo_method(this, "_settings_changed"); +	undo_redo->commit_action(); +} +  void ProjectSettingsEditor::_copy_to_platform(int p_which) {  	String path = globals_editor->get_inspector()->get_selected_path(); @@ -1662,6 +1740,10 @@ void ProjectSettingsEditor::_bind_methods() {  	ClassDB::bind_method(D_METHOD("_editor_restart_close"), &ProjectSettingsEditor::_editor_restart_close);  	ClassDB::bind_method(D_METHOD("get_tabs"), &ProjectSettingsEditor::get_tabs); + +	ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ProjectSettingsEditor::get_drag_data_fw); +	ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ProjectSettingsEditor::can_drop_data_fw); +	ClassDB::bind_method(D_METHOD("drop_data_fw"), &ProjectSettingsEditor::drop_data_fw);  }  ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { @@ -1844,6 +1926,8 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {  	input_editor->connect("item_activated", this, "_action_activated");  	input_editor->connect("cell_selected", this, "_action_selected");  	input_editor->connect("button_pressed", this, "_action_button_pressed"); +	input_editor->set_drag_forwarding(this); +  	popup_add = memnew(PopupMenu);  	add_child(popup_add);  	popup_add->connect("id_pressed", this, "_add_item"); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index d302c0d34b..4dfd8ba602 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -158,6 +158,10 @@ class ProjectSettingsEditor : public AcceptDialog {  	void _toggle_search_bar(bool p_pressed); +	Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); +	bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; +	void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); +  	void _copy_to_platform_about_to_show();  	ProjectSettingsEditor(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index e45b08c992..2ddf1f7056 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1552,18 +1552,20 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V  	if (p_nodes.size() == 0)  		return; // Nothing to reparent. -	bool same_parent = true; +	p_nodes.sort_custom<Node::Comparator>(); //Makes result reliable. + +	bool no_change = true;  	for (int ni = 0; ni < p_nodes.size(); ni++) {  		if (p_nodes[ni] == p_new_parent)  			return; // Attempt to reparent to itself. -		if (p_nodes[ni]->get_parent() != p_new_parent) -			same_parent = false; +		if (p_nodes[ni]->get_parent() != p_new_parent || p_position_in_parent + ni != p_nodes[ni]->get_position_in_parent()) +			no_change = false;  	} -	if (same_parent) -		return; // No new parent changes. +	if (no_change) +		return; // Position and parent didn't change.  	Node *validate = new_parent;  	while (validate) { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 26ca3726f5..74b2f483b4 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -434,6 +434,15 @@ int ScriptEditorDebugger::_update_scene_tree(TreeItem *parent, const Array &node  	}  	item->set_metadata(0, id); +	if (id == inspected_object_id) { +		TreeItem *cti = item->get_parent(); +		while (cti) { +			cti->set_collapsed(false); +			cti = cti->get_parent(); +		} +		item->select(0); +	} +  	// Set current item as collapsed if necessary  	if (parent) {  		if (!unfold_cache.has(id)) { diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 70389b6729..6bed1742eb 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -578,6 +578,10 @@ void VisualScript::get_data_connection_list(const StringName &p_func, List<DataC  	}  } +void VisualScript::set_tool_enabled(bool p_enabled) { +	is_tool_script = p_enabled; +} +  void VisualScript::add_variable(const StringName &p_name, const Variant &p_default_value, bool p_export) {  	ERR_FAIL_COND(instances.size()); @@ -894,7 +898,7 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) {  #ifdef TOOLS_ENABLED -	if (!ScriptServer::is_scripting_enabled()) { +	if (!ScriptServer::is_scripting_enabled() && !is_tool_script) {  		PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(VisualScriptLanguage::singleton, Ref<Script>((Script *)this), p_this));  		placeholders.insert(sins); @@ -958,7 +962,7 @@ Error VisualScript::reload(bool p_keep_state) {  bool VisualScript::is_tool() const { -	return false; +	return is_tool_script;  }  bool VisualScript::is_valid() const { @@ -1164,6 +1168,11 @@ void VisualScript::_set_data(const Dictionary &p_data) {  			data_connect(name, data_connections[j + 0], data_connections[j + 1], data_connections[j + 2], data_connections[j + 3]);  		}  	} + +	if (d.has("is_tool_script")) +		is_tool_script = d["is_tool_script"]; +	else +		is_tool_script = false;  }  Dictionary VisualScript::_get_data() const { @@ -1246,6 +1255,8 @@ Dictionary VisualScript::_get_data() const {  	d["functions"] = funcs; +	d["is_tool_script"] = is_tool_script; +  	return d;  } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 098c28370d..14927c4363 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -247,6 +247,8 @@ private:  	Map<Object *, VisualScriptInstance *> instances; +	bool is_tool_script; +  #ifdef TOOLS_ENABLED  	Set<PlaceHolderScriptInstance *> placeholders;  	//void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); @@ -273,6 +275,7 @@ public:  	Vector2 get_function_scroll(const StringName &p_name) const;  	void get_function_list(List<StringName> *r_functions) const;  	int get_function_node_id(const StringName &p_name) const; +	void set_tool_enabled(bool p_enabled);  	void add_node(const StringName &p_func, int p_id, const Ref<VisualScriptNode> &p_node, const Point2 &p_pos = Point2());  	void remove_node(const StringName &p_func, int p_id); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 8faa342bbe..7262dde359 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -2227,6 +2227,10 @@ void VisualScriptEditor::_change_base_type() {  	select_base_type->popup_create(true, true);  } +void VisualScriptEditor::_toggle_tool_script() { +	script->set_tool_enabled(!script->is_tool()); +} +  void VisualScriptEditor::clear_edit_menu() {  	memdelete(edit_menu);  	memdelete(left_vsplit); @@ -3448,6 +3452,7 @@ void VisualScriptEditor::_bind_methods() {  	ClassDB::bind_method("_update_members", &VisualScriptEditor::_update_members);  	ClassDB::bind_method("_change_base_type", &VisualScriptEditor::_change_base_type);  	ClassDB::bind_method("_change_base_type_callback", &VisualScriptEditor::_change_base_type_callback); +	ClassDB::bind_method("_toggle_tool_script", &VisualScriptEditor::_toggle_tool_script);  	ClassDB::bind_method("_node_selected", &VisualScriptEditor::_node_selected);  	ClassDB::bind_method("_node_moved", &VisualScriptEditor::_node_moved);  	ClassDB::bind_method("_move_node", &VisualScriptEditor::_move_node); @@ -3533,6 +3538,11 @@ VisualScriptEditor::VisualScriptEditor() {  	left_vb->set_v_size_flags(SIZE_EXPAND_FILL);  	//left_vb->set_custom_minimum_size(Size2(230, 1) * EDSCALE); +	CheckButton *tool_script_check = memnew(CheckButton); +	tool_script_check->set_text(TTR("Make Tool:")); +	left_vb->add_child(tool_script_check); +	tool_script_check->connect("pressed", this, "_toggle_tool_script"); +  	base_type_select = memnew(Button);  	left_vb->add_margin_child(TTR("Base Type:"), base_type_select);  	base_type_select->connect("pressed", this, "_change_base_type"); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 4f302d1d72..5df9b1a004 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -186,6 +186,7 @@ class VisualScriptEditor : public ScriptEditorBase {  	void _node_filter_changed(const String &p_text);  	void _change_base_type_callback();  	void _change_base_type(); +	void _toggle_tool_script();  	void _member_selected();  	void _member_edited(); diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 567f7e7b09..6d0811e168 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -1537,7 +1537,7 @@ public:  		args.push_back("-a");  		args.push_back("android.intent.action.MAIN");  		args.push_back("-n"); -		args.push_back(get_package_name(package_name) + "/org.godotengine.godot.Godot"); +		args.push_back(get_package_name(package_name) + "/com.godot.game.GodotApp");  		err = OS::get_singleton()->execute(adb, args, true, NULL, NULL, &rv);  		if (err || rv != 0) { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index de0fb9300d..04e03f569e 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -532,6 +532,16 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {  					set_cursor_position(text.length());  					shift_selection_check_post(k->get_shift());  				} break; +				case KEY_MENU: { +					if (context_menu_enabled) { +						Point2 pos = Point2(get_cursor_pixel_pos(), (get_size().y + get_font("font")->get_height()) / 2); +						menu->set_position(get_global_transform().xform(pos)); +						menu->set_size(Vector2(1, 1)); +						menu->set_scale(get_global_transform().get_scale()); +						menu->popup(); +						menu->grab_focus(); +					} +				} break;  				default: { @@ -1058,6 +1068,52 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {  	set_cursor_position(ofs);  } +int LineEdit::get_cursor_pixel_pos() { + +	Ref<Font> font = get_font("font"); +	int ofs = window_pos; +	Ref<StyleBox> style = get_stylebox("normal"); +	int pixel_ofs = 0; +	Size2 size = get_size(); +	bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled; +	int r_icon_width = Control::get_icon("clear")->get_width(); + +	switch (align) { + +		case ALIGN_FILL: +		case ALIGN_LEFT: { + +			pixel_ofs = int(style->get_offset().x); +		} break; +		case ALIGN_CENTER: { + +			if (window_pos != 0) +				pixel_ofs = int(style->get_offset().x); +			else +				pixel_ofs = int(size.width - (cached_width)) / 2; + +			if (display_clear_icon) +				pixel_ofs -= int(r_icon_width / 2 + style->get_margin(MARGIN_RIGHT)); +		} break; +		case ALIGN_RIGHT: { + +			pixel_ofs = int(size.width - style->get_margin(MARGIN_RIGHT) - (cached_width)); + +			if (display_clear_icon) +				pixel_ofs -= int(r_icon_width + style->get_margin(MARGIN_RIGHT)); +		} break; +	} + +	while (ofs < cursor_pos) { +		if (font != NULL) { +			pixel_ofs += font->get_char_size(text[ofs]).width; +		} +		ofs++; +	} + +	return pixel_ofs; +} +  bool LineEdit::cursor_get_blink_enabled() const {  	return caret_blink_enabled;  } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 154df89fae..3424131dad 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -143,6 +143,7 @@ private:  	void set_window_pos(int p_pos);  	void set_cursor_at_pixel_pos(int p_x); +	int get_cursor_pixel_pos();  	void _reset_caret_blink_timer();  	void _toggle_draw_caret(); diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index d1840e43a3..de8df4215d 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -116,10 +116,16 @@ void OptionButton::add_item(const String &p_label, int p_id) {  void OptionButton::set_item_text(int p_idx, const String &p_text) {  	popup->set_item_text(p_idx, p_text); + +	if (current == p_idx) +		set_text(p_text);  }  void OptionButton::set_item_icon(int p_idx, const Ref<Texture> &p_icon) {  	popup->set_item_icon(p_idx, p_icon); + +	if (current == p_idx) +		set_icon(p_icon);  }  void OptionButton::set_item_id(int p_idx, int p_id) { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 9678ebe6ea..7227942ccb 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2081,6 +2081,44 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co  	r_col = col;  } +Vector2i TextEdit::_get_cursor_pixel_pos() { +	adjust_viewport_to_cursor(); +	int row = (cursor.line - get_first_visible_line() - cursor.wrap_ofs); +	// Correct for hidden and wrapped lines +	for (int i = get_first_visible_line(); i < cursor.line; i++) { +		if (is_line_hidden(i)) { +			row -= 1; +			continue; +		} +		row += times_line_wraps(i); +	} +	// Row might be wrapped. Adjust row and r_column +	Vector<String> rows2 = get_wrap_rows_text(cursor.line); +	while (rows2.size() > 1) { +		if (cursor.column >= rows2[0].length()) { +			cursor.column -= rows2[0].length(); +			rows2.remove(0); +			row++; +		} else { +			break; +		} +	} + +	// Calculate final pixel position +	int y = (row - get_v_scroll_offset() + 1 /*Bottom of line*/) * get_row_height(); +	int x = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width - cursor.x_ofs; +	int ix = 0; +	while (ix < rows2[0].size() && ix < cursor.column) { +		if (cache.font != NULL) { +			x += cache.font->get_char_size(rows2[0].get(ix)).width; +		} +		ix++; +	} +	x += get_indent_level(cursor.line) * cache.font->get_char_size(' ').width; + +	return Vector2i(x, y); +} +  void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const {  	float rows = p_mouse.y; @@ -3596,6 +3634,16 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {  			} break; +			case KEY_MENU: { +				if (context_menu_enabled) { +					menu->set_position(get_global_transform().xform(_get_cursor_pixel_pos())); +					menu->set_size(Vector2(1, 1)); +					menu->set_scale(get_global_transform().get_scale()); +					menu->popup(); +					menu->grab_focus(); +				} +			} break; +  			default: {  				scancode_handled = false; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index e98201c1eb..e5d9b006fe 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -587,6 +587,7 @@ public:  	int cursor_get_column() const;  	int cursor_get_line() const; +	Vector2i _get_cursor_pixel_pos();  	bool cursor_get_blink_enabled() const;  	void cursor_set_blink_enabled(const bool p_enabled); diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index cd229732ba..1c41f30a94 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -1713,6 +1713,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r  			}  			if (groups.size()) { +				groups.sort_custom<StringName::AlphCompare>();  				String sgroups = " groups=[\n";  				for (int j = 0; j < groups.size(); j++) {  					sgroups += "\"" + String(groups[j]).c_escape() + "\",\n";  |