Style, Colors and UI
FluxRender.ui.Button
Button(text: str, on_click: Callable, position: Sequence[int] = (0, 50), width: int = 150, height: int = 50, align: Align = Align.LEFT_TOP, style: UIStyle = None)
Bases: UIWidget
Represents an interactive button widget in the UI system.
This class extends UIWidget to provide a clickable element with a text label.
It manages its own visual state transitions (idle, hover, active) and efficiently
updates GPU-accessible color fields (ti.field) for rendering.
Key Features:
- Dynamic Styling: Automatically updates text and background colors based on mouse interaction.
- Smart Callbacks: Inspects the provided
on_clickhandler to optionally pass the button instance as an argument. - Text Rendering: Handles text texture baking for the button label.
- Alignment: Supports various anchor points (e.g., Center, Top-Left) for flexible positioning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
The label text displayed on the button. |
required |
on_click
|
callable
|
The function to execute when the button is clicked. This function can accept 0 arguments or 1 argument (the Button instance). |
required |
position
|
Sequence[int]
|
The (x, y) coordinates for the button's anchor point. Defaults to (0, 50). |
(0, 50)
|
width
|
int
|
The width of the button in pixels. Defaults to 150. |
150
|
height
|
int
|
The height of the button in pixels. Defaults to 50. |
50
|
align
|
Align
|
The alignment anchor point relative to the position coordinates (e.g., LEFT_TOP, CENTER). Defaults to Align.LEFT_TOP. |
LEFT_TOP
|
style
|
UIStyle
|
A styling object defining colors and fonts. If None, default styling is used. |
None
|
Example
Creating a button that changes the color_property of a VectorField when clicked:
import FluxRender as fr
# [Initializing the scene and coordinate system]
# Create a vector field
vector_field = fr.VectorField(vec_function=lambda x, y: (y, -x))
# Define function to toggle vector field color
def toggle_color():
if vector_field.color_property == fr.Property.VELOCITY:
vector_field.color_property = fr.Property.DIVERGENCE
else:
vector_field.color_property = fr.Property.VELOCITY
# Create a button with the toggle function
button = fr.Button(
text = "Change Property",
on_click = toggle_color,
style = fr.UIStyle(
font_size=15
)
)
scene.add(vector_field, button)
Source code in FluxRender/ui.py
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | |
change_text
Changes the button's text and updates the texture.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
new_text
|
str
|
The new text to display on the button. |
required |
is_hovered
A method to check if the cursor position matches the button area
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene
|
Scene
|
Scene object |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if the mouse is hovering over the button, False otherwise |
Source code in FluxRender/ui.py
FluxRender.ui.DynamicText
DynamicText(text: str | Callable, position: Sequence[int] = (20, 100), align: Align = Align.LEFT_TOP, style: UIStyle = None, width: int | None = None, height: int | None = None)
Bases: UIWidget
A highly customizable UI widget designed for rendering text that can update dynamically.
This widget behaves similarly to a standard UI container or button, supporting rich styling options such as backgrounds, text colors, font sizes, text strokes, padding, and rounded corners. It utilizes an anchor-based alignment system to position itself precisely on the screen. The widget features an intelligent sizing layout: it can either force strict physical dimensions or automatically adapt its bounding box to fit the current text content and padding.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str | Callable
|
The static text string to display, or a zero-argument callable (e.g., a lambda function) that provides a dynamically updating string every frame. |
required |
position
|
Sequence[int]
|
The absolute (x, y) screen coordinates serving as the spatial anchor point for the widget. Defaults to (20, 100). |
(20, 100)
|
align
|
Align
|
The alignment behavior relative to the |
LEFT_TOP
|
style
|
UIStyle
|
The styling object defining visual aesthetics like background color, text color, font size, text stroke, padding, and border radius. Defaults to None. |
None
|
width
|
int | None
|
A fixed pixel width for the widget's bounding box. If set to None, the width automatically scales to fit the text length and padding. |
None
|
height
|
int | None
|
A fixed pixel height for the widget's bounding box. If set to None, the height automatically scales to fit the font metrics and padding. |
None
|
Example
Creating an automatically resizing label that displays a dynamically changing simulation value:
import FluxRender as fr
import numpy as np
# 1. Define the mathematical flow
def flow_vector(x, y):
X = np.sin(x) * y
Y = np.cos(y) * x
return X, Y
# 2. Initialize the automated workspace (gives us a Scene with grids and axes)
scene = fr.create_workspace()
# 3. Create a math engine based on our flow function
math_engine = fr.VectorMathEngine(scene, flow_vector)
# 4. Create vector field (optional)
vortex_vector_field = fr.VectorField(vec_function=flow_vector)
# 5. Set up a DataProbe to track the velocity at the mouse cursor's position
mouse_region = fr.CursorRegion(always_active=True)
probe = fr.DataProbe(
target_region=mouse_region,
math_engine=math_engine,
measured_property=fr.Property.VELOCITY
)
# Display the velocity value at the cursor position using a DynamicText widget
text = fr.DynamicText(
text=lambda: f"Current Velocity: {probe.value:.2f}",
position=(20, 600)
)
# 6. Add your entities to the scene and launch!
scene.add(vortex_vector_field, text, mouse_region, probe)
scene.run()
Source code in FluxRender/ui.py
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | |
FluxRender.ui.Axis
Axis(color: Sequence[float] = (1.0, 1.0, 1.0, 1.0), thickness: float = 2.5, label_size: int = 14, label_color: Sequence[float] = (1, 1, 1, 1), label_density: int = 10, label_offset_x: Sequence[float] = (0, -4), label_offset_y: Sequence[float] = (-4, 0), label_offset_0: Sequence[float] = (-4, -4), cover_background: bool = False, antyaliasing: bool = True, draw_arrows: bool = True, arrow_size: float = 25, arrow_style: ArrowStyle = ArrowStyle.HARPOON, arrow_color: Sequence[float] = (0.8, 0.8, 0.8, 1.0))
Bases: Renderable
Renders 2D coordinate axes with dynamic, GPU-accelerated labels.
This class handles the drawing of the main X and Y axes lines using SDF (Signed Distance Fields) for anti-aliasing, and manages the batch rendering of textual labels via a texture atlas. It supports dynamic level-of-detail (LOD) for label density and customizable positioning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
color
|
Sequence[float]
|
The RGBA color of the axis lines (0.0 to 1.0). |
(1.0, 1.0, 1.0, 1.0)
|
thickness
|
float
|
The thickness of the axis lines in pixels. |
2.5
|
label_size
|
int
|
The base font size used for label layout calculations. |
14
|
label_color
|
Sequence[float]
|
The RGBA color tint applied to the text labels. |
(1, 1, 1, 1)
|
label_density
|
int
|
A divisor for the screen dimension to determine target step size. Higher values result in more frequent labels (tighter spacing), while lower values result in fewer labels. Similar to the density logic in Grid. |
10
|
label_offset_x
|
Sequence[float]
|
A tuple (dx, dy) in pixels indicating the rendering offset for labels along the X-axis. Used to center or position text relative to the tick mark. |
(0, -4)
|
label_offset_y
|
Sequence[float]
|
A tuple (dx, dy) in pixels indicating the rendering offset for labels along the Y-axis. |
(-4, 0)
|
label_offset_0
|
Sequence[float]
|
A tuple (dx, dy) in pixels specifically for the origin (0, 0) label, usually positioned in a quadrant to avoid overlapping both axes. |
(-4, -4)
|
cover_background
|
bool
|
If True, disables alpha blending for the text pixels. Instead of mixing with the background, the text color strictly overwrites the destination pixels. This is useful for making labels "erase" or cover underlying grid lines to improve legibility. |
False
|
antyaliasing
|
bool
|
If True, smooths the edges of the axis lines (default True) |
True
|
draw_arrows
|
bool
|
If True, draws arrows at the ends of the axes (default True) |
True
|
arrow_size
|
float
|
The size of the arrows in pixels (default 10.0) |
25
|
arrow_style
|
ArrowStyle
|
The style of the arrows (default ArrowStyle.HARPOON) |
HARPOON
|
arrow_color
|
Sequence[float]
|
The RGBA color of the arrows (0.0 to 1.0). |
(0.8, 0.8, 0.8, 1.0)
|
Example
Creating a yellow coordinate axis with large labels that cover the elements behind them (such as grid lines):
import FluxRender as fr
# [Initializing the scene and coordinate system]
axis = fr.Axis(
color = (1, 0.8, 0, 1), # Yellow axes
label_size = 18, # Larger font size for labels
label_color = (1, 0.8, 0, 1), # Yellow labels
cover_background = True, # Make labels cover elements behind them
arrow_color = (1, 0.8, 0, 1) # Yellow arrows
)
scene.add(axis)
Source code in FluxRender/ui.py
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 | |
FluxRender.ui.Grid
Bases: Renderable
Creates a visible grid on the coordinate system that adjusts depending on zoom. Supports custom color, thickness, density, and anti-aliasing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
color
|
tuple / list
|
The RGBA color of the grid lines. Defaults to (0.6, 0.6, 0.6, 1). |
(0.6, 0.6, 0.6, 1)
|
thickness
|
float
|
The thickness of the grid lines in pixels. Defaults to 1. |
1
|
density
|
int
|
The target number of grid lines across the visible range (higher means more lines). Defaults to 10. |
10
|
antyaliasing
|
bool
|
Whether to apply anti-aliasing. Defaults to True. |
True
|
Example
Creating a double grid with different colors and densities:
import FluxRender as fr
# [Initializing the scene and coordinate system]
# Create a main grid with lower density
main_grid = fr.Grid()
# Create a secondary, less prominent grid with higher density
secondary_grid = fr.Grid(
color=(0.6, 0.6, 0.6, 0.5), # More transparent
density=50
)
scene.add(main_grid, secondary_grid)
Source code in FluxRender/ui.py
FluxRender.ui.UIStyle
dataclass
UIStyle(background_color: Optional[Sequence[float]] = None, hover_background_color: Optional[Sequence[float]] = None, active_background_color: Optional[Sequence[float]] = None, text_color: Optional[Sequence[float]] = None, hover_text_color: Optional[Sequence[float]] = None, text_stroke: Optional[int] = None, text_stroke_color: Optional[Sequence[float]] = None, active_text_color: Optional[Sequence[float]] = None, border_radius: Optional[int] = None, font_size: Optional[int] = None, padding: Optional[Tuple[int, int]] = None, display: Optional[bool] = None, visible: Optional[bool] = None)
A highly flexible, CSS-like styling configuration for UI elements.
Unlike rigid styling properties, UIStyle utilizes a cascading resolution system.
By default, all attributes are initialized to None. This allows elements to
intelligently inherit properties from their parent containers or fall back to
their class-specific and global default themes.
The Cascading Resolution Order
When a UI element needs to render, it resolves its style properties in this exact order: 1. Instance Override: Is it explicitly set in this specific UIStyle instance? 2. Parent Inheritance: If the property is inheritable, does the parent container have it set? 3. Class Default: What is the natural default for this element type (e.g., Button vs. Container)? 4. Global Theme: The ultimate fallback theme defined by the engine.
Inheritable vs. Non-Inheritable Properties
- Inheritable Properties: Typography and deep layout states (e.g.,
text_color,display). If you set these on a container, all child elements inside will inherit them. - Non-Inheritable Properties: Physical bounds and surface appearances (e.g.,
background_color,padding,visible). Setting a red background on a container will NOT make its inner buttons red.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
background_color
|
Optional[Sequence[float]]
|
The background color of the widget in RGBA format. |
None
|
hover_background_color
|
Optional[Sequence[float]]
|
The background color when the mouse hovers over the widget. |
None
|
active_background_color
|
Optional[Sequence[float]]
|
The background color when the widget is active (e.g., clicked). |
None
|
text_color
|
Optional[Sequence[float]]
|
(Inheritable) The color of the text in RGBA format. |
None
|
hover_text_color
|
Optional[Sequence[float]]
|
(Inheritable) The color of the text when the mouse hovers. |
None
|
text_stroke
|
Optional[int]
|
(Inheritable) The width of the stroke around the text. |
None
|
text_stroke_color
|
Optional[Sequence[float]]
|
(Inheritable) The color of the stroke around the text. |
None
|
active_text_color
|
Optional[Sequence[float]]
|
(Inheritable) The color of the text when the widget is active. |
None
|
border_radius
|
Optional[int]
|
Corner rounding radius. |
None
|
font_size
|
Optional[int]
|
(Inheritable) The size of the font used for the widget's text. |
None
|
padding
|
Optional[Tuple[int, int]]
|
Inner spacing (x, y) between the widget's border and its internal content. |
None
|
display
|
Optional[bool]
|
(Inheritable) Toggles rendering for both the element AND all of its children. |
None
|
visible
|
Optional[bool]
|
Toggles rendering for the element's surface only. Children remain drawn. |
None
|
Example
Creating a button with custom styling:
import FluxRender as fr
# [Initializing the scene and coordinate system]
# Create a container style with a warning aesthetic.
# Background is explicitly red, and text is explicitly yellow.
warning_panel_style = fr.UIStyle(
background_color = (1.0, 0.0, 0.0, 0.5),
text_color = (1.0, 1.0, 0.0, 1.0)
)
warning_container = fr.VBox(position=(100, 100), style=warning_panel_style)
# Define function to handle button click
def acknowledge_warning():
print("Warning acknowledged!")
# Create a button WITHOUT passing any specific style.
# It will use its default button background, but intelligently inherit the yellow text color from the warning container.
action_button = fr.Button(
text = "Understood",
on_click = acknowledge_warning
)
warning_container.add(action_button)
scene.add(warning_container)
FluxRender.ui.VBox
VBox(position: Sequence[int] = (20, 200), spacing: int = 15, align: Align = Align.LEFT_TOP, common_width: int = None, common_height: int = None, style: UIStyle = None)
Bases: Container
A vertical layout manager that automatically stacks its children from top to bottom.
The VBox utilizes a deferred layout resolution system. It does not calculate positions immediately upon adding elements. Instead, it waits until the entire UI tree is constructed, and then recursively computes bounding boxes (bottom-up) and element coordinates (top-down). This ensures pixel-perfect alignment regardless of the order in which nested containers and widgets are added.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
position
|
Sequence[int]
|
The (x, y) coordinates for the container's anchor point. |
(20, 200)
|
spacing
|
int
|
The number of pixels inserted vertically between each child element. |
15
|
align
|
Align
|
The alignment method that objects in the container will inherit. |
LEFT_TOP
|
common_width
|
int
|
Forces a uniform width for all DIRECT children (e.g., Buttons) added to this specific container. Does not affect deeply nested elements. |
None
|
common_height
|
int
|
Forces a uniform height for all DIRECT children added to this specific container. Does not affect deeply nested elements. |
None
|
style
|
UIStyle
|
The UIStyle object dictating the container's appearance (e.g., background, padding). Inheritable properties provided here will cascade to all children. |
None
|
Example
Creating a vertical set of three buttons:
import FluxRender as fr
# [Inicialize the scene and coordinate system]
# Define the container for the buttons
vertical_container = fr.VBox((30, 400), common_height=40, common_width=290)
# Create a function called by buttons
def print_name(button):
print(f"Button pressed: {button.text}")
# Create buttons
button1 = fr.Button("Orange", print_name)
button2 = fr.Button("Blue", print_name)
button3 = fr.Button("Green", print_name)
# Add buttons to the container
vertical_container.add(button1, button2, button3)
# Add the container to the scene
scene.add(vertical_container)
Creating a vertical set of three buttons using the context manager to automatically add buttons to the container:
import FluxRender as fr
# [Inicialize the scene and coordinate system]
# Define the container for the buttons
with fr.VBox((30, 400), common_height=40, common_width=290) as vertical_container:
# Create a function called by buttons
def print_name(button):
print(f"Button pressed: {button.text}")
# Create buttons
button1 = fr.Button("Orange", print_name)
button2 = fr.Button("Blue", print_name)
button3 = fr.Button("Green", print_name)
# Add the container to the scene
scene.add(vertical_container)
Source code in FluxRender/ui.py
1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 | |
FluxRender.ui.HBox
HBox(position: Sequence[int] = (20, 100), spacing: int = 15, align: Align = Align.LEFT_TOP, common_width: int = None, common_height: int = None, style: UIStyle = None)
Bases: Container
A horizontal layout manager that automatically arranges its children from left to right.
The HBox relies on a robust deferred layout architecture. By separating the hierarchy building phase from the mathematical layout phase, it can dynamically adapt its own bounding box to wrap exactly around its content, making it highly scalable for complex, nested UI structures.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
position
|
Sequence[int]
|
The (x, y) coordinates for the container's anchor point. |
(20, 100)
|
spacing
|
int
|
The number of pixels inserted horizontally between each child element. |
15
|
align
|
Align
|
The alignment method that objects in the container will inherit. |
LEFT_TOP
|
common_width
|
int
|
Forces a uniform width for all DIRECT children (e.g., Buttons) added to this specific container. Does not affect deeply nested elements. |
None
|
common_height
|
int
|
Forces a uniform height for all DIRECT children added to this |
None
|
spacing
|
int
|
The number of pixels inserted horizontally between each child element. |
15
|
align
|
Align
|
The alignment method that objects in the container will inherit. |
LEFT_TOP
|
common_width
|
int
|
Forces a uniform width for all DIRECT children (e.g., Buttons) added to this specific container. Does not affect deeply nested elements. |
None
|
common_height
|
int
|
Forces a uniform height for all DIRECT children added to this specific container. Does not affect deeply nested elements. |
None
|
style
|
UIStyle
|
The UIStyle object dictating the container's appearance (e.g., background, padding). Inheritable properties provided here will cascade to all children. |
None
|
Example
Creating a horizontal set of three buttons:
import FluxRender as fr
# [Inicialize the scene and coordinate system]
# Define the container for the buttons
horizontal_container = fr.HBox((10, 80), common_height=40, common_width=290)
# Create a function called by buttons
def print_name(button):
print(f"Button pressed: {button.text}")
# Create buttons
button1 = fr.Button("Orange", print_name)
button2 = fr.Button("Blue", print_name)
button3 = fr.Button("Green", print_name)
# Add buttons to the container
horizontal_container.add(button1, button2, button3)
# Add the container to the scene
scene.add(horizontal_container)
Creating a horizontal set of three buttons using the context manager to automatically add buttons to the container:
import FluxRender as fr
# [Inicialize the scene and coordinate system]
# Define the container for the buttons
with fr.HBox((10, 80), common_height=40, common_width=290) as horizontal_container:
# Create a function called by buttons
def print_name(button):
print(f"Button pressed: {button.text}")
# Create buttons
button1 = fr.Button("Orange", print_name)
button2 = fr.Button("Blue", print_name)
button3 = fr.Button("Green", print_name)
# Add the container to the scene
scene.add(horizontal_container)
Source code in FluxRender/ui.py
1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 | |
FluxRender.colors.ColorMapper
ColorMapper(min_hue: int = 240, max_hue: int = 0, min_saturation: float = 0.4, max_saturation: float = 1.0, min_lightness: float = 0.3, max_lightness: float = 0.65, min_alpha: float = 0.8, max_alpha: float = 1.0, scale_type: ScaleType = ScaleType.LINEAR, scale_function=None, min_value: float = None, max_value: float = None)
A dynamic color interpolation engine that translates scalar fields into vibrant visual gradients.
The ColorMapper acts as the visual translator for the mathematical engine. It takes raw scalar values (such as velocity magnitude, divergence, or custom topological metrics) and smoothly maps them to physical RGBA colors.
Crucially, all color interpolation is performed natively within the HSL (Hue, Saturation, Lightness) color space rather than RGB. This architectural choice guarantees perceptually uniform, vivid transitions and completely eliminates the "muddy" or desaturated mid-tones commonly seen in standard linear color blending. It features highly flexible normalization, allowing bounds to be strictly locked at initialization or dynamically injected frame-by-frame by the rendering entities (like VectorField or ParticleSystem).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_hue
|
int
|
Minimum hue in degrees (0-360). Default is 240 (blue). |
240
|
max_hue
|
int
|
Maximum hue in degrees (0-360). Default is 0 (red). |
0
|
min_saturation
|
float
|
Minimum saturation (0-1). Default is 0.4. |
0.4
|
max_saturation
|
float
|
Maximum saturation (0-1). Default is 1.0. |
1.0
|
min_lightness
|
float
|
Minimum lightness (0-1). Default is 0.3. |
0.3
|
max_lightness
|
float
|
Maximum lightness (0-1). Default is 0.65. |
0.65
|
min_alpha
|
float
|
Minimum alpha (0-1). Default is 0.8. |
0.8
|
max_alpha
|
float
|
Maximum alpha (0-1). Default is 1.0. |
1.0
|
scale_type
|
ScaleType
|
The type of scaling to apply to the input values. Default is ScaleType.LINEAR. |
LINEAR
|
scale_function
|
Callable
|
A custom single-argument function f(t). Input t is normalized in [0.0, 1.0], and the output must also be within [0.0, 1.0]. Used only if |
None
|
min_value
|
float
|
Hardcoded minimum value for normalization. If None, the rendering entity will dynamically calculate and inject the minimum value of the current frame. |
None
|
max_value
|
float
|
Hardcoded maximum value for normalization. If None, the rendering entity will dynamically calculate and inject the maximum value. |
None
|
Example
Creating a highly saturated thermal gradient (Blue to Red) with a custom logarithmic-like curve:
import FluxRender as fr
# [Initialize scene and coordinate system here]
# This mapper transitions from green to orange, but uses a square-root curve
mapper = fr.ColorMapper(
min_hue=150,
max_hue=20,
min_saturation=0.8,
max_saturation=1,
min_lightness=0.1,
max_lightness=0.6,
min_alpha=1,
scale_type = fr.ScaleType.CUSTOM,
scale_function = lambda x: x ** 0.5,
)
# Apply the mapper directly to a ParticleSystem
particles = fr.ParticleSystem(
vec_function = lambda x, y: (np.sin(x), np.cos(x) * np.sin(y)),
color_mapper = mapper,
)
scene.add(particles)
Source code in FluxRender/colors.py
calc_color
Maps a scalar value to an RGBA color using HSL color space.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
float
|
The scalar value to map. |
required |
min_value
|
float
|
The minimum value of the range (if self.min_value is not None, it will be used). |
None
|
max_value
|
float
|
The maximum value of the range (if self.max_value is not None, it will be used). |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
color |
tuple
|
A tuple representing the RGBA color (r, g, b, a). |
Source code in FluxRender/colors.py
map_array
Maps a NumPy array of scalar values to an array of RGBA colors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
ndarray
|
A NumPy array of scalar values. |
required |
min_value
|
float
|
The minimum value of the range. |
None
|
max_value
|
float
|
The maximum value of the range. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
colors |
ndarray
|
A NumPy array of RGBA colors corresponding to the input values. |
Source code in FluxRender/colors.py
FluxRender.ui.create_mode_switch
Creates an interactive UI button that cycles through the available rendering modes of a vector field.
This factory function generates a state-machine toggle switch. Each click smoothly
advances the target VectorField to its next sequential FieldMode (e.g., from
WORLD_FIXED to SCREEN_FIXED) and automatically updates the button's text label
to reflect the current state. When the final mode is reached, the switch loops
seamlessly back to the first available mode.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene
|
Scene
|
The main scene object where the button will be registered and rendered. |
required |
vector_field
|
VectorField
|
The target vector field whose rendering mode will be controlled by this button. |
required |
add_to_scene
|
bool
|
If True, the constructed button will be automatically added to the scene. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
Button |
Button
|
The constructed UI button widget, fully bound to the scene and ready for interaction. |
Example
import FluxRender as fr
import numpy as np
scene = fr.create_workspace()
def swirling_vortex(x, y):
vector_dx = np.sin(y) * x
vector_dy = np.cos(x) * y
return vector_dx, vector_dy
vector_field = fr.VectorField(swirling_vortex)
fr.create_mode_switch(scene, vector_field)
scene.add(vector_field)
scene.run()
Source code in FluxRender/ui.py
1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 | |
FluxRender.ui.create_property_switch
Creates a vertical UI panel containing a set of buttons to toggle the active rendering property for multiple vector fields or particle systems.
This function generates a data-driven switch menu. When a button is clicked, it updates the 'color_property' attribute of all provided target entities and visually highlights the currently active button while resetting the others.
Smart Custom Button Injection:
The menu dynamically evaluates the capabilities of the provided entities before construction.
The button for Property.CUSTOM is strictly injected into the UI only if ALL provided
target_entities safely support it. This means every entity must either explicitly have a valid
custom_color_function defined, or its underlying VectorMathEngine must possess a valid
custom_function. This robust check completely eliminates the risk of runtime crashes caused
by unsupported custom property switches.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene
|
Scene
|
The main scene object where the UI container will be registered. |
required |
*target_entities
|
An arbitrary number of objects (e.g., VectorField, ParticleSystem) that possess a 'color_property' attribute to be updated. |
()
|
|
add_to_scene
|
bool
|
If True, the constructed VBox will be automatically added to the scene. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
VBox |
VBox
|
The constructed vertical container holding the property buttons, fully bound to the scene. |
Example
import FluxRender as fr
import numpy as np
scene = fr.create_workspace()
def swirling_vortex(x, y):
vector_dx = np.sin(y) * x
vector_dy = np.cos(x) * y
return vector_dx, vector_dy
vector_field = fr.VectorField(swirling_vortex)
particles = fr.ParticleSystem(swirling_vortex)
fr.create_property_switch(scene, vector_field, particles)
scene.add(vector_field, particles)
scene.run()
Source code in FluxRender/ui.py
2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 | |
FluxRender.ui.create_color_scale_switch
Creates an interactive UI button that cycles through the available color scaling types.
This switch is state-aware. It dynamically builds its cycle path based on the target ColorMapper's capabilities. If the user has not defined a custom scaling function, the switch safely skips the CUSTOM state to prevent runtime errors, cycling only through standard mathematical scales.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene
|
Scene
|
The main scene object where the button will be registered. |
required |
mapper
|
ColorMapper
|
The target color mapper whose scale type will be controlled. |
required |
add_to_scene
|
bool
|
If True, the constructed Button will be automatically added to the scene. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
Button |
Button
|
The constructed UI button widget. |
Example
import FluxRender as fr
import numpy as np
scene = fr.create_workspace()
def swirling_vortex(x, y):
vector_dx = np.sin(y) * x
vector_dy = np.cos(x) * y
return vector_dx, vector_dy
color_mapper = fr.ColorMapper()
vector_field = fr.VectorField(swirling_vortex, color_mapper=color_mapper)
fr.create_color_scale_switch(scene, color_mapper)
scene.add(vector_field)
scene.run()
Source code in FluxRender/ui.py
2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 | |
FluxRender.ui.create_cursor_probe_display
create_cursor_probe_display(scene: Scene, vector_function: Callable | VectorMathEngine, target_property: Property | None = None, display_position: Sequence[int] = (20, 100), add_to_scene: bool = True) -> Tuple[rg.CursorRegion, pr.DataProbe, DynamicText]
The text widget automatically updates every frame, displaying the value of the requested mathematical property at the current mouse position.
Creates a complete, linked data inspection tool consisting of a cursor tracking region, a mathematical data probe, and a dynamic user interface text display.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene
|
Scene
|
The main scene to which the elements will be attached. |
required |
vector_function
|
Callable | VectorMathEngine
|
The mathematical function or math engine used for calculations. |
required |
target_property
|
Property | None
|
The specific vector field property to measure (e.g., DIVERGENCE). If None, the current value of the vector field will be displayed. Default is None. |
None
|
display_position
|
Sequence[int]
|
The screen coordinates (x, y) where the UI text will be anchored. |
(20, 100)
|
add_to_scene
|
bool
|
Whether to automatically add the created elements to the scene. Set to False if you want to manage their addition manually. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
cursor_tracking_region |
CursorRegion
|
The cursor tracking region. |
data_probe |
DataProbe
|
The data probe. |
dynamic_text_display |
DynamicText
|
The dynamic text display. |
Example
import FluxRender as fr
import numpy as np
scene = fr.create_workspace()
def swirling_vortex(x, y):
vector_dx = np.sin(y) * x
vector_dy = np.cos(x) * y
return vector_dx, vector_dy
color_mapper = fr.ColorMapper()
vector_field = fr.VectorField(swirling_vortex, color_mapper=color_mapper)
# Create dynamic text that displays the current value of a vector function under the cursor
fr.create_cursor_probe_display(scene, swirling_vortex)
scene.add(vector_field)
scene.run()
Source code in FluxRender/ui.py
2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 | |