Skip to content

Commit

Permalink
Nested layers tests
Browse files Browse the repository at this point in the history
  • Loading branch information
davesmith00000 committed Apr 19, 2024
1 parent 8d402bf commit aae4878
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class JobMarketTests extends munit.FunSuite {
val job: Job = SampleJobs.WanderTo(10)
val market: JobMarket[Unit] = JobMarket.subSystem(SubSystemId("market"))

assertEquals(market.present(context, List(job)).unsafeGet.layers.flatMap(_.nodes).isEmpty, true)
assertEquals(market.present(context, List(job)).unsafeGet.layers.flatMap(_.toBatch).flatMap(_.nodes).isEmpty, true)
assertEquals(market.present(context, List(job)).unsafeGlobalEvents.isEmpty, true)
assertEquals(market.present(context, List(job)).unsafeGet.audio, None)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,10 @@ class AutomataTests extends munit.FunSuite {
.present(ctx, nextState)
.unsafeGet
.layers
.find(l => l.key.contains(layerKey))
.find(l => l.hasTag(layerKey))
.get
.toBatch
.head
.nodes
.collect { case g: Graphic[_] => g }
.head
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ final class SceneProcessor(

val displayLayers: scalajs.js.Array[(DisplayLayer, scalajs.js.Array[(String, DisplayObject)])] =
scene.layers
.flatMap(_.layer.toBatch)
.flatMap(_.toBatch)
.toJSArray
.filter(l => l.visible.getOrElse(true))
.zipWithIndex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ import scala.annotation.tailrec
*/
enum Layer derives CanEqual:

// An Empty layer
case Empty

/** A 'stack' represents a group of nested layers. Stacks are purely for organisation, and are ignored at render time.
*
* @param layers
Expand Down Expand Up @@ -69,9 +66,6 @@ enum Layer derives CanEqual:
*/
def withMagnification(level: Int): Layer =
this match
case e @ Layer.Empty =>
e

case l: Layer.Stack =>
l.copy(
layers = l.layers.map(_.withMagnification(level))
Expand All @@ -89,9 +83,6 @@ enum Layer derives CanEqual:
val t = remaining.tail

h match
case Layer.Empty =>
rec(t, acc)

case Layer.Stack(layers) =>
rec(layers ++ t, acc)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
package indigo.shared.scenegraph

import indigo.BindingKey
import indigo.shared.collections.Batch
import indigo.shared.datatypes.BindingKey

/** Layer entries are holders for Layers, that can either be tagged or untagged. If a layer entry is tagged with a
* `BindingKey`, then if two SceneUpdateFragements are merged together, two entries will the same tag will be combined
* at the depth of the original.
*/
enum LayerEntry:
def layer: Layer

case Untagged(layer: Layer)
case Tagged(key: BindingKey, layer: Layer)
case Tagged(tag: BindingKey, layer: Layer)

def hasKey(key: BindingKey): Boolean =
def hasTag(tag: BindingKey): Boolean =
this match
case _: LayerEntry.Untagged => false
case l: LayerEntry.Tagged => l.key == key
case l: LayerEntry.Tagged => l.tag == tag

def withKey(newKey: BindingKey): LayerEntry =
def giveTag: Option[BindingKey] =
this match
case Untagged(_) => None
case Tagged(tag, _) => Option(tag)

def withTag(newKey: BindingKey): LayerEntry =
LayerEntry.Tagged(newKey, this.layer)

def withLayer(newLayer: Layer): LayerEntry =
Expand All @@ -33,13 +43,16 @@ enum LayerEntry:
case l: LayerEntry.Untagged => l.copy(layer = l.layer.withMagnification(level))
case l: LayerEntry.Tagged => l.copy(layer = l.layer.withMagnification(level))

def toBatch: Batch[Layer.Content] =
layer.toBatch

object LayerEntry:

def apply(key: BindingKey, layer: Layer): LayerEntry =
LayerEntry.Tagged(key, layer)
def apply(tag: BindingKey, layer: Layer): LayerEntry =
LayerEntry.Tagged(tag, layer)

def apply(maybeKey: Option[BindingKey], layer: Layer): LayerEntry =
maybeKey.fold(LayerEntry(layer))(key => LayerEntry(key, layer))
maybeKey.fold(LayerEntry(layer))(tag => LayerEntry(tag, layer))

def apply(keyAndLayer: (BindingKey, Layer)): LayerEntry =
LayerEntry.Tagged(keyAndLayer._1, keyAndLayer._2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ final case class SceneUpdateFragment(
SceneUpdateFragment.insertLayer(this, LayerEntry(Layer(nodes)))

def addLayers(newLayers: Batch[LayerEntry]): SceneUpdateFragment =
this.copy(layers = newLayers.foldLeft(layers)((acc, l) => SceneUpdateFragment.mergeLayers(this.layers, l)))
this.copy(layers = newLayers.foldLeft(layers)((acc, l) => SceneUpdateFragment.mergeLayers(acc, l)))
def addLayers(newLayers: LayerEntry*): SceneUpdateFragment =
addLayers(newLayers.toBatch)
@targetName("addLayers_batch_key_layer")
def addLayers(newLayers: Batch[(BindingKey, Layer)]): SceneUpdateFragment =
this.copy(
layers = newLayers.foldLeft(layers) { case (acc, (k, l)) =>
SceneUpdateFragment.mergeLayers(this.layers, LayerEntry(k, l))
SceneUpdateFragment.mergeLayers(acc, LayerEntry(k, l))
}
)
@targetName("addLayers_args_key_layer")
Expand All @@ -76,7 +76,7 @@ final case class SceneUpdateFragment(
@targetName("addLayers_batch_layer")
def addLayers(newLayers: Batch[Layer]): SceneUpdateFragment =
this.copy(
layers = newLayers.foldLeft(layers)((acc, l) => SceneUpdateFragment.mergeLayers(this.layers, LayerEntry(l)))
layers = newLayers.foldLeft(layers)((acc, l) => SceneUpdateFragment.mergeLayers(acc, LayerEntry(l)))
)
@targetName("addLayers_args_layer")
def addLayers(newLayers: Layer*): SceneUpdateFragment =
Expand All @@ -101,9 +101,6 @@ final case class SceneUpdateFragment(

def mapLayers(f: LayerEntry => LayerEntry): SceneUpdateFragment =
this.copy(layers = layers.map(_.modify(f)))
@targetName("mapLayers_untagged")
def mapLayers(f: Layer => Layer): SceneUpdateFragment =
this.copy(layers = layers.map(_.modifyLayer(f)))

def noLights: SceneUpdateFragment =
this.copy(lights = Batch.empty)
Expand Down Expand Up @@ -227,21 +224,23 @@ object SceneUpdateFragment:
case l @ LayerEntry.Untagged(_) =>
layers :+ layer

case LayerEntry.Tagged(t, l) if layers.exists(_.hasKey(t)) =>
layers.map { ll =>
if ll.hasKey(t) then
case LayerEntry.Tagged(t, l) if layers.exists(_.hasTag(t)) =>
layers.map {
case x: LayerEntry.Untagged =>
x

case x @ LayerEntry.Tagged(k, ll) if t == k =>
val newLayer =
(ll.layer, l) match
case (Layer.Empty, b) => b
case (a: Layer.Stack, Layer.Empty) => a
(ll, l) match
case (a: Layer.Stack, b: Layer.Content) => a.append(b)
case (a: Layer.Stack, b: Layer.Stack) => a ++ b
case (a: Layer.Content, Layer.Empty) => a
case (a: Layer.Content, b: Layer.Content) => a |+| b
case (a: Layer.Content, b: Layer.Stack) => a :: b

LayerEntry.Tagged(t, newLayer)
else ll

case x: LayerEntry.Tagged =>
x
}

case LayerEntry.Tagged(_, _) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,9 @@ import indigo.shared.materials.BlendMaterial

class LayerTests extends munit.FunSuite {

test("combining layer should preserve left hand side magnification") {

assertEquals(Layer(BindingKey("key A")).key, Some(BindingKey("key A")))
assertEquals((Layer(BindingKey("key A")) |+| Layer(BindingKey("key B"))).key, Some(BindingKey("key A")))
assertEquals((Layer(BindingKey("key A")) |+| Layer(Batch.empty)).key, Some(BindingKey("key A")))
assertEquals((Layer(Batch.empty) |+| Layer(BindingKey("key B"))).key, Some(BindingKey("key B")))

}

test("Can add a blend material with no Blending instance in place") {
val layer =
Layer(BindingKey("test")).withBlendMaterial(BlendMaterial.Lighting(RGBA.Red))
Layer.empty.withBlendMaterial(BlendMaterial.Lighting(RGBA.Red))

layer.blending match
case Some(Blending(entity, layer, BlendMaterial.Lighting(color), clearColor)) =>
Expand All @@ -30,7 +21,7 @@ class LayerTests extends munit.FunSuite {

test("Can modify blending with no Blending instance in place") {
val layer =
Layer(BindingKey("test")).modifyBlending(_.withClearColor(RGBA.Green))
Layer.empty.modifyBlending(_.withClearColor(RGBA.Green))

layer.blending match
case Some(Blending(entity, layer, blendMaterial, Some(clearColor))) =>
Expand All @@ -42,7 +33,7 @@ class LayerTests extends munit.FunSuite {

test("Can add an entity blend mode with no Blending instance in place") {
val layer =
Layer(BindingKey("test")).withEntityBlend(Blend.LightingEntity)
Layer.empty.withEntityBlend(Blend.LightingEntity)

layer.blending match
case Some(Blending(entity, layer, blendMaterial, clearColor)) =>
Expand All @@ -54,7 +45,7 @@ class LayerTests extends munit.FunSuite {

test("Can add a layer blend mode with no Blending instance in place") {
val layer =
Layer(BindingKey("test")).withLayerBlend(Blend.LightingEntity)
Layer.empty.withLayerBlend(Blend.LightingEntity)

layer.blending match
case Some(Blending(entity, layer, blendMaterial, clearColor)) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,23 @@ class SceneUpdateFragmentTests extends munit.FunSuite {
test("Able to add a batch of layers from a constructor") {

val actual =
SceneUpdateFragment(Batch(Layer(BindingKey("key A")), Layer(BindingKey("key B"))))
SceneUpdateFragment(Batch(BindingKey("key A") -> Layer.empty, BindingKey("key B") -> Layer.empty))

val expected =
SceneUpdateFragment.empty.addLayers(Batch(Layer(BindingKey("key A")), Layer(BindingKey("key B"))))
SceneUpdateFragment.empty.addLayers(
Batch(LayerEntry(BindingKey("key A"), Layer.empty), LayerEntry(BindingKey("key B"), Layer.empty))
)

assertEquals(actual, expected)

}

test("Able to add an optional layer from a constructor (Some)") {

val actual =
SceneUpdateFragment(Option(Layer(BindingKey("key A"))))
SceneUpdateFragment(Option(BindingKey("key A") -> Layer.empty))

val expected =
SceneUpdateFragment.empty.addLayers(Batch(Layer(BindingKey("key A"))))
SceneUpdateFragment.empty.addLayers(Batch(LayerEntry(BindingKey("key A"), Layer.empty)))

assertEquals(actual, expected)

Expand All @@ -46,81 +47,85 @@ class SceneUpdateFragmentTests extends munit.FunSuite {
test("Adding a layer with an existing key merges magnification down (none, none)") {

val scene =
SceneUpdateFragment.empty.addLayer(Layer(BindingKey("key A")))
SceneUpdateFragment.empty.addLayer(LayerEntry(BindingKey("key A"), Layer.empty))

val actual =
scene.addLayer(Layer(BindingKey("key A")))
scene.addLayer(BindingKey("key A") -> Layer.empty)

assert(actual.layers.length == 1)
assertEquals(actual.layers.head.magnification, None)
assertEquals(actual.layers.flatMap(_.toBatch).head.magnification, None)

}

test("Adding a layer with an existing key merges magnification down (some, some)") {

val scene =
SceneUpdateFragment.empty.addLayer(Layer(BindingKey("key A")).withMagnification(2))
SceneUpdateFragment.empty.addLayer((BindingKey("key A") -> Layer.empty.withMagnification(2)))

val actual =
scene.addLayer(Layer(BindingKey("key A")).withMagnification(1))
scene.addLayer(LayerEntry(BindingKey("key A"), Layer.empty.withMagnification(1)))

assert(actual.layers.length == 1)
assertEquals(actual.layers.head.magnification, Some(2))
assertEquals(actual.layers.flatMap(_.toBatch).head.magnification, Some(2))

}

test("Adding a layer with an existing key merges magnification down (none, some)") {

val scene =
SceneUpdateFragment.empty.addLayer(Layer(BindingKey("key A")))
SceneUpdateFragment.empty.addLayer(BindingKey("key A") -> Layer.empty)

val actual =
scene.addLayer(Layer(BindingKey("key A")).withMagnification(1))
scene.addLayer(BindingKey("key A") -> Layer.empty.withMagnification(1))

assert(actual.layers.length == 1)
assertEquals(actual.layers.head.magnification, Some(1))
assertEquals(actual.layers.flatMap(_.toBatch).head.magnification, Some(1))

}

test("Adding a layer with an existing key merges magnification down (some, none)") {

val scene =
SceneUpdateFragment.empty.addLayer(Layer(BindingKey("key A")).withMagnification(2))
SceneUpdateFragment.empty.addLayer(BindingKey("key A") -> Layer.empty.withMagnification(2))

val actual =
scene.addLayer(Layer(BindingKey("key A")))
scene.addLayer(BindingKey("key A") -> Layer.empty)

assert(actual.layers.length == 1)
assertEquals(actual.layers.head.magnification, Some(2))
assertEquals(actual.layers.flatMap(_.toBatch).head.magnification, Some(2))

}

test("Replace layers using withLayers") {

val scene =
SceneUpdateFragment.empty.addLayer(Layer(BindingKey("key A")))
SceneUpdateFragment.empty.addLayer(BindingKey("key A") -> Layer.empty)

val actual =
scene.withLayers(Layer(BindingKey("key B")))
scene.withLayers(BindingKey("key B") -> Layer.empty)

assert(actual.layers.length == 1)
assertEquals(actual.layers.head.key, Some(BindingKey("key B")))

actual.layers.head match
case LayerEntry.Untagged(_) => fail("Should have been a tagged layer entry")
case LayerEntry.Tagged(key, _) =>
assertEquals(key, BindingKey("key B"))

}

test("SUF append preseves layer keys") {

val sceneA: SceneUpdateFragment =
SceneUpdateFragment.empty.addLayer(Layer(BindingKey("key A")).withMagnification(2))
SceneUpdateFragment.empty.addLayer(BindingKey("key A") -> Layer.empty.withMagnification(2))

val sceneB: SceneUpdateFragment =
SceneUpdateFragment.empty.addLayer(Layer(BindingKey("key A")).withMagnification(3))
SceneUpdateFragment.empty.addLayer(BindingKey("key A") -> Layer.empty.withMagnification(3))

val actual: SceneUpdateFragment =
sceneA |+| sceneB

assert(actual.layers.length == 1)
assertEquals(actual.layers.head.magnification, Some(2))
assertEquals(actual.layers.flatMap(_.toBatch).head.magnification, Some(2))

}

Expand Down Expand Up @@ -151,15 +156,25 @@ class SceneUpdateFragmentTests extends munit.FunSuite {
test("Map over layers") {
val scene =
SceneUpdateFragment.empty
.addLayer(Layer(BindingKey("key A")).withMagnification(1))
.addLayer(Layer(BindingKey("key B")).withMagnification(1))
.addLayer(BindingKey("key A") -> Layer.empty.withMagnification(1))
.addLayer(BindingKey("key B") -> Layer.empty.withMagnification(1))

val actual =
scene.mapLayers(l => l.withKey(BindingKey(l.key.map(_.toString).getOrElse("!") + "?")).withMagnification(2))
scene.mapLayers {
case LayerEntry.Untagged(_) =>
fail("Should have been a tagged layer entry")

case l @ LayerEntry.Tagged(key, layer) =>
l.withTag(BindingKey(key.toString + "?")).withMagnification(2)
}

assert(actual.layers.flatMap(_.toBatch).length == 2)

assert(actual.layers.length == 2)
assertEquals(actual.layers.map(_.key.get).toList, List(BindingKey("key A?"), BindingKey("key B?")))
assertEquals(actual.layers.map(_.magnification.get).toList, List(2, 2))
assertEquals(
actual.layers.map(_.giveTag.get).toList,
List(BindingKey("key A?"), BindingKey("key B?"))
)
assertEquals(actual.layers.flatMap(_.toBatch).map(_.magnification.get).toList, List(2, 2))
}

}
Loading

0 comments on commit aae4878

Please sign in to comment.