Skip to content

Commit

Permalink
KTX 1.11.0-rc1 release. #416
Browse files Browse the repository at this point in the history
  • Loading branch information
czyzby committed May 22, 2022
2 parents 9716f90 + 335a541 commit 73fc120
Show file tree
Hide file tree
Showing 21 changed files with 140 additions and 67 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
_See also: [the official libGDX changelog](https://github.com/libgdx/libgdx/blob/master/CHANGES)._

#### 1.11.0-rc1

- **[UPDATE]** Updated to libGDX 1.11.0.
- **[MISC]** Gradle dependencies changed from _compile-only_ to _API_ scope.
- **[FEATURE]** (`ktx-app`) Added `gdxError` utility that throws a `GdxRuntimeException`.
- **[FIX]** (`ktx-assets-async`) Fixed a niche bug with `AsyncAssetManager` which could lead to missed callbacks
after attempting to load the same asset concurrently with `loadAsync`.

#### 1.10.0-rc2

- **[UPDATE]** Updated to Kotlin 1.6.21.
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![GitHub Build](https://github.com/libktx/ktx/workflows/build/badge.svg)](https://github.com/libktx/ktx/actions?query=workflow%3Abuild)
[![Kotlin](https://img.shields.io/badge/kotlin-1.6.21-orange.svg)](http://kotlinlang.org/)
[![libGDX](https://img.shields.io/badge/libgdx-1.10.0-red.svg)](https://libgdx.com/)
[![libGDX](https://img.shields.io/badge/libgdx-1.11.0-red.svg)](https://libgdx.com/)
[![Maven Central](https://img.shields.io/maven-central/v/io.github.libktx/ktx-async.svg)](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22io.github.libktx%22)

[![KTX](.github/ktx-logo.png "KTX")](http://libktx.github.io)
Expand Down Expand Up @@ -79,7 +79,7 @@ in your `build.gradle` file:
// Groovy DSL:
ext {
// Update this version to match the latest KTX release:
ktxVersion = '1.10.0-rc1'
ktxVersion = '1.11.0-rc1'
}
dependencies {
Expand All @@ -91,7 +91,7 @@ dependencies {
// Kotlin DSL:

// Update this version to match the latest KTX release:
val ktxVersion = "1.10.0-rc1"
val ktxVersion = "1.11.0-rc1"

dependencies {
api(group = "io.github.libktx", name = "ktx-app", version = ktxVersion)
Expand Down Expand Up @@ -145,7 +145,7 @@ repositories {
ext {
// Update this version to match the latest libGDX release:
ktxVersion = '1.10.0-SNAPSHOT'
ktxVersion = '1.11.0-SNAPSHOT'
}
```

Expand All @@ -157,7 +157,7 @@ repositories {
}

// Update this version to match the latest libGDX release:
val ktxVersion = "1.10.0-SNAPSHOT"
val ktxVersion = "1.11.0-SNAPSHOT"
```

The latest snapshot version name can be found on the [`develop`](https://github.com/libktx/ktx/blob/develop/version.txt)
Expand Down
1 change: 1 addition & 0 deletions app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ being a class like `com.badlogic.gdx.InputAdapter`.
- `clearScreen` is an inlined utility function that hides the OpenGL calls, allowing to clear the screen with a chosen
color.
- `emptyScreen` provides no-op implementations of `Screen`.
- `gdxError` throws a `GdxRuntimeException` with an optional message and cause.

#### Platform-specific utilities

Expand Down
11 changes: 11 additions & 0 deletions app/src/main/kotlin/ktx/app/exceptions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ktx.app

import com.badlogic.gdx.utils.GdxRuntimeException

/**
* Throws a [GdxRuntimeException]. The [message] will be converted to string and passed as the exception message.
* The [cause] is an optional exception cause. See also: [error].
*/
@Suppress("NOTHING_TO_INLINE")
inline fun gdxError(message: Any? = null, cause: Throwable? = null): Nothing =
throw GdxRuntimeException(message.toString(), cause)
55 changes: 55 additions & 0 deletions app/src/test/kotlin/ktx/app/ExceptionsTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package ktx.app

import com.badlogic.gdx.utils.GdxRuntimeException
import io.kotlintest.matchers.shouldThrow
import org.junit.Assert.assertEquals
import org.junit.Assert.assertSame
import org.junit.Test

class ExceptionsTest {
@Test
fun `should throw error`() {
shouldThrow<GdxRuntimeException> {
gdxError()
}
}

@Test
fun `should throw error given a null message`() {
val exception = shouldThrow<GdxRuntimeException> {
gdxError(null)
}

assertEquals("null", exception.message)
}

@Test
fun `should throw error given a string message`() {
val exception = shouldThrow<GdxRuntimeException> {
gdxError("Test")
}

assertEquals("Test", exception.message)
}

@Test
fun `should throw error given an object message`() {
val exception = shouldThrow<GdxRuntimeException> {
gdxError(42)
}

assertEquals("42", exception.message)
}

@Test
fun `should throw error given a cause`() {
val cause = Exception()

val exception = shouldThrow<GdxRuntimeException> {
gdxError("Message", cause)
}

assertEquals("Message", exception.message)
assertSame(cause, exception.cause)
}
}
2 changes: 1 addition & 1 deletion ashley/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import ktx.*
val junitPlatformVersion: String by project

dependencies {
compileOnly("com.badlogicgames.ashley:ashley:$ashleyVersion")
api("com.badlogicgames.ashley:ashley:$ashleyVersion")

testImplementation("org.jetbrains.spek:spek-api:$spekVersion")
testImplementation("org.assertj:assertj-core:$assertjVersion")
Expand Down
8 changes: 4 additions & 4 deletions assets-async/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont
// A common example of this would be getting the assets for the loading screen.
// In this case you can use `loadSync`, which will block the current thread until
// the asset is loaded:
val font = assetStorage.loadSync<BitmapFont>("com/badlogic/gdx/utils/arial-15.fnt")
val font = assetStorage.loadSync<BitmapFont>("com/badlogic/gdx/utils/lsans-15.fnt")

// Note that you should not use `loadSync` from within coroutines.

Expand Down Expand Up @@ -733,7 +733,7 @@ class WithAssetManager: ApplicationAdapter() {

// Scheduling assets for asynchronous loading:
assetManager.load("images/logo.png", Texture::class.java)
assetManager.load("com/badlogic/gdx/utils/arial-15.fnt", BitmapFont::class.java)
assetManager.load("com/badlogic/gdx/utils/lsans-15.fnt", BitmapFont::class.java)
}

override fun render() {
Expand Down Expand Up @@ -794,7 +794,7 @@ class WithAssetStorageBasic: ApplicationAdapter() {

// Scheduling assets for asynchronous loading:
assetStorage.loadAsync<Texture>("images/logo.png")
assetStorage.loadAsync<BitmapFont>("com/badlogic/gdx/utils/arial-15.fnt")
assetStorage.loadAsync<BitmapFont>("com/badlogic/gdx/utils/lsans-15.fnt")
}

override fun render() {
Expand Down Expand Up @@ -845,7 +845,7 @@ class WithAssetStorage: ApplicationAdapter() {
// Scheduling assets for asynchronous loading:
val assets = listOf(
assetStorage.loadAsync<Texture>("images/logo.png"),
assetStorage.loadAsync<BitmapFont>("com/badlogic/gdx/utils/arial-15.fnt")
assetStorage.loadAsync<BitmapFont>("com/badlogic/gdx/utils/lsans-15.fnt")
)

// Instead of constantly updating or checking the progress,
Expand Down
2 changes: 1 addition & 1 deletion assets-async/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ val async = project(":async")
dependencies {
api(project(":assets"))
api(async)
compileOnly("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion")

testImplementation(async.sourceSets.test.get().output)
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$kotlinCoroutinesVersion")
Expand Down
59 changes: 31 additions & 28 deletions assets-async/src/main/kotlin/ktx/assets/async/manager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class AsyncAssetManager(
* dependencies. The possible exceptions include [DependencyLoadingException] if one of the asset's
* dependencies failed to load, or any exception thrown by the asset loader.
*/
fun <T> AssetManager.loadAsync(assetDescriptor: AssetDescriptor<T>): Deferred<T> {
fun <T> loadAsync(assetDescriptor: AssetDescriptor<T>): Deferred<T> {
synchronized(this) {
// isLoaded and get are both synchronized. We want to perform these in a single step.
if (isLoaded(assetDescriptor)) {
Expand All @@ -153,44 +153,47 @@ class AsyncAssetManager(
// Returning existing callback to the asset:
@Suppress("UNCHECKED_CAST") return callbacks[assetDescriptor.fileName] as Deferred<T>
}
}

val result = CompletableDeferred<T>()
val result = CompletableDeferred<T>()

// The Deferred can be completed via a LoadedCallback. However, AssetLoaderParameters can be null.
@Suppress("UNCHECKED_CAST")
val parameters: AssetLoaderParameters<T> = assetDescriptor.params as AssetLoaderParameters<T>?
?: getDefaultParameters(assetDescriptor)
// The Deferred can be completed via a LoadedCallback. However, AssetLoaderParameters can be null.
@Suppress("UNCHECKED_CAST")
val parameters: AssetLoaderParameters<T> = assetDescriptor.params as AssetLoaderParameters<T>?
?: getDefaultParameters(assetDescriptor)

// Adding a custom LoadedCallback that completes the Deferred instance:
val userDefinedCallback = parameters.loadedCallback
parameters.loadedCallback = LoadedCallback { assetManager, fileName, type ->
if (result.isCompleted) return@LoadedCallback
try {
// If the user defined a custom callback, it should still be executed:
userDefinedCallback?.finishedLoading(assetManager, fileName, type)
// Completing the callback:
result.complete(assetManager.get(assetDescriptor))
// Restoring original user callback:
parameters.loadedCallback = userDefinedCallback
} catch (exception: Throwable) {
result.completeExceptionally(exception)
} finally {
synchronized(this) {
callbacks.remove(fileName)
// Adding a custom LoadedCallback that completes the Deferred instance:
val userDefinedCallback = parameters.loadedCallback
parameters.loadedCallback = LoadedCallback { assetManager, fileName, type ->
if (result.isCompleted) {
// Executing the original user callback without resolving the deferred instance:
userDefinedCallback?.finishedLoading(assetManager, fileName, type)
// No error handling, since the deferred instance was already completed.
parameters.loadedCallback = userDefinedCallback
return@LoadedCallback
}
try {
// If the user defined a custom callback, it should still be executed:
userDefinedCallback?.finishedLoading(assetManager, fileName, type)
// Completing the deferred:
result.complete(assetManager.get(assetDescriptor))
// Restoring original user callback:
parameters.loadedCallback = userDefinedCallback
} catch (exception: Throwable) {
result.completeExceptionally(exception)
} finally {
synchronized(this) {
callbacks.remove(fileName)
}
}
}
}

// Scheduling actual loading:
synchronized(this) {
callbacks[assetDescriptor.fileName] = result
// AssetDescriptor is final, and the load(AssetDescriptor) method destructs it either way.
// In order to pass our (possibly new) parameters, `load` is called with individual properties:
load(assetDescriptor.fileName, assetDescriptor.type, parameters)
}

return result
return result
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -874,8 +874,8 @@ class AssetStorageTest : AsyncTest() {
fileResolver = ClasspathFileHandleResolver(),
asyncContext = loaders
)
val path = "com/badlogic/gdx/utils/arial-15.fnt"
val dependency = "com/badlogic/gdx/utils/arial-15.png"
val path = "com/badlogic/gdx/utils/lsans-15.fnt"
val dependency = "com/badlogic/gdx/utils/lsans-15.png"

// When:
val assets = (1..100).map {
Expand Down Expand Up @@ -959,8 +959,8 @@ class AssetStorageTest : AsyncTest() {
fileResolver = ClasspathFileHandleResolver(),
asyncContext = loaders
)
val path = "com/badlogic/gdx/utils/arial-15.fnt"
val dependency = "com/badlogic/gdx/utils/arial-15.png"
val path = "com/badlogic/gdx/utils/lsans-15.fnt"
val dependency = "com/badlogic/gdx/utils/lsans-15.png"

// When: spawning 100 coroutines that load and unload the asset, 1 of which loads it 2 times:
val assets = (1..100).map { id ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ class AsyncAssetManagerTest : AsyncTest() {
@Test
fun `should load BitmapFont asynchronously`() {
// Given:
val path = "com/badlogic/gdx/utils/arial-15.fnt"
val dependency = "com/badlogic/gdx/utils/arial-15.png"
val path = "com/badlogic/gdx/utils/lsans-15.fnt"
val dependency = "com/badlogic/gdx/utils/lsans-15.png"

// When:
val asset = assetManager.loadAsync<BitmapFont>(path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ abstract class AbstractAssetStorageLoadingTest : AsyncTest() {
fun `should load BitmapFont assets`() {
// Given:
val storage = AssetStorage(fileResolver = ClasspathFileHandleResolver())
val path = "com/badlogic/gdx/utils/arial-15.fnt"
val dependency = "com/badlogic/gdx/utils/arial-15.png"
val path = "com/badlogic/gdx/utils/lsans-15.fnt"
val dependency = "com/badlogic/gdx/utils/lsans-15.png"

// When:
val asset = storage.testLoad<BitmapFont>(path)
Expand All @@ -154,8 +154,8 @@ abstract class AbstractAssetStorageLoadingTest : AsyncTest() {
fun `should unload BitmapFont with dependencies`() {
// Given:
val storage = AssetStorage(fileResolver = ClasspathFileHandleResolver())
val path = "com/badlogic/gdx/utils/arial-15.fnt"
val dependency = "com/badlogic/gdx/utils/arial-15.png"
val path = "com/badlogic/gdx/utils/lsans-15.fnt"
val dependency = "com/badlogic/gdx/utils/lsans-15.png"
storage.testLoad<BitmapFont>(path)

// When:
Expand Down Expand Up @@ -717,7 +717,7 @@ abstract class AbstractAssetStorageLoadingTest : AsyncTest() {
storage.logger.level = Logger.NONE
val assets = listOf(
storage.getIdentifier<String>("ktx/assets/async/string.txt"),
storage.getIdentifier<BitmapFont>("com/badlogic/gdx/utils/arial-15.fnt"),
storage.getIdentifier<BitmapFont>("com/badlogic/gdx/utils/lsans-15.fnt"),
storage.getIdentifier<Music>("ktx/assets/async/sound.ogg"),
storage.getIdentifier<TextureAtlas>("ktx/assets/async/skin.atlas"),
storage.getIdentifier<Texture>("ktx/assets/async/texture.png"),
Expand Down
2 changes: 1 addition & 1 deletion async/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ktx.*

dependencies {
compileOnly("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion")

testImplementation("com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion")
testImplementation("com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion")
Expand Down
2 changes: 1 addition & 1 deletion box2d/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ktx.*

dependencies {
compileOnly("com.badlogicgames.gdx:gdx-box2d:$gdxVersion")
api("com.badlogicgames.gdx:gdx-box2d:$gdxVersion")
testImplementation("com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop")
}
9 changes: 2 additions & 7 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,10 @@ subprojects {

repositories {
mavenLocal()
gradlePluginPortal()
mavenCentral()
maven("https://oss.sonatype.org/content/repositories/snapshots/")
}

configurations {
testImplementation.get().extendsFrom(compileOnly.get())
}

group = libGroup
version = libVersion
val projectName: String by project
Expand All @@ -90,8 +85,8 @@ subprojects {
dependencies {
val kotlinVersion: String by project

compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
compileOnly("com.badlogicgames.gdx:gdx:$gdxVersion")
implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
implementation("com.badlogicgames.gdx:gdx:$gdxVersion")
testImplementation("junit:junit:$junitVersion")
testImplementation("io.kotlintest:kotlintest:$kotlinTestVersion")
testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:$kotlinMockitoVersion")
Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/ktx/Versions.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package ktx

const val gdxVersion = "1.10.0"
const val gdxVersion = "1.11.0"
const val kotlinCoroutinesVersion = "1.6.1"

const val ashleyVersion = "1.7.4"
const val visUiVersion = "1.5.0"

const val spekVersion = "1.2.1"
const val spekVersion = "1.1.5"
const val kotlinTestVersion = "2.0.7"
const val kotlinMockitoVersion = "2.1.0"
const val assertjVersion = "3.11.1"
Expand Down
Loading

0 comments on commit 73fc120

Please sign in to comment.