Code is in Scala, and much of it is copy/pasted (with appropriate translation to Scala) from the Zay-Es sample code for Asteroid Panic. I think I got everything that is currently in use - let me know if I missed something.
The issue is that in ToyModelFactory, there is a mouse event listener set up, but I’m not seeing any of those callbacks - as evidenced by a complete lack of the appropriate logging messages.
I’m a complete neophyte, so it’s a dead certainty that I’ve missed an important item somewhere. Any hints or suggestions would be appreciated.
Main.scala:
object Main {
def main(args: Array[String]): Unit = {
val main = DemoApp()
main.start()
}
}
class DemoApp extends SimpleApplication(
new EntityDataState(),
new ModelState(new ToyModelFactory()),
new MainMenuState()
) {
private val logger: Logger = LoggerFactory.getLogger(getClass.getName)
override def simpleInitApp(): Unit = {
logger.debug("[DemoApp.simpleInitApp] enter.")
val settings = getContext.getSettings
// Initialize the Lemur helper instance
GuiGlobals.initialize(this)
// Setup the "retro" style for our HUD and GUI elements
val styles = GuiGlobals.getInstance.getStyles
ToyStyles.initializeStyles(styles)
}
}
MatchGameState.scala:
class MatchGameState extends BaseAppState {
private val logger: Logger = LoggerFactory.getLogger(getClass.getName)
private var app: DemoApp = _
private var assets: AssetManager = _
private var container: Container = _
private var inputManager: InputManager = _
private var x: Geometry = _
private var ed: EntityData = _
private var entities: EntitySet = _
private var cardID: EntityId = _
override def initialize(app: Application): Unit = {
logger.debug("[MatchGameState.initialize] enter")
this.app = app.asInstanceOf[DemoApp]
assets = app.getAssetManager
ed = getState(classOf[EntityDataState]).getEntityData
entities = ed.getEntities(classOf[Position], classOf[Position])
cardID = ed.createEntity
ed.setComponents(
cardID,
new Position(new Vector3f(-2.0, -2.0, 0.0), new Quaternion),
new ModelType(ToyModelFactory.MATCH_CARD, "Lion")
)
logger.debug("[MatchGameState.initialize] cardID is: {}", cardID)
}
override def cleanup(app: Application): Unit = {
logger.debug("[MatchGameState.cleanup] enter.")
}
override def onEnable(): Unit = {
logger.debug("[MatchGameState.onEnable] enter.")
// app.getGuiNode.attachChild(x)
}
override def onDisable(): Unit = {
logger.debug("[MatchGameState.onDisable] enter.")
}
}
ToyModelFactory.scala:
object ToyModelFactory {
val ENTITY_ID = "entityID"
val MATCH_CARD = "match game card"
}
class ToyModelFactory extends ModelFactory {
private val logger: Logger = LoggerFactory.getLogger(getClass.getName)
private var state: ModelState = _
private var assets: AssetManager = _
private var ed: EntityData = _
override def setState(state: ModelState): Unit = {
this.state = state
this.assets = state.getApplication.getAssetManager
this.ed = state.getApplication.getStateManager.getState(classOf[EntityDataState]).getEntityData
}
override def createModel(e: Entity): Spatial = {
val modelType = e.get(classOf[ModelType])
logger.debug("[ToyModelFactory.createModel] creating: {}", modelType)
val id = e.getId.getId
val parent = new Node()
parent.setUserData(ToyModelFactory.ENTITY_ID, id)
val label = modelType.getLabel
val fileName = s"$label.png"
val t: Texture = assets.loadTexture(fileName)
val mesh = createMesh()
val front = new Geometry("Card", mesh)
front.setUserData(ToyModelFactory.ENTITY_ID, id)
front.move(-0.55f, -0.8f, 0f)
val mat = new Material(assets, "Common/MatDefs/Misc/Unshaded.j3md")
mat.setTexture("ColorMap", t)
front.setMaterial(mat)
val back = new Geometry("Card", mesh)
back.setUserData(ToyModelFactory.ENTITY_ID, id)
val mat2 = new Material(assets, "Common/MatDefs/Misc/Unshaded.j3md")
mat2.setColor("Color", ColorRGBA.Blue)
back.setMaterial(mat2)
back.move(0.55f, -0.8f, 0.01f)
back.rotate(0f, FastMath.PI, 0f)
parent.attachChild(front)
parent.attachChild(back)
MouseEventControl.addListenersToSpatial(parent, MouseListener)
parent
}
private def createMesh(): Mesh = {
val mesh = new Mesh()
val vertices = new Array[Vector3f](4)
vertices(0) = new Vector3f(0, 0, 0)
vertices(1) = new Vector3f(1.1, 0, 0)
vertices(2) = new Vector3f(0, 1.6, 0)
vertices(3) = new Vector3f(1.1, 1.6, 0)
val texCoord = new Array[Vector2f](4)
texCoord(0) = new Vector2f(0, 0)
texCoord(1) = new Vector2f(1, 0)
texCoord(2) = new Vector2f(0, 1)
texCoord(3) = new Vector2f(1, 1)
val indexes = Array(2, 0, 1, 1, 3, 2)
mesh.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertices:_*))
mesh.setBuffer(VertexBuffer.Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord:_*))
mesh.setBuffer(VertexBuffer.Type.Index, 3, BufferUtils.createIntBuffer(indexes:_*))
mesh
}
object MouseListener extends DefaultMouseListener {
override def click(event: MouseButtonEvent, target: Spatial, capture: Spatial): Unit = {
val entityID = target.getUserData(ToyModelFactory.ENTITY_ID)
logger.debug("[MouseListener.click] target: {}", entityID)
}
override def mouseButtonEvent(event: MouseButtonEvent, target: Spatial, capture: Spatial): Unit = {
val entityID = target.getUserData(ToyModelFactory.ENTITY_ID)
logger.debug("[MouseListener.mouseButtonEvent] target: {}", entityID)
}
override def mouseEntered(event: MouseMotionEvent, target: Spatial, capture: Spatial): Unit = {
val entityID = target.getUserData(ToyModelFactory.ENTITY_ID)
logger.debug("[MouseListener.mouseEntered] target: {}", entityID)
}
override def mouseExited(event: MouseMotionEvent, target: Spatial, capture: Spatial): Unit = {
val entityID = target.getUserData(ToyModelFactory.ENTITY_ID)
logger.debug("[MouseListener.mouseExited] target: {}", entityID)
}
override def mouseMoved(event: MouseMotionEvent, target: Spatial, capture: Spatial): Unit = {
val entityID = target.getUserData(ToyModelFactory.ENTITY_ID)
logger.debug("[MouseListener.mouseMoved] target: {}", entityID)
}
}
}
MainMenuState.scala:
class MainMenuState() extends BaseAppState {
private val logger: Logger = LoggerFactory.getLogger(getClass.getName)
private var menu: Container = _
override def initialize(app: Application): Unit = {
logger.debug("[MainMenuState.initialize] enter.")
menu = new Container(new SpringGridLayout, new ElementId(ToyStyles.MENU_ID), "retro")
menu.addChild(new Label("Match Game", new ElementId(ToyStyles.MENU_TITLE_ID), "retro"))
val start = menu.addChild(new Button("Start Game", "retro"))
start.addClickCommands(new Start())
start.addCommands(Button.ButtonAction.HighlightOn, new Highlight())
val exit = menu.addChild(new Button("Exit", "retro"))
exit.addClickCommands(new Stop())
exit.addCommands(Button.ButtonAction.HighlightOn, new Highlight())
val cam = app.getCamera
val menuScale = cam.getHeight / 720f
val pref = menu.getPreferredSize
menu.setLocalTranslation(cam.getWidth * 0.5f - pref.x * 0.5f * menuScale, cam.getHeight * 0.75f + pref.y * 0.5f * menuScale, 10)
menu.setLocalScale(menuScale)
}
override def cleanup(app: Application): Unit = {
logger.debug("[MainMenuState.cleanup] enter.")
}
override def onEnable(): Unit = {
logger.debug("[MainMenuState.onEnable] enter.")
val app = getApplication.asInstanceOf[DemoApp]
app.getGuiNode.attachChild(menu)
}
override def onDisable(): Unit = {
logger.debug("[MainMenuState.onDisable] enter.")
menu.removeFromParent()
}
private class Highlight extends Command[Button] {
override def execute(source: Button): Unit = {
logger.debug("[Highlight.execute] enter.")
}
}
private class Start extends Command[Button] {
override def execute(source: Button): Unit = {
logger.debug("[Start.execute] enter.")
getStateManager.attach(new MatchGameState)
setEnabled(false)
}
}
private class Stop extends Command[Button] {
override def execute(source: Button): Unit = {
logger.debug("[Stop.execute] enter.")
getApplication.stop()
}
}
}
ModelType.scala:
/**
* A general "model type" used for entities with a visual
* display.
*
* @author Paul Speed
* Converted to Scala by IntelliJ IDEA
*/
class ModelType(private var myType: String, private var label: String) extends EntityComponent {
def getType: String = myType
def getLabel: String = label
override def toString: String = s"ModelType[$myType, $label]"
}
EntityDataState.scala:
/**
* AppState providing convenient access to the global
* ES entity data. It also properly cleans up the ES
* upon termination.
*
* @author Paul Speed
* Converted to Scala by IntelliJ IDEA
*/
class EntityDataState(private var entityData: EntityData) extends BaseAppState {
private val logger: Logger = LoggerFactory.getLogger(getClass.getName)
def this() = {
this(new DefaultEntityData)
}
def getEntityData: EntityData = entityData
override protected def initialize(app: Application): Unit = {
}
override protected def cleanup(app: Application): Unit = {
entityData.close()
entityData = null // cannot be reused
}
override protected def onEnable(): Unit = {
}
override protected def onDisable(): Unit = {
}
}
ModelFactory.scala:
/**
* Called by the ModelState to create new Spatials when
* required.
*
* @author Paul Speed
* Converted to Scala by IntelliJ IDEA
*/
trait ModelFactory {
def setState(state: ModelState): Unit
def createModel(e: Entity): Spatial
}
Position.scala:
/**
* Represents a position and orientation of an entity.
*
* @author Paul Speed
* Converted to Scala by IntelliJ IDEA
*/
class Position(private var location: Vector3f, private var facing: Quaternion) extends EntityComponent {
def getLocation: Vector3f = location
def getFacing: Quaternion = facing
override def toString: String = "Position[" + location + ", " + facing + "]"
}