Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement individual mesh transform for meshlibrary items #52298

Merged
merged 1 commit into from
Sep 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions doc/classes/MeshLibrary.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@
Returns the item's mesh.
</description>
</method>
<method name="get_item_mesh_transform" qualifiers="const">
<return type="Transform3D" />
<argument index="0" name="id" type="int" />
<description>
Returns the transform applied to the item's mesh.
</description>
</method>
<method name="get_item_name" qualifiers="const">
<return type="String" />
<argument index="0" name="id" type="int" />
Expand Down Expand Up @@ -102,6 +109,14 @@
Sets the item's mesh.
</description>
</method>
<method name="set_item_mesh_transform">
<return type="void" />
<argument index="0" name="id" type="int" />
<argument index="1" name="mesh_transform" type="Transform3D" />
<description>
Sets the transform to apply to the item's mesh.
</description>
</method>
<method name="set_item_name">
<return type="void" />
<argument index="0" name="id" type="int" />
Expand Down
6 changes: 5 additions & 1 deletion editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1856,7 +1856,7 @@ void EditorNode::_dialog_action(String p_file) {
ml = Ref<MeshLibrary>(memnew(MeshLibrary));
}

MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true);
MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true, file_export_lib_apply_xforms->is_pressed());

Error err = ResourceSaver::save(p_file, ml);
if (err) {
Expand Down Expand Up @@ -6811,6 +6811,10 @@ EditorNode::EditorNode() {
file_export_lib_merge->set_text(TTR("Merge With Existing"));
file_export_lib_merge->set_pressed(true);
file_export_lib->get_vbox()->add_child(file_export_lib_merge);
file_export_lib_apply_xforms = memnew(CheckBox);
file_export_lib_apply_xforms->set_text(TTR("Apply MeshInstance Transforms"));
file_export_lib_apply_xforms->set_pressed(false);
file_export_lib->get_vbox()->add_child(file_export_lib_apply_xforms);
gui_base->add_child(file_export_lib);

file_script = memnew(EditorFileDialog);
Expand Down
1 change: 1 addition & 0 deletions editor/editor_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ class EditorNode : public Node {
EditorFileDialog *file_script;
EditorFileDialog *file_android_build_source;
CheckBox *file_export_lib_merge;
CheckBox *file_export_lib_apply_xforms;
String current_path;
MenuButton *update_spinner;

Expand Down
59 changes: 40 additions & 19 deletions editor/plugins/mesh_library_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,25 @@ void MeshLibraryEditor::edit(const Ref<MeshLibrary> &p_mesh_library) {
}
}

void MeshLibraryEditor::_menu_confirm() {
void MeshLibraryEditor::_menu_remove_confirm() {
switch (option) {
case MENU_OPTION_REMOVE_ITEM: {
mesh_library->remove_item(to_erase);
} break;
case MENU_OPTION_UPDATE_FROM_SCENE: {
String existing = mesh_library->get_meta("_editor_source_scene");
ERR_FAIL_COND(existing == "");
_import_scene_cbk(existing);

} break;
default: {
};
}
}

void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge) {
void MeshLibraryEditor::_menu_update_confirm(bool p_apply_xforms) {
cd_update->hide();
apply_xforms = p_apply_xforms;
String existing = mesh_library->get_meta("_editor_source_scene");
ERR_FAIL_COND(existing == "");
_import_scene_cbk(existing);
}

void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge, bool p_apply_xforms) {
if (!p_merge) {
p_library->clear();
}
Expand Down Expand Up @@ -108,6 +110,13 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
}

p_library->set_item_mesh(id, mesh);

if (p_apply_xforms) {
p_library->set_item_mesh_transform(id, mi->get_transform());
} else {
p_library->set_item_mesh_transform(id, Transform3D());
}

mesh_instances[id] = mi;

Vector<MeshLibrary::ShapeData> collisions;
Expand Down Expand Up @@ -197,15 +206,16 @@ void MeshLibraryEditor::_import_scene_cbk(const String &p_str) {

ERR_FAIL_COND_MSG(!scene, "Cannot create an instance from PackedScene '" + p_str + "'.");

_import_scene(scene, mesh_library, option == MENU_OPTION_UPDATE_FROM_SCENE);
_import_scene(scene, mesh_library, option == MENU_OPTION_UPDATE_FROM_SCENE, apply_xforms);

memdelete(scene);
mesh_library->set_meta("_editor_source_scene", p_str);

menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE), false);
}

Error MeshLibraryEditor::update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml, bool p_merge) {
_import_scene(p_base_scene, ml, p_merge);
Error MeshLibraryEditor::update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml, bool p_merge, bool p_apply_xforms) {
_import_scene(p_base_scene, ml, p_merge, p_apply_xforms);
return OK;
}

