Flash
2014年05月10日 15:16GMT+8
可以说 haxe 的目标平台最稳定的就是 flash 平台了
-
flash.Lib 提供几个方法,也许会很有用, 如:
// 在浏览器中将 trace 输出到浏览器的 console // 当你的 flash 需要在浏览器中调试时这非常有效 Lib.redirectTraces() // 调用 flash 原生的 trace,例如当你在处于 Worker 时,就能能用这个方法了 // 如果你用 flashdevelop 可以在 视图 -> flash 日志视图里看到输出, Lib.trace(arg:Dynamic) // 或者加上 -D fdb 参数将重定向所有 trace 语句
跨域安全沙箱错误
crossdomain.xml
中文参考: http://www.adobe.com/cn/devnet/adobe-media-server/articles/cross-domain-xml-for-streaming.html
很可能需要添加编译参数 -D network-sandbox
使得 swf 只能访问网络.
注意: 使用 Workder
时,工作线程总是为 只访问网络.
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="all" />
<allow-access-from domain="*" />
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>
编译
仅针对 flash 平台, 这个清单可能并不完整, 详细通过 haxe --help
查询
# 将 hx 源码直接编译成 swf 文件
haxe -swf out.swf -main Main
# 将 hx 源码打包成 swc, 将输出文件名改为 swc, 并且不需要指定 -main 参数
# 其它一些细节后边再述
haxe -swf out.swc Main.hx
# 将 hx 源码编译成 as3 文件, 通过 -as3 并指定 outdir 目录,注意: 生成的代码仅供参考
haxe -as3 outdir -main Main
调试
在编译时指定 -D fdb
, 这时 trace 将不再以 Textfiled 的形式输出了
相关命令行参数
用于 haxe 命令行参数
# 更严格的类型检测, 反正加上就是
--flash-strict : more type strict flash API
# 指定 flash 版本, 例: -swf-version 10.3, 或 -swf-version 11.6
-swf-version <version> : change the SWF version
# 指定 flash 文件头, 例 : -swf-header 800:600:FFFFFF
-swf-header <header>: define SWF header (width:height:fps:color)
# 添加 swf 库, 文件通常为 swc 格式
-swf-lib <file> : add the SWF library to the compiled SWF
#
-swf-lib-extern <file> : use the SWF library for type checking
# (个人认为)实际上这是被弃用的, 见补充说明小节,
--gen-hx-classes : generate hx headers for all input classes
关于 flash 版本的问题, haxe 的 -swf-header 使用第一行的样式, 其实可以查看 flashdevelop 的 flash生成项目属性可以看得能够生成哪些版本
f: 9.0 10.0 10.1 10.2 10.3 11.0 11.1 ~ 11.9 12.0 13.0 14.0 15.0 16.0 17.0
i: 9 10 10 11 12 13 14 ~ 22 23 24 25 26 27 28
Defines
通过 -D
或相关宏定义的值
# 启用交互式调试的 Flash 内容。它在 SWF 输出中包含调试器标记,并添加额外的调试信息。
# 这也将把 trace 输出重定向到 flashlog.txt, 而不是 swf 中的 Textfiled
fdb : Enable full flash debug infos for FDB interactive debugging
# 使用 `haxe` 名, 作为 flash 的引导类名, 替换掉默认的 boot_xxx 名, 这项定义将会 自动用于编译成 swc 时
haxe-boot : Given the name 'haxe' to the flash boot class instead of a generated name
# 更改 flash 网络沙箱模式, 定义后将为 只访问网络, 默认为只访问本地
network-sandbox : Use local network sandbox instead of local file access one
# 禁用 swf 压缩
no-swf-compress : Disable SWF output compression
# flash 硬件加速 第 1 级 - 直接
swf-direct-blit : Use hardware acceleration to blit graphics
# flash 硬件加速 第 2 级 - GPU
swf-gpu : Use GPU compositing features when drawing graphics
## 注: swf-gpu 和 swf-direct-blit 只适用于 Flash Player 独立播放器时
## 当 位于浏览器中播放时, swf-direct-blit 对应 wmode="direct", 而 swf-gpu 则是 wmode="gpu"
# 嵌入元数据 xml文件到 swf,以便搜索引擎检索信息, 示例: -D swf-metadata=data.xml
# 元数据 xml文件 格式参见 http://www.adobe.com/products/xmp.html
swf-metadata : =<file> Include contents of <file> as metadata in the swf.
# 示例: http://old.haxe.org/doc/flash/preloader
swf-preloader-frame : Insert empty first frame in swf, To be used together with -D flash-use-stage and -swf-lib
# 配合 swf-preloader-frame 的.
flash-use-stage : Keep the SWF library initial stage. To be used together with -swf-lib. Place objects found on the stage of the SWF lib. (Not to be used together with -swf-header)
# 编译时将 private 属性将变成 protected 而不是 public
# 实际上 hx 中的 private 仅仅只用于限制 hx 代码, 生成 swf 后, 都为 public
swf-protected : Compile Haxe private as protected in the SWF instead of public
# 设置 swf 超时时间
swf-script-timeout : Maximum ActionScript processing time before script stuck dialog box displays (in seconds)
# ???
swf-use-doabc : Use DoAbc swf-tag instead of DoAbcDefine
# 添加 Scout (aka Monocle) 支持. Since SVN r5429
advanced-telemetry : Allow the SWF to be measured with Monocle tool
# 编译时将 private 属性将变成 protected 而不是 public
# 实际上 hx 中的 private 仅仅只用于限制 hx 代码, 生成 swf 后, 都为 public
swf-protected : Compile Haxe private as protected in the SWF instead of public
Metas
标记在源码上的特殊元数据
@:bind : 覆盖 flash 的同名定义, 当在 Haxe 中声明了一个类(不是extern类)已经存在于 SWF 库, 将会报错.
@:setter(property) : 示例: 见补充说明的 "override flash"
@:getter(property) : 同 @:setter
@:meta : 生成相应的 Flash 元数据, 例: @:meta(Event(name="test",type="Foo")).
@:ns("namespace") :指定的字段或方法的命名空间
@:sound : 用于嵌入声音,
例: @:sound("blit.mp3") class MySound extends flash.media.Sound{}
@:file : 以 ByteArray 的方式嵌入文件,
例: @:file("a.dat") class MyByteArray extends flash.utils.ByteArray{}
@:font : 嵌入字体,仅限 ttf. 第二个参数为可选字符,而不是全部字符
例: @:font("font/ceri0553.ttf", "a-zA-Z0-9~!@#$%^&*()_+=-][}{.,;\":><") class MyFont extends Font { }
@:bitmap : 以 bitmapData 形式嵌入图片,
例: @:bitmap("path/logo.png|jgp|gif") class MyBitmapData extends flash.display.BitmapData{}
黑魔法
用于直接在 haxe 中直接写 AS3 代码. 参看 http://old.haxe.org/doc/advanced/magic 由于太多这里就不全部列出了.
# __global__ 调用 as3 的全局成员
untyped __global__["undefined"];
untyped __global__["uint"]; //basic type
untyped __global__["flash.display.DisplayObject"];
# 创建 as3 源生类
__new__(className, arg1, arg2 ...)
__keys__(obj) # 将构建一个数组包含 obj 的 keys. 例: for(k in __key__(obj))
__delete__(o, f) # delete o.f
__in__ (e,f) # e in f
__is__(e, t) # e is t
__has_next__(o, i) # 见 ds.unsafeStringMap, 这个将会修改 i 的值
__forin__(o, index) # 复制 UnsafeIntMapValuesIterator 即可用.
__foreach__(o, index)#
# 对于 flash 平台, 使用 __keys__ 遍历要比使用 Reflect.Fields 要更有效率
var obj = Lib.current.stage.loaderInfo.parameters;
for(k in untyped __keys__(obj)){
trace(k +": "+untyped obj[k]);
}
extern class
haxe 能直接引用并解析 AS3 的 swc 库, 因此没特别的地方(参看 patch files)根本不需要写 extern class;
swc
导出
一些参考 https://github.com/jcward/HaxeSWCExample 和 http://old.haxe.org/manual/swc?lang=cn , 示例:
# 单个文件或多个文件, 每个 hx 文件不要带有扩展名, 因为会与包名混淆
# A, B C 分别代表 A.hx B.hx com/some/C.hx....
haxe -swf bin/hxlib.swc A B com.some.C
# 导出整个文件夹, 这种方法仅用于导出带有 **包名** 的整个目录.
# 参考 haxe.macro.Compiler.include 方法
haxe -swf bin/hxlib.swc --macro "include('com.some')"
NOTE: 在 AS3 中使用 haxe 导出的 swc 库.需要初使化 haxe.initSwc(root_sprite)
引用
在 haxe 引用 AS 的 swc 的外部库很简单, 只要指编译参数 -swf-lib libname.swc
就行了,
haxe -main Test -swf-lib libname.swc -swf Test.swf
如果你使用 openfl, 那么则在 project.xml 中配置
<haxeflag name="-swf-lib" value="pathto/libname.swc" if="flash" />
错误 1: You cannot have both a static and a non static member or function with the same name…
问题解决原文, 需要建一个 patch 文件如:
// haxe 调用 starling.swc 示例
// 将这个文件 保存为 Starling.patch 或其它任意文件名.
// 项目中添加 haxeflag 编译选项 --macro "patchTypes('Starling.patch')"
-starling.core.RenderSupport.clear
-starling.core.Starling.context
-starling.core.Starling.juggler
-starling.core.Starling.contentScaleFactor
错误 2: 当调用 flash alchemy 打包的 swc 库时,将会出错,
但使用 -debug
编绎选项却能通过. 问题#1976
此问题已经解决, 只是还没合并
patch files
当在 haxe 中调用 flash 的 swc 库时, haxe 编译器能自动提取里边的定义,虽然大多数情况下不会造成问题,
但在某些情况下你可能必须创建 patch file, patch file 将修改 flash库中已经存在类的字段类型,
// Removes a class field from Haxe definition
-flash.accessibility.Accessibility.new
// Adds metadata to a given class
@:require(flash10) flash.desktop.Clipboard
// Adds metadata to a given class field
@:require(flash10) flash.display.BitmapData.setVector
// Modifies a given field type
flash.display.DisplayObject.blendMode : BlendMode;
// Modifies a static field type
static flash.system.IME.conversionMode : IMEConversionMode;
// Modifies all function parameters with this specific name
flash.display.BitmapData.$blendMode : BlendMode;
// Modifies a single function parameter
ClassName.$functionName__parameterName : Type;
// Convert a class made of statics vars into an Haxe enum
enum flash.text.TextFieldAutoSize;
大量这样的例子可以从 this patch file 获取,这对是对flash的定义的一个补充。
You can use a patch file with –macro patchTypes(‘patchFile’)
自定义 Preloader
总的来说不算太复杂, 只是需要一些耐心
-
openfl 项目,
haxepunk
库源码有一个很好的示例.<app preloader="MyPreloader" /> <!-- 源码中必须能查找得到MyPreloader这个类,也可以指定包名如: --> <app preloader="com.myname.Preloader" />
补充
override flash
覆盖 flash 的 setter 时要注意 返回值类型应该为 Void, 而 Haxe 的 setter 却应返回对应类型.
class LEByteArray extends ByteArray{
public function new(len:UInt) {
super();
super.length = len;
super.endian = Endian.LITTLE_ENDIAN;
}
override public function clear():Void {}
@:setter(length) function set_length(len:UInt):Void {
if(len > super.length){
super.length = len;
}else if(len < super.length ){
throw 'You are not allowed to change the length.';
}
}
@:setter(endian) function set_endian(endian:String):Void {
//throw new Error( 'You are not allowed to change the endian.' );
throw 'You are not allowed to change the endian.';
}
}
–gen-hx-classes
解析 swc 库,并自动生成库中所有类的 extern class, 但是目前 haxe3 已经可以直接使用 flash 的 swc 库, 不需要做这多余的步骤了. 所以不用关心这个能做什么.
haxe -swf nothing.swf --no-output -swf-lib lib.swc --gen-hx-classes
SWF文件结构
SWF = HEADER + TAGS
, 数据结构描述:
-
swf使用 twips 表示 Rect 数据,1 twips=1/20 pixel
-
无特别说明,使用 litle endian 结构,后边用 LE 表示
-
定点数, (8-8),(16-16) 二种 使用 litle endian.
-
浮点数, 16(半精度) ,32(单精度) ,64(双精度)
-
变长数,通常为低于32位, 使用 符号位扩展成 Int 类型. signExtend1, signExtend8, signExtend16
-
字符串,字符串是以全0结束的byte序列,采用utf-8编码
通过参考 format 库中的 swf 目录:
# ----- SWF HEADER -----
#偏移(字节) 大小 描述
00~02 3 # CWS(deflate算法)已压缩, 而 FWS 则未压缩, ZWS 表示为 lzma压缩
03 1 # flash 版本号
04~07 4 # LE小头 Int 类型,解压后, 整个 swf 的大小
# 1. 获得后边的二进制数据, 如果压缩则解压(这里没有考虑到 lzma 算法生成的压缩),
# 2. 然后使用 bitsInput(位) 的方式读取一个 Rect 数据: 参考 format/tools/bitsIntput
#偏移(位) 大小 描述
b0~b04 5 # 获得 left ,right ,top ,bottom 所占用的位数 SB(符号位扩展), 5个二进制最多表示 31 位
b05+SB SB # left, 单位为 twip, 1 twip等于1/20象素
+= SB SB # right
+= SB SB # top
+= SB SB # bottom
# 切换回 字节模式
#偏移(字节) 大小 描述
00~01 2 # 定点数8-8, 帧率
02~03 2 # 定点数8-8, 总帧数
# ----- SWF TAGS -----