From 98220921bd692603d5f86b3426d40f553798a4a8 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 1 May 2026 12:24:54 -0500 Subject: [PATCH] Add radial command menu for minions --- game/project.godot | 5 + game/scenes/Interaction/RadialCommandMenu.gd | 56 ++++++ .../Interaction/RadialCommandMenu.gd.uid | 1 + .../scenes/Interaction/RadialCommandMenu.tscn | 42 ++++ game/scenes/Levels/RadialCommandMenu.gd | 41 ++++ game/scenes/Levels/RadialCommandMenu.gd.uid | 1 + game/scenes/Levels/level.gd | 136 ++++++------- game/scenes/Levels/level.tscn | 10 +- game/scenes/Levels/starting_area_level.tscn | 37 ++-- game/scenes/UI/start_screen.gd | 124 ++++++------ game/scenes/UI/start_screen.tscn | 184 +++++++++--------- game/themes/button_theme.tres | 106 +++++----- 12 files changed, 449 insertions(+), 294 deletions(-) create mode 100644 game/scenes/Interaction/RadialCommandMenu.gd create mode 100644 game/scenes/Interaction/RadialCommandMenu.gd.uid create mode 100644 game/scenes/Interaction/RadialCommandMenu.tscn create mode 100644 game/scenes/Levels/RadialCommandMenu.gd create mode 100644 game/scenes/Levels/RadialCommandMenu.gd.uid diff --git a/game/project.godot b/game/project.godot index f079af3..a3fc8f9 100644 --- a/game/project.godot +++ b/game/project.godot @@ -115,6 +115,11 @@ interact={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null) ] } +OpenRadialCommandMenu={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null) +] +} [shader_globals] diff --git a/game/scenes/Interaction/RadialCommandMenu.gd b/game/scenes/Interaction/RadialCommandMenu.gd new file mode 100644 index 0000000..ae2b0ac --- /dev/null +++ b/game/scenes/Interaction/RadialCommandMenu.gd @@ -0,0 +1,56 @@ +extends Control + +@export var radius: float = 150.0 +@export var transition_speed: float = 0.2 + +func _ready(): + hide() # Start hidden + _arrange_buttons() + +func _input(event): + if event.is_action_pressed("OpenRadialCommandMenu"): # Map 'Q' to "open_menu" in Input Map + _toggle_menu() + +func _toggle_menu(): + visible = !visible + if visible: + # Center the menu on the mouse or screen + global_position = get_viewport().get_mouse_position() + _animate_menu(true) + else: + _animate_menu(false) + +func _arrange_buttons(): + var buttons = get_children() + var count = buttons.size() + + for i in range(count): + # Calculate the angle for each button in radians + var angle = i * (2 * PI / count) + + # Standard circle math: x = cos(a) * r, y = sin(a) * r + var target_pos = Vector2(cos(angle), sin(angle)) * radius + + # Offset by button size to keep them centered + buttons[i].position = target_pos - (buttons[i].size / 2) + +func _animate_menu(opening: bool): + var tween = create_tween().set_parallel(true) + for button in get_children(): + var final_scale = Vector2.ONE if opening else Vector2.ZERO + tween.tween_property(button, "scale", final_scale, transition_speed).from(Vector2.ZERO if opening else Vector2.ONE) + + +func _on_btn_follow_pressed() -> void: + print("Follow command pressed") + _toggle_menu() # Closes the menu after clicking + + +func _on_btn_go_to_pressed() -> void: + print("Go to command pressed") + _toggle_menu() # Closes the menu after clicking + + +func _on_btn_attack_pressed() -> void: + print("Attack command pressed") + _toggle_menu() # Closes the menu after clicking diff --git a/game/scenes/Interaction/RadialCommandMenu.gd.uid b/game/scenes/Interaction/RadialCommandMenu.gd.uid new file mode 100644 index 0000000..9f98885 --- /dev/null +++ b/game/scenes/Interaction/RadialCommandMenu.gd.uid @@ -0,0 +1 @@ +uid://cjfhlslc5vp7b diff --git a/game/scenes/Interaction/RadialCommandMenu.tscn b/game/scenes/Interaction/RadialCommandMenu.tscn new file mode 100644 index 0000000..3b0932b --- /dev/null +++ b/game/scenes/Interaction/RadialCommandMenu.tscn @@ -0,0 +1,42 @@ +[gd_scene format=3 uid="uid://bnwpu7p8sbsfa"] + +[ext_resource type="Script" uid="uid://cjfhlslc5vp7b" path="res://scenes/Interaction/RadialCommandMenu.gd" id="1_j0xof"] + +[node name="RadialCommandCanvas" type="CanvasLayer" unique_id=1002896311] + +[node name="PivotControl" type="Control" parent="." unique_id=374070149] +layout_mode = 3 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -20.0 +offset_top = -20.0 +offset_right = 20.0 +offset_bottom = 20.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_j0xof") + +[node name="BtnFollow" type="Button" parent="PivotControl" unique_id=1839549428] +layout_mode = 0 +offset_right = 8.0 +offset_bottom = 8.0 +text = "Follow" + +[node name="BtnGoTo" type="Button" parent="PivotControl" unique_id=818273339] +layout_mode = 0 +offset_right = 8.0 +offset_bottom = 8.0 +text = "Go To" + +[node name="BtnAttack" type="Button" parent="PivotControl" unique_id=744805255] +layout_mode = 0 +offset_right = 8.0 +offset_bottom = 8.0 +text = "Attack" + +[connection signal="pressed" from="PivotControl/BtnFollow" to="PivotControl" method="_on_btn_follow_pressed"] +[connection signal="pressed" from="PivotControl/BtnGoTo" to="PivotControl" method="_on_btn_go_to_pressed"] +[connection signal="pressed" from="PivotControl/BtnAttack" to="PivotControl" method="_on_btn_attack_pressed"] diff --git a/game/scenes/Levels/RadialCommandMenu.gd b/game/scenes/Levels/RadialCommandMenu.gd new file mode 100644 index 0000000..8466fe0 --- /dev/null +++ b/game/scenes/Levels/RadialCommandMenu.gd @@ -0,0 +1,41 @@ +extends Control + +@export var radius: float = 150.0 +@export var transition_speed: float = 0.2 + +func _ready(): + hide() # Start hidden + _arrange_buttons() + +func _input(event): + if event.is_action_pressed("OpenRadialCommandMenu"): # Map 'Q' to "open_menu" in Input Map + _toggle_menu() + +func _toggle_menu(): + visible = !visible + if visible: + # Center the menu on the mouse or screen + global_position = get_viewport().get_mouse_position() + _animate_menu(true) + else: + _animate_menu(false) + +func _arrange_buttons(): + var buttons = get_children() + var count = buttons.size() + + for i in range(count): + # Calculate the angle for each button in radians + var angle = i * (2 * PI / count) + + # Standard circle math: x = cos(a) * r, y = sin(a) * r + var target_pos = Vector2(cos(angle), sin(angle)) * radius + + # Offset by button size to keep them centered + buttons[i].position = target_pos - (buttons[i].size / 2) + +func _animate_menu(opening: bool): + var tween = create_tween().set_parallel(true) + for button in get_children(): + var final_scale = Vector2.ONE if opening else Vector2.ZERO + tween.tween_property(button, "scale", final_scale, transition_speed).from(Vector2.ZERO if opening else Vector2.ONE) diff --git a/game/scenes/Levels/RadialCommandMenu.gd.uid b/game/scenes/Levels/RadialCommandMenu.gd.uid new file mode 100644 index 0000000..814d18a --- /dev/null +++ b/game/scenes/Levels/RadialCommandMenu.gd.uid @@ -0,0 +1 @@ +uid://bv2ei5rg0dn3d diff --git a/game/scenes/Levels/level.gd b/game/scenes/Levels/level.gd index 6dee10b..88c8a1c 100644 --- a/game/scenes/Levels/level.gd +++ b/game/scenes/Levels/level.gd @@ -1,39 +1,39 @@ -extends Node3D - +extends Node3D + @export var day_length := 120.0 # seconds for full rotation @export var start_light_angle := -35.0 -@export var show_spawn_dialog := true -@export_multiline var spawn_dialog_text := "Welcome to Promiscuity.\n\nPress E to close this message." -@export var spawn_dialog_auto_close_seconds := 4.0 -var end_light_angle = start_light_angle + 360.0 -var start_radians = start_light_angle * PI / 180 -var time := 0.0 - -@onready var sun := $DirectionalLight3D -@onready var _player: Node = $Player -@onready var _quest_text: RichTextLabel = $PhoneUI/Control/PhoneFrame/QuestText - +@export var show_spawn_dialog := true +@export_multiline var spawn_dialog_text := "Welcome to Promiscuity.\n\nPress E to close this message." +@export var spawn_dialog_auto_close_seconds := 4.0 +var end_light_angle = start_light_angle + 360.0 +var start_radians = start_light_angle * PI / 180 +var time := 0.0 + +@onready var sun := $DirectionalLight3D +@onready var _player: Node = $Player +@onready var _quest_text: RichTextLabel = $PhoneUI/Control/PhoneFrame/QuestText + const FIRST_QUEST_ID := "first_drive" const QUEST_PROMPT_META_PREFIX := "quest_intro_prompt_shown_" const SPAWN_DIALOG_META_KEY := "level_spawn_dialog_shown" const FIRST_QUEST := { "id": FIRST_QUEST_ID, "title": "RepoBot's First Task", - "description": "Get familiar with movement and vehicles.", - "steps": [ - { - "id": "enter_vehicle", - "text": "Get in the car (E).", - "complete_event": "entered_vehicle", - }, - { - "id": "reach_checkpoint", - "text": "Drive the car into the checkpoint marker.", - "complete_event": "reach_checkpoint", - }, - ], -} - + "description": "Get familiar with movement and vehicles.", + "steps": [ + { + "id": "enter_vehicle", + "text": "Get in the car (E).", + "complete_event": "entered_vehicle", + }, + { + "id": "reach_checkpoint", + "text": "Drive the car into the checkpoint marker.", + "complete_event": "reach_checkpoint", + }, + ], +} + func _ready() -> void: _apply_sun_state(0.0) _setup_quests() @@ -46,7 +46,7 @@ func _ready() -> void: if DialogSystem and DialogSystem.has_method("close_if_text"): DialogSystem.close_if_text(spawn_dialog_text) _show_quest_intro_dialog() - + func _process(delta): time = fmod((time + delta), day_length) _apply_sun_state(time / day_length) @@ -60,45 +60,45 @@ func _apply_sun_state(t: float) -> void: var cur_sin = -sin((t * TAU) + start_radians) var energy = clamp((cur_sin * 1.0) + 0.2, 0.0, 1.2) sun.light_energy = energy - - -func _setup_quests() -> void: - if QuestManager == null: - return - if not QuestManager.has_quest(FIRST_QUEST_ID): - QuestManager.register_quest(FIRST_QUEST) - if not QuestManager.is_active_quest(FIRST_QUEST_ID) and not QuestManager.is_quest_completed(FIRST_QUEST_ID): - QuestManager.start_quest(FIRST_QUEST_ID) - if not QuestManager.is_connected("quest_state_changed", Callable(self, "_refresh_quest_ui")): - QuestManager.quest_state_changed.connect(_refresh_quest_ui) - if _player and _player.has_signal("vehicle_entered"): - if not _player.is_connected("vehicle_entered", Callable(self, "_on_player_vehicle_entered")): - _player.vehicle_entered.connect(_on_player_vehicle_entered) - _refresh_quest_ui() - - -func _on_player_vehicle_entered(_vehicle: Node) -> void: - if QuestManager: - QuestManager.emit_event(&"entered_vehicle") - - -func _refresh_quest_ui() -> void: - if _quest_text == null or QuestManager == null: - return - var state: Dictionary = QuestManager.get_active_quest_state() - if not bool(state.get("active", false)): - _quest_text.text = "No active quest." - return - var title := String(state.get("title", "Quest")) - if bool(state.get("completed", false)): - _quest_text.text = "[b]%s[/b]\nComplete." % title - return - var step_index: int = int(state.get("current_step_index", 0)) - var total_steps: int = int(state.get("total_steps", 0)) - var step_text := String(state.get("current_step_text", "")) - _quest_text.text = "[b]%s[/b]\nStep %d/%d\n%s" % [title, step_index + 1, total_steps, step_text] - - + + +func _setup_quests() -> void: + if QuestManager == null: + return + if not QuestManager.has_quest(FIRST_QUEST_ID): + QuestManager.register_quest(FIRST_QUEST) + if not QuestManager.is_active_quest(FIRST_QUEST_ID) and not QuestManager.is_quest_completed(FIRST_QUEST_ID): + QuestManager.start_quest(FIRST_QUEST_ID) + if not QuestManager.is_connected("quest_state_changed", Callable(self, "_refresh_quest_ui")): + QuestManager.quest_state_changed.connect(_refresh_quest_ui) + if _player and _player.has_signal("vehicle_entered"): + if not _player.is_connected("vehicle_entered", Callable(self, "_on_player_vehicle_entered")): + _player.vehicle_entered.connect(_on_player_vehicle_entered) + _refresh_quest_ui() + + +func _on_player_vehicle_entered(_vehicle: Node) -> void: + if QuestManager: + QuestManager.emit_event(&"entered_vehicle") + + +func _refresh_quest_ui() -> void: + if _quest_text == null or QuestManager == null: + return + var state: Dictionary = QuestManager.get_active_quest_state() + if not bool(state.get("active", false)): + _quest_text.text = "No active quest." + return + var title := String(state.get("title", "Quest")) + if bool(state.get("completed", false)): + _quest_text.text = "[b]%s[/b]\nComplete." % title + return + var step_index: int = int(state.get("current_step_index", 0)) + var total_steps: int = int(state.get("total_steps", 0)) + var step_text := String(state.get("current_step_text", "")) + _quest_text.text = "[b]%s[/b]\nStep %d/%d\n%s" % [title, step_index + 1, total_steps, step_text] + + func _show_quest_intro_dialog() -> void: if QuestManager == null: return diff --git a/game/scenes/Levels/level.tscn b/game/scenes/Levels/level.tscn index 4440f42..90497cd 100644 --- a/game/scenes/Levels/level.tscn +++ b/game/scenes/Levels/level.tscn @@ -15,7 +15,9 @@ [ext_resource type="Material" path="res://assets/materials/kenney_prototype_ground_green.tres" id="9_ground_mat"] [ext_resource type="Texture2D" uid="uid://c4ggdp0kg5wjk" path="res://addons/simplegrasstextured/textures/grassbushcc008.png" id="10_loupo"] [ext_resource type="Script" uid="uid://2juaclm8gc1n" path="res://addons/simplegrasstextured/grass.gd" id="11_1meta"] +[ext_resource type="Script" uid="uid://bv2ei5rg0dn3d" path="res://scenes/Levels/RadialCommandMenu.gd" id="15_18iqp"] [ext_resource type="Texture2D" uid="uid://b2dmnrm3ubjon" path="res://assets/textures/stolenFire.png" id="16_i35yb"] +[ext_resource type="PackedScene" uid="uid://bnwpu7p8sbsfa" path="res://scenes/Interaction/RadialCommandMenu.tscn" id="16_px5jg"] [sub_resource type="PhysicsMaterial" id="PhysicsMaterial_2q6dc"] bounce = 0.5 @@ -428,7 +430,7 @@ phone_path = NodePath("../PhoneUI") [node name="TestCharAnimated" parent="Player" unique_id=77323368 instance=ExtResource("5_fi66n")] transform = Transform3D(-0.9998549, 0, 0.01703362, 0, 1, 0, -0.01703362, 0, -0.9998549, 0, 0, 0) -[node name="AnimationPlayer" parent="Player/TestCharAnimated" index="1" unique_id=351712567] +[node name="AnimationPlayer" parent="Player/TestCharAnimated" index="1"] root_motion_track = NodePath("Armature/Skeleton3D:mixamorig_Hips") [node name="CollisionShape3D" type="CollisionShape3D" parent="Player" unique_id=804053331] @@ -533,7 +535,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.298158, -7.0724635) [node name="Block2" parent="Starter Blocks" unique_id=620097644 instance=ExtResource("2_tc7dm")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.63255787, 2.596316, -6.980046) -[node name="PauseMenu" parent="." instance=ExtResource("3_pause_menu")] +[node name="PauseMenu" parent="." unique_id=657058638 instance=ExtResource("3_pause_menu")] [node name="PhoneUI" type="CanvasLayer" parent="." unique_id=1455569026] layer = 5 @@ -546,6 +548,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +script = ExtResource("15_18iqp") [node name="PhoneFrame" type="ColorRect" parent="PhoneUI/Control" unique_id=1204675817] layout_mode = 1 @@ -580,6 +583,9 @@ bbcode_enabled = true text = "No active quest." scroll_active = false +[node name="RadialCommandMenu" parent="PhoneUI/Control" unique_id=1630028573 instance=ExtResource("16_px5jg")] +layout_mode = 1 + [node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1808155101] environment = SubResource("Environment_a4mo8") diff --git a/game/scenes/Levels/starting_area_level.tscn b/game/scenes/Levels/starting_area_level.tscn index ba0027a..1d0d630 100644 --- a/game/scenes/Levels/starting_area_level.tscn +++ b/game/scenes/Levels/starting_area_level.tscn @@ -1,12 +1,11 @@ -[gd_scene load_steps=8 format=3] +[gd_scene format=3 uid="uid://87wtvoj8u22y"] -[ext_resource type="Script" path="res://scenes/Levels/starting_area_level.gd" id="1_start"] -[ext_resource type="Script" path="res://scenes/player.gd" id="2_player"] -[ext_resource type="PackedScene" path="res://assets/models/TestCharAnimated.glb" id="3_model"] +[ext_resource type="Script" uid="uid://r1oe7fu5n765" path="res://scenes/Levels/starting_area_level.gd" id="1_start"] +[ext_resource type="Script" uid="uid://bpxggc8nr6tf6" path="res://scenes/player.gd" id="2_player"] +[ext_resource type="PackedScene" uid="uid://bnqaqbgynoyys" path="res://assets/models/TestCharAnimated.glb" id="3_model"] [ext_resource type="Material" path="res://assets/materials/kenney_prototype_ground_green.tres" id="4_ground"] [ext_resource type="PackedScene" uid="uid://dp6jk0k3o4v1u" path="res://scenes/UI/pause_menu.tscn" id="5_pause_menu"] - -[sub_resource type="SphereShape3D" id="SphereShape3D_player"] +[ext_resource type="PackedScene" uid="uid://bnwpu7p8sbsfa" path="res://scenes/Interaction/RadialCommandMenu.tscn" id="6_th1jj"] [sub_resource type="BoxShape3D" id="BoxShape3D_ground"] size = Vector3(160, 2, 160) @@ -15,43 +14,47 @@ size = Vector3(160, 2, 160) material = ExtResource("4_ground") size = Vector3(160, 2, 160) -[node name="StartingAreaLevel" type="Node3D"] +[sub_resource type="SphereShape3D" id="SphereShape3D_player"] + +[node name="StartingAreaLevel" type="Node3D" unique_id=987742792] script = ExtResource("1_start") -[node name="Ground" type="StaticBody3D" parent="."] +[node name="Ground" type="StaticBody3D" parent="." unique_id=1889441587] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground" unique_id=1350300878] shape = SubResource("BoxShape3D_ground") -[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"] +[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground" unique_id=1303841260] mesh = SubResource("BoxMesh_ground") -[node name="Player" type="RigidBody3D" parent="."] +[node name="Player" type="RigidBody3D" parent="." unique_id=614825452] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0) script = ExtResource("2_player") camera_path = NodePath("Camera3D") -[node name="CollisionShape3D" type="CollisionShape3D" parent="Player"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Player" unique_id=268018771] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) shape = SubResource("SphereShape3D_player") -[node name="TestCharAnimated" parent="Player" instance=ExtResource("3_model")] +[node name="TestCharAnimated" parent="Player" unique_id=1368073591 instance=ExtResource("3_model")] transform = Transform3D(-0.9998549, 0, 0.01703362, 0, 1, 0, -0.01703362, 0, -0.9998549, 0, 0, 0) -[node name="Camera3D" type="Camera3D" parent="Player"] +[node name="Camera3D" type="Camera3D" parent="Player" unique_id=1401723174] transform = Transform3D(0.9989785, -4.651856e-10, -0.045188628, 0.006969331, 0.9880354, 0.15407, 0.044647958, -0.15422754, 0.9870261, 0.22036135, 1.8988357, 0.64972365) current = true fov = 49.0 -[node name="SpotLight3D" type="SpotLight3D" parent="Player"] +[node name="SpotLight3D" type="SpotLight3D" parent="Player" unique_id=1199474715] transform = Transform3D(1, 0, 0, 0, 0.906308, -0.422618, 0, 0.422618, 0.906308, 0, 1.7, -0.35) visible = false spot_range = 30.0 spot_angle = 25.0 -[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=1949850408] transform = Transform3D(1, 0, 0, 0, 0.819152, 0.573576, 0, -0.573576, 0.819152, 0, 6, 0) shadow_enabled = true -[node name="PauseMenu" parent="." instance=ExtResource("5_pause_menu")] +[node name="PauseMenu" parent="." unique_id=1537852793 instance=ExtResource("5_pause_menu")] + +[node name="RadialCommandCanvas" parent="." unique_id=1002896311 instance=ExtResource("6_th1jj")] diff --git a/game/scenes/UI/start_screen.gd b/game/scenes/UI/start_screen.gd index 98c2db9..4e4c57b 100644 --- a/game/scenes/UI/start_screen.gd +++ b/game/scenes/UI/start_screen.gd @@ -3,72 +3,72 @@ extends Control const AUTH_LOGOUT_URL := "https://pauth.ranaze.com/api/Auth/logout" const START_LEVEL_SCENE := "res://scenes/Levels/starting_area_level.tscn" const PLAYGROUND_SCENE := "res://scenes/Levels/level.tscn" - -@onready var _login_button: Button = $MarginContainer/CenterContainer/ContentVBox/VBoxContainer/LogInButton -@onready var _logout_request: HTTPRequest = %LogoutRequest - -func _ready(): - _register_focus_sounds() - _update_login_button() - -func _register_focus_sounds() -> void: - var button_container := $MarginContainer/CenterContainer/ContentVBox/VBoxContainer - for child in button_container.get_children(): - if child is BaseButton: - var button: BaseButton = child - if not button.is_connected("focus_entered", Callable(self, "_on_menu_item_focus")): - button.focus_entered.connect(_on_menu_item_focus) - if not button.is_connected("mouse_entered", Callable(self, "_on_menu_item_focus")): - button.mouse_entered.connect(_on_menu_item_focus) - + +@onready var _login_button: Button = $MarginContainer/CenterContainer/ContentVBox/VBoxContainer/LogInButton +@onready var _logout_request: HTTPRequest = %LogoutRequest + +func _ready(): + _register_focus_sounds() + _update_login_button() + +func _register_focus_sounds() -> void: + var button_container := $MarginContainer/CenterContainer/ContentVBox/VBoxContainer + for child in button_container.get_children(): + if child is BaseButton: + var button: BaseButton = child + if not button.is_connected("focus_entered", Callable(self, "_on_menu_item_focus")): + button.focus_entered.connect(_on_menu_item_focus) + if not button.is_connected("mouse_entered", Callable(self, "_on_menu_item_focus")): + button.mouse_entered.connect(_on_menu_item_focus) + func _on_start_button_pressed(): get_tree().change_scene_to_file(START_LEVEL_SCENE) func _on_playground_button_pressed() -> void: get_tree().change_scene_to_file(PLAYGROUND_SCENE) - -func _on_settings_button_pressed(): - get_tree().change_scene_to_file("uid://d3tqrm4ry4l88") - -func _on_quit_button_pressed(): - get_tree().quit() - -func _on_log_in_button_pressed(): - if AuthState.is_logged_in: - _request_logout() - else: - get_tree().change_scene_to_file("res://scenes/UI/login_screen.tscn") - -func _on_menu_item_focus() -> void: - if MenuSfx: - MenuSfx.play_hover() - -func _request_logout() -> void: - if AuthState.access_token.is_empty(): - AuthState.clear_session() - _update_login_button() - return - var headers := PackedStringArray([ - "Authorization: Bearer %s" % AuthState.access_token, - ]) - var err := _logout_request.request(AUTH_LOGOUT_URL, headers, HTTPClient.METHOD_POST) - if err != OK: - push_warning("Failed to send logout request: %s" % err) - AuthState.clear_session() - _update_login_button() - -func _on_logout_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: - var body_text := body.get_string_from_utf8() - if result != HTTPRequest.RESULT_SUCCESS or response_code < 200 or response_code >= 300: - push_warning("Logout failed (%s/%s): %s" % [result, response_code, body_text]) - AuthState.clear_session() - _update_login_button() - -func _update_login_button() -> void: - if AuthState.is_logged_in: - _login_button.text = "LOG OUT" - else: - _login_button.text = "LOG IN" - + +func _on_settings_button_pressed(): + get_tree().change_scene_to_file("uid://d3tqrm4ry4l88") + +func _on_quit_button_pressed(): + get_tree().quit() + +func _on_log_in_button_pressed(): + if AuthState.is_logged_in: + _request_logout() + else: + get_tree().change_scene_to_file("res://scenes/UI/login_screen.tscn") + +func _on_menu_item_focus() -> void: + if MenuSfx: + MenuSfx.play_hover() + +func _request_logout() -> void: + if AuthState.access_token.is_empty(): + AuthState.clear_session() + _update_login_button() + return + var headers := PackedStringArray([ + "Authorization: Bearer %s" % AuthState.access_token, + ]) + var err := _logout_request.request(AUTH_LOGOUT_URL, headers, HTTPClient.METHOD_POST) + if err != OK: + push_warning("Failed to send logout request: %s" % err) + AuthState.clear_session() + _update_login_button() + +func _on_logout_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: + var body_text := body.get_string_from_utf8() + if result != HTTPRequest.RESULT_SUCCESS or response_code < 200 or response_code >= 300: + push_warning("Logout failed (%s/%s): %s" % [result, response_code, body_text]) + AuthState.clear_session() + _update_login_button() + +func _update_login_button() -> void: + if AuthState.is_logged_in: + _login_button.text = "LOG OUT" + else: + _login_button.text = "LOG IN" + func _on_secret_button_pressed(): get_tree().change_scene_to_file("uid://q4abhlwqdvay") diff --git a/game/scenes/UI/start_screen.tscn b/game/scenes/UI/start_screen.tscn index 4bd9f47..6cc27e5 100644 --- a/game/scenes/UI/start_screen.tscn +++ b/game/scenes/UI/start_screen.tscn @@ -1,74 +1,74 @@ -[gd_scene load_steps=5 format=3 uid="uid://b4k81taauef4q"] - -[ext_resource type="Script" uid="uid://cc8lskf7y74kh" path="res://scenes/UI/start_screen.gd" id="1_o7i0r"] -[ext_resource type="Theme" uid="uid://wpxmub0n2dr3" path="res://themes/button_theme.tres" id="1_tx5wa"] -[ext_resource type="Texture2D" uid="uid://dhuosr0p605gj" path="res://assets/images/pp_start_bg.png" id="2_r2jwc"] -[ext_resource type="Theme" uid="uid://tn8qndst18d6" path="res://themes/title_font_theme.tres" id="4_hm208"] - -[node name="StartScreen" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1_o7i0r") - -[node name="TextureRect" type="TextureRect" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -texture = ExtResource("2_r2jwc") - -[node name="MarginContainer" type="MarginContainer" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -theme_override_constants/margin_left = 10 -theme_override_constants/margin_top = 10 -theme_override_constants/margin_right = 10 -theme_override_constants/margin_bottom = 10 - -[node name="CenterContainer" type="CenterContainer" parent="MarginContainer"] -layout_mode = 2 - -[node name="ContentVBox" type="VBoxContainer" parent="MarginContainer/CenterContainer"] -layout_mode = 2 -size_flags_horizontal = 4 -size_flags_vertical = 8 -theme_override_constants/separation = 10 - -[node name="Label" type="Label" parent="MarginContainer/CenterContainer/ContentVBox"] -layout_mode = 2 -size_flags_horizontal = 4 -theme = ExtResource("4_hm208") -text = "PROJECT -PROMISCUOUS" -horizontal_alignment = 1 - -[node name="TitleSpacer" type="Control" parent="MarginContainer/CenterContainer/ContentVBox"] -custom_minimum_size = Vector2(0, 40) -layout_mode = 2 - -[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/CenterContainer/ContentVBox"] -layout_mode = 2 -size_flags_horizontal = 4 -size_flags_vertical = 8 -theme_override_constants/separation = 6 - -[node name="LogInButton" type="Button" parent="MarginContainer/CenterContainer/ContentVBox/VBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 4 -size_flags_vertical = 4 -theme = ExtResource("1_tx5wa") -text = "LOG IN" - +[gd_scene load_steps=5 format=3 uid="uid://b4k81taauef4q"] + +[ext_resource type="Script" uid="uid://cc8lskf7y74kh" path="res://scenes/UI/start_screen.gd" id="1_o7i0r"] +[ext_resource type="Theme" uid="uid://wpxmub0n2dr3" path="res://themes/button_theme.tres" id="1_tx5wa"] +[ext_resource type="Texture2D" uid="uid://dhuosr0p605gj" path="res://assets/images/pp_start_bg.png" id="2_r2jwc"] +[ext_resource type="Theme" uid="uid://tn8qndst18d6" path="res://themes/title_font_theme.tres" id="4_hm208"] + +[node name="StartScreen" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_o7i0r") + +[node name="TextureRect" type="TextureRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("2_r2jwc") + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="CenterContainer" type="CenterContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="ContentVBox" type="VBoxContainer" parent="MarginContainer/CenterContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 8 +theme_override_constants/separation = 10 + +[node name="Label" type="Label" parent="MarginContainer/CenterContainer/ContentVBox"] +layout_mode = 2 +size_flags_horizontal = 4 +theme = ExtResource("4_hm208") +text = "PROJECT +PROMISCUOUS" +horizontal_alignment = 1 + +[node name="TitleSpacer" type="Control" parent="MarginContainer/CenterContainer/ContentVBox"] +custom_minimum_size = Vector2(0, 40) +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/CenterContainer/ContentVBox"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 8 +theme_override_constants/separation = 6 + +[node name="LogInButton" type="Button" parent="MarginContainer/CenterContainer/ContentVBox/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +theme = ExtResource("1_tx5wa") +text = "LOG IN" + [node name="StartButton" type="Button" parent="MarginContainer/CenterContainer/ContentVBox/VBoxContainer"] layout_mode = 2 size_flags_horizontal = 4 @@ -89,29 +89,29 @@ size_flags_horizontal = 4 size_flags_vertical = 4 theme = ExtResource("1_tx5wa") text = "SETTINGS" - -[node name="QuitButton" type="Button" parent="MarginContainer/CenterContainer/ContentVBox/VBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 4 -size_flags_vertical = 4 -theme = ExtResource("1_tx5wa") -text = "QUIT" - -[node name="SecretButton" type="Button" parent="."] -show_behind_parent = true -layout_mode = 0 -offset_left = 840.0 -offset_top = 142.0 -offset_right = 856.0 -offset_bottom = 159.0 - -[node name="LogoutRequest" type="HTTPRequest" parent="."] -unique_name_in_owner = true - + +[node name="QuitButton" type="Button" parent="MarginContainer/CenterContainer/ContentVBox/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +theme = ExtResource("1_tx5wa") +text = "QUIT" + +[node name="SecretButton" type="Button" parent="."] +show_behind_parent = true +layout_mode = 0 +offset_left = 840.0 +offset_top = 142.0 +offset_right = 856.0 +offset_bottom = 159.0 + +[node name="LogoutRequest" type="HTTPRequest" parent="."] +unique_name_in_owner = true + [connection signal="pressed" from="MarginContainer/CenterContainer/ContentVBox/VBoxContainer/LogInButton" to="." method="_on_log_in_button_pressed"] [connection signal="pressed" from="MarginContainer/CenterContainer/ContentVBox/VBoxContainer/StartButton" to="." method="_on_start_button_pressed"] [connection signal="pressed" from="MarginContainer/CenterContainer/ContentVBox/VBoxContainer/PlaygroundButton" to="." method="_on_playground_button_pressed"] [connection signal="pressed" from="MarginContainer/CenterContainer/ContentVBox/VBoxContainer/SettingsButton" to="." method="_on_settings_button_pressed"] [connection signal="pressed" from="MarginContainer/CenterContainer/ContentVBox/VBoxContainer/QuitButton" to="." method="_on_quit_button_pressed"] -[connection signal="pressed" from="SecretButton" to="." method="_on_secret_button_pressed"] -[connection signal="request_completed" from="LogoutRequest" to="." method="_on_logout_request_completed"] +[connection signal="pressed" from="SecretButton" to="." method="_on_secret_button_pressed"] +[connection signal="request_completed" from="LogoutRequest" to="." method="_on_logout_request_completed"] diff --git a/game/themes/button_theme.tres b/game/themes/button_theme.tres index 49b097a..183213e 100644 --- a/game/themes/button_theme.tres +++ b/game/themes/button_theme.tres @@ -1,57 +1,16 @@ -[gd_resource type="Theme" load_steps=11 format=3 uid="uid://wpxmub0n2dr3"] +[gd_resource type="Theme" format=3 uid="uid://wpxmub0n2dr3"] -[ext_resource type="FontFile" path="res://assets/ui/kenney_ui_pack/Font/Kenney Future.ttf" id="1_font"] -[ext_resource type="Texture2D" path="res://assets/ui/kenney_ui_pack/PNG/Green/Default/button_rectangle_depth_flat.png" id="2_normal"] -[ext_resource type="Texture2D" path="res://assets/ui/kenney_ui_pack/PNG/Green/Default/button_rectangle_depth_gloss.png" id="3_hover"] -[ext_resource type="Texture2D" path="res://assets/ui/kenney_ui_pack/PNG/Green/Double/button_rectangle_depth_flat.png" id="4_pressed"] -[ext_resource type="Texture2D" path="res://assets/ui/kenney_ui_pack/PNG/Grey/Default/button_rectangle_depth_flat.png" id="5_disabled"] - -[sub_resource type="StyleBoxTexture" id="1_style_normal"] -texture = ExtResource("2_normal") -texture_margin_left = 16.0 -texture_margin_top = 16.0 -texture_margin_right = 16.0 -texture_margin_bottom = 16.0 -expand_margin_left = 4.0 -expand_margin_top = 4.0 -expand_margin_right = 4.0 -expand_margin_bottom = 4.0 -content_margin_left = 24.0 -content_margin_top = 14.0 -content_margin_right = 24.0 -content_margin_bottom = 14.0 - -[sub_resource type="StyleBoxTexture" id="2_style_hover"] -texture = ExtResource("3_hover") -texture_margin_left = 16.0 -texture_margin_top = 16.0 -texture_margin_right = 16.0 -texture_margin_bottom = 16.0 -expand_margin_left = 4.0 -expand_margin_top = 4.0 -expand_margin_right = 4.0 -expand_margin_bottom = 4.0 -content_margin_left = 24.0 -content_margin_top = 14.0 -content_margin_right = 24.0 -content_margin_bottom = 14.0 - -[sub_resource type="StyleBoxTexture" id="3_style_pressed"] -texture = ExtResource("4_pressed") -texture_margin_left = 16.0 -texture_margin_top = 16.0 -texture_margin_right = 16.0 -texture_margin_bottom = 16.0 -expand_margin_left = 4.0 -expand_margin_top = 4.0 -expand_margin_right = 4.0 -expand_margin_bottom = 4.0 -content_margin_left = 24.0 -content_margin_top = 16.0 -content_margin_right = 24.0 -content_margin_bottom = 12.0 +[ext_resource type="FontFile" uid="uid://bcyh4kjfid1q8" path="res://assets/ui/kenney_ui_pack/Font/Kenney Future.ttf" id="1_font"] +[ext_resource type="Texture2D" uid="uid://k8kqflfhia0n" path="res://assets/ui/kenney_ui_pack/PNG/Green/Default/button_rectangle_depth_flat.png" id="2_normal"] +[ext_resource type="Texture2D" uid="uid://dwox0g5c5q6wv" path="res://assets/ui/kenney_ui_pack/PNG/Green/Default/button_rectangle_depth_gloss.png" id="3_hover"] +[ext_resource type="Texture2D" uid="uid://i35jl23ui8og" path="res://assets/ui/kenney_ui_pack/PNG/Green/Double/button_rectangle_depth_flat.png" id="4_pressed"] +[ext_resource type="Texture2D" uid="uid://do3y2npj7u427" path="res://assets/ui/kenney_ui_pack/PNG/Grey/Default/button_rectangle_depth_flat.png" id="5_disabled"] [sub_resource type="StyleBoxTexture" id="4_style_disabled"] +content_margin_left = 24.0 +content_margin_top = 14.0 +content_margin_right = 24.0 +content_margin_bottom = 14.0 texture = ExtResource("5_disabled") texture_margin_left = 16.0 texture_margin_top = 16.0 @@ -61,12 +20,12 @@ expand_margin_left = 4.0 expand_margin_top = 4.0 expand_margin_right = 4.0 expand_margin_bottom = 4.0 + +[sub_resource type="StyleBoxTexture" id="5_style_focus"] content_margin_left = 24.0 content_margin_top = 14.0 content_margin_right = 24.0 content_margin_bottom = 14.0 - -[sub_resource type="StyleBoxTexture" id="5_style_focus"] texture = ExtResource("3_hover") texture_margin_left = 16.0 texture_margin_top = 16.0 @@ -76,10 +35,51 @@ expand_margin_left = 6.0 expand_margin_top = 6.0 expand_margin_right = 6.0 expand_margin_bottom = 6.0 + +[sub_resource type="StyleBoxTexture" id="2_style_hover"] content_margin_left = 24.0 content_margin_top = 14.0 content_margin_right = 24.0 content_margin_bottom = 14.0 +texture = ExtResource("3_hover") +texture_margin_left = 16.0 +texture_margin_top = 16.0 +texture_margin_right = 16.0 +texture_margin_bottom = 16.0 +expand_margin_left = 4.0 +expand_margin_top = 4.0 +expand_margin_right = 4.0 +expand_margin_bottom = 4.0 + +[sub_resource type="StyleBoxTexture" id="1_style_normal"] +content_margin_left = 24.0 +content_margin_top = 14.0 +content_margin_right = 24.0 +content_margin_bottom = 14.0 +texture = ExtResource("2_normal") +texture_margin_left = 16.0 +texture_margin_top = 16.0 +texture_margin_right = 16.0 +texture_margin_bottom = 16.0 +expand_margin_left = 4.0 +expand_margin_top = 4.0 +expand_margin_right = 4.0 +expand_margin_bottom = 4.0 + +[sub_resource type="StyleBoxTexture" id="3_style_pressed"] +content_margin_left = 24.0 +content_margin_top = 16.0 +content_margin_right = 24.0 +content_margin_bottom = 12.0 +texture = ExtResource("4_pressed") +texture_margin_left = 16.0 +texture_margin_top = 16.0 +texture_margin_right = 16.0 +texture_margin_bottom = 16.0 +expand_margin_left = 4.0 +expand_margin_top = 4.0 +expand_margin_right = 4.0 +expand_margin_bottom = 4.0 [resource] Button/colors/font_color = Color(0.098, 0.161, 0.047, 1)