支持预览界面接收场景基点

This commit is contained in:
zhangshun
2026-06-01 15:55:39 +08:00
parent 2368d6e6c1
commit 7ab0c2bba4

View File

@@ -96,10 +96,24 @@ type ParentImportScenePayload = {
rawOperationTree: string;
};
type ParentBasePointMessage = {
type?: string;
message?: string;
payload?: {
modelId?: string;
modelName?: string;
basePoint?: PreviewBasePoint;
};
};
export type ModelPreviewOptions = {
onImportScene?: (payload: PreviewImportScenePayload) => Promise<void> | void;
};
const BASE_POINT_SUBSCRIBE_MESSAGE = "DMT_MODEL_LIBRARY_BASE_POINT_SUBSCRIBE";
const BASE_POINT_UNSUBSCRIBE_MESSAGE = "DMT_MODEL_LIBRARY_BASE_POINT_UNSUBSCRIBE";
const BASE_POINT_UPDATE_MESSAGE = "DMT_MODEL_LIBRARY_BASE_POINT_UPDATE";
const BASE_POINT_ERROR_MESSAGE = "DMT_MODEL_LIBRARY_BASE_POINT_ERROR";
const zeroBasePoint: PreviewResolvedBasePoint = {
x: 0,
y: 0,
@@ -117,6 +131,8 @@ let runtime: PreviewRuntime | null = null;
let activePreviewContext: PreviewLoadContext | null = null;
let previewEnvironmentTexturePromise: Promise<Texture> | null = null;
let previewPlayback: PreviewPlaybackState = createEmptyPlaybackState();
let basePointBridgeBound = false;
let basePointSubscribed = false;
export function openModelPreview(
model: ModelItem,
@@ -202,6 +218,7 @@ export function openModelPreview(
.on("open:after", () => {popup
console.log(popup)
bindProcessPlaceholder(operations);
bindBasePointSelection();
bindImportScene(model, operations, options.onImportScene);
if (canWrite) bindThumbnailCapture(model.id, onThumbnailSaved);
requestAnimationFrame(() => {
@@ -210,7 +227,10 @@ export function openModelPreview(
});
});
})
.on("close:after", () => disposePreview());
.on("close:after", () => {
unsubscribeBasePointSelection();
disposePreview();
});
}
export function setPreviewBasePoint(basePoint: PreviewBasePoint, enabled = true) {
@@ -301,6 +321,68 @@ function resolveParentOrigin() {
return "*";
}
function isAllowedParentOrigin(origin: string) {
const expectedOrigin = resolveParentOrigin();
return expectedOrigin === "*" || origin === expectedOrigin || isLocalDmtParentOrigin(origin);
}
function isLocalDmtParentOrigin(origin: string) {
try {
const url = new URL(origin);
const isLocalHost = url.hostname === "localhost" || url.hostname === "127.0.0.1";
return isLocalHost && url.port === "3000";
} catch {
return false;
}
}
function bindBasePointSelection() {
bindBasePointBridge();
const checkbox = document.querySelector<HTMLInputElement>("#previewUseBasePoint");
checkbox?.addEventListener("change", () => {
if (checkbox.checked) {
subscribeBasePointSelection();
} else {
unsubscribeBasePointSelection();
}
});
if (checkbox?.checked) subscribeBasePointSelection();
}
function bindBasePointBridge() {
if (basePointBridgeBound) return;
basePointBridgeBound = true;
window.addEventListener("message", (event) => {
const data = event.data as ParentBasePointMessage;
if (data?.type !== BASE_POINT_UPDATE_MESSAGE && data?.type !== BASE_POINT_ERROR_MESSAGE) return;
if (!isAllowedParentOrigin(event.origin)) return;
if (data.type === BASE_POINT_ERROR_MESSAGE) {
notify(data.message || "请先在主场景中选择模型或坐标");
return;
}
if (data.payload?.basePoint) {
setPreviewBasePoint(data.payload.basePoint, true);
}
});
}
function subscribeBasePointSelection() {
if (!window.parent || window.parent === window) return;
basePointSubscribed = true;
window.parent.postMessage({
type: BASE_POINT_SUBSCRIBE_MESSAGE
}, resolveParentPostMessageOrigin());
}
function unsubscribeBasePointSelection() {
if (!basePointSubscribed) return;
basePointSubscribed = false;
if (!window.parent || window.parent === window) return;
window.parent.postMessage({
type: BASE_POINT_UNSUBSCRIBE_MESSAGE
}, resolveParentPostMessageOrigin());
}
function parseModelOperations(value: string): PreviewOperation[] {
try {
const dbValue = JSON.parse(value || "{}") as Partial<OperationTreeDB>;