get basic input moving to work
This commit is contained in:
parent
f8033e7e06
commit
c1ba32552d
|
@ -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)
|
||||
)
|
||||
|
|
|
@ -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")
|
||||
|
|
89
content/ui/components/input/text_handler.gd
Normal file
89
content/ui/components/input/text_handler.gd
Normal 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
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue
Block a user