2013年10月18日

アクセント記号付きのアルファベット


とあるフリーの辞典ソフト向けに配られている外国語辞書データを調べていたんですが、そのテキスト形式のデータはSJIS と Latin-1 が混在していたので最初はすごく戸惑いました。テキストエディタをどう設定しても文字化けが解消されないぞと。というか Latin-1 なんてまったくなじみがないですよね。バイナリエディタで文字コード調べて、ようやく気がつきました。

見出し文字や例文などはアクセントやウムラウトつきのアルファベットに対応する為に Latin-1 コードで、日本語での解説部分は SJIS になっていたのです。というわけで、欧州言語の基本的な文字コードは Latin-1 です。覚えておくことにします。

イラっとしたので、例の辞書データは Python スクリプトで一括処理し、全部 UTF-8 に統一してやりました。すっきりです。あとは入力文章に出現した単語に対応する日本語説明文を並べて表示するだけで、簡易直訳ツールの出来上がりです。なんせ翻訳ツールによっては、下手に日本語らしい文章にしようと努力されるよりも、直訳で表示してくれた方がよほど分かりやすい場合がありますから…

posted by JUNOSOFT at 15:43| Comment(0) | プログラミング

2013年10月13日

プログラム用フォント

突然ですが、フォントの美しさというのは、開発意欲に少なからず影響を与えると思っています。
きたないフォントだとやる気もなくなりますからね。
ところがプログラムに使えるフォントとなると、それは自動的に固定ピッチフォントになるわけで、あまり数がないんですよね。
そのうえ日本語にも対応してないといけませんし。読みやすさも考えると結局 MSゴシック, Consolas, Lucida, ぐらいしか選択肢がありません。

そんなわけで、メイリオを固定ピッチ化したという救世主的なフォントの登場です。

http://jutememo.blogspot.jp/2013/03/windows-meiryoke-mactype.html

しかしこれ、自分の環境 WinXP+VC2008 では快適に使えてたのに、WinXP/Win7+VC2010 だと文字が表示されないという問題がありました。
さらに Win7 で使ってみようとしたらフォントがうまく生成されなかったという…. VC2012 ではそのへんどうなっているのでしょうか。
プログラマ向け日本語フォントは難しいですね。
posted by JUNOSOFT at 20:44| Comment(0) | プログラミング

2013年10月09日

頂点カラー

これまで頂点には D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 を使っていたのですが、
2Dゲームを作っていると、四角形ポリゴンの4頂点には全て同じ頂点カラーを適用することがほとんどです。
そうしないのはグラデーションを作りたいときぐらいですから。そうすると、頂点ごとに個別のカラー設定をしているのが無駄に思えてきます。
実際そのせいで1頂点に付き4バイトが消費されているわけで、わざわざ各頂点ごとにカラー情報をもたせる必要はないよな、
ということで D3DFVF_DIFFUSE を頂点定義から外し、D3DTSS_CONSTANT / D3DTA_CONSTANT で定数色を設定するようにしました。

ところが、これでつくったプログラムを配布したとところ、なんか表示がおかしいという報告がいくつもありました。
D3DTSS_CONSTANT が使えるかどうかを判別するには D3DPMISCCAPS_PERSTAGECONSTANT を使うのですが、
どうやら思った以上にサポートしていない環境が多いみたいです。

http://www.kludx.com/capability.php?capability=97

で、よくよく考えてみれば D3DTSS_CONSTANT はマルチテクスチャ用なわけで、
マルチテクスチャ使わないなら素直に D3DRS_TEXTUREFACTOR / D3DTA_TFACTOR を使っておけばよかったんですね。
一件落着。
posted by JUNOSOFT at 16:08| Comment(0) | プログラミング

2013年09月19日

Direct3DとOpenGLで頂点宣言を共有したい

Android 向けと Windows 向けのプログラムを書いているので、グラフィック関連のインターフェースはなるべく同じにしておいて、OpenGL と Direct3D のどちらを使っているのか意識しなくても大丈夫なようにしたかったのですが、なんせ OpenGL と Direct3D では流儀が異なるため、そのままではうまくいきません。

