Merge pull request #52298 from DeleteSystem32/meshlib-transform
implement individual mesh transform for meshlibrary items
This commit is contained in:
commit
dde48ebed6
9 changed files with 99 additions and 26 deletions
|
@ -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" />
|
||||
|
@ -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" />
|
||||
|
|
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
|
|
@ -335,6 +335,7 @@ private:
|
|||
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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
@ -66,7 +70,7 @@ public:
|
|||
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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -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") {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
Vector<ShapeData> shapes;
|
||||
Ref<Texture2D> preview;
|
||||
Transform3D navmesh_transform;
|
||||
Transform3D mesh_transform;
|
||||
Ref<NavigationMesh> navmesh;
|
||||
};
|
||||
|
||||
|
@ -72,12 +73,14 @@ public:
|
|||
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;
|
||||
|
|
Loading…
Reference in a new issue