2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* tile_map_editor_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2019-01-01 12:53:14 +01:00
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
2014-02-10 02:10:30 +01:00
/* */
/* 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. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# include "tile_map_editor_plugin.h"
2016-03-11 20:30:08 +01:00
2014-02-10 02:10:30 +01:00
# include "canvas_item_editor_plugin.h"
2018-10-29 17:16:18 +01:00
# include "core/math/math_funcs.h"
2018-09-11 18:13:45 +02:00
# include "core/os/input.h"
# include "core/os/keyboard.h"
2017-03-05 14:21:25 +01:00
# include "editor/editor_scale.h"
2017-03-05 16:44:50 +01:00
# include "editor/editor_settings.h"
2018-06-01 23:12:25 +02:00
# include "scene/gui/split_container.h"
2014-02-10 02:10:30 +01:00
void TileMapEditor : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
switch ( p_what ) {
2014-02-10 02:10:30 +01:00
2017-09-24 15:35:55 +02:00
case NOTIFICATION_PROCESS : {
2018-10-18 14:06:57 +02:00
if ( bucket_queue . size ( ) ) {
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-09-24 15:35:55 +02:00
}
} break ;
2018-02-25 17:04:16 +01:00
case EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED : {
bool new_show_tile_info = EditorSettings : : get_singleton ( ) - > get ( " editors/tile_map/show_tile_info_on_hover " ) ;
if ( new_show_tile_info ! = show_tile_info ) {
show_tile_info = new_show_tile_info ;
tile_info - > set_visible ( show_tile_info ) ;
}
if ( is_visible_in_tree ( ) ) {
_update_palette ( ) ;
}
2019-06-29 05:09:59 +02:00
FALLTHROUGH ;
}
2018-02-25 17:04:16 +01:00
2016-03-11 20:30:08 +01:00
case NOTIFICATION_ENTER_TREE : {
2014-02-10 02:10:30 +01:00
2019-01-29 19:55:52 +01:00
paint_button - > set_icon ( get_icon ( " Edit " , " EditorIcons " ) ) ;
bucket_fill_button - > set_icon ( get_icon ( " Bucket " , " EditorIcons " ) ) ;
picker_button - > set_icon ( get_icon ( " ColorPick " , " EditorIcons " ) ) ;
select_button - > set_icon ( get_icon ( " ActionCopy " , " EditorIcons " ) ) ;
2018-10-29 17:16:18 +01:00
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 " ) ) ;
2014-02-10 02:10:30 +01:00
2018-08-11 12:04:19 +02:00
search_box - > set_right_icon ( get_icon ( " Search " , " EditorIcons " ) ) ;
2018-07-26 13:45:38 +02:00
search_box - > set_clear_button_enabled ( true ) ;
2017-08-10 21:48:48 +02:00
2018-02-24 14:39:19 +01:00
PopupMenu * p = options - > get_popup ( ) ;
2018-08-21 21:33:24 +02:00
p - > set_item_icon ( p - > get_item_index ( OPTION_CUT ) , get_icon ( " ActionCut " , " EditorIcons " ) ) ;
p - > set_item_icon ( p - > get_item_index ( OPTION_COPY ) , get_icon ( " Duplicate " , " EditorIcons " ) ) ;
2018-02-24 14:39:19 +01:00
p - > set_item_icon ( p - > get_item_index ( OPTION_ERASE_SELECTION ) , get_icon ( " Remove " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
}
2016-03-10 19:10:31 +01:00
}
2019-01-29 19:55:52 +01:00
void TileMapEditor : : _update_button_tool ( ) {
2016-03-10 19:10:31 +01:00
2019-01-29 19:55:52 +01:00
ToolButton * tb [ 4 ] = { paint_button , bucket_fill_button , picker_button , select_button } ;
// Unpress all buttons
for ( int i = 0 ; i < 4 ; i + + ) {
tb [ i ] - > set_pressed ( false ) ;
}
2017-09-12 20:22:04 +02:00
2019-01-29 19:55:52 +01:00
// Press the good button
switch ( tool ) {
case TOOL_NONE :
case TOOL_PAINTING : {
paint_button - > set_pressed ( true ) ;
2017-09-12 20:22:04 +02:00
} break ;
2019-01-29 19:55:52 +01:00
case TOOL_BUCKET : {
bucket_fill_button - > set_pressed ( true ) ;
2016-03-12 14:34:34 +01:00
} break ;
2019-01-29 19:55:52 +01:00
case TOOL_PICKING : {
picker_button - > set_pressed ( true ) ;
} break ;
case TOOL_SELECTING : {
select_button - > set_pressed ( true ) ;
} break ;
default :
break ;
}
2019-04-28 16:36:39 +02:00
if ( tool ! = TOOL_PICKING )
last_tool = tool ;
2019-01-29 19:55:52 +01:00
}
2016-03-10 19:10:31 +01:00
2019-01-29 19:55:52 +01:00
void TileMapEditor : : _button_tool_select ( int p_tool ) {
tool = ( Tool ) p_tool ;
_update_button_tool ( ) ;
switch ( tool ) {
case TOOL_SELECTING : {
2016-03-10 19:10:31 +01:00
2019-01-29 19:55:52 +01:00
selection_active = false ;
2016-03-10 19:10:31 +01:00
} break ;
2019-01-29 19:55:52 +01:00
default :
break ;
}
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
}
2016-03-10 19:10:31 +01:00
2019-01-29 19:55:52 +01:00
void TileMapEditor : : _menu_option ( int p_option ) {
2016-03-10 19:10:31 +01:00
2019-01-29 19:55:52 +01:00
switch ( p_option ) {
2018-08-21 21:33:24 +02:00
case OPTION_COPY : {
2016-03-10 19:10:31 +01:00
_update_copydata ( ) ;
if ( selection_active ) {
2018-08-21 21:33:24 +02:00
tool = TOOL_PASTING ;
2016-03-10 19:10:31 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2016-03-10 19:10:31 +01:00
}
2016-03-11 20:30:08 +01:00
} break ;
2016-03-10 19:10:31 +01:00
case OPTION_ERASE_SELECTION : {
if ( ! selection_active )
return ;
2018-05-25 18:59:05 +02:00
_start_undo ( TTR ( " Erase Selection " ) ) ;
2018-08-21 21:33:24 +02:00
_erase_selection ( ) ;
2018-05-25 18:59:05 +02:00
_finish_undo ( ) ;
2016-03-10 19:10:31 +01:00
2017-03-05 16:44:50 +01:00
selection_active = false ;
2016-03-10 19:10:31 +01:00
copydata . clear ( ) ;
2014-02-10 02:10:30 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2016-03-11 20:30:08 +01:00
} break ;
2018-02-24 06:56:48 +01:00
case OPTION_FIX_INVALID : {
undo_redo - > create_action ( TTR ( " Fix Invalid Tiles " ) ) ;
undo_redo - > add_undo_method ( node , " set " , " tile_data " , node - > get ( " tile_data " ) ) ;
node - > fix_invalid_tiles ( ) ;
undo_redo - > add_do_method ( node , " set " , " tile_data " , node - > get ( " tile_data " ) ) ;
undo_redo - > commit_action ( ) ;
} break ;
2018-08-21 21:33:24 +02:00
case OPTION_CUT : {
2018-03-30 15:47:46 +02:00
if ( selection_active ) {
_update_copydata ( ) ;
2018-08-21 21:33:24 +02:00
_start_undo ( TTR ( " Cut Selection " ) ) ;
_erase_selection ( ) ;
_finish_undo ( ) ;
selection_active = false ;
tool = TOOL_PASTING ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2018-03-30 15:47:46 +02:00
}
} break ;
2016-03-10 19:10:31 +01:00
}
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2014-02-10 02:10:30 +01:00
}
2018-06-01 23:12:25 +02:00
void TileMapEditor : : _palette_selected ( int index ) {
2018-07-29 23:54:12 +02:00
_update_palette ( ) ;
}
2018-06-01 23:12:25 +02:00
2018-07-29 23:54:12 +02:00
void TileMapEditor : : _palette_multi_selected ( int index , bool selected ) {
_update_palette ( ) ;
2018-06-01 23:12:25 +02:00
}
2017-03-05 16:44:50 +01:00
void TileMapEditor : : _canvas_mouse_enter ( ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
mouse_over = true ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void TileMapEditor : : _canvas_mouse_exit ( ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
mouse_over = false ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2014-02-10 02:10:30 +01:00
}
2018-03-17 13:12:26 +01:00
Vector < int > TileMapEditor : : get_selected_tiles ( ) const {
2016-03-10 19:10:31 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > items = palette - > get_selected_items ( ) ;
2016-03-10 19:10:31 +01:00
2018-03-17 13:12:26 +01:00
if ( items . size ( ) = = 0 ) {
items . push_back ( TileMap : : INVALID_CELL ) ;
return items ;
}
2016-03-10 19:10:31 +01:00
2018-03-17 13:12:26 +01:00
for ( int i = items . size ( ) - 1 ; i > = 0 ; i - - ) {
2018-07-25 03:11:03 +02:00
items . write [ i ] = palette - > get_item_metadata ( items [ i ] ) ;
2018-03-17 13:12:26 +01:00
}
return items ;
2014-02-10 02:10:30 +01:00
}
2018-03-17 13:12:26 +01:00
void TileMapEditor : : set_selected_tiles ( Vector < int > p_tiles ) {
2015-01-17 07:48:21 +01:00
2018-03-17 13:12:26 +01:00
palette - > unselect_all ( ) ;
2016-03-10 19:10:31 +01:00
2018-03-17 13:12:26 +01:00
for ( int i = p_tiles . size ( ) - 1 ; i > = 0 ; i - - ) {
int idx = palette - > find_metadata ( p_tiles [ i ] ) ;
if ( idx > = 0 ) {
palette - > select ( idx , false ) ;
}
2016-03-10 19:10:31 +01:00
}
2018-03-17 13:12:26 +01:00
palette - > ensure_current_is_visible ( ) ;
2015-02-11 12:40:50 +01:00
}
2015-06-22 15:05:03 +02:00
2019-04-08 23:38:31 +02:00
Dictionary TileMapEditor : : _create_cell_dictionary ( int tile , bool flip_x , bool flip_y , bool transpose , Vector2 autotile_coord ) {
2018-05-25 18:59:05 +02:00
2019-04-08 23:38:31 +02:00
Dictionary cell ;
2018-05-25 18:59:05 +02:00
2019-04-08 23:38:31 +02:00
cell [ " id " ] = tile ;
cell [ " flip_h " ] = flip_x ;
cell [ " flip_y " ] = flip_y ;
cell [ " transpose " ] = transpose ;
cell [ " auto_coord " ] = autotile_coord ;
2018-05-25 18:59:05 +02:00
2019-04-08 23:38:31 +02:00
return cell ;
}
void TileMapEditor : : _create_set_cell_undo_redo ( const Vector2 & p_vec , const CellOp & p_cell_old , const CellOp & p_cell_new ) {
Dictionary cell_old = _create_cell_dictionary ( p_cell_old . idx , p_cell_old . xf , p_cell_old . yf , p_cell_old . tr , p_cell_old . ac ) ;
Dictionary cell_new = _create_cell_dictionary ( p_cell_new . idx , p_cell_new . xf , p_cell_new . yf , p_cell_new . tr , p_cell_new . ac ) ;
2018-05-25 18:59:05 +02:00
2018-08-29 14:00:00 +02:00
undo_redo - > add_undo_method ( node , " _set_celld " , p_vec , cell_old ) ;
undo_redo - > add_do_method ( node , " _set_celld " , p_vec , cell_new ) ;
2018-05-25 18:59:05 +02:00
}
void TileMapEditor : : _start_undo ( const String & p_action ) {
undo_data . clear ( ) ;
undo_redo - > create_action ( p_action ) ;
}
void TileMapEditor : : _finish_undo ( ) {
if ( undo_data . size ( ) ) {
for ( Map < Point2i , CellOp > : : Element * E = undo_data . front ( ) ; E ; E = E - > next ( ) ) {
2019-04-08 23:38:31 +02:00
_create_set_cell_undo_redo ( E - > key ( ) , E - > get ( ) , _get_op_from_cell ( E - > key ( ) ) ) ;
2018-05-25 18:59:05 +02:00
}
undo_data . clear ( ) ;
}
undo_redo - > commit_action ( ) ;
}
2019-07-10 11:54:12 +02:00
void TileMapEditor : : _set_cell ( const Point2i & p_pos , Vector < int > p_values , bool p_flip_h , bool p_flip_v , bool p_transpose , const Point2i & p_autotile_coord ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! node ) ;
2018-03-17 13:12:26 +01:00
if ( p_values . size ( ) = = 0 )
return ;
int p_value = p_values [ Math : : rand ( ) % p_values . size ( ) ] ;
2017-03-05 16:44:50 +01:00
int prev_val = node - > get_cell ( p_pos . x , p_pos . y ) ;
2016-03-11 20:30:08 +01:00
2017-03-05 16:44:50 +01:00
bool prev_flip_h = node - > is_cell_x_flipped ( p_pos . x , p_pos . y ) ;
bool prev_flip_v = node - > is_cell_y_flipped ( p_pos . x , p_pos . y ) ;
bool prev_transpose = node - > is_cell_transposed ( p_pos . x , p_pos . y ) ;
2018-06-01 23:12:25 +02:00
Vector2 prev_position = node - > get_cell_autotile_coord ( p_pos . x , p_pos . y ) ;
2014-02-10 02:10:30 +01:00
2018-06-01 23:12:25 +02:00
Vector2 position ;
int current = manual_palette - > get_current ( ) ;
if ( current ! = - 1 ) {
2019-06-04 05:30:36 +02:00
if ( tool ! = TOOL_PASTING ) {
position = manual_palette - > get_item_metadata ( current ) ;
} else {
position = p_autotile_coord ;
}
2018-06-01 23:12:25 +02:00
} else {
2019-06-04 05:30:36 +02:00
// If there is no manual tile selected, that either means that
2018-06-01 23:12:25 +02:00
// autotiling is enabled, or the given tile is not autotiling. Either
// way, the coordinate of the tile does not matter, so assigning it to
// the coordinate of the existing tile works fine.
position = prev_position ;
}
if ( p_value = = prev_val & & p_flip_h = = prev_flip_h & & p_flip_v = = prev_flip_v & & p_transpose = = prev_transpose & & prev_position = = position )
2019-06-04 05:30:36 +02:00
return ; // Check that it's actually different.
2014-02-10 02:10:30 +01:00
2018-05-25 18:59:05 +02:00
for ( int y = p_pos . y - 1 ; y < = p_pos . y + 1 ; y + + ) {
for ( int x = p_pos . x - 1 ; x < = p_pos . x + 1 ; x + + ) {
Point2i p = Point2i ( x , y ) ;
if ( ! undo_data . has ( p ) ) {
undo_data [ p ] = _get_op_from_cell ( p ) ;
}
}
}
2019-04-08 23:38:31 +02:00
node - > _set_celld ( p_pos , _create_cell_dictionary ( p_value , p_flip_h , p_flip_v , p_transpose , p_autotile_coord ) ) ;
2019-03-28 21:37:01 +01:00
2019-06-04 05:30:36 +02:00
if ( tool = = TOOL_PASTING )
return ;
2018-11-10 18:52:52 +01:00
if ( manual_autotile | | ( p_value ! = - 1 & & node - > get_tileset ( ) - > tile_get_tile_mode ( p_value ) = = TileSet : : ATLAS_TILE ) ) {
2018-06-01 23:12:25 +02:00
if ( current ! = - 1 ) {
node - > set_cell_autotile_coord ( p_pos . x , p_pos . y , position ) ;
2019-06-04 05:30:36 +02:00
} else if ( node - > get_tileset ( ) - > tile_get_tile_mode ( p_value ) = = TileSet : : ATLAS_TILE & & priority_atlastile ) {
// BIND_CENTER is used to indicate that bitmask should not update for this tile cell.
2018-12-23 14:06:53 +01:00
node - > get_tileset ( ) - > autotile_set_bitmask ( p_value , Vector2 ( p_pos . x , p_pos . y ) , TileSet : : BIND_CENTER ) ;
node - > update_cell_bitmask ( p_pos . x , p_pos . y ) ;
2018-06-01 23:12:25 +02:00
}
} else {
2019-06-04 05:30:36 +02:00
node - > update_bitmask_area ( Point2 ( p_pos ) ) ;
2018-06-01 23:12:25 +02:00
}
}
void TileMapEditor : : _manual_toggled ( bool p_enabled ) {
manual_autotile = p_enabled ;
_update_palette ( ) ;
2014-02-10 02:10:30 +01:00
}
2018-12-23 14:06:53 +01:00
void TileMapEditor : : _priority_toggled ( bool p_enabled ) {
priority_atlastile = p_enabled ;
_update_palette ( ) ;
}
2017-03-05 16:44:50 +01:00
void TileMapEditor : : _text_entered ( const String & p_text ) {
2015-06-22 15:05:03 +02:00
2018-10-04 14:20:03 +02:00
canvas_item_editor_viewport - > grab_focus ( ) ;
2016-03-10 19:10:31 +01:00
}
2015-06-22 15:05:03 +02:00
2017-03-05 16:44:50 +01:00
void TileMapEditor : : _text_changed ( const String & p_text ) {
2015-06-22 15:05:03 +02:00
_update_palette ( ) ;
}
2017-05-20 17:38:03 +02:00
void TileMapEditor : : _sbox_input ( const Ref < InputEvent > & p_ie ) {
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEventKey > k = p_ie ;
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
if ( k . is_valid ( ) & & ( k - > get_scancode ( ) = = KEY_UP | |
k - > get_scancode ( ) = = KEY_DOWN | |
k - > get_scancode ( ) = = KEY_PAGEUP | |
k - > get_scancode ( ) = = KEY_PAGEDOWN ) ) {
palette - > call ( " _gui_input " , k ) ;
2016-03-10 19:10:31 +01:00
search_box - > accept_event ( ) ;
}
}
2017-03-27 02:50:51 +02:00
// Implementation detail of TileMapEditor::_update_palette();
// in modern C++ this could have been inside its body
namespace {
struct _PaletteEntry {
int id ;
String name ;
bool operator < ( const _PaletteEntry & p_rhs ) const {
return name < p_rhs . name ;
}
} ;
2017-10-15 22:33:25 +02:00
} // namespace
2017-03-27 02:50:51 +02:00
2014-02-10 02:10:30 +01:00
void TileMapEditor : : _update_palette ( ) {
if ( ! node )
return ;
2018-10-29 17:16:18 +01:00
// Update the clear button
clear_transform_button - > set_disabled ( ! flip_h & & ! flip_v & & ! transpose ) ;
// Update the palette
2018-03-17 13:12:26 +01:00
Vector < int > selected = get_selected_tiles ( ) ;
2019-06-04 01:01:27 +02:00
int selected_single = palette - > get_current ( ) ;
int selected_manual = manual_palette - > get_current ( ) ;
2015-06-22 15:05:03 +02:00
palette - > clear ( ) ;
2018-06-01 23:12:25 +02:00
manual_palette - > clear ( ) ;
manual_palette - > hide ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Ref < TileSet > tileset = node - > get_tileset ( ) ;
2016-03-10 19:10:31 +01:00
if ( tileset . is_null ( ) )
2014-02-10 02:10:30 +01:00
return ;
List < int > tiles ;
tileset - > get_tile_list ( & tiles ) ;
2016-03-10 19:10:31 +01:00
if ( tiles . empty ( ) )
return ;
2014-02-10 02:10:30 +01:00
2017-01-05 23:41:36 +01:00
float min_size = EDITOR_DEF ( " editors/tile_map/preview_size " , 64 ) ;
2016-08-15 21:48:04 +02:00
min_size * = EDSCALE ;
2017-03-05 16:44:50 +01:00
int hseparation = EDITOR_DEF ( " editors/tile_map/palette_item_hseparation " , 8 ) ;
2017-01-05 23:41:36 +01:00
bool show_tile_names = bool ( EDITOR_DEF ( " editors/tile_map/show_tile_names " , true ) ) ;
2017-03-27 02:50:51 +02:00
bool show_tile_ids = bool ( EDITOR_DEF ( " editors/tile_map/show_tile_ids " , false ) ) ;
bool sort_by_name = bool ( EDITOR_DEF ( " editors/tile_map/sort_tiles_by_name " , true ) ) ;
2016-05-27 21:42:51 +02:00
2017-03-05 16:44:50 +01:00
palette - > add_constant_override ( " hseparation " , hseparation * EDSCALE ) ;
palette - > add_constant_override ( " vseparation " , 8 * EDSCALE ) ;
2016-06-12 22:10:34 +02:00
palette - > set_fixed_icon_size ( Size2 ( min_size , min_size ) ) ;
2017-01-04 05:16:14 +01:00
palette - > set_fixed_column_width ( min_size * MAX ( size_slider - > get_value ( ) , 1 ) ) ;
2018-06-01 23:12:25 +02:00
palette - > set_same_column_width ( true ) ;
manual_palette - > set_fixed_icon_size ( Size2 ( min_size , min_size ) ) ;
manual_palette - > set_same_column_width ( true ) ;
2016-06-12 22:10:34 +02:00
2016-03-10 19:10:31 +01:00
String filter = search_box - > get_text ( ) . strip_edges ( ) ;
2017-03-27 02:50:51 +02:00
Vector < _PaletteEntry > entries ;
2017-03-05 16:44:50 +01:00
for ( List < int > : : Element * E = tiles . front ( ) ; E ; E = E - > next ( ) ) {
2016-03-10 19:10:31 +01:00
2017-03-27 02:50:51 +02:00
String name = tileset - > tile_get_name ( E - > get ( ) ) ;
2016-03-10 19:10:31 +01:00
2017-03-27 02:50:51 +02:00
if ( name ! = " " ) {
if ( show_tile_ids ) {
if ( sort_by_name ) {
name = name + " - " + itos ( E - > get ( ) ) ;
} else {
name = itos ( E - > get ( ) ) + " - " + name ;
}
}
2016-03-10 19:10:31 +01:00
} else {
2017-03-05 16:44:50 +01:00
name = " # " + itos ( E - > get ( ) ) ;
2016-03-10 19:10:31 +01:00
}
2016-08-15 21:48:04 +02:00
if ( filter ! = " " & & ! filter . is_subsequence_ofi ( name ) )
2016-03-10 19:10:31 +01:00
continue ;
2017-03-27 02:50:51 +02:00
const _PaletteEntry entry = { E - > get ( ) , name } ;
entries . push_back ( entry ) ;
}
if ( sort_by_name ) {
entries . sort ( ) ;
}
for ( int i = 0 ; i < entries . size ( ) ; i + + ) {
2016-08-15 21:48:04 +02:00
if ( show_tile_names ) {
2017-03-27 02:50:51 +02:00
palette - > add_item ( entries [ i ] . name ) ;
2016-08-15 21:48:04 +02:00
} else {
palette - > add_item ( String ( ) ) ;
}
2014-02-10 02:10:30 +01:00
2017-03-27 02:50:51 +02:00
Ref < Texture > tex = tileset - > tile_get_texture ( entries [ i ] . id ) ;
2015-06-22 15:05:03 +02:00
2014-02-10 02:10:30 +01:00
if ( tex . is_valid ( ) ) {
2017-03-27 02:50:51 +02:00
Rect2 region = tileset - > tile_get_region ( entries [ i ] . id ) ;
2014-02-10 02:10:30 +01:00
2018-07-29 23:54:12 +02:00
if ( tileset - > tile_get_tile_mode ( entries [ i ] . id ) = = TileSet : : AUTO_TILE | | tileset - > tile_get_tile_mode ( entries [ i ] . id ) = = TileSet : : ATLAS_TILE ) {
2017-10-22 03:42:23 +02:00
int spacing = tileset - > autotile_get_spacing ( entries [ i ] . id ) ;
region . size = tileset - > autotile_get_size ( entries [ i ] . id ) ;
region . position + = ( region . size + Vector2 ( spacing , spacing ) ) * tileset - > autotile_get_icon_coordinate ( entries [ i ] . id ) ;
}
2018-10-29 17:16:18 +01:00
// 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 ( ) )
2017-03-05 16:44:50 +01:00
palette - > set_item_icon_region ( palette - > get_item_count ( ) - 1 , region ) ;
2014-02-10 02:10:30 +01:00
2018-10-29 17:16:18 +01:00
// Set icon
2017-03-05 16:44:50 +01:00
palette - > set_item_icon ( palette - > get_item_count ( ) - 1 , tex ) ;
2018-10-29 17:16:18 +01:00
// Modulation
Color color = tileset - > tile_get_modulate ( entries [ i ] . id ) ;
palette - > set_item_icon_modulate ( palette - > get_item_count ( ) - 1 , color ) ;
2015-06-22 15:05:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-27 02:50:51 +02:00
palette - > set_item_metadata ( palette - > get_item_count ( ) - 1 , entries [ i ] . id ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
2018-03-17 13:12:26 +01:00
int sel_tile = selected . get ( 0 ) ;
if ( selected . get ( 0 ) ! = TileMap : : INVALID_CELL ) {
set_selected_tiles ( selected ) ;
sel_tile = selected . get ( Math : : rand ( ) % selected . size ( ) ) ;
2019-06-04 06:44:38 +02:00
} else if ( palette - > get_item_count ( ) > 0 ) {
2016-08-15 21:48:04 +02:00
palette - > select ( 0 ) ;
2018-03-17 13:12:26 +01:00
}
2018-06-01 23:12:25 +02:00
2018-08-26 22:10:01 +02:00
if ( sel_tile ! = TileMap : : INVALID_CELL ) {
2018-12-23 14:06:53 +01:00
if ( ( manual_autotile & & tileset - > tile_get_tile_mode ( sel_tile ) = = TileSet : : AUTO_TILE ) | |
( ! priority_atlastile & & tileset - > tile_get_tile_mode ( sel_tile ) = = TileSet : : ATLAS_TILE ) ) {
2018-06-01 23:12:25 +02:00
2019-03-31 19:28:42 +02:00
const Map < Vector2 , uint32_t > & tiles2 = tileset - > autotile_get_bitmask_map ( sel_tile ) ;
2018-06-01 23:12:25 +02:00
2019-02-12 21:10:08 +01:00
Vector < Vector2 > entries2 ;
2019-03-31 19:28:42 +02:00
for ( const Map < Vector2 , uint32_t > : : Element * E = tiles2 . front ( ) ; E ; E = E - > next ( ) ) {
2019-02-12 21:10:08 +01:00
entries2 . push_back ( E - > key ( ) ) ;
2018-08-26 22:10:01 +02:00
}
2019-08-03 21:32:13 +02:00
// Sort tiles in row-major order
struct SwapComparator {
_FORCE_INLINE_ bool operator ( ) ( const Vector2 & v_l , const Vector2 & v_r ) const {
return v_l . y ! = v_r . y ? v_l . y < v_r . y : v_l . x < v_r . x ;
}
} ;
entries2 . sort_custom < SwapComparator > ( ) ;
2018-06-01 23:12:25 +02:00
2018-08-26 22:10:01 +02:00
Ref < Texture > tex = tileset - > tile_get_texture ( sel_tile ) ;
2018-06-01 23:12:25 +02:00
2019-02-12 21:10:08 +01:00
for ( int i = 0 ; i < entries2 . size ( ) ; i + + ) {
2018-06-01 23:12:25 +02:00
2018-08-26 22:10:01 +02:00
manual_palette - > add_item ( String ( ) ) ;
2018-06-01 23:12:25 +02:00
2018-08-26 22:10:01 +02:00
if ( tex . is_valid ( ) ) {
2018-06-01 23:12:25 +02:00
2018-08-26 22:10:01 +02:00
Rect2 region = tileset - > tile_get_region ( sel_tile ) ;
int spacing = tileset - > autotile_get_spacing ( sel_tile ) ;
region . size = tileset - > autotile_get_size ( sel_tile ) ; // !!
2019-02-12 21:10:08 +01:00
region . position + = ( region . size + Vector2 ( spacing , spacing ) ) * entries2 [ i ] ;
2018-06-01 23:12:25 +02:00
2018-08-26 22:10:01 +02:00
if ( ! region . has_no_area ( ) )
manual_palette - > set_item_icon_region ( manual_palette - > get_item_count ( ) - 1 , region ) ;
2018-06-01 23:12:25 +02:00
2018-08-26 22:10:01 +02:00
manual_palette - > set_item_icon ( manual_palette - > get_item_count ( ) - 1 , tex ) ;
}
2018-06-01 23:12:25 +02:00
2019-02-12 21:10:08 +01:00
manual_palette - > set_item_metadata ( manual_palette - > get_item_count ( ) - 1 , entries2 [ i ] ) ;
2018-08-26 22:10:01 +02:00
}
2018-06-01 23:12:25 +02:00
}
}
if ( manual_palette - > get_item_count ( ) > 0 ) {
// Only show the manual palette if at least tile exists in it
2019-06-04 01:01:27 +02:00
if ( selected_manual = = - 1 | | selected_single ! = palette - > get_current ( ) )
selected_manual = 0 ;
if ( selected_manual < manual_palette - > get_item_count ( ) )
manual_palette - > set_current ( selected_manual ) ;
2018-06-01 23:12:25 +02:00
manual_palette - > show ( ) ;
}
2018-12-20 18:17:52 +01:00
2018-12-19 17:20:49 +01:00
if ( sel_tile ! = TileMap : : INVALID_CELL & & tileset - > tile_get_tile_mode ( sel_tile ) = = TileSet : : AUTO_TILE ) {
2018-12-20 18:17:52 +01:00
manual_button - > show ( ) ;
2018-12-23 14:06:53 +01:00
priority_button - > hide ( ) ;
2018-12-20 18:17:52 +01:00
} else {
manual_button - > hide ( ) ;
2018-12-23 14:06:53 +01:00
priority_button - > show ( ) ;
2018-12-20 18:17:52 +01:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void TileMapEditor : : _pick_tile ( const Point2 & p_pos ) {
2014-02-10 02:10:30 +01:00
2016-03-10 19:10:31 +01:00
int id = node - > get_cell ( p_pos . x , p_pos . y ) ;
2017-03-05 16:44:50 +01:00
if ( id = = TileMap : : INVALID_CELL )
2016-03-10 19:10:31 +01:00
return ;
2019-06-04 16:27:00 +02:00
if ( search_box - > get_text ( ) ! = " " ) {
2016-03-10 19:10:31 +01:00
search_box - > set_text ( " " ) ;
_update_palette ( ) ;
2014-02-10 02:10:30 +01:00
}
2018-10-29 17:16:18 +01:00
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 ) ;
2018-12-19 00:09:37 +01:00
autotile_coord = node - > get_cell_autotile_coord ( p_pos . x , p_pos . y ) ;
2016-03-10 19:10:31 +01:00
2019-06-04 16:27:00 +02:00
Vector < int > selected ;
selected . push_back ( id ) ;
set_selected_tiles ( selected ) ;
2018-10-29 17:16:18 +01:00
_update_palette ( ) ;
2019-06-04 16:27:00 +02:00
if ( ( manual_autotile & & node - > get_tileset ( ) - > tile_get_tile_mode ( id ) = = TileSet : : AUTO_TILE ) | | ( ! priority_atlastile & & node - > get_tileset ( ) - > tile_get_tile_mode ( id ) = = TileSet : : ATLAS_TILE ) ) {
manual_palette - > select ( manual_palette - > find_metadata ( ( Point2 ) autotile_coord ) ) ;
}
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
PoolVector < Vector2 > TileMapEditor : : _bucket_fill ( const Point2i & p_start , bool erase , bool preview ) {
2016-03-12 14:34:34 +01:00
2016-09-02 13:17:50 +02:00
int prev_id = node - > get_cell ( p_start . x , p_start . y ) ;
2018-03-17 13:12:26 +01:00
Vector < int > ids ;
ids . push_back ( TileMap : : INVALID_CELL ) ;
2016-09-02 13:17:50 +02:00
if ( ! erase ) {
2018-03-17 13:12:26 +01:00
ids = get_selected_tiles ( ) ;
2016-03-12 14:34:34 +01:00
2018-07-24 17:42:24 +02:00
if ( ids . size ( ) = = 0 | | ids [ 0 ] = = TileMap : : INVALID_CELL )
2017-01-07 22:25:37 +01:00
return PoolVector < Vector2 > ( ) ;
2017-08-03 20:44:15 +02:00
} else if ( prev_id = = TileMap : : INVALID_CELL ) {
return PoolVector < Vector2 > ( ) ;
2016-09-02 13:17:50 +02:00
}
2016-03-12 14:34:34 +01:00
2018-08-07 12:28:58 +02:00
if ( ids . size ( ) = = 1 & & ids [ 0 ] = = prev_id ) {
// Same ID, nothing to change
return PoolVector < Vector2 > ( ) ;
2017-09-24 04:30:00 +02:00
}
2018-07-24 18:11:38 +02:00
Rect2i r = node - > get_used_rect ( ) ;
2016-03-12 14:34:34 +01:00
2016-12-31 17:42:05 +01:00
int area = r . get_area ( ) ;
2017-03-05 16:44:50 +01:00
if ( preview ) {
2016-12-31 17:42:05 +01:00
// Test if we can re-use the result from preview bucket fill
bool invalidate_cache = false ;
// Area changed
2017-03-05 16:44:50 +01:00
if ( r ! = bucket_cache_rect )
2016-12-31 17:42:05 +01:00
_clear_bucket_cache ( ) ;
// Cache grid is not initialized
2017-03-05 16:44:50 +01:00
if ( bucket_cache_visited = = 0 ) {
2016-12-31 17:42:05 +01:00
bucket_cache_visited = new bool [ area ] ;
invalidate_cache = true ;
}
// Tile ID changed or position wasn't visited by the previous fill
2017-06-04 00:25:13 +02:00
int loc = ( p_start . x - r . position . x ) + ( p_start . y - r . position . y ) * r . get_size ( ) . x ;
2017-03-05 16:44:50 +01:00
if ( prev_id ! = bucket_cache_tile | | ! bucket_cache_visited [ loc ] ) {
2016-12-31 17:42:05 +01:00
invalidate_cache = true ;
}
2017-03-05 16:44:50 +01:00
if ( invalidate_cache ) {
for ( int i = 0 ; i < area ; + + i )
2016-12-31 17:42:05 +01:00
bucket_cache_visited [ i ] = false ;
2017-01-07 22:25:37 +01:00
bucket_cache = PoolVector < Vector2 > ( ) ;
2016-12-31 17:42:05 +01:00
bucket_cache_tile = prev_id ;
bucket_cache_rect = r ;
2017-09-24 15:35:55 +02:00
bucket_queue . clear ( ) ;
2016-12-31 17:42:05 +01:00
}
}
2017-01-07 22:25:37 +01:00
PoolVector < Vector2 > points ;
2017-12-01 01:50:09 +01:00
Vector < Vector2 > non_preview_cache ;
2017-09-24 15:35:55 +02:00
int count = 0 ;
int limit = 0 ;
2016-03-12 14:34:34 +01:00
2017-09-24 15:35:55 +02:00
if ( preview ) {
limit = 1024 ;
} else {
bucket_queue . clear ( ) ;
}
2016-03-12 14:34:34 +01:00
2017-09-24 15:35:55 +02:00
bucket_queue . push_back ( p_start ) ;
2016-03-12 14:34:34 +01:00
2017-09-24 15:35:55 +02:00
while ( bucket_queue . size ( ) ) {
Point2i n = bucket_queue . front ( ) - > get ( ) ;
bucket_queue . pop_front ( ) ;
2016-03-12 14:34:34 +01:00
2016-03-12 21:21:01 +01:00
if ( ! r . has_point ( n ) )
2016-03-12 14:34:34 +01:00
continue ;
2016-09-02 13:17:50 +02:00
if ( node - > get_cell ( n . x , n . y ) = = prev_id ) {
2016-03-12 14:34:34 +01:00
2017-03-05 16:44:50 +01:00
if ( preview ) {
2017-06-04 00:25:13 +02:00
int loc = ( n . x - r . position . x ) + ( n . y - r . position . y ) * r . get_size ( ) . x ;
2017-03-05 16:44:50 +01:00
if ( bucket_cache_visited [ loc ] )
2016-12-31 17:42:05 +01:00
continue ;
bucket_cache_visited [ loc ] = true ;
bucket_cache . push_back ( n ) ;
2017-03-05 16:44:50 +01:00
} else {
2017-12-01 01:50:09 +01:00
if ( non_preview_cache . find ( n ) > = 0 )
continue ;
2016-12-31 17:42:05 +01:00
points . push_back ( n ) ;
2017-12-01 01:50:09 +01:00
non_preview_cache . push_back ( n ) ;
2016-12-31 17:42:05 +01:00
}
2016-03-12 14:34:34 +01:00
2017-09-24 15:35:55 +02:00
bucket_queue . push_back ( Point2i ( n . x , n . y + 1 ) ) ;
bucket_queue . push_back ( Point2i ( n . x , n . y - 1 ) ) ;
bucket_queue . push_back ( Point2i ( n . x + 1 , n . y ) ) ;
bucket_queue . push_back ( Point2i ( n . x - 1 , n . y ) ) ;
count + + ;
}
if ( limit > 0 & & count > = limit ) {
break ;
2016-03-12 14:34:34 +01:00
}
}
2016-12-31 17:42:05 +01:00
return preview ? bucket_cache : points ;
2016-03-12 14:34:34 +01:00
}
2019-07-10 11:54:12 +02:00
void TileMapEditor : : _fill_points ( const PoolVector < Vector2 > & p_points , const Dictionary & p_op ) {
2016-03-12 14:34:34 +01:00
int len = p_points . size ( ) ;
2017-01-07 22:25:37 +01:00
PoolVector < Vector2 > : : Read pr = p_points . read ( ) ;
2016-03-12 14:34:34 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > ids = p_op [ " id " ] ;
2016-03-12 14:34:34 +01:00
bool xf = p_op [ " flip_h " ] ;
bool yf = p_op [ " flip_v " ] ;
bool tr = p_op [ " transpose " ] ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < len ; i + + ) {
2018-03-17 13:12:26 +01:00
_set_cell ( pr [ i ] , ids , xf , yf , tr ) ;
2017-12-01 01:50:09 +01:00
node - > make_bitmask_area_dirty ( pr [ i ] ) ;
2016-03-12 14:34:34 +01:00
}
2018-12-23 14:06:53 +01:00
if ( ! manual_autotile )
node - > update_dirty_bitmask ( ) ;
2016-03-12 14:34:34 +01:00
}
2019-07-10 11:54:12 +02:00
void TileMapEditor : : _erase_points ( const PoolVector < Vector2 > & p_points ) {
2016-03-12 14:34:34 +01:00
int len = p_points . size ( ) ;
2017-01-07 22:25:37 +01:00
PoolVector < Vector2 > : : Read pr = p_points . read ( ) ;
2016-03-12 14:34:34 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < len ; i + + ) {
2016-03-12 14:34:34 +01:00
2018-03-17 13:12:26 +01:00
_set_cell ( pr [ i ] , invalid_cell ) ;
2016-03-12 14:34:34 +01:00
}
}
2017-03-05 16:44:50 +01:00
void TileMapEditor : : _select ( const Point2i & p_from , const Point2i & p_to ) {
2016-03-10 19:10:31 +01:00
2017-03-05 16:44:50 +01:00
Point2i begin = p_from ;
Point2i end = p_to ;
2014-02-10 02:10:30 +01:00
2016-03-10 19:10:31 +01:00
if ( begin . x > end . x ) {
2017-03-05 16:44:50 +01:00
SWAP ( begin . x , end . x ) ;
2016-03-10 19:10:31 +01:00
}
if ( begin . y > end . y ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
SWAP ( begin . y , end . y ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-10 19:10:31 +01:00
2017-06-04 00:25:13 +02:00
rectangle . position = begin ;
2017-03-05 16:44:50 +01:00
rectangle . size = end - begin ;
2016-03-10 19:10:31 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2014-02-10 02:10:30 +01:00
}
2018-08-21 21:33:24 +02:00
void TileMapEditor : : _erase_selection ( ) {
if ( ! selection_active )
return ;
for ( int i = rectangle . position . y ; i < = rectangle . position . y + rectangle . size . y ; i + + ) {
for ( int j = rectangle . position . x ; j < = rectangle . position . x + rectangle . size . x ; j + + ) {
_set_cell ( Point2i ( j , i ) , invalid_cell , false , false , false ) ;
}
}
}
2019-07-10 11:54:12 +02:00
void TileMapEditor : : _draw_cell ( Control * p_viewport , int p_cell , const Point2i & p_point , bool p_flip_h , bool p_flip_v , bool p_transpose , const Point2i & p_autotile_coord , const Transform2D & p_xform ) {
2014-02-10 02:10:30 +01:00
2016-03-10 19:10:31 +01:00
Ref < Texture > t = node - > get_tileset ( ) - > tile_get_texture ( p_cell ) ;
if ( t . is_null ( ) )
return ;
Vector2 tile_ofs = node - > get_tileset ( ) - > tile_get_texture_offset ( p_cell ) ;
Rect2 r = node - > get_tileset ( ) - > tile_get_region ( p_cell ) ;
2018-07-29 23:54:12 +02:00
if ( node - > get_tileset ( ) - > tile_get_tile_mode ( p_cell ) = = TileSet : : AUTO_TILE | | node - > get_tileset ( ) - > tile_get_tile_mode ( p_cell ) = = TileSet : : ATLAS_TILE ) {
2018-06-01 23:12:25 +02:00
Vector2 offset ;
2019-06-04 05:30:36 +02:00
if ( tool ! = TOOL_PASTING ) {
int selected = manual_palette - > get_current ( ) ;
if ( ( manual_autotile | | ( node - > get_tileset ( ) - > tile_get_tile_mode ( p_cell ) = = TileSet : : ATLAS_TILE & & ! priority_atlastile ) ) & & selected ! = - 1 ) {
offset = manual_palette - > get_item_metadata ( selected ) ;
2018-12-19 00:09:37 +01:00
} else {
2019-06-04 05:30:36 +02:00
offset = node - > get_tileset ( ) - > autotile_get_icon_coordinate ( p_cell ) ;
2018-12-19 00:09:37 +01:00
}
2019-06-04 05:30:36 +02:00
} else {
offset = p_autotile_coord ;
2018-06-01 23:12:25 +02:00
}
2017-10-22 03:42:23 +02:00
int spacing = node - > get_tileset ( ) - > autotile_get_spacing ( p_cell ) ;
r . size = node - > get_tileset ( ) - > autotile_get_size ( p_cell ) ;
2018-06-01 23:12:25 +02:00
r . position + = ( r . size + Vector2 ( spacing , spacing ) ) * offset ;
2017-10-22 03:42:23 +02:00
}
2016-03-10 19:10:31 +01:00
Size2 sc = p_xform . get_scale ( ) ;
2019-07-01 22:43:52 +02:00
Size2 cell_size = node - > get_cell_size ( ) ;
bool centered_texture = node - > is_centered_textures_enabled ( ) ;
bool compatibility_mode_enabled = node - > is_compatibility_mode_enabled ( ) ;
2016-03-11 20:30:08 +01:00
Rect2 rect = Rect2 ( ) ;
2017-06-04 00:25:13 +02:00
rect . position = node - > map_to_world ( p_point ) + node - > get_cell_draw_offset ( ) ;
2016-03-10 19:10:31 +01:00
2016-03-11 20:30:08 +01:00
if ( r . has_no_area ( ) ) {
rect . size = t - > get_size ( ) ;
2016-03-10 19:10:31 +01:00
} else {
2016-03-11 20:30:08 +01:00
rect . size = r . size ;
2016-03-10 19:10:31 +01:00
}
2019-07-01 22:43:52 +02:00
if ( compatibility_mode_enabled & & ! centered_texture ) {
if ( rect . size . y > rect . size . x ) {
if ( ( p_flip_h & & ( p_flip_v | | p_transpose ) ) | | ( p_flip_v & & ! p_transpose ) )
tile_ofs . y + = rect . size . y - rect . size . x ;
} else if ( rect . size . y < rect . size . x ) {
if ( ( p_flip_v & & ( p_flip_h | | p_transpose ) ) | | ( p_flip_h & & ! p_transpose ) )
tile_ofs . x + = rect . size . x - rect . size . y ;
}
}
2016-03-10 19:10:31 +01:00
if ( p_transpose ) {
SWAP ( tile_ofs . x , tile_ofs . y ) ;
2019-07-01 22:43:52 +02:00
if ( centered_texture ) {
rect . position . x + = cell_size . x / 2 - rect . size . y / 2 ;
rect . position . y + = cell_size . y / 2 - rect . size . x / 2 ;
}
} else if ( centered_texture ) {
rect . position + = cell_size / 2 - rect . size / 2 ;
2016-03-10 19:10:31 +01:00
}
2019-05-15 04:14:27 +02:00
2016-03-10 19:10:31 +01:00
if ( p_flip_h ) {
2017-03-05 16:44:50 +01:00
sc . x * = - 1.0 ;
tile_ofs . x * = - 1.0 ;
2016-03-10 19:10:31 +01:00
}
2019-05-15 04:14:27 +02:00
2016-03-10 19:10:31 +01:00
if ( p_flip_v ) {
2017-03-05 16:44:50 +01:00
sc . y * = - 1.0 ;
tile_ofs . y * = - 1.0 ;
2016-03-10 19:10:31 +01:00
}
2019-07-01 22:43:52 +02:00
if ( compatibility_mode_enabled & & ! centered_texture ) {
if ( node - > get_tile_origin ( ) = = TileMap : : TILE_ORIGIN_TOP_LEFT ) {
rect . position + = tile_ofs ;
} else if ( node - > get_tile_origin ( ) = = TileMap : : TILE_ORIGIN_BOTTOM_LEFT ) {
rect . position + = tile_ofs ;
if ( p_transpose ) {
if ( p_flip_h )
rect . position . x - = cell_size . x ;
else
rect . position . x + = cell_size . x ;
} else {
if ( p_flip_v )
rect . position . y - = cell_size . y ;
else
rect . position . y + = cell_size . y ;
}
} else if ( node - > get_tile_origin ( ) = = TileMap : : TILE_ORIGIN_CENTER ) {
rect . position + = tile_ofs ;
if ( p_flip_h )
rect . position . x - = cell_size . x / 2 ;
else
rect . position . x + = cell_size . x / 2 ;
if ( p_flip_v )
rect . position . y - = cell_size . y / 2 ;
else
rect . position . y + = cell_size . y / 2 ;
}
} else {
rect . position + = tile_ofs ;
}
2017-06-04 00:25:13 +02:00
rect . position = p_xform . xform ( rect . position ) ;
2017-03-05 16:44:50 +01:00
rect . size * = sc ;
2016-03-10 19:10:31 +01:00
2018-01-20 05:56:30 +01:00
Color modulate = node - > get_tileset ( ) - > tile_get_modulate ( p_cell ) ;
modulate . a = 0.5 ;
2019-06-04 05:30:36 +02:00
if ( r . has_no_area ( ) ) {
2018-09-18 20:00:07 +02:00
p_viewport - > draw_texture_rect ( t , rect , false , modulate , p_transpose ) ;
2019-06-04 05:30:36 +02:00
} else {
2018-09-18 20:00:07 +02:00
p_viewport - > draw_texture_rect_region ( t , rect , r , modulate , p_transpose ) ;
2019-06-04 05:30:36 +02:00
}
2016-03-10 19:10:31 +01:00
}
2019-07-10 11:54:12 +02:00
void TileMapEditor : : _draw_fill_preview ( Control * p_viewport , int p_cell , const Point2i & p_point , bool p_flip_h , bool p_flip_v , bool p_transpose , const Point2i & p_autotile_coord , const Transform2D & p_xform ) {
2016-12-31 17:42:05 +01:00
2017-01-07 22:25:37 +01:00
PoolVector < Vector2 > points = _bucket_fill ( p_point , false , true ) ;
PoolVector < Vector2 > : : Read pr = points . read ( ) ;
2016-12-31 17:42:05 +01:00
int len = points . size ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < len ; + + i ) {
2018-12-19 00:09:37 +01:00
_draw_cell ( p_viewport , p_cell , pr [ i ] , p_flip_h , p_flip_v , p_transpose , p_autotile_coord , p_xform ) ;
2016-12-31 17:42:05 +01:00
}
}
void TileMapEditor : : _clear_bucket_cache ( ) {
2017-03-05 16:44:50 +01:00
if ( bucket_cache_visited ) {
2016-12-31 17:42:05 +01:00
delete [ ] bucket_cache_visited ;
bucket_cache_visited = 0 ;
}
}
2016-03-10 19:10:31 +01:00
void TileMapEditor : : _update_copydata ( ) {
copydata . clear ( ) ;
if ( ! selection_active )
return ;
2017-06-04 00:25:13 +02:00
for ( int i = rectangle . position . y ; i < = rectangle . position . y + rectangle . size . y ; i + + ) {
2016-03-10 19:10:31 +01:00
2017-06-04 00:25:13 +02:00
for ( int j = rectangle . position . x ; j < = rectangle . position . x + rectangle . size . x ; j + + ) {
2016-03-10 19:10:31 +01:00
TileData tcd ;
2017-03-05 16:44:50 +01:00
tcd . cell = node - > get_cell ( j , i ) ;
if ( tcd . cell ! = TileMap : : INVALID_CELL ) {
tcd . pos = Point2i ( j , i ) ;
tcd . flip_h = node - > is_cell_x_flipped ( j , i ) ;
tcd . flip_v = node - > is_cell_y_flipped ( j , i ) ;
tcd . transpose = node - > is_cell_transposed ( j , i ) ;
2018-12-19 00:09:37 +01:00
tcd . autotile_coord = node - > get_cell_autotile_coord ( j , i ) ;
2016-03-10 19:10:31 +01:00
}
copydata . push_back ( tcd ) ;
}
}
}
2016-03-11 18:06:54 +01:00
static inline Vector < Point2i > line ( int x0 , int x1 , int y0 , int y1 ) {
Vector < Point2i > points ;
float dx = ABS ( x1 - x0 ) ;
float dy = ABS ( y1 - y0 ) ;
int x = x0 ;
int y = y0 ;
int sx = x0 > x1 ? - 1 : 1 ;
int sy = y0 > y1 ? - 1 : 1 ;
if ( dx > dy ) {
2017-03-05 16:44:50 +01:00
float err = dx / 2 ;
2016-03-11 18:06:54 +01:00
2016-03-11 20:30:08 +01:00
for ( ; x ! = x1 ; x + = sx ) {
2016-03-11 18:06:54 +01:00
points . push_back ( Vector2 ( x , y ) ) ;
err - = dy ;
if ( err < 0 ) {
y + = sy ;
err + = dx ;
}
}
} else {
2017-03-05 16:44:50 +01:00
float err = dy / 2 ;
2016-03-11 18:06:54 +01:00
2016-03-11 20:30:08 +01:00
for ( ; y ! = y1 ; y + = sy ) {
2016-03-11 18:06:54 +01:00
points . push_back ( Vector2 ( x , y ) ) ;
err - = dx ;
if ( err < 0 ) {
x + = sx ;
err + = dy ;
}
}
}
points . push_back ( Vector2 ( x , y ) ) ;
return points ;
}
2017-05-20 17:38:03 +02:00
bool TileMapEditor : : forward_gui_input ( const Ref < InputEvent > & p_event ) {
2015-12-29 01:23:32 +01:00
2019-08-21 15:34:06 +02:00
if ( ! node | | ! node - > get_tileset ( ) . is_valid ( ) | | ! node - > is_visible_in_tree ( ) | | CanvasItemEditor : : get_singleton ( ) - > get_current_tool ( ) ! = CanvasItemEditor : : TOOL_SELECT )
2014-02-10 02:10:30 +01:00
return false ;
2018-10-04 14:20:03 +02:00
Transform2D xform = CanvasItemEditor : : get_singleton ( ) - > get_canvas_transform ( ) * node - > get_global_transform ( ) ;
2017-01-11 04:52:51 +01:00
Transform2D xform_inv = xform . affine_inverse ( ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > mb = p_event ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( mb . is_valid ( ) ) {
if ( mb - > get_button_index ( ) = = BUTTON_LEFT ) {
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( mb - > is_pressed ( ) ) {
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( KEY_SPACE ) )
return false ; //drag
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_NONE ) {
2016-03-11 18:06:54 +01:00
2017-05-20 17:38:03 +02:00
if ( mb - > get_shift ( ) ) {
2016-03-12 21:21:01 +01:00
2018-04-23 15:55:36 +02:00
if ( mb - > get_command ( ) )
2017-05-20 17:38:03 +02:00
tool = TOOL_RECTANGLE_PAINT ;
else
tool = TOOL_LINE_PAINT ;
2016-03-11 18:06:54 +01:00
2017-05-20 17:38:03 +02:00
selection_active = false ;
rectangle_begin = over_tile ;
2016-03-12 21:21:01 +01:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
}
2019-04-28 16:36:39 +02:00
2018-04-23 15:55:36 +02:00
if ( mb - > get_command ( ) ) {
2017-05-20 17:38:03 +02:00
tool = TOOL_PICKING ;
_pick_tile ( over_tile ) ;
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
return true ;
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
tool = TOOL_PAINTING ;
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-05-20 17:38:03 +02:00
}
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_PAINTING ) {
2016-03-10 19:10:31 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > ids = get_selected_tiles ( ) ;
2016-03-10 19:10:31 +01:00
2018-03-17 13:12:26 +01:00
if ( ids . size ( ) > 0 & & ids [ 0 ] ! = TileMap : : INVALID_CELL ) {
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
tool = TOOL_PAINTING ;
2014-02-10 02:10:30 +01:00
2018-05-25 18:59:05 +02:00
_start_undo ( TTR ( " Paint TileMap " ) ) ;
2016-03-10 19:10:31 +01:00
}
2017-05-20 17:38:03 +02:00
} else if ( tool = = TOOL_PICKING ) {
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
_pick_tile ( over_tile ) ;
} else if ( tool = = TOOL_SELECTING ) {
2016-03-12 14:34:34 +01:00
2017-05-20 17:38:03 +02:00
selection_active = true ;
rectangle_begin = over_tile ;
}
2014-02-10 02:10:30 +01:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
} else {
2019-06-04 16:27:00 +02:00
// Mousebutton was released.
2017-05-20 17:38:03 +02:00
if ( tool ! = TOOL_NONE ) {
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_PAINTING ) {
2016-03-11 20:30:08 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > ids = get_selected_tiles ( ) ;
2014-02-10 02:10:30 +01:00
2018-03-17 13:12:26 +01:00
if ( ids . size ( ) > 0 & & ids [ 0 ] ! = TileMap : : INVALID_CELL ) {
2016-03-11 18:06:54 +01:00
2018-03-17 13:12:26 +01:00
_set_cell ( over_tile , ids , flip_h , flip_v , transpose ) ;
2018-05-25 18:59:05 +02:00
_finish_undo ( ) ;
2016-03-11 18:06:54 +01:00
2017-05-20 17:38:03 +02:00
paint_undo . clear ( ) ;
}
} else if ( tool = = TOOL_LINE_PAINT ) {
2016-03-11 18:06:54 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > ids = get_selected_tiles ( ) ;
2016-03-11 18:06:54 +01:00
2018-03-17 13:12:26 +01:00
if ( ids . size ( ) > 0 & & ids [ 0 ] ! = TileMap : : INVALID_CELL ) {
2016-03-11 18:06:54 +01:00
2018-05-25 18:59:05 +02:00
_start_undo ( TTR ( " Line Draw " ) ) ;
2017-05-20 17:38:03 +02:00
for ( Map < Point2i , CellOp > : : Element * E = paint_undo . front ( ) ; E ; E = E - > next ( ) ) {
2016-03-12 21:21:01 +01:00
2018-03-17 13:12:26 +01:00
_set_cell ( E - > key ( ) , ids , flip_h , flip_v , transpose ) ;
2016-03-11 18:06:54 +01:00
}
2018-05-25 18:59:05 +02:00
_finish_undo ( ) ;
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
paint_undo . clear ( ) ;
2016-03-10 19:10:31 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-05-20 17:38:03 +02:00
}
} else if ( tool = = TOOL_RECTANGLE_PAINT ) {
2016-03-10 19:10:31 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > ids = get_selected_tiles ( ) ;
2016-03-12 14:34:34 +01:00
2018-03-17 13:12:26 +01:00
if ( ids . size ( ) > 0 & & ids [ 0 ] ! = TileMap : : INVALID_CELL ) {
2016-03-12 14:34:34 +01:00
2018-05-25 18:59:05 +02:00
_start_undo ( TTR ( " Rectangle Paint " ) ) ;
2017-06-04 00:25:13 +02:00
for ( int i = rectangle . position . y ; i < = rectangle . position . y + rectangle . size . y ; i + + ) {
for ( int j = rectangle . position . x ; j < = rectangle . position . x + rectangle . size . x ; j + + ) {
2016-03-12 14:34:34 +01:00
2018-03-17 13:12:26 +01:00
_set_cell ( Point2i ( j , i ) , ids , flip_h , flip_v , transpose ) ;
2017-05-20 17:38:03 +02:00
}
2016-03-12 14:34:34 +01:00
}
2018-05-25 18:59:05 +02:00
_finish_undo ( ) ;
2016-03-12 14:34:34 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-05-20 17:38:03 +02:00
}
2018-08-21 21:33:24 +02:00
} else if ( tool = = TOOL_PASTING ) {
2016-03-12 14:34:34 +01:00
2017-06-04 00:25:13 +02:00
Point2 ofs = over_tile - rectangle . position ;
2018-03-17 13:12:26 +01:00
Vector < int > ids ;
2016-03-10 19:10:31 +01:00
2018-08-21 21:33:24 +02:00
_start_undo ( TTR ( " Paste " ) ) ;
2018-03-17 13:12:26 +01:00
ids . push_back ( 0 ) ;
2017-05-20 17:38:03 +02:00
for ( List < TileData > : : Element * E = copydata . front ( ) ; E ; E = E - > next ( ) ) {
2018-07-25 03:11:03 +02:00
ids . write [ 0 ] = E - > get ( ) . cell ;
2018-12-19 00:09:37 +01:00
_set_cell ( E - > get ( ) . pos + ofs , ids , E - > get ( ) . flip_h , E - > get ( ) . flip_v , E - > get ( ) . transpose , E - > get ( ) . autotile_coord ) ;
2017-05-20 17:38:03 +02:00
}
2018-05-25 18:59:05 +02:00
_finish_undo ( ) ;
2016-03-12 14:34:34 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2016-09-02 13:17:50 +02:00
2019-06-04 16:27:00 +02:00
return true ; // We want to keep the Pasting tool.
2017-05-20 17:38:03 +02:00
} else if ( tool = = TOOL_SELECTING ) {
2016-03-12 14:34:34 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2016-03-12 14:34:34 +01:00
2017-05-20 17:38:03 +02:00
} else if ( tool = = TOOL_BUCKET ) {
2016-03-12 14:34:34 +01:00
2017-05-20 17:38:03 +02:00
PoolVector < Vector2 > points = _bucket_fill ( over_tile ) ;
2016-03-12 14:34:34 +01:00
2017-05-20 17:38:03 +02:00
if ( points . size ( ) = = 0 )
return false ;
2016-03-10 19:10:31 +01:00
2018-07-24 18:11:38 +02:00
_start_undo ( TTR ( " Bucket Fill " ) ) ;
2017-12-01 01:50:09 +01:00
2017-05-20 17:38:03 +02:00
Dictionary op ;
2018-03-17 13:12:26 +01:00
op [ " id " ] = get_selected_tiles ( ) ;
2017-05-20 17:38:03 +02:00
op [ " flip_h " ] = flip_h ;
op [ " flip_v " ] = flip_v ;
op [ " transpose " ] = transpose ;
2016-03-10 19:10:31 +01:00
2017-12-01 01:50:09 +01:00
_fill_points ( points , op ) ;
2017-05-20 17:38:03 +02:00
2018-07-24 18:11:38 +02:00
_finish_undo ( ) ;
2017-09-12 20:22:04 +02:00
2019-06-04 16:27:00 +02:00
// So the fill preview is cleared right after the click.
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
// We want to keep the bucket-tool active.
2017-09-12 20:22:04 +02:00
return true ;
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
tool = TOOL_NONE ;
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
return true ;
}
}
} else if ( mb - > get_button_index ( ) = = BUTTON_RIGHT ) {
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( mb - > is_pressed ( ) ) {
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_SELECTING | | selection_active ) {
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
tool = TOOL_NONE ;
selection_active = false ;
2016-03-10 19:10:31 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2016-03-10 19:10:31 +01:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
}
2016-03-10 19:10:31 +01:00
2018-08-21 21:33:24 +02:00
if ( tool = = TOOL_PASTING ) {
2018-03-30 15:47:46 +02:00
tool = TOOL_NONE ;
copydata . clear ( ) ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2018-03-30 15:47:46 +02:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2018-03-30 15:47:46 +02:00
return true ;
}
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_NONE ) {
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
paint_undo . clear ( ) ;
2016-03-11 18:06:54 +01:00
2017-06-03 10:54:24 +02:00
Point2 local = node - > world_to_map ( xform_inv . xform ( mb - > get_position ( ) ) ) ;
2016-03-11 18:06:54 +01:00
2018-05-25 18:59:05 +02:00
_start_undo ( TTR ( " Erase TileMap " ) ) ;
2017-12-01 01:50:09 +01:00
2017-05-20 17:38:03 +02:00
if ( mb - > get_shift ( ) ) {
2018-04-23 15:55:36 +02:00
if ( mb - > get_command ( ) )
2017-05-20 17:38:03 +02:00
tool = TOOL_RECTANGLE_ERASE ;
else
tool = TOOL_LINE_ERASE ;
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
selection_active = false ;
rectangle_begin = local ;
} else {
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
tool = TOOL_ERASING ;
2018-03-17 13:12:26 +01:00
_set_cell ( local , invalid_cell ) ;
2016-03-10 19:10:31 +01:00
}
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
} else {
if ( tool = = TOOL_ERASING | | tool = = TOOL_RECTANGLE_ERASE | | tool = = TOOL_LINE_ERASE ) {
2014-04-19 21:46:52 +02:00
2018-05-25 18:59:05 +02:00
_finish_undo ( ) ;
2016-03-11 20:30:08 +01:00
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_RECTANGLE_ERASE | | tool = = TOOL_LINE_ERASE ) {
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-05-20 17:38:03 +02:00
}
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
tool = TOOL_NONE ;
2016-09-02 13:17:50 +02:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
2016-09-02 13:17:50 +02:00
2017-05-20 17:38:03 +02:00
} else if ( tool = = TOOL_BUCKET ) {
2016-09-02 13:17:50 +02:00
2018-03-17 13:12:26 +01:00
Vector < int > ids ;
ids . push_back ( node - > get_cell ( over_tile . x , over_tile . y ) ) ;
2017-05-20 17:38:03 +02:00
Dictionary pop ;
2018-03-17 13:12:26 +01:00
pop [ " id " ] = ids ;
2017-05-20 17:38:03 +02:00
pop [ " flip_h " ] = node - > is_cell_x_flipped ( over_tile . x , over_tile . y ) ;
pop [ " flip_v " ] = node - > is_cell_y_flipped ( over_tile . x , over_tile . y ) ;
pop [ " transpose " ] = node - > is_cell_transposed ( over_tile . x , over_tile . y ) ;
2016-09-02 13:17:50 +02:00
2017-05-20 17:38:03 +02:00
PoolVector < Vector2 > points = _bucket_fill ( over_tile , true ) ;
2016-09-02 13:17:50 +02:00
2017-05-20 17:38:03 +02:00
if ( points . size ( ) = = 0 )
return false ;
2016-09-02 13:17:50 +02:00
2019-02-21 20:41:01 +01:00
undo_redo - > create_action ( TTR ( " Bucket Fill " ) ) ;
2016-09-02 13:17:50 +02:00
2017-05-20 17:38:03 +02:00
undo_redo - > add_do_method ( this , " _erase_points " , points ) ;
undo_redo - > add_undo_method ( this , " _fill_points " , points , pop ) ;
undo_redo - > commit_action ( ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-05-20 17:38:03 +02:00
}
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseMotion > mm = p_event ;
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
if ( mm . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
2017-06-03 10:54:24 +02:00
Point2i new_over_tile = node - > world_to_map ( xform_inv . xform ( mm - > get_position ( ) ) ) ;
2017-10-23 00:48:03 +02:00
Point2i old_over_tile = over_tile ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( new_over_tile ! = over_tile ) {
2016-06-17 02:10:44 +02:00
2017-05-20 17:38:03 +02:00
over_tile = new_over_tile ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-05-20 17:38:03 +02:00
}
2016-06-17 02:10:44 +02:00
2017-08-16 19:51:55 +02:00
if ( show_tile_info ) {
int tile_under = node - > get_cell ( over_tile . x , over_tile . y ) ;
String tile_name = " none " ;
2014-02-10 02:10:30 +01:00
2017-08-16 19:51:55 +02:00
if ( node - > get_tileset ( ) - > has_tile ( tile_under ) )
tile_name = node - > get_tileset ( ) - > tile_get_name ( tile_under ) ;
tile_info - > set_text ( String : : num ( over_tile . x ) + " , " + String : : num ( over_tile . y ) + " [ " + tile_name + " ] " ) ;
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_PAINTING ) {
2016-03-12 21:21:01 +01:00
2019-06-04 16:27:00 +02:00
// Paint using bresenham line to prevent holes in painting if the user moves fast.
2017-10-23 00:48:03 +02:00
Vector < Point2i > points = line ( old_over_tile . x , over_tile . x , old_over_tile . y , over_tile . y ) ;
2018-03-17 13:12:26 +01:00
Vector < int > ids = get_selected_tiles ( ) ;
2017-10-23 00:48:03 +02:00
for ( int i = 0 ; i < points . size ( ) ; + + i ) {
Point2i pos = points [ i ] ;
2014-02-10 02:10:30 +01:00
2017-11-08 22:26:19 +01:00
if ( ! paint_undo . has ( pos ) ) {
2017-10-23 00:48:03 +02:00
paint_undo [ pos ] = _get_op_from_cell ( pos ) ;
2014-02-10 02:10:30 +01:00
}
2018-03-17 13:12:26 +01:00
_set_cell ( pos , ids , flip_h , flip_v , transpose ) ;
2017-10-23 00:48:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-23 00:48:03 +02:00
return true ;
}
if ( tool = = TOOL_ERASING ) {
2019-06-04 16:27:00 +02:00
// Erase using bresenham line to prevent holes in painting if the user moves fast.
2017-10-23 00:48:03 +02:00
Vector < Point2i > points = line ( old_over_tile . x , over_tile . x , old_over_tile . y , over_tile . y ) ;
for ( int i = 0 ; i < points . size ( ) ; + + i ) {
Point2i pos = points [ i ] ;
2018-03-17 13:12:26 +01:00
_set_cell ( pos , invalid_cell ) ;
2016-03-10 19:10:31 +01:00
}
2017-10-23 00:48:03 +02:00
return true ;
2017-05-20 17:38:03 +02:00
}
2016-03-12 21:21:01 +01:00
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_SELECTING ) {
2016-03-11 18:06:54 +01:00
2017-05-20 17:38:03 +02:00
_select ( rectangle_begin , over_tile ) ;
2016-03-11 18:06:54 +01:00
2017-05-20 17:38:03 +02:00
return true ;
}
2016-03-11 18:06:54 +01:00
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_LINE_PAINT | | tool = = TOOL_LINE_ERASE ) {
2016-03-11 18:06:54 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > ids = get_selected_tiles ( ) ;
Vector < int > tmp_cell ;
2017-05-20 17:38:03 +02:00
bool erasing = ( tool = = TOOL_LINE_ERASE ) ;
2016-03-11 18:06:54 +01:00
2018-03-17 13:12:26 +01:00
tmp_cell . push_back ( 0 ) ;
2017-05-20 17:38:03 +02:00
if ( erasing & & paint_undo . size ( ) ) {
2016-03-11 20:30:08 +01:00
2017-05-20 17:38:03 +02:00
for ( Map < Point2i , CellOp > : : Element * E = paint_undo . front ( ) ; E ; E = E - > next ( ) ) {
2016-03-11 18:06:54 +01:00
2018-07-25 03:11:03 +02:00
tmp_cell . write [ 0 ] = E - > get ( ) . idx ;
2018-03-17 13:12:26 +01:00
_set_cell ( E - > key ( ) , tmp_cell , E - > get ( ) . xf , E - > get ( ) . yf , E - > get ( ) . tr ) ;
2017-05-20 17:38:03 +02:00
}
}
2016-03-11 20:30:08 +01:00
2017-05-20 17:38:03 +02:00
paint_undo . clear ( ) ;
2016-03-11 18:06:54 +01:00
2018-03-17 13:12:26 +01:00
if ( ids . size ( ) > 0 & & ids [ 0 ] ! = TileMap : : INVALID_CELL ) {
2016-03-11 18:06:54 +01:00
2017-05-20 17:38:03 +02:00
Vector < Point2i > points = line ( rectangle_begin . x , over_tile . x , rectangle_begin . y , over_tile . y ) ;
2016-03-11 18:06:54 +01:00
2017-05-20 17:38:03 +02:00
for ( int i = 0 ; i < points . size ( ) ; i + + ) {
paint_undo [ points [ i ] ] = _get_op_from_cell ( points [ i ] ) ;
if ( erasing )
2018-03-17 13:12:26 +01:00
_set_cell ( points [ i ] , invalid_cell ) ;
2016-03-11 18:06:54 +01:00
}
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2016-03-11 18:06:54 +01:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
return true ;
}
if ( tool = = TOOL_RECTANGLE_PAINT | | tool = = TOOL_RECTANGLE_ERASE ) {
2014-02-10 02:10:30 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > tmp_cell ;
tmp_cell . push_back ( 0 ) ;
2017-05-20 17:38:03 +02:00
_select ( rectangle_begin , over_tile ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( tool = = TOOL_RECTANGLE_ERASE ) {
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( paint_undo . size ( ) ) {
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
for ( Map < Point2i , CellOp > : : Element * E = paint_undo . front ( ) ; E ; E = E - > next ( ) ) {
2018-07-25 03:11:03 +02:00
tmp_cell . write [ 0 ] = E - > get ( ) . idx ;
2018-03-17 13:12:26 +01:00
_set_cell ( E - > key ( ) , tmp_cell , E - > get ( ) . xf , E - > get ( ) . yf , E - > get ( ) . tr ) ;
2016-03-10 19:10:31 +01:00
}
2017-05-20 17:38:03 +02:00
}
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
paint_undo . clear ( ) ;
2016-03-11 20:30:08 +01:00
2017-06-04 00:25:13 +02:00
for ( int i = rectangle . position . y ; i < = rectangle . position . y + rectangle . size . y ; i + + ) {
for ( int j = rectangle . position . x ; j < = rectangle . position . x + rectangle . size . x ; j + + ) {
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
Point2i tile = Point2i ( j , i ) ;
paint_undo [ tile ] = _get_op_from_cell ( tile ) ;
2016-03-10 19:10:31 +01:00
2018-03-17 13:12:26 +01:00
_set_cell ( tile , invalid_cell ) ;
2016-03-10 19:10:31 +01:00
}
}
}
2017-05-20 17:38:03 +02:00
return true ;
}
if ( tool = = TOOL_PICKING & & Input : : get_singleton ( ) - > is_mouse_button_pressed ( BUTTON_LEFT ) ) {
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
_pick_tile ( over_tile ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
return true ;
}
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEventKey > k = p_event ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( k . is_valid ( ) & & k - > is_pressed ( ) ) {
2014-02-10 02:10:30 +01:00
2019-04-28 16:36:39 +02:00
if ( last_tool = = TOOL_NONE & & tool = = TOOL_PICKING & & k - > get_scancode ( ) = = KEY_SHIFT & & k - > get_command ( ) ) {
// trying to draw a rectangle with the painting tool, so change to the correct tool
tool = last_tool ;
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
_update_button_tool ( ) ;
}
2017-05-20 17:38:03 +02:00
if ( k - > get_scancode ( ) = = KEY_ESCAPE ) {
2014-02-10 02:10:30 +01:00
2018-08-21 21:33:24 +02:00
if ( tool = = TOOL_PASTING )
2017-05-20 17:38:03 +02:00
copydata . clear ( ) ;
else if ( tool = = TOOL_SELECTING | | selection_active )
selection_active = false ;
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
tool = TOOL_NONE ;
2014-02-10 02:10:30 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2014-02-10 02:10:30 +01:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
}
2014-02-10 02:10:30 +01:00
2017-09-12 20:22:04 +02:00
if ( ! mouse_over ) {
2019-06-04 16:27:00 +02:00
// Editor shortcuts should not fire if mouse not in viewport.
2017-05-20 17:38:03 +02:00
return false ;
2017-09-12 20:22:04 +02:00
}
2014-02-10 02:10:30 +01:00
2017-09-12 20:22:04 +02:00
if ( ED_IS_SHORTCUT ( " tile_map_editor/paint_tile " , p_event ) ) {
// NOTE: We do not set tool = TOOL_PAINTING as this begins painting
2019-06-04 16:27:00 +02:00
// immediately without pressing the left mouse button first.
2017-09-12 20:22:04 +02:00
tool = TOOL_NONE ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-09-12 20:22:04 +02:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-09-12 20:22:04 +02:00
return true ;
}
if ( ED_IS_SHORTCUT ( " tile_map_editor/bucket_fill " , p_event ) ) {
tool = TOOL_BUCKET ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-09-12 20:22:04 +02:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-09-12 20:22:04 +02:00
return true ;
}
2017-05-20 17:38:03 +02:00
if ( ED_IS_SHORTCUT ( " tile_map_editor/erase_selection " , p_event ) ) {
_menu_option ( OPTION_ERASE_SELECTION ) ;
2014-02-10 02:10:30 +01:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
}
if ( ED_IS_SHORTCUT ( " tile_map_editor/select " , p_event ) ) {
tool = TOOL_SELECTING ;
selection_active = false ;
2014-02-10 02:10:30 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2014-02-10 02:10:30 +01:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
}
2018-08-21 21:33:24 +02:00
if ( ED_IS_SHORTCUT ( " tile_map_editor/copy_selection " , p_event ) ) {
2017-05-20 17:38:03 +02:00
_update_copydata ( ) ;
2016-03-10 19:10:31 +01:00
2017-05-20 17:38:03 +02:00
if ( selection_active ) {
2018-08-21 21:33:24 +02:00
tool = TOOL_PASTING ;
2016-03-11 20:30:08 +01:00
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-05-20 17:38:03 +02:00
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2016-06-13 00:19:18 +02:00
return true ;
2016-03-10 19:10:31 +01:00
}
2017-05-20 17:38:03 +02:00
}
2018-08-21 21:33:24 +02:00
if ( ED_IS_SHORTCUT ( " tile_map_editor/cut_selection " , p_event ) ) {
2018-03-30 15:47:46 +02:00
if ( selection_active ) {
_update_copydata ( ) ;
2018-08-21 21:33:24 +02:00
_start_undo ( TTR ( " Cut Selection " ) ) ;
_erase_selection ( ) ;
_finish_undo ( ) ;
selection_active = false ;
tool = TOOL_PASTING ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2019-01-29 19:55:52 +01:00
_update_button_tool ( ) ;
2018-03-30 15:47:46 +02:00
return true ;
}
}
2017-05-20 17:38:03 +02:00
if ( ED_IS_SHORTCUT ( " tile_map_editor/find_tile " , p_event ) ) {
search_box - > select_all ( ) ;
search_box - > grab_focus ( ) ;
return true ;
}
2019-07-14 15:32:17 +02:00
if ( ED_IS_SHORTCUT ( " tile_map_editor/rotate_left " , p_event ) ) {
_rotate ( - 1 ) ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
}
2019-07-14 15:32:17 +02:00
if ( ED_IS_SHORTCUT ( " tile_map_editor/rotate_right " , p_event ) ) {
_rotate ( 1 ) ;
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
return true ;
}
if ( ED_IS_SHORTCUT ( " tile_map_editor/flip_horizontal " , p_event ) ) {
_flip_horizontal ( ) ;
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
return true ;
}
if ( ED_IS_SHORTCUT ( " tile_map_editor/flip_vertical " , p_event ) ) {
_flip_vertical ( ) ;
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
return true ;
}
if ( ED_IS_SHORTCUT ( " tile_map_editor/clear_transform " , p_event ) ) {
_clear_transform ( ) ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
}
if ( ED_IS_SHORTCUT ( " tile_map_editor/transpose " , p_event ) ) {
transpose = ! transpose ;
2018-10-29 17:16:18 +01:00
_update_palette ( ) ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2017-05-20 17:38:03 +02:00
return true ;
}
2019-06-04 16:27:00 +02:00
} else if ( k . is_valid ( ) ) { // Release event.
2019-04-28 16:36:39 +02:00
if ( tool = = TOOL_NONE ) {
if ( k - > get_scancode ( ) = = KEY_SHIFT & & k - > get_command ( ) ) {
tool = TOOL_PICKING ;
_update_button_tool ( ) ;
}
} else if ( tool = = TOOL_PICKING ) {
2014-02-10 02:10:30 +01:00
2019-04-28 16:36:39 +02:00
# ifdef APPLE_STYLE_KEYS
if ( k - > get_scancode ( ) = = KEY_META ) {
# else
if ( k - > get_scancode ( ) = = KEY_CONTROL ) {
# endif
2019-06-04 16:27:00 +02:00
// Go back to that last tool if KEY_CONTROL was released.
2019-04-28 16:36:39 +02:00
tool = last_tool ;
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
_update_button_tool ( ) ;
}
}
}
2014-02-10 02:10:30 +01:00
return false ;
}
2016-03-11 18:06:54 +01:00
2018-09-18 20:00:07 +02:00
void TileMapEditor : : forward_canvas_draw_over_viewport ( Control * p_overlay ) {
2014-02-10 02:10:30 +01:00
2019-08-21 15:34:06 +02:00
if ( ! node | | CanvasItemEditor : : get_singleton ( ) - > get_current_tool ( ) ! = CanvasItemEditor : : TOOL_SELECT )
2014-02-10 02:10:30 +01:00
return ;
2017-01-11 04:52:51 +01:00
Transform2D cell_xf = node - > get_cell_transform ( ) ;
2018-09-29 15:52:35 +02:00
Transform2D xform = CanvasItemEditor : : get_singleton ( ) - > get_canvas_transform ( ) * node - > get_global_transform ( ) ;
2017-01-11 04:52:51 +01:00
Transform2D xform_inv = xform . affine_inverse ( ) ;
2014-02-10 02:10:30 +01:00
2018-09-18 20:00:07 +02:00
Size2 screen_size = p_overlay - > get_size ( ) ;
2014-10-03 05:10:51 +02:00
{
Rect2 aabb ;
2017-06-04 00:25:13 +02:00
aabb . position = node - > world_to_map ( xform_inv . xform ( Vector2 ( ) ) ) ;
2017-03-05 16:44:50 +01:00
aabb . expand_to ( node - > world_to_map ( xform_inv . xform ( Vector2 ( 0 , screen_size . height ) ) ) ) ;
aabb . expand_to ( node - > world_to_map ( xform_inv . xform ( Vector2 ( screen_size . width , 0 ) ) ) ) ;
2014-10-03 05:10:51 +02:00
aabb . expand_to ( node - > world_to_map ( xform_inv . xform ( screen_size ) ) ) ;
2017-03-05 16:44:50 +01:00
Rect2i si = aabb . grow ( 1.0 ) ;
2014-02-10 02:10:30 +01:00
2019-03-24 00:59:24 +01:00
if ( node - > get_half_offset ( ) ! = TileMap : : HALF_OFFSET_X & & node - > get_half_offset ( ) ! = TileMap : : HALF_OFFSET_NEGATIVE_X ) {
2014-02-10 02:10:30 +01:00
2019-03-24 00:59:24 +01:00
int max_lines = 2000 ; //avoid crash if size too small
2016-01-24 21:22:17 +01:00
2017-06-04 00:25:13 +02:00
for ( int i = ( si . position . x ) - 1 ; i < = ( si . position . x + si . size . x ) ; i + + ) {
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
Vector2 from = xform . xform ( node - > map_to_world ( Vector2 ( i , si . position . y ) ) ) ;
Vector2 to = xform . xform ( node - > map_to_world ( Vector2 ( i , si . position . y + si . size . y + 1 ) ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Color col = i = = 0 ? Color ( 1 , 0.8 , 0.2 , 0.5 ) : Color ( 1 , 0.3 , 0.1 , 0.2 ) ;
2018-09-18 20:00:07 +02:00
p_overlay - > draw_line ( from , to , col , 1 ) ;
2017-03-05 16:44:50 +01:00
if ( max_lines - - = = 0 )
2016-01-24 21:22:17 +01:00
break ;
2014-10-03 05:10:51 +02:00
}
} else {
2014-02-10 02:10:30 +01:00
2019-03-24 00:59:24 +01:00
int max_lines = 10000 ; //avoid crash if size too small
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
for ( int i = ( si . position . x ) - 1 ; i < = ( si . position . x + si . size . x ) ; i + + ) {
2014-10-03 05:10:51 +02:00
2017-06-04 00:25:13 +02:00
for ( int j = ( si . position . y ) - 1 ; j < = ( si . position . y + si . size . y ) ; j + + ) {
2014-10-03 05:10:51 +02:00
Vector2 ofs ;
2017-03-05 16:44:50 +01:00
if ( ABS ( j ) & 1 ) {
2019-03-24 00:59:24 +01:00
ofs = cell_xf [ 0 ] * ( node - > get_half_offset ( ) = = TileMap : : HALF_OFFSET_X ? 0.5 : - 0.5 ) ;
2014-10-03 05:10:51 +02:00
}
2017-03-05 16:44:50 +01:00
Vector2 from = xform . xform ( node - > map_to_world ( Vector2 ( i , j ) , true ) + ofs ) ;
Vector2 to = xform . xform ( node - > map_to_world ( Vector2 ( i , j + 1 ) , true ) + ofs ) ;
2019-03-24 19:17:02 +01:00
2017-03-05 16:44:50 +01:00
Color col = i = = 0 ? Color ( 1 , 0.8 , 0.2 , 0.5 ) : Color ( 1 , 0.3 , 0.1 , 0.2 ) ;
2018-09-18 20:00:07 +02:00
p_overlay - > draw_line ( from , to , col , 1 ) ;
2016-01-24 21:22:17 +01:00
2019-03-24 19:17:02 +01:00
if ( - - max_lines = = 0 )
2016-01-24 21:22:17 +01:00
break ;
2014-10-03 05:10:51 +02:00
}
2019-03-24 19:17:02 +01:00
if ( max_lines = = 0 )
break ;
2014-10-03 05:10:51 +02:00
}
}
2017-03-05 16:44:50 +01:00
int max_lines = 10000 ; //avoid crash if size too smal
2016-01-24 21:22:17 +01:00
2019-03-24 00:59:24 +01:00
if ( node - > get_half_offset ( ) ! = TileMap : : HALF_OFFSET_Y & & node - > get_half_offset ( ) ! = TileMap : : HALF_OFFSET_NEGATIVE_Y ) {
2014-10-03 05:10:51 +02:00
2017-06-04 00:25:13 +02:00
for ( int i = ( si . position . y ) - 1 ; i < = ( si . position . y + si . size . y ) ; i + + ) {
2014-10-03 05:10:51 +02:00
2017-06-04 00:25:13 +02:00
Vector2 from = xform . xform ( node - > map_to_world ( Vector2 ( si . position . x , i ) ) ) ;
Vector2 to = xform . xform ( node - > map_to_world ( Vector2 ( si . position . x + si . size . x + 1 , i ) ) ) ;
2014-10-03 05:10:51 +02:00
2017-03-05 16:44:50 +01:00
Color col = i = = 0 ? Color ( 1 , 0.8 , 0.2 , 0.5 ) : Color ( 1 , 0.3 , 0.1 , 0.2 ) ;
2018-09-18 20:00:07 +02:00
p_overlay - > draw_line ( from , to , col , 1 ) ;
2014-10-03 05:10:51 +02:00
2017-03-05 16:44:50 +01:00
if ( max_lines - - = = 0 )
2016-01-24 21:22:17 +01:00
break ;
2014-10-03 05:10:51 +02:00
}
} else {
2017-06-04 00:25:13 +02:00
for ( int i = ( si . position . y ) - 1 ; i < = ( si . position . y + si . size . y ) ; i + + ) {
2014-10-03 05:10:51 +02:00
2017-06-04 00:25:13 +02:00
for ( int j = ( si . position . x ) - 1 ; j < = ( si . position . x + si . size . x ) ; j + + ) {
2014-10-03 05:10:51 +02:00
Vector2 ofs ;
2017-03-05 16:44:50 +01:00
if ( ABS ( j ) & 1 ) {
2019-03-24 00:59:24 +01:00
ofs = cell_xf [ 1 ] * ( node - > get_half_offset ( ) = = TileMap : : HALF_OFFSET_Y ? 0.5 : - 0.5 ) ;
2014-10-03 05:10:51 +02:00
}
2017-03-05 16:44:50 +01:00
Vector2 from = xform . xform ( node - > map_to_world ( Vector2 ( j , i ) , true ) + ofs ) ;
Vector2 to = xform . xform ( node - > map_to_world ( Vector2 ( j + 1 , i ) , true ) + ofs ) ;
2019-03-24 19:17:02 +01:00
2017-03-05 16:44:50 +01:00
Color col = i = = 0 ? Color ( 1 , 0.8 , 0.2 , 0.5 ) : Color ( 1 , 0.3 , 0.1 , 0.2 ) ;
2018-09-18 20:00:07 +02:00
p_overlay - > draw_line ( from , to , col , 1 ) ;
2016-01-24 21:22:17 +01:00
2019-03-24 19:17:02 +01:00
if ( - - max_lines = = 0 )
2016-01-24 21:22:17 +01:00
break ;
2014-10-03 05:10:51 +02:00
}
2019-03-24 19:17:02 +01:00
if ( max_lines = = 0 )
break ;
2014-10-03 05:10:51 +02:00
}
}
2014-02-10 02:10:30 +01:00
}
if ( selection_active ) {
Vector < Vector2 > points ;
2017-06-04 00:25:13 +02:00
points . push_back ( xform . xform ( node - > map_to_world ( ( rectangle . position ) ) ) ) ;
points . push_back ( xform . xform ( node - > map_to_world ( ( rectangle . position + Point2 ( rectangle . size . x + 1 , 0 ) ) ) ) ) ;
points . push_back ( xform . xform ( node - > map_to_world ( ( rectangle . position + Point2 ( rectangle . size . x + 1 , rectangle . size . y + 1 ) ) ) ) ) ;
points . push_back ( xform . xform ( node - > map_to_world ( ( rectangle . position + Point2 ( 0 , rectangle . size . y + 1 ) ) ) ) ) ;
2014-02-10 02:10:30 +01:00
2018-09-18 20:00:07 +02:00
p_overlay - > draw_colored_polygon ( points , Color ( 0.2 , 0.8 , 1 , 0.4 ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( mouse_over ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Vector2 endpoints [ 4 ] = {
2016-03-10 19:10:31 +01:00
node - > map_to_world ( over_tile , true ) ,
2017-03-05 16:44:50 +01:00
node - > map_to_world ( ( over_tile + Point2 ( 1 , 0 ) ) , true ) ,
node - > map_to_world ( ( over_tile + Point2 ( 1 , 1 ) ) , true ) ,
node - > map_to_world ( ( over_tile + Point2 ( 0 , 1 ) ) , true )
2014-02-10 02:10:30 +01:00
} ;
2014-10-03 05:10:51 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
if ( node - > get_half_offset ( ) = = TileMap : : HALF_OFFSET_X & & ABS ( over_tile . y ) & 1 )
endpoints [ i ] + = cell_xf [ 0 ] * 0.5 ;
2019-03-24 00:59:24 +01:00
if ( node - > get_half_offset ( ) = = TileMap : : HALF_OFFSET_NEGATIVE_X & & ABS ( over_tile . y ) & 1 )
endpoints [ i ] + = cell_xf [ 0 ] * - 0.5 ;
2017-03-05 16:44:50 +01:00
if ( node - > get_half_offset ( ) = = TileMap : : HALF_OFFSET_Y & & ABS ( over_tile . x ) & 1 )
endpoints [ i ] + = cell_xf [ 1 ] * 0.5 ;
2019-03-24 00:59:24 +01:00
if ( node - > get_half_offset ( ) = = TileMap : : HALF_OFFSET_NEGATIVE_Y & & ABS ( over_tile . x ) & 1 )
endpoints [ i ] + = cell_xf [ 1 ] * - 0.5 ;
2017-03-05 16:44:50 +01:00
endpoints [ i ] = xform . xform ( endpoints [ i ] ) ;
2014-10-03 05:10:51 +02:00
}
2014-02-10 02:10:30 +01:00
Color col ;
2017-03-05 16:44:50 +01:00
if ( node - > get_cell ( over_tile . x , over_tile . y ) ! = TileMap : : INVALID_CELL )
col = Color ( 0.2 , 0.8 , 1.0 , 0.8 ) ;
2014-02-10 02:10:30 +01:00
else
2017-03-05 16:44:50 +01:00
col = Color ( 1.0 , 0.4 , 0.2 , 0.8 ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + )
2018-09-18 20:00:07 +02:00
p_overlay - > draw_line ( endpoints [ i ] , endpoints [ ( i + 1 ) % 4 ] , col , 2 ) ;
2014-02-10 02:10:30 +01:00
2017-01-05 23:41:36 +01:00
bool bucket_preview = EditorSettings : : get_singleton ( ) - > get ( " editors/tile_map/bucket_fill_preview " ) ;
2017-03-05 16:44:50 +01:00
if ( tool = = TOOL_SELECTING | | tool = = TOOL_PICKING | | ! bucket_preview ) {
2016-03-10 19:10:31 +01:00
return ;
2016-03-11 18:06:54 +01:00
}
2017-03-05 16:44:50 +01:00
if ( tool = = TOOL_LINE_PAINT ) {
2016-03-11 18:06:54 +01:00
if ( paint_undo . empty ( ) )
return ;
2018-03-17 13:12:26 +01:00
Vector < int > ids = get_selected_tiles ( ) ;
2016-03-11 18:06:54 +01:00
2018-03-17 13:12:26 +01:00
if ( ids . size ( ) = = 1 & & ids [ 0 ] = = TileMap : : INVALID_CELL )
2016-03-11 18:06:54 +01:00
return ;
2017-03-05 16:44:50 +01:00
for ( Map < Point2i , CellOp > : : Element * E = paint_undo . front ( ) ; E ; E = E - > next ( ) ) {
2016-03-11 18:06:54 +01:00
2018-12-19 00:09:37 +01:00
_draw_cell ( p_overlay , ids [ 0 ] , E - > key ( ) , flip_h , flip_v , transpose , autotile_coord , xform ) ;
2016-03-11 18:06:54 +01:00
}
2017-03-05 16:44:50 +01:00
} else if ( tool = = TOOL_RECTANGLE_PAINT ) {
2014-02-10 02:10:30 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > ids = get_selected_tiles ( ) ;
2014-02-10 02:10:30 +01:00
2018-03-17 13:12:26 +01:00
if ( ids . size ( ) = = 1 & & ids [ 0 ] = = TileMap : : INVALID_CELL )
2016-03-10 19:10:31 +01:00
return ;
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
for ( int i = rectangle . position . y ; i < = rectangle . position . y + rectangle . size . y ; i + + ) {
for ( int j = rectangle . position . x ; j < = rectangle . position . x + rectangle . size . x ; j + + ) {
2014-02-10 02:10:30 +01:00
2018-12-19 00:09:37 +01:00
_draw_cell ( p_overlay , ids [ 0 ] , Point2i ( j , i ) , flip_h , flip_v , transpose , autotile_coord , xform ) ;
2016-03-10 19:10:31 +01:00
}
}
2018-08-21 21:33:24 +02:00
} else if ( tool = = TOOL_PASTING ) {
2016-01-04 15:28:11 +01:00
2016-03-10 19:10:31 +01:00
if ( copydata . empty ( ) )
return ;
2016-01-04 15:28:11 +01:00
2016-03-10 19:10:31 +01:00
Ref < TileSet > ts = node - > get_tileset ( ) ;
2016-01-04 15:28:11 +01:00
2016-03-10 19:10:31 +01:00
if ( ts . is_null ( ) )
return ;
2016-01-02 18:17:20 +01:00
2017-06-04 00:25:13 +02:00
Point2 ofs = over_tile - rectangle . position ;
2015-03-09 06:34:56 +01:00
2017-03-05 16:44:50 +01:00
for ( List < TileData > : : Element * E = copydata . front ( ) ; E ; E = E - > next ( ) ) {
2015-03-09 06:34:56 +01:00
2016-03-10 19:10:31 +01:00
if ( ! ts - > has_tile ( E - > get ( ) . cell ) )
continue ;
2015-03-09 06:34:56 +01:00
2016-03-10 19:10:31 +01:00
TileData tcd = E - > get ( ) ;
2015-03-09 06:34:56 +01:00
2018-12-19 00:09:37 +01:00
_draw_cell ( p_overlay , tcd . cell , tcd . pos + ofs , tcd . flip_h , tcd . flip_v , tcd . transpose , tcd . autotile_coord , xform ) ;
2016-03-10 19:10:31 +01:00
}
2015-03-09 06:34:56 +01:00
2017-03-05 16:44:50 +01:00
Rect2i duplicate = rectangle ;
2017-06-04 00:25:13 +02:00
duplicate . position = over_tile ;
2015-03-09 06:34:56 +01:00
2016-03-10 19:10:31 +01:00
Vector < Vector2 > points ;
2017-06-04 00:25:13 +02:00
points . push_back ( xform . xform ( node - > map_to_world ( duplicate . position ) ) ) ;
points . push_back ( xform . xform ( node - > map_to_world ( ( duplicate . position + Point2 ( duplicate . size . x + 1 , 0 ) ) ) ) ) ;
points . push_back ( xform . xform ( node - > map_to_world ( ( duplicate . position + Point2 ( duplicate . size . x + 1 , duplicate . size . y + 1 ) ) ) ) ) ;
points . push_back ( xform . xform ( node - > map_to_world ( ( duplicate . position + Point2 ( 0 , duplicate . size . y + 1 ) ) ) ) ) ;
2015-03-09 06:34:56 +01:00
2018-09-18 20:00:07 +02:00
p_overlay - > draw_colored_polygon ( points , Color ( 0.2 , 1.0 , 0.8 , 0.2 ) ) ;
2015-03-09 06:34:56 +01:00
2017-03-05 16:44:50 +01:00
} else if ( tool = = TOOL_BUCKET ) {
2016-12-31 17:42:05 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > tiles = get_selected_tiles ( ) ;
2018-12-19 00:09:37 +01:00
_draw_fill_preview ( p_overlay , tiles [ 0 ] , over_tile , flip_h , flip_v , transpose , autotile_coord , xform ) ;
2016-12-31 17:42:05 +01:00
2016-03-10 19:10:31 +01:00
} else {
2014-02-10 02:10:30 +01:00
2018-03-17 13:12:26 +01:00
Vector < int > st = get_selected_tiles ( ) ;
2014-02-10 02:10:30 +01:00
2018-03-17 13:12:26 +01:00
if ( st . size ( ) = = 1 & & st [ 0 ] = = TileMap : : INVALID_CELL )
2016-03-10 19:10:31 +01:00
return ;
2014-02-10 02:10:30 +01:00
2018-12-19 00:09:37 +01:00
_draw_cell ( p_overlay , st [ 0 ] , over_tile , flip_h , flip_v , transpose , autotile_coord , xform ) ;
2014-02-10 02:10:30 +01:00
}
}
}
void TileMapEditor : : edit ( Node * p_tile_map ) {
2016-03-10 19:10:31 +01:00
search_box - > set_text ( " " ) ;
2018-10-04 14:20:03 +02:00
if ( ! canvas_item_editor_viewport ) {
canvas_item_editor_viewport = CanvasItemEditor : : get_singleton ( ) - > get_viewport_control ( ) ;
2014-02-10 02:10:30 +01:00
}
2014-04-19 21:46:52 +02:00
if ( node )
2017-03-05 16:44:50 +01:00
node - > disconnect ( " settings_changed " , this , " _tileset_settings_changed " ) ;
2014-02-10 02:10:30 +01:00
if ( p_tile_map ) {
2017-08-24 22:58:51 +02:00
node = Object : : cast_to < TileMap > ( p_tile_map ) ;
2018-10-04 14:20:03 +02:00
if ( ! canvas_item_editor_viewport - > is_connected ( " mouse_entered " , this , " _canvas_mouse_enter " ) )
canvas_item_editor_viewport - > connect ( " mouse_entered " , this , " _canvas_mouse_enter " ) ;
if ( ! canvas_item_editor_viewport - > is_connected ( " mouse_exited " , this , " _canvas_mouse_exit " ) )
canvas_item_editor_viewport - > connect ( " mouse_exited " , this , " _canvas_mouse_exit " ) ;
2014-02-10 02:10:30 +01:00
_update_palette ( ) ;
} else {
2017-03-05 16:44:50 +01:00
node = NULL ;
2014-02-10 02:10:30 +01:00
2018-10-04 14:20:03 +02:00
if ( canvas_item_editor_viewport - > is_connected ( " mouse_entered " , this , " _canvas_mouse_enter " ) )
canvas_item_editor_viewport - > disconnect ( " mouse_entered " , this , " _canvas_mouse_enter " ) ;
if ( canvas_item_editor_viewport - > is_connected ( " mouse_exited " , this , " _canvas_mouse_exit " ) )
canvas_item_editor_viewport - > disconnect ( " mouse_exited " , this , " _canvas_mouse_exit " ) ;
2014-02-10 02:10:30 +01:00
_update_palette ( ) ;
}
2014-04-19 21:46:52 +02:00
if ( node )
2017-03-05 16:44:50 +01:00
node - > connect ( " settings_changed " , this , " _tileset_settings_changed " ) ;
2014-04-19 21:46:52 +02:00
2016-12-31 17:42:05 +01:00
_clear_bucket_cache ( ) ;
2014-04-19 21:46:52 +02:00
}
void TileMapEditor : : _tileset_settings_changed ( ) {
2014-02-10 02:10:30 +01:00
2014-04-19 21:46:52 +02:00
_update_palette ( ) ;
2018-10-18 14:06:57 +02:00
CanvasItemEditor : : get_singleton ( ) - > update_viewport ( ) ;
2014-02-10 02:10:30 +01:00
}
2016-05-24 19:18:56 +02:00
void TileMapEditor : : _icon_size_changed ( float p_value ) {
if ( node ) {
2016-05-27 18:54:46 +02:00
palette - > set_icon_scale ( p_value ) ;
2018-06-01 23:12:25 +02:00
manual_palette - > set_icon_scale ( p_value ) ;
2016-05-24 19:18:56 +02:00
_update_palette ( ) ;
}
}
2014-02-10 02:10:30 +01:00
void TileMapEditor : : _bind_methods ( ) {
2018-06-01 23:12:25 +02:00
ClassDB : : bind_method ( D_METHOD ( " _manual_toggled " ) , & TileMapEditor : : _manual_toggled ) ;
2018-12-23 14:06:53 +01:00
ClassDB : : bind_method ( D_METHOD ( " _priority_toggled " ) , & TileMapEditor : : _priority_toggled ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _text_entered " ) , & TileMapEditor : : _text_entered ) ;
ClassDB : : bind_method ( D_METHOD ( " _text_changed " ) , & TileMapEditor : : _text_changed ) ;
ClassDB : : bind_method ( D_METHOD ( " _sbox_input " ) , & TileMapEditor : : _sbox_input ) ;
2019-01-29 19:55:52 +01:00
ClassDB : : bind_method ( D_METHOD ( " _button_tool_select " ) , & TileMapEditor : : _button_tool_select ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _menu_option " ) , & TileMapEditor : : _menu_option ) ;
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 ) ;
2018-10-29 17:16:18 +01:00
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 ) ;
2018-06-01 23:12:25 +02:00
ClassDB : : bind_method ( D_METHOD ( " _palette_selected " ) , & TileMapEditor : : _palette_selected ) ;
2018-07-29 23:54:12 +02:00
ClassDB : : bind_method ( D_METHOD ( " _palette_multi_selected " ) , & TileMapEditor : : _palette_multi_selected ) ;
2017-02-13 12:47:24 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _fill_points " ) , & TileMapEditor : : _fill_points ) ;
ClassDB : : bind_method ( D_METHOD ( " _erase_points " ) , & TileMapEditor : : _erase_points ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " _icon_size_changed " ) , & TileMapEditor : : _icon_size_changed ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
TileMapEditor : : CellOp TileMapEditor : : _get_op_from_cell ( const Point2i & p_pos ) {
2015-01-17 07:48:21 +01:00
CellOp op ;
2017-03-05 16:44:50 +01:00
op . idx = node - > get_cell ( p_pos . x , p_pos . y ) ;
if ( op . idx ! = TileMap : : INVALID_CELL ) {
if ( node - > is_cell_x_flipped ( p_pos . x , p_pos . y ) )
op . xf = true ;
if ( node - > is_cell_y_flipped ( p_pos . x , p_pos . y ) )
op . yf = true ;
if ( node - > is_cell_transposed ( p_pos . x , p_pos . y ) )
op . tr = true ;
2018-05-25 18:59:05 +02:00
op . ac = node - > get_cell_autotile_coord ( p_pos . x , p_pos . y ) ;
2015-01-17 07:48:21 +01:00
}
return op ;
}
2018-10-29 17:16:18 +01:00
void TileMapEditor : : _rotate ( int steps ) {
const bool normal_rotation_matrix [ ] [ 3 ] = {
{ false , false , false } ,
{ true , true , false } ,
{ false , true , true } ,
{ true , false , 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 ] ;
2018-11-07 18:29:24 +01:00
break ;
2018-10-29 17:16:18 +01:00
}
}
} 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 ;
}
}
2015-02-02 13:28:10 +01:00
}
2015-06-22 15:05:03 +02:00
2018-10-29 17:16:18 +01:00
_update_palette ( ) ;
}
void TileMapEditor : : _flip_horizontal ( ) {
flip_h = ! flip_h ;
_update_palette ( ) ;
}
2016-03-10 19:10:31 +01:00
2018-10-29 17:16:18 +01:00
void TileMapEditor : : _flip_vertical ( ) {
flip_v = ! flip_v ;
_update_palette ( ) ;
}
void TileMapEditor : : _clear_transform ( ) {
transpose = false ;
flip_h = false ;
flip_v = false ;
_update_palette ( ) ;
2015-02-02 12:27:48 +01:00
}
2014-02-10 02:10:30 +01:00
TileMapEditor : : TileMapEditor ( EditorNode * p_editor ) {
2017-03-05 16:44:50 +01:00
node = NULL ;
2018-06-01 23:12:25 +02:00
manual_autotile = false ;
2018-12-23 14:06:53 +01:00
priority_atlastile = false ;
2018-06-01 23:12:25 +02:00
manual_position = Vector2 ( 0 , 0 ) ;
2018-10-04 14:20:03 +02:00
canvas_item_editor_viewport = NULL ;
2017-03-05 16:44:50 +01:00
editor = p_editor ;
2019-06-26 15:08:25 +02:00
undo_redo = EditorNode : : get_undo_redo ( ) ;
2016-03-10 19:10:31 +01:00
2017-03-05 16:44:50 +01:00
tool = TOOL_NONE ;
selection_active = false ;
mouse_over = false ;
2017-08-16 19:51:55 +02:00
show_tile_info = true ;
2016-03-10 19:10:31 +01:00
2017-03-05 16:44:50 +01:00
flip_h = false ;
flip_v = false ;
transpose = false ;
2016-03-10 19:10:31 +01:00
2016-12-31 17:42:05 +01:00
bucket_cache_tile = - 1 ;
bucket_cache_visited = 0 ;
2018-03-17 13:12:26 +01:00
invalid_cell . resize ( 1 ) ;
2018-07-25 03:11:03 +02:00
invalid_cell . write [ 0 ] = TileMap : : INVALID_CELL ;
2018-03-17 13:12:26 +01:00
2018-02-24 14:39:19 +01:00
ED_SHORTCUT ( " tile_map_editor/erase_selection " , TTR ( " Erase Selection " ) , KEY_DELETE ) ;
ED_SHORTCUT ( " tile_map_editor/find_tile " , TTR ( " Find Tile " ) , KEY_MASK_CMD + KEY_F ) ;
2017-09-12 20:22:04 +02:00
ED_SHORTCUT ( " tile_map_editor/transpose " , TTR ( " Transpose " ) , KEY_T ) ;
2016-06-12 01:40:11 +02:00
2018-10-29 17:16:18 +01:00
HBoxContainer * tool_hb = memnew ( HBoxContainer ) ;
add_child ( tool_hb ) ;
2017-08-09 03:46:26 +02:00
2018-06-01 23:12:25 +02:00
manual_button = memnew ( CheckBox ) ;
2018-12-23 14:06:53 +01:00
manual_button - > set_text ( TTR ( " Disable Autotile " ) ) ;
2018-06-01 23:12:25 +02:00
manual_button - > connect ( " toggled " , this , " _manual_toggled " ) ;
add_child ( manual_button ) ;
2018-12-23 14:06:53 +01:00
priority_button = memnew ( CheckBox ) ;
priority_button - > set_text ( TTR ( " Enable Priority " ) ) ;
priority_button - > connect ( " toggled " , this , " _priority_toggled " ) ;
add_child ( priority_button ) ;
2017-03-05 16:44:50 +01:00
search_box = memnew ( LineEdit ) ;
2016-03-10 19:10:31 +01:00
search_box - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
search_box - > connect ( " text_entered " , this , " _text_entered " ) ;
search_box - > connect ( " text_changed " , this , " _text_changed " ) ;
2017-01-08 20:28:12 +01:00
search_box - > connect ( " gui_input " , this , " _sbox_input " ) ;
2016-03-10 19:10:31 +01:00
add_child ( search_box ) ;
2017-03-05 16:44:50 +01:00
size_slider = memnew ( HSlider ) ;
2016-05-24 19:18:56 +02:00
size_slider - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
size_slider - > set_min ( 0.1f ) ;
size_slider - > set_max ( 4.0f ) ;
size_slider - > set_step ( 0.1f ) ;
2017-01-04 05:16:14 +01:00
size_slider - > set_value ( 1.0f ) ;
2016-05-24 19:18:56 +02:00
size_slider - > connect ( " value_changed " , this , " _icon_size_changed " ) ;
add_child ( size_slider ) ;
2017-01-05 23:41:36 +01:00
int mw = EDITOR_DEF ( " editors/tile_map/palette_min_width " , 80 ) ;
2015-06-22 15:05:03 +02:00
2018-06-01 23:12:25 +02:00
VSplitContainer * palette_container = memnew ( VSplitContainer ) ;
palette_container - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
palette_container - > set_custom_minimum_size ( Size2 ( mw , 0 ) ) ;
add_child ( palette_container ) ;
2014-12-28 23:37:25 +01:00
// Add tile palette
2017-03-05 16:44:50 +01:00
palette = memnew ( ItemList ) ;
2018-06-01 23:12:25 +02:00
palette - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2014-12-28 23:37:25 +01:00
palette - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2016-08-15 21:48:04 +02:00
palette - > set_max_columns ( 0 ) ;
palette - > set_icon_mode ( ItemList : : ICON_MODE_TOP ) ;
palette - > set_max_text_lines ( 2 ) ;
2018-03-17 13:12:26 +01:00
palette - > set_select_mode ( ItemList : : SELECT_MULTI ) ;
2018-06-01 23:12:25 +02:00
palette - > connect ( " item_selected " , this , " _palette_selected " ) ;
2018-07-29 23:54:12 +02:00
palette - > connect ( " multi_selected " , this , " _palette_multi_selected " ) ;
2018-06-01 23:12:25 +02:00
palette_container - > add_child ( palette ) ;
// Add autotile override palette
manual_palette = memnew ( ItemList ) ;
manual_palette - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
manual_palette - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
manual_palette - > set_max_columns ( 0 ) ;
manual_palette - > set_icon_mode ( ItemList : : ICON_MODE_TOP ) ;
manual_palette - > set_max_text_lines ( 2 ) ;
manual_palette - > hide ( ) ;
palette_container - > add_child ( manual_palette ) ;
2014-02-10 02:10:30 +01:00
2014-12-28 23:37:25 +01:00
// Add menu items
2017-03-05 16:44:50 +01:00
toolbar = memnew ( HBoxContainer ) ;
2017-08-10 21:48:48 +02:00
toolbar - > hide ( ) ;
2016-03-10 19:10:31 +01:00
CanvasItemEditor : : get_singleton ( ) - > add_control_to_menu_panel ( toolbar ) ;
2019-01-29 19:55:52 +01:00
// Separator
toolbar - > add_child ( memnew ( VSeparator ) ) ;
// Tools
paint_button = memnew ( ToolButton ) ;
paint_button - > set_shortcut ( ED_SHORTCUT ( " tile_map_editor/paint_tile " , TTR ( " Paint Tile " ) , KEY_P ) ) ;
2019-08-19 19:40:31 +02:00
paint_button - > set_tooltip ( TTR ( " Shift+LMB: Line Draw \n Shift+Ctrl+LMB: Rectangle Paint " ) ) ;
2019-01-29 19:55:52 +01:00
paint_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_NONE ) ) ;
paint_button - > set_toggle_mode ( true ) ;
toolbar - > add_child ( paint_button ) ;
bucket_fill_button = memnew ( ToolButton ) ;
bucket_fill_button - > set_shortcut ( ED_SHORTCUT ( " tile_map_editor/bucket_fill " , TTR ( " Bucket Fill " ) , KEY_G ) ) ;
bucket_fill_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_BUCKET ) ) ;
bucket_fill_button - > set_toggle_mode ( true ) ;
toolbar - > add_child ( bucket_fill_button ) ;
picker_button = memnew ( ToolButton ) ;
2019-04-25 02:30:50 +02:00
picker_button - > set_shortcut ( ED_SHORTCUT ( " tile_map_editor/pick_tile " , TTR ( " Pick Tile " ) , KEY_CONTROL ) ) ;
2019-01-29 19:55:52 +01:00
picker_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_PICKING ) ) ;
picker_button - > set_toggle_mode ( true ) ;
toolbar - > add_child ( picker_button ) ;
select_button = memnew ( ToolButton ) ;
2019-04-25 02:30:50 +02:00
select_button - > set_shortcut ( ED_SHORTCUT ( " tile_map_editor/select " , TTR ( " Select " ) , KEY_MASK_CMD + KEY_B ) ) ;
2019-01-29 19:55:52 +01:00
select_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_SELECTING ) ) ;
select_button - > set_toggle_mode ( true ) ;
toolbar - > add_child ( select_button ) ;
_update_button_tool ( ) ;
// Container to the right of the toolbar
toolbar_right = memnew ( HBoxContainer ) ;
2019-04-23 20:30:03 +02:00
toolbar_right - > hide ( ) ;
2019-01-29 19:55:52 +01:00
toolbar_right - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
toolbar_right - > set_alignment ( BoxContainer : : ALIGN_END ) ;
CanvasItemEditor : : get_singleton ( ) - > add_control_to_menu_panel ( toolbar_right ) ;
2016-06-17 02:10:44 +02:00
// Tile position
2017-03-05 16:44:50 +01:00
tile_info = memnew ( Label ) ;
2019-01-29 19:55:52 +01:00
toolbar_right - > add_child ( tile_info ) ;
2016-06-17 02:10:44 +02:00
2019-01-29 19:55:52 +01:00
// Menu
2017-03-05 16:44:50 +01:00
options = memnew ( MenuButton ) ;
2018-11-24 05:38:26 +01:00
options - > set_text ( " TileMap " ) ;
2016-03-10 19:10:31 +01:00
options - > set_icon ( EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_icon ( " TileMap " , " EditorIcons " ) ) ;
2016-03-11 20:30:08 +01:00
options - > set_process_unhandled_key_input ( false ) ;
2019-01-29 19:55:52 +01:00
toolbar_right - > add_child ( options ) ;
2016-03-10 19:10:31 +01:00
PopupMenu * p = options - > get_popup ( ) ;
2018-08-21 21:33:24 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " tile_map_editor/cut_selection " , TTR ( " Cut Selection " ) , KEY_MASK_CMD + KEY_X ) , OPTION_CUT ) ;
p - > add_shortcut ( ED_SHORTCUT ( " tile_map_editor/copy_selection " , TTR ( " Copy Selection " ) , KEY_MASK_CMD + KEY_C ) , OPTION_COPY ) ;
2016-06-13 00:19:18 +02:00
p - > add_shortcut ( ED_GET_SHORTCUT ( " tile_map_editor/erase_selection " ) , OPTION_ERASE_SELECTION ) ;
2018-02-24 06:56:48 +01:00
p - > add_separator ( ) ;
p - > add_item ( TTR ( " Fix Invalid Tiles " ) , OPTION_FIX_INVALID ) ;
2017-01-08 22:18:54 +01:00
p - > connect ( " id_pressed " , this , " _menu_option " ) ;
2016-03-10 19:10:31 +01:00
2018-10-29 17:16:18 +01:00
rotate_left_button = memnew ( ToolButton ) ;
2019-06-04 01:01:27 +02:00
rotate_left_button - > set_tooltip ( TTR ( " Rotate Left " ) ) ;
2018-10-29 17:16:18 +01:00
rotate_left_button - > set_focus_mode ( FOCUS_NONE ) ;
rotate_left_button - > connect ( " pressed " , this , " _rotate " , varray ( - 1 ) ) ;
2019-07-14 15:32:17 +02:00
rotate_left_button - > set_shortcut ( ED_SHORTCUT ( " tile_map_editor/rotate_left " , TTR ( " Rotate Left " ) , KEY_A ) ) ;
2018-10-29 17:16:18 +01:00
tool_hb - > add_child ( rotate_left_button ) ;
rotate_right_button = memnew ( ToolButton ) ;
2019-06-04 01:01:27 +02:00
rotate_right_button - > set_tooltip ( TTR ( " Rotate Right " ) ) ;
2018-10-29 17:16:18 +01:00
rotate_right_button - > set_focus_mode ( FOCUS_NONE ) ;
rotate_right_button - > connect ( " pressed " , this , " _rotate " , varray ( 1 ) ) ;
2019-07-14 15:32:17 +02:00
rotate_right_button - > set_shortcut ( ED_SHORTCUT ( " tile_map_editor/rotate_right " , TTR ( " Rotate Right " ) , KEY_S ) ) ;
2018-10-29 17:16:18 +01:00
tool_hb - > add_child ( rotate_right_button ) ;
flip_horizontal_button = memnew ( ToolButton ) ;
2019-06-04 01:01:27 +02:00
flip_horizontal_button - > set_tooltip ( TTR ( " Flip Horizontally " ) ) ;
2018-10-29 17:16:18 +01:00
flip_horizontal_button - > set_focus_mode ( FOCUS_NONE ) ;
flip_horizontal_button - > connect ( " pressed " , this , " _flip_horizontal " ) ;
2019-07-14 15:32:17 +02:00
flip_horizontal_button - > set_shortcut ( ED_SHORTCUT ( " tile_map_editor/flip_horizontal " , TTR ( " Flip Horizontally " ) , KEY_X ) ) ;
2018-10-29 17:16:18 +01:00
tool_hb - > add_child ( flip_horizontal_button ) ;
flip_vertical_button = memnew ( ToolButton ) ;
2019-06-04 01:01:27 +02:00
flip_vertical_button - > set_tooltip ( TTR ( " Flip Vertically " ) ) ;
2018-10-29 17:16:18 +01:00
flip_vertical_button - > set_focus_mode ( FOCUS_NONE ) ;
flip_vertical_button - > connect ( " pressed " , this , " _flip_vertical " ) ;
2019-07-14 15:32:17 +02:00
flip_vertical_button - > set_shortcut ( ED_SHORTCUT ( " tile_map_editor/flip_vertical " , TTR ( " Flip Vertically " ) , KEY_Z ) ) ;
2018-10-29 17:16:18 +01:00
tool_hb - > add_child ( flip_vertical_button ) ;
clear_transform_button = memnew ( ToolButton ) ;
2019-06-04 01:01:27 +02:00
clear_transform_button - > set_tooltip ( TTR ( " Clear Transform " ) ) ;
2018-10-29 17:16:18 +01:00
clear_transform_button - > set_focus_mode ( FOCUS_NONE ) ;
clear_transform_button - > connect ( " pressed " , this , " _clear_transform " ) ;
2019-07-14 15:32:17 +02:00
clear_transform_button - > set_shortcut ( ED_SHORTCUT ( " tile_map_editor/clear_transform " , TTR ( " Clear Transform " ) , KEY_W ) ) ;
2018-10-29 17:16:18 +01:00
tool_hb - > add_child ( clear_transform_button ) ;
clear_transform_button - > set_disabled ( true ) ;
2014-02-10 02:10:30 +01:00
}
2016-12-31 17:42:05 +01:00
TileMapEditor : : ~ TileMapEditor ( ) {
_clear_bucket_cache ( ) ;
2018-08-21 21:33:24 +02:00
copydata . clear ( ) ;
2016-12-31 17:42:05 +01:00
}
2016-03-10 19:10:31 +01:00
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
2014-02-10 02:10:30 +01:00
2018-08-21 06:35:48 +02:00
void TileMapEditorPlugin : : _notification ( int p_what ) {
if ( p_what = = EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED ) {
switch ( ( int ) EditorSettings : : get_singleton ( ) - > get ( " editors/tile_map/editor_side " ) ) {
case 0 : { // Left.
CanvasItemEditor : : get_singleton ( ) - > get_palette_split ( ) - > move_child ( tile_map_editor , 0 ) ;
} break ;
case 1 : { // Right.
CanvasItemEditor : : get_singleton ( ) - > get_palette_split ( ) - > move_child ( tile_map_editor , 1 ) ;
} break ;
}
}
}
2014-02-10 02:10:30 +01:00
void TileMapEditorPlugin : : edit ( Object * p_object ) {
2017-08-24 22:58:51 +02:00
tile_map_editor - > edit ( Object : : cast_to < Node > ( p_object ) ) ;
2014-02-10 02:10:30 +01:00
}
bool TileMapEditorPlugin : : handles ( Object * p_object ) const {
2017-01-03 03:03:46 +01:00
return p_object - > is_class ( " TileMap " ) ;
2014-02-10 02:10:30 +01:00
}
void TileMapEditorPlugin : : make_visible ( bool p_visible ) {
if ( p_visible ) {
2016-03-10 19:10:31 +01:00
tile_map_editor - > show ( ) ;
tile_map_editor - > get_toolbar ( ) - > show ( ) ;
2019-04-23 20:30:03 +02:00
tile_map_editor - > get_toolbar_right ( ) - > show ( ) ;
2019-08-21 15:34:06 +02:00
CanvasItemEditor : : get_singleton ( ) - > set_current_tool ( CanvasItemEditor : : TOOL_SELECT ) ; //Change to TOOL_SELECT when TileMap node is selected, to prevent accidental movement.
2014-02-10 02:10:30 +01:00
} else {
tile_map_editor - > hide ( ) ;
2016-03-10 19:10:31 +01:00
tile_map_editor - > get_toolbar ( ) - > hide ( ) ;
2019-04-23 20:30:03 +02:00
tile_map_editor - > get_toolbar_right ( ) - > hide ( ) ;
2014-02-10 02:10:30 +01:00
tile_map_editor - > edit ( NULL ) ;
}
}
TileMapEditorPlugin : : TileMapEditorPlugin ( EditorNode * p_node ) {
2017-03-05 16:44:50 +01:00
EDITOR_DEF ( " editors/tile_map/preview_size " , 64 ) ;
EDITOR_DEF ( " editors/tile_map/palette_item_hseparation " , 8 ) ;
2017-01-05 23:41:36 +01:00
EDITOR_DEF ( " editors/tile_map/show_tile_names " , true ) ;
2017-03-27 02:50:51 +02:00
EDITOR_DEF ( " editors/tile_map/show_tile_ids " , false ) ;
EDITOR_DEF ( " editors/tile_map/sort_tiles_by_name " , true ) ;
2017-01-05 23:41:36 +01:00
EDITOR_DEF ( " editors/tile_map/bucket_fill_preview " , true ) ;
2017-08-16 19:51:55 +02:00
EDITOR_DEF ( " editors/tile_map/show_tile_info_on_hover " , true ) ;
2018-08-21 06:35:48 +02:00
EDITOR_DEF ( " editors/tile_map/editor_side " , 1 ) ;
EditorSettings : : get_singleton ( ) - > add_property_hint ( PropertyInfo ( Variant : : INT , " editors/tile_map/editor_side " , PROPERTY_HINT_ENUM , " Left,Right " ) ) ;
2016-08-15 21:48:04 +02:00
2017-03-05 16:44:50 +01:00
tile_map_editor = memnew ( TileMapEditor ( p_node ) ) ;
2018-08-21 06:35:48 +02:00
switch ( ( int ) EditorSettings : : get_singleton ( ) - > get ( " editors/tile_map/editor_side " ) ) {
case 0 : { // Left.
add_control_to_container ( CONTAINER_CANVAS_EDITOR_SIDE_LEFT , tile_map_editor ) ;
} break ;
case 1 : { // Right.
add_control_to_container ( CONTAINER_CANVAS_EDITOR_SIDE_RIGHT , tile_map_editor ) ;
} break ;
}
2014-02-10 02:10:30 +01:00
tile_map_editor - > hide ( ) ;
}
2017-03-05 16:44:50 +01:00
TileMapEditorPlugin : : ~ TileMapEditorPlugin ( ) {
2014-02-10 02:10:30 +01:00
}