Skip to content

Commit

Permalink
Improves screen capture API to accept configuration
Browse files Browse the repository at this point in the history
Also allows for capturing multiple images at once, and scaling
  • Loading branch information
hobnob committed Oct 23, 2024
1 parent 15f78b3 commit 8c57ffe
Show file tree
Hide file tree
Showing 8 changed files with 417 additions and 192 deletions.
3 changes: 3 additions & 0 deletions indigo/indigo/src/main/scala/indigo/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,9 @@ val AnalogAxis: shared.input.AnalogAxis.type = shared.input.AnalogAxis
type GamepadButtons = shared.input.GamepadButtons
val GamepadButtons: shared.input.GamepadButtons.type = shared.input.GamepadButtons

type ImageType = shared.ImageType
val ImageType: shared.ImageType.type = shared.ImageType

type BoundaryLocator = shared.BoundaryLocator

type FrameContext[StartUpData] = shared.FrameContext[StartUpData]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package indigo.platform.renderer

import indigo.shared.ImageData
import indigo.shared.ImageType
import indigo.shared.assets.AssetType
import indigo.shared.collections.Batch
import indigo.shared.config.RenderingTechnology
import indigo.shared.datatypes.BindingKey
Expand All @@ -20,56 +20,28 @@ trait Renderer:

def init(shaders: Set[RawShaderCode]): Unit
def drawScene(sceneData: ProcessedSceneData, runningTime: Seconds): Unit
def captureScreen(
clippingRect: Option[Rectangle],
excludeLayers: Batch[BindingKey],
imageType: ImageType
): ImageData

/** Capture the screen as a WebP image
/** Capture the screen as a number of images, each with the specified configuration
*
* @param captureConfig
* The configurations to use when capturing the screen
* @return
* A batch containing either the captured images, or error messages
*/
def captureScreen(): ImageData = captureScreen(None, Batch.empty, ImageType.WEBP)
def captureScreen(captureConfig: Batch[ScreenCaptureConfig]): Batch[Either[String, AssetType.Image]]

/** Capture the screen as a WebP image, only capturing the specified rectangle
/** Capture the screen as an image, with the specified configuration
*
* @param clippingRect
* @param captureOption
* The configuration to use when capturing the screen
* @return
* The captured image, or an error message
*/
def captureScreen(clippingRect: Rectangle): ImageData = captureScreen(Some(clippingRect), Batch.empty, ImageType.WEBP)

/** Capture the screen as an image, only capturing the specified rectangle, with the specified image type
*
* @param clippingRect
* @param imageType
* @return
*/
def captureScreen(clippingRect: Rectangle, imageType: ImageType): ImageData =
captureScreen(Some(clippingRect), Batch.empty, imageType)

/** Capture the screen as an image, excluding the specified layers
*
* @param excludeLayers
* @return
*/
def captureScreen(excludeLayers: Batch[BindingKey]): ImageData = captureScreen(None, excludeLayers, ImageType.WEBP)

/** Capture the screen as an image, excluding the specified layers, with the specified image type
*
* @param excludeLayers
* @param imageType
* @return
*/
def captureScreen(excludeLayers: Batch[BindingKey], imageType: ImageType): ImageData =
captureScreen(None, excludeLayers, imageType)

/** Capture the screen as an image, with the specified image type
*
* @param imageType
* @return
*/
def captureScreen(imageType: ImageType): ImageData = captureScreen(None, Batch.empty, imageType)
def captureScreen(captureConfig: ScreenCaptureConfig): Either[String, AssetType.Image] =
captureScreen(Batch(captureConfig)).headOption match {
case Some(v) => v
case None => Left("Could not capture image")
}

