Fix BIM share transform persistence
This commit is contained in:
parent
abf899fefd
commit
ef7179dc6c
|
|
@ -2301,6 +2301,7 @@ const getShareableModelPayload = () => {
|
|||
src,
|
||||
type: normalizeType(null, src) || entry.meta?.artifactType || entry.type,
|
||||
versionId: entry.meta?.versionId || entry.meta?.conversion?.versionId || null,
|
||||
viewerSettings: buildModelViewerSettings(),
|
||||
versions: Array.isArray(entry.meta?.versions) ? entry.meta.versions : [],
|
||||
};
|
||||
};
|
||||
|
|
@ -4077,6 +4078,37 @@ const applyStoredTransformsToModel = (modelId) => {
|
|||
return applied;
|
||||
};
|
||||
|
||||
const getViewerSettingsTransformMap = (settings) => {
|
||||
const transforms = settings?.viewerState?.transforms;
|
||||
return transforms && typeof transforms === "object" && !Array.isArray(transforms)
|
||||
? transforms
|
||||
: null;
|
||||
};
|
||||
|
||||
const ensureLoadedModelTransformAlias = (modelId, settings = null) => {
|
||||
if (!modelId) return false;
|
||||
const currentTransforms = transformStore[modelId];
|
||||
if (currentTransforms && Object.keys(currentTransforms).length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const transforms = getViewerSettingsTransformMap(settings) || transformStore;
|
||||
const preferredIds = Array.isArray(settings?.viewerState?.models)
|
||||
? settings.viewerState.models.map((item) => item?.id).filter(Boolean)
|
||||
: [];
|
||||
const candidateIds = [...preferredIds, ...Object.keys(transforms || {})]
|
||||
.filter((id, index, items) => id && id !== modelId && items.indexOf(id) === index);
|
||||
|
||||
const sourceId = candidateIds.find((id) => {
|
||||
const value = transformStore[id] || transforms?.[id];
|
||||
return value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length;
|
||||
});
|
||||
if (!sourceId) return false;
|
||||
|
||||
transformStore[modelId] = safeClone(transformStore[sourceId] || transforms[sourceId]);
|
||||
return true;
|
||||
};
|
||||
|
||||
const getModelIdFromNode = (node) => {
|
||||
const title = (node?.title || node?.text || node?.name || "").trim();
|
||||
const firstObject = (node && collectObjectIds(node)[0]) || null;
|
||||
|
|
@ -5532,9 +5564,7 @@ const snapshotVec = (v) => {
|
|||
return null;
|
||||
};
|
||||
|
||||
const buildProjectSnapshot = async (name) => {
|
||||
const models = [];
|
||||
|
||||
const buildActiveTransformsSnapshot = () => {
|
||||
const transformsCopy = safeClone(transformStore);
|
||||
activeModels.forEach(({ model }) => {
|
||||
if (!model || !model.id) return;
|
||||
|
|
@ -5547,6 +5577,18 @@ const buildProjectSnapshot = async (name) => {
|
|||
};
|
||||
}
|
||||
});
|
||||
return transformsCopy;
|
||||
};
|
||||
|
||||
const buildActiveModelStateSnapshot = () => activeModels.map((entry) => ({
|
||||
id: entry.model?.id,
|
||||
visible: entry.model?.visible !== false
|
||||
}));
|
||||
|
||||
const buildProjectSnapshot = async (name) => {
|
||||
const models = [];
|
||||
|
||||
const transformsCopy = buildActiveTransformsSnapshot();
|
||||
|
||||
for (const entry of activeModels) {
|
||||
const model = entry.model;
|
||||
|
|
@ -5637,10 +5679,7 @@ const buildProjectSnapshot = async (name) => {
|
|||
ids: lastSelection.ids || [],
|
||||
modelId: lastSelection.modelId || null,
|
||||
},
|
||||
models: activeModels.map((entry) => ({
|
||||
id: entry.model?.id,
|
||||
visible: entry.model?.visible !== false
|
||||
})),
|
||||
models: buildActiveModelStateSnapshot(),
|
||||
transforms: transformsCopy
|
||||
} : {};
|
||||
|
||||
|
|
@ -5704,6 +5743,8 @@ const buildModelViewerSettings = () => ({
|
|||
lightingMode: activeLightingMode,
|
||||
navigationAxis: activeNavigationAxis,
|
||||
zoomSpeed: activeZoomSpeed,
|
||||
models: buildActiveModelStateSnapshot(),
|
||||
transforms: buildActiveTransformsSnapshot(),
|
||||
lod: (() => {
|
||||
const entry = getPrimaryModelEntry();
|
||||
const selected = getSelectedLodRecord(entry);
|
||||
|
|
@ -5885,7 +5926,10 @@ const applyViewerState = (state) => {
|
|||
if (state.transforms && typeof state.transforms === "object") {
|
||||
Object.keys(transformStore).forEach((k) => delete transformStore[k]);
|
||||
Object.assign(transformStore, safeClone(state.transforms));
|
||||
Object.keys(sceneModels).forEach((mid) => applyStoredTransformsToModel(mid));
|
||||
Object.keys(sceneModels).forEach((mid) => {
|
||||
ensureLoadedModelTransformAlias(mid, { viewerState: state });
|
||||
applyStoredTransformsToModel(mid);
|
||||
});
|
||||
}
|
||||
if (Array.isArray(state.models)) {
|
||||
state.models.forEach((m) => {
|
||||
|
|
@ -6445,6 +6489,7 @@ const initViewer = async () => {
|
|||
}
|
||||
sceneModels[id] = currentModel;
|
||||
modelTypes[id] = inferredType;
|
||||
ensureLoadedModelTransformAlias(id, modelSettings);
|
||||
|
||||
currentModel.on("loaded", () => {
|
||||
reportViewerEvent("model-loaded", {
|
||||
|
|
@ -6455,8 +6500,14 @@ const initViewer = async () => {
|
|||
objectCount: Object.keys(viewer.scene.objects || {}).length,
|
||||
src: srcToLoad,
|
||||
});
|
||||
setTimeout(() => applyStoredTransformsToModel(id), 0);
|
||||
setTimeout(() => applyStoredTransformsToModel(id), 60);
|
||||
setTimeout(() => {
|
||||
ensureLoadedModelTransformAlias(id, modelSettings);
|
||||
applyStoredTransformsToModel(id);
|
||||
}, 0);
|
||||
setTimeout(() => {
|
||||
ensureLoadedModelTransformAlias(id, modelSettings);
|
||||
applyStoredTransformsToModel(id);
|
||||
}, 60);
|
||||
const hasModelCamera = !!modelSettings?.viewerState?.camera;
|
||||
if (!isLoadingSavedProject && !hasModelCamera) {
|
||||
viewer.cameraFlight.flyTo({ aabb: viewer.scene.getAABB({}) });
|
||||
|
|
@ -6520,6 +6571,7 @@ const initViewer = async () => {
|
|||
refreshModelLods({ silent: true }).catch(() => {});
|
||||
|
||||
// если есть сохранённые трансформы для модели — применим
|
||||
ensureLoadedModelTransformAlias(id, modelSettings);
|
||||
applyStoredTransformsToModel(id);
|
||||
return currentModel;
|
||||
} catch (e) {
|
||||
|
|
@ -6600,6 +6652,9 @@ const initViewer = async () => {
|
|||
clearShareStartupPending();
|
||||
|
||||
let settingsSrc = sharedViewer?.settingsSrc || params.get("settingsSrc") || params.get("sourceSrc") || params.get("originalSrc") || src;
|
||||
const sharedViewerSettings = sharedViewer?.viewerSettings && typeof sharedViewer.viewerSettings === "object"
|
||||
? sharedViewer.viewerSettings
|
||||
: null;
|
||||
const applyQueryViewerOverrides = () => {
|
||||
if (params.has("displayMode")) {
|
||||
activeDisplayMode = params.get("displayMode") || "source";
|
||||
|
|
@ -6637,11 +6692,11 @@ const initViewer = async () => {
|
|||
selectedLod: sharedViewer?.selectedLod || null,
|
||||
versions: Array.isArray(sharedViewer?.versions) ? sharedViewer.versions : [],
|
||||
shareToken: startupSharePayload?.share?.token || getShareTokenFromPath(),
|
||||
viewerSettings: null,
|
||||
viewerSettings: sharedViewerSettings,
|
||||
};
|
||||
|
||||
const applyFetchedStartupSettings = (settingsResponse) => {
|
||||
const modelSettings = settingsResponse?.viewerSettings || null;
|
||||
const modelSettings = sharedViewerSettings || settingsResponse?.viewerSettings || null;
|
||||
settingsSrc = settingsResponse?.sourceSrc || settingsSrc;
|
||||
reportViewerEvent("startup-settings-loaded", {
|
||||
settingsSrc,
|
||||
|
|
@ -6683,7 +6738,9 @@ const initViewer = async () => {
|
|||
|
||||
if (params.has("edges")) {
|
||||
startupMeta.viewerSettings = {
|
||||
...(startupMeta.viewerSettings || {}),
|
||||
viewerState: {
|
||||
...(startupMeta.viewerSettings?.viewerState || {}),
|
||||
edges: params.get("edges") !== "false"
|
||||
}
|
||||
};
|
||||
|
|
@ -6694,7 +6751,7 @@ const initViewer = async () => {
|
|||
name,
|
||||
type,
|
||||
settingsSrc,
|
||||
hasViewerSettings: false,
|
||||
hasViewerSettings: !!sharedViewerSettings,
|
||||
});
|
||||
loadModel({
|
||||
type,
|
||||
|
|
|
|||
|
|
@ -1973,6 +1973,9 @@ const handleCreateShare = async (req, res) => {
|
|||
const name = typeof payload?.name === "string" && payload.name.trim()
|
||||
? payload.name.trim().slice(0, 240)
|
||||
: path.basename(src);
|
||||
const viewerSettings = payload?.viewerSettings && typeof payload.viewerSettings === "object" && !Array.isArray(payload.viewerSettings)
|
||||
? payload.viewerSettings
|
||||
: null;
|
||||
const share = {
|
||||
token,
|
||||
access: "public-readonly",
|
||||
|
|
@ -1984,6 +1987,7 @@ const handleCreateShare = async (req, res) => {
|
|||
projectId: identity.projectId,
|
||||
versionId: typeof payload?.versionId === "string" ? payload.versionId : null,
|
||||
selectedLod: stringOrNull(payload?.selectedLod),
|
||||
viewerSettings,
|
||||
createdAt: now,
|
||||
createdBy: session?.user ? {
|
||||
id: session.user.id || null,
|
||||
|
|
@ -2073,6 +2077,7 @@ const handleGetShare = async (req, res, token) => {
|
|||
projectId: share.projectId || null,
|
||||
versionId: share.versionId || versionHistory?.currentVersionId || null,
|
||||
selectedLod: share.selectedLod || null,
|
||||
viewerSettings: share.viewerSettings || null,
|
||||
versions: versionHistory?.versions || []
|
||||
},
|
||||
share: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue