Browse Source

Merge pull request #1367 from not-surt/snapping2

Better 2D Snapping
Juan Linietsky 10 years ago
parent
commit
393e5605c9

+ 1 - 0
tools/editor/io_plugins/editor_import_collada.cpp

@@ -39,6 +39,7 @@
 #include "scene/resources/packed_scene.h"
 #include "os/os.h"
 #include "tools/editor/editor_node.h"
+#include <iostream>
 
 
 struct ColladaImport {

+ 253 - 233
tools/editor/plugins/canvas_item_editor_plugin.cpp

@@ -36,6 +36,110 @@
 #include "globals.h"
 #include "os/input.h"
 #include "tools/editor/editor_settings.h"
+#include "scene/gui/grid_container.h"
+
+class SnapDialog : public ConfirmationDialog {
+
+	OBJ_TYPE(SnapDialog,ConfirmationDialog);
+	
+protected:
+	friend class CanvasItemEditor;
+	SpinBox *grid_offset_x;
+	SpinBox *grid_offset_y;
+	SpinBox *grid_step_x;
+	SpinBox *grid_step_y;	
+	SpinBox *rotation_offset;	
+	SpinBox *rotation_step;
+	
+public:
+	SnapDialog() : ConfirmationDialog() {
+		const int SPIN_BOX_GRID_RANGE = 256;
+		const int SPIN_BOX_ROTATION_RANGE = 360;
+		Label *label;
+		VBoxContainer *container;
+		GridContainer *child_container;
+		
+		set_title("Configure Snap");
+		get_ok()->set_text("Close");
+		container = memnew(VBoxContainer);
+		add_child(container);
+		
+		child_container = memnew(GridContainer);
+		child_container->set_columns(3);
+		container->add_child(child_container);
+		
+		label = memnew(Label);
+		label->set_text("Grid Offset:");
+		child_container->add_child(label);
+		grid_offset_x=memnew(SpinBox);
+		grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
+		grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
+		grid_offset_x->set_suffix("px");
+		child_container->add_child(grid_offset_x);
+		grid_offset_y=memnew(SpinBox);
+		grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
+		grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
+		grid_offset_y->set_suffix("px");
+		child_container->add_child(grid_offset_y);
+
+		label = memnew(Label);
+		label->set_text("Grid Step:");
+		child_container->add_child(label);
+		grid_step_x=memnew(SpinBox);
+		grid_step_x->set_min(-SPIN_BOX_GRID_RANGE);
+		grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
+		grid_step_x->set_suffix("px");
+		child_container->add_child(grid_step_x);
+		grid_step_y=memnew(SpinBox);
+		grid_step_y->set_min(-SPIN_BOX_GRID_RANGE);
+		grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
+		grid_step_y->set_suffix("px");
+		child_container->add_child(grid_step_y);
+		
+		container->add_child(memnew(HSeparator));
+
+		child_container = memnew(GridContainer);
+		child_container->set_columns(2);
+		container->add_child(child_container);
+
+		label = memnew(Label);
+		label->set_text("Rotation Offset:");
+		child_container->add_child(label);
+		rotation_offset=memnew(SpinBox);
+		rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE);
+		rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE);
+		rotation_offset->set_suffix("deg");
+		child_container->add_child(rotation_offset);
+		
+		label = memnew(Label);
+		label->set_text("Rotation Step:");
+		child_container->add_child(label);
+		rotation_step=memnew(SpinBox);
+		rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE);
+		rotation_step->set_max(SPIN_BOX_ROTATION_RANGE);
+		rotation_step->set_suffix("deg");
+		child_container->add_child(rotation_step);
+	}
+	
+	void set_fields(const Point2 p_grid_offset, const Size2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) {
+		grid_offset_x->set_val(p_grid_offset.x);
+		grid_offset_y->set_val(p_grid_offset.y);
+		grid_step_x->set_val(p_grid_step.x);
+		grid_step_y->set_val(p_grid_step.y);
+		rotation_offset->set_val(p_rotation_offset * (180 / Math_PI));
+		rotation_step->set_val(p_rotation_step * (180 / Math_PI));
+	}
+	
+	void get_fields(Point2 &p_grid_offset, Size2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) {
+		p_grid_offset.x = grid_offset_x->get_val();
+		p_grid_offset.y = grid_offset_y->get_val();
+		p_grid_step.x = grid_step_x->get_val();
+		p_grid_step.y = grid_step_y->get_val();
+		p_rotation_offset = rotation_offset->get_val() / (180 / Math_PI);
+		p_rotation_step = rotation_step->get_val() / (180 / Math_PI);
+	}
+};
+
 void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) {
 
 	if (!is_visible())
@@ -75,9 +179,24 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
 	return memnew( CanvasItemEditorSelectedItem );
 }
 
