WIP moving difficulty selection to engine

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-18 12:25:59 +01:00
parent 0f7c77e85a
commit e39dfd5da0
29 changed files with 1337 additions and 3360 deletions
@@ -0,0 +1,94 @@
import 'package:wolf_3d_dart/wolf_3d_data_types.dart';
import 'package:wolf_3d_dart/wolf_3d_engine.dart';
/// Handles menu-only input state such as selection movement and edge triggers.
class MenuManager {
int _selectedDifficultyIndex = 0;
bool _prevUp = false;
bool _prevDown = false;
bool _prevConfirm = false;
bool _prevBack = false;
/// Current selected difficulty row index.
int get selectedDifficultyIndex => _selectedDifficultyIndex;
/// Resets menu navigation state for a new difficulty selection flow.
void beginDifficultySelection({Difficulty? initialDifficulty}) {
_selectedDifficultyIndex = initialDifficulty == null
? 0
: Difficulty.values
.indexOf(initialDifficulty)
.clamp(
0,
Difficulty.values.length - 1,
);
_prevUp = false;
_prevDown = false;
_prevConfirm = false;
_prevBack = false;
}
/// Returns a menu action snapshot for this frame.
({Difficulty? selected, bool goBack}) updateDifficultySelection(
EngineInput input,
) {
final upNow = input.isMovingForward;
final downNow = input.isMovingBackward;
final confirmNow = input.isInteracting || input.isFiring;
final backNow = input.isBack;
if (upNow && !_prevUp) {
_selectedDifficultyIndex =
(_selectedDifficultyIndex - 1 + Difficulty.values.length) %
Difficulty.values.length;
}
if (downNow && !_prevDown) {
_selectedDifficultyIndex =
(_selectedDifficultyIndex + 1) % Difficulty.values.length;
}
// Pointer/touch selection for hosts that provide menu tap coordinates.
if (input.menuTapX != null && input.menuTapY != null) {
final x320 = (input.menuTapX!.clamp(0.0, 1.0) * 320).toDouble();
final y200 = (input.menuTapY!.clamp(0.0, 1.0) * 200).toDouble();
const panelX = 28.0;
const panelY = 70.0;
const panelW = 264.0;
const panelH = 82.0;
const rowYStart = 86.0;
const rowStep = 15.0;
if (x320 >= panelX &&
x320 <= panelX + panelW &&
y200 >= panelY &&
y200 <= panelY + panelH) {
final index = ((y200 - rowYStart + (rowStep / 2)) / rowStep).floor();
if (index >= 0 && index < Difficulty.values.length) {
_selectedDifficultyIndex = index;
return (selected: Difficulty.values[index], goBack: false);
}
}
}
Difficulty? selected;
if (confirmNow && !_prevConfirm) {
selected = Difficulty.values[_selectedDifficultyIndex];
}
final bool goBack = backNow && !_prevBack;
_prevUp = upNow;
_prevDown = downNow;
_prevConfirm = confirmNow;
_prevBack = backNow;
return (selected: selected, goBack: goBack);
}
/// Whether to show the alternate cursor frame at [elapsedMs].
bool isCursorAltFrame(int elapsedMs) => ((elapsedMs ~/ 220) % 2) == 1;
}