147 lines
5.1 KiB
C++
147 lines
5.1 KiB
C++
#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();
|
|
}
|
|
this->primitive_nodes.clear();
|
|
for (Variant var : primitives) {
|
|
if (this->point_primitive_object.is_valid() && this->point_primitive_object->get_state()->get_node_type(0) == PointPrimitiveNode::get_class_static()) {
|
|
Ref<PointPrimitive> point{ var };
|
|
if (point.is_valid()) {
|
|
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;
|
|
}
|
|
switch (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;
|
|
}
|
|
|
|
Ref<PackedScene> TerrainMeshEditor::get_point_primitive_object() const {
|
|
return this->point_primitive_object;
|
|
}
|