From 3eb089b776e63a6915193e03fd52ce08fc4b616d Mon Sep 17 00:00:00 2001 From: Eric Smith <5d@fifthdread.com> Date: Wed, 20 May 2026 15:03:47 -0400 Subject: [PATCH] add vial-fill shader with liquid effect and smooth tween transitions; increase corner radius to 12px; replace progress bars with shader-based vial fill --- panels/cpu/cpu_module.gd | 68 +++++++++++++++++--------------- panels/cpu/cpu_module.tscn | 15 +++---- panels/memory/memory_module.gd | 46 +++++++++++---------- panels/memory/memory_module.tscn | 15 +++---- scripts/dashboard_grid.gd | 16 ++++---- shaders/vial_fill.gdshader | 60 ++++++++++++++++++++++++++++ 6 files changed, 147 insertions(+), 73 deletions(-) create mode 100644 shaders/vial_fill.gdshader diff --git a/panels/cpu/cpu_module.gd b/panels/cpu/cpu_module.gd index d9ca0fa..1463c78 100644 --- a/panels/cpu/cpu_module.gd +++ b/panels/cpu/cpu_module.gd @@ -4,46 +4,52 @@ class_name CpuModule @onready var title_label: Label = %Title @onready var label: Label = %Label -@onready var progress: ProgressBar = %ProgressBar +@onready var vial_fill: ColorRect = %VialFill var _collector: CpuCollector +var _displayed_fill: float = 0.0 +var _fill_tween: Tween func initialize() -> void: - module_title = "CPU" - _collector = CpuCollector.new() - _style() + module_title = "CPU" + _collector = CpuCollector.new() + _setup_shader() + _style() func refresh(data: Dictionary) -> void: - var usage: float = _collector.collect() - if usage < 0.0: - return + var usage: float = _collector.collect() + if usage < 0.0: + return - var pct: int = roundi(usage) - label.text = "%d%%" % pct - progress.value = pct + var pct: int = roundi(usage) + label.text = "%d%%" % pct + + # Smoothly tween the vial fill + var target: float = usage / 100.0 + if _fill_tween and _fill_tween.is_valid(): + _fill_tween.kill() + _fill_tween = create_tween() + _fill_tween.tween_method(_set_fill, _displayed_fill, target, 0.4).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) + + +func _set_fill(value: float) -> void: + _displayed_fill = value + var mat := vial_fill.material as ShaderMaterial + if mat: + mat.set_shader_parameter("fill", value) + + +func _setup_shader() -> void: + var mat := ShaderMaterial.new() + mat.shader = preload("res://shaders/vial_fill.gdshader") + mat.set_shader_parameter("liquid_color", Color(0.2, 0.5, 0.8, 1.0)) + mat.set_shader_parameter("fill", 0.0) + vial_fill.material = mat func _style() -> void: - title_label.add_theme_color_override("font_color", Color(0.7, 0.7, 0.8, 1.0)) - - label.add_theme_color_override("font_color", Color(0.9, 0.9, 1.0, 1.0)) - label.add_theme_font_size_override("font_size", 48) - - var fg := StyleBoxFlat.new() - fg.bg_color = Color(0.2, 0.5, 0.8, 1.0) - fg.corner_radius_top_left = 4 - fg.corner_radius_top_right = 4 - fg.corner_radius_bottom_right = 4 - fg.corner_radius_bottom_left = 4 - - var bg := StyleBoxFlat.new() - bg.bg_color = Color(0.1, 0.1, 0.14, 1.0) - bg.corner_radius_top_left = 4 - bg.corner_radius_top_right = 4 - bg.corner_radius_bottom_right = 4 - bg.corner_radius_bottom_left = 4 - - progress.add_theme_stylebox_override("fill", fg) - progress.add_theme_stylebox_override("background", bg) + title_label.add_theme_color_override("font_color", Color(0.7, 0.7, 0.8, 1.0)) + label.add_theme_color_override("font_color", Color(0.9, 0.9, 1.0, 1.0)) + label.add_theme_font_size_override("font_size", 48) diff --git a/panels/cpu/cpu_module.tscn b/panels/cpu/cpu_module.tscn index 53ed348..481e1bc 100644 --- a/panels/cpu/cpu_module.tscn +++ b/panels/cpu/cpu_module.tscn @@ -1,11 +1,19 @@ [gd_scene format=3 uid="uid://bq3bs2hb4r7fb"] [ext_resource type="Script" path="res://panels/cpu/cpu_module.gd" id="1"] +[ext_resource type="Shader" path="res://shaders/vial_fill.gdshader" id="2"] [node name="CpuModule" type="PanelContainer"] anchors_preset = 0 script = ExtResource("1") +[node name="VialFill" type="ColorRect" parent="."] +unique_name_in_owner = true +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 + [node name="MarginContainer" type="MarginContainer" parent="."] anchors_preset = 15 anchor_right = 1.0 @@ -31,10 +39,3 @@ size_flags_vertical = 3 unique_name_in_owner = true horizontal_alignment = 1 size_flags_horizontal = 4 - -[node name="ProgressBar" type="ProgressBar" parent="MarginContainer/VBoxContainer"] -unique_name_in_owner = true -size_flags_horizontal = 4 -max_value = 100.0 -value = 0.0 -show_percentage = false diff --git a/panels/memory/memory_module.gd b/panels/memory/memory_module.gd index b1f63b7..ddc866e 100644 --- a/panels/memory/memory_module.gd +++ b/panels/memory/memory_module.gd @@ -4,14 +4,17 @@ class_name MemoryModule @onready var title_label: Label = %Title @onready var label: Label = %Label -@onready var progress: ProgressBar = %ProgressBar +@onready var vial_fill: ColorRect = %VialFill var _collector: MemoryCollector +var _displayed_fill: float = 0.0 +var _fill_tween: Tween func initialize() -> void: module_title = "Memory" _collector = MemoryCollector.new() + _setup_shader() _style() @@ -22,28 +25,31 @@ func refresh(data: Dictionary) -> void: var pct: int = roundi(usage) label.text = "%d%%" % pct - progress.value = pct + + # Smoothly tween the vial fill + var target: float = usage / 100.0 + if _fill_tween and _fill_tween.is_valid(): + _fill_tween.kill() + _fill_tween = create_tween() + _fill_tween.tween_method(_set_fill, _displayed_fill, target, 0.4).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) + + +func _set_fill(value: float) -> void: + _displayed_fill = value + var mat := vial_fill.material as ShaderMaterial + if mat: + mat.set_shader_parameter("fill", value) + + +func _setup_shader() -> void: + var mat := ShaderMaterial.new() + mat.shader = preload("res://shaders/vial_fill.gdshader") + mat.set_shader_parameter("liquid_color", Color(0.2, 0.7, 0.4, 1.0)) + mat.set_shader_parameter("fill", 0.0) + vial_fill.material = mat func _style() -> void: title_label.add_theme_color_override("font_color", Color(0.7, 0.7, 0.8, 1.0)) - label.add_theme_color_override("font_color", Color(0.9, 0.9, 1.0, 1.0)) label.add_theme_font_size_override("font_size", 48) - - var fg := StyleBoxFlat.new() - fg.bg_color = Color(0.2, 0.7, 0.4, 1.0) - fg.corner_radius_top_left = 4 - fg.corner_radius_top_right = 4 - fg.corner_radius_bottom_right = 4 - fg.corner_radius_bottom_left = 4 - - var bg := StyleBoxFlat.new() - bg.bg_color = Color(0.1, 0.1, 0.14, 1.0) - bg.corner_radius_top_left = 4 - bg.corner_radius_top_right = 4 - bg.corner_radius_bottom_right = 4 - bg.corner_radius_bottom_left = 4 - - progress.add_theme_stylebox_override("fill", fg) - progress.add_theme_stylebox_override("background", bg) diff --git a/panels/memory/memory_module.tscn b/panels/memory/memory_module.tscn index a59833f..814d36f 100644 --- a/panels/memory/memory_module.tscn +++ b/panels/memory/memory_module.tscn @@ -1,11 +1,19 @@ [gd_scene format=3 uid="uid://d2d4uqrd2hh3d"] [ext_resource type="Script" path="res://panels/memory/memory_module.gd" id="1"] +[ext_resource type="Shader" path="res://shaders/vial_fill.gdshader" id="2"] [node name="MemoryModule" type="PanelContainer"] anchors_preset = 0 script = ExtResource("1") +[node name="VialFill" type="ColorRect" parent="."] +unique_name_in_owner = true +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 + [node name="MarginContainer" type="MarginContainer" parent="."] anchors_preset = 15 anchor_right = 1.0 @@ -31,10 +39,3 @@ size_flags_vertical = 3 unique_name_in_owner = true horizontal_alignment = 1 size_flags_horizontal = 4 - -[node name="ProgressBar" type="ProgressBar" parent="MarginContainer/VBoxContainer"] -unique_name_in_owner = true -size_flags_horizontal = 4 -max_value = 100.0 -value = 0.0 -show_percentage = false diff --git a/scripts/dashboard_grid.gd b/scripts/dashboard_grid.gd index 3a195bd..d15667f 100644 --- a/scripts/dashboard_grid.gd +++ b/scripts/dashboard_grid.gd @@ -447,10 +447,10 @@ func _style_cell(cell: PanelContainer, col: int, row: int) -> void: hidden.border_width_right = 1 hidden.border_width_bottom = 1 hidden.border_color = Color.TRANSPARENT - hidden.corner_radius_top_left = 6 - hidden.corner_radius_top_right = 6 - hidden.corner_radius_bottom_right = 6 - hidden.corner_radius_bottom_left = 6 + hidden.corner_radius_top_left = 12 + hidden.corner_radius_top_right = 12 + hidden.corner_radius_bottom_right = 12 + hidden.corner_radius_bottom_left = 12 # Visible style — used during drag, may be modified by highlights var visible := StyleBoxFlat.new() @@ -460,10 +460,10 @@ func _style_cell(cell: PanelContainer, col: int, row: int) -> void: visible.border_width_right = 1 visible.border_width_bottom = 1 visible.border_color = Color(0.25, 0.25, 0.35, 1.0) - visible.corner_radius_top_left = 6 - visible.corner_radius_top_right = 6 - visible.corner_radius_bottom_right = 6 - visible.corner_radius_bottom_left = 6 + visible.corner_radius_top_left = 12 + visible.corner_radius_top_right = 12 + visible.corner_radius_bottom_right = 12 + visible.corner_radius_bottom_left = 12 cell.add_theme_stylebox_override("panel", hidden) cell.add_theme_stylebox_override("panel_focused", hidden) diff --git a/shaders/vial_fill.gdshader b/shaders/vial_fill.gdshader new file mode 100644 index 0000000..ac21ed8 --- /dev/null +++ b/shaders/vial_fill.gdshader @@ -0,0 +1,60 @@ +shader_type canvas_item; + +uniform float fill : hint_range(0.0, 1.0) = 0.0; + +uniform vec4 liquid_color : source_color = vec4(0.2, 0.5, 0.8, 1.0); +uniform vec4 bg_color : source_color = vec4(0.08, 0.08, 0.12, 1.0); +uniform vec4 border_color : source_color = vec4(0.2, 0.2, 0.28, 1.0); + +uniform float corner_radius : hint_range(0.0, 0.5) = 0.06; +uniform float border_width : hint_range(0.0, 0.1) = 0.008; + +uniform float wave_amp : hint_range(0.0, 0.05) = 0.012; +uniform float wave_freq : hint_range(0.0, 15.0) = 4.0; + + +float rr_sdf(vec2 p, vec2 half_size, float r) { + vec2 d = abs(p) - half_size + r; + return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - r; +} + + +void fragment() { + vec2 half_size = vec2(0.5, 0.5); + vec2 uv_centered = UV - half_size; + + float max_r = min(corner_radius, half_size.x); + + // Outer rounded rect + float outer_d = rr_sdf(uv_centered, half_size, max_r); + float outer = 1.0 - smoothstep(0.0, max(0.001, fwidth(outer_d)), max(outer_d, 0.0)); + + // Inner (inset by border_width) + float inner_r = max(0.0, max_r - border_width); + float inner_hw = max(0.0, half_size.x - border_width); + float inner_hh = max(0.0, half_size.y - border_width); + float inner_d = rr_sdf(uv_centered, vec2(inner_hw, inner_hh), inner_r); + float inner = 1.0 - smoothstep(0.0, max(0.001, fwidth(inner_d)), max(inner_d, 0.0)); + + // Liquid fill with a gentle animated wave at the surface + float wave = sin(UV.x * wave_freq * 6.283 + TIME * 1.5) * wave_amp; + float fill_line = fill + wave; + float liquid = 1.0 - smoothstep(fill_line - 0.001, fill_line + 0.001, UV.y); + liquid *= inner; + + // Base background + vec3 col = bg_color.rgb; + + // Liquid with subtle depth gradient (lighter near the top) + vec3 liq = mix(liquid_color.rgb, liquid_color.rgb * 1.35, 1.0 - UV.y * 0.6); + col = mix(col, liq, liquid); + + // Surface highlight line + float surface = smoothstep(fill_line - 0.008, fill_line, UV.y) - smoothstep(fill_line, fill_line + 0.002, UV.y); + col += surface * vec3(0.3, 0.4, 0.5) * liquid; + + // Border + col = mix(col, border_color.rgb, outer - inner); + + COLOR = vec4(col, outer); +}