Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split render loops into pure and impure render loops #48

Merged
merged 3 commits into from
Jan 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import scala.scalajs.js.timers

import eu.joaocosta.minart.core._

object JsRenderLoop extends RenderLoop {
object JsRenderLoop extends ImpureRenderLoop {
def finiteRenderLoop[S](
canvasManager: CanvasManager,
initialState: S,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package eu.joaocosta.minart.backend

import eu.joaocosta.minart.backend._
import eu.joaocosta.minart.core._

class JsRenderLoopSpec extends RenderLoopTests {
lazy val renderLoop: RenderLoop = JsRenderLoop
lazy val renderLoop: ImpureRenderLoop = JsRenderLoop
lazy val renderLoopName: String = "JsRenderLoop"
override lazy val testLoop: Boolean = false
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import scala.concurrent.duration.FiniteDuration

import eu.joaocosta.minart.core._

object JavaRenderLoop extends RenderLoop {
object JavaRenderLoop extends ImpureRenderLoop {
def finiteRenderLoop[S](
canvasManager: CanvasManager,
initialState: S,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package eu.joaocosta.minart.backend

import eu.joaocosta.minart.backend._
import eu.joaocosta.minart.core._

class JavaRenderLoopSpec extends RenderLoopTests {
lazy val renderLoop: RenderLoop = JavaRenderLoop
lazy val renderLoop: ImpureRenderLoop = JavaRenderLoop
lazy val renderLoopName: String = "JavaRenderLoop"
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import sdl2.SDL._

import eu.joaocosta.minart.core._

object SdlRenderLoop extends RenderLoop {
object SdlRenderLoop extends ImpureRenderLoop {
def finiteRenderLoop[S](
canvasManager: CanvasManager,
initialState: S,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package eu.joaocosta.minart.backend

import eu.joaocosta.minart.core._
import eu.joaocosta.minart.backend.defaults.DefaultBackend

trait ImpureRenderLoop extends RenderLoop[Function1, Function2] {
def infiniteRenderLoop[S](
canvasManager: CanvasManager,
initialState: S,
renderFrame: (Canvas, S) => S,
frameRate: FrameRate): Unit =
finiteRenderLoop(canvasManager, initialState, renderFrame, (_: S) => false, frameRate)

def infiniteRenderLoop(
canvasManager: CanvasManager,
renderFrame: Canvas => Unit,
frameRate: FrameRate): Unit =
infiniteRenderLoop(canvasManager, (), (c: Canvas, _: Unit) => renderFrame(c), frameRate)
}

object ImpureRenderLoop {
/**
* Returns an [[ImpureRenderLoop]] for the default backend for the target platform.
*/
def default()(implicit d: DefaultBackend[Any, ImpureRenderLoop]): ImpureRenderLoop =
d.defaultValue(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import eu.joaocosta.minart.backend.defaults.DefaultBackend
* The `RenderLoop` contains a set of helpful methods to implement basic render
* loops in a platform agonstic way.
*/
trait RenderLoop {
trait RenderLoop[F1[-_, +_], F2[-_, -_, +_]] {

/**
* Creates a render loop that terminates when a certain condition is reached.
Expand All @@ -22,7 +22,7 @@ trait RenderLoop {
def finiteRenderLoop[S](
canvasManager: CanvasManager,
initialState: S,
renderFrame: (Canvas, S) => S,
renderFrame: F2[Canvas, S, S],
terminateWhen: S => Boolean,
frameRate: FrameRate): Unit

Expand All @@ -39,9 +39,8 @@ trait RenderLoop {
def infiniteRenderLoop[S](
canvasManager: CanvasManager,
initialState: S,
renderFrame: (Canvas, S) => S,
frameRate: FrameRate): Unit =
finiteRenderLoop(canvasManager, initialState, renderFrame, (_: S) => false, frameRate)
renderFrame: F2[Canvas, S, S],
frameRate: FrameRate): Unit

/**
* Creates a render loop that never terminates.
Expand All @@ -52,9 +51,8 @@ trait RenderLoop {
*/
def infiniteRenderLoop(
canvasManager: CanvasManager,
renderFrame: Canvas => Unit,
frameRate: FrameRate): Unit =
infiniteRenderLoop(canvasManager, (), (c: Canvas, _: Unit) => renderFrame(c), frameRate)
renderFrame: F1[Canvas, Unit],
frameRate: FrameRate): Unit

/**
* Renders a single frame
Expand All @@ -64,13 +62,13 @@ trait RenderLoop {
*/
def singleFrame(
canvasManager: CanvasManager,
renderFrame: Canvas => Unit): Unit
renderFrame: F1[Canvas, Unit]): Unit
}

object RenderLoop {
/**
* Returns [[RenderLoop]] for the default backend for the target platform.
* Returns a [[RenderLoop]] for the default backend for the target platform.
*/
def default()(implicit d: DefaultBackend[Any, RenderLoop]): RenderLoop =
def default()(implicit d: DefaultBackend[Any, RenderLoop[Function1, Function2]]): RenderLoop[Function1, Function2] =
d.defaultValue(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package eu.joaocosta.minart.core

import org.specs2.mutable._

import eu.joaocosta.minart.backend.PpmCanvas
import eu.joaocosta.minart.backend._

trait RenderLoopTests extends Specification {

def renderLoop: RenderLoop
def renderLoop: ImpureRenderLoop
def renderLoopName: String
def testLoop: Boolean = true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package eu.joaocosta.minart.examples

import eu.joaocosta.minart.core._
import eu.joaocosta.minart.pure._
import eu.joaocosta.minart.pure.backend._

object PureColorSquare extends MinartApp {
type State = Unit
val renderLoop = RenderLoop.default()
val renderLoop = PureRenderLoop.default()
val canvasSettings = Canvas.Settings(
width = 128,
height = 128,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package eu.joaocosta.minart.pure

import eu.joaocosta.minart.core._
import eu.joaocosta.minart.pure.backend._

/** Entrypoint for pure Minart applications. */
trait MinartApp {
type State
def canvasManager: CanvasManager
def renderLoop: RenderLoop
def renderLoop: PureRenderLoop
def initialState: State
def renderFrame: State => CanvasIO[State]
def terminateWhen: State => Boolean
Expand All @@ -16,7 +17,7 @@ trait MinartApp {
renderLoop.finiteRenderLoop[State](
canvasManager,
initialState,
(canvas, state) => renderFrame(state).run(canvas),
renderFrame,
terminateWhen,
frameRate)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package eu.joaocosta.minart.pure.backend

import eu.joaocosta.minart.backend.ImpureRenderLoop
import eu.joaocosta.minart.backend.defaults.DefaultBackend
import eu.joaocosta.minart.core._
import eu.joaocosta.minart.pure._

class PureRenderLoop(impureRenderLoop: ImpureRenderLoop) extends RenderLoop[RIO, PureRenderLoop.StateCanvasIO] {

def finiteRenderLoop[S](
canvasManager: CanvasManager,
initialState: S,
renderFrame: S => CanvasIO[S],
terminateWhen: S => Boolean,
frameRate: FrameRate): Unit =
impureRenderLoop.finiteRenderLoop[S](
canvasManager,
initialState,
(canvas, state) => renderFrame(state).run(canvas),
terminateWhen,
frameRate)

def infiniteRenderLoop[S](
canvasManager: CanvasManager,
initialState: S,
renderFrame: S => CanvasIO[S],
frameRate: FrameRate): Unit =
impureRenderLoop.infiniteRenderLoop[S](
canvasManager,
initialState,
(canvas, state) => renderFrame(state).run(canvas),
frameRate)

def infiniteRenderLoop(
canvasManager: CanvasManager,
renderFrame: CanvasIO[Unit],
frameRate: FrameRate): Unit =
impureRenderLoop.infiniteRenderLoop(
canvasManager,
canvas => renderFrame.run(canvas),
frameRate)

def singleFrame(
canvasManager: CanvasManager,
renderFrame: CanvasIO[Unit]): Unit =
impureRenderLoop.singleFrame(
canvasManager,
canvas => renderFrame.run(canvas))
}

object PureRenderLoop {
type StateCanvasIO[-Canvas, -State, +A] = Function1[State, RIO[Canvas, A]]

/**
* Returns [[PureRenderLoop]] for the default backend for the target platform.
*/
def default()(implicit d: DefaultBackend[Any, ImpureRenderLoop]): PureRenderLoop =
new PureRenderLoop(d.defaultValue(()))
}