Skip to content

LUA SCRIPTING API

APIリファレンス

Mug TypographyのLuaスクリプトから利用できるコールバック、ctxオブジェクト、座標系、mt.*ユーティリティの完全な仕様です。

オフラインでも参照できます

同じAPI仕様書を、配布ZIPの scripting-simulator/docs/ にも同梱しています。

Mug Typography のスクリプティングは、プラグインの Script Text に書いた Lua 5.4 スクリプトで テキストレイアウトと文字・パーツのアニメーションを制御する機能です。開発環境として、VSCode 拡張 「Mug Typography Scripting Simulator」(MT Sim) と、インストール不要でブラウザから使える オンラインシミュレーターを利用できます。 どちらもホストアプリを起動せずにスクリプトをプレビュー・デバッグできます。

1. 基本モデル ​

スクリプトには最大3つのコールバック関数を定義します。どれも省略可能で、定義しなかった コールバックは単にスキップされます。

text
フレーム評価パス(毎フレーム)

  毎フレーム
    └─ OnPreLayout(ctx)
         レイアウト・全体・カメラの基礎値を変更、図形・カスタムグリフを宣言
          ↓
       文字・パーツのレイアウト生成
          ↓
       OnLayout(ctx)
         生成された文字・パーツ・図形を個別に調整
          ↓
       OnPath(ctx)
         選択したパーツ・図形の輪郭を調整
          ↓
       描画

重要なのは、各コールバックで実行されるタイミングと操作できる対象が異なることです。 目的に合う段階のコールバックだけを定義します。

  • OnPreLayout は毎フレームのレイアウト生成前に実行されます。テキスト、フォント、字送り、全体設定、カメラなど、文字・パーツの生成条件を変更し、図形やカスタムグリフを宣言します
  • OnLayout は文字・パーツの生成後に実行されます。生成された各要素や図形の位置、回転、色などを調整します
  • OnPath は個別調整後、描画前に実行されます。選択したパーツや図形の輪郭を置換・再構築します

後段のコールバックでは、前段で確定した値を参照できます。ただし、処理済みの段階へ戻って 値を書き換えることはできません。たとえば OnLayout から ctx.global や ctx.camera は 参照できますが、変更はできません。

変更はフレーム内でのみ有効 ​

ctx は毎フレーム、ホストのInspector値から作り直された状態 でコールバックに渡されます。 コールバックで書き込んだ値はそのフレームの描画にだけ使われ、次のフレームではまたInspector値 から再スタートします。Inspectorやキーフレームへ書き戻されることもありません。

たとえば ctx.global.rotation = ctx.global.rotation + 1.0 は「毎フレーム1度ずつ回り続ける」 のではなく、「常にInspector値+1度」になります。Inspectorの回転を基準に回転を進める場合は、 ctx.global.rotation = ctx.global.rotation + ctx.time * 20.0 のように、ctx.timeから求めた フレーム独立な差分を現在値へ加えます。ctx.global.rotation = ctx.time * 20.0と直接代入する書き方は、 Inspectorの回転を意図的に完全上書きする場合だけ使用します。

2. フレーム独立性の要件(ステートレス実行) ​

ホストはフレームを時系列順に評価するとは限りません。スクラブ、逆再生、キャッシュ、並列レンダーの どの場合でも同じ結果になる必要があります。各フレームの結果は現在の入力値だけから決まり、 前フレームの結果やフレームの評価順序に依存してはいけません。本書では、この性質を フレーム独立性 と呼びます。

  • グローバル変数や関数の外側で宣言した local 変数を書き換える場合は、同一フレーム内のコールバック間で値を渡す用途に限り、毎フレーム現在の入力値から上書きする。前フレームの値を読み継いだり累積したりしない
  • ctx や ctx.chars[index] などの参照をコールバック終了後まで保持しない
  • 文字数、パーツ数、特定フォントの形状を固定値として仮定しない
  • 逐次シミュレーションではなく、ctx.time からそのフレームの値を直接求める
  • 文字・パーツの走査は必ず ctx.char_count / ctx.part_count を使う

スクリプトメタデータ ​

スクリプトファイルの先頭に、Luaのコメントとして @<name> <value> を記述すると、必要なAPI、 MT Simの動作、初期設定、Script Inputsを宣言できます。メタデータはコールバック内で実行される Lua APIではありませんが、@api_level・@input・@time_independentはホストプラグインも解釈します。

スクリプトの認識と実行設定 ​

記述内容
@MugTypographyファイルの1行目から始まる連続した -- 単一行コメント内(MT Simでは先頭から5行以内)に置くと、Mug Typography用スクリプトとして認識されます。入力補完・シミュレーター連携・ホストでの @input 認識に必要で、配布サンプルにも必ず1行目に含まれます。@mt または @mug も使用できます
@duration <秒数>シミュレーターの初期再生時間を設定します。例: @duration 5.0
@required 3dシミュレーター起動時に3D投影設定(Enable 3D projection)を有効にします。3dprojection も使用できます

推奨初期設定 ​

@recommend <設定> は、スクリプトの演出に特定の初期条件が必要な場合だけ使用します。 指定は必要最低限にしてください。テキスト、位置、背景などをむやみに指定すると、表示結果が スクリプトによるものか、Inspectorの初期設定によるものか分かりにくくなります。 任意の設定で成立するスクリプトでは使用しません。

記述内容
@recommend bg <指定>背景の初期値。#RRGGBB / #RRGGBBAA で単色、checkerboard / checker でチェッカー背景、solid でチェッカーを明示的に解除します。色とモードを同じ行にも書けます。例: @recommend bg checkerboard #ffffff
@recommend fill <色>グローバル塗り色の初期値。#RRGGBB / #RRGGBBAA で指定します。例: @recommend fill #d8d4f2
@recommend gradient <色>Gradient End Colorの初期値。グラデーションがnoneでも、スクリプト用の第2色として使用できます。例: @recommend gradient #ff4f9a
@recommend pos <X> <Y>グローバル文字位置の初期値。Xは大きいほど右、Yは大きいほど上です。例: 中央は @recommend pos 0.5 0.5、画面下部は @recommend pos 0.5 0.18
@recommend text "<文字列>"Textの初期値。"..." または '...' で囲みます。\n は改行、\" \' \\ は各文字そのものになります。例: @recommend text 'ゆれる\nもじ'。"" にするとTextを空にして始めます(本文を使わない全画面の背景向け)
@recommend vertical <boolean>文字方向の初期値。trueで縦書き、falseで横書き。読み込み時に適用し、その後のInspector変更を尊重します
@recommend lang <言語コード>対応言語のフォントを自動選択します。例: @recommend lang ja。text から言語を推定できる場合は省略でき、明示した値は自動判定より優先されます

シミュレーターの Reset ボタンを押した場合も、これらの推奨初期設定が適用されます。 VS Code拡張機能とオンラインシミュレーターでは、bg / fill / gradientのHEX値に 色見本が表示されます。色見本を選択すると、標準のカラーピッカーから値を変更できます。

Script Inputs ​

Script InputsはAPI Level 8以降で利用できます。 @inputは、InspectorのScript Inputsに表示するslot、表示名、任意の初期値を宣言します。 構文は次のとおりです。

text
@input <type> <index> "<label>" [default=<value>]
lua
-- @input number 1 "Amplitude" default=15.0
-- @input number 2 "Speed" default=1.0
-- @input color 1 "Primary Color" default={1.0, 0.4, 0.2, 1.0}
-- @input text 1 "Caption" default="Hello"
-- @input boolean 1 "Enable Glow" default=true
typeindexLuaからの参照default省略時
number1〜14ctx.inputs.numbers[index]0.0
color1〜8ctx.inputs.colors[index]{1.0, 1.0, 1.0, 1.0}
text1〜4ctx.inputs.texts[index]空文字列
boolean1〜8ctx.inputs.booleans[index]false

booleanはAPI Level 10以降で利用できます。defaultはtrueまたはfalseだけを受け付けます。

  • typeはASCIIの大文字・小文字を区別しません。slotの表示順は宣言順ではなく、Number、Color、Text、Booleanのindex順です
  • labelは1〜64 UTF-8 bytesで、\"と\\だけをescapeできます
  • Numberのdefaultは-1000000.0〜1000000.0の有限数、Colorは各channelが0.0〜1.0のRGBA 4要素、TextはNULを含まない4096 UTF-8 bytes以下の単一行文字列です
  • 同じtype/indexの重複、未知type、範囲外index、不正なquote・escape・default・余分なtokenはメタデータエラーです。エラー時は直前の有効なInspector表示を維持し、Script StatusにInput line <行番号>: <内容>を表示します(Luaのcompile・実行は妨げません)
  • 宣言されたslotだけがInspectorに表示されます。宣言がなければScript Inputsグループ全体が隠れます。Luaでは未宣言slotを含む固定長配列を常に読み取れます
  • Script Text変更時、新規slotまたは実効defaultが変わったslotだけに初期値を適用します。labelだけの変更では値とキーフレームを維持します
  • キーフレームがあるslotへdefaultを上書きしません。プロジェクト読込み時は保存済みの値とキーフレームを維持し、metadataのdefaultを再適用しません

時間非依存の宣言 ​

-- @time_independent(値なし)を宣言すると、Inspector値が同じフレーム間で描画結果を再利用し、このスクリプトをホストへの時間依存通知から除外します。

-- @time_independent は先頭の連続する -- コメント内に置いてください(空行・字下げ・本文・ブロックコメントより前)。省略時は従来どおり時間依存です。これは作者の契約で、自動解析は行いません。ctx.time、ctx.frame、タイムライン情報、呼び出し回数や外部状態などに結果が依存する場合は宣言しないでください。Inspector値(@input のキーフレームを含む)、スクリプト本文、描画サイズの変更は引き続き再描画の対象です。Pulseなど他の時間依存エフェクトは通知・再描画の対象のままです。シミュレーターは宣言を読み取りますが、プレビューのフレーム評価は継続します。

サンプルブラウザの表示情報 ​

Web版シミュレーターのサンプルブラウザに表示する情報です。省略した場合、タイトルにはファイル名が 使われ、作者・バージョン・APIレベルは表示されません。

記述内容
@title <表示名>カードに表示するタイトル。例: @title Callback Flow Basics
@author <作者名>作者名。例: @author Mug
@version <バージョン>スクリプトのバージョン。例: @version 1.0
@api_level <数値>スクリプトが必要とするAPIレベル。例: @api_level 6。新しいAPIレベルを宣言したスクリプトは、未対応のプラグインでは読み込まれません
@animation_id同梱サンプルの固定ID(所属ジャンルの英大文字3文字+3桁の連番、例: FAD002)。ブラウザに表示し、IDで検索できます。ご自身のスクリプトには書かなくて構いません
@descriptionブロックコメント内の複数行の説明文。@description 直後の改行は無視されます
@description.<locale>サンプル説明の翻訳(例: @description.ja、@description.en)。表示言語の翻訳がなければ@descriptionを使用。検索は全言語の説明を対象にします

記述例 ​

lua
-- @MugTypography
-- @duration 5
-- @title Callback Flow Basics
-- @author Mug
-- @version 1.0
-- @api_level 8
-- @input number 1 "Amplitude" default=15.0
--[[ @description
Reference: callback execution timing and the frame-independent
scripting contract.
]]

記述位置と解析範囲 ​

@MugTypography および @duration / @required / @recommend / @input / @title / @author / @version / @time_independent / @api_level は、 ファイルの1行目から始まる連続した -- 単一行コメントの範囲内に記述してください。 @description のブロックコメントや、コメントではない行(空行・字下げした行を含む)に達した時点で解析範囲は 終了します。そのため、単一行のメタデータは@descriptionより前に書いてください。 複数の@recommend行にも、1行へ複数設定を書いた形式にも対応します。生成コードでは@MugTypographyを1行目、 その他のメタデータ・説明文をその直後に置いてください。

3. コールバック ​

コールバック呼ばれるタイミング主な用途
OnPreLayout(ctx)レイアウト生成前(毎フレーム)文字・パーツの生成条件と全体設定の変更、図形・カスタムグリフの宣言
OnLayout(ctx)レイアウト生成後(毎フレーム)生成された文字・パーツ・図形の個別調整
OnPath(ctx)OnLayout 後(毎フレーム)選択したパーツ・図形の輪郭の置換・再構築

OnPreLayout / OnLayout で参照・変更できるフィールドは、 ctx リファレンスを参照してください。OnPath のフィールドは§3.3で説明します。

3.1 OnPreLayout(ctx) ​

項目内容
シグネチャfunction OnPreLayout(ctx)
引数ctx: table。レイアウト生成前のコンテキスト
戻り値なし。値を返しても無視される
実行タイミング毎フレーム、文字・パーツのレイアウト生成前
主な変更対象ctx.global / ctx.camera / ctx.shapes:declare / ctx.shape_cameras:declare / ctx.glyphs:declare
エラー時ホストでは後続コールバックを実行せず、そのフレームを描画しない(MT Simでは元の値でプレビューを継続)

ホストパラメーターから作られた全体設定の作業コピーを受け取り、レイアウト生成前の値を変更します。

TIP

スケール調整の設計ルール: テキストの長さや文字数に合わせて全体のサイズを調整する(画面外へのはみ出しを防ぐなど)ときは、OnLayout の中で各文字の character.scale を縮めるのではなく、OnPreLayout で ctx.global.scale をあらかじめ調整してください。そうすることで、タイプライター演出のように文字が1文字ずつ増えていく途中でも、文字数に合わせて全体サイズがガタつくのを防げます。

時間軸(実秒数 vs 進行度)の設計ルールは ctx.timeline を参照してください。

3.2 OnLayout(ctx) ​

項目内容
シグネチャfunction OnLayout(ctx)
引数ctx: table。レイアウト生成後のコンテキスト
戻り値なし。値を返しても無視される
実行タイミング毎フレーム、文字・パーツのレイアウト生成後
主な変更対象ctx.chars[index] / ctx.parts[index] / ctx.shapes[index] / ctx.shape_cameras[index] / ctx.bounding_box / ctx.output
エラー時ホストでは OnPath を実行せず、そのフレームを描画しない(MT Simでは未変更のレイアウトでプレビューを継続)

確定した全体設定から生成された文字・パーツ・図形を調整します。文字数とパーツ数はこの時点で確定しています。

3.3 OnPath(ctx) ​

項目内容
シグネチャfunction OnPath(ctx)
引数ctx: table。パス編集用コンテキスト
戻り値なし。値を返しても無視される
実行タイミング毎フレーム、OnLayout の後、変形・投影・描画の前
主な変更対象ctx.paths から取得したパーツ・図形の path
エラー時ホストではそのフレームを描画しない(MT Simでは元のグリフ輪郭でプレビューを継続)

ctx.paths の part / character / select / shape を使って対象パーツを取得し、その path を編集します。 取得方法と編集APIの詳細は、ctx リファレンスを 参照してください。

3.4 完全なスクリプト例 ​

lua
-- @MugTypography
-- @api_level 8

-- Base phase: values that determine layout and global inheritance.
function OnPreLayout(ctx)
    ctx.global.tracking = mt.wave(ctx.time, 0.25, 0.0) * 0.05
    ctx.global.rotation = mt.wave(ctx.time, 0.1, 0.0) * 5.0
end

-- Layout phase: adjust only the generated characters and parts.
function OnLayout(ctx)
    for index = 1, ctx.char_count do
        local character = ctx.chars[index]
        local progress = mt.stagger(ctx.time, index, 0.06, 0.35)
        character.offset_y = 0.5 + (1.0 - mt.ease.out_cubic(progress)) * 0.15
        character.rotation = character.rotation + mt.wave(ctx.time, 0.5, index * 0.25) * 3.0
    end

    for index = 1, ctx.part_count do
        local part = ctx.parts[index]
        part.scale = part.scale * (1.0 + mt.random(42, index) * 0.05)
    end
end

より実践的な例は、配布物に同梱されている samples/ を参照してください。 samples/reference/ は基本モデルと各APIをジャンル別に学べる短いサンプル、 samples/showcase/ は完成されたアニメーション集です。

4. 型と座標系 ​

4.1 座標・単位の定義 ​

公開 number フィールドは、次のいずれかの単位系に属します。

X 成分は canvas 幅、Y 成分は canvas 高さを 1 とします。Y は上方向が正です(§4.3)。

canvas 正規化座標(位置) ​

canvas 上の位置を表します。値 0.5 は当該軸における canvas 中央です。

フィールド定義
ctx.global.position_x / position_y全体の位置。書き込み可(OnPreLayout)
ctx.global.pivot_x / pivot_yglobal.position を基準とする全体変形の支点の変位。書き込み可(OnPreLayout)
geometry の canvas 座標(bounds_center_* 等)変形前レイアウトにおける読み取り専用の位置。文字・パーツごとに異なります

canvas 正規化変位(中立値 0.5) ​

レイアウトが決めた自然位置に対する変位を表します。絶対位置ではありません。中立値は 0.5 であり、 描画時の変位量は次式で解釈されます。

text
変位量(canvas 比) = value - 0.5

変位量の基準は canvas 幅または高さであり、文字サイズや geometry.advance_* ではありません。

フィールド定義
文字・パーツの offset_x / offset_y自然位置からの平行移動。0.5 のとき変位量は 0 であり、レイアウトが決めた位置(変形前中心は geometry.bounds_center_*)に留まります。0.5 より大きいと右/上へ平行移動します。2D canvas目標位置への配置にはmt.layout.place_2dを使います
global.pivot_x / global.pivot_y回転・スケールの支点の、global.position からの変位。0.5 のとき支点は global.position に一致します
文字・パーツの pivot_x / pivot_y回転・スケールの支点の、自然中心からの変位。0.5 のとき支点は自然中心(文字は geometry.bounds_center、パーツは自然位置)に一致します

位置と変位の対応:

種別対象値の意味中立 / 中央
位置global.position_*、geometry の canvas 座標canvas に対する座標0.5 = canvas 中央
変位global.pivot_*、文字・パーツの offset_* / pivot_*global.position、自然位置、自然中心のいずれかを基準とする差分0.5 = 差分ゼロ

その他の単位系 ​

単位系フィールド定義
emtracking、margins、stroke.width、stroke.gap、shadow.distanceフォントサイズに対する比率。1.0 = 1 em。ストロークは描画時に fontSize を掛ける
fontSize 百分率bounding_box.width / margin_* / corner_radius / fill_offset_* / stroke_offset_*100.0 = fontSize と同じ長さ。px 換算は value * fontSizePx / 100
倍率scale、stretch_*、zoom1.0 が等倍
0-1opacity、color の各成分、write_on_start / write_on_end、bounding_box.fill_opacity 等閉区間または進行度として解釈される値
degreerotation、yaw、pitch、各種 angle角度。符号は §4.3
遠近強度camera.perspective単位なし。内部で distancePx = f(perspective) * canvas.height に写像(大きいほどカメラが近い)
pxcanvas.width / heightピクセル

NOTE

shadow.distance は stroke.width と同じ em 単位で、パーツ自身の空間で測ります。 パーツの拡縮(global・文字・パーツの scale と stretch_*)、回転、遠近のどれがあっても、 シャドウは文字から常に同じ距離に見えます。shadow.angle で決めた方向は canvas 上で固定されます。

4.2 color ​

lua
{ r = 1.0, g = 0.5, b = 0.0, a = 1.0 }

r / g / b / a は number で、範囲は 0-1 です。 4つすべてを同時に指定する必要はなく、変更したい成分だけを書いたテーブル(例: { a = 0.5 })を代入できます。省略したキーは元の色の値がそのまま保たれます。 r / g / b / a 以外のキーを含めるとエラーになります。

4.3 座標 ​

  • 位置・offset・pivot の単位定義は §4.1

  • X は canvas 幅、Y は canvas 高さを基準にします

  • global.position、文字・パーツの offset / pivot、geometry では、Y は上方向が正です(Lua値のYを増やすと画面上方向へ移動します)

  • 3Dの奥行き z は奥方向が正です(値が大きくなるほどカメラから遠ざかり、画面奥に配置されます。負の値で手前に近づきます)

  • global.pivot と文字・パーツの offset / pivot は canvas 正規化変位です(§4.1)。geometry の canvas 座標と global.position は canvas 正規化位置です

  • geometry の canvas 位置は canvas 左下が 0,0、中心が 0.5,0.5

  • geometry の local 位置と advance は変位量なので中心オフセットを持たず、Y-up で表されます

  • 形状を描く座標はY-down、配置座標・移動量・文字メトリクスはY-upです

  • rotation、yaw、pitch、angle はすべて degree です

    • 2D回転(rotation): 正(+)が時計回り(右回り)、負(-)が反時計回り(左回り)です(90 で上を向いていたものが右を向きます)。
    • 3Dオブジェクト回転(yaw, pitch): Individual/Global ともに、個別ピボットを中心とした回転です。
      • yaw: 正(+)でオブジェクトの右端が手前(-Z)へ、左端が奥(+Z)へ回転します。
      • pitch: 正(+)でオブジェクトの上端が手前(-Z)へ、下端が奥(+Z)へ回転します。
    • カメラの旋回(yaw, pitch): 注視点の周りをカメラが公転(Orbit)します。
      • yaw: 正(+)でカメラが注視点の周りを右に回り込みます(画面上のオブジェクトは左に回転して見えるようになります)。
      • pitch: 正(+)でカメラが注視点の周りを上に回り込みます(見下ろすアングルになります)。
    • グラデーション角度(angle): 0度で左から右(Xの正方向)に進み、角度が増える(正)と時計回りに回転します。
    • シャドウ角度(angle): 0度で右方向(Xの正方向)に伸び、角度が増える(正)と時計回りに回転します(90度で真下方向)。

WARNING

2Dの角度系は「スクリーン感覚(時計回りが正、90度 = 真下)」で統一されており、 座標系(Y-up)とは向きの感覚が逆です。 offset_y は上が正なのに対し、rotation / gradient.angle / shadow.angle は正で時計回りに回り、シャドウ角 90 は真下を 指します。

座標系から符号を導くと逆になります。 Y-up なら通常は反時計回りが正で、数学的慣習も Fusion の Transform ノードもそちらです。本エフェクトだけが例外なので、どちらから持ち込んだ 角度も符号を反転する必要があります。Transform と組み合わせて同じ向きに回すときも、 どちらか一方を反転してください。

符号は時計の文字盤で確認してください。 rotation = 90 で上を向いていたものが 右を向きます(12時 → 3時)。文字盤と画面の感覚がずれる下半分に注意してください。 下に垂れたものは正の値で左へ振れます(6時から7時・8時へ進むため)。

角度から向きベクトルを作って offset_y に渡すときは、mt.polar_offset_2d を使ってください。 入力の角度は角度系(90 度 = 画面下向き)のまま、戻り値は位置系(Y は上が正)で返るので、 offset_x / offset_y の両方へそのまま加算できます。

lua
local dx, dy = mt.polar_offset_2d(angle, radius)
character.offset_x = character.offset_x + dx
character.offset_y = character.offset_y + dy

TIP

円形・放射状エフェクトの距離には mt.layout.radial_distanceを使ってください。 Canvasのアスペクト比は関数内で補正されるため、X座標を手動で変換する必要はありません。

lua
local distance = mt.layout.radial_distance(
    ctx,
    geometry.bounds_center_x,
    geometry.bounds_center_y
)

斜め方向への符号付き距離や内積を求める場合は、X方向の差分に ctx.canvas.aspect_ratio を掛けてから計算します。非正方形ピクセルの物理表示比を考慮する場合は、 ctx.canvas.pixel_aspect_ratio も掛けます。

pivot は基準点からの変位 ​

  • ctx.global.pivot_x/y は global.position からの変位です。0.5, 0.5 のとき支点は global.position と一致します
  • 文字・パーツの pivot_x/y は自身の基準点からの変位です。0.5, 0.5 のとき、文字は 自然なバウンディングボックス中心(geometry.bounds_center 相当)、パーツは自然位置 (geometry.canvas_center 相当)を中心に回転・スケールします
  • したがって文字・パーツの pivot に geometry の canvas 座標をそのまま代入してはいけません。 「自身の中心から右へ10%ずらした点を中心に回す」なら pivot_x = 0.5 + 0.1 です
  • 文字の辺を支点にするときは、自然中心からの半サイズ分だけ変位させます (bounds_width / bounds_height は canvas 軸比で、pivot の変位と同じ単位系です):
    • 下辺: pivot_y = 0.5 - geometry.bounds_height * 0.5
    • 上辺: pivot_y = 0.5 + geometry.bounds_height * 0.5
    • 左辺: pivot_x = 0.5 - geometry.bounds_width * 0.5
    • 右辺: pivot_x = 0.5 + geometry.bounds_width * 0.5

4.4 代入のルール ​

書き込み可能フィールドの現在値には、Inspector設定と前段のコールバックで確定した値が入っています。 完全上書きが演出の意図でない限り、その現在値を基準にアニメーションを合成してください。

  • 位置、オフセット、ピボット、回転、奥行きには、アニメーションで求めた差分を加算します
  • Scale、Stretch、Opacityには、アニメーションで求めた係数を乗算します
  • FillやStrokeの色など、作品固有のスタイルへ置き換えること自体が目的なら直接代入できます
  • 複数の計算で元の値が必要な場合は、最初の書き込み前にローカル変数へ保存します
lua
local inspectorRotation = character.rotation
local inspectorScale = character.scale

character.rotation = inspectorRotation + math.sin(ctx.time) * 10.0
character.offset_y = character.offset_y + math.sin(ctx.time * 2.0) * 0.05
character.scale = inspectorScale * (1.0 + math.sin(ctx.time) * 0.1)
character.opacity = character.opacity * fade

-- Inspector設定を置き換えることが意図である場合だけ直接代入する
character.rotation = ctx.time * 20.0

次の操作はエラーになります。

  • 書き込み不可フィールドへの代入
  • 未知フィールドの追加
  • 型の不一致(numberの場所へstringなど)
  • ctx.chars / ctx.parts など読み取り専用コンテナの置換・要素数変更
  • 列挙値フィールドへの不正な文字列

5. 継承の仕組み ​

use / opacity / fill.transparent の役割 ​

設定描画への影響
fill.use / stroke.use / shadow.usetrueなら対象の文字・パーツに設定された個別値を使い、falseなら上位の設定を引き継ぎます。表示・非表示は切り替えません
opacity(global / character / part)継承後に決まった塗り・線・影などの不透明度へ乗算します。0で透明、1で元の不透明度です
global.fill.transparent塗りだけを透明にします。ストロークやシャドウには影響しません

描画に使う色と不透明度は、次の順で決まります。

  1. 色の決定: fill.use が true なら文字・パーツに設定された個別色を使い、false ならグラデーション(有効時)またはGlobalの塗り色を使います
  2. 不透明度の適用: 決定した色の不透明度に global.opacity × character.opacity × part.opacity を掛けます

use = false の場合、文字・パーツの個別色を変更しても描画には使われません。 opacityだけを変更した場合、使用する色やグラデーションは変えずに不透明度だけが変わります。

描画に使われる値は次の順で決まります。

text
OnPreLayout で確定した Global
  ↓
文字: 各グループの use が true なら文字の個別値、false なら Global 値
  ↓
パーツ: 各グループの use が true ならパーツの個別値、false なら文字の段階で選ばれた値

gradient.color_space が none 以外のときは、この順序でGlobal値が選ばれた (文字・パーツどちらの fill.use も false の)部分だけがグラデーションで塗られ、 個別色が有効な文字・パーツは、その個別色の単色で塗られます。

パーツの stroke / shadow はホスト側にパラメーターグループが存在しない(常に未使用/既定値から 始まる)点を除けば、fill と同じ順序で使用する値が選ばれます。

OnLayout に渡される文字・パーツには、上位の設定を反映する前の個別設定値が入っています。 Luaからは各グループの use も変更できるため、個別値を書き換えて同じコールバック内で 有効にできます。

lua
local character = ctx.chars[index]
character.fill.use = true
character.fill.color = mt.color.from_hsv(index / ctx.char_count, 0.8, 1.0)

transform系フィールド(offset / scale / rotation など)には use_* がなく、常に描画へ反映されます。 スクリプトによる変更はそのフレーム内だけで完結し、ホストのInspectorやキーフレームへ書き戻される ことはありません。

6. 実行環境・エラー・制限 ​

6.1 エラー時のフレーム処理 ​

ホストではコールバック内のどこかでエラーが起きると、そのフレームは描画されません。失敗までに行われた変更の ロールバックは保証されませんが、未完了の結果が描画に使われることはありません。

MT Simではデバッグを続けやすくするため、エラーをOutputパネルへ表示し、スクリプト適用前の値へフォールバックして プレビューを続けます。この点はホストのフレーム中止動作と異なります。

失敗箇所結果
スクリプトロードホストでは描画しない。MT Simではエラーを表示し、直前の正常なスクリプトを維持する
OnPreLayoutホストでは後続コールバックを実行せず描画しない。MT Simでは元の値でプレビューする
OnLayoutホストではOnPathを実行せず描画しない。MT Simでは未変更のレイアウトをプレビューする
OnPathホストでは描画しない。MT Simでは元のグリフ輪郭をプレビューする

6.2 利用可能な標準ライブラリ ​

Lua標準ライブラリは、安全なサブセットに限定されています。

  • 利用可能: 基本関数の安全なもの、math、string、table、utf8
  • 利用不可: os、io、package、require、dofile、loadfile、load、debug、 collectgarbage、rawget、rawset、getmetatable、setmetatable

ファイル、ネットワーク、プロセスへのアクセスはできません。

6.3 実行制限 ​

  • 1コールバック呼び出しあたり 5,000,000 命令
  • メモリ上限 128MiB(ホスト実行時)

上限を超えたコールバックは失敗として扱われ、§6.1 の動作になります。

6.4 print(...) とフレームダンプ ​

Lua標準の print(...) は、MT SimのOutputパネル(ログ)へ診断情報を出力するために使えます。

フレームダンプ機能 ​

シミュレータツールバーの 虫アイコン(フレームダンプ)ボタン をクリックすると、タイムラインの選択範囲(未指定時は全フレーム)を順次評価し、シーンの前提情報(解像度・文字数・フォント等)と各フレームの print(...) 出力・エラーを一括してログへダンプします。

  • === SIMULATOR CONTEXT ===: 解像度、FPS、文字数、パーツ数、フォント、配置設定などのシーン前提値
  • === FRAME LOGS ===: 各フレームの [<フレーム番号>] <出力内容>(出力がないフレームは省略)
  • === DUMP COMPLETE ===: 評価結果サマリー
  • タイムラインのイン/アウトハンドルを動かして範囲を絞り込むことで、特定の区間だけを素早く検証できます。

6.5 エラーの確認 ​

ホストではスクリプトのエラー内容を確認できません。まずMT Simでスクリプトを実行し、 Outputパネルに表示されるエラーメッセージとスタックトレースを確認して修正してください。

対象APIレベル: 15

ctxは、Mug Typographyが各コールバックへ渡すコンテキストです。現在時刻、Canvas情報、 全体設定、生成された文字・パーツなど、そのフレームの処理に必要な情報が含まれます。

利用できるフィールドと書き込み権限はコールバックによって異なります。本書では、最初に コールバックごとの利用可否を一覧にしたあと、ctxのフィールドを順に説明します。 コールバックの実行順序と用途は コールバックの概要を参照してください。

1. ctxのフィールド一覧 ​

ctx直下のフィールド自体は読み取り専用で、別の値へ置き換えることはできません。 ただし、ctx.globalやctx.chars[index]などの内部には、コールバックに応じて変更できる フィールドがあります。○はそのコールバックで参照できることを表します。

フィールド型OnPreLayoutOnLayoutOnPath内容
ctx.timenumber○○○クリップ先頭を0とする現在時刻(秒、§1.1)
ctx.framenumber○○○クリップ先頭を0とするフレーム番号。サブフレームを含む場合があります(§1.1)
ctx.fpsnumber○○○フレームレート(§1.1)
ctx.canvastable○○○Canvasとプロジェクトの画素情報(§1.2)
ctx.fontsstring[]○○○global.font_nameへ設定できるフォント名の1始まり配列(§1.3)
ctx.timelinetable○○○クリップの時間範囲と現在進行度(§1.4)
ctx.fonttable-○○使用中フォントのメトリクス(寸法情報、§1.5)
ctx.textstring○○-廃止予定のテキスト参照(§1.6)
ctx.char_countinteger-○○有効な本文の文字数。図形は数えません(§1.6)
ctx.part_countinteger-○○有効な本文のパーツ数。図形は数えません(§1.6)
ctx.shape_countinteger-○○宣言された図形の数(§1.17)
ctx.metatable○○○APIバージョンと機能情報(§1.7)
ctx.inputstable○○○Inspectorで設定したスクリプト入力(§1.16)
ctx.globaltable○○○全体設定。OnPreLayoutで変更でき、以降は読み取り専用です(§1.8)
ctx.cameratable○○○カメラ設定。OnPreLayoutで変更でき、以降は読み取り専用です(§1.9)
ctx.charstable[]-○○生成された本文の文字の1始まり配列(§1.10)
ctx.partstable[]-○○生成された本文のパーツの1始まり配列(§1.11)
ctx.bounding_boxtable-○○バウンディングボックスの描画設定(§1.12)
ctx.outputtable-○○出力フィルタと描画順の設定(§1.13)
ctx.pathstable--○パーツのパスを取得・編集するためのコンテキスト(§1.14)
ctx.glyphstable○--カスタムグリフを宣言するためのコンテキスト(§1.15)
ctx.shapestable○○○図形を宣言し、番号で参照するためのコンテキスト(§1.17)
ctx.shape_camerastable○○-図形を映すカメラを宣言し、番号で動かすためのコンテキスト(§1.17)

1.1 ctx.time / ctx.frame / ctx.fps ​

現在の評価位置をクリップ先頭基準で表します。ctx.timeは秒、ctx.frameはフレーム単位です。 ctx.frameにはサブフレームが含まれる場合があるため、整数とは限りません。ctx.fpsは 1秒あたりのフレーム数です。

1.2 ctx.canvas ​

Canvasとプロジェクトの画素情報です。すべて読み取り専用です。

フィールド型単位内容
width / heightnumberpxCanvasの幅と高さ
aspect_rationumber-Canvasの幅を高さで割った値(width / height)
pixel_aspect_rationumber-ホストプロジェクトのピクセルアスペクト比

1.3 ctx.fonts ​

ホストが認識しているインストール済みフォントの名前を格納した、読み取り専用の1始まり配列です。 内容はホストUIのFontリストと同じで、OnPreLayoutでは要素をctx.global.font_nameへ 設定できます。

配列の要素や要素数は変更できません。

1.4 ctx.timeline ​

フィールド型単位内容
availableboolean-有限なクリップ範囲を取得できたか
start_frame / end_framenumberframe範囲の始端/終端(クリップローカル。始端は常に0)
duration_framesnumberframeend_frame - start_frame
duration_secondsnumbersecond秒に換算した長さ
progressnumber0-10-1にクランプされた現在位置

クリップ範囲 ​

クリップ範囲は、トリムや前後の引き伸ばしを含むタイムライン上の実範囲です。 ctx.time / ctx.frame / ctx.timelineには、クリップ先頭を0とした同じ時間軸の値が 渡されます。フィルタとして映像クリップに適用した場合も、そのクリップの範囲に追従します。

availableがfalseのときは他の値が0になるため、フォールバックを用意してください。

NOTE

ジェネレータ運用での前方引き伸ばしの制限: ジェネレータクリップ(入力未接続)の前方を タイムライン上で引き伸ばした場合、その区間はホストが先頭フレームの静止画として扱うため、 スクリプト時間は引き伸ばし境界まで進みません(イントロが先頭姿で静止して見えます)。 尺を変えたい場合は引き伸ばしではなくジェネレータクリップ自体の長さを変更してください。 フィルタ運用にはこの制限はありません。

時間軸の設計ルール(アンカー × 速度) ​

アニメーションの時間設計は「①どこに固定するか(アンカー)」と「②どの速さで進めるか(速度)」の 2軸で決めます。**速度の既定は実秒(ctx.time ベース)**で、クリップ長に比例させる progress を 使ってよいのは後述の「全体スパン型」だけです。

パターンアンカー書き方
イントロ(登場)クリップ先頭ctx.time をそのまま使う(実秒)。イントロ+アウトロ一括なら mt.timeline.intro_outro_seconds(§10.9)
アウトロ(退場)クリップ終端mt.timeline.remaining(ctx)(終端までの残り実秒。§10.9)
タイプライター・stagger・ばね等クリップ先頭ctx.time(実秒。1文字あたり○秒など物理速度で指定)
全体スパン型(尺いっぱいのドリフト・スイープ・リビール)クリップ全体progress(尺が伸びたら動きも伸びるのが期待動作)

トランジションを progress の割合で書くと、尺を伸ばしたときにフェードやタイピングが スローモーション化して破綻します。アウトロも本質は「終端に揃えること」であって速度を尺に 比例させることではないため、終端アンカーの実秒で書きます。

lua
-- NG: typing speed changes when the clip length changes
local visible = math.floor(mt.timeline.progress(ctx) * ctx.char_count)

-- OK: constant 0.08s per character regardless of clip length
local visible = math.floor(ctx.time / 0.08)

-- OK: outro fade over the last 0.5s, anchored to the clip end
local fade = mt.clamp(mt.timeline.remaining(ctx) / 0.5, 0.0, 1.0)

-- OK: 0.8s intro + 0.5s outro at fixed real-time speed
-- (compressed automatically only when the clip is shorter)
local intro, outro = mt.timeline.intro_outro_seconds(ctx, 0.8, 0.5)

1.5 ctx.font - 使用中フォントの寸法情報 ​

レイアウト生成後に確定した、使用中フォントのメトリクス(寸法情報)です。

フィールド型単位内容
em_sizenumbercanvas 高さ比変形前の1emの大きさ
ascentnumbercanvas 高さ比ベースラインから上方向のアセント
descentnumbercanvas 高さ比ベースラインから下方向のディセント(正値。下向きの量として表す)
line_heightnumbercanvas 高さ比行の高さ
units_per_emnumberフォント設計単位フォントの em 正方形の設計単位数

NOTE

画面上の最終サイズは scale 系フィールドの積で予測できます(2Dプリセット限定)。 フォントサイズはホストが内部で canvas.height に対する固定比率として計算しているため、 canvas解像度が変わっても同じ比率を保ちます。この基準サイズに character.scale × character.stretch_x/y・part.scale・ctx.global.scale × ctx.global.stretch_x/y を 掛け合わせたものが、2Dプリセットでは実際の画面上サイズと一致します(すべて乗算で 合成される変形だからです)。

3Dプリセットではこの積は近似にしかなりません。 カメラ投影が奥行き(z、 yaw/pitchによる見かけの奥行き変化、カメラの perspective / zoom を含む)に応じた 遠近除算を行うため、画面上サイズは奥行きに対して非線形に変化し、傾いた文字は 頂点ごとに歪みが生じて単一の倍率では表せません。ctx.fontとcharacter.geometry は投影前の値であり、投影後の画面上サイズはOnLayoutから取得できません。

1.6 ctx.text / ctx.char_count / ctx.part_count ​

ctx.textは廃止予定です。現在のテキストを参照するときはctx.global.textを使い、 書き換えるときはOnPreLayoutでctx.global.textへ代入してください。

ctx.char_countとctx.part_countは、それぞれレイアウト生成後の有効な本文の文字数とパーツ数を 表します。図形(§1.17)は数えず、ctx.shape_countで数えます。テキストやフォントを変更すると、シェイプ結果に応じて値も変わります。

1.7 ctx.meta ​

フィールド型単位内容
ctx.meta.api_levelinteger-Lua API互換レベル
ctx.meta.plugin_versionstring-実行中のプラグインバージョン(表示用)
ctx.meta.capabilitiestable-現在利用できる機能の情報。読み取り専用
ctx.meta.capabilities.has_3dboolean-3D Projectionが現在のプリセットで有効か
ctx.meta.limitstable-このインスタンスに適用される上限値。読み取り専用
ctx.meta.limits.max_charactersinteger-このインスタンスで扱える最大文字数
ctx.meta.limits.max_partsinteger-このインスタンスで扱える最大パーツ数
ctx.meta.limits.max_shapesinteger-このインスタンスで扱える最大図形数。図形は文字・パーツの上限を使わないため、全プリセット共通です
ctx.meta.instance_seedinteger-このインスタンス固有の安定した乱数シード(0以上2^31-1以下)。同一インスタンスでは生存期間中ずっと同じ値、別インスタンスでは別の値になります

機能の判定 ​

機能の有無はctx.meta.api_level >= 必要レベルとcapabilitiesで判定します。 has_3dがfalseでもCameraおよびyaw / pitch / zへの代入はエラーになりませんが、 描画には反映されません。

instance_seedの用途 ​

instance_seedをmt.randomのseedに使うと、同じスクリプトでもインスタンスごとに 異なる乱数列になります。

1.8 ctx.global ​

フィールド型単位内容
textstring-UTF-8テキスト。変更すると再シェイプし、文字・パーツ数を再生成します
font_namestring-フォントファミリー名(ctx.fontsのいずれか)。変更すると使用フォントを変更して再シェイプします
trackingnumberem各文字の後方送りに加算する文字送り。1.0は1 emです
line_spacingnumber倍率行/縦書き列の送り
verticalboolean-trueで縦書きにし、シェイプと配置方向を変更します
single_part_glyphboolean-trueでフォントグリフを1パーツ化し、半透明の輪郭交差部分が濃くなることと内部の縁取りを防ぎます。カスタムグリフ・カラー絵文字は対象外です。OnPreLayoutで変更するとレイアウトを再生成します。毎フレームInspectorの値から初期化されます(APIレベル15)。
h_alignstring-水平アラインメント。left / center / right
v_alignstring-垂直アラインメント。top / center / bottom / baseline
marginsnumber[]em各文字の後方送り。trackingと同じ単位です
emojitable-絵文字の配置とフォントの設定(下表)
position_x / position_ynumbercanvas正規化座標全体位置。0.5が中央で、Xは右、Yは上が正です
rotationnumberdegree2D全体回転。正(+)で右回り(時計回り)、負(-)で左回り(反時計回り)です
yaw / pitchnumberdegree3D全体姿勢。3Dプリセットのみ描画に反映されます。yawは正(+)で右端が手前へ、pitchは正(+)で上端が手前へ回転します
scalenumber倍率全体均等スケール。書き込み時に最小0.0001へクランプされます
stretch_x / stretch_ynumber倍率全体非均等スケール。scaleと異なり正の下限はなく、0や負値も受理されます
pivot_x / pivot_ynumbercanvas正規化変位全体変形のピボット。0.5で変位量0になり、大きいほどglobal.positionから右/上へ移動します
opacitynumber0-1全体の不透明度。既定値は1.0です。範囲外の値はホストが描画直前に0-1へクランプします。塗り・グラデーション・ストローク・シャドウ・バウンディングボックスすべてに、色が決まった後のアルファとして乗算されます(fill.useの判定には関与しません。use / opacity / fill.transparent の役割を参照してください)。ホスト側にキーフレームパラメータは存在せず、スクリプトからのみ書き込めます
filltable-全体塗り設定(下表)
gradienttable-グラデーション設定(下表)
stroketable-全体ストローク設定(下表)
shadowtable-全体シャドウ設定(下表)
texturetable-全体テクスチャ設定(下表)
blurtable-全体の文字そのもののぼかし設定(下表)

Inspectorの本文に入力した \n・<br>・<br/>・<br /> は、OnPreLayout より前に実際の改行文字(LF)へ変換されます。CRLFもLFになります。\\n と \<br> は文字としての \n と <br> になります。ctx.textも同じ解釈済みテキストを参照します。

OnPreLayoutで代入したテキストは改行表記を再解釈しません。Luaでは "A\nB" または複数行文字列で実際の改行を作り、文字としての \n は "A\\nB" と書いてください。カスタムグリフの宣言・挿入後に文字配列を生成し、改行自体は ctx.chars に含めません。

ctx.global.margins ​

インデックスと計算 ​

marginsは、レイアウト順の文字番号をキーとする1始まりの配列です。この番号は、 あとでctx.charsに付くindexと同じです。margins[i]はi番目の文字の後ろの送りへ、 trackingと合わせてem単位で加算されます。

text
(margins[i] + tracking) * designUnitsPerEm
配列形式 ​

キーは1以上の整数、値は数値にしてください。非整数キー、文字列キー、0以下のキー、数値以外の値はエラーになります。 途中の番号を省略しても構いません。省略した番号は0(余白なし)として扱われるため、margins[2]だけの代入や { [2] = 0.5 }のようなテーブルも有効で、margins[1]は0になります。

OnPreLayoutのctx.global.marginsはctx.meta.limits.max_characters個の要素を持ちます。そのため #ctx.global.marginsは文字数ではありません。この上限を超える番号はどの文字にも届かないため、エラーにならず 無視されます。

文字数 ​

OnPreLayoutではctx.char_countが未定義です。utf8.len(ctx.global.text)で得られるのは UTF-8コードポイント数であり、結合文字、合字、書記素クラスタなどにより、シェイプ後の 文字数と一致しない場合があります。正確な個数が必要な処理はOnLayoutで行ってください。

サブオブジェクトのマージ ​

ctx.global.shadow = { enabled = true, distance = 0.8 }のようにテーブル全体を代入すると、 フィールドごとにマージされます。省略したフィールドは現在値を維持します。

ctx.global.fill ​

NOTE

color型

colorはr(赤)、g(緑)、b(青)、a(アルファ)を持つテーブルです。 各フィールドは0-1のnumberで、a = 0は完全な透明、a = 1は完全な不透明を表します。

フィールドへ直接代入できるほか、テーブル全体を代入するときは変更するフィールドだけを 記載できます。省略したフィールドは現在値を維持します。

lua
ctx.global.fill.color.r = 1.0
ctx.global.fill.color = { a = 0.5 }

r / g / b / a以外のフィールドや、number以外の値はエラーになります。

フィールド型単位内容
colorcolorRGBA 0-1全体の塗り色。グラデーションの始端色も兼ねます
transparentboolean-trueにすると、ストロークや効果を残して塗りを非表示にします

chars[index].fill.useがfalseの文字にはfill.colorが使われます。 パーツまで含めた継承順は「継承の仕組み」を 参照してください。

ctx.global.gradient ​

フィールド型単位内容
color_spacestring-グラデーション/Crayonモード。値は下記の列挙値です
end_colorcolorRGBA 0-1グラデーション終端色
midpointnumber0-1色補間の中点
anglenumberdegreeグラデーション方向。0度で左から右に進み、正(+)で右回り(時計回り)に回転
start_position / end_positionnumber変形後の全体範囲に対する相対位置グラデーション区間。標準は0.0〜1.0です。詳しくはグラデーションの範囲と向きを参照してください

gradient.color_space の値:

  • none
  • okhsv
  • okhsl
  • oklab
  • linear_rgb
  • oklch_short - API Level 11。OKLCHの短い色相経路。
  • oklch_long - API Level 11。OKLCHの長い色相経路。
  • crayon

ctx.global.texture ​

塗りに重ねるマテリアル(質感)です。p1〜p4 はマテリアル共通の汎用コントロールで、意味は選んだ type によって変わります。

フィールド型単位内容
useboolean-継承したテクスチャの代わりに自身のテクスチャを使うか。ctx.global では無視され、ctx.chars[i] / ctx.parts[i] でのみ意味を持ちます
typestring-マテリアルの種類。値は下記の列挙値です
p1number素材による第1コントロール
p2number素材による第2コントロール
p3number素材による第3コントロール
p4number素材による第4コントロール
p5number素材による第5コントロール。halftone・halftone_diamond・colored_pencil・prism_foil・iridescent・metallic だけが読みます。halftone 系では Fade の向きを度で表し(0 で下へ向かって濃くなる)、colored_pencil では光が来る画面上の方向を度で表します(0 が右、90 が下)。prism_foil ではタイルの並ぶ向きを度で表します(0 でパーツの x 軸方向)。iridescent では膜厚のムラを 0〜1 で表します(0 で一様な膜)。metallic ではヘアラインの角度を度で表します(0 でパーツの x 軸方向)。ほかの素材は無視します。初期値は 0(API レベル 14)
colorcolorRGBA 0-1マテリアルが塗りの上に加えるものの色。stained_glass では鉛線、glitter では金属片、stripe では縞、halftone では点、prism_foil では箔(白で銀)、それ以外では光の色です。白の場合、光はマテリアルのまま、鉛線は白になります(iridescent は無視します)

texture.type の値と、p1〜p4 の意味:

typep1p2p3p4
none----
water_droplet厚み丸み光沢光の角度
air_cushion膨らみ圧着幅皺光の角度
glitterフレークサイズ光る粒の割合粒の量光の角度
iridescent膜厚色相幅強度光の角度
faceted面の数面取りの深さ磨き光の角度
stained_glassガラス片の大きさ鉛線の太さ色相幅Glow
metallic磨き起伏反射コントラスト光の角度
metallic_2磨き起伏露出光の角度
stripe縞の密度(本数)縞の太さ縞の濃さ縞の向き(度)
colored_pencil白い線の密度白い線の長さ光の強さ線の向き(度)
halftone・halftone_diamond点の密度(個数)点の大きさ減衰の強さ格子の向き(度)
prism_foilタイルの大きさ虹色の量箔の濃さ光の角度(画面上の度)

Flake Amount は全体の粒の量です。0 で粒とグローなし、1 で最大密度になります。色相幅は従来の Hue Range 1.0 相当で固定です。

光る粒には白寄りの芯と柔らかなグローが付きます。グローは文字の輪郭内に描かれ、Highlight Ratio で光る粒とともに増減します。

p1〜p4 はいずれも汎用スロットで、範囲も単位もマテリアルが決めます。多くは 0〜1 ですが、たとえば光の角度は度で読まれます。マテリアルは受け取った値を自身が扱える範囲へ丸めてから使うため(角度のように一周するものは繰り返し、上限があるものは端で止まります)、範囲外の値を書いても保存値やキーフレームは書き換えられません。

テクスチャは全体・文字・パートの3段で継承されます。ctx.chars[i].texture / ctx.parts[i].texture に use = true を設定すると、その要素だけ別のマテリアルに差し替えられます。文字やパート側はホストのパラメータを持たないスクリプト専用の値のため、スクリプトが設定しない限り常に未使用として読み取られます。

ctx.global.blur ​

文字そのもの(塗り・グラデーション・テクスチャ・ストローク・クレヨン)をまとめてぼかします。シャドウはこの設定ではぼけません。シャドウには専用の shadow.blur_x / blur_y があります。バウンディングボックスはぼけません。

フィールド型単位内容
useboolean-継承した値の代わりに、この要素自身のぼかしを使うかどうか。use を持たない ctx.global では無視され、ctx.chars[i] / ctx.parts[i] でのみ意味を持ちます
amount_xnumberem水平方向のぼかし(ガウスのσ)。1.0 = 1 em。0 で水平方向の縁はぼけません。書き込み時は 0〜10 に丸められます
amount_ynumberem垂直方向のぼかし。単位と範囲は amount_x と同じです
glownumber-グローの強さ。ぼかした文字を明るく持ち上げて発光させ、色が飽和した芯は白に近づきます。0 でグローなし。文字がぼけていないときは効果がありません。書き込み時は 0〜10 に丸められます

ぼかしはパーツ自身の空間で、canvasの軸方向に測るため、shadow.distance と同じくパーツの拡縮・stretch・遠近に追従します。ぼかしは、全体・文字・パーツの3段で継承されます。ctx.chars[i].blur / ctx.parts[i].blur で use = true にすると、その要素だけ自身のぼかしを使います。文字とパーツの値はスクリプト専用(ホスト側パラメータの裏付けなし)のため、スクリプトが設定するまでは常に未使用で、継承する値と同じ値として読み取られます。シャドウのぼかしはシャドウ色と同じ shadow.use に従うため、1つのパーツのぼかしだけを上書きするには継承した色を書き戻します。その色は mt.shadow.resolve(ctx, target, { level = "character" }) が返します。

ctx.global.stroke ​

フィールド型単位内容
widthnumberem(1.0 = フォントサイズ 1 em。描画時に fontSize を掛ける)ストロークの太さ
gapnumberem(1.0 = フォントサイズ 1 em)塗りとストロークの間隔
colorcolorRGBA 0-1ストローク色
outer_widthnumberem(1.0 = フォントサイズ 1 em)Inner Strokeの外側に隣接するOuter Strokeの太さ。width > 0のときだけ有効
outer_colorcolorRGBA 0-1Outer Strokeの色
orderstring-塗りとストロークの重なり順。fill_over_stroke / stroke_over_fill / fill_over_stroke_per_character
joinstring-ストローク角の接続方式。miter_clip / round / bevel / miter_round / miter_bevel
miter_limitnumber倍率鋭いmiter角の最大長

fill_over_stroke_per_characterはfill_over_strokeと同じ重なり(塗りがストロークの上)を、 文字ごとに完結させて描画します。描画順で同じ文字番号が連続する範囲ごとに全パスを終えてから 次の範囲へ進むため、各文字が自分のストロークを自分の塗りで隠した状態で完成します。 文字を重ねたとき、後続の文字のストロークが先行する文字の塗りの上に乗ることがありません。 文字番号による並べ替えは行わないため、描画順がA A B Aなら3つの範囲になります。 Gapがある場合、その消去はその範囲の内側だけに閉じ込められ、先行文字を削りません。 3D投影が有効なフレームは、orderの指定に関わらず常にこの文字単位描画になります。 Crayonは従来どおり通常描画の後にまとめて描かれるため、この設定の対象外です。

シミュレータのCanvasプレビューはorderの合成を再現しません。 選択・保存・スクリプトからの読み書きは動作しますが、 重なりの最終的な見え方はプラグイン本体の描画結果で確認してください。

chars[index].stroke.useがfalseの文字には、上記の全体ストローク設定が使われます。 パーツまで含めた継承順は「継承の仕組み」を 参照してください。

ctx.global.shadow ​

NOTE

このシャドウは、文字・パーツと同じ形状を distance/angle の位置へオフセットしたコピーで、 blur_x/blur_y でぼかせます(どちらも既定値は 0 で、輪郭が鮮明なままです)。サイズは 本体と常に等倍のため、distance = 0 でぼかしも無い場合は本体テキストの真後ろに完全一致で重なり、 見た目にはシャドウが全く見えません(縮小されて透けて見える、といった挙動にはなりません)。

フィールド型単位内容
enabledboolean-全体シャドウの有効状態
distancenumberemシャドウ距離。1.0 = 1 em。パーツ自身の空間で測るため、拡縮・stretch・回転・遠近があってもシャドウは文字から同じ距離に見える。angle で決めた方向は canvas 上で固定される。正で angle 方向へ遠ざかる。書き込み時の上限は10.0
anglenumberdegreeシャドウ方向。0度で右方向、正(+)で右回り(時計回り)に回転(90度で真下方向)
blur_x / blur_ynumberemシャドウのぼかし(ガウスのσ)。1.0 = 1 em。書き込み時は 0〜10 に丸められます
glownumber-グローの強さ。ぼかしたシャドウを明るく持ち上げて発光させ、色が飽和した芯は白に近づきます。0 でグローなし。シャドウがぼけていないときは効果がありません。書き込み時は 0〜10 に丸められます
colorcolorRGBA 0-1シャドウ色

chars[index].shadow.useがfalseの文字にはshadow.colorが使われます。 パーツまで含めた継承順は「継承の仕組み」を 参照してください。

WARNING

シャドウを有効にすると描画負荷が増え、レンダリング性能が低下します。 特に高解像度や複雑なテキストでは影響が大きくなるため、必要な場合だけ使用してください。

グラデーションが塗るのは、文字・パーツのfill.useがどちらもfalseの部分だけです。 fill.useがtrueの個別色はグラデーションより優先され、単色になります。 fill.useとopacityの段階分けは 「継承の仕組み」を参照してください。

ctx.global.emoji ​

ホストのText Settings内「Emoji」グループに対応します。OnPreLayoutで書き換えられ、OnLayout・OnPathでは読み取りのみです。

フィールド型単位内容
offset_x / offset_ynumberem(1.0 = フォントサイズ 1 em)フォントが置く位置からの絵文字のずらし量。Yは上が正です。文字送りは変わりません
scalenumber倍率本文の何倍のフォントサイズで絵文字を組むか。文字送りも一緒に変わります。書き込み時に最小0.001へクランプされます
use_custom_fontboolean-trueでfont_nameのフォントを使います。falseならシステムの絵文字フォント(Windows: Segoe UI Emoji、macOS: Apple Color Emoji)です
font_namestring-カスタム絵文字フォント(ctx.fontsのいずれか)。use_custom_fontがfalseの間は値を保持したまま無視されます。見つからない名前はシステムの絵文字フォントになります
use_outlineboolean-trueでカスタムフォントの輪郭から絵文字を描きます。use_custom_fontがtrueのときだけ効きます

WARNING

どの値も、変えるとレイアウトを作り直します(変形中の絵文字は画像も作り直します)。 フレームごとに変化させると描画が大きく遅くなるため、固定値で使ってください。

use_outlineが効いている絵文字は通常の文字として扱われ、塗り色・グラデーション・テクスチャ・ストローク・シャドウが本文と同じように効きます。 輪郭を持たないグリフ(カラー専用のグリフなど)は、パーツを持たない文字になり何も描かれません。

シミュレータは絵文字を簡易表示します。絵文字のシーケンスを1文字1パーツにまとめ、offset_x / offset_y / scaleで配置し、ブラウザの絵文字フォントで描きます。 カスタム絵文字フォントの読み込みやuse_outlineの輪郭描画は行わず、3Dプリセットでは絵文字の四角だけを表示します。最終的な見た目はプラグイン本体で確認してください。

1.9 ctx.camera ​

3Dプリセットのカメラです。2Dプリセットでも代入はエラーになりませんが、描画に反映されるのは 3Dプリセットだけです。

フィールド型単位内容
target_x / target_ynumbercanvas正規化座標カメラ注視点。Xは右、Yは上が正です。注視点が動くとオブジェクトは逆方向に動いて見えます
yaw / pitchnumberdegreeカメラの旋回。yawは正(+)でカメラが右に回り込み、pitchは正(+)で上に回り込む(見下ろす)
perspectivenumber-カメラ距離/遠近感を表す強度。内部でカメラ距離distancePx = f(perspective) * canvas.heightに写像されます(fは強度から距離係数への単調写像で、大きいほどカメラが近づき遠近が強くなります)。0〜1に丸められます。カメラのどの項目も有限である必要があり、NaN・infを書くとエラーです
zoomnumber倍率投影拡大率。書き込み時に最小0.001へクランプされます
lens_shift_x / lens_shift_ynumbercanvas比率主点移動。lens_shift_xの正(+)で全体が右、lens_shift_yの正(+)で全体が上にシフト

1.10 ctx.chars[index] ​

ctx.charsはLua標準どおり1始まりの配列です。テキストやフォントが変わると、 文字数と各要素のindexも変わります。

fill / stroke / shadowのuseがfalseの場合は非表示になるのではなく、 グローバル値を継承します。詳しくは 「継承の仕組み」を参照してください。

フィールド型単位内容
indexinteger-1始まりの文字index。読み取り専用
textstring-この文字クラスタの元テキスト。読み取り専用
part_start / part_countinteger-所有パーツの先頭グローバルindex(1始まり)と個数。読み取り専用
line_indexinteger-属する行の1始まりindex。読み取り専用
geometrytable-変形前の配置情報(下記)。読み取り専用
offset_x / offset_ynumbercanvas正規化変位文字の移動量。0.5で変位量0になり、大きいほど右/上へ移動します
pivot_x / pivot_ynumbercanvas正規化変位文字変形の支点。0.5で自然中心になり、大きいほど右/上へ移動します
scalenumber倍率均等スケール。書き込み時に最小0.001へクランプされます
stretch_x / stretch_ynumber倍率非均等スケール。scaleと異なり正の下限はなく、0や負値も受理されます
rotationnumberdegree2D回転。正(+)が時計回り(右回り)、負(-)が反時計回り(左回り)です
znumbercanvas高さ比奥行き。正(+)で奥(カメラから遠ざかる)方向、負(-)で手前(カメラに近づく)方向です。3Dプリセットのみ描画に反映されます
yaw / pitchnumberdegree3D個別回転。yawは正(+)で右端が手前へ、pitchは正(+)で上端が手前へ回転します。3Dプリセットのみ描画に反映されます
opacitynumber0-1この文字の不透明度。既定値は1.0で、範囲外の値はホストが描画直前にクランプします。ctx.global.opacityと乗算されます(fill.useの判定には関与しません。役割分担を参照してください)
z_indexnumber-図形(ctx.shapes)専用の描画順の値です。本文の文字では無視されます(書き込みは受理されますが、描画順に影響しません)
filltable-個別塗り(下表)
stroketable-個別ストローク(下表)
shadowtable-個別シャドウ色(下表)
texturetable-個別テクスチャ。ctx.global.texture と同じ構造に use が付きます
blurtable-文字の個別ぼかし。ctx.global.blur と同じ構造に use が付きます

chars[index].fill ​

フィールド型単位内容
useboolean-trueならfill.colorを使います
colorcolorRGBA 0-1useがtrueのときに使う個別色

chars[index].stroke ​

フィールド型単位内容
useboolean-trueならInner / Outerを含む個別ストローク設定を使います
widthnumberem(1.0 = フォントサイズ 1 em)useがtrueのとき
gapnumberem(1.0 = フォントサイズ 1 em)useがtrueのとき
colorcolorRGBA 0-1useがtrueのとき
outer_widthnumberem(1.0 = フォントサイズ 1 em)Inner Strokeの外側に隣接するOuter Strokeの太さ。width > 0のときだけ有効
outer_colorcolorRGBA 0-1Outer Strokeの色

chars[index].shadow ​

フィールド型単位内容
useboolean-trueならshadow.color、blur_x、blur_y、glowを使います
colorcolorRGBA 0-1useがtrueのときに使う個別色
blur_x / blur_ynumberemuseがtrueのときに使うシャドウの個別ぼかし。設定するまでは継承した値が読み取れます。書き込み時は 0〜10 に丸められます
glownumber-useがtrueのときに使うシャドウの個別グローの強さ。設定するまでは継承した値が読み取れます。書き込み時は 0〜10 に丸められます

サブオブジェクトへのテーブル全体代入は、§1.8と同じマージ規則です。

chars[index].geometry ​

文字のスクリプト変形、Deform、3D投影より前のレイアウトを表します。

位置と寸法はcanvas正規化です。内部画素座標からは Xを0.5 + px/width、Yを0.5 - px/heightとして変換します。

フィールド型単位内容
canvas_origin_x / canvas_origin_ynumbercanvas 正規化位置組版原点(横書き: セル左端 × ベースラインに相当する placement origin)
vertical_origin_x / vertical_origin_ynumbercanvas 正規化位置縦組み原点(列中心軸 × セル上端)
bounds_center_x / bounds_center_ynumbercanvas 正規化位置変形前の文字輪郭が占める範囲(ink bounds)の中心
bounds_widthnumbercanvas 幅比ink bounds の幅 / canvas 幅
bounds_heightnumbercanvas 高さ比ink bounds の高さ / canvas 高さ
advance_xnumbercanvas 幅比フォントの水平送り(px)/ canvas 幅。tracking / margins を含まない
advance_ynumbercanvas 高さ比フォントの垂直送り(px)/ canvas 高さ(符号反転して Y-up)。下方向送りは負。tracking / margins を含まない

スペースなど輪郭を持たない文字は ink bounds が潰れるため、代わりにフォント定義の文字セルを 返します。組版の流れ方向(横書きならX、縦書きならY)はその文字自身の送りが幅・高さになり、 交差軸はセルの高さ(横書き)/列幅(縦書き)になります。これにより、スペースの bounds_center_y が隣の文字より半セル下にずれることはありません。

1.11 ctx.parts[index] ​

ctx.partsはLua標準どおり1始まりの配列です。indexは文字ごとの番号ではなく、 フレーム全体を通したパーツ番号です。テキストやフォントが変わると、パーツ数と各要素の indexも変わります。

フィールド型単位内容
indexinteger-1始まりのグローバルパーツindex。読み取り専用
character_indexinteger-所有文字の1始まりindex。読み取り専用
index_in_characterinteger-文字内での1始まりパーツindex。読み取り専用
geometrytable-変形前の配置情報(下表)。読み取り専用
offset_x / offset_ynumbercanvas正規化変位パーツの移動量。0.5で変位量0になり、大きいほど右/上へ移動します
pivot_x / pivot_ynumbercanvas正規化変位パーツ変形の支点。0.5で自然位置になり、大きいほど右/上へ移動します
scalenumber倍率均等スケール。書き込み時に最小0.001へクランプされます
rotationnumberdegree2D回転。正(+)が時計回り(右回り)、負(-)が反時計回り(左回り)です
stretch_x / stretch_ynumber倍率非均等スケール。scaleと異なり正の下限はなく、0や負値も受理されます
znumbercanvas高さ比奥行き。正(+)で奥(カメラから遠ざかる)方向、負(-)で手前(カメラに近づく)方向です。3Dプリセットのみ描画に反映されます
yaw / pitchnumberdegreeパーツ個別の3D回転。パーツpivotを中心に、所有文字の回転済み空間の内側で適用されます。yawは正(+)で右端が手前へ、pitchは正(+)で上端が手前へ回転します。3Dプリセットのみ描画に反映されます
opacitynumber0-1このパーツの不透明度。既定値は1.0で、範囲外の値はホストが描画直前にクランプします。所有文字のopacity(さらにctx.global.opacity)と乗算されます(fill.useの判定には関与しません。役割分担を参照してください)
filltable-use / colorを持つ個別塗り。文字のfillと同じ構造で、useがtrueならcolorを採用します
stroketable-use / width / gap / color / outer_width / outer_colorを持つ個別ストローク。文字のstrokeと同じ構造で、useがtrueなら個別値を採用します
shadowtable-use / colorを持つ個別シャドウ色。文字のshadowと同じ構造で、useがtrueならcolorを採用します
texturetable-個別テクスチャ。文字のtextureと同じ構造で、useがtrueならそのマテリアルを採用します
blurtable-文字の個別ぼかし。文字のblurと同じ構造で、useがtrueならamount_x / amount_y / glowを採用します

文字からの継承 ​

パーツの塗り・ストローク・シャドウは、それぞれのuseによって次のように決まります。

パーツの設定use = falseuse = true
fill所有文字の段階で選ばれた塗りを継承しますパーツのfill.colorを使います
stroke所有文字の段階で選ばれたInner / Outer設定を継承しますパーツのstroke設定を使います
shadow所有文字の段階で選ばれたshadow.colorを継承しますパーツのshadow.colorを使います

所有文字でもuse = falseの場合は、さらにctx.globalの設定まで遡ります。詳しくは 「継承の仕組み」を参照してください。

インスペクタにない個別設定 ​

パーツのstrokeとshadowにはインスペクタ上のパラメータがなく、初期状態は 未使用/既定値です。スクリプトでuseをtrueにすると、設定した個別値が優先されます。

yaw / pitchもインスペクタにはなく、初期値は0です。所有文字の回転とは独立しており、 文字の回転空間内で追加の回転として適用されます。

parts[index].geometry ​

スクリプト変形、Deform、3D投影より前のレイアウトを表します。Yは上が正です。

フィールド型単位内容
local_center_x / local_center_ynumbercanvas 軸比の変位所有文字の変形前の輪郭範囲(ink bounds)の中心を原点としたパーツ中心。中立オフセットなし(0が文字中心上)。Y成分はY-up
canvas_center_x / canvas_center_ynumbercanvas 正規化位置パーツ自然位置(レイアウト後の中心)の canvas 座標
bounds_center_x / bounds_center_ynumbercanvas 正規化位置変形前のパーツ輪郭が占める範囲(ink bounds)の中心
bounds_width / bounds_heightnumber各 canvas 軸比ink bounds の幅・高さ

1.12 ctx.bounding_box ​

InspectorでOFFのBBをスクリプトから有効化するときは、各辺・線幅・余白・色・塗り・opacity・cap・offsetなど、演出に必要な設定を明示してください。本体はOFFのBBについて現在のInspector値を読み込まないため、これらのフィールドをスタイルの初期値として参照しないでください。

基準矩形 ​

2Dの基準矩形はGlobal回転前の変換済みFill境界を囲み、本文と同じGlobal回転を適用します。3Dではglobal layout plane上で組み立てて投影します。 その外側へmarginを加え、fillとstrokeをそれぞれ独立したoffsetでずらして描画します。

寸法の基準 ​

次の寸法系フィールドはfontSizeに対する百分率です (描画: value * fontSizePx / 100。100.0 = fontSizeと同じ長さです)。

フィールド型単位内容
enabledboolean-枠の描画を有効にする
draw_top / draw_bottom / draw_left / draw_rightboolean-各辺のストロークを描くか
colorcolorRGBA 0-1枠線色
widthnumberfontSize 百分率枠線の太さ
fill_enabledboolean-枠内塗りを有効にする
fill_colorcolorRGBA 0-1枠内塗り色(アルファに fill_opacity を乗算)
fill_opacitynumber0-1枠内塗りの不透明度乗数
start_cap / end_capstring下記列挙開いたパス端のキャップ
margin_x / margin_ynumberfontSize 百分率テキスト bounds 外側への余白(各辺に加算)
corner_radiusnumberfontSize 百分率四辺すべて有効時の角丸半径(矩形の半分で上限)
fill_offset_x / fill_offset_ynumberfontSize 百分率塗り矩形の平行移動
stroke_offset_x / stroke_offset_ynumberfontSize 百分率枠線の平行移動(塗りと独立)

start_cap / end_cap の値: butt / square / round / round_rev / triangle / triangle_rev

1.13 ctx.output ​

OnLayoutで読み書きする出力フィルタ・描画順制御です。Separation系のみ読み取り専用です。

フィールド型単位内容
separation_enabledboolean-Separation出力が有効か。読み取り専用
render_modestring-現在の出力スロット。default / separation_1 / separation_2。読み取り専用
targets_1 / targets_2string-各Separation出力に割り当てられたターゲット指定文字列。読み取り専用
write_on_modestring-Write-onの単位。characterまたはpart
write_on_startnumber0-1表示区間の始端(正規化進行度)
write_on_endnumber0-1表示区間の終端。start = 0かつend = 1のときフィルタなし(全表示)
reorder_partsboolean-trueのときパーツの描画順・reveal順を書き順(stroke order)にします。単一パーツ文字では見た目に影響しません
manual_order_enabledboolean-trueのときmanual_order_textでreveal / 描画順を上書きします
manual_order_textstring-手動順の指定(下記構文)
force_disable_3d_projectionboolean-trueのとき、そのフレームの3D投影を最終的に無効化します。既定値はfalse(API Level 7)

2D専用スクリプト ​

ctx.output.force_disable_3d_projection = trueを指定すると、プリセットが3D対応でも2D描画経路を使用します。Camera、Global、Character、Partに対するインスペクタ設定とキーフレームを含め、すべての3D操作が無視されます。現在の3D値が偶然ニュートラルであることを理由に設定せず、作品を2D専用にすることが明確な場合にだけ使用してください。

lua
function OnLayout(ctx)
    -- This effect intentionally guarantees 2D output.
    ctx.output.force_disable_3d_projection = true
end

Write-on ​

表示対象は、単位ごとの1始まりの順位が[startLimit, endLimit]に入る要素に限られます。

text
startLimit = floor(write_on_start * N) + 1
endLimit   = ceil(write_on_end * N)

Nはwrite_on_mode == "character"のとき文字数、"part"のときパーツ数です。

順位の取り方:

mode既定の順位manual_order_enabled 時reorder_parts のみ
characterレイアウト順の文字 index(1..N)文字レベルの manual reveal 順文字順位はレイアウト順のまま
partctx.parts[index].index(1..N)パーツの manual reveal 順stroke order の reveal 順

manual_order_text 構文 ​

トークンの解釈 ​

トークンはカンマまたは空白で区切ります。無効なトークンは無視され、同じパーツを 複数回指定した場合は最初の指定だけが採用されます。

トークン意味
c<n> / C<n>1 始まり文字 n。その文字の全パーツを、当時のパーツ順(reorder_parts が true なら stroke order、false ならレイアウト順)で展開
p<n> / P<n>1 始まりグローバルパーツ n
<n>プレフィックス無し。パーツ index として解釈
<a>-<b>両端を含む範囲。両端は同じ種別(文字同士またはパーツ同士)。片方だけプレフィックスがある場合は他方に種別を継承。展開は昇順

例: "3,1,2"(パーツ 3→1→2)、"c1-c3"(文字 1〜3)、"p2-p5"(パーツ 2〜5)。

順序への反映 ​

指定された要素は指定順で先頭へ移動します。未指定パーツは非表示にならず、 基準順序での相対順を保って後ろへ続きます。

順序は未変形のレイアウトと指定文字列から決まり、アニメーション後の空間位置から フレームごとに再計算されません。write_on_start/endは表示範囲を決め、 manual orderは要素の順序だけを変更します。

2Dの描画順にはmanual orderがそのまま適用されます。3Dでは各パーツの奥行きを優先し、 奥行きが同じパーツをmanual order、stroke order、レイアウト順の優先順位で並べます。 Write-onのreveal順は2D/3Dとも常にmanual orderに従います。

1.14 ctx.paths ​

ctx.pathsは対象を遅延取得するため、取得しなかったパーツのパスはLua側へコピーされません。ctx.pathsはOnPathの呼び出しの間だけ有効です。変数に保存して、あとの呼び出しで使うとエラーになります。

フィールド型単位内容
units_per_emnumberpath unit/emパス座標のスケール。常に1000
part(index)function-1始まりの通しパーツ番号から1パーツを取得。存在しなければnil
character(index)function-1始まりの文字番号が所有する全パーツを、通しパーツ番号順の配列で取得
select(selector)function-選択書式に一致するパーツを、通しパーツ番号順の配列で取得
shape(number)function-1始まりの図形番号の図形が持つパーツを、1要素の配列で取得。その番号の図形が無ければ空の配列。part・character・selectは本文だけを対象にします

select(selector)の選択書式 ​

cは文字番号、pは通しパーツ番号、!は除外を表します。カンマで複数の条件を 指定でき、c3-5やp8-10のような範囲にも対応します。

lua
local parts = ctx.paths:select("c1, p8-10, !p9")

同じパーツを複数回取得した場合、同一フレーム内では同じ可変オブジェクトが返されます。

取得したパーツ ​

フィールド型単位内容
indexinteger-フレーム全体の1始まり通しパーツ番号
character_indexinteger-所属文字の1始まり番号
index_in_characterinteger-所属文字内の1始まりパーツ番号
line_indexinteger-所属行の1始まり番号
textstring-所属文字が表すテキスト
pathpath-変更対象の描画パス

pathの編集 ​

pathはパーツの描画輪郭を表す可変オブジェクトです。元の輪郭を消去・置換したり、 直線やベジェ曲線を追加したりできます。メソッドと座標系の詳細は 描画パス編集APIを参照してください。

1.15 ctx.glyphs ​

APIレベル: 9+

ctx.glyphs:declare(declaration) ​

ctx.glyphs:declare(declaration)は、パスと文字メトリクスを持つカスタムグリフを宣言し、 ctx.global.textへ埋め込める1文字のプレースホルダー文字列を返します。 レイアウト生成前に宣言を確定する必要があるため、OnPreLayoutでのみ呼び出せます。

この宣言は2つの座標空間を扱います。形状を描くpathは既存の描画APIと同じY-down、 形状を配置するadvance_*とboundsは既存のgeometry APIと同じY-upです。 したがって、縦書きで下方向へ900 units送る場合はadvance_y = -900と指定します。

fieldtype既定値単位・内容
pathMtDrawingPath空パス初期形状。Part中心原点、Y-down、1000 units = 1 em
advance_xnumber0.0水平送り。右が正、1000 units = 1 em
advance_ynumber0.0垂直送り。上が正、1000 units = 1 em。縦書きの下方向送りは負
boundsnumber[4]pathから自動算出{minimumX, minimumY, maximumX, maximumY}。ベースライン原点、Y-up、1000 units = 1 em

boundsを省略すると、Part中心のXをadvance_x / 2へ置き、pathの最下端をベースラインへ 揃えます。自動boundsは{ advance_x / 2 + pathMinimumX, 0, advance_x / 2 + pathMaximumX, pathMaximumY - pathMinimumY }です。このためmt.svg_pathで view_boxを指定して中心原点へ正規化したSVGアイコンは、寸法を重複指定せずそのまま利用できます。 pathが空の場合は{0,0,0,0}になります。advance_yは送りメトリクスであり、横書きの自動配置には使いません。

縦書きでは、横書き用のベースライン位置にかかわらず、字面中心をadvance_yが作るセルの中央へ 配置します。trackingと個別marginsはセルの後方余白なので字面中心には含めません。 advance_y = 0の場合は現在の縦書きpen位置へ字面中心を置きます。

幅も高さも0のbounds(例:{0,0,0,0})は「描画はするが測らないグリフ」として扱い、 h_align / v_alignが参照する整列ボックスから除外します。送りを持たない装飾マーカーを テキスト末尾へ追加しても、行が整列端から動きません。整列は送りではなくboundsで決まるため、 負のmarginsで送りを打ち消してもこの除外の代わりにはなりません。

boundsを明示すると、その中心をPart中心として使用します。ベースラインより下が負、上が正です。 たとえばベースラインから上へ700 units、左右へ500 units広がる図形は { -500, 0, 500, 700 }と指定します。パス座標だけは既存の描画パスAPIと同じY-downです。

lua
local icon = mt.svg_path("M 2 2 L 22 2 L 22 22 L 2 22 Z", {
    view_box = { 0, 0, 24, 24 },
    em_scale = 0.8,
})

function OnPreLayout(ctx)
    local marker = ctx.glyphs:declare({
        path = icon,
        advance_x = 1000,
        advance_y = -1000,
    })
    ctx.global.text = "A" .. marker .. "B"
end

pathは宣言時点のsnapshotです。宣言後に元のパスを変更しても、宣言済みの形状は変わりません。 pathを省略しboundsを指定すると、送り幅とboundsだけを持つ不可視文字として使用できます。同じカスタムグリフを 複数箇所へ置く場合は、返されたmarkerを複数回テキストへ埋め込みます。 advance_xとadvance_yは、trackingと個別marginsを含まない純粋なグリフ送りです。 カスタムグリフにも通常文字と同じく、その文字の後方送りへtrackingと対応するmarginsを加算します。 このためadvance_x = 0でも、横書きではtracking + margins[i]分の送りが残ります。

プレースホルダーはホストがUnicode私用領域のU+E002から宣言順に割り当てます。U+E000と U+E001は内部の改行処理用に予約されています。カスタムグリフも通常文字と同じ文字数・パーツ数の 上限を消費します。hookまたはcommitが失敗したフレームでは、そのフレームの宣言をすべて破棄します。

1.16 ctx.inputs ​

ctx.inputsはInspectorのScript Inputsで設定した値を全コールバックへ渡す読み取り専用objectです。 各配列は1始まりで、要素数は固定です。

フィールド型要素数内容
numbersnumber[]14単位を持たない数値入力
colorsMtColor[]8RGBA色入力
textsstring[]4単一行のテキスト入力
booleansboolean[]8checkboxの真偽値入力
lua
local amount = ctx.inputs.numbers[1]
local primary = ctx.inputs.colors[1]
local caption = ctx.inputs.texts[1]
local enabled = ctx.inputs.booleans[1]

ctx.inputs、各配列、色の各channelはすべて読み取り専用です。配列外のindexはnilを返します。

1.17 ctx.shapes ​

ctx.shapesは、本文とは別に置く図形(背景、枠、飾りなど)を扱います。図形はctx.global.textに 含まれず、送り幅・整列・折り返しといったレイアウトの流れに入りません。ctx.chars・ctx.char_count・ ctx.parts・ctx.part_countは本文だけを数え、図形はctx.shapes[number]・ctx.shape_countで扱います。

図形はOnPreLayoutで宣言し、OnLayoutとOnPathでは1始まりの図形番号で読みます。

ctx.shapes:declare(declaration) ​

図形を1つ宣言し、1始まりの図形番号(宣言した順)を返します。OnPreLayoutでのみ呼び出せます。 未知のフィールドや不正な値はエラーになります。

fieldtype既定値内容
pathMtDrawingPath空パス図形の輪郭。図形の位置が原点、Y-down、1000 units = 1 em(カスタムグリフのpathと同じ座標系)
layerstring"back""back"は本文より後ろ、"front"は本文より前に描く
parentintegerなし親にする図形の番号。先に宣言した図形(このdeclareより前の戻り値)に限ります。省略すると親なしです
camerainteger親のカメラ。なければなしこの図形を3Dで投影するカメラの番号。先にctx.shape_cameras:declare()で宣言したものに限ります。親のある図形は親のカメラを引き継ぎ、親と違う番号を指定するとエラーです(カメラのない親の子も指定できません)。カメラのない図形は、これまでどおりキャンバスに固定されます

pathは宣言時点のsnapshotです。同じ層の図形は、z_indexが小さい順、同じなら宣言した順に重なります。

parentを指定した図形は、親に対する相対の位置・回転・拡大・伸縮になります。子の変形は、親の変形を受けた座標系で働きます。

  • offset_x / offset_yが0.5のとき、子は親の位置(親のパスの原点)に重なります。ずれ量は、親の拡大・回転・伸縮を受けます。
  • 子のrotation・scale・stretch_*・pivot_*は、子自身の位置を中心に、親の座標系で働きます。親が非等方に伸縮していると、回転した子は歪んで見えます。
  • 親のopacity・fill・stroke・shadow・blur・textureは、子に引き継がれません。各図形が自分で設定します。
  • 子も親になれます(祖父母まで辿ります)。親をopacity = 0にして、子だけを見せることもできます。
  • 親の拡大が0になると、子も大きさを失い、何も描かれません。連鎖の倍率は倍精度で累積し、その図形の描画用の行列が単精度の範囲を超えるときも、その図形は何も描かれません(途中の図形が範囲を超えても、後ろの図形の倍率が戻れば、後ろの図形は描かれます)。
  • 親に使えるのは図形だけで、本文の文字は親にできません。
lua
local rectangle = mt.svg_path("M -500 -300 L 500 -300 L 500 300 L -500 300 Z")

function OnPreLayout(ctx)
    local background = ctx.shapes:declare({ path = rectangle })
    local frame = ctx.shapes:declare({ path = rectangle, layer = "front" })
end

図形の設定 ​

ctx.shapes[number]はOnLayoutとOnPathで参照できます。OnLayoutでは次のフィールドを、ctx.chars[index]と 同じ規則で設定できます。

フィールド型内容
indexinteger図形番号。ctx.shapes:declareの戻り値と同じ値
offset_x / offset_ynumber位置のずれ。0.5でずれなし。何も設定しない図形は、キャンバスの中央に出ます
pivot_x / pivot_y / scale / stretch_x / stretch_y / rotation / z / yaw / pitchnumberctx.chars[index]と同じ変形。図形は自分の位置(パスの原点)を中心に回転・拡縮し、pivot_*もそこからの変位です
opacitynumber不透明度の倍率(0〜1)
parentinteger読み取り専用。ctx.shapes:declareで指定した親の図形番号。親がないときは0
camerainteger読み取り専用。この図形を投影するカメラの番号(親から引き継いだ番号を含む)。カメラがないときは0
z_indexnumber描画順の値(既定値0)。同じ層の中で、小さいものから順に描かれ(大きいものが手前)、同じ値は宣言した順です。layerの背面・前面は越えません。+inf・-infは最大・最小として並び、NaNは代入するとエラーです。親子関係とは無関係です
fill / stroke / shadow / texture / blurtable個別の見た目。ctx.chars[index]と同じ項目
pathpath図形の輪郭。OnLayoutのみ。宣言したパスから始まり、path:assign(p)などで直接編集する。毎フレーム、宣言したパスへ戻る

pathは代入できません。shape.path:assign(p)のように、渡したパスをコピーして置き換えます。編集したパスだけが そのフレームで使われます。ctx.paths:shape(number)(OnPath)で、OnLayoutで編集した後のパスを、さらに編集できます。

lua
function OnLayout(ctx)
    local shape = ctx.shapes[1]
    shape.path:assign(drawLights(ctx))
    shape.opacity = 0.8
    shape.fill.use = true
    shape.fill.color = { r = 1.0, g = 0.5, b = 0.7, a = 1.0 }
end

ctx.shape_cameras:declare() ​

図形用のカメラを1つ宣言し、1始まりのカメラ番号(宣言した順)を返します。OnPreLayoutでのみ呼び出せ、上限は16個です。 図形用のカメラは、本文のカメラ(ctx.camera)とは別のカメラです。本文のカメラ、Global、本文の3D姿勢は図形に影響せず、 図形用のカメラも本文に影響しません。

ctx.shape_cameras[number]はOnLayoutで参照・設定できます。値は毎フレーム、本文のカメラの既定値から始まるので、 動かしたいフレームごとに書きます。

フィールド型既定値内容
target_x / target_ynumber0.5 / 0.5カメラの注視点(キャンバスの割合)。target_yは上向きが正
yaw / pitchnumber0カメラの軌道角(度)。ctx.cameraと同じ向き
perspectivenumber0.5遠近感の強さ。0〜1に丸められます
zoomnumber1ズーム倍率
lens_shift_x / lens_shift_ynumber0レンズシフト(キャンバスの割合)。lens_shift_yは上向きが正

数値は有限である必要があり、NaN・infを書くとエラーです。位置・姿勢・カメラの値が数として扱えなくなった図形(z = 1e308など)は、何も描かれません。

カメラを指定した図形(ctx.shapes:declare({ camera = number }))は、yaw・pitch・zを含む自分の姿勢が3Dになり、 そのカメラで投影されます。

  • 各図形は自分の位置(パスの原点)を中心に回ります。親の姿勢は、子の位置と向きに掛かります。親をpitchで倒すと、親の上方向にずらした子は奥行き方向に動きます。
  • 同じ親子の木は、1つのカメラで投影されます。子がcameraを省略すれば親のカメラを使い、親と違う番号を指定するとエラーです。
  • カメラのない図形では、yaw・pitch・zは見た目に効きません。
  • scaleは図形の面内(x・y)にだけ効き、奥行きには効きません。縮尺を変えた親の下で、回転した子は、せん断(斜めに歪むこと)します。回転した図形に付ける子の形を保ちたいときは、scaleを1のままにして、大きさをパスの寸法と、子のoffset(親の長さ)に直接反映してください。
  • 描画順は、層、z_indexの順で決まり、同じ層・同じz_indexの中で、同じカメラの図形どうしだけ奥行きの遠い順に並びます。カメラの違う図形、カメラのない図形の位置は動かしません。
  • 線幅、影、ぼかしの大きさは、図形の位置の奥行きの縮尺に従います。
lua
function OnPreLayout(ctx)
    local view = ctx.shape_cameras:declare()
    local card = ctx.shapes:declare({ path = rectangle, camera = view })
end

function OnLayout(ctx)
    ctx.shape_cameras[1].pitch = 20
    ctx.shapes[1].yaw = ctx.time * 90
end

本文と違う扱い ​

  • レイアウトの流れ(送り幅、整列、折り返し)に入りません。
  • Write On、Gradient、Bounding Box、Deform、Crayon、ビューアでの選択の対象になりません。
  • Globalの変形と本文の3Dのカメラの影響を受けません。図形はキャンバスに固定され、ctx.shape_camerasのカメラを指定した図形だけが、そのカメラで3Dに投影されます。
  • 手動の順序(manual_order_text)に図形の番号は書けません。描画順は、layer、z_index、宣言の順で決まります。本文を図形の間に挟むことはできません。
  • 文字数・パーツ数の上限を使いません。図形の数の上限は、全プリセット共通でctx.meta.limits.max_shapesです。上限を超えた宣言はエラーです。
  • Output Separationの影響は受けます。
  • 制限事項: 本文のCrayon(実験的機能)の線は、layer = "front"の図形より手前に描かれます。
  • mt.layout.place_2d・mt.layout.get_canvas_position_2d・mt.layout.canvas_to_offset_2dは、図形を文字と同じように受け取れます。アンカーは図形の位置です。親のある図形では、親の変形を通した位置を扱い、place_2dとcanvas_to_offset_2dは親の座標系のoffsetを返します(親の大きさが0のときはエラー)。
  • 本文の見た目の設定(文字色、縁取り、影、ぼかし、glow、テクスチャ)は図形にも掛かります。掛けたくない設定は、OnLayoutでctx.shapes[number]へ設定して上書きします。

対象APIレベル: 10

mtは、アニメーションの計算、色の操作、レイアウト、パス、時間制御などに使用する ユーティリティをまとめた名前空間です。

NOTE

timeまたはtには、通常、アニメーション開始からの経過時間を渡します。クリップ先頭から 開始する場合はctx.time、途中から開始する場合はctx.time - startTimeを使用します。

用途別索引 ​

用途API
値の制限・区間写像mt.clamp / mt.saturate / mt.remap / mt.wrap
補間・キーフレームmt.lerp / mt.inverse_lerp / mt.lerp_angle / mt.smoothstep / mt.keyframes
進行度の分配(ドミノ・順次時間差・タイピング)mt.distribute / mt.stagger / mt.stagger_progress / mt.stagger_pattern
手動の描画順・Write On順mt.order_text / mt.CHAR / mt.PART / mt.NOT
距離による影響度(波紋・光沢・衝撃波)mt.falloff
決定論的乱数・ノイズ(散乱・手ブレ揺らぎ)mt.random / mt.random_range / mt.distributed_random / mt.noise1 / mt.noise2 / mt.wiggle
周期・ばね(浮遊・波・減衰振動)mt.cycle / mt.pingpong / mt.wave / mt.wave_square / mt.wave_triangle / mt.wave_sawtooth / mt.spring
極座標からの変位(放射状散乱・公転)mt.polar_offset_2d
方向ベクトルから回転角(アスペクト比補正可)mt.direction_to_rotation_2d
物理モーション(弾道・着地バウンス・摩擦減速)mt.bounce_y / mt.bounce_x / mt.bounce_ground / mt.bounce_wall / mt.impact_squash / mt.projectile_2d / mt.friction_decay
色(色相回転・補間・知覚的一様)mt.color.resolve_fill / mt.color.from_* / mt.color.to_* / mt.color.lerp* / mt.color.with_alpha
要素のシャドウ・ぼかし・ストローク・テクスチャの解決(上位の段階から継承する値の取得)mt.shadow.resolve / mt.blur.resolve / mt.stroke.resolve / mt.texture.resolve
イージングmt.ease.*
再組版・行単位のグループ化mt.layout.reflow / mt.layout.group_by_line
Canvas上の位置・距離・支点mt.layout.place_2d / mt.layout.get_canvas_position_2d / mt.layout.canvas_to_offset_2d / mt.layout.radial_distance / mt.layout.pivot_at_2d
2D変換後の境界mt.layout.measure_bounds_2d
パス上への整列mt.layout.queue_on_path
モーションパスmt.path.bezier / mt.path.catmull_rom / mt.path.arc_length
パスの作成・編集mt.svg_path / path:*
UTF-8テキスト処理mt.text.slice / mt.text.classify
文字・パーツの指定文字列mt.target.chars / mt.target.parts
クリップ時間mt.timeline.progress / mt.timeline.duration / mt.timeline.remaining / mt.timeline.intro_outro_seconds / mt.timeline.window_progress / mt.timeline.window_ctx / mt.timeline.chain
非推奨の互換APImt.storage / mt.polar_offset / mt.layout.retypeset / mt.layout.canvas_to_offset / mt.layout.set_canvas_position / mt.layout.group_bounds / mt.timeline.intro_outro

1. 値の制限・区間写像 ​

mt.clamp(value, low, high) ​

APIレベル: 1+

値を閉区間 [low, high] へ制限します。

引数 ​

引数型単位省略時内容
valuenumber-指定必須制限する値
lownumber-指定必須下限
highnumber-指定必須上限

戻り値 ​

型単位内容
number-制限後の値

mt.saturate(value) ​

APIレベル: 1+

mt.clamp(value, 0.0, 1.0) の短縮形です。進行度やアルファ値を0-1に収めるときに使います。

引数 ​

引数型単位省略時内容
valuenumber-指定必須0-1へ制限する値

戻り値 ​

型単位内容
number0-10-1へ制限された値

mt.remap(value, in_low, in_high, out_low, out_high, clamped?) ​

APIレベル: 1+

値を入力区間から出力区間へ写します。「秒数を進行度に変換する」など区間の変換全般に使います。

引数 ​

引数型単位省略時内容
valuenumber-指定必須変換する値
in_low / in_highnumber-指定必須入力区間
out_low / out_highnumber-指定必須出力区間
clampedboolean-falsetrueなら入力位置を0-1へ制限してから変換します

戻り値 ​

型単位内容
number-変換後の値

制約・エラー ​

条件内容
in_low == in_high入力区間の幅が0になるため指定できません

使用例 ​

lua
-- 0.5秒から1.2秒にかけて、Yオフセットを0.7から0.5へ
character.offset_y = mt.remap(ctx.time, 0.5, 1.2, 0.7, 0.5, true)

mt.wrap(value, boundaryA, boundaryB) ​

APIレベル: 1+

値を2つの境界のうち小さい方を含み、大きい方を含まない半開区間 [min(boundaryA, boundaryB), max(boundaryA, boundaryB))内で周回させます。 境界はどちらの順でも指定できます。角度や色相の周期化に使います。

APIレベル6での変更: 境界をlow / highではなくboundaryA / boundaryBとして扱い、 逆順の指定でも小さい境界から大きい境界までの区間を周回するようになりました。

引数 ​

引数型単位省略時内容
valuenumber-指定必須周回させる値
boundaryAnumber-指定必須区間を決める一方の境界
boundaryBnumber-指定必須区間を決めるもう一方の境界

戻り値 ​

型単位内容
number-周回後の値

制約・エラー ​

2つの境界が等しい場合は、その境界値を返します。

2. 補間・キーフレーム ​

mt.lerp(from, to, t) ​

APIレベル: 1+

from から to への線形補間です。

引数 ​

引数型単位省略時内容
fromnumber-指定必須t = 0のときの値
tonumber-指定必須t = 1のときの値
tnumber-指定必須補間係数。クランプされないため、0-1の外を渡すと外挿されます

戻り値 ​

型単位内容
number入力値と同じfrom + (to - from) * t

mt.inverse_lerp(from, to, value) ​

APIレベル: 1+

mt.lerp の逆関数です。value が区間 [from, to] のどの位置にあるかを補間係数として返します。

引数 ​

引数型単位省略時内容
fromnumber-指定必須係数0に対応する区間の始端
tonumber-指定必須係数1に対応する区間の終端
valuenumber-指定必須位置を求める値

戻り値 ​

型単位内容
number-(value - from) / (to - from)。クランプされません

制約・エラー ​

from == toの場合は0を返します。


mt.lerp_angle(from, to, t) ​

APIレベル: 1+

角度(degree)を最短方向で補間します。mt.lerp(350, 10, t) のような遠回りを避けたいときに 使います(350°→10°を+20°側で補間)。

引数 ​

引数型単位省略時内容
fromnumberdegree指定必須開始角度
tonumberdegree指定必須目標角度
tnumber-指定必須補間係数。クランプされません

戻り値 ​

型単位内容
numberdegree補間後の角度

mt.smoothstep(edge0, edge1, value) ​

APIレベル: 1+

value が edge0 から edge1 を横切る間、0から1へ滑らかに遷移する値を返します (Hermite補間。両端で速度が0になります)。

引数 ​

引数型単位省略時内容
edge0number-指定必須結果が0になる遷移の開始位置
edge1number-指定必須結果が1になる遷移の終了位置
valuenumber-指定必須評価する値

戻り値 ​

型単位内容
number0-1滑らかな遷移値。区間外はクランプされます

制約・エラー ​

条件内容
edge0 == edge1遷移区間の幅が0になるため指定できません

mt.keyframes(keys, time) ​

APIレベル: 1+

複数区間のキーフレームを評価します。ctx.timeから直接呼べるため、 落下→バウンド→静止のような多段の振り付けを clamp + inverse_lerp の手書きなしで書けます。

引数 ​

引数型単位省略時内容
keystable[]-指定必須キーフレームの配列。各要素は{ t = <時刻>, v = <値>, ease = <省略可> }で、tを昇順に並べます
timenumber秒指定必須評価する時刻

各キーの v は number または { r, g, b, a } 形式の color テーブルのいずれかで、1つの keys 配列内で混在させることはできません。ease は省略可(既定は線形)で、そのキーへ到達するまでの 区間に適用されます。mt.ease.out_bounce のような名前の文字列、または function(t) ... end の 形の任意のイージング関数を渡せます。

time が最初のキーより前なら最初の値、最後のキーより後なら最後の値を返します(クランプ)。

戻り値 ​

型単位内容
number | colorキーの値と同じ区間内で補間された値

使用例 ​

lua
-- 0.0〜0.3秒でバウンドしながら落下し、0.3〜0.5秒は静止、
-- 0.5秒以降クリップ終端に向けてゆっくり退場する
local y = mt.keyframes({
    { t = 0.0, v = 1.2 },
    { t = 0.3, v = 0.5, ease = "out_bounce" },
    { t = 0.8, v = 0.5 },
    { t = 1.3, v = -0.2, ease = "in_cubic" },
}, ctx.time)

-- color もそのまま補間できる
local tint = mt.keyframes({
    { t = 0.0, v = { r = 1.0, g = 1.0, b = 1.0, a = 1.0 } },
    { t = 1.0, v = { r = 1.0, g = 0.4, b = 0.1, a = 1.0 } },
}, ctx.time)
character.fill.color = tint

3. 進行度の分配 ​

mt.distribute(index, count) ​

APIレベル: 1+

1始まりの index を 0-1 へ均等に割り付けます。先頭が 0、末尾が 1 になります。

引数 ​

引数型単位省略時内容
indexinteger-指定必須1始まりのindex。ctx.chars[index]のindexなどを渡します
countinteger-指定必須総数。ctx.char_countなどを渡します

戻り値 ​

型単位内容
number0-1(index - 1) / (count - 1)を0-1へ制限した値。count <= 1の場合は0

使用例 ​

lua
-- 文字位置に応じて色相を虹状に配置
local hue = mt.distribute(index, ctx.char_count)
character.fill.use = true
character.fill.color = mt.color.from_okhsv(hue, 0.8, 1.0)

mt.order_text(entries) ​

APIレベル: 8+

文字またはglobal partのindexを符号化した配列から、検証済みのctx.output.manual_order_textを生成します。入力順と重複は維持します。

文字は1始まりのindexをそのまま、またはmt.CHAR | indexで指定し、global partはmt.PART | indexで指定します。各indexは1以上1024以下のintegerでなければなりません。manual orderには除外構文がないため、mt.NOTは使用できません。

引数 ​

引数型単位省略時内容
entriesinteger[]-指定必須出力順に並べた文字・global partの符号化index

戻り値 ​

型単位内容
string-入力順を表す有効なmanual order文字列。空配列では空文字列

使用例 ​

