@@ -45,7 +45,7 @@ import {
4545 RenderScaleHistogram ,
4646 trackableRenderScaleTarget ,
4747} from "#src/render_scale_statistics.js" ;
48- import { SegmentColorHash } from "#src/segment_color.js" ;
48+ import { getCssColor , SegmentColorHash } from "#src/segment_color.js" ;
4949import type {
5050 SegmentationColorGroupState ,
5151 SegmentationDisplayState ,
@@ -54,6 +54,7 @@ import type {
5454import {
5555 augmentSegmentId ,
5656 bindSegmentListWidth ,
57+ getBaseObjectColor ,
5758 makeSegmentWidget ,
5859 maybeAugmentSegmentId ,
5960 registerCallbackWhenSegmentationDisplayStateChanged ,
@@ -95,6 +96,7 @@ import {
9596 IndirectWatchableValue ,
9697 makeCachedDerivedWatchableValue ,
9798 makeCachedLazyDerivedWatchableValue ,
99+ observeWatchable ,
98100 registerNestedSync ,
99101 TrackableValue ,
100102 WatchableValue ,
@@ -131,6 +133,8 @@ import { makeWatchableShaderError } from "#src/webgl/dynamic_shader.js";
131133import type { DependentViewContext } from "#src/widget/dependent_view_widget.js" ;
132134import { registerLayerShaderControlsTool } from "#src/widget/shader_controls.js" ;
133135
136+ const MAX_LAYER_BAR_UI_INDICATOR_COLORS = 6 ;
137+
134138export class SegmentationUserLayerGroupState
135139 extends RefCounted
136140 implements SegmentationGroupState
@@ -539,6 +543,7 @@ class SegmentationUserLayerDisplayState implements SegmentationDisplayState {
539543 baseSegmentColoring = new TrackableBoolean ( false , false ) ;
540544 baseSegmentHighlighting = new TrackableBoolean ( false , false ) ;
541545 useTempSegmentStatedColors2d : SharedWatchableValue < boolean > ;
546+ hasVolume = new TrackableBoolean ( false , false ) ;
542547
543548 filterBySegmentLabel : ( id : bigint ) => void ;
544549
@@ -746,6 +751,7 @@ export class SegmentationUserLayer extends Base {
746751 const isGroupRoot =
747752 this . displayState . linkedSegmentationGroup . root . value === this ;
748753 let updatedGraph : SegmentationGraphSource | undefined ;
754+ let hasVolume = false ;
749755 for ( const loadedSubsource of subsources ) {
750756 if ( this . addStaticAnnotations ( loadedSubsource ) ) continue ;
751757 const { volume, mesh, segmentPropertyMap, segmentationGraph, local } =
@@ -758,6 +764,7 @@ export class SegmentationUserLayer extends Base {
758764 ) ;
759765 continue ;
760766 }
767+ hasVolume = true ;
761768 loadedSubsource . activate (
762769 ( ) =>
763770 loadedSubsource . addRenderLayer (
@@ -880,6 +887,7 @@ export class SegmentationUserLayer extends Base {
880887 updatedSegmentPropertyMaps ,
881888 ) ;
882889 this . displayState . originalSegmentationGroupState . graph . value = updatedGraph ;
890+ this . displayState . hasVolume . value = hasVolume ;
883891 }
884892
885893 getLegacyDataSourceSpecifications (
@@ -1287,9 +1295,90 @@ export class SegmentationUserLayer extends Base {
12871295 ) ;
12881296 }
12891297
1298+ observeLayerColor ( callback : ( ) => void ) {
1299+ const disposer = super . observeLayerColor ( callback ) ;
1300+ const defaultColorDisposer = observeWatchable (
1301+ callback ,
1302+ this . displayState . segmentDefaultColor ,
1303+ ) ;
1304+ const visibleSegmentDisposer =
1305+ this . displayState . segmentationGroupState . value . visibleSegments . changed . add (
1306+ callback ,
1307+ ) ;
1308+ const colorHashChangeDisposer =
1309+ this . displayState . segmentationColorGroupState . value . segmentColorHash . changed . add (
1310+ callback ,
1311+ ) ;
1312+ const showAllByDefaultDisposer =
1313+ this . displayState . ignoreNullVisibleSet . changed . add ( callback ) ;
1314+ const hasVolumeDisposer = this . displayState . hasVolume . changed . add ( callback ) ;
1315+ return ( ) => {
1316+ disposer ( ) ;
1317+ defaultColorDisposer ( ) ;
1318+ visibleSegmentDisposer ( ) ;
1319+ colorHashChangeDisposer ( ) ;
1320+ showAllByDefaultDisposer ( ) ;
1321+ hasVolumeDisposer ( ) ;
1322+ } ;
1323+ }
1324+
1325+ get automaticLayerBarColors ( ) {
1326+ const { displayState } = this ;
1327+ const visibleSegmentsSet =
1328+ displayState . segmentationGroupState . value . visibleSegments ;
1329+ const fixedColor = displayState . segmentDefaultColor . value ;
1330+
1331+ const noVisibleSegments = visibleSegmentsSet . size === 0 ;
1332+ const tooManyVisibleSegments =
1333+ visibleSegmentsSet . size > MAX_LAYER_BAR_UI_INDICATOR_COLORS ;
1334+ const hasMappedColors =
1335+ displayState . segmentationColorGroupState . value . segmentStatedColors . size >
1336+ 0 ;
1337+ const isFixedColorOnly = fixedColor !== undefined && ! hasMappedColors ;
1338+ const showAllByDefault = displayState . ignoreNullVisibleSet . value ;
1339+ const hasVolume = displayState . hasVolume . value ;
1340+
1341+ if ( noVisibleSegments ) {
1342+ if ( ! showAllByDefault || ! hasVolume ) return [ ] ; // No segments visible
1343+ if ( isFixedColorOnly ) return [ getCssColor ( fixedColor ) ] ;
1344+ return undefined ; // Rainbow colors
1345+ }
1346+ if ( isFixedColorOnly ) {
1347+ return [ getCssColor ( fixedColor ) ] ; // All segments show as one color
1348+ }
1349+
1350+ // Because manually mapped colors are not guaranteed to be unique,
1351+ // we need to actually check all the visible segments if
1352+ // manually mapped colors are used
1353+ if ( ! hasMappedColors && tooManyVisibleSegments ) {
1354+ return undefined ; // Too many segments to show
1355+ }
1356+
1357+ const visibleSegments = [ ...visibleSegmentsSet ] ;
1358+ const colors = visibleSegments . map ( ( id ) => {
1359+ const color = getCssColor ( getBaseObjectColor ( displayState , id ) ) ;
1360+ return { color, id } ;
1361+ } ) ;
1362+
1363+ // Sort the colors by their segment ID
1364+ // Otherwise, the order is random which is a bit confusing in the UI
1365+ colors . sort ( ( a , b ) => {
1366+ const aId = a . id ;
1367+ const bId = b . id ;
1368+ return aId < bId ? - 1 : aId > bId ? 1 : 0 ;
1369+ } ) ;
1370+
1371+ const uniqueColors = [ ...new Set ( colors . map ( ( color ) => color . color ) ) ] ;
1372+ if ( uniqueColors . length > MAX_LAYER_BAR_UI_INDICATOR_COLORS ) {
1373+ return undefined ; // Too many colors to show
1374+ }
1375+ return uniqueColors ;
1376+ }
1377+
12901378 static type = "segmentation" ;
12911379 static typeAbbreviation = "seg" ;
12921380 static supportsPickOption = true ;
1381+ static supportsLayerBarColorSyncOption = true ;
12931382}
12941383
12951384registerLayerControls ( SegmentationUserLayer ) ;
0 commit comments