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

Implemented export window ratio preservation when holding shift

parent 1bd6a10e
Loading
Loading
Loading
Loading
+2 −0
Changes for index.html: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -108,6 +108,8 @@
            <span>{{ `${exportParams.innerGrab}` }}</span>
            <span>Outer: </span>
            <span>{{ `${exportParams.outerGrab}` }}</span>
            <span>Keys:</span>
            <span>{{ modKeys }}</span>
            <span>Reset</span>
            <button v-icon="zoom-fit" @click="fn.setExportParams()"></button>
            <span>To view</span>
+46 −23
Changes for src/app.ts: 46 added lines, 23 removed lines.
Original line number Diff line number Diff line
@@ -227,6 +227,7 @@ export class App {
            cursor: null as string | null,
            datasetsDisabled: false,
            dataset: '',
            modKeys: '',
            requestFullscreen: null as (() => void) | null,
            t: (k: string) => this.i18n.t(k),
            loc: this.getLocString.bind(this),
@@ -694,8 +695,8 @@ export class App {
                    : 'full';
        let canvas = new Rect(0, 0, ...source.totalSize);
        if (from === 'view') {
            const tr = this.state.viewport.clipToTexture([1, 1]);
            const bl = this.state.viewport.clipToTexture([-1, -1]);
            const tr = this.state.viewport.clipToTexture([0.95, 0.95]);
            const bl = this.state.viewport.clipToTexture([-0.95, -0.95]);
            let area = Rect.fromCorners(vec2.floor(tr, tr), vec2.ceil(bl, bl));
            area = area.intersection(canvas)!;
            let dezoom = Math.max(-source.zoomDepth, Math.min(0, Math.ceil(Math.log2(this.state.viewport.zoom))));
@@ -794,30 +795,28 @@ export class App {
        exportDialog.close();
    }

    /**
     * Returns the coordinates of the given quadrant of the export window divided into thirds on both axes
     * @param x horizontal coordinate of the quadrant
     * @param y vertical coordinate of the quadrant
     */
    private getExportWindowQuadrant([x, y]: [0 | 1 | 2, 0 | 1 | 2]): vec2 {
        const area = this.rx.exportParams.area;
        return [area.x + (x * area.w) / 2, area.y + (y * area.h) / 2];
    }

    /**
     * Sets the coordinates of the given quadrant of the export window divided into thirds on both axes
     * @param qx horizontal coordinate of the quadrant
     * @param qy vertical coordinate of the quadrant
     * @param value position to set the given quadrant to
     // * @param keepRatio whether aspect ratio should be kept unmodified by the operation
     * @param prev original state of the window
     * @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) {
    private setExportWindowQuadrant(
        [qx, qy]: [0 | 1 | 2, 0 | 1 | 2],
        value: vec2,
        prev: Rect,
        _centered: boolean,
        keepRatio: boolean,
    ) {
        if (!this.source) return;
        const curVal = this.getExportWindowQuadrant([qx, qy]);
        const params = this.rx.exportParams;
        const diff = vec2.sub(curVal, value, curVal),
            { xy, wh } = params.area,
            total = this.source.totalSize;
        const prevVal = prev.getQuadrantCoords([qx, qy]),
            params = this.rx.exportParams,
            { xy, wh } = prev,
            total = this.source.totalSize,
            diff = vec2.sub([0, 0], value, prevVal);

        if (qx === 1 && qy === 1) {
            // Center
@@ -826,8 +825,7 @@ export class App {
                clamp(Math.round(xy[1] + diff[1]), 0, total[1] - wh[1]),
                ...wh,
            );
            return;
        }
        } 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];
@@ -841,8 +839,24 @@ export class App {
                    // Right or top
                    xyMax[ax] = clamp(Math.round(xyMax[ax] + diff[ax]), xyMin[ax] + 1, total[ax]);
                }
                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;
                }
            } 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),
                    );
                }
                for (const ax of [0, 1] as const) {
                    if ([qx, qy][ax] === 0) {
                        // Left or bottom
@@ -855,6 +869,7 @@ export class App {
            }
            params.area = Rect.fromCorners(xyMin, xyMax);
        }
    }

    private getQuadrantCursor(xy: [0 | 1 | 2, 0 | 1 | 2] | null): string | null {
        return (
@@ -898,7 +913,13 @@ export class App {
                    let texCoord = viewport.screenToTexture(evpos);
                    if (pointerState.exportWindowHover) {
                        vec2.sub(texCoord, texCoord, pointerState.origin);
                        this.setExportWindowQuadrant(pointerState.exportWindowHover!, texCoord);
                        this.setExportWindowQuadrant(
                            pointerState.exportWindowHover!,
                            texCoord,
                            pointerState.originWindow,
                            ev.ctrlKey,
                            ev.shiftKey,
                        );
                    } else {
                        let diff = vec2.sub([0, 0], texCoord, pointerState.origin);
                        viewport.move(diff);
@@ -948,11 +969,13 @@ export class App {
                    pointerState.exportWindowHover = exportWindowPart(texPos);
                    this.rx.cursor = this.getQuadrantCursor(pointerState.exportWindowHover);
                    if (pointerState.exportWindowHover) {
                        let [x, y]: [0 | 1 | 2, 0 | 1 | 2] = pointerState.exportWindowHover;
                        vec2.sub(
                            pointerState.origin,
                            pointerState.origin,
                            this.getExportWindowQuadrant(pointerState.exportWindowHover),
                            this.rx.raw().exportParams.area.getQuadrantCoords([x, y]),
                        );
                        pointerState.originWindow = this.rx.raw().exportParams.area.clone();
                    }
                    doUpdate();
                    window.addEventListener('wheel', onPointerEvent, { passive: false });
+2 −0
Changes for src/control.ts: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
import { vec2 } from 'gl-matrix';
import { Viewport } from './viewport.ts';
import { Exportable, ExportableSym } from './utils.ts';
import {Rect} from "./tiling.ts";

export class ControlUpdateEvent<T> extends Event {
    public static readonly type = 'formupdate';
@@ -259,6 +260,7 @@ export function getStateDefaults() {
            dragging: false,
            overLightball: false,
            origin: vec2.create(),
            originWindow: new Rect(0, 0, 0, 0),
            exportWindowHover: null as [0 | 1 | 2, 0 | 1 | 2] | null, // Which quadrant of the export window is currently hovered
        },
    };
+13 −0
Changes for src/tiling.ts: 13 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -183,6 +183,19 @@ export class Rect {
            Math.abs(this.h),
        );
    }

    clone(): Rect {
        return new Rect(this.x, this.y, this.w, this.h);
    }

    /**
     * Returns the coordinates of the given quadrant of the rectangle divided into thirds on both axes
     * @param x horizontal coordinate of the quadrant
     * @param y vertical coordinate of the quadrant
     */
    getQuadrantCoords([x, y]: [0 | 1 | 2, 0 | 1 | 2]): vec2 {
        return [this.x + (x * this.w) / 2, this.y + (y * this.h) / 2];
    }
}

export class TileTree implements TextureSource {