Neo Inspiration

Avatar

中の人:jakkrokk (HN統一しました) がphp,javascript,air,flex などなど好き勝手書いてます。仕事は主にWEBシステムの設計と開発、SEO全般など。

Papervision3D + SHADEができるのね

3Dかふーんとか思ってちょっと線つけるくらい遊んで終わってたネタですが、

ここらへんとか
http://blog.livedoor.jp/techblog/archives/65135414.html

ここらへんとか
http://d.hatena.ne.jp/haru-komugi/20071123/1195829334

ここらへんとか
http://www.libspark.org/wiki/rch850/Metasequoia

みて革命がおきたw
まさかメタセコや六角からインポートできるとか。。。
っていうかまさかDAEデータ食わせれるとは。。。
つかSHADEってDAEデータ作れたよな。。。
じゃあDAEファイルにすればFlashで読み込めるじゃんね!まじで!

とまあ一人で超もりあがってました。
まあそのままやるわけにはいかなくて、
基本BMPで作ってるテクスチャ系は全部JPEGなりに当てなおさないといけないし
(SHADE5(古)だとJPEGでテクスチャ当てれなかったきがする。。)

大学の頃ガンダムを3Dで作りまくって遊んでたので、
こんなの

SHADE結構得意なので、
3Dに起こしてみようかなとおもった!

が マダヤッテナイ。
だってSHADEデータのレンダリングに1発3日とかかかるから。。。

Flexで phpでいうsleepみたいなことをしてhttp requestを大量に発行する

イベント駆動のプログラミングがここまで違うとは思わなくて、
思わぬところではまったのでめも。

PHPならこう書きたい・・

ハマったのは、phpで言うところの

foreach ($myRssUrlList as $key=>$url) {
    $html[] = file_get_contents($url);
}

みたいなことがしたかったんですが、
イベント駆動の考え方でこれがめんどくさくって。

Flex的には file_get_contents にイベントを設定して、
file_get_contentsが完了したら次にやる
っていう感じに書き方をするわけで、
そのまま書くとこうなっちゃう。

<mx:HTTPService id="httpService" />

function httpReq():void {
    for each (var url:String in myRssUrlList) {
        httpService.url = url;
        httpService.addEventListener(ResultEvent.RESULT,function():void{});
        httpService.send();
    }
}

(myRssUrlListにはRSSのURLが10個くらい入ってるイメージ)
が、 これだとうまくいかない。
どうなるかというと、 例えばmyRssUrlListにURLが10個入ってると、
最後のURLの結果が10回取得されて終わっちゃう。(自分の環境では)

ほぼ同時に(一応順番どおりだけど)リクエストを全部走らせて、
終わったものから順にfuntionを走らせるので、
1個のオブジェクトの結果をひたすら上書きしていて、
イベントのfunctionが走るタイミングでは、指定したURLの結果かどうかが担保されていないから。
さらに全部ほぼ同時にrequestが走るので、10とかならまだしも10000とかURLリストがあると
即効落ちるw

でしょうがないので、毎回オブジェクトを作ることにする。

function httpReq():void {
    for each (var url:String in myRssUrlList) {
        var httpService:HTTPService = new HTTPService();
        httpService.url = url;
        httpService.addEventListener(ResultEvent.RESULT,function():void{});
        httpService.send();
    }
}

こうすると毎回別のオブジェクトなので、うまく取れるようになるわけだけど、
やっぱり問題は全部同時に走らせちゃうこと。

で、次に思ったのが、

foreach ($myRssUrlList as $key=>$url) {
    $html[] = file_get_contents($url);
    sleep(3);
}

こう書きたい。
ので、 flexでsleepを探してみる。
javascriptでも似たようなことで詰まった覚えがあるので、
あんまり期待しない。

Flex で Sleep的な~

で、 やっぱ sleepみたいなことはなかったけど、(探したりないだけかもしれないけど)
変わりに Timer();を使うといいとか書いてあったので、それを使ってみる。