とはいえ、行列の Colmun major order と Row major order の違いは単に転置すればよいだけだし、右手系左手系なんかもスケーリング行列を挟むだけで違いは吸収できるし、楽勝じゃん!!とか思っていたのですが、ただひとつ、頂点の構造体をつくりたいときに、色設定が Direct3D では D3DCOLOR (32ビット符号無し整数)なのに対し、OpenGL が float*4 になっていることが悩みでした。

使い勝手を考えると、Direct3D 側で色設定が float*4 でできるようになるのが一番なのですが、D3DFVF 列挙にはそういった指定が見当たりません。


と思ってたら、D3DFVF なんて使わないで IDirect3DVertexDeclaration9 使えばよかっただけみたい…


そんなわけで、例えば頂点として

struct VERTEX {
 float x, y, z;
 float r, g, b, a;
 float u, v;
};

を使うなら、Direct3D 利用時には


void DrawTriangleStripDX(const VERTEX *vertexArray, int numVertices) {
 D3DVERTEXELEMENT9 elm[] = {
  {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
  {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
  {0, 28, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
  D3DDECL_END()
 };
 IDirect3DVertexDeclaration9 *decl;
 g_D3DDevice->CreateVertexDeclaration(elm, &decl);
 g_D3DDevice->SetVertexDeclaration(decl);
 decl->Release();
 g_D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, numVertices-2, vertexArray, sizeof(VERTEX)));
}

みたいに呼び出せばいいし、OpenGL 使用時には

void DrawTriangleStripGL(const VERTEX *vertexArray, int numVertices) {
 glEnableClientState(GL_VERTEX_ARRAY);
 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 glEnableClientState(GL_COLOR_ARRAY);
 glVertexPointer (3, GL_FLOAT, sizoef(VERTEX), ((const BYTE*)vertexArray) + 0);
 glColorPointer (4, GL_FLOAT, sizoef(VERTEX), ((const BYTE*)vertexArray) + 12);
 glTexCoordPointer(2, GL_FLOAT, sizoef(VERTEX), ((const BYTE*)vertexArray) + 28);
 glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices);
}

のようにすれば、同じ形式の頂点を OpenGL でも Direct3D でも使うことができる…と。
なんかすごく遠回りした気分。
posted by JUNOSOFT at 12:13| Comment(0) | プログラミング

2013年09月06日

ファイル名が欲しい5

今回は、ソート機能を追加してみようと思います


■ソートメニューを追加
・フォームを選択した状態で、「ソート(&S)」メニューを追加する


■パスを昇順(A→Z)でソートする
 配列をソートするには Array.Sort を使います

・「ソート(&S)」にサブメニュー「昇順(A→Z)」を追加
・private void 昇順AZToolStripMenuItem_Click(object sender, EventArgs e) {} というメソッドが追加されるので、
 そこに以下のコードを追加
 
  string[] lines = (string[])textBox1.Lines.Clone();
  Array.Sort(lines);
  textBox1.Lines = lines;
 

■パスを降順(Z→A)でソートする
 昇順ソート同じですが、最後にリストを逆順にします
 
・「ソート(&S)」にサブメニュー「降順(Z→A)」を追加
・private void 昇順AZToolStripMenuItem_Click(object sender, EventArgs e) {} というメソッドが追加されるので、
 そこに以下のコードを追加

  string[] lines = (string[])textBox1.Lines.Clone();
  Array.Sort(lines);
  Array.Reverse(lines);
  textBox1.Lines = lines;


■パスを拡張子順でソートする
 単純比較できない場合のソートには、比較用クラスを用意します
 
・「ソート(&S)」にサブメニュー「拡張子 昇順(A→Z)」を追加
・private void 拡張子順ToolStripMenuItem_Click(object sender, EventArgs e) {} というメソッドが追加されるので、
 そこに以下のコードを追加

  string[] lines = (string[])textBox1.Lines.Clone();
  Array.Sort(lines, new ExtComp());
  textBox1.Lines = lines;

