Skip to content

Instantly share code, notes, and snippets.

@romgerman
Last active July 29, 2024 10:54
Show Gist options
  • Save romgerman/868572002e6c386a3f1f37033d7546ef to your computer and use it in GitHub Desktop.
Save romgerman/868572002e6c386a3f1f37033d7546ef to your computer and use it in GitHub Desktop.
Animation function for Godot 4
extends Node
## Animation function
## [br]
## [param start_props] Sets values to properties on init. $ means "set property to initial value of node"
## [br]
## [param end_props] Sets properties for tweening
## [br]
## [param options] Global tween options such as duration, delay, parallel and trans
## [br]
## Example: [br]
## [codeblock]
## anim(initial_state, final_state, options).call(bind_to_node_or_array_of_nodes).play()
## [/codeblock]
func anim(start_props: Dictionary, end_props: Dictionary, options: Dictionary) -> Callable:
if not options.has("duration"):
printerr("Animation tween doesn't have a duration")
var parse_props = func(props: Dictionary) -> Dictionary:
var dict = {}
for key in props.keys():
var value = props.get(key)
if typeof(value) == TYPE_STRING:
var props_values = []
var vector_regex = RegEx.new()
# Example: 0, -3.14, $
vector_regex.compile("(\\$|-?\\d*\\.\\d*|-?\\d*)(?:,? ?)*")
for res in vector_regex.search_all(value):
var res_str = res.get_string().replace(",", "").replace(" ", "")
if res_str != "":
props_values.push_back(res_str)
dict[key] = props_values
else:
dict[key] = value
return dict
var parsed_start_props = parse_props.call(start_props)
var parsed_end_props = parse_props.call(end_props)
var get_parsed_value_for_node = func(prop: String, node: Node, parsed_value):
match parsed_value.size():
1:
return node[prop] if parsed_value[0] == "$" else float(parsed_value[0])
2:
return Vector2(
node[prop].x if parsed_value[0] == "$" else float(parsed_value[0]),
node[prop].y if parsed_value[1] == "$" else float(parsed_value[1])
)
3:
return Vector3(
node[prop].x if parsed_value[0] == "$" else float(parsed_value[0]),
node[prop].y if parsed_value[1] == "$" else float(parsed_value[1]),
node[prop].y if parsed_value[2] == "$" else float(parsed_value[2])
)
var set_node_value = func(prop: String, node: Node, parsed_value) -> void:
if typeof(parsed_value) == TYPE_ARRAY:
node[prop] = get_parsed_value_for_node.call(prop, node, parsed_value)
else:
node[prop] = parsed_value
var get_node_value = func(prop: String, node: Node, parsed_value):
if typeof(parsed_value) == TYPE_ARRAY:
return get_parsed_value_for_node.call(prop, node, parsed_value)
else:
return parsed_value
var animate_nodes = func(tw: Tween, obj: Array) -> void:
var index = 0
# Prepare property tweening
for node in obj:
for key in parsed_end_props.keys():
var value = parsed_end_props[key]
var tp = tw.tween_property(node, key, get_node_value.call(key, node, value), options.get("duration"))
if options.has("delay"):
if obj.size() > 1:
tp.set_delay(index * options.get("delay"))
else:
tp.set_delay(options.get("delay"))
if options.get('parallel'):
tw.parallel()
index += 1
# Set initial values
for node in obj:
for key in parsed_start_props.keys():
var value = parsed_start_props[key]
set_node_value.call(key, node, value)
return func(obj) -> Tween:
var tw = get_tree().create_tween()
if options.has('trans'):
tw.set_trans(options.get('trans'))
if options.has('loops'):
tw.set_loops(options.get('loops'))
if typeof(obj) == TYPE_ARRAY:
animate_nodes.call(tw, obj)
else:
animate_nodes.call(tw, [obj])
return tw
for c in item_container.get_children():
var btn = c as Button
btn.mouse_entered.connect(func ():
anim({}, {
"position": "25, $"
}, {
"duration": 0.25,
"trans": Tween.TRANS_CIRC
}).call(btn).play()
)
btn.mouse_exited.connect(func ():
anim({}, {
"position": "0, $"
}, {
"duration": 0.25,
"trans": Tween.TRANS_CIRC
}).call(btn).play()
)
func _ready():
await get_tree().process_frame
anim({
'modulate': Color.TRANSPARENT,
'position': "-50, $"
}, {
'modulate': Color.WHITE,
'position': "$, $"
}, {
'parallel': true,
'delay': 0.35,
'duration': 0.25,
'trans': Tween.TRANS_SINE
}).call(item_container.get_children()).play()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment