Files
Beyond-KLE/provisional/decisions.md
T
ewdernaandClaude Opus 5.5 3749f267b5 provisional: PHY Editorで異形キーを描き・編集し・追加する方法を仮に決める(T-32)
- 2つの矩形の和の外形を1つの輪郭で描き、選択枠も同じ外形にする
- プロパティ欄は「異形キー」のチェックで2つ目の矩形の欄(X2・Y2・Width2・Height2)を出し入れする
- 1Uの「キーを足す」は残し、隣に「異形キーを足す」selectを置く。候補はdomainのプリセット表から出し、今はISO Enterだけ
- 追加位置は1Uと同じ規則で、外接矩形の左上を合わせる

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xmqw9x7EoryY6zf116i3yM
2026-10-26 08:54:46 +09:00

28 KiB

仮決定

各項目: 仮決定 / 理由(短く) / 覆すときに影響する箇所。 「モック対象外」は、未決のまま進めてもモックが作れるという意味で、問いが解決したことを意味しない。

A. モックの範囲と技術

T-1 モックの目的

配置を編集しても割り当てがずれないこと、全バリアントを保持したまま選択した構成を出力・往復できることを、動くもので確かめる。 完成品のツールにはしない。

T-2 対象範囲

ブラウザで動く1つのアプリ。1画面でタブを切り替える。

ツール 作る範囲
PHY Editor KLE JSONの新規取り込み、キー・部品の追加、移動・回転・サイズ編集、クラスター化・解除・reparent・数値入力のreframe、バリアントの編集・表示切替、KLE JSON出力
Key Indexer 全バリアントのキーの一覧、order への登録・除外・並べ替え、選択構成での出力番号のプレビュー
Wiring Editor MCUの提供者と接点キーの端子のフォーム編集、配線の表示、未配線・衝突の表示、LEDチェーンの順序編集
Keymap Designer 基本キーコードと名前によるレイヤー動作の割り当て、レイヤーの追加・改名・並べ替え、未割り当ての表示
Generator(プレビュー) 選択構成の平坦な配置、IDXの並び、row/col、MAPの配列、対応表を mock-target.json に出力。QMKにそのまま渡せる生成物とは扱わない
共通 プロジェクトの保存・読み込み、Undo/Redo、検証結果の一覧

対象外: 実機との通信(VIA/WebHID)、QMKのビルド・書き込み、HST、アナログ入力、マルチプレクサ、光学スイッチ、エンコーダ等への割り当て、マクロ・タップダンス等の動作定義。

後段(任意): 疑似デバイスとの往復(書き込み → 外部での変更を模擬 → 読み出し → 差分確認 → MAPへ取り込み)。着手する場合は T-24 に従う。

T-3 作る順番

  1. 回転したクラスター内のキーのドラッグと、保存・再読み込みの往復(描画方式の確認を兼ねる)
  2. IDX・MAPとの連携
  3. ELCと出力の対応表
  4. (任意)疑似デバイスとの往復

T-4 検証に使うデータ

samples/kle/macropad-4x4.json、samples/kle/cr0wn60.json(幾何のみ)、手作りの回転・入れ子バリアントのfixture。 実在の配線とVIAの適合は検証の対象にしない。

T-5 技術選定 (implementation-plan P-2)

項目 仮決定
言語 TypeScript(strict)
UI Vue 3(Composition API) + Vite。Nuxtは使わない(SSR・ルーティングが不要)
描画 素のSVG。PHYの階層を入れ子の <g> に対応させ、ドラッグは親要素の getScreenCTM() の逆行列でローカル座標へ戻す
状態管理 文書全体を1つの shallowRef に置き、純粋な更新関数(コマンド)で置き換える。UIの状態は別に持つ。Piniaは入れない
Schema検証 Ajv(draft 2020-12)。参照の整合性などの意味的な検証は別の関数にする
テスト Vitest(変換・参照整合性)、Playwright(SVG上の操作・保存の往復)
パッケージ管理 pnpm。依存の版はlockfileで固定

理由: 描画の変換がPHYの Translate · Rotate と同じ定義で、座標の逆変換をブラウザに任せられる。Vueは既存の経験を使える。

T-6 リポジトリ構成 (implementation-plan P-3)

このリポジトリの mock/ に単一のパッケージとして置く。 中は domain/(層のモデル・変換。Vue・DOMを参照しない)、io/(KLE・プロジェクトファイル)、ui/ に分ける。 モノレポ化とパッケージの分割はモックの後に決める。

T-7 KLE JSONの読み書き (implementation-plan P-1)

kle-serial2 を使わず、読み書きともに自作する。ijprest/keyboard-layout-editor・kle-serial・過去のkbd-editorのコードも取り込まない。 KLE本家の挙動の確認は、既存の検証ハーネスで本家の serial.js を動かして比べる(コードは写さない)。 理由: 出自の確認を待たずに進められ、後からライブラリへ差し替えられる。

T-29 PHY Editorの作り直し

ui/phy/ だけを作り直し、domain/・io/ とそのテストは流用する。作り直したものもモックとして扱う。 入力は phy-editor-feedback.md と phy-editor-keybindings.md。 理由: 所感はすべて画面の操作と表示に関するもので、データモデル側に作り直す理由がない。

T-30 作り直し1回目の所感への対応

T-29 のコードを作り直さず、phy-editor-feedback.md「作り直し1回目(T-29)を触った所感」を下の単位で順に直す。 1単位1コミットとし、各単位で既存の Vitest・Playwright を通してから次へ進む。 理由: 所感はどれも局所的な修正か機能の追加で、T-29 の構成(composable・純粋モジュールの分離)のまま入る。

順 単位 内容 主な箇所
1 選択の描画層 選択枠を太くし、NodeSvg の再帰から外して最前面の層に描く。以後のオーバーレイ(5・8)もこの層に載せる NodeSvg.vue、PhyEditor.vue
2 パネルの幅 階層パネルを閉じたら、キャンバスが空いた幅を埋める PhyEditor.vue の grid-template-columns
3 バリアント ポップオーバーの印を「既定」と分かる見た目にする。バッジには名前を書かず、表示中のバリアント名はツールチップで示す。クラスター内のキーから作ったバリアントグループは、そのクラスターの中に作る NodeSvg.vue、usePhyCommands.ts
4 ドラッグ中の自動スクロール キーを画面の端へ寄せると、キャンバスがスクロールする usePhyCanvasPointer.ts、usePhyCanvasView.ts
5 クラスターの原点 選択中のクラスターにだけ、原点に丸を出す 1の層
6 キー追加の位置 選択中のキー(複数なら最後に選んだキー)の行の右端に追加する。何も選んでいなければ、同じコンテナの全キーの下に新しい行を作り、その左端に置く。クラスターを選んでいればその中に、バリアントグループを選んでいれば表示中のバリアントの中に、同じように新しい行を作る。行の判定は domain/ に純粋関数として実装してテストし、のちにIDX Editorでも使う。規則は idx-editor-feedback.md「行と列の判定」 domain/rows.ts、usePhyCommands.ts
7a 長押しの切り出し 長押しの処理を composable に切り出す。挙動は変えない usePhyCanvasPointer.ts
7b 長押しの2方式 ループ方式(間隔を延ばし、円形インジケータと選択先のリストを付ける)と、長押しでリストを出して選ぶ方式を入れ、ツールバーで切り替えて比べる。間隔は、押してから600msで始まり1000msごとに進む。リスト方式は、押した位置から少し離してリストを出し、ポインタがリストに入ったら巡回を止め、離したときに指している行で確定する。リストに入らずに離せば、そのときの巡回先で確定する。ループ方式は長押しのあと動かすと選んだ先をドラッグし、リスト方式はドラッグしない 7aの composable
8 スイッチ・スタビライザーの表示 既定は非表示にし、トグルで色違いの十字を出す。プロパティ欄に switchOffset の入力欄と、スタビ位置の候補の選択欄を置く(下の「単位8のスタビ候補」) 1の層、PhyProperties.vue

順番の理由: 1で作る層を5と8が使う。2〜5は小さく独立しているので先に片付ける。 7は最も大きく、試して比べる部分なので、挙動を変えない切り出しを先に入れる。

単位8のスタビ候補

スタビ位置はキーのサイズで候補を引き、キーごとに候補を複数選べる。何も選ばなくてもよい。 選んだ候補はプロジェクトファイルの ui にキーIDごとに持ち、PHYには入れない(いずれPHYへ移す)。 どのサイズも、何も選ばない状態から始める。 候補を選んでも switchOffset は変えない。switchOffset は手で入れる。

候補は、キーの (w,h) 矩形の中心から±の位置に置く2点で表す(1U = 19.05mm)。縦長のキーは長辺の向きに置く。 Cherry MX系の値を使う。出典は Deskthority wiki「Space bar dimensions」と、プレート・基板の生成ツール(kad、keyswitch-kicad-library)。

