All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.barrybecker4.ui.animation.FrameRateCalculator.scala Maven / Gradle / Ivy

// Copyright by Barry G. Becker, 2017 - 2018. Licensed under MIT License: http://www.opensource.org/licenses/MIT
package com.barrybecker4.ui.animation

import FrameRateCalculator.HISTORY_LENGTH

/**
  * Calculates the frame rate given previous times in milliseconds
  * @see AnimationComponent
  * @author Barry Becker
  */
object FrameRateCalculator {
  /** keep times for this many recent frames so we can get a more accurate averate */
  private val HISTORY_LENGTH = 32
}

class FrameRateCalculator() {

  /** previous times in milliseconds. */
  private val previousTimes = new Array[Long](HISTORY_LENGTH)

  /** incremented for every frame that is shown */
  private var frameCount = 0L

  previousTimes(0) = System.currentTimeMillis

  /** frames per second. */
  private var frameRate = .0
  /** becomes dirty when the frameCount changes */

  private var dirty = true
  private var startPauseTime = 0L
  private var totalPauseTime: Long = 0L
  private var isPaused = false

  /**
    * This must be called right before each frame is rendered.
    * Calling it when paused does nothing.
    */
  def incrementFrameCount(): Unit = {
    if (!isPaused) {
      frameCount += 1
      previousTimes(getIndex) = System.currentTimeMillis - totalPauseTime
      dirty = true
    }
  }

  /** @return the number of animation frames so far */
  def getFrameCount: Long = frameCount

  def getFrameRate: Double = {
    if (dirty) calculateFrameRate()
    frameRate
  }

  def setPaused(paused: Boolean): Unit = {
    if (paused != isPaused) {
      if (paused) startPauseTime = System.currentTimeMillis
      else totalPauseTime += System.currentTimeMillis - startPauseTime
      isPaused = paused
    }
  }

  /** Determine the number of frames per second as a moving average.
    * Use the more stable method of calculation if all history is available.
    */
  private def calculateFrameRate(): Unit = {
    var deltaTime = 0.0
    val index = getIndex
    val now = System.currentTimeMillis - totalPauseTime.toDouble
    if (frameCount < HISTORY_LENGTH) {
      deltaTime = now - previousTimes(0)
      frameRate = if (deltaTime == 0) 0.0 else (1000.0 * index) / deltaTime
    }
    else {
      deltaTime = now - previousTimes((index + 1) % HISTORY_LENGTH)
      frameRate = if (deltaTime == 0) 0 else (1000.0 * HISTORY_LENGTH) / deltaTime
    }
    if (frameRate < 0) {
      throw new IllegalStateException(
        s"The frame-rate unexpectedly fell below 0. " +
          s"index=$index deltaTime=$deltaTime fct=$frameCount fr=$frameRate totalPause=$totalPauseTime " +
          s"prev=${previousTimes((index + 1) % HISTORY_LENGTH)}")
    }
    dirty = false
  }

  private def getIndex = (frameCount % HISTORY_LENGTH).toInt
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy