Add position adjustment logic and size adjustment logic. Still need to complete scale and fix an issue with letterboxed images just discovered with a 4:3 monitor
This commit is contained in:
parent
58b9310128
commit
582a95202e
|
@ -57,6 +57,11 @@ interface State {
|
|||
interface Message {
|
||||
cmd? : string;
|
||||
state? : State;
|
||||
x? : number;
|
||||
y? : number;
|
||||
width? : number;
|
||||
height? : number;
|
||||
scale? : number;
|
||||
}
|
||||
|
||||
declare function humanizeDuration(a : any, b : any) : string;
|
|
@ -57,17 +57,17 @@ class Display {
|
|||
this.canvasScale = window.devicePixelRatio;
|
||||
this.canvasWidth = this.parentElement.clientWidth - 12;
|
||||
this.canvasHeight = this.parentElement.clientHeight - 12;
|
||||
console.log(`${this.canvasWidth},${this.canvasHeight}`);
|
||||
//console.log(`${this.canvasWidth},${this.canvasHeight}`);
|
||||
this.canvas.width = this.canvasWidth;
|
||||
this.canvas.height = this.canvasHeight;
|
||||
}
|
||||
|
||||
private clear () {
|
||||
public clear () {
|
||||
this.ctx.fillStyle = 'rgb(0, 0, 0)';
|
||||
this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
|
||||
}
|
||||
|
||||
private updateScreen () {
|
||||
public updateScreen () {
|
||||
const clientRatio : number = this.canvasWidth / this.canvasHeight;
|
||||
const screenRatio : number = this.screen.width / this.screen.height;
|
||||
|
||||
|
@ -91,7 +91,7 @@ class Display {
|
|||
if (!this.sequence) {
|
||||
return;
|
||||
}
|
||||
console.log(this.sequence)
|
||||
//console.log(this.sequence);
|
||||
const screenScaleX : number = this.screenWidth / this.screen.width;
|
||||
const screenScaleY : number = this.screenHeight / this.screen.height;
|
||||
this.displayWidth = Math.round(this.width * screenScaleX);
|
||||
|
@ -101,7 +101,7 @@ class Display {
|
|||
|
||||
this.ctx.fillStyle = 'rgb(0, 0, 0)';
|
||||
this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
|
||||
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
|
||||
//console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
|
||||
this.updateImage();
|
||||
}
|
||||
|
||||
|
@ -257,6 +257,8 @@ class Client {
|
|||
if (typeof state.display !== 'undefined') {
|
||||
this.set('displayWidth', state.display.width.toString());
|
||||
this.set('displayHeight', state.display.height.toString());
|
||||
this.set('offsetLeft', state.offset.x.toString());
|
||||
this.set('offsetTop', state.offset.y.toString());
|
||||
this.set('sourceWidth', state.source.width.toString());
|
||||
this.set('sourceHeight', state.source.height.toString());
|
||||
|
||||
|
@ -322,6 +324,9 @@ class Client {
|
|||
case 'focus' :
|
||||
this.receiveFocus(msg);
|
||||
break;
|
||||
case 'display' :
|
||||
this.receiveDisplay(msg);
|
||||
break;
|
||||
default:
|
||||
console.warn(`No command "${msg.cmd}"`);
|
||||
break;
|
||||
|
@ -441,6 +446,12 @@ class Client {
|
|||
this.setUpdate(msg.state);
|
||||
}
|
||||
|
||||
private receiveDisplay (msg: Message) {
|
||||
this.display.clear();
|
||||
this.display.updateScreen();
|
||||
this.setDisplay(msg.state);
|
||||
}
|
||||
|
||||
public sendFocus () {
|
||||
console.log('send focus');
|
||||
//this.disableClass('manualCtrl');
|
||||
|
@ -451,6 +462,18 @@ class Client {
|
|||
this.display.updateImage();
|
||||
}
|
||||
|
||||
public sendOffset (x : number, y : number) {
|
||||
this.client.send(JSON.stringify({ cmd : 'offset', x, y }));
|
||||
}
|
||||
|
||||
public sendSize (width : number, height : number) {
|
||||
this.client.send(JSON.stringify({ cmd : 'size', width, height }));
|
||||
}
|
||||
|
||||
public sendScale (scale : number) {
|
||||
this.client.send(JSON.stringify({ cmd : 'scale', scale }));
|
||||
}
|
||||
|
||||
/**
|
||||
* HELPERS
|
||||
**/
|
||||
|
|
|
@ -5,6 +5,10 @@ export declare class Dimensions {
|
|||
constructor(width: number, height: number);
|
||||
getRatio(): number;
|
||||
}
|
||||
interface Offset {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
export declare class Display {
|
||||
private screen;
|
||||
private source;
|
||||
|
@ -13,8 +17,13 @@ export declare class Display {
|
|||
constructor(width: number, height: number);
|
||||
setOffsetX(x: number): void;
|
||||
setOffsetY(y: number): void;
|
||||
setWidth(width: number): void;
|
||||
setHeight(height: number): void;
|
||||
setSource(width: number, height: number): void;
|
||||
getDimensions(): fdOutgoingPosition;
|
||||
getOutgoingPosition(): fdOutgoingPosition;
|
||||
getDimensions(): Dimensions;
|
||||
getOffset(): Offset;
|
||||
getScreen(): Dimensions;
|
||||
getSource(): Dimensions;
|
||||
}
|
||||
export type { Offset };
|
||||
|
|
|
@ -22,6 +22,12 @@ class Display {
|
|||
setOffsetY(y) {
|
||||
this.offset.y = y;
|
||||
}
|
||||
setWidth(width) {
|
||||
this.display.width = width;
|
||||
}
|
||||
setHeight(height) {
|
||||
this.display.height = height;
|
||||
}
|
||||
setSource(width, height) {
|
||||
let offset;
|
||||
this.source = new Dimensions(width, height);
|
||||
|
@ -36,7 +42,7 @@ class Display {
|
|||
this.offset = { x: Math.round(offset / 2), y: 0 };
|
||||
}
|
||||
}
|
||||
getDimensions() {
|
||||
getOutgoingPosition() {
|
||||
return {
|
||||
w: this.display.width,
|
||||
h: this.display.height,
|
||||
|
@ -44,6 +50,12 @@ class Display {
|
|||
y: this.offset.y
|
||||
};
|
||||
}
|
||||
getDimensions() {
|
||||
return this.display;
|
||||
}
|
||||
getOffset() {
|
||||
return this.offset;
|
||||
}
|
||||
getScreen() {
|
||||
return this.screen;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/display/index.ts"],"names":[],"mappings":";;;AAEA,MAAa,UAAU;IAItB,YAAa,KAAc,EAAE,MAAe;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAEM,QAAQ;QACd,OAAO,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,CAAC;CACD;AAZD,gCAYC;AAOD,MAAa,OAAO;IAQnB,YAAa,KAAc,EAAE,MAAe;QAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAA;IAC9B,CAAC;IAEM,UAAU,CAAE,CAAU;QAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAEM,UAAU,CAAE,CAAU;QAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAEM,SAAS,CAAE,KAAc,EAAE,MAAe;QAChD,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrD,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACzG,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAClD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACrD,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC3G,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YAChD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC;QACrD,CAAC;IACF,CAAC;IAEM,aAAa;QACnB,OAAO;YACN,CAAC,EAAG,IAAI,CAAC,OAAO,CAAC,KAAK;YACtB,CAAC,EAAG,IAAI,CAAC,OAAO,CAAC,MAAM;YACvB,CAAC,EAAG,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,CAAC,EAAG,IAAI,CAAC,MAAM,CAAC,CAAC;SACjB,CAAA;IACF,CAAC;IAEM,SAAS;QACf,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAEM,SAAS;QACf,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;CACD;AAnDD,0BAmDC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,OAAO,EAAG,UAAU,EAAE,CAAC"}
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/display/index.ts"],"names":[],"mappings":"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"}
|
|
@ -238,6 +238,15 @@ async function cmd(msg) {
|
|||
case 'focus':
|
||||
await focus();
|
||||
break;
|
||||
case 'offset':
|
||||
offset(msg);
|
||||
break;
|
||||
case 'size':
|
||||
size(msg);
|
||||
break;
|
||||
case 'scale':
|
||||
scale(msg);
|
||||
break;
|
||||
default:
|
||||
log.warn(`No matching command: ${msg.cmd}`);
|
||||
}
|
||||
|
@ -319,6 +328,24 @@ async function focus() {
|
|||
focusImage = await testimage_1.TestImage.Focus(pos.w, pos.h);
|
||||
send({ cmd: 'focus' });
|
||||
}
|
||||
function offset(msg) {
|
||||
let current = sequence.getCurrent();
|
||||
if (current !== null) {
|
||||
sequence.updateOffset(msg.x, msg.y);
|
||||
}
|
||||
}
|
||||
function size(msg) {
|
||||
let current = sequence.getCurrent();
|
||||
if (current !== null) {
|
||||
sequence.updateSize(msg.width, msg.height);
|
||||
}
|
||||
}
|
||||
function scale(msg) {
|
||||
let current = sequence.getCurrent();
|
||||
if (current !== null) {
|
||||
sequence.updateScale(msg.scale);
|
||||
}
|
||||
}
|
||||
app.get('/', async (req, res, next) => {
|
||||
const sequencesArr = await files_1.Files.enumerateSequences(sequences);
|
||||
//const videosArr : VideoObject[] = await Files.enumerateVideos(videos);
|
||||
|
@ -336,7 +363,7 @@ app.get('/:width/:height/image.jpg', async (req, res, next) => {
|
|||
log.info(`Image: ${current.path} - ${width},${height}`);
|
||||
}
|
||||
catch (err) {
|
||||
log.error('Error getting thumbnail of ${current}', err);
|
||||
log.error(`Error getting thumbnail of ${current}`, err);
|
||||
return next(new Error('Error getting thumbnail'));
|
||||
}
|
||||
}
|
||||
|
@ -346,7 +373,7 @@ app.get('/:width/:height/image.jpg', async (req, res, next) => {
|
|||
log.info(`Image: ${current.path} - ${width},${height}`);
|
||||
}
|
||||
catch (err) {
|
||||
log.error('Error getting thumbnail of ${current}', err);
|
||||
log.error(`Error getting thumbnail of ${current}`, err);
|
||||
return next(new Error('Error getting thumbnail'));
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,7 @@ export declare class Sequence {
|
|||
load(seq: SequenceObject): Promise<void>;
|
||||
updateClientsOnLoad(): void;
|
||||
updateClientsOnState(): void;
|
||||
updateClientsOnDisplay(): void;
|
||||
private enumerate;
|
||||
unload(): void;
|
||||
getState(): State;
|
||||
|
@ -45,6 +46,9 @@ export declare class Sequence {
|
|||
frameAdvance(frames?: number): void;
|
||||
frameRewind(frames?: number): void;
|
||||
frameSet(frame: number): void;
|
||||
updateOffset(x: number, y: number): void;
|
||||
updateSize(width: number, height: number): void;
|
||||
updateScale(scale: number): void;
|
||||
private frameRecord;
|
||||
}
|
||||
export {};
|
||||
|
|
|
@ -149,6 +149,11 @@ class Sequence {
|
|||
this.send({ cmd: 'update', state: this.getState() });
|
||||
}
|
||||
}
|
||||
updateClientsOnDisplay() {
|
||||
if (this.current !== null) {
|
||||
this.send({ cmd: 'display', state: this.getState() });
|
||||
}
|
||||
}
|
||||
async enumerate() {
|
||||
let screen;
|
||||
if (this.current === null) {
|
||||
|
@ -172,7 +177,7 @@ class Sequence {
|
|||
this.display.setSource(this.info.width, this.info.height);
|
||||
this.log.info(`Screen : ${screen.width},${screen.height}`);
|
||||
this.log.info(`Sequence : ${this.info.width},${this.info.height}`);
|
||||
this.log.info(`Display : ${JSON.stringify(this.display.getDimensions())}`);
|
||||
this.log.info(`Display : ${JSON.stringify(this.display.getOutgoingPosition())}`);
|
||||
}
|
||||
}
|
||||
unload() {
|
||||
|
@ -181,7 +186,7 @@ class Sequence {
|
|||
this.images = [];
|
||||
}
|
||||
getState() {
|
||||
const dimensions = this.display.getDimensions();
|
||||
const dimensions = this.display.getOutgoingPosition();
|
||||
const source = this.display.getSource();
|
||||
const screen = this.display.getScreen();
|
||||
return {
|
||||
|
@ -281,6 +286,76 @@ class Sequence {
|
|||
this.progress = this.frame > 0 ? this.frame / (this.images.length - 1) : 0;
|
||||
this.updateClientsOnState();
|
||||
}
|
||||
updateOffset(x, y) {
|
||||
const current = this.display.getOutgoingPosition();
|
||||
const screen = this.display.getScreen();
|
||||
let totalX;
|
||||
let totalY;
|
||||
let updated = false;
|
||||
if (x !== 0) {
|
||||
if (current.x + x < 0) {
|
||||
return;
|
||||
}
|
||||
totalX = current.x + current.w + x;
|
||||
if (totalX > screen.width) {
|
||||
return;
|
||||
}
|
||||
this.display.setOffsetX(current.x + x);
|
||||
updated = true;
|
||||
}
|
||||
if (y !== 0) {
|
||||
if (current.y + y < 0) {
|
||||
return;
|
||||
}
|
||||
totalY = current.y + current.h + y;
|
||||
if (totalY > screen.height) {
|
||||
return;
|
||||
}
|
||||
this.display.setOffsetY(current.y + y);
|
||||
updated = true;
|
||||
}
|
||||
if (updated) {
|
||||
this.updateClientsOnDisplay();
|
||||
}
|
||||
}
|
||||
updateSize(width, height) {
|
||||
const current = this.display.getOutgoingPosition();
|
||||
const screen = this.display.getScreen();
|
||||
let totalX;
|
||||
let totalY;
|
||||
let updated = false;
|
||||
if (width !== 0) {
|
||||
if (current.w + width < 1) {
|
||||
return;
|
||||
}
|
||||
totalX = current.x + current.w + width;
|
||||
if (totalX > screen.width) {
|
||||
return;
|
||||
}
|
||||
this.display.setWidth(current.w + width);
|
||||
updated = true;
|
||||
}
|
||||
if (height !== 0) {
|
||||
if (current.h + height < 1) {
|
||||
return;
|
||||
}
|
||||
totalY = current.y + current.h + height;
|
||||
if (totalY > screen.height) {
|
||||
return;
|
||||
}
|
||||
this.display.setHeight(current.h + height);
|
||||
updated = true;
|
||||
}
|
||||
if (updated) {
|
||||
this.updateClientsOnDisplay();
|
||||
}
|
||||
}
|
||||
updateScale(scale) {
|
||||
const current = this.display.getDimensions();
|
||||
const offset = this.display.getOffset();
|
||||
const screen = this.display.getScreen();
|
||||
console.dir(scale);
|
||||
}
|
||||
async frameRecord() {
|
||||
const start = Date.now();
|
||||
let load;
|
||||
|
@ -291,7 +366,7 @@ class Sequence {
|
|||
let total;
|
||||
let result;
|
||||
const img = this.images[this.frame];
|
||||
const dimensions = this.display.getDimensions();
|
||||
const dimensions = this.display.getOutgoingPosition();
|
||||
this.log.info(`Frame: ${this.frame} / ${this.images.length}`);
|
||||
await this.fd.load(img.path, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
|
||||
load = Date.now() - start;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -40,6 +40,14 @@ export class Display {
|
|||
this.offset.y = y;
|
||||
}
|
||||
|
||||
public setWidth (width : number) {
|
||||
this.display.width = width;
|
||||
}
|
||||
|
||||
public setHeight (height : number) {
|
||||
this.display.height = height;
|
||||
}
|
||||
|
||||
public setSource (width : number, height : number) {
|
||||
let offset : number;
|
||||
this.source = new Dimensions(width, height);
|
||||
|
@ -54,7 +62,7 @@ export class Display {
|
|||
}
|
||||
}
|
||||
|
||||
public getDimensions () : fdOutgoingPosition {
|
||||
public getOutgoingPosition () : fdOutgoingPosition {
|
||||
return {
|
||||
w : this.display.width,
|
||||
h : this.display.height,
|
||||
|
@ -63,6 +71,14 @@ export class Display {
|
|||
}
|
||||
}
|
||||
|
||||
public getDimensions () : Dimensions {
|
||||
return this.display;
|
||||
}
|
||||
|
||||
public getOffset () : Offset {
|
||||
return this.offset;
|
||||
}
|
||||
|
||||
public getScreen () : Dimensions {
|
||||
return this.screen;
|
||||
}
|
||||
|
@ -72,4 +88,5 @@ export class Display {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = { Display, Dimensions };
|
||||
module.exports = { Display, Dimensions };
|
||||
export type { Offset };
|
|
@ -57,6 +57,11 @@ interface State {
|
|||
interface Message {
|
||||
cmd? : string;
|
||||
state? : State;
|
||||
x? : number;
|
||||
y? : number;
|
||||
width? : number;
|
||||
height? : number;
|
||||
scale? : number;
|
||||
}
|
||||
|
||||
declare function humanizeDuration(a : any, b : any) : string;
|
30
src/index.ts
30
src/index.ts
|
@ -226,6 +226,15 @@ async function cmd (msg : Message) {
|
|||
case 'focus' :
|
||||
await focus();
|
||||
break;
|
||||
case 'offset' :
|
||||
offset(msg);
|
||||
break;
|
||||
case 'size' :
|
||||
size(msg);
|
||||
break;
|
||||
case 'scale' :
|
||||
scale(msg);
|
||||
break;
|
||||
default :
|
||||
log.warn(`No matching command: ${msg.cmd}`);
|
||||
}
|
||||
|
@ -319,6 +328,27 @@ async function focus () {
|
|||
send({ cmd : 'focus' });
|
||||
}
|
||||
|
||||
function offset (msg : Message) {
|
||||
let current : ImageObject = sequence.getCurrent();
|
||||
if (current !== null) {
|
||||
sequence.updateOffset(msg.x, msg.y);
|
||||
}
|
||||
}
|
||||
|
||||
function size (msg : Message) {
|
||||
let current : ImageObject = sequence.getCurrent();
|
||||
if (current !== null) {
|
||||
sequence.updateSize(msg.width, msg.height);
|
||||
}
|
||||
}
|
||||
|
||||
function scale (msg : Message) {
|
||||
let current : ImageObject = sequence.getCurrent();
|
||||
if (current !== null) {
|
||||
sequence.updateScale(msg.scale);
|
||||
}
|
||||
}
|
||||
|
||||
app.get('/', async (req : Request, res : Response, next : NextFunction) => {
|
||||
const sequencesArr : SequenceObject[] = await Files.enumerateSequences(sequences);
|
||||
//const videosArr : VideoObject[] = await Files.enumerateVideos(videos);
|
||||
|
|
|
@ -5,7 +5,7 @@ import type { Logger } from 'winston';
|
|||
import type { SequenceObject, ImageObject } from '../files';
|
||||
import type { FD, fdOutgoingPosition, fdResult } from '../fd';
|
||||
import type { Camera } from '../camera';
|
||||
import type { Display, Dimensions } from '../display';
|
||||
import type { Display, Dimensions, Offset } from '../display';
|
||||
import type { FFPROBE, VideoInfo } from '../ffprobe';
|
||||
|
||||
enum SequenceStatus {
|
||||
|
@ -196,6 +196,12 @@ export class Sequence {
|
|||
}
|
||||
}
|
||||
|
||||
public updateClientsOnDisplay () {
|
||||
if (this.current !== null) {
|
||||
this.send({ cmd : 'display', state : this.getState() });
|
||||
}
|
||||
}
|
||||
|
||||
private async enumerate () {
|
||||
let screen : Dimensions;
|
||||
|
||||
|
@ -223,7 +229,7 @@ export class Sequence {
|
|||
this.display.setSource(this.info.width, this.info.height);
|
||||
this.log.info(`Screen : ${screen.width},${screen.height}`);
|
||||
this.log.info(`Sequence : ${this.info.width},${this.info.height}`);
|
||||
this.log.info(`Display : ${JSON.stringify(this.display.getDimensions())}`)
|
||||
this.log.info(`Display : ${JSON.stringify(this.display.getOutgoingPosition())}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,7 +240,7 @@ export class Sequence {
|
|||
}
|
||||
|
||||
public getState () : State {
|
||||
const dimensions : fdOutgoingPosition = this.display.getDimensions();
|
||||
const dimensions : fdOutgoingPosition = this.display.getOutgoingPosition();
|
||||
const source : Dimensions = this.display.getSource();
|
||||
const screen : Dimensions = this.display.getScreen();
|
||||
return {
|
||||
|
@ -341,6 +347,79 @@ export class Sequence {
|
|||
this.updateClientsOnState();
|
||||
}
|
||||
|
||||
public updateOffset (x : number, y : number) {
|
||||
const current : fdOutgoingPosition = this.display.getOutgoingPosition();
|
||||
const screen : Dimensions = this.display.getScreen();
|
||||
let totalX : number;
|
||||
let totalY : number;
|
||||
let updated : boolean = false;
|
||||
if (x !== 0) {
|
||||
if (current.x + x < 0) {
|
||||
return;
|
||||
}
|
||||
totalX = current.x + current.w + x;
|
||||
if (totalX > screen.width) {
|
||||
return;
|
||||
}
|
||||
this.display.setOffsetX(current.x + x);
|
||||
updated = true;
|
||||
}
|
||||
if (y !== 0) {
|
||||
if (current.y + y < 0) {
|
||||
return;
|
||||
}
|
||||
totalY = current.y + current.h + y;
|
||||
if (totalY > screen.height) {
|
||||
return;
|
||||
}
|
||||
this.display.setOffsetY(current.y + y);
|
||||
updated = true;
|
||||
}
|
||||
if (updated) {
|
||||
this.updateClientsOnDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
public updateSize (width : number, height : number) {
|
||||
const current : fdOutgoingPosition = this.display.getOutgoingPosition();
|
||||
const screen : Dimensions = this.display.getScreen();
|
||||
let totalX : number;
|
||||
let totalY : number;
|
||||
let updated : boolean = false;
|
||||
if (width !== 0) {
|
||||
if (current.w + width < 1) {
|
||||
return;
|
||||
}
|
||||
totalX = current.x + current.w + width;
|
||||
if (totalX > screen.width) {
|
||||
return;
|
||||
}
|
||||
this.display.setWidth(current.w + width);
|
||||
updated = true;
|
||||
}
|
||||
if (height !== 0) {
|
||||
if (current.h + height < 1) {
|
||||
return;
|
||||
}
|
||||
totalY = current.y + current.h + height;
|
||||
if (totalY > screen.height) {
|
||||
return;
|
||||
}
|
||||
this.display.setHeight(current.h + height);
|
||||
updated = true;
|
||||
}
|
||||
if (updated) {
|
||||
this.updateClientsOnDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
public updateScale (scale : number) {
|
||||
const current : Dimensions = this.display.getDimensions();
|
||||
const offset : Offset = this.display.getOffset();
|
||||
const screen : Dimensions = this.display.getScreen();
|
||||
console.dir(scale);
|
||||
}
|
||||
|
||||
private async frameRecord () {
|
||||
const start : number = Date.now();
|
||||
let load : number;
|
||||
|
@ -351,7 +430,7 @@ export class Sequence {
|
|||
let total : number;
|
||||
let result : fdResult;
|
||||
const img : ImageObject = this.images[this.frame];
|
||||
const dimensions : fdOutgoingPosition = this.display.getDimensions();
|
||||
const dimensions : fdOutgoingPosition = this.display.getOutgoingPosition();
|
||||
this.log.info(`Frame: ${this.frame} / ${this.images.length}`);
|
||||
await this.fd.load(img.path, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
|
||||
load = Date.now() - start;
|
||||
|
|
|
@ -30,8 +30,8 @@ declare class Display {
|
|||
constructor();
|
||||
private create;
|
||||
private updateSize;
|
||||
private clear;
|
||||
private updateScreen;
|
||||
clear(): void;
|
||||
updateScreen(): void;
|
||||
updateDisplay(): void;
|
||||
updateImage(): void;
|
||||
update(msg: Message): void;
|
||||
|
@ -79,8 +79,12 @@ declare class Client {
|
|||
sendStop(): void;
|
||||
sendExposure(): void;
|
||||
private receiveUpdate;
|
||||
private receiveDisplay;
|
||||
sendFocus(): void;
|
||||
private receiveFocus;
|
||||
sendOffset(x: number, y: number): void;
|
||||
sendSize(width: number, height: number): void;
|
||||
sendScale(scale: number): void;
|
||||
fullscreen(): void;
|
||||
exitFullscreen(): void;
|
||||
private active;
|
||||
|
|
|
@ -45,7 +45,6 @@ class Display {
|
|||
this.canvasScale = window.devicePixelRatio;
|
||||
this.canvasWidth = this.parentElement.clientWidth - 12;
|
||||
this.canvasHeight = this.parentElement.clientHeight - 12;
|
||||
console.log(`${this.canvasWidth},${this.canvasHeight}`);
|
||||
this.canvas.width = this.canvasWidth;
|
||||
this.canvas.height = this.canvasHeight;
|
||||
}
|
||||
|
@ -76,7 +75,6 @@ class Display {
|
|||
if (!this.sequence) {
|
||||
return;
|
||||
}
|
||||
console.log(this.sequence);
|
||||
const screenScaleX = this.screenWidth / this.screen.width;
|
||||
const screenScaleY = this.screenHeight / this.screen.height;
|
||||
this.displayWidth = Math.round(this.width * screenScaleX);
|
||||
|
@ -85,7 +83,6 @@ class Display {
|
|||
this.displayOffsetY = this.screenOffsetY + Math.round(this.offsetY * screenScaleY);
|
||||
this.ctx.fillStyle = 'rgb(0, 0, 0)';
|
||||
this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
|
||||
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
|
||||
this.updateImage();
|
||||
}
|
||||
updateImage() {
|
||||
|
@ -215,6 +212,8 @@ class Client {
|
|||
if (typeof state.display !== 'undefined') {
|
||||
this.set('displayWidth', state.display.width.toString());
|
||||
this.set('displayHeight', state.display.height.toString());
|
||||
this.set('offsetLeft', state.offset.x.toString());
|
||||
this.set('offsetTop', state.offset.y.toString());
|
||||
this.set('sourceWidth', state.source.width.toString());
|
||||
this.set('sourceHeight', state.source.height.toString());
|
||||
this.display.set(state);
|
||||
|
@ -266,6 +265,9 @@ class Client {
|
|||
case 'focus':
|
||||
this.receiveFocus(msg);
|
||||
break;
|
||||
case 'display':
|
||||
this.receiveDisplay(msg);
|
||||
break;
|
||||
default:
|
||||
console.warn(`No command "${msg.cmd}"`);
|
||||
break;
|
||||
|
@ -366,6 +368,11 @@ class Client {
|
|||
receiveUpdate(msg) {
|
||||
this.setUpdate(msg.state);
|
||||
}
|
||||
receiveDisplay(msg) {
|
||||
this.display.clear();
|
||||
this.display.updateScreen();
|
||||
this.setDisplay(msg.state);
|
||||
}
|
||||
sendFocus() {
|
||||
console.log('send focus');
|
||||
this.client.send(JSON.stringify({ cmd: 'focus' }));
|
||||
|
@ -373,6 +380,15 @@ class Client {
|
|||
receiveFocus(msg) {
|
||||
this.display.updateImage();
|
||||
}
|
||||
sendOffset(x, y) {
|
||||
this.client.send(JSON.stringify({ cmd: 'offset', x, y }));
|
||||
}
|
||||
sendSize(width, height) {
|
||||
this.client.send(JSON.stringify({ cmd: 'size', width, height }));
|
||||
}
|
||||
sendScale(scale) {
|
||||
this.client.send(JSON.stringify({ cmd: 'scale', scale }));
|
||||
}
|
||||
fullscreen() {
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen();
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -61,7 +61,7 @@
|
|||
<input id="offsetLeft" type="text" value="0" readonly />
|
||||
</span>
|
||||
<span class="field-row">
|
||||
<label for="offsetTop">Height</label>
|
||||
<label for="offsetTop">Top</label>
|
||||
<input id="offsetTop" type="text" value="0" readonly />
|
||||
</span>
|
||||
</fieldset>
|
||||
|
@ -132,33 +132,65 @@
|
|||
<span>
|
||||
<div></div>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="offsetXMinus" disabled><</button>
|
||||
<button class="small manualCtrl" id="offsetXMinus" onclick="client.sendOffset(-1, 0);" disabled>←</button>
|
||||
</div>
|
||||
<div></div>
|
||||
</span>
|
||||
<span>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="offsetYPlus" disabled>^</button>
|
||||
<button class="small manualCtrl" id="offsetYPlus" onclick="client.sendOffset(0, -1);" disabled>↑</button>
|
||||
</div>
|
||||
<div>
|
||||
Position
|
||||
</div>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="offsetYMinus" disabled>Y -</button>
|
||||
<button class="small manualCtrl" id="offsetYMinus" onclick="client.sendOffset(0, 1);" disabled>↓</button>
|
||||
</div>
|
||||
</span>
|
||||
<span>
|
||||
<div></div>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="offsetXPlus" disabled>></button>
|
||||
<button class="small manualCtrl" id="offsetXPlus" onclick="client.sendOffset(1, 0);" disabled>→</button>
|
||||
</div>
|
||||
<div></div>
|
||||
</span>
|
||||
<span>
|
||||
<button class="small manualCtrl" id="widthPlus" disabled>W +</button>
|
||||
<button class="small manualCtrl" id="widthMinus" disabled>W -</button>
|
||||
<button class="small manualCtrl" id="heightPlus" disabled>H +</button>
|
||||
<button class="small manualCtrl" id="heightMinus" disabled>H -</button>
|
||||
<div style="width: 30px;"> </div>
|
||||
</span>
|
||||
<span>
|
||||
<div></div>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="widthMinus" onclick="client.sendSize(-1, 0);" disabled>W -</button>
|
||||
</div>
|
||||
<div></div>
|
||||
</span>
|
||||
<span>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="heightPlus" onclick="client.sendSize(0, 1);" disabled>H +</button>
|
||||
</div>
|
||||
<div>Size</div>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="heightMinus" onclick="client.sendSize(0, -1);" disabled>H -</button>
|
||||
</div>
|
||||
</span>
|
||||
<span>
|
||||
<div></div>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="widthPlus" onclick="client.sendSize(1, 0);" disabled>W +</button>
|
||||
</div>
|
||||
<div></div>
|
||||
</span>
|
||||
<span>
|
||||
<div style="width: 30px;"> </div>
|
||||
</span>
|
||||
<span>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="scalePlus" onclick="client.sendScale(2);" disabled>S +</button>
|
||||
</div>
|
||||
<div>Scale</div>
|
||||
<div>
|
||||
<button class="small manualCtrl" id="scaleMinus" onclick="client.sendScale(-2);" disabled>S -</button>
|
||||
</div>
|
||||
</span>
|
||||
</form>
|
||||
</fieldset>
|
||||
|
|
Loading…
Reference in New Issue