@buerli.io/core 0.0.34-beta.0 → 0.0.35-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/geometry/ThreeGeometryCreator.js +284 -0
- package/build/cjs/geometry/index.js +13 -0
- package/build/cjs/index.js +20 -0
- package/build/cjs/store/index.js +46 -0
- package/build/cjs/store/states/buerli.js +97 -0
- package/build/cjs/store/states/canvas.js +18 -0
- package/build/cjs/store/states/drawing.js +44 -0
- package/build/cjs/store/states/geometry.js +110 -0
- package/build/cjs/store/states/graphic.js +87 -0
- package/build/cjs/store/states/message.js +25 -0
- package/build/cjs/store/states/plugin.js +113 -0
- package/build/cjs/store/states/selection.js +226 -0
- package/build/cjs/store/states/structure.js +203 -0
- package/build/cjs/store/store.js +14 -0
- package/build/cjs/store/subscribtion/selection.js +47 -0
- package/build/cjs/store/subscribtion/subscribeToDrawing.js +9 -0
- package/build/cjs/types/ErrorTypes.js +2 -0
- package/build/cjs/types/IGraphicPackage.js +24 -0
- package/build/cjs/types/IStructurePatch.js +2 -0
- package/build/cjs/types/IStructureTree.js +27 -0
- package/build/cjs/types/index.js +16 -0
- package/build/cjs/utils/Math.js +33 -0
- package/build/cjs/utils/Measure.js +576 -0
- package/build/cjs/utils/Timing.js +34 -0
- package/build/{geometry → esm/geometry}/ThreeGeometryCreator.js +0 -0
- package/build/{geometry → esm/geometry}/index.js +0 -0
- package/build/{index.js → esm/index.js} +1 -0
- package/build/{store → esm/store}/index.js +5 -1
- package/build/{store → esm/store}/states/buerli.js +0 -0
- package/build/{store → esm/store}/states/canvas.js +0 -0
- package/build/{store → esm/store}/states/drawing.js +0 -0
- package/build/{store → esm/store}/states/geometry.js +0 -0
- package/build/{store → esm/store}/states/graphic.js +0 -0
- package/build/{store → esm/store}/states/message.js +0 -0
- package/build/{store → esm/store}/states/plugin.js +1 -8
- package/build/{store → esm/store}/states/selection.js +35 -12
- package/build/{store → esm/store}/states/structure.js +0 -0
- package/build/{store → esm/store}/store.js +0 -0
- package/build/esm/store/subscribtion/selection.js +42 -0
- package/build/esm/store/subscribtion/subscribeToDrawing.js +5 -0
- package/build/{types → esm/types}/ErrorTypes.js +0 -0
- package/build/{types → esm/types}/IGraphicPackage.js +0 -0
- package/build/{types → esm/types}/IStructurePatch.js +0 -0
- package/build/{types → esm/types}/IStructureTree.js +0 -0
- package/build/{types → esm/types}/index.js +0 -0
- package/build/{utils → esm/utils}/Math.js +0 -0
- package/build/{utils → esm/utils}/Measure.js +0 -0
- package/build/{utils → esm/utils}/Timing.js +4 -0
- package/build/{geometry → types/geometry}/ThreeGeometryCreator.d.ts +0 -0
- package/build/{geometry → types/geometry}/index.d.ts +0 -0
- package/build/types/index.d.ts +36 -4
- package/build/{store → types/store}/index.d.ts +3 -0
- package/build/{store → types/store}/states/buerli.d.ts +0 -0
- package/build/{store → types/store}/states/canvas.d.ts +0 -0
- package/build/{store → types/store}/states/drawing.d.ts +0 -0
- package/build/{store → types/store}/states/geometry.d.ts +0 -0
- package/build/{store → types/store}/states/graphic.d.ts +0 -0
- package/build/{store → types/store}/states/message.d.ts +0 -0
- package/build/{store → types/store}/states/plugin.d.ts +1 -1
- package/build/{store → types/store}/states/selection.d.ts +1 -0
- package/build/{store → types/store}/states/structure.d.ts +0 -0
- package/build/{store → types/store}/store.d.ts +0 -0
- package/build/types/store/subscribtion/selection.d.ts +5 -0
- package/build/types/store/subscribtion/subscribeToDrawing.d.ts +2 -0
- package/build/types/{ErrorTypes.d.ts → types/ErrorTypes.d.ts} +0 -0
- package/build/types/{IGraphicPackage.d.ts → types/IGraphicPackage.d.ts} +0 -0
- package/build/types/{IStructurePatch.d.ts → types/IStructurePatch.d.ts} +0 -0
- package/build/types/{IStructureTree.d.ts → types/IStructureTree.d.ts} +0 -1
- package/build/types/types/index.d.ts +4 -0
- package/build/{utils → types/utils}/Math.d.ts +0 -0
- package/build/{utils → types/utils}/Measure.d.ts +0 -0
- package/build/{utils → types/utils}/Timing.d.ts +0 -0
- package/package.json +9 -6
- package/build/index.d.ts +0 -35
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.graphicApi = exports.graphicData = void 0;
|
|
4
|
+
////////////////////////////////////////////////////
|
|
5
|
+
// DATA
|
|
6
|
+
////////////////////////////////////////////////////
|
|
7
|
+
const graphicData = () => ({
|
|
8
|
+
containers: {},
|
|
9
|
+
});
|
|
10
|
+
exports.graphicData = graphicData;
|
|
11
|
+
////////////////////////////////////////////////////
|
|
12
|
+
// API
|
|
13
|
+
////////////////////////////////////////////////////
|
|
14
|
+
const graphicApi = (set, get) => ({
|
|
15
|
+
addPackages: (packages) => {
|
|
16
|
+
// Timing.dump('load', `add graphic packages ${graphic.length} ${graphic[0].containers.length}`)
|
|
17
|
+
let cacheChanged = false;
|
|
18
|
+
const newChache = Object.assign({}, get().geometry.cache);
|
|
19
|
+
const addedContainers = {};
|
|
20
|
+
packages.forEach(gr => {
|
|
21
|
+
gr.containers.forEach(cont => {
|
|
22
|
+
addedContainers[cont.id] = cont;
|
|
23
|
+
// If the cached geometry for the added container already exist,
|
|
24
|
+
// it has to be removed from the cache to ensure geometry updates.
|
|
25
|
+
if (newChache[cont.id]) {
|
|
26
|
+
delete newChache[cont.id];
|
|
27
|
+
cacheChanged = true;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
set(state => ({
|
|
32
|
+
graphic: Object.assign(Object.assign({}, state.graphic), { containers: Object.assign(Object.assign({}, state.graphic.containers), addedContainers) }),
|
|
33
|
+
geometry: cacheChanged ? Object.assign(Object.assign({}, state.geometry), { cache: newChache, stamp: Date.now() }) : state.geometry,
|
|
34
|
+
}));
|
|
35
|
+
const { graphic, api } = get();
|
|
36
|
+
/**
|
|
37
|
+
* Update the bounds with the newly added graphic.
|
|
38
|
+
*/
|
|
39
|
+
api.geometry.updateBounds();
|
|
40
|
+
/**
|
|
41
|
+
* Create the geometry for the graphic packages.
|
|
42
|
+
* Only the geometry which does not already exist will be created (@see createGeometryIfNotCached).
|
|
43
|
+
*/
|
|
44
|
+
const containerIds = Object.getOwnPropertyNames(graphic.containers);
|
|
45
|
+
const createGeometry = async () => {
|
|
46
|
+
for (const id of containerIds) {
|
|
47
|
+
api.geometry.createGeometryIfNotCached(id);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
createGeometry().catch();
|
|
51
|
+
// console.log('graphicContainers after add:', Object.getOwnPropertyNames(get().graphic.containers))
|
|
52
|
+
},
|
|
53
|
+
cleanupGraphicRecords: () => {
|
|
54
|
+
const { graphic, geometry, api } = get();
|
|
55
|
+
// collect the used solid ids from the structure tree
|
|
56
|
+
const solidIds = api.structure.collectUsedSolidIds();
|
|
57
|
+
// console.log('solidIds before cleanup:', solidIds)
|
|
58
|
+
// cleanup the graphic containers in the state
|
|
59
|
+
const usedContainers = {};
|
|
60
|
+
const existingContainers = graphic.containers;
|
|
61
|
+
const existingContainerIds = Object.getOwnPropertyNames(existingContainers);
|
|
62
|
+
if (existingContainerIds.length > 0) {
|
|
63
|
+
existingContainerIds.forEach(contIdStr => {
|
|
64
|
+
const contId = Number(contIdStr);
|
|
65
|
+
if (solidIds.indexOf(contId) >= 0) {
|
|
66
|
+
usedContainers[contId] = existingContainers[contId];
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
set({ graphic: Object.assign(Object.assign({}, graphic), { containers: usedContainers }) });
|
|
70
|
+
// console.log('graphicContainers after cleanup:', Object.getOwnPropertyNames(get().graphic.ontainers))
|
|
71
|
+
}
|
|
72
|
+
// cleanup the cached geometry depending on the uses solids
|
|
73
|
+
const usedGeometry = {};
|
|
74
|
+
const existingGeometry = geometry.cache;
|
|
75
|
+
const existingGeometryIds = Object.getOwnPropertyNames(existingGeometry);
|
|
76
|
+
if (existingGeometryIds.length > 0) {
|
|
77
|
+
existingGeometryIds.forEach(contIdStr => {
|
|
78
|
+
const contId = Number(contIdStr);
|
|
79
|
+
if (solidIds.indexOf(contId) >= 0) {
|
|
80
|
+
usedGeometry[contId] = existingGeometry[contId];
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
set({ geometry: Object.assign(Object.assign({}, geometry), { cache: usedGeometry, stamp: Date.now() }) });
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
exports.graphicApi = graphicApi;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getInitialMessageState = exports.BuerliMessageScope = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
exports.BuerliMessageScope = 'BuerliMessageScope';
|
|
6
|
+
const getInitialMessageState = (set, get, api) => ({
|
|
7
|
+
message: {
|
|
8
|
+
data: null,
|
|
9
|
+
timestamp: -1,
|
|
10
|
+
api: messageApi(set, get, api),
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
exports.getInitialMessageState = getInitialMessageState;
|
|
14
|
+
const messageApi = (set, get, api) => ({
|
|
15
|
+
show(message) {
|
|
16
|
+
const newId = uuid_1.v4();
|
|
17
|
+
const msg = get().message;
|
|
18
|
+
set({ message: Object.assign(Object.assign({}, msg), { data: Object.assign({ id: newId }, message), timestamp: Date.now() }) });
|
|
19
|
+
return newId;
|
|
20
|
+
},
|
|
21
|
+
update(id, message) {
|
|
22
|
+
const msg = get().message;
|
|
23
|
+
set({ message: Object.assign(Object.assign({}, msg), { data: Object.assign({ id }, message), timestamp: Date.now() }) });
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPromisePlugin = exports.pluginApi = exports.pluginData = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
const pluginData = () => ({
|
|
6
|
+
feature: [],
|
|
7
|
+
global: [],
|
|
8
|
+
refs: {},
|
|
9
|
+
active: {
|
|
10
|
+
feature: null,
|
|
11
|
+
global: [],
|
|
12
|
+
},
|
|
13
|
+
visible: [],
|
|
14
|
+
});
|
|
15
|
+
exports.pluginData = pluginData;
|
|
16
|
+
const pluginApi = (set, get) => ({
|
|
17
|
+
setActiveFeature: (id) => {
|
|
18
|
+
set(state => {
|
|
19
|
+
let plugins = state.plugin.refs;
|
|
20
|
+
const oldPlugin = state.plugin.active.feature !== null && state.plugin.refs[state.plugin.active.feature];
|
|
21
|
+
if (oldPlugin && state.plugin.active.feature !== id && !oldPlugin.persistent && id !== null) {
|
|
22
|
+
// Reset plugin-state when the plugin is re-activated, not persistent and has not been active all along
|
|
23
|
+
const initState = oldPlugin.initialState || {};
|
|
24
|
+
plugins = Object.assign(Object.assign({}, plugins), { [oldPlugin.id]: Object.assign(Object.assign({}, oldPlugin), { state: typeof initState === 'function' ? initState(get().id, id) : initState }) });
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
plugin: Object.assign(Object.assign({}, state.plugin), { active: Object.assign(Object.assign({}, state.plugin.active), { feature: id }), refs: plugins }),
|
|
28
|
+
selection: Object.assign(Object.assign({}, state.selection), { active: null }),
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
setVisiblePlugin: (id, visible) => {
|
|
33
|
+
set(currentState => {
|
|
34
|
+
const filtered = currentState.plugin.visible.filter(p => p !== id);
|
|
35
|
+
if (visible)
|
|
36
|
+
filtered.push(id);
|
|
37
|
+
return {
|
|
38
|
+
plugin: Object.assign(Object.assign({}, currentState.plugin), { visible: filtered }),
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
setActiveGlobal: (id, active) => {
|
|
43
|
+
set(currentState => {
|
|
44
|
+
if (currentState.plugin.global.indexOf(id) === -1) {
|
|
45
|
+
console.warn('Given plugin id does not exist.');
|
|
46
|
+
return currentState;
|
|
47
|
+
}
|
|
48
|
+
const filtered = currentState.plugin.active.global.filter(p => p !== id);
|
|
49
|
+
if (active)
|
|
50
|
+
filtered.push(id);
|
|
51
|
+
return {
|
|
52
|
+
plugin: Object.assign(Object.assign({}, currentState.plugin), { active: Object.assign(Object.assign({}, currentState.plugin.active), { global: filtered }) }),
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
// TODO remove defaultId and useEmbeddedPlugin ?
|
|
57
|
+
createPlugin: (def, defaultId, drawingId, objectId) => {
|
|
58
|
+
const id = defaultId !== void 0 ? defaultId : uuid_1.v4();
|
|
59
|
+
function init(definition) {
|
|
60
|
+
const { description, Root = null, View = null } = definition;
|
|
61
|
+
const initialState = description.initialState || {};
|
|
62
|
+
const localState = typeof initialState === 'function' ? initialState(drawingId, objectId) : initialState;
|
|
63
|
+
set(currentState => {
|
|
64
|
+
const newPlugin = Object.assign(Object.assign({ id }, description), { drawingId,
|
|
65
|
+
objectId, state: localState, Root,
|
|
66
|
+
View, set: (sel) => {
|
|
67
|
+
// set function can be called when drawing doesn't exist anymore, in this case nothing should be done.
|
|
68
|
+
if (get() === undefined)
|
|
69
|
+
return;
|
|
70
|
+
set(state => {
|
|
71
|
+
const newState = typeof sel === 'function' ? sel(state.plugin.refs[id].state) : sel;
|
|
72
|
+
return {
|
|
73
|
+
plugin: Object.assign(Object.assign({}, state.plugin), { refs: Object.assign(Object.assign({}, state.plugin.refs), { [id]: Object.assign(Object.assign({}, state.plugin.refs[id]), { state: Object.assign(Object.assign({}, state.plugin.refs[id].state), newState) }) }) }),
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
} });
|
|
77
|
+
return {
|
|
78
|
+
plugin: Object.assign(Object.assign({}, currentState.plugin), { feature: description.global ? currentState.plugin.feature : [...currentState.plugin.feature, id], global: description.global ? [...currentState.plugin.global, id] : currentState.plugin.global, refs: Object.assign(Object.assign({}, currentState.plugin.refs), { [id]: Object.assign(Object.assign({}, currentState.plugin.refs[id]), newPlugin) }) }),
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// Initialize plugin definition, which may be a promise or an object
|
|
83
|
+
if (isPromisePlugin(def)) {
|
|
84
|
+
// The definition is async, so we create a plugin slot right away and complete it later
|
|
85
|
+
init({
|
|
86
|
+
description: { author: '', name: '', persistent: false, global: false, version: '' },
|
|
87
|
+
Root: null,
|
|
88
|
+
View: null,
|
|
89
|
+
});
|
|
90
|
+
def.then(init).catch();
|
|
91
|
+
}
|
|
92
|
+
else
|
|
93
|
+
init(def);
|
|
94
|
+
// Return unsubscribe
|
|
95
|
+
return (deactivate = true) => {
|
|
96
|
+
// Use 'get' to check if the drawing still exists
|
|
97
|
+
get &&
|
|
98
|
+
get() &&
|
|
99
|
+
set(state => {
|
|
100
|
+
const newPlugins = Object.assign({}, state.plugin.refs);
|
|
101
|
+
delete newPlugins[id];
|
|
102
|
+
return {
|
|
103
|
+
plugin: Object.assign(Object.assign({}, state.plugin), { active: Object.assign(Object.assign({}, state.plugin.active), { feature: deactivate ? null : state.plugin.active.feature }), feature: state.plugin.feature.filter(pluginId => pluginId !== id), global: state.plugin.global.filter(pluginId => pluginId !== id), refs: newPlugins }),
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
exports.pluginApi = pluginApi;
|
|
110
|
+
function isPromisePlugin(def) {
|
|
111
|
+
return def.then !== undefined;
|
|
112
|
+
}
|
|
113
|
+
exports.isPromisePlugin = isPromisePlugin;
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createGraphicItem = exports.selectionApi = exports.selectionData = exports.BuerliScope = void 0;
|
|
4
|
+
const selection_1 = require("../subscribtion/selection");
|
|
5
|
+
////////////////////////////////////////////////////
|
|
6
|
+
// CONSTANTS
|
|
7
|
+
////////////////////////////////////////////////////
|
|
8
|
+
exports.BuerliScope = 'ClassCAD';
|
|
9
|
+
const selectionData = () => ({
|
|
10
|
+
refs: {},
|
|
11
|
+
active: null,
|
|
12
|
+
});
|
|
13
|
+
exports.selectionData = selectionData;
|
|
14
|
+
const selectionApi = (set, get) => ({
|
|
15
|
+
unselectAll() {
|
|
16
|
+
const drawingId = get().id;
|
|
17
|
+
const activeSelector = get().selection.active;
|
|
18
|
+
if (activeSelector) {
|
|
19
|
+
const unselItems = get().selection.refs[activeSelector].items;
|
|
20
|
+
selection_1.unsubscribeItems(drawingId, activeSelector, unselItems);
|
|
21
|
+
set(state => {
|
|
22
|
+
const selector = state.selection.refs[activeSelector];
|
|
23
|
+
return {
|
|
24
|
+
selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [activeSelector]: Object.assign(Object.assign({}, selector), { items: [] }) }) }),
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
unselect(...unselItems) {
|
|
30
|
+
const { selection, id: drawingId } = get();
|
|
31
|
+
const activeSelectorId = selection.active;
|
|
32
|
+
if (activeSelectorId) {
|
|
33
|
+
// Remove unselItems from selector's items
|
|
34
|
+
const selector = selection.refs[activeSelectorId];
|
|
35
|
+
const newItems = selector.items.filter(item => unselItems.find(uItem => uItem.id === item.id) === undefined);
|
|
36
|
+
selection_1.unsubscribeItems(drawingId, activeSelectorId, unselItems);
|
|
37
|
+
if (selector.customUnSelect) {
|
|
38
|
+
// Find recently unselected items
|
|
39
|
+
const diff = selector.items.filter(item1 => {
|
|
40
|
+
return newItems.find(item2 => item2.id === item1.id) === undefined;
|
|
41
|
+
});
|
|
42
|
+
selector.customUnSelect(activeSelectorId, newItems, diff);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
set(state => {
|
|
46
|
+
return {
|
|
47
|
+
selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [activeSelectorId]: Object.assign(Object.assign({}, state.selection.refs[activeSelectorId]), { items: newItems }) }) }),
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
this.setHovered(null, activeSelectorId);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
select(...newItems) {
|
|
55
|
+
const { selection, api, id: drawingId } = get();
|
|
56
|
+
const activeSelectorId = selection.active;
|
|
57
|
+
const { isItemSelected } = api.selection;
|
|
58
|
+
if (activeSelectorId) {
|
|
59
|
+
const selector = selection.refs[activeSelectorId];
|
|
60
|
+
const curItems = selector.items;
|
|
61
|
+
// Remove duplicates
|
|
62
|
+
let filteredItems = newItems.filter((item1, idx) => newItems.findIndex(item2 => item2.id === item1.id) === idx);
|
|
63
|
+
// Remove already selected items and duplicates
|
|
64
|
+
filteredItems = filteredItems.filter(item => !isItemSelected(item, activeSelectorId));
|
|
65
|
+
let unsubItems = [];
|
|
66
|
+
let result = [...curItems, ...filteredItems];
|
|
67
|
+
if (selector.maxLen > 0) {
|
|
68
|
+
if (filteredItems.length === selector.maxLen) {
|
|
69
|
+
result = [...filteredItems];
|
|
70
|
+
unsubItems = [...curItems];
|
|
71
|
+
}
|
|
72
|
+
else if (filteredItems.length > selector.maxLen) {
|
|
73
|
+
const extraItems = filteredItems.length - selector.maxLen;
|
|
74
|
+
// If filteredItems has bigger length then selector.maxLen, remove last few items from filteredItems.
|
|
75
|
+
result = filteredItems.slice(0, -extraItems);
|
|
76
|
+
unsubItems = [...curItems];
|
|
77
|
+
}
|
|
78
|
+
else if (filteredItems.length + curItems.length >= selector.maxLen) {
|
|
79
|
+
const extraItems = filteredItems.length + curItems.length - selector.maxLen;
|
|
80
|
+
const allItems = [...curItems, ...filteredItems];
|
|
81
|
+
// If filteredItems.len + curItems.len > selector.maxLen, remove first few items from union of curItems and filteredItems.
|
|
82
|
+
result = allItems.slice(extraItems);
|
|
83
|
+
unsubItems = allItems.slice(0, extraItems);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (selector.customSelect !== undefined) {
|
|
87
|
+
// Find items which weren't selected before.
|
|
88
|
+
const diff = result.filter(item1 => {
|
|
89
|
+
return selector.items.find(item2 => item2.id === item1.id) === undefined;
|
|
90
|
+
});
|
|
91
|
+
selector.customSelect(activeSelectorId, result, diff);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// subscribe items which will be selected
|
|
95
|
+
selection_1.subscribeItems(drawingId, activeSelectorId, result);
|
|
96
|
+
// unsubscribe items which will be unselected
|
|
97
|
+
selection_1.unsubscribeItems(drawingId, activeSelectorId, unsubItems);
|
|
98
|
+
set(state => {
|
|
99
|
+
return {
|
|
100
|
+
selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [activeSelectorId]: Object.assign(Object.assign({}, selector), { items: result }) }) }),
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
this.setHovered(null, activeSelectorId);
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
setHovered(item, selectorId) {
|
|
108
|
+
const { selection } = get();
|
|
109
|
+
if (selection.active === null && selectorId === undefined)
|
|
110
|
+
return;
|
|
111
|
+
const selId = selection.active || selectorId;
|
|
112
|
+
set(state => ({
|
|
113
|
+
selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [selId]: Object.assign(Object.assign({}, state.selection.refs[selId]), { hoveredItem: item }) }) }),
|
|
114
|
+
}));
|
|
115
|
+
},
|
|
116
|
+
activateSelector(selectorId) {
|
|
117
|
+
set(state => {
|
|
118
|
+
const refs = state.selection.refs;
|
|
119
|
+
const curSelectorId = state.selection.active;
|
|
120
|
+
if (curSelectorId) {
|
|
121
|
+
// Reset hoveredItem
|
|
122
|
+
refs[curSelectorId] = Object.assign(Object.assign({}, refs[curSelectorId]), { hoveredItem: null });
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
selection: Object.assign(Object.assign({}, state.selection), { active: state.selection.active === selectorId ? null : selectorId, refs: Object.assign({}, refs) }),
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
createSelector(selectorId, filter, activate = false, initialItems = [], maxLen = -1, customSelect, customUnSelect) {
|
|
130
|
+
if (maxLen > 0 && initialItems.length > maxLen)
|
|
131
|
+
console.error('Number initialItems should be less or equal to selector.maxLen');
|
|
132
|
+
set(state => ({
|
|
133
|
+
selection: Object.assign(Object.assign({}, state.selection), { active: activate ? selectorId : state.selection.active, refs: Object.assign(Object.assign({}, state.selection.refs), { [selectorId]: {
|
|
134
|
+
items: maxLen > 0 && initialItems.length > maxLen ? [] : initialItems,
|
|
135
|
+
hoveredItem: null,
|
|
136
|
+
isSelectable: filter,
|
|
137
|
+
maxLen,
|
|
138
|
+
customSelect,
|
|
139
|
+
customUnSelect,
|
|
140
|
+
} }) }),
|
|
141
|
+
}));
|
|
142
|
+
return () => {
|
|
143
|
+
if (get && get()) {
|
|
144
|
+
const drawingId = get().id;
|
|
145
|
+
selection_1.unsubscribeItems(drawingId, selectorId);
|
|
146
|
+
set(state => {
|
|
147
|
+
const refs = state.selection.refs;
|
|
148
|
+
delete refs[selectorId];
|
|
149
|
+
return {
|
|
150
|
+
selection: Object.assign(Object.assign({}, state.selection), { active: state.selection.active === selectorId ? null : state.selection.active, refs }),
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
},
|
|
156
|
+
areItemsSelected: (items, selectorId) => {
|
|
157
|
+
const { selection } = get();
|
|
158
|
+
if (selection.active === null && selectorId === undefined)
|
|
159
|
+
return false;
|
|
160
|
+
const selId = selection.active || selectorId;
|
|
161
|
+
const selector = selection.refs[selId];
|
|
162
|
+
let res = true;
|
|
163
|
+
items.forEach(item => {
|
|
164
|
+
const itemSelected = Boolean(selector.items.find(i => areItemsEqual(i, item)));
|
|
165
|
+
if (!itemSelected) {
|
|
166
|
+
res = false;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
return res;
|
|
170
|
+
},
|
|
171
|
+
isItemSelected: (item, selectorId) => {
|
|
172
|
+
const { selection } = get();
|
|
173
|
+
if (selection.active === null && selectorId === undefined)
|
|
174
|
+
return false;
|
|
175
|
+
const selId = selection.active || selectorId;
|
|
176
|
+
const selector = selection.refs[selId];
|
|
177
|
+
return Boolean(selector.items.find(i => areItemsEqual(i, item)));
|
|
178
|
+
},
|
|
179
|
+
setItems(id, items) {
|
|
180
|
+
var _a;
|
|
181
|
+
const { selection, id: drawingId } = get();
|
|
182
|
+
const curItems = ((_a = selection.refs[id]) === null || _a === void 0 ? void 0 : _a.items) || [];
|
|
183
|
+
selection_1.unsubscribeItems(drawingId, id, curItems);
|
|
184
|
+
selection_1.subscribeItems(drawingId, id, items);
|
|
185
|
+
set(state => {
|
|
186
|
+
const selector = state.selection.refs[id];
|
|
187
|
+
return {
|
|
188
|
+
selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [id]: Object.assign(Object.assign({}, selector), { items }) }) }),
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
},
|
|
192
|
+
getGraphicItem: (productId, containerId, graphicId) => {
|
|
193
|
+
const { cache } = get().geometry;
|
|
194
|
+
const container = cache[containerId];
|
|
195
|
+
if (container) {
|
|
196
|
+
if (graphicId === undefined) {
|
|
197
|
+
const ids = Object.getOwnPropertyNames(container.map);
|
|
198
|
+
graphicId = ids.length > 0 ? Number(ids[0]) : undefined;
|
|
199
|
+
}
|
|
200
|
+
if (graphicId !== undefined) {
|
|
201
|
+
const geomElem = container.map[graphicId];
|
|
202
|
+
if (geomElem) {
|
|
203
|
+
return exports.createGraphicItem(productId, geomElem);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
exports.selectionApi = selectionApi;
|
|
211
|
+
////////////////////////////////////////////////////
|
|
212
|
+
//#region GLOBAL FUNCTIONS
|
|
213
|
+
const areItemsEqual = (a, b) => a.id === b.id && a.scope === b.scope;
|
|
214
|
+
const createGraphicIdent = (productId, graphicId, type) => {
|
|
215
|
+
return {
|
|
216
|
+
id: `${productId}|${graphicId}|${type}`,
|
|
217
|
+
scope: exports.BuerliScope,
|
|
218
|
+
label: (type[0] + type[1]).toUpperCase(),
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
const createGraphicItem = (productId, el) => {
|
|
222
|
+
return Object.assign(Object.assign({}, createGraphicIdent(productId, el.graphicId, el.type)), { data: Object.assign(Object.assign({}, el), { productId }) });
|
|
223
|
+
};
|
|
224
|
+
exports.createGraphicItem = createGraphicItem;
|
|
225
|
+
//#endregion GLOBAL FUNCTIONS
|
|
226
|
+
////////////////////////////////////////////////////
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.structureApi = exports.structureData = void 0;
|
|
26
|
+
const jsonpatch_1 = __importDefault(require("jsonpatch"));
|
|
27
|
+
const THREE = __importStar(require("three"));
|
|
28
|
+
const types_1 = require("../../types");
|
|
29
|
+
const Math_1 = require("../../utils/Math");
|
|
30
|
+
////////////////////////////////////////////////////
|
|
31
|
+
// DATA
|
|
32
|
+
////////////////////////////////////////////////////
|
|
33
|
+
const structureData = () => {
|
|
34
|
+
return Object.assign(Object.assign({}, types_1.DEFAULT_STRUCTURE_TREE()), { visibleContainers: [], products: [] });
|
|
35
|
+
};
|
|
36
|
+
exports.structureData = structureData;
|
|
37
|
+
////////////////////////////////////////////////////
|
|
38
|
+
// API
|
|
39
|
+
////////////////////////////////////////////////////
|
|
40
|
+
const structureApi = (set, get) => ({
|
|
41
|
+
get: () => {
|
|
42
|
+
return get().structure;
|
|
43
|
+
},
|
|
44
|
+
set: (structure) => {
|
|
45
|
+
const { api } = get();
|
|
46
|
+
// TODO: clear object selection if needed
|
|
47
|
+
// 1. set the state
|
|
48
|
+
set({
|
|
49
|
+
structure: Object.assign(Object.assign({}, get().structure), structure),
|
|
50
|
+
});
|
|
51
|
+
// 2. collect and cleanup data
|
|
52
|
+
api.graphic.cleanupGraphicRecords();
|
|
53
|
+
// console.log('cleanup')
|
|
54
|
+
api.structure.postProcessStructureUpdate();
|
|
55
|
+
},
|
|
56
|
+
applyPatches: (patches) => {
|
|
57
|
+
const before = get().structure.products.concat(get().structure.visibleContainers);
|
|
58
|
+
// Timing.dump('load', 'received tree patches')
|
|
59
|
+
set(state => {
|
|
60
|
+
let structure = state.structure;
|
|
61
|
+
try {
|
|
62
|
+
structure = jsonpatch_1.default.apply_patch(state.structure, patches);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
console.error(e);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
structure: Object.assign(Object.assign({}, get().structure), structure),
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
const { api } = get();
|
|
72
|
+
api.structure.postProcessStructureUpdate();
|
|
73
|
+
// Update the bounds, but only if products or visible containers changed.
|
|
74
|
+
const after = get().structure.products.concat(get().structure.visibleContainers);
|
|
75
|
+
if (before.sort().join() !== after.sort().join()) {
|
|
76
|
+
api.geometry.updateBounds();
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
filterTree: (tree, filter) => {
|
|
80
|
+
const objs = [];
|
|
81
|
+
Object.getOwnPropertyNames(tree).forEach(name => {
|
|
82
|
+
const obj = tree[name];
|
|
83
|
+
if (filter(obj)) {
|
|
84
|
+
objs.push(obj);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
return objs;
|
|
88
|
+
},
|
|
89
|
+
collectUsedSolidIds: () => {
|
|
90
|
+
const { api, structure } = get();
|
|
91
|
+
const solidObjs = api.structure.filterTree(structure.tree, obj => typeof obj.geometryIdList !== 'undefined');
|
|
92
|
+
const solidIds = [];
|
|
93
|
+
solidObjs.forEach(solidObj => solidIds.push(...(solidObj.geometryIdList || [])));
|
|
94
|
+
return solidIds;
|
|
95
|
+
},
|
|
96
|
+
collectProducts: (root) => {
|
|
97
|
+
const { structure } = get();
|
|
98
|
+
const products = [];
|
|
99
|
+
const recursive = (id) => {
|
|
100
|
+
const obj = structure.tree[id];
|
|
101
|
+
if (obj) {
|
|
102
|
+
if ((obj.solids && obj.solids.length > 0) || obj.link) {
|
|
103
|
+
products.push(obj);
|
|
104
|
+
}
|
|
105
|
+
if (obj.children) {
|
|
106
|
+
for (const child of obj.children) {
|
|
107
|
+
recursive(child);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
recursive(root);
|
|
113
|
+
return products;
|
|
114
|
+
},
|
|
115
|
+
getProductSolidIds: (productId) => {
|
|
116
|
+
const { structure } = get();
|
|
117
|
+
let solids;
|
|
118
|
+
const product = structure.tree[productId];
|
|
119
|
+
if (product.link !== undefined) {
|
|
120
|
+
solids = structure.tree[product.link].solids || [];
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
solids = product.solids || [];
|
|
124
|
+
}
|
|
125
|
+
return [...solids];
|
|
126
|
+
},
|
|
127
|
+
postProcessStructureUpdate: () => {
|
|
128
|
+
const { api, structure } = get();
|
|
129
|
+
//////////
|
|
130
|
+
// 1. Collect the products
|
|
131
|
+
//////////
|
|
132
|
+
const searchRoot = structure.root; // || structure.currentNode || structure.currentProduct
|
|
133
|
+
const productIds = api.structure.collectProducts(searchRoot).map(p => p.id);
|
|
134
|
+
//////////
|
|
135
|
+
// 2. Collect the solid ids
|
|
136
|
+
//////////
|
|
137
|
+
let solidIds = [];
|
|
138
|
+
productIds.forEach(prodId => solidIds.push(...(api.structure.getProductSolidIds(prodId) || [])));
|
|
139
|
+
// remove duplicates
|
|
140
|
+
solidIds = solidIds.filter((item, index) => solidIds.indexOf(item) === index);
|
|
141
|
+
//////////
|
|
142
|
+
// 3. Add the result to the state
|
|
143
|
+
//////////
|
|
144
|
+
set(state => ({
|
|
145
|
+
structure: Object.assign(Object.assign({}, state.structure), { visibleContainers: solidIds, products: productIds }),
|
|
146
|
+
}));
|
|
147
|
+
},
|
|
148
|
+
/**
|
|
149
|
+
* Calculates the global transformation matrix for the given _objectId_.
|
|
150
|
+
*
|
|
151
|
+
* @param objectId The object to calculate the global transformation for.
|
|
152
|
+
* @param matrix The initial matrix (mainly used for recursion). It is an out parameter and in the end, it will contain the same matrix as the return value of this function.
|
|
153
|
+
* @returns The global transformation matrix for the given _objectId_.
|
|
154
|
+
*/
|
|
155
|
+
calculateGlobalTransformation: (objectId, matrix = new THREE.Matrix4().identity()) => {
|
|
156
|
+
const { structure, api } = get();
|
|
157
|
+
const { tree, root } = structure;
|
|
158
|
+
const obj = tree[objectId];
|
|
159
|
+
if (obj && obj.coordinateSystem) {
|
|
160
|
+
const objMatrix = Math_1.MathUtils.convertToMatrix4(obj.coordinateSystem);
|
|
161
|
+
matrix = matrix.clone().premultiply(objMatrix);
|
|
162
|
+
}
|
|
163
|
+
if (objectId !== root && obj.parent) {
|
|
164
|
+
matrix = api.structure.calculateGlobalTransformation(obj.parent, matrix);
|
|
165
|
+
}
|
|
166
|
+
return matrix;
|
|
167
|
+
},
|
|
168
|
+
calculateProductBounds: (productId, base) => {
|
|
169
|
+
const { graphic, api } = get();
|
|
170
|
+
const posInf = Number.POSITIVE_INFINITY;
|
|
171
|
+
const negInf = Number.NEGATIVE_INFINITY;
|
|
172
|
+
const baseMin = base ? base.min.clone() : new THREE.Vector3(posInf, posInf, posInf);
|
|
173
|
+
const baseMax = base ? base.max.clone() : new THREE.Vector3(negInf, negInf, negInf);
|
|
174
|
+
let box = new THREE.Box3(baseMin, baseMax);
|
|
175
|
+
const productIds = api.structure.collectProducts(productId).map(p => p.id);
|
|
176
|
+
for (const pId of productIds) {
|
|
177
|
+
const matrix = api.structure.calculateGlobalTransformation(pId);
|
|
178
|
+
const contIds = api.structure.getProductSolidIds(pId);
|
|
179
|
+
for (const contId of contIds) {
|
|
180
|
+
const cont = graphic.containers[contId];
|
|
181
|
+
if (cont) {
|
|
182
|
+
const min = new THREE.Vector3().fromArray(cont.properties.min);
|
|
183
|
+
const max = new THREE.Vector3().fromArray(cont.properties.max);
|
|
184
|
+
const b = new THREE.Box3(min.clone(), max.clone());
|
|
185
|
+
b.applyMatrix4(matrix);
|
|
186
|
+
box = box.union(b);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const sphere = new THREE.Sphere();
|
|
191
|
+
box.getBoundingSphere(sphere);
|
|
192
|
+
return { center: sphere.center, radius: sphere.radius, max: box.max, min: box.min };
|
|
193
|
+
},
|
|
194
|
+
/**
|
|
195
|
+
* This is a workaround to get the corresponding drawing id via API.
|
|
196
|
+
*
|
|
197
|
+
* > !!! Should not be used in user code !!!
|
|
198
|
+
*
|
|
199
|
+
* @returns The drawing id.
|
|
200
|
+
*/
|
|
201
|
+
getDrawingId: () => get().id,
|
|
202
|
+
});
|
|
203
|
+
exports.structureApi = structureApi;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.api = void 0;
|
|
7
|
+
const vanilla_1 = __importDefault(require("zustand/vanilla"));
|
|
8
|
+
const buerli_1 = require("./states/buerli");
|
|
9
|
+
const store = (set, get, buerliApi) => buerli_1.createState(set, get, buerliApi);
|
|
10
|
+
const wnd = typeof window !== 'undefined' ? window : null;
|
|
11
|
+
const middleware = wnd ? wnd.BUERLI_MIDDLEWARE || (wnd.BUERLI_MIDDLEWARE = []) : [];
|
|
12
|
+
const buerliStore = middleware.reduceRight((acc, cur) => cur(acc), store);
|
|
13
|
+
const api = vanilla_1.default(buerliStore);
|
|
14
|
+
exports.api = api;
|