Initial commit
This commit is contained in:
372
Frontend/pages/home/ts/KeyHandler.ts
Normal file
372
Frontend/pages/home/ts/KeyHandler.ts
Normal file
@@ -0,0 +1,372 @@
|
||||
var KeyHandler: KeyHandler = {
|
||||
elements: {
|
||||
keys: {}
|
||||
},
|
||||
|
||||
selected: [],
|
||||
imagecache: {},
|
||||
ghostImage: null,
|
||||
|
||||
init() {
|
||||
KeyHandler.ghostImage = new Image();
|
||||
KeyHandler.ghostImage.src = '/stc/icon/ghost.png';
|
||||
KeyHandler.ghostImage.onload = () => {
|
||||
for (var y = 0; y < 4; y++) {
|
||||
if (KeyHandler.elements.keys[y] == undefined) KeyHandler.elements.keys[y] = {};
|
||||
for (var x = 0; x < 8; x++) {
|
||||
var keyCheck: HTMLDivElement = document.querySelector(`.key[y="${y}"][x="${x}"]`);
|
||||
if (keyCheck) {
|
||||
((keyX: number, keyY: number, key: HTMLDivElement) => {
|
||||
var canvas = key.querySelector('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
KeyHandler.elements.keys[keyY][keyX] = { key, canvas, context };
|
||||
|
||||
context.textBaseline = 'middle';
|
||||
context.textAlign = 'center';
|
||||
|
||||
key.onclick = () => {
|
||||
if (altDown == false) KeyHandler.select(String(keyX), String(keyY));
|
||||
else {
|
||||
socket.emit('page', 'executekey', PageHandler.currentPageID, keyX, keyY);
|
||||
}
|
||||
};
|
||||
})(x, y, keyCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
clear() {
|
||||
for (var y in KeyHandler.elements.keys) {
|
||||
for (var x in KeyHandler.elements.keys[y]) {
|
||||
var key = KeyHandler.elements.keys[y][x];
|
||||
|
||||
key.context.clearRect(0, 0, 100, 100);
|
||||
key.key.classList.remove('selected');
|
||||
}
|
||||
}
|
||||
KeyHandler.selected = [];
|
||||
Editor.close();
|
||||
},
|
||||
|
||||
render(x: string, y: string, data: Page_Key) {
|
||||
if (KeyHandler.elements.keys[String(y)]) {
|
||||
if (KeyHandler.elements.keys[String(y)][String(x)]) {
|
||||
var context = KeyHandler.elements.keys[String(y)][String(x)].context;
|
||||
|
||||
context.clearRect(0, 0, renderQuality, renderQuality);
|
||||
|
||||
if (data.state.type == 'custom') {
|
||||
var appearence = data.appearence;
|
||||
|
||||
render(appearence);
|
||||
} else if (data.state.type == 'ghost') {
|
||||
var appearence = data.appearence;
|
||||
|
||||
if (appearence == undefined) appearence = {};
|
||||
|
||||
appearence.system = { ghost: true };
|
||||
|
||||
render(appearence);
|
||||
} else if (data.state.type == 'pageup') {
|
||||
render({
|
||||
text: { value: 'Up', color: '#ffffff', size: 18, offsetX: 0, offsetY: 25 },
|
||||
background: { color: '#4676b7' },
|
||||
image: {
|
||||
size: 100,
|
||||
rotation: 0,
|
||||
offsetX: 0,
|
||||
offsetY: -15,
|
||||
iconid: 'keyboard_arrow_up',
|
||||
iconstyle: 'white'
|
||||
},
|
||||
system: {
|
||||
border: {
|
||||
color: '#253e5e',
|
||||
thickness: 8
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (data.state.type == 'pagedown') {
|
||||
render({
|
||||
text: { value: 'Down', color: '#ffffff', size: 18, offsetX: 0, offsetY: -25 },
|
||||
background: { color: '#4676b7' },
|
||||
image: {
|
||||
size: 100,
|
||||
rotation: 0,
|
||||
offsetX: 0,
|
||||
offsetY: 15,
|
||||
iconid: 'keyboard_arrow_down',
|
||||
iconstyle: 'white'
|
||||
},
|
||||
system: {
|
||||
border: {
|
||||
color: '#253e5e',
|
||||
thickness: 8
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (data.state.type == 'currentpage') {
|
||||
render({
|
||||
text: {
|
||||
value: `Page\\n\\n${PageHandler.currentIndex + 1}`,
|
||||
color: '#ffffff',
|
||||
size: 22,
|
||||
offsetX: 0,
|
||||
offsetY: 0
|
||||
},
|
||||
background: { color: '#4676b7' },
|
||||
system: {
|
||||
border: {
|
||||
color: '#253e5e',
|
||||
thickness: 8
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else console.error(`Invalid x '${x}'`);
|
||||
} else console.error(`Invalid y '${y}'`);
|
||||
|
||||
function render(appearence: Page_Key_Appearence) {
|
||||
if (appearence.background != undefined) {
|
||||
context.fillStyle = appearence.background.color;
|
||||
context.fillRect(0, 0, renderQuality, renderQuality);
|
||||
context.fill();
|
||||
}
|
||||
|
||||
if (appearence.text != undefined) {
|
||||
context.fillStyle = appearence.text.color;
|
||||
context.font = `800 ${appearence.text.size * fontSizeRatio}px "Montserrat"`;
|
||||
|
||||
var text = appearence.text.value;
|
||||
var lineHeight = appearence.text.size * fontSizeRatio;
|
||||
|
||||
var centerX = renderQuality / 2 + appearence.text.offsetX / 100 * (renderQuality * 2);
|
||||
var centerY = renderQuality / 2 + appearence.text.offsetY / 100 * renderQuality;
|
||||
var canvasYCounter = centerY;
|
||||
|
||||
var words = text.replace(/\\n/g, ' \\n ').split(' ');
|
||||
var line = '';
|
||||
|
||||
var totalLineHeight = 0;
|
||||
for (var n = 0; n < words.length; n++) {
|
||||
if (words[n].length == 0) continue;
|
||||
|
||||
var testLine = line + words[n] + ' ';
|
||||
var metrics = context.measureText(testLine);
|
||||
var testWidth = metrics.width;
|
||||
if (words[n] != '\\n')
|
||||
if (testWidth > renderQuality && n > 0) {
|
||||
line = words[n] + ' ';
|
||||
totalLineHeight += lineHeight;
|
||||
} else {
|
||||
line = testLine;
|
||||
}
|
||||
else {
|
||||
totalLineHeight += lineHeight;
|
||||
line = '';
|
||||
}
|
||||
}
|
||||
|
||||
line = '';
|
||||
canvasYCounter = canvasYCounter - totalLineHeight / 2;
|
||||
|
||||
var firstSkip = false;
|
||||
for (var n = 0; n < words.length; n++) {
|
||||
if (words[n].length == 0) continue;
|
||||
var testLine = line + words[n] + ' ';
|
||||
var metrics = context.measureText(testLine);
|
||||
var testWidth = metrics.width;
|
||||
if (words[n] != '\\n')
|
||||
if (testWidth > renderQuality && n > 0) {
|
||||
context.fillText(line, centerX, canvasYCounter);
|
||||
line = words[n] + ' ';
|
||||
canvasYCounter += lineHeight;
|
||||
} else {
|
||||
line = testLine;
|
||||
}
|
||||
else {
|
||||
context.fillText(line, centerX, canvasYCounter);
|
||||
line = '';
|
||||
|
||||
canvasYCounter += firstSkip ? lineHeight * 2 : lineHeight;
|
||||
if (firstSkip) firstSkip = false;
|
||||
}
|
||||
}
|
||||
context.fillText(line, centerX, canvasYCounter);
|
||||
}
|
||||
|
||||
if (appearence.image != undefined) {
|
||||
var imageAddress =
|
||||
appearence.image.address != undefined
|
||||
? appearence.image.address
|
||||
: appearence.image.iconid != undefined
|
||||
? `/stc/materialicons/white/${appearence.image.iconid}.png`
|
||||
: null;
|
||||
|
||||
var imageSize =
|
||||
appearence.image.size != undefined ? appearence.image.size / 100 * renderQuality : renderQuality;
|
||||
if (imageAddress) {
|
||||
var centerX = renderQuality / 2 + appearence.image.offsetX / 100 * renderQuality;
|
||||
var centerY = renderQuality / 2 + appearence.image.offsetY / 100 * renderQuality;
|
||||
|
||||
if (KeyHandler.imagecache[imageAddress] != undefined)
|
||||
renderImage(KeyHandler.imagecache[imageAddress]);
|
||||
else {
|
||||
KeyHandler.imagecache[imageAddress] = new Image();
|
||||
KeyHandler.imagecache[imageAddress].src = imageAddress;
|
||||
KeyHandler.imagecache[imageAddress].onload = () =>
|
||||
renderImage(KeyHandler.imagecache[imageAddress]);
|
||||
}
|
||||
|
||||
function renderImage(image) {
|
||||
context.save();
|
||||
context.translate(centerX, centerY);
|
||||
context.rotate(appearence.image.rotation * Math.PI / 180);
|
||||
context.drawImage(
|
||||
image,
|
||||
imageSize / 2 - imageSize,
|
||||
imageSize / 2 - imageSize,
|
||||
imageSize,
|
||||
imageSize
|
||||
);
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appearence.system != undefined) {
|
||||
if (appearence.system.border != undefined) {
|
||||
var relativeThickness = appearence.system.border.thickness / 100 * renderQuality;
|
||||
context.fillStyle = appearence.system.border.color;
|
||||
context.fillRect(0, 0, renderQuality, relativeThickness);
|
||||
context.rect(0, renderQuality - relativeThickness, renderQuality, relativeThickness);
|
||||
context.rect(0, 0, relativeThickness, renderQuality);
|
||||
context.rect(renderQuality - relativeThickness, 0, relativeThickness, renderQuality);
|
||||
context.fill();
|
||||
}
|
||||
|
||||
if (appearence.system.ghost == true) {
|
||||
var size = 50 / 100 * renderQuality;
|
||||
context.save();
|
||||
context.globalAlpha = 0.7;
|
||||
context.translate(renderQuality / 2, renderQuality / 2);
|
||||
context.drawImage(KeyHandler.ghostImage, size / 2 - size, size / 2 - size, size, size);
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
select(x: string, y: string, multi: boolean = false) {
|
||||
if (PageHandler.currentPage != null) {
|
||||
if (PageHandler.currentPage.keys[y] != undefined && PageHandler.currentPage.keys[y][x] != undefined) {
|
||||
// var keyConfig = PageHandler.currentPage.keys[y][x];
|
||||
|
||||
var query = `${x},${y}`;
|
||||
if (multi) {
|
||||
if (!KeyHandler.selected.includes(query)) KeyHandler.selected.push(query);
|
||||
} else
|
||||
KeyHandler.selected = [
|
||||
query
|
||||
];
|
||||
|
||||
document.querySelectorAll('.key').forEach((key: HTMLDivElement) => {
|
||||
var checkX = key.getAttribute('x');
|
||||
var checkY = key.getAttribute('y');
|
||||
var checkQuery = `${checkX},${checkY}`;
|
||||
if (KeyHandler.selected.includes(checkQuery)) key.classList.add('selected');
|
||||
else key.classList.remove('selected');
|
||||
});
|
||||
|
||||
if (KeyHandler.selected.length > 1) Editor.close();
|
||||
else {
|
||||
socket.emit('page', 'getkey', PageHandler.currentPageID, x, y, (key: Page_Key) => {
|
||||
Editor.open(x, y, key);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
KeyHandler.init();
|
||||
|
||||
var altDown = false;
|
||||
|
||||
window.addEventListener('keydown', (e: KeyboardEvent) => {
|
||||
if (e.key == 'alt' || e.altKey == true) altDown = true;
|
||||
});
|
||||
window.addEventListener('keyup', (e: KeyboardEvent) => {
|
||||
if (e.key == 'alt' || e.altKey == false) altDown = false;
|
||||
});
|
||||
|
||||
interface KeyHandler {
|
||||
elements: {
|
||||
keys: {
|
||||
[y: string]: {
|
||||
[x: string]: {
|
||||
key: HTMLDivElement;
|
||||
canvas: HTMLCanvasElement;
|
||||
context: CanvasRenderingContext2D;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
selected: string[];
|
||||
imagecache: { [iconID: string]: HTMLImageElement };
|
||||
ghostImage: any;
|
||||
|
||||
init: () => void;
|
||||
clear: () => void;
|
||||
render: (x: string, y: string, data: Page_Key) => void;
|
||||
select: (x: string, y: string, multi?: boolean) => void;
|
||||
}
|
||||
|
||||
interface Page_Key {
|
||||
id: string;
|
||||
state: {
|
||||
type: KeyTypes;
|
||||
toggle: boolean;
|
||||
confirm: boolean;
|
||||
};
|
||||
actions: Page_Key_ActionTypes;
|
||||
appearence: Page_Key_Appearence;
|
||||
}
|
||||
interface Page_Key_Appearence {
|
||||
text?: Page_Key_Text;
|
||||
image?: Page_Key_Image;
|
||||
background?: Page_Key_Background;
|
||||
system?: {
|
||||
border?: {
|
||||
color: string;
|
||||
thickness: number;
|
||||
};
|
||||
ghost?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
interface Page_Key_Text {
|
||||
value: string;
|
||||
size: number;
|
||||
color: string;
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
}
|
||||
|
||||
interface Page_Key_Image {
|
||||
address?: string;
|
||||
iconid?: string;
|
||||
iconstyle?: 'black' | 'white';
|
||||
size: number;
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
rotation: number;
|
||||
}
|
||||
|
||||
interface Page_Key_Background {
|
||||
color: string;
|
||||
}
|
||||
|
||||
type KeyTypes = 'empty' | 'custom' | 'pageup' | 'pagedown' | 'currentpage' | 'ghost';
|
||||
Reference in New Issue
Block a user