Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions api/xr.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { translate } from "../main/translation.js";
import * as fflate from "fflate";

let flock;

Expand Down Expand Up @@ -176,6 +177,27 @@ export const flockXR = {
);
} else if (format === "OBJ") {
flock.EXPORT.OBJExport.OBJ(mesh);
} else if (format === "3MF") {
try {
if (!globalThis.fflate) {
globalThis.fflate = fflate;
}
const serializer = new flock.EXPORT.ThreeMfSerializer();
const data = await flock.EXPORT.ThreeMf.SerializeToMemoryAsync(
serializer,
...meshList,
);
if (data?.length) {
flock.download(`${mesh.name}.3mf`, data, "model/3mf");
} else {
console.error(
"3MF export did not produce output data for mesh:",
mesh.name,
);
}
} catch (error) {
console.error("3MF export failed:", error);
}
} else if (format === "GLB") {
const ghostMat = new flock.BABYLON.PBRMaterial(
"_tmpExportWrapperGhost",
Expand Down
1 change: 1 addition & 0 deletions blocks/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ export function defineConnectBlocks() {
["STL", "STL"],
["OBJ", "OBJ"],
["GLB", "GLB"],
["3MF", "3MF"],
],
},
],
Expand Down
45 changes: 45 additions & 0 deletions tests/xr-export.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,50 @@ export function runXRExportTests(flock) {
.filter((mesh) => shouldExportNode(mesh));
expect(exportedDescendants.length).to.be.greaterThan(0);
});

it("exports 3MF using Babylon serializer and downloads file", async function () {
const treeId = flock.createObject({
modelName: "tree.glb",
modelId: `tree.glb__3mf_export_${Date.now()}`,
position: { x: 1, y: 0, z: 0 },
});
const treeMesh = await waitForModel(flock, treeId);

const originalSerializer = flock.EXPORT.ThreeMfSerializer;
const originalSerializeToMemoryAsync = flock.EXPORT.ThreeMf.SerializeToMemoryAsync;
const originalDownload = flock.download;

let serializerInstance;
let serializeMeshes;
let downloadedFile = null;

flock.EXPORT.ThreeMfSerializer = function MockThreeMfSerializer() {
serializerInstance = this;
};
flock.EXPORT.ThreeMf.SerializeToMemoryAsync = async (serializer, ...meshes) => {
serializeMeshes = meshes;
Comment on lines +121 to +132
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Run Prettier on changed files to unblock CI.

The PR currently fails the Prettier check; please run formatting before merge.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/xr-export.test.js` around lines 121 - 132, The changed test file
tests/xr-export.test.js is failing Prettier; run the project's formatter on the
modified files (e.g., npx prettier --write or npm run format) to reformat the
test and any related files so the CI Prettier check passes, then re-stage the
formatted changes — pay attention to formatting around the mocked symbols like
flock.EXPORT.ThreeMf.SerializeToMemoryAsync, flock.EXPORT.ThreeMfSerializer,
flock.download, and the variables serializerInstance/serializeMeshes so no
lint/format differences remain.

expect(serializer).to.equal(serializerInstance);
return new Uint8Array([1, 2, 3]);
};
flock.download = (filename, data, mimeType) => {
downloadedFile = { filename, data, mimeType };
};

try {
await flock.exportMesh(treeId, "3MF");
} finally {
flock.EXPORT.ThreeMfSerializer = originalSerializer;
flock.EXPORT.ThreeMf.SerializeToMemoryAsync = originalSerializeToMemoryAsync;
flock.download = originalDownload;
}

expect(serializeMeshes).to.be.an("array");
expect(serializeMeshes.length).to.be.greaterThan(0);
expect(serializeMeshes[0]).to.equal(treeMesh);
expect(downloadedFile).to.not.equal(null);
expect(downloadedFile.filename).to.equal(`${treeMesh.name}.3mf`);
expect(downloadedFile.mimeType).to.equal("model/3mf");
expect(downloadedFile.data).to.be.instanceof(Uint8Array);
});
});
}
Loading