void  GridMapEditor::_menu_option(int p_option) {


	switch(p_option) {

		case MENU_OPTION_CONFIGURE: {


		} break;
		case MENU_OPTION_LOCK_VIEW: {

			int index=options->get_popup()->get_item_index(MENU_OPTION_LOCK_VIEW);
			lock_view=!options->get_popup()->is_item_checked(index);

			options->get_popup()->set_item_checked(index,lock_view);
		} break;
		case MENU_OPTION_CLIP_DISABLED:
		case MENU_OPTION_CLIP_ABOVE:
		case MENU_OPTION_CLIP_BELOW: {

			clip_mode=ClipMode(p_option-MENU_OPTION_CLIP_DISABLED);
			for(int i=0;i<3;i++) {

				int index=options->get_popup()->get_item_index(MENU_OPTION_CLIP_DISABLED+i);
				options->get_popup()->set_item_checked(index,i==clip_mode);

			}

			_update_clip();
		} break;
		case MENU_OPTION_X_AXIS:
		case MENU_OPTION_Y_AXIS:
		case MENU_OPTION_Z_AXIS: {

			int new_axis = p_option-MENU_OPTION_X_AXIS;
			for(int i=0;i<3;i++) {
				int idx=options->get_popup()->get_item_index(MENU_OPTION_X_AXIS+i);
				options->get_popup()->set_item_checked(idx,i==new_axis);
			}
			edit_axis=Vector3::Axis(new_axis);
			update_grid();
			_update_clip();

		} break;
		case MENU_OPTION_CURSOR_ROTATE_Y: {
			Basis r;
			if (input_action==INPUT_DUPLICATE) {

				r.set_orthogonal_index(selection.duplicate_rot);
				r.rotate(Vector3(0,1,0),-Math_PI/2.0);
				selection.duplicate_rot=r.get_orthogonal_index();
				_update_duplicate_indicator();
				break;
			}
			r.set_orthogonal_index(cursor_rot);
			r.rotate(Vector3(0,1,0),-Math_PI/2.0);
			cursor_rot=r.get_orthogonal_index();
			_update_cursor_transform();
		} break;
		case MENU_OPTION_CURSOR_ROTATE_X: {
			Basis r;
			if (input_action==INPUT_DUPLICATE) {

				r.set_orthogonal_index(selection.duplicate_rot);
				r.rotate(Vector3(1,0,0),-Math_PI/2.0);
				selection.duplicate_rot=r.get_orthogonal_index();
				_update_duplicate_indicator();
				break;
			}

			r.set_orthogonal_index(cursor_rot);
			r.rotate(Vector3(1,0,0),-Math_PI/2.0);
			cursor_rot=r.get_orthogonal_index();
			_update_cursor_transform();
		} break;
		case MENU_OPTION_CURSOR_ROTATE_Z: {
			Basis r;
			if (input_action==INPUT_DUPLICATE) {

				r.set_orthogonal_index(selection.duplicate_rot);
				r.rotate(Vector3(0,0,1),-Math_PI/2.0);
				selection.duplicate_rot=r.get_orthogonal_index();
				_update_duplicate_indicator();
				break;
			}

			r.set_orthogonal_index(cursor_rot);
			r.rotate(Vector3(0,0,1),-Math_PI/2.0);
			cursor_rot=r.get_orthogonal_index();
			_update_cursor_transform();
		} break;
		case MENU_OPTION_CURSOR_BACK_ROTATE_Y: {
			Basis r;
			r.set_orthogonal_index(cursor_rot);
			r.rotate(Vector3(0,1,0),Math_PI/2.0);
			cursor_rot=r.get_orthogonal_index();
			_update_cursor_transform();
		} break;
		case MENU_OPTION_CURSOR_BACK_ROTATE_X: {
			Basis r;
			r.set_orthogonal_index(cursor_rot);
			r.rotate(Vector3(1,0,0),Math_PI/2.0);
			cursor_rot=r.get_orthogonal_index();
			_update_cursor_transform();
		} break;
		case MENU_OPTION_CURSOR_BACK_ROTATE_Z: {
			Basis r;
			r.set_orthogonal_index(cursor_rot);
			r.rotate(Vector3(0,0,1),Math_PI/2.0);
			cursor_rot=r.get_orthogonal_index();
			_update_cursor_transform();
		} break;
		case MENU_OPTION_CURSOR_CLEAR_ROTATION: {

			if (input_action==INPUT_DUPLICATE) {


				selection.duplicate_rot=0;
				_update_duplicate_indicator();
				break;
			}

			cursor_rot=0;
			_update_cursor_transform();
		} break;


		case MENU_OPTION_DUPLICATE_SELECTS: {
			int idx = options->get_popup()->get_item_index(MENU_OPTION_DUPLICATE_SELECTS);
			options->get_popup()->set_item_checked( idx, !options->get_popup()->is_item_checked( idx ) );
		} break;
		case MENU_OPTION_SELECTION_MAKE_AREA:
		case MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR: {

			if (!selection.active)
				break;
			int area = node->get_unused_area_id();
			Error err = node->create_area(area,Rect3(selection.begin,selection.end-selection.begin+Vector3(1,1,1)));
			if (err!=OK) {


			}
			if (p_option==MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR) {

				node->area_set_exterior_portal(area,true);
			}
			_update_areas_display();
			update_areas();


		} break;
		case MENU_OPTION_REMOVE_AREA: {
			if (selected_area<1)
				return;
			node->erase_area(selected_area);
			_update_areas_display();
			update_areas();
		} break;
		case MENU_OPTION_SELECTION_DUPLICATE:
			if (!(selection.active && input_action==INPUT_NONE))
				return;
			if (last_mouseover==Vector3(-1,-1,-1)) //nono mouseovering anythin
				break;

			input_action=INPUT_DUPLICATE;
			selection.click=last_mouseover;
			selection.current=last_mouseover;
			selection.duplicate_rot=0;
			_update_duplicate_indicator();
			break;
		case MENU_OPTION_SELECTION_CLEAR: {
			if (!selection.active)
				return;

			_delete_selection();


		} break;
		case MENU_OPTION_GRIDMAP_SETTINGS: {
			settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50));
		} break;

	}
}
static int message_handle_key_editmode(struct key_event * k)
{
        int line_len, num_lines = -1;
        int new_cursor_line = cursor_line;
        int new_cursor_char = cursor_char;
        char *ptr;
        int doing_drag = 0;
        int clipl, clipr, cp;

        if (k->mouse == MOUSE_SCROLL_UP) {
                if (k->state == KEY_RELEASE)
                        return 0;
                new_cursor_line -= MOUSE_SCROLL_LINES;
        } else if (k->mouse == MOUSE_SCROLL_DOWN) {
                if (k->state == KEY_RELEASE)
                        return 0;
                new_cursor_line += MOUSE_SCROLL_LINES;
        } else if (k->mouse == MOUSE_CLICK && k->mouse_button == 2) {
                if (k->state == KEY_RELEASE)
                        status.flags |= CLIPPY_PASTE_SELECTION;
                return 1;
        } else if (k->mouse == MOUSE_CLICK) {
                if (k->x >= 2 && k->x <= 77 && k->y >= 13 && k->y <= 47) {
                        new_cursor_line = (k->y - 13) + top_line;
                        new_cursor_char = (k->x - 2);
                        if (k->sx != k->x || k->sy != k->y) {
                                /* yay drag operation */
                                cp = get_absolute_position(current_song->message, (k->sy-13)+top_line,
                                                        (k->sx-2));
                                widgets_message[0].clip_start = cp;
                                doing_drag = 1;
                        }
                }
        }

        line_len = get_nth_line(current_song->message, cursor_line, &ptr);


        switch (k->sym) {
        case SDLK_UP:
                if (!NO_MODIFIER(k->mod))
                        return 0;
                if (k->state == KEY_RELEASE)
                        return 1;
                new_cursor_line--;
                break;
        case SDLK_DOWN:
                if (!NO_MODIFIER(k->mod))
                        return 0;
                if (k->state == KEY_RELEASE)
                        return 1;
                new_cursor_line++;
                break;
        case SDLK_LEFT:
                if (!NO_MODIFIER(k->mod))
                        return 0;
                if (k->state == KEY_RELEASE)
                        return 1;
                new_cursor_char--;
                break;
        case SDLK_RIGHT:
                if (!NO_MODIFIER(k->mod))
                        return 0;
                if (k->state == KEY_RELEASE)
                        return 1;
                new_cursor_char++;
                break;
        case SDLK_PAGEUP:
                if (!NO_MODIFIER(k->mod))
                        return 0;
                if (k->state == KEY_RELEASE)
                        return 1;
                new_cursor_line -= 35;
                break;
        case SDLK_PAGEDOWN:
                if (!NO_MODIFIER(k->mod))
                        return 0;
                if (k->state == KEY_RELEASE)
                        return 1;
                new_cursor_line += 35;
                break;
        case SDLK_HOME:
                if (k->state == KEY_RELEASE)
                        return 1;
                if (k->mod & KMOD_CTRL)
                        new_cursor_line = 0;
                else
                        new_cursor_char = 0;
                break;
        case SDLK_END:
                if (k->state == KEY_RELEASE)
                        return 1;
                if (k->mod & KMOD_CTRL) {
                        num_lines = get_num_lines(current_song->message);
                        new_cursor_line = num_lines;
                } else {
                        new_cursor_char = line_len;
                }
                break;
        case SDLK_ESCAPE:
                if (!NO_MODIFIER(k->mod))
                        return 0;
                if (k->state == KEY_RELEASE)
                        return 1;
                message_set_viewmode();
                memused_songchanged();
                return 1;
        case SDLK_BACKSPACE:
                if (!NO_MODIFIER(k->mod))
                        return 0;
                if (k->state == KEY_RELEASE)
                        return 1;
                if (k->sym && clippy_owner(CLIPPY_SELECT) == widgets_message) {
                        _delete_selection();
                } else {
                        message_delete_char();
                }
                return 1;
        case SDLK_DELETE:
                if (!NO_MODIFIER(k->mod))
                        return 0;
                if (k->state == KEY_RELEASE)
                        return 1;
                if (k->sym && clippy_owner(CLIPPY_SELECT) == widgets_message) {
                        _delete_selection();
                } else {
                        message_delete_next_char();
                }
                return 1;
        default:
                if (k->mod & KMOD_CTRL) {
                        if (k->state == KEY_RELEASE)
                                return 1;
                        if (k->sym == SDLK_t) {
                                message_extfont = !message_extfont;
                                break;
                        } else if (k->sym == SDLK_y) {
                                clippy_select(NULL, NULL, 0);
                                message_delete_line();
                                break;
                        }
                } else if (k->mod & KMOD_ALT) {
                        if (k->state == KEY_RELEASE)
                                return 1;
                        if (k->sym == SDLK_c) {
                                prompt_message_clear();
                                return 1;
                        }
                } else if (k->mouse == MOUSE_NONE) {
                        if (k->unicode == '\r' || k->unicode == '\t'
                        || k->unicode >= 32) {
                                if (k->state == KEY_RELEASE)
                                        return 1;
                                if (k->sym && clippy_owner(CLIPPY_SELECT) == widgets_message) {
                                        _delete_selection();
                                }
                                if (k->mod & (KMOD_SHIFT|KMOD_CAPS)) {
                                        message_insert_char(toupper((unsigned int)k->unicode));
                                } else {
                                        message_insert_char(k->unicode);
                                }
                                return 1;
                        }
                        return 0;
                }

                if (k->mouse != MOUSE_CLICK)
                        return 0;

                if (k->state == KEY_RELEASE)
                        return 1;
                if (!doing_drag) {
                        clippy_select(NULL, NULL, 0);
                }
        }

        if (new_cursor_line != cursor_line) {
                if (num_lines == -1)
                        num_lines = get_num_lines(current_song->message);

                if (new_cursor_line < 0)
                        new_cursor_line = 0;
                else if (new_cursor_line > num_lines)
                        new_cursor_line = num_lines;

                /* make sure the cursor doesn't go past the new eol */
                line_len = get_nth_line(current_song->message, new_cursor_line, &ptr);
                if (new_cursor_char > line_len)
                        new_cursor_char = line_len;

                cursor_char = new_cursor_char;
                cursor_line = new_cursor_line;
        } else if (new_cursor_char != cursor_char) {
        /* we say "else" here ESPECIALLY because the mouse can only come
        in the top section - not because it's some clever optimization */
                if (new_cursor_char < 0) {
                        if (cursor_line == 0) {
                                new_cursor_char = cursor_char;
                        } else {
                                cursor_line--;
                                new_cursor_char =
                                        get_nth_line(current_song->message, cursor_line, &ptr);
                        }

                } else if (new_cursor_char >
                           get_nth_line(current_song->message, cursor_line, &ptr)) {
                        if (cursor_line == get_num_lines(current_song->message)) {
                                new_cursor_char = cursor_char;
                        } else {
                                cursor_line++;
                                new_cursor_char = 0;
                        }
                }
                cursor_char = new_cursor_char;
        }

        message_reposition();
        cursor_pos = get_absolute_position(current_song->message, cursor_line, cursor_char);

        if (doing_drag) {
                widgets_message[0].clip_end = cursor_pos;

                clipl = widgets_message[0].clip_start;
                clipr = widgets_message[0].clip_end;
                if (clipl > clipr) {
                        cp = clipl;
                        clipl = clipr;
                        clipr = cp;
                }
                clippy_select(widgets_message, (current_song->message+clipl), clipr-clipl);
        }

        status.flags |= NEED_UPDATE;

        return 1;
}
bool GridMapEditor::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) {


	if (edit_mode->get_selected()==0) { // regular click
		switch (p_event.type) {
			case InputEvent::KEY: {

				if (p_event.key.pressed && p_event.key.scancode==KEY_D && p_event.key.mod.shift && selection.active && input_action==INPUT_NONE) {

					if (last_mouseover==Vector3(-1,-1,-1)) //nono mouseovering anythin
						return false;

					input_action=INPUT_DUPLICATE;
					selection.click=last_mouseover;
					selection.current=last_mouseover;
					selection.duplicate_rot=0;
					_update_duplicate_indicator();


				}

				if (p_event.key.pressed && p_event.key.scancode==KEY_DELETE && selection.active) {

					_delete_selection();
					return true;
				}

			} break;
			case InputEvent::MOUSE_BUTTON: {

				if (p_event.mouse_button.button_index==BUTTON_WHEEL_UP && (p_event.mouse_button.mod.command || p_event.mouse_button.mod.shift)) {
					if (p_event.mouse_button.pressed)
						floor->set_val( floor->get_val() +1);

					return true; //eaten
				} else if (p_event.mouse_button.button_index==BUTTON_WHEEL_DOWN && (p_event.mouse_button.mod.command || p_event.mouse_button.mod.shift)) {
					if (p_event.mouse_button.pressed)
						floor->set_val( floor->get_val() -1);
					return true;
				}

				if (p_event.mouse_button.pressed) {

					if (p_event.mouse_button.button_index==BUTTON_LEFT) {

						if (input_action==INPUT_DUPLICATE) {

							//paste
							_duplicate_paste();
							input_action=INPUT_NONE;
							_update_duplicate_indicator();
						} else if (p_event.mouse_button.mod.shift) {
							input_action=INPUT_SELECT;
						} else if (p_event.mouse_button.mod.command)
							input_action=INPUT_COPY;
						else {
							input_action=INPUT_PAINT;
							set_items.clear();
						}
					} else if (p_event.mouse_button.button_index==BUTTON_RIGHT)
						if (input_action==INPUT_DUPLICATE) {

							input_action=INPUT_NONE;
							_update_duplicate_indicator();
						} else {
							input_action=INPUT_ERASE;
							set_items.clear();
						}
					else
						return false;

					return do_input_action(p_camera,Point2(p_event.mouse_button.x,p_event.mouse_button.y),true);
				} else {


					if (
						(p_event.mouse_button.button_index==BUTTON_RIGHT && input_action==INPUT_ERASE) ||
						(p_event.mouse_button.button_index==BUTTON_LEFT && input_action==INPUT_PAINT) ) {

						if (set_items.size()) {
							undo_redo->create_action("GridMap Paint");
							for(List<SetItem>::Element *E=set_items.front();E;E=E->next()) {

								const SetItem &si=E->get();
								undo_redo->add_do_method(node,"set_cell_item",si.pos.x,si.pos.y,si.pos.z,si.new_value,si.new_orientation);
							}
							for(List<SetItem>::Element *E=set_items.back();E;E=E->prev()) {

								const SetItem &si=E->get();
								undo_redo->add_undo_method(node,"set_cell_item",si.pos.x,si.pos.y,si.pos.z,si.old_value,si.old_orientation);
							}


							undo_redo->commit_action();
						}
						set_items.clear();
						input_action=INPUT_NONE;
						return true;

					}



					if (p_event.mouse_button.button_index==BUTTON_LEFT && input_action!=INPUT_NONE) {

						set_items.clear();
						input_action=INPUT_NONE;
						return true;
					}
					if (p_event.mouse_button.button_index==BUTTON_RIGHT && (input_action==INPUT_ERASE || input_action==INPUT_DUPLICATE)) {
						input_action=INPUT_NONE;
						return true;
					}
				}
			} break;
			case InputEvent::MOUSE_MOTION: {

				return do_input_action(p_camera,Point2(p_event.mouse_motion.x,p_event.mouse_motion.y),false);
			} break;
		}

	} else if (edit_mode->get_selected()==1) {
		//area mode, select an area

		switch (p_event.type) {
			case InputEvent::MOUSE_BUTTON: {

				if (p_event.mouse_button.button_index==BUTTON_LEFT && p_event.mouse_button.pressed) {

					Point2 point = Point2(p_event.mouse_motion.x,p_event.mouse_motion.y);

					Camera *camera = p_camera;
					Vector3 from = camera->project_ray_origin(point);
					Vector3 normal = camera->project_ray_normal(point);
					Transform local_xform = node->get_global_transform().affine_inverse();
					from=local_xform.xform(from);
					normal=local_xform.basis.xform(normal).normalized();

					List<int> areas;
					node->get_area_list(&areas);

					float min_d=1e10;
					int min_area=-1;


					for(List<int>::Element *E=areas.front();E;E=E->next()) {

						int area = E->get();
						AABB aabb = node->area_get_bounds(area);
						aabb.pos*=node->get_cell_size();
						aabb.size*=node->get_cell_size();


						Vector3 rclip,rnormal;
						if (!aabb.intersects_segment(from,from+normal*10000,&rclip,&rnormal))
							continue;

						float d = normal.dot(rclip);
						if (d<min_d) {
							min_d=d;
							min_area=area;
						}
					}

					selected_area=min_area;
					update_areas();

				}
			} break;
		}

	}


	return false;
}