implement notification system

This commit is contained in:
Nitwel 2023-12-13 22:22:52 +01:00
parent dcfad4ddaf
commit a215ababff
13 changed files with 312 additions and 18 deletions

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:3782adb5391dac4872890ccd7c7820c6c4eb20d56031598c1f3c4d978438a914 oid sha256:5a691fa84af96f6cb9243d817266e0a4064cee5384eb97bf2bf45ce799b859ae
size 12684397 size 16818156

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:92f36b94bc49caee6ea06bae49983840ce37d27c0e38309038c20163c8b1c7b4 oid sha256:130236cec1c40b3b471db1c7099d86383a83b28d79316dd2ac45bc445e4a9bc5
size 1035 size 1038

View File

@ -2,7 +2,7 @@
[ext_resource type="Script" path="res://content/system/keyboard/keyboard.gd" id="1_maojw"] [ext_resource type="Script" path="res://content/system/keyboard/keyboard.gd" id="1_maojw"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_xdpwr"] [ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_xdpwr"]
[ext_resource type="Script" path="res://content/ui/menu/grid.gd" id="3_mx544"] [ext_resource type="Script" path="res://content/ui/components/grid_container/grid_container.gd" id="3_mx544"]
[ext_resource type="Script" path="res://content/functions/movable.gd" id="4_86fct"] [ext_resource type="Script" path="res://content/functions/movable.gd" id="4_86fct"]
[ext_resource type="Material" uid="uid://bnwimm214q67g" path="res://assets/materials/sec-500.material" id="5_8c8rc"] [ext_resource type="Material" uid="uid://bnwimm214q67g" path="res://assets/materials/sec-500.material" id="5_8c8rc"]
[ext_resource type="Script" path="res://content/functions/occludable.gd" id="6_y4sdl"] [ext_resource type="Script" path="res://content/functions/occludable.gd" id="6_y4sdl"]

View File

@ -0,0 +1,54 @@
@tool
extends Node3D
@onready var label: Label3D = $AnimationNode/Text
@onready var icon_label: Label3D = $AnimationNode/Icon
@onready var mesh: MeshInstance3D = $AnimationNode/MeshInstance3D
@onready var collision: CollisionShape3D = $AnimationNode/CollisionShape3D
@onready var animation_player: AnimationPlayer = $AnimationNode/AnimationPlayer
@onready var button = $AnimationNode/Button
@onready var timer = $AnimationNode/Timer
@export var type: EventNotify.Type = EventNotify.Type.INFO:
set(value):
type = value
if !is_node_ready(): await ready
print(value, " ", _type_to_string(value))
icon_label.text = _type_to_string(value)
@export var text: String = "":
set(value):
text = value
if !is_node_ready(): await ready
label.text = value
func _ready():
button.on_button_down.connect(fade_out)
fade_in()
timer.timeout.connect(func():
fade_out()
)
func fade_in():
if !is_node_ready(): await ready
animation_player.play("fade_in")
func fade_out():
animation_player.play_backwards("fade_in")
await animation_player.animation_finished
queue_free()
func _type_to_string(type: EventNotify.Type) -> String:
match type:
EventNotify.Type.INFO:
return "info"
EventNotify.Type.SUCCESS:
return "check_circle"
EventNotify.Type.WARNING:
return "error"
EventNotify.Type.DANGER:
return "warning"
_:
return "info"

View File

