From f77083e4152c995b1437a8bfdb567cf9a1c1f524 Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Tue, 24 Nov 2015 01:26:51 -0800 Subject: [PATCH] Save 3D --- web/app/3d/ctrl.js | 31 +++++++++++----------- web/app/3d/main.js | 35 ++++++++++++++++++++----- web/app/engine.js | 1 + web/app/math/math.js | 8 ++++++ web/app/ui/toolkit.js | 13 +++++++++ web/app/workbench.js | 61 ++++++++++++++++++++++++++++++++++++++++--- web/css/toolkit.css | 8 ++++++ 7 files changed, 133 insertions(+), 24 deletions(-) diff --git a/web/app/3d/ctrl.js b/web/app/3d/ctrl.js index 45e97221..4e4fda8c 100644 --- a/web/app/3d/ctrl.js +++ b/web/app/3d/ctrl.js @@ -31,18 +31,17 @@ TCAD.UI = function(app) { tk.add(cameraFolder, new tk.Number("z")); tk.add(mainBox, objectsFolder); tk.add(mainBox, modificationsFolder); - var modificationsTreeComp = new tk.Tree(); - tk.add(modificationsFolder, modificationsTreeComp); + var modificationsListComp = new tk.List(); + tk.add(modificationsFolder, modificationsListComp); var ui = this; this.app.bus.subscribe("craft", function() { - var data = {children : []}; + modificationsListComp.root.empty(); for (var i = 0; i < app.craft.history.length; i++) { var op = app.craft.history[i]; - data.children.push(ui.getInfoForOp(op)); + modificationsListComp.addRow(ui.getInfoForOp(op)); } - modificationsTreeComp.set(data); }); function cutExtrude(isCut) { @@ -147,10 +146,9 @@ TCAD.UI = function(app) { tk.add(folder, new tk.ButtonRow(["Cancel", "OK"], [close, ok])); }); printSolids.root.click(function () { - app.viewer.scene.children.map(function(o) { - if (o.geometry instanceof TCAD.Solid) { - console.log(JSON.stringify(o.geometry.csg)); - } + app.findAllSolids().map(function(o) { + console.log("Solid ID: " + o.tCadId); + console.log(JSON.stringify(o.csg)); }); }); printFace.root.click(function () { @@ -182,15 +180,18 @@ TCAD.UI = function(app) { }; TCAD.UI.prototype.getInfoForOp = function(op) { - var info = {name : op.type}; + var p = op.params; + var norm2 = TCAD.math.norm2; if ('CUT' === op.type) { - info.name += " (" + op.depth + ")"; - info.children = [{name : "depth : " + op.depth}] + return op.type + " (" + norm2(p.target) + ")"; + } else if ('PAD' === op.type) { + return op.type + " (" + norm2(p.target) + ")"; } else if ('BOX' === op.type) { - info.name += " (" + op.size + ")"; - info.children = [{name : "size : " + op.size}] + return op.type + " (" + op.size + ")"; + } else if ('PLANE' === op.type) { + return op.type + " (" + p.depth + ")"; } - return info; + return op.type; }; TCAD.UI.prototype.setSolid = function(solid) { diff --git a/web/app/3d/main.js b/web/app/3d/main.js index 3b6244c9..f1812903 100644 --- a/web/app/3d/main.js +++ b/web/app/3d/main.js @@ -13,6 +13,8 @@ TCAD.App = function() { if (this.id == '$scratch$') { this.addBox(); + } else { + this.load(); } this._refreshSketches(); @@ -73,10 +75,28 @@ TCAD.App.prototype.findFace = function(faceId) { return null; }; +TCAD.App.prototype.indexEntities = function() { + var out = {solids : {}, faces : {}}; + var solids = this.findAllSolids(); + for (var i = 0; i < solids.length; i++) { + var solid = solids[i]; + out.solids[solid.tCadId] = solid; + for (var j = 0; j < solid.polyFaces.length; j++) { + var face = solid.polyFaces[j]; + out.faces[face.id] = face; + } + } + return out; +}; + TCAD.App.prototype.faceStorageKey = function(polyFaceId) { return "TCAD.projects."+this.id+".sketch." + polyFaceId; }; +TCAD.App.prototype.projectStorageKey = function(polyFaceId) { + return "TCAD.projects."+this.id; +}; + TCAD.App.prototype.sketchFace = function() { if (this.viewer.selectionMgr.selection.length == 0) { return; @@ -289,12 +309,15 @@ TCAD.App.prototype._refreshSketches = function() { TCAD.App.prototype.save = function() { var data = {}; - data.solids = []; - data.planes = []; - data.history = this.craft.history - var solid = this.findAllSolids(); - for (var i = 0; i < solid.length; i++) { - var solid = solid[i]; + data.history = this.craft.history; + localStorage.setItem(this.projectStorageKey(), JSON.stringify(data)); +}; +TCAD.App.prototype.load = function() { + var project = localStorage.getItem(this.projectStorageKey()); + if (!!project) { + var data = JSON.parse(project); + this.craft.loadHistory(data.history); + } }; diff --git a/web/app/engine.js b/web/app/engine.js index 03fe05b6..1ff7a22c 100644 --- a/web/app/engine.js +++ b/web/app/engine.js @@ -181,6 +181,7 @@ TCAD.utils.createPlane = function(basis, depth, boundingPolygon, shared) { plane.vanish(); bbox.expand(20); var newPlane = TCAD.utils.createPlane(basis, depth, bbox.toPolygon(), sketchFace.csgGroup.shared); + newPlane.geometry.tCadId = plane.tCadId; TCAD.SketchFace.prototype.syncSketches.call(newPlane.geometry.polyFaces[0], geom); parent.add(newPlane); } diff --git a/web/app/math/math.js b/web/app/math/math.js index 18ac4fd8..11aa2413 100644 --- a/web/app/math/math.js +++ b/web/app/math/math.js @@ -110,4 +110,12 @@ TCAD.math.circleFromPoints = function(p1, p2, p3) { center.x = (bc * (p2.y - p3.y) - cd * (p1.y - p2.y)) * idet; center.y = (cd * (p1.x - p2.x) - bc * (p2.x - p3.x)) * idet; return center; +}; + +TCAD.math.norm2 = function(vec) { + var sq = 0; + for (var i = 0; i < vec.length; i++) { + sq += vec[i] * vec[i]; + } + return Math.sqrt(sq); }; \ No newline at end of file diff --git a/web/app/ui/toolkit.js b/web/app/ui/toolkit.js index 44239121..890e8aed 100644 --- a/web/app/ui/toolkit.js +++ b/web/app/ui/toolkit.js @@ -138,6 +138,19 @@ TCAD.toolkit.ButtonRow = function(captions, actions) { } }; +TCAD.toolkit.List = function() { + this.root = $('
', {class: 'tc-tree'}); +}; + +TCAD.toolkit.List.prototype.addRow = function(name) { + var row = $('
', { + text: name, class: 'tc-row tc-pseudo-btn', + css: {'margin-left': '10px'} + }); + this.root.append(row); + return row; +}; + TCAD.toolkit.Tree = function() { this.root = $('
', {class: 'tc-tree'}); }; diff --git a/web/app/workbench.js b/web/app/workbench.js index d0c97c7c..bd782918 100644 --- a/web/app/workbench.js +++ b/web/app/workbench.js @@ -808,6 +808,24 @@ TCAD.craft.cut = function(app, request) { TCAD.Craft = function(app) { this.app = app; this.history = []; + this.historyPointer = -1; +}; + +TCAD.Craft.prototype.loadHistory = function(history) { + this.history = -1; + this.history = history; + this.reset(history); + this.app.bus.notify('craft'); + this.app.viewer.render(); +}; + +TCAD.Craft.prototype.reset = function(modifications) { + TCAD.utils.SOLID_COUNTER = 0; + TCAD.utils.SHARED_COUNTER = 0; + for (var i = 0; i < modifications.length; i++) { + var request = TCAD.craft.materialize(this.app.indexEntities(), modifications[i]); + this.modifyInternal(request); + } }; TCAD.Craft.prototype.current = function() { @@ -819,8 +837,16 @@ TCAD.craft.detach = function(request) { for (var prop in request) { if (request.hasOwnProperty(prop)) { var value = request[prop]; - if (typeof(value) === 'object' && value.id !== undefined) { + if (prop == 'solids') { + detachedConfig[prop] = value.map(function(s){return s.tCadId}); + } else if (prop == 'face') { detachedConfig[prop] = value.id; + } else if (prop == 'target') { + detachedConfig[prop] = [value.x, value.y, value.z]; + } else if (prop == 'basis') { + detachedConfig[prop] = value.map(function(v){return [v.x, v.y, v.z]}); + } else if (prop == 'params') { + detachedConfig[prop] = TCAD.craft.detach(value); } else { detachedConfig[prop] = value; } @@ -829,8 +855,34 @@ TCAD.craft.detach = function(request) { return detachedConfig }; -TCAD.Craft.prototype.modify = function(request) { +TCAD.craft.materialize = function(index, detachedConfig) { + var request = {}; + function required(value) { + if (value == null || value == undefined) throw "value is required"; + return value; + } + for (var prop in detachedConfig) { + if (detachedConfig.hasOwnProperty(prop)) { + var value = detachedConfig[prop]; + if (prop == 'solids') { + request[prop] = value.map(function(id){return required(index.solids[id])}); + } else if (prop == 'target') { + request[prop] = new TCAD.Vector().set3(value); + } else if (prop == 'face') { + request[prop] = required(index.faces[value]); + } else if (prop == 'basis') { + request[prop] = value.map(function(v) {return new TCAD.Vector().set3(v)}); + } else if (prop == 'params') { + request[prop] = TCAD.craft.materialize(index, value); + } else { + request[prop] = value; + } + } + } + return request; +}; +TCAD.Craft.prototype.modifyInternal = function(request) { var op = TCAD.craft.OPS[request.type]; if (!op) return; @@ -844,9 +896,12 @@ TCAD.Craft.prototype.modify = function(request) { for (i = 0; i < newSolids.length; i++) { this.app.viewer.workGroup.add(newSolids[i].meshObject); } +}; + +TCAD.Craft.prototype.modify = function(request) { + this.modifyInternal(request); this.history.push(TCAD.craft.detach(request)); this.app.bus.notify('craft'); - this.app.viewer.render(); }; diff --git a/web/css/toolkit.css b/web/css/toolkit.css index 6b46a754..916072d3 100644 --- a/web/css/toolkit.css +++ b/web/css/toolkit.css @@ -130,3 +130,11 @@ .tc-inline-radio label { padding-right: 5px; } + +.tc-pseudo-btn { + cursor : pointer; +} + +.tc-pseudo-btn:hover { + background-color: #000; +}