package wow.doge.mygame.game.subsystems.level import cats.effect.Resource import com.jme3.bullet.control.RigidBodyControl import com.jme3.light.AmbientLight import com.jme3.light.DirectionalLight import com.jme3.scene.Node import com.jme3.scene.Spatial import com.softwaremill.tagging._ import monix.bio.IO import monix.bio.Task import monix.bio.UIO import wow.doge.mygame.game.GameAppTags import wow.doge.mygame.utils.wrappers.jme.AppNode import wow.doge.mygame.utils.wrappers.jme.AssetManager import wow.doge.mygame.utils.wrappers.jme.CollisionShapeFactory import wow.doge.mygame.utils.wrappers.jme.PhysicsSpace class GameLevel( val model: Spatial, val physicsControl: RigidBodyControl, val ambientLight: AmbientLight, val directionalLight: DirectionalLight ) { def addToGame( rootNode: AppNode[Task] @@ GameAppTags.RootNode, physicsSpace: PhysicsSpace[Task] ) = { for { _ <- rootNode += model _ <- rootNode += ambientLight _ <- rootNode += directionalLight _ <- physicsSpace += model _ <- physicsSpace += physicsControl } yield () } def removeFromGame( rootNode: AppNode[Task] @@ GameAppTags.RootNode, physicsSpace: PhysicsSpace[Task] ) = { for { _ <- rootNode -= model _ <- rootNode -= ambientLight _ <- rootNode -= directionalLight _ <- physicsSpace -= model _ <- physicsSpace -= physicsControl } yield () } def resource( rootNode: AppNode[Task] @@ GameAppTags.RootNode, physicsSpace: PhysicsSpace[Task] ) = Resource.make(this.addToGame(rootNode, physicsSpace))(_ => this.removeFromGame(rootNode, physicsSpace) ) } object GameLevel { sealed trait Error case class AssetLoadError(err: AssetManager.Error) extends Error case class CollisionShapeCreationFailed(err: CollisionShapeFactory.Error) extends Error def apply( modelPath: os.RelPath, al: AmbientLight, dl: DirectionalLight )(implicit assetManager: wow.doge.mygame.utils.wrappers.jme.AssetManager ): IO[Error, GameLevel] = for { sceneModel <- assetManager .loadModelAs[Node](modelPath) .mapError(AssetLoadError) sceneShape <- CollisionShapeFactory .createMeshShape(sceneModel) .mapError(CollisionShapeCreationFailed) landscape <- UIO(new RigidBodyControl(sceneShape, 0)) } yield new GameLevel( model = sceneModel, physicsControl = landscape, ambientLight = al, directionalLight = dl ) }