diff --git a/web/app/cad/craft/craftPlugin.js b/web/app/cad/craft/craftPlugin.js
index d51727e5..674595fa 100644
--- a/web/app/cad/craft/craftPlugin.js
+++ b/web/app/cad/craft/craftPlugin.js
@@ -50,6 +50,12 @@ export function activate({streams, services}) {
pointer: modifications.length - 1
});
}
+
+ function rebuild() {
+ const mods = streams.craft.modifications.value;
+ reset([]);
+ streams.craft.modifications.next(mods);
+ }
function runRequest(request) {
let op = services.operation.get(request.type);
@@ -79,7 +85,7 @@ export function activate({streams, services}) {
}
services.craft = {
- modify, modifyInHistoryAndStep, reset, runRequest,
+ modify, modifyInHistoryAndStep, reset, runRequest, rebuild,
historyTravel: historyTravel(streams.craft.modifications)
};
diff --git a/web/app/cad/craft/ui/HistoryTimeline.jsx b/web/app/cad/craft/ui/HistoryTimeline.jsx
index 6293fc44..99b24384 100644
--- a/web/app/cad/craft/ui/HistoryTimeline.jsx
+++ b/web/app/cad/craft/ui/HistoryTimeline.jsx
@@ -19,19 +19,20 @@ import {aboveElement} from '../../../../../modules/ui/positionUtils';
inProgressOperation: insertOperationReq.type,
getOperation: type => operationRegistry[type]||EMPTY_OBJECT
})))
-@mapContext(({streams}) => ({
+@mapContext(({streams, services}) => ({
remove: atIndex => streams.craft.modifications.update(modifications => removeAndDropDependants(modifications, atIndex)),
cancel: () => streams.craft.modifications.update(modifications => finishHistoryEditing(modifications)),
- setHistoryPointer: pointer => streams.craft.modifications.update(({history}) => ({history, pointer}))
+ setHistoryPointer: pointer => streams.craft.modifications.update(({history}) => ({history, pointer})),
+ rebuild: () => services.craft.rebuild()
}))
export default class HistoryTimeline extends React.Component {
render() {
- let {history, pointer, setHistoryPointer, remove, getOperation, inProgressOperation} = this.props;
+ let {history, pointer, setHistoryPointer, rebuild, getOperation, inProgressOperation} = this.props;
let scrolly;
let eof = history.length-1;
return
-
+
scrolly.scrollLeft -= 60}>
scrolly = el}>
{history.map((m, i) =>
@@ -102,10 +103,13 @@ function Handle() {
;
}
-function Controls({pointer, eoh, setHistoryPointer}) {
+function Controls({rebuild, history, pointer, eoh, setHistoryPointer, }) {
const noB = pointer===-1;
const noF = pointer===eoh;
return
+
setHistoryPointer(pointer-1)}>
diff --git a/web/app/cad/expressions/expressionsPlugin.js b/web/app/cad/expressions/expressionsPlugin.js
index dcfdeb40..81802e2a 100644
--- a/web/app/cad/expressions/expressionsPlugin.js
+++ b/web/app/cad/expressions/expressionsPlugin.js
@@ -1,6 +1,6 @@
-import {state, stream, merge} from 'lstream';
-import {indexArray} from '../../../../modules/gems/iterables';
-import {NOOP} from '../../../../modules/gems/func';
+import {merge, state} from 'lstream';
+import {indexArray} from 'gems/iterables';
+import {NOOP} from 'gems/func';
export function defineStreams(ctx) {
const script = state('');
@@ -39,8 +39,10 @@ export function activate(ctx) {
return value;
}
ctx.services.expressions = {
- reevaluateExpressions, load, evaluateExpression
+ reevaluateExpressions, load, evaluateExpression,
+ signature: ''
};
+ ctx.streams.expressions.list.attach(list => ctx.services.expressions.signature = Date.now() + '');
ctx.services.action.registerAction({
id: 'expressionsUpdateTable',
appearance: {
diff --git a/web/app/cad/sketch/inPlaceSketcher.js b/web/app/cad/sketch/inPlaceSketcher.js
index 1152b5e9..efd1d23d 100644
--- a/web/app/cad/sketch/inPlaceSketcher.js
+++ b/web/app/cad/sketch/inPlaceSketcher.js
@@ -19,7 +19,7 @@ export class InPlaceSketcher {
return !!this.face
}
- enter(face) {
+ enter(face, headless) {
let viewer3d = this.ctx.services.viewer;
this.face = face;
this.face.ext.view.sketchGroup.visible = false;
@@ -34,6 +34,7 @@ export class InPlaceSketcher {
container.appendChild(canvas);
this.viewer = new Viewer(canvas, IO);
+ this.viewer.parametricManager.externalConstantResolver = this.ctx.services.expressions.evaluateExpression;
this.ctx.streams.sketcherApp = this.viewer.streams;
this.syncWithCamera();
@@ -45,7 +46,7 @@ export class InPlaceSketcher {
this.viewer.io.loadSketch(sketchData);
this.ctx.streams.sketcher.sketchingFace.value = face;
}
-
+
get sketchStorageKey() {
return this.ctx.services.project.sketchStorageKey(this.face.id);
}
@@ -106,7 +107,9 @@ export class InPlaceSketcher {
};
save() {
- this.ctx.services.storage.set(this.sketchStorageKey, this.viewer.io.serializeSketch());
+ this.ctx.services.storage.set(this.sketchStorageKey, this.viewer.io.serializeSketch({
+ expressionsSignature: this.ctx.services.expressions.signature
+ }));
}
}
diff --git a/web/app/cad/sketch/sketcherPlugin.js b/web/app/cad/sketch/sketcherPlugin.js
index bfda96ad..e78b24af 100644
--- a/web/app/cad/sketch/sketcherPlugin.js
+++ b/web/app/cad/sketch/sketcherPlugin.js
@@ -5,6 +5,9 @@ import {InPlaceSketcher} from './inPlaceSketcher';
import sketcherUIContrib from './sketcherUIContrib';
import initReassignSketchMode from './reassignSketchMode';
import sketcherStreams from '../../sketcher/sketcherStreams';
+import {Viewer} from "../../sketcher/viewer2d";
+import {IO} from "../../sketcher/io";
+import {DelegatingPanTool} from "../../sketcher/tools/pan";
export function defineStreams(ctx) {
ctx.streams.sketcher = {
@@ -55,11 +58,34 @@ export function activate(ctx) {
return services.storage.remove(sketchStorageKey);
}
+ const headlessCanvas = document.createElement('canvas');
+ document.createElement('div').appendChild(headlessCanvas);
+
function readSketch(sketchId) {
let savedSketch = getSketchData(sketchId);
if (savedSketch === null) {
return null;
}
+
+ let signature = services.expressions.signature;
+ if (savedSketch && (!savedSketch.metadata || savedSketch.expressionsSignature !== signature)) {
+ try {
+ const viewer = new Viewer(headlessCanvas, IO);
+ viewer.parametricManager.externalConstantResolver = services.expressions.evaluateExpression;
+ viewer.historyManager.init(savedSketch);
+ viewer.io.loadSketch(savedSketch);
+ viewer.parametricManager.refresh();
+ services.storage.set(services.project.sketchStorageKey(sketchId), viewer.io.serializeSketch({
+ expressionsSignature: signature
+ }), true);
+ savedSketch = getSketchData(sketchId);
+ } catch (e) {
+ console.error(e);
+ return null;
+ }
+ }
+
+
try {
return ReadSketch(JSON.parse(savedSketch), sketchId, true);
} catch (e) {
@@ -132,7 +158,14 @@ export function activate(ctx) {
}
}
});
-
+ streams.expressions.table.attach(() => {
+ if (inPlaceEditor.viewer !== null) {
+ inPlaceEditor.viewer.parametricManager.refresh();
+ }
+ updateAllSketches();
+ });
+
+
services.sketcher = {
sketchFace, sketchFace2D, updateAllSketches, getAllSketches, readSketch, hasSketch, inPlaceEditor, reassignSketch,
reassignSketchMode: initReassignSketchMode(ctx)
diff --git a/web/app/cad/storagePlugin.js b/web/app/cad/storagePlugin.js
index 5c9907a1..fd13820d 100644
--- a/web/app/cad/storagePlugin.js
+++ b/web/app/cad/storagePlugin.js
@@ -8,9 +8,11 @@ export function defineStreams(ctx) {
export function activate({services, streams}) {
- function set(key, value) {
+ function set(key, value, quiet) {
localStorage.setItem(key, value);
- notify(key);
+ if (!quiet) {
+ notify(key);
+ }
}
function get(key) {
diff --git a/web/app/cad/tpi/tpiPlugin.js b/web/app/cad/tpi/tpiPlugin.js
index 9664183f..e55271a7 100644
--- a/web/app/cad/tpi/tpiPlugin.js
+++ b/web/app/cad/tpi/tpiPlugin.js
@@ -12,7 +12,7 @@ export function activate({streams, services}) {
return sceneSolid;
}
function addOnScene(sceneSolid, skin) {
- services.cadRegistry.update(null, [sceneSolid]);
+ streams.craft.models.next([sceneSolid]);
services.viewer.render();
}
services.tpi = Object.assign({
diff --git a/web/app/math/vec.js b/web/app/math/vec.js
index bb2520f0..65fccc89 100644
--- a/web/app/math/vec.js
+++ b/web/app/math/vec.js
@@ -1,6 +1,6 @@
export {dotVM} from 'numeric';
-function scalarOperand(v, out, func) {
+export function scalarOperand(v, out, func) {
for (let i = 0; i < v.length; i++) {
out[i] = func(v[i]);
}
diff --git a/web/app/sketcher/io.js b/web/app/sketcher/io.js
index 142c4d52..47502c69 100644
--- a/web/app/sketcher/io.js
+++ b/web/app/sketcher/io.js
@@ -43,8 +43,8 @@ IO.prototype.loadSketch = function(sketchData) {
return this._loadSketch(JSON.parse(sketchData));
};
-IO.prototype.serializeSketch = function() {
- return JSON.stringify(this._serializeSketch());
+IO.prototype.serializeSketch = function(metadata) {
+ return JSON.stringify(this._serializeSketch(metadata));
};
IO.prototype._loadSketch = function(sketch) {
@@ -333,7 +333,7 @@ IO.prototype.cleanUpData = function() {
}
};
-IO.prototype._serializeSketch = function() {
+IO.prototype._serializeSketch = function(metadata) {
var sketch = {};
//sketch.boundary = boundary;
sketch['layers'] = [];
@@ -408,6 +408,7 @@ IO.prototype._serializeSketch = function() {
if (constantDefinition !== undefined && constantDefinition != null && !/^\s*$/.test(constantDefinition)) {
sketch['constants'] = constantDefinition;
}
+ sketch.metadata = metadata;
return sketch;
};
diff --git a/web/app/sketcher/parametric.js b/web/app/sketcher/parametric.js
index 494cdaea..a2886cfb 100644
--- a/web/app/sketcher/parametric.js
+++ b/web/app/sketcher/parametric.js
@@ -19,6 +19,7 @@ class ParametricManager {
this.viewer.params.define('constantDefinition', null);
this.viewer.params.subscribe('constantDefinition', 'parametricManager', this.onConstantsExternalChange, this)();
this.constantResolver = this.createConstantResolver();
+ this.externalConstantResolver = null;
this.messageSink = msg => alert(msg);
}
@@ -28,9 +29,11 @@ class ParametricManager {
}
ParametricManager.prototype.createConstantResolver = function() {
- var pm = this;
- return function(value) {
- var _value = pm.constantTable[value];
+ return value => {
+ var _value = this.constantTable[value];
+ if (_value === undefined && this.externalConstantResolver) {
+ _value = this.externalConstantResolver(value);
+ }
if (_value !== undefined) {
value = _value;
} else if (typeof(value) != 'number') {