Skip to content

Commit

Permalink
#7 configurable keys
Browse files Browse the repository at this point in the history
  • Loading branch information
Guzmazow committed Dec 14, 2022
1 parent d84043a commit 9f403cf
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 29 deletions.
81 changes: 81 additions & 0 deletions src/app/components/preferences/preferences-dialog.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,87 @@ <h1 mat-dialog-title>Preferences</h1>
<div mat-dialog-content>
<form [formGroup]="preferencesForm">
<mat-accordion [multi]="true">
<mat-expansion-panel formGroupName="controls" [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
Controls
</mat-panel-title>
<mat-panel-description>
Focus field and press key to assign
</mat-panel-description>
</mat-expansion-panel-header>
<div class="mb2">
<mat-form-field appearance="fill">
<mat-label>UP</mat-label>
<input (keydown)="keyConfigure($event)" matInput formControlName="up" type="text">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>DOWN</mat-label>
<input (keydown)="keyConfigure($event)" matInput formControlName="down" type="text">
</mat-form-field>
</div>
<div class="mb2">
<mat-form-field appearance="fill">
<mat-label>LEFT</mat-label>
<input (keydown)="keyConfigure($event)" matInput formControlName="left" type="text">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>RIGHT</mat-label>
<input (keydown)="keyConfigure($event)" matInput formControlName="right" type="text">
</mat-form-field>
</div>
<div class="mb2">
<mat-form-field appearance="fill">
<mat-label>START</mat-label>
<input (keydown)="keyConfigure($event)"matInput formControlName="start" type="text">
<mat-hint>Hold to cancel gameplay</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>SELECT</mat-label>
<input (keydown)="keyConfigure($event)" matInput formControlName="select" type="text">
<mat-hint>does same as START</mat-hint>
</mat-form-field>
</div>
<div>
<mat-form-field appearance="fill">
<mat-label>CANCEL</mat-label>
<input (keydown)="keyConfigure($event)" matInput formControlName="cancel" type="text">
<mat-hint>cancel current gameplay</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>TEST</mat-label>
<input (keydown)="keyConfigure($event)" matInput formControlName="test" type="text">
<mat-hint>Display more info during gameplay</mat-hint>
</mat-form-field>
</div>
</mat-expansion-panel>
<mat-expansion-panel [expanded]="false">
<mat-expansion-panel-header>
<mat-panel-title>
COM Port control
</mat-panel-title>
<mat-panel-description>
Currently provided without configuration
</mat-panel-description>
</mat-expansion-panel-header>
<div>
<p>
To start press "Connect to serial" at top right corner. <br>
Selected serial device is expected to continuously send <br>
16 bit array (Uint8array) aka usinged int (spec. bellow). <br>
It is a FLAG variable. You sum up all pressed keys in one value. <br>
Example: 1 + 4 = 5 (UP and LEFT pressed at the same time)
</p>
<table mat-table mat-table [dataSource]="controlsCOM" class="mat-elevation-z8">
<ng-container *ngFor="let col of controlsCOMDisplayedColumns" [matColumnDef]="col">
<th mat-header-cell *matHeaderCellDef> {{col}} </th>
<td mat-cell *matCellDef="let element"> {{element[col]}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="controlsCOMDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: controlsCOMDisplayedColumns;"></tr>
</table>
</div>
</mat-expansion-panel>
<mat-expansion-panel formGroupName="npsFilter" [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
mat-form-field + mat-form-field {
margin-left: 8px;
}

[class*='mat-column-']{
text-align: center;
min-width: 50px;
}
34 changes: 32 additions & 2 deletions src/app/components/preferences/preferences-dialog.component.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,35 @@
import { Component, Inject, OnInit } from '@angular/core';
import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatInput } from '@angular/material/input';
import { Preferences } from '@models/preferences';


const ControlsCOM = [
{ "key": "index", "UP": "15", "DOWN": "14", "LEFT": "13", "RIGHT": "12", "START": "11", "SELECT": "10", "N/A": "9 .. 0" },
{ "key": "value", "UP": "1", "DOWN": "2", "LEFT": "4", "RIGHT": "8", "START": "16", "SELECT": "32", "N/A": "64 .. 32768" },
];

@Component({
selector: 'app-preferences-dialog',
templateUrl: './preferences-dialog.component.html',
styleUrls: ['./preferences-dialog.component.scss']
})
export class PreferencesDialogComponent {
controlsCOMDisplayedColumns: string[] = ["key", "UP", "DOWN", "LEFT", "RIGHT", "START", "SELECT", "N/A"];
controlsCOM = ControlsCOM;

preferencesForm = new FormGroup({
controls: new FormGroup({
left: new FormControl(null),
down: new FormControl(null),
up: new FormControl(null),
right: new FormControl(null),
start: new FormControl(null),
select: new FormControl(null),
cancel: new FormControl(null),
test: new FormControl(null),
}),
npsFilter: new FormGroup({
from: new FormControl(null),
to: new FormControl(null),
Expand All @@ -26,7 +46,8 @@ export class PreferencesDialogComponent {

constructor(
public dialogRef: MatDialogRef<PreferencesDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: Preferences
@Inject(MAT_DIALOG_DATA) public data: Preferences,
private cdRef: ChangeDetectorRef
) {
this.preferencesForm.patchValue(data);
}
Expand All @@ -35,4 +56,13 @@ export class PreferencesDialogComponent {
this.dialogRef.close();
}

keyConfigure(event: KeyboardEvent): boolean {
var input = event.target as HTMLInputElement;
var controlsFormGroup = this.preferencesForm.controls['controls'] as FormGroup;
var keyInputFormControl = controlsFormGroup.controls[input.getAttribute("formControlName") || ""];
keyInputFormControl.setValue(event.code || event.key);
if(event.preventDefault) event.preventDefault();
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@
<div>Rolls: {{selectedSimfileMode?.rollCount}}</div>
<div>Holds: {{selectedSimfileMode?.holdCount}}</div>
<div>Mines: {{selectedSimfileMode?.mineCount}}</div>
<div>BPMs: {{selectedSimfile?.bpmReadable}}</div>
<div>Stops: {{selectedSimfile?.stopsReadable}}</div>
<div>BPMs: {{selectedSimfile.bpmReadable}}</div>
<div>Stops: {{selectedSimfile.stopsReadable}}</div>
<div title="Quantizations">Quant.: {{selectedSimfileMode?.quantizationCountReadable}}</div>
<div>Scores: {{selectedSimfileMode?.displayScores ?? 'Not played'}}</div>
</mat-card-content>
Expand Down
48 changes: 40 additions & 8 deletions src/app/models/preferences.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
export class Preferences {
controls: {
left: string,
down: string,
up: string,
right: string,
start: string,
select: string,
cancel: string,
test: string
} = {
left: "ArrowLeft",
down: "ArrowDown",
up: "ArrowUp",
right: "ArrowRight",
start: "Space",
select: "Enter",
cancel: "Escape",
test: "KeyT"
}

npsFilter: { from: number | null, to: number | null } = {
from: null,
to: null
Expand All @@ -8,18 +28,30 @@ export class Preferences {
laneWidth: 700
}

play: {
xMod: number,
play: {
xMod: number,
avgMod: number | null,
minMod: number | null,
} = {
xMod: 1,
avgMod: null,
minMod: null,
}
xMod: 1,
avgMod: null,
minMod: null,
}

constructor(preferences?: Preferences){
if(preferences)
constructor(preferences?: Preferences) {
if (preferences) {
Object.assign(this, preferences);
var defaults = new Preferences();
this.controls.left = this.controls.left || defaults.controls.left;
this.controls.down = this.controls.down || defaults.controls.down;
this.controls.up = this.controls.up || defaults.controls.up;
this.controls.right = this.controls.right || defaults.controls.right;
this.controls.start = this.controls.start || defaults.controls.start;
this.controls.select = this.controls.select || defaults.controls.select;
this.controls.cancel = this.controls.cancel || defaults.controls.cancel;
this.controls.test = this.controls.test || defaults.controls.test;
this.display.laneWidth = this.display.laneWidth || defaults.display.laneWidth;
this.play.xMod = this.play.xMod || defaults.play.xMod;
}
}
}
45 changes: 28 additions & 17 deletions src/app/services/keyboard.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Injectable } from '@angular/core';
import { Direction, Key } from '@models/enums';
import { Preferences } from '@models/preferences';
import { Subject } from 'rxjs';
import { DisplayService } from './display.service';
import { Log } from './log.service';
import { PreferenceService } from './preference.service';

@Injectable({
providedIn: 'root'
Expand All @@ -14,20 +16,8 @@ export class KeyboardService {
onPress = new Subject<{ key: Key, state: boolean }>();
onLongPress = new Subject<Key>();

keyMap = new Map<string, Key>([
["ArrowLeft", Key.LEFT],
["ArrowDown", Key.DOWN],
["ArrowUp", Key.UP],
["ArrowRight", Key.RIGHT],
["KeyA", Key.SECONDLEFT],
["KeyS", Key.SECONDDOWN],
["KeyW", Key.SECONDUP],
["KeyD", Key.SECONDRIGHT],
["Space", Key.START],
["Enter", Key.SELECT],
["Escape", Key.CANCEL],
["KeyT", Key.TEST]
]);
//overrriden at start of game from preferences
keyMap = new Map<string, Key>();

//setTimeout handles
keyLongPressState = new Map<Key, ReturnType<typeof setTimeout> | null>([
Expand Down Expand Up @@ -58,18 +48,36 @@ export class KeyboardService {
[Key.CANCEL, false]
]);

constructor() {
constructor(preferenceService: PreferenceService) {
preferenceService.onPreferenceChange.subscribe(pref => this.configure(pref));

Log.debug("KeyboardService", 'started listening keys');
window.addEventListener('keyup', this.onKeyHandler.bind(this));
window.addEventListener('keydown', this.onKeyHandler.bind(this));
//this.displayService.onStart.subscribe(x => this.listenStarted = true);
}

onKeyHandler(event: KeyboardEvent) {
configure(preferences: Preferences) {
this.keyMap.clear();
this.keyMap.set(preferences.controls.left, Key.LEFT);
this.keyMap.set(preferences.controls.down, Key.DOWN);
this.keyMap.set(preferences.controls.up, Key.UP);
this.keyMap.set(preferences.controls.right, Key.RIGHT);
// this.keyMap.set("KeyA", Key.SECONDLEFT);
// this.keyMap.set("KeyS", Key.SECONDDOWN);
// this.keyMap.set("KeyW", Key.SECONDUP);
// this.keyMap.set("KeyD", Key.SECONDRIGHT);
this.keyMap.set(preferences.controls.start, Key.START);
this.keyMap.set(preferences.controls.select, Key.SELECT);
this.keyMap.set(preferences.controls.cancel, Key.CANCEL);
this.keyMap.set(preferences.controls.test, Key.TEST);
}

onKeyHandler(event: KeyboardEvent): boolean {
//if (!this.listenStarted) return;
let isKeyDown = event.type == 'keydown';
let systemKey = this.keyMap.get(event.code || event.key);
if (systemKey === undefined) return;
if (systemKey === undefined) return true;
let keyState = this.keyState.get(systemKey);
if (isKeyDown != keyState) {
Log.debug("KeyboardService", `KeyState change: ${event.code || event.key}, ${isKeyDown}`)
Expand All @@ -85,5 +93,8 @@ export class KeyboardService {
if (timerHandle) clearTimeout(timerHandle);
}
}

if(event.preventDefault) event.preventDefault();
return false;
}
}

0 comments on commit 9f403cf

Please sign in to comment.