void MeshInstanceEditor::_create_outline_mesh() {

    Ref<Mesh> mesh = node->get_mesh();
    if (mesh.is_null()) {
        err_dialog->set_text(TTR("MeshInstance lacks a Mesh!"));
        err_dialog->popup_centered_minsize();
        return;
    }

    Ref<Mesh> mesho = mesh->create_outline(outline_size->get_val());

    if (mesho.is_null()) {
        err_dialog->set_text(TTR("Could not create outline!"));
        err_dialog->popup_centered_minsize();
        return;
    }

    MeshInstance *mi = memnew( MeshInstance );
    mi->set_mesh(mesho);
    Node *owner=node->get_owner();
    if (get_tree()->get_edited_scene_root()==node) {
        owner=node;
    }

    UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();

    ur->create_action(TTR("Create Outline"));

    ur->add_do_method(node,"add_child",mi);
    ur->add_do_method(mi,"set_owner",owner);

    ur->add_do_reference(mi);
    ur->add_undo_method(node,"remove_child",mi);
    ur->commit_action();
}
void SkeletonEditor::create_physical_skeleton() {
	UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
	Node *owner = skeleton == get_tree()->get_edited_scene_root() ? skeleton : skeleton->get_owner();

	const int bc = skeleton->get_bone_count();

	if (!bc) {
		return;
	}

	Vector<BoneInfo> bones_infos;
	bones_infos.resize(bc);

	for (int bone_id = 0; bc > bone_id; ++bone_id) {

		const int parent = skeleton->get_bone_parent(bone_id);
		const int parent_parent = skeleton->get_bone_parent(parent);

		if (parent < 0) {

			bones_infos.write[bone_id].relative_rest = skeleton->get_bone_rest(bone_id);

		} else {

			bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id);

			/// create physical bone on parent
			if (!bones_infos[parent].physical_bone) {

				bones_infos.write[parent].physical_bone = create_physical_bone(parent, bone_id, bones_infos);

				ur->create_action(TTR("Create physical bones"));
				ur->add_do_method(skeleton, "add_child", bones_infos[parent].physical_bone);
				ur->add_do_reference(bones_infos[parent].physical_bone);
				ur->add_undo_method(skeleton, "remove_child", bones_infos[parent].physical_bone);
				ur->commit_action();

				bones_infos[parent].physical_bone->set_bone_name(skeleton->get_bone_name(parent));
				bones_infos[parent].physical_bone->set_owner(owner);
				bones_infos[parent].physical_bone->get_child(0)->set_owner(owner); // set shape owner

				/// Create joint between parent of parent
				if (-1 != parent_parent) {

					bones_infos[parent].physical_bone->set_joint_type(PhysicalBone::JOINT_TYPE_PIN);
				}
			}
		}
	}
}
void MeshInstanceEditor::_menu_option(int p_option) {

	Ref<Mesh> mesh = node->get_mesh();
	if (mesh.is_null()) {
		err_dialog->set_text(TTR("Mesh is empty!"));
		err_dialog->popup_centered_minsize();
		return;
	}

	switch (p_option) {
		case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY:
		case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: {

			bool trimesh_shape = (p_option == MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);

			EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();

			List<Node *> selection = editor_selection->get_selected_node_list();

			if (selection.empty()) {
				Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape();
				if (shape.is_null())
					return;

				CollisionShape *cshape = memnew(CollisionShape);
				cshape->set_shape(shape);
				StaticBody *body = memnew(StaticBody);
				body->add_child(cshape);

				Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner();

				if (trimesh_shape)
					ur->create_action(TTR("Create Static Trimesh Body"));
				else
					ur->create_action(TTR("Create Static Convex Body"));

				ur->add_do_method(node, "add_child", body);
				ur->add_do_method(body, "set_owner", owner);
				ur->add_do_method(cshape, "set_owner", owner);
				ur->add_do_reference(body);
				ur->add_undo_method(node, "remove_child", body);
				ur->commit_action();
				return;
			}

			if (trimesh_shape)
				ur->create_action(TTR("Create Static Trimesh Body"));
			else
				ur->create_action(TTR("Create Static Convex Body"));

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

				MeshInstance *instance = E->get()->cast_to<MeshInstance>();
				if (!instance)
					continue;

				Ref<Mesh> m = instance->get_mesh();
				if (m.is_null())
					continue;

				Ref<Shape> shape = trimesh_shape ? m->create_trimesh_shape() : m->create_convex_shape();
				if (shape.is_null())
					continue;

				CollisionShape *cshape = memnew(CollisionShape);
				cshape->set_shape(shape);
				StaticBody *body = memnew(StaticBody);
				body->add_child(cshape);

				Node *owner = instance == get_tree()->get_edited_scene_root() ? instance : instance->get_owner();

				ur->add_do_method(instance, "add_child", body);
				ur->add_do_method(body, "set_owner", owner);
				ur->add_do_method(cshape, "set_owner", owner);
				ur->add_do_reference(body);
				ur->add_undo_method(instance, "remove_child", body);
			}

			ur->commit_action();

		} break;

		case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE:
		case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {

			if (node == get_tree()->get_edited_scene_root()) {
				err_dialog->set_text(TTR("This doesn't work on scene root!"));
				err_dialog->popup_centered_minsize();
				return;
			}

			bool trimesh_shape = (p_option == MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);

			Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape();
			if (shape.is_null())
				return;

			CollisionShape *cshape = memnew(CollisionShape);
			cshape->set_shape(shape);

			Node *owner = node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();

			if (trimesh_shape)
				ur->create_action(TTR("Create Trimesh Shape"));
			else
				ur->create_action(TTR("Create Convex Shape"));

			ur->add_do_method(node->get_parent(), "add_child", cshape);
			ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1);
			ur->add_do_method(cshape, "set_owner", owner);
			ur->add_do_reference(cshape);
			ur->add_undo_method(node->get_parent(), "remove_child", cshape);
			ur->commit_action();

		} break;

		case MENU_OPTION_CREATE_NAVMESH: {

			Ref<NavigationMesh> nmesh = memnew(NavigationMesh);

			if (nmesh.is_null())
				return;

			nmesh->create_from_mesh(mesh);
			NavigationMeshInstance *nmi = memnew(NavigationMeshInstance);
			nmi->set_navigation_mesh(nmesh);

			Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner();

			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
			ur->create_action(TTR("Create Navigation Mesh"));

			ur->add_do_method(node, "add_child", nmi);
			ur->add_do_method(nmi, "set_owner", owner);

			ur->add_do_reference(nmi);
			ur->add_undo_method(node, "remove_child", nmi);
			ur->commit_action();
		} break;

		case MENU_OPTION_CREATE_OUTLINE_MESH: {

			outline_dialog->popup_centered(Vector2(200, 90));
		} break;
	}
}