支持预览界面接收场景基点
This commit is contained in:
@@ -96,10 +96,24 @@ type ParentImportScenePayload = {
|
|||||||
rawOperationTree: string;
|
rawOperationTree: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ParentBasePointMessage = {
|
||||||
|
type?: string;
|
||||||
|
message?: string;
|
||||||
|
payload?: {
|
||||||
|
modelId?: string;
|
||||||
|
modelName?: string;
|
||||||
|
basePoint?: PreviewBasePoint;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export type ModelPreviewOptions = {
|
export type ModelPreviewOptions = {
|
||||||
onImportScene?: (payload: PreviewImportScenePayload) => Promise<void> | void;
|
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 = {
|
const zeroBasePoint: PreviewResolvedBasePoint = {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
@@ -117,6 +131,8 @@ let runtime: PreviewRuntime | null = null;
|
|||||||
let activePreviewContext: PreviewLoadContext | null = null;
|
let activePreviewContext: PreviewLoadContext | null = null;
|
||||||
let previewEnvironmentTexturePromise: Promise<Texture> | null = null;
|
let previewEnvironmentTexturePromise: Promise<Texture> | null = null;
|
||||||
let previewPlayback: PreviewPlaybackState = createEmptyPlaybackState();
|
let previewPlayback: PreviewPlaybackState = createEmptyPlaybackState();
|
||||||
|
let basePointBridgeBound = false;
|
||||||
|
let basePointSubscribed = false;
|
||||||
|
|
||||||
export function openModelPreview(
|
export function openModelPreview(
|
||||||
model: ModelItem,
|
model: ModelItem,
|
||||||
@@ -202,6 +218,7 @@ export function openModelPreview(
|
|||||||
.on("open:after", () => {popup
|
.on("open:after", () => {popup
|
||||||
console.log(popup)
|
console.log(popup)
|
||||||
bindProcessPlaceholder(operations);
|
bindProcessPlaceholder(operations);
|
||||||
|
bindBasePointSelection();
|
||||||
bindImportScene(model, operations, options.onImportScene);
|
bindImportScene(model, operations, options.onImportScene);
|
||||||
if (canWrite) bindThumbnailCapture(model.id, onThumbnailSaved);
|
if (canWrite) bindThumbnailCapture(model.id, onThumbnailSaved);
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
@@ -210,7 +227,10 @@ export function openModelPreview(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.on("close:after", () => disposePreview());
|
.on("close:after", () => {
|
||||||
|
unsubscribeBasePointSelection();
|
||||||
|
disposePreview();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setPreviewBasePoint(basePoint: PreviewBasePoint, enabled = true) {
|
export function setPreviewBasePoint(basePoint: PreviewBasePoint, enabled = true) {
|
||||||
@@ -301,6 +321,68 @@ function resolveParentOrigin() {
|
|||||||
return "*";
|
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[] {
|
function parseModelOperations(value: string): PreviewOperation[] {
|
||||||
try {
|
try {
|
||||||
const dbValue = JSON.parse(value || "{}") as Partial<OperationTreeDB>;
|
const dbValue = JSON.parse(value || "{}") as Partial<OperationTreeDB>;
|
||||||
|
|||||||
Reference in New Issue
Block a user