Add IO wrapper for InputManager
This commit is contained in:
parent
4ff54c1373
commit
dd01b070ff
@ -53,8 +53,10 @@ import wow.doge.mygame.game.entities.NpcActorSupervisor
|
||||
import wow.doge.mygame.game.entities.NpcMovementActor
|
||||
import wow.doge.mygame.game.entities.player.PlayerActor
|
||||
import wow.doge.mygame.game.entities.player.PlayerController
|
||||
import wow.doge.mygame.game.subsystems.input.GameInputHandler
|
||||
import wow.doge.mygame.game.entities.player.PlayerMovementReducer
|
||||
import wow.doge.mygame.game.subsystems.input.InputMappings
|
||||
import wow.doge.mygame.game.subsystems.input.PlayerCameraInput
|
||||
import wow.doge.mygame.game.subsystems.input.PlayerMovementInput
|
||||
import wow.doge.mygame.game.subsystems.level.DefaultGameLevel
|
||||
import wow.doge.mygame.implicits._
|
||||
import wow.doge.mygame.launcher.Launcher
|
||||
@ -80,6 +82,7 @@ import wow.doge.mygame.utils.IOUtils
|
||||
import wow.doge.mygame.utils.MonixDirectoryWatcher
|
||||
import wow.doge.mygame.utils.MonixDirectoryWatcher.ModifyEvent
|
||||
import wow.doge.mygame.utils.controls.JFXProgressBar
|
||||
import wow.doge.mygame.utils.wrappers.jme
|
||||
import wow.doge.mygame.utils.wrappers.jme.AssetManager
|
||||
import wow.doge.mygame.utils.wrappers.jme.PhysicsSpace
|
||||
|
||||
@ -118,7 +121,7 @@ class MainApp(
|
||||
.toIO(
|
||||
obs
|
||||
.doOnNextF(pme =>
|
||||
Coeval(pprint.log(show"Received event $pme")).void
|
||||
logger.trace(show"Received event $pme").toTask.void
|
||||
)
|
||||
.completedL
|
||||
.startAndForget
|
||||
@ -259,7 +262,8 @@ class MainAppDelegate(
|
||||
_ <- level.addToGame(rootNode, physicsSpace)
|
||||
playerActor <- createPlayerController()
|
||||
// .onErrorRestart(3)
|
||||
_ <- wire[GameInputHandler.Props].begin
|
||||
// _ <- wire[GameInputHandler.Props].begin
|
||||
_ <- new InputMappings(new jme.InputManager(inputManager)).setup
|
||||
// .onErrorRestart(3)
|
||||
johnActor <- createTestNpc("John")
|
||||
// _ <- johnActor !! NpcActorSupervisor.Move(ImVector3f(0, 0, 20))
|
||||
@ -394,7 +398,7 @@ class MainAppDelegate(
|
||||
new Label("Health") { textFill = Color.White },
|
||||
new Label("100") {
|
||||
text <-- statsObs
|
||||
.doOnNextF(i => loggerL.debug(show"Received stats: $i"))
|
||||
.doOnNextF(i => loggerL.trace(show"Received stats: $i"))
|
||||
.map(_.hp.toInt.toString)
|
||||
textFill = Color.White
|
||||
},
|
||||
@ -407,11 +411,7 @@ class MainAppDelegate(
|
||||
c += statsObs
|
||||
.scanEval(me.Task.pure("green-bar")) {
|
||||
case (a, b) =>
|
||||
me.Task {
|
||||
pprint.log(show"Received $a $b")
|
||||
pprint.log(show"${styleClass.toString}")
|
||||
styleClass.removeAll(a)
|
||||
} >>
|
||||
me.Task(styleClass.removeAll(a)) >>
|
||||
me.Task.pure(
|
||||
(b.hp.toInt: @switch) match {
|
||||
case v if v > 80 => "green-bar"
|
||||
@ -435,7 +435,7 @@ class MainAppDelegate(
|
||||
new Label("100") {
|
||||
textFill = Color.White
|
||||
text <-- statsObs
|
||||
.doOnNextF(i => loggerL.debug(show"Received stats: $i"))
|
||||
.doOnNextF(i => loggerL.trace(show"Received stats: $i"))
|
||||
.map(_.stamina.toInt.toString)
|
||||
},
|
||||
new JFXProgressBar {
|
||||
@ -449,11 +449,7 @@ class MainAppDelegate(
|
||||
c += statsObs
|
||||
.scanEval(me.Task.pure("green-bar")) {
|
||||
case (a, b) =>
|
||||
me.Task {
|
||||
pprint.log(show"Received $a $b")
|
||||
pprint.log(show"${styleClass.toString}")
|
||||
styleClass.removeAll(a)
|
||||
} >>
|
||||
me.Task(styleClass.removeAll(a)) >>
|
||||
me.Task.pure(
|
||||
(b.stamina.toInt: @switch) match {
|
||||
case v if v > 80 => "green-bar"
|
||||
@ -546,9 +542,22 @@ class MainAppDelegate(
|
||||
.toIO
|
||||
.hideErrors
|
||||
.startAndForget
|
||||
|
||||
sched <- UIO.pure(schedulers.async)
|
||||
fxSched <- UIO.pure(schedulers.fx)
|
||||
playerActor <- wire[PlayerController.Props].create
|
||||
playerMovementReducer = new PlayerMovementReducer(playerActor, loggerL)
|
||||
_ <-
|
||||
inputManager
|
||||
.enumObservableAction(PlayerMovementInput)
|
||||
.sample(1.millis)
|
||||
.scanEval(me.Task.pure(PlayerMovementReducer.State.empty))(
|
||||
playerMovementReducer.value
|
||||
)
|
||||
.completedL
|
||||
.toIO
|
||||
.hideErrors
|
||||
.startAndForget
|
||||
} yield playerActor
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
||||
import wow.doge.mygame.subsystems.events.PlayerEvent
|
||||
import wow.doge.mygame.subsystems.events.PlayerMovementEvent
|
||||
import wow.doge.mygame.utils.IOUtils._
|
||||
import wow.doge.mygame.utils.methodName
|
||||
|
||||
object GameInputHandler {
|
||||
|
||||
@ -29,16 +30,16 @@ object GameInputHandler {
|
||||
) {
|
||||
def begin =
|
||||
for {
|
||||
_ <- UIO(setupMovementKeys(inputManager))
|
||||
_ <- UIO(setupMovementKeys)
|
||||
// _ <- UIO(setupAnalogMovementKeys)
|
||||
_ <- UIO(setupCameraKeys())
|
||||
_ <- toIO(
|
||||
me.Task.parSequence(
|
||||
Seq(
|
||||
playerMovementInputEventsGenerator(
|
||||
inputManager,
|
||||
playerEventBus
|
||||
).completedL,
|
||||
// playerMovementInputEventsGenerator(
|
||||
// inputManager,
|
||||
// playerEventBus
|
||||
// ).completedL,
|
||||
// generateAnalogMovementEvents(
|
||||
// inputManager,
|
||||
// playerEventBus
|
||||
@ -55,7 +56,7 @@ object GameInputHandler {
|
||||
).startAndForget
|
||||
} yield ()
|
||||
|
||||
def setupMovementKeys(inputManager: InputManager) =
|
||||
def setupMovementKeys =
|
||||
inputManager.withEnumMappings(PlayerMovementInput) {
|
||||
case PlayerMovementInput.WalkRight =>
|
||||
new KeyTrigger(KeyInput.KEY_D) :: Nil
|
||||
@ -128,9 +129,6 @@ object GameInputHandler {
|
||||
|
||||
}
|
||||
|
||||
def methodName(implicit enclosing: sourcecode.Enclosing) =
|
||||
enclosing.value.split(" ")(0).split("""\.""").last
|
||||
|
||||
def playerMovementInputEventsGenerator(
|
||||
inputManager: InputManager,
|
||||
playerEventBus: GameEventBus[PlayerEvent]
|
||||
|
@ -0,0 +1,87 @@
|
||||
package wow.doge.mygame.game.subsystems.input
|
||||
|
||||
import com.jme3.input.KeyInput
|
||||
import com.jme3.input.MouseInput
|
||||
import com.jme3.input.controls.KeyTrigger
|
||||
import com.jme3.input.controls.MouseAxisTrigger
|
||||
import monix.{eval => me}
|
||||
import wow.doge.mygame.implicits._
|
||||
import wow.doge.mygame.utils.wrappers.jme.InputManager
|
||||
|
||||
class InputMappings(inputManager: InputManager) {
|
||||
|
||||
def setup =
|
||||
for {
|
||||
_ <- setupMovementKeys
|
||||
_ <- setupAnalogMovementKeys
|
||||
_ <- setupCameraKeys
|
||||
_ <- cursorToggle
|
||||
} yield ()
|
||||
|
||||
def setupMovementKeys =
|
||||
inputManager.withEnumMappings(PlayerMovementInput) {
|
||||
case PlayerMovementInput.WalkRight =>
|
||||
new KeyTrigger(KeyInput.KEY_D) :: Nil
|
||||
case PlayerMovementInput.WalkLeft =>
|
||||
new KeyTrigger(KeyInput.KEY_A) :: Nil
|
||||
case PlayerMovementInput.WalkForward =>
|
||||
new KeyTrigger(KeyInput.KEY_W) :: Nil
|
||||
case PlayerMovementInput.WalkBackward =>
|
||||
new KeyTrigger(KeyInput.KEY_S) :: Nil
|
||||
case PlayerMovementInput.Jump =>
|
||||
new KeyTrigger(KeyInput.KEY_SPACE) :: Nil
|
||||
}
|
||||
|
||||
def setupAnalogMovementKeys =
|
||||
inputManager.withEnumMappings(PlayerAnalogMovementInput) {
|
||||
case PlayerAnalogMovementInput.TurnRight =>
|
||||
Seq(new KeyTrigger(KeyInput.KEY_D))
|
||||
case PlayerAnalogMovementInput.TurnLeft =>
|
||||
Seq(new KeyTrigger(KeyInput.KEY_A))
|
||||
}
|
||||
|
||||
def setupCameraKeys =
|
||||
inputManager.withEnumMappings(PlayerCameraInput) {
|
||||
case PlayerCameraInput.CameraRotateLeft =>
|
||||
Seq(
|
||||
new KeyTrigger(KeyInput.KEY_LEFT),
|
||||
new MouseAxisTrigger(MouseInput.AXIS_X, false)
|
||||
)
|
||||
case PlayerCameraInput.CameraRotateRight =>
|
||||
Seq(
|
||||
new KeyTrigger(KeyInput.KEY_RIGHT),
|
||||
new MouseAxisTrigger(MouseInput.AXIS_X, true)
|
||||
)
|
||||
case PlayerCameraInput.CameraRotateUp =>
|
||||
Seq(
|
||||
new KeyTrigger(KeyInput.KEY_UP),
|
||||
new MouseAxisTrigger(MouseInput.AXIS_Y, false)
|
||||
)
|
||||
case PlayerCameraInput.CameraRotateDown =>
|
||||
Seq(
|
||||
new KeyTrigger(KeyInput.KEY_DOWN),
|
||||
new MouseAxisTrigger(MouseInput.AXIS_Y, true)
|
||||
)
|
||||
}
|
||||
|
||||
def cursorToggle =
|
||||
inputManager.withMapping(
|
||||
MiscInput.ToggleCursor,
|
||||
new KeyTrigger(KeyInput.KEY_Z)
|
||||
) >>
|
||||
inputManager
|
||||
.enumEntryObservableAction(MiscInput.ToggleCursor)
|
||||
.doOnNext(action =>
|
||||
action.binding match {
|
||||
case MiscInput.ToggleCursor =>
|
||||
if (action.value)(inputManager.cursorVisible =
|
||||
!inputManager.cursorVisible).toTask
|
||||
else me.Task.unit
|
||||
}
|
||||
)
|
||||
.completedL
|
||||
.toIO
|
||||
.hideErrors
|
||||
.startAndForget
|
||||
|
||||
}
|
@ -40,19 +40,16 @@ object MonixDirectoryWatcher {
|
||||
logger = logger.underlying
|
||||
) {
|
||||
override def onCreate(file: File, count: Int) =
|
||||
// println(show"$file got created")
|
||||
if (sub.onNext(CreateEvent(file, count)) == Ack.Stop)
|
||||
c.cancel()
|
||||
override def onModify(file: File, count: Int) = {
|
||||
pprint.log(show"${file.toString} got modified $count times")
|
||||
|
||||
override def onModify(file: File, count: Int) =
|
||||
if (sub.onNext(ModifyEvent(file, count)) == Ack.Stop)
|
||||
c.cancel()
|
||||
}
|
||||
|
||||
override def onDelete(file: File, count: Int) =
|
||||
// println(show"$file got deleted")
|
||||
if (sub.onNext(DeleteEvent(file, count)) == Ack.Stop)
|
||||
c.cancel()
|
||||
|
||||
}
|
||||
watcher.start()(scheduler)
|
||||
c := Cancelable(() => watcher.stop())
|
||||
|
@ -1,7 +1,6 @@
|
||||
package wow.doge.mygame
|
||||
|
||||
// import wow.doge.mygame.utils.wrappers.Node
|
||||
|
||||
package object utils {
|
||||
// type AppNode = Node
|
||||
def methodName(implicit enclosing: sourcecode.Enclosing) =
|
||||
enclosing.value.split(" ")(0).split("""\.""").last
|
||||
}
|
||||
|
@ -0,0 +1,126 @@
|
||||
package wow.doge.mygame.utils.wrappers.jme
|
||||
import com.jme3.input.controls.InputListener
|
||||
import com.jme3.input.controls.Trigger
|
||||
import com.jme3.{input => jmei}
|
||||
import enumeratum._
|
||||
import monix.bio.UIO
|
||||
import monix.reactive.Observable
|
||||
import wow.doge.mygame.ActionEvent
|
||||
import wow.doge.mygame.AnalogEvent
|
||||
import wow.doge.mygame.EnumActionEvent
|
||||
import wow.doge.mygame.EnumAnalogEvent
|
||||
import wow.doge.mygame.implicits._
|
||||
|
||||
final class InputManager(val delegate: jmei.InputManager) {
|
||||
|
||||
/**
|
||||
* Create a new mapping to the given triggers.
|
||||
*
|
||||
* <p>
|
||||
* The given mapping will be assigned to the given triggers, when
|
||||
* any of the triggers given raise an event, the listeners
|
||||
* registered to the mappings will receive appropriate events.
|
||||
*
|
||||
* @param mappingName The mapping name to assign.
|
||||
* @param triggers The triggers to which the mapping is to be registered.
|
||||
*/
|
||||
def withMapping(mapping: String, triggers: Trigger*): UIO[Unit] =
|
||||
UIO(delegate.withMapping(mapping, triggers: _*)).void
|
||||
|
||||
def withMapping[T <: EnumEntry](
|
||||
mapping: T,
|
||||
triggers: Trigger*
|
||||
): UIO[Unit] = UIO(delegate.withMapping(mapping, triggers: _*)).void
|
||||
|
||||
def withListener(listener: InputListener, mappings: String*) =
|
||||
UIO(delegate.withListener(listener, mappings: _*))
|
||||
|
||||
/**
|
||||
* Creates new mappings from the values of the given Enum
|
||||
*
|
||||
* <p>
|
||||
* The given mapping will be assigned to the given triggers, when
|
||||
* any of the triggers given raise an event, the listeners
|
||||
* registered to the mappings will receive appropriate events.
|
||||
*
|
||||
* @param mappingName The mapping name to assign.
|
||||
* @param mappingFn Function from enum values to the sequence of trigers.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* {{{
|
||||
*
|
||||
* sealed trait PlayerAnalogMovementInput extends EnumEntry with UpperSnakecase
|
||||
* object PlayerAnalogMovementInput extends Enum[PlayerAnalogMovementInput] {
|
||||
* val values = findValues
|
||||
* case object TurnRight extends PlayerAnalogMovementInput
|
||||
* case object TurnLeft extends PlayerAnalogMovementInput
|
||||
* }
|
||||
*
|
||||
* {
|
||||
* inputManager.withEnumMappings(PlayerAnalogMovementInput) {
|
||||
* case PlayerAnalogMovementInput.TurnRight =>
|
||||
* Seq(new KeyTrigger(KeyInput.KEY_RIGHT))
|
||||
* case PlayerAnalogMovementInput.TurnLeft =>
|
||||
* Seq(new KeyTrigger(KeyInput.KEY_LEFT))
|
||||
* }
|
||||
* }
|
||||
* }}}
|
||||
*/
|
||||
def withEnumMappings[T <: EnumEntry](
|
||||
mappingEnum: Enum[T]
|
||||
)(mappingFn: T => Seq[Trigger]) =
|
||||
UIO(delegate.withEnumMappings(mappingEnum)(mappingFn))
|
||||
|
||||
/**
|
||||
* Create an observable which emits the given mappings as elements of an observable
|
||||
*
|
||||
* @param mappingNames
|
||||
* @return Observable of action events
|
||||
*
|
||||
* @see [[ActionEvent]]
|
||||
* @see [[enumObservableAction]]
|
||||
*/
|
||||
def observableAction(mappingNames: String*): Observable[ActionEvent] =
|
||||
delegate.observableAction(mappingNames: _*)
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Create an observable which emits the values of the given
|
||||
* enum as elements of an observable
|
||||
*
|
||||
* @param mappingNames
|
||||
* @return Observable of enum values
|
||||
*
|
||||
* @example {{{
|
||||
* inputManager
|
||||
* .enumObservableAction(PlayerMovementInput)
|
||||
* .doOnNext { action =>
|
||||
* action.binding match {
|
||||
* case PlayerMovementInput.WalkLeft => Task {/* your actions */}
|
||||
* }
|
||||
* }
|
||||
* }}}
|
||||
*
|
||||
* @see [[EnumActionEvent]]
|
||||
* @see [[enumAnalogObservable]]
|
||||
*/
|
||||
def enumObservableAction[T <: EnumEntry](
|
||||
mappingEnum: Enum[T]
|
||||
): Observable[EnumActionEvent[T]] =
|
||||
delegate.enumObservableAction(mappingEnum)
|
||||
|
||||
def enumEntryObservableAction[T <: EnumEntry](
|
||||
mappingEnumEntry: T
|
||||
) = delegate.enumEntryObservableAction(mappingEnumEntry)
|
||||
|
||||
def analogObservable(mappingNames: String*): Observable[AnalogEvent] =
|
||||
delegate.analogObservable(mappingNames: _*)
|
||||
|
||||
def enumAnalogObservable[T <: EnumEntry](
|
||||
mappingEnum: Enum[T]
|
||||
): Observable[EnumAnalogEvent[T]] = delegate.enumAnalogObservable(mappingEnum)
|
||||
|
||||
def cursorVisible_=(value: Boolean) = UIO(delegate.setCursorVisible(value))
|
||||
def cursorVisible = delegate.isCursorVisible
|
||||
}
|
Loading…
Reference in New Issue
Block a user