使用类级嵌入访问 MainTimeline 符号

发布于 2024-12-28 05:26:47 字数 2168 浏览 3 评论 0原文

场景如下:

我们有一个在 Flash CS5.5 中运行并生成包含图形元素和 Actionscript 代码的 SWF 资源的创意团队,以及一个编写 .as 文件并构建“代码 SWF”的工程团队。代码 SWF 文件必须加载或嵌入创意资源并与其中的代码交互,以便我们的应用程序正常运行。

对于 iOS 移动开发,还有另一个考虑因素 - 由于 Apple TOS,无法在 iOS 的 AIR 应用程序包中加载运行时代码(请参阅 相关问题)。因此,不可能使用 Loader 在 iOS 环境中加载 SWF 并保留其代码。

以标准方式将 SWF 嵌入到 ActionScript 文件中会产生一个将嵌入的 SWF 直接作为字节加载的加载器。这会导致对顶层主时间线的访问,如下所示:

[Embed(source="embed_test.swf")]
  private var no_aot_support:Class;

public function main():void
{
  var no_ios:* = new no_aot_support();
  addChild(no_ios);
  no_ios.addEventListener(Event.COMPLETE, function():void {
    var timeline:MovieClip = no_ios.getChildAt(0).getChildAt(0);
    trace(timeline.foo); // foo variable exists, output is 'blah'
  });
}

但是,这种嵌入机制在 iOS 设备上不起作用,因为 Apple 的 TOS 不允许运行时代码 - 所有代码都必须提前通过编译器(AOTCompiler)在编译时,而通过这种方式嵌入的SWF不符合这个标准。

经过询问,我发现可以使用类级嵌入来解决这个问题,因为类级嵌入确实会通过编译器,并会在 iOS 下产生工作代码:

package
{
  import flash.display.MovieClip;

  [Embed(source="embed_test.swf", symbol="Symbol1")]
   public final dynamic class anim extends MovieClip { };
}

这工作正常,但我不想引用SWF 中的符号,我想要整个 swf(又名引用主时间线),但以下结果会导致编译器错误:

package
{
  import flash.display.MovieClip;

  [Embed(source="embed_test.swf")]
   public final dynamic class anim extends MovieClip { };
}

我还反编译了 SWF,找到了主时间线符号,并尝试了此操作:

package
{
  import flash.display.MovieClip;

  [Embed(source="embed_test.swf", symbol="embed_test_fla.MainTimeline")]
   public final dynamic class anim extends MovieClip { };
}

但编译器坚持这样做符号不存在。

由于我有很多很多 SWF 资源,因此我需要一个不涉及更改整个工作流程(即进入每个 FLA 并进行更改)的解决方案。这应该是可能的,如果不可能,这就是 Adob​​e 应该解决的工作流程问题。

所以我在这里陷入困境 - 常规嵌入获取 MainTimeline 但在 iOS 中不起作用,类级嵌入在 iOS 中工作但无法访问 MainTimeline。

请随意下载我的示例项目并使用它。

Here's the scenario:

We have a creative team that operates in Flash CS5.5 and produces SWF assets which have both graphics elements and actionscript code in them, and an engineering team which authors .as files and builds "code SWFs". The code SWF files must load or embed the creative assets and interact with the code therein for our apps to function.

For iOS mobile development, there is another consideration - it is not possible to load runtime code in an AIR app packages for iOS because of Apple TOS (see related question). Hence, it is not possible to use a Loader to load SWFs in an iOS environment and retain their code.

Embedding a SWF into an ActionScript file the standard way results in a Loader that loads the embedded SWF directly as bytes. This results in access to the top-level, main timeline as follows:

[Embed(source="embed_test.swf")]
  private var no_aot_support:Class;

public function main():void
{
  var no_ios:* = new no_aot_support();
  addChild(no_ios);
  no_ios.addEventListener(Event.COMPLETE, function():void {
    var timeline:MovieClip = no_ios.getChildAt(0).getChildAt(0);
    trace(timeline.foo); // foo variable exists, output is 'blah'
  });
}

However, this embedding mechanism doesn't work on iOS devices because runtime-code is not allowed per Apple's TOS - all code must be passed through the ahead-of-time compiler (AOTCompiler) at compile-time, and the SWF embedded in this way does not meet this criteria.

