Skip to content

Commit 7c82d15

Browse files
authored
Merge pull request #525 from baaahs/grid-swap-and-stagger
Grid swap and stagger
2 parents 3b71a77 + d89de6b commit 7c82d15

35 files changed

+557
-189
lines changed

src/commonMain/kotlin/baaahs/client/document/SceneManager.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import baaahs.io.resourcesFs
1111
import baaahs.mapper.Storage
1212
import baaahs.plugin.Plugins
1313
import baaahs.scene.*
14+
import baaahs.show.SceneMigrator
1415
import baaahs.show.mutable.MutableDocument
1516
import baaahs.ui.DialogHolder
1617
import baaahs.ui.DialogMenuItem
@@ -88,7 +89,7 @@ class SceneManager(
8889
}
8990

9091
override suspend fun onUpload(name: String, content: String) {
91-
val scene = plugins.json.decodeFromString(Scene.serializer(), content)
92+
val scene = plugins.json.decodeFromString(SceneMigrator, content)
9293
onNew(scene)
9394
}
9495

src/commonMain/kotlin/baaahs/mapper/Storage.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import baaahs.libraries.ShaderLibraryIndexFile
88
import baaahs.plugin.Plugins
99
import baaahs.scene.OpenScene
1010
import baaahs.scene.Scene
11+
import baaahs.show.SceneMigrator
1112
import baaahs.show.Show
1213
import baaahs.show.ShowMigrator
1314
import baaahs.sim.MergedFs
@@ -144,11 +145,11 @@ class Storage(val fs: Fs, val plugins: Plugins) {
144145
}
145146

146147
suspend fun loadScene(file: Fs.File): Scene? {
147-
return loadJson(file, Scene.serializer())
148+
return loadJson(file, SceneMigrator)
148149
}
149150

150151
suspend fun saveScene(file: Fs.File, scene: Scene) {
151-
file.write(plugins.json.encodeToString(Scene.serializer(), scene), true)
152+
file.write(plugins.json.encodeToString(SceneMigrator, scene), true)
152153
}
153154

