Skip to content

Commit 7aef949

Browse files
added some live runner examples, also fixed some broken links. Updated threejs and babylonjs starter template code with some better looking kernel initialization...
1 parent 5949ed0 commit 7aef949

12 files changed

+806
-128
lines changed

docs/blog/2024-04-23-introducing-bitbybit-runner.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ We've developed and launched three different types of examples to demonstrate a
6060
When you only need to run a script created in Bitbybit.dev without much external interaction, this is a good starting point. There are several ways to load the exported script file into your website, but perhaps the simplest is to just copy and paste its content and assign it to a variable or return it from a function.
6161

6262
We've provided this example on three popular external coding sites:
63-
* [StackBlitz Example](https://stackblitz.com/edit/stackblitz-starters-f6d3a2?file=script.js)
63+
* [StackBlitz Example](https://stackblitz.com/edit/bitbybit-dev-runner-example-inline-string-embed-from-ret?file=script.js)
6464
* [JSFiddle Example](https://jsfiddle.net/matas_bitbybitdev/sa5jroqn/11/)
6565
* [CodePen Example](https://codepen.io/matas-bitbybit-dev/pen/XWQoxmX)
6666

@@ -98,7 +98,7 @@ While this example is basic, it includes all the essential elements of a 3D conf
9898
* Demonstration of how you can provide inputs to your exported Rete script and read outputs from it.
9999

100100
Check out the examples:
101-
* [StackBlitz Example](https://stackblitz.com/edit/stackblitz-starters-ohhh1g?file=script.js)
101+
* [StackBlitz Example](https://stackblitz.com/edit/bitbybit-dev-runner-example-io-from-rete-editor?file=index.html,script.js)
102102
* [JSFiddle Example](https://jsfiddle.net/matas_bitbybitdev/z1pku4gj/3/)
103103
* [CodePen Example](https://codepen.io/matas-bitbybit-dev/pen/KKYbJdj)
104104

docs/learn/npm-packages/start-with-babylon-js.md

Lines changed: 90 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
sidebar_position: 2
2+
sidebar_position: 3
33
title: Using Bitbybit with Babylon.js
44
sidebar_label: Babylon.js Integration
55
description: Learn how to set up and use the @bitbybit-dev/babylonjs package with Vite to create 3D CAD applications, and control which geometry kernels (OCCT, JSCAD, Manifold) are initialized.
@@ -204,7 +204,7 @@ import {
204204
HemisphericLight,
205205
Color4, // Using Color4 for scene clearColor for alpha
206206
} from '@babylonjs/core';
207-
import { first } from 'rxjs';
207+
import { first, firstValueFrom, tap } from 'rxjs';
208208

209209
// Define an interface for kernel options
210210
interface KernelOptions {
@@ -260,6 +260,7 @@ function initBabylonJS() {
260260
stencil: true,
261261
});
262262
const scene = new Scene(engine);
263+
scene.metadata = { shadowGenerators: [] }; // Important for Bitbybit till we have better implementation...
263264
scene.clearColor = new Color4(0.1, 0.11, 0.12, 1); // Set background color
264265

265266
const camera = new ArcRotateCamera(
@@ -289,93 +290,121 @@ function initBabylonJS() {
289290

290291
// --- 5. Bitbybit Kernel Initialization Logic ---
291292
async function initWithKernels(
292-
scene: Scene, // Babylon.js Scene
293-
bitbybit: BitByBitBase,
294-
options: KernelOptions
293+
scene: Scene,
294+
bitbybit: BitByBitBase,
295+
options: KernelOptions
295296
): Promise<{ message: string }> {
296-
return new Promise(async (resolve) => {
297297
let occtWorkerInstance: Worker | undefined;
298298
let jscadWorkerInstance: Worker | undefined;
299299
let manifoldWorkerInstance: Worker | undefined;
300300

301-
// Conditionally create worker instances based on options
301+
// 1. Conditionally create worker instances
302302
if (options.enableOCCT) {
303-
occtWorkerInstance = new Worker(
303+
occtWorkerInstance = new Worker(
304304
new URL('./workers/occt.worker.ts', import.meta.url),
305305
{ name: 'OCC_WORKER', type: 'module' }
306-
);
306+
);
307307
}
308308
if (options.enableJSCAD) {
309-
jscadWorkerInstance = new Worker(
309+
jscadWorkerInstance = new Worker(
310310
new URL('./workers/jscad.worker.ts', import.meta.url),
311311
{ name: 'JSCAD_WORKER', type: 'module' }
312-
);
312+
);
313313
}
314314
if (options.enableManifold) {
315-
manifoldWorkerInstance = new Worker(
315+
manifoldWorkerInstance = new Worker(
316316
new URL('./workers/manifold.worker.ts', import.meta.url),
317317
{ name: 'MANIFOLD_WORKER', type: 'module' }
318-
);
318+
);
319319
}
320320

321-
// Initialize Bitbybit with the (potentially undefined) worker instances.
322-
// This passes the Babylon.js 'scene' to Bitbybit for integration.
323-
scene.metadata = { shadowGenerators: [] };
321+
// 2. Initialize Bitbybit
324322
await bitbybit.init(
325-
scene,
326-
occtWorkerInstance,
327-
jscadWorkerInstance,
328-
manifoldWorkerInstance
323+
scene,
324+
occtWorkerInstance,
325+
jscadWorkerInstance,
326+
manifoldWorkerInstance
329327
);
330328

331-
// Logic to wait for selected kernels to be initialized
332-
let nrResolved = 0;
333-
let resolutionsNeeded = 0;
329+
// 3. Collect promises for kernel initializations
330+
const initializationPromises: Promise<void>[] = [];
331+
let anyKernelSelectedForInit = false;
334332

335-
const checkIfAllInitialized = () => {
336-
if (nrResolved === resolutionsNeeded) {
337-
console.log('Selected kernels initialized:', options);
338-
resolve({ message: 'Selected kernels initialized successfully.' });
339-
}
340-
};
333+
if (options.enableOCCT) {
334+
anyKernelSelectedForInit = true;
335+
if (bitbybit.occtWorkerManager) {
336+
initializationPromises.push(
337+
firstValueFrom(
338+
bitbybit.occtWorkerManager.occWorkerState$.pipe(
339+
first((s) => s.state === OccStateEnum.initialised),
340+
tap(() => console.log('OCCT Initialized'))
341+
)
342+
).then(() => {}) // Ensure the promise resolves to void for Promise.all
343+
);
344+
} else {
345+
console.warn(
346+
'OCCT enabled in options, but occtWorkerManager not found after init.'
347+
);
348+
}
349+
}
341350

342-
if (options.enableOCCT && bitbybit.occtWorkerManager) {
343-
resolutionsNeeded++;
344-
bitbybit.occtWorkerManager.occWorkerState$
345-
.pipe(first((s) => s.state === OccStateEnum.initialised))
346-
.subscribe(() => {
347-
console.log('OCCT Initialized');
348-
nrResolved++;
349-
checkIfAllInitialized();
350-
});
351+
if (options.enableJSCAD) {
352+
anyKernelSelectedForInit = true;
353+
if (bitbybit.jscadWorkerManager) {
354+
initializationPromises.push(
355+
firstValueFrom(
356+
bitbybit.jscadWorkerManager.jscadWorkerState$.pipe(
357+
first((s) => s.state === JscadStateEnum.initialised),
358+
tap(() => console.log('JSCAD Initialized'))
359+
)
360+
).then(() => {})
361+
);
362+
} else {
363+
console.warn(
364+
'JSCAD enabled in options, but jscadWorkerManager not found after init.'
365+
);
366+
}
351367
}
352-
if (options.enableJSCAD && bitbybit.jscadWorkerManager) {
353-
resolutionsNeeded++;
354-
bitbybit.jscadWorkerManager.jscadWorkerState$
355-
.pipe(first((s) => s.state === JscadStateEnum.initialised))
356-
.subscribe(() => {
357-
console.log('JSCAD Initialized');
358-
nrResolved++;
359-
checkIfAllInitialized();
360-
});
368+
369+
if (options.enableManifold) {
370+
anyKernelSelectedForInit = true;
371+
if (bitbybit.manifoldWorkerManager) {
372+
initializationPromises.push(
373+
firstValueFrom(
374+
bitbybit.manifoldWorkerManager.manifoldWorkerState$.pipe(
375+
first((s) => s.state === ManifoldStateEnum.initialised),
376+
tap(() => console.log('Manifold Initialized'))
377+
)
378+
).then(() => {})
379+
);
380+
} else {
381+
console.warn(
382+
'Manifold enabled in options, but manifoldWorkerManager not found after init.'
383+
);
384+
}
361385
}
362-
if (options.enableManifold && bitbybit.manifoldWorkerManager) {
363-
resolutionsNeeded++;
364-
bitbybit.manifoldWorkerManager.manifoldWorkerState$
365-
.pipe(first((s) => s.state === ManifoldStateEnum.initialised))
366-
.subscribe(() => {
367-
console.log('Manifold Initialized');
368-
nrResolved++;
369-
checkIfAllInitialized();
370-
});
386+
387+
// 4. Wait for selected & available kernels or handle no selection/availability
388+
if (!anyKernelSelectedForInit) {
389+
console.log('No kernels selected for initialization.');
390+
return { message: 'No kernels selected for initialization.' };
371391
}
372392

373-
// If no kernels were selected to be enabled
374-
if (resolutionsNeeded === 0) {
375-
console.log('No kernels selected for initialization.');
376-
resolve({ message: 'No kernels selected for initialization.' });
393+
if (initializationPromises.length === 0) {
394+
// Kernels were selected, but none were awaitable (e.g., managers missing for all selected)
395+
console.log(
396+
'Kernels were selected, but none had managers available for awaiting initialization.'
397+
);
398+
return {
399+
message: 'Selected kernels were not awaitable for initialization state.',
400+
};
377401
}
378-
});
402+
403+
await Promise.all(initializationPromises);
404+
console.log('Selected and awaitable kernels initialized:', options);
405+
return {
406+
message: 'Selected and awaitable kernels initialized successfully.',
407+
};
379408
}
380409

381410
// --- 6. Geometry Creation Functions (Examples) ---

0 commit comments

Comments
 (0)