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.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexFormat 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.chars.CharOpenHashSet
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectMap import it.unimi.dsi.fastutil.ints.Int2ObjectMap
import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.renderer.GameRenderer import net.minecraft.client.renderer.GameRenderer
import org.joml.Vector2i
import ru.dbotthepony.mc.otm.client.isCtrlDown import ru.dbotthepony.mc.otm.client.isCtrlDown
import ru.dbotthepony.mc.otm.client.isKeyDown import ru.dbotthepony.mc.otm.client.isKeyDown
import ru.dbotthepony.mc.otm.client.isShiftDown 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 { override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
selections.clear() selections.clear()
requestFocus() requestFocus()
val (lx, ly) = screenToLocal(x, y)
val pos = localToText(lx, ly)
cursorLine = pos.y
cursorCharacter = pos.x
return true 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 { private enum class CharType {
SPACES { SPACES {
override fun contains(input: Char): Boolean { override fun contains(input: Char): Boolean {