Commit caaeb9cb authored by Laureline Nevin's avatar Laureline Nevin ⌨️
Browse files

Implemented export window centered resize while holding ctrl

parent b4fcd606
Loading
Loading
Loading
Loading
+1 −1
Changes for index.html: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@
</head>
<body v-scope>
<div class="body-content" :style="{cursor: cursor}">
    <h1 class="title" title="Image Viewer with Online Interactive Relighting">{{title}}</h1>
    <h1 class="title" title="Image Viewer with Online Interactive Relighting" v-text="title"></h1>

    <header class="navbar" v-cloak>
        <div>
+45 −30
Changes for src/app.ts: 45 added lines, 30 removed lines.
Original line number Diff line number Diff line
@@ -801,14 +801,14 @@ export class App {
     * @param qy vertical coordinate of the quadrant
     * @param value position to set the given quadrant to
     * @param prev original state of the window
     * @param _centered to resize the window around its center
     * @param centered to resize the window around its center
     * @param keepRatio whether aspect ratio should be kept unmodified by the operation
     */
    private setExportWindowQuadrant(
        [qx, qy]: [0 | 1 | 2, 0 | 1 | 2],
        value: vec2,
        prev: Rect,
        _centered: boolean,
        centered: boolean,
        keepRatio: boolean,
    ) {
        if (!this.source) return;
@@ -828,43 +828,41 @@ export class App {
        } else {
            // Switch from offset/size to start/end coordinates
            let xyMin = [xy[0], xy[1]] as [number, number],
                xyMax = [xy[0] + wh[0], xy[1] + wh[1]] as [number, number];
            if (qx === 1 || qy === 1) {
                // Middle column or row
                const ax = qy === 1 ? 0 : 1;
                if (qx === 0 || qy === 0) {
                xyMax = [xy[0] + wh[0], xy[1] + wh[1]] as [number, number],
                xyMid = [xy[0] + wh[0] / 2, xy[1] + wh[1] / 2];
            const setMinMax = (ax: number) => {
                const lb = (!ax && !qx) || (ax && !qy),
                    minFact = lb ? 1 : centered ? -1 : 0,
                    maxFact = !lb ? 1 : centered ? -1 : 0;
                if (minFact) {
                    // Left or bottom
                    xyMin[ax] = clamp(Math.round(xyMin[ax] + diff[ax]), 0, xyMax[ax] - 1);
                } else {
                    xyMin[ax] = Math.floor(
                        clamp(xyMin[ax] + diff[ax] * minFact, 0, (centered ? xyMid[ax] : xyMax[ax]) - 1),
                    );
                }
                if (maxFact) {
                    // Right or top
                    xyMax[ax] = clamp(Math.round(xyMax[ax] + diff[ax]), xyMin[ax] + 1, total[ax]);
                    xyMax[ax] = Math.ceil(
                        clamp(xyMax[ax] + diff[ax] * maxFact, (centered ? xyMid[ax] : xyMin[ax]) + 1, total[ax]),
                    );
                }
            };
            if (qx === 1 || qy === 1) {
                // Side
                setMinMax(qy === 1 ? 0 : 1);
                if (keepRatio) {
                    const newSize = wh[1 - ax] * (xyMax[ax] - xyMin[ax]) / wh[ax];
                    xyMin[1 - ax] += (wh[1 - ax] - newSize) / 2;
                    xyMax[1 - ax] = xyMin[1 - ax] + newSize;
                    const newSize = Math.max(1, (wh[1 - (qy === 1 ? 0 : 1)] * (xyMax[qy === 1 ? 0 : 1] - xyMin[qy === 1 ? 0 : 1])) / wh[qy === 1 ? 0 : 1]);
                    xyMin[1 - (qy === 1 ? 0 : 1)] += Math.floor((wh[1 - (qy === 1 ? 0 : 1)] - newSize) / 2);
                    xyMax[1 - (qy === 1 ? 0 : 1)] = xyMin[1 - (qy === 1 ? 0 : 1)] + Math.ceil(newSize);
                }
            } else {
                // Corner
                if (keepRatio) {
                    let diagonal = [
                        prev.w * (1 - qx),
                        prev.h * (1 - qy),
                    ] as const;
                    vec2.scale(
                        diff,
                        diagonal,
                        vec2.dot(diff, diagonal) / Math.pow(vec2.len(diagonal), 2),
                    );
                    let diagonal = [prev.w * (1 - qx), prev.h * (1 - qy)] as const;
                    vec2.scale(diff, diagonal, vec2.dot(diff, diagonal) / Math.pow(vec2.len(diagonal), 2));
                }
                for (const ax of [0, 1] as const) {
                    if ([qx, qy][ax] === 0) {
                        // Left or bottom
                        xyMin[ax] = clamp(Math.round(xyMin[ax] + diff[ax]), 0, xyMax[ax] - 1);
                    } else {
                        // Right or top
                        xyMax[ax] = clamp(Math.round(xyMax[ax] + diff[ax]), xyMin[ax] + 1, total[ax]);
                    }
                    setMinMax(ax);
                }
            }
            params.area = Rect.fromCorners(xyMin, xyMax);
@@ -883,6 +881,7 @@ export class App {
    }

    private bindPointerEvents() {
        let lastMoveEvent: PointerEvent | null = null;
        const onPointerEvent = (ev: PointerEvent | WheelEvent) => {
            const viewport = this.state.viewport!;
            const pointerState = this.rx.pointerState;
@@ -958,7 +957,6 @@ export class App {
                    pos[1] >= exPar.innerGrab.y ? (pos[1] >= exPar.innerGrab.y2 ? 2 : 1) : 0,
                ];
            };

            if (ev instanceof PointerEvent && ev.type === 'pointerdown') {
                if (pointerState.dragging || !ev.isPrimary || ev.button !== 0) return;
                if (!highlight()) {
@@ -982,6 +980,7 @@ export class App {
                }
            } else if (ev instanceof PointerEvent && (ev.type === 'pointerup' || ev.type === 'pointerleave')) {
                if (!pointerState.dragging || !ev.isPrimary || ev.button !== 0) return;
                lastMoveEvent = null;
                doUpdate();
                pointerState.overLightball = lightball;
                pointerState.dragging = false;
@@ -991,6 +990,7 @@ export class App {
                window.removeEventListener('wheel', onPointerEvent);
            } else if (ev instanceof PointerEvent && ev.type === 'pointermove')
                if (pointerState.dragging) {
                    lastMoveEvent = ev;
                    doUpdate();
                } else {
                    highlight();
@@ -1017,6 +1017,19 @@ export class App {
            ev.stopPropagation();
        };

        const keyUpDown = (ev: KeyboardEvent) => {
            if (lastMoveEvent && (ev.key === 'Control' || ev.key === 'Shift')) {
                ev.preventDefault();
                ev.stopPropagation();
                let data: any = {};
                for (const key in lastMoveEvent) data[key] = (lastMoveEvent as any)[key];

                data.shiftKey = ev.shiftKey;
                data.ctrlKey = ev.ctrlKey;
                onPointerEvent(new PointerEvent('pointermove', data));
            }
        };

        this.gls.relight.canvas.addEventListener('pointerdown', onPointerEvent);
        this.gls.relight.canvas.addEventListener('wheel', onPointerEvent, { passive: false });
        this.gls.lightball.canvas.addEventListener('pointerdown', onPointerEvent);
@@ -1024,5 +1037,7 @@ export class App {
        window.addEventListener('pointerleave', onPointerEvent);
        window.addEventListener('pointerup', onPointerEvent);
        window.addEventListener('pointermove', onPointerEvent);
        window.addEventListener('keyup', keyUpDown);
        window.addEventListener('keydown', keyUpDown);
    }
}