・このままでは比較クラス ExtComp が存在せずコンパイルできないので、適当な場所に ExtComp クラスの定義を追加

  private class ExtComp : System.Collections.IComparer {
   public int Compare(object x, object y) {
    string ext1 = System.IO.Path.GetExtension((string)x);
    string ext2 = System.IO.Path.GetExtension((string)y);
    return String.Compare(ext1, ext2);
   }
  }

これで実行すると、たしかに拡張子順にソートされることが確認できます
posted by JUNOSOFT at 00:56| Comment(0) | プログラミング

2013年09月01日

始点1ピクセルが描画されない

ちょっと小ネタ

四角形のアウトラインを描画するときに、ラインを4本引いて四角形にしているのですが、
左上の1ピクセルが常に欠けているのがすごく気になってました。
以下のコードでいうと、ドットバイドットで描画したときに (x0, y0) の1ピクセルが必ず欠けます。
直線描画のときだけ欠けるので、ステンシルマスクやZバッファの問題ではなさそうです。

struct VERTEX {
 float x, y, z;
};
const VERTEX v[] = {
 {x0, y0, 0},
 {x1, y0, 0},
 {x1, y1, 0},
 {x0, y1, 0},
 {x0, y0, 0}};
device->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE);
device->DrawPrimitiveUP(D3DPT_LINESTRIP, 4, v, sizeof(VERTEX));

終点の1ピクセルが描画されないのであれば D3DRS_LASTPIXEL が FALSE になっているのかな、とも思うのですが、
なぜか終点ではなく始点です。というか、仮に始点が描画されない設定になっているなら4本目の終点としての x0, y0 が、
終点が描画されない設定になっているなら、1、2本目の始点としての x0, y0 が、始点終点両方とも描画されない設定になっているなら、
x0, y0 だけでなく4頂点すべてが描画されないはずです。謎です。

どうも納得がいかないのですが、結局太さ1ピクセルの超細長い長方形ポリゴンを描画して直線の代わりにしました。
拡大したときに直線の太さが1ピクセルでなくなってしまいますが、ドットバイドットが基本のゲームなのでそこは問題無しとします。釈然としませんが…
posted by JUNOSOFT at 11:42| Comment(0) | プログラミング

2013年08月19日

ファイル名が欲しい4

今回は、複数のファイル名に対する一括操作を追加してみようと思います


■一括操作用のメニューを追加
・フォームを選択した状態で、「一括操作(&O)」メニューを追加する


■ファイル名だけを抜き出す(ドライブ名、ディレクトリ名部分を削除する)
 ファイル名を取り出すには System.IO.Path.GetFileName を使います

・「一括操作(&D)」にサブメニュー「ファイル名を抽出」を追加
・private void ファイル名を抽出ToolStripMenuItem_Click(object sender, EventArgs e) {} というメソッドが追加されるので、
 そこに以下のコードを追加
  for (int i=0; i<textBox1.Lines.Length; i++) {
   textBox1.Lines[i] = System.IO.Path.GetFileName(textBox1.Lines[i]);
  }
 
 ところが、このコードだとコンパイルは通るものの、うまくいきません。
 Delphi だとこの方法を使って行単位で書き換えることができたのですが、どうやら C#(というより .NET Framework)での Lines プロパティは読み取り専用…というかただの配列のようです。
 というわけで、文字列配列を作成して一気に Lines プロパティに代入するように変更します

  string[] lines = (string[])textBox1.Lines.Clone();
  for (int i = 0; i<lines.Length; i++) {
   lines[i] = System.IO.Path.GetFileName(lines[i]);
  }
  textBox1.Lines = lines;

 あるいは単に、単一の文字列を生成してから Text プロパティに代入してもOKです。
 
  string text = "";
  for (int i=0; i<textBox1.Lines.Length; i++) {
   text += System.IO.Path.GetFileName(textBox1.Lines[i]) + System.Environment.NewLine;
  }
  textBox1.Text = text;


