Mouse and keyboard input

This commit is contained in:
Pyrex 2023-09-09 20:26:30 -07:00
parent e5cd74926f
commit fe89f4e0af
4 changed files with 139 additions and 4 deletions

45
lib/input.dart Normal file
View File

@ -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,
};

View File

@ -1,11 +1,11 @@
import 'package:dartterm/colors.dart'; import 'package:dartterm/colors.dart';
import 'package:dartterm/input.dart' as input;
import 'package:dartterm/game.dart' as game; import 'package:dartterm/game.dart' as game;
import 'package:dartterm/terminal.dart' as terminal; import 'package:dartterm/terminal.dart' as terminal;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
void main() { void main() {
// terminal.at(0, 0).puts("Hello, world!");
runApp(const App()); runApp(const App());
} }
@ -43,6 +43,7 @@ class _ViewerState extends State<Viewer> {
super.initState(); super.initState();
ticker = Ticker(tick); ticker = Ticker(tick);
ticker!.start(); ticker!.start();
input.startListening();
game.main(); game.main();
} }

View File

@ -1,7 +1,11 @@
import 'dart:developer';
import 'package:dartterm/colors.dart'; import 'package:dartterm/colors.dart';
import 'package:dartterm/cp437.dart'; import 'package:dartterm/cp437.dart';
import 'package:dartterm/fonts.dart'; import 'package:dartterm/fonts.dart';
import 'package:dartterm/input.dart';
import 'package:dartterm/terminal_painter.dart'; import 'package:dartterm/terminal_painter.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class Terminal { class Terminal {
@ -10,14 +14,23 @@ class Terminal {
static const int nTiles = width * height; static const int nTiles = width * height;
late List<Tile> tiles; late List<Tile> tiles;
(int, int)? lastSeenMouse;
ScreenDimensions? screenDimensions;
List<Input> inputEvents = [];
Terminal() { Terminal() {
tiles = [for (var i = 0; i < nTiles; i += 1) Tile.empty()]; tiles = [for (var i = 0; i < nTiles; i += 1) Tile.empty()];
} }
CustomPaint toWidget(BuildContext context) { Widget toWidget(BuildContext context) {
var scalingFactor = MediaQuery.devicePixelRatioOf(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) { (int, int)? toXY(int i) {
@ -37,6 +50,71 @@ class Terminal {
return x + y * width; 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 { class Cursor {
@ -154,6 +232,14 @@ Widget toWidget(BuildContext context) {
return _terminal.toWidget(context); return _terminal.toWidget(context);
} }
void notifyInput(Input i) {
_terminal.notifyInput(i);
}
void notifyScreenDimensions(ScreenDimensions sd) {
_terminal.notifyScreenDimensions(sd);
}
void clear() { void clear() {
at(0, 0).clear(); at(0, 0).clear();
} }

View File

@ -53,12 +53,15 @@ class TerminalCustomPainter extends CustomPainter {
break; break;
} }
} }
log("$x0, $y0, $xSz, $ySz");
canvas.drawImageRect( canvas.drawImageRect(
image, image,
const Offset(0, 0) & smallSize, const Offset(0, 0) & smallSize,
Offset(x0, y0) & Size(xSz, ySz), Offset(x0, y0) & Size(xSz, ySz),
Paint()..filterQuality = FilterQuality.none); Paint()..filterQuality = FilterQuality.none);
notifyScreenDimensions(
ScreenDimensions(x0: x0, y0: y0, xSz: xSz, ySz: ySz));
image.dispose();
} }
void virtualPaint(Canvas canvas, Size size) { void virtualPaint(Canvas canvas, Size size) {