幅 候補
2〜2.75U ±11.938mm
3U ±1U
4U ±1.5U
4.5U ±34.671mm
5.5U ±2.25U
6U ±2.5U(軸がずれた型。実物は switchOffset.x = +0.5U)、±2U
6.25U ±50mm(軸がずれた型もこの位置。実物は switchOffset.x = +0.625U)、±40mm、±42.5mm
6.5U ±2.75U
7U ±3U
8U・9U・9.75U・10U ±3.5U

6Uの±2.5Uは、軸が中央の型(Topre等)と軸がずれた型で同じ位置になるため、1つの候補にまとめる。 ISO Enter・BAE等の異形キー(w2・h2・x2・y2 のいずれかを持つキー)には、候補を出す仕組みだけを入れ、候補は置かない。 上にない幅のキーは候補なし。

覆すときに影響する箇所: mock/src/ui/phy/、6の行判定の関数とそのテスト。

T-31 IDX Editorの作り直し

ui/panels/IdxPanel.vue を捨て、ui/idx/ に一から作る。入力は idx-editor-feedback.md「方向が合意できたもの」。 order の操作(挿入・入れ替え・連番の並べ直し・走査・取り込みの照合)は domain/ に純粋関数として置いてテストし、行と列の判定は domain/rows.ts を変えずに使う。 ui/phy/viewport.ts の純粋関数は使ってよいが、ui/phy/ は変えない。 理由: 所感は画面の操作の作り直しで、IdxFile の形と domain/idx.ts は変える理由がない。

所感が定めていない部分は、下のとおり仮に決める。

  • 表示する構成: エディタ内の状態として持ち、開いたときは output.variantSelection(欠けたグループは既定)から始める。 切り替えても output は書き換えず、Undoにも積まない。
  • 画面: 左にバリアントのツリー、中央にキャンバス、右に並べ替え(プリセット・取り込み・未登録の登録)と選択中のキーの情報。 キーには選んだ構成での出力番号を出す。未登録のキーは番号を出さず、未登録と分かる見た目にする。並びのリストは置かない。
  • 選択: クリックで1つ、Shift/Ctrl+クリックで追加・解除、何もない場所からのドラッグで範囲選択、Escと何もない場所のクリックで解除。
  • ドロップの判定: ドロップ先のキーの幅を4等分し、左端の1/4は「そのキーの前へ挿入」、右端の1/4は「後へ挿入」、中央は入れ替え。 回転したキーはキーの向きで測る。ドラッグ中は挿入位置の線か入れ替えの印を出す。何もない場所へのドロップは取り消し。 ドラッグで動かすのは押したキー1つだけ。未登録のキーをドロップすると、その位置に登録する(入れ替えはしない)。
  • 隠れたキーのくっつき先: 前後で最も近い表示中のキーを候補にし、VariantGroupの祖先を共有するほうへ付ける。 両方と共有する、どちらとも共有しない場合は手前に付ける。手前がなければ後ろに付ける。 表示中のキーに挟まれた隠れたキーの並びは、後ろに付くキーが出たら、そこから先をすべて後ろに付ける(順序を保つため)。
  • 連番の並べ直し(プリセット・取り込みの共通操作): 渡された列のキーを、列の先頭キーがあった位置から連続して置く。 列に入らない表示中のキーは、互いの順序を保つ。列に未登録のキーがあれば登録する。 隠れたキーは、くっついている表示中のキーと一緒に動く(ドラッグでの移動と異なる)。
  • 左右の半身: 判定した列のうち、隣り合う列の隙間が最も大きい所で分ける。最大の隙間が0.5U未満なら、範囲の中央のx座標で分ける。 回転したキーは、外接矩形で行と列を判定する。
  • 向き: 行優先・列優先は全体に1つ(通常 / 左右逆)。半身ごと・行ごとに左右交互は、左手側と右手側に別々に指定する。 マトリクス順は向きを持たず、row→colの順に並べ、ELCで位置が決まらないキーは今の順序のまま末尾に置く。
  • プレビュー: 行で走査する方式は行を線で結んで色分けし、列を選んで↑/↓で行の割り当てをずらす。 列優先は列を結び、行を選んで←/→でずらす。仮の出力番号と半身の境界も出す。Escで取り消し、適用で1回のUndo単位にする。
  • 取り込み(QMK keyboard.json の layout[]、VIA定義の layouts.keymap、KLE JSON): 各キーの位置・回転を、表示中のキーの位置・回転と照合する(1対1、許容差0.01U)。 照合できたキーの列を連番の並べ直しに渡し、照合できなかった数を表示する。QMKで複数のレイアウトがあれば選ばせる。

