Moving text cursor using mice

This commit is contained in:
DBotThePony 2023-01-26 15:21:34 +07:00
parent 962ac1d6b7
commit b6d5cc4024
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -6,11 +6,15 @@ import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexFormat
import it.unimi.dsi.fastutil.chars.Char2IntAVLTreeMap
import it.unimi.dsi.fastutil.chars.Char2IntFunction
import it.unimi.dsi.fastutil.chars.Char2IntOpenHashMap
import it.unimi.dsi.fastutil.chars.CharOpenHashSet
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectMap
import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.renderer.GameRenderer
import org.joml.Vector2i
import ru.dbotthepony.mc.otm.client.isCtrlDown
import ru.dbotthepony.mc.otm.client.isKeyDown
import ru.dbotthepony.mc.otm.client.isShiftDown
@ -929,9 +933,69 @@ open class TextInputPanel<out S : Screen>(
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
selections.clear()
requestFocus()
val (lx, ly) = screenToLocal(x, y)
val pos = localToText(lx, ly)
cursorLine = pos.y
cursorCharacter = pos.x
return true
}
fun localToText(x: Float, y: Float): Vector2i {
if (lines.isEmpty())
return Vector2i(0, 0)
val line = (y / (font.lineHeight + 2f)).toInt().coerceIn(0, lines.size - 1)
val sLine = this[line] ?: return Vector2i(0, line)
if (x <= 0f)
return Vector2i(0, line)
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
for ((i, char) in sLine.withIndex()) {
val width = cache.computeIfAbsent(char, Char2IntFunction { font.width(it.toString()) })
if (x in accumulatedWidth .. accumulatedWidth + width) {
if (x - accumulatedWidth < width / 2)
return Vector2i(i, line)
else
return Vector2i(i + 1, line)
} else {
accumulatedWidth += width
}
}
return Vector2i(sLine.length, line)
}
private enum class CharType {
SPACES {
override fun contains(input: Char): Boolean {