Proposal
Here is a sketch of what it could look like:
class_name TauLineConfig extends TauPaneOverlayConfig
enum LineMode
{
INDEPENDENT, ## Each series is drawn independently. Lines at the same X may overlap.
STACKED ## Series values are summed along Y so each line sits on top of the previous.
}
@export var mode: LineMode = LineMode.INDEPENDENT
## Normalization applied to stacked line sums when mode is STACKED.
@export var stacked_normalization: StackedNormalization = StackedNormalization.NONE
enum InterpolationMode
{
LINEAR, ## Straight segment between consecutive samples.
STEP_BEFORE, ## Vertical jump first, then horizontal. Y changes at the previous X.
STEP_AFTER, ## Horizontal first, then vertical jump. Y changes at the next X.
STEP_MIDDLE, ## Jump at the midpoint between the two X positions.
SMOOTH_MONOTONE ## Fritsch-Carlson monotone cubic, no overshoot between samples.
}
@export var interpolation_mode: InterpolationMode = InterpolationMode.LINEAR
enum GapPolicy
{
SKIP, ## The curve breaks at any NaN or infinite sample.
BRIDGE ## Invalid samples are dropped and neighbors are connected directly.
}
## Strategy applied when a sample has an invalid X or Y value.
@export var gap_policy: GapPolicy = GapPolicy.SKIP
enum FillMode
{
NONE, ## No area is filled.
TO_BASELINE, ## Fill between the line and a configurable constant baseline.
STACKED ## Each stacked layer is filled down to the layer below.
}
## Strategy applied to fill the area between the line and a baseline.
@export var fill_mode: FillMode = FillMode.NONE
## Reference Y value used when fill_mode is TO_BASELINE.
@export var fill_baseline: float = 0.0
@export var hover_max_distance_px: int = 10
## Visual style applied to this overlay. Never null.
@export var style: TauLineStyle = TauLineStyle.new()
var line_visual_callbacks: LineVisualCallbacks:
get:
return visual_callbacks as LineVisualCallbacks
set(value):
visual_callbacks = value
func _init() -> void:
overlay_type = PaneOverlayType.LINE
And the style:
class_name TauLineStyle extends Resource
## Line widths in pixels in the normal state per series index.
@export var line_widths_px: Array[float] = [2.0]
## Line width in pixels for the two segments adjacent to the hovered sample.
@export var hovered_line_width_px: float = 3.0
## Dash lengths in pixels per series index. Zero means solid.
@export var dash_lengths_px: Array[int] = [0]
## Flat fill color. Color(0, 0, 0, 0) means "use the series color".
@export var fill_color: Color = Color(0, 0, 0, 0)
## Multiplier applied to the fill alpha channel.
@export var fill_alpha: float = 0.2
## Texture sampled across the fill area. Null disables texture fill.
@export var fill_texture: Texture2D = null
## Number of times fill_texture repeats across the reference frame.
@export var fill_texture_tiling: Vector2 = Vector2(1, 1)
## UV translation applied to fill_texture after tiling.
@export var fill_texture_offset: Vector2 = Vector2(0, 0)
## Rotation in degrees applied to fill_texture around UV (0.5, 0.5).
@export var fill_texture_rotation_deg: float = 0.0
enum FillAnchor
{
PANE_RECT, ## Reference frame is the pane rectangle in pixels.
FILL_BOUNDS, ## Reference frame is the bounding box of the filled polygon in pixels.
DATA_DOMAIN ## Reference frame is the visible data domain in data coordinates.
}
## Reference frame used by fill_texture.
@export var fill_anchor: FillAnchor = FillAnchor.PANE_RECT
VisualAttributes carries only the inherited buffers color_buffer and alpha_buffer.
At draw time the final fill color is resolved in this order:
fill_texture if non-null.
fill_color if different from Color(0, 0, 0, 0)
- else series color from
TauXYStyle.series_colors
Whatever survives has its alpha channel multiplied by fill_alpha before rendering.
Edits:
- changed
dash_px scalar to dash_lengths_px array (indexed by series index)
- changed
line_width_px scalar to line_widths_px array (indexed by series index)
Proposal
Here is a sketch of what it could look like:
And the style:
VisualAttributescarries only the inherited bufferscolor_bufferandalpha_buffer.At draw time the final fill color is resolved in this order:
fill_textureif non-null.fill_colorif different fromColor(0, 0, 0, 0)TauXYStyle.series_colorsWhatever survives has its alpha channel multiplied by
fill_alphabefore rendering.Edits:
dash_pxscalar todash_lengths_pxarray (indexed by series index)line_width_pxscalar toline_widths_pxarray (indexed by series index)