@ -0,0 +1,202 @@
[gd_scene load_steps=10 format=3 uid="uid://bqj7qwj5mgd30"]
[ext_resource type="Script" path="res://content/ui/components/notification/notification.gd" id="1_yw3yb"]
[ext_resource type="Material" uid="uid://bujy3egn1oqac" path="res://assets/materials/pri-500.material" id="2_5b8oo"]
[ext_resource type="FontVariation" uid="uid://sshfnckriqxn" path="res://assets/icons/icons.tres" id="3_1ljpc"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="4_ocg5j"]
[sub_resource type="BoxMesh" id="BoxMesh_s37oj"]
size = Vector3(0.25, 0.01, 0.05)
[sub_resource type="BoxShape3D" id="BoxShape3D_m4d21"]
size = Vector3(0.25, 0.01, 0.05)
[sub_resource type="Animation" id="Animation_bkual"]
length = 0.001
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:scale:x")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
tracks/1/type = "bezier"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:scale:y")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
tracks/2/type = "bezier"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath(".:scale:z")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
tracks/3/type = "bezier"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath(".:position:x")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
tracks/4/type = "bezier"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath(".:position:y")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
tracks/5/type = "bezier"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath(".:position:z")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
[sub_resource type="Animation" id="Animation_r1tka"]
resource_name = "fade_in"
length = 0.3
step = 0.01
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:scale:x")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0.01, -0.25, 0, 0.25, 0, 1, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.3)
}
tracks/1/type = "bezier"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:scale:y")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0, 1, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.3)
}
tracks/2/type = "bezier"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath(".:scale:z")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0, 1, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.3)
}
tracks/3/type = "bezier"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath(".:position:x")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(-0.13, -0.25, 0, 0.25, 0, 0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.3)
}
tracks/4/type = "bezier"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath(".:position:y")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, 0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.3)
}
tracks/5/type = "bezier"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath(".:position:z")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, 0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.3)
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_kbhuj"]
_data = {
"RESET": SubResource("Animation_bkual"),
"fade_in": SubResource("Animation_r1tka")
}
[node name="Notification" type="Node3D"]
script = ExtResource("1_yw3yb")
[node name="AnimationNode" type="StaticBody3D" parent="."]
[node name="MeshInstance3D" type="MeshInstance3D" parent="AnimationNode"]
material_override = ExtResource("2_5b8oo")
mesh = SubResource("BoxMesh_s37oj")
[node name="CollisionShape3D" type="CollisionShape3D" parent="AnimationNode"]
shape = SubResource("BoxShape3D_m4d21")
[node name="Text" type="Label3D" parent="AnimationNode"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.08, 0.006, 0)
pixel_size = 0.001
text = "Example Text"
font_size = 10
outline_size = 0
horizontal_alignment = 0
autowrap_mode = 3
width = 190.0
[node name="Icon" type="Label3D" parent="AnimationNode"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.1, 0.006, 0)
pixel_size = 0.001
text = "check_circle"
font = ExtResource("3_1ljpc")
font_size = 24
outline_size = 0
[node name="AnimationPlayer" type="AnimationPlayer" parent="AnimationNode"]
libraries = {
"": SubResource("AnimationLibrary_kbhuj")
}
[node name="Button" parent="AnimationNode" instance=ExtResource("4_ocg5j")]
transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0.12, -0.003, -0.02)
label = "close"
icon = true
[node name="Timer" type="Timer" parent="AnimationNode"]
wait_time = 3.0
autostart = true

View File

@ -1,7 +1,7 @@
[gd_scene load_steps=4 format=3 uid="uid://crrb0l3ekuotj"] [gd_scene load_steps=4 format=3 uid="uid://crrb0l3ekuotj"]
[ext_resource type="Script" path="res://content/ui/menu/edit/edit_menu.gd" id="1_34cbn"] [ext_resource type="Script" path="res://content/ui/menu/edit/edit_menu.gd" id="1_34cbn"]
[ext_resource type="Script" path="res://content/ui/menu/grid.gd" id="3_0xvyw"] [ext_resource type="Script" path="res://content/ui/components/grid_container/grid_container.gd" id="3_0xvyw"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="4_tvimg"] [ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="4_tvimg"]
[node name="EditMenu" type="Node3D"] [node name="EditMenu" type="Node3D"]

View File

@ -1,6 +1,7 @@
extends Node3D extends Node3D
const Proxy = preload("res://lib/utils/proxy.gd") const Proxy = preload("res://lib/utils/proxy.gd")
const Notification = preload("res://content/ui/components/notification/notification.tscn")
@onready var _controller := XRHelpers.get_xr_controller(self) @onready var _controller := XRHelpers.get_xr_controller(self)
@ -17,6 +18,7 @@ const Proxy = preload("res://lib/utils/proxy.gd")
@onready var content = $AnimationContainer/Content @onready var content = $AnimationContainer/Content
@onready var nav = $AnimationContainer/Navigation @onready var nav = $AnimationContainer/Navigation
@onready var animation_player = $AnimationPlayer @onready var animation_player = $AnimationPlayer
@onready var notify_place = $AnimationContainer/NotifyPlace
var selected_nav = null var selected_nav = null
@ -34,6 +36,21 @@ func _ready():
_controller.button_pressed.connect(func(button): _controller.button_pressed.connect(func(button):
if button == "by_button": if button == "by_button":
show_menu = !show_menu show_menu = !show_menu
)
EventSystem.on_notify.connect(func(event: EventNotify):
var notification_node = Notification.instantiate()
notification_node.text = event.message
notification_node.type = event.type
for child in notify_place.get_children():
child.position += Vector3(0, 0, -0.06)
notify_place.add_child(notification_node)
) )
var nav_buttons = [ var nav_buttons = [

View File

@ -213,6 +213,9 @@ visible = false
[node name="SettingsMenu" parent="AnimationContainer/Content" instance=ExtResource("11_7wm6b")] [node name="SettingsMenu" parent="AnimationContainer/Content" instance=ExtResource("11_7wm6b")]
visible = false visible = false
[node name="NotifyPlace" type="Marker3D" parent="AnimationContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.2, 0, -0.05)
[node name="ImmersiveHomePanels" type="MeshInstance3D" parent="."] [node name="ImmersiveHomePanels" type="MeshInstance3D" parent="."]
transform = Transform3D(-4.37114e-10, 0, 0.01, 0, 0.01, 0, -0.01, 0, -4.37114e-10, 0.32, 0, -0.0500001) transform = Transform3D(-4.37114e-10, 0, 0.01, 0, 0.01, 0, -0.01, 0, -4.37114e-10, 0.32, 0, -0.0500001)
visible = false visible = false

View File

@ -0,0 +1,12 @@
extends Event
class_name EventNotify
enum Type {
INFO,
SUCCESS,
WARNING,
DANGER
}
var message: String
var type: Type

View File

@ -24,6 +24,8 @@ signal on_touch_enter(event: EventTouch)
signal on_touch_move(event: EventTouch) signal on_touch_move(event: EventTouch)
signal on_touch_leave(event: EventTouch) signal on_touch_leave(event: EventTouch)
signal on_notify(event: EventNotify)
var _active_node: Node = null var _active_node: Node = null
func emit(type: String, event: Event): func emit(type: String, event: Event):
@ -32,6 +34,12 @@ func emit(type: String, event: Event):
else: else:
_root_call(type, event) _root_call(type, event)
func notify(message: String, type := EventNotify.Type.INFO):
var event = EventNotify.new()
event.message = message
event.type = type
emit("notify", event)
func is_focused(node: Node): func is_focused(node: Node):
return _active_node == node return _active_node == node

View File

@ -20,8 +20,6 @@ var authenticated := false
var id := 1 var id := 1
var entities: Dictionary = {} var entities: Dictionary = {}
var retries := 5
var entitiy_callbacks := CallbackMap.new() var entitiy_callbacks := CallbackMap.new()
var packet_callbacks := CallbackMap.new() var packet_callbacks := CallbackMap.new()
@ -36,18 +34,13 @@ func connect_ws():
if url == "" || token == "": if url == "" || token == "":
return return
retries -= 1
if retries < 0:
print("Failed to connect to %s" % self.url)
return
print("Connecting to %s" % self.url) print("Connecting to %s" % self.url)
socket.connect_to_url(self.url) socket.connect_to_url(self.url)
set_process(true) set_process(true)
# https://github.com/godotengine/godot/issues/84423 # https://github.com/godotengine/godot/issues/84423
# Otherwise the WebSocketPeer will crash when receiving large packets # Otherwise the WebSocketPeer will crash when receiving large packets
socket.set_inbound_buffer_size(65535 * 2) socket.set_inbound_buffer_size(65535 * 4)
func _process(delta): func _process(delta):
socket.poll() socket.poll()
@ -66,7 +59,13 @@ func _process(delta):
elif state == WebSocketPeer.STATE_CLOSED: elif state == WebSocketPeer.STATE_CLOSED:
var code = socket.get_close_code() var code = socket.get_close_code()
var reason = socket.get_close_reason() var reason = socket.get_close_reason()
print("WS connection closed with code: %s, reason: %s" % [code, reason])
if reason == "":
reason = "Invalid URL"
var message = "WS connection closed with code: %s, reason: %s" % [code, reason]
EventSystem.notify(message, EventNotify.Type.DANGER)
print(message)
handle_disconnect() handle_disconnect()
func handle_packet(packet: Dictionary): func handle_packet(packet: Dictionary):
@ -83,6 +82,8 @@ func handle_packet(packet: Dictionary):
start_subscriptions() start_subscriptions()
elif packet.type == "auth_invalid": elif packet.type == "auth_invalid":
EventSystem.notify("Failed to authenticate, invalid auth token", EventNotify.Type.DANGER)
print("Failed to authenticate, invalid auth token")
handle_disconnect() handle_disconnect()
else: else:
packet_callbacks.call_key(int(packet.id), [packet]) packet_callbacks.call_key(int(packet.id), [packet])
@ -136,9 +137,6 @@ func handle_disconnect():
set_process(false) set_process(false)
on_disconnect.emit() on_disconnect.emit()
# Reconnect
connect_ws()
func send_subscribe_packet(packet: Dictionary, callback: Callable): func send_subscribe_packet(packet: Dictionary, callback: Callable):
packet.id = id packet.id = id
id += 1 id += 1