イナヅマTVログ

ActionScript 3.0, AS2ライクにDuplicateMovieclipをするために

| 4件のコメント

以前のエントリー。
DisplayObject['constructor'] as Class を使えば ActionScript 2 の DuplicateMovieclip みたいなことができるかもって記事です。

で、実際に DuplicateMovieclip みたいにするためにはプロパティを全コピー出来ないと duplicate にはなりません。
あの膨大なプロパティをどうやったらコピーできるかと悶々してたら Google 先生が教えてくれました。

kirupa.com にそのものズバリがありました。
http://www.kirupa.com/forum/showthread.php?p=1939827

package com.senocular.display {
 
	import flash.display.DisplayObject;
	import flash.geom.Rectangle;
 
	/**
	 * duplicateDisplayObject
	 * creates a duplicate of the DisplayObject passed.
	 * similar to duplicateMovieClip in AVM1
	 * @param target the display object to duplicate
	 * @param autoAdd if true, adds the duplicate to the display list
	 * in which target was located
	 * @return a duplicate instance of target
	 */
	public function duplicateDisplayObject(target:DisplayObject, autoAdd:Boolean = false):DisplayObject {
		// create duplicate
		var targetClass:Class = Object(target).constructor;
		var duplicate:DisplayObject = new targetClass();
 
		// duplicate properties
		duplicate.transform = target.transform;
		duplicate.filters = target.filters;
		duplicate.cacheAsBitmap = target.cacheAsBitmap;
		duplicate.opaqueBackground = target.opaqueBackground;
		if (target.scale9Grid) {
			var rect:Rectangle = target.scale9Grid;
			// WAS Flash 9 bug where returned scale9Grid is 20x larger than assigned
			// rect.x /= 20, rect.y /= 20, rect.width /= 20, rect.height /= 20;
			duplicate.scale9Grid = rect;
		}
 
		// add to target parent's display list
		// if autoAdd was provided as true
		if (autoAdd && target.parent) {
			target.parent.addChild(duplicate);
		}
		return duplicate;
	}
}

x, y… などのプロパティをコピーするのに DisplayObject.transform をつかうのかぁ。
transform でコピーできないプロパティは個別に設定するのか。

使い方は

import com.senocular.display.duplicateDisplayObject;
 
// create duplicate and assign to newInstance variable
// using true for autoAdd automatically adds the newInstance
// into the display list where myOldSprite is located
var newInstance:Sprite = duplicateDisplayObject(myOldSprite, true);
newInstance.x += 100; // shift to see duplicate

ご存知、senocularさんの投稿です。

ためになるなぁ。

update 2011-01-17
muta244さんのコメントのByteArrayを使う方法はreadObjectをキャストすると戻り値がnullになり残念ながら使えないようです。
キャストしないと戻り値型はObjectになりプロパティ値にアクセスすることは可能です。
ただインスタンスそのものを再利用したいのでこの方法だと役不足でした。

import flash.utils.ByteArray;
import flash.display.Sprite;
 
var original:Sprite = new Sprite();
original.graphics.clear();
original.graphics.beginFill(0xffff00);
original.graphics.drawRect(0, 0, 30, 30);
original.graphics.endFill();
addChild(original);
original.x = 100;
 
var data:ByteArray = new ByteArray();
data.writeObject(original);
data.position = 0;
 
var copy:Object = data.readObject();
trace(copy.x); // 100
 
data.position = 0;
var copy2:Sprite = data.readObject();
trace(copy2.x); // TypeError: Error #1034: 強制型変換に失敗しました。Object@3ce16d79 を flash.display.Sprite に変換できません。
 
data.position = 0;
var copy3:Sprite = data.readObject() as Sprite;
trace(copy3.x); // TypeError: Error #1009: null のオブジェクト参照のプロパティまたはメソッドにアクセスすることはできません。

タイムラインに配置したMCや生成したSpriteをByteArrayを使って再利用はどうも無理っぽい。

4件のコメント

  1. 先生、ご無沙汰してます!
    こんな方法もあります。


    var original:Sprite = new Sprite();
    original.x = 100;

    var data:ByteArray = new ByteArray();
    data.writeObject(original);
    data.position = 0;

    var copy:Sprite = b.readObject() as Sprite;
    trace(copy.x); // 100

    ただ、どちらの方法にしろ、
    private なプロパティはコピー出来ない気がするので(すいません、検証していないです)、
    注意は必要そうですね。

  2. すいません、一カ所訂正です。

    × var copy:Sprite = b.readObject() as Sprite;
    ○ var copy:Sprite = data.readObject() as Sprite;

  3. 久しぶり、元気そうでなにより。

    ByteArrayを使う方法は試したけど、readObjectの戻り値がnullになっちゃうんだけど。

  4. ピンバック: Actionscript 3.0, AS2ライクにDuplicateMovieclipをするために2 – 完全に複製できない | イナヅマtvログ

コメントを残す

必須欄は * がついています