mirror of
https://github.com/jlengrand/korge-samples.git
synced 2026-03-10 08:31:18 +00:00
Updated KorGE to 1.5.0c
This commit is contained in:
@@ -6,6 +6,6 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.soywiz.korlibs.korge.plugins:korge-gradle-plugin:1.4.3c")
|
||||
classpath("com.soywiz.korlibs.korge.plugins:korge-gradle-plugin:$korgePluginVersion")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
korgePluginVersion=1.5.0c
|
||||
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
org.gradle.parallel=true
|
||||
#disable.kotlin.native=true
|
||||
org.gradle.parallel.intra=true
|
||||
org.gradle.configureondemand=true
|
||||
|
||||
@@ -5,9 +5,9 @@ import com.soywiz.korge.render.*
|
||||
import com.soywiz.korge.scene.*
|
||||
import com.soywiz.korge.tween.*
|
||||
import com.soywiz.korge.view.*
|
||||
import com.soywiz.korge3d.experimental.*
|
||||
import com.soywiz.korge3d.experimental.animation.*
|
||||
import com.soywiz.korge3d.experimental.format.*
|
||||
import com.soywiz.korge3d.*
|
||||
import com.soywiz.korge3d.animation.*
|
||||
import com.soywiz.korge3d.format.*
|
||||
import com.soywiz.korim.color.*
|
||||
import com.soywiz.korim.format.*
|
||||
import com.soywiz.korinject.*
|
||||
|
||||
@@ -3,7 +3,7 @@ import com.soywiz.korge.input.*
|
||||
import com.soywiz.korge.scene.*
|
||||
import com.soywiz.korge.tween.*
|
||||
import com.soywiz.korge.view.*
|
||||
import com.soywiz.korge3d.experimental.*
|
||||
import com.soywiz.korge3d.*
|
||||
import com.soywiz.korim.color.*
|
||||
import com.soywiz.korio.async.*
|
||||
import com.soywiz.korma.geom.*
|
||||
|
||||
@@ -19,9 +19,9 @@ class AtlasTest : ViewsForTesting() {
|
||||
fun testAtlas() = suspendTest {
|
||||
val atlas = resourcesVfs["logos.atlas.json"].readAtlas(views)
|
||||
assertEquals(3, atlas.textures.size)
|
||||
assertEquals(Size(66, 66), atlas.textures["korau.png"]!!.texture.size)
|
||||
assertEquals(Size(66, 66), atlas.textures["korge.png"]!!.texture.size)
|
||||
assertEquals(Size(66, 66), atlas.textures["korim.png"]!!.texture.size)
|
||||
assertEquals(Size(64, 64), atlas.textures["korau.png"]!!.texture.size)
|
||||
assertEquals(Size(64, 64), atlas.textures["korge.png"]!!.texture.size)
|
||||
assertEquals(Size(64, 64), atlas.textures["korim.png"]!!.texture.size)
|
||||
}
|
||||
|
||||
private val BmpSlice.size get() = Size(width, height)
|
||||
|
||||
@@ -1,106 +1,66 @@
|
||||
import com.soywiz.korge.*
|
||||
import com.soywiz.korge.admob.*
|
||||
import com.soywiz.korge.box2d.*
|
||||
import com.soywiz.korge.input.*
|
||||
import com.soywiz.korge.view.*
|
||||
import com.soywiz.korgw.*
|
||||
import com.soywiz.korim.color.*
|
||||
import com.soywiz.korim.format.*
|
||||
import com.soywiz.korim.vector.*
|
||||
import com.soywiz.korio.async.*
|
||||
import com.soywiz.korio.file.std.*
|
||||
import com.soywiz.korio.lang.*
|
||||
import com.soywiz.korma.geom.vector.*
|
||||
import org.jbox2d.collision.shapes.*
|
||||
import org.jbox2d.callbacks.*
|
||||
import org.jbox2d.collision.*
|
||||
import org.jbox2d.dynamics.*
|
||||
import org.jbox2d.dynamics.contacts.*
|
||||
|
||||
suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "My Awesome Box2D Game!") {
|
||||
val admob = AdmobCreate(testing = true)
|
||||
|
||||
println("STARTED!")
|
||||
|
||||
addUpdatable {
|
||||
//println("FRAME!")
|
||||
}
|
||||
|
||||
launchImmediately {
|
||||
try {
|
||||
admob.bannerPrepareAndShow(Admob.Config("ca-app-pub-xxx/xxx"))
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
views.clearColor = Colors.DARKGREEN
|
||||
solidRect(300, 200, Colors.DARKCYAN)
|
||||
sgraphics {
|
||||
fill(Colors.DARKCYAN) {
|
||||
rect(-1, -1, 3, 2)
|
||||
}
|
||||
fill(Colors.AQUAMARINE) {
|
||||
circle(0, 0, 1)
|
||||
}
|
||||
fill(Colors.AQUAMARINE) {
|
||||
circle(1, 0, 1)
|
||||
}
|
||||
position(100, 100)
|
||||
}.scale(100, 100).interactive()
|
||||
worldView {
|
||||
position(400, 400).scale(20)
|
||||
|
||||
createBody {
|
||||
setPosition(0, -10)
|
||||
}.fixture {
|
||||
shape = BoxShape(100, 20)
|
||||
density = 0f
|
||||
}.setViewWithContainer(solidRect(100, 20, Colors.RED).position(-50, -10).interactive())
|
||||
}.setView(solidRect(100, 20, Colors.RED).position(-50, -10))
|
||||
|
||||
// Dynamic Body
|
||||
createBody {
|
||||
val ball = createBody {
|
||||
type = BodyType.DYNAMIC
|
||||
setPosition(0, 7)
|
||||
setPosition(0, 0)
|
||||
}.fixture {
|
||||
shape = BoxShape(2f, 2f)
|
||||
density = 0.5f
|
||||
friction = 0.2f
|
||||
}.setView(solidRect(2f, 2f, Colors.GREEN).anchor(.5, .5).interactive())
|
||||
shape = BoxShape(4f, 4f)
|
||||
density = 985f
|
||||
friction = 0f
|
||||
userData = "ball"
|
||||
}.setView(container {
|
||||
// [...]
|
||||
})
|
||||
|
||||
createBody {
|
||||
val enemy = createBody {
|
||||
type = BodyType.DYNAMIC
|
||||
setPosition(0.75, 13)
|
||||
setPosition(5, 0)
|
||||
}.fixture {
|
||||
shape = BoxShape(2f, 2f)
|
||||
density = 1f
|
||||
friction = 0.2f
|
||||
}.setView(sgraphics {
|
||||
fill(Colors.BLUE) {
|
||||
rect(-1f, -1f, 2f, 2f)
|
||||
}
|
||||
}.interactive())
|
||||
|
||||
createBody {
|
||||
type = BodyType.DYNAMIC
|
||||
setPosition(0.5, 15)
|
||||
}.fixture {
|
||||
shape = CircleShape().apply { m_radius = 2f }
|
||||
density = 22f
|
||||
friction = 3f
|
||||
}.setView(sgraphics {
|
||||
fillStroke(Context2d.Color(Colors.BLUE), Context2d.Color(Colors.RED), Context2d.StrokeInfo(thickness = 0.3)) {
|
||||
circle(0, 0, 2)
|
||||
//rect(0, 0, 400, 20)
|
||||
}
|
||||
fill(Colors.DARKCYAN) {
|
||||
circle(1, 1, 0.2)
|
||||
}
|
||||
hitTestUsingShapes = true
|
||||
}.interactive())
|
||||
shape = BoxShape(10, 20)
|
||||
}.setView(container {
|
||||
image(resourcesVfs["korge-ui.png"].readBitmap())
|
||||
.size(4f, 4f)
|
||||
.position(-2f, -2f)
|
||||
})
|
||||
}.apply {
|
||||
world.setContactListener(contactListener)
|
||||
}
|
||||
image(resourcesVfs["korge.png"].readBitmap())
|
||||
}
|
||||
|
||||
fun <T : View> T.interactive(): T = this.apply {
|
||||
alpha = 0.5
|
||||
onOver { alpha = 1.0 }
|
||||
onOut { alpha = 0.5 }
|
||||
val contactListener = object : ContactListener {
|
||||
override fun beginContact(contact: Contact) {
|
||||
println("beginContact")
|
||||
}
|
||||
|
||||
override fun endContact(contact: Contact) {
|
||||
println("endContact")
|
||||
}
|
||||
|
||||
override fun postSolve(contact: Contact, impulse: ContactImpulse) {
|
||||
println("postSolve")
|
||||
}
|
||||
|
||||
override fun preSolve(contact: Contact, oldManifold: Manifold) {
|
||||
println("preSolve")
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -13,7 +13,8 @@ import com.soywiz.korio.lang.*
|
||||
import com.soywiz.korma.geom.*
|
||||
import com.soywiz.korma.geom.ds.*
|
||||
|
||||
suspend fun main() = Korge(Korge.Config(module = TicTacToeModule, debug = true))
|
||||
//suspend fun main() = Korge(Korge.Config(module = TicTacToeModule, debug = true))
|
||||
suspend fun main() = Korge(Korge.Config(module = TicTacToeModule))
|
||||
|
||||
object TicTacToeModule : Module() {
|
||||
override val mainScene = TicTacToeMainScene::class
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import com.soywiz.kds.*
|
||||
import com.soywiz.korge.html.*
|
||||
import com.soywiz.korge.scene.*
|
||||
import com.soywiz.korim.bitmap.*
|
||||
import com.soywiz.korim.color.*
|
||||
import com.soywiz.korim.font.*
|
||||
import com.soywiz.korim.format.*
|
||||
import com.soywiz.korio.util.*
|
||||
import com.soywiz.korio.util.encoding.*
|
||||
|
||||
val DEFAULT_UI_SKIN_IMG by lazy {
|
||||
PNG.decode(
|
||||
"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".fromBase64()
|
||||
).toBMP32()
|
||||
}
|
||||
|
||||
val DefaultUISkin by lazy {
|
||||
UISkin(
|
||||
normal = DEFAULT_UI_SKIN_IMG.sliceWithSize(0, 0, 64, 64),
|
||||
hover = DEFAULT_UI_SKIN_IMG.sliceWithSize(64, 0, 64, 64),
|
||||
down = DEFAULT_UI_SKIN_IMG.sliceWithSize(127, 0, 64, 64),
|
||||
font = Html.FontFace.Bitmap(getSyncDebugBmpFontOnce())
|
||||
)
|
||||
}
|
||||
|
||||
private class SyncOnce<T> {
|
||||
var value: T? = null
|
||||
|
||||
operator fun invoke(callback: () -> T): T {
|
||||
if (value == null) {
|
||||
value = callback()
|
||||
}
|
||||
return value!!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var bmpFontOnce2 = SyncOnce<BitmapFont>()
|
||||
|
||||
private fun getSyncDebugBmpFontOnce() = bmpFontOnce2 {
|
||||
val tex = PNG.decode(DebugBitmapFont.DEBUG_FONT_BYTES).toBMP32().premultiplied().slice()
|
||||
val fntAdvance = 7
|
||||
val fntWidth = 8
|
||||
val fntHeight = 8
|
||||
|
||||
val fntBlockX = 2
|
||||
val fntBlockY = 2
|
||||
val fntBlockWidth = 12
|
||||
val fntBlockHeight = 12
|
||||
|
||||
BitmapFont(tex.bmp, fntHeight, fntHeight, fntHeight, (0 until 256).associate {
|
||||
val x = it % 16
|
||||
val y = it / 16
|
||||
it to BitmapFont.Glyph(
|
||||
it,
|
||||
tex.sliceWithSize(x * fntBlockWidth + fntBlockX, y * fntBlockHeight + fntBlockY, fntWidth, fntHeight),
|
||||
0,
|
||||
0,
|
||||
fntAdvance
|
||||
)
|
||||
}.toIntMap(), IntMap())
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import com.soywiz.korge.html.*
|
||||
import com.soywiz.korge.input.*
|
||||
import com.soywiz.korge.render.*
|
||||
import com.soywiz.korge.view.*
|
||||
import com.soywiz.korim.color.*
|
||||
import com.soywiz.korma.geom.*
|
||||
import kotlin.properties.*
|
||||
|
||||
inline fun Container.uiButton(
|
||||
width: Number = 128,
|
||||
height: Number = 64,
|
||||
label: String = "Button",
|
||||
skin: UISkin = defaultUISkin,
|
||||
block: UIButton.() -> Unit = {}
|
||||
): UIButton = UIButton(width.toDouble(), height.toDouble(), label, skin).also { addChild(it) }.apply(block)
|
||||
|
||||
open class UIButton(
|
||||
width: Double = 128.0,
|
||||
height: Double = 64.0,
|
||||
label: String = "Button",
|
||||
skin: UISkin = DefaultUISkin
|
||||
) : UIView(width, height) {
|
||||
var forcePressed by uiObservable(false) { updateState() }
|
||||
var skin: UISkin by uiObservable(skin) { updateState() }
|
||||
var label by uiObservable(label) { updateState() }
|
||||
private val rect = ninePatch(skin.normal, width, height, 16.0 / 64.0, 16.0 / 64.0, (64.0 - 16.0) / 64.0, (64.0 - 16.0) / 64.0) {}
|
||||
private val textShadow = text(label).also { it.position(1, 1) }
|
||||
private val text = text(label)
|
||||
private var bover by uiObservable(false) { updateState() }
|
||||
private var bpressing by uiObservable(false) { updateState() }
|
||||
|
||||
// @TODO: Make mouseEnabled open
|
||||
//override var mouseEnabled = uiObservable(true) { updateState() }
|
||||
|
||||
fun simulateHover() {
|
||||
bover = true
|
||||
}
|
||||
|
||||
fun simulateOut() {
|
||||
bover = false
|
||||
}
|
||||
|
||||
fun simulatePressing(value: Boolean) {
|
||||
bpressing = value
|
||||
}
|
||||
|
||||
fun simulateDown() {
|
||||
bpressing = true
|
||||
}
|
||||
|
||||
fun simulateUp() {
|
||||
bpressing = false
|
||||
}
|
||||
|
||||
init {
|
||||
mouse {
|
||||
onOver {
|
||||
simulateHover()
|
||||
}
|
||||
onOut {
|
||||
simulateOut()
|
||||
}
|
||||
onDown {
|
||||
simulateDown()
|
||||
}
|
||||
onUpAnywhere {
|
||||
simulateUp()
|
||||
}
|
||||
}
|
||||
updateState()
|
||||
}
|
||||
|
||||
private fun updateState() {
|
||||
when {
|
||||
bpressing || forcePressed -> {
|
||||
rect.tex = skin.down
|
||||
}
|
||||
bover -> {
|
||||
rect.tex = skin.hover
|
||||
}
|
||||
else -> {
|
||||
rect.tex = skin.normal
|
||||
}
|
||||
}
|
||||
text.format = Html.Format(face = skin.font, align = Html.Alignment.MIDDLE_CENTER, color = Colors.WHITE)
|
||||
text.setTextBounds(Rectangle(0, 0, width, height))
|
||||
text.setText(label)
|
||||
textShadow.format = Html.Format(face = skin.font, align = Html.Alignment.MIDDLE_CENTER, color = Colors.BLACK.withA(64))
|
||||
textShadow.setTextBounds(Rectangle(0, 0, width, height))
|
||||
textShadow.setText(label)
|
||||
}
|
||||
|
||||
override fun updatedSize() {
|
||||
super.updatedSize()
|
||||
rect.width = width
|
||||
rect.height = height
|
||||
updateState()
|
||||
}
|
||||
|
||||
override fun renderInternal(ctx: RenderContext) {
|
||||
//alpha = if (mouseEnabled) 1.0 else 0.5
|
||||
super.renderInternal(ctx)
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import com.soywiz.korge.html.*
|
||||
import com.soywiz.korge.input.*
|
||||
import com.soywiz.korge.view.*
|
||||
import com.soywiz.korim.color.*
|
||||
import com.soywiz.korma.geom.*
|
||||
import kotlin.properties.*
|
||||
|
||||
inline fun Container.uiCheckBox(
|
||||
checked: Boolean? = false,
|
||||
width: Number = 96.0,
|
||||
height: Number = 32.0,
|
||||
label: String = "CheckBox",
|
||||
skin: UISkin = defaultUISkin,
|
||||
block: UICheckBox.() -> Unit = {}
|
||||
): UICheckBox = UICheckBox(checked, width.toDouble(), height.toDouble(), label, skin).also { addChild(it) }.apply(block)
|
||||
|
||||
open class UICheckBox(
|
||||
checked: Boolean? = false,
|
||||
width: Double = 96.0,
|
||||
height: Double = 32.0,
|
||||
label: String = "CheckBox",
|
||||
private val skin: UISkin = DefaultUISkin
|
||||
) : UIView(width, height) {
|
||||
var checked by uiObservable(checked) { onPropsUpdate() }
|
||||
var label by uiObservable(label) { onPropsUpdate() }
|
||||
|
||||
private val area = solidRect(16, 16, Colors.TRANSPARENT_BLACK)
|
||||
//private val box = solidRect(16, 16, Colors.DARKGREY)
|
||||
private val box = uiButton(16, 16, skin = skin).also { it.mouseEnabled = false }
|
||||
private val text = text(label)
|
||||
|
||||
init {
|
||||
onClick {
|
||||
this@UICheckBox.checked = this@UICheckBox.checked != true
|
||||
onPropsUpdate()
|
||||
}
|
||||
onPropsUpdate()
|
||||
}
|
||||
|
||||
protected fun onPropsUpdate() {
|
||||
println("checked: $checked")
|
||||
area.position(0, 0).size(width, height)
|
||||
box.position(0, 0).size(height, height)
|
||||
.also {
|
||||
it.forcePressed = true
|
||||
if (checked == true) {
|
||||
it.label = "X"
|
||||
} else {
|
||||
it.label = ""
|
||||
}
|
||||
}
|
||||
text.position(height + 8.0, 0)
|
||||
.also { it.format = Html.Format(face = skin.font, align = Html.Alignment.MIDDLE_LEFT) }
|
||||
.also { it.setTextBounds(Rectangle(0, 0, width - height, height)) }
|
||||
.setText(label)
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import com.soywiz.korge.input.*
|
||||
import com.soywiz.korge.view.*
|
||||
import com.soywiz.korim.color.*
|
||||
import com.soywiz.korio.async.*
|
||||
|
||||
inline fun <T> Container.uiComboBox(
|
||||
width: Number = 192.0,
|
||||
height: Number = 32.0,
|
||||
selectedIndex: Int = 0,
|
||||
items: List<T>,
|
||||
skin: UISkin = defaultUISkin,
|
||||
block: UIComboBox<T>.() -> Unit = {}
|
||||
) = UIComboBox(width.toDouble(), height.toDouble(), selectedIndex, items, skin).also { addChild(it) }.also(block)
|
||||
|
||||
open class UIComboBox<T>(
|
||||
width: Double = 192.0,
|
||||
height: Double = 32.0,
|
||||
selectedIndex: Int = 0,
|
||||
items: List<T>,
|
||||
private val skin: UISkin = DefaultUISkin
|
||||
) : UIView(width, height) {
|
||||
|
||||
val onUpdatedSelection = Signal<UIComboBox<T>>()
|
||||
|
||||
var selectedIndex by uiObservable(selectedIndex) { updatedSelection() }
|
||||
var selectedItem: T?
|
||||
set(value) = run { selectedIndex = items.indexOf(value) }
|
||||
get() = items.getOrNull(selectedIndex)
|
||||
var items: List<T> by uiObservable(items) { updatedItems() }
|
||||
|
||||
val itemHeight get() = 32
|
||||
private val buttonSize get() = height
|
||||
private val itemsView = uiScrollableArea(verticalScroll = true, horizontalScroll = false, skin = skin, config = { visible = false }) { }
|
||||
private val selectedButton = uiButton(16, 16, "", skin = skin).also { it.mouseEnabled = false }
|
||||
private val dropButton = uiButton(16, 16, "+", skin = skin).also { it.mouseEnabled = false }
|
||||
private val invisibleRect = solidRect(16, 16, Colors.TRANSPARENT_BLACK)
|
||||
private var showItems = false
|
||||
|
||||
init {
|
||||
updatedItems()
|
||||
invisibleRect.onOver {
|
||||
selectedButton.simulateHover()
|
||||
dropButton.simulateHover()
|
||||
}
|
||||
invisibleRect.onOut {
|
||||
selectedButton.simulateOut()
|
||||
dropButton.simulateOut()
|
||||
}
|
||||
invisibleRect.onClick {
|
||||
showItems = !showItems
|
||||
updatedSize()
|
||||
}
|
||||
}
|
||||
|
||||
override fun updatedSize() {
|
||||
super.updatedSize()
|
||||
itemsView.visible = showItems
|
||||
itemsView.size(width, 196).position(0, height)
|
||||
selectedButton.simulatePressing(showItems)
|
||||
dropButton.simulatePressing(showItems)
|
||||
dropButton.label = if (showItems) "-" else "+"
|
||||
invisibleRect.size(width, height)
|
||||
selectedButton.position(0, 0).size(width - buttonSize, height)
|
||||
selectedButton.label = selectedItem?.toString() ?: ""
|
||||
//println("selectedIndex: $selectedIndex, selectedItem: $selectedItem")
|
||||
dropButton.position(width - buttonSize, 0).size(buttonSize, height)
|
||||
}
|
||||
|
||||
protected fun updatedSelection() {
|
||||
updatedSize()
|
||||
for (n in items.indices) {
|
||||
val button = itemsView.container.children[n] as? UIButton? ?: continue
|
||||
button.forcePressed = selectedIndex == n
|
||||
}
|
||||
onUpdatedSelection(this)
|
||||
}
|
||||
|
||||
protected fun updatedItems() {
|
||||
itemsView.container.removeChildren()
|
||||
for ((index, item) in items.withIndex()) {
|
||||
val button = itemsView.container.uiButton(width - 32, itemHeight, label = item.toString(), skin = skin) {
|
||||
position(0, index * itemHeight)
|
||||
onClick {
|
||||
showItems = false
|
||||
selectedIndex = index
|
||||
updatedSize()
|
||||
}
|
||||
}
|
||||
}
|
||||
itemsView.contentHeight = ((items.size) * itemHeight).toDouble()
|
||||
updatedSelection()
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import kotlin.reflect.*
|
||||
|
||||
inline fun <T> uiObservable(value: T, noinline observe: () -> Unit) = UIObservable(value, observe)
|
||||
|
||||
class UIObservable<T>(val initial: T, val observe: () -> Unit) {
|
||||
var currentValue = initial
|
||||
|
||||
operator fun getValue(obj: Any, prop: KProperty<*>): T {
|
||||
return currentValue
|
||||
}
|
||||
|
||||
operator fun setValue(obj: Any, prop: KProperty<*>, value: T) {
|
||||
currentValue = value
|
||||
observe()
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import com.soywiz.korge.view.*
|
||||
|
||||
inline fun Container.uiProgressBar(
|
||||
width: Number = 256.0,
|
||||
height: Number = 24.0,
|
||||
current: Number = 0.0,
|
||||
maximum: Number = 1.0,
|
||||
skin: UISkin = defaultUISkin,
|
||||
block: UIProgressBar.() -> Unit = {}
|
||||
): UIProgressBar = UIProgressBar(width.toDouble(), height.toDouble(), current.toDouble(), maximum.toDouble(), skin).also { addChild(it) }.also(block)
|
||||
|
||||
open class UIProgressBar(
|
||||
width: Double = 256.0,
|
||||
height: Double = 24.0,
|
||||
current: Double = 0.0,
|
||||
maximum: Double = 1.0,
|
||||
skin: UISkin = DefaultUISkin
|
||||
) : UIView(width, height) {
|
||||
var current: Double by uiObservable(current) { updatedSize() }
|
||||
var maximum: Double by uiObservable(maximum) { updatedSize() }
|
||||
override var ratio: Double
|
||||
set(value) = run { current = value * maximum }
|
||||
get() = current / maximum
|
||||
|
||||
private val bg = solidRect(width, height, skin.backColor)
|
||||
private val progress = uiButton(width, height, "", skin = skin).also { mouseEnabled = false }
|
||||
|
||||
init {
|
||||
updatedSize()
|
||||
}
|
||||
|
||||
override fun updatedSize() {
|
||||
bg.size(width, height)
|
||||
progress.forcePressed = true
|
||||
progress.size(width * ratio, height)
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import com.soywiz.kmem.*
|
||||
import com.soywiz.korge.input.*
|
||||
import com.soywiz.korge.view.*
|
||||
import com.soywiz.korio.async.*
|
||||
import com.soywiz.korma.geom.*
|
||||
import kotlin.math.*
|
||||
import kotlin.properties.*
|
||||
|
||||
inline fun Container.uiScrollBar(
|
||||
width: Number,
|
||||
height: Number,
|
||||
current: Number = 0.0,
|
||||
pageSize: Number = 1.0,
|
||||
totalSize: Number = 10.0,
|
||||
buttonSize: Number = 32.0,
|
||||
direction: UIScrollBar.Direction = if (width.toDouble() > height.toDouble()) UIScrollBar.Direction.Horizontal else UIScrollBar.Direction.Vertical,
|
||||
stepSize: Double = pageSize.toDouble() / 10.0,
|
||||
skin: UISkin = defaultUISkin,
|
||||
block: UIScrollBar.() -> Unit = {}
|
||||
): UIScrollBar = UIScrollBar(width.toDouble(), height.toDouble(), current.toDouble(), pageSize.toDouble(), totalSize.toDouble(), buttonSize.toDouble(), direction, stepSize, skin).also { addChild(it) }.apply(block)
|
||||
|
||||
open class UIScrollBar(
|
||||
width: Double,
|
||||
height: Double,
|
||||
current: Double,
|
||||
pageSize: Double,
|
||||
totalSize: Double,
|
||||
buttonSize: Double = 32.0,
|
||||
direction: Direction = if (width > height) Direction.Horizontal else Direction.Vertical,
|
||||
var stepSize: Double = pageSize / 10.0,
|
||||
skin: UISkin = DefaultUISkin
|
||||
) : UIView() {
|
||||
val onChange = Signal<UIScrollBar>()
|
||||
enum class Direction { Vertical, Horizontal }
|
||||
var current by uiObservable(current) { updatedPos() }
|
||||
var pageSize by uiObservable(pageSize) { updatedPos() }
|
||||
var totalSize by uiObservable(totalSize) { updatedPos() }
|
||||
var direction by uiObservable(direction) { reshape() }
|
||||
val isHorizontal get() = direction == Direction.Horizontal
|
||||
val isVertical get() = direction == Direction.Vertical
|
||||
override var ratio: Double
|
||||
set(value) = run { current = value.clamp01() * (totalSize - pageSize) }
|
||||
get() = (current / (totalSize - pageSize)).clamp(0.0, 1.0)
|
||||
override var width: Double by uiObservable(width) { reshape() }
|
||||
override var height: Double by uiObservable(height) { reshape() }
|
||||
var buttonSize by uiObservable(buttonSize) { reshape() }
|
||||
val buttonWidth get() = if (isHorizontal) buttonSize else width
|
||||
val buttonHeight get() = if (isHorizontal) height else buttonSize
|
||||
val clientWidth get() = if (isHorizontal) width - buttonWidth * 2 else width
|
||||
val clientHeight get() = if (isHorizontal) height else height - buttonHeight * 2
|
||||
|
||||
protected val background = solidRect(100, 100, skin.backColor)
|
||||
protected val lessButton = uiButton(16, 16, "-", skin = skin)
|
||||
protected val moreButton = uiButton(16, 16, "+", skin = skin)
|
||||
protected val caretButton = uiButton(16, 16, "", skin = skin)
|
||||
|
||||
protected val views get() = stage?.views
|
||||
|
||||
init {
|
||||
reshape()
|
||||
|
||||
var slx: Double = 0.0
|
||||
var sly: Double = 0.0
|
||||
var iratio: Double = 0.0
|
||||
var sratio: Double = 0.0
|
||||
val tempP = Point()
|
||||
|
||||
lessButton.onDown {
|
||||
deltaCurrent(-stepSize)
|
||||
reshape()
|
||||
}
|
||||
moreButton.onDown {
|
||||
deltaCurrent(+stepSize)
|
||||
reshape()
|
||||
}
|
||||
background.onClick {
|
||||
val pos = if (isHorizontal) caretButton.localMouseX(views!!) else caretButton.localMouseY(views!!)
|
||||
deltaCurrent(this.pageSize * pos.sign)
|
||||
}
|
||||
caretButton.onMouseDrag {
|
||||
val lmouse = background.localMouseXY(views, tempP)
|
||||
val lx = lmouse.x
|
||||
val ly = lmouse.y
|
||||
val cratio = if (isHorizontal) lmouse.x / background.width else lmouse.y / background.height
|
||||
if (it.start) {
|
||||
slx = lx
|
||||
sly = ly
|
||||
iratio = ratio
|
||||
sratio = cratio
|
||||
}
|
||||
val dratio = cratio - sratio
|
||||
ratio = iratio + dratio
|
||||
reshape()
|
||||
}
|
||||
}
|
||||
|
||||
private fun deltaCurrent(value: Double) {
|
||||
//println("deltaCurrent: $value")
|
||||
current = (current + value).clamp(0.0, totalSize - pageSize)
|
||||
}
|
||||
|
||||
private fun reshape() {
|
||||
if (isHorizontal) {
|
||||
background.position(buttonWidth, 0).size(clientWidth, clientHeight)
|
||||
lessButton.position(0, 0).size(buttonWidth, buttonHeight)
|
||||
moreButton.position(width - buttonWidth, 0).size(buttonWidth, buttonHeight)
|
||||
val caretWidth = (clientWidth * (pageSize / totalSize)).clamp(4.0, clientWidth)
|
||||
caretButton.position(buttonWidth + (clientWidth - caretWidth) * ratio, 0).size(caretWidth, buttonHeight)
|
||||
} else {
|
||||
background.position(0, buttonHeight).size(clientWidth, clientHeight)
|
||||
lessButton.position(0, 0).size(buttonWidth, buttonHeight)
|
||||
moreButton.position(0, height - buttonHeight).size(buttonWidth, buttonHeight)
|
||||
val caretHeight = (clientHeight * (pageSize / totalSize)).clamp(4.0, clientHeight)
|
||||
caretButton.position(0, buttonHeight + (clientHeight - caretHeight) * ratio).size(buttonWidth, caretHeight)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatedPos() {
|
||||
reshape()
|
||||
onChange(this)
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import com.soywiz.korge.view.*
|
||||
|
||||
inline fun Container.uiScrollableArea(
|
||||
width: Number = 256.0,
|
||||
height: Number = 256.0,
|
||||
contentWidth: Number = 512.0,
|
||||
contentHeight: Number = 512.0,
|
||||
buttonSize: Number = 32.0,
|
||||
verticalScroll: Boolean = true,
|
||||
horizontalScroll: Boolean = true,
|
||||
skin: UISkin = defaultUISkin,
|
||||
config: UIScrollableArea.() -> Unit = {},
|
||||
block: Container.() -> Unit = {}
|
||||
): UIScrollableArea = UIScrollableArea(
|
||||
width.toDouble(), height.toDouble(), contentWidth.toDouble(), contentHeight.toDouble(), buttonSize.toDouble(), verticalScroll, horizontalScroll, skin
|
||||
).also { addChild(it) }.also(config).also { block(it.container) }
|
||||
|
||||
// @TODO: Optimize this!
|
||||
// @TODO: Add an actualContainer = this inside Container
|
||||
open class UIScrollableArea(
|
||||
width: Double = 256.0,
|
||||
height: Double = 256.0,
|
||||
contentWidth: Double = 512.0,
|
||||
contentHeight: Double = 512.0,
|
||||
buttonSize: Double = 32.0,
|
||||
verticalScroll: Boolean = true,
|
||||
horizontalScroll: Boolean = true,
|
||||
skin: UISkin = DefaultUISkin
|
||||
) : UIView(width, height) {
|
||||
var buttonSize by uiObservable(buttonSize) { updatedSize() }
|
||||
|
||||
var contentWidth by uiObservable(contentWidth) { updatedSize() }
|
||||
var contentHeight by uiObservable(contentHeight) { updatedSize() }
|
||||
|
||||
var verticalScroll by uiObservable(verticalScroll) { updatedSize() }
|
||||
var horizontalScroll by uiObservable(horizontalScroll) { updatedSize() }
|
||||
|
||||
val clientWidth get() = if (verticalScroll) width - buttonSize else width
|
||||
val clientHeight get() = if (horizontalScroll) height - buttonSize else height
|
||||
|
||||
val clipContainer = clipContainer(clientWidth, clientHeight)
|
||||
val container = clipContainer.fixedSizeContainer(contentWidth, contentHeight)
|
||||
val horScroll = uiScrollBar(width, buttonSize, skin = skin).also { it.onChange { moved() } }
|
||||
val verScroll = uiScrollBar(buttonSize, height, skin = skin).also { it.onChange { moved() } }
|
||||
|
||||
init {
|
||||
updatedSize()
|
||||
}
|
||||
|
||||
override fun updatedSize() {
|
||||
super.updatedSize()
|
||||
|
||||
horScroll.totalSize = contentWidth
|
||||
horScroll.pageSize = clientWidth
|
||||
horScroll.stepSize = clientWidth / 4
|
||||
|
||||
verScroll.totalSize = contentHeight
|
||||
verScroll.pageSize = clientHeight
|
||||
verScroll.stepSize = clientHeight / 4
|
||||
|
||||
clipContainer.size(clientWidth, clientHeight)
|
||||
container.size(contentWidth, contentHeight)
|
||||
|
||||
horScroll.size(clientWidth, buttonSize).position(0, height - buttonSize).also { it.visible = horizontalScroll }
|
||||
verScroll.size(buttonSize, clientHeight).position(width - buttonSize, 0).also { it.visible = verticalScroll }
|
||||
}
|
||||
|
||||
protected fun moved() {
|
||||
//println("" + verScroll.current + " :: " + verScroll.totalSize + " :: " + verScroll.pageSize + " :: " + verScroll.stepSize)
|
||||
container.x = -horScroll.current
|
||||
container.y = -verScroll.current
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import com.soywiz.kds.*
|
||||
import com.soywiz.korge.html.*
|
||||
import com.soywiz.korge.view.*
|
||||
import com.soywiz.korim.bitmap.*
|
||||
import com.soywiz.korim.color.*
|
||||
|
||||
@PublishedApi
|
||||
internal var View.internalDefaultUISkin: UISkin? by extraProperty("defaultUiSkin") { null }
|
||||
var View.defaultUISkin: UISkin
|
||||
set(value) = run { internalDefaultUISkin = value }
|
||||
get() = internalDefaultUISkin ?: parent?.defaultUISkin ?: DefaultUISkin
|
||||
|
||||
fun Container.uiSkin(skin: UISkin, block: Container.() -> Unit) {
|
||||
defaultUISkin = skin
|
||||
block()
|
||||
}
|
||||
|
||||
data class UISkin(
|
||||
val normal: BmpSlice,
|
||||
val hover: BmpSlice,
|
||||
val down: BmpSlice,
|
||||
val backColor: RGBA = Colors.DARKGREY,
|
||||
val font: Html.FontFace = Html.FontFace.Named("Arial")
|
||||
)
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.soywiz.korge.newui
|
||||
|
||||
import com.soywiz.kds.*
|
||||
import com.soywiz.korge.component.*
|
||||
import com.soywiz.korge.input.*
|
||||
import com.soywiz.korge.render.*
|
||||
import com.soywiz.korge.view.*
|
||||
import kotlin.properties.*
|
||||
|
||||
open class UIView(
|
||||
width: Double = 90.0,
|
||||
height: Double = 32.0
|
||||
) : Container() {
|
||||
override var width: Double by uiObservable(width) { updatedSize() }
|
||||
override var height: Double by uiObservable(height) { updatedSize() }
|
||||
|
||||
open var uiEnabled by uiObservable(true) { updateEnabled() }
|
||||
open var uiDisabled: Boolean
|
||||
set(value) = run { uiEnabled = !value }
|
||||
get() = !uiEnabled
|
||||
|
||||
fun enable(set: Boolean = true) = run { uiEnabled = set }
|
||||
fun disable() = run { uiEnabled = false }
|
||||
|
||||
protected open fun updatedSize() {
|
||||
}
|
||||
|
||||
protected open fun updateEnabled() {
|
||||
mouseEnabled = uiEnabled
|
||||
// @TODO: Shouldn't change alpha
|
||||
alpha = if (uiEnabled) 1.0 else 0.7
|
||||
}
|
||||
|
||||
override fun renderInternal(ctx: RenderContext) {
|
||||
registerUISupportOnce()
|
||||
super.renderInternal(ctx)
|
||||
}
|
||||
|
||||
private var registered = false
|
||||
private fun registerUISupportOnce() {
|
||||
if (registered) return
|
||||
val stage = stage ?: return
|
||||
registered = true
|
||||
if (stage.getExtra("uiSupport") == true) return
|
||||
stage.setExtra("uiSupport", true)
|
||||
stage.keys {
|
||||
onKeyDown {
|
||||
|
||||
}
|
||||
}
|
||||
stage?.getOrCreateComponent { stage ->
|
||||
object : UpdateComponentWithViews {
|
||||
override val view: View = stage
|
||||
override fun update(views: Views, ms: Double) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user