Gamepad support

This commit is contained in:
Rendo 2025-07-28 05:07:37 +05:00
commit ed369cf718
24 changed files with 240 additions and 78 deletions

View file

@ -1,50 +1,52 @@
using Godot;
using Newlon.Components.Level;
namespace Newlon;
public partial class Cursor : Node
public partial class Cursor : Node2D
{
public static Cursor Instance { get; private set; }
#region Textures
private readonly Texture2D defaultArrow = ResourceLoader.Load<Texture2D>("uid://c20dwjohaljdk");
private readonly Texture2D defaultPoint = ResourceLoader.Load<Texture2D>("uid://cw0rqtl8ulndd");
private readonly Texture2D shovelArrow = ResourceLoader.Load<Texture2D>("uid://dq375kjjo17g2");
private readonly Texture2D plantArrow = ResourceLoader.Load<Texture2D>("uid://dx123mhv4oee");
#endregion
public static Cursor Instance { get; private set; }
public bool shovel = false;
public bool plant = false;
public static CursorMode Mode = CursorMode.Mouse;
private float sensitivity = 200.0f;
public override void _Ready()
public enum CursorMode
{
Mouse,
Gamepad
}
public override void _EnterTree()
{
Instance = this;
SetDefaultCursor();
}
public void UpdateCursor()
public override void _Process(double delta)
{
if (shovel)
switch (Mode)
{
SetShovelCursor();
return;
case CursorMode.Mouse:
break;
case CursorMode.Gamepad:
var vector = Input.GetVector("cursor_left", "cursor_right", "cursor_up", "cursor_down");
var set_position = GetGlobalMousePosition() + vector * (float)delta * sensitivity;
GetViewport().WarpMouse(GetGlobalTransformWithCanvas() * set_position);
break;
}
if (plant)
{
SetPlantCursor();
return;
}
SetDefaultCursor() ;
}
public void SetDefaultCursor()
}
public static Vector2 GetCursorPosition()
{
Input.SetCustomMouseCursor(ResourceLoader.Load<Texture2D>("res://assets/sprites/atlases/cursor/default_arrow.png"),shape:Input.CursorShape.Arrow);
Input.SetCustomMouseCursor(ResourceLoader.Load<Texture2D>("res://assets/sprites/atlases/cursor/default_point.png"),shape:Input.CursorShape.PointingHand);
}
public void SetPlantCursor()
{
Input.SetCustomMouseCursor(ResourceLoader.Load<Texture2D>("res://assets/sprites/atlases/cursor/plant_arrow.png"));
}
public void SetShovelCursor()
{
Input.SetCustomMouseCursor(ResourceLoader.Load<Texture2D>("res://assets/sprites/atlases/cursor/shovel_arrow.png"));
return Instance.GetGlobalMousePosition();
}
}

View file

@ -29,7 +29,7 @@ public partial class SnipachBehaviour : BaseBehaviour
{
if (dragging)
{
attackBox.GlobalPosition = (attackBox.GetGlobalMousePosition() / FieldParams.Tile).Ceil() * FieldParams.Tile - new Vector2(20, 14);
attackBox.GlobalPosition = (Cursor.GetCursorPosition() / FieldParams.Tile).Ceil() * FieldParams.Tile - new Vector2(20, 14);
}
}

View file

@ -0,0 +1,10 @@
using Godot;
using System;
public partial class ExplosionVibration : Node
{
public override void _EnterTree()
{
Input.StartJoyVibration(GamepadHandler.Instance.CurrentDevice, 0, 1,0.25f);
}
}

View file

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

View file

@ -0,0 +1,52 @@
using Godot;
using Newlon;
using System;
public partial class GamepadHandler : Node
{
public static GamepadHandler Instance { get; private set; }
public int CurrentDevice { get; private set; } = 0;
public bool IsGamepadControlled => focused && controlled;
private bool focused;
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)
{
SetControlled(false);
}
}
private void SetControlled(bool to)
{
controlled = to;
if (controlled)
{
Cursor.Mode = Cursor.CursorMode.Gamepad;
}
else
{
Cursor.Mode = Cursor.CursorMode.Mouse;
}
}
}

View file

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

View file

@ -29,7 +29,6 @@ public partial class ShovelButton : TextureButton
public override void _Toggled(bool toggledOn)
{
Cursor.Instance.shovel = toggledOn;
Cursor.Instance.UpdateCursor();
}
public override void _Input(InputEvent @event)
@ -68,7 +67,7 @@ public partial class ShovelButton : TextureButton
if (ButtonPressed)
{
var gridEntity = GetTile(PoolContainer.Instance.Plants.GetGlobalMousePosition());
var gridEntity = GetTile(Cursor.GetCursorPosition());
if (TrySetGridEntity(gridEntity)) return;
if (TrySetDynEntity()) return;
@ -129,7 +128,7 @@ public partial class ShovelButton : TextureButton
}
private bool TrySetDynEntity()
{
raycast.GlobalPosition = PoolContainer.Instance.GetGlobalMousePosition();
raycast.GlobalPosition = Cursor.GetCursorPosition();
if (raycast.IsColliding())
{

View file

@ -22,9 +22,11 @@ public partial class GridLoader : GridContainer
Seedpacket slot = _plantCard.Instantiate<Seedpacket>();
AddChild(slot);
slot.SetResource(resource);
slot.SetForbidden(RuntimeLevelData.LevelResource.forbiddenPlants.Contains(resource.internal_id));
slot.SetLocked(PlayerProgress.Instance.PlayerPlants.Contains(resource) == false);
if (GetChildCount() == 1) slot.GrabFocus();
var handler = new ChoosableHandler(slot);
slot.SetHandler(handler);
}

View file

@ -1,4 +1,5 @@
using Godot;
using Newlon.Components.GUI.Seedpackets;
using Newlon.Components.Level;
namespace Newlon.Components.GUI;
@ -8,5 +9,6 @@ public partial class LevelRunButton : Button
public override void _Pressed()
{
RuntimeLevelData.Instance.SetLevelState(RuntimeLevelData.LevelStates.Pregame);
LevelGUIElements.Instance.SeedpacketsHotbar.GetChild<Seedpacket>(0).GrabFocus();
}
}

View file

@ -1,5 +1,7 @@
extends Node
func _ready() -> void:
$InfoButtons/AboutButton.grab_focus()
func _on_play_button_pressed() -> void:
LevelController.call("StartLevel",preload("uid://dd3yegl1xo44m"),preload("uid://dwd5oqr0tuvhv"))

View file

@ -37,14 +37,6 @@ public partial class Seedpacket : TextureButton
public override void _Process(double delta)
{
Disabled = disablePacket || _timer.TimeLeft > 0;
if (Disabled)
{
FocusMode = FocusModeEnum.None;
}
else
{
FocusMode = FocusModeEnum.All;
}
if (_handler is ISeedpacketProcess processHandler) processHandler.Process();
}
public void SetResource(GridEntityResource resource)
@ -88,7 +80,6 @@ public partial class Seedpacket : TextureButton
public void Recharge()
{
_timer.Start();
ReleaseFocus();
}
public void OnUnfocused()

View file

@ -47,7 +47,7 @@ public partial class PlantField : Node2D
public override void _Process(double delta)
{
// Getting and storing global mouse position, setting plant-poiner to it
var mouse_pos = GetGlobalMousePosition();
var mouse_pos = Cursor.GetCursorPosition();
_plantSetter.GlobalPosition = mouse_pos;
// Getting position in grid coordinates
@ -74,7 +74,6 @@ public partial class PlantField : Node2D
Material.Set("shader_parameter/amount", 1);
}
Cursor.Instance.plant = canPlace;
Cursor.Instance.UpdateCursor();
}
_previousCanPlace = canPlace;
@ -86,7 +85,7 @@ public partial class PlantField : Node2D
{
if (@event.IsActionPressed("cancel_plant") && _slot != null)
{
_slot.ReleaseFocus();
ResetPlant();
}
if (@event.IsActionPressed("primary_action") && _previousCanPlace)
@ -106,6 +105,7 @@ public partial class PlantField : Node2D
// Unfocusing and recharging slot
_slot.Recharge();
ResetPlant();
}
}
}

View file

@ -8,11 +8,14 @@ public partial class StandardParticles : Node2D
private int counterMax = 0;
public override void _Ready()
{
foreach (GpuParticles2D emitter in GetChildren())
foreach (Node child in GetChildren())
{
emitter.Emitting = true;
counterMax += 1;
emitter.Finished += MarkForDestruction;
if (child is GpuParticles2D emitter)
{
emitter.Emitting = true;
counterMax += 1;
emitter.Finished += MarkForDestruction;
}
}
}
public void MarkForDestruction()