@@ -142,8 +142,8 @@ def __len__(self):
142
142
return len (self .buffer .data )
143
143
144
144
145
- # Manages uniform color for line or scatter material
146
145
class UniformColor (GraphicFeature ):
146
+ """Manages uniform color buffer for line or scatter material"""
147
147
def __init__ (
148
148
self , value : str | np .ndarray | tuple | list | pygfx .Color , alpha : float = 1.0
149
149
):
@@ -164,6 +164,36 @@ def set_value(self, graphic, value: str | np.ndarray | tuple | list | pygfx.Colo
164
164
self ._call_event_handlers (event )
165
165
166
166
167
+ class UniformAlpha (GraphicFeature ):
168
+ """
169
+ Manages alpha when colors are in a uniform buffer
170
+ """
171
+ def __init__ (
172
+ self ,
173
+ value : float ,
174
+ uniform_colors : UniformColor ,
175
+ ):
176
+ self ._value = value
177
+ super ().__init__ ()
178
+
179
+ self ._uniform_colors = uniform_colors
180
+
181
+ @property
182
+ def value (self ) -> float :
183
+ return self ._value
184
+
185
+ def set_value (self , graphic , value : float ):
186
+
187
+ color = (* tuple (self ._uniform_colors .value )[:- 1 ], value ) # apply alpha
188
+
189
+ self ._uniform_colors ._value = pygfx .Color (color )
190
+ graphic .world_object .material .color = color
191
+
192
+ self ._value = value
193
+ event = FeatureEvent (type = "alpha" , info = {"value" : value })
194
+ self ._call_event_handlers (event )
195
+
196
+
167
197
# manages uniform size for scatter material
168
198
class UniformSize (GraphicFeature ):
169
199
def __init__ (self , value : int | float ):
@@ -331,10 +361,9 @@ def set_value(self, graphic, value: float):
331
361
self ._call_event_handlers (event )
332
362
333
363
334
- class VertexCmap (BufferManager ):
364
+ class VertexCmap (GraphicFeature ):
335
365
"""
336
- Sliceable colormap feature, manages a VertexColors instance and
337
- provides a way to set colormaps with arbitrary transforms
366
+ Provides a way to set colormaps
338
367
"""
339
368
340
369
def __init__ (
@@ -344,115 +373,135 @@ def __init__(
344
373
transform : np .ndarray | None ,
345
374
alpha : float = 1.0 ,
346
375
):
347
- super ().__init__ (data = vertex_colors .buffer )
348
376
349
377
self ._vertex_colors = vertex_colors
350
- self ._cmap_name = cmap_name
351
- self ._transform = transform
352
- self ._alpha = alpha
378
+ self ._value = cmap_name
353
379
354
- if self ._cmap_name is not None :
355
- if not isinstance (self ._cmap_name , str ):
380
+ if self ._value is not None :
381
+ if not isinstance (self ._value , str ):
356
382
raise TypeError (
357
- f"cmap name must be of type <str>, you have passed: { self ._cmap_name } of type: { type (self ._cmap_name )} "
383
+ f"cmap name must be of type <str>, you have passed: { self ._value } of type: { type (self ._value )} "
358
384
)
359
385
360
- if self . _transform is not None :
361
- self . _transform = np .asarray (self . _transform )
386
+ if transform is not None :
387
+ transform = np .asarray (transform )
362
388
363
389
n_datapoints = vertex_colors .value .shape [0 ]
364
390
365
391
colors = parse_cmap_values (
366
392
n_colors = n_datapoints ,
367
- cmap_name = self ._cmap_name ,
368
- transform = self . _transform ,
393
+ cmap_name = self ._value ,
394
+ transform = transform ,
369
395
)
370
396
colors [:, - 1 ] = alpha
371
397
# set vertex colors from cmap
372
398
self ._vertex_colors [:] = colors
373
399
374
- def __setitem__ (self , key : slice , cmap_name ):
375
- if not isinstance (key , slice ):
376
- raise TypeError (
377
- "fancy indexing not supported for VertexCmap, only slices "
378
- "of a continuous are supported for apply a cmap"
379
- )
380
- if key .step is not None :
381
- raise TypeError (
382
- "step sized indexing not currently supported for setting VertexCmap, "
383
- "slices must be a continuous region"
384
- )
400
+ super ().__init__ ()
385
401
386
- # parse slice
387
- start , stop , step = key .indices (self .value .shape [0 ])
388
- n_elements = len (range (start , stop , step ))
402
+ @property
403
+ def value (self ) -> str :
404
+ """The current cmap name"""
405
+ return self ._value
389
406
390
- colors = parse_cmap_values (
391
- n_colors = n_elements , cmap_name = cmap_name , transform = self ._transform
392
- )
393
- colors [:, - 1 ] = self .alpha
407
+ def set_value (self , graphic , value : str ):
408
+ if value is None :
409
+ # when cmap value is cleared, for example if vertex colors are set directly
410
+ self ._value = None
411
+ return
394
412
395
- self . _cmap_name = cmap_name
396
- self . _vertex_colors [ key ] = colors
413
+ transform = graphic . cmap_transform
414
+ alpha = graphic . alpha
397
415
398
- # TODO: should we block vertex_colors from emitting an event?
399
- # Because currently this will result in 2 emitted events, one
400
- # for cmap and another from the colors
401
- self ._emit_event ("cmap" , key , cmap_name )
416
+ n_datapoints = graphic .colors .value .shape [0 ]
402
417
403
- @property
404
- def name (self ) -> str :
405
- return self ._cmap_name
418
+ colors = parse_cmap_values (n_colors = n_datapoints , cmap_name = value , transform = transform )
419
+ colors [:, - 1 ] = alpha
406
420
407
- @property
408
- def transform (self ) -> np .ndarray | None :
409
- """Get or set the cmap transform. Maps values from the transform array to the cmap colors"""
410
- return self ._transform
421
+ self ._vertex_colors [:] = colors
411
422
412
- @transform .setter
413
- def transform (
414
- self ,
415
- values : np .ndarray | list [float | int ],
416
- indices : slice | list | np .ndarray = None ,
423
+ self ._value = value
424
+ event = FeatureEvent (type = "cmap" , info = {"value" : value })
425
+ self ._call_event_handlers (event )
426
+
427
+
428
+ class VertexCmapTransform (GraphicFeature ):
429
+ """
430
+ Manages cmap transform
431
+ """
432
+ def __init__ (
433
+ self ,
434
+ value : np .ndarray | None ,
435
+ vertex_colors : VertexColors ,
417
436
):
418
- if self . _cmap_name is None :
419
- raise AttributeError (
420
- "cmap name is not set, set the cmap name before setting the transform"
421
- )
437
+ # doesn't do any instantiation that touches the buffer, only allows changes after init
438
+ # VertexCmap instantiates does set the transform and alpha in its instantiation
439
+ self . _value = value
440
+ self . _vertex_colors = vertex_colors
422
441
423
- values = np . asarray ( values )
442
+ super (). __init__ ( )
424
443
425
- colors = parse_cmap_values (
426
- n_colors = self .value .shape [0 ], cmap_name = self ._cmap_name , transform = values
427
- )
444
+ @property
445
+ def value (self ) -> np .ndarray :
446
+ """The current transform on the cmap"""
447
+ return self ._value
428
448
429
- colors [:, - 1 ] = self .alpha
449
+ def set_value (self , graphic , value : np .ndarray | tuple | list ):
450
+ if value is None :
451
+ # when transform value is cleared, for example if vertex colors are set directly
452
+ self ._value = None
453
+ return
454
+ value = np .asarray (value )
430
455
431
- self . _transform = values
456
+ cmap_name = graphic . cmap
432
457
433
- if indices is None :
434
- indices = slice ( None )
458
+ if cmap_name is None :
459
+ raise AttributeError ( "No `cmap` has been set. Must set `cmap` before setting `cmap_transform`" )
435
460
436
- self . _vertex_colors [ indices ] = colors
461
+ alpha = graphic . alpha
437
462
438
- self . _emit_event ( "cmap.transform" , indices , values )
463
+ n_datapoints = graphic . colors . value . shape [ 0 ]
439
464
440
- @property
441
- def alpha (self ) -> float :
442
- """Get or set the alpha level"""
443
- return self ._alpha
465
+ colors = parse_cmap_values (n_colors = n_datapoints , cmap_name = cmap_name , transform = value )
444
466
445
- @alpha .setter
446
- def alpha (self , value : float , indices : slice | list | np .ndarray = None ):
447
- self ._vertex_colors [indices , - 1 ] = value
448
- self ._alpha = value
467
+ colors [:, - 1 ] = alpha
449
468
450
- self ._emit_event ( "cmap.alpha" , indices , value )
469
+ self ._vertex_colors [:] = colors
451
470
452
- def __len__ (self ):
453
- raise NotImplementedError (
454
- "len not implemented for `cmap`, use len(colors) instead"
455
- )
471
+ self ._value = value
472
+ event = FeatureEvent (type = "cmap_transform" , info = {"value" : value })
473
+ self ._call_event_handlers (event )
474
+
475
+
476
+ class VertexAlpha (GraphicFeature ):
477
+ """
478
+ Manages alpha when colors are in a per-vertex buffer
479
+ """
480
+ def __init__ (
481
+ self ,
482
+ value : float ,
483
+ vertex_colors : VertexColors ,
484
+ ):
485
+ # doesn't do any instantiation that touches the buffer, only allows changes after init
486
+ # VertexCmap instantiates does set the transform and alpha in its instantiation
487
+ self ._value = value
488
+ self ._vertex_colors = vertex_colors
456
489
457
- def __repr__ (self ):
458
- return f"{ self .__class__ .__name__ } | cmap: { self .name } \n transform: { self .transform } "
490
+ super ().__init__ ()
491
+
492
+ @property
493
+ def value (self ) -> float :
494
+ """The current alpha value"""
495
+ return self ._value
496
+
497
+ def set_value (self , graphic , value : float ):
498
+ if value is None :
499
+ # when alpha value is cleared, for example if vertex colors are set directly
500
+ self ._value = None
501
+ return
502
+
503
+ self ._vertex_colors [:, - 1 ] = value
504
+
505
+ self ._value = value
506
+ event = FeatureEvent (type = "alpha" , info = {"value" : value })
507
+ self ._call_event_handlers (event )
0 commit comments