Skip to content
Agentmart
Submit a tool

sv-pit-art

SV2 彩蛋功能 —— 用音高线(PitchControlCurve)在钢琴窗里"画画"。利用 SV2 多条音高线可重叠且逐条渲染的特性,把 SVG 路径/文字轮廓/任意折线映射成时间×半音坐标,用一条曲线画一笔,组成图案。含已验证的 API 用法、坐标映射、笔画拆分、性能与限制、实测结论。⚠️ 开工前必读…

Skill by Akunda123

IndexedMIT★ 29
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/akunda123-sv-pit-art

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

SV2 彩蛋功能 —— 用音高线(PitchControlCurve)在钢琴窗里"画画"。利用 SV2 多条音高线可重叠且逐条渲染的特性,把 SVG 路径/文字轮廓/任意折线映射成时间×半音坐标,用一条曲线画一笔,组成图案。含已验证的 API 用法、坐标映射、笔画拆分、性能与限制、实测结论。⚠️ 开工前必读 §0:**画布必须锚定组内音符并夹进可见音高区间**(读 `getNavigation().getValueViewRange()`)、**点的 y 是相对 anchor pitch 的偏移量而非绝对音高**、**画完必须读回逐段核对**。触发:用音高线画图、pitch 画图、SV 彩蛋、在钢琴窗画图案/文字/logo、pitch art、把 SVG 画进 Synthesizer V、曲线重叠作图、图案画到天上/位置不对/顶到上限、曲线接缝断口等。

Use cases: design, backend

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Node.js package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/sv-pit-art

What's inside

Skill name
sv-pit-art
Description
SV2 彩蛋功能 —— 用音高线(PitchControlCurve)在钢琴窗里"画画"。利用 SV2 多条音高线可重叠且逐条渲染的特性,把 SVG 路径/文字轮廓/任意折线映射成时间×半音坐标,用一条曲线画一笔,组成图案。含已验证的 API 用法、坐标映射、笔画拆分、性能与限制、实测结论。⚠️ 开工前必读 §0:**画布必须锚定组内音符并夹进可见音高区间**(读 `getNavigation().getValueViewRange()`)、**点的 y 是相对 anchor pitch 的偏移量而非绝对音高**、**画完必须读回逐段核对**。触发:用音高线画图、pitch 画图、SV 彩蛋、在钢琴窗画图案/文字/logo、pitch art、把 SVG 画进 Synthesizer V、曲线重叠作图、图案画到天上/位置不对/顶到上限、曲线接缝断口等。
License
MIT
Instructions
491 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Agent Skills spec issues

  • files: referenced but missing: references/08-pit-drawing.md

Files (3)

  • SKILL.md
  • X交叉线-验证重叠渲染.md · examples/
  • 画汉字-竖线漂移参考实现.js · examples/

SKILL.md (first lines)

# sv-pit-art —— 用音高线画画(SV2 彩蛋)

> **一句话**:**SV2 的钢琴窗就是画布,`addPitchControl()` 就是画笔,多条音高线重叠就是图层。**
>
> ⚠️ **与 `sv-scripting/references/08-pit-drawing.md` 的关系(重要)**:
> 那篇讲**音乐性**的音高线,核心诉求是**避免相邻曲线重叠冲突**;
> **本技能的诉求正好相反 —— 刻意让曲线重叠,用重叠来叠图层**。
> **两套逻辑不可复用**:08 的"全局轮廓"合成是为了让重叠区数值一致;
> 画画则要求每条笔画是**互不相同的独立曲线**。

---

## 0. ⛔ 开工必做(2026-09-12 真机教训 —— 这三条不做,画出来就是废的)

> **背景(必须记住)**:第一次真机画图(五角星)**几何正确、音高数值也正确**,
> 但用户看到的评价是 **「画的太高了」→「看起来音高是对的,但是画在天上」**,且**三个内顶点处有可见断口/残段**。
> 两次翻车的根因**都不是画法**,而是**没读宿主状态**、**没核对结果**。以下三条已固化为硬规矩。

### 0.1 放置:**必须读"视图坐标" + 锚定音符**,禁止写死基音

> **🆕 基准三选一** ——
> 画图**先问用户要哪种**,用户不指定就用 `view`:
>
> | # | 模式 | 画布中心的绝对音高(`base`)取自 | 适用 |
> |---|---|---|---|
> | ① | `midi60` | **固定 MIDI 60(C4)为中心**(与音符、视图都无关) | 图案要"钉死不动、便于反复对齐/比对";音符也在 C4 附近时够用 |
> | ② | `view` | **用户当前屏幕可见范围**(读 `getNavigation().getValueViewRange()` 取中点) | **默认**;图案一定出现在眼前、不用滚屏(= 现在的行为) |
> | ③ | `range` | **用户指定范围**(如「第四小节起」「从选中段开始」) | 图案按段落落位,而不是"跟着当前屏幕走" |
>
> 三选一只改 `base`;下方"锚定到本组音符(`base = median(组内音高) − 画布高/2`)"仍适用于**要骑在音符上**的场景
> (可视作第 ④ 种语义,现阶段并入模式 ② 处理)。

钢琴窗的可见范围**可以直接读**(`CoordinateSystem`,见 `sv-scripting/api/CoordinateSystem.md`):

| 要读的 | 调用 | 单位 |
|---|---|---|
| **可见音高区间** | `SV.getMainEditor().getNavigation().getValueViewRange()` | **MIDI 半音**,`{低, 高}` |
| 可见时间区间 | `…getTimeViewRange()` | blick,`{起, 止}` |
| 纵向比例 | `…getValuePxPerUnit()` | px / 半音 |
| 值 ↔ 屏幕像素 | `…v2y(v)` / `…y2v(y)` · `t2x(t)` / `x2t(x)` | px |

**实测示例(2026-09-12 真机)**:可见音高 **44.54..64.21** · 组内音符中位数 **53** · **24 px/半音** · `v2y(62)=53px`(贴顶);
而当时**写死**的画布是 **62..76** ⇒ **绝大部分落在可见区之上** ⇒ 用户必须往上滚才看得见。
**这就是"画在天上"的量化原因 —— 不是观感问题,是可测量的错误。**

**放置规则(必须同时满足)**:
1. **垂直锚定到本组音符**:`base = median(组内音符音高) − 画布高 / 2`(图案"骑"在音符上);
2. **再夹进可见音高区间**:`base + 高 > 可见高` ⇒ 下压;`base < 可见低` ⇒ 上抬;
3. 收尾**把落点换算成像素回报**(`v2y`),明确写出"**完全可见**"还是"**需要滚动**"。

> ❌ **反面教材**:`BASE_PITCH = 62` 这种**写死**基音 —— 与你的工程、你的音符、你当前视图**全都无关**。
> 只在显式 `--base=` / `--anchor=fixed` 时才允许固定值,且仍必须回报可见性。

### 0.2 接缝:x 极值切分点在两条曲线里**必须同坐标**

一笔在 **x 极值顶点**处会被切成两条曲线(一条以它为终点、一条以它为起点)。
若两条曲线给**同一个顶点**算出**不同的 x**(典型:各自套用竖线水平漂移),接缝就**错开** ⇒ 视觉上**断口 + 小残段**。

- 漂移**只作用于"非共享"的内部点**;**末点(=共享顶点)最多挪 `+1` blick**(既保严格递增,又能与对面接上)。
- 兜底:相邻两条曲线可在接缝处**各向外多写半步重叠**(重叠无害,见 §1)。

### 0.3 完成定义:**必须读回核对**,不许只看脚本自报

> 教训:脚本自报"曲线 N 条 / 点 M 个"**完全可以同时是"画在天上 + 有断口"**。
> 2026-09-12 我就是只看了自报,**把废图当成成功交付**。

**画完必须做三件核对**(现成实现在 `sv/lua/draw-pit-art.cjs`,默认开启,`--no-verify` 才关):
1. **读回曲线**(`getPitchControl(i).getPoints()`),把点还原成**绝对坐标**;
2. **与"预期笔画逐段"比对** ⇒ 报告**缺失段数**(`缺 0 段` 才算完整);容差必须覆盖漂移(x ≈ `2e6` blick);
3. **可见性核对**:实际音高范围 vs `getValueViewRange()` ⇒ "完全可见" 还是 "要滚动"。

#### 0.3.1 读回的**确切形状**(2026-09-20 真机复核,IX 1.0.1 · 桥 0.3.18)

```lua
local c   = group:getPitchControl(i)   -- 1 起
local pts = c:getPoints()              -- ⚠️ 返回**普通数组**:pts[k] = { 位置, 半音 } 两个 number
local pos, pitch = pts[k][1], pts[k][2]   -- ✅ 就这样取
```
- **不是** `pts[k]:getPosition()` / `:getPitch()`(那套方法在 **curve 对象**上:`c:getPosition()` / `c:getPitch()` = 锚点位置 / 锚点音高),
  点在 Lua 里**就是两个 number 的数组**(`pairs` 出来是 `1=number, 2=number`)。
- 桥自己的 `PIT.levelAt()` 也是这么读的(`pts[i][1]` / `pts[i][2]`);离线回归里也钉了这条。
- 判断"这个 control 是 curve 还是 point"仍然用 **`has(pc,"getPoints")`**(对象上没有 `type` 字段)。

#### 0.3.2 ⚠️ 和弦(同 onset)上写曲线:**0.3.18 前会丢**

`write_pit` 的幂等替换原本按 **"窗口起点一致"** 认"这是我这条曲线的旧版"。而**和弦里多个音 onset 相同 ⇒ 窗口起点相同**
⇒ 给第 2 个音写时会把第 1 个音的曲线**当旧版删掉** ⇒ **只剩最后一条**,而返回里只报 `removedCurves`、**不报丢音**。
- **0.3.18 起已修**:写入时给曲线打 `scriptData.akdagentNoteIndex`(该音符的 0 起组内下标),重写**只删自己那条**。
- **仍在旧版桥上**遇到"和弦写曲线只剩一条":逐个音写 + 每次写完**读回条数**核对;或先 `clear="all"` 再**只写一个音**。
- **历史数据无损**:旧版写的曲线**没有标记** ⇒ 新版只在"该音符 onset 在组内唯一"时才按锚点删它(有同伴时不动,**宁留不误删**);
  想彻底重来用 `clear="all"`。

### 0.4 桥接口的坑(2026-09-13 已**全部查明**,含我自己两次误判的更正)

| 坑 | 真相 | 正确做法 |
|---|---|---|
| **`run_script` 的 `scope` 注入** | ✅ **一直是好的**。语义是:**`scope` 的"内容"被注入成一个个独立全局变量**(实现:`for k,v in pairs(args.scope) do env[k]=v end`)。<br>❌ 我此前写成"真机 `type(scope)=="nil"`、注入不生效" —— **那是我把 `scope` 当命名空间读了 `scope.x`**;实读 `_ENV` 得到 `SV,SVH,readonly,strokes,x` 即证 | 脚本里**直接写 `x` / `strokes`**(顶层键名),**不要写 `scope.x`**(永远 nil)。<br>本技能的 `draw-pit-art.cjs` 采用**内联数据**(历史原因,也行且更省事),但**知道正确语义**才能不误诊 |
| **`run_script` 返回值有包封** | `{result:<Lua值>, resultType}` | 客户端 `callOk()` 已剥过响应外层 ⇒ **只剥一层**;多剥一层得到 `undefined`(我因此误判成"两个修订抢答",纯属自伤) |
| **两个宿主共用 `-sv` 通道** | SV1/SV2/OPSV Flat 共用(协议如此) | 一次只开一个桥;写入脚本内置**组名 + 音符数**预检,不符即中止 |
| ~~"常驻桥是 18:24 之前的旧循环"~~ | ❌ **已作废**:在 **SV2 里重跑桥后**仍复现 ⇒ 再查:部署文件与仓库 **MD5 相同**、含注入代码、`selftest` 的 25 个返回键**逐个吻合**、嵌套数组参数(`create_harmony_group` 的 `notes`)**正常工作** ⇒ **常驻代码就是这份文件**,问题从来不在桥上 | 结论:**别把"我没验证过"当"对方有问题"** —— 先读 `_ENV`、先做最小对照 |

### 0.5 现成工具(别再手搓)

```bash
node sv/lua/draw-pit-art.cjs sv pelican --at=11.5              # 图形:star|heart|check|pelican
node sv/lua/draw-pit-art.cjs sv star --base=48 --height=16     # 显式覆盖基音/画布高
node sv/lua/draw-pit-art.cjs sv clear --force                  # 清当前活跃组全部曲线(需 --force)
node sv/lua/draw-pit-art.cjs sv remove                         # 删自建「AKDAgent画板」组
node sv/lua/probe-view.cjs sv                                  # 读视图坐标(可见音高/时间、px 换算)
node sv/lua/probe-groups.cjs sv                                # 列组引用(名字/isMain/音符数/曲线数)
```

默认**画在"你现在活跃的那个组"**(`--new` 才另建独立画板组);数据内联、写前预检、**写后自动读回核对**。

### 0.6 ⛔⛔ **坐标语义(本次翻车的真正根因,比前面四条更致命)**

> **2026-09-12 用户实测抓出**:导出的曲线是 `{"pitch": 62, "points": [0, 69.76, …]}`,
> 而**实际音高变成了 ~132** —— 因为 **`实际音高 = 曲线 anchor pitch + 点的 y`**。

From Akunda123/SVIXAGENT, MIT.

More from Akunda123/SVIXAGENT

Signals

Stars
29
Forks
5
Open issues
4
Last commit (this folder)
Sep 25, 2026 (1 month ago)
Last release
Oct 9, 2026 (21 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from Akunda123

Cite this page

sv-pit-art skill. Agent Mart. https://agentmart.dev/skills/akunda123-sv-pit-art (last updated 2026-10-24)