diff --git a/src/net/torvald/terrarum/Terrarum.kt b/src/net/torvald/terrarum/Terrarum.kt index c8ba0fb08..5cc666c41 100644 --- a/src/net/torvald/terrarum/Terrarum.kt +++ b/src/net/torvald/terrarum/Terrarum.kt @@ -938,4 +938,4 @@ fun interpolateLinear(scale: Double, startValue: Double, endValue: Double): Doub return endValue } return (1.0 - scale) * startValue + scale * endValue -} \ No newline at end of file +} diff --git a/src/net/torvald/terrarum/tests/UITestPad1.kt b/src/net/torvald/terrarum/tests/UITestPad1.kt index d028684f0..14ead40b1 100644 --- a/src/net/torvald/terrarum/tests/UITestPad1.kt +++ b/src/net/torvald/terrarum/tests/UITestPad1.kt @@ -84,7 +84,7 @@ class UITestPad1 : ScreenAdapter() { override fun render(delta: Float) { // UPDATE - + nsMenu.update(delta) // RENDER diff --git a/src/net/torvald/terrarum/ui/UICanvas.kt b/src/net/torvald/terrarum/ui/UICanvas.kt index f5e67029e..fe16f69bf 100644 --- a/src/net/torvald/terrarum/ui/UICanvas.kt +++ b/src/net/torvald/terrarum/ui/UICanvas.kt @@ -66,9 +66,11 @@ abstract class UICanvas( get() = mouseUp && Gdx.input.isButtonPressed(Terrarum.getConfigInt("mouseprimary")) + /** Called by the screen */ fun update(delta: Float) { handler.update(this, delta) } + /** Called by the screen */ fun render(batch: SpriteBatch, camera: Camera) { handler.render(this, batch, camera) } @@ -127,6 +129,8 @@ abstract class UICanvas( } /** + * Called by the screen's InputProcessor + * * When implementing this, make sure to use ```mouseInScreen()``` function! */ open fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean { @@ -137,6 +141,7 @@ abstract class UICanvas( } else return false } + /** Called by the screen's InputProcessor */ open fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean { if (this.isVisible && mouseInScreen(screenX, screenY)) { uiItems.forEach { it.touchDown(screenX, screenY, pointer, button) } @@ -145,6 +150,7 @@ abstract class UICanvas( } else return false } + /** Called by the screen's InputProcessor */ open fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean { if (this.isVisible) { uiItems.forEach { it.touchUp(screenX, screenY, pointer, button) } @@ -153,6 +159,7 @@ abstract class UICanvas( } else return false } + /** Called by the screen's InputProcessor */ open fun scrolled(amount: Int): Boolean { if (this.isVisible) { uiItems.forEach { it.scrolled(amount) } @@ -161,6 +168,7 @@ abstract class UICanvas( } else return false } + /** Called by the screen's InputProcessor */ open fun keyDown(keycode: Int): Boolean { if (this.isVisible) { uiItems.forEach { it.keyDown(keycode) } @@ -169,6 +177,7 @@ abstract class UICanvas( } else return false } + /** Called by the screen's InputProcessor */ open fun keyUp(keycode: Int): Boolean { if (this.isVisible) { uiItems.forEach { it.keyUp(keycode) } @@ -177,6 +186,7 @@ abstract class UICanvas( } else return false } + /** Called by the screen's InputProcessor */ open fun keyTyped(character: Char): Boolean { return false //uiItems.forEach { it.keyT } diff --git a/src/net/torvald/terrarum/ui/UINSMenu.kt b/src/net/torvald/terrarum/ui/UINSMenu.kt index 153a05796..00e8a496b 100644 --- a/src/net/torvald/terrarum/ui/UINSMenu.kt +++ b/src/net/torvald/terrarum/ui/UINSMenu.kt @@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Camera import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.terrarum.* +import java.lang.Error /** * Nextstep-themed menu bar with mandatory title line @@ -23,56 +24,122 @@ class UINSMenu( ) : UICanvas() { override var openCloseTime: Second = 0f - val LINE_HEIGHT = 24 + val LINE_HEIGHT = 30 val TEXT_OFFSETX = 3f val TEXT_OFFSETY = (LINE_HEIGHT - Terrarum.fontGame.lineHeight) / 2f val CHILD_ARROW = "${0x2023.toChar()}" val tree = treeRepresentation.parse() - override var width = maxOf(minimumWidth, tree.getLevelData(1).map { Terrarum.fontGame.getWidth(it ?: "") }.max() ?: 0) - override var height = LINE_HEIGHT * (tree.children.size + 1) - private val treeChildrenLabels = Array(tree.children.size) { - tree.children[it].toString() + if (tree.children[it].children.isNotEmpty()) " $CHILD_ARROW" else "" - } + override var width = 0 + override var height = 0 + //override var width = maxOf(minimumWidth, tree.getLevelData(1).map { Terrarum.fontGame.getWidth(it ?: "") }.max() ?: 0) + //override var height = LINE_HEIGHT * (tree.children.size + 1) - private val theRealList = UIItemTextButtonList( - this, - treeChildrenLabels, - posX, posY + LINE_HEIGHT, - width, height - LINE_HEIGHT, - textAreaWidth = width - (2 * TEXT_OFFSETX.toInt()), - alignment = UIItemTextButton.Companion.Alignment.LEFT, - activeBackCol = Color(0x242424_80),//Color(1f,0f,.75f,1f), - inactiveCol = Color(.94f,.94f,.94f,1f), - itemHitboxSize = LINE_HEIGHT - ) + private val listStack = ArrayList() + private var currentDepth = 0 + + private data class MenuPack(val title: String, val list: UIItemTextButtonList) + + private fun ArrayList.push(item: MenuPack) { this.add(item) } + private fun ArrayList.pop() = this.removeAt(this.lastIndex)!! + private fun ArrayList.peek() = this.last()!! + val selectedIndex: Int? - get() = theRealList.selectedIndex + get() = listStack.peek().list.selectedIndex + + init { + addSubMenu(tree) + } + + private fun addSubMenu(tree: QNDTreeNode) { + val stringsFromTree = Array(tree.children.size) { + tree.children[it].toString() + if (tree.children[it].children.isNotEmpty()) " $CHILD_ARROW" else "" + } + + val listWidth = maxOf(minimumWidth, tree.getLevelData(1).map { Terrarum.fontGame.getWidth(it ?: "") }.max() ?: 0) + val listHeight = stringsFromTree.size * LINE_HEIGHT + + val list = UIItemTextButtonList( + this, + stringsFromTree, + width, LINE_HEIGHT, + listWidth, listHeight, + textAreaWidth = listWidth - (2 * TEXT_OFFSETX.toInt()), + alignment = UIItemTextButton.Companion.Alignment.LEFT, + activeBackCol = Color(0x242424_80),//Color(1f,0f,.75f,1f), + inactiveCol = Color(.94f,.94f,.94f,1f), + itemHitboxSize = LINE_HEIGHT + + ) + + // List selection change listener + list.selectionChangeListener = { old, new -> + // if the selection has a child... + if (tree.children[new].children.isNotEmpty()) { + // 1. pop as far as possible + // 2. push the new menu + + // 1. pop as far as possible + while (listStack.peek().list != list) { + popSubMenu() + } + + // 2. push the new menu + addSubMenu(tree.children[new]) + } + } + // END List selection change listener + + + // push the processed list + listStack.push(MenuPack(tree.data ?: title, list)) + // increment the memoized width + width += listWidth + currentDepth += 1 + } + + private fun popSubMenu() { + if (listStack.size == 1) throw Error("Tried to pop root menu") + + val poppedUIItem = listStack.pop() + width -= poppedUIItem.list.width + } override fun updateUI(delta: Float) { - theRealList.update(delta) + /*listStack.forEach { + it.list.update(delta) + }*/ // fucking concurrent modification + + var c = 0 + while (c < listStack.size) { + listStack[c].list.update(delta) + c += 1 + } } override fun renderUI(batch: SpriteBatch, camera: Camera) { - // draw title bar - batch.color = titleBackCol - BlendMode.resolve(titleBlendMode, batch) - batch.fillRect(0f, 0f, width.toFloat(), LINE_HEIGHT.toFloat()) + listStack.forEach { + // draw title bar + batch.color = titleBackCol + BlendMode.resolve(titleBlendMode, batch) + batch.fillRect(it.list.posX.toFloat(), it.list.posY.toFloat() - LINE_HEIGHT, it.list.width.toFloat(), LINE_HEIGHT.toFloat()) - batch.color = titleTextCol - blendNormal(batch) - Terrarum.fontGame.draw(batch, title, TEXT_OFFSETX, TEXT_OFFSETY) + batch.color = titleTextCol + blendNormal(batch) + Terrarum.fontGame.draw(batch, it.title, TEXT_OFFSETX + it.list.posX, TEXT_OFFSETY + it.list.posY - LINE_HEIGHT) + + // draw the list + batch.color = Color.WHITE + it.list.render(batch, camera) + } - // draw the list - batch.color = Color.WHITE - theRealList.render(batch, camera) } override fun dispose() { - theRealList.dispose() + listStack.forEach { it.list.dispose() } } fun mouseOnTitleBar() = @@ -104,7 +171,7 @@ class UINSMenu( if (mouseInScreen(screenX, screenY)) { if (dragForReal) { handler.setPosition(screenX - dragOriginX, screenY - dragOriginY) - println("drag $screenX, $screenY") + //println("drag $screenX, $screenY") } }