forked from nova/jmonkey-test
added npc state machine
This commit is contained in:
parent
2d3fea4fd8
commit
73d657952f
@ -1,39 +0,0 @@
|
|||||||
|
|
||||||
package ammonite
|
|
||||||
package $file.src.main.resources
|
|
||||||
import _root_.ammonite.interp.api.InterpBridge.{
|
|
||||||
value => interp
|
|
||||||
}
|
|
||||||
import _root_.ammonite.interp.api.InterpBridge.value.{
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
import _root_.ammonite.interp.api.IvyConstructor.{
|
|
||||||
ArtifactIdExt,
|
|
||||||
GroupIdExt
|
|
||||||
}
|
|
||||||
import _root_.ammonite.runtime.tools.{
|
|
||||||
browse,
|
|
||||||
grep,
|
|
||||||
time,
|
|
||||||
tail
|
|
||||||
}
|
|
||||||
import _root_.ammonite.repl.tools.{
|
|
||||||
desugar,
|
|
||||||
source
|
|
||||||
}
|
|
||||||
import _root_.ammonite.main.Router.{
|
|
||||||
doc,
|
|
||||||
main
|
|
||||||
}
|
|
||||||
import _root_.ammonite.repl.tools.Util.{
|
|
||||||
pathScoptRead
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
object dep{
|
|
||||||
/*<script>*/class Test(x: Int)
|
|
||||||
/*</script>*/ /*<generated>*/
|
|
||||||
def $main() = { scala.Iterator[String]() }
|
|
||||||
override def toString = "dep"
|
|
||||||
/*</generated>*/
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
|
|
||||||
package ammonite
|
|
||||||
package $file.src.main.resources
|
|
||||||
import _root_.ammonite.interp.api.InterpBridge.{
|
|
||||||
value => interp
|
|
||||||
}
|
|
||||||
import _root_.ammonite.interp.api.InterpBridge.value.{
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
import _root_.ammonite.interp.api.IvyConstructor.{
|
|
||||||
ArtifactIdExt,
|
|
||||||
GroupIdExt
|
|
||||||
}
|
|
||||||
import _root_.ammonite.runtime.tools.{
|
|
||||||
browse,
|
|
||||||
grep,
|
|
||||||
time,
|
|
||||||
tail
|
|
||||||
}
|
|
||||||
import _root_.ammonite.repl.tools.{
|
|
||||||
desugar,
|
|
||||||
source
|
|
||||||
}
|
|
||||||
import _root_.ammonite.main.Router.{
|
|
||||||
doc,
|
|
||||||
main
|
|
||||||
}
|
|
||||||
import _root_.ammonite.repl.tools.Util.{
|
|
||||||
pathScoptRead
|
|
||||||
}
|
|
||||||
import ammonite.$file.src.main.resources.{
|
|
||||||
dep
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
object hello{
|
|
||||||
/*<script>*/import $file.$
|
|
||||||
import dep.Test
|
|
||||||
|
|
||||||
/*<amm>*/val res_2 = /*</amm>*/new Test(1)
|
|
||||||
/*</script>*/ /*<generated>*/
|
|
||||||
def $main() = { scala.Iterator[String]() }
|
|
||||||
override def toString = "hello"
|
|
||||||
/*</generated>*/
|
|
||||||
}
|
|
@ -1,134 +0,0 @@
|
|||||||
|
|
||||||
package ammonite
|
|
||||||
package $file.src.main.resources
|
|
||||||
import _root_.ammonite.interp.api.InterpBridge.{
|
|
||||||
value => interp
|
|
||||||
}
|
|
||||||
import _root_.ammonite.interp.api.InterpBridge.value.{
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
import _root_.ammonite.interp.api.IvyConstructor.{
|
|
||||||
ArtifactIdExt,
|
|
||||||
GroupIdExt
|
|
||||||
}
|
|
||||||
import _root_.ammonite.runtime.tools.{
|
|
||||||
browse,
|
|
||||||
grep,
|
|
||||||
time,
|
|
||||||
tail
|
|
||||||
}
|
|
||||||
import _root_.ammonite.repl.tools.{
|
|
||||||
desugar,
|
|
||||||
source
|
|
||||||
}
|
|
||||||
import _root_.ammonite.main.Router.{
|
|
||||||
doc,
|
|
||||||
main
|
|
||||||
}
|
|
||||||
import _root_.ammonite.repl.tools.Util.{
|
|
||||||
pathScoptRead
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
object hello2{
|
|
||||||
/*<script>*/import $repo.$
|
|
||||||
// import $repo.`https://bintray.com/jmonkeyengine/com.jme3`
|
|
||||||
// import $file.dep
|
|
||||||
import $ivy.$
|
|
||||||
// import $ivy.`wow.doge:game:1.0-SNAPSHOT`
|
|
||||||
import $ivy.$
|
|
||||||
// import wow.doge.game.types.GameScript
|
|
||||||
import com.jme3.scene.control.Control
|
|
||||||
|
|
||||||
// println("hello from script")
|
|
||||||
|
|
||||||
// class Scr extends GameScript {
|
|
||||||
// def start(): Unit = println("hello from start")
|
|
||||||
|
|
||||||
// def stop(): Unit = println("hello from stop")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // class SomeClass extends Control {}
|
|
||||||
|
|
||||||
// @main
|
|
||||||
// def main(): GameScript = new Scr()
|
|
||||||
import com.simsilica.es.base.DefaultEntityData
|
|
||||||
import com.simsilica.es.EntityData
|
|
||||||
import com.jme3.app.Application
|
|
||||||
import wow.doge.mygame.game.Implicits._
|
|
||||||
import wow.doge.mygame.components.TestComponent
|
|
||||||
import com.jme3.scene.shape.Box
|
|
||||||
import com.jme3.scene.Geometry
|
|
||||||
import com.jme3.material.Material
|
|
||||||
import com.jme3.math.ColorRGBA
|
|
||||||
import com.jme3.asset.AssetManager
|
|
||||||
import com.jme3.math.Vector3f
|
|
||||||
import wow.doge.mygame.state._
|
|
||||||
class TestAppState(
|
|
||||||
// private var _entity: Option[EntityData] = Some(new DefaultEntityData())
|
|
||||||
) extends MyBaseState {
|
|
||||||
protected lazy val b = new Box(1, 1, 1)
|
|
||||||
protected lazy val geom = new Geometry("Box", b)
|
|
||||||
protected lazy val mat = Material(
|
|
||||||
assetManager = assetManager,
|
|
||||||
path = "Common/MatDefs/Misc/Unshaded.j3md"
|
|
||||||
)
|
|
||||||
|
|
||||||
// def entity = _entity
|
|
||||||
// override def initialize(app: Application): Unit = {
|
|
||||||
// super.initialize(app)
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
override def init() = {
|
|
||||||
entityData
|
|
||||||
.createEntity()
|
|
||||||
.withComponents(TestComponent())
|
|
||||||
// entityData.setComponents(x, TestComponent())
|
|
||||||
val es = entityData.getEntities(classOf[TestComponent])
|
|
||||||
println(es)
|
|
||||||
geom.setMaterial(mat)
|
|
||||||
rootNode.attachChild(geom)
|
|
||||||
|
|
||||||
// geom.foreach(e => {
|
|
||||||
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
override def update(tpf: Float) = {
|
|
||||||
geom.rotate(0, 0.5f * tpf, 0)
|
|
||||||
geom.move(new Vector3f(0, 1 * tpf, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
override def cleanup(app: Application): Unit = {
|
|
||||||
// _entity.map(_.close())
|
|
||||||
// _entity = None
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onEnable(): Unit = {}
|
|
||||||
|
|
||||||
override def onDisable(): Unit = {}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
object Material {
|
|
||||||
def apply(
|
|
||||||
color: String = "Color",
|
|
||||||
colorType: com.jme3.math.ColorRGBA = ColorRGBA.Blue,
|
|
||||||
assetManager: AssetManager,
|
|
||||||
path: String
|
|
||||||
): Material = {
|
|
||||||
val mat =
|
|
||||||
new Material(assetManager, path)
|
|
||||||
mat.setColor(color, colorType)
|
|
||||||
mat
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@main
|
|
||||||
def main(): MyBaseState = new TestAppState()
|
|
||||||
/*</script>*/ /*<generated>*/
|
|
||||||
def $main() = { scala.Iterator[String]() }
|
|
||||||
override def toString = "hello2"
|
|
||||||
/*</generated>*/
|
|
||||||
}
|
|
@ -91,8 +91,8 @@ lazy val root = (project in file(".")).settings(
|
|||||||
"com.beachape" %% "enumeratum-circe" % "1.6.1",
|
"com.beachape" %% "enumeratum-circe" % "1.6.1",
|
||||||
"com.lihaoyi" %% "os-lib" % "0.7.1",
|
"com.lihaoyi" %% "os-lib" % "0.7.1",
|
||||||
// "com.jayfella" % "jme-jfx-11" % "1.1.5",
|
// "com.jayfella" % "jme-jfx-11" % "1.1.5",
|
||||||
"com.github.goxr3plus" % "FX-BorderlessScene" % "4.4.0",
|
// "com.github.goxr3plus" % "FX-BorderlessScene" % "4.4.0",
|
||||||
"com.github.Oshan96" % "CustomStage" % "v1.3.1",
|
// "com.github.Oshan96" % "CustomStage" % "v1.3.1",
|
||||||
"com.badlogicgames.gdx" % "gdx-ai" % "1.8.2",
|
"com.badlogicgames.gdx" % "gdx-ai" % "1.8.2",
|
||||||
"org.recast4j" % "recast" % "1.2.5",
|
"org.recast4j" % "recast" % "1.2.5",
|
||||||
"org.recast4j" % "detour" % "1.2.5"
|
"org.recast4j" % "detour" % "1.2.5"
|
||||||
|
@ -34,7 +34,7 @@ class StaticLoggerBinder extends OdinLoggerBinder[IO] {
|
|||||||
|
|
||||||
private lazy val (defaultConsoleLogger, release1) =
|
private lazy val (defaultConsoleLogger, release1) =
|
||||||
consoleLogger[IO](minLevel = Level.Debug)
|
consoleLogger[IO](minLevel = Level.Debug)
|
||||||
.withAsync(timeWindow = 1.milliseconds)
|
.withAsync(timeWindow = 1.milliseconds, maxBufferSize = Some(2000))
|
||||||
.allocated
|
.allocated
|
||||||
.unsafeRunSync()
|
.unsafeRunSync()
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class StaticLoggerBinder extends OdinLoggerBinder[IO] {
|
|||||||
"application-log-2.log",
|
"application-log-2.log",
|
||||||
Formatter.json,
|
Formatter.json,
|
||||||
minLevel = Level.Debug
|
minLevel = Level.Debug
|
||||||
).withAsync(timeWindow = 1.milliseconds)
|
).withAsync(timeWindow = 1.milliseconds, maxBufferSize = Some(2000))
|
||||||
.allocated
|
.allocated
|
||||||
.unsafeRunSync()
|
.unsafeRunSync()
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ class StaticLoggerBinder extends OdinLoggerBinder[IO] {
|
|||||||
"eventbus.log",
|
"eventbus.log",
|
||||||
Formatter.json,
|
Formatter.json,
|
||||||
minLevel = Level.Debug
|
minLevel = Level.Debug
|
||||||
).withAsync(timeWindow = 1.milliseconds)
|
).withAsync(timeWindow = 1.milliseconds, maxBufferSize = Some(2000))
|
||||||
.allocated
|
.allocated
|
||||||
.unsafeRunSync()
|
.unsafeRunSync()
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ class StaticLoggerBinder extends OdinLoggerBinder[IO] {
|
|||||||
// "wow.doge.mygame.subsystems.movement.PlayerMovementEventHandler"
|
// "wow.doge.mygame.subsystems.movement.PlayerMovementEventHandler"
|
||||||
// ) =>
|
// ) =>
|
||||||
// defaultConsoleLogger.withMinimalLevel( Level.Trace) //selectively turn on trace logging for specific classes
|
// defaultConsoleLogger.withMinimalLevel( Level.Trace) //selectively turn on trace logging for specific classes
|
||||||
case s if s.startsWith("wow.doge.mygame.events.EventBus") =>
|
case s if s.startsWith("wow.doge.mygame.subsystems.events.EventBus") =>
|
||||||
defaultConsoleLogger.withMinimalLevel(Level.Debug) |+| eventBusFileLogger
|
defaultConsoleLogger.withMinimalLevel(Level.Debug) |+| eventBusFileLogger
|
||||||
case s if s.startsWith("akka.actor") || s.startsWith("wow.doge.mygame") =>
|
case s if s.startsWith("akka.actor") || s.startsWith("wow.doge.mygame") =>
|
||||||
defaultConsoleLogger.withMinimalLevel(Level.Debug) |+| mainFileLogger
|
defaultConsoleLogger.withMinimalLevel(Level.Debug) |+| mainFileLogger
|
||||||
|
@ -2,19 +2,19 @@ package wow.doge.mygame
|
|||||||
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
|
import _root_.monix.bio.BIOApp
|
||||||
|
import _root_.monix.bio.Task
|
||||||
|
import _root_.monix.bio.UIO
|
||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
import cats.effect.ExitCode
|
import cats.effect.ExitCode
|
||||||
|
import cats.effect.Resource
|
||||||
import cats.implicits._
|
import cats.implicits._
|
||||||
import com.softwaremill.macwire._
|
import com.softwaremill.macwire._
|
||||||
import io.odin._
|
import io.odin._
|
||||||
import io.odin.json.Formatter
|
import io.odin.json.Formatter
|
||||||
import io.odin.syntax._
|
import io.odin.syntax._
|
||||||
import wow.doge.mygame.game.GameAppResource
|
|
||||||
import _root_.monix.bio.BIOApp
|
|
||||||
import _root_.monix.bio.Task
|
|
||||||
import _root_.monix.bio.UIO
|
|
||||||
import cats.effect.Resource
|
|
||||||
import scalafx.scene.control.TextArea
|
import scalafx.scene.control.TextArea
|
||||||
|
import wow.doge.mygame.game.GameAppResource
|
||||||
import wow.doge.mygame.utils.GenericConsoleStream
|
import wow.doge.mygame.utils.GenericConsoleStream
|
||||||
|
|
||||||
object Main extends BIOApp with MainModule {
|
object Main extends BIOApp with MainModule {
|
||||||
@ -25,15 +25,16 @@ object Main extends BIOApp with MainModule {
|
|||||||
def appResource(consoleStream: GenericConsoleStream[TextArea]) =
|
def appResource(consoleStream: GenericConsoleStream[TextArea]) =
|
||||||
for {
|
for {
|
||||||
logger <-
|
logger <-
|
||||||
consoleLogger().withAsync(timeWindow = 1.milliseconds) |+|
|
consoleLogger().withAsync(
|
||||||
|
timeWindow = 1.milliseconds,
|
||||||
|
maxBufferSize = Some(2000)
|
||||||
|
) |+|
|
||||||
fileLogger(
|
fileLogger(
|
||||||
"application-log-1.log",
|
"application-log-1.log",
|
||||||
Formatter.json
|
Formatter.json
|
||||||
).withAsync(timeWindow = 1.milliseconds)
|
).withAsync(timeWindow = 1.milliseconds, maxBufferSize = Some(2000))
|
||||||
jmeScheduler <- jMESchedulerResource
|
jmeScheduler <- jMESchedulerResource
|
||||||
actorSystem <- actorSystemResource2(logger)
|
actorSystem <- actorSystemResource(logger)
|
||||||
// consoleTextArea <- Resource.liftF(Task(new TextArea()))
|
|
||||||
// consoleStream <- wireWith(JFXConsoleStream.textAreaStream _)
|
|
||||||
gameApp <- {
|
gameApp <- {
|
||||||
// new BulletAppState()
|
// new BulletAppState()
|
||||||
// bas.setThreadingType(Thr)
|
// bas.setThreadingType(Thr)
|
||||||
@ -61,7 +62,7 @@ object Main extends BIOApp with MainModule {
|
|||||||
lazy val consoleStream = GenericConsoleStream.textAreaStream()
|
lazy val consoleStream = GenericConsoleStream.textAreaStream()
|
||||||
Console.withOut(consoleStream)(
|
Console.withOut(consoleStream)(
|
||||||
appResource(consoleStream)
|
appResource(consoleStream)
|
||||||
.use(_ => Task.unit)
|
.use(_ => Task.unit >> Task(consoleStream.close()))
|
||||||
.onErrorHandle(_.printStackTrace())
|
.onErrorHandle(_.printStackTrace())
|
||||||
.as(ExitCode.Success)
|
.as(ExitCode.Success)
|
||||||
)
|
)
|
||||||
|
@ -5,56 +5,54 @@ import akka.actor.typed.ActorSystem
|
|||||||
import akka.actor.typed.Scheduler
|
import akka.actor.typed.Scheduler
|
||||||
import akka.actor.typed.SpawnProtocol
|
import akka.actor.typed.SpawnProtocol
|
||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
import cats.effect.concurrent.Ref
|
import cats.effect.concurrent.Deferred
|
||||||
import com.jme3.app.state.AppStateManager
|
import com.jme3.app.state.AppStateManager
|
||||||
import com.jme3.asset.AssetManager
|
import com.jme3.asset.AssetManager
|
||||||
import com.jme3.asset.plugins.ZipLocator
|
import com.jme3.asset.plugins.ZipLocator
|
||||||
import com.jme3.bullet.BulletAppState
|
import com.jme3.bullet.BulletAppState
|
||||||
import com.jme3.input.InputManager
|
import com.jme3.input.InputManager
|
||||||
import com.jme3.renderer.Camera
|
import com.jme3.renderer.Camera
|
||||||
|
import com.jme3.renderer.ViewPort
|
||||||
import com.jme3.scene.Node
|
import com.jme3.scene.Node
|
||||||
import com.softwaremill.macwire._
|
import com.softwaremill.macwire._
|
||||||
import com.softwaremill.tagging._
|
import com.softwaremill.tagging._
|
||||||
import io.odin.Logger
|
import io.odin.Logger
|
||||||
|
import monix.bio.Fiber
|
||||||
import monix.bio.IO
|
import monix.bio.IO
|
||||||
import monix.bio.Task
|
import monix.bio.Task
|
||||||
import wow.doge.mygame.events.EventBus
|
|
||||||
import wow.doge.mygame.game.GameApp2
|
|
||||||
import wow.doge.mygame.game.nodes.PlayerTag
|
|
||||||
import wow.doge.mygame.game.nodes.PlayerController
|
|
||||||
import wow.doge.mygame.game.subsystems.input.GameInputHandler
|
|
||||||
import wow.doge.mygame.implicits._
|
|
||||||
import wow.doge.mygame.math.ImVector3f
|
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent
|
|
||||||
import wow.doge.mygame.subsystems.events.EventsModule2
|
|
||||||
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
|
||||||
import wow.doge.mygame.game.subsystems.level.DefaultGameLevel
|
|
||||||
import com.jme3.renderer.ViewPort
|
|
||||||
import wow.doge.mygame.subsystems.scriptsystem.ScriptSystemResource
|
|
||||||
import wow.doge.mygame.subsystems.scriptsystem.ScriptInitMode
|
|
||||||
import wow.doge.mygame.launcher.Launcher
|
|
||||||
import wow.doge.mygame.executors.Schedulers
|
|
||||||
import scalafx.application.JFXApp.PrimaryStage
|
|
||||||
import scalafx.geometry.Insets
|
|
||||||
import scalafx.scene.Scene
|
|
||||||
import scalafx.scene.control.Button
|
|
||||||
import scalafx.scene.layout.StackPane
|
|
||||||
import scalafx.scene.paint.Color
|
|
||||||
import scalafx.scene.shape.Rectangle
|
|
||||||
import scalafx.Includes._
|
|
||||||
import scala.concurrent.duration._
|
|
||||||
import cats.effect.concurrent.Deferred
|
|
||||||
import monix.bio.Fiber
|
|
||||||
import wow.doge.mygame.launcher.Launcher.LauncherResult
|
|
||||||
import scalafx.scene.control.TextArea
|
import scalafx.scene.control.TextArea
|
||||||
import com.jayfella.jme.jfx.JavaFxUI
|
import wow.doge.mygame.executors.Schedulers
|
||||||
|
import wow.doge.mygame.game.GameApp
|
||||||
|
import wow.doge.mygame.game.GameAppActor
|
||||||
|
import wow.doge.mygame.game.GameAppTags
|
||||||
|
import wow.doge.mygame.game.entities.PlayerController
|
||||||
|
import wow.doge.mygame.game.entities.PlayerControllerTags
|
||||||
|
import wow.doge.mygame.game.subsystems.input.GameInputHandler
|
||||||
|
import wow.doge.mygame.game.subsystems.level.DefaultGameLevel
|
||||||
|
import wow.doge.mygame.implicits._
|
||||||
|
import wow.doge.mygame.launcher.Launcher
|
||||||
|
import wow.doge.mygame.launcher.Launcher.LauncherResult
|
||||||
|
import wow.doge.mygame.math.ImVector3f
|
||||||
|
import wow.doge.mygame.subsystems.events.EventBus
|
||||||
|
import wow.doge.mygame.subsystems.events.EventsModule
|
||||||
|
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
||||||
|
import wow.doge.mygame.subsystems.events.PlayerMovementEvent
|
||||||
|
import wow.doge.mygame.subsystems.events.TickEvent
|
||||||
|
import wow.doge.mygame.subsystems.scriptsystem.ScriptInitMode
|
||||||
|
import wow.doge.mygame.subsystems.scriptsystem.ScriptSystemResource
|
||||||
|
import wow.doge.mygame.utils.AkkaUtils
|
||||||
import wow.doge.mygame.utils.GenericConsoleStream
|
import wow.doge.mygame.utils.GenericConsoleStream
|
||||||
import java.io.PrintStream
|
|
||||||
|
import EventsModule.GameEventBus
|
||||||
|
import wow.doge.mygame.game.entities.NpcMovementActor2
|
||||||
|
import wow.doge.mygame.game.entities.NpcActorSupervisor
|
||||||
|
import monix.execution.exceptions.DummyException
|
||||||
|
import com.jme3.bullet.control.BetterCharacterControl
|
||||||
|
|
||||||
class MainApp(
|
class MainApp(
|
||||||
logger: Logger[Task],
|
logger: Logger[Task],
|
||||||
gameApp: GameApp2,
|
gameApp: GameApp,
|
||||||
spawnProtocol: ActorSystem[SpawnProtocol.Command],
|
implicit val spawnProtocol: ActorSystem[SpawnProtocol.Command],
|
||||||
jmeThread: monix.execution.Scheduler,
|
jmeThread: monix.execution.Scheduler,
|
||||||
schedulers: Schedulers,
|
schedulers: Schedulers,
|
||||||
consoleStream: GenericConsoleStream[TextArea]
|
consoleStream: GenericConsoleStream[TextArea]
|
||||||
@ -68,19 +66,29 @@ class MainApp(
|
|||||||
|
|
||||||
def gameInit: Task[Fiber[Throwable, Unit]] =
|
def gameInit: Task[Fiber[Throwable, Unit]] =
|
||||||
for {
|
for {
|
||||||
eventsModule <- Task(new EventsModule2(spawnProtocol))
|
eventsModule <- Task(new EventsModule(spawnProtocol))
|
||||||
playerMovementEventBus <- eventsModule.playerMovementEventBusTask
|
playerMovementEventBus <- eventsModule.playerMovementEventBusTask
|
||||||
playerCameraEventBus <- eventsModule.playerCameraEventBusTask
|
playerCameraEventBus <- eventsModule.playerCameraEventBusTask
|
||||||
|
mainEventBus <- eventsModule.mainEventBusTask
|
||||||
|
tickEventBus <- eventsModule.tickEventBusTask
|
||||||
|
gameAppActor <- AkkaUtils.spawnActorL2(
|
||||||
|
GameAppActor.Props(tickEventBus).create,
|
||||||
|
"gameAppActor"
|
||||||
|
)
|
||||||
|
_ <- gameAppActor !! GameAppActor.Start
|
||||||
gameAppFib <- gameApp.start.executeOn(jmeThread).start
|
gameAppFib <- gameApp.start.executeOn(jmeThread).start
|
||||||
/**
|
/**
|
||||||
* schedule a task to run on the JME thread and wait for it's completion
|
* schedule a task to run on the JME thread and wait for it's completion
|
||||||
* before proceeding forward, as a signal that JME thread has been
|
* before proceeding forward, as a signal that the JME thread has been
|
||||||
* initialized, otherwise we'll get NPEs trying to access the fields
|
* initialized, otherwise we'll get NPEs trying to access the fields
|
||||||
* of the game app
|
* of the game app
|
||||||
*/
|
*/
|
||||||
res <- gameApp.enqueueL(() => Task("done")).flatten
|
res <- gameApp.enqueueL(() => "done")
|
||||||
|
|
||||||
_ <- logger.info(s"Result = $res")
|
_ <- logger.info(s"Result = $res")
|
||||||
|
/**
|
||||||
|
* JME Thread has been initialized at this point. We can now access the
|
||||||
|
* field of the game application
|
||||||
|
*/
|
||||||
inputManager <- gameApp.inputManager
|
inputManager <- gameApp.inputManager
|
||||||
assetManager <- gameApp.assetManager
|
assetManager <- gameApp.assetManager
|
||||||
stateManager <- gameApp.stateManager
|
stateManager <- gameApp.stateManager
|
||||||
@ -89,41 +97,20 @@ class MainApp(
|
|||||||
enqueueR <- Task(gameApp.enqueue _)
|
enqueueR <- Task(gameApp.enqueue _)
|
||||||
viewPort <- gameApp.viewPort
|
viewPort <- gameApp.viewPort
|
||||||
_ <- logger.info("before")
|
_ <- logger.info("before")
|
||||||
// jfxUI <- Task(JavaFxUI.initialize(gameApp.app))
|
// jfxUI <- gameApp.jfxUI
|
||||||
// .executeOn(gameApp.scheduler) >> Task.sleep(500.millis) >> Task(
|
|
||||||
// JavaFxUI.getInstance()
|
|
||||||
// )
|
|
||||||
// .start
|
|
||||||
jfxUI <- gameApp.jfxUI
|
|
||||||
consoleTextArea <- Task(new TextArea {
|
consoleTextArea <- Task(new TextArea {
|
||||||
text = "hello"
|
text = "hello \n"
|
||||||
editable = false
|
editable = false
|
||||||
wrapText = true
|
wrapText = true
|
||||||
// maxHeight = 150
|
// maxHeight = 150
|
||||||
// maxWidth = 300
|
// maxWidth = 300
|
||||||
})
|
})
|
||||||
_ <- Task(consoleStream := consoleTextArea)
|
// _ <- Task(consoleStream := consoleTextArea)
|
||||||
_ <- Task(jfxUI += consoleTextArea)
|
// _ <- Task(jfxUI += consoleTextArea)
|
||||||
// consoleStream <- Task(
|
|
||||||
// GenericConsoleStream.textAreaStream(consoleTextArea)
|
|
||||||
// )
|
|
||||||
_ <- logger.info("after")
|
_ <- logger.info("after")
|
||||||
bulletAppState <- Task(new BulletAppState())
|
bulletAppState <- Task(new BulletAppState())
|
||||||
_ <- Task(stateManager.attach(bulletAppState))
|
_ <- Task(stateManager.attach(bulletAppState))
|
||||||
_ <- logger.info("Initializing console stream")
|
_ <- logger.info("Initializing console stream")
|
||||||
// _ <- Task(GenericConsoleStream.textAreaStream(consoleTextArea)).bracket(
|
|
||||||
// consoleStream =>
|
|
||||||
// Task { System.setOut(consoleStream) } >> wire[MainAppDelegate]
|
|
||||||
// .init(gameApp.scheduler, consoleStream)
|
|
||||||
// // consoleLogger
|
|
||||||
// // Console.withOut(consoleStream)(
|
|
||||||
// // wire[MainAppDelegate].init(gameApp.scheduler, consoleStream)
|
|
||||||
// // )
|
|
||||||
// )(stream => Task(stream.close()).onErrorHandle(_.printStackTrace()))
|
|
||||||
// _ <- Task { System.setOut(new PrintStream(consoleStream, true)) }
|
|
||||||
// _ <- Task {
|
|
||||||
// Console.withOut(consoleStream)(println("hello"))
|
|
||||||
// }
|
|
||||||
_ <- wire[MainAppDelegate].init(gameApp.scheduler)
|
_ <- wire[MainAppDelegate].init(gameApp.scheduler)
|
||||||
} yield (gameAppFib)
|
} yield (gameAppFib)
|
||||||
|
|
||||||
@ -131,7 +118,7 @@ class MainApp(
|
|||||||
scriptSystem <- scriptSystemInit
|
scriptSystem <- scriptSystemInit
|
||||||
/**
|
/**
|
||||||
* Signal for synchronization between the JavaFX launcher and the in-game JavaFX GUI
|
* Signal for synchronization between the JavaFX launcher and the in-game JavaFX GUI
|
||||||
* Without this, we get a "Toolkit already initialized" excResult. The launch button
|
* Without this, we get a "Toolkit already initialized" exception. The launch button
|
||||||
* in the launcher completes the signal. The game init process which listens for this
|
* in the launcher completes the signal. The game init process which listens for this
|
||||||
* signal can then continue
|
* signal can then continue
|
||||||
*/
|
*/
|
||||||
@ -141,15 +128,16 @@ class MainApp(
|
|||||||
launchResult <- launchSignal.get
|
launchResult <- launchSignal.get
|
||||||
_ <- cancelToken.cancel
|
_ <- cancelToken.cancel
|
||||||
_ <-
|
_ <-
|
||||||
|
/**
|
||||||
|
* User chose to quit
|
||||||
|
*/
|
||||||
if (launchResult == LauncherResult.Exit)
|
if (launchResult == LauncherResult.Exit)
|
||||||
logger.info("Exiting")
|
logger.info("Exiting")
|
||||||
else gameInit.flatMap(_.join)
|
|
||||||
// _ <- Task.sleep(2000.millis)
|
|
||||||
// gameAppFib <- gameInit
|
|
||||||
/**
|
/**
|
||||||
* Wait for game window to close
|
* User chose launch. Wait for game window to close
|
||||||
*/
|
*/
|
||||||
// _ <- gameAppFib.join
|
else
|
||||||
|
gameInit.flatMap(_.join)
|
||||||
} yield ()
|
} yield ()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,27 +145,27 @@ class MainApp(
|
|||||||
* Class with all dependencies in one place for easy wiring
|
* Class with all dependencies in one place for easy wiring
|
||||||
*/
|
*/
|
||||||
class MainAppDelegate(
|
class MainAppDelegate(
|
||||||
gameApp: GameApp2,
|
gameApp: GameApp,
|
||||||
spawnProtocol: ActorSystem[SpawnProtocol.Command],
|
implicit val spawnProtocol: ActorSystem[SpawnProtocol.Command],
|
||||||
loggerL: Logger[Task],
|
loggerL: Logger[Task],
|
||||||
// eventBuses: EventsModule2
|
|
||||||
playerMovementEventBus: ActorRef[
|
playerMovementEventBus: ActorRef[
|
||||||
EventBus.Command[EntityMovementEvent.PlayerMovementEvent]
|
EventBus.Command[PlayerMovementEvent]
|
||||||
],
|
],
|
||||||
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
|
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
|
||||||
|
tickEventBus: GameEventBus[TickEvent],
|
||||||
inputManager: InputManager,
|
inputManager: InputManager,
|
||||||
assetManager: AssetManager,
|
assetManager: AssetManager,
|
||||||
stateManager: AppStateManager,
|
stateManager: AppStateManager,
|
||||||
camera: Camera,
|
camera: Camera,
|
||||||
viewPort: ViewPort,
|
viewPort: ViewPort,
|
||||||
enqueueR: Function1[() => Unit, Unit],
|
enqueueR: Function1[() => Unit, Unit],
|
||||||
rootNode: Ref[Task, Node],
|
rootNode: Node @@ GameAppTags.RootNode,
|
||||||
bulletAppState: BulletAppState
|
bulletAppState: BulletAppState
|
||||||
)(implicit
|
)(implicit
|
||||||
@annotation.unused timeout: Timeout,
|
@annotation.unused timeout: Timeout,
|
||||||
@annotation.unused scheduler: Scheduler
|
@annotation.unused scheduler: Scheduler
|
||||||
) {
|
) {
|
||||||
|
lazy val physicsSpace = bulletAppState.physicsSpace
|
||||||
def init(
|
def init(
|
||||||
appScheduler: monix.execution.Scheduler
|
appScheduler: monix.execution.Scheduler
|
||||||
// consoleStream: GenericConsoleStream[TextArea]
|
// consoleStream: GenericConsoleStream[TextArea]
|
||||||
@ -186,11 +174,11 @@ class MainAppDelegate(
|
|||||||
_ <- loggerL.info("Initializing Systems")
|
_ <- loggerL.info("Initializing Systems")
|
||||||
_ <- Task(
|
_ <- Task(
|
||||||
assetManager.registerLocator(
|
assetManager.registerLocator(
|
||||||
(os.rel / "assets" / "town.zip"),
|
os.rel / "assets" / "town.zip",
|
||||||
classOf[ZipLocator]
|
classOf[ZipLocator]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
_ <- loggerL.info("test hmm")
|
_ <- loggerL.info("test")
|
||||||
// _ <- Task(consoleStream.println("text"))
|
// _ <- Task(consoleStream.println("text"))
|
||||||
_ <- DefaultGameLevel(assetManager, viewPort)
|
_ <- DefaultGameLevel(assetManager, viewPort)
|
||||||
.addToGame(
|
.addToGame(
|
||||||
@ -198,23 +186,91 @@ class MainAppDelegate(
|
|||||||
bulletAppState.physicsSpace
|
bulletAppState.physicsSpace
|
||||||
)
|
)
|
||||||
.executeOn(appScheduler)
|
.executeOn(appScheduler)
|
||||||
_ <- createPlayerController(appScheduler).startAndForget.onErrorRestart(3)
|
_ <- createPlayerController(appScheduler)
|
||||||
|
.absorbWith(e => DummyException("boom"))
|
||||||
|
.onErrorRestart(3)
|
||||||
|
johnActor <- createNpc(appScheduler, "John").executeOn(appScheduler)
|
||||||
|
_ <- johnActor !! NpcActorSupervisor.Move(ImVector3f(0, 0, 20))
|
||||||
_ <- wire[GameInputHandler.Props].begin.onErrorRestart(3)
|
_ <- wire[GameInputHandler.Props].begin.onErrorRestart(3)
|
||||||
} yield ()
|
} yield ()
|
||||||
|
|
||||||
def createPlayerController(
|
def createPlayerController(
|
||||||
appScheduler: monix.execution.Scheduler
|
appScheduler: monix.execution.Scheduler
|
||||||
// playerMovementEventBus: ActorRef[
|
|
||||||
// EventBus.Command[PlayerMovementEvent]
|
|
||||||
// ],
|
|
||||||
// playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
|
|
||||||
): IO[PlayerController.Error, Unit] = {
|
): IO[PlayerController.Error, Unit] = {
|
||||||
@annotation.unused
|
|
||||||
val playerPos = ImVector3f.ZERO
|
val playerPos = ImVector3f.ZERO
|
||||||
@annotation.unused
|
|
||||||
val playerNode = None.taggedWith[PlayerTag]
|
|
||||||
@annotation.unused
|
|
||||||
val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
|
val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
|
||||||
wire[PlayerController.Props].create
|
val playerPhysicsControl =
|
||||||
|
PlayerController.Defaults.defaultPlayerPhysicsControl
|
||||||
|
.taggedWith[PlayerControllerTags.PlayerTag]
|
||||||
|
val camNode =
|
||||||
|
PlayerController.Defaults
|
||||||
|
.defaultCamerNode(camera, playerPos)
|
||||||
|
.taggedWith[PlayerControllerTags.PlayerCameraNode]
|
||||||
|
val mbPlayerNode = PlayerController.Defaults
|
||||||
|
.defaultPlayerNode(
|
||||||
|
assetManager,
|
||||||
|
modelPath,
|
||||||
|
playerPos,
|
||||||
|
camNode,
|
||||||
|
playerPhysicsControl
|
||||||
|
)
|
||||||
|
|
||||||
|
for {
|
||||||
|
playerNode <- IO.fromEither(mbPlayerNode)
|
||||||
|
_ <- wire[PlayerController.Props].create
|
||||||
|
} yield ()
|
||||||
}
|
}
|
||||||
|
def createNpc(
|
||||||
|
appScheduler: monix.execution.Scheduler,
|
||||||
|
npcName: String
|
||||||
|
) =
|
||||||
|
// : IO[PlayerController.Error, Unit] =
|
||||||
|
{
|
||||||
|
val initialPos = ImVector3f(100, 0, 0)
|
||||||
|
// val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
|
||||||
|
lazy val npcPhysicsControl =
|
||||||
|
new BetterCharacterControl(1f, 2.1f, 10f)
|
||||||
|
// .withJumpForce(ImVector3f(0, 5f, 0))
|
||||||
|
// val npcMovementActor = AkkaUtils.spawnActorL2(
|
||||||
|
// new NpcMovementActor2.Props(
|
||||||
|
// initialPos,
|
||||||
|
// tickEventBus,
|
||||||
|
// npcPhysicsControl
|
||||||
|
// ).create,
|
||||||
|
// s"${npcName}-npcMovementActor"
|
||||||
|
// )
|
||||||
|
lazy val mbNpcNode = PlayerController.Defaults.defaultNpcNode(
|
||||||
|
assetManager,
|
||||||
|
initialPos,
|
||||||
|
npcPhysicsControl,
|
||||||
|
"John"
|
||||||
|
)
|
||||||
|
val npcActorTask = AkkaUtils.spawnActorL2(
|
||||||
|
NpcActorSupervisor
|
||||||
|
.Props(
|
||||||
|
new NpcMovementActor2.Props(
|
||||||
|
enqueueR,
|
||||||
|
initialPos,
|
||||||
|
tickEventBus,
|
||||||
|
npcPhysicsControl
|
||||||
|
).create,
|
||||||
|
npcName,
|
||||||
|
initialPos
|
||||||
|
)
|
||||||
|
.create,
|
||||||
|
s"${npcName}-npcMovementActorSupervisor"
|
||||||
|
)
|
||||||
|
// .taggedWith[PlayerControllerTags.PlayerTag]
|
||||||
|
|
||||||
|
for {
|
||||||
|
npcNode <- IO.fromEither(mbNpcNode)
|
||||||
|
npcActor <- npcActorTask
|
||||||
|
_ <- IO {
|
||||||
|
physicsSpace += npcPhysicsControl
|
||||||
|
physicsSpace += npcNode
|
||||||
|
rootNode += npcNode
|
||||||
|
}
|
||||||
|
} yield (npcActor)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,10 @@ import cats.effect.Resource
|
|||||||
import io.odin.Logger
|
import io.odin.Logger
|
||||||
import monix.bio.Task
|
import monix.bio.Task
|
||||||
import wow.doge.mygame.executors.ExecutorsModule
|
import wow.doge.mygame.executors.ExecutorsModule
|
||||||
import wow.doge.mygame.game.GameModule
|
|
||||||
|
|
||||||
trait MainModule extends GameModule with ExecutorsModule {
|
trait MainModule extends ExecutorsModule {
|
||||||
|
|
||||||
def actorSystemResource2(
|
def actorSystemResource(
|
||||||
logger: Logger[Task]
|
logger: Logger[Task]
|
||||||
): Resource[Task, ActorSystem[SpawnProtocol.Command]] =
|
): Resource[Task, ActorSystem[SpawnProtocol.Command]] =
|
||||||
Resource.make(logger.info("Creating Actor System") >> Task {
|
Resource.make(logger.info("Creating Actor System") >> Task {
|
||||||
@ -18,8 +17,10 @@ trait MainModule extends GameModule with ExecutorsModule {
|
|||||||
name = "GameActorSystem"
|
name = "GameActorSystem"
|
||||||
)
|
)
|
||||||
})(sys =>
|
})(sys =>
|
||||||
logger.info("Shutting down actor system") >> Task(
|
for {
|
||||||
sys.terminate()
|
_ <- Task(sys.terminate())
|
||||||
)
|
_ <- Task.fromFuture(sys.whenTerminated)
|
||||||
|
_ <- logger.info("Actor System Terminated")
|
||||||
|
} yield ()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,132 +1,191 @@
|
|||||||
package wow.doge.mygame.game
|
package wow.doge.mygame.game
|
||||||
|
|
||||||
import scala.collection.immutable.Queue
|
import cats.effect.concurrent.Deferred
|
||||||
|
import com.jme3.app.state.AppStateManager
|
||||||
import com.jme3.app.SimpleApplication
|
import com.jme3.asset.AssetManager
|
||||||
import com.jme3.app.state.AppState
|
import com.jme3.input.InputManager
|
||||||
|
import com.jme3.scene.Node
|
||||||
|
import com.jme3.scene.Spatial
|
||||||
|
import com.softwaremill.tagging._
|
||||||
|
import com.typesafe.scalalogging.{Logger => SLogger}
|
||||||
|
import io.odin.Logger
|
||||||
|
import monix.bio.IO
|
||||||
import monix.bio.Task
|
import monix.bio.Task
|
||||||
import monix.execution.CancelableFuture
|
import monix.catnap.ConcurrentChannel
|
||||||
import monix.execution.Scheduler
|
import monix.catnap.ConsumerF
|
||||||
import monix.execution.atomic.Atomic
|
import monix.catnap.Semaphore
|
||||||
import monix.execution.{CancelablePromise => Promise}
|
import monix.eval.Coeval
|
||||||
import monix.reactive.MulticastStrategy
|
import wow.doge.mygame.game.subsystems.ui.JFxUI
|
||||||
import monix.reactive.Observable
|
|
||||||
import monix.reactive.subjects.ConcurrentSubject
|
|
||||||
import wow.doge.mygame.executors.GUIExecutorService
|
|
||||||
import wow.doge.mygame.executors.Schedulers
|
|
||||||
|
|
||||||
class GameApp(
|
sealed trait Error
|
||||||
schedulers: Schedulers,
|
case object FlyCamNotExists extends Error
|
||||||
appStates: AppState*
|
|
||||||
) extends SimpleApplication(appStates: _*) {
|
object GameAppTags {
|
||||||
import GameApp._
|
sealed trait RootNode
|
||||||
|
sealed trait GuiNode
|
||||||
|
}
|
||||||
|
|
||||||
|
class GameApp(logger: Logger[Task], val app: SimpleAppExt) {
|
||||||
|
import Ops._
|
||||||
|
|
||||||
|
def stateManager: Task[AppStateManager] = Task(app.getStateManager())
|
||||||
|
def inputManager: Task[InputManager] = Task(app.getInputManager())
|
||||||
|
def assetManager: Task[AssetManager] = Task(app.getAssetManager())
|
||||||
|
def guiNode = Task(app.getGuiNode().taggedWith[GameAppTags.GuiNode])
|
||||||
|
def addToGuiNode = guiNode.flatMap(rn => Task(new AddToNode(rn)))
|
||||||
|
def flyCam =
|
||||||
|
IO(app.getFlyByCamera()).onErrorHandleWith(_ =>
|
||||||
|
IO.raiseError(FlyCamNotExists)
|
||||||
|
)
|
||||||
|
def camera = Task(app.getCamera())
|
||||||
|
def viewPort = Task(app.getViewPort())
|
||||||
|
def rootNode = Task(app.getRootNode().taggedWith[GameAppTags.RootNode])
|
||||||
|
// def rootNode2 = SynchedObject(app.getRootNode())
|
||||||
|
def addToRootNode = rootNode.flatMap(rn => Task(new AddToNode(rn)))
|
||||||
|
def enqueue(cb: () => Unit) =
|
||||||
|
app.enqueue(new Runnable {
|
||||||
|
override def run() = cb()
|
||||||
|
})
|
||||||
|
def enqueueL[T](cb: () => T): Task[T] = app.enqueueL(cb)
|
||||||
|
|
||||||
|
def start = Task(app.start())
|
||||||
|
def stop = Task(app.stop())
|
||||||
|
def scheduler = app.scheduler
|
||||||
|
def jfxUI = JFxUI(app)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object GameApp {
|
||||||
|
|
||||||
|
class WrappedNode(node: Node, lock: Semaphore[Task]) {
|
||||||
|
|
||||||
|
def +=(spat: Spatial) = lock.withPermit(Task(node.attachChild(spat)))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A non blocking synchronized queue using an immutable scala queue and monix's atomic class
|
* Synchronization wrapper for a mutable object
|
||||||
|
*
|
||||||
|
* @param obj the mutable object
|
||||||
|
* @param lock lock for synchronization
|
||||||
*/
|
*/
|
||||||
private lazy val taskQueue2 = Atomic(Queue.empty[MyTask[_]])
|
class SynchedObject[A](obj: A, lock: Semaphore[Task]) {
|
||||||
|
def modify(f: A => Unit): Task[Unit] =
|
||||||
|
lock.withPermit(Task(f(obj)))
|
||||||
|
|
||||||
private val tickSubject =
|
def flatModify(f: A => Task[Unit]): Task[Unit] =
|
||||||
ConcurrentSubject[Float](multicast = MulticastStrategy.publish)(
|
lock.withPermit(f(obj))
|
||||||
schedulers.async
|
|
||||||
|
def get: Task[A] = lock.withPermit(Task(obj))
|
||||||
|
}
|
||||||
|
|
||||||
|
object SynchedObject {
|
||||||
|
def apply[A](obj: A) =
|
||||||
|
Semaphore[Task](1).flatMap(lock => Task(new SynchedObject(obj, lock)))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object Ops {
|
||||||
|
final class AddToNode[T <: Node](private val node: T) extends AnyVal {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure version
|
||||||
|
*/
|
||||||
|
def apply(spatial: Spatial)(implicit logger: Logger[Task]) =
|
||||||
|
logger.debug(
|
||||||
|
s"Request to add spatial with name ${spatial.getName()} to node ${node.getName()}"
|
||||||
|
) >> Task(node.attachChild(spatial))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Impure version
|
||||||
|
*/
|
||||||
|
def apply(spatial: Spatial)(implicit logger: SLogger) =
|
||||||
|
Coeval {
|
||||||
|
logger.debug(
|
||||||
|
s"Request to add spatial with name ${spatial.getName()} to node ${node.getName()}"
|
||||||
|
)
|
||||||
|
node.attachChild(spatial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object SpawnSystem {
|
||||||
|
sealed trait Result
|
||||||
|
final case object Ok extends Result
|
||||||
|
|
||||||
|
sealed trait Complete
|
||||||
|
final case object Complete extends Complete
|
||||||
|
|
||||||
|
sealed trait SpawnRequest
|
||||||
|
final case class SpawnSpatial(node: Node) extends SpawnRequest
|
||||||
|
|
||||||
|
final case class SpawnRequestWrapper(
|
||||||
|
spawnRequest: SpawnRequest,
|
||||||
|
result: Deferred[Task, Result]
|
||||||
)
|
)
|
||||||
|
|
||||||
def tickObservable: Observable[Float] = tickSubject
|
def apply(logger: Logger[Task]) =
|
||||||
|
for {
|
||||||
override def simpleInitApp(): Unit = {}
|
spawnChannel <- ConcurrentChannel[Task].of[Complete, SpawnRequestWrapper]
|
||||||
|
spawnSystem <- Task(new SpawnSystem(logger, spawnChannel))
|
||||||
override def simpleUpdate(tpf: Float): Unit = {
|
consumer <-
|
||||||
tickSubject.onNext(tpf)
|
spawnChannel.consume
|
||||||
}
|
.use(consumer => spawnSystem.receive(consumer))
|
||||||
|
.startAndForget
|
||||||
override def stop(): Unit = {
|
} yield (spawnSystem)
|
||||||
tickSubject.onComplete()
|
|
||||||
super.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
def enqueueScala[T](cb: () => T): CancelableFuture[T] = {
|
|
||||||
val p = Promise[T]()
|
|
||||||
taskQueue2.transform(_ :+ MyTask(p, cb))
|
|
||||||
p.future
|
|
||||||
}
|
|
||||||
|
|
||||||
def enqueueL[T](cb: () => T): Task[T] =
|
|
||||||
Task.deferFuture(enqueueScala(cb))
|
|
||||||
|
|
||||||
override protected def runQueuedTasks(): Unit = {
|
|
||||||
taskQueue2.transform { current =>
|
|
||||||
current.dequeueOption.fold(current) {
|
|
||||||
case (MyTask(p, cb), updated) =>
|
|
||||||
p.success(cb())
|
|
||||||
updated
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
super.runQueuedTasks()
|
|
||||||
}
|
|
||||||
|
|
||||||
object JMEExecutorService extends GUIExecutorService {
|
|
||||||
override def execute(command: Runnable): Unit =
|
|
||||||
enqueueScala(() => command.run())
|
|
||||||
// enqueue(command)
|
|
||||||
// new SingleThreadEventExecutor()
|
|
||||||
// sys.addShutdownHook(JMEExecutorService.shutdown())
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val scheduler = Scheduler(JMEExecutorService)
|
|
||||||
}
|
|
||||||
object GameApp {
|
|
||||||
private[game] case class MyTask[T](p: Promise[T], cb: () => T)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// val ship = ed.createEntity()
|
class SpawnSystem(
|
||||||
// val mbState = stateManager().state[EntityDataState]().map(_.getEntityData())
|
logger: Logger[Task],
|
||||||
// val mbState = Try(
|
spawnChannel: ConcurrentChannel[
|
||||||
// stateManager()
|
Task,
|
||||||
// .state[TestAppState]()
|
SpawnSystem.Complete,
|
||||||
// .entity
|
SpawnSystem.SpawnRequestWrapper
|
||||||
// ).toOption.flatten.toRight(println("empty"))
|
]
|
||||||
// // .flatMap(_.entity)
|
) {
|
||||||
// val x = mbState.flatMap(
|
import SpawnSystem._
|
||||||
// _.query
|
|
||||||
// .filter[TestComponent]("name", new Object())
|
|
||||||
// // .filterOr[TestEntity](
|
|
||||||
// // Filters
|
|
||||||
// // .fieldEquals(classOf[TestEntity], "", null)
|
|
||||||
// // )
|
|
||||||
// .component[Tag]()
|
|
||||||
// .component[TestComponent]()
|
|
||||||
// .result
|
|
||||||
// .toRight(println("failed"))
|
|
||||||
// )
|
|
||||||
|
|
||||||
// rootNode
|
for {
|
||||||
// .child(geom)
|
spawnSystem <- SpawnSystem(logger)
|
||||||
// .child(geom)
|
n <- spawnSystem.request(SpawnSpatial(new Node("Test")))
|
||||||
// .child(geom)
|
} yield ()
|
||||||
// .child(geom)
|
|
||||||
// .child(geom)
|
|
||||||
// .child(geom)
|
|
||||||
// .child(geom)
|
|
||||||
// .child(geom)
|
|
||||||
// Future(println("hello"))(jmeEC(this))
|
|
||||||
// val wbActor: Future[ActorRef[Greeter.Greet]] = actorSystem.ask(
|
|
||||||
// SpawnProtocol.Spawn(
|
|
||||||
// behavior = Greeter(),
|
|
||||||
// name = "listener",
|
|
||||||
// DispatcherSelector.fromConfig("jme-dispatcher"),
|
|
||||||
// _
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
|
|
||||||
// wbActor.map(a => a.ask(Greeter.Greet("hello", _)).map(println))
|
// val spawnChannel = ConcurrentChannel[Task].of[Result, SpawnRequest]
|
||||||
|
|
||||||
// Task(Promise[T]()).flatMap { p =>
|
private def receive(
|
||||||
// Task(taskQueue2.transform(_ :+ MyTask(p, cb))) >>
|
consumer: ConsumerF[Task, Complete, SpawnRequestWrapper]
|
||||||
// Task.fromCancelablePromise(p)
|
): Task[Unit] =
|
||||||
// }
|
consumer.pull.flatMap {
|
||||||
// Task.fromCancelablePromise {
|
case Right(message) =>
|
||||||
// val p = Promise[T]()
|
for {
|
||||||
// taskQueue2.transform(_ :+ MyTask(p, cb))
|
_ <-
|
||||||
// p
|
logger
|
||||||
// }
|
.debug(s"Received spawn request $message")
|
||||||
|
_ <- handleSpawn(message)
|
||||||
|
} yield receive(consumer)
|
||||||
|
case Left(r) =>
|
||||||
|
logger.info("Worker $$index is done!")
|
||||||
|
}
|
||||||
|
|
||||||
|
private def handleSpawn(spawnRequestWrapper: SpawnRequestWrapper) =
|
||||||
|
spawnRequestWrapper match {
|
||||||
|
case SpawnRequestWrapper(spawnRequest, result) =>
|
||||||
|
spawnRequest match {
|
||||||
|
case SpawnSpatial(spatial) =>
|
||||||
|
logger.debug(
|
||||||
|
s"Spawning spatial with name ${spatial.getName()}"
|
||||||
|
) >> result
|
||||||
|
.complete(Ok)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def request(spawnRequest: SpawnRequest) =
|
||||||
|
for {
|
||||||
|
d <- Deferred[Task, Result]
|
||||||
|
_ <- spawnChannel.push(SpawnRequestWrapper(spawnRequest, d))
|
||||||
|
res <- d.get
|
||||||
|
} yield (res)
|
||||||
|
|
||||||
|
def stop = spawnChannel.halt(Complete)
|
||||||
|
}
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
package wow.doge.mygame.game
|
|
||||||
|
|
||||||
import cats.effect.concurrent.Ref
|
|
||||||
import com.jme3.app.state.AppStateManager
|
|
||||||
import com.jme3.asset.AssetManager
|
|
||||||
import com.jme3.input.InputManager
|
|
||||||
import monix.bio.IO
|
|
||||||
import monix.bio.Task
|
|
||||||
import com.jme3.scene.Node
|
|
||||||
import monix.catnap.Semaphore
|
|
||||||
import com.jme3.scene.Spatial
|
|
||||||
import wow.doge.mygame.game.GameApp2.SynchedObject
|
|
||||||
import wow.doge.mygame.game.subsystems.ui.JFxUI
|
|
||||||
|
|
||||||
sealed trait Error
|
|
||||||
case object FlyCamNotExists extends Error
|
|
||||||
|
|
||||||
class GameApp2(val app: GameApp) {
|
|
||||||
def stateManager: Task[AppStateManager] = Task(app.getStateManager())
|
|
||||||
def inputManager: Task[InputManager] = Task(app.getInputManager())
|
|
||||||
def assetManager: Task[AssetManager] = Task(app.getAssetManager())
|
|
||||||
def guiNode = Ref[Task].of(app.getGuiNode())
|
|
||||||
def flyCam =
|
|
||||||
IO(app.getFlyByCamera()).onErrorHandleWith(_ =>
|
|
||||||
IO.raiseError(FlyCamNotExists)
|
|
||||||
)
|
|
||||||
def camera = Task(app.getCamera())
|
|
||||||
def viewPort = Task(app.getViewPort())
|
|
||||||
def rootNode = Ref[Task].of(app.getRootNode())
|
|
||||||
def rootNode2 = SynchedObject(app.getRootNode())
|
|
||||||
def enqueue(cb: () => Unit) =
|
|
||||||
app.enqueue(new Runnable {
|
|
||||||
override def run() = cb()
|
|
||||||
})
|
|
||||||
def enqueueL[T](cb: () => T): Task[T] = app.enqueueL(cb)
|
|
||||||
|
|
||||||
def start = Task(app.start())
|
|
||||||
def stop = Task(app.stop())
|
|
||||||
def scheduler = app.scheduler
|
|
||||||
def jfxUI = JFxUI(app)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
object GameApp2 {
|
|
||||||
|
|
||||||
class WrappedNode(node: Node, lock: Semaphore[Task]) {
|
|
||||||
|
|
||||||
def +=(spat: Spatial) = lock.withPermit(Task(node.attachChild(spat)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronization wrapper for a mutable object
|
|
||||||
*
|
|
||||||
* @param obj the mutable object
|
|
||||||
* @param lock lock for synchronization
|
|
||||||
*/
|
|
||||||
class SynchedObject[A](obj: A, lock: Semaphore[Task]) {
|
|
||||||
def modify(f: A => Unit): Task[Unit] =
|
|
||||||
lock.withPermit(Task(f(obj)))
|
|
||||||
|
|
||||||
def flatModify(f: A => Task[Unit]): Task[Unit] =
|
|
||||||
lock.withPermit(f(obj))
|
|
||||||
|
|
||||||
def get: Task[A] = lock.withPermit(Task(obj))
|
|
||||||
}
|
|
||||||
|
|
||||||
object SynchedObject {
|
|
||||||
def apply[A](obj: A) =
|
|
||||||
Semaphore[Task](1).flatMap(lock => Task(new SynchedObject(obj, lock)))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +1,83 @@
|
|||||||
package wow.doge.mygame.game
|
package wow.doge.mygame.game
|
||||||
|
|
||||||
import akka.actor.typed.ActorRef
|
import scala.concurrent.duration._
|
||||||
import akka.actor.typed.Scheduler
|
|
||||||
import akka.actor.typed.SpawnProtocol
|
import akka.actor.typed.SupervisorStrategy
|
||||||
import akka.actor.typed.scaladsl.Behaviors
|
import akka.actor.typed.scaladsl.Behaviors
|
||||||
import io.odin.Logger
|
import wow.doge.mygame.game.TickGenerator.Send
|
||||||
import monix.bio.Task
|
import wow.doge.mygame.game.entities.GenericTimerActor
|
||||||
import wow.doge.mygame.events.Events
|
import wow.doge.mygame.subsystems.events.EventBus
|
||||||
import wow.doge.mygame.executors.Schedulers
|
import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
|
||||||
|
import wow.doge.mygame.subsystems.events.TickEvent
|
||||||
|
import wow.doge.mygame.subsystems.events.TickEvent.PhysicsTick
|
||||||
|
|
||||||
object GameAppActor {
|
object GameAppActor {
|
||||||
|
|
||||||
sealed trait Command
|
sealed trait Command
|
||||||
case object ApplicationStarted extends Command
|
case object Start extends Command
|
||||||
case class ApplicationStartFailed(reason: String) extends Command
|
case object Pause extends Command
|
||||||
case object Stop extends Command
|
case object Stop extends Command
|
||||||
|
|
||||||
case class Props(
|
case class Props(
|
||||||
app: GameApp,
|
// app: SimpleAppExt,
|
||||||
akkaScheduler: Scheduler,
|
// akkaScheduler: Scheduler,
|
||||||
schedulers: Schedulers,
|
// schedulers: Schedulers,
|
||||||
spawnProtocol: ActorRef[SpawnProtocol.Command],
|
// spawnProtocol: ActorRef[SpawnProtocol.Command],
|
||||||
loggerL: Logger[Task]
|
// loggerL: Logger[Task]
|
||||||
|
tickEventBus: GameEventBus[TickEvent]
|
||||||
) {
|
) {
|
||||||
def create =
|
def create =
|
||||||
Behaviors.setup[Command] { ctx =>
|
Behaviors.setup[Command] { ctx =>
|
||||||
ctx.log.info("Hello from GameAppActor")
|
ctx.log.info("Hello from GameAppActor")
|
||||||
|
val renderTickGenerator =
|
||||||
|
ctx.spawn(
|
||||||
|
Behaviors
|
||||||
|
.supervise(renderTickGeneratorBehavior)
|
||||||
|
.onFailure[Exception](SupervisorStrategy.restart),
|
||||||
|
"tickGeneratorActor"
|
||||||
|
)
|
||||||
|
|
||||||
Behaviors.receiveMessage { msg =>
|
val tickGeneratorTimer = ctx.spawn(
|
||||||
msg match {
|
GenericTimerActor
|
||||||
|
.Props(renderTickGenerator, TickGenerator.Send, 10.millis)
|
||||||
|
.create,
|
||||||
|
"tickGeneratorTimer"
|
||||||
|
)
|
||||||
|
|
||||||
|
Behaviors.receiveMessage {
|
||||||
|
case Start =>
|
||||||
|
tickGeneratorTimer ! GenericTimerActor.Start
|
||||||
|
Behaviors.same
|
||||||
|
case Pause =>
|
||||||
|
tickGeneratorTimer ! GenericTimerActor.Stop
|
||||||
|
Behaviors.same
|
||||||
case Stop =>
|
case Stop =>
|
||||||
ctx.log.info("Received stop")
|
ctx.log.info("Received stop")
|
||||||
|
tickGeneratorTimer ! GenericTimerActor.Stop
|
||||||
Behaviors.stopped
|
Behaviors.stopped
|
||||||
case ApplicationStarted =>
|
|
||||||
ctx.log.info("Application started")
|
}
|
||||||
Behaviors.same
|
}
|
||||||
case ApplicationStartFailed(reason) =>
|
|
||||||
ctx.log.error(
|
val renderTickGeneratorBehavior =
|
||||||
s"Failed to start application - $reason"
|
Behaviors.receiveMessage[TickGenerator.Command] {
|
||||||
|
case Send =>
|
||||||
|
tickEventBus ! EventBus.Publish(
|
||||||
|
TickEvent.RenderTick,
|
||||||
|
"tickGeneratorActor"
|
||||||
)
|
)
|
||||||
Behaviors.stopped
|
Behaviors.same
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object TickGenerator {
|
||||||
|
sealed trait Command
|
||||||
|
case object Send extends Command
|
||||||
|
}
|
||||||
object SubscribingActor {
|
object SubscribingActor {
|
||||||
def apply() =
|
def apply() =
|
||||||
Behaviors.receive[Events.Tick.PhysicsTick.type] { (ctx, msg) =>
|
Behaviors.receive[PhysicsTick.type] { (ctx, msg) =>
|
||||||
ctx.log.debug(s"received event $msg")
|
ctx.log.debug(s"received event $msg")
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,24 @@
|
|||||||
package wow.doge.mygame.game
|
package wow.doge.mygame.game
|
||||||
|
|
||||||
import akka.actor.typed.ActorRef
|
|
||||||
import akka.actor.typed.SpawnProtocol
|
|
||||||
import cats.effect.Resource
|
import cats.effect.Resource
|
||||||
import com.jme3.app.StatsAppState
|
import com.jme3.app.StatsAppState
|
||||||
import com.jme3.system.AppSettings
|
import com.jme3.system.AppSettings
|
||||||
import io.odin.Logger
|
import io.odin.Logger
|
||||||
import monix.bio.Fiber
|
|
||||||
import monix.bio.IO
|
|
||||||
import monix.bio.Task
|
import monix.bio.Task
|
||||||
import monix.execution.Scheduler
|
import monix.execution.Scheduler
|
||||||
import wow.doge.mygame.executors.Schedulers
|
import wow.doge.mygame.executors.Schedulers
|
||||||
import wow.doge.mygame.game.subsystems.input.GameInputHandler
|
|
||||||
class GameAppResource(
|
class GameAppResource(
|
||||||
logger: Logger[Task],
|
logger: Logger[Task],
|
||||||
jmeScheduler: Scheduler,
|
jmeScheduler: Scheduler,
|
||||||
schedulers: Schedulers
|
schedulers: Schedulers
|
||||||
) {
|
) {
|
||||||
def get2: Resource[Task, (GameApp2, Fiber[Throwable, Unit])] =
|
|
||||||
Resource.make(
|
|
||||||
for {
|
|
||||||
_ <- logger.info("Creating game app")
|
|
||||||
app <- Task(new GameApp(schedulers, new StatsAppState()))
|
|
||||||
app2 <- Task {
|
|
||||||
val settings = new AppSettings(true)
|
|
||||||
settings.setVSync(true)
|
|
||||||
settings.setUseInput(true)
|
|
||||||
// new FlyCamAppState
|
|
||||||
// settings.setFrameRate(250)
|
|
||||||
app.setSettings(settings)
|
|
||||||
// JMERunner.runner = app
|
|
||||||
// app
|
|
||||||
new GameApp2(app)
|
|
||||||
}
|
|
||||||
fib <- app2.start.executeOn(jmeScheduler).start
|
|
||||||
} yield (app2 -> fib)
|
|
||||||
)(logger.info("Closing game app") >> _._2.cancel)
|
|
||||||
|
|
||||||
def get: Resource[Task, GameApp2] =
|
def get: Resource[Task, GameApp] =
|
||||||
Resource.make(
|
Resource.make(
|
||||||
for {
|
for {
|
||||||
_ <- logger.info("Creating game app")
|
_ <- logger.info("Creating game app")
|
||||||
app <- Task(new GameApp(schedulers, new StatsAppState()))
|
appExt <- Task(new SimpleAppExt(schedulers, new StatsAppState()))
|
||||||
app2 <- Task {
|
app <- Task {
|
||||||
val settings = new AppSettings(true)
|
val settings = new AppSettings(true)
|
||||||
settings.setVSync(true)
|
settings.setVSync(true)
|
||||||
|
|
||||||
@ -50,48 +26,11 @@ class GameAppResource(
|
|||||||
* disables the launcher
|
* disables the launcher
|
||||||
* We'll be making our own launcher anyway
|
* We'll be making our own launcher anyway
|
||||||
*/
|
*/
|
||||||
app.setShowSettings(false)
|
appExt.setShowSettings(false)
|
||||||
app.setSettings(settings)
|
appExt.setSettings(settings)
|
||||||
// JMERunner.runner = app
|
// JMERunner.runner = app
|
||||||
new GameApp2(app)
|
new GameApp(logger, appExt)
|
||||||
}
|
}
|
||||||
// fib <- app2.start.executeOn(jmeScheduler).start
|
} yield (app)
|
||||||
} yield (app2)
|
|
||||||
)(_ => logger.info("Closing game app"))
|
)(_ => logger.info("Closing game app"))
|
||||||
}
|
}
|
||||||
|
|
||||||
trait GameModule {
|
|
||||||
|
|
||||||
def gameAppResource(
|
|
||||||
logger: Logger[Task],
|
|
||||||
jmeScheduler: Scheduler,
|
|
||||||
schedulers: Schedulers
|
|
||||||
): Resource[Task, (GameApp, Fiber[Throwable, Unit])] =
|
|
||||||
Resource.make(
|
|
||||||
(for {
|
|
||||||
_ <- logger.info("Creating game app")
|
|
||||||
app <- Task(new GameApp(schedulers))
|
|
||||||
_ <- Task {
|
|
||||||
val settings = new AppSettings(true)
|
|
||||||
settings.setVSync(true)
|
|
||||||
// settings.setFrameRate(250)
|
|
||||||
app.setSettings(settings)
|
|
||||||
// JMERunner.runner = app
|
|
||||||
app
|
|
||||||
}
|
|
||||||
fib <- Task(app.start()).executeOn(jmeScheduler).start
|
|
||||||
} yield (app -> fib))
|
|
||||||
)(_._2.cancel)
|
|
||||||
|
|
||||||
def inputHandlerSystemResource(
|
|
||||||
props: GameInputHandler.Props
|
|
||||||
): Resource[Task, Task[Unit]] =
|
|
||||||
Resource.liftF {
|
|
||||||
Task.evalAsync(props.begin)
|
|
||||||
}
|
|
||||||
def gameSystemsResource(
|
|
||||||
spawnProtocol: ActorRef[SpawnProtocol.Command],
|
|
||||||
gameSystems: Task[Unit]*
|
|
||||||
): Resource[Task, List[Unit]] =
|
|
||||||
Resource.liftF(IO.defer(Task.parSequence(gameSystems)))
|
|
||||||
}
|
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
package wow.doge.mygame.game
|
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
|
||||||
|
|
||||||
import akka.actor.typed.ActorRef
|
|
||||||
import akka.actor.typed.ActorSystem
|
|
||||||
import akka.actor.typed.Scheduler
|
|
||||||
import akka.actor.typed.SpawnProtocol
|
|
||||||
import akka.util.Timeout
|
|
||||||
import cats.effect.concurrent.Ref
|
|
||||||
import com.jme3.app.state.AppStateManager
|
|
||||||
import com.jme3.asset.AssetManager
|
|
||||||
import com.jme3.asset.plugins.ZipLocator
|
|
||||||
import com.jme3.bullet.BulletAppState
|
|
||||||
import com.jme3.input.InputManager
|
|
||||||
import com.jme3.renderer.Camera
|
|
||||||
import com.jme3.scene.Node
|
|
||||||
import com.softwaremill.macwire._
|
|
||||||
import com.softwaremill.tagging._
|
|
||||||
import io.odin.Logger
|
|
||||||
import monix.bio.IO
|
|
||||||
import monix.bio.Task
|
|
||||||
import monix.reactive.Consumer
|
|
||||||
import wow.doge.mygame.events.EventBus
|
|
||||||
import wow.doge.mygame.game.nodes.PlayerTag
|
|
||||||
import wow.doge.mygame.game.nodes.PlayerController
|
|
||||||
import wow.doge.mygame.game.subsystems.input.GameInputHandler
|
|
||||||
import wow.doge.mygame.implicits._
|
|
||||||
import wow.doge.mygame.math.ImVector3f
|
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent
|
|
||||||
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
|
||||||
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
|
||||||
import wow.doge.mygame.utils.IOUtils
|
|
||||||
|
|
||||||
class GameSystemsInitializer(
|
|
||||||
spawnProtocol: ActorSystem[SpawnProtocol.Command],
|
|
||||||
loggerL: Logger[Task],
|
|
||||||
// eventBuses: EventsModule2
|
|
||||||
playerMovementEventBus: ActorRef[
|
|
||||||
EventBus.Command[EntityMovementEvent.PlayerMovementEvent]
|
|
||||||
],
|
|
||||||
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
|
|
||||||
inputManager: InputManager,
|
|
||||||
assetManager: AssetManager,
|
|
||||||
stateManager: AppStateManager,
|
|
||||||
camera: Camera,
|
|
||||||
enqueueR: Function1[() => Unit, Unit],
|
|
||||||
appScheduler: monix.execution.Scheduler,
|
|
||||||
rootNode: Ref[Task, Node]
|
|
||||||
) {
|
|
||||||
implicit val timeout: Timeout = Timeout(1.second)
|
|
||||||
|
|
||||||
import GameSystemsInitializer._
|
|
||||||
|
|
||||||
implicit val akkaScheduler: Scheduler = spawnProtocol.scheduler
|
|
||||||
// lazy val inputManager = app.inputManager
|
|
||||||
// lazy val assetManager = app.assetManager
|
|
||||||
lazy val bulletAppState = new BulletAppState()
|
|
||||||
// lazy val playerMovementEventBus = eventBuses.playerMovementEventBusTask
|
|
||||||
|
|
||||||
val init =
|
|
||||||
for {
|
|
||||||
_ <- loggerL.info("Initializing Systems")
|
|
||||||
// playerMovementEventBus <- playerMovementEventBusTask
|
|
||||||
_ <- Task(stateManager.attach(bulletAppState))
|
|
||||||
_ <- Task(
|
|
||||||
assetManager.registerLocator(
|
|
||||||
// "src/main/resources/assets/town.zip",
|
|
||||||
(os.rel / "assets" / "town.zip"),
|
|
||||||
classOf[ZipLocator]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// _ <- app.enqueueL(() => DefaultGameLevel(app, bulletAppState))
|
|
||||||
_ <- wireWith(createPlayerController _).startAndForget
|
|
||||||
_ <- wire[GameInputHandler.Props].begin
|
|
||||||
|
|
||||||
} yield ()
|
|
||||||
|
|
||||||
def createPlayerController(
|
|
||||||
// playerMovementEventBus: ActorRef[
|
|
||||||
// EventBus.Command[PlayerMovementEvent]
|
|
||||||
// ],
|
|
||||||
// playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
|
|
||||||
): IO[PlayerController.Error, Unit] = {
|
|
||||||
@annotation.unused
|
|
||||||
val playerPos = ImVector3f.ZERO
|
|
||||||
@annotation.unused
|
|
||||||
val playerNode = None.taggedWith[PlayerTag]
|
|
||||||
@annotation.unused
|
|
||||||
val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
|
|
||||||
wire[PlayerController.Props].create
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object GameSystemsInitializer {
|
|
||||||
|
|
||||||
def playerMovementActorTickConsumer(
|
|
||||||
playerMovementActor: ActorRef[ImMovementActor.Command]
|
|
||||||
) =
|
|
||||||
Consumer
|
|
||||||
.foreachTask[Float](tpf =>
|
|
||||||
IOUtils.toTask(playerMovementActor !! ImMovementActor.Tick)
|
|
||||||
)
|
|
||||||
// .mapTask()
|
|
||||||
}
|
|
132
src/main/scala/wow/doge/mygame/game/SimpleAppExt.scala
Normal file
132
src/main/scala/wow/doge/mygame/game/SimpleAppExt.scala
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
package wow.doge.mygame.game
|
||||||
|
|
||||||
|
import scala.collection.immutable.Queue
|
||||||
|
|
||||||
|
import com.jme3.app.SimpleApplication
|
||||||
|
import com.jme3.app.state.AppState
|
||||||
|
import monix.bio.Task
|
||||||
|
import monix.execution.CancelableFuture
|
||||||
|
import monix.execution.Scheduler
|
||||||
|
import monix.execution.atomic.Atomic
|
||||||
|
import monix.execution.{CancelablePromise => Promise}
|
||||||
|
import monix.reactive.MulticastStrategy
|
||||||
|
import monix.reactive.Observable
|
||||||
|
import monix.reactive.subjects.ConcurrentSubject
|
||||||
|
import wow.doge.mygame.executors.GUIExecutorService
|
||||||
|
import wow.doge.mygame.executors.Schedulers
|
||||||
|
|
||||||
|
class SimpleAppExt(
|
||||||
|
schedulers: Schedulers,
|
||||||
|
appStates: AppState*
|
||||||
|
) extends SimpleApplication(appStates: _*) {
|
||||||
|
import SimpleAppExt._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A non blocking synchronized queue using an immutable scala queue and monix's atomic class
|
||||||
|
*/
|
||||||
|
private lazy val taskQueue2 = Atomic(Queue.empty[MyTask[_]])
|
||||||
|
|
||||||
|
private val tickSubject =
|
||||||
|
ConcurrentSubject[Float](multicast = MulticastStrategy.publish)(
|
||||||
|
schedulers.async
|
||||||
|
)
|
||||||
|
|
||||||
|
def tickObservable: Observable[Float] = tickSubject
|
||||||
|
|
||||||
|
override def simpleInitApp(): Unit = {}
|
||||||
|
|
||||||
|
override def simpleUpdate(tpf: Float): Unit = {
|
||||||
|
tickSubject.onNext(tpf)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def stop(): Unit = {
|
||||||
|
tickSubject.onComplete()
|
||||||
|
super.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
def enqueueScala[T](cb: () => T): CancelableFuture[T] = {
|
||||||
|
val p = Promise[T]()
|
||||||
|
taskQueue2.transform(_ :+ MyTask(p, cb))
|
||||||
|
p.future
|
||||||
|
}
|
||||||
|
|
||||||
|
def enqueueL[T](cb: () => T): Task[T] =
|
||||||
|
Task.deferFuture(enqueueScala(cb))
|
||||||
|
|
||||||
|
override protected def runQueuedTasks(): Unit = {
|
||||||
|
taskQueue2.transform { current =>
|
||||||
|
current.dequeueOption.fold(current) {
|
||||||
|
case (MyTask(p, cb), updated) =>
|
||||||
|
p.success(cb())
|
||||||
|
updated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.runQueuedTasks()
|
||||||
|
}
|
||||||
|
|
||||||
|
object JMEExecutorService extends GUIExecutorService {
|
||||||
|
override def execute(command: Runnable): Unit =
|
||||||
|
enqueueScala(() => command.run())
|
||||||
|
// enqueue(command)
|
||||||
|
// new SingleThreadEventExecutor()
|
||||||
|
// sys.addShutdownHook(JMEExecutorService.shutdown())
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy val scheduler = Scheduler(JMEExecutorService)
|
||||||
|
}
|
||||||
|
object SimpleAppExt {
|
||||||
|
private[game] case class MyTask[T](p: Promise[T], cb: () => T)
|
||||||
|
}
|
||||||
|
|
||||||
|
// val ship = ed.createEntity()
|
||||||
|
// val mbState = stateManager().state[EntityDataState]().map(_.getEntityData())
|
||||||
|
// val mbState = Try(
|
||||||
|
// stateManager()
|
||||||
|
// .state[TestAppState]()
|
||||||
|
// .entity
|
||||||
|
// ).toOption.flatten.toRight(println("empty"))
|
||||||
|
// // .flatMap(_.entity)
|
||||||
|
// val x = mbState.flatMap(
|
||||||
|
// _.query
|
||||||
|
// .filter[TestComponent]("name", new Object())
|
||||||
|
// // .filterOr[TestEntity](
|
||||||
|
// // Filters
|
||||||
|
// // .fieldEquals(classOf[TestEntity], "", null)
|
||||||
|
// // )
|
||||||
|
// .component[Tag]()
|
||||||
|
// .component[TestComponent]()
|
||||||
|
// .result
|
||||||
|
// .toRight(println("failed"))
|
||||||
|
// )
|
||||||
|
|
||||||
|
// rootNode
|
||||||
|
// .child(geom)
|
||||||
|
// .child(geom)
|
||||||
|
// .child(geom)
|
||||||
|
// .child(geom)
|
||||||
|
// .child(geom)
|
||||||
|
// .child(geom)
|
||||||
|
// .child(geom)
|
||||||
|
// .child(geom)
|
||||||
|
// Future(println("hello"))(jmeEC(this))
|
||||||
|
// val wbActor: Future[ActorRef[Greeter.Greet]] = actorSystem.ask(
|
||||||
|
// SpawnProtocol.Spawn(
|
||||||
|
// behavior = Greeter(),
|
||||||
|
// name = "listener",
|
||||||
|
// DispatcherSelector.fromConfig("jme-dispatcher"),
|
||||||
|
// _
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
|
||||||
|
// wbActor.map(a => a.ask(Greeter.Greet("hello", _)).map(println))
|
||||||
|
|
||||||
|
// Task(Promise[T]()).flatMap { p =>
|
||||||
|
// Task(taskQueue2.transform(_ :+ MyTask(p, cb))) >>
|
||||||
|
// Task.fromCancelablePromise(p)
|
||||||
|
// }
|
||||||
|
// Task.fromCancelablePromise {
|
||||||
|
// val p = Promise[T]()
|
||||||
|
// taskQueue2.transform(_ :+ MyTask(p, cb))
|
||||||
|
// p
|
||||||
|
// }
|
@ -0,0 +1,225 @@
|
|||||||
|
package wow.doge.mygame.game.entities
|
||||||
|
|
||||||
|
import akka.actor.typed.ActorRef
|
||||||
|
import akka.actor.typed.Behavior
|
||||||
|
import akka.actor.typed.SupervisorStrategy
|
||||||
|
import akka.actor.typed.scaladsl.ActorContext
|
||||||
|
import akka.actor.typed.scaladsl.Behaviors
|
||||||
|
import wow.doge.mygame.subsystems.events.Event
|
||||||
|
import wow.doge.mygame.subsystems.events.EventBus
|
||||||
|
import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
|
||||||
|
import wow.doge.mygame.subsystems.events.TickEvent
|
||||||
|
import wow.doge.mygame.subsystems.events.TickEvent.RenderTick
|
||||||
|
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
||||||
|
import wow.doge.mygame.subsystems.events.EntityMovementEvent
|
||||||
|
import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedLeft
|
||||||
|
import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedUp
|
||||||
|
import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedRight
|
||||||
|
import wow.doge.mygame.subsystems.events.EntityMovementEvent.MovedDown
|
||||||
|
import wow.doge.mygame.math.ImVector3f
|
||||||
|
import wow.doge.mygame.game.subsystems.movement.CanMove
|
||||||
|
import wow.doge.mygame.implicits._
|
||||||
|
import akka.util.Timeout
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
import scala.util.Success
|
||||||
|
import scala.util.Failure
|
||||||
|
|
||||||
|
object NpcActorSupervisor {
|
||||||
|
sealed trait Command
|
||||||
|
case class Move(pos: ImVector3f) extends Command
|
||||||
|
private case class UpdatePosition(pos: ImVector3f) extends Command
|
||||||
|
private case class LogError(err: Throwable) extends Command
|
||||||
|
case object MovementTick extends Command
|
||||||
|
|
||||||
|
final case class Props(
|
||||||
|
npcMovementActorBehavior: Behavior[NpcMovementActor2.Command],
|
||||||
|
npcName: String,
|
||||||
|
initialPos: ImVector3f
|
||||||
|
) {
|
||||||
|
def create =
|
||||||
|
Behaviors.setup[Command] { ctx =>
|
||||||
|
val npcMovementActor = ctx.spawn(
|
||||||
|
(npcMovementActorBehavior),
|
||||||
|
s"npc-${npcName}-NpcMovementActor"
|
||||||
|
)
|
||||||
|
|
||||||
|
new NpcActorSupervisor(ctx, this)
|
||||||
|
.idle(State(npcMovementActor, initialPos))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final case class State(
|
||||||
|
npcMovementActor: ActorRef[NpcMovementActor2.Command],
|
||||||
|
currentPos: ImVector3f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
class NpcActorSupervisor(
|
||||||
|
ctx: ActorContext[NpcActorSupervisor.Command],
|
||||||
|
props: NpcActorSupervisor.Props
|
||||||
|
) {
|
||||||
|
import NpcActorSupervisor._
|
||||||
|
implicit val timeout = Timeout(1.second)
|
||||||
|
def idle(state: State): Behavior[NpcActorSupervisor.Command] =
|
||||||
|
Behaviors.receiveMessage[Command] {
|
||||||
|
case Move(pos) => {
|
||||||
|
state.npcMovementActor ! NpcMovementActor2.Move(pos)
|
||||||
|
val movementTimer = ctx.spawn(
|
||||||
|
GenericTimerActor.Props(ctx.self, MovementTick, 100.millis).create,
|
||||||
|
s"npc-${props.npcName}-NpcActorTimer"
|
||||||
|
)
|
||||||
|
movementTimer ! GenericTimerActor.Start
|
||||||
|
moving(state, pos, movementTimer)
|
||||||
|
}
|
||||||
|
case LogError(err) =>
|
||||||
|
ctx.log.warn(err.getMessage())
|
||||||
|
Behaviors.same
|
||||||
|
case _ => Behaviors.unhandled
|
||||||
|
}
|
||||||
|
|
||||||
|
def moving(
|
||||||
|
state: State,
|
||||||
|
targetPos: ImVector3f,
|
||||||
|
movementTimer: ActorRef[GenericTimerActor.Command]
|
||||||
|
): Behavior[NpcActorSupervisor.Command] =
|
||||||
|
Behaviors.receiveMessagePartial[Command] {
|
||||||
|
case LogError(err) =>
|
||||||
|
ctx.log.warn(err.getMessage())
|
||||||
|
Behaviors.same
|
||||||
|
case Move(pos) => moving(state, pos, movementTimer)
|
||||||
|
case UpdatePosition(pos) =>
|
||||||
|
ctx.log.trace("Current pos = " + state.currentPos.toString())
|
||||||
|
moving(state.copy(currentPos = pos), targetPos, movementTimer)
|
||||||
|
case MovementTick =>
|
||||||
|
val dst = ImVector3f.dst(targetPos, state.currentPos)
|
||||||
|
if (dst <= 10f) {
|
||||||
|
state.npcMovementActor ! NpcMovementActor2.StopMoving
|
||||||
|
movementTimer ! GenericTimerActor.Stop
|
||||||
|
idle(state)
|
||||||
|
} else {
|
||||||
|
// ctx.log.debug("Difference = " + dst.toString())
|
||||||
|
// ctx.log.debug("Current pos = " + state.currentPos.toString())
|
||||||
|
|
||||||
|
ctx.ask(state.npcMovementActor, NpcMovementActor2.AskPosition(_)) {
|
||||||
|
case Success(value) =>
|
||||||
|
UpdatePosition(value)
|
||||||
|
case Failure(exception) => LogError(exception)
|
||||||
|
}
|
||||||
|
// Behaviors.same
|
||||||
|
moving(state, targetPos, movementTimer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object NpcMovementActor2 {
|
||||||
|
sealed trait Command
|
||||||
|
case class AskPosition(replyTo: ActorRef[ImVector3f]) extends Command
|
||||||
|
case object StopMoving extends Command
|
||||||
|
case class Move(target: ImVector3f) extends Command
|
||||||
|
|
||||||
|
final class Props[T: CanMove](
|
||||||
|
val enqueueR: Function1[() => Unit, Unit],
|
||||||
|
val initialPos: ImVector3f,
|
||||||
|
val tickEventBus: GameEventBus[TickEvent],
|
||||||
|
val movable: T
|
||||||
|
) {
|
||||||
|
def create =
|
||||||
|
Behaviors.setup[Command] { ctx =>
|
||||||
|
new NpcMovementActor2(ctx, this).receive(State(initialPos))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final case class State(currentPos: ImVector3f)
|
||||||
|
}
|
||||||
|
class NpcMovementActor2[T](
|
||||||
|
ctx: ActorContext[NpcMovementActor2.Command],
|
||||||
|
props: NpcMovementActor2.Props[T]
|
||||||
|
) {
|
||||||
|
import NpcMovementActor2._
|
||||||
|
def receive(
|
||||||
|
state: State
|
||||||
|
)(implicit cm: CanMove[T]): Behavior[NpcMovementActor2.Command] =
|
||||||
|
Behaviors.receiveMessage[Command] {
|
||||||
|
case AskPosition(replyTo) =>
|
||||||
|
replyTo ! cm.location(props.movable)
|
||||||
|
Behaviors.same
|
||||||
|
case Move(target: ImVector3f) =>
|
||||||
|
props.enqueueR(() =>
|
||||||
|
cm.move(props.movable, (target - state.currentPos) * 0.005f)
|
||||||
|
)
|
||||||
|
receive(state = state.copy(currentPos = cm.location(props.movable)))
|
||||||
|
case StopMoving =>
|
||||||
|
ctx.log.debug(
|
||||||
|
"Position at Stop = " + cm.location(props.movable).toString
|
||||||
|
)
|
||||||
|
props.enqueueR(() => cm.stop(props.movable))
|
||||||
|
receive(state = state.copy(currentPos = cm.location(props.movable)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object NpcMovementActor {
|
||||||
|
sealed trait Command
|
||||||
|
final case class Props(
|
||||||
|
imMovementActorBehavior: Behavior[ImMovementActor.Command],
|
||||||
|
npcName: String,
|
||||||
|
// movementActor: ActorRef[ImMovementActor.Command],
|
||||||
|
mainEventBus: ActorRef[
|
||||||
|
EventBus.Command[Event]
|
||||||
|
],
|
||||||
|
tickEventBus: GameEventBus[TickEvent]
|
||||||
|
) {
|
||||||
|
|
||||||
|
def create: Behavior[Command] =
|
||||||
|
Behaviors.setup { ctx =>
|
||||||
|
val movementActor = ctx.spawn(
|
||||||
|
Behaviors
|
||||||
|
.supervise(imMovementActorBehavior)
|
||||||
|
.onFailure[Exception](SupervisorStrategy.restart),
|
||||||
|
s"npc-${npcName}-MovementActorChild"
|
||||||
|
)
|
||||||
|
val npcMovementElBehavior = Behaviors.receiveMessagePartial[Event] {
|
||||||
|
case event: EntityMovementEvent =>
|
||||||
|
event match {
|
||||||
|
case MovedLeft(name, pressed) =>
|
||||||
|
if (name == npcName)
|
||||||
|
movementActor ! ImMovementActor.MovedLeft(pressed)
|
||||||
|
Behaviors.same
|
||||||
|
case MovedUp(name, pressed) =>
|
||||||
|
if (name == npcName)
|
||||||
|
movementActor ! ImMovementActor.MovedUp(pressed)
|
||||||
|
Behaviors.same
|
||||||
|
case MovedRight(name, pressed) =>
|
||||||
|
if (name == npcName)
|
||||||
|
movementActor ! ImMovementActor.MovedRight(pressed)
|
||||||
|
Behaviors.same
|
||||||
|
case MovedDown(name, pressed) =>
|
||||||
|
if (name == npcName)
|
||||||
|
movementActor ! ImMovementActor.MovedDown(pressed)
|
||||||
|
Behaviors.same
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val npcMovementEl = ctx.spawn(
|
||||||
|
Behaviors
|
||||||
|
.supervise(npcMovementElBehavior)
|
||||||
|
.onFailure[Exception](SupervisorStrategy.restart),
|
||||||
|
s"npc-${npcName}-MovementEventHandler"
|
||||||
|
)
|
||||||
|
val renderTickElBehavior =
|
||||||
|
Behaviors.receiveMessage[RenderTick.type] {
|
||||||
|
case RenderTick =>
|
||||||
|
movementActor ! ImMovementActor.Tick
|
||||||
|
Behaviors.same
|
||||||
|
}
|
||||||
|
|
||||||
|
val renderTickEl =
|
||||||
|
ctx.spawn(
|
||||||
|
renderTickElBehavior,
|
||||||
|
s"npc-${npcName}-MovementTickListener"
|
||||||
|
)
|
||||||
|
|
||||||
|
mainEventBus ! EventBus.Subscribe(npcMovementEl)
|
||||||
|
tickEventBus ! EventBus.Subscribe(renderTickEl)
|
||||||
|
Behaviors.receiveMessage { msg => Behaviors.same }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package wow.doge.mygame.game.nodes
|
package wow.doge.mygame.game.entities
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
import scala.util.Random
|
||||||
|
|
||||||
import akka.actor.typed.ActorRef
|
import akka.actor.typed.ActorRef
|
||||||
import akka.actor.typed.Behavior
|
import akka.actor.typed.Behavior
|
||||||
@ -9,26 +10,27 @@ import akka.actor.typed.SupervisorStrategy
|
|||||||
import akka.actor.typed.scaladsl.ActorContext
|
import akka.actor.typed.scaladsl.ActorContext
|
||||||
import akka.actor.typed.scaladsl.Behaviors
|
import akka.actor.typed.scaladsl.Behaviors
|
||||||
import akka.actor.typed.scaladsl.TimerScheduler
|
import akka.actor.typed.scaladsl.TimerScheduler
|
||||||
import com.jme3.scene.CameraNode
|
|
||||||
import com.typesafe.scalalogging.Logger
|
import com.typesafe.scalalogging.Logger
|
||||||
import org.slf4j.event.Level
|
import org.slf4j.event.Level
|
||||||
import wow.doge.mygame.events.EventBus
|
|
||||||
import wow.doge.mygame.game.subsystems.movement.CanMove
|
import wow.doge.mygame.game.subsystems.movement.CanMove
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent
|
import wow.doge.mygame.subsystems.events.EventBus
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
|
import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
|
||||||
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
||||||
|
import wow.doge.mygame.subsystems.events.PlayerMovementEvent
|
||||||
|
import wow.doge.mygame.subsystems.events.TickEvent
|
||||||
|
import wow.doge.mygame.subsystems.events.TickEvent.RenderTick
|
||||||
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
||||||
|
|
||||||
object PlayerActorSupervisor {
|
object PlayerActorSupervisor {
|
||||||
sealed trait Command
|
sealed trait Command
|
||||||
|
|
||||||
final case class Props(
|
final case class Props(
|
||||||
enqueueR: Function1[() => Unit, Unit],
|
|
||||||
camNode: CameraNode,
|
|
||||||
playerMovementEventBus: ActorRef[
|
playerMovementEventBus: ActorRef[
|
||||||
EventBus.Command[PlayerMovementEvent]
|
EventBus.Command[PlayerMovementEvent]
|
||||||
],
|
],
|
||||||
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
|
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
|
||||||
|
tickEventBus: GameEventBus[TickEvent],
|
||||||
|
imMovementActorBehavior: Behavior[ImMovementActor.Command],
|
||||||
|
playerCamELBehavior: Behavior[PlayerCameraEvent]
|
||||||
) {
|
) {
|
||||||
def create[T: CanMove](movable: T) =
|
def create[T: CanMove](movable: T) =
|
||||||
Behaviors.logMessages(
|
Behaviors.logMessages(
|
||||||
@ -44,59 +46,40 @@ object PlayerActorSupervisor {
|
|||||||
lazy val movementActor =
|
lazy val movementActor =
|
||||||
ctx.spawn(
|
ctx.spawn(
|
||||||
Behaviors
|
Behaviors
|
||||||
.supervise(
|
.supervise(imMovementActorBehavior)
|
||||||
ImMovementActor
|
|
||||||
.Props(enqueueR, movable, playerMovementEventBus)
|
|
||||||
.create
|
|
||||||
)
|
|
||||||
.onFailure[Exception](SupervisorStrategy.restart),
|
.onFailure[Exception](SupervisorStrategy.restart),
|
||||||
"playerMovementActor"
|
"playerMovementActorChild"
|
||||||
)
|
)
|
||||||
lazy val playerMovementEventHandler = ctx.spawn(
|
ctx.spawn(
|
||||||
Behaviors
|
PlayerMovementActor
|
||||||
.supervise(PlayerMovementEventListener(movementActor))
|
.Props(movementActor, playerMovementEventBus, tickEventBus)
|
||||||
.onFailure[Exception](SupervisorStrategy.restart),
|
.create,
|
||||||
"playerMovementEventHandler"
|
"playerMovementAcor"
|
||||||
)
|
)
|
||||||
lazy val movementActorTimer = ctx.spawn(
|
|
||||||
Behaviors
|
|
||||||
.supervise(MovementActorTimer(movementActor))
|
|
||||||
.onFailure[Exception](SupervisorStrategy.restart),
|
|
||||||
"playerMovementActorTimer"
|
|
||||||
)
|
|
||||||
|
|
||||||
lazy val playerCameraHandler = {
|
lazy val playerCameraHandler = {
|
||||||
ctx.spawn(
|
ctx.spawn(
|
||||||
Behaviors
|
Behaviors
|
||||||
.supervise(
|
.supervise(playerCamELBehavior)
|
||||||
PlayerCameraEventListener(camNode, enqueueR)
|
|
||||||
)
|
|
||||||
.onFailure[Exception](SupervisorStrategy.restart),
|
.onFailure[Exception](SupervisorStrategy.restart),
|
||||||
"playerCameraHandler"
|
"playerCameraHandler"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//init actors
|
//init actors
|
||||||
movementActorTimer ! MovementActorTimer.Start
|
|
||||||
playerMovementEventBus ! EventBus.Subscribe(
|
|
||||||
playerMovementEventHandler
|
|
||||||
)
|
|
||||||
playerCameraEventBus ! EventBus.Subscribe(playerCameraHandler)
|
playerCameraEventBus ! EventBus.Subscribe(playerCameraHandler)
|
||||||
|
|
||||||
new PlayerActorSupervisor(
|
new PlayerActorSupervisor(
|
||||||
ctx,
|
ctx,
|
||||||
this,
|
this,
|
||||||
Children(movementActor, playerMovementEventHandler)
|
Children(movementActor)
|
||||||
).receive
|
).receive
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case class Children(
|
case class Children(
|
||||||
movementActor: ActorRef[ImMovementActor.Command],
|
movementActor: ActorRef[ImMovementActor.Command]
|
||||||
playerMovementEventHandler: ActorRef[
|
|
||||||
EntityMovementEvent.PlayerMovementEvent
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
class PlayerActorSupervisor[T: CanMove](
|
class PlayerActorSupervisor[T: CanMove](
|
||||||
@ -113,45 +96,38 @@ class PlayerActorSupervisor[T: CanMove](
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MovementActorTimer {
|
object PlayerMovementActor {
|
||||||
sealed trait Command
|
sealed trait Command
|
||||||
final case object Start extends Command
|
final case class Props(
|
||||||
final case object Stop extends Command
|
movementActor: ActorRef[ImMovementActor.Command],
|
||||||
private case object Send extends Command
|
playerMovementEventBus: ActorRef[
|
||||||
case object TimerKey
|
EventBus.Command[PlayerMovementEvent]
|
||||||
|
],
|
||||||
|
tickEventBus: GameEventBus[TickEvent]
|
||||||
|
) {
|
||||||
|
|
||||||
def apply(target: ActorRef[ImMovementActor.Command]) =
|
def create: Behavior[Command] =
|
||||||
Behaviors.withTimers[Command] { timers =>
|
Behaviors.setup { ctx =>
|
||||||
new MovementActorTimer(timers, target).idle
|
val playerMovementEl = ctx.spawn(
|
||||||
}
|
Behaviors
|
||||||
}
|
.supervise(PlayerMovementEventListener(movementActor))
|
||||||
class MovementActorTimer(
|
.onFailure[Exception](SupervisorStrategy.restart),
|
||||||
timers: TimerScheduler[MovementActorTimer.Command],
|
"playerMovementEventHandler"
|
||||||
target: ActorRef[ImMovementActor.Command]
|
)
|
||||||
) {
|
val renderTickElBehavior =
|
||||||
import MovementActorTimer._
|
Behaviors.receiveMessage[RenderTick.type] {
|
||||||
|
case RenderTick =>
|
||||||
val idle: Behavior[Command] =
|
movementActor ! ImMovementActor.Tick
|
||||||
Behaviors.receiveMessage { msg =>
|
|
||||||
msg match {
|
|
||||||
case Start =>
|
|
||||||
timers.startTimerWithFixedDelay(TimerKey, Send, (60f / 144).millis)
|
|
||||||
active
|
|
||||||
case _ => Behaviors.unhandled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val active: Behavior[Command] =
|
|
||||||
Behaviors.receiveMessage { msg =>
|
|
||||||
msg match {
|
|
||||||
case Send =>
|
|
||||||
target ! ImMovementActor.Tick
|
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case Stop =>
|
}
|
||||||
timers.cancel(TimerKey)
|
val renderTickEl =
|
||||||
idle
|
ctx.spawn(renderTickElBehavior, "playerMovementTickListener")
|
||||||
case _ => Behaviors.unhandled
|
|
||||||
|
|
||||||
|
playerMovementEventBus ! EventBus.Subscribe(
|
||||||
|
playerMovementEl
|
||||||
|
)
|
||||||
|
tickEventBus ! EventBus.Subscribe(renderTickEl)
|
||||||
|
Behaviors.receiveMessage { msg => Behaviors.same }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,7 +137,7 @@ object GenericTimerActor {
|
|||||||
final case object Start extends Command
|
final case object Start extends Command
|
||||||
final case object Stop extends Command
|
final case object Stop extends Command
|
||||||
private case object Send extends Command
|
private case object Send extends Command
|
||||||
case object TimerKey
|
case class TimerKey(seed: Long)
|
||||||
|
|
||||||
case class Props[T](
|
case class Props[T](
|
||||||
target: ActorRef[T],
|
target: ActorRef[T],
|
||||||
@ -169,12 +145,13 @@ object GenericTimerActor {
|
|||||||
timeInterval: FiniteDuration
|
timeInterval: FiniteDuration
|
||||||
) {
|
) {
|
||||||
val create = Behaviors.withTimers[Command] { timers =>
|
val create = Behaviors.withTimers[Command] { timers =>
|
||||||
new GenericTimerActor(timers, this).idle
|
new GenericTimerActor(timers, TimerKey(Random.nextLong()), this).idle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class GenericTimerActor[T](
|
class GenericTimerActor[T](
|
||||||
timers: TimerScheduler[GenericTimerActor.Command],
|
timers: TimerScheduler[GenericTimerActor.Command],
|
||||||
|
timerKey: GenericTimerActor.TimerKey,
|
||||||
props: GenericTimerActor.Props[T]
|
props: GenericTimerActor.Props[T]
|
||||||
) {
|
) {
|
||||||
import GenericTimerActor._
|
import GenericTimerActor._
|
||||||
@ -182,7 +159,7 @@ class GenericTimerActor[T](
|
|||||||
val idle: Behavior[Command] =
|
val idle: Behavior[Command] =
|
||||||
Behaviors.receiveMessage {
|
Behaviors.receiveMessage {
|
||||||
case Start =>
|
case Start =>
|
||||||
timers.startTimerWithFixedDelay(TimerKey, Send, props.timeInterval)
|
timers.startTimerWithFixedDelay(timerKey, Send, props.timeInterval)
|
||||||
active
|
active
|
||||||
case _ => Behaviors.unhandled
|
case _ => Behaviors.unhandled
|
||||||
|
|
||||||
@ -194,7 +171,7 @@ class GenericTimerActor[T](
|
|||||||
props.target ! props.messageToSend
|
props.target ! props.messageToSend
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case Stop =>
|
case Stop =>
|
||||||
timers.cancel(TimerKey)
|
timers.cancel(timerKey)
|
||||||
idle
|
idle
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package wow.doge.mygame.game.nodes
|
package wow.doge.mygame.game.entities
|
||||||
|
|
||||||
import akka.actor.typed.scaladsl.ActorContext
|
import akka.actor.typed.scaladsl.ActorContext
|
||||||
import akka.actor.typed.scaladsl.Behaviors
|
import akka.actor.typed.scaladsl.Behaviors
|
@ -0,0 +1,248 @@
|
|||||||
|
package wow.doge.mygame.game.entities
|
||||||
|
|
||||||
|
import akka.actor.typed.ActorRef
|
||||||
|
import akka.actor.typed.Props
|
||||||
|
import akka.actor.typed.Scheduler
|
||||||
|
import akka.actor.typed.SpawnProtocol
|
||||||
|
import akka.util.Timeout
|
||||||
|
import cats.implicits._
|
||||||
|
import com.jme3.asset.AssetManager
|
||||||
|
import com.jme3.bullet.BulletAppState
|
||||||
|
import com.jme3.bullet.PhysicsSpace
|
||||||
|
import com.jme3.bullet.control.BetterCharacterControl
|
||||||
|
import com.jme3.math.FastMath
|
||||||
|
import com.jme3.renderer.Camera
|
||||||
|
import com.jme3.scene.CameraNode
|
||||||
|
import com.jme3.scene.Geometry
|
||||||
|
import com.jme3.scene.Node
|
||||||
|
import com.jme3.scene.control.CameraControl.ControlDirection
|
||||||
|
import com.jme3.scene.shape.Box
|
||||||
|
import com.softwaremill.macwire._
|
||||||
|
import com.softwaremill.tagging._
|
||||||
|
import io.odin.Logger
|
||||||
|
import monix.bio.IO
|
||||||
|
import monix.bio.Task
|
||||||
|
import wow.doge.mygame.game.GameAppTags
|
||||||
|
import wow.doge.mygame.game.SimpleAppExt
|
||||||
|
import wow.doge.mygame.implicits._
|
||||||
|
import wow.doge.mygame.math.ImVector3f
|
||||||
|
import wow.doge.mygame.state.MyMaterial
|
||||||
|
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.subsystems.events.TickEvent
|
||||||
|
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
||||||
|
import wow.doge.mygame.utils.AkkaUtils
|
||||||
|
|
||||||
|
object PlayerControllerTags {
|
||||||
|
sealed trait PlayerTag
|
||||||
|
sealed trait PlayerCameraNode
|
||||||
|
}
|
||||||
|
|
||||||
|
object PlayerController {
|
||||||
|
sealed trait Error
|
||||||
|
case class CouldNotCreatePlayerNode(reason: String) extends Error
|
||||||
|
case class GenericError(reason: String) extends Error
|
||||||
|
|
||||||
|
class Props(
|
||||||
|
enqueueR: Function1[() => Unit, Unit],
|
||||||
|
rootNode: Node @@ GameAppTags.RootNode,
|
||||||
|
loggerL: Logger[Task],
|
||||||
|
physicsSpace: PhysicsSpace,
|
||||||
|
initialPlayerPos: ImVector3f = ImVector3f.ZERO,
|
||||||
|
spawnProtocol: ActorRef[SpawnProtocol.Command],
|
||||||
|
playerMovementEventBus: ActorRef[
|
||||||
|
EventBus.Command[PlayerMovementEvent]
|
||||||
|
],
|
||||||
|
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
|
||||||
|
playerPhysicsControl: BetterCharacterControl,
|
||||||
|
appScheduler: monix.execution.Scheduler,
|
||||||
|
playerNode: Node @@ PlayerControllerTags.PlayerTag,
|
||||||
|
cameraNode: CameraNode @@ PlayerControllerTags.PlayerCameraNode,
|
||||||
|
tickEventBus: GameEventBus[TickEvent]
|
||||||
|
)(implicit timeout: Timeout, scheduler: Scheduler) {
|
||||||
|
val create: IO[Error, Unit] =
|
||||||
|
(for {
|
||||||
|
playerActor <- AkkaUtils.spawnActorL(
|
||||||
|
spawnProtocol,
|
||||||
|
"playerActorSupervisor",
|
||||||
|
new PlayerActorSupervisor.Props(
|
||||||
|
playerMovementEventBus,
|
||||||
|
playerCameraEventBus,
|
||||||
|
tickEventBus,
|
||||||
|
ImMovementActor
|
||||||
|
.Props(enqueueR, playerPhysicsControl)
|
||||||
|
.create,
|
||||||
|
wireWith(PlayerCameraEventListener.apply _)
|
||||||
|
).create(playerPhysicsControl)
|
||||||
|
)
|
||||||
|
_ <- IO {
|
||||||
|
physicsSpace += playerNode
|
||||||
|
physicsSpace += playerPhysicsControl
|
||||||
|
}
|
||||||
|
_ <- Task(rootNode += playerNode)
|
||||||
|
} yield ())
|
||||||
|
.onErrorHandleWith(e => IO.raiseError(GenericError(e.getMessage())))
|
||||||
|
.executeOn(appScheduler)
|
||||||
|
}
|
||||||
|
|
||||||
|
def apply(
|
||||||
|
app: SimpleAppExt,
|
||||||
|
modelPath: os.RelPath,
|
||||||
|
cam: Camera
|
||||||
|
)(assetManager: AssetManager, bulletAppState: BulletAppState) = {
|
||||||
|
lazy val playerPos = ImVector3f.ZERO
|
||||||
|
lazy val playerPhysicsControl = new BetterCharacterControl(1.5f, 6f, 1f)
|
||||||
|
.withJumpForce(ImVector3f(0, 5f, 0))
|
||||||
|
lazy val playerNode = new Node("PlayerNode")
|
||||||
|
.withChildren(
|
||||||
|
assetManager
|
||||||
|
.loadModel(modelPath)
|
||||||
|
.asInstanceOf[Node]
|
||||||
|
.withRotate(0, FastMath.PI, 0)
|
||||||
|
)
|
||||||
|
.withLocalTranslation(playerPos)
|
||||||
|
.withControl(playerPhysicsControl)
|
||||||
|
|
||||||
|
{
|
||||||
|
bulletAppState.physicsSpace += playerNode
|
||||||
|
bulletAppState.physicsSpace += playerPhysicsControl
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
app.rootNode += playerNode
|
||||||
|
}
|
||||||
|
|
||||||
|
playerPhysicsControl
|
||||||
|
}
|
||||||
|
|
||||||
|
object Defaults {
|
||||||
|
def defaultMesh = {
|
||||||
|
val b = Box(1, 1, 1)
|
||||||
|
val geom = Geometry("playerGeom", b)
|
||||||
|
geom
|
||||||
|
}
|
||||||
|
def defaultTexture(assetManager: AssetManager) =
|
||||||
|
MyMaterial(
|
||||||
|
assetManager = assetManager,
|
||||||
|
path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md"
|
||||||
|
)
|
||||||
|
|
||||||
|
def defaultCamerNode(cam: Camera, playerPos: ImVector3f) =
|
||||||
|
new CameraNode("CameraNode", cam)
|
||||||
|
.withControlDir(ControlDirection.SpatialToCamera)
|
||||||
|
.withLocalTranslation(ImVector3f(0, 1.5f, 10))
|
||||||
|
.withLookAt(playerPos, ImVector3f.UNIT_Y)
|
||||||
|
|
||||||
|
def defaultPlayerNode(
|
||||||
|
assetManager: AssetManager,
|
||||||
|
modelPath: os.RelPath,
|
||||||
|
playerPos: ImVector3f,
|
||||||
|
camNode: CameraNode,
|
||||||
|
playerPhysicsControl: BetterCharacterControl
|
||||||
|
) =
|
||||||
|
Either
|
||||||
|
.catchNonFatal(
|
||||||
|
Node("PlayerNode")
|
||||||
|
.withChildren(
|
||||||
|
camNode,
|
||||||
|
assetManager
|
||||||
|
.loadModel(modelPath)
|
||||||
|
.asInstanceOf[Node]
|
||||||
|
.withRotate(0, FastMath.PI, 0)
|
||||||
|
)
|
||||||
|
.withLocalTranslation(playerPos)
|
||||||
|
.withControl(playerPhysicsControl)
|
||||||
|
)
|
||||||
|
.map(_.taggedWith[PlayerControllerTags.PlayerTag])
|
||||||
|
.leftMap(e => PlayerController.CouldNotCreatePlayerNode(e.getMessage()))
|
||||||
|
|
||||||
|
def defaultNpcNode(
|
||||||
|
assetManager: AssetManager,
|
||||||
|
// modelPath: os.RelPath,
|
||||||
|
initialPos: ImVector3f,
|
||||||
|
npcPhysicsControl: BetterCharacterControl,
|
||||||
|
npcName: String
|
||||||
|
) =
|
||||||
|
Either
|
||||||
|
.catchNonFatal(
|
||||||
|
Node(npcName)
|
||||||
|
.withChildren(
|
||||||
|
// assetManager
|
||||||
|
// .loadModel(modelPath)
|
||||||
|
// .asInstanceOf[Node]
|
||||||
|
// .withRotate(0, FastMath.PI, 0)
|
||||||
|
defaultMesh.withMaterial(defaultTexture(assetManager))
|
||||||
|
)
|
||||||
|
.withLocalTranslation(initialPos)
|
||||||
|
.withControl(npcPhysicsControl)
|
||||||
|
)
|
||||||
|
// .map(_.taggedWith[PlayerControllerTags.PlayerTag])
|
||||||
|
// .leftMap(e => PlayerController.CouldNotCreatePlayerNode(e.getMessage()))
|
||||||
|
|
||||||
|
def defaultPlayerPhysicsControl =
|
||||||
|
new BetterCharacterControl(1.5f, 6f, 1f)
|
||||||
|
.withJumpForce(ImVector3f(0, 5f, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Methods {
|
||||||
|
def spawnMovementActor(
|
||||||
|
enqueueR: Function1[() => Unit, Unit],
|
||||||
|
spawnProtocol: ActorRef[SpawnProtocol.Command],
|
||||||
|
movable: BetterCharacterControl @@ PlayerControllerTags.PlayerTag,
|
||||||
|
playerMovementEventBus: ActorRef[
|
||||||
|
EventBus.Command[PlayerMovementEvent]
|
||||||
|
],
|
||||||
|
loggerL: Logger[Task]
|
||||||
|
)(implicit timeout: Timeout, scheduler: Scheduler) =
|
||||||
|
spawnProtocol.askL[ActorRef[ImMovementActor.Command]](
|
||||||
|
SpawnProtocol.Spawn(
|
||||||
|
ImMovementActor.Props(enqueueR, movable).create,
|
||||||
|
"imMovementActor",
|
||||||
|
Props.empty,
|
||||||
|
_
|
||||||
|
)
|
||||||
|
)
|
||||||
|
// def spawnPlayerActor(
|
||||||
|
// app: GameApp,
|
||||||
|
// spawnProtocol: ActorRef[SpawnProtocol.Command],
|
||||||
|
// movable: BetterCharacterControl @@ Player,
|
||||||
|
// playerMovementEventBus: ActorRef[
|
||||||
|
// EventBus.Command[PlayerMovementEvent]
|
||||||
|
// ]
|
||||||
|
// )(implicit timeout: Timeout, scheduler: Scheduler) =
|
||||||
|
// spawnProtocol.askL[ActorRef[PlayerActorSupervisor.Command]](
|
||||||
|
// SpawnProtocol.Spawn(
|
||||||
|
// new PlayerActorSupervisor.Props(
|
||||||
|
// app,
|
||||||
|
// movable,
|
||||||
|
// playerMovementEventBus
|
||||||
|
// ).create,
|
||||||
|
// "playerActor",
|
||||||
|
// Props.empty,
|
||||||
|
// _
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
|
||||||
|
// camNode <- IO(
|
||||||
|
// _cameraNode.getOrElse(defaultCamerNode(camera, initialPlayerPos))
|
||||||
|
// )
|
||||||
|
// playerPhysicsControl <- IO(
|
||||||
|
// _playerPhysicsControl
|
||||||
|
// .getOrElse(defaultPlayerPhysicsControl)
|
||||||
|
// .taggedWith[PlayerTag]
|
||||||
|
// )
|
||||||
|
// playerNode <- IO.fromEither(
|
||||||
|
// _playerNode.fold(
|
||||||
|
// defaultPlayerNode(
|
||||||
|
// assetManager,
|
||||||
|
// modelPath,
|
||||||
|
// initialPlayerPos,
|
||||||
|
// camNode,
|
||||||
|
// playerPhysicsControl
|
||||||
|
// )
|
||||||
|
// )(_.asRight)
|
||||||
|
// )
|
@ -1,4 +1,4 @@
|
|||||||
package wow.doge.mygame.game.nodes
|
package wow.doge.mygame.game.entities
|
||||||
|
|
||||||
import akka.actor.typed.ActorRef
|
import akka.actor.typed.ActorRef
|
||||||
import akka.actor.typed.LogOptions
|
import akka.actor.typed.LogOptions
|
||||||
@ -6,10 +6,10 @@ import akka.actor.typed.scaladsl.Behaviors
|
|||||||
import com.jme3.scene.CameraNode
|
import com.jme3.scene.CameraNode
|
||||||
import com.typesafe.scalalogging.Logger
|
import com.typesafe.scalalogging.Logger
|
||||||
import org.slf4j.event.Level
|
import org.slf4j.event.Level
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
|
|
||||||
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
||||||
import wow.doge.mygame.subsystems.events.PlayerCameraEvent.CameraMovedDown
|
import wow.doge.mygame.subsystems.events.PlayerCameraEvent.CameraMovedDown
|
||||||
import wow.doge.mygame.subsystems.events.PlayerCameraEvent.CameraMovedUp
|
import wow.doge.mygame.subsystems.events.PlayerCameraEvent.CameraMovedUp
|
||||||
|
import wow.doge.mygame.subsystems.events.PlayerMovementEvent
|
||||||
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
||||||
|
|
||||||
object PlayerMovementEventListener {
|
object PlayerMovementEventListener {
|
||||||
@ -39,11 +39,9 @@ object PlayerMovementEventListener {
|
|||||||
movementActor ! ImMovementActor.Jump
|
movementActor ! ImMovementActor.Jump
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case PlayerRotatedRight =>
|
case PlayerRotatedRight =>
|
||||||
// ctx.log.warn("right rotate not implemented yet")
|
|
||||||
movementActor ! ImMovementActor.RotateRight
|
movementActor ! ImMovementActor.RotateRight
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case PlayerRotatedLeft =>
|
case PlayerRotatedLeft =>
|
||||||
// ctx.log.warn("left rotate not implemented yet")
|
|
||||||
movementActor ! ImMovementActor.RotateLeft
|
movementActor ! ImMovementActor.RotateLeft
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case PlayerCameraUp =>
|
case PlayerCameraUp =>
|
@ -1,222 +0,0 @@
|
|||||||
package wow.doge.mygame.game.nodes
|
|
||||||
|
|
||||||
import akka.actor.typed.ActorRef
|
|
||||||
import akka.actor.typed.Props
|
|
||||||
import akka.actor.typed.Scheduler
|
|
||||||
import akka.actor.typed.SpawnProtocol
|
|
||||||
import akka.util.Timeout
|
|
||||||
import cats.effect.concurrent.Ref
|
|
||||||
import cats.implicits._
|
|
||||||
import com.jme3.asset.AssetManager
|
|
||||||
import com.jme3.bullet.BulletAppState
|
|
||||||
import com.jme3.bullet.control.BetterCharacterControl
|
|
||||||
import com.jme3.math.FastMath
|
|
||||||
import com.jme3.renderer.Camera
|
|
||||||
import com.jme3.scene.CameraNode
|
|
||||||
import com.jme3.scene.Geometry
|
|
||||||
import com.jme3.scene.Node
|
|
||||||
import com.jme3.scene.control.CameraControl.ControlDirection
|
|
||||||
import com.jme3.scene.shape.Box
|
|
||||||
import com.softwaremill.tagging._
|
|
||||||
import io.odin.Logger
|
|
||||||
import monix.bio.IO
|
|
||||||
import monix.bio.Task
|
|
||||||
import wow.doge.mygame.events.EventBus
|
|
||||||
import wow.doge.mygame.game.GameApp
|
|
||||||
import wow.doge.mygame.implicits._
|
|
||||||
import wow.doge.mygame.math.ImVector3f
|
|
||||||
import wow.doge.mygame.state.MyMaterial
|
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
|
|
||||||
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
|
|
||||||
import wow.doge.mygame.subsystems.movement.ImMovementActor
|
|
||||||
import wow.doge.mygame.utils.AkkaUtils
|
|
||||||
|
|
||||||
// class PlayerNode(val name: String) extends Node(name) {}
|
|
||||||
sealed trait PlayerTag
|
|
||||||
sealed trait PlayerCameraNode
|
|
||||||
|
|
||||||
object PlayerController {
|
|
||||||
sealed trait Error
|
|
||||||
case class GenericError(reason: String) extends Error
|
|
||||||
|
|
||||||
class Props(
|
|
||||||
enqueueR: Function1[() => Unit, Unit],
|
|
||||||
rootNode: Ref[Task, Node],
|
|
||||||
camera: Camera,
|
|
||||||
loggerL: Logger[Task],
|
|
||||||
assetManager: AssetManager,
|
|
||||||
bulletAppState: BulletAppState,
|
|
||||||
initialPlayerPos: ImVector3f = ImVector3f.ZERO,
|
|
||||||
modelPath: os.RelPath,
|
|
||||||
spawnProtocol: ActorRef[SpawnProtocol.Command],
|
|
||||||
playerMovementEventBus: ActorRef[
|
|
||||||
EventBus.Command[PlayerMovementEvent]
|
|
||||||
],
|
|
||||||
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
|
|
||||||
_playerPhysicsControl: Option[BetterCharacterControl],
|
|
||||||
_playerNode: Option[Node with PlayerTag] = None,
|
|
||||||
_cameraNode: Option[CameraNode with PlayerCameraNode] = None,
|
|
||||||
appScheduler: monix.execution.Scheduler
|
|
||||||
)(implicit timeout: Timeout, scheduler: Scheduler) {
|
|
||||||
import Defaults._
|
|
||||||
val create: IO[Error, Unit] =
|
|
||||||
// IO.raiseError(GenericError("not implemented yet"))
|
|
||||||
(for {
|
|
||||||
camNode <- IO(
|
|
||||||
_cameraNode.getOrElse(defaultCamerNode(camera, initialPlayerPos))
|
|
||||||
)
|
|
||||||
playerPhysicsControl <- IO(
|
|
||||||
_playerPhysicsControl
|
|
||||||
.getOrElse(defaultPlayerPhysicsControl)
|
|
||||||
.taggedWith[PlayerTag]
|
|
||||||
)
|
|
||||||
playerNode <- IO.fromEither(
|
|
||||||
_playerNode.fold(
|
|
||||||
defaultPlayerNode(
|
|
||||||
assetManager,
|
|
||||||
modelPath,
|
|
||||||
initialPlayerPos,
|
|
||||||
camNode,
|
|
||||||
playerPhysicsControl
|
|
||||||
)
|
|
||||||
)(_.asRight)
|
|
||||||
)
|
|
||||||
playerActor <- AkkaUtils.spawnActorL(
|
|
||||||
spawnProtocol,
|
|
||||||
"playerActorSupervisor",
|
|
||||||
new PlayerActorSupervisor.Props(
|
|
||||||
enqueueR,
|
|
||||||
camNode,
|
|
||||||
playerMovementEventBus,
|
|
||||||
playerCameraEventBus
|
|
||||||
).create(playerPhysicsControl)
|
|
||||||
)
|
|
||||||
_ <- IO {
|
|
||||||
bulletAppState.physicsSpace += playerNode
|
|
||||||
bulletAppState.physicsSpace += playerPhysicsControl
|
|
||||||
}
|
|
||||||
_ <- rootNode.update(_ :+ playerNode)
|
|
||||||
} yield ())
|
|
||||||
.onErrorHandleWith(e => IO.raiseError(GenericError(e.getMessage())))
|
|
||||||
.executeOn(appScheduler)
|
|
||||||
}
|
|
||||||
|
|
||||||
def apply(
|
|
||||||
app: GameApp,
|
|
||||||
modelPath: os.RelPath,
|
|
||||||
cam: Camera
|
|
||||||
)(assetManager: AssetManager, bulletAppState: BulletAppState) = {
|
|
||||||
lazy val playerPos = ImVector3f.ZERO
|
|
||||||
lazy val playerPhysicsControl = new BetterCharacterControl(1.5f, 6f, 1f)
|
|
||||||
.withJumpForce(ImVector3f(0, 5f, 0))
|
|
||||||
lazy val playerNode = new Node("PlayerNode")
|
|
||||||
.withChildren(
|
|
||||||
assetManager
|
|
||||||
.loadModel(modelPath)
|
|
||||||
.asInstanceOf[Node]
|
|
||||||
.withRotate(0, FastMath.PI, 0)
|
|
||||||
)
|
|
||||||
.withLocalTranslation(playerPos)
|
|
||||||
.withControl(playerPhysicsControl)
|
|
||||||
|
|
||||||
{
|
|
||||||
bulletAppState.physicsSpace += playerNode
|
|
||||||
bulletAppState.physicsSpace += playerPhysicsControl
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
app.rootNode += playerNode
|
|
||||||
}
|
|
||||||
|
|
||||||
playerPhysicsControl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object Defaults {
|
|
||||||
lazy val defaultMesh = {
|
|
||||||
val b = Box(1, 1, 1)
|
|
||||||
val geom = Geometry("playerMesh", b)
|
|
||||||
geom
|
|
||||||
}
|
|
||||||
def defaultTexture(assetManager: AssetManager) =
|
|
||||||
MyMaterial(
|
|
||||||
assetManager = assetManager,
|
|
||||||
path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md"
|
|
||||||
)
|
|
||||||
|
|
||||||
def defaultCamerNode(cam: Camera, playerPos: ImVector3f) =
|
|
||||||
new CameraNode("CameraNode", cam)
|
|
||||||
.withControlDir(ControlDirection.SpatialToCamera)
|
|
||||||
.withLocalTranslation(ImVector3f(0, 1.5f, 10))
|
|
||||||
.withLookAt(playerPos, ImVector3f.UNIT_Y)
|
|
||||||
|
|
||||||
def defaultPlayerNode(
|
|
||||||
assetManager: AssetManager,
|
|
||||||
modelPath: os.RelPath,
|
|
||||||
playerPos: ImVector3f,
|
|
||||||
camNode: CameraNode,
|
|
||||||
playerPhysicsControl: BetterCharacterControl
|
|
||||||
) =
|
|
||||||
Either.catchNonFatal(
|
|
||||||
Node("PlayerNode")
|
|
||||||
.withChildren(
|
|
||||||
camNode,
|
|
||||||
assetManager
|
|
||||||
.loadModel(modelPath)
|
|
||||||
.asInstanceOf[Node]
|
|
||||||
.withRotate(0, FastMath.PI, 0)
|
|
||||||
)
|
|
||||||
.withLocalTranslation(playerPos)
|
|
||||||
.withControl(playerPhysicsControl)
|
|
||||||
)
|
|
||||||
|
|
||||||
lazy val defaultPlayerPhysicsControl =
|
|
||||||
new BetterCharacterControl(1.5f, 6f, 1f)
|
|
||||||
.withJumpForce(ImVector3f(0, 5f, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
object Methods {
|
|
||||||
def spawnMovementActor(
|
|
||||||
enqueueR: Function1[() => Unit, Unit],
|
|
||||||
spawnProtocol: ActorRef[SpawnProtocol.Command],
|
|
||||||
movable: BetterCharacterControl @@ PlayerTag,
|
|
||||||
playerMovementEventBus: ActorRef[
|
|
||||||
EventBus.Command[PlayerMovementEvent]
|
|
||||||
],
|
|
||||||
loggerL: Logger[Task]
|
|
||||||
)(implicit timeout: Timeout, scheduler: Scheduler) =
|
|
||||||
spawnProtocol.askL[ActorRef[ImMovementActor.Command]](
|
|
||||||
SpawnProtocol.Spawn(
|
|
||||||
ImMovementActor.Props(enqueueR, movable, playerMovementEventBus).create,
|
|
||||||
"imMovementActor",
|
|
||||||
Props.empty,
|
|
||||||
_
|
|
||||||
)
|
|
||||||
)
|
|
||||||
// def spawnPlayerActor(
|
|
||||||
// app: GameApp,
|
|
||||||
// spawnProtocol: ActorRef[SpawnProtocol.Command],
|
|
||||||
// movable: BetterCharacterControl @@ Player,
|
|
||||||
// playerMovementEventBus: ActorRef[
|
|
||||||
// EventBus.Command[PlayerMovementEvent]
|
|
||||||
// ]
|
|
||||||
// )(implicit timeout: Timeout, scheduler: Scheduler) =
|
|
||||||
// spawnProtocol.askL[ActorRef[PlayerActorSupervisor.Command]](
|
|
||||||
// SpawnProtocol.Spawn(
|
|
||||||
// new PlayerActorSupervisor.Props(
|
|
||||||
// app,
|
|
||||||
// movable,
|
|
||||||
// playerMovementEventBus
|
|
||||||
// ).create,
|
|
||||||
// "playerActor",
|
|
||||||
// Props.empty,
|
|
||||||
// _
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
}
|
|
||||||
// spawnPlayerActor(
|
|
||||||
// app,
|
|
||||||
// spawnProtocol,
|
|
||||||
// playerPhysicsControl,
|
|
||||||
// playerMovementEventBus
|
|
||||||
// )
|
|
@ -1,8 +1,13 @@
|
|||||||
package wow.doge.mygame.game.subsystems.ai
|
package wow.doge.mygame.game.subsystems.ai
|
||||||
|
|
||||||
|
import scala.collection.immutable.ArraySeq
|
||||||
|
|
||||||
import com.badlogic.gdx.ai.pfa.Connection
|
import com.badlogic.gdx.ai.pfa.Connection
|
||||||
import wow.doge.mygame.game.subsystems.ai.gdx.MyIndexedGraph
|
import wow.doge.mygame.game.subsystems.ai.gdx.MyIndexedGraph
|
||||||
import scala.collection.immutable.ArraySeq
|
import com.badlogic.gdx.ai.steer.Steerable
|
||||||
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import com.badlogic.gdx.ai.utils.Location
|
||||||
|
import com.badlogic.gdx.ai.steer.behaviors.Arrive
|
||||||
// import com.badlogic.gdx.ai.pfa.indexed.IndexedGraph
|
// import com.badlogic.gdx.ai.pfa.indexed.IndexedGraph
|
||||||
// import scala.jdk.javaapi.CollectionConverters._
|
// import scala.jdk.javaapi.CollectionConverters._
|
||||||
|
|
||||||
@ -31,3 +36,50 @@ class CityGraph extends MyIndexedGraph[City] {
|
|||||||
override def getNodeCount(): Int = ???
|
override def getNodeCount(): Int = ???
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MySteerable extends Steerable[Vector3] {
|
||||||
|
val arrive = new Arrive[Vector3](this)
|
||||||
|
|
||||||
|
override def getPosition(): Vector3 = ???
|
||||||
|
|
||||||
|
override def getOrientation(): Float = ???
|
||||||
|
|
||||||
|
override def setOrientation(x$1: Float): Unit = ???
|
||||||
|
|
||||||
|
override def vectorToAngle(x$1: Vector3): Float = ???
|
||||||
|
|
||||||
|
override def angleToVector(x$1: Vector3, x$2: Float): Vector3 = ???
|
||||||
|
|
||||||
|
override def newLocation(): Location[Vector3] = ???
|
||||||
|
|
||||||
|
override def getZeroLinearSpeedThreshold(): Float = ???
|
||||||
|
|
||||||
|
override def setZeroLinearSpeedThreshold(x$1: Float): Unit = ???
|
||||||
|
|
||||||
|
override def getMaxLinearSpeed(): Float = ???
|
||||||
|
|
||||||
|
override def setMaxLinearSpeed(x$1: Float): Unit = ???
|
||||||
|
|
||||||
|
override def getMaxLinearAcceleration(): Float = ???
|
||||||
|
|
||||||
|
override def setMaxLinearAcceleration(x$1: Float): Unit = ???
|
||||||
|
|
||||||
|
override def getMaxAngularSpeed(): Float = ???
|
||||||
|
|
||||||
|
override def setMaxAngularSpeed(x$1: Float): Unit = ???
|
||||||
|
|
||||||
|
override def getMaxAngularAcceleration(): Float = ???
|
||||||
|
|
||||||
|
override def setMaxAngularAcceleration(x$1: Float): Unit = ???
|
||||||
|
|
||||||
|
override def getLinearVelocity(): Vector3 = ???
|
||||||
|
|
||||||
|
override def getAngularVelocity(): Float = ???
|
||||||
|
|
||||||
|
override def getBoundingRadius(): Float = ???
|
||||||
|
|
||||||
|
override def isTagged(): Boolean = ???
|
||||||
|
|
||||||
|
override def setTagged(x$1: Boolean): Unit = ???
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -9,20 +9,20 @@ import com.jme3.input.MouseInput
|
|||||||
import com.jme3.input.controls.KeyTrigger
|
import com.jme3.input.controls.KeyTrigger
|
||||||
import com.jme3.input.controls.MouseAxisTrigger
|
import com.jme3.input.controls.MouseAxisTrigger
|
||||||
import monix.bio.UIO
|
import monix.bio.UIO
|
||||||
import wow.doge.mygame.events.EventBus
|
|
||||||
import wow.doge.mygame.implicits._
|
import wow.doge.mygame.implicits._
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
|
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.PlayerCameraEvent
|
||||||
|
import wow.doge.mygame.subsystems.events.PlayerMovementEvent
|
||||||
import wow.doge.mygame.utils.IOUtils._
|
import wow.doge.mygame.utils.IOUtils._
|
||||||
|
|
||||||
object GameInputHandler {
|
object GameInputHandler {
|
||||||
|
|
||||||
final case class Props(
|
final case class Props(
|
||||||
inputManager: InputManager,
|
inputManager: InputManager,
|
||||||
playerMovementEventBus: ActorRef[
|
playerMovementEventBus: GameEventBus[PlayerMovementEvent],
|
||||||
EventBus.Command[PlayerMovementEvent]
|
playerCameraEventBus: GameEventBus[PlayerCameraEvent]
|
||||||
],
|
// tickEventBus: GameEventBus[TickEvent]
|
||||||
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
|
|
||||||
) {
|
) {
|
||||||
def begin =
|
def begin =
|
||||||
for {
|
for {
|
||||||
@ -66,12 +66,12 @@ object GameInputHandler {
|
|||||||
def setupKeys(inputManager: InputManager) =
|
def setupKeys(inputManager: InputManager) =
|
||||||
inputManager
|
inputManager
|
||||||
.withMapping(
|
.withMapping(
|
||||||
PlayerAnalogInput.TurnRight.entryName,
|
PlayerAnalogMovementInput.TurnRight.entryName,
|
||||||
new KeyTrigger(KeyInput.KEY_RIGHT),
|
new KeyTrigger(KeyInput.KEY_RIGHT),
|
||||||
new MouseAxisTrigger(MouseInput.AXIS_X, true)
|
new MouseAxisTrigger(MouseInput.AXIS_X, true)
|
||||||
)
|
)
|
||||||
.withMapping(
|
.withMapping(
|
||||||
PlayerAnalogInput.TurnLeft.entryName,
|
PlayerAnalogMovementInput.TurnLeft.entryName,
|
||||||
new KeyTrigger(KeyInput.KEY_LEFT),
|
new KeyTrigger(KeyInput.KEY_LEFT),
|
||||||
new MouseAxisTrigger(MouseInput.AXIS_X, false)
|
new MouseAxisTrigger(MouseInput.AXIS_X, false)
|
||||||
)
|
)
|
||||||
@ -85,7 +85,6 @@ object GameInputHandler {
|
|||||||
// new KeyTrigger(KeyInput.KEY_LEFT),
|
// new KeyTrigger(KeyInput.KEY_LEFT),
|
||||||
new MouseAxisTrigger(MouseInput.AXIS_Y, true)
|
new MouseAxisTrigger(MouseInput.AXIS_Y, true)
|
||||||
)
|
)
|
||||||
.setCursorVisible(false)
|
|
||||||
|
|
||||||
def generateMovementInputEvents(
|
def generateMovementInputEvents(
|
||||||
inputManager: InputManager,
|
inputManager: InputManager,
|
||||||
@ -148,19 +147,18 @@ object GameInputHandler {
|
|||||||
) = {
|
) = {
|
||||||
val name = "rotateMovementEventsGenerator"
|
val name = "rotateMovementEventsGenerator"
|
||||||
inputManager
|
inputManager
|
||||||
.enumAnalogObservable(PlayerAnalogInput)
|
.enumAnalogObservable(PlayerAnalogMovementInput)
|
||||||
.sample(1.millis)
|
.sample(1.millis)
|
||||||
// .map(e => e)
|
|
||||||
.doOnNext(analogEvent =>
|
.doOnNext(analogEvent =>
|
||||||
analogEvent.binding match {
|
analogEvent.binding match {
|
||||||
case PlayerAnalogInput.TurnRight =>
|
case PlayerAnalogMovementInput.TurnRight =>
|
||||||
toTask(
|
toTask(
|
||||||
playerMovementEventBus !! EventBus.Publish(
|
playerMovementEventBus !! EventBus.Publish(
|
||||||
PlayerMovementEvent.PlayerRotatedRight,
|
PlayerMovementEvent.PlayerRotatedRight,
|
||||||
name
|
name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
case PlayerAnalogInput.TurnLeft =>
|
case PlayerAnalogMovementInput.TurnLeft =>
|
||||||
toTask(
|
toTask(
|
||||||
playerMovementEventBus !! EventBus.Publish(
|
playerMovementEventBus !! EventBus.Publish(
|
||||||
PlayerMovementEvent.PlayerRotatedLeft,
|
PlayerMovementEvent.PlayerRotatedLeft,
|
||||||
@ -179,7 +177,7 @@ object GameInputHandler {
|
|||||||
inputManager
|
inputManager
|
||||||
.analogObservable("CAMERA_UP", "CAMERA_DOWN")
|
.analogObservable("CAMERA_UP", "CAMERA_DOWN")
|
||||||
.sample(1.millis)
|
.sample(1.millis)
|
||||||
.mapEval(analogEvent =>
|
.doOnNext(analogEvent =>
|
||||||
analogEvent.binding.name match {
|
analogEvent.binding.name match {
|
||||||
case "CAMERA_UP" =>
|
case "CAMERA_UP" =>
|
||||||
toTask(
|
toTask(
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
package wow.doge.mygame.game.subsystems.input
|
|
||||||
|
|
||||||
object InputConstants {
|
|
||||||
val PLAYER_MOVE_LEFT = "PLAYER_MOVE_LEFT"
|
|
||||||
val PLAYER_MOVE_RIGHT = "PLAYER_MOVE_RIGHT"
|
|
||||||
val PLAYER_MOVE_FORWARD = "PLAYER_MOVE_FORWARD"
|
|
||||||
val PLAYER_MOVE_BACKWARD = "PLAYER_MOVE_BACKWARD"
|
|
||||||
val PLAYER_JUMP = "PLAYER_JUMP "
|
|
||||||
}
|
|
@ -12,9 +12,9 @@ object PlayerMovementInput extends Enum[PlayerMovementInput] {
|
|||||||
case object Jump extends PlayerMovementInput
|
case object Jump extends PlayerMovementInput
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait PlayerAnalogInput extends EnumEntry with UpperSnakecase
|
sealed trait PlayerAnalogMovementInput extends EnumEntry with UpperSnakecase
|
||||||
object PlayerAnalogInput extends Enum[PlayerAnalogInput] {
|
object PlayerAnalogMovementInput extends Enum[PlayerAnalogMovementInput] {
|
||||||
val values = findValues
|
val values = findValues
|
||||||
case object TurnRight extends PlayerAnalogInput
|
case object TurnRight extends PlayerAnalogMovementInput
|
||||||
case object TurnLeft extends PlayerAnalogInput
|
case object TurnLeft extends PlayerAnalogMovementInput
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package wow.doge.mygame.game.subsystems.level
|
package wow.doge.mygame.game.subsystems.level
|
||||||
|
|
||||||
|
import com.jme3.bullet.PhysicsSpace
|
||||||
import com.jme3.bullet.control.RigidBodyControl
|
import com.jme3.bullet.control.RigidBodyControl
|
||||||
import com.jme3.light.AmbientLight
|
import com.jme3.light.AmbientLight
|
||||||
import com.jme3.light.DirectionalLight
|
import com.jme3.light.DirectionalLight
|
||||||
import com.jme3.scene.Spatial
|
|
||||||
import com.jme3.bullet.PhysicsSpace
|
|
||||||
import cats.effect.concurrent.Ref
|
|
||||||
import monix.bio.Task
|
|
||||||
import com.jme3.scene.Node
|
import com.jme3.scene.Node
|
||||||
|
import com.jme3.scene.Spatial
|
||||||
|
import com.softwaremill.tagging._
|
||||||
|
import monix.bio.Task
|
||||||
|
import wow.doge.mygame.game.GameAppTags
|
||||||
import wow.doge.mygame.implicits._
|
import wow.doge.mygame.implicits._
|
||||||
|
|
||||||
class GameLevel(
|
class GameLevel(
|
||||||
@ -16,11 +17,14 @@ class GameLevel(
|
|||||||
ambientLight: AmbientLight,
|
ambientLight: AmbientLight,
|
||||||
directionalLight: DirectionalLight
|
directionalLight: DirectionalLight
|
||||||
) {
|
) {
|
||||||
def addToGame(rootNode: Ref[Task, Node], physicsSpace: PhysicsSpace) = {
|
def addToGame(
|
||||||
|
rootNode: Node @@ GameAppTags.RootNode,
|
||||||
|
physicsSpace: PhysicsSpace
|
||||||
|
) = {
|
||||||
for {
|
for {
|
||||||
_ <- rootNode.update(_ :+ model)
|
_ <- Task(rootNode += model)
|
||||||
_ <- rootNode.update(_ :+ ambientLight)
|
_ <- Task(rootNode :+ ambientLight)
|
||||||
_ <- rootNode.update(_ :+ directionalLight)
|
_ <- Task(rootNode :+ directionalLight)
|
||||||
_ <- Task(physicsSpace += model)
|
_ <- Task(physicsSpace += model)
|
||||||
_ <- Task(physicsSpace += physicsControl)
|
_ <- Task(physicsSpace += physicsControl)
|
||||||
} yield ()
|
} yield ()
|
||||||
|
@ -13,6 +13,7 @@ import wow.doge.mygame.subsystems.movement.RotateDir
|
|||||||
trait CanMove[-A] {
|
trait CanMove[-A] {
|
||||||
// def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f
|
// def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f
|
||||||
def move(inst: A, direction: ImVector3f): Unit
|
def move(inst: A, direction: ImVector3f): Unit
|
||||||
|
def location(inst: A): ImVector3f
|
||||||
def jump(inst: A): Unit
|
def jump(inst: A): Unit
|
||||||
def stop(inst: A): Unit
|
def stop(inst: A): Unit
|
||||||
def rotate(inst: A, rotateDir: RotateDir): Unit
|
def rotate(inst: A, rotateDir: RotateDir): Unit
|
||||||
@ -30,6 +31,8 @@ object CanMove {
|
|||||||
// inst.setViewDirection(direction.mutable)
|
// inst.setViewDirection(direction.mutable)
|
||||||
inst.setWalkDirection(direction.mutable.multLocal(50f))
|
inst.setWalkDirection(direction.mutable.multLocal(50f))
|
||||||
}
|
}
|
||||||
|
override def location(inst: BetterCharacterControl) =
|
||||||
|
inst.getSpatial().getLocalTranslation().immutable
|
||||||
override def jump(inst: BetterCharacterControl): Unit = inst.jump()
|
override def jump(inst: BetterCharacterControl): Unit = inst.jump()
|
||||||
override def rotate(
|
override def rotate(
|
||||||
inst: BetterCharacterControl,
|
inst: BetterCharacterControl,
|
||||||
@ -39,10 +42,10 @@ object CanMove {
|
|||||||
rotateDir match {
|
rotateDir match {
|
||||||
case RotateDir.Left =>
|
case RotateDir.Left =>
|
||||||
new Quaternion()
|
new Quaternion()
|
||||||
.fromAngleAxis(-10f * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y)
|
.fromAngleAxis(-5 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y)
|
||||||
case RotateDir.Right =>
|
case RotateDir.Right =>
|
||||||
new Quaternion()
|
new Quaternion()
|
||||||
.fromAngleAxis(10 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y)
|
.fromAngleAxis(5 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
val tmp = new Vector3f()
|
val tmp = new Vector3f()
|
||||||
@ -57,6 +60,8 @@ object CanMove {
|
|||||||
override def move(inst: Spatial, direction: ImVector3f): Unit = {
|
override def move(inst: Spatial, direction: ImVector3f): Unit = {
|
||||||
inst.move(direction.mutable)
|
inst.move(direction.mutable)
|
||||||
}
|
}
|
||||||
|
override def location(inst: Spatial) =
|
||||||
|
inst.getLocalTranslation().immutable
|
||||||
override def jump(inst: Spatial): Unit =
|
override def jump(inst: Spatial): Unit =
|
||||||
logger.warn("`Jump` is not implemented for type `Spatial`")
|
logger.warn("`Jump` is not implemented for type `Spatial`")
|
||||||
override def rotate(inst: Spatial, rotateDir: RotateDir): Unit = {
|
override def rotate(inst: Spatial, rotateDir: RotateDir): Unit = {
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
package wow.doge.mygame.subsystems.movement
|
package wow.doge.mygame.subsystems.movement
|
||||||
|
|
||||||
import akka.actor.typed.ActorRef
|
|
||||||
import akka.actor.typed.Behavior
|
import akka.actor.typed.Behavior
|
||||||
import akka.actor.typed.scaladsl.ActorContext
|
import akka.actor.typed.scaladsl.ActorContext
|
||||||
import akka.actor.typed.scaladsl.Behaviors
|
import akka.actor.typed.scaladsl.Behaviors
|
||||||
import com.jme3.math.Vector3f
|
import com.jme3.math.Vector3f
|
||||||
import com.softwaremill.quicklens._
|
import com.softwaremill.quicklens._
|
||||||
import wow.doge.mygame.events.EventBus
|
|
||||||
import wow.doge.mygame.game.subsystems.movement.CanMove
|
import wow.doge.mygame.game.subsystems.movement.CanMove
|
||||||
import wow.doge.mygame.implicits._
|
import wow.doge.mygame.implicits._
|
||||||
import wow.doge.mygame.math.ImVector3f
|
import wow.doge.mygame.math.ImVector3f
|
||||||
import wow.doge.mygame.state.CardinalDirection
|
import wow.doge.mygame.state.CardinalDirection
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
|
|
||||||
|
|
||||||
sealed trait RotateDir
|
sealed trait RotateDir
|
||||||
object RotateDir {
|
object RotateDir {
|
||||||
@ -35,21 +32,13 @@ object ImMovementActor {
|
|||||||
|
|
||||||
final case class Props[T: CanMove](
|
final case class Props[T: CanMove](
|
||||||
enqueueR: Function1[() => Unit, Unit],
|
enqueueR: Function1[() => Unit, Unit],
|
||||||
movable: T,
|
movable: T
|
||||||
playerMovementEventBus: ActorRef[
|
// playerMovementEventBus: ActorRef[
|
||||||
EventBus.Command[PlayerMovementEvent]
|
// EventBus.Command[PlayerMovementEvent]
|
||||||
]
|
// ]
|
||||||
) {
|
) {
|
||||||
def create: Behavior[Command] =
|
def create: Behavior[Command] =
|
||||||
Behaviors.setup(ctx => {
|
Behaviors.setup(ctx => new ImMovementActor(ctx, this).receive(State()))
|
||||||
ctx.log.info("Hello from MovementActor")
|
|
||||||
// val playerMovementEventHandler = ctx.spawn(
|
|
||||||
// PlayerMovementEventHandler(ctx.self),
|
|
||||||
// "playerMovementEventHandler"
|
|
||||||
// )
|
|
||||||
// playerMovementEventBus ! EventBus.Subscribe(playerMovementEventHandler)
|
|
||||||
new ImMovementActor(ctx, this).receive(State())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,19 +48,6 @@ object ImMovementActor {
|
|||||||
*/
|
*/
|
||||||
final case class State(cardinalDir: CardinalDirection = CardinalDirection())
|
final case class State(cardinalDir: CardinalDirection = CardinalDirection())
|
||||||
|
|
||||||
// def apply[T: CanMove](props: Props[T]): Behavior[Command] =
|
|
||||||
// Behaviors.setup(ctx => {
|
|
||||||
// ctx.log.info("Hello from MovementActor")
|
|
||||||
// val playerMovementEventHandler = ctx.spawn(
|
|
||||||
// PlayerMovementEventHandler(ctx.self),
|
|
||||||
// "playerMovementEventHandler"
|
|
||||||
// )
|
|
||||||
// props.playerMovementEventBus ! EventBus.Subscribe(
|
|
||||||
// playerMovementEventHandler
|
|
||||||
// )
|
|
||||||
// new ImMovementActor(ctx, props).receive(State())
|
|
||||||
// })
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImMovementActor[T](
|
class ImMovementActor[T](
|
||||||
|
@ -1,43 +1,15 @@
|
|||||||
package wow.doge.mygame.game.subsystems.ui
|
package wow.doge.mygame.game.subsystems.ui
|
||||||
|
|
||||||
import com.jme3.app.Application
|
|
||||||
import com.jayfella.jme.jfx.JavaFxUI
|
|
||||||
import scalafx.application.Platform
|
|
||||||
import monix.execution.CancelablePromise
|
|
||||||
import monix.bio.Task
|
|
||||||
import cats.effect.concurrent.Deferred
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import wow.doge.mygame.game.GameApp
|
|
||||||
|
import com.jayfella.jme.jfx.JavaFxUI
|
||||||
|
import monix.bio.Task
|
||||||
|
import wow.doge.mygame.game.SimpleAppExt
|
||||||
|
|
||||||
object JFxUI {
|
object JFxUI {
|
||||||
def apply(app: GameApp) =
|
def apply(app: SimpleAppExt) =
|
||||||
Task(JavaFxUI.initialize(app))
|
Task(JavaFxUI.initialize(app))
|
||||||
.executeOn(app.scheduler) >> Task.sleep(500.millis) >> Task(
|
.executeOn(app.scheduler) >> Task.sleep(500.millis) >> Task(
|
||||||
JavaFxUI.getInstance()
|
JavaFxUI.getInstance()
|
||||||
)
|
)
|
||||||
// Task {
|
|
||||||
// Platform.runLater(() => {
|
|
||||||
// println("here jfx")
|
|
||||||
// JavaFxUI.initialize(app)
|
|
||||||
// println("here2 jfx2")
|
|
||||||
// val inst = JavaFxUI.getInstance()
|
|
||||||
// println(inst)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// Task.fromFuture {
|
|
||||||
// val p = CancelablePromise[JavaFxUI]()
|
|
||||||
// Platform.runLater(() => {
|
|
||||||
// println("here")
|
|
||||||
// JavaFxUI.initialize(app)
|
|
||||||
// println("here2")
|
|
||||||
// val inst = JavaFxUI.getInstance()
|
|
||||||
// println(inst)
|
|
||||||
// p.success(inst)
|
|
||||||
// })
|
|
||||||
// p.future
|
|
||||||
// }
|
|
||||||
// for {
|
|
||||||
// d <- Deferred[Task, JavaFxUI]
|
|
||||||
// _ <- Task(JavaFxUI.initialize(app))
|
|
||||||
// } yield ()
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
package wow.doge.mygame.implicits
|
package wow.doge.mygame.implicits
|
||||||
|
|
||||||
import javafx.{
|
import javafx.scene.{input => jfxsi}
|
||||||
collections => jfxc,
|
import javafx.{event => jfxe}
|
||||||
event => jfxe,
|
|
||||||
geometry => jfxg,
|
|
||||||
scene => jfxs,
|
|
||||||
util => jfxu
|
|
||||||
}
|
|
||||||
import javafx.scene.{input => jfxsi, layout => jfxsl, paint => jfxsp}
|
|
||||||
import scalafx.scene.Scene
|
|
||||||
import monix.execution.Cancelable
|
|
||||||
import monix.reactive.OverflowStrategy
|
|
||||||
import monix.reactive.Observable
|
|
||||||
import monix.execution.Ack
|
import monix.execution.Ack
|
||||||
|
import monix.execution.Cancelable
|
||||||
|
import monix.reactive.Observable
|
||||||
|
import monix.reactive.OverflowStrategy
|
||||||
|
import scalafx.scene.Scene
|
||||||
import scalafx.scene.control.ButtonBase
|
import scalafx.scene.control.ButtonBase
|
||||||
|
|
||||||
object JavaFXMonixObservables {
|
object JavaFXMonixObservables {
|
||||||
|
@ -1,18 +1,5 @@
|
|||||||
package wow.doge.mygame.implicits
|
package wow.doge.mygame.implicits
|
||||||
|
|
||||||
import javafx.{
|
|
||||||
collections => jfxc,
|
|
||||||
event => jfxe,
|
|
||||||
geometry => jfxg,
|
|
||||||
scene => jfxs,
|
|
||||||
util => jfxu
|
|
||||||
}
|
|
||||||
import javafx.scene.{input => jfxsi, layout => jfxsl, paint => jfxsp}
|
|
||||||
import scalafx.scene.Scene
|
|
||||||
import monix.execution.Cancelable
|
|
||||||
import monix.reactive.OverflowStrategy
|
|
||||||
import monix.reactive.Observable
|
|
||||||
import monix.execution.Ack
|
|
||||||
import scalafx.scene.control.Button
|
|
||||||
|
|
||||||
package object observables {}
|
package object observables {}
|
||||||
|
@ -6,6 +6,7 @@ import scala.reflect.ClassTag
|
|||||||
import akka.actor.typed.ActorRef
|
import akka.actor.typed.ActorRef
|
||||||
import akka.actor.typed.Scheduler
|
import akka.actor.typed.Scheduler
|
||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
|
import com.jayfella.jme.jfx.JavaFxUI
|
||||||
import com.jme3.app.Application
|
import com.jme3.app.Application
|
||||||
import com.jme3.app.SimpleApplication
|
import com.jme3.app.SimpleApplication
|
||||||
import com.jme3.app.state.AppState
|
import com.jme3.app.state.AppState
|
||||||
@ -24,6 +25,7 @@ import com.jme3.input.controls.ActionListener
|
|||||||
import com.jme3.input.controls.AnalogListener
|
import com.jme3.input.controls.AnalogListener
|
||||||
import com.jme3.input.controls.InputListener
|
import com.jme3.input.controls.InputListener
|
||||||
import com.jme3.input.controls.Trigger
|
import com.jme3.input.controls.Trigger
|
||||||
|
import com.jme3.light.Light
|
||||||
import com.jme3.math.Vector3f
|
import com.jme3.math.Vector3f
|
||||||
import com.jme3.scene.CameraNode
|
import com.jme3.scene.CameraNode
|
||||||
import com.jme3.scene.Geometry
|
import com.jme3.scene.Geometry
|
||||||
@ -48,23 +50,23 @@ import monix.reactive.OverflowStrategy
|
|||||||
import monix.reactive.observers.Subscriber
|
import monix.reactive.observers.Subscriber
|
||||||
import wow.doge.mygame.math.ImVector3f
|
import wow.doge.mygame.math.ImVector3f
|
||||||
import wow.doge.mygame.state.MyBaseState
|
import wow.doge.mygame.state.MyBaseState
|
||||||
import com.jme3.light.Light
|
import com.jme3.material.Material
|
||||||
import com.jayfella.jme.jfx.JavaFxUI
|
|
||||||
|
|
||||||
case class ActionEvent(binding: Action, value: Boolean, tpf: Float)
|
final case class ActionEvent(binding: Action, value: Boolean, tpf: Float)
|
||||||
case class EnumActionEvent[T <: EnumEntry](
|
final case class EnumActionEvent[T <: EnumEntry](
|
||||||
binding: T,
|
binding: T,
|
||||||
value: Boolean,
|
value: Boolean,
|
||||||
tpf: Float
|
tpf: Float
|
||||||
)
|
)
|
||||||
|
|
||||||
case class AnalogEvent(binding: Action, value: Float, tpf: Float)
|
final case class AnalogEvent(binding: Action, value: Float, tpf: Float)
|
||||||
case class EnumAnalogEvent[T <: EnumEntry](
|
final case class EnumAnalogEvent[T <: EnumEntry](
|
||||||
binding: T,
|
binding: T,
|
||||||
value: Float,
|
value: Float,
|
||||||
tpf: Float
|
tpf: Float
|
||||||
)
|
)
|
||||||
case class PhysicsTickEvent(space: PhysicsSpace, tpf: Float)
|
final class PrePhysicsTickEvent(val space: PhysicsSpace) extends AnyVal
|
||||||
|
final class PhysicsTickEvent(val space: PhysicsSpace) extends AnyVal
|
||||||
|
|
||||||
package object implicits {
|
package object implicits {
|
||||||
type PrePhysicsTickEvent = PhysicsTickEvent
|
type PrePhysicsTickEvent = PhysicsTickEvent
|
||||||
@ -334,6 +336,13 @@ package object implicits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implicit final class GeometryExt(private val geom: Geometry) {
|
||||||
|
def withMaterial(mat: Material) = {
|
||||||
|
geom.setMaterial(mat)
|
||||||
|
geom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
implicit final class EntityDataExt(private val ed: EntityData)
|
implicit final class EntityDataExt(private val ed: EntityData)
|
||||||
extends AnyVal {
|
extends AnyVal {
|
||||||
|
|
||||||
@ -356,10 +365,7 @@ package object implicits {
|
|||||||
import akka.actor.typed.scaladsl.AskPattern._
|
import akka.actor.typed.scaladsl.AskPattern._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param replyTo
|
* Same as [[ask]] but returns a [[Task]]
|
||||||
* @param timeout
|
|
||||||
* @param scheduler
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
def askL[Res](
|
def askL[Res](
|
||||||
replyTo: ActorRef[Res] => Req
|
replyTo: ActorRef[Res] => Req
|
||||||
@ -378,12 +384,16 @@ package object implicits {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def tellL(msg: Req) = UIO(a.tell(msg))
|
def tellL(msg: Req) = UIO(a.tell(msg))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as [[tell]], but wrapped in a Task
|
||||||
|
*
|
||||||
|
* @param msg
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
def !!(msg: Req) = tellL(msg)
|
def !!(msg: Req) = tellL(msg)
|
||||||
|
|
||||||
}
|
}
|
||||||
// def ?[Res](replyTo: ActorRef[Res] => Req)(implicit timeout: Timeout, scheduler: Scheduler): Future[Res] = {
|
|
||||||
// ask(replyTo)(timeout, scheduler)
|
|
||||||
// }
|
|
||||||
|
|
||||||
implicit final class InputManagerExt(private val inputManager: InputManager)
|
implicit final class InputManagerExt(private val inputManager: InputManager)
|
||||||
extends AnyVal {
|
extends AnyVal {
|
||||||
@ -523,7 +533,7 @@ package object implicits {
|
|||||||
|
|
||||||
def collisionObservable(): Observable[PhysicsCollisionEvent] = {
|
def collisionObservable(): Observable[PhysicsCollisionEvent] = {
|
||||||
|
|
||||||
Observable.create(OverflowStrategy.Unbounded) { sub =>
|
Observable.create(OverflowStrategy.DropOld(50)) { sub =>
|
||||||
val c = SingleAssignCancelable()
|
val c = SingleAssignCancelable()
|
||||||
val cl = new PhysicsCollisionListener {
|
val cl = new PhysicsCollisionListener {
|
||||||
override def collision(event: PhysicsCollisionEvent): Unit = {
|
override def collision(event: PhysicsCollisionEvent): Unit = {
|
||||||
@ -543,23 +553,45 @@ package object implicits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def physicsTickObservable(): PhysicsTickObservable = {
|
def prePhysicsTickObservable(): Observable[PrePhysicsTickEvent] = {
|
||||||
|
|
||||||
Observable.create(OverflowStrategy.Unbounded) { sub =>
|
Observable.create(OverflowStrategy.DropOld(50)) { sub =>
|
||||||
val c = SingleAssignCancelable()
|
val c = SingleAssignCancelable()
|
||||||
val cl = new PhysicsTickListener {
|
val cl = new PhysicsTickListener {
|
||||||
|
|
||||||
override def prePhysicsTick(space: PhysicsSpace, tpf: Float): Unit = {
|
override def prePhysicsTick(space: PhysicsSpace, tpf: Float): Unit = {
|
||||||
val event = PhysicsTickEvent(space, tpf)
|
val event = new PrePhysicsTickEvent(space)
|
||||||
if (sub.onNext(Left(event)) == Ack.Stop) {
|
if (sub.onNext(event) == Ack.Stop) {
|
||||||
sub.onComplete()
|
sub.onComplete()
|
||||||
c.cancel()
|
c.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def physicsTick(space: PhysicsSpace, tpf: Float): Unit = {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
space.addTickListener(cl)
|
||||||
|
|
||||||
|
c := Cancelable(() => space.removeTickListener(cl))
|
||||||
|
c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def physicsTickObservable(): Observable[PhysicsTickEvent] = {
|
||||||
|
|
||||||
|
Observable.create(OverflowStrategy.DropOld(50)) { sub =>
|
||||||
|
val c = SingleAssignCancelable()
|
||||||
|
val cl = new PhysicsTickListener {
|
||||||
|
|
||||||
|
override def prePhysicsTick(
|
||||||
|
space: PhysicsSpace,
|
||||||
|
tpf: Float
|
||||||
|
): Unit = {}
|
||||||
|
|
||||||
override def physicsTick(space: PhysicsSpace, tpf: Float): Unit = {
|
override def physicsTick(space: PhysicsSpace, tpf: Float): Unit = {
|
||||||
val event = PhysicsTickEvent(space, tpf)
|
val event = new PhysicsTickEvent(space)
|
||||||
if (sub.onNext(Right(event)) == Ack.Stop) {
|
if (sub.onNext(event) == Ack.Stop) {
|
||||||
sub.onComplete()
|
sub.onComplete()
|
||||||
c.cancel()
|
c.cancel()
|
||||||
}
|
}
|
||||||
@ -574,7 +606,7 @@ package object implicits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO Create a typeclass for this
|
//TODO Consider creating a typeclass for this
|
||||||
def +=(anyObject: Any) = space.add(anyObject)
|
def +=(anyObject: Any) = space.add(anyObject)
|
||||||
|
|
||||||
def :+(anyObject: Any) = {
|
def :+(anyObject: Any) = {
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
package wow.doge.mygame.launcher
|
package wow.doge.mygame.launcher
|
||||||
|
|
||||||
import scalafx.geometry.Insets
|
import scalafx.geometry.Insets
|
||||||
|
import scalafx.geometry.Orientation
|
||||||
|
import scalafx.geometry.Pos
|
||||||
import scalafx.scene.Scene
|
import scalafx.scene.Scene
|
||||||
|
import scalafx.scene.control.Button
|
||||||
import scalafx.scene.effect.DropShadow
|
import scalafx.scene.effect.DropShadow
|
||||||
|
import scalafx.scene.layout.FlowPane
|
||||||
import scalafx.scene.layout.HBox
|
import scalafx.scene.layout.HBox
|
||||||
|
import scalafx.scene.layout.VBox
|
||||||
import scalafx.scene.paint.Color._
|
import scalafx.scene.paint.Color._
|
||||||
import scalafx.scene.paint._
|
import scalafx.scene.paint._
|
||||||
import scalafx.scene.text.Text
|
import scalafx.scene.text.Text
|
||||||
import scalafx.scene.control.Button
|
|
||||||
import scalafx.scene.layout.VBox
|
|
||||||
import scalafx.scene.layout.FlowPane
|
|
||||||
import scalafx.geometry.Orientation
|
|
||||||
import scalafx.geometry.Pos
|
|
||||||
import scalafx.stage.Stage
|
|
||||||
|
|
||||||
object DefaultUI {
|
object DefaultUI {
|
||||||
def scene(
|
def scene(
|
||||||
@ -64,39 +63,4 @@ object DefaultUI {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
def box(launchButton: Button, exitButton: Button) =
|
|
||||||
new VBox {
|
|
||||||
children = Seq(
|
|
||||||
new HBox {
|
|
||||||
padding = Insets(50, 80, 50, 80)
|
|
||||||
children = Seq(
|
|
||||||
new Text {
|
|
||||||
text = "JMonkeyEngine"
|
|
||||||
style = "-fx-font: normal bold 50pt sans-serif"
|
|
||||||
fill = new LinearGradient(endX = 0, stops = Stops(Red, DarkRed))
|
|
||||||
},
|
|
||||||
new Text {
|
|
||||||
text = " Game"
|
|
||||||
style = "-fx-font: italic bold 50pt sans-serif"
|
|
||||||
fill = new LinearGradient(
|
|
||||||
endX = 0,
|
|
||||||
stops = Stops(White, DarkGray)
|
|
||||||
)
|
|
||||||
effect = new DropShadow {
|
|
||||||
color = DarkGray
|
|
||||||
radius = 15
|
|
||||||
spread = 0.25
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
new FlowPane {
|
|
||||||
hgap = 10
|
|
||||||
padding = Insets(50, 80, 50, 80)
|
|
||||||
orientation = Orientation.Horizontal
|
|
||||||
alignment = Pos.Center
|
|
||||||
children = Seq(launchButton, exitButton)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,22 @@
|
|||||||
package wow.doge.mygame.launcher
|
package wow.doge.mygame.launcher
|
||||||
|
|
||||||
import scala.concurrent.duration.FiniteDuration
|
import scala.concurrent.duration.FiniteDuration
|
||||||
import scalafx.application.JFXApp
|
|
||||||
import scalafx.application.JFXApp.PrimaryStage
|
|
||||||
import wow.doge.mygame.executors.Schedulers
|
|
||||||
import cats.effect.Resource
|
|
||||||
import monix.bio.Task
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import javafx.application.Platform
|
|
||||||
import scalafx.scene.control.Button
|
|
||||||
import cats.effect.concurrent.Deferred
|
import cats.effect.concurrent.Deferred
|
||||||
import wow.doge.mygame.utils.IOUtils._
|
import javafx.application.Platform
|
||||||
|
import monix.bio.Task
|
||||||
|
import monix.catnap.CancelableF
|
||||||
import monix.eval.{Task => ETask}
|
import monix.eval.{Task => ETask}
|
||||||
import monix.reactive.Observable
|
import monix.reactive.Observable
|
||||||
import monix.bio.Fiber
|
|
||||||
import scalafx.stage.StageStyle
|
|
||||||
import scalafx.Includes._
|
import scalafx.Includes._
|
||||||
import wow.doge.mygame.utils.ResizeHelper
|
import scalafx.application.JFXApp
|
||||||
import scalafx.scene.Scene
|
import scalafx.application.JFXApp.PrimaryStage
|
||||||
import scalafx.scene.layout.VBox
|
import scalafx.scene.control.Button
|
||||||
|
import scalafx.stage.StageStyle
|
||||||
|
import wow.doge.mygame.executors.Schedulers
|
||||||
import wow.doge.mygame.implicits.JavaFXMonixObservables._
|
import wow.doge.mygame.implicits.JavaFXMonixObservables._
|
||||||
import monix.catnap.cancelables.SingleAssignCancelableF
|
import wow.doge.mygame.utils.IOUtils._
|
||||||
import monix.catnap.CancelableF
|
|
||||||
// import wow.doge.mygame.implicits.JavaFXMonixObservables._
|
|
||||||
|
|
||||||
// import scala.language.implicitConversions
|
|
||||||
|
|
||||||
// object Stage {
|
|
||||||
// implicit def sfxStage2jfx(v: Stage): jfxs.Stage = if (v != null) v.delegate else null
|
|
||||||
// }
|
|
||||||
|
|
||||||
object Launcher {
|
object Launcher {
|
||||||
sealed trait LauncherResult
|
sealed trait LauncherResult
|
||||||
@ -41,19 +29,7 @@ object Launcher {
|
|||||||
val schedulers: Schedulers,
|
val schedulers: Schedulers,
|
||||||
val signal: Deferred[Task, LauncherResult]
|
val signal: Deferred[Task, LauncherResult]
|
||||||
) {
|
) {
|
||||||
// val resource2
|
|
||||||
// : Resource[Task, (LauncherApp, Task[Ref[Task, Stage]], Fiber[Unit])] =
|
|
||||||
// Resource.make(for {
|
|
||||||
// app <- Task(new LauncherApp(this))
|
|
||||||
// fib <- app.init.start
|
|
||||||
// } yield ((app, app.stageRef, fib)))(_._3.cancel)
|
|
||||||
val create = Task(new Launcher(this))
|
val create = Task(new Launcher(this))
|
||||||
|
|
||||||
val resource: Resource[Task, Launcher] =
|
|
||||||
Resource.make(for {
|
|
||||||
app <- Task(new Launcher(this))
|
|
||||||
// fib <- app.init.start
|
|
||||||
} yield (app))(_ => Task.unit)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Launcher private (props: Launcher.Props) {
|
class Launcher private (props: Launcher.Props) {
|
||||||
@ -62,7 +38,6 @@ class Launcher private (props: Launcher.Props) {
|
|||||||
private lazy val launchButton = new Button {
|
private lazy val launchButton = new Button {
|
||||||
text = "Launch"
|
text = "Launch"
|
||||||
}
|
}
|
||||||
// private lazy val launchButtonObs =
|
|
||||||
|
|
||||||
private lazy val launchAction =
|
private lazy val launchAction =
|
||||||
launchButton
|
launchButton
|
||||||
@ -72,7 +47,6 @@ class Launcher private (props: Launcher.Props) {
|
|||||||
private lazy val exitButton = new Button {
|
private lazy val exitButton = new Button {
|
||||||
text = "Exit"
|
text = "Exit"
|
||||||
}
|
}
|
||||||
// private lazy val exitButtonObs =
|
|
||||||
|
|
||||||
private lazy val exitAction =
|
private lazy val exitAction =
|
||||||
exitButton
|
exitButton
|
||||||
@ -80,9 +54,6 @@ class Launcher private (props: Launcher.Props) {
|
|||||||
.doOnNext(_ => toTask(props.signal.complete(LauncherResult.Exit)))
|
.doOnNext(_ => toTask(props.signal.complete(LauncherResult.Exit)))
|
||||||
|
|
||||||
private lazy val _scene =
|
private lazy val _scene =
|
||||||
// new Scene {
|
|
||||||
// content = new VBox
|
|
||||||
// }
|
|
||||||
DefaultUI.scene(launchButton, exitButton)
|
DefaultUI.scene(launchButton, exitButton)
|
||||||
|
|
||||||
private lazy val _stage = new PrimaryStage {
|
private lazy val _stage = new PrimaryStage {
|
||||||
@ -113,41 +84,21 @@ class Launcher private (props: Launcher.Props) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// var stage = internal.stage
|
|
||||||
|
|
||||||
// lazy val stageRef = Ref.of[Task, Stage](internal.stage)
|
|
||||||
// stage: => PrimaryStage
|
|
||||||
def init(delay: FiniteDuration = 2000.millis) =
|
def init(delay: FiniteDuration = 2000.millis) =
|
||||||
for {
|
for {
|
||||||
_ <- Task(Platform.setImplicitExit(false))
|
_ <- Task(Platform.setImplicitExit(false))
|
||||||
|
|
||||||
fib <- Task(internal.main(Array.empty)).start
|
fib <- Task(internal.main(Array.empty)).start
|
||||||
_ <- Task.sleep(500.millis)
|
_ <- Task.sleep(500.millis)
|
||||||
// _ <- Task {
|
|
||||||
// // lazy val _stage = new CustomStageBuilder()
|
|
||||||
// // .setWindowTitle("CustomStage example")
|
|
||||||
// // .setWindowColor("rgb(34,54,122)")
|
|
||||||
// // .build()
|
|
||||||
// internal.stage.scene =
|
|
||||||
// DefaultUI.scene(internal.stage, launchButton, exitButton)
|
|
||||||
// // _stage.setScene(DefaultUI.scene(launchButton, exitButton))
|
|
||||||
// // JFXApp.Stage = _stage
|
|
||||||
// }.executeOn(props.schedulers.fx)
|
|
||||||
// c <- SingleAssignCancelableF[Task]
|
|
||||||
sceneDragFib <- toIO(sceneDragObservable.completedL).start
|
sceneDragFib <- toIO(sceneDragObservable.completedL).start
|
||||||
fib2 <- toIO(
|
fib2 <- toIO(
|
||||||
Observable(launchAction, exitAction).merge
|
Observable(launchAction, exitAction).merge
|
||||||
.doOnNext(_ =>
|
.doOnNext(_ =>
|
||||||
ETask(internal.stage.close()).executeOn(props.schedulers.fx)
|
ETask(internal.stage.close()).executeOn(props.schedulers.fx)
|
||||||
)
|
)
|
||||||
// .doOnNext(_ => toTask(fib.cancel))
|
|
||||||
.completedL
|
.completedL
|
||||||
).start
|
).start
|
||||||
c <- CancelableF[Task](fib.cancel >> fib2.cancel >> sceneDragFib.cancel)
|
c <- CancelableF[Task](fib.cancel >> fib2.cancel >> sceneDragFib.cancel)
|
||||||
// _ <- Task {
|
|
||||||
// internal.stage = stage
|
|
||||||
// }.executeOn(props.schedulers.fx)
|
|
||||||
// .delayExecution(delay)
|
|
||||||
} yield (c)
|
} yield (c)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package wow.doge.mygame.math;
|
package wow.doge.mygame.math;
|
||||||
|
|
||||||
|
import Math.{abs, sqrt, pow}
|
||||||
|
|
||||||
case class ImVector3f(x: Float = 0f, y: Float = 0f, z: Float = 0f)
|
case class ImVector3f(x: Float = 0f, y: Float = 0f, z: Float = 0f)
|
||||||
|
|
||||||
object ImVector3f {
|
object ImVector3f {
|
||||||
@ -8,4 +10,6 @@ object ImVector3f {
|
|||||||
val UNIT_Y = ImVector3f(0, 1, 0)
|
val UNIT_Y = ImVector3f(0, 1, 0)
|
||||||
val UNIT_Z = ImVector3f(0, 0, 1)
|
val UNIT_Z = ImVector3f(0, 0, 1)
|
||||||
|
|
||||||
|
def dst(v1: ImVector3f, v2: ImVector3f) =
|
||||||
|
sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2) + pow(v1.z - v2.z, 2))
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package wow.doge.mygame.events
|
package wow.doge.mygame.subsystems.events
|
||||||
|
|
||||||
import scala.reflect.ClassTag
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
|
@ -1,14 +1,24 @@
|
|||||||
package wow.doge.mygame.events
|
package wow.doge.mygame.subsystems.events
|
||||||
|
|
||||||
object Events {
|
sealed trait Event
|
||||||
sealed trait Event
|
final case object BulletFired extends Event
|
||||||
final case object BulletFired extends Event
|
|
||||||
// type BulletFired = BulletFired.type
|
// type BulletFired = BulletFired.type
|
||||||
final case class EventWithData(data: Int) extends Event
|
final case class EventWithData(data: Int) extends Event
|
||||||
|
|
||||||
sealed trait Tick extends Event
|
sealed trait TickEvent extends Event
|
||||||
object Tick {
|
object TickEvent {
|
||||||
final case object RenderTick extends Tick
|
final case object RenderTick extends TickEvent
|
||||||
final case object PhysicsTick extends Tick
|
final case object PhysicsTick extends TickEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed trait EntityMovementEvent extends Event
|
||||||
|
object EntityMovementEvent {
|
||||||
|
final case class MovedLeft(name: String, pressed: Boolean)
|
||||||
|
extends EntityMovementEvent
|
||||||
|
final case class MovedUp(name: String, pressed: Boolean)
|
||||||
|
extends EntityMovementEvent
|
||||||
|
final case class MovedRight(name: String, pressed: Boolean)
|
||||||
|
extends EntityMovementEvent
|
||||||
|
final case class MovedDown(name: String, pressed: Boolean)
|
||||||
|
extends EntityMovementEvent
|
||||||
}
|
}
|
||||||
|
@ -10,22 +10,19 @@ import akka.actor.typed.SpawnProtocol
|
|||||||
import akka.actor.typed.SupervisorStrategy
|
import akka.actor.typed.SupervisorStrategy
|
||||||
import akka.actor.typed.scaladsl.Behaviors
|
import akka.actor.typed.scaladsl.Behaviors
|
||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
import cats.effect.Resource
|
import com.typesafe.scalalogging.{Logger => SLogger}
|
||||||
import com.typesafe.scalalogging.{Logger => SLLogger}
|
|
||||||
import monix.bio.Task
|
|
||||||
import org.slf4j.event.Level
|
import org.slf4j.event.Level
|
||||||
import wow.doge.mygame.events.EventBus
|
|
||||||
import wow.doge.mygame.implicits._
|
import wow.doge.mygame.implicits._
|
||||||
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
|
import wow.doge.mygame.subsystems.events.Event
|
||||||
|
import wow.doge.mygame.subsystems.events.EventBus
|
||||||
|
import wow.doge.mygame.subsystems.events.TickEvent
|
||||||
|
|
||||||
class EventsModule2(
|
class EventsModule(spawnProtocol: ActorSystem[SpawnProtocol.Command]) {
|
||||||
spawnProtocol: ActorSystem[SpawnProtocol.Command]
|
|
||||||
) {
|
|
||||||
implicit lazy val s = spawnProtocol.scheduler
|
implicit lazy val s = spawnProtocol.scheduler
|
||||||
|
|
||||||
implicit lazy val timeout = Timeout(1.second)
|
implicit lazy val timeout = Timeout(1.second)
|
||||||
|
|
||||||
lazy val eventBusLogger = SLLogger[EventBus[_]]
|
lazy val eventBusLogger = SLogger[EventBus[_]]
|
||||||
|
|
||||||
lazy val playerMovementEventBusTask =
|
lazy val playerMovementEventBusTask =
|
||||||
createEventBus[PlayerMovementEvent]("movementEventBus")
|
createEventBus[PlayerMovementEvent]("movementEventBus")
|
||||||
@ -33,6 +30,11 @@ class EventsModule2(
|
|||||||
lazy val playerCameraEventBusTask =
|
lazy val playerCameraEventBusTask =
|
||||||
createEventBus[PlayerCameraEvent]("playerCameraEventBus", Level.DEBUG)
|
createEventBus[PlayerCameraEvent]("playerCameraEventBus", Level.DEBUG)
|
||||||
|
|
||||||
|
lazy val tickEventBusTask =
|
||||||
|
createEventBus[TickEvent]("tickEventBus", Level.TRACE)
|
||||||
|
|
||||||
|
lazy val mainEventBusTask = createEventBus[Event]("mainEventBus")
|
||||||
|
|
||||||
def createEventBus[T](busName: String, logLevel: Level = Level.DEBUG) =
|
def createEventBus[T](busName: String, logLevel: Level = Level.DEBUG) =
|
||||||
spawnProtocol.askL(
|
spawnProtocol.askL(
|
||||||
SpawnProtocol.Spawn[EventBus.Command[T]](
|
SpawnProtocol.Spawn[EventBus.Command[T]](
|
||||||
@ -49,17 +51,8 @@ class EventsModule2(
|
|||||||
_
|
_
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
type EventBuses = (
|
|
||||||
ActorRef[
|
object EventsModule {
|
||||||
EventBus.Command[EntityMovementEvent.PlayerMovementEvent],
|
type GameEventBus[T] = ActorRef[EventBus.Command[T]]
|
||||||
],
|
|
||||||
ActorRef[EventBus.Command[PlayerCameraEvent]]
|
|
||||||
)
|
|
||||||
|
|
||||||
val resource: Resource[Task, EventBuses] =
|
|
||||||
Resource.liftF(for {
|
|
||||||
playerMovementEventBus <- playerMovementEventBusTask
|
|
||||||
playerCameraEventBus <- playerCameraEventBusTask
|
|
||||||
} yield (playerMovementEventBus, playerCameraEventBus))
|
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package wow.doge.mygame.subsystems.events
|
|
||||||
|
|
||||||
import wow.doge.mygame.game.subsystems.movement.CanMove
|
|
||||||
|
|
||||||
sealed trait EntityMovementEvent
|
|
||||||
object EntityMovementEvent {
|
|
||||||
final case class MovedLeft[T: CanMove](pressed: Boolean, movable: T)
|
|
||||||
extends EntityMovementEvent
|
|
||||||
final case class MovedUp[T: CanMove](pressed: Boolean, movable: T)
|
|
||||||
extends EntityMovementEvent
|
|
||||||
final case class MovedRight[T: CanMove](pressed: Boolean, movable: T)
|
|
||||||
extends EntityMovementEvent
|
|
||||||
final case class MovedDown[T: CanMove](pressed: Boolean, movable: T)
|
|
||||||
extends EntityMovementEvent
|
|
||||||
|
|
||||||
sealed trait PlayerMovementEvent extends EntityMovementEvent
|
|
||||||
object PlayerMovementEvent {
|
|
||||||
final case class PlayerMovedLeft(pressed: Boolean)
|
|
||||||
extends PlayerMovementEvent
|
|
||||||
final case class PlayerMovedRight(pressed: Boolean)
|
|
||||||
extends PlayerMovementEvent
|
|
||||||
final case class PlayerMovedForward(pressed: Boolean)
|
|
||||||
extends PlayerMovementEvent
|
|
||||||
final case class PlayerMovedBackward(pressed: Boolean)
|
|
||||||
extends PlayerMovementEvent
|
|
||||||
final case object PlayerJumped extends PlayerMovementEvent
|
|
||||||
final case object PlayerRotatedRight extends PlayerMovementEvent
|
|
||||||
final case object PlayerRotatedLeft extends PlayerMovementEvent
|
|
||||||
final case object PlayerCameraUp extends PlayerMovementEvent
|
|
||||||
final case object PlayerCameraDown extends PlayerMovementEvent
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1 @@
|
|||||||
package wow.doge.mygame.subsystems.events
|
package wow.doge.mygame.subsystems.events
|
||||||
|
|
||||||
sealed trait PlayerCameraEvent
|
|
||||||
|
|
||||||
object PlayerCameraEvent {
|
|
||||||
final case object CameraMovedUp extends PlayerCameraEvent
|
|
||||||
final case object CameraMovedDown extends PlayerCameraEvent
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package wow.doge.mygame.subsystems.events
|
||||||
|
|
||||||
|
sealed trait PlayerMovementEvent
|
||||||
|
object PlayerMovementEvent {
|
||||||
|
final case class PlayerMovedLeft(pressed: Boolean) extends PlayerMovementEvent
|
||||||
|
final case class PlayerMovedRight(pressed: Boolean)
|
||||||
|
extends PlayerMovementEvent
|
||||||
|
final case class PlayerMovedForward(pressed: Boolean)
|
||||||
|
extends PlayerMovementEvent
|
||||||
|
final case class PlayerMovedBackward(pressed: Boolean)
|
||||||
|
extends PlayerMovementEvent
|
||||||
|
final case object PlayerJumped extends PlayerMovementEvent
|
||||||
|
final case object PlayerRotatedRight extends PlayerMovementEvent
|
||||||
|
final case object PlayerRotatedLeft extends PlayerMovementEvent
|
||||||
|
final case object PlayerCameraUp extends PlayerMovementEvent
|
||||||
|
final case object PlayerCameraDown extends PlayerMovementEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed trait PlayerCameraEvent
|
||||||
|
|
||||||
|
object PlayerCameraEvent {
|
||||||
|
final case object CameraMovedUp extends PlayerCameraEvent
|
||||||
|
final case object CameraMovedDown extends PlayerCameraEvent
|
||||||
|
}
|
@ -8,6 +8,7 @@ import scala.util.Try
|
|||||||
|
|
||||||
import cats.implicits._
|
import cats.implicits._
|
||||||
import io.circe._
|
import io.circe._
|
||||||
|
import io.circe.generic.JsonCodec
|
||||||
import io.circe.generic.semiauto._
|
import io.circe.generic.semiauto._
|
||||||
import io.circe.parser._
|
import io.circe.parser._
|
||||||
import monix.bio.IO
|
import monix.bio.IO
|
||||||
@ -15,7 +16,6 @@ import monix.bio.UIO
|
|||||||
import monix.reactive.Consumer
|
import monix.reactive.Consumer
|
||||||
import monix.reactive.Observable
|
import monix.reactive.Observable
|
||||||
import wow.doge.mygame.utils.IOUtils
|
import wow.doge.mygame.utils.IOUtils
|
||||||
import io.circe.generic.JsonCodec
|
|
||||||
|
|
||||||
@JsonCodec
|
@JsonCodec
|
||||||
final case class Test1(hello1: String, hello2: String)
|
final case class Test1(hello1: String, hello2: String)
|
||||||
|
@ -5,9 +5,9 @@ import akka.actor.typed.Scheduler
|
|||||||
import akka.actor.typed.SpawnProtocol
|
import akka.actor.typed.SpawnProtocol
|
||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
import cats.effect.Resource
|
import cats.effect.Resource
|
||||||
|
import monix.bio.Task
|
||||||
import wow.doge.mygame.scriptsystem.ScriptCachingActor
|
import wow.doge.mygame.scriptsystem.ScriptCachingActor
|
||||||
import wow.doge.mygame.utils.AkkaUtils
|
import wow.doge.mygame.utils.AkkaUtils
|
||||||
import monix.bio.Task
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scripts can either be searched and compiled at startup (Eager mode)
|
* Scripts can either be searched and compiled at startup (Eager mode)
|
||||||
|
@ -22,4 +22,20 @@ object AkkaUtils {
|
|||||||
_
|
_
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
def spawnActorL2[T](
|
||||||
|
behavior: Behavior[T],
|
||||||
|
actorName: String
|
||||||
|
)(implicit
|
||||||
|
timeout: Timeout,
|
||||||
|
scheduler: Scheduler,
|
||||||
|
spawnProtocol: ActorRef[SpawnProtocol.Command]
|
||||||
|
) =
|
||||||
|
spawnProtocol.askL[ActorRef[T]](
|
||||||
|
SpawnProtocol.Spawn(
|
||||||
|
behavior,
|
||||||
|
actorName,
|
||||||
|
Props.empty,
|
||||||
|
_
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,750 +0,0 @@
|
|||||||
package wow.doge.mygame.utils
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2011-2019, ScalaFX Project
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of the ScalaFX Project nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE SCALAFX PROJECT OR ITS CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import javafx.scene.{input => jfxsi, layout => jfxsl, paint => jfxsp}
|
|
||||||
import javafx.{
|
|
||||||
collections => jfxc,
|
|
||||||
event => jfxe,
|
|
||||||
geometry => jfxg,
|
|
||||||
scene => jfxs,
|
|
||||||
util => jfxu
|
|
||||||
}
|
|
||||||
import scalafx.Includes._
|
|
||||||
import scalafx.beans.property.{
|
|
||||||
ObjectProperty,
|
|
||||||
ReadOnlyDoubleProperty,
|
|
||||||
ReadOnlyObjectProperty
|
|
||||||
}
|
|
||||||
import scalafx.collections._
|
|
||||||
import scalafx.delegate.SFXDelegate
|
|
||||||
import scalafx.geometry.NodeOrientation
|
|
||||||
import scalafx.scene.image.WritableImage
|
|
||||||
import scalafx.scene.input.{Dragboard, Mnemonic, TransferMode}
|
|
||||||
import scalafx.scene.paint.Paint
|
|
||||||
import com.goxr3plus.fxborderlessscene.borderless.{BorderlessScene => BScene}
|
|
||||||
|
|
||||||
import scala.language.implicitConversions
|
|
||||||
import scalafx.scene.Cursor
|
|
||||||
import scalafx.scene._
|
|
||||||
import scalafx.stage.Stage
|
|
||||||
import scalafx.stage.StageStyle
|
|
||||||
|
|
||||||
object BorderlessScene {
|
|
||||||
implicit def sfxScene2jfx(v: BorderlessScene): Scene =
|
|
||||||
if (v != null) v.delegate else null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Scene.html]].
|
|
||||||
*
|
|
||||||
* @constructor Create a new ScalaFX Scene with JavaFX Scene as delegate.
|
|
||||||
* @param delegate JavaFX Scene delegated. Its default value is a JavaFX Scene with a
|
|
||||||
* [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Group.html Group]] as root Node.
|
|
||||||
*/
|
|
||||||
class BorderlessScene(
|
|
||||||
override val delegate: BScene
|
|
||||||
) extends SFXDelegate[BScene] {
|
|
||||||
|
|
||||||
def this(stage: Stage, stageStyle: StageStyle, parent: Parent) =
|
|
||||||
this(new BScene(stage, stageStyle, parent))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the root Node of the scene graph
|
|
||||||
*/
|
|
||||||
def root: ObjectProperty[jfxs.Parent] = delegate.rootProperty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the root Node of the scene graph
|
|
||||||
*/
|
|
||||||
def root_=(v: Parent): Unit = {
|
|
||||||
root() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns Nodes children from this Scene's `root`.
|
|
||||||
*/
|
|
||||||
def getChildren =
|
|
||||||
root.value match {
|
|
||||||
case group: jfxs.Group => group.getChildren
|
|
||||||
case pane: jfxsl.Pane => pane.getChildren
|
|
||||||
case _ =>
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Cannot access children of root: " + root + "\n" +
|
|
||||||
"Use a class that extends Group or Pane, or override the getChildren method."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns scene's antialiasing setting.
|
|
||||||
*/
|
|
||||||
def antialiasing: SceneAntialiasing = delegate.getAntiAliasing
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns Content's Node children from this Scene's `root`.
|
|
||||||
*/
|
|
||||||
def content: jfxc.ObservableList[jfxs.Node] = getChildren
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the list of Nodes children from this Scene's `root`, replacing the prior content. If you want append to
|
|
||||||
* current content, use `add` or similar.
|
|
||||||
*
|
|
||||||
* @param c list of Nodes children from this Scene's `root` to replace prior content.
|
|
||||||
*/
|
|
||||||
def content_=(c: Iterable[Node]): Unit = {
|
|
||||||
fillSFXCollection(this.content, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a Node child, replacing the prior content. If you want append to current content, use `add` or similar.
|
|
||||||
*
|
|
||||||
* @param n Node child to replace prior content.
|
|
||||||
*/
|
|
||||||
def content_=(n: Node): Unit = {
|
|
||||||
fillSFXCollectionWithOne(this.content, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the type of camera use for rendering this `Scene`.
|
|
||||||
*/
|
|
||||||
def camera: ObjectProperty[jfxs.Camera] = delegate.cameraProperty
|
|
||||||
|
|
||||||
def camera_=(v: Camera): Unit = {
|
|
||||||
camera() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the mouse cursor for this `Scene`.
|
|
||||||
*/
|
|
||||||
def cursor: ObjectProperty[jfxs.Cursor] = delegate.cursorProperty
|
|
||||||
|
|
||||||
def cursor_=(v: Cursor): Unit = {
|
|
||||||
cursor() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The effective node orientation of a scene resolves the inheritance of node orientation, returning either left-to-right or right-to-left. */
|
|
||||||
def effectiveNodeOrientation: ReadOnlyObjectProperty[jfxg.NodeOrientation] =
|
|
||||||
delegate.effectiveNodeOrientationProperty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the event dispatcher for this scene.
|
|
||||||
*/
|
|
||||||
def eventDispatcher: ObjectProperty[jfxe.EventDispatcher] =
|
|
||||||
delegate.eventDispatcherProperty
|
|
||||||
|
|
||||||
def eventDispatcher_=(v: jfxe.EventDispatcher): Unit = {
|
|
||||||
eventDispatcher() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the background fill of this Scene.
|
|
||||||
*/
|
|
||||||
def fill: ObjectProperty[jfxsp.Paint] = delegate.fillProperty
|
|
||||||
|
|
||||||
def fill_=(v: Paint): Unit = {
|
|
||||||
fill() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The height of this Scene
|
|
||||||
*/
|
|
||||||
def height: ReadOnlyDoubleProperty = delegate.heightProperty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The width of this Scene
|
|
||||||
*/
|
|
||||||
def width: ReadOnlyDoubleProperty = delegate.widthProperty
|
|
||||||
|
|
||||||
def nodeOrientation: ObjectProperty[jfxg.NodeOrientation] =
|
|
||||||
delegate.nodeOrientationProperty
|
|
||||||
|
|
||||||
def nodeOrientation_=(v: NodeOrientation): Unit = {
|
|
||||||
ObjectProperty.fillProperty[jfxg.NodeOrientation](this.nodeOrientation, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a mouse button has been clicked (pressed and released) on this `Scene`.
|
|
||||||
*/
|
|
||||||
def onContextMenuRequested = delegate.onContextMenuRequestedProperty
|
|
||||||
|
|
||||||
def onContextMenuRequested_=(
|
|
||||||
v: jfxe.EventHandler[_ >: jfxsi.ContextMenuEvent]
|
|
||||||
): Unit = {
|
|
||||||
onContextMenuRequested() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when drag gesture has been detected.
|
|
||||||
*/
|
|
||||||
def onDragDetected = delegate.onDragDetectedProperty
|
|
||||||
|
|
||||||
def onDragDetected_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
|
|
||||||
onDragDetected() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when this `Scene` is a drag and drop gesture source after its data has been
|
|
||||||
* dropped on a drop target.
|
|
||||||
*/
|
|
||||||
def onDragDone = delegate.onDragDoneProperty
|
|
||||||
|
|
||||||
def onDragDone_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
|
|
||||||
onDragDone() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when the mouse button is released on this `Scene` during drag and drop gesture.
|
|
||||||
*/
|
|
||||||
def onDragDropped = delegate.onDragDroppedProperty
|
|
||||||
|
|
||||||
def onDragDropped_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
|
|
||||||
onDragDropped() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when drag gesture enters this Scene.
|
|
||||||
*/
|
|
||||||
def onDragEntered = delegate.onDragEnteredProperty
|
|
||||||
|
|
||||||
def onDragEntered_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
|
|
||||||
onDragEntered() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when drag gesture exits this Scene.
|
|
||||||
*/
|
|
||||||
def onDragExited = delegate.onDragExitedProperty
|
|
||||||
|
|
||||||
def onDragExited_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
|
|
||||||
onDragExited() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when drag gesture progresses within this `Scene`.
|
|
||||||
*/
|
|
||||||
def onDragOver = delegate.onDragOverProperty
|
|
||||||
|
|
||||||
def onDragOver_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = {
|
|
||||||
onDragOver() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when this `Node` has input focus and the input method text has changed.
|
|
||||||
*/
|
|
||||||
def onInputMethodTextChanged = delegate.onInputMethodTextChangedProperty
|
|
||||||
|
|
||||||
def onInputMethodTextChanged_=(
|
|
||||||
v: jfxe.EventHandler[_ >: jfxsi.InputMethodEvent]
|
|
||||||
): Unit = {
|
|
||||||
onInputMethodTextChanged() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when some `Node` of this `Scene` has input focus and a key has been pressed.
|
|
||||||
*/
|
|
||||||
def onKeyPressed = delegate.onKeyPressedProperty
|
|
||||||
|
|
||||||
def onKeyPressed_=(v: jfxe.EventHandler[_ >: jfxsi.KeyEvent]): Unit = {
|
|
||||||
onKeyPressed() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when some `Node` of this `Scene` has input focus and a key has been released.
|
|
||||||
*/
|
|
||||||
def onKeyReleased = delegate.onKeyReleasedProperty
|
|
||||||
|
|
||||||
def onKeyReleased_=(v: jfxe.EventHandler[_ >: jfxsi.KeyEvent]): Unit = {
|
|
||||||
onKeyReleased() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when some `Node` of this `Scene` has input focus and a key has been typed.
|
|
||||||
*/
|
|
||||||
def onKeyTyped = delegate.onKeyTypedProperty
|
|
||||||
|
|
||||||
def onKeyTyped_=(v: jfxe.EventHandler[_ >: jfxsi.KeyEvent]): Unit = {
|
|
||||||
onKeyTyped() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a mouse button has been clicked (pressed and released) on this `Scene`.
|
|
||||||
*/
|
|
||||||
def onMouseClicked = delegate.onMouseClickedProperty
|
|
||||||
|
|
||||||
def onMouseClicked_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
|
|
||||||
onMouseClicked() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a mouse button is pressed on this `Scene` and then dragged.
|
|
||||||
*/
|
|
||||||
def onMouseDragged = delegate.onMouseDraggedProperty
|
|
||||||
|
|
||||||
def onMouseDragged_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
|
|
||||||
onMouseDragged() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a full press-drag-release gesture enters this `Scene`.
|
|
||||||
*/
|
|
||||||
def onMouseDragEntered = delegate.onMouseDragEnteredProperty
|
|
||||||
|
|
||||||
def onMouseDragEntered_=(
|
|
||||||
v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent]
|
|
||||||
): Unit = {
|
|
||||||
onMouseDragEntered() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a full press-drag-release gesture exits this `Scene`.
|
|
||||||
*/
|
|
||||||
def onMouseDragExited = delegate.onMouseDragExitedProperty
|
|
||||||
|
|
||||||
def onMouseDragExited_=(
|
|
||||||
v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent]
|
|
||||||
): Unit = {
|
|
||||||
onMouseDragExited() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a full press-drag-release gesture progresses within this `Scene`.
|
|
||||||
*/
|
|
||||||
def onMouseDragOver = delegate.onMouseDragOverProperty
|
|
||||||
|
|
||||||
def onMouseDragOver_=(
|
|
||||||
v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent]
|
|
||||||
): Unit = {
|
|
||||||
onMouseDragOver() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a full press-drag-release gesture ends within this `Scene`.
|
|
||||||
*/
|
|
||||||
def onMouseDragReleased = delegate.onMouseDragReleasedProperty
|
|
||||||
|
|
||||||
def onMouseDragReleased_=(
|
|
||||||
v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent]
|
|
||||||
): Unit = {
|
|
||||||
onMouseDragReleased() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when the mouse enters this `Scene`.
|
|
||||||
*/
|
|
||||||
def onMouseEntered = delegate.onMouseEnteredProperty
|
|
||||||
|
|
||||||
def onMouseEntered_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
|
|
||||||
onMouseEntered() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when the mouse exits this `Scene`.
|
|
||||||
*/
|
|
||||||
def onMouseExited = delegate.onMouseExitedProperty
|
|
||||||
|
|
||||||
def onMouseExited_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
|
|
||||||
onMouseExited() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when mouse cursor moves within this `Scene` but no buttons have been pushed.
|
|
||||||
*/
|
|
||||||
def onMouseMoved = delegate.onMouseMovedProperty
|
|
||||||
|
|
||||||
def onMouseMoved_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
|
|
||||||
onMouseMoved() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a mouse button has been pressed on this `Scene`.
|
|
||||||
*/
|
|
||||||
def onMousePressed = delegate.onMousePressedProperty
|
|
||||||
|
|
||||||
def onMousePressed_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
|
|
||||||
onMousePressed() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a mouse button has been released on this `Scene`.
|
|
||||||
*/
|
|
||||||
def onMouseReleased = delegate.onMouseReleasedProperty
|
|
||||||
|
|
||||||
def onMouseReleased_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = {
|
|
||||||
onMouseReleased() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when user performs a scrolling action.
|
|
||||||
*/
|
|
||||||
def onScroll = delegate.onScrollProperty
|
|
||||||
|
|
||||||
def onScroll_=(v: jfxe.EventHandler[_ >: jfxsi.ScrollEvent]): Unit = {
|
|
||||||
onScroll() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The URL of the user-agent stylesheet that will be used by this Scene in place of the the platform-default
|
|
||||||
* user-agent stylesheet. If the URL does not resolve to a valid location, the platform-default user-agent
|
|
||||||
* stylesheet will be used.
|
|
||||||
*
|
|
||||||
* For additional information about using CSS with the scene graph, see the
|
|
||||||
* [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html CSS Reference Guide]].
|
|
||||||
*
|
|
||||||
* @return The URL of the user-agent stylesheet that will be used by this SubScene, or null if has not been set.
|
|
||||||
*/
|
|
||||||
def userAgentStylesheet: ObjectProperty[String] =
|
|
||||||
delegate.userAgentStylesheetProperty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the URL of the user-agent stylesheet that will be used by this Scene in place of the the platform-default
|
|
||||||
* user-agent stylesheet. If the URL does not resolve to a valid location, the platform-default user-agent
|
|
||||||
* stylesheet will be used.
|
|
||||||
*
|
|
||||||
* For additional information about using CSS with the scene graph, see the
|
|
||||||
* [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html CSS Reference Guide]].
|
|
||||||
*
|
|
||||||
* @param url The URL is a hierarchical URI of the form `[scheme:][//authority][path]`.
|
|
||||||
* If the URL does not have a `[scheme:]` component, the URL is considered to be the `[path]`
|
|
||||||
* component only. Any leading '/' character of the `[path]` is ignored and the `[path]` is
|
|
||||||
* treated as a path relative to the root of the application's classpath.
|
|
||||||
*/
|
|
||||||
def userAgentStylesheet_=(url: String): Unit = {
|
|
||||||
ObjectProperty.fillProperty[String](userAgentStylesheet, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `Window` for this Scene
|
|
||||||
*/
|
|
||||||
def window: ReadOnlyObjectProperty[javafx.stage.Window] =
|
|
||||||
delegate.windowProperty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The horizontal location of this `Scene` on the `Window`.
|
|
||||||
*/
|
|
||||||
def x: ReadOnlyDoubleProperty = delegate.xProperty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The vertical location of this `Scene` on the `Window`.
|
|
||||||
*/
|
|
||||||
def y: ReadOnlyDoubleProperty = delegate.yProperty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the depth buffer attribute for this scene.
|
|
||||||
*/
|
|
||||||
def depthBuffer = delegate.isDepthBuffer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an observable list of string URLs linking to the stylesheets to use with this Parent's contents.
|
|
||||||
*/
|
|
||||||
def stylesheets: jfxc.ObservableList[String] = delegate.getStylesheets
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the list of stylesheets URLs, replacing the prior content. If you want append to current content, use `add` or
|
|
||||||
* similar.
|
|
||||||
*
|
|
||||||
* @param c list of stylesheets URLs to replace prior content.
|
|
||||||
*/
|
|
||||||
def stylesheets_=(c: Iterable[String]): Unit = {
|
|
||||||
fillCollection(stylesheets, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Looks for any node within the scene graph based on the specified CSS selector.
|
|
||||||
*
|
|
||||||
* @param selector The css selector to look up
|
|
||||||
* @return A [[scala.Some]] containing the Node in the scene which matches the CSS selector, or [[scala.None]]
|
|
||||||
* if none is found.
|
|
||||||
*/
|
|
||||||
def lookup(selector: String): Option[Node] = Option(delegate.lookup(selector))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the specified mnemonic.
|
|
||||||
*
|
|
||||||
* @param m The Mnemonic
|
|
||||||
*/
|
|
||||||
def addMnemonic(m: Mnemonic): Unit = {
|
|
||||||
delegate.addMnemonic(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregisters the specified mnemonic.
|
|
||||||
*
|
|
||||||
* @param m The Mnemonic to be removed.
|
|
||||||
*/
|
|
||||||
def removeMnemonic(m: Mnemonic): Unit = {
|
|
||||||
delegate.removeMnemonic(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the list of mnemonics for this `Scene`.
|
|
||||||
*/
|
|
||||||
def getMnemonics
|
|
||||||
: jfxc.ObservableMap[jfxsi.KeyCombination, jfxc.ObservableList[
|
|
||||||
jfxsi.Mnemonic
|
|
||||||
]] = delegate.getMnemonics
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the list of accelerators for this Scene.
|
|
||||||
*/
|
|
||||||
def accelerators: jfxc.ObservableMap[jfxsi.KeyCombination, Runnable] =
|
|
||||||
delegate.getAccelerators
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirms a potential drag and drop gesture that is recognized over this `Scene`.
|
|
||||||
*
|
|
||||||
* @param transferModes The supported `TransferMode`(s) of this `Node`
|
|
||||||
* @return A `Dragboard` to place this `Scene`'s data on
|
|
||||||
*/
|
|
||||||
def startDragAndDrop(transferModes: TransferMode*): Dragboard =
|
|
||||||
delegate.startDragAndDrop(transferModes.map(_.delegate): _*)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a full press-drag-release gesture with this scene as gesture source.
|
|
||||||
*/
|
|
||||||
def startFullDrag(): Unit = {
|
|
||||||
delegate.startFullDrag()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene's current focus owner node. This node's "focused" variable might be false if this scene has no window,
|
|
||||||
* or if the window is inactive (window.focused == false).
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def focusOwner: ReadOnlyObjectProperty[jfxs.Node] =
|
|
||||||
delegate.focusOwnerProperty()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when user performs a rotation action.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onRotate = delegate.onRotateProperty
|
|
||||||
|
|
||||||
def onRotate_=(v: jfxe.EventHandler[_ >: jfxsi.RotateEvent]): Unit = {
|
|
||||||
onRotate() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a rotation gesture ends.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onRotationFinished = delegate.onRotationFinishedProperty()
|
|
||||||
|
|
||||||
def onRotationFinished_=(
|
|
||||||
v: jfxe.EventHandler[_ >: jfxsi.RotateEvent]
|
|
||||||
): Unit = {
|
|
||||||
onRotationFinished() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a rotation gesture starts.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onRotationStarted = delegate.onRotationFinishedProperty()
|
|
||||||
|
|
||||||
def onRotationStarted_=(
|
|
||||||
v: jfxe.EventHandler[_ >: jfxsi.RotateEvent]
|
|
||||||
): Unit = {
|
|
||||||
onRotationStarted() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a Scroll gesture ends.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onScrollFinished = delegate.onScrollFinishedProperty()
|
|
||||||
|
|
||||||
def onScrollFinished_=(v: jfxe.EventHandler[_ >: jfxsi.ScrollEvent]): Unit = {
|
|
||||||
onScrollFinished() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a Scroll gesture starts.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onScrollStarted = delegate.onScrollStartedProperty()
|
|
||||||
|
|
||||||
def onScrollStarted_=(v: jfxe.EventHandler[_ >: jfxsi.ScrollEvent]): Unit = {
|
|
||||||
onScrollStarted() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a Swipe Down gesture starts.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onSwipeDown = delegate.onSwipeDownProperty()
|
|
||||||
|
|
||||||
def onSwipeDown_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = {
|
|
||||||
onSwipeDown() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a Swipe Down gesture starts.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onSwipeLeft = delegate.onSwipeLeftProperty()
|
|
||||||
|
|
||||||
def onSwipeLeft_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = {
|
|
||||||
onSwipeLeft() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a Swipe Up gesture starts.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onSwipeUp = delegate.onSwipeUpProperty()
|
|
||||||
|
|
||||||
def onSwipeUp_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = {
|
|
||||||
onSwipeUp() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a Swipe Right gesture starts.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onSwipeRight = delegate.onSwipeRightProperty()
|
|
||||||
|
|
||||||
def onSwipeRight_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = {
|
|
||||||
onSwipeRight() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when user performs a Touch action.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onZoom = delegate.onZoomProperty()
|
|
||||||
|
|
||||||
def onZoom_=(v: jfxe.EventHandler[_ >: jfxsi.ZoomEvent]): Unit = {
|
|
||||||
onZoom() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a Zoom gesture ends.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onZoomFinished = delegate.onZoomFinishedProperty()
|
|
||||||
|
|
||||||
def onZoomFinished_=(v: jfxe.EventHandler[_ >: jfxsi.ZoomEvent]): Unit = {
|
|
||||||
onZoomFinished() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when a Zoom gesture starts.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onZoomStarted = delegate.onZoomStartedProperty()
|
|
||||||
|
|
||||||
def onZoomStarted_=(v: jfxe.EventHandler[_ >: jfxsi.ZoomEvent]): Unit = {
|
|
||||||
onZoomStarted() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when user performs a Touch Moved action.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onTouchMoved = delegate.onTouchMovedProperty()
|
|
||||||
|
|
||||||
def onTouchMoved_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = {
|
|
||||||
onTouchMoved() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when user performs a Touch Pressed action.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onTouchPressed = delegate.onTouchPressedProperty()
|
|
||||||
|
|
||||||
def onTouchPressed_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = {
|
|
||||||
onTouchPressed() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when user performs a Touch Released action.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onTouchReleased = delegate.onTouchReleasedProperty()
|
|
||||||
|
|
||||||
def onTouchReleased_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = {
|
|
||||||
onTouchReleased() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a function to be called when user performs a Touch Stationary action.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def onTouchStationary = delegate.onTouchStationaryProperty()
|
|
||||||
|
|
||||||
def onTouchStationary_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = {
|
|
||||||
onTouchStationary() = v
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a snapshot of this scene and returns the rendered image when it is ready.
|
|
||||||
*
|
|
||||||
* @param image The writable image that will be used to hold the rendered scene.
|
|
||||||
* @return the rendered image
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def snapshot(image: WritableImage): WritableImage = delegate.snapshot(image)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a snapshot of this scene at the next frame and calls the specified callback method when the image is ready.
|
|
||||||
*
|
|
||||||
* @param callback A function to be called when the image is ready.
|
|
||||||
* @param image The writable image that will be used to hold the rendered scene.
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
def snapshot(callback: SnapshotResult => Unit, image: WritableImage): Unit = {
|
|
||||||
val javaCallback = new jfxu.Callback[jfxs.SnapshotResult, java.lang.Void] {
|
|
||||||
def call(result: jfxs.SnapshotResult): java.lang.Void = {
|
|
||||||
callback(new SnapshotResult(result))
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delegate.snapshot(javaCallback, image)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -4,10 +4,8 @@ import java.io.ByteArrayOutputStream
|
|||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
|
|
||||||
import cats.effect.Resource
|
|
||||||
import monix.bio.Task
|
|
||||||
import scalafx.scene.control.TextArea
|
|
||||||
import scalafx.application.Platform
|
import scalafx.application.Platform
|
||||||
|
import scalafx.scene.control.TextArea
|
||||||
|
|
||||||
trait ConsoleStreamable[T] {
|
trait ConsoleStreamable[T] {
|
||||||
def println(inst: T, text: String): Unit
|
def println(inst: T, text: String): Unit
|
||||||
@ -18,7 +16,8 @@ class GenericConsoleStream[T](
|
|||||||
outputStream: OutputStream,
|
outputStream: OutputStream,
|
||||||
val config: GenericConsoleStream.Config =
|
val config: GenericConsoleStream.Config =
|
||||||
GenericConsoleStream.Config.default,
|
GenericConsoleStream.Config.default,
|
||||||
private var streamable: Option[T] = None
|
// TODO make this atomic
|
||||||
|
private var _streamable: Option[T] = None
|
||||||
)(implicit
|
)(implicit
|
||||||
cs: ConsoleStreamable[T]
|
cs: ConsoleStreamable[T]
|
||||||
) extends PrintStream(outputStream, true) {
|
) extends PrintStream(outputStream, true) {
|
||||||
@ -29,26 +28,24 @@ class GenericConsoleStream[T](
|
|||||||
|
|
||||||
override def println(text: String): Unit =
|
override def println(text: String): Unit =
|
||||||
if (config.exclusive) {
|
if (config.exclusive) {
|
||||||
printToStreamable(streamable, text)
|
printToStreamable(_streamable, text)
|
||||||
} else {
|
} else {
|
||||||
defaultOut.println(text)
|
defaultOut.println(text)
|
||||||
printToStreamable(streamable, text)
|
printToStreamable(_streamable, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def print(text: String): Unit =
|
override def print(text: String): Unit =
|
||||||
streamable.foreach(s =>
|
|
||||||
if (config.exclusive) {
|
if (config.exclusive) {
|
||||||
printToStreamable(streamable, text)
|
printToStreamable(_streamable, text)
|
||||||
} else {
|
} else {
|
||||||
defaultOut.println(text)
|
defaultOut.println(text)
|
||||||
printToStreamable(streamable, text)
|
printToStreamable(_streamable, text)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
def :=(s: T) = {
|
def :=(s: T) = {
|
||||||
streamable match {
|
_streamable match {
|
||||||
case Some(value) =>
|
case Some(value) =>
|
||||||
case None => streamable = Some(s)
|
case None => _streamable = Some(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,41 +61,25 @@ object GenericConsoleStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
implicit val implJFXConsoleStreamForTextArea =
|
implicit val implJFXConsoleStreamForTextArea =
|
||||||
new ConsoleStreamable[scalafx.scene.control.TextArea] {
|
new ConsoleStreamable[TextArea] {
|
||||||
|
|
||||||
override def println(
|
override def println(
|
||||||
ta: scalafx.scene.control.TextArea,
|
ta: TextArea,
|
||||||
text: String
|
text: String
|
||||||
): Unit =
|
): Unit =
|
||||||
ta.appendText(text + "\n")
|
Platform.runLater(() => ta.appendText(text + "\n"))
|
||||||
|
|
||||||
override def print(
|
override def print(
|
||||||
ta: scalafx.scene.control.TextArea,
|
ta: TextArea,
|
||||||
text: String
|
text: String
|
||||||
): Unit =
|
): Unit =
|
||||||
ta.appendText(text)
|
Platform.runLater(() => ta.appendText(text))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// def textAreaStreamResource(ta: TextArea) =
|
def textAreaStream() =
|
||||||
// Resource.make(
|
|
||||||
// Task(
|
|
||||||
// new GenericConsoleStream(
|
|
||||||
// outputStream = new ByteArrayOutputStream(),
|
|
||||||
// streamable = ta
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
// )(s => Task(s.close()))
|
|
||||||
|
|
||||||
def textAreaStream(
|
|
||||||
// ta: TextArea
|
|
||||||
) =
|
|
||||||
// Task(
|
|
||||||
new GenericConsoleStream[TextArea](
|
new GenericConsoleStream[TextArea](
|
||||||
outputStream = new ByteArrayOutputStream()
|
outputStream = new ByteArrayOutputStream()
|
||||||
// streamable = ta
|
|
||||||
)
|
)
|
||||||
// )
|
|
||||||
// (s => Task(s.close()))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user