概要
Prometeにビルトインの UIライブラリを実装する。既存のノードシステムの上に構築し、ボタン・テキスト入力・モーダルダイアログなどの基本的なUI要素を提供する。
設計方針
- ノードシステムベース: UIElement は ContainableNode を継承し、既存の ZIndex・Transform・Trim・レンダリングパイプラインをそのまま活用する
- Shapeベースのデフォルト描画: テクスチャアセットをエンジンに同梱せず、Shape による最低限の見た目をデフォルトとする。NineSliceSprite によるカスタムデザインはオプション
- プラガブルなスタイル:
IUIStyle<TElement> で描画ロジックを分離し、ゲームごとにデザインを自由に差し替え可能にする
- レイアウトシステムとの共存余地: UIElement は通常の Node なので、将来 FlexBox 等のレイアウトライブラリを別途作った際にそのまま併用できる
主要コンポーネント
UIManager(DIプラグイン)
var app = PrometeApp.Create()
.Use<Keyboard>()
.Use<Mouse>()
.Use<UIManager>()
.BuildWithOpenGLDesktop();
責務:
- ヒットテスト: 毎フレーム、マウス位置に対してUI要素をZIndex順(手前→奥)に走査
- フォーカス管理: キーボード/ゲームパッドでのフォーカス移動、FocusGroup によるスコープ管理
- モーダルスタック: モーダル表示中はモーダル以下の要素へのイベントを遮断
- 入力ディスパッチ: 生の入力を UIイベント(Click, Hover, Submit, Cancel 等)に変換
UIElement 基底クラス
public abstract class UIElement : ContainableNode
{
public virtual bool HitTest(VectorInt point);
public bool IsInteractable { get; set; } = true;
public bool IsFocusable { get; set; } = true;
public int NavigationOrder { get; set; }
// スタイル
public UIElementState CurrentState { get; }
// 仮想メソッド(継承でオーバーライド)
protected virtual void OnPointerEnter();
protected virtual void OnPointerLeave();
protected virtual void OnPointerDown(PointerEventArgs e);
protected virtual void OnPointerUp(PointerEventArgs e);
protected virtual void OnFocus();
protected virtual void OnBlur();
protected virtual void OnSubmit();
protected virtual void OnCancel();
// 外部フック用イベント
public event Action? Clicked;
}
IUIStyle(スタイルシステム)
public interface IUIStyle<TElement> where TElement : UIElement
{
void Apply(TElement element, UIElementState state);
}
DefaultButtonStyle: Shape ベース(色指定のみ、テクスチャ不要)
NineSliceButtonStyle: ユーザー提供の Texture9Sliced で描画
状態変化時のみ Apply() を呼び出す(毎フレームではない)。
入力バインディング(InputMap)
マウス・キーボード・ゲームパッドの入力を統一的な「アクション」に抽象化する。
public class InputMap
{
public InputAction CreateAction(string name);
public void Bind(string actionName, KeyCode key);
public void Bind(string actionName, MouseButtonType button);
public void Bind(string actionName, GamepadButtonType button);
}
UIManager は内部的にデフォルトの InputMap を持ち、フォーカス移動や Submit/Cancel をバインドする。ユーザーが自由にリバインド可能。
プログラムからの仮想入力発火
InputMap はプログラムから直接アクションを発火できるAPIを提供する。
public class InputMap
{
/// <summary>
/// 指定したアクションをプログラムから発火する。
/// 実際のデバイス入力と同等に扱われる。
/// </summary>
public void Fire(string actionName);
/// <summary>
/// 指定したアクションの押下状態を制御する(押し続け等のシミュレーション用)。
/// </summary>
public void SetPressed(string actionName, bool pressed);
}
用途:
- 仮想入力: タッチスクリーンの仮想ボタン、アクセシビリティ支援など、アプリケーション側で独自の入力ソースを実装する場合
- テスト: ヘッドレスバックエンドと組み合わせ、UIの自動テストをデバイス入力なしで実行
- デバッグ: 開発中にスクリプトやデバッグコンソールからUI操作を再現
// テストでの使用例
var inputMap = app.GetPlugin<InputMap>();
inputMap.Fire("Submit"); // Enterキー押下と同等の効果
// 押し続けのシミュレーション
inputMap.SetPressed("MoveRight", true);
// ... 数フレーム後 ...
inputMap.SetPressed("MoveRight", false);
UI要素一覧
| 要素 |
デフォルト描画構成 |
備考 |
| Button |
Shape(矩形+ボーダー) + Text |
状態で色変更 |
| TextInput |
Shape(矩形+ボーダー) + Text(値) + Text(placeholder) + Shape(カーソル) |
Keyboard.GetChar() でテキスト入力 |
| Checkbox |
Shape(矩形) + Shape(チェックマーク) + Text(ラベル) |
トグル状態 |
| Slider |
Shape(トラック) + Shape(つまみ) |
ドラッグで float 値操作 |
| ScrollView |
Container(IsTrimmable) + Shape(スクロールバー) |
既存の Trim 機構を活用 |
| Panel |
Shape(矩形背景) |
子ノードのグループ化 |
| Modal |
Shape(全画面半透明オーバーレイ) + Panel |
UIManager.PushModal() で表示 |
モーダルとヒットテスト
- モーダルスタックの最上位のみがイベントを受け取る
- モーダル外クリックはイベントとして発火(閉じる動作に利用可能)
- モーダルがない場合は全 UIElement を ZIndex 降順で走査し、最初にヒットした要素で停止
フォーカスナビゲーション
NavigationOrder による Tab/上下キーでの順次移動
- 空間ナビゲーション(AbsoluteLocation ベースで方向キーの最近傍要素を探索)をオプション対応
FocusGroup(Container 単位)でフォーカススコープを区切る(モーダル内ではモーダルの子だけが対象)
プロジェクト構造
Promete/UI/
├── UIManager.cs
├── UIElement.cs
├── UIElementState.cs
├── FocusGroup.cs
├── InputMap.cs
├── InputAction.cs
├── Styles/
│ └── IUIStyle.cs
├── Elements/
│ ├── Button.cs
│ ├── TextInput.cs
│ ├── Checkbox.cs
│ ├── Slider.cs
│ ├── ScrollView.cs
│ ├── Panel.cs
│ └── Modal.cs
└── Events/
└── PointerEventArgs.cs
Promete 本体 (Promete.csproj) に含める。
概要
Prometeにビルトインの UIライブラリを実装する。既存のノードシステムの上に構築し、ボタン・テキスト入力・モーダルダイアログなどの基本的なUI要素を提供する。
設計方針
IUIStyle<TElement>で描画ロジックを分離し、ゲームごとにデザインを自由に差し替え可能にする主要コンポーネント
UIManager(DIプラグイン)
責務:
UIElement 基底クラス
IUIStyle(スタイルシステム)
DefaultButtonStyle: Shape ベース(色指定のみ、テクスチャ不要)NineSliceButtonStyle: ユーザー提供の Texture9Sliced で描画状態変化時のみ
Apply()を呼び出す(毎フレームではない)。入力バインディング(InputMap)
マウス・キーボード・ゲームパッドの入力を統一的な「アクション」に抽象化する。
UIManager は内部的にデフォルトの InputMap を持ち、フォーカス移動や Submit/Cancel をバインドする。ユーザーが自由にリバインド可能。
プログラムからの仮想入力発火
InputMap はプログラムから直接アクションを発火できるAPIを提供する。
用途:
UI要素一覧
モーダルとヒットテスト
フォーカスナビゲーション
NavigationOrderによる Tab/上下キーでの順次移動FocusGroup(Container 単位)でフォーカススコープを区切る(モーダル内ではモーダルの子だけが対象)プロジェクト構造
Promete 本体 (
Promete.csproj) に含める。