2022-01-13 05:24:03 +01:00
|
|
|
enum CURVE_TYPE {
|
|
|
|
bezier,
|
|
|
|
bounce,
|
|
|
|
damping
|
|
|
|
}
|
|
|
|
|
|
|
|
globalvar ON_END_NAME;
|
|
|
|
ON_END_NAME = [ "Hold", "Loop", "Ping pong" ];
|
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
function valueKey(_time, _value, _anim = noone, _in = 0, _out = 0) constructor {
|
|
|
|
time = _time;
|
2022-12-10 05:06:01 +01:00
|
|
|
ratio = time / ANIMATOR.frames_total;
|
2022-09-23 13:28:42 +02:00
|
|
|
value = _value;
|
|
|
|
anim = _anim;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
ease_in = _in;
|
2022-01-13 05:24:03 +01:00
|
|
|
ease_out = _out;
|
2022-09-23 13:28:42 +02:00
|
|
|
|
|
|
|
ease_in_type = CURVE_TYPE.bezier;
|
|
|
|
ease_out_type = CURVE_TYPE.bezier;
|
2022-12-10 05:06:01 +01:00
|
|
|
|
|
|
|
static setTime = function(time) {
|
|
|
|
self.time = time;
|
|
|
|
ratio = time / ANIMATOR.frames_total;
|
|
|
|
}
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
function valueAnimator(_val, _prop) constructor {
|
2022-01-13 05:24:03 +01:00
|
|
|
values = ds_list_create();
|
|
|
|
show_graph = false;
|
2022-09-23 13:28:42 +02:00
|
|
|
ds_list_add(values, new valueKey(0, _val, self));
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
is_anim = false;
|
2022-09-23 13:28:42 +02:00
|
|
|
prop = _prop;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
static interpolate = function(from, to, rat) {
|
|
|
|
if(from.ease_out == 0 && to.ease_in == 0)
|
2022-09-23 13:28:42 +02:00
|
|
|
return rat;
|
|
|
|
|
|
|
|
var eo = rat;
|
|
|
|
var ei = rat;
|
|
|
|
|
2022-12-27 04:00:50 +01:00
|
|
|
if(from.ease_out != 0) {
|
2022-09-23 13:28:42 +02:00
|
|
|
switch(from.ease_out_type) {
|
2022-11-01 03:06:03 +01:00
|
|
|
case CURVE_TYPE.bezier :
|
2022-09-23 13:28:42 +02:00
|
|
|
eo = ease_cubic_in(rat);
|
|
|
|
eo = lerp(rat, eo, from.ease_out);
|
|
|
|
break;
|
|
|
|
case CURVE_TYPE.damping :
|
|
|
|
eo = ease_damp_in(rat, 1 + from.ease_out * 10);
|
|
|
|
break;
|
|
|
|
}
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
|
2022-12-27 04:00:50 +01:00
|
|
|
if(to.ease_in != 0) {
|
2022-09-23 13:28:42 +02:00
|
|
|
switch(to.ease_in_type) {
|
|
|
|
case CURVE_TYPE.bezier :
|
|
|
|
ei = ease_cubic_out(rat);
|
|
|
|
ei = lerp(rat, ei, to.ease_in);
|
|
|
|
break;
|
|
|
|
case CURVE_TYPE.damping :
|
|
|
|
ei = ease_damp_out(rat, 1 + to.ease_in * 10);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(from.ease_out_type == CURVE_TYPE.damping && to.ease_in_type == CURVE_TYPE.damping)
|
|
|
|
return lerp(eo, ei, rat < 0.5 ? 4 * power(rat, 3) : 1 - power(-2 * rat + 2, 3) / 2);
|
2022-12-27 04:00:50 +01:00
|
|
|
|
|
|
|
return lerp(eo, ei, rat);
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
|
2022-12-10 05:06:01 +01:00
|
|
|
static getValue = function(_time = ANIMATOR.current_frame) {
|
2022-09-23 13:28:42 +02:00
|
|
|
if(prop.display_type == VALUE_DISPLAY.gradient) return processType(values);
|
|
|
|
if(prop.type == VALUE_TYPE.path) return processType(values[| 0].value);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
if(ds_list_size(values) == 0) return processType(0);
|
|
|
|
if(ds_list_size(values) == 1) return processType(values[| 0].value);
|
2022-12-12 09:08:03 +01:00
|
|
|
if(!is_anim) return processType(values[| 0].value);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
if(ds_list_size(values) > 1) {
|
|
|
|
var _time_first = values[| 0].time;
|
|
|
|
var _time_last = values[| ds_list_size(values) - 1].time;
|
|
|
|
var _time_dura = _time_last - _time_first;
|
|
|
|
|
|
|
|
if(_time > _time_last) {
|
2022-09-23 13:28:42 +02:00
|
|
|
switch(prop.on_end) {
|
2022-01-13 05:24:03 +01:00
|
|
|
case KEYFRAME_END.loop :
|
|
|
|
_time = _time_first + safe_mod(_time - _time_last, _time_dura + 1);
|
|
|
|
break;
|
|
|
|
case KEYFRAME_END.ping :
|
|
|
|
var time_in_loop = safe_mod(_time - _time_first, _time_dura * 2);
|
|
|
|
if(time_in_loop < _time_dura)
|
|
|
|
_time = _time_first + time_in_loop;
|
|
|
|
else
|
|
|
|
_time = _time_first + _time_dura * 2 - time_in_loop;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(var i = 0; i < ds_list_size(values); i++) {
|
|
|
|
var _key = values[| i];
|
|
|
|
if(_key.time > _time) {
|
|
|
|
if(i == 0)
|
|
|
|
return processType(values[| 0].value);
|
|
|
|
else {
|
|
|
|
var rat = (_time - values[| i - 1].time) / (values[| i].time - values[| i - 1].time);
|
|
|
|
var from = values[| i - 1];
|
|
|
|
var to = values[| i];
|
|
|
|
var _lerp = interpolate(from, to, rat);
|
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
if(prop.type == VALUE_TYPE.color) {
|
2022-01-13 05:24:03 +01:00
|
|
|
return processType(merge_color(from.value, to.value, _lerp));
|
2022-12-27 04:00:50 +01:00
|
|
|
} else if(typeArray(prop.display_type) && is_array(from.value)) {
|
2022-01-13 05:24:03 +01:00
|
|
|
var _vec = array_create(array_length(from.value));
|
|
|
|
for(var i = 0; i < array_length(_vec); i++)
|
|
|
|
_vec[i] = processType(lerp(from.value[i], to.value[i], _lerp));
|
|
|
|
return _vec;
|
2022-09-23 13:28:42 +02:00
|
|
|
} else if(prop.type == VALUE_TYPE.text) {
|
2022-01-13 05:24:03 +01:00
|
|
|
return processType(from.value);
|
|
|
|
} else {
|
|
|
|
return processType(lerp(from.value, to.value, _lerp));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return processType(values[| ds_list_size(values) - 1].value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static processType = function(_val) {
|
2022-12-27 04:00:50 +01:00
|
|
|
if(typeArray(prop.display_type) && is_array(_val)) {
|
2022-01-13 05:24:03 +01:00
|
|
|
for(var i = 0; i < array_length(_val); i++)
|
|
|
|
_val[i] = processValue(_val[i]);
|
|
|
|
return _val;
|
|
|
|
}
|
|
|
|
return processValue(_val);
|
|
|
|
}
|
|
|
|
static processValue = function(_val) {
|
|
|
|
if(is_array(_val)) return _val;
|
|
|
|
|
2022-12-27 04:00:50 +01:00
|
|
|
if(prop.type == VALUE_TYPE.integer && prop.unit.mode == VALUE_UNIT.constant)
|
|
|
|
return round(toNumber(_val));
|
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
switch(prop.type) {
|
2022-12-27 04:00:50 +01:00
|
|
|
case VALUE_TYPE.integer :
|
2022-09-21 06:09:40 +02:00
|
|
|
case VALUE_TYPE.float : return toNumber(_val);
|
2022-01-13 05:24:03 +01:00
|
|
|
case VALUE_TYPE.text : return string(_val);
|
2022-09-27 06:37:28 +02:00
|
|
|
case VALUE_TYPE.surface :
|
|
|
|
if(is_string(_val))
|
|
|
|
return get_asset(_val);
|
|
|
|
return is_surface(_val)? _val : DEF_SURFACE;
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return _val;
|
|
|
|
}
|
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
static setKeyTime = function(_key, _time, _replace = true) {
|
|
|
|
if(!ds_list_exist(values, _key)) return 0;
|
2022-09-27 06:37:28 +02:00
|
|
|
MODIFIED = true;
|
2022-09-23 13:28:42 +02:00
|
|
|
|
2022-11-21 06:38:44 +01:00
|
|
|
_time = clamp(_time, 0, ANIMATOR.frames_total - 1);
|
2022-12-10 05:06:01 +01:00
|
|
|
_key.setTime(_time);
|
2022-09-23 13:28:42 +02:00
|
|
|
ds_list_remove(values, _key);
|
|
|
|
|
|
|
|
if(_replace) {
|
|
|
|
for( var i = 0; i < ds_list_size(values); i++ ) {
|
|
|
|
if(values[| i].time == _time) {
|
|
|
|
values[| i] = _key;
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for( var i = 0; i < ds_list_size(values); i++ ) {
|
|
|
|
if(values[| i].time > _time) {
|
|
|
|
ds_list_insert(values, i, _key);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ds_list_add(values, _key);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-12-27 04:00:50 +01:00
|
|
|
static setValue = function(_val = 0, _record = true, _time = ANIMATOR.current_frame, ease_in = 0, ease_out = 0) {
|
2022-09-27 06:37:28 +02:00
|
|
|
MODIFIED = true;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
if(!is_anim) {
|
2022-11-22 14:25:39 +01:00
|
|
|
if(isEqual(values[| 0].value, _val))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(_record)
|
|
|
|
recordAction(ACTION_TYPE.var_modify, values[| 0], [ values[| 0].value, "value" ]);
|
|
|
|
values[| 0].value = _val;
|
|
|
|
return true;
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if(ds_list_size(values) == 0) {
|
2022-09-23 13:28:42 +02:00
|
|
|
var k = new valueKey(_time, _val, self, ease_in, ease_out);
|
2022-01-13 05:24:03 +01:00
|
|
|
ds_list_add(values, k);
|
|
|
|
if(_record)
|
|
|
|
recordAction(ACTION_TYPE.list_insert, values, [ k, ds_list_size(values) - 1 ]);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(var i = 0; i < ds_list_size(values); i++) {
|
|
|
|
var _key = values[| i];
|
|
|
|
if(_key.time == _time) {
|
2022-11-22 14:25:39 +01:00
|
|
|
if(_record)
|
|
|
|
recordAction(ACTION_TYPE.var_modify, _key, [ _key.value, "value" ]);
|
2022-01-13 05:24:03 +01:00
|
|
|
if(_key.value != _val) {
|
|
|
|
_key.value = _val;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} else if(_key.time > _time) {
|
2022-09-23 13:28:42 +02:00
|
|
|
var k = new valueKey(_time, _val, self, ease_in, ease_out);
|
2022-01-13 05:24:03 +01:00
|
|
|
ds_list_insert(values, i, k);
|
|
|
|
if(_record)
|
|
|
|
recordAction(ACTION_TYPE.list_insert, values, [k, i]);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
var k = new valueKey(_time, _val, self, ease_in, ease_out);
|
2022-01-13 05:24:03 +01:00
|
|
|
ds_list_add(values, k);
|
|
|
|
if(_record)
|
|
|
|
recordAction(ACTION_TYPE.list_insert, values, [ k, ds_list_size(values) - 1 ]);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
static removeKey = function(key) {
|
|
|
|
if(ds_list_size(values) > 1)
|
|
|
|
ds_list_remove(values, key);
|
|
|
|
else
|
|
|
|
is_anim = false;
|
|
|
|
}
|
|
|
|
|
2022-01-13 05:24:03 +01:00
|
|
|
static serialize = function(scale = false) {
|
|
|
|
var _list = ds_list_create();
|
|
|
|
|
|
|
|
for(var i = 0; i < ds_list_size(values); i++) {
|
|
|
|
var _value_list = ds_list_create();
|
2022-09-23 13:28:42 +02:00
|
|
|
if(scale && prop.display_type != VALUE_DISPLAY.gradient)
|
2022-12-10 05:06:01 +01:00
|
|
|
_value_list[| 0] = values[| i].time / (ANIMATOR.frames_total - 1);
|
2022-01-13 05:24:03 +01:00
|
|
|
else
|
|
|
|
_value_list[| 0] = values[| i].time;
|
|
|
|
|
2022-12-27 04:00:50 +01:00
|
|
|
if(typeArray(prop.display_type) && is_array(values[| i].value)) {
|
2022-01-13 05:24:03 +01:00
|
|
|
var __v = ds_list_create();
|
|
|
|
for(var j = 0; j < array_length(values[| i].value); j++)
|
|
|
|
ds_list_add(__v, values[| i].value[j]);
|
|
|
|
_value_list[| 1] = __v;
|
|
|
|
ds_list_mark_as_list(_value_list, 1);
|
|
|
|
} else {
|
|
|
|
_value_list[| 1] = values[| i].value;
|
|
|
|
}
|
|
|
|
|
|
|
|
_value_list[| 2] = values[| i].ease_in;
|
|
|
|
_value_list[| 3] = values[| i].ease_out;
|
2022-09-23 13:28:42 +02:00
|
|
|
_value_list[| 4] = values[| i].ease_in_type;
|
|
|
|
_value_list[| 5] = values[| i].ease_out_type;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
ds_list_add(_list, _value_list);
|
|
|
|
ds_list_mark_as_list(_list, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static deserialize = function(_list, scale = false) {
|
|
|
|
var base = getValue();
|
|
|
|
ds_list_clear(values);
|
2022-12-12 09:08:03 +01:00
|
|
|
|
2022-01-13 05:24:03 +01:00
|
|
|
for(var i = 0; i < ds_list_size(_list); i++) {
|
|
|
|
var _key = _list[| i];
|
|
|
|
var _time = _key[| 0];
|
2022-09-23 13:28:42 +02:00
|
|
|
if(prop.display_type == VALUE_DISPLAY.gradient)
|
2022-01-13 05:24:03 +01:00
|
|
|
_time = _key[| 0];
|
|
|
|
else if(scale && _key[| 0] <= 1)
|
2022-12-10 05:06:01 +01:00
|
|
|
_time = round(_key[| 0] * (ANIMATOR.frames_total - 1));
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
var ease_in = ds_list_get(_key, 2);
|
2022-01-13 05:24:03 +01:00
|
|
|
var ease_out = ds_list_get(_key, 3);
|
2022-09-23 13:28:42 +02:00
|
|
|
var ease_in_type = ds_list_get(_key, 4, CURVE_TYPE.bezier);
|
|
|
|
var ease_out_type = ds_list_get(_key, 5, CURVE_TYPE.bezier);
|
2022-09-21 06:09:40 +02:00
|
|
|
var _val = 0;
|
2022-12-27 04:00:50 +01:00
|
|
|
var t = typeArray(prop.display_type) && is_array(base);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
if(t) {
|
|
|
|
if(is_string(_key[| 1])) {
|
|
|
|
_val = compat_path_array(_key[| 1]);
|
|
|
|
} else {
|
2022-09-21 06:09:40 +02:00
|
|
|
_val = array_create(array_length(base));
|
|
|
|
|
2022-01-13 05:24:03 +01:00
|
|
|
if(ds_exists(_key[| 1], ds_type_list)) {
|
|
|
|
var ll = t == 1? min(array_length(base), ds_list_size(_key[| 1])) : ds_list_size(_key[| 1]);
|
|
|
|
for(var j = 0; j < ll; j++)
|
2022-09-21 06:09:40 +02:00
|
|
|
_val[j] = processValue(_key[| 1][| j]);
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
}
|
2022-09-21 06:09:40 +02:00
|
|
|
} else
|
2022-01-13 05:24:03 +01:00
|
|
|
_val = _key[| 1];
|
|
|
|
|
2022-09-23 13:28:42 +02:00
|
|
|
var vk = new valueKey(_time, _val, self, ease_in, ease_out);
|
|
|
|
vk.ease_in_type = ease_in_type;
|
|
|
|
vk.ease_out_type = ease_out_type;
|
|
|
|
ds_list_add(values, vk);
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
}
|
2022-01-19 06:11:17 +01:00
|
|
|
|
|
|
|
static cleanUp = function() {
|
|
|
|
ds_list_destroy(values);
|
|
|
|
}
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|