acceptsCharacter, support text padding in text input
This commit is contained in:
parent
03927bfc72
commit
f76fe4add6
@ -22,6 +22,7 @@ import ru.dbotthepony.mc.otm.client.render.TextAlign
|
||||
import ru.dbotthepony.mc.otm.client.render.drawAligned
|
||||
import ru.dbotthepony.mc.otm.client.render.drawRect
|
||||
import ru.dbotthepony.mc.otm.client.render.tesselator
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.DockProperty
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.core.addAll
|
||||
import ru.dbotthepony.mc.otm.core.math.RGBAColor
|
||||
@ -144,6 +145,11 @@ open class TextInputPanel<out S : Screen>(
|
||||
open var backgroundColor = RGBAColor.BLACK
|
||||
open var isActive = true
|
||||
|
||||
init {
|
||||
scissor = true
|
||||
dockPadding = DockProperty(2f, 2f, 2f, 2f)
|
||||
}
|
||||
|
||||
private var oldText = ArrayList<String>()
|
||||
private var textCache: String? = null
|
||||
private val lines = ArrayList<String>()
|
||||
@ -968,12 +974,21 @@ open class TextInputPanel<out S : Screen>(
|
||||
return true
|
||||
}
|
||||
|
||||
open fun acceptsCharacter(codepoint: Char, mods: Int = 0): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun charTypedInternal(codepoint: Char, mods: Int): Boolean {
|
||||
if (!isActive) {
|
||||
killFocus()
|
||||
return true
|
||||
}
|
||||
|
||||
if (!acceptsCharacter(codepoint, mods)) {
|
||||
playGuiClickSound()
|
||||
return true
|
||||
}
|
||||
|
||||
wipeSelection()
|
||||
|
||||
if (!multiLine)
|
||||
@ -1003,9 +1018,10 @@ open class TextInputPanel<out S : Screen>(
|
||||
}
|
||||
|
||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||
drawRect(stack, 0f, 0f, width, height, backgroundColor)
|
||||
if (!backgroundColor.isFullyTransparent)
|
||||
drawRect(stack, 0f, 0f, width, height, backgroundColor)
|
||||
|
||||
var y = 0f
|
||||
var y = dockPadding.top
|
||||
|
||||
for ((i, line) in lines.withIndex()) {
|
||||
val selection = selections[i]
|
||||
@ -1015,7 +1031,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
buffer = BUFFER,
|
||||
text = line,
|
||||
align = TextAlign.TOP_LEFT,
|
||||
x = 0f,
|
||||
x = dockPadding.left,
|
||||
y = y,
|
||||
color = textColor
|
||||
)
|
||||
@ -1023,10 +1039,10 @@ open class TextInputPanel<out S : Screen>(
|
||||
if (selection != null && selection.isValid) {
|
||||
val (before, selected) = selection.sub(line)
|
||||
|
||||
var x = 0f
|
||||
var x = dockPadding.left
|
||||
|
||||
if (before.isNotEmpty()) {
|
||||
x = font.width(before).toFloat()
|
||||
x += font.width(before).toFloat()
|
||||
}
|
||||
|
||||
val width = if (selection.coversNewline(line) && i != lines.size - 1) this.width - x else font.width(selected).toFloat()
|
||||
@ -1057,6 +1073,9 @@ open class TextInputPanel<out S : Screen>(
|
||||
}
|
||||
|
||||
y += font.lineHeight + 2f
|
||||
|
||||
if (y > height - dockPadding.bottom)
|
||||
break
|
||||
}
|
||||
|
||||
if (isFocused && milliTime % 1000L > 500L) {
|
||||
@ -1068,8 +1087,8 @@ open class TextInputPanel<out S : Screen>(
|
||||
buffer = BUFFER,
|
||||
text = "_",
|
||||
align = TextAlign.TOP_LEFT,
|
||||
x = if (activeLine == null) 0f else font.width(activeLine).toFloat(),
|
||||
y = cursorLine * (font.lineHeight + 2f),
|
||||
x = dockPadding.left + (if (activeLine == null) 0f else font.width(activeLine).toFloat()),
|
||||
y = dockPadding.top + cursorLine * (font.lineHeight + 2f),
|
||||
color = cursorColor
|
||||
)
|
||||
} else {
|
||||
@ -1078,8 +1097,8 @@ open class TextInputPanel<out S : Screen>(
|
||||
buffer = BUFFER,
|
||||
text = "|",
|
||||
align = TextAlign.TOP_LEFT,
|
||||
x = font.width(activeLine.substring(0, cursorCharacter)).toFloat() - 1f,
|
||||
y = cursorLine * (font.lineHeight + 2f),
|
||||
x = dockPadding.left + font.width(activeLine.substring(0, cursorCharacter)).toFloat() - 1f,
|
||||
y = dockPadding.top + cursorLine * (font.lineHeight + 2f),
|
||||
color = cursorColor
|
||||
)
|
||||
}
|
||||
@ -1092,7 +1111,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
text = cursorLine.toString(),
|
||||
align = TextAlign.TOP_RIGHT,
|
||||
x = width,
|
||||
y = 0f,
|
||||
y = dockPadding.top,
|
||||
color = cursorColor
|
||||
)
|
||||
|
||||
@ -1101,8 +1120,8 @@ open class TextInputPanel<out S : Screen>(
|
||||
buffer = BUFFER,
|
||||
text = cursorCharacter.toString(),
|
||||
align = TextAlign.TOP_RIGHT,
|
||||
x = width,
|
||||
y = font.lineHeight + 2f,
|
||||
x = width - dockPadding.right,
|
||||
y = dockPadding.top + font.lineHeight + 2f,
|
||||
color = cursorColor
|
||||
)
|
||||
|
||||
@ -1111,8 +1130,8 @@ open class TextInputPanel<out S : Screen>(
|
||||
buffer = BUFFER,
|
||||
text = lines.size.toString(),
|
||||
align = TextAlign.TOP_RIGHT,
|
||||
x = width,
|
||||
y = font.lineHeight * 2 + 4f,
|
||||
x = width - dockPadding.right,
|
||||
y = dockPadding.top + font.lineHeight * 2 + 4f,
|
||||
color = cursorColor
|
||||
)
|
||||
}
|
||||
@ -1142,10 +1161,20 @@ open class TextInputPanel<out S : Screen>(
|
||||
return true
|
||||
}
|
||||
|
||||
@Suppress("name_shadowing")
|
||||
fun localToText(x: Float, y: Float): Vector2i {
|
||||
if (lines.isEmpty())
|
||||
return Vector2i(0, 0)
|
||||
|
||||
var x = x - dockPadding.left
|
||||
var y = y - dockPadding.top
|
||||
|
||||
if (y > height - dockPadding.bottom)
|
||||
y = height - dockPadding.bottom
|
||||
|
||||
if (x > width - dockPadding.right)
|
||||
x = width - dockPadding.right
|
||||
|
||||
val line = (y / (font.lineHeight + 2f)).toInt().coerceIn(0, lines.size - 1)
|
||||
val sLine = this[line] ?: return Vector2i(0, line)
|
||||
|
||||
@ -1154,29 +1183,6 @@ open class TextInputPanel<out S : Screen>(
|
||||
else if (x >= font.width(sLine))
|
||||
return Vector2i(sLine.length, line)
|
||||
|
||||
// binary search attempt
|
||||
// simply: sucks
|
||||
/*@Suppress("name_shadowing")
|
||||
var x = x
|
||||
var start = 0
|
||||
var end = sLine.length - 1
|
||||
|
||||
while (start < end - 1) {
|
||||
val split = (end - start) / 2
|
||||
val before = font.width(sLine.substring(start, start + split))
|
||||
|
||||
if (x < before) {
|
||||
end = start + split
|
||||
} else if (x > before) {
|
||||
x -= before
|
||||
start += split
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return Vector2i(start, line)*/
|
||||
|
||||
val cache = Char2IntOpenHashMap()
|
||||
var accumulatedWidth = 0f
|
||||
|
||||
|
@ -76,33 +76,38 @@ data class RGBAColor(val red: Float, val green: Float, val blue: Float, val alph
|
||||
)
|
||||
}
|
||||
|
||||
val isFullyTransparent get() = alpha <= 0f
|
||||
|
||||
companion object {
|
||||
val BLACK = RGBAColor(0f, 0f, 0f, 1f)
|
||||
val WHITE = RGBAColor(1f, 1f, 1f, 1f)
|
||||
val RED = RGBAColor(1f, 0f, 0f)
|
||||
val GREEN = RGBAColor(0f, 1f, 0f, 1f)
|
||||
val LIGHT_GREEN = RGBAColor(136, 255, 124)
|
||||
val SLATE_GRAY = RGBAColor(64, 64, 64)
|
||||
val GRAY = RGBAColor(0x2C2C2CFFL)
|
||||
@JvmField val TRANSPARENT_BLACK = RGBAColor(0f, 0f, 0f, 0f)
|
||||
@JvmField val TRANSPARENT_WHITE = RGBAColor(1f, 1f, 1f, 0f)
|
||||
|
||||
val DARK_BLUE = rgb(ChatFormatting.DARK_BLUE.color!!)
|
||||
val DARK_GREEN = rgb(ChatFormatting.DARK_GREEN.color!!)
|
||||
val DARK_AQUA = rgb(ChatFormatting.DARK_AQUA.color!!)
|
||||
val DARK_RED = rgb(ChatFormatting.DARK_RED.color!!)
|
||||
val DARK_PURPLE = rgb(ChatFormatting.DARK_PURPLE.color!!)
|
||||
val GOLD = rgb(ChatFormatting.GOLD.color!!)
|
||||
val DARK_GRAY = rgb(ChatFormatting.DARK_GRAY.color!!)
|
||||
val BLUE = rgb(ChatFormatting.BLUE.color!!)
|
||||
val AQUA = rgb(ChatFormatting.AQUA.color!!)
|
||||
val LIGHT_PURPLE = rgb(ChatFormatting.LIGHT_PURPLE.color!!)
|
||||
val YELLOW = rgb(ChatFormatting.YELLOW.color!!)
|
||||
@JvmField val BLACK = RGBAColor(0f, 0f, 0f, 1f)
|
||||
@JvmField val WHITE = RGBAColor(1f, 1f, 1f, 1f)
|
||||
@JvmField val RED = RGBAColor(1f, 0f, 0f)
|
||||
@JvmField val GREEN = RGBAColor(0f, 1f, 0f, 1f)
|
||||
@JvmField val LIGHT_GREEN = RGBAColor(136, 255, 124)
|
||||
@JvmField val SLATE_GRAY = RGBAColor(64, 64, 64)
|
||||
@JvmField val GRAY = RGBAColor(0x2C2C2CFFL)
|
||||
|
||||
val LOW_POWER = RGBAColor(173, 41, 41)
|
||||
val FULL_POWER = RGBAColor(255, 242, 40)
|
||||
val LOW_MATTER = RGBAColor(0, 24, 148)
|
||||
val FULL_MATTER = RGBAColor(72, 90, 255)
|
||||
val LOW_PATTERNS = RGBAColor(44, 104, 57)
|
||||
val FULL_PATTERNS = RGBAColor(65, 255, 87)
|
||||
@JvmField val DARK_BLUE = rgb(ChatFormatting.DARK_BLUE.color!!)
|
||||
@JvmField val DARK_GREEN = rgb(ChatFormatting.DARK_GREEN.color!!)
|
||||
@JvmField val DARK_AQUA = rgb(ChatFormatting.DARK_AQUA.color!!)
|
||||
@JvmField val DARK_RED = rgb(ChatFormatting.DARK_RED.color!!)
|
||||
@JvmField val DARK_PURPLE = rgb(ChatFormatting.DARK_PURPLE.color!!)
|
||||
@JvmField val GOLD = rgb(ChatFormatting.GOLD.color!!)
|
||||
@JvmField val DARK_GRAY = rgb(ChatFormatting.DARK_GRAY.color!!)
|
||||
@JvmField val BLUE = rgb(ChatFormatting.BLUE.color!!)
|
||||
@JvmField val AQUA = rgb(ChatFormatting.AQUA.color!!)
|
||||
@JvmField val LIGHT_PURPLE = rgb(ChatFormatting.LIGHT_PURPLE.color!!)
|
||||
@JvmField val YELLOW = rgb(ChatFormatting.YELLOW.color!!)
|
||||
|
||||
@JvmField val LOW_POWER = RGBAColor(173, 41, 41)
|
||||
@JvmField val FULL_POWER = RGBAColor(255, 242, 40)
|
||||
@JvmField val LOW_MATTER = RGBAColor(0, 24, 148)
|
||||
@JvmField val FULL_MATTER = RGBAColor(72, 90, 255)
|
||||
@JvmField val LOW_PATTERNS = RGBAColor(44, 104, 57)
|
||||
@JvmField val FULL_PATTERNS = RGBAColor(65, 255, 87)
|
||||
|
||||
fun inv(color: Int): RGBAColor {
|
||||
val r = (color and -0x1000000 ushr 24) / 255f
|
||||
|
Loading…
Reference in New Issue
Block a user