Compare commits

...

2 Commits

Author SHA1 Message Date
Shadowfacts cb66900cb5
Add Window constraints 2019-06-26 19:54:23 -04:00
Shadowfacts 0defbdeffd
Add panel background nine patch 2019-06-26 19:32:06 -04:00
12 changed files with 121 additions and 31 deletions

View File

@ -8,8 +8,8 @@ import net.shadowfacts.cacao.Window
import net.shadowfacts.cacao.geometry.Axis import net.shadowfacts.cacao.geometry.Axis
import net.shadowfacts.cacao.geometry.Size import net.shadowfacts.cacao.geometry.Size
import net.shadowfacts.cacao.util.Color import net.shadowfacts.cacao.util.Color
import net.shadowfacts.cacao.util.NinePatchTexture import net.shadowfacts.cacao.util.texture.NinePatchTexture
import net.shadowfacts.cacao.util.Texture import net.shadowfacts.cacao.util.texture.Texture
import net.shadowfacts.cacao.view.* import net.shadowfacts.cacao.view.*
import net.shadowfacts.cacao.view.button.DropdownButton import net.shadowfacts.cacao.view.button.DropdownButton
@ -26,8 +26,7 @@ class TestCacaoScreen: CacaoScreen() {
val red = stack.addArrangedSubview(TextureView(Texture(Identifier("textures/block/birch_log_top.png"), 0, 0, 16, 16)).apply { val red = stack.addArrangedSubview(TextureView(Texture(Identifier("textures/block/birch_log_top.png"), 0, 0, 16, 16)).apply {
intrinsicContentSize = Size(50.0, 50.0) intrinsicContentSize = Size(50.0, 50.0)
}) })
val buttonNinePatch = NinePatchTexture(Texture(Identifier("textures/gui/widgets.png"), 0, 66), 3, 3, 194, 14) val green = stack.addArrangedSubview(NinePatchView(NinePatchTexture.PANEL_BG).apply {
val green = stack.addArrangedSubview(NinePatchView(buttonNinePatch).apply {
intrinsicContentSize = Size(75.0, 100.0) intrinsicContentSize = Size(75.0, 100.0)
}) })
val blue = stack.addArrangedSubview(View().apply { val blue = stack.addArrangedSubview(View().apply {
@ -46,9 +45,9 @@ class TestCacaoScreen: CacaoScreen() {
}) })
solver.dsl { solver.dsl {
stack.topAnchor equalTo 50 stack.topAnchor equalTo 0
stack.leftAnchor equalTo 50 stack.centerXAnchor equalTo this@apply.centerXAnchor
stack.rightAnchor equalTo 150 stack.widthAnchor equalTo 100
purple.centerXAnchor equalTo blue.centerXAnchor purple.centerXAnchor equalTo blue.centerXAnchor
purple.centerYAnchor equalTo blue.centerYAnchor purple.centerYAnchor equalTo blue.centerYAnchor
// purple.widthAnchor equalTo 50 // purple.widthAnchor equalTo 50

View File

@ -1,11 +1,13 @@
package net.shadowfacts.cacao package net.shadowfacts.cacao
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.screen.Screen import net.minecraft.client.gui.screen.Screen
import net.minecraft.network.chat.TextComponent import net.minecraft.network.chat.TextComponent
import net.minecraft.sound.SoundEvents import net.minecraft.sound.SoundEvents
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.util.MouseButton import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.util.RenderHelper import net.shadowfacts.cacao.util.RenderHelper
import net.shadowfacts.kiwidsl.dsl
import java.util.* import java.util.*
/** /**
@ -46,6 +48,14 @@ open class CacaoScreen: Screen(TextComponent("CacaoScreen")) {
_windows.remove(window) _windows.remove(window)
} }
override fun init() {
super.init()
windows.forEach {
it.resize(width, height)
}
}
override fun render(mouseX: Int, mouseY: Int, delta: Float) { override fun render(mouseX: Int, mouseY: Int, delta: Float) {
if (minecraft != null) { if (minecraft != null) {
// workaround this.minecraft sometimes being null causing a crash // workaround this.minecraft sometimes being null causing a crash

View File

@ -3,7 +3,10 @@ package net.shadowfacts.cacao
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.util.MouseButton import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.view.View import net.shadowfacts.cacao.view.View
import net.shadowfacts.kiwidsl.dsl
import no.birkett.kiwi.Constraint
import no.birkett.kiwi.Solver import no.birkett.kiwi.Solver
import no.birkett.kiwi.Variable
import java.util.* import java.util.*
/** /**
@ -22,8 +25,49 @@ class Window {
*/ */
lateinit var screen: CacaoScreen lateinit var screen: CacaoScreen
/**
* The constraint solver used by this window and all its views and subviews.
*/
var solver = Solver() var solver = Solver()
/**
* Layout anchor for the left edge of this view in the window's coordinate system.
*/
val leftAnchor = Variable("left")
/**
* Layout anchor for the right edge of this view in the window's coordinate system.
*/
val rightAnchor = Variable("right")
/**
* Layout anchor for the top edge of this view in the window's coordinate system.
*/
val topAnchor = Variable("top")
/**
* Layout anchor for the bottom edge of this view in the window's coordinate system.
*/
val bottomAnchor = Variable("bottom")
/**
* Layout anchor for the width of this view in the window's coordinate system.
*/
val widthAnchor = Variable("width")
/**
* Layout anchor for the height of this view in the window's coordinate system.
*/
val heightAnchor = Variable("height")
/**
* Layout anchor for the center X position of this view in the window's coordinate system.
*/
val centerXAnchor = Variable("centerX")
/**
* Layout anchor for the center Y position of this view in the window's coordinate system.
*/
val centerYAnchor = Variable("centerY")
// internal constraints that specify the window size based on the MC screen size
// stored so that they can be removed when the screen is resized
private var widthConstraint: Constraint? = null
private var heightConstraint: Constraint? = null
// _views is the internal, mutable object, since we only want it to be mutated by the add/removeView methods // _views is the internal, mutable object, since we only want it to be mutated by the add/removeView methods
private val _views = LinkedList<View>() private val _views = LinkedList<View>()
/** /**
@ -34,6 +78,40 @@ class Window {
private var viewsSortedByZIndex: List<View> = listOf() private var viewsSortedByZIndex: List<View> = listOf()
init {
createInternalConstraints()
}
/**
* Creates the internal constraints used by the window.
* If overridden, the super-class method must be called.
*/
protected open fun createInternalConstraints() {
solver.dsl {
leftAnchor equalTo 0
topAnchor equalTo 0
rightAnchor equalTo (leftAnchor + widthAnchor)
bottomAnchor equalTo (topAnchor + heightAnchor)
centerXAnchor equalTo (leftAnchor + widthAnchor / 2)
centerYAnchor equalTo (topAnchor + heightAnchor / 2)
}
}
/**
* Called by the window's [screen] when the Minecraft screen is resized.
* Used to update the window's width and height constraints and re-layout views.
*/
internal fun resize(width: Int, height: Int) {
if (widthConstraint != null) solver.removeConstraint(widthConstraint)
if (heightConstraint != null) solver.removeConstraint(heightConstraint)
solver.dsl {
widthConstraint = (widthAnchor equalTo width)
heightConstraint = (heightAnchor equalTo height)
}
layout()
}
/** /**
* Convenience method that removes this window from its [screen]. * Convenience method that removes this window from its [screen].
*/ */

View File

@ -8,6 +8,7 @@ import net.minecraft.client.render.VertexFormats
import net.minecraft.client.sound.PositionedSoundInstance import net.minecraft.client.sound.PositionedSoundInstance
import net.minecraft.sound.SoundEvent import net.minecraft.sound.SoundEvent
import net.shadowfacts.cacao.geometry.Rect import net.shadowfacts.cacao.geometry.Rect
import net.shadowfacts.cacao.util.texture.Texture
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
/** /**

View File

@ -1,4 +1,6 @@
package net.shadowfacts.cacao.util package net.shadowfacts.cacao.util.texture
import net.minecraft.util.Identifier
/** /**
* Helper class that represents a texture that can be divided into nine pieces (4 corners, 4 edges, and the center) * Helper class that represents a texture that can be divided into nine pieces (4 corners, 4 edges, and the center)
@ -15,12 +17,20 @@ package net.shadowfacts.cacao.util
*/ */
data class NinePatchTexture(val texture: Texture, val cornerWidth: Int, val cornerHeight: Int, val centerWidth: Int, val centerHeight: Int) { data class NinePatchTexture(val texture: Texture, val cornerWidth: Int, val cornerHeight: Int, val centerWidth: Int, val centerHeight: Int) {
companion object {
val PANEL_BG = NinePatchTexture(Texture(Identifier("textures/gui/demo_background.png"), 0, 0), 5, 5, 238, 156)
val BUTTON_BG = NinePatchTexture(Texture(Identifier("textures/gui/widgets.png"), 0, 66), 3, 3, 194, 14)
val BUTTON_HOVERED_BG = NinePatchTexture(Texture(Identifier("textures/gui/widgets.png"), 0, 86), 3, 3, 194, 14)
val BUTTON_DISABLED_BG = NinePatchTexture(Texture(Identifier("textures/gui/widgets.png"), 0, 46), 3, 3, 194, 14)
}
// Corners // Corners
val topLeft by lazy { val topLeft by lazy {
texture texture
} }
val topRight by lazy { val topRight by lazy {
Texture(texture.location, texture.u + cornerWidth + centerWidth, texture.v, texture.width, texture.height) Texture(texture.location, texture.u + cornerWidth + centerWidth, texture.v, texture.width, texture.height)
} }
val bottomLeft by lazy { val bottomLeft by lazy {
Texture(texture.location, texture.u, texture.v + cornerHeight + centerHeight, texture.width, texture.height) Texture(texture.location, texture.u, texture.v + cornerHeight + centerHeight, texture.width, texture.height)

View File

@ -1,4 +1,4 @@
package net.shadowfacts.cacao.util package net.shadowfacts.cacao.util.texture
import net.minecraft.util.Identifier import net.minecraft.util.Identifier

View File

@ -2,7 +2,7 @@ package net.shadowfacts.cacao.view
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.geometry.Rect import net.shadowfacts.cacao.geometry.Rect
import net.shadowfacts.cacao.util.NinePatchTexture import net.shadowfacts.cacao.util.texture.NinePatchTexture
import net.shadowfacts.cacao.util.RenderHelper import net.shadowfacts.cacao.util.RenderHelper
import net.shadowfacts.cacao.util.properties.ResettableLazyProperty import net.shadowfacts.cacao.util.properties.ResettableLazyProperty

View File

@ -2,7 +2,7 @@ package net.shadowfacts.cacao.view
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.util.RenderHelper import net.shadowfacts.cacao.util.RenderHelper
import net.shadowfacts.cacao.util.Texture import net.shadowfacts.cacao.util.texture.Texture
/** /**
* A helper class for drawing a [Texture] in a view. * A helper class for drawing a [Texture] in a view.

View File

@ -207,7 +207,7 @@ open class View() {
* Called during [wasAdded] to add any constraints to the [solver] that are internal to this view. * Called during [wasAdded] to add any constraints to the [solver] that are internal to this view.
* If overridden, the super-class method must be called. * If overridden, the super-class method must be called.
*/ */
open fun createInternalConstraints() { protected open fun createInternalConstraints() {
if (!usesConstraintBasedLayout) return if (!usesConstraintBasedLayout) return
solver.dsl { solver.dsl {

View File

@ -1,11 +1,9 @@
package net.shadowfacts.cacao.view.button package net.shadowfacts.cacao.view.button
import net.minecraft.util.Identifier
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.util.MouseButton import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.util.NinePatchTexture import net.shadowfacts.cacao.util.texture.NinePatchTexture
import net.shadowfacts.cacao.util.RenderHelper import net.shadowfacts.cacao.util.RenderHelper
import net.shadowfacts.cacao.util.Texture
import net.shadowfacts.cacao.view.NinePatchView import net.shadowfacts.cacao.view.NinePatchView
import net.shadowfacts.cacao.view.View import net.shadowfacts.cacao.view.View
import net.shadowfacts.kiwidsl.dsl import net.shadowfacts.kiwidsl.dsl
@ -23,12 +21,6 @@ import net.shadowfacts.kiwidsl.dsl
*/ */
abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val padding: Double = 4.0): View() { abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val padding: Double = 4.0): View() {
companion object {
val DEFAULT_BG = NinePatchTexture(Texture(Identifier("textures/gui/widgets.png"), 0, 66), 3, 3, 194, 14)
val HOVERED_BG = NinePatchTexture(Texture(Identifier("textures/gui/widgets.png"), 0, 86), 3, 3, 194, 14)
val DISABLED_BG = NinePatchTexture(Texture(Identifier("textures/gui/widgets.png"), 0, 46), 3, 3, 194, 14)
}
/** /**
* The function that handles when this button is clicked. * The function that handles when this button is clicked.
* The parameter is the type of the concrete button implementation that was used. * The parameter is the type of the concrete button implementation that was used.
@ -50,19 +42,19 @@ abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val
* If a [backgroundColor] is specified, it will be drawn behind the background View and thus not visible * If a [backgroundColor] is specified, it will be drawn behind the background View and thus not visible
* unless the background view is not fully opaque. * unless the background view is not fully opaque.
*/ */
var background: View? = NinePatchView(DEFAULT_BG) var background: View? = NinePatchView(NinePatchTexture.BUTTON_BG)
/** /**
* The background to draw when the button is hovered over by the mouse. * The background to draw when the button is hovered over by the mouse.
* If `null`, the normal [background] will be used. * If `null`, the normal [background] will be used.
* @see background * @see background
*/ */
var hoveredBackground: View? = NinePatchView(HOVERED_BG) var hoveredBackground: View? = NinePatchView(NinePatchTexture.BUTTON_HOVERED_BG)
/** /**
* The background to draw when the button is [disabled]. * The background to draw when the button is [disabled].
* If `null`, the normal [background] will be used. * If `null`, the normal [background] will be used.
* @see background * @see background
*/ */
var disabledBackground: View? = NinePatchView(DISABLED_BG) var disabledBackground: View? = NinePatchView(NinePatchTexture.BUTTON_DISABLED_BG)
override fun wasAdded() { override fun wasAdded() {
solver.dsl { solver.dsl {

View File

@ -6,8 +6,8 @@ import net.shadowfacts.cacao.geometry.Axis
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.geometry.Rect import net.shadowfacts.cacao.geometry.Rect
import net.shadowfacts.cacao.util.MouseButton import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.util.NinePatchTexture import net.shadowfacts.cacao.util.texture.NinePatchTexture
import net.shadowfacts.cacao.util.Texture import net.shadowfacts.cacao.util.texture.Texture
import net.shadowfacts.cacao.util.properties.ResettableLazyProperty import net.shadowfacts.cacao.util.properties.ResettableLazyProperty
import net.shadowfacts.cacao.view.NinePatchView import net.shadowfacts.cacao.view.NinePatchView
import net.shadowfacts.cacao.view.StackView import net.shadowfacts.cacao.view.StackView
@ -89,7 +89,7 @@ class DropdownButton<Value, ContentView: View>(
private fun showDropdown() { private fun showDropdown() {
val dropdownWindow = window.screen.addWindow(Window()) val dropdownWindow = window.screen.addWindow(Window())
val dropdownBackground = dropdownWindow.addView(NinePatchView(DEFAULT_BG).apply { val dropdownBackground = dropdownWindow.addView(NinePatchView(NinePatchTexture.BUTTON_BG).apply {
zIndex = -1.0 zIndex = -1.0
}) })
val stack = dropdownWindow.addView(StackView(Axis.VERTICAL, StackView.Distribution.LEADING)) val stack = dropdownWindow.addView(StackView(Axis.VERTICAL, StackView.Distribution.LEADING))
@ -100,8 +100,8 @@ class DropdownButton<Value, ContentView: View>(
val contentView = createView(value) val contentView = createView(value)
val button = stack.addArrangedSubview(Button(contentView, padding).apply { val button = stack.addArrangedSubview(Button(contentView, padding).apply {
background = null background = null
hoveredBackground = DropdownItemBackgroundView(index == 0, index == last, HOVERED_BG) hoveredBackground = DropdownItemBackgroundView(index == 0, index == last, NinePatchTexture.BUTTON_HOVERED_BG)
disabledBackground = DropdownItemBackgroundView(index == 0, index == last, DISABLED_BG) disabledBackground = DropdownItemBackgroundView(index == 0, index == last, NinePatchTexture.BUTTON_DISABLED_BG)
disabled = value == this@DropdownButton.value disabled = value == this@DropdownButton.value
handler = { handler = {
dropdownWindow.removeFromScreen() dropdownWindow.removeFromScreen()

View File

@ -4,7 +4,7 @@ import net.minecraft.util.Identifier
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.geometry.Size import net.shadowfacts.cacao.geometry.Size
import net.shadowfacts.cacao.util.MouseButton import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.util.Texture import net.shadowfacts.cacao.util.texture.Texture
import net.shadowfacts.cacao.view.TextureView import net.shadowfacts.cacao.view.TextureView
/** /**