[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.model.map.GameMap
|
||||||
import com.bartlomiejpluta.base.editor.map.view.wizard.MapCreationWizard
|
import com.bartlomiejpluta.base.editor.map.view.wizard.MapCreationWizard
|
||||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapBuilderVM
|
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.context.ProjectContext
|
||||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||||
import com.bartlomiejpluta.base.editor.project.view.ProjectSettingsFragment
|
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) }
|
val modal = find<ProjectSettingsFragment>().apply { openModal(block = true, resizable = false) }
|
||||||
|
|
||||||
if (modal.result) {
|
if (modal.result) {
|
||||||
|
openMaps.clear()
|
||||||
projectContext.project = project
|
projectContext.project = project
|
||||||
projectContext.save()
|
projectContext.save()
|
||||||
}
|
}
|
||||||
@@ -49,10 +51,24 @@ class MainController : Controller() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadProject() {
|
fun openProject() {
|
||||||
chooseFile(
|
chooseFile(
|
||||||
title = "Load Project",
|
title = "Load Project",
|
||||||
filters = arrayOf(FileChooser.ExtensionFilter("BASE Editor Project (*.bep)", "*.bep")),
|
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") {
|
menu("Open") {
|
||||||
item("Project...") {
|
item("Project...") {
|
||||||
action {
|
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.view.editor.MapFragment
|
||||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
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 javafx.scene.control.Tab
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
@@ -35,6 +38,15 @@ class MainView : View("BASE Game Editor") {
|
|||||||
setOnClosed { mainController.openMaps.remove(scope) }
|
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
|
left = projectStructureView.root
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
package com.bartlomiejpluta.base.editor.main.view
|
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.map.asset.GameMapAsset
|
||||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||||
import com.bartlomiejpluta.base.editor.util.fx.BindingUtil
|
|
||||||
import javafx.beans.binding.Bindings
|
import javafx.beans.binding.Bindings
|
||||||
import javafx.beans.property.SimpleStringProperty
|
import javafx.beans.property.SimpleStringProperty
|
||||||
import javafx.collections.ObservableList
|
import javafx.collections.ObservableList
|
||||||
import javafx.scene.control.TreeItem
|
import javafx.scene.control.TreeItem
|
||||||
|
import javafx.scene.input.MouseEvent
|
||||||
import org.kordamp.ikonli.javafx.FontIcon
|
import org.kordamp.ikonli.javafx.FontIcon
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
|
|
||||||
class ProjectStructureView : View() {
|
class ProjectStructureView : View() {
|
||||||
private val projectContext: ProjectContext by di()
|
private val projectContext: ProjectContext by di()
|
||||||
|
private val mainController: MainController by di()
|
||||||
|
|
||||||
private val structureMaps = StructureCategory("Maps")
|
private val structureMaps = StructureCategory("Maps")
|
||||||
|
|
||||||
@@ -23,6 +25,7 @@ class ProjectStructureView : View() {
|
|||||||
project?.let {
|
project?.let {
|
||||||
structureRoot.nameProperty.bind(it.nameProperty)
|
structureRoot.nameProperty.bind(it.nameProperty)
|
||||||
Bindings.bindContent(structureMaps.items, project.maps)
|
Bindings.bindContent(structureMaps.items, project.maps)
|
||||||
|
root.root.expandAll()
|
||||||
root.refresh()
|
root.refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,6 +55,14 @@ class ProjectStructureView : View() {
|
|||||||
else -> null
|
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()) {
|
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.asset.model.Asset
|
||||||
import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset
|
import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset
|
||||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
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.map.serial.MapSerializer
|
||||||
import com.bartlomiejpluta.base.editor.project.model.Project
|
import com.bartlomiejpluta.base.editor.project.model.Project
|
||||||
import com.bartlomiejpluta.base.editor.project.serial.ProjectDeserializer
|
import com.bartlomiejpluta.base.editor.project.serial.ProjectDeserializer
|
||||||
import com.bartlomiejpluta.base.editor.project.serial.ProjectSerializer
|
import com.bartlomiejpluta.base.editor.project.serial.ProjectSerializer
|
||||||
import com.bartlomiejpluta.base.editor.util.uid.UID
|
import com.bartlomiejpluta.base.editor.util.uid.UID
|
||||||
import javafx.beans.property.ObjectProperty
|
import javafx.beans.property.ObjectProperty
|
||||||
import javafx.beans.property.ReadOnlyObjectWrapper
|
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
import tornadofx.getValue
|
import tornadofx.getValue
|
||||||
import tornadofx.select
|
|
||||||
import tornadofx.setValue
|
import tornadofx.setValue
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
@@ -32,23 +31,15 @@ class DefaultProjectContext : ProjectContext {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private lateinit var mapSerializer: MapSerializer
|
private lateinit var mapSerializer: MapSerializer
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private lateinit var mapDeserializer: MapDeserializer
|
||||||
|
|
||||||
override val projectProperty = SimpleObjectProperty<Project?>() as ObjectProperty<Project?>
|
override val projectProperty = SimpleObjectProperty<Project?>() as ObjectProperty<Project?>
|
||||||
override var project by projectProperty
|
override var project by projectProperty
|
||||||
|
|
||||||
private val mapsDirectoryProperty = SimpleObjectProperty<File?>()
|
|
||||||
private val mapsDirectory by mapsDirectoryProperty
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
projectProperty.addListener { _, _, newProject ->
|
projectProperty.addListener { _, _, newProject ->
|
||||||
when(newProject) {
|
newProject?.mkdirs()
|
||||||
null -> {
|
|
||||||
mapsDirectoryProperty.value = null
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
mapsDirectoryProperty.value = File(newProject.sourceDirectory, MAPS_DIR).apply(File::mkdirs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,12 +68,15 @@ class DefaultProjectContext : ProjectContext {
|
|||||||
it.maps += asset
|
it.maps += asset
|
||||||
|
|
||||||
save()
|
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 {
|
override fun loadMap(uid: String) = project?.let {
|
||||||
const val MAPS_DIR = "maps"
|
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 open(file: File)
|
||||||
|
|
||||||
fun importMap(name: String, map: GameMap)
|
fun importMap(name: String, map: GameMap)
|
||||||
|
fun loadMap(uid: String): GameMap
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.bartlomiejpluta.base.editor.project.model
|
package com.bartlomiejpluta.base.editor.project.model
|
||||||
|
|
||||||
import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset
|
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.SimpleObjectProperty
|
||||||
import javafx.beans.property.SimpleStringProperty
|
import javafx.beans.property.SimpleStringProperty
|
||||||
import tornadofx.getValue
|
import tornadofx.getValue
|
||||||
@@ -16,4 +17,23 @@ class Project {
|
|||||||
val sourceDirectory by sourceDirectoryProperty
|
val sourceDirectory by sourceDirectoryProperty
|
||||||
|
|
||||||
val maps = observableListOf<GameMapAsset>()
|
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