mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 18:44:05 +09:00
buildingmaker penmenu; resolving mouse click clash between world and UIs
This commit is contained in:
@@ -6,7 +6,9 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.itemproperties.ItemID
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
||||
@@ -33,12 +35,17 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
- Import…
|
||||
- Save terrain…
|
||||
- Load terrain…
|
||||
-
|
||||
- Exit to Title : net.torvald.terrarum.modulebasegame.YamlCommandExit
|
||||
- Tool
|
||||
- Pencil : net.torvald.terrarum.modulebasegame.YamlCommandToolPencil
|
||||
- Eyedropper
|
||||
- Select mrq. : net.torvald.terrarum.modulebasegame.YamlCommandToolMarquee
|
||||
- Move
|
||||
- Eraser : net.torvald.terrarum.modulebasegame.YamlCommandToolPencilErase
|
||||
- Wall Hammer : net.torvald.terrarum.modulebasegame.YamlCommandToolPencilEraseWall
|
||||
- Eyedropper : net.torvald.terrarum.modulebasegame.YamlCommandToolEyedropper
|
||||
- Add Selection : net.torvald.terrarum.modulebasegame.YamlCommandToolMarquee
|
||||
- Remove Sel. : net.torvald.terrarum.modulebasegame.YamlCommandToolMarqueeErase
|
||||
- Clear Sel.
|
||||
- Move Selected
|
||||
- Undo
|
||||
- Redo
|
||||
- Time
|
||||
@@ -84,12 +91,15 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
val notifier = Notification()
|
||||
val uiPaletteSelector = UIPaletteSelector(this)
|
||||
val uiPalette = UIBuildingMakerBlockChooser(this)
|
||||
val uiPenMenu = UIBuildingMakerPenMenu(this)
|
||||
|
||||
|
||||
val uiContainer = ArrayList<UICanvas>()
|
||||
|
||||
var currentPenMode = PENMODE_PENCIL
|
||||
var currentPenTarget = PENTARGET_TERRAIN
|
||||
|
||||
val selection = ArrayList<Point2i>()
|
||||
|
||||
val blockPointingCursor = object : ActorWithBody(Actor.RenderOrder.OVERLAY) {
|
||||
|
||||
@@ -130,11 +140,20 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
companion object {
|
||||
const val PENMODE_PENCIL = 0
|
||||
const val PENMODE_MARQUEE = 1
|
||||
const val PENMODE_PENCIL_ERASE = 1
|
||||
const val PENMODE_MARQUEE = 2
|
||||
const val PENMODE_MARQUEE_ERASE = 3
|
||||
const val PENMODE_EYEDROPPER = 4
|
||||
|
||||
const val PENTARGET_TERRAIN = 1
|
||||
const val PENTARGET_WALL = 2
|
||||
|
||||
val toolCursorColour = arrayOf(
|
||||
Color.YELLOW,
|
||||
Color.MAGENTA
|
||||
Color.YELLOW,
|
||||
Color.MAGENTA,
|
||||
Color.MAGENTA,
|
||||
Color.WHITE
|
||||
)
|
||||
}
|
||||
|
||||
@@ -150,6 +169,7 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
uiContainer.add(uiPaletteSelector)
|
||||
uiContainer.add(notifier)
|
||||
uiContainer.add(uiPalette)
|
||||
uiContainer.add(uiPenMenu)
|
||||
|
||||
|
||||
|
||||
@@ -168,7 +188,6 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
|
||||
uiPalette.setPosition(200, 100)
|
||||
uiPalette.isVisible = true // TEST CODE should not be visible
|
||||
|
||||
|
||||
LightmapRenderer.fireRecalculateEvent()
|
||||
@@ -206,30 +225,47 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
}
|
||||
|
||||
private fun updateGame(delta: Float) {
|
||||
var mouseOnUI = false
|
||||
private var mouseOnUI = false
|
||||
internal var tappedOnUI = false // when true, even if the UI is closed, pen won't work unless your pen is lifted
|
||||
// must be set to TRUE by UIs
|
||||
|
||||
private fun updateGame(delta: Float) {
|
||||
|
||||
WeatherMixer.update(delta, actorNowPlaying, gameWorld)
|
||||
blockPointingCursor.update(delta)
|
||||
actorNowPlaying?.update(delta)
|
||||
var overwriteMouseOnUI = false
|
||||
uiContainer.forEach {
|
||||
it.update(delta)
|
||||
if (it.isVisible && it.mouseUp) {
|
||||
mouseOnUI = true
|
||||
overwriteMouseOnUI = true
|
||||
}
|
||||
}
|
||||
|
||||
mouseOnUI = (overwriteMouseOnUI || uiPenMenu.isVisible)
|
||||
|
||||
|
||||
WorldCamera.update(world, actorNowPlaying)
|
||||
|
||||
|
||||
// make pen work HERE
|
||||
if (Gdx.input.isTouched && !mouseOnUI) {
|
||||
// when LEFT mouse is down
|
||||
if (!tappedOnUI && Gdx.input.isButtonPressed(AppLoader.getConfigInt("mouseprimary")) && !mouseOnUI) {
|
||||
|
||||
makePenWork(Terrarum.mouseTileX, Terrarum.mouseTileY)
|
||||
// TODO drag support using bresenham's algo
|
||||
// for some reason it just doesn't work...
|
||||
}
|
||||
else if (!uiPenMenu.isVisible && Gdx.input.isButtonPressed(AppLoader.getConfigInt("mousesecondary"))) {
|
||||
// open pen menu
|
||||
// position the menu to where the cursor is
|
||||
uiPenMenu.posX = Terrarum.mouseScreenX - uiPenMenu.width / 2
|
||||
uiPenMenu.posY = Terrarum.mouseScreenY - uiPenMenu.height / 2
|
||||
uiPenMenu.posX = uiPenMenu.posX.coerceIn(0, Terrarum.WIDTH - uiPenMenu.width)
|
||||
uiPenMenu.posY = uiPenMenu.posY.coerceIn(0, Terrarum.HEIGHT - uiPenMenu.height)
|
||||
|
||||
// actually open
|
||||
uiPenMenu.setAsOpen()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,18 +282,37 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
println("[BuildingMaker] Resize event")
|
||||
}
|
||||
|
||||
fun setPencilColour(itemID: ItemID) {
|
||||
uiPaletteSelector.fore = itemID
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
blockPointingCursor.dispose()
|
||||
}
|
||||
|
||||
private fun makePenWork(worldTileX: Int, worldTileY: Int) {
|
||||
private fun makePenWork(x: Int, y: Int) {
|
||||
val world = gameWorld
|
||||
val palSelection = uiPaletteSelector.fore
|
||||
|
||||
when (currentPenMode) {
|
||||
// test paint terrain layer
|
||||
PENMODE_PENCIL -> {
|
||||
world.setTileTerrain(worldTileX, worldTileY, palSelection)
|
||||
if (palSelection < BlockCodex.MAX_TERRAIN_TILES)
|
||||
world.setTileTerrain(x, y, palSelection)
|
||||
else if (palSelection < 2 * BlockCodex.MAX_TERRAIN_TILES)
|
||||
world.setTileWall(x, y, palSelection - BlockCodex.MAX_TERRAIN_TILES)
|
||||
}
|
||||
PENMODE_PENCIL_ERASE -> {
|
||||
if (currentPenTarget and PENTARGET_WALL != 0)
|
||||
world.setTileWall(x, y, Block.AIR)
|
||||
else
|
||||
world.setTileTerrain(x, y, Block.AIR)
|
||||
}
|
||||
PENMODE_EYEDROPPER -> {
|
||||
uiPaletteSelector.fore = if (world.getTileFromTerrain(x, y) == Block.AIR)
|
||||
world.getTileFromWall(x, y)!! + BlockCodex.MAX_TERRAIN_TILES
|
||||
else
|
||||
world.getTileFromTerrain(x, y)!!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,6 +321,7 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
class BuildingMakerController(val screen: BuildingMaker) : InputAdapter() {
|
||||
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||
screen.uiContainer.forEach { it.touchUp(screenX, screenY, pointer, button) }
|
||||
screen.tappedOnUI = false
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -289,7 +345,6 @@ class BuildingMakerController(val screen: BuildingMaker) : InputAdapter() {
|
||||
return true
|
||||
}
|
||||
|
||||
// let left mouse button to paint, because that's how graphic tablets work
|
||||
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
|
||||
screen.uiContainer.forEach { it.touchDragged(screenX, screenY, pointer) }
|
||||
return true
|
||||
@@ -368,6 +423,28 @@ class YamlCommandSetTimeNight : YamlInvokable {
|
||||
class YamlCommandToolPencil : YamlInvokable {
|
||||
override fun invoke(args: Array<Any>) {
|
||||
(args[0] as BuildingMaker).currentPenMode = BuildingMaker.PENMODE_PENCIL
|
||||
(args[0] as BuildingMaker).currentPenTarget = BuildingMaker.PENTARGET_TERRAIN
|
||||
}
|
||||
}
|
||||
|
||||
class YamlCommandToolPencilErase : YamlInvokable {
|
||||
override fun invoke(args: Array<Any>) {
|
||||
(args[0] as BuildingMaker).currentPenMode = BuildingMaker.PENMODE_PENCIL_ERASE
|
||||
(args[0] as BuildingMaker).currentPenTarget = BuildingMaker.PENTARGET_TERRAIN
|
||||
}
|
||||
}
|
||||
|
||||
class YamlCommandToolPencilEraseWall : YamlInvokable {
|
||||
override fun invoke(args: Array<Any>) {
|
||||
(args[0] as BuildingMaker).currentPenMode = BuildingMaker.PENMODE_PENCIL_ERASE
|
||||
(args[0] as BuildingMaker).currentPenTarget = BuildingMaker.PENTARGET_WALL
|
||||
}
|
||||
}
|
||||
|
||||
class YamlCommandToolEyedropper : YamlInvokable {
|
||||
override fun invoke(args: Array<Any>) {
|
||||
(args[0] as BuildingMaker).currentPenMode = BuildingMaker.PENMODE_EYEDROPPER
|
||||
(args[0] as BuildingMaker).currentPenTarget = BuildingMaker.PENTARGET_TERRAIN
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,4 +452,10 @@ class YamlCommandToolMarquee : YamlInvokable {
|
||||
override fun invoke(args: Array<Any>) {
|
||||
(args[0] as BuildingMaker).currentPenMode = BuildingMaker.PENMODE_MARQUEE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class YamlCommandToolMarqueeErase : YamlInvokable {
|
||||
override fun invoke(args: Array<Any>) {
|
||||
(args[0] as BuildingMaker).currentPenMode = BuildingMaker.PENMODE_MARQUEE_ERASE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||
import net.torvald.terrarum.itemproperties.GameItem
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.itemproperties.Material
|
||||
import net.torvald.terrarum.modulebasegame.imagefont.WatchFont
|
||||
|
||||
/**
|
||||
* The entry point for the module "Basegame"
|
||||
@@ -103,4 +104,7 @@ class EntryPoint : ModuleEntryPoint() {
|
||||
println("Welcome back!")
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
WatchFont.dispose()
|
||||
}
|
||||
}
|
||||
@@ -588,6 +588,8 @@ object IngameRenderer {
|
||||
LightmapRenderer.dispose()
|
||||
BlocksDrawer.dispose()
|
||||
WeatherMixer.dispose()
|
||||
|
||||
batch.dispose()
|
||||
}
|
||||
|
||||
private fun worldCamToRenderPos(): Pair<Float, Float> {
|
||||
|
||||
@@ -3,6 +3,8 @@ package net.torvald.terrarum.modulebasegame
|
||||
import com.badlogic.gdx.graphics.Camera
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.terrarum.blendNormal
|
||||
import net.torvald.terrarum.blendScreen
|
||||
import net.torvald.terrarum.fillRect
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
@@ -21,7 +23,7 @@ class UIBuildingMakerBlockChooser(val parent: BuildingMaker): UICanvas() {
|
||||
|
||||
const val TILESREGION_SIZE = 24
|
||||
const val MENUBAR_SIZE = 80
|
||||
const val SCROLLBAR_SIZE = 16
|
||||
const val SCROLLBAR_SIZE = 24
|
||||
|
||||
const val WIDTH = TILES_X*TILESREGION_SIZE + SCROLLBAR_SIZE + MENUBAR_SIZE
|
||||
const val HEIGHT = TILES_Y*TILESREGION_SIZE
|
||||
@@ -60,14 +62,31 @@ class UIBuildingMakerBlockChooser(val parent: BuildingMaker): UICanvas() {
|
||||
palette.forEach { it.update(delta) }
|
||||
tabs.update(delta)
|
||||
closeButton.update(delta)
|
||||
if (closeButton.mousePushed) {
|
||||
parent.tappedOnUI = true
|
||||
isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private val addCol = Color(0x242424ff)
|
||||
private var scrollBarPos = 0
|
||||
private val scrollBarHeight = (HEIGHT - 16*14).toFloat()
|
||||
private val scrollableArea = HEIGHT - scrollBarHeight
|
||||
|
||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||
palette.forEach { it.render(batch, camera) }
|
||||
|
||||
// gaps between tabs and close button
|
||||
batch.color = DEFAULT_BACKGROUNDCOL
|
||||
batch.fillRect(0f, tabs.height.toFloat(), MENUBAR_SIZE.toFloat(), height.toFloat() - (tabs.height + closeButton.height))
|
||||
// scrollbar back
|
||||
batch.fillRect(width - SCROLLBAR_SIZE.toFloat(), 0f, SCROLLBAR_SIZE.toFloat(), height.toFloat())
|
||||
blendScreen(batch)
|
||||
batch.color = addCol
|
||||
batch.fillRect(width - SCROLLBAR_SIZE.toFloat(), 0f, SCROLLBAR_SIZE.toFloat(), height.toFloat())
|
||||
// scrollbar
|
||||
batch.fillRect(width - SCROLLBAR_SIZE.toFloat(), scrollBarPos.toFloat(), SCROLLBAR_SIZE.toFloat(), scrollBarHeight)
|
||||
blendNormal(batch)
|
||||
|
||||
// the actual buttons
|
||||
tabs.render(batch, camera)
|
||||
@@ -77,7 +96,6 @@ class UIBuildingMakerBlockChooser(val parent: BuildingMaker): UICanvas() {
|
||||
private var dragOriginX = 0 // relative mousepos
|
||||
private var dragOriginY = 0 // relative mousepos
|
||||
private var dragForReal = false
|
||||
private var closeReady = false // so that it'll close when the mouse is DOWN then UP
|
||||
|
||||
private fun mouseOnDragHandle() = relativeMouseX in 0 until MENUBAR_SIZE && relativeMouseY in tabs.height until height - closeButton.height
|
||||
|
||||
@@ -96,22 +114,16 @@ class UIBuildingMakerBlockChooser(val parent: BuildingMaker): UICanvas() {
|
||||
dragOriginX = relativeMouseX
|
||||
dragOriginY = relativeMouseY
|
||||
dragForReal = true
|
||||
parent.tappedOnUI = true
|
||||
}
|
||||
else {
|
||||
dragForReal = false
|
||||
}
|
||||
|
||||
closeReady = closeButton.mouseUp
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||
if (closeReady && closeButton.mouseUp) {
|
||||
closeButton.deselect()
|
||||
this.isVisible = false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package net.torvald.terrarum.modulebasegame
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.Camera
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.fillCircle
|
||||
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory
|
||||
import net.torvald.terrarum.roundInt
|
||||
import net.torvald.terrarum.sqr
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import org.dyn4j.geometry.Vector2
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2019-02-16.
|
||||
*/
|
||||
class UIBuildingMakerPenMenu(val parent: BuildingMaker): UICanvas() {
|
||||
|
||||
companion object {
|
||||
const val SIZE = 400
|
||||
const val RADIUS = SIZE / 2.0
|
||||
const val RADIUSF = RADIUS.toFloat()
|
||||
|
||||
const val BLOCKS_ROW_RADIUS = 150
|
||||
const val TOOLS_ROW_RADIUS = 72
|
||||
|
||||
const val BLOCK_BACK_SIZE = 72
|
||||
const val BLOCK_BACK_RADIUS = BLOCK_BACK_SIZE / 2f
|
||||
|
||||
const val ICON_SIZE = 38
|
||||
const val ICON_HITBOX_SIZE = 52
|
||||
const val ICON_HITBOX_RADIUS = ICON_HITBOX_SIZE / 2f
|
||||
|
||||
const val PALETTE_SIZE = 10
|
||||
}
|
||||
|
||||
private val backCol = ItemSlotImageFactory.CELLCOLOUR_BLACK
|
||||
private val blockCellCol = ItemSlotImageFactory.CELLCOLOUR_WHITE
|
||||
/** Centre pos. */
|
||||
private val blockCellPos = Array<Vector2>(PALETTE_SIZE) {
|
||||
val newvec = Vector2(0.0, 0.0 - BLOCKS_ROW_RADIUS)
|
||||
newvec.rotate(Math.PI / 5.0 * it).plus(Vector2(RADIUS, RADIUS))
|
||||
}
|
||||
|
||||
override var width = SIZE
|
||||
override var height = SIZE
|
||||
override var openCloseTime = 0f//UIQuickslotBar.COMMON_OPEN_CLOSE
|
||||
|
||||
private var mouseVec = Vector2(0.0, 0.0)
|
||||
|
||||
override fun updateUI(delta: Float) {
|
||||
mouseVec.x = relativeMouseX.toDouble()
|
||||
mouseVec.y = relativeMouseY.toDouble()
|
||||
|
||||
if (Gdx.input.isKeyPressed(Input.Keys.ESCAPE)) {
|
||||
this.isVisible = false
|
||||
parent.tappedOnUI = false
|
||||
}
|
||||
|
||||
// primary click
|
||||
if (Gdx.input.isButtonPressed(AppLoader.getConfigInt("mouseprimary"))) {
|
||||
// close by clicking close button or out-of-boud
|
||||
if (mouseVec.distanceSquared(RADIUS, RADIUS) !in ICON_HITBOX_RADIUS.sqr()..RADIUSF.sqr()) {
|
||||
this.isVisible = false
|
||||
parent.tappedOnUI = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||
// draw back
|
||||
batch.color = backCol
|
||||
batch.fillCircle(0f, 0f, SIZE.toFloat(), SIZE.toFloat())
|
||||
|
||||
// draw fore
|
||||
batch.color = blockCellCol
|
||||
for (i in 0 until PALETTE_SIZE) {
|
||||
val x = blockCellPos[i].x.roundInt().toFloat() - BLOCK_BACK_RADIUS
|
||||
val y = blockCellPos[i].y.roundInt().toFloat() - BLOCK_BACK_RADIUS
|
||||
batch.fillCircle(x, y, BLOCK_BACK_SIZE.toFloat(), BLOCK_BACK_SIZE.toFloat())
|
||||
}
|
||||
|
||||
// draw close button
|
||||
batch.fillCircle(RADIUSF - ICON_HITBOX_RADIUS, RADIUSF - ICON_HITBOX_RADIUS, ICON_HITBOX_SIZE.toFloat(), ICON_HITBOX_SIZE.toFloat())
|
||||
}
|
||||
|
||||
override fun doOpening(delta: Float) {
|
||||
}
|
||||
|
||||
override fun doClosing(delta: Float) {
|
||||
}
|
||||
|
||||
override fun endOpening(delta: Float) {
|
||||
}
|
||||
|
||||
override fun endClosing(delta: Float) {
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import net.torvald.terrarum.itemproperties.GameItem
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-03-15.
|
||||
@@ -18,7 +17,7 @@ open class DroppedItem(private val item: GameItem) : ActorWBMovable(RenderOrder.
|
||||
|
||||
isVisible = true
|
||||
|
||||
avBaseMass = if (item.dynamicID < BlockCodex.TILE_UNIQUE_MAX)
|
||||
avBaseMass = if (item.dynamicID < BlockCodex.MAX_TERRAIN_TILES)
|
||||
BlockCodex[item.dynamicID].density / 1000.0
|
||||
else
|
||||
ItemCodex[item.dynamicID].mass
|
||||
|
||||
Reference in New Issue
Block a user