//HTTPリクエストのタイマー
private function httpQue():void {
    var timer:Timer = new Timer(2000,myRssUrlList.length); //2秒ごとにイベント発動
    for each (var url:String in myRssUrlList) { //とにかくmyRssUrlListの数だけtimerイベントを発動させる
        timer.addEventListener(TimerEvent.TIMER,httpReq);
    }
    timer.start();
}

//HTTPリクエストを発行するメソッド
private function httpReq(evt:Event):void {
    var url:String = myRssUrlList.shift() as String;
    var httpService:HTTPService = new HTTPService();
    httpService.url = url;
    httpService.addEventListener(ResultEvent.RESULT,function():void{});
    httpService.send();
}

これで2秒置きにHTTPリクエストが発行できるようになる。
とりあえず10000くらいは処理できたので、
あとはPCがんばれ!

ちなみに

タイマーのところで

これを
timer.addEventListener(TimerEvent.TIMER,httpReq);
こうかいちゃうと
timer.addEventListener(TimerEvent.TIMER,function(evt:TimerEvent):void{httpReq(url);});

functionの生成の順番のせいで、最後のURLが回数分だけアクセスされちゃうことになるので注意。

この生成の順番で超はまってしまった。。

最後

ながかった。。

FlexでAccordionHeaderにつけたボタンに押した感を出す

FlexでAccordionHeaderにボタンを配置の続きで、
AccordionHeaderにつけたボタンに押した感を出すやり方。

やり方としては2段階にわけて、
まずはボタンの上にマウスが来たら指マークにして、
その後その部分をダブルクリックしたら、イベントをさらに発生させる
ようにします。

こんなかんじ

とりあえず前提としてAccodionにイベントを埋め込んでおく

//Accordionはこうかいておいてイベントリッスンさせる

各イベント

//マウスカーソルがボタンの上にきたら指マークに変更
private function dispatchMouseMove(e:MouseEvent):void {
    var accHeader:AccordionHeader = new AccordionHeader();
    var button:Button = new Button();

    //AccordionHeaderをすべてチェックする
    for (var i:int = 0;i < myAccordionHeader.numChildren;i++) {
        accHeader = myAccordionHeader.getHeaderAt(i) as AccordionHeader;
        button = accHeader.getChildAt(0) as Button;
        //ボタンの上にマウスがあるかをチェックする
        if (button.getRect(this).useHandCursor(e.stageX,e.stageY)) {
            //マウスがボタンの上にいたら useHandCursorをtrueにする
            accHeader.buttonMode = true;
            accHeader.useHandCursor = true;
        } else {
            accHeader.useHandCursor = false;
        }
    }
}

まあ経験が浅いので上記のやり方くらいしか思いつかなかったんですが、
AccordionHeaderのボタンの位置とマウスカーソルの位置をチェックして、
contains() でチェックしていくというやり方です。
指カーソルに変更するのは、別のやり方もあると思いますが、
とりあえずAccordionHeaderのプロパティを書き換えるだけでも上手くいきます。

で、次に指カーソル状態でダブルクリックをチェックします。

//ボタンの上でダブルクリックされたらイベント発動
private function dispatchDblClick(e:MouseEvent):void {
    var accHeader:AccordionHeader = new AccordionHeader();
    var button:Button = new Button();

    //AccordionHeaderをすべてチェックする
    for (var i:int = 0;i < myAccordionHeader.numChildren;i++) {
        accHeader = myAccordionHeader.getHeaderAt(i) as AccordionHeader;
        button = accHeader.getChildAt(0) as Button;
        if (button.getRect(this).contains(e.stageX,e.stageY)) {
            accHeader.addEventListener(MouseEvent.CLICK,myDoubleClickEvent);
            accHeader.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
        }
    }
}

こっちも同じようにAccordionHeaderのボタンの位置と
マウスカーソルの位置をチェックして、
contains() でチェックしていくというやり方です。

一応実装してみた

一応このAccordionはTinyTodoというアプリで実装してみたので、
よかったら見てみてください。
Air製Todo管理ツール

Continue Next page

Twitter