mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-27 10:55:56 +01:00
pushing expressions to the sketcher
This commit is contained in:
parent
9cf9f18e37
commit
dbd871c920
10 changed files with 78 additions and 24 deletions
|
|
@ -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)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <div className={ls.root} ref={this.keepRef}>
|
||||
<Controls pointer={pointer} eoh={eof} setHistoryPointer={this.setHistoryPointerAndRequestScroll}/>
|
||||
<Controls rebuild={rebuild} history={history} pointer={pointer} eoh={eof} setHistoryPointer={this.setHistoryPointerAndRequestScroll}/>
|
||||
<div className={ls.scroller} onClick={e => scrolly.scrollLeft -= 60}><Fa icon='caret-left'/></div>
|
||||
<div className={ls.history} ref={el => scrolly = el}>
|
||||
{history.map((m, i) => <React.Fragment key={i}>
|
||||
|
|
@ -102,10 +103,13 @@ function Handle() {
|
|||
</svg>;
|
||||
}
|
||||
|
||||
function Controls({pointer, eoh, setHistoryPointer}) {
|
||||
function Controls({rebuild, history, pointer, eoh, setHistoryPointer, }) {
|
||||
const noB = pointer===-1;
|
||||
const noF = pointer===eoh;
|
||||
return <React.Fragment>
|
||||
<button disabled={!history.length} className={cx(ls.controlBtn)} onClick={rebuild}>
|
||||
<Fa icon='repeat' fw/>
|
||||
</button>
|
||||
<div className={cx(ls.controlBtn, noB&&ls.disabled)} onClick={noB?undefined :() => setHistoryPointer(pointer-1)}>
|
||||
<Fa icon='step-backward' fw/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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') {
|
||||
|
|
|
|||
Loading…
Reference in a new issue