覆すときに影響する箇所: mock/src/ui/idx/、mock/src/domain/ の IDX の並べ替え関数とそのテスト、mock/e2e/idx.spec.ts。

T-32 PHY Editorでの異形キー

PHY Editorで、2つ目の矩形(x2・y2・w2・h2)を持つキーを描き、編集し、追加できるようにする。 理由: データモデル・KLEの読み書きは2つ目の矩形を扱えるのに、キャンバスは主矩形しか描かず、編集手段もなかった。

  • 描画: 2つの矩形の和の外形を1つの輪郭で描く。選択枠も同じ外形にする。当たり判定と範囲選択は両方の矩形で取る。 2つ目の矩形を持たないキーは今までどおり角丸の矩形で描く。
  • 編集: プロパティ欄に「異形キー」のチェックを置き、オンのときだけ2つ目の矩形の欄(X2・Y2・Width2・Height2)を出す。 オンにしたときの初期値はKLEの既定(0, 0, w, h)。オフにすると4つとも消す。Width・Heightを変えても2つ目の矩形は変えない。
  • 追加: ツールバーの「キーを足す」(1U)はそのまま残し、隣に「異形キーを足す」のselectを置く。 候補は domain/ のプリセット表から出し、今はISO Enter(KLEのプリセットと同じ w1.25 h2、x2 -0.25 w2 1.5 h2 1)だけを置く。 プリセットを表に足せば、selectの項目も増える。ショートカットのキー追加は1Uのまま。
  • 追加位置: 1Uキーと同じ規則(T-30 単位6)で求めた位置に、キーの外接矩形の左上を合わせる。ISO Enterは原点が外接矩形の0.25U右になる。
  • スイッチ位置・スタビ: 変えない。スイッチは主矩形の中心(switchOffset 0)、スタビ候補は置かない(T-30 単位8)。

覆すときに影響する箇所: mock/src/domain/keyShape.ts とそのテスト、mock/src/ui/phy/ の描画・選択枠・プロパティ欄・ツールバー、mock/e2e/phy.spec.ts。

B. 明示的な未決事項

未確認事項

出典 仮決定
全体 P-1 アナログ値の解釈の所属 モック対象外。ELCにも仮置きしない
MAP P-1 動作定義とキーごとの設定の保存形式 モック対象外。MAPは現行Schemaの layers[].keymap[] だけを扱う。モック後の叩き台として: マクロ・Staticの動作は map.definitions[](name で識別、kind と種別ごとの内容)に置き、キーごとの設定はPHYのキーIDに付ける(map.keySettings[keyId])
MAP P-2 VIAのコマンドは0.34.4のソースどおり[推測] 推測に依存しない。実機通信を作らない。疑似デバイスはアプリ側の操作を模擬するだけで、VIAの動作とは扱わない
MAP P-3 プロジェクトと実機の対応・状態管理 本線のモックでは対象外。疑似デバイスの段階で T-24 を使う
HST P-1 使う側が逆引きを判断できる[推測] 推測に依存しない。逆引き・Key Overrideの候補生成を作らない
HST P-2 対象ホストを複数持つか モックではホストを持たない。MAPはQMKの表記のまま表示し、よく使うコードだけUS配列の文字を添える(T-23)
implementation-plan P-1〜P-3 T-7、T-5、T-6

backlog

項目 仮決定
PHY-P-2 KLE取り込みの照合基準 新規PHYとしての取り込みだけ。照合・更新は作らない
PHY-P-6 見た目情報の所属層 現行Schemaどおり、キー単位とファイル単位の kleCompatibility に退避し書き戻す。編集UIは作らない。ラベルと a の往復はT-20
PHY-P-8 ラベルのMAP適用 自動適用しない。ラベルは表示だけ
PHY-P-12 部品の表裏 描き分けない。予約グループ名は @led @encoder @screw @oled の4つを仮に置き、形だけ変えて描く。それ以外は共通のマーカーと名前
PHY-P-13 reframeの操作系 通常の移動・回転とは別の「座標枠の変更」コマンドにし、原点と基準角度を数値で入れる。ハンドル操作は作らない
PHY-P-14 原点の吸着 作らない
ELC-P-1 光学スイッチ 対象外。接点に読み替えない
ELC-P-2 複数マルチプレクサ 対象外。analog-muxの提供者はデータとして読み書きだけする
ELC-P-3 走査設定 Generatorのプレビューは単純な接点マトリクスに限る(T-19)。走査方向は出力設定で明示させ、配線から推定しない
IDX-P-1 既存コミュニティレイアウトとの互換 保証しない。独自の order を編集・保存するだけ
MAP-P-4 ON/OFF以外の入力 対象外。エンコーダはPHYの部品ノードとして置くまで
MAP-P-5 表示するOS配列 T-23
MAP-P-6 developブランチ・Community Modules 対象外(QMKへの実出力をしない)
MAP-P-7 再ビルド時の調整の保全 対象外
MAP-P-8 QMK以外のキーコード表記 QMK表記だけを保存する
MAP-P-9 Cコードの生成 対象外

