Skip to content

Commit d0f3687

Browse files
Added animated focus outline, titles to option sections and improved btn navigation (#191)
* Button hover state theme is now unique * Add focus outline manager (WIP) * Stop relying on Godot built in theme / manual node * Only show outline on keyboard or gamepad * Do not initially show focus outline on scene change * Manually try to fix options btn navigation * Fix many btn nav errors through script * Added scripted title to options
1 parent b468c26 commit d0f3687

20 files changed

+391
-146
lines changed

Framework/Autoloads/Autoloads.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ public partial class Autoloads : Node
2222

2323
public static Autoloads Instance { get; private set; }
2424

25-
public ComponentManager ComponentManager { get; private set; } // Cannot use [Export] here because Godot will bug out and unlink export path in editor after setup completes and restarts the editor
26-
public GameConsole GameConsole { get; private set; } // Cannot use [Export] here because Godot will bug out and unlink export path in editor after setup completes and restarts the editor
27-
public AudioManager AudioManager { get; private set; }
28-
public OptionsManager OptionsManager { get; private set; }
29-
public Services Services { get; private set; }
30-
public MetricsOverlay MetricsOverlay { get; private set; }
31-
public SceneManager SceneManager { get; private set; }
32-
public Profiler Profiler { get; private set; }
25+
public ComponentManager ComponentManager { get; private set; } // Cannot use [Export] here because Godot will bug out and unlink export path in editor after setup completes and restarts the editor
26+
public GameConsole GameConsole { get; private set; } // Cannot use [Export] here because Godot will bug out and unlink export path in editor after setup completes and restarts the editor
27+
public AudioManager AudioManager { get; private set; }
28+
public OptionsManager OptionsManager { get; private set; }
29+
public Services Services { get; private set; }
30+
public MetricsOverlay MetricsOverlay { get; private set; }
31+
public SceneManager SceneManager { get; private set; }
32+
public Profiler Profiler { get; private set; }
33+
public FocusOutlineManager FocusOutline { get; private set; }
3334

3435
#if NETCODE_ENABLED
3536
public Logger Logger { get; private set; }
@@ -51,6 +52,7 @@ public override void _EnterTree()
5152
MetricsOverlay = new MetricsOverlay();
5253
Profiler = new Profiler();
5354
GameConsole = GetNode<GameConsole>("%Console");
55+
FocusOutline = new FocusOutlineManager(this);
5456

5557
#if NETCODE_ENABLED
5658
Logger = new Logger(GameConsole);

Framework/Autoloads/Autoloads.tscn

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[gd_scene load_steps=10 format=3 uid="uid://cj4fbh1a1lpq4"]
1+
[gd_scene load_steps=11 format=3 uid="uid://cj4fbh1a1lpq4"]
22

33
[ext_resource type="Script" uid="uid://cdt2k6s3xm13g" path="res://Framework/Autoloads/Autoloads.cs" id="1_00yjk"]
44
[ext_resource type="PackedScene" uid="uid://rbcqvr4snrvn" path="res://Framework/Scenes/MenuUI/Credits/Credits.tscn" id="2_xdmsn"]
@@ -8,6 +8,7 @@
88
[ext_resource type="PackedScene" uid="uid://d1jo48n2hdkih" path="res://Framework/ModLoader/ModLoader.tscn" id="4_ems5f"]
99
[ext_resource type="PackedScene" uid="uid://7tfets4irkba" path="res://Framework/Scenes/Options/Options.tscn" id="5_vm4c5"]
1010
[ext_resource type="Script" uid="uid://17yxgcswri77" path="res://Framework/Scenes/MenuScenes.cs" id="6_2fq88"]
11+
[ext_resource type="Texture2D" uid="uid://djggjhepn0bsf" path="res://Framework/Theme/CornerDashOutline.png" id="9_3cpyl"]
1112

1213
[sub_resource type="Resource" id="Resource_xdmsn"]
1314
script = ExtResource("6_2fq88")
@@ -17,12 +18,10 @@ Options = ExtResource("5_vm4c5")
1718
Credits = ExtResource("2_xdmsn")
1819
metadata/_custom_type_script = "uid://17yxgcswri77"
1920

20-
[node name="Autoloads" type="Node" node_paths=PackedStringArray("GameConsole", "ComponentManager")]
21+
[node name="Autoloads" type="Node"]
2122
process_mode = 3
2223
script = ExtResource("1_00yjk")
2324
_scenes = SubResource("Resource_xdmsn")
24-
GameConsole = NodePath("Debug/Console")
25-
ComponentManager = NodePath("ComponentManager")
2625

2726
[node name="ComponentManager" type="Node" parent="."]
2827
process_mode = 1
@@ -33,3 +32,13 @@ layer = 128
3332

3433
[node name="Console" parent="Debug" instance=ExtResource("4_8po21")]
3534
unique_name_in_owner = true
35+
36+
[node name="CornerDashOutline" type="NinePatchRect" parent="."]
37+
z_index = 1
38+
offset_right = 40.0
39+
offset_bottom = 40.0
40+
texture = ExtResource("9_3cpyl")
41+
patch_margin_left = 8
42+
patch_margin_top = 8
43+
patch_margin_right = 8
44+
patch_margin_bottom = 8

Framework/Autoloads/SceneManager.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ namespace __TEMPLATE__;
88
// About Scene Switching: https://docs.godotengine.org/en/latest/tutorials/scripting/singletons_autoload.html
99
public class SceneManager
1010
{
11-
/// <summary>
12-
/// The event is invoked right before the scene is changed
13-
/// </summary>
1411
public event Action<string> PreSceneChanged;
12+
public event Action<string> PostSceneChanged;
1513

1614
public const int DefaultSceneFadeDuration = 2;
1715

@@ -55,6 +53,8 @@ public void SwitchTo(PackedScene scene, TransType transType = TransType.None)
5553
FadeTo(TransColor.Black, DefaultSceneFadeDuration, () => ChangeScene(path, transType));
5654
break;
5755
}
56+
57+
PostSceneChanged?.Invoke(path);
5858
}
5959