■拡張子を削除する
 拡張子の削除は System.IO.Path.ChangeExtension を使います
 
・「一括操作(&D)」にサブメニュー「拡張子を削除」を追加
・private void 拡張子を削除ToolStripMenuItem_Click(object sender, EventArgs e) {} というメソッドが追加されるので、
 そこに以下のコードを追加
 
  string[] lines = (string[])textBox1.Lines.Clone();
  for (int i = 0; i<lines.Length; i++) {
   lines[i] = System.IO.Path.ChangeExtension(lines[i], null);
  }
  textBox1.Lines = lines;

 Win32Api の PathRenameExtension ではピリオドを含む拡張子を対象としていましたが、System.IO.Path.ChangeExtension はピリオドを含まない部分を対称にするので気をつけましょう
 もし System.IO.Path.ChangeExtension("filename.ext", ""); としてしまうと、末尾にピリオドが残ってしまいます



次回はソート機能を追加します
posted by JUNOSOFT at 21:15| Comment(0) | プログラミング

2013年08月12日

ファイル名が欲しい3

前回作った雛形で、「ファイルをドロップしてファイルパスを得る」 という、最低限欲しかった機能がすでに付いているのですが、あまりにも使いづらいので、そのあたりを改善してみようと思います。

■長い行が勝手に折り返されてしまう
 ファイル名の一覧などは1行1項目が見やすいのですが、デフォルト状態だと長い行が右端で折り返されて見づらいため、まずはこの機能をOFFにします
 
 ・フォーム上に配置してあるテキストボックスを選択
 ・メニューから 表示→プロパティウィンドウ を選択してプロパティウィンドウを表示
 ・プロパティウィンドウの WordWrap を False に変更


■複数行表示したとき、文字の位置がガタガタになる
 ファイル名はピリオドなどの小さな記号を含んでいますし、似たようなパス名を持つであろうファイル名を複数表示するわけですから、縦方向(列方向)に文字の位置がそろっていたほうが何かと見やすくなります
 そんなわけで、デフォルトで設定されている可変ピッチフォント(プロポーショナルフォント」)はあまり良くありません。
 これを固定ピッチフォント(等幅フォント)に変えてみましょう。

 ・フォーム上に配置してあるテキストボックスを選択
 ・プロパティウィンドウの Font をクリック
 ・サブ項目が展開されるので、そこにある Name 項目の値を 「MS ゴシック」に変更
 ・この状態で実行(F5)し、フォントが変化していることを確認


■メニューを追加する
 これからさまざまな機能を追加するので、今のうちにメインメニューを追加しておこうと思います
 
 ・ツールボックス(無ければ表示→ツールボックスで表示)の「メニューとツールバー」にある MenuStrip をダブルクリック
 ・フォームに空っぽのメニューが追加されるので、「ここへ入力」と書いてある場所に 「ファイル(&F)」と入力(&Fは必ず半角にする。&記号を忘れずにつけておくこと)
  → & と F を並べて書いておくと F に下線がつき、Alt+Fを押すことでメニューが選べるようになる
 ・同じ要領で「ファイル(&F)」の下にサブメニュー「終了(&X)」を追加
 ・この状態で実行(F5)し、ウィンドウにメニューがちゃんとついていることを確認


■メニューを選択したときの動作を追加する
 いま追加したメニューは見た目だけで、選んでも何もおきません。というわけで、メニューが選択されたときの動作を追加します

 ・「ファイル(&F)」をクリック
 ・サブメニューが出るので、「終了(&X)」をダブルクリック。これにより 終了XToolStripMenuItem_Click のような名前のメソッドが追加される(メニューを追加したときに最初に入力した名前から記号を除いたものが、メソッド名の先頭に勝手に付く。今回は「終了(&x)」という名前を入力していたので、先頭に終了X])
 ・追加された 終了XToolStripMenuItem_Click メソッドの中に

  Close();

  という行を追加
 ・この状態で実行(F5)し、ファイル→終了メニューでウィンドウが閉じることを確認


