Skip to content
52 changes: 50 additions & 2 deletions api/csg.js
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,9 @@ export const flockCSG = {
};

return new Promise((resolve) => {
console.info(
`[subtractMeshes][path] approach=merge modelId=${modelId} base=${baseMeshName} tools=${meshNames.length}`,
);
flock.whenModelReady(baseMeshName, (baseMesh) => {
if (!baseMesh) return resolve(null);
let actualBase = baseMesh.metadata?.modelName
Expand All @@ -767,6 +770,9 @@ export const flockCSG = {
}

flock.prepareMeshes(modelId, meshNames, blockKey).then((validMeshes) => {
console.info(
`[subtractMeshes][merge] validTools=${validMeshes.length}`,
);
const inferredUvProjection =
options.uvProjection === undefined &&
flock.toolMeshesUseTextures(validMeshes)
Expand All @@ -783,6 +789,9 @@ export const flockCSG = {
// Check if mesh itself has valid geometry (e.g., manifold text meshes)
const meshHasGeometry =
mesh.getTotalVertices && mesh.getTotalVertices() > 0;
console.info(
`[subtractMeshes][merge] toolIndex=${meshIndex} name=${mesh.name} parts=${parts.length} meshHasGeometry=${meshHasGeometry}`,
);

if (parts.length > 0) {
const partClones = parts.map((p, i) =>
Expand Down Expand Up @@ -820,18 +829,30 @@ export const flockCSG = {
// Direct mesh without children (e.g., manifold text mesh)
const clone = cloneForCSG(mesh, `direct_tool_${meshIndex}`);
subtractDuplicates.push(clone);
console.info(
`[subtractMeshes][merge] toolIndex=${meshIndex} using=direct_mesh`,
);
}
});

console.info(
`[subtractMeshes][merge] subtractToolCount=${subtractDuplicates.length}`,
);
subtractDuplicates.forEach((m, idx) => {
try {
const meshCSG = flock.BABYLON.CSG2.FromMesh(m, false);
outerCSG = outerCSG.subtract(meshCSG);
console.info(
`[subtractMeshes][merge] subtractionIndex=${idx} status=ok tool=${m.name}`,
);
} catch (e) {
console.warn(
`[subtractMeshesMerge] Subtraction ${idx} failed:`,
e.message,
);
console.info(
`[subtractMeshes][merge] subtractionIndex=${idx} status=failed tool=${m.name}`,
);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
});

Expand All @@ -844,6 +865,9 @@ export const flockCSG = {
if (!resultMesh || resultMesh.getTotalVertices() === 0) {
throw new Error("CSG produced empty mesh");
}
console.info(
`[subtractMeshes][merge] result=status_ok vertices=${resultMesh.getTotalVertices()}`,
);
} catch (e) {
console.warn(
"[subtractMeshesMerge] CSG subtract failed:",
Expand Down Expand Up @@ -922,6 +946,9 @@ export const flockCSG = {
};

return new Promise((resolve) => {
console.info(
`[subtractMeshes][path] approach=individual modelId=${modelId} base=${baseMeshName} tools=${meshNames.length}`,
);
flock.whenModelReady(baseMeshName, (baseMesh) => {
if (!baseMesh) return resolve(null);
let actualBase = baseMesh;
Expand All @@ -941,6 +968,9 @@ export const flockCSG = {
}

flock.prepareMeshes(modelId, meshNames, blockKey).then((validMeshes) => {
console.info(
`[subtractMeshes][individual] validTools=${validMeshes.length}`,
);
const inferredUvProjection =
options.uvProjection === undefined &&
flock.toolMeshesUseTextures(validMeshes)
Expand All @@ -958,8 +988,11 @@ export const flockCSG = {

let outerCSG = flock.BABYLON.CSG2.FromMesh(baseDuplicate, false);
const allToolParts = [];
validMeshes.forEach((mesh) => {
validMeshes.forEach((mesh, meshIndex) => {
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

Fix ESLint violation: unused meshIndex parameter.

The pipeline is failing because meshIndex is defined but never used. Per the project's ESLint configuration, unused arguments must be prefixed with _.

🔧 Proposed fix
-          validMeshes.forEach((mesh, meshIndex) => {
+          validMeshes.forEach((mesh, _meshIndex) => {

Alternatively, if the index is not needed at all:

-          validMeshes.forEach((mesh, meshIndex) => {
+          validMeshes.forEach((mesh) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
validMeshes.forEach((mesh, meshIndex) => {
validMeshes.forEach((mesh, _meshIndex) => {
🧰 Tools
🪛 GitHub Actions: ESLint

[error] 978-978: ESLint (no-unused-vars): 'meshIndex' is defined but never used. Allowed unused args must match /^_/u

🪛 GitHub Check: eslint

[failure] 978-978:
'meshIndex' is defined but never used. Allowed unused args must match /^_/u

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

In `@api/csg.js` at line 978, The forEach callback currently declares an unused
parameter named meshIndex which violates ESLint; update the callback signature
used on validMeshes.forEach to either remove the unused second parameter or
rename it to start with an underscore (e.g., _meshIndex) so it satisfies the
project's lint rule; locate the validMeshes.forEach(...) callback and change the
parameter accordingly in that anonymous function.

const parts = collectMaterialMeshesDeep(mesh);
console.info(
`[subtractMeshes][individual] toolIndex=${meshIndex} name=${mesh.name} parts=${parts.length}`,
);
parts.forEach((p) => {
const dup = p.clone("partDup", null, true);
dup.computeWorldMatrix(true);
Expand All @@ -968,12 +1001,21 @@ export const flockCSG = {
});
});

allToolParts.forEach((part) => {
console.info(
`[subtractMeshes][individual] subtractPartCount=${allToolParts.length}`,
);
allToolParts.forEach((part, index) => {
try {
const partCSG = flock.BABYLON.CSG2.FromMesh(part, false);
outerCSG = outerCSG.subtract(partCSG);
console.info(
`[subtractMeshes][individual] subtractionIndex=${index} status=ok tool=${part.name}`,
);
} catch (e) {
console.warn(e);
console.info(
`[subtractMeshes][individual] subtractionIndex=${index} status=failed tool=${part.name}`,
);
}
});

Expand All @@ -986,6 +1028,9 @@ export const flockCSG = {
if (!resultMesh || resultMesh.getTotalVertices() === 0) {
throw new Error("CSG produced empty mesh");
}
console.info(
`[subtractMeshes][individual] result=status_ok vertices=${resultMesh.getTotalVertices()}`,
);
} catch (e) {
console.warn(
"[subtractMeshesIndividual] CSG subtract failed:",
Expand Down Expand Up @@ -1058,6 +1103,9 @@ export const flockCSG = {
typeof optionsOrApproach === "string"
? optionsOrApproach
: options.approach || "merge";
console.info(
`[subtractMeshes][entry] requestedApproach=${approach} modelId=${modelId} base=${baseMeshName} tools=${meshNames.length}`,
);

if (approach === "individual") {
return this.subtractMeshesIndividual(
Expand Down
17 changes: 17 additions & 0 deletions api/shapes.js
Original file line number Diff line number Diff line change
Expand Up @@ -721,8 +721,16 @@ export const flockShapes = {
try {
let mesh;
let fontReferenceHeight = null;
const manifoldRequested = useManifold;

console.info(
`[create3DText][path] meshId=${meshId} blockKey=${blockKey} manifoldRequested=${manifoldRequested}`,
);

if (useManifold) {
console.info(
`[create3DText][path] meshId=${meshId} attempting=manifold`,
);
try {
let fontUrl = font;
if (font.endsWith(".json")) {
Expand Down Expand Up @@ -777,6 +785,9 @@ export const flockShapes = {
vertexData.positions = centeredPositions;
vertexData.applyToMesh(mesh);
mesh.flipFaces();
console.info(
`[create3DText][path] meshId=${meshId} used=manifold`,
);
} catch (manifoldError) {
console.warn(
"[create3DText] Manifold approach failed, falling back to standard:",
Expand All @@ -787,6 +798,12 @@ export const flockShapes = {
}

if (!useManifold) {
const fallbackReason = manifoldRequested
? "manifold_failed"
: "manifold_disabled";
console.info(
`[create3DText][path] meshId=${meshId} used=standard reason=${fallbackReason}`,
);
const fontData = await (await fetch(font)).json();
mesh = flock.BABYLON.MeshBuilder.CreateText(
meshId,
Expand Down
Loading