UNPKG

@quick-game/cli

Version:

Command line interface for rapid qg development

230 lines 9.14 kB
// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Common from '../../core/common/common.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; import * as UI from '../../ui/legacy/legacy.js'; const UIStrings = { /** *@description Tooltip text that appears when hovering over largeicon pan button in Transform Controller of the Layers panel */ panModeX: 'Pan mode (X)', /** *@description Tooltip text that appears when hovering over largeicon rotate button in Transform Controller of the Layers panel */ rotateModeV: 'Rotate mode (V)', /** *@description Tooltip text that appears when hovering over the largeicon center button in the Transform Controller of the Layers panel */ resetTransform: 'Reset transform (0)', }; const str_ = i18n.i18n.registerUIStrings('panels/layer_viewer/TransformController.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class TransformController extends Common.ObjectWrapper.ObjectWrapper { mode; scaleInternal; offsetXInternal; offsetYInternal; rotateXInternal; rotateYInternal; oldRotateX; oldRotateY; originX; originY; element; minScale; maxScale; controlPanelToolbar; modeButtons; constructor(element, disableRotate) { super(); this.scaleInternal = 1; this.offsetXInternal = 0; this.offsetYInternal = 0; this.rotateXInternal = 0; this.rotateYInternal = 0; this.oldRotateX = 0; this.oldRotateY = 0; this.originX = 0; this.originY = 0; this.element = element; this.registerShortcuts(); UI.UIUtils.installDragHandle(element, this.onDragStart.bind(this), this.onDrag.bind(this), this.onDragEnd.bind(this), 'move', null); element.addEventListener('wheel', this.onMouseWheel.bind(this), false); this.minScale = 0; this.maxScale = Infinity; this.controlPanelToolbar = new UI.Toolbar.Toolbar('transform-control-panel'); this.modeButtons = {}; if (!disableRotate) { const panModeButton = new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.panModeX), '3d-pan'); panModeButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this.setMode.bind(this, "Pan" /* Modes.Pan */)); this.modeButtons["Pan" /* Modes.Pan */] = panModeButton; this.controlPanelToolbar.appendToolbarItem(panModeButton); const rotateModeButton = new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.rotateModeV), '3d-rotate'); rotateModeButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this.setMode.bind(this, "Rotate" /* Modes.Rotate */)); this.modeButtons["Rotate" /* Modes.Rotate */] = rotateModeButton; this.controlPanelToolbar.appendToolbarItem(rotateModeButton); } this.setMode("Pan" /* Modes.Pan */); const resetButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.resetTransform), '3d-center'); resetButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this.resetAndNotify.bind(this, undefined)); this.controlPanelToolbar.appendToolbarItem(resetButton); this.reset(); } toolbar() { return this.controlPanelToolbar; } registerShortcuts() { const zoomFactor = 1.1; UI.ShortcutRegistry.ShortcutRegistry.instance().addShortcutListener(this.element, { 'layers.reset-view': async () => { this.resetAndNotify(); return true; }, 'layers.pan-mode': async () => { this.setMode("Pan" /* Modes.Pan */); return true; }, 'layers.rotate-mode': async () => { this.setMode("Rotate" /* Modes.Rotate */); return true; }, 'layers.zoom-in': this.onKeyboardZoom.bind(this, zoomFactor), 'layers.zoom-out': this.onKeyboardZoom.bind(this, 1 / zoomFactor), 'layers.up': this.onKeyboardPanOrRotate.bind(this, 0, -1), 'layers.down': this.onKeyboardPanOrRotate.bind(this, 0, 1), 'layers.left': this.onKeyboardPanOrRotate.bind(this, -1, 0), 'layers.right': this.onKeyboardPanOrRotate.bind(this, 1, 0), }); } postChangeEvent() { this.dispatchEventToListeners(Events.TransformChanged); } reset() { this.scaleInternal = 1; this.offsetXInternal = 0; this.offsetYInternal = 0; this.rotateXInternal = 0; this.rotateYInternal = 0; } setMode(mode) { if (this.mode === mode) { return; } this.mode = mode; this.updateModeButtons(); } updateModeButtons() { for (const mode in this.modeButtons) { this.modeButtons[mode].setToggled(mode === this.mode); } } resetAndNotify(event) { this.reset(); this.postChangeEvent(); if (event) { event.preventDefault(); } this.element.focus(); } setScaleConstraints(minScale, maxScale) { this.minScale = minScale; this.maxScale = maxScale; this.scaleInternal = Platform.NumberUtilities.clamp(this.scaleInternal, minScale, maxScale); } clampOffsets(minX, maxX, minY, maxY) { this.offsetXInternal = Platform.NumberUtilities.clamp(this.offsetXInternal, minX, maxX); this.offsetYInternal = Platform.NumberUtilities.clamp(this.offsetYInternal, minY, maxY); } scale() { return this.scaleInternal; } offsetX() { return this.offsetXInternal; } offsetY() { return this.offsetYInternal; } rotateX() { return this.rotateXInternal; } rotateY() { return this.rotateYInternal; } onScale(scaleFactor, x, y) { scaleFactor = Platform.NumberUtilities.clamp(this.scaleInternal * scaleFactor, this.minScale, this.maxScale) / this.scaleInternal; this.scaleInternal *= scaleFactor; this.offsetXInternal -= (x - this.offsetXInternal) * (scaleFactor - 1); this.offsetYInternal -= (y - this.offsetYInternal) * (scaleFactor - 1); this.postChangeEvent(); } onPan(offsetX, offsetY) { this.offsetXInternal += offsetX; this.offsetYInternal += offsetY; this.postChangeEvent(); } onRotate(rotateX, rotateY) { this.rotateXInternal = rotateX; this.rotateYInternal = rotateY; this.postChangeEvent(); } async onKeyboardZoom(zoomFactor) { this.onScale(zoomFactor, this.element.clientWidth / 2, this.element.clientHeight / 2); return true; } async onKeyboardPanOrRotate(xMultiplier, yMultiplier) { const panStepInPixels = 6; const rotateStepInDegrees = 5; if (this.mode === "Rotate" /* Modes.Rotate */) { // Sic! onRotate treats X and Y as "rotate around X" and "rotate around Y", so swap X/Y multiplers. this.onRotate(this.rotateXInternal + yMultiplier * rotateStepInDegrees, this.rotateYInternal + xMultiplier * rotateStepInDegrees); } else { this.onPan(xMultiplier * panStepInPixels, yMultiplier * panStepInPixels); } return true; } onMouseWheel(event) { /** @const */ const zoomFactor = 1.1; /** @const */ const wheelZoomSpeed = 1 / 53; const mouseEvent = event; const scaleFactor = Math.pow(zoomFactor, -mouseEvent.deltaY * wheelZoomSpeed); this.onScale(scaleFactor, mouseEvent.clientX - this.element.getBoundingClientRect().left, mouseEvent.clientY - this.element.getBoundingClientRect().top); } onDrag(event) { const { clientX, clientY } = event; if (this.mode === "Rotate" /* Modes.Rotate */) { this.onRotate(this.oldRotateX + (this.originY - clientY) / this.element.clientHeight * 180, this.oldRotateY - (this.originX - clientX) / this.element.clientWidth * 180); } else { this.onPan(clientX - this.originX, clientY - this.originY); this.originX = clientX; this.originY = clientY; } } onDragStart(event) { this.element.focus(); this.originX = event.clientX; this.originY = event.clientY; this.oldRotateX = this.rotateXInternal; this.oldRotateY = this.rotateYInternal; return true; } onDragEnd() { this.originX = 0; this.originY = 0; this.oldRotateX = 0; this.oldRotateY = 0; } } // TODO(crbug.com/1167717): Make this a const enum again // eslint-disable-next-line rulesdir/const_enum export var Events; (function (Events) { Events["TransformChanged"] = "TransformChanged"; })(Events || (Events = {})); //# sourceMappingURL=TransformController.js.map