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 core and backends #174

Merged
merged 1 commit into from
Jan 23, 2022
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
@@ -0,0 +1,46 @@
package eu.joaocosta.minart.graphics

import verify._

import eu.joaocosta.minart.backend._
import eu.joaocosta.minart.runtime._

trait MutableSurfaceTests extends BasicTestSuite {

def surface: Surface.MutableSurface

test("Return the correct number of pixels") {
val pixels = surface.getPixels()
assert(pixels.size == surface.height)
assert(pixels.forall(_.size == surface.width))
}

test("Write and read pixels in certain positions") {
surface.putPixel(0, 0, Color(1, 2, 3))
surface.putPixel(0, 1, Color(3, 2, 1))
surface.putPixel(1, 0, Color(2, 1, 3))
assert(surface.getPixel(0, 0) == Some(Color(1, 2, 3)))
assert(surface.getPixel(0, 1) == Some(Color(3, 2, 1)))
assert(surface.getPixel(1, 0) == Some(Color(2, 1, 3)))
assert(surface.getPixels()(0)(0) == Color(1, 2, 3))
assert(surface.getPixels()(1)(0) == Color(3, 2, 1))
assert(surface.getPixels()(0)(1) == Color(2, 1, 3))
}

test("Don't blow up when invalid positions are provided") {
surface.putPixel(-1, -1, Color(1, 2, 3))
surface.putPixel(surface.width, 0, Color(1, 2, 3))
surface.putPixel(0, surface.height, Color(1, 2, 3))

assert(surface.getPixel(-1, -1) == None)
assert(surface.getPixel(surface.width, 0) == None)
assert(surface.getPixel(0, surface.height) == None)
}

test("Fill the surface with a single color") {
surface.fill(Color(1, 2, 3))
assert(surface.getPixels().flatten.forall(_ == Color(1, 2, 3)))
surface.fill(Color(3, 2, 1))
assert(surface.getPixels().flatten.forall(_ == Color(3, 2, 1)))
}
}
11 changes: 11 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ lazy val core =
.jsSettings(jsSettings)
.nativeSettings(nativeSettings)

lazy val backend =
crossProject(JVMPlatform, JSPlatform, NativePlatform)
.dependsOn(core)
.settings(sharedSettings)
.settings(name := "minart-backend")
.settings(testSettings)
.settings(publishSettings)
.jsSettings(jsSettings)
.nativeSettings(nativeSettings)

lazy val pure =
crossProject(JVMPlatform, JSPlatform, NativePlatform)
.dependsOn(core)
Expand Down Expand Up @@ -132,6 +142,7 @@ def example(project: sbtcrossproject.CrossProject.Builder, exampleName: String)
project
.in(file(s"examples/${exampleName}"))
.dependsOn(core)
.dependsOn(backend)
.settings(sharedSettings)
.settings(name := s"minart-examples-${exampleName}")
.settings(noTestSettings)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package eu.joaocosta.minart.backend.defaults

import scala.annotation.implicitNotFound

