ISM(InteractiveSceneManager)が登場して、FaceLevelイベントがサポートされたあたりから訳解んなさ全開だったマウスイベント関連が、かなりスッキリして扱いやすくなった印象。試してみたのが以下のデモ。
InteractiveTest.swf(要:FlashPlayer9)
※各キューブがマウスオーバー、アウト、クリックに反応。
DisplayObject3Dインスタンスでマウスイベントを取得する場合は、
viewport = new Viewport3D(0,0,true,ture);
var flmat:FlatShadeMaterial = new FlatShadeMaterial(light, 0x00ccff );
flmat.interactive = true;
var objPlane:Plane = new Plane( flmat, 250, 250);
objPlane.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, mouseClick);
private function mouseClick(event:InteractiveScene3DEvent):void
{
//イベント発生時の処理
event.displayObject3D.pitch(90);
}
なんて感じで、Viewport定義の際にinteractiveプロパティをtrueにして、イベントリスナーを登録したいDisplayObject3Dインスタンスに与えるマテリアルのinteractiveプロパティをtrueに。この状態でDisplayObject3DインスタンスにaddEventListerすればいいと。
取得できるマウスイベントの種類は、
InteractiveScene3DEvent.OBJECT_CLICK InteractiveScene3DEvent.OBJECT_OVER InteractiveScene3DEvent.OBJECT_OUT InteractiveScene3DEvent.OBJECT_MOVE InteractiveScene3DEvent.OBJECT_PRESS InteractiveScene3DEvent.OBJECT_RELEASE InteractiveScene3DEvent.OBJECT_RELEASE_OUTSIDE ※未実装
あと、マウスイベントじゃないけど
InteractiveScene3DEvent.OBJECT_ADDED
ってのもある。
今回の仕様変更で、入れ子にしたDisplayObject3Dインスタンスでもきちんとイベント取れるようになった。
1.7の頃のようにGroup.asとか使わなくていいのはうれしげ。
08/02/20追記
l4lさんによるとInteractiveScene3DEvent.OBJECT_RELEASE_OUTSIDEは、イベント名の定義だけで実際の処理は未実装だそうな。ちゃんと確認しないとダメね>オレ
さらに追記
OBJECT_RELEASE_OUTSIDEについてもう少し調べてみたところ、AS3のマウスイベントは以下のような仕様になっているらしい。
マウスイベントはそのインスタンス上でしか発生しないため releaseOutside を実現するためには stage にリスナー登録する必要が出てきます。
void element blog: ボタン作成のためのイベントフロー制御
実際どうすりゃいいのか良くわかんなかったんで、上記のvoid element blogさんや、「Adobeデベロッパーセンター:ActionScript 3.0のイベント処理について」を参考にして、一応ソレっぽく動くものを作ってみた。
OBJECT_PRESSして、カーソルを動かさずそのままマウスボタンを離した場合の「mouseRelease」と、OBJECT_PRESSしたまま、マウスカーソルを何もオブジェクトが無い場所や、他のCubeの上で離した場合の「mouseReleaseOutside」をmousePressハンドラ内で定義したら何となく問題なさそうな動きになった。ソース見たほうが早いと思うので貼っておく。このやり方じゃダメダメな気がしてならねぇ。超自信無い。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | package { import flash.display.*; import flash.events.*; import caurina.transitions.Tweener; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.view.BasicView; import org.papervision3d.core.utils.InteractiveSceneManager; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.*; import org.papervision3d.materials.*; import org.papervision3d.materials.special.CompositeMaterial; import org.papervision3d.materials.utils.MaterialsList; [SWF(backgroundColor=0x000000)] public class InteractiveTest2 extends BasicView { private var targetObj:DisplayObject3D; public function InteractiveTest2() { stage.frameRate = 60; stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.quality = StageQuality.MEDIUM; //viewportの定義とカメラタイプ定義 super (0,0,true,true,"Target"); //カメラ設定 camera.x = 600; camera.y = 600; camera.z = -2000; camera.fov = 30; //マテリアル設定 var colorMat:ColorMaterial = new ColorMaterial( 0x006699, 1 ); var wireMat:WireframeMaterial = new WireframeMaterial( 0x0099cc ); var compoMat:CompositeMaterial = new CompositeMaterial(); compoMat.addMaterial(colorMat); compoMat.addMaterial(wireMat); compoMat.interactive = true; var fmaterials:MaterialsList = new MaterialsList( { all: compoMat }); //Cube生成 var tx:Number = -270; var ty:Number = 0; var tz:Number = 0; var objCube1:Cube = new Cube( fmaterials, 250, 250, 250, 1, 1, 1); scene.addChild(objCube1, "cube1"); objCube1.x = tx; objCube1.y = ty; objCube1.z = tz; objCube1.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, mousePress); tx = 270; var objCube2:Cube = new Cube( fmaterials, 250, 250, 250, 1, 1, 1); objCube1.addChild(objCube2, "cube2"); objCube2.x = tx; objCube2.y = ty; objCube2.z = tz; objCube2.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, mousePress); var objCube3:Cube = new Cube( fmaterials, 250, 250, 250, 1, 1, 1); objCube2.addChild(objCube3, "cube3"); objCube3.x = tx; objCube3.y = ty; objCube3.z = tz; objCube3.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, mousePress); //レンダリング開始 startRendering(); } override protected function onRenderTick(event:Event=null):void { super.onRenderTick(event); } //OBJECT_PRESS イベントリスナー private function mousePress(event:InteractiveScene3DEvent):void { Tweener.addTween( event.displayObject3D, { scaleZ:0.5, time:0.8, transition:"easeoutelastic" } ); targetObj = event.displayObject3D; targetObj.addEventListener(InteractiveScene3DEvent.OBJECT_RELEASE, mouseRelease); stage.addEventListener( MouseEvent.MOUSE_UP, mouseReleaseOutside ); } //OBJECT_RELEASE イベントリスナー private function mouseRelease(event:InteractiveScene3DEvent):void { Tweener.addTween( event.displayObject3D, { scaleZ:1, time:0.8, transition:"easeoutelastic" } ); event.displayObject3D.removeEventListener(InteractiveScene3DEvent.OBJECT_RELEASE, mouseRelease); } //stage.MouseEvent.MOUSE_UP イベントリスナー private function mouseReleaseOutside(event:MouseEvent):void { Tweener.addTween( targetObj, { scaleZ:2, time:0.5, transition:"easeoutelastic" } ); stage.removeEventListener( MouseEvent.MOUSE_UP, mouseReleaseOutside ); } } } |
※コンパイルにはTweenerも必要
テストついでに、階層化されたオブジェクトのマウスイベントについても改めて動作確認してみた。3つのCubeは左から「親」「子」「孫」の階層になっていて、それぞれ問題なくマウスイベントが取れているみたいだ。








