Moved "Update From Scene" button to multimesh item inspector

master
Marc Gilleron 2022-08-21 20:18:29 +01:00
parent 414d1ce2b8
commit 90dbf9418e
9 changed files with 144 additions and 58 deletions

View File

@ -52,12 +52,8 @@ void VoxelInstanceLibraryEditorPlugin::_notification(int p_what) {
// otherwise `add_inspector_plugin` causes ANOTHER editor plugin to leak on exit... Oo
add_inspector_plugin(_inspector_plugin);
_multimesh_item_inspector_plugin.instantiate();
add_inspector_plugin(_multimesh_item_inspector_plugin);
} else if (p_what == NOTIFICATION_EXIT_TREE) {
remove_inspector_plugin(_inspector_plugin);
remove_inspector_plugin(_multimesh_item_inspector_plugin);
}
}
@ -88,15 +84,6 @@ void VoxelInstanceLibraryEditorPlugin::_on_button_pressed(int id) {
ur.commit_action();
} break;
case VoxelInstanceLibraryInspectorPlugin::BUTTON_UPDATE_MULTIMESH_ITEM_FROM_SCENE: {
ERR_FAIL_COND(_library.is_null());
const int item_id = try_get_selected_item_id();
if (item_id != -1) {
_item_id_to_update = item_id;
_open_scene_dialog->popup_centered_ratio();
}
} break;
case VoxelInstanceLibraryInspectorPlugin::BUTTON_ADD_SCENE_ITEM: {
_open_scene_dialog->popup_centered_ratio();
} break;
@ -161,10 +148,6 @@ void VoxelInstanceLibraryEditorPlugin::_on_open_scene_dialog_file_selected(Strin
add_scene_item(fpath);
break;
case VoxelInstanceLibraryInspectorPlugin::BUTTON_UPDATE_MULTIMESH_ITEM_FROM_SCENE:
update_multimesh_item_from_scene(fpath, _item_id_to_update);
break;
default:
ERR_PRINT("Invalid menu option");
break;
@ -196,33 +179,6 @@ void VoxelInstanceLibraryEditorPlugin::add_scene_item(String fpath) {
ur.commit_action();
}
void VoxelInstanceLibraryEditorPlugin::update_multimesh_item_from_scene(String fpath, int item_id) {
ERR_FAIL_COND(_library.is_null());
Ref<PackedScene> scene = ResourceLoader::load(fpath);
ERR_FAIL_COND(scene.is_null());
Ref<VoxelInstanceLibraryItem> item_base = _library->get_item(item_id);
ERR_FAIL_COND_MSG(item_base.is_null(), "Item not found");
Ref<VoxelInstanceLibraryMultiMeshItem> item = item_base;
ERR_FAIL_COND_MSG(item.is_null(), "Item not using multimeshes");
Node *node = scene->instantiate();
ERR_FAIL_COND(node == nullptr);
Variant data_before = item->serialize_multimesh_item_properties();
item->setup_from_template(node);
Variant data_after = item->serialize_multimesh_item_properties();
memdelete(node);
UndoRedo &ur = get_undo_redo();
ur.create_action("Update Multimesh Item From Scene");
ur.add_do_method(item.ptr(), "_deserialize_multimesh_item_properties", data_after);
ur.add_undo_method(item.ptr(), "_deserialize_multimesh_item_properties", data_before);
ur.commit_action();
}
void VoxelInstanceLibraryEditorPlugin::_bind_methods() {
// ClassDB::bind_method(D_METHOD("_on_button_pressed", "id"),
// &VoxelInstanceLibraryEditorPlugin::_on_button_pressed); ClassDB::bind_method(

View File

@ -3,7 +3,6 @@
#include "../../terrain/instancing/voxel_instance_library.h"
#include "voxel_instance_library_inspector_plugin.h"
#include "voxel_instance_library_multimesh_item_inspector_plugin.h"
#include <editor/editor_plugin.h>
class Control;
@ -31,7 +30,6 @@ private:
int try_get_selected_item_id();
void add_scene_item(String fpath);
void update_multimesh_item_from_scene(String fpath, int item_id);
void _on_remove_item_confirmed();
void _on_open_scene_dialog_file_selected(String fpath);
@ -47,7 +45,6 @@ private:
Ref<VoxelInstanceLibrary> _library;
Ref<VoxelInstanceLibraryInspectorPlugin> _inspector_plugin;
Ref<VoxelInstanceLibraryMultiMeshItemInspectorPlugin> _multimesh_item_inspector_plugin;
};
} // namespace zylann::voxel

View File

@ -46,14 +46,6 @@ void VoxelInstanceLibraryInspectorPlugin::add_buttons() {
spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL);
hb->add_child(spacer);
Button *button_update = memnew(Button);
// TODO Move this to multimesh items?
button_update->set_text(TTR("Update From Scene..."));
button_update->connect("pressed",
callable_mp(button_listener, &VoxelInstanceLibraryEditorPlugin::_on_button_pressed)
.bind(BUTTON_UPDATE_MULTIMESH_ITEM_FROM_SCENE));
hb->add_child(button_update);
add_custom_control(hb);
}

