diff --git a/web/app/3d/ctrl.js b/web/app/3d/ctrl.js index 025d8506..06bf2fc3 100644 --- a/web/app/3d/ctrl.js +++ b/web/app/3d/ctrl.js @@ -163,7 +163,7 @@ function UI(app) { IO.exportTextData(stl.data[0], app.id + ".stl"); }); app.bus.subscribe("solid-pick", function(solid) { - new TransformWizard(app.viewer, solid).createUI(mainBox); + ui.registerWizard(new TransformWizard(app.viewer, solid)); }); } diff --git a/web/app/3d/wizards/transform.js b/web/app/3d/wizards/transform.js index ab4d6e07..c2dfd85b 100644 --- a/web/app/3d/wizards/transform.js +++ b/web/app/3d/wizards/transform.js @@ -1,35 +1,130 @@ -import * as tk from '../../ui/toolkit' +import {AXIS, IDENTITY_BASIS} from '../../math/l3space' +import * as tk from '../../ui/toolkit.js' +import {FACE_COLOR} from '../cad-utils' +import {addOkCancelLogic} from './wizard-commons' -export function TransformWizard(viewer, solid) { +export function TransformWizard(viewer, solid, initParams) { + this.previewGroup = new THREE.Object3D(); this.viewer = viewer; this.solid = solid; + addOkCancelLogic(this); + if (!initParams) { + initParams = TransformWizard.DEFAULT_PARAMS; + } + this._cancelClick = this.cancelClick; + this.cancelClick = function() { + this.discardChanges(); + this._cancelClick(); + }; + this.ui = {}; + this.initialPosition = this.solid.cadGroup.position.clone(); + this.viewer.transformControls.attach(this.solid.cadGroup); + this.transfomControlListener = tk.methodRef(this, "synchToUI"); + this.viewer.transformControls.addEventListener( 'objectChange', this.transfomControlListener ); + this.createUI.apply(this, initParams); + this.synch(); } -TransformWizard.prototype.createUI = function(alignComponent) { - this.viewer.transformControls.attach(this.solid.cadGroup); +TransformWizard.DEFAULT_PARAMS = [0, 0, 0, 0, 0, 0, 1]; + +TransformWizard.prototype.discardChanges = function() { + this.solid.cadGroup.position.copy(this.initialPosition); +}; + +TransformWizard.prototype.update = function(x, y, z, rotationX, rotationY, rotationZ, rotationW) { + this.solid.cadGroup.position.setX(x); + this.solid.cadGroup.position.setX(y); + this.solid.cadGroup.position.setX(z); + + this.solid.cadGroup.quaternion.x = rotationX; + this.solid.cadGroup.quaternion.y = rotationY; + this.solid.cadGroup.quaternion.z = rotationZ; + this.solid.cadGroup.quaternion.w = rotationW; + + this.viewer.transformControls.update(); this.viewer.render(); - var box = new tk.Box(); - box.root.css({left : (alignComponent.root.width() + 10) + 'px', top : 0}); - var folder = new tk.Folder("Transformation"); - tk.add(box, folder); - var wizard = this; - function close() { - box.close(); - wizard.dispose(); +}; + +TransformWizard.prototype.createUI = function(x, y, z, rotationX, rotationY, rotationZ, rotationW) { + var ui = this.ui; + ui.box = new tk.Box(); + var folder = new tk.Folder("Solid Transform"); + var position = new tk.Folder("Position"); + var rotation = new tk.Folder("Rotation"); + tk.add(folder, position); + tk.add(folder, rotation); + tk.add(ui.box, folder); + ui.x = new tk.Number("Position X", x, 1, 6); + ui.y = new tk.Number("Position Y", y, 1, 6); + ui.z = new tk.Number("Position Z", z, 1, 6); + ui.rotationX = tk.config(new tk.Number("Rotation X", rotationX, 0.1, 6), {min: -1, max: 1}); + ui.rotationY = tk.config(new tk.Number("Rotation Y", rotationY, 0.1, 6), {min: -1, max: 1}); + ui.rotationZ = tk.config(new tk.Number("Rotation Z", rotationZ, 0.1, 6), {min: -1, max: 1}); + ui.rotationW = tk.config(new tk.Number("Rotation W", rotationW, 0.1, 6), {min: -1, max: 1}); + ui.mode = new tk.InlineRadio(['translate(T)', 'rotate(R)'], ['translate', 'rotate'], 0); + tk.add(position, ui.x); + tk.add(position, ui.y); + tk.add(position, ui.z); + tk.add(rotation, ui.rotationX); + tk.add(rotation, ui.rotationY); + tk.add(rotation, ui.rotationZ); + tk.add(rotation, ui.rotationW); + tk.add(rotation, ui.mode); + this.ui.mode.root.find('input:radio').change(tk.methodRef(this, "modeChanged")); + var onChange = tk.methodRef(this, "synch"); + ui.x.input.on('t-change', onChange); + ui.y.input.on('t-change', onChange); + ui.z.input.on('t-change', onChange); + ui.rotationX.input.on('t-change', onChange); + ui.rotationY.input.on('t-change', onChange); + ui.rotationZ.input.on('t-change', onChange); + tk.add(folder, new tk.ButtonRow(["Cancel", "OK"], [tk.methodRef(this, "cancelClick"), tk.methodRef(this, "okClick")])); +}; + +TransformWizard.prototype.modeChanged = function() { + var mode = this.ui.mode.getValue(); + this.viewer.transformControls.setMode(mode); +}; + +TransformWizard.prototype.synchToUI = function() { + function round(val){return val.toFixed(6);} + var ui = this.ui; + ui.x.input.val( round(this.solid.cadGroup.position.x) ); + ui.y.input.val( round(this.solid.cadGroup.position.y) ); + ui.z.input.val( round(this.solid.cadGroup.position.z) ); + ui.rotationX.input.val( round(this.solid.cadGroup.quaternion.x) ); + ui.rotationY.input.val( round(this.solid.cadGroup.quaternion.y) ); + ui.rotationZ.input.val( round(this.solid.cadGroup.quaternion.z) ); + ui.rotationW.input.val( round(this.solid.cadGroup.quaternion.w) ); + this.viewer.render(); +}; + +TransformWizard.prototype.synch = function() { + this.update.apply(this, this.getParams()); + this.viewer.render(); +}; + +TransformWizard.prototype.getParams = function() { + return [this.ui.x.val(), this.ui.y.val(), this.ui.z.val(), + this.ui.rotationX.val(), this.ui.rotationY.val(), this.ui.rotationZ.val(), this.ui.rotationW.val()]; +}; + +TransformWizard.prototype.createRequest = function() { + var params = this.getParams(); + return { + type: 'TRANSFORM', + solids : [], + params : { + position: {x : params[0], y : params[1], z : params[2]}, + rotate: {x : params[3], y : params[4], z : params[5]} + } , + protoParams : params } - function apply() { - //app.craft.modify({ - // type: 'PLANE', - // solids : [], - // params : wizard.operationParams, - // protoParams : protoParams() - //}, overiding); - close(); - } - tk.add(folder, new tk.ButtonRow(["Cancel", "Apply"], [close, apply])); }; TransformWizard.prototype.dispose = function() { + this.viewer.transformControls.removeEventListener( 'objectChange', this.transfomControlListener ); this.viewer.transformControls.detach(this.solid.cadGroup); + this.ui.box.close(); this.viewer.render(); }; diff --git a/web/app/ui/toolkit.js b/web/app/ui/toolkit.js index a650b441..ef167833 100644 --- a/web/app/ui/toolkit.js +++ b/web/app/ui/toolkit.js @@ -47,7 +47,7 @@ export function InlineRadio(choiceLabels, choiceValues, checkedIndex) { this.inputs = []; for (var i = 0; i < choiceLabels.length; i++) { var checked = checkedIndex === i ? "checked" : ''; - var label = $(''); + var label = $(''); this.inputs.push(label.find("input")); this.root.append(label); } @@ -110,7 +110,7 @@ function NumberWidget(name, initValue, baseStep, round) { if (scope.min != null && val < scope.min) { val = scope.min; } - if (scope.max != null && val > scope.min) { + if (scope.max != null && val > scope.max) { val = scope.max; } if (round !== 0) { diff --git a/web/css/toolkit.css b/web/css/toolkit.css index 51a2f803..2100f56e 100644 --- a/web/css/toolkit.css +++ b/web/css/toolkit.css @@ -82,6 +82,14 @@ color: #eee; } +.tc-ctrl input[type=checkbox] { + vertical-align: sub; +} + +.tc-ctrl input[type=radio] { + vertical-align: sub; +} + .tc-scroll { overflow-y: auto; overflow-x: hidden; @@ -140,6 +148,10 @@ padding-right: 5px; } +input[type=checkbox] { + vertical-align: sub; +} + .tc-pseudo-btn { cursor : pointer; }