ELC本文にある「LEDのドライバIC方式」「デジタル側の提供者の種別ごとの記述」も対象外とする。

C. 暗黙の未決事項

仕様だけでは実装が一意にならない箇所。

T-10 プロジェクトファイル

1ファイル *.bkle.json に束ねる。

type ProjectFile = {
    format: "beyond-kle-mock-project",
    version: "0.1.0",
    projectId: string,
    phy: PhyFile, elc: ElcFile, idx: IdxFile, map: MapFile, // 各層はSchemaどおりのファイル形
    output: { variantSelection: Record<string, string>, matrix?: MatrixOutputSettings },
    ui?: unknown // 表示中のバリアント、ズーム等。仕様の層には入れない
}

各層を単独のJSONとして書き出す・読み込む機能も持つ。モック独自の拡張は各層の中に入れず、ProjectFile の直下に置く。

T-11 ID

新規ノードは種別の接頭辞 + ランダム文字列(key-, cl-, cmp-, vg-, v- + crypto.randomUUID() の先頭12桁)。 プロファイル・提供者・LEDチェーンも同じ規則。PHY内の全ノードでIDを一意にする。 移動・並べ替え・reparentではIDを変えない。複製(コピー&ペーストを含む)は配下も含めて新しいIDにし、ELC・MAP・IDXへの参照は複製しない。 複製した範囲の中で閉じた参照(VariantGroupの default)は新しいIDへ付け替える。複製したキーはIDXの末尾へ足さず、未登録のままにする。 同じプロジェクト内のカット&ペーストはreparentとして扱い、IDと参照を保つ(削除+複製にすると T-15 で参照が消える)。 KLEの取り込みは毎回新しいIDを振る。

T-12 phyReference

  • source: プロジェクト内では project:phy。単独ファイルでは読み込んだPHYのファイル名(利用者がPHYを選び直せる)
  • checksum: PHY全体をJCS(RFC 8785)で正規化し、UTF-8のSHA-256を sha256-jcs:<hex> とする
  • 不一致は警告だけ。IDを付け替えず、参照の検証をやり直す。保存時に更新する

T-13 version

モックが出力する各層とプロジェクトファイルは 0.1.0。読み込みは 0.1.0 だけを受け付ける(文書の例にある 1.0.0 は互換の約束とは扱わない)。

T-14 読み込んだ未知のフィールド

保持して書き戻す。新しく書き出すデータには追加しない。

T-15 ノードの削除

IDX・ELC・MAP・LEDチェーンにある参照を一覧で示し、同じ操作(1回のUndo単位)で削除する。 Variantを削除したときは、VariantGroupの default を先頭のVariantへ移す。子が1つになるVariantGroupの削除は、確認して止める。

T-16 検証の段階

  • 保存を止めるもの: Schema違反、ID重複、参照先がない
  • 出力(mock-target.json)を止めるもの: IDXに未登録のキー、選択構成のキーの未配線・未割り当て、非排他キーの接続先の衝突
  • どちらでも警告として一覧に出す。編集途中の状態は保存できる

T-17 Undo/Redo

プロジェクト全体のスナップショットで持つ。ドラッグ1回を1操作にまとめる。

T-18 IDXの初期の並び

KLE取り込み時は、取り込んだファイルでのキーの出現順で order を1回だけ作る。手で置いたキーは作った順に末尾へ足す。 その後はPHYから作り直さない。IDXに未登録のキーは「未登録」と表示する。 decal と部品ノードは対象外、ghost は対象にする。

T-19 row/col の割り当て(Generatorのプレビュー)

