diff --git a/scripts/animation_controller/animation_controller.gml b/scripts/animation_controller/animation_controller.gml index 3ee873d55..7a3a42f8d 100644 --- a/scripts/animation_controller/animation_controller.gml +++ b/scripts/animation_controller/animation_controller.gml @@ -1,7 +1,8 @@ #region global enum ANIMATOR_END { loop, - stop + stop, + pingpong, } #macro ANIMATION_STATIC !(PROJECT.animator.is_playing || PROJECT.animator.frame_progress) @@ -32,17 +33,18 @@ frame_progress = false; frame_range = noone; + play_direction = 1; is_simulating = false; __debug_animator_counter = 0; playback = ANIMATOR_END.loop; - static setFrame = function(frame, _round = true) { #region + static setFrame = function(_frame, _round = true) { var _c = current_frame; - frame = clamp(frame, 0, frames_total); - real_frame = frame; - current_frame = _round? round(frame) : frame; + _frame = clamp(_frame, 0, frames_total); + real_frame = _frame; + current_frame = _round? round(_frame) : _frame; frame_progress = _c != current_frame; @@ -50,53 +52,44 @@ time_since_last_frame = 0; RENDER_ALL } - } #endregion + } - static getFirstFrame = function(range = true) { INLINE return range && frame_range != noone? frame_range[0] - 1 : 0; } - static getLastFrame = function(range = true) { INLINE return range && frame_range != noone? frame_range[1] - 1 : frames_total - 1; } + static getFirstFrame = function(range = true) { return range && frame_range != noone? frame_range[0] - 1 : 0; } + static getLastFrame = function(range = true) { return range && frame_range != noone? frame_range[1] - 1 : frames_total - 1; } - static firstFrame = function(range = true) { INLINE setFrame(getFirstFrame(range)); } - static lastFrame = function(range = true) { INLINE setFrame(getLastFrame(range)); } + static firstFrame = function(range = true) { setFrame(getFirstFrame(range)); } + static lastFrame = function(range = true) { setFrame(getLastFrame(range)); } - static isFirstFrame = function() { INLINE return current_frame == getFirstFrame(); } - static isLastFrame = function() { INLINE return current_frame == getLastFrame(); } + static isFirstFrame = function() { return current_frame == getFirstFrame(); } + static isLastFrame = function() { return current_frame == getLastFrame(); } - static resetAnimation = function() { #region - INLINE - + static resetAnimation = function() { array_foreach(PROJECT.allNodes, function(node) { node.resetAnimation(); }); - } #endregion + } - static toggle = function() { #region - INLINE - + static toggle = function() { is_playing = !is_playing; frame_progress = true; time_since_last_frame = 0; - } #endregion + } - static pause = function() { #region - INLINE - + static pause = function() { is_playing = false; frame_progress = true; time_since_last_frame = 0; - } #endregion + } - static play = function() { #region - INLINE - + static play = function() { if(is_simulating) setFrame(0); else firstFrame(); is_playing = true; frame_progress = true; time_since_last_frame = 0; - } #endregion + play_direction = 1; + } - static render = function() { #region - INLINE - + static render = function() { if(is_simulating) setFrame(0); else firstFrame(); @@ -104,28 +97,22 @@ is_rendering = true; frame_progress = true; time_since_last_frame = 0; - } #endregion + } - static resume = function() { #region - INLINE - + static resume = function() { is_playing = true; frame_progress = true; time_since_last_frame = 0; - } #endregion + } - static stop = function() { #region - INLINE - + static stop = function() { firstFrame(); is_playing = false; time_since_last_frame = 0; - } #endregion + } - static step = function() { #region - INLINE - + static step = function() { if(frame_range != noone) { var _fr0 = min(frame_range[0], frame_range[1]); var _fr1 = max(frame_range[0], frame_range[1]); @@ -142,28 +129,32 @@ var _frTime = 1 / framerate; time_since_last_frame += delta_time / 1_000_000; - var tslf = time_since_last_frame; - if(0 && IS_CMD) { - setFrame(real_frame + 1); - - } else if(time_since_last_frame >= _frTime) { - var dt = time_since_last_frame - _frTime; - setFrame(real_frame + 1); - time_since_last_frame = dt; - - var _maxFrame = frame_range != noone? frame_range[1] : frames_total; - if(current_frame >= _maxFrame) { - firstFrame(); - - if(playback == ANIMATOR_END.stop || is_rendering) { - is_playing = false; - is_rendering = false; - time_since_last_frame = 0; - } - } + if(time_since_last_frame < _frTime) return; + var dt = time_since_last_frame - _frTime; + setFrame(real_frame + play_direction); + time_since_last_frame = dt; + + var _maxFrame = frame_range != noone? frame_range[1] : frames_total; + + if(current_frame >= _maxFrame) { + firstFrame(); + + if(playback == ANIMATOR_END.stop || is_rendering) { + is_playing = false; + is_rendering = false; + time_since_last_frame = 0; + + } else if(playback == ANIMATOR_END.pingpong) { + setFrame(max(0, frames_total - 2)); + play_direction = -1; + } + + } else if(current_frame <= 0) { + if(playback == ANIMATOR_END.pingpong) + play_direction = 1; } - } #endregion + } } #endregion \ No newline at end of file diff --git a/scripts/panel_animation_settings/panel_animation_settings.gml b/scripts/panel_animation_settings/panel_animation_settings.gml index cc1ee53a2..2730bf8eb 100644 --- a/scripts/panel_animation_settings/panel_animation_settings.gml +++ b/scripts/panel_animation_settings/panel_animation_settings.gml @@ -17,7 +17,7 @@ function Panel_Animation_Setting() : Panel_Linear_Setting() constructor { ), new __Panel_Linear_Setting_Item( __txtx("anim_on_end", "On end"), - new buttonGroup([__txt("Loop"), __txt("Stop")], function(b) { PROJECT.animator.playback = b; }), + new buttonGroup([ __txt("Loop"), __txt("Stop"), __txt("Ping Pong")], function(b) { PROJECT.animator.playback = b; }), function() { return PROJECT.animator.playback; } ), ]; diff --git a/scripts/project_data/project_data.gml b/scripts/project_data/project_data.gml index 7f04b10c2..93574f38a 100644 --- a/scripts/project_data/project_data.gml +++ b/scripts/project_data/project_data.gml @@ -164,6 +164,7 @@ _anim_map.frames_total = animator.frames_total; _anim_map.framerate = animator.framerate; _anim_map.frame_range = animator.frame_range; + _anim_map.playback = animator.playback; _map.animator = _anim_map; _map.metadata = meta.serialize(); @@ -204,6 +205,7 @@ animator.frames_total = struct_try_get(_anim_map, "frames_total", 30); animator.framerate = struct_try_get(_anim_map, "framerate", 30); animator.frame_range = struct_try_get(_anim_map, "frame_range", noone); + animator.playback = struct_try_get(_anim_map, "playback", ANIMATOR_END.loop); } if(struct_has(_map, "onion_skin")) struct_override(onion_skin, _map.onion_skin);