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
This commit is contained in:
parent
12b45b2685
commit
57b36798b9
24 changed files with 1065 additions and 183 deletions
57
AGENTS.md
57
AGENTS.md
|
|
@ -24,9 +24,11 @@ V Panel is a Godot Engine project that builds a fancy real-time status monitor.
|
|||
- 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.
|
||||
- `@export var grid_columns: int` / `@export var grid_rows: int` — fixed grid dimensions. Square cells, centered layout.
|
||||
- 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.
|
||||
- Double-click: opens `PopupMenu` with shader preset names from `ShaderPresets`. Selection applies all preset params to the module's `ShaderMaterial`.
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
### Shaders
|
||||
|
|
@ -63,20 +65,33 @@ V Panel is a Godot Engine project that builds a fancy real-time status monitor.
|
|||
|
||||
### Plugin System
|
||||
- `autoload/plugin_manager.gd` — autoload singleton, scans `res://plugins/*/plugin.cfg` at startup.
|
||||
- Each plugin folder contains a `plugin.cfg` INI file with `[plugin]` metadata and `[tile_N]` entries defining tiles (id, name, scene path, min/max grid spans).
|
||||
- Each plugin folder contains a `plugin.cfg` INI file with `[plugin]` metadata, `[tile_N]` entries defining tiles, and optional `[settings]` section.
|
||||
- Tile IDs are scoped as `{plugin_id}/{tile_id}` to guarantee global uniqueness.
|
||||
- `PluginManager.instantiate_tile(tile_id)` loads the tile scene, instantiates it, and tags the root node with `tile_id` and `tile_config` metadata.
|
||||
- `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)`.
|
||||
- `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.
|
||||
|
||||
### 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).
|
||||
|
||||
### Layout System
|
||||
- `autoload/layout_manager.gd` — autoload singleton for saving/restoring tile grid positions.
|
||||
- Layout files stored as INI in `res://config/layouts/{name}.cfg`. Each entry maps a `tile_id` to `{col, row, w, h}`.
|
||||
- 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`.
|
||||
- `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`.
|
||||
|
||||
### Config System
|
||||
- `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.
|
||||
|
||||
### 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.
|
||||
|
|
@ -84,6 +99,19 @@ V Panel is a Godot Engine project that builds a fancy real-time status monitor.
|
|||
- 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.
|
||||
|
||||
### 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.
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
res://
|
||||
|
|
@ -94,24 +122,30 @@ res://
|
|||
│ └── textures/ # noise_100.png (tileable Perlin noise for shader distortion)
|
||||
├── autoload/ # Singleton/autoload scripts
|
||||
│ ├── config_manager.gd # INI config via ConfigFile
|
||||
│ ├── plugin_manager.gd # Plugin scanning, tile instantiation
|
||||
│ ├── plugin_manager.gd # Plugin scanning, tile instantiation, settings CRUD
|
||||
│ └── layout_manager.gd # Layout save/load/switch
|
||||
├── config/ # Configuration files (INI format)
|
||||
│ ├── default.cfg # Shipped defaults, tracked in git
|
||||
│ ├── config.cfg # User overrides, gitignored (auto-generated)
|
||||
│ ├── plugin_settings.cfg # Plugin settings storage (auto-created)
|
||||
│ └── layouts/ # Saved layout files (*.cfg)
|
||||
├── plugins/ # Plugin folders
|
||||
│ └── system_monitor/ # Built-in system monitoring plugin
|
||||
│ ├── local_system_monitor/ # CPU + Memory tiles
|
||||
│ │ ├── plugin.cfg
|
||||
│ │ └── tiles/
|
||||
│ │ ├── cpu/
|
||||
│ │ └── memory/
|
||||
│ └── test/ # Testing tile
|
||||
│ ├── plugin.cfg
|
||||
│ └── tiles/
|
||||
│ ├── cpu/
|
||||
│ ├── memory/
|
||||
│ └── testing/
|
||||
├── scenes/ # Root scenes
|
||||
│ ├── splash.tscn # Animated splash → dashboard transition
|
||||
│ └── dashboard.tscn # Main dashboard (PanelContainer root)
|
||||
│ ├── dashboard.tscn # Main dashboard (PanelContainer root)
|
||||
│ ├── settings_menu.tscn # Settings popup
|
||||
│ └── plugin_settings_popup.tscn # Per-plugin settings popup
|
||||
├── scripts/ # Shared utility scripts
|
||||
│ ├── dashboard_grid.gd # Responsive grid with drag, resize, preset popup
|
||||
│ ├── dashboard_grid.gd # Responsive grid with drag, resize, long-press, action menu
|
||||
│ ├── module_base.gd # Base class for all modules (mouse_filter IGNORE)
|
||||
│ ├── panel_base.gd # Base class for panels
|
||||
│ ├── plugin_tile.gd # Base class for plugin tiles (extends ModuleBase)
|
||||
|
|
@ -129,6 +163,9 @@ res://
|
|||
- `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.
|
||||
- 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.
|
||||
|
||||
### Git Workflow
|
||||
- Main branch: `main`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue