Looks
How the 3D view draws: the realistic or the flat look, and materials for the products in the realistic look. A host needs it to switch the look from controls of its own, or to give its products the materials they are made of.
Functions
setRenderMode()
function setRenderMode(mode): void;
Switches the look, as the user's switch does: the page remembers it, and opens in it the next time.
It is kept in the page's localStorage (where there is none, for as long as the page is open). A remembered look
outweighs setDefaultRenderMode and Buerligons' defaultLook.
Parameters
| Parameter | Type | Description |
|---|---|---|
mode | RenderMode | the look to draw in. |
Returns
void
Example
import { getRenderMode, setRenderMode, type RenderMode } from '@buerli.io/buerligons'
// The host's presentation: the realistic look while it lasts, then the look the user had
let before: RenderMode | null = null
export function startPresenting() {
before = getRenderMode()
setRenderMode('realistic')
}
export function stopPresenting() {
if (before) setRenderMode(before)
before = null
}
setLooks()
function setLooks(looks): void;
Gives products their looks in the realistic look, by product name; replaces those set before, {} clears them.
The name is a part's name, or a template's name in an assembly: each body wears the look of its product, and a product without one keeps the stage's finish. A host sets the looks after it opened a document, and clears them when it closes it. The flat look (RenderMode) does not show them.
Parameters
| Parameter | Type | Description |
|---|---|---|
looks | Record<string, Look> | the look of each product, by its name. |
Returns
void
Example
import { EditorController, setLooks, type Look } from '@buerli.io/buerligons'
declare const editor: EditorController
declare function materialOf(productName: string): Promise<Look | undefined> // the host's material library
// After an open: a look for every product the host has a material for
export async function dressProducts() {
const looks: Record<string, Look> = {}
for (const product of editor.products()) {
const look = await materialOf(product.name)
if (look) looks[product.name] = look
}
setLooks(looks) // replaces the looks set before
}
Hooks
useRenderMode()
function useRenderMode(): RenderMode;
The look the stage draws in now: the component renders again when it changes.
Returns
The render mode.
Example
import { setRenderMode, useLooks, useRenderMode } from '@buerli.io/buerligons'
// A hint where the host gave its products looks and the stage draws flat, in which they do not show
export function LooksHint() {
const flat = useRenderMode() === 'flat'
const hasLooks = useLooks(s => Object.keys(s.looks).length > 0)
if (!flat || !hasLooks) return null
return <button onClick={() => setRenderMode('realistic')}>Show the materials</button>
}
Types
RenderMode
type RenderMode = "flat" | "realistic";
How the stage draws the bodies: 'realistic' (the default) or 'flat'.
realistic: a lit studio. Physically based materials among softboxes, deeper occlusion, light bounced between parts, edges rounded in screen space and a hint of reflection. The ink edges are switched off each time it is switched on (the user can switch them on again; the flat look gets back what it had). The products' looks (setLooks) show in it.flat: the drawing look. Even light, ink edges and silhouettes, a little occlusion where faces meet.
The user switches it in the view options and in the stage's context menu. A host reads it with useRenderMode or getRenderMode, and sets it with setRenderMode or, as the look to open in, with setDefaultRenderMode.
Example
import { Buerligons, setRenderMode, useRenderMode, type RenderMode } from '@buerli.io/buerligons'
// A choice of the host's own, at the end of the app's bar
function LookChoice() {
const mode = useRenderMode()
return (
<select value={mode} onChange={e => setRenderMode(e.target.value as RenderMode)}>
<option value="realistic">Realistic</option>
<option value="flat">Drawing</option>
</select>
)
}
export const App = () => (
<div style={{ height: '100vh' }}>
<Buerligons trail={<LookChoice />} />
</div>
)
Look
A material for the bodies of a product in the realistic look, named as three.js's MeshPhysicalMaterial names it.
A host gives its products their looks by name (setLooks); colours are #rrggbb. The flat look does not show
them. Not every field is taken:
- A body's colour and opacity stay the model's (
colorandopacityare not taken): a host that wants another colour sets it in the model (v1.part.setAppearance). - The environment is the studio's for every body alike, so
envMapIntensityis not taken. - Neither are
anisotropyand its rotation: brushed metal needs a direction along its surface, which a CAD body's mesh does not carry. - Glass (
transmission) is see-through rather than refracting, sothicknessis not taken either.
A field left out keeps the stage's satin finish (roughness and metalness) or three.js's default.
Example
import { init, WASMClient } from '@buerli.io/classcad'
import { Buerligons, EditorController, setLooks, setRenderMode, type Look } from '@buerli.io/buerligons'
init(drawingId => new WASMClient(drawingId, { token: 'ccpk_…' }))
const editor = new EditorController()
// Materials of the host's own, named as three.js names them; the colours stay the model's
const brushedSteel: Look = { metalness: 1, roughness: 0.4 }
const frostedGlass: Look = { transmission: 0.9, roughness: 0.6 }
const lacquer: Look = { roughness: 0.5, clearcoat: 1, clearcoatRoughness: 0.1 }
// Once the document is open: its products' looks by name, and the realistic look, in which they show
export async function openGearbox(data: ArrayBuffer) {
await editor.open({ name: 'Gearbox.ofb', format: 'OFB', data })
setLooks({ Housing: brushedSteel, Cover: frostedGlass, Knob: lacquer })
setRenderMode('realistic')
}
// On close the looks go with the document
export async function closeGearbox() {
setLooks({})
await editor.close()
}
export const App = () => <div style={{ height: '100vh' }}><Buerligons welcome={false} /></div>
Properties
Advanced
Most apps do not need these directly: types they meet through the exports above, and what is there for special cases or for building on buerli itself.
getRenderMode()
function getRenderMode(): RenderMode;
The look the stage draws in now, read once (outside React, say); useRenderMode follows it.
Returns
The render mode.
Example
import { getRenderMode } from '@buerli.io/buerligons'
declare function capture(): Promise<Blob> // the host's screenshot of the page
// A screenshot the host files, with the look it was taken in
export async function screenshot() {
return { image: await capture(), look: getRenderMode() }
}
setDefaultRenderMode()
function setDefaultRenderMode(mode): void;
Sets the look to draw in where the page remembers no choice of the user's; otherwise it does nothing.
A look chosen before (by the user, or with setRenderMode) stays. Buerligons' defaultLook prop calls it;
called before the stage is there, the stage opens in the look.
Parameters
| Parameter | Type | Description |
|---|---|---|
mode | RenderMode | the look to open in. |
Returns
void
Example
import { createRoot } from 'react-dom/client'
import { init, WASMClient } from '@buerli.io/classcad'
import { Buerligons, setDefaultRenderMode } from '@buerli.io/buerligons'
init(drawingId => new WASMClient(drawingId, { token: 'ccpk_…' }))
// A host for drawings opens in the flat look, unless the user chose a look on this page before
setDefaultRenderMode('flat') // or <Buerligons defaultLook="flat" />
createRoot(document.getElementById('root')!).render(
<div style={{ height: '100vh' }}>
<Buerligons />
</div>,
)
useLooks
const useLooks: UseBoundStore<StoreApi<{
looks: Record<string, Look>;
setLooks: (looks) => void;
}>>;
The looks as a zustand store: useLooks(s => s.looks) in a component, useLooks.getState() outside React.
looks holds the look of each product by its name; setLooks on it is setLooks.
Example
import { useLooks } from '@buerli.io/buerligons'
// A legend beside the app: the products that wear a look
export function LookLegend() {
const looks = useLooks(s => s.looks)
return (
<ul>
{Object.entries(looks).map(([name, look]) => (
<li key={name}>
{name}: {(look.metalness ?? 0) > 0.5 ? 'metal' : look.transmission ? 'glass' : 'plastic'}
</li>
))}
</ul>
)
}
// Outside React
console.log(Object.keys(useLooks.getState().looks))