ktx.assets.async.LoadingProgress.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ktx-assets-async Show documentation
Show all versions of ktx-assets-async Show documentation
Asynchronous coroutines-based asset loader for libGDX.
The newest version!
package ktx.assets.async
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.max
import kotlin.math.min
/**
* Tracks the loading progress of the [AssetStorage].
*
* Counts the [total], [loaded] and [failed] assets.
*
* [percent] allows to see current loading progress in range of [0, 1].
*
* The values stored by the [LoadingProgress] are _eventually consistent._
* The progress can go slightly out of sync of the actual amounts of loaded assets,
* as it is not protected by the [AssetStorage.lock].
*
* Due to the asynchronous nature of [AssetStorage], some assets that will eventually
* be scheduled by coroutines might not be counted by [LoadingProgress] yet.
* Calling [AssetStorage.load] or [AssetStorage.loadAsync] is not guaranteed
* to immediately update the [total] number of assets.
*
* Use the [LoadingProgress] for display only and base your actual application
* logic on [AssetStorage] API instead.
*/
class LoadingProgress {
private val totalCounter = AtomicInteger()
private val loadedCounter = AtomicInteger()
private val failedCounter = AtomicInteger()
/** Total number of scheduled assets. */
val total: Int
get() = totalCounter.get()
/** Total number of successfully loaded assets. */
val loaded: Int
get() = loadedCounter.get()
/** Total number of assets that failed to load. */
val failed: Int
get() = failedCounter.get()
/** Current asset loading percent. Does not take [failed] assets into account. */
val percent: Float
get() {
val total = max(totalCounter.get(), 0)
val loaded = max(min(loadedCounter.get(), total), 0)
return when {
total == 0 || loaded == 0 -> 0f
total == loaded -> 1f
else -> loaded.toFloat() / total.toFloat()
}
}
/**
* True if all registered assets are loaded or failed to load.
*
* Remember that his value might not reflect the actual state of all assets that are being scheduled
* due to the asynchronous nature of [AssetStorage].
*/
val isFinished: Boolean
get() = total > 0 && (loadedCounter.get() + failedCounter.get()) == totalCounter.get()
/** True if there are any [failed] assets. */
val isFailed: Boolean
get() = failedCounter.get() > 0
/** Must be called after a new asset was scheduled for loading. */
internal fun registerScheduledAsset() {
totalCounter.incrementAndGet()
}
/** Must be called after a new loaded asset was added manually. */
internal fun registerAddedAsset() {
totalCounter.incrementAndGet()
loadedCounter.incrementAndGet()
}
/** Must be called after an asset has finished loading. */
internal fun registerLoadedAsset() {
loadedCounter.incrementAndGet()
}
/** Must be called after an asset failed to load successfully. */
internal fun registerFailedAsset() {
failedCounter.incrementAndGet()
}
/** Must be called after a fully loaded asset was unloaded. */
internal fun removeLoadedAsset() {
totalCounter.decrementAndGet()
loadedCounter.decrementAndGet()
}
/** Must be called after an asset currently in the process of loading was cancelled and unloaded. */
internal fun removeScheduledAsset() {
totalCounter.decrementAndGet()
}
/** Must be called after an unsuccessfully loaded asset was unloaded. */
internal fun removeFailedAsset() {
totalCounter.decrementAndGet()
failedCounter.decrementAndGet()
}
/** Must be called after disposal of all assets. */
internal fun reset() {
totalCounter.set(0)
loadedCounter.set(0)
failedCounter.set(0)
}
}