ink-custom-brush-builder について
Android Ink API でプログラムからカスタムブラシを作るためのスキルです。ブラシ構造、入力に応じた動作、テクスチャ、シリアライズを、`1.1.0-alpha03` 以降の公開 Kotlin API に基づいて案内します。
主な機能
- 01BrushFamily と複数コートの構成
- 02スタイラス・タッチ動作用ノードツリー
- 03ブラシ先端の形状と描画設定
- 04テクスチャレイヤーとビットマップストアの案内
- 05ブラシ定義のエンコードとデコード
活用シーン
- 01筆圧に反応するカスタムブラシの作成
- 02書道用やテクスチャ付きブラシの設計
- 03スタイラスの傾きや速度をブラシ動作に反映
- 04カスタムブラシ定義の保存
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ android/ skills --skill ink-custom-brush-builderインストール後、Claude Code で/ink-custom-brush-builderを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/brush-behaviors.mdbrush-structure.mdexamples.mdtextures-and-serialization.mdreferences/android/develop/ui/compose/touch-input/stylus-input/ink-api-brush-apis.md詳細
Android Ink API のカスタムブラシは、BrushFamily
階層を中心に構築されています。
BrushFamily
├── InputModel (BrushFamily.InputModel.SlidingWindowModel または PASSTHROUGH_MODEL)
└── BrushCoat[] (1 つ以上のレンダリングレイヤー)
├── BrushTip (形状: scaleX、scaleY、cornerRounding、rotationDegrees、slantDegrees、pinch)
│ └── BrushBehavior[] (スタイラスまたはタッチ入力に対する動的な反応)
│ └── Tree: TargetNode(input = [Operators](input = SourceNode))
└── BrushPaint (視覚的な外観)
├── SelfOverlap (ANY、ACCUMULATE、または DISCARD)
├── TextureLayer[] (BrushPaint.TilingTexture または BrushPaint.StampingTexture)
└── BrushPaint.ColorFunction[] (OpacityMultiplier または ReplaceColor)
カスタムの BrushFamily を Compose の Color、
size、epsilon と組み合わせて Brush を作成します:
val brush = Brush.createWithComposeColor(
family = myCustomFamily,
color = Color.Black,
size = 10f,
epsilon = 0.1f,
)
バージョンと実験的 API の要件:
androidx.ink1.1.0-alpha03以降が必要です:1.0.0(安定版) および1.1.0-alpha01〜alpha02では、BrushFamily(...)、BrushCoat、BrushTip、BrushPaint、BrushBehavior、およびandroidx.ink.brush.behavior.*ノードは@RestrictTo(LIBRARY_GROUP)でした(安定版の1.0.0では、カスタムブラシはBrushFamily.decodeを使ってバイナリ proto ストリームから読み込む場合に限り使用できます)。1.1.0-alpha03以降では、プログラムによるカスタムブラシのコンストラクターが パブリック API になりました(BrushPaint.TilingTexture、BrushPaint.StampingTexture、BrushPaint.ColorFunction、BrushFamily.InputModel.SlidingWindowModel、およびすべての behavior ノード)。1.1.0-alpha03以降では@OptInは不要です:すべてのパブリックなカスタム ブラシクラスとink-storageのBrushFamilyシリアライズ API (BrushFamily.encodeとdecode、AndroidBrushFamilySerialization、BrushFamilyDecodeCallback)には、1.1.0-alpha03以降、アノテーションが付いていません (ExperimentalInkCustomBrushApiは1.1.0-alpha05以降で@RestrictTo(LIBRARY_GROUP)となり、安定版の1.0.0ではBrushFamilyの シリアライズにのみ必要です)。
ワークフローとタスクの振り分け
依頼されたカスタムブラシのタスクに応じて、以下の条件付き指示に従ってください。
- ステップ 1(依存関係):プログラムでカスタムブラシを作成するために Android プロジェクトをセットアップする場合、ビルドファイルを編集する前にユーザーの許可を求めてください。また、
gradle/libs.versions.tomlとapp/build.gradle.ktsで、androidx.ink:ink-brush、androidx.ink:ink-brush-compose、androidx.ink:ink-storage、androidx.ink:ink-nativeloaderがバージョン1.1.0-alpha03以上を使用していることを確認してください。 - ステップ 2(階層、先端形状、ペイント、入力の平滑化):
BrushFamilyと複数のコートから成るBrushCoatレイヤーの定義、BrushTipのジオメトリ(scaleX、scaleY、cornerRounding、rotationDegrees、slantDegrees、pinch)の設定、BrushPaintのプロパティ(SelfOverlap、ColorFunction)の設定、またはBrushFamily.InputModel.SlidingWindowModelによるストローク入力の平滑化を行う場合は、必ず brush-structure.md に従ってください。基本的なBrushの作成や1.0.0リソースの読み込みについては、Brush API を確認してください。 - ステップ 3(スタイラスとタッチの動的な動作):
BrushBehaviorのノードツリー(SourceNode、DampingNode、NoiseNode、ResponseNode、TargetNode、PolarTargetNode)を使用して、スタイラスの筆圧、傾き、速度、方向、または手続き型ノイズにブラシを動的に応答させる場合は、必ず brush-behaviors.md に従ってください。 - ステップ 4(テクスチャとシリアル化):
BrushPaint.TilingTextureまたはBrushPaint.StampingTextureレイヤーの追加、TextureBitmapStoreの実装、またはカスタムBrushFamily定義のエンコードとデコード(BrushFamily.encodeおよびdecode、AndroidBrushFamilySerialization、BrushFamilyDecodeCallback)を行う場合は、必ず textures-and-serialization.md に従ってください。ユーザーのプロジェクトに追加し、TextureBitmapStoreに登録するテクスチャ画像ファイル(app/src/main/res/drawable-nodpi/pencil_grain.pngなど)をユーザーに伝えてください。 - ステップ 5(ブラシの完全なレシピ):筆圧対応のペン、カリグラフィー用ペン先、陰影用鉛筆、水彩のにじみ、または複数のコートから成るシャドウブラシを一から作成する場合は、examples.md にあるコピーしてすぐ使える実装を出発点にしてください。
- Compose の描画サーフェス、消しゴム、または永続化:Compose の描画サーフェスのセットアップ、
InProgressStrokesのウェット/ドライ描画、ジオメトリベースの消去、または Room によるストロークの永続化については、ink-app-builderスキルを提案してください。
避けるべきパターン
- ブラシの構築に raw
ink.proto.*ビルダーを絶対に使用しないでください――必ず公開 Kotlin コンストラクター(androidx.ink.brush.*のBrushFamily、BrushCoat、BrushTip、BrushPaint、BrushBehavior)を使用してください。 - 筆圧や傾きへの感度を得るために、タッチリスナー内でストローク幅を手動でスケーリングしないでください――
BrushBehaviorを使用し、SourceNode.Source.NORMALIZED_PRESSUREまたはTILT_IN_RADIANSをTargetNode.Target.SIZE_MULTIPLIERまたはWIDTH_MULTIPLIERにマッピングしてください。 - テクスチャブラシに手動の
CanvasビットマップスタンプやBitmapShaderを絶対に使用しないでください――TextureBitmapStoreとともにBrushPaint.TilingTextureまたはBrushPaint.StampingTextureを使用してください。 - 最後の(または唯一の)
TextureLayerにBlendMode.SRC_OVERを絶対に使用しないでください――エッジのアンチエイリアスやOPACITY_MULTIPLIERの動作が上書きされないよう、BlendMode.MODULATE、DST_IN、DST_OUT、SRC_ATOP、またはSRC_INを使用してください。 BrushFamilyを JSON、Gson、Moshi、またはParcelableとしてシリアル化しないでください――必ずBrushFamily.encodeとBrushFamily.decode、またはandroidx.ink.storageのAndroidBrushFamilySerializationを使用してください。- 手動でベジェ曲線(
quadTo、cubicTo)の平滑化を実装しないでください――入力の平滑化にはBrushFamily.InputModel.SlidingWindowModelを、動作の平滑化にはDampingNodeを設定してください。 - 有機的なストロークの揺らぎを加えるために、描画ループ内で
Random.nextFloatを使用しないでください――BrushBehaviorでストローク距離に応じて変化するNoiseNodeを追加してください。
コメント
Markdown 対応