get basic input moving to work

This commit is contained in:
Nitwel 2023-11-23 18:26:09 +01:00
parent f8033e7e06
commit c1ba32552d
4 changed files with 145 additions and 57 deletions

View File

@ -1,36 +1,36 @@
@tool
extends StaticBody3D
@onready var label: Label3D = $Label
@export var text: String = "Hello World":
set(value):
var old_text = text
text = value
if label == null:
return
label.text = value
if Engine.is_editor_hint():
return
gap_offsets = _calculate_text_gaps()
caret_position += text.length() - old_text.length()
text_changed.emit(value)
var text_handler = preload("res://content/ui/components/input/text_handler.gd").new()
@onready var caret: MeshInstance3D = $Label/Caret
@onready var mesh_box: MeshInstance3D = $Box
@onready var collision: CollisionShape3D = $Collision
@onready var animation: AnimationPlayer = $AnimationPlayer
@onready var label: Label3D = $Label
signal text_changed(text: String)
@export_range(0.1, 2, 0.01, "suffix:m") var width: float = 0.15:
get:
return text_handler.width
set(value):
set_width(value)
@export var text: String:
get:
return text_handler.text
set(value):
text_handler.set_text(value, EventSystem.is_focused(self) == false)
if label != null:
label.text = text_handler.get_display_text()
var keyboard_input: bool = false
var gap_offsets = []
var caret_position: int = 3:
set(value):
caret_position = clampi(value, 0, text.length())
caret.position.x = gap_offsets[caret_position]
func _ready():
text = text # So @tool works
text_handler.label = label
text = text
width = width
if Engine.is_editor_hint():
return
@ -39,7 +39,9 @@ func _ready():
if EventSystem.is_focused(self) == false:
return
text = EventKey.key_to_string(event.key, event.shift_pressed, text.substr(0, caret_position)) + text.substr(caret_position, text.length())
text = EventKey.key_to_string(event.key, event.shift_pressed, text.substr(0, text_handler.caret_position)) + text.substr(text_handler.caret_position, text.length())
caret.position.x = text_handler.get_caret_position()
label.text = text_handler.get_display_text()
)
func _input(event):
@ -49,7 +51,8 @@ func _input(event):
return
if keyboard_input:
text = EventKey.key_to_string(event.keycode, event.shift_pressed, text.substr(0, caret_position)) + text.substr(caret_position, text.length())
text = EventKey.key_to_string(event.keycode, event.shift_pressed, text.substr(0, text_handler.caret_position)) + text.substr(text_handler.caret_position, text.length())
caret.position.x = text_handler.get_caret_position()
func _process(_delta):
if Engine.is_editor_hint():
@ -58,46 +61,37 @@ func _process(_delta):
if get_tree().debug_collisions_hint && OS.get_name() != "Android":
_draw_debug_text_gaps()
func _calculate_caret_pos(click_pos_x: float):
for i in range(1, gap_offsets.size()):
var left = gap_offsets[i]
if click_pos_x < left:
return i - 1
func set_width(value: float):
text_handler.width = value
return gap_offsets.size() - 1
if mesh_box == null || collision == null || label == null:
return
mesh_box.mesh.size.x = value
collision.shape.size.x = value
label.position.x = -value / 2 + 0.002
func _on_focus_in(event):
gap_offsets = _calculate_text_gaps()
var pos_x = label.to_local(event.ray.get_collision_point()).x
caret_position = _calculate_caret_pos(pos_x)
text_handler.update_caret_position(pos_x)
caret.position.x = text_handler.get_caret_position()
caret.show()
animation.play("blink")
func _on_focus_out(_event):
animation.stop()
caret.hide()
func _calculate_text_gaps():
var font = label.get_font()
var offsets = [0.0]
var offset = 0.0
for i in range(text.length()):
var character = text[i]
var size = font.get_string_size(character, HORIZONTAL_ALIGNMENT_CENTER, -1, label.font_size)
offset += size.x * label.pixel_size
offsets.append(offset)
return offsets
func _draw_debug_text_gaps():
for offset in gap_offsets:
if text_handler.gap_offsets == null:
return
for i in range(text_handler.gap_offsets.size()):
var offset = text_handler.gap_offsets[i] - text_handler.gap_offsets[text_handler.char_offset]
DebugDraw3D.draw_line(
label.to_global(Vector3(offset, -0.01, 0)),
label.to_global(Vector3(offset, 0.01, 0)),
Color(1, 0, 0),
Color(1, 0, 0) if i != text_handler.overflow_index else Color(0, 1, 0)
)

View File

@ -4,10 +4,12 @@
[ext_resource type="Script" path="res://content/ui/components/input/input.gd" id="1_uml3t"]
[sub_resource type="BoxMesh" id="BoxMesh_kjbca"]
size = Vector3(0.2, 0.006, 0.03)
resource_local_to_scene = true
size = Vector3(0.15, 0.006, 0.03)
[sub_resource type="BoxShape3D" id="BoxShape3D_x4yp8"]
size = Vector3(0.2, 0.006, 0.03)
resource_local_to_scene = true
size = Vector3(0.15, 0.006, 0.03)
[sub_resource type="SystemFont" id="SystemFont_nbea0"]
@ -53,18 +55,19 @@ _data = {
[node name="Input" type="StaticBody3D" groups=["ui_focus"]]
script = ExtResource("1_uml3t")
text = "Hello World"
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
[node name="Box" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.003, 0)
material_override = ExtResource("1_0kd7r")
mesh = SubResource("BoxMesh_kjbca")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
[node name="Collision" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.003, 0)
shape = SubResource("BoxShape3D_x4yp8")
[node name="Label" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.096, 0.00618291, 0)
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.073, 0.00618291, 0)
pixel_size = 0.0004
text = "Hello World"
font = SubResource("SystemFont_nbea0")

View File

@ -0,0 +1,89 @@
extends Object
var label: Label3D
var text: String = ""
var width: float = 0.2
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())
func set_width(value: float):
width = value
func set_text(value: String, insert: bool = false):
var old_text = text
text = value
if label == null:
return
gap_offsets = _calculate_text_gaps()
if insert == false:
caret_position += text.length() - old_text.length()
else:
caret_position = 0
overflow_index = _calculate_overflow_index()
focus_caret()
func get_display_text():
# In case all chars fit, return the whole text.
if overflow_index == -1:
return text.substr(char_offset)
return text.substr(char_offset, overflow_index - char_offset)
func focus_caret():
if overflow_index == -1:
char_offset = 0
return
while caret_position > overflow_index:
char_offset += caret_position - overflow_index
overflow_index = _calculate_overflow_index()
while caret_position < char_offset:
char_offset = caret_position#
overflow_index = _calculate_overflow_index()
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)
print("caret_position: ", caret_position)
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:
return i - 1
return gap_offsets.size() - 1
func _calculate_text_gaps():
var font = label.get_font()
var offsets = [0.0]
var offset = 0.0
for i in range(text.length()):
var character = text[i]
var size = font.get_string_size(character, HORIZONTAL_ALIGNMENT_CENTER, -1, label.font_size)
offset += size.x * label.pixel_size
offsets.append(offset)
return offsets
## Returns the index of the last character that fits in the width.
## If all characters fit, returns -1.
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
return -1

View File

@ -43,6 +43,7 @@ horizontal_alignment = 0
[node name="InputURL" parent="Content" instance=ExtResource("4_q3x6k")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.18, 0, 0.03)
width = 0.2
text = "ws://192.168.33.33:8123"
[node name="LabelToken" type="Label3D" parent="Content"]
@ -54,7 +55,8 @@ horizontal_alignment = 0
[node name="InputToken" parent="Content" instance=ExtResource("4_q3x6k")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.18, 0, 0.07)
text = "paste token here"
width = 0.2
text = "paste token here paste token here"
[node name="LabelConnect" type="Label3D" parent="Content"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.15, 0, 0.12)