diff --git a/package.json b/package.json index 5a322914..f4174b5c 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,12 @@ "@stylistic/eslint-plugin": "^1.6.0", "eslint": "^8.56.0", "parcel": "^2.11.0", + "tsc": "^2.0.4", "typescript": ">=3.0.0" }, - "scripts": {}, + "scripts": { + "check": "tsc --noEmit" + }, "repository": { "type": "git", "url": "https://github.com/Microtome/sculptgl.git" @@ -33,4 +36,4 @@ "bugs": { "url": "https://github.com/stephomi/sculptgl/issues" } -} +} \ No newline at end of file diff --git a/src/Scene.js b/src/Scene.ts similarity index 83% rename from src/Scene.js rename to src/Scene.ts index 91a340f4..63e17391 100644 --- a/src/Scene.js +++ b/src/Scene.ts @@ -18,9 +18,61 @@ import Rtt from './drawables/Rtt'; import ShaderLib from './render/ShaderLib'; import MeshStatic from './mesh/meshStatic/MeshStatic'; import WebGLCaps from './render/WebGLCaps'; +import MeshDynamic from './mesh/dynamic/MeshDynamic'; class Scene { + protected _gl: WebGLRenderingContext; // webgl context + + protected _cameraSpeed: 0.25; + + // cache canvas stuffs + protected _pixelRatio: number; + protected _viewport: HTMLElement; + protected _canvas: HTMLCanvasElement; + protected _canvasWidth: number; + protected _canvasHeight: number; + protected _canvasOffsetLeft: number; + protected _canvasOffsetTop: number; + + // core of the app + protected _stateManager: StateManager; // for undo-redo + protected _sculptManager: SculptManager; + protected _camera: Camera; + protected _picking: Picking; // the ray picking + protected _pickingSym: Picking; // the symmetrical picking + + // TODO primitive builder + protected _meshPreview: any; + protected _torusLength: number; + protected _torusWidth: number; + protected _torusRadius: number; + protected _torusRadial: number; + protected _torusTubular: number; + + protected _showContour: boolean; + protected _showGrid: boolean; + protected _grid: any; + protected _background: any; + protected _meshes: Mesh[]; // the meshes + protected _selectMeshes: Mesh[]; // multi selection + protected _mesh: Mesh; // the selected mesh + + protected _rttContour: Rtt; // rtt for contour + protected _rttMerge: Rtt; // rtt decode opaque + merge transparent + protected _rttOpaque: Rtt; // rtt half float + protected _rttTransparent: Rtt; // rtt rgbm + + // ui stuffs + protected _focusGui: boolean; // if the gui is being focused + protected _gui: Gui; + + protected _preventRender: boolean; // prevent multiple render per frame + protected _drawFullScene: boolean; // render everything on the rtt + protected _autoMatrix: boolean; // scale and center the imported meshes + protected _vertexSRGB: boolean; // srgb vs linear colorspace for vertex color + protected _action: number; + constructor() { this._gl = null; // webgl context @@ -29,7 +81,7 @@ class Scene { // cache canvas stuffs this._pixelRatio = 1.0; this._viewport = document.getElementById('viewport'); - this._canvas = document.getElementById('canvas'); + this._canvas = document.getElementById('canvas'); this._canvasWidth = 0; this._canvasHeight = 0; this._canvasOffsetLeft = 0; @@ -100,6 +152,19 @@ class Scene { else this.addSphere(); } + //////////////// + // LOAD FILES + //////////////// + getFileType(name) { + var lower = name.toLowerCase(); + if (lower.endsWith('.obj')) return 'obj'; + if (lower.endsWith('.sgl')) return 'sgl'; + if (lower.endsWith('.stl')) return 'stl'; + if (lower.endsWith('.ply')) return 'ply'; + return; + } + + addModelURL(url) { var fileType = this.getFileType(url); if (!fileType) @@ -110,10 +175,10 @@ class Scene { xhr.responseType = fileType === 'obj' ? 'text' : 'arraybuffer'; - xhr.onload = function () { + xhr.onload = () => { if (xhr.status === 200) this.loadScene(xhr.response, fileType); - }.bind(this); + }; xhr.send(null); } @@ -197,7 +262,7 @@ class Scene { grid.setFlatColor([0.04, 0.04, 0.04]); } - setOrUnsetMesh(mesh, multiSelect) { + setOrUnsetMesh(mesh, multiSelect = false) { if (!mesh) { this._selectMeshes.length = 0; } else if (!multiSelect) { @@ -370,11 +435,11 @@ class Scene { stencil: true }; - var canvas = document.getElementById('canvas'); + var canvas = document.getElementById('canvas'); + + var gl = this._gl = (canvas.getContext('webgl', attributes) + || canvas.getContext('experimental-webgl', attributes)); - var gl = this._gl = canvas.getContext('webgl', attributes) - || canvas.getContext('experimental-webgl', attributes); - if (!gl) { window.alert('Could not initialise WebGL. No WebGL, no SculptGL. Sorry.'); return; @@ -426,7 +491,7 @@ class Scene { } initAlphaTextures() { - Picking.initAlphas().then((alphaNames)=>{ + Picking.initAlphas().then((alphaNames) => { for (let alphaName of alphaNames) { var entry = {}; entry[alphaName] = alphaName; @@ -497,8 +562,8 @@ class Scene { var mCen = mat4.create(); mat4.scale(mCen, mCen, [scale, scale, scale]); mat4.translate( - mCen, - mCen, + mCen, + mCen, [-(box[0] + box[3]) * 0.5, -(box[1] + box[4]) * 0.5, -(box[2] + box[5]) * 0.5] ); @@ -535,11 +600,11 @@ class Scene { addTorus(preview) { var mesh = new Multimesh( Primitives.createTorus( - this._gl, + this._gl, this._torusLength, - this._torusWidth, - this._torusRadius, - this._torusRadial, + this._torusWidth, + this._torusRadius, + this._torusRadial, this._torusTubular) ); if (preview) { @@ -554,7 +619,7 @@ class Scene { this.addNewMesh(mesh); } - subdivideClamp(mesh, linear) { + subdivideClamp(mesh, linear = false) { Subdivision.LINEAR = !!linear; while (mesh.getNbFaces() < 50000) mesh.addLevel(); @@ -606,6 +671,23 @@ class Scene { return newMeshes; } + resetCameraMeshes(meshes = null) { + if (!meshes) meshes = this._meshes; + + if (meshes.length > 0) { + var pivot: vec3 = [0.0, 0.0, 0.0]; + var box = this.computeBoundingBoxMeshes(meshes); + var zoom = 0.8 * this.computeRadiusFromBoundingBox(box); + zoom *= this._camera.computeFrustumFit(); + vec3.set(pivot, (box[0] + box[3]) * 0.5, (box[1] + box[4]) * 0.5, (box[2] + box[5]) * 0.5); + this._camera.setAndFocusOnPivot(pivot, zoom); + } else { + this._camera.resetView(); + } + + this.render(); + } + clearScene() { this.getStateManager().reset(); this.getMeshes().length = 0; @@ -630,7 +712,7 @@ class Scene { meshes.splice(this.getIndexMesh(rm[i]), 1); } - getIndexMesh(mesh, select) { + getIndexMesh(mesh, select = false) { var meshes = select ? this._selectMeshes : this._meshes; var id = mesh.getID(); for (var i = 0, nbMeshes = meshes.length; i < nbMeshes; ++i) { diff --git a/src/SculptGL.js b/src/SculptGL.ts similarity index 90% rename from src/SculptGL.js rename to src/SculptGL.ts index a0df72b4..059bd3db 100644 --- a/src/SculptGL.js +++ b/src/SculptGL.ts @@ -5,6 +5,7 @@ import Enums from './misc/Enums'; import Utils from './misc/Utils'; import Scene from './Scene'; import Multimesh from './mesh/multiresolution/Multimesh'; +import MeshDynamic from './mesh/dynamic/MeshDynamic'; var MOUSE_LEFT = 1; var MOUSE_MIDDLE = 2; @@ -13,6 +14,33 @@ var MOUSE_RIGHT = 3; // Manage events class SculptGL extends Scene { + + // all x and y position are canvas based + + // controllers stuffs + protected _mouseX: number; + protected _mouseY: number; + protected _lastMouseX: number; + protected _lastMouseY: number; + protected _lastScale: number; + + // NOTHING, MASK_EDIT, SCULPT_EDIT, CAMERA_ZOOM, CAMERA_ROTATE, CAMERA_PAN, CAMERA_PAN_ZOOM_ALT + protected _lastNbPointers: number; + protected _isWheelingIn: boolean; + + // masking + protected _maskX: number; + protected _maskY: number; + protected _hammer: HammerManager; + + protected _eventProxy: any; + + protected _isIOS: boolean; + + protected _timerResetPointer: number; + protected _timerEndWheel: number; + + constructor() { super(); @@ -37,6 +65,8 @@ class SculptGL extends Scene { this._eventProxy = {}; + this._isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent); + this.initHammer(); this.addEvents(); } @@ -188,19 +218,14 @@ class SculptGL extends Scene { } this.onDeviceMove(evProxy); - if (this._isIOS()) { + if (this._isIOS) { window.clearTimeout(this._timerResetPointer); - this._timerResetPointer = window.setTimeout(function () { + this._timerResetPointer = window.setTimeout(() => { this._lastNbPointers = 0; - }.bind(this), 60); + }, 60); } } - _isIOS() { - if (this._isIOS !== undefined) return this._isIOS; - this._isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent); - return this._isIOS; - } onPanUpdateNbPointers(nbPointers) { // called on panstart or panmove (not consistent) @@ -215,9 +240,9 @@ class SculptGL extends Scene { return; this.onDeviceUp(); // we need to detect when all fingers are released - window.setTimeout(function () { + window.setTimeout(() => { if (!e.pointers.length) this._lastNbPointers = 0; - }.bind(this), 60); + }, 60); } onDoubleTap(e) { @@ -233,7 +258,7 @@ class SculptGL extends Scene { var picking = this._picking; var res = picking.intersectionMouseMeshes(); var cam = this._camera; - var pivot = [0.0, 0.0, 0.0]; + var pivot: vec3 = [0.0, 0.0, 0.0]; if (!res) { return this.resetCameraMeshes(); } @@ -264,35 +289,6 @@ class SculptGL extends Scene { this.onDeviceWheel(dir); } - resetCameraMeshes(meshes) { - if (!meshes) meshes = this._meshes; - - if (meshes.length > 0) { - var pivot = [0.0, 0.0, 0.0]; - var box = this.computeBoundingBoxMeshes(meshes); - var zoom = 0.8 * this.computeRadiusFromBoundingBox(box); - zoom *= this._camera.computeFrustumFit(); - vec3.set(pivot, (box[0] + box[3]) * 0.5, (box[1] + box[4]) * 0.5, (box[2] + box[5]) * 0.5); - this._camera.setAndFocusOnPivot(pivot, zoom); - } else { - this._camera.resetView(); - } - - this.render(); - } - - //////////////// - // LOAD FILES - //////////////// - getFileType(name) { - var lower = name.toLowerCase(); - if (lower.endsWith('.obj')) return 'obj'; - if (lower.endsWith('.sgl')) return 'sgl'; - if (lower.endsWith('.stl')) return 'stl'; - if (lower.endsWith('.ply')) return 'ply'; - return; - } - loadFiles(event) { event.stopPropagation(); event.preventDefault(); @@ -313,7 +309,7 @@ class SculptGL extends Scene { var self = this; reader.onload = function (evt) { self.loadScene(evt.target.result, fileType); - document.getElementById('fileopen').value = ''; + (document.getElementById('fileopen')).value = ''; }; if (fileType === 'obj') @@ -494,8 +490,8 @@ class SculptGL extends Scene { if (action === Enums.Action.SCULPT_EDIT) { Multimesh.RENDER_HINT = Multimesh.SCULPT; - this._sculptManager.update(this); - if (this.getMesh().isDynamic) + this._sculptManager.update(); + if (this.getMesh() instanceof MeshDynamic) this._gui.updateMeshInfo(); } } diff --git a/src/editing/tools/Brush.ts b/src/editing/tools/Brush.ts index 5b6c07a7..31602378 100644 --- a/src/editing/tools/Brush.ts +++ b/src/editing/tools/Brush.ts @@ -19,7 +19,7 @@ class Brush extends SculptBase { this._lockPosition = false; } - stroke(picking) { + override stroke(picking) { var iVertsInRadius = picking.getPickedVertices(); var intensity = this._intensity * Tablet.getPressureIntensity(); diff --git a/src/editing/tools/Crease.ts b/src/editing/tools/Crease.ts index ee324d42..b3f95dfd 100644 --- a/src/editing/tools/Crease.ts +++ b/src/editing/tools/Crease.ts @@ -15,7 +15,7 @@ class Crease extends SculptBase { this._lockPosition = false; } - stroke(picking) { + override stroke(picking) { var iVertsInRadius = picking.getPickedVertices(); var intensity = this._intensity * Tablet.getPressureIntensity(); diff --git a/src/editing/tools/Drag.ts b/src/editing/tools/Drag.ts index 1b74c185..63c8b0b4 100644 --- a/src/editing/tools/Drag.ts +++ b/src/editing/tools/Drag.ts @@ -15,7 +15,7 @@ class Drag extends SculptBase { } - sculptStroke() { + override sculptStroke() { var main = this._main; var mesh = this.getMesh(); var picking = main.getPicking(); @@ -54,7 +54,7 @@ class Drag extends SculptBase { this._lastMouseY = main._mouseY; } - makeStroke(mouseX, mouseY, picking, pickingSym) { + override makeStroke(mouseX, mouseY, picking, pickingSym) { var mesh = this.getMesh(); this.updateDragDir(picking, mouseX, mouseY); picking.pickVerticesInSphere(picking.getLocalRadius2()); @@ -75,7 +75,7 @@ class Drag extends SculptBase { } /** On stroke */ - stroke(picking, sym) { + override stroke(picking, sym) { var iVertsInRadius = picking.getPickedVertices(); // undo-redo diff --git a/src/editing/tools/Flatten.ts b/src/editing/tools/Flatten.ts index b676aebb..556b54b1 100644 --- a/src/editing/tools/Flatten.ts +++ b/src/editing/tools/Flatten.ts @@ -17,7 +17,7 @@ class Flatten extends SculptBase { this._lockPosition = false; } - stroke(picking) { + override stroke(picking) { var iVertsInRadius = picking.getPickedVertices(); var intensity = this._intensity * Tablet.getPressureIntensity(); diff --git a/src/editing/tools/Inflate.ts b/src/editing/tools/Inflate.ts index 7f538bf8..471054f5 100644 --- a/src/editing/tools/Inflate.ts +++ b/src/editing/tools/Inflate.ts @@ -3,6 +3,12 @@ import SculptBase from './SculptBase'; class Inflate extends SculptBase { + protected _intensity: number; + protected _negative: boolean; + protected _culling: boolean; + protected _idAlpha: number; + + constructor(main) { super(main); @@ -14,7 +20,7 @@ class Inflate extends SculptBase { this._lockPosition = false; } - stroke(picking) { + override stroke(picking) { var iVertsInRadius = picking.getPickedVertices(); var intensity = this._intensity * Tablet.getPressureIntensity(); diff --git a/src/editing/tools/LocalScale.ts b/src/editing/tools/LocalScale.ts index 2c3a9b60..2dc1c819 100644 --- a/src/editing/tools/LocalScale.ts +++ b/src/editing/tools/LocalScale.ts @@ -2,6 +2,9 @@ import SculptBase from './SculptBase'; class LocalScale extends SculptBase { + protected _culling: boolean; + protected _idAlpha: number; + constructor(main) { super(main); @@ -10,7 +13,7 @@ class LocalScale extends SculptBase { this._idAlpha = 0; } - startSculpt() { + override startSculpt() { var main = this._main; if (main.getSculptManager().getSymmetry()) { var pickingSym = main.getPickingSymmetry(); @@ -20,7 +23,7 @@ class LocalScale extends SculptBase { } /** Make a brush scale stroke */ - sculptStroke() { + override sculptStroke() { var main = this._main; var delta = main._mouseX - main._lastMouseX; var picking = main.getPicking(); @@ -39,7 +42,7 @@ class LocalScale extends SculptBase { } /** On stroke */ - stroke(picking, delta) { + override stroke(picking, delta) { var iVertsInRadius = picking.getPickedVertices(); // undo-redo diff --git a/src/editing/tools/Masking.ts b/src/editing/tools/Masking.ts index 33b6b5f2..975cf796 100644 --- a/src/editing/tools/Masking.ts +++ b/src/editing/tools/Masking.ts @@ -7,7 +7,6 @@ import MeshStatic from '../../mesh/meshStatic/MeshStatic'; class Masking extends SculptBase { - protected _radius = 50; protected hardness = 0.25; protected intensity = 1.0; protected negative = true; @@ -23,12 +22,12 @@ class Masking extends SculptBase { } - pushState() { + override pushState() { // too lazy to add a pushStateMaterial this._main.getStateManager().pushStateColorAndMaterial(this.getMesh()); } - updateMeshBuffers() { + override updateMeshBuffers() { var mesh = this.getMesh(); if (mesh.isDynamic) mesh.updateBuffers(); @@ -36,11 +35,11 @@ class Masking extends SculptBase { mesh.updateMaterialBuffer(); } - stroke(picking) { + override stroke(picking) { Paint.prototype.stroke.call(this, picking); } - dynamicTopology(picking) { + override dynamicTopology(picking) { // no dynamic topo with masking return picking.getPickedVertices(); } diff --git a/src/editing/tools/Move.ts b/src/editing/tools/Move.ts index 44e18082..5eb85694 100644 --- a/src/editing/tools/Move.ts +++ b/src/editing/tools/Move.ts @@ -26,7 +26,7 @@ class Move extends SculptBase { } - startSculpt() { + override startSculpt() { var main = this._main; var picking = main.getPicking(); this.initMoveData(picking, this._moveData); @@ -76,7 +76,7 @@ class Move extends SculptBase { } } - sculptStroke() { + override sculptStroke() { var main = this._main; var picking = main.getPicking(); var pickingSym = main.getPickingSymmetry(); diff --git a/src/editing/tools/Pinch.ts b/src/editing/tools/Pinch.ts index deb08a8a..03130102 100644 --- a/src/editing/tools/Pinch.ts +++ b/src/editing/tools/Pinch.ts @@ -15,7 +15,7 @@ class Pinch extends SculptBase { this._lockPosition = false; } - stroke(picking) { + override stroke(picking) { var iVertsInRadius = picking.getPickedVertices(); var intensity = this._intensity * Tablet.getPressureIntensity(); diff --git a/src/editing/tools/Smooth.ts b/src/editing/tools/Smooth.ts index fc834671..838f5f81 100644 --- a/src/editing/tools/Smooth.ts +++ b/src/editing/tools/Smooth.ts @@ -8,15 +8,14 @@ class Smooth extends SculptBase { protected _culling: boolean = false; protected _tangent: boolean = false; protected _idAlpha: number = 0; - protected _lockPosition: boolean = false; - constructor(main) { + constructor(main = null) { super(main); this._radius = 50; } - stroke(picking) { + override stroke(picking) { var iVertsInRadius = picking.getPickedVertices(); var intensity = this._intensity * Tablet.getPressureIntensity(); @@ -36,7 +35,7 @@ class Smooth extends SculptBase { } /** Smooth a group of vertices. New position is given by simple averaging */ - smooth(iVerts, intensity, picking: any | null = null) { + smooth(iVerts, intensity, picking: (any | null) = null) { var mesh = this.getMesh(); var vAr = mesh.getVertices(); var mAr = mesh.getMaterials(); @@ -62,7 +61,7 @@ class Smooth extends SculptBase { } /** Smooth a group of vertices. Reproject the position on each vertex normals plane */ - smoothTangent(iVerts, intensity, picking) { + smoothTangent(iVerts, intensity, picking = null) { var mesh = this.getMesh(); var vAr = mesh.getVertices(); var mAr = mesh.getMaterials(); diff --git a/src/editing/tools/Transform.ts b/src/editing/tools/Transform.ts index 966d703f..bb0ca51c 100644 --- a/src/editing/tools/Transform.ts +++ b/src/editing/tools/Transform.ts @@ -20,7 +20,7 @@ class Transform extends SculptBase { return true; } - preUpdate() { + override preUpdate() { var picking = this._main.getPicking(); var mesh = picking.getMesh(); @@ -30,7 +30,7 @@ class Transform extends SculptBase { this._main.setCanvasCursor('default'); } - start(ctrl) { + override start(ctrl) { var main = this._main; var mesh = this.getMesh(); var picking = main.getPicking(); @@ -51,7 +51,7 @@ class Transform extends SculptBase { return false; } - end() { + override end() { this._gizmo.onMouseUp(); if (!this.getMesh() || this.isIdentity(this.getMesh().getEditMatrix())) @@ -98,14 +98,14 @@ class Transform extends SculptBase { else mesh.updateGeometry(mesh.getFacesFromVertices(iVerts), iVerts); } - update() { } + override update() { } - postRender() { + override postRender() { if (this.getMesh()) this._gizmo.render(); } - addSculptToScene(scene) { + override addSculptToScene(scene) { if (this.getMesh()) this._gizmo.addGizmoToScene(scene); } diff --git a/src/editing/tools/Twist.ts b/src/editing/tools/Twist.ts index 716a0c03..c6b6e40d 100644 --- a/src/editing/tools/Twist.ts +++ b/src/editing/tools/Twist.ts @@ -21,7 +21,7 @@ class Twist extends SculptBase { this._radius = 75; } - startSculpt() { + override startSculpt() { var main = this._main; var mouseX = main._mouseX; var mouseY = main._mouseY; @@ -44,7 +44,7 @@ class Twist extends SculptBase { } /** Make a brush twist stroke */ - sculptStroke() { + override sculptStroke() { var main = this._main; var mx = main._mouseX; var my = main._mouseY; @@ -67,7 +67,7 @@ class Twist extends SculptBase { } /** On stroke */ - stroke(picking, mx, my, lx, ly, twistData) { + override stroke(picking, mx, my, lx, ly, twistData) { var iVertsInRadius = picking.getPickedVertices(); // undo-redo diff --git a/src/files/Export.ts b/src/files/Export.ts index a7273a3b..b7ee3a01 100644 --- a/src/files/Export.ts +++ b/src/files/Export.ts @@ -2,13 +2,6 @@ import { exportOBJ } from './ExportOBJ'; import { exportSGL } from './ExportSGL'; import { exportAsciiPLY, exportBinaryPLY } from './ExportPLY'; import { exportAsciiSTL, exportBinarySTL } from './ExportSTL'; -// import ExportSculpteo from './ExportSculpteo'; -// import ExportMaterialise from './ExportMaterialise'; - - -// TODO These probably need to be updated to latest API before use. -// Export.exportSculpteo = ExportSculpteo.exportSculpteo; -// Export.exportMaterialise = ExportMaterialise.exportMaterialise; export default { exportOBJ, exportSGL, exportAsciiPLY, exportBinaryPLY, exportAsciiSTL, exportBinarySTL diff --git a/src/files/ExportMaterialise.ts b/src/files/ExportMaterialise.ts deleted file mode 100644 index e1666e9c..00000000 --- a/src/files/ExportMaterialise.ts +++ /dev/null @@ -1,71 +0,0 @@ -import * as stl from './ExportSTL'; -let zip = require('../../lib/zip'); - - -export function exportMaterialise(main, statusWidget) { - var xhr = new XMLHttpRequest(); - // xhr.open('POST', 'https://i.materialise.com/upload', true); - // xhr.open('POST', 'uploadMaterialise.php', true); - // TODO: Need to make this configurable - xhr.open( - 'POST', - 'https://i.materialise.com/web-api/tool/20cc0fd6-3cef-4111-a201-0b87026d892c/model', - true - ); - - xhr.onprogress = function (event) { - if (event.lengthComputable && event.total) { - var val = Math.round(event.loaded * 100.0 / event.total); - statusWidget.setMessage('Materialise upload: ' + val + '%'); - } - }; - - var hideStatus = function () { - statusWidget.setMessage(''); - }; - xhr.onerror = hideStatus; - xhr.onabort = hideStatus; - - xhr.onload = function () { - hideStatus(); - - if (xhr.status === 200) { - var json = JSON.parse(xhr.responseText); - window.open('https://i.materialise.com/en/3dprint#modelId=' + json.modelID, '_blank'); - } - }; - - var meshes = main.getMeshes(); - var box = main.computeBoundingBoxMeshes(meshes); - var radius = main.computeRadiusFromBoundingBox(box); - var data = stl.exportBinarySTL(meshes, { colorMagic: true, swapXY: true }); - - // var blob = new Blob([data], { type: 'application/octet-stream' }); - // Export.exportFileMaterialise(radius, xhr, domStatus, blob); - - statusWidget.setMessage('Creating zip...'); - zip.useWebWorkers = true; - zip.workerScriptsPath = 'worker/'; - zip.createWriter(new zip.BlobWriter('application/zip'), function (zipWriter) { - zipWriter.add('yourMesh.stl', new zip.BlobReader(data), function () { - zipWriter.close(exportFileMaterialise.bind(this, radius, xhr, statusWidget)); - }); - }, onerror); - - return xhr; -}; - -export function exportFileMaterialise(radius, xhr, statusWidget, blob) { - if (xhr.isAborted) return; - - var fd = new FormData(); - fd.append('file', blob, 'yourMesh.zip'); - // fd.append('scale', 100 * 4.0 / radius); - // fd.append('useAjax', 'true'); - // fd.append('plugin', ''); - // fd.append('forceEmbedding', false); - - statusWidget.setMessage('Materialise upload...'); - xhr.send(fd); -}; - diff --git a/src/files/ExportSculpteo.ts b/src/files/ExportSculpteo.ts deleted file mode 100644 index b1ba772e..00000000 --- a/src/files/ExportSculpteo.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as ply from './ExportPLY'; -let zip = require('../../lib/zip'); - - - -export function exportSculpteo(main, statusWidget) { - var xhr = new XMLHttpRequest(); - // xhr.open('POST', 'https://www.sculpteo.com/en/upload_design/a/3D/', true); - //TODO: This is probably very old and probably needs to be updated to match the modern api. - xhr.open('POST', 'uploadSculpteo.php', true); - - xhr.onprogress = function (event) { - if (event.lengthComputable && event.total) { - var val = Math.round(event.loaded * 100.0 / event.total); - statusWidget.setMessage('Sculpteo upload: ' + val + '%'); - } - }; - - var hideStatus = function () { - statusWidget.setMessage(''); - }; - xhr.onerror = hideStatus; - xhr.onabort = hideStatus; - - xhr.onload = function () { - hideStatus(); - - if (this.status === 200) { - var match = xhr.responseText.match(/\/print\/(.+?)(?=")/); - if (match) { - window.open('https://www.sculpteo.com/en' + match[0], '_blank'); - } - - // var json = JSON.parse(xhr.responseText); - // window.open('https://www.sculpteo.com/en/print/' + json.slug + '/' + json.uuid, '_blank'); - } - }; - - var meshes = main.getMeshes(); - var box = main.computeBoundingBoxMeshes(meshes); - var radius = main.computeRadiusFromBoundingBox(box); - var data = ply.exportBinaryPLY(meshes, { swapXY: true }); - - statusWidget.setMessage('Creating zip...'); - zip.useWebWorkers = true; - zip.workerScriptsPath = 'worker/'; - zip.createWriter(new zip.BlobWriter('application/zip'), function (zipWriter) { - zipWriter.add('yourMesh.ply', new zip.BlobReader(data), function () { - zipWriter.close(exportFileSculpteo.bind(this, radius, xhr, statusWidget)); - }); - }, onerror); - - return xhr; -}; - -export function exportFileSculpteo(radius, xhr, statusWidget, blob) { - if (xhr.isAborted) return; - - var fd = new FormData(); - fd.append('file', blob); - fd.append('name', 'fromSculptgl'); - - // fd.append('trackid', '....'); - // fd.append('share', '0'); - // fd.append('print_authorization', '0'); - // fd.append('customizable', '0'); - // fd.append('unit', 'cm'); - fd.append('scale', "" + (4.0 / radius)); - // fd.append('rotation', '0,0,0'); - // fd.append('terms', '1'); - - // xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - statusWidget.setMessage('Sculpteo upload...'); - xhr.send(fd); -}; - diff --git a/src/gui/Gui.js b/src/gui/Gui.js index 80ae1692..2fdb3a96 100644 --- a/src/gui/Gui.js +++ b/src/gui/Gui.js @@ -47,7 +47,10 @@ class Gui { initGui() { this.deleteGui(); - this._guiMain = new GuiMain(this._main.getViewport(), this._main.onCanvasResize.bind(this._main)); + this._guiMain = new GuiMain( + this._main.getViewport(), + this._main.onCanvasResize.bind(this._main) + ); var ctrls = this._ctrls; ctrls.length = 0; @@ -56,7 +59,6 @@ class Gui { // Initialize the topbar this._topbar = this._guiMain.addTopbar(); ctrls[idc++] = this._ctrlFiles = new GuiFiles(this._topbar, this); - // this.initPrint(this._topbar); ctrls[idc++] = this._ctrlScene = new GuiScene(this._topbar, this); ctrls[idc++] = this._ctrlStates = new GuiStates(this._topbar, this); ctrls[idc++] = this._ctrlBackground = new GuiBackground(this._topbar, this); @@ -120,26 +122,6 @@ class Gui { return notif; } - initPrint(guiParent) { - var menu = guiParent.addMenu('Print it!'); - // menu.addButton('with Sculpteo', this, 'exportSculpteo'); - menu.addButton('Go to Materialise!', this, 'exportMaterialise'); - } - - exportSculpteo() { - this._export('sculpteo'); - } - - exportMaterialise() { - if (window.confirm('A new webpage will be opened. Start upload?')) { - this._export('materialise'); - } - } - - exportSketchfab() { - this._export('sketchfab'); - } - _export(notifName) { var mesh = this._main.getMesh(); if (!mesh) return; diff --git a/src/gui/GuiCamera.js b/src/gui/GuiCamera.js index 91de2650..fc413ba2 100644 --- a/src/gui/GuiCamera.js +++ b/src/gui/GuiCamera.js @@ -21,18 +21,32 @@ class GuiCamera { // reset camera menu.addTitle(TR('cameraReset')); - menu.addDualButton(TR('cameraCenter'), TR('cameraFront'), this.resetCamera.bind(this), this.resetFront.bind(this)); - menu.addDualButton(TR('cameraLeft'), TR('cameraTop'), this.resetLeft.bind(this), this.resetTop.bind(this)); + menu.addDualButton( + TR('cameraCenter'), + TR('cameraFront'), + this.resetCamera.bind(this), + this.resetFront.bind(this)) + ; + menu.addDualButton( + TR('cameraLeft'), + TR('cameraTop'), + this.resetLeft.bind(this), + this.resetTop.bind(this) + ); // camera type this._ctrlProjectionTitle = menu.addTitle(TR('cameraProjection')); var optionsType = []; optionsType[Enums.Projection.PERSPECTIVE] = TR('cameraPerspective'); optionsType[Enums.Projection.ORTHOGRAPHIC] = TR('cameraOrthographic'); - this._ctrlProjection = menu.addCombobox('', camera.getProjectionType(), this.onCameraTypeChange.bind(this), optionsType); + this._ctrlProjection = menu.addCombobox( + '', camera.getProjectionType(), this.onCameraTypeChange.bind(this), optionsType + ); // camera fov - this._ctrlFov = menu.addSlider(TR('cameraFov'), camera.getFov(), this.onFovChange.bind(this), 10, 90, 1); + this._ctrlFov = menu.addSlider( + TR('cameraFov'), camera.getFov(), this.onFovChange.bind(this), 10, 90, 1 + ); this._ctrlFov.setVisibility(camera.getProjectionType() === Enums.Projection.PERSPECTIVE); // camera mode @@ -42,7 +56,9 @@ class GuiCamera { optionsMode[Enums.CameraMode.SPHERICAL] = TR('cameraSpherical'); optionsMode[Enums.CameraMode.PLANE] = TR('cameraPlane'); menu.addCombobox('', camera.getMode(), this.onCameraModeChange.bind(this), optionsMode); - this._ctrlPivot = menu.addCheckbox(TR('cameraPivot'), camera.getUsePivot(), this.onPivotChange.bind(this)); + this._ctrlPivot = menu.addCheckbox( + TR('cameraPivot'), camera.getUsePivot(), this.onPivotChange.bind(this) + ); // TR('CameraSpeed') ... menu.addSlider('speed', this._main, '_cameraSpeed', 0.05, 1.0, 0.001); diff --git a/src/gui/GuiConfig.js b/src/gui/GuiConfig.js index 38fb0f5c..b954b74a 100644 --- a/src/gui/GuiConfig.js +++ b/src/gui/GuiConfig.js @@ -12,7 +12,9 @@ class GuiConfig { // config stuffs this._langs = Object.keys(TR.languages); this._menu = guiParent.addMenu('Language'); - this._menu.addCombobox('', this._langs.indexOf(TR.select), this.onLangChange.bind(this), this._langs); + this._menu.addCombobox( + '', this._langs.indexOf(TR.select), this.onLangChange.bind(this), this._langs + ); } onLangChange(value) { diff --git a/src/gui/GuiFiles.js b/src/gui/GuiFiles.js index f55d60bc..1ad1e37f 100644 --- a/src/gui/GuiFiles.js +++ b/src/gui/GuiFiles.js @@ -40,11 +40,12 @@ class GuiFiles { menu.addButton(TR('fileExportSTL'), this, 'saveFileAsSTL'); menu.addCheckbox('OBJ color zbrush', this, '_objColorZbrush'); menu.addCheckbox('OBJ color append', this, '_objColorAppended'); - menu.addButton(TR('sketchfabTitle'), this._ctrlGui, 'exportSketchfab'); // export texture menu.addTitle(TR('fileExportTextureTitle')); - this._guiTexSize = menu.addSlider(TR('fileExportTextureSize'), 10, this.onTextureSize.bind(this), 8, 12, 1); + this._guiTexSize = menu.addSlider(TR( + 'fileExportTextureSize'), 10, this.onTextureSize.bind(this), 8, 12, 1 + ); this._guiTexSize.setValue(10); menu.addButton(TR('fileExportColor'), this, 'saveColor'); menu.addButton(TR('fileExportRoughness'), this, 'saveRoughness'); @@ -182,7 +183,10 @@ class GuiFiles { saveFileAsOBJ() { var meshes = this._getExportMeshes(); if (!meshes) return; - this._save(Export.exportOBJ(meshes, this._objColorZbrush, this._objColorAppended), 'yourMesh.obj'); + this._save( + Export.exportOBJ(meshes, this._objColorZbrush, this._objColorAppended), + 'yourMesh.obj' + ); } saveFileAsPLY() { diff --git a/src/gui/GuiRendering.js b/src/gui/GuiRendering.js index c7db201c..38156b8d 100644 --- a/src/gui/GuiRendering.js +++ b/src/gui/GuiRendering.js @@ -36,27 +36,37 @@ class GuiRendering { optionsShaders[Enums.Shader.NORMAL] = TR('renderingNormal'); optionsShaders[Enums.Shader.UV] = TR('renderingUV'); menu.addTitle(TR('renderingShader')); - this._ctrlShaders = menu.addCombobox('', Enums.Shader.MATCAP, this.onShaderChanged.bind(this), optionsShaders); + this._ctrlShaders = menu.addCombobox( + '', Enums.Shader.MATCAP, this.onShaderChanged.bind(this), optionsShaders + ); // flat shading - this._ctrlCurvature = menu.addSlider(TR('renderingCurvature'), 20, this.onCurvatureChanged.bind(this), 0, 100, 1); + this._ctrlCurvature = menu.addSlider( + TR('renderingCurvature'), 20, this.onCurvatureChanged.bind(this), 0, 100, 1 + ); // filmic tonemapping - this._ctrlFilmic = menu.addCheckbox(TR('renderingFilmic'), ShaderMERGE.FILMIC, this.onFilmic.bind(this)); + this._ctrlFilmic = menu.addCheckbox( + TR('renderingFilmic'), ShaderMERGE.FILMIC, this.onFilmic.bind(this) + ); // environments var optionEnvs = {}; for (var i = 0, envs = ShaderPBR.environments, l = envs.length; i < l; ++i) optionEnvs[i] = envs[i].name; this._ctrlEnvTitle = menu.addTitle(TR('renderingEnvironment')); - this._ctrlEnv = menu.addCombobox('', ShaderPBR.idEnv, this.onEnvironmentChanged.bind(this), optionEnvs); + this._ctrlEnv = menu.addCombobox( + '', ShaderPBR.idEnv, this.onEnvironmentChanged.bind(this), optionEnvs + ); // matcap texture var optionMatcaps = {}; for (var j = 0, mats = ShaderMatcap.matcaps, k = mats.length; j < k; ++j) optionMatcaps[j] = mats[j].name; this._ctrlMatcapTitle = menu.addTitle(TR('renderingMaterial')); - this._ctrlMatcap = menu.addCombobox(TR('renderingMatcap'), 0, this.onMatcapChanged.bind(this), optionMatcaps); + this._ctrlMatcap = menu.addCombobox(TR( + 'renderingMatcap'), 0, this.onMatcapChanged.bind(this), optionMatcaps + ); // matcap load this._ctrlImportMatcap = menu.addButton(TR('renderingImportMatcap'), this, 'importMatcap'); @@ -64,17 +74,25 @@ class GuiRendering { // uv texture this._ctrlUV = menu.addButton(TR('renderingImportUV'), this, 'importTexture'); - this._ctrlExposure = menu.addSlider(TR('renderingExposure'), 1, this.onExposureChanged.bind(this), 0, 5, 0.001); + this._ctrlExposure = menu.addSlider( + TR('renderingExposure'), 1, this.onExposureChanged.bind(this), 0, 5, 0.001 + ); this.onUpdateCtrlExposure(); menu.addTitle(TR('renderingExtra')); - this._ctrlTransparency = menu.addSlider(TR('renderingTransparency'), 0.0, this.onTransparencyChanged.bind(this), 0, 100, 1); + this._ctrlTransparency = menu.addSlider( + TR('renderingTransparency'), 0.0, this.onTransparencyChanged.bind(this), 0, 100, 1 + ); // flat shading - this._ctrlFlatShading = menu.addCheckbox(TR('renderingFlat'), false, this.onFlatShading.bind(this)); + this._ctrlFlatShading = menu.addCheckbox( + TR('renderingFlat'), false, this.onFlatShading.bind(this) + ); // wireframe - this._ctrlShowWireframe = menu.addCheckbox(TR('renderingWireframe'), false, this.onShowWireframe.bind(this)); + this._ctrlShowWireframe = menu.addCheckbox( + TR('renderingWireframe'), false, this.onShowWireframe.bind(this) + ); if (RenderData.ONLY_DRAW_ARRAYS) this._ctrlShowWireframe.setVisibility(false); diff --git a/src/gui/GuiScene.js b/src/gui/GuiScene.js index a9383fbe..08865662 100644 --- a/src/gui/GuiScene.js +++ b/src/gui/GuiScene.js @@ -20,18 +20,6 @@ class GuiScene { menu.addButton(TR('sceneAddCylinder'), this._main, 'addCylinder'); menu.addButton(TR('sceneAddTorus'), this._main, 'addTorus'); - // menu.addTitle(TR('Torus')); - // menu.addSlider(TR('Arc'), this._main._torusRadius, this.updateTorusRadius.bind(this), 0.01, Math.PI * 2, 0.001); - // this.ctrlWI = menu.addSlider(TR('Width'), this._main._torusWidth, this.updateTorusWidth.bind(this), 0.01, 0.5, 0.01); - // this.ctrlLE = menu.addSlider(TR('Length'), this._main._torusLength, this.updateTorusLength.bind(this), 0.2, 2.0, 0.01); - // menu.addSlider(TR('Radial'), this._main._torusRadial, this.updateTorusRadial.bind(this), 3, 64, 1); - // menu.addSlider(TR('Tubular'), this._main._torusTubular, this.updateTorusTubular.bind(this), 3, 256, 1); - - // this.ctrlValidate = menu.addButton(TR('Validate !'), this, 'validatePreview'); - // this.ctrlValidate.setVisibility(false); - // this.ctrlDiscard = menu.addButton(TR('Discard !'), this, 'discardPreview'); - // this.ctrlDiscard.setVisibility(false); - // selection stuffs menu.addTitle(TR('sceneSelection')); this._ctrlIsolate = menu.addCheckbox(TR('renderingIsolate'), false, this.showHide.bind(this)); @@ -44,11 +32,17 @@ class GuiScene { // extra menu.addTitle(TR('renderingExtra')); - menu.addCheckbox(TR('darkenUnselected'), ShaderBase.darkenUnselected, this.onDarkenUnselected.bind(this)); + menu.addCheckbox(TR( + 'darkenUnselected'), ShaderBase.darkenUnselected, this.onDarkenUnselected.bind(this) + ); menu.addCheckbox(TR('contourShow'), this._main._showContour, this.onShowContour.bind(this)); menu.addCheckbox(TR('renderingGrid'), this._main._showGrid, this.onShowGrid.bind(this)); - menu.addCheckbox(TR('renderingSymmetryLine'), ShaderBase.showSymmetryLine, this.onShowSymmetryLine.bind(this)); - this._ctrlOffSym = menu.addSlider('SymOffset', 0.0, this.onOffsetSymmetry.bind(this), -1.0, 1.0, 0.001); + menu.addCheckbox( + TR('renderingSymmetryLine'), ShaderBase.showSymmetryLine, this.onShowSymmetryLine.bind(this) + ); + this._ctrlOffSym = menu.addSlider( + 'SymOffset', 0.0, this.onOffsetSymmetry.bind(this), -1.0, 1.0, 0.001 + ); } clearScene() { @@ -144,7 +138,9 @@ class GuiScene { updateMesh() { var nbMeshes = this._main.getMeshes().length; var nbSelected = this._main.getSelectedMeshes().length; - this._ctrlIsolate.setVisibility(this.hasHiddenMeshes() || (nbMeshes !== nbSelected && nbSelected >= 1)); + this._ctrlIsolate.setVisibility( + this.hasHiddenMeshes() || (nbMeshes !== nbSelected && nbSelected >= 1) + ); this._ctrlMerge.setVisibility(nbSelected > 1); var mesh = this._main.getMesh(); diff --git a/src/gui/GuiSculpting.js b/src/gui/GuiSculpting.js index 71de0bb9..aa1fc17e 100644 --- a/src/gui/GuiSculpting.js +++ b/src/gui/GuiSculpting.js @@ -45,15 +45,21 @@ class GuiSculpting { for (var i = 0, nbTools = Tools.length; i < nbTools; ++i) { if (Tools[i]) optTools[i] = TR(Tools[i].uiName); } - this._ctrlSculpt = menu.addCombobox(TR('sculptTool'), this._sculptManager.getToolIndex(), this.onChangeTool.bind(this), optTools); + this._ctrlSculpt = menu.addCombobox( + TR('sculptTool'), this._sculptManager.getToolIndex(), this.onChangeTool.bind(this), optTools + ); GuiSculptingTools.initGuiTools(this._sculptManager, this._menu, this._main); this._ctrlTitleCommon = menu.addTitle(TR('sculptCommon')); // symmetry - this._ctrlSymmetry = menu.addCheckbox(TR('sculptSymmetry'), this._sculptManager._symmetry, this.onSymmetryChange.bind(this)); + this._ctrlSymmetry = menu.addCheckbox( + TR('sculptSymmetry'), this._sculptManager._symmetry, this.onSymmetryChange.bind(this) + ); // continuous - this._ctrlContinuous = menu.addCheckbox(TR('sculptContinuous'), this._sculptManager, '_continuous'); + this._ctrlContinuous = menu.addCheckbox( + TR('sculptContinuous'), this._sculptManager, '_continuous') + ; GuiSculptingTools.show(this._sculptManager.getToolIndex()); this.addEvents(); @@ -237,7 +243,11 @@ class GuiSculpting { } onKeyUp(event) { - var releaseTool = this._main._action === Enums.Action.NOTHING && this._toolOnRelease !== -1 && !event.ctrlKey && !event.shiftKey; + var releaseTool = this._main._action === Enums.Action.NOTHING + && this._toolOnRelease !== -1 + && !event.ctrlKey + && !event.shiftKey; + if (!event.altKey || releaseTool) this.releaseInvertSign(); diff --git a/src/gui/GuiSculptingTools.js b/src/gui/GuiSculptingTools.js index 9150871c..95655be0 100644 --- a/src/gui/GuiSculptingTools.js +++ b/src/gui/GuiSculptingTools.js @@ -51,12 +51,21 @@ var addCtrlRadius = function (tool, fold, widget, main) { return ctrl; }; var addCtrlIntensity = function (tool, fold, widget) { - var ctrl = fold.addSlider(TR('sculptIntensity'), tool._intensity * 100, setOnChange.bind(tool, '_intensity', 100), 0, 100, 1); + var ctrl = fold.addSlider( + TR('sculptIntensity'), + tool._intensity * 100, + setOnChange.bind(tool, '_intensity', 100), + 0, + 100, + 1 + ); widget._ctrlIntensity = ctrl; return ctrl; }; var addCtrlHardness = function (tool, fold) { - return fold.addSlider(TR('sculptHardness'), tool._hardness * 100, setOnChange.bind(tool, '_hardness', 100), 0, 100, 1); + return fold.addSlider( + TR('sculptHardness'), tool._hardness * 100, setOnChange.bind(tool, '_hardness', 100), 0, 100, 1 + ); }; var addCtrlCulling = function (tool, fold) { return fold.addCheckbox(TR('sculptCulling'), tool, '_culling'); @@ -186,7 +195,9 @@ GuiTools[Enums.Tools.PAINT] = { this._ctrls.push(fold.addTitle(TR('sculptPBRTitle'))); this._ctrls.push(fold.addButton(TR('sculptPaintAll'), tool, 'paintAll')); - this._ctrlPicker = fold.addCheckbox(TR('sculptPickColor'), tool._pickColor, this.onColorPick.bind(this, tool, main)); + this._ctrlPicker = fold.addCheckbox( + TR('sculptPickColor'), tool._pickColor, this.onColorPick.bind(this, tool, main) + ); this._ctrls.push(this._ctrlPicker); var materials = []; @@ -194,7 +205,9 @@ GuiTools[Enums.Tools.PAINT] = { var ctrlColor = fold.addColor(TR('sculptColor'), tool._color, cbMatChanged); var ctrlRoughness = fold.addSlider( TR('sculptRoughness'), tool._material[0] * 100, cbMatChanged, 0, 100, 1); - var ctrlMetallic = fold.addSlider(TR('sculptMetallic'), tool._material[1] * 100, cbMatChanged, 0, 100, 1); + var ctrlMetallic = fold.addSlider( + TR('sculptMetallic'), tool._material[1] * 100, cbMatChanged, 0, 100, 1 + ); materials.push(ctrlColor, ctrlRoughness, ctrlMetallic); this._ctrls.push(ctrlColor, ctrlRoughness, ctrlMetallic); tool.setPickCallback(this.onPickedMaterial.bind(this, materials, tool, main)); @@ -273,12 +286,18 @@ GuiTools[Enums.Tools.MASKING] = { this._ctrls.push(addCtrlCulling(tool, fold)); this._main = main; this._tool = tool; - var bci = fold.addDualButton(TR('sculptMaskingClear'), TR('sculptMaskingInvert'), tool, tool, 'clear', 'invert'); - var bbs = fold.addDualButton(TR('sculptMaskingBlur'), TR('sculptMaskingSharpen'), tool, tool, 'blur', 'sharpen'); + var bci = fold.addDualButton( + TR('sculptMaskingClear'), TR('sculptMaskingInvert'), tool, tool, 'clear', 'invert' + ); + var bbs = fold.addDualButton( + TR('sculptMaskingBlur'), TR('sculptMaskingSharpen'), tool, tool, 'blur', 'sharpen' + ); this._ctrls.push(bci[0], bci[1], bbs[0], bbs[1]); // mask extract this._ctrls.push(fold.addTitle(TR('sculptExtractTitle'))); - this._ctrls.push(fold.addSlider(TR('sculptExtractThickness'), tool, '_thickness', -5, 5, 0.001)); + this._ctrls.push( + fold.addSlider(TR('sculptExtractThickness'), tool, '_thickness', -5, 5, 0.001) + ); this._ctrls.push(fold.addButton(TR('sculptExtractAction'), tool, 'extract')); addCtrlAlpha(this._ctrls, fold, tool, this); } diff --git a/src/gui/GuiTopology.js b/src/gui/GuiTopology.js index c964f4bc..d83a683a 100644 --- a/src/gui/GuiTopology.js +++ b/src/gui/GuiTopology.js @@ -25,34 +25,52 @@ class GuiMultiresolution { // multires menu.addTitle(TR('multiresTitle')); - this._ctrlResolution = menu.addSlider(TR('multiresResolution'), 1, this.onResolutionChanged.bind(this), 1, 1, 1); - var dual = menu.addDualButton(TR('multiresReverse'), TR('multiresSubdivide'), this, this, 'reverse', 'subdivide'); + this._ctrlResolution = menu.addSlider( + TR('multiresResolution'), 1, this.onResolutionChanged.bind(this), 1, 1, 1 + ); + var dual = menu.addDualButton( + TR('multiresReverse'), TR('multiresSubdivide'), this, this, 'reverse', 'subdivide' + ); this._ctrlReverse = dual[0]; this._ctrlSubdivide = dual[1]; - dual = this._dualButtonDel = menu.addDualButton(TR('multiresDelLower'), TR('multiresDelHigher'), this, this, 'deleteLower', 'deleteHigher'); + dual = this._dualButtonDel = menu.addDualButton( + TR('multiresDelLower'), TR('multiresDelHigher'), this, this, 'deleteLower', 'deleteHigher' + ); this._ctrlDelLower = dual[0]; this._ctrlDelHigher = dual[1]; - this._ctrlDelLower.domButton.style.background = this._ctrlDelHigher.domButton.style.background = 'rgba(230,53,59,0.35)'; + this._ctrlDelLower.domButton.style.background + = this._ctrlDelHigher.domButton.style.background + = 'rgba(230,53,59,0.35)'; var cbResolution = this.remeshResolution.bind(this); // surface nets remeshing menu.addTitle(TR('remeshTitle')); - this._ctrlRes1 = menu.addSlider(TR('remeshResolution'), Remesh.RESOLUTION, cbResolution, 8, 400, 1); + this._ctrlRes1 = menu.addSlider( + TR('remeshResolution'), Remesh.RESOLUTION, cbResolution, 8, 400, 1 + ); menu.addCheckbox(TR('remeshBlock'), Remesh, 'BLOCK'); menu.addButton(TR('remeshRemesh'), this, 'remesh'); // marching cube remeshing menu.addTitle(TR('remeshTitleMC')); - this._ctrlRes2 = menu.addSlider(TR('remeshResolution'), Remesh.RESOLUTION, cbResolution, 8, 400, 1); + this._ctrlRes2 = menu.addSlider( + TR('remeshResolution'), Remesh.RESOLUTION, cbResolution, 8, 400, 1 + ); menu.addCheckbox(TR('remeshSmoothingMC'), Remesh, 'SMOOTHING'); menu.addButton(TR('remeshRemeshMC'), this, 'remeshMC'); // dynamic menu.addTitle(TR('dynamicTitle')); - this._ctrlDynamic = menu.addCheckbox(TR('dynamicActivated'), false, this.dynamicToggleActivate.bind(this)); - this._ctrlDynSubd = menu.addSlider(TR('dynamicSubdivision'), MeshDynamic, 'SUBDIVISION_FACTOR', 0, 100, 1); - this._ctrlDynDec = menu.addSlider(TR('dynamicDecimation'), MeshDynamic, 'DECIMATION_FACTOR', 0, 100, 1); + this._ctrlDynamic = menu.addCheckbox( + TR('dynamicActivated'), false, this.dynamicToggleActivate.bind(this) + ); + this._ctrlDynSubd = menu.addSlider( + TR('dynamicSubdivision'), MeshDynamic, 'SUBDIVISION_FACTOR', 0, 100, 1 + ); + this._ctrlDynDec = menu.addSlider( + TR('dynamicDecimation'), MeshDynamic, 'DECIMATION_FACTOR', 0, 100, 1 + ); this._ctrlDynLin = menu.addCheckbox(TR('dynamicLinear'), MeshDynamic, 'LINEAR'); this.updateDynamicVisibility(false); } @@ -182,7 +200,9 @@ class GuiMultiresolution { main.getStateManager().pushStateAddRemove(mul, mesh, true); } - main.getStateManager().pushState(new StateMultiresolution(main, mul, StateMultiresolution.SUBDIVISION)); + main.getStateManager().pushState( + new StateMultiresolution(main, mul, StateMultiresolution.SUBDIVISION) + ); mul.addLevel(); main.setMesh(mul); main.render(); @@ -227,7 +247,9 @@ class GuiMultiresolution { return; } - main.getStateManager().pushState(new StateMultiresolution(main, mul, StateMultiresolution.DELETE_LOWER)); + main.getStateManager().pushState( + new StateMultiresolution(main, mul, StateMultiresolution.DELETE_LOWER) + ); mul.deleteLower(); this.updateMeshResolution(); } @@ -241,7 +263,9 @@ class GuiMultiresolution { return; } - main.getStateManager().pushState(new StateMultiresolution(main, mul, StateMultiresolution.DELETE_HIGHER)); + main.getStateManager().pushState( + new StateMultiresolution(main, mul, StateMultiresolution.DELETE_HIGHER) + ); mul.deleteHigher(); this.updateMeshResolution(); } @@ -263,7 +287,9 @@ class GuiMultiresolution { if (!isMulti || multimesh._sel === uiRes) return; - main.getStateManager().pushState(new StateMultiresolution(main, multimesh, StateMultiresolution.SELECTION)); + main.getStateManager().pushState( + new StateMultiresolution(main, multimesh, StateMultiresolution.SELECTION) + ); multimesh.selectResolution(uiRes); this._ctrlGui.updateMeshInfo(); main.render(); diff --git a/src/math3d/Camera.ts b/src/math3d/Camera.ts index c367992d..481b884c 100644 --- a/src/math3d/Camera.ts +++ b/src/math3d/Camera.ts @@ -471,14 +471,14 @@ class Camera { var lastR = 0; var tStart = (new Date()).getTime(); - this._timers[nTimer] = window.setInterval(function () { + this._timers[nTimer] = window.setInterval(() => { var r = ((new Date()).getTime() - tStart) / duration; r = easeOutQuart(r); cb(r - lastR, r); lastR = r; if (r >= 1.0) this.clearTimerN(nTimer); - }.bind(this), 16.6); + }, 16.6); } private _translateDelta(delta, dr) { diff --git a/src/math3d/Picking.ts b/src/math3d/Picking.ts index ec162b3e..3d4b30e6 100644 --- a/src/math3d/Picking.ts +++ b/src/math3d/Picking.ts @@ -117,7 +117,7 @@ class Picking { return newAlpha; } - constructor(main, xSym) { + constructor(main, xSym = false) { this._main = main; // the camera this._xSym = !!xSym; } diff --git a/src/mesh/Mesh.ts b/src/mesh/Mesh.ts index 9e36f133..2e49690c 100644 --- a/src/mesh/Mesh.ts +++ b/src/mesh/Mesh.ts @@ -24,7 +24,7 @@ mesh.initRender(); // only if gl has been provided var DEF_ROUGHNESS = 0.18; // 0.18; var DEF_METALNESS = 0.08; // 0.08; -class Mesh { +abstract class Mesh { static OPTIMIZE = true; static ID = 0; diff --git a/src/mesh/RenderData.ts b/src/mesh/RenderData.ts index 0b1c62c6..887e1e0d 100644 --- a/src/mesh/RenderData.ts +++ b/src/mesh/RenderData.ts @@ -33,7 +33,7 @@ class RenderData { _alpha = 1.0; _flatColor = new Float32Array([1.0, 0.0, 0.0]); - _mode = WebGL2RenderingContext.TRIANGLES + _mode = WebGLRenderingContext.TRIANGLES constructor(gl: any) { var opts = getOptionsURL(); diff --git a/src/mesh/dynamic/MeshDynamic.ts b/src/mesh/dynamic/MeshDynamic.ts index 1ef63cef..b9323d60 100644 --- a/src/mesh/dynamic/MeshDynamic.ts +++ b/src/mesh/dynamic/MeshDynamic.ts @@ -55,7 +55,7 @@ class MeshDynamic extends Mesh { return MeshDynamic.DECIMATION_FACTOR * 0.01; } - getVerticesProxy() { + override getVerticesProxy() { return this.getVertices(); // for now no proxy sculpting for dynamic meshes } @@ -63,7 +63,7 @@ class MeshDynamic extends Mesh { this._meshData._nbVertices += nb; } - getNbTriangles() { + override getNbTriangles() { return this.getNbFaces(); } @@ -71,7 +71,7 @@ class MeshDynamic extends Mesh { this._meshData._nbFaces += nb; } - getNbEdges() { + override getNbEdges() { return this.getNbTriangles() * 3; } @@ -132,7 +132,7 @@ class MeshDynamic extends Mesh { // TODO This code is weirdly coupled to setShowWireframe as well // What is this even trying to do? - getWireframe() { + override getWireframe() { if (!this._wireframe) { this._wireframe = new Uint32Array(this.getTriangles().length * 2); this.updateWireframe(); @@ -140,7 +140,7 @@ class MeshDynamic extends Mesh { return this._wireframe; } - setShowWireframe(showWireframe) { + override setShowWireframe(showWireframe) { this._wireframe = null; super.setShowWireframe(showWireframe); } @@ -268,7 +268,7 @@ class MeshDynamic extends Mesh { } } - initTopology() { + override initTopology() { var vrings = this.getVerticesRingVert(); var frings = this.getVerticesRingFace(); var i = 0; diff --git a/src/mesh/meshStatic/MeshStatic.ts b/src/mesh/meshStatic/MeshStatic.ts index 3a482466..8abeb9cc 100644 --- a/src/mesh/meshStatic/MeshStatic.ts +++ b/src/mesh/meshStatic/MeshStatic.ts @@ -5,7 +5,7 @@ import RenderData from '../RenderData'; class MeshStatic extends Mesh { - constructor(gl) { + constructor(gl = null) { super(); this._id = Mesh.ID++; // useful id to retrieve a mesh (dynamic mesh, multires mesh, voxel mesh) diff --git a/src/render/Attribute.ts b/src/render/Attribute.ts index 2690366a..c7c1009d 100644 --- a/src/render/Attribute.ts +++ b/src/render/Attribute.ts @@ -1,11 +1,11 @@ class Attribute { - _gl: WebGL2RenderingContext; + _gl: WebGLRenderingContext; _location: GLint; _size: number; _type: number; - constructor(gl: WebGL2RenderingContext, program, name, size, type) { + constructor(gl: WebGLRenderingContext, program, name, size, type) { this._gl = gl; // webgl context this._location = gl.getAttribLocation(program, name); // the location this._size = size; // numbe of components diff --git a/src/render/Buffer.ts b/src/render/Buffer.ts index 9c5a1551..48dbac93 100644 --- a/src/render/Buffer.ts +++ b/src/render/Buffer.ts @@ -1,12 +1,12 @@ class Buffer { - _gl: WebGL2RenderingContext; + _gl: WebGLRenderingContext; _buffer: WebGLBuffer; _type: number; _hint: number; _size: number; - constructor(gl: WebGL2RenderingContext, type, hint) { + constructor(gl: WebGLRenderingContext, type, hint) { this._gl = gl; // webgl context this._buffer = gl.createBuffer(); // the buffer this._type = type; // the type (vert data vs index) diff --git a/src/render/WebGLCaps.ts b/src/render/WebGLCaps.ts index a39d82f9..0ba1c6a0 100644 --- a/src/render/WebGLCaps.ts +++ b/src/render/WebGLCaps.ts @@ -4,7 +4,7 @@ const HALF_FLOAT = 0x8D61; class WebGLCaps { - static _gl: WebGL2RenderingContext = null; + static _gl: WebGLRenderingContext = null; static _checkRTT = {}; static _webGLExtensions: { [k: string]: any } = {}; @@ -77,7 +77,7 @@ class WebGLCaps { /// until this method is called. /// /// TODO: Turn into true singleton - static initWebGLExtensions(gl: WebGL2RenderingContext) { + static initWebGLExtensions(gl: WebGLRenderingContext) { WebGLCaps._gl = gl; var supported = gl.getSupportedExtensions(); var ext = WebGLCaps._webGLExtensions; diff --git a/src/render/shaders/IShaderBase.d.ts b/src/render/shaders/IShaderBase.d.ts index 883fb0bb..68430715 100644 --- a/src/render/shaders/IShaderBase.d.ts +++ b/src/render/shaders/IShaderBase.d.ts @@ -34,16 +34,16 @@ export interface IShaderBase { fragColorUniforms: string; fragColorFunction: string; }; - getOrCreate: (gl: WebGL2RenderingContext) => IShaderBase; - initUniforms: (gl: WebGL2RenderingContext) => void; + getOrCreate: (gl: WebGLRenderingContext) => IShaderBase; + initUniforms: (gl: WebGLRenderingContext) => void; updateUniforms: (mesh: any, main?: any) => void; draw: (mesh: any, main: any, other: any | null) => void; drawBuffer: (mesh: any) => void; - setTextureParameters: (gl: WebGL2RenderingContext, tex: HTMLImageElement) => void; - onLoadTexture0: (gl: WebGL2RenderingContext, tex: HTMLImageElement, main: any) => void; - getDummyTexture: (gl: WebGL2RenderingContext) => WebGLTexture; - getOrCreateTexture0: (gl: WebGL2RenderingContext, texPath: string, main: any) => false | WebGLTexture; - initAttributes: (gl: WebGL2RenderingContext) => void; + setTextureParameters: (gl: WebGLRenderingContext, tex: HTMLImageElement) => void; + onLoadTexture0: (gl: WebGLRenderingContext, tex: HTMLImageElement, main: any) => void; + getDummyTexture: (gl: WebGLRenderingContext) => WebGLTexture; + getOrCreateTexture0: (gl: WebGLRenderingContext, texPath: string, main: any) => false | WebGLTexture; + initAttributes: (gl: WebGLRenderingContext) => void; bindAttributes: (mesh: any) => void; unbindAttributes: () => void; getCopy: () => IShaderBase; diff --git a/src/render/shaders/ShaderBase.ts b/src/render/shaders/ShaderBase.ts index 458c94a2..944813a7 100644 --- a/src/render/shaders/ShaderBase.ts +++ b/src/render/shaders/ShaderBase.ts @@ -112,7 +112,7 @@ let ShaderBase: IShaderBase = { ].join('\n'), }, - getOrCreate(gl: WebGL2RenderingContext): IShaderBase { + getOrCreate(gl: WebGLRenderingContext): IShaderBase { if (this.program !== null) { return this; } @@ -153,7 +153,7 @@ let ShaderBase: IShaderBase = { return this; }, - initUniforms(gl: WebGL2RenderingContext) { + initUniforms(gl: WebGLRenderingContext) { var program = this.program; var unifNames = this.uniformNames; var unifs = this.uniforms; @@ -213,7 +213,7 @@ let ShaderBase: IShaderBase = { this.unbindAttributes(); }, - setTextureParameters(gl: WebGL2RenderingContext, tex: HTMLImageElement) { + setTextureParameters(gl: WebGLRenderingContext, tex: HTMLImageElement) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); if (Utils.isPowerOfTwo(tex.width) && Utils.isPowerOfTwo(tex.height)) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); @@ -227,7 +227,7 @@ let ShaderBase: IShaderBase = { } }, - onLoadTexture0(gl: WebGL2RenderingContext, tex: HTMLImageElement, main) { + onLoadTexture0(gl: WebGLRenderingContext, tex: HTMLImageElement, main) { this.texture0 = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture0); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tex); @@ -238,8 +238,8 @@ let ShaderBase: IShaderBase = { } }, - getDummyTexture(gl: WebGL2RenderingContext): WebGLTexture { - if (this._dummyTex !== null) + getDummyTexture(gl: WebGLRenderingContext): WebGLTexture { + if (this._dummyTex != null) return this._dummyTex; this._dummyTex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this._dummyTex); @@ -248,8 +248,8 @@ let ShaderBase: IShaderBase = { return this._dummyTex; }, - getOrCreateTexture0(gl: WebGL2RenderingContext, texPath: string, main): WebGLTexture | false { - if (this.texture0 !== undefined) + getOrCreateTexture0(gl: WebGLRenderingContext, texPath: string, main): WebGLTexture | false { + if (this.texture0 != null) return this.texture0; this.texture0 = null; // trigger loading var tex = new Image(); @@ -258,7 +258,7 @@ let ShaderBase: IShaderBase = { return false; }, - initAttributes(gl: WebGL2RenderingContext) { + initAttributes(gl: WebGLRenderingContext) { var program = this.program; var attrs = this.attributes; attrs.aVertex = new Attribute(gl, program, 'aVertex', 3, gl.FLOAT); diff --git a/src/render/shaders/ShaderMatcap.ts b/src/render/shaders/ShaderMatcap.ts index 072d4ad3..22ba5cdd 100644 --- a/src/render/shaders/ShaderMatcap.ts +++ b/src/render/shaders/ShaderMatcap.ts @@ -13,7 +13,7 @@ import { IShaderBase } from './IShaderBase'; interface IShaderMatcap { textures: {}, - createTexture: (gl: WebGL2RenderingContext, img: HTMLImageElement, idMaterial: string) => void + createTexture: (gl: WebGLRenderingContext, img: HTMLImageElement, idMaterial: string) => void matcaps: { path: string, name: string }[] } diff --git a/src/render/shaders/ShaderPBR.ts b/src/render/shaders/ShaderPBR.ts index 746496f1..d3868a29 100644 --- a/src/render/shaders/ShaderPBR.ts +++ b/src/render/shaders/ShaderPBR.ts @@ -16,7 +16,7 @@ interface IShaderPBR { environments: any[], idEnv: number, exposure: number, - onLoadEnvironment: (xhr: HTMLImageElement | XMLHttpRequest, gl: WebGL2RenderingContext, main: any, env: any) => void, + onLoadEnvironment: (xhr: HTMLImageElement | XMLHttpRequest, gl: WebGLRenderingContext, main: any, env: any) => void, getOrCreateEnvironment: (gl: WebGLRenderingContext, main: any, env: any) => boolean, } diff --git a/tsconfig.json b/tsconfig.json index 11bdcd9d..8f39eccd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,15 @@ { + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "build/", + "dist/", + "node_modules" + ], "compilerOptions": { "allowJs": true, - "checkJs": true, + "checkJs": false, "isolatedModules": true, "lib": [ "es2023", diff --git a/yarn.lock b/yarn.lock index 922e0993..cee9d999 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2841,6 +2841,11 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== +tsc@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/tsc/-/tsc-2.0.4.tgz#5f6499146abea5dca4420b451fa4f2f9345238f5" + integrity sha512-fzoSieZI5KKJVBYGvwbVZs/J5za84f2lSTLPYf6AGiIf43tZ3GNrI1QzTLcjtyDDP4aLxd46RTZq1nQxe7+k5Q== + tslib@^2.4.0: version "2.6.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"