package fmon.builder import java.io._ import javafx.application.Application import javafx.fxml.FXML import javafx.fxml.FXMLLoader import javafx.fxml.JavaFXBuilderFactory import javafx.scene.{control => jfxsc, layout => jfxsl, Parent, Scene} import javafx.stage.Stage import scalafx.Includes._ import scalafx.beans.property._ import scalafx.collections.ObservableBuffer import scalafx.scene.control._ import scalafx.scene.image.ImageView import scalafx.scene.input.MouseEvent import scalafx.scene.paint.Color import scalafx.scene.layout._ import fmon.Config import fmon.draw.tile.{AutoTile, AutoTilePalette} import fmon.util.YamlHelper import fmon.world.{Tileset, TileInfo, TilesetToken} class ObsTileset(name_ : String) { val name = new StringProperty(this, "name", name_) val a1 = new ObjectProperty[File](this, "a1", null) val a2 = new ObjectProperty[File](this, "a2", null) val a3 = new ObjectProperty[File](this, "a3", null) val a4 = new ObjectProperty[File](this, "a4", null) val a5 = new ObjectProperty[File](this, "a5", null) val b = new ObjectProperty[File](this, "b", null) val c = new ObjectProperty[File](this, "c", null) val a1Size = new IntegerProperty(this, "a1size", 0) val a2Size = new IntegerProperty(this, "a2size", 0) val a3Size = new IntegerProperty(this, "a3size", 0) val a4Size = new IntegerProperty(this, "a4size", 0) val a5Size = new IntegerProperty(this, "a5size", 0) val bSize = new IntegerProperty(this, "bsize", 0) val cSize = new IntegerProperty(this, "csize", 0) val tileInfo = ObservableBuffer[TileInfo]() def toToken = { def nm(file: File) = if (file != null) file.getName else null println(tileInfo.size) TilesetToken(name(), nm(a1()), nm(a2()), nm(a3()), nm(a4()), nm(a5()), nm(b()), nm(c()), IndexedSeq(tileInfo: _*)) } override def toString = name() } class TilesetBuilder extends Savable { @FXML var tilesetList: jfxsc.ListView[ObsTileset] = _ @FXML var nameField: jfxsc.TextField = _ @FXML var a1Chooser: jfxsc.ComboBox[File] = _ @FXML var a2Chooser: jfxsc.ComboBox[File] = _ @FXML var a3Chooser: jfxsc.ComboBox[File] = _ @FXML var a4Chooser: jfxsc.ComboBox[File] = _ @FXML var a5Chooser: jfxsc.ComboBox[File] = _ @FXML var bChooser: jfxsc.ComboBox[File] = _ @FXML var cChooser: jfxsc.ComboBox[File] = _ @FXML var tileView: jfxsl.TilePane = _ @FXML var doesPassNorth: jfxsc.CheckBox = _ @FXML var doesPassEast: jfxsc.CheckBox = _ @FXML var doesPassSouth: jfxsc.CheckBox = _ @FXML var doesPassWest: jfxsc.CheckBox = _ @FXML var isCounter: jfxsc.CheckBox = _ val tilesets = ObservableBuffer[ObsTileset]() var a1Palette = IndexedSeq[AutoTile]() var a2Palette = IndexedSeq[AutoTile]() var a3Palette = IndexedSeq[AutoTile]() var a4Palette = IndexedSeq[AutoTile]() var a5Palette = IndexedSeq[AutoTile]() var bPalette = IndexedSeq[AutoTile]() var cPalette = IndexedSeq[AutoTile]() val resourceDir = new File(raw"C:\Users\James\Documents\Design\Project\Progena\Resources\tilesets") val files = resourceDir.listFiles() val filenames = files.map(f => (f.getName(), f)).toMap var currTileIndex = 0 def currTileset = getSelected(tilesetList) @FXML def initialize(): Unit = { tilesetList.items = tilesets tilesetList.selectionModel().selectedIndex.onChange(selectionChange) a1Chooser.converter = FilenameConverter a2Chooser.converter = FilenameConverter a3Chooser.converter = FilenameConverter a4Chooser.converter = FilenameConverter a5Chooser.converter = FilenameConverter bChooser.converter = FilenameConverter cChooser.converter = FilenameConverter a1Chooser.items() ++= null +: files.filter(f => f.getName.endsWith("A1.png")) a2Chooser.items() ++= null +: files.filter(f => f.getName.endsWith("A2.png")) a3Chooser.items() ++= null +: files.filter(f => f.getName.endsWith("A3.png")) a4Chooser.items() ++= null +: files.filter(f => f.getName.endsWith("A4.png")) a5Chooser.items() ++= null +: files.filter(f => f.getName.endsWith("A5.png")) bChooser.items() ++= null +: files.filter(f => f.getName.endsWith("B.png")) cChooser.items() ++= null +: files.filter(f => f.getName.endsWith("C.png")) println(files.size) } def addTileset(): Unit = { tilesets += new ObsTileset("Tileset") tilesetList.selectionModel().selectLast() } def selectionChange(): Unit = { val ts = getSelected(tilesetList) nameField.text = ts.name() def safeSelect(box: ComboBox[File], file: File) = { box.selectionModel().clearSelection() box.selectionModel().select(file) } safeSelect(a1Chooser, ts.a1()) safeSelect(a2Chooser, ts.a2()) safeSelect(a3Chooser, ts.a3()) safeSelect(a4Chooser, ts.a4()) safeSelect(a5Chooser, ts.a5()) safeSelect(bChooser, ts.b()) safeSelect(cChooser, ts.c()) } def setName(): Unit = { getSelected(tilesetList).name.value = nameField.text() tilesetList.refresh() } def setA1(): Unit = { currTileset.a1.value = getSelected(a1Chooser) a1Palette = if (getSelected(a1Chooser) == null) IndexedSeq() else AutoTilePalette.a2(getSelected(a1Chooser), Config.tileSize).tiles if (a1Palette.size != currTileset.a1Size()) { currTileset.tileInfo.removeRange(0, currTileset.a1Size()) currTileset.a1Size() = a1Palette.size val info = a1Palette.map(_ => allPassInfo) currTileset.tileInfo.insert(0, info : _*) } updateTileView() } def setA2(): Unit = { currTileset.a2.value = getSelected(a2Chooser) a2Palette = if (getSelected(a2Chooser) == null) IndexedSeq() else AutoTilePalette.a2(getSelected(a2Chooser), Config.tileSize).tiles if (a2Palette.size != currTileset.a2Size()) { val priorSize = currTileset.a2Size() currTileset.tileInfo.removeRange(priorSize, priorSize + currTileset.a2Size()) currTileset.a2Size() = a1Palette.size val info = a2Palette.map(_ => allPassInfo) currTileset.tileInfo.insert(priorSize, info : _*) } updateTileView() } def setA3(): Unit = { currTileset.a3.value = getSelected(a3Chooser) a3Palette = if (getSelected(a3Chooser) == null) IndexedSeq() else AutoTilePalette.a3(getSelected(a3Chooser), Config.tileSize).tiles if (a3Palette.size != currTileset.a3Size()) { val priorSize = currTileset.a1Size() + currTileset.a2Size() currTileset.tileInfo.removeRange(priorSize, priorSize + currTileset.a3Size()) currTileset.a3Size() = a1Palette.size val info = a3Palette.map(_ => allPassInfo) currTileset.tileInfo.insert(priorSize, info : _*) } updateTileView() } def setA4(): Unit = { currTileset.a4.value = getSelected(a4Chooser) a4Palette = if (getSelected(a4Chooser) == null) IndexedSeq() else AutoTilePalette.a4(getSelected(a4Chooser), Config.tileSize).tiles if (a4Palette.size != currTileset.a4Size()) { val priorSize = currTileset.a1Size() + currTileset.a2Size() + currTileset.a3Size() currTileset.tileInfo.removeRange(priorSize, priorSize + currTileset.a4Size()) currTileset.a4Size() = a4Palette.size val info = a4Palette.map(_ => allPassInfo) currTileset.tileInfo.insert(priorSize, info : _*) } updateTileView() } def setA5(): Unit = { currTileset.a5.value = getSelected(a5Chooser) a5Palette = if (getSelected(a5Chooser) == null) IndexedSeq() else AutoTilePalette.basic(getSelected(a5Chooser), Config.tileSize).tiles if (a5Palette.size != currTileset.a5Size()) { val priorSize = currTileset.a1Size() + currTileset.a2Size() + currTileset.a3Size() + currTileset.a4Size() currTileset.tileInfo.removeRange(priorSize, priorSize + currTileset.a5Size()) currTileset.a5Size() = a5Palette.size val info = a5Palette.map(_ => allPassInfo) currTileset.tileInfo.insert(priorSize, info : _*) } updateTileView() } def setB(): Unit = { currTileset.b.value = getSelected(bChooser) bPalette = if (getSelected(bChooser) == null) IndexedSeq() else AutoTilePalette.partitioned(getSelected(bChooser), 2, Config.tileSize).tiles if (bPalette.size != currTileset.bSize()) { val priorSize = currTileset.a1Size() + currTileset.a2Size() + currTileset.a3Size() + currTileset.a4Size() + currTileset.a5Size() currTileset.tileInfo.removeRange(priorSize, priorSize + currTileset.bSize()) currTileset.bSize() = bPalette.size val info = bPalette.map(_ => allPassInfo) currTileset.tileInfo.insert(priorSize, info : _*) } updateTileView() } def setC(): Unit = { currTileset.c.value = getSelected(cChooser) cPalette = if (getSelected(cChooser) == null) IndexedSeq() else AutoTilePalette.partitioned(getSelected(cChooser), 2, Config.tileSize).tiles if (cPalette.size != currTileset.cSize()) { val priorSize = currTileset.a1Size() + currTileset.a2Size() + currTileset.a3Size() + currTileset.a4Size() + currTileset.a5Size() + currTileset.bSize() currTileset.tileInfo.removeRange(priorSize, priorSize + currTileset.cSize()) currTileset.cSize() = cPalette.size val info = cPalette.map(_ => allPassInfo) currTileset.tileInfo.insert(priorSize, info : _*) } updateTileView() } def updateTileView(): Unit = { tileView.children.clear() val tiles = a1Palette ++ a2Palette ++ a3Palette ++ a4Palette ++ a5Palette ++ bPalette ++ cPalette tileView.children ++= tiles.zipWithIndex.map{case (t, i) => new ImageView(t.icon.croppedImage()){ handleEvent(MouseEvent.Any) { e: MouseEvent => if (e.eventType == MouseEvent.MouseClicked) { currTileIndex = i setTile(currTileset.tileInfo(i)) } } }.delegate} } def setTile(info: TileInfo): Unit = { doesPassNorth.selected = info.doesPassNorth doesPassEast.selected = info.doesPassEast doesPassSouth.selected = info.doesPassSouth doesPassWest.selected = info.doesPassWest isCounter.selected = info.isCounter } def updateTile(): Unit = { currTileset.tileInfo(currTileIndex) = TileInfo( doesPassNorth.selected(), doesPassEast.selected(), doesPassSouth.selected(), doesPassWest.selected(), isCounter.selected()) } def saveTo(file: File): Unit = { val tileSeq = tilesets.map(a => a.toToken) YamlHelper.writeSeq(new FileOutputStream(file), tileSeq) } def openFrom(file: File): Unit = { def f(name: String) = if (name != null) new File(resourceDir, name) else null val tokens = YamlHelper.extractSeq[TilesetToken](new FileInputStream(file)) tilesets.clear() tilesets ++= tokens.map(t=> { val ts = new ObsTileset(t.name) ts.a1.value = f(t.a1) ts.a2.value = f(t.a2) ts.a3.value = f(t.a3) ts.a4.value = f(t.a4) ts.a5.value = f(t.a5) ts.b.value = f(t.b) ts.c.value = f(t.c) // TODO : Individual sizes ts.tileInfo ++= t.info ts }) tilesetList.refresh() } private def allPassInfo = TileInfo(true, true, true, true, false) } object TilesetBuilder { class TBA extends Application { override def start(primaryStage: Stage): Unit = { val frameLoader = new FXMLLoader(getClass.getResource("App.fxml")) val root: Parent = frameLoader.load() val controller = frameLoader.getController[App]() val builderLoader = new FXMLLoader(getClass.getResource("TilesetBuilder.fxml")) val builder: Parent = builderLoader.load() val builderController = builderLoader.getController[TilesetBuilder]() controller.pane.children = builder controller.builder = builderController val scene: Scene = new Scene(root) primaryStage.setScene(scene) primaryStage.show() } } def main(args: Array[String]): Unit = { Application.launch(classOf[TBA], args: _*) } }