Home > papervision3d > Papervision3Dで複数のオブジェクトにマウスイベントを付ける方法

Papervision3Dで複数のオブジェクトにマウスイベントを付ける方法

Papervision3D Rev1.5で複数のオブジェクトにマウスイベントを設置する方法にはちょっとしたテクニックが必要です。ライブラリとしての設計不足な気もしますが、まだまだ若いライブラリなので、これから改善されていく事でしょう。

シーンの作成

まず、1つ目に大切なのはシーンの作成です。今まで私のエントリではScene3Dというクラスを使って3D環境となるシーンを作ってきました。しかし、これでは複数のオブジェクトにマウスイベントを付ける事ができません。
これはScene3Dのソースコードからも明らかです。これは是非改善してほしい点ですが、Rev1.5ではMovieScene3Dで複数オブジェクトにマウスイベントを設置できるので、今回はこれを使います。

container = new Sprite();
addChild(container);
scene = new MovieScene3D(container);
オブジェクトを作る

今回は前回のエントリで作った文字オブジェクトを利用します。
文字オブジェクトを作るために必要なマテリアルを生成するメソッドはこうです。

private function get_clip(text:String, color:Number):MovieClip {
  var format:TextFormat = new TextFormat("Impact", obj_h, color);
  var txt_field:TextField = new TextField();
  var mc:MovieClip = new MovieClip();
 
  txt_field.text = String(text);
  txt_field.height = obj_h;
  txt_field.setTextFormat(format);
  format.align = TextFormatAlign.CENTER;
  mc.addChild(txt_field);
 
  return mc;
}

引数に文字列と色を指定すると、そのマテリアルを生成するためのMovieClipを返します。
これを使って文字マテリアルを作ります。

var mc:MovieClip = get_clip(i.toString(), GRAY);
material = new MovieMaterial(mc, true);

このマテリアルを利用してオブジェクトを作成します。

obj = new Plane(material, obj_w, obj_h, obj_segw, obj_segh);

これらの詳細は前回のエントリ「Papervision3DのMovieMaterialを使ってテクスチャを生成する方法」を参照下さい。

オブジェクトをシーンに設置する

2つ目に大切なことは、マウスイベントを取得したいオブジェクトは全て3Dシーン内に設置する必要があるということです。これだと、多重構造のオブジェクトはマウスイベントが取得できない事になります。これについても是非改善してほしい所です。

obj = new Plane(material, obj_w, obj_h, obj_segw, obj_segh);
scene.addChild(obj);

3Dシーンに設置したオブジェクトにマウスイベントを設定します。
オブジェクトが持つコンテナにマウスイベントを付ける必要があります。

obj.container.addEventListener(MouseEvent.CLICK, mouse_click);

あとはmouse_clickという関数を作るだけです。今回はクリックされたオブジェクトの色を変化させることにします。

if(name == "gray") {
  mc = get_clip(num.toString(), BLACK);
  plane.material = new MovieMaterial(mc, true);
  plane.name = "black";
} else {
  mc = get_clip(num.toString(), GRAY);
  plane.material = new MovieMaterial(mc, true);
  plane.name = "gray";
}

オブジェクトの色は簡単にオブジェクトの名前から判別するようにしています。
名前が”black”なら色をGRAY(0xcccccc)に設定し、”gray”ならBLACK(0×999999)に設定します。
上のフラッシュ動画の各オブジェクトをクリックしてみて下さい。色が変化するはずです。

Source Code

ソースコードを公開しておきます。

