Skip to content

Commit 56dbde1

Browse files
committed
Render nested classes below node fields
1 parent 7d33aa5 commit 56dbde1

File tree

6 files changed

+112
-72
lines changed

6 files changed

+112
-72
lines changed

src/main/kotlin/com/tomwyr/generator/Renderer.kt

Lines changed: 78 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ class NodeTreeRenderer {
1010
val sceneNodes = scenes.map { renderScene(it) }.joinLines(spacing = 2)
1111
val types = renderTypes()
1212

13-
return listOfNotNull(header, nodeTree, sceneNodes, types)
14-
.joinLines(spacing = 2).plus("\n")
13+
return listOf(header, nodeTree, sceneNodes, types)
14+
.joinLines(spacing = 2).trimBlankLines().plus("\n")
1515
}
1616

1717
private fun renderHeader(packageName: String?): String {
@@ -39,35 +39,25 @@ class NodeTreeRenderer {
3939
private fun renderScene(scene: Scene): String {
4040
val nodePath = "\$path/${scene.root.name}"
4141

42-
val renderNodeHeader = { type: String ->
43-
"""
44-
|class ${scene.name}Scene(private val path: String) : NodeRef<${type}>("$nodePath", "$type")
42+
return when (val root = scene.root) {
43+
is ParentNode -> renderParentNode(
44+
node = root,
45+
nodePath = nodePath,
46+
className = "${scene.name}Scene",
47+
nestedClass = false,
48+
)
49+
50+
is LeafNode -> """
51+
|class ${scene.name}Scene(private val path: String) : NodeRef<${root.type}>("$nodePath", "${root.type}")
4552
""".trimMargin()
46-
}
4753

48-
return when (val root = scene.root) {
49-
is ParentNode -> {
50-
val header = renderNodeHeader(root.type)
51-
val children = root.children.map { renderNode(it, nodePath) }.joinLines().indentLine()
52-
53-
"""
54-
|$header {
55-
| $children
56-
|}
57-
""".trimMargin()
58-
}
59-
60-
is LeafNode -> renderNodeHeader(root.type)
61-
62-
is NestedScene -> {
63-
"""
64-
|class ${scene.name}Scene(private val path: String) : ${root.scene}Scene(path)
65-
""".trimMargin()
66-
}
54+
is NestedScene -> """
55+
|class ${scene.name}Scene(private val path: String) : ${root.scene}Scene(path)
56+
""".trimMargin()
6757
}
6858
}
6959

70-
private fun renderNode(node: Node, parentPath: String): String {
60+
private fun renderNode(node: Node, parentPath: String): RenderNodeResult {
7161
val nodePath = "$parentPath/${node.name}"
7262
val symbolName = node.name
7363
.split("\\s+".toRegex())
@@ -76,37 +66,70 @@ class NodeTreeRenderer {
7666

7767
Log.renderingNode(node, nodePath)
7868

79-
return when (node) {
80-
is ParentNode -> {
81-
val children = node.children.map { renderNode(it, nodePath) }.joinLines().indentLine()
82-
83-
"""
84-
|val $symbolName = ${symbolName}Tree()
85-
|inner class ${symbolName}Tree : NodeRef<${node.type}>("$nodePath", "${node.type}") {
86-
| $children
87-
|}
88-
""".trimMargin()
89-
}
90-
91-
is LeafNode -> {
92-
"""
93-
|val $symbolName = NodeRef<${node.type}>("$nodePath", "${node.type}")
94-
""".trimMargin()
95-
}
96-
97-
is NestedScene -> {
98-
"""
99-
|val $symbolName = ${node.scene}Scene("$nodePath")
100-
""".trimMargin()
101-
}
69+
val field = when (node) {
70+
is ParentNode -> """
71+
|val $symbolName = ${symbolName}Tree()
72+
""".trimMargin()
73+
74+
is LeafNode -> """
75+
|val $symbolName = NodeRef<${node.type}>("$nodePath", "${node.type}")
76+
""".trimMargin()
77+
78+
is NestedScene -> """
79+
|val $symbolName = ${node.scene}Scene("$nodePath")
80+
""".trimMargin()
81+
}
82+
83+
val nestedClass = when (node) {
84+
is ParentNode -> renderParentNode(
85+
node = node,
86+
nodePath = "$parentPath/${node.name}",
87+
className = "${symbolName}Tree",
88+
nestedClass = true,
89+
)
90+
91+
else -> null
92+
}
93+
94+
return RenderNodeResult(field, nestedClass)
95+
}
96+
97+
private fun renderParentNode(
98+
node: ParentNode,
99+
nodePath: String,
100+
className: String,
101+
nestedClass: Boolean,
102+
): String {
103+
val (classType, constructor) = when (nestedClass) {
104+
true -> "inner class" to ""
105+
false -> "class" to "(private val path: String)"
102106
}
107+
val header = """
108+
|$classType $className$constructor : NodeRef<${node.type}>("$nodePath", "${node.type}")
109+
""".trimMargin()
110+
111+
val children = node.children.map { child -> renderNode(child, nodePath) }
112+
val fields = children.map { it.field }.joinLines().indentLine()
113+
val nestedClasses = children.mapNotNull { it.nestedClass }.joinLines(spacing = 2).indentLine()
114+
115+
val body = """
116+
| $fields
117+
|
118+
| $nestedClasses
119+
""".trimMargin().trimEnd()
120+
121+
return """
122+
|$header {
123+
|$body
124+
|}
125+
""".trimMargin()
103126
}
104127

105128
private fun renderTypes(): String {
106129
return """
107130
|open class NodeRef<T : Node>(
108-
| private val path: String,
109-
| private val type: String,
131+
| private val path: String,
132+
| private val type: String,
110133
|) {
111134
| operator fun getValue(thisRef: Node, property: KProperty<*>): T {
112135
| val node = thisRef.getNode(NodePath(path)) ?: throw NodeNotFoundException(path)
@@ -126,3 +149,7 @@ class NodeTreeRenderer {
126149
private fun Iterable<String>.joinLines(spacing: Int = 1): String = joinToString("\n".repeat(spacing))
127150

128151
private fun String.indentLine(times: Int = 1): String = lineSequence().joinToString("\n" + " ".repeat(times))
152+
153+
private fun String.trimBlankLines(): String = lineSequence().joinToString("\n") { it.ifBlank { "" } }
154+
155+
private data class RenderNodeResult(val field: String, val nestedClass: String?)

src/test/resources/dodge-the-creeps/Expected

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ class MainScene(private val path: String) : NodeRef<Node>("$path/Main", "Node")
2626
val StartTimer = NodeRef<Timer>("$path/Main/StartTimer", "Timer")
2727
val StartPosition = NodeRef<Marker2D>("$path/Main/StartPosition", "Marker2D")
2828
val MobPath = MobPathTree()
29-
inner class MobPathTree : NodeRef<Path2D>("$path/Main/MobPath", "Path2D") {
30-
val MobSpawnLocation = NodeRef<PathFollow2D>("$path/Main/MobPath/MobSpawnLocation", "PathFollow2D")
31-
}
3229
val HUD = HUDScene("$path/Main/HUD")
3330
val Music = NodeRef<AudioStreamPlayer>("$path/Main/Music", "AudioStreamPlayer")
3431
val DeathSound = NodeRef<AudioStreamPlayer>("$path/Main/DeathSound", "AudioStreamPlayer")
32+
33+
inner class MobPathTree : NodeRef<Path2D>("$path/Main/MobPath", "Path2D") {
34+
val MobSpawnLocation = NodeRef<PathFollow2D>("$path/Main/MobPath/MobSpawnLocation", "PathFollow2D")
35+
}
3536
}
3637

3738
class MobScene(private val path: String) : NodeRef<RigidBody2D>("$path/Mob", "RigidBody2D") {
@@ -47,8 +48,8 @@ class PlayerScene(private val path: String) : NodeRef<Area2D>("$path/Player", "A
4748
}
4849

4950
open class NodeRef<T : Node>(
50-
private val path: String,
51-
private val type: String,
51+
private val path: String,
52+
private val type: String,
5253
) {
5354
operator fun getValue(thisRef: Node, property: KProperty<*>): T {
5455
val node = thisRef.getNode(NodePath(path)) ?: throw NodeNotFoundException(path)

src/test/resources/physics-test/Expected

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@ class MainScene(private val path: String) : NodeRef<Control>("$path/Main", "Cont
1717
val LabelTest = NodeRef<Label>("$path/Main/LabelTest", "Label")
1818
val LabelPause = NodeRef<Label>("$path/Main/LabelPause", "Label")
1919
val PanelLog = PanelLogTree()
20+
2021
inner class PanelLogTree : NodeRef<Panel>("$path/Main/PanelLog", "Panel") {
2122
val ButtonClear = NodeRef<Button>("$path/Main/PanelLog/ButtonClear", "Button")
2223
val CheckBoxScroll = NodeRef<CheckButton>("$path/Main/PanelLog/CheckBoxScroll", "CheckButton")
2324
val ScrollLog = ScrollLogTree()
25+
2426
inner class ScrollLogTree : NodeRef<ScrollContainer>("$path/Main/PanelLog/ScrollLog", "ScrollContainer") {
2527
val VBoxLog = VBoxLogTree()
28+
2629
inner class VBoxLogTree : NodeRef<VBoxContainer>("$path/Main/PanelLog/ScrollLog/VBoxLog", "VBoxContainer") {
2730
val LabelLog = NodeRef<Label>("$path/Main/PanelLog/ScrollLog/VBoxLog/LabelLog", "Label")
2831
}
@@ -31,8 +34,8 @@ class MainScene(private val path: String) : NodeRef<Control>("$path/Main", "Cont
3134
}
3235

3336
open class NodeRef<T : Node>(
34-
private val path: String,
35-
private val type: String,
37+
private val path: String,
38+
private val type: String,
3639
) {
3740
operator fun getValue(thisRef: Node, property: KProperty<*>): T {
3841
val node = thisRef.getNode(NodePath(path)) ?: throw NodeNotFoundException(path)

src/test/resources/scene-changer/Expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class SceneBScene(private val path: String) : NodeRef<Panel>("$path/SceneB", "Pa
2020
}
2121

2222
open class NodeRef<T : Node>(
23-
private val path: String,
24-
private val type: String,
23+
private val path: String,
24+
private val type: String,
2525
) {
2626
operator fun getValue(thisRef: Node, property: KProperty<*>): T {
2727
val node = thisRef.getNode(NodePath(path)) ?: throw NodeNotFoundException(path)

src/test/resources/simple/Expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ class MainScene(private val path: String) : NodeRef<GridContainer>("$path/Root",
1616
}
1717

1818
open class NodeRef<T : Node>(
19-
private val path: String,
20-
private val type: String,
19+
private val path: String,
20+
private val type: String,
2121
) {
2222
operator fun getValue(thisRef: Node, property: KProperty<*>): T {
2323
val node = thisRef.getNode(NodePath(path)) ?: throw NodeNotFoundException(path)

src/test/resources/waypoints/Expected

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,47 @@ object GDTree {
1111

1212
class MainScene(private val path: String) : NodeRef<Node3D>("$path/Main", "Node3D") {
1313
val BlueCube = BlueCubeTree()
14+
val GreenCube = GreenCubeTree()
15+
val YellowCube = YellowCubeTree()
16+
val RedCube = RedCubeTree()
17+
val Camera3D = NodeRef<Camera3D>("$path/Main/Camera3D", "Camera3D")
18+
val Label = NodeRef<Label>("$path/Main/Label", "Label")
19+
val Ground = NodeRef<MeshInstance3D>("$path/Main/Ground", "MeshInstance3D")
20+
val WhiteCube = NodeRef<MeshInstance3D>("$path/Main/WhiteCube", "MeshInstance3D")
21+
val Environment = EnvironmentTree()
22+
1423
inner class BlueCubeTree : NodeRef<MeshInstance3D>("$path/Main/BlueCube", "MeshInstance3D") {
1524
val WaypointAnchor = WaypointAnchorTree()
25+
1626
inner class WaypointAnchorTree : NodeRef<Marker3D>("$path/Main/BlueCube/WaypointAnchor", "Marker3D") {
1727
val Waypoint = WaypointScene("$path/Main/BlueCube/WaypointAnchor/Waypoint")
1828
}
1929
}
20-
val GreenCube = GreenCubeTree()
30+
2131
inner class GreenCubeTree : NodeRef<MeshInstance3D>("$path/Main/GreenCube", "MeshInstance3D") {
2232
val WaypointAnchor = WaypointAnchorTree()
33+
2334
inner class WaypointAnchorTree : NodeRef<Marker3D>("$path/Main/GreenCube/WaypointAnchor", "Marker3D") {
2435
val Waypoint = WaypointScene("$path/Main/GreenCube/WaypointAnchor/Waypoint")
2536
}
2637
}
27-
val YellowCube = YellowCubeTree()
38+
2839
inner class YellowCubeTree : NodeRef<MeshInstance3D>("$path/Main/YellowCube", "MeshInstance3D") {
2940
val WaypointAnchor = WaypointAnchorTree()
41+
3042
inner class WaypointAnchorTree : NodeRef<Marker3D>("$path/Main/YellowCube/WaypointAnchor", "Marker3D") {
3143
val Waypoint = WaypointScene("$path/Main/YellowCube/WaypointAnchor/Waypoint")
3244
}
3345
}
34-
val RedCube = RedCubeTree()
46+
3547
inner class RedCubeTree : NodeRef<MeshInstance3D>("$path/Main/RedCube", "MeshInstance3D") {
3648
val WaypointAnchor = WaypointAnchorTree()
49+
3750
inner class WaypointAnchorTree : NodeRef<Marker3D>("$path/Main/RedCube/WaypointAnchor", "Marker3D") {
3851
val Waypoint = WaypointScene("$path/Main/RedCube/WaypointAnchor/Waypoint")
3952
}
4053
}
41-
val Camera3D = NodeRef<Camera3D>("$path/Main/Camera3D", "Camera3D")
42-
val Label = NodeRef<Label>("$path/Main/Label", "Label")
43-
val Ground = NodeRef<MeshInstance3D>("$path/Main/Ground", "MeshInstance3D")
44-
val WhiteCube = NodeRef<MeshInstance3D>("$path/Main/WhiteCube", "MeshInstance3D")
45-
val Environment = EnvironmentTree()
54+
4655
inner class EnvironmentTree : NodeRef<WorldEnvironment>("$path/Main/Environment", "WorldEnvironment") {
4756
val Sun = NodeRef<DirectionalLight3D>("$path/Main/Environment/Sun", "DirectionalLight3D")
4857
}
@@ -54,8 +63,8 @@ class WaypointScene(private val path: String) : NodeRef<Control>("$path/Waypoint
5463
}
5564

5665
open class NodeRef<T : Node>(
57-
private val path: String,
58-
private val type: String,
66+
private val path: String,
67+
private val type: String,
5968
) {
6069
operator fun getValue(thisRef: Node, property: KProperty<*>): T {
6170
val node = thisRef.getNode(NodePath(path)) ?: throw NodeNotFoundException(path)

0 commit comments

Comments
 (0)