Skip to content

Commit a119884

Browse files
committed
Merge branch 'master' into core_os2_revamp
2 parents f8afec5 + ade1890 commit a119884

File tree

5 files changed

+475
-208
lines changed

5 files changed

+475
-208
lines changed

core/math/ease/ease.odin

Lines changed: 34 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
// Easing procedures and flux easing used for animations.
1+
// Easing procedures used for animations.
22
package ease
33

4-
import "core:math"
4+
@require import "core:math"
55
import "base:intrinsics"
6-
import "core:time"
76

87
@(private) PI_2 :: math.PI / 2
98

@@ -174,7 +173,7 @@ exponential_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_f
174173
if p == 0.0 || p == 1.0 {
175174
return p
176175
}
177-
176+
178177
if p < 0.5 {
179178
return 0.5 * math.pow(2, (20 * p) - 10)
180179
} else {
@@ -307,224 +306,51 @@ Ease :: enum {
307306
}
308307

309308
@(require_results)
310-
ease :: proc "contextless" (type: Ease, p: $T) -> T
311-
where intrinsics.type_is_float(T) {
309+
ease :: proc "contextless" (type: Ease, p: $T) -> T where intrinsics.type_is_float(T) {
312310
switch type {
313-
case .Linear: return p
311+
case .Linear: return p
314312

315-
case .Quadratic_In: return quadratic_in(p)
316-
case .Quadratic_Out: return quadratic_out(p)
317-
case .Quadratic_In_Out: return quadratic_in_out(p)
313+
case .Quadratic_In: return quadratic_in(p)
314+
case .Quadratic_Out: return quadratic_out(p)
315+
case .Quadratic_In_Out: return quadratic_in_out(p)
318316

319-
case .Cubic_In: return cubic_in(p)
320-
case .Cubic_Out: return cubic_out(p)
321-
case .Cubic_In_Out: return cubic_in_out(p)
317+
case .Cubic_In: return cubic_in(p)
318+
case .Cubic_Out: return cubic_out(p)
319+
case .Cubic_In_Out: return cubic_in_out(p)
322320

323-
case .Quartic_In: return quartic_in(p)
324-
case .Quartic_Out: return quartic_out(p)
325-
case .Quartic_In_Out: return quartic_in_out(p)
321+
case .Quartic_In: return quartic_in(p)
322+
case .Quartic_Out: return quartic_out(p)
323+
case .Quartic_In_Out: return quartic_in_out(p)
326324

327-
case .Quintic_In: return quintic_in(p)
328-
case .Quintic_Out: return quintic_out(p)
329-
case .Quintic_In_Out: return quintic_in_out(p)
325+
case .Quintic_In: return quintic_in(p)
326+
case .Quintic_Out: return quintic_out(p)
327+
case .Quintic_In_Out: return quintic_in_out(p)
330328

331-
case .Sine_In: return sine_in(p)
332-
case .Sine_Out: return sine_out(p)
333-
case .Sine_In_Out: return sine_in_out(p)
329+
case .Sine_In: return sine_in(p)
330+
case .Sine_Out: return sine_out(p)
331+
case .Sine_In_Out: return sine_in_out(p)
334332

335-
case .Circular_In: return circular_in(p)
336-
case .Circular_Out: return circular_out(p)
337-
case .Circular_In_Out: return circular_in_out(p)
333+
case .Circular_In: return circular_in(p)
334+
case .Circular_Out: return circular_out(p)
335+
case .Circular_In_Out: return circular_in_out(p)
338336

339-
case .Exponential_In: return exponential_in(p)
340-
case .Exponential_Out: return exponential_out(p)
337+
case .Exponential_In: return exponential_in(p)
338+
case .Exponential_Out: return exponential_out(p)
341339
case .Exponential_In_Out: return exponential_in_out(p)
342340

343-
case .Elastic_In: return elastic_in(p)
344-
case .Elastic_Out: return elastic_out(p)
345-
case .Elastic_In_Out: return elastic_in_out(p)
341+
case .Elastic_In: return elastic_in(p)
342+
case .Elastic_Out: return elastic_out(p)
343+
case .Elastic_In_Out: return elastic_in_out(p)
346344

347-
case .Back_In: return back_in(p)
348-
case .Back_Out: return back_out(p)
349-
case .Back_In_Out: return back_in_out(p)
345+
case .Back_In: return back_in(p)
346+
case .Back_Out: return back_out(p)
347+
case .Back_In_Out: return back_in_out(p)
350348

351-
case .Bounce_In: return bounce_in(p)
352-
case .Bounce_Out: return bounce_out(p)
353-
case .Bounce_In_Out: return bounce_in_out(p)
349+
case .Bounce_In: return bounce_in(p)
350+
case .Bounce_Out: return bounce_out(p)
351+
case .Bounce_In_Out: return bounce_in_out(p)
354352
}
355353

356354
// in case type was invalid
357355
return 0
358356
}
359-
Flux_Map :: struct($T: typeid) {
360-
values: map[^T]Flux_Tween(T),
361-
keys_to_be_deleted: [dynamic]^T,
362-
}
363-
364-
Flux_Tween :: struct($T: typeid) {
365-
value: ^T,
366-
start: T,
367-
diff: T,
368-
goal: T,
369-
370-
delay: f64, // in seconds
371-
duration: time.Duration,
372-
373-
progress: f64,
374-
rate: f64,
375-
type: Ease,
376-
377-
inited: bool,
378-
379-
// callbacks, data can be set, will be pushed to callback
380-
data: rawptr, // by default gets set to value input
381-
on_start: proc(flux: ^Flux_Map(T), data: rawptr),
382-
on_update: proc(flux: ^Flux_Map(T), data: rawptr),
383-
on_complete: proc(flux: ^Flux_Map(T), data: rawptr),
384-
}
385-
386-
// init flux map to a float type and a wanted cap
387-
@(require_results)
388-
flux_init :: proc($T: typeid, value_capacity := 8) -> Flux_Map(T) where intrinsics.type_is_float(T) {
389-
return {
390-
values = make(map[^T]Flux_Tween(T), value_capacity),
391-
keys_to_be_deleted = make([dynamic]^T, 0, value_capacity),
392-
}
393-
}
394-
395-
// delete map content
396-
flux_destroy :: proc(flux: Flux_Map($T)) where intrinsics.type_is_float(T) {
397-
delete(flux.values)
398-
delete(flux.keys_to_be_deleted)
399-
}
400-
401-
// clear map content, stops all animations
402-
flux_clear :: proc(flux: ^Flux_Map($T)) where intrinsics.type_is_float(T) {
403-
clear(&flux.values)
404-
}
405-
406-
// append / overwrite existing tween value to parameters
407-
// rest is initialized in flux_tween_init, inside update
408-
// return value can be used to set callbacks
409-
@(require_results)
410-
flux_to :: proc(
411-
flux: ^Flux_Map($T),
412-
value: ^T,
413-
goal: T,
414-
type: Ease = .Quadratic_Out,
415-
duration: time.Duration = time.Second,
416-
delay: f64 = 0,
417-
) -> (tween: ^Flux_Tween(T)) where intrinsics.type_is_float(T) {
418-
if res, ok := &flux.values[value]; ok {
419-
tween = res
420-
} else {
421-
flux.values[value] = {}
422-
tween = &flux.values[value]
423-
}
424-
425-
tween^ = {
426-
value = value,
427-
goal = goal,
428-
duration = duration,
429-
delay = delay,
430-
type = type,
431-
data = value,
432-
}
433-
434-
return
435-
}
436-
437-
// init internal properties
438-
flux_tween_init :: proc(tween: ^Flux_Tween($T), duration: time.Duration) where intrinsics.type_is_float(T) {
439-
tween.inited = true
440-
tween.start = tween.value^
441-
tween.diff = tween.goal - tween.value^
442-
s := time.duration_seconds(duration)
443-
tween.rate = duration > 0 ? 1.0 / s : 0
444-
tween.progress = duration > 0 ? 0 : 1
445-
}
446-
447-
// update all tweens, wait for their delay if one exists
448-
// calls callbacks in all stages, when they're filled
449-
// deletes tween from the map after completion
450-
flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) {
451-
clear(&flux.keys_to_be_deleted)
452-
453-
for key, &tween in flux.values {
454-
delay_remainder := f64(0)
455-
456-
// Update delay if necessary.
457-
if tween.delay > 0 {
458-
tween.delay -= dt
459-
460-
if tween.delay < 0 {
461-
// We finished the delay, but in doing so consumed part of this frame's `dt` budget.
462-
// Keep track of it so we can apply it to this tween without affecting others.
463-
delay_remainder = tween.delay
464-
// We're done with this delay.
465-
tween.delay = 0
466-
}
467-
}
468-
469-
// We either had no delay, or the delay has been consumed.
470-
if tween.delay <= 0 {
471-
if !tween.inited {
472-
flux_tween_init(&tween, tween.duration)
473-
474-
if tween.on_start != nil {
475-
tween.on_start(flux, tween.data)
476-
}
477-
}
478-
479-
// If part of the `dt` budget was consumed this frame, then `delay_remainder` will be
480-
// that remainder, a negative value. Adding it to `dt` applies what's left of the `dt`
481-
// to the tween so it advances properly, instead of too much or little.
482-
tween.progress += tween.rate * (dt + delay_remainder)
483-
x := tween.progress >= 1 ? 1 : ease(tween.type, tween.progress)
484-
tween.value^ = tween.start + tween.diff * T(x)
485-
486-
if tween.on_update != nil {
487-
tween.on_update(flux, tween.data)
488-
}
489-
490-
if tween.progress >= 1 {
491-
// append keys to array that will be deleted after the loop
492-
append(&flux.keys_to_be_deleted, key)
493-
494-
if tween.on_complete != nil {
495-
tween.on_complete(flux, tween.data)
496-
}
497-
}
498-
}
499-
}
500-
501-
// loop through keys that should be deleted from the map
502-
if len(flux.keys_to_be_deleted) != 0 {
503-
for key in flux.keys_to_be_deleted {
504-
delete_key(&flux.values, key)
505-
}
506-
}
507-
}
508-
509-
// stop a specific key inside the map
510-
// returns true when it successfully removed the key
511-
@(require_results)
512-
flux_stop :: proc(flux: ^Flux_Map($T), key: ^T) -> bool where intrinsics.type_is_float(T) {
513-
if key in flux.values {
514-
delete_key(&flux.values, key)
515-
return true
516-
}
517-
518-
return false
519-
}
520-
521-
// returns the amount of time left for the tween animation, if the key exists in the map
522-
// returns 0 if the tween doesnt exist on the map
523-
@(require_results)
524-
flux_tween_time_left :: proc(flux: Flux_Map($T), key: ^T) -> f64 {
525-
if tween, ok := flux.values[key]; ok {
526-
return ((1 - tween.progress) * tween.rate) + tween.delay
527-
} else {
528-
return 0
529-
}
530-
}

0 commit comments

Comments
 (0)