Asking around, I found that one can use a class-level embed to get around this, as a class-level embed does go through the compiler and will result in working code under iOS:

package
{
  import flash.display.MovieClip;

  [Embed(source="embed_test.swf", symbol="Symbol1")]
   public final dynamic class anim extends MovieClip { };
}

This works fine, but I don't want to reference a symbol in the SWF, I want the whole swf (aka reference the main timeline), but the following results in a compiler error:

package
{
  import flash.display.MovieClip;

  [Embed(source="embed_test.swf")]
   public final dynamic class anim extends MovieClip { };
}

I've also decompiled the SWF, found the main timeline symbol, and tried this:

package
{
  import flash.display.MovieClip;

  [Embed(source="embed_test.swf", symbol="embed_test_fla.MainTimeline")]
   public final dynamic class anim extends MovieClip { };
}

But the compiler insists this symbol doesn't exist.

Since I have many, many SWF assets, I need a solution that doesn't involve changing my whole workflow (i.e. going into each FLA and making changes). This should be possible, and if not, this is a workflow problem Adobe should address.

So here I am stuck - regular embeds get the MainTimeline but don't work in iOS, class-level embeds work in iOS and can't access the MainTimeline.

Feel free to download my expample project and play with this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

自由如风 2025-01-04 05:26:47

将对象放置在主时间轴上始终会在 SWF 文件中生成生成的代码:Flash IDE 会生成应用程序运行所需的所有代码,也就是说,它会创建要放置的文档类的实例运行时在舞台上。然而,这是无法访问的代码,除非通过加载器对象加载 SWF - 无论使用 [Embed] 还是生成 SWC 都不允许这样做。

