Graphics
What goes into the app's canvas besides the geometry: StageLook, the model as a drawing, and the pieces the
plugins draw with.
Components
StageLook
const StageLook: React.FC<StageLookProps>;
The model on the stage: a solid body, drawn by its lines as a drawing shows it (BRANDING.md, "The stage").
- Body. A body the model gives a colour of its own keeps it; the engine's stock grey takes the theme's body tone: a neutral grey that stands clearly off the ground, in either theme.
- Edges. The engine's edges are hairlines (a GL line is one device pixel wide, half a pixel on a dense screen). Each is drawn instead as a line of real width, which takes its colour and its opacity from the hairline, so whatever recolours or fades the model's edges still does. The hairline stays where it is, unseen, as what is pointed at and picked. Seams, where a curved face meets itself, are not drawn: a drawing has none.
- Silhouettes. Where a curved face turns away from the eye there is no edge, and a drawing has a line. It is found for the view as it stands, and found again when the view turns.
- Thin bodies. A body only a few lines thick on screen (a rod, a wire, a sheet from far off) is drawn by its faces: it has no silhouette, and the edges of a body that narrow, or edges that lie that close together, take on its colour. A dense model reads as its parts, not as ink.
Mount it inside the canvas, beside the geometry. (That the edges are ink is the theme's doing: Drawing tells the engine's geometry so.) Without it the model is the engine's own grey with hairline edges. Its props: StageLookProps.
Example
import { Canvas } from '@react-three/fiber'
import type { DrawingID } from '@buerli.io/core'
import { BuerliGeometry } from '@buerli.io/react'
import { StageLook } from '@buerli.io/react-cad'
// the model drawn as a drawing: heavier lines, and no silhouettes on its curved faces
const Stage = ({ drawingId }: { drawingId: DrawingID }) => (
<Canvas orthographic>
<StageLook weight={1.8} silhouettes={false} />
<BuerliGeometry drawingId={drawingId} />
</Canvas>
)
GeometryOverridesManager
const GeometryOverridesManager: React.FC<GeometryOverridesManagerProps>;
Applies the colour overrides that useOverrideGeometryColor registers to the model's meshes and edges in the scene.
It swaps the material of each mesh and edge of the geometry for a recoloured copy, and puts the material back when the override goes. It applies them anew when the geometry, the active feature or the rollback bar changes. Without it, the overrides do nothing: mount it once inside the canvas. Its props: GeometryOverridesManagerProps.
Example
import { Canvas } from '@react-three/fiber'
import type { DrawingID } from '@buerli.io/core'
import { BuerliGeometry } from '@buerli.io/react'
import { GeometryOverridesManager, HoveredConstraintDisplay, PluginGeometryBounds, StageLook } from '@buerli.io/react-cad'
// the pieces an app's own canvas carries for react-cad's plugins and panels
const Stage = ({ drawingId }: { drawingId: DrawingID }) => (
<Canvas orthographic>
<StageLook />
<GeometryOverridesManager drawingId={drawingId} />
<HoveredConstraintDisplay drawingId={drawingId} />
<BuerliGeometry drawingId={drawingId} />
<PluginGeometryBounds drawingId={drawingId} />
</Canvas>
)
Types
GeometryOverridesManagerProps
type GeometryOverridesManagerProps = {
drawingId: DrawingID;
};
Props of GeometryOverridesManager.
Properties
| Property | Type | Description |
|---|---|---|
drawingId | DrawingID | The drawing whose geometry is recoloured. |
StageLookProps
type StageLookProps = {
silhouettes?: boolean;
weight?: number;
};
Props of StageLook.
Properties
| Property | Type | Description |
|---|---|---|
silhouettes? | boolean | false leaves curved faces without their silhouettes. Default true. |
weight? | number | How wide a line is inked, in px. Default 1.4. |
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.
Badge
const Badge: React.FC<BadgeProps>;
A badge on the stage: a constraint's sign where it holds. At rest a neutral disc, its ring and its glyph in the theme's grey. A badge that has something to say (it is under the pointer, in hand, redundant, in conflict) is lit in that colour, its glyph in white, or in ink on a light one.
Its three layers lie in one plane, at the badge's offset, and are drawn in their order: the disc
and the ring are a ground that leaves the depth alone, so the glyph is never measured against
them. (They were set apart by fractions of a polygon offset, which WebGPU takes in whole units
only: there the disc came out in front, and the badges were empty.) A badge onTop, in a HUD,
is not measured against anything: it lies in the sketch's plane with its lines and regions,
which in a slanted view and on WebGPU won it by a hair or lost it as the view was zoomed.
It lies in the XY plane of where it is put, and takes no pointer. Its props: BadgeProps.
Example
import { useMemo } from 'react'
import * as THREE from 'three'
import { Badge, iconDataUrl, useStage } from '@buerli.io/react-cad'
// a badge of the app's own on the stage: a pin's sign, lit while it is under the pointer
function PinBadge({ position, hovered }: { position: [number, number, number]; hovered: boolean }) {
const stage = useStage()
const glyph = useMemo(() => new THREE.TextureLoader().load(iconDataUrl('pin', { ink: '#ffffff' }, 96, 15)), [])
return (
<group position={position}>
<Badge size={6} texture={glyph} tone={hovered ? stage.sketchHover : undefined} renderOrder={10} />
</group>
)
}
BadgeProps
type BadgeProps = {
onTop?: boolean;
polygonOffsetUnits?: number;
renderOrder?: number;
size: number;
texture?: THREE.Texture | null;
tone?: THREE.ColorRepresentation;
};
Props of Badge.
Properties
| Property | Type | Description |
|---|---|---|
onTop? | boolean | Drawn over what it lies on, in its render order (a HUD's badge): no depth test. Default false. |
polygonOffsetUnits? | number | The polygon offset of its layers, in whole units. Default 0. |
renderOrder? | number | The render order of the glyph; the disc and the ring are drawn just before it. Default 0. |
size | number | The disc's diameter, in the scene's units. |
texture? | THREE.Texture | null | The glyph: a texture of a drawing in white, which the badge colours (see iconDataUrl). |
tone? | THREE.ColorRepresentation | The colour the badge is lit in, when it has something to say. Without it, it is at rest. |
CompositeCurveObj
const CompositeCurveObj: React.FC<CompositeCurveObjProps>;
Draws a composite curve of the drawing's structure on the stage: its curves as lines of a width in px.
It draws what the engine tessellated of the curve (its lines, edges and arcs), over the model. Its props: CompositeCurveObjProps. See WorkPointObj.
CompositeCurveObjProps
type CompositeCurveObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
lineWidth?: number;
objectId: ObjectID;
userData?: any;
};
Props of CompositeCurveObj.
Properties
| Property | Type | Description |
|---|---|---|
color? | THREE.ColorRepresentation | Its colour. Default: the stage's datum colour (StageColors.datum). |
drawingId | DrawingID | The drawing the curve is in. |
handlers? | any | Pointer handlers for its lines (react-three-fiber's onClick, onPointerOver, …). |
lineWidth? | number | How wide its line is, in px. Default 3. |
objectId | ObjectID | The composite curve (CC_CompositeCurve) in the drawing's structure tree. |
userData? | any | Given to its lines' userData, for whoever picks it from the scene. |
CSysDisplay
const CSysDisplay: React.FC<CSysDisplayProps>;
Shows the mates of an assembly on the stage: the work coordinate systems of its instances, in a HUD.
It walks the current instance and the instances in it. A mate that is selected in a field (an assembly
constraint's) is drawn flipped and turned as the field has it; the others as their coordinate system lies, as
displayMode says. An instance that does not take part shows only its selected mates. It goes inside the canvas.
Its props: CSysDisplayProps.
Example
import type { DrawingID } from '@buerli.io/core'
import { CSysDisplay, CSysDisplayMode, EditMode, useEditMode } from '@buerli.io/react-cad'
// in the canvas: the mates the user switched visible in the tree, while an assembly is worked on
function Mates({ drawingId }: { drawingId: DrawingID }) {
const mode = useEditMode(drawingId)
if (mode !== EditMode.Assembly) return null
return <CSysDisplay drawingId={drawingId} displayMode={CSysDisplayMode.DisplayVisible} />
}
CSysDisplayMode
Which mates CSysDisplay shows.
Enumeration Members
CSysDisplayProps
type CSysDisplayProps = {
csys?: React.FC<{
drawingId: DrawingID;
matrix: THREE.Matrix4;
userData: {
csysId: ObjectID;
path: ObjectID[];
};
}>;
displayMode?: CSysDisplayMode;
drawingId: DrawingID;
includeSelected?: boolean;
instances?: ObjectID[];
};
Props of CSysDisplay.
Properties
| Property | Type | Description |
|---|---|---|
csys? | React.FC<{ drawingId: DrawingID; matrix: THREE.Matrix4; userData: { csysId: ObjectID; path: ObjectID[]; }; }> | A component that draws a mate that is not selected, instead of the stock axes. |
displayMode? | CSysDisplayMode | Which mates are shown. Default CSysDisplayMode.DisplayAll. |
drawingId | DrawingID | The drawing whose current assembly's mates are shown. |
includeSelected? | boolean | Lets an instance take part that already has a mate selected in another field, which by default does not (a constraint joins two instances); the current product's own mates then do not. Default false. |
instances? | ObjectID[] | The instances whose mates take part, by their product. Default: the current product and every instance in it. |
HoveredConstraintDisplay
const HoveredConstraintDisplay: React.FC<HoveredConstraintDisplayProps>;
Shows what an assembly constraint under the pointer holds: the two mates it joins, or, for a relation such as a gear, the badges of the constraints it relates.
The pointer is on the constraint in the Constraints list or on the stage (the drawing's hovered object). Nothing is shown while a field picks. It goes inside the canvas, and draws in a HUD; the example of GeometryOverridesManager has it in its place. Its props: HoveredConstraintDisplayProps.
HoveredConstraintDisplayProps
type HoveredConstraintDisplayProps = {
drawingId: DrawingID;
};
Props of HoveredConstraintDisplay.
Properties
| Property | Type | Description |
|---|---|---|
drawingId | DrawingID | The drawing whose assembly constraints are pointed at. |
HUD
const HUD: React.FC<HUDProps>;
Draws its children over the scene, after it and without its depth: what is in a HUD is never hidden by the model.
Every HUD of a canvas shares one scene, which is drawn once a frame with the stage's camera, and only while something in it shows; its children are placed in the scene's coordinates as anywhere else. The work geometry, the mates and the sketch's badges on the stage are drawn in one. It goes inside the canvas. Its props: HUDProps.
Example
import { Canvas } from '@react-three/fiber'
import type { DrawingID, ObjectID } from '@buerli.io/core'
import { useBuerliCadFacade } from '@buerli.io/react'
import { HUD, StageLook, WorkPointObj } from '@buerli.io/react-cad'
// a work point that stays in sight, even where the body is in front of it
function Stage({ pointId }: { pointId: ObjectID }) {
const { drawingId, Geometry } = useBuerliCadFacade('bracket')
return (
<Canvas orthographic>
<StageLook />
<Geometry />
<HUD>
<WorkPointObj drawingId={drawingId} objectId={pointId} color="#e7000b" />
</HUD>
</Canvas>
)
}
HUDProps
type HUDProps = {
children?: React.ReactNode;
};
Props of HUD.
Properties
| Property | Type | Description |
|---|---|---|
children? | React.ReactNode | What is drawn over the scene. |
Outline
const Outline: ForwardRefExoticComponent<{
edgeColor1?: [ColorRepresentation, ColorRepresentation];
edgeColor2?: [ColorRepresentation, ColorRepresentation];
edgeColor3?: [ColorRepresentation, ColorRepresentation];
width?: number;
} & Partial<{
selectionLayer: number;
selections1: Object3D<Object3DEventMap>[][];
selections2: Object3D<Object3DEventMap>[][];
selections3: Object3D<Object3DEventMap>[][];
}> & RefAttributes<OutlineEffect>>;
An outline effect for postprocessing's EffectComposer: draws a line around each object of up to three groups,
each group in its own colour.
It is an effect, not an object: it goes into an EffectComposer (@react-three/postprocessing), on WebGL. The
groups are what is hovered, selected and picked, say. A colour comes as a pair: the outline's colour, and the one
that stands in for it on a body of nearly that colour. A ref reaches the effect. Its props: OutlineProps.
Example
import { EffectComposer } from '@react-three/postprocessing'
import type * as THREE from 'three'
import { Outline, useStage } from '@buerli.io/react-cad'
// in a WebGL canvas: what is hovered outlined in the highlight, held back; what is selected, in the highlight
function Outlines({ hovered, selected }: { hovered: THREE.Object3D[]; selected: THREE.Object3D[] }) {
const stage = useStage()
return (
<EffectComposer autoClear={false} multisampling={8}>
<Outline selections1={[hovered]} selections2={[selected]} width={4}
edgeColor1={[stage.hover, stage.alt]} edgeColor2={[stage.select, stage.alt]} />
</EffectComposer>
)
}
OutlineProps
type OutlineProps = OutlineProps1;
Props of Outline: the three groups of objects that are outlined, and the outlines' width and colours.
PluginGeometryBounds
const PluginGeometryBounds: React.FC<PluginGeometryBoundsProps>;
An unseen box around what the plugins of the current part show: its visible work geometry and sketches.
It is a mesh that is not drawn, with the box as its geometry's bounds, so that what fits the view to the scene
(drei's <Bounds>) takes the work points, axes, planes, coordinate systems and sketches in, which are not part of
the model's geometry. It follows them as they change. It goes inside the canvas, next to the geometry that is
fitted. Its props: PluginGeometryBoundsProps.
Example
import { Bounds } from '@react-three/drei'
import type { DrawingID } from '@buerli.io/core'
import { BuerliGeometry } from '@buerli.io/react'
import { PluginGeometryBounds } from '@buerli.io/react-cad'
// zoom to fit takes the work planes and sketches in, not only the bodies
const Fitted = ({ drawingId }: { drawingId: DrawingID }) => (
<Bounds fit observe margin={1.2}>
<BuerliGeometry drawingId={drawingId} />
<PluginGeometryBounds drawingId={drawingId} />
</Bounds>
)
PluginGeometryBoundsProps
type PluginGeometryBoundsProps = {
drawingId: DrawingID;
};
Props of PluginGeometryBounds.
Properties
| Property | Type | Description |
|---|---|---|
drawingId | DrawingID | The drawing whose current part's features are measured. |
SelectedMateObj
const SelectedMateObj: React.FC<SelectedMateObjProps>;
Draws a mate of an assembly as it is selected: the coordinate system it is on, flipped and turned as the mate says, where its path places it in the current instance.
Its props: SelectedMateObjProps. CSysDisplay draws all the mates of an assembly.
Example
import { FlipType, ReorientedType } from '@buerli.io/classcad'
import type { DrawingID, ObjectID } from '@buerli.io/core'
import { HUD, SelectedMateObj, useStage } from '@buerli.io/react-cad'
// in the canvas: a mate the app has in hand, lying along -Z of its coordinate system, over the model
function MateInHand({ drawingId, csysId, path }: { drawingId: DrawingID; csysId: ObjectID; path: ObjectID[] }) {
const stage = useStage()
return (
<HUD>
<SelectedMateObj drawingId={drawingId} csysId={csysId} path={path} flip={FlipType.FLIP_Z_INV}
reorient={ReorientedType.REORIENTED_0} color={stage.pick} />
</HUD>
)
}
SelectedMateObjProps
type SelectedMateObjProps = {
color?: THREE.ColorRepresentation;
csysId: ObjectID;
drawingId: DrawingID;
flip: FlipType;
opacity?: number;
path: ObjectID[];
reorient: ReorientedType;
};
Props of SelectedMateObj.
Properties
useOverrideGeometryColor()
function useOverrideGeometryColor(
name,
priority,
values,
solidIds?
): void;
Recolours bodies of the model while the component that calls it is mounted: a geometry override.
The override is registered under name, and removed again when the component unmounts or its arguments change;
GeometryOverridesManager applies it in the canvas. Where overrides meet on a body, the one with the lower
priority wins. An override without solidIds is for every body that no override of a lower priority has taken,
and overrides of a higher priority are then not applied at all. Keep values and solidIds the same objects from
render to render (useMemo): a new one registers the override anew.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | The override's name: one of the same name replaces it. |
priority | number | Its priority: lower wins. |
values | { lineColor?: Color; lineOpacity?: number; meshColor?: Color; meshOpacity?: number; } | The colours it gives. |
values.lineColor? | Color | The edges' colour. |
values.lineOpacity? | number | The edges' opacity, from 0 to 1 (0 leaves it as it is). |
values.meshColor? | Color | The faces' colour. |
values.meshOpacity? | number | The faces' opacity, from 0 to 1 (0 leaves it as it is). |
solidIds? | number[] | The bodies it is for, as useVisibleSolids gives them; without them, all the others. |
Returns
void
Example
import { useMemo } from 'react'
import type { ObjectID } from '@buerli.io/core'
import { useOverrideGeometryColor } from '@buerli.io/react-cad'
// while it is mounted, the bodies to keep stay as they are and all the others are see-through
function GhostTheRest({ keep }: { keep: ObjectID[] }) {
const asTheyAre = useMemo(() => ({}), [])
const ghost = useMemo(() => ({ meshOpacity: 0.2, lineOpacity: 0.2 }), [])
useOverrideGeometryColor('keep', 0, asTheyAre, keep)
useOverrideGeometryColor('ghost', 1, ghost)
return null
}
WorkAxisObj
const WorkAxisObj: React.FC<WorkAxisObjProps>;
Draws a work axis of the drawing's structure on the stage: an arrow from its position along its direction, the same size on the screen at any zoom.
Its props: WorkAxisObjProps. See WorkPointObj.
WorkAxisObjProps
type WorkAxisObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};
Props of WorkAxisObj.
Properties
| Property | Type | Description |
|---|---|---|
color? | THREE.ColorRepresentation | Its colour. Default: the stage's datum colour (StageColors.datum). |
drawingId | DrawingID | The drawing the object is in. |
handlers? | any | Pointer handlers for its meshes (react-three-fiber's onClick, onPointerOver, …). |
objectId | ObjectID | The work axis (CC_WorkAxis) in the drawing's structure tree. |
opacity? | number | Its opacity, from 0 to 1. Default 1. |
userData? | any | Given to its meshes' userData, for whoever picks it from the scene. |
WorkCoordSystemObj
const WorkCoordSystemObj: React.FC<WorkCoordSystemObjProps>;
Draws a work coordinate system (CC_WorkCoordSystem) of the drawing's structure on the stage: its three axes.
Its props: WorkCoordSystemObjProps. See WorkPointObj.
WorkCoordSystemObjProps
type WorkCoordSystemObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};
Props of WorkCoordSystemObj.
Properties
WorkCSysObj
const WorkCSysObj: React.FC<WorkCSysObjProps>;
Draws a work coordinate system (CC_WorkCSys) of the drawing's structure on the stage: its three axes, where its
coordinate system puts them.
Its props: WorkCSysObjProps. See WorkPointObj.
WorkCSysObjProps
type WorkCSysObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};
Props of WorkCSysObj.
Properties
WorkPlaneObj
const WorkPlaneObj: React.FC<WorkPlaneObjProps>;
Draws a work plane of the drawing's structure on the stage: a square of its size at its position, its outline over a thin fill, seen from either side.
Its props: WorkPlaneObjProps. See WorkPointObj.
WorkPlaneObjProps
type WorkPlaneObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};
Props of WorkPlaneObj.
Properties
| Property | Type | Description |
|---|---|---|
color? | THREE.ColorRepresentation | Its colour. Default: the stage's plane colour (StageColors.plane). |
drawingId | DrawingID | The drawing the object is in. |
handlers? | any | Pointer handlers for its meshes (react-three-fiber's onClick, onPointerOver, …). |
objectId | ObjectID | The work plane (CC_WorkPlane) in the drawing's structure tree. |
opacity? | number | Its opacity, from 0 to 1. Default 1. |
userData? | any | Given to its meshes' userData, for whoever picks it from the scene. |
WorkPointObj
const WorkPointObj: React.FC<WorkPointObjProps>;
Draws a work point of the drawing's structure on the stage: a dot at its position, the same size on the screen at any zoom.
Buerligons draws one over the model where the pointer is on a work point, or where one is selected, in a HUD. Its props: WorkPointObjProps.
Example
import { ScgClassType } from '@buerli.io/classcad'
import { useDrawing } from '@buerli.io/react'
import type { DrawingID } from '@buerli.io/core'
import { HUD, useStage, WorkAxisObj, WorkPlaneObj, WorkPointObj } from '@buerli.io/react-cad'
// in the canvas: the work geometry under the pointer, drawn over the model in the highlight
function HoveredWorkGeometry({ drawingId }: { drawingId: DrawingID }) {
const stage = useStage()
const id = useDrawing(drawingId, (d) => d.interaction.hovered?.objectId)
const clazz = useDrawing(drawingId, (d) => (id ? d.structure.tree[id]?.class : undefined))
if (!id) return null
return (
<HUD>
{clazz === ScgClassType.CCWorkPoint && <WorkPointObj drawingId={drawingId} objectId={id} color={stage.hover} />}
{clazz === ScgClassType.CCWorkAxis && <WorkAxisObj drawingId={drawingId} objectId={id} color={stage.hover} />}
{clazz === ScgClassType.CCWorkPlane && <WorkPlaneObj drawingId={drawingId} objectId={id} color={stage.hover} opacity={0.22} />}
</HUD>
)
}
WorkPointObjProps
type WorkPointObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};
Props of WorkPointObj.
Properties
| Property | Type | Description |
|---|---|---|
color? | THREE.ColorRepresentation | Its colour. Default: the stage's datum colour (StageColors.datum). |
drawingId | DrawingID | The drawing the object is in. |
handlers? | any | Pointer handlers for its meshes (react-three-fiber's onClick, onPointerOver, …). |
objectId | ObjectID | The work point (CC_WorkPoint) in the drawing's structure tree. |
opacity? | number | Its opacity, from 0 to 1. Default 1. |
userData? | any | Given to its meshes' userData, for whoever picks it from the scene. |