紬ちゃんマスコット 〜Linux / Gtkmm編〜
前回がこちら
その後DxLib + なんちゃってWinAPIでゴリ押したところで終わりました。
今回はGTKのエラーを解消して制作を進めていきたいと思います(願望)
エラーの壁
前回詰んだエラーがこちら
g++ -o mascot_tsumugi main.cxx `pkg-config gtkmm-3.0 --cflags --libs` main.cxx:6:16: error: ‘GC’ is not a member of ‘Gdk’ Glib::RefPtr< Gdk::GC > m_gc; ^ main.cxx:6:16: error: ‘GC’ is not a member of ‘Gdk’ main.cxx:6:24: error: template argument 1 is invalid Glib::RefPtr< Gdk::GC > m_gc; ^ main.cxx: In member function ‘virtual void MyDrawArea::on_realize()’: main.cxx:32:14: error: ‘Gdk::GC’ has not been declared m_gc = Gdk::GC::create( get_window() ); ^ main.cxx: In member function ‘virtual bool MyDrawArea::on_expose_event(GdkEventExpose*)’: main.cxx:40:16: error: ‘class Gdk::Window’ has no member named ‘draw_pixbuf’ get_window()->draw_pixbuf( ^ main.cxx:42:19: error: ‘RGB_DITHER_NONE’ is not a member of ‘Gdk’ width, height, Gdk::RGB_DITHER_NONE, 0, 0 ); ^ make: *** [mascot_tsumugi] エラー 1
確認していきましょう。
まずオプションでつけた`gtk-config gtkmm-3.0 --cflags --libs`。
そのままbashで実行すると色々出てきました。どうやら勝手に探してきてくれるような感じです。
この中からgrepでGdkを探すと6つほどヒットしました。
多分問題ないと思います。
エラーはすべてGdkクラス絡みっぽい。
よくわからんのでまたteratailに投げました。
回答お待ちしております(宣伝
解決
gtkmm-3.0を2.4にすると通りました。
Gtkmm-3.0は互換性ないっぽいですね。消しとこ。
これでやっと先に奨める。
いざ実行。
天使がいない pic.twitter.com/JSElwaXdV6
— 友利奈緒::name(”てまー”); (@toshihito_IT) February 5, 2016
いない。
と思ってたら
リアルに「おぅっ」って声だした pic.twitter.com/awqqcM7dLO
— 友利奈緒::name(”てまー”); (@toshihito_IT) February 5, 2016
いました。
ウィンドウが小さくて見えなかっただけでした。天使。
ウィンドウの透明化
さて写経プログラミングなのであんまり理解できてないけどウィンドウ透明化しよう。
調べた結果、Gtk::Window::set_opacityで不透明度を設定できるらしい。
早速設定。
違う、そうじゃない pic.twitter.com/xtHV6nLXmV
— 友利奈緒::name(”てまー”); (@toshihito_IT) February 5, 2016
なんか寧々√思い出してすこし悲しくなりました。
どうやらウィンドウごと透明にするのはNG。
考えてみたらウィンドウ透明にしてもタイトルバーの判定は残ってるし、透明部分クリックしたらマスコットがアクティブになりますしね。
非短形非矩形ウィンドウ
それであれか、非短形ウィンドウが出るのか。
— 友利奈緒::name(”てまー”); (@toshihito_IT) February 5, 2016
なんかgtkmmの非短形ウィンドウ作れる関数っぽいのが3.0からなんですが
— 友利奈緒::name(”てまー”); (@toshihito_IT) February 5, 2016
こんなこと言ってると
非短形じゃなくて非矩形ね
— けんつ (@RabbitFoot141) February 5, 2016
くけー
— 白沢さん家のノエルちゃん (@shirakami_erg) February 5, 2016
訂正を頂いた。
クケーッ
— Aruneko@2/9~12は東京 (@aruneko99) February 5, 2016
くけー
— 瀬野@ガルパンは良いぞおじいさん (@K26_PTFE) February 5, 2016
TLにイャンクックが大量に発生するろいう事案。
— 白沢さん家のノエルちゃん (@shirakami_erg) February 5, 2016
そしてこれ。
反省してます。本当に。
ひくけい。
でも間違える人多いみたいですね。
矩形を短形と書くと殺されるので気を付けような…(*бωб)
— 獏(ばく) (@baku_dreameater) February 5, 2016
とのこと。
死体蹴り
くけー
— nasa9084@某某某某(0x16歳) (@nasa9084) February 5, 2016
@toshihito_IT くけーっ
— Gunzi@猫侮辱罪 (@hebereke2920083) February 6, 2016
@toshihito_IT くけーくけーくけー
— puts”友利奈緒#{Nakasan}” (@chikuwa_macman) February 6, 2016
気を取り直して。
透明部分が邪魔なら非矩形ウィンドウにすればいいじゃない。
DxLib版もあれ非矩形ウィンドウなんだなぁ…簡単に作れるので実感沸かなかった。
とりあえずGtkmmで非矩形ウィンドウを作る方法を探します。
が、ない。
見当たらない。
仕方がない、自分で探します。
バージョンの壁
まず非矩形ウィンドウってどうやって作るんだ!?ってなります。
octworks.orz.hm
WinAPIですが、きっと仕組みは同じ。
画像データからリージョン(領域)データを作成
↓
リージョンデータを元にウィンドウ成形
こんな流れ。
ならばこれらをやってくれるメソッドをgtkmmから探せば良い。
gtkmm: Gtk::Widget Class Reference
英語リファレンス。僕の天敵。
まぁ中国語資料よりマシですので頑張ります。
shapeで検索したところ
void Gtk::Widget::shape_combine_region ( const ::Cairo::RefPtr< const ::Cairo::Region > & region )
なんてメソッドがありました。これかな?
何とか行けそうと思ってましたがその下
since gtkmm 3.0;
うん。エラー出たバージョンですね。
ついでにCairoクラスとか新しい名前も出始めました。
調べてやるしかないですね。
@toshihito_IT https://t.co/H9POyvJDxH
— NaMACHAN (@namachan10777) February 5, 2016
このようなMLの記録があります。ご参考になれば
なんと情報提供。びっくり。
感謝です。
そろそろ本気出す
僕に残された道は2つ
1, gtkmm-2.4で非矩形ウィンドウを作る
なんかできるらしいんですが、詳しいやり方が出てこないので非常につらみ。
2, gtkmm-3.0を使えるようにする
こっちのほうが現実的かな。そうすればNaMACHANさんから頂いた情報もきっと使えるし。
というわけでgtkmm-3.0を使って頑張っていく方向で行きます。
さてあのエラーと向き合わなければいけないのですが
そもそもエラー出してるGdk::GCってなんぞや?と。
調べてみたらGLContextの略っぽいですね。ただ公式リファレンス漁ってもよくわかりませんでした。
Gtk+3.0について調べているうちにグラフィック関連がCairoに!(ガバガバ意訳)みたいな情報に辿り着いた。
ほう、ならばCairoだ。
ファイルから画像を読み込んで表示(cairomm編)
Cairo編も載せてくれてました。感謝。
写経してmake。
通る。
しかし紬は顔を出してくれない。
試しにgtkmm-2.4でmake。
紬が出る。
またか。
これはもう本格的に一からgtkmm-3.0を勉強する必要がありそうだ。
やってやろう。
勉強用に選んだサイトがこちら
Programming with gtkmm 3
公式講座(もちろん英語)。
正直つらいけど頑張ります。
しょっぱなからautoがエラー吐いて詰みそうになったけど頑張ります。
(autoはC++11からなので -std=c++11 をつけたら通った)
全ては紬のため。
だからこそ紬のこの優しい微笑み+すこし頬染めてるこれが天使なわけで、この微笑みを見るだけで僕はまた明日も頑張ろうって思えるんだ。 pic.twitter.com/w8eAkgYBRt
— 友利奈緒::name(”てまー”); (@toshihito_IT) February 5, 2016
ようやくスタートライン
— 友利奈緒::name(”てまー”); (@toshihito_IT) February 6, 2016
心温まるミスを経て
やりました pic.twitter.com/x1rfTN9yI2
— 友利奈緒::name(”てまー”); (@toshihito_IT) February 6, 2016
ついにgtkmm-3.0のサンプルソースが動きました()
ようやくサンプル動くとかクソザコ過ぎィ!
写経元はこちら
Drawing Images
ここからようやく非矩形ウィンドウ化です。
そこでNaMACHANさんに教えていただいたリンク先を参考にしていきます。
#if GTK_CHECK_VERSION(2,91,0) GdkPixbuf *pixbuf = NULL; GdkPixbufAnimation *anime = NULL; switch(gtk_image_get_storage_type(GTK_IMAGE(image))) { case GTK_IMAGE_PIXBUF: pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image)); break; case GTK_IMAGE_ANIMATION: anime = gtk_image_get_animation(GTK_IMAGE(image)); pixbuf = gdk_pixbuf_animation_get_static_image(anime); break; default: break; } cairo_surface_t *img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); cairo_t *cr = cairo_create(img); gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); cairo_paint(cr); cairo_region_t *mask = gdk_cairo_region_create_from_surface(img); gtk_widget_shape_combine_region(gwin_message, mask); cairo_region_destroy(mask); cairo_destroy(cr); cairo_surface_destroy(img); #else GdkBitmap *bitmap = NULL; gdk_pixbuf_render_pixmap_and_mask(gdk_pixbuf_new_from_file(icon, NULL), NULL, &bitmap, 128); gtk_widget_shape_combine_mask(gwin_message, bitmap, 0, 0); #endif
こんなソースがあった。
GTK+(C言語向けラッパー)なのでこのままでは使えない。
まずは何やってるのか推測します。
#if GTK_CHECK_VERSION(2,91,0) GdkPixbuf *pixbuf = NULL; //バッファ GdkPixbufAnimation *anime = NULL; //アニメーション?多分関係ない switch(gtk_image_get_storage_type(GTK_IMAGE(image))) { //多分関係ない case GTK_IMAGE_PIXBUF: //きっとここ pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image)); break; case GTK_IMAGE_ANIMATION: //多分これは違う anime = gtk_image_get_animation(GTK_IMAGE(image)); pixbuf = gdk_pixbuf_animation_get_static_image(anime); break; default: break; } cairo_surface_t *img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); //表面どうのこうの cairo_t *cr = cairo_create(img); //作る gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); //画像セットかな cairo_paint(cr); //描画 cairo_region_t *mask = gdk_cairo_region_create_from_surface(img); //多分非矩形ウィンドウの形とってる gtk_widget_shape_combine_region(gwin_message, mask); //非矩形ウィンドウ作成かな cairo_region_destroy(mask); //さっき取った非矩形ウィンドウの形データ消す cairo_destroy(cr); //えっ これも消すの cairo_surface_destroy(img); //描画したら使ったもの全部消すらしい。 #else //GTK+3.0使えるのでこれ以降は関係なし? GdkBitmap *bitmap = NULL; gdk_pixbuf_render_pixmap_and_mask(gdk_pixbuf_new_from_file(icon, NULL), NULL, &bitmap, 128); gtk_widget_shape_combine_mask(gwin_message, bitmap, 0, 0); #endif
こんな感じに。
さらにメインの処理っぽいのを抜き出します。
GdkPixbuf *pixbuf = NULL; //バッファ pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image)); //読み出し cairo_surface_t *img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); //表面どうのこうの cairo_t *cr = cairo_create(img); //作る gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); //画像セットかな cairo_paint(cr); //描画 cairo_region_t *mask = gdk_cairo_region_create_from_surface(img); //多分非矩形ウィンドウの形とってる gtk_widget_shape_combine_region(gwin_message, mask); //非矩形ウィンドウ作成かな cairo_region_destroy(mask); //さっき取った非矩形ウィンドウの形データ消す cairo_destroy(cr); //えっ これも消すの cairo_surface_destroy(img); //描画したら使ったもの全部消すらしい。
そんな難しいことはしていないけど、対応したクラスとメソッドを探しだすのめんどい…
紬のためなので頑張ります。
紬不足による疲労感
1日半くらいgtkmmの公式リファレンスを漁ったが、一向に理解できる気配がない。@toshihito_IT gdk_cairo_region_create_from_surface
— NaMACHAN (@namachan10777) 2016, 2月 7
って言う関数がありますよ
たまに情報飛んできます。とてもありがたい。
今更ながら「___::RefPtr< "クラス名" >」ってなんだろ…と思っておりました。
猫C++をクラス付近で投げ出したため理解してませんでした。
改めてテンプレートクラスの章をよんでやっとこさ理解。
Gtk、Cairoを中心に調べてましたが、Glib::RefPtrが多用されてるのでGlibも調べてみます。
というか最初から猫C++読みながらやるべきだった…
流石に長くなりすぎたので次エントリにします。