2021-05-07 15:41:39 +02:00
/*************************************************************************/
/* tile_atlas_view.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
# include "tile_atlas_view.h"
# include "core/input/input.h"
# include "core/os/keyboard.h"
# include "scene/gui/box_container.h"
# include "scene/gui/label.h"
# include "scene/gui/panel.h"
# include "scene/gui/texture_rect.h"
# include "editor/editor_scale.h"
2021-05-21 17:28:28 +02:00
# include "editor/editor_settings.h"
2021-05-07 15:41:39 +02:00
void TileAtlasView : : _gui_input ( const Ref < InputEvent > & p_event ) {
2021-06-09 20:01:08 +02:00
Ref < InputEventMouseButton > mb = p_event ;
if ( mb . is_valid ( ) ) {
drag_type = DRAG_TYPE_NONE ;
2021-05-07 15:41:39 +02:00
2021-07-19 23:35:07 +02:00
Vector2i scroll_vec = Vector2 ( ( mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_LEFT ) - ( mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_RIGHT ) , ( mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_UP ) - ( mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_DOWN ) ) ;
if ( scroll_vec ! = Vector2 ( ) ) {
if ( mb - > is_ctrl_pressed ( ) ) {
if ( mb - > is_shift_pressed ( ) ) {
panning . x + = 32 * mb - > get_factor ( ) * scroll_vec . y ;
panning . y + = 32 * mb - > get_factor ( ) * scroll_vec . x ;
} else {
panning . y + = 32 * mb - > get_factor ( ) * scroll_vec . y ;
panning . x + = 32 * mb - > get_factor ( ) * scroll_vec . x ;
}
emit_signal ( SNAME ( " transform_changed " ) , zoom_widget - > get_zoom ( ) , panning ) ;
_update_zoom_and_panning ( true ) ;
accept_event ( ) ;
} else if ( ! mb - > is_shift_pressed ( ) ) {
zoom_widget - > set_zoom_by_increments ( scroll_vec . y * 2 ) ;
emit_signal ( SNAME ( " transform_changed " ) , zoom_widget - > get_zoom ( ) , panning ) ;
_update_zoom_and_panning ( true ) ;
accept_event ( ) ;
}
2021-06-09 20:01:08 +02:00
}
if ( mb - > get_button_index ( ) = = MOUSE_BUTTON_MIDDLE | | mb - > get_button_index ( ) = = MOUSE_BUTTON_RIGHT ) {
if ( mb - > is_pressed ( ) ) {
drag_type = DRAG_TYPE_PAN ;
} else {
drag_type = DRAG_TYPE_NONE ;
}
accept_event ( ) ;
}
}
Ref < InputEventMouseMotion > mm = p_event ;
if ( mm . is_valid ( ) ) {
if ( drag_type = = DRAG_TYPE_PAN ) {
panning + = mm - > get_relative ( ) ;
_update_zoom_and_panning ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " transform_changed " ) , zoom_widget - > get_zoom ( ) , panning ) ;
2021-05-07 15:41:39 +02:00
accept_event ( ) ;
}
}
}
Size2i TileAtlasView : : _compute_base_tiles_control_size ( ) {
// Update the texture.
Vector2i size ;
Ref < Texture2D > texture = tile_set_atlas_source - > get_texture ( ) ;
if ( texture . is_valid ( ) ) {
size = texture - > get_size ( ) ;
}
// Extend the size to all existing tiles.
Size2i grid_size = tile_set_atlas_source - > get_atlas_grid_size ( ) ;
for ( int i = 0 ; i < tile_set_atlas_source - > get_tiles_count ( ) ; i + + ) {
Vector2i tile_id = tile_set_atlas_source - > get_tile_id ( i ) ;
grid_size = grid_size . max ( tile_id + Vector2i ( 1 , 1 ) ) ;
}
size = size . max ( grid_size * ( tile_set_atlas_source - > get_texture_region_size ( ) + tile_set_atlas_source - > get_separation ( ) ) + tile_set_atlas_source - > get_margins ( ) ) ;
return size ;
}
Size2i TileAtlasView : : _compute_alternative_tiles_control_size ( ) {
Vector2i size ;
for ( int i = 0 ; i < tile_set_atlas_source - > get_tiles_count ( ) ; i + + ) {
Vector2i tile_id = tile_set_atlas_source - > get_tile_id ( i ) ;
int alternatives_count = tile_set_atlas_source - > get_alternative_tiles_count ( tile_id ) ;
Vector2i line_size ;
Size2i texture_region_size = tile_set_atlas_source - > get_tile_texture_region ( tile_id ) . size ;
for ( int j = 1 ; j < alternatives_count ; j + + ) {
int alternative_id = tile_set_atlas_source - > get_alternative_tile_id ( tile_id , j ) ;
bool transposed = Object : : cast_to < TileData > ( tile_set_atlas_source - > get_tile_data ( tile_id , alternative_id ) ) - > get_transpose ( ) ;
line_size . x + = transposed ? texture_region_size . y : texture_region_size . x ;
line_size . y = MAX ( line_size . y , transposed ? texture_region_size . x : texture_region_size . y ) ;
}
size . x = MAX ( size . x , line_size . x ) ;
size . y + = line_size . y ;
}
return size ;
}
2021-06-09 20:01:08 +02:00
void TileAtlasView : : _update_zoom_and_panning ( bool p_zoom_on_mouse_pos ) {
float zoom = zoom_widget - > get_zoom ( ) ;
2021-05-07 15:41:39 +02:00
// Compute the minimum sizes.
Size2i base_tiles_control_size = _compute_base_tiles_control_size ( ) ;
2021-06-09 20:01:08 +02:00
base_tiles_root_control - > set_custom_minimum_size ( Vector2 ( base_tiles_control_size ) * zoom ) ;
2021-05-07 15:41:39 +02:00
Size2i alternative_tiles_control_size = _compute_alternative_tiles_control_size ( ) ;
2021-06-09 20:01:08 +02:00
alternative_tiles_root_control - > set_custom_minimum_size ( Vector2 ( alternative_tiles_control_size ) * zoom ) ;
2021-05-07 15:41:39 +02:00
// Set the texture for the base tiles.
Ref < Texture2D > texture = tile_set_atlas_source - > get_texture ( ) ;
// Set the scales.
if ( base_tiles_control_size . x > 0 & & base_tiles_control_size . y > 0 ) {
2021-06-09 20:01:08 +02:00
base_tiles_drawing_root - > set_scale ( Vector2 ( zoom , zoom ) ) ;
2021-05-07 15:41:39 +02:00
} else {
base_tiles_drawing_root - > set_scale ( Vector2 ( 1 , 1 ) ) ;
}
if ( alternative_tiles_control_size . x > 0 & & alternative_tiles_control_size . y > 0 ) {
2021-06-09 20:01:08 +02:00
alternative_tiles_drawing_root - > set_scale ( Vector2 ( zoom , zoom ) ) ;
2021-05-07 15:41:39 +02:00
} else {
alternative_tiles_drawing_root - > set_scale ( Vector2 ( 1 , 1 ) ) ;
}
// Update the margin container's margins.
const char * constants [ ] = { " margin_left " , " margin_top " , " margin_right " , " margin_bottom " } ;
for ( int i = 0 ; i < 4 ; i + + ) {
2021-06-09 20:01:08 +02:00
margin_container - > add_theme_constant_override ( constants [ i ] , margin_container_paddings [ i ] * zoom ) ;
2021-05-07 15:41:39 +02:00
}
// Update the backgrounds.
background_left - > update ( ) ;
background_right - > update ( ) ;
// Zoom on the position.
2021-06-09 20:01:08 +02:00
if ( p_zoom_on_mouse_pos ) {
// Offset the panning relative to the center of panel.
Vector2 relative_mpos = get_local_mouse_position ( ) - get_size ( ) / 2 ;
panning = ( panning - relative_mpos ) * zoom / previous_zoom + relative_mpos ;
} else {
// Center of panel.
panning = panning * zoom / previous_zoom ;
}
button_center_view - > set_disabled ( panning . is_equal_approx ( Vector2 ( ) ) ) ;
2021-05-07 15:41:39 +02:00
2021-06-09 20:01:08 +02:00
previous_zoom = zoom ;
2021-05-07 15:41:39 +02:00
2021-06-09 20:01:08 +02:00
center_container - > set_begin ( panning - center_container - > get_minimum_size ( ) / 2 ) ;
center_container - > set_size ( center_container - > get_minimum_size ( ) ) ;
2021-05-07 15:41:39 +02:00
}
2021-06-09 20:01:08 +02:00
void TileAtlasView : : _zoom_widget_changed ( ) {
_update_zoom_and_panning ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " transform_changed " ) , zoom_widget - > get_zoom ( ) , panning ) ;
2021-05-07 15:41:39 +02:00
}
2021-06-09 20:01:08 +02:00
void TileAtlasView : : _center_view ( ) {
panning = Vector2 ( ) ;
button_center_view - > set_disabled ( true ) ;
_update_zoom_and_panning ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " transform_changed " ) , zoom_widget - > get_zoom ( ) , panning ) ;
2021-05-07 15:41:39 +02:00
}
void TileAtlasView : : _base_tiles_root_control_gui_input ( const Ref < InputEvent > & p_event ) {
base_tiles_root_control - > set_tooltip ( " " ) ;
Ref < InputEventMouseMotion > mm = p_event ;
if ( mm . is_valid ( ) ) {
Transform2D xform = base_tiles_drawing_root - > get_transform ( ) . affine_inverse ( ) ;
Vector2i coords = get_atlas_tile_coords_at_pos ( xform . xform ( mm - > get_position ( ) ) ) ;
2021-05-18 15:40:52 +02:00
if ( coords ! = TileSetSource : : INVALID_ATLAS_COORDS ) {
2021-05-07 15:41:39 +02:00
coords = tile_set_atlas_source - > get_tile_at_coords ( coords ) ;
2021-05-18 15:40:52 +02:00
if ( coords ! = TileSetSource : : INVALID_ATLAS_COORDS ) {
2021-05-07 15:41:39 +02:00
base_tiles_root_control - > set_tooltip ( vformat ( TTR ( " Source: %d \n Atlas coordinates: %s \n Alternative: 0 " ) , source_id , coords ) ) ;
}
}
}
}
void TileAtlasView : : _draw_base_tiles ( ) {
Ref < Texture2D > texture = tile_set_atlas_source - > get_texture ( ) ;
if ( texture . is_valid ( ) ) {
Vector2i margins = tile_set_atlas_source - > get_margins ( ) ;
Vector2i texture_region_size = tile_set_atlas_source - > get_texture_region_size ( ) ;
// Draw the texture, square by square.
Size2i grid_size = tile_set_atlas_source - > get_atlas_grid_size ( ) ;
for ( int x = 0 ; x < grid_size . x ; x + + ) {
for ( int y = 0 ; y < grid_size . y ; y + + ) {
Vector2i coords = Vector2i ( x , y ) ;
2021-05-18 15:40:52 +02:00
if ( tile_set_atlas_source - > get_tile_at_coords ( coords ) = = TileSetSource : : INVALID_ATLAS_COORDS ) {
2021-05-07 15:41:39 +02:00
Rect2i rect = Rect2i ( texture_region_size * coords + margins , texture_region_size ) ;
base_tiles_draw - > draw_texture_rect_region ( texture , rect , rect ) ;
}
}
}
// Draw the texture around the grid.
Rect2i rect ;
// Top.
rect . position = Vector2i ( ) ;
rect . set_end ( Vector2i ( texture - > get_size ( ) . x , margins . y ) ) ;
base_tiles_draw - > draw_texture_rect_region ( texture , rect , rect ) ;
// Bottom
2021-05-18 15:40:52 +02:00
int bottom_border = margins . y + ( grid_size . y * texture_region_size . y ) ;
if ( bottom_border < texture - > get_size ( ) . y ) {
rect . position = Vector2i ( 0 , bottom_border ) ;
rect . set_end ( texture - > get_size ( ) ) ;
base_tiles_draw - > draw_texture_rect_region ( texture , rect , rect ) ;
}
2021-05-07 15:41:39 +02:00
// Left
rect . position = Vector2i ( 0 , margins . y ) ;
rect . set_end ( Vector2i ( margins . x , margins . y + ( grid_size . y * texture_region_size . y ) ) ) ;
base_tiles_draw - > draw_texture_rect_region ( texture , rect , rect ) ;
// Right.
2021-05-18 15:40:52 +02:00
int right_border = margins . x + ( grid_size . x * texture_region_size . x ) ;
if ( right_border < texture - > get_size ( ) . x ) {
rect . position = Vector2i ( right_border , margins . y ) ;
rect . set_end ( Vector2i ( texture - > get_size ( ) . x , margins . y + ( grid_size . y * texture_region_size . y ) ) ) ;
base_tiles_draw - > draw_texture_rect_region ( texture , rect , rect ) ;
}
2021-05-07 15:41:39 +02:00
// Draw actual tiles, using their properties (modulation, etc...)
for ( int i = 0 ; i < tile_set_atlas_source - > get_tiles_count ( ) ; i + + ) {
Vector2i atlas_coords = tile_set_atlas_source - > get_tile_id ( i ) ;
// Update the y to max value.
Vector2i offset_pos = ( margins + ( atlas_coords * texture_region_size ) + tile_set_atlas_source - > get_tile_texture_region ( atlas_coords ) . size / 2 + tile_set_atlas_source - > get_tile_effective_texture_offset ( atlas_coords , 0 ) ) ;
// Draw the tile.
2021-05-18 15:40:52 +02:00
TileSetPluginAtlasRendering : : draw_tile ( base_tiles_draw - > get_canvas_item ( ) , offset_pos , tile_set , source_id , atlas_coords , 0 ) ;
2021-05-07 15:41:39 +02:00
}
}
}
void TileAtlasView : : _draw_base_tiles_texture_grid ( ) {
Ref < Texture2D > texture = tile_set_atlas_source - > get_texture ( ) ;
if ( texture . is_valid ( ) ) {
Vector2i margins = tile_set_atlas_source - > get_margins ( ) ;
Vector2i separation = tile_set_atlas_source - > get_separation ( ) ;
Vector2i texture_region_size = tile_set_atlas_source - > get_texture_region_size ( ) ;
Size2i grid_size = tile_set_atlas_source - > get_atlas_grid_size ( ) ;
// Draw each tile texture region.
for ( int x = 0 ; x < grid_size . x ; x + + ) {
for ( int y = 0 ; y < grid_size . y ; y + + ) {
Vector2i origin = margins + ( Vector2i ( x , y ) * ( texture_region_size + separation ) ) ;
Vector2i base_tile_coords = tile_set_atlas_source - > get_tile_at_coords ( Vector2i ( x , y ) ) ;
2021-05-18 15:40:52 +02:00
if ( base_tile_coords ! = TileSetSource : : INVALID_ATLAS_COORDS ) {
2021-05-07 15:41:39 +02:00
if ( base_tile_coords = = Vector2i ( x , y ) ) {
// Draw existing tile.
Vector2i size_in_atlas = tile_set_atlas_source - > get_tile_size_in_atlas ( base_tile_coords ) ;
Vector2 region_size = texture_region_size * size_in_atlas + separation * ( size_in_atlas - Vector2i ( 1 , 1 ) ) ;
base_tiles_texture_grid - > draw_rect ( Rect2i ( origin , region_size ) , Color ( 1.0 , 1.0 , 1.0 , 0.8 ) , false ) ;
}
} else {
// Draw the grid.
base_tiles_texture_grid - > draw_rect ( Rect2i ( origin , texture_region_size ) , Color ( 0.7 , 0.7 , 0.7 , 0.1 ) , false ) ;
}
}
}
}
}
void TileAtlasView : : _draw_base_tiles_dark ( ) {
Ref < Texture2D > texture = tile_set_atlas_source - > get_texture ( ) ;
if ( texture . is_valid ( ) ) {
Vector2i margins = tile_set_atlas_source - > get_margins ( ) ;
Vector2i separation = tile_set_atlas_source - > get_separation ( ) ;
Vector2i texture_region_size = tile_set_atlas_source - > get_texture_region_size ( ) ;
Size2i grid_size = tile_set_atlas_source - > get_atlas_grid_size ( ) ;
// Draw each tile texture region.
for ( int x = 0 ; x < grid_size . x ; x + + ) {
for ( int y = 0 ; y < grid_size . y ; y + + ) {
Vector2i origin = margins + ( Vector2i ( x , y ) * ( texture_region_size + separation ) ) ;
Vector2i base_tile_coords = tile_set_atlas_source - > get_tile_at_coords ( Vector2i ( x , y ) ) ;
2021-05-18 15:40:52 +02:00
if ( base_tile_coords = = TileSetSource : : INVALID_ATLAS_COORDS ) {
2021-05-07 15:41:39 +02:00
// Draw the grid.
base_tiles_dark - > draw_rect ( Rect2i ( origin , texture_region_size ) , Color ( 0.0 , 0.0 , 0.0 , 0.5 ) , true ) ;
}
}
}
}
}
void TileAtlasView : : _draw_base_tiles_shape_grid ( ) {
// Draw the shapes.
2021-05-21 17:28:28 +02:00
Color grid_color = EditorSettings : : get_singleton ( ) - > get ( " editors/tiles_editor/grid_color " ) ;
2021-05-07 15:41:39 +02:00
Vector2i tile_shape_size = tile_set - > get_tile_size ( ) ;
for ( int i = 0 ; i < tile_set_atlas_source - > get_tiles_count ( ) ; i + + ) {
Vector2i tile_id = tile_set_atlas_source - > get_tile_id ( i ) ;
Vector2 in_tile_base_offset = tile_set_atlas_source - > get_tile_effective_texture_offset ( tile_id , 0 ) ;
Rect2i texture_region = tile_set_atlas_source - > get_tile_texture_region ( tile_id ) ;
Vector2 origin = texture_region . position + ( texture_region . size - tile_shape_size ) / 2 + in_tile_base_offset ;
// Draw only if the tile shape fits in the texture region
2021-05-21 17:28:28 +02:00
tile_set - > draw_tile_shape ( base_tiles_shape_grid , Rect2 ( origin , tile_shape_size ) , grid_color ) ;
2021-05-07 15:41:39 +02:00
}
}
void TileAtlasView : : _alternative_tiles_root_control_gui_input ( const Ref < InputEvent > & p_event ) {
alternative_tiles_root_control - > set_tooltip ( " " ) ;
Ref < InputEventMouseMotion > mm = p_event ;
if ( mm . is_valid ( ) ) {
Transform2D xform = alternative_tiles_drawing_root - > get_transform ( ) . affine_inverse ( ) ;
Vector3i coords3 = get_alternative_tile_at_pos ( xform . xform ( mm - > get_position ( ) ) ) ;
Vector2i coords = Vector2i ( coords3 . x , coords3 . y ) ;
int alternative_id = coords3 . z ;
2021-05-18 15:40:52 +02:00
if ( coords ! = TileSetSource : : INVALID_ATLAS_COORDS & & alternative_id ! = TileSetSource : : INVALID_TILE_ALTERNATIVE ) {
2021-05-07 15:41:39 +02:00
alternative_tiles_root_control - > set_tooltip ( vformat ( TTR ( " Source: %d \n Atlas coordinates: %s \n Alternative: %d " ) , source_id , coords , alternative_id ) ) ;
}
}
}
void TileAtlasView : : _draw_alternatives ( ) {
// Draw the alternative tiles.
Ref < Texture2D > texture = tile_set_atlas_source - > get_texture ( ) ;
if ( texture . is_valid ( ) ) {
Vector2 current_pos ;
for ( int i = 0 ; i < tile_set_atlas_source - > get_tiles_count ( ) ; i + + ) {
Vector2i atlas_coords = tile_set_atlas_source - > get_tile_id ( i ) ;
current_pos . x = 0 ;
int y_increment = 0 ;
Rect2i texture_region = tile_set_atlas_source - > get_tile_texture_region ( atlas_coords ) ;
int alternatives_count = tile_set_atlas_source - > get_alternative_tiles_count ( atlas_coords ) ;
for ( int j = 1 ; j < alternatives_count ; j + + ) {
int alternative_id = tile_set_atlas_source - > get_alternative_tile_id ( atlas_coords , j ) ;
TileData * tile_data = Object : : cast_to < TileData > ( tile_set_atlas_source - > get_tile_data ( atlas_coords , alternative_id ) ) ;
bool transposed = tile_data - > get_transpose ( ) ;
// Update the y to max value.
Vector2i offset_pos = current_pos ;
if ( transposed ) {
offset_pos = ( current_pos + Vector2 ( texture_region . size . y , texture_region . size . x ) / 2 + tile_set_atlas_source - > get_tile_effective_texture_offset ( atlas_coords , alternative_id ) ) ;
y_increment = MAX ( y_increment , texture_region . size . x ) ;
} else {
offset_pos = ( current_pos + texture_region . size / 2 + tile_set_atlas_source - > get_tile_effective_texture_offset ( atlas_coords , alternative_id ) ) ;
y_increment = MAX ( y_increment , texture_region . size . y ) ;
}
// Draw the tile.
2021-05-18 15:40:52 +02:00
TileSetPluginAtlasRendering : : draw_tile ( alternatives_draw - > get_canvas_item ( ) , offset_pos , tile_set , source_id , atlas_coords , alternative_id ) ;
2021-05-07 15:41:39 +02:00
// Increment the x position.
current_pos . x + = transposed ? texture_region . size . y : texture_region . size . x ;
}
if ( alternatives_count > 1 ) {
current_pos . y + = y_increment ;
}
}
}
}
void TileAtlasView : : _draw_background_left ( ) {
2021-07-17 23:22:52 +02:00
Ref < Texture2D > texture = get_theme_icon ( SNAME ( " Checkerboard " ) , SNAME ( " EditorIcons " ) ) ;
2021-05-07 15:41:39 +02:00
background_left - > set_size ( base_tiles_root_control - > get_custom_minimum_size ( ) ) ;
background_left - > draw_texture_rect ( texture , Rect2 ( Vector2 ( ) , background_left - > get_size ( ) ) , true ) ;
}
void TileAtlasView : : _draw_background_right ( ) {
2021-07-17 23:22:52 +02:00
Ref < Texture2D > texture = get_theme_icon ( SNAME ( " Checkerboard " ) , SNAME ( " EditorIcons " ) ) ;
2021-05-07 15:41:39 +02:00
background_right - > set_size ( alternative_tiles_root_control - > get_custom_minimum_size ( ) ) ;
background_right - > draw_texture_rect ( texture , Rect2 ( Vector2 ( ) , background_right - > get_size ( ) ) , true ) ;
}
void TileAtlasView : : set_atlas_source ( TileSet * p_tile_set , TileSetAtlasSource * p_tile_set_atlas_source , int p_source_id ) {
ERR_FAIL_COND ( ! p_tile_set ) ;
ERR_FAIL_COND ( ! p_tile_set_atlas_source ) ;
ERR_FAIL_COND ( p_source_id < 0 ) ;
ERR_FAIL_COND ( p_tile_set - > get_source ( p_source_id ) ! = p_tile_set_atlas_source ) ;
tile_set = p_tile_set ;
tile_set_atlas_source = p_tile_set_atlas_source ;
source_id = p_source_id ;
// Show or hide the view.
bool valid = tile_set_atlas_source - > get_texture ( ) . is_valid ( ) ;
hbox - > set_visible ( valid ) ;
missing_source_label - > set_visible ( ! valid ) ;
// Update the rect cache.
_update_alternative_tiles_rect_cache ( ) ;
// Update everything.
2021-06-09 20:01:08 +02:00
_update_zoom_and_panning ( ) ;
2021-05-07 15:41:39 +02:00
// Change children control size.
Size2i base_tiles_control_size = _compute_base_tiles_control_size ( ) ;
for ( int i = 0 ; i < base_tiles_drawing_root - > get_child_count ( ) ; i + + ) {
Control * control = Object : : cast_to < Control > ( base_tiles_drawing_root - > get_child ( i ) ) ;
if ( control ) {
control - > set_size ( base_tiles_control_size ) ;
}
}
Size2i alternative_control_size = _compute_alternative_tiles_control_size ( ) ;
for ( int i = 0 ; i < alternative_tiles_drawing_root - > get_child_count ( ) ; i + + ) {
Control * control = Object : : cast_to < Control > ( alternative_tiles_drawing_root - > get_child ( i ) ) ;
if ( control ) {
control - > set_size ( alternative_control_size ) ;
}
}
// Update.
base_tiles_draw - > update ( ) ;
base_tiles_texture_grid - > update ( ) ;
base_tiles_shape_grid - > update ( ) ;
base_tiles_dark - > update ( ) ;
alternatives_draw - > update ( ) ;
background_left - > update ( ) ;
background_right - > update ( ) ;
}
float TileAtlasView : : get_zoom ( ) const {
return zoom_widget - > get_zoom ( ) ;
} ;
2021-06-09 20:01:08 +02:00
void TileAtlasView : : set_transform ( float p_zoom , Vector2i p_panning ) {
2021-05-07 15:41:39 +02:00
zoom_widget - > set_zoom ( p_zoom ) ;
2021-06-09 20:01:08 +02:00
panning = p_panning ;
_update_zoom_and_panning ( ) ;
2021-05-07 15:41:39 +02:00
} ;
void TileAtlasView : : set_padding ( Side p_side , int p_padding ) {
ERR_FAIL_COND ( p_padding < 0 ) ;
margin_container_paddings [ p_side ] = p_padding ;
}
Vector2i TileAtlasView : : get_atlas_tile_coords_at_pos ( const Vector2 p_pos ) const {
Ref < Texture2D > texture = tile_set_atlas_source - > get_texture ( ) ;
if ( texture . is_valid ( ) ) {
Vector2i margins = tile_set_atlas_source - > get_margins ( ) ;
Vector2i separation = tile_set_atlas_source - > get_separation ( ) ;
Vector2i texture_region_size = tile_set_atlas_source - > get_texture_region_size ( ) ;
// Compute index in atlas
Vector2 pos = p_pos - margins ;
Vector2i ret = ( pos / ( texture_region_size + separation ) ) . floor ( ) ;
return ret ;
}
2021-05-18 15:40:52 +02:00
return TileSetSource : : INVALID_ATLAS_COORDS ;
2021-05-07 15:41:39 +02:00
}
void TileAtlasView : : _update_alternative_tiles_rect_cache ( ) {
alternative_tiles_rect_cache . clear ( ) ;
Rect2i current ;
for ( int i = 0 ; i < tile_set_atlas_source - > get_tiles_count ( ) ; i + + ) {
Vector2i tile_id = tile_set_atlas_source - > get_tile_id ( i ) ;
int alternatives_count = tile_set_atlas_source - > get_alternative_tiles_count ( tile_id ) ;
Size2i texture_region_size = tile_set_atlas_source - > get_tile_texture_region ( tile_id ) . size ;
int line_height = 0 ;
for ( int j = 1 ; j < alternatives_count ; j + + ) {
int alternative_id = tile_set_atlas_source - > get_alternative_tile_id ( tile_id , j ) ;
TileData * tile_data = Object : : cast_to < TileData > ( tile_set_atlas_source - > get_tile_data ( tile_id , alternative_id ) ) ;
bool transposed = tile_data - > get_transpose ( ) ;
current . size = transposed ? Vector2i ( texture_region_size . y , texture_region_size . x ) : texture_region_size ;
// Update the rect.
if ( ! alternative_tiles_rect_cache . has ( tile_id ) ) {
alternative_tiles_rect_cache [ tile_id ] = Map < int , Rect2i > ( ) ;
}
alternative_tiles_rect_cache [ tile_id ] [ alternative_id ] = current ;
current . position . x + = transposed ? texture_region_size . y : texture_region_size . x ;
line_height = MAX ( line_height , transposed ? texture_region_size . x : texture_region_size . y ) ;
}
current . position . x = 0 ;
current . position . y + = line_height ;
}
}
Vector3i TileAtlasView : : get_alternative_tile_at_pos ( const Vector2 p_pos ) const {
for ( Map < Vector2 , Map < int , Rect2i > > : : Element * E_coords = alternative_tiles_rect_cache . front ( ) ; E_coords ; E_coords = E_coords - > next ( ) ) {
for ( Map < int , Rect2i > : : Element * E_alternative = E_coords - > value ( ) . front ( ) ; E_alternative ; E_alternative = E_alternative - > next ( ) ) {
if ( E_alternative - > value ( ) . has_point ( p_pos ) ) {
return Vector3i ( E_coords - > key ( ) . x , E_coords - > key ( ) . y , E_alternative - > key ( ) ) ;
}
}
}
2021-05-18 15:40:52 +02:00
return Vector3i ( TileSetSource : : INVALID_ATLAS_COORDS . x , TileSetSource : : INVALID_ATLAS_COORDS . y , TileSetSource : : INVALID_TILE_ALTERNATIVE ) ;
2021-05-07 15:41:39 +02:00
}
Rect2i TileAtlasView : : get_alternative_tile_rect ( const Vector2i p_coords , int p_alternative_tile ) {
ERR_FAIL_COND_V_MSG ( ! alternative_tiles_rect_cache . has ( p_coords ) , Rect2i ( ) , vformat ( " No cached rect for tile coords:%s " , p_coords ) ) ;
ERR_FAIL_COND_V_MSG ( ! alternative_tiles_rect_cache [ p_coords ] . has ( p_alternative_tile ) , Rect2i ( ) , vformat ( " No cached rect for tile coords:%s alternative_id:%d " , p_coords , p_alternative_tile ) ) ;
return alternative_tiles_rect_cache [ p_coords ] [ p_alternative_tile ] ;
}
void TileAtlasView : : update ( ) {
2021-06-09 20:01:08 +02:00
base_tiles_draw - > update ( ) ;
2021-05-07 15:41:39 +02:00
base_tiles_texture_grid - > update ( ) ;
base_tiles_shape_grid - > update ( ) ;
base_tiles_dark - > update ( ) ;
alternatives_draw - > update ( ) ;
background_left - > update ( ) ;
background_right - > update ( ) ;
}
2021-06-09 20:01:08 +02:00
void TileAtlasView : : _notification ( int p_what ) {
switch ( p_what ) {
case NOTIFICATION_READY :
2021-07-17 23:22:52 +02:00
button_center_view - > set_icon ( get_theme_icon ( SNAME ( " CenterView " ) , SNAME ( " EditorIcons " ) ) ) ;
2021-06-09 20:01:08 +02:00
break ;
}
}
2021-05-07 15:41:39 +02:00
void TileAtlasView : : _bind_methods ( ) {
2021-06-09 20:01:08 +02:00
ClassDB : : bind_method ( " _gui_input " , & TileAtlasView : : _gui_input ) ;
2021-05-07 15:41:39 +02:00
ADD_SIGNAL ( MethodInfo ( " transform_changed " , PropertyInfo ( Variant : : FLOAT , " zoom " ) , PropertyInfo ( Variant : : VECTOR2 , " scroll " ) ) ) ;
}
TileAtlasView : : TileAtlasView ( ) {
2021-06-09 20:01:08 +02:00
set_texture_filter ( CanvasItem : : TEXTURE_FILTER_NEAREST ) ;
Panel * panel = memnew ( Panel ) ;
panel - > set_clip_contents ( true ) ;
panel - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
panel - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
panel - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
panel - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
add_child ( panel ) ;
2021-05-07 15:41:39 +02:00
2021-06-09 20:01:08 +02:00
// Scrollingsc
2021-05-07 15:41:39 +02:00
zoom_widget = memnew ( EditorZoomWidget ) ;
add_child ( zoom_widget ) ;
zoom_widget - > set_anchors_and_offsets_preset ( Control : : PRESET_TOP_LEFT , Control : : PRESET_MODE_MINSIZE , 2 * EDSCALE ) ;
zoom_widget - > connect ( " zoom_changed " , callable_mp ( this , & TileAtlasView : : _zoom_widget_changed ) . unbind ( 1 ) ) ;
2021-06-09 20:01:08 +02:00
button_center_view = memnew ( Button ) ;
2021-07-17 23:22:52 +02:00
button_center_view - > set_icon ( get_theme_icon ( SNAME ( " CenterView " ) , SNAME ( " EditorIcons " ) ) ) ;
2021-06-09 20:01:08 +02:00
button_center_view - > set_anchors_and_offsets_preset ( Control : : PRESET_TOP_RIGHT , Control : : PRESET_MODE_MINSIZE , 5 ) ;
button_center_view - > connect ( " pressed " , callable_mp ( this , & TileAtlasView : : _center_view ) ) ;
button_center_view - > set_flat ( true ) ;
button_center_view - > set_disabled ( true ) ;
add_child ( button_center_view ) ;
center_container = memnew ( CenterContainer ) ;
center_container - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
center_container - > set_anchors_preset ( Control : : PRESET_CENTER ) ;
2021-05-07 15:41:39 +02:00
center_container - > connect ( " gui_input " , callable_mp ( this , & TileAtlasView : : _gui_input ) ) ;
2021-06-09 20:01:08 +02:00
panel - > add_child ( center_container ) ;
2021-05-07 15:41:39 +02:00
missing_source_label = memnew ( Label ) ;
missing_source_label - > set_text ( TTR ( " No atlas source with a valid texture selected. " ) ) ;
center_container - > add_child ( missing_source_label ) ;
margin_container = memnew ( MarginContainer ) ;
2021-06-09 20:01:08 +02:00
margin_container - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
center_container - > add_child ( margin_container ) ;
hbox = memnew ( HBoxContainer ) ;
2021-06-09 20:01:08 +02:00
hbox - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
hbox - > add_theme_constant_override ( " separation " , 10 ) ;
hbox - > hide ( ) ;
margin_container - > add_child ( hbox ) ;
VBoxContainer * left_vbox = memnew ( VBoxContainer ) ;
2021-06-09 20:01:08 +02:00
left_vbox - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
hbox - > add_child ( left_vbox ) ;
VBoxContainer * right_vbox = memnew ( VBoxContainer ) ;
2021-06-09 20:01:08 +02:00
right_vbox - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
hbox - > add_child ( right_vbox ) ;
// Base tiles.
Label * base_tile_label = memnew ( Label ) ;
2021-06-09 20:01:08 +02:00
base_tile_label - > set_mouse_filter ( Control : : MOUSE_FILTER_PASS ) ;
2021-05-10 23:01:08 +02:00
base_tile_label - > set_text ( TTR ( " Base Tiles " ) ) ;
2021-05-07 15:41:39 +02:00
base_tile_label - > set_align ( Label : : ALIGN_CENTER ) ;
left_vbox - > add_child ( base_tile_label ) ;
base_tiles_root_control = memnew ( Control ) ;
2021-06-09 20:01:08 +02:00
base_tiles_root_control - > set_mouse_filter ( Control : : MOUSE_FILTER_PASS ) ;
2021-05-07 15:41:39 +02:00
base_tiles_root_control - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
base_tiles_root_control - > connect ( " gui_input " , callable_mp ( this , & TileAtlasView : : _base_tiles_root_control_gui_input ) ) ;
left_vbox - > add_child ( base_tiles_root_control ) ;
background_left = memnew ( Control ) ;
2021-06-09 20:01:08 +02:00
background_left - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
background_left - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
background_left - > set_texture_repeat ( TextureRepeat : : TEXTURE_REPEAT_ENABLED ) ;
background_left - > connect ( " draw " , callable_mp ( this , & TileAtlasView : : _draw_background_left ) ) ;
base_tiles_root_control - > add_child ( background_left ) ;
base_tiles_drawing_root = memnew ( Control ) ;
2021-06-09 20:01:08 +02:00
base_tiles_drawing_root - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
base_tiles_drawing_root - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
base_tiles_drawing_root - > set_texture_filter ( TEXTURE_FILTER_NEAREST ) ;
base_tiles_root_control - > add_child ( base_tiles_drawing_root ) ;
base_tiles_draw = memnew ( Control ) ;
2021-06-09 20:01:08 +02:00
base_tiles_draw - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
base_tiles_draw - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
base_tiles_draw - > connect ( " draw " , callable_mp ( this , & TileAtlasView : : _draw_base_tiles ) ) ;
base_tiles_drawing_root - > add_child ( base_tiles_draw ) ;
base_tiles_texture_grid = memnew ( Control ) ;
2021-06-09 20:01:08 +02:00
base_tiles_texture_grid - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
base_tiles_texture_grid - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
base_tiles_texture_grid - > connect ( " draw " , callable_mp ( this , & TileAtlasView : : _draw_base_tiles_texture_grid ) ) ;
base_tiles_drawing_root - > add_child ( base_tiles_texture_grid ) ;
base_tiles_shape_grid = memnew ( Control ) ;
2021-06-09 20:01:08 +02:00
base_tiles_shape_grid - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
base_tiles_shape_grid - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
base_tiles_shape_grid - > connect ( " draw " , callable_mp ( this , & TileAtlasView : : _draw_base_tiles_shape_grid ) ) ;
base_tiles_drawing_root - > add_child ( base_tiles_shape_grid ) ;
base_tiles_dark = memnew ( Control ) ;
2021-06-09 20:01:08 +02:00
base_tiles_dark - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
base_tiles_dark - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
base_tiles_dark - > connect ( " draw " , callable_mp ( this , & TileAtlasView : : _draw_base_tiles_dark ) ) ;
base_tiles_drawing_root - > add_child ( base_tiles_dark ) ;
// Alternative tiles.
Label * alternative_tiles_label = memnew ( Label ) ;
2021-06-09 20:01:08 +02:00
alternative_tiles_label - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-10 23:01:08 +02:00
alternative_tiles_label - > set_text ( TTR ( " Alternative Tiles " ) ) ;
2021-05-07 15:41:39 +02:00
alternative_tiles_label - > set_align ( Label : : ALIGN_CENTER ) ;
right_vbox - > add_child ( alternative_tiles_label ) ;
alternative_tiles_root_control = memnew ( Control ) ;
2021-06-09 20:01:08 +02:00
alternative_tiles_root_control - > set_mouse_filter ( Control : : MOUSE_FILTER_PASS ) ;
2021-05-07 15:41:39 +02:00
alternative_tiles_root_control - > connect ( " gui_input " , callable_mp ( this , & TileAtlasView : : _alternative_tiles_root_control_gui_input ) ) ;
right_vbox - > add_child ( alternative_tiles_root_control ) ;
background_right = memnew ( Control ) ;
2021-06-09 20:01:08 +02:00
background_right - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-05-07 15:41:39 +02:00
background_right - > set_texture_repeat ( TextureRepeat : : TEXTURE_REPEAT_ENABLED ) ;
background_right - > connect ( " draw " , callable_mp ( this , & TileAtlasView : : _draw_background_right ) ) ;
2021-06-09 20:01:08 +02:00
2021-05-07 15:41:39 +02:00
alternative_tiles_root_control - > add_child ( background_right ) ;
alternative_tiles_drawing_root = memnew ( Control ) ;
alternative_tiles_drawing_root - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-06-09 20:01:08 +02:00
alternative_tiles_drawing_root - > set_texture_filter ( TEXTURE_FILTER_NEAREST ) ;
2021-05-07 15:41:39 +02:00
alternative_tiles_root_control - > add_child ( alternative_tiles_drawing_root ) ;
alternatives_draw = memnew ( Control ) ;
alternatives_draw - > set_mouse_filter ( Control : : MOUSE_FILTER_IGNORE ) ;
2021-06-09 20:01:08 +02:00
alternatives_draw - > connect ( " draw " , callable_mp ( this , & TileAtlasView : : _draw_alternatives ) ) ;
2021-05-07 15:41:39 +02:00
alternative_tiles_drawing_root - > add_child ( alternatives_draw ) ;
}