Skip to content

Commit 86ef29b

Browse files
committed
streamlined ShapeData types
1 parent 23d64b1 commit 86ef29b

5 files changed

Lines changed: 75 additions & 80 deletions

File tree

kool-editor-model/src/commonMain/kotlin/de/fabmax/kool/editor/components/MeshComponent.kt

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package de.fabmax.kool.editor.components
22

33
import de.fabmax.kool.editor.api.*
4-
import de.fabmax.kool.editor.data.ComponentInfo
5-
import de.fabmax.kool.editor.data.MaterialComponentData
6-
import de.fabmax.kool.editor.data.MeshComponentData
7-
import de.fabmax.kool.editor.data.ShapeData
4+
import de.fabmax.kool.editor.data.*
85
import de.fabmax.kool.math.Vec2f
96
import de.fabmax.kool.math.Vec3f
107
import de.fabmax.kool.math.deg
@@ -180,10 +177,8 @@ class MeshComponent(
180177
}
181178

182179
fun MeshBuilder.generateShape(shape: ShapeData) = withTransform {
183-
applyCommon(shape.common)
184-
185180
when (shape) {
186-
is ShapeData.Box -> cube { size.set(shape.size.toVec3f()) }
181+
is ShapeData.Box -> generateBox(shape)
187182
is ShapeData.Sphere -> generateSphere(shape)
188183
is ShapeData.Cylinder -> generateCylinder(shape)
189184
is ShapeData.Capsule -> generateCapsule(shape)
@@ -194,7 +189,13 @@ class MeshComponent(
194189
}
195190
}
196191

192+
fun MeshBuilder.generateBox(shape: ShapeData.Box) {
193+
applyCommon(shape.pose, shape.color, shape.uvScale)
194+
cube { size.set(shape.size.toVec3f()) }
195+
}
196+
197197
fun MeshBuilder.generateSphere(shape: ShapeData.Sphere) {
198+
applyCommon(shape.pose, shape.color, shape.uvScale)
198199
if (shape.sphereType == "ico") {
199200
icoSphere {
200201
radius = shape.radius.toFloat()
@@ -209,6 +210,7 @@ class MeshComponent(
209210
}
210211

211212
fun MeshBuilder.generateCylinder(shape: ShapeData.Cylinder) {
213+
applyCommon(shape.pose, shape.color, shape.uvScale)
212214
// cylinder is generated in x-axis major orientation to make it align with physics geometry
213215
rotate(90f.deg, Vec3f.Z_AXIS)
214216
cylinder {
@@ -220,6 +222,7 @@ class MeshComponent(
220222
}
221223

222224
fun MeshBuilder.generateCapsule(shape: ShapeData.Capsule) {
225+
applyCommon(shape.pose, shape.color, shape.uvScale)
223226
profile {
224227
val r = shape.radius.toFloat()
225228
val h = shape.length.toFloat()
@@ -236,6 +239,7 @@ class MeshComponent(
236239
}
237240

238241
fun MeshBuilder.generateRect(shape: ShapeData.Rect) {
242+
applyCommon(shape.pose, shape.color, shape.uvScale)
239243
grid {
240244
sizeX = shape.size.x.toFloat()
241245
sizeY = shape.size.y.toFloat()
@@ -255,7 +259,7 @@ class MeshComponent(
255259
val szY = (rows - 1) * shape.rowScale.toFloat()
256260

257261
generate {
258-
applyCommon(shape.common)
262+
applyCommon(uvScale = shape.uvScale)
259263

260264
translate(szX * 0.5f, 0f, szY * 0.5f)
261265
grid {
@@ -271,12 +275,14 @@ class MeshComponent(
271275
}
272276
}
273277

274-
fun MeshBuilder.applyCommon(common: ShapeData.CommonShapeData) {
275-
common.pose.toMat4f(transform)
276-
color = common.vertexColor.toColorLinear()
277-
vertexModFun = {
278-
texCoord.x *= common.uvScale.x.toFloat()
279-
texCoord.y *= common.uvScale.y.toFloat()
278+
fun MeshBuilder.applyCommon(pose: TransformData? = null, shapeColor: ColorData? = null, uvScale: Vec2Data? = null) {
279+
pose?.toMat4f(transform)
280+
shapeColor?.let { color = it.toColorLinear() }
281+
uvScale?.let { scale ->
282+
vertexModFun = {
283+
texCoord.x *= scale.x.toFloat()
284+
texCoord.y *= scale.y.toFloat()
285+
}
280286
}
281287
}
282288

kool-editor-model/src/commonMain/kotlin/de/fabmax/kool/editor/data/ShapeData.kt

Lines changed: 27 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,41 @@ import de.fabmax.kool.util.MdColor
44
import kotlinx.serialization.Serializable
55

66
@Serializable
7-
sealed class ShapeData {
7+
sealed interface ShapeData {
88

9-
abstract val name: String
10-
abstract val hasUvs: Boolean
11-
abstract val common: CommonShapeData
12-
13-
fun copyShape(common: CommonShapeData = this.common): ShapeData {
14-
val copied = when (this) {
15-
is Box -> copy(common = common)
16-
is Capsule -> copy(common = common)
17-
is Cylinder -> copy(common = common)
18-
is Custom -> copy(common = common)
19-
is Sphere -> copy(common = common)
20-
is Rect -> copy(common = common)
21-
is Model -> copy(common = common)
22-
is Heightmap -> copy(common = common)
23-
is Plane -> copy(common = common)
24-
}
25-
return copied
26-
}
27-
28-
@Serializable
29-
data class CommonShapeData(
30-
val pose: TransformData = TransformData.IDENTITY,
31-
val vertexColor: ColorData = ColorData(MdColor.GREY.toLinear()),
32-
val uvScale: Vec2Data = Vec2Data(1.0, 1.0)
33-
)
9+
val name: String
3410

3511
@Serializable
3612
data class Box(
3713
val size: Vec3Data = Vec3Data(1.0, 1.0, 1.0),
38-
override val common: CommonShapeData = CommonShapeData()
39-
) : ShapeData() {
14+
val pose: TransformData = TransformData.IDENTITY,
15+
val uvScale: Vec2Data = Vec2Data(1.0, 1.0),
16+
val color: ColorData = ColorData(MdColor.GREY),
17+
) : ShapeData {
4018
override val name: String get() = "Box"
41-
override val hasUvs: Boolean = true
4219
}
4320

4421
@Serializable
4522
data class Sphere(
4623
val radius: Double = 1.0,
4724
val steps: Int = 20,
4825
val sphereType: String = "uv",
49-
override val common: CommonShapeData = CommonShapeData()
50-
) : ShapeData() {
26+
val pose: TransformData = TransformData.IDENTITY,
27+
val uvScale: Vec2Data = Vec2Data(1.0, 1.0),
28+
val color: ColorData = ColorData(MdColor.GREY),
29+
) : ShapeData {
5130

5231
override val name: String get() = "Sphere"
53-
override val hasUvs: Boolean = true
5432
}
5533

5634
@Serializable
5735
data class Rect(
5836
val size: Vec2Data = Vec2Data(1.0, 1.0),
59-
override val common: CommonShapeData = CommonShapeData()
60-
) : ShapeData() {
37+
val pose: TransformData = TransformData.IDENTITY,
38+
val uvScale: Vec2Data = Vec2Data(1.0, 1.0),
39+
val color: ColorData = ColorData(MdColor.GREY),
40+
) : ShapeData {
6141
override val name: String get() = "Rect"
62-
override val hasUvs: Boolean = true
6342
}
6443

6544
@Serializable
@@ -68,34 +47,32 @@ sealed class ShapeData {
6847
val bottomRadius: Double = 1.0,
6948
val length: Double = 1.0,
7049
val steps: Int = 32,
71-
override val common: CommonShapeData = CommonShapeData()
72-
) : ShapeData() {
73-
50+
val pose: TransformData = TransformData.IDENTITY,
51+
val uvScale: Vec2Data = Vec2Data(1.0, 1.0),
52+
val color: ColorData = ColorData(MdColor.GREY),
53+
) : ShapeData {
7454
override val name: String get() = "Cylinder"
75-
override val hasUvs: Boolean = true
7655
}
7756

7857
@Serializable
7958
data class Capsule(
8059
val radius: Double = 1.0,
8160
val length: Double = 1.0,
8261
val steps: Int = 32,
83-
override val common: CommonShapeData = CommonShapeData()
84-
) : ShapeData() {
85-
62+
val pose: TransformData = TransformData.IDENTITY,
63+
val uvScale: Vec2Data = Vec2Data(1.0, 1.0),
64+
val color: ColorData = ColorData(MdColor.GREY),
65+
) : ShapeData {
8666
override val name: String get() = "Capsule"
87-
override val hasUvs: Boolean = false
8867
}
8968

9069
@Serializable
9170
data class Model(
9271
val modelPath: String = "",
9372
val sceneIndex: Int = 0,
9473
val animationIndex: Int = -1,
95-
override val common: CommonShapeData = CommonShapeData()
96-
) : ShapeData() {
74+
) : ShapeData {
9775
override val name: String get() = "Model"
98-
override val hasUvs: Boolean = false
9976
}
10077

10178
@Serializable
@@ -105,33 +82,28 @@ sealed class ShapeData {
10582
val heightScale: Double = 100.0,
10683
val rowScale: Double = 1.0,
10784
val colScale: Double = 1.0,
108-
override val common: CommonShapeData = CommonShapeData()
109-
) : ShapeData() {
85+
val uvScale: Vec2Data = Vec2Data(1.0, 1.0),
86+
) : ShapeData {
11087
override val name: String get() = "Heightmap"
111-
override val hasUvs: Boolean = true
11288
}
11389

11490
@Serializable
115-
data class Custom(override val common: CommonShapeData = CommonShapeData()) : ShapeData() {
91+
data object Custom : ShapeData {
11692
override val name: String get() = "Custom"
117-
override val hasUvs: Boolean = false
11893
}
11994

12095
@Serializable
121-
data class Plane(override val common: CommonShapeData = CommonShapeData()) : ShapeData() {
96+
data object Plane : ShapeData {
12297
override val name: String get() = "Plane"
123-
override val hasUvs: Boolean = false
12498
}
12599

126100
companion object {
127-
val defaultCustom = Custom()
128101
val defaultBox = Box()
129102
val defaultSphere = Sphere()
130103
val defaultRect = Rect()
131104
val defaultCylinder = Cylinder()
132105
val defaultCapsule = Capsule()
133106
val defaultModel = Model()
134107
val defaultHeightmap = Heightmap()
135-
val defaultPlane = Plane()
136108
}
137109
}

kool-editor/src/commonMain/kotlin/de/fabmax/kool/editor/ui/ContextMenus.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ fun addSceneObjectMenu(label: String, parent: GameEntity?, position: Vec3f? = nu
2020
item("Sphere", IconMap.small.shadowedSphere) { scene.addNewMesh(parent, ShapeData.defaultSphere, position) }
2121
item("Cylinder", IconMap.small.cylinder) { scene.addNewMesh(parent, ShapeData.defaultCylinder, position) }
2222
item("Capsule", IconMap.small.capsule) { scene.addNewMesh(parent, ShapeData.defaultCapsule, position) }
23-
item("Custom", IconMap.small.code) { scene.addNewMesh(parent, ShapeData.defaultCustom, position) }
23+
item("Custom", IconMap.small.code) { scene.addNewMesh(parent, ShapeData.Custom, position) }
2424
}
2525
if (editor.availableAssets.modelAssets.isNotEmpty()) {
2626
subMenu("glTF model", IconMap.small.file3d) {

kool-editor/src/commonMain/kotlin/de/fabmax/kool/editor/ui/MeshEditor.kt

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class MeshEditor : ComponentEditor<MeshComponent>() {
6161
ShapeOption.Capsule -> listOf(ShapeData.defaultCapsule)
6262
ShapeOption.Model -> listOf(ShapeData.defaultModel)
6363
ShapeOption.Heightmap -> listOf(ShapeData.defaultHeightmap)
64-
ShapeOption.Empty -> listOf(ShapeData.defaultCustom)
64+
ShapeOption.Empty -> listOf(ShapeData.Custom)
6565
}
6666
val actions = components
6767
.filter { it.data.shapes != newShapes }
@@ -84,14 +84,6 @@ class MeshEditor : ComponentEditor<MeshComponent>() {
8484
is ShapeData.Custom -> { }
8585
is ShapeData.Plane -> error("Plane shape is not supported as mesh shape")
8686
}
87-
88-
if (shape.hasUvs) {
89-
shapeVec2Editor<ShapeData>(
90-
valueGetter = { it.common.uvScale.toVec2d() },
91-
valueSetter = { oldData, newValue -> oldData.copyShape(oldData.common.copy(uvScale = Vec2Data(newValue))) },
92-
label = "Texture scale:"
93-
)
94-
}
9587
}
9688

9789
private fun UiScope.boxProperties() = Column(width = Grow.Std, scopeName = "boxProperties") {
@@ -101,6 +93,11 @@ class MeshEditor : ComponentEditor<MeshComponent>() {
10193
label = "Size:",
10294
minValues = Vec3d.ZERO
10395
)
96+
shapeVec2Editor<ShapeData.Box>(
97+
valueGetter = { it.uvScale.toVec2d() },
98+
valueSetter = { oldData, newValue -> oldData.copy(uvScale = Vec2Data(newValue)) },
99+
label = "Texture scale:"
100+
)
104101
}
105102

106103
private fun UiScope.rectProperties() = Column(width = Grow.Std, scopeName = "rectProperties") {
@@ -110,6 +107,11 @@ class MeshEditor : ComponentEditor<MeshComponent>() {
110107
label = "Size:",
111108
minValues = Vec2d.ZERO
112109
)
110+
shapeVec2Editor<ShapeData.Rect>(
111+
valueGetter = { it.uvScale.toVec2d() },
112+
valueSetter = { oldData, newValue -> oldData.copy(uvScale = Vec2Data(newValue)) },
113+
label = "Texture scale:"
114+
)
113115
}
114116

115117
private fun UiScope.sphereProperties() = Column(width = Grow.Std, scopeName = "sphereProperties") {
@@ -149,6 +151,11 @@ class MeshEditor : ComponentEditor<MeshComponent>() {
149151
maxValue = 100.0
150152
)
151153
}
154+
shapeVec2Editor<ShapeData.Sphere>(
155+
valueGetter = { it.uvScale.toVec2d() },
156+
valueSetter = { oldData, newValue -> oldData.copy(uvScale = Vec2Data(newValue)) },
157+
label = "Texture scale:"
158+
)
152159
}
153160

154161
private fun UiScope.cylinderProperties() = Column(
@@ -200,6 +207,11 @@ class MeshEditor : ComponentEditor<MeshComponent>() {
200207
minValue = 3.0,
201208
maxValue = 100.0
202209
)
210+
shapeVec2Editor<ShapeData.Cylinder>(
211+
valueGetter = { it.uvScale.toVec2d() },
212+
valueSetter = { oldData, newValue -> oldData.copy(uvScale = Vec2Data(newValue)) },
213+
label = "Texture scale:"
214+
)
203215
}
204216

205217
private fun UiScope.capsuleProperties() = Column(
@@ -341,6 +353,11 @@ class MeshEditor : ComponentEditor<MeshComponent>() {
341353
}
342354
}
343355
)
356+
shapeVec2Editor<ShapeData.Heightmap>(
357+
valueGetter = { it.uvScale.toVec2d() },
358+
valueSetter = { oldData, newValue -> oldData.copy(uvScale = Vec2Data(newValue)) },
359+
label = "Texture scale:"
360+
)
344361
}
345362

346363
private inline fun <reified T: ShapeData> UiScope.shapeDoubleEditor(

kool-editor/src/commonMain/kotlin/de/fabmax/kool/editor/ui/RigidActorEditor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ class RigidActorEditor : ComponentEditor<RigidActorComponent>() {
105105
ShapeOption.Sphere -> listOf(ShapeData.defaultSphere)
106106
ShapeOption.Cylinder -> listOf(ShapeData.defaultCylinder)
107107
ShapeOption.Capsule -> listOf(ShapeData.defaultCapsule)
108-
ShapeOption.Plane -> listOf(ShapeData.defaultPlane)
109108
ShapeOption.Heightmap -> listOf(ShapeData.defaultHeightmap)
109+
ShapeOption.Plane -> listOf(ShapeData.Plane)
110110
}
111111
val actions = components
112112
.filter { it.data.shapes != newShapes }

0 commit comments

Comments
 (0)