6060
/// <summary>
@@ -71,6 +71,8 @@ public void ResetCurrentScene()
7171

7272
// Wait for engine to be ready before switching scenes
7373
_autoloads.CallDeferred(nameof(Autoloads.DeferredSwitchSceneProxy), sceneFilePath, Variant.From(TransType.None));
74+
75+
PostSceneChanged?.Invoke(sceneName);
7476
}
7577

7678
public void DeferredSwitchScene(string rawName, Variant transTypeVariant)

Framework/Game.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ private static T IsAutoloadsSetup<T>(Func<Autoloads, T> getPropertyFrom, string
3434
return getPropertyFrom(autoloads)!; // Assumes the field may be null, but we are not checking it here
3535
}
3636

37+
public static FocusOutlineManager FocusOutline => IsAutoloadsSetup(a => a.FocusOutline, nameof(FocusOutline));
3738
public static MetricsOverlay Metrics => IsAutoloadsSetup(a => a.MetricsOverlay, nameof(Metrics));
3839
public static OptionsManager Options => IsAutoloadsSetup(a => a.OptionsManager, nameof(Options));
3940
public static AudioManager Audio => IsAutoloadsSetup(a => a.AudioManager, nameof(Audio));
@@ -44,13 +45,14 @@ private static T IsAutoloadsSetup<T>(Func<Autoloads, T> getPropertyFrom, string
4445
public static Logger Logger => IsAutoloadsSetup(a => a.Logger, nameof(Logger));
4546
#else
4647
// The games release will not have the slow debugging checks
47-
public static MetricsOverlay Metrics => Autoloads.Instance.MetricsOverlay;
48-
public static OptionsManager Options => Autoloads.Instance.OptionsManager;
49-
public static AudioManager Audio => Autoloads.Instance.AudioManager;
50-
public static SceneManager Scene => Autoloads.Instance.SceneManager;
51-
public static GameConsole Console => Autoloads.Instance.GameConsole;
52-
public static Profiler Profiler => Autoloads.Instance.Profiler;
53-
public static Services Services => Autoloads.Instance.Services;
54-
public static Logger Logger => Autoloads.Instance.Logger;
48+
public static FocusOutlineManager FocusOutline => Autoloads.Instance.FocusOutline;
49+
public static MetricsOverlay Metrics => Autoloads.Instance.MetricsOverlay;
50+
public static OptionsManager Options => Autoloads.Instance.OptionsManager;
51+
public static AudioManager Audio => Autoloads.Instance.AudioManager;
52+
public static SceneManager Scene => Autoloads.Instance.SceneManager;
53+
public static GameConsole Console => Autoloads.Instance.GameConsole;
54+
public static Profiler Profiler => Autoloads.Instance.Profiler;
55+
public static Services Services => Autoloads.Instance.Services;
56+
public static Logger Logger => Autoloads.Instance.Logger;
5557
#endif
56-
}
58+
}

