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))) } }