Skip to content

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パネルに表示されるエラーメッセージとスタックトレースを確認して修正してください。