Skip to content

Commit 1369497

Browse files
committed
syntax check, show an error icon if there are incomplete paths, #651
1 parent 0d50a63 commit 1369497

File tree

3 files changed

+79
-5
lines changed

3 files changed

+79
-5
lines changed

fxgl-tools/src/main/kotlin/com/almasb/fxgl/tools/dialogues/DialoguePane.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ class DialoguePane(graph: DialogueGraph = DialogueGraph()) : Pane() {
9191

9292
val isDirtyProperty = SimpleBooleanProperty(false)
9393

94+
/**
95+
* Are all outgoing links connected.
96+
*/
97+
val isConnectedProperty = SimpleBooleanProperty(true)
98+
9499
private val scale = Scale()
95100

96101
private val dragScale = 1.35
@@ -363,6 +368,8 @@ class DialoguePane(graph: DialogueGraph = DialogueGraph()) : Pane() {
363368
val nodeView = nodeViewConstructor(node)
364369

365370
addNodeView(nodeView, x, y)
371+
372+
evaluateGraphConnectivity()
366373
}
367374

368375
private fun onRemoved(node: DialogueNode) {
@@ -383,6 +390,8 @@ class DialoguePane(graph: DialogueGraph = DialogueGraph()) : Pane() {
383390
.from(Point2D(1.0, 1.0))
384391
.to(Point2D.ZERO)
385392
.buildAndPlay()
393+
394+
evaluateGraphConnectivity()
386395
}
387396

388397
private fun onAdded(edge: DialogueEdge) {
@@ -401,6 +410,8 @@ class DialoguePane(graph: DialogueGraph = DialogueGraph()) : Pane() {
401410
val edgeView = EdgeView(edge, outPoint, inPoint)
402411

403412
edgeViews.children.add(edgeView)
413+
414+
evaluateGraphConnectivity()
404415
}
405416

406417
private fun onRemoved(edge: DialogueEdge) {
@@ -444,6 +455,18 @@ class DialoguePane(graph: DialogueGraph = DialogueGraph()) : Pane() {
444455
edgeView.source.disconnect()
445456

446457
edgeViews.children -= edgeView
458+
459+
evaluateGraphConnectivity()
460+
}
461+
462+
/**
463+
* Checks that all outgoing links are connected.
464+
*/
465+
private fun evaluateGraphConnectivity() {
466+
isConnectedProperty.value = nodeViews.children
467+
.map { it as NodeView }
468+
.flatMap { it.outPoints }
469+
.all { it.isConnected }
447470
}
448471

449472
private fun getNodeView(node: DialogueNode): NodeView {

fxgl-tools/src/main/kotlin/com/almasb/fxgl/tools/dialogues/MainUI.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,15 @@ import com.almasb.fxgl.cutscene.dialogue.SerializableGraph
1010
import com.almasb.fxgl.dsl.*
1111
import com.almasb.fxgl.input.InputModifier
1212
import com.almasb.fxgl.input.UserAction
13+
import com.almasb.fxgl.tools.dialogues.ui.ErrorIcon
1314
import com.almasb.fxgl.tools.dialogues.ui.FXGLContextMenu
1415
import com.fasterxml.jackson.databind.ObjectMapper
1516
import com.fasterxml.jackson.databind.SerializationFeature
1617
import javafx.beans.binding.Bindings
1718
import javafx.geometry.Pos
1819
import javafx.scene.Cursor
1920
import javafx.scene.Node
20-
import javafx.scene.control.Menu
21-
import javafx.scene.control.MenuBar
22-
import javafx.scene.control.Tab
23-
import javafx.scene.control.TabPane
21+
import javafx.scene.control.*
2422
import javafx.scene.input.KeyCode
2523
import javafx.scene.layout.BorderPane
2624
import javafx.scene.layout.HBox
@@ -30,6 +28,7 @@ import javafx.scene.paint.Color
3028
import javafx.scene.shape.Polygon
3129
import javafx.scene.shape.Rectangle
3230
import javafx.stage.FileChooser
31+
import javafx.util.Duration
3332
import java.io.File
3433
import java.nio.file.Files
3534

@@ -42,6 +41,8 @@ class MainUI : BorderPane() {
4241
private val toolbar = HBox(35.0)
4342
private val tabPane = TabPane()
4443

44+
private val errorIcon = ErrorIcon()
45+
4546
private val preferences by lazy { PreferencesSubScene() }
4647

4748
private val currentTab: DialogueTab?
@@ -55,6 +56,22 @@ class MainUI : BorderPane() {
5556
toolbar.style = "-fx-background-color: black"
5657
toolbar.alignment = Pos.CENTER_LEFT
5758

59+
errorIcon.layoutXProperty().bind(FXGL.getSettings().actualWidthProperty().subtract(35))
60+
errorIcon.layoutY = 40.0
61+
62+
val tooltip = Tooltip()
63+
tooltip.showDelay = Duration.ZERO;
64+
tooltip.text = "There are incomplete dialogue paths."
65+
66+
Tooltip.install(errorIcon, tooltip)
67+
68+
tabPane.selectionModel.selectedItemProperty().addListener { _, _, newTab ->
69+
newTab?.let {
70+
errorIcon.visibleProperty().unbind()
71+
errorIcon.visibleProperty().bind((newTab as DialogueTab).pane.isConnectedProperty.not())
72+
}
73+
}
74+
5875
val contextMenuFile = FXGLContextMenu()
5976
contextMenuFile.addItem("New (CTRL+N)") { openNewDialog() }
6077
contextMenuFile.addItem("Open... (CTRL+O)") { openLoadDialog() }
@@ -77,7 +94,7 @@ class MainUI : BorderPane() {
7794
contextMenuHelp.addItem("Check for Updates...") { FXGL.getFXApp().hostServices.showDocument("https://fxgl.itch.io/fxgl-dialogue-editor") }
7895
contextMenuHelp.addItem("About") { openAboutDialog() }
7996

80-
val pane = Pane(tabPane, toolbar)
97+
val pane = Pane(tabPane, toolbar, errorIcon)
8198

8299
val menuFile = EditorMenu("File") {
83100
contextMenuFile.show(pane, 0.0, toolbar.prefHeight)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* FXGL - JavaFX Game Library. The MIT License (MIT).
3+
* Copyright (c) AlmasB (almaslvl@gmail.com).
4+
* See LICENSE for details.
5+
*/
6+
7+
package com.almasb.fxgl.tools.dialogues.ui
8+
9+
import javafx.scene.layout.StackPane
10+
import javafx.scene.paint.Color
11+
import javafx.scene.shape.Circle
12+
import javafx.scene.text.Font
13+
import javafx.scene.text.FontWeight
14+
import javafx.scene.text.Text
15+
16+
/**
17+
*
18+
* @author Almas Baimagambetov (almaslvl@gmail.com)
19+
*/
20+
class ErrorIcon : StackPane() {
21+
22+
init {
23+
val bgCircle = Circle(10.0, Color.RED).also {
24+
it.stroke = Color.WHITE
25+
}
26+
27+
val symbol = Text("!").also {
28+
it.font = Font.font("", FontWeight.BOLD, 14.0)
29+
it.fill = Color.WHITE
30+
}
31+
32+
children.addAll(bgCircle, symbol)
33+
}
34+
}

0 commit comments

Comments
 (0)