[Editor] Enable opening map on double-click on project structure panel
This commit is contained in:
@@ -4,6 +4,7 @@ import com.bartlomiejpluta.base.editor.command.context.UndoableScope
|
||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
||||
import com.bartlomiejpluta.base.editor.map.view.wizard.MapCreationWizard
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapBuilderVM
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import com.bartlomiejpluta.base.editor.project.view.ProjectSettingsFragment
|
||||
@@ -27,6 +28,7 @@ class MainController : Controller() {
|
||||
val modal = find<ProjectSettingsFragment>().apply { openModal(block = true, resizable = false) }
|
||||
|
||||
if (modal.result) {
|
||||
openMaps.clear()
|
||||
projectContext.project = project
|
||||
projectContext.save()
|
||||
}
|
||||
@@ -49,10 +51,24 @@ class MainController : Controller() {
|
||||
}
|
||||
}
|
||||
|
||||
fun loadProject() {
|
||||
fun openProject() {
|
||||
chooseFile(
|
||||
title = "Load Project",
|
||||
filters = arrayOf(FileChooser.ExtensionFilter("BASE Editor Project (*.bep)", "*.bep")),
|
||||
).getOrNull(0)?.let { projectContext.open(it) }
|
||||
).getOrNull(0)?.let {
|
||||
openMaps.clear()
|
||||
projectContext.open(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun openMap(uid: String) {
|
||||
if (openMaps.count { (_, map) -> map.uid == uid } == 0) {
|
||||
val map = projectContext.loadMap(uid)
|
||||
val vm = GameMapVM(map)
|
||||
val scope = UndoableScope()
|
||||
setInScope(vm, scope)
|
||||
|
||||
openMaps[scope] = map
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ class MainMenuView : View() {
|
||||
menu("Open") {
|
||||
item("Project...") {
|
||||
action {
|
||||
mainController.loadProject()
|
||||
mainController.openProject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ import com.bartlomiejpluta.base.editor.main.controller.MainController
|
||||
import com.bartlomiejpluta.base.editor.map.view.editor.MapFragment
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import javafx.beans.InvalidationListener
|
||||
import javafx.beans.Observable
|
||||
import javafx.collections.MapChangeListener
|
||||
import javafx.scene.control.Tab
|
||||
import tornadofx.*
|
||||
|
||||
@@ -35,6 +38,15 @@ class MainView : View("BASE Game Editor") {
|
||||
setOnClosed { mainController.openMaps.remove(scope) }
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME
|
||||
// For some reason cleaning mainController.openMaps just takes off the tabs content keeping open themselves.
|
||||
// The workaround is to detect if map is cleaned and the clean the tabs by hand.
|
||||
mainController.openMaps.addListener(MapChangeListener {
|
||||
if(it.map.isEmpty()) {
|
||||
tabs.clear()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
left = projectStructureView.root
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package com.bartlomiejpluta.base.editor.main.view
|
||||
|
||||
import com.bartlomiejpluta.base.editor.main.controller.MainController
|
||||
import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import com.bartlomiejpluta.base.editor.util.fx.BindingUtil
|
||||
import javafx.beans.binding.Bindings
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.scene.control.TreeItem
|
||||
import javafx.scene.input.MouseEvent
|
||||
import org.kordamp.ikonli.javafx.FontIcon
|
||||
import tornadofx.*
|
||||
|
||||
|
||||
class ProjectStructureView : View() {
|
||||
private val projectContext: ProjectContext by di()
|
||||
private val mainController: MainController by di()
|
||||
|
||||
private val structureMaps = StructureCategory("Maps")
|
||||
|
||||
@@ -23,6 +25,7 @@ class ProjectStructureView : View() {
|
||||
project?.let {
|
||||
structureRoot.nameProperty.bind(it.nameProperty)
|
||||
Bindings.bindContent(structureMaps.items, project.maps)
|
||||
root.root.expandAll()
|
||||
root.refresh()
|
||||
}
|
||||
}
|
||||
@@ -52,6 +55,14 @@ class ProjectStructureView : View() {
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
setOnMouseClicked { event ->
|
||||
if(event.clickCount == 2) {
|
||||
when(val item = selectionModel?.selectedItem?.value) {
|
||||
is GameMapAsset -> mainController.openMap(item.uid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class StructureCategory(name: String = "", var items: ObservableList<out Any> = observableListOf()) {
|
||||
|
||||
@@ -3,18 +3,17 @@ package com.bartlomiejpluta.base.editor.project.context
|
||||
import com.bartlomiejpluta.base.editor.asset.model.Asset
|
||||
import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset
|
||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
||||
import com.bartlomiejpluta.base.editor.map.serial.MapDeserializer
|
||||
import com.bartlomiejpluta.base.editor.map.serial.MapSerializer
|
||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||
import com.bartlomiejpluta.base.editor.project.serial.ProjectDeserializer
|
||||
import com.bartlomiejpluta.base.editor.project.serial.ProjectSerializer
|
||||
import com.bartlomiejpluta.base.editor.util.uid.UID
|
||||
import javafx.beans.property.ObjectProperty
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Component
|
||||
import tornadofx.getValue
|
||||
import tornadofx.select
|
||||
import tornadofx.setValue
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
@@ -32,23 +31,15 @@ class DefaultProjectContext : ProjectContext {
|
||||
@Autowired
|
||||
private lateinit var mapSerializer: MapSerializer
|
||||
|
||||
@Autowired
|
||||
private lateinit var mapDeserializer: MapDeserializer
|
||||
|
||||
override val projectProperty = SimpleObjectProperty<Project?>() as ObjectProperty<Project?>
|
||||
override var project by projectProperty
|
||||
|
||||
private val mapsDirectoryProperty = SimpleObjectProperty<File?>()
|
||||
private val mapsDirectory by mapsDirectoryProperty
|
||||
|
||||
init {
|
||||
projectProperty.addListener { _, _, newProject ->
|
||||
when(newProject) {
|
||||
null -> {
|
||||
mapsDirectoryProperty.value = null
|
||||
}
|
||||
|
||||
else -> {
|
||||
mapsDirectoryProperty.value = File(newProject.sourceDirectory, MAPS_DIR).apply(File::mkdirs)
|
||||
}
|
||||
}
|
||||
newProject?.mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,12 +68,15 @@ class DefaultProjectContext : ProjectContext {
|
||||
it.maps += asset
|
||||
|
||||
save()
|
||||
File(mapsDirectory, asset.source).outputStream().use { fos -> mapSerializer.serialize(map, fos) }
|
||||
File(it.mapsDirectory, asset.source).outputStream().use { fos -> mapSerializer.serialize(map, fos) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAPS_DIR = "maps"
|
||||
}
|
||||
override fun loadMap(uid: String) = project?.let {
|
||||
val asset = it.maps.first { map -> map.uid == uid }
|
||||
?: throw IllegalStateException("The map with uid [$uid] does not exist ")
|
||||
|
||||
File(it.mapsDirectory, asset.source).inputStream().use { fis -> mapDeserializer.deserialize(fis) }
|
||||
} ?: throw IllegalStateException("There is no open project in the context")
|
||||
}
|
||||
@@ -13,4 +13,5 @@ interface ProjectContext {
|
||||
fun open(file: File)
|
||||
|
||||
fun importMap(name: String, map: GameMap)
|
||||
fun loadMap(uid: String): GameMap
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.bartlomiejpluta.base.editor.project.model
|
||||
|
||||
import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset
|
||||
import com.bartlomiejpluta.base.editor.project.context.DefaultProjectContext
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import tornadofx.getValue
|
||||
@@ -16,4 +17,23 @@ class Project {
|
||||
val sourceDirectory by sourceDirectoryProperty
|
||||
|
||||
val maps = observableListOf<GameMapAsset>()
|
||||
|
||||
val mapsDirectoryProperty = SimpleObjectProperty<File>()
|
||||
var mapsDirectory by mapsDirectoryProperty
|
||||
private set
|
||||
|
||||
init {
|
||||
sourceDirectoryProperty.addListener { _, _, dir ->
|
||||
dir?.let { mapsDirectory = File(it, MAPS_DIR) }
|
||||
}
|
||||
}
|
||||
|
||||
fun mkdirs() {
|
||||
sourceDirectory?.mkdirs()
|
||||
mapsDirectory?.mkdirs()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAPS_DIR = "maps"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user