Skip to content

Commit 5fb6e02

Browse files
committed
feat: added EntitySelectionRectangle, closes #720
1 parent 878533a commit 5fb6e02

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

fxgl/src/main/kotlin/com/almasb/fxgl/app/scene/GameScene.kt

+82
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@ import javafx.beans.property.SimpleIntegerProperty
2525
import javafx.beans.value.ChangeListener
2626
import javafx.collections.ObservableList
2727
import javafx.event.EventHandler
28+
import javafx.geometry.Point2D
29+
import javafx.geometry.Rectangle2D
2830
import javafx.scene.Group
2931
import javafx.scene.Node
3032
import javafx.scene.SceneAntialiasing
3133
import javafx.scene.SubScene
3234
import javafx.scene.input.MouseEvent
35+
import javafx.scene.paint.Color
3336
import javafx.scene.robot.Robot
37+
import javafx.scene.shape.Rectangle
3438
import javafx.scene.transform.Rotate
3539
import javafx.scene.transform.Scale
3640
import java.util.concurrent.Callable
@@ -84,6 +88,10 @@ internal constructor(width: Int, height: Int,
8488

8589
private val updatableViews = arrayListOf<View>()
8690

91+
val entitySelectionRectangle: EntitySelectionRectangle by lazy {
92+
EntitySelectionRectangle(this)
93+
}
94+
8795
/**
8896
* If set to true, Game Scene will require calling step()
8997
* to advance each frame.
@@ -363,6 +371,8 @@ internal constructor(width: Int, height: Int,
363371

364372
timer.clear()
365373

374+
entitySelectionRectangle.lastSelection.clear()
375+
366376
viewport.unbind()
367377
gameRoot.children.clear()
368378
uiRoot.children.clear()
@@ -461,4 +471,76 @@ class GameView(val node: Node, zIndex: Int) {
461471
set(value) {
462472
zProperty.value = value
463473
}
474+
}
475+
476+
class EntitySelectionRectangle(
477+
private val gameScene: GameScene
478+
) : Rectangle(), View {
479+
480+
private val world = gameScene.gameWorld
481+
private val input = gameScene.input
482+
483+
/**
484+
* This list is populated on [stopSelection].
485+
*/
486+
val lastSelection: MutableList<Entity> = arrayListOf()
487+
488+
private var selectionStart: Point2D = Point2D.ZERO
489+
490+
init {
491+
fill = Color.web("darkblue", 0.4)
492+
stroke = Color.LIGHTBLUE
493+
isVisible = false
494+
}
495+
496+
fun startSelection() {
497+
if (scene == null) {
498+
gameScene.addUINode(this)
499+
}
500+
501+
selectionStart = input.mousePositionUI
502+
translateX = selectionStart.x
503+
translateY = selectionStart.y
504+
width = 0.0
505+
height = 0.0
506+
507+
isVisible = true
508+
}
509+
510+
fun stopSelection() {
511+
isVisible = false
512+
513+
lastSelection.clear()
514+
515+
lastSelection.addAll(
516+
world.getEntitiesInRange(Rectangle2D(translateX, translateY, width, height))
517+
)
518+
}
519+
520+
override fun onUpdate(tpf: Double) {
521+
if (isVisible) {
522+
val dx = input.mouseXUI - selectionStart.x
523+
val dy = input.mouseYUI - selectionStart.y
524+
525+
if (dx > 0) {
526+
width = dx
527+
} else {
528+
translateX = input.mouseXUI
529+
width = -dx
530+
}
531+
532+
if (dy > 0) {
533+
height = dy
534+
} else {
535+
translateY = input.mouseYUI
536+
height = -dy
537+
}
538+
}
539+
}
540+
541+
override fun getNode(): Node {
542+
return this
543+
}
544+
545+
override fun dispose() { }
464546
}

0 commit comments

Comments
 (0)