成果物
こういう感じのウィンドウ。
キーワードを設定しておけばそれに下線が引かれ、マウスオーバーすると解説用ウィンドウが追加で出る。
ほかにもいろいろ機能を載せたのだが、万人に役立ちそうにないところなので割愛する。
ここではGodot+C#で会話ウィンドウを作るうえで万人に共通するであろう知見を主に解説する。
(だって調べても日本語情報ほとんど出てこないんだもん、特にC#つかってると)
シーン構造
PanelContainer
背景をつけて内部にControllerを持てる。
Panel+Containerという感じだ。
見た目はThemeの編集によってそれっぽくいじれる。
RichTextLabelのBBCode
結構多機能。BBCodeEnabledを有効にするとタグを使って書ける。
と違ってタグの囲いが[BBCode]なだけで、ほぼXMLだ。
普通のタグについては調べたら何ができるか十分わかるので、ここでは[url]について書く。
Text = "[url]テスト用テキスト[/url]";
たとえばこのように書いてやるとurlタグとして成立する……のだがurlとしての機能はない。
BBCodeの元ネタに準拠しているだけのようで、このタグは本質的にはクリックイベント機能を持たせるためのより汎用性のあるタグである。
https://docs.godotengine.org/ja/3.x/classes/class_richtextlabel.html#class-richtextlabel-signal-meta-clicked
公式ドキュメントではurlと書いたタグはmetaタグと呼ばれているようだ。
さて、このタグで囲まれた部分の文字列は特殊な扱いを受ける。
- 下線が引かれる(オプションで消せる)
- マウスオーバーするとカーソルが指になる
- マウスオーバーとクリックのシグナルが走る
お察しの通り、一番最後のやつを利用して独自のマウスオーバーイベントを作れる。
ちなみに、hintタグは該当部分にマウスオーバーしていたら好きな文字列をツールチップ表示できるというものだが、
- マウスオーバーしたあとしばらく静止しないといけない
- ツールチップが表示されたあと、マウスを動かしてもそのツールチップは動かない
といった具合で、大問題というほどではないが使い勝手が悪い。
そのうえカスタマイズがおそらくできない。
デバッグ機能ならともかく、ゲームに入れる機能としては使えないだろう。
BBCodeイベントの受け取り方
GodotのRichTextLabelを継承してイベントハンドラに関数を渡すだけである。
ここでのイベントハンドラはGDScriptでいうところのSignalである。
Godot+C#を触るからにはこの脳内変換ができるようになっとかないとな!
public partial class RichTextLabelCustomed : RichTextLabel
{
[Export] Tooltip Tooltip;
public override void _Ready()
{
// マウスオーバー時のイベント登録
MetaHoverStarted += OnMetaHoverStarted;
MetaHoverEnded += OnMetaHoverEnded;
}
void OnMetaHoverStarted(Variant meta)
{
Tooltip.Text = meta.ToString();
Tooltip.Visible = true;
GD.Print($"OnMetaHoverStarted: {meta}");
}
void OnMetaHoverEnded(Variant meta)
{
Tooltip.Visible = false;
GD.Print($"OnMetaHoverEnded: {meta}");
}
}
イベントの引数はVariant。こういうユニオン型みたいなやつを見るとかなり抵抗を感じるが、urlタグでオプション文字列を指定しない限りはurlに囲まれた部分が文字列としてやってくると考えてよい。
マウスオーバー判定で詰まったところ
さて、meta(url)タグを使ってツールチップをマウス付近に置くことにした。
するとアラ不思議、マウスを左上に動かしているときだけマウスオーバーイベントが発生し、しかも出たり入ったりの振動をマウスが動いている間だけしている……
真相は単純で、このツールチップがマウスの判定を奪っているだけだった。
ツールチップのマウス奪い判定をすべてIgnoreにすると解決した。
感想とか
RichTextLabelが思いの外万能!
ここでは紹介していないがモダンな2Dゲームで見るようなwavyなテキストもこれで賄えるらしい。
urlタグではイベントが受け取れて結構なんでもできる。
マウスオーバーとクリックだけなので、ボタンほど融通は効かないがメッセージ内でそんな凝ったことはさせないだろうから今はこれで十分だ。
ドキュメントが足りていないことだけ恨めしいが、それ以外直感に反したこととかはやってこないので、うれし~~~って言いながらコーディングできた。