出力設定に順序付きの rowPins と colPins を利用者が指定し、その添字をrow/colとする。 各接点キーの両端子が、片方は rowPins、もう片方は colPins に属することを検査する。満たさない構成(charlieplexing、direct)は「未対応」と表示して出力しない。 端子の a/b の順、キーの位置、IDXの順からは推定しない。

T-20 KLEの入出力の細部

  • 入力は厳密なJSON(KLEの緩いJSONは読まない)。VIA定義の layouts.keymap は、KLE JSONとして幾何だけを取り込む
  • ラベルは欄の位置と空欄を保って保持する。a 等の属性の引き継ぎとリセットは入出力の処理で解決する
  • 書き出しは、同じ絶対角度のキーに共通の回転中心を使い、キーの順を固定する。座標は小数6桁に丸める(PHYの値は丸めない)
  • 書き出し時のバリアント選択は output.variantSelection を使い、指定のないものはPHYの default

T-21 プロファイルと座標の単位

モックで編集できるのは、全プロファイルの unitSize が同じ場合だけ。違うものは読み込んで保持するが、編集不可と表示する。 理由: 親の座標系のUを、どのプロファイルでmmへ換算するかが決まっていない(discrepancies.md D-6)。

T-22 MAPの割り当て

  • 未割り当ては keymap に要素がない状態で表す。KC_NO・KC_TRNS は明示の割り当てとして区別する
  • 同じレイヤーでの keyId の重複は禁止
  • 新規MAPは名前 Base の空のレイヤー1枚から始める。レイヤー名は大文字小文字を区別し、MAP内で一意
  • レイヤーへの参照は MO(Nav) のように括弧内にレイヤー名を書く。対象は MO TG TO TT DF OSL LT(名前, kc) に限る。専用の解析器で読み、eval は使わない
  • レイヤー名の変更は、参照を同じ操作で書き換える。参照されているレイヤーの削除は止める
  • 編集できるキーコードは、基本キー・修飾キー・KC_NO・KC_TRNS・上のレイヤー動作・修飾キー付き(LCTL(kc) 等)に限る。知らないコードは保持し、表示だけする

T-23 キーコードの表示

QMKの表記をそのまま出し、基本キーだけUS配列の文字を添える。表示用の小さな対応表はUI側に置き、HSTのデータ形式としては扱わない。

T-24 疑似デバイスとの対応(後段・任意)

MAP P-3 の問いを、モック用に次のように固定する。

  • 出力のたびに「出力記録」を作り、選択構成・キーID↔出力番号↔row/col・レイヤー名↔番号を保存する。疑似デバイスは記録のIDを持つ
  • 書き込みは選択構成のキーだけ。選択外のバリアントのキーの割り当てはMAPに残す
  • 読み出した値は、記録にある選択構成のキーだけへ戻す。通信上のアドレスからPHYキーを推定しない
  • layout optionは疑似デバイス側で変えられないものとする。バリアントを変えたら新しい出力記録にする
  • 配線・IDXの対象キー・バリアント選択・IDXの順・レイヤーの順が変わったら記録を失効させる。座標やラベルの変更では失効させない
  • 「現在のMAP」「出力時のMAP」「最後に読んだ値」を分けて持つ。読み出しは差分を見せてから取り込む。自動同期はしない

T-25 非排他キーの接続先の衝突判定

ダイオードがあれば、接続先を(アノード側のピン, カソード側のピン)の順序付きの組として比べる。ダイオードがなければ順序のない組として比べる。 理由: 順序のない組で比べると、Cr0wn60のようなcharlieplexingが常にエラーになる(discrepancies.md D-5)。

T-26 MCUのピン名

提供者の part は1種類(RP2040)だけをモックに組み込み、ピン名(GP0〜GP29)を候補として出す。知らない part は自由入力にする。 提供者のIDに . を含めない(PinRef の区切りと衝突するため)。

T-27 reparentの計算

ワールド変換を使って 新しいローカル変換 = (新しい親のワールド変換)⁻¹ · 旧ワールド変換 とする。 仕様の式を、親が兄弟でない場合にも当てはまる形で実装する(discrepancies.md D-7)。 reparent・reframeの前後で、絶対位置の差が1e-9U以下であることをテストで確かめる。

T-28 スナップ

移動(ドラッグ・矢印キー)はグリッドの刻みに従う。刻みはエディタの状態として持ち、候補は 1U・0.25U・0.125U・1/12U、初期値は0.25U。 サイズは0.25U、回転は15度刻みで固定する。いずれも操作開始時の値から刻む。 数値の直接入力はグリッド外の値も受け付ける。計算結果は丸めない。