Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package intermediate;

import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import javafx.scene.input.MouseButton;

import static com.almasb.fxgl.dsl.FXGL.onBtnBuilder;

public class MouseInputFluentSample extends GameApplication {

@Override
protected void initSettings(GameSettings settings) { }

@Override
protected void initInput() {

onBtnBuilder(MouseButton.PRIMARY)
.onActionBegin(() -> System.out.println("Primary Begin"))
.onAction(() -> System.out.println("Primary Action"))
.onActionEnd(() -> System.out.println("Primary End"));

onBtnBuilder(MouseButton.SECONDARY)
.onActionBegin(() -> System.out.println("Secondary Begin"))
.onActionEnd(() -> System.out.println("Secondary End"));
}

public static void main(String[] args) {
launch(args);
}
}
46 changes: 46 additions & 0 deletions fxgl/src/main/kotlin/com/almasb/fxgl/dsl/ButtonInputBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.almasb.fxgl.dsl

import com.almasb.fxgl.core.util.EmptyRunnable
import com.almasb.fxgl.input.Input
import com.almasb.fxgl.input.InputModifier
import com.almasb.fxgl.input.UserAction
import javafx.scene.input.MouseButton

class ButtonInputBuilder {

companion object {
private var counter = 0
}

private var onActionBegin: Runnable = EmptyRunnable
private var onAction: Runnable = EmptyRunnable
private var onActionEnd: Runnable = EmptyRunnable

constructor(input: Input, button: MouseButton, modifier: InputModifier = InputModifier.NONE, name: String = "AUTO-${counter++}") {
input.addAction(object : UserAction(name) {
override fun onActionBegin() {
onActionBegin.run()
}

override fun onAction() {
onAction.run()
}

override fun onActionEnd() {
onActionEnd.run()
}
}, button, modifier)
}

fun onActionBegin(onActionBegin: Runnable) = this.also {
it.onActionBegin = onActionBegin
}

fun onAction(onAction: Runnable) = this.also {
it.onAction = onAction
}

fun onActionEnd(onActionEnd: Runnable) = this.also {
it.onActionEnd = onActionEnd
}
}
24 changes: 20 additions & 4 deletions fxgl/src/main/kotlin/com/almasb/fxgl/dsl/FXGL.kt
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,26 @@ class FXGL private constructor() { companion object {
* Note: for onAction() to work, [input.update()] needs to be called.
*/
@JvmStatic @JvmOverloads fun onKeyBuilder(
input: Input,
key: KeyCode,
modifier: InputModifier = InputModifier.NONE) = KeyInputBuilder(input, key, modifier)
input: Input,
key: KeyCode,
modifier: InputModifier = InputModifier.NONE) = KeyInputBuilder(input, key, modifier)

@JvmStatic fun onBtnBuilder(
btn: MouseButton,
name: String) = ButtonInputBuilder(getInput(), btn, InputModifier.NONE, name)

@JvmStatic @JvmOverloads fun onBtnBuilder(
btn: MouseButton,
modifier: InputModifier = InputModifier.NONE) = ButtonInputBuilder(getInput(), btn, modifier)

/**
* Button builder for custom input.
* Note: for onAction() to work, [input.update()] needs to be called.
*/
@JvmStatic @JvmOverloads fun onBtnBuilder(
input: Input,
btn: MouseButton,
modifier: InputModifier = InputModifier.NONE) = ButtonInputBuilder(input, btn, modifier)
}
}

Expand All @@ -873,4 +890,3 @@ class FXGL private constructor() { companion object {




141 changes: 141 additions & 0 deletions fxgl/src/test/kotlin/com/almasb/fxgl/dsl/ButtonInputBuilderTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package com.almasb.fxgl.dsl

import com.almasb.fxgl.input.Input
import javafx.scene.input.MouseButton
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

class ButtonInputBuilderTest {

private lateinit var input: Input
private val timePerFrame = 0.016

@BeforeEach
fun setUp() {
input = Input()
}

@Test
fun `onActionBegin is called when mouse button is pressed`() {
var count = 0
val expectedCount = 1

ButtonInputBuilder(input, MouseButton.PRIMARY)
.onActionBegin { count++ }

input.mockButtonPress(MouseButton.PRIMARY)
input.update(timePerFrame)

assertEquals(expectedCount, count)
}

@Test
fun `onAction is called while mouse button is held`() {
var count = 0
val expectedCount = 3

ButtonInputBuilder(input, MouseButton.PRIMARY)
.onAction { count++ }

input.mockButtonPress(MouseButton.PRIMARY)

input.update(timePerFrame)
input.update(timePerFrame)
input.update(timePerFrame)

assertEquals(expectedCount, count)
}

@Test
fun `onActionEnd is called when mouse button is released`() {
var count = 0
val expectedCount = 1

ButtonInputBuilder(input, MouseButton.PRIMARY)
.onActionEnd { count++ }

input.mockButtonPress(MouseButton.PRIMARY)
input.update(timePerFrame)

input.mockButtonRelease(MouseButton.PRIMARY)
input.update(timePerFrame)

assertEquals(expectedCount, count)
}

@Test
fun `all callbacks can be chained`() {
var beginCount = 0
var actionCount = 0
var endCount = 0

val expectedBeginCount = 1
val expectedActionCount = 2
val expectedEndCount = 1

ButtonInputBuilder(input, MouseButton.PRIMARY)
.onActionBegin { beginCount++ }
.onAction { actionCount++ }
.onActionEnd { endCount++ }

input.mockButtonPress(MouseButton.PRIMARY)

input.update(timePerFrame)
input.update(timePerFrame)

input.mockButtonRelease(MouseButton.PRIMARY)
input.update(timePerFrame)

assertEquals(expectedBeginCount, beginCount)
assertEquals(expectedActionCount, actionCount)
assertEquals(expectedEndCount, endCount)
}

@Test
fun `FXGL onBtnBuilder with custom input supports onActionBegin`() {
var count = 0
val expectedCount = 1

FXGL.onBtnBuilder(input, MouseButton.PRIMARY)
.onActionBegin { count++ }

input.mockButtonPress(MouseButton.PRIMARY)
input.update(timePerFrame)

assertEquals(expectedCount, count)
}

@Test
fun `FXGL onBtnBuilder with custom input supports onAction`() {
var count = 0
val expectedCount = 2

FXGL.onBtnBuilder(input, MouseButton.PRIMARY)
.onAction { count++ }

input.mockButtonPress(MouseButton.PRIMARY)

input.update(timePerFrame)
input.update(timePerFrame)

assertEquals(expectedCount, count)
}

@Test
fun `FXGL onBtnBuilder with custom input supports onActionEnd`() {
var count = 0
val expectedCount = 1

FXGL.onBtnBuilder(input, MouseButton.PRIMARY)
.onActionEnd { count++ }

input.mockButtonPress(MouseButton.PRIMARY)
input.update(timePerFrame)

input.mockButtonRelease(MouseButton.PRIMARY)
input.update(timePerFrame)

assertEquals(expectedCount, count)
}
}