Expand All @@ -219,16 +229,21 @@ void MeshLibraryEditor::_menu_cbk(int p_option) {
String p = editor->get_inspector()->get_selected_path();
if (p.begins_with("/MeshLibrary/item") && p.get_slice_count("/") >= 3) {
to_erase = p.get_slice("/", 3).to_int();
cd->set_text(vformat(TTR("Remove item %d?"), to_erase));
cd->popup_centered(Size2(300, 60));
cd_remove->set_text(vformat(TTR("Remove item %d?"), to_erase));
cd_remove->popup_centered(Size2(300, 60));
}
} break;
case MENU_OPTION_IMPORT_FROM_SCENE: {
apply_xforms = false;
file->popup_file_dialog();
} break;
case MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS: {
apply_xforms = true;
file->popup_file_dialog();
} break;
case MENU_OPTION_UPDATE_FROM_SCENE: {
cd->set_text(vformat(TTR("Update from existing scene?:\n%s"), String(mesh_library->get_meta("_editor_source_scene"))));
cd->popup_centered(Size2(500, 60));
cd_update->set_text(vformat(TTR("Update from existing scene?:\n%s"), String(mesh_library->get_meta("_editor_source_scene"))));
cd_update->popup_centered(Size2(500, 60));
} break;
}
}
Expand Down Expand Up @@ -258,16 +273,22 @@ MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) {
menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM);
menu->get_popup()->add_item(TTR("Remove Selected Item"), MENU_OPTION_REMOVE_ITEM);
menu->get_popup()->add_separator();
menu->get_popup()->add_item(TTR("Import from Scene"), MENU_OPTION_IMPORT_FROM_SCENE);
menu->get_popup()->add_item(TTR("Import from Scene (Ignore Transforms)"), MENU_OPTION_IMPORT_FROM_SCENE);
menu->get_popup()->add_item(TTR("Import from Scene (Apply Transforms)"), MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS);
menu->get_popup()->add_item(TTR("Update from Scene"), MENU_OPTION_UPDATE_FROM_SCENE);
menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE), true);
menu->get_popup()->connect("id_pressed", callable_mp(this, &MeshLibraryEditor::_menu_cbk));
menu->hide();

editor = p_editor;
cd = memnew(ConfirmationDialog);
add_child(cd);
cd->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_confirm));
cd_remove = memnew(ConfirmationDialog);
add_child(cd_remove);
cd_remove->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_remove_confirm));
cd_update = memnew(ConfirmationDialog);
add_child(cd_update);
cd_update->get_ok_button()->set_text("Apply without Transforms");
cd_update->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(false));
cd_update->add_button("Apply with Transforms")->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(true));
}

void MeshLibraryEditorPlugin::edit(Object *p_node) {
Expand Down
14 changes: 9 additions & 5 deletions editor/plugins/mesh_library_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,27 @@ class MeshLibraryEditor : public Control {

EditorNode *editor;
MenuButton *menu;
ConfirmationDialog *cd;
ConfirmationDialog *cd_remove;
ConfirmationDialog *cd_update;
EditorFileDialog *file;
bool apply_xforms;
int to_erase;

enum {
MENU_OPTION_ADD_ITEM,
MENU_OPTION_REMOVE_ITEM,
MENU_OPTION_UPDATE_FROM_SCENE,
MENU_OPTION_IMPORT_FROM_SCENE
MENU_OPTION_IMPORT_FROM_SCENE,
MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS
};

int option;
void _import_scene_cbk(const String &p_str);
void _menu_cbk(int p_option);
void _menu_confirm();
void _menu_remove_confirm();
void _menu_update_confirm(bool p_apply_xforms);

static void _import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge);
static void _import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge, bool p_apply_xforms);

protected:
static void _bind_methods();
Expand All @@ -66,7 +70,7 @@ class MeshLibraryEditor : public Control {
MenuButton *get_menu_button() const { return menu; }

void edit(const Ref<MeshLibrary> &p_mesh_library);
static Error update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml, bool p_merge = true);
static Error update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml, bool p_merge = true, bool p_apply_xforms = false);

MeshLibraryEditor(EditorNode *p_editor);
};
Expand Down
2 changes: 1 addition & 1 deletion modules/gridmap/grid_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
}

