私は AS3 プロジェクトに取り組んでおり、近い将来に多くのリファクタリングが必要になる特に壊れやすい部分に苦労しています。個別のクラスを個別に単体テストするだけでは、遭遇しているすべての問題を把握できるわけではありません。たとえば、透明なオーバーレイでマウス イベントを無効にするのを忘れて、ボタンのすべてのクリックをブロックすることがあります。したがって、実際のユーザー入力をシミュレートするテストを作成しようとしています。
MouseEvent をステージの正しい位置に手動で送信しようとしました。
stage.dispatchEvent(new MouseEvent(MouseEvent.CLICK, true, true, 380, 490, stage));
ステージにはクリック イベント ハンドラーがないため、イベントが階層を介して実際に処理するボタンに伝達されることを期待していました (マウスを物理的にクリックしたときと同様)。しかし、そうではありません。
ボタンでイベントをディスパッチできることはわかっていますが、オブジェクトが何らかの形で遮られているかどうかは検出されません。マウス イベントをシミュレートして、階層全体に適切に伝達する方法はありますか?
編集: Flashの伝播動作を再実装することで、なんとかそれを行うことができました:
編集 2: いくつかのシェイプを含むスプライトのように、クリック ハンドラーを含む部分的に透明なオーバーレイがある場合、以前のソリューションは機能しませんでした。問題は、問題のオブジェクトがその時点で完全に透過的であっても、hitTestPoint メソッドが true を返すことです。したがって、実際のピクセル値を確認するように変更しました。
private function clickObject(obj:DisplayObject) : void
{
var relPos:Point = new Point(obj.width / 2, obj.height / 2);
var globalPos:Point = obj.localToGlobal(relPos);
simulateClick(obj.stage, globalPos);
}
private function simulateClick(obj:InteractiveObject, globalPos:Point) : Boolean
{
// first, check if we have any children that would rather handle the event
var container:DisplayObjectContainer = obj as DisplayObjectContainer;
if (container != null)
{
if (container.mouseChildren)
{
for (var i:int = 0; i < container.numChildren; ++i)
{
var child:DisplayObject = container.getChildAt(i);
var interactive:InteractiveObject = child as InteractiveObject;
if (interactive != null)
{
if (simulateClick(interactive, globalPos))
{
// if we have found a handler in the children, we are done
return true;
}
}
}
}
}
if (!obj.mouseEnabled) {
return false;
}
if (obj.hitTestPoint(globalPos.x, globalPos.y))
{
var localPos:Point = obj.globalToLocal(globalPos);
// check if object is visible at the clicked location
var pixel:BitmapData = new BitmapData(1, 1);
pixel.draw(obj, new Matrix(1, 0, 0, 1, -localPos.x, -localPos.y));
var color:uint = pixel.getPixel32(0, 0);
if ((pixel.getPixel32(0, 0) & 0xff000000) != 0)
{
// if yes, dispatch the click event
var e:MouseEvent = new MouseEvent(MouseEvent.CLICK, true, true, localPos.x, localPos.y, obj);
obj.dispatchEvent(e);
return true;
}
}
return false;
}
残念ながら、カバーされていないケースが少なくとも 1 つあります。それは、オブジェクトが別のオブジェクトのマスクである場合です。表示階層のどこでもマスクになる可能性があるため、これを確認する方法がわかりません。これを見つけるには、ツリー全体を走査し、すべての表示オブジェクトをチェックする必要があります。
だから、私の質問は残っています:これを行う簡単な方法はありませんか?