feat(wip): implementing edit history and un-re-do
This commit is contained in:
parent
b875c2089b
commit
e2926f7c3f
33
modules/terrain_editor/edit_history.cpp
Normal file
33
modules/terrain_editor/edit_history.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#include "edit_history.h"
|
||||
#include "macros.h"
|
||||
|
||||
EditHistory *EditHistory::singleton_instance{ nullptr };
|
||||
|
||||
void EditHistory::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("push_action", "do_action", "undo_action"), &self_type::push_action);
|
||||
ClassDB::bind_method(D_METHOD("undo_last"), &self_type::undo);
|
||||
ClassDB::bind_method(D_METHOD("redo_last"), &self_type::redo);
|
||||
}
|
||||
|
||||
void EditHistory::push_action(Callable do_action, Callable undo_action) {
|
||||
if (this->undo_count != 0) {
|
||||
this->history.resize(this->history.size() - this->undo_count);
|
||||
this->undo_count = 0;
|
||||
}
|
||||
do_action.call();
|
||||
this->history.push_back({ do_action, undo_action });
|
||||
}
|
||||
|
||||
void EditHistory::undo() {
|
||||
if (this->undo_count + 1 < this->history.size()) {
|
||||
this->undo_count++;
|
||||
this->history[this->history.size() - this->undo_count].undo_action.call();
|
||||
}
|
||||
}
|
||||
|
||||
void EditHistory::redo() {
|
||||
if (this->undo_count > 1) {
|
||||
this->undo_count--;
|
||||
this->history[this->history.size() - this->undo_count].do_action.call();
|
||||
}
|
||||
}
|
||||
27
modules/terrain_editor/edit_history.h
Normal file
27
modules/terrain_editor/edit_history.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/object.h"
|
||||
#include "core/variant/callable.h"
|
||||
#include "terrain_editor/register_types.h"
|
||||
|
||||
class EditHistory : public Object {
|
||||
GDCLASS(EditHistory, Object);
|
||||
static void _bind_methods();
|
||||
static EditHistory *singleton_instance;
|
||||
friend void initialize_terrain_editor_module(ModuleInitializationLevel p_level);
|
||||
struct EditAction {
|
||||
Callable do_action;
|
||||
Callable undo_action;
|
||||
};
|
||||
|
||||
public:
|
||||
static EditHistory *get_singleton() { return singleton_instance; }
|
||||
void push_action(Callable do_action, Callable undo_action);
|
||||
void undo();
|
||||
void redo();
|
||||
|
||||
private:
|
||||
size_t undo_count{ 0 };
|
||||
Vector<EditAction> history{};
|
||||
};
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
#include "point_primitive_node.h"
|
||||
#include "scene/3d/node_3d.h"
|
||||
#include "terrain_editor/edit_history.h"
|
||||
#include "terrain_editor/macros.h"
|
||||
#include "terrain_editor/terrain_primitive.h"
|
||||
|
||||
void PointPrimitiveNode::_bind_methods() {
|
||||
BIND_GET_SET(primitive);
|
||||
|
|
@ -32,8 +34,17 @@ void PointPrimitiveNode::push_transform_changes() {
|
|||
if (this->primitive.is_valid()) {
|
||||
this->pushing_change = true;
|
||||
Vector3 const position{ get_global_position() };
|
||||
this->primitive->set_center({ position.x, position.z });
|
||||
this->primitive->set_height(position.y);
|
||||
Vector2 const center{ position.x, position.z };
|
||||
if (center != this->primitive->get_center()) {
|
||||
EditHistory::get_singleton()->push_action(
|
||||
callable_mp(*this->primitive, &PointPrimitive::set_center).bind(center),
|
||||
callable_mp(*this->primitive, &PointPrimitive::set_center).bind(this->primitive->get_center()));
|
||||
}
|
||||
if (position.y != this->primitive->get_height()) {
|
||||
EditHistory::get_singleton()->push_action(
|
||||
callable_mp(*this->primitive, &PointPrimitive::set_height).bind(position.y),
|
||||
callable_mp(*this->primitive, &PointPrimitive::set_height).bind(this->primitive->get_height()));
|
||||
}
|
||||
this->pushing_change = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#include "register_types.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "terrain_editor/edit_history.h"
|
||||
#include "terrain_editor/point_primitive_node.h"
|
||||
#include "terrain_editor/terrain_chunk.h"
|
||||
#include "terrain_editor/terrain_mesh_editor.h"
|
||||
|
|
@ -21,10 +24,13 @@ void initialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
|||
ClassDB::register_class<TerrainMeshEditor>();
|
||||
ClassDB::register_class<SaveData>();
|
||||
ClassDB::register_class<TerrainChunk>();
|
||||
ClassDB::register_class<EditHistory>();
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("EditHistory", (EditHistory::singleton_instance = memnew(EditHistory)), "EditHistory"));
|
||||
}
|
||||
|
||||
void uninitialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
memdelete_notnull(EditHistory::get_singleton());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "scene/3d/node_3d.h"
|
||||
#include "scene/gui/file_dialog.h"
|
||||
#include "scene/resources/packed_scene.h"
|
||||
#include "terrain_editor/edit_history.h"
|
||||
#include "terrain_editor/macros.h"
|
||||
#include "terrain_editor/point_primitive_node.h"
|
||||
#include "terrain_editor/terrain_primitive.h"
|
||||
|
|
@ -110,15 +111,24 @@ void TerrainMeshEditor::_notification(int what) {
|
|||
void TerrainMeshEditor::unhandled_input(Ref<InputEvent> const &event) {
|
||||
Ref<InputEventKey> key{ event };
|
||||
if (key.is_valid() && key->get_key_label() == Key::S && key->get_modifiers_mask() == (KeyModifierMask::SHIFT | KeyModifierMask::CTRL)) {
|
||||
get_viewport()->set_input_as_handled();
|
||||
this->file_dialog->set_file_mode(FileDialog::FILE_MODE_SAVE_FILE);
|
||||
this->file_dialog->set_ok_button_text("Save");
|
||||
this->file_dialog->popup_file_dialog();
|
||||
} else if (key.is_valid() && key->get_key_label() == Key::S && key->get_modifiers_mask() == KeyModifierMask::CTRL) {
|
||||
get_viewport()->set_input_as_handled();
|
||||
save_data();
|
||||
} else if (key.is_valid() && key->get_key_label() == Key::O && key->get_modifiers_mask() == KeyModifierMask::CTRL) {
|
||||
get_viewport()->set_input_as_handled();
|
||||
this->file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE);
|
||||
this->file_dialog->set_ok_button_text("Open");
|
||||
this->file_dialog->popup_file_dialog();
|
||||
} else if (key.is_valid() && key->get_key_label() == Key::Z && key->get_modifiers_mask() == KeyModifierMask::CTRL) {
|
||||
get_viewport()->set_input_as_handled();
|
||||
EditHistory::get_singleton()->undo();
|
||||
} else if (key.is_valid() && key->get_key_label() == Key::Z && key->get_modifiers_mask() == (KeyModifierMask::CTRL | KeyModifierMask::SHIFT)) {
|
||||
get_viewport()->set_input_as_handled();
|
||||
EditHistory::get_singleton()->redo();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ func _input(event: InputEvent) -> void:
|
|||
|
||||
func _input_event(_camera: Camera3D, event: InputEvent, _event_position: Vector3, _normal: Vector3, _shape_idx: int) -> void:
|
||||
if not dragged and event is InputEventMouseButton and (event as InputEventMouseButton).is_pressed():
|
||||
get_viewport().set_input_as_handled()
|
||||
dragged = true
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
get_viewport().set_input_as_handled()
|
||||
"
|
||||
|
||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_mx0s0"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue