Skip to content

レンダラが 🐢 を自分で描けるようにしたい(Canvas の外にタートルを置く) #46

Description

@temoki

背景

TortoiseBlocks の visionOS 版(temoki/TortoiseBlocks#53)で、机の上に置いた紙の上を 3D モデルの 🐢 が歩くようにしたい。線は今まで通り TortoiseCanvasViewAttachmentComponent の中で描き、タートルだけを RealityKit のエンティティに差し替える。

つまり「描画はライブラリ、カーソルは呼び出し側」という構成で、これは visionOS 固有の話ではない。SwiftUI のオーバーレイ、別のゲームエンジンのスプライト、SpriteKit — どれも同じものを必要とする。

いま、これができない。3 つ足りない。

足りないもの

1. スプライトを描かない指定がない

TortoiseSprite.triangle.image だけ。自前のカーソルを描くと、canvas が描く三角形/画像と二重に出る。

hideTortoise()別のもので、代わりにはならない。あれはコマンドなので、シリアライズされて SVG にも PNG にもサムネイルにも保存ファイルにも付いて回る。ここで欲しいのは「この view では描かない」という表示側の指定。

2. タートルの現在位置が取れない

TortoisePlayer が公開しているのは currentCommandIndexisFinished だけ。これはコマンド単位、つまり毎秒 10 回程度しか動かない。

一方 canvas は animationProgress でコマンドを補間してスプライトを描いている(CanvasModel は internal)。だから currentCommandIndex からカーソルを動かすと、線はなめらかに伸びていくのにタートルだけがワープする。「タートルが線を引きながら歩く」がこのライブラリの売りなので、これが取れないと自前描画は成立しない。

3. 座標のマッピングが取れない

ViewportMode.transform(...)TortoiseSprite.halfExtent が internal。.autoFit は描画のバウンディングボックスに合わせて拡大・中央寄せするので、呼び出し側は同じ写像を自分で書き直すしかない。書いた日は一致していて、あとから黙ってずれる種類のコードになる。

提案

  • TortoiseSprite.hidden — canvas はアニメーションはそのまま、スプライトだけ描かない。halfExtent は 0(描かないものに余白を取る理由がない)ので .autoFit の inset も 0 になる。余白が要るなら呼び出し側で .padding()
  • TortoisePlayer.currentTortoiseState: TortoiseState? — いま canvas がスプライトを描いている、まさにその状態。canvas に attach されるまでは nil
  • ViewportMode.transform(canvasSize:viewSize:drawingBounds:spriteHalfExtent:)TortoiseSprite.halfExtent を public に

補間そのものは TortoiseState.interpolated(toward:progress:) として Core に置き、CanvasRenderercurrentTortoiseState の両方がそこを通るようにする。そうすれば自前カーソルが組み込みスプライトから 1 コマンドの端数ぶんずれることが原理的に起きない。位置と向きだけを補間する(ペンはコマンドの瞬間に下りるもので、途中まで下りた状態は存在しない)。

受け入れ条件

  • .hidden で線は今まで通り描かれ、スプライトだけ消える
  • currentTortoiseState がコマンド間で補間されている(コミット済みの状態ではない)
  • currentTortoiseState が canvas の描画位置と一致する
  • 既存の golden が変わらない

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions