SudokuInput.cs
using Sandbox;
public sealed class SudokuInput : Component
{
public static bool Up;
public static bool Down;
public static bool Left;
public static bool Right;
public static bool Escape; // latched: stays true until SudokuGamePanel handles it
public static bool Erase;
public static int NumberPressed; // 0 = none, 1–9 = digit
float _lastEscape;
protected override void OnUpdate()
{
Up = Input.Keyboard.Pressed( "UPARROW" ) || Input.Keyboard.Pressed( "w" );
Down = Input.Keyboard.Pressed( "DOWNARROW" ) || Input.Keyboard.Pressed( "s" );
Left = Input.Keyboard.Pressed( "LEFTARROW" ) || Input.Keyboard.Pressed( "a" );
Right = Input.Keyboard.Pressed( "RIGHTARROW" ) || Input.Keyboard.Pressed( "d" );
// Number row 1–9 OR numpad KP_1–KP_9
NumberPressed = 0;
for ( int i = 0; i < 9; i++ )
{
string row = (i + 1).ToString();
string kp = $"KP_{i + 1}";
if ( Input.Keyboard.Pressed( row ) || Input.Keyboard.Pressed( kp ) )
{
NumberPressed = i + 1;
break;
}
}
// DEL or BACKSPACE to erase
Erase = Input.Keyboard.Pressed( "DEL" ) || Input.Keyboard.Pressed( "BACKSPACE" );
// Swallow Escape so the engine's pause menu stays shut, and latch it for the panel's own
// pause menu. Latching (instead of a one-frame flag) means component/panel update order
// can't make the press vanish. The short debounce stops both sources firing one press twice.
bool esc = Input.EscapePressed || Input.Keyboard.Pressed( "escape" );
if ( Input.EscapePressed ) Input.EscapePressed = false;
if ( esc && RealTime.Now - _lastEscape > 0.15f )
{
_lastEscape = RealTime.Now;
Escape = true;
}
}
}