Created
July 29, 2021 08:50
-
-
Save xsellier/d5e1ebc05e084f3255756ababe1a32b0 to your computer and use it in GitHub Desktop.
AnimatedToggle button for Godot Engine 2.1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
tool | |
extends TextureButton | |
const ANIMATION_DURATION = 0.667 | |
const TICK_TEXTURE = preload('res://theme/blank/white-128x128-circle.tex') | |
const BUTTON_BACKGROUND = preload('res://theme/blank/bean-128x60.tex') | |
export(float, 0.1, 1.0, 0.01) var tick_ratio = 0.8 setget set_tick_ratio, get_tick_ratio | |
export(Color) var unselected_background = Color('#12171e') setget set_unselected_background, get_unselected_background | |
export(Color) var unselected_tick = Color('#fefefe') setget set_unselected_tick, get_unselected_tick | |
export(Color) var selected_background = Color('#0092e9') setget set_selected_background, get_selected_background | |
export(Color) var selected_tick = Color('#fefefe') setget set_selected_tick, get_selected_tick | |
export(Color) var warning_background = Color('#ff6363') setget set_warning_background, get_warning_background | |
export(bool) var wargning_color = false setget set_warning, is_warning | |
var TOGGLER_POSITIONS = [ | |
Vector2(0, 0), | |
Vector2(0, 0) | |
] | |
var texture_frame_node = TextureFrame.new() | |
var tween_node = Tween.new() | |
var button_texture_size = Vector2() | |
var button_texture_aspect = 1.0 | |
func _init(): | |
set_toggle_mode(true) | |
set_normal_texture(BUTTON_BACKGROUND) | |
set_resize_mode(RESIZE_STRETCH) | |
set_stretch_mode(STRETCH_KEEP_ASPECT_CENTERED) | |
button_texture_size = get_normal_texture().get_size() | |
button_texture_aspect = button_texture_size.get_aspect() | |
texture_frame_node.set_texture(TICK_TEXTURE) | |
texture_frame_node.set_expand(true) | |
texture_frame_node.set_stretch_mode(TextureFrame.STRETCH_KEEP_ASPECT_CENTERED) | |
add_child(tween_node) | |
add_child(texture_frame_node) | |
connect('resized', self, '_update_tick') | |
connect('toggled', self, '_update_toggler') | |
call_deferred('_update_tick') | |
func set_unselected_background(value): | |
if unselected_background != value: | |
unselected_background = value | |
_update_tick() | |
func set_unselected_tick(value): | |
if unselected_tick != value: | |
unselected_tick = value | |
_update_tick() | |
func set_selected_background(value): | |
if selected_background != value: | |
selected_background = value | |
_update_tick() | |
func set_selected_tick(value): | |
if selected_tick != value: | |
selected_tick = value | |
_update_tick() | |
func set_warning_background(value): | |
if warning_background != value: | |
warning_background = value | |
_update_toggler(is_pressed()) | |
func set_warning(value): | |
if wargning_color != value: | |
wargning_color = value | |
_update_toggler(is_pressed()) | |
func is_warning(): | |
return wargning_color | |
func get_warning_background(): | |
return warning_background | |
func get_unselected_background(): | |
return unselected_background | |
func get_unselected_tick(): | |
return unselected_tick | |
func get_selected_background(): | |
return selected_background | |
func get_selected_tick(): | |
return selected_tick | |
func set_tick_ratio(value): | |
tick_ratio = value | |
_update_tick() | |
func get_tick_ratio(): | |
return tick_ratio | |
func set_disabled(value): | |
.set_disabled(value) | |
if value: | |
set_opacity(0.6) | |
else: | |
set_opacity(1.0) | |
func set_button_pressed(value): | |
set_pressed(value) | |
_update_toggler(value) | |
func toggle(): | |
set_button_pressed(not is_pressed()) | |
func _update_tick(): | |
var button_size = get_size() | |
var texture_size_y = floor(min(button_size.x / button_texture_aspect, button_size.y)) | |
var texture_size_x = floor(min(button_size.x, button_size.y * button_texture_aspect)) | |
var texture_size = Vector2(texture_size_x, texture_size_y) | |
var tick_computed_size = (Vector2(texture_size.y, texture_size.y) * tick_ratio).floor() | |
var tick_position = (button_size - texture_size) / 2.0 | |
var tick_color = selected_tick if is_pressed() else unselected_tick | |
var postion_decal_ratio = (Vector2(texture_size.y, texture_size.y) - tick_computed_size) / 2.0 | |
texture_frame_node.set_custom_minimum_size(tick_computed_size) | |
texture_frame_node.set_size(tick_computed_size) | |
texture_frame_node.set_modulate(tick_color) | |
TOGGLER_POSITIONS[0] = tick_position + postion_decal_ratio | |
TOGGLER_POSITIONS[1] = tick_position + postion_decal_ratio | |
TOGGLER_POSITIONS[1].x += texture_size.x - tick_computed_size.x - 2.0 * postion_decal_ratio.x | |
var tick_position_computed = TOGGLER_POSITIONS[1] if is_pressed() else TOGGLER_POSITIONS[0] | |
texture_frame_node.set_pos(tick_position_computed) | |
call_deferred('_update_toggler', is_pressed()) | |
func _update_toggler(value): | |
var from_position = texture_frame_node.get_pos() | |
var to_position = TOGGLER_POSITIONS[1] if value else TOGGLER_POSITIONS[0] | |
var from_color = get_modulate() | |
var to_color = selected_background if value else unselected_background | |
var tick_from_color = texture_frame_node.get_modulate() | |
var tick_to_color = selected_tick if value else unselected_tick | |
if is_warning(): | |
to_color = warning_background | |
tween_node.remove_all() | |
tween_node.interpolate_property(texture_frame_node, 'rect/pos', from_position, to_position, ANIMATION_DURATION, Tween.TRANS_BOUNCE, Tween.EASE_OUT) | |
tween_node.interpolate_property(texture_frame_node, 'modulate', tick_from_color, tick_to_color, ANIMATION_DURATION, Tween.TRANS_SINE, Tween.EASE_OUT) | |
tween_node.interpolate_property(self, 'params/modulate', from_color, to_color, ANIMATION_DURATION, Tween.TRANS_SINE, Tween.EASE_OUT) | |
tween_node.start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment