Пока что частичное решение @ rvmook является наиболее близким с моей точки зрения.Было бы полезно, если вы используете метод DisplayObjectContainer getObjectsUnderPoint () , чтобы получить список экранных объектов, которые вы переворачиваете, затем циклически просматриваете их и проверяете, какие из них имеют обработчики событий при опрокидывании / наведении курсора мыши, а затем продолжите детализацию.
Таким образом, одним из коротких решений будет:
- Загрузите SWF-файл, который вы хотите узнать, имя этого обработчика ролловера / наведения мыши. *
- Добавьте обработчик ролловера(с пузырьками, установленными в true)
- В обработчике при опрокидывании переберите объекты под мышью, которые имеют обработчики при опрокидывании / наведении курсора, и получите их детали.
Примечание! getObjectsUnderPoint () работает, если загрузочный SWF-файл имеет разрешения от домена, в котором размещен загруженный SWF-файл.Один из способов найти - метод InIncesscessObjectsUnderPoint () .Если у вас есть загруженный SWF-файл, проблем не должно быть.В противном случае вам потребуется либо файл crossdomain.xml в домене, где размещен загруженный SWF-файл, предоставляющий доступ к домену SWF-файла загрузчика (и SWF-файл загрузчика должен передать new LoaderContext(true)
в качестве второго параметра для метода load () объекта Loader), либо использовать сторону сервера.скрипт на выбранном вами языке для прокси / копирования сначала загруженного SWF-файла.
Вот базовый пример того, что я имею в виду:
package{
import flash.display.*;
import flash.events.*;
import flash.geom.Point;
import flash.net.URLRequest;
import flash.sampler.getMemberNames;
public class BasicInfoTest extends Sprite{
private var cursor:Point = new Point();
public function BasicInfoTest(){
init();
}
private function init():void{
var loader:Loader = addChild(new Loader) as Loader;
loader.load(new URLRequest('B.swf'));
addEventListener(MouseEvent.ROLL_OVER,onOver);
}
private function onOver(event:MouseEvent):void{
cursor.x = mouseX;cursor.y = mouseY;
var obj:Array = getObjectsUnderPoint(cursor);
var numObj:int = obj.length;
for(var i:int = 0 ; i < numObj ; i++){//look for objects under cursor that have rollover/mouseover event handlers
if(obj[i].hasEventListener(MouseEvent.ROLL_OVER) || obj[i].hasEventListener(MouseEvent.MOUSE_OVER)){
var members:Object = getMemberNames(obj[i]);//use @rvmook's method to get listeners
for each (var name:QName in members){
if (name.localName == "listeners"){
for (var j : int = 0; j < obj[i][name].length; j++){
var func:Function = obj[i][name][j];
try{
func.call();
}catch(error:Error){
trace('Methods called on mouse over:',error.message.split('on ')[1].split('.')[0]);//parse error message, you might need to adapt this
trace('StackTrace',error.getStackTrace());
}
}
}
}
}
}
}
}
}
Это следует делать, если вам нужно только найтииз названия метода.Если вам нужна дополнительная информация, вы можете получить доступ к байт-массиву загруженного SWF-файла и проанализировать байт-код actionscript, чтобы получить информацию.Я должен признать, что двоичные файлы и ассемблер немного недоступны, но, к счастью, есть отличные библиотеки для декомпиляции SWF-файлов во время выполнения в as3. AS3SWF блестящий, но не имеет большого значения для тегов ActionScript, в то время как as3commons - это большая коллекция библиотек, специализирующихся на аспектах кода.
Вотадаптация предыдущего примера, которая использует библиотеки as3-commons ( байт-код , lang , logging и отражает ) для отображения методаподпись и тело (как инструкции AVM2):
package{
import flash.display.*;
import flash.events.*;
import flash.geom.Point;
import flash.net.*;
import flash.sampler.getMemberNames;
import flash.utils.ByteArray;
import org.as3commons.bytecode.swf.SWFFile;
import org.as3commons.bytecode.swf.SWFFileIO;
import org.as3commons.bytecode.tags.DoABCTag;
public class AdvancedInfo extends Sprite{
private var cursor:Point = new Point();
private var methodInfo:Array;
public function AdvancedInfo(){
init();
}
private function init():void{
var byteLoader:URLLoader = new URLLoader(new URLRequest('B.swf'));
byteLoader.dataFormat = URLLoaderDataFormat.BINARY;
byteLoader.addEventListener(Event.COMPLETE,bytesLoaded);
}
private function bytesLoaded(event:Event):void{
var ba:ByteArray = event.target.data as ByteArray;//get swf bytes
var swfFile:SWFFile = new SWFFileIO().read(ba);//read the bytes using as3-commons
var abcTags:Array = swfFile.getTagsByType(DoABCTag);//get actionscript bytecode (ABC) tags
for each(var tag:DoABCTag in abcTags) methodInfo = tag.abcFile.methodInfo;//loop though tags and get method information
//display and rollOver
var d:Loader = addChild(new Loader()) as Loader;
d.loadBytes(ba);
addEventListener(MouseEvent.ROLL_OVER, rolledOver,true,0,true);
}
private function getMethodDetails(methodName:String):String{
var result:String = '';
for(var i:int = 0 ; i < methodInfo.length; i++){
if(methodInfo[i].methodName == methodName){
result += 'signature:\t'+methodInfo[i]+'\n';
result += 'body:\t'+methodInfo[i].methodBody;
return result;
}
}
return result;
}
private function rolledOver(event:MouseEvent):void{
cursor.x = mouseX;cursor.y = mouseY;
var obj:Array = getObjectsUnderPoint(cursor);
var numObj:int = obj.length;
for(var i:int = 0 ; i < numObj ; i++){
if(obj[i].hasEventListener(MouseEvent.ROLL_OVER) || obj[i].hasEventListener(MouseEvent.MOUSE_OVER)){
var members:Object = getMemberNames(obj[i]);
for each (var name:QName in members){
if (name.localName == "listeners"){
for (var j : int = 0; j < obj[i][name].length; j++){
var func:Function = obj[i][name][j];
try{
func.call();
}catch(error:Error){
var methodName:String = error.message.split('on ')[1].split('.')[0].split('/')[1].split('()')[0];
trace(getMethodDetails(methodName));
}
}
}
}
}
}
}
}
}
Для целей документирования вот код загруженного SWF-файла:
package {
import flash.events.*;
import flash.display.*;
public class B extends Sprite {
public function B() {
addEventListener(Event.ADDED_TO_STAGE, init)
}
private function init(event:Event = null) : void {
for (var i : int = 0; i < 1000 ; i++) {
var b:Sprite = addChild(new Sprite()) as Sprite;
b.graphics.lineStyle(Math.random()*3);
b.graphics.drawCircle(-3, -3, 3);
b.x = 3+Math.random() * stage.stageWidth - 6;
b.y = 3+Math.random() * stage.stageHeight - 6;
b.buttonMode = true;
b.addEventListener(MouseEvent.ROLL_OVER, onRollOver);
}
}
private function onRollOver(event : MouseEvent) : void {
event.currentTarget.scaleX = event.currentTarget.scaleY = .1 + Math.random() * 2.1;
}
}
}
, а вот пример детальной трассировки метода с использованиемgetMethodDetails в моем примере AdvancedInfo:
signature: private function QName[Namespace[private::B]:onRollOver](QName[Namespace[public::flash.events]:MouseEvent]) : QName[Namespace[public]:void]
body:
private function QName[Namespace[private::B]:onRollOver](QName[Namespace[public::flash.events]:MouseEvent]) : QName[Namespace[public]:void]
{
//maxStack=5, localCount=3, initScopeDepth=9, maxScopeDepth=10
0:debugfile [/Users/george/Documents/Flex Builder 3/Del/src;;B.as]:2
2:debugline [28]:4
4:getlocal_0 :5
5:pushscope :6
6:debug [1, 18, 0, 28]:11
11:debugline [29]:13
13:getlocal_1 :14
14:getproperty [QName[Namespace[public]:currentTarget]]:16
16:getlocal_1 :17
17:getproperty [QName[Namespace[public]:currentTarget]]:19
19:pushdouble [0.1]:21
21:getlex [QName[Namespace[public]:Math]]:23
23:callproperty [QName[Namespace[public]:random], 0]:26
26:pushdouble [2.1]:28
28:multiply :29
29:add :30
30:dup :31
31:setlocal_2 :32
32:setproperty [Multiname[name=scaleY, nsset=[Namespace[private::B], Namespace[public], Namespace[private::B.as$25], Namespace[packageInternalNamespace], Namespace[namespace::http://adobe.com/AS3/2006/builtin], Namespace[protectedNamespace::B], Namespace[staticProtectedNamespace::B], Namespace[staticProtectedNamespace::flash.display:Sprite], Namespace[staticProtectedNamespace::flash.display:DisplayObjectContainer], Namespace[staticProtectedNamespace::flash.display:InteractiveObject], Namespace[staticProtectedNamespace::flash.display:DisplayObject], Namespace[staticProtectedNamespace::flash.events:EventDispatcher], Namespace[staticProtectedNamespace::Object]]]]:34
34:getlocal_2 :35
35:kill [2]:37
37:setproperty [Multiname[name=scaleX, nsset=[Namespace[private::B], Namespace[public], Namespace[private::B.as$25], Namespace[packageInternalNamespace], Namespace[namespace::http://adobe.com/AS3/2006/builtin], Namespace[protectedNamespace::B], Namespace[staticProtectedNamespace::B], Namespace[staticProtectedNamespace::flash.display:Sprite], Namespace[staticProtectedNamespace::flash.display:DisplayObjectContainer], Namespace[staticProtectedNamespace::flash.display:InteractiveObject], Namespace[staticProtectedNamespace::flash.display:DisplayObject], Namespace[staticProtectedNamespace::flash.events:EventDispatcher], Namespace[staticProtectedNamespace::Object]]]]:39
39:debugline [30]:41
41:returnvoid :42
}
traits=(no traits)
Для получения дополнительной информации о инструкциях AVM2 см. документацию или спецификации формата SWF-файла (ссылка в формате PDF).
Другие варианты, включающие стороннее программное обеспечение, которое я не полностью изучил, были бы:
- Использование FlashFirebug - Лично мне не удалось запустить егоможет я ненастроить правильно.
- Используйте getObjectsUnderPoint для трассировки информации об объектах (имя экземпляра / и т. д.) с помощью обработчиков ролловера / наведения мыши, а затем используйте коммерческий декомпилятор для поиска обработчика с использованием полученной информации.
НТН