mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-12 19:44:05 +09:00
js cannot be accessed concurrently
This commit is contained in:
@@ -343,7 +343,7 @@ let bufAssemble = (isPreview) => {
|
|||||||
}
|
}
|
||||||
//let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" : `\\u${buf[i].codePointAt(0).toString(16).toUpperCase()}`).join(' ')
|
//let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" : `\\u${buf[i].codePointAt(0).toString(16).toUpperCase()}`).join(' ')
|
||||||
let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" : `${buf[i]}`).join(' ')
|
let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" : `${buf[i]}`).join(' ')
|
||||||
return Object.freeze({"n":"두벌식 표준","states":states,"c":"CuriousTo\uA75Bvald",
|
return Object.freeze({"n":"두벌식 표준","v":"one","c":"CuriousTo\uA75Bvald",
|
||||||
// return: [displayed output, composed output]
|
// return: [displayed output, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
@@ -472,6 +472,5 @@ return Object.freeze({"n":"두벌식 표준","states":states,"c":"CuriousTo\uA75
|
|||||||
return ret
|
return ret
|
||||||
},
|
},
|
||||||
"reset":()=>{ reset() },
|
"reset":()=>{ reset() },
|
||||||
"composing":()=>(states.code!=0),
|
"composing":()=>(states.code!=0)
|
||||||
"maxCandidates":()=>1
|
|
||||||
})
|
})
|
||||||
@@ -369,7 +369,7 @@ let bufAssemble = (isPreview) => {
|
|||||||
return states.buf.join('')
|
return states.buf.join('')
|
||||||
}
|
}
|
||||||
let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" : `\\u${buf[i].codePointAt(0).toString(16).toUpperCase()}`).join(' ')
|
let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" : `\\u${buf[i].codePointAt(0).toString(16).toUpperCase()}`).join(' ')
|
||||||
return Object.freeze({"n":"세벌식 3-90","states":states,"c":"CuriousTo\uA75Bvald",
|
return Object.freeze({"n":"세벌식 3-90","v":"one","c":"CuriousTo\uA75Bvald",
|
||||||
// return: [displayed output, composed output]
|
// return: [displayed output, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
@@ -474,6 +474,5 @@ return Object.freeze({"n":"세벌식 3-90","states":states,"c":"CuriousTo\uA75Bv
|
|||||||
return ret
|
return ret
|
||||||
},
|
},
|
||||||
"reset":()=>{ reset() },
|
"reset":()=>{ reset() },
|
||||||
"composing":()=>(states.code!=0),
|
"composing":()=>(states.code!=0)
|
||||||
"maxCandidates":()=>1
|
|
||||||
})
|
})
|
||||||
@@ -380,7 +380,7 @@ let bufAssemble = (isPreview) => {
|
|||||||
return states.buf.join('')
|
return states.buf.join('')
|
||||||
}
|
}
|
||||||
let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" : `\\u${buf[i].codePointAt(0).toString(16).toUpperCase()}`).join(' ')
|
let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" : `\\u${buf[i].codePointAt(0).toString(16).toUpperCase()}`).join(' ')
|
||||||
return Object.freeze({"n":"신세벌식 P2","states":states,"c":"CuriousTo\uA75Bvald",
|
return Object.freeze({"n":"신세벌식 P2","v":"one","c":"CuriousTo\uA75Bvald",
|
||||||
// return: [displayed output, composed output]
|
// return: [displayed output, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
@@ -509,6 +509,5 @@ return Object.freeze({"n":"신세벌식 P2","states":states,"c":"CuriousTo\uA75B
|
|||||||
return ret
|
return ret
|
||||||
},
|
},
|
||||||
"reset":()=>{ reset() },
|
"reset":()=>{ reset() },
|
||||||
"composing":()=>(states.code!=0),
|
"composing":()=>(states.code!=0)
|
||||||
"maxCandidates":()=>1
|
|
||||||
})
|
})
|
||||||
@@ -269,7 +269,7 @@ let getCandidatesUsingBuf = () => {
|
|||||||
// console.log(`cangjie in, buf: ${states.buf}, candidates: ${states.candidates}`)
|
// console.log(`cangjie in, buf: ${states.buf}, candidates: ${states.candidates}`)
|
||||||
return `${states.buf},${states.candidates}`
|
return `${states.buf},${states.candidates}`
|
||||||
}
|
}
|
||||||
return Object.freeze({"n":"五仓简体 Qwerty","states":states,"c":"CuriousTo\uA75Bvald, 倉頡之友 。馬來西亞 http://www.chinesecj.com",
|
return Object.freeze({"n":"五仓简体 Qwerty","v":"many","c":"CuriousTo\uA75Bvald, 倉頡之友 。馬來西亞 http://www.chinesecj.com",
|
||||||
// return: [displayed output, composed output]
|
// return: [displayed output, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
@@ -313,6 +313,5 @@ return Object.freeze({"n":"五仓简体 Qwerty","states":states,"c":"CuriousTo\u
|
|||||||
return ret
|
return ret
|
||||||
},
|
},
|
||||||
"reset":()=>{ reset() },
|
"reset":()=>{ reset() },
|
||||||
"composing":()=>(states.code!=0),
|
"composing":()=>(states.code!=0)
|
||||||
"maxCandidates":()=>10
|
|
||||||
})
|
})
|
||||||
@@ -269,7 +269,7 @@ let getCandidatesUsingBuf = () => {
|
|||||||
// console.log(`cangjie in, buf: ${states.buf}, candidates: ${states.candidates}`)
|
// console.log(`cangjie in, buf: ${states.buf}, candidates: ${states.candidates}`)
|
||||||
return `${states.buf},${states.candidates}`
|
return `${states.buf},${states.candidates}`
|
||||||
}
|
}
|
||||||
return Object.freeze({"n":"五倉正體 Qwerty","states":states,"c":"CuriousTo\uA75Bvald, 倉頡之友 。馬來西亞 http://www.chinesecj.com",
|
return Object.freeze({"n":"五倉正體 Qwerty","v":"many","c":"CuriousTo\uA75Bvald, 倉頡之友 。馬來西亞 http://www.chinesecj.com",
|
||||||
// return: [displayed output, composed output]
|
// return: [displayed output, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
@@ -313,6 +313,5 @@ return Object.freeze({"n":"五倉正體 Qwerty","states":states,"c":"CuriousTo\u
|
|||||||
return ret
|
return ret
|
||||||
},
|
},
|
||||||
"reset":()=>{ reset() },
|
"reset":()=>{ reset() },
|
||||||
"composing":()=>(states.code!=0),
|
"composing":()=>(states.code!=0)
|
||||||
"maxCandidates":()=>10
|
|
||||||
})
|
})
|
||||||
@@ -11,17 +11,33 @@ data class TerrarumKeyLayout(
|
|||||||
val symbols: Array<Array<String?>>?
|
val symbols: Array<Array<String?>>?
|
||||||
)
|
)
|
||||||
|
|
||||||
data class TerrarumInputMethod(
|
data class TerrarumIME(
|
||||||
val name: String,
|
val name: String,
|
||||||
|
val config: TerrarumIMEConf,
|
||||||
// (headkey, shiftin, altgrin, lowLayerKeysym)
|
// (headkey, shiftin, altgrin, lowLayerKeysym)
|
||||||
val acceptChar: (Int, Boolean, Boolean, String) -> Pair<IMECanditates, IMEOutput>,
|
val acceptChar: (Int, Boolean, Boolean, String) -> Pair<IMECanditates, IMEOutput>,
|
||||||
val backspace: () -> IMECanditates,
|
val backspace: () -> IMECanditates,
|
||||||
val endCompose: () -> IMEOutput,
|
val endCompose: () -> IMEOutput,
|
||||||
val reset: () -> Unit,
|
val reset: () -> Unit,
|
||||||
val composing: () -> Boolean,
|
val composing: () -> Boolean
|
||||||
val maxCandidates: () -> Int
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class TerrarumIMEConf(
|
||||||
|
val name: String,
|
||||||
|
val copying: String,
|
||||||
|
val candidates: TerrarumIMEViewCount
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class TerrarumIMEViewCount {
|
||||||
|
NONE, ONE, MANY;
|
||||||
|
|
||||||
|
fun toInt() = when (this) {
|
||||||
|
NONE -> 0
|
||||||
|
ONE -> 1
|
||||||
|
MANY -> 10 // an hard-coded config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key Layout File Structure for Low Layer:
|
* Key Layout File Structure for Low Layer:
|
||||||
* - n: Displayed name of the keyboard layout
|
* - n: Displayed name of the keyboard layout
|
||||||
@@ -44,7 +60,7 @@ object IME {
|
|||||||
const val IME_EXTENSION = "ime"
|
const val IME_EXTENSION = "ime"
|
||||||
|
|
||||||
private val lowLayers = HashMap<String, TerrarumKeyLayout>()
|
private val lowLayers = HashMap<String, TerrarumKeyLayout>()
|
||||||
private val highLayers = HashMap<String, TerrarumInputMethod>()
|
private val highLayers = HashMap<String, TerrarumIME>()
|
||||||
|
|
||||||
private val context = org.graalvm.polyglot.Context.newBuilder("js")
|
private val context = org.graalvm.polyglot.Context.newBuilder("js")
|
||||||
.allowHostAccess(org.graalvm.polyglot.HostAccess.EXPLICIT)
|
.allowHostAccess(org.graalvm.polyglot.HostAccess.EXPLICIT)
|
||||||
@@ -73,7 +89,7 @@ object IME {
|
|||||||
return lowLayers[name.lowercase()]!!
|
return lowLayers[name.lowercase()]!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getHighLayerByName(name: String): TerrarumInputMethod {
|
fun getHighLayerByName(name: String): TerrarumIME {
|
||||||
return highLayers[name.lowercase()]!!
|
return highLayers[name.lowercase()]!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,12 +101,20 @@ object IME {
|
|||||||
return highLayers.keys.toList()
|
return highLayers.keys.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun String.toViewCount() = when (this.lowercase()) {
|
||||||
|
"none" -> TerrarumIMEViewCount.NONE
|
||||||
|
"one" -> TerrarumIMEViewCount.ONE
|
||||||
|
"many" -> TerrarumIMEViewCount.MANY
|
||||||
|
else -> throw IllegalArgumentException(this)
|
||||||
|
}
|
||||||
|
|
||||||
private fun parseKeylayoutFile(file: File): TerrarumKeyLayout {
|
private fun parseKeylayoutFile(file: File): TerrarumKeyLayout {
|
||||||
val src = file.readText(Charsets.UTF_8)
|
val src = file.readText(Charsets.UTF_8)
|
||||||
val jsval = context.eval("js", "'use strict';Object.freeze($src)")
|
val jsval = context.eval("js", "'use strict';Object.freeze($src)")
|
||||||
val name = jsval.getMember("n").asString()
|
val name = jsval.getMember("n").asString()
|
||||||
|
|
||||||
val out = Array(256) { Array<String?>(4) { null } }
|
val out = Array(256) { Array<String?>(4) { null } }
|
||||||
|
|
||||||
for (keycode in 0L until 256L) {
|
for (keycode in 0L until 256L) {
|
||||||
val a = jsval.getMember("t").getArrayElement(keycode)
|
val a = jsval.getMember("t").getArrayElement(keycode)
|
||||||
if (!a.isNull) {
|
if (!a.isNull) {
|
||||||
@@ -113,26 +137,30 @@ object IME {
|
|||||||
private fun String.toCanditates(): List<String> =
|
private fun String.toCanditates(): List<String> =
|
||||||
this.split(',').mapNotNull { it.ifBlank { null } }
|
this.split(',').mapNotNull { it.ifBlank { null } }
|
||||||
|
|
||||||
private fun parseImeFile(file: File): TerrarumInputMethod {
|
private fun parseImeFile(file: File): TerrarumIME {
|
||||||
val code = file.readText(Charsets.UTF_8)
|
val code = file.readText(Charsets.UTF_8)
|
||||||
val jsval = context.eval("js", "\"use strict\";(function(){$code})()")
|
val jsval = context.eval("js", "\"use strict\";(function(){$code})()")
|
||||||
val name = jsval.getMember("n").asString()
|
val name = jsval.getMember("n").asString()
|
||||||
|
val candidatesCount = jsval.getMember("v").asString().toViewCount()
|
||||||
|
val copying = jsval.getMember("c").asString()
|
||||||
|
|
||||||
|
return TerrarumIME(
|
||||||
return TerrarumInputMethod(name, { headkey, shifted, alted, lowLayerKeysym ->
|
name,
|
||||||
val a = jsval.invokeMember("accept", headkey, shifted, alted, lowLayerKeysym)
|
TerrarumIMEConf(
|
||||||
a.getArrayElement(0).asString().toCanditates() to a.getArrayElement(1).asString()
|
name, copying, candidatesCount
|
||||||
}, {
|
),
|
||||||
jsval.invokeMember("backspace").asString().toCanditates()
|
{ headkey, shifted, alted, lowLayerKeysym ->
|
||||||
}, {
|
val a = jsval.invokeMember("accept", headkey, shifted, alted, lowLayerKeysym)
|
||||||
jsval.invokeMember("end").asString()
|
a.getArrayElement(0).asString().toCanditates() to a.getArrayElement(1).asString()
|
||||||
}, {
|
}, {
|
||||||
jsval.invokeMember("reset")
|
jsval.invokeMember("backspace").asString().toCanditates()
|
||||||
}, {
|
}, {
|
||||||
jsval.invokeMember("composing").asBoolean()
|
jsval.invokeMember("end").asString()
|
||||||
}, {
|
}, {
|
||||||
jsval.invokeMember("maxCandidates").asInt()
|
jsval.invokeMember("reset")
|
||||||
}
|
}, {
|
||||||
|
jsval.invokeMember("composing").asBoolean()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package net.torvald.terrarum.gamecontroller
|
|||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.Input
|
import com.badlogic.gdx.Input
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.TerrarumAppConfiguration
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BIG WARNING SIGN: since the strober will run on separate thread, ALWAYS BEWARE OF THE [ConcurrentModificationException]!
|
* BIG WARNING SIGN: since the strober will run on separate thread, ALWAYS BEWARE OF THE [ConcurrentModificationException]!
|
||||||
@@ -23,9 +24,9 @@ object InputStrober {
|
|||||||
/** always Low Layer */
|
/** always Low Layer */
|
||||||
// private var keymap = IME.getLowLayerByName(App.getConfigString("basekeyboardlayout"))
|
// private var keymap = IME.getLowLayerByName(App.getConfigString("basekeyboardlayout"))
|
||||||
|
|
||||||
private val thread = Thread { while (!Thread.interrupted()) {
|
private val thread = Thread({ while (!Thread.interrupted()) {
|
||||||
if (Gdx.input != null) withKeyboardEvent()
|
try { if (Gdx.input != null) withKeyboardEvent() } catch (e: InterruptedException) { break }
|
||||||
} }
|
} }, "${TerrarumAppConfiguration.GAME_NAME}${this.javaClass.simpleName}")
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// println("InputStrobe start")
|
// println("InputStrobe start")
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ object UILoadGovernor {
|
|||||||
*/
|
*/
|
||||||
class UILoadDemoSavefiles(val remoCon: UIRemoCon) : UICanvas() {
|
class UILoadDemoSavefiles(val remoCon: UIRemoCon) : UICanvas() {
|
||||||
|
|
||||||
private val hash = RandomWordsName(3)
|
// private val hash = RandomWordsName(3)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
CommonResourcePool.addToLoadingList("inventory_category") {
|
CommonResourcePool.addToLoadingList("inventory_category") {
|
||||||
@@ -359,7 +359,7 @@ class UILoadDemoSavefiles(val remoCon: UIRemoCon) : UICanvas() {
|
|||||||
batch.draw(saveTex, (width - uiWidth - 10) / 2f, 0f)
|
batch.draw(saveTex, (width - uiWidth - 10) / 2f, 0f)
|
||||||
|
|
||||||
// draw texts
|
// draw texts
|
||||||
val loadGameTitleStr = Lang[titles[mode]] + "$EMDASH$hash"
|
val loadGameTitleStr = Lang[titles[mode]]// + "$EMDASH$hash"
|
||||||
// "Game Load"
|
// "Game Load"
|
||||||
App.fontGame.draw(batch, loadGameTitleStr, (width - App.fontGame.getWidth(loadGameTitleStr)).div(2).toFloat(), titleTextPosY.toFloat())
|
App.fontGame.draw(batch, loadGameTitleStr, (width - App.fontGame.getWidth(loadGameTitleStr)).div(2).toFloat(), titleTextPosY.toFloat())
|
||||||
// Control help
|
// Control help
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import net.torvald.terrarum.ccE
|
|||||||
import net.torvald.terrarum.console.Authenticator
|
import net.torvald.terrarum.console.Authenticator
|
||||||
import net.torvald.terrarum.console.CommandInterpreter
|
import net.torvald.terrarum.console.CommandInterpreter
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.util.CircularArray
|
import net.torvald.util.CircularArray
|
||||||
|
|
||||||
@@ -32,14 +33,16 @@ class ConsoleWindow : UICanvas() {
|
|||||||
private var messageDisplayPos: Int = 0
|
private var messageDisplayPos: Int = 0
|
||||||
private var messagesCount: Int = 0
|
private var messagesCount: Int = 0
|
||||||
|
|
||||||
private var commandInputPool: StringBuilder? = null
|
// private var commandInputPool: StringBuilder? = null
|
||||||
private var commandHistory = CircularArray<String>(COMMAND_HISTORY_MAX, true)
|
private var commandHistory = CircularArray<String>(COMMAND_HISTORY_MAX, true)
|
||||||
|
|
||||||
private val LINE_HEIGHT = 20
|
private val LINE_HEIGHT = 20
|
||||||
private val MESSAGES_DISPLAY_COUNT = 11
|
private val MESSAGES_DISPLAY_COUNT = 11
|
||||||
|
|
||||||
|
private val inputToMsgboxGap = 3
|
||||||
|
|
||||||
override var width: Int = App.scr.width
|
override var width: Int = App.scr.width
|
||||||
override var height: Int = LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT + 1)
|
override var height: Int = LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT + 1) + inputToMsgboxGap
|
||||||
|
|
||||||
override var openCloseTime = 0f
|
override var openCloseTime = 0f
|
||||||
|
|
||||||
@@ -51,8 +54,12 @@ class ConsoleWindow : UICanvas() {
|
|||||||
|
|
||||||
private var iMadeTheGameToPause = false
|
private var iMadeTheGameToPause = false
|
||||||
|
|
||||||
|
private val textinput = UIItemTextLineInput(this, 0, 0, this.width)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
reset()
|
reset()
|
||||||
|
addUIitem(textinput)
|
||||||
|
textinput.isActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private val lb = ArrayList<String>()
|
private val lb = ArrayList<String>()
|
||||||
@@ -73,6 +80,8 @@ class ConsoleWindow : UICanvas() {
|
|||||||
it.setTooltipMessage(null)
|
it.setTooltipMessage(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uiItems.forEach { it.update(delta) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||||
@@ -81,65 +90,75 @@ class ConsoleWindow : UICanvas() {
|
|||||||
Toolkit.fillArea(batch, drawOffX, drawOffY, width.toFloat(), height.toFloat())
|
Toolkit.fillArea(batch, drawOffX, drawOffY, width.toFloat(), height.toFloat())
|
||||||
Toolkit.fillArea(batch, drawOffX, drawOffY, width.toFloat(), LINE_HEIGHT.toFloat())
|
Toolkit.fillArea(batch, drawOffX, drawOffY, width.toFloat(), LINE_HEIGHT.toFloat())
|
||||||
|
|
||||||
val input = commandInputPool!!.toString()
|
// val input = commandInputPool!!.toString()
|
||||||
val inputDrawWidth = App.fontGame.getWidth(input)
|
// val inputDrawWidth = App.fontGame.getWidth(input)
|
||||||
val inputDrawHeight = App.fontGame.lineHeight
|
// val inputDrawHeight = App.fontGame.lineHeight
|
||||||
|
//
|
||||||
// text and cursor
|
// text and cursor
|
||||||
batch.color = Color.WHITE
|
// batch.color = Color.WHITE
|
||||||
App.fontGame.draw(batch, input, 1f + drawOffX, drawOffY)
|
// App.fontGame.draw(batch, input, 1f + drawOffX, drawOffY)
|
||||||
|
//
|
||||||
batch.color = Color(0x7f7f7f_ff)
|
// batch.color = Color(0x7f7f7f_ff)
|
||||||
Toolkit.fillArea(batch, inputDrawWidth.toFloat() + drawOffX + 1, drawOffY, 2f, inputDrawHeight)
|
// Toolkit.fillArea(batch, inputDrawWidth.toFloat() + drawOffX + 1, drawOffY, 2f, inputDrawHeight)
|
||||||
batch.color = Color.WHITE
|
// batch.color = Color.WHITE
|
||||||
Toolkit.fillArea(batch, inputDrawWidth.toFloat() + drawOffX + 1, drawOffY, 1f, inputDrawHeight - 1)
|
// Toolkit.fillArea(batch, inputDrawWidth.toFloat() + drawOffX + 1, drawOffY, 1f, inputDrawHeight - 1)
|
||||||
|
|
||||||
|
|
||||||
// messages
|
// messages
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
|
||||||
for (i in 0 until MESSAGES_DISPLAY_COUNT) {
|
for (i in 0 until MESSAGES_DISPLAY_COUNT) {
|
||||||
val message = messages[messageDisplayPos + i] ?: ""
|
val message = messages[messageDisplayPos + i] ?: ""
|
||||||
App.fontGame.draw(batch, message, 1f + drawOffX, (LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT - i)).toFloat() + drawOffY)
|
App.fontGame.draw(batch, message, 1f + drawOffX, (LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT - i)).toFloat() + drawOffY + inputToMsgboxGap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uiItems.forEach { it.render(batch, camera) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun inputStrobed(e: TerrarumKeyboardEvent) {
|
||||||
|
uiItems.forEach { it.inputStrobed(e) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun keyDown(key: Int): Boolean {
|
override fun keyDown(key: Int): Boolean {
|
||||||
// history
|
try {
|
||||||
if (key == Input.Keys.UP && historyIndex < commandHistory.elemCount)
|
val textOnBuffer = textinput.getText()
|
||||||
historyIndex++
|
|
||||||
else if (key == Input.Keys.DOWN && historyIndex >= 0)
|
|
||||||
historyIndex--
|
|
||||||
else if (key != Input.Keys.UP && key != Input.Keys.DOWN)
|
|
||||||
historyIndex = -1
|
|
||||||
|
|
||||||
// execute
|
// history
|
||||||
if (key == Input.Keys.ENTER && commandInputPool!!.isNotEmpty()) {
|
if (key == Input.Keys.UP && historyIndex < commandHistory.elemCount)
|
||||||
commandHistory.appendHead(commandInputPool!!.toString())
|
historyIndex++
|
||||||
executeCommand()
|
else if (key == Input.Keys.DOWN && historyIndex >= 0)
|
||||||
commandInputPool = StringBuilder()
|
historyIndex--
|
||||||
|
else if (key != Input.Keys.UP && key != Input.Keys.DOWN)
|
||||||
|
historyIndex = -1
|
||||||
|
|
||||||
|
// execute
|
||||||
|
if (key == Input.Keys.ENTER && textOnBuffer.isNotEmpty()) {
|
||||||
|
commandHistory.appendHead(textOnBuffer)
|
||||||
|
executeCommand(textOnBuffer)
|
||||||
|
textinput.clearText()
|
||||||
|
}
|
||||||
|
// scroll
|
||||||
|
else if (key == Input.Keys.UP || key == Input.Keys.DOWN) {
|
||||||
|
// create new stringbuilder
|
||||||
|
textinput.clearText()
|
||||||
|
if (historyIndex >= 0) // just leave blank if index is -1
|
||||||
|
textinput.setText(commandHistory[historyIndex] ?: "")
|
||||||
|
}
|
||||||
|
// delete input
|
||||||
|
// else if (key == Input.Keys.BACKSPACE) {
|
||||||
|
// commandInputPool = StringBuilder()
|
||||||
|
// }
|
||||||
|
// message scroll up
|
||||||
|
else if (key == Input.Keys.PAGE_UP) {
|
||||||
|
setDisplayPos(-MESSAGES_DISPLAY_COUNT + 1)
|
||||||
|
}
|
||||||
|
// message scroll down
|
||||||
|
else if (key == Input.Keys.PAGE_DOWN) {
|
||||||
|
setDisplayPos(MESSAGES_DISPLAY_COUNT - 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// erase last letter
|
catch (e: ConcurrentModificationException) {
|
||||||
else if (key == Input.Keys.BACKSPACE && commandInputPool!!.isNotEmpty()) {
|
System.err.println("[ConsoleWindow] ConcurrentModificationException")
|
||||||
commandInputPool!!.deleteCharAt(commandInputPool!!.length - 1)
|
|
||||||
}
|
|
||||||
// scroll
|
|
||||||
else if (key == Input.Keys.UP || key == Input.Keys.DOWN) {
|
|
||||||
// create new stringbuilder
|
|
||||||
commandInputPool = StringBuilder()
|
|
||||||
if (historyIndex >= 0) // just leave blank if index is -1
|
|
||||||
commandInputPool!!.append(commandHistory[historyIndex])
|
|
||||||
}
|
|
||||||
// delete input
|
|
||||||
else if (key == Input.Keys.BACKSPACE) {
|
|
||||||
commandInputPool = StringBuilder()
|
|
||||||
}
|
|
||||||
// message scroll up
|
|
||||||
else if (key == Input.Keys.PAGE_UP) {
|
|
||||||
setDisplayPos(-MESSAGES_DISPLAY_COUNT + 1)
|
|
||||||
}
|
|
||||||
// message scroll down
|
|
||||||
else if (key == Input.Keys.PAGE_DOWN) {
|
|
||||||
setDisplayPos(MESSAGES_DISPLAY_COUNT - 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -148,7 +167,7 @@ class ConsoleWindow : UICanvas() {
|
|||||||
|
|
||||||
val acceptedChars = "1234567890-=qwfpgjluy;[]\\arstdhneio'zxcvbkm,./!@#$%^&*()_+QWFPGJLUY:{}|ARSTDHNEIO\"ZXCVBKM<>? ".toSet()
|
val acceptedChars = "1234567890-=qwfpgjluy;[]\\arstdhneio'zxcvbkm,./!@#$%^&*()_+QWFPGJLUY:{}|ARSTDHNEIO\"ZXCVBKM<>? ".toSet()
|
||||||
|
|
||||||
override fun keyTyped(character: Char): Boolean {
|
/*override fun keyTyped(character: Char): Boolean {
|
||||||
if (character in acceptedChars) {
|
if (character in acceptedChars) {
|
||||||
commandInputPool!!.append(character)
|
commandInputPool!!.append(character)
|
||||||
inputCursorPos += 1
|
inputCursorPos += 1
|
||||||
@@ -158,14 +177,14 @@ class ConsoleWindow : UICanvas() {
|
|||||||
else {
|
else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
override fun keyUp(keycode: Int): Boolean {
|
override fun keyUp(keycode: Int): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun executeCommand() {
|
private fun executeCommand(s: String) {
|
||||||
CommandInterpreter.execute(commandInputPool!!.toString())
|
CommandInterpreter.execute(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMessage(msg: String) {
|
fun sendMessage(msg: String) {
|
||||||
@@ -200,7 +219,7 @@ class ConsoleWindow : UICanvas() {
|
|||||||
messagesCount = 0
|
messagesCount = 0
|
||||||
inputCursorPos = 0
|
inputCursorPos = 0
|
||||||
commandHistory = CircularArray<String>(COMMAND_HISTORY_MAX, true)
|
commandHistory = CircularArray<String>(COMMAND_HISTORY_MAX, true)
|
||||||
commandInputPool = StringBuilder()
|
textinput.clearText()
|
||||||
|
|
||||||
if (Authenticator.b()) {
|
if (Authenticator.b()) {
|
||||||
sendMessage("$ccE${TerrarumAppConfiguration.GAME_NAME} ${App.getVERSION_STRING()} $EMDASH ${TerrarumAppConfiguration.COPYRIGHT_DATE_NAME}")
|
sendMessage("$ccE${TerrarumAppConfiguration.GAME_NAME} ${App.getVERSION_STRING()} $EMDASH ${TerrarumAppConfiguration.COPYRIGHT_DATE_NAME}")
|
||||||
@@ -232,11 +251,13 @@ class ConsoleWindow : UICanvas() {
|
|||||||
drawOffY = MovementInterpolator.fastPullOut(openingTimeCounter.toFloat() / openCloseTime.toFloat(),
|
drawOffY = MovementInterpolator.fastPullOut(openingTimeCounter.toFloat() / openCloseTime.toFloat(),
|
||||||
0f, -height.toFloat()
|
0f, -height.toFloat()
|
||||||
)*/
|
)*/
|
||||||
|
textinput.isActive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun endOpening(delta: Float) {
|
override fun endOpening(delta: Float) {
|
||||||
drawOffY = 0f
|
drawOffY = 0f
|
||||||
openingTimeCounter = 0f
|
openingTimeCounter = 0f
|
||||||
|
textinput.isActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun endClosing(delta: Float) {
|
override fun endClosing(delta: Float) {
|
||||||
@@ -252,5 +273,6 @@ class ConsoleWindow : UICanvas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
|
uiItems.forEach { it.dispose() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.printdbg
|
|
||||||
import net.torvald.terrarum.gamecontroller.*
|
import net.torvald.terrarum.gamecontroller.*
|
||||||
import net.torvald.terrarum.utils.Clipboard
|
import net.torvald.terrarum.utils.Clipboard
|
||||||
import net.torvald.terrarumsansbitmap.gdx.CodepointSequence
|
import net.torvald.terrarumsansbitmap.gdx.CodepointSequence
|
||||||
@@ -44,7 +43,8 @@ data class InputLenCap(val count: Int, val unit: CharLenUnit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make sure `inputStrobed()` of the parentUI is up and running.
|
* UIItemTextLineInput does not require any GDX's input event handlers, but it does require InputStrober
|
||||||
|
* to be running and `inputStrobed()` of the parentUI is calling the same method on this.
|
||||||
*
|
*
|
||||||
* Protip: if there are multiple TextLineInputs on a same UI, draw bottom one first, otherwise the IME's
|
* Protip: if there are multiple TextLineInputs on a same UI, draw bottom one first, otherwise the IME's
|
||||||
* candidate window will be hidden by the bottom UIItem if they overlaps.
|
* candidate window will be hidden by the bottom UIItem if they overlaps.
|
||||||
@@ -126,7 +126,7 @@ class UIItemTextLineInput(
|
|||||||
private val candidatesBackCol = TEXTINPUT_COL_BACKGROUND.cpy().mul(1f,1f,1f,1.5f)
|
private val candidatesBackCol = TEXTINPUT_COL_BACKGROUND.cpy().mul(1f,1f,1f,1.5f)
|
||||||
private val candidateNumberStrWidth = App.fontGame.getWidth("8. ")
|
private val candidateNumberStrWidth = App.fontGame.getWidth("8. ")
|
||||||
|
|
||||||
private fun getIME(): TerrarumInputMethod? {
|
private fun getIME(): TerrarumIME? {
|
||||||
if (!imeOn) return null
|
if (!imeOn) return null
|
||||||
|
|
||||||
val selectedIME = App.getConfigString("inputmethod")
|
val selectedIME = App.getConfigString("inputmethod")
|
||||||
@@ -165,100 +165,105 @@ class UIItemTextLineInput(
|
|||||||
|
|
||||||
val (eventType, char, headkey, repeatCount, keycodes) = e
|
val (eventType, char, headkey, repeatCount, keycodes) = e
|
||||||
|
|
||||||
if (eventType == InputStrober.KEY_DOWN || eventType == InputStrober.KEY_CHANGE) {
|
try {
|
||||||
fboUpdateLatch = true
|
if (eventType == InputStrober.KEY_DOWN || eventType == InputStrober.KEY_CHANGE) {
|
||||||
forceLitCursor()
|
fboUpdateLatch = true
|
||||||
val ime = getIME()
|
forceLitCursor()
|
||||||
|
val ime = getIME()
|
||||||
|
|
||||||
if (keycodes.contains(App.getConfigInt("control_key_toggleime")) && repeatCount == 1) {
|
if (keycodes.contains(App.getConfigInt("control_key_toggleime")) && repeatCount == 1) {
|
||||||
toggleIME()
|
toggleIME()
|
||||||
}
|
|
||||||
else if (keycodes.contains(Input.Keys.V) && (keycodes.contains(Input.Keys.CONTROL_LEFT) || keycodes.contains(Input.Keys.CONTROL_RIGHT))) {
|
|
||||||
endComposing()
|
|
||||||
paste(Clipboard.fetch().substringBefore('\n').substringBefore('\t').toCodePoints())
|
|
||||||
}
|
|
||||||
else if (keycodes.contains(Input.Keys.C) && (keycodes.contains(Input.Keys.CONTROL_LEFT) || keycodes.contains(Input.Keys.CONTROL_RIGHT))) {
|
|
||||||
endComposing()
|
|
||||||
copyToClipboard()
|
|
||||||
}
|
|
||||||
else if (keycodes.contains(Input.Keys.BACKSPACE)) {
|
|
||||||
if (ime != null && ime.composing()) {
|
|
||||||
candidates = ime.backspace().map { CodepointSequence(it.toCodePoints()) }
|
|
||||||
}
|
}
|
||||||
else if (cursorX <= 0) {
|
else if (keycodes.contains(Input.Keys.V) && (keycodes.contains(Input.Keys.CONTROL_LEFT) || keycodes.contains(Input.Keys.CONTROL_RIGHT))) {
|
||||||
cursorX = 0
|
|
||||||
cursorDrawX = 0
|
|
||||||
cursorDrawScroll = 0
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
endComposing()
|
endComposing()
|
||||||
if (cursorX > 0) {
|
paste(Clipboard.fetch().substringBefore('\n').substringBefore('\t').toCodePoints())
|
||||||
while (true) {
|
|
||||||
cursorX -= 1
|
|
||||||
val oldCode = textbuf.removeAt(cursorX)
|
|
||||||
// continue deleting hangul pieces because of the font...
|
|
||||||
if (cursorX == 0 || (oldCode !in 0x115F..0x11FF && oldCode !in 0xD7B0..0xD7FF)) break
|
|
||||||
}
|
|
||||||
|
|
||||||
cursorDrawX = App.fontGame.getWidth(CodepointSequence(textbuf.subList(0, cursorX)))
|
|
||||||
tryCursorForward()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else if (keycodes.contains(Input.Keys.C) && (keycodes.contains(Input.Keys.CONTROL_LEFT) || keycodes.contains(Input.Keys.CONTROL_RIGHT))) {
|
||||||
else if (keycodes.contains(Input.Keys.LEFT)) {
|
endComposing()
|
||||||
endComposing()
|
copyToClipboard()
|
||||||
|
}
|
||||||
if (cursorX > 0) {
|
else if (keycodes.contains(Input.Keys.BACKSPACE)) {
|
||||||
cursorX -= 1
|
if (ime != null && ime.composing()) {
|
||||||
cursorDrawX = App.fontGame.getWidth(CodepointSequence(textbuf.subList(0, cursorX)))
|
candidates = ime.backspace().map { CodepointSequence(it.toCodePoints()) }
|
||||||
tryCursorForward()
|
}
|
||||||
if (cursorX <= 0) {
|
else if (cursorX <= 0) {
|
||||||
cursorX = 0
|
cursorX = 0
|
||||||
cursorDrawX = 0
|
cursorDrawX = 0
|
||||||
cursorDrawScroll = 0
|
cursorDrawScroll = 0
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
}
|
endComposing()
|
||||||
else if (keycodes.contains(Input.Keys.RIGHT)) {
|
if (cursorX > 0) {
|
||||||
endComposing()
|
while (true) {
|
||||||
|
cursorX -= 1
|
||||||
|
val oldCode = textbuf.removeAt(cursorX)
|
||||||
|
// continue deleting hangul pieces because of the font...
|
||||||
|
if (cursorX == 0 || (oldCode !in 0x115F..0x11FF && oldCode !in 0xD7B0..0xD7FF)) break
|
||||||
|
}
|
||||||
|
|
||||||
if (cursorX < textbuf.size) {
|
cursorDrawX = App.fontGame.getWidth(CodepointSequence(textbuf.subList(0, cursorX)))
|
||||||
cursorX += 1
|
tryCursorForward()
|
||||||
cursorDrawX = App.fontGame.getWidth(CodepointSequence(textbuf.subList(0, cursorX)))
|
}
|
||||||
tryCursorBack()
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (keycodes.contains(Input.Keys.LEFT)) {
|
||||||
// accept:
|
endComposing()
|
||||||
// - literal "<"
|
|
||||||
// - keysymbol that does not start with "<" (not always has length of 1 because UTF-16)
|
|
||||||
else if (char != null && char.length > 0 && char[0].code >= 32 && (char == "<" || !char.startsWith("<"))) {
|
|
||||||
val shiftin = keycodes.contains(Input.Keys.SHIFT_LEFT) || keycodes.contains(Input.Keys.SHIFT_RIGHT)
|
|
||||||
val altgrin = keycodes.contains(Input.Keys.ALT_RIGHT)
|
|
||||||
|
|
||||||
val codepoints = if (ime != null) {
|
if (cursorX > 0) {
|
||||||
val newStatus = ime.acceptChar(headkey, shiftin, altgrin, char)
|
cursorX -= 1
|
||||||
candidates = newStatus.first.map { CodepointSequence(it.toCodePoints()) }
|
cursorDrawX = App.fontGame.getWidth(CodepointSequence(textbuf.subList(0, cursorX)))
|
||||||
|
tryCursorForward()
|
||||||
newStatus.second.toCodePoints()
|
if (cursorX <= 0) {
|
||||||
|
cursorX = 0
|
||||||
|
cursorDrawX = 0
|
||||||
|
cursorDrawScroll = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else char.toCodePoints()
|
else if (keycodes.contains(Input.Keys.RIGHT)) {
|
||||||
|
endComposing()
|
||||||
|
|
||||||
|
if (cursorX < textbuf.size) {
|
||||||
|
cursorX += 1
|
||||||
|
cursorDrawX = App.fontGame.getWidth(CodepointSequence(textbuf.subList(0, cursorX)))
|
||||||
|
tryCursorBack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// accept:
|
||||||
|
// - literal "<"
|
||||||
|
// - keysymbol that does not start with "<" (not always has length of 1 because UTF-16)
|
||||||
|
else if (char != null && char.length > 0 && char[0].code >= 32 && (char == "<" || !char.startsWith("<"))) {
|
||||||
|
val shiftin = keycodes.contains(Input.Keys.SHIFT_LEFT) || keycodes.contains(Input.Keys.SHIFT_RIGHT)
|
||||||
|
val altgrin = keycodes.contains(Input.Keys.ALT_RIGHT)
|
||||||
|
|
||||||
|
val codepoints = if (ime != null) {
|
||||||
|
val newStatus = ime.acceptChar(headkey, shiftin, altgrin, char)
|
||||||
|
candidates = newStatus.first.map { CodepointSequence(it.toCodePoints()) }
|
||||||
|
|
||||||
|
newStatus.second.toCodePoints()
|
||||||
|
}
|
||||||
|
else char.toCodePoints()
|
||||||
|
|
||||||
// println("textinput codepoints: ${codepoints.map { it.toString(16) }.joinToString()}")
|
// println("textinput codepoints: ${codepoints.map { it.toString(16) }.joinToString()}")
|
||||||
|
|
||||||
if (!maxLen.exceeds(textbuf, codepoints)) {
|
if (!maxLen.exceeds(textbuf, codepoints)) {
|
||||||
textbuf.addAll(cursorX, codepoints)
|
textbuf.addAll(cursorX, codepoints)
|
||||||
|
|
||||||
cursorX += codepoints.size
|
cursorX += codepoints.size
|
||||||
cursorDrawX = App.fontGame.getWidth(CodepointSequence(textbuf.subList(0, cursorX)))
|
cursorDrawX = App.fontGame.getWidth(CodepointSequence(textbuf.subList(0, cursorX)))
|
||||||
|
|
||||||
tryCursorBack()
|
tryCursorBack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (keycodes.contains(Input.Keys.ENTER) || keycodes.contains(Input.Keys.NUMPAD_ENTER)) {
|
||||||
|
endComposing()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (keycodes.contains(Input.Keys.ENTER) || keycodes.contains(Input.Keys.NUMPAD_ENTER)) {
|
|
||||||
endComposing()
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't put innards of tryCursorBack/Forward here -- you absolutely don't want that behaviour
|
// don't put innards of tryCursorBack/Forward here -- you absolutely don't want that behaviour
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e: NullPointerException) {
|
||||||
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textbuf.size == 0) {
|
if (textbuf.size == 0) {
|
||||||
@@ -454,7 +459,7 @@ class UIItemTextLineInput(
|
|||||||
// draw candidates view
|
// draw candidates view
|
||||||
if (candidates.isNotEmpty()) {
|
if (candidates.isNotEmpty()) {
|
||||||
val textWidths = candidates.map { App.fontGame.getWidth(CodepointSequence(it)) }
|
val textWidths = candidates.map { App.fontGame.getWidth(CodepointSequence(it)) }
|
||||||
val candidatesMax = getIME()!!.maxCandidates()
|
val candidatesMax = getIME()!!.config.candidates.toInt()
|
||||||
val candidatesCount = minOf(candidatesMax, candidates.size)
|
val candidatesCount = minOf(candidatesMax, candidates.size)
|
||||||
val isOnecolumn = (candidatesCount <= 3)
|
val isOnecolumn = (candidatesCount <= 3)
|
||||||
val halfcount = if (isOnecolumn) candidatesCount else FastMath.ceil(candidatesCount / 2f)
|
val halfcount = if (isOnecolumn) candidatesCount else FastMath.ceil(candidatesCount / 2f)
|
||||||
@@ -510,6 +515,17 @@ class UIItemTextLineInput(
|
|||||||
|
|
||||||
fun getText() = textbufToString()
|
fun getText() = textbufToString()
|
||||||
fun getTextOrPlaceholder(): String = if (textbuf.isEmpty()) currentPlaceholderText.toJavaString() else getText()
|
fun getTextOrPlaceholder(): String = if (textbuf.isEmpty()) currentPlaceholderText.toJavaString() else getText()
|
||||||
|
fun clearText() {
|
||||||
|
resetIME()
|
||||||
|
textbuf.clear()
|
||||||
|
cursorX = 0
|
||||||
|
cursorDrawScroll = 0
|
||||||
|
cursorDrawX = 0
|
||||||
|
}
|
||||||
|
fun setText(s: String) {
|
||||||
|
clearText()
|
||||||
|
textbuf.addAll(s.toCodePoints())
|
||||||
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
fbo.dispose()
|
fbo.dispose()
|
||||||
|
|||||||
Reference in New Issue
Block a user