/** Typeclass to fetch an implicit default backend (e.g. Canvas or RenderLoop) for a cetain platform.
* This is used to power the `Backend.apply()` implementations.
* Ideally, an end user of the library should not need to implement this.
*/
@implicitNotFound(
"Default backend not found.\nIf you want to use the default backends import eu.joaocosta.minart.backend.defaults._ and add the minart-backend dependency."
)
trait DefaultBackend[-A, +B] {
def defaultValue(params: A): B
def defaultValue()(implicit ev: Any <:< A): B = defaultValue(ev(()))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.joaocosta.minart.graphics

import eu.joaocosta.minart.backend.defaults._
import eu.joaocosta.minart.input._

/** Window with a canvas that can be painted.
Expand Down Expand Up @@ -78,7 +79,7 @@ object Canvas {
*
* @return [[Canvas]] using the default backend for the target platform
*/
def create(settings: Canvas.Settings): Canvas =
def create(settings: Canvas.Settings)(implicit backend: DefaultBackend[Any, LowLevelCanvas]): Canvas =
CanvasManager().init(settings)

/** A system resource used by the Canvas.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package eu.joaocosta.minart.graphics

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

/** Abstraction that provides an `init` operation to create a new canvas.
*
* This is helpful to deal with the fact that creating a new canvas is a
Expand Down Expand Up @@ -28,6 +30,6 @@ object CanvasManager {
*
* @return [[CanvasManager]] using the default backend for the target platform
*/
def apply(): CanvasManager =
def apply()(implicit backend: DefaultBackend[Any, LowLevelCanvas]): CanvasManager =
CanvasManager(() => LowLevelCanvas.create())
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ object LowLevelCanvas {
*
* @return [[LowLevelCanvas]] using the default backend for the target platform
*/
def create(): LowLevelCanvas =
DefaultBackend[Any, LowLevelCanvas].defaultValue()
def create()(implicit backend: DefaultBackend[Any, LowLevelCanvas]): LowLevelCanvas =
backend.defaultValue()

/** Internal data structure containing canvas settings and precomputed values.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.joaocosta.minart.graphics

import eu.joaocosta.minart.backend.defaults._
import eu.joaocosta.minart.graphics.RenderLoop._
import eu.joaocosta.minart.runtime._

Expand Down Expand Up @@ -82,7 +83,10 @@ object RenderLoop {
*
* @param canvasSettings settings to use to build the canvas
*/
def apply(canvasSettings: Canvas.Settings): Unit = apply(LoopRunner(), CanvasManager(), canvasSettings)
def apply(
canvasSettings: Canvas.Settings
)(implicit lr: DefaultBackend[Any, LoopRunner], cm: DefaultBackend[Any, LowLevelCanvas]): Unit =
apply(LoopRunner(), CanvasManager(), canvasSettings)
def apply(
runner: LoopRunner,
canvasManager: CanvasManager,
Expand Down Expand Up @@ -113,7 +117,10 @@ object RenderLoop {
* @param canvasSettings settings to use to build the canvas
* @param initalState initial render loop state
*/
def apply(canvasSettings: Canvas.Settings, initialState: S): Unit =
def apply(canvasSettings: Canvas.Settings, initialState: S)(implicit
lr: DefaultBackend[Any, LoopRunner],
cm: DefaultBackend[Any, LowLevelCanvas]
): Unit =
apply(LoopRunner(), CanvasManager(), canvasSettings, initialState)

/** Converts this render loop to a stateless render loop, with a predefined initial state.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ trait LoopRunner {
object LoopRunner {

/** Get the default loop runner */
def apply(): LoopRunner =
DefaultBackend[Any, LoopRunner].defaultValue()
def apply()(implicit backend: DefaultBackend[Any, LoopRunner]): LoopRunner =
backend.defaultValue()
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ trait Resource {
}

object Resource {
def apply(resourcePath: String): Resource =
DefaultBackend[String, Resource].defaultValue(resourcePath)
def apply(resourcePath: String)(implicit backend: DefaultBackend[String, Resource]): Resource =
backend.defaultValue(resourcePath)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.joaocosta.minart.examples

import eu.joaocosta.minart.backend.defaults._
import eu.joaocosta.minart.graphics._
import eu.joaocosta.minart.runtime._

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.joaocosta.minart.examples

import eu.joaocosta.minart.backend.defaults._
import eu.joaocosta.minart.graphics._

object ColorSquare {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.joaocosta.minart.examples

import eu.joaocosta.minart.backend.defaults._
import eu.joaocosta.minart.graphics._
import eu.joaocosta.minart.input._
import eu.joaocosta.minart.runtime._
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.joaocosta.minart.examples

import eu.joaocosta.minart.backend.defaults._
import eu.joaocosta.minart.graphics._
import eu.joaocosta.minart.runtime._

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.joaocosta.minart.examples

import eu.joaocosta.minart.backend.defaults._
import eu.joaocosta.minart.graphics._
import eu.joaocosta.minart.graphics.pure._
import eu.joaocosta.minart.runtime._
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.joaocosta.minart.examples

import eu.joaocosta.minart.backend.defaults._
import eu.joaocosta.minart.graphics._
import eu.joaocosta.minart.input.KeyboardInput.Key
import eu.joaocosta.minart.runtime._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package eu.joaocosta.minart.examples

import scala.util.Random

import eu.joaocosta.minart.backend.defaults._
import eu.joaocosta.minart.graphics._
import eu.joaocosta.minart.input._
import eu.joaocosta.minart.runtime._
Expand Down