Mouse and keyboard input
This commit is contained in:
parent
e5cd74926f
commit
fe89f4e0af
45
lib/input.dart
Normal file
45
lib/input.dart
Normal 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,
|
||||
};
|
@ -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<Viewer> {
|
||||
super.initState();
|
||||
ticker = Ticker(tick);
|
||||
ticker!.start();
|
||||
input.startListening();
|
||||
game.main();
|
||||
}
|
||||
|
||||
|
@ -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<Tile> tiles;
|
||||
(int, int)? lastSeenMouse;
|
||||
ScreenDimensions? screenDimensions;
|
||||
List<Input> 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();
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user