switch文内のコメントからimportの整理バグを発動

7月 12th, 2011

とあるソースを改修することになった際に
import文がなぜかメソッドの中にあったり、それを削るとエラーになったりで
意味不明のままずっと謎だった記述の発生原因がわかりました。

簡単に説明するとswitch文の中に/** */ 形式でコメントを記述し
その状態でimport の整理をすると一部のimportが削除される現象が発生します。

実際にサンプルソースで説明します。

まずはswitch文とimportを必要とするクラスを入れたソースを記述
(サンプルは、条件によって描画の色を変更する簡単なクラス)

package
{
  import flash.display.Graphics;
  import flash.display.Sprite;

  public class SwitchTest extends Sprite
  {
    public function SwitchTest()
    {
      var hoge:uint = 0;

      switch (hoge)
      {
        case 0:
          draw(this.graphics, 0xff0000);
          break;
        case 1:
          draw(this.graphics, 0xffff00);
          break;
      }
    }

    private function draw(g:Graphics, color:uint):void
    {
      g.clear();
      g.beginFill(color);
      g.drawRect(0, 0, 100, 100);
      g.endFill();
    }
  }
}

次に上記のswitch文の中に/** */の形式でコメントを記述します。

      switch (hoge)
      {
        /**
         * このコメントは危険です。
         */
        case 0:
          draw(this.graphics, 0xff0000);
          break;

この状態でimportの整理(Ctrl+Shit+O)をすると、、

package
{
  import flash.display.Sprite;

  public class SwitchTest extends Sprite
  {
    public function SwitchTest()
    {
      var hoge:uint = 0;

      switch (hoge)
      {
        /**
         * このコメントは危険です。
         */
        case 0:
          draw(this.graphics, 0xff0000);
          break;
        case 1:
          draw(this.graphics, 0xffff00);
          break;
      }
    }

    private function draw(g:Graphics, color:uint):void
    {
      g.clear();
      g.beginFill(color);
      g.drawRect(0, 0, 100, 100);
      g.endFill();
    }
  }
}

ソースからGraphicsクラスのimportが消えます!

そして、仕方なくこの状態でGraphicsクラスを定義している箇所(g:Graphics)で
コンテンツアシスト(Ctrl+Space)からGraphicsクラスを選択してimportしようとすると

package
{
  import flash.display.Sprite;

  public class SwitchTest extends Sprite
  {
    public function SwitchTest()
    {
      var hoge:uint = 0;

      switch (hoge)
      {
        /**
         * このコメントは危険です。
         */
        case 0:
          draw(this.graphics, 0xff0000);
          break;
        case 1:
          draw(this.graphics, 0xffff00);
          break;
      }
import flash.display.Graphics;

    }

    private function draw(g:Graphics, color:uint):void
    {
      g.clear();
      g.beginFill(color);
      g.drawRect(0, 0, 100, 100);
      g.endFill();
    }
  }
}

今度はGraphicsクラスのimportがメソッドの中に記述されます!!

これを発見したときはかなりの衝撃でした。

今回のサンプルでコンパイルするとエラーになってしまいますが、
エラーにならないこともあるようです。。
(実際自分が触ったソースはコンパイルとおってました。。。)

FlashBuilderのバグと言っていいとは思いますが、
メソッド内ではswitch文に限らず、クラスの説明などで使用する/** */形式での
コメントは避けるべきだと思われます。

ちなみに、
// 形式のコメントや、 /* */ 形式のコメントは問題ありませんでした。

Google Apps Scriptの勉強初めでつまづかないために、、

3月 2nd, 2011

Google Apps では、JavaScriptをベースにしたGoogle Apps Script
というスクリプト言語が使用できます。

とある案件用に、Google Sites でどんなものか試そうかとして
いきなりつまづきましたのでシェアしておきます。

プログラミング経験者なら真っ先に試したくなるのは簡単な文字列”HelloWorld”を表示しようと
することが多いかと思いますが、、

そこで、Google SitesのApps Script エディタに次のようなシンプルなソースを記述し実行

function testFunc(){
  Browser.msgBox("Hello World");
}

アラートボックスにHello Worldと表示されることを期待していたのですが、
次のエラーがでて全く動きません。なんど実行してもエラーです。

Cannot call Browser.msgBox() from this context; have you tried Logger.log() instead? (line 2)

実は、Browser.msgBoxはGoogle Sitesではまだ利用できないようなのです。
(リファレンスには、特に書かれておらず、ユーザーガイドにこっそり書かれていました。)

Since Browser.msgBox() isn’t currently available in a Google Site, you can instead send an email notification

Google Apps Script より抜粋

流石に単純なコードすら動かないと一気にモチベーションが下がります。

Google Apps Scriptは、実行対象のアプリによって動かないことがあることを
知っておいた方が良いと思います。

ちなみに、同じコードをGoogle Spreadsheetsで試したところ、問題なく実行できました。

KINECT+Mac+Processingを連携する

1月 11th, 2011

巷で流行の兆しを見せているKINECTハックですが、自分も試してみることにしました。

自分のマシン環境は、Mac OS X(10.6.6)です。

次の偉大な先人方々の記事を参考にさせていただき、

Kinect Hack 現状まとめ
KinectをPCで使う1 – M-Tea
試験管のなかのコード :: MacOS X で Kinect にチャレンジ
KinectをopenFrameworksで動かしてみた
Kinect使ってみました(mac, openframeworks, ofxKinect) – Dr popeyeブログ:研究、メディアアート、ダンス

どうやらそのまま繋げただけではドライバを認識してくれないとのことだったので
OpenKinectを入れることにしました。

当初、次のURLの手順で試してみたのですが、
Install libfreenect on linux or OSX

githubでlibfreenectを取得する際にusernameとpasswordの
入力を求められ、どうしたらいいかわかりませんでした。
(記事のUPDATEだったりコメント欄をよく読むとOpenKinectの公式ページに移管した模様。)

結局のところ、基本的には次のURLの手順に従っていくだけでOK。
Getting Started – OpenKinect

Macを常に触っている人ならたぶん簡単にできると思いますが
自分はWindowsメインなのでかなり苦労しました。。

git-core、libtool、libusb-devel
をインストールする際に、db46に関してのエラーがでて
ちょっとこのまま進めていいか迷いましたが
とりあえず、進めることにしました。

若干のトラブルもありつつ、一通り手順どおりにインストール作業を終えたので
Processingと連携することにしてみました。

Shiffmanさんの次の記事にリンクされているopenkinect.zipをダウンロードして
Kinect and Processing at daniel shiffman

サンプルのProcessingファイル(PointCloud.pde、RGBDepthTest.pde)を起動。

外部ライブラリ(libKinect.jnilib、openkinect.jar)を使用しているので
設定を確認してから実行。


RGBDepthTest.pde のスクリーンキャプチャ(一部抜粋)

結果、上手く動くことができました!

まだ連携しただけなので色々実験して行きたいと思います。

ローカル環境でSWFを動かす時の注意点

12月 10th, 2010

なかなか珍しい案件ですが、
ローカル環境でHTMLを開き、そこにFlashコンテンツを表示させる
案件でハマりました。

まず、navigationURLがデフォルトでは動かないです。
セキュリティサンドボックス侵害エラーがでます。

プロジェクタ形式では問題ないのですが、SWFだと動きません。
納品近くでそのことが判明しかなり冷や汗ものでした。
(事前検証は必須ですね。。)

過去に見聞きした事例をなんとか思い出し、
運よく外部サイトへの遷移がなかったので
コンパイル時に引数で-use-network=falseで回避することができました。

そして、アンカーリンク、クエリーストリングが渡せません。
これは、もうどうしようもなかったです。
実態参照でもダメでしたね。

最後に、FlashからJavaScriptが実行&呼び出しができません。

ローカル環境は、ネットワーク環境に比べて
ものすごくセキュリティが厳しいです。

気持ちは、わからないでもないですが、、もうちょっとなんとかしてほしいです。。

スパムコメント発生中

8月 17th, 2010

コメント欄を解放したら早速スパムの嵐です。。

試しにSI CAPTCHA Anti-Spamというプラグインをいれてみましたが、
上手く動かない、、

どうやら自分はWordPressと相性が良くないようです。

ブログ改装中

7月 16th, 2010

コメント欄がずいぶん前から入力できない現象がおきていたけど、
どうやらこのブログを開設したときから起きていたようだ。
(プレビューではコメント欄が出るのできづかなかったみたい、、)

フォーラムをみるとどうやら仕様のようす。
http://ja.forums.wordpress.org/topic/3811

つまり、パーマリンク設定でURLをカスタム構造にした場合
ユニークIDと完全にわかるタグを入れないとコメント欄が表示されない現象が発生するとのこと。

まさに、自分は日付(年月日時間)だったので、ユニークとはいえないタグでした。

正直、ずいぶんたってからこの致命的な問題に直面したのは悲しい。

まー、アクセス数が全くないのが不幸中の幸いで
ここで思い切って全パーマリンクの構造を切り替えることにしました。

記事にリンクを張ってくれていた方には申し訳ないですがご了承ください。

しかし、このデフォルトテーマはより悲しい。

オートコンプリートが機能していないように見せかける

4月 8th, 2010

今やっている案件で、
違うユーザーが同一PC、同一ブラウザで認証が必要なシステムにアクセスしたい
といった要望がありました。

オートコンプリート機能を使うと入力情報は保存されるので
違うユーザーがなりすまして入ることができてしまいます。

しかし、そもそも
オートコンプリート機能自体は、ブラウザに依存するので
システムからでは根本的に回避する方法はないのですが、
大人の事情があり、見かけ上だけでも見せなくする手段を
作ることになりました。

そして、できたのがこちらです。
回避策対応版

検証方法は、
1.上記のページにアクセスします。
2.適当に、文字を入力しsubmitボタンを押します。
3.ブラウザで記憶するか聞かれるので記憶します。
4.一度閉じるか、リロードするなどして、再度上記のページを開きます。
再度ページを開いた際に、入力フォームに値が入っていないと思います。
ブラウザによっては、inputタイプがpasswordではない場合に、
フォーカスを合わせて下キーを押すと候補がでるようですが、
選択してもpasswordは表示されないと思います。

実装方法は、
ソースを見ていただければわかると思いますが、
bodyタグのonloadイベントで、
フォームのinputboxを作成しているだけです。

この方法を使えば、どうやらオートコンプリート機能は動かないようです。

こちらは、何も実装していないオートコンプリートが働くフォームです。
回避策非対応版

改めて書きますが、
この方法は、根本的な解決にはなりません。

以上、苦肉の策でした。

HYPEでFlashコンテンツを透過PNG保存する

1月 28th, 2010

HYPE frameworkの中で最も興味深い機能の一つが
Flashコンテンツを透過PNG形式保存できることではないでしょうか。

JoshaDavisさんが、Flashコンテンツを印刷媒体に使っているのを見て
Flashコンテンツをどうやってベクターデータをキープしてイラレやフォトショにエクスポートするかを
1、2年ぐらい前に、l00oo.oo00lさんと何度か議論したことがあり
結局、fladdictさんがやっているようなSVGエクスポートしかないのかなぁと
その時は思っていました。

しかし、このHYPE frameworkではPNG保存ができるということをアナウンスしていたので
早速試してみました。

チュートリアルで一通りチェックをした感じだとすごい簡単に出来そうでした。

ContextSavePNG from Joshua Davis on Vimeo.

サンプルコードをHYPEのサイトから適当にもってきて試します。
(自分は01_objectpoolを少し改造して試します。)

まずは、ContextSavePNGクラスをインポートします。

	import hype.extended.util.ContextSavePNG;

後は、BitmapCanvasクラスのインスタンスをつくり、
setupLargeCanvas()メソッドに保存倍率を指定し、
ContextSavePNGをインスタンス化するだけで準備は完了です。

			// PNGエンコードの際の倍率を指定
			clipCanvas.setupLargeCanvas(10);
			// PNG保存のコンテキストを登録
			var savePNG:ContextSavePNG = new ContextSavePNG(clipCanvas);

ものすごくシンプルです!!

では実際に、Flashコンテンツをキャプチャしてみます。

※ 描画用の背景は透明で、描画領域は縦横300pxです。

まずはFlashコンテンツを実行し、感性に任せて程好いところで右クリック。
すると、コンテキストメニューに[ Encode PNG ] と表示されるのでそこでクリック。
プログレスバーが表示されPNGへのエンコードを行います。
プログレスバーが消えたら再度右クリック。
すると、今度はコンテキストメニューに[ Save PNG... ] と表示されるのでそこでクリック。
ダイアログが表示されるのでお好みの場所に保存で完了です。

早速、フォトショで確認してみます。

ちゃんと、透過できて取り込めています。
そして、気になる解像度も、300px * 300px の10倍でPNG保存したので
3000px * 3000px になっています。

これであれば、たとえば解像度300にしても
254mm サイズの印刷に劣化せず対応できるということになります。

これは、とても便利です!
間単に自作のジェネレーティブアートが印刷できるようになりました!!

ベクターデータではないので、
Joshuaさんの実際の作品用エクスポートだったり、fladdictさんがやっているようなアプローチとは
ちょっと違うとは思いますが、これでも、十分可能性を秘めていると思います。
検証の価値ありです。

ますます、Flashが楽くなりますね。

HYPE frameworkの勉強(4)

1月 27th, 2010

初回はこちら
第2回はこちら
第3回はこちら
前回までのソースはこちら

※ 注意 ※
自分はFlexBuilder3を使用して試していますので
CS4を使ったやり方は実際のチュートリアルを参照ください。

オブジェクトをビットマップでキャプチャする

今までは、オブジェクトを移動させていただけですが、
今度は動きをビットマップでキャプチャをしていきます。

まずは、BitmapCanvasクラスをインポートします。

	import hype.framework.display.BitmapCanvas;

ビットマップキャプチャ用のキャンバスを作成します。

		// ビットマップキャプチャ用キャンバス
		private var clipCanvas:BitmapCanvas;

コンストラクタにステージの領域でインスタンスを作成。
※一部抜粋

			// シェイプを非表示
			exitShape.visible = false;

			// ビットマップキャプチャ用キャンバスを作成します
			// 第1引数には、キャンバスの横幅
			// 第2引数には、キャンバスの高さ
			clipCanvas = new BitmapCanvas(myWidth, myHeight);
			addChild(clipCanvas);

コンストラクタの最後にキャプチャを開始する処理を記述します。
はじめはstartCaptureメソッドの第2引数をtrueにします。

※一部抜粋

			// キャプチャを開始します。
			// 第1引数には、対象オブジェクト
			// 第2引数には、キャプチャを繰り返すかどうか
			clipCanvas.startCapture(clipContainer, true);

			addEventListener(Event.ADDED_TO_STAGE, onAddToStage);

実行してみると、オブジェクトが動くたびにキャンバスに転写され
足跡みたいな描画になります。

別ウインドウで表示

描画されている箇所をよく見ると、BitmapCanvasのコンストラクタで設定したとおり
ステージ領域だけ足跡が描画されていることがわかります。
つまり、Graphicクラスのclear()メソッドを呼ばないで描画している状態と同じです。

そこで、ステージ領域だけを描画するようにコンストラクタに記述していた
コンテナ(clipConteiner)の追加処理を削除します。
※一部抜粋

			// コンテナを作成
			clipContainer = new Sprite();
// 削除		addChild(clipContainer);

これでBitmapCanvasのキャプチャ部分だけを表示するようできました。

別ウインドウで表示

ステージへ入る前、出た後は表示されず、ステージ上では正しく表示されています。
何よりもDisplayObjectを描画しているわけではなく、Bitmapに転写したものを描画しているので
パフォーマンスもかなり期待できます。

ここで、はじめに設定したstartCaptureメソッドの第2引数をfalseにして実行してみます。

別ウインドウで表示

画面がスッキリしました。そして、スムーズに動きます。

オブジェクトにいろいろな動作をつけてみる

初回で、DIrectionalVibrationクラスで下から上に動きをつけましたが、
その他の動きもつけてみます。

まず、FixedVibrationクラスをインポートします。

	import hype.extended.behavior.FixedVibration;

はじめに角度をつけます。
FixedVibrationのインスタンスをpool.onRequestObjectの関数内に記述します。

				// オブジェクトを指定した角度に振動させます。
				// 第1引数には、対象オブジェクト
				// 第2引数には、対象プロパティ
				// 第3引数には、弾力値?
				// 第4引数には、加減速値?
				// 第5引数には、振動幅の最小値
				// 第6引数には、振動幅の最大値
				// 第7引数には、現在の値を維持するかどうか
				var rVibration:FixedVibration = new FixedVibration(clip, "rotation", 0.9, 0.1, -13, 13, false);

				// 振動を実行させます。
				rVibration.start();

-13度から13度の間で動きます。

別ウインドウで表示

次に、第7引数がどのような影響をあたえるか、X座標を動かすことで確認します。
角度を少し抑え(min:-2、max:2)
X座標用のFixedVibrationのインスタンスをpool.onRequestObjectの関数内に記述します。
第7引数はとりあえずfalseに設定します。

				// オブジェクトを指定した座標に振動させます。
				// 第1引数には、対象オブジェクト
				// 第2引数には、対象プロパティ
				// 第3引数には、弾力値?
				// 第4引数には、加減速値?
				// 第5引数には、振動幅の最小値
				// 第6引数には、振動幅の最大値
				// 第7引数には、現在の値を維持するかどうか
				var xVibration:FixedVibration = new FixedVibration(clip, "x", 0.9, 0.1, 10, 40, false);

				// 振動を実行させます。
				xVibration.start();

実行すると、左側にオブジェクトが寄ってしまいます。

別ウインドウで表示

これは、第7引数の現在の値、つまり現在のX座標を維持するかどうかで、false=しないに設定しているので
常に10pxから40pxの間を行き来することになります。

動きがわかるように振動幅を大きくし(min:-40、max:40)、第7引数をtrueにして実行してみます。

別ウインドウで表示

現在のX座標を維持し相対で動くことが確認できました。

最後に角度、X座標ともに程よい振動幅(min:-4、max:4)に設定し実行してみます。

別ウインドウで表示

3ヶ月遅れのハロウィンですが、、これで出来上がりです!!

気づいたら第4回まで続いてしまい
つたない文章と、わかりずらいコードの説明が散見していたと思いますので
出来上がりのソースをおいて置きます。

個人的に解釈して記述している箇所もあるので
是非、Joshuaさんのチュートリアルを閲覧されることをお勧めいたします。

チュートリアルを見て試しているだけで、ActionScriptのテクニックが物凄い詰まっていることがわかります。
コードも直感的でわかりやすいし、引数のパラメータをいじるだけでいろいろな動きがつけられるので
コードを書くのがが苦手な方や、AS初心者にはとてもなじみ易いと思います。
メモリ管理もしっかり考慮されていてASになれている方にも興味深いフレームワークだと思いました。

指摘等ございましたら以下までご連絡いただけると幸いです。
otayori[at]awk2.net

HYPE frameworkの勉強(3)

1月 26th, 2010

初回はこちら
第2回はこちら
前回までのソースはこちら

※ 注意 ※
自分はFlexBuilder3を使用して試していますので
CS4を使ったやり方は実際のチュートリアルを参照ください。

オブジェクトのステージアウトを検知する

ステージと同じ領域にしたシェイプから
オブジェクトが外れたかどうかをチェックすることで
ステージアウトしたかを判断します。

ExitShapeTriggerクラスをインポートします。

	import hype.extended.trigger.ExitShapeTrigger;

ステージ領域のシェイプを作成します。

メンバー変数を定義します。

※一部抜粋

		// ステージ領域のシェイプ
		private var exitShape:Shape;

コンストラクタでインスタンスを作成し、
ステージ領域で塗りつぶします。

※一部抜粋

			var myWidth:Number = stage.stageWidth;
			var myHeight:Number = stage.stageHeight;

			// ステージ領域のシェイプを作成します
			exitShape = new Shape();
			exitShape.graphics.beginFill(0x333333);
			exitShape.graphics.drawRect(0, 0, myWidth, myHeight);
			exitShape.graphics.endFill();
			addChild(exitShape);

次に、オブジェクトがステージ領域から外れたら呼ばれる関数に
プールからの解放と表示リストからの削除をする処理を記述します。

		/**
		 * ExitShapeTriggerクラスのコンストラクタに設定するコールバック関数
		 * リファレンスには詳しく書かれていないですが第1引数は対象オブジェクトのようです。
		 */
		private function onExitShape(clip):void
		{
			// 対象オブジェクトをプールから解放します
			pool.release(clip);
			// クリップコンテナから対象オブジェクトを削除します
			clipContainer.removeChild(clip);
		}

最後に、オブジェクトがステージ領域から外れたかどうかをチェックする処理を、
pool.onRequestObjectの関数内に記述します。

※一部抜粋

				// 振動を実行させます。
				yVibration.start();

				// シェイプから外れたかどうかをチェックします
				// 第1引数には、対象オブジェクトがシェイプから外れた場合に呼ばれるメソッド
				// 第2引数には、対象オブジェクト
				// 第3引数には、検知するシェイプ
				// 第4引数には、対象オブジェクトの実際のピクセルで比較するか境界ポックスで比較するかどうか(hitTestPointメソッドの第3引数と同じ意味)
				// 第5引数には、対象オブジェクトを一度シェイプに入れる必要があるかどうか
				var exitTrigger:ExitShapeTrigger = new ExitShapeTrigger(onExitShape, clip, exitShape, false, false);

				// チェックを開始します。
				exitTrigger.start();

				clipContainer.addChild(clip);

ステージ領域から外れたオブジェクトが消えることが確認できます。
しかも、外れたオブジェクトが新たに作成されることも確認できました。
※ステージサイズが550px×400pxで、SWFの表示サイズを600px×480pxにして確認しています。

別ウインドウで表示

これは、前回の『ランダムにムービークリップを表示する』で記述したSimpleRhythmクラスのメソッドが
一定時間動いてるからです。

次に、ExitShapeTriggerコンストラクタの第5引数について仕組みを考察してみます。

第5引数をfalseに設定してみるとオブジェクトが上に動くことなく、点滅したようになります。

別ウインドウで表示

これは第5引数で、オブジェクトが既にシェイプに入っていると設定しているので
SimpleRhythmクラスのメソッドによって作成された瞬間に
シェイプから外れたと判断され削除の処理が実行されます。
さらにSimpleRhythmクラスのメソッドによって再度作成されるので
ステージを横断することなく点滅してしまいます。

では、第5引数をfalseの状態のまま
オブジェクトが作成した際に既にシェイプに入っている状態になるように
ステージ領域のシェイプを広げてみます。

※一部抜粋

			exitShape.graphics.drawRect(0, -myHeight*0.25, myWidth, myHeight*1.5);

※ステージサイズが550px×600pxで、SWFの表示サイズを600px×720pxにして確認しています。

別ウインドウで表示

正常に動くことが確認できました。

再度、第5引数をtrueの状態に変更します。
そこで今度はステージ領域のシェイプの横幅を半分ぐらい短く設定してみます。
※一部抜粋

			exitShape.graphics.drawRect(0, 0, myWidth*0.6, myHeight);

※ステージサイズが330px×400pxで、SWFの表示サイズを600px×480pxにして確認しています。

別ウインドウで表示

シェイプに入ったオブジェクトだけ、シェイプから外れた瞬間に消えることが確認できました。

最後に、これまでの内容を踏まえコンテンツを次のように調整します。
・第5引数をfalseの状態に変更
・シェイプの横幅をステージ領域に戻し、高さをオブジェクトの生成/削除されるタイミングが
 ステージ上で見えないように調整
・シェイプを非表示に設定(非表示にしても検知可能です。)
・オブジェクトの数を増加(200個)

別ウインドウで表示

段々と形になってきました!

今回は、チュートリアルの26分ぐらいから39分ぐらいまでのお話でした。

調べれば調べるほど興味深いです。
ちゃんと、メモリ管理も考慮して作られています。

指摘等ございましたらご連絡いただけると幸いです。