lua
local order = {}
for index = ctx.char_count, 1, -1 do
    order[#order + 1] = mt.CHAR | index
end
ctx.output.manual_order_enabled = true
ctx.output.manual_order_text = mt.order_text(order)

mt.CHAR ​

値は0x0000。1始まりの文字indexと合成する文字種別flagです。値が0のため、indexをそのまま指定しても同じ意味になります。

mt.PART ​

値は0x10000。1始まりのglobal part indexと合成するパーツ種別flagです。下位16bitはindex専用です。

mt.NOT ​

値は0x20000。targets構文用の除外flagです。mt.order_textには渡せません。


mt.each_char(ctx, options?) ​

APIレベル: 6+

整形済み文字を絞り込みつつ反復するイテレータを返します。index は常に ctx.chars 上のindexなので、ctx.chars[index] や mt.layout.* にそのまま渡せます。絞り込み後の通し番号は info.n です。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayout / OnPath の context
options.frominteger-1反復を開始する文字index
options.tointeger-ctx.char_count反復を終了する文字index(この値を含む)
options.lineinteger-絞り込みなしこの line_index の文字だけを通します
options.orderstring-"asc"info.progress の割り当て順。"asc" / "desc" / "center" / "random"
options.seedinteger-0order = "random" のときの並びを決めるseed

戻り値 ​

型内容
functionindex(ctx.chars上のindex)、character、info を返すイテレータ

info の各フィールド:

フィールド型内容
progressnumberorder に沿った 0-1 の正規化位置
ninteger絞り込み後の通し番号(1始まり)
countinteger絞り込み後の要素数(最低1)
first / lastboolean絞り込み後の先頭・末尾かどうか

order の割り当ては次の通りです(訪問順は常にindexの昇順で、変わるのは progress の値だけです)。

指定progress の並び(5要素の場合)
"asc"0, 0.25, 0.5, 0.75, 1
"desc"1, 0.75, 0.5, 0.25, 0
"center"1, 0.5, 0, 0.5, 1
"random"seedで決まる重複のない並び替え

"center" は中点からの距離を正規化した値です。要素数が偶数の場合は中点に要素が乗らないため、最小値は 0 になりません。

注意: info は毎回同じテーブルを使い回します。ループの外へ持ち出す場合は値をコピーしてください。

使用例 ​

lua
-- 2行目だけを、中央から外側へ順に開く
for index, character, info in mt.each_char(ctx, { line = 1, order = "center" }) do
    local delay = info.progress * 0.4
    character.opacity = mt.saturate((ctx.time - delay) * 4.0)
end

mt.each_part(ctx, options?) ​

APIレベル: 6+

整形済みパートを絞り込みつつ反復するイテレータを返します。mt.each_char と同じ規則に加えて、所属文字を info から直接参照でき、所属文字による絞り込みができます。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayout / OnPath の context
options.frominteger-1反復を開始するパートindex
options.tointeger-ctx.part_count反復を終了するパートindex(この値を含む)
options.from_charinteger-絞り込みなし所属文字のindexがこの値以上のパートだけを通します
options.to_charinteger-絞り込みなし所属文字のindexがこの値以下のパートだけを通します
options.lineinteger-絞り込みなしこの line_index のパートだけを通します
options.orderstring-"asc"info.progress の割り当て順。mt.each_char と同じ
options.seedinteger-0order = "random" のときの並びを決めるseed

from / to(パートindexの範囲)と from_char / to_char(所属文字indexの範囲)は別々の軸で、両方指定した場合は両方を満たすパートだけが通ります。

戻り値 ​

型内容
functionindex(ctx.parts上のindex)、part、info を返すイテレータ

info は mt.each_char の全フィールドに加えて次を持ちます。

フィールド型内容
charMtCharacterこのパートが属する文字(ctx.chars の要素)
char_indexinteger属する文字の ctx.chars 上のindex
index_in_charintegerその文字の中での位置

info.progress は絞り込み後の集合全体を通しで 0-1 に張ります。文字の境界でリセットはしません。文字ごとに 0-1 を張りたい場合は mt.each_char と mt.each_part を入れ子にしてください。

使用例 ​

lua
-- 3〜5文字目のパートだけを、通しで順に持ち上げる
for index, part, info in mt.each_part(ctx, { from_char = 3, to_char = 5 }) do
    part.offset_y = info.progress * 0.05
    part.rotation = info.char.rotation * 0.5
end

mt.stagger(time, index, delay, duration) ​

APIレベル: 1+

index ごとに開始をずらしたアニメーション進行度(ドミノ倒し、カスケード登場、タイピング風の順次アニメーション)を返します。文字送りの定番関数です。 index i のアニメーションは delay * (i - 1) 秒遅れて始まり、duration 秒かけて 0から1へ進みます。

引数 ​

引数型単位省略時内容
timenumber秒指定必須アニメーション開始からの経過時間
indexinteger-指定必須1始まりのindex
delaynumber秒指定必須次のindexが開始するまでの遅延
durationnumber秒指定必須各indexのアニメーション時間

戻り値 ​

型単位内容
number0-10-1へクランプされた進行度

制約・エラー ​

条件内容
duration <= 00より大きい値を指定してください

使用例 ​

lua
for index = 1, ctx.char_count do
    local progress = mt.stagger(ctx.time, index, 0.08, 0.4)
    ctx.chars[index].offset_y = 0.5 + (1.0 - mt.ease.out_cubic(progress)) * 0.2
end

mt.stagger_progress(progress, position, span) ​

APIレベル: 6+

0-1へ正規化済みの全体進行度へ、要素位置に応じた開始時間差(一斉・同期登場やグループカスケード)を付けます。 position = 0の要素は全体と同時に開始し、position = 1の要素は全体進行度が spanへ達した時点で開始します。すべての要素は全体進行度が1へ達した時点で完了します。

秒単位の時刻、index、要素ごとのdurationから進行度を作る場合はmt.staggerを使用します。 mt.timeline.intro_outro_secondsなどから得た既存の進行度を分散する場合は mt.stagger_progressを使用します。

引数 ​

引数型単位省略時内容
progressnumber0-1指定必須分散元の全体進行度。範囲外も許可され、戻り値が0-1へクランプされます
positionnumber0-1指定必須要素の正規化位置。範囲外は0-1へクランプされます。通常はinfo.progressを渡します
spannumber0-1未満指定必須全体時間のうち、開始時刻の分散に使用する割合

戻り値 ​

型単位内容
number0-1positionに対応する要素の進行度

戻り値は次の式で計算されます。

lua
mt.saturate((progress - mt.saturate(position) * span) / (1.0 - span))

制約・エラー ​

条件内容
progressまたはpositionが有限数ではないエラー
spanが有限数ではないエラー
span < 0またはspan >= 1エラー

使用例 ​

lua
local introProgress, outroProgress =
    mt.timeline.intro_outro_seconds(ctx, 0.5, 0.5, 5.0)

for _, character, info in mt.each_char(ctx, { order = "center" }) do
    local appear = mt.ease.out_back(
        mt.stagger_progress(introProgress, info.progress, 0.35))
    local disappear = mt.ease.in_cubic(
        mt.stagger_progress(outroProgress, info.progress, 0.25))

    character.scale = appear
    character.opacity = appear * (1.0 - disappear)
end

mt.each_char / mt.each_partのorderを変えると、ループの訪問順を変えずに 開始時間の割り当てだけを変更できます。


mt.stagger_pattern(time, index, count, pattern, delay, duration, seed?) ​

APIレベル: 1+

開始方向や順序(昇順・降順・中央から外側への波紋・重複なしランダム順)を指定できるスタガー進行度を返します。

引数 ​

引数型単位省略時内容
timenumber秒指定必須評価する時刻
indexinteger-指定必須1始まりのindex
countinteger-指定必須総数。ctx.char_countなどを渡します
patternstring-指定必須進行パターン。"asc" / "desc"(別名"right_to_left")/ "center" / "random"
delaynumber秒指定必須開始遅延
durationnumber秒指定必須アニメーション時間
seedinteger-42pattern = "random"のときの乱数種

"random"は各indexへ重複しないランダム順位を割り当てます。順位は必ず1つずつ離れるため、遅延の間隔が均等になります。

APIレベル6での変更: 以前はindexごとに独立した乱数で遅延を決めていたため、数文字が偶然ほぼ同時に動き、逆に何も起きない区間ができることがありました。現在は順列を使うため、同じseedでも以前とは並びが変わります。

戻り値 ​

型単位内容
number0-10-1へクランプされた進行度

制約・エラー ​

条件内容
duration <= 00より大きい値を指定してください

4. 距離による影響度 ​

mt.falloff(distance, radius) ​

APIレベル: 3+

中心で最大、離れるほどなだらかに弱まる影響度の重み(波の通過、光沢の走り、水面の波紋、衝撃波、局所強調)を返します。戻り値は 0〜1 です。

引数 ​

引数型単位省略時内容
distancenumber入力座標系指定必須効果の中心からの距離
radiusnumber入力座標系指定必須減衰の広がり。この距離で重みが約0.37(e^-1)になります

「波の峰」「走る光沢」「注目箇所だけ強調」など、特定の位置を中心に効果を集中させる用途の定番です。

mt.smoothstep との使い分け: smoothstep は範囲外で完全に 0 になる(切れ目ができる)のに対し、falloff は裾が無限に続くため、峰や光が通り抜けていく動きが途切れずに見えます。線形減衰(1 - d/r)のような折れ曲がりも生じません。

戻り値 ​

型単位内容
number0-1距離に応じた影響度の重み

使用例 ​

lua
-- 波の先端 waveFront が通過した文字だけを持ち上げる
local distance = characterRadius - waveFront
character.offset_y = 0.5 + mt.falloff(distance, 0.25) * 0.1

NOTE

radius に 0 を渡した場合は 0 を返します(ゼロ除算を避けるため)。

5. 決定論的乱数・ノイズ ​

mt.random(seed, index, channel?) ​

APIレベル: 1+

(seed, index, channel) の組だけで値が決まる安定乱数です。呼び出し順に依存しないため、 文字・パーツごとのばらつきに安全に使えます(math.random は呼び出し順に依存するため この用途には使えません)。

TIP

"angle"や"distance"のようにchannelへ用途ごとの名前を付けると、seedやindexへ 手作業でsaltを加えずに独立した乱数を得られます。

APIレベル6での追加: 任意の文字列channelを指定できるようになりました。 省略時の結果は以前と同じです。

引数 ​

引数型単位省略時内容
seedinteger-指定必須乱数系列を選ぶ値。同じ用途には同じseedを使います
indexinteger-指定必須系列内の位置。文字indexなどを渡します
channelstring-省略用途を分離する名前。

戻り値 ​

型単位内容
number0-1[0, 1)の乱数。同じ引数なら常に同じ値

制約・エラー ​

channelはUTF-8のバイト列を固定の32bitハッシュへ変換します。Unicode正規化は行わないため、 channel名には"angle"や"color.hue"のようなASCII文字列を推奨します。32bitハッシュには 理論上の衝突があり、暗号用途には使用できません。


mt.random_range(seed, index, low, high, channel?) ​

APIレベル: 1+

mt.random の結果を [low, high) へ変換した値を返します。では、 任意の文字列channelで用途ごとの乱数系列を分離できます。

引数 ​

引数型単位省略時内容
seed / indexinteger-指定必須mt.randomと同じ
low / highnumber-指定必須出力範囲
channelstring-省略mt.randomと同じ。

戻り値 ​

型単位内容
number出力範囲と同じ[low, high)の安定乱数

mt.distributed_random(seed, index, count, low, high, channel?) ​

APIレベル: 8+

count個の等間隔な値を、決定論的な順列で1始まりのindexへ割り当てます。戻り値は[low, high)に収まり、mt.random_rangeを独立に呼ぶ場合と異なり、全体に値の集中や重複がありません。mt.each_charまたはmt.each_partと組み合わせる場合は、絞り込み後もindexが連続するようinfo.nとinfo.countを渡します。

引数 ​

引数型単位省略時内容
seedinteger-指定必須順列と共通offsetを決める値
indexinteger-指定必須1以上count以下の割り当て位置
countinteger-指定必須値の個数。1以上
low / highnumber-指定必須low < highを満たす有限の出力境界
channelstring-省略独立した割り当てを分離する名前

戻り値 ​

型単位内容
number出力範囲と同じ[low, high)内の安定した割り当て値。sort後の隣接値は(high - low) / countずつ離れます

使用例 ​

lua
for _, character, info in mt.each_char(ctx) do
    local phase = mt.distributed_random(
        ctx.meta.instance_seed, info.n, info.count, 0.0, math.pi * 2.0, "phase")
    character.offset_y = 0.5 + mt.wave(ctx.time, 0.5, phase) * 0.03
end

mt.noise1(x, seed?) ​

APIレベル: 1+

決定論的な1次元 value noise です。x に対して滑らかに連続する「揺らぎ」を返します。 x に時間を渡せば時間方向の揺らぎ、位置を渡せば空間方向の揺らぎになります。

引数 ​

引数型単位省略時内容
xnumber-指定必須サンプル位置。整数間隔の格子点間が滑らかに補間されます
seedinteger-0揺らぎのパターンを変える値

戻り値 ​

型単位内容
number-1-1同じ引数に対して常に同じ連続値

使用例 ​

lua
-- 文字ごとに位相の違う手ぶれ風の揺れ
character.rotation = mt.noise1(ctx.time * 0.8, index) * 4.0

mt.noise2(x, y, seed?) ​

APIレベル: 1+

決定論的な2次元 value noise です。位置 (x, y) に対して滑らかな揺らぎを返します。 片方の軸に時間、もう片方に文字位置を渡すと「空間的に流れる」揺らぎが作れます。

引数 ​

引数型単位省略時内容
x / ynumber-指定必須サンプル位置
seedinteger-0揺らぎのパターンを変える値

戻り値 ​

型単位内容
number-1-1同じ引数に対して常に同じ連続値

mt.wiggle(time, frequency, amplitude, octaves?, seed?) ​

APIレベル: 1+

決定論的ノイズによる有機的な揺らぎ(手ブレ、ランダムな微振動、浮遊感)を計算します。

引数 ​

引数型単位省略時内容
timenumber秒指定必須評価する時刻
frequencynumberHz指定必須1秒あたりの揺れの回数
amplitudenumber出力値と同じ指定必須第1オクターブの振幅。複数オクターブの合計最大値ではありません
octavesinteger-1重ねるノイズのオクターブ数
seedinteger-0乱数種

戻り値 ​

型単位内容
numberamplitudeと同じ揺らぎの値

octaves > 1では振幅を半減しながら加算するため、理論上の絶対値上限は amplitude * (2 - 2^(1 - octaves))で、オクターブ数が増えると2 * amplitudeへ近づきます。

6. 周期・ばね ​

mt.cycle(t, period) ​

APIレベル: 1+

0から1へ繰り返すノコギリ波進行度(ループアニメーション、回転、連続タイマー、レーダー走査)を返します。

引数 ​

引数型単位省略時内容
tnumber秒指定必須評価する時刻
periodnumber秒指定必須1周期の長さ

戻り値 ​

型単位内容
number0-10以上1未満の進行度

制約・エラー ​

条件内容
period <= 00より大きい値を指定してください

mt.pingpong(t, period) ​

APIレベル: 1+

0→1→0を繰り返す往復進行度(振り子運動、シャトル往復)を返します。行って戻るループに使います。

引数 ​

引数型単位省略時内容
tnumber秒指定必須評価する時刻
periodnumber秒指定必須1往復の長さ

戻り値 ​

型単位内容
number0-10-1の往復値

制約・エラー ​

条件内容
period <= 00より大きい値を指定してください

mt.wave(t, frequency, phase?) ​

APIレベル: 1+

正弦波による周期運動(浮遊、上下の揺れ、うねり、呼吸のような緩急)を計算します。短縮形 sin(2π × frequency × t + phase) です。

引数 ​

引数型単位省略時内容
tnumber秒指定必須評価する時刻
frequencynumberHz指定必須1秒あたりの周期数
phasenumberradian0位相オフセット。indexごとに波をずらす用途にも使えます

戻り値 ​

型単位内容
number-1-1波形値

mt.wave_square(t, frequency, phase?) ​

APIレベル: 1+

矩形波による周期的な二値切り替え(点滅、ストロボ、フラッシュ)を計算します。

引数 ​

引数型単位省略時内容
tnumber秒指定必須評価する時刻
frequencynumberHz指定必須1秒あたりの周期数
phasenumberradian0位相オフセット

戻り値 ​

型単位内容
number--1.0または1.0

mt.wave_triangle(t, frequency, phase?) ​

APIレベル: 1+

三角波(トライアングルウェーブ)です。

引数 ​

引数型単位省略時内容
tnumber秒指定必須評価する時刻
frequencynumberHz指定必須1秒あたりの周期数
phasenumberradian0位相オフセット

戻り値 ​

型単位内容
number-1-1-1.0から1.0の間で直線的に往復する値

mt.wave_sawtooth(t, frequency, phase?) ​

APIレベル: 1+

のこぎり波(ソートゥースウェーブ)です。

引数 ​

引数型単位省略時内容
tnumber秒指定必須評価する時刻
frequencynumberHz指定必須1秒あたりの周期数
phasenumberradian0位相オフセット

戻り値 ​

型単位内容
number-1-1-1.0から1.0未満へ直線的に上昇し、繰り返す値

mt.spring(t, frequency, damping) ​

APIレベル: 1+

減衰振動(バネの揺れ戻し、プルプルした弾性、ぐらつき、オーバーシュートからの収束)を計算します。t = 0で1から始まり、振動しながら0へ収束します。

引数 ​

引数型単位省略時内容
tnumber秒指定必須動き始めてからの経過時間。t <= 0では初期値を返します
frequencynumberHz指定必須1秒あたりの振動回数
dampingnumber1/秒指定必須減衰の強さ。大きいほど早く収束します

戻り値 ​

型単位内容
number-初期値1から0へ収束する減衰振動値

t > 0ではexp(-damping * t) * cos(2π * frequency * t)を計算します。

WARNING

戻り値は 0-1 に収まりません。 減衰中に 負の値(および、位相によっては 1 をわずかに 超えない範囲での行き過ぎ)を取り得ます。これはオーバーシュート表現そのものであり、 mt.ease.out_back / elastic が 0-1 の外へはみ出すのと同種です。

  • 向いている用途: offset / rotation / 散らばり量などの変位の残差 (例: 0.5 + settle * 0.1)
  • 向いていない用途: 進行度・opacity・scale / stretch へのそのままの代入や、 mt.lerp の t としての利用。進行度が必要なら mt.ease.* や mt.saturate を使い、 負値をそのまま倍率に掛けないでください(stretch はホスト側の下限クランプがなく、 負のまま描画に渡り得ます。scale は正の下限へクランプされ、opacity は描画直前に 0-1 へクランプされます)

使用例 ​

lua
-- 目標位置からのずれとして使う(t=0で最大、時間とともに収束。負の区間が行き過ぎ)
local settle = mt.spring(ctx.time - start_time, 3.0, 4.0)
character.offset_y = 0.5 + settle * 0.1

7. 極座標からの変位 ​

mt.polar_offset_2d(angleDegrees, radius) ​

APIレベル: 5+

極座標(方向と距離)を Canvas 空間のオフセット 2 値へ変換します(放射状の飛び散り、円運動・公転、爆発演出)。散開・集結・周回といった動きを cos / sin を書かずに表現できます。

引数 ​

引数型単位省略時内容
angleDegreesnumberdegree指定必須方向。座標と同じく、0度は右方向で正の値は時計回りです
radiusnumbercanvas正規化変位指定必須その方向への距離

戻り値 ​

型単位内容
number, numbercanvas正規化変位offsetX, offsetYの2値

入力角度はrotation / shadow.angleと同じ画面基準(90度は下)ですが、戻り値はY-upです。 offset_x / offset_yへそのまま加算できます。mt.projectile_2dも同じ規則です。

使用例 ​

lua
-- 文字ごとに放射状へ散らす
local angle = mt.distribute(index, ctx.char_count) * 360.0
local dx, dy = mt.polar_offset_2d(angle, 0.3 * scatterAmount)
character.offset_x = 0.5 + dx
character.offset_y = 0.5 + dy

mt.direction_to_rotation_2d(dx, dy, aspectRatio?) ​

API level: 15+

Y-up の方向ベクトルから、時計回りを正とする回転角(度)を返します。必須引数 dx・dy は数値です。第3引数を省略する場合、両方ともピクセルなど、同じ縮尺で指定します。右は0度、下は90度、上は-90度です。戻り値は -180〜180 度、ゼロベクトルは0度です。正の半径での mt.polar_offset_2d と逆向きの変換です。

省略可能な第3引数 aspectRatio(既定1)でXの縮尺を補正します。画面幅比・高さ比の変位から求める場合は ctx.canvas.aspect_ratio を指定します。ローカル・グローバル間の変換は行いません。回転の適用先と同じ座標空間の方向を使ってください。未回転時の前方向を +X とする角度なので、元の図柄が別方向を向く場合は補正角を加えます。

lua
local dx, dy = mt.polar_offset_2d(45, 0.1)
character.rotation = mt.direction_to_rotation_2d(dx, dy) -- 45 degrees

-- Heading from normalized canvas deltas, with equally scaled axes:
local heading = mt.direction_to_rotation_2d(deltaX, deltaY, ctx.canvas.aspect_ratio)

8. 物理モーション ​

mt.bounce_y(config) / mt.bounce_x(config) ​

APIレベル: 3+

床面(Y軸)または壁面(X軸)に対する1次元弾道バウンドの位置、速度、Squash & Stretch、 接触位置の補正量を計算して返します。文字やパーツは直接変更しません。設定table形式と 引数並び形式の両方で呼び出せます。

引数 ​

引数型単位省略時内容
configtable-指定必須時刻、衝突面、開始位置、重力または加速度、反発係数、初速、Squash & Stretchの設定

共通のconfig ​

フィールド型単位省略時内容
tnumber秒0.0アニメーション開始からの経過時間
restitutionnumber-0.5反発係数。値が大きいほど衝突後の跳ね返りが強くなります
start_velocitynumbercanvas正規化変位/秒0.0軸方向の初速
squash / squash_strengthnumber係数0.15衝突速度に応じて接触軸を潰す強さ
stretch / stretch_strengthnumber係数0.02移動速度に応じて進行軸を伸ばす強さ
flexibilitynumberradian/秒16.0衝突後に元の形へ戻る振動の速さ
dampingnumber1/秒7.0衝突後の振動が収束する速さ

同じ項目に複数の名前がある場合は、左側の名前を優先して使用します。右側は互換用の別名です。

mt.bounce_y固有のconfig ​

フィールド型単位省略時内容
ground_ynumbercanvas正規化位置0.0衝突する床面のY座標
start_ynumbercanvas正規化位置0.0開始時のY座標
gravitynumbercanvas正規化変位/秒²9.81床面へ向かう加速度の大きさ

mt.bounce_x固有のconfig ​

フィールド型単位省略時内容
wall_x / ground_xnumbercanvas正規化位置0.0衝突する壁面のX座標。ground_xは互換用の別名です
start_xnumbercanvas正規化位置0.0開始時のX座標
acceleration / accel_x / gravitynumbercanvas正規化変位/秒²9.81壁面へ向かう加速度の大きさ。accel_xとgravityは互換用の別名です

引数並び形式 ​

設定tableの代わりに、各値を次の順序で渡すこともできます。

lua
mt.bounce_y(t, groundY, startY, gravity, restitution, startVelocity,
    squashStrength, stretchStrength, flexibility, damping)

mt.bounce_x(t, wallX, startX, acceleration, restitution, startVelocity,
    squashStrength, stretchStrength, flexibility, damping)

各引数は省略でき、対応するconfigフィールドと同じ既定値を使用します。

戻り値(いずれか) ​

型単位内容
table-設定table形式では、位置、速度、変形、衝突状態を持つtable
複数のnumber各値に準拠引数並び形式では、計算結果を8値で返します

戻り値table ​

フィールド型単位内容
posnumbercanvas正規化位置計算後の軸座標
ynumbercanvas正規化位置mt.bounce_yの計算後のY座標。posと同じ値です
xnumbercanvas正規化位置mt.bounce_xの計算後のX座標。posと同じ値です
velocitynumbercanvas正規化変位/秒その時点の軸方向速度
stretch_x / stretch_ynumber倍率Squash & Stretchを反映したX方向とY方向の伸縮率
offset_ynumberbounds_heightに対する比率mt.bounce_yで接地位置を保つための補正量
offset_xnumberbounds_widthに対する比率mt.bounce_xで接触位置を保つための補正量
last_impact_timenumber / nil秒直前の衝突時刻。まだ衝突していない場合はnilです
next_impact_timenumber / nil秒次に衝突する時刻。静止済みの場合はnilです
impact_countinteger回これまでの衝突回数
settledboolean-バウンドが終了して静止したかどうか

tableの[1]〜[5]でも、軸座標、stretch_x、stretch_y、接触位置の補正量、 velocityの順に取得できます。

引数並び形式では、軸座標、stretch_x、stretch_y、接触位置の補正量、velocity、 last_impact_time、next_impact_time、impact_countの順に返します。settledは設定table形式で のみ取得できます。

注意事項 ​

  • restitutionは通常、0以上1未満を指定します。
  • gravityまたはaccelerationの符号は使用されず、絶対値が加速度の大きさとして扱われます。

使用例 ​

lua
-- 詳細設定テーブルで Y 軸バウンド物理を精密計算
local b = mt.bounce_y({
    t = ctx.time,
    ground_y = 0.1,
    start_y = 0.6,
    gravity = 9.81,
    restitution = 0.5,
    squash = 0.2,
    stretch = 0.03,
    flexibility = 18.0,
    damping = 6.0,
})

-- 計算結果を柔軟に適用
local targetY = b.y + b.offset_y * char.geometry.bounds_height
local _, calcOffsetY = mt.layout.canvas_to_offset_2d(ctx, char, curX, targetY)
char.offset_y = calcOffsetY
char.stretch_x = b.stretch_x
char.stretch_y = b.stretch_y

mt.bounce_ground(ctx, item, groundY, config?) ​

APIレベル: 3+

文字またはパーツ item を指定した地面 Canvas 座標 groundY(例: 0.1)に向かってドロップし、ポヨンとバウンド・着地させる簡易便利関数です。offset_y, stretch_x, stretch_y が自動適用されます。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト
itemtable-指定必須変更する文字またはパーツ
groundYnumbercanvas正規化座標指定必須接地先のY座標
configtable-nil開始位置、接地基準、物理パラメータなどの設定

戻り値 ​

型単位内容
table-計算済みのバウンド状態

変更内容 ​

フィールド型単位内容
item.offset_ynumbercanvas正規化変位計算したY方向の変位を設定します
item.offset_xnumbercanvas正規化変位ground_mode = "absolute"の場合に、現在のcanvas上のX位置を保つ変位を設定します
item.stretch_x / item.stretch_ynumber倍率バウンド状態のSquash & Stretchを設定します

config ​

フィールド型単位省略時内容
tnumber秒ctx.time評価する時刻
delaynumber秒0.0動き始めるまでの待ち時間
start_modestring-start_y指定時は"absolute"、それ以外は"relative"開始位置の基準。"relative"では現在位置からdrop_heightだけ上、"absolute"ではstart_yを使用します
start_ynumbercanvas正規化位置nilstart_mode = "absolute"で使用する開始位置
drop_heightnumbercanvas正規化変位0.3start_mode = "relative"で現在位置から上へ離す距離
ground_modestring-start_modeと同じ接地位置の基準。"absolute"ではgroundYをcanvas上の固定位置として扱い、"relative"では上位階層の変換に追従します
align_tostring-"bottom"接地させる位置。"bottom" / "bounds_bottom"はink boundsの下端、"baseline"は文字の横組みベースライン、"center"はink boundsの中心です。ベースラインを持たないパーツで"baseline"を指定すると下端へフォールバックします
gravitynumbercanvas正規化変位/秒²4.0地面へ向かう加速度の大きさ
restitutionnumber-0.45反発係数
start_velocitynumbercanvas正規化変位/秒0.0Y軸方向の初速
squashnumber係数0.15衝突速度に応じて接触軸を潰す強さ
stretchnumber係数0.02移動速度に応じて進行軸を伸ばす強さ
flexibilitynumberradian/秒16.0衝突後に元の形へ戻る振動の速さ
dampingnumber1/秒7.0衝突後の振動が収束する速さ

ground_mode = "absolute"では、回転・スケール適用後のcanvas上の外接矩形を使って接地位置を 求めます。

使用例 ​

lua
-- 画面共通の一定の高さ (0.85) から全文字を垂直落下させて BB 端で接地
mt.bounce_ground(ctx, ctx.chars[i], 0.1, { start_mode = "absolute", start_y = 0.85, align_to = "bottom" })

-- 文字ごとの高さから一定距離 (0.3) 浮かせた位置から落とし、ベースラインに整列
mt.bounce_ground(ctx, ctx.chars[i], 0.1, { start_mode = "relative", drop_height = 0.3, align_to = "baseline" })

-- global.rotation が入っていても、画面の 0.85 から落として画面の 0.1 に正確に接地
mt.bounce_ground(ctx, ctx.chars[i], 0.1, {
    start_mode = "absolute", start_y = 0.85,
    ground_mode = "absolute", align_to = "bottom"
})

NOTE

"absolute" 指定時は、指定 Canvas 位置へ正確に配置するために offset_x と offset_y の 両方 が書き込まれます(回転が入ると2軸が連動するため、片方だけでは目標座標に到達できません)。バウンス軸以外のオフセットは「現在の画面位置を保つための補正」として働きます。


mt.bounce_wall(ctx, item, wallX, config?) ​

APIレベル: 3+

文字またはパーツ item を指定した壁 Canvas 座標 wallX(例: 0.9)に向かって衝突・バウンドさせる簡易便利関数です。offset_x, stretch_x, stretch_y が自動適用されます。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト
itemtable-指定必須変更する文字またはパーツ
wallXnumbercanvas正規化座標指定必須衝突先のX座標
configtable-nil開始位置、衝突基準、物理パラメータなどの設定

戻り値 ​

型単位内容
table-計算済みのバウンド状態

変更内容 ​

フィールド型単位内容
item.offset_xnumbercanvas正規化変位計算したX方向の変位を設定します
item.offset_ynumbercanvas正規化変位config.wall_mode = "absolute"の場合に、現在のcanvas上のY位置を保つ変位を設定します
item.stretch_x / item.stretch_ynumber倍率衝突時のSquash & Stretchを設定します

config ​

フィールド型単位省略時内容
tnumber秒ctx.time評価する時刻
delaynumber秒0.0動き始めるまでの待ち時間
start_modestring-start_x指定時は"absolute"、それ以外は"relative"開始位置の基準。"relative"では現在位置から壁と反対方向へtravel_distanceだけ離し、"absolute"ではstart_xを使用します
start_xnumbercanvas正規化位置nilstart_mode = "absolute"で使用する開始位置
travel_distancenumbercanvas正規化変位0.3start_mode = "relative"で現在位置から壁と反対方向へ離す距離
wall_modestring-start_modeと同じ衝突位置の基準。"absolute"ではwallXをcanvas上の固定位置として扱い、"relative"では上位階層の変換に追従します
align_tostring-進行方向から決定接触させる位置。左から接近する場合は"right"、右から接近する場合は"left"が既定です。"bounds_right"、"bounds_left"、"center"も指定できます
accel / accelerationnumbercanvas正規化変位/秒²4.0壁へ向かう加速度の大きさ。accelが優先されます
restitutionnumber-0.45反発係数
start_velocitynumbercanvas正規化変位/秒0.0X軸方向の初速
squashnumber係数0.15衝突速度に応じて接触軸を潰す強さ
stretchnumber係数0.02移動速度に応じて進行軸を伸ばす強さ
flexibilitynumberradian/秒16.0衝突後に元の形へ戻る振動の速さ
dampingnumber1/秒7.0衝突後の振動が収束する速さ

使用例 ​

lua
-- 画面共通の一定の位置 (0.1) から全パーツを発射して壁 (wallX = 0.9) にバウンド
mt.bounce_wall(ctx, ctx.parts[i], 0.9, { start_mode = "absolute", start_x = 0.1, delay = i * 0.05 })

-- パーツごとの位置から一定距離 (0.25) 引いた位置から発射
mt.bounce_wall(ctx, ctx.parts[i], 0.9, { start_mode = "relative", travel_distance = 0.25 })

mt.impact_squash(config) ​

APIレベル: 3+

衝突の瞬間に潰れて弾む Squash & Stretch のインパルスを計算します。sin(ωt) * exp(-γt) の減衰振動で、衝突直後に最も潰れ、揺れながら元の形へ戻ります。

mt.bounce_* は Squash & Stretch を内部で適用済みなので、この関数は自前のタイミングで衝突を表現したいときに使います(他の文字にぶつかる、地面以外に当たる、など)。

引数 ​

引数型単位省略時内容
configtable-指定必須衝突時刻と変形特性の設定

config ​

フィールド型単位省略時内容
tnumber秒0.0現在時刻。impact_time未満では無変形の値を返します
impact_timenumber秒0.0衝突時刻。mt.bounce_*のlast_impact_timeを渡せます
squashnumber比率0.15潰れ量の最大値。0.2なら最も潰れた瞬間に高さが80%になります
stiffnessnumberradian/秒25.0元の形へ戻る速さ
dampingnumber1/秒12.0振動が収束する速さ

戻り値(多値) ​

型単位内容
number倍率stretchX。X方向の伸縮率
number倍率stretchY。Y方向の伸縮率。stretchXとは体積を保つよう逆数の関係になります
numberbounds_heightに対する比率offsetCorrection。潰れて縮んだ分だけ接地位置がずれるのを補正する値です。bounds_heightに掛けてoffset_yへ加算します

squash の名前と意味は mt.bounce_* の squash と共通です。

使用例 ​

lua
-- 衝突時刻を自分で決めて潰れを適用する
local sx, sy, correction = mt.impact_squash({
    t = ctx.time,
    impact_time = landTime,
    squash = 0.2,
})
character.stretch_x = sx
character.stretch_y = sy
character.offset_y = character.offset_y + correction * character.geometry.bounds_height

TIP

衝突速度に応じて潰れ具合を変えたい場合は、squash 自体を計算してください。 速度を直接渡す引数は用意していません。速度を素直に掛ける方式では、速度が少し大きいだけで 潰れ量が下限に張り付き、それ以上速くしても絵が変わらなくなるためです。下記のように 「どの速度で最大まで潰れるか」を明示するほうが、意図した範囲に収まります。

lua
local squashAmount = 0.3 * mt.saturate(impactSpeed / kFullSquashSpeed)
local sx, sy, correction = mt.impact_squash({ t = ctx.time, impact_time = landTime, squash = squashAmount })

mt.projectile_2d(config) / mt.projectile_2d(t, speed, angle, gravity?, spin?, drag?) ​

APIレベル: 3+

初速と重力による2次元の弾道飛行・放物線運動(打ち上げ、落下、破片の飛び散り)を計算します。mt.bounce_y / mt.bounce_x が「面にぶつかって跳ねる」動きなのに対し、こちらは着地しない「投げ出される」動き(破片の飛散、爆発、放り投げ)向けです。

引数 ​

引数型単位省略時内容
configtable-指定必須発射からの経過時間、初速、方向、重力などの設定

config ​

フィールド型単位省略時内容
tnumber秒0.0発射からの経過時間。負値は0として扱います
speednumbercanvas正規化変位/秒0.0初速
anglenumber度0.0発射方向。0は右で、正方向は時計回りです。-90で真上になります
gravitynumbercanvas正規化変位/秒²4.0下向きの加速度
spinnumber度/秒0.0角速度。戻り値のrotationを同名フィールドへそのまま渡せます
dragnumber1/秒0.0空気抵抗の指数減衰率。0では減衰しません
start_x / start_ynumbercanvas正規化位置0.0発射位置。省略時は原点からの相対変位を返します

引数並び形式 ​

引数型単位省略時内容
tnumber秒0.0発射からの経過時間。負値は0として扱います
speednumbercanvas正規化変位/秒0.0初速
anglenumber度0.0発射方向
gravitynumbercanvas正規化変位/秒²4.0下向きの加速度
spinnumber度/秒0.0角速度
dragnumber1/秒0.0空気抵抗の指数減衰率

引数並び形式では発射位置を指定できないため、原点からの相対変位を返します。

戻り値(いずれか) ​

型単位内容
table-テーブル形式では、x、y、rotation、velocity_x、velocity_yを持つ結果を返します。同じ値を[1]〜[5]でも取得できます
複数のnumber各値に準拠引数並び形式では、x、y、rotation、velocity_x、velocity_yを同じ順に返します

IMPORTANT

角度は画面基準(時計回り)ですが、戻り値の y は Canvas 基準(上が正)です。angle = -90(真上へ発射)とすると y は増加し、重力で減少へ転じます。offset_y にそのまま加算できます。

使用例 ​

lua
-- 破片を扇状に飛ばし、回転させながら落下させる
local angle = mt.random_range(seed, index, -140.0, -40.0, "angle")
local speed = mt.random_range(seed, index, 0.6, 1.2, "speed")
local flight = mt.projectile_2d({
    t = ctx.time - burstTime,
    speed = speed,
    angle = angle,
    gravity = 3.0,
    spin = mt.random_range(seed, index, -360.0, 360.0, "spin"),
})
part.offset_x = 0.5 + flight.x
part.offset_y = 0.5 + flight.y
part.rotation = flight.rotation

放物線を読み取れる状態に保つ ​

戻り値の x / y は常に正しい放物線です。飛び方がおかしく見えるとき、原因が 軌道側にあることはまれで、たいていはその上に重ねた処理です。

  • pivot_* は触らない。 0.5 のままにします。飛行変位を pivot にも加算すると、 破片は弧をたどらず離れた点を中心に円運動します。「ピボットの基準点」を参照してください。
  • 回転量に上限を設ける。 spin は軌道を曲げませんが、毎秒何回転もする破片は その場で転がっているように見え、弧が読み取れなくなります。3D の yaw / pitch は、 経過時間に掛けて無制限に累積させるのではなく、総回転角を指定して姿勢を 落ち着かせる形を推奨します。
  • 真の放射方向だけではほとんど弧を描かない。 一行のテキストでは外向き方向が ほぼ水平なので、落ちてくるための高さが生まれません。方向を真上(-90)へ ブレンドして、破片に十分な浮きを与えてください。

mt.friction_decay(t, speed, friction) ​

APIレベル: 3+

摩擦による指数関数的減速(慣性スライド、ブレーキ、停止アニメーション)を計算します。「勢いよく入ってスーッと止まる」動きを、到達時間ではなく初速と摩擦係数という物理量で制御できます。

引数 ​

引数型単位省略時内容
tnumber秒指定必須経過時間。負値は0として扱います
speednumbercanvas正規化変位/秒指定必須初速
frictionnumber1/秒0.0減衰率。大きいほど早く止まります

戻り値(多値) ​

型単位内容
numbercanvas正規化変位distance。それまでに進んだ距離
numbercanvas正規化変位/秒currentSpeed。その時点での速度

最終的な移動距離は speed / friction に収束します。逆にいえば、止まってほしい距離が決まっているなら speed = distance * friction と置けます。

mt.ease.out_expo との使い分け: イージングは「決まった時間で 0→1 を進む」進行度なのに対し、こちらは初速と摩擦が独立した物理量なので、初速だけを変えて減速の質感は揃えるといった調整ができます。

使用例 ​

lua
-- 左から滑り込んで摩擦で止まる
local travelled = mt.friction_decay(ctx.time - startTime, 2.0, 4.0)
character.offset_x = 0.5 - 0.5 + travelled

NOTE

friction が極めて小さい(1e-4 以下)場合は等速直線運動として扱います。数式上の桁落ちを避けるためで、実用上は摩擦なしと同じ挙動です。

9. 色 ​

color の形式は概念編の「color」を参照してください。 RGBAはcolorの格納形式です。色を計算する場合は、用途に合う色空間を選択してください。

mt.color.resolve_fill(ctx, target, options?) ​

APIレベル: 6+

文字またはパートに適用される塗りを解決し、基本色、塗りモード、オブジェクト不透明度を 返します。OnLayoutとOnPathで使用できます。optionsなしでは対象が描画される最終的な塗りを返し、 options.levelで継承を途中の段階までに止められます(スタイルの継承を参照)。

引数 ​

引数型単位省略時内容
ctxtable-指定必須現在のOnLayout / OnPath context
targetcharacter | part-指定必須ctx.charsまたはctx.partsの要素
optionstable-nil(12+) { level = "global" | "character" | "part" }

戻り値 ​

値型単位内容
colorcolor-継承解決後の単色、またはGlobalグラデーション/Crayonの始端となるctx.global.fill.colorのコピー
modestring-"solid" / "gradient" / "crayon" / "transparent"
opacitynumber0-1Global、所有文字、対象パートのopacityを乗算し、0-1へクランプした値

パートではpart.fill.use、所有文字のfill.use、Globalの順に解決します。文字では文字と Globalだけを解決し、その文字に属するパートの個別色は調べません。個別色が選ばれた場合、 modeは常に"solid"です。

Globalまで継承した場合、fill.transparentがtrueなら"transparent"、 gradient.color_spaceが"none"なら"solid"、"crayon"なら"crayon"、 それ以外のグラデーションモードなら"gradient"を返します。

opacityにはcolor自身のaは乗算されません。返されるcolorは新しいテーブルなので、 変更しても元のfill.colorには影響しません。

lua
for _, part in mt.each_part(ctx) do
    local color, mode, opacity = mt.color.resolve_fill(ctx, part)
    if mode == "gradient" and opacity > 0.0 then
        -- このパートはGlobalグラデーションで塗られる
        print(color.r, ctx.global.gradient.end_color.r)
    end
end

Colorの生成・分解・補間 ​

以下の関数は新しいtableを返し、引数を変更しません。from_*は成分からcolorを作り、 to_*はcolorを成分tableへ分解し、lerp*は2色とtからcolorを作ります。 省略可能なalphaと、to_*へ渡したcolorに存在しないaは1.0になります。 hueは一周を1とする値で、範囲外の入力は[0, 1)へ周回します。すべての補間関数で tはクランプされません。OKHSV/OKHSLのsaturation、value、lightness入力は 0-1へ制限されます。lerp_oklch/lerp_okhsv/lerp_okhslは既定で最短の色相経路を通り、 無彩色端では有彩色端の色相を使います。正確に半周なら元の色相差の符号を維持します。 lerp_oklch(from, to, t, "long")で長い色相経路を選べます。 "short"または省略時は短い経路です。"long"で両端の色相が同じ場合は増加方向へ一周します。 無彩色端が有彩色端の色相を引き継いだ場合も同様です。それ以外のhueMethodはエラーになります。

APIレベル: 1+

  • mt.color.lerp(from, to, t) - RGBA成分を線形補間します。
  • mt.color.from_hsv(hue, saturation, value, alpha?) - 正規化HSVからcolorを作ります。
  • mt.color.with_alpha(color, alpha) - RGBを保ち、alphaだけを置き換えます。
  • mt.color.from_oklch(lightness, chroma, hue, alpha?) - OKLCHからcolorを作ります。chromaは通常0-0.4程度で、RGB出力は0-1へ制限されます。

APIレベル: 8+

  • mt.color.from_oklab(lightness, aAxis, bAxis, alpha?) - OKLab成分からRGBA colorを作ります。RGB出力は0-1へ制限されます。
  • mt.color.to_oklab(color) - { lightness, a, b, alpha }へ変換します。入力RGBは制限しません。
  • mt.color.to_oklch(color) - { lightness, chroma, hue, alpha }へ変換します。無彩色のhueは0です。
  • mt.color.from_okhsv(hue, saturation, value, alpha?) - sRGB gamutに正規化されたOKHSVからcolorを作ります。
  • mt.color.to_okhsv(color) - { hue, saturation, value, alpha }へ変換します。無彩色のhueは0です。
  • mt.color.from_okhsl(hue, saturation, lightness, alpha?) - sRGB gamutに正規化されたOKHSLからcolorを作ります。
  • mt.color.to_okhsl(color) - { hue, saturation, lightness, alpha }へ変換します。無彩色のhueは0です。
  • mt.color.lerp_oklab(from, to, t) - OKLabの直交座標で補間します。
  • mt.color.lerp_oklch(from, to, t, hueMethod?) - OKLCHで補間します。hueMethodは"short"(既定)または"long"です。
  • mt.color.lerp_okhsv(from, to, t) - OKHSVで最短の色相経路に沿って補間します。
  • mt.color.lerp_okhsl(from, to, t) - OKHSLで最短の色相経路に沿って補間します。

10. スタイルの継承 ​

塗り・ストローク・シャドウ・ぼかし・テクスチャは、ctx.global、所属する文字、パートの3段階で継承されます。 要素の use フラグは継承するグループ全体を置き換えるため、shadow.use はシャドウの色とぼかしをまとめて切り替えます。 resolve関数は、要素が描画に使うグループを返します。 mt.color.resolve_fill、mt.shadow.resolve、mt.blur.resolve、mt.stroke.resolve、mt.texture.resolve です。

options なしでは対象の最終値を返します。パートでは自身の上書きを含み、文字ではその文字に属するパートの上書きを含みません。 options.level で継承を途中の段階までに止められます。

level返す値
"global"フレームの値(ctx.global)
"character"所属する文字の上書きまでを反映した値
"part"パートの上書きまでを反映した値(パートの既定)

文字の既定は "character" で、対象自身の段階より下の level はエラーです。上書きしたグループの1項目だけを変えるには、 level で上位の段階を読み、use を設定して値を書き戻します。

lua
function OnLayout(ctx)
    for _, part in mt.each_part(ctx) do
        local shadow = mt.shadow.resolve(ctx, part, { level = "character" })
        -- このパートのシャドウだけぼかしを足し、色は継承した値のままにする。
        part.shadow.use = true
        part.shadow.color = shadow.color
        part.shadow.blur_x = shadow.blur_x + 0.2
        part.shadow.blur_y = shadow.blur_y + 0.2
    end
end

NOTE

shadow.use = true のパートは、個別のシャドウ色と同じく、全体のシャドウがOFFでもシャドウを落とします。

どれも OnLayout と OnPath で使え、返される色は新しいテーブルなので、変更しても元の設定には影響しません。

すべてのresolve関数の引数:

引数型単位既定値説明
ctxtable-必須現在のOnLayoutまたはOnPathのコンテキスト
targetcharacter | part-必須ctx.chars または ctx.parts の要素
optionstable-nil{ level = "global" | "character" | "part" }

APIレベル: 12+

mt.shadow.resolve(ctx, target, options?) ​

シャドウを解決します。{ color, blur_x, blur_y, glow }(シャドウ色、水平・垂直のぼかし(em)、グローの強さ)を返します。

mt.blur.resolve(ctx, target, options?) ​

文字本体のぼかしを解決します。{ amount_x, amount_y, glow }(ぼかし(em)とグローの強さ)を返します。

mt.stroke.resolve(ctx, target, options?) ​

ストロークを解決します。{ width, gap, color, outer_width, outer_color } を返します。order・join・miter_limit は ctx.global.stroke にだけ存在します。

mt.texture.resolve(ctx, target, options?) ​

テクスチャを解決します。{ type, p1, p2, p3, p4, color } を返します。

11. イージング ​

APIレベル: 1+

mt.ease.<name>(t) は進行度 t(通常0-1)を受け取り、緩急のついた進行度を返します。 mt.stagger や mt.cycle が返す直線的な進行度に表情を付けるのが典型的な使い方です。 mt.ease.cubic_bezierを除き、入力tは自動でクランプされません。0-1に制限する場合は、 mt.saturateを通してから渡してください。

名前は「カーブの種類」と「向き」の組み合わせです。

  • in_ - 加速(ゆっくり始まり、速く終わる)。退場向き
  • out_ - 減速(速く始まり、ゆっくり止まる)。登場向き
  • in_out_ - 前半加速・後半減速
カーブ使いどころ
Linear等速(変化なし)
Quad最も緩やかな加減速
Cubic標準的な加減速。迷ったらまずこれ
QuartCubicより急峻
Sineサイン波由来のごく緩やかな緩急
Circ端で急激に立ち上がる円弧カーブ
Expo指数的な非常に強い緩急
Back一度行き過ぎてから戻る(0-1の外へはみ出す)
Elasticバネのように振動しながら収まる(0-1の外へはみ出す)
Bounce床で弾むようなバウンド

BackとElasticは戻り値が0-1の範囲を超えることがある点に注意してください(それがはみ出し表現の 本体です)。

以下の関数はmt.ease.cubic_bezierを除き、すべて引数t(number、進行度、クランプなし)を1つ取りnumberを返します。cubic_bezierのシグネチャは表に併記しています。

関数特性戻り値
mt.ease.linear(t)入力した進行度をそのまま返す、等速のイージングです。入力したtと同じ値
mt.ease.in_quad(t)ゆっくり始まり、徐々に加速する2次関数のイージングです。t²で計算した進行度
mt.ease.out_quad(t)速く始まり、徐々に減速する2次関数のイージングです。1 - (1 - t)²で計算した進行度
mt.ease.in_out_quad(t)前半で加速し、後半で減速する2次関数のイージングです。t = 0.5を中心にin_quadとout_quadを対称に組み合わせた進行度
mt.ease.in_cubic(t)ゆっくり始まり、徐々に加速する3次関数のイージングです。t³で計算した進行度
mt.ease.out_cubic(t)速く始まり、徐々に減速する3次関数のイージングです。1 - (1 - t)³で計算した進行度
mt.ease.in_out_cubic(t)前半で加速し、後半で減速する3次関数のイージングです。t = 0.5を中心にin_cubicとout_cubicを対称に組み合わせた進行度
mt.ease.in_quart(t)ゆっくり始まり、Cubicより急峻に加速する4次関数のイージングです。t⁴で計算した進行度
mt.ease.out_quart(t)速く始まり、Cubicより急峻に減速する4次関数のイージングです。1 - (1 - t)⁴で計算した進行度
mt.ease.in_out_quart(t)前半で加速し、後半で減速する4次関数のイージングです。t = 0.5を中心にin_quartとout_quartを対称に組み合わせた進行度
mt.ease.in_sine(t)サイン波由来の、ごく緩やかに加速するイージングです。1 - cos(t × π / 2)で計算した進行度
mt.ease.out_sine(t)サイン波由来の、ごく緩やかに減速するイージングです。sin(t × π / 2)で計算した進行度
mt.ease.in_out_sine(t)サイン波由来の、前半で加速し後半で減速するイージングです。t = 0.5を中心にin_sineとout_sineを対称に組み合わせた進行度
mt.ease.in_circ(t)円弧を使い、終端へ向かって急激に加速するイージングです。1 - √(1 - t²)で計算した進行度
mt.ease.out_circ(t)円弧を使い、開始直後に急激に進んでから減速するイージングです。√(1 - (1 - t)²)で計算した進行度
mt.ease.in_out_circ(t)円弧を使い、前半で加速し後半で減速するイージングです。t = 0.5を中心にin_circとout_circを対称に組み合わせた進行度
mt.ease.in_expo(t)指数関数を使い、終端へ向かって非常に強く加速するイージングです。t <= 0では0、それ以外では2^(10t - 10)で計算した進行度
mt.ease.out_expo(t)指数関数を使い、開始直後に非常に強く進んでから減速するイージングです。t >= 1では1、それ以外では1 - 2^(-10t)で計算した進行度
mt.ease.in_out_expo(t)指数関数を使い、前半で非常に強く加速し、後半で非常に強く減速するイージングです。t = 0.5を中心にin_expoとout_expoを対称に組み合わせた進行度
mt.ease.in_back(t)開始直後に負方向へ少し戻ってから、終端へ加速するイージングです。開始付近で0未満へ行き過ぎる進行度
mt.ease.out_back(t)終端を少し越えてから戻りながら減速するイージングです。終端付近で1を超えて行き過ぎる進行度
mt.ease.in_out_back(t)開始付近と終端付近の両方で行き過ぎるイージングです。t = 0.5を中心にin_backとout_backを対称に組み合わせた進行度
mt.ease.in_elastic(t)振動しながら振幅を広げ、終端へ加速するイージングです。0-1の範囲外へ振動する進行度。t <= 0とt >= 1ではtをそのまま返します
mt.ease.out_elastic(t)終端の周囲を振動しながら減速して収束するイージングです。0-1の範囲外へ振動する進行度。t <= 0とt >= 1ではtをそのまま返します
mt.ease.in_out_elastic(t)前半で振動しながら加速し、後半で振動しながら減速して収束するイージングです。t = 0.5を中心にin_elasticとout_elasticを対称に組み合わせた進行度
mt.ease.in_bounce(t)開始側で弾んでから終端へ向かうイージングです。out_bounceを時間反転した進行度
mt.ease.out_bounce(t)床で複数回弾むように減速して終端へ到達するイージングです。区間ごとの2次関数でバウンドを表現した進行度
mt.ease.in_out_bounce(t)開始側と終端側の両方で弾むイージングです。t = 0.5を中心にin_bounceとout_bounceを対称に組み合わせた進行度
mt.ease.cubic_bezier(x1, y1, x2, y2, t)CSSのcubic-bezier() timing-functionと互換の3次Bézierカーブを評価します。 上記の定義済みカーブで足りないときに、任意の緩急を数値で指定できます。指定したBézierカーブ上の進行度

circ系の3関数は平方根を含むため、通常はtを0-1に制限して使用します。

mt.ease.cubic_bezierの引数 ​

引数型単位省略時内容
x1 / y1number-指定必須第1制御点
x2 / y2number-指定必須第2制御点
tnumber-指定必須進行度。t <= 0では0、t >= 1では1へ固定されます

CSS互換の単調な時間曲線として使用する場合は、x1とx2を0-1にします。

使用例 ​

lua
-- CSSの ease-in-out と同じカーブ
local eased = mt.ease.cubic_bezier(0.42, 0.0, 0.58, 1.0, progress)

12. 再組版・行単位のグループ化 ​

mt.layout.reflow(ctx, gap?, config?) ​

APIレベル: 2+

横書きではgeometry.canvas_origin_*、縦書きでは geometry.vertical_origin_*を使い、隣接する自然原点の差からシェーピング・kerning・tracking・ margins由来の間隔を保持したまま、現在のscale * stretchを送りへ反映します。個別rotationと pivotも原点整列へ含まれます。可視インク輪郭間の距離を均一化する関数ではありません。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト
gapnumbercanvas幅比または高さ比0.0隣接する送りへ追加する余白。正値は進行方向の間隔を広げます
configtable-nil再組版する方向・対象・固定位置の設定

config ​

フィールド型単位省略時内容
modestring-ctx.global.verticalから決定再組版する方向。"horizontal"または"vertical"
targetstable-全文字再組版する1始まりの文字index配列。対象間に飛ばした文字があれば、その文字の送りは計算へ含みますが座標は変更しません
anchorinteger-各行/列の先頭文字現在の変形済み組版原点を固定し、その両側を並べる文字index

targetsを省略すると、各line_indexを独立した行/列として全文字を再組版し、それぞれの 先頭文字を固定します。config.anchorを指定した場合は、その所属行だけ指定文字を固定します。

戻り値 ​

戻り値はありません。

変更内容 ​

対象文字のoffset_xとoffset_yを書き換えます。サイズ・回転・pivotのアニメーションを 設定した後、そのフレームの最終レイアウト処理として呼び出してください。

制約・エラー ​

  • modeには"horizontal"または"vertical"を指定します。
  • targetsのindexは有効範囲内で厳密な昇順に並べ、重複させないでください。
  • targetsに含める文字はすべて同じline_indexに属する必要があります。
  • targetsを指定した場合、anchorはその配列に含まれる文字を指定します。
  • targetsを省略した場合、anchorは有効な文字indexを指定します。

使用例 ​

lua
mt.layout.reflow(ctx, 0.02, {
    targets = {3, 4, 7, 8}, -- 5, 6は送りへ含むが移動しない
    anchor = 3,
})

mt.layout.group_by_line(ctx) ​

APIレベル: 4+

シェーピング済み文字をline_indexごとにグループ化し、ホストの読み順で返します。 横書きでは行、縦書きでは列を表します。レイアウトや文字プロパティは変更しません。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト

戻り値 ​

型単位内容
table-line_indexごとのグループを組版上の行/列順に格納した配列

各グループは次のフィールドを持ちます。

フィールド型単位内容
line_indexinteger-グループに対応する行/列のindex
item_countinteger個グループ内の文字数
itemstable-読み順に並んだ文字の配列

使用例 ​

lua
local columns = mt.layout.group_by_line(ctx)
for columnOrder, column in ipairs(columns) do
    for indexInColumn, character in ipairs(column.items) do
        local start = (columnOrder - 1) * 0.2 + (indexInColumn - 1) * 0.05
        character.opacity = mt.saturate((ctx.time - start) / 0.4)
    end
end

13. Canvas上の位置・距離・支点 ​

mt.layout.place_2d(ctx, item, canvasX, canvasY) ​

APIレベル: 2+

文字またはパーツのアンカーを、3D・camera・projection・Deform適用前のcanvas正規化位置へ 正確に配置します。global、所有文字、対象自身のoffset / pivot / rotation / scale / stretchを、Native描画と同じ階層・同じ非正方形canvasの画素座標で合成して逆算します。

  • 文字アンカー: 自然インク境界中心geometry.bounds_center_x/y
  • パーツアンカー: パーツローカル自然中心(描画パスのローカル原点)
  • 図形アンカー: 図形の位置(パスの原点。offsetしなければcanvas中心)。Globalは図形に届かないので、図形自身のoffset / pivot / rotation / scale / stretchだけが関わります

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト
itemtable-指定必須対象の文字またはパーツ
canvasX / canvasYnumbercanvas正規化位置指定必須配置先の座標

戻り値(多値) ​

型単位内容
numbercanvas正規化変位設定したoffsetX
numbercanvas正規化変位設定したoffsetY

変更内容 ​

対象のoffset_xとoffset_yを直接更新します。

制約・エラー ​

変換階層内のscale * stretchが0の場合は逆変換できないため、エラーになります。

使用例 ​

lua
mt.layout.place_2d(ctx, ctx.chars[1], 0.8, 0.8)
mt.layout.place_2d(ctx, ctx.parts[1], 0.5, 0.5)

mt.layout.get_canvas_position_2d(ctx, item) ​

APIレベル: 3+

文字またはパーツのアンカーの、現在の 3D 変換前の Canvas 座標 (canvasX, canvasY)(0.0〜1.0 の正規化 Y-up 座標系)を取得します。引数 item に文字(ctx.chars[i])またはパーツ(ctx.parts[j])のいずれを渡しても自動的に判定されます。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト
itemtable-指定必須対象の文字またはパーツ

戻り値(多値) ​

型単位内容
numbercanvas正規化位置アンカーのcanvasX
numbercanvas正規化位置アンカーのcanvasY

使用例 ​

lua
-- 文字(Character)の Canvas 位置を取得
local charX, charY = mt.layout.get_canvas_position_2d(ctx, ctx.chars[1])

-- パーツ(Part)の Canvas 位置を取得(自動判定)
local partX, partY = mt.layout.get_canvas_position_2d(ctx, ctx.parts[1])

mt.layout.match_pose(ctx, destination, source, options?) ​

APIレベル: 9+

sourceの現在の姿勢を同じ種類のdestinationへ同期します。Character同士、または同じCharacterが 所有するPart同士に使用できます。OnLayout専用です。適用順はsize、rotation、depth、opacity、positionです。

option型既定値内容
positionbooleantrue3D適用前のcanvas位置を同期
position_delta_x / position_delta_ynumber0.0sourceローカルX/Y軸に沿う変形前em単位の変位
rotationbooleantrue2D回転を同期
rotation_offsetnumber0.0同期後の回転へ加える度数
sizestring"copy""none" / "copy" / "match_bounds"
size_scale_x / size_scale_ynumber1.0同期後の各軸倍率。正数のみ
depthbooleantruez / yaw / pitchを同期
z_offsetnumber0.0同期後のZへ加えるcanvas比変位
yaw_offset / pitch_offsetnumber0.0同期後に加える角度(度)
opacitybooleanfalseopacityを同期
opacity_scalenumber1.0同期後のopacity倍率。0以上

match_boundsは自然boundsの幅・高さの比をstretchへ反映します。sourceのink boundsが0の軸では 論理文字セルを使います。横書きのXは水平送り、縦書きのYは垂直送りを優先し、送りも0の場合と 交差軸は1emです。Partは送りを持たないため1emを使います。destinationのboundsが0の軸では その軸の実効scaleを維持し、他の軸と姿勢の同期を継続します。destinationのpivotは変更しません。

position deltaのX/Yはどちらも変形前の1emを1.0とし、画面固定のX/Y方向ではありません。CharacterではGlobalとsource Character、Partでは Global、所有Character、source Partのrotation・scale・stretchを通してから同期位置へ加えます。 したがってsourceを回転・拡縮するとdeltaの方向と長さも追従します。rotation_offsetとsize_scaleは destination側の補正なのでdelta変換には含まれません。

lua
mt.layout.match_pose(ctx, ctx.chars[4], ctx.chars[1], {
    size = "match_bounds",
    size_scale_x = 1.15,
    size_scale_y = 1.2,
    position_delta_y = -0.75,
})

mt.layout.canvas_to_offset_2d(ctx, item, canvasX, canvasY) ​

APIレベル: 3+

文字またはパーツを指定した 3D 変換前の Canvas 座標 (canvasX, canvasY) に配置するために必要な offset_x, offset_y を計算して返却します(プロパティ自体の書き換えは行いません)。引数 item に文字またはパーツを渡すことで自動判定されます。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト
itemtable-指定必須対象の文字またはパーツ
canvasX / canvasYnumbercanvas正規化位置指定必須配置先の座標

戻り値(多値) ​

型単位内容
numbercanvas正規化変位必要なoffsetX
numbercanvas正規化変位必要なoffsetY

対象のフィールドは変更しません。

制約・エラー ​

逆変換する親階層のscale * stretchが0の場合はエラーになります。

使用例 ​

lua
-- 文字を Target Canvas 座標 (0.5, 0.8) に配置するための offset を逆算
local cox, coy = mt.layout.canvas_to_offset_2d(ctx, ctx.chars[1], 0.5, 0.8)

-- パーツを Target Canvas 座標 (0.2, 0.3) に配置するための offset を逆算(自動判定)
local pox, poy = mt.layout.canvas_to_offset_2d(ctx, ctx.parts[1], 0.2, 0.3)

mt.layout.radial_distance(ctx, canvasX, canvasY, centerX?, centerY?) ​

APIレベル: 3+

放射状エフェクトの中心から、指定した Canvas 座標までの距離を返します。centerX / centerY を省略した場合は画面中央 (0.5, 0.5) が中心になります。

引数 ​

引数型単位省略時内容
ctxtable-指定必須canvas情報を持つコンテキスト
canvasX / canvasYnumbercanvas正規化位置指定必須距離を測る座標
centerX / centerYnumbercanvas正規化位置0.5効果の中心

戻り値 ​

型単位内容
numbercanvas高さ比アスペクト比を補正した中心からの距離

IMPORTANT

アスペクト比が補正されます。 Canvas の正規化座標は縦横で 1.0 の実寸が異なるため、単純に sqrt(dx² + dy²) で距離を求めると、16:9 のような横長プロジェクトでは同心円のつもりが楕円に潰れます。この関数は横方向を ctx.canvas.aspect_ratio 倍して補正するので、返る距離は常に真円基準です。

使用例 ​

lua
-- 中心から広がる波紋。文字ごとの距離に応じて峰が通過する
for index = 1, ctx.char_count do
    local character = ctx.chars[index]
    local geometry = character.geometry
    local radius = mt.layout.radial_distance(ctx, geometry.bounds_center_x, geometry.bounds_center_y)
    local crest = mt.falloff(radius - waveFront, 0.2)
    character.offset_y = character.offset_y + crest * 0.08
end

mt.layout.pivot_at_2d(ctx, item, anchor) ​

APIレベル: 4+

文字またはパーツを自動判定し、意味的な2D位置へpivotを設定します。変更前後のローカル2D行列差を offset_x/yへ補正するため、現在のrotation、scale、stretchによる3D適用前の姿勢は移動しません。 Globalは対象外です。yaw、pitch、z、カメラ、投影後の見た目は維持対象に含みません。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト
itemtable-指定必須対象の文字またはパーツ
anchorstring-指定必須設定する意味的な2D位置名

戻り値 ​

戻り値はありません。

変更内容 ​

対象のpivot_xとpivot_yを設定し、姿勢が移動しないようoffset_xとoffset_yを補正します。

anchor ​

文字とパーツに共通するanchorは次のとおりです。

  • "center": ink boundsの中心
  • "top" / "bottom": ink boundsの水平中央と上端/下端の交点
  • "left" / "right": ink boundsの左端/右端と垂直中央の交点
  • "top_left" / "top_right" / "bottom_left" / "bottom_right": ink boundsの各角

文字ではさらに次のanchorを指定できます。

  • "baseline_left" / "baseline" / "baseline_right": ink boundsの左端/中央/右端と横組みベースラインの交点
  • "typesetting_origin": 文字セル左端と横組みベースラインの交点
  • "vertical_start" / "vertical_center" / "vertical_end": 縦組みの列中心軸と文字セルの始端/中央/終端の交点

既存のpivot値はbounds内の0〜1比率ではありません。0.5を自然中心とし、Xはcanvas幅比、 Yはcanvas高さ比の変位です。この関数がbounds寸法、文字の組版原点、文字/パーツで異なる 自然中心を既存pivot単位へ変換します。

使用例 ​

lua
mt.layout.pivot_at_2d(ctx, character, "top")
character.rotation = math.sin(ctx.time * 3.0) * 8.0

14. 2D変換後の境界 ​

mt.layout.measure_bounds_2d(ctx, targets?, targetType?, space?) ​

space(level 12+)は既定"canvas"。"before_global_rotation"はGlobalの位置+ピボットを中心とする回転だけを除いて計測します。scale・stretch・個別変形・組版は保持し、結果はCanvas正規化Y-up座標です。この空間で描いた装飾には、同じ中心のGlobal回転を再適用します。ctxやInspectorの値は変更しません。

APIレベル: 2+

指定対象の自然境界矩形をglobal→文字→パーツの完全な2D階層で変換し、その全頂点を囲む canvas軸平行境界を返します。文字を指定した場合は所有パーツの自然境界を合成し、パーツを持たない 文字は文字の自然境界を使います。対象フィールドを書いた後に呼び出してください。

この境界は3D・camera・projection・Deform適用前です。strokeとshadowの張り出し、および 自然境界矩形内に余白を持つ輪郭のpath-tight境界は含みません。この段階と定義に対しては近似ではなく、 rotation・pivot・負のstretch・親文字変形・global変形をすべて反映します。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト
targetstable | nil-全件1始まりの文字またはパーツindex配列。nilなら対象種別の全要素
targetTypestring-"character"対象の種類。"character"または"part"
spacestring-"canvas""canvas"または"before_global_rotation"

戻り値(いずれか) ​

型単位内容
table-有効な対象全体を囲む境界
nil-有効な対象がない場合

境界tableは次のフィールドを持ちます。座標系はすべてY-upです。

フィールド型単位内容
left / rightnumbercanvas正規化位置左端と右端
bottom / topnumbercanvas正規化位置下端と上端
center_x / center_ynumbercanvas正規化位置境界の中心
width / heightnumbercanvas正規化変位境界の幅と高さ

制約・エラー ​

targetsを省略すると全件を指定できます。targetTypeが"character"なら 全文字、"part"なら全パートを対象にします。空table {} は全件指定ではなく、従来どおり 対象なしとしてnilを返します。

全件文字指定にはパートを持たない文字も含まれ、その文字の自然境界を使用します。全件パート 指定にはctx.partsに存在するパートだけが含まれます。不可視状態、opacity、write-onは 対象選択へ影響せず、指定対象の幾何境界を計測します。

使用例 ​

lua
local bounds = mt.layout.measure_bounds_2d(ctx, {1, 2, 3})
if bounds then
    mt.layout.place_2d(ctx, ctx.chars[4], bounds.center_x, bounds.top + 0.05)
end

local allCharacterBounds = mt.layout.measure_bounds_2d(ctx)
local allPartBounds = mt.layout.measure_bounds_2d(ctx, nil, "part")

15. パス上への整列 ​

mt.layout.queue_on_path(ctx, path, options?) ​

APIレベル: 3+

mt.path.arc_lengthで作ったパス上に、文字(またはパーツ)を読み順のまま並べ、各要素が 占める距離比(0-1)を返します。

間隔はホストが実際に組版した原点の間隔から求めます(mt.layout.reflowと同じ方式)。 そのためtracking・文字ごとのmargins・カーニングといったパラメータ設定が、そのまま パス上の字送りに反映されます。options.gapはそれに上乗せする追加間隔なので、gapが 0ならホストの字送りどおりに並びます。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutのコンテキスト
pathtable-指定必須mt.path.arc_lengthの戻り値
optionstable-nil配置方法の設定
options.alignstring-"end"文字列を置く位置。"end"、"start"、"center"を指定します
options.gapnumbercanvas幅比0.0ホストの字送りへ上乗せする追加間隔
options.modestring-"horizontal"ホストの組版方向。"horizontal"または"vertical"
options.target_typestring-"character"対象の種類。"character"または"part"
options.targetstable-全要素読み順に並べた対象index配列

戻り値 ​

型単位内容
table0-1ctx.charsまたはctx.partsと同じindexで、各要素が占めるパス上の距離比を取得できるslots配列

slotsはアニメーションの進行度ではなく、パス上の位置を表します。

進行方向と読み順 ​

スロットは進行方向に沿った距離の昇順で割り当てられます。基準は画面の左右ではなく パスの進行方向です。targetsを省略した場合はindexの昇順に割り当てるため、パスが 左から右へ進むならそのまま画面上の読み順になります。

IMPORTANT

右から左へ進むパスでは、距離の昇順が x の減少方向になります。 そのためtargetsを 省略すると文字1が最も右、文字Nが最も左に置かれ、画面上では文字列が逆転して見えます。 左から右に読める配置にしたい場合は、targetsを読み順の逆で渡してください。

lua
-- 右から左へ進むパスで、画面上の読み順を保つ
local targets = {}
for index = ctx.char_count, 1, -1 do
    targets[#targets + 1] = index
end
local slots = mt.layout.queue_on_path(ctx, path, { targets = targets })

これはトレードオフであり、逆向きパスでは次の2つを同時には満たせません。どちらを取るかは 用途によって選んでください。

targets画面上の並び隊列の先頭
省略(index昇順)逆転(右→左に読む)文字1
読み順の逆正しい(左→右に読む)最後の文字

alignも同様に進行方向基準です。"end"はパスの終端に文字列の末尾を置くため、 右から左へ進むパスでは末尾が画面の左側に来ます。

パスの向きalign = "end"で末尾が来る位置
左→右画面右側
右→左画面左側

使用例 ​

lua
-- 用途1: パスに沿ってテキストを並べる(静止)
local path = mt.path.arc_length(kPathPoints, ctx.canvas.aspect_ratio)
local slots = mt.layout.queue_on_path(ctx, path, { gap = 0.004 })
for index = 1, ctx.char_count do
    local x, y, heading = path:at_distance(slots[index])
    ctx.chars[index].rotation = heading
    mt.layout.place_2d(ctx, ctx.chars[index], x, y)
end
lua
-- 用途2: パスを走って自分のスロットで停止する(隊列がブレーキ)
local path = mt.path.arc_length(kPathPoints, ctx.canvas.aspect_ratio)
local slots = mt.layout.queue_on_path(ctx, path, { align = "end" })
local progress = mt.ease.out_cubic(mt.saturate(ctx.time / 3.2))
for index = 1, ctx.char_count do
    -- math.minが隊列の停止そのもの: 先頭は終端まで、後続は自分の位置で止まる
    local x, y, heading = path:at_distance(math.min(progress, slots[index]))
    ctx.chars[index].rotation = heading
    mt.layout.place_2d(ctx, ctx.chars[index], x, y)
end

NOTE

文字列の総長がパス全長を超える場合、距離比が0と1にクランプされ、文字同士が重なります。 長いテキストを短いパスに載せる場合は、path:length()で収まるか確認してください。

16. モーションパス ​

制御点に沿って「流れ込むように登場する」「弧を描いて着地する」といった動きを表現する 曲線評価APIです。

座標系は決め打ちされていません。点は単なる { x, y } テーブルで、呼び出し側が 渡した座標系(offsetの正規化座標、canvas px、文字ローカル座標など)をそのまま受け取り、 同じ座標系の値を返します。

NOTE

戻り値を offset_x / offset_y に直接代入するときは、点も offset の単位 (中立値 0.5 のcanvas正規化変位)で置いてください。 下記の例は着地点を { x = 0.5, y = 0.5 }(変位ゼロ)にしているため、character.offset_x = x がそのまま 自然位置への着地になります。canvas 絶対座標や 0 始まりの局所座標を渡したまま offset に代入すると、意図しない位置に飛びます。

いずれの関数も戻り値は x, y, tangentX, tangentY の4つです。tangentX / tangentY は 正規化されていない生の微分値(進行速度も含む)で、進行方向の角度が欲しい場合は math.deg(math.atan(tangentY, tangentX))、単位ベクトルが欲しい場合は local length = math.sqrt(tangentX^2 + tangentY^2) で割ってください。

mt.path.bezier(p0, p1, p2, p3, t) ​

APIレベル: 1+

4点で定義される3次Bézier曲線上の座標と接線を返します。

引数 ​

引数型単位省略時内容
p0table座標指定必須始点{ x, y }
p1table座標指定必須始点側の制御点{ x, y }
p2table座標指定必須終点側の制御点{ x, y }
p3table座標指定必須終点{ x, y }
tnumber0-1指定必須曲線上の位置。範囲外はクランプされず、そのまま外挿されます

戻り値(多値) ​

型単位内容
number入力座標に準拠曲線上のx
number入力座標に準拠曲線上のy
number入力座標に準拠接線のtangentX
number入力座標に準拠接線のtangentY

使用例 ​

lua
-- 文字が弧を描いて自分の自然な位置へ着地する
local p0 = { x = 0.5, y = 0.2 }
local p1 = { x = 0.3, y = 0.6 }
local p2 = { x = 0.5, y = 0.5 }
local p3 = { x = 0.5, y = 0.5 }
local progress = mt.saturate(mt.stagger(ctx.time, index, 0.05, 0.6))
local x, y = mt.path.bezier(p0, p1, p2, p3, mt.ease.out_cubic(progress))
character.offset_x = x
character.offset_y = y

mt.path.catmull_rom(points, t) ​

APIレベル: 1+

任意個数の制御点を通るCatmull-Romスプライン上の座標と接線を返します。Bézierと違い、 リストに並べた点すべてを厳密に通過する曲線になります。

引数 ​

引数型単位省略時内容
pointstable座標指定必須1始まりの通過点配列。{ x, y }を2個以上並べます
tnumber0-1指定必須曲線全体を通した進行度。0-1にクランプされます

戻り値(多値) ​

型単位内容
number入力座標に準拠曲線上のx
number入力座標に準拠曲線上のy
number入力座標に準拠接線のtangentX
number入力座標に準拠接線のtangentY

制約・エラー ​

pointsには2個以上の点が必要です。

使用例 ​

lua
-- あらかじめ決めた3点を通る軌道に沿って文字を流し込む
local waypoints = {
    { x = 0.1, y = 0.8 },
    { x = 0.5, y = 0.3 },
    { x = 0.9, y = 0.8 },
}
local progress = mt.saturate(ctx.time / 1.5)
local x, y = mt.path.catmull_rom(waypoints, progress)
character.offset_x = x
character.offset_y = y

mt.path.arc_length(points, aspectRatio?, options?) ​

APIレベル: 3+

制御点から弧長パラメータ化されたパスを構築します。上記2関数は曲線パラメータtで 評価しますが、tの等間隔は距離の等間隔ではありません。曲線が曲がっている所ではサンプルが 詰まるため、「距離で間隔を取る」用途(隊列、パス上の字送り、等速移動)では必ず累積長テーブルが 必要になります。この関数がそれを1度だけ構築し、距離での参照を提供します。

aspectRatioにctx.canvas.aspect_ratioを渡すと、x方向の差分に掛けて距離の意味を縦横で 揃えます。省略すると正規化単位そのままで測るため、非正方canvasでは間隔が伸び縮みします。

引数 ​

引数型単位省略時内容
pointstable座標指定必須1始まりの制御点配列。canvas正規化座標で指定するとmt.layout.place_2dやmt.layout.queue_on_pathと組み合わせられます
aspectRationumber-1.0X方向の距離へ掛けるアスペクト比。通常はctx.canvas.aspect_ratioを渡します
optionstable-nil曲線の種類を指定する設定
options.kindstring-"catmull_rom""catmull_rom"または"bezier"

戻り値 ​

型単位内容
table-距離による参照を提供するパスオブジェクト

パスオブジェクトは次のメソッドを持ちます。

メソッド戻り値単位内容
path:length()number入力座標に準拠アスペクト比を補正したパス全長
path:at_distance(distanceRatio)3つのnumber入力座標に準拠、度距離比0-1でのx、y、headingDegrees

制約・エラー ​

  • pointsには2個以上の点が必要です。
  • options.kind = "bezier"では、pointsにちょうど4個の点が必要です。
  • options.kindには"catmull_rom"または"bezier"を指定します。

NOTE

at_distanceの3番目の戻り値は度数の向きで、画面座標系(canvasのYは下向き)に変換済みです。 rotationへそのまま代入できます。mt.path.bezier / catmull_romが返す生の接線と違い、 符号を自分で反転する必要はありません。

向きは進行方向に追従します。右から左へ進むパスでは約180度になるため、rotationへ そのまま代入すると文字が上下反転します。傾きを保ったまま正立させるには180.0を加算します。

lua
-- 右から左へ進むパスで文字を正立させる
character.rotation = heading + 180.0

使用例 ​

lua
-- 距離で等間隔に配置する(tで等間隔にすると曲がりで詰まる)
local path = mt.path.arc_length(kWaypoints, ctx.canvas.aspect_ratio)
for index = 1, ctx.char_count do
    local ratio = mt.distribute(index, ctx.char_count)
    local x, y, heading = path:at_distance(ratio)
    ctx.chars[index].rotation = heading
    mt.layout.place_2d(ctx, ctx.chars[index], x, y)
end

17. パスの作成・編集 ​

mt.svg_path(source, optionsOrSourceUnitsPerEm?) ​

APIレベル: 5+

SVGの d 属性と同じ文字列を、再利用可能な読み取り専用パステンプレートへ変換します。 簡易SVG互換として、絶対・相対の M / L / H / V / Q / T / C / S / Z と 連続する座標組を扱います。楕円弧 A / a は未対応です。

引数 ​

引数型単位省略時内容
sourcestring-指定必須SVGのパスデータ
optionsOrSourceUnitsPerEmnumber / table-nil元データの1emあたりの単位数、または{ view_box, em_scale }

戻り値 ​

型単位内容
MtDrawingPath-path:assign(template)へ渡せる読み取り専用のパステンプレート

正規化の指定 ​

数値を指定すると、その値を元データの1emあたりの単位数として1000単位へ正規化します (例: 24単位を1emとして扱う場合は mt.svg_path(source, 24))。

view_box = { minX, minY, width, height } を指定すると、viewBox中央を原点へ移し、縦横比を 維持したまま最大辺を em_scale emへ合わせます。em_scale の既定値は 1.0 です。

制約・エラー ​

  • 数値で指定する1emあたりの単位数は、有限の正数である必要があります。
  • view_boxは4個の有限な数値を持ち、幅と高さは正数である必要があります。
  • em_scaleは有限の正数である必要があります。
  • units_per_emは設定tableでは指定できません。数値形式またはem_scaleを使用します。

使用例 ​

lua
local icon = mt.svg_path(svgPathFrom24PxIcon, {
    view_box = { 0, 0, 24, 24 },
    em_scale = 0.7,
})

function OnPath(ctx)
    for _, part in ipairs(ctx.paths:select("c1, p8-10, !p9")) do
        part.path:assign(icon)
    end
end

IMPORTANT

em_scale は描画サイズ(1emの何倍か)です。em_scale = 0.5 なら半分の大きさになります。 多くのフォントで実際の字面は1emより小さいため、既定の 1.0 ではアイコンが隣の文字へ 食い込むことがあります。その場合は em_scale を下げるか、OnLayout で字送りを広げます。

注意事項 ​

静的なSVG文字列は関数の外側で mt.svg_path に変換して local 変数へ保持すると、 毎フレームの再解析を避けられます。


mt.drawing_path() ​

APIレベル: 9+

空の可変MtDrawingPathを生成します。top levelと全hookで呼び出せます。座標はY-downの part-local座標で、1000単位が1emです。既存の構築メソッドで形状を作り、 ctx.glyphs:declare({ path = path })などへ渡せます。

lua
local diamond = mt.drawing_path()
diamond:move_to(0, -500)
diamond:line_to(500, 0)
diamond:line_to(0, 500)
diamond:line_to(-500, 0)
diamond:close()

描画パス編集API ​

APIレベル: 5+

ctx.pathsで取得したパーツのpathは、次のメソッドで編集できます。

メソッド内容
path:clear()パス内の全コマンドを削除
path:assign(template)mt.svg_pathで作成したテンプレートで置換
path:set_svg(source)SVGのパスデータを解析して置換
path:move_to(x, y)サブパスの始点を追加
path:line_to(x, y)直線を追加
path:quad_to(cx, cy, x, y)2次Bézier曲線を追加
path:cubic_to(cx1, cy1, cx2, cy2, x, y)3次Bézier曲線を追加
path:close()現在のサブパスを閉じる
path:bounds()曲線極値を含むtight boundsを取得
path:map_points(callback)トポロジーを維持して全pointを変形

座標系 ​

パス座標はパーツ中心を原点とするY-downの正規化ローカル座標で、1000単位が1 emです。 API境界で実際のフォントサイズへ自動変換されるため、Canvas解像度には依存しません。

変更の適用 ​

ctx.pathsはフレームごとに再構築されるため、pathの変更は毎フレーム適用してください。 適用しなかったパーツは元のグリフ輪郭に戻ります。


path:clear() ​

APIレベル: 5+

パス内のすべてのコマンドを削除します。

戻り値 ​

戻り値はありません。

変更内容 ​

対象のパスを空にし、座標の正規化設定を初期値へ戻します。


path:assign(template) ​

APIレベル: 5+

パスをmt.svg_pathで作成したテンプレートの内容へ置き換えます。

引数 ​

引数型単位省略時内容
templateMtDrawingPath-指定必須コピー元のパステンプレート

戻り値 ​

戻り値はありません。

変更内容 ​

対象のパスデータと座標の正規化設定を、テンプレートの内容へ置き換えます。


path:set_svg(source) ​

APIレベル: 5+

SVGのパスデータを解析し、対象のパスを置き換えます。

引数 ​

引数型単位省略時内容
sourcestring-指定必須SVGのd属性と同じ形式のパスデータ

戻り値 ​

戻り値はありません。

変更内容 ​

対象のパスを指定したSVGパスへ置き換え、座標の正規化設定を初期値へ戻します。


path:move_to(x, y) ​

APIレベル: 5+

指定した座標を始点とする新しいサブパスを追加します。

引数 ​

引数型単位省略時内容
x / ynumberパスローカル座標指定必須サブパスの始点

戻り値 ​

戻り値はありません。

変更内容 ​

対象のパスへmoveコマンドを追加します。

制約・エラー ​

座標は有限の数値である必要があります。


path:line_to(x, y) ​

APIレベル: 5+

現在位置から指定した座標までの直線を追加します。

引数 ​

引数型単位省略時内容
x / ynumberパスローカル座標指定必須直線の終点

戻り値 ​

戻り値はありません。

変更内容 ​

対象のパスへlineコマンドを追加します。

制約・エラー ​

座標は有限の数値である必要があります。


path:quad_to(cx, cy, x, y) ​

APIレベル: 5+

現在位置から指定した終点までの2次Bézier曲線を追加します。

引数 ​

引数型単位省略時内容
cx / cynumberパスローカル座標指定必須制御点
x / ynumberパスローカル座標指定必須曲線の終点

戻り値 ​

戻り値はありません。

変更内容 ​

対象のパスへquadratic Bézierコマンドを追加します。

制約・エラー ​

座標は有限の数値である必要があります。


path:cubic_to(cx1, cy1, cx2, cy2, x, y) ​

APIレベル: 5+

現在位置から指定した終点までの3次Bézier曲線を追加します。

引数 ​

引数型単位省略時内容
cx1 / cy1numberパスローカル座標指定必須現在位置側の制御点
cx2 / cy2numberパスローカル座標指定必須終点側の制御点
x / ynumberパスローカル座標指定必須曲線の終点

戻り値 ​

戻り値はありません。

変更内容 ​

対象のパスへcubic Bézierコマンドを追加します。

制約・エラー ​

座標は有限の数値である必要があります。


path:close() ​

APIレベル: 5+

現在のサブパスを始点へ接続して閉じます。

戻り値 ​

戻り値はありません。

変更内容 ​

対象のパスへcloseコマンドを追加します。


path:bounds() ​

APIレベル: 9+

曲線極値を含むtight boundsをminimumX, minimumY, maximumX, maximumYの4値で返します。 空パスではnilを1つ返します。値はパスと同じY-down、1000単位=1emです。パスを参照できる 任意の場所で、読み取り専用テンプレートと可変パスの両方に利用できます。


path:map_points(callback) ​

APIレベル: 9+

callback(x, y, point)が返す2座標で、アンカー点と制御点をcommand順に置き換えます。 command種別・数、contour、close状態は変わりません。全callback成功後にだけ反映されます。 standaloneの可変パスでは保持している任意の場所、ctx.pathsのtargetではOnPath中に利用できます。

pointは再利用される読み取り専用viewで、index、command_index、contour_index、 role(anchor / control1 / control2)、command(move / line / quad / cubic)を持ちます。 1パス4096 points、1 script実行16384 pointsが上限です。同じreceiverへのcallback中の再入・変更、 有限でない戻り値はエラーになり、パスは変更されません。

lua
path:map_points(function(x, y, point)
    return x, y + math.sin(point.index * 1.7 + ctx.progress * math.pi * 2) * 25
end)

18. UTF-8テキスト処理 ​

mt.text.slice(text, startChar, endChar?) ​

APIレベル: 1+

UTF-8コードポイント境界で文字列をスライスします(Lua標準のバイト単位のstring.subと 異なり、個々のUTF-8コードポイントの途中では切りません)。書記素クラスタ単位ではないため、 結合文字やZWJで連結された絵文字を見た目上の1文字の途中で分割することがあります。 ctx.chars[index].textはシェイピング後のクラスタであり、この関数のindexとは同一概念では ありません。

引数 ​

引数型単位省略時内容
textstring-指定必須対象の文字列
startCharinteger-指定必須切り出し開始コードポイントindex。1始まりで、この位置を含みます
endCharinteger-末尾切り出し終了コードポイントindex。1始まりで、この位置を含みます

戻り値 ​

型単位内容
string-指定範囲を切り出した文字列。範囲が空または無効な場合は空文字列

mt.text.classify(text) ​

APIレベル: 4+

テキストクラスタの先頭Unicodeコードポイントを、アニメーションで扱いやすい文字種名へ分類します。

引数 ​

引数型単位省略時内容
textstring-指定必須分類するテキストクラスタ

戻り値 ​

型単位内容
string-"kanji"、"hiragana"、"katakana"、"punctuation"、"latin"、"digit"、"space"、"other"のいずれか

使用例 ​

lua
for _, character in ipairs(ctx.chars) do
    if mt.text.classify(character.text) == "kanji" then
        character.scale = 1.2
    end
end

注意事項 ​

書記素クラスタ全体の言語判定ではなく先頭コードポイントによる軽量分類です。空文字列、絵文字、 結合記号など、定義済み範囲に該当しないものは"other"になります。

19. 文字・パーツ指定 ​

mt.target.chars(ctx, specification, options?) ​

APIレベル: 13+

指定文字列を文字番号に解決します。文法は本体の文字・パーツ対象設定と同じなので、スクリプトの入力でも同じ書き方を提供できます。

  • トークンはカンマまたは空白で区切ります。
  • c3は文字3、p2はグローバルパーツ2、数字だけの指定はこの関数では文字を表します。
  • a-bは両端を含む範囲です。c1-c3・p2-p5・2-4のいずれも書けます。片側が数字だけのときはもう一方の種別に揃い、逆順の範囲は入れ替えられ、両端の種別が異なる範囲は無視されます。
  • 先頭の!は除外です。除外は書く順序にかかわらず、すべての指定より優先されます。
  • テキストに存在しない番号・不正なトークン・0は無視されます。

パーツが1つでも選ばれた文字が列挙されるため、p5はパーツ5を持つ文字を返します。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutまたはOnPathのコンテキスト
specificationstring-指定必須指定文字列
optionstable-nil{ empty = "none" | "all" }。何も選ばない文字列の扱い。"none"(既定)は何も選ばず、"all"はすべての文字を選びます。"all"でも除外は有効です

戻り値 ​

型単位内容
integer[]-昇順の文字番号(ctx.charsのindex)。ipairsでそのまま回せます

例 ​

lua
function OnLayout(ctx)
    for _, characterNumber in ipairs(mt.target.chars(ctx, "1-3, 6, !c2")) do
        ctx.chars[characterNumber].scale = 1.2
    end
end

mt.target.parts(ctx, specification, options?) ​

APIレベル: 13+

指定文字列をグローバルパーツ番号に解決します。文法はmt.target.charsと同じで、数字だけの指定がパーツを表す点だけが異なります。c3のような文字の指定は、その文字のすべてのパーツを選びます。

引数 ​

引数型単位省略時内容
ctxtable-指定必須OnLayoutまたはOnPathのコンテキスト
specificationstring-指定必須指定文字列
optionstable-nil{ empty = "none" | "all" }。何も選ばない文字列の扱い。"none"(既定)は何も選ばず、"all"はすべてのパーツを選びます。"all"でも除外は有効です

戻り値 ​

型単位内容
integer[]-昇順のグローバルパーツ番号(ctx.partsのindex)。ipairsでそのまま回せます

例 ​

lua
function OnLayout(ctx)
    for _, partNumber in ipairs(mt.target.parts(ctx, "c1 p9")) do
        ctx.parts[partNumber].opacity = 0.5
    end
end

20. クリップ時間 ​

mt.timeline.progress(ctx, fallbackDuration?) ​

APIレベル: 1+

現在の進行度(0から1)を取得します。

引数 ​

引数型単位省略時内容
ctxtable-指定必須コンテキスト
fallbackDurationnumber秒4.0タイムラインを取得できない場合にループさせる仮想クリップ長

戻り値 ​

型単位内容
number0-1現在の進行度

制約・エラー ​

タイムラインを取得できない場合、fallbackDurationには正数を指定します。


mt.timeline.duration(ctx, fallbackDuration?) ​

APIレベル: 6+

ホストから取得した正のクリップ長を秒で返します。ホストタイムラインを利用できない場合、 または取得した秒数が有限の正数でない場合は、指定したフォールバック時間を返します。

引数 ​

引数型単位省略時内容
ctxtable-指定必須コンテキスト
fallbackDurationnumber秒4.0タイムラインを取得できない場合の仮想クリップ長

戻り値 ​

型単位内容
number秒ホストのクリップ長、またはフォールバック時間

制約・エラー ​

明示するfallbackDurationは有限の正数である必要があります。window_ctxが返す派生contextを 渡した場合は、その時間窓のdurationを返します。

lua
local clipDuration =
    mt.timeline.duration(ctx, kFallbackClipLength)

mt.timeline.remaining(ctx, fallbackDuration?) ​

APIレベル: 1+

クリップ終端までの残り実秒を返します。アウトロ(退場アニメーション)を終端アンカーの 実時間で書くための基礎部品です(ctx.timelineの設計ルール参照)。

引数 ​

引数型単位省略時内容
ctxtable-指定必須コンテキスト
fallbackDurationnumber秒4.0タイムラインを取得できない場合にループさせる仮想クリップ長

戻り値 ​

型単位内容
number秒クリップ終端までの残り時間

使用例 ​

lua
-- クリップ長にかかわらず、最後の0.5秒でフェードアウト
local fade = mt.clamp(mt.timeline.remaining(ctx) / 0.5, 0.0, 1.0)

mt.timeline.intro_outro_seconds(ctx, introSeconds, outroSeconds, fallbackDuration?) ​

APIレベル: 1+

イントロ(クリップ先頭アンカー)とアウトロ(クリップ終端アンカー)の進行度を、 指定した実秒数で進む固定速度で返します。クリップの尺を変えてもトランジションの 速度は変わりません。クリップが introSeconds + outroSeconds より短い場合のみ、 両区間を比例圧縮してクリップ内に収めます(自動早送り)。

引数 ​

引数型単位省略時内容
ctxtable-指定必須コンテキスト
introSecondsnumber秒指定必須イントロの長さ。負値は0として扱います
outroSecondsnumber秒指定必須アウトロの長さ。負値は0として扱います
fallbackDurationnumber秒4.0タイムラインを取得できない場合の仮想クリップ長

戻り値(多値) ​

型単位内容
number0-1introProgress。イントロの進行度
number0-1outroProgress。アウトロの進行度

使用例 ​

lua
local intro, outro = mt.timeline.intro_outro_seconds(ctx, 0.8, 0.5)
character.offset_y = 0.5 + (1.0 - mt.ease.out_cubic(intro)) * 0.2
character.scale = character.scale * (1.0 - mt.ease.in_cubic(outro))

mt.timeline.window_progress(ctx, start, duration) ​

APIレベル: 6+

コンテキスト内の指定時間窓を0-1の線形進行度へ変換します。startより前は正確に0.0、 start + duration以後は正確に1.0を返します。区間内では (ctx.time - start) / durationを返します。

引数 ​

引数型単位省略時内容
ctxtable-指定必須時間を読み取るコンテキスト
startnumber秒指定必須コンテキスト内での開始時間
durationnumber秒指定必須時間窓の長さ

戻り値 ​

型単位内容
number0-1開始前と終了後をクランプした時間窓内の線形進行度

制約・エラー ​

  • ctx.timeは数値である必要があります。
  • startは有限の数値である必要があります。
  • durationは有限の正数である必要があります。

使用例 ​

lua
local appear =
    mt.timeline.window_progress(ctx, 0.5, 0.8)
local disappear =
    mt.timeline.window_progress(ctx, 4.0, 0.5)

character.opacity = appear * (1.0 - disappear)

注意事項 ​

進行度だけが必要な場合に使用します。時間やframeもローカル化して時間依存APIへ渡す場合は、 mt.timeline.window_ctxを使用します。


mt.timeline.window_ctx(ctx, start, duration) ​

APIレベル: 4+

元のctxから、指定時間窓の派生ctxを生成します。startは元ctx内の開始秒、durationは正の 時間窓長です。派生ctxのtimeはctx.time - startを0〜durationへクランプした値となり、 frame、timeline.duration_*、timeline.progressも同じローカル時間基準へ変換されます。 canvas、global、chars、partsなど、それ以外の値は元ctxから引き継ぎます。

引数 ​

引数型単位省略時内容
ctxtable-指定必須元のコンテキスト
startnumber秒指定必須元のコンテキスト内での開始時間
durationnumber秒指定必須時間窓の長さ

戻り値 ​

型単位内容
table-時間関係を指定窓へ再マッピングした派生コンテキスト

制約・エラー ​

  • ctx.timeは数値である必要があります。
  • startは有限の数値である必要があります。
  • durationは有限の正数である必要があります。

使用例 ​

lua
local characterCtx =
    mt.timeline.window_ctx(ctx, (index - 1) * 0.08, 0.5)

local bounce = mt.bounce_y({ t = characterCtx.time })
local opacity = mt.ease.out_cubic(characterCtx.timeline.progress)

注意事項 ​

元ctxや共有された文字・パーツを複製するAPIではありません。時間関係だけを差し替えた 浅い派生コンテキストです。


mt.timeline.chain(ctx, initialValue, segments, options?) ​

APIレベル: 4+

時間区間ごとの純粋関数を順番に評価し、完了した区間の最終戻り値を次区間へ渡します。 現在時刻より前の evaluate はその区間の終端コンテキストで評価され、現在の区間だけが 区間ローカルの ctx で評価されます。戻り値は number、color、座標や変形をまとめたtableなど 任意のLua値にできます。

引数 ​

引数型単位省略時内容
ctxtable-指定必須元のコンテキスト
initialValue任意-指定必須最初の区間へ渡す初期値
segmentstable-指定必須アニメーション区間または保持区間の配列
optionstable-nilタイムラインを取得できない場合の設定
options.fallback_durationnumber秒4.0仮想クリップ長

戻り値 ​

型単位内容
任意-現在時刻まで評価した最後の区間の値

使用例 ​

lua
local result = mt.timeline.chain(ctx, initialValue, {
    {
        duration = 1.0,
        evaluate = function(segmentCtx, previousValue)
            return enterAnimation(segmentCtx, previousValue)
        end,
    },
    { hold = 0.5 },
    {
        duration = 1.2,
        evaluate = function(segmentCtx, previousValue)
            return bounceAnimation(segmentCtx, previousValue)
        end,
    },
})

区間コンテキスト ​

segmentCtxは呼び出し元のctxからcanvas、global、chars、partsなどを引き継ぎ、時間関係だけを 現在区間へ置き換えたコンテキストです。mt.timeline.progressなど、ctxを読み取る既存の Level 3 APIへ通常のctxと同じように渡せます。

フィールド型単位内容
segmentCtx.timenumber秒区間開始からの時間
segmentCtx.framenumberframe区間開始からのフレーム数
segmentCtx.fpsnumberfps呼び出し元と同じフレームレート
segmentCtx.timeline.duration_secondsnumber秒区間の論理duration
segmentCtx.timeline.duration_framesnumberframe区間の論理durationをフレーム換算した値
segmentCtx.timeline.progressnumber0-1区間内の進行度

区間の形式 ​

各区間は次のいずれかの形式です。

区間指定動作
固定長アニメーション{ duration = 秒数, evaluate = 関数 }evaluate(segmentCtx, previousValue) の戻り値を使用
固定長保持{ hold = 秒数 }関数を呼ばず、直前の値を保持
可変長アニメーション{ duration = "remaining", evaluate = 関数 }固定区間を除いた残りのクリップ尺を使用
可変長保持{ hold = "remaining" }残りのクリップ尺で直前の値を保持

"remaining"は1つのchain内で1区間だけ指定できます。その後ろに固定長のアウトロを置くと、 可変区間だけがクリップ尺の変更を吸収し、アウトロは常にクリップ終端で完了します。

lua
local state = mt.timeline.chain(ctx, initialState, {
    { duration = 1.0, evaluate = evaluateIntro },
    { duration = 1.2, evaluate = evaluateBounce },
    { duration = "remaining", evaluate = evaluateIdle },
    { duration = 0.6, evaluate = evaluateOutro },
}, {
    fallback_duration = 6.0,
})

固定区間の合計がクリップ尺を超える場合は、すべての固定区間を比例圧縮します。 segmentCtx.timeとsegmentCtx.timelineは宣言したdurationへ再マッピングされるため、 短いクリップでも各アニメーションは終端状態まで到達します。タイムライン取得不可時は options.fallback_duration(既定 4.0 秒)を仮想クリップ長としてループします。

制約・エラー ​

  • ctx.timeは数値、segmentsとoptionsはtableである必要があります。
  • 各区間はdurationまたはholdのどちらか一方だけを指定します。
  • duration区間にはevaluate関数が必要で、hold区間には指定できません。
  • 区間長には有限の0以上の数値または"remaining"を指定します。
  • "remaining"を指定できる区間は1つだけです。
  • options.fallback_durationは有限の正数である必要があります。

IMPORTANT

evaluateは過去区間の終端値を得るため同じフレーム内で再評価されます。ctxやcharacterを 直接変更せず、引数から計算した値を返す純粋関数として記述し、最終結果だけを適用してください。 mt.bounce_groundのようにitemを直接変更するAPIではなく、値を返すmt.bounce_yなどを segmentCtx.timeと組み合わせて使用します。

21. 非推奨の互換API ​

mt.storage 非推奨 ​

APIレベル: 1+

mt.storageは既存スクリプトとの互換性のために残されています。 新規スクリプトでは、関数の外側で宣言したlocal変数に不変値を保持してください。

型内容
table読み取り専用の互換用ストレージ

mt.polar_offset(angleDegrees, radius) 非推奨 ​

APIレベル: 3+

角度系のY方向を使う旧形式の極座標変換です。

引数 ​

引数型単位省略時内容
angleDegreesnumber度指定必須方向。0度は右で、正方向は時計回りです
radiusnumber変位指定必須その方向への距離

戻り値(多値) ​

型単位内容
numberradiusに準拠offsetX
numberradiusに準拠screenOffsetY。画面基準で下が正です

WARNING

非推奨です。mt.polar_offset_2d を使用してください。 引数は mt.polar_offset_2d と同じですが、戻り値が角度系(Y は下が正)のため、offset_y へ渡す際に符号の反転が必要でした。反転を忘れると上下だけが逆に動くという取り違えが起き やすいため、位置系で返す mt.polar_offset_2d に置き換えています。動作は変更していないので 既存のスクリプトはそのまま動作します。

使用例 ​

lua
-- 旧: 呼び出し側で反転が必要
local dx, dy = mt.polar_offset(angle, radius)
character.offset_y = 0.5 - dy

-- 新: そのまま加算できる
local dx, dy = mt.polar_offset_2d(angle, radius)
character.offset_y = 0.5 + dy

mt.layout.retypeset(ctx, gap?, config?) 非推奨 ​

APIレベル: 1+

CAUTION

API Level 1互換関数です。新規コードではmt.layout.reflowを使用してください。

文字ごとの個別のscaleやstretchを考慮し、geometry.advance_x/yを使って簡易的に 字送りを再計算します。可視インク境界間の隙間を均一にする関数ではありません。 文字ごとのサイズアニメーションを適用した後、そのフレームの最終再組版処理として呼び出します。 rotation、個別pivot、tracking、margins、変形後の輪郭は送り計算に含みません。

引数 ​

引数型単位省略時内容
ctxtable-指定必須コンテキスト
gapnumbercanvas幅比または高さ比0.0advance間へ追加する余白
configtable-nil再整列の設定
config.alignstring-"baseline"横書き時の交差軸整列。"baseline"、"top"、"center"、"bottom"
config.modestring-"horizontal""horizontal"または"vertical"
config.targetstable-全文字再整列する1始まりの文字index配列。対象外の文字は変更しません
config.anchorinteger-targetsの最小index送り軸の現在位置を固定する文字index
config.baselinestring-"anchor"基準線を現在の姿から取る"anchor"、または自然な姿から取る"natural"

config.baseline = "anchor"では、アンカー文字のscaleがフレームごとに変わると基準線ごと 行全体が上下します。"natural"は交差軸を自然位置に固定するため、時間変化するscaleと 併用する場合に適しています。"anchor"はscaleとoffset適用後の現在の姿、"natural"は scale 1・offsetなしのBaseレイアウト時の姿を基準にします。送り軸のアンカー位置はどちらでも 現在位置のままです。config.alignは縦書きの簡易整列では使用しません。

戻り値 ​

戻り値はありません。

変更内容 ​

対象文字のoffset_xとoffset_yを直接書き換えます。

WARNING

targets で一部の文字だけを対象にした場合、gap は対象範囲を対象外の隣接文字に 衝突させることがあります。 gap は対象範囲内の文字間隔に呼び出しのたびに加算され、 対象範囲全体の幅を押し広げます。この関数は targets に含まれない文字の座標を一切 変更しない(=対象外の文字の位置を考慮して自動的に間を空けたりしない)ため、対象範囲の 端(先頭または末尾)が対象外の文字にもともと隣接していた場合、gap を足すたびに その対象外の文字と重なる方向へ範囲が伸びていきます。全文字を対象にする場合や、 対象範囲の前後に元から十分な余白がある場合は問題になりませんが、一部の文字だけを 対象にして、かつその境界が別の文字と隣接している場合は gap を 0 にするか、 対象範囲の外側にも手動で余白(tracking / margins)を確保してください。

使用例 ​

lua
-- インデックス 3〜6 の文字のみを整列し、インデックス 3 の文字位置を基準に固定して左右に整列
mt.layout.retypeset(ctx, 0.02, {
    targets = {3, 4, 5, 6},
    anchor = 3,
    align = "baseline"
})

mt.layout.canvas_to_offset(resolvedGlobal, canvasWidth, canvasHeight, naturalCenterX, naturalCenterY, canvasX, canvasY) 非推奨 ​

APIレベル: 1+

CAUTION

API Level 1互換関数です。globalの2D変形しか逆算しません。新規コードでは mt.layout.place_2dを使用してください。

文字・パーツの自然中心を、2Dのglobal変形までを考慮したcanvas上の目標位置へ移す offsetを求めるときに使います。offset_x / offset_y は「自身の自然な位置からの変位量」であり ctx.global(position / rotation / scale / stretch / pivot)による全体変形の前の座標系にあるため、目標のcanvas座標を そのまま offset_x = canvasX のように代入しても、ctx.global が初期値のときしか意図した 画面位置になりません。全体を回転・移動・拡大している場合、その変形の分だけ実際の位置が ずれます。この関数は ctx.global の2D変形を打ち消した上で、目標のcanvas位置に対応する offset_x / offset_y を計算します。

引数 ​

引数型単位省略時内容
resolvedGlobaltable-指定必須OnPreLayoutで確定済みのctx.global
canvasWidth / canvasHeightnumberpx指定必須ctx.canvas.widthとctx.canvas.height
naturalCenterX / naturalCenterYnumbercanvas正規化位置指定必須対象の自然中心。文字ではgeometry.bounds_center_x/y、パーツではgeometry.canvas_center_x/y
canvasX / canvasYnumbercanvas正規化位置指定必須配置先の座標

戻り値(多値) ​

型単位内容
numbercanvas正規化変位offsetX
numbercanvas正規化変位offsetY

制約・エラー ​

この関数が反転するのはposition_x/y、rotation、scale、stretch_x/y、 pivot_x/yだけです。文字・パーツの個別rotation/pivot、所有文字からパーツへの階層変形、 global/個別の3D値、camera、projection、Deformは反転しません。幅・高さおよび global.scale * stretch_x/yは非ゼロでなければなりません。

使用例 ​

lua
-- 2D ctx.global.rotation / position_x などを OnPreLayout で変更していても、
-- 個別/3D/Deform変形がなければ自然中心は canvas 上の (0.8, 0.3) に来る
local geometry = character.geometry
character.offset_x, character.offset_y = mt.layout.canvas_to_offset(
    ctx.global, ctx.canvas.width, ctx.canvas.height,
    geometry.bounds_center_x, geometry.bounds_center_y,
    0.8, 0.3
)

注意事項 ​

パーツの場合、パーツ自身の変形(part.offset_x/y 等)は 所有文字の解決済み変形の 内側に重ねて適用されるため、この関数は「文字の変形を無視して canvas 上の固定位置に 置く」ことはできません(文字自体が動いていれば、パーツも一緒に動きます)。パーツを 文字の変形とは独立に canvas 上の固定位置へ置きたい場合は、まずその文字の offset_x/y / rotation / scale 等を確認し、パーツ側の変位量にその逆変形を 別途適用する必要があります。


mt.layout.set_canvas_position(item, canvasX, canvasY, ctx?) 非推奨 ​

APIレベル: 1+

CAUTION

API Level 1互換関数です。パーツの所有文字階層と対象自身の変形を逆算しません。 新規コードではmt.layout.place_2dを使用してください。

文字オブジェクト(ctx.chars[i])またはパーツオブジェクト(ctx.parts[i])へ、指定した canvas目標位置(canvasX, canvasY)に対応するoffset_x/yを書き込むヘルパーです。

文字にはgeometry.bounds_center_x/y、パーツにはgeometry.canvas_center_x/yを自然中心として 使います。第4引数にctxを渡すとcanvas_to_offsetと同じ2D global変形だけを反転します。 パーツの所有文字変形、3D、camera、projection、Deformは反転しないため、これらが有効な場面の 最終画面位置を保証する関数ではありません。ctxを省略した場合はglobalがidentityのときだけ 自然中心が目標canvas位置と一致します。

引数 ​

引数型単位省略時内容
itemtable-指定必須対象の文字またはパーツ
canvasX / canvasYnumbercanvas正規化位置指定必須配置先の座標
ctxtable-nil指定するとctx.globalの2D変形だけを逆算します

戻り値(多値) ​

型単位内容
numbercanvas正規化変位設定したoffsetX
numbercanvas正規化変位設定したoffsetY

変更内容 ​

対象のoffset_xとoffset_yを直接更新します。

使用例 ​

lua
-- 文字の自然中心を2D画面右上 (0.8, 0.8) へ
mt.layout.set_canvas_position(ctx.chars[1], 0.8, 0.8, ctx)

-- 親文字とglobalがidentityなら、パーツの自然中心を画面中央へ
mt.layout.set_canvas_position(ctx.parts[1], 0.5, 0.5)

mt.layout.group_bounds(ctx, targets, targetType?) 非推奨 ​

APIレベル: 1+

CAUTION

API Level 1互換関数です。rotation、pivot、親文字、globalを除外した近似値です。 新規コードではmt.layout.measure_bounds_2dを使用してください。

指定した文字またはパーツの、変形途中の近似軸平行境界を返します。

自然インク境界へ各要素のoffset_x/y、scale、stretch_x/yだけを適用します。 要素のrotation/pivot、パーツの所有文字変形、ctx.global、3D、camera、projection、Deformは 考慮しません。したがって、回転なし・階層/global変形なしの2Dレイアウトにおける補助計算には 使えますが、最終描画境界、物理境界、衝突判定を保証しません。公開APIには最終投影済みパス境界を 取得する関数はありません。対象要素のoffset/scale/stretchを書いた後に呼び出してください。

引数 ​

引数型単位省略時内容
ctxtable-指定必須レイアウトコンテキスト
targetstable-指定必須1始まりの対象index配列
targetTypestring-"character""character"または"part"

戻り値(いずれか) ​

型単位内容
table-近似境界
nil-有効な対象がない場合

境界tableは次のフィールドを持ちます。

フィールド型単位内容
left / right / bottom / topnumbercanvas正規化位置上記の変形段階における近似境界
center_x / center_ynumbercanvas正規化位置グループの中心
width / heightnumbercanvas正規化変位グループ全体の幅と高さ

使用例 ​

lua
-- インデックス 1〜3 の親文字グループ全体の境界を取得
local bounds = mt.layout.group_bounds(ctx, {1, 2, 3})
if bounds then
    -- グループ全体の中心座標や幅・高さを利用して背景プレートやルビを配置
    print(bounds.center_x, bounds.center_y, bounds.width, bounds.height)
end

mt.timeline.intro_outro(progress, introFraction, outroFraction) 非推奨 ​

APIレベル: 1+

全体進行度から、最初(イントロ)と最後(アウトロ)の区間それぞれの進行度を個別に抽出して返します。

WARNING

非推奨: 割合ベースのトランジションはクリップの尺に比例して伸び縮みするため、 尺を伸ばすとフェードがスローモーション化します。固定速度で進む mt.timeline.intro_outro_seconds を使ってください (ctx.timelineの設計ルール参照)。

引数 ​

引数型単位省略時内容
progressnumber0-1指定必須全体進行度。通常はmt.timeline.progressから取得します
introFractionnumber0-1指定必須イントロとして扱う全体尺の割合
outroFractionnumber0-1指定必須アウトロとして扱う全体尺の割合

戻り値(多値) ​

型単位内容
number0-1introProgress。イントロの進行度
number0-1outroProgress。アウトロの進行度

この付録では、スクリプトを作成するときに迷いやすい問題と、その対処方法を説明します。

1. 個別にscaleした文字の送りを整える ​

1.1 どのようなときに必要か ​

OnLayoutで文字ごとにscaleやstretchを変更し、変更後の大きさに合わせて文字を 並べ直したいときに必要です。

1.2 起きる問題 ​

文字の送りは、OnLayoutで個別の変形を加える前に決まります。そのため、文字ごとに scaleやstretchを変更しただけでは、次の問題が起きることがあります。

  • 大きくした文字が隣の文字と重なります。
  • 小さくした文字の左右に余分な間隔が残ります。
  • 文字の基準位置がベースラインからずれます。

これは、文字がgeometry.bounds_centerを中心に拡大・縮小される一方で、元の送りが そのまま使われるためです。

1.3 対処方法 ​

文字のサイズ、回転、pivotを変更したあと、OnLayoutの最後に mt.layout.reflowを呼び出してください。

lua
function OnLayout(ctx)
    for index = 1, ctx.char_count do
        local character = ctx.chars[index]
        character.scale = 0.8 + index * 0.05
    end

    -- 変形後の文字サイズに合わせて送りを整える
    mt.layout.reflow(ctx)
end

文字間に追加の余白が必要な場合は、第2引数に間隔を指定します。対象文字や固定する文字を 限定する場合は、configを指定します。引数の詳細は mt.layout.reflowを参照してください。

1.4 仕組み ​

mt.layout.reflowは、横書きと縦書きの組版原点を使い、シェーピング、kerning、tracking、 marginsによる間隔を保ったまま、現在のscale、stretch、rotation、pivotを反映して文字を 並べ直します。個々のインク輪郭の間隔を均一にする機能ではありません。

pivotが0.5でscaleだけを変更する場合、自然座標上の点Pは次式で移動します。 Cはgeometry.bounds_center、sはscale×stretch、dはoffset-0.5です。

text
P' = C + s × (P - C) + d
d  = P'(目標) - C - s × (P - C)

この式をスクリプト内で直接計算する必要はありません。mt.layout.reflowは、rotation、pivot、 縦書き、非正方形canvasを含む完全な2D文字変換を考慮して組版原点を整列します。

2. グラデーションの範囲と向きを調整する ​

2.1 どのようなときに必要か ​

start_position、end_position、angleを変更したときに、グラデーションの開始位置、 終了位置、色の向きが想定と合わない場合に確認してください。

2.2 起きる問題 ​

start_positionとend_positionは、canvas全体を基準とする座標ではありません。 グラデーションのangleも、単純にバウンディングボックスの幅や高さだけを使って 計算されるわけではありません。

これらをcanvas座標として扱うと、テキストを移動・回転・拡大したときや、斜め方向の グラデーションを設定したときに、色の切り替わる位置が想定からずれて見えます。

2.3 対処方法 ​

start_positionとend_positionは、変形後のテキスト全体をangle方向に見た範囲に 対する比率として指定してください。

  • テキストの端から端までグラデーションを適用する場合は、start_position = 0.0、 end_position = 1.0にします。
  • テキストの内側で色を切り替える場合は、start_positionを大きくし、 end_positionを小さくします。標準設定の0.2と0.8では、両端から20%内側が グラデーション区間になります。
  • angle = 0では左から右、angle = 90では上から下、 angle = -90または270では下から上へ色が変化します。

start_position側にはfill色、end_position側にはend_colorが割り当てられます。 angleの向きは座標の定義と同じです。

2.4 基準となる範囲 ​

グラデーションは、OnLayoutで文字やパーツへscale、rotation、offsetなどを適用した 後のテキスト全体のバウンディングボックスを基準とします。

  • 2D描画時: 変形後の全文字・パーツのパスを囲むcanvas上の2Dバウンディングボックスです。
  • 3D投影時: カメラ投影の影響を受けない3Dレイアウト平面上のバウンディングボックスです。 キャラクターごとに投影座標が計算されるため、カメラが動いてもグラデーションの位置は 文字に対してずれません。

2.5 基準線の計算方法 ​

グラデーションの0.0〜1.0の基準線は、バウンディングボックスをangle方向へ投影したときの 最近端と最遠端を結ぶ線分です。斜め方向では、矩形の幅や高さではなく、指定方向へ最も 突き出た位置と、その反対側の位置が境界になります。

バウンディングボックスの中心をC、angleの方向ベクトルをD、4つの頂点をP_iとすると、 各頂点の射影値は次式で求められます。

text
proj_i = (P_i - C) · D

射影値の最小値をminProj、最大値をmaxProjとすると、基準線の開始点bbP0と 終了点bbP1は次のようになります。

text
bbP0 = C + D * minProj
bbP1 = C + D * maxProj

start_positionをt_s、end_positionをt_eとすると、実際の開始点P0と終了点P1は 基準線上の次の位置になります。

text
P0 = bbP0 + (bbP1 - bbP0) * t_s
P1 = bbP0 + (bbP1 - bbP0) * t_e

3. コールバック間で値を受け渡す ​

3.1 どのようなときに必要か ​

OnPreLayoutで上書きする前の値を、同じフレームのOnLayoutでも使いたい場合に必要です。 たとえば、ホストのScaleを文字サイズではなくアニメーションの移動量を決める係数として使う場合が 該当します。

3.2 起きる問題 ​

OnPreLayoutでctx.global.scaleを1.0に変更すると、OnLayoutから参照できるのは 変更後の値です。上書き前のホスト値は復元できないため、その値を使った計算ができなくなります。

一方、OnPreLayoutで上書きしていない値は、OnLayoutのctx.globalからそのまま読めます。 たとえばtrackingやline_spacingは、退避せずに使う場所で直接参照してください。

3.3 対処方法 ​

上書き前の値を関数の外側で宣言したlocal変数へ保存し、OnLayoutから参照してください。 Luaの実行環境はインスタンスごとに1つ作成され、スクリプトが再読み込みされるまで維持されるため、 同じ変数をコールバック間で参照できます。

lua
local scaleKnob = 1.0

function OnPreLayout(ctx)
    -- ホストのScaleを退避してから、文字サイズへの影響を打ち消す
    scaleKnob = math.max(ctx.global.scale, 0.05)
    ctx.global.scale = 1.0
end

function OnLayout(ctx)
    local travel = 0.07 * scaleKnob
    for index = 1, ctx.char_count do
        ctx.chars[index].offset_y = ctx.chars[index].offset_y + travel
    end
end

この受け渡しは、上書き前の値が必要な場合だけ使ってください。不要な値まで保存すると、 スクリプトの状態が増え、処理の流れが分かりにくくなります。

3.4 フレーム間の状態保持には使わない ​

関数の外側で宣言した変数は、コールバック間だけでなくフレーム間でも値を保持します。しかし、 ホストはシーク、レンダリング順序の変化、並列描画などにより、フレームを時間順に評価するとは 限りません。

前フレームの値を使った差分計算や累積を行うと、再生時とレンダリング時で結果が変わることが あります。各フレームの結果は、そのフレームのctx.timeから一意に決まるようにしてください。 関数の外側では、定数やコールバック間で同一フレーム内に受け渡す値だけを保持します。