mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-11-22 00:48:09 +01:00
Also removed the MeshLibrary.
This commit is contained in:
parent
5767e12b56
commit
aaf91df4c1
@ -128,7 +128,6 @@
|
|||||||
#include "editor/plugins/material_editor_plugin.h"
|
#include "editor/plugins/material_editor_plugin.h"
|
||||||
#include "editor/plugins/mesh_editor_plugin.h"
|
#include "editor/plugins/mesh_editor_plugin.h"
|
||||||
#include "editor/plugins/mesh_instance_editor_plugin.h"
|
#include "editor/plugins/mesh_instance_editor_plugin.h"
|
||||||
#include "editor/plugins/mesh_library_editor_plugin.h"
|
|
||||||
#include "editor/plugins/multimesh_editor_plugin.h"
|
#include "editor/plugins/multimesh_editor_plugin.h"
|
||||||
#include "editor/plugins/navigation_polygon_editor_plugin.h"
|
#include "editor/plugins/navigation_polygon_editor_plugin.h"
|
||||||
#include "editor/plugins/path_2d_editor_plugin.h"
|
#include "editor/plugins/path_2d_editor_plugin.h"
|
||||||
@ -1720,30 +1719,6 @@ void EditorNode::_dialog_action(String p_file) {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FILE_EXPORT_MESH_LIBRARY: {
|
|
||||||
Ref<MeshLibrary> ml;
|
|
||||||
if (file_export_lib_merge->is_pressed() && FileAccess::exists(p_file)) {
|
|
||||||
ml = ResourceLoader::load(p_file, "MeshLibrary");
|
|
||||||
|
|
||||||
if (ml.is_null()) {
|
|
||||||
show_accept(TTR("Can't load MeshLibrary for merging!"), TTR("OK"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ml.is_null()) {
|
|
||||||
ml = Ref<MeshLibrary>(memnew(MeshLibrary));
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
show_accept(TTR("Error saving MeshLibrary!"), TTR("OK"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case FILE_EXPORT_TILESET: {
|
case FILE_EXPORT_TILESET: {
|
||||||
Ref<TileSet> tileset;
|
Ref<TileSet> tileset;
|
||||||
if (FileAccess::exists(p_file) && file_export_lib_merge->is_pressed()) {
|
if (FileAccess::exists(p_file) && file_export_lib_merge->is_pressed()) {
|
||||||
@ -2427,24 +2402,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
|
|||||||
project_export->popup_export();
|
project_export->popup_export();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FILE_EXPORT_MESH_LIBRARY: {
|
|
||||||
if (!editor_data.get_edited_scene_root()) {
|
|
||||||
show_accept(TTR("This operation can't be done without a scene."), TTR("OK"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> extensions;
|
|
||||||
Ref<MeshLibrary> ml(memnew(MeshLibrary));
|
|
||||||
ResourceSaver::get_recognized_extensions(ml, &extensions);
|
|
||||||
file_export_lib->clear_filters();
|
|
||||||
for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
|
|
||||||
file_export_lib->add_filter("*." + E->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
file_export_lib->popup_centered_ratio();
|
|
||||||
file_export_lib->set_title(TTR("Export Mesh Library"));
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case FILE_EXPORT_TILESET: {
|
case FILE_EXPORT_TILESET: {
|
||||||
//Make sure that the scene has a root before trying to convert to tileset
|
//Make sure that the scene has a root before trying to convert to tileset
|
||||||
if (!editor_data.get_edited_scene_root()) {
|
if (!editor_data.get_edited_scene_root()) {
|
||||||
@ -5878,7 +5835,7 @@ EditorNode::EditorNode() {
|
|||||||
EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false);
|
EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false);
|
||||||
EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true);
|
EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true);
|
||||||
EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true);
|
EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true);
|
||||||
EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,MeshLibrary,TileSet");
|
EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,TileSet");
|
||||||
EDITOR_DEF("interface/inspector/default_color_picker_mode", 0);
|
EDITOR_DEF("interface/inspector/default_color_picker_mode", 0);
|
||||||
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW", PROPERTY_USAGE_DEFAULT));
|
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW", PROPERTY_USAGE_DEFAULT));
|
||||||
EDITOR_DEF("run/auto_save/save_before_running", true);
|
EDITOR_DEF("run/auto_save/save_before_running", true);
|
||||||
@ -6210,7 +6167,6 @@ EditorNode::EditorNode() {
|
|||||||
pm_export->set_name("Export");
|
pm_export->set_name("Export");
|
||||||
p->add_child(pm_export);
|
p->add_child(pm_export);
|
||||||
p->add_submenu_item(TTR("Convert To..."), "Export");
|
p->add_submenu_item(TTR("Convert To..."), "Export");
|
||||||
pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_MeshLibrary", TTR("MeshLibrary...")), FILE_EXPORT_MESH_LIBRARY);
|
|
||||||
pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_TileSet", TTR("TileSet...")), FILE_EXPORT_TILESET);
|
pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_TileSet", TTR("TileSet...")), FILE_EXPORT_TILESET);
|
||||||
pm_export->connect("id_pressed", this, "_menu_option");
|
pm_export->connect("id_pressed", this, "_menu_option");
|
||||||
|
|
||||||
@ -6811,7 +6767,6 @@ EditorNode::EditorNode() {
|
|||||||
add_editor_plugin(memnew(MeshInstanceEditorPlugin(this)));
|
add_editor_plugin(memnew(MeshInstanceEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(AnimationTreeEditorPlugin(this)));
|
add_editor_plugin(memnew(AnimationTreeEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(AnimationTreePlayerEditorPlugin(this)));
|
add_editor_plugin(memnew(AnimationTreePlayerEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(MeshLibraryEditorPlugin(this)));
|
|
||||||
add_editor_plugin(memnew(StyleBoxEditorPlugin(this)));
|
add_editor_plugin(memnew(StyleBoxEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(SpriteEditorPlugin(this)));
|
add_editor_plugin(memnew(SpriteEditorPlugin(this)));
|
||||||
add_editor_plugin(memnew(Skeleton2DEditorPlugin(this)));
|
add_editor_plugin(memnew(Skeleton2DEditorPlugin(this)));
|
||||||
|
@ -128,7 +128,6 @@ private:
|
|||||||
FILE_SHOW_IN_FILESYSTEM,
|
FILE_SHOW_IN_FILESYSTEM,
|
||||||
FILE_IMPORT_SUBSCENE,
|
FILE_IMPORT_SUBSCENE,
|
||||||
FILE_EXPORT_PROJECT,
|
FILE_EXPORT_PROJECT,
|
||||||
FILE_EXPORT_MESH_LIBRARY,
|
|
||||||
FILE_INSTALL_ANDROID_SOURCE,
|
FILE_INSTALL_ANDROID_SOURCE,
|
||||||
FILE_EXPLORE_ANDROID_BUILD_TEMPLATES,
|
FILE_EXPLORE_ANDROID_BUILD_TEMPLATES,
|
||||||
FILE_EXPORT_TILESET,
|
FILE_EXPORT_TILESET,
|
||||||
|
@ -1,331 +0,0 @@
|
|||||||
/*************************************************************************/
|
|
||||||
/* mesh_library_editor_plugin.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#include "mesh_library_editor_plugin.h"
|
|
||||||
|
|
||||||
#include "editor/editor_node.h"
|
|
||||||
#include "editor/editor_settings.h"
|
|
||||||
#include "main/main.h"
|
|
||||||
#include "scene/3d/mesh_instance.h"
|
|
||||||
#include "scene/3d/navigation_mesh_instance.h"
|
|
||||||
#include "scene/3d/physics_body.h"
|
|
||||||
#include "scene/main/viewport.h"
|
|
||||||
#include "scene/resources/packed_scene.h"
|
|
||||||
#include "spatial_editor_plugin.h"
|
|
||||||
|
|
||||||
void MeshLibraryEditor::edit(const Ref<MeshLibrary> &p_mesh_library) {
|
|
||||||
mesh_library = p_mesh_library;
|
|
||||||
if (mesh_library.is_valid()) {
|
|
||||||
menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE), !mesh_library->has_meta("_editor_source_scene"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibraryEditor::_menu_remove_confirm() {
|
|
||||||
switch (option) {
|
|
||||||
case MENU_OPTION_REMOVE_ITEM: {
|
|
||||||
mesh_library->remove_item(to_erase);
|
|
||||||
} break;
|
|
||||||
default: {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<int, MeshInstance *> mesh_instances;
|
|
||||||
|
|
||||||
for (int i = 0; i < p_scene->get_child_count(); i++) {
|
|
||||||
Node *child = p_scene->get_child(i);
|
|
||||||
|
|
||||||
if (!Object::cast_to<MeshInstance>(child)) {
|
|
||||||
if (child->get_child_count() > 0) {
|
|
||||||
child = child->get_child(0);
|
|
||||||
if (!Object::cast_to<MeshInstance>(child)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MeshInstance *mi = Object::cast_to<MeshInstance>(child);
|
|
||||||
Ref<Mesh> mesh = mi->get_mesh();
|
|
||||||
if (mesh.is_null()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh = mesh->duplicate();
|
|
||||||
for (int j = 0; j < mesh->get_surface_count(); ++j) {
|
|
||||||
Ref<Material> mat = mi->get_surface_material(j);
|
|
||||||
|
|
||||||
if (mat.is_valid()) {
|
|
||||||
mesh->surface_set_material(j, mat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int id = p_library->find_item_by_name(mi->get_name());
|
|
||||||
if (id < 0) {
|
|
||||||
id = p_library->get_last_unused_item_id();
|
|
||||||
p_library->create_item(id);
|
|
||||||
p_library->set_item_name(id, mi->get_name());
|
|
||||||
}
|
|
||||||
|
|
||||||
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, Transform());
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh_instances[id] = mi;
|
|
||||||
|
|
||||||
Vector<MeshLibrary::ShapeData> collisions;
|
|
||||||
|
|
||||||
for (int j = 0; j < mi->get_child_count(); j++) {
|
|
||||||
Node *child2 = mi->get_child(j);
|
|
||||||
if (!Object::cast_to<StaticBody>(child2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
StaticBody *sb = Object::cast_to<StaticBody>(child2);
|
|
||||||
List<uint32_t> shapes;
|
|
||||||
sb->get_shape_owners(&shapes);
|
|
||||||
|
|
||||||
for (List<uint32_t>::Element *E = shapes.front(); E; E = E->next()) {
|
|
||||||
if (sb->is_shape_owner_disabled(E->get())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform shape_transform;
|
|
||||||
if (p_apply_xforms) {
|
|
||||||
shape_transform = mi->get_transform();
|
|
||||||
}
|
|
||||||
shape_transform *= sb->get_transform() * sb->shape_owner_get_transform(E->get());
|
|
||||||
|
|
||||||
for (int k = 0; k < sb->shape_owner_get_shape_count(E->get()); k++) {
|
|
||||||
Ref<Shape> collision = sb->shape_owner_get_shape(E->get(), k);
|
|
||||||
if (!collision.is_valid()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MeshLibrary::ShapeData shape_data;
|
|
||||||
shape_data.shape = collision;
|
|
||||||
shape_data.local_transform = shape_transform;
|
|
||||||
collisions.push_back(shape_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p_library->set_item_shapes(id, collisions);
|
|
||||||
|
|
||||||
Ref<NavigationMesh> navmesh;
|
|
||||||
Transform navmesh_transform;
|
|
||||||
for (int j = 0; j < mi->get_child_count(); j++) {
|
|
||||||
Node *child2 = mi->get_child(j);
|
|
||||||
if (!Object::cast_to<NavigationMeshInstance>(child2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
NavigationMeshInstance *sb = Object::cast_to<NavigationMeshInstance>(child2);
|
|
||||||
navmesh = sb->get_navigation_mesh();
|
|
||||||
navmesh_transform = sb->get_transform();
|
|
||||||
if (!navmesh.is_null()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!navmesh.is_null()) {
|
|
||||||
p_library->set_item_navmesh(id, navmesh);
|
|
||||||
p_library->set_item_navmesh_transform(id, navmesh_transform);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//generate previews!
|
|
||||||
|
|
||||||
if (true) {
|
|
||||||
Vector<Ref<Mesh>> meshes;
|
|
||||||
Vector<Transform> transforms;
|
|
||||||
Vector<int> ids = p_library->get_item_list();
|
|
||||||
for (int i = 0; i < ids.size(); i++) {
|
|
||||||
if (mesh_instances.find(ids[i])) {
|
|
||||||
meshes.push_back(p_library->get_item_mesh(ids[i]));
|
|
||||||
transforms.push_back(mesh_instances[ids[i]]->get_transform());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<Ref<Texture>> textures = EditorInterface::get_singleton()->make_mesh_previews(meshes, &transforms, EditorSettings::get_singleton()->get("editors/grid_map/preview_size"));
|
|
||||||
int j = 0;
|
|
||||||
for (int i = 0; i < ids.size(); i++) {
|
|
||||||
if (mesh_instances.find(ids[i])) {
|
|
||||||
p_library->set_item_preview(ids[i], textures[j]);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibraryEditor::_import_scene_cbk(const String &p_str) {
|
|
||||||
Ref<PackedScene> ps = ResourceLoader::load(p_str, "PackedScene");
|
|
||||||
ERR_FAIL_COND(ps.is_null());
|
|
||||||
Node *scene = ps->instance();
|
|
||||||
|
|
||||||
ERR_FAIL_COND_MSG(!scene, "Cannot create an instance from PackedScene '" + p_str + "'.");
|
|
||||||
|
|
||||||
_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, bool p_apply_xforms) {
|
|
||||||
_import_scene(p_base_scene, ml, p_merge, p_apply_xforms);
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibraryEditor::_menu_cbk(int p_option) {
|
|
||||||
option = p_option;
|
|
||||||
switch (p_option) {
|
|
||||||
case MENU_OPTION_ADD_ITEM: {
|
|
||||||
mesh_library->create_item(mesh_library->get_last_unused_item_id());
|
|
||||||
} break;
|
|
||||||
case MENU_OPTION_REMOVE_ITEM: {
|
|
||||||
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_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_centered_ratio();
|
|
||||||
} break;
|
|
||||||
case MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS: {
|
|
||||||
apply_xforms = true;
|
|
||||||
file->popup_centered_ratio();
|
|
||||||
} break;
|
|
||||||
case MENU_OPTION_UPDATE_FROM_SCENE: {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibraryEditor::_bind_methods() {
|
|
||||||
ClassDB::bind_method("_menu_cbk", &MeshLibraryEditor::_menu_cbk);
|
|
||||||
ClassDB::bind_method("_menu_remove_confirm", &MeshLibraryEditor::_menu_remove_confirm);
|
|
||||||
ClassDB::bind_method("_menu_update_confirm", &MeshLibraryEditor::_menu_update_confirm);
|
|
||||||
ClassDB::bind_method("_import_scene_cbk", &MeshLibraryEditor::_import_scene_cbk);
|
|
||||||
}
|
|
||||||
|
|
||||||
MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) {
|
|
||||||
file = memnew(EditorFileDialog);
|
|
||||||
file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
|
|
||||||
//not for now?
|
|
||||||
List<String> extensions;
|
|
||||||
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions);
|
|
||||||
file->clear_filters();
|
|
||||||
file->set_title(TTR("Import Scene"));
|
|
||||||
for (int i = 0; i < extensions.size(); i++) {
|
|
||||||
file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
|
|
||||||
}
|
|
||||||
add_child(file);
|
|
||||||
file->connect("file_selected", this, "_import_scene_cbk");
|
|
||||||
|
|
||||||
menu = memnew(MenuButton);
|
|
||||||
SpatialEditor::get_singleton()->add_control_to_menu_panel(menu);
|
|
||||||
menu->set_position(Point2(1, 1));
|
|
||||||
menu->set_text(TTR("Mesh Library"));
|
|
||||||
menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MeshLibrary", "EditorIcons"));
|
|
||||||
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 (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", this, "_menu_cbk");
|
|
||||||
menu->hide();
|
|
||||||
|
|
||||||
editor = p_editor;
|
|
||||||
cd_remove = memnew(ConfirmationDialog);
|
|
||||||
add_child(cd_remove);
|
|
||||||
cd_remove->get_ok()->connect("pressed", this, "_menu_remove_confirm");
|
|
||||||
cd_update = memnew(ConfirmationDialog);
|
|
||||||
add_child(cd_update);
|
|
||||||
cd_update->get_ok()->set_text(TTR("Apply without Transforms"));
|
|
||||||
cd_update->get_ok()->connect("pressed", this, "_menu_update_confirm", varray(false));
|
|
||||||
cd_update->add_button(TTR("Apply with Transforms"))->connect("pressed", this, "_menu_update_confirm", varray(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibraryEditorPlugin::edit(Object *p_node) {
|
|
||||||
if (Object::cast_to<MeshLibrary>(p_node)) {
|
|
||||||
mesh_library_editor->edit(Object::cast_to<MeshLibrary>(p_node));
|
|
||||||
mesh_library_editor->show();
|
|
||||||
} else {
|
|
||||||
mesh_library_editor->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MeshLibraryEditorPlugin::handles(Object *p_node) const {
|
|
||||||
return p_node->is_class("MeshLibrary");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibraryEditorPlugin::make_visible(bool p_visible) {
|
|
||||||
if (p_visible) {
|
|
||||||
mesh_library_editor->show();
|
|
||||||
mesh_library_editor->get_menu_button()->show();
|
|
||||||
} else {
|
|
||||||
mesh_library_editor->hide();
|
|
||||||
mesh_library_editor->get_menu_button()->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MeshLibraryEditorPlugin::MeshLibraryEditorPlugin(EditorNode *p_node) {
|
|
||||||
EDITOR_DEF("editors/grid_map/preview_size", 64);
|
|
||||||
mesh_library_editor = memnew(MeshLibraryEditor(p_node));
|
|
||||||
|
|
||||||
p_node->get_viewport()->add_child(mesh_library_editor);
|
|
||||||
mesh_library_editor->set_anchors_and_margins_preset(Control::PRESET_TOP_WIDE);
|
|
||||||
mesh_library_editor->set_end(Point2(0, 22));
|
|
||||||
mesh_library_editor->hide();
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
/*************************************************************************/
|
|
||||||
/* mesh_library_editor_plugin.h */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifndef MESH_LIBRARY_EDITOR_PLUGIN_H
|
|
||||||
#define MESH_LIBRARY_EDITOR_PLUGIN_H
|
|
||||||
|
|
||||||
#include "editor/editor_node.h"
|
|
||||||
#include "scene/resources/mesh_library.h"
|
|
||||||
|
|
||||||
class MeshLibraryEditor : public Control {
|
|
||||||
GDCLASS(MeshLibraryEditor, Control);
|
|
||||||
|
|
||||||
Ref<MeshLibrary> mesh_library;
|
|
||||||
|
|
||||||
EditorNode *editor;
|
|
||||||
MenuButton *menu;
|
|
||||||
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_APPLY_XFORMS
|
|
||||||
};
|
|
||||||
|
|
||||||
int option;
|
|
||||||
void _import_scene_cbk(const String &p_str);
|
|
||||||
void _menu_cbk(int p_option);
|
|
||||||
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, bool p_apply_xforms);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
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, bool p_apply_xforms = false);
|
|
||||||
|
|
||||||
MeshLibraryEditor(EditorNode *p_editor);
|
|
||||||
};
|
|
||||||
|
|
||||||
class MeshLibraryEditorPlugin : public EditorPlugin {
|
|
||||||
GDCLASS(MeshLibraryEditorPlugin, EditorPlugin);
|
|
||||||
|
|
||||||
MeshLibraryEditor *mesh_library_editor;
|
|
||||||
EditorNode *editor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual String get_name() const { return "MeshLibrary"; }
|
|
||||||
bool has_main_screen() const { return false; }
|
|
||||||
virtual void edit(Object *p_node);
|
|
||||||
virtual bool handles(Object *p_node) const;
|
|
||||||
virtual void make_visible(bool p_visible);
|
|
||||||
|
|
||||||
MeshLibraryEditorPlugin(EditorNode *p_node);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MESH_LIBRARY_EDITOR_PLUGIN_H
|
|
@ -61,12 +61,6 @@
|
|||||||
|
|
||||||
#include "modules/modules_enabled.gen.h" // For csg, gridmap, regex.
|
#include "modules/modules_enabled.gen.h" // For csg, gridmap, regex.
|
||||||
|
|
||||||
#ifdef MODULE_CSG_ENABLED
|
|
||||||
#include "modules/csg/csg_shape.h"
|
|
||||||
#endif // MODULE_CSG_ENABLED
|
|
||||||
#ifdef MODULE_GRIDMAP_ENABLED
|
|
||||||
#include "modules/gridmap/grid_map.h"
|
|
||||||
#endif // MODULE_GRIDMAP_ENABLED
|
|
||||||
#ifdef MODULE_REGEX_ENABLED
|
#ifdef MODULE_REGEX_ENABLED
|
||||||
#include "modules/regex/regex.h"
|
#include "modules/regex/regex.h"
|
||||||
#endif // MODULE_REGEX_ENABLED
|
#endif // MODULE_REGEX_ENABLED
|
||||||
@ -5315,18 +5309,6 @@ void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, co
|
|||||||
} else if (cast_to<MultiMeshInstance>(p_current)) {
|
} else if (cast_to<MultiMeshInstance>(p_current)) {
|
||||||
MultiMeshInstance *multi = cast_to<MultiMeshInstance>(p_current);
|
MultiMeshInstance *multi = cast_to<MultiMeshInstance>(p_current);
|
||||||
_convert_mult_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, state);
|
_convert_mult_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, state);
|
||||||
#ifdef MODULE_CSG_ENABLED
|
|
||||||
} else if (cast_to<CSGShape>(p_current)) {
|
|
||||||
CSGShape *shape = cast_to<CSGShape>(p_current);
|
|
||||||
if (shape->get_parent() && shape->is_root_shape()) {
|
|
||||||
_convert_csg_shape_to_gltf(shape, p_gltf_parent, gltf_node, state);
|
|
||||||
}
|
|
||||||
#endif // MODULE_CSG_ENABLED
|
|
||||||
#ifdef MODULE_GRIDMAP_ENABLED
|
|
||||||
} else if (cast_to<GridMap>(p_current)) {
|
|
||||||
GridMap *gridmap = Object::cast_to<GridMap>(p_current);
|
|
||||||
_convert_grid_map_to_gltf(gridmap, p_gltf_parent, p_gltf_root, gltf_node, state);
|
|
||||||
#endif // MODULE_GRIDMAP_ENABLED
|
|
||||||
} else if (cast_to<Camera>(p_current)) {
|
} else if (cast_to<Camera>(p_current)) {
|
||||||
Camera *camera = Object::cast_to<Camera>(p_current);
|
Camera *camera = Object::cast_to<Camera>(p_current);
|
||||||
_convert_camera_to_gltf(camera, state, gltf_node);
|
_convert_camera_to_gltf(camera, state, gltf_node);
|
||||||
@ -5351,35 +5333,6 @@ void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_CSG_ENABLED
|
|
||||||
void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) {
|
|
||||||
CSGShape *csg = p_current;
|
|
||||||
csg->call("_update_shape");
|
|
||||||
Array meshes = csg->get_meshes();
|
|
||||||
if (meshes.size() != 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Ref<Material> mat;
|
|
||||||
if (csg->get_material_override().is_valid()) {
|
|
||||||
mat = csg->get_material_override();
|
|
||||||
}
|
|
||||||
Ref<GLTFMesh> gltf_mesh;
|
|
||||||
gltf_mesh.instance();
|
|
||||||
Ref<ArrayMesh> import_mesh;
|
|
||||||
import_mesh.instance();
|
|
||||||
Ref<ArrayMesh> array_mesh = csg->get_meshes()[1];
|
|
||||||
for (int32_t surface_i = 0; surface_i < array_mesh->get_surface_count(); surface_i++) {
|
|
||||||
import_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array_mesh->surface_get_arrays(surface_i));
|
|
||||||
}
|
|
||||||
gltf_mesh->set_mesh(import_mesh);
|
|
||||||
GLTFMeshIndex mesh_i = state->meshes.size();
|
|
||||||
state->meshes.push_back(gltf_mesh);
|
|
||||||
gltf_node->mesh = mesh_i;
|
|
||||||
gltf_node->xform = csg->get_meshes()[0];
|
|
||||||
gltf_node->set_name(_gen_unique_name(state, csg->get_name()));
|
|
||||||
}
|
|
||||||
#endif // MODULE_CSG_ENABLED
|
|
||||||
|
|
||||||
void GLTFDocument::_create_gltf_node(Ref<GLTFState> state, Node *p_scene_parent, GLTFNodeIndex current_node_i,
|
void GLTFDocument::_create_gltf_node(Ref<GLTFState> state, Node *p_scene_parent, GLTFNodeIndex current_node_i,
|
||||||
GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref<GLTFNode> gltf_node) {
|
GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref<GLTFNode> gltf_node) {
|
||||||
state->scene_nodes.insert(current_node_i, p_scene_parent);
|
state->scene_nodes.insert(current_node_i, p_scene_parent);
|
||||||
@ -5427,36 +5380,6 @@ void GLTFDocument::_convert_light_to_gltf(Light *light, Ref<GLTFState> state, Re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_GRIDMAP_ENABLED
|
|
||||||
void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) {
|
|
||||||
Array cells = p_grid_map->get_used_cells();
|
|
||||||
for (int32_t k = 0; k < cells.size(); k++) {
|
|
||||||
GLTFNode *new_gltf_node = memnew(GLTFNode);
|
|
||||||
gltf_node->children.push_back(state->nodes.size());
|
|
||||||
state->nodes.push_back(new_gltf_node);
|
|
||||||
Vector3 cell_location = cells[k];
|
|
||||||
int32_t cell = p_grid_map->get_cell_item(
|
|
||||||
cell_location.x, cell_location.y, cell_location.z);
|
|
||||||
Transform cell_xform;
|
|
||||||
cell_xform.basis.set_orthogonal_index(
|
|
||||||
p_grid_map->get_cell_item_orientation(
|
|
||||||
cell_location.x, cell_location.y, cell_location.z));
|
|
||||||
cell_xform.basis.scale(Vector3(p_grid_map->get_cell_scale(),
|
|
||||||
p_grid_map->get_cell_scale(),
|
|
||||||
p_grid_map->get_cell_scale()));
|
|
||||||
cell_xform.set_origin(p_grid_map->map_to_world(
|
|
||||||
cell_location.x, cell_location.y, cell_location.z));
|
|
||||||
Ref<GLTFMesh> gltf_mesh;
|
|
||||||
gltf_mesh.instance();
|
|
||||||
gltf_mesh->set_mesh(_mesh_to_array_mesh(p_grid_map->get_mesh_library()->get_item_mesh(cell)));
|
|
||||||
new_gltf_node->mesh = state->meshes.size();
|
|
||||||
state->meshes.push_back(gltf_mesh);
|
|
||||||
new_gltf_node->xform = cell_xform * p_grid_map->get_transform();
|
|
||||||
new_gltf_node->set_name(_gen_unique_name(state, p_grid_map->get_mesh_library()->get_item_name(cell)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // MODULE_GRIDMAP_ENABLED
|
|
||||||
|
|
||||||
void GLTFDocument::_convert_mult_mesh_instance_to_gltf(MultiMeshInstance *p_multi_mesh_instance, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) {
|
void GLTFDocument::_convert_mult_mesh_instance_to_gltf(MultiMeshInstance *p_multi_mesh_instance, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) {
|
||||||
Ref<MultiMesh> multi_mesh = p_multi_mesh_instance->get_multimesh();
|
Ref<MultiMesh> multi_mesh = p_multi_mesh_instance->get_multimesh();
|
||||||
if (multi_mesh.is_valid()) {
|
if (multi_mesh.is_valid()) {
|
||||||
|
@ -52,13 +52,6 @@ class GLTFSpecGloss;
|
|||||||
class GLTFSkeleton;
|
class GLTFSkeleton;
|
||||||
class MultiMeshInstance;
|
class MultiMeshInstance;
|
||||||
|
|
||||||
#ifdef MODULE_CSG_ENABLED
|
|
||||||
class CSGShape;
|
|
||||||
#endif // MODULE_CSG_ENABLED
|
|
||||||
#ifdef MODULE_GRIDMAP_ENABLED
|
|
||||||
class GridMap;
|
|
||||||
#endif // MODULE_GRIDMAP_ENABLED
|
|
||||||
|
|
||||||
using GLTFAccessorIndex = int;
|
using GLTFAccessorIndex = int;
|
||||||
using GLTFAnimationIndex = int;
|
using GLTFAnimationIndex = int;
|
||||||
using GLTFBufferIndex = int;
|
using GLTFBufferIndex = int;
|
||||||
@ -391,10 +384,6 @@ public:
|
|||||||
const GLTFNodeIndex p_gltf_current,
|
const GLTFNodeIndex p_gltf_current,
|
||||||
const GLTFNodeIndex p_gltf_root);
|
const GLTFNodeIndex p_gltf_root);
|
||||||
|
|
||||||
#ifdef MODULE_CSG_ENABLED
|
|
||||||
void _convert_csg_shape_to_gltf(CSGShape *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> gltf_node, Ref<GLTFState> state);
|
|
||||||
#endif // MODULE_CSG_ENABLED
|
|
||||||
|
|
||||||
void _create_gltf_node(Ref<GLTFState> state,
|
void _create_gltf_node(Ref<GLTFState> state,
|
||||||
Node *p_scene_parent,
|
Node *p_scene_parent,
|
||||||
GLTFNodeIndex current_node_i,
|
GLTFNodeIndex current_node_i,
|
||||||
@ -409,13 +398,6 @@ public:
|
|||||||
void _check_visibility(Node *p_node, bool &retflag);
|
void _check_visibility(Node *p_node, bool &retflag);
|
||||||
void _convert_camera_to_gltf(Camera *camera, Ref<GLTFState> state,
|
void _convert_camera_to_gltf(Camera *camera, Ref<GLTFState> state,
|
||||||
Ref<GLTFNode> gltf_node);
|
Ref<GLTFNode> gltf_node);
|
||||||
#ifdef MODULE_GRIDMAP_ENABLED
|
|
||||||
void _convert_grid_map_to_gltf(
|
|
||||||
GridMap *p_grid_map,
|
|
||||||
GLTFNodeIndex p_parent_node_index,
|
|
||||||
GLTFNodeIndex p_root_node_index,
|
|
||||||
Ref<GLTFNode> gltf_node, Ref<GLTFState> state);
|
|
||||||
#endif // MODULE_GRIDMAP_ENABLED
|
|
||||||
void _convert_mult_mesh_instance_to_gltf(
|
void _convert_mult_mesh_instance_to_gltf(
|
||||||
MultiMeshInstance *p_scene_parent,
|
MultiMeshInstance *p_scene_parent,
|
||||||
GLTFNodeIndex p_parent_node_index,
|
GLTFNodeIndex p_parent_node_index,
|
||||||
|
@ -56,13 +56,6 @@
|
|||||||
#include "editor/editor_settings.h"
|
#include "editor/editor_settings.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE_CSG_ENABLED
|
|
||||||
#include "modules/csg/csg_shape.h"
|
|
||||||
#endif
|
|
||||||
#ifdef MODULE_GRIDMAP_ENABLED
|
|
||||||
#include "modules/gridmap/grid_map.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NavigationMeshGenerator *NavigationMeshGenerator::singleton = NULL;
|
NavigationMeshGenerator *NavigationMeshGenerator::singleton = NULL;
|
||||||
|
|
||||||
void NavigationMeshGenerator::_add_vertex(const Vector3 &p_vec3, Vector<float> &p_vertices) {
|
void NavigationMeshGenerator::_add_vertex(const Vector3 &p_vec3, Vector<float> &p_vertices) {
|
||||||
@ -165,19 +158,6 @@ void NavigationMeshGenerator::_parse_geometry(const Transform &p_navmesh_xform,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_CSG_ENABLED
|
|
||||||
if (Object::cast_to<CSGShape>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) {
|
|
||||||
CSGShape *csg_shape = Object::cast_to<CSGShape>(p_node);
|
|
||||||
Array meshes = csg_shape->get_meshes();
|
|
||||||
if (!meshes.empty()) {
|
|
||||||
Ref<Mesh> mesh = meshes[1];
|
|
||||||
if (mesh.is_valid()) {
|
|
||||||
_add_mesh(mesh, p_navmesh_xform * csg_shape->get_global_transform(), p_vertices, p_indices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (Object::cast_to<StaticBody>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES) {
|
if (Object::cast_to<StaticBody>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES) {
|
||||||
StaticBody *static_body = Object::cast_to<StaticBody>(p_node);
|
StaticBody *static_body = Object::cast_to<StaticBody>(p_node);
|
||||||
|
|
||||||
@ -265,106 +245,6 @@ void NavigationMeshGenerator::_parse_geometry(const Transform &p_navmesh_xform,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_GRIDMAP_ENABLED
|
|
||||||
GridMap *gridmap = Object::cast_to<GridMap>(p_node);
|
|
||||||
|
|
||||||
if (gridmap) {
|
|
||||||
if (p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) {
|
|
||||||
Array meshes = gridmap->get_meshes();
|
|
||||||
Transform xform = gridmap->get_global_transform();
|
|
||||||
for (int i = 0; i < meshes.size(); i += 2) {
|
|
||||||
Ref<Mesh> mesh = meshes[i + 1];
|
|
||||||
if (mesh.is_valid()) {
|
|
||||||
Transform mesh_xform = meshes[i];
|
|
||||||
_add_mesh(mesh, p_navmesh_xform * xform * mesh_xform, p_vertices, p_indices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_generate_from != NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES && (gridmap->get_collision_layer() & p_collision_mask)) {
|
|
||||||
Array shapes = gridmap->get_collision_shapes();
|
|
||||||
for (int i = 0; i < shapes.size(); i += 2) {
|
|
||||||
RID shape = shapes[i + 1];
|
|
||||||
PhysicsServer::ShapeType type = PhysicsServer::get_singleton()->shape_get_type(shape);
|
|
||||||
Variant data = PhysicsServer::get_singleton()->shape_get_data(shape);
|
|
||||||
Ref<Mesh> mesh;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case PhysicsServer::SHAPE_SPHERE: {
|
|
||||||
real_t radius = data;
|
|
||||||
Ref<SphereMesh> sphere_mesh;
|
|
||||||
sphere_mesh.instance();
|
|
||||||
sphere_mesh->set_radius(radius);
|
|
||||||
sphere_mesh->set_height(radius * 2.0);
|
|
||||||
mesh = sphere_mesh;
|
|
||||||
} break;
|
|
||||||
case PhysicsServer::SHAPE_BOX: {
|
|
||||||
Vector3 extents = data;
|
|
||||||
Ref<CubeMesh> box_mesh;
|
|
||||||
box_mesh.instance();
|
|
||||||
box_mesh->set_size(2.0 * extents);
|
|
||||||
mesh = box_mesh;
|
|
||||||
} break;
|
|
||||||
case PhysicsServer::SHAPE_CAPSULE: {
|
|
||||||
Dictionary dict = data;
|
|
||||||
real_t radius = dict["radius"];
|
|
||||||
real_t height = dict["height"];
|
|
||||||
Ref<CapsuleMesh> capsule_mesh;
|
|
||||||
capsule_mesh.instance();
|
|
||||||
capsule_mesh->set_radius(radius);
|
|
||||||
capsule_mesh->set_mid_height(0.5 * height);
|
|
||||||
mesh = capsule_mesh;
|
|
||||||
} break;
|
|
||||||
case PhysicsServer::SHAPE_CYLINDER: {
|
|
||||||
Dictionary dict = data;
|
|
||||||
real_t radius = dict["radius"];
|
|
||||||
real_t height = dict["height"];
|
|
||||||
Ref<CylinderMesh> cylinder_mesh;
|
|
||||||
cylinder_mesh.instance();
|
|
||||||
cylinder_mesh->set_height(height);
|
|
||||||
cylinder_mesh->set_bottom_radius(radius);
|
|
||||||
cylinder_mesh->set_top_radius(radius);
|
|
||||||
mesh = cylinder_mesh;
|
|
||||||
} break;
|
|
||||||
case PhysicsServer::SHAPE_CONVEX_POLYGON: {
|
|
||||||
PoolVector3Array vertices = data;
|
|
||||||
Geometry::MeshData md;
|
|
||||||
|
|
||||||
Error err = ConvexHullComputer::convex_hull(vertices, md);
|
|
||||||
|
|
||||||
if (err == OK) {
|
|
||||||
PoolVector3Array faces;
|
|
||||||
|
|
||||||
for (int j = 0; j < md.faces.size(); ++j) {
|
|
||||||
Geometry::MeshData::Face face = md.faces[j];
|
|
||||||
|
|
||||||
for (int k = 2; k < face.indices.size(); ++k) {
|
|
||||||
faces.push_back(md.vertices[face.indices[0]]);
|
|
||||||
faces.push_back(md.vertices[face.indices[k - 1]]);
|
|
||||||
faces.push_back(md.vertices[face.indices[k]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_add_faces(faces, shapes[i], p_vertices, p_indices);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case PhysicsServer::SHAPE_CONCAVE_POLYGON: {
|
|
||||||
PoolVector3Array faces = data;
|
|
||||||
_add_faces(faces, shapes[i], p_vertices, p_indices);
|
|
||||||
} break;
|
|
||||||
default: {
|
|
||||||
WARN_PRINT("Unsupported collision shape type.");
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mesh.is_valid()) {
|
|
||||||
_add_mesh(mesh, shapes[i], p_vertices, p_indices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (p_recurse_children) {
|
if (p_recurse_children) {
|
||||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||||
_parse_geometry(p_navmesh_xform, p_node->get_child(i), p_vertices, p_indices, p_generate_from, p_collision_mask, p_recurse_children);
|
_parse_geometry(p_navmesh_xform, p_node->get_child(i), p_vertices, p_indices, p_generate_from, p_collision_mask, p_recurse_children);
|
||||||
|
@ -49,9 +49,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "modules/modules_enabled.gen.h" // For csg.
|
#include "modules/modules_enabled.gen.h" // For csg.
|
||||||
#ifdef MODULE_CSG_ENABLED
|
|
||||||
#include "modules/csg/csg_shape.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// #define GODOT_PORTALS_USE_BULLET_CONVEX_HULL
|
// #define GODOT_PORTALS_USE_BULLET_CONVEX_HULL
|
||||||
|
|
||||||
@ -1726,56 +1723,7 @@ bool RoomManager::_bound_findpoints_geom_instance(GeometryInstance *p_gi, Vector
|
|||||||
// it can fail once mesh min is larger than FLT_MAX / 2.
|
// it can fail once mesh min is larger than FLT_MAX / 2.
|
||||||
r_aabb.position = Vector3(FLT_MAX / 2, FLT_MAX / 2, FLT_MAX / 2);
|
r_aabb.position = Vector3(FLT_MAX / 2, FLT_MAX / 2, FLT_MAX / 2);
|
||||||
r_aabb.size = Vector3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
r_aabb.size = Vector3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||||
|
|
||||||
#ifdef MODULE_CSG_ENABLED
|
|
||||||
CSGShape *shape = Object::cast_to<CSGShape>(p_gi);
|
|
||||||
if (shape) {
|
|
||||||
// Shapes will not be up to date on the first frame due to a quirk
|
|
||||||
// of CSG - it defers updates to the next frame. So we need to explicitly
|
|
||||||
// force an update to make sure the CSG is correct on level load.
|
|
||||||
shape->force_update_shape();
|
|
||||||
|
|
||||||
Array arr = shape->get_meshes();
|
|
||||||
if (!arr.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<ArrayMesh> arr_mesh = arr[1];
|
|
||||||
if (!arr_mesh.is_valid()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arr_mesh->get_surface_count() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for converting meshes to world space
|
|
||||||
Transform trans = p_gi->get_global_transform();
|
|
||||||
|
|
||||||
for (int surf = 0; surf < arr_mesh->get_surface_count(); surf++) {
|
|
||||||
Array arrays = arr_mesh->surface_get_arrays(surf);
|
|
||||||
|
|
||||||
if (!arrays.size()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PoolVector<Vector3> vertices = arrays[VS::ARRAY_VERTEX];
|
|
||||||
|
|
||||||
// convert to world space
|
|
||||||
for (int n = 0; n < vertices.size(); n++) {
|
|
||||||
Vector3 pt_world = trans.xform(vertices[n]);
|
|
||||||
r_room_pts.push_back(pt_world);
|
|
||||||
|
|
||||||
// keep the bound up to date
|
|
||||||
r_aabb.expand_to(pt_world);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // for through the surfaces
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} // if csg shape
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// multimesh
|
// multimesh
|
||||||
MultiMeshInstance *mmi = Object::cast_to<MultiMeshInstance>(p_gi);
|
MultiMeshInstance *mmi = Object::cast_to<MultiMeshInstance>(p_gi);
|
||||||
if (mmi) {
|
if (mmi) {
|
||||||
|
@ -213,7 +213,6 @@
|
|||||||
#include "scene/3d/visibility_notifier.h"
|
#include "scene/3d/visibility_notifier.h"
|
||||||
#include "scene/animation/skeleton_ik.h"
|
#include "scene/animation/skeleton_ik.h"
|
||||||
#include "scene/resources/environment.h"
|
#include "scene/resources/environment.h"
|
||||||
#include "scene/resources/mesh_library.h"
|
|
||||||
#include "scene/resources/occluder_shape.h"
|
#include "scene/resources/occluder_shape.h"
|
||||||
#include "scene/resources/occluder_shape_polygon.h"
|
#include "scene/resources/occluder_shape_polygon.h"
|
||||||
#endif
|
#endif
|
||||||
@ -583,8 +582,6 @@ void register_scene_types() {
|
|||||||
SceneTree::add_idle_callback(SpatialMaterial::flush_changes);
|
SceneTree::add_idle_callback(SpatialMaterial::flush_changes);
|
||||||
SpatialMaterial::init_shaders();
|
SpatialMaterial::init_shaders();
|
||||||
|
|
||||||
ClassDB::register_class<MeshLibrary>();
|
|
||||||
|
|
||||||
OS::get_singleton()->yield(); //may take time to init
|
OS::get_singleton()->yield(); //may take time to init
|
||||||
|
|
||||||
ClassDB::register_virtual_class<Shape>();
|
ClassDB::register_virtual_class<Shape>();
|
||||||
|
@ -1,335 +0,0 @@
|
|||||||
/*************************************************************************/
|
|
||||||
/* mesh_library.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#include "mesh_library.h"
|
|
||||||
|
|
||||||
#include "box_shape.h"
|
|
||||||
|
|
||||||
bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) {
|
|
||||||
String name = p_name;
|
|
||||||
if (name.begins_with("item/")) {
|
|
||||||
int idx = name.get_slicec('/', 1).to_int();
|
|
||||||
String what = name.get_slicec('/', 2);
|
|
||||||
if (!item_map.has(idx)) {
|
|
||||||
create_item(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (what == "name") {
|
|
||||||
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;
|
|
||||||
sd.shape = p_value;
|
|
||||||
shapes.push_back(sd);
|
|
||||||
set_item_shapes(idx, shapes);
|
|
||||||
} else if (what == "shapes") {
|
|
||||||
_set_item_shapes(idx, p_value);
|
|
||||||
} else if (what == "preview") {
|
|
||||||
set_item_preview(idx, p_value);
|
|
||||||
} else if (what == "navmesh") {
|
|
||||||
set_item_navmesh(idx, p_value);
|
|
||||||
} else if (what == "navmesh_transform") {
|
|
||||||
set_item_navmesh_transform(idx, p_value);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MeshLibrary::_get(const StringName &p_name, Variant &r_ret) const {
|
|
||||||
String name = p_name;
|
|
||||||
int idx = name.get_slicec('/', 1).to_int();
|
|
||||||
ERR_FAIL_COND_V(!item_map.has(idx), false);
|
|
||||||
String what = name.get_slicec('/', 2);
|
|
||||||
|
|
||||||
if (what == "name") {
|
|
||||||
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") {
|
|
||||||
r_ret = get_item_navmesh(idx);
|
|
||||||
} else if (what == "navmesh_transform") {
|
|
||||||
r_ret = get_item_navmesh_transform(idx);
|
|
||||||
} else if (what == "preview") {
|
|
||||||
r_ret = get_item_preview(idx);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
||||||
for (Map<int, Item>::Element *E = item_map.front(); E; E = E->next()) {
|
|
||||||
String name = "item/" + itos(E->key()) + "/";
|
|
||||||
p_list->push_back(PropertyInfo(Variant::STRING, name + "name"));
|
|
||||||
p_list->push_back(PropertyInfo(Variant::OBJECT, name + "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"));
|
|
||||||
p_list->push_back(PropertyInfo(Variant::TRANSFORM, name + "mesh_transform"));
|
|
||||||
p_list->push_back(PropertyInfo(Variant::ARRAY, name + "shapes"));
|
|
||||||
p_list->push_back(PropertyInfo(Variant::OBJECT, name + "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"));
|
|
||||||
p_list->push_back(PropertyInfo(Variant::TRANSFORM, name + "navmesh_transform"));
|
|
||||||
p_list->push_back(PropertyInfo(Variant::OBJECT, name + "preview", PROPERTY_HINT_RESOURCE_TYPE, "Texture", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_HELPER));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::create_item(int p_item) {
|
|
||||||
ERR_FAIL_COND(p_item < 0);
|
|
||||||
ERR_FAIL_COND(item_map.has(p_item));
|
|
||||||
item_map[p_item] = Item();
|
|
||||||
_change_notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::set_item_name(int p_item, const String &p_name) {
|
|
||||||
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
item_map[p_item].name = p_name;
|
|
||||||
emit_changed();
|
|
||||||
_change_notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::set_item_mesh(int p_item, const Ref<Mesh> &p_mesh) {
|
|
||||||
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
item_map[p_item].mesh = p_mesh;
|
|
||||||
notify_change_to_owners();
|
|
||||||
emit_changed();
|
|
||||||
_change_notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::set_item_mesh_transform(int p_item, const Transform &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();
|
|
||||||
_change_notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
_change_notify();
|
|
||||||
notify_change_to_owners();
|
|
||||||
emit_changed();
|
|
||||||
_change_notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh) {
|
|
||||||
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
item_map[p_item].navmesh = p_navmesh;
|
|
||||||
_change_notify();
|
|
||||||
notify_change_to_owners();
|
|
||||||
emit_changed();
|
|
||||||
_change_notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform &p_transform) {
|
|
||||||
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
item_map[p_item].navmesh_transform = p_transform;
|
|
||||||
notify_change_to_owners();
|
|
||||||
emit_changed();
|
|
||||||
_change_notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::set_item_preview(int p_item, const Ref<Texture> &p_preview) {
|
|
||||||
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
item_map[p_item].preview = p_preview;
|
|
||||||
emit_changed();
|
|
||||||
_change_notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
String MeshLibrary::get_item_name(int p_item) const {
|
|
||||||
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), "", "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
return item_map[p_item].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<Mesh> MeshLibrary::get_item_mesh(int p_item) const {
|
|
||||||
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<Mesh>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
return item_map[p_item].mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform MeshLibrary::get_item_mesh_transform(int p_item) const {
|
|
||||||
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Transform(), "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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<NavigationMesh> MeshLibrary::get_item_navmesh(int p_item) const {
|
|
||||||
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<NavigationMesh>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
return item_map[p_item].navmesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform MeshLibrary::get_item_navmesh_transform(int p_item) const {
|
|
||||||
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Transform(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
return item_map[p_item].navmesh_transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<Texture> MeshLibrary::get_item_preview(int p_item) const {
|
|
||||||
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<Texture>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
return item_map[p_item].preview;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MeshLibrary::has_item(int p_item) const {
|
|
||||||
return item_map.has(p_item);
|
|
||||||
}
|
|
||||||
void MeshLibrary::remove_item(int p_item) {
|
|
||||||
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
item_map.erase(p_item);
|
|
||||||
notify_change_to_owners();
|
|
||||||
_change_notify();
|
|
||||||
emit_changed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::clear() {
|
|
||||||
item_map.clear();
|
|
||||||
notify_change_to_owners();
|
|
||||||
_change_notify();
|
|
||||||
emit_changed();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<int> MeshLibrary::get_item_list() const {
|
|
||||||
Vector<int> ret;
|
|
||||||
ret.resize(item_map.size());
|
|
||||||
int idx = 0;
|
|
||||||
for (Map<int, Item>::Element *E = item_map.front(); E; E = E->next()) {
|
|
||||||
ret.write[idx++] = E->key();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MeshLibrary::find_item_by_name(const String &p_name) const {
|
|
||||||
for (Map<int, Item>::Element *E = item_map.front(); E; E = E->next()) {
|
|
||||||
if (E->get().name == p_name) {
|
|
||||||
return E->key();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MeshLibrary::get_last_unused_item_id() const {
|
|
||||||
if (!item_map.size()) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return item_map.back()->key() + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshLibrary::_set_item_shapes(int p_item, const Array &p_shapes) {
|
|
||||||
Array arr_shapes = p_shapes;
|
|
||||||
int size = p_shapes.size();
|
|
||||||
if (size & 1) {
|
|
||||||
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
|
||||||
int prev_size = item_map[p_item].shapes.size() * 2;
|
|
||||||
|
|
||||||
if (prev_size < size) {
|
|
||||||
// Check if last element is a shape.
|
|
||||||
Ref<Shape> shape = arr_shapes[size - 1];
|
|
||||||
if (shape.is_null()) {
|
|
||||||
Ref<BoxShape> box_shape;
|
|
||||||
box_shape.instance();
|
|
||||||
arr_shapes[size - 1] = box_shape;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the added element is a Transform.
|
|
||||||
arr_shapes.push_back(Transform());
|
|
||||||
size++;
|
|
||||||
} else {
|
|
||||||
size--;
|
|
||||||
arr_shapes.resize(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<ShapeData> shapes;
|
|
||||||
for (int i = 0; i < size; i += 2) {
|
|
||||||
ShapeData sd;
|
|
||||||
sd.shape = arr_shapes[i + 0];
|
|
||||||
sd.local_transform = arr_shapes[i + 1];
|
|
||||||
|
|
||||||
if (sd.shape.is_valid()) {
|
|
||||||
shapes.push_back(sd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set_item_shapes(p_item, shapes);
|
|
||||||
}
|
|
||||||
|
|
||||||
Array MeshLibrary::_get_item_shapes(int p_item) const {
|
|
||||||
Vector<ShapeData> shapes = get_item_shapes(p_item);
|
|
||||||
Array ret;
|
|
||||||
for (int i = 0; i < shapes.size(); i++) {
|
|
||||||
ret.push_back(shapes[i].shape);
|
|
||||||
ret.push_back(shapes[i].local_transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_item_preview", "id"), &MeshLibrary::get_item_preview);
|
|
||||||
ClassDB::bind_method(D_METHOD("remove_item", "id"), &MeshLibrary::remove_item);
|
|
||||||
ClassDB::bind_method(D_METHOD("find_item_by_name", "name"), &MeshLibrary::find_item_by_name);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("clear"), &MeshLibrary::clear);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_item_list"), &MeshLibrary::get_item_list);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_last_unused_item_id"), &MeshLibrary::get_last_unused_item_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
MeshLibrary::MeshLibrary() {
|
|
||||||
}
|
|
||||||
MeshLibrary::~MeshLibrary() {
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
/*************************************************************************/
|
|
||||||
/* mesh_library.h */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifndef GRID_THEME_H
|
|
||||||
#define GRID_THEME_H
|
|
||||||
|
|
||||||
#include "core/map.h"
|
|
||||||
#include "core/resource.h"
|
|
||||||
#include "mesh.h"
|
|
||||||
#include "scene/3d/navigation_mesh_instance.h"
|
|
||||||
#include "shape.h"
|
|
||||||
|
|
||||||
class MeshLibrary : public Resource {
|
|
||||||
GDCLASS(MeshLibrary, Resource);
|
|
||||||
RES_BASE_EXTENSION("meshlib");
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct ShapeData {
|
|
||||||
Ref<Shape> shape;
|
|
||||||
Transform local_transform;
|
|
||||||
};
|
|
||||||
struct Item {
|
|
||||||
String name;
|
|
||||||
Ref<Mesh> mesh;
|
|
||||||
Vector<ShapeData> shapes;
|
|
||||||
Ref<Texture> preview;
|
|
||||||
Transform navmesh_transform;
|
|
||||||
Transform mesh_transform;
|
|
||||||
Ref<NavigationMesh> navmesh;
|
|
||||||
};
|
|
||||||
|
|
||||||
Map<int, Item> item_map;
|
|
||||||
|
|
||||||
void _set_item_shapes(int p_item, const Array &p_shapes);
|
|
||||||
Array _get_item_shapes(int p_item) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
|
||||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
|
||||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
|
||||||
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
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 Transform &p_transform);
|
|
||||||
void set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh);
|
|
||||||
void set_item_navmesh_transform(int p_item, const Transform &p_transform);
|
|
||||||
void set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes);
|
|
||||||
void set_item_preview(int p_item, const Ref<Texture> &p_preview);
|
|
||||||
String get_item_name(int p_item) const;
|
|
||||||
Ref<Mesh> get_item_mesh(int p_item) const;
|
|
||||||
Transform get_item_mesh_transform(int p_item) const;
|
|
||||||
Ref<NavigationMesh> get_item_navmesh(int p_item) const;
|
|
||||||
Transform get_item_navmesh_transform(int p_item) const;
|
|
||||||
Vector<ShapeData> get_item_shapes(int p_item) const;
|
|
||||||
Ref<Texture> get_item_preview(int p_item) const;
|
|
||||||
|
|
||||||
void remove_item(int p_item);
|
|
||||||
bool has_item(int p_item) const;
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
int find_item_by_name(const String &p_name) const;
|
|
||||||
|
|
||||||
Vector<int> get_item_list() const;
|
|
||||||
int get_last_unused_item_id() const;
|
|
||||||
|
|
||||||
MeshLibrary();
|
|
||||||
~MeshLibrary();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CUBE_GRID_THEME_H
|
|
Loading…
Reference in New Issue
Block a user