/*
Copyright (c) 2019-2023 Péter Magyar

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "mdi_ed.h"

#include "../mesh_data_resource.h"
#include "./uv_editor/mdr_ed_uv_previewer.h"
#include "./uv_editor/mdr_uv_rect_editor.h"
#include "./uv_editor/mdr_uv_rect_editor_popup.h"
#include "core/os/keyboard.h"
#include "editor/plugins/spatial_editor_plugin.h"
#include "mdi_ed_plugin.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"
#include "scene/gui/scroll_container.h"
#include "scene/gui/separator.h"

bool MDIEd::is_editing() {
	return _editing;
}

void MDIEd::make_visible(const bool visible) {
	_edit_mode_button->set_visible(visible);

	if (!visible) {
		hide();
	} else {
		set_visible(_editing);
		_plugin->set_gizmo_visible(_editing);
	}
}

void MDIEd::set_plugin(MDIEdPlugin *plugin) {
	_plugin = plugin;
	uv_editor->set_plugin(plugin);
}
void MDIEd::set_mesh_data_resource(const Ref<MeshDataResource> &a) {
	uv_preview->set_mesh_data_resource(a);
	uv_editor->get_editor()->set_mesh_data_resource(a);
}
void MDIEd::set_mesh_data_instance(MeshDataInstance *a) {
	uv_preview->set_mesh_data_instance(a);
	uv_editor->get_editor()->set_mesh_data_instance(a);
}
void MDIEd::_unhandled_key_input(const Ref<InputEventKey> &event) {
	if (event->is_echo()) {
		return;
	}

	if (event->get_alt() || event->get_shift() || event->get_control() || event->get_metakey() || event->get_command()) {
		return;
	}

	uint32_t scancode = event->get_scancode();

	if (scancode == KEY_G) {
		set_edit_mode_translate();
	} else if (scancode == KEY_H) {
		set_edit_mode_rotate();
	} else if (scancode == KEY_J) {
		set_edit_mode_scale();
	} else if (scancode == KEY_V) {
		set_axis_x(!get_axis_x());
	} else if (scancode == KEY_B) {
		set_axis_y(!get_axis_y());
	} else if (scancode == KEY_N) {
		set_axis_z(!get_axis_z());
	} else if (scancode == KEY_K) {
		set_selection_mode_vertex();
	} else if (scancode == KEY_L) {
		set_selection_mode_edge();
	} else if (scancode == KEY_SEMICOLON) {
		set_selection_mode_face();
	}
}

//Edit modes
void MDIEd::set_edit_mode_translate() {
	_edit_mode_translate_button->set_pressed(true);
}
void MDIEd::set_edit_mode_rotate() {
	_edit_mode_rotate_button->set_pressed(true);
}
void MDIEd::set_edit_mode_scale() {
	_edit_mode_scale_button->set_pressed(true);
}

void MDIEd::on_edit_mode_translate_toggled(bool on) {
	if (on) {
		_plugin->set_translate();
	}
}
void MDIEd::on_edit_mode_rotate_toggled(bool on) {
	if (on) {
		_plugin->set_rotate();
	}
}
void MDIEd::on_edit_mode_scale_toggled(bool on) {
	if (on) {
		_plugin->set_scale();
	}
}

//axis locks
bool MDIEd::get_axis_x() {
	return _axis_lock_x_button->is_pressed();
}
bool MDIEd::get_axis_y() {
	return _axis_lock_y_button->is_pressed();
}
bool MDIEd::get_axis_z() {
	return _axis_lock_z_button->is_pressed();
}
void MDIEd::set_axis_x(bool on) {
	_axis_lock_x_button->set_pressed(on);
}
void MDIEd::set_axis_y(bool on) {
	_axis_lock_y_button->set_pressed(on);
}
void MDIEd::set_axis_z(bool on) {
	_axis_lock_z_button->set_pressed(on);
}

void MDIEd::on_axis_x_toggled(bool on) {
	_plugin->set_axis_x(on);
}
void MDIEd::on_axis_y_toggled(bool on) {
	_plugin->set_axis_y(on);
}
void MDIEd::on_axis_z_toggled(bool on) {
	_plugin->set_axis_z(on);
}

//selection modes
void MDIEd::on_selection_mode_vertex_toggled(bool on) {
	if (on) {
		_plugin->set_selection_mode_vertex();

		vertex_operations_container->show();
		edge_operations_container->hide();
		face_operations_container->hide();
	}
}
void MDIEd::on_selection_mode_edge_toggled(bool on) {
	if (on) {
		_plugin->set_selection_mode_edge();

		vertex_operations_container->hide();
		edge_operations_container->show();
		face_operations_container->hide();
	}
}
void MDIEd::on_selection_mode_face_toggled(bool on) {
	if (on) {
		_plugin->set_selection_mode_face();

		vertex_operations_container->hide();
		edge_operations_container->hide();
		face_operations_container->show();
	}
}

void MDIEd::set_selection_mode_vertex() {
	_selection_mode_vertex_button->set_pressed(true);
}
void MDIEd::set_selection_mode_edge() {
	_selection_mode_edge_button->set_pressed(true);
}
void MDIEd::set_selection_mode_face() {
	_selection_mode_face_button->set_pressed(true);
}

void MDIEd::on_handle_selection_type_front_toggled(bool on) {
	if (on) {
		_plugin->handle_selection_type_front();
	}
}
void MDIEd::on_handle_selection_type_back_toggled(bool on) {
	if (on) {
		_plugin->handle_selection_type_back();
	}
}
void MDIEd::on_handle_selection_type_all_toggled(bool on) {
	if (on) {
		_plugin->handle_selection_type_all();
	}
}

void MDIEd::on_select_all_pressed() {
	_plugin->select_all();
}

void MDIEd::on_create_face_pressed() {
	_plugin->create_face();
}
void MDIEd::on_split_pressed() {
	_plugin->split();
}
void MDIEd::on_connect_to_first_selected_pressed() {
	_plugin->connect_to_first_selected();
}
void MDIEd::on_connect_to_avg_pressed() {
	_plugin->connect_to_avg();
}
void MDIEd::on_connect_to_last_selected_pressed() {
	_plugin->connect_to_last_selected();
}

//Edge ops
void MDIEd::on_extrude_pressed() {
	_plugin->extrude();
}
void MDIEd::on_add_triangle_at_pressed() {
	_plugin->add_triangle_at();
}
void MDIEd::on_add_quad_at_pressed() {
	_plugin->add_quad_at();
}
void MDIEd::on_mark_seam_pressed() {
	_plugin->mark_seam();
}
void MDIEd::on_unmark_seam_pressed() {
	_plugin->unmark_seam();
}

//Face ops
void MDIEd::on_delete_pressed() {
	_plugin->delete_selected();
}
void MDIEd::on_flip_face_pressed() {
	_plugin->flip_selected_faces();
}

void MDIEd::on_pivot_average_toggled(bool on) {
	if (on) {
		_plugin->set_pivot_averaged();
	}
}
void MDIEd::on_pivot_mdi_origin_toggled(bool on) {
	if (on) {
		_plugin->set_pivot_mdi_origin();
	}
}
void MDIEd::on_pivot_world_origin_toggled(bool on) {
	if (on) {
		_plugin->set_pivot_world_origin();
	}
}
void MDIEd::on_visual_indicator_outline_toggled(bool on) {
	_plugin->visual_indicator_outline_set(on);
}
void MDIEd::on_visual_indicator_seam_toggled(bool on) {
	_plugin->visual_indicator_seam_set(on);
}
void MDIEd::on_visual_indicator_handle_toggled(bool on) {
	_plugin->visual_indicator_handle_set(on);
}

void MDIEd::on_generate_normals_pressed() {
	_plugin->generate_normals();
}
void MDIEd::on_generate_tangents_pressed() {
	_plugin->generate_tangents();
}

void MDIEd::on_remove_doubles_pressed() {
	_plugin->remove_doubles();
}
void MDIEd::on_merge_optimize_pressed() {
	_plugin->merge_optimize();
}
void MDIEd::on_clean_mesh_pressed() {
	_plugin->clean_mesh();
}
void MDIEd::on_uv_edit_pressed() {
	uv_editor->popup_centered();
}
void MDIEd::on_apply_seams_pressed() {
	_plugin->apply_seam();
}
void MDIEd::on_unwrap_button_pressed() {
	_plugin->uv_unwrap();
}

void MDIEd::on_add_box_pressed() {
	_plugin->add_box();
}
void MDIEd::on_add_triangle_pressed() {
	_plugin->add_triangle();
}
void MDIEd::on_add_quad_pressed() {
	_plugin->add_quad();
}

void MDIEd::_on_disconnect_pressed() {
	_plugin->disconnect_action();
}

MDIEd::MDIEd() {
	//Main
	VBoxContainer *main_cont = memnew(VBoxContainer);
	add_child(main_cont);

	// -- Actions
	VBoxContainer *main_actions_container = memnew(VBoxContainer);
	main_cont->add_child(main_actions_container);

	HBoxContainer *actions_inner_container = memnew(HBoxContainer);
	actions_inner_container->set_alignment(BoxContainer::ALIGN_CENTER);
	main_actions_container->add_child(actions_inner_container);

	VBoxContainer *left_actions_container = memnew(VBoxContainer);
	actions_inner_container->add_child(left_actions_container);

	VBoxContainer *right_actions_container = memnew(VBoxContainer);
	actions_inner_container->add_child(right_actions_container);

	// -- Actions -- Edit Mode
	Label *action_label = memnew(Label);
	action_label->set_text("E");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	action_label->set_tooltip("Edit Mode");
	action_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
	action_label->set_v_size_flags(SIZE_EXPAND_FILL | SIZE_SHRINK_CENTER);
	left_actions_container->add_child(action_label);

	Ref<ButtonGroup> action_button_group;
	action_button_group.instance();

	HBoxContainer *action_buttons_container = memnew(HBoxContainer);
	right_actions_container->add_child(action_buttons_container);

	Button *action_button = memnew(Button);
	action_button->set_text("T");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Translate");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_edit_mode_translate_toggled");
	action_buttons_container->add_child(action_button);
	_edit_mode_translate_button = action_button;

	action_button = memnew(Button);
	action_button->set_text("R");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(false);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Rotate");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_edit_mode_rotate_toggled");
	action_buttons_container->add_child(action_button);
	_edit_mode_rotate_button = action_button;

	action_button = memnew(Button);
	action_button->set_text("S");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(false);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Scale");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_edit_mode_scale_toggled");
	action_buttons_container->add_child(action_button);
	_edit_mode_scale_button = action_button;

	// -- Actions -- Active Axis
	action_label = memnew(Label);
	action_label->set_text("A");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	action_label->set_tooltip("Active Axis");
	action_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
	action_label->set_v_size_flags(SIZE_EXPAND_FILL | SIZE_SHRINK_CENTER);
	left_actions_container->add_child(action_label);

	action_buttons_container = memnew(HBoxContainer);
	right_actions_container->add_child(action_buttons_container);

	action_button = memnew(Button);
	action_button->set_text("X");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_axis_x_toggled");
	action_buttons_container->add_child(action_button);
	_axis_lock_x_button = action_button;

	action_button = memnew(Button);
	action_button->set_text("Y");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_axis_y_toggled");
	action_buttons_container->add_child(action_button);
	_axis_lock_y_button = action_button;

	action_button = memnew(Button);
	action_button->set_text("Z");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_axis_z_toggled");
	action_buttons_container->add_child(action_button);
	_axis_lock_z_button = action_button;

	// -- Actions -- Selection Mode
	action_label = memnew(Label);
	action_label->set_text("S");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	action_label->set_tooltip("Selection Mode");
	action_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
	action_label->set_v_size_flags(SIZE_EXPAND_FILL | SIZE_SHRINK_CENTER);
	left_actions_container->add_child(action_label);

	action_button_group.instance();

	action_buttons_container = memnew(HBoxContainer);
	right_actions_container->add_child(action_buttons_container);

	action_button = memnew(Button);
	action_button->set_text("V");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Vertex");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_selection_mode_vertex_toggled");
	action_buttons_container->add_child(action_button);
	_selection_mode_vertex_button = action_button;

	action_button = memnew(Button);
	action_button->set_text("E");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(false);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Edge");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_selection_mode_edge_toggled");
	action_buttons_container->add_child(action_button);
	_selection_mode_edge_button = action_button;

	action_button = memnew(Button);
	action_button->set_text("F");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(false);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Face");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_selection_mode_face_toggled");
	action_buttons_container->add_child(action_button);
	_selection_mode_face_button = action_button;

	// -- Main separator
	main_cont->add_child(memnew(HSeparator));

	// -- Main ScrollContainer
	ScrollContainer *main_scroll_container = memnew(ScrollContainer);
	main_scroll_container->set_v_size_flags(SIZE_EXPAND_FILL);
	main_scroll_container->set_h_size_flags(SIZE_EXPAND_FILL);
	main_scroll_container->set_enable_h_scroll(false);
	main_cont->add_child(main_scroll_container);

	VBoxContainer *scroll_container_content = memnew(VBoxContainer);
	scroll_container_content->set_h_size_flags(SIZE_EXPAND_FILL);
	main_scroll_container->add_child(scroll_container_content);

	// -- Scroll -- Handle Selection type
	action_buttons_container = memnew(HBoxContainer);
	scroll_container_content->add_child(action_buttons_container);

	action_label = memnew(Label);
	action_label->set_text("H");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	action_label->set_tooltip("Handle Selection Type");
	action_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
	action_label->set_v_size_flags(SIZE_EXPAND_FILL | SIZE_SHRINK_CENTER);
	action_buttons_container->add_child(action_label);

	action_button_group.instance();

	action_button = memnew(Button);
	action_button->set_text("F");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Front");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_handle_selection_type_front_toggled");
	action_buttons_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("B");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(false);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Back");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_handle_selection_type_back_toggled");
	action_buttons_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("A");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(false);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("All");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_handle_selection_type_all_toggled");
	action_buttons_container->add_child(action_button);

	// -- Scroll -- Pivot
	action_buttons_container = memnew(HBoxContainer);
	scroll_container_content->add_child(action_buttons_container);

	action_label = memnew(Label);
	action_label->set_text("P");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	action_label->set_tooltip("Pivot");
	action_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
	action_label->set_v_size_flags(SIZE_EXPAND_FILL | SIZE_SHRINK_CENTER);
	action_buttons_container->add_child(action_label);

	action_button_group.instance();

	action_button = memnew(Button);
	action_button->set_text("A");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Average");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_pivot_average_toggled");
	action_buttons_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("M");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(false);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Mesh Data Instance Origin");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_pivot_mdi_origin_toggled");
	action_buttons_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("W");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(false);
	action_button->set_button_group(action_button_group);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("World Origin");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_pivot_world_origin_toggled");
	action_buttons_container->add_child(action_button);

	// -- Scroll -- Visual indicators
	action_buttons_container = memnew(HBoxContainer);
	scroll_container_content->add_child(action_buttons_container);

	action_label = memnew(Label);
	action_label->set_text("V");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	action_label->set_tooltip("Visual indicators");
	action_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
	action_label->set_v_size_flags(SIZE_EXPAND_FILL | SIZE_SHRINK_CENTER);
	action_buttons_container->add_child(action_label);

	action_button = memnew(Button);
	action_button->set_text("O");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Outline");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_handle_selection_type_front_toggled");
	action_buttons_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("S");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Seam");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_handle_selection_type_back_toggled");
	action_buttons_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("H");
	action_button->set_toggle_mode(true);
	action_button->set_pressed(true);
	action_button->set_custom_minimum_size(Size2(25, 20));
	action_button->set_tooltip("Handle");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("toggled", this, "on_handle_selection_type_all_toggled");
	action_buttons_container->add_child(action_button);

	// -- Scroll -- Separator
	scroll_container_content->add_child(memnew(HSeparator));

	// -- Scroll -- Select All Button
	action_button = memnew(Button);
	action_button->set_text("Select All");
	action_button->connect("pressed", this, "on_select_all_pressed");
	scroll_container_content->add_child(action_button);

	// -- Scroll -- Separator
	scroll_container_content->add_child(memnew(HSeparator));

	// -- Scroll -- Vertex Operations
	vertex_operations_container = memnew(VBoxContainer);
	scroll_container_content->add_child(vertex_operations_container);

	action_label = memnew(Label);
	action_label->set_text("= Vertex =");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	vertex_operations_container->add_child(action_label);

	action_button = memnew(Button);
	action_button->set_text("Create Face");
	action_button->connect("pressed", this, "on_create_face_pressed");
	vertex_operations_container->add_child(action_button);

	action_label = memnew(Label);
	action_label->set_text("Connect");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	vertex_operations_container->add_child(action_label);

	HBoxContainer *vertex_connect_operations_container = memnew(HBoxContainer);
	vertex_operations_container->add_child(vertex_connect_operations_container);

	action_button = memnew(Button);
	action_button->set_text("x<");
	action_button->set_tooltip("Move all vertices to the first one that was selected.");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("pressed", this, "on_connect_to_first_selected_pressed");
	vertex_connect_operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text(">x<");
	action_button->set_tooltip("Move all selected vertices to their average.");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("pressed", this, "on_connect_to_avg_pressed");
	vertex_connect_operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text(">x");
	action_button->set_tooltip("Move all selected vertices to the last that was selected.");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("pressed", this, "on_connect_to_last_selected_pressed");
	vertex_connect_operations_container->add_child(action_button);

	// -- Scroll -- Edge Operations
	edge_operations_container = memnew(VBoxContainer);
	edge_operations_container->hide();
	scroll_container_content->add_child(edge_operations_container);

	action_label = memnew(Label);
	action_label->set_text("= Edge =");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	edge_operations_container->add_child(action_label);

	action_button = memnew(Button);
	action_button->set_text("Extrude");
	action_button->connect("pressed", this, "on_extrude_pressed");
	edge_operations_container->add_child(action_button);

	action_label = memnew(Label);
	action_label->set_text("Append");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	edge_operations_container->add_child(action_label);

	HBoxContainer *edge_operations_sub_container = memnew(HBoxContainer);
	edge_operations_container->add_child(edge_operations_sub_container);

	action_button = memnew(Button);
	action_button->set_text("Tri");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("pressed", this, "on_add_triangle_at_pressed");
	edge_operations_sub_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Quad");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("pressed", this, "on_add_quad_at_pressed");
	edge_operations_sub_container->add_child(action_button);

	action_label = memnew(Label);
	action_label->set_text("Seam");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	edge_operations_container->add_child(action_label);

	edge_operations_sub_container = memnew(HBoxContainer);
	edge_operations_container->add_child(edge_operations_sub_container);

	action_button = memnew(Button);
	action_button->set_text("Mark");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("pressed", this, "on_mark_seam_pressed");
	edge_operations_sub_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Unmark");
	action_button->set_h_size_flags(SIZE_EXPAND_FILL);
	action_button->connect("pressed", this, "on_unmark_seam_pressed");
	edge_operations_sub_container->add_child(action_button);

	// -- Scroll -- Face Operations
	face_operations_container = memnew(VBoxContainer);
	face_operations_container->hide();
	scroll_container_content->add_child(face_operations_container);

	action_label = memnew(Label);
	action_label->set_text("= Face =");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	face_operations_container->add_child(action_label);

	action_button = memnew(Button);
	action_button->set_text("Delete");
	action_button->connect("pressed", this, "on_delete_pressed");
	face_operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Flip");
	action_button->connect("pressed", this, "on_flip_face_pressed");
	face_operations_container->add_child(action_button);

	// -- Scroll -- Separator
	scroll_container_content->add_child(memnew(HSeparator));

	// -- Scroll -- Operations
	VBoxContainer *operations_container = memnew(VBoxContainer);
	scroll_container_content->add_child(operations_container);

	action_label = memnew(Label);
	action_label->set_text("= Operations =");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	operations_container->add_child(action_label);

	action_label = memnew(Label);
	action_label->set_text("Generate");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	operations_container->add_child(action_label);

	action_button = memnew(Button);
	action_button->set_text("Normals");
	action_button->connect("pressed", this, "on_generate_normals_pressed");
	operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Tangents");
	action_button->connect("pressed", this, "on_remove_doubles_pressed");
	operations_container->add_child(action_button);

	action_label = memnew(Label);
	action_label->set_text("Optimizations");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	operations_container->add_child(action_label);

	action_button = memnew(Button);
	action_button->set_text("Rem Doubles");
	action_button->connect("pressed", this, "on_remove_doubles_pressed");
	operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Full Merge");
	action_button->connect("pressed", this, "on_merge_optimize_pressed");
	operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Clean");
	action_button->set_tooltip("Clean mesh for example for unused verts.");
	action_button->connect("pressed", this, "on_clean_mesh_pressed");
	operations_container->add_child(action_button);

	action_label = memnew(Label);
	action_label->set_text("UV");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	operations_container->add_child(action_label);

	uv_preview = memnew(MDREdUVPreviewer);
	uv_preview->set_custom_minimum_size(Point2(100, 100));
	operations_container->add_child(uv_preview);

	action_button = memnew(Button);
	action_button->set_text("Edit");
	action_button->connect("pressed", this, "on_uv_edit_pressed");
	operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Apply seams");
	action_button->connect("pressed", this, "on_apply_seams_pressed");
	operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Unwrap");
	action_button->connect("pressed", this, "on_unwrap_button_pressed");
	operations_container->add_child(action_button);

	// -- Scroll -- Separator
	scroll_container_content->add_child(memnew(HSeparator));

	// -- Scroll -- Add
	VBoxContainer *add_operations_container = memnew(VBoxContainer);
	scroll_container_content->add_child(add_operations_container);

	action_label = memnew(Label);
	action_label->set_text("= Add =");
	action_label->set_align(Label::ALIGN_CENTER);
	action_label->set_valign(Label::VALIGN_CENTER);
	add_operations_container->add_child(action_label);

	action_button = memnew(Button);
	action_button->set_text("Box");
	action_button->connect("pressed", this, "on_add_box_pressed");
	add_operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Tri");
	action_button->connect("pressed", this, "on_add_triangle_pressed");
	add_operations_container->add_child(action_button);

	action_button = memnew(Button);
	action_button->set_text("Quad");
	action_button->connect("pressed", this, "on_add_quad_pressed");
	add_operations_container->add_child(action_button);

	// -- Scroll -- Separator
	scroll_container_content->add_child(memnew(HSeparator));

	//Popups
	Control *popups_node = memnew(Control);
	popups_node->set_mouse_filter(MOUSE_FILTER_IGNORE);
	add_child(popups_node);

	uv_editor = memnew(MDRUVRectEditorPopup);
	uv_editor->set_title("UV Editor");
	uv_editor->set_resizable(true);
	uv_editor->hide();
	popups_node->add_child(uv_editor);

	_edit_mode_button = memnew(Button);
	_edit_mode_button->set_flat(true);
	_edit_mode_button->set_toggle_mode(true);
	_edit_mode_button->set_focus_mode(BaseButton::FOCUS_NONE);
	//_edit_mode_button->set_text("Edit");
	_edit_mode_button->set_tooltip(TTR("Edit MeshDataResource."));
	_edit_mode_button->connect("toggled", this, "_edit_mode_toggled");
	SpatialEditor::get_singleton()->add_control_to_menu_panel(_edit_mode_button);
	_edit_mode_button->hide();

	_editing = false;
}

MDIEd::~MDIEd() {
}

void MDIEd::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_ENTER_TREE: {
			_edit_mode_button->set_icon(get_theme_icon("MeshDataResourceEdit", "EditorIcons"));
		} break;
	}
}

void MDIEd::_edit_mode_toggled(const bool pressed) {
	_editing = pressed;

	make_visible(_editing);
}

void MDIEd::_bind_methods() {
	ClassDB::bind_method(D_METHOD("on_edit_mode_translate_toggled"), &MDIEd::on_edit_mode_translate_toggled);
	ClassDB::bind_method(D_METHOD("on_edit_mode_rotate_toggled"), &MDIEd::on_edit_mode_rotate_toggled);
	ClassDB::bind_method(D_METHOD("on_edit_mode_scale_toggled"), &MDIEd::on_edit_mode_scale_toggled);

	ClassDB::bind_method(D_METHOD("on_axis_x_toggled"), &MDIEd::on_axis_x_toggled);
	ClassDB::bind_method(D_METHOD("on_axis_y_toggled"), &MDIEd::on_axis_y_toggled);
	ClassDB::bind_method(D_METHOD("on_axis_z_toggled"), &MDIEd::on_axis_z_toggled);

	ClassDB::bind_method(D_METHOD("on_selection_mode_vertex_toggled"), &MDIEd::on_selection_mode_vertex_toggled);
	ClassDB::bind_method(D_METHOD("on_selection_mode_edge_toggled"), &MDIEd::on_selection_mode_edge_toggled);
	ClassDB::bind_method(D_METHOD("on_selection_mode_face_toggled"), &MDIEd::on_selection_mode_face_toggled);

	ClassDB::bind_method(D_METHOD("on_handle_selection_type_front_toggled"), &MDIEd::on_handle_selection_type_front_toggled);
	ClassDB::bind_method(D_METHOD("on_handle_selection_type_back_toggled"), &MDIEd::on_handle_selection_type_back_toggled);
	ClassDB::bind_method(D_METHOD("on_handle_selection_type_all_toggled"), &MDIEd::on_handle_selection_type_all_toggled);

	ClassDB::bind_method(D_METHOD("on_pivot_average_toggled"), &MDIEd::on_pivot_average_toggled);
	ClassDB::bind_method(D_METHOD("on_pivot_mdi_origin_toggled"), &MDIEd::on_pivot_mdi_origin_toggled);
	ClassDB::bind_method(D_METHOD("on_pivot_world_origin_toggled"), &MDIEd::on_pivot_world_origin_toggled);

	ClassDB::bind_method(D_METHOD("on_visual_indicator_outline_toggled"), &MDIEd::on_visual_indicator_outline_toggled);
	ClassDB::bind_method(D_METHOD("on_visual_indicator_seam_toggled"), &MDIEd::on_visual_indicator_seam_toggled);
	ClassDB::bind_method(D_METHOD("on_visual_indicator_handle_toggled"), &MDIEd::on_visual_indicator_handle_toggled);

	ClassDB::bind_method(D_METHOD("on_select_all_pressed"), &MDIEd::on_select_all_pressed);

	//Vertex
	ClassDB::bind_method(D_METHOD("on_create_face_pressed"), &MDIEd::on_create_face_pressed);
	//ClassDB::bind_method(D_METHOD("on_split_pressed"), &MDIEd::on_split_pressed);
	ClassDB::bind_method(D_METHOD("on_connect_to_first_selected_pressed"), &MDIEd::on_connect_to_first_selected_pressed);
	ClassDB::bind_method(D_METHOD("on_connect_to_avg_pressed"), &MDIEd::on_connect_to_avg_pressed);
	ClassDB::bind_method(D_METHOD("on_connect_to_last_selected_pressed"), &MDIEd::on_connect_to_last_selected_pressed);

	//Edge
	ClassDB::bind_method(D_METHOD("on_extrude_pressed"), &MDIEd::on_extrude_pressed);
	ClassDB::bind_method(D_METHOD("on_add_triangle_at_pressed"), &MDIEd::on_add_triangle_at_pressed);
	ClassDB::bind_method(D_METHOD("on_add_quad_at_pressed"), &MDIEd::on_add_quad_at_pressed);
	ClassDB::bind_method(D_METHOD("on_mark_seam_pressed"), &MDIEd::on_mark_seam_pressed);
	ClassDB::bind_method(D_METHOD("on_unmark_seam_pressed"), &MDIEd::on_unmark_seam_pressed);

	//Face
	ClassDB::bind_method(D_METHOD("on_delete_pressed"), &MDIEd::on_delete_pressed);
	ClassDB::bind_method(D_METHOD("on_flip_face_pressed"), &MDIEd::on_flip_face_pressed);

	//Operations
	ClassDB::bind_method(D_METHOD("on_generate_normals_pressed"), &MDIEd::on_generate_normals_pressed);
	ClassDB::bind_method(D_METHOD("on_generate_tangents_pressed"), &MDIEd::on_generate_tangents_pressed);

	ClassDB::bind_method(D_METHOD("on_remove_doubles_pressed"), &MDIEd::on_remove_doubles_pressed);
	ClassDB::bind_method(D_METHOD("on_merge_optimize_pressed"), &MDIEd::on_merge_optimize_pressed);
	ClassDB::bind_method(D_METHOD("on_clean_mesh_pressed"), &MDIEd::on_clean_mesh_pressed);

	ClassDB::bind_method(D_METHOD("on_uv_edit_pressed"), &MDIEd::on_uv_edit_pressed);
	ClassDB::bind_method(D_METHOD("on_apply_seams_pressed"), &MDIEd::on_apply_seams_pressed);
	ClassDB::bind_method(D_METHOD("on_unwrap_button_pressed"), &MDIEd::on_unwrap_button_pressed);

	ClassDB::bind_method(D_METHOD("on_add_box_pressed"), &MDIEd::on_add_box_pressed);
	ClassDB::bind_method(D_METHOD("on_add_triangle_pressed"), &MDIEd::on_add_triangle_pressed);
	ClassDB::bind_method(D_METHOD("on_add_quad_pressed"), &MDIEd::on_add_quad_pressed);

	ClassDB::bind_method(D_METHOD("_edit_mode_toggled"), &MDIEd::_edit_mode_toggled);
}