Factor camera logic into a separate object in preparation for the 3D demo
This commit is contained in:
parent
444e7bbf96
commit
7360a41a60
|
@ -19,6 +19,7 @@ import {BUILTIN_FONT_URI, TextLayout, PathfinderGlyph} from "./text";
|
||||||
import {PathfinderError, panic, unwrapNull} from "./utils";
|
import {PathfinderError, panic, unwrapNull} from "./utils";
|
||||||
import {PathfinderDemoView, Timings} from "./view";
|
import {PathfinderDemoView, Timings} from "./view";
|
||||||
import SSAAStrategy from "./ssaa-strategy";
|
import SSAAStrategy from "./ssaa-strategy";
|
||||||
|
import { OrthographicCamera } from "./camera";
|
||||||
|
|
||||||
const TEXT: string = "Lorem ipsum dolor sit amet";
|
const TEXT: string = "Lorem ipsum dolor sit amet";
|
||||||
|
|
||||||
|
@ -80,7 +81,10 @@ class ThreeDView extends PathfinderDemoView {
|
||||||
super(commonShaderSource, shaderSources);
|
super(commonShaderSource, shaderSources);
|
||||||
|
|
||||||
this.appController = appController;
|
this.appController = appController;
|
||||||
this._scale = 1.0;
|
|
||||||
|
this.camera = new OrthographicCamera(this.canvas);
|
||||||
|
this.camera.onPan = () => this.setDirty();
|
||||||
|
this.camera.onZoom = () => this.setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadPathMetadata(pathCount: number) {
|
uploadPathMetadata(pathCount: number) {
|
||||||
|
@ -98,7 +102,6 @@ class ThreeDView extends PathfinderDemoView {
|
||||||
|
|
||||||
const textGlyph = textGlyphs[pathIndex];
|
const textGlyph = textGlyphs[pathIndex];
|
||||||
const glyphRect = textGlyph.getRect(PIXELS_PER_UNIT);
|
const glyphRect = textGlyph.getRect(PIXELS_PER_UNIT);
|
||||||
console.log(glyphRect);
|
|
||||||
pathTransforms.set([1, 1, glyphRect[0], glyphRect[1]], startOffset);
|
pathTransforms.set([1, 1, glyphRect[0], glyphRect[1]], startOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,25 +138,19 @@ class ThreeDView extends PathfinderDemoView {
|
||||||
return glmatrix.vec2.fromValues(1.0, 1.0);
|
return glmatrix.vec2.fromValues(1.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get scale(): number {
|
|
||||||
return this._scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected set scale(newScale: number) {
|
|
||||||
this._scale = newScale;
|
|
||||||
this.setDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get worldTransform() {
|
protected get worldTransform() {
|
||||||
const transform = glmatrix.mat4.create();
|
const transform = glmatrix.mat4.create();
|
||||||
glmatrix.mat4.fromTranslation(transform, [this.translation[0], this.translation[1], 0]);
|
const translation = this.camera.translation;
|
||||||
glmatrix.mat4.scale(transform, transform, [this.scale, this.scale, 1.0]);
|
glmatrix.mat4.fromTranslation(transform, [translation[0], translation[1], 0]);
|
||||||
|
glmatrix.mat4.scale(transform, transform, [this.camera.scale, this.camera.scale, 1.0]);
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _scale: number;
|
private _scale: number;
|
||||||
|
|
||||||
private appController: ThreeDController;
|
private appController: ThreeDController;
|
||||||
|
|
||||||
|
camera: OrthographicCamera;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThreeDGlyph extends PathfinderGlyph {
|
class ThreeDGlyph extends PathfinderGlyph {
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
// pathfinder/client/src/camera.ts
|
||||||
|
//
|
||||||
|
// Copyright © 2017 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
import * as glmatrix from 'gl-matrix';
|
||||||
|
import {PathfinderView} from "./view";
|
||||||
|
|
||||||
|
const SCALE_FACTOR: number = 1.0 / 100.0;
|
||||||
|
|
||||||
|
export abstract class Camera {
|
||||||
|
constructor(canvas: HTMLCanvasElement) {
|
||||||
|
this.canvas = canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected canvas: HTMLCanvasElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class OrthographicCamera extends Camera {
|
||||||
|
constructor(canvas: HTMLCanvasElement) {
|
||||||
|
super(canvas);
|
||||||
|
|
||||||
|
this.translation = glmatrix.vec2.create();
|
||||||
|
this.scale = 1.0;
|
||||||
|
|
||||||
|
this.canvas.addEventListener('wheel', event => this.onWheel(event), false);
|
||||||
|
|
||||||
|
this.onPan = null;
|
||||||
|
this.onZoom = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
onWheel(event: MouseWheelEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
// Zoom event: see https://developer.mozilla.org/en-US/docs/Web/Events/wheel
|
||||||
|
const mouseLocation = glmatrix.vec2.fromValues(event.clientX, event.clientY);
|
||||||
|
const canvasLocation = this.canvas.getBoundingClientRect();
|
||||||
|
mouseLocation[0] -= canvasLocation.left;
|
||||||
|
mouseLocation[1] = canvasLocation.bottom - mouseLocation[1];
|
||||||
|
glmatrix.vec2.scale(mouseLocation, mouseLocation, window.devicePixelRatio);
|
||||||
|
|
||||||
|
const absoluteTranslation = glmatrix.vec2.create();
|
||||||
|
glmatrix.vec2.sub(absoluteTranslation, this.translation, mouseLocation);
|
||||||
|
glmatrix.vec2.scale(absoluteTranslation, absoluteTranslation, 1.0 / this.scale);
|
||||||
|
|
||||||
|
this.scale *= 1.0 - event.deltaY * window.devicePixelRatio * SCALE_FACTOR;
|
||||||
|
|
||||||
|
glmatrix.vec2.scale(absoluteTranslation, absoluteTranslation, this.scale);
|
||||||
|
glmatrix.vec2.add(this.translation, absoluteTranslation, mouseLocation);
|
||||||
|
|
||||||
|
if (this.onZoom != null)
|
||||||
|
this.onZoom();
|
||||||
|
} else {
|
||||||
|
// Pan event.
|
||||||
|
const delta = glmatrix.vec2.fromValues(-event.deltaX, event.deltaY);
|
||||||
|
glmatrix.vec2.scale(delta, delta, window.devicePixelRatio);
|
||||||
|
glmatrix.vec2.add(this.translation, this.translation, delta);
|
||||||
|
|
||||||
|
if (this.onPan != null)
|
||||||
|
this.onPan();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPan: (() => void) | null;
|
||||||
|
onZoom: (() => void) | null;
|
||||||
|
|
||||||
|
translation: glmatrix.vec2;
|
||||||
|
scale: number;
|
||||||
|
}
|
|
@ -11,13 +11,14 @@
|
||||||
import * as glmatrix from 'gl-matrix';
|
import * as glmatrix from 'gl-matrix';
|
||||||
|
|
||||||
import {AppController} from "./app-controller";
|
import {AppController} from "./app-controller";
|
||||||
|
import {OrthographicCamera} from "./camera";
|
||||||
import {B_QUAD_SIZE, B_QUAD_UPPER_LEFT_VERTEX_OFFSET} from "./meshes";
|
import {B_QUAD_SIZE, B_QUAD_UPPER_LEFT_VERTEX_OFFSET} from "./meshes";
|
||||||
import {B_QUAD_UPPER_RIGHT_VERTEX_OFFSET} from "./meshes";
|
import {B_QUAD_UPPER_RIGHT_VERTEX_OFFSET} from "./meshes";
|
||||||
import {B_QUAD_UPPER_CONTROL_POINT_VERTEX_OFFSET, B_QUAD_LOWER_LEFT_VERTEX_OFFSET} from "./meshes";
|
import {B_QUAD_UPPER_CONTROL_POINT_VERTEX_OFFSET, B_QUAD_LOWER_LEFT_VERTEX_OFFSET} from "./meshes";
|
||||||
import {B_QUAD_LOWER_RIGHT_VERTEX_OFFSET} from "./meshes";
|
import {B_QUAD_LOWER_RIGHT_VERTEX_OFFSET} from "./meshes";
|
||||||
import {B_QUAD_LOWER_CONTROL_POINT_VERTEX_OFFSET, PathfinderMeshData} from "./meshes";
|
import {B_QUAD_LOWER_CONTROL_POINT_VERTEX_OFFSET, PathfinderMeshData} from "./meshes";
|
||||||
import {BUILTIN_FONT_URI, GlyphStorage, PathfinderGlyph} from "./text";
|
import {BUILTIN_FONT_URI, GlyphStorage, PathfinderGlyph} from "./text";
|
||||||
import { unwrapNull, UINT32_SIZE, UINT32_MAX } from "./utils";
|
import {unwrapNull, UINT32_SIZE, UINT32_MAX} from "./utils";
|
||||||
import {PathfinderView} from "./view";
|
import {PathfinderView} from "./view";
|
||||||
|
|
||||||
const CHARACTER: string = 'r';
|
const CHARACTER: string = 'r';
|
||||||
|
@ -67,6 +68,7 @@ class MeshDebuggerView extends PathfinderView {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.appController = appController;
|
this.appController = appController;
|
||||||
|
this.camera = new OrthographicCamera(this.canvas);
|
||||||
this.scale = 1.0;
|
this.scale = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +87,8 @@ class MeshDebuggerView extends PathfinderView {
|
||||||
context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
|
||||||
context.save();
|
context.save();
|
||||||
context.translate(this.translation[0], this.canvas.height - this.translation[1]);
|
context.translate(this.camera.translation[0],
|
||||||
|
this.canvas.height - this.camera.translation[1]);
|
||||||
context.scale(this.scale, this.scale);
|
context.scale(this.scale, this.scale);
|
||||||
|
|
||||||
context.font = POINT_LABEL_FONT;
|
context.font = POINT_LABEL_FONT;
|
||||||
|
@ -156,6 +159,8 @@ class MeshDebuggerView extends PathfinderView {
|
||||||
protected scale: number;
|
protected scale: number;
|
||||||
|
|
||||||
private appController: MeshDebuggerAppController;
|
private appController: MeshDebuggerAppController;
|
||||||
|
|
||||||
|
camera: OrthographicCamera;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MeshDebuggerGlyph extends PathfinderGlyph {}
|
class MeshDebuggerGlyph extends PathfinderGlyph {}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'path-data-polyfill.js';
|
||||||
|
|
||||||
import {DemoAppController} from './app-controller';
|
import {DemoAppController} from './app-controller';
|
||||||
import {AntialiasingStrategy, AntialiasingStrategyName, NoAAStrategy} from "./aa-strategy";
|
import {AntialiasingStrategy, AntialiasingStrategyName, NoAAStrategy} from "./aa-strategy";
|
||||||
|
import {OrthographicCamera} from "./camera";
|
||||||
import {ECAAStrategy, ECAAMulticolorStrategy} from "./ecaa-strategy";
|
import {ECAAStrategy, ECAAMulticolorStrategy} from "./ecaa-strategy";
|
||||||
import {PathfinderMeshData} from "./meshes";
|
import {PathfinderMeshData} from "./meshes";
|
||||||
import {ShaderMap, ShaderProgramSource} from './shader-loader';
|
import {ShaderMap, ShaderProgramSource} from './shader-loader';
|
||||||
|
@ -172,7 +173,10 @@ class SVGDemoView extends PathfinderDemoView {
|
||||||
super(commonShaderSource, shaderSources);
|
super(commonShaderSource, shaderSources);
|
||||||
|
|
||||||
this.appController = appController;
|
this.appController = appController;
|
||||||
this._scale = 1.0;
|
|
||||||
|
this.camera = new OrthographicCamera(this.canvas);
|
||||||
|
this.camera.onPan = () => this.setDirty();
|
||||||
|
this.camera.onZoom = () => this.setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
get destAllocatedSize(): glmatrix.vec2 {
|
get destAllocatedSize(): glmatrix.vec2 {
|
||||||
|
@ -223,25 +227,17 @@ class SVGDemoView extends PathfinderDemoView {
|
||||||
return glmatrix.vec2.fromValues(1.0, 1.0);
|
return glmatrix.vec2.fromValues(1.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get scale(): number {
|
|
||||||
return this._scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected set scale(newScale: number) {
|
|
||||||
this._scale = newScale;
|
|
||||||
this.setDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get worldTransform() {
|
protected get worldTransform() {
|
||||||
const transform = glmatrix.mat4.create();
|
const transform = glmatrix.mat4.create();
|
||||||
glmatrix.mat4.fromTranslation(transform, [this.translation[0], this.translation[1], 0]);
|
const translation = this.camera.translation;
|
||||||
glmatrix.mat4.scale(transform, transform, [this.scale, this.scale, 1.0]);
|
glmatrix.mat4.fromTranslation(transform, [translation[0], translation[1], 0]);
|
||||||
|
glmatrix.mat4.scale(transform, transform, [this.camera.scale, this.camera.scale, 1.0]);
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _scale: number;
|
|
||||||
|
|
||||||
private appController: SVGDemoController;
|
private appController: SVGDemoController;
|
||||||
|
|
||||||
|
camera: OrthographicCamera;
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import {PathfinderError, assert, expectNotNull, UINT32_SIZE, unwrapNull, panic}
|
||||||
import {MonochromePathfinderView, Timings} from './view';
|
import {MonochromePathfinderView, Timings} from './view';
|
||||||
import PathfinderBufferTexture from './buffer-texture';
|
import PathfinderBufferTexture from './buffer-texture';
|
||||||
import SSAAStrategy from './ssaa-strategy';
|
import SSAAStrategy from './ssaa-strategy';
|
||||||
|
import { OrthographicCamera } from "./camera";
|
||||||
|
|
||||||
const DEFAULT_TEXT: string =
|
const DEFAULT_TEXT: string =
|
||||||
`’Twas brillig, and the slithy toves
|
`’Twas brillig, and the slithy toves
|
||||||
|
@ -227,6 +228,10 @@ class TextDemoView extends MonochromePathfinderView {
|
||||||
|
|
||||||
this.appController = appController;
|
this.appController = appController;
|
||||||
|
|
||||||
|
this.camera = new OrthographicCamera(this.canvas);
|
||||||
|
this.camera.onPan = () => this.onPan();
|
||||||
|
this.camera.onZoom = () => this.onZoom();
|
||||||
|
|
||||||
this.canvas.addEventListener('dblclick', () => this.appController.showTextEditor(), false);
|
this.canvas.addEventListener('dblclick', () => this.appController.showTextEditor(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,10 +284,11 @@ class TextDemoView extends MonochromePathfinderView {
|
||||||
const pixelsPerUnit = this.appController.pixelsPerUnit;
|
const pixelsPerUnit = this.appController.pixelsPerUnit;
|
||||||
|
|
||||||
// Only build glyphs in view.
|
// Only build glyphs in view.
|
||||||
const canvasRect = glmatrix.vec4.fromValues(-this.translation[0],
|
const translation = this.camera.translation;
|
||||||
-this.translation[1],
|
const canvasRect = glmatrix.vec4.fromValues(-translation[0],
|
||||||
-this.translation[0] + this.canvas.width,
|
-translation[1],
|
||||||
-this.translation[1] + this.canvas.height);
|
-translation[0] + this.canvas.width,
|
||||||
|
-translation[1] + this.canvas.height);
|
||||||
|
|
||||||
let atlasGlyphs =
|
let atlasGlyphs =
|
||||||
textGlyphs.filter(glyph => rectsIntersect(glyph.getRect(pixelsPerUnit), canvasRect))
|
textGlyphs.filter(glyph => rectsIntersect(glyph.getRect(pixelsPerUnit), canvasRect))
|
||||||
|
@ -387,8 +393,14 @@ class TextDemoView extends MonochromePathfinderView {
|
||||||
this.setDirty();
|
this.setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected panned() {
|
protected onPan() {
|
||||||
super.panned();
|
this.setDirty();
|
||||||
|
this.rebuildAtlasIfNecessary();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onZoom() {
|
||||||
|
this.appController.fontSize = this.camera.scale * INITIAL_FONT_SIZE;
|
||||||
|
this.setDirty();
|
||||||
this.rebuildAtlasIfNecessary();
|
this.rebuildAtlasIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,7 +446,7 @@ class TextDemoView extends MonochromePathfinderView {
|
||||||
[2.0 / this.canvas.width, 2.0 / this.canvas.height, 1.0]);
|
[2.0 / this.canvas.width, 2.0 / this.canvas.height, 1.0]);
|
||||||
glmatrix.mat4.translate(transform,
|
glmatrix.mat4.translate(transform,
|
||||||
transform,
|
transform,
|
||||||
[this.translation[0], this.translation[1], 0.0]);
|
[this.camera.translation[0], this.camera.translation[1], 0.0]);
|
||||||
|
|
||||||
// Blit.
|
// Blit.
|
||||||
this.gl.uniformMatrix4fv(blitProgram.uniforms.uTransform, false, transform);
|
this.gl.uniformMatrix4fv(blitProgram.uniforms.uTransform, false, transform);
|
||||||
|
@ -468,14 +480,6 @@ class TextDemoView extends MonochromePathfinderView {
|
||||||
return this.appController.atlas.usedSize;
|
return this.appController.atlas.usedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get scale(): number {
|
|
||||||
return this.appController.fontSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected set scale(newScale: number) {
|
|
||||||
this.appController.fontSize = newScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected createAAStrategy(aaType: AntialiasingStrategyName, aaLevel: number):
|
protected createAAStrategy(aaType: AntialiasingStrategyName, aaLevel: number):
|
||||||
AntialiasingStrategy {
|
AntialiasingStrategy {
|
||||||
return new (ANTIALIASING_STRATEGIES[aaType])(aaLevel);
|
return new (ANTIALIASING_STRATEGIES[aaType])(aaLevel);
|
||||||
|
@ -497,6 +501,8 @@ class TextDemoView extends MonochromePathfinderView {
|
||||||
glyphElementsBuffer: WebGLBuffer;
|
glyphElementsBuffer: WebGLBuffer;
|
||||||
|
|
||||||
appController: TextDemoController;
|
appController: TextDemoController;
|
||||||
|
|
||||||
|
camera: OrthographicCamera;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AntialiasingStrategyTable {
|
interface AntialiasingStrategyTable {
|
||||||
|
|
|
@ -17,8 +17,7 @@ import {PathfinderShaderProgram, SHADER_NAMES, ShaderMap} from './shader-loader'
|
||||||
import {ShaderProgramSource, UnlinkedShaderProgram} from './shader-loader';
|
import {ShaderProgramSource, UnlinkedShaderProgram} from './shader-loader';
|
||||||
import {PathfinderError, UINT32_SIZE, expectNotNull, unwrapNull} from './utils';
|
import {PathfinderError, UINT32_SIZE, expectNotNull, unwrapNull} from './utils';
|
||||||
import PathfinderBufferTexture from './buffer-texture';
|
import PathfinderBufferTexture from './buffer-texture';
|
||||||
|
import { Camera } from "./camera";
|
||||||
const SCALE_FACTOR: number = 1.0 / 100.0;
|
|
||||||
|
|
||||||
const TIME_INTERVAL_DELAY: number = 32;
|
const TIME_INTERVAL_DELAY: number = 32;
|
||||||
|
|
||||||
|
@ -51,12 +50,8 @@ export abstract class PathfinderView {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.dirty = false;
|
this.dirty = false;
|
||||||
|
|
||||||
this.translation = glmatrix.vec2.create();
|
|
||||||
|
|
||||||
this.canvas = unwrapNull(document.getElementById('pf-canvas')) as HTMLCanvasElement;
|
this.canvas = unwrapNull(document.getElementById('pf-canvas')) as HTMLCanvasElement;
|
||||||
|
|
||||||
this.canvas.addEventListener('wheel', event => this.onWheel(event), false);
|
|
||||||
|
|
||||||
window.addEventListener('resize', () => this.resizeToFit(false), false);
|
window.addEventListener('resize', () => this.resizeToFit(false), false);
|
||||||
this.resizeToFit(true);
|
this.resizeToFit(true);
|
||||||
}
|
}
|
||||||
|
@ -78,42 +73,6 @@ export abstract class PathfinderView {
|
||||||
this.resized();
|
this.resized();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onWheel(event: WheelEvent) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if (event.ctrlKey) {
|
|
||||||
// Zoom event: see https://developer.mozilla.org/en-US/docs/Web/Events/wheel
|
|
||||||
const mouseLocation = glmatrix.vec2.fromValues(event.clientX, event.clientY);
|
|
||||||
const canvasLocation = this.canvas.getBoundingClientRect();
|
|
||||||
mouseLocation[0] -= canvasLocation.left;
|
|
||||||
mouseLocation[1] = canvasLocation.bottom - mouseLocation[1];
|
|
||||||
glmatrix.vec2.scale(mouseLocation, mouseLocation, window.devicePixelRatio);
|
|
||||||
|
|
||||||
const absoluteTranslation = glmatrix.vec2.create();
|
|
||||||
glmatrix.vec2.sub(absoluteTranslation, this.translation, mouseLocation);
|
|
||||||
glmatrix.vec2.scale(absoluteTranslation, absoluteTranslation, 1.0 / this.scale);
|
|
||||||
|
|
||||||
this.scale *= 1.0 - event.deltaY * window.devicePixelRatio * SCALE_FACTOR;
|
|
||||||
|
|
||||||
glmatrix.vec2.scale(absoluteTranslation, absoluteTranslation, this.scale);
|
|
||||||
glmatrix.vec2.add(this.translation, absoluteTranslation, mouseLocation);
|
|
||||||
|
|
||||||
this.setDirty();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pan event.
|
|
||||||
const delta = glmatrix.vec2.fromValues(-event.deltaX, event.deltaY);
|
|
||||||
glmatrix.vec2.scale(delta, delta, window.devicePixelRatio);
|
|
||||||
glmatrix.vec2.add(this.translation, this.translation, delta);
|
|
||||||
|
|
||||||
this.panned();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected panned(): void {
|
|
||||||
this.setDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected resized(): void {
|
protected resized(): void {
|
||||||
this.setDirty();
|
this.setDirty();
|
||||||
}
|
}
|
||||||
|
@ -129,12 +88,9 @@ export abstract class PathfinderView {
|
||||||
this.dirty = false;
|
this.dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract get scale(): number;
|
|
||||||
protected abstract set scale(newScale: number);
|
|
||||||
|
|
||||||
protected canvas: HTMLCanvasElement;
|
protected canvas: HTMLCanvasElement;
|
||||||
|
|
||||||
protected translation: glmatrix.vec2;
|
protected camera: Camera;
|
||||||
|
|
||||||
private dirty: boolean;
|
private dirty: boolean;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue