2013年11月1日金曜日

BloggerでSyntaxHighlighterを利用する際のTIPS

前の記事で、SyntaxHighlighterを導入してソースコードをBlogger上で表示した。 Luaの表示には公式ウェブサイトからリンクされているサイトの追加ブラシのLua1を利用した。 SyntaxHighlighterを使う際に以下のような問題に遭遇したため、ここにその対処法を示す。
  • Bloggerでは任意のファイルをアップロード出来ない
  • 記事上で、<等の特殊文字がうまく表示できない
  • タブが半角スペースに置換され、インデントがずれる
  • 全ての行の背景が同じ色で表示されるため、少し見辛い
  • shThemeXxx.css と shCoreXxx.css の違いが分からない

Bloggerでは任意のファイルをアップロード出来ない

Bloggerでは、任意のファイルをアップロードする事はできない。よって、JavaScriptやCSSをBloggerのドメインでホスティングする事は出来ず、Alex氏がホスティングしているファイルを参照する事になる。
別にそれはそれで構わないのだが、出来れば自分でホスティングしたい。それに、Syntax Highlighterがサポートしていない形式のコードを扱う時は困る(これも、その作者がホスティングしてくれているファイルを参照すれば問題ないが、精神的によろしくない)。
Google サイトを使った方法や、Google ドライブを利用する方法等があるようだが、いずれも欠点を抱えているようなので、私のオススメはDropboxを利用することである。
ここで注意したいのが、DropboxでのファイルのURLを生成する方法は二種類あることだ。
Publicフォルダに置いたファイルは「公開リンクをコピー」することで、そのURLを取得出来る。この方法で取得するURLには一意なユーザIDと、Publicフォルダ内におけるディレクトリ情報が含まれる。複数のハンドルネームを使っている場合等、「このファイルとあのファイルが置かれているアカウントは同じアカウントだ」とバレたくなければ使わないほうがいいだろう。ただし、内部的に相対パスを利用するファイルではこちらの方法が必須となる。
尚、生成されるURLは https://dl.dropboxusercontent.com/u/userID/filename だ。
Publicフォルダ以外に置いたファイルは「Dropbox リンクを共有」の機能を使用することで、URLを生成することができる。こちらの方法で生成したURLは、どのアカウントのファイルなのかを含め、隠蔽される。相対パスは利用できないが、よりセキュアであると言える。
生成されるURLは https://www.dropbox.com/s/fileID/filename だ。
参考:

記事上で、<等の特殊文字がうまく表示できない

HTMLでは一部の特殊文字は文法上の記法に利用されるため、エスケープシーケンスが必要となる。 置換にはこのサイトを利用した。
HTML特殊文字変換|コードをホームページに載せる時に便利 | すぐに使える便利なWEBツール | Tech-Unlimited 他にもあるかも知れないし、ローカルで出来るようなプログラムがあった方が良いかもしれない。

タブが半角スペースに置換され、インデントがずれる

Bloggerでは、タブが半角スペースに勝手に置換されるため、ソースコードのインデントがずれる。 プレビューではちゃんと表示されるのに、保存、公開した途端に置換されるのが曲者だ。 投稿時の編集のモードをHTMLにし、タブを &#9; に置換して記述することで、この現象を避けることが出来る。 ただし、一度編集のモードを作成にすると、せっかく置き換えたタブが半角スペースに戻ってしまうため注意。 公開後、きちんと投稿後の記事を確認した方が良いだろう。

全ての行の背景が同じ色で表示されるため、少し見辛い

これは、SyntaxHighlighterのCSSを編集することで改善できる。 .syntaxhighlighter .line.alt1 と .syntaxhighlighter .line.alt2 のそれぞれに背景色を設定してやればよい。 詳細は Syntax Highlighterの背景色と行間を変更する | ジャイアントモリンキーのjavaテック を参照。

shThemeXxx.css と shCoreXxx.css の違いが分からない

shCoreXxx.css は shCore.css と shThemeXxx.css を合成したものである。 参考: そらとぶくじら。 SyntaxHighlighter

以上。

2013年10月22日火曜日

Luaを使ってクラスっぽい物を生成してCから使う方法

2013.11.04 修正版記事を作りました。
2013.11.04 大きな間違いに気がついたので後日書き直します。本記事は大嘘です。
2013.11.01 誤って記事を消してしまったので書き直し。

本記事は間違いだらけです。修正版はこちら。


以下のようなコードによって、Luaで簡単なクラス風のテーブルを作成できる。

クラス風のテーブルを作成する方法はWEB上に多数のサンプルが見受けられたが、 Cとの連携を付記したコードは見当たらなかったので備忘録として作成。

継承にはもう少し工夫が必要だが、複雑なテーブルを作成するならC++で普通にクラスを書いたほうが良い気がする。主観だが。

Luaでグローバル領域に宣言されたテーブルのフィールドを利用する際は、一度テーブルをスタックに積んでからフィールドを取得する点に注意。

main.cpp

#include <lua.hpp>
#include <stdio.h>

int main( void ) {
	lua_State *L = luaL_newstate();	// Luaステートを生成
	luaL_openlibs( L );				// 標準ライブラリを読み込み
	
	// スクリプトの読み込み
	if (luaL_dofile(L, "script.lua") ) {
		// エラー処理
		printf("%s\n", lua_tostring(L, lua_gettop(L) ) );
		lua_close(L);
		return 0;
	}

	// まず犬を生成
	lua_getglobal( L, "Dog" );					// グローバルなテーブル"Dog"をスタックに積む
	lua_getfield( L, lua_gettop( L ), "new" );	// トップに積まれたテーブルのメンバ"new"をスタックに積む
	lua_pushstring( L, "Neko" );				// 名前はNeko。犬なのにNeko。
	lua_pcall( L, 1, 1, 0 );					// 実行!
	int idx_dog = lua_gettop( L );				// Nekoのスタック上の位置を取得

	// 次に猫を生成
	lua_getglobal( L, "Cat" );					// グローバルなテーブル"Cat"をスタックに積む
	lua_getfield( L, lua_gettop( L ), "new" );	// トップに積まれたテーブルのメンバ"new"をスタックに積む
	lua_pushstring( L, "Inu" );					// 名前はInu。猫なのにInu。
	lua_pcall( L, 1, 1, 0 );					// 実行
	int idx_cat = lua_gettop( L );				// Inuのスタック上の位置を取得

	lua_getfield( L, idx_dog, "show" );	// 関数をスタック
	lua_pcall( L, 0, 0, 0 );			// 呼び出し
	
	lua_getfield( L, idx_cat, "show" );	// 関数をスタック
	lua_pcall( L, 0, 0, 0 );			// 呼び出し

    lua_close( L );	// 終了
    return 0;
}

script.lua

-- Dog
Dog = {}
Dog.new = function( name )
	local obj = {}
	obj.name = name
	obj.show = function( self )
		s = string.format( "%s the DOG.", name )
		print( s )
	end
	obj:show()
	return obj
end

-- Cat
Cat = {}
Cat.new = function( name )
	local obj = {}
	obj.name = name
	obj.show = function( self )
		s = string.format( "%s the CAT.", name )
		print( s )
	end
	obj:show()
	return obj
end

2013年8月23日金曜日

glBeginとglMaterialfvの順番とGLSLの関係

OpenGLで描画を行う際、
glBeginよりも後にglMaterialfvを呼び出すと、
シェーダーを使用した際に色が設定されない。
シェーダーを使用しなかった場合は正しく描画されてしまうのが曲者である。

// NG
glUseProgram( shaderProgram );
glBegin( GL_POLYGON );
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red );
glVertex3f( 0.0, 0.0, 0.0 );
glVertex3f( 1.0, 0.0, 0.0 );
glVertex3f( 1.0, 1.0, 0.0 );
glVertex3f( 0.0, 1.0, 0.0 );
glEnd();

// OK
glUseProgram( shaderProgram );
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red );
glBegin( GL_POLYGON );
glVertex3f( 0.0, 0.0, 0.0 );
glVertex3f( 1.0, 0.0, 0.0 );
glVertex3f( 1.0, 1.0, 0.0 );
glVertex3f( 0.0, 1.0, 0.0 );
glEnd();

shaderProgramとredは書いていないが適切な変数だと思って頂きたい。

恐らく、glBeginの時点でGPUにカラー情報が渡され、後から変更できない為に、
このような挙動になっているのではないかと。
シェーダーを使用しない場合何故通ってしまうのかは不明。

描画するオブジェクトの種類によっては、
glBeginとglEndの間で普通にglMaterialfvを呼び出すオブジェクトもあるが、
そういったオブジェクトでglBeginとglEndの間でglMaterialfvを間で呼び出すと、
シェーダーを使用する際どうなるかは調べていないので不明。
もしかしたら環境によって挙動が異なる可能性すらある。

2013年8月11日日曜日

DGZ サポートページ

DGZのサポートページです。

DGZはソースコードを公開しているフリーゲームです。
ユーザーは自由にコードを改変し、コード及びプログラムを公開することができます。
また、その際に報告の義務はありません。
ただし、コード以外のリソースは二次利用できません。
予めご了承下さい。

バグ報告・感想等は当記事のコメント欄にお願い致します。
ダウンロード

2013年7月11日木曜日

Luaの標準ライブラリのロード方法

今まで一部で躓いていたCからのLuaステートへの標準ライブラリのロードがうまくいったのでアウトプット。

以下はうまくいかないコード。
#include

int main( void ) {
    lua_State *L = luaL_newstate();
    luaopen_package( L );
    lua_close( L );
    return 0;
}

出力:
PANIC: unprotected error in call to Lua API (no calling environment)

以下が正しいコード。
#include

int main( void ) {
    lua_State *L = luaL_newstate();
    lua_pushcfunction(L, luaopen_package);
    lua_pushstring(L, LUA_LOADLIBNAME);
    lua_call(L, 1, 0);
    lua_close( L );
    return 0;
}

リファレンスを見る限りは、全てのライブラリのロードで下の方法を用いるべきと思われる。上の方法でうまく動くライブラリとそうでないライブラリが存在する。
luaL_openlibs( L ); // OK
luaopen_base( L ); // OK
luaopen_math( L ); // OK
luaopen_string( L ); // OK
luaopen_table( L ); // OK
luaopen_debug( L ); // OK
luaopen_package( L ); // NG
luaopen_io( L ); // NG
環境によるかもしれないので必ず上を使いましょう。

2013年7月10日水曜日

luaopen_mathでスタックに謎のLUA_TTABLEが積まれる件について

以下のコードは動作はするが、予期せぬ結果となる。

script.lua

function func(num)
    return num;
end

main.cpp

#include "lua.hpp"
int main( void ) {
    lua_State* p = luaL_newstate();
    luaopen_math( p );
    luaL_dofile( p, "script.lua" );
    int num = 100;
    lua_getglobal( p, "func" );
    lua_pushnumber( p, num );
    lua_pcall( p, 1, 1, 0 );
    num = lua_tonumber( p, 1 );
    lua_close( p );

    return 0;
}

最終的にnumに入っている値は100であると予想されるが、
実際には0が入っている。
luaopen_mathを呼び出した際に、謎の LUA_TTABLE がプッシュされるため、
スタックの一番下には func の返り値ではなく、
テーブルが入っており、その上に返り値が積まれている。

NG: num = lua_tonumber( p, 1 );
OK: num = lua_tonumber( p, -1 );

何が積まれているのかは調べたけど分からなかった。
誰か、Luaに詳しい方で分かる方いらっしゃったら教えて下さい。