From 472ea1b743b4ae004701b689c1556cf2dcd4a3bc Mon Sep 17 00:00:00 2001 From: Oli Larkin Date: Sun, 17 May 2026 20:51:45 +0200 Subject: [PATCH] Add CLAUDE.md for TemplateProject Documents the responsive IGraphics layout pattern (two-branch mLayoutFunc keyed off NControls(), SetLayoutOnResize, corner resizer) and gives a checklist for adding new controls without breaking resize behavior. --- TemplateProject/CLAUDE.md | 48 +++++++++++++++++++++++++++++++++++++++ duplicate.py | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 TemplateProject/CLAUDE.md diff --git a/TemplateProject/CLAUDE.md b/TemplateProject/CLAUDE.md new file mode 100644 index 0000000..b033d59 --- /dev/null +++ b/TemplateProject/CLAUDE.md @@ -0,0 +1,48 @@ +# CLAUDE.md + +iPlug2 plugin project. This document describes choices in this project's structure that are not obvious from the iPlug2 framework docs. + +> This file is duplicated by `../duplicate.py` along with the rest of the project, and the project-name string-rewrite pass runs over it — so `TemplateProject.cpp` etc. resolve to the new project's filenames after duplication. + +## UI: responsive IGraphics layout + +The UI in `TemplateProject.cpp` is a **resizable / responsive IGraphics** example. The pattern is the important thing to preserve when extending it. + +Key pieces: + +- `config.h` enables host resize and sets bounds: `PLUG_HOST_RESIZE 1`, `PLUG_MIN_WIDTH/HEIGHT`, `PLUG_MAX_WIDTH/HEIGHT`. +- `OnHostRequestingSupportedViewConfiguration` returns `true` so hosts know any size in range is acceptable. +- `mLayoutFunc` runs on both first attach AND every resize: in the initial-attach branch it calls `pGraphics->SetLayoutOnResize(true)` and `AttachCornerResizer(...)`, which together cause it to re-run on every resize. + +### How `mLayoutFunc` is structured + +The function computes every IRECT once at the top from the current `pGraphics->GetBounds()`, then splits: + +1. **Resize branch (appears first in the code):** `if (pGraphics->NControls()) { ... return; }` — re-applies each tagged control's new rect via `SetTargetAndDrawRECTs(...)` (background uses `GetBackgroundControl()`), then returns early so the attach code below doesn't run again. +2. **Initial-attach branch (fall-through below the `if`):** one-time setup — `SetLayoutOnResize(true)`, `AttachCornerResizer`, `LoadFont`, `AttachPanelBackground`, then `AttachControl(...)` for each control with its tag. + +The early `return` in the resize branch is load-bearing — without it, controls would be re-attached on every resize. + +Because the IRECTs are computed once at the top, the same layout math feeds both branches. + +## Adding a new control — checklist + +To keep the responsive layout working, every new control needs all of these: + +1. Add a tag to `ECtrlTags` in the plugin header. +2. In `mLayoutFunc`, compute its `IRECT` at the top from `innerBounds` (or `bounds`) using IRECT helpers like `GetFromLeft`, `GetMidVPadded`, `GetCentredInside`, `GetGridCell`, etc. — never hard-code pixel coordinates that don't derive from the current bounds. +3. In the **resize branch** (inside `if (pGraphics->NControls())`, before the `return`), add `pGraphics->GetControlWithTag(kYourTag)->SetTargetAndDrawRECTs(yourRect);`. +4. In the **initial-attach branch** (the fall-through below the `if`), `AttachControl(new IVWhatever(rect, ...), kYourTag);`. + +Forgetting step 3 is the common mistake: the control will appear correctly at startup but stay frozen at its original rect when the window is resized. + +Controls that are not tagged (e.g. the panel background, corner resizer) are handled via their dedicated accessors or don't need repositioning. + +## Files of interest + +- `TemplateProject.cpp` / `.h` — plugin class, parameters (`EParams`), control tags (`ECtrlTags`), `ProcessBlock`, `mLayoutFunc`. +- `config.h` — plugin metadata, channel I/O, size constraints, format-specific IDs (`PLUG_UNIQUE_ID`, `PLUG_MFR_ID`, `AAX_TYPE_IDS`, etc.). +- `projects/` — per-format IDE projects (Xcode, VS, WAM makefiles). +- `resources/` — Info.plists, icons, fonts, images. Fonts referenced via `*_FN` macros in `config.h` (e.g. `ROBOTO_FN`). +- `CMakeLists.txt` — alternative CMake build (see `build-cmake` skill). +- `build-mac/`, `build-win/`, `installer/`, `manual/`, `scripts/` — build, packaging, and docs tooling. diff --git a/duplicate.py b/duplicate.py index c7a1291..a7e7a37 100755 --- a/duplicate.py +++ b/duplicate.py @@ -38,7 +38,7 @@ # binary files that we don't want to do find and replace inside FILTERED_FILE_EXTENSIONS = [".ico",".icns", ".pdf", ".png", ".zip", ".exe", ".wav", ".aif", ".data", ".wasm", "mkcert"] -FILTERED_FILE_NAMES = [".DS_Store", "CLAUDE.md", "duplicate.py"] +FILTERED_FILE_NAMES = [".DS_Store", "duplicate.py"] # files that we don't want to duplicate DONT_COPY = (".vs", "*.exe", "*.dmg", "*.pkg", "*.mpkg", "*.svn", "*.ncb", "*.suo", "*sdf", "ipch", "*.layout", "*.depend", ".DS_Store", "xcuserdata", "*.aps")