tekuto.net

メール:g.tekuto@gmail.com

twitter


2019/02/02 03:00

fg::StateEnterEventとfg::StateLeaveEventの仕様を変更することにした。

今までこれらのイベントは、fg::Stateをプッシュした時やポップした時に発生していた。

プッシュ時には、まず元のfg::Stateについてのfg::StateLeaveEventが発生する。

次にプッシュしたfg::Stateについてのfg::StatePushEvent。

最後にプッシュしたfg::Stateについてのfg::StateEnterEvent、という順だ。

ポップ時には元ステートについてのLeaveEvent、PopEvent、ポップ後のステートについてのEnterEvent、という順に発生する。

この仕様を変更して、プッシュ時におけるEnterEventと、ポップ時におけるLeaveEventを発生しないようにしようと思う。

1つのイベントが複数異なる状況で発生することで、扱いにくくなっているように思うのだ。

現在の仕様では、ポップ時に発生するEnterEventは処理したいけど、プッシュ時に発生するEnterEventは無視する、といったことができない。

そもそも、プッシュ時のEnterEventや、ポップ時のLeaveEventなんて無くても問題ないのだ。

プッシュ時はPushEvent、ポップ時はPopEventで代用できる。

なぜ無駄なものが付いていたのかと言えば、EnterEventとLeaveEventでリソース管理を手軽にしようとしてた、というのが主目的だった気がする。

EnterEventでリソースの確保、LeaveEventでリソースの解放を行うようにすれば、ステートが有効になるタイミングでリソースが確保され、またステートが無効になるタイミングでリソースが解放される。

しかし、そのようなやり方は少々安直すぎたように思える。

そのステートがプッシュされて有効になった、という状況と他のステートがポップされてステートが有効になった、という状況を完全に同一に捉えてしまうのはどうかと思う。

実装するにしたって、その2つの状況で同じ処理をさせる場合、処理を関数化しておいて各状況から同じ関数を呼び出す、という形にするべきだろう。

というわけで、EnterEventはポップ時、LeaveEventはプッシュ時にしか発生しないようにする。

そのような挙動の都合上、EnterEventについては名前も変えて、ReenterEventにしようと思う。

それとは直接関係ないんだけど、ReenterEventで直前のステートを特定できるデータを取得できるようにしようと思う。

ステートの管理はスタック構造により、あるステートに遷移した後元のステートに戻る、という関数のような、縦のつながりとでも呼べばいいのか、そのような挙動は表現できるようになっている。

問題は、あるステートから別のステートに遷移する、というGOTOのような挙動の表現だ。

現状絶対に表現できない、というわけではない。

あるステートをポップし、直後に別のステートをプッシュしてやればいい。

問題はそれをどこでやるのか、ということだ。

ステート内に、別のステートへの遷移処理を記述してしまうのはまずい。

ステートの遷移が1回に留まらず、何度も遷移を行なうような構成の場合、あちこちに遷移処理が書かれることになりとても把握できなくなってしまう。

まさにGOTOの濫用によるスパゲッティコード状態になってしまうことだろう。

そこで考えたのは、管理ステートという概念だ。

管理ステート自体は画面の描画やコントローラの入力などの処理は行なわない。

管理ステートは、別のステートへの遷移のみを行う。

管理ステートがプッシュされたら、管理ステートのPushEventでステート1に遷移する。

ステート1の処理が終了し、ポップされたら管理ステートのReenterEventでステート2に遷移する。

ステート2が終了したら次はステート3に、といった具合だ。

この構造なら、遷移処理は管理ステートに集約される。

で、このような構造を実現する場合、ReenterEventでは直前のステートを特定できないといけないわけだ。

ステートに対応する列挙型を用意し、それを管理ステートに持たせて現在のステートの把握に使う、という手もあるだろうけどどう考えてもバグの温床になるし。

他にもっといい方法があればいいのだが、思い付かないものは仕方がない。


2019/01/31 15:10

記事を年単位で分割した。

編集はvimでやってるけど、開くのに時間かかるのがいやだったので。

前は月単位で分けてたけど、正直そんな頻繁に分割作業したくないので年単位にした。

skiaに対応するために、OpenGLコンテキスト周りを修正した。

skiaではステンシルバッファが必要だそうだが、現状ではステンシルバッファのサイズが0でサイズ指定もできなかったので、その辺のパラメータを設定できるようにした。

また、skiaで生成した画像をテクスチャとして扱う、みたいなことをするにはskia用のコンテキストは別に用意した方がよさそうだが、その場合コンテキスト間でリソースを共有できた方がいい。

なので、コンテキスト間のリソース共有もできるようにした。

これでkasuteraの作り直しに入れるかな。


2019/01/26 03:10

skiaを使った簡単な描画処理は書けた。

最初の生成処理はあれでいいのか不安だが、ヘッダファイルを見ても他の関数は見当たらないし、多分いいのだろう。

