Browse Source

Removal of InputEvent as built-in Variant type..
this might cause bugs I haven't found yet..

Juan Linietsky 8 years ago
parent
commit
5b3709d309
100 changed files with 4561 additions and 4872 deletions
  1. 43 26
      core/global_config.cpp
  2. 3 3
      core/global_constants.cpp
  3. 52 86
      core/input_map.cpp
  4. 8 10
      core/input_map.h
  5. 0 137
      core/io/marshalls.cpp
  6. 0 14
      core/io/resource_format_binary.cpp
  7. 0 1
      core/method_bind.h
  8. 0 1
      core/method_ptrcall.h
  9. 2 2
      core/os/input.h
  10. 750 231
      core/os/input_event.cpp
  11. 245 70
      core/os/input_event.h
  12. 2 2
      core/os/main_loop.cpp
  13. 1 1
      core/os/main_loop.h
  14. 0 1
      core/packed_data_container.cpp
  15. 12 0
      core/register_core_types.cpp
  16. 0 41
      core/variant.cpp
  17. 1 5
      core/variant.h
  18. 0 26
      core/variant_call.cpp
  19. 0 714
      core/variant_op.cpp
  20. 30 151
      core/variant_parser.cpp
  21. 1 1
      doc/base/classes.xml
  22. 790 792
      editor/animation_editor.cpp
  23. 1 1
      editor/animation_editor.h
  24. 17 14
      editor/code_editor.cpp
  25. 2 2
      editor/code_editor.h
  26. 7 6
      editor/create_dialog.cpp
  27. 1 1
      editor/create_dialog.h
  28. 54 74
      editor/doc/doc_data.cpp
  29. 1 2
      editor/doc/doc_dump.cpp
  30. 7 4
      editor/editor_audio_buses.cpp
  31. 1 1
      editor/editor_audio_buses.h
  32. 5 3
      editor/editor_file_dialog.cpp
  33. 1 1
      editor/editor_file_dialog.h
  34. 26 16
      editor/editor_help.cpp
  35. 4 4
      editor/editor_help.h
  36. 6 4
      editor/editor_name_dialog.cpp
  37. 1 1
      editor/editor_name_dialog.h
  38. 13 8
      editor/editor_node.cpp
  39. 4 4
      editor/editor_node.h
  40. 3 2
      editor/editor_path.cpp
  41. 1 1
      editor/editor_path.h
  42. 4 4
      editor/editor_plugin.cpp
  43. 2 2
      editor/editor_plugin.h
  44. 9 5
      editor/editor_profiler.cpp
  45. 1 1
      editor/editor_profiler.h
  46. 13 12
      editor/editor_settings.cpp
  47. 1 1
      editor/editor_settings.h
  48. 4 3
      editor/pane_drag.cpp
  49. 1 1
      editor/pane_drag.h
  50. 7 6
      editor/plugins/animation_player_editor_plugin.cpp
  51. 2 2
      editor/plugins/animation_player_editor_plugin.h
  52. 106 106
      editor/plugins/animation_tree_editor_plugin.cpp
  53. 1 1
      editor/plugins/animation_tree_editor_plugin.h
  54. 63 62
      editor/plugins/canvas_item_editor_plugin.cpp
  55. 3 3
      editor/plugins/canvas_item_editor_plugin.h
  56. 141 146
      editor/plugins/collision_polygon_2d_editor_plugin.cpp
  57. 2 2
      editor/plugins/collision_polygon_2d_editor_plugin.h
  58. 8 8
      editor/plugins/collision_polygon_editor_plugin.cpp
  59. 40 42
      editor/plugins/collision_shape_2d_editor_plugin.cpp
  60. 2 2
      editor/plugins/collision_shape_2d_editor_plugin.h
  61. 12 7
      editor/plugins/curve_editor_plugin.cpp
  62. 1 1
      editor/plugins/curve_editor_plugin.h
  63. 19 14
      editor/plugins/gradient_texture_editor_plugin.cpp
  64. 1 1
      editor/plugins/gradient_texture_editor_plugin.h
  65. 150 152
      editor/plugins/light_occluder_2d_editor_plugin.cpp
  66. 2 2
      editor/plugins/light_occluder_2d_editor_plugin.h
  67. 61 62
      editor/plugins/line_2d_editor_plugin.cpp
  68. 2 2
      editor/plugins/line_2d_editor_plugin.h
  69. 3 3
      editor/plugins/mesh_editor_plugin.cpp
  70. 180 181
      editor/plugins/navigation_polygon_editor_plugin.cpp
  71. 2 2
      editor/plugins/navigation_polygon_editor_plugin.h
  72. 298 259
      editor/plugins/path_2d_editor_plugin.cpp
  73. 2 2
      editor/plugins/path_2d_editor_plugin.h
  74. 3 3
      editor/plugins/path_editor_plugin.cpp
  75. 163 166
      editor/plugins/polygon_2d_editor_plugin.cpp
  76. 3 3
      editor/plugins/polygon_2d_editor_plugin.h
  77. 1 1
      editor/plugins/resource_preloader_editor_plugin.cpp
  78. 1 1
      editor/plugins/resource_preloader_editor_plugin.h
  79. 10 8
      editor/plugins/script_editor_plugin.cpp
  80. 2 2
      editor/plugins/script_editor_plugin.h
  81. 9 7
      editor/plugins/script_text_editor.cpp
  82. 1 1
      editor/plugins/script_text_editor.h
  83. 9 9
      editor/plugins/shader_graph_editor_plugin.cpp
  84. 601 599
      editor/plugins/spatial_editor_plugin.cpp
  85. 5 5
      editor/plugins/spatial_editor_plugin.h
  86. 1 1
      editor/plugins/sprite_frames_editor_plugin.cpp
  87. 1 1
      editor/plugins/sprite_frames_editor_plugin.h
  88. 1 1
      editor/plugins/texture_editor_plugin.cpp
  89. 1 1
      editor/plugins/texture_editor_plugin.h
  90. 27 26
      editor/plugins/texture_region_editor_plugin.cpp
  91. 1 1
      editor/plugins/texture_region_editor_plugin.h
  92. 300 303
      editor/plugins/tile_map_editor_plugin.cpp
  93. 3 3
      editor/plugins/tile_map_editor_plugin.h
  94. 17 15
      editor/project_manager.cpp
  95. 2 2
      editor/project_manager.h
  96. 130 97
      editor/project_settings.cpp
  97. 11 4
      editor/project_settings.h
  98. 9 19
      editor/property_editor.cpp
  99. 1 1
      editor/property_editor.h
  100. 10 31
      editor/property_selector.cpp

+ 43 - 26
core/global_config.cpp

@@ -846,10 +846,8 @@ GlobalConfig::GlobalConfig() {
 	registering_order = true;
 
 	Array va;
-	InputEvent key;
-	key.type = InputEvent::KEY;
-	InputEvent joyb;
-	joyb.type = InputEvent::JOYPAD_BUTTON;
+	Ref<InputEventKey> key;
+	Ref<InputEventJoypadButton> joyb;
 
 	GLOBAL_DEF("application/name", "");
 	GLOBAL_DEF("application/main_scene", "");
@@ -858,87 +856,106 @@ GlobalConfig::GlobalConfig() {
 	GLOBAL_DEF("application/disable_stderr", false);
 	GLOBAL_DEF("application/use_shared_user_dir", true);
 
-	key.key.scancode = KEY_RETURN;
+	key.instance();
+	key->set_scancode(KEY_RETURN);
 	va.push_back(key);
-	key.key.scancode = KEY_ENTER;
+	key.instance();
+	key->set_scancode(KEY_ENTER);
 	va.push_back(key);
-	key.key.scancode = KEY_SPACE;
+	key.instance();
+	key->set_scancode(KEY_SPACE);
 	va.push_back(key);
-	joyb.joy_button.button_index = JOY_BUTTON_0;
+	joyb.instance();
+	joyb->set_button_index(JOY_BUTTON_0);
 	va.push_back(joyb);
 	GLOBAL_DEF("input/ui_accept", va);
 	input_presets.push_back("input/ui_accept");
 
 	va = Array();
-	key.key.scancode = KEY_SPACE;
+	key.instance();
+	key->set_scancode(KEY_SPACE);
 	va.push_back(key);
-	joyb.joy_button.button_index = JOY_BUTTON_3;
+	joyb.instance();
+	joyb->set_button_index(JOY_BUTTON_3);
 	va.push_back(joyb);
 	GLOBAL_DEF("input/ui_select", va);
 	input_presets.push_back("input/ui_select");
 
 	va = Array();
-	key.key.scancode = KEY_ESCAPE;
+	key.instance();
+	key->set_scancode(KEY_ESCAPE);
 	va.push_back(key);
-	joyb.joy_button.button_index = JOY_BUTTON_1;
+	joyb.instance();
+	joyb->set_button_index(JOY_BUTTON_1);
 	va.push_back(joyb);
 	GLOBAL_DEF("input/ui_cancel", va);
 	input_presets.push_back("input/ui_cancel");
 
 	va = Array();
-	key.key.scancode = KEY_TAB;
+	key.instance();
+	key->set_scancode(KEY_TAB);
 	va.push_back(key);
 	GLOBAL_DEF("input/ui_focus_next", va);
 	input_presets.push_back("input/ui_focus_next");
 
 	va = Array();
-	key.key.scancode = KEY_TAB;
-	key.key.mod.shift = true;
+	key.instance();
+	key->set_scancode(KEY_TAB);
+	key->set_shift(true);
 	va.push_back(key);
 	GLOBAL_DEF("input/ui_focus_prev", va);
 	input_presets.push_back("input/ui_focus_prev");
-	key.key.mod.shift = false;
 
 	va = Array();
-	key.key.scancode = KEY_LEFT;
+	key.instance();
+	key->set_scancode(KEY_LEFT);
 	va.push_back(key);
-	joyb.joy_button.button_index = JOY_DPAD_LEFT;
+	joyb.instance();
+	joyb->set_button_index(JOY_DPAD_LEFT);
 	va.push_back(joyb);
 	GLOBAL_DEF("input/ui_left", va);
 	input_presets.push_back("input/ui_left");
 
 	va = Array();
-	key.key.scancode = KEY_RIGHT;
+	key.instance();
+	key->set_scancode(KEY_RIGHT);
 	va.push_back(key);
-	joyb.joy_button.button_index = JOY_DPAD_RIGHT;
+	joyb.instance();
+	joyb->set_button_index(JOY_DPAD_RIGHT);
 	va.push_back(joyb);
 	GLOBAL_DEF("input/ui_right", va);
 	input_presets.push_back("input/ui_right");
 
 	va = Array();
-	key.key.scancode = KEY_UP;
+	key.instance();
+	key->set_scancode(KEY_UP);
 	va.push_back(key);
-	joyb.joy_button.button_index = JOY_DPAD_UP;
+	joyb.instance();
+	joyb->set_button_index(JOY_DPAD_UP);
 	va.push_back(joyb);
 	GLOBAL_DEF("input/ui_up", va);
 	input_presets.push_back("input/ui_up");
 
 	va = Array();
-	key.key.scancode = KEY_DOWN;
+	key.instance();
+	key->set_scancode(KEY_DOWN);
 	va.push_back(key);
-	joyb.joy_button.button_index = JOY_DPAD_DOWN;
+	joyb.instance();
+	joyb->set_button_index(JOY_DPAD_DOWN);
 	va.push_back(joyb);
 	GLOBAL_DEF("input/ui_down", va);
 	input_presets.push_back("input/ui_down");
 
 	va = Array();
-	key.key.scancode = KEY_PAGEUP;
+	key.instance();
+	key->set_scancode(KEY_PAGEUP);
 	va.push_back(key);
 	GLOBAL_DEF("input/ui_page_up", va);
 	input_presets.push_back("input/ui_page_up");
 
 	va = Array();
-	key.key.scancode = KEY_PAGEDOWN;
+	key.instance();
+	key->set_scancode(KEY_PAGEDOWN);
 	va.push_back(key);
 	GLOBAL_DEF("input/ui_page_down", va);
 	input_presets.push_back("input/ui_page_down");

+ 3 - 3
core/global_constants.cpp

@@ -30,6 +30,7 @@
 #include "global_constants.h"
 
 #include "object.h"
+#include "os/input_event.h"
 #include "os/keyboard.h"
 #include "variant.h"
 
@@ -513,9 +514,8 @@ static _GlobalConstant _global_constants[] = {
 	{ "TYPE_NODE_PATH", Variant::NODE_PATH }, // 15
 	{ "TYPE_RID", Variant::_RID },
 	{ "TYPE_OBJECT", Variant::OBJECT },
-	{ "TYPE_INPUT_EVENT", Variant::INPUT_EVENT },
-	{ "TYPE_DICTIONARY", Variant::DICTIONARY },
-	{ "TYPE_ARRAY", Variant::ARRAY }, // 20
+	{ "TYPE_DICTIONARY", Variant::DICTIONARY }, // 20
+	{ "TYPE_ARRAY", Variant::ARRAY },
 	{ "TYPE_RAW_ARRAY", Variant::POOL_BYTE_ARRAY },
 	{ "TYPE_INT_ARRAY", Variant::POOL_INT_ARRAY },
 	{ "TYPE_REAL_ARRAY", Variant::POOL_REAL_ARRAY },

+ 52 - 86
core/input_map.cpp

@@ -37,8 +37,6 @@ InputMap *InputMap::singleton = NULL;
 void InputMap::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action);
-	ClassDB::bind_method(D_METHOD("get_action_id", "action"), &InputMap::get_action_id);
-	ClassDB::bind_method(D_METHOD("get_action_from_id", "id"), &InputMap::get_action_from_id);
 	ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions);
 	ClassDB::bind_method(D_METHOD("add_action", "action"), &InputMap::add_action);
 	ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action);
@@ -57,23 +55,15 @@ void InputMap::add_action(const StringName &p_action) {
 	input_map[p_action] = Action();
 	static int last_id = 1;
 	input_map[p_action].id = last_id;
-	input_id_map[last_id] = p_action;
 	last_id++;
 }
 
 void InputMap::erase_action(const StringName &p_action) {
 
 	ERR_FAIL_COND(!input_map.has(p_action));
-	input_id_map.erase(input_map[p_action].id);
 	input_map.erase(p_action);
 }
 
-StringName InputMap::get_action_from_id(int p_id) const {
-
-	ERR_FAIL_COND_V(!input_id_map.has(p_id), StringName());
-	return input_id_map[p_id];
-}
-
 Array InputMap::_get_actions() {
 
 	Array ret;
@@ -103,49 +93,18 @@ List<StringName> InputMap::get_actions() const {
 	return actions;
 }
 
-List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list, const InputEvent &p_event, bool p_action_test) const {
-
-	for (List<InputEvent>::Element *E = p_list.front(); E; E = E->next()) {
-
-		const InputEvent &e = E->get();
-		if (e.type != p_event.type)
-			continue;
-		if (e.type != InputEvent::KEY && e.device != p_event.device)
-			continue;
-
-		bool same = false;
-
-		switch (p_event.type) {
-
-			case InputEvent::KEY: {
-
-				if (p_action_test) {
-					uint32_t code = e.key.get_scancode_with_modifiers();
-					uint32_t event_code = p_event.key.get_scancode_with_modifiers();
-					same = (e.key.scancode == p_event.key.scancode && (!p_event.key.pressed || ((code & event_code) == code)));
-				} else {
-					same = (e.key.scancode == p_event.key.scancode && e.key.mod == p_event.key.mod);
-				}
-
-			} break;
-			case InputEvent::JOYPAD_BUTTON: {
+List<Ref<InputEvent> >::Element *InputMap::_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test) const {
 
-				same = (e.joy_button.button_index == p_event.joy_button.button_index);
+	for (List<Ref<InputEvent> >::Element *E = p_list.front(); E; E = E->next()) {
 
-			} break;
-			case InputEvent::MOUSE_BUTTON: {
+		const Ref<InputEvent> e = E->get();
 
-				same = (e.mouse_button.button_index == p_event.mouse_button.button_index);
+		//if (e.type != Ref<InputEvent>::KEY && e.device != p_event.device) -- unsure about the KEY comparison, why is this here?
+		//	continue;
 
-			} break;
-			case InputEvent::JOYPAD_MOTION: {
-
-				same = (e.joy_motion.axis == p_event.joy_motion.axis && (e.joy_motion.axis_value < 0) == (p_event.joy_motion.axis_value < 0));
-
-			} break;
-		}
-
-		if (same)
+		if (e->get_device() != p_event->get_device())
+			continue;
+		if (e->action_match(p_event))
 			return E;
 	}
 
@@ -157,9 +116,9 @@ bool InputMap::has_action(const StringName &p_action) const {
 	return input_map.has(p_action);
 }
 
-void InputMap::action_add_event(const StringName &p_action, const InputEvent &p_event) {
+void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
 
-	ERR_FAIL_COND(p_event.type == InputEvent::ACTION);
+	ERR_FAIL_COND(p_event.is_null());
 	ERR_FAIL_COND(!input_map.has(p_action));
 	if (_find_event(input_map[p_action].inputs, p_event))
 		return; //already gots
@@ -167,23 +126,17 @@ void InputMap::action_add_event(const StringName &p_action, const InputEvent &p_
 	input_map[p_action].inputs.push_back(p_event);
 }
 
-int InputMap::get_action_id(const StringName &p_action) const {
-
-	ERR_FAIL_COND_V(!input_map.has(p_action), -1);
-	return input_map[p_action].id;
-}
-
-bool InputMap::action_has_event(const StringName &p_action, const InputEvent &p_event) {
+bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
 
 	ERR_FAIL_COND_V(!input_map.has(p_action), false);
 	return (_find_event(input_map[p_action].inputs, p_event) != NULL);
 }
 
-void InputMap::action_erase_event(const StringName &p_action, const InputEvent &p_event) {
+void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
 
 	ERR_FAIL_COND(!input_map.has(p_action));
 
-	List<InputEvent>::Element *E = _find_event(input_map[p_action].inputs, p_event);
+	List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action].inputs, p_event);
 	if (E)
 		input_map[p_action].inputs.erase(E);
 }
@@ -191,9 +144,9 @@ void InputMap::action_erase_event(const StringName &p_action, const InputEvent &
 Array InputMap::_get_action_list(const StringName &p_action) {
 
 	Array ret;
-	const List<InputEvent> *al = get_action_list(p_action);
+	const List<Ref<InputEvent> > *al = get_action_list(p_action);
 	if (al) {
-		for (const List<InputEvent>::Element *E = al->front(); E; E = E->next()) {
+		for (const List<Ref<InputEvent> >::Element *E = al->front(); E; E = E->next()) {
 
 			ret.push_back(E->get());
 		}
@@ -202,7 +155,7 @@ Array InputMap::_get_action_list(const StringName &p_action) {
 	return ret;
 }
 
-const List<InputEvent> *InputMap::get_action_list(const StringName &p_action) {
+const List<Ref<InputEvent> > *InputMap::get_action_list(const StringName &p_action) {
 
 	const Map<StringName, Action>::Element *E = input_map.find(p_action);
 	if (!E)
@@ -211,7 +164,7 @@ const List<InputEvent> *InputMap::get_action_list(const StringName &p_action) {
 	return &E->get().inputs;
 }
 
-bool InputMap::event_is_action(const InputEvent &p_event, const StringName &p_action) const {
+bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const {
 
 	Map<StringName, Action>::Element *E = input_map.find(p_action);
 	if (!E) {
@@ -219,9 +172,9 @@ bool InputMap::event_is_action(const InputEvent &p_event, const StringName &p_ac
 		ERR_FAIL_COND_V(!E, false);
 	}
 
-	if (p_event.type == InputEvent::ACTION) {
-
-		return p_event.action.action == E->get().id;
+	Ref<InputEventAction> iea = p_event;
+	if (iea.is_valid()) {
+		return iea->get_action() == p_action;
 	}
 
 	return _find_event(E->get().inputs, p_event, true) != NULL;
@@ -252,8 +205,8 @@ void InputMap::load_from_globals() {
 
 		for (int i = 0; i < va.size(); i++) {
 
-			InputEvent ie = va[i];
-			if (ie.type == InputEvent::NONE)
+			Ref<InputEvent> ie = va[i];
+			if (ie.is_null())
 				continue;
 			action_add_event(name, ie);
 		}
@@ -262,57 +215,70 @@ void InputMap::load_from_globals() {
 
 void InputMap::load_default() {
 
-	InputEvent key;
-	key.type = InputEvent::KEY;
+	Ref<InputEventKey> key;
 
 	add_action("ui_accept");
-	key.key.scancode = KEY_RETURN;
+	key.instance();
+	key->set_scancode(KEY_RETURN);
 	action_add_event("ui_accept", key);
-	key.key.scancode = KEY_ENTER;
+
+	key.instance();
+	key->set_scancode(KEY_ENTER);
 	action_add_event("ui_accept", key);
-	key.key.scancode = KEY_SPACE;
+
+	key.instance();
+	key->set_scancode(KEY_SPACE);
 	action_add_event("ui_accept", key);
 
 	add_action("ui_select");
-	key.key.scancode = KEY_SPACE;
+	key.instance();
+	key->set_scancode(KEY_SPACE);
 	action_add_event("ui_select", key);
 
 	add_action("ui_cancel");
-	key.key.scancode = KEY_ESCAPE;
+	key.instance();
+	key->set_scancode(KEY_ESCAPE);
 	action_add_event("ui_cancel", key);
 
 	add_action("ui_focus_next");
-	key.key.scancode = KEY_TAB;
+	key.instance();
+	key->set_scancode(KEY_TAB);
 	action_add_event("ui_focus_next", key);
 
 	add_action("ui_focus_prev");
-	key.key.scancode = KEY_TAB;
-	key.key.mod.shift = true;
+	key.instance();
+	key->set_scancode(KEY_TAB);
+	key->set_shift(true);
 	action_add_event("ui_focus_prev", key);
-	key.key.mod.shift = false;
 
 	add_action("ui_left");
-	key.key.scancode = KEY_LEFT;
+	key.instance();
+	key->set_scancode(KEY_LEFT);
 	action_add_event("ui_left", key);
 
 	add_action("ui_right");
-	key.key.scancode = KEY_RIGHT;
+	key.instance();
+	key->set_scancode(KEY_RIGHT);
 	action_add_event("ui_right", key);
 
 	add_action("ui_up");
-	key.key.scancode = KEY_UP;
+	key.instance();
+	key->set_scancode(KEY_UP);
 	action_add_event("ui_up", key);
 
 	add_action("ui_down");
-	key.key.scancode = KEY_DOWN;
+	key.instance();
+	key->set_scancode(KEY_DOWN);
 	action_add_event("ui_down", key);
 
 	add_action("ui_page_up");
-	key.key.scancode = KEY_PAGEUP;
+	key.instance();
+	key->set_scancode(KEY_PAGEUP);
 	action_add_event("ui_page_up", key);
 
 	add_action("ui_page_down");
-	key.key.scancode = KEY_PAGEDOWN;
+	key.instance();
+	key->set_scancode(KEY_PAGEDOWN);
 	action_add_event("ui_page_down", key);
 
 	//set("display/handheld/orientation", "landscape");

+ 8 - 10
core/input_map.h

@@ -31,6 +31,7 @@
 #define INPUT_MAP_H
 
 #include "object.h"
+#include "os/input_event.h"
 
 class InputMap : public Object {
 
@@ -39,16 +40,15 @@ class InputMap : public Object {
 public:
 	struct Action {
 		int id;
-		List<InputEvent> inputs;
+		List<Ref<InputEvent> > inputs;
 	};
 
 private:
 	static InputMap *singleton;
 
 	mutable Map<StringName, Action> input_map;
-	mutable Map<int, StringName> input_id_map;
 
-	List<InputEvent>::Element *_find_event(List<InputEvent> &p_list, const InputEvent &p_event, bool p_action_test = false) const;
+	List<Ref<InputEvent> >::Element *_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test = false) const;
 
 	Array _get_action_list(const StringName &p_action);
 	Array _get_actions();
@@ -60,18 +60,16 @@ public:
 	static _FORCE_INLINE_ InputMap *get_singleton() { return singleton; }
 
 	bool has_action(const StringName &p_action) const;
-	int get_action_id(const StringName &p_action) const;
-	StringName get_action_from_id(int p_id) const;
 	List<StringName> get_actions() const;
 	void add_action(const StringName &p_action);
 	void erase_action(const StringName &p_action);
 
-	void action_add_event(const StringName &p_action, const InputEvent &p_event);
-	bool action_has_event(const StringName &p_action, const InputEvent &p_event);
-	void action_erase_event(const StringName &p_action, const InputEvent &p_event);
+	void action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event);
+	bool action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event);
+	void action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event);
 
-	const List<InputEvent> *get_action_list(const StringName &p_action);
-	bool event_is_action(const InputEvent &p_event, const StringName &p_action) const;
+	const List<Ref<InputEvent> > *get_action_list(const StringName &p_action);
+	bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const;
 
 	const Map<StringName, Action> &get_action_map() const;
 	void load_from_globals();

+ 0 - 137
core/io/marshalls.cpp

@@ -365,66 +365,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
 
 			r_variant = (Object *)NULL;
 		} break;
-		case Variant::INPUT_EVENT: {
-
-			InputEvent ie;
-
-			ie.type = decode_uint32(&buf[0]);
-			ie.device = decode_uint32(&buf[4]);
-
-			if (r_len)
-				(*r_len) += 12;
-
-			switch (ie.type) {
-
-				case InputEvent::KEY: {
-
-					uint32_t mods = decode_uint32(&buf[12]);
-					if (mods & KEY_MASK_SHIFT)
-						ie.key.mod.shift = true;
-					if (mods & KEY_MASK_CTRL)
-						ie.key.mod.control = true;
-					if (mods & KEY_MASK_ALT)
-						ie.key.mod.alt = true;
-					if (mods & KEY_MASK_META)
-						ie.key.mod.meta = true;
-					ie.key.scancode = decode_uint32(&buf[16]);
-
-					if (r_len)
-						(*r_len) += 8;
-
-				} break;
-				case InputEvent::MOUSE_BUTTON: {
-
-					ie.mouse_button.button_index = decode_uint32(&buf[12]);
-					if (r_len)
-						(*r_len) += 4;
-
-				} break;
-				case InputEvent::JOYPAD_BUTTON: {
-
-					ie.joy_button.button_index = decode_uint32(&buf[12]);
-					if (r_len)
-						(*r_len) += 4;
-				} break;
-				case InputEvent::SCREEN_TOUCH: {
-
-					ie.screen_touch.index = decode_uint32(&buf[12]);
-					if (r_len)
-						(*r_len) += 4;
-				} break;
-				case InputEvent::JOYPAD_MOTION: {
-
-					ie.joy_motion.axis = decode_uint32(&buf[12]);
-					ie.joy_motion.axis_value = decode_float(&buf[16]);
-					if (r_len)
-						(*r_len) += 8;
-				} break;
-			}
-
-			r_variant = ie;
-
-		} break;
 		case Variant::DICTIONARY: {
 
 			ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
@@ -1054,83 +994,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {
 		case Variant::_RID:
 		case Variant::OBJECT: {
 
-		} break;
-		case Variant::INPUT_EVENT: {
-
-			InputEvent ie = p_variant;
-
-			if (buf) {
-
-				encode_uint32(ie.type, &buf[0]);
-				encode_uint32(ie.device, &buf[4]);
-				encode_uint32(0, &buf[8]);
-			}
-
-			int llen = 12;
-
-			switch (ie.type) {
-
-				case InputEvent::KEY: {
-
-					if (buf) {
-
-						uint32_t mods = 0;
-						if (ie.key.mod.shift)
-							mods |= KEY_MASK_SHIFT;
-						if (ie.key.mod.control)
-							mods |= KEY_MASK_CTRL;
-						if (ie.key.mod.alt)
-							mods |= KEY_MASK_ALT;
-						if (ie.key.mod.meta)
-							mods |= KEY_MASK_META;
-
-						encode_uint32(mods, &buf[llen]);
-						encode_uint32(ie.key.scancode, &buf[llen + 4]);
-					}
-					llen += 8;
-
-				} break;
-				case InputEvent::MOUSE_BUTTON: {
-
-					if (buf) {
-
-						encode_uint32(ie.mouse_button.button_index, &buf[llen]);
-					}
-					llen += 4;
-				} break;
-				case InputEvent::JOYPAD_BUTTON: {
-
-					if (buf) {
-
-						encode_uint32(ie.joy_button.button_index, &buf[llen]);
-					}
-					llen += 4;
-				} break;
-				case InputEvent::SCREEN_TOUCH: {
-
-					if (buf) {
-
-						encode_uint32(ie.screen_touch.index, &buf[llen]);
-					}
-					llen += 4;
-				} break;
-				case InputEvent::JOYPAD_MOTION: {
-
-					if (buf) {
-
-						int axis = ie.joy_motion.axis;
-						encode_uint32(axis, &buf[llen]);
-						encode_float(ie.joy_motion.axis_value, &buf[llen + 4]);
-					}
-					llen += 8;
-				} break;
-			}
-
-			if (buf)
-				encode_uint32(llen, &buf[8]);
-			r_len += llen;
-
-			// not supported
 		} break;
 		case Variant::DICTIONARY: {
 

+ 0 - 14
core/io/resource_format_binary.cpp

@@ -358,13 +358,6 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
 				} break;
 			}
 
-		} break;
-		case VARIANT_INPUT_EVENT: {
-
-			InputEvent ev;
-			ev.type = f->get_32(); //will only work for null though.
-			r_v = ev;
-
 		} break;
 		case VARIANT_DICTIONARY: {
 
@@ -1445,13 +1438,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
 				//internal resource
 			}
 
-		} break;
-		case Variant::INPUT_EVENT: {
-
-			f->store_32(VARIANT_INPUT_EVENT);
-			InputEvent event = p_property;
-			f->store_32(0); //event type none, nothing else suported for now.
-
 		} break;
 		case Variant::DICTIONARY: {
 

+ 0 - 1
core/method_bind.h

@@ -154,7 +154,6 @@ VARIANT_ENUM_CAST(Orientation);
 VARIANT_ENUM_CAST(HAlign);
 VARIANT_ENUM_CAST(Variant::Type);
 VARIANT_ENUM_CAST(Variant::Operator);
-VARIANT_ENUM_CAST(InputEvent::Type);
 
 class MethodBind {
 

+ 0 - 1
core/method_ptrcall.h

@@ -105,7 +105,6 @@ MAKE_PTRARG(Transform);
 MAKE_PTRARG(Color);
 MAKE_PTRARG(NodePath);
 MAKE_PTRARG(RID);
-MAKE_PTRARG(InputEvent);
 MAKE_PTRARG(Dictionary);
 MAKE_PTRARG(Array);
 MAKE_PTRARG(PoolByteArray);

+ 2 - 2
core/os/input.h

@@ -82,7 +82,7 @@ public:
 	virtual int get_mouse_button_mask() const = 0;
 
 	virtual void warp_mouse_pos(const Vector2 &p_to) = 0;
-	virtual Point2i warp_mouse_motion(const InputEventMouseMotion &p_motion, const Rect2 &p_rect) = 0;
+	virtual Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) = 0;
 
 	virtual Vector3 get_gravity() const = 0;
 	virtual Vector3 get_accelerometer() const = 0;
@@ -104,7 +104,7 @@ public:
 	virtual int get_joy_button_index_from_string(String p_button) = 0;
 	virtual int get_joy_axis_index_from_string(String p_axis) = 0;
 
-	virtual void parse_input_event(const InputEvent &p_event) = 0;
+	virtual void parse_input_event(const Ref<InputEvent> &p_event) = 0;
 
 	Input();
 };

+ 750 - 231
core/os/input_event.cpp

@@ -34,275 +34,794 @@
  *
  */
 
-bool InputEvent::operator==(const InputEvent &p_event) const {
-	if (type != p_event.type) {
-		return false;
-	}
+void InputEvent::set_id(uint32_t p_id) {
+	id = p_id;
+}
 
-	switch (type) {
-		/** Current clang-format style doesn't play well with the aligned return values of that switch. */
-		/* clang-format off */
-		case NONE:
-			return true;
-		case KEY:
-			return key.unicode == p_event.key.unicode
-				&& key.scancode == p_event.key.scancode
-				&& key.echo == p_event.key.echo
-				&& key.pressed == p_event.key.pressed
-				&& key.mod == p_event.key.mod;
-		case MOUSE_MOTION:
-			return mouse_motion.x == p_event.mouse_motion.x
-				&& mouse_motion.y == p_event.mouse_motion.y
-				&& mouse_motion.relative_x == p_event.mouse_motion.relative_x
-				&& mouse_motion.relative_y == p_event.mouse_motion.relative_y
-				&& mouse_motion.button_mask == p_event.mouse_motion.button_mask
-				&& key.mod == p_event.key.mod;
-		case MOUSE_BUTTON:
-			return mouse_button.pressed == p_event.mouse_button.pressed
-				&& mouse_button.x == p_event.mouse_button.x
-				&& mouse_button.y == p_event.mouse_button.y
-				&& mouse_button.button_index == p_event.mouse_button.button_index
-				&& mouse_button.button_mask == p_event.mouse_button.button_mask
-				&& key.mod == p_event.key.mod;
-		case JOYPAD_MOTION:
-			return joy_motion.axis == p_event.joy_motion.axis
-				&& joy_motion.axis_value == p_event.joy_motion.axis_value;
-		case JOYPAD_BUTTON:
-			return joy_button.pressed == p_event.joy_button.pressed
-				&& joy_button.button_index == p_event.joy_button.button_index
-				&& joy_button.pressure == p_event.joy_button.pressure;
-		case SCREEN_TOUCH:
-			return screen_touch.pressed == p_event.screen_touch.pressed
-				&& screen_touch.index == p_event.screen_touch.index
-				&& screen_touch.x == p_event.screen_touch.x
-				&& screen_touch.y == p_event.screen_touch.y;
-		case SCREEN_DRAG:
-			return screen_drag.index == p_event.screen_drag.index
-				&& screen_drag.x == p_event.screen_drag.x
-				&& screen_drag.y == p_event.screen_drag.y;
-		case ACTION:
-			return action.action == p_event.action.action
-				&& action.pressed == p_event.action.pressed;
-		/* clang-format on */
-		default:
-			ERR_PRINT("No logic to compare InputEvents of this type, this shouldn't happen.");
-	}
+uint32_t InputEvent::get_id() const {
+	return id;
+}
 
-	return false;
+void InputEvent::set_device(int p_device) {
+	device = p_device;
 }
-InputEvent::operator String() const {
-
-	String str = "Device " + itos(device) + " ID " + itos(ID) + " ";
-
-	switch (type) {
-
-		case NONE: {
-
-			return "Event: None";
-		} break;
-		case KEY: {
-
-			str += "Event: Key ";
-			str = str + "Unicode: " + String::chr(key.unicode) + " Scan: " + itos(key.scancode) + " Echo: " + String(key.echo ? "True" : "False") + " Pressed" + String(key.pressed ? "True" : "False") + " Mod: ";
-			if (key.mod.shift)
-				str += "S";
-			if (key.mod.control)
-				str += "C";
-			if (key.mod.alt)
-				str += "A";
-			if (key.mod.meta)
-				str += "M";
-
-			return str;
-		} break;
-		case MOUSE_MOTION: {
-
-			str += "Event: Motion ";
-			str = str + " Pos: " + itos(mouse_motion.x) + "," + itos(mouse_motion.y) + " Rel: " + itos(mouse_motion.relative_x) + "," + itos(mouse_motion.relative_y) + " Mask: ";
-			for (int i = 0; i < 8; i++) {
-
-				if ((1 << i) & mouse_motion.button_mask)
-					str += itos(i + 1);
-			}
-			str += " Mod: ";
-			if (key.mod.shift)
-				str += "S";
-			if (key.mod.control)
-				str += "C";
-			if (key.mod.alt)
-				str += "A";
-			if (key.mod.meta)
-				str += "M";
-
-			return str;
-		} break;
-		case MOUSE_BUTTON: {
-			str += "Event: Button ";
-			str = str + "Pressed: " + itos(mouse_button.pressed) + " Pos: " + itos(mouse_button.x) + "," + itos(mouse_button.y) + " Button: " + itos(mouse_button.button_index) + " Mask: ";
-			for (int i = 0; i < 8; i++) {
-
-				if ((1 << i) & mouse_button.button_mask)
-					str += itos(i + 1);
-			}
-			str += " Mod: ";
-			if (key.mod.shift)
-				str += "S";
-			if (key.mod.control)
-				str += "C";
-			if (key.mod.alt)
-				str += "A";
-			if (key.mod.meta)
-				str += "M";
-
-			str += String(" DoubleClick: ") + (mouse_button.doubleclick ? "Yes" : "No");
-
-			return str;
-
-		} break;
-		case JOYPAD_MOTION: {
-			str += "Event: JoypadMotion ";
-			str = str + "Axis: " + itos(joy_motion.axis) + " Value: " + rtos(joy_motion.axis_value);
-			return str;
-
-		} break;
-		case JOYPAD_BUTTON: {
-			str += "Event: JoypadButton ";
-			str = str + "Pressed: " + itos(joy_button.pressed) + " Index: " + itos(joy_button.button_index) + " pressure " + rtos(joy_button.pressure);
-			return str;
-
-		} break;
-		case SCREEN_TOUCH: {
-			str += "Event: ScreenTouch ";
-			str = str + "Pressed: " + itos(screen_touch.pressed) + " Index: " + itos(screen_touch.index) + " pos " + rtos(screen_touch.x) + "," + rtos(screen_touch.y);
-			return str;
-
-		} break;
-		case SCREEN_DRAG: {
-			str += "Event: ScreenDrag ";
-			str = str + " Index: " + itos(screen_drag.index) + " pos " + rtos(screen_drag.x) + "," + rtos(screen_drag.y);
-			return str;
-
-		} break;
-		case ACTION: {
-			str += "Event: Action: " + InputMap::get_singleton()->get_action_from_id(action.action) + " Pressed: " + itos(action.pressed);
-			return str;
-
-		} break;
-	}
 
-	return "";
+int InputEvent::get_device() const {
+	return device;
 }
 
-void InputEvent::set_as_action(const String &p_action, bool p_pressed) {
+bool InputEvent::is_pressed() const {
 
-	type = ACTION;
-	action.action = InputMap::get_singleton()->get_action_id(p_action);
-	action.pressed = p_pressed;
+	return false;
 }
 
-bool InputEvent::is_pressed() const {
+bool InputEvent::is_action(const StringName &p_action) const {
 
-	switch (type) {
+	return InputMap::get_singleton()->event_is_action(Ref<InputEvent>(this), p_action);
+}
 
-		case KEY: return key.pressed;
-		case MOUSE_BUTTON: return mouse_button.pressed;
-		case JOYPAD_BUTTON: return joy_button.pressed;
-		case SCREEN_TOUCH: return screen_touch.pressed;
-		case JOYPAD_MOTION: return ABS(joy_motion.axis_value) > 0.5;
-		case ACTION: return action.pressed;
-		default: {}
-	}
+bool InputEvent::is_action_pressed(const StringName &p_action) const {
+
+	return false; // InputMap::get_singleton()->event_is_action(Ref<InputEvent>(this),p_action);
+}
+bool InputEvent::is_action_released(const StringName &p_action) const {
 
 	return false;
 }
 
 bool InputEvent::is_echo() const {
 
-	return (type == KEY && key.echo);
+	return false;
+}
+
+Ref<InputEvent> InputEvent::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+	return Ref<InputEvent>((InputEvent *)this);
+}
+
+String InputEvent::as_text() const {
+
+	return String();
+}
+
+bool InputEvent::action_match(const Ref<InputEvent> &p_event) const {
+
+	return false;
+}
+
+bool InputEvent::is_action_type() const {
+
+	return false;
+}
+
+#if 0
+if (String(p_method) == "is_action" && p_argidx == 0) {
+
+	List<PropertyInfo> pinfo;
+	GlobalConfig::get_singleton()->get_property_list(&pinfo);
+
+	for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
+		const PropertyInfo &pi = E->get();
+
+		if (!pi.name.begins_with("input/"))
+			continue;
+
+		String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
+		result.insert("\"" + name + "\"");
+	}
+
+} else
+#endif
+
+void InputEvent::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_id", "id"), &InputEvent::set_id);
+	ClassDB::bind_method(D_METHOD("get_id"), &InputEvent::get_id);
+
+	ClassDB::bind_method(D_METHOD("set_device", "device"), &InputEvent::set_device);
+	ClassDB::bind_method(D_METHOD("get_device"), &InputEvent::get_device);
+
+	ClassDB::bind_method(D_METHOD("is_pressed"), &InputEvent::is_pressed);
+	ClassDB::bind_method(D_METHOD("is_action", "action"), &InputEvent::is_action);
+	ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &InputEvent::is_action_pressed);
+	ClassDB::bind_method(D_METHOD("is_action_released", "action"), &InputEvent::is_action_released);
+	ClassDB::bind_method(D_METHOD("is_echo"), &InputEvent::is_echo);
+
+	ClassDB::bind_method(D_METHOD("as_text"), &InputEvent::as_text);
+
+	ClassDB::bind_method(D_METHOD("action_match", "event:InputEvent"), &InputEvent::action_match);
+
+	ClassDB::bind_method(D_METHOD("is_action_type"), &InputEvent::is_action_type);
+
+	ClassDB::bind_method(D_METHOD("xformed_by:InputEvent", "xform", "local_ofs"), &InputEvent::xformed_by, DEFVAL(Vector2()));
+}
+
+InputEvent::InputEvent() {
+
+	id = 0;
+	device = 0;
+}
+
+//////////////////
+
+void InputEventWithModifiers::set_shift(bool p_enabled) {
+
+	shift = p_enabled;
+}
+
+bool InputEventWithModifiers::get_shift() const {
+
+	return shift;
+}
+
+void InputEventWithModifiers::set_alt(bool p_enabled) {
+
+	alt = p_enabled;
+}
+bool InputEventWithModifiers::get_alt() const {
+
+	return alt;
+}
+
+void InputEventWithModifiers::set_control(bool p_enabled) {
+
+	control = p_enabled;
+}
+bool InputEventWithModifiers::get_control() const {
+
+	return control;
+}
+
+void InputEventWithModifiers::set_metakey(bool p_enabled) {
+
+	meta = p_enabled;
+}
+bool InputEventWithModifiers::get_metakey() const {
+
+	return meta;
+}
+
+void InputEventWithModifiers::set_command(bool p_enabled) {
+
+	command = p_enabled;
+}
+bool InputEventWithModifiers::get_command() const {
+
+	return command;
+}
+
+void InputEventWithModifiers::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_alt", "enable"), &InputEventWithModifiers::set_alt);
+	ClassDB::bind_method(D_METHOD("get_alt"), &InputEventWithModifiers::get_alt);
+
+	ClassDB::bind_method(D_METHOD("set_shift", "enable"), &InputEventWithModifiers::set_shift);
+	ClassDB::bind_method(D_METHOD("get_shift"), &InputEventWithModifiers::get_shift);
+
+	ClassDB::bind_method(D_METHOD("set_control", "enable"), &InputEventWithModifiers::set_control);
+	ClassDB::bind_method(D_METHOD("get_control"), &InputEventWithModifiers::get_control);
+
+	ClassDB::bind_method(D_METHOD("set_metakey", "enable"), &InputEventWithModifiers::set_metakey);
+	ClassDB::bind_method(D_METHOD("get_metakey"), &InputEventWithModifiers::get_metakey);
+
+	ClassDB::bind_method(D_METHOD("set_command", "enable"), &InputEventWithModifiers::set_command);
+	ClassDB::bind_method(D_METHOD("get_command"), &InputEventWithModifiers::get_command);
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alt"), "set_alt", "get_alt");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shift"), "set_shift", "get_shift");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "control"), "set_control", "get_control");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta"), "set_metakey", "get_metakey");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "command"), "set_command", "get_command");
+}
+
+InputEventWithModifiers::InputEventWithModifiers() {
+
+	alt = false;
+	shift = false;
+	control = false;
+	meta = false;
+}
+
+//////////////////////////////////
+
+void InputEventKey::set_pressed(bool p_pressed) {
+
+	pressed = p_pressed;
+}
+
+bool InputEventKey::is_pressed() {
+
+	return pressed;
 }
 
-bool InputEvent::is_action(const String &p_action) const {
+void InputEventKey::set_scancode(uint32_t p_scancode) {
+
+	scancode = p_scancode;
+}
+uint32_t InputEventKey::get_scancode() const {
 
-	return InputMap::get_singleton()->event_is_action(*this, p_action);
+	return scancode;
 }
 
-bool InputEvent::is_action_pressed(const String &p_action) const {
+void InputEventKey::set_unicode(uint32_t p_unicode) {
 
-	return is_action(p_action) && is_pressed() && !is_echo();
+	unicode = p_unicode;
 }
+uint32_t InputEventKey::get_unicode() const {
 
-bool InputEvent::is_action_released(const String &p_action) const {
+	return unicode;
+}
+
+void InputEventKey::set_echo(bool p_enable) {
+
+	echo = p_enable;
+}
+bool InputEventKey::is_echo() const {
 
-	return is_action(p_action) && !is_pressed();
+	return echo;
 }
 
 uint32_t InputEventKey::get_scancode_with_modifiers() const {
 
 	uint32_t sc = scancode;
-	if (mod.control)
+	if (get_control())
 		sc |= KEY_MASK_CTRL;
-	if (mod.alt)
+	if (get_alt())
 		sc |= KEY_MASK_ALT;
-	if (mod.shift)
+	if (get_shift())
 		sc |= KEY_MASK_SHIFT;
-	if (mod.meta)
+	if (get_metakey())
 		sc |= KEY_MASK_META;
 
 	return sc;
 }
 
-InputEvent InputEvent::xform_by(const Transform2D &p_xform) const {
-
-	InputEvent ev = *this;
-
-	switch (ev.type) {
-
-		case InputEvent::MOUSE_BUTTON: {
-
-			Vector2 g = p_xform.xform(Vector2(ev.mouse_button.global_x, ev.mouse_button.global_y));
-			Vector2 l = p_xform.xform(Vector2(ev.mouse_button.x, ev.mouse_button.y));
-			ev.mouse_button.x = l.x;
-			ev.mouse_button.y = l.y;
-			ev.mouse_button.global_x = g.x;
-			ev.mouse_button.global_y = g.y;
-
-		} break;
-		case InputEvent::MOUSE_MOTION: {
-
-			Vector2 g = p_xform.xform(Vector2(ev.mouse_motion.global_x, ev.mouse_motion.global_y));
-			Vector2 l = p_xform.xform(Vector2(ev.mouse_motion.x, ev.mouse_motion.y));
-			Vector2 r = p_xform.basis_xform(Vector2(ev.mouse_motion.relative_x, ev.mouse_motion.relative_y));
-			Vector2 s = p_xform.basis_xform(Vector2(ev.mouse_motion.speed_x, ev.mouse_motion.speed_y));
-			ev.mouse_motion.x = l.x;
-			ev.mouse_motion.y = l.y;
-			ev.mouse_motion.global_x = g.x;
-			ev.mouse_motion.global_y = g.y;
-			ev.mouse_motion.relative_x = r.x;
-			ev.mouse_motion.relative_y = r.y;
-			ev.mouse_motion.speed_x = s.x;
-			ev.mouse_motion.speed_y = s.y;
-
-		} break;
-		case InputEvent::SCREEN_TOUCH: {
-
-			Vector2 t = p_xform.xform(Vector2(ev.screen_touch.x, ev.screen_touch.y));
-			ev.screen_touch.x = t.x;
-			ev.screen_touch.y = t.y;
-
-		} break;
-		case InputEvent::SCREEN_DRAG: {
-
-			Vector2 t = p_xform.xform(Vector2(ev.screen_drag.x, ev.screen_drag.y));
-			Vector2 r = p_xform.basis_xform(Vector2(ev.screen_drag.relative_x, ev.screen_drag.relative_y));
-			Vector2 s = p_xform.basis_xform(Vector2(ev.screen_drag.speed_x, ev.screen_drag.speed_y));
-			ev.screen_drag.x = t.x;
-			ev.screen_drag.y = t.y;
-			ev.screen_drag.relative_x = r.x;
-			ev.screen_drag.relative_y = r.y;
-			ev.screen_drag.speed_x = s.x;
-			ev.screen_drag.speed_y = s.y;
-		} break;
-	}
+bool InputEventKey::action_match(const Ref<InputEvent> &p_event) const {
+
+	Ref<InputEventKey> key = p_event;
+	if (key.is_null())
+		return false;
+
+	return get_scancode_with_modifiers() == key->get_scancode_with_modifiers();
+}
+
+void InputEventKey::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventKey::set_pressed);
+
+	ClassDB::bind_method(D_METHOD("set_scancode", "scancode"), &InputEventKey::set_scancode);
+	ClassDB::bind_method(D_METHOD("get_scancode"), &InputEventKey::get_scancode);
+
+	ClassDB::bind_method(D_METHOD("set_unicode", "unicode"), &InputEventKey::set_unicode);
+	ClassDB::bind_method(D_METHOD("get_unicode"), &InputEventKey::get_unicode);
+
+	ClassDB::bind_method(D_METHOD("set_echo", "echo"), &InputEventKey::set_echo);
+
+	ClassDB::bind_method(D_METHOD("get_scancode_with_modifiers"), &InputEventKey::get_scancode_with_modifiers);
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "scancode"), "set_scancode", "get_scancode");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "unicode"), "set_unicode", "get_unicode");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "echo"), "set_echo", "is_echo");
+}
+
+InputEventKey::InputEventKey() {
+
+	pressed = false;
+	scancode = 0;
+	unicode = 0; ///unicode
+	echo = false;
+}
+
+////////////////////////////////////////
+
+void InputEventMouse::set_button_mask(int p_mask) {
+
+	button_mask = p_mask;
+}
+int InputEventMouse::get_button_mask() const {
+
+	return button_mask;
+}
+
+void InputEventMouse::set_pos(const Vector2 &p_pos) {
+
+	pos = p_pos;
+}
+Vector2 InputEventMouse::get_pos() const {
+
+	return pos;
+}
+
+void InputEventMouse::set_global_pos(const Vector2 &p_global_pos) {
+
+	global_pos = p_global_pos;
+}
+Vector2 InputEventMouse::get_global_pos() const {
+
+	return global_pos;
+}
+
+void InputEventMouse::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_button_mask", "button_mask"), &InputEventMouse::set_button_mask);
+	ClassDB::bind_method(D_METHOD("get_button_mask"), &InputEventMouse::get_button_mask);
+
+	ClassDB::bind_method(D_METHOD("set_pos", "pos"), &InputEventMouse::set_pos);
+	ClassDB::bind_method(D_METHOD("get_pos"), &InputEventMouse::get_pos);
+
+	ClassDB::bind_method(D_METHOD("set_global_pos", "global_pos"), &InputEventMouse::set_global_pos);
+	ClassDB::bind_method(D_METHOD("get_global_pos"), &InputEventMouse::get_global_pos);
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask"), "set_button_mask", "get_button_mask");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pos"), "set_pos", "get_pos");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_pos"), "set_global_pos", "get_global_pos");
+}
+
+InputEventMouse::InputEventMouse() {
+
+	button_mask = 0;
+}
+
+///////////////////////////////////////
+
+void InputEventMouseButton::set_factor(float p_factor) {
+
+	factor = p_factor;
+}
+
+float InputEventMouseButton::get_factor() {
+
+	return factor;
+}
+
+void InputEventMouseButton::set_button_index(int p_index) {
+
+	button_index = p_index;
+}
+int InputEventMouseButton::get_button_index() const {
+
+	return button_index;
+}
+
+void InputEventMouseButton::set_pressed(bool p_pressed) {
+
+	pressed = p_pressed;
+}
+bool InputEventMouseButton::is_pressed() const {
+
+	return pressed;
+}
+
+void InputEventMouseButton::set_doubleclick(bool p_doubleclick) {
+
+	doubleclick = p_doubleclick;
+}
+bool InputEventMouseButton::is_doubleclick() const {
+
+	return doubleclick;
+}
+
+Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+	Vector2 g = p_xform.xform(get_global_pos());
+	Vector2 l = p_xform.xform(get_pos() + p_local_ofs);
+
+	Ref<InputEventMouseButton> mb;
+	mb.instance();
+
+	mb->set_id(get_id());
+	mb->set_device(get_device());
+
+	mb->set_alt(get_alt());
+	mb->set_shift(get_shift());
+	mb->set_control(get_control());
+	mb->set_metakey(get_metakey());
+
+	mb->set_pos(l);
+	mb->set_global_pos(g);
+
+	mb->set_button_mask(get_button_mask());
+	mb->set_pressed(pressed);
+	mb->set_doubleclick(doubleclick);
+	mb->set_factor(factor);
+	mb->set_button_index(button_index);
+
+	return mb;
+}
+
+bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event) const {
+
+	Ref<InputEventMouseButton> mb = p_event;
+	if (mb.is_null())
+		return false;
+
+	return mb->button_index == button_index;
+}
+
+void InputEventMouseButton::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_factor", "factor"), &InputEventMouseButton::set_factor);
+	ClassDB::bind_method(D_METHOD("get_factor"), &InputEventMouseButton::get_factor);
+
+	ClassDB::bind_method(D_METHOD("set_button_index", "button_index"), &InputEventMouseButton::set_button_index);
+	ClassDB::bind_method(D_METHOD("get_button_index"), &InputEventMouseButton::get_button_index);
+
+	ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventMouseButton::set_pressed);
+	//	ClassDB::bind_method(D_METHOD("is_pressed"), &InputEventMouseButton::is_pressed);
+
+	ClassDB::bind_method(D_METHOD("set_doubleclick", "doubleclick"), &InputEventMouseButton::set_doubleclick);
+	ClassDB::bind_method(D_METHOD("is_doubleclick"), &InputEventMouseButton::is_doubleclick);
+
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "factor"), "set_factor", "get_factor");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "button_index"), "set_button_index", "get_button_index");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "doubleclick"), "set_doubleclick", "is_doubleclick");
+}
+
+InputEventMouseButton::InputEventMouseButton() {
+
+	factor = 0;
+	button_index = 0;
+	pressed = false;
+	doubleclick = false;
+}
+
+////////////////////////////////////////////
+
+void InputEventMouseMotion::set_relative(const Vector2 &p_relative) {
+
+	relative = p_relative;
+}
+Vector2 InputEventMouseMotion::get_relative() const {
+
+	return relative;
+}
+
+void InputEventMouseMotion::set_speed(const Vector2 &p_speed) {
+
+	speed = p_speed;
+}
+Vector2 InputEventMouseMotion::get_speed() const {
+
+	return speed;
+}
+
+Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+	Vector2 g = p_xform.xform(get_global_pos());
+	Vector2 l = p_xform.xform(get_pos() + p_local_ofs);
+	Vector2 r = p_xform.basis_xform(get_relative());
+	Vector2 s = p_xform.basis_xform(get_speed());
+
+	Ref<InputEventMouseMotion> mm;
+	mm.instance();
+
+	mm->set_id(get_id());
+	mm->set_device(get_device());
+
+	mm->set_alt(get_alt());
+	mm->set_shift(get_shift());
+	mm->set_control(get_control());
+	mm->set_metakey(get_metakey());
+
+	mm->set_pos(l);
+	mm->set_global_pos(g);
+
+	mm->set_button_mask(get_button_mask());
+	mm->set_relative(r);
+	mm->set_speed(s);
+
+	return mm;
+}
+
+void InputEventMouseMotion::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventMouseMotion::set_relative);
+	ClassDB::bind_method(D_METHOD("get_relative"), &InputEventMouseMotion::get_relative);
+
+	ClassDB::bind_method(D_METHOD("set_speed", "speed"), &InputEventMouseMotion::set_speed);
+	ClassDB::bind_method(D_METHOD("get_speed"), &InputEventMouseMotion::get_speed);
+
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "speed"), "set_speed", "get_speed");
+}
+
+InputEventMouseMotion::InputEventMouseMotion() {
+}
+
+////////////////////////////////////////
+
+void InputEventJoypadMotion::set_axis(int p_axis) {
+
+	axis = p_axis;
+}
+
+int InputEventJoypadMotion::get_axis() const {
+
+	return axis;
+}
+
+void InputEventJoypadMotion::set_axis_value(float p_value) {
+
+	axis_value = p_value;
+}
+float InputEventJoypadMotion::get_axis_value() const {
+
+	return axis_value;
+}
+
+bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event) const {
+
+	Ref<InputEventJoypadMotion> jm = p_event;
+	if (jm.is_null())
+		return false;
+
+	return (axis == jm->axis && (axis_value < 0) == (jm->axis_value < 0));
+}
+
+void InputEventJoypadMotion::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_axis", "axis"), &InputEventJoypadMotion::set_axis);
+	ClassDB::bind_method(D_METHOD("get_axis"), &InputEventJoypadMotion::get_axis);
+
+	ClassDB::bind_method(D_METHOD("set_axis_value", "axis_value"), &InputEventJoypadMotion::set_axis_value);
+	ClassDB::bind_method(D_METHOD("get_axis_value"), &InputEventJoypadMotion::get_axis_value);
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "axis"), "set_axis", "get_axis");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "axis_value"), "set_axis_value", "get_axis_value");
+}
+
+InputEventJoypadMotion::InputEventJoypadMotion() {
+
+	axis = 0;
+	axis_value = 0;
+}
+/////////////////////////////////
+
+void InputEventJoypadButton::set_button_index(int p_index) {
+
+	button_index = p_index;
+}
+
+int InputEventJoypadButton::get_button_index() const {
+
+	return button_index;
+}
+
+void InputEventJoypadButton::set_pressed(bool p_pressed) {
+
+	pressed = p_pressed;
+}
+bool InputEventJoypadButton::is_pressed() const {
+
+	return pressed;
+}
+
+void InputEventJoypadButton::set_pressure(float p_pressure) {
+
+	pressure = p_pressure;
+}
+float InputEventJoypadButton::get_pressure() const {
+
+	return pressure;
+}
+
+bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event) const {
+
+	Ref<InputEventJoypadButton> jb = p_event;
+	if (jb.is_null())
+		return false;
+
+	return button_index == jb->button_index;
+}
+
+void InputEventJoypadButton::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_button_index", "button_index"), &InputEventJoypadButton::set_button_index);
+	ClassDB::bind_method(D_METHOD("get_button_index"), &InputEventJoypadButton::get_button_index);
+
+	ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventJoypadButton::set_pressure);
+	ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventJoypadButton::get_pressure);
+
+	ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventJoypadButton::set_pressed);
+	//	ClassDB::bind_method(D_METHOD("is_pressed"), &InputEventJoypadButton::is_pressed);
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "button_index"), "set_button_index", "get_button_index");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "pressure"), "set_pressure", "get_pressure");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
+}
+
+InputEventJoypadButton::InputEventJoypadButton() {
+
+	button_index = 0;
+	pressure = 0;
+	pressed = false;
+}
+
+//////////////////////////////////////////////
+
+void InputEventScreenTouch::set_index(int p_index) {
+
+	index = p_index;
+}
+int InputEventScreenTouch::get_index() const {
+
+	return index;
+}
+
+void InputEventScreenTouch::set_pos(const Vector2 &p_pos) {
+
+	pos = p_pos;
+}
+Vector2 InputEventScreenTouch::get_pos() const {
+
+	return pos;
+}
+
+void InputEventScreenTouch::set_pressed(bool p_pressed) {
+
+	pressed = p_pressed;
+}
+bool InputEventScreenTouch::is_pressed() const {
+
+	return pressed;
+}
+
+Ref<InputEvent> InputEventScreenTouch::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+	Ref<InputEventScreenTouch> st;
+	st.instance();
+	st->set_id(get_id());
+	st->set_device(get_device());
+	st->set_index(index);
+	st->set_pos(p_xform.xform(pos + p_local_ofs));
+	st->set_pressed(pressed);
+
+	return st;
+}
+
+void InputEventScreenTouch::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_index", "index"), &InputEventScreenTouch::set_index);
+	ClassDB::bind_method(D_METHOD("get_index"), &InputEventScreenTouch::get_index);
+
+	ClassDB::bind_method(D_METHOD("set_pos", "pos"), &InputEventScreenTouch::set_pos);
+	ClassDB::bind_method(D_METHOD("get_pos"), &InputEventScreenTouch::get_pos);
+
+	ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventScreenTouch::set_pressed);
+	//ClassDB::bind_method(D_METHOD("is_pressed"),&InputEventScreenTouch::is_pressed);
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pos"), "set_pos", "get_pos");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
+}
+
+InputEventScreenTouch::InputEventScreenTouch() {
+
+	index = 0;
+	pressed = false;
+}
+
+/////////////////////////////
+
+void InputEventScreenDrag::set_index(int p_index) {
+
+	index = p_index;
+}
+
+int InputEventScreenDrag::get_index() const {
+
+	return index;
+}
+
+void InputEventScreenDrag::set_pos(const Vector2 &p_pos) {
+
+	pos = p_pos;
+}
+Vector2 InputEventScreenDrag::get_pos() const {
+
+	return pos;
+}
+
+void InputEventScreenDrag::set_relative(const Vector2 &p_relative) {
+
+	relative = p_relative;
+}
+Vector2 InputEventScreenDrag::get_relative() const {
+
+	return relative;
+}
+
+void InputEventScreenDrag::set_speed(const Vector2 &p_speed) {
+
+	speed = p_speed;
+}
+Vector2 InputEventScreenDrag::get_speed() const {
+
+	return speed;
+}
+
+Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+	Ref<InputEventScreenDrag> sd;
+
+	sd.instance();
+
+	sd->set_id(get_id());
+	sd->set_device(get_device());
+
+	sd->set_index(index);
+	sd->set_pos(p_xform.xform(pos + p_local_ofs));
+	sd->set_relative(p_xform.basis_xform(relative));
+	sd->set_speed(p_xform.basis_xform(speed));
+
+	return sd;
+}
+
+void InputEventScreenDrag::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_index", "index"), &InputEventScreenDrag::set_index);
+	ClassDB::bind_method(D_METHOD("get_index"), &InputEventScreenDrag::get_index);
+
+	ClassDB::bind_method(D_METHOD("set_pos", "pos"), &InputEventScreenDrag::set_pos);
+	ClassDB::bind_method(D_METHOD("get_pos"), &InputEventScreenDrag::get_pos);
+
+	ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventScreenDrag::set_relative);
+	ClassDB::bind_method(D_METHOD("get_relative"), &InputEventScreenDrag::get_relative);
+
+	ClassDB::bind_method(D_METHOD("set_speed", "speed"), &InputEventScreenDrag::set_speed);
+	ClassDB::bind_method(D_METHOD("get_speed"), &InputEventScreenDrag::get_speed);
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pos"), "set_pos", "get_pos");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "speed"), "set_speed", "get_speed");
+}
+
+InputEventScreenDrag::InputEventScreenDrag() {
+
+	index = 0;
+}
+/////////////////////////////
+
+void InputEventAction::set_action(const StringName &p_action) {
+
+	action = p_action;
+}
+StringName InputEventAction::get_action() const {
+
+	return action;
+}
+
+void InputEventAction::set_pressed(bool p_pressed) {
+
+	pressed = p_pressed;
+}
+bool InputEventAction::is_pressed() const {
+
+	return pressed;
+}
+
+bool InputEventAction::is_action(const StringName &p_action) const {
+
+	return action == p_action;
+}
+
+void InputEventAction::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_action", "action"), &InputEventAction::set_action);
+	ClassDB::bind_method(D_METHOD("get_action"), &InputEventAction::get_action);
+
+	ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventAction::set_pressed);
+	//ClassDB::bind_method(D_METHOD("is_pressed"), &InputEventAction::is_pressed);
+
+	ClassDB::bind_method(D_METHOD("is_action", "name"), &InputEventAction::is_action);
+
+	ADD_PROPERTY(PropertyInfo(Variant::STRING, "action"), "set_action", "get_action");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
+}
 
-	return ev;
+InputEventAction::InputEventAction() {
+	pressed = false;
 }

+ 245 - 70
core/os/input_event.h

@@ -32,6 +32,7 @@
 
 #include "math_2d.h"
 #include "os/copymem.h"
+#include "resource.h"
 #include "typedefs.h"
 #include "ustring.h"
 /**
@@ -137,7 +138,40 @@ enum {
  * Input Modifier Status
  * for keyboard/mouse events.
  */
-struct InputModifierState {
+
+class InputEvent : public Resource {
+	GDCLASS(InputEvent, Resource)
+
+	uint32_t id;
+	int device;
+
+protected:
+	static void _bind_methods();
+
+public:
+	void set_id(uint32_t p_id);
+	uint32_t get_id() const;
+
+	void set_device(int p_device);
+	int get_device() const;
+
+	virtual bool is_pressed() const;
+	virtual bool is_action(const StringName &p_action) const;
+	virtual bool is_action_pressed(const StringName &p_action) const;
+	virtual bool is_action_released(const StringName &p_action) const;
+	virtual bool is_echo() const;
+	virtual String as_text() const;
+
+	virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+
+	virtual bool action_match(const Ref<InputEvent> &p_event) const;
+	virtual bool is_action_type() const;
+
+	InputEvent();
+};
+
+class InputEventWithModifiers : public InputEvent {
+	GDCLASS(InputEventWithModifiers, InputEvent)
 
 	bool shift;
 	bool alt;
@@ -157,126 +191,267 @@ struct InputModifierState {
 
 #endif
 
-	bool operator==(const InputModifierState &rvalue) const {
+protected:
+	static void _bind_methods();
+
+public:
+	void set_shift(bool p_enabled);
+	bool get_shift() const;
+
+	void set_alt(bool p_enabled);
+	bool get_alt() const;
+
+	void set_control(bool p_enabled);
+	bool get_control() const;
+
+	void set_metakey(bool p_enabled);
+	bool get_metakey() const;
+
+	void set_command(bool p_enabled);
+	bool get_command() const;
 
-		return ((shift == rvalue.shift) && (alt == rvalue.alt) && (control == rvalue.control) && (meta == rvalue.meta));
-	}
+	InputEventWithModifiers();
 };
 
-struct InputEventKey {
+class InputEventKey : public InputEventWithModifiers {
 
-	InputModifierState mod;
+	GDCLASS(InputEventKey, InputEventWithModifiers)
 
 	bool pressed; /// otherwise release
 
 	uint32_t scancode; ///< check keyboard.h , KeyCode enum, without modifier masks
 	uint32_t unicode; ///unicode
 
+	bool echo; /// true if this is an echo key
+
+protected:
+	static void _bind_methods();
+
+public:
+	void set_pressed(bool p_pressed);
+	bool is_pressed();
+
+	void set_scancode(uint32_t p_scancode);
+	uint32_t get_scancode() const;
+
+	void set_unicode(uint32_t p_unicode);
+	uint32_t get_unicode() const;
+
+	void set_echo(bool p_enable);
+	bool is_echo() const;
+
 	uint32_t get_scancode_with_modifiers() const;
 
-	bool echo; /// true if this is an echo key
+	virtual bool action_match(const Ref<InputEvent> &p_event) const;
+
+	virtual bool is_action_type() const { return true; }
+
+	InputEventKey();
 };
 
-struct InputEventMouse {
+class InputEventMouse : public InputEventWithModifiers {
+
+	GDCLASS(InputEventMouse, InputEventWithModifiers)
 
-	InputModifierState mod;
 	int button_mask;
-	float x, y;
-	float global_x, global_y;
-	int pointer_index;
+
+	Vector2 pos;
+	Vector2 global_pos;
+
+protected:
+	static void _bind_methods();
+
+public:
+	void set_button_mask(int p_mask);
+	int get_button_mask() const;
+
+	void set_pos(const Vector2 &p_pos);
+	Vector2 get_pos() const;
+
+	void set_global_pos(const Vector2 &p_global_pos);
+	Vector2 get_global_pos() const;
+
+	InputEventMouse();
 };
 
-struct InputEventMouseButton : public InputEventMouse {
+class InputEventMouseButton : public InputEventMouse {
+
+	GDCLASS(InputEventMouseButton, InputEventMouse)
 
-	double factor;
+	float factor;
 	int button_index;
 	bool pressed; //otherwise released
 	bool doubleclick; //last even less than doubleclick time
+
+protected:
+	static void _bind_methods();
+
+public:
+	void set_factor(float p_factor);
+	float get_factor();
+
+	void set_button_index(int p_index);
+	int get_button_index() const;
+
+	void set_pressed(bool p_pressed);
+	virtual bool is_pressed() const;
+
+	void set_doubleclick(bool p_doubleclick);
+	bool is_doubleclick() const;
+
+	virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+	virtual bool action_match(const Ref<InputEvent> &p_event) const;
+
+	virtual bool is_action_type() const { return true; }
+
+	InputEventMouseButton();
 };
 
-struct InputEventMouseMotion : public InputEventMouse {
+class InputEventMouseMotion : public InputEventMouse {
+
+	GDCLASS(InputEventMouseMotion, InputEventMouse)
+	Vector2 relative;
+	Vector2 speed;
+
+protected:
+	static void _bind_methods();
+
+public:
+	void set_relative(const Vector2 &p_relative);
+	Vector2 get_relative() const;
+
+	void set_speed(const Vector2 &p_speed);
+	Vector2 get_speed() const;
+
+	virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
 
-	float relative_x, relative_y;
-	float speed_x, speed_y;
+	InputEventMouseMotion();
 };
 
-struct InputEventJoypadMotion {
+class InputEventJoypadMotion : public InputEvent {
 
+	GDCLASS(InputEventJoypadMotion, InputEvent)
 	int axis; ///< Joypad axis
 	float axis_value; ///< -1 to 1
+
+protected:
+	static void _bind_methods();
+
+public:
+	void set_axis(int p_axis);
+	int get_axis() const;
+
+	void set_axis_value(float p_value);
+	float get_axis_value() const;
+
+	virtual bool action_match(const Ref<InputEvent> &p_event) const;
+
+	virtual bool is_action_type() const { return true; }
+
+	InputEventJoypadMotion();
 };
 
-struct InputEventJoypadButton {
+class InputEventJoypadButton : public InputEvent {
+	GDCLASS(InputEventJoypadButton, InputEvent)
 
 	int button_index;
 	bool pressed;
 	float pressure; //0 to 1
-};
+protected:
+	static void _bind_methods();
+
+public:
+	void set_button_index(int p_index);
+	int get_button_index() const;
+
+	void set_pressed(bool p_pressed);
+	virtual bool is_pressed() const;
+
+	void set_pressure(float p_pressure);
+	float get_pressure() const;
 
-struct InputEventScreenTouch {
+	virtual bool action_match(const Ref<InputEvent> &p_event) const;
 
+	virtual bool is_action_type() const { return true; }
+
+	InputEventJoypadButton();
+};
+
+struct InputEventScreenTouch : public InputEvent {
+	GDCLASS(InputEventScreenTouch, InputEvent)
 	int index;
-	float x, y;
+	Vector2 pos;
 	bool pressed;
+
+protected:
+	static void _bind_methods();
+
+public:
+	void set_index(int p_index);
+	int get_index() const;
+
+	void set_pos(const Vector2 &p_pos);
+	Vector2 get_pos() const;
+
+	void set_pressed(bool p_pressed);
+	virtual bool is_pressed() const;
+
+	virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+
+	InputEventScreenTouch();
 };
-struct InputEventScreenDrag {
 
+class InputEventScreenDrag : public InputEvent {
+
+	GDCLASS(InputEventScreenDrag, InputEvent)
 	int index;
-	float x, y;
-	float relative_x, relative_y;
-	float speed_x, speed_y;
+	Vector2 pos;
+	Vector2 relative;
+	Vector2 speed;
+
+protected:
+	static void _bind_methods();
+
+public:
+	void set_index(int p_index);
+	int get_index() const;
+
+	void set_pos(const Vector2 &p_pos);
+	Vector2 get_pos() const;
+
+	void set_relative(const Vector2 &p_relative);
+	Vector2 get_relative() const;
+
+	void set_speed(const Vector2 &p_speed);
+	Vector2 get_speed() const;
+
+	virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+
+	InputEventScreenDrag();
 };
 
-struct InputEventAction {
+class InputEventAction : public InputEvent {
+
+	GDCLASS(InputEventAction, InputEvent)
 
-	int action;
+	StringName action;
 	bool pressed;
-};
 
-struct InputEvent {
-
-	enum Type {
-		NONE,
-		KEY,
-		MOUSE_MOTION,
-		MOUSE_BUTTON,
-		JOYPAD_MOTION,
-		JOYPAD_BUTTON,
-		SCREEN_TOUCH,
-		SCREEN_DRAG,
-		ACTION,
-		TYPE_MAX
-	};
+protected:
+	static void _bind_methods();
 
-	uint32_t ID;
-	int type;
-	int device;
+public:
+	void set_action(const StringName &p_action);
+	StringName get_action() const;
 
-	union {
-		InputEventMouseMotion mouse_motion;
-		InputEventMouseButton mouse_button;
-		InputEventJoypadMotion joy_motion;
-		InputEventJoypadButton joy_button;
-		InputEventKey key;
-		InputEventScreenTouch screen_touch;
-		InputEventScreenDrag screen_drag;
-		InputEventAction action;
-	};
+	void set_pressed(bool p_pressed);
+	virtual bool is_pressed() const;
 
-	bool is_pressed() const;
-	bool is_action(const String &p_action) const;
-	bool is_action_pressed(const String &p_action) const;
-	bool is_action_released(const String &p_action) const;
-	bool is_echo() const;
-	void set_as_action(const String &p_action, bool p_pressed);
-
-	InputEvent xform_by(const Transform2D &p_xform) const;
-	bool operator==(const InputEvent &p_event) const;
-	operator String() const;
-	InputEvent() {
-		zeromem(this, sizeof(InputEvent));
-		mouse_button.factor = 1;
-	}
+	virtual bool is_action(const StringName &p_action) const;
+
+	virtual bool is_action_type() const { return true; }
+
+	InputEventAction();
 };
 
 #endif

+ 2 - 2
core/os/main_loop.cpp

@@ -39,7 +39,7 @@ void MainLoop::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("idle", "delta"), &MainLoop::idle);
 	ClassDB::bind_method(D_METHOD("finish"), &MainLoop::finish);
 
-	BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::INPUT_EVENT, "ev")));
+	BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "ev", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
 	BIND_VMETHOD(MethodInfo("_input_text", PropertyInfo(Variant::STRING, "text")));
 	BIND_VMETHOD(MethodInfo("_initialize"));
 	BIND_VMETHOD(MethodInfo("_iteration", PropertyInfo(Variant::REAL, "delta")));
@@ -73,7 +73,7 @@ void MainLoop::input_text(const String &p_text) {
 		get_script_instance()->call("_input_text", p_text);
 }
 
-void MainLoop::input_event(const InputEvent &p_event) {
+void MainLoop::input_event(const Ref<InputEvent> &p_event) {
 
 	if (get_script_instance())
 		get_script_instance()->call("_input_event", p_event);

+ 1 - 1
core/os/main_loop.h

@@ -59,7 +59,7 @@ public:
 		NOTIFICATION_TRANSLATION_CHANGED = 10,
 	};
 
-	virtual void input_event(const InputEvent &p_event);
+	virtual void input_event(const Ref<InputEvent> &p_event);
 	virtual void input_text(const String &p_text);
 
 	virtual void init();

+ 0 - 1
core/packed_data_container.cpp

@@ -237,7 +237,6 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
 		case Variant::RECT3:
 		case Variant::BASIS:
 		case Variant::TRANSFORM:
-		case Variant::INPUT_EVENT:
 		case Variant::POOL_BYTE_ARRAY:
 		case Variant::POOL_INT_ARRAY:
 		case Variant::POOL_REAL_ARRAY:

+ 12 - 0
core/register_core_types.cpp

@@ -110,6 +110,18 @@ void register_core_types() {
 	ClassDB::register_class<Resource>();
 	ClassDB::register_class<Image>();
 
+	ClassDB::register_virtual_class<InputEvent>();
+	ClassDB::register_virtual_class<InputEventWithModifiers>();
+	ClassDB::register_class<InputEventKey>();
+	ClassDB::register_virtual_class<InputEventMouse>();
+	ClassDB::register_class<InputEventMouseButton>();
+	ClassDB::register_class<InputEventMouseMotion>();
+	ClassDB::register_class<InputEventJoypadButton>();
+	ClassDB::register_class<InputEventJoypadMotion>();
+	ClassDB::register_class<InputEventScreenDrag>();
+	ClassDB::register_class<InputEventScreenTouch>();
+	ClassDB::register_class<InputEventAction>();
+
 	ClassDB::register_class<FuncRef>();
 	ClassDB::register_virtual_class<StreamPeer>();
 	ClassDB::register_class<StreamPeerBuffer>();

+ 0 - 41
core/variant.cpp

@@ -132,11 +132,6 @@ String Variant::get_type_name(Variant::Type p_type) {
 
 			return "NodePath";
 
-		} break;
-		case INPUT_EVENT: {
-
-			return "InputEvent";
-
 		} break;
 		case DICTIONARY: {
 
@@ -797,11 +792,6 @@ bool Variant::is_zero() const {
 
 			return reinterpret_cast<const NodePath *>(_data._mem)->is_empty();
 
-		} break;
-		case INPUT_EVENT: {
-
-			return _data._input_event->type == InputEvent::NONE;
-
 		} break;
 		case DICTIONARY: {
 
@@ -1017,11 +1007,6 @@ void Variant::reference(const Variant &p_variant) {
 
 			memnew_placement(_data._mem, NodePath(*reinterpret_cast<const NodePath *>(p_variant._data._mem)));
 
-		} break;
-		case INPUT_EVENT: {
-
-			_data._input_event = memnew(InputEvent(*p_variant._data._input_event));
-
 		} break;
 		case DICTIONARY: {
 
@@ -1149,12 +1134,6 @@ void Variant::clear() {
 			reinterpret_cast<Array *>(_data._mem)->~Array();
 
 		} break;
-		case INPUT_EVENT: {
-
-			memdelete(_data._input_event);
-
-		} break;
-
 		// arrays
 		case POOL_BYTE_ARRAY: {
 
@@ -1503,7 +1482,6 @@ Variant::operator String() const {
 		} break;
 		case TRANSFORM: return operator Transform();
 		case NODE_PATH: return operator NodePath();
-		case INPUT_EVENT: return operator InputEvent();
 		case COLOR: return String::num(operator Color().r) + "," + String::num(operator Color().g) + "," + String::num(operator Color().b) + "," + String::num(operator Color().a);
 		case DICTIONARY: {
 
@@ -1798,14 +1776,6 @@ Variant::operator Control *() const {
 		return NULL;
 }
 
-Variant::operator InputEvent() const {
-
-	if (type == INPUT_EVENT)
-		return *reinterpret_cast<const InputEvent *>(_data._input_event);
-	else
-		return InputEvent();
-}
-
 Variant::operator Dictionary() const {
 
 	if (type == DICTIONARY)
@@ -2285,12 +2255,6 @@ Variant::Variant(const NodePath &p_node_path) {
 	memnew_placement(_data._mem, NodePath(p_node_path));
 }
 
-Variant::Variant(const InputEvent &p_input_event) {
-
-	type = INPUT_EVENT;
-	_data._input_event = memnew(InputEvent(p_input_event));
-}
-
 Variant::Variant(const RefPtr &p_resource) {
 
 	type = OBJECT;
@@ -2690,11 +2654,6 @@ uint32_t Variant::hash() const {
 
 			return reinterpret_cast<const NodePath *>(_data._mem)->hash();
 		} break;
-		case INPUT_EVENT: {
-
-			return hash_djb2_buffer((uint8_t *)_data._input_event, sizeof(InputEvent));
-
-		} break;
 		case DICTIONARY: {
 
 			return reinterpret_cast<const Dictionary *>(_data._mem)->hash();

+ 1 - 5
core/variant.h

@@ -42,7 +42,6 @@
 #include "io/ip_address.h"
 #include "math_2d.h"
 #include "matrix3.h"
-#include "os/input_event.h"
 #include "os/power.h"
 #include "path_db.h"
 #include "plane.h"
@@ -100,7 +99,6 @@ public:
 		NODE_PATH, // 15
 		_RID,
 		OBJECT,
-		INPUT_EVENT,
 		DICTIONARY,
 		ARRAY, // 20
 
@@ -143,7 +141,6 @@ private:
 		Basis *_basis;
 		Transform *_transform;
 		RefPtr *_resource;
-		InputEvent *_input_event;
 		void *_ptr; //generic pointer
 		uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)];
 	} _data;
@@ -207,7 +204,7 @@ public:
 	operator NodePath() const;
 	operator RefPtr() const;
 	operator RID() const;
-	operator InputEvent() const;
+
 	operator Object *() const;
 	operator Node *() const;
 	operator Control *() const;
@@ -276,7 +273,6 @@ public:
 	Variant(const RefPtr &p_resource);
 	Variant(const RID &p_rid);
 	Variant(const Object *p_object);
-	Variant(const InputEvent &p_input_event);
 	Variant(const Dictionary &p_dictionary);
 
 	Variant(const Array &p_array);

+ 0 - 26
core/variant_call.cpp

@@ -737,13 +737,6 @@ struct _VariantCall {
 	VCALL_PTR1( Transform, translate );
 	VCALL_PTR0( Transform, orthonormalize ); */
 
-	VCALL_PTR0R(InputEvent, is_pressed);
-	VCALL_PTR1R(InputEvent, is_action);
-	VCALL_PTR1R(InputEvent, is_action_pressed);
-	VCALL_PTR1R(InputEvent, is_action_released);
-	VCALL_PTR0R(InputEvent, is_echo);
-	VCALL_PTR2(InputEvent, set_as_action);
-
 	struct ConstructData {
 
 		int arg_count;
@@ -1036,7 +1029,6 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
 				return NodePath(); // 15
 			case _RID: return RID();
 			case OBJECT: return (Object *)NULL;
-			case INPUT_EVENT: return InputEvent();
 			case DICTIONARY: return Dictionary();
 			case ARRAY:
 				return Array(); // 20
@@ -1117,7 +1109,6 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
 				return (NodePath(p_args[0]->operator NodePath())); // 15
 			case _RID: return (RID(*p_args[0]));
 			case OBJECT: return ((Object *)(p_args[0]->operator Object *()));
-			case INPUT_EVENT: return (InputEvent(*p_args[0]));
 			case DICTIONARY: return p_args[0]->operator Dictionary();
 			case ARRAY:
 				return p_args[0]->operator Array(); // 20
@@ -1690,13 +1681,6 @@ void register_variant_methods() {
 	_VariantCall::type_funcs[Variant::TRANSFORM].functions["xform_inv"].returns = true;
 #endif
 
-	ADDFUNC0(INPUT_EVENT, BOOL, InputEvent, is_pressed, varray());
-	ADDFUNC1(INPUT_EVENT, BOOL, InputEvent, is_action, STRING, "action", varray());
-	ADDFUNC1(INPUT_EVENT, BOOL, InputEvent, is_action_pressed, STRING, "action", varray());
-	ADDFUNC1(INPUT_EVENT, BOOL, InputEvent, is_action_released, STRING, "action", varray());
-	ADDFUNC0(INPUT_EVENT, BOOL, InputEvent, is_echo, varray());
-	ADDFUNC2(INPUT_EVENT, NIL, InputEvent, set_as_action, STRING, "action", BOOL, "pressed", varray());
-
 	/* REGISTER CONSTRUCTORS */
 
 	_VariantCall::add_constructor(_VariantCall::Vector2_init1, Variant::VECTOR2, "x", Variant::REAL, "y", Variant::REAL);
@@ -1733,16 +1717,6 @@ void register_variant_methods() {
 	_VariantCall::add_constant(Variant::VECTOR3, "AXIS_X", Vector3::AXIS_X);
 	_VariantCall::add_constant(Variant::VECTOR3, "AXIS_Y", Vector3::AXIS_Y);
 	_VariantCall::add_constant(Variant::VECTOR3, "AXIS_Z", Vector3::AXIS_Z);
-
-	_VariantCall::add_constant(Variant::INPUT_EVENT, "NONE", InputEvent::NONE);
-	_VariantCall::add_constant(Variant::INPUT_EVENT, "KEY", InputEvent::KEY);
-	_VariantCall::add_constant(Variant::INPUT_EVENT, "MOUSE_MOTION", InputEvent::MOUSE_MOTION);
-	_VariantCall::add_constant(Variant::INPUT_EVENT, "MOUSE_BUTTON", InputEvent::MOUSE_BUTTON);
-	_VariantCall::add_constant(Variant::INPUT_EVENT, "JOYPAD_MOTION", InputEvent::JOYPAD_MOTION);
-	_VariantCall::add_constant(Variant::INPUT_EVENT, "JOYPAD_BUTTON", InputEvent::JOYPAD_BUTTON);
-	_VariantCall::add_constant(Variant::INPUT_EVENT, "SCREEN_TOUCH", InputEvent::SCREEN_TOUCH);
-	_VariantCall::add_constant(Variant::INPUT_EVENT, "SCREEN_DRAG", InputEvent::SCREEN_DRAG);
-	_VariantCall::add_constant(Variant::INPUT_EVENT, "ACTION", InputEvent::ACTION);
 }
 
 void unregister_variant_methods() {

+ 0 - 714
core/variant_op.cpp

@@ -61,7 +61,6 @@ bool Variant::booleanize(bool &r_valid) const {
 		case _RID: return (*reinterpret_cast<const RID *>(_data._mem)).is_valid();
 		case OBJECT: return _get_obj().obj;
 		case NODE_PATH: return (*reinterpret_cast<const NodePath *>(_data._mem)) != NodePath();
-		case INPUT_EVENT:
 		case DICTIONARY:
 		case ARRAY:
 		case POOL_BYTE_ARRAY:
@@ -291,7 +290,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
 					if (p_b.type == NIL)
 						_RETURN(!p_a._get_obj().obj);
 				} break;
-					DEFAULT_OP_PTRREF(==, INPUT_EVENT, _input_event);
 
 				case DICTIONARY: {
 
@@ -378,7 +376,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
 					if (p_b.type == OBJECT)
 						_RETURN((p_a._get_obj().obj < p_b._get_obj().obj));
 				} break;
-					DEFAULT_OP_FAIL(INPUT_EVENT);
 					DEFAULT_OP_FAIL(DICTIONARY);
 				case ARRAY: {
 
@@ -443,7 +440,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
 					if (p_b.type == OBJECT)
 						_RETURN((p_a._get_obj().obj <= p_b._get_obj().obj));
 				} break;
-					DEFAULT_OP_FAIL(INPUT_EVENT);
 					DEFAULT_OP_FAIL(DICTIONARY);
 					DEFAULT_OP_FAIL(ARRAY);
 					DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
@@ -502,7 +498,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
 				DEFAULT_OP_FAIL(NODE_PATH);
 				DEFAULT_OP_FAIL(_RID);
 				DEFAULT_OP_FAIL(OBJECT);
-				DEFAULT_OP_FAIL(INPUT_EVENT);
 				DEFAULT_OP_FAIL(DICTIONARY);
 
 				case ARRAY: {
@@ -559,7 +554,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
 				DEFAULT_OP_FAIL(NODE_PATH);
 				DEFAULT_OP_FAIL(_RID);
 				DEFAULT_OP_FAIL(OBJECT);
-				DEFAULT_OP_FAIL(INPUT_EVENT);
 				DEFAULT_OP_FAIL(DICTIONARY);
 				DEFAULT_OP_FAIL(ARRAY);
 				DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
@@ -656,7 +650,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
 					DEFAULT_OP_FAIL(NODE_PATH);
 					DEFAULT_OP_FAIL(_RID);
 					DEFAULT_OP_FAIL(OBJECT);
-					DEFAULT_OP_FAIL(INPUT_EVENT);
 					DEFAULT_OP_FAIL(DICTIONARY);
 					DEFAULT_OP_FAIL(ARRAY);
 					DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
@@ -729,7 +722,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
 					DEFAULT_OP_FAIL(NODE_PATH);
 					DEFAULT_OP_FAIL(_RID);
 					DEFAULT_OP_FAIL(OBJECT);
-					DEFAULT_OP_FAIL(INPUT_EVENT);
 					DEFAULT_OP_FAIL(DICTIONARY);
 					DEFAULT_OP_FAIL(ARRAY);
 					DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
@@ -771,7 +763,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
 				DEFAULT_OP_FAIL(NODE_PATH);
 				DEFAULT_OP_FAIL(_RID);
 				DEFAULT_OP_FAIL(OBJECT);
-				DEFAULT_OP_FAIL(INPUT_EVENT);
 				DEFAULT_OP_FAIL(DICTIONARY);
 				DEFAULT_OP_FAIL(ARRAY);
 				DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
@@ -811,7 +802,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
 				DEFAULT_OP_FAIL(NODE_PATH);
 				DEFAULT_OP_FAIL(_RID);
 				DEFAULT_OP_FAIL(OBJECT);
-				DEFAULT_OP_FAIL(INPUT_EVENT);
 				DEFAULT_OP_FAIL(DICTIONARY);
 				DEFAULT_OP_FAIL(ARRAY);
 				DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
@@ -1507,389 +1497,6 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
 				return obj->set(p_index, p_value, r_valid);
 			}
 		} break;
-		case INPUT_EVENT: {
-
-			InputEvent &ie = *_data._input_event;
-
-			if (p_index.get_type() != Variant::STRING)
-				return;
-
-			const String &str = *reinterpret_cast<const String *>(p_index._data._mem);
-
-			if (str == "type") {
-
-				if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-					return;
-
-				int type = p_value;
-				if (type < 0 || type >= InputEvent::TYPE_MAX)
-					return; //fail
-				valid = true;
-				ie.type = InputEvent::Type(type);
-				return;
-			} else if (str == "device") {
-
-				if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-					return;
-
-				valid = true;
-				ie.device = p_value;
-				return;
-			} else if (str == "ID") {
-
-				if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-					return;
-
-				valid = true;
-				ie.ID = p_value;
-				return;
-			}
-
-			if (ie.type == InputEvent::KEY || ie.type == InputEvent::MOUSE_BUTTON || ie.type == InputEvent::MOUSE_MOTION) {
-
-				if (str == "shift") {
-
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL && p_value.type != Variant::BOOL)
-						return;
-
-					valid = true;
-					ie.key.mod.shift = p_value;
-					return;
-				}
-				if (str == "alt") {
-
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL && p_value.type != Variant::BOOL)
-						return;
-
-					valid = true;
-					ie.key.mod.alt = p_value;
-					return;
-				}
-				if (str == "control") {
-
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL && p_value.type != Variant::BOOL)
-						return;
-
-					valid = true;
-					ie.key.mod.control = p_value;
-					return;
-				}
-				if (str == "meta") {
-
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL && p_value.type != Variant::BOOL)
-						return;
-
-					valid = true;
-					ie.key.mod.meta = p_value;
-					return;
-				}
-			}
-
-			if (ie.type == InputEvent::KEY) {
-
-				if (str == "pressed") {
-
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL && p_value.type != Variant::BOOL)
-						return;
-
-					valid = true;
-					ie.key.pressed = p_value;
-					return;
-				} else if (str == "scancode") {
-
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-						return;
-
-					valid = true;
-					ie.key.scancode = p_value;
-					return;
-				} else if (str == "unicode") {
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-						return;
-					valid = true;
-					ie.key.unicode = p_value;
-					return;
-				} else if (str == "echo") {
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL && p_value.type != Variant::BOOL)
-						return;
-
-					valid = true;
-					ie.key.echo = p_value;
-					return;
-				}
-			}
-
-			if (ie.type == InputEvent::MOUSE_MOTION || ie.type == InputEvent::MOUSE_BUTTON) {
-
-				if (str == "button_mask") {
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-						return;
-					valid = true;
-					ie.mouse_button.button_mask = p_value;
-					return;
-				} else if (str == "x") {
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-						return;
-					valid = true;
-					ie.mouse_button.x = p_value;
-					return;
-				} else if (str == "y") {
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-						return;
-					valid = true;
-					ie.mouse_button.y = p_value;
-					return;
-				} else if (str == "pos") {
-					if (p_value.type != Variant::VECTOR2)
-						return;
-					valid = true;
-					Point2 value = p_value;
-					ie.mouse_button.x = value.x;
-					ie.mouse_button.y = value.y;
-					return;
-				} else if (str == "global_x") {
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-						return;
-					valid = true;
-					ie.mouse_button.global_x = p_value;
-					return;
-				} else if (str == "global_y") {
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-						return;
-					valid = true;
-					ie.mouse_button.global_y = p_value;
-					return;
-				} else if (str == "global_pos") {
-					if (p_value.type != Variant::VECTOR2)
-						return;
-					valid = true;
-					Point2 value = p_value;
-					ie.mouse_button.global_x = value.x;
-					ie.mouse_button.global_y = value.y;
-					return;
-				} /*else if (str=="pointer_index") {
-					valid=true;
-					return ie.mouse_button.pointer_index;
-				}*/
-
-				if (ie.type == InputEvent::MOUSE_MOTION) {
-
-					if (str == "relative_x") {
-						if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-							return;
-						valid = true;
-						ie.mouse_motion.relative_x = p_value;
-						return;
-					} else if (str == "relative_y") {
-						if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-							return;
-						valid = true;
-						ie.mouse_motion.relative_y = p_value;
-						return;
-					} else if (str == "relative_pos") {
-						if (p_value.type != Variant::VECTOR2)
-							return;
-						valid = true;
-						Point2 value = p_value;
-						ie.mouse_motion.relative_x = value.x;
-						ie.mouse_motion.relative_y = value.y;
-						return;
-					}
-
-					if (str == "speed_x") {
-						if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-							return;
-						valid = true;
-						ie.mouse_motion.speed_x = p_value;
-						return;
-					} else if (str == "speed_y") {
-						if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-							return;
-						valid = true;
-						ie.mouse_motion.speed_y = p_value;
-						return;
-					} else if (str == "speed") {
-						if (p_value.type != Variant::VECTOR2)
-							return;
-						valid = true;
-						Point2 value = p_value;
-						ie.mouse_motion.speed_x = value.x;
-						ie.mouse_motion.speed_y = value.y;
-						return;
-					}
-
-				} else if (ie.type == InputEvent::MOUSE_BUTTON) {
-
-					if (str == "button_index") {
-						if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
-							return;
-						valid = true;
-						ie.mouse_button.button_index = p_value;
-						return;
-					} else if (str == "pressed") {
-						if (p_value.type != Variant::INT && p_value.type != Variant::REAL && p_value.type != Variant::BOOL)
-							return;
-						valid = true;
-						ie.mouse_button.pressed = p_value;
-						return;
-					} else if (str == "doubleclick") {
-						if (p_value.type != Variant::INT && p_value.type != Variant::REAL && p_value.type != Variant::BOOL)
-							return;
-						valid = true;
-						ie.mouse_button.doubleclick = p_value;
-						return;
-					}
-				}
-			}
-
-			if (ie.type == InputEvent::JOYPAD_BUTTON) {
-
-				if (str == "button_index") {
-					if (p_value.type != Variant::REAL && p_value.type != Variant::INT)
-						return;
-					valid = true;
-					ie.joy_button.button_index = p_value;
-					return;
-				}
-				if (str == "pressed") {
-					if (p_value.type != Variant::INT && p_value.type != Variant::REAL && p_value.type != Variant::BOOL)
-						return;
-
-					valid = true;
-					ie.joy_button.pressed = p_value;
-					return;
-				}
-				if (str == "pressure") {
-					if (p_value.type != Variant::REAL && p_value.type != Variant::INT)
-						return;
-					valid = true;
-					ie.joy_button.pressure = p_value;
-					return;
-				}
-			}
-
-			if (ie.type == InputEvent::JOYPAD_MOTION) {
-
-				if (str == "axis") {
-					if (p_value.type != Variant::REAL && p_value.type != Variant::INT)
-						return;
-					valid = true;
-					ie.joy_motion.axis = p_value;
-					return;
-				}
-				if (str == "value") {
-					if (p_value.type != Variant::REAL && p_value.type != Variant::INT)
-						return;
-					valid = true;
-					ie.joy_motion.axis_value = p_value;
-					return;
-				}
-			}
-
-			if (ie.type == InputEvent::SCREEN_TOUCH) {
-
-				if (str == "index") {
-					valid = true;
-					ie.screen_touch.index = p_value;
-					return;
-				}
-				if (str == "x") {
-					valid = true;
-					ie.screen_touch.x = p_value;
-					return;
-				}
-				if (str == "y") {
-					valid = true;
-					ie.screen_touch.y = p_value;
-					return;
-				}
-				if (str == "pos") {
-					valid = true;
-					Vector2 v = p_value;
-					ie.screen_touch.x = v.x;
-					ie.screen_touch.y = v.y;
-					return;
-				}
-				if (str == "pressed") {
-					valid = true;
-					ie.screen_touch.pressed = p_value;
-					return;
-				}
-			}
-
-			if (ie.type == InputEvent::SCREEN_DRAG) {
-
-				if (str == "index") {
-					valid = true;
-					ie.screen_drag.index = p_value;
-					return;
-				}
-				if (str == "x") {
-					valid = true;
-					ie.screen_drag.x = p_value;
-					return;
-				}
-				if (str == "y") {
-					valid = true;
-					ie.screen_drag.y = p_value;
-					return;
-				}
-				if (str == "pos") {
-					valid = true;
-					Vector2 v = p_value;
-					ie.screen_drag.x = v.x;
-					ie.screen_drag.y = v.y;
-					return;
-				}
-				if (str == "relative_x") {
-					valid = true;
-					ie.screen_drag.relative_x = p_value;
-					return;
-				}
-				if (str == "relative_y") {
-					valid = true;
-					ie.screen_drag.relative_y = p_value;
-					return;
-				}
-				if (str == "relative_pos") {
-					valid = true;
-					Vector2 v = p_value;
-					ie.screen_drag.relative_x = v.x;
-					ie.screen_drag.relative_y = v.y;
-					return;
-				}
-				if (str == "speed_x") {
-					valid = true;
-					ie.screen_drag.speed_x = p_value;
-					return;
-				}
-				if (str == "speed_y") {
-					valid = true;
-					ie.screen_drag.speed_y = p_value;
-					return;
-				}
-				if (str == "speed") {
-					valid = true;
-					Vector2 v = p_value;
-					ie.screen_drag.speed_x = v.x;
-					ie.screen_drag.speed_y = v.y;
-					return;
-				}
-			}
-			if (ie.type == InputEvent::ACTION) {
-
-				if (str == "action") {
-					valid = true;
-					ie.action.action = p_value;
-					return;
-				} else if (str == "pressed") {
-					valid = true;
-					ie.action.pressed = p_value;
-					return;
-				}
-			}
-
-		} break;
 		case DICTIONARY: {
 
 			Dictionary *dic = reinterpret_cast<Dictionary *>(_data._mem);
@@ -2260,235 +1867,6 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
 				return obj->get(p_index, r_valid);
 			}
 
-		} break;
-		case INPUT_EVENT: {
-
-			InputEvent ie = operator InputEvent();
-
-			if (p_index.get_type() != Variant::STRING)
-				break;
-
-			const String &str = *reinterpret_cast<const String *>(p_index._data._mem);
-
-			if (str == "type") {
-				valid = true;
-				return ie.type;
-			} else if (str == "device") {
-				valid = true;
-				return ie.device;
-			} else if (str == "ID") {
-				valid = true;
-				return ie.ID;
-			}
-
-			if (ie.type == InputEvent::KEY || ie.type == InputEvent::MOUSE_BUTTON || ie.type == InputEvent::MOUSE_MOTION) {
-
-				if (str == "shift") {
-					valid = true;
-					return ie.key.mod.shift;
-				}
-				if (str == "alt") {
-					valid = true;
-					return ie.key.mod.alt;
-				}
-				if (str == "control") {
-					valid = true;
-					return ie.key.mod.control;
-				}
-				if (str == "meta") {
-					valid = true;
-					return ie.key.mod.meta;
-				}
-			}
-
-			if (ie.type == InputEvent::KEY) {
-
-				if (str == "pressed") {
-					valid = true;
-					return ie.key.pressed;
-				} else if (str == "scancode") {
-					valid = true;
-					return ie.key.scancode;
-				} else if (str == "unicode") {
-					valid = true;
-					return ie.key.unicode;
-				} else if (str == "echo") {
-					valid = true;
-					return ie.key.echo;
-				}
-			}
-
-			if (ie.type == InputEvent::MOUSE_MOTION || ie.type == InputEvent::MOUSE_BUTTON) {
-
-				if (str == "button_mask") {
-					valid = true;
-					return ie.mouse_button.button_mask;
-				} else if (str == "x") {
-					valid = true;
-					return ie.mouse_button.x;
-				} else if (str == "y") {
-					valid = true;
-					return ie.mouse_button.y;
-				} else if (str == "pos") {
-					valid = true;
-					return Point2(ie.mouse_button.x, ie.mouse_button.y);
-				} else if (str == "global_x") {
-					valid = true;
-					return ie.mouse_button.global_x;
-				} else if (str == "global_y") {
-					valid = true;
-					return ie.mouse_button.global_y;
-				} else if (str == "global_pos") {
-					valid = true;
-					return Point2(ie.mouse_button.global_x, ie.mouse_button.global_y);
-				} /*else if (str=="pointer_index") {
-					valid=true;
-					return ie.mouse_button.pointer_index;
-				}*/
-
-				if (ie.type == InputEvent::MOUSE_MOTION) {
-
-					if (str == "relative_x") {
-						valid = true;
-						return ie.mouse_motion.relative_x;
-					} else if (str == "relative_y") {
-						valid = true;
-						return ie.mouse_motion.relative_y;
-					} else if (str == "relative_pos") {
-						valid = true;
-						return Point2(ie.mouse_motion.relative_x, ie.mouse_motion.relative_y);
-					} else if (str == "speed_x") {
-						valid = true;
-						return ie.mouse_motion.speed_x;
-					} else if (str == "speed_y") {
-						valid = true;
-						return ie.mouse_motion.speed_y;
-					} else if (str == "speed") {
-						valid = true;
-						return Point2(ie.mouse_motion.speed_x, ie.mouse_motion.speed_y);
-					}
-
-				} else if (ie.type == InputEvent::MOUSE_BUTTON) {
-
-					if (str == "button_index") {
-						valid = true;
-						return ie.mouse_button.button_index;
-					} else if (str == "pressed") {
-						valid = true;
-						return ie.mouse_button.pressed;
-					} else if (str == "doubleclick") {
-						valid = true;
-						return ie.mouse_button.doubleclick;
-					}
-				}
-			}
-
-			if (ie.type == InputEvent::JOYPAD_BUTTON) {
-
-				if (str == "button_index") {
-					valid = true;
-					return ie.joy_button.button_index;
-				}
-				if (str == "pressed") {
-					valid = true;
-					return ie.joy_button.pressed;
-				}
-				if (str == "pressure") {
-					valid = true;
-					return ie.joy_button.pressure;
-				}
-			}
-
-			if (ie.type == InputEvent::JOYPAD_MOTION) {
-
-				if (str == "axis") {
-					valid = true;
-					return ie.joy_motion.axis;
-				}
-				if (str == "value") {
-					valid = true;
-					return ie.joy_motion.axis_value;
-				}
-			}
-
-			if (ie.type == InputEvent::SCREEN_TOUCH) {
-
-				if (str == "index") {
-					valid = true;
-					return ie.screen_touch.index;
-				}
-				if (str == "x") {
-					valid = true;
-					return ie.screen_touch.x;
-				}
-				if (str == "y") {
-					valid = true;
-					return ie.screen_touch.y;
-				}
-				if (str == "pos") {
-					valid = true;
-					return Vector2(ie.screen_touch.x, ie.screen_touch.y);
-				}
-				if (str == "pressed") {
-					valid = true;
-					return ie.screen_touch.pressed;
-				}
-			}
-
-			if (ie.type == InputEvent::SCREEN_DRAG) {
-
-				if (str == "index") {
-					valid = true;
-					return ie.screen_drag.index;
-				}
-				if (str == "x") {
-					valid = true;
-					return ie.screen_drag.x;
-				}
-				if (str == "y") {
-					valid = true;
-					return ie.screen_drag.y;
-				}
-				if (str == "pos") {
-					valid = true;
-					return Vector2(ie.screen_drag.x, ie.screen_drag.y);
-				}
-				if (str == "relative_x") {
-					valid = true;
-					return ie.screen_drag.relative_x;
-				}
-				if (str == "relative_y") {
-					valid = true;
-					return ie.screen_drag.relative_y;
-				}
-				if (str == "relative_pos") {
-					valid = true;
-					return Vector2(ie.screen_drag.relative_x, ie.screen_drag.relative_y);
-				}
-				if (str == "speed_x") {
-					valid = true;
-					return ie.screen_drag.speed_x;
-				}
-				if (str == "speed_y") {
-					valid = true;
-					return ie.screen_drag.speed_y;
-				}
-				if (str == "speed") {
-					valid = true;
-					return Vector2(ie.screen_drag.speed_x, ie.screen_drag.speed_y);
-				}
-			}
-			if (ie.type == InputEvent::ACTION) {
-
-				if (str == "action") {
-					valid = true;
-					return ie.action.action;
-				} else if (str == "pressed") {
-					valid = true;
-					return ie.action.pressed;
-				}
-			}
-
 		} break;
 		case DICTIONARY: {
 
@@ -2822,94 +2200,6 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
 				obj->get_property_list(p_list);
 			}
 
-		} break;
-		case INPUT_EVENT: {
-
-			InputEvent ie = operator InputEvent();
-
-			p_list->push_back(PropertyInfo(Variant::INT, "type"));
-			p_list->push_back(PropertyInfo(Variant::INT, "device"));
-			p_list->push_back(PropertyInfo(Variant::INT, "ID"));
-
-			if (ie.type == InputEvent::KEY || ie.type == InputEvent::MOUSE_BUTTON || ie.type == InputEvent::MOUSE_MOTION) {
-
-				p_list->push_back(PropertyInfo(Variant::BOOL, "shift"));
-				p_list->push_back(PropertyInfo(Variant::BOOL, "alt"));
-				p_list->push_back(PropertyInfo(Variant::BOOL, "control"));
-				p_list->push_back(PropertyInfo(Variant::BOOL, "meta"));
-			}
-
-			if (ie.type == InputEvent::KEY) {
-
-				p_list->push_back(PropertyInfo(Variant::BOOL, "pressed"));
-				p_list->push_back(PropertyInfo(Variant::BOOL, "echo"));
-				p_list->push_back(PropertyInfo(Variant::INT, "scancode"));
-				p_list->push_back(PropertyInfo(Variant::INT, "unicode"));
-			}
-
-			if (ie.type == InputEvent::MOUSE_MOTION || ie.type == InputEvent::MOUSE_BUTTON) {
-
-				p_list->push_back(PropertyInfo(Variant::INT, "button_mask"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "x"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "y"));
-				p_list->push_back(PropertyInfo(Variant::VECTOR2, "pos"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "global_x"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "global_y"));
-				p_list->push_back(PropertyInfo(Variant::VECTOR2, "global_pos"));
-
-				if (ie.type == InputEvent::MOUSE_MOTION) {
-
-					p_list->push_back(PropertyInfo(Variant::REAL, "relative_x"));
-					p_list->push_back(PropertyInfo(Variant::REAL, "relative_y"));
-					p_list->push_back(PropertyInfo(Variant::VECTOR2, "relative_pos"));
-					p_list->push_back(PropertyInfo(Variant::REAL, "speed_x"));
-					p_list->push_back(PropertyInfo(Variant::REAL, "speed_y"));
-					p_list->push_back(PropertyInfo(Variant::VECTOR2, "speed"));
-
-				} else if (ie.type == InputEvent::MOUSE_BUTTON) {
-
-					p_list->push_back(PropertyInfo(Variant::INT, "button_index"));
-					p_list->push_back(PropertyInfo(Variant::BOOL, "pressed"));
-					p_list->push_back(PropertyInfo(Variant::BOOL, "doubleclick"));
-				}
-			}
-
-			if (ie.type == InputEvent::JOYPAD_BUTTON) {
-
-				p_list->push_back(PropertyInfo(Variant::INT, "button_index"));
-				p_list->push_back(PropertyInfo(Variant::BOOL, "pressed"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "pressure"));
-			}
-
-			if (ie.type == InputEvent::JOYPAD_MOTION) {
-
-				p_list->push_back(PropertyInfo(Variant::INT, "axis"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "value"));
-			}
-
-			if (ie.type == InputEvent::SCREEN_TOUCH) {
-
-				p_list->push_back(PropertyInfo(Variant::INT, "index"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "x"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "y"));
-				p_list->push_back(PropertyInfo(Variant::VECTOR2, "pos"));
-				p_list->push_back(PropertyInfo(Variant::BOOL, "pressed"));
-			}
-
-			if (ie.type == InputEvent::SCREEN_DRAG) {
-
-				p_list->push_back(PropertyInfo(Variant::INT, "index"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "x"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "y"));
-				p_list->push_back(PropertyInfo(Variant::VECTOR2, "pos"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "relative_x"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "relative_y"));
-				p_list->push_back(PropertyInfo(Variant::VECTOR2, "relative_pos"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "speed_x"));
-				p_list->push_back(PropertyInfo(Variant::REAL, "speed_y"));
-				p_list->push_back(PropertyInfo(Variant::VECTOR2, "speed"));
-			}
-
 		} break;
 		case DICTIONARY: {
 
@@ -3636,10 +2926,6 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
 			r_dst = a;
 		}
 			return;
-		case INPUT_EVENT: {
-			r_dst = a;
-		}
-			return;
 		case DICTIONARY: {
 		}
 			return;

+ 30 - 151
core/variant_parser.cpp

@@ -30,6 +30,7 @@
 #include "variant_parser.h"
 
 #include "io/resource_loader.h"
+#include "os/input_event.h"
 #include "os/keyboard.h"
 
 CharType VariantParser::StreamFile::get_char() {
@@ -760,7 +761,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 			}
 
 			return OK;
-
+#ifndef DISABLE_DEPRECATED
 		} else if (id == "InputEvent") {
 
 			get_token(p_stream, token, line, r_err_str);
@@ -778,12 +779,10 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 
 			String id = token.value;
 
-			InputEvent ie;
+			Ref<InputEvent> ie;
 
 			if (id == "NONE") {
 
-				ie.type = InputEvent::NONE;
-
 				get_token(p_stream, token, line, r_err_str);
 
 				if (token.type != TK_PARENTHESIS_CLOSE) {
@@ -793,21 +792,23 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 
 			} else if (id == "KEY") {
 
+				Ref<InputEventKey> key;
+				key.instance();
+				ie = key;
+
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type != TK_COMMA) {
 					r_err_str = "Expected ','";
 					return ERR_PARSE_ERROR;
 				}
 
-				ie.type = InputEvent::KEY;
-
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type == TK_IDENTIFIER) {
 					String name = token.value;
-					ie.key.scancode = find_keycode(name);
+					key->set_scancode(find_keycode(name));
 				} else if (token.type == TK_NUMBER) {
 
-					ie.key.scancode = token.value;
+					key->set_scancode(token.value);
 				} else {
 
 					r_err_str = "Expected string or integer for keycode";
@@ -828,13 +829,13 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 					String mods = token.value;
 
 					if (mods.findn("C") != -1)
-						ie.key.mod.control = true;
+						key->set_control(true);
 					if (mods.findn("A") != -1)
-						ie.key.mod.alt = true;
+						key->set_alt(true);
 					if (mods.findn("S") != -1)
-						ie.key.mod.shift = true;
+						key->set_shift(true);
 					if (mods.findn("M") != -1)
-						ie.key.mod.meta = true;
+						key->set_metakey(true);
 
 					get_token(p_stream, token, line, r_err_str);
 					if (token.type != TK_PARENTHESIS_CLOSE) {
@@ -850,21 +851,23 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 
 			} else if (id == "MBUTTON") {
 
+				Ref<InputEventMouseButton> mb;
+				mb.instance();
+				ie = mb;
+
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type != TK_COMMA) {
 					r_err_str = "Expected ','";
 					return ERR_PARSE_ERROR;
 				}
 
-				ie.type = InputEvent::MOUSE_BUTTON;
-
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type != TK_NUMBER) {
 					r_err_str = "Expected button index";
 					return ERR_PARSE_ERROR;
 				}
 
-				ie.mouse_button.button_index = token.value;
+				mb->set_button_index(token.value);
 
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type != TK_PARENTHESIS_CLOSE) {
@@ -874,21 +877,23 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 
 			} else if (id == "JBUTTON") {
 
+				Ref<InputEventJoypadButton> jb;
+				jb.instance();
+				ie = jb;
+
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type != TK_COMMA) {
 					r_err_str = "Expected ','";
 					return ERR_PARSE_ERROR;
 				}
 
-				ie.type = InputEvent::JOYPAD_BUTTON;
-
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type != TK_NUMBER) {
 					r_err_str = "Expected button index";
 					return ERR_PARSE_ERROR;
 				}
 
-				ie.joy_button.button_index = token.value;
+				jb->set_button_index(token.value);
 
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type != TK_PARENTHESIS_CLOSE) {
@@ -898,21 +903,23 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 
 			} else if (id == "JAXIS") {
 
+				Ref<InputEventJoypadMotion> jm;
+				jm.instance();
+				ie = jm;
+
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type != TK_COMMA) {
 					r_err_str = "Expected ','";
 					return ERR_PARSE_ERROR;
 				}
 
-				ie.type = InputEvent::JOYPAD_MOTION;
-
 				get_token(p_stream, token, line, r_err_str);
 				if (token.type != TK_NUMBER) {
 					r_err_str = "Expected axis index";
 					return ERR_PARSE_ERROR;
 				}
 
-				ie.joy_motion.axis = token.value;
+				jm->set_axis(token.value);
 
 				get_token(p_stream, token, line, r_err_str);
 
@@ -927,7 +934,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 					return ERR_PARSE_ERROR;
 				}
 
-				ie.joy_motion.axis_value = token.value;
+				jm->set_axis_value(token.value);
 
 				get_token(p_stream, token, line, r_err_str);
 
@@ -945,7 +952,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 			value = ie;
 
 			return OK;
-
+#endif
 		} else if (id == "PoolByteArray" || id == "ByteArray") {
 
 			Vector<uint8_t> args;
@@ -1121,91 +1128,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 			value = arr;
 
 			return OK;
-		} else if (id == "key") { // compatibility with project.godot
-
-			Vector<String> params;
-			Error err = _parse_enginecfg(p_stream, params, line, r_err_str);
-			if (err)
-				return err;
-			ERR_FAIL_COND_V(params.size() != 1 && params.size() != 2, ERR_PARSE_ERROR);
-
-			int scode = 0;
-
-			if (params[0].is_numeric()) {
-				scode = params[0].to_int();
-				if (scode < 10) {
-					scode = KEY_0 + scode;
-				}
-			} else
-				scode = find_keycode(params[0]);
-
-			InputEvent ie;
-			ie.type = InputEvent::KEY;
-			ie.key.scancode = scode;
-
-			if (params.size() == 2) {
-				String mods = params[1];
-				if (mods.findn("C") != -1)
-					ie.key.mod.control = true;
-				if (mods.findn("A") != -1)
-					ie.key.mod.alt = true;
-				if (mods.findn("S") != -1)
-					ie.key.mod.shift = true;
-				if (mods.findn("M") != -1)
-					ie.key.mod.meta = true;
-			}
-			value = ie;
-			return OK;
-
-		} else if (id == "mbutton") { // compatibility with project.godot
-
-			Vector<String> params;
-			Error err = _parse_enginecfg(p_stream, params, line, r_err_str);
-			if (err)
-				return err;
-			ERR_FAIL_COND_V(params.size() != 2, ERR_PARSE_ERROR);
-
-			InputEvent ie;
-			ie.type = InputEvent::MOUSE_BUTTON;
-			ie.device = params[0].to_int();
-			ie.mouse_button.button_index = params[1].to_int();
-
-			value = ie;
-			return OK;
-		} else if (id == "jbutton") { // compatibility with project.godot
-
-			Vector<String> params;
-			Error err = _parse_enginecfg(p_stream, params, line, r_err_str);
-			if (err)
-				return err;
-			ERR_FAIL_COND_V(params.size() != 2, ERR_PARSE_ERROR);
-			InputEvent ie;
-			ie.type = InputEvent::JOYPAD_BUTTON;
-			ie.device = params[0].to_int();
-			ie.joy_button.button_index = params[1].to_int();
-
-			value = ie;
-
-			return OK;
-		} else if (id == "jaxis") { // compatibility with project.godot
-
-			Vector<String> params;
-			Error err = _parse_enginecfg(p_stream, params, line, r_err_str);
-			if (err)
-				return err;
-			ERR_FAIL_COND_V(params.size() != 2, ERR_PARSE_ERROR);
-
-			InputEvent ie;
-			ie.type = InputEvent::JOYPAD_MOTION;
-			ie.device = params[0].to_int();
-			int axis = params[1].to_int();
-			ie.joy_motion.axis = axis >> 1;
-			ie.joy_motion.axis_value = axis & 1 ? 1 : -1;
-
-			value = ie;
-
-			return OK;
-
 		} else {
 			r_err_str = "Unexpected identifier: '" + id + "'.";
 			return ERR_PARSE_ERROR;
@@ -1715,50 +1637,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
 			p_store_string_func(p_store_string_ud, res_text);
 
 		} break;
-		case Variant::INPUT_EVENT: {
-
-			String str = "InputEvent(";
-
-			InputEvent ev = p_variant;
-			switch (ev.type) {
-				case InputEvent::KEY: {
-
-					str += "KEY," + itos(ev.key.scancode);
-					String mod;
-					if (ev.key.mod.alt)
-						mod += "A";
-					if (ev.key.mod.shift)
-						mod += "S";
-					if (ev.key.mod.control)
-						mod += "C";
-					if (ev.key.mod.meta)
-						mod += "M";
-
-					if (mod != String())
-						str += "," + mod;
-				} break;
-				case InputEvent::MOUSE_BUTTON: {
-
-					str += "MBUTTON," + itos(ev.mouse_button.button_index);
-				} break;
-				case InputEvent::JOYPAD_BUTTON: {
-					str += "JBUTTON," + itos(ev.joy_button.button_index);
-
-				} break;
-				case InputEvent::JOYPAD_MOTION: {
-					str += "JAXIS," + itos(ev.joy_motion.axis) + "," + itos(ev.joy_motion.axis_value);
-				} break;
-				case InputEvent::NONE: {
-					str += "NONE";
-				} break;
-				default: {}
-			}
 
-			str += ")";
-
-			p_store_string_func(p_store_string_ud, str); //will be added later
-
-		} break;
 		case Variant::DICTIONARY: {
 
 			Dictionary dict = p_variant;

+ 1 - 1
doc/base/classes.xml

@@ -20360,7 +20360,7 @@
 		Singleton that manages actions.
 	</brief_description>
 	<description>
-		Singleton that manages actions. InputMap has a list of the actions used in InputEvent, which can be modified.
+		Singleton that manages actions. InputMap has a list of the actions used in Ref<InputEvent>, which can be modified.
 	</description>
 	<methods>
 		<method name="action_add_event">

+ 790 - 792
editor/animation_editor.cpp

@@ -154,13 +154,15 @@ private:
 		}
 	}
 
-	void _gui_input(const InputEvent &p_ev) {
-		if (p_ev.type == InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask & BUTTON_MASK_LEFT) {
+	void _gui_input(const Ref<InputEvent> &p_ev) {
+
+		Ref<InputEventMouseMotion> mm = p_ev;
+		if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
 
 			if (mode == MODE_DISABLED)
 				return;
 
-			float rel = p_ev.mouse_motion.relative_x;
+			float rel = mm->get_relative().x;
 			if (rel == 0)
 				return;
 
@@ -1746,7 +1748,7 @@ void AnimationKeyEditor::_anim_delete_keys() {
 	}
 }
 
-void AnimationKeyEditor::_track_editor_gui_input(const InputEvent &p_input) {
+void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input) {
 
 	Control *te = track_editor;
 	Ref<StyleBox> style = get_stylebox("normal", "TextEdit");
@@ -1804,1087 +1806,1083 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent &p_input) {
 	int settings_limit = size.width - right_separator_ofs;
 	int name_limit = settings_limit * name_column_ratio;
 
-	switch (p_input.type) {
+	Ref<InputEventKey> key = p_input;
+	if (key.is_valid()) {
 
-		case InputEvent::KEY: {
+		if (key->get_scancode() == KEY_D && key->is_pressed() && key->get_command()) {
 
-			if (p_input.key.scancode == KEY_D && p_input.key.pressed && p_input.key.mod.command) {
+			if (key->get_shift())
+				_menu_track(TRACK_MENU_DUPLICATE_TRANSPOSE);
+			else
+				_menu_track(TRACK_MENU_DUPLICATE);
 
-				if (p_input.key.mod.shift)
-					_menu_track(TRACK_MENU_DUPLICATE_TRANSPOSE);
-				else
-					_menu_track(TRACK_MENU_DUPLICATE);
+			accept_event();
 
-				accept_event();
+		} else if (key->get_scancode() == KEY_DELETE && key->is_pressed() && click.click == ClickOver::CLICK_NONE) {
 
-			} else if (p_input.key.scancode == KEY_DELETE && p_input.key.pressed && click.click == ClickOver::CLICK_NONE) {
+			_anim_delete_keys();
+		} else if (animation.is_valid() && animation->get_track_count() > 0) {
 
-				_anim_delete_keys();
-			} else if (animation.is_valid() && animation->get_track_count() > 0) {
-
-				if (p_input.is_pressed() && (p_input.is_action("ui_up") || p_input.is_action("ui_page_up"))) {
+			if (key->is_pressed() && (key->is_action("ui_up") || key->is_action("ui_page_up"))) {
 
-					if (p_input.is_action("ui_up"))
-						selected_track--;
-					if (v_scroll->is_visible_in_tree() && p_input.is_action("ui_page_up"))
-						selected_track--;
+				if (key->is_action("ui_up"))
+					selected_track--;
+				if (v_scroll->is_visible_in_tree() && key->is_action("ui_page_up"))
+					selected_track--;
 
-					if (selected_track < 0)
-						selected_track = 0;
+				if (selected_track < 0)
+					selected_track = 0;
 
-					if (v_scroll->is_visible_in_tree()) {
-						if (v_scroll->get_value() > selected_track)
-							v_scroll->set_value(selected_track);
-					}
-
-					track_editor->update();
-					accept_event();
+				if (v_scroll->is_visible_in_tree()) {
+					if (v_scroll->get_value() > selected_track)
+						v_scroll->set_value(selected_track);
 				}
 
-				if (p_input.is_pressed() && (p_input.is_action("ui_down") || p_input.is_action("ui_page_down"))) {
+				track_editor->update();
+				accept_event();
+			}
 
-					if (p_input.is_action("ui_down"))
-						selected_track++;
-					else if (v_scroll->is_visible_in_tree() && p_input.is_action("ui_page_down"))
-						selected_track += v_scroll->get_page();
+			if (key->is_pressed() && (key->is_action("ui_down") || key->is_action("ui_page_down"))) {
 
-					if (selected_track >= animation->get_track_count())
-						selected_track = animation->get_track_count() - 1;
+				if (key->is_action("ui_down"))
+					selected_track++;
+				else if (v_scroll->is_visible_in_tree() && key->is_action("ui_page_down"))
+					selected_track += v_scroll->get_page();
 
-					if (v_scroll->is_visible_in_tree() && v_scroll->get_page() + v_scroll->get_value() < selected_track + 1) {
-						v_scroll->set_value(selected_track - v_scroll->get_page() + 1);
-					}
+				if (selected_track >= animation->get_track_count())
+					selected_track = animation->get_track_count() - 1;
 
-					track_editor->update();
-					accept_event();
+				if (v_scroll->is_visible_in_tree() && v_scroll->get_page() + v_scroll->get_value() < selected_track + 1) {
+					v_scroll->set_value(selected_track - v_scroll->get_page() + 1);
 				}
+
+				track_editor->update();
+				accept_event();
 			}
+		}
+	}
 
-		} break;
-		case InputEvent::MOUSE_BUTTON: {
+	Ref<InputEventMouseButton> mb = p_input;
 
-			const InputEventMouseButton &mb = p_input.mouse_button;
+	if (mb.is_valid()) {
 
-			if (mb.button_index == BUTTON_WHEEL_UP && mb.pressed) {
+		if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
 
-				if (mb.mod.command) {
+			if (mb->get_command()) {
 
-					zoom->set_value(zoom->get_value() + zoom->get_step());
-				} else {
+				zoom->set_value(zoom->get_value() + zoom->get_step());
+			} else {
 
-					v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * mb.factor / 8);
-				}
+				v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * mb->get_factor() / 8);
 			}
+		}
 
-			if (mb.button_index == BUTTON_WHEEL_DOWN && mb.pressed) {
+		if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) {
 
-				if (mb.mod.command) {
+			if (mb->get_command()) {
 
-					zoom->set_value(zoom->get_value() - zoom->get_step());
-				} else {
+				zoom->set_value(zoom->get_value() - zoom->get_step());
+			} else {
 
-					v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * mb.factor / 8);
-				}
+				v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * mb->get_factor() / 8);
 			}
+		}
 
-			if (mb.button_index == BUTTON_WHEEL_RIGHT && mb.pressed) {
+		if (mb->get_button_index() == BUTTON_WHEEL_RIGHT && mb->is_pressed()) {
 
-				h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb.factor / 8);
-			}
+			h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb->get_factor() / 8);
+		}
 
-			if (mb.button_index == BUTTON_WHEEL_LEFT && mb.pressed) {
+		if (mb->get_button_index() == BUTTON_WHEEL_LEFT && mb->is_pressed()) {
 
-				v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * mb.factor / 8);
-			}
+			v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * mb->get_factor() / 8);
+		}
 
-			if (mb.button_index == BUTTON_RIGHT && mb.pressed) {
+		if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
 
-				Point2 mpos = Point2(mb.x, mb.y) - ofs;
+			Point2 mpos = mb->get_pos() - ofs;
 
-				if (selection.size() == 0) {
-					// Auto-select on right-click if nothing is selected
-					// Note: This code is pretty much duplicated from the left click code,
-					// both codes could be moved into a function to avoid the duplicated code.
-					Point2 mpos = Point2(mb.x, mb.y) - ofs;
+			if (selection.size() == 0) {
+				// Auto-select on right-click if nothing is selected
+				// Note: This code is pretty much duplicated from the left click code,
+				// both codes could be moved into a function to avoid the duplicated code.
+				Point2 mpos = mb->get_pos() - ofs;
 
-					if (mpos.y < h) {
-						return;
-					}
+				if (mpos.y < h) {
+					return;
+				}
 
-					mpos.y -= h;
+				mpos.y -= h;
 
-					int idx = mpos.y / h;
-					idx += v_scroll->get_value();
-					if (idx < 0 || idx >= animation->get_track_count())
-						break;
+				int idx = mpos.y / h;
+				idx += v_scroll->get_value();
+				if (idx < 0 || idx >= animation->get_track_count())
+					return;
 
-					if (mpos.x < name_limit) {
-					} else if (mpos.x < settings_limit) {
-						float pos = mpos.x - name_limit;
-						pos /= _get_zoom_scale();
-						pos += h_scroll->get_value();
-						float w_time = (type_icon[0]->get_width() / _get_zoom_scale()) / 2.0;
+				if (mpos.x < name_limit) {
+				} else if (mpos.x < settings_limit) {
+					float pos = mpos.x - name_limit;
+					pos /= _get_zoom_scale();
+					pos += h_scroll->get_value();
+					float w_time = (type_icon[0]->get_width() / _get_zoom_scale()) / 2.0;
 
-						int kidx = animation->track_find_key(idx, pos);
-						int kidx_n = kidx + 1;
-						int key = -1;
+					int kidx = animation->track_find_key(idx, pos);
+					int kidx_n = kidx + 1;
+					int key = -1;
 
-						if (kidx >= 0 && kidx < animation->track_get_key_count(idx)) {
+					if (kidx >= 0 && kidx < animation->track_get_key_count(idx)) {
 
-							float kpos = animation->track_get_key_time(idx, kidx);
-							if (ABS(pos - kpos) <= w_time) {
+						float kpos = animation->track_get_key_time(idx, kidx);
+						if (ABS(pos - kpos) <= w_time) {
 
-								key = kidx;
-							}
+							key = kidx;
 						}
+					}
 
-						if (key == -1 && kidx_n >= 0 && kidx_n < animation->track_get_key_count(idx)) {
+					if (key == -1 && kidx_n >= 0 && kidx_n < animation->track_get_key_count(idx)) {
 
-							float kpos = animation->track_get_key_time(idx, kidx_n);
-							if (ABS(pos - kpos) <= w_time) {
+						float kpos = animation->track_get_key_time(idx, kidx_n);
+						if (ABS(pos - kpos) <= w_time) {
 
-								key = kidx_n;
-							}
+							key = kidx_n;
 						}
+					}
 
-						if (key == -1) {
+					if (key == -1) {
 
-							click.click = ClickOver::CLICK_SELECT_KEYS;
-							click.at = Point2(mb.x, mb.y);
-							click.to = click.at;
-							click.shift = mb.mod.shift;
-							selected_track = idx;
-							track_editor->update();
-							//drag select region
-							return;
-						}
+						click.click = ClickOver::CLICK_SELECT_KEYS;
+						click.at = mb->get_pos();
+						click.to = click.at;
+						click.shift = mb->get_shift();
+						selected_track = idx;
+						track_editor->update();
+						//drag select region
+						return;
+					}
 
-						SelectedKey sk;
-						sk.track = idx;
-						sk.key = key;
-						KeyInfo ki;
-						ki.pos = animation->track_get_key_time(idx, key);
-						click.shift = mb.mod.shift;
-						click.selk = sk;
+					SelectedKey sk;
+					sk.track = idx;
+					sk.key = key;
+					KeyInfo ki;
+					ki.pos = animation->track_get_key_time(idx, key);
+					click.shift = mb->get_shift();
+					click.selk = sk;
 
-						if (!mb.mod.shift && !selection.has(sk))
-							_clear_selection();
+					if (!mb->get_shift() && !selection.has(sk))
+						_clear_selection();
 
-						selection.insert(sk, ki);
+					selection.insert(sk, ki);
 
-						click.click = ClickOver::CLICK_MOVE_KEYS;
-						click.at = Point2(mb.x, mb.y);
-						click.to = click.at;
-						update();
-						selected_track = idx;
-						track_editor->update();
+					click.click = ClickOver::CLICK_MOVE_KEYS;
+					click.at = mb->get_pos();
+					click.to = click.at;
+					update();
+					selected_track = idx;
+					track_editor->update();
 
-						if (_edit_if_single_selection() && mb.mod.command) {
-							edit_button->set_pressed(true);
-							key_editor_tab->show();
-						}
+					if (_edit_if_single_selection() && mb->get_command()) {
+						edit_button->set_pressed(true);
+						key_editor_tab->show();
 					}
 				}
+			}
 
-				if (selection.size()) {
-					// User has right clicked and we have a selection, show a popup menu with options
-					track_menu->clear();
-					track_menu->set_size(Point2(1, 1));
-					track_menu->add_item(TTR("Duplicate Selection"), RIGHT_MENU_DUPLICATE);
-					track_menu->add_item(TTR("Duplicate Transposed"), RIGHT_MENU_DUPLICATE_TRANSPOSE);
-					track_menu->add_item(TTR("Remove Selection"), RIGHT_MENU_REMOVE);
+			if (selection.size()) {
+				// User has right clicked and we have a selection, show a popup menu with options
+				track_menu->clear();
+				track_menu->set_size(Point2(1, 1));
+				track_menu->add_item(TTR("Duplicate Selection"), RIGHT_MENU_DUPLICATE);
+				track_menu->add_item(TTR("Duplicate Transposed"), RIGHT_MENU_DUPLICATE_TRANSPOSE);
+				track_menu->add_item(TTR("Remove Selection"), RIGHT_MENU_REMOVE);
 
-					track_menu->set_position(te->get_global_position() + mpos);
+				track_menu->set_position(te->get_global_position() + mpos);
 
-					interp_editing = -1;
-					cont_editing = -1;
-					wrap_editing = -1;
+				interp_editing = -1;
+				cont_editing = -1;
+				wrap_editing = -1;
 
-					track_menu->popup();
-				}
+				track_menu->popup();
 			}
+		}
 
-			if (mb.button_index == BUTTON_LEFT && !(mb.button_mask & ~BUTTON_MASK_LEFT)) {
+		if (mb->get_button_index() == BUTTON_LEFT && !(mb->get_button_mask() & ~BUTTON_MASK_LEFT)) {
 
-				if (mb.pressed) {
+			if (mb->is_pressed()) {
 
-					Point2 mpos = Point2(mb.x, mb.y) - ofs;
+				Point2 mpos = mb->get_pos() - ofs;
 
-					if (mpos.y < h) {
+				if (mpos.y < h) {
 
-						if (mpos.x < name_limit && mpos.x > (name_limit - hsep - hsize_icon->get_width())) {
+					if (mpos.x < name_limit && mpos.x > (name_limit - hsep - hsize_icon->get_width())) {
 
-							click.click = ClickOver::CLICK_RESIZE_NAMES;
-							click.at = Point2(mb.x, mb.y);
-							click.to = click.at;
-							click.at.y = name_limit;
-						}
+						click.click = ClickOver::CLICK_RESIZE_NAMES;
+						click.at = mb->get_pos();
+						click.to = click.at;
+						click.at.y = name_limit;
+					}
 
-						if (mpos.x >= name_limit && mpos.x < settings_limit) {
-							//seek
-							//int zoomw = settings_limit-name_limit;
-							float scale = _get_zoom_scale();
-							float pos = h_scroll->get_value() + (mpos.x - name_limit) / scale;
-							if (animation->get_step())
-								pos = Math::stepify(pos, animation->get_step());
-
-							if (pos < 0)
-								pos = 0;
-							if (pos >= animation->get_length())
-								pos = animation->get_length();
-							timeline_pos = pos;
-							click.click = ClickOver::CLICK_DRAG_TIMELINE;
-							click.at = Point2(mb.x, mb.y);
-							click.to = click.at;
-							emit_signal("timeline_changed", pos, false);
-						}
+					if (mpos.x >= name_limit && mpos.x < settings_limit) {
+						//seek
+						//int zoomw = settings_limit-name_limit;
+						float scale = _get_zoom_scale();
+						float pos = h_scroll->get_value() + (mpos.x - name_limit) / scale;
+						if (animation->get_step())
+							pos = Math::stepify(pos, animation->get_step());
 
-						return;
+						if (pos < 0)
+							pos = 0;
+						if (pos >= animation->get_length())
+							pos = animation->get_length();
+						timeline_pos = pos;
+						click.click = ClickOver::CLICK_DRAG_TIMELINE;
+						click.at = mb->get_pos();
+						click.to = click.at;
+						emit_signal("timeline_changed", pos, false);
 					}
 
-					mpos.y -= h;
+					return;
+				}
 
-					int idx = mpos.y / h;
-					idx += v_scroll->get_value();
-					if (idx < 0)
-						break;
+				mpos.y -= h;
 
-					if (idx >= animation->get_track_count()) {
+				int idx = mpos.y / h;
+				idx += v_scroll->get_value();
+				if (idx < 0)
+					return;
 
-						if (mpos.x >= name_limit && mpos.x < settings_limit) {
+				if (idx >= animation->get_track_count()) {
 
-							click.click = ClickOver::CLICK_SELECT_KEYS;
-							click.at = Point2(mb.x, mb.y);
-							click.to = click.at;
-							//drag select region
-						}
+					if (mpos.x >= name_limit && mpos.x < settings_limit) {
 
-						break;
+						click.click = ClickOver::CLICK_SELECT_KEYS;
+						click.at = mb->get_pos();
+						click.to = click.at;
+						//drag select region
 					}
 
-					if (mpos.x < name_limit) {
-						//name column
-
-						// area
-						if (idx != selected_track) {
-
-							selected_track = idx;
-							track_editor->update();
-							break;
-						}
+					return;
+				}
 
-						Rect2 area(ofs.x, ofs.y + ((int(mpos.y) / h) + 1) * h, name_limit, h);
-						track_name->set_text(animation->track_get_path(idx));
-						track_name->set_position(te->get_global_position() + area.pos);
-						track_name->set_size(area.size);
-						track_name->show_modal();
-						track_name->grab_focus();
-						track_name->select_all();
-						track_name_editing = idx;
+				if (mpos.x < name_limit) {
+					//name column
 
-					} else if (mpos.x < settings_limit) {
+					// area
+					if (idx != selected_track) {
 
-						float pos = mpos.x - name_limit;
-						pos /= _get_zoom_scale();
-						pos += h_scroll->get_value();
-						float w_time = (type_icon[0]->get_width() / _get_zoom_scale()) / 2.0;
+						selected_track = idx;
+						track_editor->update();
+						return;
+					}
 
-						int kidx = animation->track_find_key(idx, pos);
-						int kidx_n = kidx + 1;
-						int key = -1;
+					Rect2 area(ofs.x, ofs.y + ((int(mpos.y) / h) + 1) * h, name_limit, h);
+					track_name->set_text(animation->track_get_path(idx));
+					track_name->set_position(te->get_global_position() + area.pos);
+					track_name->set_size(area.size);
+					track_name->show_modal();
+					track_name->grab_focus();
+					track_name->select_all();
+					track_name_editing = idx;
 
-						if (kidx >= 0 && kidx < animation->track_get_key_count(idx)) {
+				} else if (mpos.x < settings_limit) {
 
-							float kpos = animation->track_get_key_time(idx, kidx);
-							if (ABS(pos - kpos) <= w_time) {
+					float pos = mpos.x - name_limit;
+					pos /= _get_zoom_scale();
+					pos += h_scroll->get_value();
+					float w_time = (type_icon[0]->get_width() / _get_zoom_scale()) / 2.0;
 
-								key = kidx;
-							}
-						}
+					int kidx = animation->track_find_key(idx, pos);
+					int kidx_n = kidx + 1;
+					int key = -1;
 
-						if (key == -1 && kidx_n >= 0 && kidx_n < animation->track_get_key_count(idx)) {
+					if (kidx >= 0 && kidx < animation->track_get_key_count(idx)) {
 
-							float kpos = animation->track_get_key_time(idx, kidx_n);
-							if (ABS(pos - kpos) <= w_time) {
+						float kpos = animation->track_get_key_time(idx, kidx);
+						if (ABS(pos - kpos) <= w_time) {
 
-								key = kidx_n;
-							}
+							key = kidx;
 						}
+					}
 
-						if (key == -1) {
+					if (key == -1 && kidx_n >= 0 && kidx_n < animation->track_get_key_count(idx)) {
 
-							click.click = ClickOver::CLICK_SELECT_KEYS;
-							click.at = Point2(mb.x, mb.y);
-							click.to = click.at;
-							click.shift = mb.mod.shift;
-							selected_track = idx;
-							track_editor->update();
-							//drag select region
-							return;
-						}
-
-						SelectedKey sk;
-						sk.track = idx;
-						sk.key = key;
-						KeyInfo ki;
-						ki.pos = animation->track_get_key_time(idx, key);
-						click.shift = mb.mod.shift;
-						click.selk = sk;
+						float kpos = animation->track_get_key_time(idx, kidx_n);
+						if (ABS(pos - kpos) <= w_time) {
 
-						if (!mb.mod.shift && !selection.has(sk))
-							_clear_selection();
+							key = kidx_n;
+						}
+					}
 
-						selection.insert(sk, ki);
+					if (key == -1) {
 
-						click.click = ClickOver::CLICK_MOVE_KEYS;
-						click.at = Point2(mb.x, mb.y);
+						click.click = ClickOver::CLICK_SELECT_KEYS;
+						click.at = mb->get_pos();
 						click.to = click.at;
-						update();
+						click.shift = mb->get_shift();
 						selected_track = idx;
 						track_editor->update();
+						//drag select region
+						return;
+					}
 
-						if (_edit_if_single_selection() && mb.mod.command) {
-							edit_button->set_pressed(true);
-							key_editor_tab->show();
-						}
-					} else {
-						//button column
-						int ofsx = size.width - mpos.x;
-						if (ofsx < 0)
-							break;
-						/*
-						if (ofsx < remove_icon->get_width()) {
-
-							undo_redo->create_action("Remove Anim Track");
-							undo_redo->add_do_method(animation.ptr(),"remove_track",idx);
-							undo_redo->add_undo_method(animation.ptr(),"add_track",animation->track_get_type(idx),idx);
-							undo_redo->add_undo_method(animation.ptr(),"track_set_path",idx,animation->track_get_path(idx));
-							//todo interpolation
-							for(int i=0;i<animation->track_get_key_count(idx);i++) {
+					SelectedKey sk;
+					sk.track = idx;
+					sk.key = key;
+					KeyInfo ki;
+					ki.pos = animation->track_get_key_time(idx, key);
+					click.shift = mb->get_shift();
+					click.selk = sk;
 
-								Variant v = animation->track_get_key_value(idx,i);
-								float time =  animation->track_get_key_time(idx,i);
-								float trans =  animation->track_get_key_transition(idx,i);
+					if (!mb->get_shift() && !selection.has(sk))
+						_clear_selection();
 
-								undo_redo->add_undo_method(animation.ptr(),"track_insert_key",idx,time,v);
-								undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",idx,i,trans);
+					selection.insert(sk, ki);
 
-							}
+					click.click = ClickOver::CLICK_MOVE_KEYS;
+					click.at = mb->get_pos();
+					click.to = click.at;
+					update();
+					selected_track = idx;
+					track_editor->update();
 
-							undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",idx,animation->track_get_interpolation_type(idx));
-							if (animation->track_get_type(idx)==Animation::TYPE_VALUE) {
-								undo_redo->add_undo_method(animation.ptr(),"value_track_set_continuous",idx,animation->value_track_is_continuous(idx));
+					if (_edit_if_single_selection() && mb->get_command()) {
+						edit_button->set_pressed(true);
+						key_editor_tab->show();
+					}
+				} else {
+					//button column
+					int ofsx = size.width - mpos.x;
+					if (ofsx < 0)
+						return;
+					/*
+					if (ofsx < remove_icon->get_width()) {
 
-							}
+						undo_redo->create_action("Remove Anim Track");
+						undo_redo->add_do_method(animation.ptr(),"remove_track",idx);
+						undo_redo->add_undo_method(animation.ptr(),"add_track",animation->track_get_type(idx),idx);
+						undo_redo->add_undo_method(animation.ptr(),"track_set_path",idx,animation->track_get_path(idx));
+						//todo interpolation
+						for(int i=0;i<animation->track_get_key_count(idx);i++) {
 
-							undo_redo->commit_action();
+							Variant v = animation->track_get_key_value(idx,i);
+							float time =  animation->track_get_key_time(idx,i);
+							float trans =  animation->track_get_key_transition(idx,i);
 
+							undo_redo->add_undo_method(animation.ptr(),"track_insert_key",idx,time,v);
+							undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",idx,i,trans);
 
-							return;
 						}
 
-						ofsx-=hsep+remove_icon->get_width();
-
-						if (ofsx < move_down_icon->get_width()) {
+						undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",idx,animation->track_get_interpolation_type(idx));
+						if (animation->track_get_type(idx)==Animation::TYPE_VALUE) {
+							undo_redo->add_undo_method(animation.ptr(),"value_track_set_continuous",idx,animation->value_track_is_continuous(idx));
 
-							if (idx < animation->get_track_count() -1) {
-								undo_redo->create_action("Move Anim Track Down");
-								undo_redo->add_do_method(animation.ptr(),"track_move_up",idx);
-								undo_redo->add_undo_method(animation.ptr(),"track_move_down",idx+1);
-								undo_redo->commit_action();
-							}
-							return;
 						}
 
-						ofsx-=hsep+move_down_icon->get_width();
+						undo_redo->commit_action();
 
-						if (ofsx < move_up_icon->get_width()) {
 
-							if (idx >0) {
-								undo_redo->create_action("Move Anim Track Up");
-								undo_redo->add_do_method(animation.ptr(),"track_move_down",idx);
-								undo_redo->add_undo_method(animation.ptr(),"track_move_up",idx-1);
-								undo_redo->commit_action();
-							}
-							return;
-						}
+						return;
+					}
 
+					ofsx-=hsep+remove_icon->get_width();
 
-						ofsx-=hsep*3+move_up_icon->get_width();
-						*/
+					if (ofsx < move_down_icon->get_width()) {
 
-						if (ofsx < track_ofs[1]) {
+						if (idx < animation->get_track_count() -1) {
+							undo_redo->create_action("Move Anim Track Down");
+							undo_redo->add_do_method(animation.ptr(),"track_move_up",idx);
+							undo_redo->add_undo_method(animation.ptr(),"track_move_down",idx+1);
+							undo_redo->commit_action();
+						}
+						return;
+					}
 
-							track_menu->clear();
-							track_menu->set_size(Point2(1, 1));
-							static const char *interp_name[2] = { "Clamp Loop Interp", "Wrap Loop Interp" };
-							for (int i = 0; i < 2; i++) {
-								track_menu->add_icon_item(wrap_icon[i], interp_name[i]);
-							}
+					ofsx-=hsep+move_down_icon->get_width();
 
-							int popup_y = ofs.y + ((int(mpos.y) / h) + 2) * h;
-							int popup_x = size.width - track_ofs[1];
+					if (ofsx < move_up_icon->get_width()) {
 
-							track_menu->set_position(te->get_global_position() + Point2(popup_x, popup_y));
+						if (idx >0) {
+							undo_redo->create_action("Move Anim Track Up");
+							undo_redo->add_do_method(animation.ptr(),"track_move_down",idx);
+							undo_redo->add_undo_method(animation.ptr(),"track_move_up",idx-1);
+							undo_redo->commit_action();
+						}
+						return;
+					}
 
-							wrap_editing = idx;
-							interp_editing = -1;
-							cont_editing = -1;
 
-							track_menu->popup();
+					ofsx-=hsep*3+move_up_icon->get_width();
+					*/
 
-							return;
+					if (ofsx < track_ofs[1]) {
+
+						track_menu->clear();
+						track_menu->set_size(Point2(1, 1));
+						static const char *interp_name[2] = { "Clamp Loop Interp", "Wrap Loop Interp" };
+						for (int i = 0; i < 2; i++) {
+							track_menu->add_icon_item(wrap_icon[i], interp_name[i]);
 						}
 
-						if (ofsx < track_ofs[2]) {
+						int popup_y = ofs.y + ((int(mpos.y) / h) + 2) * h;
+						int popup_x = size.width - track_ofs[1];
 
-							track_menu->clear();
-							track_menu->set_size(Point2(1, 1));
-							static const char *interp_name[3] = { "Nearest", "Linear", "Cubic" };
-							for (int i = 0; i < 3; i++) {
-								track_menu->add_icon_item(interp_icon[i], interp_name[i]);
-							}
+						track_menu->set_position(te->get_global_position() + Point2(popup_x, popup_y));
 
-							int popup_y = ofs.y + ((int(mpos.y) / h) + 2) * h;
-							int popup_x = size.width - track_ofs[2];
+						wrap_editing = idx;
+						interp_editing = -1;
+						cont_editing = -1;
 
-							track_menu->set_position(te->get_global_position() + Point2(popup_x, popup_y));
+						track_menu->popup();
 
-							interp_editing = idx;
-							cont_editing = -1;
-							wrap_editing = -1;
+						return;
+					}
 
-							track_menu->popup();
+					if (ofsx < track_ofs[2]) {
 
-							return;
+						track_menu->clear();
+						track_menu->set_size(Point2(1, 1));
+						static const char *interp_name[3] = { "Nearest", "Linear", "Cubic" };
+						for (int i = 0; i < 3; i++) {
+							track_menu->add_icon_item(interp_icon[i], interp_name[i]);
 						}
 
-						if (ofsx < track_ofs[3]) {
+						int popup_y = ofs.y + ((int(mpos.y) / h) + 2) * h;
+						int popup_x = size.width - track_ofs[2];
 
-							track_menu->clear();
-							track_menu->set_size(Point2(1, 1));
-							String cont_name[3] = { TTR("Continuous"), TTR("Discrete"), TTR("Trigger") };
-							for (int i = 0; i < 3; i++) {
-								track_menu->add_icon_item(cont_icon[i], cont_name[i]);
-							}
+						track_menu->set_position(te->get_global_position() + Point2(popup_x, popup_y));
 
-							int popup_y = ofs.y + ((int(mpos.y) / h) + 2) * h;
-							int popup_x = size.width - track_ofs[3];
+						interp_editing = idx;
+						cont_editing = -1;
+						wrap_editing = -1;
 
-							track_menu->set_position(te->get_global_position() + Point2(popup_x, popup_y));
+						track_menu->popup();
 
-							interp_editing = -1;
-							wrap_editing = -1;
-							cont_editing = idx;
+						return;
+					}
 
-							track_menu->popup();
+					if (ofsx < track_ofs[3]) {
 
-							return;
+						track_menu->clear();
+						track_menu->set_size(Point2(1, 1));
+						String cont_name[3] = { TTR("Continuous"), TTR("Discrete"), TTR("Trigger") };
+						for (int i = 0; i < 3; i++) {
+							track_menu->add_icon_item(cont_icon[i], cont_name[i]);
 						}
 
-						if (ofsx < track_ofs[4]) {
+						int popup_y = ofs.y + ((int(mpos.y) / h) + 2) * h;
+						int popup_x = size.width - track_ofs[3];
 
-							Animation::TrackType tt = animation->track_get_type(idx);
+						track_menu->set_position(te->get_global_position() + Point2(popup_x, popup_y));
 
-							float pos = timeline_pos;
-							int existing = animation->track_find_key(idx, pos, true);
+						interp_editing = -1;
+						wrap_editing = -1;
+						cont_editing = idx;
 
-							Variant newval;
+						track_menu->popup();
 
-							if (tt == Animation::TYPE_TRANSFORM) {
-								Dictionary d;
-								d["loc"] = Vector3();
-								d["rot"] = Quat();
-								d["scale"] = Vector3();
-								newval = d;
+						return;
+					}
 
-							} else if (tt == Animation::TYPE_METHOD) {
+					if (ofsx < track_ofs[4]) {
 
-								Dictionary d;
-								d["method"] = "";
-								d["args"] = Vector<Variant>();
+						Animation::TrackType tt = animation->track_get_type(idx);
 
-								newval = d;
-							} else if (tt == Animation::TYPE_VALUE) {
+						float pos = timeline_pos;
+						int existing = animation->track_find_key(idx, pos, true);
 
-								NodePath np;
-								PropertyInfo inf = _find_hint_for_track(idx, np);
-								if (inf.type != Variant::NIL) {
+						Variant newval;
 
-									Variant::CallError err;
-									newval = Variant::construct(inf.type, NULL, 0, err);
-								}
+						if (tt == Animation::TYPE_TRANSFORM) {
+							Dictionary d;
+							d["loc"] = Vector3();
+							d["rot"] = Quat();
+							d["scale"] = Vector3();
+							newval = d;
 
-								if (newval.get_type() == Variant::NIL) {
-									//popup a new type
-									cvi_track = idx;
-									cvi_pos = pos;
+						} else if (tt == Animation::TYPE_METHOD) {
 
-									type_menu->set_position(get_global_position() + mpos + ofs);
-									type_menu->popup();
-									return;
-								}
-							}
+							Dictionary d;
+							d["method"] = "";
+							d["args"] = Vector<Variant>();
 
-							undo_redo->create_action(TTR("Anim Add Key"));
+							newval = d;
+						} else if (tt == Animation::TYPE_VALUE) {
 
-							undo_redo->add_do_method(animation.ptr(), "track_insert_key", idx, pos, newval, 1);
-							undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_pos", idx, pos);
+							NodePath np;
+							PropertyInfo inf = _find_hint_for_track(idx, np);
+							if (inf.type != Variant::NIL) {
 
-							if (existing != -1) {
-								Variant v = animation->track_get_key_value(idx, existing);
-								float trans = animation->track_get_key_transition(idx, existing);
-								undo_redo->add_undo_method(animation.ptr(), "track_insert_key", idx, pos, v, trans);
+								Variant::CallError err;
+								newval = Variant::construct(inf.type, NULL, 0, err);
 							}
 
-							undo_redo->commit_action();
+							if (newval.get_type() == Variant::NIL) {
+								//popup a new type
+								cvi_track = idx;
+								cvi_pos = pos;
 
-							return;
+								type_menu->set_position(get_global_position() + mpos + ofs);
+								type_menu->popup();
+								return;
+							}
 						}
-					}
 
-				} else {
+						undo_redo->create_action(TTR("Anim Add Key"));
 
-					switch (click.click) {
-						case ClickOver::CLICK_SELECT_KEYS: {
+						undo_redo->add_do_method(animation.ptr(), "track_insert_key", idx, pos, newval, 1);
+						undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_pos", idx, pos);
 
-							float zoom_scale = _get_zoom_scale();
-							float keys_from = h_scroll->get_value();
-							float keys_to = keys_from + (settings_limit - name_limit) / zoom_scale;
+						if (existing != -1) {
+							Variant v = animation->track_get_key_value(idx, existing);
+							float trans = animation->track_get_key_transition(idx, existing);
+							undo_redo->add_undo_method(animation.ptr(), "track_insert_key", idx, pos, v, trans);
+						}
 
-							float from_time = keys_from + (click.at.x - (name_limit + ofs.x)) / zoom_scale;
-							float to_time = keys_from + (click.to.x - (name_limit + ofs.x)) / zoom_scale;
+						undo_redo->commit_action();
 
-							if (to_time < from_time)
-								SWAP(from_time, to_time);
+						return;
+					}
+				}
 
-							if (from_time > keys_to || to_time < keys_from)
-								break;
+			} else {
 
-							if (from_time < keys_from)
-								from_time = keys_from;
+				switch (click.click) {
+					case ClickOver::CLICK_SELECT_KEYS: {
 
-							if (to_time >= keys_to)
-								to_time = keys_to;
+						float zoom_scale = _get_zoom_scale();
+						float keys_from = h_scroll->get_value();
+						float keys_to = keys_from + (settings_limit - name_limit) / zoom_scale;
 
-							int from_track = int(click.at.y - ofs.y - h - sep) / h + v_scroll->get_value();
-							int to_track = int(click.to.y - ofs.y - h - sep) / h + v_scroll->get_value();
-							int from_mod = int(click.at.y - ofs.y - sep) % h;
-							int to_mod = int(click.to.y - ofs.y - sep) % h;
+						float from_time = keys_from + (click.at.x - (name_limit + ofs.x)) / zoom_scale;
+						float to_time = keys_from + (click.to.x - (name_limit + ofs.x)) / zoom_scale;
 
-							if (to_track < from_track) {
+						if (to_time < from_time)
+							SWAP(from_time, to_time);
 
-								SWAP(from_track, to_track);
-								SWAP(from_mod, to_mod);
-							}
+						if (from_time > keys_to || to_time < keys_from)
+							break;
 
-							if ((from_mod > (h / 2)) && ((click.at.y - ofs.y) >= (h + sep))) {
-								from_track++;
-							}
+						if (from_time < keys_from)
+							from_time = keys_from;
 
-							if (to_mod < h / 2) {
-								to_track--;
-							}
+						if (to_time >= keys_to)
+							to_time = keys_to;
 
-							if (from_track > to_track) {
-								if (!click.shift)
-									_clear_selection();
-								_edit_if_single_selection();
-								break;
-							}
+						int from_track = int(click.at.y - ofs.y - h - sep) / h + v_scroll->get_value();
+						int to_track = int(click.to.y - ofs.y - h - sep) / h + v_scroll->get_value();
+						int from_mod = int(click.at.y - ofs.y - sep) % h;
+						int to_mod = int(click.to.y - ofs.y - sep) % h;
+
+						if (to_track < from_track) {
 
-							int tracks_from = v_scroll->get_value();
-							int tracks_to = v_scroll->get_value() + fit - 1;
-							if (tracks_to >= animation->get_track_count())
-								tracks_to = animation->get_track_count() - 1;
+							SWAP(from_track, to_track);
+							SWAP(from_mod, to_mod);
+						}
+
+						if ((from_mod > (h / 2)) && ((click.at.y - ofs.y) >= (h + sep))) {
+							from_track++;
+						}
 
-							tracks_from = 0;
+						if (to_mod < h / 2) {
+							to_track--;
+						}
+
+						if (from_track > to_track) {
+							if (!click.shift)
+								_clear_selection();
+							_edit_if_single_selection();
+							break;
+						}
+
+						int tracks_from = v_scroll->get_value();
+						int tracks_to = v_scroll->get_value() + fit - 1;
+						if (tracks_to >= animation->get_track_count())
 							tracks_to = animation->get_track_count() - 1;
-							if (to_track > tracks_to)
-								to_track = tracks_to;
-							if (from_track < tracks_from)
-								from_track = tracks_from;
-
-							if (from_track > tracks_to || to_track < tracks_from) {
-								if (!click.shift)
-									_clear_selection();
-								_edit_if_single_selection();
-								break;
-							}
 
+						tracks_from = 0;
+						tracks_to = animation->get_track_count() - 1;
+						if (to_track > tracks_to)
+							to_track = tracks_to;
+						if (from_track < tracks_from)
+							from_track = tracks_from;
+
+						if (from_track > tracks_to || to_track < tracks_from) {
 							if (!click.shift)
 								_clear_selection();
+							_edit_if_single_selection();
+							break;
+						}
 
-							int higher_track = 0x7FFFFFFF;
-							for (int i = from_track; i <= to_track; i++) {
+						if (!click.shift)
+							_clear_selection();
 
-								int kc = animation->track_get_key_count(i);
-								for (int j = 0; j < kc; j++) {
+						int higher_track = 0x7FFFFFFF;
+						for (int i = from_track; i <= to_track; i++) {
 
-									float t = animation->track_get_key_time(i, j);
-									if (t < from_time)
-										continue;
-									if (t > to_time)
-										break;
+							int kc = animation->track_get_key_count(i);
+							for (int j = 0; j < kc; j++) {
 
-									if (i < higher_track)
-										higher_track = i;
+								float t = animation->track_get_key_time(i, j);
+								if (t < from_time)
+									continue;
+								if (t > to_time)
+									break;
 
-									SelectedKey sk;
-									sk.track = i;
-									sk.key = j;
-									KeyInfo ki;
-									ki.pos = t;
-									selection[sk] = ki;
-								}
-							}
+								if (i < higher_track)
+									higher_track = i;
 
-							if (higher_track != 0x7FFFFFFF) {
-								selected_track = higher_track;
-								track_editor->update();
+								SelectedKey sk;
+								sk.track = i;
+								sk.key = j;
+								KeyInfo ki;
+								ki.pos = t;
+								selection[sk] = ki;
 							}
+						}
 
-							_edit_if_single_selection();
+						if (higher_track != 0x7FFFFFFF) {
+							selected_track = higher_track;
+							track_editor->update();
+						}
 
-						} break;
-						case ClickOver::CLICK_MOVE_KEYS: {
+						_edit_if_single_selection();
 
-							if (selection.empty())
-								break;
-							if (click.at == click.to) {
+					} break;
+					case ClickOver::CLICK_MOVE_KEYS: {
 
-								if (!click.shift) {
+						if (selection.empty())
+							break;
+						if (click.at == click.to) {
 
-									KeyInfo ki = selection[click.selk];
-									_clear_selection();
-									selection[click.selk] = ki;
-									_edit_if_single_selection();
-								}
+							if (!click.shift) {
 
-								break;
+								KeyInfo ki = selection[click.selk];
+								_clear_selection();
+								selection[click.selk] = ki;
+								_edit_if_single_selection();
 							}
 
-							float from_t = 1e20;
+							break;
+						}
 
-							for (Map<SelectedKey, KeyInfo>::Element *E = selection.front(); E; E = E->next()) {
-								float t = animation->track_get_key_time(E->key().track, E->key().key);
-								if (t < from_t)
-									from_t = t;
-							}
+						float from_t = 1e20;
 
-							float motion = from_t + (click.to.x - click.at.x) / _get_zoom_scale();
-							if (step->get_value())
-								motion = Math::stepify(motion, step->get_value());
+						for (Map<SelectedKey, KeyInfo>::Element *E = selection.front(); E; E = E->next()) {
+							float t = animation->track_get_key_time(E->key().track, E->key().key);
+							if (t < from_t)
+								from_t = t;
+						}
 
-							undo_redo->create_action(TTR("Anim Move Keys"));
+						float motion = from_t + (click.to.x - click.at.x) / _get_zoom_scale();
+						if (step->get_value())
+							motion = Math::stepify(motion, step->get_value());
 
-							List<_AnimMoveRestore> to_restore;
+						undo_redo->create_action(TTR("Anim Move Keys"));
 
-							// 1-remove the keys
-							for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
+						List<_AnimMoveRestore> to_restore;
 
-								undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key);
-							}
-							// 2- remove overlapped keys
-							for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
+						// 1-remove the keys
+						for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
 
-								float newtime = E->get().pos - from_t + motion;
-								int idx = animation->track_find_key(E->key().track, newtime, true);
-								if (idx == -1)
-									continue;
-								SelectedKey sk;
-								sk.key = idx;
-								sk.track = E->key().track;
-								if (selection.has(sk))
-									continue; //already in selection, don't save
+							undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key);
+						}
+						// 2- remove overlapped keys
+						for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
+
+							float newtime = E->get().pos - from_t + motion;
+							int idx = animation->track_find_key(E->key().track, newtime, true);
+							if (idx == -1)
+								continue;
+							SelectedKey sk;
+							sk.key = idx;
+							sk.track = E->key().track;
+							if (selection.has(sk))
+								continue; //already in selection, don't save
+
+							undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_pos", E->key().track, newtime);
+							_AnimMoveRestore amr;
+
+							amr.key = animation->track_get_key_value(E->key().track, idx);
+							amr.track = E->key().track;
+							amr.time = newtime;
+							amr.transition = animation->track_get_key_transition(E->key().track, idx);
+
+							to_restore.push_back(amr);
+						}
 
-								undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_pos", E->key().track, newtime);
-								_AnimMoveRestore amr;
+						// 3-move the keys (re insert them)
+						for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
 
-								amr.key = animation->track_get_key_value(E->key().track, idx);
-								amr.track = E->key().track;
-								amr.time = newtime;
-								amr.transition = animation->track_get_key_transition(E->key().track, idx);
+							float newpos = E->get().pos - from_t + motion;
+							/*
+							if (newpos<0)
+								continue; //no add at the beginning
+							*/
+							undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
+						}
 
-								to_restore.push_back(amr);
-							}
+						// 4-(undo) remove inserted keys
+						for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
 
-							// 3-move the keys (re insert them)
-							for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
+							float newpos = E->get().pos + -from_t + motion;
+							/*
+							if (newpos<0)
+								continue; //no remove what no inserted
+							*/
+							undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_pos", E->key().track, newpos);
+						}
 
-								float newpos = E->get().pos - from_t + motion;
-								/*
-								if (newpos<0)
-									continue; //no add at the beginning
-								*/
-								undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
-							}
+						// 5-(undo) reinsert keys
+						for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
 
-							// 4-(undo) remove inserted keys
-							for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
+							undo_redo->add_undo_method(animation.ptr(), "track_insert_key", E->key().track, E->get().pos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
+						}
 
-								float newpos = E->get().pos + -from_t + motion;
-								/*
-								if (newpos<0)
-									continue; //no remove what no inserted
-								*/
-								undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_pos", E->key().track, newpos);
-							}
+						// 6-(undo) reinsert overlapped keys
+						for (List<_AnimMoveRestore>::Element *E = to_restore.front(); E; E = E->next()) {
 
-							// 5-(undo) reinsert keys
-							for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
+							_AnimMoveRestore &amr = E->get();
+							undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, amr.transition);
+						}
 
-								undo_redo->add_undo_method(animation.ptr(), "track_insert_key", E->key().track, E->get().pos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
-							}
+						// 6-(undo) reinsert overlapped keys
+						for (List<_AnimMoveRestore>::Element *E = to_restore.front(); E; E = E->next()) {
 
-							// 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, amr.transition);
+						}
 
-								_AnimMoveRestore &amr = E->get();
-								undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, amr.transition);
-							}
+						undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
+						undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
 
-							// 6-(undo) reinsert overlapped keys
-							for (List<_AnimMoveRestore>::Element *E = to_restore.front(); E; E = E->next()) {
+						// 7-reselect
 
-								_AnimMoveRestore &amr = E->get();
-								undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, amr.transition);
-							}
+						for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
 
-							undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
-							undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
+							float oldpos = E->get().pos;
+							float newpos = oldpos - from_t + motion;
+							//if (newpos>=0)
+							undo_redo->add_do_method(this, "_select_at_anim", animation, E->key().track, newpos);
+							undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, oldpos);
+						}
 
-							// 7-reselect
+						undo_redo->commit_action();
+						_edit_if_single_selection();
 
-							for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
+					} break;
+					default: {}
+				}
 
-								float oldpos = E->get().pos;
-								float newpos = oldpos - from_t + motion;
-								//if (newpos>=0)
-								undo_redo->add_do_method(this, "_select_at_anim", animation, E->key().track, newpos);
-								undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, oldpos);
-							}
+				//button released
+				click.click = ClickOver::CLICK_NONE;
+				track_editor->update();
+			}
+		}
+	}
 
-							undo_redo->commit_action();
-							_edit_if_single_selection();
+	Ref<InputEventMouseMotion> mm = p_input;
 
-						} break;
-						default: {}
-					}
+	if (mm.is_valid()) {
 
-					//button released
-					click.click = ClickOver::CLICK_NONE;
-					track_editor->update();
-				}
-			}
+		mouse_over.over = MouseOver::OVER_NONE;
+		mouse_over.track = -1;
+		te->update();
+		track_editor->set_tooltip("");
 
-		} break;
+		if (!track_editor->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
+			track_editor->call_deferred("grab_focus");
 
-		case InputEvent::MOUSE_MOTION: {
+		if (click.click != ClickOver::CLICK_NONE) {
 
-			const InputEventMouseMotion &mb = p_input.mouse_motion;
+			switch (click.click) {
+				case ClickOver::CLICK_RESIZE_NAMES: {
 
-			mouse_over.over = MouseOver::OVER_NONE;
-			mouse_over.track = -1;
-			te->update();
-			track_editor->set_tooltip("");
+					float base = click.at.y;
+					float clickp = click.at.x - ofs.x;
+					float dif = base - clickp;
 
-			if (!track_editor->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
-				track_editor->call_deferred("grab_focus");
+					float target = mb->get_pos().x + dif - ofs.x;
 
-			if (click.click != ClickOver::CLICK_NONE) {
+					float ratio = target / settings_limit;
 
-				switch (click.click) {
-					case ClickOver::CLICK_RESIZE_NAMES: {
+					if (ratio > 0.9)
+						ratio = 0.9;
+					else if (ratio < 0.2)
+						ratio = 0.2;
 
-						float base = click.at.y;
-						float clickp = click.at.x - ofs.x;
-						float dif = base - clickp;
+					name_column_ratio = ratio;
 
-						float target = mb.x + dif - ofs.x;
+				} break;
+				case ClickOver::CLICK_DRAG_TIMELINE: {
 
-						float ratio = target / settings_limit;
+					Point2 mpos = mb->get_pos() - ofs;
+					/*
+					if (mpos.x<name_limit)
+						mpos.x=name_limit;
+					if (mpos.x>settings_limit)
+						mpos.x=settings_limit;
+						*/
 
-						if (ratio > 0.9)
-							ratio = 0.9;
-						else if (ratio < 0.2)
-							ratio = 0.2;
+					//int zoomw = settings_limit-name_limit;
+					float scale = _get_zoom_scale();
+					float pos = h_scroll->get_value() + (mpos.x - name_limit) / scale;
+					if (animation->get_step()) {
+						pos = Math::stepify(pos, animation->get_step());
+					}
+					if (pos < 0)
+						pos = 0;
+					if (pos >= animation->get_length())
+						pos = animation->get_length();
+
+					if (pos < h_scroll->get_value()) {
+						h_scroll->set_value(pos);
+					} else if (pos > h_scroll->get_value() + (settings_limit - name_limit) / scale) {
+						h_scroll->set_value(pos - (settings_limit - name_limit) / scale);
+					}
 
-						name_column_ratio = ratio;
+					timeline_pos = pos;
+					emit_signal("timeline_changed", pos, true);
 
-					} break;
-					case ClickOver::CLICK_DRAG_TIMELINE: {
-
-						Point2 mpos = Point2(mb.x, mb.y) - ofs;
-						/*
-						if (mpos.x<name_limit)
-							mpos.x=name_limit;
-						if (mpos.x>settings_limit)
-							mpos.x=settings_limit;
-							*/
+				} break;
+				case ClickOver::CLICK_SELECT_KEYS: {
 
-						//int zoomw = settings_limit-name_limit;
-						float scale = _get_zoom_scale();
-						float pos = h_scroll->get_value() + (mpos.x - name_limit) / scale;
-						if (animation->get_step()) {
-							pos = Math::stepify(pos, animation->get_step());
-						}
-						if (pos < 0)
-							pos = 0;
-						if (pos >= animation->get_length())
-							pos = animation->get_length();
+					click.to = mb->get_pos();
+					if (click.to.y < h && click.at.y > h && mm->get_relative().y < 0) {
 
-						if (pos < h_scroll->get_value()) {
-							h_scroll->set_value(pos);
-						} else if (pos > h_scroll->get_value() + (settings_limit - name_limit) / scale) {
-							h_scroll->set_value(pos - (settings_limit - name_limit) / scale);
-						}
+						float prev = v_scroll->get_value();
+						v_scroll->set_value(v_scroll->get_value() - 1);
+						if (prev != v_scroll->get_value())
+							click.at.y += h;
+					}
+					if (click.to.y > size.height && click.at.y < size.height && mm->get_relative().y > 0) {
 
-						timeline_pos = pos;
-						emit_signal("timeline_changed", pos, true);
+						float prev = v_scroll->get_value();
+						v_scroll->set_value(v_scroll->get_value() + 1);
+						if (prev != v_scroll->get_value())
+							click.at.y -= h;
+					}
 
-					} break;
-					case ClickOver::CLICK_SELECT_KEYS: {
+				} break;
+				case ClickOver::CLICK_MOVE_KEYS: {
 
-						click.to = Point2(mb.x, mb.y);
-						if (click.to.y < h && click.at.y > h && mb.relative_y < 0) {
+					click.to = mb->get_pos();
+				} break;
+				default: {}
+			}
 
-							float prev = v_scroll->get_value();
-							v_scroll->set_value(v_scroll->get_value() - 1);
-							if (prev != v_scroll->get_value())
-								click.at.y += h;
-						}
-						if (click.to.y > size.height && click.at.y < size.height && mb.relative_y > 0) {
+			return;
+		} else if (mb->get_button_mask() & BUTTON_MASK_MIDDLE) {
 
-							float prev = v_scroll->get_value();
-							v_scroll->set_value(v_scroll->get_value() + 1);
-							if (prev != v_scroll->get_value())
-								click.at.y -= h;
-						}
+			int rel = mm->get_relative().x;
+			float relf = rel / _get_zoom_scale();
+			h_scroll->set_value(h_scroll->get_value() - relf);
+		}
 
-					} break;
-					case ClickOver::CLICK_MOVE_KEYS: {
+		if (mb->get_button_mask() == 0) {
 
-						click.to = Point2(mb.x, mb.y);
-					} break;
-					default: {}
-				}
+			Point2 mpos = mb->get_pos() - ofs;
 
+			if (mpos.y < h) {
+#if 0
+				//seek
+				//int zoomw = settings_limit-name_limit;
+				float scale = _get_zoom_scale();
+				float pos = h_scroll->get_val() + (mpos.y-name_limit) / scale;
+				if (pos<0 )
+					pos=0;
+				if (pos>=animation->get_length())
+					pos=animation->get_length();
+				timeline->set_val(pos);
+#endif
 				return;
-			} else if (mb.button_mask & BUTTON_MASK_MIDDLE) {
-
-				int rel = mb.relative_x;
-				float relf = rel / _get_zoom_scale();
-				h_scroll->set_value(h_scroll->get_value() - relf);
 			}
 
-			if (mb.button_mask == 0) {
+			mpos.y -= h;
 
-				Point2 mpos = Point2(mb.x, mb.y) - ofs;
+			int idx = mpos.y / h;
+			idx += v_scroll->get_value();
+			if (idx < 0 || idx >= animation->get_track_count())
+				return;
 
-				if (mpos.y < h) {
-#if 0
-					//seek
-					//int zoomw = settings_limit-name_limit;
-					float scale = _get_zoom_scale();
-					float pos = h_scroll->get_val() + (mpos.y-name_limit) / scale;
-					if (pos<0 )
-						pos=0;
-					if (pos>=animation->get_length())
-						pos=animation->get_length();
-					timeline->set_val(pos);
-#endif
-					return;
-				}
+			mouse_over.track = idx;
 
-				mpos.y -= h;
+			if (mpos.x < name_limit) {
+				//name column
 
-				int idx = mpos.y / h;
-				idx += v_scroll->get_value();
-				if (idx < 0 || idx >= animation->get_track_count())
-					break;
+				mouse_over.over = MouseOver::OVER_NAME;
 
-				mouse_over.track = idx;
+			} else if (mpos.x < settings_limit) {
 
-				if (mpos.x < name_limit) {
-					//name column
+				float pos = mpos.x - name_limit;
+				pos /= _get_zoom_scale();
+				pos += h_scroll->get_value();
+				float w_time = (type_icon[0]->get_width() / _get_zoom_scale()) / 2.0;
 
-					mouse_over.over = MouseOver::OVER_NAME;
+				int kidx = animation->track_find_key(idx, pos);
+				int kidx_n = kidx + 1;
 
-				} else if (mpos.x < settings_limit) {
+				bool found = false;
 
-					float pos = mpos.x - name_limit;
-					pos /= _get_zoom_scale();
-					pos += h_scroll->get_value();
-					float w_time = (type_icon[0]->get_width() / _get_zoom_scale()) / 2.0;
+				if (kidx >= 0 && kidx < animation->track_get_key_count(idx)) {
 
-					int kidx = animation->track_find_key(idx, pos);
-					int kidx_n = kidx + 1;
+					float kpos = animation->track_get_key_time(idx, kidx);
+					if (ABS(pos - kpos) <= w_time) {
 
-					bool found = false;
+						mouse_over.over = MouseOver::OVER_KEY;
+						mouse_over.track = idx;
+						mouse_over.over_key = kidx;
+						found = true;
+					}
+				}
 
-					if (kidx >= 0 && kidx < animation->track_get_key_count(idx)) {
+				if (!found && kidx_n >= 0 && kidx_n < animation->track_get_key_count(idx)) {
 
-						float kpos = animation->track_get_key_time(idx, kidx);
-						if (ABS(pos - kpos) <= w_time) {
+					float kpos = animation->track_get_key_time(idx, kidx_n);
+					if (ABS(pos - kpos) <= w_time) {
 
-							mouse_over.over = MouseOver::OVER_KEY;
-							mouse_over.track = idx;
-							mouse_over.over_key = kidx;
-							found = true;
-						}
+						mouse_over.over = MouseOver::OVER_KEY;
+						mouse_over.track = idx;
+						mouse_over.over_key = kidx_n;
+						found = true;
 					}
+				}
 
-					if (!found && kidx_n >= 0 && kidx_n < animation->track_get_key_count(idx)) {
+				if (found) {
 
-						float kpos = animation->track_get_key_time(idx, kidx_n);
-						if (ABS(pos - kpos) <= w_time) {
+					String text;
+					text = "time: " + rtos(animation->track_get_key_time(idx, mouse_over.over_key)) + "\n";
 
-							mouse_over.over = MouseOver::OVER_KEY;
-							mouse_over.track = idx;
-							mouse_over.over_key = kidx_n;
-							found = true;
-						}
-					}
+					switch (animation->track_get_type(idx)) {
 
-					if (found) {
-
-						String text;
-						text = "time: " + rtos(animation->track_get_key_time(idx, mouse_over.over_key)) + "\n";
-
-						switch (animation->track_get_type(idx)) {
-
-							case Animation::TYPE_TRANSFORM: {
-
-								Dictionary d = animation->track_get_key_value(idx, mouse_over.over_key);
-								if (d.has("loc"))
-									text += "loc: " + String(d["loc"]) + "\n";
-								if (d.has("rot"))
-									text += "rot: " + String(d["rot"]) + "\n";
-								if (d.has("scale"))
-									text += "scale: " + String(d["scale"]) + "\n";
-							} break;
-							case Animation::TYPE_VALUE: {
-
-								Variant v = animation->track_get_key_value(idx, mouse_over.over_key);
-								//text+="value: "+String(v)+"\n";
-
-								bool prop_exists = false;
-								Variant::Type valid_type = Variant::NIL;
-								Object *obj = NULL;
-
-								RES res;
-								Node *node = root->get_node_and_resource(animation->track_get_path(idx), res);
-
-								if (res.is_valid()) {
-									obj = res.ptr();
-								} else if (node) {
-									obj = node;
-								}
-
-								if (obj) {
-									valid_type = obj->get_static_property_type(animation->track_get_path(idx).get_property(), &prop_exists);
-								}
-
-								text += "type: " + Variant::get_type_name(v.get_type()) + "\n";
-								if (prop_exists && !Variant::can_convert(v.get_type(), valid_type)) {
-									text += "value: " + String(v) + "  (Invalid, expected type: " + Variant::get_type_name(valid_type) + ")\n";
-								} else {
-									text += "value: " + String(v) + "\n";
-								}
-
-							} break;
-							case Animation::TYPE_METHOD: {
-
-								Dictionary d = animation->track_get_key_value(idx, mouse_over.over_key);
-								if (d.has("method"))
-									text += String(d["method"]);
-								text += "(";
-								Vector<Variant> args;
-								if (d.has("args"))
-									args = d["args"];
-								for (int i = 0; i < args.size(); i++) {
-
-									if (i > 0)
-										text += ", ";
-									text += String(args[i]);
-								}
-								text += ")\n";
-
-							} break;
-						}
-						text += "easing: " + rtos(animation->track_get_key_transition(idx, mouse_over.over_key));
+						case Animation::TYPE_TRANSFORM: {
 
-						track_editor->set_tooltip(text);
-						return;
-					}
+							Dictionary d = animation->track_get_key_value(idx, mouse_over.over_key);
+							if (d.has("loc"))
+								text += "loc: " + String(d["loc"]) + "\n";
+							if (d.has("rot"))
+								text += "rot: " + String(d["rot"]) + "\n";
+							if (d.has("scale"))
+								text += "scale: " + String(d["scale"]) + "\n";
+						} break;
+						case Animation::TYPE_VALUE: {
 
-				} else {
-					//button column
-					int ofsx = size.width - mpos.x;
-					if (ofsx < 0)
-						break;
-					/*
-					if (ofsx < remove_icon->get_width()) {
+							Variant v = animation->track_get_key_value(idx, mouse_over.over_key);
+							//text+="value: "+String(v)+"\n";
 
-						mouse_over.over=MouseOver::OVER_REMOVE;
+							bool prop_exists = false;
+							Variant::Type valid_type = Variant::NIL;
+							Object *obj = NULL;
 
-						return;
-					}
+							RES res;
+							Node *node = root->get_node_and_resource(animation->track_get_path(idx), res);
 
-					ofsx-=hsep+remove_icon->get_width();
+							if (res.is_valid()) {
+								obj = res.ptr();
+							} else if (node) {
+								obj = node;
+							}
 
-					if (ofsx < move_down_icon->get_width()) {
+							if (obj) {
+								valid_type = obj->get_static_property_type(animation->track_get_path(idx).get_property(), &prop_exists);
+							}
 
-						mouse_over.over=MouseOver::OVER_DOWN;
-						return;
+							text += "type: " + Variant::get_type_name(v.get_type()) + "\n";
+							if (prop_exists && !Variant::can_convert(v.get_type(), valid_type)) {
+								text += "value: " + String(v) + "  (Invalid, expected type: " + Variant::get_type_name(valid_type) + ")\n";
+							} else {
+								text += "value: " + String(v) + "\n";
+							}
+
+						} break;
+						case Animation::TYPE_METHOD: {
+
+							Dictionary d = animation->track_get_key_value(idx, mouse_over.over_key);
+							if (d.has("method"))
+								text += String(d["method"]);
+							text += "(";
+							Vector<Variant> args;
+							if (d.has("args"))
+								args = d["args"];
+							for (int i = 0; i < args.size(); i++) {
+
+								if (i > 0)
+									text += ", ";
+								text += String(args[i]);
+							}
+							text += ")\n";
+
+						} break;
 					}
+					text += "easing: " + rtos(animation->track_get_key_transition(idx, mouse_over.over_key));
 
-					ofsx-=hsep+move_down_icon->get_width();
+					track_editor->set_tooltip(text);
+					return;
+				}
 
-					if (ofsx < move_up_icon->get_width()) {
+			} else {
+				//button column
+				int ofsx = size.width - mpos.x;
+				if (ofsx < 0)
+					return;
+				/*
+				if (ofsx < remove_icon->get_width()) {
 
-						mouse_over.over=MouseOver::OVER_UP;
-						return;
-					}
+					mouse_over.over=MouseOver::OVER_REMOVE;
 
-					ofsx-=hsep*3+move_up_icon->get_width();
+					return;
+				}
 
-	*/
+				ofsx-=hsep+remove_icon->get_width();
 
-					if (ofsx < down_icon->get_width() + wrap_icon[0]->get_width() + hsep * 3) {
+				if (ofsx < move_down_icon->get_width()) {
 
-						mouse_over.over = MouseOver::OVER_WRAP;
-						return;
-					}
+					mouse_over.over=MouseOver::OVER_DOWN;
+					return;
+				}
 
-					ofsx -= hsep * 3 + wrap_icon[0]->get_width() + down_icon->get_width();
+				ofsx-=hsep+move_down_icon->get_width();
 
-					if (ofsx < down_icon->get_width() + interp_icon[0]->get_width() + hsep * 3) {
+				if (ofsx < move_up_icon->get_width()) {
 
-						mouse_over.over = MouseOver::OVER_INTERP;
-						return;
-					}
+					mouse_over.over=MouseOver::OVER_UP;
+					return;
+				}
 
-					ofsx -= hsep * 2 + interp_icon[0]->get_width() + down_icon->get_width();
+				ofsx-=hsep*3+move_up_icon->get_width();
 
-					if (ofsx < down_icon->get_width() + cont_icon[0]->get_width() + hsep * 3) {
+*/
 
-						mouse_over.over = MouseOver::OVER_VALUE;
-						return;
-					}
+				if (ofsx < down_icon->get_width() + wrap_icon[0]->get_width() + hsep * 3) {
 
-					ofsx -= hsep * 3 + cont_icon[0]->get_width() + down_icon->get_width();
+					mouse_over.over = MouseOver::OVER_WRAP;
+					return;
+				}
 
-					if (ofsx < add_key_icon->get_width()) {
+				ofsx -= hsep * 3 + wrap_icon[0]->get_width() + down_icon->get_width();
 
-						mouse_over.over = MouseOver::OVER_ADD_KEY;
-						return;
-					}
+				if (ofsx < down_icon->get_width() + interp_icon[0]->get_width() + hsep * 3) {
+
+					mouse_over.over = MouseOver::OVER_INTERP;
+					return;
 				}
-			}
 
-		} break;
+				ofsx -= hsep * 2 + interp_icon[0]->get_width() + down_icon->get_width();
+
+				if (ofsx < down_icon->get_width() + cont_icon[0]->get_width() + hsep * 3) {
+
+					mouse_over.over = MouseOver::OVER_VALUE;
+					return;
+				}
+
+				ofsx -= hsep * 3 + cont_icon[0]->get_width() + down_icon->get_width();
+
+				if (ofsx < add_key_icon->get_width()) {
+
+					mouse_over.over = MouseOver::OVER_ADD_KEY;
+					return;
+				}
+			}
+		}
 	}
 }
 

+ 1 - 1
editor/animation_editor.h

@@ -273,7 +273,7 @@ class AnimationKeyEditor : public VBoxContainer {
 	float _get_zoom_scale() const;
 
 	void _track_editor_draw();
-	void _track_editor_gui_input(const InputEvent &p_input);
+	void _track_editor_gui_input(const Ref<InputEvent> &p_input);
 	void _track_pos_draw();
 
 	void _track_name_changed(const String &p_name);

+ 17 - 14
editor/code_editor.cpp

@@ -94,17 +94,16 @@ void FindReplaceBar::_notification(int p_what) {
 	}
 }
 
-void FindReplaceBar::_unhandled_input(const InputEvent &p_event) {
+void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) {
 
-	if (p_event.type == InputEvent::KEY) {
+	Ref<InputEventKey> k = p_event;
+	if (k.is_valid()) {
 
-		const InputEventKey &k = p_event.key;
-
-		if (k.pressed && (text_edit->has_focus() || text_vbc->is_a_parent_of(get_focus_owner()))) {
+		if (k->is_pressed() && (text_edit->has_focus() || text_vbc->is_a_parent_of(get_focus_owner()))) {
 
 			bool accepted = true;
 
-			switch (k.scancode) {
+			switch (k->get_scancode()) {
 
 				case KEY_ESCAPE: {
 
@@ -957,23 +956,27 @@ FindReplaceDialog::FindReplaceDialog() {
 
 /*** CODE EDITOR ****/
 
-void CodeTextEditor::_text_editor_gui_input(const InputEvent &p_event) {
+void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
 
-	if (p_event.type == InputEvent::MOUSE_BUTTON) {
+	Ref<InputEventMouseButton> mb = p_event;
 
-		const InputEventMouseButton &mb = p_event.mouse_button;
+	if (mb.is_valid()) {
 
-		if (mb.pressed && mb.mod.command) {
+		if (mb->is_pressed() && mb->get_command()) {
 
-			if (mb.button_index == BUTTON_WHEEL_UP) {
+			if (mb->get_button_index() == BUTTON_WHEEL_UP) {
 				_zoom_in();
-			} else if (mb.button_index == BUTTON_WHEEL_DOWN) {
+			} else if (mb->get_button_index() == BUTTON_WHEEL_DOWN) {
 				_zoom_out();
 			}
 		}
-	} else if (p_event.type == InputEvent::KEY) {
+	}
+
+	Ref<InputEventKey> k = p_event;
+
+	if (k.is_valid()) {
 
-		if (p_event.key.pressed) {
+		if (k->is_pressed()) {
 			if (ED_IS_SHORTCUT("script_editor/zoom_in", p_event)) {
 				_zoom_in();
 			}

+ 2 - 2
editor/code_editor.h

@@ -100,7 +100,7 @@ class FindReplaceBar : public HBoxContainer {
 
 protected:
 	void _notification(int p_what);
-	void _unhandled_input(const InputEvent &p_event);
+	void _unhandled_input(const Ref<InputEvent> &p_event);
 
 	bool _search(uint32_t p_flags, int p_from_line, int p_from_col);
 
@@ -213,7 +213,7 @@ class CodeTextEditor : public VBoxContainer {
 	void _complete_request();
 	void _font_resize_timeout();
 
-	void _text_editor_gui_input(const InputEvent &p_event);
+	void _text_editor_gui_input(const Ref<InputEvent> &p_event);
 	void _zoom_in();
 	void _zoom_out();
 	void _reset_zoom();

+ 7 - 6
editor/create_dialog.cpp

@@ -109,14 +109,15 @@ void CreateDialog::_text_changed(const String &p_newtext) {
 	_update_search();
 }
 
-void CreateDialog::_sbox_input(const InputEvent &p_ie) {
+void CreateDialog::_sbox_input(const Ref<InputEvent> &p_ie) {
 
-	if (p_ie.type == InputEvent::KEY && (p_ie.key.scancode == KEY_UP ||
-												p_ie.key.scancode == KEY_DOWN ||
-												p_ie.key.scancode == KEY_PAGEUP ||
-												p_ie.key.scancode == KEY_PAGEDOWN)) {
+	Ref<InputEventKey> k = p_ie;
+	if (k.is_valid() && (k->get_scancode() == KEY_UP ||
+								k->get_scancode() == KEY_DOWN ||
+								k->get_scancode() == KEY_PAGEUP ||
+								k->get_scancode() == KEY_PAGEDOWN)) {
 
-		search_options->call("_gui_input", p_ie);
+		search_options->call("_gui_input", k);
 		search_box->accept_event();
 	}
 }

+ 1 - 1
editor/create_dialog.h

@@ -69,7 +69,7 @@ class CreateDialog : public ConfirmationDialog {
 	void _history_activated();
 	void _favorite_activated();
 
-	void _sbox_input(const InputEvent &p_ie);
+	void _sbox_input(const Ref<InputEvent> &p_ie);
 
 	void _confirmed();
 	void _text_changed(const String &p_newtext);

+ 54 - 74
editor/doc/doc_data.cpp

@@ -331,8 +331,7 @@ void DocData::generate(bool p_basic_types) {
 									default_arg_text = "NULL";
 									break;
 								}
-							case Variant::INPUT_EVENT:
-							case Variant::DICTIONARY:
+							case Variant::DICTIONARY: // 20
 							case Variant::ARRAY:
 							case Variant::_RID:
 
@@ -477,97 +476,78 @@ void DocData::generate(bool p_basic_types) {
 		if (i == Variant::OBJECT)
 			continue; //use the core type instead
 
-		int loops = 1;
+		String cname = Variant::get_type_name(Variant::Type(i));
 
-		if (i == Variant::INPUT_EVENT)
-			loops = InputEvent::TYPE_MAX;
-
-		for (int j = 0; j < loops; j++) {
-
-			String cname = Variant::get_type_name(Variant::Type(i));
-
-			if (i == Variant::INPUT_EVENT) {
-				static const char *ie_type[InputEvent::TYPE_MAX] = {
-					"", "Key", "MouseMotion", "MouseButton", "JoypadMotion", "JoypadButton", "ScreenTouch", "ScreenDrag", "Action"
-				};
-				cname += ie_type[j];
-			}
-
-			class_list[cname] = ClassDoc();
-			ClassDoc &c = class_list[cname];
-			c.name = cname;
-			c.category = "Built-In Types";
-
-			Variant::CallError cerror;
-			Variant v = Variant::construct(Variant::Type(i), NULL, 0, cerror);
+		class_list[cname] = ClassDoc();
+		ClassDoc &c = class_list[cname];
+		c.name = cname;
+		c.category = "Built-In Types";
 
-			if (i == Variant::INPUT_EVENT) {
-				v.set("type", j);
-			}
+		Variant::CallError cerror;
+		Variant v = Variant::construct(Variant::Type(i), NULL, 0, cerror);
 
-			List<MethodInfo> method_list;
-			v.get_method_list(&method_list);
-			method_list.sort();
-			Variant::get_constructor_list(Variant::Type(i), &method_list);
+		List<MethodInfo> method_list;
+		v.get_method_list(&method_list);
+		method_list.sort();
+		Variant::get_constructor_list(Variant::Type(i), &method_list);
 
-			for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
+		for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
 
-				MethodInfo &mi = E->get();
-				MethodDoc method;
+			MethodInfo &mi = E->get();
+			MethodDoc method;
 
-				method.name = mi.name;
+			method.name = mi.name;
 
-				for (int i = 0; i < mi.arguments.size(); i++) {
+			for (int i = 0; i < mi.arguments.size(); i++) {
 
-					ArgumentDoc arg;
-					PropertyInfo pi = mi.arguments[i];
+				ArgumentDoc arg;
+				PropertyInfo pi = mi.arguments[i];
 
-					arg.name = pi.name;
-					//print_line("arg name: "+arg.name);
-					if (pi.type == Variant::NIL)
-						arg.type = "var";
-					else
-						arg.type = Variant::get_type_name(pi.type);
-					int defarg = mi.default_arguments.size() - mi.arguments.size() + i;
-					if (defarg >= 0)
-						arg.default_value = mi.default_arguments[defarg];
-
-					method.arguments.push_back(arg);
-				}
+				arg.name = pi.name;
+				//print_line("arg name: "+arg.name);
+				if (pi.type == Variant::NIL)
+					arg.type = "var";
+				else
+					arg.type = Variant::get_type_name(pi.type);
+				int defarg = mi.default_arguments.size() - mi.arguments.size() + i;
+				if (defarg >= 0)
+					arg.default_value = mi.default_arguments[defarg];
 
-				if (mi.return_val.type == Variant::NIL) {
-					if (mi.return_val.name != "")
-						method.return_type = "var";
+				method.arguments.push_back(arg);
+			}
 
-				} else {
-					method.return_type = Variant::get_type_name(mi.return_val.type);
-				}
+			if (mi.return_val.type == Variant::NIL) {
+				if (mi.return_val.name != "")
+					method.return_type = "var";
 
-				c.methods.push_back(method);
+			} else {
+				method.return_type = Variant::get_type_name(mi.return_val.type);
 			}
 
-			List<PropertyInfo> properties;
-			v.get_property_list(&properties);
-			for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+			c.methods.push_back(method);
+		}
+
+		List<PropertyInfo> properties;
+		v.get_property_list(&properties);
+		for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
 
-				PropertyInfo pi = E->get();
-				PropertyDoc property;
-				property.name = pi.name;
-				property.type = Variant::get_type_name(pi.type);
+			PropertyInfo pi = E->get();
+			PropertyDoc property;
+			property.name = pi.name;
+			property.type = Variant::get_type_name(pi.type);
 
-				c.properties.push_back(property);
-			}
+			c.properties.push_back(property);
+		}
 
-			List<StringName> constants;
-			Variant::get_numeric_constants_for_type(Variant::Type(i), &constants);
+		List<StringName> constants;
+		Variant::get_numeric_constants_for_type(Variant::Type(i), &constants);
 
-			for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
+		for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
 
-				ConstantDoc constant;
-				constant.name = E->get();
-				constant.value = itos(Variant::get_numeric_constant_value(Variant::Type(i), E->get()));
-				c.constants.push_back(constant);
-			}
+			ConstantDoc constant;
+			constant.name = E->get();
+			constant.value = itos(Variant::get_numeric_constant_value(Variant::Type(i), E->get()));
+			c.constants.push_back(constant);
 		}
 	}
 

+ 1 - 2
editor/doc/doc_dump.cpp

@@ -194,8 +194,7 @@ void DocDump::dump(const String &p_file) {
 								default_arg_text = Variant::get_type_name(default_arg.get_type()) + "(" + default_arg_text + ")";
 								break;
 							case Variant::OBJECT:
-							case Variant::INPUT_EVENT:
-							case Variant::DICTIONARY:
+							case Variant::DICTIONARY: // 20
 							case Variant::ARRAY:
 							case Variant::_RID:
 

+ 7 - 4
editor/editor_audio_buses.cpp

@@ -385,15 +385,18 @@ void EditorAudioBus::_effect_add(int p_which) {
 	ur->commit_action();
 }
 
-void EditorAudioBus::_gui_input(const InputEvent &p_event) {
+void EditorAudioBus::_gui_input(const Ref<InputEvent> &p_event) {
 
-	if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode == KEY_DELETE && !p_event.key.echo) {
+	Ref<InputEventKey> k = p_event;
+	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && !k->is_echo()) {
 		accept_event();
 		emit_signal("delete_request");
 	}
-	if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 2 && p_event.mouse_button.pressed) {
 
-		Vector2 pos = Vector2(p_event.mouse_button.x, p_event.mouse_button.y);
+	Ref<InputEventMouseButton> mb = p_event;
+	if (mb.is_valid() && mb->get_button_index() == 2 && mb->is_pressed()) {
+
+		Vector2 pos = Vector2(mb->get_pos().x, mb->get_pos().y);
 		delete_popup->set_position(get_global_position() + pos);
 		delete_popup->popup();
 	}

+ 1 - 1
editor/editor_audio_buses.h

@@ -75,7 +75,7 @@ class EditorAudioBus : public PanelContainer {
 
 	bool updating_bus;
 
-	void _gui_input(const InputEvent &p_event);
+	void _gui_input(const Ref<InputEvent> &p_event);
 	void _delete_pressed(int p_option);
 
 	void _name_changed(const String &p_new_name);

+ 5 - 3
editor/editor_file_dialog.cpp

@@ -95,11 +95,13 @@ void EditorFileDialog::_notification(int p_what) {
 	}
 }
 
-void EditorFileDialog::_unhandled_input(const InputEvent &p_event) {
+void EditorFileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
 
-	if (p_event.type == InputEvent::KEY && is_window_modal_on_top()) {
+	Ref<InputEventKey> k = p_event;
 
-		if (p_event.key.pressed) {
+	if (k.is_valid() && is_window_modal_on_top()) {
+
+		if (k->is_pressed()) {
 
 			bool handled = false;
 

+ 1 - 1
editor/editor_file_dialog.h

@@ -169,7 +169,7 @@ private:
 	void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata);
 	void _request_single_thumbnail(const String &p_path);
 
-	void _unhandled_input(const InputEvent &p_event);
+	void _unhandled_input(const Ref<InputEvent> &p_event);
 
 protected:
 	void _notification(int p_what);

+ 26 - 16
editor/editor_help.cpp

@@ -61,14 +61,16 @@ void EditorHelpSearch::_text_changed(const String &p_newtext) {
 	_update_search();
 }
 
-void EditorHelpSearch::_sbox_input(const InputEvent &p_ie) {
+void EditorHelpSearch::_sbox_input(const Ref<InputEvent> &p_ie) {
 
-	if (p_ie.type == InputEvent::KEY && (p_ie.key.scancode == KEY_UP ||
-												p_ie.key.scancode == KEY_DOWN ||
-												p_ie.key.scancode == KEY_PAGEUP ||
-												p_ie.key.scancode == KEY_PAGEDOWN)) {
+	Ref<InputEventKey> k = p_ie;
 
-		search_options->call("_gui_input", p_ie);
+	if (k.is_valid() && (k->get_scancode() == KEY_UP ||
+								k->get_scancode() == KEY_DOWN ||
+								k->get_scancode() == KEY_PAGEUP ||
+								k->get_scancode() == KEY_PAGEDOWN)) {
+
+		search_options->call("_gui_input", k);
 		search_box->accept_event();
 	}
 }
@@ -448,14 +450,16 @@ void EditorHelpIndex::_update_class_list() {
 	}
 }
 
-void EditorHelpIndex::_sbox_input(const InputEvent &p_ie) {
+void EditorHelpIndex::_sbox_input(const Ref<InputEvent> &p_ie) {
+
+	Ref<InputEventKey> k = p_ie;
 
-	if (p_ie.type == InputEvent::KEY && (p_ie.key.scancode == KEY_UP ||
-												p_ie.key.scancode == KEY_DOWN ||
-												p_ie.key.scancode == KEY_PAGEUP ||
-												p_ie.key.scancode == KEY_PAGEDOWN)) {
+	if (k.is_valid() && (k->get_scancode() == KEY_UP ||
+								k->get_scancode() == KEY_DOWN ||
+								k->get_scancode() == KEY_PAGEUP ||
+								k->get_scancode() == KEY_PAGEDOWN)) {
 
-		class_list->call("_gui_input", p_ie);
+		class_list->call("_gui_input", k);
 		search_box->accept_event();
 	}
 }
@@ -499,11 +503,14 @@ EditorHelpIndex::EditorHelpIndex() {
 /// /////////////////////////////////
 DocData *EditorHelp::doc = NULL;
 
-void EditorHelp::_unhandled_key_input(const InputEvent &p_ev) {
+void EditorHelp::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
 
 	if (!is_visible_in_tree())
 		return;
-	if (p_ev.key.mod.control && p_ev.key.scancode == KEY_F) {
+
+	Ref<InputEventKey> k = p_ev;
+
+	if (k.is_valid() && k->get_control() && k->get_scancode() == KEY_F) {
 
 		search->grab_focus();
 		search->select_all();
@@ -598,8 +605,11 @@ void EditorHelp::_class_desc_select(const String &p_select) {
 	}
 }
 
-void EditorHelp::_class_desc_input(const InputEvent &p_input) {
-	if (p_input.type == InputEvent::MOUSE_BUTTON && p_input.mouse_button.pressed && p_input.mouse_button.button_index == 1) {
+void EditorHelp::_class_desc_input(const Ref<InputEvent> &p_input) {
+
+	Ref<InputEventMouseButton> mb = p_input;
+
+	if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == 1) {
 		class_desc->set_selection_enabled(false);
 		class_desc->set_selection_enabled(true);
 	}

+ 4 - 4
editor/editor_help.h

@@ -56,7 +56,7 @@ class EditorHelpSearch : public ConfirmationDialog {
 
 	void _update_search();
 
-	void _sbox_input(const InputEvent &p_ie);
+	void _sbox_input(const Ref<InputEvent> &p_ie);
 
 	void _confirmed();
 	void _text_changed(const String &p_newtext);
@@ -81,7 +81,7 @@ class EditorHelpIndex : public ConfirmationDialog {
 
 	void _tree_item_selected();
 	void _text_changed(const String &p_text);
-	void _sbox_input(const InputEvent &p_ie);
+	void _sbox_input(const Ref<InputEvent> &p_ie);
 
 	void _update_class_list();
 
@@ -147,7 +147,7 @@ class EditorHelp : public VBoxContainer {
 	void _scroll_changed(double p_scroll);
 	void _class_list_select(const String &p_select);
 	void _class_desc_select(const String &p_select);
-	void _class_desc_input(const InputEvent &p_input);
+	void _class_desc_input(const Ref<InputEvent> &p_input);
 
 	Error _goto_desc(const String &p_class, int p_vscr = -1);
 	//void _update_history_buttons();
@@ -157,7 +157,7 @@ class EditorHelp : public VBoxContainer {
 	void _search(const String &p_str);
 	void _search_cbk();
 
-	void _unhandled_key_input(const InputEvent &p_ev);
+	void _unhandled_key_input(const Ref<InputEvent> &p_ev);
 
 protected:
 	void _notification(int p_what);

+ 6 - 4
editor/editor_name_dialog.cpp

@@ -32,14 +32,16 @@
 #include "class_db.h"
 #include "os/keyboard.h"
 
-void EditorNameDialog::_line_gui_input(const InputEvent &p_event) {
+void EditorNameDialog::_line_gui_input(const Ref<InputEvent> &p_event) {
 
-	if (p_event.type == InputEvent::KEY) {
+	Ref<InputEventKey> k = p_event;
 
-		if (!p_event.key.pressed)
+	if (k.is_valid()) {
+
+		if (!k->is_pressed())
 			return;
 
-		switch (p_event.key.scancode) {
+		switch (k->get_scancode()) {
 			case KEY_ENTER:
 			case KEY_RETURN: {
 

+ 1 - 1
editor/editor_name_dialog.h

@@ -41,7 +41,7 @@ class EditorNameDialog : public ConfirmationDialog {
 	VBoxContainer *makevb;
 	LineEdit *name;
 
-	void _line_gui_input(const InputEvent &p_event);
+	void _line_gui_input(const Ref<InputEvent> &p_event);
 
 protected:
 	static void _bind_methods();

+ 13 - 8
editor/editor_node.cpp

@@ -173,12 +173,13 @@ void EditorNode::_update_title() {
 	OS::get_singleton()->set_window_title(title);
 }
 
-void EditorNode::_unhandled_input(const InputEvent &p_event) {
+void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) {
 
 	if (Node::get_viewport()->get_modal_stack_top())
 		return; //ignore because of modal window
 
-	if (p_event.type == InputEvent::KEY && p_event.key.pressed && !p_event.key.echo && !gui_base->get_viewport()->gui_has_modal_stack()) {
+	Ref<InputEventKey> k = p_event;
+	if (k.is_valid() && k->is_pressed() && !k->is_echo() && !gui_base->get_viewport()->gui_has_modal_stack()) {
 
 		if (ED_IS_SHORTCUT("editor/next_tab", p_event)) {
 			int next_tab = editor_data.get_edited_scene() + 1;
@@ -3710,11 +3711,13 @@ void EditorNode::show_warning(const String &p_text, const String &p_title) {
 	warning->popup_centered_minsize();
 }
 
-void EditorNode::_dock_select_input(const InputEvent &p_input) {
+void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) {
 
-	if (p_input.type == InputEvent::MOUSE_BUTTON || p_input.type == InputEvent::MOUSE_MOTION) {
+	Ref<InputEventMouse> me = p_input;
 
-		Vector2 point(p_input.mouse_motion.x, p_input.mouse_motion.y);
+	if (me.is_valid()) {
+
+		Vector2 point = me->get_pos();
 
 		int nrect = -1;
 		for (int i = 0; i < DOCK_SLOT_MAX; i++) {
@@ -3732,7 +3735,9 @@ void EditorNode::_dock_select_input(const InputEvent &p_input) {
 		if (nrect == -1)
 			return;
 
-		if (p_input.type == InputEvent::MOUSE_BUTTON && p_input.mouse_button.button_index == 1 && p_input.mouse_button.pressed && dock_popup_selected != nrect) {
+		Ref<InputEventMouseButton> mb = me;
+
+		if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && dock_popup_selected != nrect) {
 			Control *dock = dock_slot[dock_popup_selected]->get_current_tab_control();
 			if (dock) {
 				dock_slot[dock_popup_selected]->remove_child(dock);
@@ -6190,7 +6195,7 @@ void EditorPluginList::edit(Object *p_object) {
 	}
 }
 
-bool EditorPluginList::forward_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event) {
+bool EditorPluginList::forward_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) {
 
 	bool discard = false;
 
@@ -6203,7 +6208,7 @@ bool EditorPluginList::forward_gui_input(const Transform2D &p_canvas_xform, cons
 	return discard;
 }
 
-bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const InputEvent &p_event) {
+bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event) {
 	bool discard = false;
 
 	for (int i = 0; i < plugins_list.size(); i++) {

+ 4 - 4
editor/editor_node.h

@@ -482,7 +482,7 @@ private:
 
 	bool convert_old;
 
-	void _unhandled_input(const InputEvent &p_event);
+	void _unhandled_input(const Ref<InputEvent> &p_event);
 
 	static void _load_error_notify(void *p_ud, const String &p_text);
 
@@ -539,7 +539,7 @@ private:
 
 	bool _find_scene_in_use(Node *p_node, const String &p_path) const;
 
-	void _dock_select_input(const InputEvent &p_input);
+	void _dock_select_input(const Ref<InputEvent> &p_input);
 	void _dock_move_left();
 	void _dock_move_right();
 	void _dock_select_draw();
@@ -807,8 +807,8 @@ public:
 
 	void make_visible(bool p_visible);
 	void edit(Object *p_object);
-	bool forward_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event);
-	bool forward_spatial_gui_input(Camera *p_camera, const InputEvent &p_event);
+	bool forward_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event);
+	bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event);
 	void forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas);
 	void clear();
 	bool empty();

+ 3 - 2
editor/editor_path.cpp

@@ -69,9 +69,10 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) {
 	}
 }
 
-void EditorPath::_gui_input(const InputEvent &p_event) {
+void EditorPath::_gui_input(const Ref<InputEvent> &p_event) {
 
-	if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == BUTTON_LEFT && p_event.mouse_button.pressed) {
+	Ref<InputEventMouseButton> mb = p_event;
+	if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
 
 		Object *obj = ObjectDB::get_instance(history->get_path_object(history->get_path_size() - 1));
 		if (!obj)

+ 1 - 1
editor/editor_path.h

@@ -46,7 +46,7 @@ class EditorPath : public Control {
 	EditorPath();
 
 	void _popup_select(int p_idx);
-	void _gui_input(const InputEvent &p_event);
+	void _gui_input(const Ref<InputEvent> &p_event);
 	void _add_children_to_popup(Object *p_obj, int p_depth = 0);
 
 protected:

+ 4 - 4
editor/editor_plugin.cpp

@@ -156,7 +156,7 @@ Ref<SpatialEditorGizmo> EditorPlugin::create_spatial_gizmo(Spatial *p_spatial) {
 	return Ref<SpatialEditorGizmo>();
 }
 
-bool EditorPlugin::forward_canvas_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event) {
+bool EditorPlugin::forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) {
 
 	if (get_script_instance() && get_script_instance()->has_method("forward_canvas_gui_input")) {
 		return get_script_instance()->call("forward_canvas_gui_input", p_canvas_xform, p_event);
@@ -175,7 +175,7 @@ void EditorPlugin::update_canvas() {
 	CanvasItemEditor::get_singleton()->get_viewport_control()->update();
 }
 
-bool EditorPlugin::forward_spatial_gui_input(Camera *p_camera, const InputEvent &p_event) {
+bool EditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event) {
 
 	if (get_script_instance() && get_script_instance()->has_method("forward_spatial_gui_input")) {
 		return get_script_instance()->call("forward_spatial_gui_input", p_camera, p_event);
@@ -366,9 +366,9 @@ void EditorPlugin::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("queue_save_layout"), &EditorPlugin::queue_save_layout);
 	ClassDB::bind_method(D_METHOD("edit_resource"), &EditorPlugin::edit_resource);
 	ClassDB::bind_method(D_METHOD("add_import_plugin"), &EditorPlugin::add_import_plugin);
-	ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_canvas_gui_input", PropertyInfo(Variant::TRANSFORM2D, "canvas_xform"), PropertyInfo(Variant::INPUT_EVENT, "event")));
+	ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_canvas_gui_input", PropertyInfo(Variant::TRANSFORM2D, "canvas_xform"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
 	ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_draw_over_canvas", PropertyInfo(Variant::TRANSFORM2D, "canvas_xform"), PropertyInfo(Variant::OBJECT, "canvas:Control")));
-	ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::INPUT_EVENT, "event")));
+	ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
 	MethodInfo gizmo = MethodInfo(Variant::OBJECT, "create_spatial_gizmo", PropertyInfo(Variant::OBJECT, "for_spatial:Spatial"));
 	gizmo.return_val.hint = PROPERTY_HINT_RESOURCE_TYPE;
 	gizmo.return_val.hint_string = "EditorSpatialGizmo";

+ 2 - 2
editor/editor_plugin.h

@@ -107,9 +107,9 @@ public:
 	void remove_tool_menu_item(const String &p_name);
 
 	virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial *p_spatial);
-	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event);
+	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event);
 	virtual void forward_draw_over_canvas(const Transform2D &p_canvas_xform, Control *p_canvas);
-	virtual bool forward_spatial_gui_input(Camera *p_camera, const InputEvent &p_event);
+	virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event);
 	virtual String get_name() const;
 	virtual bool has_main_screen() const;
 	virtual void make_visible(bool p_visible);

+ 9 - 5
editor/editor_profiler.cpp

@@ -483,16 +483,20 @@ void EditorProfiler::_cursor_metric_changed(double) {
 	_update_frame();
 }
 
-void EditorProfiler::_graph_tex_input(const InputEvent &p_ev) {
+void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) {
 
 	if (last_metric < 0)
 		return;
 
+	Ref<InputEventMouse> me = p_ev;
+	Ref<InputEventMouseButton> mb = p_ev;
+	Ref<InputEventMouseMotion> mm = p_ev;
+
 	if (
-			(p_ev.type == InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index == BUTTON_LEFT && p_ev.mouse_button.pressed) ||
-			(p_ev.type == InputEvent::MOUSE_MOTION)) {
+			(mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) ||
+			(mm.is_valid())) {
 
-		int x = p_ev.mouse_button.x;
+		int x = me->get_pos().x;
 		x = x * frame_metrics.size() / graph->get_size().width;
 
 		bool show_hover = x >= 0 && x < frame_metrics.size();
@@ -519,7 +523,7 @@ void EditorProfiler::_graph_tex_input(const InputEvent &p_ev) {
 			hover_metric = -1;
 		}
 
-		if (p_ev.type == InputEvent::MOUSE_BUTTON || p_ev.mouse_motion.button_mask & BUTTON_MASK_LEFT) {
+		if (mb.is_valid() || mb->get_button_mask() & BUTTON_MASK_LEFT) {
 			//cursor_metric=x;
 			updating_frame = true;
 

+ 1 - 1
editor/editor_profiler.h

@@ -143,7 +143,7 @@ private:
 	void _graph_tex_mouse_exit();
 
 	void _graph_tex_draw();
-	void _graph_tex_input(const InputEvent &p_ev);
+	void _graph_tex_input(const Ref<InputEvent> &p_ev);
 
 	int _get_cursor_index() const;
 

+ 13 - 12
editor/editor_settings.cpp

@@ -65,7 +65,7 @@ bool EditorSettings::_set(const StringName &p_name, const Variant &p_value) {
 		for (int i = 0; i < arr.size(); i += 2) {
 
 			String name = arr[i];
-			InputEvent shortcut = arr[i + 1];
+			Ref<InputEvent> shortcut = arr[i + 1];
 
 			Ref<ShortCut> sc;
 			sc.instance();
@@ -109,8 +109,8 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const {
 					continue; //this came from settings but is not any longer used
 				}
 
-				InputEvent original = sc->get_meta("original");
-				if (sc->is_shortcut(original) || (original.type == InputEvent::NONE && sc->get_shortcut().type == InputEvent::NONE))
+				Ref<InputEvent> original = sc->get_meta("original");
+				if (sc->is_shortcut(original) || (original.is_null() && sc->get_shortcut().is_null()))
 					continue; //not changed from default, don't save
 			}
 
@@ -984,7 +984,7 @@ void EditorSettings::add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcu
 	shortcuts[p_name] = p_shortcut;
 }
 
-bool EditorSettings::is_shortcut(const String &p_name, const InputEvent &p_event) const {
+bool EditorSettings::is_shortcut(const String &p_name, const Ref<InputEvent> &p_event) const {
 
 	const Map<String, Ref<ShortCut> >::Element *E = shortcuts.find(p_name);
 	if (!E) {
@@ -1101,15 +1101,16 @@ Ref<ShortCut> ED_GET_SHORTCUT(const String &p_path) {
 
 Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode) {
 
-	InputEvent ie;
+	Ref<InputEventKey> ie;
 	if (p_keycode) {
-		ie.type = InputEvent::KEY;
-		ie.key.unicode = p_keycode & KEY_CODE_MASK;
-		ie.key.scancode = p_keycode & KEY_CODE_MASK;
-		ie.key.mod.shift = bool(p_keycode & KEY_MASK_SHIFT);
-		ie.key.mod.alt = bool(p_keycode & KEY_MASK_ALT);
-		ie.key.mod.control = bool(p_keycode & KEY_MASK_CTRL);
-		ie.key.mod.meta = bool(p_keycode & KEY_MASK_META);
+		ie.instance();
+
+		ie->set_unicode(p_keycode & KEY_CODE_MASK);
+		ie->set_scancode(p_keycode & KEY_CODE_MASK);
+		ie->set_shift(bool(p_keycode & KEY_MASK_SHIFT));
+		ie->set_alt(bool(p_keycode & KEY_MASK_ALT));
+		ie->set_control(bool(p_keycode & KEY_MASK_CTRL));
+		ie->set_metakey(bool(p_keycode & KEY_MASK_META));
 	}
 
 	Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);

+ 1 - 1
editor/editor_settings.h

@@ -160,7 +160,7 @@ public:
 	bool save_text_editor_theme_as(String p_file);
 
 	void add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcut);
-	bool is_shortcut(const String &p_name, const InputEvent &p_event) const;
+	bool is_shortcut(const String &p_name, const Ref<InputEvent> &p_event) const;
 	Ref<ShortCut> get_shortcut(const String &p_name) const;
 	void get_shortcut_list(List<String> *r_shortcuts);
 

+ 4 - 3
editor/pane_drag.cpp

@@ -29,11 +29,12 @@
 /*************************************************************************/
 #include "pane_drag.h"
 
-void PaneDrag::_gui_input(const InputEvent &p_input) {
+void PaneDrag::_gui_input(const Ref<InputEvent> &p_input) {
 
-	if (p_input.type == InputEvent::MOUSE_MOTION && p_input.mouse_motion.button_mask & BUTTON_MASK_LEFT) {
+	Ref<InputEventMouseMotion> mm = p_input;
+	if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
 
-		emit_signal("dragged", Point2(p_input.mouse_motion.relative_x, p_input.mouse_motion.relative_y));
+		emit_signal("dragged", Point2(mm->get_relative().x, mm->get_relative().y));
 	}
 }
 

+ 1 - 1
editor/pane_drag.h

@@ -39,7 +39,7 @@ class PaneDrag : public Control {
 	bool mouse_over;
 
 protected:
-	void _gui_input(const InputEvent &p_input);
+	void _gui_input(const Ref<InputEvent> &p_input);
 	void _notification(int p_what);
 	virtual Size2 get_minimum_size() const;
 	static void _bind_methods();

+ 7 - 6
editor/plugins/animation_player_editor_plugin.cpp

@@ -51,7 +51,7 @@ void AnimationPlayerEditor::_node_removed(Node *p_node) {
 	}
 }
 
-void AnimationPlayerEditor::_gui_input(InputEvent p_event) {
+void AnimationPlayerEditor::_gui_input(Ref<InputEvent> p_event) {
 }
 
 void AnimationPlayerEditor::_notification(int p_what) {
@@ -1160,14 +1160,15 @@ void AnimationPlayerEditor::_animation_save_menu(int p_option) {
 	}
 }
 
-void AnimationPlayerEditor::_unhandled_key_input(const InputEvent &p_ev) {
+void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
 
-	if (is_visible_in_tree() && p_ev.type == InputEvent::KEY && p_ev.key.pressed && !p_ev.key.echo && !p_ev.key.mod.alt && !p_ev.key.mod.control && !p_ev.key.mod.meta) {
+	Ref<InputEventKey> k = p_ev;
+	if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo() && !k->get_alt() && !k->get_control() && !k->get_metakey()) {
 
-		switch (p_ev.key.scancode) {
+		switch (k->get_scancode()) {
 
 			case KEY_A: {
-				if (!p_ev.key.mod.shift)
+				if (!k->get_shift())
 					_play_bw_from_pressed();
 				else
 					_play_bw_pressed();
@@ -1176,7 +1177,7 @@ void AnimationPlayerEditor::_unhandled_key_input(const InputEvent &p_ev) {
 				_stop_pressed();
 			} break;
 			case KEY_D: {
-				if (!p_ev.key.mod.shift)
+				if (!k->get_shift())
 					_play_from_pressed();
 				else
 					_play_pressed();

+ 2 - 2
editor/plugins/animation_player_editor_plugin.h

@@ -158,7 +158,7 @@ class AnimationPlayerEditor : public VBoxContainer {
 	void _animation_key_editor_anim_len_changed(float p_new);
 	void _animation_key_editor_anim_step_changed(float p_len);
 
-	void _unhandled_key_input(const InputEvent &p_ev);
+	void _unhandled_key_input(const Ref<InputEvent> &p_ev);
 	void _animation_tool_menu(int p_option);
 	void _animation_save_menu(int p_option);
 
@@ -166,7 +166,7 @@ class AnimationPlayerEditor : public VBoxContainer {
 
 protected:
 	void _notification(int p_what);
-	void _gui_input(InputEvent p_event);
+	void _gui_input(Ref<InputEvent> p_event);
 	void _node_removed(Node *p_node);
 	static void _bind_methods();
 

+ 106 - 106
editor/plugins/animation_tree_editor_plugin.cpp

@@ -735,139 +735,139 @@ void AnimationTreeEditor::_node_edit_property(const StringName& p_node) {
 }
 #endif
 
-void AnimationTreeEditor::_gui_input(InputEvent p_event) {
+void AnimationTreeEditor::_gui_input(Ref<InputEvent> p_event) {
 
-	switch (p_event.type) {
+	Ref<InputEventMouseButton> mb = p_event;
 
-		case InputEvent::MOUSE_BUTTON: {
+	if (mb.is_valid()) {
 
-			if (p_event.mouse_button.pressed) {
+		if (mb->is_pressed()) {
 
-				if (p_event.mouse_button.button_index == 1) {
-					click_pos = Point2(p_event.mouse_button.x, p_event.mouse_button.y);
-					click_motion = click_pos;
-					click_type = _locate_click(click_pos, &click_node, &click_slot);
-					if (click_type != CLICK_NONE) {
+			if (mb->get_button_index() == 1) {
+				click_pos = Point2(mb->get_pos().x, mb->get_pos().y);
+				click_motion = click_pos;
+				click_type = _locate_click(click_pos, &click_node, &click_slot);
+				if (click_type != CLICK_NONE) {
 
-						order.erase(click_node);
-						order.push_back(click_node);
-						update();
-					}
+					order.erase(click_node);
+					order.push_back(click_node);
+					update();
+				}
 
-					switch (click_type) {
-						case CLICK_INPUT_SLOT: {
-							click_pos = _get_slot_pos(click_node, true, click_slot);
-						} break;
-						case CLICK_OUTPUT_SLOT: {
-							click_pos = _get_slot_pos(click_node, false, click_slot);
-						} break;
-						case CLICK_PARAMETER: {
-
-							edited_node = click_node;
-							renaming_edit = false;
-							_popup_edit_dialog();
-							//open editor
-							//_node_edit_property(click_node);
-						} break;
-						default: {}
-					}
+				switch (click_type) {
+					case CLICK_INPUT_SLOT: {
+						click_pos = _get_slot_pos(click_node, true, click_slot);
+					} break;
+					case CLICK_OUTPUT_SLOT: {
+						click_pos = _get_slot_pos(click_node, false, click_slot);
+					} break;
+					case CLICK_PARAMETER: {
+
+						edited_node = click_node;
+						renaming_edit = false;
+						_popup_edit_dialog();
+						//open editor
+						//_node_edit_property(click_node);
+					} break;
+					default: {}
 				}
-				if (p_event.mouse_button.button_index == 2) {
-
-					if (click_type != CLICK_NONE) {
-						click_type = CLICK_NONE;
-						update();
-					} else {
-						// try to disconnect/remove
-
-						Point2 rclick_pos = Point2(p_event.mouse_button.x, p_event.mouse_button.y);
-						rclick_type = _locate_click(rclick_pos, &rclick_node, &rclick_slot);
-						if (rclick_type == CLICK_INPUT_SLOT || rclick_type == CLICK_OUTPUT_SLOT) {
-
-							node_popup->clear();
-							node_popup->add_item(TTR("Disconnect"), NODE_DISCONNECT);
-							if (anim_tree->node_get_type(rclick_node) == AnimationTreePlayer::NODE_TRANSITION) {
-								node_popup->add_item(TTR("Add Input"), NODE_ADD_INPUT);
-								if (rclick_type == CLICK_INPUT_SLOT) {
-									if (anim_tree->transition_node_has_input_auto_advance(rclick_node, rclick_slot))
-										node_popup->add_item(TTR("Clear Auto-Advance"), NODE_CLEAR_AUTOADVANCE);
-									else
-										node_popup->add_item(TTR("Set Auto-Advance"), NODE_SET_AUTOADVANCE);
-									node_popup->add_item(TTR("Delete Input"), NODE_DELETE_INPUT);
-								}
-							}
+			}
+			if (mb->get_button_index() == 2) {
 
-							node_popup->set_position(rclick_pos + get_global_position());
-							node_popup->popup();
+				if (click_type != CLICK_NONE) {
+					click_type = CLICK_NONE;
+					update();
+				} else {
+					// try to disconnect/remove
+
+					Point2 rclick_pos = Point2(mb->get_pos().x, mb->get_pos().y);
+					rclick_type = _locate_click(rclick_pos, &rclick_node, &rclick_slot);
+					if (rclick_type == CLICK_INPUT_SLOT || rclick_type == CLICK_OUTPUT_SLOT) {
+
+						node_popup->clear();
+						node_popup->add_item(TTR("Disconnect"), NODE_DISCONNECT);
+						if (anim_tree->node_get_type(rclick_node) == AnimationTreePlayer::NODE_TRANSITION) {
+							node_popup->add_item(TTR("Add Input"), NODE_ADD_INPUT);
+							if (rclick_type == CLICK_INPUT_SLOT) {
+								if (anim_tree->transition_node_has_input_auto_advance(rclick_node, rclick_slot))
+									node_popup->add_item(TTR("Clear Auto-Advance"), NODE_CLEAR_AUTOADVANCE);
+								else
+									node_popup->add_item(TTR("Set Auto-Advance"), NODE_SET_AUTOADVANCE);
+								node_popup->add_item(TTR("Delete Input"), NODE_DELETE_INPUT);
+							}
 						}
 
-						if (rclick_type == CLICK_NODE) {
-							node_popup->clear();
-							node_popup->add_item(TTR("Rename"), NODE_RENAME);
-							node_popup->add_item(TTR("Remove"), NODE_ERASE);
-							if (anim_tree->node_get_type(rclick_node) == AnimationTreePlayer::NODE_TRANSITION)
-								node_popup->add_item(TTR("Add Input"), NODE_ADD_INPUT);
-							node_popup->set_position(rclick_pos + get_global_position());
-							node_popup->popup();
-						}
+						node_popup->set_position(rclick_pos + get_global_position());
+						node_popup->popup();
 					}
-				}
-			} else {
 
-				if (p_event.mouse_button.button_index == 1 && click_type != CLICK_NONE) {
+					if (rclick_type == CLICK_NODE) {
+						node_popup->clear();
+						node_popup->add_item(TTR("Rename"), NODE_RENAME);
+						node_popup->add_item(TTR("Remove"), NODE_ERASE);
+						if (anim_tree->node_get_type(rclick_node) == AnimationTreePlayer::NODE_TRANSITION)
+							node_popup->add_item(TTR("Add Input"), NODE_ADD_INPUT);
+						node_popup->set_position(rclick_pos + get_global_position());
+						node_popup->popup();
+					}
+				}
+			}
+		} else {
 
-					switch (click_type) {
-						case CLICK_INPUT_SLOT:
-						case CLICK_OUTPUT_SLOT: {
+			if (mb->get_button_index() == 1 && click_type != CLICK_NONE) {
 
-							Point2 dst_click_pos = Point2(p_event.mouse_button.x, p_event.mouse_button.y);
-							StringName id;
-							int slot;
-							ClickType dst_click_type = _locate_click(dst_click_pos, &id, &slot);
+				switch (click_type) {
+					case CLICK_INPUT_SLOT:
+					case CLICK_OUTPUT_SLOT: {
 
-							if (dst_click_type == CLICK_INPUT_SLOT && click_type == CLICK_OUTPUT_SLOT) {
+						Point2 dst_click_pos = Point2(mb->get_pos().x, mb->get_pos().y);
+						StringName id;
+						int slot;
+						ClickType dst_click_type = _locate_click(dst_click_pos, &id, &slot);
 
-								anim_tree->connect_nodes(click_node, id, slot);
-							}
-							if (click_type == CLICK_INPUT_SLOT && dst_click_type == CLICK_OUTPUT_SLOT) {
+						if (dst_click_type == CLICK_INPUT_SLOT && click_type == CLICK_OUTPUT_SLOT) {
 
-								anim_tree->connect_nodes(id, click_node, click_slot);
-							}
+							anim_tree->connect_nodes(click_node, id, slot);
+						}
+						if (click_type == CLICK_INPUT_SLOT && dst_click_type == CLICK_OUTPUT_SLOT) {
 
-						} break;
-						case CLICK_NODE: {
-							Point2 new_pos = anim_tree->node_get_pos(click_node) + (click_motion - click_pos);
-							if (new_pos.x < 5)
-								new_pos.x = 5;
-							if (new_pos.y < 5)
-								new_pos.y = 5;
-							anim_tree->node_set_pos(click_node, new_pos);
-
-						} break;
-						default: {}
-					}
+							anim_tree->connect_nodes(id, click_node, click_slot);
+						}
 
-					click_type = CLICK_NONE;
-					update();
+					} break;
+					case CLICK_NODE: {
+						Point2 new_pos = anim_tree->node_get_pos(click_node) + (click_motion - click_pos);
+						if (new_pos.x < 5)
+							new_pos.x = 5;
+						if (new_pos.y < 5)
+							new_pos.y = 5;
+						anim_tree->node_set_pos(click_node, new_pos);
+
+					} break;
+					default: {}
 				}
+
+				click_type = CLICK_NONE;
+				update();
 			}
 		}
+	}
 
-		case InputEvent::MOUSE_MOTION: {
+	Ref<InputEventMouseMotion> mm = p_event;
 
-			if (p_event.mouse_motion.button_mask & 1 && click_type != CLICK_NONE) {
+	if (mm.is_valid()) {
 
-				click_motion = Point2(p_event.mouse_button.x, p_event.mouse_button.y);
-				update();
-			}
-			if ((p_event.mouse_motion.button_mask & 4 || Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
+		if (mm->get_button_mask() & 1 && click_type != CLICK_NONE) {
 
-				h_scroll->set_value(h_scroll->get_value() - p_event.mouse_motion.relative_x);
-				v_scroll->set_value(v_scroll->get_value() - p_event.mouse_motion.relative_y);
-				update();
-			}
+			click_motion = Point2(mm->get_pos().x, mm->get_pos().y);
+			update();
+		}
+		if ((mm->get_button_mask() & 4 || Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
 
-		} break;
+			h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x);
+			v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y);
+			update();
+		}
 	}
 }
 

+ 1 - 1
editor/plugins/animation_tree_editor_plugin.h

@@ -155,7 +155,7 @@ class AnimationTreeEditor : public Control {
 
 protected:
 	void _notification(int p_what);
-	void _gui_input(InputEvent p_event);
+	void _gui_input(Ref<InputEvent> p_event);
 	static void _bind_methods();
 
 public:

+ 63 - 62
editor/plugins/canvas_item_editor_plugin.cpp

@@ -204,17 +204,19 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) {
 	undo_redo->commit_action();
 }
 
-void CanvasItemEditor::_unhandled_key_input(const InputEvent &p_ev) {
+void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
+
+	Ref<InputEventKey> k = p_ev;
 
 	if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
 		return;
 
-	if (p_ev.key.mod.control)
+	if (k->get_control())
 		return;
 
-	if (p_ev.key.pressed && !p_ev.key.echo && p_ev.key.scancode == KEY_V && drag == DRAG_NONE && can_move_pivot) {
+	if (k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V && drag == DRAG_NONE && can_move_pivot) {
 
-		if (p_ev.key.mod.shift) {
+		if (k->get_shift()) {
 			//move drag pivot
 			drag = DRAG_PIVOT;
 		} else if (!Input::get_singleton()->is_mouse_button_pressed(0)) {
@@ -958,9 +960,9 @@ bool CanvasItemEditor::get_remove_list(List<Node *> *p_list) {
 	return false; //!p_list->empty();
 }
 
-void CanvasItemEditor::_list_select(const InputEventMouseButton &b) {
+void CanvasItemEditor::_list_select(const Ref<InputEventMouseButton> &b) {
 
-	Point2 click = Point2(b.x, b.y);
+	Point2 click = b->get_pos();
 
 	Node *scene = editor->get_edited_scene();
 	if (!scene)
@@ -982,7 +984,7 @@ void CanvasItemEditor::_list_select(const InputEventMouseButton &b) {
 		CanvasItem *item = selection_results[0].item;
 		selection_results.clear();
 
-		additive_selection = b.mod.shift;
+		additive_selection = b->get_shift();
 		if (!_select(item, click, additive_selection, false))
 			return;
 
@@ -1012,9 +1014,9 @@ void CanvasItemEditor::_list_select(const InputEventMouseButton &b) {
 														"\nType: " + item->get_class() + "\nPath: " + node_path);
 		}
 
-		additive_selection = b.mod.shift;
+		additive_selection = b->get_shift();
 
-		selection_menu->set_global_position(Vector2(b.global_x, b.global_y));
+		selection_menu->set_global_position(b->get_global_pos());
 		selection_menu->popup();
 		selection_menu->call_deferred("grab_click_focus");
 		selection_menu->set_invalidate_click_until_motion();
@@ -1023,7 +1025,7 @@ void CanvasItemEditor::_list_select(const InputEventMouseButton &b) {
 	}
 }
 
-void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
+void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
 
 	{
 
@@ -1039,19 +1041,19 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 		}
 	}
 
-	if (p_event.type == InputEvent::MOUSE_BUTTON) {
+	Ref<InputEventMouseButton> b = p_event;
 
-		const InputEventMouseButton &b = p_event.mouse_button;
+	if (b.is_valid()) {
 
-		if (b.button_index == BUTTON_WHEEL_DOWN) {
+		if (b->get_button_index() == BUTTON_WHEEL_DOWN) {
 
 			if (zoom < MIN_ZOOM)
 				return;
 
 			float prev_zoom = zoom;
-			zoom = zoom * (1 - (0.05 * b.factor));
+			zoom = zoom * (1 - (0.05 * b->get_factor()));
 			{
-				Point2 ofs(b.x, b.y);
+				Point2 ofs = b->get_pos();
 				ofs = ofs / prev_zoom - ofs / zoom;
 				h_scroll->set_value(h_scroll->get_value() + ofs.x);
 				v_scroll->set_value(v_scroll->get_value() + ofs.y);
@@ -1061,15 +1063,15 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 			return;
 		}
 
-		if (b.button_index == BUTTON_WHEEL_UP) {
+		if (b->get_button_index() == BUTTON_WHEEL_UP) {
 
 			if (zoom > MAX_ZOOM)
 				return;
 
 			float prev_zoom = zoom;
-			zoom = zoom * ((0.95 + (0.05 * b.factor)) / 0.95);
+			zoom = zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95);
 			{
-				Point2 ofs(b.x, b.y);
+				Point2 ofs = b->get_pos();
 				ofs = ofs / prev_zoom - ofs / zoom;
 				h_scroll->set_value(h_scroll->get_value() + ofs.x);
 				v_scroll->set_value(v_scroll->get_value() + ofs.y);
@@ -1080,9 +1082,9 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 			return;
 		}
 
-		if (b.button_index == BUTTON_RIGHT) {
+		if (b->get_button_index() == BUTTON_RIGHT) {
 
-			if (b.pressed && (tool == TOOL_SELECT && b.mod.alt)) {
+			if (b->is_pressed() && (tool == TOOL_SELECT && b->get_alt())) {
 
 				_list_select(b);
 				return;
@@ -1129,7 +1131,7 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 			} else if (box_selecting) {
 				box_selecting = false;
 				viewport->update();
-			} else if (b.pressed) {
+			} else if (b->is_pressed()) {
 #if 0
 				ref_item = NULL;
 				Node* scene = get_scene()->get_root_node()->cast_to<EditorNode>()->get_edited_scene();
@@ -1145,16 +1147,16 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 			return;
 		*/
 
-		if (b.button_index == BUTTON_LEFT && tool == TOOL_LIST_SELECT) {
-			if (b.pressed)
+		if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_LIST_SELECT) {
+			if (b->is_pressed())
 				_list_select(b);
 			return;
 		}
 
-		if (b.button_index == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) {
-			if (b.pressed) {
+		if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) {
+			if (b->is_pressed()) {
 
-				Point2 mouse_pos(b.x, b.y);
+				Point2 mouse_pos = b->get_pos();
 				mouse_pos = transform.affine_inverse().xform(mouse_pos);
 				mouse_pos = snap_point(mouse_pos);
 				_edit_set_pivot(mouse_pos);
@@ -1162,10 +1164,10 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 			return;
 		}
 
-		if (tool == TOOL_PAN || b.button_index != BUTTON_LEFT || Input::get_singleton()->is_key_pressed(KEY_SPACE))
+		if (tool == TOOL_PAN || b->get_button_index() != BUTTON_LEFT || Input::get_singleton()->is_key_pressed(KEY_SPACE))
 			return;
 
-		if (!b.pressed) {
+		if (!b->is_pressed()) {
 
 			if (drag != DRAG_NONE) {
 
@@ -1227,7 +1229,7 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 
 			if (box_selecting) {
 #if 0
-				if ( ! b.mod.shift ) _clear_canvas_items();
+				if ( ! b->get_shift() ) _clear_canvas_items();
 				if ( box_selection_end() ) return;
 #endif
 
@@ -1272,8 +1274,8 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 					E->get().to
 				};
 
-				Vector2 p = Geometry::get_closest_point_to_segment_2d(Vector2(b.x, b.y), s);
-				float d = p.distance_to(Vector2(b.x, b.y));
+				Vector2 p = Geometry::get_closest_point_to_segment_2d(b->get_pos(), s);
+				float d = p.distance_to(b->get_pos());
 				if (d < bone_width && d < closest_dist) {
 					Cbone = E;
 					closest_dist = d;
@@ -1340,9 +1342,9 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 			CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
 			ERR_FAIL_COND(!se);
 
-			Point2 click(b.x, b.y);
+			Point2 click = b->get_pos();
 
-			if ((b.mod.control && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
+			if ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
 
 				drag = DRAG_ROTATE;
 				drag_from = transform.affine_inverse().xform(click);
@@ -1361,7 +1363,7 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 			if (tool == TOOL_SELECT) {
 				drag = _find_drag_type(xform, rect, click, drag_point_from);
 
-				if (b.doubleclick) {
+				if (b->is_doubleclick()) {
 
 					if (canvas_item->get_filename() != "" && canvas_item != editor->get_edited_scene()) {
 
@@ -1386,9 +1388,9 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 
 		//multi canvas_item edit
 
-		Point2 click = Point2(b.x, b.y);
+		Point2 click = b->get_pos();
 
-		if ((b.mod.alt || tool == TOOL_MOVE) && get_item_count()) {
+		if ((b->get_alt() || tool == TOOL_MOVE) && get_item_count()) {
 			_prepare_drag(click);
 			viewport->update();
 			return;
@@ -1433,37 +1435,36 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 		};
 		c = n->cast_to<CanvasItem>();
 #if 0
-		if ( b.pressed ) box_selection_start( click );
+		if ( b->is_pressed() ) box_selection_start( click );
 #endif
 
-		additive_selection = b.mod.shift;
+		additive_selection = b->get_shift();
 		if (!_select(c, click, additive_selection))
 			return;
 	}
 
-	if (p_event.type == InputEvent::MOUSE_MOTION) {
+	Ref<InputEventMouseMotion> m = p_event;
+	if (m.is_valid()) {
 
 		if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
 			viewport->call_deferred("grab_focus");
 
-		const InputEventMouseMotion &m = p_event.mouse_motion;
-
 		if (box_selecting) {
 
-			box_selecting_to = transform.affine_inverse().xform(Point2(m.x, m.y));
+			box_selecting_to = transform.affine_inverse().xform(m->get_pos());
 			viewport->update();
 			return;
 		}
 
 		if (drag == DRAG_NONE) {
 
-			if ((m.button_mask & BUTTON_MASK_LEFT && tool == TOOL_PAN) || m.button_mask & BUTTON_MASK_MIDDLE || (m.button_mask & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
+			if ((m->get_button_mask() & BUTTON_MASK_LEFT && tool == TOOL_PAN) || m->get_button_mask() & BUTTON_MASK_MIDDLE || (m->get_button_mask() & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
 
 				Point2i relative;
 				if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
 					relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
 				} else {
-					relative = Point2i(m.relative_x, m.relative_y);
+					relative = m->get_relative();
 				}
 
 				h_scroll->set_value(h_scroll->get_value() - relative.x / zoom);
@@ -1496,7 +1497,7 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 			}
 
 			Vector2 dfrom = drag_from;
-			Vector2 dto = transform.affine_inverse().xform(Point2(m.x, m.y));
+			Vector2 dto = transform.affine_inverse().xform(m->get_pos());
 			if (canvas_item->has_meta("_edit_lock_"))
 				continue;
 
@@ -1530,8 +1531,8 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 				continue;
 			}
 
-			bool uniform = m.mod.shift;
-			bool symmetric = m.mod.alt;
+			bool uniform = b->get_shift();
+			bool symmetric = b->get_alt();
 
 			dto = dto - (drag == DRAG_ALL || drag == DRAG_NODE_2D ? drag_from - drag_point_from : Vector2(0, 0));
 
@@ -1765,25 +1766,25 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) {
 		}
 	}
 
-	if (p_event.type == InputEvent::KEY) {
+	Ref<InputEventKey> k = p_event;
 
-		const InputEventKey &k = p_event.key;
+	if (k.is_valid()) {
 
-		if (k.pressed && drag == DRAG_NONE) {
+		if (k->is_pressed() && drag == DRAG_NONE) {
 
 			KeyMoveMODE move_mode = MOVE_VIEW_BASE;
-			if (k.mod.alt) move_mode = MOVE_LOCAL_BASE;
-			if (k.mod.control || k.mod.meta) move_mode = MOVE_LOCAL_WITH_ROT;
-
-			if (k.scancode == KEY_UP)
-				_key_move(Vector2(0, -1), k.mod.shift, move_mode);
-			else if (k.scancode == KEY_DOWN)
-				_key_move(Vector2(0, 1), k.mod.shift, move_mode);
-			else if (k.scancode == KEY_LEFT)
-				_key_move(Vector2(-1, 0), k.mod.shift, move_mode);
-			else if (k.scancode == KEY_RIGHT)
-				_key_move(Vector2(1, 0), k.mod.shift, move_mode);
-			else if (k.scancode == KEY_ESCAPE) {
+			if (k->get_alt()) move_mode = MOVE_LOCAL_BASE;
+			if (k->get_control() || k->get_metakey()) move_mode = MOVE_LOCAL_WITH_ROT;
+
+			if (k->get_scancode() == KEY_UP)
+				_key_move(Vector2(0, -1), k->get_shift(), move_mode);
+			else if (k->get_scancode() == KEY_DOWN)
+				_key_move(Vector2(0, 1), k->get_shift(), move_mode);
+			else if (k->get_scancode() == KEY_LEFT)
+				_key_move(Vector2(-1, 0), k->get_shift(), move_mode);
+			else if (k->get_scancode() == KEY_RIGHT)
+				_key_move(Vector2(1, 0), k->get_shift(), move_mode);
+			else if (k->get_scancode() == KEY_ESCAPE) {
 				editor_selection->clear();
 				viewport->update();
 			} else

+ 3 - 3
editor/plugins/canvas_item_editor_plugin.h

@@ -322,7 +322,7 @@ class CanvasItemEditor : public VBoxContainer {
 	void _clear_canvas_items();
 	void _visibility_changed(ObjectID p_canvas_item);
 	void _key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE p_move_mode);
-	void _list_select(const InputEventMouseButton &b);
+	void _list_select(const Ref<InputEventMouseButton> &b);
 
 	DragType _find_drag_type(const Transform2D &p_xform, const Rect2 &p_local_rect, const Point2 &p_click, Vector2 &r_point);
 	void _prepare_drag(const Point2 &p_click_pos);
@@ -352,9 +352,9 @@ class CanvasItemEditor : public VBoxContainer {
 	int get_item_count();
 	void _keying_changed();
 
-	void _unhandled_key_input(const InputEvent &p_ev);
+	void _unhandled_key_input(const Ref<InputEvent> &p_ev);
 
-	void _viewport_gui_input(const InputEvent &p_event);
+	void _viewport_gui_input(const Ref<InputEvent> &p_event);
 	void _viewport_draw();
 
 	void _focus_selection(int p_op);

+ 141 - 146
editor/plugins/collision_polygon_2d_editor_plugin.cpp

@@ -94,213 +94,208 @@ void CollisionPolygon2DEditor::_wip_close() {
 	edited_point = -1;
 }
 
-bool CollisionPolygon2DEditor::forward_gui_input(const InputEvent &p_event) {
+bool CollisionPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 	if (!node)
 		return false;
 
-	switch (p_event.type) {
+	Ref<InputEventMouseButton> mb;
 
-		case InputEvent::MOUSE_BUTTON: {
+	if (mb.is_valid()) {
+		Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
-			const InputEventMouseButton &mb = p_event.mouse_button;
+		Vector2 gpoint = mb->get_pos();
+		Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+		cpoint = canvas_item_editor->snap_point(cpoint);
+		cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
 
-			Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+		Vector<Vector2> poly = node->get_polygon();
 
-			Vector2 gpoint = Point2(mb.x, mb.y);
-			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-			cpoint = canvas_item_editor->snap_point(cpoint);
-			cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+		//first check if a point is to be added (segment split)
+		real_t grab_treshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
 
-			Vector<Vector2> poly = node->get_polygon();
+		switch (mode) {
 
-			//first check if a point is to be added (segment split)
-			real_t grab_treshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+			case MODE_CREATE: {
 
-			switch (mode) {
+				if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
 
-				case MODE_CREATE: {
+					if (!wip_active) {
 
-					if (mb.button_index == BUTTON_LEFT && mb.pressed) {
+						wip.clear();
+						wip.push_back(cpoint);
+						wip_active = true;
+						edited_point_pos = cpoint;
+						canvas_item_editor->get_viewport_control()->update();
+						edited_point = 1;
+						return true;
+					} else {
 
-						if (!wip_active) {
+						if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_treshold) {
+							//wip closed
+							_wip_close();
 
-							wip.clear();
-							wip.push_back(cpoint);
-							wip_active = true;
-							edited_point_pos = cpoint;
-							canvas_item_editor->get_viewport_control()->update();
-							edited_point = 1;
 							return true;
 						} else {
 
-							if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_treshold) {
-								//wip closed
-								_wip_close();
-
-								return true;
-							} else {
-
-								wip.push_back(cpoint);
-								edited_point = wip.size();
-								canvas_item_editor->get_viewport_control()->update();
-								return true;
+							wip.push_back(cpoint);
+							edited_point = wip.size();
+							canvas_item_editor->get_viewport_control()->update();
+							return true;
 
-								//add wip point
-							}
+							//add wip point
 						}
-					} else if (mb.button_index == BUTTON_RIGHT && mb.pressed && wip_active) {
-						_wip_close();
 					}
+				} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
+					_wip_close();
+				}
 
-				} break;
-
-				case MODE_EDIT: {
+			} break;
 
-					if (mb.button_index == BUTTON_LEFT) {
-						if (mb.pressed) {
+			case MODE_EDIT: {
 
-							if (mb.mod.control) {
+				if (mb->get_button_index() == BUTTON_LEFT) {
+					if (mb->is_pressed()) {
 
-								if (poly.size() < 3) {
+						if (mb->get_control()) {
 
-									undo_redo->create_action(TTR("Edit Poly"));
-									undo_redo->add_undo_method(node, "set_polygon", poly);
-									poly.push_back(cpoint);
-									undo_redo->add_do_method(node, "set_polygon", poly);
-									undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-									undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-									undo_redo->commit_action();
-									return true;
-								}
-
-								//search edges
-								int closest_idx = -1;
-								Vector2 closest_pos;
-								real_t closest_dist = 1e10;
-								for (int i = 0; i < poly.size(); i++) {
-
-									Vector2 points[2] = { xform.xform(poly[i]),
-										xform.xform(poly[(i + 1) % poly.size()]) };
-
-									Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
-									if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
-										continue; //not valid to reuse point
-
-									real_t d = cp.distance_to(gpoint);
-									if (d < closest_dist && d < grab_treshold) {
-										closest_dist = d;
-										closest_pos = cp;
-										closest_idx = i;
-									}
-								}
-
-								if (closest_idx >= 0) {
+							if (poly.size() < 3) {
 
-									pre_move_edit = poly;
-									poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
-									edited_point = closest_idx + 1;
-									edited_point_pos = xform.affine_inverse().xform(closest_pos);
-									node->set_polygon(poly);
-									canvas_item_editor->get_viewport_control()->update();
-									return true;
-								}
-							} else {
+								undo_redo->create_action(TTR("Edit Poly"));
+								undo_redo->add_undo_method(node, "set_polygon", poly);
+								poly.push_back(cpoint);
+								undo_redo->add_do_method(node, "set_polygon", poly);
+								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+								undo_redo->commit_action();
+								return true;
+							}
 
-								//look for points to move
+							//search edges
+							int closest_idx = -1;
+							Vector2 closest_pos;
+							real_t closest_dist = 1e10;
+							for (int i = 0; i < poly.size(); i++) {
 
-								int closest_idx = -1;
-								Vector2 closest_pos;
-								real_t closest_dist = 1e10;
-								for (int i = 0; i < poly.size(); i++) {
+								Vector2 points[2] = { xform.xform(poly[i]),
+									xform.xform(poly[(i + 1) % poly.size()]) };
 
-									Vector2 cp = xform.xform(poly[i]);
+								Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
+								if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
+									continue; //not valid to reuse point
 
-									real_t d = cp.distance_to(gpoint);
-									if (d < closest_dist && d < grab_treshold) {
-										closest_dist = d;
-										closest_pos = cp;
-										closest_idx = i;
-									}
+								real_t d = cp.distance_to(gpoint);
+								if (d < closest_dist && d < grab_treshold) {
+									closest_dist = d;
+									closest_pos = cp;
+									closest_idx = i;
 								}
+							}
 
-								if (closest_idx >= 0) {
+							if (closest_idx >= 0) {
 
-									pre_move_edit = poly;
-									edited_point = closest_idx;
-									edited_point_pos = xform.affine_inverse().xform(closest_pos);
-									canvas_item_editor->get_viewport_control()->update();
-									return true;
-								}
+								pre_move_edit = poly;
+								poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
+								edited_point = closest_idx + 1;
+								edited_point_pos = xform.affine_inverse().xform(closest_pos);
+								node->set_polygon(poly);
+								canvas_item_editor->get_viewport_control()->update();
+								return true;
 							}
 						} else {
 
-							if (edited_point != -1) {
+							//look for points to move
 
-								//apply
+							int closest_idx = -1;
+							Vector2 closest_pos;
+							real_t closest_dist = 1e10;
+							for (int i = 0; i < poly.size(); i++) {
 
-								ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
-								poly[edited_point] = edited_point_pos;
-								undo_redo->create_action(TTR("Edit Poly"));
-								undo_redo->add_do_method(node, "set_polygon", poly);
-								undo_redo->add_undo_method(node, "set_polygon", pre_move_edit);
-								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->commit_action();
+								Vector2 cp = xform.xform(poly[i]);
 
-								edited_point = -1;
-								return true;
+								real_t d = cp.distance_to(gpoint);
+								if (d < closest_dist && d < grab_treshold) {
+									closest_dist = d;
+									closest_pos = cp;
+									closest_idx = i;
+								}
 							}
-						}
-					} else if (mb.button_index == BUTTON_RIGHT && mb.pressed && edited_point == -1) {
-
-						int closest_idx = -1;
-						Vector2 closest_pos;
-						real_t closest_dist = 1e10;
-						for (int i = 0; i < poly.size(); i++) {
 
-							Vector2 cp = xform.xform(poly[i]);
+							if (closest_idx >= 0) {
 
-							real_t d = cp.distance_to(gpoint);
-							if (d < closest_dist && d < grab_treshold) {
-								closest_dist = d;
-								closest_pos = cp;
-								closest_idx = i;
+								pre_move_edit = poly;
+								edited_point = closest_idx;
+								edited_point_pos = xform.affine_inverse().xform(closest_pos);
+								canvas_item_editor->get_viewport_control()->update();
+								return true;
 							}
 						}
+					} else {
+
+						if (edited_point != -1) {
 
-						if (closest_idx >= 0) {
+							//apply
 
-							undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
-							undo_redo->add_undo_method(node, "set_polygon", poly);
-							poly.remove(closest_idx);
+							ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
+							poly[edited_point] = edited_point_pos;
+							undo_redo->create_action(TTR("Edit Poly"));
 							undo_redo->add_do_method(node, "set_polygon", poly);
+							undo_redo->add_undo_method(node, "set_polygon", pre_move_edit);
 							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
 							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
 							undo_redo->commit_action();
+
+							edited_point = -1;
 							return true;
 						}
 					}
+				} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
 
-				} break;
-			}
+					int closest_idx = -1;
+					Vector2 closest_pos;
+					real_t closest_dist = 1e10;
+					for (int i = 0; i < poly.size(); i++) {
 
-		} break;
-		case InputEvent::MOUSE_MOTION: {
+						Vector2 cp = xform.xform(poly[i]);
 
-			const InputEventMouseMotion &mm = p_event.mouse_motion;
+						real_t d = cp.distance_to(gpoint);
+						if (d < closest_dist && d < grab_treshold) {
+							closest_dist = d;
+							closest_pos = cp;
+							closest_idx = i;
+						}
+					}
 
-			if (edited_point != -1 && (wip_active || mm.button_mask & BUTTON_MASK_LEFT)) {
+					if (closest_idx >= 0) {
 
-				Vector2 gpoint = Point2(mm.x, mm.y);
-				Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-				cpoint = canvas_item_editor->snap_point(cpoint);
-				edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+						undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+						undo_redo->add_undo_method(node, "set_polygon", poly);
+						poly.remove(closest_idx);
+						undo_redo->add_do_method(node, "set_polygon", poly);
+						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->commit_action();
+						return true;
+					}
+				}
 
-				canvas_item_editor->get_viewport_control()->update();
-			}
+			} break;
+		}
+	}
 
-		} break;
+	Ref<InputEventMouseMotion> mm = p_event;
+
+	if (mm.is_valid()) {
+
+		if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) {
+
+			Vector2 gpoint = mm->get_pos();
+			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+			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();
+		}
 	}
 
 	return false;

+ 2 - 2
editor/plugins/collision_polygon_2d_editor_plugin.h

@@ -80,7 +80,7 @@ protected:
 	static void _bind_methods();
 
 public:
-	bool forward_gui_input(const InputEvent &p_event);
+	bool forward_gui_input(const Ref<InputEvent> &p_event);
 	void edit(Node *p_collision_polygon);
 	CollisionPolygon2DEditor(EditorNode *p_editor);
 };
@@ -93,7 +93,7 @@ class CollisionPolygon2DEditorPlugin : public EditorPlugin {
 	EditorNode *editor;
 
 public:
-	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
 
 	virtual String get_name() const { return "CollisionPolygon2D"; }
 	bool has_main_screen() const { return false; }

+ 8 - 8
editor/plugins/collision_polygon_editor_plugin.cpp

@@ -131,7 +131,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera* p_camera,const In
 
 
 
-			Vector2 gpoint=Point2(mb.x,mb.y);
+			Vector2 gpoint=Point2(mb->get_pos().x,mb->get_pos().y);
 			Vector3 ray_from = p_camera->project_ray_origin(gpoint);
 			Vector3 ray_dir = p_camera->project_ray_normal(gpoint);
 
@@ -156,7 +156,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera* p_camera,const In
 
 				case MODE_CREATE: {
 
-					if (mb.button_index==BUTTON_LEFT && mb.pressed) {
+					if (mb->get_button_index()==BUTTON_LEFT && mb->is_pressed()) {
 
 
 						if (!wip_active) {
@@ -186,7 +186,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera* p_camera,const In
 								//add wip point
 							}
 						}
-					} else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
+					} else if (mb->get_button_index()==BUTTON_RIGHT && mb->is_pressed() && wip_active) {
 						_wip_close();
 					}
 
@@ -196,10 +196,10 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera* p_camera,const In
 
 				case MODE_EDIT: {
 
-					if (mb.button_index==BUTTON_LEFT) {
-						if (mb.pressed) {
+					if (mb->get_button_index()==BUTTON_LEFT) {
+						if (mb->is_pressed()) {
 
-							if (mb.mod.control) {
+							if (mb->get_control()) {
 
 
 								if (poly.size() < 3) {
@@ -297,7 +297,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera* p_camera,const In
 								return true;
 							}
 						}
-					} if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+					} if (mb->get_button_index()==BUTTON_RIGHT && mb->is_pressed() && edited_point==-1) {
 
 
 
@@ -344,7 +344,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera* p_camera,const In
 
 			const InputEventMouseMotion &mm=p_event.mouse_motion;
 
-			if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+			if (edited_point!=-1 && (wip_active || mm->get_button_mask()&BUTTON_MASK_LEFT)) {
 
 				Vector2 gpoint = Point2(mm.x,mm.y);
 

+ 40 - 42
editor/plugins/collision_shape_2d_editor_plugin.cpp

@@ -302,7 +302,7 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
 	undo_redo->commit_action();
 }
 
-bool CollisionShape2DEditor::forward_gui_input(const InputEvent &p_event) {
+bool CollisionShape2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 	if (!node) {
 		return false;
@@ -316,68 +316,66 @@ bool CollisionShape2DEditor::forward_gui_input(const InputEvent &p_event) {
 		return false;
 	}
 
-	switch (p_event.type) {
-		case InputEvent::MOUSE_BUTTON: {
-			const InputEventMouseButton &mb = p_event.mouse_button;
+	Ref<InputEventMouseButton> mb = p_event;
 
-			Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+	if (mb.is_valid()) {
 
-			Point2 gpoint(mb.x, mb.y);
+		Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
-			if (mb.button_index == BUTTON_LEFT) {
-				if (mb.pressed) {
-					for (int i = 0; i < handles.size(); i++) {
-						if (gt.xform(handles[i]).distance_to(gpoint) < 8) {
-							edit_handle = i;
+		Point2 gpoint(mb->get_pos().x, mb->get_pos().y);
 
-							break;
-						}
+		if (mb->get_button_index() == BUTTON_LEFT) {
+			if (mb->is_pressed()) {
+				for (int i = 0; i < handles.size(); i++) {
+					if (gt.xform(handles[i]).distance_to(gpoint) < 8) {
+						edit_handle = i;
+
+						break;
 					}
+				}
 
-					if (edit_handle == -1) {
-						pressed = false;
+				if (edit_handle == -1) {
+					pressed = false;
 
-						return false;
-					}
+					return false;
+				}
 
-					original = get_handle_value(edit_handle);
-					pressed = true;
+				original = get_handle_value(edit_handle);
+				pressed = true;
 
-					return true;
+				return true;
 
-				} else {
-					if (pressed) {
-						commit_handle(edit_handle, original);
+			} else {
+				if (pressed) {
+					commit_handle(edit_handle, original);
 
-						edit_handle = -1;
-						pressed = false;
+					edit_handle = -1;
+					pressed = false;
 
-						return true;
-					}
+					return true;
 				}
 			}
+		}
 
-			return false;
-
-		} break;
+		return false;
+	}
 
-		case InputEvent::MOUSE_MOTION: {
-			const InputEventMouseMotion &mm = p_event.mouse_motion;
+	Ref<InputEventMouseMotion> mm = p_event;
 
-			if (edit_handle == -1 || !pressed) {
-				return false;
-			}
+	if (mm.is_valid()) {
 
-			Point2 gpoint = Point2(mm.x, mm.y);
-			Point2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-			cpoint = canvas_item_editor->snap_point(cpoint);
-			cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+		if (edit_handle == -1 || !pressed) {
+			return false;
+		}
 
-			set_handle(edit_handle, cpoint);
+		Point2 gpoint = mm->get_pos();
+		Point2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+		cpoint = canvas_item_editor->snap_point(cpoint);
+		cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
 
-			return true;
+		set_handle(edit_handle, cpoint);
 
-		} break;
+		return true;
 	}
 
 	return false;

+ 2 - 2
editor/plugins/collision_shape_2d_editor_plugin.h

@@ -74,7 +74,7 @@ protected:
 	static void _bind_methods();
 
 public:
-	bool forward_gui_input(const InputEvent &p_event);
+	bool forward_gui_input(const Ref<InputEvent> &p_event);
 	void edit(Node *p_node);
 
 	CollisionShape2DEditor(EditorNode *p_editor);
@@ -87,7 +87,7 @@ class CollisionShape2DEditorPlugin : public EditorPlugin {
 	EditorNode *editor;
 
 public:
-	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event) { return collision_shape_2d_editor->forward_gui_input(p_event); }
+	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_shape_2d_editor->forward_gui_input(p_event); }
 
 	virtual String get_name() const { return "CollisionShape2D"; }
 	bool has_main_screen() const { return false; }

+ 12 - 7
editor/plugins/curve_editor_plugin.cpp

@@ -33,9 +33,10 @@
 #include "os/keyboard.h"
 #include "spatial_editor_plugin.h"
 
-void CurveTextureEdit::_gui_input(const InputEvent &p_event) {
+void CurveTextureEdit::_gui_input(const Ref<InputEvent> &p_event) {
 
-	if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode == KEY_DELETE && grabbed != -1) {
+	Ref<InputEventKey> k = p_event;
+	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && grabbed != -1) {
 
 		points.remove(grabbed);
 		grabbed = -1;
@@ -44,7 +45,9 @@ void CurveTextureEdit::_gui_input(const InputEvent &p_event) {
 		accept_event();
 	}
 
-	if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed) {
+	Ref<InputEventMouseButton> mb = p_event;
+
+	if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
 
 		update();
 		Ref<Font> font = get_font("font", "Label");
@@ -54,7 +57,7 @@ void CurveTextureEdit::_gui_input(const InputEvent &p_event) {
 		Vector2 size = get_size();
 		size.y -= font_h;
 
-		Point2 p = Vector2(p_event.mouse_button.x, p_event.mouse_button.y) / size;
+		Point2 p = Vector2(mb->get_pos().x, mb->get_pos().y) / size;
 		p.y = CLAMP(1.0 - p.y, 0, 1) * (max - min) + min;
 		grabbed = -1;
 		grabbing = true;
@@ -90,7 +93,7 @@ void CurveTextureEdit::_gui_input(const InputEvent &p_event) {
 		emit_signal("curve_changed");
 	}
 
-	if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && !p_event.mouse_button.pressed) {
+	if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
 
 		if (grabbing) {
 			grabbing = false;
@@ -99,14 +102,16 @@ void CurveTextureEdit::_gui_input(const InputEvent &p_event) {
 		update();
 	}
 
-	if (p_event.type == InputEvent::MOUSE_MOTION && grabbing && grabbed != -1) {
+	Ref<InputEventMouseMotion> mm = p_event;
+
+	if (mm.is_valid() && grabbing && grabbed != -1) {
 
 		Ref<Font> font = get_font("font", "Label");
 		int font_h = font->get_height();
 		Vector2 size = get_size();
 		size.y -= font_h;
 
-		Point2 p = Vector2(p_event.mouse_motion.x, p_event.mouse_motion.y) / size;
+		Point2 p = mm->get_pos() / size;
 		p.y = CLAMP(1.0 - p.y, 0, 1) * (max - min) + min;
 		p.x = CLAMP(p.x, 0.0, 1.0);
 

+ 1 - 1
editor/plugins/curve_editor_plugin.h

@@ -54,7 +54,7 @@ class CurveTextureEdit : public Control {
 	void _plot_curve(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_c, const Vector2 &p_d);
 
 protected:
-	void _gui_input(const InputEvent &p_event);
+	void _gui_input(const Ref<InputEvent> &p_event);
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 19 - 14
editor/plugins/gradient_texture_editor_plugin.cpp

@@ -77,9 +77,11 @@ void GradientTextureEdit::_show_color_picker() {
 GradientTextureEdit::~GradientTextureEdit() {
 }
 
-void GradientTextureEdit::_gui_input(const InputEvent &p_event) {
+void GradientTextureEdit::_gui_input(const Ref<InputEvent> &p_event) {
 
-	if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode == KEY_DELETE && grabbed != -1) {
+	Ref<InputEventKey> k = p_event;
+
+	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && grabbed != -1) {
 
 		points.remove(grabbed);
 		grabbed = -1;
@@ -89,16 +91,17 @@ void GradientTextureEdit::_gui_input(const InputEvent &p_event) {
 		accept_event();
 	}
 
+	Ref<InputEventMouseButton> mb = p_event;
 	//Show color picker on double click.
-	if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.doubleclick && p_event.mouse_button.pressed) {
-		grabbed = _get_point_from_pos(p_event.mouse_button.x);
+	if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_doubleclick() && mb->is_pressed()) {
+		grabbed = _get_point_from_pos(mb->get_pos().x);
 		_show_color_picker();
 		accept_event();
 	}
 
 	//Delete point on right click
-	if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 2 && p_event.mouse_button.pressed) {
-		grabbed = _get_point_from_pos(p_event.mouse_button.x);
+	if (mb.is_valid() && mb->get_button_index() == 2 && mb->is_pressed()) {
+		grabbed = _get_point_from_pos(mb->get_pos().x);
 		if (grabbed != -1) {
 			points.remove(grabbed);
 			grabbed = -1;
@@ -110,9 +113,9 @@ void GradientTextureEdit::_gui_input(const InputEvent &p_event) {
 	}
 
 	//Hold alt key to duplicate selected color
-	if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed && p_event.key.mod.alt) {
+	if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->get_alt()) {
 
-		int x = p_event.mouse_button.x;
+		int x = mb->get_pos().x;
 		grabbed = _get_point_from_pos(x);
 
 		if (grabbed != -1) {
@@ -134,10 +137,10 @@ void GradientTextureEdit::_gui_input(const InputEvent &p_event) {
 		}
 	}
 
-	if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed) {
+	if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
 
 		update();
-		int x = p_event.mouse_button.x;
+		int x = mb->get_pos().x;
 		int total_w = get_size().width - get_size().height - 3;
 
 		//Check if color selector was clicked.
@@ -202,7 +205,7 @@ void GradientTextureEdit::_gui_input(const InputEvent &p_event) {
 		emit_signal("ramp_changed");
 	}
 
-	if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && !p_event.mouse_button.pressed) {
+	if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
 
 		if (grabbing) {
 			grabbing = false;
@@ -211,15 +214,17 @@ void GradientTextureEdit::_gui_input(const InputEvent &p_event) {
 		update();
 	}
 
-	if (p_event.type == InputEvent::MOUSE_MOTION && grabbing) {
+	Ref<InputEventMouseMotion> mm = p_event;
+
+	if (mm.is_valid() && grabbing) {
 
 		int total_w = get_size().width - get_size().height - 3;
 
-		int x = p_event.mouse_motion.x;
+		int x = mm->get_pos().x;
 		float newofs = CLAMP(x / float(total_w), 0, 1);
 
 		//Snap to nearest point if holding shift
-		if (p_event.key.mod.shift) {
+		if (mm->get_shift()) {
 			float snap_treshhold = 0.03;
 			float smallest_ofs = snap_treshhold;
 			bool founded = false;

+ 1 - 1
editor/plugins/gradient_texture_editor_plugin.h

@@ -53,7 +53,7 @@ class GradientTextureEdit : public Control {
 	void _show_color_picker();
 
 protected:
-	void _gui_input(const InputEvent &p_event);
+	void _gui_input(const Ref<InputEvent> &p_event);
 	void _notification(int p_what);
 	static void _bind_methods();
 

+ 150 - 152
editor/plugins/light_occluder_2d_editor_plugin.cpp

@@ -98,225 +98,223 @@ void LightOccluder2DEditor::_wip_close(bool p_closed) {
 	edited_point = -1;
 }
 
-bool LightOccluder2DEditor::forward_gui_input(const InputEvent &p_event) {
+bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 	if (!node)
 		return false;
 
 	if (node->get_occluder_polygon().is_null()) {
-		if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed) {
+		Ref<InputEventMouseButton> mb = p_event;
+		if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
 			create_poly->set_text("No OccluderPolygon2D resource on this node.\nCreate and assign one?");
 			create_poly->popup_centered_minsize();
 		}
-		return (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1);
+		return (mb.is_valid() && mb->get_button_index() == 1);
 	}
-	switch (p_event.type) {
 
-		case InputEvent::MOUSE_BUTTON: {
+	Ref<InputEventMouseButton> mb = p_event;
 
-			const InputEventMouseButton &mb = p_event.mouse_button;
+	if (mb.is_valid()) {
 
-			Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+		Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
-			Vector2 gpoint = Point2(mb.x, mb.y);
-			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-			cpoint = canvas_item_editor->snap_point(cpoint);
-			cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+		Vector2 gpoint = mb->get_pos();
+		Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+		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());
+		Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon());
 
-			//first check if a point is to be added (segment split)
-			real_t grab_treshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+		//first check if a point is to be added (segment split)
+		real_t grab_treshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
 
-			switch (mode) {
+		switch (mode) {
 
-				case MODE_CREATE: {
+			case MODE_CREATE: {
 
-					if (mb.button_index == BUTTON_LEFT && mb.pressed) {
+				if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
 
-						if (!wip_active) {
+					if (!wip_active) {
 
-							wip.clear();
-							wip.push_back(cpoint);
-							wip_active = true;
-							edited_point_pos = cpoint;
-							canvas_item_editor->get_viewport_control()->update();
-							edited_point = 1;
-							return true;
-						} else {
+						wip.clear();
+						wip.push_back(cpoint);
+						wip_active = true;
+						edited_point_pos = cpoint;
+						canvas_item_editor->get_viewport_control()->update();
+						edited_point = 1;
+						return true;
+					} else {
 
-							if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_treshold) {
-								//wip closed
-								_wip_close(true);
+						if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_treshold) {
+							//wip closed
+							_wip_close(true);
 
-								return true;
-							} else if (wip.size() > 1 && xform.xform(wip[wip.size() - 1]).distance_to(gpoint) < grab_treshold) {
-								//wip closed
-								_wip_close(false);
-								return true;
+							return true;
+						} else if (wip.size() > 1 && xform.xform(wip[wip.size() - 1]).distance_to(gpoint) < grab_treshold) {
+							//wip closed
+							_wip_close(false);
+							return true;
 
-							} else {
+						} else {
 
-								wip.push_back(cpoint);
-								edited_point = wip.size();
-								canvas_item_editor->get_viewport_control()->update();
-								return true;
+							wip.push_back(cpoint);
+							edited_point = wip.size();
+							canvas_item_editor->get_viewport_control()->update();
+							return true;
 
-								//add wip point
-							}
+							//add wip point
 						}
-					} else if (mb.button_index == BUTTON_RIGHT && mb.pressed && wip_active) {
-						_wip_close(true);
 					}
+				} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
+					_wip_close(true);
+				}
 
-				} break;
-
-				case MODE_EDIT: {
-
-					if (mb.button_index == BUTTON_LEFT) {
-						if (mb.pressed) {
-
-							if (mb.mod.control) {
+			} break;
 
-								if (poly.size() < 3) {
+			case MODE_EDIT: {
 
-									undo_redo->create_action(TTR("Edit Poly"));
-									undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", poly);
-									poly.push_back(cpoint);
-									undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly);
-									undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-									undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-									undo_redo->commit_action();
-									return true;
-								}
+				if (mb->get_button_index() == BUTTON_LEFT) {
+					if (mb->is_pressed()) {
 
-								//search edges
-								int closest_idx = -1;
-								Vector2 closest_pos;
-								real_t closest_dist = 1e10;
-								for (int i = 0; i < poly.size(); i++) {
-
-									Vector2 points[2] = { xform.xform(poly[i]),
-										xform.xform(poly[(i + 1) % poly.size()]) };
-
-									Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
-									if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
-										continue; //not valid to reuse point
-
-									real_t d = cp.distance_to(gpoint);
-									if (d < closest_dist && d < grab_treshold) {
-										closest_dist = d;
-										closest_pos = cp;
-										closest_idx = i;
-									}
-								}
+						if (mb->get_control()) {
 
-								if (closest_idx >= 0) {
+							if (poly.size() < 3) {
 
-									pre_move_edit = poly;
-									poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
-									edited_point = closest_idx + 1;
-									edited_point_pos = xform.affine_inverse().xform(closest_pos);
-									node->get_occluder_polygon()->set_polygon(Variant(poly));
-									canvas_item_editor->get_viewport_control()->update();
-									return true;
-								}
-							} else {
+								undo_redo->create_action(TTR("Edit Poly"));
+								undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", poly);
+								poly.push_back(cpoint);
+								undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly);
+								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+								undo_redo->commit_action();
+								return true;
+							}
 
-								//look for points to move
+							//search edges
+							int closest_idx = -1;
+							Vector2 closest_pos;
+							real_t closest_dist = 1e10;
+							for (int i = 0; i < poly.size(); i++) {
 
-								int closest_idx = -1;
-								Vector2 closest_pos;
-								real_t closest_dist = 1e10;
-								for (int i = 0; i < poly.size(); i++) {
+								Vector2 points[2] = { xform.xform(poly[i]),
+									xform.xform(poly[(i + 1) % poly.size()]) };
 
-									Vector2 cp = xform.xform(poly[i]);
+								Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
+								if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
+									continue; //not valid to reuse point
 
-									real_t d = cp.distance_to(gpoint);
-									if (d < closest_dist && d < grab_treshold) {
-										closest_dist = d;
-										closest_pos = cp;
-										closest_idx = i;
-									}
+								real_t d = cp.distance_to(gpoint);
+								if (d < closest_dist && d < grab_treshold) {
+									closest_dist = d;
+									closest_pos = cp;
+									closest_idx = i;
 								}
+							}
 
-								if (closest_idx >= 0) {
+							if (closest_idx >= 0) {
 
-									pre_move_edit = poly;
-									edited_point = closest_idx;
-									edited_point_pos = xform.affine_inverse().xform(closest_pos);
-									canvas_item_editor->get_viewport_control()->update();
-									return true;
-								}
+								pre_move_edit = poly;
+								poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
+								edited_point = closest_idx + 1;
+								edited_point_pos = xform.affine_inverse().xform(closest_pos);
+								node->get_occluder_polygon()->set_polygon(Variant(poly));
+								canvas_item_editor->get_viewport_control()->update();
+								return true;
 							}
 						} else {
 
-							if (edited_point != -1) {
+							//look for points to move
 
-								//apply
+							int closest_idx = -1;
+							Vector2 closest_pos;
+							real_t closest_dist = 1e10;
+							for (int i = 0; i < poly.size(); i++) {
 
-								ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
-								poly[edited_point] = edited_point_pos;
-								undo_redo->create_action(TTR("Edit Poly"));
-								undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly);
-								undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", pre_move_edit);
-								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->commit_action();
+								Vector2 cp = xform.xform(poly[i]);
 
-								edited_point = -1;
-								return true;
+								real_t d = cp.distance_to(gpoint);
+								if (d < closest_dist && d < grab_treshold) {
+									closest_dist = d;
+									closest_pos = cp;
+									closest_idx = i;
+								}
 							}
-						}
-					} else if (mb.button_index == BUTTON_RIGHT && mb.pressed && edited_point == -1) {
-
-						int closest_idx = -1;
-						Vector2 closest_pos;
-						real_t closest_dist = 1e10;
-						for (int i = 0; i < poly.size(); i++) {
 
-							Vector2 cp = xform.xform(poly[i]);
+							if (closest_idx >= 0) {
 
-							real_t d = cp.distance_to(gpoint);
-							if (d < closest_dist && d < grab_treshold) {
-								closest_dist = d;
-								closest_pos = cp;
-								closest_idx = i;
+								pre_move_edit = poly;
+								edited_point = closest_idx;
+								edited_point_pos = xform.affine_inverse().xform(closest_pos);
+								canvas_item_editor->get_viewport_control()->update();
+								return true;
 							}
 						}
+					} else {
+
+						if (edited_point != -1) {
 
-						if (closest_idx >= 0) {
+							//apply
 
-							undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
-							undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", poly);
-							poly.remove(closest_idx);
+							ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
+							poly[edited_point] = edited_point_pos;
+							undo_redo->create_action(TTR("Edit Poly"));
 							undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly);
+							undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", pre_move_edit);
 							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
 							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
 							undo_redo->commit_action();
+
+							edited_point = -1;
 							return true;
 						}
 					}
+				} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
 
-				} break;
-			}
+					int closest_idx = -1;
+					Vector2 closest_pos;
+					real_t closest_dist = 1e10;
+					for (int i = 0; i < poly.size(); i++) {
 
-		} break;
-		case InputEvent::MOUSE_MOTION: {
+						Vector2 cp = xform.xform(poly[i]);
 
-			const InputEventMouseMotion &mm = p_event.mouse_motion;
+						real_t d = cp.distance_to(gpoint);
+						if (d < closest_dist && d < grab_treshold) {
+							closest_dist = d;
+							closest_pos = cp;
+							closest_idx = i;
+						}
+					}
 
-			if (edited_point != -1 && (wip_active || mm.button_mask & BUTTON_MASK_LEFT)) {
+					if (closest_idx >= 0) {
 
-				Vector2 gpoint = Point2(mm.x, mm.y);
-				Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-				cpoint = canvas_item_editor->snap_point(cpoint);
-				edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+						undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+						undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", poly);
+						poly.remove(closest_idx);
+						undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly);
+						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->commit_action();
+						return true;
+					}
+				}
 
-				canvas_item_editor->get_viewport_control()->update();
-			}
+			} break;
+		}
+	}
 
-		} break;
+	Ref<InputEventMouseMotion> mm = p_event;
+
+	if (mm.is_valid()) {
+
+		if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) {
+
+			Vector2 gpoint = mm->get_pos();
+			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+			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();
+		}
 	}
 
 	return false;

+ 2 - 2
editor/plugins/light_occluder_2d_editor_plugin.h

@@ -84,7 +84,7 @@ protected:
 
 public:
 	Vector2 snap_point(const Vector2 &p_point) const;
-	bool forward_gui_input(const InputEvent &p_event);
+	bool forward_gui_input(const Ref<InputEvent> &p_event);
 	void edit(Node *p_collision_polygon);
 	LightOccluder2DEditor(EditorNode *p_editor);
 };
@@ -97,7 +97,7 @@ class LightOccluder2DEditorPlugin : public EditorPlugin {
 	EditorNode *editor;
 
 public:
-	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
 
 	virtual String get_name() const { return "LightOccluder2D"; }
 	bool has_main_screen() const { return false; }

+ 61 - 62
editor/plugins/line_2d_editor_plugin.cpp

@@ -75,7 +75,7 @@ int Line2DEditor::get_point_index_at(Vector2 gpos) {
 	return -1;
 }
 
-bool Line2DEditor::forward_gui_input(const InputEvent &p_event) {
+bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 	if (!node)
 		return false;
@@ -83,75 +83,74 @@ bool Line2DEditor::forward_gui_input(const InputEvent &p_event) {
 	if (!node->is_visible())
 		return false;
 
-	switch (p_event.type) {
-
-		case InputEvent::MOUSE_BUTTON: {
-
-			const InputEventMouseButton &mb = p_event.mouse_button;
-
-			Vector2 gpoint = Point2(mb.x, mb.y);
-			Vector2 cpoint = mouse_to_local_pos(gpoint, mb.mod.alt);
-
-			if (mb.pressed && _dragging == false) {
-				int i = get_point_index_at(gpoint);
-				if (i != -1) {
-					if (mb.button_index == BUTTON_LEFT && !mb.mod.shift && mode == MODE_EDIT) {
-						_dragging = true;
-						action_point = i;
-						moving_from = node->get_point_pos(i);
-						moving_screen_from = gpoint;
-					} else if ((mb.button_index == BUTTON_RIGHT && mode == MODE_EDIT) || (mb.button_index == BUTTON_LEFT && mode == MODE_DELETE)) {
-						undo_redo->create_action(TTR("Remove Point from Line2D"));
-						undo_redo->add_do_method(node, "remove_point", i);
-						undo_redo->add_undo_method(node, "add_point", node->get_point_pos(i), i);
-						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-						undo_redo->commit_action();
-					}
-					return true;
+	Ref<InputEventMouseButton> mb = p_event;
+
+	if (mb.is_valid()) {
+
+		Vector2 gpoint = mb->get_pos();
+		Vector2 cpoint = mouse_to_local_pos(gpoint, mb->get_alt());
+
+		if (mb->is_pressed() && _dragging == false) {
+			int i = get_point_index_at(gpoint);
+			if (i != -1) {
+				if (mb->get_button_index() == BUTTON_LEFT && !mb->get_shift() && mode == MODE_EDIT) {
+					_dragging = true;
+					action_point = i;
+					moving_from = node->get_point_pos(i);
+					moving_screen_from = gpoint;
+				} else if ((mb->get_button_index() == BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == BUTTON_LEFT && mode == MODE_DELETE)) {
+					undo_redo->create_action(TTR("Remove Point from Line2D"));
+					undo_redo->add_do_method(node, "remove_point", i);
+					undo_redo->add_undo_method(node, "add_point", node->get_point_pos(i), i);
+					undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+					undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+					undo_redo->commit_action();
 				}
+				return true;
 			}
+		}
 
-			if (mb.pressed && mb.button_index == BUTTON_LEFT && ((mb.mod.command && mode == MODE_EDIT) || mode == MODE_CREATE)) {
+		if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) {
 
-				undo_redo->create_action(TTR("Add Point to Line2D"));
-				undo_redo->add_do_method(node, "add_point", cpoint);
-				undo_redo->add_undo_method(node, "remove_point", node->get_point_count());
-				undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-				undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-				undo_redo->commit_action();
+			undo_redo->create_action(TTR("Add Point to Line2D"));
+			undo_redo->add_do_method(node, "add_point", cpoint);
+			undo_redo->add_undo_method(node, "remove_point", node->get_point_count());
+			undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+			undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+			undo_redo->commit_action();
 
-				_dragging = true;
-				action_point = node->get_point_count() - 1;
-				moving_from = node->get_point_pos(action_point);
-				moving_screen_from = gpoint;
+			_dragging = true;
+			action_point = node->get_point_count() - 1;
+			moving_from = node->get_point_pos(action_point);
+			moving_screen_from = gpoint;
 
-				canvas_item_editor->get_viewport_control()->update();
+			canvas_item_editor->get_viewport_control()->update();
 
-				return true;
-			}
+			return true;
+		}
 
-			if (!mb.pressed && mb.button_index == BUTTON_LEFT && _dragging) {
-				undo_redo->create_action(TTR("Move Point in Line2D"));
-				undo_redo->add_do_method(node, "set_point_pos", action_point, cpoint);
-				undo_redo->add_undo_method(node, "set_point_pos", action_point, moving_from);
-				undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-				undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-				undo_redo->commit_action();
-				_dragging = false;
-				return true;
-			}
-		} break;
-
-		case InputEvent::MOUSE_MOTION: {
-			if (_dragging) {
-				const InputEventMouseMotion &mm = p_event.mouse_motion;
-				Vector2 cpoint = mouse_to_local_pos(Vector2(mm.x, mm.y), mm.mod.alt);
-				node->set_point_pos(action_point, cpoint);
-				canvas_item_editor->get_viewport_control()->update();
-				return true;
-			}
-		} break;
+		if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && _dragging) {
+			undo_redo->create_action(TTR("Move Point in Line2D"));
+			undo_redo->add_do_method(node, "set_point_pos", action_point, cpoint);
+			undo_redo->add_undo_method(node, "set_point_pos", action_point, moving_from);
+			undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+			undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+			undo_redo->commit_action();
+			_dragging = false;
+			return true;
+		}
+	}
+
+	Ref<InputEventMouseMotion> mm = p_event;
+
+	if (mm.is_valid()) {
+
+		if (_dragging) {
+			Vector2 cpoint = mouse_to_local_pos(mm->get_pos(), mm->get_alt());
+			node->set_point_pos(action_point, cpoint);
+			canvas_item_editor->get_viewport_control()->update();
+			return true;
+		}
 	}
 
 	return false;

+ 2 - 2
editor/plugins/line_2d_editor_plugin.h

@@ -43,7 +43,7 @@ class Line2DEditor : public HBoxContainer {
 	GDCLASS(Line2DEditor, HBoxContainer)
 
 public:
-	bool forward_gui_input(const InputEvent &p_event);
+	bool forward_gui_input(const Ref<InputEvent> &p_event);
 	void edit(Node *p_line2d);
 	Line2DEditor(EditorNode *p_editor);
 
@@ -95,7 +95,7 @@ class Line2DEditorPlugin : public EditorPlugin {
 public:
 	virtual bool forward_canvas_gui_input(
 			const Transform2D &p_canvas_xform,
-			const InputEvent &p_event) {
+			const Ref<InputEvent> &p_event) {
 		return line2d_editor->forward_gui_input(p_event);
 	}
 

+ 3 - 3
editor/plugins/mesh_editor_plugin.cpp

@@ -33,10 +33,10 @@
 void MeshEditor::_gui_input(InputEvent p_event) {
 
 
-	if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
+	if (p_event.type==InputEvent::MOUSE_MOTION && p_event->get_button_mask()&BUTTON_MASK_LEFT) {
 
-		rot_x-=p_event.mouse_motion.relative_y*0.01;
-		rot_y-=p_event.mouse_motion.relative_x*0.01;
+		rot_x-=p_event->get_relative().y*0.01;
+		rot_y-=p_event->get_relative().x*0.01;
 		if (rot_x<-Math_PI/2)
 			rot_x=-Math_PI/2;
 		else if (rot_x>Math_PI/2) {

+ 180 - 181
editor/plugins/navigation_polygon_editor_plugin.cpp

@@ -112,263 +112,262 @@ void NavigationPolygonEditor::_wip_close() {
 	edited_point = -1;
 }
 
-bool NavigationPolygonEditor::forward_gui_input(const InputEvent &p_event) {
+bool NavigationPolygonEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 	if (!node)
 		return false;
 
 	if (node->get_navigation_polygon().is_null()) {
-		if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed) {
+
+		Ref<InputEventMouseButton> mb = p_event;
+
+		if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
 			create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?");
 			create_nav->popup_centered_minsize();
 		}
-		return (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1);
+		return (mb.is_valid() && mb->get_button_index() == 1);
 	}
 
-	switch (p_event.type) {
+	Ref<InputEventMouseButton> mb = p_event;
 
-		case InputEvent::MOUSE_BUTTON: {
+	if (mb.is_valid()) {
 
-			const InputEventMouseButton &mb = p_event.mouse_button;
+		Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
-			Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+		Vector2 gpoint = mb->get_pos();
+		Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+		cpoint = canvas_item_editor->snap_point(cpoint);
+		cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
 
-			Vector2 gpoint = Point2(mb.x, mb.y);
-			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-			cpoint = canvas_item_editor->snap_point(cpoint);
-			cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+		//first check if a point is to be added (segment split)
+		real_t grab_treshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
 
-			//first check if a point is to be added (segment split)
-			real_t grab_treshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+		switch (mode) {
 
-			switch (mode) {
+			case MODE_CREATE: {
 
-				case MODE_CREATE: {
+				if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
 
-					if (mb.button_index == BUTTON_LEFT && mb.pressed) {
+					if (!wip_active) {
 
-						if (!wip_active) {
+						wip.clear();
+						wip.push_back(cpoint);
+						wip_active = true;
+						edited_point_pos = cpoint;
+						edited_outline = -1;
+						canvas_item_editor->get_viewport_control()->update();
+						edited_point = 1;
+						return true;
+					} else {
+
+						if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_treshold) {
+							//wip closed
+							_wip_close();
 
-							wip.clear();
-							wip.push_back(cpoint);
-							wip_active = true;
-							edited_point_pos = cpoint;
-							edited_outline = -1;
-							canvas_item_editor->get_viewport_control()->update();
-							edited_point = 1;
 							return true;
 						} else {
 
-							if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_treshold) {
-								//wip closed
-								_wip_close();
-
-								return true;
-							} else {
-
-								wip.push_back(cpoint);
-								edited_point = wip.size();
-								canvas_item_editor->get_viewport_control()->update();
-								return true;
+							wip.push_back(cpoint);
+							edited_point = wip.size();
+							canvas_item_editor->get_viewport_control()->update();
+							return true;
 
-								//add wip point
-							}
+							//add wip point
 						}
-					} else if (mb.button_index == BUTTON_RIGHT && mb.pressed && wip_active) {
-						_wip_close();
 					}
+				} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
+					_wip_close();
+				}
 
-				} break;
+			} break;
 
-				case MODE_EDIT: {
+			case MODE_EDIT: {
 
-					if (mb.button_index == BUTTON_LEFT) {
-						if (mb.pressed) {
+				if (mb->get_button_index() == BUTTON_LEFT) {
+					if (mb->is_pressed()) {
 
-							if (mb.mod.control) {
+						if (mb->get_control()) {
 
-								//search edges
-								int closest_outline = -1;
-								int closest_idx = -1;
-								Vector2 closest_pos;
-								real_t closest_dist = 1e10;
+							//search edges
+							int closest_outline = -1;
+							int closest_idx = -1;
+							Vector2 closest_pos;
+							real_t closest_dist = 1e10;
 
-								for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
+							for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
 
-									PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
+								PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
 
-									int pc = points.size();
-									PoolVector<Vector2>::Read poly = points.read();
+								int pc = points.size();
+								PoolVector<Vector2>::Read poly = points.read();
 
-									for (int i = 0; i < pc; i++) {
+								for (int i = 0; i < pc; i++) {
 
-										Vector2 points[2] = { xform.xform(poly[i]),
-											xform.xform(poly[(i + 1) % pc]) };
+									Vector2 points[2] = { xform.xform(poly[i]),
+										xform.xform(poly[(i + 1) % pc]) };
 
-										Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
-										if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
-											continue; //not valid to reuse point
+									Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
+									if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
+										continue; //not valid to reuse point
 
-										real_t d = cp.distance_to(gpoint);
-										if (d < closest_dist && d < grab_treshold) {
-											closest_dist = d;
-											closest_outline = j;
-											closest_pos = cp;
-											closest_idx = i;
-										}
+									real_t d = cp.distance_to(gpoint);
+									if (d < closest_dist && d < grab_treshold) {
+										closest_dist = d;
+										closest_outline = j;
+										closest_pos = cp;
+										closest_idx = i;
 									}
 								}
+							}
 
-								if (closest_idx >= 0) {
-
-									pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline);
-									PoolVector<Point2> poly = pre_move_edit;
-									poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
-									edited_point = closest_idx + 1;
-									edited_outline = closest_outline;
-									edited_point_pos = xform.affine_inverse().xform(closest_pos);
-									node->get_navigation_polygon()->set_outline(closest_outline, poly);
-									canvas_item_editor->get_viewport_control()->update();
-									return true;
-								}
-							} else {
+							if (closest_idx >= 0) {
+
+								pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline);
+								PoolVector<Point2> poly = pre_move_edit;
+								poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
+								edited_point = closest_idx + 1;
+								edited_outline = closest_outline;
+								edited_point_pos = xform.affine_inverse().xform(closest_pos);
+								node->get_navigation_polygon()->set_outline(closest_outline, poly);
+								canvas_item_editor->get_viewport_control()->update();
+								return true;
+							}
+						} else {
 
-								//look for points to move
-								int closest_outline = -1;
-								int closest_idx = -1;
-								Vector2 closest_pos;
-								real_t closest_dist = 1e10;
+							//look for points to move
+							int closest_outline = -1;
+							int closest_idx = -1;
+							Vector2 closest_pos;
+							real_t closest_dist = 1e10;
 
-								for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
+							for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
 
-									PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
+								PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
 
-									int pc = points.size();
-									PoolVector<Vector2>::Read poly = points.read();
+								int pc = points.size();
+								PoolVector<Vector2>::Read poly = points.read();
 
-									for (int i = 0; i < pc; i++) {
+								for (int i = 0; i < pc; i++) {
 
-										Vector2 cp = xform.xform(poly[i]);
+									Vector2 cp = xform.xform(poly[i]);
 
-										real_t d = cp.distance_to(gpoint);
-										if (d < closest_dist && d < grab_treshold) {
-											closest_dist = d;
-											closest_pos = cp;
-											closest_outline = j;
-											closest_idx = i;
-										}
+									real_t d = cp.distance_to(gpoint);
+									if (d < closest_dist && d < grab_treshold) {
+										closest_dist = d;
+										closest_pos = cp;
+										closest_outline = j;
+										closest_idx = i;
 									}
 								}
+							}
 
-								if (closest_idx >= 0) {
+							if (closest_idx >= 0) {
 
-									pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline);
-									edited_point = closest_idx;
-									edited_outline = closest_outline;
-									edited_point_pos = xform.affine_inverse().xform(closest_pos);
-									canvas_item_editor->get_viewport_control()->update();
-									return true;
-								}
+								pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline);
+								edited_point = closest_idx;
+								edited_outline = closest_outline;
+								edited_point_pos = xform.affine_inverse().xform(closest_pos);
+								canvas_item_editor->get_viewport_control()->update();
+								return true;
 							}
-						} else {
+						}
+					} else {
 
-							if (edited_point != -1) {
+						if (edited_point != -1) {
 
-								//apply
+							//apply
 
-								PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(edited_outline);
-								ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
-								poly.set(edited_point, edited_point_pos);
-								undo_redo->create_action(TTR("Edit Poly"));
-								undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, poly);
-								undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, pre_move_edit);
-								undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
-								undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
-								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->commit_action();
+							PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(edited_outline);
+							ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
+							poly.set(edited_point, edited_point_pos);
+							undo_redo->create_action(TTR("Edit Poly"));
+							undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, poly);
+							undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, pre_move_edit);
+							undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
+							undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
+							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+							undo_redo->commit_action();
 
-								edited_point = -1;
-								return true;
-							}
+							edited_point = -1;
+							return true;
 						}
-					} else if (mb.button_index == BUTTON_RIGHT && mb.pressed && edited_point == -1) {
+					}
+				} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
 
-						int closest_outline = -1;
-						int closest_idx = -1;
-						Vector2 closest_pos;
-						real_t closest_dist = 1e10;
+					int closest_outline = -1;
+					int closest_idx = -1;
+					Vector2 closest_pos;
+					real_t closest_dist = 1e10;
 
-						for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
+					for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
 
-							PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
+						PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
 
-							int pc = points.size();
-							PoolVector<Vector2>::Read poly = points.read();
+						int pc = points.size();
+						PoolVector<Vector2>::Read poly = points.read();
 
-							for (int i = 0; i < pc; i++) {
+						for (int i = 0; i < pc; i++) {
 
-								Vector2 cp = xform.xform(poly[i]);
+							Vector2 cp = xform.xform(poly[i]);
 
-								real_t d = cp.distance_to(gpoint);
-								if (d < closest_dist && d < grab_treshold) {
-									closest_dist = d;
-									closest_pos = cp;
-									closest_outline = j;
-									closest_idx = i;
-								}
+							real_t d = cp.distance_to(gpoint);
+							if (d < closest_dist && d < grab_treshold) {
+								closest_dist = d;
+								closest_pos = cp;
+								closest_outline = j;
+								closest_idx = i;
 							}
 						}
+					}
 
-						if (closest_idx >= 0) {
-
-							PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(closest_outline);
-
-							if (poly.size() > 3) {
-								undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
-								undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly);
-								poly.remove(closest_idx);
-								undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly);
-								undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
-								undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
-								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->commit_action();
-							} else {
-
-								undo_redo->create_action(TTR("Remove Poly And Point"));
-								undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "add_outline_at_index", poly, closest_outline);
-								poly.remove(closest_idx);
-								undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "remove_outline", closest_outline);
-								undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
-								undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
-								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->commit_action();
-							}
-							return true;
+					if (closest_idx >= 0) {
+
+						PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(closest_outline);
+
+						if (poly.size() > 3) {
+							undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+							undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly);
+							poly.remove(closest_idx);
+							undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly);
+							undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
+							undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
+							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+							undo_redo->commit_action();
+						} else {
+
+							undo_redo->create_action(TTR("Remove Poly And Point"));
+							undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "add_outline_at_index", poly, closest_outline);
+							poly.remove(closest_idx);
+							undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "remove_outline", closest_outline);
+							undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
+							undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
+							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+							undo_redo->commit_action();
 						}
+						return true;
 					}
+				}
 
-				} break;
-			}
-
-		} break;
-		case InputEvent::MOUSE_MOTION: {
+			} break;
+		}
+	}
 
-			const InputEventMouseMotion &mm = p_event.mouse_motion;
+	Ref<InputEventMouseMotion> mm = p_event;
 
-			if (edited_point != -1 && (wip_active || mm.button_mask & BUTTON_MASK_LEFT)) {
+	if (mm.is_valid()) {
 
-				Vector2 gpoint = Point2(mm.x, mm.y);
-				Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-				cpoint = canvas_item_editor->snap_point(cpoint);
-				edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+		if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) {
 
-				canvas_item_editor->get_viewport_control()->update();
-			}
+			Vector2 gpoint = mm->get_pos();
+			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+			cpoint = canvas_item_editor->snap_point(cpoint);
+			edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
 
-		} break;
+			canvas_item_editor->get_viewport_control()->update();
+		}
 	}
 
 	return false;

+ 2 - 2
editor/plugins/navigation_polygon_editor_plugin.h

@@ -85,7 +85,7 @@ protected:
 	static void _bind_methods();
 
 public:
-	bool forward_gui_input(const InputEvent &p_event);
+	bool forward_gui_input(const Ref<InputEvent> &p_event);
 	void edit(Node *p_collision_polygon);
 	NavigationPolygonEditor(EditorNode *p_editor);
 };
@@ -98,7 +98,7 @@ class NavigationPolygonEditorPlugin : public EditorPlugin {
 	EditorNode *editor;
 
 public:
-	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
 
 	virtual String get_name() const { return "NavigationPolygonInstance"; }
 	bool has_main_screen() const { return false; }

+ 298 - 259
editor/plugins/path_2d_editor_plugin.cpp

@@ -58,7 +58,7 @@ void Path2DEditor::_node_removed(Node *p_node) {
 	}
 }
 
-bool Path2DEditor::forward_gui_input(const InputEvent &p_event) {
+bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 	if (!node)
 		return false;
@@ -69,279 +69,299 @@ bool Path2DEditor::forward_gui_input(const InputEvent &p_event) {
 	if (!node->get_curve().is_valid())
 		return false;
 
-	switch (p_event.type) {
+	Ref<InputEventMouseButton> mb = p_event;
 
-		case InputEvent::MOUSE_BUTTON: {
+	if (mb.is_valid()) {
 
-			const InputEventMouseButton &mb = p_event.mouse_button;
+		Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
-			Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
-			Vector2 gpoint = Point2(mb.x, mb.y);
-			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_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+		Vector2 gpoint = mb->get_pos();
+		Vector2 cpoint = !mb->get_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_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
 
-			// Test move point!!
+		// Test move point!!
 
-			if (mb.pressed && action == ACTION_NONE) {
+		if (mb->is_pressed() && action == ACTION_NONE) {
 
-				Ref<Curve2D> curve = node->get_curve();
+			Ref<Curve2D> curve = node->get_curve();
 
-				for (int i = 0; i < curve->get_point_count(); i++) {
+			for (int i = 0; i < curve->get_point_count(); i++) {
 
-					bool pointunder = false;
+				bool pointunder = false;
 
-					real_t dist_to_p = gpoint.distance_to(xform.xform(curve->get_point_pos(i)));
-					real_t dist_to_p_out = gpoint.distance_to(xform.xform(curve->get_point_pos(i) + curve->get_point_out(i)));
-					real_t dist_to_p_in = gpoint.distance_to(xform.xform(curve->get_point_pos(i) + curve->get_point_in(i)));
+				real_t dist_to_p = gpoint.distance_to(xform.xform(curve->get_point_pos(i)));
+				real_t dist_to_p_out = gpoint.distance_to(xform.xform(curve->get_point_pos(i) + curve->get_point_out(i)));
+				real_t dist_to_p_in = gpoint.distance_to(xform.xform(curve->get_point_pos(i) + curve->get_point_in(i)));
 
-					if (mb.button_index == BUTTON_LEFT && !mb.mod.shift && mode == MODE_EDIT) {
-						if (dist_to_p < grab_threshold) {
+				if (mb->get_button_index() == BUTTON_LEFT && !mb->get_shift() && mode == MODE_EDIT) {
+					if (dist_to_p < grab_threshold) {
 
-							action = ACTION_MOVING_POINT;
-							action_point = i;
-							moving_from = curve->get_point_pos(i);
-							moving_screen_from = gpoint;
-							return true;
-						}
+						action = ACTION_MOVING_POINT;
+						action_point = i;
+						moving_from = curve->get_point_pos(i);
+						moving_screen_from = gpoint;
+						return true;
 					}
+				}
 
-					if ((mb.button_index == BUTTON_RIGHT && mode == MODE_EDIT) || (mb.button_index == BUTTON_LEFT && mode == MODE_DELETE)) {
-						if (dist_to_p < grab_threshold) {
+				if ((mb->get_button_index() == BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == BUTTON_LEFT && mode == MODE_DELETE)) {
+					if (dist_to_p < grab_threshold) {
 
-							undo_redo->create_action(TTR("Remove Point from Curve"));
-							undo_redo->add_do_method(curve.ptr(), "remove_point", i);
-							undo_redo->add_undo_method(curve.ptr(), "add_point", curve->get_point_pos(i), curve->get_point_in(i), curve->get_point_out(i), i);
-							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-							undo_redo->commit_action();
-							return true;
-						} else if (dist_to_p_out < grab_threshold) {
+						undo_redo->create_action(TTR("Remove Point from Curve"));
+						undo_redo->add_do_method(curve.ptr(), "remove_point", i);
+						undo_redo->add_undo_method(curve.ptr(), "add_point", curve->get_point_pos(i), curve->get_point_in(i), curve->get_point_out(i), i);
+						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->commit_action();
+						return true;
+					} else if (dist_to_p_out < grab_threshold) {
 
-							undo_redo->create_action(TTR("Remove Out-Control from Curve"));
-							undo_redo->add_do_method(curve.ptr(), "set_point_out", i, Vector2());
-							undo_redo->add_undo_method(curve.ptr(), "set_point_out", i, curve->get_point_out(i));
-							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-							undo_redo->commit_action();
-							return true;
-						} else if (dist_to_p_in < grab_threshold) {
+						undo_redo->create_action(TTR("Remove Out-Control from Curve"));
+						undo_redo->add_do_method(curve.ptr(), "set_point_out", i, Vector2());
+						undo_redo->add_undo_method(curve.ptr(), "set_point_out", i, curve->get_point_out(i));
+						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->commit_action();
+						return true;
+					} else if (dist_to_p_in < grab_threshold) {
 
-							undo_redo->create_action(TTR("Remove In-Control from Curve"));
-							undo_redo->add_do_method(curve.ptr(), "set_point_in", i, Vector2());
-							undo_redo->add_undo_method(curve.ptr(), "set_point_in", i, curve->get_point_in(i));
-							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-							undo_redo->commit_action();
-							return true;
-						}
+						undo_redo->create_action(TTR("Remove In-Control from Curve"));
+						undo_redo->add_do_method(curve.ptr(), "set_point_in", i, Vector2());
+						undo_redo->add_undo_method(curve.ptr(), "set_point_in", i, curve->get_point_in(i));
+						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->commit_action();
+						return true;
 					}
+				}
 
-					if (dist_to_p < grab_threshold)
-						pointunder = true;
+				if (dist_to_p < grab_threshold)
+					pointunder = true;
 
-					if (mb.button_index == BUTTON_LEFT && i < (curve->get_point_count() - 1)) {
-						if (dist_to_p_out < grab_threshold && (mode == MODE_EDIT || mode == MODE_EDIT_CURVE)) {
+				if (mb->get_button_index() == BUTTON_LEFT && i < (curve->get_point_count() - 1)) {
+					if (dist_to_p_out < grab_threshold && (mode == MODE_EDIT || mode == MODE_EDIT_CURVE)) {
 
-							action = ACTION_MOVING_OUT;
-							action_point = i;
-							moving_from = curve->get_point_out(i);
-							moving_screen_from = gpoint;
-							return true;
-						}
-					}
-
-					if (mb.button_index == BUTTON_LEFT && i > 0) {
-						if (dist_to_p_in < grab_threshold && (mode == MODE_EDIT || mode == MODE_EDIT_CURVE)) {
-
-							action = ACTION_MOVING_IN;
-							action_point = i;
-							moving_from = curve->get_point_in(i);
-							moving_screen_from = gpoint;
-							return true;
-						}
-					}
+						action_point = i;
+						moving_from = curve->get_point_pos(i);
+						moving_screen_from = gpoint;
+						return true;
+					} else if ((mb->get_button_index() == BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == BUTTON_LEFT && mode == MODE_DELETE)) {
 
-					if (pointunder)
+						undo_redo->create_action(TTR("Remove Point from Curve"));
+						undo_redo->add_do_method(curve.ptr(), "remove_point", i);
+						undo_redo->add_undo_method(curve.ptr(), "add_point", curve->get_point_pos(i), curve->get_point_in(i), curve->get_point_out(i), i);
+						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->commit_action();
 						return true;
+					} else
+						pointunder = true;
+				}
+
+				if (pointunder)
+					return true;
+			}
+#if 0
+I think i broke this, was this not suposed to go somewhere?
+			if (mb->get_button_index() == BUTTON_LEFT && i < (curve->get_point_count() - 1)) {
+				Point2 p = xform.xform(curve->get_point_pos(i) + curve->get_point_out(i));
+				if (gpoint.distance_to(p) < grab_treshold && (mode == MODE_EDIT || mode == MODE_EDIT_CURVE)) {
+					action = ACTION_MOVING_OUT;
+					action_point = i;
+					moving_from = curve->get_point_out(i);
+					moving_screen_from = gpoint;
+					return true;
 				}
 			}
 
-			// Test add point in empty space!
+			if (mb->get_button_index() == BUTTON_LEFT && i > 0) {
+				Point2 p = xform.xform(curve->get_point_pos(i) + curve->get_point_in(i));
+				if (gpoint.distance_to(p) < grab_treshold && (mode == MODE_EDIT || mode == MODE_EDIT_CURVE)) {
 
-			if (mb.pressed && mb.button_index == BUTTON_LEFT && ((mb.mod.command && mode == MODE_EDIT) || mode == MODE_CREATE)) {
+					action = ACTION_MOVING_IN;
+					action_point = i;
+					moving_from = curve->get_point_in(i);
+					moving_screen_from = gpoint;
+					return true;
+				}
+			}
 
-				Ref<Curve2D> curve = node->get_curve();
+			if (pointunder)
+				return true;
+#endif
+		}
 
-				undo_redo->create_action(TTR("Add Point to Curve"));
-				undo_redo->add_do_method(curve.ptr(), "add_point", cpoint);
-				undo_redo->add_undo_method(curve.ptr(), "remove_point", curve->get_point_count());
-				undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-				undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-				undo_redo->commit_action();
+		// Test add point in empty space!
 
-				action = ACTION_MOVING_POINT;
-				action_point = curve->get_point_count() - 1;
-				moving_from = curve->get_point_pos(action_point);
-				moving_screen_from = gpoint;
+		if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && ((mb->get_command() && mode == MODE_EDIT) || mode == MODE_CREATE)) {
 
-				canvas_item_editor->get_viewport_control()->update();
+			Ref<Curve2D> curve = node->get_curve();
 
-				return true;
-			}
+			undo_redo->create_action(TTR("Add Point to Curve"));
+			undo_redo->add_do_method(curve.ptr(), "add_point", cpoint);
+			undo_redo->add_undo_method(curve.ptr(), "remove_point", curve->get_point_count());
+			undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+			undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+			undo_redo->commit_action();
 
-			if (!mb.pressed && mb.button_index == BUTTON_LEFT && action != ACTION_NONE) {
+			action = ACTION_MOVING_POINT;
+			action_point = curve->get_point_count() - 1;
+			moving_from = curve->get_point_pos(action_point);
+			moving_screen_from = gpoint;
 
-				Ref<Curve2D> curve = node->get_curve();
+			canvas_item_editor->get_viewport_control()->update();
 
-				Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
-				switch (action) {
+			return true;
+		}
 
-					case ACTION_MOVING_POINT: {
+		if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && action != ACTION_NONE) {
 
-						undo_redo->create_action(TTR("Move Point in Curve"));
-						undo_redo->add_do_method(curve.ptr(), "set_point_pos", action_point, cpoint);
-						undo_redo->add_undo_method(curve.ptr(), "set_point_pos", action_point, moving_from);
-						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-						undo_redo->commit_action();
+			Ref<Curve2D> curve = node->get_curve();
 
-					} break;
-					case ACTION_MOVING_IN: {
+			Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
+			switch (action) {
 
-						undo_redo->create_action(TTR("Move In-Control in Curve"));
-						undo_redo->add_do_method(curve.ptr(), "set_point_in", action_point, new_pos);
-						undo_redo->add_undo_method(curve.ptr(), "set_point_in", action_point, moving_from);
-						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-						undo_redo->commit_action();
+				case ACTION_MOVING_POINT: {
 
-					} break;
-					case ACTION_MOVING_OUT: {
+					undo_redo->create_action(TTR("Move Point in Curve"));
+					undo_redo->add_do_method(curve.ptr(), "set_point_pos", action_point, cpoint);
+					undo_redo->add_undo_method(curve.ptr(), "set_point_pos", action_point, moving_from);
+					undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+					undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+					undo_redo->commit_action();
 
-						undo_redo->create_action(TTR("Move Out-Control in Curve"));
-						undo_redo->add_do_method(curve.ptr(), "set_point_out", action_point, new_pos);
-						undo_redo->add_undo_method(curve.ptr(), "set_point_out", action_point, moving_from);
-						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-						undo_redo->commit_action();
+				} break;
+				case ACTION_MOVING_IN: {
 
-					} break;
-				}
+					undo_redo->create_action(TTR("Move In-Control in Curve"));
+					undo_redo->add_do_method(curve.ptr(), "set_point_in", action_point, new_pos);
+					undo_redo->add_undo_method(curve.ptr(), "set_point_in", action_point, moving_from);
+					undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+					undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+					undo_redo->commit_action();
 
-				action = ACTION_NONE;
+				} break;
+				case ACTION_MOVING_OUT: {
 
-				return true;
+					undo_redo->create_action(TTR("Move Out-Control in Curve"));
+					undo_redo->add_do_method(curve.ptr(), "set_point_out", action_point, new_pos);
+					undo_redo->add_undo_method(curve.ptr(), "set_point_out", action_point, moving_from);
+					undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+					undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+					undo_redo->commit_action();
+
+				} break;
 			}
 
-#if 0
-			switch(mode) {
+			action = ACTION_NONE;
 
+			return true;
+		}
 
-				case MODE_CREATE: {
+#if 0
+		switch(mode) {
 
-					if (mb.button_index==BUTTON_LEFT && mb.pressed) {
 
+			case MODE_CREATE: {
 
-						if (!wip_active) {
+				if (mb->get_button_index()==BUTTON_LEFT && mb->is_pressed()) {
 
-							wip.clear();
-							wip.push_back( canvas_item_editor->snap_point(cpoint) );
-							wip_active=true;
-							edited_point_pos=canvas_item_editor->snap_point(cpoint);
-							canvas_item_editor->update();
-							edited_point=1;
-							return true;
-						} else {
 
+					if (!wip_active) {
+
+						wip.clear();
+						wip.push_back( canvas_item_editor->snap_point(cpoint) );
+						wip_active=true;
+						edited_point_pos=canvas_item_editor->snap_point(cpoint);
+						canvas_item_editor->update();
+						edited_point=1;
+						return true;
+					} else {
 							if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_threshold) {
 								//wip closed
 								_wip_close();
+						if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
+							//wip closed
+							_wip_close();
 
-								return true;
-							} else {
 
-								wip.push_back( canvas_item_editor->snap_point(cpoint) );
-								edited_point=wip.size();
-								canvas_item_editor->update();
-								return true;
+							return true;
+						} else {
 
-								//add wip point
-							}
+							wip.push_back( canvas_item_editor->snap_point(cpoint) );
+							edited_point=wip.size();
+							canvas_item_editor->update();
+							return true;
+
+							//add wip point
 						}
-					} else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
-						_wip_close();
 					}
+				} else if (mb->get_button_index()==BUTTON_RIGHT && mb->is_pressed() && wip_active) {
+					_wip_close();
+				}
 
 
 
-				} break;
-
-				case MODE_EDIT: {
+			} break;
 
-					if (mb.button_index==BUTTON_LEFT) {
-						if (mb.pressed) {
+			case MODE_EDIT: {
 
-							if (mb.mod.control) {
+				if (mb->get_button_index()==BUTTON_LEFT) {
+					if (mb->is_pressed()) {
 
+						if (mb->get_control()) {
 
-								if (poly.size() < 3) {
-
-									undo_redo->create_action(TTR("Edit Poly"));
-									undo_redo->add_undo_method(node,"set_polygon",poly);
-									poly.push_back(cpoint);
-									undo_redo->add_do_method(node,"set_polygon",poly);
-									undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
-									undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
-									undo_redo->commit_action();
-									return true;
-								}
 
-								//search edges
-								int closest_idx=-1;
-								Vector2 closest_pos;
-								real_t closest_dist=1e10;
-								for(int i=0;i<poly.size();i++) {
+							if (poly.size() < 3) {
 
-									Vector2 points[2] ={ xform.xform(poly[i]),
-										xform.xform(poly[(i+1)%poly.size()]) };
+								undo_redo->create_action(TTR("Edit Poly"));
+								undo_redo->add_undo_method(node,"set_polygon",poly);
+								poly.push_back(cpoint);
+								undo_redo->add_do_method(node,"set_polygon",poly);
+								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+								undo_redo->commit_action();
+								return true;
+							}
 
-									Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
-									if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
-										continue; //not valid to reuse point
+							//search edges
+							int closest_idx=-1;
+							Vector2 closest_pos;
+							real_t closest_dist=1e10;
+							for(int i=0;i<poly.size();i++) {
 
-									real_t d = cp.distance_to(gpoint);
 									if (d<closest_dist && d<grab_threshold) {
 										closest_dist=d;
 										closest_pos=cp;
 										closest_idx=i;
 									}
 
+								Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
+								if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
+									continue; //not valid to reuse point
 
+								real_t d = cp.distance_to(gpoint);
+								if (d<closest_dist && d<grab_treshold) {
+									closest_dist=d;
+									closest_pos=cp;
+									closest_idx=i;
 								}
 
-								if (closest_idx>=0) {
-
-									pre_move_edit=poly;
-									poly.insert(closest_idx+1,canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos)));
-									edited_point=closest_idx+1;
-									edited_point_pos=canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos));
-									node->set_polygon(poly);
-									canvas_item_editor->update();
-									return true;
-								}
-							} else {
 
-								//look for points to move
+							}
 
-								int closest_idx=-1;
-								Vector2 closest_pos;
-								real_t closest_dist=1e10;
-								for(int i=0;i<poly.size();i++) {
+							if (closest_idx>=0) {
 
-									Vector2 cp =xform.xform(poly[i]);
+								pre_move_edit=poly;
+								poly.insert(closest_idx+1,canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos)));
+								edited_point=closest_idx+1;
+								edited_point_pos=canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos));
+								node->set_polygon(poly);
+								canvas_item_editor->update();
+								return true;
+							}
+						} else {
 
 									real_t d = cp.distance_to(gpoint);
 									if (d<closest_dist && d<grab_threshold) {
@@ -350,46 +370,51 @@ bool Path2DEditor::forward_gui_input(const InputEvent &p_event) {
 										closest_idx=i;
 									}
 
-								}
+							int closest_idx=-1;
+							Vector2 closest_pos;
+							real_t closest_dist=1e10;
+							for(int i=0;i<poly.size();i++) {
 
-								if (closest_idx>=0) {
+								Vector2 cp =xform.xform(poly[i]);
 
-									pre_move_edit=poly;
-									edited_point=closest_idx;
-									edited_point_pos=xform.affine_inverse().xform(closest_pos);
-									canvas_item_editor->update();
-									return true;
+								real_t d = cp.distance_to(gpoint);
+								if (d<closest_dist && d<grab_treshold) {
+									closest_dist=d;
+									closest_pos=cp;
+									closest_idx=i;
 								}
-							}
-						} else {
 
-							if (edited_point!=-1) {
+							}
 
-								//apply
+							if (closest_idx>=0) {
 
-								ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
-								poly[edited_point]=edited_point_pos;
-								undo_redo->create_action(TTR("Edit Poly"));
-								undo_redo->add_do_method(node,"set_polygon",poly);
-								undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
-								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
-								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
-								undo_redo->commit_action();
-
-								edited_point=-1;
+								pre_move_edit=poly;
+								edited_point=closest_idx;
+								edited_point_pos=xform.affine_inverse().xform(closest_pos);
+								canvas_item_editor->update();
 								return true;
 							}
 						}
-					} if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+					} else {
 
+						if (edited_point!=-1) {
 
+							//apply
 
-						int closest_idx=-1;
-						Vector2 closest_pos;
-						real_t closest_dist=1e10;
-						for(int i=0;i<poly.size();i++) {
+							ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
+							poly[edited_point]=edited_point_pos;
+							undo_redo->create_action(TTR("Edit Poly"));
+							undo_redo->add_do_method(node,"set_polygon",poly);
+							undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
+							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+							undo_redo->commit_action();
 
-							Vector2 cp =xform.xform(poly[i]);
+							edited_point=-1;
+							return true;
+						}
+					}
+				} if (mb->get_button_index()==BUTTON_RIGHT && mb->is_pressed() && edited_point==-1) {
 
 							real_t d = cp.distance_to(gpoint);
 							if (d<closest_dist && d<grab_threshold) {
@@ -398,79 +423,93 @@ bool Path2DEditor::forward_gui_input(const InputEvent &p_event) {
 								closest_idx=i;
 							}
 
+					int closest_idx=-1;
+					Vector2 closest_pos;
+					real_t closest_dist=1e10;
+					for(int i=0;i<poly.size();i++) {
+
+						Vector2 cp =xform.xform(poly[i]);
+
+						real_t d = cp.distance_to(gpoint);
+						if (d<closest_dist && d<grab_treshold) {
+							closest_dist=d;
+							closest_pos=cp;
+							closest_idx=i;
 						}
 
-						if (closest_idx>=0) {
+					}
 
+					if (closest_idx>=0) {
 
-							undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
-							undo_redo->add_undo_method(node,"set_polygon",poly);
-							poly.remove(closest_idx);
-							undo_redo->add_do_method(node,"set_polygon",poly);
-							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
-							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
-							undo_redo->commit_action();
-							return true;
-						}
 
+						undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+						undo_redo->add_undo_method(node,"set_polygon",poly);
+						poly.remove(closest_idx);
+						undo_redo->add_do_method(node,"set_polygon",poly);
+						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+						undo_redo->commit_action();
+						return true;
 					}
 
+				}
 
 
-				} break;
-			}
+
+			} break;
+		}
 
 #endif
-		} break;
-		case InputEvent::MOUSE_MOTION: {
+	}
 
-			const InputEventMouseMotion &mm = p_event.mouse_motion;
+	Ref<InputEventMouseMotion> mm = p_event;
 
-			if (action != ACTION_NONE) {
+	if (mm.is_valid()) {
 
-				Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-				Vector2 gpoint = Point2(mm.x, mm.y);
-				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)));
+		if (action != ACTION_NONE) {
 
-				Ref<Curve2D> curve = node->get_curve();
+			Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+			Vector2 gpoint = mm->get_pos();
+			Vector2 cpoint = !mm->get_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)));
 
-				Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
+			Ref<Curve2D> curve = node->get_curve();
 
-				switch (action) {
+			Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
 
-					case ACTION_MOVING_POINT: {
+			switch (action) {
 
-						curve->set_point_pos(action_point, cpoint);
-					} break;
-					case ACTION_MOVING_IN: {
+				case ACTION_MOVING_POINT: {
 
-						curve->set_point_in(action_point, new_pos);
+					curve->set_point_pos(action_point, cpoint);
+				} break;
+				case ACTION_MOVING_IN: {
 
-					} break;
-					case ACTION_MOVING_OUT: {
+					curve->set_point_in(action_point, new_pos);
 
-						curve->set_point_out(action_point, new_pos);
+				} break;
+				case ACTION_MOVING_OUT: {
 
-					} break;
-				}
+					curve->set_point_out(action_point, new_pos);
 
-				canvas_item_editor->get_viewport_control()->update();
-				return true;
+				} break;
 			}
 
+			canvas_item_editor->get_viewport_control()->update();
+			return true;
+		}
+
 #if 0
-			if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+		if (edited_point!=-1 && (wip_active || mm->get_button_mask()&BUTTON_MASK_LEFT)) {
 
 
-				Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+			Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
-				Vector2 gpoint = Point2(mm.x,mm.y);
-				edited_point_pos = canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint));
-				canvas_item_editor->update();
+			Vector2 gpoint = Point2(mm.x,mm.y);
+			edited_point_pos = canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint));
+			canvas_item_editor->update();
 
-			}
+		}
 #endif
-		} break;
 	}
 
 	return false;

+ 2 - 2
editor/plugins/path_2d_editor_plugin.h

@@ -95,7 +95,7 @@ protected:
 	static void _bind_methods();
 
 public:
-	bool forward_gui_input(const InputEvent &p_event);
+	bool forward_gui_input(const Ref<InputEvent> &p_event);
 	void edit(Node *p_path2d);
 	Path2DEditor(EditorNode *p_editor);
 };
@@ -108,7 +108,7 @@ class Path2DEditorPlugin : public EditorPlugin {
 	EditorNode *editor;
 
 public:
-	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event) { return path2d_editor->forward_gui_input(p_event); }
+	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return path2d_editor->forward_gui_input(p_event); }
 
 	virtual String get_name() const { return "Path2D"; }
 	bool has_main_screen() const { return false; }

+ 3 - 3
editor/plugins/path_editor_plugin.cpp

@@ -303,9 +303,9 @@ bool PathEditorPlugin::forward_spatial_gui_input(Camera* p_camera,const InputEve
 	if (p_event.type==InputEvent::MOUSE_BUTTON) {
 
 		const InputEventMouseButton &mb=p_event.mouse_button;
-		Point2 mbpos(mb.x,mb.y);
+		Point2 mbpos(mb->get_pos().x,mb->get_pos().y);
 
-		if (mb.pressed && mb.button_index==BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb.mod.control))) {
+		if (mb->is_pressed() && mb->get_button_index()==BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->get_control()))) {
 			//click into curve, break it down
 			Vector3Array v3a = c->tesselate();
 			int idx=0;
@@ -405,7 +405,7 @@ bool PathEditorPlugin::forward_spatial_gui_input(Camera* p_camera,const InputEve
 				//add new at pos
 			}
 
-		} else if (mb.pressed && ((mb.button_index==BUTTON_LEFT && curve_del->is_pressed()) || (mb.button_index==BUTTON_RIGHT && curve_edit->is_pressed()))) {
+		} else if (mb->is_pressed() && ((mb->get_button_index()==BUTTON_LEFT && curve_del->is_pressed()) || (mb->get_button_index()==BUTTON_RIGHT && curve_edit->is_pressed()))) {
 
 			for(int i=0;i<c->get_point_count();i++) {
 				real_t dist_to_p = p_camera->unproject_position(gt.xform(c->get_point_pos(i))).distance_to(mbpos);

+ 163 - 166
editor/plugins/polygon_2d_editor_plugin.cpp

@@ -201,213 +201,209 @@ void Polygon2DEditor::_wip_close() {
 	edited_point = -1;
 }
 
-bool Polygon2DEditor::forward_gui_input(const InputEvent &p_event) {
+bool Polygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 	if (node == NULL)
 		return false;
 
-	switch (p_event.type) {
+	Ref<InputEventMouseButton> mb = p_event;
 
-		case InputEvent::MOUSE_BUTTON: {
+	if (mb.is_valid()) {
 
-			const InputEventMouseButton &mb = p_event.mouse_button;
+		Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
-			Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+		Vector2 gpoint = mb->get_pos();
+		Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+		cpoint = canvas_item_editor->snap_point(cpoint);
+		cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
 
-			Vector2 gpoint = Point2(mb.x, mb.y);
-			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-			cpoint = canvas_item_editor->snap_point(cpoint);
-			cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+		Vector<Vector2> poly = Variant(node->get_polygon());
 
-			Vector<Vector2> poly = Variant(node->get_polygon());
+		//first check if a point is to be added (segment split)
+		real_t grab_treshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
 
-			//first check if a point is to be added (segment split)
-			real_t grab_treshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+		switch (mode) {
 
-			switch (mode) {
+			case MODE_CREATE: {
 
-				case MODE_CREATE: {
+				if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
 
-					if (mb.button_index == BUTTON_LEFT && mb.pressed) {
+					if (!wip_active) {
 
-						if (!wip_active) {
+						wip.clear();
+						wip.push_back(cpoint - node->get_offset());
+						wip_active = true;
+						edited_point_pos = cpoint;
+						canvas_item_editor->get_viewport_control()->update();
+						edited_point = 1;
+						return true;
+					} else {
+
+						if (wip.size() > 1 && xform.xform(wip[0] + node->get_offset()).distance_to(gpoint) < grab_treshold) {
+							//wip closed
+							_wip_close();
 
-							wip.clear();
-							wip.push_back(cpoint - node->get_offset());
-							wip_active = true;
-							edited_point_pos = cpoint;
-							canvas_item_editor->get_viewport_control()->update();
-							edited_point = 1;
 							return true;
 						} else {
 
-							if (wip.size() > 1 && xform.xform(wip[0] + node->get_offset()).distance_to(gpoint) < grab_treshold) {
-								//wip closed
-								_wip_close();
-
-								return true;
-							} else {
-
-								wip.push_back(cpoint - node->get_offset());
-								edited_point = wip.size();
-								canvas_item_editor->get_viewport_control()->update();
-								return true;
+							wip.push_back(cpoint - node->get_offset());
+							edited_point = wip.size();
+							canvas_item_editor->get_viewport_control()->update();
+							return true;
 
-								//add wip point
-							}
+							//add wip point
 						}
-					} else if (mb.button_index == BUTTON_RIGHT && mb.pressed && wip_active) {
-						_wip_close();
 					}
+				} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
+					_wip_close();
+				}
 
-				} break;
-
-				case MODE_EDIT: {
-
-					if (mb.button_index == BUTTON_LEFT) {
-						if (mb.pressed) {
-
-							if (mb.mod.control) {
+			} break;
 
-								if (poly.size() < 3) {
+			case MODE_EDIT: {
 
-									undo_redo->create_action(TTR("Edit Poly"));
-									undo_redo->add_undo_method(node, "set_polygon", poly);
-									poly.push_back(cpoint);
-									undo_redo->add_do_method(node, "set_polygon", poly);
-									undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-									undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-									undo_redo->commit_action();
-									return true;
-								}
+				if (mb->get_button_index() == BUTTON_LEFT) {
+					if (mb->is_pressed()) {
 
-								//search edges
-								int closest_idx = -1;
-								Vector2 closest_pos;
-								real_t closest_dist = 1e10;
-								for (int i = 0; i < poly.size(); i++) {
-
-									Vector2 points[2] = { xform.xform(poly[i] + node->get_offset()),
-										xform.xform(poly[(i + 1) % poly.size()] + node->get_offset()) };
-
-									Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
-									if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
-										continue; //not valid to reuse point
-
-									real_t d = cp.distance_to(gpoint);
-									if (d < closest_dist && d < grab_treshold) {
-										closest_dist = d;
-										closest_pos = cp;
-										closest_idx = i;
-									}
-								}
+						if (mb->get_control()) {
 
-								if (closest_idx >= 0) {
+							if (poly.size() < 3) {
 
-									pre_move_edit = poly;
-									poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos) - node->get_offset());
-									edited_point = closest_idx + 1;
-									edited_point_pos = xform.affine_inverse().xform(closest_pos);
-									node->set_polygon(Variant(poly));
-									canvas_item_editor->get_viewport_control()->update();
-									return true;
-								}
-							} else {
+								undo_redo->create_action(TTR("Edit Poly"));
+								undo_redo->add_undo_method(node, "set_polygon", poly);
+								poly.push_back(cpoint);
+								undo_redo->add_do_method(node, "set_polygon", poly);
+								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+								undo_redo->commit_action();
+								return true;
+							}
 
-								//look for points to move
+							//search edges
+							int closest_idx = -1;
+							Vector2 closest_pos;
+							real_t closest_dist = 1e10;
+							for (int i = 0; i < poly.size(); i++) {
 
-								int closest_idx = -1;
-								Vector2 closest_pos;
-								real_t closest_dist = 1e10;
-								for (int i = 0; i < poly.size(); i++) {
+								Vector2 points[2] = { xform.xform(poly[i] + node->get_offset()),
+									xform.xform(poly[(i + 1) % poly.size()] + node->get_offset()) };
 
-									Vector2 cp = xform.xform(poly[i] + node->get_offset());
+								Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
+								if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
+									continue; //not valid to reuse point
 
-									real_t d = cp.distance_to(gpoint);
-									if (d < closest_dist && d < grab_treshold) {
-										closest_dist = d;
-										closest_pos = cp;
-										closest_idx = i;
-									}
+								real_t d = cp.distance_to(gpoint);
+								if (d < closest_dist && d < grab_treshold) {
+									closest_dist = d;
+									closest_pos = cp;
+									closest_idx = i;
 								}
+							}
 
-								if (closest_idx >= 0) {
+							if (closest_idx >= 0) {
 
-									pre_move_edit = poly;
-									edited_point = closest_idx;
-									edited_point_pos = xform.affine_inverse().xform(closest_pos);
-									canvas_item_editor->get_viewport_control()->update();
-									return true;
-								}
+								pre_move_edit = poly;
+								poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos) - node->get_offset());
+								edited_point = closest_idx + 1;
+								edited_point_pos = xform.affine_inverse().xform(closest_pos);
+								node->set_polygon(Variant(poly));
+								canvas_item_editor->get_viewport_control()->update();
+								return true;
 							}
 						} else {
 
-							if (edited_point != -1) {
+							//look for points to move
 
-								//apply
+							int closest_idx = -1;
+							Vector2 closest_pos;
+							real_t closest_dist = 1e10;
+							for (int i = 0; i < poly.size(); i++) {
 
-								ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
-								poly[edited_point] = edited_point_pos - node->get_offset();
-								undo_redo->create_action(TTR("Edit Poly"));
-								undo_redo->add_do_method(node, "set_polygon", poly);
-								undo_redo->add_undo_method(node, "set_polygon", pre_move_edit);
-								undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
-								undo_redo->commit_action();
+								Vector2 cp = xform.xform(poly[i] + node->get_offset());
 
-								edited_point = -1;
-								return true;
+								real_t d = cp.distance_to(gpoint);
+								if (d < closest_dist && d < grab_treshold) {
+									closest_dist = d;
+									closest_pos = cp;
+									closest_idx = i;
+								}
 							}
-						}
-					} else if (mb.button_index == BUTTON_RIGHT && mb.pressed && edited_point == -1) {
 
-						int closest_idx = -1;
-						Vector2 closest_pos;
-						real_t closest_dist = 1e10;
-						for (int i = 0; i < poly.size(); i++) {
+							if (closest_idx >= 0) {
 
-							Vector2 cp = xform.xform(poly[i] + node->get_offset());
-
-							real_t d = cp.distance_to(gpoint);
-							if (d < closest_dist && d < grab_treshold) {
-								closest_dist = d;
-								closest_pos = cp;
-								closest_idx = i;
+								pre_move_edit = poly;
+								edited_point = closest_idx;
+								edited_point_pos = xform.affine_inverse().xform(closest_pos);
+								canvas_item_editor->get_viewport_control()->update();
+								return true;
 							}
 						}
+					} else {
+
+						if (edited_point != -1) {
 
-						if (closest_idx >= 0) {
+							//apply
 
-							undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
-							undo_redo->add_undo_method(node, "set_polygon", poly);
-							poly.remove(closest_idx);
+							ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
+							poly[edited_point] = edited_point_pos - node->get_offset();
+							undo_redo->create_action(TTR("Edit Poly"));
 							undo_redo->add_do_method(node, "set_polygon", poly);
+							undo_redo->add_undo_method(node, "set_polygon", pre_move_edit);
 							undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
 							undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
 							undo_redo->commit_action();
+
+							edited_point = -1;
 							return true;
 						}
 					}
+				} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
 
-				} break;
-			}
+					int closest_idx = -1;
+					Vector2 closest_pos;
+					real_t closest_dist = 1e10;
+					for (int i = 0; i < poly.size(); i++) {
 
-		} break;
-		case InputEvent::MOUSE_MOTION: {
+						Vector2 cp = xform.xform(poly[i] + node->get_offset());
 
-			const InputEventMouseMotion &mm = p_event.mouse_motion;
+						real_t d = cp.distance_to(gpoint);
+						if (d < closest_dist && d < grab_treshold) {
+							closest_dist = d;
+							closest_pos = cp;
+							closest_idx = i;
+						}
+					}
 
-			if (edited_point != -1 && (wip_active || mm.button_mask & BUTTON_MASK_LEFT)) {
+					if (closest_idx >= 0) {
 
-				Vector2 gpoint = Point2(mm.x, mm.y);
-				Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
-				cpoint = canvas_item_editor->snap_point(cpoint);
-				edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+						undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+						undo_redo->add_undo_method(node, "set_polygon", poly);
+						poly.remove(closest_idx);
+						undo_redo->add_do_method(node, "set_polygon", poly);
+						undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+						undo_redo->commit_action();
+						return true;
+					}
+				}
 
-				canvas_item_editor->get_viewport_control()->update();
-			}
+			} break;
+		}
+	}
 
-		} break;
+	Ref<InputEventMouseMotion> mm = p_event;
+
+	if (mm.is_valid()) {
+
+		if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) {
+
+			Vector2 gpoint = mm->get_pos();
+			Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+			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();
+		}
 	}
 
 	return false;
@@ -455,31 +451,31 @@ void Polygon2DEditor::_uv_mode(int p_mode) {
 	}
 }
 
-void Polygon2DEditor::_uv_input(const InputEvent &p_input) {
+void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
 
 	Transform2D mtx;
 	mtx.elements[2] = -uv_draw_ofs;
 	mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom));
 
-	if (p_input.type == InputEvent::MOUSE_BUTTON) {
+	Ref<InputEventMouseButton> mb = p_input;
 
-		const InputEventMouseButton &mb = p_input.mouse_button;
+	if (mb.is_valid()) {
 
-		if (mb.button_index == BUTTON_LEFT) {
+		if (mb->get_button_index() == BUTTON_LEFT) {
 
-			if (mb.pressed) {
+			if (mb->is_pressed()) {
 
-				uv_drag_from = Vector2(mb.x, mb.y);
+				uv_drag_from = Vector2(mb->get_pos().x, mb->get_pos().y);
 				uv_drag = true;
 				uv_prev = node->get_uv();
 				uv_move_current = uv_mode;
 				if (uv_move_current == UV_MODE_EDIT_POINT) {
 
-					if (mb.mod.shift && mb.mod.command)
+					if (mb->get_shift() && mb->get_command())
 						uv_move_current = UV_MODE_SCALE;
-					else if (mb.mod.shift)
+					else if (mb->get_shift())
 						uv_move_current = UV_MODE_MOVE;
-					else if (mb.mod.command)
+					else if (mb->get_command())
 						uv_move_current = UV_MODE_ROTATE;
 				}
 
@@ -489,7 +485,7 @@ void Polygon2DEditor::_uv_input(const InputEvent &p_input) {
 					for (int i = 0; i < uv_prev.size(); i++) {
 
 						Vector2 tuv = mtx.xform(uv_prev[i]);
-						if (tuv.distance_to(Vector2(mb.x, mb.y)) < 8) {
+						if (tuv.distance_to(Vector2(mb->get_pos().x, mb->get_pos().y)) < 8) {
 							uv_drag_from = tuv;
 							uv_drag_index = i;
 						}
@@ -511,7 +507,7 @@ void Polygon2DEditor::_uv_input(const InputEvent &p_input) {
 				uv_drag = false;
 			}
 
-		} else if (mb.button_index == BUTTON_RIGHT && mb.pressed) {
+		} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
 
 			if (uv_drag) {
 
@@ -520,27 +516,28 @@ void Polygon2DEditor::_uv_input(const InputEvent &p_input) {
 				uv_edit_draw->update();
 			}
 
-		} else if (mb.button_index == BUTTON_WHEEL_UP && mb.pressed) {
+		} else if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
 
-			uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * mb.factor)));
-		} else if (mb.button_index == BUTTON_WHEEL_DOWN && mb.pressed) {
+			uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * mb->get_factor())));
+		} else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) {
 
-			uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * mb.factor)));
+			uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * mb->get_factor())));
 		}
+	}
 
-	} else if (p_input.type == InputEvent::MOUSE_MOTION) {
+	Ref<InputEventMouseMotion> mm = p_input;
 
-		const InputEventMouseMotion &mm = p_input.mouse_motion;
+	if (mm.is_valid()) {
 
-		if (mm.button_mask & BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+		if (mm->get_button_mask() & BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
 
-			Vector2 drag(mm.relative_x, mm.relative_y);
+			Vector2 drag(mm->get_relative().x, mm->get_relative().y);
 			uv_hscroll->set_value(uv_hscroll->get_value() - drag.x);
 			uv_vscroll->set_value(uv_vscroll->get_value() - drag.y);
 
 		} else if (uv_drag) {
 
-			Vector2 uv_drag_to = snap_point(Vector2(mm.x, mm.y));
+			Vector2 uv_drag_to = mm->get_pos();
 			Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from);
 
 			switch (uv_move_current) {

+ 3 - 3
editor/plugins/polygon_2d_editor_plugin.h

@@ -113,7 +113,7 @@ class Polygon2DEditor : public HBoxContainer {
 	Vector2 snap_step;
 
 	void _uv_scroll_changed(float);
-	void _uv_input(const InputEvent &p_input);
+	void _uv_input(const Ref<InputEvent> &p_input);
 	void _uv_draw();
 	void _uv_mode(int p_mode);
 	void _wip_close();
@@ -135,7 +135,7 @@ protected:
 	Vector2 snap_point(Vector2 p_target) const;
 
 public:
-	bool forward_gui_input(const InputEvent &p_event);
+	bool forward_gui_input(const Ref<InputEvent> &p_event);
 	void edit(Node *p_collision_polygon);
 	Polygon2DEditor(EditorNode *p_editor);
 };
@@ -148,7 +148,7 @@ class Polygon2DEditorPlugin : public EditorPlugin {
 	EditorNode *editor;
 
 public:
-	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
 
 	virtual String get_name() const { return "Polygon2D"; }
 	bool has_main_screen() const { return false; }

+ 1 - 1
editor/plugins/resource_preloader_editor_plugin.cpp

@@ -33,7 +33,7 @@
 #include "global_config.h"
 #include "io/resource_loader.h"
 
-void ResourcePreloaderEditor::_gui_input(InputEvent p_event) {
+void ResourcePreloaderEditor::_gui_input(Ref<InputEvent> p_event) {
 }
 
 void ResourcePreloaderEditor::_notification(int p_what) {

+ 1 - 1
editor/plugins/resource_preloader_editor_plugin.h

@@ -70,7 +70,7 @@ class ResourcePreloaderEditor : public PanelContainer {
 
 protected:
 	void _notification(int p_what);
-	void _gui_input(InputEvent p_event);
+	void _gui_input(Ref<InputEvent> p_event);
 	static void _bind_methods();
 
 public:

+ 10 - 8
editor/plugins/script_editor_plugin.cpp

@@ -164,14 +164,16 @@ void ScriptEditorQuickOpen::_text_changed(const String &p_newtext) {
 	_update_search();
 }
 
-void ScriptEditorQuickOpen::_sbox_input(const InputEvent &p_ie) {
+void ScriptEditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) {
 
-	if (p_ie.type == InputEvent::KEY && (p_ie.key.scancode == KEY_UP ||
-												p_ie.key.scancode == KEY_DOWN ||
-												p_ie.key.scancode == KEY_PAGEUP ||
-												p_ie.key.scancode == KEY_PAGEDOWN)) {
+	Ref<InputEventKey> k = p_ie;
 
-		search_options->call("_gui_input", p_ie);
+	if (k.is_valid() && (k->get_scancode() == KEY_UP ||
+								k->get_scancode() == KEY_DOWN ||
+								k->get_scancode() == KEY_PAGEUP ||
+								k->get_scancode() == KEY_PAGEDOWN)) {
+
+		search_options->call("_gui_input", k);
 		search_box->accept_event();
 	}
 }
@@ -1778,8 +1780,8 @@ void ScriptEditor::_script_split_dragged(float) {
 	_save_layout();
 }
 
-void ScriptEditor::_unhandled_input(const InputEvent &p_event) {
-	if (p_event.key.pressed || !is_visible_in_tree()) return;
+void ScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
+	if (p_event->is_pressed() || !is_visible_in_tree()) return;
 	if (ED_IS_SHORTCUT("script_editor/next_script", p_event)) {
 		int next_tab = script_list->get_current() + 1;
 		next_tab %= script_list->get_item_count();

+ 2 - 2
editor/plugins/script_editor_plugin.h

@@ -54,7 +54,7 @@ class ScriptEditorQuickOpen : public ConfirmationDialog {
 
 	void _update_search();
 
-	void _sbox_input(const InputEvent &p_ie);
+	void _sbox_input(const Ref<InputEvent> &p_ie);
 	Vector<String> functions;
 
 	void _confirmed();
@@ -288,7 +288,7 @@ class ScriptEditor : public VBoxContainer {
 
 	void _script_split_dragged(float);
 
-	void _unhandled_input(const InputEvent &p_event);
+	void _unhandled_input(const Ref<InputEvent> &p_event);
 
 	void _help_search(String p_text);
 

+ 9 - 7
editor/plugins/script_text_editor.cpp

@@ -124,7 +124,6 @@ void ScriptTextEditor::_load_theme_settings() {
 	text_edit->add_keyword_color("Transform", basetype_color);
 	text_edit->add_keyword_color("Color", basetype_color);
 	text_edit->add_keyword_color("Image", basetype_color);
-	text_edit->add_keyword_color("InputEvent", basetype_color);
 	text_edit->add_keyword_color("Rect2", basetype_color);
 	text_edit->add_keyword_color("NodePath", basetype_color);
 
@@ -1227,15 +1226,18 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
 	}
 }
 
-void ScriptTextEditor::_text_edit_gui_input(const InputEvent &ev) {
-	if (ev.type == InputEvent::MOUSE_BUTTON) {
-		InputEventMouseButton mb = ev.mouse_button;
-		if (mb.button_index == BUTTON_RIGHT && !mb.pressed) {
+void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
+
+	Ref<InputEventMouseButton> mb = ev;
+
+	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(Point2i(mb.global_x, mb.global_y) - tx->get_global_position(), row, col);
-			Vector2 mpos = Vector2(mb.global_x, mb.global_y) - tx->get_global_position();
+			tx->_get_mouse_pos(mb->get_global_pos() - tx->get_global_position(), row, col);
+			Vector2 mpos = mb->get_global_pos() - tx->get_global_position();
 			bool have_selection = (tx->get_selection_text().length() > 0);
 			bool have_color = (tx->get_word_at_pos(mpos) == "Color");
 			if (have_color) {

+ 1 - 1
editor/plugins/script_text_editor.h

@@ -106,7 +106,7 @@ protected:
 
 	void _edit_option(int p_op);
 	void _make_context_menu(bool p_selection, bool p_color);
-	void _text_edit_gui_input(const InputEvent &ev);
+	void _text_edit_gui_input(const Ref<InputEvent> &ev);
 	void _color_changed(const Color &p_color);
 
 	void _goto_line(int p_line) { goto_line(p_line); }

+ 9 - 9
editor/plugins/shader_graph_editor_plugin.cpp

@@ -40,7 +40,7 @@
 
 void GraphColorRampEdit::_gui_input(const InputEvent& p_event) {
 
-	if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) {
+	if (p_event.type==InputEvent::KEY && p_event->is_pressed() && p_event->get_scancode()==KEY_DELETE && grabbed!=-1) {
 
 		points.remove(grabbed);
 		grabbed=-1;
@@ -49,10 +49,10 @@ void GraphColorRampEdit::_gui_input(const InputEvent& p_event) {
 		accept_event();
 	}
 
-	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
+	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event->get_button_index()==1 && p_event->is_pressed()) {
 
 		update();
-		int x = p_event.mouse_button.x;
+		int x = p_event->get_pos().x;
 		int total_w = get_size().width-get_size().height-3;
 		if (x>total_w+3) {
 
@@ -132,7 +132,7 @@ void GraphColorRampEdit::_gui_input(const InputEvent& p_event) {
 
 	}
 
-	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) {
+	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event->get_button_index()==1 && !p_event->is_pressed()) {
 
 		if (grabbing) {
 			grabbing=false;
@@ -319,7 +319,7 @@ GraphColorRampEdit::GraphColorRampEdit(){
 
 void GraphCurveMapEdit::_gui_input(const InputEvent& p_event) {
 
-	if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) {
+	if (p_event.type==InputEvent::KEY && p_event->is_pressed() && p_event->get_scancode()==KEY_DELETE && grabbed!=-1) {
 
 		points.remove(grabbed);
 		grabbed=-1;
@@ -328,10 +328,10 @@ void GraphCurveMapEdit::_gui_input(const InputEvent& p_event) {
 		accept_event();
 	}
 
-	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
+	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event->get_button_index()==1 && p_event->is_pressed()) {
 
 		update();
-		Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size();
+		Point2 p = Vector2(p_event->get_pos().x,p_event->get_pos().y)/get_size();
 		p.y=1.0-p.y;
 		grabbed=-1;
 		grabbing=true;
@@ -371,7 +371,7 @@ void GraphCurveMapEdit::_gui_input(const InputEvent& p_event) {
 
 	}
 
-	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) {
+	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event->get_button_index()==1 && !p_event->is_pressed()) {
 
 		if (grabbing) {
 			grabbing=false;
@@ -382,7 +382,7 @@ void GraphCurveMapEdit::_gui_input(const InputEvent& p_event) {
 
 	if (p_event.type==InputEvent::MOUSE_MOTION && grabbing  && grabbed != -1) {
 
-		Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size();
+		Point2 p = Vector2(p_event->get_pos().x,p_event->get_pos().y)/get_size();
 		p.y=1.0-p.y;
 
 		p.x = CLAMP(p.x,0.0,1.0);

File diff suppressed because it is too large
+ 601 - 599
editor/plugins/spatial_editor_plugin.cpp


+ 5 - 5
editor/plugins/spatial_editor_plugin.h

@@ -236,7 +236,7 @@ private:
 	void _draw();
 
 	void _smouseenter();
-	void _sinput(const InputEvent &p_ie);
+	void _sinput(const Ref<InputEvent> &p_ie);
 	void _update_freelook(real_t delta);
 	SpatialEditor *spatial_editor;
 
@@ -249,8 +249,8 @@ private:
 	void _finish_gizmo_instances();
 	void _selection_result_pressed(int);
 	void _selection_menu_hide();
-	void _list_select(InputEventMouseButton b);
-	Point2i _get_warped_mouse_motion(const InputEventMouseMotion &p_ev_mouse_motion) const;
+	void _list_select(Ref<InputEventMouseButton> b);
+	Point2i _get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const;
 
 protected:
 	void _notification(int p_what);
@@ -464,14 +464,14 @@ private:
 
 	void _update_ambient_light_color(const Color &p_color);
 	void _update_default_light_angle();
-	void _default_light_angle_input(const InputEvent &p_event);
+	void _default_light_angle_input(const Ref<InputEvent> &p_event);
 
 	bool is_any_freelook_active() const;
 
 protected:
 	void _notification(int p_what);
 	//void _gui_input(InputEvent p_event);
-	void _unhandled_key_input(InputEvent p_event);
+	void _unhandled_key_input(Ref<InputEvent> p_event);
 
 	static void _bind_methods();
 

+ 1 - 1
editor/plugins/sprite_frames_editor_plugin.cpp

@@ -34,7 +34,7 @@
 #include "io/resource_loader.h"
 #include "scene/3d/sprite_3d.h"
 
-void SpriteFramesEditor::_gui_input(InputEvent p_event) {
+void SpriteFramesEditor::_gui_input(Ref<InputEvent> p_event) {
 }
 
 void SpriteFramesEditor::_notification(int p_what) {

+ 1 - 1
editor/plugins/sprite_frames_editor_plugin.h

@@ -100,7 +100,7 @@ class SpriteFramesEditor : public PanelContainer {
 
 protected:
 	void _notification(int p_what);
-	void _gui_input(InputEvent p_event);
+	void _gui_input(Ref<InputEvent> p_event);
 	static void _bind_methods();
 
 public:

+ 1 - 1
editor/plugins/texture_editor_plugin.cpp

@@ -33,7 +33,7 @@
 #include "global_config.h"
 #include "io/resource_loader.h"
 
-void TextureEditor::_gui_input(InputEvent p_event) {
+void TextureEditor::_gui_input(Ref<InputEvent> p_event) {
 }
 
 void TextureEditor::_notification(int p_what) {

+ 1 - 1
editor/plugins/texture_editor_plugin.h

@@ -42,7 +42,7 @@ class TextureEditor : public Control {
 
 protected:
 	void _notification(int p_what);
-	void _gui_input(InputEvent p_event);
+	void _gui_input(Ref<InputEvent> p_event);
 	static void _bind_methods();
 
 public:

+ 27 - 26
editor/plugins/texture_region_editor_plugin.cpp

@@ -202,7 +202,7 @@ void TextureRegionEditor::_region_draw() {
 	}
 }
 
-void TextureRegionEditor::_region_input(const InputEvent &p_input) {
+void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
 	Transform2D mtx;
 	mtx.elements[2] = -draw_ofs;
 	mtx.scale_basis(Vector2(draw_zoom, draw_zoom));
@@ -218,13 +218,12 @@ void TextureRegionEditor::_region_input(const InputEvent &p_input) {
 		mtx.xform(rect.pos + Vector2(0, rect.size.y / 2)) + Vector2(-4, 0)
 	};
 
-	if (p_input.type == InputEvent::MOUSE_BUTTON) {
+	Ref<InputEventMouseButton> mb;
+	if (mb.is_valid()) {
 
-		const InputEventMouseButton &mb = p_input.mouse_button;
+		if (mb->get_button_index() == BUTTON_LEFT) {
 
-		if (mb.button_index == BUTTON_LEFT) {
-
-			if (mb.pressed) {
+			if (mb->is_pressed()) {
 				if (node_patch9 || obj_styleBox.is_valid()) {
 					edited_margin = -1;
 					float margins[4];
@@ -245,26 +244,26 @@ void TextureRegionEditor::_region_input(const InputEvent &p_input) {
 						mtx.basis_xform(rect.pos + Vector2(margins[2], 0)) - draw_ofs,
 						mtx.basis_xform(rect.pos + rect.size - Vector2(margins[3], 0)) - draw_ofs
 					};
-					if (Math::abs(mb.y - pos[0].y) < 8) {
+					if (Math::abs(mb->get_pos().y - pos[0].y) < 8) {
 						edited_margin = 0;
 						prev_margin = margins[0];
-					} else if (Math::abs(mb.y - pos[1].y) < 8) {
+					} else if (Math::abs(mb->get_pos().y - pos[1].y) < 8) {
 						edited_margin = 1;
 						prev_margin = margins[1];
-					} else if (Math::abs(mb.x - pos[2].x) < 8) {
+					} else if (Math::abs(mb->get_pos().x - pos[2].x) < 8) {
 						edited_margin = 2;
 						prev_margin = margins[2];
-					} else if (Math::abs(mb.x - pos[3].x) < 8) {
+					} else if (Math::abs(mb->get_pos().x - pos[3].x) < 8) {
 						edited_margin = 3;
 						prev_margin = margins[3];
 					}
 					if (edited_margin >= 0) {
-						drag_from = Vector2(mb.x, mb.y);
+						drag_from = Vector2(mb->get_pos().x, mb->get_pos().y);
 						drag = true;
 					}
 				}
 				if (edited_margin < 0 && snap_mode == SNAP_AUTOSLICE) {
-					Vector2 point = mtx.affine_inverse().xform(Vector2(mb.x, mb.y));
+					Vector2 point = mtx.affine_inverse().xform(Vector2(mb->get_pos().x, mb->get_pos().y));
 					for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) {
 						if (E->get().has_point(point)) {
 							rect = E->get();
@@ -302,7 +301,7 @@ void TextureRegionEditor::_region_input(const InputEvent &p_input) {
 						}
 					}
 				} else if (edited_margin < 0) {
-					drag_from = mtx.affine_inverse().xform(Vector2(mb.x, mb.y));
+					drag_from = mtx.affine_inverse().xform(Vector2(mb->get_pos().x, mb->get_pos().y));
 					if (snap_mode == SNAP_PIXEL)
 						drag_from = drag_from.snapped(Vector2(1, 1));
 					else if (snap_mode == SNAP_GRID)
@@ -319,7 +318,7 @@ void TextureRegionEditor::_region_input(const InputEvent &p_input) {
 
 					for (int i = 0; i < 8; i++) {
 						Vector2 tuv = endpoints[i];
-						if (tuv.distance_to(Vector2(mb.x, mb.y)) < 8) {
+						if (tuv.distance_to(Vector2(mb->get_pos().x, mb->get_pos().y)) < 8) {
 							drag_index = i;
 						}
 					}
@@ -369,7 +368,7 @@ void TextureRegionEditor::_region_input(const InputEvent &p_input) {
 				creating = false;
 			}
 
-		} else if (mb.button_index == BUTTON_RIGHT && mb.pressed) {
+		} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
 
 			if (drag) {
 				drag = false;
@@ -387,18 +386,20 @@ void TextureRegionEditor::_region_input(const InputEvent &p_input) {
 					drag_index = -1;
 				}
 			}
-		} else if (mb.button_index == BUTTON_WHEEL_UP && mb.pressed) {
+		} else if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
 			_zoom_in();
-		} else if (mb.button_index == BUTTON_WHEEL_DOWN && mb.pressed) {
+		} else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed()) {
 			_zoom_out();
 		}
-	} else if (p_input.type == InputEvent::MOUSE_MOTION) {
+	}
+
+	Ref<InputEventMouseMotion> mm = p_input;
 
-		const InputEventMouseMotion &mm = p_input.mouse_motion;
+	if (mm.is_valid()) {
 
-		if (mm.button_mask & BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+		if (mm->get_button_mask() & BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
 
-			Vector2 draged(mm.relative_x, mm.relative_y);
+			Vector2 draged(mm->get_relative().x, mm->get_relative().y);
 			hscroll->set_value(hscroll->get_value() - draged.x);
 			vscroll->set_value(vscroll->get_value() - draged.y);
 
@@ -407,13 +408,13 @@ void TextureRegionEditor::_region_input(const InputEvent &p_input) {
 			if (edited_margin >= 0) {
 				float new_margin;
 				if (edited_margin == 0)
-					new_margin = prev_margin + (mm.y - drag_from.y) / draw_zoom;
+					new_margin = prev_margin + (mm->get_pos().y - drag_from.y) / draw_zoom;
 				else if (edited_margin == 1)
-					new_margin = prev_margin - (mm.y - drag_from.y) / draw_zoom;
+					new_margin = prev_margin - (mm->get_pos().y - drag_from.y) / draw_zoom;
 				else if (edited_margin == 2)
-					new_margin = prev_margin + (mm.x - drag_from.x) / draw_zoom;
+					new_margin = prev_margin + (mm->get_pos().x - drag_from.x) / draw_zoom;
 				else if (edited_margin == 3)
-					new_margin = prev_margin - (mm.x - drag_from.x) / draw_zoom;
+					new_margin = prev_margin - (mm->get_pos().x - drag_from.x) / draw_zoom;
 				if (new_margin < 0)
 					new_margin = 0;
 				static Margin m[4] = { MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT };
@@ -422,7 +423,7 @@ void TextureRegionEditor::_region_input(const InputEvent &p_input) {
 				if (obj_styleBox.is_valid())
 					obj_styleBox->set_margin_size(m[edited_margin], new_margin);
 			} else {
-				Vector2 new_pos = mtx.affine_inverse().xform(Vector2(mm.x, mm.y));
+				Vector2 new_pos = mtx.affine_inverse().xform(mm->get_pos());
 				if (snap_mode == SNAP_PIXEL)
 					new_pos = new_pos.snapped(Vector2(1, 1));
 				else if (snap_mode == SNAP_GRID)

+ 1 - 1
editor/plugins/texture_region_editor_plugin.h

@@ -122,7 +122,7 @@ protected:
 public:
 	void _edit_region();
 	void _region_draw();
-	void _region_input(const InputEvent &p_input);
+	void _region_input(const Ref<InputEvent> &p_input);
 	void _scroll_changed(float);
 
 	void edit(Object *p_obj);

+ 300 - 303
editor/plugins/tile_map_editor_plugin.cpp

@@ -179,14 +179,16 @@ void TileMapEditor::_text_changed(const String &p_text) {
 	_update_palette();
 }
 
-void TileMapEditor::_sbox_input(const InputEvent &p_ie) {
+void TileMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
 
-	if (p_ie.type == InputEvent::KEY && (p_ie.key.scancode == KEY_UP ||
-												p_ie.key.scancode == KEY_DOWN ||
-												p_ie.key.scancode == KEY_PAGEUP ||
-												p_ie.key.scancode == KEY_PAGEDOWN)) {
+	Ref<InputEventKey> k = p_ie;
 
-		palette->call("_gui_input", p_ie);
+	if (k.is_valid() && (k->get_scancode() == KEY_UP ||
+								k->get_scancode() == KEY_DOWN ||
+								k->get_scancode() == KEY_PAGEUP ||
+								k->get_scancode() == KEY_PAGEDOWN)) {
+
+		palette->call("_gui_input", k);
 		search_box->accept_event();
 	}
 }
@@ -622,7 +624,7 @@ static inline Vector<Point2i> line(int x0, int x1, int y0, int y1) {
 	return points;
 }
 
-bool TileMapEditor::forward_gui_input(const InputEvent &p_event) {
+bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 	if (!node || !node->get_tileset().is_valid() || !node->is_visible_in_tree())
 		return false;
@@ -630,464 +632,459 @@ bool TileMapEditor::forward_gui_input(const InputEvent &p_event) {
 	Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
 	Transform2D xform_inv = xform.affine_inverse();
 
-	switch (p_event.type) {
-
-		case InputEvent::MOUSE_BUTTON: {
-
-			const InputEventMouseButton &mb = p_event.mouse_button;
-
-			if (mb.button_index == BUTTON_LEFT) {
+	Ref<InputEventMouseButton> mb = p_event;
 
-				if (mb.pressed) {
+	if (mb.is_valid()) {
+		if (mb->get_button_index() == BUTTON_LEFT) {
 
-					if (Input::get_singleton()->is_key_pressed(KEY_SPACE))
-						return false; //drag
+			if (mb->is_pressed()) {
 
-					if (tool == TOOL_NONE) {
+				if (Input::get_singleton()->is_key_pressed(KEY_SPACE))
+					return false; //drag
 
-						if (mb.mod.shift) {
+				if (tool == TOOL_NONE) {
 
-							if (mb.mod.control)
-								tool = TOOL_RECTANGLE_PAINT;
-							else
-								tool = TOOL_LINE_PAINT;
+					if (mb->get_shift()) {
 
-							selection_active = false;
-							rectangle_begin = over_tile;
+						if (mb->get_control())
+							tool = TOOL_RECTANGLE_PAINT;
+						else
+							tool = TOOL_LINE_PAINT;
 
-							return true;
-						}
+						selection_active = false;
+						rectangle_begin = over_tile;
 
-						if (mb.mod.control) {
+						return true;
+					}
 
-							tool = TOOL_PICKING;
-							_pick_tile(over_tile);
+					if (mb->get_control()) {
 
-							return true;
-						}
+						tool = TOOL_PICKING;
+						_pick_tile(over_tile);
 
-						tool = TOOL_PAINTING;
+						return true;
 					}
 
-					if (tool == TOOL_PAINTING) {
-
-						int id = get_selected_tile();
+					tool = TOOL_PAINTING;
+				}
 
-						if (id != TileMap::INVALID_CELL) {
+				if (tool == TOOL_PAINTING) {
 
-							tool = TOOL_PAINTING;
+					int id = get_selected_tile();
 
-							paint_undo.clear();
-							paint_undo[over_tile] = _get_op_from_cell(over_tile);
+					if (id != TileMap::INVALID_CELL) {
 
-							_set_cell(over_tile, id, flip_h, flip_v, transpose);
-						}
-					} else if (tool == TOOL_PICKING) {
+						tool = TOOL_PAINTING;
 
-						_pick_tile(over_tile);
-					} else if (tool == TOOL_SELECTING) {
+						paint_undo.clear();
+						paint_undo[over_tile] = _get_op_from_cell(over_tile);
 
-						selection_active = true;
-						rectangle_begin = over_tile;
+						_set_cell(over_tile, id, flip_h, flip_v, transpose);
 					}
+				} else if (tool == TOOL_PICKING) {
 
-					return true;
+					_pick_tile(over_tile);
+				} else if (tool == TOOL_SELECTING) {
 
-				} else {
+					selection_active = true;
+					rectangle_begin = over_tile;
+				}
+
+				return true;
 
-					if (tool != TOOL_NONE) {
+			} else {
 
-						if (tool == TOOL_PAINTING) {
+				if (tool != TOOL_NONE) {
 
-							int id = get_selected_tile();
+					if (tool == TOOL_PAINTING) {
 
-							if (id != TileMap::INVALID_CELL && paint_undo.size()) {
+						int id = get_selected_tile();
 
-								undo_redo->create_action(TTR("Paint TileMap"));
-								for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
+						if (id != TileMap::INVALID_CELL && paint_undo.size()) {
 
-									Point2 p = E->key();
-									undo_redo->add_do_method(node, "set_cellv", p, id, flip_h, flip_v, transpose);
-									undo_redo->add_undo_method(node, "set_cellv", p, E->get().idx, E->get().xf, E->get().yf, E->get().tr);
-								}
-								undo_redo->commit_action();
+							undo_redo->create_action(TTR("Paint TileMap"));
+							for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
 
-								paint_undo.clear();
+								Point2 p = E->key();
+								undo_redo->add_do_method(node, "set_cellv", p, id, flip_h, flip_v, transpose);
+								undo_redo->add_undo_method(node, "set_cellv", p, E->get().idx, E->get().xf, E->get().yf, E->get().tr);
 							}
-						} else if (tool == TOOL_LINE_PAINT) {
-
-							int id = get_selected_tile();
+							undo_redo->commit_action();
 
-							if (id != TileMap::INVALID_CELL) {
+							paint_undo.clear();
+						}
+					} else if (tool == TOOL_LINE_PAINT) {
 
-								undo_redo->create_action("Line Draw");
-								for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
+						int id = get_selected_tile();
 
-									_set_cell(E->key(), id, flip_h, flip_v, transpose, true);
-								}
-								undo_redo->commit_action();
+						if (id != TileMap::INVALID_CELL) {
 
-								paint_undo.clear();
+							undo_redo->create_action("Line Draw");
+							for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
 
-								canvas_item_editor->update();
+								_set_cell(E->key(), id, flip_h, flip_v, transpose, true);
 							}
-						} else if (tool == TOOL_RECTANGLE_PAINT) {
-
-							int id = get_selected_tile();
-
-							if (id != TileMap::INVALID_CELL) {
+							undo_redo->commit_action();
 
-								undo_redo->create_action("Rectangle Paint");
-								for (int i = rectangle.pos.y; i <= rectangle.pos.y + rectangle.size.y; i++) {
-									for (int j = rectangle.pos.x; j <= rectangle.pos.x + rectangle.size.x; j++) {
+							paint_undo.clear();
 
-										_set_cell(Point2i(j, i), id, flip_h, flip_v, transpose, true);
-									}
-								}
-								undo_redo->commit_action();
+							canvas_item_editor->update();
+						}
+					} else if (tool == TOOL_RECTANGLE_PAINT) {
 
-								canvas_item_editor->update();
-							}
-						} else if (tool == TOOL_DUPLICATING) {
+						int id = get_selected_tile();
 
-							Point2 ofs = over_tile - rectangle.pos;
+						if (id != TileMap::INVALID_CELL) {
 
-							undo_redo->create_action(TTR("Duplicate"));
-							for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) {
+							undo_redo->create_action("Rectangle Paint");
+							for (int i = rectangle.pos.y; i <= rectangle.pos.y + rectangle.size.y; i++) {
+								for (int j = rectangle.pos.x; j <= rectangle.pos.x + rectangle.size.x; j++) {
 
-								_set_cell(E->get().pos + ofs, E->get().cell, E->get().flip_h, E->get().flip_v, E->get().transpose, true);
+									_set_cell(Point2i(j, i), id, flip_h, flip_v, transpose, true);
+								}
 							}
 							undo_redo->commit_action();
 
-							copydata.clear();
-
 							canvas_item_editor->update();
+						}
+					} else if (tool == TOOL_DUPLICATING) {
 
-						} else if (tool == TOOL_SELECTING) {
+						Point2 ofs = over_tile - rectangle.pos;
 
-							canvas_item_editor->update();
+						undo_redo->create_action(TTR("Duplicate"));
+						for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) {
 
-						} else if (tool == TOOL_BUCKET) {
+							_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();
 
-							Dictionary pop;
-							pop["id"] = node->get_cell(over_tile.x, over_tile.y);
-							pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
-							pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
-							pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
+						copydata.clear();
+
+						canvas_item_editor->update();
 
-							PoolVector<Vector2> points = _bucket_fill(over_tile);
+					} else if (tool == TOOL_SELECTING) {
 
-							if (points.size() == 0)
-								return false;
+						canvas_item_editor->update();
 
-							Dictionary op;
-							op["id"] = get_selected_tile();
-							op["flip_h"] = flip_h;
-							op["flip_v"] = flip_v;
-							op["transpose"] = transpose;
+					} else if (tool == TOOL_BUCKET) {
 
-							undo_redo->create_action("Bucket Fill");
+						Dictionary pop;
+						pop["id"] = node->get_cell(over_tile.x, over_tile.y);
+						pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
+						pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
+						pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
 
-							undo_redo->add_do_method(this, "_fill_points", points, op);
-							undo_redo->add_undo_method(this, "_fill_points", points, pop);
+						PoolVector<Vector2> points = _bucket_fill(over_tile);
 
-							undo_redo->commit_action();
-						}
+						if (points.size() == 0)
+							return false;
 
-						tool = TOOL_NONE;
+						Dictionary op;
+						op["id"] = get_selected_tile();
+						op["flip_h"] = flip_h;
+						op["flip_v"] = flip_v;
+						op["transpose"] = transpose;
 
-						return true;
+						undo_redo->create_action("Bucket Fill");
+
+						undo_redo->add_do_method(this, "_fill_points", points, op);
+						undo_redo->add_undo_method(this, "_fill_points", points, pop);
+
+						undo_redo->commit_action();
 					}
-				}
-			} else if (mb.button_index == BUTTON_RIGHT) {
 
-				if (mb.pressed) {
+					tool = TOOL_NONE;
 
-					if (tool == TOOL_SELECTING || selection_active) {
+					return true;
+				}
+			}
+		} else if (mb->get_button_index() == BUTTON_RIGHT) {
 
-						tool = TOOL_NONE;
-						selection_active = false;
+			if (mb->is_pressed()) {
 
-						canvas_item_editor->update();
+				if (tool == TOOL_SELECTING || selection_active) {
 
-						return true;
-					}
+					tool = TOOL_NONE;
+					selection_active = false;
 
-					if (tool == TOOL_DUPLICATING) {
+					canvas_item_editor->update();
 
-						tool = TOOL_NONE;
-						copydata.clear();
+					return true;
+				}
 
-						canvas_item_editor->update();
+				if (tool == TOOL_DUPLICATING) {
 
-						return true;
-					}
+					tool = TOOL_NONE;
+					copydata.clear();
 
-					if (tool == TOOL_NONE) {
+					canvas_item_editor->update();
 
-						paint_undo.clear();
+					return true;
+				}
 
-						Point2 local = node->world_to_map(xform_inv.xform(Point2(mb.x, mb.y)));
+				if (tool == TOOL_NONE) {
 
-						if (mb.mod.shift) {
+					paint_undo.clear();
 
-							if (mb.mod.control)
-								tool = TOOL_RECTANGLE_ERASE;
-							else
-								tool = TOOL_LINE_ERASE;
+					Point2 local = node->world_to_map(xform_inv.xform(mb->get_pos()));
 
-							selection_active = false;
-							rectangle_begin = local;
-						} else {
+					if (mb->get_shift()) {
 
-							tool = TOOL_ERASING;
+						if (mb->get_control())
+							tool = TOOL_RECTANGLE_ERASE;
+						else
+							tool = TOOL_LINE_ERASE;
 
-							paint_undo[local] = _get_op_from_cell(local);
-							_set_cell(local, TileMap::INVALID_CELL);
-						}
+						selection_active = false;
+						rectangle_begin = local;
+					} else {
 
-						return true;
+						tool = TOOL_ERASING;
+
+						paint_undo[local] = _get_op_from_cell(local);
+						_set_cell(local, TileMap::INVALID_CELL);
 					}
 
-				} else {
-					if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
+					return true;
+				}
 
-						if (paint_undo.size()) {
-							undo_redo->create_action(TTR("Erase TileMap"));
-							for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
+			} else {
+				if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
 
-								Point2 p = E->key();
-								undo_redo->add_do_method(node, "set_cellv", p, TileMap::INVALID_CELL, false, false, false);
-								undo_redo->add_undo_method(node, "set_cellv", p, E->get().idx, E->get().xf, E->get().yf, E->get().tr);
-							}
+					if (paint_undo.size()) {
+						undo_redo->create_action(TTR("Erase TileMap"));
+						for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
 
-							undo_redo->commit_action();
-							paint_undo.clear();
+							Point2 p = E->key();
+							undo_redo->add_do_method(node, "set_cellv", p, TileMap::INVALID_CELL, false, false, false);
+							undo_redo->add_undo_method(node, "set_cellv", p, E->get().idx, E->get().xf, E->get().yf, E->get().tr);
 						}
 
-						if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
-							canvas_item_editor->update();
-						}
+						undo_redo->commit_action();
+						paint_undo.clear();
+					}
 
-						tool = TOOL_NONE;
+					if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
+						canvas_item_editor->update();
+					}
 
-						return true;
+					tool = TOOL_NONE;
 
-					} else if (tool == TOOL_BUCKET) {
+					return true;
 
-						Dictionary pop;
-						pop["id"] = node->get_cell(over_tile.x, over_tile.y);
-						pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
-						pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
-						pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
+				} else if (tool == TOOL_BUCKET) {
 
-						PoolVector<Vector2> points = _bucket_fill(over_tile, true);
+					Dictionary pop;
+					pop["id"] = node->get_cell(over_tile.x, over_tile.y);
+					pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
+					pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
+					pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
 
-						if (points.size() == 0)
-							return false;
+					PoolVector<Vector2> points = _bucket_fill(over_tile, true);
 
-						undo_redo->create_action("Bucket Fill");
+					if (points.size() == 0)
+						return false;
 
-						undo_redo->add_do_method(this, "_erase_points", points);
-						undo_redo->add_undo_method(this, "_fill_points", points, pop);
+					undo_redo->create_action("Bucket Fill");
 
-						undo_redo->commit_action();
-					}
+					undo_redo->add_do_method(this, "_erase_points", points);
+					undo_redo->add_undo_method(this, "_fill_points", points, pop);
+
+					undo_redo->commit_action();
 				}
 			}
-		} break;
-		case InputEvent::MOUSE_MOTION: {
+		}
+	}
 
-			const InputEventMouseMotion &mm = p_event.mouse_motion;
+	Ref<InputEventMouseMotion> mm = p_event;
 
-			Point2i new_over_tile = node->world_to_map(xform_inv.xform(Point2(mm.x, mm.y)));
+	if (mm.is_valid()) {
 
-			if (new_over_tile != over_tile) {
+		Point2i new_over_tile = node->world_to_map(xform_inv.xform(mm->get_pos()));
 
-				over_tile = new_over_tile;
-				canvas_item_editor->update();
-			}
+		if (new_over_tile != over_tile) {
 
-			int tile_under = node->get_cell(over_tile.x, over_tile.y);
-			String tile_name = "none";
+			over_tile = new_over_tile;
+			canvas_item_editor->update();
+		}
 
-			if (node->get_tileset()->has_tile(tile_under))
-				tile_name = node->get_tileset()->tile_get_name(tile_under);
-			tile_info->set_text(String::num(over_tile.x) + ", " + String::num(over_tile.y) + " [" + tile_name + "]");
+		int tile_under = node->get_cell(over_tile.x, over_tile.y);
+		String tile_name = "none";
 
-			if (tool == TOOL_PAINTING) {
+		if (node->get_tileset()->has_tile(tile_under))
+			tile_name = node->get_tileset()->tile_get_name(tile_under);
+		tile_info->set_text(String::num(over_tile.x) + ", " + String::num(over_tile.y) + " [" + tile_name + "]");
 
-				int id = get_selected_tile();
-				if (id != TileMap::INVALID_CELL) {
+		if (tool == TOOL_PAINTING) {
 
-					if (!paint_undo.has(over_tile)) {
-						paint_undo[over_tile] = _get_op_from_cell(over_tile);
-					}
-
-					_set_cell(over_tile, id, flip_h, flip_v, transpose);
+			int id = get_selected_tile();
+			if (id != TileMap::INVALID_CELL) {
 
-					return true;
+				if (!paint_undo.has(over_tile)) {
+					paint_undo[over_tile] = _get_op_from_cell(over_tile);
 				}
-			}
 
-			if (tool == TOOL_SELECTING) {
-
-				_select(rectangle_begin, over_tile);
+				_set_cell(over_tile, id, flip_h, flip_v, transpose);
 
 				return true;
 			}
+		}
 
-			if (tool == TOOL_LINE_PAINT || tool == TOOL_LINE_ERASE) {
+		if (tool == TOOL_SELECTING) {
 
-				int id = get_selected_tile();
-				bool erasing = (tool == TOOL_LINE_ERASE);
+			_select(rectangle_begin, over_tile);
 
-				if (erasing && paint_undo.size()) {
+			return true;
+		}
 
-					for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
+		if (tool == TOOL_LINE_PAINT || tool == TOOL_LINE_ERASE) {
 
-						_set_cell(E->key(), E->get().idx, E->get().xf, E->get().yf, E->get().tr);
-					}
-				}
+			int id = get_selected_tile();
+			bool erasing = (tool == TOOL_LINE_ERASE);
 
-				paint_undo.clear();
+			if (erasing && paint_undo.size()) {
+
+				for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
+
+					_set_cell(E->key(), E->get().idx, E->get().xf, E->get().yf, E->get().tr);
+				}
+			}
 
-				if (id != TileMap::INVALID_CELL) {
+			paint_undo.clear();
 
-					Vector<Point2i> points = line(rectangle_begin.x, over_tile.x, rectangle_begin.y, over_tile.y);
+			if (id != TileMap::INVALID_CELL) {
 
-					for (int i = 0; i < points.size(); i++) {
+				Vector<Point2i> points = line(rectangle_begin.x, over_tile.x, rectangle_begin.y, over_tile.y);
 
-						paint_undo[points[i]] = _get_op_from_cell(points[i]);
+				for (int i = 0; i < points.size(); i++) {
 
-						if (erasing)
-							_set_cell(points[i], TileMap::INVALID_CELL);
-					}
+					paint_undo[points[i]] = _get_op_from_cell(points[i]);
 
-					canvas_item_editor->update();
+					if (erasing)
+						_set_cell(points[i], TileMap::INVALID_CELL);
 				}
 
-				return true;
+				canvas_item_editor->update();
 			}
-			if (tool == TOOL_RECTANGLE_PAINT || tool == TOOL_RECTANGLE_ERASE) {
 
-				_select(rectangle_begin, over_tile);
+			return true;
+		}
+		if (tool == TOOL_RECTANGLE_PAINT || tool == TOOL_RECTANGLE_ERASE) {
 
-				if (tool == TOOL_RECTANGLE_ERASE) {
+			_select(rectangle_begin, over_tile);
 
-					if (paint_undo.size()) {
+			if (tool == TOOL_RECTANGLE_ERASE) {
 
-						for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
+				if (paint_undo.size()) {
 
-							_set_cell(E->key(), E->get().idx, E->get().xf, E->get().yf, E->get().tr);
-						}
+					for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
+
+						_set_cell(E->key(), E->get().idx, E->get().xf, E->get().yf, E->get().tr);
 					}
+				}
 
-					paint_undo.clear();
+				paint_undo.clear();
 
-					for (int i = rectangle.pos.y; i <= rectangle.pos.y + rectangle.size.y; i++) {
-						for (int j = rectangle.pos.x; j <= rectangle.pos.x + rectangle.size.x; j++) {
+				for (int i = rectangle.pos.y; i <= rectangle.pos.y + rectangle.size.y; i++) {
+					for (int j = rectangle.pos.x; j <= rectangle.pos.x + rectangle.size.x; j++) {
 
-							Point2i tile = Point2i(j, i);
-							paint_undo[tile] = _get_op_from_cell(tile);
+						Point2i tile = Point2i(j, i);
+						paint_undo[tile] = _get_op_from_cell(tile);
 
-							_set_cell(tile, TileMap::INVALID_CELL);
-						}
+						_set_cell(tile, TileMap::INVALID_CELL);
 					}
 				}
-
-				return true;
 			}
-			if (tool == TOOL_ERASING) {
-
-				if (!paint_undo.has(over_tile)) {
-					paint_undo[over_tile] = _get_op_from_cell(over_tile);
-				}
 
-				_set_cell(over_tile, TileMap::INVALID_CELL);
+			return true;
+		}
+		if (tool == TOOL_ERASING) {
 
-				return true;
+			if (!paint_undo.has(over_tile)) {
+				paint_undo[over_tile] = _get_op_from_cell(over_tile);
 			}
-			if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
 
-				_pick_tile(over_tile);
+			_set_cell(over_tile, TileMap::INVALID_CELL);
 
-				return true;
-			}
-		} break;
-		case InputEvent::KEY: {
+			return true;
+		}
+		if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
 
-			const InputEventKey &k = p_event.key;
+			_pick_tile(over_tile);
 
-			if (!k.pressed)
-				break;
+			return true;
+		}
+	}
 
-			if (k.scancode == KEY_ESCAPE) {
+	Ref<InputEventKey> k = p_event;
 
-				if (tool == TOOL_DUPLICATING)
-					copydata.clear();
-				else if (tool == TOOL_SELECTING || selection_active)
-					selection_active = false;
+	if (k.is_valid() && k->is_pressed()) {
 
-				tool = TOOL_NONE;
+		if (k->get_scancode() == KEY_ESCAPE) {
 
-				canvas_item_editor->update();
+			if (tool == TOOL_DUPLICATING)
+				copydata.clear();
+			else if (tool == TOOL_SELECTING || selection_active)
+				selection_active = false;
 
-				return true;
-			}
+			tool = TOOL_NONE;
 
-			if (tool != TOOL_NONE || !mouse_over)
-				return false;
+			canvas_item_editor->update();
 
-			if (ED_IS_SHORTCUT("tile_map_editor/erase_selection", p_event)) {
-				_menu_option(OPTION_ERASE_SELECTION);
+			return true;
+		}
 
-				return true;
-			}
-			if (ED_IS_SHORTCUT("tile_map_editor/select", p_event)) {
-				tool = TOOL_SELECTING;
-				selection_active = false;
+		if (tool != TOOL_NONE || !mouse_over)
+			return false;
 
-				canvas_item_editor->update();
+		if (ED_IS_SHORTCUT("tile_map_editor/erase_selection", p_event)) {
+			_menu_option(OPTION_ERASE_SELECTION);
 
-				return true;
-			}
-			if (ED_IS_SHORTCUT("tile_map_editor/duplicate_selection", p_event)) {
-				_update_copydata();
+			return true;
+		}
+		if (ED_IS_SHORTCUT("tile_map_editor/select", p_event)) {
+			tool = TOOL_SELECTING;
+			selection_active = false;
 
-				if (selection_active) {
-					tool = TOOL_DUPLICATING;
+			canvas_item_editor->update();
 
-					canvas_item_editor->update();
+			return true;
+		}
+		if (ED_IS_SHORTCUT("tile_map_editor/duplicate_selection", p_event)) {
+			_update_copydata();
 
-					return true;
-				}
-			}
-			if (ED_IS_SHORTCUT("tile_map_editor/find_tile", p_event)) {
-				search_box->select_all();
-				search_box->grab_focus();
+			if (selection_active) {
+				tool = TOOL_DUPLICATING;
 
-				return true;
-			}
-			if (ED_IS_SHORTCUT("tile_map_editor/mirror_x", p_event)) {
-				flip_h = !flip_h;
-				mirror_x->set_pressed(flip_h);
-				canvas_item_editor->update();
-				return true;
-			}
-			if (ED_IS_SHORTCUT("tile_map_editor/mirror_y", p_event)) {
-				flip_v = !flip_v;
-				mirror_y->set_pressed(flip_v);
-				canvas_item_editor->update();
-				return true;
-			}
-			if (ED_IS_SHORTCUT("tile_map_editor/transpose", p_event)) {
-				transpose = !transpose;
-				transp->set_pressed(transpose);
 				canvas_item_editor->update();
+
 				return true;
 			}
-		} break;
+		}
+		if (ED_IS_SHORTCUT("tile_map_editor/find_tile", p_event)) {
+			search_box->select_all();
+			search_box->grab_focus();
+
+			return true;
+		}
+		if (ED_IS_SHORTCUT("tile_map_editor/mirror_x", p_event)) {
+			flip_h = !flip_h;
+			mirror_x->set_pressed(flip_h);
+			canvas_item_editor->update();
+			return true;
+		}
+		if (ED_IS_SHORTCUT("tile_map_editor/mirror_y", p_event)) {
+			flip_v = !flip_v;
+			mirror_y->set_pressed(flip_v);
+			canvas_item_editor->update();
+			return true;
+		}
+		if (ED_IS_SHORTCUT("tile_map_editor/transpose", p_event)) {
+			transpose = !transpose;
+			transp->set_pressed(transpose);
+			canvas_item_editor->update();
+			return true;
+		}
 	}
 
 	return false;

+ 3 - 3
editor/plugins/tile_map_editor_plugin.h

@@ -158,7 +158,7 @@ class TileMapEditor : public VBoxContainer {
 
 	void _text_entered(const String &p_text);
 	void _text_changed(const String &p_text);
-	void _sbox_input(const InputEvent &p_ie);
+	void _sbox_input(const Ref<InputEvent> &p_ie);
 	void _update_palette();
 	void _canvas_draw();
 	void _menu_option(int p_option);
@@ -179,7 +179,7 @@ protected:
 public:
 	HBoxContainer *get_toolbar() const { return toolbar; }
 
-	bool forward_gui_input(const InputEvent &p_event);
+	bool forward_gui_input(const Ref<InputEvent> &p_event);
 	void edit(Node *p_tile_map);
 
 	TileMapEditor(EditorNode *p_editor);
@@ -193,7 +193,7 @@ class TileMapEditorPlugin : public EditorPlugin {
 	TileMapEditor *tile_map_editor;
 
 public:
-	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const InputEvent &p_event) { return tile_map_editor->forward_gui_input(p_event); }
+	virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return tile_map_editor->forward_gui_input(p_event); }
 
 	virtual String get_name() const { return "TileMap"; }
 	bool has_main_screen() const { return false; }

+ 17 - 15
editor/project_manager.cpp

@@ -503,14 +503,16 @@ void ProjectManager::_update_project_buttons() {
 	run_btn->set_disabled(!has_runnable_scene);
 }
 
-void ProjectManager::_panel_input(const InputEvent &p_ev, Node *p_hb) {
+void ProjectManager::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
 
-	if (p_ev.type == InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index == BUTTON_LEFT) {
+	Ref<InputEventMouseButton> mb = p_ev;
+
+	if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
 
 		String clicked = p_hb->get_meta("name");
 		String clicked_main_scene = p_hb->get_meta("main_scene");
 
-		if (p_ev.key.mod.shift && selected_list.size() > 0 && last_clicked != "" && clicked != last_clicked) {
+		if (mb->get_shift() && selected_list.size() > 0 && last_clicked != "" && clicked != last_clicked) {
 
 			int clicked_id = -1;
 			int last_clicked_id = -1;
@@ -527,7 +529,7 @@ void ProjectManager::_panel_input(const InputEvent &p_ev, Node *p_hb) {
 				for (int i = 0; i < scroll_childs->get_child_count(); ++i) {
 					HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
 					if (!hb) continue;
-					if (i != clicked_id && (i < min || i > max) && !p_ev.key.mod.control) {
+					if (i != clicked_id && (i < min || i > max) && !mb->get_control()) {
 						selected_list.erase(hb->get_meta("name"));
 					} else if (i >= min && i <= max) {
 						selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
@@ -535,14 +537,14 @@ void ProjectManager::_panel_input(const InputEvent &p_ev, Node *p_hb) {
 				}
 			}
 
-		} else if (selected_list.has(clicked) && p_ev.key.mod.control) {
+		} else if (selected_list.has(clicked) && mb->get_control()) {
 
 			selected_list.erase(clicked);
 
 		} else {
 
 			last_clicked = clicked;
-			if (p_ev.key.mod.control || selected_list.size() == 0) {
+			if (mb->get_control() || selected_list.size() == 0) {
 				selected_list.insert(clicked, clicked_main_scene);
 			} else {
 				selected_list.clear();
@@ -552,23 +554,23 @@ void ProjectManager::_panel_input(const InputEvent &p_ev, Node *p_hb) {
 
 		_update_project_buttons();
 
-		if (p_ev.mouse_button.doubleclick)
+		if (mb->is_doubleclick())
 			_open_project(); //open if doubleclicked
 	}
 }
 
-void ProjectManager::_unhandled_input(const InputEvent &p_ev) {
+void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
 
-	if (p_ev.type == InputEvent::KEY) {
+	Ref<InputEventKey> k = p_ev;
 
-		const InputEventKey &k = p_ev.key;
+	if (k.is_valid()) {
 
-		if (!k.pressed)
+		if (!k->is_pressed())
 			return;
 
 		bool scancode_handled = true;
 
-		switch (k.scancode) {
+		switch (k->get_scancode()) {
 
 			case KEY_RETURN: {
 
@@ -606,7 +608,7 @@ void ProjectManager::_unhandled_input(const InputEvent &p_ev) {
 			} break;
 			case KEY_UP: {
 
-				if (k.mod.shift)
+				if (k->get_shift())
 					break;
 
 				if (selected_list.size()) {
@@ -645,7 +647,7 @@ void ProjectManager::_unhandled_input(const InputEvent &p_ev) {
 			}
 			case KEY_DOWN: {
 
-				if (k.mod.shift)
+				if (k->get_shift())
 					break;
 
 				bool found = selected_list.empty();
@@ -679,7 +681,7 @@ void ProjectManager::_unhandled_input(const InputEvent &p_ev) {
 
 			} break;
 			case KEY_F: {
-				if (k.mod.command)
+				if (k->get_command())
 					this->project_filter->search_box->grab_focus();
 				else
 					scancode_handled = false;

+ 2 - 2
editor/project_manager.h

@@ -91,8 +91,8 @@ class ProjectManager : public Control {
 	void _install_project(const String &p_zip_path, const String &p_title);
 
 	void _panel_draw(Node *p_hb);
-	void _panel_input(const InputEvent &p_ev, Node *p_hb);
-	void _unhandled_input(const InputEvent &p_ev);
+	void _panel_input(const Ref<InputEvent> &p_ev, Node *p_hb);
+	void _unhandled_input(const Ref<InputEvent> &p_ev);
 	void _favorite_pressed(Node *p_hb);
 	void _files_dropped(PoolStringArray p_files, int p_screen);
 	void _scan_multiple_folders(PoolStringArray p_files);

+ 130 - 97
editor/project_settings.cpp

@@ -83,10 +83,10 @@ void ProjectSettings::_notification(int p_what) {
 
 			translation_list->connect("button_pressed", this, "_translation_delete");
 			_update_actions();
-			popup_add->add_icon_item(get_icon("Keyboard", "EditorIcons"), TTR("Key "), InputEvent::KEY); //"Key " - because the word 'key' has already been used as a key animation
-			popup_add->add_icon_item(get_icon("JoyButton", "EditorIcons"), TTR("Joy Button"), InputEvent::JOYPAD_BUTTON);
-			popup_add->add_icon_item(get_icon("JoyAxis", "EditorIcons"), TTR("Joy Axis"), InputEvent::JOYPAD_MOTION);
-			popup_add->add_icon_item(get_icon("Mouse", "EditorIcons"), TTR("Mouse Button"), InputEvent::MOUSE_BUTTON);
+			popup_add->add_icon_item(get_icon("Keyboard", "EditorIcons"), TTR("Key "), INPUT_KEY); //"Key " - because the word 'key' has already been used as a key animation
+			popup_add->add_icon_item(get_icon("JoyButton", "EditorIcons"), TTR("Joy Button"), INPUT_JOY_BUTTON);
+			popup_add->add_icon_item(get_icon("JoyAxis", "EditorIcons"), TTR("Joy Axis"), INPUT_JOY_MOTION);
+			popup_add->add_icon_item(get_icon("Mouse", "EditorIcons"), TTR("Mouse Button"), INPUT_MOUSE_BUTTON);
 
 			List<String> tfn;
 			ResourceLoader::get_recognized_extensions_for_type("Translation", &tfn);
@@ -178,54 +178,74 @@ void ProjectSettings::_action_edited() {
 
 void ProjectSettings::_device_input_add() {
 
-	InputEvent ie;
+	Ref<InputEvent> ie;
 	String name = add_at;
 	Variant old_val = GlobalConfig::get_singleton()->get(name);
 	Array arr = old_val;
-	ie.device = device_id->get_value();
-
-	ie.type = add_type;
+	//	ie.device = device_id->get_value();
+	//	ie.type = add_type;
 
 	switch (add_type) {
 
-		case InputEvent::MOUSE_BUTTON: {
+		case INPUT_MOUSE_BUTTON: {
 
-			ie.mouse_button.button_index = device_index->get_selected() + 1;
+			Ref<InputEventMouseButton> mb;
+			mb.instance();
+			mb->set_button_index(device_index->get_selected() + 1);
+			mb->set_device(device_id->get_value());
 
 			for (int i = 0; i < arr.size(); i++) {
 
-				InputEvent aie = arr[i];
-				if (aie.device == ie.device && aie.type == InputEvent::MOUSE_BUTTON && aie.mouse_button.button_index == ie.mouse_button.button_index) {
+				Ref<InputEventMouseButton> aie = arr[i];
+				if (aie.is_null())
+					continue;
+				if (aie->get_device() == mb->get_device() && aie->get_button_index() == mb->get_button_index()) {
 					return;
 				}
 			}
 
+			ie = mb;
+
 		} break;
-		case InputEvent::JOYPAD_MOTION: {
+		case INPUT_JOY_MOTION: {
 
-			ie.joy_motion.axis = device_index->get_selected() >> 1;
-			ie.joy_motion.axis_value = device_index->get_selected() & 1 ? 1 : -1;
+			Ref<InputEventJoypadMotion> jm;
+			jm.instance();
+			jm->set_axis(device_index->get_selected() >> 1);
+			jm->set_axis_value(device_index->get_selected() & 1 ? 1 : -1);
+			jm->set_device(device_id->get_value());
 
 			for (int i = 0; i < arr.size(); i++) {
 
-				InputEvent aie = arr[i];
-				if (aie.device == ie.device && aie.type == InputEvent::JOYPAD_MOTION && aie.joy_motion.axis == ie.joy_motion.axis && aie.joy_motion.axis_value == ie.joy_motion.axis_value) {
+				Ref<InputEventJoypadMotion> aie = arr[i];
+				if (aie.is_null())
+					continue;
+				if (aie->get_device() == jm->get_device() && aie->get_axis() == jm->get_axis() && aie->get_axis_value() == jm->get_axis_value()) {
 					return;
 				}
 			}
 
+			ie = jm;
+
 		} break;
-		case InputEvent::JOYPAD_BUTTON: {
+		case INPUT_JOY_BUTTON: {
 
-			ie.joy_button.button_index = device_index->get_selected();
+			Ref<InputEventJoypadButton> jb;
+			jb.instance();
+
+			jb->set_button_index(device_index->get_selected());
+			jb->set_device(device_id->get_value());
 
 			for (int i = 0; i < arr.size(); i++) {
 
-				InputEvent aie = arr[i];
-				if (aie.device == ie.device && aie.type == InputEvent::JOYPAD_BUTTON && aie.joy_button.button_index == ie.joy_button.button_index) {
+				Ref<InputEventJoypadButton> aie = arr[i];
+				if (aie.is_null())
+					continue;
+				if (aie->get_device() == jb->get_device() && aie->get_button_index() == jb->get_button_index()) {
 					return;
 				}
 			}
+			ie = jb;
 
 		} break;
 		default: {}
@@ -247,13 +267,17 @@ void ProjectSettings::_device_input_add() {
 
 void ProjectSettings::_press_a_key_confirm() {
 
-	if (last_wait_for_key.type != InputEvent::KEY)
+	if (last_wait_for_key.is_null())
 		return;
 
-	InputEvent ie;
-	ie.type = InputEvent::KEY;
-	ie.key.scancode = last_wait_for_key.key.scancode;
-	ie.key.mod = last_wait_for_key.key.mod;
+	Ref<InputEventKey> ie;
+	ie.instance();
+	ie->set_scancode(last_wait_for_key->get_scancode());
+	ie->set_shift(last_wait_for_key->get_shift());
+	ie->set_alt(last_wait_for_key->get_alt());
+	ie->set_control(last_wait_for_key->get_control());
+	ie->set_metakey(last_wait_for_key->get_metakey());
+
 	String name = add_at;
 
 	Variant old_val = GlobalConfig::get_singleton()->get(name);
@@ -261,8 +285,10 @@ void ProjectSettings::_press_a_key_confirm() {
 
 	for (int i = 0; i < arr.size(); i++) {
 
-		InputEvent aie = arr[i];
-		if (aie.type == InputEvent::KEY && aie.key.scancode == ie.key.scancode && aie.key.mod == ie.key.mod) {
+		Ref<InputEventKey> aie = arr[i];
+		if (aie.is_null())
+			continue;
+		if (aie->get_scancode_with_modifiers() == ie->get_scancode_with_modifiers()) {
 			return;
 		}
 	}
@@ -281,7 +307,7 @@ void ProjectSettings::_press_a_key_confirm() {
 	_show_last_added(ie, name);
 }
 
-void ProjectSettings::_show_last_added(const InputEvent &p_event, const String &p_name) {
+void ProjectSettings::_show_last_added(const Ref<InputEvent> &p_event, const String &p_name) {
 	TreeItem *r = input_editor->get_root();
 
 	String name = p_name;
@@ -314,19 +340,21 @@ void ProjectSettings::_show_last_added(const InputEvent &p_event, const String &
 	if (found) input_editor->ensure_cursor_is_visible();
 }
 
-void ProjectSettings::_wait_for_key(const InputEvent &p_event) {
+void ProjectSettings::_wait_for_key(const Ref<InputEvent> &p_event) {
+
+	Ref<InputEventKey> k = p_event;
 
-	if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode != 0) {
+	if (k.is_valid() && k->is_pressed() && k->get_scancode() != 0) {
 
 		last_wait_for_key = p_event;
-		String str = keycode_get_string(p_event.key.scancode).capitalize();
-		if (p_event.key.mod.meta)
+		String str = keycode_get_string(k->get_scancode()).capitalize();
+		if (k->get_metakey())
 			str = TTR("Meta+") + str;
-		if (p_event.key.mod.shift)
+		if (k->get_shift())
 			str = TTR("Shift+") + str;
-		if (p_event.key.mod.alt)
+		if (k->get_alt())
 			str = TTR("Alt+") + str;
-		if (p_event.key.mod.control)
+		if (k->get_control())
 			str = TTR("Control+") + str;
 
 		press_a_key_label->set_text(str);
@@ -336,18 +364,18 @@ void ProjectSettings::_wait_for_key(const InputEvent &p_event) {
 
 void ProjectSettings::_add_item(int p_item) {
 
-	add_type = InputEvent::Type(p_item);
+	add_type = InputType(p_item);
 
 	switch (add_type) {
 
-		case InputEvent::KEY: {
+		case INPUT_KEY: {
 
 			press_a_key_label->set_text(TTR("Press a Key.."));
-			last_wait_for_key = InputEvent();
+			last_wait_for_key = Ref<InputEvent>();
 			press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
 			press_a_key->grab_focus();
 		} break;
-		case InputEvent::MOUSE_BUTTON: {
+		case INPUT_MOUSE_BUTTON: {
 
 			device_id->set_value(0);
 			device_index_label->set_text(TTR("Mouse Button Index:"));
@@ -363,7 +391,7 @@ void ProjectSettings::_add_item(int p_item) {
 			device_index->add_item(TTR("Button 9"));
 			device_input->popup_centered_minsize(Size2(350, 95));
 		} break;
-		case InputEvent::JOYPAD_MOTION: {
+		case INPUT_JOY_MOTION: {
 
 			device_id->set_value(0);
 			device_index_label->set_text(TTR("Joypad Axis Index:"));
@@ -376,7 +404,7 @@ void ProjectSettings::_add_item(int p_item) {
 			device_input->popup_centered_minsize(Size2(350, 95));
 
 		} break;
-		case InputEvent::JOYPAD_BUTTON: {
+		case INPUT_JOY_BUTTON: {
 
 			device_id->set_value(0);
 			device_index_label->set_text(TTR("Joypad Button Index:"));
@@ -496,65 +524,70 @@ void ProjectSettings::_update_actions() {
 
 		for (int i = 0; i < actions.size(); i++) {
 
-			if (actions[i].get_type() != Variant::INPUT_EVENT)
+			Ref<InputEvent> ie = actions[i];
+			if (ie.is_null())
 				continue;
-			InputEvent ie = actions[i];
 
 			TreeItem *action = input_editor->create_item(item);
 
-			switch (ie.type) {
-
-				case InputEvent::KEY: {
-
-					String str = keycode_get_string(ie.key.scancode).capitalize();
-					if (ie.key.mod.meta)
-						str = TTR("Meta+") + str;
-					if (ie.key.mod.shift)
-						str = TTR("Shift+") + str;
-					if (ie.key.mod.alt)
-						str = TTR("Alt+") + str;
-					if (ie.key.mod.control)
-						str = TTR("Control+") + str;
-
-					action->set_text(0, str);
-					action->set_icon(0, get_icon("Keyboard", "EditorIcons"));
-
-				} break;
-				case InputEvent::JOYPAD_BUTTON: {
-
-					String str = TTR("Device") + " " + itos(ie.device) + ", " + TTR("Button") + " " + itos(ie.joy_button.button_index);
-					if (ie.joy_button.button_index >= 0 && ie.joy_button.button_index < JOY_BUTTON_MAX)
-						str += String() + " (" + _button_names[ie.joy_button.button_index] + ").";
-					else
-						str += ".";
-
-					action->set_text(0, str);
-					action->set_icon(0, get_icon("JoyButton", "EditorIcons"));
-				} break;
-				case InputEvent::MOUSE_BUTTON: {
-
-					String str = TTR("Device") + " " + itos(ie.device) + ", ";
-					switch (ie.mouse_button.button_index) {
-						case BUTTON_LEFT: str += TTR("Left Button."); break;
-						case BUTTON_RIGHT: str += TTR("Right Button."); break;
-						case BUTTON_MIDDLE: str += TTR("Middle Button."); break;
-						case BUTTON_WHEEL_UP: str += TTR("Wheel Up."); break;
-						case BUTTON_WHEEL_DOWN: str += TTR("Wheel Down."); break;
-						default: str += TTR("Button") + " " + itos(ie.mouse_button.button_index) + ".";
-					}
-
-					action->set_text(0, str);
-					action->set_icon(0, get_icon("Mouse", "EditorIcons"));
-				} break;
-				case InputEvent::JOYPAD_MOTION: {
-
-					int ax = ie.joy_motion.axis;
-					int n = 2 * ax + (ie.joy_motion.axis_value < 0 ? 0 : 1);
-					String desc = _axis_names[n];
-					String str = TTR("Device") + " " + itos(ie.device) + ", " + TTR("Axis") + " " + itos(ax) + " " + (ie.joy_motion.axis_value < 0 ? "-" : "+") + desc + ".";
-					action->set_text(0, str);
-					action->set_icon(0, get_icon("JoyAxis", "EditorIcons"));
-				} break;
+			Ref<InputEventKey> k = ie;
+			if (k.is_valid()) {
+
+				String str = keycode_get_string(k->get_scancode()).capitalize();
+				if (k->get_metakey())
+					str = TTR("Meta+") + str;
+				if (k->get_shift())
+					str = TTR("Shift+") + str;
+				if (k->get_alt())
+					str = TTR("Alt+") + str;
+				if (k->get_control())
+					str = TTR("Control+") + str;
+
+				action->set_text(0, str);
+				action->set_icon(0, get_icon("Keyboard", "EditorIcons"));
+			}
+
+			Ref<InputEventJoypadButton> jb = ie;
+
+			if (jb.is_valid()) {
+
+				String str = TTR("Device") + " " + itos(jb->get_device()) + ", " + TTR("Button") + " " + itos(jb->get_button_index());
+				if (jb->get_button_index() >= 0 && jb->get_button_index() < JOY_BUTTON_MAX)
+					str += String() + " (" + _button_names[jb->get_button_index()] + ").";
+				else
+					str += ".";
+
+				action->set_text(0, str);
+				action->set_icon(0, get_icon("JoyButton", "EditorIcons"));
+			}
+
+			Ref<InputEventMouseButton> mb = ie;
+
+			if (mb.is_valid()) {
+				String str = TTR("Device") + " " + itos(mb->get_device()) + ", ";
+				switch (mb->get_button_index()) {
+					case BUTTON_LEFT: str += TTR("Left Button."); break;
+					case BUTTON_RIGHT: str += TTR("Right Button."); break;
+					case BUTTON_MIDDLE: str += TTR("Middle Button."); break;
+					case BUTTON_WHEEL_UP: str += TTR("Wheel Up."); break;
+					case BUTTON_WHEEL_DOWN: str += TTR("Wheel Down."); break;
+					default: str += TTR("Button") + " " + itos(mb->get_button_index()) + ".";
+				}
+
+				action->set_text(0, str);
+				action->set_icon(0, get_icon("Mouse", "EditorIcons"));
+			}
+
+			Ref<InputEventJoypadMotion> jm = ie;
+
+			if (jm.is_valid()) {
+
+				int ax = jm->get_axis();
+				int n = 2 * ax + (jm->get_axis_value() < 0 ? 0 : 1);
+				String desc = _axis_names[n];
+				String str = TTR("Device") + " " + itos(jm->get_device()) + ", " + TTR("Axis") + " " + itos(ax) + " " + (jm->get_axis_value() < 0 ? "-" : "+") + desc + ".";
+				action->set_text(0, str);
+				action->set_icon(0, get_icon("JoyAxis", "EditorIcons"));
 			}
 			action->add_button(0, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove"));
 			action->set_metadata(0, i);

+ 11 - 4
editor/project_settings.h

@@ -43,10 +43,17 @@
 class ProjectSettings : public AcceptDialog {
 	GDCLASS(ProjectSettings, AcceptDialog);
 
+	enum InputType {
+		INPUT_KEY,
+		INPUT_JOY_BUTTON,
+		INPUT_JOY_MOTION,
+		INPUT_MOUSE_BUTTON
+	};
+
 	TabContainer *tab_container;
 
 	Timer *timer;
-	InputEvent::Type add_type;
+	InputType add_type;
 	String add_at;
 
 	EditorData *data;
@@ -77,7 +84,7 @@ class ProjectSettings : public AcceptDialog {
 	bool setting;
 	bool updating_translations;
 
-	InputEvent last_wait_for_key;
+	Ref<InputEventKey> last_wait_for_key;
 
 	EditorFileDialog *translation_file_open;
 	Tree *translation_list;
@@ -108,9 +115,9 @@ class ProjectSettings : public AcceptDialog {
 	void _action_selected();
 	void _action_edited();
 	void _action_button_pressed(Object *p_obj, int p_column, int p_id);
-	void _wait_for_key(const InputEvent &p_event);
+	void _wait_for_key(const Ref<InputEvent> &p_event);
 	void _press_a_key_confirm();
-	void _show_last_added(const InputEvent &p_event, const String &p_name);
+	void _show_last_added(const Ref<InputEvent> &p_event, const String &p_name);
 
 	void _settings_prop_edited(const String &p_name);
 	void _settings_changed();

+ 9 - 19
editor/property_editor.cpp

@@ -609,12 +609,9 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
 						type = Variant::Type(Variant::Type(i));
 					}
 				}
-				InputEvent::Type iet = InputEvent::NONE;
-				if (hint_text.find(".") != -1) {
-					iet = InputEvent::Type(int(hint_text.get_slice(".", 1).to_int()));
-				}
+
 				if (type)
-					property_select->select_property_from_basic_type(type, iet, v);
+					property_select->select_property_from_basic_type(type, v);
 
 				updating = false;
 				return false;
@@ -978,9 +975,6 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
 			updating = false;
 			return false;
 
-		} break;
-		case Variant::INPUT_EVENT: {
-
 		} break;
 		case Variant::DICTIONARY: {
 
@@ -1401,11 +1395,13 @@ void CustomPropertyEditor::_scroll_modified(double p_value) {
 	*/
 }
 
-void CustomPropertyEditor::_drag_easing(const InputEvent &p_ev) {
+void CustomPropertyEditor::_drag_easing(const Ref<InputEvent> &p_ev) {
+
+	Ref<InputEventMouseMotion> mm = p_ev;
 
-	if (p_ev.type == InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask & BUTTON_MASK_LEFT) {
+	if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
 
-		float rel = p_ev.mouse_motion.relative_x;
+		float rel = mm->get_relative().x;
 		if (rel == 0)
 			return;
 
@@ -1434,8 +1430,8 @@ void CustomPropertyEditor::_drag_easing(const InputEvent &p_ev) {
 		//emit_signal("variant_changed");
 		emit_signal("variant_changed");
 	}
-	if (p_ev.type == InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index == BUTTON_LEFT) {
-	}
+	//	if (p_ev.type == Ref<InputEvent>::MOUSE_BUTTON && p_ev->get_button_index() == BUTTON_LEFT) {
+	//	}
 }
 
 void CustomPropertyEditor::_draw_easing() {
@@ -1714,9 +1710,6 @@ void CustomPropertyEditor::_modified(String p_string) {
 
 			v = NodePath(value_editor[0]->get_text());
 			emit_signal("variant_changed");
-		} break;
-		case Variant::INPUT_EVENT: {
-
 		} break;
 		case Variant::DICTIONARY: {
 
@@ -3862,9 +3855,6 @@ void PropertyEditor::_item_edited() {
 
 		} break;
 
-		case Variant::INPUT_EVENT: {
-
-		} break;
 		case Variant::DICTIONARY: {
 
 		} break;

+ 1 - 1
editor/property_editor.h

@@ -134,7 +134,7 @@ class CustomPropertyEditor : public Popup {
 	void _draw_easing();
 	void _menu_option(int p_which);
 
-	void _drag_easing(const InputEvent &p_ev);
+	void _drag_easing(const Ref<InputEvent> &p_ev);
 
 	void _node_path_selected(NodePath p_path);
 	void show_value_editors(int p_amount);

+ 10 - 31
editor/property_selector.cpp

@@ -37,17 +37,19 @@ void PropertySelector::_text_changed(const String &p_newtext) {
 	_update_search();
 }
 
-void PropertySelector::_sbox_input(const InputEvent &p_ie) {
+void PropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) {
 
-	if (p_ie.type == InputEvent::KEY) {
+	Ref<InputEventKey> k = p_ie;
 
-		switch (p_ie.key.scancode) {
+	if (k.is_valid()) {
+
+		switch (k->get_scancode()) {
 			case KEY_UP:
 			case KEY_DOWN:
 			case KEY_PAGEUP:
 			case KEY_PAGEDOWN: {
 
-				search_options->call("_gui_input", p_ie);
+				search_options->call("_gui_input", k);
 				search_box->accept_event();
 
 				TreeItem *root = search_options->get_root();
@@ -89,14 +91,8 @@ void PropertySelector::_update_search() {
 			instance->get_property_list(&props, true);
 		} else if (type != Variant::NIL) {
 			Variant v;
-			if (type == Variant::INPUT_EVENT) {
-				InputEvent ie;
-				ie.type = event_type;
-				v = ie;
-			} else {
-				Variant::CallError ce;
-				v = Variant::construct(type, NULL, 0, ce);
-			}
+			Variant::CallError ce;
+			v = Variant::construct(type, NULL, 0, ce);
 
 			v.get_property_list(&props);
 		} else {
@@ -139,7 +135,6 @@ void PropertySelector::_update_search() {
 			Control::get_icon("MiniPath", "EditorIcons"),
 			Control::get_icon("MiniRid", "EditorIcons"),
 			Control::get_icon("MiniObject", "EditorIcons"),
-			Control::get_icon("MiniInput", "EditorIcons"),
 			Control::get_icon("MiniDictionary", "EditorIcons"),
 			Control::get_icon("MiniArray", "EditorIcons"),
 			Control::get_icon("MiniRawArray", "EditorIcons"),
@@ -325,22 +320,7 @@ void PropertySelector::_item_selected() {
 	String name = item->get_metadata(0);
 
 	String class_type;
-	if (properties && type == Variant::INPUT_EVENT) {
-
-		switch (event_type) {
-			case InputEvent::NONE: class_type = "InputEvent"; break;
-			case InputEvent::KEY: class_type = "InputEventKey"; break;
-			case InputEvent::MOUSE_MOTION: class_type = "InputEventMouseMotion"; break;
-			case InputEvent::MOUSE_BUTTON: class_type = "InputEventMouseButton"; break;
-			case InputEvent::JOYPAD_MOTION: class_type = "InputEventJoypadMotion"; break;
-			case InputEvent::JOYPAD_BUTTON: class_type = "InputEventJoypadButton"; break;
-			case InputEvent::SCREEN_TOUCH: class_type = "InputEventScreenTouch"; break;
-			case InputEvent::SCREEN_DRAG: class_type = "InputEventScreenDrag"; break;
-			case InputEvent::ACTION: class_type = "InputEventAction"; break;
-			default: {}
-		}
-
-	} else if (type) {
+	if (type) {
 		class_type = Variant::get_type_name(type);
 
 	} else {
@@ -514,13 +494,12 @@ void PropertySelector::select_property_from_script(const Ref<Script> &p_script,
 	search_box->grab_focus();
 	_update_search();
 }
-void PropertySelector::select_property_from_basic_type(Variant::Type p_type, InputEvent::Type p_event_type, const String &p_current) {
+void PropertySelector::select_property_from_basic_type(Variant::Type p_type, const String &p_current) {
 
 	ERR_FAIL_COND(p_type == Variant::NIL);
 	base_type = "";
 	selected = p_current;
 	type = p_type;
-	event_type = p_event_type;
 	script = 0;
 	properties = true;
 	instance = NULL;

Some files were not shown because too many files changed in this diff