我尝试过导出 SWC,因为像 @32bitkid 一样,我相信这是绕过限制的一种方法。事实证明,您可以实例化文档类,即使您没有显式声明文档类并让 IDE 自动生成它。但遗憾的是,所有舞台实例都消失了。 :( 您还可以声明一个自定义文档类并使用 addChild() 将您的库对象放置在舞台上 - 然后一切正常。但是您在 IDE 的主时间轴上执行的任何操作,这

也是有道理的:这些对象实际上是放置在主时间轴实例上的。 MyDocumentClass(),你是创建一个新实例 - 还没有任何成员 -

奇怪的是,所有这些对于任何库对象都应该是正确的 - 将对象实例放置在库对象时间轴中也应该需要代码生成,而不应该。 - 但它确实完全不一样:您在库对象中放置在舞台上的任何内容都将仍然存在,并且当您调用 new MyLibraryObject(); 时可以访问所以

我看到的唯一方法 。您的项目工作是让您的设计人员在每个 FLA 库中创建一个唯一命名的“时间轴”MovieClip(或 Sprite),并将其导出到 ActionScript。 (您不能总是使用“时间轴”,因为这样在使用多个 SWC 时就会出现命名冲突)然后,该“时间轴”用于将任何必要的对象直接放置在舞台上、添加帧代码等。在其中,设计人员可以完全按照他们习惯的方式工作,除了设备硬件和可用的 API 之外没有任何限制。唯一真正的区别是 FLA 本身的主时间线上不可能存在任何东西。

然后,您可以使用 SWC 方法(这比手动生成 [嵌入] 代码要简单得多)并在主应用程序中实例化“时间轴”符号 - 一切都应该在您需要的地方。

Placing objects on the main timeline always produces generated code in an SWF file: The Flash IDE generates all the necessary code for your application to run, that is, it creates an instance of the document class to be placed on the stage at runtime. This, however, is code that can not be accessed, unless the SWF is loaded via a loader object - neither using [Embed], nor generating an SWC will allow it.

I've tried exporting an SWC, because like @32bitkid I believed this to be a way around the restrictions. And as it turns out, you can instantiate the document class, even if you don't explicitly declare one and have the IDE auto-generate it. But alas, all the stage instances are gone. :( You can also declare a custom document class and place your library objects on the stage using addChild() - then it all works fine. But anything you'll do on the main timeline in the IDE, you can't access. Ever.

This makes sense, too: The objects are in fact stage instances placed on the main timeline instance. But once you call new MyDocumentClass(), you are creating a new instance - which does not have any members yet.

The strange thing is, that all of this should be true for any library objects, as well - placing object instances within a library object timeline should also require code generation, shouldn't it? - but it really isn't the same at all: Anything you've placed on the stage in your library object will still exist and be accessible when you call new MyLibraryObject();.

So. The only way I see for your project to work is that you make your designers create a uniquely named "Timeline" MovieClip (or Sprite) in the library of every FLA and export that for ActionScript. (You can't always use "Timeline", because then you'd have naming conflicts when working with more than one SWC) This "Timeline" is then used to place any necessary objects directly on the stage, add frame code, etc. Within it, the designers can work exactly the way they are used to, without any restrictions other than device hardware and available API. The only real difference is that nothing can ever exist on the main timeline of the FLA itself.

You can then use the SWC approach (which is a lot less tedious than manually producing [Embed] code) and instantiate the "Timeline" symbol from within the main application - everything should be right where you need it.

晨敛清荷 2025-01-04 05:26:47

我正在发布我自己的解决方法来解决这个问题,以防万一这个问题发生:

这里有更详细的回复:是否可以嵌入或加载制作 iPhone 应用程序时使用 SWF(Apple 是否允许)

我创建了一个工具,通过将嵌入式 SWF 合并到主 SWF 中来解决此问题。通过这种方式,嵌入内容经过 AOT 编译并转换为 Objective-C 代码,因此我获得了资产的实例(主时间线),并且资产的代码经过正确的交叉编译以在 iOS 设备上运行。

它通过使用如下嵌入来工作:

[Embed(source="GameLevel.swf")]
  private var GameLevel:Class;

public function main():void
{
  var my_level:* = new GameLevel();
  addChild(my_level);
}

在这种情况下,如果 gameLevel.swf 中有代码,它通常在 iOS 中不起作用,因为 new gameLevel() 将创建一个 Loader 并解释 SWF 字节码。但是,如果您首先通过我的名为 SWFMerge 的工具运行上述 SWF,它将获取您的嵌入式 SWF 并将其合并到您的根 SWF 中。然后 ADT 会将您的主 swf(包括嵌入代码)编译为 Objective-C,它将在 iOS 上运行,并注意:new gameLevel() 现在直接生成您的资产实例 - 而不是加载器。

SWFMerge 工具位于:

http://www.onetacoshort.com/temp/SWFMerge_alpha.swf< /a>

请在评论中告诉我此解决方法是否适合您或者您是否遇到问题。

我要补充一点,使用 SWC 工作流程更好并且得到官方支持,但是当您没有原始 FLA 源文件,或者只是想快速使用其中包含代码的现有资源时,这种解决方法非常有用。

I'm posting my own workaround to this problem, in case any happens by this question:

There is a more details response here: Is it possible to embed or load SWFs when making iphone apps (Is it allowed by Apple)

I've created a tool to workaround this issue by merging embedded SWFs into the main SWF. In this way, the embeds are AOT-compiled and converted into objective-c code, so I get an instance of my asset (the main timeline), and the asset's code is properly cross-compiled to work on iOS devices.

It works by using an embed like this:

[Embed(source="GameLevel.swf")]
  private var GameLevel:Class;

public function main():void
{
  var my_level:* = new GameLevel();
  addChild(my_level);
}

In this scenario, if gameLevel.swf has code in it, it typically wouldn't work in iOS, because new gameLevel() would create a Loader and interpret SWF bytecode. But, if you first run the above SWF through my tool called SWFMerge, it will take your embedded SWF and merge it into your root SWF. Then ADT will compile your main swf (including embedded code) into objective-C, it will work on iOS, and note: new gameLevel() now results directly in an instance of your asset - NOT a Loader.

The SWFMerge tool is here:

http://www.onetacoshort.com/temp/SWFMerge_alpha.swf

Let me know in the comments if this workaround works for you or if you have trouble.

I'll add that using a SWC workflow is better and officially supported, but this workaround is great in a pinch when you either don't have the original FLA source file, or simply want to quickly use existing assets with code in them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文