書いてみた感じからすると、fgインターフェースにskia用の関数を追加するとか、そういうものは必要なさそうだ。

バックエンドにOpenGLを使用する場合の関連付けも、カレントコンテキストに対してのみ行なわれるため、fg::GLContextに対して直接なにかしたり、といった処理は必要ない。

skiaをモジュールとして扱うために、設定ファイルを追加すれば問題なく扱えそう。


2019/01/25 14:55

例の仕様変更については対応済み。

テストについても、初期化関数を比較することで目的の画面に遷移していることを確認できるようになった。

で、kasuteraを作り直そうと思ってるけど、その前にグラフィックライブラリを導入することにした。

画面に表示する画像を用意するのが面倒なのだ。

1つや2つで済むならいいけど、これから画面作るたびにその画面を画像を描かないといけない、というのは面倒で気が滅入る。

なので、フォントファイルを参照して文字を描画したりなどできるライブラリを導入することにした。

適当に検索かけて、まず見つけたのはcairo。

このマシンにも導入されていて、ウィンドウマネージャのawesomeやwebブラウザのfirefox、chromeなどから使われているようだ。

既に導入されているというのは手が出しやすくていい。

更に調べていくと、skiaとかいうのも見つけた。

androidやchromeの描画に使われているらしい。

chromeはcairoにも依存してるんだけど、使うライブラリを切り替えたりできるんだろうか。

chromeだけでなくfirefoxでも使われているようだ。

cairoとはなんだったのか。

ともかく2つのライブラリが見つかった。

skiaの方が高速だの、有名なソフトウェアで使われててフィードバックが多いから開発が進んでるだのとskiaを評価する声が多いように思えるので、とりあえずskiaを使ってみようと思う。

思ったのはいいのだが、skiaのサンプルコードがあまりネットに落ちてない。

必死に色々調べた結果、skiaのリポジトリ内に参考になりそうなソースファイルがあった。

それを見ながら、実際に動作するコードを自分で書いてみるとしよう。


2019/01/21 16:10

ちょっと詰まってる。

画面遷移についてのテストの記述が直接的でなく、私はとても不満げだ。

現状、特定の画面に遷移したかどうかのテストは、その画面で行なわれるべき動作が行なわれるか、という反応を見ている。

その画面に遷移したなら、コントローラをこのように操作することでこういう結果になるはずだ、ということだ。

はっきり言って回りくどく、非常に分かりづらい。

テストコードがテスト可能になるまで、必要な記述も多すぎる。

前述のようにコントローラ操作をテストに含めようとすると、その下準備もテストに記述する必要があるからだ。

しかも、下準備を書いてなくても動作自体はしてしまう。

動作するが、テストが成功することはない。

実装が間違っているのか、テストの記述を間違えているのか見分けがつかず、とても不安になってしまう。

これはとてもよくない。

画面におけるコントローラ操作のテストであれば、下準備をする必要があるのでまだ分かるが、なぜ単なる画面遷移のテストでそれらをしなくてはいけないのか。

大体、コントローラ操作が行なわれない画面だったら、この方法ではテストできなくなってしまう。

長々と書いたが、要するにそのfg::Stateがなんの画面のfg::Stateなのか、特定する方法が存在していないのはまずい。

fg::Stateに、画面を特定するためのデータを持たせる必要がある。

テストのためだけに余計な情報を持たせる、ということはしたくないが、テスト以外でも有効に活用できそうな気はする。

イベント中から画面特定データにアクセスできるようにすれば、1つのイベント関数を複数の画面で使い回し、画面ごとに処理を多少変える、といったことができるようになるだろう。

そういった処理は複雑化の元だからあんまりやりたくないけど。

で、問題は画面特定データとして何を持たせるか、だけど、fg::Stateの初期化関数のアドレスを持たせようかな、と。

現状扱ってるデータで考えるとそれが妥当、というかそれしかない。

fg::Stateに文字列で名前を付けるとかIDを振るとかも考えられるけど、扱いきれなくなって後悔する予感しかしない。

というわけでそんな感じの修正をして、テストも修正しよう。

いやむしろ、kasuteraについては作り直した方がいいかもしれない。

kasuteraは最初テストができず、テストをできるようにするためにbrownsugarを追加し、新たに追加した画面についてはテストができている。

まだあまり量書いてないし、未テスト部分にもbrownsugarを使ったテストコードを追加しようとしているけど、テストができなかった影響か構成がだめなのだ。

なんとなくでコードを書いてしまい、処理は一応まともに動いているようだが関数の引数などのインターフェースが悪い。

簡単に言えば扱いにくい、テストがしにくい。

それを修正してまともな形にすることもできるだろうけど、いっそ最初からテストファーストでまともなものを作った方がよさそう。

まだあまり量書いてないわけだし。


過去ログ

2018

2017

2016

2015

2014

2013