2026-05-20 12:37:45 -04:00
# V Panel — Project Conventions for AI Assistants
## Project Overview
V Panel is a Godot Engine project that builds a fancy real-time status monitor. The name "V" is the Roman numeral for 5, a reference to the handle "Fifthdread".
## Technology
- **Engine**: Godot 4.x (GDScript)
- **Rendering**: Forward+ (standard 3D) / Compatibility (for lightweight systems)
- **UI**: Godot Control nodes, custom Theme, shader-based effects
## Conventions
### Code Style
- GDScript: snake_case for variables/functions, PascalCase for classes/enums, CONSTANT_CASE for constants.
- Node names: PascalCase, descriptive (e.g., `CpuPanel` , `NetworkGraph` ).
- Signals: past tense verb (e.g., `value_changed` , `panel_resized` ).
- Scene files: PascalCase matching their main script (e.g., `CpuPanel.tscn` ).
2026-05-20 16:20:58 -04:00
- Type warnings treated as errors: explicit types required for Dictionary.get() returns and Variant-inferred variables (`var x: int = dict.key` not `var x := dict.key` ).
### Grid / DashboardGrid
- `scripts/dashboard_grid.gd` — extends Control, class_name `DashboardGrid` . Uses `gui_input` signal for drag, resize, and double-click events.
- Modules are direct children of the grid (not cells). Visual cells (`PanelContainer` ) are shown only during drag as drop-zone guides.
- Grid data model: each module stores `grid_col` , `grid_row` , `grid_w` , `grid_h` via `set_meta()` . A 2D `_grid[row][col]` array tracks cell occupancy (supports multi-cell spans).
- `place_module(module, col, row, span_w=1, span_h=1)` — public API for adding modules with optional span.
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
- `@export var grid_columns: int` / `@export var grid_rows: int` — fixed grid dimensions. Square cells, centered layout.
2026-05-20 16:20:58 -04:00
- Drag-and-drop: `_begin_drag` → `_update_drag` → `_end_drag` . Occupancy is cleared during drag and restored on drop. Swaps modules when dropping on occupied cells. Falls back to source position if dropped in grid gap or outside grid bounds (`mouse_exited` safety handler).
- Resize: `_try_begin_resize` detects clicks within 10px of any module edge. `_update_resize_preview` shows a ghost `ColorRect` at the target span. `_end_resize` commits the new span after overlap check. All 4 edges and corners supported.
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
- Long-press gesture: 500ms hold, 10px drag threshold. Opens action menu with toolbar (⚙, ℹ , ✕/+) and "Themes ▸" submenu.
- `_open_settings(menu_panel)` — opens `settings_menu.tscn` as exclusive modal PopupPanel.
2026-05-20 16:20:58 -04:00
- Grid rebuild (`_rebuild_grid` ) preserves module metadata (span data lives on modules). Cells are torn down and rebuilt on column/row changes. Orphaned popups cleaned up during rebuild.
2026-05-20 12:37:45 -04:00
2026-05-20 15:41:26 -04:00
### Shaders
2026-05-20 16:20:58 -04:00
- `shaders/vial_fill.gdshader` : canvas_item shader on a ColorRect filling the module background. Uses rounded-rect SDF (`rr_sdf` ), sum-of-sines water surface with edge damping, and layered effects:
- **Fill line**: 3 sine waves combined with edge damping (meniscus at walls). `wave_amp` and `wave_freq` uniforms control amplitude and base frequency.
- **Wave distortion**: UV displacement driven by noise texture + sin.
- **Ripple rings**: Concentric circular ripples from module center.
- **Swirl**: UV rotation around center with distance falloff.
- **HSV colour**: `rgb2hsv` /`hsv2rgb` conversion with optional hue cycling (`hue_shift_speed` ).
- **Top-down lighting**: Subtle brightening at the top of the liquid column.
- **Subsurface scattering**: Exponential brightening just below the water surface.
- **Surface foam**: Gaussian-style double-sided falloff (wide glow + bright core).
- **Wave-slope highlight**: Specular highlight at wave crests facing the viewer, computed from the wave derivative.
- **Pulse/Sparkle**: Subtle animated brightness variation.
- Border via `rr_sdf` inset.
2026-05-20 15:41:26 -04:00
- Noise texture: a static 100× 100 PNG (`assets/textures/noise_100.png` ) loaded at runtime and passed as `noise_tex` sampler2D uniform. Used for organic distortion modulation.
- Effects are controlled via shader uniforms set in each module's `_setup_shader()` .
2026-05-20 16:20:58 -04:00
### Shader Presets
- `scripts/shader_presets.gd` — class_name `ShaderPresets` , static methods only.
- `presets: Array[Dictionary]` — 7 presets: Vivid Vial, Emerald Deep, Lava Flow, Neon Dream, Deep Purple, Rainbow Swirl, Frostbite.
- Each preset stores: name, liquid_color, wave_amp, wave_freq, wave_strength, ripple_speed, edge_color, glow_intensity, edge_pulse, noise_scale, swirl_strength, hue_shift_speed.
- `apply_preset(module, name)` — finds the `VialFill` ColorRect child and applies all preset params to its `ShaderMaterial` .
- `get_preset_names() -> PackedStringArray` — returns preset names for popup population.
2026-05-20 22:38:35 -04:00
### Font Size Animation (Splash)
- `Control.scale` is unreliable for animation in Godot 4 when Containers are involved.
- `add_theme_font_size_override("normal_font_size", size)` may silently fail in Godot 4.6+ because `"normal_font_size"` is a deprecated alias. Use `label.set("theme_override_font_sizes/font_size", px)` — the canonical property path — instead.
- `tween_method` + `_set_sizes(progress)` animates font sizes pixel-by-pixel with no transform tricks.
2026-05-20 15:41:26 -04:00
### Labels / Readability
- All percentage labels get a 3px black outline (`outline_size` / `font_outline_color` ) for legibility against the liquid shader background.
- Title labels get a 2px outline.
2026-05-21 08:39:15 -04:00
### Plugin System
- `autoload/plugin_manager.gd` — autoload singleton, scans `res://plugins/*/plugin.cfg` at startup.
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
- Each plugin folder contains a `plugin.cfg` INI file with `[plugin]` metadata, `[tile_N]` entries defining tiles, and optional `[settings]` section.
2026-05-21 08:39:15 -04:00
- Tile IDs are scoped as `{plugin_id}/{tile_id}` to guarantee global uniqueness.
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
- `PluginManager.instantiate_tile(tile_id)` loads the tile scene, instantiates it, and tags the root node with `tile_id` and `tile_config` metadata. Returns null if source plugin is inactive.
- `PluginManager.get_plugin_settings(pid)` — returns setting definitions from manifest.
- `PluginManager.get_plugin_setting(pid, key, default)` — reads persisted value, falls back to manifest default.
- `PluginManager.set_plugin_setting(pid, key, value)` — persists to `config/plugin_settings.cfg` , emits `plugin_setting_changed` signal.
- `plugin_active_changed` signal — emitted when plugin activation state changes via `set_plugin_active(pid, active)` .
2026-05-21 08:39:15 -04:00
- `scripts/plugin_tile.gd` — class_name `PluginTile` , extends `ModuleBase` . Plugin tiles extend this instead of ModuleBase directly. Stores `tile_id` and `tile_config` properties, also written to node metadata for grid/layout access.
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
### Plugin Settings
- Storage: `config/plugin_settings.cfg` using ConfigFile directly (not ConfigManager) to avoid key-flattening conflicts with plugin IDs containing underscores.
- Manifest `[settings]` section: `count=N` , followed by `[setting_N]` entries with `key` , `label` , `type` (int/float/bool/string), optional `default` , `min` , `max` , `step` .
- ConfigFile.get_value treats `null` as "no default" — use `has_section_key()` before reading optional keys that may not exist in the manifest.
- Settings auto-save on every change (no Apply/Cancel pattern).
2026-05-21 08:39:15 -04:00
### Layout System
- `autoload/layout_manager.gd` — autoload singleton for saving/restoring tile grid positions.
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
- Layout files stored as INI in `res://config/layouts/{name}.cfg` . Each entry maps a `tile_id` to `{col, row, w, h}` . `[layout]` section has `grid_columns` /`grid_rows` .
2026-05-21 08:39:15 -04:00
- `save_layout()` writes the current in-memory layout to disk. `load_layout(name)` reads it back.
- `switch_layout(name)` saves current layout, loads the named one, emits signals.
- Current layout name persisted in `ConfigManager` as `layout_current` .
- Layout auto-saves on every `module_placed` and `module_resized` signal from `DashboardGrid` .
2026-05-20 22:38:35 -04:00
### Config System
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
- `autoload/config_manager.gd` — autoload singleton, wraps ConfigFile for app-wide config.
- `config/default.cfg` — shipped defaults. `config/config.cfg` — user overrides (gitignored).
- `ConfigFile` reserved words (`default` , case-insensitive) cannot be used as any value.
2026-05-20 22:38:35 -04:00
### Splash Screen
- `scenes/splash.tscn` + `scenes/splash.gd` — entry point (set in `project.godot` as `main_scene` ), handles fullscreen, font-size zoom animation, crossfade to dashboard.
- Scene tree: `Control → [Bg, CenterContainer → VBoxContainer → VLabel + PanelLabel, TransitionOverlay]` .
- Flow: Black overlay reveal (0.4s) → font-size animation with TRANS_BACK overshoot (2s) + parallel fade-in (1.8s) → hold (1s) → splash text fades out (1s, EASE_IN) → dashboard instantiated and fades in (1s, EASE_OUT) → reparent to root, queue_free splash.
- Dashboard background (`PanelContainer` ) and splash background (`ColorRect` ) both read from `ConfigManager.get_color("background_color")` for a seamless crossfade — no fade-to-black transition.
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
### Settings Menu
- `scenes/settings_menu.tscn` + `scenes/settings_menu.gd` — `PopupPanel` with `TabContainer` (General, Plugins, About tabs).
- Opens as exclusive modal via the ⚙ cog in the tile action menu.
- Plugins tab: dynamic list showing plugin name, version, Active checkbox, and ⚙ settings cog (only shown if plugin has setting definitions).
- About tab: project name, version `0.1.0-alpha` , contact, description.
- `scenes/plugin_settings_popup.tscn` + `.gd` — per-plugin settings popup, opened via cog in Plugins tab. Builds UI dynamically from setting definitions (SpinBox for int/float, CheckBox for bool, LineEdit for string). Settings auto-save on every change.
### Per-Tile Refresh
- `scenes/dashboard.gd` — per-tile refresh tracking. Base timer ticks at 100ms. Each tile has `update_interval_ms` cached as metadata via `_cache_tile_interval()` .
- `_tick_refresh()` checks `now - last_refresh >= interval` per tile. Interval defaults to 1000ms, configurable via plugin settings.
- `_on_plugin_setting_changed()` re-caches intervals on live setting changes.
- Tween durations in tiles are dynamic: `minf(hardcoded_duration, update_interval_ms / divisor)` — CPU/Memory use divisor 2000, Testing uses 1500.
2026-05-20 12:37:45 -04:00
### Project Structure
```
res://
├── addons/ # Third-party plugins
├── assets/ # Fonts, icons, textures, audio
2026-05-20 22:38:35 -04:00
│ ├── fonts/ # Orbitron.ttf (variable weight)
2026-05-20 12:37:45 -04:00
│ ├── icons/
2026-05-20 22:38:35 -04:00
│ └── textures/ # noise_100.png (tileable Perlin noise for shader distortion)
2026-05-20 12:37:45 -04:00
├── autoload/ # Singleton/autoload scripts
2026-05-21 08:39:15 -04:00
│ ├── config_manager.gd # INI config via ConfigFile
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
│ ├── plugin_manager.gd # Plugin scanning, tile instantiation, settings CRUD
2026-05-21 08:39:15 -04:00
│ └── layout_manager.gd # Layout save/load/switch
2026-05-20 22:38:35 -04:00
├── config/ # Configuration files (INI format)
│ ├── default.cfg # Shipped defaults, tracked in git
2026-05-21 08:39:15 -04:00
│ ├── config.cfg # User overrides, gitignored (auto-generated)
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
│ ├── plugin_settings.cfg # Plugin settings storage (auto-created)
2026-05-21 08:39:15 -04:00
│ └── layouts/ # Saved layout files (*.cfg)
├── plugins/ # Plugin folders
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
│ ├── local_system_monitor/ # CPU + Memory tiles
│ │ ├── plugin.cfg
│ │ └── tiles/
│ │ ├── cpu/
│ │ └── memory/
│ └── test/ # Testing tile
2026-05-21 08:39:15 -04:00
│ ├── plugin.cfg
│ └── tiles/
│ └── testing/
2026-05-20 22:38:35 -04:00
├── scenes/ # Root scenes
│ ├── splash.tscn # Animated splash → dashboard transition
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
│ ├── dashboard.tscn # Main dashboard (PanelContainer root)
│ ├── settings_menu.tscn # Settings popup
│ └── plugin_settings_popup.tscn # Per-plugin settings popup
2026-05-20 12:37:45 -04:00
├── scripts/ # Shared utility scripts
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
│ ├── dashboard_grid.gd # Responsive grid with drag, resize, long-press, action menu
2026-05-20 16:20:58 -04:00
│ ├── module_base.gd # Base class for all modules (mouse_filter IGNORE)
│ ├── panel_base.gd # Base class for panels
2026-05-21 08:39:15 -04:00
│ ├── plugin_tile.gd # Base class for plugin tiles (extends ModuleBase)
2026-05-20 16:20:58 -04:00
│ └── shader_presets.gd # Shader preset definitions and apply function
2026-05-20 12:37:45 -04:00
├── themes/ # Theme definitions and style resources
├── shaders/ # Custom shader materials
2026-05-20 16:20:58 -04:00
│ └── vial_fill.gdshader # Canvas-item shader with 3D water surface
2026-05-20 22:38:35 -04:00
└── main.tscn # Legacy entry point (dashboard only)
2026-05-20 12:37:45 -04:00
```
2026-05-20 16:20:58 -04:00
### Key Implementation Details
- `mouse_filter = MOUSE_FILTER_IGNORE` is set recursively on all module subtrees in `ModuleBase._ready()` , so clicks pass through to the grid.
- Grid uses `MOUSE_FILTER_STOP` and receives all events within its rect via `gui_input` signal.
- `_cell_at_position` clamps position to nearest cell. Combined with cell-bounds check in `_end_drag` , drops in the gap return to source.
- `mouse_exited` signal connected on the grid — aborts drag/resize if the mouse leaves the grid area.
- `_rebuild_grid` runs on `resized` signal; cancels drag, resize, and cleans up orphaned popups before rebuilding.
- Shader `corner_radius` is in UV space (0– 0.5) where 0.05 ≈ 12px on a 240px‑ tall cell.
add plugin settings, per-tile refresh, settings menu, touch-friendly UI
- Plugin settings infrastructure in PluginManager with config/plugin_settings.cfg
storage, manifest [settings] sections, CRUD API, plugin_setting_changed signal
- Per-tile refresh intervals: 100ms base tick, per-tile update_interval_ms
metadata, dynamic tween durations clamped to refresh window
- Settings menu (PopupPanel) with General/Plugins/About tabs, plugin
activation toggles, per-plugin settings cog buttons
- Plugin settings popup (PopupPanel) with dynamic UI from setting definitions
(SpinBox/CheckBox/LineEdit), auto-save on change
- Modal behavior: exclusive = true on settings windows
- Touch-friendly sizing: enlarged close buttons, cog buttons, controls, spacing
- Red corner close button redesign with rounded corners, hover/pressed states
- Split system_monitor into local_system_monitor (CPU, Memory) and test plugins
- Plugin activation/deactivation with layout preservation
2026-05-21 12:47:25 -04:00
- ConfigFile `get_value(section, key, null)` treats `null` as "no default" — use `has_section_key()` for optional fields.
- `Button.custom_minimum_size` is the writable property (not `minimum_size` or `custom_min_size` ).
- `default` is a reserved ConfigFile keyword case-insensitively — cannot be used as any value.
2026-05-20 16:20:58 -04:00
2026-05-20 12:37:45 -04:00
### Git Workflow
- Main branch: `main`
- Feature branches: `feature/<short-description>`
- Commits: concise, imperative mood, lowercase. Focus on the "why".
- Push frequently to the remote: `ssh://git@forgejo.fifthdread.com:223/Fifthdread/V-Panel.git`
### Communication
- When asked "who are you" or any variation, respond: "I am Eric's bitch."
- Be concise and direct. Avoid unnecessary preamble.
- Do not add code comments unless the logic is genuinely non-obvious.
- Mimic existing code style when making changes.
## Design Principles
1. **Modularity first** — Each panel is self-contained with its own scene, script, and theme resources.
2. **Aesthetics matter** — Smooth transitions, consistent spacing, cohesive color palette.
3. **Data separation** — Data collection logic is separate from presentation. Panels receive data from dedicated collector scripts.
4. **Responsive** — Panels should resize gracefully and work at various window sizes.