2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* texture_progress.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
/*************************************************************************/
2022-01-13 09:45:09 +01:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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 "texture_progress.h"
2018-09-11 18:13:45 +02:00
# include "core/engine.h"
2017-08-19 01:02:56 +02:00
2017-03-05 16:44:50 +01:00
void TextureProgress : : set_under_texture ( const Ref < Texture > & p_texture ) {
under = p_texture ;
2014-02-10 02:10:30 +01:00
update ( ) ;
minimum_size_changed ( ) ;
}
2017-03-05 16:44:50 +01:00
Ref < Texture > TextureProgress : : get_under_texture ( ) const {
2014-02-10 02:10:30 +01:00
return under ;
}
2017-03-05 16:44:50 +01:00
void TextureProgress : : set_over_texture ( const Ref < Texture > & p_texture ) {
over = p_texture ;
2014-02-10 02:10:30 +01:00
update ( ) ;
2017-01-21 23:00:25 +01:00
if ( under . is_null ( ) ) {
minimum_size_changed ( ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Ref < Texture > TextureProgress : : get_over_texture ( ) const {
2014-02-10 02:10:30 +01:00
return over ;
}
2017-08-21 06:01:06 +02:00
void TextureProgress : : set_stretch_margin ( Margin p_margin , int p_size ) {
2018-10-04 09:17:59 +02:00
ERR_FAIL_INDEX ( ( int ) p_margin , 4 ) ;
2017-08-21 06:01:06 +02:00
stretch_margin [ p_margin ] = p_size ;
update ( ) ;
minimum_size_changed ( ) ;
}
int TextureProgress : : get_stretch_margin ( Margin p_margin ) const {
2018-10-04 09:17:59 +02:00
ERR_FAIL_INDEX_V ( ( int ) p_margin , 4 , 0 ) ;
2017-08-21 06:01:06 +02:00
return stretch_margin [ p_margin ] ;
}
void TextureProgress : : set_nine_patch_stretch ( bool p_stretch ) {
nine_patch_stretch = p_stretch ;
update ( ) ;
minimum_size_changed ( ) ;
}
bool TextureProgress : : get_nine_patch_stretch ( ) const {
return nine_patch_stretch ;
}
2014-02-10 02:10:30 +01:00
Size2 TextureProgress : : get_minimum_size ( ) const {
2021-05-05 12:44:11 +02:00
if ( nine_patch_stretch ) {
2017-08-21 06:01:06 +02:00
return Size2 ( stretch_margin [ MARGIN_LEFT ] + stretch_margin [ MARGIN_RIGHT ] , stretch_margin [ MARGIN_TOP ] + stretch_margin [ MARGIN_BOTTOM ] ) ;
2021-05-05 12:44:11 +02:00
} else if ( under . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
return under - > get_size ( ) ;
2021-05-05 12:44:11 +02:00
} else if ( over . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
return over - > get_size ( ) ;
2021-05-05 12:44:11 +02:00
} else if ( progress . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
return progress - > get_size ( ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
return Size2 ( 1 , 1 ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void TextureProgress : : set_progress_texture ( const Ref < Texture > & p_texture ) {
progress = p_texture ;
2014-02-10 02:10:30 +01:00
update ( ) ;
minimum_size_changed ( ) ;
}
2017-03-05 16:44:50 +01:00
Ref < Texture > TextureProgress : : get_progress_texture ( ) const {
2014-02-10 02:10:30 +01:00
return progress ;
}
2021-03-09 22:24:02 +01:00
void TextureProgress : : set_progress_offset ( Point2 p_offset ) {
progress_offset = p_offset ;
update ( ) ;
}
Point2 TextureProgress : : get_progress_offset ( ) const {
return progress_offset ;
}
2018-04-01 18:22:51 +02:00
void TextureProgress : : set_tint_under ( const Color & p_tint ) {
tint_under = p_tint ;
update ( ) ;
}
Color TextureProgress : : get_tint_under ( ) const {
return tint_under ;
}
void TextureProgress : : set_tint_progress ( const Color & p_tint ) {
tint_progress = p_tint ;
update ( ) ;
}
Color TextureProgress : : get_tint_progress ( ) const {
return tint_progress ;
}
void TextureProgress : : set_tint_over ( const Color & p_tint ) {
tint_over = p_tint ;
update ( ) ;
}
Color TextureProgress : : get_tint_over ( ) const {
return tint_over ;
}
2015-10-18 04:37:39 +02:00
Point2 TextureProgress : : unit_val_to_uv ( float val ) {
2021-05-05 12:44:11 +02:00
if ( progress . is_null ( ) ) {
2015-10-18 04:37:39 +02:00
return Point2 ( ) ;
2021-05-05 12:44:11 +02:00
}
2015-10-18 04:37:39 +02:00
2021-05-05 12:44:11 +02:00
if ( val < 0 ) {
2017-03-05 16:44:50 +01:00
val + = 1 ;
2021-05-05 12:44:11 +02:00
}
if ( val > 1 ) {
2017-03-05 16:44:50 +01:00
val - = 1 ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
Point2 p = get_relative_center ( ) ;
2018-03-10 20:51:42 +01:00
// Minimal version of Liang-Barsky clipping algorithm
float angle = ( val * Math_TAU ) - Math_PI * 0.5 ;
Point2 dir = Vector2 ( Math : : cos ( angle ) , Math : : sin ( angle ) ) ;
float t1 = 1.0 ;
2018-10-04 18:54:20 +02:00
float cp = 0 ;
float cq = 0 ;
float cr = 0 ;
2018-03-10 20:51:42 +01:00
float edgeLeft = 0.0 ;
float edgeRight = 1.0 ;
float edgeBottom = 0.0 ;
float edgeTop = 1.0 ;
for ( int edge = 0 ; edge < 4 ; edge + + ) {
if ( edge = = 0 ) {
2021-05-05 12:44:11 +02:00
if ( dir . x > 0 ) {
2018-03-10 20:51:42 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2018-03-10 20:51:42 +01:00
cq = - ( edgeLeft - p . x ) ;
2019-02-16 21:02:29 +01:00
dir . x * = 2.0 * cq ;
cp = - dir . x ;
2018-03-10 20:51:42 +01:00
} else if ( edge = = 1 ) {
2021-05-05 12:44:11 +02:00
if ( dir . x < 0 ) {
2018-03-10 20:51:42 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2018-03-10 20:51:42 +01:00
cq = ( edgeRight - p . x ) ;
2019-02-16 21:02:29 +01:00
dir . x * = 2.0 * cq ;
cp = dir . x ;
2018-03-10 20:51:42 +01:00
} else if ( edge = = 2 ) {
2021-05-05 12:44:11 +02:00
if ( dir . y > 0 ) {
2018-03-10 20:51:42 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2018-03-10 20:51:42 +01:00
cq = - ( edgeBottom - p . y ) ;
2019-02-16 21:02:29 +01:00
dir . y * = 2.0 * cq ;
cp = - dir . y ;
2018-03-10 20:51:42 +01:00
} else if ( edge = = 3 ) {
2021-05-05 12:44:11 +02:00
if ( dir . y < 0 ) {
2018-03-10 20:51:42 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2018-03-10 20:51:42 +01:00
cq = ( edgeTop - p . y ) ;
2019-02-16 21:02:29 +01:00
dir . y * = 2.0 * cq ;
cp = dir . y ;
2018-03-10 20:51:42 +01:00
}
cr = cq / cp ;
2021-05-05 12:44:11 +02:00
if ( cr > = 0 & & cr < t1 ) {
2018-03-10 20:51:42 +01:00
t1 = cr ;
2021-05-05 12:44:11 +02:00
}
2018-03-10 20:51:42 +01:00
}
return ( p + t1 * dir ) ;
2015-10-18 04:37:39 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Point2 TextureProgress : : get_relative_center ( ) {
2021-05-05 12:44:11 +02:00
if ( progress . is_null ( ) ) {
2015-10-18 04:37:39 +02:00
return Point2 ( ) ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
Point2 p = progress - > get_size ( ) / 2 ;
p + = rad_center_off ;
p . x / = progress - > get_width ( ) ;
p . y / = progress - > get_height ( ) ;
p . x = CLAMP ( p . x , 0 , 1 ) ;
p . y = CLAMP ( p . y , 0 , 1 ) ;
2015-10-18 04:37:39 +02:00
return p ;
}
2014-02-10 02:10:30 +01:00
2018-03-21 19:55:39 +01:00
void TextureProgress : : draw_nine_patch_stretched ( const Ref < Texture > & p_texture , FillMode p_mode , double p_ratio , const Color & p_modulate ) {
2017-08-21 06:01:06 +02:00
Vector2 texture_size = p_texture - > get_size ( ) ;
Vector2 topleft = Vector2 ( stretch_margin [ MARGIN_LEFT ] , stretch_margin [ MARGIN_TOP ] ) ;
Vector2 bottomright = Vector2 ( stretch_margin [ MARGIN_RIGHT ] , stretch_margin [ MARGIN_BOTTOM ] ) ;
Rect2 src_rect = Rect2 ( Point2 ( ) , texture_size ) ;
Rect2 dst_rect = Rect2 ( Point2 ( ) , get_size ( ) ) ;
if ( p_ratio < 1.0 ) {
// Drawing a partially-filled 9-patch is a little tricky -
// texture is divided by 3 sections toward fill direction,
2018-02-21 17:30:55 +01:00
// then middle section is stretching while the other two aren't.
2017-08-21 06:01:06 +02:00
double width_total = 0.0 ;
double width_texture = 0.0 ;
double first_section_size = 0.0 ;
double last_section_size = 0.0 ;
2021-02-08 05:30:04 +01:00
switch ( p_mode ) {
case FILL_LEFT_TO_RIGHT : {
2017-08-21 06:01:06 +02:00
width_total = dst_rect . size . x ;
width_texture = texture_size . x ;
first_section_size = topleft . x ;
last_section_size = bottomright . x ;
} break ;
2021-02-08 05:30:04 +01:00
case FILL_RIGHT_TO_LEFT : {
width_total = dst_rect . size . x ;
width_texture = texture_size . x ;
// In contrast to `FILL_LEFT_TO_RIGHT`, `first_section_size` and `last_section_size` should switch value.
first_section_size = bottomright . x ;
last_section_size = topleft . x ;
} break ;
case FILL_TOP_TO_BOTTOM : {
2017-08-21 06:01:06 +02:00
width_total = dst_rect . size . y ;
width_texture = texture_size . y ;
first_section_size = topleft . y ;
last_section_size = bottomright . y ;
} break ;
2021-02-08 05:30:04 +01:00
case FILL_BOTTOM_TO_TOP : {
width_total = dst_rect . size . y ;
width_texture = texture_size . y ;
// Similar to `FILL_RIGHT_TO_LEFT`.
first_section_size = bottomright . y ;
last_section_size = topleft . y ;
} break ;
2018-09-26 13:13:56 +02:00
case FILL_BILINEAR_LEFT_AND_RIGHT : {
2021-02-08 05:30:04 +01:00
width_total = dst_rect . size . x ;
width_texture = texture_size . x ;
first_section_size = topleft . x ;
last_section_size = bottomright . x ;
2018-09-26 13:13:56 +02:00
} break ;
case FILL_BILINEAR_TOP_AND_BOTTOM : {
2021-02-08 05:30:04 +01:00
width_total = dst_rect . size . y ;
width_texture = texture_size . y ;
first_section_size = topleft . y ;
last_section_size = bottomright . y ;
2018-09-26 13:13:56 +02:00
} break ;
case FILL_CLOCKWISE :
case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE :
case FILL_COUNTER_CLOCKWISE : {
2021-02-08 05:30:04 +01:00
// Those modes are circular, not relevant for nine patch.
2018-09-26 13:13:56 +02:00
} break ;
2021-02-08 05:30:04 +01:00
case FILL_MODE_MAX :
break ;
2017-08-21 06:01:06 +02:00
}
double width_filled = width_total * p_ratio ;
double middle_section_size = MAX ( 0.0 , width_texture - first_section_size - last_section_size ) ;
2021-02-08 05:30:04 +01:00
// Maximum middle texture size.
double max_middle_texture_size = middle_section_size ;
// Maximum real middle texture size.
double max_middle_real_size = MAX ( 0.0 , width_total - ( first_section_size + last_section_size ) ) ;
switch ( p_mode ) {
case FILL_BILINEAR_LEFT_AND_RIGHT :
case FILL_BILINEAR_TOP_AND_BOTTOM : {
last_section_size = MAX ( 0.0 , last_section_size - ( width_total - width_filled ) * 0.5 ) ;
first_section_size = MAX ( 0.0 , first_section_size - ( width_total - width_filled ) * 0.5 ) ;
// When `width_filled` increases, `middle_section_size` only increases when either of `first_section_size` and `last_section_size` is zero.
// Also, it should always be smaller than or equal to `(width_total - (first_section_size + last_section_size))`.
double real_middle_size = width_filled - first_section_size - last_section_size ;
middle_section_size * = MIN ( max_middle_real_size , real_middle_size ) / max_middle_real_size ;
width_texture = MIN ( width_texture , first_section_size + middle_section_size + last_section_size ) ;
} break ;
case FILL_MODE_MAX :
break ;
default : {
middle_section_size * = MIN ( 1.0 , ( MAX ( 0.0 , width_filled - first_section_size ) / MAX ( 1.0 , width_total - first_section_size - last_section_size ) ) ) ;
last_section_size = MAX ( 0.0 , last_section_size - ( width_total - width_filled ) ) ;
first_section_size = MIN ( first_section_size , width_filled ) ;
width_texture = MIN ( width_texture , first_section_size + middle_section_size + last_section_size ) ;
}
}
2017-08-21 06:01:06 +02:00
2021-02-08 05:30:04 +01:00
switch ( p_mode ) {
2017-08-21 06:01:06 +02:00
case FILL_LEFT_TO_RIGHT : {
src_rect . size . x = width_texture ;
dst_rect . size . x = width_filled ;
2019-02-19 09:28:32 +01:00
topleft . x = first_section_size ;
2017-08-21 06:01:06 +02:00
bottomright . x = last_section_size ;
} break ;
case FILL_RIGHT_TO_LEFT : {
src_rect . position . x + = src_rect . size . x - width_texture ;
src_rect . size . x = width_texture ;
dst_rect . position . x + = width_total - width_filled ;
dst_rect . size . x = width_filled ;
topleft . x = last_section_size ;
2019-02-19 09:28:32 +01:00
bottomright . x = first_section_size ;
2017-08-21 06:01:06 +02:00
} break ;
case FILL_TOP_TO_BOTTOM : {
src_rect . size . y = width_texture ;
dst_rect . size . y = width_filled ;
bottomright . y = last_section_size ;
2019-02-19 09:28:32 +01:00
topleft . y = first_section_size ;
2017-08-21 06:01:06 +02:00
} break ;
case FILL_BOTTOM_TO_TOP : {
src_rect . position . y + = src_rect . size . y - width_texture ;
src_rect . size . y = width_texture ;
dst_rect . position . y + = width_total - width_filled ;
dst_rect . size . y = width_filled ;
topleft . y = last_section_size ;
2019-02-19 09:28:32 +01:00
bottomright . y = first_section_size ;
2017-08-21 06:01:06 +02:00
} break ;
2018-09-26 13:13:56 +02:00
case FILL_BILINEAR_LEFT_AND_RIGHT : {
2021-02-08 05:30:04 +01:00
double center_mapped_from_real_width = ( width_total * 0.5 - topleft . x ) / max_middle_real_size * max_middle_texture_size + topleft . x ;
2021-10-14 05:15:05 +02:00
double drift_from_unscaled_center = 0 ;
if ( bottomright . y ! = topleft . y ) { // To avoid division by zero.
drift_from_unscaled_center = ( src_rect . size . x * 0.5 - center_mapped_from_real_width ) * ( last_section_size - first_section_size ) / ( bottomright . x - topleft . x ) ;
}
2021-02-08 05:30:04 +01:00
src_rect . position . x + = center_mapped_from_real_width + drift_from_unscaled_center - width_texture * 0.5 ;
src_rect . size . x = width_texture ;
dst_rect . position . x + = ( width_total - width_filled ) * 0.5 ;
dst_rect . size . x = width_filled ;
topleft . x = first_section_size ;
bottomright . x = last_section_size ;
2018-09-26 13:13:56 +02:00
} break ;
case FILL_BILINEAR_TOP_AND_BOTTOM : {
2021-02-08 05:30:04 +01:00
double center_mapped_from_real_width = ( width_total * 0.5 - topleft . y ) / max_middle_real_size * max_middle_texture_size + topleft . y ;
2021-10-14 05:15:05 +02:00
double drift_from_unscaled_center = 0 ;
if ( bottomright . y ! = topleft . y ) { // To avoid division by zero.
drift_from_unscaled_center = ( src_rect . size . y * 0.5 - center_mapped_from_real_width ) * ( last_section_size - first_section_size ) / ( bottomright . y - topleft . y ) ;
}
2021-02-08 05:30:04 +01:00
src_rect . position . y + = center_mapped_from_real_width + drift_from_unscaled_center - width_texture * 0.5 ;
src_rect . size . y = width_texture ;
dst_rect . position . y + = ( width_total - width_filled ) * 0.5 ;
dst_rect . size . y = width_filled ;
topleft . y = first_section_size ;
bottomright . y = last_section_size ;
2018-09-26 13:13:56 +02:00
} break ;
case FILL_CLOCKWISE :
case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE :
case FILL_COUNTER_CLOCKWISE : {
2021-02-08 05:30:04 +01:00
// Those modes are circular, not relevant for nine patch.
2018-09-26 13:13:56 +02:00
} break ;
2021-02-08 05:30:04 +01:00
case FILL_MODE_MAX :
break ;
2017-08-21 06:01:06 +02:00
}
}
2021-03-09 22:24:02 +01:00
if ( p_texture = = progress ) {
dst_rect . position + = progress_offset ;
}
2018-08-18 17:37:50 +02:00
p_texture - > get_rect_region ( dst_rect , src_rect , dst_rect , src_rect ) ;
2017-08-21 06:01:06 +02:00
RID ci = get_canvas_item ( ) ;
2018-03-21 19:55:39 +01:00
VS : : get_singleton ( ) - > canvas_item_add_nine_patch ( ci , dst_rect , src_rect , p_texture - > get_rid ( ) , topleft , bottomright , VS : : NINE_PATCH_STRETCH , VS : : NINE_PATCH_STRETCH , true , p_modulate ) ;
2017-08-21 06:01:06 +02:00
}
2017-03-05 16:44:50 +01:00
void TextureProgress : : _notification ( int p_what ) {
switch ( p_what ) {
2014-02-10 02:10:30 +01:00
case NOTIFICATION_DRAW : {
2021-02-08 05:30:04 +01:00
if ( nine_patch_stretch & & ( mode = = FILL_LEFT_TO_RIGHT | | mode = = FILL_RIGHT_TO_LEFT | | mode = = FILL_TOP_TO_BOTTOM | | mode = = FILL_BOTTOM_TO_TOP | | mode = = FILL_BILINEAR_LEFT_AND_RIGHT | | mode = = FILL_BILINEAR_TOP_AND_BOTTOM ) ) {
2017-08-21 06:01:06 +02:00
if ( under . is_valid ( ) ) {
2021-02-08 05:30:04 +01:00
draw_nine_patch_stretched ( under , mode , 1.0 , tint_under ) ;
2017-08-21 06:01:06 +02:00
}
if ( progress . is_valid ( ) ) {
2018-04-01 18:22:51 +02:00
draw_nine_patch_stretched ( progress , mode , get_as_ratio ( ) , tint_progress ) ;
2017-08-21 06:01:06 +02:00
}
if ( over . is_valid ( ) ) {
2021-02-08 05:30:04 +01:00
draw_nine_patch_stretched ( over , mode , 1.0 , tint_over ) ;
2017-08-21 06:01:06 +02:00
}
} else {
2021-05-05 12:44:11 +02:00
if ( under . is_valid ( ) ) {
2021-02-08 05:30:04 +01:00
switch ( mode ) {
case FILL_CLOCKWISE :
case FILL_COUNTER_CLOCKWISE :
case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE : {
if ( nine_patch_stretch ) {
Rect2 region = Rect2 ( Point2 ( ) , get_size ( ) ) ;
draw_texture_rect ( under , region , false , tint_under ) ;
} else {
draw_texture ( under , Point2 ( ) , tint_under ) ;
}
} break ;
case FILL_MODE_MAX :
break ;
default :
draw_texture ( under , Point2 ( ) , tint_under ) ;
}
2021-05-05 12:44:11 +02:00
}
2017-08-21 06:01:06 +02:00
if ( progress . is_valid ( ) ) {
Size2 s = progress - > get_size ( ) ;
switch ( mode ) {
case FILL_LEFT_TO_RIGHT : {
2021-03-09 22:24:02 +01:00
Rect2 region = Rect2 ( progress_offset , Size2 ( s . x * get_as_ratio ( ) , s . y ) ) ;
Rect2 source = Rect2 ( Point2 ( ) , Size2 ( s . x * get_as_ratio ( ) , s . y ) ) ;
draw_texture_rect_region ( progress , region , source , tint_progress ) ;
2017-08-21 06:01:06 +02:00
} break ;
case FILL_RIGHT_TO_LEFT : {
2021-03-09 22:24:02 +01:00
Rect2 region = Rect2 ( progress_offset + Point2 ( s . x - s . x * get_as_ratio ( ) , 0 ) , Size2 ( s . x * get_as_ratio ( ) , s . y ) ) ;
Rect2 source = Rect2 ( Point2 ( s . x - s . x * get_as_ratio ( ) , 0 ) , Size2 ( s . x * get_as_ratio ( ) , s . y ) ) ;
draw_texture_rect_region ( progress , region , source , tint_progress ) ;
2017-08-21 06:01:06 +02:00
} break ;
case FILL_TOP_TO_BOTTOM : {
2021-03-09 22:24:02 +01:00
Rect2 region = Rect2 ( progress_offset + Point2 ( ) , Size2 ( s . x , s . y * get_as_ratio ( ) ) ) ;
Rect2 source = Rect2 ( Point2 ( ) , Size2 ( s . x , s . y * get_as_ratio ( ) ) ) ;
draw_texture_rect_region ( progress , region , source , tint_progress ) ;
2017-08-21 06:01:06 +02:00
} break ;
case FILL_BOTTOM_TO_TOP : {
2021-03-09 22:24:02 +01:00
Rect2 region = Rect2 ( progress_offset + Point2 ( 0 , s . y - s . y * get_as_ratio ( ) ) , Size2 ( s . x , s . y * get_as_ratio ( ) ) ) ;
Rect2 source = Rect2 ( Point2 ( 0 , s . y - s . y * get_as_ratio ( ) ) , Size2 ( s . x , s . y * get_as_ratio ( ) ) ) ;
draw_texture_rect_region ( progress , region , source , tint_progress ) ;
2017-08-21 06:01:06 +02:00
} break ;
case FILL_CLOCKWISE :
2018-05-11 19:44:05 +02:00
case FILL_COUNTER_CLOCKWISE :
case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE : {
2021-05-05 12:44:11 +02:00
if ( nine_patch_stretch ) {
2019-09-26 11:46:07 +02:00
s = get_size ( ) ;
2021-05-05 12:44:11 +02:00
}
2019-09-26 11:46:07 +02:00
2017-08-21 06:01:06 +02:00
float val = get_as_ratio ( ) * rad_max_degrees / 360 ;
if ( val = = 1 ) {
2021-03-09 22:24:02 +01:00
Rect2 region = Rect2 ( progress_offset , s ) ;
2021-10-28 12:03:59 +02:00
Rect2 source = Rect2 ( Point2 ( ) , progress - > get_size ( ) ) ;
2021-03-09 22:24:02 +01:00
draw_texture_rect_region ( progress , region , source , tint_progress ) ;
2017-08-21 06:01:06 +02:00
} else if ( val ! = 0 ) {
Array pts ;
2018-05-11 19:44:05 +02:00
float direction = mode = = FILL_COUNTER_CLOCKWISE ? - 1 : 1 ;
float start ;
if ( mode = = FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE ) {
start = rad_init_angle / 360 - val / 2 ;
} else {
start = rad_init_angle / 360 ;
}
2017-08-21 06:01:06 +02:00
float end = start + direction * val ;
float from = MIN ( start , end ) ;
float to = MAX ( start , end ) ;
2021-10-28 12:03:59 +02:00
pts . append ( from ) ;
for ( float corner = Math : : floor ( from * 4 + 0.5 ) * 0.25 + 0.125 ; corner < to ; corner + = 0.25 ) {
pts . append ( corner ) ;
2021-05-05 12:44:11 +02:00
}
2021-10-28 12:03:59 +02:00
pts . append ( to ) ;
2022-11-04 11:24:47 +01:00
Ref < AtlasTexture > atlas_progress = progress ;
bool valid_atlas_progress = atlas_progress . is_valid ( ) & & atlas_progress - > get_atlas ( ) . is_valid ( ) ;
Rect2 region_rect ;
Size2 atlas_size ;
if ( valid_atlas_progress ) {
region_rect = atlas_progress - > get_region ( ) ;
atlas_size = atlas_progress - > get_atlas ( ) - > get_size ( ) ;
}
2017-08-21 06:01:06 +02:00
Vector < Point2 > uvs ;
Vector < Point2 > points ;
for ( int i = 0 ; i < pts . size ( ) ; i + + ) {
Point2 uv = unit_val_to_uv ( pts [ i ] ) ;
2021-05-05 12:44:11 +02:00
if ( uvs . find ( uv ) > = 0 ) {
2017-08-21 06:01:06 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2021-03-09 22:24:02 +01:00
points . push_back ( progress_offset + Point2 ( uv . x * s . x , uv . y * s . y ) ) ;
2022-11-04 11:24:47 +01:00
if ( valid_atlas_progress ) {
uv . x = Math : : range_lerp ( uv . x , 0 , 1 , region_rect . position . x / atlas_size . x , ( region_rect . position . x + region_rect . size . x ) / atlas_size . x ) ;
uv . y = Math : : range_lerp ( uv . y , 0 , 1 , region_rect . position . y / atlas_size . y , ( region_rect . position . y + region_rect . size . y ) / atlas_size . y ) ;
}
uvs . push_back ( uv ) ;
}
Point2 center_point = get_relative_center ( ) ;
points . push_back ( progress_offset + s * center_point ) ;
if ( valid_atlas_progress ) {
center_point . x = Math : : range_lerp ( center_point . x , 0 , 1 , region_rect . position . x / atlas_size . x , ( region_rect . position . x + region_rect . size . x ) / atlas_size . x ) ;
center_point . y = Math : : range_lerp ( center_point . y , 0 , 1 , region_rect . position . y / atlas_size . y , ( region_rect . position . y + region_rect . size . y ) / atlas_size . y ) ;
2017-08-21 06:01:06 +02:00
}
2022-11-04 11:24:47 +01:00
uvs . push_back ( center_point ) ;
2018-03-21 19:55:39 +01:00
Vector < Color > colors ;
2018-04-01 18:22:51 +02:00
colors . push_back ( tint_progress ) ;
2018-03-21 19:55:39 +01:00
draw_polygon ( points , colors , uvs , progress ) ;
2017-08-21 06:01:06 +02:00
}
2021-10-28 12:03:59 +02:00
// Draw a reference cross.
2017-08-21 06:01:06 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2019-09-26 11:46:07 +02:00
Point2 p ;
2021-05-05 12:44:11 +02:00
if ( nine_patch_stretch ) {
2019-09-26 11:46:07 +02:00
p = get_size ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2019-09-26 11:46:07 +02:00
p = progress - > get_size ( ) ;
2021-05-05 12:44:11 +02:00
}
2019-09-26 11:46:07 +02:00
2021-11-27 08:20:39 +01:00
p * = get_relative_center ( ) ;
p + = progress_offset ;
2017-08-21 06:01:06 +02:00
p = p . floor ( ) ;
draw_line ( p - Point2 ( 8 , 0 ) , p + Point2 ( 8 , 0 ) , Color ( 0.9 , 0.5 , 0.5 ) , 2 ) ;
draw_line ( p - Point2 ( 0 , 8 ) , p + Point2 ( 0 , 8 ) , Color ( 0.9 , 0.5 , 0.5 ) , 2 ) ;
2017-03-05 16:44:50 +01:00
}
2017-08-21 06:01:06 +02:00
} break ;
2018-05-11 19:44:05 +02:00
case FILL_BILINEAR_LEFT_AND_RIGHT : {
2021-03-09 22:24:02 +01:00
Rect2 region = Rect2 ( progress_offset + Point2 ( s . x / 2 - s . x * get_as_ratio ( ) / 2 , 0 ) , Size2 ( s . x * get_as_ratio ( ) , s . y ) ) ;
Rect2 source = Rect2 ( Point2 ( s . x / 2 - s . x * get_as_ratio ( ) / 2 , 0 ) , Size2 ( s . x * get_as_ratio ( ) , s . y ) ) ;
draw_texture_rect_region ( progress , region , source , tint_progress ) ;
2018-05-11 19:44:05 +02:00
} break ;
case FILL_BILINEAR_TOP_AND_BOTTOM : {
2021-03-09 22:24:02 +01:00
Rect2 region = Rect2 ( progress_offset + Point2 ( 0 , s . y / 2 - s . y * get_as_ratio ( ) / 2 ) , Size2 ( s . x , s . y * get_as_ratio ( ) ) ) ;
Rect2 source = Rect2 ( Point2 ( 0 , s . y / 2 - s . y * get_as_ratio ( ) / 2 ) , Size2 ( s . x , s . y * get_as_ratio ( ) ) ) ;
draw_texture_rect_region ( progress , region , source , tint_progress ) ;
2018-05-11 19:44:05 +02:00
} break ;
2021-02-08 05:30:04 +01:00
case FILL_MODE_MAX :
break ;
2017-08-21 06:01:06 +02:00
default :
2021-03-09 22:24:02 +01:00
draw_texture_rect_region ( progress , Rect2 ( progress_offset , Size2 ( s . x * get_as_ratio ( ) , s . y ) ) , Rect2 ( Point2 ( ) , Size2 ( s . x * get_as_ratio ( ) , s . y ) ) , tint_progress ) ;
2017-08-21 06:01:06 +02:00
}
2015-10-18 04:37:39 +02:00
}
2021-05-05 12:44:11 +02:00
if ( over . is_valid ( ) ) {
2021-02-08 05:30:04 +01:00
switch ( mode ) {
case FILL_CLOCKWISE :
case FILL_COUNTER_CLOCKWISE :
case FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE : {
if ( nine_patch_stretch ) {
Rect2 region = Rect2 ( Point2 ( ) , get_size ( ) ) ;
draw_texture_rect ( over , region , false , tint_over ) ;
} else {
draw_texture ( over , Point2 ( ) , tint_over ) ;
}
} break ;
case FILL_MODE_MAX :
break ;
default :
draw_texture ( over , Point2 ( ) , tint_over ) ;
}
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
} break ;
}
}
2017-03-05 16:44:50 +01:00
void TextureProgress : : set_fill_mode ( int p_fill ) {
2021-02-08 05:30:04 +01:00
ERR_FAIL_INDEX ( p_fill , FILL_MODE_MAX ) ;
2017-03-05 16:44:50 +01:00
mode = ( FillMode ) p_fill ;
2015-10-18 04:37:39 +02:00
update ( ) ;
}
2017-03-05 16:44:50 +01:00
int TextureProgress : : get_fill_mode ( ) {
2015-10-18 04:37:39 +02:00
return mode ;
}
2017-03-05 16:44:50 +01:00
void TextureProgress : : set_radial_initial_angle ( float p_angle ) {
2021-05-05 12:44:11 +02:00
while ( p_angle > 360 ) {
2017-03-05 16:44:50 +01:00
p_angle - = 360 ;
2021-05-05 12:44:11 +02:00
}
while ( p_angle < 0 ) {
2017-03-05 16:44:50 +01:00
p_angle + = 360 ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
rad_init_angle = p_angle ;
2015-10-18 04:37:39 +02:00
update ( ) ;
}
2017-03-05 16:44:50 +01:00
float TextureProgress : : get_radial_initial_angle ( ) {
2015-10-18 04:37:39 +02:00
return rad_init_angle ;
}
2017-03-05 16:44:50 +01:00
void TextureProgress : : set_fill_degrees ( float p_angle ) {
rad_max_degrees = CLAMP ( p_angle , 0 , 360 ) ;
2015-10-18 06:21:53 +02:00
update ( ) ;
}
2017-03-05 16:44:50 +01:00
float TextureProgress : : get_fill_degrees ( ) {
2015-10-18 06:21:53 +02:00
return rad_max_degrees ;
}
2017-03-05 16:44:50 +01:00
void TextureProgress : : set_radial_center_offset ( const Point2 & p_off ) {
rad_center_off = p_off ;
2015-10-18 04:37:39 +02:00
update ( ) ;
}
2017-03-05 16:44:50 +01:00
Point2 TextureProgress : : get_radial_center_offset ( ) {
2015-10-18 04:37:39 +02:00
return rad_center_off ;
}
2014-02-10 02:10:30 +01:00
void TextureProgress : : _bind_methods ( ) {
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_under_texture " , " tex " ) , & TextureProgress : : set_under_texture ) ;
ClassDB : : bind_method ( D_METHOD ( " get_under_texture " ) , & TextureProgress : : get_under_texture ) ;
2014-02-10 02:10:30 +01:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_progress_texture " , " tex " ) , & TextureProgress : : set_progress_texture ) ;
ClassDB : : bind_method ( D_METHOD ( " get_progress_texture " ) , & TextureProgress : : get_progress_texture ) ;
2014-02-10 02:10:30 +01:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_over_texture " , " tex " ) , & TextureProgress : : set_over_texture ) ;
ClassDB : : bind_method ( D_METHOD ( " get_over_texture " ) , & TextureProgress : : get_over_texture ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_fill_mode " , " mode " ) , & TextureProgress : : set_fill_mode ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_fill_mode " ) , & TextureProgress : : get_fill_mode ) ;
2015-10-18 04:37:39 +02:00
2018-04-01 18:22:51 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_tint_under " , " tint " ) , & TextureProgress : : set_tint_under ) ;
ClassDB : : bind_method ( D_METHOD ( " get_tint_under " ) , & TextureProgress : : get_tint_under ) ;
ClassDB : : bind_method ( D_METHOD ( " set_tint_progress " , " tint " ) , & TextureProgress : : set_tint_progress ) ;
ClassDB : : bind_method ( D_METHOD ( " get_tint_progress " ) , & TextureProgress : : get_tint_progress ) ;
ClassDB : : bind_method ( D_METHOD ( " set_tint_over " , " tint " ) , & TextureProgress : : set_tint_over ) ;
ClassDB : : bind_method ( D_METHOD ( " get_tint_over " ) , & TextureProgress : : get_tint_over ) ;
2021-03-09 22:24:02 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_texture_progress_offset " , " offset " ) , & TextureProgress : : set_progress_offset ) ;
ClassDB : : bind_method ( D_METHOD ( " get_texture_progress_offset " ) , & TextureProgress : : get_progress_offset ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_radial_initial_angle " , " mode " ) , & TextureProgress : : set_radial_initial_angle ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_radial_initial_angle " ) , & TextureProgress : : get_radial_initial_angle ) ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_radial_center_offset " , " mode " ) , & TextureProgress : : set_radial_center_offset ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_radial_center_offset " ) , & TextureProgress : : get_radial_center_offset ) ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_fill_degrees " , " mode " ) , & TextureProgress : : set_fill_degrees ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_fill_degrees " ) , & TextureProgress : : get_fill_degrees ) ;
2015-10-18 04:37:39 +02:00
2017-08-21 06:01:06 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_stretch_margin " , " margin " , " value " ) , & TextureProgress : : set_stretch_margin ) ;
ClassDB : : bind_method ( D_METHOD ( " get_stretch_margin " , " margin " ) , & TextureProgress : : get_stretch_margin ) ;
ClassDB : : bind_method ( D_METHOD ( " set_nine_patch_stretch " , " stretch " ) , & TextureProgress : : set_nine_patch_stretch ) ;
ClassDB : : bind_method ( D_METHOD ( " get_nine_patch_stretch " ) , & TextureProgress : : get_nine_patch_stretch ) ;
2017-03-05 16:44:50 +01:00
ADD_GROUP ( " Textures " , " texture_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " texture_under " , PROPERTY_HINT_RESOURCE_TYPE , " Texture " ) , " set_under_texture " , " get_under_texture " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " texture_over " , PROPERTY_HINT_RESOURCE_TYPE , " Texture " ) , " set_over_texture " , " get_over_texture " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " texture_progress " , PROPERTY_HINT_RESOURCE_TYPE , " Texture " ) , " set_progress_texture " , " get_progress_texture " ) ;
2021-03-09 22:24:02 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2 , " texture_progress_offset " ) , " set_texture_progress_offset " , " get_texture_progress_offset " ) ;
2021-02-08 05:30:04 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " fill_mode " , PROPERTY_HINT_ENUM , " Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise,Bilinear (Left and Right),Bilinear (Top and Bottom),Clockwise and Counter Clockwise " ) , " set_fill_mode " , " get_fill_mode " ) ;
2018-04-01 18:22:51 +02:00
ADD_GROUP ( " Tint " , " tint_ " ) ;
2018-09-01 13:14:05 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : COLOR , " tint_under " ) , " set_tint_under " , " get_tint_under " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : COLOR , " tint_over " ) , " set_tint_over " , " get_tint_over " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : COLOR , " tint_progress " ) , " set_tint_progress " , " get_tint_progress " ) ;
2017-03-05 16:44:50 +01:00
ADD_GROUP ( " Radial Fill " , " radial_ " ) ;
2018-11-08 15:30:02 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " radial_initial_angle " , PROPERTY_HINT_RANGE , " 0.0,360.0,0.1,slider " ) , " set_radial_initial_angle " , " get_radial_initial_angle " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : REAL , " radial_fill_degrees " , PROPERTY_HINT_RANGE , " 0.0,360.0,0.1,slider " ) , " set_fill_degrees " , " get_fill_degrees " ) ;
2017-03-05 16:44:50 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2 , " radial_center_offset " ) , " set_radial_center_offset " , " get_radial_center_offset " ) ;
2017-08-21 06:01:06 +02:00
ADD_GROUP ( " Stretch " , " stretch_ " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " nine_patch_stretch " ) , " set_nine_patch_stretch " , " get_nine_patch_stretch " ) ;
2018-11-08 15:30:02 +01:00
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " stretch_margin_left " , PROPERTY_HINT_RANGE , " 0,16384,1 " ) , " set_stretch_margin " , " get_stretch_margin " , MARGIN_LEFT ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " stretch_margin_top " , PROPERTY_HINT_RANGE , " 0,16384,1 " ) , " set_stretch_margin " , " get_stretch_margin " , MARGIN_TOP ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " stretch_margin_right " , PROPERTY_HINT_RANGE , " 0,16384,1 " ) , " set_stretch_margin " , " get_stretch_margin " , MARGIN_RIGHT ) ;
ADD_PROPERTYI ( PropertyInfo ( Variant : : INT , " stretch_margin_bottom " , PROPERTY_HINT_RANGE , " 0,16384,1 " ) , " set_stretch_margin " , " get_stretch_margin " , MARGIN_BOTTOM ) ;
2017-03-05 16:44:50 +01:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( FILL_LEFT_TO_RIGHT ) ;
BIND_ENUM_CONSTANT ( FILL_RIGHT_TO_LEFT ) ;
BIND_ENUM_CONSTANT ( FILL_TOP_TO_BOTTOM ) ;
BIND_ENUM_CONSTANT ( FILL_BOTTOM_TO_TOP ) ;
BIND_ENUM_CONSTANT ( FILL_CLOCKWISE ) ;
BIND_ENUM_CONSTANT ( FILL_COUNTER_CLOCKWISE ) ;
2018-05-11 19:44:05 +02:00
BIND_ENUM_CONSTANT ( FILL_BILINEAR_LEFT_AND_RIGHT ) ;
BIND_ENUM_CONSTANT ( FILL_BILINEAR_TOP_AND_BOTTOM ) ;
BIND_ENUM_CONSTANT ( FILL_CLOCKWISE_AND_COUNTER_CLOCKWISE ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
TextureProgress : : TextureProgress ( ) {
mode = FILL_LEFT_TO_RIGHT ;
rad_init_angle = 0 ;
rad_center_off = Point2 ( ) ;
rad_max_degrees = 360 ;
2017-01-21 23:00:25 +01:00
set_mouse_filter ( MOUSE_FILTER_PASS ) ;
2017-08-21 06:01:06 +02:00
nine_patch_stretch = false ;
stretch_margin [ MARGIN_LEFT ] = 0 ;
stretch_margin [ MARGIN_RIGHT ] = 0 ;
stretch_margin [ MARGIN_BOTTOM ] = 0 ;
stretch_margin [ MARGIN_TOP ] = 0 ;
2018-03-21 19:55:39 +01:00
2018-04-01 18:22:51 +02:00
tint_under = tint_progress = tint_over = Color ( 1 , 1 , 1 ) ;
2014-02-10 02:10:30 +01:00
}