■少しはマシになった?
ひとまず、これで土台が完成しました。最低限の機能と、最低限の見た目を備えています。
次からはファイル名に対する一括処理の機能を追加していくことにします。
posted by JUNOSOFT at 09:43| Comment(0) | プログラミング

2013年08月07日

ファイル名が欲しい2

とりあえず C# を使ってファイル名取得ツールの土台を一気に作ってみようと思います。
必要な手順だけを箇条書きにしたので、参考にしてみてください。


■プロジェクトの新規作成
・まず C# を起動
・「ファイル」→「新しいプロジェクト」→「Windowsフォームアプリケーション」を選択し、適当なプロジェクト名を入力して決定
・この状態で実行(F5)し、なにもないフォームが表示されることを確認


■テキストボックスを追加
・ツールボックス(表示→ツールボックス)から TextBox を選んでダブルクリックし、フォーム上に1行サイズのテキストボックスを配置
・配置されたテキストボックス上で右クリックし、メニューからプロパティを選択
・プロパティ一覧の MultiLine を True に変更(複数行の編集に対応させるため)
・プロパティ一覧の Dock を Client に変更(ウィンドウいっぱいの大きさにし、ウィンドウサイズの変更に対応させるため)
・この状態で実行(F5)し、テキストが自由に編集できることを確認


■ファイルのドラッグドロップを受け入れる
・フォームを選んだ状態でプロパティを出し、AllowDrop を True にする(ドロップ動作を許可するため)
・フォームを選んだ状態でプロパティを出し、雷マークのついたボタンをクリックし、イベント編集モードにする
・イベント一覧から DragDrop をダブルクリックしてイベントを追加。これにより Form1_DragDrop というメソッドが追加される
・追加された Form1_DragDrop メソッドに
  e.Effect = DragDropEffects.All;
 という行を追加

・フォームのイベント一覧から DragEnter をダブルクリック。これにより Form1_DragEnter というメソッドが追加される
・追加された Form1_DragEnter メソッドの中に
  if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
   foreach (string path in (string[])e.Data.GetData(DataFormats.FileDrop)) {
    textBox1.Text += path + System.Environment.NewLine;
   }
  }
 という行を追加
 
■確認
あっけないかもしれませんが、以上で基本形は出来上がりです。F5で実行し、適当なファイルをドラッグドロップしてみてください。もちろん複数ファイルにも対応しています。

次回、もう少し機能を追加していくことにします
posted by JUNOSOFT at 05:23| Comment(0) | プログラミング

2013年08月04日

ファイル名がほしい


プログラムをしていると、フォルダ内のファイル名一覧がテキスト形式で欲しくなる時があります。
もちろん、適当なフォルダをドロップするとファイル名一覧を作成してくれるツールはいくつかあるのですが、自分にとっては少し使いにくかったので、簡単なツールを作ってみることにしました。
ついでにその製作過程を載せておきます。

まず、欲しい機能は以下のとおり。

・見た目はメモ帳みたいにシンプルで、テキストを自由に編集できる
・そこにフォルダをドロップすると、フォルダ内の全てのファイル名がフルパスで追加される
・そこにファイルをドロップすると、そのファイル名がフルパスで追加される
・カーソル行のファイル(フォルダ名ならそれを、ファイル名ならその親フォルダを)エクスプローラで開くことができる
・カーソル行のファイルを OPEN できる
・以下の操作を、すべての行または選択された範囲内に対して一括で適用できる
  ファイル名だけを抽出(=パス部分を削除)
  拡張子を削除
  拡張子を変更
  実際に存在するファイル名だけを残し、あとは削除
  ファイル名順でソート
  拡張子順でソート
  末尾に \ がなければ、追加
  末尾に \ があるなら、削除
  ファイルに対してリンクするようなHTMLソースを生成

以上の要求を満たすツールをC#でサクッと作ってみたいと思います
posted by JUNOSOFT at 18:49| Comment(0) | プログラミング