¶詳細は調べてみよう!
¶自宅の書籍を全部電子化してiPadにつっこんで終わりにしたい!!!
¶あとバックアップも兼ねてNASも欲しい!!!
¶土日に遊びほうけてたので、いまいち今日は仕事に集中しきれなかった。
¶仕事一直線になるつもりもさらさらないけれども、さりとてゴロゴロ遊んでいるのも有意義な行動でもないし、今後は土日に呆け過ぎないようにしよう。
¶夕食に豚肉と白菜のミルフィーユ鍋、明日の弁当用に豚カツを料理した。
¶家事した後はチマチマプログラミングした。本当自分には設計能力が無いと思う。クラス構成とか、どういう風に処理を分割するかとか、いっつも綺麗にできない。
¶いや、綺麗にできないどころか、後々の開発に最初の設計では苦しくなって頻繁に書き直す羽目になる。誰か僕に設計を教授して欲しい。
¶考えてみたら日記ってその日の夜に書くものな気がしてきた。朝書いてもその日のこと分からないし。
¶昨晩は大学サークルの後輩と先輩と飲んだ。楽しかった。
¶9:30くらいに起床。朝食にホットケーキと目玉焼きを作った。
¶スプラトゥーンを購入しようか悩んでいる。楽しそうだか、いかんせん同棲している彼女が多忙で休日にも遊ぶ余裕が無いのに、そばで僕がハシャいでたらイライラしそうなので、もう少し購入は見送るか……。
¶そもそも、ゲームはプロジェクターで遊んでいるので、どうしても表示遅延でアクション系のゲームはつらいのもある。
¶使い易いメーラーは世の中に存在してるのか?ってくらいどれもこれも使いにくい。
¶朝9:30くらい起床した。
¶vimperatorをまた使ってみてるが、入力が効かなかったか?と思って別のコマンドを入れると実は効いてて数秒後にドバッと動いてアアアってなることが多々あってつらい。キー入力処理とレンダリング部分で分離されてるブラウザでも作った方が良いかな……
¶vimperatorだとブラウザなので顕著だけど、この手のイライラはほとんどのソフトウェアで発生するのがつらい。良いCPUとか多くのメモリ積めば解決するのかなぁ
¶朝食はまだ食べてない。気がむいたら食べる。
¶Host github
User git
Hostname github.com
¶こう~/.ssh/config
に記述しておくと、Githubからのcloneをgit clone github:nyaocat/project
みたいに書ける。
¶ ベクトルベースかつアンチエイリアスが利くので、綺麗な描画が出来る。
¶基本的に、グラデーション・単色・画像から一部を切り出して描画することしか出来ない。なので、ボカシ効果などは無理
¶普通に1pxの線を書こうとしてもなんかぼける。いわゆるサブピクセル云々なアレ。 座標を0.5ズラして指定してやると綺麗に1ドットの線が引かれる。
¶まぁ、ベクトルベースなグラフィックライブラリでドット単位の表現をしたがるのが間違いといえばそうなのかもしれない。
¶APIがステートフルなので少々扱いにくい。gtkで別のウィジェットであってもcairoのcontextの状態が共有されてるのが面倒。
¶msys2のgtkmmパッケージとgtkmm3パッケージで確認。
¶要するに、-std=c++11
か-std=c++14
か-std=gnu++11
か-std=gnu++14
を付ける必要がある。
¶真面目にエラーメッセージを読んでないから原因は分からないが、どうも ABI が変わっちゃうからっぽい?
¶他人に見せれるように整えるのはかなり労力が掛かってしまう。
¶そこで力尽きるくらいなら、雑にガンガンやって形になってから整理したら良い。
¶どうせ形になってなけば、他人から興味もそうそう持たれない。
¶以下のようなコードをLinuxでg++ -std=c++14 a.cpp $(pkg-config sdl2 gtkmm-3.0 --cflags --lib)
とコンパイルすれば動く。
¶Mac, Windows上でも色々修正すれば多分動く。
¶#include <type_traits>
#include <sigc++/sigc++.h>
#include <iostream>
#include <cmath>
#include <gtkmm.h>
#include <gtkmm/socket.h>
#include <iostream>
#include <cmath>
#include <SDL.h>
#include <X11/Xlib.h>
namespace sigc
{
template <typename Functor>
struct functor_trait<Functor, false>
{
typedef decltype (::sigc::mem_fun (std::declval<Functor&> (),
&Functor::operator())) _intermediate;
typedef typename _intermediate::result_type result_type;
typedef Functor functor_type;
};
}
double spd = 0.05;
int sdl_init(::Window windowid);
bool sdl_loop();
void on_button() { std::cout << "Button" << std::endl; spd += 0.02; }
int main(int argc, char **argv) {
Gtk::Main kit(argc, argv);
Gtk::Window main_window;
Gtk::VBox *vbox = manage(new Gtk::VBox());
Gtk::Socket *sock = manage(new Gtk::Socket());
sock->set_size_request(400, 300);
vbox->pack_start(*sock, true, true);
auto spin = manage(new Gtk::SpinButton(0.01, 3));
spin->set_range( 0.0, 100.0);
spin->set_increments( 0.01, 0.1);
spin->signal_value_changed().connect([=](){
spd = spin->get_value();
});
vbox->pack_start(*spin, true, true);
main_window.add(*vbox);
main_window.show_all();
Glib::signal_timeout().connect([&]() -> bool {
std::cout << "Window ID: " << sock->get_id() << std::endl;
sdl_init(sock->get_id());
std::cout << "inited!\n";
Glib::signal_timeout().connect(&sdl_loop, 16);
return false;
}, 200);
Gtk::Main::run(main_window);
return 0;
}
SDL_Window* window;
SDL_Renderer* render;
int sdl_init(::Window windowid) {
if (SDL_VideoInit(NULL) < 0) {
std::cerr << "Couldn't initialize SDL video: " << SDL_GetError()
<< std::endl;
exit(1);
}
window = SDL_CreateWindowFrom((void *)windowid);
if (!window) {
std::cerr << "Couldn't create SDL window: " << SDL_GetError() << std::endl;
exit(1);
}
render = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
if (!render) {
std::cerr << "Couldn't create renderer: " << SDL_GetError() << std::endl;
exit(1);
}
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
SDL_SetRenderDrawColor(render, 0xA0, 0xA0, 0xA0, 0xFF);
SDL_RenderClear(render);
return 0;
}
bool sdl_loop() {
int const center_x = 200;
int const center_y = 150;
int const radius = 100;
static double rotate = 0.0;
SDL_Event ev;
while (SDL_PollEvent(&ev)) {
if (ev.type == SDL_QUIT)
return false;
}
SDL_SetRenderDrawColor(render, 0, 0, 0, 255);
SDL_RenderClear(render);
SDL_SetRenderDrawColor(render, 255, 0, 0, 255);
rotate += spd;
SDL_RenderDrawLine(render, center_x + radius * std::cos(rotate),
center_y + radius * std::sin(rotate),
center_x - radius * std::cos(rotate),
center_y - radius * std::sin(rotate));
SDL_RenderPresent(render);
//SDL_Delay(12);
return true;
}
¶描画はSDL2で行い、そこにgtkmmでGUI部品を付けている。
¶ゲーム作る時にデバッグ用フォームをこれで出したりとかに良さそうだ。
¶もちろん、それ目的ならば何かゲームエンジンを使った方が良いが、僕はチマチマ車輪の再実装するのが好きなのだ。
¶口を開く前に1秒考える
¶If the source type is bool, the value false is converted to zero and the value true is converted to one. [conv.integral]
A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. [conv.bool]
¶つまり、bool
から整数型への変換の際、false
は0
に、true
は1
になる。
¶整数型・ポインタ・メンバポインタからbool
への変換の際、0
とヌルポインタはfalse
に、他の値はtrue
になる。
¶ふと気になって調べた。
¶io.tmpfileを使うと、一時ファイルへのハンドルが得られる。このファイルはプログラム終了時に自動的に削除される。
¶実は今までこれの使い道が分かってなかった。書きこみしても、ファイルハンドルからはファイル名は得られないし、どう利用するのか?
¶と思ってたが、書いた後に:seek("set", 0)
することで読みこめる事を知った。
¶$ lua
Lua 5.3.2 Copyright (C) 1994-2015 Lua.org, PUC-Rio
> f = io.tmpfile()
> f:write("happy new year")
file (0x800ffb840)
> f:seek("set", 0)
0
> f:read("a")
happy new year
¶メモリに載りきらない大きさのデータをあつかう時に良さそうだ。
¶ひとまず、今作成しているLua用cgiモジュールで、アップロードされたファイルを受けるのに使おう。
¶./configure LUA='lua' LUA_INCLUDE='-I/home/nyaocat/local/include' --prefix='/home/nyaocat/local/lib/luarocks/rocks/luaposix/33.3.1-1' --libdir='/home/nyaocat/local/lib/luarocks/rocks/luaposix/33.3.1-1/lib' --datadir='/home/nyaocat/local/lib/luarocks/rocks/luaposix/33.3.1-1/lua' --datarootdir='/home/nyaocat/local/lib/luarocks/rocks/luaposix/33.3.1-1' && make clean all
./configure: パーミッションが拒絶されました
Error: Build error: Failed building.
¶なんでやねーん
¶四元徳「知恵」を倒すところまでやった。
¶サビエンチアさんはメカメカしくてかっこいい。フォルティテュードに次いで好き。
¶メカメカしくて天使とは一体なんなんだ、という気もするが……どう見ても車な天使も居たし……。
¶昼はチャーハン。良い出来。
¶夜はハンバーグを作った。玉ねぎの量を二倍にしたら、柔らかくなりすぎてちょっと微妙だった。
¶カンマ区切りで記号を指定することで、複数指定できる。
¶$ ls -l aaaa
-rwxrwxrwx 1 nyaocat nyaocat 0 Jan 3 10:34 aaaa
$ chmod g-rw,o-x aaaa
$ ls -l aaaa
-rwx--xrw- 1 nyaocat nyaocat 0 Jan 3 10:34 aaaa
¶FreeBSDのman chmod
には載っているが、何故かGNUのman chmod
には載ってない。が、GNU chmodでも可能。
¶元旦に4時間で作ったものは流石に適当で。将来性が無さすぎるので作り直した。
¶今度は8時間くらいでできた。
¶Luaとbashスクリプトで作った。やはりこれらは速く書けて素晴らしい。
¶ついでに markdown で書けるようにしたので、コードもガンガン書けて使いやすくなった。
¶#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
}
¶LuaTwitというライブラリがあるが、FreeBSDでインストールできない。
¶LuaTwitが間接的に依存しているluaosslが、ビルドスクリプト中で libdl を要求するため。FreeBSDでは libc に libdl 相当の実装が入っているので、libdl が存在せずエラーになる。
¶一応、luaosslのGNUMakefile中にOSの判定処理書いてあるな……上手く働いてないようだが。
¶あ、luarocksで公開されてるrockspecの方で libraries の中に "dl" の記述がある……これが原因か?
¶とりあえず、luaosslのソースとrockspecをダウンロードして手元で上記の二箇所を削除して luarocks make する。よし、無事インストールできた。
¶luarocks make は公開レポジトリではなく手元のソースからビルド・インストールしてくれるコマンド。
¶それが済んだら luarocks install luatwit でインストール完了。長かった。
¶フォームよるファイルアップロードの仕様というページによると、複数ファイルのアップロードではmultipartが入れ子になる、と書いてあるのだが……
¶実際にchromeとfirefoxで試してみても、入れ子にならずに複数ファイルがmultipartで来る。何か変わったのか?
¶よく分からないが、入れ子の処理とか面倒すぎるし、実際入れ子にならないみたいだし、入れ子には対応しないで実装を続けよう。
¶ゲームしつつコード書きながら過ごせた元旦だったので、今年は幸先良い
¶formタグにenctype="multipart/form-data"とか指定すると、ファイルアップロードできるフォームになるんだけどこれをcgiから解析するのが非常に面倒くさい。
¶RFC2388に書いてあるのだけどboundaryがどうとか、urlencodeとmultipartの区別もどこまで読んだら判別できるのか、そもそも各パートの区切りを認識するのが面倒くさい
¶……と思ったら、CONTENT_TYPE環境変数に、application/x-www-form-urlencodedとかmultipart/form-dataとか入ってることを今知った。
¶しかも、multipartの場合はboundaryも続けて入ってる。これならデータ区切りも楽々だ。
¶2016年の目標は挫折しない年にすること。
¶去年は、いや去年に限らず今までずっと、やろうと思ったことを中途半端に手をつけてすぐ放置してた。いや別にそれが悪いとは思ってないんですが、それにしても金が絡まないと何もやらなさすぎるので、今年くらいは頑張ってみてみようかなと。
¶この日記エンジンも作ったのもその一環。
¶luaで書いた。コードはまだ公開しません。
¶とりあえず雑にガンガン書く用。
¶ある程度以上の長さになる文章は別のところで書く。