View File

@ -10,9 +10,8 @@ class VoxelInstanceLibraryEditorPlugin;
class VoxelInstanceLibraryInspectorPlugin : public EditorInspectorPlugin {
GDCLASS(VoxelInstanceLibraryInspectorPlugin, EditorInspectorPlugin)
public:
enum Buttons {
enum Buttons { //
BUTTON_ADD_MULTIMESH_ITEM,
BUTTON_UPDATE_MULTIMESH_ITEM_FROM_SCENE,
BUTTON_ADD_SCENE_ITEM,
BUTTON_REMOVE_ITEM
};

View File

@ -0,0 +1,87 @@
#include "voxel_instance_library_multimesh_item_editor_plugin.h"
#include <editor/editor_file_dialog.h>
namespace zylann::voxel {
VoxelInstanceLibraryMultiMeshItemEditorPlugin::VoxelInstanceLibraryMultiMeshItemEditorPlugin() {
Control *base_control = get_editor_interface()->get_base_control();
_open_scene_dialog = memnew(EditorFileDialog);
List<String> extensions;
ResourceLoader::get_recognized_extensions_for_type(PackedScene::get_class_static(), &extensions);
for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
_open_scene_dialog->add_filter("*." + E->get());
}
_open_scene_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
base_control->add_child(_open_scene_dialog);
_open_scene_dialog->connect("file_selected",
callable_mp(this, &VoxelInstanceLibraryMultiMeshItemEditorPlugin::_on_open_scene_dialog_file_selected));
}
bool VoxelInstanceLibraryMultiMeshItemEditorPlugin::handles(Object *p_object) const {
// TODO Making a plugin handling sub-resources of `VoxelInstanceLibrary` breaks the inspector.
// There are also some caveats when using multiple sub-inspectors. To keep supporting multiple sub-inspectors open
// inside a library, we cannot rely on `edit` giving us edited resources.
// See https://github.com/godotengine/godot/issues/64700
return false;
// const VoxelInstanceLibraryMultiMeshItem *item = Object::cast_to<VoxelInstanceLibraryMultiMeshItem>(p_object);
// return item != nullptr;
}
void VoxelInstanceLibraryMultiMeshItemEditorPlugin::edit(Object *p_object) {
// VoxelInstanceLibraryMultiMeshItem *item = Object::cast_to<VoxelInstanceLibraryMultiMeshItem>(p_object);
// _item.reference_ptr(item);
}
void VoxelInstanceLibraryMultiMeshItemEditorPlugin::make_visible(bool visible) {
// if (!visible) {
// _item.unref();
// }
}
void VoxelInstanceLibraryMultiMeshItemEditorPlugin::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
_inspector_plugin.instantiate();
_inspector_plugin->listener = this;
add_inspector_plugin(_inspector_plugin);
} else if (p_what == NOTIFICATION_EXIT_TREE) {
remove_inspector_plugin(_inspector_plugin);
}
}
void VoxelInstanceLibraryMultiMeshItemEditorPlugin::_on_update_from_scene_button_pressed(
VoxelInstanceLibraryMultiMeshItem *item) {
_item.reference_ptr(item);
ERR_FAIL_COND(_item.is_null());
_open_scene_dialog->popup_centered_ratio();
}
static void update_multimesh_item_from_scene(
VoxelInstanceLibraryMultiMeshItem &item, String scene_file_path, UndoRedo &ur) {
Ref<PackedScene> scene = ResourceLoader::load(scene_file_path);
ERR_FAIL_COND(scene.is_null());
Node *node = scene->instantiate();
ERR_FAIL_COND(node == nullptr);
Variant data_before = item.serialize_multimesh_item_properties();
item.setup_from_template(node);
Variant data_after = item.serialize_multimesh_item_properties();
memdelete(node);
ur.create_action("Update Multimesh Item From Scene");
ur.add_do_method(&item, "_deserialize_multimesh_item_properties", data_after);
ur.add_undo_method(&item, "_deserialize_multimesh_item_properties", data_before);
ur.commit_action();
}
void VoxelInstanceLibraryMultiMeshItemEditorPlugin::_on_open_scene_dialog_file_selected(String fpath) {
ERR_FAIL_COND(_item.is_null());
update_multimesh_item_from_scene(**_item, fpath, get_undo_redo());
// We are done with this item
_item.unref();
}
} // namespace zylann::voxel

View File