object Renderer:
def blackHole = new Renderer {
Expand All @@ -80,9 +52,7 @@ object Renderer:

def init(shaders: Set[RawShaderCode]): Unit = ()
def drawScene(sceneData: ProcessedSceneData, runningTime: Seconds): Unit = ()
def captureScreen(
clippingRect: Option[Rectangle],
excludeLayers: Batch[BindingKey],
imageType: ImageType
): ImageData = ImageData("empty", 0, ImageType.PNG, Array.emptyByteArray)
def captureScreen(captureOptions: Batch[ScreenCaptureConfig]): Batch[Either[String, AssetType.Image]] = Batch(
Left("No renderer available")
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package indigo.platform.renderer

import indigo.shared.ImageType
import indigo.shared.collections.Batch
import indigo.shared.datatypes.BindingKey
import indigo.shared.datatypes.Rectangle
import indigo.shared.datatypes.Vector2

/** Configuration for a screen capture
*
* @param name
* The optional name of the capture
* @param croppingRect
* The rectangle to crop the capture to
* @param scale
* The scale to apply to the capture
* @param excludeLayers
* The layers to exclude from the capture
* @param imageType
* The type of image to capture
*/
final case class ScreenCaptureConfig(
name: Option[String],
croppingRect: Option[Rectangle],
scale: Option[Vector2],
excludeLayers: Batch[BindingKey],
imageType: ImageType
) {

/** Set the name of the capture
*
* @param name
* @return
*/
def withName(name: String): ScreenCaptureConfig =
this.copy(name = Some(name))

/** Set the cropping rectangle of the capture
*
* @param rect
* @return
*/
def withCrop(rect: Rectangle): ScreenCaptureConfig =
this.copy(croppingRect = Some(rect))

/** Set the scale of the capture
*
* @param scale
* @return
*/
def withScale(scale: Double): ScreenCaptureConfig =
withScale(Vector2(scale, scale))

/** Set the scale of the capture
*
* @param scale
* @return
*/
def withScale(scale: Vector2): ScreenCaptureConfig =
this.copy(scale = Some(scale))

/** Set the image type of the capture
*
* @param imageType
* @return
*/
def withImageType(imageType: ImageType): ScreenCaptureConfig =
this.copy(imageType = imageType)

/** Set the layers to exclude from the capture
*
* @param excludeLayers
* @return
*/
def withExcludeLayers(excludeLayers: Batch[BindingKey]): ScreenCaptureConfig =
this.copy(excludeLayers = excludeLayers)

/** Add a layer to exclude from the capture
*
* @param excludeLayer
* @return
*/
def addExcludeLayer(excludeLayer: BindingKey): ScreenCaptureConfig =
this.copy(excludeLayers = excludeLayers :+ excludeLayer)

/** Add layers to exclude from the capture
*
* @param excludeLayers
* @return
*/
def addExcludeLayers(excludeLayers: Batch[BindingKey]): ScreenCaptureConfig =
this.copy(excludeLayers = this.excludeLayers ++ excludeLayers)
}

object ScreenCaptureConfig {

/** Default configuration
*/
val default: ScreenCaptureConfig =
ScreenCaptureConfig(None, None, None, Batch.empty, ImageType.WEBP)

/** Create a configuration with a name
*
* @param name
* @return
*/
def apply(name: String): ScreenCaptureConfig =
ScreenCaptureConfig(Some(name), None, None, Batch.empty, ImageType.WEBP)

/** Create a configuration with a name and cropping rectangle
*
* @param name
* @param croppingRect
* @return
*/
def apply(name: String, croppingRect: Rectangle): ScreenCaptureConfig =
ScreenCaptureConfig(Some(name), Some(croppingRect), None, Batch.empty, ImageType.WEBP)

/** Create a configuration with a name and scale
*
* @param name
* @param scale
* @return
*/
def apply(name: String, scale: Double): ScreenCaptureConfig =
ScreenCaptureConfig(Some(name), None, Some(Vector2(scale, scale)), Batch.empty, ImageType.WEBP)

/** Create a configuration with a name and scale
*
* @param name
* @param scale
* @return
*/
def apply(name: String, scale: Vector2): ScreenCaptureConfig =
ScreenCaptureConfig(Some(name), None, Some(scale), Batch.empty, ImageType.WEBP)

/** Create a configuration with a name and excluded layers
*
* @param name
* @param excludeLayers
* @return
*/
def apply(name: String, excludeLayers: Batch[BindingKey]): ScreenCaptureConfig =
ScreenCaptureConfig(Some(name), None, None, excludeLayers, ImageType.WEBP)

/** Create a configuration with a name and image type
*
* @param name
* @param imageType
* @return
*/
def apply(name: String, imageType: ImageType): ScreenCaptureConfig =
ScreenCaptureConfig(Some(name), None, None, Batch.empty, imageType)

/** Create a configuration with a cropping rectangle
*
* @param croppingRect
* @return
*/
def apply(croppingRect: Rectangle): ScreenCaptureConfig =
ScreenCaptureConfig(None, Some(croppingRect), None, Batch.empty, ImageType.WEBP)

/** Create a configuration with a scale
*
* @param scale
* @return
*/
def apply(scale: Double): ScreenCaptureConfig =
ScreenCaptureConfig(None, None, Some(Vector2(scale, scale)), Batch.empty, ImageType.WEBP)

/** Create a configuration with a scale
*
* @param scale
* @return
*/
def apply(scale: Vector2): ScreenCaptureConfig =
ScreenCaptureConfig(None, None, Some(scale), Batch.empty, ImageType.WEBP)

/** Create a configuration with excluded layers
*
* @param excludeLayers
* @return
*/
def apply(excludeLayers: Batch[BindingKey]): ScreenCaptureConfig =
ScreenCaptureConfig(None, None, None, excludeLayers, ImageType.WEBP)

/** Create a configuration with an image type
*
* @param imageType
* @return
*/
def apply(imageType: ImageType): ScreenCaptureConfig =
ScreenCaptureConfig(None, None, None, Batch.empty, imageType)
}
Loading

0 comments on commit 8c57ffe

Please sign in to comment.