Pair<Transform3D, IndexKey> p;
p.first = xform;
p.first = xform * mesh_library->get_item_mesh_transform(c.item);
p.second = E->get();
multimesh_items[c.item].push_back(p);
}
Expand Down
6 changes: 6 additions & 0 deletions modules/gridmap/grid_map_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ void GridMapEditor::_update_cursor_transform() {
cursor_transform.basis *= node->get_cell_scale();
cursor_transform = node->get_global_transform() * cursor_transform;

if (selected_palette >= 0) {
if (node && !node->get_mesh_library().is_null()) {
cursor_transform *= node->get_mesh_library()->get_item_mesh_transform(selected_palette);
}
}

if (cursor_instance.is_valid()) {
RenderingServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform);
RenderingServer::get_singleton()->instance_set_visible(cursor_instance, cursor_visible);
Expand Down
19 changes: 19 additions & 0 deletions scene/resources/mesh_library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) {
set_item_name(idx, p_value);
} else if (what == "mesh") {
set_item_mesh(idx, p_value);
} else if (what == "mesh_transform") {
set_item_mesh_transform(idx, p_value);
} else if (what == "shape") {
Vector<ShapeData> shapes;
ShapeData sd;
Expand Down Expand Up @@ -77,6 +79,8 @@ bool MeshLibrary::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = get_item_name(idx);
} else if (what == "mesh") {
r_ret = get_item_mesh(idx);
} else if (what == "mesh_transform") {
r_ret = get_item_mesh_transform(idx);
} else if (what == "shapes") {
r_ret = _get_item_shapes(idx);
} else if (what == "navmesh") {
Expand Down Expand Up @@ -127,6 +131,14 @@ void MeshLibrary::set_item_mesh(int p_item, const Ref<Mesh> &p_mesh) {
notify_property_list_changed();
}

void MeshLibrary::set_item_mesh_transform(int p_item, const Transform3D &p_transform) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
item_map[p_item].mesh_transform = p_transform;
notify_change_to_owners();
emit_changed();
notify_property_list_changed();
}

void MeshLibrary::set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
item_map[p_item].shapes = p_shapes;
Expand Down Expand Up @@ -170,6 +182,11 @@ Ref<Mesh> MeshLibrary::get_item_mesh(int p_item) const {
return item_map[p_item].mesh;
}

Transform3D MeshLibrary::get_item_mesh_transform(int p_item) const {
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Transform3D(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
return item_map[p_item].mesh_transform;
}

Vector<MeshLibrary::ShapeData> MeshLibrary::get_item_shapes(int p_item) const {
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Vector<ShapeData>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
return item_map[p_item].shapes;
Expand Down Expand Up @@ -271,12 +288,14 @@ void MeshLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_item", "id"), &MeshLibrary::create_item);
ClassDB::bind_method(D_METHOD("set_item_name", "id", "name"), &MeshLibrary::set_item_name);
ClassDB::bind_method(D_METHOD("set_item_mesh", "id", "mesh"), &MeshLibrary::set_item_mesh);
ClassDB::bind_method(D_METHOD("set_item_mesh_transform", "id", "mesh_transform"), &MeshLibrary::set_item_mesh_transform);
ClassDB::bind_method(D_METHOD("set_item_navmesh", "id", "navmesh"), &MeshLibrary::set_item_navmesh);
ClassDB::bind_method(D_METHOD("set_item_navmesh_transform", "id", "navmesh"), &MeshLibrary::set_item_navmesh_transform);
ClassDB::bind_method(D_METHOD("set_item_shapes", "id", "shapes"), &MeshLibrary::_set_item_shapes);
ClassDB::bind_method(D_METHOD("set_item_preview", "id", "texture"), &MeshLibrary::set_item_preview);
ClassDB::bind_method(D_METHOD("get_item_name", "id"), &MeshLibrary::get_item_name);
ClassDB::bind_method(D_METHOD("get_item_mesh", "id"), &MeshLibrary::get_item_mesh);
ClassDB::bind_method(D_METHOD("get_item_mesh_transform", "id"), &MeshLibrary::get_item_mesh_transform);
ClassDB::bind_method(D_METHOD("get_item_navmesh", "id"), &MeshLibrary::get_item_navmesh);
ClassDB::bind_method(D_METHOD("get_item_navmesh_transform", "id"), &MeshLibrary::get_item_navmesh_transform);
ClassDB::bind_method(D_METHOD("get_item_shapes", "id"), &MeshLibrary::_get_item_shapes);
Expand Down
3 changes: 3 additions & 0 deletions scene/resources/mesh_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class MeshLibrary : public Resource {
Vector<ShapeData> shapes;
Ref<Texture2D> preview;
Transform3D navmesh_transform;
Transform3D mesh_transform;
Ref<NavigationMesh> navmesh;
};

Expand All @@ -72,12 +73,14 @@ class MeshLibrary : public Resource {
void create_item(int p_item);
void set_item_name(int p_item, const String &p_name);
void set_item_mesh(int p_item, const Ref<Mesh> &p_mesh);
void set_item_mesh_transform(int p_item, const Transform3D &p_transform);
void set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh);
void set_item_navmesh_transform(int p_item, const Transform3D &p_transform);
void set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes);
void set_item_preview(int p_item, const Ref<Texture2D> &p_preview);
String get_item_name(int p_item) const;
Ref<Mesh> get_item_mesh(int p_item) const;
Transform3D get_item_mesh_transform(int p_item) const;
Ref<NavigationMesh> get_item_navmesh(int p_item) const;
Transform3D get_item_navmesh_transform(int p_item) const;
Vector<ShapeData> get_item_shapes(int p_item) const;
Expand Down