From fe89f4e0af25a89618c10761ecb6bb3304aa2ae6 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Sat, 9 Sep 2023 20:26:30 -0700 Subject: [PATCH] Mouse and keyboard input --- lib/input.dart | 45 ++++++++++++++++++++ lib/main.dart | 3 +- lib/terminal.dart | 90 ++++++++++++++++++++++++++++++++++++++- lib/terminal_painter.dart | 5 ++- 4 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 lib/input.dart diff --git a/lib/input.dart b/lib/input.dart new file mode 100644 index 0000000..962fc6b --- /dev/null +++ b/lib/input.dart @@ -0,0 +1,45 @@ +import 'package:dartterm/terminal.dart'; +import 'package:flutter/services.dart'; + +abstract class Input { + const Input(); +} + +class Click extends Input { + final Button button; + final int x, y; + + const Click(this.button, this.x, this.y); +} + +class Keystroke extends Input { + final Key? key; + final String? _text; + + const Keystroke(this.key, this._text); + + String? text() => _text; +} + +enum Button { left, right } + +enum Key { space } + +void startListening() { + ServicesBinding.instance.keyboard.addHandler(_onKey); +} + +bool _onKey(KeyEvent event) { + if (event is KeyDownEvent) { + final dartKey = event.logicalKey.keyLabel; + final realKey = _keys[dartKey]; + + notifyInput(Keystroke(realKey, event.character)); + } + + return false; +} + +final _keys = { + " ": Key.space, +}; diff --git a/lib/main.dart b/lib/main.dart index 6d65d70..1edccb1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,11 @@ import 'package:dartterm/colors.dart'; +import 'package:dartterm/input.dart' as input; import 'package:dartterm/game.dart' as game; import 'package:dartterm/terminal.dart' as terminal; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; void main() { - // terminal.at(0, 0).puts("Hello, world!"); runApp(const App()); } @@ -43,6 +43,7 @@ class _ViewerState extends State { super.initState(); ticker = Ticker(tick); ticker!.start(); + input.startListening(); game.main(); } diff --git a/lib/terminal.dart b/lib/terminal.dart index ab522ce..35b3a03 100644 --- a/lib/terminal.dart +++ b/lib/terminal.dart @@ -1,7 +1,11 @@ +import 'dart:developer'; + import 'package:dartterm/colors.dart'; import 'package:dartterm/cp437.dart'; import 'package:dartterm/fonts.dart'; +import 'package:dartterm/input.dart'; import 'package:dartterm/terminal_painter.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; class Terminal { @@ -10,14 +14,23 @@ class Terminal { static const int nTiles = width * height; late List tiles; + (int, int)? lastSeenMouse; + ScreenDimensions? screenDimensions; + List inputEvents = []; Terminal() { tiles = [for (var i = 0; i < nTiles; i += 1) Tile.empty()]; } - CustomPaint toWidget(BuildContext context) { + Widget toWidget(BuildContext context) { var scalingFactor = MediaQuery.devicePixelRatioOf(context); - return CustomPaint(painter: TerminalCustomPainter(this, scalingFactor)); + return MouseRegion( + onExit: _onPointerExit, + child: Listener( + onPointerDown: _onPointerDown, + onPointerHover: _onPointerHover, + child: CustomPaint( + painter: TerminalCustomPainter(this, scalingFactor)))); } (int, int)? toXY(int i) { @@ -37,6 +50,71 @@ class Terminal { return x + y * width; } + + void notifyInput(Input i) { + // TODO: Handle it + log("Input: $i $lastSeenMouse"); + inputEvents.add(i); + } + + void notifyScreenDimensions(ScreenDimensions sd) { + screenDimensions = sd; + } + + bool _onPointerDown(PointerDownEvent me) { + final button; + if (me.buttons & kPrimaryMouseButton != 0) { + button = Button.left; + } else if (me.buttons & kSecondaryMouseButton != 0) { + button = Button.right; + } else { + return false; + } + + var localPosition = me.localPosition; + final xy = _relativizeMouse(localPosition.dx, localPosition.dy); + lastSeenMouse = xy; + if (xy != null) { + final (x, y) = xy; + notifyInput(Click(button, x, y)); + } + return true; + } + + bool _onPointerExit(PointerExitEvent me) { + lastSeenMouse = null; + return true; + } + + bool _onPointerHover(PointerHoverEvent me) { + var localPosition = me.localPosition; + lastSeenMouse = _relativizeMouse(localPosition.dx, localPosition.dy); + return true; + } + + (int, int)? _relativizeMouse(double localX, double localY) { + final sd = screenDimensions; + if (sd == null) return null; + if (sd.xSz == 0 || sd.ySz == 0) return null; + + final tx = ((localX - sd.x0) * width) ~/ sd.xSz; + final ty = ((localY - sd.y0) * height) ~/ sd.ySz; + + if (tx < 0 || tx >= width) return null; + if (ty < 0 || ty >= height) return null; + + return (tx, ty); + } +} + +class ScreenDimensions { + final double x0, y0, xSz, ySz; + + const ScreenDimensions( + {required this.x0, + required this.y0, + required this.xSz, + required this.ySz}); } class Cursor { @@ -154,6 +232,14 @@ Widget toWidget(BuildContext context) { return _terminal.toWidget(context); } +void notifyInput(Input i) { + _terminal.notifyInput(i); +} + +void notifyScreenDimensions(ScreenDimensions sd) { + _terminal.notifyScreenDimensions(sd); +} + void clear() { at(0, 0).clear(); } diff --git a/lib/terminal_painter.dart b/lib/terminal_painter.dart index 40cd2e0..eb7801d 100644 --- a/lib/terminal_painter.dart +++ b/lib/terminal_painter.dart @@ -53,12 +53,15 @@ class TerminalCustomPainter extends CustomPainter { break; } } - log("$x0, $y0, $xSz, $ySz"); canvas.drawImageRect( image, const Offset(0, 0) & smallSize, Offset(x0, y0) & Size(xSz, ySz), Paint()..filterQuality = FilterQuality.none); + notifyScreenDimensions( + ScreenDimensions(x0: x0, y0: y0, xSz: xSz, ySz: ySz)); + + image.dispose(); } void virtualPaint(Canvas canvas, Size size) {