@ -0,0 +1,33 @@
#ifndef VOXEL_INSTANCE_LIBRARY_MULTIMESH_ITEM_EDITOR_PLUGIN_H
#define VOXEL_INSTANCE_LIBRARY_MULTIMESH_ITEM_EDITOR_PLUGIN_H
#include "../../terrain/instancing/voxel_instance_library_multimesh_item.h"
#include "voxel_instance_library_multimesh_item_inspector_plugin.h"
#include <editor/editor_plugin.h>
namespace zylann::voxel {
class VoxelInstanceLibraryMultiMeshItemEditorPlugin : public EditorPlugin {
GDCLASS(VoxelInstanceLibraryMultiMeshItemEditorPlugin, EditorPlugin)
public:
VoxelInstanceLibraryMultiMeshItemEditorPlugin();
bool handles(Object *p_object) const override;
void edit(Object *p_object) override;
void make_visible(bool visible) override;
void _on_update_from_scene_button_pressed(VoxelInstanceLibraryMultiMeshItem *item);
private:
void _notification(int p_what);
void _on_open_scene_dialog_file_selected(String fpath);
EditorFileDialog *_open_scene_dialog = nullptr;
Ref<VoxelInstanceLibraryMultiMeshItem> _item;
Ref<VoxelInstanceLibraryMultiMeshItemInspectorPlugin> _inspector_plugin;
};
} // namespace zylann::voxel
#endif // VOXEL_INSTANCE_LIBRARY_MULTIMESH_ITEM_EDITOR_PLUGIN_H

View File

@ -1,5 +1,7 @@
#include "voxel_instance_library_multimesh_item_inspector_plugin.h"
#include "../../terrain/instancing/voxel_instance_library_multimesh_item.h"
#include "voxel_instance_library_editor_plugin.h"
#include "voxel_instance_library_multimesh_item_editor_plugin.h"
namespace zylann::voxel {
@ -11,6 +13,20 @@ void VoxelInstanceLibraryMultiMeshItemInspectorPlugin::parse_group(Object *p_obj
const VoxelInstanceLibraryMultiMeshItem *item = Object::cast_to<VoxelInstanceLibraryMultiMeshItem>(p_object);
ERR_FAIL_COND(item == nullptr);
if (item->get_scene().is_null()) {
ERR_FAIL_COND(listener == nullptr);
// TODO I preferred this at the end of the group, but Godot doesn't expose anything to do it.
// This is a legacy workflow, we'll see if it can be removed later.
Button *button = memnew(Button);
button->set_tooltip(TTR("Set properties based on an existing scene. This might copy mesh and material data if "
"the scene embeds them. Properties will not update if the scene changes later."));
button->set_text(TTR("Update from scene..."));
// Using a bind() instead of relying on "currently edited" item in the editor plugin allows to support multiple
// sub-inspectors. Plugins are not instanced per-inspected-object, but custom controls are.
button->connect("pressed",
callable_mp(
listener, &VoxelInstanceLibraryMultiMeshItemEditorPlugin::_on_update_from_scene_button_pressed)
.bind(item));
add_custom_control(button);
return;
}
@ -20,7 +36,7 @@ void VoxelInstanceLibraryMultiMeshItemInspectorPlugin::parse_group(Object *p_obj
add_custom_control(label);
}
// TODO Button to open scene in editor, since Godot doesn't have that in its resource picker menu?
// Perhaps it should rather be a feature request to Godot
// Perhaps it should rather be a feature request to Godot.
// else if (p_group == VoxelInstanceLibraryMultiMeshItem::SCENE_SETTINGS_GROUP_NAME) {
// ERR_FAIL_COND(listener == nullptr);
// Button *button = memnew(Button);

View File

@ -5,9 +5,13 @@
namespace zylann::voxel {
class VoxelInstanceLibraryMultiMeshItemEditorPlugin;
class VoxelInstanceLibraryMultiMeshItemInspectorPlugin : public EditorInspectorPlugin {
GDCLASS(VoxelInstanceLibraryMultiMeshItemInspectorPlugin, EditorInspectorPlugin)
public:
VoxelInstanceLibraryMultiMeshItemEditorPlugin *listener = nullptr;
bool can_handle(Object *p_object) override;
void parse_group(Object *p_object, const String &p_group) override;
bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint,

View File

@ -55,6 +55,7 @@
#include "editor/fast_noise_lite/fast_noise_lite_editor_plugin.h"
#include "editor/graph/voxel_graph_editor_plugin.h"
#include "editor/instance_library/voxel_instance_library_editor_plugin.h"
#include "editor/instance_library/voxel_instance_library_multimesh_item_editor_plugin.h"
#include "editor/instancer/voxel_instancer_editor_plugin.h"
#include "editor/mesh_sdf/voxel_mesh_sdf_editor_plugin.h"
#include "editor/terrain/voxel_terrain_editor_plugin.h"
@ -258,6 +259,7 @@ void initialize_voxel_module(ModuleInitializationLevel p_level) {
EditorPlugins::add_by_type<VoxelGraphEditorPlugin>();
EditorPlugins::add_by_type<VoxelTerrainEditorPlugin>();
EditorPlugins::add_by_type<VoxelInstanceLibraryEditorPlugin>();
EditorPlugins::add_by_type<VoxelInstanceLibraryMultiMeshItemEditorPlugin>();
EditorPlugins::add_by_type<ZN_FastNoiseLiteEditorPlugin>();
EditorPlugins::add_by_type<magica::VoxEditorPlugin>();
EditorPlugins::add_by_type<VoxelInstancerEditorPlugin>();