PAD/キーボード入力によるボタンの実装
PAD/キーボード入力によるボタンの実装
こんばんは。
現在、DxLib を使用してゲーム開発をしているのですが、ボタンのフォーカスの移動の実装をどれで実装すべきか悩んだので質問させていただきます。
入力は PAD/キーボードを想定しています。
方法1
ボタンクラスに上下左右のボタンをポインタで持たせて、ボタンクラスの Update 関数等を毎フレーム呼び出し、入力されているかつ、上下左右のポインタが nullptr でなければそのボタンにフォーカスを移動する。
良い点
・実装が直感的
悪い点
・ボタンの数が増えたときに管理が大変になる
方法2
ボタンセレクタのようなクラスを作成し、そこにボタンのインスタンスと座標(二次元かつ実際の座標ではなく、フォーカス移動用の仮想的なもの)をいれ、ボタンセレクタの Update 関数を毎フレーム呼び出し、入力の方向に応じて(例えば右入力なら現在フォーカスされているボタンのx座標+1)フォーカスする対象のボタンを探し出し、それにフォーカスする。
良い点
・ボタンが増えてもそれぞれの座標を指定するだけなので管理が方法1より楽
悪い点
・ボタンセレクタを GUI コンテナとして実装するか、それとも全く関係のないものとして実装するか悩む(GUI コンテナとして実装する場合、invisible なオブジェクトであるのに GUI 関連として実装するのはどうなのか...逆に関係のないものとして実装するとそれはそれで実装が分散して嫌な感じ...)
上記の二つの方法があると考えたのですが、どちらが一般的な実装方法なのでしょうか?
また、ほかにも方法がありましたらぜひ教えていただきたいです。
現在、DxLib を使用してゲーム開発をしているのですが、ボタンのフォーカスの移動の実装をどれで実装すべきか悩んだので質問させていただきます。
入力は PAD/キーボードを想定しています。
方法1
ボタンクラスに上下左右のボタンをポインタで持たせて、ボタンクラスの Update 関数等を毎フレーム呼び出し、入力されているかつ、上下左右のポインタが nullptr でなければそのボタンにフォーカスを移動する。
良い点
・実装が直感的
悪い点
・ボタンの数が増えたときに管理が大変になる
方法2
ボタンセレクタのようなクラスを作成し、そこにボタンのインスタンスと座標(二次元かつ実際の座標ではなく、フォーカス移動用の仮想的なもの)をいれ、ボタンセレクタの Update 関数を毎フレーム呼び出し、入力の方向に応じて(例えば右入力なら現在フォーカスされているボタンのx座標+1)フォーカスする対象のボタンを探し出し、それにフォーカスする。
良い点
・ボタンが増えてもそれぞれの座標を指定するだけなので管理が方法1より楽
悪い点
・ボタンセレクタを GUI コンテナとして実装するか、それとも全く関係のないものとして実装するか悩む(GUI コンテナとして実装する場合、invisible なオブジェクトであるのに GUI 関連として実装するのはどうなのか...逆に関係のないものとして実装するとそれはそれで実装が分散して嫌な感じ...)
上記の二つの方法があると考えたのですが、どちらが一般的な実装方法なのでしょうか?
また、ほかにも方法がありましたらぜひ教えていただきたいです。
Re: PAD/キーボード入力によるボタンの実装
追加で質問です。
PAD/キーボード入力に対応しているオープンソースなライブラリ等がありましたら教えていただけるとありがたいです。
PAD/キーボード入力に対応しているオープンソースなライブラリ等がありましたら教えていただけるとありがたいです。
Re: PAD/キーボード入力によるボタンの実装
話の前提がよくわかんねぇけど,要は,平面上に点群があるときに,ある点から見て最も「右隣りな」点っていうのはどれだろう? っていうだけの話に見える.
であれば,点間の相対的な座標関係から「右隣っぽさ」をてきとーに評価し,閾値以上の評価値を持つ最もそれっぽいやつを右隣だということにすれば良いのでは.
で,その演算を毎度やるのが重いのであれば,どこかのタイミングで求めた結果を覚えておく感じで.例えば,
> 上下左右のボタンをポインタ
とかいうのに結果を記録しとけばよい.
---
どうでもいいけど,
> 一般的な実装方法なのでしょうか?
みたいな問い方は,非常に敷居が高いものになるんじゃない?
「コレが一般的」と言えるほどにいろんなUIの実装の中身を知ってるようなすごい人しか回答できないよね,っていう意味で.
(本当にそういう趣旨の質問なのであれば,それでいいと思うけど)
であれば,点間の相対的な座標関係から「右隣っぽさ」をてきとーに評価し,閾値以上の評価値を持つ最もそれっぽいやつを右隣だということにすれば良いのでは.
で,その演算を毎度やるのが重いのであれば,どこかのタイミングで求めた結果を覚えておく感じで.例えば,
> 上下左右のボタンをポインタ
とかいうのに結果を記録しとけばよい.
---
どうでもいいけど,
> 一般的な実装方法なのでしょうか?
みたいな問い方は,非常に敷居が高いものになるんじゃない?
「コレが一般的」と言えるほどにいろんなUIの実装の中身を知ってるようなすごい人しか回答できないよね,っていう意味で.
(本当にそういう趣旨の質問なのであれば,それでいいと思うけど)
Re: PAD/キーボード入力によるボタンの実装
回答ありがとうございます。
多分、質問の趣旨が伝わっていないのですが、私が聞きたいのは実装の具体的な内容ではなく、実装の方向性(アーキテクチャまではいかないけどそんな感じの論理的な奴)です。
実際に方法1、方法2の両方のコードは書けるのですが、どちらもしっくりこなかったので質問した次第です。
日本語が下手ですみませんでした。
> みたいな問い方は,非常に敷居が高いものになるんじゃない?
これについてですが、一般的という表現が悪かったです。
「自分が見た実装の中で一番多かった手法と、方法1、2以外での実装方法がありましたら教えていただけるとありがたいです。」になります。
多分、質問の趣旨が伝わっていないのですが、私が聞きたいのは実装の具体的な内容ではなく、実装の方向性(アーキテクチャまではいかないけどそんな感じの論理的な奴)です。
実際に方法1、方法2の両方のコードは書けるのですが、どちらもしっくりこなかったので質問した次第です。
日本語が下手ですみませんでした。
> みたいな問い方は,非常に敷居が高いものになるんじゃない?
これについてですが、一般的という表現が悪かったです。
「自分が見た実装の中で一番多かった手法と、方法1、2以外での実装方法がありましたら教えていただけるとありがたいです。」になります。
Re: PAD/キーボード入力によるボタンの実装
書くのを忘れていましたが、事前に調べた所、Unity は方法1、Unreal Engine は方法1と方法2のどちらか選択のようです。
実際に触ったわけではなく、調べた範囲なので間違いがありましたら教えていただけるとありがたいです。
実際に触ったわけではなく、調べた範囲なので間違いがありましたら教えていただけるとありがたいです。
Re: PAD/キーボード入力によるボタンの実装
自分だったら1にすると思います(個人の感想です)。「実装が直感的」が大きな理由です。悪い点に「ボタンの数が増えたときに管理が大変」を挙げられていますが、保守性もそんなに悪くないかと思います。座標計算の場合だと、カーソルがループする場合にちょっと面倒になりそうな気がしています。
自分のイメージでは実装はこんな感じです。
自分のイメージでは実装はこんな感じです。
Re: PAD/キーボード入力によるボタンの実装
回答ありがとうございます。参考になります。
提示されたコードの場合、FOCUS_MAP の std::string 部分は "up", "left" 等になるのでしょうか?
> カーソルがループする場合にちょっと面倒になりそうな気がしています。
自分が座標計算で実装した際は、コンテナに追加する際に最大x座標とy座標を記録しておき、wrapping フラグでループするかを管理して、true なら最大座標からそれより大きい座標に移動するときは最小座標で検索…みたいな実装にしていました。
それでも
XOOX
OOOO
このような配置の時、上段の処理が面倒ですね。(O=ボタン、X=空白)
提示されたコードの場合、FOCUS_MAP の std::string 部分は "up", "left" 等になるのでしょうか?
> カーソルがループする場合にちょっと面倒になりそうな気がしています。
自分が座標計算で実装した際は、コンテナに追加する際に最大x座標とy座標を記録しておき、wrapping フラグでループするかを管理して、true なら最大座標からそれより大きい座標に移動するときは最小座標で検索…みたいな実装にしていました。
それでも
XOOX
OOOO
このような配置の時、上段の処理が面倒ですね。(O=ボタン、X=空白)
Re: PAD/キーボード入力によるボタンの実装
方法2に関する
> (GUI コンテナとして実装する場合、invisible なオブジェクトであるのに GUI 関連として実装するのはどうなのか...逆に関係のないものとして実装するとそれはそれで実装が分散して嫌な感じ...)
という話の内容がよくわからない.
(そもそも私が不勉強なのか「GUIコンテナ」なる単語の意味がいまいち不明.標準的に通じる言葉なの?)
「ボタンの集合もまたGUIなのだ」というCompositeパターン気味な(?)話では何が{実際に問題になる/しっくりこない/嫌/etc}なのか?
GUIって入れ子な階層構造になってるのが「一般的」な気がしますが.
いわゆる WindowなりDialog なりの上にコントロール群やらがあって… っていう.
単品のGUI部品で考えるとしても ListControl みたいな感じの物だと捉えてはどうか?
(それ自身がGUI構成要素であり,その配下に項目群を有する.項目のいずれかが選択状態になり得る.)
> (GUI コンテナとして実装する場合、invisible なオブジェクトであるのに GUI 関連として実装するのはどうなのか...逆に関係のないものとして実装するとそれはそれで実装が分散して嫌な感じ...)
という話の内容がよくわからない.
(そもそも私が不勉強なのか「GUIコンテナ」なる単語の意味がいまいち不明.標準的に通じる言葉なの?)
「ボタンの集合もまたGUIなのだ」というCompositeパターン気味な(?)話では何が{実際に問題になる/しっくりこない/嫌/etc}なのか?
GUIって入れ子な階層構造になってるのが「一般的」な気がしますが.
いわゆる WindowなりDialog なりの上にコントロール群やらがあって… っていう.
単品のGUI部品で考えるとしても ListControl みたいな感じの物だと捉えてはどうか?
(それ自身がGUI構成要素であり,その配下に項目群を有する.項目のいずれかが選択状態になり得る.)
Re: PAD/キーボード入力によるボタンの実装
オフトピック
「お前の話はズレすぎている.そういう話をしているのではない」とか
「正直話のレベルが低すぎて応答するだけでも面倒だから無理して入ってくるな」だとか
そういう場合には遠慮なく言ってください.
そういう反応を割りと良くもらう人なので大丈夫です.
「正直話のレベルが低すぎて応答するだけでも面倒だから無理して入ってくるな」だとか
そういう場合には遠慮なく言ってください.
そういう反応を割りと良くもらう人なので大丈夫です.
Re: PAD/キーボード入力によるボタンの実装
>提示されたコードの場合、FOCUS_MAP の std::string 部分は "up", "left" 等になるのでしょうか?
はい、そういうつもりです。でしたが、別に文字列ではなくてもenumとかの整数値でもいいですね。
>自分が座標計算で実装した際は...
座標を計算する方法だとバグで意図せぬ結果(移動先)になることがありますが、目的の場所を直接設定する方法は、データの準備をちゃんとやれば間違いが少ないかなと思ってます。1の方法なら計算式では表現しにくいような移動もベタで構築できるので、仕様さえしっかり固まっていればコーディングの難易度も低くてよいかなと思います。
はい、そういうつもりです。でしたが、別に文字列ではなくてもenumとかの整数値でもいいですね。
>自分が座標計算で実装した際は...
座標を計算する方法だとバグで意図せぬ結果(移動先)になることがありますが、目的の場所を直接設定する方法は、データの準備をちゃんとやれば間違いが少ないかなと思ってます。1の方法なら計算式では表現しにくいような移動もベタで構築できるので、仕様さえしっかり固まっていればコーディングの難易度も低くてよいかなと思います。
Re: PAD/キーボード入力によるボタンの実装
> 方法1と2の違いとは「グラフのノード自身が連結(枝)に関する情報を保持するか否か」と見える.見当違いであろうか?
見当違いではないと思います。まさにその通りだと思います。その考えはなかったです。
GUI コンテナについてですが、私も特に UI 関連に精通しているわけではないので一般的かどうかは知りません。
ただ、今回は「Win32 の GroupBox」のようないわゆる GUI コンポーネント達をぶち込むやつのことを想定して言いましたので、ListControl も当てはまるかと思います。
> 何が{実際に問題になる/しっくりこない/嫌/etc}なのか?
この件ですが、確かによく考えると GUI の要素って全部が全部可視ではないなぁと思い、不可視だから GUI 関連と混ぜたくないという感情(?)は消えました。
しかし、新たに「ボタンのフォーカスの移動のためだけのコンテナ」と「ボタン」との間に密接な結合が生まれるのも嫌だという感情が生まれました。(キリがなさそうなので無視していただいて結構です)
usao さんの回答ですが、とても勉強になるので感謝しています。ありがとうございます!
見当違いではないと思います。まさにその通りだと思います。その考えはなかったです。
GUI コンテナについてですが、私も特に UI 関連に精通しているわけではないので一般的かどうかは知りません。
ただ、今回は「Win32 の GroupBox」のようないわゆる GUI コンポーネント達をぶち込むやつのことを想定して言いましたので、ListControl も当てはまるかと思います。
> 何が{実際に問題になる/しっくりこない/嫌/etc}なのか?
この件ですが、確かによく考えると GUI の要素って全部が全部可視ではないなぁと思い、不可視だから GUI 関連と混ぜたくないという感情(?)は消えました。
しかし、新たに「ボタンのフォーカスの移動のためだけのコンテナ」と「ボタン」との間に密接な結合が生まれるのも嫌だという感情が生まれました。(キリがなさそうなので無視していただいて結構です)
usao さんの回答ですが、とても勉強になるので感謝しています。ありがとうございます!
Re: PAD/キーボード入力によるボタンの実装
作り方次第だけど,ボタン自体は「フォーカスを別のやつに変える」という話を知らなくても良いんじゃないかな.
入力情報が上から降りてきたとき,「コンテナ」はその入力がフォーカス移動操作になるのか否かだけを判定して,そうだったらフォーカス変更の処理をする,そうじゃないなら現在フォーカスを持っているボタンに入力情報を渡してボタン固有の処理をさせる,みたいな.
…そんな感じで,フォーカスがあるボタンだけに処理機会が回ってくるのであれば,ボタン自身はフォーカスという概念自体を知る必要も無さそうな気がします.
(例えばフォーカス有無で描画具合を変えるのだとしても,枠を付けるくらいならコンテナ側でそういう追加描画をやるのでもいいし,そんな簡単なのじゃなくてもっとボタンの描画具合が根底から変わるのだとしてもボタンの描画処理の引数で描きわけさせるとか,描画メソッドを2つ持たせて呼び分けるとか,そんなので済むかも)
入力情報が上から降りてきたとき,「コンテナ」はその入力がフォーカス移動操作になるのか否かだけを判定して,そうだったらフォーカス変更の処理をする,そうじゃないなら現在フォーカスを持っているボタンに入力情報を渡してボタン固有の処理をさせる,みたいな.
…そんな感じで,フォーカスがあるボタンだけに処理機会が回ってくるのであれば,ボタン自身はフォーカスという概念自体を知る必要も無さそうな気がします.
(例えばフォーカス有無で描画具合を変えるのだとしても,枠を付けるくらいならコンテナ側でそういう追加描画をやるのでもいいし,そんな簡単なのじゃなくてもっとボタンの描画具合が根底から変わるのだとしてもボタンの描画処理の引数で描きわけさせるとか,描画メソッドを2つ持たせて呼び分けるとか,そんなので済むかも)
Re: PAD/キーボード入力によるボタンの実装
なるほど。良い実装方法ですね。
私が考えていた実装方法は GUI のクラスごとに独立して入力処理をする方法でしたので、自分の愚かさに苦笑しています。(変な日本語ですみませんw)
実際にそのような実装方法を採用している GUI ライブラリをご存じでしたら、参考にしたいので教えていただきたいです!
私が考えていた実装方法は GUI のクラスごとに独立して入力処理をする方法でしたので、自分の愚かさに苦笑しています。(変な日本語ですみませんw)
実際にそのような実装方法を採用している GUI ライブラリをご存じでしたら、参考にしたいので教えていただきたいです!
Re: PAD/キーボード入力によるボタンの実装
Sorry.私は GUIライブラリの具体実装 を知る者ではないです.
(単に「自分ならこうするかもな」的な話を好き勝手に書いているだけの素人です.GUIについては専ら何かを「使う」だけの側.)
#14 は,
自分だったら「ボタンはコンテナの存在とかフォーカスがどうのいうようなことを可能な限り知らなくて済むようにしたいかなぁ(そんな形になんとか持ち込めないかなぁ)」と考えるかな,っていう話で,おそらく
> 「ボタンのフォーカスの移動のためだけのコンテナ」と「ボタン」との間に密接な結合が生まれるのも嫌だという感情
と 同じ/似ている 感覚であろうと思います.
例えば,単一のボタンだけがあれば済む場面があるとしたらボタンを単独で使いたい気がするから,ボタンに「XXありき」みたいなしがらみは持たせたくないかなぁ…みたいな.
(単に「自分ならこうするかもな」的な話を好き勝手に書いているだけの素人です.GUIについては専ら何かを「使う」だけの側.)
#14 は,
自分だったら「ボタンはコンテナの存在とかフォーカスがどうのいうようなことを可能な限り知らなくて済むようにしたいかなぁ(そんな形になんとか持ち込めないかなぁ)」と考えるかな,っていう話で,おそらく
> 「ボタンのフォーカスの移動のためだけのコンテナ」と「ボタン」との間に密接な結合が生まれるのも嫌だという感情
と 同じ/似ている 感覚であろうと思います.
例えば,単一のボタンだけがあれば済む場面があるとしたらボタンを単独で使いたい気がするから,ボタンに「XXありき」みたいなしがらみは持たせたくないかなぁ…みたいな.
Re: PAD/キーボード入力によるボタンの実装
…なので(?),本件に関して言えば,私ならまずは方法2側を考える.
ボタンの集合を配下に持つ「フォーカスという話を解決する者」(コンテナ)を用意するという意味で.
フォーカスの移動先に関する具体実装は
> 上下左右のボタンをポインタ
という形でも何でもいいけど,それはボタンに持たせるのではなくて,コンテナ側が勝手に持つデータ構造.
(その構造をどうやって作り上げるのか? という話はそれこそ具体実装そのものでしかないので,最も実際の用途に見合う形でやる)
ボタンの集合を配下に持つ「フォーカスという話を解決する者」(コンテナ)を用意するという意味で.
フォーカスの移動先に関する具体実装は
> 上下左右のボタンをポインタ
という形でも何でもいいけど,それはボタンに持たせるのではなくて,コンテナ側が勝手に持つデータ構造.
(その構造をどうやって作り上げるのか? という話はそれこそ具体実装そのものでしかないので,最も実際の用途に見合う形でやる)
Re: PAD/キーボード入力によるボタンの実装
なるほどぉ...これは難しいですね...
usao さんの方法も素晴らしいし、参照魚さんの直観的っていう意見もその通りだし...
悩みますね~
usao さんの方法も素晴らしいし、参照魚さんの直観的っていう意見もその通りだし...
悩みますね~
Re: PAD/キーボード入力によるボタンの実装
雰囲気書いてみたっす.
(↓のmain() の記述でしか動作確認してないけど)
ボタンの隣接関係の登録時には「ID」という値で指定.
↓
コンテナ自体は単に自身が持つ vector の index 値で全ての情報を保持.
(↓のmain() の記述でしか動作確認してないけど)
ボタンの隣接関係の登録時には「ID」という値で指定.
↓
コンテナ自体は単に自身が持つ vector の index 値で全ての情報を保持.
//ボタン.※ここでは単にTextを持つだけ.
class Button
{
private:
std::string m_Text;
public:
Button( const std::string &Text ) : m_Text{Text} {}
const std::string &Text() const { return m_Text; }
};
//「コンテナ」
class ButtonContainer
{
private:
//ボタンと,各ボタンからの4方向のフォーカス移動先.(移動先の値は m_Data のindex)
std::vector< std::pair< std::shared_ptr<Button>, std::array<int,4> > > m_Data;
//現在フォーカスがあるボタンを示す m_Data のindex.該当が無い場合は負の値とする.
int m_iCurrFocusButton;
private:
//private ctor : Builder からのみ構築できる.
ButtonContainer( std::vector< std::pair< std::shared_ptr<Button>, std::array<int,4> > > &&Data, int iCurrFocus )
: m_Data( std::move(Data) ), m_iCurrFocusButton(iCurrFocus)
{}
ButtonContainer( const ButtonContainer & ) = delete;
ButtonContainer &operator=( const ButtonContainer & ) = delete;
public:
//※これは単に保持データの中身を確認するテスト
void TestShow() const
{
for( size_t i=0; i<m_Data.size(); ++i )
{
std::cout << "[" << i << "]:" << m_Data[i].first->Text() << " ";
for( int idx : m_Data[i].second ){ std::cout << "," << idx; }
std::cout << std::endl;
}
std::cout << "Index of Curr Focus Button : " << m_iCurrFocusButton << std::endl;
}
//-------------
public: //ButtonContainer生成器
class Builder
{
private:
std::map< int, std::pair< std::shared_ptr<Button>, std::array<int,4> > > m_Data;
public:
//ctor : 引数は Add() と同じ
Builder( std::shared_ptr<Button> spButton, int ID, const std::array<int,4> &NeighborIDs )
{ Add( spButton, ID, NeighborIDs ); }
public:
//ボタンと,そのボタンを示すID値,フォーカス移動先の4方向のボタンのID値を指定して情報を登録.
//(ある方向にフォーカス移動先が無い場合は,存在しないID値を指定する)
Builder &Add( std::shared_ptr<Button> spButton, int ID, const std::array<int,4> &NeighborIDs )
{
m_Data[ID] = std::pair< std::shared_ptr<Button>, std::array<int,4> >( spButton, NeighborIDs );
return *this;
}
//登録されている情報から ButtonContainer を生成する.
//引数は初期にフォーカスを持つボタンのID.
//(初期フォーカス無し状態とする場合には登録されていないID値を指定する)
std::unique_ptr< ButtonContainer > Build( int InitFocusButtonID ) const
{
std::vector< int > IDs;
IDs.reserve( m_Data.size() );
for( const auto &D : m_Data ){ IDs.push_back(D.first); }
std::sort( IDs.begin(), IDs.end() ); //←別に要らんかも
std::vector< std::pair< std::shared_ptr<Button>, std::array<int,4> > > Result;
Result.reserve( IDs.size() );
for( int ID : IDs )
{
const auto d = m_Data.at(ID);
std::array<int,4> NeighborIndex;
for( int i=0; i<4; ++i )
{
auto iFound = std::find( IDs.begin(), IDs.end(), d.second[i] );
NeighborIndex[i] = (iFound!=IDs.end() ? (int)std::distance( IDs.begin(), iFound ) : -1 );
}
Result.emplace_back( d.first, std::move(NeighborIndex) );
}
int InitFocusIndex = -1;
{
auto iFound = std::find( IDs.begin(), IDs.end(), InitFocusButtonID );
if( iFound != IDs.end() ){ InitFocusIndex = (int)std::distance( IDs.begin(), iFound ); }
}
return std::unique_ptr<ButtonContainer>( new ButtonContainer( std::move(Result), InitFocusIndex ) );
}
};
};
//main
int main( /*int argc, const char *argv[]*/ )
{
//やってみる
std::unique_ptr<ButtonContainer> spContainer =
ButtonContainer::Builder( std::make_shared<Button>( "B1" ), 1, { 99,0,2,0 } )
.Add( std::make_shared<Button>( "B2" ), 2, { 0,0,0,1 } )
.Add( std::make_shared<Button>( "B99" ), 99, { 0,1,0,0 } )
.Build( 99 );
spContainer->TestShow();
return 0;
}
Re: PAD/キーボード入力によるボタンの実装
わざわざコードありがとうございます!!!!
質問とは話がずれるのですが、提示されたコードで Builder を利用しているのはなぜなのでしょうか?
単純に ButtonContainer のコンストラクタに可変長でぶち込むか、ButtonContainer::Add -> ButtonContainer::Build(initFocusIndex) ではダメなのでしょうか?(後者は一年後に仕様を忘れてバグりそう)
コードでは map を使って id を最適化(?)されていますが、これも id を引数で取らずに勝手に 0 から割り振ってやれば良いと思ったのです。
本題ですが、自分は Focusable なるインタフェースを作ってそれを継承したやつらでいい感じにフォーカス移動をさせる予定です。
質問とは話がずれるのですが、提示されたコードで Builder を利用しているのはなぜなのでしょうか?
単純に ButtonContainer のコンストラクタに可変長でぶち込むか、ButtonContainer::Add -> ButtonContainer::Build(initFocusIndex) ではダメなのでしょうか?(後者は一年後に仕様を忘れてバグりそう)
コードでは map を使って id を最適化(?)されていますが、これも id を引数で取らずに勝手に 0 から割り振ってやれば良いと思ったのです。
本題ですが、自分は Focusable なるインタフェースを作ってそれを継承したやつらでいい感じにフォーカス移動をさせる予定です。
Re: PAD/キーボード入力によるボタンの実装
> この辺↓の move 関係の文法は怪しいかも…
ガチ素人なので間違ってるかもなのですが、右辺値をムーブする必要ないかと...
右辺値ならそのままでよいかと思いまふ
ガチ素人なので間違ってるかもなのですが、右辺値をムーブする必要ないかと...
右辺値ならそのままでよいかと思いまふ
Re: PAD/キーボード入力によるボタンの実装
> Builder を利用しているのはなぜなのでしょうか?
完全に気分です.
(1)「ButtonContainer 自身にAddしていく形」だと,「中途半端な(データが全部揃ってない)状態の ButtonContainer が存在するタイミング」があるのがなんか嫌な気がした.
(まじめにやるなら,各Add後の状態が常に大丈夫な形になるように実装せねばならない←面倒)
(2)「全てを揃えてから BottonContainer のコンストラクタに入れる」という形だと,コンストラクタが要求する形のでかいデータを作る必要が出てきて,これもなんか嫌だなぁ,と.(→Add みたくやりたい)
・IDが自動連番ではないのは,こういうのは外部ファイルとかを読んで作ることになるかなぁ,とか思ったので.
(勝手に連番が振られるルールだと,ファイルから1項目削ったら以降に書いてあるID値を全部直す必要が…とかそういうのを勝手に想像)
---
> 右辺値ならそのままでよいかと思いまふ
これは Thx.
メンバ初期化子のところが m_Data( Data ) でおk,ということですか.
完全に気分です.
(1)「ButtonContainer 自身にAddしていく形」だと,「中途半端な(データが全部揃ってない)状態の ButtonContainer が存在するタイミング」があるのがなんか嫌な気がした.
(まじめにやるなら,各Add後の状態が常に大丈夫な形になるように実装せねばならない←面倒)
(2)「全てを揃えてから BottonContainer のコンストラクタに入れる」という形だと,コンストラクタが要求する形のでかいデータを作る必要が出てきて,これもなんか嫌だなぁ,と.(→Add みたくやりたい)
・IDが自動連番ではないのは,こういうのは外部ファイルとかを読んで作ることになるかなぁ,とか思ったので.
(勝手に連番が振られるルールだと,ファイルから1項目削ったら以降に書いてあるID値を全部直す必要が…とかそういうのを勝手に想像)
---
> 右辺値ならそのままでよいかと思いまふ
これは Thx.
メンバ初期化子のところが m_Data( Data ) でおk,ということですか.
Re: PAD/キーボード入力によるボタンの実装
※言うまでもないけど,私のコードは完全に固定配置なボタン群のみを想定している.
ボタンが途中で増えたり減ったりとか,場所が動いて配置関係(:フォーカス的な意味での)が変わったりし得るのであれば,私の書いたやつじゃ全然ダメ.
ボタンが途中で増えたり減ったりとか,場所が動いて配置関係(:フォーカス的な意味での)が変わったりし得るのであれば,私の書いたやつじゃ全然ダメ.
Re: PAD/キーボード入力によるボタンの実装
> 中途半端な(データが全部揃ってない)状態の ButtonContainer が存在するタイミング
これは自分も嫌ですね。
しかもこれを解消しようとすると計算の処理が Add 毎に走って速度的にも嫌ですしね~
> 外部ファイルとかを読んで作ることになるかなぁ
なるほど確かに普通ならそうしますよね~
自分はめんどくさいので全部コードで書こうかと思ってたんですけどまた悩むなぁ...
> メンバ初期化子のところが m_Data( Data ) でおk,ということですか.
はい。私の知る限りですが。
ただ、std::move は右辺値に変えるだけなので引数に右辺値を渡しても実際に出力されるバイナリに差はなさそうですけどね(最適化があればなおさら)
これは自分も嫌ですね。
しかもこれを解消しようとすると計算の処理が Add 毎に走って速度的にも嫌ですしね~
> 外部ファイルとかを読んで作ることになるかなぁ
なるほど確かに普通ならそうしますよね~
自分はめんどくさいので全部コードで書こうかと思ってたんですけどまた悩むなぁ...
> メンバ初期化子のところが m_Data( Data ) でおk,ということですか.
はい。私の知る限りですが。
ただ、std::move は右辺値に変えるだけなので引数に右辺値を渡しても実際に出力されるバイナリに差はなさそうですけどね(最適化があればなおさら)
Re: PAD/キーボード入力によるボタンの実装
すみません。訂正です。
Data は右辺値なので std::move に渡しても右辺値になるだけで変わらないので std::move は要らないと書きましたが、気になったのでテストしてみたところ、やはり要りそうでした。
また、調べたところ、右辺値参照・ムーブセマンティクス - cpprefjp C++日本語リファレンスにて太字で
すみませんでした。
Data は右辺値なので std::move に渡しても右辺値になるだけで変わらないので std::move は要らないと書きましたが、気になったのでテストしてみたところ、やはり要りそうでした。
また、調べたところ、右辺値参照・ムーブセマンティクス - cpprefjp C++日本語リファレンスにて太字で
と書かれていました...右辺値参照であるということと、右辺値であるということは全く違うことである。
すみませんでした。
#include <utility>
#include <iostream>
class Hoge {
public:
Hoge() = default;
Hoge(const Hoge&) {
std::cout << "copy" << std::endl;
}
Hoge(Hoge &&) {
std::cout << "move" << std::endl;
}
};
Hoge GetHoge() {
return Hoge();
}
int main() {
Hoge && rval = GetHoge();
// Hoge a2(std::move(rval)); // output: move
Hoge a2(rval); // output: copy
}
Re: PAD/キーボード入力によるボタンの実装
ちょうどこちらでもそういう感じのを書いて確認作業みたいなことをしていたので大丈夫です.
メンバ初期化子ならそのまま && が伝播する感じで(?)いけたりするのかな? とか実験してみましたが,やはり move 必要っぽいですね.
質問内容とは無関係な事柄ですが,質問内でのやりとりがきっかけとなってこういうあやふやなところが明確になる機会が得られているので,ありがたいことです.
メンバ初期化子ならそのまま && が伝播する感じで(?)いけたりするのかな? とか実験してみましたが,やはり move 必要っぽいですね.
質問内容とは無関係な事柄ですが,質問内でのやりとりがきっかけとなってこういうあやふやなところが明確になる機会が得られているので,ありがたいことです.