From 8621647ece70e84f570f78211fe0f95d694cc0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zsur=C3=B3=20Tibor?= Date: Sun, 17 Apr 2022 19:59:16 +0000 Subject: [PATCH] New terrain generation design --- .../components/terrain/TerrainGenTab.kt | 123 ++++-------------- .../terrain/generation/HeightmapTab.kt | 85 ++++++++++++ .../terrain/generation/PerlinNoiseTab.kt | 68 ++++++++++ 3 files changed, 177 insertions(+), 99 deletions(-) create mode 100644 editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/generation/HeightmapTab.kt create mode 100644 editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/generation/PerlinNoiseTab.kt diff --git a/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/TerrainGenTab.kt b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/TerrainGenTab.kt index 12001ee49..8876f31dc 100644 --- a/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/TerrainGenTab.kt +++ b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/TerrainGenTab.kt @@ -16,129 +16,54 @@ package com.mbrlabs.mundus.editor.ui.modules.inspector.components.terrain -import com.badlogic.gdx.files.FileHandle -import com.badlogic.gdx.graphics.Pixmap -import com.badlogic.gdx.scenes.scene2d.InputEvent import com.badlogic.gdx.scenes.scene2d.ui.Table -import com.badlogic.gdx.scenes.scene2d.utils.ClickListener -import com.badlogic.gdx.utils.Align -import com.kotcrab.vis.ui.util.dialog.Dialogs -import com.kotcrab.vis.ui.widget.VisLabel import com.kotcrab.vis.ui.widget.VisTable -import com.kotcrab.vis.ui.widget.VisTextButton import com.kotcrab.vis.ui.widget.tabbedpane.Tab -import com.mbrlabs.mundus.editor.Mundus -import com.mbrlabs.mundus.editor.core.project.ProjectManager -import com.mbrlabs.mundus.editor.history.CommandHistory -import com.mbrlabs.mundus.editor.history.commands.TerrainHeightCommand -import com.mbrlabs.mundus.editor.terrain.Terraformer -import com.mbrlabs.mundus.editor.ui.UI -import com.mbrlabs.mundus.editor.ui.widgets.FileChooserField -import com.mbrlabs.mundus.editor.ui.widgets.FloatFieldWithLabel -import com.mbrlabs.mundus.editor.ui.widgets.IntegerFieldWithLabel -import com.mbrlabs.mundus.editor.utils.isImage +import com.kotcrab.vis.ui.widget.tabbedpane.TabbedPane +import com.kotcrab.vis.ui.widget.tabbedpane.TabbedPaneListener +import com.mbrlabs.mundus.editor.ui.modules.inspector.components.terrain.generation.HeightmapTab +import com.mbrlabs.mundus.editor.ui.modules.inspector.components.terrain.generation.PerlinNoiseTab /** * @author Marcus Brummer * @version 04-03-2016 */ -class TerrainGenTab(private val parent: TerrainComponentWidget) : Tab(false, false) { +class TerrainGenTab(private val parent: TerrainComponentWidget) : Tab(false, false), TabbedPaneListener { private val root = VisTable() - private val hmInput = FileChooserField() - private val loadHeightMapBtn = VisTextButton("Load heightmap") + private val tabbedPane = TabbedPane() + private val tabContainer = VisTable() - private val perlinNoiseBtn = VisTextButton("Generate Perlin noise") - private val perlinNoiseSeed = IntegerFieldWithLabel("Seed", -1, false) - private val perlinNoiseMinHeight = FloatFieldWithLabel("Min height", -1, true) - private val perlinNoiseMaxHeight = FloatFieldWithLabel("Max height", -1, true) - - private val history: CommandHistory = Mundus.inject() - private val projectManager: ProjectManager = Mundus.inject() + private val heightmapTab = HeightmapTab(parent.component.terrain) + private val perlinNoiseTab = PerlinNoiseTab(parent.component.terrain) init { - root.align(Align.left) - - root.add(VisLabel("Load Heightmap")).pad(5f).left().row() - root.add(hmInput).left().expandX().fillX().row() - root.add(loadHeightMapBtn).padLeft(5f).left().row() - - root.add(VisLabel("Perlin Noise")).pad(5f).padTop(10f).left().row() - root.add(perlinNoiseSeed).pad(5f).left().fillX().expandX().row() - root.add(perlinNoiseMinHeight).pad(5f).left().fillX().expandX().row() - root.add(perlinNoiseMaxHeight).pad(5f).left().fillX().expandX().row() - root.add(perlinNoiseBtn).pad(5f).left().row() - - setupListeners() - } + tabbedPane.addListener(this) - private fun setupListeners() { - loadHeightMapBtn.addListener(object : ClickListener() { - override fun clicked(event: InputEvent?, x: Float, y: Float) { - val hm = hmInput.file - if (hm != null && hm.exists() && isImage(hm)) { - loadHeightMap(hm) - projectManager.current().assetManager.addDirtyAsset(parent.component.terrain) - } else { - Dialogs.showErrorDialog(UI, "Please select a heightmap image") - } - } - }) + tabbedPane.add(heightmapTab) + tabbedPane.add(perlinNoiseTab) - perlinNoiseBtn.addListener(object : ClickListener() { - override fun clicked(event: InputEvent?, x: Float, y: Float) { - val seed = perlinNoiseSeed.int - val min = perlinNoiseMinHeight.float - val max = perlinNoiseMaxHeight.float - generatePerlinNoise(seed, min, max) - projectManager.current().assetManager.addDirtyAsset(parent.component.terrain) - } - }) + root.add(tabbedPane.table).growX().row() + root.add(tabContainer).expand().fill().row() + tabbedPane.switchTab(0) } - private fun loadHeightMap(heightMap: FileHandle) { - val terrain = parent.component.terrain.terrain - val command = TerrainHeightCommand(terrain) - command.setHeightDataBefore(terrain.heightData) - - val originalMap = Pixmap(heightMap) - - // scale pixmap if it doesn't fit the terrainAsset - if (originalMap.width != terrain.vertexResolution || originalMap.height != terrain.vertexResolution) { - val scaledPixmap = Pixmap(terrain.vertexResolution, terrain.vertexResolution, - originalMap.format) - scaledPixmap.drawPixmap(originalMap, 0, 0, originalMap.width, originalMap.height, 0, 0, - scaledPixmap.width, scaledPixmap.height) - - originalMap.dispose() - Terraformer.heightMap(terrain).maxHeight(terrain.terrainWidth * 0.17f).map(scaledPixmap).terraform() - scaledPixmap.dispose() - } else { - Terraformer.heightMap(terrain).maxHeight(terrain.terrainWidth * 0.17f).map(originalMap).terraform() - originalMap.dispose() - } - - command.setHeightDataAfter(terrain.heightData) - history.add(command) - } - private fun generatePerlinNoise(seed: Int, min: Float, max: Float) { - val terrain = parent.component.terrain.terrain - val command = TerrainHeightCommand(terrain) - command.setHeightDataBefore(terrain.heightData) + override fun getTabTitle(): String = "Gen" - Terraformer.perlin(terrain).minHeight(min).maxHeight(max).seed(seed.toLong()).terraform() + override fun getContentTable(): Table = root - command.setHeightDataAfter(terrain.heightData) - history.add(command) + override fun switchedTab(tab: Tab) { + tabContainer.clearChildren() + tabContainer.add(tab.contentTable).expand().fill() } - override fun getTabTitle(): String { - return "Gen" + override fun removedTab(tab: Tab) { + // no } - override fun getContentTable(): Table { - return root + override fun removedAllTabs() { + // noop } } diff --git a/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/generation/HeightmapTab.kt b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/generation/HeightmapTab.kt new file mode 100644 index 000000000..92e76beb0 --- /dev/null +++ b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/generation/HeightmapTab.kt @@ -0,0 +1,85 @@ +package com.mbrlabs.mundus.editor.ui.modules.inspector.components.terrain.generation + +import com.badlogic.gdx.files.FileHandle +import com.badlogic.gdx.graphics.Pixmap +import com.badlogic.gdx.scenes.scene2d.InputEvent +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener +import com.badlogic.gdx.utils.Align +import com.kotcrab.vis.ui.util.dialog.Dialogs +import com.kotcrab.vis.ui.widget.VisTable +import com.kotcrab.vis.ui.widget.VisTextButton +import com.kotcrab.vis.ui.widget.tabbedpane.Tab +import com.mbrlabs.mundus.commons.assets.TerrainAsset +import com.mbrlabs.mundus.editor.Mundus +import com.mbrlabs.mundus.editor.core.project.ProjectManager +import com.mbrlabs.mundus.editor.history.CommandHistory +import com.mbrlabs.mundus.editor.history.commands.TerrainHeightCommand +import com.mbrlabs.mundus.editor.terrain.Terraformer +import com.mbrlabs.mundus.editor.ui.UI +import com.mbrlabs.mundus.editor.ui.widgets.FileChooserField +import com.mbrlabs.mundus.editor.utils.isImage + +class HeightmapTab(private val terrainAsset: TerrainAsset) : Tab(false, false) { + + private val root = VisTable() + + private val hmInput = FileChooserField() + private val loadHeightMapBtn = VisTextButton("Load heightmap") + + private val history: CommandHistory = Mundus.inject() + private val projectManager: ProjectManager = Mundus.inject() + + init { + root.align(Align.left) + + root.add(hmInput).pad(5f).left().expandX().fillX().row() + root.add(loadHeightMapBtn).pad(5f).right().row() + + setupListeners() + } + + override fun getTabTitle(): String = "Heightmap" + + override fun getContentTable(): Table = root + + private fun setupListeners() { + loadHeightMapBtn.addListener(object : ClickListener() { + override fun clicked(event: InputEvent?, x: Float, y: Float) { + val hm = hmInput.file + if (hm != null && hm.exists() && isImage(hm)) { + loadHeightMap(hm) + projectManager.current().assetManager.addDirtyAsset(terrainAsset) + } else { + Dialogs.showErrorDialog(UI, "Please select a heightmap image") + } + } + }) + } + + private fun loadHeightMap(heightMap: FileHandle) { + val terrain = terrainAsset.terrain + val command = TerrainHeightCommand(terrain) + command.setHeightDataBefore(terrain.heightData) + + val originalMap = Pixmap(heightMap) + + // scale pixmap if it doesn't fit the terrainAsset + if (originalMap.width != terrain.vertexResolution || originalMap.height != terrain.vertexResolution) { + val scaledPixmap = Pixmap(terrain.vertexResolution, terrain.vertexResolution, + originalMap.format) + scaledPixmap.drawPixmap(originalMap, 0, 0, originalMap.width, originalMap.height, 0, 0, + scaledPixmap.width, scaledPixmap.height) + + originalMap.dispose() + Terraformer.heightMap(terrain).maxHeight(terrain.terrainWidth * 0.17f).map(scaledPixmap).terraform() + scaledPixmap.dispose() + } else { + Terraformer.heightMap(terrain).maxHeight(terrain.terrainWidth * 0.17f).map(originalMap).terraform() + originalMap.dispose() + } + + command.setHeightDataAfter(terrain.heightData) + history.add(command) + } +} diff --git a/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/generation/PerlinNoiseTab.kt b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/generation/PerlinNoiseTab.kt new file mode 100644 index 000000000..2588d5a85 --- /dev/null +++ b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/inspector/components/terrain/generation/PerlinNoiseTab.kt @@ -0,0 +1,68 @@ +package com.mbrlabs.mundus.editor.ui.modules.inspector.components.terrain.generation + +import com.badlogic.gdx.scenes.scene2d.InputEvent +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener +import com.badlogic.gdx.utils.Align +import com.kotcrab.vis.ui.widget.VisTable +import com.kotcrab.vis.ui.widget.VisTextButton +import com.kotcrab.vis.ui.widget.tabbedpane.Tab +import com.mbrlabs.mundus.commons.assets.TerrainAsset +import com.mbrlabs.mundus.editor.Mundus +import com.mbrlabs.mundus.editor.core.project.ProjectManager +import com.mbrlabs.mundus.editor.history.CommandHistory +import com.mbrlabs.mundus.editor.history.commands.TerrainHeightCommand +import com.mbrlabs.mundus.editor.terrain.Terraformer +import com.mbrlabs.mundus.editor.ui.widgets.FloatFieldWithLabel +import com.mbrlabs.mundus.editor.ui.widgets.IntegerFieldWithLabel + +class PerlinNoiseTab(private val terrainAsset: TerrainAsset) : Tab(false, false) { + + private val root = VisTable() + + private val perlinNoiseBtn = VisTextButton("Generate Perlin noise") + private val perlinNoiseSeed = IntegerFieldWithLabel("Seed", -1, false) + private val perlinNoiseMinHeight = FloatFieldWithLabel("Min height", -1, true) + private val perlinNoiseMaxHeight = FloatFieldWithLabel("Max height", -1, true) + + private val history: CommandHistory = Mundus.inject() + private val projectManager: ProjectManager = Mundus.inject() + + init { + root.align(Align.left) + + root.add(perlinNoiseSeed).pad(5f).left().fillX().expandX().row() + root.add(perlinNoiseMinHeight).pad(5f).left().fillX().expandX().row() + root.add(perlinNoiseMaxHeight).pad(5f).left().fillX().expandX().row() + root.add(perlinNoiseBtn).pad(5f).right().row() + + setupListeners() + } + + override fun getTabTitle(): String = "Perlin noise" + + override fun getContentTable(): Table = root + + private fun setupListeners() { + perlinNoiseBtn.addListener(object : ClickListener() { + override fun clicked(event: InputEvent?, x: Float, y: Float) { + val seed = perlinNoiseSeed.int + val min = perlinNoiseMinHeight.float + val max = perlinNoiseMaxHeight.float + generatePerlinNoise(seed, min, max) + projectManager.current().assetManager.addDirtyAsset(terrainAsset) + } + }) + } + + private fun generatePerlinNoise(seed: Int, min: Float, max: Float) { + val terrain = terrainAsset.terrain + val command = TerrainHeightCommand(terrain) + command.setHeightDataBefore(terrain.heightData) + + Terraformer.perlin(terrain).minHeight(min).maxHeight(max).seed(seed.toLong()).terraform() + + command.setHeightDataAfter(terrain.heightData) + history.add(command) + } +} \ No newline at end of file