package wow.doge.mygame.game.subsystems.input import scala.concurrent.duration._ import akka.actor.typed.ActorRef import com.jme3.input.InputManager import com.jme3.input.KeyInput import com.jme3.input.MouseInput import com.jme3.input.controls.KeyTrigger import com.jme3.input.controls.MouseAxisTrigger import monix.bio.UIO import wow.doge.mygame.implicits._ import wow.doge.mygame.subsystems.events.EventBus import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus import wow.doge.mygame.subsystems.events.PlayerCameraEvent import wow.doge.mygame.subsystems.events.PlayerMovementEvent import wow.doge.mygame.utils.IOUtils._ object GameInputHandler { final case class Props( inputManager: InputManager, playerMovementEventBus: GameEventBus[PlayerMovementEvent], playerCameraEventBus: GameEventBus[PlayerCameraEvent] // tickEventBus: GameEventBus[TickEvent] ) { def begin = for { _ <- UIO(setupMovementKeys(inputManager)) _ <- UIO(setupKeys(inputManager)) _ <- toIO( generateMovementInputEvents( inputManager, playerMovementEventBus ).completedL.startAndForget ) _ <- toIO( generateRotateEvents( inputManager, playerMovementEventBus ).completedL.startAndForget ) _ <- toIO( generateCameraEvents( inputManager, playerCameraEventBus ).completedL.startAndForget ) } yield () } def setupMovementKeys(inputManager: InputManager) = inputManager.withEnumMappings(PlayerMovementInput) { case PlayerMovementInput.WalkRight => Seq(new KeyTrigger(KeyInput.KEY_D)) case PlayerMovementInput.WalkLeft => Seq(new KeyTrigger(KeyInput.KEY_A)) case PlayerMovementInput.WalkForward => Seq(new KeyTrigger(KeyInput.KEY_W)) case PlayerMovementInput.WalkBackward => Seq(new KeyTrigger(KeyInput.KEY_S)) case PlayerMovementInput.Jump => Seq(new KeyTrigger(KeyInput.KEY_SPACE)) } def setupKeys(inputManager: InputManager) = inputManager .withMapping( PlayerAnalogMovementInput.TurnRight.entryName, new KeyTrigger(KeyInput.KEY_RIGHT), new MouseAxisTrigger(MouseInput.AXIS_X, true) ) .withMapping( PlayerAnalogMovementInput.TurnLeft.entryName, new KeyTrigger(KeyInput.KEY_LEFT), new MouseAxisTrigger(MouseInput.AXIS_X, false) ) .withMapping( "CAMERA_UP", // new KeyTrigger(KeyInput.KEY_LEFT), new MouseAxisTrigger(MouseInput.AXIS_Y, false) ) .withMapping( "CAMERA_DOWN", // new KeyTrigger(KeyInput.KEY_LEFT), new MouseAxisTrigger(MouseInput.AXIS_Y, true) ) def generateMovementInputEvents( inputManager: InputManager, playerMovementEventBus: ActorRef[ EventBus.Command[PlayerMovementEvent] ] ) = { val name = "playerMovementInputEventsGenerator" inputManager .enumObservableAction(PlayerMovementInput) // .dump("O") .doOnNext { action => action.binding match { case PlayerMovementInput.WalkLeft => toTask( playerMovementEventBus !! EventBus.Publish( PlayerMovementEvent.PlayerMovedLeft(pressed = action.value), name ) ) case PlayerMovementInput.WalkRight => toTask( playerMovementEventBus !! EventBus.Publish( PlayerMovementEvent.PlayerMovedRight(pressed = action.value), name ) ) case PlayerMovementInput.WalkForward => toTask( playerMovementEventBus !! EventBus.Publish( PlayerMovementEvent.PlayerMovedForward(pressed = action.value), name ) ) case PlayerMovementInput.WalkBackward => toTask( playerMovementEventBus !! EventBus.Publish( PlayerMovementEvent.PlayerMovedBackward(pressed = action.value), name ) ) case PlayerMovementInput.Jump => if (action.value) { toTask( playerMovementEventBus !! EventBus.Publish( PlayerMovementEvent.PlayerJumped, name ) ) } else monix.eval.Task.unit } } } def generateRotateEvents( inputManager: InputManager, playerMovementEventBus: ActorRef[ EventBus.Command[PlayerMovementEvent] ] ) = { val name = "rotateMovementEventsGenerator" inputManager .enumAnalogObservable(PlayerAnalogMovementInput) .sample(1.millis) .doOnNext(analogEvent => analogEvent.binding match { case PlayerAnalogMovementInput.TurnRight => toTask( playerMovementEventBus !! EventBus.Publish( PlayerMovementEvent.PlayerRotatedRight, name ) ) case PlayerAnalogMovementInput.TurnLeft => toTask( playerMovementEventBus !! EventBus.Publish( PlayerMovementEvent.PlayerRotatedLeft, name ) ) } ) } def generateCameraEvents( inputManager: InputManager, playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]] ) = { val name = "cameraMovementEventsGenerator" inputManager .analogObservable("CAMERA_UP", "CAMERA_DOWN") .sample(1.millis) .doOnNext(analogEvent => analogEvent.binding.name match { case "CAMERA_UP" => toTask( playerCameraEventBus !! EventBus.Publish( PlayerCameraEvent.CameraMovedUp, name ) ) case "CAMERA_DOWN" => toTask( playerCameraEventBus !! EventBus.Publish( PlayerCameraEvent.CameraMovedDown, name ) ) case _ => monix.eval.Task.unit } ) } }