diff options
| author | Juan Linietsky <reduzio@gmail.com> | 2015-11-18 23:46:46 -0300 | 
|---|---|---|
| committer | Juan Linietsky <reduzio@gmail.com> | 2015-11-18 23:46:46 -0300 | 
| commit | 3118c192bdfcecaa6b08050f99d0813f5ec93882 (patch) | |
| tree | f39062f48833d8cfabf6c8dc99d532f00e058d25 | |
| parent | 94fdd01241749cb7a575ed5f9fa4c7bbb286901a (diff) | |
| parent | f84dc8e59da0f1b835a5c0017b965ad5dbc2ae13 (diff) | |
Merge pull request #2786 from neikeq/node_select_menu
Added selection menu to spatial and canvas editors
| -rw-r--r-- | tools/editor/plugins/canvas_item_editor_plugin.cpp | 289 | ||||
| -rw-r--r-- | tools/editor/plugins/canvas_item_editor_plugin.h | 21 | ||||
| -rw-r--r-- | tools/editor/plugins/spatial_editor_plugin.cpp | 153 | ||||
| -rw-r--r-- | tools/editor/plugins/spatial_editor_plugin.h | 14 | 
4 files changed, 393 insertions, 84 deletions
| diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index b03eed77b1..90bfe0bfdf 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -447,6 +447,47 @@ CanvasItem* CanvasItemEditor::_select_canvas_item_at_pos(const Point2& p_pos,Nod  	return NULL;  } +void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform, Vector<_SelectResult> &r_items) { +	if (!p_node) +		return; +	if (p_node->cast_to<Viewport>()) +		return; + +	CanvasItem *c=p_node->cast_to<CanvasItem>(); + +	for (int i=p_node->get_child_count()-1;i>=0;i--) { + +		if (c && !c->is_set_as_toplevel()) +			_find_canvas_items_at_pos(p_pos,p_node->get_child(i),p_parent_xform * c->get_transform(),p_canvas_xform, r_items); +		else { +			CanvasLayer *cl = p_node->cast_to<CanvasLayer>(); +			if (cl) +				return; +			_find_canvas_items_at_pos(p_pos,p_node->get_child(i),transform ,cl ? cl->get_transform() : p_canvas_xform, r_items); //use base transform +		} +	} + + +	if (c && c->is_visible() && !c->has_meta("_edit_lock_")) { + +		Rect2 rect = c->get_item_rect(); +		Point2 local_pos = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse().xform(p_pos); + + +		if (rect.has_point(local_pos)) { +			Node2D *node=c->cast_to<Node2D>(); + +			_SelectResult res; +			res.item=c; +			res.z=node?node->get_z():0; +			res.has_z=node; +			r_items.push_back(res); +		} + +	} + +	return; +}  void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform,List<CanvasItem*> *r_items) { @@ -489,6 +530,96 @@ void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2& p_rect,Node* p_no  } +bool CanvasItemEditor::_select(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag) { + +	if (p_append) { +		//additive selection + +		if (!item) { + +			if (p_drag) { +				drag_from=transform.affine_inverse().xform(p_click_pos); + +				box_selecting=true; +				box_selecting_to=drag_from; +			} + +			return false; //nothing to add +		} + +		if (editor_selection->is_selected(item)) { +			//already in here, erase it +			editor_selection->remove_node(item); +			//_remove_canvas_item(c); + +			viewport->update(); +			return false; + +		} +		_append_canvas_item(item); +		viewport->update(); + +	} else { +		//regular selection + +		if (!item) { +			//clear because nothing clicked +			editor_selection->clear();; + +			if (p_drag) { +				drag_from=transform.affine_inverse().xform(p_click_pos); + +				box_selecting=true; +				box_selecting_to=drag_from; +			} + +			viewport->update(); +			return false; +		} + +		if (!editor_selection->is_selected(item)) { +			//select a new one and clear previous selection +			editor_selection->clear(); +			editor_selection->add_node(item); +			//reselect +			if (get_tree()->is_editor_hint()) { +				editor->call("edit_node",item); +			} + +		} + +		if (p_drag) { +			//prepare to move! + +			List<Node*> &selection = editor_selection->get_selected_node_list(); + +			for(List<Node*>::Element *E=selection.front();E;E=E->next()) { + +				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); +				if (!canvas_item || !canvas_item->is_visible()) +					continue; +				CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); +				if (!se) +					continue; + +				se->undo_state=canvas_item->edit_get_state(); +				if (canvas_item->cast_to<Node2D>()) +					se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot(); + +			} + +			drag=DRAG_ALL; +			drag_from=transform.affine_inverse().xform(p_click_pos); +			drag_point_from=_find_topleftmost_point(); +		} + +		viewport->update(); + +		return true; + +	} +} +  void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE p_move_mode) { @@ -788,6 +919,24 @@ void CanvasItemEditor::_dialog_value_changed(double) {  	}  } +void CanvasItemEditor::_selection_result_pressed(int p_result) { + +	if (selection_results.size() <= p_result) +		return; + +	CanvasItem *item=selection_results[p_result].item; + +	if (item) +		_select(item, Point2(), additive_selection, false); +} + +void CanvasItemEditor::_selection_menu_hide() { + +	selection_results.clear(); +	selection_menu->clear(); +	selection_menu->set_size(Vector2(0, 0)); +} +  bool CanvasItemEditor::get_remove_list(List<Node*> *p_list) { @@ -850,7 +999,60 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {  		if (b.button_index==BUTTON_RIGHT) { +			if (!b.pressed && tool==TOOL_SELECT && b.mod.alt) { + +				Point2 click=Point2(b.x,b.y); + +				Node* scene = editor->get_edited_scene(); +				if (!scene) +					return; + +				_find_canvas_items_at_pos(click, scene,transform,Matrix32(), selection_results); + +				if (selection_results.size() == 1) { + +					CanvasItem *item = selection_results[0].item; +					selection_results.clear(); + +					additive_selection=b.mod.shift; +					if (!_select(item, click, additive_selection, false)) +						return; + +				} else if (!selection_results.empty()) { + +					selection_results.sort(); + +					NodePath root_path = get_tree()->get_edited_scene_root()->get_path(); +					StringName root_name = root_path.get_name(root_path.get_name_count()-1); + +					for (int i = 0; i < selection_results.size(); i++) { + +						CanvasItem *item=selection_results[i].item; +						Ref<Texture> icon; +						if (item->has_meta("_editor_icon")) +							icon=item->get_meta("_editor_icon"); +						else +							icon=get_icon( has_icon(item->get_type(),"EditorIcons")?item->get_type():String("Object"),"EditorIcons"); + +						String node_path="/"+root_name+"/"+root_path.rel_path_to(item->get_path()); + +						selection_menu->add_item(item->get_name()); +						selection_menu->set_item_icon(i, icon ); +						selection_menu->set_item_metadata(i, node_path); +						selection_menu->set_item_tooltip(i,String(item->get_name())+ +								"\nType: "+item->get_type()+"\nPath: "+node_path); +					} + +					additive_selection=b.mod.shift; + +					selection_menu->set_global_pos(Vector2( b.global_x, b.global_y )); +					selection_menu->popup(); +					selection_menu->call_deferred("grab_click_focus"); + +					return; +				} +			}  			if (get_item_count() > 0 && drag!=DRAG_NONE) {  				//cancel drag @@ -1215,82 +1417,10 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {  #if 0  		if ( b.pressed ) box_selection_start( click );  #endif -		if (b.mod.shift) { //additive selection - -			if (!c) { - -				drag_from=transform.affine_inverse().xform(click); -				box_selecting=true; -				box_selecting_to=drag_from; - -				return; //nothing to add -			} - -			if (editor_selection->is_selected(c)) { -				//already in here, erase it -				editor_selection->remove_node(c); -				//_remove_canvas_item(c); - -				viewport->update(); -				return; - -			} -			_append_canvas_item(c); -			viewport->update(); -		} else { -			//regular selection - - - -			if (!c) { -				//clear because nothing clicked -				editor_selection->clear();; - -				drag_from=transform.affine_inverse().xform(click); - -				box_selecting=true; -				box_selecting_to=drag_from; -				viewport->update(); -				return; -			} - -			if (!editor_selection->is_selected(c)) { -				//select a new one and clear previous selection -				editor_selection->clear(); -				editor_selection->add_node(c); -				//reselect -				if (get_tree()->is_editor_hint()) { -					editor->call("edit_node",c); -				} - -			} - -			//prepare to move! - -			List<Node*> &selection = editor_selection->get_selected_node_list(); - -			for(List<Node*>::Element *E=selection.front();E;E=E->next()) { - -				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); -				if (!canvas_item || !canvas_item->is_visible()) -					continue; -				CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); -				if (!se) -					continue; - -				se->undo_state=canvas_item->edit_get_state(); -				if (canvas_item->cast_to<Node2D>()) -					se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot(); - -			} - -			drag=DRAG_ALL; -			drag_from=transform.affine_inverse().xform(click); -			drag_point_from=_find_topleftmost_point(); -			viewport->update(); - -		} +		additive_selection=b.mod.shift; +		if (!_select(c, click, additive_selection)) +			return;  	} @@ -2879,6 +3009,8 @@ void CanvasItemEditor::_bind_methods() {  	ObjectTypeDB::bind_method("_viewport_draw",&CanvasItemEditor::_viewport_draw);  	ObjectTypeDB::bind_method("_viewport_input_event",&CanvasItemEditor::_viewport_input_event);  	ObjectTypeDB::bind_method("_snap_changed",&CanvasItemEditor::_snap_changed); +	ObjectTypeDB::bind_method(_MD("_selection_result_pressed"),&CanvasItemEditor::_selection_result_pressed); +	ObjectTypeDB::bind_method(_MD("_selection_menu_hide"),&CanvasItemEditor::_selection_menu_hide);  	ADD_SIGNAL( MethodInfo("item_lock_status_changed") );  	ADD_SIGNAL( MethodInfo("item_group_status_changed") ); @@ -3208,6 +3340,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {  	dialog_val->connect("value_changed",this,"_dialog_value_changed");  	select_sb = Ref<StyleBoxTexture>( memnew( StyleBoxTexture) ); +	selection_menu = memnew( PopupMenu ); +	add_child(selection_menu); +	selection_menu->set_custom_minimum_size(Vector2(100, 0)); +	selection_menu->connect("item_pressed", this, "_selection_result_pressed"); +	selection_menu->connect("popup_hide", this, "_selection_menu_hide"); +  	key_pos=true;  	key_rot=true;  	key_scale=false; @@ -3230,6 +3368,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {  	can_move_pivot=false;  	drag=DRAG_NONE;  	bone_last_frame=0; +	additive_selection=false;  }  CanvasItemEditor *CanvasItemEditor::singleton=NULL; diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 485422028e..b96d36f7dc 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -150,6 +150,7 @@ class CanvasItemEditor : public VBoxContainer {  	};  	EditorSelection *editor_selection; +	bool additive_selection;  	Tool tool;  	bool first_update; @@ -183,6 +184,18 @@ class CanvasItemEditor : public VBoxContainer {  	MenuOption last_option; +	struct _SelectResult { + +		CanvasItem* item; +		float z; +		bool has_z; +		_FORCE_INLINE_ bool operator<(const _SelectResult& p_rr) const { +			return has_z && p_rr.has_z ? p_rr.z < z : p_rr.has_z; +		} +	}; + +	Vector<_SelectResult> selection_results; +  	struct LockList {  		Point2 pos;  		bool lock; @@ -249,6 +262,8 @@ class CanvasItemEditor : public VBoxContainer {  	Button *key_scale_button;  	Button *key_insert_button; +	PopupMenu *selection_menu; +  	//PopupMenu *popup;  	DragType drag;  	Point2 drag_from; @@ -276,8 +291,11 @@ class CanvasItemEditor : public VBoxContainer {  	int handle_len;  	CanvasItem* _select_canvas_item_at_pos(const Point2 &p_pos,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform); +	void _find_canvas_items_at_pos(const Point2 &p_pos,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform, Vector<_SelectResult> &r_items);  	void _find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform,List<CanvasItem*> *r_items); +	bool _select(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag=true); +  	ConfirmationDialog *snap_dialog;  	AcceptDialog *value_dialog; @@ -304,6 +322,9 @@ class CanvasItemEditor : public VBoxContainer {  	void _append_canvas_item(CanvasItem *p_item);  	void _dialog_value_changed(double);  	void _snap_changed(); +	void _selection_result_pressed(int); +	void _selection_menu_hide(); +  	UndoRedo *undo_redo;  	Point2 _find_topleftmost_point(); diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index 8d5e7bbaea..e2202214dd 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -232,15 +232,6 @@ void SpatialEditorViewport::_select(Spatial *p_node, bool p_append,bool p_single  } - -struct _RayResult { - -	Spatial* item; -	float depth; -	int handle; -	_FORCE_INLINE_ bool operator<(const _RayResult& p_rr) const { return depth<p_rr.depth; } -}; -  ObjectID SpatialEditorViewport::_select_ray(const Point2& p_pos, bool p_append,bool &r_includes_current,int *r_gizmo_handle,bool p_alt_select) {  	if (r_gizmo_handle) @@ -379,6 +370,70 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2& p_pos, bool p_append,b  } +void SpatialEditorViewport::_find_items_at_pos(const Point2& p_pos,bool &r_includes_current,Vector<_RayResult> &results,bool p_alt_select) { + +	Vector3 ray=_get_ray(p_pos); +	Vector3 pos=_get_ray_pos(p_pos); + +	Vector<RID> instances=VisualServer::get_singleton()->instances_cull_ray(pos,ray,get_tree()->get_root()->get_world()->get_scenario() ); +	Set<Ref<SpatialEditorGizmo> > found_gizmos; + +	r_includes_current=false; + +	for (int i=0;i<instances.size();i++) { + +		uint32_t id=VisualServer::get_singleton()->instance_get_object_instance_ID(instances[i]); +		Object *obj=ObjectDB::get_instance(id); +		if (!obj) +			continue; + +		Spatial *spat=obj->cast_to<Spatial>(); + +		if (!spat) +			continue; + +		Ref<SpatialEditorGizmo> seg = spat->get_gizmo(); + +		if (!seg.is_valid()) +			continue; + +		if (found_gizmos.has(seg)) +			continue; + +		found_gizmos.insert(seg); +		Vector3 point; +		Vector3 normal; + +		int handle=-1; +		bool inters = seg->intersect_ray(camera,p_pos,point,normal,NULL,p_alt_select); + +		if (!inters) +			continue; + +		float dist = pos.distance_to(point); + +		if (dist<0) +			continue; + + + +		if (editor_selection->is_selected(spat)) +			r_includes_current=true; + +		_RayResult res; +		res.item=spat; +		res.depth=dist; +		res.handle=handle; +		results.push_back(res); +	} + + +	if (results.empty()) +		return; + +	results.sort(); +} +  Vector3 SpatialEditorViewport::_get_screen_to_space(const Vector3& p_pos) { @@ -724,6 +779,7 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {  				} break;  				case BUTTON_RIGHT: { +					NavigationScheme nav_scheme = _get_navigation_schema("3d_editor/navigation_scheme");  					if (b.pressed && _edit.gizmo.is_valid()) {  						//restore @@ -832,6 +888,57 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {  						//VisualServer::get_singleton()->poly_clear(indicators);  						set_message("Transform Aborted.",3);  					} + +					if (!b.pressed && (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT && b.mod.alt)) { + +						if (nav_scheme == NAVIGATION_MAYA) +							break; + +						_find_items_at_pos(Vector2( b.x, b.y ),clicked_includes_current,selection_results,b.mod.shift); + +						clicked_wants_append=b.mod.shift; + +						if (selection_results.size() == 1) { + +							clicked=selection_results[0].item->get_instance_ID(); +							selection_results.clear(); + +							if (clicked) { +								_select_clicked(clicked_wants_append,true); +								clicked=0; +							} + +						} else if (!selection_results.empty()) { + +							NodePath root_path = get_tree()->get_edited_scene_root()->get_path(); +							StringName root_name = root_path.get_name(root_path.get_name_count()-1); + +							for (int i = 0; i < selection_results.size(); i++) { + +								Spatial *spat=selection_results[i].item; + +								Ref<Texture> icon; +								if (spat->has_meta("_editor_icon")) +									icon=spat->get_meta("_editor_icon"); +								else +									icon=get_icon( has_icon(spat->get_type(),"EditorIcons")?spat->get_type():String("Object"),"EditorIcons"); + +								String node_path="/"+root_name+"/"+root_path.rel_path_to(spat->get_path()); + +								selection_menu->add_item(spat->get_name()); +								selection_menu->set_item_icon(i, icon ); +								selection_menu->set_item_metadata(i, node_path); +								selection_menu->set_item_tooltip(i,String(spat->get_name())+ +										"\nType: "+spat->get_type()+"\nPath: "+node_path); +							} + +							selection_menu->set_global_pos(Vector2( b.global_x, b.global_y )); +							selection_menu->popup(); +							selection_menu->call_deferred("grab_click_focus"); + +							break; +						} +					}  				} break;  				case BUTTON_MIDDLE: { @@ -2096,6 +2203,26 @@ void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) {  	}  } +void SpatialEditorViewport::_selection_result_pressed(int p_result) { + +	if (selection_results.size() <= p_result) +		return; + +	clicked=selection_results[p_result].item->get_instance_ID(); + +	if (clicked) { +		_select_clicked(clicked_wants_append,true); +		clicked=0; +	} +} + +void SpatialEditorViewport::_selection_menu_hide() { + +	selection_results.clear(); +	selection_menu->clear(); +	selection_menu->set_size(Vector2(0, 0)); +} +  void SpatialEditorViewport::set_can_preview(Camera* p_preview) {  	preview=p_preview; @@ -2210,6 +2337,8 @@ void SpatialEditorViewport::_bind_methods(){  	ObjectTypeDB::bind_method(_MD("_toggle_camera_preview"),&SpatialEditorViewport::_toggle_camera_preview);  	ObjectTypeDB::bind_method(_MD("_preview_exited_scene"),&SpatialEditorViewport::_preview_exited_scene);  	ObjectTypeDB::bind_method(_MD("update_transform_gizmo_view"),&SpatialEditorViewport::update_transform_gizmo_view); +	ObjectTypeDB::bind_method(_MD("_selection_result_pressed"),&SpatialEditorViewport::_selection_result_pressed); +	ObjectTypeDB::bind_method(_MD("_selection_menu_hide"),&SpatialEditorViewport::_selection_menu_hide);  	ADD_SIGNAL( MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")) );  } @@ -2307,6 +2436,12 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed  	preview=NULL;  	gizmo_scale=1.0; +	selection_menu = memnew( PopupMenu ); +	add_child(selection_menu); +	selection_menu->set_custom_minimum_size(Vector2(100, 0)); +	selection_menu->connect("item_pressed", this, "_selection_result_pressed"); +	selection_menu->connect("popup_hide", this, "_selection_menu_hide"); +  	if (p_index==0) {  		view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER),true);  		viewport->set_as_audio_listener(true); diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h index ff8912fca8..ebd3f77fe7 100644 --- a/tools/editor/plugins/spatial_editor_plugin.h +++ b/tools/editor/plugins/spatial_editor_plugin.h @@ -111,12 +111,21 @@ private:  	bool orthogonal;  	float gizmo_scale; +	struct _RayResult { + +		Spatial* item; +		float depth; +		int handle; +		_FORCE_INLINE_ bool operator<(const _RayResult& p_rr) const { return depth<p_rr.depth; } +	}; +  	void _update_name();  	void _compute_edit(const Point2& p_point);  	void _clear_selected();  	void _select_clicked(bool p_append,bool p_single);  	void _select(Spatial *p_node, bool p_append,bool p_single);  	ObjectID _select_ray(const Point2& p_pos, bool p_append,bool &r_includes_current,int *r_gizmo_handle=NULL,bool p_alt_select=false); +	void _find_items_at_pos(const Point2& p_pos,bool &r_includes_current,Vector<_RayResult> &results,bool p_alt_select=false);  	Vector3 _get_ray_pos(const Vector2& p_pos) const;  	Vector3 _get_ray(const Vector2& p_pos);  	Point2 _point_to_screen(const Vector3& p_point); @@ -136,9 +145,12 @@ private:  	float get_fov() const;  	ObjectID clicked; +	Vector<_RayResult> selection_results;  	bool clicked_includes_current;  	bool clicked_wants_append; +	PopupMenu *selection_menu; +  	enum NavigationScheme {  		NAVIGATION_GODOT,  		NAVIGATION_MAYA, @@ -225,6 +237,8 @@ private:  	void _toggle_camera_preview(bool);  	void _init_gizmo_instance(int p_idx);  	void _finish_gizmo_instances(); +	void _selection_result_pressed(int); +	void _selection_menu_hide();  protected: |