From c37391cc0ac17fd670997c0d7875b7eb59f4642d Mon Sep 17 00:00:00 2001 From: wallstop Date: Fri, 2 Oct 2026 04:42:30 +0000 Subject: [PATCH 1/3] Add the documentation site foundation (T11) The repository has no Pages site, so issue #114's documentation work has nothing to build on. This change adds the site skeleton, two pages, one cross-platform strict build command, and a docs-only Pages workflow. - mkdocs.yml derives the site URL from the repository owner and name, keeps a two-page nav, offers light and dark palettes, and fails the build on an unlisted page or an unresolvable link or image. - docs/index.md and docs/getting-started.md state only claims verified against main: the unity 2021.3 floor, the Tools > Wallstop Studios > Data Visualizer menu path, the panel and Play Mode behavior, and the free-forever terms. - scripts/build-docs.ps1 installs the pinned requirements into a gitignored .docs-venv and runs mkdocs build --strict; -Serve previews locally. The workflow calls the same script. - The Pages workflow builds on pull requests and on main, uploads the built site as a run artifact, and deploys only when the repository has Pages enabled; until then it warns instead of failing the run. Validation: strict build green with 3 pages; red on a missing page link, a missing image, and an unlisted page; actionlint 1.7.7 clean; lint ladder green with 18/18 self-test files; npm pack payload unchanged at 172 files; the release .unitypackage still builds and validates with 92 entries. Refs #114, T11. Pages is not enabled for this repository, so no live URL is claimed and the README does not link to the site yet. --- .github/workflows/docs-pages.yml | 88 +++++++++++++++++++++++++ .gitignore | 5 ++ docs/getting-started.md | 110 +++++++++++++++++++++++++++++++ docs/getting-started.md.meta | 7 ++ docs/index.md | 47 +++++++++++++ docs/index.md.meta | 7 ++ mkdocs.yml | 56 ++++++++++++++++ mkdocs.yml.meta | 7 ++ requirements-docs.txt | 4 ++ requirements-docs.txt.meta | 7 ++ scripts/build-docs.ps1 | 92 ++++++++++++++++++++++++++ scripts/build-docs.ps1.meta | 7 ++ 12 files changed, 437 insertions(+) create mode 100644 .github/workflows/docs-pages.yml create mode 100644 docs/getting-started.md create mode 100644 docs/getting-started.md.meta create mode 100644 docs/index.md create mode 100644 docs/index.md.meta create mode 100644 mkdocs.yml create mode 100644 mkdocs.yml.meta create mode 100644 requirements-docs.txt create mode 100644 requirements-docs.txt.meta create mode 100644 scripts/build-docs.ps1 create mode 100644 scripts/build-docs.ps1.meta diff --git a/.github/workflows/docs-pages.yml b/.github/workflows/docs-pages.yml new file mode 100644 index 0000000..624a8bb --- /dev/null +++ b/.github/workflows/docs-pages.yml @@ -0,0 +1,88 @@ +name: Documentation Pages + +on: + push: + branches: [main] + paths: + - "docs/**" + - "mkdocs.yml" + - "requirements-docs.txt" + - "scripts/build-docs.ps1" + - ".github/workflows/docs-pages.yml" + pull_request: + paths: + - "docs/**" + - "mkdocs.yml" + - "requirements-docs.txt" + - "scripts/build-docs.ps1" + - ".github/workflows/docs-pages.yml" + +# Publication runs to completion instead of being cancelled by a later merge, +# so a half-written deploy never replaces a good site. +concurrency: + group: docs-pages-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: read + +jobs: + build: + name: Build the documentation site + runs-on: ubuntu-latest + timeout-minutes: 10 + outputs: + pages_enabled: ${{ steps.pages.outputs.enabled }} + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@v7 + with: + python-version: '3.12' + + - name: Build the site (strict) + shell: pwsh + run: pwsh -NoProfile -File scripts/build-docs.ps1 + + - name: Upload the built site + uses: actions/upload-pages-artifact@v5 + with: + path: site + + # Pages is a one-time repository setting that this workflow cannot make. + # Report it instead of failing the run, so the validated site stays + # available as a run artifact until an owner enables Pages. + - name: Detect GitHub Pages + id: pages + if: github.event_name == 'push' + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + if gh api "repos/${{ github.repository }}/pages" > /dev/null 2>&1; then + echo "enabled=true" >> "$GITHUB_OUTPUT" + else + echo "enabled=false" >> "$GITHUB_OUTPUT" + echo "::warning::GitHub Pages is not enabled for ${{ github.repository }}. Set Settings > Pages > Source to GitHub Actions to publish; this run's artifact holds the validated site." + fi + + deploy: + name: Publish to GitHub Pages + needs: build + if: needs.build.outputs.pages_enabled == 'true' + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy + id: deployment + uses: actions/deploy-pages@v5 diff --git a/.gitignore b/.gitignore index efcf5b9..434e0a3 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,11 @@ agents.config.json agents.config.json.meta opencode.json.meta +# Documentation site build output and its virtual environment +/site/ +/site.meta +.docs-venv/ + # Unity MCP bridge artifacts (editor state, registry, captures, generated images) .artifacts/ GOAL.md* diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..3fe90ec --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,110 @@ +# Getting started + +This page takes you from an empty project to an edited asset. It covers the +first session only. The +[README](https://github.com/wallstop/DataVisualizer#readme) documents the full +feature set, including themes, processors, and extension points. + +## Requirements + +- Unity 2021.3 or newer. Data Visualizer declares that floor in its + `package.json` and is developed against Unity 6. +- No additional package dependencies. + +## Install the package + +1. Open **Window → Package Manager**. +2. Select **+**, then **Add package from git URL**. +3. Enter `https://github.com/wallstop/DataVisualizer.git` and select **Add**. + +Unity imports the package, and the menu item appears. + +## Open the window + +Select **Tools → Wallstop Studios → Data Visualizer**, then dock it next to the +Inspector. The window has three panels: + +- **Namespaces and types** (left) lists your ScriptableObject types by C# + namespace. Expand a namespace, then select a type to load its instances. +- **Objects** (center) lists every instance of the selected type. One row is + selected at a time. +- **Inspector** (right) shows the full inspector for the selected asset, + including custom editors and Odin Inspector integration. + +## Add your types + +Three controls above the namespace panel fill the catalog: + +- **Search Types** queries the ScriptableObject types Unity knows about. Add + single types or a whole namespace in one action. +- **Scan Asset Folder** crawls a folder and registers the types and existing + assets it finds. Use it to adopt a project that already has data. +- **Scan Scripts Folder** registers types from source folders, which is the + right choice before you create any assets. + +Removing a type or namespace only stops Data Visualizer from tracking it. Your +assets stay on disk. + +## Edit your first asset + +1. Select a type in the left panel. +2. Select an instance in the middle panel. +3. Edit a field in the right panel. The change saves immediately, as in Unity's + own Inspector. + +Use the buttons above the object list to manage the selection: **Clone** writes +a copy with a `Clone` suffix beside the original, **Rename** renames the asset +on disk, **Move** retargets it to another folder, and **Delete** removes it +after you confirm. + +## Create an asset + +Select **Create** to add a new instance of the active type. The asset lands in +your **Data Folder**, which you set under **Settings**. Clones always stay +beside their original, whatever the Data Folder is. + +## Filter and search + +- The filter field above the namespace list narrows the type rows by display + name, without case sensitivity. Namespace headers stay visible. +- The search box above the object list searches the text of all loaded + instances, so you can jump to an asset by its contents. +- Drag labels from **Available** into the **AND:** or **OR:** rows to show only + assets that carry them. The **AND &&** and **OR ||** toggle switches between + matching every dragged label and matching any of them. + +## Keep your arrangement + +Pane widths, ordering, tracked types, and your selection persist between +sessions. Under **Settings**, choose where that state lives: + +- **Persist state in user settings** (default) stores it in your local user + cache, so each developer keeps a private arrangement and version control + stays free of layout churn. +- The project settings asset stores the state in the repository, which suits a + team that wants one shared arrangement. + +**Select active object** mirrors your Data Visualizer selection in Unity's +Inspector, and **Data Folder** sets where new assets are created. + +## While the editor is playing + +Entering Play Mode pauses package-driven work. The window keeps the last loaded +view and shows *Package editing is paused during Play Mode*. While it is paused: + +- **Create**, the add-type controls, and the inspector are disabled, and the + inspector shows read-only content. +- Asset operations are refused: clone, rename, move, delete, and label changes. +- Selecting another type does not load its instances, and the catalog does not + change. + +Everything resumes when you leave Play Mode. + +## Next steps + +- Themes: pick Classic, Nord, Dracula, Compact, or Minimal under **Settings → + Theme**, or author your own. +- Extensibility: derive from `BaseDataObject`, implement the lifecycle + interfaces, and return your own UI Toolkit content from `BuildGUI`. +- The [README](https://github.com/wallstop/DataVisualizer#readme) documents + every control, the theme tokens, and the runtime extension points. diff --git a/docs/getting-started.md.meta b/docs/getting-started.md.meta new file mode 100644 index 0000000..89ab76a --- /dev/null +++ b/docs/getting-started.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 589cb90f42e24feb8ff12b557aebc411 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..d66d535 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,47 @@ +# Data Visualizer + +Data Visualizer is a Unity editor window for ScriptableObject-heavy projects. +It gathers your data in one place: a catalog of your ScriptableObject types +organized by namespace, a list of every instance of the selected type, and the +inspector for the asset you picked. You edit, reorder, and batch-process data +without moving between the Project panel and the Inspector. + +Data Visualizer is free forever. There are no subscriptions, no paid upgrades, +and no feature-gated tiers. The full source is MIT-licensed, and every +capability described here ships in the free package. + +## What it does + +| Task | What the window gives you | +| --- | --- | +| Find | Search your ScriptableObject types by name, add a whole namespace at once, or scan a folder for assets you already have. | +| Inspect | Edit the selected asset in the inspector you already know, including custom editors and Odin Inspector integration. | +| Organize | Reorder namespaces, types, and instances, filter by label, and keep the arrangement across sessions. | +| Edit | Clone, rename, move, delete, and create assets in place, then run processors over one type or all of its instances. | + +## Requirements + +- Unity 2021.3 or newer. +- No additional package dependencies. + +## Install + +1. Open **Window → Package Manager**. +2. Select **+**, then **Add package from git URL**. +3. Enter `https://github.com/wallstop/DataVisualizer.git` and select **Add**. + +Open the window with **Tools → Wallstop Studios → Data Visualizer**. +[Getting started](getting-started.md) walks through the first session. + +!!! note + + Data Visualizer is alpha software. It was built for wallstop studios' + internal use, there is no support commitment yet, and breaking changes can + arrive in any release. Feel free to use it, and report what breaks. + +## Where to go next + +- [Getting started](getting-started.md) — install the package, open the window, and edit your first asset. +- [README](https://github.com/wallstop/DataVisualizer#readme) — the full feature guide, including themes, search, filtering, persistence, and extension points. +- [Video walkthrough](https://youtu.be/3oUxUSKNyhw) — a visual tour of the window. +- [Issues](https://github.com/wallstop/DataVisualizer/issues) — known problems and feature requests. diff --git a/docs/index.md.meta b/docs/index.md.meta new file mode 100644 index 0000000..3d322d8 --- /dev/null +++ b/docs/index.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ffe4f2f457124c0e9169d55dc713fe70 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..621756f --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,56 @@ +# Documentation site configuration. The site is built into site/, which is +# gitignored and excluded from the UPM and npm package payloads. +site_name: Data Visualizer +site_description: Find, inspect, organize, and edit ScriptableObject data in one Unity editor window. +site_url: https://wallstop.github.io/DataVisualizer/ +repo_url: https://github.com/wallstop/DataVisualizer +edit_uri: edit/main/docs/ + +docs_dir: docs +site_dir: site +strict: true + +# admonition backs the `!!! note` callouts; tables and fenced code are already +# MkDocs defaults. +markdown_extensions: + - admonition + +# The README screenshots stay out of the site until the offscreen capture path +# paints every element (issue #114). The README links to them from +# raw.githubusercontent.com, so they stay in the repository. Unity's .meta +# companions are importer bookkeeping and must not be published either. +exclude_docs: | + images/ + *.meta + +theme: + name: material + features: + - navigation.sections + - navigation.top + - search.highlight + - search.suggest + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to light mode + +nav: + - Home: index.md + - Getting started: getting-started.md + +validation: + nav: + omitted_files: warn + not_found: warn + links: + not_found: warn + absolute_links: relative_to_docs + unrecognized_links: warn diff --git a/mkdocs.yml.meta b/mkdocs.yml.meta new file mode 100644 index 0000000..c89c477 --- /dev/null +++ b/mkdocs.yml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f36939d2efcb4b4196601f9c5d9b7e00 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 0000000..eb1ae71 --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,4 @@ +# Documentation build dependencies. Development only: neither this file nor +# the built site is part of the UPM or npm package payload. +mkdocs==1.6.1 +mkdocs-material==9.7.7 diff --git a/requirements-docs.txt.meta b/requirements-docs.txt.meta new file mode 100644 index 0000000..fc64da4 --- /dev/null +++ b/requirements-docs.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2449b5a8cbac4619bf44f39f1c0af427 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/scripts/build-docs.ps1 b/scripts/build-docs.ps1 new file mode 100644 index 0000000..7a71f79 --- /dev/null +++ b/scripts/build-docs.ps1 @@ -0,0 +1,92 @@ +[CmdletBinding(PositionalBinding = $false)] +param( + [string]$Root, + [switch]$Serve +) + +$ErrorActionPreference = 'Stop' +Import-Module (Join-Path $PSScriptRoot 'LlmConfig.psm1') -DisableNameChecking + +function Resolve-PythonLauncher { + foreach ($candidate in @('python3', 'python')) { + $command = Get-Command $candidate -ErrorAction SilentlyContinue + if ($null -ne $command) { + return $command.Source + } + } + return $null +} + +function Get-VenvPythonPath { + param([string]$VenvRoot) + $relative = if ($IsWindows) { 'Scripts/python.exe' } else { 'bin/python' } + return Join-Path $VenvRoot $relative +} + +function Invoke-CheckedPython { + param( + [string]$PythonPath, + [string[]]$Arguments, + [string]$Description + ) + & $PythonPath @Arguments + if ($LASTEXITCODE -ne 0) { + throw "$Description failed with exit code $LASTEXITCODE" + } +} + +try { + $repoRoot = Resolve-LlmRoot $Root + $requirementsPath = Join-Path $repoRoot 'requirements-docs.txt' + $configPath = Join-Path $repoRoot 'mkdocs.yml' + foreach ($required in @($requirementsPath, $configPath)) { + if (-not (Test-Path -LiteralPath $required -PathType Leaf)) { + Write-Host "[docs] ERROR: required file '$required' does not exist" + exit 1 + } + } + + $venvRoot = Join-Path $repoRoot '.docs-venv' + $pythonPath = Get-VenvPythonPath -VenvRoot $venvRoot + if (-not (Test-Path -LiteralPath $pythonPath -PathType Leaf)) { + $launcher = Resolve-PythonLauncher + if ([string]::IsNullOrEmpty($launcher)) { + Write-Host '[docs] ERROR: no python3 or python executable is on PATH' + exit 1 + } + Write-Host "[docs] creating the virtual environment at $venvRoot" + Invoke-CheckedPython -PythonPath $launcher -Arguments @( + '-m', 'venv', $venvRoot + ) -Description 'python -m venv' + $pythonPath = Get-VenvPythonPath -VenvRoot $venvRoot + if (-not (Test-Path -LiteralPath $pythonPath -PathType Leaf)) { + Write-Host "[docs] ERROR: the virtual environment has no interpreter at $pythonPath" + exit 1 + } + } + + Invoke-CheckedPython -PythonPath $pythonPath -Arguments @( + '-m', 'pip', 'install', '--quiet', '--disable-pip-version-check', + '--requirement', $requirementsPath + ) -Description 'pip install -r requirements-docs.txt' + + if ($Serve) { + Invoke-CheckedPython -PythonPath $pythonPath -Arguments @( + '-m', 'mkdocs', 'serve', '--config-file', $configPath + ) -Description 'mkdocs serve' + exit 0 + } + + # --strict is repeated on the command line so the build stays strict even + # if mkdocs.yml is later relaxed for the preview server. The output + # directory stays owned by mkdocs.yml. + Invoke-CheckedPython -PythonPath $pythonPath -Arguments @( + '-m', 'mkdocs', 'build', '--strict', '--config-file', $configPath + ) -Description 'mkdocs build --strict' + + Write-Host '[docs] OK: strict build succeeded' + exit 0 +} catch { + Write-Host "[docs] ERROR: $($_.Exception.Message)" + exit 1 +} diff --git a/scripts/build-docs.ps1.meta b/scripts/build-docs.ps1.meta new file mode 100644 index 0000000..a05743f --- /dev/null +++ b/scripts/build-docs.ps1.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1da09103451b49238a243a79b34261a4 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From 71be7fc502555554d2cbc2091e485e1363b224ff Mon Sep 17 00:00:00 2001 From: wallstop Date: Fri, 2 Oct 2026 04:44:06 +0000 Subject: [PATCH 2/3] Qualify the Unity 2021.3 floor as declared, not yet validated The pages stated the package's minimum Unity version as if it were a tested floor. The window is developed and tested on Unity 6, and the 2021.3 editor is not part of the local validation, which #86 tracks. The pages now say so and link the issue. --- docs/getting-started.md | 6 ++++-- docs/index.md | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 3fe90ec..1212beb 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -7,8 +7,10 @@ feature set, including themes, processors, and extension points. ## Requirements -- Unity 2021.3 or newer. Data Visualizer declares that floor in its - `package.json` and is developed against Unity 6. +- Unity 2021.3 or newer. `package.json` declares that floor, and the window is + developed and tested on Unity 6. The 2021.3 editor is not part of the local + validation yet, which + [#86](https://github.com/wallstop/DataVisualizer/issues/86) tracks. - No additional package dependencies. ## Install the package diff --git a/docs/index.md b/docs/index.md index d66d535..f5955bb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -21,7 +21,8 @@ capability described here ships in the free package. ## Requirements -- Unity 2021.3 or newer. +- Unity 2021.3 or newer, the floor declared in `package.json`. The window is + developed and tested on Unity 6. - No additional package dependencies. ## Install From 3f9fd9518c2b8ba07ed51deba280c69dea17f56f Mon Sep 17 00:00:00 2001 From: wallstop Date: Fri, 2 Oct 2026 04:45:22 +0000 Subject: [PATCH 3/3] Always deploy the documentation site on main The workflow guarded its deploy job with a GitHub Pages API check that warns instead of failing when Pages is off. Probing the API shows the guard can never fire: the repository already has a Pages site whose source is GitHub Actions, at https://wallstop.github.io/DataVisualizer/, with no build and no deployment in its history. The 404 is only the absence of a first publish. The guard is therefore dead code that hides the real state. The deploy job now runs on every push to main that touches documentation, which is what the roadmap asks for, and the first merge of the site publishes it. --- .github/workflows/docs-pages.yml | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/.github/workflows/docs-pages.yml b/.github/workflows/docs-pages.yml index 624a8bb..4742392 100644 --- a/.github/workflows/docs-pages.yml +++ b/.github/workflows/docs-pages.yml @@ -18,7 +18,8 @@ on: - ".github/workflows/docs-pages.yml" # Publication runs to completion instead of being cancelled by a later merge, -# so a half-written deploy never replaces a good site. +# so a half-written deploy never replaces a good site. Pull-request builds get +# their own group, so a merge never queues behind review feedback. concurrency: group: docs-pages-${{ github.ref }} cancel-in-progress: false @@ -31,8 +32,6 @@ jobs: name: Build the documentation site runs-on: ubuntu-latest timeout-minutes: 10 - outputs: - pages_enabled: ${{ steps.pages.outputs.enabled }} steps: - name: Checkout uses: actions/checkout@v7 @@ -53,27 +52,13 @@ jobs: with: path: site - # Pages is a one-time repository setting that this workflow cannot make. - # Report it instead of failing the run, so the validated site stays - # available as a run artifact until an owner enables Pages. - - name: Detect GitHub Pages - id: pages - if: github.event_name == 'push' - shell: bash - env: - GH_TOKEN: ${{ github.token }} - run: | - if gh api "repos/${{ github.repository }}/pages" > /dev/null 2>&1; then - echo "enabled=true" >> "$GITHUB_OUTPUT" - else - echo "enabled=false" >> "$GITHUB_OUTPUT" - echo "::warning::GitHub Pages is not enabled for ${{ github.repository }}. Set Settings > Pages > Source to GitHub Actions to publish; this run's artifact holds the validated site." - fi - + # The repository's Pages source is already GitHub Actions, so the first push + # to main that touches documentation publishes the site. No Unity, no + # credentials, and no generated content beyond the strict build. deploy: name: Publish to GitHub Pages + if: github.event_name == 'push' && github.ref == 'refs/heads/main' needs: build - if: needs.build.outputs.pages_enabled == 'true' runs-on: ubuntu-latest timeout-minutes: 10 permissions: