2023-11-28 00:46:05 +02:00
|
|
|
extends RefCounted
|
2023-11-23 19:26:09 +02:00
|
|
|
|
2024-03-15 19:27:03 +02:00
|
|
|
const FontTools = preload ("res://lib/utils/font_tools.gd")
|
|
|
|
|
2023-11-23 19:26:09 +02:00
|
|
|
var label: Label3D
|
|
|
|
|
|
|
|
var text: String = ""
|
2024-04-23 23:11:18 +03:00
|
|
|
var width: float = 0.2:
|
|
|
|
set(value):
|
|
|
|
width = max(0.0, value)
|
|
|
|
gap_offsets = _calculate_text_gaps()
|
|
|
|
overflow_index = _calculate_overflow_index()
|
|
|
|
caret_position = 0
|
2023-11-23 19:26:09 +02:00
|
|
|
var gap_offsets = null
|
|
|
|
var overflow_index: int = -1
|
|
|
|
var char_offset: int = 0
|
|
|
|
var caret_position: int = 3:
|
|
|
|
set(value):
|
|
|
|
caret_position = clampi(value, 0, text.length())
|
|
|
|
|
2024-03-07 16:49:33 +02:00
|
|
|
func set_text(value: String, insert: bool=false):
|
2023-11-23 19:26:09 +02:00
|
|
|
var old_text = text
|
|
|
|
text = value
|
|
|
|
|
|
|
|
if label == null:
|
|
|
|
return
|
|
|
|
|
|
|
|
gap_offsets = _calculate_text_gaps()
|
|
|
|
if insert == false:
|
2024-03-07 16:49:33 +02:00
|
|
|
var text_diff = text.length() - old_text.length()
|
|
|
|
caret_position += text_diff
|
|
|
|
if text_diff < 0:
|
|
|
|
char_offset = max(0, char_offset + text_diff)
|
2023-11-23 19:26:09 +02:00
|
|
|
else:
|
|
|
|
caret_position = 0
|
|
|
|
|
|
|
|
overflow_index = _calculate_overflow_index()
|
|
|
|
focus_caret()
|
|
|
|
|
|
|
|
func get_display_text():
|
|
|
|
# In case all chars fit, return the whole text.
|
2024-03-07 16:49:33 +02:00
|
|
|
if overflow_index == - 1:
|
2023-11-23 19:26:09 +02:00
|
|
|
return text.substr(char_offset)
|
|
|
|
return text.substr(char_offset, overflow_index - char_offset)
|
|
|
|
|
|
|
|
func focus_caret():
|
2024-03-07 16:49:33 +02:00
|
|
|
if overflow_index == - 1:
|
2023-11-23 19:26:09 +02:00
|
|
|
char_offset = 0
|
|
|
|
return
|
|
|
|
|
|
|
|
while caret_position > overflow_index:
|
|
|
|
char_offset += caret_position - overflow_index
|
|
|
|
overflow_index = _calculate_overflow_index()
|
2024-03-07 16:49:33 +02:00
|
|
|
if overflow_index == - 1:
|
2023-11-23 20:19:30 +02:00
|
|
|
break
|
2023-11-23 19:26:09 +02:00
|
|
|
|
|
|
|
while caret_position < char_offset:
|
2023-11-23 20:19:30 +02:00
|
|
|
char_offset = caret_position
|
2023-11-23 19:26:09 +02:00
|
|
|
overflow_index = _calculate_overflow_index()
|
2024-03-07 16:49:33 +02:00
|
|
|
if overflow_index == - 1:
|
2023-11-23 20:19:30 +02:00
|
|
|
break
|
2023-11-23 19:26:09 +02:00
|
|
|
|
|
|
|
func get_caret_position():
|
|
|
|
return gap_offsets[caret_position] - gap_offsets[char_offset]
|
|
|
|
|
|
|
|
func update_caret_position(click_pos_x: float):
|
|
|
|
caret_position = _calculate_caret_position(click_pos_x)
|
2023-11-23 20:19:30 +02:00
|
|
|
focus_caret()
|
2023-11-23 19:26:09 +02:00
|
|
|
|
|
|
|
func _calculate_caret_position(click_pos_x: float):
|
|
|
|
for i in range(1, gap_offsets.size()):
|
|
|
|
var left = gap_offsets[i] - gap_offsets[char_offset]
|
|
|
|
|
|
|
|
if click_pos_x < left:
|
2024-03-07 16:49:33 +02:00
|
|
|
return i - 1
|
2023-11-23 19:26:09 +02:00
|
|
|
|
|
|
|
return gap_offsets.size() - 1
|
|
|
|
|
|
|
|
func _calculate_text_gaps():
|
|
|
|
var offsets = [0.0]
|
|
|
|
|
|
|
|
for i in range(text.length()):
|
2023-11-25 02:46:41 +02:00
|
|
|
var chars = text.substr(0, i + 1) # Can't use single chars because of kerning.
|
2024-03-15 19:27:03 +02:00
|
|
|
var size = FontTools.get_font_size(label, chars)
|
2023-11-25 02:46:41 +02:00
|
|
|
|
2024-03-15 19:27:03 +02:00
|
|
|
offsets.append(size.x)
|
2023-11-23 19:26:09 +02:00
|
|
|
|
|
|
|
return offsets
|
|
|
|
|
|
|
|
func _calculate_overflow_index():
|
|
|
|
for i in range(char_offset, gap_offsets.size()):
|
|
|
|
if gap_offsets[i] - gap_offsets[char_offset] >= width:
|
|
|
|
return i - 1
|
2023-11-23 20:19:30 +02:00
|
|
|
return gap_offsets.size() - 1
|