diff --git a/client/Global.gd b/client/Global.gd index 21c6ae6..9cf4ff9 100644 --- a/client/Global.gd +++ b/client/Global.gd @@ -9,7 +9,6 @@ var player: Player var players: PlayerManager var terrain: Terrain3D var instance_id: int -var interacting_with_ui: bool func _enter_tree(): instance_id = OS.get_process_id() % 4 diff --git a/client/Main.gd b/client/Main.gd index 832f7eb..1bca5d4 100644 --- a/client/Main.gd +++ b/client/Main.gd @@ -1,6 +1,6 @@ extends Node -@export var ui: UIManager +@export var ui: UI func _enter_tree(): connect_main() @@ -58,6 +58,7 @@ func connect_ui(): ui.download_changed = %Client.download_changed ui.upload_changed = %Client.upload_changed ui.message_received = %Chat.message_received + ui.chat_message_submitted.connect(%Chat.send_message) func toggle_fullscreen(): var mode = DisplayServer.window_get_mode() diff --git a/client/camera/Camera.gd b/client/camera/Camera.gd index 5e611b7..06bf8ac 100644 --- a/client/camera/Camera.gd +++ b/client/camera/Camera.gd @@ -43,11 +43,9 @@ func _unhandled_input(event): match event.is_pressed(): true: - DisplayServer.mouse_set_mode(DisplayServer.MOUSE_MODE_CAPTURED) - look_enabled = true + start_look() false: - DisplayServer.mouse_set_mode(DisplayServer.MOUSE_MODE_VISIBLE) - look_enabled = false + end_look() func _input(event): if event.is_action_pressed("zoom_in", true): @@ -96,6 +94,15 @@ func _process(delta): look_at(center) +func start_look(): + DisplayServer.mouse_set_mode(DisplayServer.MOUSE_MODE_CAPTURED) + look_enabled = true + UI.unfocus() + +func end_look(): + DisplayServer.mouse_set_mode(DisplayServer.MOUSE_MODE_VISIBLE) + look_enabled = false + func on_distance_changed(): target_distance = clampf(target_distance, zoom_min, zoom_max) Global.camera_attributes.dof_blur_far_distance = target_distance + 1.0 diff --git a/client/network/Chat.gd b/client/network/Chat.gd index 0646416..7ef2f6b 100644 --- a/client/network/Chat.gd +++ b/client/network/Chat.gd @@ -17,5 +17,8 @@ func handle_packet(data: PackedByteArray): var message := buffer.get_utf8_string() %Client.log("%s: %s" % [player.name, message]) - message_received.emit("[color=#808080]%s:[/color] %s" % [player.name, message]) + message_received.emit("[color=#e0e0e0]%s:[/color] %s" % [player.name, escape_bbcode(message)]) + +func escape_bbcode(text: String) -> String: + return text.replace("[", "[lb]") \ No newline at end of file diff --git a/client/player/controller/PlayerController.gd b/client/player/controller/PlayerController.gd index 384ff8f..3dd5221 100644 --- a/client/player/controller/PlayerController.gd +++ b/client/player/controller/PlayerController.gd @@ -12,7 +12,8 @@ func _init(new_player: Player): name = "Controller" func _unhandled_input(event: InputEvent): - if Global.interacting_with_ui: + if UI.focus: + direction_changed.emit(Vector3.ZERO) return update_direction() diff --git a/client/test/benchmark/Benchmark.gd b/client/test/benchmark/Benchmark.gd index c87330b..6412b40 100644 --- a/client/test/benchmark/Benchmark.gd +++ b/client/test/benchmark/Benchmark.gd @@ -8,12 +8,13 @@ var benchmarks = [ "find_child", "get_child", "get_parent", - "get_viewport", "get_tree", "get_ticks_msec", "get_ticks_usec", "get_unix_time_from_system", + "get_viewport", "get_world_3d", + "gui_get_focus_owner", "script_func_call", "create_timer", ] @@ -51,10 +52,6 @@ func _get_parent(): for i in range(n): get_parent() -func _get_viewport(): - for i in range(n): - get_viewport() - func _get_tree(): for i in range(n): get_tree() @@ -71,6 +68,16 @@ func _get_unix_time_from_system(): for i in range(n): Time.get_unix_time_from_system() +func _gui_get_focus_owner(): + var vp := get_viewport() + + for i in range(n): + vp.gui_get_focus_owner() + +func _get_viewport(): + for i in range(n): + get_viewport() + func _get_world_3d(): for i in range(n): get_world_3d() diff --git a/client/ui/UI.gd b/client/ui/UI.gd index 9976274..4e41e43 100644 --- a/client/ui/UI.gd +++ b/client/ui/UI.gd @@ -1,6 +1,8 @@ -class_name UIManager +class_name UI extends Node +static var focus: Control + signal chat_message_submitted(message: String) @export var login: Signal @@ -11,8 +13,18 @@ signal chat_message_submitted(message: String) @export var message_received: Signal func _enter_tree(): - if !get_node_or_null("/root/Main"): - connect_fake() + if get_node_or_null("/root/Main"): + return + + connect_fake() + +func _process(_delta): + var new_focus := get_viewport().gui_get_focus_owner() + + if new_focus && new_focus.name != "Unfocus": + UI.focus = new_focus + else: + UI.focus = null func connect_fake(): for property in get_property_list(): @@ -21,3 +33,7 @@ func connect_fake(): add_user_signal(property.name) set(property.name, Signal(self, property.name)) + +static func unfocus(): + if UI.focus: + UI.focus.release_focus() \ No newline at end of file diff --git a/client/ui/UI.tscn b/client/ui/UI.tscn index 7071c21..3c115ba 100644 --- a/client/ui/UI.tscn +++ b/client/ui/UI.tscn @@ -19,6 +19,16 @@ [node name="UI" type="CanvasLayer"] script = ExtResource("1_l5b6o") +[node name="Unfocus" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +focus_mode = 1 +mouse_filter = 1 + [node name="TopLeft" type="MarginContainer" parent="."] offset_right = 40.0 offset_bottom = 50.0 @@ -113,7 +123,7 @@ grow_horizontal = 2 grow_vertical = 0 [node name="Chat" type="VBoxContainer" parent="Bottom"] -custom_minimum_size = Vector2(200, 0) +custom_minimum_size = Vector2(320, 180) layout_mode = 2 size_flags_vertical = 3 alignment = 2 @@ -121,8 +131,12 @@ alignment = 2 [node name="ChatBox" type="RichTextLabel" parent="Bottom/Chat"] layout_mode = 2 size_flags_vertical = 3 +focus_mode = 2 bbcode_enabled = true +scroll_active = false scroll_following = true +context_menu_enabled = true +selection_enabled = true script = ExtResource("5_43juw") [node name="ChatInput" type="LineEdit" parent="Bottom/Chat"] @@ -224,7 +238,3 @@ anchor_left = 0.25 anchor_top = 0.25 anchor_right = 0.75 anchor_bottom = 0.75 - -[connection signal="focus_entered" from="Bottom/Chat/ChatInput" to="Bottom/Chat/ChatInput" method="_on_focus_entered"] -[connection signal="focus_exited" from="Bottom/Chat/ChatInput" to="Bottom/Chat/ChatInput" method="_on_focus_exited"] -[connection signal="text_submitted" from="Bottom/Chat/ChatInput" to="Bottom/Chat/ChatInput" method="_on_text_submitted"] diff --git a/client/ui/chat/ChatInput.gd b/client/ui/chat/ChatInput.gd index 809792c..8fd4cc7 100644 --- a/client/ui/chat/ChatInput.gd +++ b/client/ui/chat/ChatInput.gd @@ -2,26 +2,27 @@ extends LineEdit func _ready(): modulate.a = 0.0 + focus_entered.connect(on_focus_entered) + focus_exited.connect(on_focus_exited) + text_submitted.connect(on_text_submitted) func _unhandled_key_input(event): - if Global.interacting_with_ui: + if UI.focus: return if event.is_action_pressed("open_chat"): call_deferred("grab_focus") get_viewport().set_input_as_handled() -func _on_focus_entered(): +func on_focus_entered(): var tween := get_tree().create_tween() tween.tween_property(self, "modulate", Color(1, 1, 1, 1), 0.2) - Global.interacting_with_ui = true -func _on_focus_exited(): +func on_focus_exited(): var tween := get_tree().create_tween() tween.tween_property(self, "modulate", Color(1, 1, 1, 0), 0.2) - Global.interacting_with_ui = false -func _on_text_submitted(message: String): - (owner as UIManager).chat_message_submitted.emit(message) +func on_text_submitted(message: String): + (owner as UI).chat_message_submitted.emit(message) text = "" release_focus() diff --git a/client/ui/settings/layer/CullMaskToggle.gd b/client/ui/settings/layer/CullMaskToggle.gd index dc752e7..141b840 100644 --- a/client/ui/settings/layer/CullMaskToggle.gd +++ b/client/ui/settings/layer/CullMaskToggle.gd @@ -3,9 +3,15 @@ extends CheckButton @export var layer_number: int func _ready(): + if !Global.camera: + return + set_pressed_no_signal(Global.camera.cull_mask & (1 << (layer_number - 1))) func on_toggled(toggled_on: bool): + if !Global.camera: + return + if toggled_on: Global.camera.cull_mask |= 1 << (layer_number - 1) else: