浏览代码

Prep for tile transpose transform.

Carl Olsson 10 年之前
父节点
当前提交
a8b318871c

+ 7 - 7
core/object.h

@@ -35,13 +35,13 @@
 #include "map.h"
 #include "map.h"
 #include "vmap.h"
 #include "vmap.h"
 
 
-#define VARIANT_ARG_LIST const Variant& p_arg1=Variant(),const Variant& p_arg2=Variant(),const Variant& p_arg3=Variant(),const Variant& p_arg4=Variant(),const Variant& p_arg5=Variant()
-#define VARIANT_ARG_PASS p_arg1,p_arg2,p_arg3,p_arg4,p_arg5
-#define VARIANT_ARG_DECLARE const Variant& p_arg1,const Variant& p_arg2,const Variant& p_arg3,const Variant& p_arg4,const Variant& p_arg5
-#define VARIANT_ARG_MAX 5
-#define VARIANT_ARGPTRS const Variant *argptr[5]={&p_arg1,&p_arg2,&p_arg3,&p_arg4,&p_arg5};
-#define VARIANT_ARGPTRS_PASS *argptr[0],*argptr[1],*argptr[2],*argptr[3],*argptr[4]
-#define VARIANT_ARGS_FROM_ARRAY(m_arr) m_arr[0],m_arr[1],m_arr[2],m_arr[3],m_arr[4]
+#define VARIANT_ARG_LIST const Variant& p_arg1=Variant(),const Variant& p_arg2=Variant(),const Variant& p_arg3=Variant(),const Variant& p_arg4=Variant(),const Variant& p_arg5=Variant(),const Variant& p_arg6=Variant()
+#define VARIANT_ARG_PASS p_arg1,p_arg2,p_arg3,p_arg4,p_arg5,p_arg6
+#define VARIANT_ARG_DECLARE const Variant& p_arg1,const Variant& p_arg2,const Variant& p_arg3,const Variant& p_arg4,const Variant& p_arg5,const Variant& p_arg6
+#define VARIANT_ARG_MAX 6
+#define VARIANT_ARGPTRS const Variant *argptr[6]={&p_arg1,&p_arg2,&p_arg3,&p_arg4,&p_arg5,&p_arg6};
+#define VARIANT_ARGPTRS_PASS *argptr[0],*argptr[1],*argptr[2],*argptr[3],*argptr[4],*argptr[5]
+#define VARIANT_ARGS_FROM_ARRAY(m_arr) m_arr[0],m_arr[1],m_arr[2],m_arr[3],m_arr[4],m_arr[5]
 
 
 /**
 /**
 @author Juan Linietsky <[email protected]>
 @author Juan Linietsky <[email protected]>

+ 1 - 1
core/variant.h

@@ -387,7 +387,7 @@ public:
 	};
 	};
 
 
 	Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,CallError &r_error);
 	Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,CallError &r_error);
-	Variant call(const StringName& p_method,const Variant& p_arg1=Variant(),const Variant& p_arg2=Variant(),const Variant& p_arg3=Variant(),const Variant& p_arg4=Variant(),const Variant& p_arg5=Variant());
+	Variant call(const StringName& p_method,const Variant& p_arg1=Variant(),const Variant& p_arg2=Variant(),const Variant& p_arg3=Variant(),const Variant& p_arg4=Variant(),const Variant& p_arg5=Variant(),const Variant& p_arg6=Variant());
 	static Variant construct(const Variant::Type,const Variant** p_args,int p_argcount,CallError &r_error);
 	static Variant construct(const Variant::Type,const Variant** p_args,int p_argcount,CallError &r_error);
 
 
 	void get_method_list(List<MethodInfo> *p_list) const;
 	void get_method_list(List<MethodInfo> *p_list) const;

+ 4 - 4
demos/2d/polygon_path_finder_demo/.fscache

@@ -1,4 +1,4 @@
-::res://::1421147952
-icon.png::ImageTexture::1420046079::
-new_scene_poly_with_holes.scn::PackedScene::1421147952::
-polygonpathfinder.gd::GDScript::1421146502::
+::res://::1421669411
+icon.png::ImageTexture::1421499066::
+new_scene_poly_with_holes.scn::PackedScene::1421499066::
+polygonpathfinder.gd::GDScript::1421669411::

+ 29 - 4
scene/2d/tile_map.cpp

@@ -29,6 +29,7 @@
 #include "tile_map.h"
 #include "tile_map.h"
 #include "io/marshalls.h"
 #include "io/marshalls.h"
 #include "servers/physics_2d_server.h"
 #include "servers/physics_2d_server.h"
+#include "method_bind_ext.inc"
 void TileMap::_notification(int p_what) {
 void TileMap::_notification(int p_what) {
 
 
 	switch(p_what) {
 	switch(p_what) {
@@ -221,6 +222,10 @@ void TileMap::_update_dirty_quadrants() {
 				rect.size.x=-rect.size.x;
 				rect.size.x=-rect.size.x;
 			if (c.flip_v)
 			if (c.flip_v)
 				rect.size.y=-rect.size.y;
 				rect.size.y=-rect.size.y;
+			if (c.transpose) {
+				//TODO
+			}
+				
 
 
 
 
 			rect.pos+=tile_ofs;
 			rect.pos+=tile_ofs;
@@ -257,6 +262,11 @@ void TileMap::_update_dirty_quadrants() {
 
 
 						xform.elements[2].y+=shape_ofs.y;
 						xform.elements[2].y+=shape_ofs.y;
 					}
 					}
+					if (c.transpose) {
+						//TODO
+					} else {
+					}
+
 
 
 
 
 					ps->body_add_shape(q.static_body,shape->get_rid(),xform);
 					ps->body_add_shape(q.static_body,shape->get_rid(),xform);
@@ -385,7 +395,7 @@ void TileMap::_make_quadrant_dirty(Map<PosKey,Quadrant>::Element *Q) {
 }
 }
 
 
 
 
-void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) {
+void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bool p_transpose) {
 
 
 	PosKey pk(p_x,p_y);
 	PosKey pk(p_x,p_y);
 
 
@@ -421,7 +431,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) {
 	} else {
 	} else {
 		ERR_FAIL_COND(!Q); // quadrant should exist...
 		ERR_FAIL_COND(!Q); // quadrant should exist...
 
 
-		if (E->get().id==p_tile && E->get().flip_h==p_flip_x && E->get().flip_v==p_flip_y)
+		if (E->get().id==p_tile && E->get().flip_h==p_flip_x && E->get().flip_v==p_flip_y && E->get().transpose==p_transpose)
 			return; //nothing changed
 			return; //nothing changed
 
 
 	}
 	}
@@ -432,6 +442,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) {
 	c.id=p_tile;
 	c.id=p_tile;
 	c.flip_h=p_flip_x;
 	c.flip_h=p_flip_x;
 	c.flip_v=p_flip_y;
 	c.flip_v=p_flip_y;
+	c.transpose=p_transpose;
 
 
 	_make_quadrant_dirty(Q);
 	_make_quadrant_dirty(Q);
 
 
@@ -471,6 +482,17 @@ bool TileMap::is_cell_y_flipped(int p_x,int p_y) const {
 
 
 	return E->get().flip_v;
 	return E->get().flip_v;
 }
 }
+bool TileMap::is_cell_transposed(int p_x,int p_y) const {
+
+	PosKey pk(p_x,p_y);
+
+	const Map<PosKey,Cell>::Element *E=tile_map.find(pk);
+
+	if (!E)
+		return false;
+
+	return E->get().transpose;
+}
 
 
 
 
 void TileMap::_recreate_quadrants() {
 void TileMap::_recreate_quadrants() {
@@ -535,11 +557,12 @@ void TileMap::_set_tile_data(const DVector<int>& p_data) {
 		uint32_t v = decode_uint32(&local[4]);
 		uint32_t v = decode_uint32(&local[4]);
 		bool flip_h = v&(1<<29);
 		bool flip_h = v&(1<<29);
 		bool flip_v = v&(1<<30);
 		bool flip_v = v&(1<<30);
+		bool transpose = v&(1<<31);
 		v&=(1<<29)-1;
 		v&=(1<<29)-1;
 
 
 //		if (x<-20 || y <-20 || x>4000 || y>4000)
 //		if (x<-20 || y <-20 || x>4000 || y>4000)
 //			continue;
 //			continue;
-		set_cell(x,y,v,flip_h,flip_v);
+		set_cell(x,y,v,flip_h,flip_v,transpose);
 
 
 	}
 	}
 
 
@@ -562,6 +585,8 @@ DVector<int> TileMap::_get_tile_data() const {
 			val|=(1<<29);
 			val|=(1<<29);
 		if (E->get().flip_v)
 		if (E->get().flip_v)
 			val|=(1<<30);
 			val|=(1<<30);
+		if (E->get().transpose)
+			val|=(1<<31);
 
 
 		encode_uint32(val,&ptr[4]);
 		encode_uint32(val,&ptr[4]);
 		idx+=2;
 		idx+=2;
@@ -813,7 +838,7 @@ void TileMap::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_collision_bounce","value"),&TileMap::set_collision_bounce);
 	ObjectTypeDB::bind_method(_MD("set_collision_bounce","value"),&TileMap::set_collision_bounce);
 	ObjectTypeDB::bind_method(_MD("get_collision_bounce"),&TileMap::get_collision_bounce);
 	ObjectTypeDB::bind_method(_MD("get_collision_bounce"),&TileMap::get_collision_bounce);
 
 
-	ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false));
+	ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false));
 	ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell);
 	ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell);
 	ObjectTypeDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped);
 	ObjectTypeDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped);
 	ObjectTypeDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped);
 	ObjectTypeDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped);

+ 3 - 1
scene/2d/tile_map.h

@@ -85,6 +85,7 @@ private:
 			int32_t id:24;
 			int32_t id:24;
 			bool flip_h:1;
 			bool flip_h:1;
 			bool flip_v:1;
 			bool flip_v:1;
+			bool transpose:1;
 		};
 		};
 
 
 		uint32_t _u32t;
 		uint32_t _u32t;
@@ -167,10 +168,11 @@ public:
 	void set_center_y(bool p_enable);
 	void set_center_y(bool p_enable);
 	bool get_center_y() const;
 	bool get_center_y() const;
 
 
-	void set_cell(int p_x,int p_y,int p_tile,bool p_flip_x=false,bool p_flip_y=false);
+	void set_cell(int p_x,int p_y,int p_tile,bool p_flip_x=false,bool p_flip_y=false,bool p_transpose=false);
 	int get_cell(int p_x,int p_y) const;
 	int get_cell(int p_x,int p_y) const;
 	bool is_cell_x_flipped(int p_x,int p_y) const;
 	bool is_cell_x_flipped(int p_x,int p_y) const;
 	bool is_cell_y_flipped(int p_x,int p_y) const;
 	bool is_cell_y_flipped(int p_x,int p_y) const;
+	bool is_cell_transposed(int p_x,int p_y) const;
 
 
 	Rect2 get_item_rect() const;
 	Rect2 get_item_rect() const;
 
 

二进制
tools/editor/icons/icon_rotate_0.png


二进制
tools/editor/icons/icon_rotate_180.png


二进制
tools/editor/icons/icon_rotate_270.png


二进制
tools/editor/icons/icon_rotate_90.png


二进制
tools/editor/icons/icon_transpose.png


+ 57 - 15
tools/editor/plugins/tile_map_editor_plugin.cpp

@@ -44,6 +44,11 @@ void TileMapEditor::_notification(int p_what) {
 
 
 			mirror_x->set_icon( get_icon("MirrorX","EditorIcons"));
 			mirror_x->set_icon( get_icon("MirrorX","EditorIcons"));
 			mirror_y->set_icon( get_icon("MirrorY","EditorIcons"));
 			mirror_y->set_icon( get_icon("MirrorY","EditorIcons"));
+			transpose->set_icon( get_icon("Transpose","EditorIcons"));
+			rotate_0->set_icon( get_icon("Rotate0","EditorIcons"));
+			rotate_90->set_icon( get_icon("Rotate90","EditorIcons"));
+			rotate_180->set_icon( get_icon("Rotate180","EditorIcons"));
+			rotate_270->set_icon( get_icon("Rotate270","EditorIcons"));
 
 
 		} break;
 		} break;
 	}
 	}
@@ -85,24 +90,25 @@ void TileMapEditor::set_selected_tile(int p_tile) {
 	}
 	}
 }
 }
 
 
-void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bool p_flip_v,bool p_with_undo) {
+void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bool p_flip_v, bool p_transpose,bool p_with_undo) {
 
 
 	ERR_FAIL_COND(!node);
 	ERR_FAIL_COND(!node);
 
 
 	bool prev_flip_h=node->is_cell_x_flipped(p_pos.x,p_pos.y);
 	bool prev_flip_h=node->is_cell_x_flipped(p_pos.x,p_pos.y);
 	bool prev_flip_v=node->is_cell_y_flipped(p_pos.x,p_pos.y);
 	bool prev_flip_v=node->is_cell_y_flipped(p_pos.x,p_pos.y);
+	bool prev_transpose=node->is_cell_transposed(p_pos.x,p_pos.y);
 	int prev_val=node->get_cell(p_pos.x,p_pos.y);
 	int prev_val=node->get_cell(p_pos.x,p_pos.y);
 
 
-	if (p_value==prev_val && p_flip_h==prev_flip_h && p_flip_v==prev_flip_v)
+	if (p_value==prev_val && p_flip_h==prev_flip_h && p_flip_v==prev_transpose && p_flip_v==prev_transpose)
 		return; //check that it's actually different
 		return; //check that it's actually different
 
 
 
 
 	if (p_with_undo) {
 	if (p_with_undo) {
-		undo_redo->add_do_method(node,"set_cell",p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v);
-		undo_redo->add_undo_method(node,"set_cell",p_pos.x,p_pos.y,prev_val,prev_flip_h,prev_flip_v);
+		undo_redo->add_do_method(node,"set_cell",p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v,p_transpose);
+		undo_redo->add_undo_method(node,"set_cell",p_pos.x,p_pos.y,prev_val,prev_flip_h,prev_flip_v,prev_transpose);
 	} else {
 	} else {
 
 
-		node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v);
+		node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v,p_transpose);
 
 
 	}
 	}
 
 
@@ -168,6 +174,7 @@ struct _TileMapEditorCopyData {
 	int cell;
 	int cell;
 	bool flip_h;
 	bool flip_h;
 	bool flip_v;
 	bool flip_v;
+	bool transpose;
 };
 };
 
 
 bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
@@ -214,7 +221,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 					for (List<_TileMapEditorCopyData>::Element *E=dupdata.front();E;E=E->next()) {
 					for (List<_TileMapEditorCopyData>::Element *E=dupdata.front();E;E=E->next()) {
 
 
 
 
-						_set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,true);
+						_set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,E->get().transpose,true);
 					}
 					}
 					undo_redo->commit_action();
 					undo_redo->commit_action();
 
 
@@ -239,6 +246,9 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 					} else if (mb.mod.control) {
 					} else if (mb.mod.control) {
 						tool=TOOL_PICKING;
 						tool=TOOL_PICKING;
 						set_selected_tile(node->get_cell(over_tile.x, over_tile.y));
 						set_selected_tile(node->get_cell(over_tile.x, over_tile.y));
+						mirror_x->set_pressed(node->is_cell_x_flipped(over_tile.x, over_tile.y));
+						mirror_y->set_pressed(node->is_cell_y_flipped(over_tile.x, over_tile.y));
+						transpose->set_pressed(node->is_cell_transposed(over_tile.x, over_tile.y));
 						canvas_item_editor->update();
 						canvas_item_editor->update();
 						return true;
 						return true;
 					} else {
 					} else {
@@ -248,7 +258,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 							Point2i local =node->world_to_map((xform_inv.xform(Point2(mb.x,mb.y))));
 							Point2i local =node->world_to_map((xform_inv.xform(Point2(mb.x,mb.y))));
 							paint_undo.clear();
 							paint_undo.clear();
 							paint_undo[local]=_get_op_from_cell(local);
 							paint_undo[local]=_get_op_from_cell(local);
-							node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed());
+							node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed());
 							return true;
 							return true;
 						}
 						}
 					}
 					}
@@ -263,8 +273,8 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 								for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
 								for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
 
 
 									Point2i p=E->key();
 									Point2i p=E->key();
-									undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y));
-									undo_redo->add_undo_method(node,"set_cell",p.x,p.y,E->get().idx,E->get().xf,E->get().yf);
+									undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y));
+									undo_redo->add_undo_method(node,"set_cell",p.x,p.y,E->get().idx,E->get().xf,E->get().yf,E->get().tr);
 								}
 								}
 
 
 								undo_redo->commit_action();
 								undo_redo->commit_action();
@@ -289,7 +299,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 					Point2i local =node->world_to_map(xform_inv.xform(Point2(mb.x,mb.y)));
 					Point2i local =node->world_to_map(xform_inv.xform(Point2(mb.x,mb.y)));
 					paint_undo.clear();
 					paint_undo.clear();
 					paint_undo[local]=_get_op_from_cell(local);
 					paint_undo[local]=_get_op_from_cell(local);
-					//node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed());
+					//node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed());
 					//return true;
 					//return true;
 					_set_cell(local,TileMap::INVALID_CELL);
 					_set_cell(local,TileMap::INVALID_CELL);
 					return true;
 					return true;
@@ -302,9 +312,9 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 							for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
 							for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
 
 
 								Point2i p=E->key();
 								Point2i p=E->key();
-								//undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y));
-								_set_cell(p,TileMap::INVALID_CELL,false,false,true);
-								undo_redo->add_undo_method(node,"set_cell",p.x,p.y,E->get().idx,E->get().xf,E->get().yf);
+								//undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y));
+								_set_cell(p,TileMap::INVALID_CELL,false,false,false,true);
+								undo_redo->add_undo_method(node,"set_cell",p.x,p.y,E->get().idx,E->get().xf,E->get().yf,E->get().tr);
 							}
 							}
 
 
 							undo_redo->commit_action();
 							undo_redo->commit_action();
@@ -340,7 +350,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 
 
 						paint_undo[over_tile]=_get_op_from_cell(over_tile);
 						paint_undo[over_tile]=_get_op_from_cell(over_tile);
 					}
 					}
-					node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed());
+					node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed());
 
 
 					return true;
 					return true;
 				}
 				}
@@ -373,13 +383,16 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 				if (!paint_undo.has(over_tile)) {
 				if (!paint_undo.has(over_tile)) {
 					paint_undo[over_tile]=_get_op_from_cell(over_tile);
 					paint_undo[over_tile]=_get_op_from_cell(over_tile);
 				}
 				}
-				//node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed());
+				//node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed());
 				_set_cell(local,TileMap::INVALID_CELL);
 				_set_cell(local,TileMap::INVALID_CELL);
 				return true;
 				return true;
 			}
 			}
 
 
 			if (tool==TOOL_PICKING) {
 			if (tool==TOOL_PICKING) {
 				set_selected_tile(node->get_cell(over_tile.x, over_tile.y));
 				set_selected_tile(node->get_cell(over_tile.x, over_tile.y));
+				mirror_x->set_pressed(node->is_cell_x_flipped(over_tile.x, over_tile.y));
+				mirror_y->set_pressed(node->is_cell_y_flipped(over_tile.x, over_tile.y));
+				transpose->set_pressed(node->is_cell_transposed(over_tile.x, over_tile.y));
 				canvas_item_editor->update();
 				canvas_item_editor->update();
 				return true;
 				return true;
 			}
 			}
@@ -625,6 +638,9 @@ void TileMapEditor::_canvas_draw() {
 							sc.x*=-1.0;
 							sc.x*=-1.0;
 						if (mirror_y->is_pressed())
 						if (mirror_y->is_pressed())
 							sc.y*=-1.0;
 							sc.y*=-1.0;
+						if (transpose->is_pressed()) {
+							//TODO
+						}
 						if (r==Rect2()) {
 						if (r==Rect2()) {
 
 
 							canvas_item_editor->draw_texture_rect(t,Rect2(from,t->get_size()*sc),false,Color(1,1,1,0.5));
 							canvas_item_editor->draw_texture_rect(t,Rect2(from,t->get_size()*sc),false,Color(1,1,1,0.5));
@@ -744,6 +760,32 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
 	mirror_y->set_tooltip("Mirror Y (S)");
 	mirror_y->set_tooltip("Mirror Y (S)");
 	mirror_y->set_focus_mode(FOCUS_NONE);
 	mirror_y->set_focus_mode(FOCUS_NONE);
 	canvas_item_editor_hb->add_child(mirror_y);
 	canvas_item_editor_hb->add_child(mirror_y);
+	transpose = memnew( ToolButton );
+	transpose->set_toggle_mode(true);
+	transpose->set_tooltip("Transpose");
+	transpose->set_focus_mode(FOCUS_NONE);
+	canvas_item_editor_hb->add_child(transpose);
+	canvas_item_editor_hb->add_child(memnew(VSeparator));
+	rotate_0 = memnew( ToolButton );
+	rotate_0->set_toggle_mode(true);
+	rotate_0->set_tooltip("Rotate 0 degrees");
+	rotate_0->set_focus_mode(FOCUS_NONE);
+	canvas_item_editor_hb->add_child(rotate_0);
+	rotate_90 = memnew( ToolButton );
+	rotate_90->set_toggle_mode(true);
+	rotate_90->set_tooltip("Rotate 90 degrees");
+	rotate_90->set_focus_mode(FOCUS_NONE);
+	canvas_item_editor_hb->add_child(rotate_90);
+	rotate_180 = memnew( ToolButton );
+	rotate_180->set_toggle_mode(true);
+	rotate_180->set_tooltip("Rotate 180 degrees");
+	rotate_180->set_focus_mode(FOCUS_NONE);
+	canvas_item_editor_hb->add_child(rotate_180);
+	rotate_270 = memnew( ToolButton );
+	rotate_270->set_toggle_mode(true);
+	rotate_270->set_tooltip("Rotate 270 degrees");
+	rotate_270->set_focus_mode(FOCUS_NONE);
+	canvas_item_editor_hb->add_child(rotate_270);
 	canvas_item_editor_hb->hide();
 	canvas_item_editor_hb->hide();
 
 
 	tool=TOOL_NONE;
 	tool=TOOL_NONE;

+ 8 - 3
tools/editor/plugins/tile_map_editor_plugin.h

@@ -73,6 +73,11 @@ class TileMapEditor : public VBoxContainer {
 	Label *mirror_label;
 	Label *mirror_label;
 	ToolButton *mirror_x;
 	ToolButton *mirror_x;
 	ToolButton *mirror_y;
 	ToolButton *mirror_y;
+	ToolButton *transpose;
+	ToolButton *rotate_0;
+	ToolButton *rotate_90;
+	ToolButton *rotate_180;
+	ToolButton *rotate_270;
 
 
 	HBoxContainer *canvas_item_editor_hb;
 	HBoxContainer *canvas_item_editor_hb;
 
 
@@ -81,8 +86,8 @@ class TileMapEditor : public VBoxContainer {
 		int idx;
 		int idx;
 		bool xf;
 		bool xf;
 		bool yf;
 		bool yf;
-		CellOp() { idx=-1; xf=false; yf=false; }
-		CellOp(const CellOp& p_other) : idx(p_other.idx), xf(p_other.xf), yf(p_other.yf) {}
+		bool tr;
+		CellOp() { idx=-1; xf=false; yf=false; tr=false; }
 	};
 	};
 
 
 	Map<Point2i,CellOp> paint_undo;
 	Map<Point2i,CellOp> paint_undo;
@@ -94,7 +99,7 @@ class TileMapEditor : public VBoxContainer {
 	void _canvas_draw();
 	void _canvas_draw();
 	void _menu_option(int p_option);
 	void _menu_option(int p_option);
 
 
-	void _set_cell(const Point2i& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_with_undo=false);
+	void _set_cell(const Point2i& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_transpose=false, bool p_with_undo=false);
 
 
 	void _canvas_mouse_enter();
 	void _canvas_mouse_enter();
 	void _canvas_mouse_exit();
 	void _canvas_mouse_exit();