154155
suspend fun loadShow(file: Fs.File): Show? {

src/commonMain/kotlin/baaahs/model/ModelData.kt

+4-3
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,9 @@ data class GridData(
171171
val columns: Int,
172172
val rowGap: Float,
173173
val columnGap: Float,
174-
val direction: Direction = Direction.ColumnsThenRows,
175-
val zigZag: Boolean = false
174+
val direction: Direction = Direction.RowsThenColumns,
175+
val zigZag: Boolean = false,
176+
val stagger: Int = 1
176177
) : EntityData {
177178
override fun edit(): MutableEntity = MutableGridData(this)
178179

@@ -184,7 +185,7 @@ data class GridData(
184185
override fun open(position: Vector3F, rotation: EulerAngle, scale: Vector3F) =
185186
Grid(
186187
title, description, position, rotation, scale,
187-
rows, columns, rowGap, columnGap, direction, zigZag, id
188+
rows, columns, rowGap, columnGap, direction, zigZag, stagger, id
188189
)
189190
}
190191

src/commonMain/kotlin/baaahs/model/PolyLine.kt

+12-8
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ class Grid(
2424
columnGap: Float,
2525
direction: GridData.Direction,
2626
zigZag: Boolean,
27+
stagger: Int = 1,
2728
id: EntityId = Model.Entity.nextId()
2829
): PolyLine(
2930
name, description,
30-
calcSegments(rows, columns, rowGap, columnGap, direction, zigZag),
31+
calcSegments(rows, columns, rowGap, columnGap, direction, zigZag, stagger),
3132
position, rotation, scale, columnGap, rowGap, id) {
3233
}
3334

@@ -37,26 +38,29 @@ fun calcSegments(
3738
rowGap: Float,
3839
columnGap: Float,
3940
direction: GridData.Direction,
40-
zigZag: Boolean
41+
zigZag: Boolean,
42+
stagger: Int = 1
4143
): List<PolyLine.Segment> {
4244
return when (direction) {
43-
GridData.Direction.ColumnsThenRows ->
45+
GridData.Direction.RowsThenColumns ->
4446
(0 until rows).map { yI ->
47+
val staggerAmount = columnGap / stagger * (yI % stagger)
4548
val y = yI * rowGap
4649
PolyLine.Segment(
47-
Vector3F(0f, y, 0f),
48-
Vector3F((columns - 1) * columnGap, y, 0f),
50+
Vector3F(0f + staggerAmount, y, 0f),
51+
Vector3F((columns - 1) * columnGap + staggerAmount, y, 0f),
4952
columns
5053
).let {
5154
if (zigZag && yI % 2 == 1) it.reverse() else it
5255
}
5356
}
54-
GridData.Direction.RowsThenColumns ->
57+
GridData.Direction.ColumnsThenRows ->
5558
(0 until columns).map { xI ->
59+
val staggerAmount = rowGap / stagger * (xI % stagger)
5660
val x = xI * columnGap
5761
PolyLine.Segment(
58-
Vector3F(x, 0f, 0f),
59-
Vector3F(x, (rows - 1) * rowGap, 0f),
62+
Vector3F(x, 0f + staggerAmount, 0f),
63+
Vector3F(x, (rows - 1) * rowGap + staggerAmount, 0f),
6064
rows
6165
).let {
6266
if (zigZag && xI % 2 == 1) it.reverse() else it

src/commonMain/kotlin/baaahs/models/DemoModel.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ val demoModelData = ModelData(
2525
EulerAngle(1.0, .5, .25),
2626
Vector3F.unit3d,
2727
Model.Entity.nextId(),
28-
20, 25, 1f, 1f
28+
20, 25, 1f, 1f,
29+
GridData.Direction.RowsThenColumns
2930
),
3031
LightRingData(
3132
"Light Ring", null,

src/commonMain/kotlin/baaahs/models/Playa2021Model.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ val playa2021ModelData = ModelData(
1818
EulerAngle.identity,
1919
Vector3F.unit3d,
2020
Model.Entity.nextId(),
21-
7, 11, 1f, 1f, zigZag = true
21+
7, 11, 1f, 1f,
22+
direction = GridData.Direction.RowsThenColumns,
23+
zigZag = true
2224
)
2325
),
2426
ModelUnit.Inches

src/commonMain/kotlin/baaahs/scene/MutableScene.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,10 @@ class MutableGridData(
398398
var columnGap = baseGridData.columnGap
399399
var direction = baseGridData.direction
400400
var zigZag = baseGridData.zigZag
401+
var stagger = baseGridData.stagger
401402

402403
override fun build(): EntityData =
403-
GridData(title, description, position, rotation, scale, id, rows, columns, rowGap, columnGap, direction, zigZag)
404+
GridData(title, description, position, rotation, scale, id, rows, columns, rowGap, columnGap, direction, zigZag, stagger)
404405

405406
override fun getEditorPanels() =
406407
listOf(

src/commonMain/kotlin/baaahs/show/ShowMigrator.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package baaahs.show
22

33
import baaahs.scene.Scene
4-
import baaahs.show.migration.AllSceneMigrations
54
import baaahs.show.migration.AllShowMigrations
5+
import baaahs.show.migration.scene.AllSceneMigrations
66
import baaahs.show.migration.toJsonObj
77
import baaahs.util.Logger
88
import kotlinx.serialization.KSerializer

src/commonMain/kotlin/baaahs/show/migration/AllMigrations.kt src/commonMain/kotlin/baaahs/show/migration/AllShowMigrations.kt

-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,4 @@ val AllShowMigrations: List<DataMigrator.Migration> = listOf(
1212
V7_LegacyTabs,
1313
V8_RenameShaderChannelToStream,
1414
V9_RenameDataSourceToFeed
15-
)
16-
17-
val AllSceneMigrations: List<DataMigrator.Migration> = listOf(
1815
)

src/commonMain/kotlin/baaahs/show/migration/V1_UpdateDataSourceRefs.kt

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package baaahs.show.migration
33
import baaahs.show.DataMigrator
44
import kotlinx.serialization.json.JsonObject
55
import kotlinx.serialization.json.JsonPrimitive
6-
import kotlinx.serialization.json.contentOrNull
7-
import kotlinx.serialization.json.jsonPrimitive
86

97
@Suppress("ClassName")
108
object V1_UpdateDataSourceRefs : DataMigrator.Migration(1) {
@@ -25,7 +23,7 @@ object V1_UpdateDataSourceRefs : DataMigrator.Migration(1) {
2523
override fun migrate(from: JsonObject): JsonObject {
2624
return from.toMutableMap().apply {
2725
mapObjsInDict("dataSources") { _, dataSource ->
28-
val type = dataSource["type"]?.jsonPrimitive?.contentOrNull
26+
val type = dataSource.type
2927
if (type == "baaahs.plugin.CorePlugin.ModelInfoDataSource") {
3028
dataSource.remove("structType")
3129
}

src/commonMain/kotlin/baaahs/show/migration/V4_FlattenGadgetControls.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ object V4_FlattenGadgetControls : DataMigrator.Migration(4) {
3232
override fun migrate(from: JsonObject): JsonObject {
3333
return from.toMutableMap().apply {
3434
mapObjsInDict("controls") { _, control ->
35-
val type = control["type"]?.jsonPrimitive?.contentOrNull
35+
val type = control.type
3636
if (type == "baaahs.Core:Gadget") {
3737
val gadgetData = control["gadget"]?.jsonObject
3838
control.remove("gadget")!!

src/commonMain/kotlin/baaahs/show/migration/V5_FixFixtureInfoRefs.kt

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package baaahs.show.migration
33
import baaahs.show.DataMigrator
44
import kotlinx.serialization.json.JsonObject
55
import kotlinx.serialization.json.JsonPrimitive
6-
import kotlinx.serialization.json.contentOrNull
7-
import kotlinx.serialization.json.jsonPrimitive
86

97
@Suppress("ClassName")
108
object V5_FixFixtureInfoRefs : DataMigrator.Migration(5) {
@@ -15,7 +13,7 @@ object V5_FixFixtureInfoRefs : DataMigrator.Migration(5) {
1513
override fun migrate(from: JsonObject): JsonObject {
1614
return from.toMutableMap().apply {
1715
mapObjsInDict("dataSources") { _, dataSource ->
18-
val type = dataSource["type"]?.jsonPrimitive?.contentOrNull
16+
val type = dataSource.type
1917
if (type != null) {
2018
dataSourceTypeMap[type]?.let { dataSource["type"] = JsonPrimitive(it) }
2119
}

src/commonMain/kotlin/baaahs/show/migration/V8_RenameShaderChannelToStream.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ object V8_RenameShaderChannelToStream : DataMigrator.Migration(8) {
1717
patch.toMutableMap().apply {
1818
replaceJsonObj("incomingLinks") { incomingLinks ->
1919
JsonObject(incomingLinks.mapValues { (_, format) ->
20-
if (format.jsonObject["type"]?.jsonPrimitive?.contentOrNull == "shader-channel") {
20+
if (format.type == "shader-channel") {
2121
format.jsonObject.edit {
2222
put("type", JsonPrimitive("stream"))
2323
put("stream", remove("shaderChannel")!!)

src/commonMain/kotlin/baaahs/show/migration/V9_RenameDataSourceToFeed.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object V9_RenameDataSourceToFeed : DataMigrator.Migration(9) {
2222
patch.jsonObject.edit {
2323
replaceMapValues("incomingLinks") { _, incomingLink ->
2424
incomingLink.jsonObject.edit {
25-
if (this["type"]?.jsonPrimitive?.contentOrNull == "datasource") {
25+
if (this.type == "datasource") {
2626
put("type", JsonPrimitive("feed"))
2727
rename("dataSourceId", "feedId")
2828
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package baaahs.show.migration.scene
2+
3+
import baaahs.show.DataMigrator
4+
5+
val AllSceneMigrations: List<DataMigrator.Migration> = listOf(
6+
V1_GridDirectionBackwards
7+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package baaahs.show.migration.scene
2+
3+
import baaahs.show.DataMigrator
4+
import baaahs.show.migration.*
5+
import kotlinx.serialization.json.*
6+
7+
/**
8+
* Grid directions were backwards.
9+
*/
10+
@Suppress("ClassName")
11+
object V1_GridDirectionBackwards : DataMigrator.Migration(1) {
12+
override fun migrate(from: JsonObject): JsonObject {
13+
return from.edit {
14+
replaceJsonObj("model") { model ->
15+
model.jsonObject.edit {
16+
mapObjsInArray("entities") { entity ->
17+
entity.apply {
18+
if (this.type == "Grid") {
19+
// Grid's direction was backwards
20+
val wrongDirection = this["direction"]?.jsonPrimitive?.contentOrNull
21+
?: "ColumnsThenRows"
22+
when(wrongDirection) {
23+
"RowsThenColumns" -> this["direction"] = JsonPrimitive("ColumnsThenRows")
24+
"ColumnsThenRows" -> this.remove("direction")
25+
else -> error("Unknown direction \"$wrongDirection\".")
26+
}
27+
28+
// Grid's zigzag might as well default to true.
29+
val oldZigZag = this.remove("zigZag")?.jsonPrimitive?.booleanOrNull ?: false
30+
if (!oldZigZag) this["zigZag"] = JsonPrimitive(false)
31+
}
32+
}
33+
}
34+
}
35+
}
36+
}
37+
}
38+
}

src/commonMain/kotlin/baaahs/show/migration/util.kt

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package baaahs.show.migration
22

3-
import kotlinx.serialization.json.JsonArray
4-
import kotlinx.serialization.json.JsonElement
5-
import kotlinx.serialization.json.JsonObject
6-
import kotlinx.serialization.json.buildJsonObject
3+
import kotlinx.serialization.json.*
74

85
fun MutableMap<String, JsonElement>.mapObjsInDict(
96
key: String,
@@ -35,9 +32,20 @@ fun Map<String, JsonElement>.toJsonObj(): JsonObject = buildJsonObject {
3532
}
3633

3734
fun MutableMap<String, JsonElement>.replaceJsonObj(name: String, block: (JsonObject) -> JsonElement) {
38-
this[name] = block((this[name] ?: buildJsonObject { }) as JsonObject)
35+
val origEl = this[name] ?: buildJsonObject { }
36+
if (origEl !is JsonObject) error("\"$name\" entry is a ${origEl::class.simpleName}, not an object.")
37+
this[name] = block(origEl)
3938
}
4039

40+
val JsonElement.type get(): String? =
41+
this.jsonObject["type"]?.jsonPrimitive?.contentOrNull
42+
43+
val JsonObject.type get(): String? =
44+
this["type"]?.jsonPrimitive?.contentOrNull
45+
46+
val MutableMap<String, JsonElement>.type get(): String? =
47+
this["type"]?.jsonPrimitive?.contentOrNull
48+
4149
fun MutableMap<String, JsonElement>.replaceMapValues(
4250
name: String,
4351
block: (key: String, value: JsonElement) -> JsonElement
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package baaahs.model
2+
3+
import baaahs.describe
4+
import baaahs.geom.Vector3F
5+
import baaahs.gl.override
6+
import baaahs.model.PolyLine.Segment
7+
import ch.tutteli.atrium.api.fluent.en_GB.containsExactly
8+
import ch.tutteli.atrium.api.verbs.expect
9+
import org.spekframework.spek2.Spek
10+
11+
object GridSpec : Spek({
12+
describe<Grid> {
13+
val grid by value {
14+
Grid(
15+
"grid",
16+
columns = 4, rows = 5, columnGap = 1f, rowGap = 1f,
17+
direction = GridData.Direction.RowsThenColumns,
18+
zigZag = true
19+
)
20+
}
21+
22+
it("calculates segments") {
23+
expect(grid.segments).containsExactly(
24+
Segment(Vector3F(0.0, 0.0, 0.0), Vector3F(3.0, 0.0, 0.0), 4),
25+
Segment(Vector3F(3.0, 1.0, 0.0), Vector3F(0.0, 1.0, 0.0), 4),
26+
Segment(Vector3F(0.0, 2.0, 0.0), Vector3F(3.0, 2.0, 0.0), 4),
27+
Segment(Vector3F(3.0, 3.0, 0.0), Vector3F(0.0, 3.0, 0.0), 4),
28+
Segment(Vector3F(0.0, 4.0, 0.0), Vector3F(3.0, 4.0, 0.0), 4)
29+
)
30+
}
31+
32+
context("with stagger") {
33+
override(grid) {
34+
Grid(
35+
"grid",
36+
columns = 4, rows = 5, columnGap = 1f, rowGap = 1f,
37+
direction = GridData.Direction.RowsThenColumns,
38+
zigZag = true, stagger = 2
39+
)
40+
}
41+
42+
it("calculates segments with stagger") {
43+
expect(grid.segments).containsExactly(
44+
Segment(Vector3F(0.0, 0.0, 0.0), Vector3F(3.0, 0.0, 0.0), 4),
45+
Segment(Vector3F(3.5, 1.0, 0.0), Vector3F(0.5, 1.0, 0.0), 4),
46+
Segment(Vector3F(0.0, 2.0, 0.0), Vector3F(3.0, 2.0, 0.0), 4),
47+
Segment(Vector3F(3.5, 3.0, 0.0), Vector3F(0.5, 3.0, 0.0), 4),
48+
Segment(Vector3F(0.0, 4.0, 0.0), Vector3F(3.0, 4.0, 0.0), 4)
49+
)
50+
}
51+
}
52+
}
53+
})

0 commit comments

Comments
 (0)