full gamepad support

This commit is contained in:
Rendo 2025-07-28 18:03:26 +05:00
commit a57d79e84a
21 changed files with 213 additions and 46 deletions

View file

@ -35,9 +35,13 @@ public partial class Cursor : Node2D
case CursorMode.Mouse:
break;
case CursorMode.Gamepad:
if (GamepadHandler.Instance.IsGamepadControlled == false) return;
var vector = Input.GetVector("cursor_left", "cursor_right", "cursor_up", "cursor_down");
var set_position = GetGlobalMousePosition() + vector * (float)delta * sensitivity;
if (vector == Vector2.Zero) return;
var set_position = GetGlobalMousePosition() + vector * (float)delta * sensitivity / (float)Engine.TimeScale;
GetViewport().WarpMouse(GetGlobalTransformWithCanvas() * set_position);
break;

View file

@ -6,13 +6,23 @@ namespace Newlon.Components.Droppables;
public partial class DroppableItem : Area2D
{
[Signal] public delegate void PickedUpEventHandler();
public override void _MouseEnter()
{
if (GamepadHandler.Instance.IsGamepadControlled)
{
GetViewport().SetInputAsHandled();
PickUp();
EmitSignal(SignalName.PickedUp);
}
}
public override void _InputEvent(Viewport viewport, InputEvent @event, int shapeIdx)
{
if (@event.IsActionPressed("primary_action"))
{
GetViewport().SetInputAsHandled();
PickUp();
EmitSignal(SignalName.PickedUp);
EmitSignal(SignalName.PickedUp);
}
}
public virtual void PickUp() {}

View file

@ -181,6 +181,7 @@ public partial class Entity : Node2D
if (_activeEffectSlots[slot] != null)
{
_activeEffectSlots[slot].Exit(this);
_effectSlotTimers[slot].Stop();
_activeEffectSlots[slot] = null;
}
}

View file

@ -4,48 +4,39 @@ using System;
public partial class GamepadHandler : Node
{
[Signal] public delegate void GamepadControlledEventHandler(bool isControlled);
public static GamepadHandler Instance { get; private set; }
public int CurrentDevice { get; private set; } = 0;
public bool IsGamepadControlled => focused && controlled;
private bool focused;
public bool IsGamepadControlled => controlled;
private bool controlled;
public override void _EnterTree()
{
Instance = this;
}
public override void _Notification(int what)
{
if (what == NotificationApplicationFocusIn)
{
focused = true;
}
if (what == NotificationApplicationFocusOut)
{
focused = false;
}
}
public override void _Input(InputEvent @event)
{
if (@event is InputEventJoypadButton || @event is InputEventJoypadMotion)
{
SetControlled(true);
}
if ((@event is InputEventMouse && Input.GetVector("cursor_left", "cursor_right", "cursor_up", "cursor_down") == Vector2.Zero) || @event is InputEventKey)
else if (@event is InputEventMouseButton || @event is InputEventKey)
{
SetControlled(false);
}
}
private void SetControlled(bool to)
{
if (controlled == to) return;
controlled = to;
if (controlled)
{
Cursor.Mode = Cursor.CursorMode.Gamepad;
EmitSignal(SignalName.GamepadControlled, true);
}
else
{
Cursor.Mode = Cursor.CursorMode.Mouse;
EmitSignal(SignalName.GamepadControlled, false);
}
}

View file

@ -11,7 +11,7 @@ public partial class LevelGUIElements : Control
public HBoxContainer SeedpacketsHotbar;
[Export]
public SunCounter SunCounter;
public override void _Ready()
public override void _EnterTree()
{
Instance = this;
}

View file

@ -0,0 +1,62 @@
using Godot;
using System;
public partial class CYSFocusSetup : Node
{
[Export] private GridContainer grid;
[Export] private Button button;
[Export] private ScrollContainer textContainer;
public override void _Ready()
{
for (int i = 0; i < grid.GetChildCount(); i++)
{
int x = i % grid.Columns;
int y = i / grid.Columns;
Control control = grid.GetChild<Control>(i);
// If it isn't leftmost element
if (x != 0)
{
control.FocusNeighborLeft = control.GetPathTo(grid.GetChild(PositionToIndex(x - 1, y)));
}
// If it isn't upmost element
if (y != 0)
{
control.FocusNeighborTop = control.GetPathTo(grid.GetChild(PositionToIndex(x, y - 1)));
}
else
{
control.FocusNeighborTop = control.GetPathTo(textContainer);
}
// If it isn't rightmost element
if (x != grid.Columns - 1 && i != grid.GetChildCount())
{
control.FocusNeighborRight = control.GetPathTo(grid.GetChild(PositionToIndex(x + 1, y)));
}
else
{
if (y != 0)
{
control.FocusNeighborRight = control.GetPathTo(grid.GetChild(PositionToIndex(x + 1, y - 1)));
}
else
{
control.FocusNeighborRight = control.GetPathTo(button);
}
}
if (PositionToIndex(x, y + 1) < grid.GetChildCount())
{
control.FocusNeighborBottom = control.GetPathTo(grid.GetChild(PositionToIndex(x, y + 1)));
}
}
QueueFree();
}
private int PositionToIndex(int x, int y)
{
return y * grid.Columns + x;
}
}

View file

@ -0,0 +1 @@
uid://bksslrqq5vhm3

View file

@ -0,0 +1,17 @@
using Godot;
using Newlon.Components;
using Newlon.Components.GUI.Seedpackets;
public partial class CYSResetButton : Button
{
public override void _Pressed()
{
foreach (Seedpacket packet in LevelGUIElements.Instance.SeedpacketsHotbar.GetChildren())
{
packet._Pressed();
packet.EmitSignal(Seedpacket.SignalName.Pressed);
}
GrabFocus();
}
}

View file

@ -0,0 +1 @@
uid://diwjgekhvn017

View file

@ -0,0 +1,15 @@
using Godot;
using System;
public partial class PM_GamepadFocus : Node
{
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
}
}

View file

@ -0,0 +1 @@
uid://cc8loabsf43m0

View file

@ -8,9 +8,11 @@ public partial class PauseMenu : Control
private bool previousPaused;
private bool currently_paused = false;
private AudioStream pauseSound = ResourceLoader.Load<AudioStream>("uid://ckja8ym50y0d4");
public override void _Ready()
private Control stolenFocus;
public override void _Ready()
{
Instance = this;
GetViewport().GuiFocusChanged += OnFocusChanged;
}
public void Continue()
@ -18,6 +20,7 @@ public partial class PauseMenu : Control
GetParent<Control>().Visible = false;
GetTree().Paused = previousPaused;
currently_paused = false;
stolenFocus.GrabFocus();
}
public void Restart()
{
@ -36,10 +39,22 @@ public partial class PauseMenu : Control
{
return;
}
Instance.currently_paused = true;
Instance.GetNode<Control>("%ContinueButton").GrabFocus();
Instance.GetParent<Control>().Visible = true;
Instance.previousPaused = Instance.GetTree().Paused;
Instance.GetTree().Paused = true;
Instance.currently_paused = true;
AudioSequencer.Play("pause",Instance.pauseSound);
AudioSequencer.Play("pause", Instance.pauseSound);
}
public override void _ExitTree()
{
GetViewport().GuiFocusChanged -= OnFocusChanged;
}
public void OnFocusChanged(Control to)
{
if (currently_paused) return;
stolenFocus = to;
}
}