mirror of
https://github.com/mdgriffith/elm-animator.git
synced 2024-09-11 12:47:52 +03:00
ove duration discounting to when interruptions are applied
This commit is contained in:
parent
016ede0536
commit
3237d09237
@ -333,44 +333,10 @@ interrupt steps ((Timeline.Timeline tl) as fullTimeline) =
|
||||
-- **NOTE** - if we recieve a new interruption, we throw away the existing one!
|
||||
-- This was leading to issues when the same event was added to the `interrupted` queue
|
||||
-- multiple times in before being scheduled.
|
||||
-- Also
|
||||
-- If we're returning to a previous state while enroute to a new state,
|
||||
-- we can "discount" the duration to return.
|
||||
let
|
||||
discountedSchedule =
|
||||
if Duration.isZero (scheduleDelay schedule) && previous fullTimeline == currentScheduleTarget schedule then
|
||||
let
|
||||
transitionProgress =
|
||||
Timeline.transitionProgress fullTimeline
|
||||
in
|
||||
schedule
|
||||
|> scaleScheduleDurationBy (Maybe.withDefault 1 <| List.maximum transitionProgress)
|
||||
|
||||
else
|
||||
schedule
|
||||
in
|
||||
[ List.foldl stepsToEvents discountedSchedule otherSteps ]
|
||||
[ List.foldl stepsToEvents schedule otherSteps ]
|
||||
}
|
||||
|
||||
|
||||
scaleScheduleDurationBy : Float -> Timeline.Schedule state -> Timeline.Schedule state
|
||||
scaleScheduleDurationBy factor (Timeline.Schedule currentScheduleDelay (Timeline.Event dur checkpoint dwell) events) =
|
||||
Timeline.Schedule
|
||||
currentScheduleDelay
|
||||
(Timeline.Event (Duration.scale factor dur) checkpoint dwell)
|
||||
events
|
||||
|
||||
|
||||
scheduleDelay : Timeline.Schedule state -> Time.Duration
|
||||
scheduleDelay (Timeline.Schedule d _ _) =
|
||||
d
|
||||
|
||||
|
||||
currentScheduleTarget : Timeline.Schedule state -> state
|
||||
currentScheduleTarget (Timeline.Schedule _ (Timeline.Event _ target _) _) =
|
||||
target
|
||||
|
||||
|
||||
{-| -}
|
||||
initializeSchedule : Time.Duration -> List (Step state) -> Maybe ( Schedule state, List (Step state) )
|
||||
initializeSchedule waiting steps =
|
||||
|
@ -61,6 +61,16 @@ getScheduledEvent (Event _ ev _) =
|
||||
ev
|
||||
|
||||
|
||||
currentScheduleTarget : Schedule event -> event
|
||||
currentScheduleTarget (Schedule _ (Event _ target _) _) =
|
||||
target
|
||||
|
||||
|
||||
scheduleDelay : Schedule state -> Time.Duration
|
||||
scheduleDelay (Schedule d _ _) =
|
||||
d
|
||||
|
||||
|
||||
adjustScheduledDuration : (Time.Duration -> Time.Duration) -> Event event -> Event event
|
||||
adjustScheduledDuration fn (Event dur ev maybeDwell) =
|
||||
Event (fn dur) ev maybeDwell
|
||||
@ -502,18 +512,38 @@ scheduledEventEqual (Event _ schedEvent _) (Occurring occurEvent _ _) =
|
||||
|
||||
applyInterruptions : TimelineDetails event -> TimelineDetails event
|
||||
applyInterruptions timeline =
|
||||
case timeline.interruption of
|
||||
-- Note, the foldl is reversing the interruptions, which is intentional
|
||||
-- we reverse the interruptions so that they're applied as First-in-First-Out.
|
||||
-- If we do Last-in-First-Out we run into issues.
|
||||
-- Imagine mouse events coming in where there is movement and then an end.
|
||||
-- It means `timeline.interruptions` would be the following
|
||||
-- [End, Move, Move, Move]
|
||||
-- We have to reverse the list so they're processed as [Move, Move, Move, End]
|
||||
let
|
||||
discountInterruption schedule discounted =
|
||||
-- If we're returning to a previous state while enroute to a new state,
|
||||
-- we can "discount" the duration to return.
|
||||
if Duration.isZero (scheduleDelay schedule) && previous (Timeline timeline) == currentScheduleTarget schedule then
|
||||
let
|
||||
maxProgress =
|
||||
transitionProgress (Timeline timeline)
|
||||
|> List.maximum
|
||||
|> Maybe.withDefault 1
|
||||
in
|
||||
(schedule
|
||||
|> scaleScheduleDurationBy maxProgress
|
||||
)
|
||||
:: discounted
|
||||
|
||||
else
|
||||
schedule :: discounted
|
||||
in
|
||||
case List.foldl discountInterruption [] timeline.interruption of
|
||||
[] ->
|
||||
timeline
|
||||
|
||||
_ ->
|
||||
-- Note, we reverse the interruptions so that they're applied as First-in-First-Out.
|
||||
-- If we do Last-in-First-Out we run into issues.
|
||||
-- Imagine mouse events coming in where there is movement and then an end.
|
||||
-- It means `timeline.interruptions` would be the following
|
||||
-- [End, Move, Move, Move]
|
||||
-- We have to reverse the list so they're processed as [Move, Move, Move, End]
|
||||
applyInterruptionHelper (List.reverse timeline.interruption)
|
||||
interruptions ->
|
||||
applyInterruptionHelper interruptions
|
||||
{ timeline | interruption = [] }
|
||||
|
||||
|
||||
@ -537,6 +567,14 @@ applyInterruptionHelper interrupts timeline =
|
||||
}
|
||||
|
||||
|
||||
scaleScheduleDurationBy : Float -> Schedule state -> Schedule state
|
||||
scaleScheduleDurationBy factor (Schedule currentScheduleDelay (Event dur checkpoint dwell) events) =
|
||||
Schedule
|
||||
currentScheduleDelay
|
||||
(Event (Duration.scale factor dur) checkpoint dwell)
|
||||
events
|
||||
|
||||
|
||||
{-| Interrupt a current timetable with a new list of events.
|
||||
|
||||
- If this timeline is after all other timelines
|
||||
@ -565,9 +603,7 @@ interruptLines now scheduled pastLines lines =
|
||||
startLine :: remaining ->
|
||||
let
|
||||
startInterruption =
|
||||
case scheduled of
|
||||
Schedule scheduleDelay _ _ ->
|
||||
Time.advanceBy scheduleDelay now
|
||||
Time.advanceBy (scheduleDelay scheduled) now
|
||||
in
|
||||
if interruptionHappensLater startInterruption remaining then
|
||||
interruptLines now scheduled (startLine :: pastLines) remaining
|
||||
@ -608,9 +644,7 @@ interruptLine now scheduled line future =
|
||||
Line start startEvent trailing ->
|
||||
let
|
||||
startInterruption =
|
||||
case scheduled of
|
||||
Schedule scheduleDelay _ _ ->
|
||||
Time.advanceBy scheduleDelay now
|
||||
Time.advanceBy (scheduleDelay scheduled) now
|
||||
in
|
||||
if Time.thisAfterOrEqualThat startInterruption start then
|
||||
-- this line starts before the interruption
|
||||
@ -804,7 +838,7 @@ createLine now (Schedule delay (Event dur startEvent maybeDwell) reverseQueued)
|
||||
|
||||
-}
|
||||
addEventsToLine : Time.Absolute -> Schedule events -> Line events -> List (Line events) -> List (Line events)
|
||||
addEventsToLine now ((Schedule scheduleDelay _ _) as scheduled) (Line startLineAt startingEvent events) lines =
|
||||
addEventsToLine now scheduled (Line startLineAt startingEvent events) lines =
|
||||
case List.reverse events of
|
||||
[] ->
|
||||
let
|
||||
@ -821,7 +855,7 @@ addEventsToLine now ((Schedule scheduleDelay _ _) as scheduled) (Line startLineA
|
||||
Occurring ev eventStart _ ->
|
||||
-- if the scheduled events are way after the current event
|
||||
-- extend that events dwell until the start of the scheduled stuff
|
||||
Occurring ev eventStart (Time.advanceBy scheduleDelay startNewEventsAt)
|
||||
Occurring ev eventStart (Time.advanceBy (scheduleDelay scheduled) startNewEventsAt)
|
||||
in
|
||||
Line startLineAt startingEventWithDwell [] :: newLine :: lines
|
||||
|
||||
@ -842,7 +876,7 @@ addEventsToLine now ((Schedule scheduleDelay _ _) as scheduled) (Line startLineA
|
||||
lastEventTime
|
||||
-- createLine handles applying the schedule scheduleDelay
|
||||
-- but we need to apply it here manually
|
||||
(Time.advanceBy scheduleDelay startNewEventsAt)
|
||||
(Time.advanceBy (scheduleDelay scheduled) startNewEventsAt)
|
||||
in
|
||||
Line startLineAt
|
||||
startingEvent
|
||||
|
Loading…
Reference in New Issue
Block a user