diff --git a/skills/tilemap-palette-gridpaintingstate/SKILL.md b/skills/tilemap-palette-gridpaintingstate/SKILL.md new file mode 100644 index 0000000..e6bc95b --- /dev/null +++ b/skills/tilemap-palette-gridpaintingstate/SKILL.md @@ -0,0 +1,82 @@ +--- +name: tilemap-palette-gridpaintingstate +description: Manages Tile Palette painting states. Use when working with Tile Palette painting targets, brushes, palettes, or responding to painting state changes (active Grid Brush, active Target, etc.). +required_packages: + com.unity.2d.tilemap: ">=1.0.0" +modes: [agent] +--- + +# Tile Palette Grid Painting State + +## Step 0: Confirm you can run C# in the Editor + +`GridPaintingState` and `GridPaintPaletteWindow` are Editor-only types that describe the +*live* state of the Tile Palette window. Nothing on disk holds that state, so this skill +needs an Editor it can execute C# in. + +**The `unity-cli` skill owns getting you there** — installing the CLI, confirming a connected +Editor, adding the project's `com.unity.pipeline` package, telling a genuinely absent Editor +apart from one stuck in Safe Mode, and discovering the Editor's command catalog. Follow it +first; don't re-derive any of it here. + +Two things it can't know for you: + +- **You need `eval` in particular**, not just a reachable Editor. Confirm it appears in the + catalog. Its presence depends on the Pipeline package version, not on the CLI — if it's + missing, say so and stop. +- **These types live in `UnityEditor.Tilemaps` and some are internal.** `eval` does reach + them (measured), so use them directly — only fall back to reflection if a compile error + actually reports a visibility problem. + +Run C# through the connected Editor with the `eval` command. Discover its parameter shape +from `unity command --format json` rather than assuming one — the inline form is +`unity command eval --code ''`, and some Pipeline versions also register +`eval_file` for running a snippet from a file. **Check the catalog before reaching for +`eval_file`; it is frequently absent.** `unity command` defaults to a 30 second timeout. + +### Passing C# to `eval` + +`eval` compiles a **statement block, not a file**. Two consequences, both of which cause a +compile error rather than a warning: + +- **No `using` directives.** The compiler reads `using UnityEngine;` as a resource-disposal + statement and rejects it (`CS0210`). +- **Types must be fully qualified.** A bare `AssetDatabase` or `Volume` does not resolve + (`CS0246` / `CS0103`), and a bare `Object` is ambiguous with `object` (`CS0104`). + +Where a snippet below is written as a file — with usings, for readability, or because it is +meant to be saved into the project — qualify the types before passing it to `eval`. + +## Workflow + +### Step 1: Pre-Flight Check +Ensure that the Tile Palette Window is open using: +```csharp +UnityEditor.EditorWindow.GetWindow(); +``` + +Do not use `MenuItem` patterns to open the Tile Palette Window. + +### Step 2: Generate and Execute Script +Create a script using the core pattern, run it through the Editor as described in Step 0, +and report the results. + +### Step 3: Validate Results +Check the Unity console for errors and verify changes in the Project window. + +### Step 4: Iterate (Max 3 Times) +If errors occur, fix and re-execute. After 3 attempts, **WAIT** for user guidance. + +## Reference + +**API Reference**: [references/references.md](references/references.md) + +## Important Notes + +- Always include a pre-flight check in generated scripts. +- Do NOT use `AssetDatabase` patterns for retrieving available assets such as palettes and brushes. Use the existing methods in GridPaintingState to retrieve them. +- Generate standalone snippets only — no `MenuItem`, no `AssetPostprocessor`. Return the + values you need to read; logs land in the Editor console. +- **Enum assignments:** Always use enum values and cast to numeric types. Never use raw numbers. + - ✅ Correct: `(int)SpriteAlignment.Center` + - ❌ Wrong: `1` (magic number) \ No newline at end of file diff --git a/skills/tilemap-palette-gridpaintingstate/references/references.md b/skills/tilemap-palette-gridpaintingstate/references/references.md new file mode 100644 index 0000000..ad6c80f --- /dev/null +++ b/skills/tilemap-palette-gridpaintingstate/references/references.md @@ -0,0 +1,189 @@ +# GridPaintingState Public API + +`GridPaintingState` is a `ScriptableSingleton` in `UnityEditor.Tilemaps` that controls the state of objects for painting with a Tile Palette. + +**Source:** `Packages/com.unity.2d.tilemap/Editor/GridPaintingState.cs` + +## Events + +All events are static and can be subscribed to for monitoring painting state changes. + +| Event | Type | Description | +|-------|------|-------------| +| `scenePaintTargetChanged` | `Action` | Fired when the active paint target changes | +| `scenePaintTargetEdited` | `Action` | Fired when the active paint target is edited | +| `brushChanged` | `Action` | Fired when the active brush changes | +| `brushPickChanged` | `Action` | Fired when the brush's selection changes | +| `brushPickStoreChanged` | `Action` | Fired when the brush pick store changes | +| `brushToolsChanged` | `Action` | Fired when brush tools change | +| `beforePaletteChanged` | `Action` | Fired before the active palette changes | +| `paletteChanged` | `Action` | Fired when the active palette changes | +| `palettesChanged` | `Action` | Fired when the list of palettes changes | +| `validTargetsChanged` | `Action` | Fired when valid paint targets change | +| `editModeChanged` | `Action` | Fired when edit mode state changes | + +**Example - Subscribing to events:** +```csharp +void OnEnable() +{ + GridPaintingState.scenePaintTargetChanged += OnTargetChanged; + GridPaintingState.brushChanged += OnBrushChanged; +} + +void OnDisable() +{ + GridPaintingState.scenePaintTargetChanged -= OnTargetChanged; + GridPaintingState.brushChanged -= OnBrushChanged; +} + +void OnTargetChanged(GameObject newTarget) +{ + Debug.Log($"Paint target changed to: {newTarget?.name}"); +} + +void OnBrushChanged(GridBrushBase newBrush) +{ + Debug.Log($"Brush changed to: {newBrush?.name}"); +} +``` + +## Properties + +### Paint Target + +| Property | Type | Access | Description | +|----------|------|--------|-------------| +| `scenePaintTarget` | `GameObject` | get/set | The currently active painting target in the scene | +| `validTargets` | `GameObject[]` | get | All valid GameObjects that can be set as paint targets | + +### Brush + +| Property | Type | Access | Description | +|----------|------|--------|-------------| +| `gridBrush` | `GridBrushBase` | get/set | The currently active brush for painting | +| `brushes` | `IList` | get | All available brushes | +| `brushPickStore` | `GridBrushPickStore` | get | Store of brush selection data for the current brush | +| `activeBrushEditor` | `GridBrushEditorBase` | get | The editor for the active brush | + +### Palette + +| Property | Type | Access | Description | +|----------|------|--------|-------------| +| `palette` | `GameObject` | get/set | The currently active palette GameObject | +| `palettes` | `IList` | get | All available palette GameObjects | +| `isPaletteEditable` | `bool` | get | Whether the active palette can be edited (false for model prefabs) | + +### State + +| Property | Type | Access | Description | +|----------|------|--------|-------------| +| `isEditing` | `bool` | get | Whether GridPaintingState is active for editing | +| `lastSceneViewMousePosition` | `Vector2` | get | Last mouse position on SceneView when painting is active | +| `lastSceneViewGridPosition` | `Vector3Int` | get | Last grid position on SceneView when painting is active | + +## Methods + +### IsPartOfActivePalette + +```csharp +public static bool IsPartOfActivePalette(GameObject target) +``` + +Checks if a GameObject is part of the active palette. + +**Parameters:** +- `target`: The GameObject to check + +**Returns:** `true` if the target is part of the active palette, `false` otherwise + +**Example:** +```csharp +if (UnityEditor.Tilemaps.GridPaintingState.IsPartOfActivePalette(selectedObject)) +{ + Debug.Log("Selected object is part of the active palette"); +} +``` + +### SetPickOnActiveGridBrush + +```csharp +public static void SetPickOnActiveGridBrush(bool user, int index) +``` + +Retrieves a stored selection from the current `GridBrushPickStore` and copies it into the active `GridBrush`. + +**Parameters:** +- `user`: If `true`, uses user-saved selections; if `false`, uses last-saved selections +- `index`: Index of the selection in the store to apply + +**Example:** +```csharp +// Apply the first user-saved brush selection +UnityEditor.Tilemaps.GridPaintingState.SetPickOnActiveGridBrush(user: true, index: 0); + +// Apply the second automatically-saved brush selection +UnityEditor.Tilemaps.GridPaintingState.SetPickOnActiveGridBrush(user: false, index: 1); +``` + +## Common Usage Patterns + +### Setting up a custom paint target + +```csharp +// Get available targets +var targets = UnityEditor.Tilemaps.GridPaintingState.validTargets; +if (targets != null && targets.Length > 0) +{ + // Set the first valid target + UnityEditor.Tilemaps.GridPaintingState.scenePaintTarget = targets[0]; +} +``` + +### Changing the active brush + +```csharp +// Get available brushes +var availableBrushes = UnityEditor.Tilemaps.GridPaintingState.brushes; +foreach (var brush in availableBrushes) +{ + if (brush is MyCustomBrush) + { + UnityEditor.Tilemaps.GridPaintingState.gridBrush = brush; + break; + } +} +``` + +### Changing the active palette + +```csharp +// Get available palettes. Fully qualified: this runs through `eval`, which takes no usings. +var availablePalettes = UnityEditor.Tilemaps.GridPaintingState.palettes; +if (availablePalettes.Count > 0) +{ + // Setting an invalid palette throws ArgumentException + UnityEditor.Tilemaps.GridPaintingState.palette = availablePalettes[0]; +} +``` + +### Monitoring edit state + +```csharp +void Update() +{ + if (GridPaintingState.isEditing) + { + Vector3Int gridPos = GridPaintingState.lastSceneViewGridPosition; + // Use grid position for custom visualization or logic + } +} +``` + +## Related Types + +- `GridBrushBase` - Base class for all tile brushes +- `GridBrush` - Default tile brush implementation +- `GridBrushEditorBase` - Base class for brush editors +- `GridBrushPickStore` - Stores brush selection history +- `GridPalettes` - Manages available palettes (`GridPalettes.palettes`) +- `GridPaletteBrushes` - Manages available brushes (`GridPaletteBrushes.brushes`) \ No newline at end of file