MasterSelects supports per-clip vector masks with preview-overlay editing, bezier handles, and GPU compositing through the layer pipeline.
- Masks are stored on timeline clips as
ClipMask[]. - The properties panel exposes rectangle, ellipse, and pen creation.
- The preview overlay supports vertex, handle, edge, and whole-mask dragging.
- Mask changes are serialized with the project.
ClipMask currently includes:
idandnameverticesclosedopacityfeatherfeatherQualityinvertedmodeexpandedpositionvisible
MaskMode is currently add, subtract, or intersect.
The UI stores that value and persists it, but the current compositor uses the clip-level mask texture plus inversion when rendering. The preview overlay does not implement separate per-mask compositing passes.
The properties panel exposes three creation flows:
- Rectangle mask
- Ellipse mask
- Pen mask
Rectangle and ellipse masks can be drawn directly on the preview by dragging. Pen mode adds points by clicking in the preview. Clicking the first point closes the path once at least three vertices exist.
MaskEditMode currently includes:
nonedrawingeditingdrawingRectdrawingEllipsedrawingPen
The preview overlay is implemented in src/components/preview/MaskOverlay.tsx.
- Active masks render as SVG paths over the preview.
- Visible masks show vertex squares, bezier handle circles, and edge hit areas.
- Whole-mask dragging moves all vertices together.
- Dragging an edge moves the two adjacent vertices together.
- Dragging a vertex moves that vertex.
- Shift-drag on a vertex scales both bezier handles while keeping the vertex fixed.
Deleteremoves selected vertices.Escapeexits drawing or editing modes.
The overlay uses normalized coordinates internally and maps them to the preview canvas size.
The properties panel exposes the following controls per mask:
- Name
- Visibility toggle
- Mode dropdown
- Opacity
- Feather
- Feather quality
- Position X / Y
- Inverted
featherQuality is stored as a 1-100 value in the UI and defaults to 50 for new masks.
The compositor reads a per-layer mask texture through maskClipId.
If a clip has masks, LayerBuilderService sets the layer's mask lookup id and an inversion flag.
MaskTextureManager falls back to a white texture when no mask texture exists.
Relevant files:
src/stores/timeline/maskSlice.tssrc/components/panels/properties/MasksTab.tsxsrc/components/preview/MaskOverlay.tsxsrc/components/preview/useMaskVertexDrag.tssrc/components/preview/useMaskDrag.tssrc/components/preview/useMaskEdgeDrag.tssrc/components/preview/useMaskShapeDraw.tssrc/engine/texture/MaskTextureManager.ts
- Animated mask paths are not implemented.
- Mask tracking is not implemented.
- Mask interpolation between shapes is not implemented.
- The mask
modefield is stored and editable, but it is not currently used as a separate compositing stage in the code we inspected.