From 0a8cf3cb3fd1d02efbff3e00cfead661fd19d2e3 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sat, 8 Oct 2022 19:48:37 +0200 Subject: [PATCH] Added MeshLibrary to the GridMap module. Also include cleanups. --- modules/gridmap/doc_classes/MeshLibrary.xml | 165 ++++++++++ modules/gridmap/grid_map.cpp | 20 +- modules/gridmap/grid_map.h | 2 +- modules/gridmap/grid_map_editor_plugin.cpp | 90 +++--- modules/gridmap/mesh_library.cpp | 335 ++++++++++++++++++++ modules/gridmap/mesh_library.h | 102 ++++++ modules/gridmap/register_types.cpp | 4 +- 7 files changed, 661 insertions(+), 57 deletions(-) create mode 100644 modules/gridmap/doc_classes/MeshLibrary.xml create mode 100644 modules/gridmap/mesh_library.cpp create mode 100644 modules/gridmap/mesh_library.h diff --git a/modules/gridmap/doc_classes/MeshLibrary.xml b/modules/gridmap/doc_classes/MeshLibrary.xml new file mode 100644 index 000000000..e785f0dec --- /dev/null +++ b/modules/gridmap/doc_classes/MeshLibrary.xml @@ -0,0 +1,165 @@ + + + + Library of meshes. + + + A library of meshes. Contains a list of [Mesh] resources, each with a name and ID. Each item can also include collision and navigation shapes. This resource is used in [GridMap]. + + + https://godotengine.org/asset-library/asset/126 + https://godotengine.org/asset-library/asset/125 + + + + + + Clears the library. + + + + + + + Creates a new item in the library with the given ID. + You can get an unused ID from [method get_last_unused_item_id]. + + + + + + + Returns the first item with the given name. + + + + + + Returns the list of item IDs in use. + + + + + + + Returns the item's mesh. + + + + + + + Returns the transform applied to the item's mesh. + + + + + + + Returns the item's name. + + + + + + + Returns the item's navigation mesh. + + + + + + + Returns the transform applied to the item's navigation mesh. + + + + + + + When running in the editor, returns a generated item preview (a 3D rendering in isometric perspective). When used in a running project, returns the manually-defined item preview which can be set using [method set_item_preview]. Returns an empty [Texture] if no preview was manually set in a running project. + + + + + + + Returns an item's collision shapes. + The array consists of each [Shape] followed by its [Transform]. + + + + + + Gets an unused ID for a new item. + + + + + + + Removes the item. + + + + + + + + Sets the item's mesh. + + + + + + + + Sets the transform to apply to the item's mesh. + + + + + + + + Sets the item's name. + This name is shown in the editor. It can also be used to look up the item later using [method find_item_by_name]. + + + + + + + + Sets the item's navigation mesh. + + + + + + + + Sets the transform to apply to the item's navigation mesh. + + + + + + + + Sets a texture to use as the item's preview icon in the editor. + + + + + + + + Sets an item's collision shapes. + The array should consist of [Shape] objects, each followed by a [Transform] that will be applied to it. For shapes that should not have a transform, use [constant Transform.IDENTITY]. + + + + + + diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index b0a2689e0..a761e61ec 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -31,15 +31,15 @@ #include "grid_map.h" #include "core/io/marshalls.h" -#include "core/message_queue.h" +#include "core/object/message_queue.h" #include "scene/3d/light.h" -#include "scene/resources/mesh_library.h" +#include "mesh_library.h" #include "scene/resources/physics_material.h" #include "scene/resources/primitive_meshes.h" #include "scene/resources/surface_tool.h" #include "scene/scene_string_names.h" #include "servers/navigation_server.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" bool GridMap::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; @@ -74,7 +74,7 @@ bool GridMap::_set(const StringName &p_name, const Variant &p_value) { bm.mesh = meshes[i]; ERR_CONTINUE(!bm.mesh.is_valid()); bm.instance = RID_PRIME(VS::get_singleton()->instance_create()); - VS::get_singleton()->instance_set_portal_mode(bm.instance, VisualServer::InstancePortalMode::INSTANCE_PORTAL_MODE_GLOBAL); + VS::get_singleton()->instance_set_portal_mode(bm.instance, RenderingServer::InstancePortalMode::INSTANCE_PORTAL_MODE_GLOBAL); VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); if (is_inside_tree()) { @@ -355,10 +355,10 @@ void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { SceneTree *st = SceneTree::get_singleton(); if (st && st->is_debugging_collisions_hint()) { - g->collision_debug = RID_PRIME(VisualServer::get_singleton()->mesh_create()); - g->collision_debug_instance = RID_PRIME(VisualServer::get_singleton()->instance_create()); - VS::get_singleton()->instance_set_portal_mode(g->collision_debug_instance, VisualServer::InstancePortalMode::INSTANCE_PORTAL_MODE_GLOBAL); - VisualServer::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug); + g->collision_debug = RID_PRIME(RenderingServer::get_singleton()->mesh_create()); + g->collision_debug_instance = RID_PRIME(RenderingServer::get_singleton()->instance_create()); + VS::get_singleton()->instance_set_portal_mode(g->collision_debug_instance, RenderingServer::InstancePortalMode::INSTANCE_PORTAL_MODE_GLOBAL); + RenderingServer::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug); } octant_map[octantkey] = g; @@ -613,7 +613,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) { RID instance = RID_PRIME(VS::get_singleton()->instance_create()); VS::get_singleton()->instance_set_base(instance, mm); - VS::get_singleton()->instance_set_portal_mode(instance, VisualServer::InstancePortalMode::INSTANCE_PORTAL_MODE_GLOBAL); + VS::get_singleton()->instance_set_portal_mode(instance, RenderingServer::InstancePortalMode::INSTANCE_PORTAL_MODE_GLOBAL); if (is_inside_tree()) { VS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); @@ -1171,7 +1171,7 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe BakedMesh bm; bm.mesh = mesh; bm.instance = RID_PRIME(VS::get_singleton()->instance_create()); - VS::get_singleton()->instance_set_portal_mode(bm.instance, VisualServer::InstancePortalMode::INSTANCE_PORTAL_MODE_GLOBAL); + VS::get_singleton()->instance_set_portal_mode(bm.instance, RenderingServer::InstancePortalMode::INSTANCE_PORTAL_MODE_GLOBAL); VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); if (is_inside_tree()) { diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index b0ebe18bb..9f278e2e0 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -33,7 +33,7 @@ #include "scene/3d/navigation.h" #include "scene/3d/spatial.h" -#include "scene/resources/mesh_library.h" +#include "mesh_library.h" #include "scene/resources/multimesh.h" //heh heh, godotsphir!! this shares no code and the design is completely different with previous projects i've done.. diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 20bcefbe5..53bb28df6 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "grid_map_editor_plugin.h" -#include "core/os/input.h" +#include "core/input/input.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/plugins/spatial_editor_plugin.h" @@ -268,8 +268,8 @@ void GridMapEditor::_update_cursor_transform() { } if (cursor_instance.is_valid()) { - VisualServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); - VisualServer::get_singleton()->instance_set_visible(cursor_instance, cursor_visible); + RenderingServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); + RenderingServer::get_singleton()->instance_set_visible(cursor_instance, cursor_visible); } } @@ -278,9 +278,9 @@ void GridMapEditor::_update_selection_transform() { xf_zero.basis.set_zero(); if (!selection.active) { - VisualServer::get_singleton()->instance_set_transform(selection_instance, xf_zero); + RenderingServer::get_singleton()->instance_set_transform(selection_instance, xf_zero); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); } return; } @@ -289,11 +289,11 @@ void GridMapEditor::_update_selection_transform() { xf.scale((Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size()); xf.origin = selection.begin * node->get_cell_size(); - VisualServer::get_singleton()->instance_set_transform(selection_instance, node->get_global_transform() * xf); + RenderingServer::get_singleton()->instance_set_transform(selection_instance, node->get_global_transform() * xf); for (int i = 0; i < 3; i++) { if (i != edit_axis || (edit_floor[edit_axis] < selection.begin[edit_axis]) || (edit_floor[edit_axis] > selection.end[edit_axis] + 1)) { - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); } else { Vector3 scale = (selection.end - selection.begin + Vector3(1, 1, 1)); scale[edit_axis] = 1.0; @@ -307,7 +307,7 @@ void GridMapEditor::_update_selection_transform() { xf2.basis.scale(scale); xf2.origin = pos; - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); } } } @@ -508,7 +508,7 @@ void GridMapEditor::_fill_selection() { void GridMapEditor::_clear_clipboard_data() { for (List::Element *E = clipboard_items.front(); E; E = E->next()) { if (E->get().instance.is_valid()) { - VisualServer::get_singleton()->free(E->get().instance); + RenderingServer::get_singleton()->free(E->get().instance); } } @@ -534,7 +534,7 @@ void GridMapEditor::_set_clipboard_data() { item.cell_item = itm; item.grid_offset = Vector3(i, j, k) - selection.begin; item.orientation = node->get_cell_item_orientation(i, j, k); - item.instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); + item.instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); clipboard_items.push_back(item); } @@ -546,7 +546,7 @@ void GridMapEditor::_update_paste_indicator() { if (input_action != INPUT_PASTE) { Transform xf; xf.basis.set_zero(); - VisualServer::get_singleton()->instance_set_transform(paste_instance, xf); + RenderingServer::get_singleton()->instance_set_transform(paste_instance, xf); return; } @@ -560,7 +560,7 @@ void GridMapEditor::_update_paste_indicator() { xf.basis = rot * xf.basis; xf.translate((-center * node->get_cell_size()) / scale); - VisualServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf); + RenderingServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf); for (List::Element *E = clipboard_items.front(); E; E = E->next()) { ClipboardItem &item = E->get(); @@ -574,7 +574,7 @@ void GridMapEditor::_update_paste_indicator() { item_rot.set_orthogonal_index(item.orientation); xf.basis = item_rot * xf.basis * node->get_cell_scale(); - VisualServer::get_singleton()->instance_set_transform(item.instance, node->get_global_transform() * xf); + RenderingServer::get_singleton()->instance_set_transform(item.instance, node->get_global_transform() * xf); } } @@ -929,11 +929,11 @@ void GridMapEditor::edit(GridMap *p_gridmap) { if (!node) { set_process(false); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], false); + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], false); } if (cursor_instance.is_valid()) { - VisualServer::get_singleton()->instance_set_visible(cursor_instance, false); + RenderingServer::get_singleton()->instance_set_visible(cursor_instance, false); } return; @@ -971,7 +971,7 @@ void GridMapEditor::update_grid() { edit_grid_xform.basis = Basis(); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], i == edit_axis); + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], i == edit_axis); } updating = true; @@ -1027,8 +1027,8 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) { d.resize(VS::ARRAY_MAX); d[VS::ARRAY_VERTEX] = grid_points[i]; d[VS::ARRAY_COLOR] = grid_colors[i]; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], VisualServer::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], RenderingServer::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); } } @@ -1041,13 +1041,13 @@ void GridMapEditor::_notification(int p_what) { grid[i] = RID_PRIME(VS::get_singleton()->mesh_create()); grid_instance[i] = VS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario()); VS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << SpatialEditorViewport::MISC_TOOL_LAYER); - selection_level_instance[i] = VisualServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world()->get_scenario()); + selection_level_instance[i] = RenderingServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world()->get_scenario()); VS::get_singleton()->instance_set_layer_mask(selection_level_instance[i], 1 << SpatialEditorViewport::MISC_TOOL_LAYER); } - selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario()); + selection_instance = RenderingServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario()); VS::get_singleton()->instance_set_layer_mask(selection_instance, 1 << SpatialEditorViewport::MISC_TOOL_LAYER); - paste_instance = VisualServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world()->get_scenario()); + paste_instance = RenderingServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world()->get_scenario()); VS::get_singleton()->instance_set_layer_mask(paste_instance, 1 << SpatialEditorViewport::MISC_TOOL_LAYER); _update_selection_transform(); @@ -1142,7 +1142,7 @@ void GridMapEditor::_update_cursor_instance() { } if (cursor_instance.is_valid()) { - VisualServer::get_singleton()->free(cursor_instance); + RenderingServer::get_singleton()->free(cursor_instance); cursor_instance = RID(); } @@ -1150,8 +1150,8 @@ void GridMapEditor::_update_cursor_instance() { if (node && !node->get_mesh_library().is_null()) { Ref mesh = node->get_mesh_library()->get_item_mesh(selected_palette); if (!mesh.is_null() && mesh->get_rid().is_valid()) { - cursor_instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); - VisualServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); + cursor_instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); + RenderingServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); } } } @@ -1344,8 +1344,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { lock_view = false; cursor_rot = 0; - selection_mesh = RID_PRIME(VisualServer::get_singleton()->mesh_create()); - paste_mesh = RID_PRIME(VisualServer::get_singleton()->mesh_create()); + selection_mesh = RID_PRIME(RenderingServer::get_singleton()->mesh_create()); + paste_mesh = RID_PRIME(RenderingServer::get_singleton()->mesh_create()); { // Selection mesh create. @@ -1425,8 +1425,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { inner_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); d[VS::ARRAY_VERTEX] = triangles; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_TRIANGLES, d); - VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 0, inner_mat->get_rid()); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_TRIANGLES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_mesh, 0, inner_mat->get_rid()); outer_mat.instance(); outer_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.8)); @@ -1442,22 +1442,22 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { selection_floor_mat->set_line_width(3.0); d[VS::ARRAY_VERTEX] = lines; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat->get_rid()); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat->get_rid()); d[VS::ARRAY_VERTEX] = triangles; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_TRIANGLES, d); - VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 0, inner_mat->get_rid()); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_TRIANGLES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(paste_mesh, 0, inner_mat->get_rid()); d[VS::ARRAY_VERTEX] = lines; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 1, outer_mat->get_rid()); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(paste_mesh, 1, outer_mat->get_rid()); for (int i = 0; i < 3; i++) { d[VS::ARRAY_VERTEX] = square[i]; selection_level_mesh[i] = RID_PRIME(VS::get_singleton()->mesh_create()); - VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_level_mesh[i], VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(selection_level_mesh[i], 0, selection_floor_mat->get_rid()); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_level_mesh[i], VS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_level_mesh[i], 0, selection_floor_mat->get_rid()); } } @@ -1478,33 +1478,33 @@ GridMapEditor::~GridMapEditor() { for (int i = 0; i < 3; i++) { if (grid[i].is_valid()) { - VisualServer::get_singleton()->free(grid[i]); + RenderingServer::get_singleton()->free(grid[i]); } if (grid_instance[i].is_valid()) { - VisualServer::get_singleton()->free(grid_instance[i]); + RenderingServer::get_singleton()->free(grid_instance[i]); } if (cursor_instance.is_valid()) { - VisualServer::get_singleton()->free(cursor_instance); + RenderingServer::get_singleton()->free(cursor_instance); } if (selection_level_instance[i].is_valid()) { - VisualServer::get_singleton()->free(selection_level_instance[i]); + RenderingServer::get_singleton()->free(selection_level_instance[i]); } if (selection_level_mesh[i].is_valid()) { - VisualServer::get_singleton()->free(selection_level_mesh[i]); + RenderingServer::get_singleton()->free(selection_level_mesh[i]); } } if (selection_mesh.is_valid()) { - VisualServer::get_singleton()->free(selection_mesh); + RenderingServer::get_singleton()->free(selection_mesh); } if (selection_instance.is_valid()) { - VisualServer::get_singleton()->free(selection_instance); + RenderingServer::get_singleton()->free(selection_instance); } if (paste_mesh.is_valid()) { - VisualServer::get_singleton()->free(paste_mesh); + RenderingServer::get_singleton()->free(paste_mesh); } if (paste_instance.is_valid()) { - VisualServer::get_singleton()->free(paste_instance); + RenderingServer::get_singleton()->free(paste_instance); } } diff --git a/modules/gridmap/mesh_library.cpp b/modules/gridmap/mesh_library.cpp new file mode 100644 index 000000000..cc07e554a --- /dev/null +++ b/modules/gridmap/mesh_library.cpp @@ -0,0 +1,335 @@ +/*************************************************************************/ +/* 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 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 *p_list) const { + for (Map::Element *E = item_map.front(); E; E = E->next()) { + String name = vformat("%s/%d/", PNAME("item"), E->key()); + p_list->push_back(PropertyInfo(Variant::STRING, name + PNAME("name"))); + p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("mesh"), PROPERTY_HINT_RESOURCE_TYPE, "Mesh")); + p_list->push_back(PropertyInfo(Variant::TRANSFORM, name + PNAME("mesh_transform"))); + p_list->push_back(PropertyInfo(Variant::ARRAY, name + PNAME("shapes"))); + p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("navmesh"), PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh")); + p_list->push_back(PropertyInfo(Variant::TRANSFORM, name + PNAME("navmesh_transform"))); + p_list->push_back(PropertyInfo(Variant::OBJECT, name + PNAME("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 &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 &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 &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 &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 MeshLibrary::get_item_mesh(int p_item) const { + ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref(), "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::get_item_shapes(int p_item) const { + ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Vector(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); + return item_map[p_item].shapes; +} + +Ref MeshLibrary::get_item_navmesh(int p_item) const { + ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref(), "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 MeshLibrary::get_item_preview(int p_item) const { + ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref(), "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 MeshLibrary::get_item_list() const { + Vector ret; + ret.resize(item_map.size()); + int idx = 0; + for (Map::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::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 = arr_shapes[size - 1]; + if (shape.is_null()) { + Ref 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 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 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() { +} diff --git a/modules/gridmap/mesh_library.h b/modules/gridmap/mesh_library.h new file mode 100644 index 000000000..4fb9c311a --- /dev/null +++ b/modules/gridmap/mesh_library.h @@ -0,0 +1,102 @@ +/*************************************************************************/ +/* 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 MESH_LIBRARY_H +#define MESH_LIBRARY_H + +#include "core/containers/map.h" +#include "core/object/resource.h" +#include "scenes/resources/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; + Transform local_transform; + }; + struct Item { + String name; + Ref mesh; + Vector shapes; + Ref preview; + Transform navmesh_transform; + Transform mesh_transform; + Ref navmesh; + }; + + Map 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 *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 &p_mesh); + void set_item_mesh_transform(int p_item, const Transform &p_transform); + void set_item_navmesh(int p_item, const Ref &p_navmesh); + void set_item_navmesh_transform(int p_item, const Transform &p_transform); + void set_item_shapes(int p_item, const Vector &p_shapes); + void set_item_preview(int p_item, const Ref &p_preview); + String get_item_name(int p_item) const; + Ref get_item_mesh(int p_item) const; + Transform get_item_mesh_transform(int p_item) const; + Ref get_item_navmesh(int p_item) const; + Transform get_item_navmesh_transform(int p_item) const; + Vector get_item_shapes(int p_item) const; + Ref 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 get_item_list() const; + int get_last_unused_item_id() const; + + MeshLibrary(); + ~MeshLibrary(); +}; + +#endif // MESH_LIBRARY_H diff --git a/modules/gridmap/register_types.cpp b/modules/gridmap/register_types.cpp index adacbea7f..f1ec2a967 100644 --- a/modules/gridmap/register_types.cpp +++ b/modules/gridmap/register_types.cpp @@ -30,14 +30,16 @@ #include "register_types.h" #ifndef _3D_DISABLED -#include "core/class_db.h" +#include "core/object/class_db.h" #include "grid_map.h" #include "grid_map_editor_plugin.h" +#include "mesh_library.h" #endif void register_gridmap_types() { #ifndef _3D_DISABLED ClassDB::register_class(); + ClassDB::register_class(); #ifdef TOOLS_ENABLED EditorPlugins::add_by_type(); #endif