diff --git a/modules/gridmap/config.py b/modules/gridmap/config.py index 720401b92d8..213c96342d2 100644 --- a/modules/gridmap/config.py +++ b/modules/gridmap/config.py @@ -7,9 +7,7 @@ def configure(env): def get_doc_classes(): - return [ - "GridMap", - ] + return ["GridMap", "GridMapEditorPlugin"] def get_doc_path(): diff --git a/modules/gridmap/doc_classes/GridMapEditorPlugin.xml b/modules/gridmap/doc_classes/GridMapEditorPlugin.xml new file mode 100644 index 00000000000..fdda03414a0 --- /dev/null +++ b/modules/gridmap/doc_classes/GridMapEditorPlugin.xml @@ -0,0 +1,66 @@ + + + + Editor for [GridMap] nodes. + + + GridMapEditorPlugin provides access to the [GridMap] editor functionality. + + + + + + + + Deselects any currently selected cells. + + + + + + Returns the [GridMap] node currently edited by the grid map editor. + + + + + + Returns an array of [Vector3i]s with the selected cells' coordinates. + + + + + + Returns the index of the selected [MeshLibrary] item in the grid map editor's palette or [code]-1[/code] if no item is selected. + [b]Note:[/b] The indices might not be in the same order as they appear in the editor's interface. + + + + + + Returns the cell coordinate bounds of the current selection. Use [method has_selection] to check if there is an active selection. + + + + + + Returns [code]true[/code] if there are selected cells. + + + + + + + Selects the [MeshLibrary] item with the given index in the grid map editor's palette. If a negative index is given, no item will be selected. If a value greater than the last index is given, the last item will be selected. + [b]Note:[/b] The indices might not be in the same order as they appear in the editor's interface. + + + + + + + + Selects the cells inside the given bounds from [param begin] to [param end]. + + + + diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index 905067b69bb..8622ab9d261 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -343,6 +343,41 @@ void GridMapEditor::_set_selection(bool p_active, const Vector3 &p_begin, const } } +AABB GridMapEditor::_get_selection() const { + AABB ret; + if (selection.active) { + ret.position = selection.begin; + ret.size = selection.end - selection.begin; + } else { + ret.position.zero(); + ret.size.zero(); + } + return ret; +} + +bool GridMapEditor::_has_selection() const { + return node != nullptr && selection.active; +} + +Array GridMapEditor::_get_selected_cells() const { + Array ret; + if (node != nullptr && selection.active) { + for (int i = selection.begin.x; i <= selection.end.x; i++) { + for (int j = selection.begin.y; j <= selection.end.y; j++) { + for (int k = selection.begin.z; k <= selection.end.z; k++) { + Vector3i selected = Vector3i(i, j, k); + int itm = node->get_cell_item(selected); + if (itm == GridMap::INVALID_CELL_ITEM) { + continue; + } + ret.append(selected); + } + } + } + } + return ret; +} + bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click) { if (!spatial_editor) { return false; @@ -1717,7 +1752,40 @@ GridMapEditor::~GridMapEditor() { } } +void GridMapEditorPlugin::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + grid_map_editor = memnew(GridMapEditor); + grid_map_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); + grid_map_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); + grid_map_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); + grid_map_editor->hide(); + + panel_button = EditorNode::get_bottom_panel()->add_item(TTR("GridMap"), grid_map_editor, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_grid_map_bottom_panel", TTR("Toggle GridMap Bottom Panel"))); + panel_button->hide(); + } break; + case NOTIFICATION_EXIT_TREE: { + EditorNode::get_bottom_panel()->remove_item(grid_map_editor); + memdelete_notnull(grid_map_editor); + grid_map_editor = nullptr; + panel_button = nullptr; + } break; + } +} + +void GridMapEditorPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_current_grid_map"), &GridMapEditorPlugin::get_current_grid_map); + ClassDB::bind_method(D_METHOD("set_selection", "begin", "end"), &GridMapEditorPlugin::set_selection); + ClassDB::bind_method(D_METHOD("clear_selection"), &GridMapEditorPlugin::clear_selection); + ClassDB::bind_method(D_METHOD("get_selection"), &GridMapEditorPlugin::get_selection); + ClassDB::bind_method(D_METHOD("has_selection"), &GridMapEditorPlugin::has_selection); + ClassDB::bind_method(D_METHOD("get_selected_cells"), &GridMapEditorPlugin::get_selected_cells); + ClassDB::bind_method(D_METHOD("set_selected_palette_item", "item"), &GridMapEditorPlugin::set_selected_palette_item); + ClassDB::bind_method(D_METHOD("get_selected_palette_item"), &GridMapEditorPlugin::get_selected_palette_item); +} + void GridMapEditorPlugin::edit(Object *p_object) { + ERR_FAIL_NULL(grid_map_editor); grid_map_editor->edit(Object::cast_to(p_object)); } @@ -1726,6 +1794,7 @@ bool GridMapEditorPlugin::handles(Object *p_object) const { } void GridMapEditorPlugin::make_visible(bool p_visible) { + ERR_FAIL_NULL(grid_map_editor); if (p_visible) { BaseButton *button = grid_map_editor->mode_buttons_group->get_pressed_button(); if (button == nullptr) { @@ -1745,15 +1814,61 @@ void GridMapEditorPlugin::make_visible(bool p_visible) { } } -GridMapEditorPlugin::GridMapEditorPlugin() { - grid_map_editor = memnew(GridMapEditor); - grid_map_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); - grid_map_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); - grid_map_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); - grid_map_editor->hide(); +GridMap *GridMapEditorPlugin::get_current_grid_map() const { + ERR_FAIL_NULL_V(grid_map_editor, nullptr); + return grid_map_editor->node; +} - panel_button = EditorNode::get_bottom_panel()->add_item(TTR("GridMap"), grid_map_editor, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_grid_map_bottom_panel", TTR("Toggle GridMap Bottom Panel"))); - panel_button->hide(); +void GridMapEditorPlugin::set_selection(const Vector3i &p_begin, const Vector3i &p_end) { + ERR_FAIL_NULL(grid_map_editor); + grid_map_editor->_set_selection(true, p_begin, p_end); +} + +void GridMapEditorPlugin::clear_selection() { + ERR_FAIL_NULL(grid_map_editor); + grid_map_editor->_set_selection(false); +} + +AABB GridMapEditorPlugin::get_selection() const { + ERR_FAIL_NULL_V(grid_map_editor, AABB()); + return grid_map_editor->_get_selection(); +} + +bool GridMapEditorPlugin::has_selection() const { + ERR_FAIL_NULL_V(grid_map_editor, false); + return grid_map_editor->_has_selection(); +} + +Array GridMapEditorPlugin::get_selected_cells() const { + ERR_FAIL_NULL_V(grid_map_editor, Array()); + return grid_map_editor->_get_selected_cells(); +} + +void GridMapEditorPlugin::set_selected_palette_item(int p_item) const { + ERR_FAIL_NULL(grid_map_editor); + if (grid_map_editor->node && grid_map_editor->node->get_mesh_library().is_valid()) { + if (p_item < -1) { + p_item = -1; + } else if (p_item >= grid_map_editor->node->get_mesh_library()->get_item_list().size()) { + p_item = grid_map_editor->node->get_mesh_library()->get_item_list().size() - 1; + } + if (p_item != grid_map_editor->selected_palette) { + grid_map_editor->selected_palette = p_item; + grid_map_editor->update_palette(); + } + } +} + +int GridMapEditorPlugin::get_selected_palette_item() const { + ERR_FAIL_NULL_V(grid_map_editor, 0); + if (grid_map_editor->selected_palette >= 0 && grid_map_editor->node && grid_map_editor->node->get_mesh_library().is_valid()) { + return grid_map_editor->selected_palette; + } else { + return -1; + } +} + +GridMapEditorPlugin::GridMapEditorPlugin() { } GridMapEditorPlugin::~GridMapEditorPlugin() { diff --git a/modules/gridmap/editor/grid_map_editor_plugin.h b/modules/gridmap/editor/grid_map_editor_plugin.h index 55d9266aceb..6bab87ba609 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.h +++ b/modules/gridmap/editor/grid_map_editor_plugin.h @@ -243,6 +243,9 @@ class GridMapEditor : public VBoxContainer { void _update_selection_transform(); void _validate_selection(); void _set_selection(bool p_active, const Vector3 &p_begin = Vector3(), const Vector3 &p_end = Vector3()); + AABB _get_selection() const; + bool _has_selection() const; + Array _get_selected_cells() const; void _floor_changed(float p_value); void _floor_mouse_exited(); @@ -272,6 +275,10 @@ class GridMapEditorPlugin : public EditorPlugin { GridMapEditor *grid_map_editor = nullptr; Button *panel_button = nullptr; +protected: + void _notification(int p_what); + static void _bind_methods(); + public: virtual EditorPlugin::AfterGUIInput forward_3d_gui_input(Camera3D *p_camera, const Ref &p_event) override { return grid_map_editor->forward_spatial_input_event(p_camera, p_event); } virtual String get_plugin_name() const override { return "GridMap"; } @@ -280,6 +287,15 @@ public: virtual bool handles(Object *p_object) const override; virtual void make_visible(bool p_visible) override; + GridMap *get_current_grid_map() const; + void set_selection(const Vector3i &p_begin, const Vector3i &p_end); + void clear_selection(); + AABB get_selection() const; + bool has_selection() const; + Array get_selected_cells() const; + void set_selected_palette_item(int p_item) const; + int get_selected_palette_item() const; + GridMapEditorPlugin(); ~GridMapEditorPlugin(); }; diff --git a/modules/gridmap/register_types.cpp b/modules/gridmap/register_types.cpp index 76d24310e91..e293dc72cee 100644 --- a/modules/gridmap/register_types.cpp +++ b/modules/gridmap/register_types.cpp @@ -46,6 +46,7 @@ void initialize_gridmap_module(ModuleInitializationLevel p_level) { } #ifdef TOOLS_ENABLED if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) { + GDREGISTER_CLASS(GridMapEditorPlugin); EditorPlugins::add_by_type(); } #endif