Loading index.html +2 −0 Changes for index.html: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -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> Loading src/app.ts +46 −23 Changes for src/app.ts: 46 added lines, 23 removed lines. Original line number Diff line number Diff line Loading @@ -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), Loading Loading @@ -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)))); Loading Loading @@ -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 Loading @@ -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]; Loading @@ -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 Loading @@ -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 ( Loading Loading @@ -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); Loading Loading @@ -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 }); Loading src/control.ts +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'; Loading Loading @@ -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 }, }; Loading src/tiling.ts +13 −0 Changes for src/tiling.ts: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -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 { Loading Loading
index.html +2 −0 Changes for index.html: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -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> Loading
src/app.ts +46 −23 Changes for src/app.ts: 46 added lines, 23 removed lines. Original line number Diff line number Diff line Loading @@ -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), Loading Loading @@ -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)))); Loading Loading @@ -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 Loading @@ -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]; Loading @@ -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 Loading @@ -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 ( Loading Loading @@ -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); Loading Loading @@ -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 }); Loading
src/control.ts +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'; Loading Loading @@ -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 }, }; Loading
src/tiling.ts +13 −0 Changes for src/tiling.ts: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -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 { Loading