feat: implemented saving & loading
This commit is contained in:
parent
6724c38968
commit
61ba2a54f2
|
|
@ -18,6 +18,7 @@ void initialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
|||
ClassDB::register_class<ExpressionPrimitive>();
|
||||
ClassDB::register_class<PointPrimitiveNode>();
|
||||
ClassDB::register_class<TerrainMeshEditor>();
|
||||
ClassDB::register_class<SaveData>();
|
||||
}
|
||||
|
||||
void uninitialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
||||
|
|
|
|||
|
|
@ -1,20 +1,59 @@
|
|||
#include "terrain_mesh_editor.h"
|
||||
#include "core/input/input_event.h"
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "core/os/keyboard.h"
|
||||
#include "scene/3d/node_3d.h"
|
||||
#include "scene/gui/file_dialog.h"
|
||||
#include "scene/resources/packed_scene.h"
|
||||
#include "terrain_editor/macros.h"
|
||||
#include "terrain_editor/point_primitive_node.h"
|
||||
#include "terrain_editor/terrain_primitive.h"
|
||||
|
||||
void SaveData::_bind_methods() {
|
||||
BIND_HPROPERTY(Variant::ARRAY, primitives, PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:TerrainPrimitive", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE));
|
||||
}
|
||||
|
||||
void SaveData::write_to_file() {
|
||||
ResourceSaver::save(this, this->save_file_path, ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES | ResourceSaver::FLAG_BUNDLE_RESOURCES);
|
||||
}
|
||||
|
||||
void SaveData::set_save_path(String value) {
|
||||
this->save_file_path = value;
|
||||
}
|
||||
|
||||
String SaveData::get_save_path() const {
|
||||
return this->save_file_path;
|
||||
}
|
||||
|
||||
void SaveData::set_primitives(Array array) {
|
||||
this->primitives = array.duplicate(true); // do a full deep copy of the data, to avoid modification before saving
|
||||
}
|
||||
|
||||
Array SaveData::get_primitives() const {
|
||||
return this->primitives;
|
||||
}
|
||||
|
||||
void TerrainMeshEditor::_bind_methods() {
|
||||
BIND_HPROPERTY(Variant::OBJECT, point_primitive_object, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene");
|
||||
ClassDB::bind_method(D_METHOD("save_data"), &self_type::save_data);
|
||||
}
|
||||
|
||||
void TerrainMeshEditor::ready() {
|
||||
connect(sig_primitive_list_changed, callable_mp(this, &self_type::on_primitive_list_changed));
|
||||
on_primitive_list_changed(get_primitives());
|
||||
if (FileDialog * dialog{ memnew(FileDialog) }) {
|
||||
this->file_dialog = dialog;
|
||||
add_child(dialog);
|
||||
dialog->set_filters({ "*.terrain.tres;World Resource Files;", "*.terrain.res;Binary World Resource Files;" });
|
||||
dialog->set_access(FileDialog::ACCESS_FILESYSTEM);
|
||||
dialog->connect("file_selected", callable_mp(this, &self_type::on_save_file_selected));
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainMeshEditor::on_primitive_list_changed(Array primitives) {
|
||||
this->out_of_date = true;
|
||||
for (Node3D *existing : this->primitive_nodes) {
|
||||
existing->queue_free();
|
||||
}
|
||||
|
|
@ -26,11 +65,34 @@ void TerrainMeshEditor::on_primitive_list_changed(Array primitives) {
|
|||
PointPrimitiveNode *primitive_node{ cast_to<PointPrimitiveNode>(this->point_primitive_object->instantiate()) };
|
||||
primitive_node->set_primitive(point);
|
||||
this->add_child(primitive_node);
|
||||
this->primitive_nodes.push_back(primitive_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainMeshEditor::on_save_file_selected(String path) {
|
||||
switch (this->file_dialog->get_file_mode()) {
|
||||
default:
|
||||
print_error("Attempt to open or save with invalid file dialog mode");
|
||||
break;
|
||||
case FileDialog::FILE_MODE_SAVE_FILE:
|
||||
this->data->set_save_path(path);
|
||||
this->data->set_primitives(get_primitives());
|
||||
this->data->write_to_file();
|
||||
break;
|
||||
case FileDialog::FILE_MODE_OPEN_FILE:
|
||||
Ref<Resource> resource{ ResourceLoader::load(path, "SaveData", ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP) };
|
||||
Ref<SaveData> loaded_data{ resource };
|
||||
if (loaded_data.is_valid()) {
|
||||
this->data = loaded_data;
|
||||
this->set_primitives(this->data->get_primitives().duplicate(true));
|
||||
this->data->set_save_path(path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainMeshEditor::_notification(int what) {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
return;
|
||||
|
|
@ -39,11 +101,42 @@ void TerrainMeshEditor::_notification(int what) {
|
|||
default:
|
||||
return;
|
||||
case NOTIFICATION_READY:
|
||||
set_process_unhandled_input(true);
|
||||
ready();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
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) {
|
||||
save_data();
|
||||
} else if (key.is_valid() && key->get_key_label() == Key::O && key->get_modifiers_mask() == KeyModifierMask::CTRL) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainMeshEditor::save_data() {
|
||||
// TODO: figure out if this is the correct way to see if the popup is popped up
|
||||
if (this->file_dialog->is_visible()) {
|
||||
return;
|
||||
}
|
||||
if (this->data->get_save_path().is_empty()) {
|
||||
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 {
|
||||
this->data->set_primitives(get_primitives());
|
||||
this->data->write_to_file();
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainMeshEditor::set_point_primitive_object(Ref<PackedScene> scene) {
|
||||
this->point_primitive_object = scene;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/io/resource.h"
|
||||
#include "scene/gui/file_dialog.h"
|
||||
#include "terrain_editor/terrain_mesh_generator.h"
|
||||
|
||||
class SaveData : public Resource {
|
||||
GDCLASS(SaveData, Resource);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void write_to_file();
|
||||
void set_save_path(String value);
|
||||
String get_save_path() const;
|
||||
void set_primitives(Array primitives);
|
||||
Array get_primitives() const;
|
||||
|
||||
private:
|
||||
String save_file_path{};
|
||||
Array primitives{};
|
||||
};
|
||||
|
||||
class TerrainMeshEditor : public TerrainMeshGenerator {
|
||||
GDCLASS(TerrainMeshEditor, TerrainMeshGenerator);
|
||||
static void _bind_methods();
|
||||
void ready();
|
||||
void on_primitive_list_changed(Array primitives);
|
||||
void on_primitive_node_removed();
|
||||
void on_save_file_selected(String path);
|
||||
|
||||
protected:
|
||||
void _notification(int what);
|
||||
virtual void unhandled_input(Ref<InputEvent> const &event) override;
|
||||
|
||||
public:
|
||||
void save_data();
|
||||
void set_point_primitive_object(Ref<PackedScene> scene);
|
||||
Ref<PackedScene> get_point_primitive_object() const;
|
||||
|
||||
private:
|
||||
Ref<SaveData> data{ memnew(SaveData) };
|
||||
FileDialog *file_dialog{};
|
||||
bool out_of_date{ false };
|
||||
Vector<Node3D *> primitive_nodes{};
|
||||
Ref<PackedScene> point_primitive_object{};
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue