From 1a1873385723b08da56239da07a6c8f73c312132 Mon Sep 17 00:00:00 2001 From: Stefania Pedrazzi Date: Wed, 3 Jul 2019 12:11:04 +0200 Subject: [PATCH 01/12] Dynamically add robot-designer to specified DOM element; add tabs for grouping parts; use vertical layout --- app/assets/asset.js | 4 + app/assets/asset_library.js | 10 +- app/robot_designer.js | 403 +++++++++++++++++++++--------------- app/view/part_browser.js | 70 +++++-- assets/assets.json | 4 +- index.html | 44 +--- style.css | 66 ++++-- 7 files changed, 364 insertions(+), 237 deletions(-) diff --git a/app/assets/asset.js b/app/assets/asset.js index 6a97ca8..5a9bc56 100644 --- a/app/assets/asset.js +++ b/app/assets/asset.js @@ -14,4 +14,8 @@ class Asset { // eslint-disable-line no-unused-vars getSlotNames() { return Object.keys(this.slots); } + + getRobotName() { + return this.name.split('/')[0]; + } } diff --git a/app/assets/asset_library.js b/app/assets/asset_library.js index 1141fd9..a65a200 100644 --- a/app/assets/asset_library.js +++ b/app/assets/asset_library.js @@ -5,11 +5,16 @@ class AssetLibrary extends Observable { // eslint-disable-line no-unused-vars constructor() { super(); this.assets = []; + this.robotNames = []; fetch('/robot-designer/assets/assets.json') .then(response => response.text()) .then((txt) => this._loadAssets(JSON.parse(txt))); } + getRobotNames() { + return this.robotNames; + } + getAssetByName(assetName) { for (let a = 0; a < this.assets.length; a++) { if (this.assets[a].name === assetName) @@ -17,13 +22,16 @@ class AssetLibrary extends Observable { // eslint-disable-line no-unused-vars } return undefined; } - _loadAssets(assetsData) { Object.keys(assetsData).forEach((assetName) => { var assetData = assetsData[assetName]; var asset = new Asset(assetName, assetData); this.assets.push(asset); + let robotName = asset.getRobotName(); + if (!this.robotNames.includes(robotName)) + this.robotNames.push(robotName); }); + this.notify('loaded', null); } } diff --git a/app/robot_designer.js b/app/robot_designer.js index e8da405..8bac7d0 100644 --- a/app/robot_designer.js +++ b/app/robot_designer.js @@ -1,37 +1,12 @@ /* global RobotViewer, Robot, Dragger, RobotMediator, RobotController, PartBrowser, PartViewer, AssetLibrary, Commands, MouseEvents */ 'use strict'; -class RobotDesigner { - constructor(part, undoButton, redoButton, selectButton, translateButton, rotateButton) { - this.part = part; - this.undoButton = undoButton; - this.redoButton = redoButton; - this.selectButton = selectButton; - this.translateButton = translateButton; - this.rotateButton = rotateButton; - - if (typeof part === 'undefined') { - console.error('The Robot Designer is initialized on an undefined part.'); - return; - } - this.robotViewerElement = document.getElementsByName('robotViewer')[0]; - if (typeof this.robotViewerElement === 'undefined') { - console.error('The Robot Designer cannot find its 3D component.'); - return; - } - this.assetLibraryElement = document.getElementsByName('assets-library-component')[0]; - if (typeof this.assetLibraryElement === 'undefined') { - console.error('The Robot Designer cannot find its asset library component.'); - return; - } - this.partViewerElement = document.getElementsByName('part-viewer')[0]; - if (typeof this.partViewerElement === 'undefined') { - console.error('The Robot Designer cannot find its part viewer component.'); - return; - } +class RobotDesigner { // eslint-disable-line no-unused-vars + constructor(domElement, showHeader) { + this._createDomElements(domElement); this.assetLibrary = new AssetLibrary(); - this.partBrowser = new PartBrowser(this.assetLibraryElement, this.assetLibrary); + this.partBrowser = new PartBrowser(this.assetLibraryElement, this.assetLibrary, (event) => { this.dragStart(event); }); this.assetLibrary.addObserver('loaded', () => { this.partBrowser.loadAssets(); }); this.commands = new Commands(); @@ -61,169 +36,263 @@ class RobotDesigner { else this.undoButton.classList.add('fa-disabled'); } -} -var designer = new RobotDesigner( // eslint-disable-line no-new - document.getElementById('nrp-robot-designer'), - document.getElementById('nrp-robot-designer-undo-button'), - document.getElementById('nrp-robot-designer-redo-button'), - document.getElementById('nrp-robot-designer-select-button'), - document.getElementById('nrp-robot-designer-translate-button'), - document.getElementById('nrp-robot-designer-rotate-button') -); - -function openExportModal() { // eslint-disable-line no-unused-vars - var modal = document.getElementById('nrp-robot-designer-modal-window'); - modal.style.display = 'block'; - - var span = document.getElementsByClassName('modal-close-button')[0]; - span.onclick = () => { - modal.style.display = 'none'; - }; - - window.onclick = (event) => { - if (event.target === modal) + // events + + openExportModal() { // eslint-disable-line no-unused-vars + var modal = document.getElementById('nrp-robot-designer-modal-window'); + modal.style.display = 'block'; + + var span = document.getElementsByClassName('modal-close-button')[0]; + span.onclick = () => { modal.style.display = 'none'; - }; -} + }; -function exportToFile(format) { // eslint-disable-line no-unused-vars - var mimeType = ''; - var data = ''; - var filename = ''; - - if (format === 'json') { - mimeType = 'text/json'; - data = JSON.stringify(designer.robot.serialize(), null, 2); - filename = 'robot.json'; - } else if (format === 'webots') { - mimeType = 'text/txt'; - data = designer.robot.webotsExport(); - filename = 'robot.wbt'; - } else { - console.assert(false); // Invalid format. - return; - } - - var blob = new Blob([data], {type: mimeType}); - var e = document.createEvent('MouseEvents'); - var a = document.createElement('a'); - a.download = filename; - a.href = window.URL.createObjectURL(blob); - a.dataset.downloadurl = [mimeType, a.download, a.href].join(':'); - e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); - a.dispatchEvent(e); -} + window.onclick = (event) => { + if (event.target === modal) + modal.style.display = 'none'; + }; + } -function undo() { // eslint-disable-line no-unused-vars - designer.commands.undo(); -} + exportToFile(format) { // eslint-disable-line no-unused-vars + var mimeType = ''; + var data = ''; + var filename = ''; + + if (format === 'json') { + mimeType = 'text/json'; + data = JSON.stringify(this.robot.serialize(), null, 2); + filename = 'robot.json'; + } else if (format === 'webots') { + mimeType = 'text/txt'; + data = this.robot.webotsExport(); + filename = 'robot.wbt'; + } else { + console.assert(false); // Invalid format. + return; + } -function redo() { // eslint-disable-line no-unused-vars - designer.commands.redo(); -} + var blob = new Blob([data], {type: mimeType}); + var e = document.createEvent('MouseEvents'); + var a = document.createElement('a'); + a.download = filename; + a.href = window.URL.createObjectURL(blob); + a.dataset.downloadurl = [mimeType, a.download, a.href].join(':'); + e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + a.dispatchEvent(e); + } -function changeMode(mode) { // eslint-disable-line no-unused-vars - designer.selectButton.classList.remove('fa-selected'); - designer.translateButton.classList.remove('fa-selected'); - designer.rotateButton.classList.remove('fa-selected'); + undo() { // eslint-disable-line no-unused-vars + this.commands.undo(); + } - if (mode === 'select') - designer.selectButton.classList.add('fa-selected'); - else if (mode === 'translate') - designer.translateButton.classList.add('fa-selected'); - else if (mode === 'rotate') - designer.rotateButton.classList.add('fa-selected'); + redo() { // eslint-disable-line no-unused-vars + this.commands.redo(); + } - designer.robotViewer.handle.setMode(mode); -} + changeMode(mode) { // eslint-disable-line no-unused-vars + this.selectButton.classList.remove('fa-selected'); + this.translateButton.classList.remove('fa-selected'); + this.rotateButton.classList.remove('fa-selected'); -function mouseDown(ev) { // eslint-disable-line no-unused-vars - var domElement = designer.robotViewer.robotViewerElement; - var relativePosition = MouseEvents.convertMouseEventPositionToRelativePosition(domElement, ev.clientX, ev.clientY); - var screenPosition = MouseEvents.convertMouseEventPositionToScreenPosition(domElement, ev.clientX, ev.clientY); - // get picked part that will be selected on mouseUp if the mouse doesn't move - designer.partToBeSelected = designer.robotViewer.getPartAt(relativePosition, screenPosition); - designer.mouseDownPosition = {x: ev.clientX, y: ev.clientY }; -} + if (mode === 'select') + this.selectButton.classList.add('fa-selected'); + else if (mode === 'translate') + this.translateButton.classList.add('fa-selected'); + else if (mode === 'rotate') + this.rotateButton.classList.add('fa-selected'); -function mouseUp(ev) { // eslint-disable-line no-unused-vars - if (typeof designer.partToBeSelected === 'undefined' || typeof designer.mouseDownPosition === 'undefined') - return; + this.robotViewer.handle.setMode(mode); + } - // compute Manhattan length - let length = Math.abs(designer.mouseDownPosition.x - ev.clientX) + Math.abs(designer.mouseDownPosition.y - ev.clientY); - if (length < 20) { // the mouse was moved by less than 20 pixels (determined empirically) - // select part - designer.robotViewer.selector.selectPart(designer.partToBeSelected); - designer.robotViewer.handle.attachToObject(designer.partToBeSelected); + mouseDown(ev) { // eslint-disable-line no-unused-vars + var domElement = this.robotViewer.robotViewerElement; + var relativePosition = MouseEvents.convertMouseEventPositionToRelativePosition(domElement, ev.clientX, ev.clientY); + var screenPosition = MouseEvents.convertMouseEventPositionToScreenPosition(domElement, ev.clientX, ev.clientY); + // get picked part that will be selected on mouseUp if the mouse doesn't move + this.partToBeSelected = this.robotViewer.getPartAt(relativePosition, screenPosition); + this.mouseDownPosition = {x: ev.clientX, y: ev.clientY }; } - designer.partToBeSelected = undefined; - designer.mouseDownPosition = undefined; -} + mouseUp(ev) { // eslint-disable-line no-unused-vars + if (typeof this.partToBeSelected === 'undefined' || typeof this.mouseDownPosition === 'undefined') + return; -function deleteSelectedPart() { // eslint-disable-line no-unused-vars - var mesh = designer.robotViewer.selector.selectedPart; + // compute Manhattan length + let length = Math.abs(this.mouseDownPosition.x - ev.clientX) + Math.abs(this.mouseDownPosition.y - ev.clientY); + if (length < 20) { // the mouse was moved by less than 20 pixels (determined empirically) + // select part + this.robotViewer.selector.selectPart(this.partToBeSelected); + this.robotViewer.handle.attachToObject(this.partToBeSelected); + } - if (mesh) { - var parent = mesh; - do { - if (parent.userData.isPartContainer) { - designer.robotController.removePart(parent.mediator.model); - break; - } - parent = parent.parent; - } while (parent); + this.partToBeSelected = undefined; + this.mouseDownPosition = undefined; } - designer.robotViewer.clearSelection(); -} + deleteSelectedPart() { // eslint-disable-line no-unused-vars + var mesh = this.robotViewer.selector.selectedPart; + + if (mesh) { + var parent = mesh; + do { + if (parent.userData.isPartContainer) { + this.robotController.removePart(parent.mediator.model); + break; + } + parent = parent.parent; + } while (parent); + } -function mouseMove(ev) { // eslint-disable-line no-unused-vars - if (designer.robotViewer.handle.isDragging()) - return; - - var domElement = designer.robotViewer.robotViewerElement; - var relativePosition = MouseEvents.convertMouseEventPositionToRelativePosition(domElement, ev.clientX, ev.clientY); - var screenPosition = MouseEvents.convertMouseEventPositionToScreenPosition(domElement, ev.clientX, ev.clientY); - var part = designer.robotViewer.getPartAt(relativePosition, screenPosition); - if (part) - designer.robotViewer.highlightor.highlight(part); - else - designer.robotViewer.highlightor.clearHighlight(); -} + this.robotViewer.clearSelection(); + } -function drop(ev) { // eslint-disable-line no-unused-vars - ev.preventDefault(); + mouseMove(ev) { // eslint-disable-line no-unused-vars + if (this.robotViewer.handle.isDragging()) + return; - designer.dragger.drop(ev.clientX, ev.clientY); -} + var domElement = this.robotViewer.robotViewerElement; + var relativePosition = MouseEvents.convertMouseEventPositionToRelativePosition(domElement, ev.clientX, ev.clientY); + var screenPosition = MouseEvents.convertMouseEventPositionToScreenPosition(domElement, ev.clientX, ev.clientY); + var part = this.robotViewer.getPartAt(relativePosition, screenPosition); + if (part) + this.robotViewer.highlightor.highlight(part); + else + this.robotViewer.highlightor.clearHighlight(); + } -function dragStart(ev) { // eslint-disable-line no-unused-vars - var part = ev.target.getAttribute('part'); - var slotType = ev.target.getAttribute('slotType'); - ev.dataTransfer.setData('text', part); // Cannot be used on Chrome. Cannot be dropped on Firefox. + drop(ev) { // eslint-disable-line no-unused-vars + ev.preventDefault(); - // https://stackoverflow.com/a/40923520/2210777 - var img = document.createElement('img'); - img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; - ev.dataTransfer.setDragImage(img, 0, 0); + this.dragger.drop(ev.clientX, ev.clientY); + } - designer.dragger.dragStart(part, slotType); -} + dragStart(ev) { // eslint-disable-line no-unused-vars + var part = ev.target.getAttribute('part'); + var slotType = ev.target.getAttribute('slotType'); + ev.dataTransfer.setData('text', part); // Cannot be used on Chrome. Cannot be dropped on Firefox. -function dragOver(ev) { // eslint-disable-line no-unused-vars - ev.preventDefault(); - ev.dataTransfer.getData('text'); // Cannot be used on Chrome. Cannot be dropped on Firefox. + // https://stackoverflow.com/a/40923520/2210777 + var img = document.createElement('img'); + img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; + ev.dataTransfer.setDragImage(img, 0, 0); - designer.dragger.dragOver(ev.clientX, ev.clientY); -} + this.dragger.dragStart(part, slotType); + } -function dragLeave(ev) { // eslint-disable-line no-unused-vars - designer.dragger.dragLeave(); -} + dragOver(ev) { // eslint-disable-line no-unused-vars + ev.preventDefault(); + ev.dataTransfer.getData('text'); // Cannot be used on Chrome. Cannot be dropped on Firefox. + + this.dragger.dragOver(ev.clientX, ev.clientY); + } + + dragLeave(ev) { // eslint-disable-line no-unused-vars + this.dragger.dragLeave(); + } -function dragEnter(ev) { // eslint-disable-line no-unused-vars - designer.dragger.dragEnter(); + dragEnter(ev) { // eslint-disable-line no-unused-vars + this.dragger.dragEnter(); + } + + // DOM setup + _createDomElements(domElement, showHeader) { + this.part = document.createElement('div'); + this.part.classList.add('nrp-robot-designer'); + this.part.id = 'nrp-robot-designer'; + if (typeof domElement === 'undefined') + document.body.appendChild(this.part); + else + domElement.appendChild(this.part); + + if (showHeader) { + let header = document.createElement('div'); + header.classList.add('header'); + header.innerHTML = `NRP Robot Designer + ' + File + Help`; + this.part.appendChild(header); + } + + this.toolbar = document.createElement('div'); + this.toolbar.classList.add('menu'); + this.toolbar.innerHTML = ` + + - + + + - + + + + - + + - + `; + this.part.appendChild(this.toolbar); + + this.undoButton = document.getElementById('nrp-robot-designer-undo-button'); + this.undoButton.addEventListener('click', () => { this.undo(); }); + this.redoButton = document.getElementById('nrp-robot-designer-redo-button'); + this.redoButton.addEventListener('click', () => { this.redo(); }); + this.translateButton = document.getElementById('nrp-robot-designer-translate-button'); + this.translateButton.addEventListener('click', () => { this.changeMode('translate'); }); + this.rotateButton = document.getElementById('nrp-robot-designer-rotate-button'); + this.rotateButton.addEventListener('click', () => { this.changeMode('rotate'); }); + var selectButton = document.getElementById('nrp-robot-designer-select-button'); + selectButton.addEventListener('click', () => { this.changeMode('select'); }); + var deleteButton = document.getElementById('nrp-robot-designer-delete-button'); + deleteButton.addEventListener('click', () => { this.this.deleteSelectedPart(); }); + var maximizeButton = document.getElementById('nrp-robot-designer-maximize-button'); + maximizeButton.addEventListener('click', () => { this.toggleFullScreen(); }); + + this.assetLibraryElement = document.createElement('div'); + this.assetLibraryElement.classList.add('part-browser'); + this.assetLibraryElement.classList.add('designer-group'); + this.part.appendChild(this.assetLibraryElement); + + var partViewerContainer = document.createElement('div'); + partViewerContainer.classList.add('part-viewer'); + partViewerContainer.classList.add('designer-group'); + partViewerContainer.innerHTML = `

Part viewer

`; + this.partViewerElement = document.createElement('div'); + partViewerContainer.appendChild(this.partViewerElement); + this.part.appendChild(partViewerContainer); + + this.robotViewerElement = document.createElement('div'); + this.robotViewerElement.classList.add('main'); + this.robotViewerElement.addEventListener('drop', (event) => { this.drop(event); }); + this.robotViewerElement.addEventListener('dragenter', (event) => { this.dragEnter(event); }); + this.robotViewerElement.addEventListener('dragover', (event) => { this.dragOver(event); }); + this.robotViewerElement.addEventListener('dragleave', (event) => { this.dragLeave(event); }); + this.robotViewerElement.addEventListener('mousemove', (event) => { this.mouseMove(event); }); + this.robotViewerElement.addEventListener('mousedown', (event) => { this.mouseDown(event); }); + this.robotViewerElement.addEventListener('mouseup', (event) => { this.mouseUp(event); }); + this.part.appendChild(this.robotViewerElement); + + // export modal window + var modalWindow = document.createElement('div'); + modalWindow.id = 'nrp-robot-designer-modal-window'; + modalWindow.classList.add('modal'); + modalWindow.innerHTML = + ``; + this.part.appendChild(modalWindow); + + var jsonExportButton = document.getElementById('nrp-robot-designer-json-export-button'); + jsonExportButton.addEventListener('click', () => { this.exportToFile('json'); }); + var webotsExportButton = document.getElementById('nrp-robot-designer-webots-export-button'); + webotsExportButton.addEventListener('click', () => { this.exportToFile('webots'); }); + var nrpExportButton = document.getElementById('nrp-robot-designer-nrp-export-button'); + nrpExportButton.addEventListener('click', () => { alert('Coming soon...'); }); + } } diff --git a/app/view/part_browser.js b/app/view/part_browser.js index f8f385f..7e9bb4a 100644 --- a/app/view/part_browser.js +++ b/app/view/part_browser.js @@ -1,29 +1,60 @@ 'use strict'; class PartBrowser { // eslint-disable-line no-unused-vars - constructor(assetLibraryElement, assetLibrary) { + constructor(assetLibraryElement, assetLibrary, dragStartCallback) { this.assetLibraryElement = assetLibraryElement; this.assetLibrary = assetLibrary; + this.robotsTabDivs = {}; this.partIconDivs = []; + this.dragStartCallback = dragStartCallback; + + this.selectElement = document.createElement('select'); + this.selectElement.classList.add('nrp-robot-designer-part-browser-select'); + this.selectElement.addEventListener('change', () => { this.showParts(); }); + + var labelBlock = document.createElement('div'); + labelBlock.classList.add('nrp-robot-designer-part-browser-label'); + labelBlock.innerHTML = '

Library

'; + labelBlock.appendChild(this.selectElement); + this.assetLibraryElement.appendChild(labelBlock); } loadAssets() { + // create robots tabs + this.assetLibrary.getRobotNames().forEach((robotName) => { + // content + let div = document.createElement('div'); + div.id = this._capitalize(robotName); + div.classList.add('nrp-robot-designer-part-browser-content'); + this.robotsTabDivs[robotName] = div; + this.assetLibraryElement.appendChild(div); + + // tab button + let option = document.createElement('option'); + option.classList.add('nrp-robot-designer-part-browser-option'); + option.setAttribute('value', robotName); + option.innerHTML = this._capitalize(robotName); + this.selectElement.appendChild(option); + }); + this.assetLibrary.assets.forEach((asset) => { var div = document.createElement('div'); - if (asset.root) { - div.innerHTML = '' + - '
' + - '' + - '
'; - } else { - div.innerHTML = '' + - ''; + var iconDiv = document.createElement('div'); + iconDiv.classList.add('part-icon'); + iconDiv.setAttribute('draggable', true); + iconDiv.setAttribute('part', asset.name); + if (!asset.root) { + iconDiv.classList.add('hidden'); + iconDiv.setAttribute('slotType', asset.slotType); } - this.partIconDivs.push(div.firstChild); - this.assetLibraryElement.appendChild(div.firstChild); + iconDiv.innerHTML = ''; + iconDiv.addEventListener('dragstart', (event) => { this.dragStartCallback(event); }); + div.appendChild(iconDiv); + this.partIconDivs.push(iconDiv); + this.robotsTabDivs[asset.getRobotName()].appendChild(iconDiv); }); + + this.showParts(this.selectElement.firstChild, this.assetLibrary.getRobotNames()[0]); } update(robot) { @@ -50,4 +81,17 @@ class PartBrowser { // eslint-disable-line no-unused-vars } } } + + showParts() { + var robotName = this.selectElement.options[this.selectElement.selectedIndex].value; + + for (let key in this.robotsTabDivs) + this.robotsTabDivs[key].style.display = 'none'; + + this.robotsTabDivs[robotName].style.display = 'block'; + } + + _capitalize(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + } } diff --git a/assets/assets.json b/assets/assets.json index cb95869..3d59b65 100644 --- a/assets/assets.json +++ b/assets/assets.json @@ -1,5 +1,5 @@ { - "tinkerbots/base": { + "tink/base": { "proto": "TinkerbotsBase", "icon": "/robot-designer/assets/models/tinkerbots/base/icon.png", "root": true, @@ -449,7 +449,7 @@ } } }, - "tinkerbots/light_sensor": { + "tink/light_sensor": { "proto": "TinkerbotsLightSensor", "icon": "/robot-designer/assets/models/tinkerbots/light_sensor/icon.png", "slotType": "tinkerbots", diff --git a/index.html b/index.html index b2a6c55..b51f21e 100644 --- a/index.html +++ b/index.html @@ -15,47 +15,13 @@ padding: 0px; } + - -
-
- NRP Robot Designer - - File - Help -
- -
- - -
- - - - diff --git a/style.css b/style.css index 169cbd0..1a12083 100644 --- a/style.css +++ b/style.css @@ -3,9 +3,9 @@ display: grid; grid-template-areas: 'header header header' - 'menu main main' - 'menu footer sidebar'; - grid-template-columns: 45px auto 275px; + 'toolbar part-browser main' + 'toolbar part-viewer main'; + grid-template-columns: 45px 290px auto ; grid-template-rows: 35px auto 110px; grid-gap: 3px; background-color: #333; @@ -26,7 +26,7 @@ } .menu { - grid-area: menu; + grid-area: toolbar; display: flex; flex-direction: column; text-align: center; @@ -36,20 +36,12 @@ grid-area: main; } -.sidebar { - grid-area: sidebar; +.part-viewer { + grid-area: part-viewer; margin-right: 2px; font-size: small; } -.footer { - grid-area: footer; - display: flex; - flex-flow: row nowrap; - align-items: center; - overflow-x: scroll !important; -} - .modal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ @@ -120,7 +112,12 @@ } .part-icon { - height: 100%; + height: 80px; + width: 80px; + max-height: 128px; + max-width: 128px; + padding-left: 6px; + display: inline-block; } .part-icon:hover { @@ -167,3 +164,42 @@ .fa-selected { color: #6E6; } + + /* Part Browser */ + .part-browser { + grid-area: part-browser; + display: flex; + flex-flow: column nowrap; + align-items: center; + overflow-y: hidden; + padding: 0px; + } + +.nrp-robot-designer-part-browser-select { + border-radius: 2px; + float: left; +} + +.nrp-robot-designer-part-browser-label { + display: flex; + float: left; + width: 100%; + background: #aaa; + margin: 0px; + padding: 5px; +} + +.nrp-robot-designer-part-browser-label > p { + margin-right: 10px; + font-size: 12px; + padding-left: 5px; +} + +/* Style the tab content */ +.nrp-robot-designer-part-browser-content { + display: none; + width: 100%; + height: 100%; + overflow-y: scroll !important; + margin: 0px; +} From 68436194798f7fc449e09c2441029351a5025821 Mon Sep 17 00:00:00 2001 From: Stefania Pedrazzi Date: Thu, 4 Jul 2019 11:01:43 +0200 Subject: [PATCH 02/12] Reset debug changes --- assets/assets.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/assets.json b/assets/assets.json index 3d59b65..cb95869 100644 --- a/assets/assets.json +++ b/assets/assets.json @@ -1,5 +1,5 @@ { - "tink/base": { + "tinkerbots/base": { "proto": "TinkerbotsBase", "icon": "/robot-designer/assets/models/tinkerbots/base/icon.png", "root": true, @@ -449,7 +449,7 @@ } } }, - "tink/light_sensor": { + "tinkerbots/light_sensor": { "proto": "TinkerbotsLightSensor", "icon": "/robot-designer/assets/models/tinkerbots/light_sensor/icon.png", "slotType": "tinkerbots", From 730d7ba0d2485c3d715345f1d1dc52e9551e25d8 Mon Sep 17 00:00:00 2001 From: Stefania Pedrazzi Date: Thu, 4 Jul 2019 11:18:23 +0200 Subject: [PATCH 03/12] Fix bugs and add NRP light theme --- app/robot-designer.min.js | 2 +- app/robot_designer.js | 132 ++++++++++++++++++-------------------- app/view/ghost.js | 6 ++ app/view/robot_viewer.js | 4 +- index.html | 7 +- nrp_style.css | 71 ++++++++++++++++++++ style.css | 15 +++-- 7 files changed, 158 insertions(+), 79 deletions(-) create mode 100644 nrp_style.css diff --git a/app/robot-designer.min.js b/app/robot-designer.min.js index 2478e78..512d7ae 100644 --- a/app/robot-designer.min.js +++ b/app/robot-designer.min.js @@ -1 +1 @@ -"use strict";THREE.OrbitControls=function(e,t){var R=Math.sqrt,D=Math.max,A=Math.min,L=Math.pow,V=Math.PI;function o(){return 2*V/60/60*j.autoRotateSpeed}function r(){return L(.95,j.zoomSpeed)}function a(e){G.theta-=e}function n(e){G.phi-=e}function i(e){j.object.isPerspectiveCamera?Q/=e:j.object.isOrthographicCamera?(j.object.zoom=D(j.minZoom,A(j.maxZoom,j.object.zoom*e)),j.object.updateProjectionMatrix(),H=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),j.enableZoom=!1)}function l(e){j.object.isPerspectiveCamera?Q*=e:j.object.isOrthographicCamera?(j.object.zoom=D(j.minZoom,A(j.maxZoom,j.object.zoom/e)),j.object.updateProjectionMatrix(),H=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),j.enableZoom=!1)}function s(e){q.set(e.clientX,e.clientY)}function d(e){ee.set(e.clientX,e.clientY)}function c(e){K.set(e.clientX,e.clientY)}function u(e){I.set(e.clientX,e.clientY),W.subVectors(I,q).multiplyScalar(j.rotateSpeed);var t=j.domElement===document?j.domElement.body:j.domElement;a(2*V*W.x/t.clientHeight),n(2*V*W.y/t.clientHeight),q.copy(I),j.update()}function p(e){te.set(e.clientX,e.clientY),oe.subVectors(te,ee),0oe.y&&l(r()),ee.copy(te),j.update()}function m(e){J.set(e.clientX,e.clientY),$.subVectors(J,K).multiplyScalar(j.panSpeed),ne($.x,$.y),K.copy(J),j.update()}function g(){}function f(e){0>e.deltaY?l(r()):0Z||8*(1-l.dot(j.object.quaternion))>Z)&&(j.dispatchEvent(N),i.copy(j.object.position),l.copy(j.object.quaternion),H=!1,!0)}}(),this.dispose=function(){j.domElement.removeEventListener("contextmenu",B,!1),j.domElement.removeEventListener("mousedown",T,!1),j.domElement.removeEventListener("wheel",M,!1),j.domElement.removeEventListener("touchstart",C,!1),j.domElement.removeEventListener("touchend",O,!1),j.domElement.removeEventListener("touchmove",k,!1),document.removeEventListener("mousemove",S,!1),document.removeEventListener("mouseup",E,!1),window.removeEventListener("keydown",w,!1)};var j=this,N={type:"change"},z={type:"start"},Y={type:"end"},X={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_DOLLY_PAN:4},_=X.NONE,Z=1e-6,F=new THREE.Spherical,G=new THREE.Spherical,Q=1,U=new THREE.Vector3,H=!1,q=new THREE.Vector2,I=new THREE.Vector2,W=new THREE.Vector2,K=new THREE.Vector2,J=new THREE.Vector2,$=new THREE.Vector2,ee=new THREE.Vector2,te=new THREE.Vector2,oe=new THREE.Vector2,re=function(){var e=new THREE.Vector3;return function(t,o){e.setFromMatrixColumn(o,0),e.multiplyScalar(-t),U.add(e)}}(),ae=function(){var e=new THREE.Vector3;return function(t,o){!0===j.screenSpacePanning?e.setFromMatrixColumn(o,1):(e.setFromMatrixColumn(o,0),e.crossVectors(j.object.up,e)),e.multiplyScalar(t),U.add(e)}}(),ne=function(){var e=new THREE.Vector3;return function(t,o){var r=j.domElement===document?j.domElement.body:j.domElement;if(j.object.isPerspectiveCamera){var a=j.object.position;e.copy(a).sub(j.target);var n=e.length();n*=Math.tan(j.object.fov/2*V/180),re(2*t*n/r.clientHeight,j.object.matrix),ae(2*o*n/r.clientHeight,j.object.matrix)}else j.object.isOrthographicCamera?(re(t*(j.object.right-j.object.left)/j.object.zoom/r.clientWidth,j.object.matrix),ae(o*(j.object.top-j.object.bottom)/j.object.zoom/r.clientHeight,j.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),j.enablePan=!1)}}();j.domElement.addEventListener("contextmenu",B,!1),j.domElement.addEventListener("mousedown",T,!1),j.domElement.addEventListener("wheel",M,!1),j.domElement.addEventListener("touchstart",C,!1),j.domElement.addEventListener("touchend",O,!1),j.domElement.addEventListener("touchmove",k,!1),window.addEventListener("keydown",w,!1),this.update()},THREE.OrbitControls.prototype=Object.create(THREE.EventDispatcher.prototype),THREE.OrbitControls.prototype.constructor=THREE.OrbitControls,Object.defineProperties(THREE.OrbitControls.prototype,{center:{get:function(){return console.warn("THREE.OrbitControls: .center has been renamed to .target"),this.target}},noZoom:{get:function(){return console.warn("THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead."),!this.enableZoom},set:function(e){console.warn("THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead."),this.enableZoom=!e}},noRotate:{get:function(){return console.warn("THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead."),!this.enableRotate},set:function(e){console.warn("THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead."),this.enableRotate=!e}},noPan:{get:function(){return console.warn("THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead."),!this.enablePan},set:function(e){console.warn("THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead."),this.enablePan=!e}},noKeys:{get:function(){return console.warn("THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead."),!this.enableKeys},set:function(e){console.warn("THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead."),this.enableKeys=!e}},staticMoving:{get:function(){return console.warn("THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead."),!this.enableDamping},set:function(e){console.warn("THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead."),this.enableDamping=!e}},dynamicDampingFactor:{get:function(){return console.warn("THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead."),this.dampingFactor},set:function(e){console.warn("THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead."),this.dampingFactor=e}}}),"use strict";function toggleFullScreen(){(!document.fullScreenElement||null===document.fullScreenElement)&&(document.mozFullScreen||document.webkitIsFullScreen)?document.cancelFullScreen?document.cancelFullScreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.webkitCancelFullScreen&&document.webkitCancelFullScreen():document.documentElement.requestFullScreen?document.documentElement.requestFullScreen():document.documentElement.mozRequestFullScreen?document.documentElement.mozRequestFullScreen():document.documentElement.webkitRequestFullScreen&&document.documentElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var o,r=0;r\nvarying vec4 vPosition;\nvarying vec4 projTexCoord;\nuniform sampler2D depthTexture;\nuniform vec2 cameraNearFar;\nvoid main() {\n float depth = unpackRGBAToDepth(texture2DProj(depthTexture, projTexCoord));\n float viewZ = - DEPTH_TO_VIEW_Z(depth, cameraNearFar.x, cameraNearFar.y);\n float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;\n gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);\n}"})},getEdgeDetectionMaterial:function(){return new THREE.ShaderMaterial({uniforms:{maskTexture:{value:null},texSize:{value:new THREE.Vector2(.5,.5)},visibleEdgeColor:{value:new THREE.Vector3(1,1,1)},hiddenEdgeColor:{value:new THREE.Vector3(1,1,1)}},vertexShader:"varying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}",fragmentShader:"varying vec2 vUv;\nuniform sampler2D maskTexture;\nuniform vec2 texSize;\nuniform vec3 visibleEdgeColor;\nuniform vec3 hiddenEdgeColor;\nvoid main() {\n vec2 invSize = 1.0 / texSize;\n vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);\n vec4 c1 = texture2D(maskTexture, vUv + uvOffset.xy);\n vec4 c2 = texture2D(maskTexture, vUv - uvOffset.xy);\n vec4 c3 = texture2D(maskTexture, vUv + uvOffset.yw);\n vec4 c4 = texture2D(maskTexture, vUv - uvOffset.yw);\n float diff1 = (c1.r - c2.r)*0.5;\n float diff2 = (c3.r - c4.r)*0.5;\n float d = length(vec2(diff1, diff2));\n float a1 = min(c1.g, c2.g);\n float a2 = min(c3.g, c4.g);\n float visibilityFactor = min(a1, a2);\n vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\n gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\n}"})},getSeperableBlurMaterial:function(e){return new THREE.ShaderMaterial({defines:{MAX_RADIUS:e},uniforms:{colorTexture:{value:null},texSize:{value:new THREE.Vector2(.5,.5)},direction:{value:new THREE.Vector2(.5,.5)},kernelRadius:{value:1}},vertexShader:"varying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}",fragmentShader:"#include \nvarying vec2 vUv;\nuniform sampler2D colorTexture;\nuniform vec2 direction;\nuniform vec2 texSize;\nuniform float kernelRadius;\nfloat gaussianPdf(in float x, in float sigma) {\n return 0.39894 * exp(-0.5 * x * x/(sigma * sigma))/sigma;\n}\nvoid main() {\n vec2 invSize = 1.0 / texSize;\n float weightSum = gaussianPdf(0.0, kernelRadius);\n vec3 diffuseSum = texture2D(colorTexture, vUv).rgb * weightSum;\n vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\n vec2 uvOffset = delta;\n for(int i = 1; i <= MAX_RADIUS; i ++) {\n float w = gaussianPdf(uvOffset.x, kernelRadius);\n vec3 sample1 = texture2D(colorTexture, vUv + uvOffset).rgb;\n vec3 sample2 = texture2D(colorTexture, vUv - uvOffset).rgb;\n diffuseSum += ((sample1 + sample2) * w);\n weightSum += (2.0 * w);\n uvOffset += delta;\n }\n gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\n}"})},getOverlayMaterial:function(){return new THREE.ShaderMaterial({uniforms:{maskTexture:{value:null},edgeTexture1:{value:null},edgeTexture2:{value:null},patternTexture:{value:null},edgeStrength:{value:1},edgeGlow:{value:1},usePatternTexture:{value:0}},vertexShader:"varying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}",fragmentShader:"varying vec2 vUv;\nuniform sampler2D maskTexture;\nuniform sampler2D edgeTexture1;\nuniform sampler2D edgeTexture2;\nuniform sampler2D patternTexture;\nuniform float edgeStrength;\nuniform float edgeGlow;\nuniform bool usePatternTexture;\nvoid main() {\n vec4 edgeValue1 = texture2D(edgeTexture1, vUv);\n vec4 edgeValue2 = texture2D(edgeTexture2, vUv);\n vec4 maskColor = texture2D(maskTexture, vUv);\n vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);\n float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;\n vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;\n vec4 finalColor = edgeStrength * maskColor.r * edgeValue;\n if(usePatternTexture)\n finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\n gl_FragColor = finalColor;\n}",blending:THREE.AdditiveBlending,depthTest:!1,depthWrite:!1,transparent:!0})}}),THREE.OutlinePass.BlurDirectionX=new THREE.Vector2(1,0),THREE.OutlinePass.BlurDirectionY=new THREE.Vector2(0,1),"use strict",THREE.TransformControls=function(e,t){var s=Math.round;function o(e,t){var o=t;Object.defineProperty(u,e,{get:function(){return o===void 0?t:o},set:function(t){o!==t&&(o=t,c[e]=t,d[e]=t,u.dispatchEvent({type:e+"-changed",value:t}),u.dispatchEvent(p))}}),u[e]=t,c[e]=t,d[e]=t}function r(e){var o=e.changedTouches?e.changedTouches[0]:e,r=t.getBoundingClientRect();return{x:2*((o.clientX-r.left)/r.width)-1,y:2*(-(o.clientY-r.top)/r.height)+1,button:e.button}}function a(e){u.enabled&&u.pointerHover(r(e))}function n(e){u.enabled&&(document.addEventListener("mousemove",i,!1),u.pointerHover(r(e)),u.pointerDown(r(e)))}function i(e){u.enabled&&u.pointerMove(r(e))}function l(e){u.enabled&&(document.removeEventListener("mousemove",i,!1),u.pointerUp(r(e)))}THREE.Object3D.call(this),t=t===void 0?document:t,this.visible=!1;var d=new THREE.TransformControlsGizmo;this.add(d);var c=new THREE.TransformControlsPlane;this.add(c);var u=this;o("camera",e),o("object",void 0),o("enabled",!0),o("axis",null),o("mode","translate"),o("translationSnap",null),o("rotationSnap",null),o("space","world"),o("size",1),o("dragging",!1),o("showX",!0),o("showY",!0),o("showZ",!0);var p={type:"change"},m={type:"mouseDown"},g={type:"mouseUp",mode:u.mode},f={type:"objectChange"},b=new THREE.Raycaster,y=new THREE.Vector3,h=new THREE.Vector3,v=new THREE.Quaternion,P={X:new THREE.Vector3(1,0,0),Y:new THREE.Vector3(0,1,0),Z:new THREE.Vector3(0,0,1)},x=new THREE.Vector3,T=new THREE.Vector3,S=new THREE.Vector3,E=new THREE.Vector3,M=new THREE.Vector3,w=new THREE.Vector3,C=0,k=new THREE.Vector3,O=new THREE.Quaternion,B=new THREE.Vector3,R=new THREE.Vector3,D=new THREE.Quaternion,A=new THREE.Quaternion,L=new THREE.Vector3,V=new THREE.Vector3,j=new THREE.Quaternion,N=new THREE.Vector3,z=new THREE.Vector3,Y=new THREE.Quaternion,X=new THREE.Quaternion,_=new THREE.Vector3,Z=new THREE.Vector3,F=new THREE.Vector3,G=new THREE.Quaternion,Q=new THREE.Vector3;o("worldPosition",z),o("worldPositionStart",V),o("worldQuaternion",Y),o("worldQuaternionStart",j),o("cameraPosition",k),o("cameraQuaternion",O),o("pointStart",x),o("pointEnd",T),o("rotationAxis",E),o("rotationAngle",C),o("eye",Z),t.addEventListener("mousedown",n,!1),t.addEventListener("touchstart",n,!1),t.addEventListener("mousemove",a,!1),t.addEventListener("touchmove",a,!1),t.addEventListener("touchmove",i,!1),document.addEventListener("mouseup",l,!1),t.addEventListener("touchend",l,!1),t.addEventListener("touchcancel",l,!1),t.addEventListener("touchleave",l,!1),this.dispose=function(){t.removeEventListener("mousedown",n),t.removeEventListener("touchstart",n),t.removeEventListener("mousemove",a),t.removeEventListener("touchmove",a),t.removeEventListener("touchmove",i),document.removeEventListener("mouseup",l),t.removeEventListener("touchend",l),t.removeEventListener("touchcancel",l),t.removeEventListener("touchleave",l),this.traverse(function(e){e.geometry&&e.geometry.dispose(),e.material&&e.material.dispose()})},this.attach=function(e){this.object=e,this.visible=!0},this.detach=function(){this.object=void 0,this.visible=!1,this.axis=null},this.updateMatrixWorld=function(){this.object!==void 0&&(this.object.updateMatrixWorld(),this.object.parent.matrixWorld.decompose(R,D,L),this.object.matrixWorld.decompose(z,Y,_),A.copy(D).inverse(),X.copy(Y).inverse()),this.camera.updateMatrixWorld(),this.camera.matrixWorld.decompose(k,O,B),this.camera instanceof THREE.PerspectiveCamera?Z.copy(k).sub(z).normalize():this.camera instanceof THREE.OrthographicCamera&&Z.copy(k).normalize(),THREE.Object3D.prototype.updateMatrixWorld.call(this)},this.pointerHover=function(e){if(void 0!==this.object&&!0!==this.dragging&&(void 0===e.button||0===e.button)){b.setFromCamera(e,this.camera);var t=b.intersectObjects(d.picker[this.mode].children,!0)[0]||!1;this.axis=t?t.object.name:null}},this.pointerDown=function(e){if(void 0!==this.object&&!0!==this.dragging&&(void 0===e.button||0===e.button)&&(0===e.button||void 0===e.button)&&null!==this.axis){b.setFromCamera(e,this.camera);var t=b.intersectObjects([c],!0)[0]||!1;if(t){var o=this.space;if("scale"===this.mode?o="local":("E"===this.axis||"XYZE"===this.axis||"XYZ"===this.axis)&&(o="world"),"local"===o&&"rotate"===this.mode){var r=this.rotationSnap;"X"===this.axis&&r&&(this.object.rotation.x=s(this.object.rotation.x/r)*r),"Y"===this.axis&&r&&(this.object.rotation.y=s(this.object.rotation.y/r)*r),"Z"===this.axis&&r&&(this.object.rotation.z=s(this.object.rotation.z/r)*r)}this.object.updateMatrixWorld(),this.object.parent.updateMatrixWorld(),F.copy(this.object.position),G.copy(this.object.quaternion),Q.copy(this.object.scale),this.object.matrixWorld.decompose(V,j,N),x.copy(t.point).sub(V)}this.dragging=!0,m.mode=this.mode,this.dispatchEvent(m)}},this.pointerMove=function(e){var t=this.axis,o=this.mode,r=this.object,a=this.space;if("scale"===o?a="local":("E"===t||"XYZE"===t||"XYZ"===t)&&(a="world"),void 0!==r&&null!==t&&!1!==this.dragging&&(void 0===e.button||0===e.button)){b.setFromCamera(e,this.camera);var n=b.intersectObjects([c],!0)[0]||!1;if(!1!==n){if(T.copy(n.point).sub(V),"translate"===o)S.copy(T).sub(x),"local"===a&&"XYZ"!==t&&S.applyQuaternion(X),-1===t.indexOf("X")&&(S.x=0),-1===t.indexOf("Y")&&(S.y=0),-1===t.indexOf("Z")&&(S.z=0),"local"===a&&"XYZ"!==t?S.applyQuaternion(G).divide(L):S.applyQuaternion(A).divide(L),r.position.copy(S).add(F),this.translationSnap&&("local"===a&&(r.position.applyQuaternion(v.copy(G).inverse()),-1!==t.search("X")&&(r.position.x=s(r.position.x/this.translationSnap)*this.translationSnap),-1!==t.search("Y")&&(r.position.y=s(r.position.y/this.translationSnap)*this.translationSnap),-1!==t.search("Z")&&(r.position.z=s(r.position.z/this.translationSnap)*this.translationSnap),r.position.applyQuaternion(G)),"world"===a&&(r.parent&&r.position.add(y.setFromMatrixPosition(r.parent.matrixWorld)),-1!==t.search("X")&&(r.position.x=s(r.position.x/this.translationSnap)*this.translationSnap),-1!==t.search("Y")&&(r.position.y=s(r.position.y/this.translationSnap)*this.translationSnap),-1!==t.search("Z")&&(r.position.z=s(r.position.z/this.translationSnap)*this.translationSnap),r.parent&&r.position.sub(y.setFromMatrixPosition(r.parent.matrixWorld))));else if("scale"===o){if(-1!==t.search("XYZ")){var i=T.length()/x.length();0>T.dot(x)&&(i*=-1),h.set(i,i,i)}else y.copy(x),h.copy(T),y.applyQuaternion(X),h.applyQuaternion(X),h.divide(y),-1===t.search("X")&&(h.x=1),-1===t.search("Y")&&(h.y=1),-1===t.search("Z")&&(h.z=1);r.scale.copy(Q).multiply(h)}else if("rotate"===o){S.copy(T).sub(x);var l=20/z.distanceTo(y.setFromMatrixPosition(this.camera.matrixWorld));"E"===t?(E.copy(Z),C=T.angleTo(x),M.copy(x).normalize(),w.copy(T).normalize(),C*=0>w.cross(M).dot(Z)?1:-1):"XYZE"===t?(E.copy(S).cross(Z).normalize(),C=S.dot(y.copy(E).cross(this.eye))*l):("X"===t||"Y"===t||"Z"===t)&&(E.copy(P[t]),y.copy(P[t]),"local"===a&&y.applyQuaternion(Y),C=S.dot(y.cross(Z).normalize())*l),this.rotationSnap&&(C=s(C/this.rotationSnap)*this.rotationSnap),this.rotationAngle=C,"local"===a&&"E"!==t&&"XYZE"!==t?(r.quaternion.copy(G),r.quaternion.multiply(v.setFromAxisAngle(E,C)).normalize()):(E.applyQuaternion(A),r.quaternion.copy(v.setFromAxisAngle(E,C)),r.quaternion.multiply(G).normalize())}this.dispatchEvent(p),this.dispatchEvent(f)}}},this.pointerUp=function(e){void 0!==e.button&&0!==e.button||(this.dragging&&null!==this.axis&&(g.mode=this.mode,this.dispatchEvent(g)),this.dragging=!1,e.button===void 0&&(this.axis=null))},this.getMode=function(){return u.mode},this.setMode=function(e){u.mode=e},this.setTranslationSnap=function(e){u.translationSnap=e},this.setRotationSnap=function(e){u.rotationSnap=e},this.setSize=function(e){u.size=e},this.setSpace=function(e){u.space=e},this.update=function(){console.warn("THREE.TransformControls: update function has been depricated.")}},THREE.TransformControls.prototype=Object.assign(Object.create(THREE.Object3D.prototype),{constructor:THREE.TransformControls,isTransformControls:!0}),THREE.TransformControlsGizmo=function(){'use strict';var e=Math.abs,t=Math.cos,o=Math.PI;THREE.Object3D.call(this),this.type="TransformControlsGizmo";var r=new THREE.MeshBasicMaterial({depthTest:!1,depthWrite:!1,transparent:!0,side:THREE.DoubleSide,fog:!1}),a=new THREE.LineBasicMaterial({depthTest:!1,depthWrite:!1,transparent:!0,linewidth:1,fog:!1}),n=r.clone();n.opacity=.15;var i=r.clone();i.opacity=.33;var l=r.clone();l.color.set(16711680);var s=r.clone();s.color.set(65280);var d=r.clone();d.color.set(255);var c=r.clone();c.opacity=.25;var u=c.clone();u.color.set(16776960);var p=c.clone();p.color.set(65535);var m=c.clone();m.color.set(16711935);var g=r.clone();g.color.set(16776960);var f=a.clone();f.color.set(16711680);var b=a.clone();b.color.set(65280);var y=a.clone();y.color.set(255);var h=a.clone();h.color.set(65535);var v=a.clone();v.color.set(16711935);var P=a.clone();P.color.set(16776960);var x=a.clone();x.color.set(7895160);var T=P.clone();T.opacity=.25;var S=new THREE.CylinderBufferGeometry(0,.05,.2,12,1,!1),E=new THREE.BoxBufferGeometry(.125,.125,.125),M=new THREE.BufferGeometry;M.addAttribute("position",new THREE.Float32BufferAttribute([0,0,0,1,0,0],3));var w=function(e,r){for(var a=Math.sin,n=new THREE.BufferGeometry,l=[],s=0;s<=64*r;++s)l.push(0,t(s/32*o)*e,a(s/32*o)*e);return n.addAttribute("position",new THREE.Float32BufferAttribute(l,3)),n},C={X:[[new THREE.Mesh(S,l),[1,0,0],[0,0,-o/2],null,"fwd"],[new THREE.Mesh(S,l),[1,0,0],[0,0,o/2],null,"bwd"],[new THREE.Line(M,f)]],Y:[[new THREE.Mesh(S,s),[0,1,0],null,null,"fwd"],[new THREE.Mesh(S,s),[0,1,0],[o,0,0],null,"bwd"],[new THREE.Line(M,b),null,[0,0,o/2]]],Z:[[new THREE.Mesh(S,d),[0,0,1],[o/2,0,0],null,"fwd"],[new THREE.Mesh(S,d),[0,0,1],[-o/2,0,0],null,"bwd"],[new THREE.Line(M,y),null,[0,-o/2,0]]],XYZ:[[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.1,0),c),[0,0,0],[0,0,0]]],XY:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.295,.295),u),[.15,.15,0]],[new THREE.Line(M,P),[.18,.3,0],null,[.125,1,1]],[new THREE.Line(M,P),[.3,.18,0],[0,0,o/2],[.125,1,1]]],YZ:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.295,.295),p),[0,.15,.15],[0,o/2,0]],[new THREE.Line(M,h),[0,.18,.3],[0,0,o/2],[.125,1,1]],[new THREE.Line(M,h),[0,.3,.18],[0,-o/2,0],[.125,1,1]]],XZ:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.295,.295),m),[.15,0,.15],[-o/2,0,0]],[new THREE.Line(M,v),[.18,0,.3],null,[.125,1,1]],[new THREE.Line(M,v),[.3,0,.18],[0,-o/2,0],[.125,1,1]]]},k={X:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,1,4,1,!1),n),[.6,0,0],[0,0,-o/2]]],Y:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,1,4,1,!1),n),[0,.6,0]]],Z:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,1,4,1,!1),n),[0,0,.6],[o/2,0,0]]],XYZ:[[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.2,0),n)]],XY:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.4,.4),n),[.2,.2,0]]],YZ:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.4,.4),n),[0,.2,.2],[0,o/2,0]]],XZ:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.4,.4),n),[.2,0,.2],[-o/2,0,0]]]},O={START:[[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.01,2),i),null,null,null,"helper"]],END:[[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.01,2),i),null,null,null,"helper"]],DELTA:[[new THREE.Line(function(){var e=new THREE.BufferGeometry;return e.addAttribute("position",new THREE.Float32BufferAttribute([0,0,0,1,1,1],3)),e}(),i),null,null,null,"helper"]],X:[[new THREE.Line(M,i.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]],Y:[[new THREE.Line(M,i.clone()),[0,-1e3,0],[0,0,o/2],[1e6,1,1],"helper"]],Z:[[new THREE.Line(M,i.clone()),[0,0,-1e3],[0,-o/2,0],[1e6,1,1],"helper"]]},B={X:[[new THREE.Line(w(1,.5),f)],[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.04,0),l),[0,0,.99],null,[1,3,1]]],Y:[[new THREE.Line(w(1,.5),b),null,[0,0,-o/2]],[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.04,0),s),[0,0,.99],null,[3,1,1]]],Z:[[new THREE.Line(w(1,.5),y),null,[0,o/2,0]],[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.04,0),d),[.99,0,0],null,[1,3,1]]],E:[[new THREE.Line(w(1.25,1),T),null,[0,o/2,0]],[new THREE.Mesh(new THREE.CylinderBufferGeometry(.03,0,.15,4,1,!1),T),[1.17,0,0],[0,0,-o/2],[1,1,.001]],[new THREE.Mesh(new THREE.CylinderBufferGeometry(.03,0,.15,4,1,!1),T),[-1.17,0,0],[0,0,o/2],[1,1,.001]],[new THREE.Mesh(new THREE.CylinderBufferGeometry(.03,0,.15,4,1,!1),T),[0,-1.17,0],[o,0,0],[1,1,.001]],[new THREE.Mesh(new THREE.CylinderBufferGeometry(.03,0,.15,4,1,!1),T),[0,1.17,0],[0,0,0],[1,1,.001]]],XYZE:[[new THREE.Line(w(1,1),x),null,[0,o/2,0]]]},R={AXIS:[[new THREE.Line(M,i.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]]},D={X:[[new THREE.Mesh(new THREE.TorusBufferGeometry(1,.1,4,24),n),[0,0,0],[0,-o/2,-o/2]]],Y:[[new THREE.Mesh(new THREE.TorusBufferGeometry(1,.1,4,24),n),[0,0,0],[o/2,0,0]]],Z:[[new THREE.Mesh(new THREE.TorusBufferGeometry(1,.1,4,24),n),[0,0,0],[0,0,-o/2]]],E:[[new THREE.Mesh(new THREE.TorusBufferGeometry(1.25,.1,2,24),n)]],XYZE:[[new THREE.Mesh(new THREE.SphereBufferGeometry(.7,10,8),n)]]},A={X:[[new THREE.Mesh(E,l),[.8,0,0],[0,0,-o/2]],[new THREE.Line(M,f),null,null,[.8,1,1]]],Y:[[new THREE.Mesh(E,s),[0,.8,0]],[new THREE.Line(M,b),null,[0,0,o/2],[.8,1,1]]],Z:[[new THREE.Mesh(E,d),[0,0,.8],[o/2,0,0]],[new THREE.Line(M,y),null,[0,-o/2,0],[.8,1,1]]],XY:[[new THREE.Mesh(E,u),[.85,.85,0],null,[2,2,.2]],[new THREE.Line(M,P),[.855,.98,0],null,[.125,1,1]],[new THREE.Line(M,P),[.98,.855,0],[0,0,o/2],[.125,1,1]]],YZ:[[new THREE.Mesh(E,p),[0,.85,.85],null,[.2,2,2]],[new THREE.Line(M,h),[0,.855,.98],[0,0,o/2],[.125,1,1]],[new THREE.Line(M,h),[0,.98,.855],[0,-o/2,0],[.125,1,1]]],XZ:[[new THREE.Mesh(E,m),[.85,0,.85],null,[2,.2,2]],[new THREE.Line(M,v),[.855,0,.98],null,[.125,1,1]],[new THREE.Line(M,v),[.98,0,.855],[0,-o/2,0],[.125,1,1]]],XYZX:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.125,.125,.125),c),[1.1,0,0]]],XYZY:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.125,.125,.125),c),[0,1.1,0]]],XYZZ:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.125,.125,.125),c),[0,0,1.1]]]},L={X:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,.8,4,1,!1),n),[.5,0,0],[0,0,-o/2]]],Y:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,.8,4,1,!1),n),[0,.5,0]]],Z:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,.8,4,1,!1),n),[0,0,.5],[o/2,0,0]]],XY:[[new THREE.Mesh(E,n),[.85,.85,0],null,[3,3,.2]]],YZ:[[new THREE.Mesh(E,n),[0,.85,.85],null,[.2,3,3]]],XZ:[[new THREE.Mesh(E,n),[.85,0,.85],null,[3,.2,3]]],XYZX:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.2,.2,.2),n),[1.1,0,0]]],XYZY:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.2,.2,.2),n),[0,1.1,0]]],XYZZ:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.2,.2,.2),n),[0,0,1.1]]]},V={X:[[new THREE.Line(M,i.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]],Y:[[new THREE.Line(M,i.clone()),[0,-1e3,0],[0,0,o/2],[1e6,1,1],"helper"]],Z:[[new THREE.Line(M,i.clone()),[0,0,-1e3],[0,-o/2,0],[1e6,1,1],"helper"]]},j=function(e){var t=new THREE.Object3D;for(var o in e)for(var r=e[o].length;r--;){var a=e[o][r][0].clone(),n=e[o][r][1],l=e[o][r][2],s=e[o][r][3],d=e[o][r][4];a.name=o,a.tag=d,n&&a.position.set(n[0],n[1],n[2]),l&&a.rotation.set(l[0],l[1],l[2]),s&&a.scale.set(s[0],s[1],s[2]),a.updateMatrix();var c=a.geometry.clone();c.applyMatrix(a.matrix),a.geometry=c,a.renderOrder=1/0,a.position.set(0,0,0),a.rotation.set(0,0,0),a.scale.set(1,1,1),t.add(a)}return t},N=new THREE.Vector3(0,0,0),z=new THREE.Euler,Y=new THREE.Vector3(0,1,0),X=new THREE.Vector3(0,0,0),_=new THREE.Matrix4,Z=new THREE.Quaternion,F=new THREE.Quaternion,G=new THREE.Quaternion,Q=new THREE.Vector3(1,0,0),U=new THREE.Vector3(0,1,0),H=new THREE.Vector3(0,0,1);this.gizmo={},this.picker={},this.helper={},this.add(this.gizmo.translate=j(C)),this.add(this.gizmo.rotate=j(B)),this.add(this.gizmo.scale=j(A)),this.add(this.picker.translate=j(k)),this.add(this.picker.rotate=j(D)),this.add(this.picker.scale=j(L)),this.add(this.helper.translate=j(O)),this.add(this.helper.rotate=j(R)),this.add(this.helper.scale=j(V)),this.picker.translate.visible=!1,this.picker.rotate.visible=!1,this.picker.scale.visible=!1,this.updateMatrixWorld=function(){var t=Math.atan2,r=this.space;"scale"===this.mode&&(r="local");var a="local"===r?this.worldQuaternion:G;this.gizmo.translate.visible="translate"===this.mode,this.gizmo.rotate.visible="rotate"===this.mode,this.gizmo.scale.visible="scale"===this.mode,this.helper.translate.visible="translate"===this.mode,this.helper.rotate.visible="rotate"===this.mode,this.helper.scale.visible="scale"===this.mode;var n=[];n=n.concat(this.picker[this.mode].children),n=n.concat(this.gizmo[this.mode].children),n=n.concat(this.helper[this.mode].children);for(var l,s=0;sc&&(l.scale.set(1e-10,1e-10,1e-10),l.visible=!1),("Y"===l.name||"XYZY"===l.name)&&e(Y.copy(U).applyQuaternion(a).dot(this.eye))>c&&(l.scale.set(1e-10,1e-10,1e-10),l.visible=!1),("Z"===l.name||"XYZZ"===l.name)&&e(Y.copy(H).applyQuaternion(a).dot(this.eye))>c&&(l.scale.set(1e-10,1e-10,1e-10),l.visible=!1),"XY"===l.name&&e(Y.copy(H).applyQuaternion(a).dot(this.eye))n?(r[0]=e[0],r[1]=e[1],r[2]=e[2]):(r[0]=e[0]/n,r[1]=e[1]/n,r[2]=e[2]/n),[r,a]}function quaternionToWebotsString(e){var t=quaternionToAxisAngle(e);return t[0][0]+" "+t[0][1]+" "+t[0][2]+" "+t[1]}function translationToWebotsString(e){return e[0]+" "+e[1]+" "+e[2]}function _typeof(e){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var o,r=0;r":"
",e.partIconDivs.push(o.firstChild),e.assetLibraryElement.appendChild(o.firstChild)})}},{key:"update",value:function(e){for(var t,o=e.getAvailableSlotTypes(),r=0;r"+e.name+"",this.element.appendChild(r);var a=document.createElement("p");if(!t)return a.innerHTML="No parameters",void this.element.appendChild(a);var n=document.createElement("form");if("color"in t){a.style.display="inline";var i=document.createTextNode("Color: ");a.appendChild(i),n.appendChild(a);var l=document.createElement("select");for(var s in l.style.display="inline",t.color){var d=document.createElement("option"),c=document.createTextNode(t.color[s]),u=document.createAttribute("value");u.value=t.color[s],d.setAttributeNode(u),d.appendChild(c),l.appendChild(d)}l.addEventListener("change",function(t){var r=t.target.value;o.robotController.changeColor(e,r)}),n.appendChild(l)}this.element.appendChild(n)}},{key:"_cleanupDiv",value:function(e){this.element.innerHTML="

"+e+"

"}}]),e}();function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var o,r=0;rl&&(n=o,i=l)}}),n}},{key:"projectScreenPositionOnFloor",value:function(e){var o=new THREE.Raycaster;o.setFromCamera(e,this.camera);var r=new THREE.Mesh(new THREE.PlaneGeometry(100,100));r.geometry.rotateX(-t/2);var a=new THREE.Mesh(new THREE.PlaneGeometry(100,100));a.geometry.rotateX(t/2);var n=o.intersectObjects([r,a]);if(0o&&(designer.robotViewer.selector.selectPart(designer.partToBeSelected),designer.robotViewer.handle.attachToObject(designer.partToBeSelected)),designer.partToBeSelected=void 0,designer.mouseDownPosition=void 0}}function deleteSelectedPart(){var e=designer.robotViewer.selector.selectedPart;if(e){var t=e;do{if(t.userData.isPartContainer){designer.robotController.removePart(t.mediator.model);break}t=t.parent}while(t)}designer.robotViewer.clearSelection()}function mouseMove(e){if(!designer.robotViewer.handle.isDragging()){var t=designer.robotViewer.robotViewerElement,o=MouseEvents.convertMouseEventPositionToRelativePosition(t,e.clientX,e.clientY),r=MouseEvents.convertMouseEventPositionToScreenPosition(t,e.clientX,e.clientY),a=designer.robotViewer.getPartAt(o,r);a?designer.robotViewer.highlightor.highlight(a):designer.robotViewer.highlightor.clearHighlight()}}function drop(e){e.preventDefault(),designer.dragger.drop(e.clientX,e.clientY)}function dragStart(e){var t=e.target.getAttribute("part"),o=e.target.getAttribute("slotType");e.dataTransfer.setData("text",t);var r=document.createElement("img");r.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",e.dataTransfer.setDragImage(r,0,0),designer.dragger.dragStart(t,o)}function dragOver(e){e.preventDefault(),e.dataTransfer.getData("text"),designer.dragger.dragOver(e.clientX,e.clientY)}function dragLeave(){designer.dragger.dragLeave()}function dragEnter(){designer.dragger.dragEnter()} \ No newline at end of file +"use strict";THREE.OrbitControls=function(e,t){var L=Math.sqrt,D=Math.max,R=Math.min,A=Math.pow,V=Math.PI;function o(){return 2*V/60/60*j.autoRotateSpeed}function r(){return A(.95,j.zoomSpeed)}function a(e){G.theta-=e}function n(e){G.phi-=e}function i(e){j.object.isPerspectiveCamera?U/=e:j.object.isOrthographicCamera?(j.object.zoom=D(j.minZoom,R(j.maxZoom,j.object.zoom*e)),j.object.updateProjectionMatrix(),H=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),j.enableZoom=!1)}function s(e){j.object.isPerspectiveCamera?U*=e:j.object.isOrthographicCamera?(j.object.zoom=D(j.minZoom,R(j.maxZoom,j.object.zoom/e)),j.object.updateProjectionMatrix(),H=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),j.enableZoom=!1)}function l(e){q.set(e.clientX,e.clientY)}function d(e){ee.set(e.clientX,e.clientY)}function c(e){K.set(e.clientX,e.clientY)}function u(e){I.set(e.clientX,e.clientY),W.subVectors(I,q).multiplyScalar(j.rotateSpeed);var t=j.domElement===document?j.domElement.body:j.domElement;a(2*V*W.x/t.clientHeight),n(2*V*W.y/t.clientHeight),q.copy(I),j.update()}function p(e){te.set(e.clientX,e.clientY),oe.subVectors(te,ee),0oe.y&&s(r()),ee.copy(te),j.update()}function m(e){J.set(e.clientX,e.clientY),$.subVectors(J,K).multiplyScalar(j.panSpeed),ne($.x,$.y),K.copy(J),j.update()}function b(){}function g(e){0>e.deltaY?s(r()):0Z||8*(1-s.dot(j.object.quaternion))>Z)&&(j.dispatchEvent(N),i.copy(j.object.position),s.copy(j.object.quaternion),H=!1,!0)}}(),this.dispose=function(){j.domElement.removeEventListener("contextmenu",B,!1),j.domElement.removeEventListener("mousedown",x,!1),j.domElement.removeEventListener("wheel",M,!1),j.domElement.removeEventListener("touchstart",C,!1),j.domElement.removeEventListener("touchend",O,!1),j.domElement.removeEventListener("touchmove",k,!1),document.removeEventListener("mousemove",T,!1),document.removeEventListener("mouseup",S,!1),window.removeEventListener("keydown",w,!1)};var j=this,N={type:"change"},z={type:"start"},_={type:"end"},X={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_DOLLY_PAN:4},Y=X.NONE,Z=1e-6,F=new THREE.Spherical,G=new THREE.Spherical,U=1,Q=new THREE.Vector3,H=!1,q=new THREE.Vector2,I=new THREE.Vector2,W=new THREE.Vector2,K=new THREE.Vector2,J=new THREE.Vector2,$=new THREE.Vector2,ee=new THREE.Vector2,te=new THREE.Vector2,oe=new THREE.Vector2,re=function(){var e=new THREE.Vector3;return function(t,o){e.setFromMatrixColumn(o,0),e.multiplyScalar(-t),Q.add(e)}}(),ae=function(){var e=new THREE.Vector3;return function(t,o){!0===j.screenSpacePanning?e.setFromMatrixColumn(o,1):(e.setFromMatrixColumn(o,0),e.crossVectors(j.object.up,e)),e.multiplyScalar(t),Q.add(e)}}(),ne=function(){var e=new THREE.Vector3;return function(t,o){var r=j.domElement===document?j.domElement.body:j.domElement;if(j.object.isPerspectiveCamera){var a=j.object.position;e.copy(a).sub(j.target);var n=e.length();n*=Math.tan(j.object.fov/2*V/180),re(2*t*n/r.clientHeight,j.object.matrix),ae(2*o*n/r.clientHeight,j.object.matrix)}else j.object.isOrthographicCamera?(re(t*(j.object.right-j.object.left)/j.object.zoom/r.clientWidth,j.object.matrix),ae(o*(j.object.top-j.object.bottom)/j.object.zoom/r.clientHeight,j.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),j.enablePan=!1)}}();j.domElement.addEventListener("contextmenu",B,!1),j.domElement.addEventListener("mousedown",x,!1),j.domElement.addEventListener("wheel",M,!1),j.domElement.addEventListener("touchstart",C,!1),j.domElement.addEventListener("touchend",O,!1),j.domElement.addEventListener("touchmove",k,!1),window.addEventListener("keydown",w,!1),this.update()},THREE.OrbitControls.prototype=Object.create(THREE.EventDispatcher.prototype),THREE.OrbitControls.prototype.constructor=THREE.OrbitControls,Object.defineProperties(THREE.OrbitControls.prototype,{center:{get:function(){return console.warn("THREE.OrbitControls: .center has been renamed to .target"),this.target}},noZoom:{get:function(){return console.warn("THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead."),!this.enableZoom},set:function(e){console.warn("THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead."),this.enableZoom=!e}},noRotate:{get:function(){return console.warn("THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead."),!this.enableRotate},set:function(e){console.warn("THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead."),this.enableRotate=!e}},noPan:{get:function(){return console.warn("THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead."),!this.enablePan},set:function(e){console.warn("THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead."),this.enablePan=!e}},noKeys:{get:function(){return console.warn("THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead."),!this.enableKeys},set:function(e){console.warn("THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead."),this.enableKeys=!e}},staticMoving:{get:function(){return console.warn("THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead."),!this.enableDamping},set:function(e){console.warn("THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead."),this.enableDamping=!e}},dynamicDampingFactor:{get:function(){return console.warn("THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead."),this.dampingFactor},set:function(e){console.warn("THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead."),this.dampingFactor=e}}}),"use strict";function toggleFullScreen(){(!document.fullScreenElement||null===document.fullScreenElement)&&(document.mozFullScreen||document.webkitIsFullScreen)?document.cancelFullScreen?document.cancelFullScreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.webkitCancelFullScreen&&document.webkitCancelFullScreen():document.documentElement.requestFullScreen?document.documentElement.requestFullScreen():document.documentElement.mozRequestFullScreen?document.documentElement.mozRequestFullScreen():document.documentElement.webkitRequestFullScreen&&document.documentElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var o,r=0;r\nvarying vec4 vPosition;\nvarying vec4 projTexCoord;\nuniform sampler2D depthTexture;\nuniform vec2 cameraNearFar;\nvoid main() {\n float depth = unpackRGBAToDepth(texture2DProj(depthTexture, projTexCoord));\n float viewZ = - DEPTH_TO_VIEW_Z(depth, cameraNearFar.x, cameraNearFar.y);\n float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;\n gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);\n}"})},getEdgeDetectionMaterial:function(){return new THREE.ShaderMaterial({uniforms:{maskTexture:{value:null},texSize:{value:new THREE.Vector2(.5,.5)},visibleEdgeColor:{value:new THREE.Vector3(1,1,1)},hiddenEdgeColor:{value:new THREE.Vector3(1,1,1)}},vertexShader:"varying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}",fragmentShader:"varying vec2 vUv;\nuniform sampler2D maskTexture;\nuniform vec2 texSize;\nuniform vec3 visibleEdgeColor;\nuniform vec3 hiddenEdgeColor;\nvoid main() {\n vec2 invSize = 1.0 / texSize;\n vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);\n vec4 c1 = texture2D(maskTexture, vUv + uvOffset.xy);\n vec4 c2 = texture2D(maskTexture, vUv - uvOffset.xy);\n vec4 c3 = texture2D(maskTexture, vUv + uvOffset.yw);\n vec4 c4 = texture2D(maskTexture, vUv - uvOffset.yw);\n float diff1 = (c1.r - c2.r)*0.5;\n float diff2 = (c3.r - c4.r)*0.5;\n float d = length(vec2(diff1, diff2));\n float a1 = min(c1.g, c2.g);\n float a2 = min(c3.g, c4.g);\n float visibilityFactor = min(a1, a2);\n vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\n gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\n}"})},getSeperableBlurMaterial:function(e){return new THREE.ShaderMaterial({defines:{MAX_RADIUS:e},uniforms:{colorTexture:{value:null},texSize:{value:new THREE.Vector2(.5,.5)},direction:{value:new THREE.Vector2(.5,.5)},kernelRadius:{value:1}},vertexShader:"varying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}",fragmentShader:"#include \nvarying vec2 vUv;\nuniform sampler2D colorTexture;\nuniform vec2 direction;\nuniform vec2 texSize;\nuniform float kernelRadius;\nfloat gaussianPdf(in float x, in float sigma) {\n return 0.39894 * exp(-0.5 * x * x/(sigma * sigma))/sigma;\n}\nvoid main() {\n vec2 invSize = 1.0 / texSize;\n float weightSum = gaussianPdf(0.0, kernelRadius);\n vec3 diffuseSum = texture2D(colorTexture, vUv).rgb * weightSum;\n vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\n vec2 uvOffset = delta;\n for(int i = 1; i <= MAX_RADIUS; i ++) {\n float w = gaussianPdf(uvOffset.x, kernelRadius);\n vec3 sample1 = texture2D(colorTexture, vUv + uvOffset).rgb;\n vec3 sample2 = texture2D(colorTexture, vUv - uvOffset).rgb;\n diffuseSum += ((sample1 + sample2) * w);\n weightSum += (2.0 * w);\n uvOffset += delta;\n }\n gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\n}"})},getOverlayMaterial:function(){return new THREE.ShaderMaterial({uniforms:{maskTexture:{value:null},edgeTexture1:{value:null},edgeTexture2:{value:null},patternTexture:{value:null},edgeStrength:{value:1},edgeGlow:{value:1},usePatternTexture:{value:0}},vertexShader:"varying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}",fragmentShader:"varying vec2 vUv;\nuniform sampler2D maskTexture;\nuniform sampler2D edgeTexture1;\nuniform sampler2D edgeTexture2;\nuniform sampler2D patternTexture;\nuniform float edgeStrength;\nuniform float edgeGlow;\nuniform bool usePatternTexture;\nvoid main() {\n vec4 edgeValue1 = texture2D(edgeTexture1, vUv);\n vec4 edgeValue2 = texture2D(edgeTexture2, vUv);\n vec4 maskColor = texture2D(maskTexture, vUv);\n vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);\n float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;\n vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;\n vec4 finalColor = edgeStrength * maskColor.r * edgeValue;\n if(usePatternTexture)\n finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\n gl_FragColor = finalColor;\n}",blending:THREE.AdditiveBlending,depthTest:!1,depthWrite:!1,transparent:!0})}}),THREE.OutlinePass.BlurDirectionX=new THREE.Vector2(1,0),THREE.OutlinePass.BlurDirectionY=new THREE.Vector2(0,1),"use strict",THREE.TransformControls=function(e,t){var l=Math.round;function o(e,t){var o=t;Object.defineProperty(u,e,{get:function(){return o===void 0?t:o},set:function(t){o!==t&&(o=t,c[e]=t,d[e]=t,u.dispatchEvent({type:e+"-changed",value:t}),u.dispatchEvent(p))}}),u[e]=t,c[e]=t,d[e]=t}function r(e){var o=e.changedTouches?e.changedTouches[0]:e,r=t.getBoundingClientRect();return{x:2*((o.clientX-r.left)/r.width)-1,y:2*(-(o.clientY-r.top)/r.height)+1,button:e.button}}function a(e){u.enabled&&u.pointerHover(r(e))}function n(e){u.enabled&&(document.addEventListener("mousemove",i,!1),u.pointerHover(r(e)),u.pointerDown(r(e)))}function i(e){u.enabled&&u.pointerMove(r(e))}function s(e){u.enabled&&(document.removeEventListener("mousemove",i,!1),u.pointerUp(r(e)))}THREE.Object3D.call(this),t=t===void 0?document:t,this.visible=!1;var d=new THREE.TransformControlsGizmo;this.add(d);var c=new THREE.TransformControlsPlane;this.add(c);var u=this;o("camera",e),o("object",void 0),o("enabled",!0),o("axis",null),o("mode","translate"),o("translationSnap",null),o("rotationSnap",null),o("space","world"),o("size",1),o("dragging",!1),o("showX",!0),o("showY",!0),o("showZ",!0);var p={type:"change"},m={type:"mouseDown"},b={type:"mouseUp",mode:u.mode},g={type:"objectChange"},y=new THREE.Raycaster,f=new THREE.Vector3,v=new THREE.Vector3,h=new THREE.Quaternion,P={X:new THREE.Vector3(1,0,0),Y:new THREE.Vector3(0,1,0),Z:new THREE.Vector3(0,0,1)},E=new THREE.Vector3,x=new THREE.Vector3,T=new THREE.Vector3,S=new THREE.Vector3,M=new THREE.Vector3,w=new THREE.Vector3,C=0,k=new THREE.Vector3,O=new THREE.Quaternion,B=new THREE.Vector3,L=new THREE.Vector3,D=new THREE.Quaternion,R=new THREE.Quaternion,A=new THREE.Vector3,V=new THREE.Vector3,j=new THREE.Quaternion,N=new THREE.Vector3,z=new THREE.Vector3,_=new THREE.Quaternion,X=new THREE.Quaternion,Y=new THREE.Vector3,Z=new THREE.Vector3,F=new THREE.Vector3,G=new THREE.Quaternion,U=new THREE.Vector3;o("worldPosition",z),o("worldPositionStart",V),o("worldQuaternion",_),o("worldQuaternionStart",j),o("cameraPosition",k),o("cameraQuaternion",O),o("pointStart",E),o("pointEnd",x),o("rotationAxis",S),o("rotationAngle",C),o("eye",Z),t.addEventListener("mousedown",n,!1),t.addEventListener("touchstart",n,!1),t.addEventListener("mousemove",a,!1),t.addEventListener("touchmove",a,!1),t.addEventListener("touchmove",i,!1),document.addEventListener("mouseup",s,!1),t.addEventListener("touchend",s,!1),t.addEventListener("touchcancel",s,!1),t.addEventListener("touchleave",s,!1),this.dispose=function(){t.removeEventListener("mousedown",n),t.removeEventListener("touchstart",n),t.removeEventListener("mousemove",a),t.removeEventListener("touchmove",a),t.removeEventListener("touchmove",i),document.removeEventListener("mouseup",s),t.removeEventListener("touchend",s),t.removeEventListener("touchcancel",s),t.removeEventListener("touchleave",s),this.traverse(function(e){e.geometry&&e.geometry.dispose(),e.material&&e.material.dispose()})},this.attach=function(e){this.object=e,this.visible=!0},this.detach=function(){this.object=void 0,this.visible=!1,this.axis=null},this.updateMatrixWorld=function(){this.object!==void 0&&(this.object.updateMatrixWorld(),this.object.parent.matrixWorld.decompose(L,D,A),this.object.matrixWorld.decompose(z,_,Y),R.copy(D).inverse(),X.copy(_).inverse()),this.camera.updateMatrixWorld(),this.camera.matrixWorld.decompose(k,O,B),this.camera instanceof THREE.PerspectiveCamera?Z.copy(k).sub(z).normalize():this.camera instanceof THREE.OrthographicCamera&&Z.copy(k).normalize(),THREE.Object3D.prototype.updateMatrixWorld.call(this)},this.pointerHover=function(e){if(void 0!==this.object&&!0!==this.dragging&&(void 0===e.button||0===e.button)){y.setFromCamera(e,this.camera);var t=y.intersectObjects(d.picker[this.mode].children,!0)[0]||!1;this.axis=t?t.object.name:null}},this.pointerDown=function(e){if(void 0!==this.object&&!0!==this.dragging&&(void 0===e.button||0===e.button)&&(0===e.button||void 0===e.button)&&null!==this.axis){y.setFromCamera(e,this.camera);var t=y.intersectObjects([c],!0)[0]||!1;if(t){var o=this.space;if("scale"===this.mode?o="local":("E"===this.axis||"XYZE"===this.axis||"XYZ"===this.axis)&&(o="world"),"local"===o&&"rotate"===this.mode){var r=this.rotationSnap;"X"===this.axis&&r&&(this.object.rotation.x=l(this.object.rotation.x/r)*r),"Y"===this.axis&&r&&(this.object.rotation.y=l(this.object.rotation.y/r)*r),"Z"===this.axis&&r&&(this.object.rotation.z=l(this.object.rotation.z/r)*r)}this.object.updateMatrixWorld(),this.object.parent.updateMatrixWorld(),F.copy(this.object.position),G.copy(this.object.quaternion),U.copy(this.object.scale),this.object.matrixWorld.decompose(V,j,N),E.copy(t.point).sub(V)}this.dragging=!0,m.mode=this.mode,this.dispatchEvent(m)}},this.pointerMove=function(e){var t=this.axis,o=this.mode,r=this.object,a=this.space;if("scale"===o?a="local":("E"===t||"XYZE"===t||"XYZ"===t)&&(a="world"),void 0!==r&&null!==t&&!1!==this.dragging&&(void 0===e.button||0===e.button)){y.setFromCamera(e,this.camera);var n=y.intersectObjects([c],!0)[0]||!1;if(!1!==n){if(x.copy(n.point).sub(V),"translate"===o)T.copy(x).sub(E),"local"===a&&"XYZ"!==t&&T.applyQuaternion(X),-1===t.indexOf("X")&&(T.x=0),-1===t.indexOf("Y")&&(T.y=0),-1===t.indexOf("Z")&&(T.z=0),"local"===a&&"XYZ"!==t?T.applyQuaternion(G).divide(A):T.applyQuaternion(R).divide(A),r.position.copy(T).add(F),this.translationSnap&&("local"===a&&(r.position.applyQuaternion(h.copy(G).inverse()),-1!==t.search("X")&&(r.position.x=l(r.position.x/this.translationSnap)*this.translationSnap),-1!==t.search("Y")&&(r.position.y=l(r.position.y/this.translationSnap)*this.translationSnap),-1!==t.search("Z")&&(r.position.z=l(r.position.z/this.translationSnap)*this.translationSnap),r.position.applyQuaternion(G)),"world"===a&&(r.parent&&r.position.add(f.setFromMatrixPosition(r.parent.matrixWorld)),-1!==t.search("X")&&(r.position.x=l(r.position.x/this.translationSnap)*this.translationSnap),-1!==t.search("Y")&&(r.position.y=l(r.position.y/this.translationSnap)*this.translationSnap),-1!==t.search("Z")&&(r.position.z=l(r.position.z/this.translationSnap)*this.translationSnap),r.parent&&r.position.sub(f.setFromMatrixPosition(r.parent.matrixWorld))));else if("scale"===o){if(-1!==t.search("XYZ")){var i=x.length()/E.length();0>x.dot(E)&&(i*=-1),v.set(i,i,i)}else f.copy(E),v.copy(x),f.applyQuaternion(X),v.applyQuaternion(X),v.divide(f),-1===t.search("X")&&(v.x=1),-1===t.search("Y")&&(v.y=1),-1===t.search("Z")&&(v.z=1);r.scale.copy(U).multiply(v)}else if("rotate"===o){T.copy(x).sub(E);var s=20/z.distanceTo(f.setFromMatrixPosition(this.camera.matrixWorld));"E"===t?(S.copy(Z),C=x.angleTo(E),M.copy(E).normalize(),w.copy(x).normalize(),C*=0>w.cross(M).dot(Z)?1:-1):"XYZE"===t?(S.copy(T).cross(Z).normalize(),C=T.dot(f.copy(S).cross(this.eye))*s):("X"===t||"Y"===t||"Z"===t)&&(S.copy(P[t]),f.copy(P[t]),"local"===a&&f.applyQuaternion(_),C=T.dot(f.cross(Z).normalize())*s),this.rotationSnap&&(C=l(C/this.rotationSnap)*this.rotationSnap),this.rotationAngle=C,"local"===a&&"E"!==t&&"XYZE"!==t?(r.quaternion.copy(G),r.quaternion.multiply(h.setFromAxisAngle(S,C)).normalize()):(S.applyQuaternion(R),r.quaternion.copy(h.setFromAxisAngle(S,C)),r.quaternion.multiply(G).normalize())}this.dispatchEvent(p),this.dispatchEvent(g)}}},this.pointerUp=function(e){void 0!==e.button&&0!==e.button||(this.dragging&&null!==this.axis&&(b.mode=this.mode,this.dispatchEvent(b)),this.dragging=!1,e.button===void 0&&(this.axis=null))},this.getMode=function(){return u.mode},this.setMode=function(e){u.mode=e},this.setTranslationSnap=function(e){u.translationSnap=e},this.setRotationSnap=function(e){u.rotationSnap=e},this.setSize=function(e){u.size=e},this.setSpace=function(e){u.space=e},this.update=function(){console.warn("THREE.TransformControls: update function has been depricated.")}},THREE.TransformControls.prototype=Object.assign(Object.create(THREE.Object3D.prototype),{constructor:THREE.TransformControls,isTransformControls:!0}),THREE.TransformControlsGizmo=function(){'use strict';var e=Math.abs,t=Math.cos,o=Math.PI;THREE.Object3D.call(this),this.type="TransformControlsGizmo";var r=new THREE.MeshBasicMaterial({depthTest:!1,depthWrite:!1,transparent:!0,side:THREE.DoubleSide,fog:!1}),a=new THREE.LineBasicMaterial({depthTest:!1,depthWrite:!1,transparent:!0,linewidth:1,fog:!1}),n=r.clone();n.opacity=.15;var i=r.clone();i.opacity=.33;var s=r.clone();s.color.set(16711680);var l=r.clone();l.color.set(65280);var d=r.clone();d.color.set(255);var c=r.clone();c.opacity=.25;var u=c.clone();u.color.set(16776960);var p=c.clone();p.color.set(65535);var m=c.clone();m.color.set(16711935);var b=r.clone();b.color.set(16776960);var g=a.clone();g.color.set(16711680);var y=a.clone();y.color.set(65280);var f=a.clone();f.color.set(255);var v=a.clone();v.color.set(65535);var h=a.clone();h.color.set(16711935);var P=a.clone();P.color.set(16776960);var E=a.clone();E.color.set(7895160);var x=P.clone();x.opacity=.25;var T=new THREE.CylinderBufferGeometry(0,.05,.2,12,1,!1),S=new THREE.BoxBufferGeometry(.125,.125,.125),M=new THREE.BufferGeometry;M.addAttribute("position",new THREE.Float32BufferAttribute([0,0,0,1,0,0],3));var w=function(e,r){for(var a=Math.sin,n=new THREE.BufferGeometry,s=[],l=0;l<=64*r;++l)s.push(0,t(l/32*o)*e,a(l/32*o)*e);return n.addAttribute("position",new THREE.Float32BufferAttribute(s,3)),n},C={X:[[new THREE.Mesh(T,s),[1,0,0],[0,0,-o/2],null,"fwd"],[new THREE.Mesh(T,s),[1,0,0],[0,0,o/2],null,"bwd"],[new THREE.Line(M,g)]],Y:[[new THREE.Mesh(T,l),[0,1,0],null,null,"fwd"],[new THREE.Mesh(T,l),[0,1,0],[o,0,0],null,"bwd"],[new THREE.Line(M,y),null,[0,0,o/2]]],Z:[[new THREE.Mesh(T,d),[0,0,1],[o/2,0,0],null,"fwd"],[new THREE.Mesh(T,d),[0,0,1],[-o/2,0,0],null,"bwd"],[new THREE.Line(M,f),null,[0,-o/2,0]]],XYZ:[[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.1,0),c),[0,0,0],[0,0,0]]],XY:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.295,.295),u),[.15,.15,0]],[new THREE.Line(M,P),[.18,.3,0],null,[.125,1,1]],[new THREE.Line(M,P),[.3,.18,0],[0,0,o/2],[.125,1,1]]],YZ:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.295,.295),p),[0,.15,.15],[0,o/2,0]],[new THREE.Line(M,v),[0,.18,.3],[0,0,o/2],[.125,1,1]],[new THREE.Line(M,v),[0,.3,.18],[0,-o/2,0],[.125,1,1]]],XZ:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.295,.295),m),[.15,0,.15],[-o/2,0,0]],[new THREE.Line(M,h),[.18,0,.3],null,[.125,1,1]],[new THREE.Line(M,h),[.3,0,.18],[0,-o/2,0],[.125,1,1]]]},k={X:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,1,4,1,!1),n),[.6,0,0],[0,0,-o/2]]],Y:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,1,4,1,!1),n),[0,.6,0]]],Z:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,1,4,1,!1),n),[0,0,.6],[o/2,0,0]]],XYZ:[[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.2,0),n)]],XY:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.4,.4),n),[.2,.2,0]]],YZ:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.4,.4),n),[0,.2,.2],[0,o/2,0]]],XZ:[[new THREE.Mesh(new THREE.PlaneBufferGeometry(.4,.4),n),[.2,0,.2],[-o/2,0,0]]]},O={START:[[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.01,2),i),null,null,null,"helper"]],END:[[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.01,2),i),null,null,null,"helper"]],DELTA:[[new THREE.Line(function(){var e=new THREE.BufferGeometry;return e.addAttribute("position",new THREE.Float32BufferAttribute([0,0,0,1,1,1],3)),e}(),i),null,null,null,"helper"]],X:[[new THREE.Line(M,i.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]],Y:[[new THREE.Line(M,i.clone()),[0,-1e3,0],[0,0,o/2],[1e6,1,1],"helper"]],Z:[[new THREE.Line(M,i.clone()),[0,0,-1e3],[0,-o/2,0],[1e6,1,1],"helper"]]},B={X:[[new THREE.Line(w(1,.5),g)],[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.04,0),s),[0,0,.99],null,[1,3,1]]],Y:[[new THREE.Line(w(1,.5),y),null,[0,0,-o/2]],[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.04,0),l),[0,0,.99],null,[3,1,1]]],Z:[[new THREE.Line(w(1,.5),f),null,[0,o/2,0]],[new THREE.Mesh(new THREE.OctahedronBufferGeometry(.04,0),d),[.99,0,0],null,[1,3,1]]],E:[[new THREE.Line(w(1.25,1),x),null,[0,o/2,0]],[new THREE.Mesh(new THREE.CylinderBufferGeometry(.03,0,.15,4,1,!1),x),[1.17,0,0],[0,0,-o/2],[1,1,.001]],[new THREE.Mesh(new THREE.CylinderBufferGeometry(.03,0,.15,4,1,!1),x),[-1.17,0,0],[0,0,o/2],[1,1,.001]],[new THREE.Mesh(new THREE.CylinderBufferGeometry(.03,0,.15,4,1,!1),x),[0,-1.17,0],[o,0,0],[1,1,.001]],[new THREE.Mesh(new THREE.CylinderBufferGeometry(.03,0,.15,4,1,!1),x),[0,1.17,0],[0,0,0],[1,1,.001]]],XYZE:[[new THREE.Line(w(1,1),E),null,[0,o/2,0]]]},L={AXIS:[[new THREE.Line(M,i.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]]},D={X:[[new THREE.Mesh(new THREE.TorusBufferGeometry(1,.1,4,24),n),[0,0,0],[0,-o/2,-o/2]]],Y:[[new THREE.Mesh(new THREE.TorusBufferGeometry(1,.1,4,24),n),[0,0,0],[o/2,0,0]]],Z:[[new THREE.Mesh(new THREE.TorusBufferGeometry(1,.1,4,24),n),[0,0,0],[0,0,-o/2]]],E:[[new THREE.Mesh(new THREE.TorusBufferGeometry(1.25,.1,2,24),n)]],XYZE:[[new THREE.Mesh(new THREE.SphereBufferGeometry(.7,10,8),n)]]},R={X:[[new THREE.Mesh(S,s),[.8,0,0],[0,0,-o/2]],[new THREE.Line(M,g),null,null,[.8,1,1]]],Y:[[new THREE.Mesh(S,l),[0,.8,0]],[new THREE.Line(M,y),null,[0,0,o/2],[.8,1,1]]],Z:[[new THREE.Mesh(S,d),[0,0,.8],[o/2,0,0]],[new THREE.Line(M,f),null,[0,-o/2,0],[.8,1,1]]],XY:[[new THREE.Mesh(S,u),[.85,.85,0],null,[2,2,.2]],[new THREE.Line(M,P),[.855,.98,0],null,[.125,1,1]],[new THREE.Line(M,P),[.98,.855,0],[0,0,o/2],[.125,1,1]]],YZ:[[new THREE.Mesh(S,p),[0,.85,.85],null,[.2,2,2]],[new THREE.Line(M,v),[0,.855,.98],[0,0,o/2],[.125,1,1]],[new THREE.Line(M,v),[0,.98,.855],[0,-o/2,0],[.125,1,1]]],XZ:[[new THREE.Mesh(S,m),[.85,0,.85],null,[2,.2,2]],[new THREE.Line(M,h),[.855,0,.98],null,[.125,1,1]],[new THREE.Line(M,h),[.98,0,.855],[0,-o/2,0],[.125,1,1]]],XYZX:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.125,.125,.125),c),[1.1,0,0]]],XYZY:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.125,.125,.125),c),[0,1.1,0]]],XYZZ:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.125,.125,.125),c),[0,0,1.1]]]},A={X:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,.8,4,1,!1),n),[.5,0,0],[0,0,-o/2]]],Y:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,.8,4,1,!1),n),[0,.5,0]]],Z:[[new THREE.Mesh(new THREE.CylinderBufferGeometry(.2,0,.8,4,1,!1),n),[0,0,.5],[o/2,0,0]]],XY:[[new THREE.Mesh(S,n),[.85,.85,0],null,[3,3,.2]]],YZ:[[new THREE.Mesh(S,n),[0,.85,.85],null,[.2,3,3]]],XZ:[[new THREE.Mesh(S,n),[.85,0,.85],null,[3,.2,3]]],XYZX:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.2,.2,.2),n),[1.1,0,0]]],XYZY:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.2,.2,.2),n),[0,1.1,0]]],XYZZ:[[new THREE.Mesh(new THREE.BoxBufferGeometry(.2,.2,.2),n),[0,0,1.1]]]},V={X:[[new THREE.Line(M,i.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]],Y:[[new THREE.Line(M,i.clone()),[0,-1e3,0],[0,0,o/2],[1e6,1,1],"helper"]],Z:[[new THREE.Line(M,i.clone()),[0,0,-1e3],[0,-o/2,0],[1e6,1,1],"helper"]]},j=function(e){var t=new THREE.Object3D;for(var o in e)for(var r=e[o].length;r--;){var a=e[o][r][0].clone(),n=e[o][r][1],s=e[o][r][2],l=e[o][r][3],d=e[o][r][4];a.name=o,a.tag=d,n&&a.position.set(n[0],n[1],n[2]),s&&a.rotation.set(s[0],s[1],s[2]),l&&a.scale.set(l[0],l[1],l[2]),a.updateMatrix();var c=a.geometry.clone();c.applyMatrix(a.matrix),a.geometry=c,a.renderOrder=1/0,a.position.set(0,0,0),a.rotation.set(0,0,0),a.scale.set(1,1,1),t.add(a)}return t},N=new THREE.Vector3(0,0,0),z=new THREE.Euler,_=new THREE.Vector3(0,1,0),X=new THREE.Vector3(0,0,0),Y=new THREE.Matrix4,Z=new THREE.Quaternion,F=new THREE.Quaternion,G=new THREE.Quaternion,U=new THREE.Vector3(1,0,0),Q=new THREE.Vector3(0,1,0),H=new THREE.Vector3(0,0,1);this.gizmo={},this.picker={},this.helper={},this.add(this.gizmo.translate=j(C)),this.add(this.gizmo.rotate=j(B)),this.add(this.gizmo.scale=j(R)),this.add(this.picker.translate=j(k)),this.add(this.picker.rotate=j(D)),this.add(this.picker.scale=j(A)),this.add(this.helper.translate=j(O)),this.add(this.helper.rotate=j(L)),this.add(this.helper.scale=j(V)),this.picker.translate.visible=!1,this.picker.rotate.visible=!1,this.picker.scale.visible=!1,this.updateMatrixWorld=function(){var t=Math.atan2,r=this.space;"scale"===this.mode&&(r="local");var a="local"===r?this.worldQuaternion:G;this.gizmo.translate.visible="translate"===this.mode,this.gizmo.rotate.visible="rotate"===this.mode,this.gizmo.scale.visible="scale"===this.mode,this.helper.translate.visible="translate"===this.mode,this.helper.rotate.visible="rotate"===this.mode,this.helper.scale.visible="scale"===this.mode;var n=[];n=n.concat(this.picker[this.mode].children),n=n.concat(this.gizmo[this.mode].children),n=n.concat(this.helper[this.mode].children);for(var s,l=0;lc&&(s.scale.set(1e-10,1e-10,1e-10),s.visible=!1),("Y"===s.name||"XYZY"===s.name)&&e(_.copy(Q).applyQuaternion(a).dot(this.eye))>c&&(s.scale.set(1e-10,1e-10,1e-10),s.visible=!1),("Z"===s.name||"XYZZ"===s.name)&&e(_.copy(H).applyQuaternion(a).dot(this.eye))>c&&(s.scale.set(1e-10,1e-10,1e-10),s.visible=!1),"XY"===s.name&&e(_.copy(H).applyQuaternion(a).dot(this.eye))n?(r[0]=e[0],r[1]=e[1],r[2]=e[2]):(r[0]=e[0]/n,r[1]=e[1]/n,r[2]=e[2]/n),[r,a]}function quaternionToWebotsString(e){var t=quaternionToAxisAngle(e);return t[0][0]+" "+t[0][1]+" "+t[0][2]+" "+t[1]}function translationToWebotsString(e){return e[0]+" "+e[1]+" "+e[2]}function _typeof(e){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var o,r=0;rLibrary

",n.appendChild(this.selectElement),this.assetLibraryElement.appendChild(n)}return _createClass(e,[{key:"loadAssets",value:function(){var e=this;this.assetLibrary.getRobotNames().forEach(function(t){var o=document.createElement("div");o.id=e._capitalize(t),o.classList.add("nrp-robot-designer-part-browser-content"),e.robotsTabDivs[t]=o,e.assetLibraryElement.appendChild(o);var r=document.createElement("option");r.classList.add("nrp-robot-designer-part-browser-option"),r.setAttribute("value",t),r.innerHTML=e._capitalize(t),e.selectElement.appendChild(r)}),this.assetLibrary.assets.forEach(function(t){var o=document.createElement("div"),r=document.createElement("div");r.classList.add("part-icon"),r.setAttribute("draggable",!0),r.setAttribute("part",t.name),t.root||(r.classList.add("hidden"),r.setAttribute("slotType",t.slotType)),r.innerHTML="",r.addEventListener("dragstart",function(t){e.dragStartCallback(t)}),o.appendChild(r),e.partIconDivs.push(r),e.robotsTabDivs[t.getRobotName()].appendChild(r)}),this.showParts(this.selectElement.firstChild,this.assetLibrary.getRobotNames()[0])}},{key:"update",value:function(e){for(var t,o=e.getAvailableSlotTypes(),r=0;r"+e.name+"",this.element.appendChild(r);var a=document.createElement("p");if(!t)return a.innerHTML="No parameters",void this.element.appendChild(a);var n=document.createElement("form");if("color"in t){a.style.display="inline";var i=document.createTextNode("Color: ");a.appendChild(i),n.appendChild(a);var s=document.createElement("select");for(var l in s.style.display="inline",t.color){var d=document.createElement("option"),c=document.createTextNode(t.color[l]),u=document.createAttribute("value");u.value=t.color[l],d.setAttributeNode(u),d.appendChild(c),s.appendChild(d)}s.addEventListener("change",function(t){var r=t.target.value;o.robotController.changeColor(e,r)}),n.appendChild(s)}this.element.appendChild(n)}},{key:"_cleanupDiv",value:function(e){this.element.innerHTML="

"+e+"

"}}]),e}();function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var o,r=0;rs&&(n=o,i=s)}}),n}},{key:"projectScreenPositionOnFloor",value:function(e){var o=new THREE.Raycaster;o.setFromCamera(e,this.camera);var r=new THREE.Mesh(new THREE.PlaneGeometry(100,100));r.geometry.rotateX(-t/2);var a=new THREE.Mesh(new THREE.PlaneGeometry(100,100));a.geometry.rotateX(t/2);var n=o.intersectObjects([r,a]);if(0o&&(this.robotViewer.selector.selectPart(this.partToBeSelected),this.robotViewer.handle.attachToObject(this.partToBeSelected)),this.partToBeSelected=void 0,this.mouseDownPosition=void 0}}},{key:"deleteSelectedPart",value:function(){var e=this.robotViewer.selector.selectedPart;if(e){var t=e;do{if(t.userData.isPartContainer){this.robotController.removePart(t.mediator.model);break}t=t.parent}while(t)}this.robotViewer.clearSelection()}},{key:"mouseMove",value:function(e){if(!this.robotViewer.handle.isDragging()){var t=this.robotViewer.robotViewerElement,o=MouseEvents.convertMouseEventPositionToRelativePosition(t,e.clientX,e.clientY),r=MouseEvents.convertMouseEventPositionToScreenPosition(t,e.clientX,e.clientY),a=this.robotViewer.getPartAt(o,r);a?this.robotViewer.highlightor.highlight(a):this.robotViewer.highlightor.clearHighlight()}}},{key:"dragStart",value:function(e){var t=e.target.getAttribute("part"),o=e.target.getAttribute("slotType");e.dataTransfer.setData("text",t);var r=document.createElement("img");r.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",e.dataTransfer.setDragImage(r,0,0),this.dragger.dragStart(t,o)}},{key:"dragOver",value:function(e){e.preventDefault(),e.dataTransfer.getData("text"),this.dragger.dragOver(e.clientX,e.clientY)}},{key:"_createDomElements",value:function(e,t){var o=this;if(this.part=document.createElement("div"),this.part.classList.add("nrp-robot-designer"),this.part.id="nrp-robot-designer","undefined"==typeof e?document.body.appendChild(this.part):e.appendChild(this.part),t){var r=document.createElement("div");r.classList.add("header"),r.innerHTML="NRP Robot Designer\n \n File\n Help",this.part.appendChild(r)}this.toolbar=document.createElement("div"),this.toolbar.classList.add("menu"),this.toolbar.innerHTML="\n \n -\n \n \n -\n \n \n \n -\n ",t&&(this.toolbar.innerHTML+="\n -\n "),this.part.appendChild(this.toolbar);var a=document.getElementById("nrp-robot-designer-export-button");a.addEventListener("click",function(){o.openExportModal()}),this.undoButton=document.getElementById("nrp-robot-designer-undo-button"),this.undoButton.addEventListener("click",function(){o.commands.undo()}),this.redoButton=document.getElementById("nrp-robot-designer-redo-button"),this.redoButton.addEventListener("click",function(){o.commands.redo()}),this.selectButton=document.getElementById("nrp-robot-designer-select-button"),this.selectButton.addEventListener("click",function(){o.changeMode("select")}),this.translateButton=document.getElementById("nrp-robot-designer-translate-button"),this.translateButton.addEventListener("click",function(){o.changeMode("translate")}),this.rotateButton=document.getElementById("nrp-robot-designer-rotate-button"),this.rotateButton.addEventListener("click",function(){o.changeMode("rotate")});var n=document.getElementById("nrp-robot-designer-delete-button");n.addEventListener("click",function(){o.deleteSelectedPart()});var i=document.getElementById("nrp-robot-designer-maximize-button");i&&i.addEventListener("click",function(){toggleFullScreen()}),this.assetLibraryElement=document.createElement("div"),this.assetLibraryElement.classList.add("part-browser"),this.assetLibraryElement.classList.add("designer-group"),this.part.appendChild(this.assetLibraryElement);var s=document.createElement("div");s.classList.add("part-viewer"),s.classList.add("designer-group"),s.innerHTML="

Part viewer

",this.partViewerElement=document.createElement("div"),s.appendChild(this.partViewerElement),this.part.appendChild(s),this.robotViewerElement=document.createElement("div"),this.robotViewerElement.classList.add("main"),this.robotViewerElement.addEventListener("drop",function(e){e.preventDefault(),o.dragger.drop(e.clientX,e.clientY)}),this.robotViewerElement.addEventListener("dragenter",function(){o.dragger.dragEnter()}),this.robotViewerElement.addEventListener("dragover",function(e){o.dragOver(e)}),this.robotViewerElement.addEventListener("dragleave",function(){o.dragger.dragLeave()}),this.robotViewerElement.addEventListener("mousemove",function(e){o.mouseMove(e)}),this.robotViewerElement.addEventListener("mousedown",function(e){o.mouseDown(e)}),this.robotViewerElement.addEventListener("mouseup",function(e){o.mouseUp(e)}),this.part.appendChild(this.robotViewerElement);var l=document.createElement("div");l.id="nrp-robot-designer-modal-window",l.classList.add("modal"),l.innerHTML="
\n ×\n
\n \n \n \n
\n
",this.part.appendChild(l);var d=document.getElementById("nrp-robot-designer-json-export-button");d.addEventListener("click",function(){o.exportToFile("json")});var c=document.getElementById("nrp-robot-designer-webots-export-button");c.addEventListener("click",function(){o.exportToFile("webots")});var u=document.getElementById("nrp-robot-designer-nrp-export-button");u.addEventListener("click",function(){alert("Coming soon...")})}},{key:"_updateUndoRedoButtons",value:function(){this.commands.canRedo()?this.redoButton.classList.remove("fa-disabled"):this.redoButton.classList.add("fa-disabled"),this.commands.canUndo()?this.undoButton.classList.remove("fa-disabled"):this.undoButton.classList.add("fa-disabled")}}]),e}(); \ No newline at end of file diff --git a/app/robot_designer.js b/app/robot_designer.js index 8bac7d0..4ed815b 100644 --- a/app/robot_designer.js +++ b/app/robot_designer.js @@ -1,23 +1,23 @@ -/* global RobotViewer, Robot, Dragger, RobotMediator, RobotController, PartBrowser, PartViewer, AssetLibrary, Commands, MouseEvents */ +/* global RobotViewer, Robot, Dragger, RobotMediator, RobotController, PartBrowser, PartViewer, AssetLibrary, Commands, MouseEvents, toggleFullScreen */ 'use strict'; class RobotDesigner { // eslint-disable-line no-unused-vars - constructor(domElement, showHeader) { - this._createDomElements(domElement); + constructor(domElement = undefined, sceneRgbColor = 0x000, isStandAlone = true) { + this._createDomElements(domElement, isStandAlone); this.assetLibrary = new AssetLibrary(); this.partBrowser = new PartBrowser(this.assetLibraryElement, this.assetLibrary, (event) => { this.dragStart(event); }); this.assetLibrary.addObserver('loaded', () => { this.partBrowser.loadAssets(); }); this.commands = new Commands(); - this.commands.addObserver('updated', () => this.updateUndoRedoButtons()); + this.commands.addObserver('updated', () => this._updateUndoRedoButtons()); this.commands.addObserver('updated', () => this.partBrowser.update(this.robot)); this.robot = new Robot(); this.robotMediator = new RobotMediator(this.robot); this.robotController = new RobotController(this.assetLibrary, this.commands, this.robot); - this.robotViewer = new RobotViewer(this.robotViewerElement, this.robotController, this.commands); + this.robotViewer = new RobotViewer(this.robotViewerElement, this.robotController, this.commands, sceneRgbColor); this.robotViewer.scene.add(this.robotMediator.rootObject); this.highlightOutlinePass = this.robotViewer.highlightOutlinePass; @@ -26,19 +26,12 @@ class RobotDesigner { // eslint-disable-line no-unused-vars this.partViewer = new PartViewer(this.robotController, this.partViewerElement, this.robotViewer.selector); } - updateUndoRedoButtons() { - if (this.commands.canRedo()) - this.redoButton.classList.remove('fa-disabled'); - else - this.redoButton.classList.add('fa-disabled'); - if (this.commands.canUndo()) - this.undoButton.classList.remove('fa-disabled'); - else - this.undoButton.classList.add('fa-disabled'); - } - // events + resize() { + this.robotViewer.resize(); + } + openExportModal() { // eslint-disable-line no-unused-vars var modal = document.getElementById('nrp-robot-designer-modal-window'); modal.style.display = 'block'; @@ -72,6 +65,11 @@ class RobotDesigner { // eslint-disable-line no-unused-vars return; } + if (typeof this.onExport === 'function') { + this.onExport(data); + return; + } + var blob = new Blob([data], {type: mimeType}); var e = document.createEvent('MouseEvents'); var a = document.createElement('a'); @@ -82,15 +80,7 @@ class RobotDesigner { // eslint-disable-line no-unused-vars a.dispatchEvent(e); } - undo() { // eslint-disable-line no-unused-vars - this.commands.undo(); - } - - redo() { // eslint-disable-line no-unused-vars - this.commands.redo(); - } - - changeMode(mode) { // eslint-disable-line no-unused-vars + changeMode(mode) { this.selectButton.classList.remove('fa-selected'); this.translateButton.classList.remove('fa-selected'); this.rotateButton.classList.remove('fa-selected'); @@ -105,7 +95,7 @@ class RobotDesigner { // eslint-disable-line no-unused-vars this.robotViewer.handle.setMode(mode); } - mouseDown(ev) { // eslint-disable-line no-unused-vars + mouseDown(ev) { var domElement = this.robotViewer.robotViewerElement; var relativePosition = MouseEvents.convertMouseEventPositionToRelativePosition(domElement, ev.clientX, ev.clientY); var screenPosition = MouseEvents.convertMouseEventPositionToScreenPosition(domElement, ev.clientX, ev.clientY); @@ -114,7 +104,7 @@ class RobotDesigner { // eslint-disable-line no-unused-vars this.mouseDownPosition = {x: ev.clientX, y: ev.clientY }; } - mouseUp(ev) { // eslint-disable-line no-unused-vars + mouseUp(ev) { if (typeof this.partToBeSelected === 'undefined' || typeof this.mouseDownPosition === 'undefined') return; @@ -130,7 +120,7 @@ class RobotDesigner { // eslint-disable-line no-unused-vars this.mouseDownPosition = undefined; } - deleteSelectedPart() { // eslint-disable-line no-unused-vars + deleteSelectedPart() { var mesh = this.robotViewer.selector.selectedPart; if (mesh) { @@ -147,7 +137,7 @@ class RobotDesigner { // eslint-disable-line no-unused-vars this.robotViewer.clearSelection(); } - mouseMove(ev) { // eslint-disable-line no-unused-vars + mouseMove(ev) { if (this.robotViewer.handle.isDragging()) return; @@ -161,13 +151,7 @@ class RobotDesigner { // eslint-disable-line no-unused-vars this.robotViewer.highlightor.clearHighlight(); } - drop(ev) { // eslint-disable-line no-unused-vars - ev.preventDefault(); - - this.dragger.drop(ev.clientX, ev.clientY); - } - - dragStart(ev) { // eslint-disable-line no-unused-vars + dragStart(ev) { var part = ev.target.getAttribute('part'); var slotType = ev.target.getAttribute('slotType'); ev.dataTransfer.setData('text', part); // Cannot be used on Chrome. Cannot be dropped on Firefox. @@ -180,23 +164,15 @@ class RobotDesigner { // eslint-disable-line no-unused-vars this.dragger.dragStart(part, slotType); } - dragOver(ev) { // eslint-disable-line no-unused-vars + dragOver(ev) { ev.preventDefault(); ev.dataTransfer.getData('text'); // Cannot be used on Chrome. Cannot be dropped on Firefox. this.dragger.dragOver(ev.clientX, ev.clientY); } - dragLeave(ev) { // eslint-disable-line no-unused-vars - this.dragger.dragLeave(); - } - - dragEnter(ev) { // eslint-disable-line no-unused-vars - this.dragger.dragEnter(); - } - // DOM setup - _createDomElements(domElement, showHeader) { + _createDomElements(domElement, isStandAlone) { this.part = document.createElement('div'); this.part.classList.add('nrp-robot-designer'); this.part.id = 'nrp-robot-designer'; @@ -205,11 +181,11 @@ class RobotDesigner { // eslint-disable-line no-unused-vars else domElement.appendChild(this.part); - if (showHeader) { + if (isStandAlone) { let header = document.createElement('div'); header.classList.add('header'); header.innerHTML = `NRP Robot Designer - ' + File Help`; this.part.appendChild(header); @@ -218,7 +194,7 @@ class RobotDesigner { // eslint-disable-line no-unused-vars this.toolbar = document.createElement('div'); this.toolbar.classList.add('menu'); this.toolbar.innerHTML = ` - + - @@ -227,25 +203,31 @@ class RobotDesigner { // eslint-disable-line no-unused-vars - - - - - `; + `; + if (isStandAlone) { + this.toolbar.innerHTML += ` + - + `; + } this.part.appendChild(this.toolbar); + var exportButton = document.getElementById('nrp-robot-designer-export-button'); + exportButton.addEventListener('click', () => { this.openExportModal(); }); this.undoButton = document.getElementById('nrp-robot-designer-undo-button'); - this.undoButton.addEventListener('click', () => { this.undo(); }); + this.undoButton.addEventListener('click', () => { this.commands.undo(); }); this.redoButton = document.getElementById('nrp-robot-designer-redo-button'); - this.redoButton.addEventListener('click', () => { this.redo(); }); + this.redoButton.addEventListener('click', () => { this.commands.redo(); }); + this.selectButton = document.getElementById('nrp-robot-designer-select-button'); + this.selectButton.addEventListener('click', () => { this.changeMode('select'); }); this.translateButton = document.getElementById('nrp-robot-designer-translate-button'); this.translateButton.addEventListener('click', () => { this.changeMode('translate'); }); this.rotateButton = document.getElementById('nrp-robot-designer-rotate-button'); this.rotateButton.addEventListener('click', () => { this.changeMode('rotate'); }); - var selectButton = document.getElementById('nrp-robot-designer-select-button'); - selectButton.addEventListener('click', () => { this.changeMode('select'); }); var deleteButton = document.getElementById('nrp-robot-designer-delete-button'); - deleteButton.addEventListener('click', () => { this.this.deleteSelectedPart(); }); + deleteButton.addEventListener('click', () => { this.deleteSelectedPart(); }); var maximizeButton = document.getElementById('nrp-robot-designer-maximize-button'); - maximizeButton.addEventListener('click', () => { this.toggleFullScreen(); }); + if (maximizeButton) + maximizeButton.addEventListener('click', () => { toggleFullScreen(); }); this.assetLibraryElement = document.createElement('div'); this.assetLibraryElement.classList.add('part-browser'); @@ -262,10 +244,13 @@ class RobotDesigner { // eslint-disable-line no-unused-vars this.robotViewerElement = document.createElement('div'); this.robotViewerElement.classList.add('main'); - this.robotViewerElement.addEventListener('drop', (event) => { this.drop(event); }); - this.robotViewerElement.addEventListener('dragenter', (event) => { this.dragEnter(event); }); + this.robotViewerElement.addEventListener('drop', (event) => { + event.preventDefault(); + this.dragger.drop(event.clientX, event.clientY); + }); + this.robotViewerElement.addEventListener('dragenter', (event) => { this.dragger.dragEnter(); }); this.robotViewerElement.addEventListener('dragover', (event) => { this.dragOver(event); }); - this.robotViewerElement.addEventListener('dragleave', (event) => { this.dragLeave(event); }); + this.robotViewerElement.addEventListener('dragleave', (event) => { this.dragger.dragLeave(); }); this.robotViewerElement.addEventListener('mousemove', (event) => { this.mouseMove(event); }); this.robotViewerElement.addEventListener('mousedown', (event) => { this.mouseDown(event); }); this.robotViewerElement.addEventListener('mouseup', (event) => { this.mouseUp(event); }); @@ -276,14 +261,12 @@ class RobotDesigner { // eslint-disable-line no-unused-vars modalWindow.id = 'nrp-robot-designer-modal-window'; modalWindow.classList.add('modal'); modalWindow.innerHTML = - `