Enable Vertical orientation for TileMap Dock

This commit is contained in:
Logan Detrick 2025-11-25 19:49:44 -08:00
parent 9dd6c4dbac
commit ad094b93be
3 changed files with 218 additions and 128 deletions

View file

@ -42,6 +42,7 @@
#include "editor/themes/editor_scale.h"
#include "scene/2d/tile_map.h"
#include "scene/2d/tile_map_layer.h"
#include "scene/gui/grid_container.h"
#include "scene/gui/split_container.h"
#include "core/input/input.h"
@ -49,6 +50,20 @@
#include "core/math/random_pcg.h"
#include "core/os/keyboard.h"
void SwitchSeparator::set_vertical(bool p_vertical) {
h_separator->set_visible(p_vertical);
v_separator->set_visible(!p_vertical);
}
SwitchSeparator::SwitchSeparator() {
h_separator = memnew(HSeparator);
h_separator->hide();
add_child(h_separator);
v_separator = memnew(VSeparator);
add_child(v_separator);
}
TileMapLayer *TileMapLayerSubEditorPlugin::_get_edited_layer() const {
return ObjectDB::get_instance<TileMapLayer>(edited_tile_map_layer_id);
}
@ -95,32 +110,14 @@ void TileMapLayerEditorTilesPlugin::_update_toolbar() {
// Stop dragging if needed.
_stop_dragging();
// Hide all settings.
for (int i = 0; i < tools_settings->get_child_count(); i++) {
Object::cast_to<CanvasItem>(tools_settings->get_child(i))->hide();
}
// Show only the correct settings.
if (tool_buttons_group->get_pressed_button() == select_tool_button) {
transform_toolbar->show();
} else if (tool_buttons_group->get_pressed_button() != bucket_tool_button) {
tools_settings_vsep->show();
picker_button->show();
erase_button->show();
transform_toolbar->show();
tools_settings_vsep_2->show();
random_tile_toggle->show();
scatter_controls_container->set_visible(random_tile_toggle->is_pressed());
} else {
tools_settings_vsep->show();
picker_button->show();
erase_button->show();
transform_toolbar->show();
tools_settings_vsep_2->show();
bucket_contiguous_checkbox->show();
random_tile_toggle->show();
scatter_controls_container->set_visible(random_tile_toggle->is_pressed());
}
bool using_select = (tool_buttons_group->get_pressed_button() == select_tool_button);
tools_settings_vsep->set_visible(!using_select);
picker_button->set_visible(!using_select);
erase_button->set_visible(!using_select);
random_tile_toggle->set_visible(!using_select);
bucket_contiguous_checkbox->set_visible(!using_select && tool_buttons_group->get_pressed_button() == bucket_tool_button);
scatter_controls_container->set_visible(!using_select && random_tile_toggle->is_pressed());
CanvasItemEditor::get_singleton()->set_current_tool(CanvasItemEditor::TOOL_SELECT);
}
@ -156,8 +153,12 @@ void TileMapLayerEditorTilesPlugin::_set_transform_buttons_state(const Vector<Bu
Vector<TileMapLayerSubEditorPlugin::TabData> TileMapLayerEditorTilesPlugin::get_tabs() const {
Vector<TileMapLayerSubEditorPlugin::TabData> tabs;
tabs.push_back({ toolbar, tiles_bottom_panel });
tabs.push_back({ toolbar, patterns_bottom_panel });
Vector<Control *> toolbar_controls;
toolbar_controls.push_back(tilemap_tiles_tools_buttons);
toolbar_controls.push_back(tools_settings);
toolbar_controls.push_back(tools_settings_vsep);
tabs.push_back({ toolbar_controls, wide_toolbar, tiles_bottom_panel });
tabs.push_back({ toolbar_controls, wide_toolbar, patterns_bottom_panel });
return tabs;
}
@ -2141,6 +2142,19 @@ void TileMapLayerEditorTilesPlugin::edit(ObjectID p_tile_map_layer_id) {
edited_tile_map_layer_id = p_tile_map_layer_id;
}
void TileMapLayerEditorTilesPlugin::update_layout(EditorDock::DockLayout p_layout) {
bool is_vertical = (p_layout == EditorDock::DockLayout::DOCK_LAYOUT_VERTICAL);
atlas_sources_split_container->set_vertical(is_vertical);
atlas_sources_split_container->move_child(split_container_left_side, is_vertical ? -1 : 0);
split_container_left_side->set_vertical(!is_vertical);
tilemap_tiles_tools_buttons->set_vertical(is_vertical);
transform_toolbar->set_vertical(is_vertical);
tools_settings->set_vertical(is_vertical);
tools_settings_vsep->set_vertical(is_vertical);
transform_separator->set_vertical(is_vertical);
}
TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
CanvasItemEditor::get_singleton()
->get_viewport_control()
@ -2154,9 +2168,9 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
// --- Toolbar ---
toolbar = memnew(HBoxContainer);
wide_toolbar = memnew(HBoxContainer);
HBoxContainer *tilemap_tiles_tools_buttons = memnew(HBoxContainer);
tilemap_tiles_tools_buttons = memnew(BoxContainer);
tool_buttons_group.instantiate();
@ -2210,15 +2224,12 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
bucket_tool_button->connect(SceneStringName(pressed), callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_toolbar));
bucket_tool_button->set_accessibility_name(TTRC("Bucket Tool"));
tilemap_tiles_tools_buttons->add_child(bucket_tool_button);
toolbar->add_child(tilemap_tiles_tools_buttons);
viewport_shortcut_buttons.push_back(bucket_tool_button);
// -- TileMap tool settings --
tools_settings = memnew(HBoxContainer);
toolbar->add_child(tools_settings);
tools_settings_vsep = memnew(VSeparator);
tools_settings->add_child(tools_settings_vsep);
tools_settings = memnew(BoxContainer);
tools_settings_vsep = memnew(SwitchSeparator);
tools_settings_vsep->set_vertical(false);
// Picker
picker_button = memnew(Button);
@ -2244,9 +2255,11 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
viewport_shortcut_buttons.push_back(erase_button);
// Transform toolbar.
transform_toolbar = memnew(HBoxContainer);
transform_toolbar = memnew(BoxContainer);
tools_settings->add_child(transform_toolbar);
transform_toolbar->add_child(memnew(VSeparator));
transform_separator = memnew(SwitchSeparator);
transform_separator->set_vertical(false);
transform_toolbar->add_child(transform_separator);
transform_button_rotate_left = memnew(Button);
transform_button_rotate_left->set_theme_type_variation(SceneStringName(FlatButton));
@ -2280,16 +2293,13 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
transform_button_flip_v->set_accessibility_name(TTRC("Flip Tile Vertically"));
viewport_shortcut_buttons.push_back(transform_button_flip_v);
// Separator 2.
tools_settings_vsep_2 = memnew(VSeparator);
tools_settings->add_child(tools_settings_vsep_2);
// Continuous checkbox.
bucket_contiguous_checkbox = memnew(CheckBox);
bucket_contiguous_checkbox->set_flat(true);
bucket_contiguous_checkbox->set_text(TTR("Contiguous"));
bucket_contiguous_checkbox->set_pressed(true);
tools_settings->add_child(bucket_contiguous_checkbox);
bucket_contiguous_checkbox->hide();
wide_toolbar->add_child(bucket_contiguous_checkbox);
// Random tile checkbox.
random_tile_toggle = memnew(Button);
@ -2300,7 +2310,8 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
tools_settings->add_child(random_tile_toggle);
// Random tile scattering.
scatter_controls_container = memnew(HBoxContainer);
scatter_controls_container = memnew(BoxContainer);
scatter_controls_container->set_vertical(false);
scatter_label = memnew(Label);
scatter_label->set_tooltip_text(TTR("Modifies the chance of painting nothing instead of a randomly selected tile."));
@ -2316,7 +2327,7 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
scatter_spinbox->connect(SceneStringName(value_changed), callable_mp(this, &TileMapLayerEditorTilesPlugin::_on_scattering_spinbox_changed));
scatter_spinbox->set_accessibility_name(TTRC("Scattering:"));
scatter_controls_container->add_child(scatter_spinbox);
tools_settings->add_child(scatter_controls_container);
wide_toolbar->add_child(scatter_controls_container);
_on_random_tile_checkbox_toggled(false);
@ -2345,25 +2356,26 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
missing_source_label->hide();
tiles_bottom_panel->add_child(missing_source_label);
atlas_sources_split_container = memnew(HSplitContainer);
atlas_sources_split_container = memnew(SplitContainer);
atlas_sources_split_container->set_vertical(false);
atlas_sources_split_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
atlas_sources_split_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tiles_bottom_panel->add_child(atlas_sources_split_container);
VBoxContainer *split_container_left_side = memnew(VBoxContainer);
split_container_left_side = memnew(BoxContainer);
split_container_left_side->set_vertical(true);
split_container_left_side->set_h_size_flags(Control::SIZE_EXPAND_FILL);
split_container_left_side->set_v_size_flags(Control::SIZE_EXPAND_FILL);
split_container_left_side->set_stretch_ratio(0.25);
split_container_left_side->set_custom_minimum_size(Size2(70, 0) * EDSCALE);
atlas_sources_split_container->add_child(split_container_left_side);
HBoxContainer *sources_bottom_actions = memnew(HBoxContainer);
sources_bottom_actions->set_alignment(HBoxContainer::ALIGNMENT_END);
source_sort_button = memnew(MenuButton);
source_sort_button->set_flat(false);
source_sort_button->set_theme_type_variation("FlatMenuButton");
source_sort_button->set_tooltip_text(TTR("Sort sources"));
source_sort_button->set_h_size_flags(Control::SIZE_SHRINK_END);
source_sort_button->set_v_size_flags(Control::SIZE_SHRINK_END);
PopupMenu *p = source_sort_button->get_popup();
p->connect(SceneStringName(id_pressed), callable_mp(this, &TileMapLayerEditorTilesPlugin::_set_source_sort));
@ -2372,7 +2384,6 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
p->add_radio_check_item(TTR("Sort by Name (Ascending)"), TilesEditorUtils::SOURCE_SORT_NAME);
p->add_radio_check_item(TTR("Sort by Name (Descending)"), TilesEditorUtils::SOURCE_SORT_NAME_REVERSE);
p->set_item_checked(TilesEditorUtils::SOURCE_SORT_ID, true);
sources_bottom_actions->add_child(source_sort_button);
sources_list = memnew(TileSetSourceItemList);
sources_list->connect(SceneStringName(item_selected), callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_source_display).unbind(1));
@ -2381,7 +2392,7 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
sources_list->connect(SceneStringName(visibility_changed), callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::synchronize_sources_list).bind(sources_list, source_sort_button));
sources_list->connect("sort_request", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_tile_set_sources_list));
split_container_left_side->add_child(sources_list);
split_container_left_side->add_child(sources_bottom_actions);
split_container_left_side->add_child(source_sort_button);
// Tile atlas source.
tile_atlas_view = memnew(TileAtlasView);
@ -2465,28 +2476,15 @@ void TileMapLayerEditorTerrainsPlugin::tile_set_changed() {
}
void TileMapLayerEditorTerrainsPlugin::_update_toolbar() {
// Hide all settings.
for (int i = 0; i < tools_settings->get_child_count(); i++) {
Object::cast_to<CanvasItem>(tools_settings->get_child(i))->hide();
}
// Show only the correct settings.
if (tool_buttons_group->get_pressed_button() != bucket_tool_button) {
tools_settings_vsep->show();
picker_button->show();
erase_button->show();
} else {
tools_settings_vsep->show();
picker_button->show();
erase_button->show();
tools_settings_vsep_2->show();
bucket_contiguous_checkbox->show();
}
bucket_contiguous_checkbox->set_visible(tool_buttons_group->get_pressed_button() == bucket_tool_button);
}
Vector<TileMapLayerSubEditorPlugin::TabData> TileMapLayerEditorTerrainsPlugin::get_tabs() const {
Vector<TileMapLayerSubEditorPlugin::TabData> tabs;
tabs.push_back({ toolbar, main_vbox_container });
Vector<Control *> toolbar_controls;
toolbar_controls.push_back(tilemap_tiles_tools_buttons);
toolbar_controls.push_back(tools_settings);
tabs.push_back({ toolbar_controls, wide_toolbar, main_box_container });
return tabs;
}
@ -2964,7 +2962,7 @@ void TileMapLayerEditorTerrainsPlugin::_update_selection() {
}
bool TileMapLayerEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
if (!main_vbox_container->is_visible_in_tree()) {
if (!main_box_container->is_visible_in_tree()) {
// If the bottom editor is not visible, we ignore inputs.
return false;
}
@ -3119,7 +3117,7 @@ void TileMapLayerEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control
bool drawing_rect = false;
// Handle the preview of the tiles to be placed.
if (main_vbox_container->is_visible_in_tree() && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered.
if (main_box_container->is_visible_in_tree() && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered.
RBSet<Vector2i> preview;
Rect2i drawn_grid_rect;
@ -3315,13 +3313,13 @@ void TileMapLayerEditorTerrainsPlugin::_update_terrains_tree() {
TreeItem *terrain_set_tree_item = terrains_tree->create_item();
String matches;
if (tile_set->get_terrain_set_mode(terrain_set_index) == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
terrain_set_tree_item->set_icon(0, main_vbox_container->get_editor_theme_icon(SNAME("TerrainMatchCornersAndSides")));
terrain_set_tree_item->set_icon(0, main_box_container->get_editor_theme_icon(SNAME("TerrainMatchCornersAndSides")));
matches = String(TTR("Matches Corners and Sides"));
} else if (tile_set->get_terrain_set_mode(terrain_set_index) == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
terrain_set_tree_item->set_icon(0, main_vbox_container->get_editor_theme_icon(SNAME("TerrainMatchCorners")));
terrain_set_tree_item->set_icon(0, main_box_container->get_editor_theme_icon(SNAME("TerrainMatchCorners")));
matches = String(TTR("Matches Corners Only"));
} else {
terrain_set_tree_item->set_icon(0, main_vbox_container->get_editor_theme_icon(SNAME("TerrainMatchSides")));
terrain_set_tree_item->set_icon(0, main_box_container->get_editor_theme_icon(SNAME("TerrainMatchSides")));
matches = String(TTR("Matches Sides Only"));
}
terrain_set_tree_item->set_text(0, vformat(TTR("Terrain Set %d (%s)"), terrain_set_index, matches));
@ -3364,13 +3362,13 @@ void TileMapLayerEditorTerrainsPlugin::_update_tiles_list() {
ERR_FAIL_INDEX(sel_terrain_id, tile_set->get_terrains_count(sel_terrain_set));
// Add the two first generic modes
int item_index = terrains_tile_list->add_icon_item(main_vbox_container->get_editor_theme_icon(SNAME("TerrainConnect")));
int item_index = terrains_tile_list->add_icon_item(main_box_container->get_editor_theme_icon(SNAME("TerrainConnect")));
terrains_tile_list->set_item_tooltip(item_index, TTR("Connect mode: paints a terrain, then connects it with the surrounding tiles with the same terrain."));
Dictionary list_metadata_dict;
list_metadata_dict["type"] = SELECTED_TYPE_CONNECT;
terrains_tile_list->set_item_metadata(item_index, list_metadata_dict);
item_index = terrains_tile_list->add_icon_item(main_vbox_container->get_editor_theme_icon(SNAME("TerrainPath")));
item_index = terrains_tile_list->add_icon_item(main_box_container->get_editor_theme_icon(SNAME("TerrainPath")));
terrains_tile_list->set_item_tooltip(item_index, TTR("Path mode: paints a terrain, then connects it to the previous tile painted within the same stroke."));
list_metadata_dict = Dictionary();
list_metadata_dict["type"] = SELECTED_TYPE_PATH;
@ -3441,13 +3439,13 @@ void TileMapLayerEditorTerrainsPlugin::_update_tiles_list() {
}
void TileMapLayerEditorTerrainsPlugin::_update_theme() {
paint_tool_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Edit")));
line_tool_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Line")));
rect_tool_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Rectangle")));
bucket_tool_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Bucket")));
paint_tool_button->set_button_icon(main_box_container->get_editor_theme_icon(SNAME("Edit")));
line_tool_button->set_button_icon(main_box_container->get_editor_theme_icon(SNAME("Line")));
rect_tool_button->set_button_icon(main_box_container->get_editor_theme_icon(SNAME("Rectangle")));
bucket_tool_button->set_button_icon(main_box_container->get_editor_theme_icon(SNAME("Bucket")));
picker_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("ColorPick")));
erase_button->set_button_icon(main_vbox_container->get_editor_theme_icon(SNAME("Eraser")));
picker_button->set_button_icon(main_box_container->get_editor_theme_icon(SNAME("ColorPick")));
erase_button->set_button_icon(main_box_container->get_editor_theme_icon(SNAME("Eraser")));
_update_tiles_list();
}
@ -3465,21 +3463,38 @@ void TileMapLayerEditorTerrainsPlugin::edit(ObjectID p_edited_tile_map_layer_id)
}
}
void TileMapLayerEditorTerrainsPlugin::update_layout(EditorDock::DockLayout p_layout) {
bool is_vertical = (p_layout == EditorDock::DockLayout::DOCK_LAYOUT_VERTICAL);
// Main Panel.
main_box_container->set_vertical(is_vertical);
tilemap_tab_terrains->move_child(terrains_tree, is_vertical ? 1 : 0);
tilemap_tab_terrains->set_vertical(is_vertical);
// Toolbar.
tilemap_tiles_tools_buttons->set_vertical(is_vertical);
tools_settings->set_vertical(is_vertical);
tools_settings_vsep->set_vertical(is_vertical);
}
TileMapLayerEditorTerrainsPlugin::TileMapLayerEditorTerrainsPlugin() {
main_vbox_container = memnew(VBoxContainer);
wide_toolbar = memnew(HBoxContainer);
main_box_container = memnew(BoxContainer);
main_box_container->set_vertical(true);
// FIXME: This can trigger theme updates when the nodes that we want to update are not yet available.
// The toolbar should be extracted to a dedicated control and theme updates should be handled through
// the notification.
main_vbox_container->connect(SceneStringName(theme_changed), callable_mp(this, &TileMapLayerEditorTerrainsPlugin::_update_theme));
main_vbox_container->set_name(TTR("Terrains"));
main_box_container->connect(SceneStringName(theme_changed), callable_mp(this, &TileMapLayerEditorTerrainsPlugin::_update_theme));
main_box_container->set_name(TTRC("Terrains"));
HSplitContainer *tilemap_tab_terrains = memnew(HSplitContainer);
tilemap_tab_terrains = memnew(SplitContainer);
tilemap_tab_terrains->set_vertical(false);
tilemap_tab_terrains->set_h_size_flags(Control::SIZE_EXPAND_FILL);
tilemap_tab_terrains->set_v_size_flags(Control::SIZE_EXPAND_FILL);
main_vbox_container->add_child(tilemap_tab_terrains);
main_box_container->add_child(tilemap_tab_terrains);
terrains_tree = memnew(Tree);
terrains_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL);
terrains_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
terrains_tree->set_stretch_ratio(0.25);
terrains_tree->set_custom_minimum_size(Size2(70, 0) * EDSCALE);
terrains_tree->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
@ -3491,6 +3506,7 @@ TileMapLayerEditorTerrainsPlugin::TileMapLayerEditorTerrainsPlugin() {
terrains_tile_list = memnew(ItemList);
terrains_tile_list->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED);
terrains_tile_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
terrains_tile_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
terrains_tile_list->set_max_columns(0);
terrains_tile_list->set_same_column_width(true);
terrains_tile_list->set_fixed_icon_size(Size2(32, 32) * EDSCALE);
@ -3498,10 +3514,7 @@ TileMapLayerEditorTerrainsPlugin::TileMapLayerEditorTerrainsPlugin() {
tilemap_tab_terrains->add_child(terrains_tile_list);
// --- Toolbar ---
toolbar = memnew(HBoxContainer);
HBoxContainer *tilemap_tiles_tools_buttons = memnew(HBoxContainer);
tilemap_tiles_tools_buttons = memnew(BoxContainer);
tool_buttons_group.instantiate();
paint_tool_button = memnew(Button);
@ -3545,13 +3558,11 @@ TileMapLayerEditorTerrainsPlugin::TileMapLayerEditorTerrainsPlugin() {
tilemap_tiles_tools_buttons->add_child(bucket_tool_button);
viewport_shortcut_buttons.push_back(bucket_tool_button);
toolbar->add_child(tilemap_tiles_tools_buttons);
// -- TileMap tool settings --
tools_settings = memnew(HBoxContainer);
toolbar->add_child(tools_settings);
tools_settings = memnew(BoxContainer);
tools_settings_vsep = memnew(VSeparator);
tools_settings_vsep = memnew(SwitchSeparator);
tools_settings_vsep->set_vertical(false);
tools_settings->add_child(tools_settings_vsep);
// Picker
@ -3574,16 +3585,13 @@ TileMapLayerEditorTerrainsPlugin::TileMapLayerEditorTerrainsPlugin() {
tools_settings->add_child(erase_button);
viewport_shortcut_buttons.push_back(erase_button);
// Separator 2.
tools_settings_vsep_2 = memnew(VSeparator);
tools_settings->add_child(tools_settings_vsep_2);
// Continuous checkbox.
bucket_contiguous_checkbox = memnew(CheckBox);
bucket_contiguous_checkbox->set_flat(true);
bucket_contiguous_checkbox->set_text(TTR("Contiguous"));
bucket_contiguous_checkbox->set_pressed(true);
tools_settings->add_child(bucket_contiguous_checkbox);
bucket_contiguous_checkbox->hide();
wide_toolbar->add_child(bucket_contiguous_checkbox);
}
TileMapLayer *TileMapLayerEditor::_get_edited_layer() const {
@ -4062,9 +4070,16 @@ void TileMapLayerEditor::_tab_changed(int p_tab_id) {
// Update toolbar.
for (TileMapLayerSubEditorPlugin::TabData &tab_data : tabs_data) {
tab_data.toolbar->hide();
for (Control *toolbar_control : tab_data.toolbar) {
toolbar_control->hide();
}
tabs_data[p_tab_id].toolbar->show();
tab_data.wide_toolbar->hide();
}
for (Control *toolbar_control : tabs_data[p_tab_id].toolbar) {
toolbar_control->show();
}
tabs_data[p_tab_id].wide_toolbar->show();
// Update visible panel.
for (TileMapLayerSubEditorPlugin::TabData &tab_data : tabs_data) {
@ -4396,17 +4411,51 @@ void TileMapLayerEditor::set_show_layer_selector(bool p_show_layer_selector) {
_update_layers_selector();
}
void TileMapLayerEditor::update_layout(DockLayout p_layout) {
bool is_vertical = (p_layout == EditorDock::DockLayout::DOCK_LAYOUT_VERTICAL);
tabs_bar->get_parent()->remove_child(tabs_bar);
tile_map_toolbar->set_vertical(is_vertical);
layer_selector_separator->set_vertical(is_vertical);
layer_selection_hbox->set_vertical(is_vertical);
tile_map_toolbar->set_h_size_flags(is_vertical ? SIZE_SHRINK_BEGIN : SIZE_EXPAND_FILL);
tile_map_toolbar->set_v_size_flags(is_vertical ? SIZE_EXPAND_FILL : SIZE_SHRINK_BEGIN);
main_box_container->move_child(padding_control, is_vertical ? 0 : 3);
if (is_vertical) {
tile_map_wide_toolbar->add_child(tabs_bar);
} else {
tile_map_toolbar->add_child(tabs_bar);
tile_map_toolbar->move_child(tabs_bar, 0);
}
for (TileMapLayerSubEditorPlugin::TabData &tab_data : tabs_data) {
tab_data.wide_toolbar->get_parent()->remove_child(tab_data.wide_toolbar);
if (is_vertical) {
tile_map_wide_toolbar->add_child(tab_data.wide_toolbar);
} else {
tile_map_toolbar->add_child(tab_data.wide_toolbar);
}
}
// Propagate layout change to sub plugins
for (TileMapLayerSubEditorPlugin *tab_plugin : tabs_plugins) {
tab_plugin->update_layout(p_layout);
}
}
TileMapLayerEditor::TileMapLayerEditor() {
set_process_internal(true);
set_name(TTRC("TileMap"));
set_icon_name("TileMapDock");
set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_tile_map_bottom_panel", TTRC("Open TileMap Dock")));
set_default_slot(DockConstants::DOCK_SLOT_BOTTOM);
set_available_layouts(EditorDock::DOCK_LAYOUT_HORIZONTAL | EditorDock::DOCK_LAYOUT_FLOATING);
set_available_layouts(EditorDock::DOCK_LAYOUT_ALL);
set_global(false);
set_transient(true);
VBoxContainer *main_box_container = memnew(VBoxContainer);
main_box_container = memnew(GridContainer);
main_box_container->set_columns(2);
add_child(main_box_container);
// Shortcuts.
@ -4431,18 +4480,31 @@ TileMapLayerEditor::TileMapLayerEditor() {
tabs_bar->connect("tab_changed", callable_mp(this, &TileMapLayerEditor::_tab_changed));
// --- TileMap toolbar ---
tile_map_toolbar = memnew(HFlowContainer);
tile_map_wide_toolbar = memnew(VBoxContainer);
main_box_container->add_child(tile_map_wide_toolbar);
tile_map_toolbar = memnew(FlowContainer);
tile_map_toolbar->set_h_size_flags(SIZE_EXPAND_FILL);
main_box_container->add_child(tile_map_toolbar);
padding_control = memnew(Control);
main_box_container->add_child(padding_control);
// Tabs.
tile_map_toolbar->add_child(tabs_bar);
// Tabs toolbars.
for (TileMapLayerSubEditorPlugin::TabData &tab_data : tabs_data) {
tab_data.toolbar->hide();
if (!tab_data.toolbar->get_parent()) {
tile_map_toolbar->add_child(tab_data.toolbar);
for (Control *toolbar_control : tab_data.toolbar) {
toolbar_control->hide();
if (!toolbar_control->get_parent()) {
tile_map_toolbar->add_child(toolbar_control);
}
}
tab_data.wide_toolbar->hide();
if (!tab_data.wide_toolbar->get_parent()) {
tile_map_toolbar->add_child(tab_data.wide_toolbar);
}
}
@ -4453,7 +4515,7 @@ TileMapLayerEditor::TileMapLayerEditor() {
tile_map_toolbar->add_child(c);
// Layer selector.
layer_selection_hbox = memnew(HBoxContainer);
layer_selection_hbox = memnew(BoxContainer);
tile_map_toolbar->add_child(layer_selection_hbox);
layers_selection_button = memnew(OptionButton);
@ -4477,7 +4539,6 @@ TileMapLayerEditor::TileMapLayerEditor() {
select_all_layers = memnew(Button);
select_all_layers->set_theme_type_variation(SceneStringName(FlatButton));
select_all_layers->set_text(TTR("Select all layers"));
select_all_layers->connect(SceneStringName(pressed), callable_mp(this, &TileMapLayerEditor::_select_all_layers_pressed));
select_all_layers->set_tooltip_text(TTR("Select all TileMapLayers in scene"));
layer_selection_hbox->add_child(select_all_layers);
@ -4490,7 +4551,9 @@ TileMapLayerEditor::TileMapLayerEditor() {
toggle_highlight_selected_layer_button->set_tooltip_text(TTR("Highlight Selected TileMap Layer"));
tile_map_toolbar->add_child(toggle_highlight_selected_layer_button);
tile_map_toolbar->add_child(memnew(VSeparator));
layer_selector_separator = memnew(SwitchSeparator);
layer_selector_separator->set_vertical(false);
tile_map_toolbar->add_child(layer_selector_separator);
// Grid toggle.
toggle_grid_button = memnew(Button);

View file

@ -30,6 +30,7 @@
#pragma once
#include "scene/gui/margin_container.h"
#include "tile_atlas_view.h"
#include "core/os/thread.h"
@ -49,6 +50,19 @@
class TileMapLayer;
class TileMapLayerEditor;
class TileSetSourceItemList;
class GridContainer;
class SwitchSeparator : public MarginContainer {
GDCLASS(SwitchSeparator, MarginContainer);
HSeparator *h_separator = nullptr;
VSeparator *v_separator = nullptr;
public:
void set_vertical(bool p_vertical);
SwitchSeparator();
};
class TileMapLayerSubEditorPlugin : public Object {
GDSOFTCLASS(TileMapLayerSubEditorPlugin, Object);
@ -60,7 +74,8 @@ protected:
public:
struct TabData {
Control *toolbar = nullptr;
Vector<Control *> toolbar;
Control *wide_toolbar;
Control *panel = nullptr;
};
@ -73,6 +88,7 @@ public:
virtual void tile_set_changed() {}
virtual void edit(ObjectID p_tile_map_layer_id) {}
virtual void draw_tile_coords_over_viewport(Control *p_overlay, const TileMapLayer *p_edited_layer, Ref<TileSet> p_tile_set, bool p_show_rectangle_size, const Vector2i &p_rectangle_origin);
virtual void update_layout(EditorDock::DockLayout p_layout) {}
};
class TileMapLayerEditorTilesPlugin : public TileMapLayerSubEditorPlugin {
@ -88,8 +104,9 @@ public:
private:
///// Toolbar /////
HBoxContainer *toolbar = nullptr;
HBoxContainer *wide_toolbar = nullptr;
BoxContainer *tilemap_tiles_tools_buttons = nullptr;
Ref<ButtonGroup> tool_buttons_group;
Button *select_tool_button = nullptr;
Button *paint_tool_button = nullptr;
@ -97,23 +114,23 @@ private:
Button *rect_tool_button = nullptr;
Button *bucket_tool_button = nullptr;
HBoxContainer *tools_settings = nullptr;
BoxContainer *tools_settings = nullptr;
VSeparator *tools_settings_vsep = nullptr;
SwitchSeparator *tools_settings_vsep = nullptr;
Button *picker_button = nullptr;
Button *erase_button = nullptr;
HBoxContainer *transform_toolbar = nullptr;
BoxContainer *transform_toolbar = nullptr;
Button *transform_button_rotate_left = nullptr;
Button *transform_button_rotate_right = nullptr;
Button *transform_button_flip_h = nullptr;
Button *transform_button_flip_v = nullptr;
SwitchSeparator *transform_separator = nullptr;
VSeparator *tools_settings_vsep_2 = nullptr;
CheckBox *bucket_contiguous_checkbox = nullptr;
Button *random_tile_toggle = nullptr;
HBoxContainer *scatter_controls_container = nullptr;
BoxContainer *scatter_controls_container = nullptr;
float scattering = 0.0;
Label *scatter_label = nullptr;
SpinBox *scatter_spinbox = nullptr;
@ -174,6 +191,8 @@ private:
void patterns_item_list_empty_clicked(const Vector2 &p_pos, MouseButton p_mouse_button_index);
///// Bottom panel common ////
BoxContainer *split_container_left_side = nullptr;
void _tab_changed();
///// Bottom panel tiles ////
@ -192,7 +211,7 @@ private:
// Atlas sources.
TileMapCell hovered_tile;
TileAtlasView *tile_atlas_view = nullptr;
HSplitContainer *atlas_sources_split_container = nullptr;
SplitContainer *atlas_sources_split_container = nullptr;
bool tile_set_dragging_selection = false;
Vector2i tile_set_drag_start_mouse_pos;
@ -241,6 +260,7 @@ public:
virtual Vector<TabData> get_tabs() const override;
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override;
virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override;
virtual void update_layout(EditorDock::DockLayout p_layout) override;
virtual void edit(ObjectID p_tile_map_layer_id) override;
@ -252,26 +272,27 @@ class TileMapLayerEditorTerrainsPlugin : public TileMapLayerSubEditorPlugin {
private:
// Toolbar.
HBoxContainer *toolbar = nullptr;
HBoxContainer *wide_toolbar = nullptr;
BoxContainer *tilemap_tiles_tools_buttons = nullptr;
Ref<ButtonGroup> tool_buttons_group;
Button *paint_tool_button = nullptr;
Button *line_tool_button = nullptr;
Button *rect_tool_button = nullptr;
Button *bucket_tool_button = nullptr;
HBoxContainer *tools_settings = nullptr;
BoxContainer *tools_settings = nullptr;
VSeparator *tools_settings_vsep = nullptr;
SwitchSeparator *tools_settings_vsep = nullptr;
Button *picker_button = nullptr;
Button *erase_button = nullptr;
VSeparator *tools_settings_vsep_2 = nullptr;
CheckBox *bucket_contiguous_checkbox = nullptr;
void _update_toolbar();
// Main vbox.
VBoxContainer *main_vbox_container = nullptr;
BoxContainer *main_box_container = nullptr;
SplitContainer *tilemap_tab_terrains = nullptr;
// TileMap editing.
bool has_mouse = false;
@ -332,6 +353,7 @@ public:
virtual Vector<TabData> get_tabs() const override;
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override;
virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override;
virtual void update_layout(EditorDock::DockLayout p_layout) override;
virtual void edit(ObjectID p_tile_map_layer_id) override;
@ -360,11 +382,15 @@ private:
Vector<TileMapLayerSubEditorPlugin *> tile_map_editor_plugins;
// Toolbar.
HFlowContainer *tile_map_toolbar = nullptr;
GridContainer *main_box_container = nullptr;
VBoxContainer *tile_map_wide_toolbar = nullptr;
FlowContainer *tile_map_toolbar = nullptr;
Control *padding_control = nullptr;
SwitchSeparator *layer_selector_separator = nullptr;
bool show_layers_selector = false;
HBoxContainer *layer_selection_hbox = nullptr;
BoxContainer *layer_selection_hbox = nullptr;
Button *select_previous_layer = nullptr;
void _select_previous_layer_pressed();
Button *select_next_layer = nullptr;
@ -414,6 +440,7 @@ private:
protected:
void _notification(int p_what);
void _draw_shape(Control *p_control, Rect2 p_region, TileSet::TileShape p_shape, TileSet::TileOffsetAxis p_offset_axis, Color p_color);
virtual void update_layout(DockLayout p_layout) override;
public:
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);

View file

@ -37,7 +37,6 @@
#include "editor/editor_interface.h"
#include "editor/editor_node.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_bottom_panel.h"
#include "editor/inspector/multi_node_edit.h"
#include "editor/scene/canvas_item_editor_plugin.h"
#include "editor/settings/editor_command_palette.h"
@ -483,6 +482,7 @@ void TileMapEditorPlugin::make_visible(bool p_visible) {
editor->open();
} else {
editor->close();
TileSetEditor::get_singleton()->close();
}
}