diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index ed1fa9b217..b5e2a8675f 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -31,6 +31,7 @@ #include "tile_map_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/math/math_funcs.h" #include "core/os/input.h" #include "core/os/keyboard.h" #include "editor/editor_scale.h" @@ -65,13 +66,11 @@ void TileMapEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { - transp->set_icon(get_icon("Transpose", "EditorIcons")); - mirror_x->set_icon(get_icon("MirrorX", "EditorIcons")); - mirror_y->set_icon(get_icon("MirrorY", "EditorIcons")); - rotate_0->set_icon(get_icon("Rotate0", "EditorIcons")); - rotate_90->set_icon(get_icon("Rotate90", "EditorIcons")); - rotate_180->set_icon(get_icon("Rotate180", "EditorIcons")); - rotate_270->set_icon(get_icon("Rotate270", "EditorIcons")); + rotate_left_button->set_icon(get_icon("Rotate270", "EditorIcons")); + rotate_right_button->set_icon(get_icon("Rotate90", "EditorIcons")); + flip_horizontal_button->set_icon(get_icon("MirrorX", "EditorIcons")); + flip_vertical_button->set_icon(get_icon("MirrorY", "EditorIcons")); + clear_transform_button->set_icon(get_icon("Clear", "EditorIcons")); search_box->set_right_icon(get_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); @@ -357,6 +356,10 @@ void TileMapEditor::_update_palette() { if (!node) return; + // Update the clear button + clear_transform_button->set_disabled(!flip_h && !flip_v && !transpose); + + // Update the palette Vector selected = get_selected_tiles(); palette->clear(); manual_palette->clear(); @@ -429,9 +432,6 @@ void TileMapEditor::_update_palette() { Ref tex = tileset->tile_get_texture(entries[i].id); if (tex.is_valid()) { - Color color = tileset->tile_get_modulate(entries[i].id); - palette->set_item_icon_modulate(palette->get_item_count() - 1, color); - Rect2 region = tileset->tile_get_region(entries[i].id); if (tileset->tile_get_tile_mode(entries[i].id) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(entries[i].id) == TileSet::ATLAS_TILE) { @@ -440,10 +440,25 @@ void TileMapEditor::_update_palette() { region.position += (region.size + Vector2(spacing, spacing)) * tileset->autotile_get_icon_coordinate(entries[i].id); } - if (!region.has_no_area()) + // Transpose and flip + palette->set_item_icon_transposed(palette->get_item_count() - 1, transpose); + if (flip_h) { + region.size.x = -region.size.x; + } + if (flip_v) { + region.size.y = -region.size.y; + } + + // Set region + if (region.size != Size2()) palette->set_item_icon_region(palette->get_item_count() - 1, region); + // Set icon palette->set_item_icon(palette->get_item_count() - 1, tex); + + // Modulation + Color color = tileset->tile_get_modulate(entries[i].id); + palette->set_item_icon_modulate(palette->get_item_count() - 1, color); } palette->set_item_metadata(palette->get_item_count() - 1, entries[i].id); @@ -519,11 +534,11 @@ void TileMapEditor::_pick_tile(const Point2 &p_pos) { selected.push_back(id); set_selected_tiles(selected); - mirror_x->set_pressed(node->is_cell_x_flipped(p_pos.x, p_pos.y)); - mirror_y->set_pressed(node->is_cell_y_flipped(p_pos.x, p_pos.y)); - transp->set_pressed(node->is_cell_transposed(p_pos.x, p_pos.y)); + flip_h = node->is_cell_x_flipped(p_pos.x, p_pos.y); + flip_v = node->is_cell_y_flipped(p_pos.x, p_pos.y); + transpose = node->is_cell_transposed(p_pos.x, p_pos.y); - _update_transform_buttons(); + _update_palette(); CanvasItemEditor::get_singleton()->update_viewport(); } @@ -1366,22 +1381,19 @@ bool TileMapEditor::forward_gui_input(const Ref &p_event) { } if (ED_IS_SHORTCUT("tile_map_editor/mirror_x", p_event)) { flip_h = !flip_h; - mirror_x->set_pressed(flip_h); - _update_transform_buttons(); + _update_palette(); CanvasItemEditor::get_singleton()->update_viewport(); return true; } if (ED_IS_SHORTCUT("tile_map_editor/mirror_y", p_event)) { flip_v = !flip_v; - mirror_y->set_pressed(flip_v); - _update_transform_buttons(); + _update_palette(); CanvasItemEditor::get_singleton()->update_viewport(); return true; } if (ED_IS_SHORTCUT("tile_map_editor/transpose", p_event)) { transpose = !transpose; - transp->set_pressed(transpose); - _update_transform_buttons(); + _update_palette(); CanvasItemEditor::get_singleton()->update_viewport(); return true; } @@ -1664,7 +1676,10 @@ void TileMapEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_canvas_mouse_enter"), &TileMapEditor::_canvas_mouse_enter); ClassDB::bind_method(D_METHOD("_canvas_mouse_exit"), &TileMapEditor::_canvas_mouse_exit); ClassDB::bind_method(D_METHOD("_tileset_settings_changed"), &TileMapEditor::_tileset_settings_changed); - ClassDB::bind_method(D_METHOD("_update_transform_buttons"), &TileMapEditor::_update_transform_buttons); + ClassDB::bind_method(D_METHOD("_rotate"), &TileMapEditor::_rotate); + ClassDB::bind_method(D_METHOD("_flip_horizontal"), &TileMapEditor::_flip_horizontal); + ClassDB::bind_method(D_METHOD("_flip_vertical"), &TileMapEditor::_flip_vertical); + ClassDB::bind_method(D_METHOD("_clear_transform"), &TileMapEditor::_clear_transform); ClassDB::bind_method(D_METHOD("_palette_selected"), &TileMapEditor::_palette_selected); ClassDB::bind_method(D_METHOD("_palette_multi_selected"), &TileMapEditor::_palette_multi_selected); @@ -1689,37 +1704,66 @@ TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i &p_pos) { return op; } -void TileMapEditor::_update_transform_buttons(Object *p_button) { - //ERR_FAIL_NULL(p_button); - ToolButton *b = Object::cast_to(p_button); - //ERR_FAIL_COND(!b); +void TileMapEditor::_rotate(int steps) { + const bool normal_rotation_matrix[][3] = { + { false, false, false }, + { true, true, false }, + { false, true, true }, + { true, false, true } + }; - if (b == rotate_0) { - mirror_x->set_pressed(false); - mirror_y->set_pressed(false); - transp->set_pressed(false); - } else if (b == rotate_90) { - mirror_x->set_pressed(true); - mirror_y->set_pressed(false); - transp->set_pressed(true); - } else if (b == rotate_180) { - mirror_x->set_pressed(true); - mirror_y->set_pressed(true); - transp->set_pressed(false); - } else if (b == rotate_270) { - mirror_x->set_pressed(false); - mirror_y->set_pressed(true); - transp->set_pressed(true); + const bool mirrored_rotation_matrix[][3] = { + { false, true, false }, + { true, true, true }, + { false, false, true }, + { true, false, false } + }; + + if (transpose ^ flip_h ^ flip_v) { + // Odd number of flags activated = mirrored rotation + for (int i = 0; i < 4; i++) { + if (transpose == mirrored_rotation_matrix[i][0] && + flip_h == mirrored_rotation_matrix[i][1] && + flip_v == mirrored_rotation_matrix[i][2]) { + int new_id = Math::wrapi(i + steps, 0, 4); + transpose = mirrored_rotation_matrix[new_id][0]; + flip_h = mirrored_rotation_matrix[new_id][1]; + flip_v = mirrored_rotation_matrix[new_id][2]; + } + } + } else { + // Even number of flags activated = normal rotation + for (int i = 0; i < 4; i++) { + if (transpose == normal_rotation_matrix[i][0] && + flip_h == normal_rotation_matrix[i][1] && + flip_v == normal_rotation_matrix[i][2]) { + int new_id = Math::wrapi(i + steps, 0, 4); + transpose = normal_rotation_matrix[new_id][0]; + flip_h = normal_rotation_matrix[new_id][1]; + flip_v = normal_rotation_matrix[new_id][2]; + break; + } + } } - flip_h = mirror_x->is_pressed(); - flip_v = mirror_y->is_pressed(); - transpose = transp->is_pressed(); + _update_palette(); +} - rotate_0->set_pressed(!flip_h && !flip_v && !transpose); - rotate_90->set_pressed(flip_h && !flip_v && transpose); - rotate_180->set_pressed(flip_h && flip_v && !transpose); - rotate_270->set_pressed(!flip_h && flip_v && transpose); +void TileMapEditor::_flip_horizontal() { + flip_h = !flip_h; + _update_palette(); +} + +void TileMapEditor::_flip_vertical() { + flip_v = !flip_v; + _update_palette(); +} + +void TileMapEditor::_clear_transform() { + transpose = false; + flip_h = false; + flip_v = false; + _update_palette(); } TileMapEditor::TileMapEditor(EditorNode *p_editor) { @@ -1752,10 +1796,8 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { ED_SHORTCUT("tile_map_editor/mirror_x", TTR("Mirror X"), KEY_A); ED_SHORTCUT("tile_map_editor/mirror_y", TTR("Mirror Y"), KEY_S); - HBoxContainer *tool_hb1 = memnew(HBoxContainer); - add_child(tool_hb1); - HBoxContainer *tool_hb2 = memnew(HBoxContainer); - add_child(tool_hb2); + HBoxContainer *tool_hb = memnew(HBoxContainer); + add_child(tool_hb); manual_button = memnew(CheckBox); manual_button->set_text("Disable Autotile"); @@ -1840,52 +1882,37 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { p->connect("id_pressed", this, "_menu_option"); toolbar->add_child(options); + rotate_left_button = memnew(ToolButton); + rotate_left_button->set_tooltip(TTR("Rotate left")); + rotate_left_button->set_focus_mode(FOCUS_NONE); + rotate_left_button->connect("pressed", this, "_rotate", varray(-1)); + tool_hb->add_child(rotate_left_button); - transp = memnew(ToolButton); - transp->set_toggle_mode(true); - transp->set_tooltip(TTR("Transpose") + " (" + ED_GET_SHORTCUT("tile_map_editor/transpose")->get_as_text() + ")"); - transp->set_focus_mode(FOCUS_NONE); - transp->connect("pressed", this, "_update_transform_buttons", make_binds(transp)); - tool_hb1->add_child(transp); - mirror_x = memnew(ToolButton); - mirror_x->set_toggle_mode(true); - mirror_x->set_tooltip(TTR("Mirror X") + " (" + ED_GET_SHORTCUT("tile_map_editor/mirror_x")->get_as_text() + ")"); - mirror_x->set_focus_mode(FOCUS_NONE); - mirror_x->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_x)); - tool_hb1->add_child(mirror_x); - mirror_y = memnew(ToolButton); - mirror_y->set_toggle_mode(true); - mirror_y->set_tooltip(TTR("Mirror Y") + " (" + ED_GET_SHORTCUT("tile_map_editor/mirror_y")->get_as_text() + ")"); - mirror_y->set_focus_mode(FOCUS_NONE); - mirror_y->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_y)); - tool_hb1->add_child(mirror_y); + rotate_right_button = memnew(ToolButton); + rotate_right_button->set_tooltip(TTR("Rotate right")); + rotate_right_button->set_focus_mode(FOCUS_NONE); + rotate_right_button->connect("pressed", this, "_rotate", varray(1)); + tool_hb->add_child(rotate_right_button); - rotate_0 = memnew(ToolButton); - rotate_0->set_toggle_mode(true); - rotate_0->set_tooltip(TTR("Rotate 0 degrees")); - rotate_0->set_focus_mode(FOCUS_NONE); - rotate_0->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_0)); - tool_hb2->add_child(rotate_0); - rotate_90 = memnew(ToolButton); - rotate_90->set_toggle_mode(true); - rotate_90->set_tooltip(TTR("Rotate 90 degrees")); - rotate_90->set_focus_mode(FOCUS_NONE); - rotate_90->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_90)); - tool_hb2->add_child(rotate_90); - rotate_180 = memnew(ToolButton); - rotate_180->set_toggle_mode(true); - rotate_180->set_tooltip(TTR("Rotate 180 degrees")); - rotate_180->set_focus_mode(FOCUS_NONE); - rotate_180->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_180)); - tool_hb2->add_child(rotate_180); - rotate_270 = memnew(ToolButton); - rotate_270->set_toggle_mode(true); - rotate_270->set_tooltip(TTR("Rotate 270 degrees")); - rotate_270->set_focus_mode(FOCUS_NONE); - rotate_270->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_270)); - tool_hb2->add_child(rotate_270); + flip_horizontal_button = memnew(ToolButton); + flip_horizontal_button->set_tooltip(TTR("Flip horizontally")); + flip_horizontal_button->set_focus_mode(FOCUS_NONE); + flip_horizontal_button->connect("pressed", this, "_flip_horizontal"); + tool_hb->add_child(flip_horizontal_button); - rotate_0->set_pressed(true); + flip_vertical_button = memnew(ToolButton); + flip_vertical_button->set_tooltip(TTR("Flip vertically")); + flip_vertical_button->set_focus_mode(FOCUS_NONE); + flip_vertical_button->connect("pressed", this, "_flip_vertical"); + tool_hb->add_child(flip_vertical_button); + + clear_transform_button = memnew(ToolButton); + clear_transform_button->set_tooltip(TTR("Clear transform")); + clear_transform_button->set_focus_mode(FOCUS_NONE); + clear_transform_button->connect("pressed", this, "_clear_transform"); + tool_hb->add_child(clear_transform_button); + + clear_transform_button->set_disabled(true); } TileMapEditor::~TileMapEditor() { diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index 3d44647a1b..68e5806ee5 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -93,13 +93,13 @@ class TileMapEditor : public VBoxContainer { Label *tile_info; MenuButton *options; - ToolButton *transp; - ToolButton *mirror_x; - ToolButton *mirror_y; - ToolButton *rotate_0; - ToolButton *rotate_90; - ToolButton *rotate_180; - ToolButton *rotate_270; + + ToolButton *flip_horizontal_button; + ToolButton *flip_vertical_button; + ToolButton *rotate_left_button; + ToolButton *rotate_right_button; + ToolButton *clear_transform_button; + CheckBox *manual_button; Tool tool; @@ -196,11 +196,15 @@ class TileMapEditor : public VBoxContainer { void _tileset_settings_changed(); void _icon_size_changed(float p_value); + void _clear_transform(); + void _flip_horizontal(); + void _flip_vertical(); + void _rotate(int steps); + protected: void _notification(int p_what); static void _bind_methods(); CellOp _get_op_from_cell(const Point2i &p_pos); - void _update_transform_buttons(Object *p_button = NULL); public: HBoxContainer *get_toolbar() const { return toolbar; } diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 494995fb85..cb37fa396d 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -36,6 +36,7 @@ void ItemList::add_item(const String &p_item, const Ref &p_texture, boo Item item; item.icon = p_texture; + item.icon_transposed = false; item.icon_region = Rect2i(); item.icon_modulate = Color(1, 1, 1, 1); item.text = p_item; @@ -54,6 +55,7 @@ void ItemList::add_icon_item(const Ref &p_item, bool p_selectable) { Item item; item.icon = p_item; + item.icon_transposed = false; item.icon_region = Rect2i(); item.icon_modulate = Color(1, 1, 1, 1); //item.text=p_item; @@ -124,6 +126,22 @@ Ref ItemList::get_item_icon(int p_idx) const { return items[p_idx].icon; } +void ItemList::set_item_icon_transposed(int p_idx, const bool p_transposed) { + + ERR_FAIL_INDEX(p_idx, items.size()); + + items.write[p_idx].icon_transposed = p_transposed; + update(); + shape_changed = true; +} + +bool ItemList::is_item_icon_transposed(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx, items.size(), false); + + return items[p_idx].icon_transposed; +} + void ItemList::set_item_icon_region(int p_idx, const Rect2 &p_region) { ERR_FAIL_INDEX(p_idx, items.size()); @@ -416,6 +434,7 @@ void ItemList::set_icon_mode(IconMode p_mode) { update(); shape_changed = true; } + ItemList::IconMode ItemList::get_icon_mode() const { return icon_mode; @@ -435,10 +454,15 @@ Size2 ItemList::Item::get_icon_size() const { if (icon.is_null()) return Size2(); - if (icon_region.has_no_area()) - return icon->get_size(); - return icon_region.size; + Size2 size_result = Size2(icon_region.size).abs(); + if (icon_transposed) { + Size2 size_tmp = size_result; + size_result.x = size_tmp.y; + size_result.y = size_tmp.x; + } + + return size_result; } void ItemList::_gui_input(const Ref &p_event) { @@ -1067,10 +1091,14 @@ void ItemList::_notification(int p_what) { if (items[i].disabled) modulate.a *= 0.5; - if (items[i].icon_region.has_no_area()) - draw_texture_rect(items[i].icon, draw_rect, false, modulate); - else - draw_texture_rect_region(items[i].icon, draw_rect, items[i].icon_region, modulate); + // If the icon is transposed, we have to swith the size so that it is drawn correctly + if (items[i].icon_transposed) { + Size2 size_tmp = draw_rect.size; + draw_rect.size.x = size_tmp.y; + draw_rect.size.y = size_tmp.x; + } + + draw_texture_rect_region(items[i].icon, draw_rect, items[i].icon_region, modulate, items[i].icon_transposed); } if (items[i].tag_icon.is_valid()) { @@ -1405,6 +1433,9 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon"), &ItemList::set_item_icon); ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &ItemList::get_item_icon); + ClassDB::bind_method(D_METHOD("set_item_icon_transposed", "idx", "rect"), &ItemList::set_item_icon_transposed); + ClassDB::bind_method(D_METHOD("is_item_icon_transposed", "idx"), &ItemList::is_item_icon_transposed); + ClassDB::bind_method(D_METHOD("set_item_icon_region", "idx", "rect"), &ItemList::set_item_icon_region); ClassDB::bind_method(D_METHOD("get_item_icon_region", "idx"), &ItemList::get_item_icon_region); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 58771c1777..acd17986eb 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -53,6 +53,7 @@ private: struct Item { Ref icon; + bool icon_transposed; Rect2i icon_region; Color icon_modulate; Ref tag_icon; @@ -133,6 +134,9 @@ public: void set_item_icon(int p_idx, const Ref &p_icon); Ref get_item_icon(int p_idx) const; + void set_item_icon_transposed(int p_idx, const bool transposed); + bool is_item_icon_transposed(int p_idx) const; + void set_item_icon_region(int p_idx, const Rect2 &p_region); Rect2 get_item_icon_region(int p_idx) const;