mirror of https://github.com/espruino/BangleApps
ctrlpad restucture: controls class
parent
40a1b1a209
commit
639afaa20a
|
@ -25,11 +25,6 @@
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type Control = {
|
|
||||||
text: string,
|
|
||||||
cb: () => void,
|
|
||||||
};
|
|
||||||
|
|
||||||
class Overlay {
|
class Overlay {
|
||||||
g2: Graphics;
|
g2: Graphics;
|
||||||
width: number;
|
width: number;
|
||||||
|
@ -63,43 +58,73 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
renderG2(): void {
|
renderG2(): void {
|
||||||
const g = this.g2;
|
this.g2
|
||||||
|
|
||||||
g
|
|
||||||
.reset()
|
.reset()
|
||||||
.clearRect(0, 0, this.width, this.height)
|
.clearRect(0, 0, this.width, this.height)
|
||||||
.drawRect(0, 0, this.width - 1, this.height - 1)
|
.drawRect(0, 0, this.width - 1, this.height - 1)
|
||||||
.drawRect(1, 1, this.width - 2, this.height - 2);
|
.drawRect(1, 1, this.width - 2, this.height - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Control = {
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
text: string,
|
||||||
|
cb: () => void,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Controls {
|
||||||
|
controls: [Control, Control, Control, Control, Control];
|
||||||
|
|
||||||
|
constructor(g: Graphics) {
|
||||||
|
// const connected = NRF.getSecurityStatus().connected;
|
||||||
|
// if (0&&connected) {
|
||||||
|
// // TODO
|
||||||
|
// return [
|
||||||
|
// { text: "<", cb: hid.next },
|
||||||
|
// { text: "@", cb: hid.toggle },
|
||||||
|
// { text: ">", cb: hid.prev },
|
||||||
|
// { text: "-", cb: hid.down },
|
||||||
|
// { text: "+", cb: hid.up },
|
||||||
|
// ];
|
||||||
|
// }
|
||||||
|
|
||||||
|
const height = g.getHeight();
|
||||||
|
const centreY = height / 2;
|
||||||
|
const circleGapY = 30;
|
||||||
|
const width = g.getWidth();
|
||||||
|
|
||||||
|
this.controls = [
|
||||||
|
{ x: width / 4 - 10, y: centreY - circleGapY, text: "BLE", cb: function() { console.log(this.text); } },
|
||||||
|
{ x: width / 2, y: centreY - circleGapY, text: "DnD", cb: function() { console.log(this.text); } },
|
||||||
|
{ x: width * 3/4 + 10, y: centreY - circleGapY, text: "?", cb: function() { console.log(this.text); } },
|
||||||
|
{ x: width / 3, y: centreY + circleGapY, text: "B-", cb: function() { console.log(this.text); } },
|
||||||
|
{ x: width * 2/3, y: centreY + circleGapY, text: "B+", cb: function() { console.log(this.text); } },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(g: Graphics): void {
|
||||||
g
|
g
|
||||||
.setFontAlign(0, 0)
|
.setFontAlign(0, 0)
|
||||||
.setFont("Vector:20");
|
.setFont("Vector:20");
|
||||||
|
|
||||||
this.drawCtrls();
|
for(const ctrl of this.controls){
|
||||||
|
g
|
||||||
|
.setColor("#fff")
|
||||||
|
.fillCircle(ctrl.x, ctrl.y, 23)
|
||||||
|
.setColor("#000")
|
||||||
|
.drawString(ctrl.text, ctrl.x, ctrl.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawCtrls(): void {
|
hitTest(x: number, y: number): Control | undefined {
|
||||||
const centreY = this.height / 2;
|
const radius = 25;
|
||||||
const circleGapY = 30;
|
|
||||||
|
|
||||||
const controls = getControls();
|
for(const ctrl of this.controls)
|
||||||
|
if(Math.abs(y - ctrl.y) < radius && Math.abs(x - ctrl.x) < radius)
|
||||||
|
return ctrl;
|
||||||
|
|
||||||
this.drawCtrl(this.width / 4 - 10, centreY - circleGapY, controls[0].text);
|
return undefined;
|
||||||
this.drawCtrl(this.width / 2, centreY - circleGapY, controls[1].text);
|
|
||||||
this.drawCtrl(this.width * 3/4 + 10, centreY - circleGapY, controls[2].text);
|
|
||||||
|
|
||||||
this.drawCtrl(this.width / 3, centreY + circleGapY, controls[3].text);
|
|
||||||
this.drawCtrl(this.width * 2/3, centreY + circleGapY, controls[4].text);
|
|
||||||
}
|
|
||||||
|
|
||||||
drawCtrl(x: number, y: number, label: string): void {
|
|
||||||
const g = this.g2;
|
|
||||||
|
|
||||||
g
|
|
||||||
.setColor("#fff")
|
|
||||||
.fillCircle(x, y, 23)
|
|
||||||
.setColor("#000")
|
|
||||||
.drawString(label, x, y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,31 +146,9 @@
|
||||||
let startY = 0;
|
let startY = 0;
|
||||||
let startedUpDrag = false;
|
let startedUpDrag = false;
|
||||||
let upDragAnim: IntervalId | undefined;
|
let upDragAnim: IntervalId | undefined;
|
||||||
let overlay: Overlay | undefined;
|
let ui: undefined | { overlay: Overlay, ctrls: Controls };
|
||||||
let touchDown = false;
|
let touchDown = false;
|
||||||
|
|
||||||
type Controls = [Control, Control, Control, Control, Control];
|
|
||||||
const getControls = (): Controls => {
|
|
||||||
const connected = NRF.getSecurityStatus().connected;
|
|
||||||
|
|
||||||
if (connected) {
|
|
||||||
return [
|
|
||||||
{ text: "<", cb: hid.next },
|
|
||||||
{ text: "@", cb: hid.toggle },
|
|
||||||
{ text: ">", cb: hid.prev },
|
|
||||||
{ text: "-", cb: hid.down },
|
|
||||||
{ text: "+", cb: hid.up },
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
{ text: "a", cb: () => {} },
|
|
||||||
{ text: "b", cb: () => {} },
|
|
||||||
{ text: "c", cb: () => {} },
|
|
||||||
{ text: "d", cb: () => {} },
|
|
||||||
{ text: "e", cb: () => {} },
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDrag = (e => {
|
const onDrag = (e => {
|
||||||
const dragDistance = 30;
|
const dragDistance = 30;
|
||||||
|
|
||||||
|
@ -155,7 +158,7 @@
|
||||||
case State.IgnoreCurrent:
|
case State.IgnoreCurrent:
|
||||||
if(e.b === 0){
|
if(e.b === 0){
|
||||||
state = State.Idle;
|
state = State.Idle;
|
||||||
overlay = undefined;
|
ui = undefined;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -168,7 +171,7 @@
|
||||||
}else{
|
}else{
|
||||||
console.log(" ignoring this drag (too low @ " + e.y + ")");
|
console.log(" ignoring this drag (too low @ " + e.y + ")");
|
||||||
state = State.IgnoreCurrent;
|
state = State.IgnoreCurrent;
|
||||||
overlay = undefined
|
ui = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -182,24 +185,31 @@
|
||||||
startY = 0;
|
startY = 0;
|
||||||
Bangle.prependListener("touch", onTouch);
|
Bangle.prependListener("touch", onTouch);
|
||||||
Bangle.buzz(20);
|
Bangle.buzz(20);
|
||||||
overlay!.setBottom(g.getHeight());
|
ui!.overlay.setBottom(g.getHeight());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
console.log("returning to idle");
|
console.log("returning to idle");
|
||||||
state = State.Idle;
|
state = State.Idle;
|
||||||
overlay?.hide();
|
ui?.overlay.hide();
|
||||||
overlay = undefined;
|
ui = undefined;
|
||||||
}else{
|
}else{
|
||||||
// partial drag, show UI feedback:
|
// partial drag, show UI feedback:
|
||||||
const dragOffset = 32;
|
const dragOffset = 32;
|
||||||
|
|
||||||
if (!overlay) overlay = new Overlay();
|
if (!ui) {
|
||||||
overlay.setBottom(e.y - dragOffset);
|
const overlay = new Overlay();
|
||||||
|
ui = {
|
||||||
|
overlay,
|
||||||
|
ctrls: new Controls(overlay.g2),
|
||||||
|
};
|
||||||
|
ui.ctrls.draw(ui.overlay.g2);
|
||||||
|
}
|
||||||
|
ui.overlay.setBottom(e.y - dragOffset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State.Active:
|
case State.Active:
|
||||||
console.log("stolen drag handling, do whatever here");
|
//console.log("stolen drag handling, do whatever here");
|
||||||
E.stopEventPropagation?.();
|
E.stopEventPropagation?.();
|
||||||
if(e.b){
|
if(e.b){
|
||||||
if(!touchDown){
|
if(!touchDown){
|
||||||
|
@ -208,34 +218,44 @@
|
||||||
const dist = Math.max(0, startY - e.y);
|
const dist = Math.max(0, startY - e.y);
|
||||||
|
|
||||||
if (startedUpDrag || (startedUpDrag = dist > 10)) // ignore small drags
|
if (startedUpDrag || (startedUpDrag = dist > 10)) // ignore small drags
|
||||||
overlay!.setBottom(g.getHeight() - dist);
|
ui!.overlay.setBottom(g.getHeight() - dist);
|
||||||
}
|
}
|
||||||
}else if(e.b === 0 && startY > dragDistance){
|
}else if(e.b === 0){
|
||||||
let bottom = g.getHeight() - Math.max(0, startY - e.y);
|
if((startY - e.y) > dragDistance){
|
||||||
|
let bottom = g.getHeight() - Math.max(0, startY - e.y);
|
||||||
|
|
||||||
if (upDragAnim) clearInterval(upDragAnim);
|
if (upDragAnim) clearInterval(upDragAnim);
|
||||||
upDragAnim = setInterval(() => {
|
upDragAnim = setInterval(() => {
|
||||||
if (!overlay || bottom <= 0) {
|
if (!ui || bottom <= 0) {
|
||||||
clearInterval(upDragAnim!);
|
clearInterval(upDragAnim!);
|
||||||
upDragAnim = undefined;
|
upDragAnim = undefined;
|
||||||
overlay?.hide();
|
ui?.overlay.hide();
|
||||||
overlay = undefined;
|
ui = undefined;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
overlay?.setBottom(bottom);
|
ui!.overlay.setBottom(bottom);
|
||||||
bottom -= 10;
|
bottom -= 30;
|
||||||
}, 50)
|
}, 50)
|
||||||
|
|
||||||
Bangle.removeListener("touch", onTouch);
|
Bangle.removeListener("touch", onTouch);
|
||||||
state = State.Idle;
|
state = State.Idle;
|
||||||
|
}else{
|
||||||
|
ui!.overlay.setBottom(g.getHeight());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(e.b) touchDown = true;
|
if(e.b) touchDown = true;
|
||||||
}) satisfies DragCallback;
|
}) satisfies DragCallback;
|
||||||
|
|
||||||
const onTouch = ((_btn, _xy) => {
|
const onTouch = ((_btn, xy) => {
|
||||||
// TODO: button presses
|
if(!ui || !xy) return;
|
||||||
|
|
||||||
|
const top = g.getHeight() - ui.overlay.height; // assumed anchored to bottom
|
||||||
|
const left = (g.getWidth() - ui.overlay.width) / 2; // more assumptions
|
||||||
|
|
||||||
|
const ctrl = ui.ctrls.hitTest(xy.x - left, xy.y - top);
|
||||||
|
ctrl?.cb();
|
||||||
}) satisfies TouchCallback;
|
}) satisfies TouchCallback;
|
||||||
|
|
||||||
Bangle.prependListener("drag", onDrag);
|
Bangle.prependListener("drag", onDrag);
|
||||||
|
@ -248,23 +268,23 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
//const DEBUG = true;
|
//const DEBUG = true;
|
||||||
const sendHid = (code: number) => {
|
//const sendHid = (code: number) => {
|
||||||
//if(DEBUG) return;
|
// //if(DEBUG) return;
|
||||||
try{
|
// try{
|
||||||
NRF.sendHIDReport(
|
// NRF.sendHIDReport(
|
||||||
[1, code],
|
// [1, code],
|
||||||
() => NRF.sendHIDReport([1, 0]),
|
// () => NRF.sendHIDReport([1, 0]),
|
||||||
);
|
// );
|
||||||
}catch(e){
|
// }catch(e){
|
||||||
console.log("sendHIDReport:", e);
|
// console.log("sendHIDReport:", e);
|
||||||
}
|
// }
|
||||||
};
|
//};
|
||||||
|
|
||||||
const hid = {
|
// const hid = {
|
||||||
next: () => sendHid(0x01),
|
// next: () => sendHid(0x01),
|
||||||
prev: () => sendHid(0x02),
|
// prev: () => sendHid(0x02),
|
||||||
toggle: () => sendHid(0x10),
|
// toggle: () => sendHid(0x10),
|
||||||
up: () => sendHid(0x40),
|
// up: () => sendHid(0x40),
|
||||||
down: () => sendHid(0x80),
|
// down: () => sendHid(0x80),
|
||||||
};
|
// };
|
||||||
})()
|
})()
|
||||||
|
|
Loading…
Reference in New Issue