package {  
  import flash.display.*;
  import flash.events.*;
  import flash.display.Sprite;
  import org.papervision3d.core.proto.*;
  import org.papervision3d.scenes.MovieScene3D;
  import org.papervision3d.objects.Plane;
  import org.papervision3d.materials.MovieMaterial;
  import org.papervision3d.cameras.Camera3D;
  import flash.text.TextField;
  import flash.text.TextFormat;
  import flash.text.TextFormatAlign;
 
  [SWF(
       backgroundColor="0xffffff",
       frameRate="45"
      )]
 
  public class MyPlanes extends Sprite
  {
    //each object parameters
    private var obj_w     :int = 240;
    private var obj_h     :int = 320;
    private var obj_segw  :int = 1;
    private var obj_segh  :int = 1;
 
    //global parameters
    private var obj_num   :int = 10;
    private var radius    :int = 1000;
    private var degree    :Number = 0.0;
    private var GRAY      :Number = 0xcccccc;
    private var BLACK     :Number = 0x999999;
 
    //global object
    private var container :Sprite;
    private var scene     :SceneObject3D;
    private var camera    :CameraObject3D;
    private var objs      :Array;
 
    //--------------------------------------------Constructor
    public function MyPlanes()
    {      
      //ステージ
      this.stage.quality   = "MEDIUM";
      this.stage.scaleMode = "noScale";
      this.stage.align = StageAlign.TOP_LEFT;
      this.stage.addEventListener(Event.ENTER_FRAME, loop);
      this.stage.addEventListener(Event.RESIZE, resize);
 
      //コンテナ生成
      container = new Sprite();
      container.x = this.stage.stageWidth  / 2;
      container.y = this.stage.stageHeight / 2;
      addChild(container);
 
      //シーン生成
      scene = new MovieScene3D(container);
 
      //オブジェクトの生成
      objs = new Array(obj_num);
      for(var i:int=0; i < obj_num; i++) {
        var pos_deg:Number = i * 360 / obj_num;
        var pos_rad:Number = Math.PI * pos_deg / 180;
        var mc:MovieClip = get_clip(i.toString(), GRAY);
        var obj:Plane;
        var material:MaterialObject3D;
 
        material = new MovieMaterial(mc, true);
        obj = new Plane(material, obj_w, obj_h, obj_segw, obj_segh);
        scene.addChild(obj);
        obj.x = radius * Math.cos(pos_rad);
        obj.z = radius * Math.sin(pos_rad);
        obj.name = "gray";
        obj.extra = pos_rad; //original position
        obj.container.name = String(i);
        obj.container.addEventListener(MouseEvent.CLICK, mouse_click);
        objs[i] = obj;
      }
 
      //カメラ設定
      camera = new Camera3D();
      camera.z = -radius * 1.1;
      camera.y = obj_w / 2;
      camera.zoom = 1.1;
 
      this.stage.addEventListener(Event.ENTER_FRAME, loop);
      this.stage.addEventListener(Event.RESIZE, resize);
      resize(null);
    }
 
    //-------------------------------------------get_clip 
    private function get_clip(text:String, color:Number):MovieClip {
      var format:TextFormat = new TextFormat("Impact", obj_h, color);
      var txt_field:TextField = new TextField();
      var mc:MovieClip = new MovieClip();
 
      txt_field.text = String(text);
      txt_field.height = obj_h;
      txt_field.setTextFormat(format);
      format.align = TextFormatAlign.CENTER;
      mc.addChild(txt_field);
 
      return mc;
    }
 
    //-------------------------------------------mouse_click
    private function mouse_click(e:Event):void {
      var num:int = Number(e.currentTarget.name);
      var plane:Plane = objs[num];
      var name:String = plane.name;
      var mc:MovieClip;
      if(name == "gray") {
        mc = get_clip(num.toString(), BLACK);
        plane.material = new MovieMaterial(mc, true);
        plane.name = "black";
      } else {
        mc = get_clip(num.toString(), GRAY);
        plane.material = new MovieMaterial(mc, true);
        plane.name = "gray";
      }
    }
 
    //--------------------------------------------------loop  
    private function loop(e:Event):void {
      var root_rad :Number = Math.PI * degree / 180;
      var rad :Number;
      var rot :Number;
 
      for each(var plane:Plane in objs) {
        rad = root_rad + plane.extra;
        rot = 45 * Math.sin(2 * rad);
        plane.x = radius * Math.cos(-rad);
        plane.z = radius * Math.sin(-rad);
      }
 
      degree += 0.3;
      //再レンダリング
      scene.renderCamera(camera);
    }
 
    //-------------------------------------------------stage
    private function resize(e:Event):void {
      container.x = this.stage.stageWidth  / 2;
      container.y = this.stage.stageHeight / 2;
      camera.focus = this.stage.stageWidth / 6;  
    }
  }
}
おわりに

Papervision3Dの複数オブジェクトにマウスイベントを設置するには少しテクニックが必要であることが分かりました。しかし、回避策が存在しますので、現時点ではそれを選択することで柔軟性は低いものの不可能ではありません。これからのPapervision3Dの改善に期待したいものです。

このエントリをはてなブックマークに登録 Deliciousにブックマーク
関連のありそうなエントリ

Comments:0

Comment Form
Remember personal info

*
To prove that you're not a bot, enter this code
Anti-Spam Image

Trackbacks:0

Trackback URL for this entry
http://www.adamrocker.com/blog/154/papervision3d_many_o.html/trackback/
Listed below are links to weblogs that reference
Papervision3Dで複数のオブジェクトにマウスイベントを付ける方法 from throw Life

Home > papervision3d > Papervision3Dで複数のオブジェクトにマウスイベントを付ける方法

Twitter
Search
Feeds
Meta

Return to page top