今回は UI の構成要素を見ていきたいと思います。
前回 で FMenu
には親クラスも合わせて以下の Dialog
が含まれていることが分かりました。
- ConsoleDialog
- FriendsDialog
- ExitDialog (非表示)
- PopupDialog (非表示)
- CustomInvitesDialog
- AuthDialog
FMenu::UpdateLayout
// custom invite / console frame #define CUSTOMINVITE_CONSOLE_FRAME_WIDTH .7f #define CUSTOMINVITE_CONSOLE_FRAME_HEIGHT 1.f #define CUSTOMINVITE_CONSOLE_FRAME_SCALE Vector2(CUSTOMINVITE_CONSOLE_FRAME_WIDTH, CUSTOMINVITE_CONSOLE_FRAME_HEIGHT) // friends frame #define FRIENDS_FRAME_WIDTH 1.f - CUSTOMINVITE_CONSOLE_FRAME_WIDTH #define FRIENDS_FRAME_HEIGHT 1.f #define FRIENDS_FRAME_SCALE Vector2(FRIENDS_FRAME_WIDTH, FRIENDS_FRAME_HEIGHT) // custom invite dialog (inside custom invite / console frame) #define CUSTOMINVITES_DIALOG_PERCENT_X 1.f #define CUSTOMINVITES_DIALOG_PERCENT_Y .2f #define CUSTOMINVITE_DIALOG_SCALE Vector2(CUSTOMINVITES_DIALOG_PERCENT_X, CUSTOMINVITES_DIALOG_PERCENT_Y) // console dialog (inside custom invite / console frame) #define CONSOLE_DIALOG_PERCENT_X 1.f #define CONSOLE_DIALOG_PERCENT_Y 1.f - CUSTOMINVITES_DIALOG_PERCENT_Y #define CONSOLE_DIALOG_SCALE Vector2(CONSOLE_DIALOG_PERCENT_X, CONSOLE_DIALOG_PERCENT_Y) // freinds dialog (inside friends frame) #define FRIENDS_USAGE_PERCENT_X 1.f #define FRIENDS_USAGE_PERCENT_Y 1.f #define FRIENDS_DIALOG_SCALE Vector2(FRIENDS_USAGE_PERCENT_X, FRIENDS_USAGE_PERCENT_Y) void FMenu::UpdateLayout(int Width, int Height) { WindowSize = Vector2((float)Width, (float)Height); Vector2 LayoutPositionMarker{ }; BackgroundImage->SetPosition(LayoutPositionMarker); BackgroundImage->SetSize(Vector2((float)Width, ((float)Height) / 2.f)); // move the layout cursor down 10px, recalculate available percentage LayoutPositionMarker += Vector2(10.f, 120.f); const Vector2 MainFrameOrigin{ LayoutPositionMarker }; const Vector2 MainFrameSize{ WindowSize - MainFrameOrigin }; const Vector2 CustomInviteConsoleFrameOrigin{ MainFrameOrigin }; const Vector2 CustomInviteConsoleFrameSize{ Vector2::CoeffProduct(CUSTOMINVITE_CONSOLE_FRAME_SCALE, MainFrameSize) }; const Vector2 CustomInviteDialogSize = Vector2::CoeffProduct(CUSTOMINVITE_DIALOG_SCALE, CustomInviteConsoleFrameSize); if (CustomInvitesDialog) { CustomInvitesDialog->SetSize(CustomInviteDialogSize); CustomInvitesDialog->SetPosition(CustomInviteConsoleFrameOrigin); } LayoutPositionMarker.y += CustomInviteDialogSize.y; const Vector2 ConsoleWidgetSize = Vector2::CoeffProduct(CONSOLE_DIALOG_SCALE, CustomInviteConsoleFrameSize); if (ConsoleDialog) { ConsoleDialog->SetSize(ConsoleWidgetSize); ConsoleDialog->SetPosition(LayoutPositionMarker); } LayoutPositionMarker = MainFrameOrigin; LayoutPositionMarker.x += CustomInviteConsoleFrameSize.x; const Vector2 FriendsFrameOrigin{ LayoutPositionMarker }; const Vector2 FriendsFrameSize = Vector2::CoeffProduct(FRIENDS_FRAME_SCALE, MainFrameSize); const Vector2 FriendsWidgetSize = Vector2::CoeffProduct(FRIENDS_DIALOG_SCALE, FriendsFrameSize); if (FriendsDialog) { FriendsDialog->SetPosition(LayoutPositionMarker); FriendsDialog->SetSize(FriendsWidgetSize); } if (PopupDialog) { PopupDialog->SetPosition(Vector2((WindowSize.x / 2.f) - PopupDialog->GetSize().x / 2.0f, (WindowSize.y / 2.f) - PopupDialog->GetSize().y)); } if (ExitDialog) { ExitDialog->SetPosition(Vector2((WindowSize.x / 2.f) - ExitDialog->GetSize().x / 2.0f, (WindowSize.y / 2.f) - ExitDialog->GetSize().y - 200.0f)); } if (AuthDialogs) { AuthDialogs->UpdateLayout(); } }
順番に見ていきます。
WindowSize = Vector2((float)Width, (float)Height); Vector2 LayoutPositionMarker{ };
引数から得られた Width
と Height
を WindowSize
に入れています。おそらくそのままの意味だと思います。
LayoutPositionMarker
を初期化しています。このベクトルに、各 Dialog の配置のベース情報を更新していくようです。
BackgroundImage->SetPosition(LayoutPositionMarker); BackgroundImage->SetSize(Vector2((float)Width, ((float)Height) / 2.f));
BackgroundImage
は Dialog
ではないのでここまでで紹介していませんが FBaseMenu
のコンストラクタで以下のように初期化されます。
BackgroundImage = std::make_shared<FSpriteWidget>(Vector2(0.f, 0.f), Vector2(1024.f, 384.f), DefaultLayer, L"Assets/menu_background.dds");
画像としては以下の部分になります。 FSpriteWidget
のコンストラクタの第一引数は「位置」であり、第二引数は「サイズ」なので、この背景画像は (0,0) の位置に配置され、幅 1024px, 高さ 384px ということになります。ただ、以下のアプリケーションの画像部分はそこまでの高さはありません。あくまでこの Widget のサイズです。
ちなみに、BackgroundImage
に対して SetPosition
と SetSize
をしていますが、他にもタイトルラベル等もあり、それらもある程度 BackgroundImage
が (0,0) に配置される前提でハードコードされているようです。(Window サイズも最小サイズが 1024x768 になっています)
// move the layout cursor down 10px, recalculate available percentage LayoutPositionMarker += Vector2(10.f, 120.f); const Vector2 MainFrameOrigin{ LayoutPositionMarker }; const Vector2 MainFrameSize{ WindowSize - MainFrameOrigin };
続いて MainFrame
ですが、これは MainFrame
というものが存在しているわけではなく BackgroundImage
エリアとの区別のために存在しているようです。配置としては、 LayoutPositionMarker
はこの直前で (0, 0) なので、ここ MainFrameOrigin
は (10, 120) を起点としていることになります。
上図のように、以降の常時表示される要素は MainFrame
から計算されることになります。
const Vector2 CustomInviteConsoleFrameOrigin{ MainFrameOrigin }; const Vector2 CustomInviteConsoleFrameSize{ Vector2::CoeffProduct(CUSTOMINVITE_CONSOLE_FRAME_SCALE, MainFrameSize) }; const Vector2 CustomInviteDialogSize = Vector2::CoeffProduct(CUSTOMINVITE_DIALOG_SCALE, CustomInviteConsoleFrameSize); if (CustomInvitesDialog) { CustomInvitesDialog->SetSize(CustomInviteDialogSize); CustomInvitesDialog->SetPosition(CustomInviteConsoleFrameOrigin); } LayoutPositionMarker.y += CustomInviteDialogSize.y;
Vector2::CoeffProduct
は成分ごとの積です。
#define CUSTOMINVITE_CONSOLE_FRAME_WIDTH .7f #define CUSTOMINVITE_CONSOLE_FRAME_HEIGHT 1.f #define CUSTOMINVITE_CONSOLE_FRAME_SCALE Vector2(CUSTOMINVITE_CONSOLE_FRAME_WIDTH, CUSTOMINVITE_CONSOLE_FRAME_HEIGHT) // custom invite dialog (inside custom invite / console frame) #define CUSTOMINVITES_DIALOG_PERCENT_X 1.f #define CUSTOMINVITES_DIALOG_PERCENT_Y .2f #define CUSTOMINVITE_DIALOG_SCALE Vector2(CUSTOMINVITES_DIALOG_PERCENT_X, CUSTOMINVITES_DIALOG_PERCENT_Y)
CustomInviteConsoleFrame
は、CustomInviteDialog
とこの後で出てくる ConsoleDialog
の両方の領域です。
そのサイズは高さは MainFrame
と同じ、幅は 0.7
倍されています。以下のような領域ですね。
続いて CustomInviteDialog
は CustomInviteConsoleFrame
に対して幅は同じ、高さは 0.2
倍となっています。
まとめると以下のような感じです。
LayoutPositionMarker.y += CustomInviteDialogSize.y;
最後に、LayoutPositionMarker
の Y 座標を CustomInviteDialog
のそれで更新しています。
const Vector2 ConsoleWidgetSize = Vector2::CoeffProduct(CONSOLE_DIALOG_SCALE, CustomInviteConsoleFrameSize); if (ConsoleDialog) { ConsoleDialog->SetSize(ConsoleWidgetSize); ConsoleDialog->SetPosition(LayoutPositionMarker); } LayoutPositionMarker = MainFrameOrigin; LayoutPositionMarker.x += CustomInviteConsoleFrameSize.x;
// console dialog (inside custom invite / console frame) #define CONSOLE_DIALOG_PERCENT_X 1.f #define CONSOLE_DIALOG_PERCENT_Y 1.f - CUSTOMINVITES_DIALOG_PERCENT_Y #define CONSOLE_DIALOG_SCALE Vector2(CONSOLE_DIALOG_PERCENT_X, CONSOLE_DIALOG_PERCENT_Y)
続いて、ConsoleDialog
ですが、先程の内容からの延長ですが、 CustomInviteConsoleFrame
に対して、幅は同じですが、高さが CustomInviteDialog
と分割するような指定になっています。
注意すべきは、 LayoutPositionMarker
の値が、 MainFrame
の Y 座標、CustomInviteConsoleFrame
の X 座標になっています。
const Vector2 FriendsFrameOrigin{ LayoutPositionMarker }; const Vector2 FriendsFrameSize = Vector2::CoeffProduct(FRIENDS_FRAME_SCALE, MainFrameSize); const Vector2 FriendsWidgetSize = Vector2::CoeffProduct(FRIENDS_DIALOG_SCALE, FriendsFrameSize); if (FriendsDialog) { FriendsDialog->SetPosition(LayoutPositionMarker); FriendsDialog->SetSize(FriendsWidgetSize); }
// friends frame #define FRIENDS_FRAME_WIDTH 1.f - CUSTOMINVITE_CONSOLE_FRAME_WIDTH #define FRIENDS_FRAME_HEIGHT 1.f #define FRIENDS_FRAME_SCALE Vector2(FRIENDS_FRAME_WIDTH, FRIENDS_FRAME_HEIGHT) // freinds dialog (inside friends frame) #define FRIENDS_USAGE_PERCENT_X 1.f #define FRIENDS_USAGE_PERCENT_Y 1.f #define FRIENDS_DIALOG_SCALE Vector2(FRIENDS_USAGE_PERCENT_X, FRIENDS_USAGE_PERCENT_Y)
続いて FriendsFrame
と FriendsDialog
です。
FriendsDialog
は FriendsFrame
に対して幅、高さともに等倍なので同じサイズです。
FriendsFrame
は MainFrame
に対して CustomeInviteConsoleFrame
と幅を分け合う形になっています。
上述の通り、 LayoutPositionMarker
は CustomInviteConsoleFrame
の右上端に移動しているので、そこから配置されることになります。
if (PopupDialog) { PopupDialog->SetPosition(Vector2((WindowSize.x / 2.f) - PopupDialog->GetSize().x / 2.0f, (WindowSize.y / 2.f) - PopupDialog->GetSize().y)); } if (ExitDialog) { ExitDialog->SetPosition(Vector2((WindowSize.x / 2.f) - ExitDialog->GetSize().x / 2.0f, (WindowSize.y / 2.f) - ExitDialog->GetSize().y - 200.0f)); }
PopupDialog
と ExitDialog
に関しては常時表示されているわけではなく、なにかの通知の場合に表示されます。なので、それぞれ、WindowSize
に対して計算されています。
PopupDialog | ExitDialog |
---|---|
AuthDialog
if (AuthDialogs) { AuthDialogs->UpdateLayout(); }
最後に AuthDialog
ですが、見ての通りでこれだけ UpdateLayout
が呼び出されています。
AuthDialog
は前回も触れましたが FriendsDialog
に依存しており、内部では ParentDialog
として保持しています。
加えて、それに対して Depth も浅い部分に AuthDialog
の UI 要素を描画しているため FriendsDialog
内に AuthDialog
の内容が描画されることになります。
まとめ
サンプルアプリケーションの UI 要素について、どのように配置されているかをざっと眺めました。
次は、今回のサンプルのメインの部分である AuthDialog
の方に入っていければと思います。