@@ -19,13 +19,12 @@ import type {
1919 UserLayerWithVoxelEditing ,
2020 VoxelEditingContext ,
2121} from "#src/layer/vox/index.js" ;
22- import type { RenderedDataPanel } from "#src/rendered_data_panel.js" ;
22+ import { RenderedDataPanel } from "#src/rendered_data_panel.js" ;
2323import { StatusMessage } from "#src/status.js" ;
2424import { LayerTool , registerTool , type ToolActivation } from "#src/ui/tool.js" ;
2525import { vec3 } from "#src/util/geom.js" ;
2626import { EventActionMap } from "#src/util/mouse_bindings.js" ;
2727import { startRelativeMouseDrag } from "#src/util/mouse_drag.js" ;
28- import { NullarySignal } from "#src/util/signal.js" ;
2928import { BrushShape } from "#src/voxel_annotation/base.js" ;
3029
3130export const BRUSH_TOOL_ID = "vox-brush" ;
@@ -138,53 +137,41 @@ export class VoxelBrushTool extends BaseVoxelTool {
138137
139138 activate ( activation : ToolActivation < this> ) {
140139 super . activate ( activation ) ;
141- const getZoom = ( ) => {
142- const panels = Array . from (
143- this . layer . manager . root . display . panels ,
144- ) as RenderedDataPanel [ ] ;
145- if ( panels . length > 0 ) {
146- return panels [ 0 ] . navigationState . zoomFactor . value ;
147- }
148- return 1.0 ;
149- } ;
150-
151- const getZoomChangedSignal = ( ) => {
152- const panels = Array . from (
153- this . layer . manager . root . display . panels ,
154- ) as RenderedDataPanel [ ] ;
155- return panels . length > 0
156- ? panels [ 0 ] . navigationState . zoomFactor . changed
157- : new NullarySignal ( ) ;
158- } ;
159-
160- const updateCursor = ( ) => {
161- const radiusInVoxels = this . layer . voxBrushRadius . value ;
162- const zoom = getZoom ( ) ;
163- const radiusInPixels = Math . max ( 1 , radiusInVoxels / zoom ) ;
164- const svgSize = 2 * radiusInPixels + 4 ;
165- const svgCenter = svgSize / 2 ;
166-
167- const svgString = `
168- <svg xmlns="http://www.w3.org/2000/svg" width="${ svgSize } " height="${ svgSize } ">
169- <circle cx="${ svgCenter } " cy="${ svgCenter } " r="${ radiusInPixels } "
170- stroke="white" stroke-width="3" fill="rgba(255, 255, 255, 0.2)" />
171- <circle cx="${ svgCenter } " cy="${ svgCenter } " r="${ radiusInPixels } "
172- stroke="black" stroke-width="1.5" fill="rgba(255, 255, 255, 0)" />
173- </svg>
174- ` . replace ( / \s \s + / g, " " ) ;
175-
176- const cursorURL = `url('data:image/svg+xml;utf8,${ encodeURIComponent ( svgString ) } ')` ;
177- this . setCursor ( `${ cursorURL } ${ svgCenter } ${ svgCenter } , crosshair` ) ;
178- } ;
179-
180- updateCursor ( ) ;
181- activation . registerDisposer (
182- this . layer . voxBrushRadius . changed . add ( updateCursor ) ,
183- ) ;
184- activation . registerDisposer ( getZoomChangedSignal ( ) . add ( updateCursor ) ) ;
140+
185141 activation . registerDisposer ( ( ) => {
142+ this . getActivePanel ( ) ?. clearOverlay ( ) ;
186143 this . resetCursor ( ) ;
187144 } ) ;
145+ activation . registerDisposer (
146+ this . mouseState . changed . add ( ( ) => {
147+ this . updateBrushOutline ( ) ;
148+ } )
149+ ) ;
150+ }
151+
152+ private getActivePanel ( ) : RenderedDataPanel | undefined {
153+ let activePanel : RenderedDataPanel | undefined ;
154+ for ( const panel of this . layer . manager . root . display . panels ) {
155+ if ( panel instanceof RenderedDataPanel ) {
156+ if ( panel . mouseX !== - 1 ) {
157+ activePanel = panel ;
158+ } else {
159+ panel . clearOverlay ( ) ;
160+ }
161+ }
162+ }
163+ return activePanel ;
164+ }
165+
166+ private updateBrushOutline ( ) {
167+ const panel = this . getActivePanel ( ) ;
168+ if ( ! panel ) return ;
169+
170+ const zoom = panel . navigationState . zoomFactor . value ;
171+ const radiusInVoxels = this . layer . voxBrushRadius . value ;
172+ const radiusInPixels = radiusInVoxels / zoom ;
173+
174+ panel . drawBrushCursor ( panel . mouseX , panel . mouseY , radiusInPixels ) ;
188175 }
189176
190177 activationCallback ( _activation : ToolActivation < this> ) : void {
0 commit comments