Initial Android commit

This commit is contained in:
OleSTEEP 2024-11-10 03:34:28 +03:00
commit 1e2b80c13d
8521 changed files with 231475 additions and 0 deletions

View file

@ -0,0 +1,571 @@
extends Tween
var loop = 1
signal finished_animation
var _animation_data = []
enum PLAY_MODE{
NORMAL,
BACKWARDS
}
var _fake_property:Dictionary = {}
var _callbacks: = {}
func _ready():
connect("tween_started", self, "_on_tween_started")
connect("tween_step", self, "_on_tween_step_with_easing")
connect("tween_step", self, "_on_tween_step_with_easing_callback")
connect("tween_step", self, "_on_tween_step_with_easing_funcref")
connect("tween_step", self, "_on_tween_step_without_easing")
connect("tween_completed", self, "_on_tween_completed")
func play(node, animation_name, duration):
var script = DialogicAnimaResources.get_animation_script(animation_name.strip_edges())
if not script:
printerr("animation not found: %s" % animation_name)
return duration
var real_duration = script.generate_animation(self, {"node":node, "duration":duration, "wait_time":0})
if real_duration is float:
duration = real_duration
var index: = 0
for animation_data in _animation_data:
var easing_points
if animation_data.has("easing"):
if animation_data.easing is FuncRef:
easing_points = animation_data.easing
else :
easing_points = get_easing_points(animation_data.easing)
if animation_data.has("easing_points"):
easing_points = animation_data.easing_points
animation_data._easing_points = easing_points
animation_data._animation_callback = funcref(self, "_calculate_from_and_to")
if easing_points is Array:
animation_data._use_step_callback = "_on_tween_step_with_easing"
elif easing_points is String:
animation_data._use_step_callback = "_on_tween_step_with_easing_callback"
elif easing_points is FuncRef:
animation_data._use_step_callback = "_on_tween_step_with_easing_funcref"
else :
animation_data._use_step_callback = "_on_tween_step_without_easing"
index += 1
var started: = start()
if not started:
printerr("something went wrong while trying to start the tween")
if is_connected("tween_all_completed", self, "finished_once"):disconnect("tween_all_completed", self, "finished_once")
connect("tween_all_completed", self, "finished_once", [node, animation_name, duration])
func finished_once(node, animation, duration):
loop -= 1
if loop > 0:
play(node, animation, duration)
else :
emit_signal("finished_animation")
func add_relative_frames(data:Dictionary, property:String, frames:Array)->float:
return _add_frames(data, property, frames, true)
func add_frames(data:Dictionary, property:String, frames:Array)->float:
return _add_frames(data, property, frames)
func _add_frames(data:Dictionary, property:String, frames:Array, relative:bool = false)->float:
var duration:float = data.duration if data.has("duration") else 0.0
var _wait_time:float = data._wait_time if data.has("_wait_time") else 0.0
var last_duration: = 0.0
var keys_to_ignore = ["duration", "_wait_time"]
for frame in frames:
var percentage = frame.percentage if frame.has("percentage") else 100.0
percentage /= 100.0
var frame_duration = max(1e-06, duration * percentage)
var diff = frame_duration - last_duration
var is_first_frame = true
var is_last_frame = percentage == 1
var animation_data = {
property = property,
relative = relative,
duration = diff,
_wait_time = _wait_time
}
for animation in _animation_data:
if animation.node == data.node:
is_first_frame = false
if animation.has("_is_last_frame"):
is_last_frame = false
if is_first_frame:
animation_data._is_first_frame = true
if is_last_frame:
animation_data._is_last_frame = true
for key in frame:
if key != "percentage":
animation_data[key] = frame[key]
for key in data:
if key == "callback" and percentage < 1:
animation_data.erase(key)
elif keys_to_ignore.find(key) < 0:
animation_data[key] = data[key]
add_animation_data(animation_data)
last_duration = frame_duration
_wait_time += diff
return _wait_time
func add_animation_data(animation_data:Dictionary, play_mode:int = PLAY_MODE.NORMAL)->void :
_animation_data.push_back(animation_data)
var index = str(_animation_data.size())
var duration = animation_data.duration if animation_data.has("duration") else 1
var property_key = "p" + index
_fake_property[property_key] = 0.0
if animation_data.has("on_completed") and animation_data.has("_is_last_frame"):
_callbacks[property_key] = animation_data.on_completed
var from: = 0.0 if play_mode == PLAY_MODE.NORMAL else 1.0
var to: = 1.0 - from
interpolate_property(
self,
"_fake_property:" + property_key,
from,
to,
duration,
Tween.TRANS_LINEAR,
Tween.EASE_IN_OUT,
animation_data._wait_time
)
func _on_tween_step_with_easing(object:Object, key:NodePath, _time:float, elapsed:float):
var index: = _get_animation_data_index(key)
if _animation_data[index]._use_step_callback != "_on_tween_step_with_easing":
return
var easing_points = _animation_data[index]._easing_points
var p1 = easing_points[0]
var p2 = easing_points[1]
var p3 = easing_points[2]
var p4 = easing_points[3]
var easing_elapsed = _cubic_bezier(Vector2.ZERO, Vector2(p1, p2), Vector2(p3, p4), Vector2(1, 1), elapsed)
_animation_data[index]._animation_callback.call_func(index, easing_elapsed)
func _on_tween_step_with_easing_callback(object:Object, key:NodePath, _time:float, elapsed:float):
var index: = _get_animation_data_index(key)
if _animation_data[index]._use_step_callback != "_on_tween_step_with_easing_callback":
return
var easing_points_function = _animation_data[index]._easing_points
var easing_callback = funcref(self, easing_points_function)
var easing_elapsed = easing_callback.call_func(elapsed)
_animation_data[index]._animation_callback.call_func(index, easing_elapsed)
func _on_tween_step_with_easing_funcref(object:Object, key:NodePath, _time:float, elapsed:float):
var index: = _get_animation_data_index(key)
if _animation_data[index]._use_step_callback != "_on_tween_step_with_easing_funcref":
return
var easing_callback = _animation_data[index]._easing_points
var easing_elapsed = easing_callback.call_func(elapsed)
_animation_data[index]._animation_callback.call_func(index, easing_elapsed)
func _on_tween_step_without_easing(object:Object, key:NodePath, _time:float, elapsed:float):
var index: = _get_animation_data_index(key)
if _animation_data[index]._use_step_callback != "_on_tween_step_without_easing":
return
_animation_data[index]._animation_callback.call_func(index, elapsed)
func _get_animation_data_index(key:NodePath)->int:
var s = str(key)
return int(s.replace("_fake_property:p", "")) - 1
func _cubic_bezier(p0:Vector2, p1:Vector2, p2:Vector2, p3:Vector2, t:float)->float:
var q0 = p0.linear_interpolate(p1, t)
var q1 = p1.linear_interpolate(p2, t)
var q2 = p2.linear_interpolate(p3, t)
var r0 = q0.linear_interpolate(q1, t)
var r1 = q1.linear_interpolate(q2, t)
var s = r0.linear_interpolate(r1, t)
return s.y
func _calculate_from_and_to(index:int, value:float)->void :
var animation_data = _animation_data[index]
var node = animation_data.node
var do_calculate = true
if animation_data.has("_recalculate_from_to") and not animation_data._recalculate_from_to and animation_data.has("_property_data"):
do_calculate = false
if do_calculate:
_do_calculate_from_to(node, animation_data)
if animation_data._property_data.has("subkey"):
animation_data._animation_callback = funcref(self, "_on_animation_with_subkey")
elif animation_data._property_data.has("key"):
animation_data._animation_callback = funcref(self, "_on_animation_with_key")
else :
animation_data._animation_callback = funcref(self, "_on_animation_without_key")
_animation_data[index]._animation_callback.call_func(index, value)
func _do_calculate_from_to(node:Node, animation_data:Dictionary)->void :
var from
var to
var relative = animation_data.relative if animation_data.has("relative") else false
var node_from = DialogicAnimaPropertiesHelper.get_property_initial_value(node, animation_data.property)
if animation_data.has("from"):
from = _maybe_convert_from_deg_to_rad(node, animation_data, animation_data.from)
from = _maybe_calculate_relative_value(relative, from, node_from)
else :
from = node_from
animation_data.__from = from
if animation_data.has("to"):
to = _maybe_convert_from_deg_to_rad(node, animation_data, animation_data.to)
to = _maybe_calculate_relative_value(relative, to, from)
else :
to = from
animation_data.__to = to
if animation_data.has("pivot"):
if node is Spatial:
printerr("3D Pivot not supported yet")
else :
DialogicAnimaPropertiesHelper.set_2D_pivot(animation_data.node, animation_data.pivot)
animation_data._property_data = DialogicAnimaPropertiesHelper.map_property_to_godot_property(node, animation_data.property)
animation_data._property_data.diff = to - from
animation_data._property_data.from = from
func _maybe_calculate_relative_value(relative, value, current_node_value):
if not relative:
return value
return value + current_node_value
func _maybe_convert_from_deg_to_rad(node:Node, animation_data:Dictionary, value):
if not node is Spatial or animation_data.property.find("rotation") < 0:
return value
if value is Vector3:
return Vector3(deg2rad(value.x), deg2rad(value.y), deg2rad(value.z))
return deg2rad(value)
func _on_animation_with_key(index:int, elapsed:float)->void :
var animation_data = _animation_data[index]
var property_data = _animation_data[index]._property_data
var node = animation_data.node
var value = property_data.from + (property_data.diff * elapsed)
node[property_data.property_name][property_data.key] = value
func _on_animation_with_subkey(index:int, elapsed:float)->void :
var animation_data = _animation_data[index]
var property_data = _animation_data[index]._property_data
var node = animation_data.node
var value = property_data.from + (property_data.diff * elapsed)
node[property_data.property_name][property_data.key][property_data.subkey] = value
func _on_animation_without_key(index:int, elapsed:float)->void :
var animation_data = _animation_data[index]
var property_data = _animation_data[index]._property_data
var node = animation_data.node
var value = property_data.from + (property_data.diff * elapsed)
if property_data.has("callback"):
property_data.callback.call_func(property_data.param, value)
return
node[property_data.property_name] = value
func _maybe_adjust_modulate_value(animation_data:Dictionary, value):
var property = animation_data.property
var node = animation_data.node
if not property == "opacity":
return value
if value is int or value is float:
var color = node.modulate
color.a = value
return color
return value
func _on_tween_completed(_ignore, property_name:String)->void :
var property_key = property_name.replace(":_fake_property:", "")
if _callbacks.has(property_key):
var callback = _callbacks[property_key]
if not callback is Array or callback.size() == 1:
callback[0].call_func()
else :
callback[0].call_funcv(callback[1])
func _on_tween_started(_ignore, key)->void :
var index: = _get_animation_data_index(key)
var animation_data = _animation_data[index]
var node = animation_data.node
var should_restore_visibility: = false
var should_restore_modulate: = false
if should_restore_modulate:
var old_modulate = node.get_meta("_old_modulate")
if old_modulate:
node.modulate = old_modulate
if should_restore_visibility:
node.show()
var should_trigger_on_started:bool = animation_data.has("_is_first_frame") and animation_data._is_first_frame and animation_data.has("on_started")
if should_trigger_on_started:
var fn:FuncRef
var args:Array = []
if animation_data.on_started is Array:
fn = animation_data.on_started[0]
args = animation_data.on_started.slice(1, - 1)
else :
fn = animation_data.on_started
fn.call_funcv(args)
enum EASING{
LINEAR,
EASE,
EASE_IN_OUT,
EASE_IN,
EASE_OUT,
EASE_IN_SINE,
EASE_OUT_SINE,
EASE_IN_OUT_SINE,
EASE_IN_QUAD,
EASE_OUT_QUAD,
EASE_IN_OUT_QUAD,
EASE_IN_CUBIC,
EASE_OUT_CUBIC,
EASE_IN_OUT_CUBIC,
EASE_IN_QUART,
EASE_OUT_QUART,
EASE_IN_OUT_QUART,
EASE_IN_QUINT,
EASE_OUT_QUINT,
EASE_IN_OUT_QUINT,
EASE_IN_EXPO,
EASE_OUT_EXPO,
EASE_IN_OUT_EXPO,
EASE_IN_CIRC,
EASE_OUT_CIRC,
EASE_IN_OUT_CIRC,
EASE_IN_BACK,
EASE_OUT_BACK,
EASE_IN_OUT_BACK,
EASE_IN_ELASTIC,
EASE_OUT_ELASTIC,
EASE_IN_OUT_ELASTIC,
EASE_IN_BOUNCE,
EASE_OUT_BOUNCE,
EASE_IN_OUT_BOUNCE,
}
const _easing_mapping = {
EASING.LINEAR:null,
EASING.EASE:[0.25, 0.1, 0.25, 1],
EASING.EASE_IN_OUT:[0.42, 0, 0.58, 1],
EASING.EASE_IN:[0.42, 0, 1, 1],
EASING.EASE_OUT:[0, 0, 0.58, 1],
EASING.EASE_IN_SINE:[0, 0, 1, 0.5],
EASING.EASE_OUT_SINE:[0.61, 1, 0.88, 1],
EASING.EASE_IN_OUT_SINE:[0.37, 0, 0.63, 1],
EASING.EASE_IN_QUAD:[0.11, 0, 0.5, 0],
EASING.EASE_OUT_QUAD:[0.5, 1.0, 0.89, 1],
EASING.EASE_IN_OUT_QUAD:[0.45, 0, 0.55, 1],
EASING.EASE_IN_CUBIC:[0.32, 0, 0.67, 0],
EASING.EASE_OUT_CUBIC:[0.33, 1, 0.68, 1],
EASING.EASE_IN_OUT_CUBIC:[0.65, 0, 0.35, 1],
EASING.EASE_IN_QUART:[0.5, 0, 0.75, 0],
EASING.EASE_OUT_QUART:[0.25, 1, 0.5, 1],
EASING.EASE_IN_OUT_QUART:[0.76, 0, 0.24, 1],
EASING.EASE_IN_QUINT:[0.64, 0, 0.78, 0],
EASING.EASE_OUT_QUINT:[0.22, 1, 0.36, 1],
EASING.EASE_IN_OUT_QUINT:[0.83, 0, 0.17, 1],
EASING.EASE_IN_EXPO:[0.7, 0, 0.84, 0],
EASING.EASE_OUT_EXPO:[0.16, 1, 0.3, 1],
EASING.EASE_IN_OUT_EXPO:[0.87, 0, 0.13, 1],
EASING.EASE_IN_CIRC:[0.55, 0, 0.1, 0.45],
EASING.EASE_OUT_CIRC:[0, 0.55, 0.45, 1],
EASING.EASE_IN_OUT_CIRC:[0.85, 0, 0.15, 1],
EASING.EASE_IN_BACK:[0.36, 0, 0.66, - 0.56],
EASING.EASE_OUT_BACK:[0.36, 1.56, 0.64, 1],
EASING.EASE_IN_OUT_BACK:[0.68, - 0.6, 0.32, 1.6],
EASING.EASE_IN_ELASTIC:"ease_in_elastic",
EASING.EASE_OUT_ELASTIC:"ease_out_elastic",
EASING.EASE_IN_OUT_ELASTIC:"ease_in_out_elastic",
EASING.EASE_IN_BOUNCE:"ease_in_bounce",
EASING.EASE_OUT_BOUNCE:"ease_out_bounce",
EASING.EASE_IN_OUT_BOUNCE:"ease_in_out_bounce"
}
const _ELASTIC_C4:float = (2.0 * PI) / 3.0
const _ELASTIC_C5:float = (2.0 * PI) / 4.5
static func get_easing_points(easing_name):
if _easing_mapping.has(easing_name):
return _easing_mapping[easing_name]
printerr("Easing not found: " + str(easing_name))
return _easing_mapping[EASING.LINEAR]
static func ease_in_elastic(elapsed:float)->float:
if elapsed == 0:
return 0.0
elif elapsed == 1:
return 1.0
return - pow(2, 10 * elapsed - 10) * sin((elapsed * 10 - 10.75) * _ELASTIC_C4)
static func ease_out_elastic(elapsed:float)->float:
if elapsed == 0:
return 0.0
elif elapsed == 1:
return 1.0
return pow(2, - 10 * elapsed) * sin((elapsed * 10 - 0.75) * _ELASTIC_C4) + 1
static func ease_in_out_elastic(elapsed:float)->float:
if elapsed == 0:
return 0.0
elif elapsed == 1:
return 1.0
elif elapsed < 0.5:
return - (pow(2, 20 * elapsed - 10) * sin((20 * elapsed - 11.125) * _ELASTIC_C5)) / 2
return (pow(2, - 20 * elapsed + 10) * sin((20 * elapsed - 11.125) * _ELASTIC_C5)) / 2 + 1
const n1 = 7.5625;
const d1 = 2.75;
static func ease_in_bounce(elapsed:float)->float:
return 1 - ease_out_bounce(1.0 - elapsed)
static func ease_out_bounce(elapsed:float)->float:
if elapsed < 1 / d1:
return n1 * elapsed * elapsed;
elif elapsed < 2 / d1:
elapsed -= 1.5 / d1
return n1 * elapsed * elapsed + 0.75;
elif elapsed < 2.5 / d1:
elapsed -= 2.25 / d1
return n1 * elapsed * elapsed + 0.9375;
elapsed -= 2.625 / d1
return n1 * elapsed * elapsed + 0.984375;
static func ease_in_out_bounce(elapsed:float)->float:
if elapsed < 0.5:
return (1 - ease_out_bounce(1 - 2 * elapsed)) / 2
return (1 + ease_out_bounce(2 * elapsed - 1)) / 2