-bool CanvasItemEditor::is_snap_active() const {
+inline float _snap_scalar(float p_offset, float p_step, bool p_snap_relative, float p_target, float p_start) {
+	float offset = p_snap_relative ? p_start : p_offset;
+	return p_step != 0 ? Math::stepify(p_target - offset, p_step) + offset : p_target;
+}
+
+Vector2 CanvasItemEditor::snap_point(Vector2 p_target, Vector2 p_start) const {
+	if (snap_grid) {
+		p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_relative, p_target.x, p_start.x);
+		p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_relative, p_target.y, p_start.y);
+	}
+	if (snap_pixel)
+		p_target = p_target.snapped(Size2(1, 1));
+
+	return p_target;
+}
 
-	return edit_menu->get_popup()->is_item_checked(edit_menu->get_popup()->get_item_index(SNAP_USE));
+float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
+	return snap_rotation ? _snap_scalar(snap_rotation_offset, snap_rotation_step, snap_relative, p_target, p_start) : p_target;
 }
 
 Dictionary CanvasItemEditor::get_state() const {
@@ -86,9 +205,15 @@ Dictionary CanvasItemEditor::get_state() const {
 	state["zoom"]=zoom;
 	state["ofs"]=Point2(h_scroll->get_val(),v_scroll->get_val());
 //	state["ofs"]=-transform.get_origin();
-	state["use_snap"]=is_snap_active();
-	state["snap_vec"]=Vector2(get_snap());
-	state["pixel_snap"]=pixel_snap;
+	state["snap_offset"]=snap_offset;
+	state["snap_step"]=snap_step;
+	state["snap_rotation_offset"]=snap_rotation_offset;
+	state["snap_rotation_step"]=snap_rotation_step;
+	state["snap_grid"]=snap_grid;
+	state["snap_show_grid"]=snap_show_grid;
+	state["snap_rotation"]=snap_rotation;
+	state["snap_relative"]=snap_relative;
+	state["snap_pixel"]=snap_pixel;
 	return state;
 }
 void CanvasItemEditor::set_state(const Dictionary& p_state){
@@ -105,27 +230,50 @@ void CanvasItemEditor::set_state(const Dictionary& p_state){
 		v_scroll->set_val(ofs.y);
 	}
 
-	if (state.has("use_snap")) {
+	if (state.has("snap_step")) {
+		snap_step=state["snap_step"];
+	}
+
+	if (state.has("snap_offset")) {
+		snap_offset=state["snap_offset"];
+	}
+
+	if (state.has("snap_rotation_step")) {
+		snap_rotation_step=state["snap_rotation_step"];
+	}
+
+	if (state.has("snap_rotation_offset")) {
+		snap_rotation_offset=state["snap_rotation_offset"];
+	}
+
+	if (state.has("snap_grid")) {
+		snap_grid=state["snap_grid"];
 		int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
-		edit_menu->get_popup()->set_item_checked(idx,state["use_snap"]);
+		edit_menu->get_popup()->set_item_checked(idx,snap_grid);
 	}
 
-	if (state.has("snap")) {
-		snap_x->set_val(state["snap"]);
-		snap_y->set_val(state["snap"]);
+	if (state.has("snap_show_grid")) {
+		snap_show_grid=state["snap_show_grid"];
+		int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
+		edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
 	}
 
-	if (state.has("snap_vec")) {
-		Vector2 sv = state["snap_vec"];
-		snap_x->set_val(sv.x);
-		snap_y->set_val(sv.y);
-		viewport->update();
+	if (state.has("snap_rotation")) {
+		snap_rotation=state["snap_rotation"];
+		int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
+		edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
 	}
 
-	if (state.has("pixel_snap")) {
-		pixel_snap=state["pixel_snap"];
+	if (state.has("snap_relative")) {
+		snap_relative=state["snap_relative"];
+		int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
+		edit_menu->get_popup()->set_item_checked(idx,snap_relative);
+	}
+
+	if (state.has("snap_pixel")) {
+		snap_pixel=state["snap_pixel"];
 		int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
-		edit_menu->get_popup()->set_item_checked(idx,pixel_snap);
+		edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
 	}
 }
 
@@ -294,9 +442,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE
 	for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 		CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-		if (!canvas_item)
-			continue;
-		if (!canvas_item->is_visible())
+		if (!canvas_item || !canvas_item->is_visible())
 			continue;
 		CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
 		if (!se)
@@ -308,7 +454,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE
 
 		Vector2 drag = p_dir;
 		if (p_snap)
-			drag*=get_snap();
+			drag*=snap_step;
 
 		undo_redo->add_undo_method(canvas_item,"edit_set_state",canvas_item->edit_get_state());
 
@@ -355,9 +501,7 @@ Point2 CanvasItemEditor::_find_topleftmost_point() {
 	for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 		CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-		if (!canvas_item)
-			continue;
-		if (!canvas_item->is_visible())
+		if (!canvas_item || !canvas_item->is_visible())
 			continue;
 
 
@@ -385,9 +529,7 @@ int CanvasItemEditor::get_item_count() {
 	for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 		CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-		if (!canvas_item)
-			continue;
-		if (!canvas_item->is_visible())
+		if (!canvas_item || !canvas_item->is_visible())
 			continue;
 
 		ic++;
@@ -406,9 +548,7 @@ CanvasItem *CanvasItemEditor::get_single_item() {
 	for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
 
 		CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
-		if (!canvas_item)
-			continue;
-		if (!canvas_item->is_visible())
+		if (!canvas_item || !canvas_item->is_visible())
 			continue;
 
 		if (single_item)
@@ -562,13 +702,11 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *c) {
 }
 
 
-void CanvasItemEditor::_snap_changed(double) {
-
+void CanvasItemEditor::_snap_changed() {
+	((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
 	viewport->update();
 }
 
-
-
 void CanvasItemEditor::_dialog_value_changed(double) {
 
 	if (updating_value_dialog)
@@ -576,11 +714,6 @@ void CanvasItemEditor::_dialog_value_changed(double) {
 
 	switch(last_option) {
 
-		case SNAP_CONFIGURE: {
-
-		//	snap=dialog_val->get_val();
-			viewport->update();
-		} break;
 		case ZOOM_SET: {
 
 			zoom=dialog_val->get_val()/100.0;
@@ -676,9 +809,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
 					for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 						CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-						if (!canvas_item)
-							continue;
-						if (!canvas_item->is_visible())
+						if (!canvas_item || !canvas_item->is_visible())
 							continue;
 
 						CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
@@ -750,9 +881,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
 						for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 							CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-							if (!canvas_item)
-								continue;
-							if (!canvas_item->is_visible())
+							if (!canvas_item || !canvas_item->is_visible())
 								continue;
 							CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
 							if (!se)
@@ -958,9 +1087,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
 			for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 				CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
 				if (!se)
@@ -1083,9 +1210,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
 			for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 				CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
 				if (!se)
@@ -1141,9 +1266,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
 		for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 			CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-			if (!canvas_item)
-				continue;
-			if (!canvas_item->is_visible())
+			if (!canvas_item || !canvas_item->is_visible())
 				continue;
 			CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
 			if (!se)
@@ -1168,39 +1291,21 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
 			if (drag==DRAG_ROTATE) {
 
 				Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin();
-
-				Matrix32 rot;
-				rot.elements[1] = (dfrom - center).normalized();
-				rot.elements[0] = rot.elements[1].tangent();
-				float ang = rot.xform_inv(dto-center).atan2();
-				canvas_item->edit_rotate(ang);
-				display_rotate_to = dto;
-				display_rotate_from = center;
+				if (Node2D *node = canvas_item->cast_to<Node2D>()) {
+					Matrix32 rot;
+					rot.elements[1] = (dfrom - center).normalized();
+					rot.elements[0] = rot.elements[1].tangent();
+					node->set_rot(snap_angle(rot.xform_inv(dto-center).atan2(), node->get_rot()));
+					display_rotate_to = dto;
+					display_rotate_from = center;
+					viewport->update();
+				}
 
 				continue;
 			}
 
-			if (pixel_snap || (is_snap_active() && get_snap().x>0 && get_snap().y>0)) {
-
-				if (drag!=DRAG_ALL) {
-					dfrom=drag_point_from;
-					dto=snapify(dto);
-				} else {
-
-					Vector2 newpos = drag_point_from + (dto-dfrom);
-					Vector2 disp;
-					if (!is_snap_active() || get_snap().x<1 || get_snap().y<1) {
-
-						disp.x = Math::fposmod(newpos.x,1);
-						disp.y = Math::fposmod(newpos.y,1);
-
-					} else {
-						disp.x = Math::fposmod(newpos.x,get_snap().x);
-						disp.y = Math::fposmod(newpos.y,get_snap().y);
-					}
-					dto-=disp;
-				}
-			}
+			dfrom = drag_point_from;
+			dto = snap_point(dto - (drag == DRAG_ALL ? drag_from - drag_point_from : Vector2(0, 0)), drag_point_from);
 
 			Vector2 drag_vector =
 					canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) -
@@ -1308,8 +1413,6 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
 
 
 
-
-
 			if (!dragging_bone) {
 
 				local_rect.pos=begin;
@@ -1492,32 +1595,32 @@ void CanvasItemEditor::_viewport_draw() {
 	_update_scrollbars();
 	RID ci=viewport->get_canvas_item();
 
-	if (get_snap().x>0 && get_snap().y>0 && is_snap_active() && true ) {
-
+	if (snap_show_grid) {
 		Size2 s = viewport->get_size();
-
 		int last_cell;
 		Matrix32 xform = transform.affine_inverse();
-		for(int i=0;i<s.width;i++) {
 
-			int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(i,0)).x/get_snap().x));
-			if (i==0)
+		if (snap_step.x!=0) {
+			for(int i=0;i<s.width;i++) {
+				int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x));
+				if (i==0)
+					last_cell=cell;
+				if (last_cell!=cell)
+					viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
 				last_cell=cell;
-			if (last_cell!=cell)
-				viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
-			last_cell=cell;
+			}
 		}
 
-		for(int i=0;i<s.height;i++) {
-
-			int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(0,i)).y/get_snap().y));
-			if (i==0)
+		if (snap_step.y!=0) {
+			for(int i=0;i<s.height;i++) {
+				int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y));
+				if (i==0)
+					last_cell=cell;
+				if (last_cell!=cell)
+					viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
 				last_cell=cell;
-			if (last_cell!=cell)
-				viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
-			last_cell=cell;
+			}
 		}
-
 	}
 
 	if (viewport->has_focus()) {
@@ -1545,9 +1648,7 @@ void CanvasItemEditor::_viewport_draw() {
 
 
 		CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
-		if (!canvas_item)
-			continue;
-		if (!canvas_item->is_visible())
+		if (!canvas_item || !canvas_item->is_visible())
 			continue;
 		CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
 		if (!se)
@@ -1764,9 +1865,7 @@ void CanvasItemEditor::_notification(int p_what) {
 		for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 			CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-			if (!canvas_item)
-				continue;
-			if (!canvas_item->is_visible())
+			if (!canvas_item || !canvas_item->is_visible())
 				continue;
 
 			CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
@@ -1824,8 +1923,6 @@ void CanvasItemEditor::_notification(int p_what) {
 		group_button->set_icon(get_icon("Group","EditorIcons"));
 		ungroup_button->set_icon(get_icon("Ungroup","EditorIcons"));
 		key_insert_button->set_icon(get_icon("Key","EditorIcons"));
-		snap_x->connect("value_changed",this,"_snap_changed");
-		snap_y->connect("value_changed",this,"_snap_changed");
 
 	}
 
@@ -2013,90 +2110,40 @@ void CanvasItemEditor::_update_scroll(float) {
 }
 
 
-Point2 CanvasItemEditor::snapify(const Point2& p_pos) const {
-
-	bool active=is_snap_active();
-
-	Vector2 pos = p_pos;
-
-	if (!active || get_snap().x<1 || get_snap().y<1) {
-
-		if (pixel_snap) {
-
-			pos.x=Math::stepify(pos.x,1);
-			pos.y=Math::stepify(pos.y,1);
-		}
-
-		return pos;
-	}
-
-	
-	pos.x=Math::stepify(pos.x,get_snap().x);
-	pos.y=Math::stepify(pos.y,get_snap().y);
-	return pos;
-
-
-}
-
-
 void CanvasItemEditor::_popup_callback(int p_op) {
 
 	last_option=MenuOption(p_op);
 	switch(p_op) {
 
 		case SNAP_USE: {
-
+			snap_grid = !snap_grid;
 			int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
-			edit_menu->get_popup()->set_item_checked( idx,!edit_menu->get_popup()->is_item_checked(0));
+			edit_menu->get_popup()->set_item_checked(idx,snap_grid);
+		} break;
+		case SNAP_SHOW_GRID: {
+			snap_show_grid = !snap_show_grid;
+			int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
+			edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
 			viewport->update();
 		} break;
+		case SNAP_USE_ROTATION: {
+			snap_rotation = !snap_rotation;
+			int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
+			edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
+		} break;
+		case SNAP_RELATIVE: {
+			snap_relative = !snap_relative;
+			int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
+			edit_menu->get_popup()->set_item_checked(idx,snap_relative);
+		} break;
 		case SNAP_USE_PIXEL: {
-			pixel_snap = ! pixel_snap;
+			snap_pixel = !snap_pixel;
 			int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
-			edit_menu->get_popup()->set_item_checked(idx,pixel_snap);
-		} break;
-		case SNAP_OBJECT_CENTERS: {
-
-			List<Node*> &selection = editor_selection->get_selected_node_list();
-
-			undo_redo->create_action("Snap Object Centers");
-			for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
-				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
-					continue;
-				Node2D* node = canvas_item->cast_to<Node2D>();
-				if (!node)
-					continue;
-
-				Matrix32 gtrans = node->get_global_transform();
-				gtrans.elements[2]=snapify(gtrans.elements[2]);
-
-				undo_redo->add_do_method(node,"set_global_transform",gtrans);
-				undo_redo->add_undo_method(node,"set_global_transform",node->get_global_transform());
-			}
-
-			undo_redo->add_do_method(viewport,"update");
-			undo_redo->add_undo_method(viewport,"update");
-			undo_redo->commit_action();
-
+			edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
 		} break;
 		case SNAP_CONFIGURE: {
-				updating_value_dialog=true;
-
-				snap_dialog->popup_centered_minsize();
-/*
-				dialog_label->set_text("Snap (Pixels):");
-				dialog_val->set_min(1);
-				dialog_val->set_step(1);
-				dialog_val->set_max(4096);
-				dialog_val->set_val(snap);
-				value_dialog->popup_centered(Size2(200,85));
-				*/
-				updating_value_dialog=false;
-
+			((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
+			snap_dialog->popup_centered(Size2(200,160));
 		} break;
 		case ZOOM_IN: {
 			zoom=zoom*(1.0/0.5);
@@ -2140,9 +2187,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 			for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 
 				canvas_item->set_meta("_edit_lock_",true);
@@ -2157,9 +2202,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 			for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 
 
@@ -2177,9 +2220,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 			for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 
 				canvas_item->set_meta("_edit_group_",true);
@@ -2194,9 +2235,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 			for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 
 				canvas_item->set_meta("_edit_group_",Variant());
@@ -2214,9 +2253,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 			for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 
 
@@ -2284,9 +2321,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 			for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 
 				if (canvas_item->cast_to<Node2D>()) {
@@ -2396,9 +2431,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 			for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 
 
@@ -2448,9 +2481,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 			for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 
 				if (canvas_item->cast_to<Node2D>()) {
@@ -2576,9 +2607,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 			for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 				CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
-				if (!canvas_item)
-					continue;
-				if (!canvas_item->is_visible())
+				if (!canvas_item || !canvas_item->is_visible())
 					continue;
 
 
@@ -2858,10 +2887,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
 	PopupMenu *p;
 	p = edit_menu->get_popup();
 	p->add_check_item("Use Snap",SNAP_USE);
+	p->add_check_item("Show Grid",SNAP_SHOW_GRID);
+	p->add_check_item("Use Rotation Snap",SNAP_USE_ROTATION);
+	p->add_check_item("Snap Relative",SNAP_RELATIVE);
 	p->add_item("Configure Snap..",SNAP_CONFIGURE);
 	p->add_separator();
 	p->add_check_item("Use Pixel Snap",SNAP_USE_PIXEL);
-	p->add_item("Snap Selected Object Centers",SNAP_OBJECT_CENTERS);
 	p->add_separator();
 	p->add_item("Expand to Parent",EXPAND_TO_PARENT,KEY_MASK_CMD|KEY_P);
 	p->add_separator();
@@ -2949,6 +2980,10 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
 	p->add_item("Paste Pose",ANIM_PASTE_POSE);
 	p->add_item("Clear Pose",ANIM_CLEAR_POSE,KEY_MASK_SHIFT|KEY_K);
 
+	snap_dialog = memnew(SnapDialog);
+	snap_dialog->connect("confirmed",this,"_snap_changed");
+	add_child(snap_dialog);
+
 	value_dialog = memnew( AcceptDialog );
 	value_dialog->set_title("Set a Value");
 	value_dialog->get_ok()->set_text("Close");
@@ -2968,33 +3003,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
 	dialog_val->connect("value_changed",this,"_dialog_value_changed");
 	select_sb = Ref<StyleBoxTexture>( memnew( StyleBoxTexture) );
 
-	snap_dialog = memnew( AcceptDialog );
-	VBoxContainer *snap_vb = memnew( VBoxContainer );
-	snap_dialog->add_child(snap_vb);
-	snap_dialog->set_child_rect(snap_vb);
-	snap_dialog->set_title("Snap Configuration");
-	snap_x = memnew( SpinBox );
-	snap_x->set_custom_minimum_size(Size2(250,0));
-	snap_y = memnew( SpinBox );
-	snap_x->set_min(1);
-	snap_x->set_max(4096);
-	snap_x->set_step(1);
-	snap_x->set_val(10);
-	snap_y->set_min(1);
-	snap_y->set_max(4096);
-	snap_y->set_step(1);
-	snap_y->set_val(10);
-	snap_vb->add_margin_child("Snap X",snap_x);
-	snap_vb->add_margin_child("Snap Y",snap_y);
-	add_child(snap_dialog);
-
-
 	key_pos=true;
 	key_rot=true;
 	key_scale=false;
 
 	zoom=1;
-	//snap=10;
+	snap_offset=Vector2(0, 0);
+	snap_step=Vector2(10, 10);
+	snap_rotation_offset=0;
+	snap_rotation_step=15 / (180 / Math_PI);
+	snap_grid=false;
+	snap_show_grid=false;
+	snap_rotation=false;
+	snap_pixel=false;
 	updating_value_dialog=false;
 	box_selecting=false;
 	//zoom=0.5;
@@ -3002,7 +3023,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
 	editor->get_animation_editor()->connect("keying_changed",this,"_keying_changed");
 	set_process_unhandled_key_input(true);
 	can_move_pivot=false;
-	pixel_snap=false;
 	drag=DRAG_NONE;
 }
 

+ 18 - 11
tools/editor/plugins/canvas_item_editor_plugin.h

@@ -75,9 +75,11 @@ class CanvasItemEditor : public VBoxContainer {
 
 	enum MenuOption {
 		SNAP_USE,
+		SNAP_SHOW_GRID,
+		SNAP_USE_ROTATION,
+		SNAP_RELATIVE,
 		SNAP_CONFIGURE,
 		SNAP_USE_PIXEL,
-		SNAP_OBJECT_CENTERS,
 		ZOOM_IN,
 		ZOOM_OUT,
 		ZOOM_RESET,
@@ -144,7 +146,15 @@ class CanvasItemEditor : public VBoxContainer {
 
 	Matrix32 transform;
 	float zoom;
-	bool pixel_snap;
+	Vector2 snap_offset;
+	Vector2 snap_step;
+	float snap_rotation_step;
+	float snap_rotation_offset;
+	bool snap_grid;
+	bool snap_show_grid;
+	bool snap_rotation;
+	bool snap_relative;
+	bool snap_pixel;
 	bool box_selecting;
 	Point2 box_selecting_to;
 	bool key_pos;
@@ -247,14 +257,12 @@ class CanvasItemEditor : public VBoxContainer {
 	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_rect(const Rect2& p_rect,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform,List<CanvasItem*> *r_items);
 
+	ConfirmationDialog *snap_dialog;
+	
 	AcceptDialog *value_dialog;
 	Label *dialog_label;
 	SpinBox *dialog_val;
-
-	AcceptDialog *snap_dialog;
-	SpinBox *snap_x;
-	SpinBox *snap_y;
-
+	
 	CanvasItem *ref_item;
 
 	void _add_canvas_item(CanvasItem *p_canvas_item);
@@ -265,7 +273,6 @@ class CanvasItemEditor : public VBoxContainer {
 
 	DragType _find_drag_type(const Matrix32& p_xform, const Rect2& p_local_rect, const Point2& p_click, Vector2& r_point);
 
-	Point2 snapify(const Point2& p_pos) const;
 	void _popup_callback(int p_op);
 	bool updating_scroll;
 	void _update_scroll(float);
@@ -275,6 +282,7 @@ class CanvasItemEditor : public VBoxContainer {
 
 	void _append_canvas_item(CanvasItem *p_item);
 	void _dialog_value_changed(double);
+	void _snap_changed();
 	UndoRedo *undo_redo;
 
 	Point2 _find_topleftmost_point();
@@ -293,7 +301,6 @@ class CanvasItemEditor : public VBoxContainer {
 
 	void _viewport_input_event(const InputEvent& p_event);
 	void _viewport_draw();
-	void _snap_changed(double);
 
 	HSplitContainer *palette_split;
 	VSplitContainer *bottom_split;
@@ -339,8 +346,8 @@ protected:
 	static CanvasItemEditor *singleton;
 public:
 
-	bool is_snap_active() const;
-	Size2i get_snap() const { return Size2i(snap_x->get_val(),snap_y->get_val()); }
+	Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const;
+	float snap_angle(float p_target, float p_start = 0) const;
 
 	Matrix32 get_canvas_transform() const { return transform; }
 

+ 2 - 13
tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp

@@ -35,17 +35,6 @@ void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
 }
 
 
-Vector2 CollisionPolygon2DEditor::snap_point(const Vector2& p_point) const {
-
-	if (canvas_item_editor->is_snap_active()) {
-
-		return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
-	} else {
-		return p_point;
-	}
-}
-
 void CollisionPolygon2DEditor::_menu_option(int p_option) {
 
 	switch(p_option) {
@@ -99,7 +88,7 @@ bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) {
 
 			Vector2 gpoint = Point2(mb.x,mb.y);
 			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-			cpoint=snap_point(cpoint);
+			cpoint=canvas_item_editor->snap_point(cpoint);
 			cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
 
 			Vector<Vector2> poly = node->get_polygon();
@@ -302,7 +291,7 @@ bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) {
 
 				Vector2 gpoint = Point2(mm.x,mm.y);
 				Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-				cpoint=snap_point(cpoint);
+				cpoint=canvas_item_editor->snap_point(cpoint);
 				edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
 
 				canvas_item_editor->get_viewport_control()->update();

+ 0 - 1
tools/editor/plugins/collision_polygon_2d_editor_plugin.h

@@ -53,7 +53,6 @@ protected:
 	static void _bind_methods();
 public:
 
-	Vector2 snap_point(const Vector2& p_point) const;
 	bool forward_input_event(const InputEvent& p_event);
 	void edit(Node *p_collision_polygon);
 	CollisionPolygon2DEditor(EditorNode *p_editor);

+ 2 - 15
tools/editor/plugins/collision_polygon_editor_plugin.cpp

@@ -70,19 +70,6 @@ void CollisionPolygonEditor::_node_removed(Node *p_node) {
 }
 
 
-Vector2 CollisionPolygonEditor::snap_point(const Vector2& p_point) const {
-
-	return p_point;
-	
-	if (CanvasItemEditor::get_singleton()->is_snap_active()) {
-
-		return p_point.snapped(Vector2(1,1)*CanvasItemEditor::get_singleton()->get_snap());
-
-	} else {
-		return p_point;
-	}
-}
-
 void CollisionPolygonEditor::_menu_option(int p_option) {
 
 	switch(p_option) {
@@ -150,7 +137,7 @@ bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const
 
 			Vector2 cpoint(spoint.x,spoint.y);
 
-			cpoint=snap_point(cpoint);
+			cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
 
 			Vector<Vector2> poly = node->get_polygon();
 
@@ -364,7 +351,7 @@ bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const
 
 				Vector2 cpoint(spoint.x,spoint.y);
 
-				cpoint=snap_point(cpoint);
+				cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
 				edited_point_pos = cpoint;
 
 				_polygon_draw();

+ 0 - 1
tools/editor/plugins/collision_polygon_editor_plugin.h

@@ -90,7 +90,6 @@ protected:
 	static void _bind_methods();
 public:
 
-	Vector2 snap_point(const Vector2& p_point) const;
 	virtual bool forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event);
 	void edit(Node *p_collision_polygon);
 	CollisionPolygonEditor(EditorNode *p_editor);

+ 2 - 13
tools/editor/plugins/light_occluder_2d_editor_plugin.cpp

@@ -35,17 +35,6 @@ void LightOccluder2DEditor::_node_removed(Node *p_node) {
 }
 
 
-Vector2 LightOccluder2DEditor::snap_point(const Vector2& p_point) const {
-
-	if (canvas_item_editor->is_snap_active()) {
-
-		return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
-	} else {
-		return p_point;
-	}
-}
-
 void LightOccluder2DEditor::_menu_option(int p_option) {
 
 	switch(p_option) {
@@ -109,7 +98,7 @@ bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) {
 
 			Vector2 gpoint = Point2(mb.x,mb.y);
 			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-			cpoint=snap_point(cpoint);
+			cpoint=canvas_item_editor->snap_point(cpoint);
 			cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
 
 			Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon());
@@ -317,7 +306,7 @@ bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) {
 
 				Vector2 gpoint = Point2(mm.x,mm.y);
 				Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-				cpoint=snap_point(cpoint);
+				cpoint=canvas_item_editor->snap_point(cpoint);
 				edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
 
 				canvas_item_editor->get_viewport_control()->update();

+ 2 - 13
tools/editor/plugins/navigation_polygon_editor_plugin.cpp

@@ -45,17 +45,6 @@ void NavigationPolygonEditor::_create_nav()  {
 	undo_redo->commit_action();
 }
 
-Vector2 NavigationPolygonEditor::snap_point(const Vector2& p_point) const {
-
-	if (canvas_item_editor->is_snap_active()) {
-
-		return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
-	} else {
-		return p_point;
-	}
-}
-
 void NavigationPolygonEditor::_menu_option(int p_option) {
 
 	switch(p_option) {
@@ -125,7 +114,7 @@ bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) {
 
 			Vector2 gpoint = Point2(mb.x,mb.y);
 			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-			cpoint=snap_point(cpoint);
+			cpoint=canvas_item_editor->snap_point(cpoint);
 			cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
 
 
@@ -373,7 +362,7 @@ bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) {
 
 				Vector2 gpoint = Point2(mm.x,mm.y);
 				Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-				cpoint=snap_point(cpoint);
+				cpoint=canvas_item_editor->snap_point(cpoint);
 				edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
 
 				canvas_item_editor->get_viewport_control()->update();

+ 0 - 1
tools/editor/plugins/navigation_polygon_editor_plugin.h

@@ -59,7 +59,6 @@ protected:
 	static void _bind_methods();
 public:
 
-	Vector2 snap_point(const Vector2& p_point) const;
 	bool forward_input_event(const InputEvent& p_event);
 	void edit(Node *p_collision_polygon);
 	NavigationPolygonEditor(EditorNode *p_editor);

+ 10 - 21
tools/editor/plugins/path_2d_editor_plugin.cpp

@@ -62,17 +62,6 @@ void Path2DEditor::_node_removed(Node *p_node) {
 }
 
 
-Vector2 Path2DEditor::snap_point(const Vector2& p_point) const {
-
-	if (canvas_item_editor->is_snap_active()) {
-
-		return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
-	} else {
-		return p_point;
-	}
-}
-
 bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
 
 	if (!node)
@@ -93,8 +82,8 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
 			Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
 			Vector2 gpoint = Point2(mb.x,mb.y);
-			Vector2 cpoint = !mb.mod.alt? snap_point(xform.affine_inverse().xform(gpoint))
-										: node->get_global_transform().affine_inverse().xform( snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
+			Vector2 cpoint = !mb.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
+										: node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
 
 			//first check if a point is to be added (segment split)
 			real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8);
@@ -250,9 +239,9 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
 						if (!wip_active) {
 
 							wip.clear();
-							wip.push_back( snap_point(cpoint) );
+							wip.push_back( canvas_item_editor->snap_point(cpoint) );
 							wip_active=true;
-							edited_point_pos=snap_point(cpoint);
+							edited_point_pos=canvas_item_editor->snap_point(cpoint);
 							canvas_item_editor->update();
 							edited_point=1;
 							return true;
@@ -265,7 +254,7 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
 								return true;
 							} else {
 
-								wip.push_back( snap_point(cpoint) );
+								wip.push_back( canvas_item_editor->snap_point(cpoint) );
 								edited_point=wip.size();
 								canvas_item_editor->update();
 								return true;
@@ -327,9 +316,9 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
 								if (closest_idx>=0) {
 
 									pre_move_edit=poly;
-									poly.insert(closest_idx+1,snap_point(xform.affine_inverse().xform(closest_pos)));
+									poly.insert(closest_idx+1,canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos)));
 									edited_point=closest_idx+1;
-									edited_point_pos=snap_point(xform.affine_inverse().xform(closest_pos));
+									edited_point_pos=canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos));
 									node->set_polygon(poly);
 									canvas_item_editor->update();
 									return true;
@@ -434,8 +423,8 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
 
 				Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 				Vector2 gpoint = Point2(mm.x,mm.y);
-				Vector2 cpoint = !mm.mod.alt? snap_point(xform.affine_inverse().xform(gpoint))
-											: node->get_global_transform().affine_inverse().xform( snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
+				Vector2 cpoint = !mm.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
+											: node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
 
 				Ref<Curve2D> curve = node->get_curve();
 
@@ -471,7 +460,7 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
 				Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
 				Vector2 gpoint = Point2(mm.x,mm.y);
-				edited_point_pos = snap_point(xform.affine_inverse().xform(gpoint));
+				edited_point_pos = canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint));
 				canvas_item_editor->update();
 
 			}

+ 0 - 1
tools/editor/plugins/path_2d_editor_plugin.h

@@ -94,7 +94,6 @@ protected:
 	static void _bind_methods();
 public:
 
-	Vector2 snap_point(const Vector2& p_point) const;
 	bool forward_input_event(const InputEvent& p_event);
 	void edit(Node *p_path2d);
 	Path2DEditor(EditorNode *p_editor);

+ 2 - 13
tools/editor/plugins/polygon_2d_editor_plugin.cpp

@@ -69,17 +69,6 @@ void Polygon2DEditor::_node_removed(Node *p_node) {
 }
 
 
-Vector2 Polygon2DEditor::snap_point(const Vector2& p_point) const {
-
-	if (canvas_item_editor->is_snap_active()) {
-
-		return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
-
-	} else {
-		return p_point;
-	}
-}
-
 void Polygon2DEditor::_menu_option(int p_option) {
 
 	switch(p_option) {
@@ -201,7 +190,7 @@ bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) {
 
 			Vector2 gpoint = Point2(mb.x,mb.y);
 			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-			cpoint=snap_point(cpoint);
+			cpoint=canvas_item_editor->snap_point(cpoint);
 			cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
 
 
@@ -405,7 +394,7 @@ bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) {
 
 				Vector2 gpoint = Point2(mm.x,mm.y);
 				Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-				cpoint=snap_point(cpoint);
+				cpoint=canvas_item_editor->snap_point(cpoint);
 				edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
 
 				canvas_item_editor->get_viewport_control()->update();

+ 0 - 1
tools/editor/plugins/polygon_2d_editor_plugin.h

@@ -92,7 +92,6 @@ protected:
 	static void _bind_methods();
 public:
 
-	Vector2 snap_point(const Vector2& p_point) const;
 	bool forward_input_event(const InputEvent& p_event);
 	void edit(Node *p_collision_polygon);
 	Polygon2DEditor(EditorNode *p_editor);

+ 0 - 1
tools/editor/plugins/tile_map_editor_plugin.h

@@ -116,7 +116,6 @@ protected:
 public:
 
 	HBoxContainer *get_canvas_item_editor_hb() const { return canvas_item_editor_hb; }
-	Vector2 snap_point(const Vector2& p_point) const;
 	bool forward_input_event(const InputEvent& p_event);
 	void edit(Node *p_tile_map);
 	TileMapEditor(EditorNode *p_editor);