Skip to content

Commit

Permalink
Added takeScreenshot utility. #183
Browse files Browse the repository at this point in the history
  • Loading branch information
czyzby committed Mar 26, 2020
1 parent 1e5d618 commit 24a452c
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- **[UPDATE]** Updated to Kotlin Coroutines 1.3.5.
- **[FEATURE]** (`ktx-ashley`) Added `Entity.contains` (`in` operator) that checks if an `Entity` has a `Component`.
- **[FEATURE]** (`ktx-async`) Added `RenderingScope` factory function for custom scopes using rendering thread dispatcher.
- **[FEATURE]** (`ktx-graphics`) Added `takeScreenshot` utility function that allows to save a screenshot of the application.
- **[FEATURE]** (`ktx-math`) Added `lerp` and `interpolate` extension functions for `Float` ranges.
- **[FEATURE]** (`ktx-preferences`) Added a new KTX module: Preferences API extensions.
- Added `set` operators for `String`, `Int`, `Float`, `Double`, `Long`, `Boolean`, `Pair<String, Any>` and `Any`
Expand Down
9 changes: 9 additions & 0 deletions graphics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ overriding with optional, named parameters.
`begin()` and `end()` calls when using batches, shader programs and buffers. Note that a camera or projection matrix can
also be passed to the `Batch.use` extension function to have it automatically applied to the batch's projection matrix.
- `begin` extension methods that automatically set projection matrix from a `Camera` or `Matrix4` were added to `Batch`.
- `takeScreenshot` allows to easily take a screenshot of current application screen.

#### `ShapeRenderer`

Expand Down Expand Up @@ -162,6 +163,14 @@ fun drawCircle(renderer: ShapeRenderer) {
}
```

Taking a screenshot of the current game screen:

```Kotlin
import ktx.graphics.takeScreenshot

takeScreenshot(Gdx.files.external("mygame/screenshot.png"))
```

#### Synergy

Use [`ktx-math`](../math) for `Vector2` and `Vector3` extensions, including idiomatic Kotlin factory
Expand Down
4 changes: 3 additions & 1 deletion graphics/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
dependencies {
provided "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
provided "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
testCompile "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion"
testCompile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
}
28 changes: 28 additions & 0 deletions graphics/src/main/kotlin/ktx/graphics/graphics.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package ktx.graphics

import com.badlogic.gdx.Gdx
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.PixmapIO
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.graphics.glutils.GLFrameBuffer
import com.badlogic.gdx.graphics.glutils.ShaderProgram
import com.badlogic.gdx.math.Matrix4
import com.badlogic.gdx.utils.BufferUtils
import com.badlogic.gdx.utils.ScreenUtils

/**
* Factory methods for LibGDX [Color] class. Allows to use named parameters.
Expand Down Expand Up @@ -82,3 +88,25 @@ inline fun <B : GLFrameBuffer<*>> B.use(action: (B) -> Unit) {
action(this)
end()
}

/**
* Takes a screenshot of the entire screen and saves the image using the given [fileHandle].
*/
fun takeScreenshot(fileHandle: FileHandle) {
val bufferWidth = Gdx.graphics.backBufferWidth
val bufferHeight = Gdx.graphics.backBufferHeight
val pixels = ScreenUtils.getFrameBufferPixels(0, 0, bufferWidth, bufferHeight, true)

// Ensuring the screenshot is opaque:
var i = 4
val alpha = 255.toByte()
while (i < pixels.size) {
pixels[i - 1] = alpha
i += 4
}

val screenshotImage = Pixmap(bufferWidth, bufferHeight, Pixmap.Format.RGBA8888)
BufferUtils.copy(pixels, 0, screenshotImage.pixels, pixels.size)
PixmapIO.writePNG(fileHandle, screenshotImage)
screenshotImage.dispose()
}
26 changes: 21 additions & 5 deletions graphics/src/test/kotlin/ktx/graphics/graphicsTest.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package ktx.graphics

import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl.LwjglNativesLoader
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.graphics.glutils.ShaderProgram
import com.badlogic.gdx.math.Matrix4
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.*
import org.junit.Assert.*
import org.junit.Test
import java.io.File

/**
* Tests general utilities related to LibGDX graphics API.
Expand Down Expand Up @@ -109,7 +110,7 @@ class GraphicsTest {
@Test
fun `should begin with provided projection matrix`() {
val batch = mock<Batch>()
val matrix = Matrix4(FloatArray(16) {it.toFloat()})
val matrix = Matrix4(FloatArray(16) { it.toFloat() })

batch.begin(projectionMatrix = matrix)

Expand Down Expand Up @@ -151,4 +152,19 @@ class GraphicsTest {
}
verify(frameBuffer).end()
}

@Test
fun `should take screenshot`() {
LwjglNativesLoader.load()
Gdx.gl = mock()
Gdx.graphics = mock {
on { backBufferHeight } doReturn 4
on { backBufferWidth } doReturn 4
}
val fileHandle = spy(FileHandle(File.createTempFile("screenshot", ".png")))

takeScreenshot(fileHandle)

verify(fileHandle).write(false)
}
}

0 comments on commit 24a452c

Please sign in to comment.