Framework/Scenes/MainMenuNav.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public partial class MainMenuNav : Node
1111
public override void _Ready()
1212
{
1313
_scene = Game.Scene;
14+
Game.FocusOutline.IgnoreNextFocus();
1415
GetNode<Button>("Play").GrabFocus();
1516
}
1617

Framework/Scenes/MenuUI/MainMenu/MainMenu.tscn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
[ext_resource type="PackedScene" uid="uid://djhd6uw7l1ok" path="res://Level.tscn" id="3_xo0to"]
44
[ext_resource type="Script" uid="uid://bi551lrt82awu" path="res://Framework/Scenes/MainMenuNav.cs" id="5_sc4as"]
55

6-
76
[node name="Main Menu" type="PanelContainer"]
87
anchors_preset = 15
98
anchor_right = 1.0
@@ -43,6 +42,7 @@ text = "CREDITS"
4342
[node name="Quit" type="Button" parent="Nav"]
4443
custom_minimum_size = Vector2(175, 60)
4544
layout_mode = 2
45+
focus_neighbor_bottom = NodePath("../../Socials/HBox/Discord")
4646
text = "QUIT"
4747

4848
[node name="Socials" type="MarginContainer" parent="."]

Framework/Scenes/Options/Options.cs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,15 @@ public partial class Options : PanelContainer
1212
private OptionsAudio _optionsAudio;
1313
private OptionsInput _optionsInput;
1414

15-
public override void _EnterTree()
16-
{
17-
_optionsNav = new OptionsNav(this);
18-
_optionsGeneral = new OptionsGeneral(this);
19-
_optionsGameplay = new OptionsGameplay(this);
20-
_optionsDisplay = new OptionsDisplay(this);
21-
_optionsGraphics = new OptionsGraphics(this);
22-
_optionsAudio = new OptionsAudio(this);
23-
_optionsInput = new OptionsInput(this);
24-
}
25-
2615
public override void _Ready()
2716
{
28-
_optionsNav.Initialize();
29-
_optionsGeneral.Initialize();
30-
_optionsGameplay.Initialize();
31-
_optionsDisplay.Initialize();
32-
_optionsGraphics.Initialize();
33-
_optionsAudio.Initialize();
34-
_optionsInput.Initialize();
17+
_optionsNav = new OptionsNav(this, GetNode<Label>("%Title"));
18+
_optionsGeneral = new OptionsGeneral(this, _optionsNav.GeneralButton);
19+
_optionsGameplay = new OptionsGameplay(this, _optionsNav.GameplayButton);
20+
_optionsDisplay = new OptionsDisplay(this, _optionsNav.DisplayButton);
21+
_optionsGraphics = new OptionsGraphics(this, _optionsNav.GraphicsButton);
22+
_optionsAudio = new OptionsAudio(this);
23+
_optionsInput = new OptionsInput(this, _optionsNav.InputButton);
3524
}
3625

3726
public override void _Input(InputEvent @event)

0 commit comments

Comments
 (0)