{"version":3,"sources":["webpack:///webpack/universalModuleDefinition?5ca6*","webpack:///canvas3d.js","webpack:///./src/web/canvas3d.js","webpack:///./src/ui/canvas3d/index.js","webpack:///./src/ui/canvas3d/texture-view.js","webpack:///./src/ui/canvas3d/doc3d-model-mixin.js","webpack:///./src/ui/canvas3d/move3d.js","webpack:///./src/ui/canvas3d/texture-view-scene.js","webpack:///./src/ui/canvas3d/canvas3d.js","webpack:///./src/ui/canvas3d/view3d.js","webpack:///./src/ui/canvas3d/orbit-controls.js","webpack:///./src/ui/canvas3d/three-util.js","webpack:///./src/ui/canvas3d/object3d.js","webpack:///./src/ui/canvas3d/thumbnail.js"],"names":["root","factory","exports","module","define","amd","this","webpackJsonpGrafika","0","__webpack_require__","118","_interopRequireWildcard","obj","__esModule","newObj","key","Object","prototype","hasOwnProperty","call","default","_lodash","_canvas3d","Canvas3d","_window","window","Cx","assign","119","defineProperty","value","_textureView","keys","forEach","enumerable","get","_thumbnail","120","_toConsumableArray","arr","Array","isArray","i","arr2","length","from","TextureView","StaticTextureView","undefined","_config","_gear","_cdl","_view","_doc3dModelMixin","_textureViewScene","_move3d","fpsLimit","View","extend","View2D_Mixin","DocumentView_Mixin","SelectedFigures_Mixin","FigureConditions_Mixin","Doc3D_Model_Mixin","typeName","Properties","document","type","def","owned","set","v","_setDoc","canvas3D","onChange","model","zoomToFitTextureFor","backSideDarkFactor","backSideColor","_backSideColor","Color","changeLuminosity","frontSideColor","textureSize","updateSize","doc","model3D","getThreeTexture","textureType","scene","threeTexture","texture","findByTextureType","textures","tiledTexture","textureTiles","backgroundColor","color","w","h","width","height","_previewing","arguments","previewingTextureSize","Math","max","stats","fps","callParent","postResize","_modelReady","createScene","TextureViewComposition","main","redrawFigure","figure","renderer","redraw","draw","computeViewToTextureScale","now","_previewingT","endPreview","render$","draw$","_this","zoom","then","prepareToDraw$","invokeMap$","mapToFigureViews","figures","map$","redrawAll","textureWidth","center","Point","zoomToFitTexture$","_this2","loadModel3D$","zoomToFit$","zoomToFitFigures$","apply","docToView","console","log","docDeltaToView","docDelta","viewTransform","viewToDoc","viewPoint","docIsland","modelToDoc","docPoint","event","modelPoint","textureDeltaToDoc","textureDelta","viewDeltaToDoc","viewDelta","figureViews","figureView","figureTextureTypes","init","config","addEvents","SyncedFigureViews","view","_backgroundColor","White","Document","insertViewPlugins","plugins","textureViewPlugins","Plugin","TextureMap","TextureViewRenderer","concat","ViewControls","PluginsLayer","Tools","insert","_this3","old","resolve","un","unlinkDoc","_document","linkDoc","is3D","update$","syncModel3D","link","fireEvent","unlink","syncTextures","_this4","Config","ignoreTextures","remove","plugin","updateMap","textureMap","getFixedTextureMap","wrap","composition","createTexture","push","unshift","layersContainer","id","TextureTile","docMaterial","materials","modelMaterial","docTextureMap","modelTextureMap","TextureComposition","on_materialschanged","on_model3dchanged","optimizePreview","texturePreview","_previewingResize","on_renderstarted","dispose","onBackgroundColorChange","textureView","pluginDirectDomEventHandling","_ref","target","createEventTracker","TextureTracker","InteractiveView_Mixin","selectAndDragEnabled","delta","viewDeltaToTexture","triggerKeyboard","are","is","status","s","get_cursor","cursor","set_cursor","_len","params","_key","121","notTextureIsland","isTextureIsland","selectableIslands","condition","activeSelectableFigures","uvToModel","uv","uvToDoc","topDocIslandAtModel","matrix","modelToDocMatrixFor","modelIsland","modelIslandAt","topDocIslandFor","docIslandsFor","modelIslandFor","modelPointIsOut","bounds_","contains","forEachDesignFiguresIn","name","func","pages","p","pEnd","page","designFigures","designFiguresFrom","docIslands","docIslandsFrom","iEnd","textureIslandName","extractHitInfo","hit","info","tight","figureAtModelPointEx","tabFigures","candidates","candidateFiguresAtModelPoint","bestFigureCandidate","filterSelectableInto","r","k","kEnd","rawFigureHitsAtModelPoint","raw","docIslandCandidates","_locked","_hidden","pagedDesignLayers","designLayersFrom","designLayers","filterTargetLayers","Layers","flatten","l","lEnd","filterIslandsFor","f","modelToDocMatrix","globalFrame_","containsPoint","on_domEvent","isPrimary","tracker","handlePluginDomEvent","_ref2","route","handleDomEvent","has_try_pointerdown","stopped","newEvent","retargetedEvent","try_pointerdown","stopPropagation","tryHandler","retargetEvent3D","move","122","retarget","eventDown","SimpleTracker3D","interpolatingExtension","newFrom","firstFrom","lastFrom","firstTo","lastTo","isEqual","clone","last_firstFrom","minus","last_firstFrom_norm","norm","last_firstFrom_n","scaled","new_firstFrom","dotProductFrom","dotProduct","ap","alpha","bp","beta","perpendicular","last_firstTo","adp","bdp","plus","Tracker3D","_event","_docIsland","track","modelPointRaw","modelIslandRaw","docIslandRaw","docPointRaw","viewPointLast","modelPointLast","viewPointFirstRaw","viewPointLastRaw","modelPointFirstRaw","modelPointLastRaw","started","retargetedEventDown","originalEvent","trackData","_ref3","_event2","123","processedDocIslandsFor","modelIslandName","pageDocIslands","pdi","pdiEnd","island","processed","filterProcessed","Figures","clearComposedCanvas","drawPlugin","context","somethingToDraw","transformModel","getViewPortTransform","drawConfig","modelIslands","save","clipTest1","bleedModelIsland","bleedModelIslandWithName","polyregions","clipContext","drawPlugin2D","transform","d","dEnd","needsToDrawFor","transformDoc","Matrix","m","docToModelMatrix","restore","drawTo_color","backgroundDocIsland","brush","_empty","defaults","ignorePen","layer","beforeDraw","di","diEnd","Frame","areOverlapping","frame_","showPin","dot","pin","afterDraw","124","Canvas3D","StaticCanvas3D","_view3d","_textureView2","_threeUtil","_object3d","View3D","_setTextureView","documentFilter","modelData","modelData3D","textureSize_","isIddle","_transformMode","FigureAnnotations","annotate","_figureAnnotations","figureAnnotations","unannotate","_figureAnnotations2","clearAnnotations","_figureAnnotations3","add","selector","destinationLayerSelector","setActiveLayerBy","activePage","layerBy","activeLayer","asFastOffset","offset","uvPoint","viewToUV","camera","object3D","uvFromViewPoint","_viewToTextureScale","dist","testPoints","translated_","scales","point","uv_close","uv_scale","min","scale","controls","c","position","sub","keepLowerLeftCornerAsOrigin","viewCenter","resetToOrigin","rs","sqrt","rse","frontDocIsland","topDocIsland","textureZoom","load$","loadedDoc","_documentFilter","onLoaded","_readyDeferred","controlsEnabled","enabled","state","_controlsPanning","onMouseUp","setOrbitMode","mouseButtons","ORBIT","THREE","MOUSE","LEFT","ZOOM","MIDDLE","PAN","RIGHT","setPanMode","isOrbitMode","isPanMode","initSelection","_initTextureView","Deferred","ready$","promise","onObject3DChange","optimizeZoomPreview","updateTextureOnZoom","_ownedTexture","selection","autoDraw","textureSize3D","parseInt","syncModelData3D","Object3D","geometry","parseGeometry","data","threeScene","on","zoomToFront","EmptyObject3D","on_modeldata3dchanged","_unlinkTextureView","change","textureView_on_change","bind","textureView_on_draw","textureView_on_redraw","_len2","_key2","_len3","_key3","loadModelData3D$","125","_orbitControls","_THREE","Vector3","autoRotate","zoomToScale","lightOffset","cameraAnim","Composition","initPlugin","addPlugin","pluginsToDraw","Renderer3D","ViewControls3D","initThreeScene","Scene","PerspectiveCamera","OrbitConstraint","addLights","lights","light","HemisphereLight","REVISION","AmbientLight","light1","PointLight","lightPower","parseFloat","parent","ambientLightPower","light1Power","light2Power","lightPowerF","split","lightAmbient","light2","objectsBBox3D","bbox","_zoomToFitCameraDistance","bb","objectSize","y","fov","PI","distance","abs","sin","_zoomToScale","_zoomToSide","dirX","dirY","dirZ","msTransition","pos","normalize","multiplyScalar","_zoomToPos","setCameraState","zoomToBack","zoomToRight","zoomToLeft","rotateCameraRight","angle","rotateModelLeft","rotateCameraLeft","rotateModelRight","rotateCameraDown","rotateModelUp","rotateCameraUp","rotateModelDown","rotateLeft","deg2rad","_updateControls","rotateUp","zoomIn","dollyIn","zoomOut","dollyOut","update","cameraStateString","cameraToString","string","setCameraStateString","cameraStateFromString","copy","updateProjectionMatrix","CameraAnimation","ms","to","onOrbitControlChange","triggerZoomEvents","debouncedTriggerZoomEvents","debounce","onOrbitControlZoomUpdated","drawTextures","animate","clock","getDelta","draw3D","setLightPos","image","canvas","toDataURL","cameraPos","lightPos","bb_max","b","subVectors","n","crossVectors","addVectors","_previousZoomToFitDistance","aspect","newZoomToFitDistance","fireResizeEvent","Clock","appendTo","domElement","OrbitControls","autoRotateSpeed","enableKeys","enableDamping","dampingFactor","addEventListener","panning","on_pointerdown","on_pointermove","fastThrottle","on_pointerup","on_mousewheel","_ref4","126","object","minDistance","maxDistance","Infinity","minZoom","maxZoom","minPolarAngle","maxPolarAngle","minAzimuthAngle","maxAzimuthAngle","theta","phi","scope","EPS","phiDelta","thetaDelta","panOffset","zoomChanged","getPolarAngle","getAzimuthalAngle","panToCenter","targetLengthSq","lengthSq","panLeft","te","elements","panUp","pan","deltaX","deltaY","screenWidth","screenHeight","targetDistance","tan","OrthographicCamera","right","left","top","bottom","warn","dollyScale","quat","Quaternion","setFromUnitVectors","up","quatInverse","inverse","lastPosition","lastQuaternion","applyQuaternion","atan2","x","z","radius","cos","lookAt","distanceToSquared","quaternion","element","body","constraint","clientWidth","clientHeight","getAutoRotationAngle","getZoomScale","pow","zoomSpeed","handleTouchStartDolly","pointers","current","dollyStart","handleTouchMoveDolly","dollyEnd","dollyDelta","enableZoom","enableRotate","rotateSpeed","enablePan","keyPanSpeed","UP","BOTTOM","rotateStart","Vector2","rotateEnd","rotateDelta","panStart","panEnd","panDelta","STATE","NONE","ROTATE","DOLLY","TOUCH_ROTATE","TOUCH_DOLLY","TOUCH_PAN","target0","position0","zoom0","zoomUpdatedEvent","changeEvent","startEvent","endEvent","dispatchEvent","reset","button","clientX","clientY","preventDefault","wheelDelta","detail","create","EventDispatcher","constructor","defineProperties","127","setObjectPosition","bbCenter","matrixWorldNeedsUpdate","n2s","toFixed","vector3ToString","vector3FromString","_parseFloat","rotationToString","order","rotation","parts","properFaceNormal","face","face_normal","normal","properVertexNormal","vertexNormal","vertexNormals","processGeometry","smooth","useBufferGeometry","face0","faces","face1","computeFaceNormals","computeVertexNormals","json","loader","JSONLoader","originalGeometry","parse","BufferGeometry","Geometry","fromBufferGeometry","smooth3D","updateMatrixWorld","vector","unproject","raycaster","Raycaster","intersects","intersectObject","start","finished","t","ellapsed","to_pos","from_pos","to_target","from_target","nextTarget","from_xz","to_xz","theta_from","angle_rad","theta_delta","turnAngle_rad","from_radius","to_radius","nextPos","128","setMaterialTexture","material","repeat","wrapS","wrapT","RepeatWrapping","ClampToEdgeWrapping","minFilter","NearestMipMapLinearFilter","LinearMipMapLinearFilter","map","uvTransform","uvRepeat","Object3DBase","Base","_forcedMapReady","createThreeObject","mixer","materialBack","objectGeometry","fromGeometry","backSideType","_currentBackSideType","backSide3D","backSide","animGeometry","bones","SkinnedMesh","skinning","Mesh","morphTargets","AnimationMixer","animations","bonesClip","bonesAction","clipAction","play","facesClip","AnimationClip","CreateFromMorphTargetSequence","facesAction","SceneUtils","createMultiMaterialObject","objectBack","computeBoundingBox","boundingBox","onTextureChange","onBackSideColorChange","createMaterialBack","createMaterial","drawcomplete","invalidateTexture","synctextures","setHex","rgbHex","transparent","tiledBumpMap","tiledNormalMap","needsUpdate","materialType","threeMaterialType","side","FrontSide","shading","SmoothShading","reflectivity","specular","shininess","roughness","metalness","alphaMap","TextureLoader","crossOrigin","load","repeatS","tiledBumpMapRepeat","tiledMapRepeat","setAlphaMap","alphaMapSlot","tiledMap","onLoad","tiledMapScale","bumpMap","bumpScale","bumpMapSlot","normalMap","normalScale","normalMapSlot","deferred","MeshLambertMaterial","BackSide","visible","render","autoClear","129","_thumbnailImage$","size","preserveDrawingBuffer","showDocument$","createPreview3D","domId","docId","a","g$","isPlainObject","Preview3D","thumbnailImage3D$","currentPromise","commit$"],"mappings":"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","file":"canvas3d.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Grafika\"] = factory();\n\telse\n\t\troot[\"Grafika\"] = factory();\n})(this, function() {\nreturn \n\n\n/** WEBPACK FOOTER **\n ** webpack/universalModuleDefinition\n **/","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Grafika\"] = factory();\n\telse\n\t\troot[\"Grafika\"] = factory();\n})(this, function() {\nreturn webpackJsonpGrafika([2],{\n\n/***/ 0:\n/***/ function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(118);\n\n\n/***/ },\n\n/***/ 118:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tvar _lodash = __webpack_require__(4);\n\t\n\tvar _canvas3d = __webpack_require__(119);\n\t\n\tvar Canvas3d = _interopRequireWildcard(_canvas3d);\n\t\n\tfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }\n\t\n\tvar _window = window;\n\tvar Cx = _window.Cx;\n\t\n\t\n\t(0, _lodash.assign)(Cx, Canvas3d);\n\n/***/ },\n\n/***/ 119:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\t\n\tvar _textureView = __webpack_require__(120);\n\t\n\tObject.keys(_textureView).forEach(function (key) {\n\t if (key === \"default\") return;\n\t Object.defineProperty(exports, key, {\n\t enumerable: true,\n\t get: function () {\n\t return _textureView[key];\n\t }\n\t });\n\t});\n\t\n\tvar _canvas3d = __webpack_require__(124);\n\t\n\tObject.keys(_canvas3d).forEach(function (key) {\n\t if (key === \"default\") return;\n\t Object.defineProperty(exports, key, {\n\t enumerable: true,\n\t get: function () {\n\t return _canvas3d[key];\n\t }\n\t });\n\t});\n\t\n\tvar _thumbnail = __webpack_require__(129);\n\t\n\tObject.keys(_thumbnail).forEach(function (key) {\n\t if (key === \"default\") return;\n\t Object.defineProperty(exports, key, {\n\t enumerable: true,\n\t get: function () {\n\t return _thumbnail[key];\n\t }\n\t });\n\t});\n\n/***/ },\n\n/***/ 120:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.TextureView = exports.StaticTextureView = undefined;\n\t\n\tvar _config = __webpack_require__(2);\n\t\n\tvar _lodash = __webpack_require__(4);\n\t\n\tvar _gear = __webpack_require__(8);\n\t\n\tvar _cdl = __webpack_require__(15);\n\t\n\tvar _view = __webpack_require__(84);\n\t\n\tvar _doc3dModelMixin = __webpack_require__(121);\n\t\n\tvar _textureViewScene = __webpack_require__(123);\n\t\n\tvar _move3d = __webpack_require__(122);\n\t\n\tfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\t\n\tvar fpsLimit = 6;\n\t\n\tvar StaticTextureView = exports.StaticTextureView = _view.View.extend(_view.View2D_Mixin).extend(_view.DocumentView_Mixin).extend(_view.SelectedFigures_Mixin).extend(_cdl.FigureConditions_Mixin).extend(_doc3dModelMixin.Doc3D_Model_Mixin).extend({\n\t\n\t typeName: 'StaticTextureView',\n\t\n\t Properties: {\n\t\n\t document: { type: 'Document', def: null, owned: false, set: function (v) {\n\t this._setDoc(v);\n\t }\n\t },\n\t\n\t canvas3D: { type: 'boolean', def: null, onChange: function (value) {\n\t if (value && this.model) {\n\t this.zoomToFitTextureFor(this.model);\n\t }\n\t }\n\t },\n\t\n\t // [TODO] onChange, fireEvent\n\t backSideDarkFactor: { type: 'number', def: 0.5 },\n\t\n\t backSideColor: { type: 'Color', def: null, get: function () {\n\t return this._backSideColor || _cdl.Color.changeLuminosity(this.frontSideColor, -this.backSideDarkFactor);\n\t }\n\t },\n\t\n\t textureSize: { type: 'number', def: null, onChange: function () {\n\t this.updateSize();\n\t }\n\t }\n\t },\n\t\n\t get model() {\n\t var doc = this.doc;\n\t\n\t return doc && doc.model3D;\n\t },\n\t\n\t getThreeTexture: function (textureType) {\n\t if (textureType === 'color') {\n\t return this.scene.threeTexture;\n\t } else {\n\t // Textures compositions, full size, same as color\n\t var texture = (0, _view.findByTextureType)(this.textures, textureType);\n\t if (texture) {\n\t return texture.threeTexture;\n\t } else {\n\t // Tiled textures\n\t var tiledTexture = this.textureTiles[textureType];\n\t if (tiledTexture) {\n\t return tiledTexture.threeTexture;\n\t }\n\t }\n\t }\n\t },\n\t\n\t\n\t get frontSideColor() {\n\t return this.backgroundColor;\n\t },\n\t set frontSideColor(color) {\n\t this.backgroundColor = color;\n\t },\n\t\n\t updateSize: function (w, h) {\n\t var textureSize = this.textureSize;\n\t var width = this.width;\n\t var height = this.height;\n\t var _previewing = this._previewing;\n\t\n\t if (textureSize && arguments.length === 0) {\n\t if (this.canvas3D) {\n\t if (!_previewing && (textureSize !== width || textureSize !== height)) {\n\t // console.log('full texture');\n\t this.callParent(textureSize, textureSize);\n\t } else if (_previewing) {\n\t if (textureSize === 512) {\n\t return;\n\t }\n\t var previewingTextureSize = Math.max(textureSize / (this.stats.fps > fpsLimit ? 2 : 4), 512);\n\t if (!(previewingTextureSize === width && previewingTextureSize === height)) {\n\t // console.log('preview texture ' + previewingTextureSize );\n\t this.callParent(previewingTextureSize, previewingTextureSize);\n\t }\n\t }\n\t } else {\n\t this.callParent(textureSize, textureSize);\n\t }\n\t } else {\n\t this.callParent(w, h);\n\t }\n\t },\n\t postResize: function () {\n\t if (this._modelReady) {\n\t this.zoomToFitTextureFor(this.model);\n\t }\n\t },\n\t createScene: function () {\n\t return new _textureViewScene.TextureViewComposition({ main: true });\n\t },\n\t redrawFigure: function (figure) {\n\t this.renderer.redraw(this, figure);\n\t },\n\t draw: function () {\n\t\n\t if (!this._modelReady) {\n\t return;\n\t }\n\t var canvas3D = this.canvas3D;\n\t\n\t if (canvas3D) {\n\t canvas3D.computeViewToTextureScale();\n\t }\n\t if (this._previewing && (0, _lodash.now)() - this._previewingT > 1200) {\n\t this.endPreview();\n\t this.render$();\n\t return;\n\t }\n\t this.callParent();\n\t },\n\t\n\t\n\t // [TODO] This should be available at the view level\n\t // This function will make sure that everything is ready to be rendered\n\t // before drawing. Is used in the 3D thumbnail generation process.\n\t draw$: function () {\n\t var _this = this;\n\t\n\t var doc = this.doc;\n\t var zoom = this.zoom;\n\t\n\t return doc.render$().then(function () {\n\t return doc.prepareToDraw$(zoom).then(function () {\n\t return (0, _gear.invokeMap$)(_this.mapToFigureViews(doc.figures), 'ready$').then(function () {\n\t return (0, _gear.map$)(_this.textureTiles, 'promise').then(function () {\n\t _this.redrawAll();\n\t _this.draw();\n\t });\n\t });\n\t });\n\t });\n\t },\n\t zoomToFitTextureFor: function (model) {\n\t var textureWidth = model.textureWidth;\n\t var width = this.width;\n\t\n\t this.zoom = width / textureWidth;\n\t this.center = new _cdl.Point(textureWidth / 2, textureWidth / 2);\n\t return this;\n\t },\n\t zoomToFitTexture$: function () {\n\t var _this2 = this;\n\t\n\t return this.loadModel3D$().then(function (model) {\n\t // [TODO]\n\t if (model) {\n\t return _this2.zoomToFitTextureFor(model);\n\t }\n\t });\n\t },\n\t zoomToFit$: function () {\n\t if (arguments.length === 0) {\n\t return this.zoomToFitTexture$();\n\t } else {\n\t return this.zoomToFitFigures$.apply(this, arguments);\n\t }\n\t },\n\t docToView: function () /* docPoint */{\n\t console.log('TextureView docToView not supported');\n\t },\n\t docDeltaToView: function (docDelta) {\n\t return this.viewTransform.docDeltaToView(this, docDelta);\n\t },\n\t viewToDoc: function (viewPoint, docIsland) {\n\t return this.modelToDoc(viewPoint, docIsland);\n\t },\n\t docPoint: function (event, docIsland) {\n\t return this.modelToDoc(this.modelPoint(event), docIsland);\n\t },\n\t textureDeltaToDoc: function (textureDelta) {\n\t return this.viewTransform.viewDeltaToDoc(this, textureDelta);\n\t },\n\t\n\t\n\t // Overwritten in TextureView below\n\t viewDeltaToDoc: function (viewDelta) {\n\t return this.viewTransform.viewDeltaToDoc(this, viewDelta);\n\t },\n\t mapToFigureViews: function (figures) {\n\t return this.figureViews.mapToFigureViews(figures);\n\t },\n\t figureView: function (figure) {\n\t return this.figureViews.get(figure);\n\t },\n\t figureTextureTypes: function () {\n\t return ['color']; // Allow 'normal', 'bump', 'specular'...\n\t },\n\t init: function () {\n\t var config = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];\n\t\n\t\n\t this.addEvents('synctextures');\n\t\n\t this._previewing = false;\n\t this._previewingT = 0;\n\t\n\t this._modelReady = false;\n\t this.figureViews = new _view.SyncedFigureViews({ view: this });\n\t\n\t this.textureTiles = {};\n\t\n\t this._backgroundColor = _cdl.Color.White();\n\t\n\t this.callParent(config);\n\t\n\t this._setDoc(new _cdl.Document());\n\t },\n\t insertViewPlugins: function (plugins) {\n\t this.callParent(plugins);\n\t var textureViewPlugins = [_view.Plugin.TextureMap({ textureType: 'color' }), _view.Plugin.TextureViewRenderer()];\n\t if (!this.canvas3D) {\n\t textureViewPlugins = (0, _gear.concat)(textureViewPlugins, [_view.Plugin.ViewControls(), _view.Plugin.PluginsLayer(), _view.Plugin.Tools()]);\n\t }\n\t plugins.insert(0, textureViewPlugins);\n\t },\n\t _setDoc: function (doc) {\n\t var _this3 = this;\n\t\n\t var old = this.doc;\n\t if (old === doc) {\n\t return (0, _gear.resolve)(); // Nothing to do\n\t }\n\t if (old) {\n\t var model3D = old.model3D; // [TODO] This will be removed\n\t\n\t if (model3D) {\n\t model3D.un(this);\n\t }\n\t\n\t this.unlinkDoc(old);\n\t }\n\t\n\t this._modelReady = false;\n\t\n\t this._document = doc;\n\t this.linkDoc(doc);\n\t\n\t if (!doc.is3D) {\n\t return (0, _gear.resolve)();\n\t }\n\t\n\t return doc.loadModel3D$().then(function () {\n\t // [TODO] We could avoid this by avoiding async processing for simple shapes\n\t // This needs further research\n\t\n\t /*\r\n\t // We are only updating when the Doc3D fires events\r\n\t doc.model3D.on({\r\n\t 'materialschanged': this.on_materialschanged,\r\n\t 'model3dchanged': this.on_model3dchanged,\r\n\t 'modeldata3dchanged': this.on_modeldata3dchanged,\r\n\t },this);\r\n\t */\n\t\n\t return doc.model3D.update$().then(function () {\n\t\n\t _this3.syncModel3D();\n\t\n\t _this3._modelReady = true;\n\t // console.log('modelReady');\n\t });\n\t });\n\t },\n\t linkDoc: function (doc) {\n\t this.figureViews.link(doc);\n\t this.callParent(doc);\n\t this.fireEvent('newdocument', this, doc);\n\t },\n\t unlinkDoc: function (doc) {\n\t this.figureViews.unlink(doc);\n\t },\n\t loadModel3D$: function () {\n\t return this.doc.is3D ? this.doc.loadModel3D$() : (0, _gear.resolve)();\n\t },\n\t syncTextures: function () {\n\t var _this4 = this;\n\t\n\t // Sync full textures, color and optinal maps\n\t // The idea is that each figure should be able to draw to these textures\n\t // Tiled textures are directly loaded and cached by getThreeTexture\n\t\n\t if (_config.Config.ignoreTextures) {\n\t return;\n\t }\n\t\n\t var textures = this.textures;\n\t\n\t // Sync texture backgrounds plugins\n\t\n\t var plugins = this.plugins;\n\t\n\t (0, _lodash.remove)(plugins, function (plugin) {\n\t return plugin instanceof _view.Plugin.TextureMap && plugin.textureType !== 'color';\n\t });\n\t\n\t (0, _view.findByTextureType)(plugins, 'color').updateMap();\n\t\n\t (0, _lodash.forEach)(['bump', 'normal', 'specular', 'displacement', 'alpha'], function (textureType) {\n\t\n\t // This function ignores bump maps if there are normal maps\n\t var textureMap = _this4.getFixedTextureMap(textureType);\n\t\n\t var texture = (0, _view.findByTextureType)(textures, textureType);\n\t if (textureMap && textureMap.wrap === 'Stretch') {\n\t // [TODO] Enable it if figures want to draw things to this textureType\n\t if (!texture) {\n\t var composition = _this4.createTexture(textureType);\n\t textures.push(composition);\n\t }\n\t plugins.unshift(_view.Plugin.TextureMap({ textureType: textureType }));\n\t } else if (texture) {\n\t if (texture.layersContainer) {\n\t // [TODO]\n\t texture.remove();\n\t }\n\t textures.remove(texture);\n\t }\n\t\n\t var textureTiles = _this4.textureTiles;\n\t\n\t var tiledTexture = textureTiles[textureType];\n\t if (textureMap && textureMap.wrap === 'Repeat') {\n\t if (!tiledTexture || tiledTexture.id !== textureMap.id) {\n\t\n\t textureTiles[textureType] = new _view.TextureTile(_this4, textureType, textureMap);\n\t }\n\t } else {\n\t textureTiles[textureType] = null;\n\t }\n\t });\n\t\n\t this.fireEvent('synctextures', this);\n\t },\n\t getFixedTextureMap: function (textureType) {\n\t var model = this.model;\n\t var doc = this.doc;\n\t\n\t var docMaterial = doc && doc.materials && doc.materials[0];\n\t if (textureType === 'normal' && docMaterial && docMaterial.getFixedTextureMap('bump')) {\n\t // Ignore normal map in Model3D if there is a bump map in Doc3D\n\t return null;\n\t } else {\n\t var modelMaterial = model && model.materials[0];\n\t var docTextureMap = docMaterial && docMaterial.getFixedTextureMap(textureType);\n\t var modelTextureMap = modelMaterial && modelMaterial.getFixedTextureMap(textureType);\n\t return docTextureMap || modelTextureMap;\n\t }\n\t },\n\t createTexture: function (textureType) {\n\t return new _view.TextureComposition({ textureType: textureType });\n\t },\n\t syncModel3D: function () {\n\t // console.log('syncModel3D');\n\t\n\t this.syncTextures();\n\t\n\t if (this.canvas3D) {\n\t // Forces the texture to cover the requested textureSize ( 512, 1024, 2048 )\n\t this.zoomToFitTextureFor(this.model);\n\t }\n\t },\n\t on_materialschanged: function () {\n\t this.syncModel3D();\n\t this.callParent.apply(this, arguments);\n\t },\n\t on_model3dchanged: function () {\n\t this.syncModel3D();\n\t this.callParent.apply(this, arguments);\n\t },\n\t\n\t /*\r\n\t on_modeldata3dchanged() {\r\n\t },\r\n\t */\n\t\n\t optimizePreview: function () {\n\t if (_config.Config.texturePreview) {\n\t this._previewingResize = true;\n\t this._previewing = true;\n\t this._previewingT = (0, _lodash.now)();\n\t this.updateSize();\n\t this._previewingResize = false;\n\t }\n\t },\n\t endPreview: function () {\n\t if (this._previewing && this.width !== this.textureSize) {\n\t this._previewingResize = true;\n\t this._previewing = false;\n\t this.updateSize();\n\t this._previewingResize = false;\n\t }\n\t },\n\t\n\t\n\t // [MODEL]\n\t on_renderstarted: function (doc, type) {\n\t if (this.canvas3D) {\n\t if (type === 'preview') {\n\t this.optimizePreview();\n\t } else if (type === 'commit') {\n\t this.endPreview();\n\t }\n\t }\n\t this.callParent(doc, type);\n\t },\n\t dispose: function () {\n\t if (this.doc) {\n\t this.unlinkDoc(this.doc);\n\t }\n\t this.callParent();\n\t },\n\t onBackgroundColorChange: function () {\n\t this.redraw('document');\n\t },\n\t\n\t\n\t get textureView() {\n\t return this;\n\t },\n\t\n\t pluginDirectDomEventHandling: function (_ref) {\n\t var target = _ref.target;\n\t\n\t return target === 'view' || target === 'model';\n\t },\n\t createEventTracker: function (event, docIsland) {\n\t return new _move3d.TextureTracker(event, docIsland);\n\t }\n\t});\n\t\n\tvar TextureView = exports.TextureView = StaticTextureView.extend(_view.InteractiveView_Mixin).extend({\n\t\n\t typeName: 'TextureView',\n\t\n\t // Rewire user interaction to Canvas3D if this texture is being used for it\n\t // Plugins are right now added to the TextureView, because the rendering code\n\t // looked complex to abstract. It may be a good idea to let the plugins in the\n\t // 3D view and wire the rendering instead. This starts to look really complex.\n\t\n\t get is3D() {\n\t return !!this.canvas3D;\n\t },\n\t\n\t get selectAndDragEnabled() {\n\t var canvas3D = this.canvas3D;\n\t\n\t return canvas3D ? canvas3D.selectAndDragEnabled : false;\n\t },\n\t\n\t viewDeltaToDoc: function (delta) {\n\t var canvas3D = this.canvas3D;\n\t\n\t return canvas3D ? canvas3D.viewDeltaToDoc(delta) : this.callParent(delta);\n\t },\n\t viewDeltaToTexture: function (delta) {\n\t var canvas3D = this.canvas3D;\n\t\n\t return canvas3D ? canvas3D.viewDeltaToTexture(delta) : this.callParent(delta);\n\t },\n\t triggerKeyboard: function (event) {\n\t var canvas3D = this.canvas3D;\n\t\n\t return canvas3D ? canvas3D.triggerKeyboard(event) : this.callParent(event);\n\t },\n\t are: function () {\n\t var canvas3D = this.canvas3D;\n\t\n\t return canvas3D ? canvas3D.are.apply(canvas3D, arguments) : this.callParent.apply(this, arguments);\n\t },\n\t is: function () {\n\t var canvas3D = this.canvas3D;\n\t\n\t return canvas3D ? canvas3D.is.apply(canvas3D, arguments) : this.callParent.apply(this, arguments);\n\t },\n\t\n\t\n\t /*\r\n\t condition() {\r\n\t const { canvas3D } = this;\r\n\t return canvas3D ? canvas3D.condition(...arguments) : this.callParent(...arguments);\r\n\t },\r\n\t */\n\t\n\t status: function (s) {\n\t var canvas3D = this.canvas3D;\n\t\n\t return canvas3D ? canvas3D.status(s) : this.callParent(s);\n\t },\n\t get_cursor: function () {\n\t var canvas3D = this.canvas3D;\n\t\n\t return canvas3D ? canvas3D.cursor : this.callParent();\n\t },\n\t set_cursor: function (cursor) {\n\t var canvas3D = this.canvas3D;\n\t\n\t if (canvas3D) {\n\t canvas3D.cursor = cursor;\n\t } else {\n\t this.callParent(cursor);\n\t }\n\t },\n\t fireEvent: function (type) {\n\t var canvas3D = this.canvas3D;\n\t\n\t for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n\t params[_key - 1] = arguments[_key];\n\t }\n\t\n\t if (canvas3D) {\n\t if (type === 'toolchanged' || type === 'figuresdrag' || type === 'figuresdrop') {\n\t\n\t canvas3D.fireEvent.apply(canvas3D, [type].concat(_toConsumableArray(params)));\n\t }\n\t }\n\t this.callParent.apply(this, [type].concat(_toConsumableArray(params)));\n\t }\n\t});\n\t\n\texports.default = TextureView;\n\n/***/ },\n\n/***/ 121:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.Doc3D_Model_Mixin = undefined;\n\t\n\tvar _cdl = __webpack_require__(15);\n\t\n\tvar _move3d = __webpack_require__(122);\n\t\n\tfunction notTextureIsland(figure) {\n\t return !(0, _cdl.isTextureIsland)(figure);\n\t}\n\t\n\tvar Doc3D_Model_Mixin = exports.Doc3D_Model_Mixin = {\n\t\n\t Properties: {\n\t selectableIslands: { type: 'boolean', def: true }\n\t },\n\t\n\t init: function () {\n\t this.callParent.apply(this, arguments);\n\t\n\t // DocIslands can not be moved from these views\n\t this.condition('movable', notTextureIsland);\n\t this.condition('rotatable', notTextureIsland);\n\t this.condition('removable', notTextureIsland);\n\t this.condition('copyable', notTextureIsland);\n\t },\n\t activeSelectableFigures: function () {\n\t // [TODO] activePageSelection, allowCrossPageSelection\n\t return this.callParent();\n\t },\n\t uvToModel: function (uv) {\n\t return this.model.uvToModel(uv);\n\t },\n\t uvToDoc: function (uv, docIsland) {\n\t return this.modelToDoc(this.uvToModel(uv), docIsland);\n\t },\n\t modelToDoc: function (modelPoint, docIsland) {\n\t if (docIsland === undefined) {\n\t docIsland = this.topDocIslandAtModel(modelPoint);\n\t if (!docIsland) {\n\t return undefined;\n\t }\n\t }\n\t var matrix = this.model.modelToDocMatrixFor(docIsland);\n\t var docPoint = matrix.apply(modelPoint);\n\t return docPoint;\n\t },\n\t topDocIslandAtModel: function (modelPoint, modelIsland) {\n\t if (!modelIsland) {\n\t modelIsland = this.modelIslandAt(modelPoint);\n\t }\n\t return modelIsland && this.topDocIslandFor(modelIsland);\n\t },\n\t topDocIslandFor: function (modelIsland) {\n\t return this.doc.topDocIslandFor(modelIsland);\n\t },\n\t docIslandsFor: function (docIsland) {\n\t return this.doc.docIslandsFor(docIsland);\n\t },\n\t modelIslandFor: function (docIsland) {\n\t return this.model.modelIslandFor(docIsland);\n\t },\n\t modelIslandAt: function (modelPoint) {\n\t return this.textureView._modelReady && this.model.modelIslandAt(modelPoint);\n\t },\n\t modelPointIsOut: function (modelPoint, modelIsland) {\n\t return !modelIsland.bounds_().contains(modelPoint);\n\t },\n\t forEachDesignFiguresIn: function (name, func) {\n\t var doc = this.doc;\n\t var pages = doc.pages;\n\t\n\t for (var p = 0, pEnd = pages.length; p < pEnd; ++p) {\n\t var page = pages[p];\n\t var designFigures = (0, _cdl.designFiguresFrom)(page);\n\t var docIslands = (0, _cdl.docIslandsFrom)(page);\n\t for (var i = 0, iEnd = docIslands.length; i < iEnd; ++i) {\n\t var docIsland = docIslands[i];\n\t if ((0, _cdl.textureIslandName)(docIsland) === name) {\n\t func(docIsland, designFigures);\n\t }\n\t }\n\t }\n\t },\n\t extractHitInfo: function (hit, info) {\n\t if (hit) {\n\t if (info) {\n\t info.tight = hit.tight;\n\t info.docPoint = hit.docPoint;\n\t info.docIsland = hit.docIsland;\n\t }\n\t return hit.figure;\n\t }\n\t return hit;\n\t },\n\t figureAtModelPointEx: function (modelPoint, tabFigures) {\n\t var candidates = this.candidateFiguresAtModelPoint(modelPoint);\n\t return this.bestFigureCandidate(candidates, tabFigures);\n\t },\n\t filterSelectableInto: function (figures, r) {\n\t // [TODO] filter by condition\n\t for (var k = 0, kEnd = figures.length; k < kEnd; k++) {\n\t var figure = figures[k];\n\t if (this.is(figure, 'selectable')) {\n\t r.push(figure);\n\t }\n\t }\n\t },\n\t rawFigureHitsAtModelPoint: function (modelPoint) {\n\t return this.candidateFiguresAtModelPoint(modelPoint, true);\n\t },\n\t candidateFiguresAtModelPoint: function (modelPoint) {\n\t var raw = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];\n\t var selectableIslands = this.selectableIslands;\n\t\n\t var candidates = [];\n\t var modelIsland = this.modelIslandAt(modelPoint);\n\t var docIslandCandidates = [];\n\t var pages = this.doc.pages;\n\t\n\t for (var p = pages.length - 1; p >= 0; --p) {\n\t var page = pages[p];\n\t\n\t if (raw || !page._locked && !page._hidden) {\n\t\n\t var pagedDesignLayers = (0, _cdl.designLayersFrom)(page);\n\t var designLayers = raw ? pagedDesignLayers : (0, _cdl.filterTargetLayers)(pagedDesignLayers);\n\t\n\t var figures = void 0;\n\t if (raw) {\n\t figures = _cdl.Layers.flatten(designLayers);\n\t } else {\n\t figures = [];\n\t for (var l = 0, lEnd = designLayers.length; l < lEnd; ++l) {\n\t this.filterSelectableInto(designLayers[l].figures, figures);\n\t }\n\t }\n\t\n\t var docIslands = (0, _cdl.filterIslandsFor)((0, _cdl.docIslandsFrom)(page), modelIsland);\n\t\n\t for (var f = figures.length - 1; f >= 0; --f) {\n\t var figure = figures[f];\n\t\n\t for (var i = docIslands.length - 1; i >= 0; --i) {\n\t var docIsland = docIslands[i];\n\t var docPoint = (0, _cdl.modelToDocMatrix)(docIsland, modelIsland).apply(modelPoint);\n\t\n\t if (figure.globalFrame_().contains(docPoint)) {\n\t candidates.push({\n\t figure: figure, docIsland: docIsland, docPoint: docPoint,\n\t tight: raw ? figure.containsPoint(docPoint) : false\n\t });\n\t }\n\t }\n\t }\n\t\n\t if (raw || selectableIslands) {\n\t for (var _i = docIslands.length - 1; _i >= 0; --_i) {\n\t var _docIsland = docIslands[_i];\n\t var _docPoint = (0, _cdl.modelToDocMatrix)(_docIsland, modelIsland).apply(modelPoint);\n\t docIslandCandidates.push({\n\t figure: _docIsland, docIsland: _docIsland, docPoint: _docPoint,\n\t tight: raw ? _docIsland.containsPoint(_docPoint) : false\n\t });\n\t }\n\t }\n\t }\n\t }\n\t\n\t return candidates.concat(docIslandCandidates);\n\t },\n\t on_domEvent: function (_ref) {\n\t var event = _ref.event;\n\t var type = _ref.type;\n\t var isPrimary = _ref.isPrimary;\n\t\n\t\n\t if (isPrimary && type === 'pointerdown') {\n\t var modelPoint = event.modelPoint;\n\t\n\t if (modelPoint && this.modelIslandAt(modelPoint)) {\n\t // track3D.log(`[3D] Start tracking of ${type}`);\n\t var docIsland = this.topDocIslandAtModel(modelPoint);\n\t if (docIsland) {\n\t this.tracker = this.createEventTracker(event, docIsland);\n\t }\n\t }\n\t }\n\t\n\t this.callParent(event);\n\t\n\t if (isPrimary && this.tracker && type === 'pointerup') {\n\t // track3D.log(`[3D] End tracking of ${type}`);\n\t this.tracker = null;\n\t }\n\t },\n\t handlePluginDomEvent: function (plugin, _ref2) {\n\t var event = _ref2.event;\n\t var type = _ref2.type;\n\t var route = _ref2.route;\n\t var isPrimary = _ref2.isPrimary;\n\t\n\t\n\t if (this.pluginDirectDomEventHandling(plugin)) {\n\t plugin.handleDomEvent(event);\n\t return;\n\t }\n\t\n\t // We avoid providing feedback in case of 3D views, as it is slowing down\n\t // things for complex models. It is also not clear how to handle properly\n\t // feedback in tools if there are several islands. \n\t if (false) {\n\t var modelPoint = event.modelPoint;\n\t\n\t var modelIsland = modelPoint && this.modelIslandAt(modelPoint);\n\t if (modelIsland) {\n\t var docIslands = this.docIslandsFor(modelIsland);\n\t for (var i = docIslands.length - 1; i >= 0 && !event.stopped; --i) {\n\t var docIsland = docIslands[i];\n\t var newEvent = (0, _move3d.retargetEvent3D)(event, docIsland);\n\t plugin.on_domEvent(newEvent);\n\t if (newEvent.stopped) {\n\t event.stopPropagation();\n\t }\n\t }\n\t }\n\t }\n\t\n\t if (type === 'pointerdown' && isPrimary) {\n\t var _modelPoint = event.modelPoint;\n\t\n\t var _modelIsland = _modelPoint && this.modelIslandAt(_modelPoint);\n\t if (_modelIsland) {\n\t\n\t if (plugin.has_try_pointerdown()) {\n\t\n\t var _docIslands = this.docIslandsFor(_modelIsland);\n\t\n\t for (var _i2 = _docIslands.length - 1; _i2 >= 0 && !event.stopped; --_i2) {\n\t var _docIsland2 = _docIslands[_i2];\n\t\n\t var tracker = this.createEventTracker(event, _docIsland2);\n\t var _newEvent = tracker.retargetedEvent;\n\t // track3D.log(`[3D] Try to start Tracking of ${type}`);\n\t plugin.try_pointerdown(_newEvent);\n\t if (_newEvent.stopped) {\n\t this.tracker = tracker; // Change the default tracking to follow this island\n\t event.stopPropagation();\n\t }\n\t }\n\t\n\t if (event.stopped) {\n\t return false;\n\t }\n\t }\n\t\n\t // track3D.log(`[3D] ${type}`);\n\t plugin.on_domEvent(event);\n\t }\n\t } else if ((type === 'pointermove' || type === 'pointerup') && isPrimary) {\n\t\n\t if (this.tracker) {\n\t // even if modelPoint is null, we track these events\n\t var _newEvent2 = this.tracker.move(event);\n\t plugin.on_domEvent(_newEvent2);\n\t if (_newEvent2.stopped) {\n\t event.stopPropagation();\n\t }\n\t }\n\t } else if (type === 'click' || type === 'dblcick' || type === 'contextmenu') {\n\t var _modelPoint2 = event.modelPoint;\n\t\n\t var _modelIsland2 = _modelPoint2 && this.modelIslandAt(_modelPoint2);\n\t if (_modelIsland2) {\n\t\n\t var tryHandler = 'try_' + type;\n\t if (plugin['has_' + tryHandler]()) {\n\t\n\t var _docIslands2 = this.docIslandsFor(_modelIsland2);\n\t for (var _i3 = _docIslands2.length - 1; _i3 >= 0 && !event.stopped; --_i3) {\n\t var _docIsland3 = _docIslands2[_i3];\n\t // track3D.log(`[3D] Retarget of ${type}, using try_`);\n\t var _newEvent3 = (0, _move3d.retargetEvent3D)(event, _docIsland3);\n\t plugin[tryHandler](_newEvent3);\n\t if (_newEvent3.stopped) {\n\t event.stopPropagation();\n\t }\n\t }\n\t\n\t if (event.stopped) {\n\t return false;\n\t }\n\t }\n\t // track3D.log(`[3D] Direct routing of ${type}`);\n\t plugin.on_domEvent(event);\n\t }\n\t } else if (type === 'keypress' || type === 'keydown' || type === 'keyup' || type === 'mousewheel' || type === 'focus' || type === 'focusout') {\n\t\n\t // track3D.log(`[3D] Direct routing of ${type}`);\n\t plugin.on_domEvent(event);\n\t }\n\t }\n\t};\n\n/***/ },\n\n/***/ 122:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.TextureTracker = exports.Tracker3D = undefined;\n\texports.retargetEvent3D = retargetEvent3D;\n\t\n\tvar _lodash = __webpack_require__(4);\n\t\n\tvar _cdl = __webpack_require__(15);\n\t\n\t// Simple retargetting without tracking\n\t\n\tvar SimpleTracker3D = function (event, docIsland) {\n\t this._event = event;\n\t this._docIsland = docIsland;\n\t};\n\tSimpleTracker3D.prototype.track = function (_ref) {\n\t var view = _ref.view;\n\t\n\t\n\t var docIsland = this._docIsland,\n\t modelPoint = this._event.modelPoint,\n\t // Important, this._event is different from track(event) here\n\t modelIsland = view.modelIslandFor(docIsland),\n\t docPoint = view.modelToDoc(modelPoint, docIsland);\n\t\n\t return {\n\t modelPoint: modelPoint,\n\t modelIsland: modelIsland,\n\t docIsland: docIsland,\n\t docPoint: docPoint,\n\t modelPointRaw: modelPoint,\n\t modelIslandRaw: modelIsland,\n\t docIslandRaw: docIsland,\n\t docPointRaw: docPoint\n\t };\n\t};\n\t\n\tfunction retargetEvent3D(event, docIsland) {\n\t return event.retarget(event.eventDown, new SimpleTracker3D(event, docIsland));\n\t}\n\t\n\t// Move3D helper to track the mouse starting from a given doc island\n\t// and following it even if it goes out it or the model\n\t\n\tvar Tracker3D = exports.Tracker3D = function (_ref2, docIsland) {\n\t var view = _ref2.view;\n\t var event = _ref2.event;\n\t var viewPoint = _ref2.viewPoint;\n\t var modelPoint = _ref2.modelPoint;\n\t\n\t\n\t var docPoint = view.modelToDoc(modelPoint, docIsland);\n\t var modelIsland = view.modelIslandFor(docIsland);\n\t\n\t (0, _lodash.assign)(this, { view: view,\n\t\n\t event: event,\n\t eventDown: event,\n\t\n\t // Points following the original island\n\t // This is used for almost all tools\n\t modelPoint: modelPoint,\n\t modelIsland: modelIsland,\n\t docIsland: docIsland,\n\t docPoint: docPoint,\n\t\n\t // Tracking, always against the docIslandDown\n\t viewPointLast: viewPoint,\n\t modelPointLast: modelPoint,\n\t\n\t // Points that jumps between islands, useful for move operations\n\t modelPointRaw: modelPoint,\n\t modelIslandRaw: modelIsland,\n\t docIslandRaw: docIsland,\n\t docPointRaw: docPoint,\n\t\n\t // Raw tracking, front => sleeve => out (should use sleeve points)\n\t viewPointFirstRaw: viewPoint,\n\t viewPointLastRaw: viewPoint,\n\t\n\t modelPointFirstRaw: modelPoint,\n\t modelPointLastRaw: modelPoint,\n\t\n\t started: false\n\t });\n\t\n\t this.retargetedEventDown = this.retargetedEvent;\n\t};\n\t\n\tTracker3D.prototype = {\n\t\n\t get retargetedEvent() {\n\t return this.event.retarget(this.retargetedEventDown, this);\n\t },\n\t\n\t track: function () {\n\t var _event = this.event;\n\t var view = _event.view;\n\t var viewPoint = _event.viewPoint;\n\t var originalEvent = _event.originalEvent;\n\t\n\t var modelPoint = view.modelPoint(originalEvent);\n\t\n\t var eventDown = this.eventDown;\n\t var docIsland = this.docIsland;\n\t var modelIsland = this.modelIsland;\n\t\n\t\n\t if (modelPoint && !modelPoint.isEqual(eventDown.modelPoint)) {\n\t this.started = true;\n\t }\n\t\n\t if (!this.started) {\n\t return this.trackData();\n\t }\n\t\n\t var modelPointRaw = modelPoint;\n\t\n\t if (modelPoint && !view.modelPointIsOut(modelPoint, modelIsland)) {\n\t\n\t this.modelPoint = modelPoint;\n\t\n\t this.viewPointLast = viewPoint;\n\t this.modelPointLast = modelPoint;\n\t } else {\n\t\n\t // We need to come up with a proper modelPoint to continue the movement\n\t this.modelPoint = interpolatingExtension(viewPoint, eventDown.viewPoint, this.viewPointLast, eventDown.modelPoint, this.modelPointLast);\n\t }\n\t\n\t this.docPoint = view.modelToDoc(this.modelPoint, this.docIsland);\n\t\n\t // Raw properties\n\t\n\t if (modelPointRaw && view.modelPointIsOut(modelPointRaw, this.modelIslandRaw)) {\n\t\n\t var docIslandRaw = view.topDocIslandAtModel(modelPointRaw);\n\t if (docIslandRaw && docIslandRaw.page === docIsland.page) {\n\t this.modelIslandRaw = view.modelIslandAt(modelPointRaw);\n\t this.docIslandRaw = docIslandRaw;\n\t\n\t this.viewPointFirstRaw = viewPoint;\n\t this.modelPointFirstRaw = modelPointRaw;\n\t } else {\n\t // Trigger interpolation\n\t modelPointRaw = null;\n\t }\n\t }\n\t\n\t if (modelPointRaw) {\n\t\n\t this.modelPointRaw = modelPointRaw;\n\t\n\t this.viewPointLastRaw = viewPoint;\n\t this.modelPointLastRaw = modelPointRaw;\n\t } else {\n\t\n\t // We need to come up with a proper modelPointRaw to continue the movement\n\t this.modelPointRaw = interpolatingExtension(viewPoint, this.viewPointFirstRaw, this.viewPointLastRaw, this.modelPointFirstRaw, this.modelPointLastRaw);\n\t }\n\t\n\t this.docPointRaw = view.modelToDoc(this.modelPointRaw, this.docIslandRaw);\n\t\n\t return this.trackData();\n\t },\n\t trackData: function () {\n\t return {\n\t modelIsland: this.modelIsland,\n\t docIsland: this.docIsland,\n\t docPoint: this.docPoint,\n\t modelPointRaw: this.modelPointRaw,\n\t modelIslandRaw: this.modelIslandRaw,\n\t docIslandRaw: this.docIslandRaw,\n\t docPointRaw: this.docPointRaw\n\t };\n\t },\n\t move: function (event) {\n\t this.event = event;\n\t return this.retargetedEvent;\n\t }\n\t};\n\t\n\t// Move3D helper to track the mouse starting from a given doc island\n\t// and following it even if it goes out it or the model\n\t\n\tvar TextureTracker = exports.TextureTracker = function (_ref3, docIsland) {\n\t var view = _ref3.view;\n\t var event = _ref3.event;\n\t var viewPoint = _ref3.viewPoint;\n\t var modelPoint = _ref3.modelPoint;\n\t\n\t\n\t var docPoint = view.modelToDoc(modelPoint, docIsland);\n\t var modelIsland = view.modelIslandFor(docIsland);\n\t\n\t (0, _lodash.assign)(this, { view: view,\n\t\n\t event: event,\n\t eventDown: event,\n\t\n\t // Points following the original island\n\t // This is used for almost all tools\n\t modelPoint: modelPoint,\n\t modelIsland: modelIsland,\n\t docIsland: docIsland,\n\t docPoint: docPoint,\n\t\n\t // Points that jumps between islands, useful for move operations\n\t modelPointRaw: modelPoint,\n\t modelIslandRaw: modelIsland,\n\t docIslandRaw: docIsland,\n\t docPointRaw: docPoint,\n\t\n\t started: false\n\t });\n\t\n\t this.retargetedEventDown = this.retargetedEvent;\n\t};\n\t\n\tTextureTracker.prototype = {\n\t\n\t get retargetedEvent() {\n\t return this.event.retarget(this.retargetedEventDown, this);\n\t },\n\t\n\t track: function () {\n\t var _event2 = this.event;\n\t var view = _event2.view;\n\t var originalEvent = _event2.originalEvent;\n\t\n\t\n\t var modelPoint = view.modelPoint(originalEvent);\n\t\n\t var eventDown = this.eventDown;\n\t var docIsland = this.docIsland;\n\t\n\t\n\t if (modelPoint && !modelPoint.isEqual(eventDown.modelPoint)) {\n\t this.started = true;\n\t }\n\t\n\t if (!this.started) {\n\t return this.trackData();\n\t }\n\t\n\t this.modelPoint = modelPoint;\n\t this.docPoint = view.modelToDoc(modelPoint, docIsland);\n\t\n\t // Raw properties\n\t\n\t\n\t if (view.modelPointIsOut(modelPoint, this.modelIslandRaw)) {\n\t\n\t var docIslandRaw = view.topDocIslandAtModel(modelPoint);\n\t if (docIslandRaw && docIslandRaw.page === docIsland.page) {\n\t this.modelIslandRaw = view.modelIslandAt(modelPoint);\n\t this.docIslandRaw = docIslandRaw;\n\t }\n\t }\n\t\n\t this.modelPointRaw = modelPoint;\n\t this.docPointRaw = view.modelToDoc(modelPoint, this.docIslandRaw);\n\t\n\t return this.trackData();\n\t },\n\t trackData: function () {\n\t return {\n\t modelIsland: this.modelIsland,\n\t docIsland: this.docIsland,\n\t docPoint: this.docPoint,\n\t modelPointRaw: this.modelPointRaw,\n\t modelIslandRaw: this.modelIslandRaw,\n\t docIslandRaw: this.docIslandRaw,\n\t docPointRaw: this.docPointRaw\n\t };\n\t },\n\t move: function (event) {\n\t this.event = event;\n\t return this.retargetedEvent;\n\t }\n\t};\n\t\n\tfunction interpolatingExtension(newFrom, firstFrom, lastFrom, firstTo, lastTo) {\n\t\n\t if (firstFrom.isEqual(lastFrom)) {\n\t return lastTo.clone();\n\t }\n\t\n\t var last_firstFrom = lastFrom.minus(firstFrom),\n\t last_firstFrom_norm = last_firstFrom.norm(),\n\t last_firstFrom_n = last_firstFrom.scaled(1 / last_firstFrom_norm),\n\t new_firstFrom = newFrom.minus(firstFrom),\n\t dotProductFrom = _cdl.Point.dotProduct(last_firstFrom, new_firstFrom),\n\t ap = last_firstFrom_n.scaled(dotProductFrom / last_firstFrom_norm),\n\t alpha = ap.norm() / last_firstFrom_norm * (dotProductFrom >= 0 ? 1 : -1),\n\t bp = new_firstFrom.minus(ap),\n\t beta = bp.norm() / last_firstFrom_norm * (_cdl.Point.dotProduct(bp, last_firstFrom.perpendicular(-1)) >= 0 ? -1 : 1),\n\t last_firstTo = lastTo.minus(firstTo),\n\t adp = last_firstTo.scaled(alpha),\n\t bdp = last_firstTo.perpendicular(-1).scaled(beta);\n\t\n\t return firstTo.plus(adp).plus(bdp);\n\t}\n\n/***/ },\n\n/***/ 123:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.TextureViewComposition = undefined;\n\t\n\tvar _config = __webpack_require__(2);\n\t\n\tvar _lodash = __webpack_require__(4);\n\t\n\tvar _gear = __webpack_require__(8);\n\t\n\tvar _cdl = __webpack_require__(15);\n\t\n\tvar _view = __webpack_require__(84);\n\t\n\tvar filterProcessed = _cdl.Figures.filterProcessed;\n\t\n\t\n\tfunction processedDocIslandsFor(page, modelIsland) {\n\t // filterProcessed( filter( docIslandsFrom(page), isDocIslandFor(modelIsland) ) );\n\t var modelIslandName = (0, _cdl.textureIslandName)(modelIsland);\n\t var pageDocIslands = (0, _cdl.docIslandsFrom)(page);\n\t var docIslands = [];\n\t for (var pdi = 0, pdiEnd = pageDocIslands.length; pdi < pdiEnd; ++pdi) {\n\t var island = pageDocIslands[pdi];\n\t if (island.processed() && (0, _cdl.textureIslandName)(island) === modelIslandName) {\n\t docIslands.push(island);\n\t }\n\t }\n\t return docIslands;\n\t}\n\t\n\tvar TextureViewComposition = exports.TextureViewComposition = _view.TextureComposition.extend({ typeName: 'TextureViewComposition',\n\t\n\t clearComposedCanvas: function () {\n\t if (!this.canvas3D) {\n\t // No need to clear the canvas in case the texture is used for a canvas3D\n\t this.callParent();\n\t }\n\t },\n\t\n\t\n\t // Overwrite drawPlugin to add the logic of rendering each plugin\n\t // once for every texture island\n\t drawPlugin: function (view, plugin, name, context) {\n\t\n\t if (!view._modelReady) {\n\t return; // There isn't a Doc3D properly loaded yet\n\t }\n\t\n\t if (!plugin.somethingToDraw()) {\n\t return; // Optimization\n\t }\n\t\n\t var model = view.model;\n\t var target = plugin.target;\n\t\n\t\n\t if (target === 'view' || target === 'model') {\n\t\n\t this.callParent(view, plugin, name, context);\n\t } else {\n\t\n\t var transformModel = view.getViewPortTransform();\n\t\n\t var drawConfig = view.drawConfig();\n\t\n\t var modelIslands = model.modelIslands;\n\t\n\t for (var i = 0, iEnd = modelIslands.length; i < iEnd; ++i) {\n\t var modelIsland = modelIslands[i];\n\t\n\t var config = (0, _lodash.assign)({ view: view, context: context, transformModel: transformModel, modelIsland: modelIsland }, drawConfig);\n\t\n\t context.save();\n\t\n\t if (!_config.Config.clipTest1) {\n\t var bleedModelIsland = model.bleedModelIslandWithName((0, _cdl.textureIslandName)(modelIsland));\n\t bleedModelIsland.polyregions[0].clipContext(context, transformModel);\n\t }\n\t\n\t if (target === 'textureIslands') {\n\t\n\t // The draw function is called once for every texture island clipped to it\n\t this.drawPlugin2D(view, plugin, name, (0, _lodash.assign)({\n\t transform: transformModel\n\t }, config));\n\t } else {\n\t // target === 'document'\n\t\n\t var pages = view.pages;\n\t\n\t for (var p = 0, pEnd = pages.length; p < pEnd; ++p) {\n\t var page = pages[p];\n\t\n\t var docIslands = processedDocIslandsFor(page, modelIsland);\n\t\n\t for (var d = 0, dEnd = docIslands.length; d < dEnd; ++d) {\n\t var docIsland = docIslands[d];\n\t\n\t // Optimization, no need to draw the plugin if it doesn't overlap with this docIsland\n\t if (plugin.needsToDrawFor(docIsland)) {\n\t\n\t var transformDoc = _cdl.Matrix.m(transformModel, (0, _cdl.docToModelMatrix)(docIsland, modelIsland));\n\t\n\t // The draw function is called, once for every pair texture island <-> docisland\n\t this.drawPlugin2D(view, plugin, name, (0, _lodash.assign)({\n\t docIsland: docIsland,\n\t transformDoc: transformDoc,\n\t transform: transformDoc\n\t }, config));\n\t }\n\t }\n\t }\n\t }\n\t\n\t context.restore(); // Remove clipping\n\t }\n\t }\n\t }\n\t});\n\t\n\t_view.Plugin.TextureViewRenderer = _view.Plugin.extend({ typeName: 'TextureViewRendererPlugin',\n\t\n\t name: 'renderer',\n\t\n\t drawTo_color: ['document'],\n\t\n\t // The draw function will be called, once for every texture island and all\n\t // drawing will be clipped to it.\n\t // We need to do it like this to respect the z-order of figures\n\t target: 'textureIslands',\n\t\n\t redrawFigure: function () /*view,figure*/{\n\t this.redraw();\n\t },\n\t draw: function (config) {\n\t var view = config.view;\n\t var context = config.context;\n\t var transformModel = config.transformModel;\n\t var modelIsland = config.modelIsland;\n\t var doc = view.doc;\n\t\n\t // First draw the islands background, using the top most island across all pages\n\t // Transparent brushes will show the color texture underneath\n\t\n\t {\n\t var backgroundDocIsland = doc.topDocIslandFor(modelIsland);\n\t if (backgroundDocIsland && backgroundDocIsland.processed()) {\n\t var transformDoc = _cdl.Matrix.m(transformModel, (0, _cdl.docToModelMatrix)(backgroundDocIsland, modelIsland));\n\t var brush = backgroundDocIsland.polyregions[0].brush;\n\t\n\t if (!(brush._empty || brush.typeName === 'Brush' && brush.color.alpha === 0)) {\n\t view.figureView(backgroundDocIsland).draw(context, transformDoc, (0, _lodash.defaults)({ transformDoc: transformDoc, ignorePen: true }, config));\n\t }\n\t }\n\t }\n\t\n\t // Then draw all the figures, respecting their z-order in their layers and\n\t // between pages. The last page will have the top most figures\n\t\n\t var pages = doc.pages;\n\t\n\t for (var p = 0, pEnd = pages.length; p < pEnd; ++p) {\n\t var page = doc.pages[p];\n\t\n\t var docIslands = processedDocIslandsFor(page, modelIsland);\n\t\n\t var designLayers = (0, _cdl.designLayersFrom)(page);\n\t for (var l = 0, lEnd = designLayers.length; l < lEnd; ++l) {\n\t var layer = designLayers[l];\n\t\n\t layer.beforeDraw(context, config);\n\t\n\t var figures = filterProcessed(layer.figures);\n\t\n\t for (var i = 0, iEnd = figures.length; i < iEnd; ++i) {\n\t var figure = figures[i];\n\t\n\t for (var di = 0, diEnd = docIslands.length; di < diEnd; ++di) {\n\t var docIsland = docIslands[di];\n\t\n\t // Optimization, no need to draw the figure if it doesn't overlap with this docIsland\n\t if (_cdl.Frame.areOverlapping(docIsland.frame_(), figure.frame_())) {\n\t\n\t // Change the transformDoc of the config\n\t var _transformDoc = _cdl.Matrix.m(transformModel, (0, _cdl.docToModelMatrix)(docIsland, modelIsland));\n\t var figureView = view.figureView(figure);\n\t\n\t if (figureView) {\n\t figureView.draw(context, _transformDoc, (0, _lodash.defaults)({ transformDoc: _transformDoc }, config));\n\t } else {\n\t console.log('[Error] FigureView is undefined');\n\t }\n\t\n\t if (view.showPin) {\n\t // Do it as a config option\n\t (0, _gear.dot)(context, figure.pin, view.viewDeltaToTexture(3), _transformDoc, '#ffffff', '#222222', view.viewDeltaToTexture(4));\n\t }\n\t }\n\t }\n\t }\n\t\n\t layer.afterDraw(context, config);\n\t }\n\t }\n\t }\n\t});\n\n/***/ },\n\n/***/ 124:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.Canvas3D = exports.StaticCanvas3D = undefined;\n\t\n\tvar _config = __webpack_require__(2);\n\t\n\tvar _gear = __webpack_require__(8);\n\t\n\tvar _lodash = __webpack_require__(4);\n\t\n\tvar _cdl = __webpack_require__(15);\n\t\n\tvar _view3d = __webpack_require__(125);\n\t\n\tvar _view = __webpack_require__(84);\n\t\n\tvar _doc3dModelMixin = __webpack_require__(121);\n\t\n\tvar _textureView2 = __webpack_require__(120);\n\t\n\tvar _threeUtil = __webpack_require__(127);\n\t\n\tvar _object3d = __webpack_require__(128);\n\t\n\tvar _move3d = __webpack_require__(122);\n\t\n\tfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\t\n\tvar StaticCanvas3D = exports.StaticCanvas3D = _view3d.View3D.extend(_view.DocumentView_Mixin).extend(_view.SelectedFigures_Mixin).extend(_cdl.FigureConditions_Mixin).extend(_doc3dModelMixin.Doc3D_Model_Mixin).extend({\n\t\n\t typeName: 'StaticCanvas3D',\n\t\n\t Properties: {\n\t\n\t document: { type: 'Document', def: null, owned: false, set: function (v) {\n\t this._setDoc(v);\n\t }\n\t },\n\t\n\t textureView: { type: 'TextureView', def: null, owned: false, set: function (v) {\n\t this._setTextureView(v);\n\t }\n\t },\n\t\n\t // [TODO]\n\t documentFilter: { type: 'function', def: null } // Used by load$ by id\n\t },\n\t\n\t // [TODO]\n\t // backSideDarkFactor\n\t // backSideColor\n\t\n\t get model() {\n\t return this.doc.model3D;\n\t },\n\t\n\t get modelData() {\n\t return this.doc.modelData3D;\n\t },\n\t\n\t get textureSize() {\n\t return this.textureView.textureSize;\n\t },\n\t set textureSize(textureSize_) {\n\t this.textureView.textureSize = textureSize_;\n\t },\n\t\n\t isIddle: function () {\n\t return this.callParent() && this.modelData && !this._transformMode;\n\t },\n\t insertViewPlugins: function (plugins) {\n\t\n\t plugins.insert(0, [_view.Plugin.PluginsLayer(), _view.Plugin.FigureAnnotations(), // [TODO] Let users add this on demand\n\t\n\t _view.Plugin.Tools()]);\n\t\n\t this.callParent(plugins);\n\t },\n\t annotate: function () /* ...params */{\n\t var _figureAnnotations;\n\t\n\t return (_figureAnnotations = this.figureAnnotations).annotate.apply(_figureAnnotations, arguments);\n\t },\n\t unannotate: function () /* ...params */{\n\t var _figureAnnotations2;\n\t\n\t return (_figureAnnotations2 = this.figureAnnotations).unannotate.apply(_figureAnnotations2, arguments);\n\t },\n\t clearAnnotations: function () /* ...params */{\n\t var _figureAnnotations3;\n\t\n\t return (_figureAnnotations3 = this.figureAnnotations).clearAnnotations.apply(_figureAnnotations3, arguments);\n\t },\n\t add: function (figures, config) {\n\t var selector = config && config.layer || this.destinationLayerSelector;\n\t if (selector) {\n\t this.setActiveLayerBy(selector);\n\t }\n\t return this.callParent(figures, config);\n\t },\n\t setActiveLayerBy: function (selector) {\n\t var doc = this.doc;\n\t\n\t var layer = doc.activePage.layerBy(selector);\n\t if (layer) {\n\t this.activeLayer = layer;\n\t }\n\t return this;\n\t },\n\t figureView: function (figure) {\n\t return this.textureView.figureView(figure);\n\t },\n\t\n\t\n\t get figureViews() {\n\t return this.textureView.figureViews;\n\t },\n\t\n\t figureTextureTypes: function () {\n\t return this.textureView.figureTextureTypes();\n\t },\n\t asFastOffset: function (offset) {\n\t return this.textureView.asFastOffset(offset);\n\t },\n\t docPoint: function (event, docIsland) {\n\t var modelPoint = this.modelPoint(event);\n\t return modelPoint && this.modelToDoc(modelPoint, docIsland);\n\t },\n\t modelPoint: function (event) {\n\t var uv = this.uvPoint(event);\n\t return uv && this.uvToModel(uv);\n\t },\n\t uvPoint: function (event) {\n\t return this.viewToUV(this.viewPoint(event));\n\t },\n\t viewToUV: function (viewPoint) {\n\t var camera = this.camera;\n\t var width = this.width;\n\t var height = this.height;\n\t\n\t var uv = this.object3D.uvFromViewPoint(camera, viewPoint, width, height);\n\t this.computeViewToTextureScale(); // [TODO] We should move this to a better place\n\t return uv;\n\t },\n\t viewDeltaToDoc: function (delta) {\n\t return this.textureView.textureDeltaToDoc(this.viewDeltaToTexture(delta));\n\t },\n\t computeViewToTextureScale: function (viewPoint) {\n\t var _this = this;\n\t\n\t if (!this._viewToTextureScale) {\n\t (function () {\n\t var camera = _this.camera;\n\t var width = _this.width;\n\t var height = _this.height;\n\t\n\t if (!viewPoint) {\n\t viewPoint = new _cdl.Point(width / 2, height / 2); // Stable... always the same on each model load\n\t }\n\t var uv = _this.object3D.uvFromViewPoint(camera, viewPoint, width, height);\n\t if (uv) {\n\t (function () {\n\t var dist = 5;\n\t var testPoints = [viewPoint.translated_(0, dist), viewPoint.translated_(0, -dist), viewPoint.translated_(dist, 0), viewPoint.translated_(-dist, 0)];\n\t var scales = [];\n\t (0, _lodash.forEach)(testPoints, function (point) {\n\t var uv_close = _this.object3D.uvFromViewPoint(camera, point, width, height);\n\t if (uv_close) {\n\t scales.push(uv_close.minus(uv).norm() / dist);\n\t }\n\t });\n\t var uv_scale = Math.min.apply(Math, scales); // [TODO] Use median ?\n\t var scale = uv_scale * _this.textureSize; // * 1.25;\n\t\n\t var controls = _this.controls;\n\t\n\t var c = camera.position.clone().sub(controls.target).length();\n\t _this._viewToTextureScale = {\n\t scale: scale,\n\t dist: c,\n\t width: width, height: height\n\t };\n\t })();\n\t }\n\t\n\t _this.redraw('tools', 'plugins');\n\t })();\n\t }\n\t },\n\t postResize: function () {\n\t this.callParent();\n\t if (!this.textureView._previewingResize) {\n\t this._viewToTextureScale = null;\n\t this.computeViewToTextureScale();\n\t }\n\t if (_config.Config.keepLowerLeftCornerAsOrigin) {\n\t this.center = this.viewCenter;\n\t }\n\t },\n\t resetToOrigin: function () {\n\t this.zoom = 1;\n\t this.center = this.viewCenter;\n\t },\n\t viewDeltaToTexture: function (viewDelta) {\n\t var camera = this.camera;\n\t var controls = this.controls;\n\t var textureView = this.textureView;\n\t\n\t var c = camera.position.clone().sub(controls.target).length();\n\t\n\t var s = this._viewToTextureScale;\n\t if (s) {\n\t\n\t var rs = viewDelta * s.scale * (this.textureView.width / this.textureSize) * Math.sqrt((c + 0.1) / s.dist); // Account for zooming\n\t\n\t // if( viewDelta === 1 ) { console.log(rs+' / '+c+' / '+s.dist+' / '+this.textureView.width+' / '+s.scale); }\n\t return rs;\n\t }\n\t\n\t var rse = viewDelta * 3 * (textureView.width / this.textureSize) * Math.sqrt((c + 0.1) / 200); //this.controls.zoom;\n\t\n\t // if( viewDelta === 1 ) { console.log('E: '+ rse+' / '+c+' / '+this.textureView.width); }\n\t return rse;\n\t },\n\t\n\t\n\t // Useful for default place where to add figures\n\t get frontDocIsland() {\n\t // [TODO] Use raytracing\n\t return this.doc.topDocIsland; // this.doc.topDocIslandFor( this.model.modelIslands[0] );\n\t },\n\t\n\t // [TODO] The coupling between Canvas3D and its TextureView is now quite complex\n\t // This is mainly to let plugins talk with the textureView or the canvas3D as if\n\t // their will be the same thing. It may be better at the end to leave the plugins\n\t // initialized with the Canvas3D, and forward the drawing instead of the way it\n\t // is done now.\n\t redraw: function () {\n\t var _textureView;\n\t\n\t (_textureView = this.textureView).redraw.apply(_textureView, arguments);\n\t this.callParent.apply(this, arguments);\n\t },\n\t\n\t\n\t get textureZoom() {\n\t return this.textureView.zoom;\n\t },\n\t\n\t // Load by id or set document, the promise finished when the 3D model is shown\n\t load$: function (doc) {\n\t var _this2 = this;\n\t\n\t this.fireEvent('loading', this);\n\t\n\t if (typeof doc === 'string') {\n\t\n\t return _cdl.Document.load$(doc).then(function (loadedDoc) {\n\t return (0, _gear.resolve)(_this2._documentFilter ? _this2._documentFilter(loadedDoc) : true).then(function () {\n\t\n\t return _this2._setDoc(loadedDoc);\n\t });\n\t });\n\t }\n\t\n\t return this._setDoc(doc);\n\t },\n\t onLoaded: function () {\n\t this._readyDeferred.resolve(this.doc);\n\t this._readyDeferred = null;\n\t this.fireEvent('loaded', this);\n\t },\n\t\n\t\n\t get controlsEnabled() {\n\t return this.controls.enabled;\n\t },\n\t set controlsEnabled(state) {\n\t var controls = this.controls;\n\t\n\t if (state === false && this._controlsPanning) {\n\t controls.onMouseUp();\n\t this._controlsPanning = false;\n\t }\n\t controls.enabled = state;\n\t },\n\t setOrbitMode: function () {\n\t this.controls.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };\n\t },\n\t setPanMode: function () {\n\t this.controls.mouseButtons = { ORBIT: THREE.MOUSE.RIGHT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.LEFT };\n\t },\n\t\n\t get isOrbitMode() {\n\t return this.controls.mouseButtons.ORBIT == THREE.MOUSE.LEFT;\n\t },\n\t get isPanMode() {\n\t return this.controls.mouseButtons.PAN == THREE.MOUSE.LEFT;\n\t },\n\t init: function () {\n\t var config = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];\n\t\n\t\n\t this._viewToTextureScale = null;\n\t\n\t this.addEvents('loading', 'loaded');\n\t\n\t this.initSelection(config);\n\t\n\t this._initTextureView(config);\n\t\n\t this._readyDeferred = new _gear.Deferred();\n\t\n\t this._setDoc(new _cdl.Document());\n\t\n\t this.callParent(config);\n\t },\n\t ready$: function () {\n\t if (this._readyDeferred == null) this._readyDeferred = new _gear.Deferred();\n\t return this._readyDeferred.promise;\n\t },\n\t onObject3DChange: function () {\n\t // console.log('object 3D change');\n\t this.redraw('3D');\n\t },\n\t draw$: function () {\n\t var _this3 = this;\n\t\n\t return this.ready$().then(function () {\n\t return _this3.object3D.ready$().then(function () {\n\t return _this3.textureView.draw$().then(function () {\n\t _this3.draw();\n\t });\n\t });\n\t });\n\t },\n\t optimizePreview: function () {\n\t this.textureView.optimizePreview();\n\t },\n\t optimizeZoomPreview: function () {\n\t if (this.updateTextureOnZoom) {\n\t this.textureView.optimizePreview();\n\t }\n\t },\n\t _initTextureView: function () {\n\t var config = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];\n\t\n\t\n\t var textureView = this._textureView;\n\t if (!textureView) {\n\t textureView = this._ownedTexture = new _textureView2.TextureView({\n\t canvas3D: this,\n\t selection: this.selection,\n\t autoDraw: false\n\t });\n\t\n\t // We need the final width to be a power of 2 so\n\t // Three.js can use THREE.LinearMipMapLinearFilter\n\t // Accept forced URL param\n\t textureView.textureSize = _config.Config.textureSize3D ? parseInt(_config.Config.textureSize3D) : config.textureSize ? config.textureSize : 2048;\n\t } else {\n\t textureView.canvas3D = this;\n\t }\n\t this._setTextureView(textureView);\n\t },\n\t syncModelData3D: function () {\n\t\n\t // console.log('syncModelData3D');\n\t\n\t this.object3D.un(this);\n\t this.object3D.dispose();\n\t\n\t var modelData = this.modelData;\n\t\n\t if (modelData) {\n\t\n\t this.object3D = new _object3d.Object3D({\n\t geometry: (0, _threeUtil.parseGeometry)(modelData.data),\n\t textureView: this.textureView,\n\t threeScene: this.threeScene\n\t });\n\t this.object3D.on('change', this.onObject3DChange, this);\n\t\n\t this._viewToTextureScale = null;\n\t\n\t // Update camera and light position\n\t\n\t this.zoomToFront();\n\t } else {\n\t this.object3D = new _object3d.EmptyObject3D();\n\t }\n\t },\n\t on_model3dchanged: function () {\n\t this.syncModelData3D();\n\t this.callParent.apply(this, arguments);\n\t },\n\t on_modeldata3dchanged: function () {\n\t this.syncModelData3D();\n\t this.callParent.apply(this, arguments);\n\t },\n\t _setTextureView: function (textureView) {\n\t\n\t // Unlink old texture\n\t var old = this.textureView;\n\t if (old) {\n\t this._unlinkTextureView(old);\n\t }\n\t\n\t // Link new one\n\t this._textureView = textureView;\n\t\n\t if (this.object3D) {\n\t this.object3D.textureView = textureView;\n\t this.redraw('3D');\n\t }\n\t\n\t textureView.on({\n\t change: this.textureView_on_change.bind(this),\n\t draw: this.textureView_on_draw.bind(this),\n\t redraw: this.textureView_on_redraw.bind(this)\n\t });\n\t },\n\t _unlinkTextureView: function (textureView) {\n\t textureView.un(this);\n\t var _ownedTexture = this._ownedTexture;\n\t\n\t if (_ownedTexture) {\n\t _ownedTexture.dispose();\n\t this._ownedTexture = null;\n\t }\n\t },\n\t textureView_on_change: function (textureView) {\n\t for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n\t params[_key - 1] = arguments[_key];\n\t }\n\t\n\t this.fireEvent.apply(this, ['change', this].concat(_toConsumableArray(params)));\n\t },\n\t textureView_on_draw: function (textureView) {\n\t for (var _len2 = arguments.length, params = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n\t params[_key2 - 1] = arguments[_key2];\n\t }\n\t\n\t this.fireEvent.apply(this, ['draw', this].concat(_toConsumableArray(params)));\n\t },\n\t textureView_on_redraw: function (textureView) {\n\t for (var _len3 = arguments.length, params = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n\t params[_key3 - 1] = arguments[_key3];\n\t }\n\t\n\t this.fireEvent.apply(this, ['redraw', this].concat(_toConsumableArray(params)));\n\t },\n\t _setDoc: function (doc) {\n\t var _this4 = this;\n\t\n\t var old = this.doc;\n\t\n\t if (old === doc) {\n\t return (0, _gear.resolve)(); // Nothing to do\n\t }\n\t if (old) {\n\t this.unlinkDoc(old);\n\t }\n\t this._document = doc;\n\t this.linkDoc(doc);\n\t\n\t var textureView = this.textureView;\n\t\n\t // Clear the current object3D\n\t\n\t if (this.object3D) {\n\t this.object3D.un(this);\n\t this.object3D.dispose();\n\t this.object3D = new _object3d.EmptyObject3D();\n\t this.redraw('3D');\n\t }\n\t\n\t if (_config.Config.keepLowerLeftCornerAsOrigin) {\n\t this.center = this.viewCenter;\n\t }\n\t\n\t return textureView._setDoc(doc).then(function () {\n\t\n\t if (!doc.is3D) {\n\t return;\n\t }\n\t\n\t if (_this4._readyDeferred == null) _this4._readyDeferred = new _gear.Deferred();\n\t\n\t return doc.loadModelData3D$().then(function () {\n\t\n\t _this4.syncModelData3D();\n\t\n\t _this4.onLoaded();\n\t });\n\t });\n\t },\n\t dispose: function () {\n\t if (this.textureView) {\n\t this._unlinkTextureView(this.textureView);\n\t }\n\t this.callParent();\n\t },\n\t pluginDirectDomEventHandling: function (_ref) {\n\t var target = _ref.target;\n\t\n\t return target === 'view';\n\t },\n\t createEventTracker: function (event, docIsland) {\n\t return new _move3d.Tracker3D(event, docIsland);\n\t }\n\t});\n\t\n\tvar Canvas3D = exports.Canvas3D = StaticCanvas3D.extend(_view.InteractiveView_Mixin).extend({\n\t\n\t typeName: 'Canvas3D',\n\t\n\t Properties: {}\n\t\n\t});\n\n/***/ },\n\n/***/ 125:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.View3D = undefined;\n\t\n\tvar _config = __webpack_require__(2);\n\t\n\tvar _lodash = __webpack_require__(4);\n\t\n\tvar _gear = __webpack_require__(8);\n\t\n\tvar _cdl = __webpack_require__(15);\n\t\n\tvar _view = __webpack_require__(84);\n\t\n\tvar _orbitControls = __webpack_require__(126);\n\t\n\tvar _threeUtil = __webpack_require__(127);\n\t\n\tvar _object3d = __webpack_require__(128);\n\t\n\t/* globals THREE */\n\t\n\tvar _THREE = THREE;\n\tvar Vector3 = _THREE.Vector3;\n\tvar View3D = exports.View3D = _view.View.extend({\n\t\n\t typeName: 'View3D',\n\t\n\t Properties: {\n\t\n\t autoRotate: { type: 'boolean',\n\t get: function () {\n\t return this.controls.autoRotate;\n\t },\n\t set: function (v) {\n\t this.controls.autoRotate = v;\n\t }\n\t },\n\t\n\t updateTextureOnZoom: { type: 'boolean', def: true },\n\t\n\t zoomToScale: { type: 'number', def: 1.0 },\n\t\n\t lightOffset: { type: 'number', def: 0 },\n\t\n\t selectAndDragEnabled: { type: 'boolean', def: false }\n\t },\n\t\n\t // [TODO]\n\t // backSideDarkFactor\n\t // backSideColor\n\t\n\t get is3D() {\n\t return true;\n\t },\n\t\n\t isIddle: function () {\n\t return !this.autoRotate && !this.cameraAnim && this.controls && this.controls.isIddle();\n\t },\n\t createScene: function () {\n\t // textures are managed by the textureView, and tools are drawn there\n\t return new _view.Composition({ textureType: '3D', main: true });\n\t },\n\t\n\t\n\t // [TODO] Eliminate setter for textureView, or re-link the plugins\n\t // to the new one\n\t\n\t // Plugins that target the model and document are linked to the textureView\n\t initPlugin: function (plugin) {\n\t if (plugin.target === 'view') {\n\t this.callParent(plugin);\n\t } else {\n\t this.textureView.addPlugin(plugin);\n\t }\n\t },\n\t pluginsToDraw: function () {\n\t // return filter(this._plugins,{ target: 'view' });\n\t var r = [];\n\t var plugins = this.plugins;\n\t\n\t for (var k = 0, kEnd = plugins.length; k < kEnd; ++k) {\n\t var plugin = plugins[k];\n\t if (plugin.target === 'view') {\n\t r.push(plugin);\n\t }\n\t }\n\t return r;\n\t },\n\t insertViewPlugins: function (plugins) {\n\t plugins.insert(0, [_view.Plugin.Renderer3D(), _view.Plugin.ViewControls3D()]);\n\t },\n\t initThreeScene: function () {\n\t\n\t // Create the scene and set the scene size.\n\t var threeScene = this.threeScene = new THREE.Scene();\n\t\n\t // Create a camera, zoom it out from the model a bit, and add it to the scene.\n\t var camera = this.camera = new THREE.PerspectiveCamera(45, this.width / this.height, 0.1, 4000);\n\t camera.position.set(100, 100, 200);\n\t\n\t // Allow to move the camera around the object, works exactly as OrbitControls but\n\t // without dealing with user interaction\n\t this.controls = new _orbitControls.OrbitConstraint(camera);\n\t\n\t threeScene.add(camera);\n\t\n\t // Set the background color of the scene.\n\t // this._setBackgroundColor();\n\t\n\t this.addLights();\n\t\n\t this.updateSize();\n\t },\n\t addLights: function () {\n\t\n\t // We tried different light strategies and it was really difficult to get good results using\n\t // directional and spot lights. To much differences bettwen the light and dark regions.\n\t // Specially for a white background. The hemisphere light that we were using so far gives\n\t // the best result. But we change the way the light moves with the camera so we do not have\n\t // unreal bright spots in right in front of the camera.\n\t\n\t var threeScene = this.threeScene;\n\t\n\t\n\t if (_config.Config.lights === 'Old') {\n\t var light = this.light = new THREE.HemisphereLight(0xffffff, 0x808080, 1);\n\t light.position.set(100, 100, 200);\n\t\n\t threeScene.add(light);\n\t } else {\n\t\n\t if (THREE.REVISION === '73') {\n\t\n\t //if( Config.noHemisphereLight ) {\n\t // threeScene.add( new THREE.HemisphereLight( 0x111111, 0x444444 ) );\n\t //}\n\t\n\t threeScene.add(new THREE.AmbientLight(0xa0a0a0, 0.1));\n\t\n\t var light1 = this.light = new THREE.PointLight(0xffffff, _config.Config.lightPower ? parseFloat(_config.Config.lightPower) : 0.4);\n\t // var light2 = this.light2 = new THREE.PointLight( 0xffffff, 0.1 );\n\t // var light3 = this.light3 = new THREE.PointLight( 0xffffff, 0.1 );\n\t light1.position.set(-1000, 0, 2000);\n\t // light2.position.set( -1000, 100, -2000 );\n\t // light3.position.set( 1000, -100, 2000 );\n\t\n\t var parent = this.camera;\n\t parent.add(light1);\n\t // parent.add(light2);\n\t // parent.add(light3);\n\t } else {\n\t\n\t var ambientLightPower = 0.3,\n\t light1Power = 0.6,\n\t light2Power = 0.3;\n\t if (_config.Config.lightPower) {\n\t var lightPowerF = _config.Config.lightPower.split(',');\n\t ambientLightPower = parseFloat(lightPowerF[0]);\n\t light1Power = parseFloat(lightPowerF[1]);\n\t light2Power = parseFloat(lightPowerF[2]);\n\t }\n\t\n\t var lightAmbient = this.lightAmbient = new THREE.AmbientLight(0xffffff, ambientLightPower);\n\t threeScene.add(lightAmbient);\n\t\n\t var _light = this.light = new THREE.PointLight(0xffffff, light1Power);\n\t var light2 = this.light2 = new THREE.PointLight(0xffffff, light2Power);\n\t //const light3 = this.light3 = new THREE.PointLight( 0xffffff, 0.4 );\n\t _light.position.set(-1000, 0, 1000);\n\t light2.position.set(500, 1000, 1000);\n\t //light3.position.set( 1000, -100, 2000 );\n\t\n\t var _parent = this.camera;\n\t _parent.add(_light);\n\t _parent.add(light2);\n\t //parent.add(light3);\n\t }\n\t }\n\t },\n\t zoomToFit$: function () {\n\t this.zoomToFront();\n\t return (0, _gear.resolve)(this);\n\t },\n\t objectsBBox3D: function () {\n\t return this.object3D.bbox;\n\t },\n\t _zoomToFitCameraDistance: function () {\n\t\n\t var bb = this.objectsBBox3D(),\n\t objectSize = bb.max.y - bb.min.y;\n\t\n\t var width = this.width;\n\t var height = this.height;\n\t var camera = this.camera;\n\t\n\t\n\t var fov = camera.fov * (Math.PI / 180);\n\t\n\t var distance = Math.abs(objectSize / Math.sin(fov / 2)) * 0.6 / this._zoomToScale;\n\t if (width < height) {\n\t distance *= Math.sqrt(height / width);\n\t }\n\t\n\t return distance;\n\t },\n\t _zoomToSide: function (dirX, dirY, dirZ, msTransition) {\n\t var distance = this._zoomToFitCameraDistance();\n\t var pos = new Vector3(dirX, dirY, dirZ).normalize().multiplyScalar(distance);\n\t this._zoomToPos(pos, msTransition);\n\t },\n\t _zoomToPos: function (pos, msTransition) {\n\t this.controls.autoRotate = false;\n\t this.setCameraState({ pos: pos, target: new Vector3(0, 0, 0) }, msTransition);\n\t },\n\t zoomToFront: function (msTransition) {\n\t this._zoomToSide(0.4, 0.2, 1, msTransition);\n\t },\n\t zoomToBack: function (msTransition) {\n\t this._zoomToSide(0.4, 0.2, -1, msTransition);\n\t },\n\t zoomToRight: function (msTransition) {\n\t this._zoomToSide(1, 0.2, 0.4, msTransition);\n\t },\n\t zoomToLeft: function (msTransition) {\n\t this._zoomToSide(-1, 0.2, 0.4, msTransition);\n\t },\n\t rotateCameraRight: function (angle) {\n\t this.rotateModelLeft(angle);\n\t },\n\t rotateCameraLeft: function (angle) {\n\t this.rotateModelRight(angle);\n\t },\n\t rotateCameraDown: function (angle) {\n\t this.rotateModelUp(angle);\n\t },\n\t rotateCameraUp: function (angle) {\n\t this.rotateModelDown(angle);\n\t },\n\t rotateModelRight: function (angle) {\n\t this.controls.rotateLeft((0, _gear.deg2rad)(angle));\n\t this._updateControls();\n\t },\n\t rotateModelLeft: function (angle) {\n\t this.rotateModelRight(-angle);\n\t },\n\t rotateModelDown: function (angle) {\n\t this.controls.rotateUp((0, _gear.deg2rad)(angle));\n\t this._updateControls();\n\t },\n\t rotateModelUp: function (angle) {\n\t this.rotateModelDown(-angle);\n\t },\n\t zoomIn: function (scale) {\n\t this.controls.dollyIn(scale);\n\t this._updateControls();\n\t },\n\t zoomOut: function (scale) {\n\t this.controls.dollyOut(scale);\n\t this._updateControls();\n\t },\n\t _updateControls: function () {\n\t var controls = this.controls;\n\t\n\t controls.autoRotate = false;\n\t controls.update();\n\t },\n\t\n\t\n\t get cameraStateString() {\n\t return (0, _threeUtil.cameraToString)(this.camera, this.controls.target);\n\t },\n\t set cameraStateString(string) {\n\t this.setCameraStateString(string, 1000);\n\t },\n\t\n\t setCameraStateString: function (string) {\n\t var msTransition = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];\n\t\n\t this.setCameraState((0, _threeUtil.cameraStateFromString)(string), msTransition);\n\t },\n\t setCameraState: function (state) {\n\t var msTransition = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];\n\t var camera = this.camera;\n\t var controls = this.controls;\n\t\n\t if (msTransition === 0) {\n\t camera.position.copy(state.pos);\n\t controls.target.copy(state.target);\n\t camera.updateProjectionMatrix();\n\t controls.update();\n\t this.redraw('3D');\n\t } else {\n\t this.cameraAnim = new _threeUtil.CameraAnimation({ camera: camera, controls: controls,\n\t ms: msTransition,\n\t to: state\n\t });\n\t }\n\t },\n\t onOrbitControlChange: function () {\n\t this.redraw('3D');\n\t },\n\t triggerZoomEvents: function () {\n\t var zoom = this.controls.zoom;\n\t\n\t // [TODO] This should be responsability of each plugin, avoid invalidating\n\t // the tools layers if there isn't a tool\n\t\n\t this.redraw('plugins', 'tools');\n\t\n\t this.fireEvent('zoomupdated', this, zoom);\n\t this.fireEvent('change', this);\n\t var textureView = this.textureView;\n\t\n\t textureView.fireEvent('zoomupdated', textureView, zoom);\n\t textureView.fireEvent('change', textureView, zoom);\n\t },\n\t\n\t debouncedTriggerZoomEvents: (0, _lodash.debounce)(function () {\n\t this.triggerZoomEvents();\n\t }, 500),\n\t\n\t onOrbitControlZoomUpdated: function () {\n\t if (this.updateTextureOnZoom) {\n\t this.triggerZoomEvents();\n\t } else {\n\t this.debouncedTriggerZoomEvents();\n\t }\n\t },\n\t\n\t\n\t // This function is triggered once per animation frame\n\t // We are auto rotating and updating the camera animation here\n\t\n\t draw: function () {\n\t\n\t this.object3D.drawTextures();\n\t\n\t var cameraAnim = this.cameraAnim;\n\t var controls = this.controls;\n\t\n\t\n\t if (this.autoRotate || cameraAnim) {\n\t\n\t if (cameraAnim) {\n\t if (!cameraAnim.update()) {\n\t this.cameraAnim = null;\n\t }\n\t }\n\t controls.update();\n\t this.redraw('3D');\n\t }\n\t\n\t if (this.object3D.animate(this.clock.getDelta())) {\n\t this.redraw('3D');\n\t }\n\t\n\t this.callParent();\n\t },\n\t\n\t\n\t // This function is issued every time the 3D scene needs to be updated\n\t // by the Renderer3D plugin\n\t\n\t draw3D: function (renderer) {\n\t var object3D = this.object3D;\n\t var camera = this.camera;\n\t // console.log('draw3D');\n\t // Create a dummy 3D object, so we always have something to show\n\t // It could also serve as a loading animation and simplify the code\n\t\n\t this.setLightPos();\n\t object3D.draw(renderer, camera);\n\t },\n\t\n\t\n\t get controlsEnabled() {\n\t return this.controls.enabled;\n\t },\n\t set controlsEnabled(state) {\n\t var controls = this.controls;\n\t if (state === false && this._controlsPanning) {\n\t controls.onMouseUp();\n\t this._controlsPanning = false;\n\t }\n\t controls.enabled = state;\n\t },\n\t\n\t // [Review]\n\t // You need to pass preserveDrawingBuffer at creation if you want to use this function\n\t image: function () {\n\t return this.canvas('3D').toDataURL(\"image/png\");\n\t },\n\t setLightPos: function () {\n\t\n\t var cameraPos = this.camera.position,\n\t lightOffset = this.lightOffset;\n\t\n\t if (_config.Config.lights === 'Old') {\n\t\n\t var lightPos = this.light.position;\n\t if (lightOffset === 0) {\n\t lightPos.copy(cameraPos);\n\t } else {\n\t var bb = this.objectsBBox3D();\n\t\n\t var bb_max = bb.max,\n\t center = bb.center;\n\t\n\t var b = new Vector3(0, lightOffset, 0);\n\t var c = new Vector3().subVectors(cameraPos, center);\n\t var n = new Vector3().crossVectors(b, c);\n\t var l = new Vector3().addVectors(center, n);\n\t\n\t l.y = bb_max.y;\n\t\n\t lightPos.copy(new Vector3().addVectors(cameraPos, new Vector3().addVectors(cameraPos, l)));\n\t }\n\t }\n\t },\n\t updateSize: function (width, height) {\n\t this._previousZoomToFitDistance = this._zoomToFitCameraDistance();\n\t this.callParent(width, height);\n\t },\n\t\n\t\n\t // Called just before the resize events, after the sizing is done\n\t postResize: function () {\n\t var camera = this.camera;\n\t var controls = this.controls;\n\t var width = this.width;\n\t var height = this.height;\n\t\n\t\n\t this.callParent();\n\t\n\t camera.aspect = width / height;\n\t camera.updateProjectionMatrix();\n\t\n\t // For width less than height aspect ratio, we need to move the camera manually to maintain\n\t // the same position of the object in the 3D view\n\t var newZoomToFitDistance = this._zoomToFitCameraDistance();\n\t camera.position.multiplyScalar(newZoomToFitDistance / this._previousZoomToFitDistance);\n\t camera.updateProjectionMatrix();\n\t\n\t controls.update();\n\t },\n\t fireResizeEvent: function () {\n\t this.textureView.fireResizeEvent();\n\t this.callParent();\n\t },\n\t init: function () {\n\t var config = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];\n\t\n\t\n\t this.clock = new THREE.Clock();\n\t\n\t this.object3D = new _object3d.EmptyObject3D();\n\t\n\t this.callParent(config);\n\t\n\t this.initThreeScene();\n\t },\n\t appendTo: function (domElement, id) {\n\t\n\t this.callParent(domElement, id);\n\t\n\t // Upgrade OrbitConstraint to OrbitControls so that we can pan around with the mouse\n\t var controls = this.controls = new _orbitControls.OrbitControls(this.camera, domElement);\n\t this._controlsPanning = false;\n\t\n\t // Disable panning, orbit looks weirds after using it\n\t (0, _lodash.assign)(controls, {\n\t autoRotate: false,\n\t autoRotateSpeed: 5.0,\n\t enableKeys: false,\n\t enableDamping: true,\n\t dampingFactor: 0.96\n\t });\n\t\n\t controls.addEventListener('change', (0, _lodash.bind)(this.onOrbitControlChange, this));\n\t controls.addEventListener('zoomupdated', (0, _lodash.bind)(this.onOrbitControlZoomUpdated, this));\n\t\n\t return this;\n\t },\n\t\n\t\n\t // [TODO]\n\t\n\t getViewPortTransform: function () {\n\t return new _cdl.Matrix();\n\t }\n\t});\n\t\n\t// We could simplify this by making OrbitControls a plugin\n\t\n\t_view.Plugin.ViewControls3D = _view.Plugin.extend({\n\t\n\t target: 'view',\n\t\n\t initPlugin: function () {\n\t this.panning = false;\n\t },\n\t on_pointerdown: function (_ref) {\n\t var view = _ref.view;\n\t var event = _ref.event;\n\t\n\t this.panning = true;\n\t view.controls.on_pointerdown(event);\n\t },\n\t\n\t\n\t on_pointermove: (0, _view.fastThrottle)(function (_ref2) {\n\t var view = _ref2.view;\n\t var event = _ref2.event;\n\t\n\t if (this.panning) {\n\t view.controls.on_pointermove(event);\n\t }\n\t }, 10),\n\t\n\t on_pointerup: function (_ref3) {\n\t var view = _ref3.view;\n\t var event = _ref3.event;\n\t\n\t if (this.panning) {\n\t this.panning = false;\n\t view.controls.on_pointerup(event);\n\t }\n\t },\n\t on_mousewheel: function (_ref4) {\n\t var view = _ref4.view;\n\t var event = _ref4.event;\n\t\n\t this.panning = false;\n\t view.controls.on_mousewheel(event);\n\t }\n\t});\n\n/***/ },\n\n/***/ 126:\n/***/ function(module, exports) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t\t\tvalue: true\n\t});\n\texports.OrbitConstraint = OrbitConstraint;\n\t/* globals THREE */\n\t\n\t/**\r\n\t* @author qiao / https://github.com/qiao\r\n\t* @author mrdoob / http://mrdoob.com\r\n\t* @author alteredq / http://alteredqualia.com/\r\n\t* @author WestLangley / http://github.com/WestLangley\r\n\t* @author erich666 / http://erichaines.com\r\n\t*/\n\t\n\t// Modified for Grafika\n\t// Expose OrbitConstraint\n\t\n\t\n\tfunction OrbitConstraint(object) {\n\t\n\t\t\tthis.object = object;\n\t\n\t\t\t// \"target\" sets the location of focus, where the object orbits around\n\t\t\t// and where it pans with respect to.\n\t\t\tthis.target = new THREE.Vector3();\n\t\n\t\t\t// Limits to how far you can dolly in and out ( PerspectiveCamera only )\n\t\t\tthis.minDistance = 0;\n\t\t\tthis.maxDistance = Infinity;\n\t\n\t\t\t// Limits to how far you can zoom in and out ( OrthographicCamera only )\n\t\t\tthis.minZoom = 0;\n\t\t\tthis.maxZoom = Infinity;\n\t\n\t\t\t// How far you can orbit vertically, upper and lower limits.\n\t\t\t// Range is 0 to Math.PI radians.\n\t\t\tthis.minPolarAngle = 0; // radians\n\t\t\tthis.maxPolarAngle = Math.PI; // radians\n\t\n\t\t\t// How far you can orbit horizontally, upper and lower limits.\n\t\t\t// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\n\t\t\tthis.minAzimuthAngle = -Infinity; // radians\n\t\t\tthis.maxAzimuthAngle = Infinity; // radians\n\t\n\t\t\t// Set to true to enable damping (inertia)\n\t\t\t// If damping is enabled, you must call controls.update() in your animation loop\n\t\t\tthis.enableDamping = false;\n\t\t\tthis.dampingFactor = 0.25;\n\t\n\t\t\t////////////\n\t\t\t// internals\n\t\n\t\t\tvar scope = this;\n\t\n\t\t\tvar EPS = 0.000001;\n\t\n\t\t\t// Current position in spherical coordinate system.\n\t\t\tvar theta;\n\t\t\tvar phi;\n\t\n\t\t\t// Pending changes\n\t\t\tvar phiDelta = 0;\n\t\t\tvar thetaDelta = 0;\n\t\t\tvar scale = 1;\n\t\t\tthis.scale = scale;\n\t\t\tvar panOffset = new THREE.Vector3();\n\t\t\tthis.zoomChanged = false;\n\t\n\t\t\tObject.defineProperty(this, 'zoom', {\n\t\t\t\t\tget: function () {\n\t\t\t\t\t\t\treturn this.scale;\n\t\t\t\t\t}\n\t\t\t});\n\t\n\t\t\t// API\n\t\n\t\t\tthis.getPolarAngle = function () {\n\t\n\t\t\t\t\treturn phi;\n\t\t\t};\n\t\n\t\t\tthis.getAzimuthalAngle = function () {\n\t\n\t\t\t\t\treturn theta;\n\t\t\t};\n\t\n\t\t\tthis.panToCenter = function (angle) {\n\t\t\t\t\t// Pan to center, it looks very strange to rotate the model when the view is not centered\n\t\t\t\t\tvar target = this.target;\n\t\t\t\t\tvar targetLengthSq = target.lengthSq();\n\t\t\t\t\tif (targetLengthSq > 0) {\n\t\t\t\t\t\t\tif (targetLengthSq < 5) {\n\t\t\t\t\t\t\t\t\ttarget.copy(new THREE.Vector3(0, 0, 0));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ttarget.copy(target.clone().multiplyScalar(9.5 / 10 * (1 - Math.abs(angle) / (2 * Math.PI))));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t};\n\t\n\t\t\tthis.rotateLeft = function (angle) {\n\t\n\t\t\t\t\tthetaDelta -= angle;\n\t\n\t\t\t\t\tthis.panToCenter(angle);\n\t\t\t};\n\t\n\t\t\tthis.rotateUp = function (angle) {\n\t\n\t\t\t\t\tphiDelta -= angle;\n\t\n\t\t\t\t\tthis.panToCenter(angle);\n\t\t\t};\n\t\n\t\t\t// pass in distance in world space to move left\n\t\t\tthis.panLeft = function () {\n\t\n\t\t\t\t\tvar v = new THREE.Vector3();\n\t\n\t\t\t\t\treturn function panLeft(distance) {\n\t\n\t\t\t\t\t\t\tvar te = this.object.matrix.elements;\n\t\n\t\t\t\t\t\t\t// get X column of matrix\n\t\t\t\t\t\t\tv.set(te[0], te[1], te[2]);\n\t\t\t\t\t\t\tv.multiplyScalar(-distance);\n\t\n\t\t\t\t\t\t\tpanOffset.add(v);\n\t\t\t\t\t};\n\t\t\t}();\n\t\n\t\t\t// pass in distance in world space to move up\n\t\t\tthis.panUp = function () {\n\t\n\t\t\t\t\tvar v = new THREE.Vector3();\n\t\n\t\t\t\t\treturn function panUp(distance) {\n\t\n\t\t\t\t\t\t\tvar te = this.object.matrix.elements;\n\t\n\t\t\t\t\t\t\t// get Y column of matrix\n\t\t\t\t\t\t\tv.set(te[4], te[5], te[6]);\n\t\t\t\t\t\t\tv.multiplyScalar(distance);\n\t\n\t\t\t\t\t\t\tpanOffset.add(v);\n\t\t\t\t\t};\n\t\t\t}();\n\t\n\t\t\t// pass in x,y of change desired in pixel space,\n\t\t\t// right and down are positive\n\t\t\tthis.pan = function (deltaX, deltaY, screenWidth, screenHeight) {\n\t\n\t\t\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\n\t\t\t\t\t\t\t// perspective\n\t\t\t\t\t\t\tvar position = scope.object.position;\n\t\t\t\t\t\t\tvar offset = position.clone().sub(scope.target);\n\t\t\t\t\t\t\tvar targetDistance = offset.length();\n\t\n\t\t\t\t\t\t\t// half of the fov is center to top of screen\n\t\t\t\t\t\t\ttargetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180.0);\n\t\n\t\t\t\t\t\t\t// we actually don't use screenWidth, since perspective camera is fixed to screen height\n\t\t\t\t\t\t\tscope.panLeft(2 * deltaX * targetDistance / screenHeight);\n\t\t\t\t\t\t\tscope.panUp(2 * deltaY * targetDistance / screenHeight);\n\t\t\t\t\t} else if (scope.object instanceof THREE.OrthographicCamera) {\n\t\n\t\t\t\t\t\t\t// orthographic\n\t\t\t\t\t\t\tscope.panLeft(deltaX * (scope.object.right - scope.object.left) / screenWidth);\n\t\t\t\t\t\t\tscope.panUp(deltaY * (scope.object.top - scope.object.bottom) / screenHeight);\n\t\t\t\t\t} else {\n\t\n\t\t\t\t\t\t\t// camera neither orthographic or perspective\n\t\t\t\t\t\t\tconsole.warn('WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.');\n\t\t\t\t\t}\n\t\t\t};\n\t\n\t\t\tthis.dollyIn = function (dollyScale) {\n\t\n\t\t\t\t\tthis.zoomChanged = true;\n\t\n\t\t\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\n\t\t\t\t\t\t\tscale /= dollyScale;\n\t\t\t\t\t\t\tthis.scale /= dollyScale;\n\t\t\t\t\t} else if (scope.object instanceof THREE.OrthographicCamera) {\n\t\n\t\t\t\t\t\t\tscope.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom * dollyScale));\n\t\t\t\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\t\t} else {\n\t\n\t\t\t\t\t\t\tconsole.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');\n\t\t\t\t\t}\n\t\t\t};\n\t\n\t\t\tthis.dollyOut = function (dollyScale) {\n\t\n\t\t\t\t\tthis.zoomChanged = true;\n\t\n\t\t\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\n\t\t\t\t\t\t\tscale *= dollyScale;\n\t\t\t\t\t\t\tthis.scale *= dollyScale;\n\t\t\t\t\t} else if (scope.object instanceof THREE.OrthographicCamera) {\n\t\n\t\t\t\t\t\t\tscope.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / dollyScale));\n\t\t\t\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\t\t} else {\n\t\n\t\t\t\t\t\t\tconsole.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');\n\t\t\t\t\t}\n\t\t\t};\n\t\n\t\t\tthis.update = function () {\n\t\n\t\t\t\t\tvar offset = new THREE.Vector3();\n\t\n\t\t\t\t\t// so camera.up is the orbit axis\n\t\t\t\t\tvar quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));\n\t\t\t\t\tvar quatInverse = quat.clone().inverse();\n\t\n\t\t\t\t\tvar lastPosition = new THREE.Vector3();\n\t\t\t\t\tvar lastQuaternion = new THREE.Quaternion();\n\t\n\t\t\t\t\treturn function () {\n\t\n\t\t\t\t\t\t\tvar position = this.object.position;\n\t\n\t\t\t\t\t\t\toffset.copy(position).sub(this.target);\n\t\n\t\t\t\t\t\t\t// rotate offset to \"y-axis-is-up\" space\n\t\t\t\t\t\t\toffset.applyQuaternion(quat);\n\t\n\t\t\t\t\t\t\t// angle from z-axis around y-axis\n\t\n\t\t\t\t\t\t\ttheta = Math.atan2(offset.x, offset.z);\n\t\n\t\t\t\t\t\t\t// angle from y-axis\n\t\n\t\t\t\t\t\t\tphi = Math.atan2(Math.sqrt(offset.x * offset.x + offset.z * offset.z), offset.y);\n\t\n\t\t\t\t\t\t\ttheta += thetaDelta;\n\t\t\t\t\t\t\tphi += phiDelta;\n\t\n\t\t\t\t\t\t\t// restrict theta to be between desired limits\n\t\t\t\t\t\t\ttheta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, theta));\n\t\n\t\t\t\t\t\t\t// restrict phi to be between desired limits\n\t\t\t\t\t\t\tphi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, phi));\n\t\n\t\t\t\t\t\t\t// restrict phi to be betwee EPS and PI-EPS\n\t\t\t\t\t\t\tphi = Math.max(EPS, Math.min(Math.PI - EPS, phi));\n\t\n\t\t\t\t\t\t\tvar radius = offset.length() * scale;\n\t\n\t\t\t\t\t\t\t// restrict radius to be between desired limits\n\t\t\t\t\t\t\tradius = Math.max(this.minDistance, Math.min(this.maxDistance, radius));\n\t\n\t\t\t\t\t\t\t// move target to panned location\n\t\t\t\t\t\t\tthis.target.add(panOffset);\n\t\n\t\t\t\t\t\t\toffset.x = radius * Math.sin(phi) * Math.sin(theta);\n\t\t\t\t\t\t\toffset.y = radius * Math.cos(phi);\n\t\t\t\t\t\t\toffset.z = radius * Math.sin(phi) * Math.cos(theta);\n\t\n\t\t\t\t\t\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\t\t\t\t\t\toffset.applyQuaternion(quatInverse);\n\t\n\t\t\t\t\t\t\tposition.copy(this.target).add(offset);\n\t\n\t\t\t\t\t\t\tthis.object.lookAt(this.target);\n\t\n\t\t\t\t\t\t\tif (this.enableDamping === true) {\n\t\n\t\t\t\t\t\t\t\t\tthetaDelta *= 1 - this.dampingFactor;\n\t\t\t\t\t\t\t\t\tphiDelta *= 1 - this.dampingFactor;\n\t\t\t\t\t\t\t} else {\n\t\n\t\t\t\t\t\t\t\t\tthetaDelta = 0;\n\t\t\t\t\t\t\t\t\tphiDelta = 0;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\tscale = 1;\n\t\t\t\t\t\t\tpanOffset.set(0, 0, 0);\n\t\n\t\t\t\t\t\t\t// update condition is:\n\t\t\t\t\t\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\n\t\t\t\t\t\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\t\n\t\t\t\t\t\t\tif (this.zoomChanged || lastPosition.distanceToSquared(this.object.position) > EPS || 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS) {\n\t\n\t\t\t\t\t\t\t\t\tlastPosition.copy(this.object.position);\n\t\t\t\t\t\t\t\t\tlastQuaternion.copy(this.object.quaternion);\n\t\t\t\t\t\t\t\t\tthis.zoomChanged = false;\n\t\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t};\n\t\t\t}();\n\t}\n\t\n\t// This set of controls performs orbiting, dollying (zooming), and panning. It maintains\n\t// the \"up\" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is\n\t// supported.\n\t//\n\t// Orbit - left mouse / touch: one finger move\n\t// Zoom - middle mouse, or mousewheel / touch: two finger spread or squish\n\t// Pan - right mouse, or arrow keys / touch: three finter swipe\n\t\n\tvar OrbitControls = exports.OrbitControls = function (object, domElement) {\n\t\n\t\t\tvar constraint = new OrbitConstraint(object);\n\t\n\t\t\tthis.domElement = domElement !== undefined ? domElement : document;\n\t\n\t\t\t// API\n\t\n\t\t\tObject.defineProperty(this, 'constraint', {\n\t\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn constraint;\n\t\t\t\t\t}\n\t\n\t\t\t});\n\t\n\t\t\tthis.getPolarAngle = function () {\n\t\n\t\t\t\t\treturn constraint.getPolarAngle();\n\t\t\t};\n\t\n\t\t\tthis.getAzimuthalAngle = function () {\n\t\n\t\t\t\t\treturn constraint.getAzimuthalAngle();\n\t\t\t};\n\t\n\t\t\t// [Grafika]\n\t\n\t\t\tthis.panToCenter = function (angle) {\n\t\t\t\t\treturn constraint.panToCenter(angle);\n\t\t\t};\n\t\n\t\t\tthis.rotateLeft = function (angle) {\n\t\t\t\t\treturn constraint.rotateLeft(angle);\n\t\t\t};\n\t\n\t\t\tthis.rotateUp = function (angle) {\n\t\t\t\t\treturn constraint.rotateUp(angle);\n\t\t\t};\n\t\n\t\t\tthis.panLeft = function (distance) {\n\t\t\t\t\treturn constraint.panLeft(distance);\n\t\t\t};\n\t\n\t\t\tthis.panUp = function (distance) {\n\t\t\t\t\treturn constraint.panUp(distance);\n\t\t\t};\n\t\n\t\t\tthis.dollyIn = function (dollyScale) {\n\t\t\t\t\treturn constraint.dollyIn(dollyScale);\n\t\t\t};\n\t\n\t\t\tthis.dollyOut = function (dollyScale) {\n\t\t\t\t\treturn constraint.dollyOut(dollyScale);\n\t\t\t};\n\t\n\t\t\t// Set to false to disable this control\n\t\t\tthis.enabled = true;\n\t\n\t\t\t// center is old, deprecated; use \"target\" instead\n\t\t\tthis.center = this.target;\n\t\n\t\t\t// This option actually enables dollying in and out; left as \"zoom\" for\n\t\t\t// backwards compatibility.\n\t\t\t// Set to false to disable zooming\n\t\t\tthis.enableZoom = true;\n\t\t\tthis.zoomSpeed = 1.0;\n\t\n\t\t\t// Set to false to disable rotating\n\t\t\tthis.enableRotate = true;\n\t\t\tthis.rotateSpeed = 1.0;\n\t\n\t\t\t// Set to false to disable panning\n\t\t\tthis.enablePan = true;\n\t\t\tthis.keyPanSpeed = 7.0; // pixels moved per arrow key push\n\t\n\t\t\t// Set to true to automatically rotate around the target\n\t\t\t// If auto-rotate is enabled, you must call controls.update() in your animation loop\n\t\t\tthis.autoRotate = false;\n\t\t\tthis.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\n\t\n\t\t\t// Set to false to disable use of the keys\n\t\t\tthis.enableKeys = true;\n\t\n\t\t\t// The four arrow keys\n\t\t\tthis.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\n\t\n\t\t\t// Mouse buttons\n\t\t\tthis.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };\n\t\n\t\t\t////////////\n\t\t\t// internals\n\t\n\t\t\tvar scope = this;\n\t\n\t\t\tvar rotateStart = new THREE.Vector2();\n\t\t\tvar rotateEnd = new THREE.Vector2();\n\t\t\tvar rotateDelta = new THREE.Vector2();\n\t\n\t\t\tvar panStart = new THREE.Vector2();\n\t\t\tvar panEnd = new THREE.Vector2();\n\t\t\tvar panDelta = new THREE.Vector2();\n\t\n\t\t\tvar dollyStart = new THREE.Vector2();\n\t\t\tvar dollyEnd = new THREE.Vector2();\n\t\t\tvar dollyDelta = new THREE.Vector2();\n\t\n\t\t\tvar STATE = {\n\t\t\t\t\tNONE: -1,\n\t\t\t\t\tROTATE: 0,\n\t\t\t\t\tDOLLY: 1,\n\t\t\t\t\tPAN: 2,\n\t\t\t\t\tTOUCH_ROTATE: 3,\n\t\t\t\t\tTOUCH_DOLLY: 4,\n\t\t\t\t\tTOUCH_PAN: 5\n\t\t\t};\n\t\n\t\t\tvar state = STATE.NONE;\n\t\n\t\t\t// for reset\n\t\n\t\t\tthis.target0 = this.target.clone();\n\t\t\tthis.position0 = this.object.position.clone();\n\t\t\tthis.zoom0 = this.object.zoom;\n\t\n\t\t\t// events\n\t\n\t\t\tvar zoomUpdatedEvent = { type: 'zoomupdated' };\n\t\t\tvar changeEvent = { type: 'change' };\n\t\t\tvar startEvent = { type: 'start' };\n\t\t\tvar endEvent = { type: 'end' };\n\t\n\t\t\t// pass in x,y of change desired in pixel space,\n\t\t\t// right and down are positive\n\t\t\tfunction pan(deltaX, deltaY) {\n\t\n\t\t\t\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\n\t\t\t\t\tconstraint.pan(deltaX, deltaY, element.clientWidth, element.clientHeight);\n\t\t\t}\n\t\n\t\t\tthis.update = function () {\n\t\n\t\t\t\t\tif (this.autoRotate && state === STATE.NONE) {\n\t\n\t\t\t\t\t\t\tconstraint.rotateLeft(getAutoRotationAngle());\n\t\t\t\t\t}\n\t\n\t\t\t\t\tvar zoomChanged = constraint.zoomChanged;\n\t\n\t\n\t\t\t\t\tif (constraint.update() === true) {\n\t\n\t\t\t\t\t\t\tif (zoomChanged) {\n\t\t\t\t\t\t\t\t\tthis.dispatchEvent(zoomUpdatedEvent);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis.dispatchEvent(changeEvent);\n\t\t\t\t\t}\n\t\t\t};\n\t\n\t\t\tthis.reset = function () {\n\t\n\t\t\t\t\tstate = STATE.NONE;\n\t\n\t\t\t\t\tthis.target.copy(this.target0);\n\t\t\t\t\tthis.object.position.copy(this.position0);\n\t\t\t\t\tthis.object.zoom = this.zoom0;\n\t\n\t\t\t\t\tthis.object.updateProjectionMatrix();\n\t\t\t\t\tthis.dispatchEvent(changeEvent);\n\t\t\t\t\tthis.dispatchEvent(zoomUpdatedEvent);\n\t\n\t\t\t\t\tthis.update();\n\t\t\t};\n\t\n\t\t\tfunction getAutoRotationAngle() {\n\t\n\t\t\t\t\treturn 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n\t\t\t}\n\t\n\t\t\tfunction getZoomScale() {\n\t\n\t\t\t\t\treturn Math.pow(0.95, scope.zoomSpeed);\n\t\t\t}\n\t\n\t\t\t// [grafika]\n\t\t\t/*\r\n\t function onDblClick( event ) {\r\n\t event.preventDefault();\r\n\t scope.autoRotate = ! scope.autoRotate;\r\n\t }\r\n\t */\n\t\n\t\t\tfunction handleTouchStartDolly(event) {\n\t\n\t\t\t\t\t//console.log( 'handleTouchStartDolly' );\n\t\n\t\t\t\t\tvar distance = event.pointers[1].current.minus(event.pointers[0].current).norm();\n\t\n\t\t\t\t\tdollyStart.set(0, distance);\n\t\t\t}\n\t\n\t\t\tfunction handleTouchMoveDolly(event) {\n\t\n\t\t\t\t\t//console.log( 'handleTouchMoveDolly' );\n\t\n\t\t\t\t\tvar distance = event.pointers[1].current.minus(event.pointers[0].current).norm();\n\t\n\t\t\t\t\tdollyEnd.set(0, distance);\n\t\n\t\t\t\t\tdollyDelta.subVectors(dollyEnd, dollyStart);\n\t\n\t\t\t\t\tif (dollyDelta.y > 0) {\n\t\n\t\t\t\t\t\t\tconstraint.dollyOut(getZoomScale());\n\t\t\t\t\t} else if (dollyDelta.y < 0) {\n\t\n\t\t\t\t\t\t\tconstraint.dollyIn(getZoomScale());\n\t\t\t\t\t}\n\t\n\t\t\t\t\tdollyStart.copy(dollyEnd);\n\t\n\t\t\t\t\tscope.update();\n\t\t\t}\n\t\n\t\t\tthis.isIddle = function () {\n\t\t\t\t\treturn state === STATE.NONE;\n\t\t\t};\n\t\n\t\t\t// [grafika]\n\t\t\tthis.on_pointerdown = function (_ref) {\n\t\t\t\t\tvar event = _ref.event;\n\t\t\t\t\tvar pointers = _ref.pointers;\n\t\n\t\n\t\t\t\t\tif (pointers.length === 2) {\n\t\n\t\t\t\t\t\t\tif (scope.enableZoom) {\n\t\t\t\t\t\t\t\t\thandleTouchStartDolly(event);\n\t\t\t\t\t\t\t\t\tstate = STATE.TOUCH_DOLLY;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\n\t\t\t\t\tif (scope.enabled === false) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\n\t\t\t\t\t// [grafika]\n\t\t\t\t\tscope.autoRotate = false;\n\t\n\t\t\t\t\t// [grafika]\n\t\t\t\t\t// event.preventDefault();\n\t\n\t\t\t\t\tif (event.button === scope.mouseButtons.ORBIT) {\n\t\n\t\t\t\t\t\t\tif (scope.enableRotate === false) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\tstate = STATE.ROTATE;\n\t\n\t\t\t\t\t\t\trotateStart.set(event.clientX, event.clientY);\n\t\t\t\t\t} else if (event.button === scope.mouseButtons.ZOOM) {\n\t\n\t\t\t\t\t\t\tif (scope.enableZoom === false) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\tstate = STATE.DOLLY;\n\t\n\t\t\t\t\t\t\tdollyStart.set(event.clientX, event.clientY);\n\t\t\t\t\t} else if (event.button === scope.mouseButtons.PAN) {\n\t\n\t\t\t\t\t\t\tif (scope.enablePan === false) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\tstate = STATE.PAN;\n\t\n\t\t\t\t\t\t\tpanStart.set(event.clientX, event.clientY);\n\t\t\t\t\t}\n\t\n\t\t\t\t\tif (state !== STATE.NONE) {\n\t\n\t\t\t\t\t\t\t// [grafika]\n\t\t\t\t\t\t\t// document.addEventListener( 'mousemove', onMouseMove, false );\n\t\t\t\t\t\t\t// document.addEventListener( 'mouseup', onMouseUp, false );\n\t\t\t\t\t\t\tscope.dispatchEvent(startEvent);\n\t\t\t\t\t}\n\t\t\t};\n\t\n\t\t\t// [grafika]\n\t\t\tthis.on_pointermove = function (event) {\n\t\n\t\t\t\t\tif (state === STATE.TOUCH_DOLLY && event.pointers.length !== 2) {\n\t\t\t\t\t\t\tstate = STATE.NONE;\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\n\t\t\t\t\tif (scope.enabled === false) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\n\t\t\t\t\t// [grafika]\n\t\t\t\t\t// event.preventDefault();\n\t\n\t\t\t\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\n\t\t\t\t\tif (state === STATE.TOUCH_DOLLY) {\n\t\n\t\t\t\t\t\t\tif (scope.enableZoom === false) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\tevent.view.optimizeZoomPreview();\n\t\n\t\t\t\t\t\t\thandleTouchMoveDolly(event);\n\t\t\t\t\t} else if (state === STATE.ROTATE) {\n\t\n\t\t\t\t\t\t\tif (scope.enableRotate === false) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\trotateEnd.set(event.clientX, event.clientY);\n\t\t\t\t\t\t\trotateDelta.subVectors(rotateEnd, rotateStart);\n\t\n\t\t\t\t\t\t\t// rotating across whole screen goes 360 degrees around\n\t\t\t\t\t\t\tconstraint.rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);\n\t\n\t\t\t\t\t\t\t// rotating up and down along whole screen attempts to go 360, but limited to 180\n\t\t\t\t\t\t\tconstraint.rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);\n\t\n\t\t\t\t\t\t\trotateStart.copy(rotateEnd);\n\t\t\t\t\t} else if (state === STATE.DOLLY) {\n\t\n\t\t\t\t\t\t\tif (scope.enableZoom === false) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\tevent.view.optimizeZoomPreview();\n\t\n\t\t\t\t\t\t\tdollyEnd.set(event.clientX, event.clientY);\n\t\t\t\t\t\t\tdollyDelta.subVectors(dollyEnd, dollyStart);\n\t\n\t\t\t\t\t\t\tif (dollyDelta.y > 0) {\n\t\n\t\t\t\t\t\t\t\t\tconstraint.dollyIn(getZoomScale());\n\t\t\t\t\t\t\t} else if (dollyDelta.y < 0) {\n\t\n\t\t\t\t\t\t\t\t\tconstraint.dollyOut(getZoomScale());\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\tdollyStart.copy(dollyEnd);\n\t\t\t\t\t} else if (state === STATE.PAN) {\n\t\n\t\t\t\t\t\t\tif (scope.enablePan === false) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\tpanEnd.set(event.clientX, event.clientY);\n\t\t\t\t\t\t\tpanDelta.subVectors(panEnd, panStart);\n\t\n\t\t\t\t\t\t\tpan(panDelta.x, panDelta.y);\n\t\n\t\t\t\t\t\t\tpanStart.copy(panEnd);\n\t\t\t\t\t}\n\t\n\t\t\t\t\tif (state !== STATE.NONE) {\n\t\t\t\t\t\t\tscope.update();\n\t\t\t\t\t}\n\t\t\t};\n\t\n\t\t\t// [grafika]\n\t\t\tthis.on_pointerup = function () /* event */{\n\t\n\t\t\t\t\tif (scope.enabled === false) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\n\t\t\t\t\t// [grafika]\n\t\t\t\t\t// document.removeEventListener( 'mousemove', onMouseMove, false );\n\t\t\t\t\t// document.removeEventListener( 'mouseup', onMouseUp, false );\n\t\t\t\t\tif (state !== STATE.NONE) {\n\t\t\t\t\t\t\tscope.dispatchEvent(endEvent);\n\t\t\t\t\t\t\tstate = STATE.NONE;\n\t\t\t\t\t}\n\t\t\t};\n\t\n\t\t\tthis.on_mousewheel = function (event) {\n\t\n\t\t\t\t\tif (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\n\t\t\t\t\tevent.view.optimizeZoomPreview();\n\t\n\t\t\t\t\tvar delta = 0;\n\t\n\t\t\t\t\tif (event.wheelDelta !== undefined) {\n\t\n\t\t\t\t\t\t\t// WebKit / Opera / Explorer 9\n\t\n\t\t\t\t\t\t\tdelta = event.wheelDelta;\n\t\t\t\t\t} else if (event.detail !== undefined) {\n\t\n\t\t\t\t\t\t\t// Firefox\n\t\n\t\t\t\t\t\t\tdelta = -event.detail;\n\t\t\t\t\t}\n\t\n\t\t\t\t\tif (delta > 0) {\n\t\n\t\t\t\t\t\t\tconstraint.dollyOut(getZoomScale());\n\t\t\t\t\t} else if (delta < 0) {\n\t\n\t\t\t\t\t\t\tconstraint.dollyIn(getZoomScale());\n\t\t\t\t\t}\n\t\n\t\t\t\t\tscope.update();\n\t\t\t\t\tscope.dispatchEvent(startEvent);\n\t\t\t\t\tscope.dispatchEvent(endEvent);\n\t\t\t};\n\t\n\t\t\t// [grafika] Use our own input system\n\t\n\t\t\tthis.dispose = function () {};\n\t\n\t\t\t// [grafika]\n\t\n\t\t\t// force an update at start\n\t\t\tthis.update();\n\t};\n\t\n\tOrbitControls.prototype = Object.create(THREE.EventDispatcher.prototype);\n\tOrbitControls.prototype.constructor = OrbitControls;\n\t\n\tObject.defineProperties(OrbitControls.prototype, {\n\t\n\t\t\tobject: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.object;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\ttarget: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.target;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tconsole.warn('OrbitControls: target is now immutable. Use target.set() instead.');\n\t\t\t\t\t\t\tthis.constraint.target.copy(value);\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tzoom: {\n\t\t\t\t\tget: function () {\n\t\t\t\t\t\t\treturn this.constraint.zoom;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tminDistance: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.minDistance;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.minDistance = value;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tmaxDistance: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.maxDistance;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.maxDistance = value;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tminZoom: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.minZoom;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.minZoom = value;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tmaxZoom: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.maxZoom;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.maxZoom = value;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tminPolarAngle: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.minPolarAngle;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.minPolarAngle = value;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tmaxPolarAngle: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.maxPolarAngle;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.maxPolarAngle = value;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tminAzimuthAngle: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.minAzimuthAngle;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.minAzimuthAngle = value;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tmaxAzimuthAngle: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.maxAzimuthAngle;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.maxAzimuthAngle = value;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tenableDamping: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.enableDamping;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.enableDamping = value;\n\t\t\t\t\t}\n\t\t\t},\n\t\n\t\t\tdampingFactor: {\n\t\t\t\t\tget: function () {\n\t\n\t\t\t\t\t\t\treturn this.constraint.dampingFactor;\n\t\t\t\t\t},\n\t\t\t\t\tset: function (value) {\n\t\n\t\t\t\t\t\t\tthis.constraint.dampingFactor = value;\n\t\t\t\t\t}\n\t\t\t}\n\t\n\t});\n\n/***/ },\n\n/***/ 127:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.CameraAnimation = undefined;\n\texports.setObjectPosition = setObjectPosition;\n\texports.vector3ToString = vector3ToString;\n\texports.vector3FromString = vector3FromString;\n\texports.rotationToString = rotationToString;\n\texports.cameraToString = cameraToString;\n\texports.cameraStateFromString = cameraStateFromString;\n\texports.processGeometry = processGeometry;\n\texports.parseGeometry = parseGeometry;\n\texports.uvFromViewPoint = uvFromViewPoint;\n\t\n\tvar _config = __webpack_require__(2);\n\t\n\tvar _lodash = __webpack_require__(4);\n\t\n\tvar _cdl = __webpack_require__(15);\n\t\n\tvar _THREE = THREE; /* globals THREE */\n\t\n\tvar Vector3 = _THREE.Vector3;\n\t\n\t\n\tvar _parseFloat = parseFloat;\n\t\n\tfunction setObjectPosition(object, bbCenter) {\n\t object.position.set(-bbCenter.x, -bbCenter.y, -bbCenter.z);\n\t object.matrixWorldNeedsUpdate = true;\n\t}\n\t\n\tfunction n2s(n) {\n\t return n.toFixed(4);\n\t}\n\t\n\tfunction vector3ToString(v) {\n\t return n2s(v.x) + ' ' + n2s(v.y) + ' ' + n2s(v.z);\n\t}\n\t\n\tfunction vector3FromString(string) {\n\t var s = string.split(' ');\n\t return new Vector3(_parseFloat(s[0]), _parseFloat(s[1]), _parseFloat(s[2]));\n\t}\n\t\n\tfunction rotationToString(v) {\n\t return n2s(v.x) + ' ' + n2s(v.y) + ' ' + n2s(v.z) + ' ' + v.order;\n\t}\n\t\n\tfunction cameraToString(camera, target) {\n\t return vector3ToString(camera.position) + ',' + rotationToString(camera.rotation) + ',' + vector3ToString(target);\n\t}\n\t\n\tfunction cameraStateFromString(string) {\n\t var parts = string.split(',');\n\t return {\n\t pos: vector3FromString(parts[0]),\n\t target: vector3FromString(parts[2])\n\t };\n\t}\n\t\n\tfunction properFaceNormal(face) {\n\t if (face) {\n\t var face_normal = face.normal;\n\t if (face_normal && face_normal.lengthSq() === 0) {\n\t return false;\n\t }\n\t }\n\t return true;\n\t}\n\t\n\tfunction properVertexNormal(face) {\n\t if (face) {\n\t var vertexNormal = face.vertexNormals[0];\n\t if (vertexNormal && vertexNormal.lengthSq() === 0) {\n\t return false;\n\t }\n\t }\n\t return true;\n\t}\n\t\n\tfunction processGeometry(geometry /*,divisions*/) {\n\t\n\t var smooth = geometry; // Clone THREE.GeometryUtils.clone( geometry );\n\t\n\t // Next, we need to merge vertices to clean up any unwanted vertex.\n\t // smooth.mergeVertices();\n\t\n\t if (!_config.Config.useBufferGeometry) {\n\t\n\t var face0 = smooth.faces[0],\n\t face1 = smooth.faces[1];\n\t\n\t var computeFaceNormals = _config.Config.computeFaceNormals;\n\t if (computeFaceNormals === 'Forced' || computeFaceNormals === 'Auto' && (!properFaceNormal(face0) || !properFaceNormal(face1))) {\n\t\n\t console.log(\"Computing face normals...\");\n\t smooth.computeFaceNormals();\n\t }\n\t\n\t var computeVertexNormals = _config.Config.computeVertexNormals;\n\t if (computeVertexNormals === 'Forced' || computeVertexNormals === 'Auto' && (!properVertexNormal(face0) || !properVertexNormal(face1))) {\n\t console.log(\"Computing vertex normals...\");\n\t smooth.computeVertexNormals();\n\t }\n\t\n\t /*\r\n\t if( divisions > 0 ) {\r\n\t // Create a new instance of the modifier and pass the number of divisions.\r\n\t const modifier = new THREE.SubdivisionModifier(divisions);\r\n\t // Apply the modifier to our cloned geometry.\r\n\t modifier.modify( smooth );\r\n\t smooth.uvsNeedsUpdate = true;\r\n\t }\r\n\t */\n\t }\n\t\n\t return smooth;\n\t}\n\t\n\tvar CameraAnimation = exports.CameraAnimation = function (config) {\n\t (0, _lodash.assign)(this, config);\n\t (0, _lodash.assign)(this, {\n\t start: (0, _lodash.now)(),\n\t from: {\n\t pos: config.camera.position.clone(),\n\t target: config.controls.target.clone()\n\t }\n\t });\n\t this.finished = false;\n\t};\n\tCameraAnimation.prototype = {\n\t update: function () {\n\t\n\t if (this.finished) {\n\t return false;\n\t }\n\t var controls = this.controls;\n\t var camera = this.camera;\n\t var to = this.to;\n\t var from = this.from;\n\t var start = this.start;\n\t var ms = this.ms;\n\t\n\t\n\t var t = (0, _lodash.now)(),\n\t ellapsed = t - start,\n\t to_pos = to.pos,\n\t from_pos = from.pos,\n\t to_target = to.target,\n\t from_target = from.target;\n\t\n\t if (ellapsed >= ms) {\n\t\n\t camera.position.copy(to_pos);\n\t controls.target.copy(to_target);\n\t controls.update();\n\t this.finished = true;\n\t\n\t return false;\n\t } else {\n\t\n\t var current = ellapsed / ms,\n\t\n\t\n\t // The next target is a direct interpolation between from and to targets\n\t\n\t nextTarget = to.target.clone().sub(from_target).multiplyScalar(current).add(from_target),\n\t\n\t\n\t // The nextPos y is a direct interpolation, x and z moves in an circle around the model\n\t\n\t from_xz = new _cdl.Point(from_pos.x - from_target.x, from_pos.z - from_target.z),\n\t to_xz = new _cdl.Point(to_pos.x - to_target.x, to_pos.z - to_target.z),\n\t theta_from = from_xz.angle_rad(),\n\t theta_delta = _cdl.Point.turnAngle_rad(from_xz, to_xz),\n\t theta = theta_from + current * theta_delta,\n\t from_radius = from_xz.norm(),\n\t to_radius = to_xz.norm(),\n\t radius = (to_radius - from_radius) * current + from_radius,\n\t nextPos = new Vector3(radius * Math.cos(theta), 0, radius * Math.sin(theta)).add(nextTarget);\n\t\n\t nextPos.y = (to_pos.y - from_pos.y) * current + from_pos.y;\n\t\n\t camera.position.copy(nextPos);\n\t controls.target.copy(nextTarget);\n\t controls.update();\n\t }\n\t return true;\n\t }\n\t};\n\t\n\tfunction parseGeometry(json) {\n\t\n\t var loader = new THREE.JSONLoader();\n\t\n\t var originalGeometry = loader.parse(json).geometry;\n\t\n\t if (!_config.Config.useBufferGeometry && originalGeometry) {\n\t if (originalGeometry instanceof THREE.BufferGeometry) {\n\t originalGeometry = new THREE.Geometry().fromBufferGeometry(originalGeometry);\n\t }\n\t }\n\t\n\t var smooth3D = _config.Config.smooth3D;\n\t return processGeometry(originalGeometry, smooth3D ? parseInt(smooth3D) : 0);\n\t}\n\t\n\tfunction uvFromViewPoint(object, camera, viewPoint, width, height) {\n\t\n\t camera.updateMatrixWorld();\n\t camera.updateProjectionMatrix();\n\t\n\t var vector = new Vector3(viewPoint.x / width * 2 - 1, -(viewPoint.y / height) * 2 + 1, 0.5);\n\t\n\t vector.unproject(camera);\n\t\n\t var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());\n\t\n\t var intersects = raycaster.intersectObject(object, true);\n\t\n\t if (intersects.length > 0) {\n\t\n\t var uv = intersects[0].uv;\n\t return uv ? new _cdl.Point(uv.x, uv.y) : null;\n\t }\n\t return null;\n\t}\n\n/***/ },\n\n/***/ 128:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.Object3D = exports.EmptyObject3D = exports.Object3DBase = undefined;\n\t\n\tvar _config = __webpack_require__(2);\n\t\n\tvar _lodash = __webpack_require__(4);\n\t\n\tvar _gear = __webpack_require__(8);\n\t\n\tvar _threeUtil = __webpack_require__(127);\n\t\n\t/* globals THREE */\n\t\n\tfunction setMaterialTexture(material, textureType, textureMap, texture) {\n\t\n\t material[textureType + 'Map'] = texture;\n\t\n\t if (texture) {\n\t\n\t var scale = textureMap ? textureMap.scale : 1;\n\t var wrap = textureMap ? textureMap.wrap : 'Stretch';\n\t var repeat = textureMap && wrap !== 'Stretch' ? textureMap.repeat : 1;\n\t\n\t material[textureType + 'Scale'] = textureType === 'normal' ? new THREE.Vector2(scale, scale) : scale;\n\t\n\t texture.wrapS = texture.wrapT = repeat > 1 ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;\n\t texture.repeat.set(repeat, repeat);\n\t texture.minFilter = repeat > 1 ? THREE.NearestMipMapLinearFilter : THREE.LinearMipMapLinearFilter;\n\t\n\t var map = material[textureType + 'MapSlot'];\n\t if (map) {\n\t map.uvTransform = repeat > 1;\n\t map.uvRepeat.x = repeat;\n\t map.uvRepeat.y = repeat;\n\t }\n\t }\n\t}\n\t\n\t// A dummy object to avoid null checks, this could also be used later to\n\t// create a 3D loading animation\n\t\n\tvar Object3DBase = exports.Object3DBase = _gear.Base.extend({\n\t init: function () {\n\t this.addEvents('change');\n\t },\n\t animate: function () /* delta */{}\n\t});\n\t\n\tvar EmptyObject3D = exports.EmptyObject3D = Object3DBase.extend({\n\t dispose: function () {},\n\t drawTextures: function () {},\n\t draw: function () /* renderer, camera */{},\n\t init: function () {\n\t this.bbox = {\n\t min: { x: -100, y: -100, z: -100 },\n\t max: { x: 100, y: 100, z: 100 }\n\t };\n\t },\n\t uvFromViewPoint: function () /* camera, viewPoint, width, height */{\n\t return null;\n\t },\n\t ready$: function () {\n\t return (0, _gear.resolve)();\n\t }\n\t});\n\t\n\t// Two sided object, using an opaque material for the interior\n\t// We use two steps rendering to be able to avoid z-order artifacts\n\t// The back object is first rendered as a background, then the front object\n\t// is rendered on top effectively making the front object always be on top\n\t// for all visible zones\n\t\n\tvar Object3D = exports.Object3D = Object3DBase.extend({\n\t\n\t Properties: {\n\t textureView: { type: 'TextureView', owned: false, def: null, set: function (textureView) {\n\t this._setTextureView(textureView);\n\t }\n\t },\n\t geometry: { type: 'geometry', owned: false },\n\t\n\t threeScene: { type: 'THREE.Scene', owned: false, def: null }\n\t },\n\t\n\t get backSideColor() {\n\t return this.textureView.backSideColor;\n\t },\n\t\n\t getThreeTexture: function (textureType) {\n\t return this.textureView.getThreeTexture(textureType);\n\t },\n\t\n\t\n\t // This is called for each animation frame, it will render what is needed\n\t drawTextures: function () {\n\t var textureView = this.textureView;\n\t\n\t if (textureView && !textureView.autoDraw) {\n\t textureView.draw();\n\t }\n\t },\n\t init: function (config) {\n\t\n\t this.callParent(config);\n\t\n\t this._forcedMapReady = null;\n\t\n\t // Inititalize materials\n\t this._setTextureView(this.textureView);\n\t\n\t this.createThreeObject();\n\t },\n\t uvFromViewPoint: function (camera, viewPoint, width, height) {\n\t return (0, _threeUtil.uvFromViewPoint)(this.object, camera, viewPoint, width, height);\n\t },\n\t animate: function (delta) {\n\t if (this.mixer) {\n\t this.mixer.update(0.8 * delta);\n\t return true;\n\t }\n\t return false;\n\t },\n\t createThreeObject: function () {\n\t var geometry = this.geometry;\n\t var threeScene = this.threeScene;\n\t var material = this.material;\n\t var materialBack = this.materialBack;\n\t\n\t // Use BufferGeometry, an efficient and GPU friendly data structure\n\t // This may not be the best for animations, we need to further explore this\n\t\n\t var objectGeometry = _config.Config.useBufferGeometry ? new THREE.BufferGeometry().fromGeometry(geometry) : geometry;\n\t\n\t var backSideType = this._currentBackSideType = _config.Config.backSide3D !== 'TwoSteps' ? _config.Config.backSide3D : this.textureView.model.materials[0].backSide === 'None' ? 'None' : 'TwoSteps';\n\t\n\t switch (backSideType) {\n\t\n\t case 'Animation':\n\t\n\t // Make sure we are using a regular Geometry\n\t\n\t var animGeometry = geometry instanceof THREE.BufferGeometry ? new THREE.Geometry().fromBufferGeometry(geometry) : geometry;\n\t\n\t if (animGeometry.bones) {\n\t this.object = new THREE.SkinnedMesh(animGeometry, material);\n\t material.skinning = true;\n\t } else {\n\t this.object = new THREE.Mesh(animGeometry, material);\n\t }\n\t\n\t material.morphTargets = true;\n\t\n\t this.mixer = new THREE.AnimationMixer(this.object);\n\t var animations = geometry.animations;\n\t var morphTargets = geometry.morphTargets;\n\t\n\t if (animGeometry.bones && animations && animations.length > 0) {\n\t // Add bones animation\n\t var bonesClip = geometry.animations[0];\n\t var bonesAction = this.mixer.clipAction(bonesClip);\n\t bonesAction.play();\n\t }\n\t if (morphTargets && morphTargets.length > 1) {\n\t var facesClip = THREE.AnimationClip.CreateFromMorphTargetSequence('morphAnimation', morphTargets, morphTargets.length - 1);\n\t var facesAction = this.mixer.clipAction(facesClip);\n\t facesAction.play();\n\t }\n\t\n\t break;\n\t\n\t case 'None':\n\t\n\t this.object = new THREE.Mesh(geometry, material);\n\t break;\n\t\n\t case 'MultiMaterial':\n\t\n\t // This method can produce artifacts. From Three.js r69 onwards the artifacts\n\t // are more notorious. Some apps may choose to use these option because of performance\n\t this.object = THREE.SceneUtils.createMultiMaterialObject(objectGeometry, [material, materialBack]);\n\t break;\n\t\n\t default:\n\t // 'TwoSteps'\n\t\n\t // This is the best way we found til the moment to avoid back side artifacts\n\t // We create two objects, one with each material. To render the scene we first\n\t // hide the main object and then render again with the back side hidden.\n\t\n\t this.objectBack = new THREE.Mesh(objectGeometry, materialBack);\n\t\n\t this.object = new THREE.Mesh(objectGeometry, material);\n\t\n\t break;\n\t }\n\t\n\t var object = this.object;\n\t var objectBack = this.objectBack;\n\t\n\t\n\t objectGeometry.computeBoundingBox();\n\t var bb = this.bbox = objectGeometry.boundingBox.clone();\n\t var bbCenter = { x: (bb.min.x + bb.max.x) / 2,\n\t y: (bb.min.y + bb.max.y) / 2,\n\t z: (bb.min.z + bb.max.z) / 2 };\n\t\n\t if (objectBack) {\n\t (0, _threeUtil.setObjectPosition)(objectBack, bbCenter);\n\t }\n\t\n\t (0, _threeUtil.setObjectPosition)(object, bbCenter);\n\t\n\t bb.min.x -= bbCenter.x;bb.max.x -= bbCenter.x;\n\t bb.min.y -= bbCenter.y;bb.max.y -= bbCenter.y;\n\t bb.min.z -= bbCenter.z;bb.max.z -= bbCenter.z;\n\t\n\t if (objectBack) {\n\t threeScene.add(objectBack);\n\t }\n\t threeScene.add(object);\n\t },\n\t dispose: function () {\n\t var threeScene = this.threeScene;\n\t var object = this.object;\n\t var objectBack = this.objectBack;\n\t\n\t\n\t threeScene.remove(object);\n\t if (objectBack) {\n\t threeScene.remove(objectBack);\n\t }\n\t },\n\t _setTextureView: function (textureView) {\n\t\n\t this._textureView = textureView;\n\t\n\t if (!this.object) {\n\t this.createMaterialBack();\n\t this.createMaterial();\n\t } else {\n\t this.onTextureChange();\n\t this.onBackSideColorChange();\n\t }\n\t\n\t textureView.on({\n\t 'drawcomplete': this.invalidateTexture,\n\t 'synctextures': this.onTextureChange\n\t }, this);\n\t },\n\t invalidateTexture: function () {\n\t // console.log('drawcomplete');\n\t this.fireEvent('change');\n\t },\n\t onBackSideColorChange: function () {\n\t if (this.materialBack) {\n\t this.materialBack.color.setHex(this.backSideColor.rgbHex);\n\t }\n\t },\n\t onTextureChange: function () {\n\t var _this = this;\n\t\n\t // console.log('on texture change');\n\t var material = this.material;\n\t var materialBack = this.materialBack;\n\t\n\t\n\t if (!material) {\n\t return;\n\t }\n\t\n\t material.map = this.getThreeTexture('color');\n\t\n\t var transparent = false;\n\t\n\t if (!(_config.Config.tiledBumpMap || _config.Config.tiledNormalMap)) {\n\t\n\t (0, _lodash.forEach)(['normal', 'bump', 'specular', 'displacement', 'alpha'], function (textureType) {\n\t var textureMap = _this.textureView.getFixedTextureMap(textureType),\n\t threeTexture = _this.getThreeTexture(textureType);\n\t\n\t setMaterialTexture(material, textureType, textureMap, threeTexture);\n\t\n\t if (textureType === 'alpha') {\n\t transparent = true;\n\t\n\t if (materialBack) {\n\t setMaterialTexture(materialBack, textureType, textureMap, threeTexture);\n\t }\n\t\n\t materialBack.needsUpdate = true;\n\t }\n\t });\n\t }\n\t material.transparent = transparent;\n\t if (materialBack) {\n\t materialBack.transparent = transparent;\n\t }\n\t\n\t material.needsUpdate = true;\n\t this.invalidateTexture();\n\t },\n\t createMaterial: function () {\n\t var _this2 = this;\n\t\n\t /*\r\n\t this.material = new THREE.MeshLambertMaterial({\r\n\t color: 0xf80505,\r\n\t side: THREE.FrontSide\r\n\t });\r\n\t return;\r\n\t */\n\t\n\t var materialType = _config.Config.threeMaterialType ? 'Mesh' + _config.Config.threeMaterialType + 'Material' : 'MeshPhongMaterial';\n\t\n\t if (materialType === 'MeshPhongMaterial') {\n\t this.material = new THREE[materialType]({\n\t side: THREE.FrontSide,\n\t shading: THREE.SmoothShading,\n\t reflectivity: _config.Config.reflectivity || 0,\n\t specular: 0x000000,\n\t shininess: _config.Config.shininess || 0\n\t });\n\t } else {\n\t this.material = new THREE[materialType]({\n\t side: THREE.FrontSide,\n\t roughness: _config.Config.roughness ? parseFloat(_config.Config.roughness) : 0.76,\n\t metalness: _config.Config.metalness ? parseFloat(_config.Config.metalness) : 0.0\n\t });\n\t }\n\t\n\t // Testing\n\t var alphaMap = _config.Config.alphaMap;\n\t if (alphaMap) {\n\t (function () {\n\t // load a texture, set wrap mode to repeat\n\t var loader = new THREE.TextureLoader();\n\t loader.crossOrigin = '';\n\t var texture = loader.load(alphaMap, function () {\n\t _this2.invalidateTexture();\n\t });\n\t\n\t texture.wrapS = THREE.RepeatWrapping;\n\t texture.wrapT = THREE.RepeatWrapping;\n\t var repeatS = _config.Config.tiledBumpMapRepeat || _config.Config.tiledMapRepeat;\n\t var repeat = repeatS ? parseInt(repeatS) : 16;\n\t texture.repeat.set(repeat, repeat);\n\t\n\t var setAlphaMap = function (material) {\n\t material.alphaMap = texture;\n\t material.transparent = true;\n\t material.needsUpdate = true;\n\t var map = material.alphaMapSlot;\n\t if (map) {\n\t map.uvTransform = true;\n\t map.uvRepeat.x = repeat;\n\t map.uvRepeat.y = repeat;\n\t }\n\t };\n\t\n\t setAlphaMap(_this2.material);\n\t if (_this2.materialBack) {\n\t setAlphaMap(_this2.materialBack);\n\t }\n\t })();\n\t }\n\t\n\t var tiledMap = _config.Config.tiledBumpMap || _config.Config.tiledNormalMap;\n\t if (tiledMap) {\n\t\n\t this._forcedMapReady = new _gear.Deferred();\n\t\n\t // load a texture, set wrap mode to repeat\n\t var onLoad = function () {\n\t _this2.invalidateTexture();\n\t _this2._forcedMapReady.resolve();\n\t };\n\t\n\t var _loader = new THREE.TextureLoader();\n\t _loader.crossOrigin = '';\n\t var _texture = _loader.load(tiledMap, onLoad, undefined, onLoad);\n\t\n\t _texture.wrapS = THREE.RepeatWrapping;\n\t _texture.wrapT = THREE.RepeatWrapping;\n\t\n\t var _repeatS = _config.Config.tiledBumpMapRepeat || _config.Config.tiledMapRepeat;\n\t var _repeat = _repeatS ? parseInt(_repeatS) : 16;\n\t _texture.repeat.set(_repeat, _repeat);\n\t\n\t _texture.minFilter = THREE.NearestMipMapLinearFilter;\n\t\n\t var tiledMapScale = _config.Config.tiledMapScale;\n\t var material = this.material;\n\t\n\t var map = void 0;\n\t if (_config.Config.tiledBumpMap) {\n\t material.bumpMap = _texture;\n\t if (tiledMapScale) {\n\t material.bumpScale = parseFloat(tiledMapScale);\n\t }\n\t map = material.bumpMapSlot;\n\t } else {\n\t material.normalMap = _texture;\n\t if (tiledMapScale) {\n\t var scale = parseFloat(tiledMapScale);\n\t material.normalScale = new THREE.Vector2(scale, scale);\n\t }\n\t map = material.normalMapSlot;\n\t }\n\t\n\t map.uvTransform = true;\n\t map.uvRepeat.x = _repeat;\n\t map.uvRepeat.y = _repeat;\n\t }\n\t\n\t this.onTextureChange();\n\t },\n\t ready$: function () {\n\t var deferred = this._forcedMapReady;\n\t return deferred ? deferred.promise : (0, _gear.resolve)();\n\t },\n\t createMaterialBack: function () {\n\t\n\t this.materialBack = new THREE.MeshLambertMaterial({\n\t color: this.backSideColor.rgbHex,\n\t side: THREE.BackSide\n\t });\n\t },\n\t draw: function (renderer, camera) {\n\t var threeScene = this.threeScene;\n\t var object = this.object;\n\t var objectBack = this.objectBack;\n\t\n\t\n\t if (this._currentBackSideType === 'TwoSteps') {\n\t\n\t objectBack.visible = true;\n\t object.visible = false;\n\t\n\t renderer.render(threeScene, camera);\n\t\n\t objectBack.visible = false;\n\t object.visible = true;\n\t\n\t renderer.autoClear = false;\n\t }\n\t\n\t renderer.render(threeScene, camera);\n\t\n\t renderer.autoClear = true;\n\t }\n\t});\n\n/***/ },\n\n/***/ 129:\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t value: true\n\t});\n\texports.Preview3D = exports.thumbnailImage3D$ = undefined;\n\texports.createPreview3D = createPreview3D;\n\t\n\tvar _lodash = __webpack_require__(4);\n\t\n\tvar _gear = __webpack_require__(8);\n\t\n\tvar _view = __webpack_require__(84);\n\t\n\tvar _canvas3d = __webpack_require__(124);\n\t\n\tvar canvas3D = null;\n\t\n\tfunction _thumbnailImage$(config) {\n\t\n\t var size = config.size === undefined ? 256 : config.size;\n\t\n\t if (!canvas3D) {\n\t canvas3D = new _canvas3d.Canvas3D({ width: size, height: size, preserveDrawingBuffer: true, autoDraw: false });\n\t } else if (canvas3D.width !== size) {\n\t canvas3D.updateSize(size, size);\n\t }\n\t\n\t if (config.canvas3D) {\n\t // Copy camera position from the user view\n\t canvas3D.cameraStateString = config.canvas3D.cameraStateString;\n\t }\n\t\n\t return canvas3D.showDocument$(config.document).then(function () {\n\t return canvas3D.draw$().then(function () {\n\t return canvas3D.image();\n\t });\n\t });\n\t}\n\t\n\tvar currentPromise = (0, _gear.resolve)();\n\t\n\tvar thumbnailImage3D$ = exports.thumbnailImage3D$ = function (config) {\n\t currentPromise = currentPromise.then(function () {\n\t return _thumbnailImage$(config);\n\t });\n\t return currentPromise;\n\t};\n\t\n\t// Cx.Preview3D({ renderTo: ..., id: ... });\n\t\n\tvar Preview3D = exports.Preview3D = _canvas3d.Canvas3D.extend({\n\t init: function () {\n\t var config = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];\n\t\n\t\n\t this.callParent(config);\n\t\n\t if (config.id) {\n\t this.load$(config.id).then(this.commit$);\n\t }\n\t }\n\t});\n\t\n\tfunction createPreview3D(domId, docId, a) {\n\t var config = { appendTo: (0, _view.g$)('#' + domId), id: docId };\n\t if ((0, _lodash.isPlainObject)(a)) {\n\t (0, _lodash.assign)(config, a);\n\t } else if (a) {\n\t config.documentFilter = a;\n\t }\n\t return Preview3D(config);\n\t}\n\n/***/ }\n\n})\n});\n;\n\n\n/** WEBPACK FOOTER **\n ** canvas3d.js\n **/","import { assign } from 'lodash';\r\n\r\nimport * as Canvas3d from '../ui/canvas3d';\r\n\r\nlet { Cx } = window;\r\n\r\nassign( Cx, Canvas3d );\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/web/canvas3d.js\n **/","export * from './texture-view';\r\nexport * from './canvas3d';\r\nexport * from './thumbnail';\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/index.js\n **/","import { Config } from 'config';\r\n\r\nimport { forEach, remove, now } from 'lodash';\r\n\r\nimport { concat, map$, invokeMap$, resolve } from 'gear';\r\n\r\nimport { Point, Color,\r\n Document, FigureConditions_Mixin } from 'cdl';\r\n\r\nimport { View, SyncedFigureViews, Plugin, findByTextureType,\r\n View2D_Mixin,\r\n DocumentView_Mixin,\r\n SelectedFigures_Mixin,\r\n InteractiveView_Mixin,\r\n TextureComposition, TextureTile } from '../view';\r\n\r\nimport { Doc3D_Model_Mixin } from './doc3d-model-mixin';\r\n\r\nimport { TextureViewComposition } from './texture-view-scene';\r\n\r\nimport { TextureTracker } from './move3d';\r\n\r\n\r\n\r\nconst fpsLimit = 6;\r\n\r\nexport const StaticTextureView = View.extend( View2D_Mixin )\r\n .extend( DocumentView_Mixin )\r\n .extend( SelectedFigures_Mixin )\r\n .extend( FigureConditions_Mixin )\r\n .extend( Doc3D_Model_Mixin ).extend({\r\n\r\n typeName: 'StaticTextureView',\r\n\r\n Properties: {\r\n\r\n document: { type: 'Document', def: null, owned: false, set( v ) { this._setDoc(v); } },\r\n\r\n canvas3D: { type: 'boolean', def: null, onChange(value) {\r\n if( value && this.model ) {\r\n this.zoomToFitTextureFor(this.model);\r\n }\r\n }},\r\n\r\n // [TODO] onChange, fireEvent\r\n backSideDarkFactor: { type: 'number', def: 0.5 },\r\n\r\n backSideColor: { type: 'Color', def: null, get() {\r\n return this._backSideColor || Color.changeLuminosity( this.frontSideColor, - this.backSideDarkFactor );\r\n }},\r\n\r\n textureSize: { type: 'number', def: null, onChange() {\r\n this.updateSize();\r\n } }\r\n },\r\n\r\n get model() {\r\n const { doc } = this;\r\n return doc && doc.model3D;\r\n },\r\n\r\n getThreeTexture( textureType ) {\r\n if( textureType === 'color' ) {\r\n return this.scene.threeTexture;\r\n }\r\n else {\r\n // Textures compositions, full size, same as color\r\n const texture = findByTextureType( this.textures, textureType );\r\n if( texture ) {\r\n return texture.threeTexture;\r\n }\r\n else {\r\n // Tiled textures\r\n const tiledTexture = this.textureTiles[ textureType ];\r\n if( tiledTexture ) {\r\n return tiledTexture.threeTexture;\r\n }\r\n }\r\n }\r\n },\r\n\r\n get frontSideColor() {\r\n return this.backgroundColor;\r\n },\r\n set frontSideColor( color ) {\r\n this.backgroundColor = color;\r\n },\r\n\r\n updateSize(w,h) {\r\n const { textureSize, width, height, _previewing } = this;\r\n if( textureSize && arguments.length === 0 ) {\r\n if( this.canvas3D ) {\r\n if( ! _previewing && ( textureSize !== width || textureSize !== height ) ) {\r\n // console.log('full texture');\r\n this.callParent(textureSize,textureSize);\r\n }\r\n else if( _previewing ) {\r\n if( textureSize === 512 ) {\r\n return;\r\n }\r\n let previewingTextureSize = Math.max( textureSize / ( this.stats.fps > fpsLimit ? 2 : 4 ) ,512);\r\n if( ! ( previewingTextureSize === width && previewingTextureSize === height ) ) {\r\n // console.log('preview texture ' + previewingTextureSize );\r\n this.callParent(previewingTextureSize,previewingTextureSize);\r\n }\r\n }\r\n }\r\n else {\r\n this.callParent(textureSize,textureSize);\r\n }\r\n }\r\n else {\r\n this.callParent(w,h);\r\n }\r\n },\r\n\r\n postResize() {\r\n if( this._modelReady ) {\r\n this.zoomToFitTextureFor( this.model );\r\n }\r\n },\r\n\r\n createScene() {\r\n return new TextureViewComposition({ main: true });\r\n },\r\n\r\n redrawFigure( figure ) {\r\n this.renderer.redraw( this, figure );\r\n },\r\n\r\n draw() {\r\n\r\n if( ! this._modelReady ) {\r\n return;\r\n }\r\n const { canvas3D } = this;\r\n if( canvas3D ) {\r\n canvas3D.computeViewToTextureScale();\r\n }\r\n if( this._previewing && now() - this._previewingT > 1200 ) {\r\n this.endPreview();\r\n this.render$();\r\n return;\r\n }\r\n this.callParent();\r\n },\r\n\r\n // [TODO] This should be available at the view level\r\n // This function will make sure that everything is ready to be rendered\r\n // before drawing. Is used in the 3D thumbnail generation process.\r\n draw$() {\r\n const { doc, zoom } = this;\r\n return doc.render$() .then( () => {\r\n return doc.prepareToDraw$(zoom) .then( () => {\r\n return invokeMap$( this.mapToFigureViews(doc.figures), 'ready$' ) .then( () => {\r\n return map$( this.textureTiles, 'promise' ) .then( () => {\r\n this.redrawAll();\r\n this.draw();\r\n });});});});\r\n },\r\n\r\n zoomToFitTextureFor( model ) {\r\n const { textureWidth } = model;\r\n const { width } = this;\r\n this.zoom = width / textureWidth;\r\n this.center = new Point( textureWidth/2, textureWidth/2 );\r\n return this;\r\n },\r\n\r\n zoomToFitTexture$() {\r\n return this.loadModel3D$() .then( model => { // [TODO]\r\n if( model ) {\r\n return this.zoomToFitTextureFor(model);\r\n }\r\n });\r\n },\r\n\r\n zoomToFit$() {\r\n if( arguments.length === 0 ){\r\n return this.zoomToFitTexture$();\r\n }\r\n else {\r\n return this.zoomToFitFigures$(...arguments);\r\n }\r\n },\r\n\r\n docToView(/* docPoint */) {\r\n console.log('TextureView docToView not supported');\r\n },\r\n\r\n docDeltaToView( docDelta ) {\r\n return this.viewTransform.docDeltaToView(this,docDelta);\r\n },\r\n\r\n viewToDoc( viewPoint, docIsland ) {\r\n return this.modelToDoc(viewPoint,docIsland);\r\n },\r\n\r\n docPoint( event, docIsland ) {\r\n return this.modelToDoc( this.modelPoint(event), docIsland );\r\n },\r\n\r\n textureDeltaToDoc( textureDelta ) {\r\n return this.viewTransform.viewDeltaToDoc(this,textureDelta);\r\n },\r\n\r\n // Overwritten in TextureView below\r\n viewDeltaToDoc( viewDelta ) {\r\n return this.viewTransform.viewDeltaToDoc(this,viewDelta);\r\n },\r\n\r\n mapToFigureViews( figures ) {\r\n return this.figureViews.mapToFigureViews(figures);\r\n },\r\n\r\n figureView( figure ) {\r\n return this.figureViews.get(figure);\r\n },\r\n\r\n figureTextureTypes() {\r\n return [ 'color' ]; // Allow 'normal', 'bump', 'specular'...\r\n },\r\n\r\n init( config = {} ) {\r\n\r\n this.addEvents('synctextures');\r\n\r\n this._previewing = false;\r\n this._previewingT = 0;\r\n\r\n this._modelReady = false;\r\n this.figureViews = new SyncedFigureViews({ view: this });\r\n\r\n this.textureTiles = {};\r\n\r\n this._backgroundColor = Color.White();\r\n\r\n this.callParent(config);\r\n\r\n this._setDoc( new Document() );\r\n },\r\n\r\n insertViewPlugins( plugins ) {\r\n this.callParent(plugins);\r\n let textureViewPlugins = [\r\n Plugin.TextureMap({ textureType: 'color' }),\r\n Plugin.TextureViewRenderer()\r\n ];\r\n if( ! this.canvas3D ) {\r\n textureViewPlugins = concat(textureViewPlugins,[\r\n Plugin.ViewControls(),\r\n Plugin.PluginsLayer(),\r\n Plugin.Tools()\r\n ]);\r\n }\r\n plugins.insert(0,textureViewPlugins);\r\n },\r\n\r\n _setDoc( doc ) {\r\n\r\n const old = this.doc;\r\n if( old === doc ) {\r\n return resolve(); // Nothing to do\r\n }\r\n if( old ) {\r\n const { model3D } = old; // [TODO] This will be removed\r\n if( model3D ) {\r\n model3D.un(this);\r\n }\r\n\r\n this.unlinkDoc(old);\r\n }\r\n\r\n this._modelReady = false;\r\n\r\n this._document = doc;\r\n this.linkDoc(doc);\r\n\r\n if( ! doc.is3D ) {\r\n return resolve();\r\n }\r\n\r\n return doc.loadModel3D$() .then( () => {\r\n // [TODO] We could avoid this by avoiding async processing for simple shapes\r\n // This needs further research\r\n\r\n /*\r\n // We are only updating when the Doc3D fires events\r\n doc.model3D.on({\r\n 'materialschanged': this.on_materialschanged,\r\n 'model3dchanged': this.on_model3dchanged,\r\n 'modeldata3dchanged': this.on_modeldata3dchanged,\r\n },this);\r\n */\r\n\r\n return doc.model3D.update$() .then( () => {\r\n\r\n\r\n this.syncModel3D();\r\n\r\n this._modelReady = true;\r\n // console.log('modelReady');\r\n\r\n }); });\r\n },\r\n\r\n linkDoc( doc ) {\r\n this.figureViews.link(doc);\r\n this.callParent(doc);\r\n this.fireEvent('newdocument',this,doc);\r\n },\r\n\r\n unlinkDoc( doc ) {\r\n this.figureViews.unlink(doc);\r\n },\r\n\r\n loadModel3D$() {\r\n return this.doc.is3D ? this.doc.loadModel3D$() : resolve();\r\n },\r\n\r\n syncTextures() {\r\n\r\n // Sync full textures, color and optinal maps\r\n // The idea is that each figure should be able to draw to these textures\r\n // Tiled textures are directly loaded and cached by getThreeTexture\r\n\r\n if( Config.ignoreTextures ) {\r\n return;\r\n }\r\n\r\n const { textures } = this;\r\n\r\n // Sync texture backgrounds plugins\r\n const { plugins } = this;\r\n remove( plugins, plugin => {\r\n return ( plugin instanceof Plugin.TextureMap ) && plugin.textureType !== 'color';\r\n });\r\n\r\n findByTextureType( plugins, 'color' ).updateMap();\r\n\r\n forEach( ['bump','normal','specular','displacement','alpha'], textureType => {\r\n\r\n // This function ignores bump maps if there are normal maps\r\n const textureMap = this.getFixedTextureMap(textureType);\r\n\r\n const texture = findByTextureType(textures,textureType);\r\n if( textureMap && textureMap.wrap === 'Stretch' ) { // [TODO] Enable it if figures want to draw things to this textureType\r\n if( ! texture ) {\r\n const composition = this.createTexture(textureType);\r\n textures.push(composition);\r\n }\r\n plugins.unshift( Plugin.TextureMap({ textureType }) );\r\n }\r\n else if( texture ) {\r\n if( texture.layersContainer ) { // [TODO]\r\n texture.remove();\r\n }\r\n textures.remove( texture );\r\n }\r\n\r\n const { textureTiles } = this;\r\n const tiledTexture = textureTiles[textureType];\r\n if( textureMap && textureMap.wrap === 'Repeat' ) {\r\n if( ! tiledTexture || tiledTexture.id !== textureMap.id ) {\r\n\r\n textureTiles[textureType] = new TextureTile(this,textureType,textureMap);\r\n }\r\n }\r\n else {\r\n textureTiles[textureType] = null;\r\n }\r\n });\r\n\r\n this.fireEvent('synctextures',this);\r\n },\r\n\r\n getFixedTextureMap( textureType ) {\r\n const { model, doc } = this;\r\n const docMaterial = doc && doc.materials && doc.materials[0];\r\n if( textureType === 'normal' && ( docMaterial && docMaterial.getFixedTextureMap('bump') ) ) {\r\n // Ignore normal map in Model3D if there is a bump map in Doc3D\r\n return null;\r\n }\r\n else {\r\n const modelMaterial = model && model.materials[0];\r\n const docTextureMap = docMaterial && docMaterial.getFixedTextureMap(textureType);\r\n const modelTextureMap = modelMaterial && modelMaterial.getFixedTextureMap(textureType);\r\n return docTextureMap || modelTextureMap;\r\n }\r\n },\r\n\r\n createTexture( textureType ) {\r\n return new TextureComposition({ textureType });\r\n },\r\n\r\n syncModel3D() {\r\n // console.log('syncModel3D');\r\n\r\n this.syncTextures();\r\n\r\n if( this.canvas3D ){\r\n // Forces the texture to cover the requested textureSize ( 512, 1024, 2048 )\r\n this.zoomToFitTextureFor(this.model);\r\n }\r\n },\r\n\r\n on_materialschanged() {\r\n this.syncModel3D();\r\n this.callParent(...arguments);\r\n },\r\n\r\n on_model3dchanged() {\r\n this.syncModel3D();\r\n this.callParent(...arguments);\r\n },\r\n /*\r\n on_modeldata3dchanged() {\r\n\r\n },\r\n */\r\n\r\n optimizePreview() {\r\n if( Config.texturePreview ) {\r\n this._previewingResize = true;\r\n this._previewing = true;\r\n this._previewingT = now();\r\n this.updateSize();\r\n this._previewingResize = false;\r\n }\r\n },\r\n endPreview() {\r\n if( this._previewing && this.width !== this.textureSize ) {\r\n this._previewingResize = true;\r\n this._previewing = false;\r\n this.updateSize();\r\n this._previewingResize = false;\r\n }\r\n },\r\n\r\n // [MODEL]\r\n on_renderstarted( doc, type ) {\r\n if( this.canvas3D ) {\r\n if( type === 'preview' ) {\r\n this.optimizePreview();\r\n }\r\n else if( type === 'commit' ) {\r\n this.endPreview();\r\n }\r\n }\r\n this.callParent(doc,type);\r\n },\r\n\r\n dispose() {\r\n if( this.doc ) {\r\n this.unlinkDoc(this.doc);\r\n }\r\n this.callParent();\r\n },\r\n\r\n onBackgroundColorChange() {\r\n this.redraw('document');\r\n },\r\n\r\n get textureView() {\r\n return this;\r\n },\r\n\r\n pluginDirectDomEventHandling({ target }) {\r\n return target === 'view' || target === 'model';\r\n },\r\n\r\n createEventTracker( event, docIsland ) {\r\n return new TextureTracker(event,docIsland);\r\n }\r\n\r\n});\r\n\r\nexport const TextureView = StaticTextureView.extend( InteractiveView_Mixin ).extend({\r\n\r\n typeName: 'TextureView',\r\n\r\n // Rewire user interaction to Canvas3D if this texture is being used for it\r\n // Plugins are right now added to the TextureView, because the rendering code\r\n // looked complex to abstract. It may be a good idea to let the plugins in the\r\n // 3D view and wire the rendering instead. This starts to look really complex.\r\n\r\n get is3D() {\r\n return !!this.canvas3D;\r\n },\r\n\r\n get selectAndDragEnabled() {\r\n const { canvas3D } = this;\r\n return canvas3D ? canvas3D.selectAndDragEnabled : false;\r\n },\r\n\r\n viewDeltaToDoc( delta ) {\r\n const { canvas3D } = this;\r\n return canvas3D ? canvas3D.viewDeltaToDoc(delta) : this.callParent(delta);\r\n },\r\n\r\n viewDeltaToTexture( delta ) {\r\n const { canvas3D } = this;\r\n return canvas3D ? canvas3D.viewDeltaToTexture(delta) : this.callParent(delta);\r\n },\r\n\r\n triggerKeyboard(event) {\r\n const { canvas3D } = this;\r\n return canvas3D ? canvas3D.triggerKeyboard(event) : this.callParent(event);\r\n },\r\n\r\n are() {\r\n const { canvas3D } = this;\r\n return canvas3D ? canvas3D.are(...arguments) : this.callParent(...arguments);\r\n },\r\n\r\n is() {\r\n const { canvas3D } = this;\r\n return canvas3D ? canvas3D.is(...arguments) : this.callParent(...arguments);\r\n },\r\n\r\n /*\r\n condition() {\r\n const { canvas3D } = this;\r\n return canvas3D ? canvas3D.condition(...arguments) : this.callParent(...arguments);\r\n },\r\n */\r\n\r\n status(s) {\r\n const { canvas3D } = this;\r\n return canvas3D ? canvas3D.status(s) : this.callParent(s);\r\n },\r\n\r\n get_cursor() {\r\n const { canvas3D } = this;\r\n return canvas3D ? canvas3D.cursor : this.callParent();\r\n },\r\n\r\n set_cursor( cursor ) {\r\n const { canvas3D } = this;\r\n if( canvas3D ) {\r\n canvas3D.cursor = cursor;\r\n }\r\n else {\r\n this.callParent(cursor);\r\n }\r\n },\r\n\r\n fireEvent( type, ...params ) {\r\n const { canvas3D } = this;\r\n if( canvas3D ) {\r\n if( type === 'toolchanged' ||\r\n type === 'figuresdrag' ||\r\n type === 'figuresdrop' ) {\r\n\r\n canvas3D.fireEvent(type,...params);\r\n }\r\n }\r\n this.callParent(type,...params);\r\n },\r\n\r\n});\r\n\r\n\r\nexport default TextureView;\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/texture-view.js\n **/","\r\nimport { Layers, isTextureIsland, textureIslandName, designLayersFrom,\r\n designFiguresFrom, docIslandsFrom, filterIslandsFor,\r\n modelToDocMatrix, filterTargetLayers } from 'cdl';\r\n\r\nimport { retargetEvent3D } from './move3d';\r\n\r\n\r\nfunction notTextureIsland( figure ) {\r\n return ! isTextureIsland(figure);\r\n}\r\n\r\nexport const Doc3D_Model_Mixin = {\r\n\r\n Properties: {\r\n selectableIslands: { type: 'boolean', def: true }\r\n },\r\n\r\n init() {\r\n this.callParent(...arguments);\r\n\r\n // DocIslands can not be moved from these views\r\n this.condition('movable' ,notTextureIsland);\r\n this.condition('rotatable',notTextureIsland);\r\n this.condition('removable',notTextureIsland);\r\n this.condition('copyable' ,notTextureIsland);\r\n\r\n },\r\n\r\n activeSelectableFigures() {\r\n // [TODO] activePageSelection, allowCrossPageSelection\r\n return this.callParent();\r\n },\r\n\r\n uvToModel( uv ) {\r\n return this.model.uvToModel( uv );\r\n },\r\n\r\n uvToDoc( uv, docIsland ) {\r\n return this.modelToDoc( this.uvToModel(uv), docIsland );\r\n },\r\n\r\n modelToDoc( modelPoint, docIsland ) {\r\n if( docIsland === undefined ) {\r\n docIsland = this.topDocIslandAtModel(modelPoint);\r\n if( ! docIsland ) {\r\n return undefined;\r\n }\r\n }\r\n const matrix = this.model.modelToDocMatrixFor(docIsland);\r\n const docPoint = matrix.apply( modelPoint );\r\n return docPoint;\r\n },\r\n\r\n topDocIslandAtModel( modelPoint, modelIsland ) {\r\n if( ! modelIsland ){\r\n modelIsland = this.modelIslandAt(modelPoint);\r\n }\r\n return modelIsland && this.topDocIslandFor(modelIsland);\r\n },\r\n\r\n topDocIslandFor( modelIsland ) {\r\n return this.doc.topDocIslandFor(modelIsland);\r\n },\r\n\r\n docIslandsFor( docIsland ) {\r\n return this.doc.docIslandsFor(docIsland);\r\n },\r\n\r\n modelIslandFor( docIsland ) {\r\n return this.model.modelIslandFor( docIsland );\r\n },\r\n\r\n modelIslandAt( modelPoint ) {\r\n return this.textureView._modelReady && this.model.modelIslandAt( modelPoint );\r\n },\r\n\r\n modelPointIsOut( modelPoint, modelIsland ) {\r\n return ! modelIsland.bounds_().contains(modelPoint);\r\n },\r\n\r\n forEachDesignFiguresIn( name, func ) {\r\n const { doc } = this;\r\n const { pages } = doc;\r\n for( let p = 0, pEnd = pages.length; p < pEnd; ++p ) {\r\n const page = pages[p];\r\n const designFigures = designFiguresFrom(page);\r\n const docIslands = docIslandsFrom(page);\r\n for( let i = 0, iEnd = docIslands.length; i < iEnd; ++i ) {\r\n const docIsland = docIslands[i];\r\n if( textureIslandName(docIsland) === name ) {\r\n func(docIsland,designFigures);\r\n }\r\n }\r\n }\r\n },\r\n\r\n extractHitInfo( hit, info ) {\r\n if( hit ) {\r\n if( info ) {\r\n info.tight = hit.tight;\r\n info.docPoint = hit.docPoint;\r\n info.docIsland = hit.docIsland;\r\n }\r\n return hit.figure;\r\n }\r\n return hit;\r\n },\r\n\r\n figureAtModelPointEx( modelPoint, tabFigures ) {\r\n const candidates = this.candidateFiguresAtModelPoint(modelPoint);\r\n return this.bestFigureCandidate(candidates,tabFigures);\r\n },\r\n\r\n filterSelectableInto( figures, r ) { // [TODO] filter by condition\r\n for( let k = 0, kEnd = figures.length; k < kEnd; k++ ) {\r\n const figure = figures[k];\r\n if( this.is( figure, 'selectable' ) ) {\r\n r.push( figure );\r\n }\r\n }\r\n },\r\n\r\n rawFigureHitsAtModelPoint( modelPoint ) {\r\n return this.candidateFiguresAtModelPoint( modelPoint, true );\r\n },\r\n\r\n candidateFiguresAtModelPoint( modelPoint, raw = false ) {\r\n const { selectableIslands } = this;\r\n const candidates = [];\r\n const modelIsland = this.modelIslandAt(modelPoint);\r\n const docIslandCandidates = [];\r\n const { pages } = this.doc;\r\n for( let p = pages.length-1; p >= 0; --p ) {\r\n const page = pages[p];\r\n\r\n if( raw || !page._locked && !page._hidden ) {\r\n\r\n const pagedDesignLayers = designLayersFrom(page);\r\n const designLayers = raw ? pagedDesignLayers : filterTargetLayers( pagedDesignLayers );\r\n\r\n let figures;\r\n if( raw ) {\r\n figures = Layers.flatten(designLayers);\r\n }\r\n else {\r\n figures = [];\r\n for( let l = 0, lEnd = designLayers.length; l < lEnd; ++l ) {\r\n this.filterSelectableInto( designLayers[l].figures, figures );\r\n }\r\n }\r\n\r\n\r\n const docIslands = filterIslandsFor( docIslandsFrom(page), modelIsland );\r\n\r\n for( let f = figures.length-1; f >= 0 ; --f ) {\r\n const figure = figures[f];\r\n\r\n for( let i = docIslands.length-1; i >= 0 ; --i ) {\r\n const docIsland = docIslands[i];\r\n const docPoint = modelToDocMatrix(docIsland,modelIsland).apply( modelPoint );\r\n\r\n if( figure.globalFrame_().contains(docPoint) ) {\r\n candidates.push({\r\n figure, docIsland, docPoint,\r\n tight: raw ? figure.containsPoint(docPoint) : false\r\n });\r\n }\r\n }\r\n }\r\n\r\n if( raw || selectableIslands ) {\r\n for( let i = docIslands.length-1; i >= 0 ; --i ) {\r\n const docIsland = docIslands[i];\r\n const docPoint = modelToDocMatrix(docIsland,modelIsland).apply( modelPoint );\r\n docIslandCandidates.push({\r\n figure: docIsland, docIsland, docPoint,\r\n tight: raw ? docIsland.containsPoint(docPoint) : false\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return candidates.concat(docIslandCandidates);\r\n },\r\n\r\n on_domEvent({ event, type, isPrimary }) {\r\n\r\n if( isPrimary && type === 'pointerdown' ) {\r\n const { modelPoint } = event;\r\n if( modelPoint && this.modelIslandAt(modelPoint) ) {\r\n // track3D.log(`[3D] Start tracking of ${type}`);\r\n const docIsland = this.topDocIslandAtModel(modelPoint);\r\n if( docIsland ) {\r\n this.tracker = this.createEventTracker( event, docIsland );\r\n }\r\n }\r\n }\r\n\r\n this.callParent(event);\r\n\r\n if( isPrimary && this.tracker && type === 'pointerup' ) {\r\n // track3D.log(`[3D] End tracking of ${type}`);\r\n this.tracker = null;\r\n }\r\n },\r\n\r\n handlePluginDomEvent( plugin, { event, type, route, isPrimary } ) {\r\n\r\n if( this.pluginDirectDomEventHandling(plugin) ) {\r\n plugin.handleDomEvent(event);\r\n return;\r\n }\r\n\r\n // We avoid providing feedback in case of 3D views, as it is slowing down\r\n // things for complex models. It is also not clear how to handle properly\r\n // feedback in tools if there are several islands. \r\n if( false && type === 'mousemove' && ! this.tracker ) {\r\n\r\n const { modelPoint } = event;\r\n const modelIsland = modelPoint && this.modelIslandAt(modelPoint);\r\n if( modelIsland ) {\r\n const docIslands = this.docIslandsFor(modelIsland);\r\n for( let i = docIslands.length-1; i >= 0 && ! event.stopped; --i ) {\r\n const docIsland = docIslands[i];\r\n const newEvent = retargetEvent3D(event,docIsland);\r\n plugin.on_domEvent(newEvent);\r\n if( newEvent.stopped ){\r\n event.stopPropagation();\r\n }\r\n }\r\n }\r\n }\r\n\r\n if( type === 'pointerdown' && isPrimary ) {\r\n\r\n const { modelPoint } = event;\r\n const modelIsland = modelPoint && this.modelIslandAt(modelPoint);\r\n if( modelIsland ) {\r\n\r\n if( plugin.has_try_pointerdown() ){\r\n\r\n const docIslands = this.docIslandsFor(modelIsland);\r\n\r\n for( let i = docIslands.length-1; i >= 0 && ! event.stopped; --i ) {\r\n const docIsland = docIslands[i];\r\n\r\n const tracker = this.createEventTracker( event, docIsland );\r\n const newEvent = tracker.retargetedEvent;\r\n // track3D.log(`[3D] Try to start Tracking of ${type}`);\r\n plugin.try_pointerdown(newEvent);\r\n if( newEvent.stopped ){\r\n this.tracker = tracker; // Change the default tracking to follow this island\r\n event.stopPropagation();\r\n }\r\n }\r\n\r\n if( event.stopped ){\r\n return false;\r\n }\r\n }\r\n\r\n // track3D.log(`[3D] ${type}`);\r\n plugin.on_domEvent( event );\r\n }\r\n }\r\n else if( ( type === 'pointermove' ||\r\n type === 'pointerup' ) && isPrimary ) {\r\n\r\n if( this.tracker ) { // even if modelPoint is null, we track these events\r\n const newEvent = this.tracker.move(event);\r\n plugin.on_domEvent(newEvent);\r\n if( newEvent.stopped ) {\r\n event.stopPropagation();\r\n }\r\n }\r\n }\r\n else if( ( type === 'click' ||\r\n type === 'dblcick' ||\r\n type === 'contextmenu' ) ) {\r\n\r\n const { modelPoint } = event;\r\n const modelIsland = modelPoint && this.modelIslandAt(modelPoint);\r\n if( modelIsland ) {\r\n\r\n const tryHandler = 'try_'+type;\r\n if( plugin['has_'+tryHandler]() ){\r\n\r\n\r\n const docIslands = this.docIslandsFor(modelIsland);\r\n for( let i = docIslands.length-1; i >= 0 && ! event.stopped; --i ) {\r\n const docIsland = docIslands[i];\r\n // track3D.log(`[3D] Retarget of ${type}, using try_`);\r\n const newEvent = retargetEvent3D(event,docIsland);\r\n plugin[tryHandler]( newEvent );\r\n if( newEvent.stopped ){\r\n event.stopPropagation();\r\n }\r\n }\r\n\r\n if( event.stopped ){\r\n return false;\r\n }\r\n }\r\n // track3D.log(`[3D] Direct routing of ${type}`);\r\n plugin.on_domEvent(event);\r\n }\r\n }\r\n else if( type === 'keypress' ||\r\n type === 'keydown' ||\r\n type === 'keyup' ||\r\n type === 'mousewheel' ||\r\n type === 'focus' ||\r\n type === 'focusout' ) {\r\n\r\n // track3D.log(`[3D] Direct routing of ${type}`);\r\n plugin.on_domEvent(event);\r\n }\r\n },\r\n\r\n};\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/doc3d-model-mixin.js\n **/","import { assign } from 'lodash';\r\n\r\nimport { Point } from 'cdl';\r\n\r\n// Simple retargetting without tracking\r\n\r\nconst SimpleTracker3D = function(event,docIsland) {\r\n this._event = event;\r\n this._docIsland = docIsland;\r\n};\r\nSimpleTracker3D.prototype.track = function({ view }) {\r\n\r\n const docIsland = this._docIsland,\r\n modelPoint = this._event.modelPoint, // Important, this._event is different from track(event) here\r\n modelIsland = view.modelIslandFor(docIsland),\r\n docPoint = view.modelToDoc(modelPoint,docIsland);\r\n\r\n return {\r\n modelPoint,\r\n modelIsland,\r\n docIsland,\r\n docPoint,\r\n modelPointRaw : modelPoint,\r\n modelIslandRaw : modelIsland,\r\n docIslandRaw : docIsland,\r\n docPointRaw : docPoint,\r\n };\r\n};\r\n\r\nexport function retargetEvent3D( event, docIsland ) {\r\n return event.retarget( event.eventDown, new SimpleTracker3D(event,docIsland) );\r\n}\r\n\r\n\r\n// Move3D helper to track the mouse starting from a given doc island\r\n// and following it even if it goes out it or the model\r\n\r\nexport const Tracker3D = function( { view, event, viewPoint, modelPoint }, docIsland ) {\r\n\r\n const docPoint = view.modelToDoc(modelPoint,docIsland);\r\n const modelIsland = view.modelIslandFor(docIsland);\r\n\r\n assign( this, { view,\r\n\r\n event,\r\n eventDown: event,\r\n\r\n // Points following the original island\r\n // This is used for almost all tools\r\n modelPoint,\r\n modelIsland,\r\n docIsland,\r\n docPoint,\r\n\r\n // Tracking, always against the docIslandDown\r\n viewPointLast : viewPoint,\r\n modelPointLast : modelPoint,\r\n\r\n // Points that jumps between islands, useful for move operations\r\n modelPointRaw : modelPoint,\r\n modelIslandRaw : modelIsland,\r\n docIslandRaw : docIsland,\r\n docPointRaw : docPoint,\r\n\r\n // Raw tracking, front => sleeve => out (should use sleeve points)\r\n viewPointFirstRaw : viewPoint,\r\n viewPointLastRaw : viewPoint,\r\n\r\n modelPointFirstRaw : modelPoint,\r\n modelPointLastRaw : modelPoint,\r\n\r\n started : false,\r\n });\r\n\r\n this.retargetedEventDown = this.retargetedEvent;\r\n};\r\n\r\nTracker3D.prototype = {\r\n\r\n get retargetedEvent() {\r\n return this.event.retarget(this.retargetedEventDown,this);\r\n },\r\n\r\n track() {\r\n\r\n const { view, viewPoint, originalEvent } = this.event;\r\n const modelPoint = view.modelPoint(originalEvent);\r\n\r\n const { eventDown, docIsland, modelIsland } = this;\r\n\r\n if( modelPoint && ! modelPoint.isEqual(eventDown.modelPoint) ) {\r\n this.started = true;\r\n }\r\n\r\n if( ! this.started ) {\r\n return this.trackData();\r\n }\r\n\r\n let modelPointRaw = modelPoint;\r\n\r\n if( modelPoint && ! view.modelPointIsOut(modelPoint,modelIsland) ) {\r\n\r\n this.modelPoint = modelPoint;\r\n\r\n this.viewPointLast = viewPoint;\r\n this.modelPointLast = modelPoint;\r\n }\r\n else {\r\n\r\n // We need to come up with a proper modelPoint to continue the movement\r\n this.modelPoint = interpolatingExtension( viewPoint, eventDown.viewPoint, this.viewPointLast,\r\n eventDown.modelPoint, this.modelPointLast );\r\n }\r\n\r\n this.docPoint = view.modelToDoc(this.modelPoint,this.docIsland);\r\n\r\n // Raw properties\r\n\r\n if( modelPointRaw && view.modelPointIsOut(modelPointRaw,this.modelIslandRaw) ) {\r\n\r\n const docIslandRaw = view.topDocIslandAtModel(modelPointRaw);\r\n if( docIslandRaw && docIslandRaw.page === docIsland.page ) {\r\n this.modelIslandRaw = view.modelIslandAt(modelPointRaw);\r\n this.docIslandRaw = docIslandRaw;\r\n\r\n this.viewPointFirstRaw = viewPoint;\r\n this.modelPointFirstRaw = modelPointRaw;\r\n }\r\n else {\r\n // Trigger interpolation\r\n modelPointRaw = null;\r\n }\r\n }\r\n\r\n if( modelPointRaw ) {\r\n\r\n this.modelPointRaw = modelPointRaw;\r\n\r\n this.viewPointLastRaw = viewPoint;\r\n this.modelPointLastRaw = modelPointRaw;\r\n }\r\n else {\r\n\r\n // We need to come up with a proper modelPointRaw to continue the movement\r\n this.modelPointRaw = interpolatingExtension( viewPoint, this.viewPointFirstRaw, this.viewPointLastRaw,\r\n this.modelPointFirstRaw, this.modelPointLastRaw );\r\n }\r\n\r\n this.docPointRaw = view.modelToDoc(this.modelPointRaw,this.docIslandRaw);\r\n\r\n return this.trackData();\r\n },\r\n\r\n trackData() {\r\n return {\r\n modelIsland : this.modelIsland,\r\n docIsland : this.docIsland,\r\n docPoint : this.docPoint,\r\n modelPointRaw : this.modelPointRaw,\r\n modelIslandRaw : this.modelIslandRaw,\r\n docIslandRaw : this.docIslandRaw,\r\n docPointRaw : this.docPointRaw,\r\n };\r\n },\r\n\r\n move(event) {\r\n this.event = event;\r\n return this.retargetedEvent;\r\n }\r\n};\r\n\r\n\r\n\r\n// Move3D helper to track the mouse starting from a given doc island\r\n// and following it even if it goes out it or the model\r\n\r\nexport const TextureTracker = function( { view, event, viewPoint, modelPoint }, docIsland ) {\r\n\r\n const docPoint = view.modelToDoc(modelPoint,docIsland);\r\n const modelIsland = view.modelIslandFor(docIsland);\r\n\r\n assign( this, { view,\r\n\r\n event,\r\n eventDown: event,\r\n\r\n // Points following the original island\r\n // This is used for almost all tools\r\n modelPoint,\r\n modelIsland,\r\n docIsland,\r\n docPoint,\r\n\r\n // Points that jumps between islands, useful for move operations\r\n modelPointRaw : modelPoint,\r\n modelIslandRaw : modelIsland,\r\n docIslandRaw : docIsland,\r\n docPointRaw : docPoint,\r\n\r\n started: false,\r\n });\r\n\r\n this.retargetedEventDown = this.retargetedEvent;\r\n};\r\n\r\nTextureTracker.prototype = {\r\n\r\n get retargetedEvent() {\r\n return this.event.retarget(this.retargetedEventDown,this);\r\n },\r\n\r\n track() {\r\n\r\n const { view, originalEvent } = this.event;\r\n\r\n const modelPoint = view.modelPoint(originalEvent);\r\n\r\n const { eventDown, docIsland } = this;\r\n\r\n if( modelPoint && ! modelPoint.isEqual(eventDown.modelPoint) ) {\r\n this.started = true;\r\n }\r\n\r\n if( ! this.started ) {\r\n return this.trackData();\r\n }\r\n\r\n this.modelPoint = modelPoint;\r\n this.docPoint = view.modelToDoc(modelPoint,docIsland);\r\n\r\n // Raw properties\r\n\r\n\r\n if( view.modelPointIsOut(modelPoint,this.modelIslandRaw) ) {\r\n\r\n const docIslandRaw = view.topDocIslandAtModel(modelPoint);\r\n if( docIslandRaw && docIslandRaw.page === docIsland.page ) {\r\n this.modelIslandRaw = view.modelIslandAt(modelPoint);\r\n this.docIslandRaw = docIslandRaw;\r\n }\r\n }\r\n\r\n this.modelPointRaw = modelPoint;\r\n this.docPointRaw = view.modelToDoc(modelPoint,this.docIslandRaw);\r\n\r\n return this.trackData();\r\n },\r\n\r\n trackData() {\r\n return {\r\n modelIsland : this.modelIsland,\r\n docIsland : this.docIsland,\r\n docPoint : this.docPoint,\r\n modelPointRaw : this.modelPointRaw,\r\n modelIslandRaw : this.modelIslandRaw,\r\n docIslandRaw : this.docIslandRaw,\r\n docPointRaw : this.docPointRaw,\r\n };\r\n },\r\n\r\n move(event) {\r\n this.event = event;\r\n return this.retargetedEvent;\r\n }\r\n};\r\n\r\n\r\nfunction interpolatingExtension( newFrom, firstFrom, lastFrom, firstTo, lastTo ) {\r\n\r\n if( firstFrom.isEqual( lastFrom ) ) {\r\n return lastTo.clone();\r\n }\r\n\r\n const\r\n last_firstFrom = lastFrom .minus( firstFrom ),\r\n last_firstFrom_norm = last_firstFrom.norm(),\r\n last_firstFrom_n = last_firstFrom.scaled( 1 / last_firstFrom_norm ),\r\n new_firstFrom = newFrom .minus( firstFrom ),\r\n\r\n dotProductFrom = Point.dotProduct( last_firstFrom, new_firstFrom ),\r\n\r\n ap = last_firstFrom_n.scaled( dotProductFrom / last_firstFrom_norm ),\r\n alpha = ap.norm() / last_firstFrom_norm * ( dotProductFrom >= 0 ? 1 : -1 ),\r\n\r\n bp = new_firstFrom.minus( ap ),\r\n beta = ( bp.norm() / last_firstFrom_norm ) *\r\n ( Point.dotProduct( bp, last_firstFrom.perpendicular(-1) ) >= 0 ? -1 : 1 ),\r\n\r\n last_firstTo = lastTo .minus( firstTo ),\r\n adp = last_firstTo.scaled(alpha),\r\n bdp = last_firstTo.perpendicular(-1).scaled(beta);\r\n\r\n return firstTo .plus(adp) .plus(bdp);\r\n}\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/move3d.js\n **/","import { Config } from 'config';\r\n\r\nimport { assign, defaults } from 'lodash';\r\n\r\nimport { dot } from 'gear';\r\n\r\nimport { Matrix, Frame, designLayersFrom, Figures,\r\n docIslandsFrom, docToModelMatrix,\r\n textureIslandName } from 'cdl';\r\n\r\nimport { TextureComposition, Plugin } from '../view';\r\n\r\nconst { filterProcessed } = Figures;\r\n\r\n\r\nfunction processedDocIslandsFor( page, modelIsland ) {\r\n // filterProcessed( filter( docIslandsFrom(page), isDocIslandFor(modelIsland) ) );\r\n const modelIslandName = textureIslandName(modelIsland);\r\n const pageDocIslands = docIslandsFrom(page);\r\n const docIslands = [];\r\n for( let pdi = 0, pdiEnd = pageDocIslands.length; pdi < pdiEnd; ++pdi ) {\r\n const island = pageDocIslands[pdi];\r\n if( island.processed() && textureIslandName(island) === modelIslandName ) {\r\n docIslands.push( island );\r\n }\r\n }\r\n return docIslands;\r\n}\r\n\r\nexport const TextureViewComposition = TextureComposition.extend({ typeName: 'TextureViewComposition',\r\n\r\n clearComposedCanvas() {\r\n if( ! this.canvas3D ) { // No need to clear the canvas in case the texture is used for a canvas3D\r\n this.callParent();\r\n }\r\n },\r\n\r\n // Overwrite drawPlugin to add the logic of rendering each plugin\r\n // once for every texture island\r\n drawPlugin( view, plugin, name, context ) {\r\n\r\n\r\n\r\n if( ! view._modelReady ){\r\n return; // There isn't a Doc3D properly loaded yet\r\n }\r\n\r\n if( ! plugin.somethingToDraw() ) {\r\n return; // Optimization\r\n }\r\n\r\n const { model } = view;\r\n const { target } = plugin;\r\n\r\n if( target === 'view' || target === 'model' ) {\r\n\r\n this.callParent(view,plugin,name,context);\r\n\r\n }\r\n else {\r\n\r\n const transformModel = view.getViewPortTransform();\r\n\r\n const drawConfig = view.drawConfig();\r\n\r\n const { modelIslands } = model;\r\n for( let i = 0, iEnd = modelIslands.length; i < iEnd; ++ i ) {\r\n const modelIsland = modelIslands[i];\r\n\r\n const config = assign({ view, context, transformModel, modelIsland },drawConfig);\r\n\r\n context.save();\r\n\r\n if( ! Config.clipTest1 ) {\r\n const bleedModelIsland = model.bleedModelIslandWithName(textureIslandName(modelIsland));\r\n bleedModelIsland.polyregions[0].clipContext(context,transformModel);\r\n }\r\n\r\n if( target === 'textureIslands' ) {\r\n\r\n // The draw function is called once for every texture island clipped to it\r\n this.drawPlugin2D(view,plugin,name,assign({\r\n transform: transformModel\r\n },config));\r\n\r\n }\r\n else { // target === 'document'\r\n\r\n const { pages } = view;\r\n for( let p = 0, pEnd = pages.length; p < pEnd; ++p ) {\r\n const page = pages[p];\r\n\r\n const docIslands = processedDocIslandsFor(page,modelIsland);\r\n\r\n for( let d = 0, dEnd = docIslands.length; d < dEnd; ++d ) {\r\n const docIsland = docIslands[d];\r\n\r\n // Optimization, no need to draw the plugin if it doesn't overlap with this docIsland\r\n if( plugin.needsToDrawFor( docIsland ) ) {\r\n\r\n const transformDoc = Matrix.m( transformModel, docToModelMatrix(docIsland,modelIsland) );\r\n\r\n // The draw function is called, once for every pair texture island <-> docisland\r\n this.drawPlugin2D(view,plugin,name,assign({\r\n docIsland,\r\n transformDoc,\r\n transform: transformDoc\r\n },config));\r\n }\r\n }\r\n }\r\n }\r\n\r\n context.restore(); // Remove clipping\r\n }\r\n }\r\n }\r\n\r\n});\r\n\r\n\r\nPlugin.TextureViewRenderer = Plugin.extend({ typeName: 'TextureViewRendererPlugin',\r\n\r\n name: 'renderer',\r\n\r\n drawTo_color: ['document'],\r\n\r\n // The draw function will be called, once for every texture island and all\r\n // drawing will be clipped to it.\r\n // We need to do it like this to respect the z-order of figures\r\n target: 'textureIslands',\r\n\r\n redrawFigure( /*view,figure*/) {\r\n this.redraw();\r\n },\r\n\r\n draw( config ) {\r\n\r\n const { view, context, transformModel, modelIsland } = config;\r\n const { doc } = view;\r\n\r\n // First draw the islands background, using the top most island across all pages\r\n // Transparent brushes will show the color texture underneath\r\n {\r\n const backgroundDocIsland = doc.topDocIslandFor(modelIsland);\r\n if( backgroundDocIsland && backgroundDocIsland.processed() ) {\r\n const transformDoc = Matrix.m( transformModel, docToModelMatrix(backgroundDocIsland,modelIsland) );\r\n const { brush } = backgroundDocIsland.polyregions[0];\r\n if( ! ( brush._empty || ( brush.typeName === 'Brush' && brush.color.alpha === 0 ) ) ) {\r\n view.figureView( backgroundDocIsland ).draw( context, transformDoc, defaults({ transformDoc, ignorePen: true }, config ) );\r\n }\r\n }\r\n }\r\n\r\n // Then draw all the figures, respecting their z-order in their layers and\r\n // between pages. The last page will have the top most figures\r\n\r\n const { pages } = doc;\r\n for( let p = 0, pEnd = pages.length; p < pEnd; ++p ) {\r\n const page = doc.pages[p];\r\n\r\n const docIslands = processedDocIslandsFor(page,modelIsland);\r\n\r\n const designLayers = designLayersFrom(page);\r\n for( let l = 0, lEnd = designLayers.length; l < lEnd; ++l ) {\r\n const layer = designLayers[l];\r\n\r\n layer.beforeDraw(context,config);\r\n\r\n const figures = filterProcessed(layer.figures);\r\n\r\n for( let i = 0, iEnd = figures.length; i < iEnd; ++i ) {\r\n const figure = figures[i];\r\n\r\n for( let di = 0, diEnd = docIslands.length; di < diEnd; ++di ) {\r\n const docIsland = docIslands[di];\r\n\r\n // Optimization, no need to draw the figure if it doesn't overlap with this docIsland\r\n if( Frame.areOverlapping( docIsland.frame_(), figure.frame_() ) ) {\r\n\r\n // Change the transformDoc of the config\r\n const transformDoc = Matrix.m( transformModel, docToModelMatrix(docIsland,modelIsland) );\r\n const figureView = view.figureView(figure);\r\n\r\n if( figureView ) {\r\n figureView.draw( context, transformDoc, defaults({ transformDoc },config) );\r\n }\r\n else {\r\n console.log('[Error] FigureView is undefined');\r\n }\r\n\r\n if( view.showPin ) { // Do it as a config option\r\n dot(context,figure.pin,view.viewDeltaToTexture(3),transformDoc,'#ffffff','#222222',view.viewDeltaToTexture(4));\r\n }\r\n }\r\n }\r\n }\r\n\r\n layer.afterDraw(context,config);\r\n }\r\n }\r\n }\r\n});\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/texture-view-scene.js\n **/","import { Config } from 'config';\r\n\r\nimport { Deferred, resolve } from 'gear';\r\n\r\nimport { forEach } from 'lodash';\r\n\r\nimport { Point, Document, FigureConditions_Mixin } from 'cdl';\r\n\r\nimport { View3D } from './view3d';\r\n\r\nimport { Plugin,\r\n DocumentView_Mixin,\r\n SelectedFigures_Mixin,\r\n InteractiveView_Mixin } from '../view';\r\n\r\nimport { Doc3D_Model_Mixin } from './doc3d-model-mixin';\r\n\r\nimport { TextureView } from './texture-view';\r\n\r\nimport { parseGeometry } from './three-util';\r\n\r\nimport { Object3D, EmptyObject3D } from './object3d';\r\n\r\nimport { Tracker3D } from './move3d';\r\n\r\nexport const StaticCanvas3D = View3D.extend( DocumentView_Mixin )\r\n .extend( SelectedFigures_Mixin )\r\n .extend( FigureConditions_Mixin )\r\n .extend( Doc3D_Model_Mixin ).extend({\r\n\r\n typeName: 'StaticCanvas3D',\r\n\r\n Properties: {\r\n\r\n document: { type: 'Document', def: null, owned: false, set( v ) { this._setDoc(v); } },\r\n\r\n textureView: { type: 'TextureView', def: null, owned: false, set( v ) { this._setTextureView(v); } },\r\n\r\n // [TODO]\r\n documentFilter: { type: 'function', def: null }, // Used by load$ by id\r\n },\r\n\r\n // [TODO]\r\n // backSideDarkFactor\r\n // backSideColor\r\n\r\n get model() {\r\n return this.doc.model3D;\r\n },\r\n\r\n get modelData() {\r\n return this.doc.modelData3D;\r\n },\r\n\r\n get textureSize() {\r\n return this.textureView.textureSize;\r\n },\r\n set textureSize( textureSize_ ) {\r\n this.textureView.textureSize = textureSize_;\r\n },\r\n\r\n isIddle() {\r\n return this.callParent() && this.modelData && !this._transformMode;\r\n },\r\n\r\n insertViewPlugins( plugins ) {\r\n\r\n plugins.insert( 0, [\r\n Plugin.PluginsLayer(),\r\n Plugin.FigureAnnotations(), // [TODO] Let users add this on demand\r\n\r\n Plugin.Tools()\r\n ]);\r\n\r\n this.callParent(plugins);\r\n },\r\n\r\n annotate(/* ...params */) {\r\n return this.figureAnnotations.annotate(...arguments);\r\n },\r\n unannotate(/* ...params */) {\r\n return this.figureAnnotations.unannotate(...arguments);\r\n },\r\n clearAnnotations(/* ...params */) {\r\n return this.figureAnnotations.clearAnnotations(...arguments);\r\n },\r\n\r\n\r\n add( figures, config ) {\r\n const selector = ( config && config.layer ) || this.destinationLayerSelector;\r\n if( selector ) {\r\n this.setActiveLayerBy(selector);\r\n }\r\n return this.callParent(figures,config);\r\n },\r\n\r\n setActiveLayerBy( selector ) {\r\n const { doc } = this;\r\n let layer = doc.activePage.layerBy(selector);\r\n if( layer ) {\r\n this.activeLayer = layer;\r\n }\r\n return this;\r\n },\r\n\r\n\r\n figureView( figure ) {\r\n return this.textureView.figureView(figure);\r\n },\r\n\r\n get figureViews() {\r\n return this.textureView.figureViews;\r\n },\r\n\r\n figureTextureTypes() {\r\n return this.textureView.figureTextureTypes();\r\n },\r\n\r\n asFastOffset( offset ) {\r\n return this.textureView.asFastOffset(offset);\r\n },\r\n\r\n docPoint( event, docIsland ) {\r\n const modelPoint = this.modelPoint(event);\r\n return modelPoint && this.modelToDoc(modelPoint,docIsland);\r\n },\r\n\r\n modelPoint( event ) {\r\n const uv = this.uvPoint( event );\r\n return uv && this.uvToModel(uv);\r\n },\r\n\r\n uvPoint( event ) {\r\n return this.viewToUV( this.viewPoint(event) );\r\n },\r\n\r\n viewToUV( viewPoint ) {\r\n const { camera, width, height } = this;\r\n const uv = this.object3D.uvFromViewPoint( camera, viewPoint, width, height );\r\n this.computeViewToTextureScale(); // [TODO] We should move this to a better place\r\n return uv;\r\n },\r\n\r\n viewDeltaToDoc( delta ) {\r\n return this.textureView.textureDeltaToDoc(this.viewDeltaToTexture(delta));\r\n },\r\n\r\n computeViewToTextureScale( viewPoint ) {\r\n if( ! this._viewToTextureScale ) {\r\n const { camera, width, height } = this;\r\n if( ! viewPoint ) {\r\n viewPoint = new Point(width/2,height/2); // Stable... always the same on each model load\r\n }\r\n const uv = this.object3D.uvFromViewPoint( camera, viewPoint, width, height );\r\n if( uv ) {\r\n const dist = 5;\r\n const testPoints = [\r\n viewPoint.translated_( 0, dist),\r\n viewPoint.translated_( 0,-dist),\r\n viewPoint.translated_( dist, 0),\r\n viewPoint.translated_(-dist, 0)\r\n ];\r\n const scales = [];\r\n forEach( testPoints, point => {\r\n const uv_close = this.object3D.uvFromViewPoint( camera, point, width, height );\r\n if( uv_close ) {\r\n scales.push( uv_close.minus(uv).norm() / dist );\r\n }\r\n });\r\n const uv_scale = Math.min(...scales); // [TODO] Use median ?\r\n const scale = uv_scale * this.textureSize; // * 1.25;\r\n\r\n const { controls } = this;\r\n const c = camera.position.clone().sub(controls.target).length();\r\n this._viewToTextureScale = {\r\n scale,\r\n dist: c,\r\n width, height\r\n };\r\n }\r\n\r\n this.redraw('tools','plugins');\r\n }\r\n },\r\n\r\n postResize() {\r\n this.callParent();\r\n if( ! this.textureView._previewingResize ) {\r\n this._viewToTextureScale = null;\r\n this.computeViewToTextureScale();\r\n }\r\n if (Config.keepLowerLeftCornerAsOrigin) {\r\n this.center = this.viewCenter;\r\n }\r\n },\r\n\r\n resetToOrigin() {\r\n this.zoom = 1;\r\n this.center = this.viewCenter;\r\n },\r\n\r\n viewDeltaToTexture( viewDelta ) {\r\n\r\n const { camera, controls, textureView } = this;\r\n const c = camera.position.clone().sub(controls.target).length();\r\n\r\n const s = this._viewToTextureScale;\r\n if( s ) {\r\n\r\n const rs = viewDelta * s.scale * ( this.textureView.width / this.textureSize ) *\r\n Math.sqrt((c+0.1)/s.dist); // Account for zooming\r\n\r\n // if( viewDelta === 1 ) { console.log(rs+' / '+c+' / '+s.dist+' / '+this.textureView.width+' / '+s.scale); }\r\n return rs;\r\n }\r\n\r\n const rse = viewDelta * 3 * (textureView.width/this.textureSize) * Math.sqrt((c+0.1)/200) ; //this.controls.zoom;\r\n\r\n // if( viewDelta === 1 ) { console.log('E: '+ rse+' / '+c+' / '+this.textureView.width); }\r\n return rse;\r\n },\r\n\r\n // Useful for default place where to add figures\r\n get frontDocIsland() {\r\n // [TODO] Use raytracing\r\n return this.doc.topDocIsland; // this.doc.topDocIslandFor( this.model.modelIslands[0] );\r\n },\r\n\r\n // [TODO] The coupling between Canvas3D and its TextureView is now quite complex\r\n // This is mainly to let plugins talk with the textureView or the canvas3D as if\r\n // their will be the same thing. It may be better at the end to leave the plugins\r\n // initialized with the Canvas3D, and forward the drawing instead of the way it\r\n // is done now.\r\n redraw() {\r\n this.textureView.redraw(...arguments);\r\n this.callParent(...arguments);\r\n },\r\n\r\n get textureZoom() {\r\n return this.textureView.zoom;\r\n },\r\n\r\n // Load by id or set document, the promise finished when the 3D model is shown\r\n load$( doc ) {\r\n\r\n this.fireEvent('loading',this);\r\n\r\n if( typeof doc === 'string' ) {\r\n\r\n return Document.load$(doc) .then( loadedDoc =>{\r\n return resolve( this._documentFilter ? this._documentFilter( loadedDoc ) : true ) .then( () => {\r\n\r\n return this._setDoc(loadedDoc);\r\n }); });\r\n }\r\n\r\n return this._setDoc(doc);\r\n },\r\n\r\n onLoaded() {\r\n this._readyDeferred.resolve(this.doc);\r\n this._readyDeferred = null;\r\n this.fireEvent('loaded',this);\r\n },\r\n\r\n get controlsEnabled() {\r\n return this.controls.enabled;\r\n },\r\n set controlsEnabled( state ) {\r\n const { controls } = this;\r\n if( state === false && this._controlsPanning ) {\r\n controls.onMouseUp();\r\n this._controlsPanning = false;\r\n }\r\n controls.enabled = state;\r\n },\r\n setOrbitMode() {\r\n this.controls.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };\r\n },\r\n setPanMode() {\r\n this.controls.mouseButtons = { ORBIT: THREE.MOUSE.RIGHT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.LEFT };\r\n },\r\n get isOrbitMode(){return this.controls.mouseButtons.ORBIT == THREE.MOUSE.LEFT},\r\n get isPanMode(){return this.controls.mouseButtons.PAN == THREE.MOUSE.LEFT},\r\n init( config = {} ) {\r\n\r\n this._viewToTextureScale = null;\r\n\r\n this.addEvents(\r\n 'loading',\r\n 'loaded'\r\n );\r\n\r\n this.initSelection(config);\r\n\r\n this._initTextureView(config);\r\n\r\n this._readyDeferred = new Deferred();\r\n\r\n this._setDoc( new Document() );\r\n\r\n this.callParent(config);\r\n },\r\n\r\n ready$() {\r\n if (this._readyDeferred == null)\r\n this._readyDeferred = new Deferred();\r\n return this._readyDeferred.promise;\r\n },\r\n\r\n onObject3DChange() {\r\n // console.log('object 3D change');\r\n this.redraw('3D');\r\n },\r\n\r\n draw$() {\r\n\r\n return this.ready$() .then( () => {\r\n return this.object3D.ready$() .then( () => {\r\n return this.textureView.draw$() .then( () => {\r\n this.draw();\r\n });});});\r\n },\r\n\r\n optimizePreview() {\r\n this.textureView.optimizePreview();\r\n },\r\n optimizeZoomPreview() {\r\n if( this.updateTextureOnZoom ) {\r\n this.textureView.optimizePreview();\r\n }\r\n },\r\n\r\n _initTextureView( config = {} ) {\r\n\r\n let textureView = this._textureView;\r\n if( ! textureView ) {\r\n textureView = this._ownedTexture = new TextureView({\r\n canvas3D: this,\r\n selection: this.selection,\r\n autoDraw: false\r\n });\r\n\r\n // We need the final width to be a power of 2 so\r\n // Three.js can use THREE.LinearMipMapLinearFilter\r\n // Accept forced URL param\r\n textureView.textureSize = Config.textureSize3D ? parseInt(Config.textureSize3D) :\r\n config.textureSize ? config.textureSize\r\n : 2048;\r\n }\r\n else {\r\n textureView.canvas3D = this;\r\n }\r\n this._setTextureView(textureView);\r\n },\r\n\r\n syncModelData3D() {\r\n\r\n // console.log('syncModelData3D');\r\n\r\n this.object3D.un(this);\r\n this.object3D.dispose();\r\n\r\n const { modelData } = this;\r\n if( modelData ) {\r\n\r\n this.object3D = new Object3D({\r\n geometry: parseGeometry( modelData.data ),\r\n textureView: this.textureView,\r\n threeScene: this.threeScene,\r\n });\r\n this.object3D.on('change',this.onObject3DChange,this);\r\n\r\n this._viewToTextureScale = null;\r\n\r\n // Update camera and light position\r\n\r\n this.zoomToFront();\r\n }\r\n else {\r\n this.object3D = new EmptyObject3D();\r\n }\r\n },\r\n\r\n on_model3dchanged() {\r\n this.syncModelData3D();\r\n this.callParent(...arguments);\r\n },\r\n\r\n on_modeldata3dchanged() {\r\n this.syncModelData3D();\r\n this.callParent(...arguments);\r\n },\r\n\r\n\r\n _setTextureView( textureView ) {\r\n\r\n // Unlink old texture\r\n const old = this.textureView;\r\n if( old ) {\r\n this._unlinkTextureView(old);\r\n }\r\n\r\n // Link new one\r\n this._textureView = textureView;\r\n\r\n if( this.object3D ) {\r\n this.object3D.textureView = textureView;\r\n this.redraw('3D');\r\n }\r\n\r\n textureView.on({\r\n change : this.textureView_on_change.bind(this),\r\n draw : this.textureView_on_draw.bind(this),\r\n redraw : this.textureView_on_redraw.bind(this),\r\n });\r\n },\r\n _unlinkTextureView( textureView ) {\r\n textureView.un(this);\r\n const { _ownedTexture } = this;\r\n if( _ownedTexture ) {\r\n _ownedTexture.dispose();\r\n this._ownedTexture = null;\r\n }\r\n },\r\n textureView_on_change( textureView, ...params ) {\r\n this.fireEvent('change',this,...params);\r\n },\r\n textureView_on_draw( textureView, ...params ) {\r\n this.fireEvent('draw',this,...params);\r\n },\r\n textureView_on_redraw( textureView, ...params ) {\r\n this.fireEvent('redraw',this,...params);\r\n },\r\n\r\n\r\n _setDoc( doc ) {\r\n\r\n const old = this.doc;\r\n\r\n if( old === doc ) {\r\n return resolve(); // Nothing to do\r\n }\r\n if( old ) {\r\n this.unlinkDoc(old);\r\n }\r\n this._document = doc;\r\n this.linkDoc(doc);\r\n\r\n const { textureView } = this;\r\n\r\n // Clear the current object3D\r\n if( this.object3D ) {\r\n this.object3D.un(this);\r\n this.object3D.dispose();\r\n this.object3D = new EmptyObject3D();\r\n this.redraw('3D');\r\n }\r\n\r\n if (Config.keepLowerLeftCornerAsOrigin) {\r\n this.center = this.viewCenter;\r\n }\r\n\r\n return textureView._setDoc( doc ) .then( () => {\r\n\r\n if( ! doc.is3D ) {\r\n return;\r\n }\r\n\r\n if (this._readyDeferred == null)\r\n this._readyDeferred = new Deferred();\r\n\r\n return doc.loadModelData3D$() .then( () => {\r\n\r\n this.syncModelData3D();\r\n\r\n this.onLoaded();\r\n\r\n }); });\r\n },\r\n\r\n dispose() {\r\n if( this.textureView ) {\r\n this._unlinkTextureView(this.textureView);\r\n }\r\n this.callParent();\r\n },\r\n\r\n pluginDirectDomEventHandling({ target }) {\r\n return target === 'view';\r\n },\r\n\r\n createEventTracker( event, docIsland ) {\r\n return new Tracker3D(event,docIsland);\r\n }\r\n});\r\n\r\n\r\nexport const Canvas3D = StaticCanvas3D.extend( InteractiveView_Mixin ).extend({\r\n\r\n typeName: 'Canvas3D',\r\n\r\n Properties: {\r\n\r\n },\r\n\r\n});\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/canvas3d.js\n **/","/* globals THREE */\r\n\r\nimport { Config } from 'config';\r\n\r\nimport { debounce, bind, assign } from 'lodash';\r\n\r\nimport { resolve, deg2rad } from 'gear';\r\n\r\nimport { Matrix } from 'cdl';\r\n\r\nimport { View, Composition, Plugin, fastThrottle } from '../view';\r\n\r\nimport { OrbitConstraint, OrbitControls } from './orbit-controls';\r\n\r\nimport { CameraAnimation, cameraToString, cameraStateFromString } from './three-util';\r\n\r\nimport { EmptyObject3D } from './object3d';\r\n\r\nconst { Vector3 } = THREE;\r\n\r\n\r\nexport const View3D = View.extend({\r\n\r\n typeName: 'View3D',\r\n\r\n Properties: {\r\n\r\n autoRotate: { type: 'boolean',\r\n get() {\r\n return this.controls.autoRotate;\r\n },\r\n set( v ) {\r\n this.controls.autoRotate = v;\r\n },\r\n },\r\n\r\n updateTextureOnZoom: { type: 'boolean', def: true },\r\n\r\n zoomToScale: { type: 'number', def: 1.0 },\r\n\r\n lightOffset: { type: 'number', def: 0 },\r\n\r\n selectAndDragEnabled: { type: 'boolean', def: false }\r\n },\r\n\r\n // [TODO]\r\n // backSideDarkFactor\r\n // backSideColor\r\n\r\n get is3D() {\r\n return true;\r\n },\r\n\r\n isIddle() {\r\n return !this.autoRotate && !this.cameraAnim && this.controls && this.controls.isIddle();\r\n },\r\n\r\n createScene() {\r\n // textures are managed by the textureView, and tools are drawn there\r\n return new Composition({ textureType: '3D', main: true });\r\n },\r\n\r\n // [TODO] Eliminate setter for textureView, or re-link the plugins\r\n // to the new one\r\n\r\n // Plugins that target the model and document are linked to the textureView\r\n initPlugin(plugin) {\r\n if( plugin.target === 'view' ) {\r\n this.callParent(plugin);\r\n }\r\n else {\r\n this.textureView.addPlugin(plugin);\r\n }\r\n },\r\n\r\n pluginsToDraw() {\r\n // return filter(this._plugins,{ target: 'view' });\r\n const r = [];\r\n const { plugins } = this;\r\n for( let k = 0, kEnd = plugins.length; k < kEnd; ++k ) {\r\n const plugin = plugins[k];\r\n if( plugin.target === 'view' ) {\r\n r.push( plugin );\r\n }\r\n }\r\n return r;\r\n },\r\n\r\n insertViewPlugins( plugins ) {\r\n plugins.insert( 0, [\r\n Plugin.Renderer3D(),\r\n Plugin.ViewControls3D(),\r\n ]);\r\n },\r\n\r\n initThreeScene() {\r\n\r\n // Create the scene and set the scene size.\r\n const threeScene = this.threeScene = new THREE.Scene();\r\n\r\n // Create a camera, zoom it out from the model a bit, and add it to the scene.\r\n const camera = this.camera = new THREE.PerspectiveCamera(45, this.width / this.height, 0.1, 4000);\r\n camera.position.set(100, 100, 200);\r\n\r\n // Allow to move the camera around the object, works exactly as OrbitControls but\r\n // without dealing with user interaction\r\n this.controls = new OrbitConstraint(camera);\r\n\r\n threeScene.add(camera);\r\n\r\n // Set the background color of the scene.\r\n // this._setBackgroundColor();\r\n\r\n this.addLights();\r\n\r\n this.updateSize();\r\n },\r\n\r\n addLights() {\r\n\r\n // We tried different light strategies and it was really difficult to get good results using\r\n // directional and spot lights. To much differences bettwen the light and dark regions.\r\n // Specially for a white background. The hemisphere light that we were using so far gives\r\n // the best result. But we change the way the light moves with the camera so we do not have\r\n // unreal bright spots in right in front of the camera.\r\n\r\n const { threeScene } = this;\r\n\r\n if( Config.lights === 'Old' ) {\r\n const light = this.light = new THREE.HemisphereLight(0xffffff, 0x808080, 1);\r\n light.position.set(100, 100, 200);\r\n\r\n threeScene.add(light);\r\n }\r\n else {\r\n\r\n if( THREE.REVISION === '73' ) {\r\n\r\n //if( Config.noHemisphereLight ) {\r\n // threeScene.add( new THREE.HemisphereLight( 0x111111, 0x444444 ) );\r\n //}\r\n\r\n threeScene.add( new THREE.AmbientLight( 0xa0a0a0, 0.1 ) );\r\n\r\n const light1 = this.light = new THREE.PointLight( 0xffffff, Config.lightPower ? parseFloat(Config.lightPower) : 0.4 );\r\n // var light2 = this.light2 = new THREE.PointLight( 0xffffff, 0.1 );\r\n // var light3 = this.light3 = new THREE.PointLight( 0xffffff, 0.1 );\r\n light1.position.set( -1000, 0, 2000 );\r\n // light2.position.set( -1000, 100, -2000 );\r\n // light3.position.set( 1000, -100, 2000 );\r\n\r\n const parent = this.camera;\r\n parent.add(light1);\r\n // parent.add(light2);\r\n // parent.add(light3);\r\n }\r\n else {\r\n\r\n let ambientLightPower = 0.3, light1Power = 0.6, light2Power = 0.3;\r\n if( Config.lightPower ) {\r\n var lightPowerF = Config.lightPower.split(',');\r\n ambientLightPower = parseFloat(lightPowerF[0]);\r\n light1Power = parseFloat(lightPowerF[1]);\r\n light2Power = parseFloat(lightPowerF[2]);\r\n }\r\n\r\n\r\n const lightAmbient = this.lightAmbient = new THREE.AmbientLight( 0xffffff, ambientLightPower );\r\n threeScene.add( lightAmbient );\r\n\r\n const light1 = this.light = new THREE.PointLight( 0xffffff, light1Power );\r\n const light2 = this.light2 = new THREE.PointLight( 0xffffff, light2Power );\r\n //const light3 = this.light3 = new THREE.PointLight( 0xffffff, 0.4 );\r\n light1.position.set( -1000, 0, 1000 );\r\n light2.position.set( 500, 1000, 1000 );\r\n //light3.position.set( 1000, -100, 2000 );\r\n\r\n const parent = this.camera;\r\n parent.add(light1);\r\n parent.add(light2);\r\n //parent.add(light3);\r\n }\r\n }\r\n },\r\n\r\n zoomToFit$() {\r\n this.zoomToFront();\r\n return resolve(this);\r\n },\r\n\r\n objectsBBox3D() {\r\n return this.object3D.bbox;\r\n },\r\n\r\n _zoomToFitCameraDistance() {\r\n\r\n const bb = this.objectsBBox3D(),\r\n objectSize = ( bb.max.y - bb.min.y );\r\n\r\n const { width, height, camera } = this;\r\n\r\n const fov = camera.fov * ( Math.PI / 180 );\r\n\r\n let distance = Math.abs( objectSize / Math.sin( fov / 2 ) ) * 0.6 / this._zoomToScale;\r\n if( width < height ) {\r\n distance *= Math.sqrt(height/width);\r\n }\r\n\r\n return distance;\r\n },\r\n\r\n _zoomToSide( dirX, dirY, dirZ, msTransition ) {\r\n const distance = this._zoomToFitCameraDistance();\r\n const pos = new Vector3(dirX,dirY,dirZ).normalize().multiplyScalar(distance);\r\n this._zoomToPos( pos, msTransition );\r\n },\r\n\r\n _zoomToPos( pos, msTransition ) {\r\n this.controls.autoRotate = false;\r\n this.setCameraState({ pos, target: new Vector3(0,0,0) },msTransition);\r\n },\r\n\r\n zoomToFront( msTransition ) {\r\n this._zoomToSide( 0.4, 0.2, 1, msTransition );\r\n },\r\n\r\n zoomToBack( msTransition ) {\r\n this._zoomToSide( 0.4, 0.2, -1, msTransition );\r\n },\r\n\r\n zoomToRight( msTransition ) {\r\n this._zoomToSide( 1, 0.2, 0.4, msTransition );\r\n },\r\n\r\n zoomToLeft( msTransition ) {\r\n this._zoomToSide( -1, 0.2, 0.4, msTransition );\r\n },\r\n\r\n rotateCameraRight( angle ) {\r\n this.rotateModelLeft(angle);\r\n },\r\n rotateCameraLeft( angle ) {\r\n this.rotateModelRight(angle);\r\n },\r\n rotateCameraDown( angle ) {\r\n this.rotateModelUp(angle);\r\n },\r\n rotateCameraUp( angle ) {\r\n this.rotateModelDown(angle);\r\n },\r\n\r\n rotateModelRight( angle ) {\r\n this.controls.rotateLeft( deg2rad(angle) );\r\n this._updateControls();\r\n },\r\n rotateModelLeft( angle ) {\r\n this.rotateModelRight(-angle);\r\n },\r\n rotateModelDown( angle ) {\r\n this.controls.rotateUp( deg2rad(angle) );\r\n this._updateControls();\r\n },\r\n rotateModelUp( angle ) {\r\n this.rotateModelDown(-angle);\r\n },\r\n\r\n zoomIn( scale ) {\r\n this.controls.dollyIn(scale);\r\n this._updateControls();\r\n },\r\n zoomOut( scale ) {\r\n this.controls.dollyOut(scale);\r\n this._updateControls();\r\n },\r\n\r\n _updateControls() {\r\n const { controls } = this;\r\n controls.autoRotate = false;\r\n controls.update();\r\n },\r\n\r\n\r\n get cameraStateString() {\r\n return cameraToString(this.camera,this.controls.target);\r\n },\r\n set cameraStateString( string ) {\r\n this.setCameraStateString( string, 1000 );\r\n },\r\n\r\n setCameraStateString( string, msTransition = 0 ){\r\n this.setCameraState( cameraStateFromString(string), msTransition );\r\n },\r\n setCameraState( state, msTransition = 0 ) {\r\n const { camera, controls } = this;\r\n if( msTransition === 0 ) {\r\n camera.position.copy( state.pos );\r\n controls.target.copy( state.target );\r\n camera.updateProjectionMatrix();\r\n controls.update();\r\n this.redraw('3D');\r\n }\r\n else {\r\n this.cameraAnim = new CameraAnimation({ camera, controls,\r\n ms: msTransition,\r\n to: state,\r\n });\r\n }\r\n },\r\n\r\n onOrbitControlChange() {\r\n this.redraw('3D');\r\n },\r\n\r\n triggerZoomEvents() {\r\n const { zoom } = this.controls;\r\n\r\n // [TODO] This should be responsability of each plugin, avoid invalidating\r\n // the tools layers if there isn't a tool\r\n this.redraw('plugins','tools');\r\n\r\n this.fireEvent('zoomupdated',this, zoom);\r\n this.fireEvent('change',this);\r\n const { textureView } = this;\r\n textureView.fireEvent('zoomupdated',textureView,zoom);\r\n textureView.fireEvent('change',textureView,zoom);\r\n },\r\n debouncedTriggerZoomEvents: debounce(function() {\r\n this.triggerZoomEvents();\r\n },500),\r\n\r\n onOrbitControlZoomUpdated() {\r\n if( this.updateTextureOnZoom ) {\r\n this.triggerZoomEvents();\r\n }\r\n else {\r\n this.debouncedTriggerZoomEvents();\r\n }\r\n },\r\n\r\n // This function is triggered once per animation frame\r\n // We are auto rotating and updating the camera animation here\r\n\r\n draw() {\r\n\r\n this.object3D.drawTextures();\r\n\r\n const { cameraAnim, controls } = this;\r\n\r\n if( this.autoRotate || cameraAnim ) {\r\n\r\n if( cameraAnim ) {\r\n if( ! cameraAnim.update() ) {\r\n this.cameraAnim = null;\r\n }\r\n }\r\n controls.update();\r\n this.redraw('3D');\r\n }\r\n\r\n if( this.object3D.animate( this.clock.getDelta() ) ) {\r\n this.redraw('3D');\r\n }\r\n\r\n this.callParent();\r\n },\r\n\r\n // This function is issued every time the 3D scene needs to be updated\r\n // by the Renderer3D plugin\r\n\r\n draw3D( renderer ) {\r\n const { object3D, camera } = this;\r\n // console.log('draw3D');\r\n // Create a dummy 3D object, so we always have something to show\r\n // It could also serve as a loading animation and simplify the code\r\n this.setLightPos();\r\n object3D.draw( renderer, camera );\r\n },\r\n\r\n get controlsEnabled() {\r\n return this.controls.enabled;\r\n },\r\n set controlsEnabled( state ) {\r\n const controls = this.controls;\r\n if( state === false && this._controlsPanning ) {\r\n controls.onMouseUp();\r\n this._controlsPanning = false;\r\n }\r\n controls.enabled = state;\r\n },\r\n\r\n // [Review]\r\n // You need to pass preserveDrawingBuffer at creation if you want to use this function\r\n image() {\r\n return this.canvas('3D').toDataURL(\"image/png\");\r\n },\r\n\r\n setLightPos() {\r\n\r\n const cameraPos = this.camera.position,\r\n lightOffset = this.lightOffset;\r\n\r\n if( Config.lights === 'Old' ) {\r\n\r\n const lightPos = this.light.position;\r\n if( lightOffset === 0 ) {\r\n lightPos.copy( cameraPos );\r\n }\r\n else {\r\n const bb = this.objectsBBox3D();\r\n\r\n const bb_max = bb.max,\r\n center = bb.center;\r\n\r\n const b = new Vector3(0,lightOffset,0);\r\n const c = new Vector3().subVectors(cameraPos,center);\r\n const n = new Vector3().crossVectors(b,c);\r\n const l = new Vector3().addVectors(center,n);\r\n\r\n l.y = bb_max.y;\r\n\r\n lightPos.copy( new Vector3().addVectors(cameraPos,new Vector3().addVectors(cameraPos,l)) );\r\n }\r\n }\r\n },\r\n\r\n updateSize(width,height) {\r\n this._previousZoomToFitDistance = this._zoomToFitCameraDistance();\r\n this.callParent(width,height);\r\n },\r\n\r\n // Called just before the resize events, after the sizing is done\r\n postResize() {\r\n const { camera, controls, width, height } = this;\r\n\r\n this.callParent();\r\n\r\n camera.aspect = width / height;\r\n camera.updateProjectionMatrix();\r\n\r\n // For width less than height aspect ratio, we need to move the camera manually to maintain\r\n // the same position of the object in the 3D view\r\n const newZoomToFitDistance = this._zoomToFitCameraDistance();\r\n camera.position.multiplyScalar( newZoomToFitDistance / this._previousZoomToFitDistance );\r\n camera.updateProjectionMatrix();\r\n\r\n controls.update();\r\n },\r\n\r\n fireResizeEvent() {\r\n this.textureView.fireResizeEvent();\r\n this.callParent();\r\n },\r\n\r\n init( config = {} ) {\r\n\r\n this.clock = new THREE.Clock();\r\n\r\n this.object3D = new EmptyObject3D();\r\n\r\n this.callParent(config);\r\n\r\n this.initThreeScene();\r\n },\r\n\r\n appendTo( domElement, id ) {\r\n\r\n this.callParent(domElement,id);\r\n\r\n // Upgrade OrbitConstraint to OrbitControls so that we can pan around with the mouse\r\n const controls = this.controls = new OrbitControls(this.camera,domElement);\r\n this._controlsPanning = false;\r\n\r\n // Disable panning, orbit looks weirds after using it\r\n assign( controls, {\r\n autoRotate : false,\r\n autoRotateSpeed : 5.0,\r\n enableKeys : false,\r\n enableDamping : true,\r\n dampingFactor : 0.96\r\n });\r\n\r\n controls.addEventListener('change',bind(this.onOrbitControlChange,this));\r\n controls.addEventListener('zoomupdated',bind(this.onOrbitControlZoomUpdated,this));\r\n\r\n return this;\r\n },\r\n\r\n // [TODO]\r\n\r\n getViewPortTransform() {\r\n return new Matrix();\r\n },\r\n});\r\n\r\n// We could simplify this by making OrbitControls a plugin\r\n\r\nPlugin.ViewControls3D = Plugin.extend({\r\n\r\n target: 'view',\r\n\r\n initPlugin() {\r\n this.panning = false;\r\n },\r\n\r\n on_pointerdown({ view, event }) {\r\n this.panning = true;\r\n view.controls.on_pointerdown(event);\r\n },\r\n\r\n on_pointermove: fastThrottle( function({ view, event }) {\r\n if( this.panning ) {\r\n view.controls.on_pointermove(event);\r\n }\r\n }, 10),\r\n\r\n on_pointerup({ view, event }) {\r\n if( this.panning ) {\r\n this.panning = false;\r\n view.controls.on_pointerup(event);\r\n }\r\n },\r\n\r\n on_mousewheel({ view, event }) {\r\n this.panning = false;\r\n view.controls.on_mousewheel(event);\r\n }\r\n});\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/view3d.js\n **/","/* globals THREE */\r\n\r\n\r\n/**\r\n* @author qiao / https://github.com/qiao\r\n* @author mrdoob / http://mrdoob.com\r\n* @author alteredq / http://alteredqualia.com/\r\n* @author WestLangley / http://github.com/WestLangley\r\n* @author erich666 / http://erichaines.com\r\n*/\r\n\r\n// Modified for Grafika\r\n// Expose OrbitConstraint\r\n\r\n\r\nexport function OrbitConstraint( object ) {\r\n\r\n\tthis.object = object;\r\n\r\n\t// \"target\" sets the location of focus, where the object orbits around\r\n\t// and where it pans with respect to.\r\n\tthis.target = new THREE.Vector3();\r\n\r\n\t// Limits to how far you can dolly in and out ( PerspectiveCamera only )\r\n\tthis.minDistance = 0;\r\n\tthis.maxDistance = Infinity;\r\n\r\n\t// Limits to how far you can zoom in and out ( OrthographicCamera only )\r\n\tthis.minZoom = 0;\r\n\tthis.maxZoom = Infinity;\r\n\r\n\t// How far you can orbit vertically, upper and lower limits.\r\n\t// Range is 0 to Math.PI radians.\r\n\tthis.minPolarAngle = 0; // radians\r\n\tthis.maxPolarAngle = Math.PI; // radians\r\n\r\n\t// How far you can orbit horizontally, upper and lower limits.\r\n\t// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\r\n\tthis.minAzimuthAngle = - Infinity; // radians\r\n\tthis.maxAzimuthAngle = Infinity; // radians\r\n\r\n\t// Set to true to enable damping (inertia)\r\n\t// If damping is enabled, you must call controls.update() in your animation loop\r\n\tthis.enableDamping = false;\r\n\tthis.dampingFactor = 0.25;\r\n\r\n\t////////////\r\n\t// internals\r\n\r\n\tvar scope = this;\r\n\r\n\tvar EPS = 0.000001;\r\n\r\n\t// Current position in spherical coordinate system.\r\n\tvar theta;\r\n\tvar phi;\r\n\r\n\t// Pending changes\r\n\tvar phiDelta = 0;\r\n\tvar thetaDelta = 0;\r\n\tvar scale = 1;\r\n this.scale = scale;\r\n\tvar panOffset = new THREE.Vector3();\r\n\tthis.zoomChanged = false;\r\n\r\n Object.defineProperty(this,'zoom',{\r\n get() {\r\n return this.scale;\r\n }\r\n });\r\n\r\n\t// API\r\n\r\n\tthis.getPolarAngle = function () {\r\n\r\n\t\treturn phi;\r\n\r\n\t};\r\n\r\n\tthis.getAzimuthalAngle = function () {\r\n\r\n\t\treturn theta;\r\n\r\n\t};\r\n\r\n\tthis.panToCenter = function( angle ){\r\n\t // Pan to center, it looks very strange to rotate the model when the view is not centered\r\n\t var target = this.target;\r\n\t var targetLengthSq = target.lengthSq();\r\n\t if( targetLengthSq > 0 ){\r\n\t if( targetLengthSq < 5 ){\r\n\t target.copy( new THREE.Vector3(0,0,0) );\r\n\t }\r\n\t else {\r\n\t target.copy( target.clone().multiplyScalar( 9.5/10 * ( 1 - Math.abs(angle) / (2*Math.PI) ) ) );\r\n\t }\r\n\t }\r\n\t};\r\n\r\n\tthis.rotateLeft = function ( angle ) {\r\n\r\n\t\tthetaDelta -= angle;\r\n\r\n this.panToCenter(angle);\r\n\t};\r\n\r\n\tthis.rotateUp = function ( angle ) {\r\n\r\n\t\tphiDelta -= angle;\r\n\r\n\t\tthis.panToCenter(angle);\r\n\t};\r\n\r\n\t// pass in distance in world space to move left\r\n\tthis.panLeft = function() {\r\n\r\n\t\tvar v = new THREE.Vector3();\r\n\r\n\t\treturn function panLeft ( distance ) {\r\n\r\n\t\t\tvar te = this.object.matrix.elements;\r\n\r\n\t\t\t// get X column of matrix\r\n\t\t\tv.set( te[ 0 ], te[ 1 ], te[ 2 ] );\r\n\t\t\tv.multiplyScalar( - distance );\r\n\r\n\t\t\tpanOffset.add( v );\r\n\r\n\t\t};\r\n\r\n\t}();\r\n\r\n\t// pass in distance in world space to move up\r\n\tthis.panUp = function() {\r\n\r\n\t\tvar v = new THREE.Vector3();\r\n\r\n\t\treturn function panUp( distance ) {\r\n\r\n\t\t\tvar te = this.object.matrix.elements;\r\n\r\n\t\t\t// get Y column of matrix\r\n\t\t\tv.set( te[ 4 ], te[ 5 ], te[ 6 ] );\r\n\t\t\tv.multiplyScalar( distance );\r\n\r\n\t\t\tpanOffset.add( v );\r\n\r\n\t\t};\r\n\r\n\t}();\r\n\r\n\t// pass in x,y of change desired in pixel space,\r\n\t// right and down are positive\r\n\tthis.pan = function ( deltaX, deltaY, screenWidth, screenHeight ) {\r\n\r\n\t\tif( scope.object instanceof THREE.PerspectiveCamera ) {\r\n\r\n\t\t\t// perspective\r\n\t\t\tvar position = scope.object.position;\r\n\t\t\tvar offset = position.clone().sub( scope.target );\r\n\t\t\tvar targetDistance = offset.length();\r\n\r\n\t\t\t// half of the fov is center to top of screen\r\n\t\t\ttargetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );\r\n\r\n\t\t\t// we actually don't use screenWidth, since perspective camera is fixed to screen height\r\n\t\t\tscope.panLeft( 2 * deltaX * targetDistance / screenHeight );\r\n\t\t\tscope.panUp( 2 * deltaY * targetDistance / screenHeight );\r\n\r\n\t\t} else if( scope.object instanceof THREE.OrthographicCamera ) {\r\n\r\n\t\t\t// orthographic\r\n\t\t\tscope.panLeft( deltaX * ( scope.object.right - scope.object.left ) / screenWidth );\r\n\t\t\tscope.panUp( deltaY * ( scope.object.top - scope.object.bottom ) / screenHeight );\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// camera neither orthographic or perspective\r\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tthis.dollyIn = function( dollyScale ) {\r\n\r\n this.zoomChanged = true;\r\n\r\n\t\tif( scope.object instanceof THREE.PerspectiveCamera ) {\r\n\r\n\t\t\tscale /= dollyScale;\r\n this.scale /= dollyScale;\r\n\r\n\t\t} else if( scope.object instanceof THREE.OrthographicCamera ) {\r\n\r\n\t\t\tscope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom * dollyScale ) );\r\n\t\t\tscope.object.updateProjectionMatrix();\r\n\r\n\t\t} else {\r\n\r\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tthis.dollyOut = function ( dollyScale ) {\r\n\r\n this.zoomChanged = true;\r\n\r\n\t\tif( scope.object instanceof THREE.PerspectiveCamera ) {\r\n\r\n\t\t\tscale *= dollyScale;\r\n this.scale *= dollyScale;\r\n\r\n\t\t} else if( scope.object instanceof THREE.OrthographicCamera ) {\r\n\r\n\t\t\tscope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / dollyScale ) );\r\n\t\t\tscope.object.updateProjectionMatrix();\r\n\r\n\t\t} else {\r\n\r\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tthis.update = function() {\r\n\r\n\t\tvar offset = new THREE.Vector3();\r\n\r\n\t\t// so camera.up is the orbit axis\r\n\t\tvar quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );\r\n\t\tvar quatInverse = quat.clone().inverse();\r\n\r\n\t\tvar lastPosition = new THREE.Vector3();\r\n\t\tvar lastQuaternion = new THREE.Quaternion();\r\n\r\n\t\treturn function () {\r\n\r\n\t\t\tvar position = this.object.position;\r\n\r\n\t\t\toffset.copy( position ).sub( this.target );\r\n\r\n\t\t\t// rotate offset to \"y-axis-is-up\" space\r\n\t\t\toffset.applyQuaternion( quat );\r\n\r\n\t\t\t// angle from z-axis around y-axis\r\n\r\n\t\t\ttheta = Math.atan2( offset.x, offset.z );\r\n\r\n\t\t\t// angle from y-axis\r\n\r\n\t\t\tphi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );\r\n\r\n\t\t\ttheta += thetaDelta;\r\n\t\t\tphi += phiDelta;\r\n\r\n\t\t\t// restrict theta to be between desired limits\r\n\t\t\ttheta = Math.max( this.minAzimuthAngle, Math.min( this.maxAzimuthAngle, theta ) );\r\n\r\n\t\t\t// restrict phi to be between desired limits\r\n\t\t\tphi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );\r\n\r\n\t\t\t// restrict phi to be betwee EPS and PI-EPS\r\n\t\t\tphi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );\r\n\r\n\t\t\tvar radius = offset.length() * scale;\r\n\r\n\t\t\t// restrict radius to be between desired limits\r\n\t\t\tradius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );\r\n\r\n\t\t\t// move target to panned location\r\n\t\t\tthis.target.add( panOffset );\r\n\r\n\t\t\toffset.x = radius * Math.sin( phi ) * Math.sin( theta );\r\n\t\t\toffset.y = radius * Math.cos( phi );\r\n\t\t\toffset.z = radius * Math.sin( phi ) * Math.cos( theta );\r\n\r\n\t\t\t// rotate offset back to \"camera-up-vector-is-up\" space\r\n\t\t\toffset.applyQuaternion( quatInverse );\r\n\r\n\t\t\tposition.copy( this.target ).add( offset );\r\n\r\n\t\t\tthis.object.lookAt( this.target );\r\n\r\n\t\t\tif( this.enableDamping === true ) {\r\n\r\n\t\t\t\tthetaDelta *= ( 1 - this.dampingFactor );\r\n\t\t\t\tphiDelta *= ( 1 - this.dampingFactor );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthetaDelta = 0;\r\n\t\t\t\tphiDelta = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscale = 1;\r\n\t\t\tpanOffset.set( 0, 0, 0 );\r\n\r\n\t\t\t// update condition is:\r\n\t\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\r\n\t\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\r\n\r\n\t\t\tif( this.zoomChanged ||\r\n\t\t\t\t lastPosition.distanceToSquared( this.object.position ) > EPS ||\r\n\t\t\t 8 * ( 1 - lastQuaternion.dot( this.object.quaternion ) ) > EPS ) {\r\n\r\n\t\t\t\tlastPosition.copy( this.object.position );\r\n\t\t\t\tlastQuaternion.copy( this.object.quaternion );\r\n\t\t\t\tthis.zoomChanged = false;\r\n\r\n\t\t\t\treturn true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn false;\r\n\r\n\t\t};\r\n\r\n\t}();\r\n}\r\n\r\n\r\n// This set of controls performs orbiting, dollying (zooming), and panning. It maintains\r\n// the \"up\" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is\r\n// supported.\r\n//\r\n// Orbit - left mouse / touch: one finger move\r\n// Zoom - middle mouse, or mousewheel / touch: two finger spread or squish\r\n// Pan - right mouse, or arrow keys / touch: three finter swipe\r\n\r\nexport const OrbitControls = function( object, domElement ) {\r\n\r\n\tvar constraint = new OrbitConstraint( object );\r\n\r\n\tthis.domElement = ( domElement !== undefined ) ? domElement : document;\r\n\r\n\t// API\r\n\r\n\tObject.defineProperty( this, 'constraint', {\r\n\r\n\t\tget: function() {\r\n\r\n\t\t\treturn constraint;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tthis.getPolarAngle = function () {\r\n\r\n\t\treturn constraint.getPolarAngle();\r\n\r\n\t};\r\n\r\n\tthis.getAzimuthalAngle = function () {\r\n\r\n\t\treturn constraint.getAzimuthalAngle();\r\n\r\n\t};\r\n\r\n\t// [Grafika]\r\n\r\n\tthis.panToCenter = function( angle ){\r\n\t\treturn constraint.panToCenter(angle);\r\n\t};\r\n\r\n\tthis.rotateLeft = function( angle ) {\r\n\t return constraint.rotateLeft(angle);\r\n\t};\r\n\r\n\tthis.rotateUp = function( angle ) {\r\n\t return constraint.rotateUp(angle);\r\n\t};\r\n\r\n\tthis.panLeft = function(distance) {\r\n\t\treturn constraint.panLeft(distance);\r\n\t};\r\n\r\n\tthis.panUp = function(distance) {\r\n\t\treturn constraint.panUp(distance);\r\n\t};\r\n\r\n\tthis.dollyIn = function ( dollyScale ) {\r\n\t return constraint.dollyIn(dollyScale);\r\n\t};\r\n\r\n\tthis.dollyOut = function ( dollyScale ) {\r\n\t return constraint.dollyOut(dollyScale);\r\n\t};\r\n\r\n\t// Set to false to disable this control\r\n\tthis.enabled = true;\r\n\r\n\t// center is old, deprecated; use \"target\" instead\r\n\tthis.center = this.target;\r\n\r\n\t// This option actually enables dollying in and out; left as \"zoom\" for\r\n\t// backwards compatibility.\r\n\t// Set to false to disable zooming\r\n\tthis.enableZoom = true;\r\n\tthis.zoomSpeed = 1.0;\r\n\r\n\t// Set to false to disable rotating\r\n\tthis.enableRotate = true;\r\n\tthis.rotateSpeed = 1.0;\r\n\r\n\t// Set to false to disable panning\r\n\tthis.enablePan = true;\r\n\tthis.keyPanSpeed = 7.0;\t// pixels moved per arrow key push\r\n\r\n\t// Set to true to automatically rotate around the target\r\n\t// If auto-rotate is enabled, you must call controls.update() in your animation loop\r\n\tthis.autoRotate = false;\r\n\tthis.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\r\n\r\n\t// Set to false to disable use of the keys\r\n\tthis.enableKeys = true;\r\n\r\n\t// The four arrow keys\r\n\tthis.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\r\n\r\n\t// Mouse buttons\r\n\tthis.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };\r\n\r\n\t////////////\r\n\t// internals\r\n\r\n\tvar scope = this;\r\n\r\n\tvar rotateStart = new THREE.Vector2();\r\n\tvar rotateEnd = new THREE.Vector2();\r\n\tvar rotateDelta = new THREE.Vector2();\r\n\r\n\tvar panStart = new THREE.Vector2();\r\n\tvar panEnd = new THREE.Vector2();\r\n\tvar panDelta = new THREE.Vector2();\r\n\r\n\tvar dollyStart = new THREE.Vector2();\r\n\tvar dollyEnd = new THREE.Vector2();\r\n\tvar dollyDelta = new THREE.Vector2();\r\n\r\n\tvar STATE = {\r\n NONE : - 1,\r\n ROTATE : 0,\r\n DOLLY : 1,\r\n PAN : 2,\r\n TOUCH_ROTATE : 3,\r\n TOUCH_DOLLY : 4,\r\n TOUCH_PAN : 5\r\n };\r\n\r\n\tvar state = STATE.NONE;\r\n\r\n\t// for reset\r\n\r\n\tthis.target0 = this.target.clone();\r\n\tthis.position0 = this.object.position.clone();\r\n\tthis.zoom0 = this.object.zoom;\r\n\r\n\t// events\r\n\r\n var zoomUpdatedEvent = { type: 'zoomupdated' };\r\n\tvar changeEvent = { type: 'change' };\r\n\tvar startEvent = { type: 'start' };\r\n\tvar endEvent = { type: 'end' };\r\n\r\n\t// pass in x,y of change desired in pixel space,\r\n\t// right and down are positive\r\n\tfunction pan( deltaX, deltaY ) {\r\n\r\n\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\r\n\r\n\t\tconstraint.pan( deltaX, deltaY, element.clientWidth, element.clientHeight );\r\n\r\n\t}\r\n\r\n\tthis.update = function () {\r\n\r\n\t\tif( this.autoRotate && state === STATE.NONE ) {\r\n\r\n\t\t\tconstraint.rotateLeft( getAutoRotationAngle() );\r\n\r\n\t\t}\r\n\r\n const { zoomChanged } = constraint;\r\n\r\n\t\tif( constraint.update() === true ) {\r\n\r\n if( zoomChanged ) {\r\n this.dispatchEvent( zoomUpdatedEvent );\r\n }\r\n\t\t\tthis.dispatchEvent( changeEvent );\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tthis.reset = function () {\r\n\r\n\t\tstate = STATE.NONE;\r\n\r\n\t\tthis.target.copy( this.target0 );\r\n\t\tthis.object.position.copy( this.position0 );\r\n\t\tthis.object.zoom = this.zoom0;\r\n\r\n\t\tthis.object.updateProjectionMatrix();\r\n\t\tthis.dispatchEvent( changeEvent );\r\n this.dispatchEvent( zoomUpdatedEvent );\r\n\r\n\t\tthis.update();\r\n\r\n\t};\r\n\r\n\tfunction getAutoRotationAngle() {\r\n\r\n\t\treturn 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\r\n\r\n\t}\r\n\r\n\tfunction getZoomScale() {\r\n\r\n\t\treturn Math.pow( 0.95, scope.zoomSpeed );\r\n\r\n\t}\r\n\r\n // [grafika]\r\n /*\r\n function onDblClick( event ) {\r\n event.preventDefault();\r\n\t scope.autoRotate = ! scope.autoRotate;\r\n }\r\n */\r\n\r\n\r\n function handleTouchStartDolly( event ) {\r\n\r\n \t//console.log( 'handleTouchStartDolly' );\r\n\r\n \tvar distance = ( event.pointers[1].current .minus( event.pointers[0].current ) ).norm();\r\n\r\n \tdollyStart.set( 0, distance );\r\n\r\n }\r\n\r\n\tfunction handleTouchMoveDolly( event ) {\r\n\r\n\t\t//console.log( 'handleTouchMoveDolly' );\r\n\r\n var distance = ( event.pointers[1].current .minus( event.pointers[0].current ) ).norm();\r\n\r\n\t\tdollyEnd.set( 0, distance );\r\n\r\n\t\tdollyDelta.subVectors( dollyEnd, dollyStart );\r\n\r\n\t\tif ( dollyDelta.y > 0 ) {\r\n\r\n\t\t\tconstraint.dollyOut( getZoomScale() );\r\n\r\n\t\t} else if ( dollyDelta.y < 0 ) {\r\n\r\n\t\t\tconstraint.dollyIn( getZoomScale() );\r\n\r\n\t\t}\r\n\r\n\t\tdollyStart.copy( dollyEnd );\r\n\r\n\t\tscope.update();\r\n\r\n\t}\r\n\r\n this.isIddle = function() {\r\n return state === STATE.NONE;\r\n };\r\n\r\n // [grafika]\r\n\tthis.on_pointerdown = function({ event, pointers }) {\r\n\r\n if( pointers.length === 2 ) {\r\n\r\n if( scope.enableZoom ) {\r\n handleTouchStartDolly( event );\r\n state = STATE.TOUCH_DOLLY;\r\n }\r\n\r\n return;\r\n }\r\n\r\n\t\tif( scope.enabled === false ) {\r\n return;\r\n }\r\n\r\n\t\t// [grafika]\r\n\t\tscope.autoRotate = false;\r\n\r\n // [grafika]\r\n\t\t// event.preventDefault();\r\n\r\n\t\tif( event.button === scope.mouseButtons.ORBIT ) {\r\n\r\n\t\t\tif( scope.enableRotate === false ) {\r\n return;\r\n }\r\n\r\n\t\t\tstate = STATE.ROTATE;\r\n\r\n\t\t\trotateStart.set( event.clientX, event.clientY );\r\n\r\n\t\t} else if( event.button === scope.mouseButtons.ZOOM ) {\r\n\r\n\t\t\tif( scope.enableZoom === false ) {\r\n return;\r\n }\r\n\r\n\t\t\tstate = STATE.DOLLY;\r\n\r\n\t\t\tdollyStart.set( event.clientX, event.clientY );\r\n\r\n\t\t} else if( event.button === scope.mouseButtons.PAN ) {\r\n\r\n\t\t\tif( scope.enablePan === false ) {\r\n return;\r\n }\r\n\r\n\t\t\tstate = STATE.PAN;\r\n\r\n\t\t\tpanStart.set( event.clientX, event.clientY );\r\n\r\n\t\t}\r\n\r\n\t\tif( state !== STATE.NONE ) {\r\n\r\n // [grafika]\r\n\t\t\t// document.addEventListener( 'mousemove', onMouseMove, false );\r\n\t\t\t// document.addEventListener( 'mouseup', onMouseUp, false );\r\n\t\t\tscope.dispatchEvent( startEvent );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n // [grafika]\r\n\tthis.on_pointermove = function( event ) {\r\n\r\n if( state === STATE.TOUCH_DOLLY && event.pointers.length !== 2 ) {\r\n state = STATE.NONE;\r\n return;\r\n }\r\n\r\n\t\tif( scope.enabled === false ) {\r\n return;\r\n }\r\n\r\n // [grafika]\r\n\t\t// event.preventDefault();\r\n\r\n\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\r\n\r\n if( state === STATE.TOUCH_DOLLY ) {\r\n\r\n if( scope.enableZoom === false ) {\r\n return;\r\n }\r\n\r\n event.view.optimizeZoomPreview();\r\n\r\n handleTouchMoveDolly(event);\r\n }\r\n\t\telse if( state === STATE.ROTATE ) {\r\n\r\n\t\t\tif( scope.enableRotate === false ) {\r\n return;\r\n }\r\n\r\n\t\t\trotateEnd.set( event.clientX, event.clientY );\r\n\t\t\trotateDelta.subVectors( rotateEnd, rotateStart );\r\n\r\n\t\t\t// rotating across whole screen goes 360 degrees around\r\n\t\t\tconstraint.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );\r\n\r\n\t\t\t// rotating up and down along whole screen attempts to go 360, but limited to 180\r\n\t\t\tconstraint.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );\r\n\r\n\t\t\trotateStart.copy( rotateEnd );\r\n\r\n\t\t} else if( state === STATE.DOLLY ) {\r\n\r\n\t\t\tif( scope.enableZoom === false ) {\r\n return;\r\n }\r\n\r\n event.view.optimizeZoomPreview();\r\n\r\n\t\t\tdollyEnd.set( event.clientX, event.clientY );\r\n\t\t\tdollyDelta.subVectors( dollyEnd, dollyStart );\r\n\r\n\t\t\tif( dollyDelta.y > 0 ) {\r\n\r\n \tconstraint.dollyIn( getZoomScale() );\r\n\r\n\t\t\t} else if( dollyDelta.y < 0 ) {\r\n\r\n \tconstraint.dollyOut( getZoomScale() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tdollyStart.copy( dollyEnd );\r\n\r\n\t\t} else if( state === STATE.PAN ) {\r\n\r\n\t\t\tif( scope.enablePan === false ) {\r\n return;\r\n }\r\n\r\n\t\t\tpanEnd.set( event.clientX, event.clientY );\r\n\t\t\tpanDelta.subVectors( panEnd, panStart );\r\n\r\n\t\t\tpan( panDelta.x, panDelta.y );\r\n\r\n\t\t\tpanStart.copy( panEnd );\r\n\r\n\t\t}\r\n\r\n\t\tif( state !== STATE.NONE ) {\r\n scope.update();\r\n }\r\n\r\n\t};\r\n\r\n // [grafika]\r\n\tthis.on_pointerup = function( /* event */ ) {\r\n\r\n\t\tif( scope.enabled === false ) {\r\n return;\r\n }\r\n\r\n // [grafika]\r\n\t\t// document.removeEventListener( 'mousemove', onMouseMove, false );\r\n\t\t// document.removeEventListener( 'mouseup', onMouseUp, false );\r\n if( state !== STATE.NONE ) {\r\n scope.dispatchEvent( endEvent );\r\n \t\tstate = STATE.NONE;\r\n }\r\n\r\n\t};\r\n\r\n\tthis.on_mousewheel = function( event ) {\r\n\r\n\t\tif( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) {\r\n return;\r\n }\r\n\r\n\t\tevent.preventDefault();\r\n\t\tevent.stopPropagation();\r\n\r\n event.view.optimizeZoomPreview();\r\n\r\n\t\tvar delta = 0;\r\n\r\n\t\tif( event.wheelDelta !== undefined ) {\r\n\r\n\t\t\t// WebKit / Opera / Explorer 9\r\n\r\n\t\t\tdelta = event.wheelDelta;\r\n\r\n\t\t} else if( event.detail !== undefined ) {\r\n\r\n\t\t\t// Firefox\r\n\r\n\t\t\tdelta = - event.detail;\r\n\r\n\t\t}\r\n\r\n\t\tif( delta > 0 ) {\r\n\r\n\t\t\tconstraint.dollyOut( getZoomScale() );\r\n\r\n\t\t} else if( delta < 0 ) {\r\n\r\n\t\t\tconstraint.dollyIn( getZoomScale() );\r\n\r\n\t\t}\r\n\r\n\t\tscope.update();\r\n\t\tscope.dispatchEvent( startEvent );\r\n\t\tscope.dispatchEvent( endEvent );\r\n\r\n\t};\r\n\r\n // [grafika] Use our own input system\r\n\r\n\tthis.dispose = function() {\r\n\r\n\t};\r\n\r\n\t// [grafika]\r\n\r\n\t// force an update at start\r\n\tthis.update();\r\n\r\n};\r\n\r\nOrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );\r\nOrbitControls.prototype.constructor = OrbitControls;\r\n\r\nObject.defineProperties( OrbitControls.prototype, {\r\n\r\n\tobject: {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.object;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\ttarget: {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.target;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tconsole.warn( 'OrbitControls: target is now immutable. Use target.set() instead.' );\r\n\t\t\tthis.constraint.target.copy( value );\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n zoom: {\r\n get() {\r\n return this.constraint.zoom;\r\n }\r\n },\r\n\r\n\tminDistance : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.minDistance;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.minDistance = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tmaxDistance : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.maxDistance;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.maxDistance = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tminZoom : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.minZoom;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.minZoom = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tmaxZoom : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.maxZoom;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.maxZoom = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tminPolarAngle : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.minPolarAngle;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.minPolarAngle = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tmaxPolarAngle : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.maxPolarAngle;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.maxPolarAngle = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tminAzimuthAngle : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.minAzimuthAngle;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.minAzimuthAngle = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tmaxAzimuthAngle : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.maxAzimuthAngle;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.maxAzimuthAngle = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tenableDamping : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.enableDamping;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.enableDamping = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tdampingFactor : {\r\n\r\n\t\tget() {\r\n\r\n\t\t\treturn this.constraint.dampingFactor;\r\n\r\n\t\t},\r\n\r\n\t\tset( value ) {\r\n\r\n\t\t\tthis.constraint.dampingFactor = value;\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n} );\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/orbit-controls.js\n **/","/* globals THREE */\r\n\r\nimport { Config } from 'config';\r\n\r\nimport { assign, now } from 'lodash';\r\n\r\nimport { Point } from 'cdl';\r\n\r\nconst { Vector3 } = THREE;\r\n\r\nconst _parseFloat = parseFloat;\r\n\r\nexport function setObjectPosition(object,bbCenter) {\r\n object.position.set(-bbCenter.x,-bbCenter.y,-bbCenter.z);\r\n object.matrixWorldNeedsUpdate = true;\r\n}\r\n\r\nfunction n2s(n) {\r\n return n.toFixed(4);\r\n}\r\n\r\nexport function vector3ToString(v) {\r\n return n2s(v.x)+' '+n2s(v.y)+' '+n2s(v.z);\r\n}\r\n\r\nexport function vector3FromString( string ) {\r\n const s = string.split(' ');\r\n return new Vector3(_parseFloat(s[0]),_parseFloat(s[1]),_parseFloat(s[2]));\r\n}\r\n\r\nexport function rotationToString(v) {\r\n return n2s(v.x)+' '+n2s(v.y)+' '+n2s(v.z)+' '+v.order;\r\n}\r\n\r\nexport function cameraToString(camera,target) {\r\n return vector3ToString(camera.position)+','+rotationToString(camera.rotation)+','+vector3ToString(target);\r\n}\r\n\r\nexport function cameraStateFromString( string ) {\r\n const parts = string.split(',');\r\n return {\r\n pos : vector3FromString( parts[0] ),\r\n target : vector3FromString( parts[2] )\r\n };\r\n}\r\n\r\nfunction properFaceNormal(face) {\r\n if( face ) {\r\n const face_normal = face.normal;\r\n if( face_normal && face_normal.lengthSq() === 0 ) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\nfunction properVertexNormal(face) {\r\n if( face ) {\r\n const vertexNormal = face.vertexNormals[0];\r\n if( vertexNormal && vertexNormal.lengthSq() === 0 ) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\nexport function processGeometry(geometry/*,divisions*/) {\r\n\r\n const smooth = geometry; // Clone THREE.GeometryUtils.clone( geometry );\r\n\r\n // Next, we need to merge vertices to clean up any unwanted vertex.\r\n // smooth.mergeVertices();\r\n\r\n if( ! Config.useBufferGeometry ) {\r\n\r\n const face0 = smooth.faces[0],\r\n face1 = smooth.faces[1];\r\n\r\n const computeFaceNormals = Config.computeFaceNormals;\r\n if( computeFaceNormals === 'Forced' ||\r\n ( computeFaceNormals === 'Auto' && ( ! properFaceNormal(face0) || ! properFaceNormal(face1) ) ) ) {\r\n\r\n console.log(\"Computing face normals...\");\r\n smooth.computeFaceNormals();\r\n }\r\n\r\n const computeVertexNormals = Config.computeVertexNormals;\r\n if( computeVertexNormals === 'Forced' ||\r\n ( computeVertexNormals === 'Auto' && ( ! properVertexNormal(face0) || ! properVertexNormal(face1) ) ) ) {\r\n console.log(\"Computing vertex normals...\");\r\n smooth.computeVertexNormals();\r\n }\r\n\r\n /*\r\n if( divisions > 0 ) {\r\n\r\n // Create a new instance of the modifier and pass the number of divisions.\r\n const modifier = new THREE.SubdivisionModifier(divisions);\r\n\r\n // Apply the modifier to our cloned geometry.\r\n modifier.modify( smooth );\r\n\r\n smooth.uvsNeedsUpdate = true;\r\n }\r\n */\r\n }\r\n\r\n return smooth;\r\n}\r\n\r\nexport const CameraAnimation = function(config){\r\n assign(this,config);\r\n assign(this,{\r\n start: now(),\r\n from: {\r\n pos: config.camera.position.clone(),\r\n target: config.controls.target.clone()\r\n }\r\n });\r\n this.finished = false;\r\n};\r\nCameraAnimation.prototype = {\r\n\r\n update(){\r\n\r\n if( this.finished ){\r\n return false;\r\n }\r\n const { controls, camera, to, from, start, ms } = this;\r\n\r\n const\r\n\r\n t = now(),\r\n\r\n ellapsed = t-start,\r\n\r\n to_pos = to.pos , from_pos = from.pos,\r\n to_target = to.target, from_target = from.target;\r\n\r\n if( ellapsed >= ms ) {\r\n\r\n camera.position.copy(to_pos);\r\n controls.target.copy(to_target);\r\n controls.update();\r\n this.finished = true;\r\n\r\n return false;\r\n }\r\n else {\r\n\r\n const\r\n\r\n current = ellapsed / ms,\r\n\r\n // The next target is a direct interpolation between from and to targets\r\n\r\n nextTarget = to.target.clone().sub(from_target).multiplyScalar(current).add(from_target),\r\n\r\n // The nextPos y is a direct interpolation, x and z moves in an circle around the model\r\n\r\n from_xz = new Point(from_pos.x-from_target.x,from_pos.z-from_target.z),\r\n to_xz = new Point( to_pos.x- to_target.x, to_pos.z- to_target.z),\r\n\r\n theta_from = from_xz.angle_rad(),\r\n theta_delta = Point.turnAngle_rad( from_xz, to_xz ),\r\n\r\n theta = theta_from + current * theta_delta,\r\n\r\n from_radius = from_xz.norm(),\r\n to_radius = to_xz.norm(),\r\n\r\n radius = (to_radius-from_radius)*current+from_radius,\r\n\r\n nextPos = (new Vector3( radius * Math.cos( theta ), 0, radius * Math.sin( theta ) )).add(nextTarget);\r\n\r\n nextPos.y = (to_pos.y-from_pos.y)*current+from_pos.y;\r\n\r\n camera.position.copy(nextPos);\r\n controls.target.copy(nextTarget);\r\n controls.update();\r\n }\r\n return true;\r\n }\r\n};\r\n\r\nexport function parseGeometry( json ) {\r\n\r\n const loader = new THREE.JSONLoader();\r\n\r\n let originalGeometry = loader.parse(json).geometry;\r\n\r\n if( ! Config.useBufferGeometry && originalGeometry ) {\r\n if( originalGeometry instanceof THREE.BufferGeometry ) {\r\n originalGeometry = new THREE.Geometry().fromBufferGeometry( originalGeometry );\r\n }\r\n }\r\n\r\n const smooth3D = Config.smooth3D;\r\n return processGeometry( originalGeometry, smooth3D ? parseInt(smooth3D) : 0 );\r\n}\r\n\r\nexport function uvFromViewPoint( object, camera, viewPoint, width, height ) {\r\n\r\n camera.updateMatrixWorld();\r\n camera.updateProjectionMatrix();\r\n\r\n const vector = new Vector3( ( viewPoint.x / width ) * 2 - 1, - ( viewPoint.y / height ) * 2 + 1, 0.5 );\r\n\r\n vector.unproject(camera);\r\n\r\n const raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );\r\n\r\n const intersects = raycaster.intersectObject( object, true );\r\n\r\n if( intersects.length > 0 ) {\r\n\r\n const uv = intersects[0].uv;\r\n return uv ? new Point(uv.x,uv.y) : null;\r\n }\r\n return null;\r\n}\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/three-util.js\n **/","/* globals THREE */\r\n\r\nimport { Config } from 'config';\r\n\r\nimport { forEach } from 'lodash';\r\n\r\nimport { Base, resolve, Deferred } from 'gear';\r\n\r\nimport { setObjectPosition, uvFromViewPoint } from './three-util';\r\n\r\n\r\n\r\nfunction setMaterialTexture( material, textureType, textureMap, texture ) {\r\n\r\n material[textureType+'Map'] = texture;\r\n\r\n if( texture ) {\r\n\r\n const scale = textureMap ? textureMap.scale : 1;\r\n const wrap = textureMap ? textureMap.wrap : 'Stretch';\r\n const repeat = textureMap && wrap !== 'Stretch' ? textureMap.repeat : 1;\r\n\r\n material[textureType+'Scale'] = textureType === 'normal' ? new THREE.Vector2(scale,scale) : scale;\r\n\r\n texture.wrapS = texture.wrapT = repeat > 1 ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;\r\n texture.repeat.set( repeat, repeat );\r\n texture.minFilter = repeat > 1 ? THREE.NearestMipMapLinearFilter : THREE.LinearMipMapLinearFilter;\r\n\r\n const map = material[textureType+'MapSlot'];\r\n if( map ) {\r\n map.uvTransform = repeat > 1;\r\n map.uvRepeat.x = repeat;\r\n map.uvRepeat.y = repeat;\r\n }\r\n\r\n }\r\n}\r\n\r\n// A dummy object to avoid null checks, this could also be used later to\r\n// create a 3D loading animation\r\n\r\nexport const Object3DBase = Base.extend({\r\n init() {\r\n this.addEvents('change');\r\n },\r\n animate(/* delta */) {\r\n\r\n }\r\n});\r\n\r\n\r\nexport const EmptyObject3D = Object3DBase.extend({\r\n dispose() { },\r\n drawTextures() { },\r\n draw(/* renderer, camera */){ },\r\n init() {\r\n this.bbox = {\r\n min: { x: -100, y: -100, z: -100 },\r\n max: { x: 100, y: 100, z: 100 }\r\n };\r\n },\r\n uvFromViewPoint(/* camera, viewPoint, width, height */) {\r\n return null;\r\n },\r\n ready$() {\r\n return resolve();\r\n }\r\n});\r\n\r\n\r\n// Two sided object, using an opaque material for the interior\r\n// We use two steps rendering to be able to avoid z-order artifacts\r\n// The back object is first rendered as a background, then the front object\r\n// is rendered on top effectively making the front object always be on top\r\n// for all visible zones\r\n\r\nexport const Object3D = Object3DBase.extend({\r\n\r\n Properties: {\r\n textureView: { type: 'TextureView', owned: false, def: null, set( textureView ) { this._setTextureView(textureView); } },\r\n geometry: { type: 'geometry', owned: false },\r\n\r\n threeScene: { type: 'THREE.Scene', owned: false, def: null },\r\n },\r\n\r\n get backSideColor() {\r\n return this.textureView.backSideColor;\r\n },\r\n\r\n getThreeTexture( textureType ) {\r\n return this.textureView.getThreeTexture(textureType);\r\n },\r\n\r\n // This is called for each animation frame, it will render what is needed\r\n drawTextures() {\r\n const { textureView } = this;\r\n if( textureView && ! textureView.autoDraw ) {\r\n textureView.draw();\r\n }\r\n },\r\n\r\n init( config ) {\r\n\r\n this.callParent(config);\r\n\r\n this._forcedMapReady = null;\r\n\r\n // Inititalize materials\r\n this._setTextureView( this.textureView );\r\n\r\n this.createThreeObject();\r\n },\r\n\r\n uvFromViewPoint( camera, viewPoint, width, height ) {\r\n return uvFromViewPoint( this.object, camera, viewPoint, width, height );\r\n },\r\n\r\n animate( delta ) {\r\n if( this.mixer ) {\r\n this.mixer.update( 0.8 * delta );\r\n return true;\r\n }\r\n return false;\r\n },\r\n\r\n createThreeObject() {\r\n\r\n const { geometry, threeScene, material, materialBack } = this;\r\n\r\n // Use BufferGeometry, an efficient and GPU friendly data structure\r\n // This may not be the best for animations, we need to further explore this\r\n const objectGeometry = Config.useBufferGeometry ? new THREE.BufferGeometry().fromGeometry(geometry) : geometry ;\r\n\r\n const backSideType = this._currentBackSideType = Config.backSide3D !== 'TwoSteps' ? Config.backSide3D :\r\n ( this.textureView.model.materials[0].backSide === 'None' ? 'None' : 'TwoSteps' );\r\n\r\n switch( backSideType ) {\r\n\r\n case 'Animation':\r\n\r\n // Make sure we are using a regular Geometry\r\n\r\n const animGeometry = geometry instanceof THREE.BufferGeometry ? new THREE.Geometry().fromBufferGeometry(geometry) : geometry;\r\n\r\n if( animGeometry.bones ) {\r\n this.object = new THREE.SkinnedMesh( animGeometry, material );\r\n material.skinning = true;\r\n }\r\n else {\r\n this.object = new THREE.Mesh( animGeometry, material );\r\n }\r\n\r\n material.morphTargets = true;\r\n\r\n this.mixer = new THREE.AnimationMixer( this.object );\r\n const { animations, morphTargets } = geometry;\r\n if( animGeometry.bones && animations && animations.length > 0 ) {\r\n // Add bones animation\r\n\t\t\t\t const bonesClip = geometry.animations[0];\r\n const bonesAction = this.mixer.clipAction(bonesClip);\r\n bonesAction.play();\r\n }\r\n if( morphTargets && morphTargets.length > 1 ) {\r\n const facesClip = THREE.AnimationClip.CreateFromMorphTargetSequence( 'morphAnimation', morphTargets, morphTargets.length-1 );\r\n const facesAction = this.mixer.clipAction(facesClip);\r\n facesAction.play();\r\n }\r\n\r\n break;\r\n\r\n case 'None':\r\n\r\n this.object = new THREE.Mesh( geometry, material );\r\n break;\r\n\r\n case 'MultiMaterial':\r\n\r\n // This method can produce artifacts. From Three.js r69 onwards the artifacts\r\n // are more notorious. Some apps may choose to use these option because of performance\r\n this.object = THREE.SceneUtils.createMultiMaterialObject( objectGeometry, [ material, materialBack ] );\r\n break;\r\n\r\n default: // 'TwoSteps'\r\n\r\n // This is the best way we found til the moment to avoid back side artifacts\r\n // We create two objects, one with each material. To render the scene we first\r\n // hide the main object and then render again with the back side hidden.\r\n\r\n this.objectBack = new THREE.Mesh( objectGeometry, materialBack );\r\n\r\n this.object = new THREE.Mesh( objectGeometry, material);\r\n\r\n break;\r\n }\r\n\r\n const { object, objectBack } = this;\r\n\r\n objectGeometry.computeBoundingBox();\r\n const bb = this.bbox = objectGeometry.boundingBox.clone();\r\n const bbCenter = { x: ( bb.min.x + bb.max.x ) / 2 ,\r\n y: ( bb.min.y + bb.max.y ) / 2 ,\r\n z: ( bb.min.z + bb.max.z ) / 2 };\r\n\r\n if( objectBack ) {\r\n setObjectPosition(objectBack,bbCenter);\r\n }\r\n\r\n setObjectPosition(object,bbCenter);\r\n\r\n bb.min.x -= bbCenter.x; bb.max.x -= bbCenter.x;\r\n bb.min.y -= bbCenter.y; bb.max.y -= bbCenter.y;\r\n bb.min.z -= bbCenter.z; bb.max.z -= bbCenter.z;\r\n\r\n if( objectBack ) {\r\n threeScene.add(objectBack);\r\n }\r\n threeScene.add(object);\r\n },\r\n\r\n dispose() {\r\n const { threeScene, object, objectBack } = this;\r\n\r\n threeScene.remove(object);\r\n if( objectBack ) {\r\n threeScene.remove(objectBack);\r\n }\r\n },\r\n\r\n _setTextureView( textureView ) {\r\n\r\n this._textureView = textureView;\r\n\r\n if( ! this.object ){\r\n this.createMaterialBack();\r\n this.createMaterial();\r\n }\r\n else {\r\n this.onTextureChange();\r\n this.onBackSideColorChange();\r\n }\r\n\r\n textureView.on({\r\n 'drawcomplete': this.invalidateTexture,\r\n 'synctextures': this.onTextureChange\r\n }, this );\r\n },\r\n\r\n invalidateTexture() {\r\n // console.log('drawcomplete');\r\n this.fireEvent('change');\r\n },\r\n\r\n onBackSideColorChange() {\r\n if( this.materialBack ) {\r\n this.materialBack.color.setHex( this.backSideColor.rgbHex );\r\n }\r\n },\r\n\r\n onTextureChange() {\r\n // console.log('on texture change');\r\n const { material, materialBack } = this;\r\n\r\n if( ! material ) {\r\n return;\r\n }\r\n\r\n material.map = this.getThreeTexture('color');\r\n\r\n let transparent = false;\r\n\r\n if( ! ( Config.tiledBumpMap || Config.tiledNormalMap ) ) {\r\n\r\n forEach(['normal','bump','specular','displacement','alpha'], textureType => {\r\n const textureMap = this.textureView.getFixedTextureMap(textureType),\r\n threeTexture = this.getThreeTexture(textureType);\r\n\r\n setMaterialTexture( material, textureType, textureMap, threeTexture );\r\n\r\n if( textureType === 'alpha' ) {\r\n transparent = true;\r\n\r\n if( materialBack ) {\r\n setMaterialTexture( materialBack, textureType, textureMap, threeTexture );\r\n }\r\n\r\n materialBack.needsUpdate = true;\r\n }\r\n });\r\n\r\n }\r\n material.transparent = transparent;\r\n if( materialBack ) {\r\n materialBack.transparent = transparent;\r\n }\r\n\r\n material.needsUpdate = true;\r\n this.invalidateTexture();\r\n },\r\n\r\n createMaterial() {\r\n\r\n /*\r\n this.material = new THREE.MeshLambertMaterial({\r\n color: 0xf80505,\r\n side: THREE.FrontSide\r\n });\r\n return;\r\n */\r\n\r\n const materialType = Config.threeMaterialType ? ('Mesh'+Config.threeMaterialType+'Material') : 'MeshPhongMaterial';\r\n\r\n if( materialType === 'MeshPhongMaterial' ) {\r\n this.material = new THREE[ materialType ]({\r\n side: THREE.FrontSide,\r\n shading: THREE.SmoothShading,\r\n reflectivity: Config.reflectivity || 0,\r\n specular: 0x000000,\r\n shininess: Config.shininess || 0\r\n });\r\n }\r\n else {\r\n this.material = new THREE[ materialType ]({\r\n side: THREE.FrontSide,\r\n roughness: Config.roughness ? parseFloat( Config.roughness ) : 0.76,\r\n metalness: Config.metalness ? parseFloat( Config.metalness ) : 0.0\r\n });\r\n }\r\n\r\n // Testing\r\n const alphaMap = Config.alphaMap;\r\n if( alphaMap ) {\r\n // load a texture, set wrap mode to repeat\r\n const loader = new THREE.TextureLoader();\r\n loader.crossOrigin = '';\r\n const texture = loader.load( alphaMap, () => {\r\n this.invalidateTexture();\r\n });\r\n\r\n texture.wrapS = THREE.RepeatWrapping;\r\n texture.wrapT = THREE.RepeatWrapping;\r\n const repeatS = Config.tiledBumpMapRepeat || Config.tiledMapRepeat;\r\n const repeat = repeatS ? parseInt(repeatS) : 16;\r\n texture.repeat.set( repeat, repeat );\r\n\r\n const setAlphaMap = material => {\r\n material.alphaMap = texture;\r\n material.transparent = true;\r\n material.needsUpdate = true;\r\n const map = material.alphaMapSlot;\r\n if( map ) {\r\n map.uvTransform = true;\r\n map.uvRepeat.x = repeat;\r\n map.uvRepeat.y = repeat;\r\n }\r\n\r\n };\r\n\r\n setAlphaMap(this.material);\r\n if( this.materialBack ) {\r\n setAlphaMap(this.materialBack);\r\n }\r\n }\r\n\r\n const tiledMap = Config.tiledBumpMap || Config.tiledNormalMap;\r\n if( tiledMap ) {\r\n\r\n this._forcedMapReady = new Deferred();\r\n\r\n // load a texture, set wrap mode to repeat\r\n var onLoad = () => {\r\n this.invalidateTexture();\r\n this._forcedMapReady.resolve();\r\n };\r\n\r\n const loader = new THREE.TextureLoader();\r\n loader.crossOrigin = '';\r\n const texture = loader.load( tiledMap, onLoad, undefined, onLoad );\r\n\r\n texture.wrapS = THREE.RepeatWrapping;\r\n texture.wrapT = THREE.RepeatWrapping;\r\n\r\n const repeatS = Config.tiledBumpMapRepeat || Config.tiledMapRepeat;\r\n const repeat = repeatS ? parseInt(repeatS) : 16;\r\n texture.repeat.set( repeat, repeat );\r\n\r\n texture.minFilter = THREE.NearestMipMapLinearFilter;\r\n\r\n const { tiledMapScale } = Config;\r\n const { material } = this;\r\n let map;\r\n if( Config.tiledBumpMap ) {\r\n material.bumpMap = texture;\r\n if( tiledMapScale ) {\r\n material.bumpScale = parseFloat(tiledMapScale);\r\n }\r\n map = material.bumpMapSlot;\r\n }\r\n else {\r\n material.normalMap = texture;\r\n if( tiledMapScale ) {\r\n const scale = parseFloat(tiledMapScale);\r\n material.normalScale = new THREE.Vector2( scale, scale );\r\n }\r\n map = material.normalMapSlot;\r\n }\r\n\r\n map.uvTransform = true;\r\n map.uvRepeat.x = repeat;\r\n map.uvRepeat.y = repeat;\r\n }\r\n\r\n this.onTextureChange();\r\n },\r\n\r\n ready$() {\r\n const deferred = this._forcedMapReady;\r\n return deferred ? deferred.promise : resolve();\r\n },\r\n\r\n createMaterialBack() {\r\n\r\n this.materialBack = new THREE.MeshLambertMaterial({\r\n color: this.backSideColor.rgbHex,\r\n side: THREE.BackSide\r\n });\r\n },\r\n\r\n draw( renderer, camera ){\r\n\r\n const { threeScene, object, objectBack } = this;\r\n\r\n if( this._currentBackSideType === 'TwoSteps' ) {\r\n\r\n objectBack.visible = true;\r\n object.visible = false;\r\n\r\n renderer.render(threeScene,camera);\r\n\r\n objectBack.visible = false;\r\n object.visible = true;\r\n\r\n renderer.autoClear = false;\r\n }\r\n\r\n renderer.render(threeScene,camera);\r\n\r\n renderer.autoClear = true;\r\n }\r\n});\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/object3d.js\n **/","import { assign, isPlainObject } from 'lodash';\r\n\r\nimport { resolve } from 'gear';\r\n\r\nimport { g$ } from '../view';\r\n\r\nimport { Canvas3D } from './canvas3d';\r\n\r\nlet canvas3D = null;\r\n\r\nfunction _thumbnailImage$( config ) {\r\n\r\n const size = ( config.size === undefined ) ? 256 : config.size;\r\n\r\n if( ! canvas3D ) {\r\n canvas3D = new Canvas3D({ width: size, height: size, preserveDrawingBuffer: true, autoDraw: false });\r\n }\r\n else if( canvas3D.width !== size ) {\r\n canvas3D.updateSize(size,size);\r\n }\r\n\r\n if( config.canvas3D ) {\r\n // Copy camera position from the user view\r\n canvas3D.cameraStateString = config.canvas3D.cameraStateString;\r\n }\r\n\r\n return canvas3D.showDocument$( config.document ) .then( () => {\r\n return canvas3D.draw$() .then( () => {\r\n return canvas3D.image();\r\n\r\n }); });\r\n}\r\n\r\nlet currentPromise = resolve();\r\n\r\nexport const thumbnailImage3D$ = function( config ) {\r\n currentPromise = currentPromise.then( () => {\r\n return _thumbnailImage$(config);\r\n });\r\n return currentPromise;\r\n};\r\n\r\n\r\n// Cx.Preview3D({ renderTo: ..., id: ... });\r\n\r\nexport const Preview3D = Canvas3D.extend({\r\n\r\n init( config = {} ) {\r\n\r\n this.callParent(config);\r\n\r\n if( config.id ) {\r\n this.load$(config.id) .then( this.commit$ );\r\n }\r\n }\r\n});\r\n\r\nexport function createPreview3D( domId, docId, a ) {\r\n const config = { appendTo: g$('#'+domId), id: docId };\r\n if( isPlainObject(a) ) {\r\n assign(config,a);\r\n }\r\n else if( a ) {\r\n config.documentFilter = a;\r\n }\r\n return Preview3D(config);\r\n}\r\n\n\n\n/** WEBPACK FOOTER **\n ** ./src/ui/canvas3d/thumbnail.js\n **/"],"sourceRoot":""}