├── .gitignore
├── README.md
├── asset
├── embed
│ ├── about.txt
│ └── chess.png
├── icon
│ ├── 128.png
│ ├── 16.png
│ ├── 32.png
│ └── 48.png
├── locale
│ ├── en_US
│ │ └── LC_MESSAGES
│ │ │ └── main.mo
│ └── zh_CN
│ │ └── LC_MESSAGES
│ │ └── main.mo
└── po
│ ├── SSE_zh_CN.txt
│ ├── en_US.po
│ ├── main.pot
│ ├── make_mo.sh
│ ├── make_po.sh
│ ├── make_pot.sh
│ ├── zh_CN.mo
│ └── zh_CN.po
├── build.xml
├── lib
├── robotlegs-framework-v1.5.2.swc
└── zrongas3.swc
├── sample.build.properties
└── src
├── SSEContext.as
├── SpriteSheetEditor-app.xml
├── SpriteSheetEditor.mxml
├── ctrl
├── BrowseFileCmd.as
├── DragFileCmd.as
├── PreviewSSChangeCmd.as
└── SaveCmd.as
├── events
└── SSEvent.as
├── interf
└── IPreview.as
├── main.css
├── mediator
├── AppMediator.as
├── comps
│ ├── FramesAndLabelMediator.as
│ └── SSPreviewMediator.as
└── panel
│ ├── PicPanelMediator.as
│ ├── SSPanelMediator.as
│ ├── StartPanelMediator.as
│ ├── SwfPanelMediator.as
│ └── TopPanelMediator.as
├── model
├── FileOpenerModel.as
├── FileProcessor.as
├── FileSaverModel.as
├── SpriteSheetModel.as
└── StateModel.as
├── type
├── ExtendedNameType.as
└── StateType.as
├── utils
├── Funs.as
└── Global.as
├── view
├── About.mxml
├── comps
│ ├── Alert.mxml
│ ├── BMPPreview.mxml
│ ├── BuildSetting.mxml
│ ├── FileManager.mxml
│ ├── FrameDataGrid.mxml
│ ├── FramesAndLabels.mxml
│ ├── ImagePreview.mxml
│ ├── ImageTypeSetting.mxml
│ ├── Preview.mxml
│ ├── SSPreview.mxml
│ ├── SaveSeqSetting.mxml
│ ├── SaveSheetSetting.mxml
│ ├── TransformTool.as
│ ├── TransformToolControlBar.mxml
│ ├── TransformToolControlBarForSS.as
│ └── VDividedButton.mxml
└── panel
│ ├── PicPanel.mxml
│ ├── SSPanel.mxml
│ ├── StartPanel.mxml
│ ├── SwfPanel.mxml
│ └── TopPanel.mxml
└── vo
├── BrowseFileDoneVO.as
├── FrameVO.as
├── LabelListVO.as
├── LabelVO.as
├── NamesVO.as
├── RectsAndBmdsVO.as
└── SaveVO.as
/.gitignore:
--------------------------------------------------------------------------------
1 | .actionScriptProperties
2 | .flexProperties
3 | .project
4 | .settings
5 | *.as3proj
6 | *.bat
7 | bin
8 | obj
9 | bat
10 | dist
11 | build.properties
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sprite Sheet Editor
2 |
3 | [Sprite Sheet Editor](http://zengrong.net/sprite_sheet_editor) 是一个生成Sprite Sheet(也叫Tile Sheet)的免费小工具。
4 |
5 | ## 开发平台
6 |
7 | * Apache Flex 4.9.1
8 | * Adobe AIR 3.7
9 |
10 | ## 特点
11 |
12 | * 将swf转换成序列图或者Sprite Sheet格式;
13 | * 将多张图像拼合成一张大的Sprite Sheet以降低文件尺寸和减少网络请求;
14 | * 让Sprite Sheet也支持Label,实现类似于MovieClip中Label的功能;
15 | * 自动修剪Sheet中每帧四周的空白像素;
16 | * 使用Mask技术让JPEG格式也支持透明,大幅降低需要透明的文件的尺寸;
17 | * 支持JPEG-XR格式,该格式支持Alpha通道,图像质量优于JPEG格式;
18 | * 还有更多……
19 |
20 | ## 更新历史
21 |
22 | 这个工具原来的名字叫做[Sprite Sheet Packer](http://zengrong.net/spritesheetpacker),从v0.5.0改名为Sprite Sheet Editor。
23 |
24 | * [2013-08-21:v0.8.2版发布](http://zengrong.net/post/1901.htm)
25 | * [2013-06-14:v0.8.1版发布](http://zengrong.net/post/1880.htm)
26 | * [2013-02-19:v0.8.0版发布](http://zengrong.net/post/1815.htm)
27 | * [2012-10-15:v0.7.3版发布](http://zengrong.net/post/1706.htm)
28 | * [2012-08-20:v0.7.2版发布](http://zengrong.net/post/1672.htm)
29 | * [2012-08-18:v0.7.1版发布](http://zengrong.net/post/1668.htm)
30 | * [2012-07-26:v0.7.0版发布](http://zengrong.net/post/1660.htm)
31 | * [2011-12-21:v0.6.2版发布](http://zengrong.net/post/1482.htm)
32 | * [2011-11-04:v0.5.9版发布](http://zengrong.net/post/1468.htm)
33 | * [2011-09-02:v0.5.7版发布](http://zengrong.net/post/1436.htm)
34 | * [2011-08-23:v0.5.6版发布](http://zengrong.net/post/1414.htm)
35 | * [2011-08-18:v0.5.0版发布,同时更名为Sprite Sheet Editor](http://zengrong.net/post/1402.htm)
36 | * [2011-06-30:v0.4版发布](http://zengrong.net/post/1357.htm)
37 | * [2011-04-26:v0.3版发布](http://zengrong.net/post/1313.htm)
38 | * [2011-04-22:v0.2版发布](http://zengrong.net/post/1311.htm)
39 | * [2011-04-19:v0.1版发布](http://zengrong.net/post/1306.htm)
40 |
41 | ## 网站
42 |
43 | * 官方网站:
44 | * WIKI:
45 |
--------------------------------------------------------------------------------
/asset/embed/about.txt:
--------------------------------------------------------------------------------
1 | 2013-08-21:v0.8.2版发布
2 |
3 | - 增加拖放功能,可以直接从资源管理器中拖动图像文件到编辑器中,规则如下:
4 |
5 | - 在开始界面中,根据文件扩展名和有无metadata文件,进入不同的界面(SWF、PIc或SS);
6 | - 在PIC界面中,将文件作为图像文件对待,加入PIC列表;
7 | - 在SS页面中,将文件作为图像文件或SpriteSheet对待,加入SpriteSheet列表;
8 |
9 |
10 | - 解决导入图像列表会出现重复的BUG;
11 | - 重写TransformTool;
12 | - 允许在SWF预览界面中移动SWF内容,以方便舞台对位有问题的SWF动画截取;
13 | - 合并了SS界面中的“增加图像帧”和“增加SpriteSheet”。
14 |
15 | 2013-06-14:v0.8.1版发布
16 |
17 | - 增加保存为Starling格式的SpriteSheet,但不支持打开Starling;
18 | - 调整程序结构以支持更多格式;
19 | - 在“编辑SpriteSheet界面”,直接单击大图选择对应的帧,左侧帧列表会自动滚动到该帧;
20 | - 在“编辑SpriteSheet界面”,可以使用Shift实现连续多选,使用Ctrl/Control键实现不连续多选。
21 |
22 | 2013-02-19:v0.8.0版发布
23 |
24 | - 关于帧和Label界面的大幅调整;
25 | - 预览界面使用单独的弹出窗口;
26 | - Label中的帧现在支持重用;
27 | - Label和帧的管理界面更新;
28 | - 允许调整Label中帧的顺序;
29 | - 支持英文界面。
30 |
31 | 2012-10-15:v0.7.3版发布
32 |
33 | - 增加对JPEG-XR格式描述符的支持;
34 | - 解决输出的XML文件第一行换行符为\r\n的问题。
35 |
36 | 2012-08-20:v0.7.2版发布
37 |
38 | - 解决增加帧有时会报错的bug;
39 | - 在帧列表中选择多个帧的时候,Sheet上的显示范围也为多个帧(上个版本只能显示单个帧);
40 | - 在Sheet上单击的时候,自动选择帧列表中的对应帧。
41 |
42 | 2012-08-18:v0.7.1版发布
43 |
44 | - 解决加入图像的BUG;
45 | - 解决保存的文件不包含文件名称的BUG;
46 | - 帧列表可以改变高度,在帧较多的时候方便查看;
47 | - 将设置预览图背景色的功能从右键菜单改为下拉列表。
48 |
49 | 2012-07-26:v0.7.0版发布
50 |
51 | - 使用AIR3.3的原生压缩功能对图像进行压缩;
52 | - 支持使用JPEG-XR作为Sprite Sheet的格式;
53 | - 让预览图部分浮动;
54 | - 选择Sprite Sheet中的图片,在整张预览图中指示出该图片的位置;
55 | - 使用robotlegs重写界面架构。
56 |
57 | 2011-12-21:v0.6.2版发布
58 |
59 | - 解决在增加和删除帧的时候,帧名称错误的问题。
60 |
61 | 2011-12-01:v0.6.1版发布
62 |
63 | - 加入在打开的SpriteSheet中增加帧的功能。帧只能增加到已有帧的末尾。
64 | - 加入在打开SpriteSheet中增加SpriteSheet的功能。这样就可以实现多个SpriteSheet的合并。规则如下:
65 |
66 | - 所有帧会增加到当前Sheet的末尾;
67 | - 若label重名,则被导入Sheet中的label不导入,但依然会导入该lable的所有帧;
68 | - 若name重名,则被导入的Sheet中该name对应的重名帧不会被导入;
69 | - 若原始Sheet中包含name,但被导入Sheet中不含name,则会自动为被导入的Sheet中的所有帧命名。
70 |
71 |
72 |
73 | 2011-11-04:v0.5.9版发布
74 |
75 | - 导入图像文件后,支持多选排序,支持“移到顶部/底部”。
善用此功能,可对最终生成SpriteSheet进行排版,以降低最终文件的尺寸。
76 | - 预览的背景可以在方格/白色/黑色之间切换,方便查看半透明的动画。
77 |
78 | 2011-09-02:v0.5.7版发布
79 |
80 | - 解决metadata中frame的的ow和oh与w和h相等的重大BUG;
81 | - 现在可以把帧还原到“修剪空白”前的状态;
82 | - 使用SharedObject保存设置。目前仅实现了帧率的保存。
83 |
84 | 2011-08-23:v0.5.6版发布
85 |
86 | - 加入缩小帧原始尺寸的功能;
87 | - 删除帧后,会立即更新Sheet预览;
88 | - 解决一些bug。
89 |
90 | 2011-08-18:v0.5.0版发布,同时更名为Sprite Sheet Editor
91 |
92 | - 采用Flex重写了界面;
93 | - 修改了生成Sheet的流程;
94 | - 自动计算生成的Sheet的尺寸,自动计算支持“正方形”和“2的幂”;
95 | - 可更改已生成的Sheet的尺寸和排列方式;
96 | - 增加对Sheet中的帧周围空白区域的自动修剪;
97 | - 可以采用可视化的方式修改截取区域;
98 | - 可以对待拼合的图像文件进行排序;
99 | - SpriteSheetMetadata格式小幅修改。
100 |
101 | 2011-06-30:v0.4版发布
102 |
103 | - 将菜单改为按钮,避免Mac等不支持菜单的操作系统无法显示菜单;
104 | - 可以打开SpriteSheet格式的图片,然后保存成其他格式。即可以在SS、JPG、PNG之间互转格式;
105 | - 可以打开已有的SpriteSheet,修改Metadata后保存成新的文件;
106 | - 解决0.3版手动提供的元数据无效的问题;
107 | - 播放位图动画的时候,在Sheet预览中显示当前帧的范围;
108 | - 解决打开的SpriteSheet格式的Label起始帧显示不正常的问题;
109 | - 采用SDK2.7编译。因此需要卸载原来的软件,再升级AIR Runtime,才能正常安装。(AIR的版本兼容性很糟糕,经常无法安装,而且给出错误的提示)
110 |
111 | 2011-04-26:v0.3版发布
112 |
113 | - 加入了XML格式的元数据导出功能。
114 | - 可以打开由SpriteSheetPacker保存的SS格式文件。
115 | - 如果以SheetSprite方式打开jpg或png文件,可以提供一个SpriteSheetPacker生成的元数据xml文件,SpriteSheetPacker会根据元数据进行解析;若没有提供元数据,会自动在图像文件所在路径寻找同名xml文件。包含mask信息的jpg文件,会自动应用Alpha通道。
116 | - 一些界面上的修改,就不说了。
117 |
118 | 2011-04-22:v0.2版发布
119 |
120 | - 修正了图像排列的BUG;
121 | - 将保存图像和元数据信息合并到一个菜单,便于对照;
122 | - 保存元数据的时候可以“包含附加信息”。附加信息包含:是否mask、有没有label、有没有包含名称、总帧数等等。
附加信息选项只会影响元数据,SS格式嵌入的数据总是包含附加信息的。
123 | - 保存SS格式图像和元数据的时候,可以“包含名称”。有时候我们希望用名称来查找一个Sheet中的Sprite。包含名称功能是独立的,不受“包含附加信息”影响。
SWF视图中不能使用“包含名称”功能。名称自动使用图片的主文件名;
124 | - 将文件名列表截断,只显示文件名,不显示路径。
125 |
126 | 2011-04-19:v0.1版发布
--------------------------------------------------------------------------------
/asset/embed/chess.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/asset/embed/chess.png
--------------------------------------------------------------------------------
/asset/icon/128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/asset/icon/128.png
--------------------------------------------------------------------------------
/asset/icon/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/asset/icon/16.png
--------------------------------------------------------------------------------
/asset/icon/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/asset/icon/32.png
--------------------------------------------------------------------------------
/asset/icon/48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/asset/icon/48.png
--------------------------------------------------------------------------------
/asset/locale/en_US/LC_MESSAGES/main.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/asset/locale/en_US/LC_MESSAGES/main.mo
--------------------------------------------------------------------------------
/asset/locale/zh_CN/LC_MESSAGES/main.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/asset/locale/zh_CN/LC_MESSAGES/main.mo
--------------------------------------------------------------------------------
/asset/po/make_mo.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | find . -type f -name "*.po" > po
4 |
5 | sed -i -e 's/\.po//g' po
6 | locales=`cat po`
7 | rm po
8 |
9 | out=../locale
10 | mkdir -p $out
11 |
12 | for locale in $locales; do
13 | echo "Processing "$locale".po ..."
14 | mkdir -p $out/$locale/LC_MESSAGES
15 | msgfmt --check --verbose --output-file $out/$locale/LC_MESSAGES/main.mo $locale.po
16 | done
17 |
--------------------------------------------------------------------------------
/asset/po/make_po.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | pot=`find . | grep -i \.pot$`
4 | msginit --no-translator --locale $1 --output-file $1.po --input $pot
5 |
6 | #echo "Missing locale: usage ./make_po.sh "
7 |
--------------------------------------------------------------------------------
/asset/po/make_pot.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | find ../../src -type f \( -name "*.as" -o -name "*.mxml" \) > files
4 | xgettext --package-name main --package-version 0.1 --default-domain main --output main.pot --from-code=UTF-8 -L C -f files
5 | rm files
6 |
--------------------------------------------------------------------------------
/asset/po/zh_CN.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/asset/po/zh_CN.mo
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Found the Flash Develop project: ${FD_PROJECT}.
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | main.file:${main.file}
41 | main.name:${main.name}
42 | swf.file:${swf.file}
43 | swf.name:${swf.name}
44 | FLEX_HOME:${FLEX_HOME}
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Building swf file ${swf.file}...
62 | The main file is ${main.file}.
63 | debug:${var.debug} optimize:${var.optimize} swfversion:${var.swfversion}
64 |
65 |
66 |
67 |
68 |
69 |
70 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | Delete old certificate file.
82 |
83 | Create a new certificate file ${AND_CERT_FILE}.
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Replace the appid from ${id} to ${APP_ID} in ${APP_XML}.
98 |
99 |
100 |
101 |
102 |
103 | Replace the content from ${initialWindow.content} to ${swf.name} in ${APP_XML}.
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | Copy ${ASSET_DIR} to ${BIN_DIR}
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | Copy ${TEMP_DIR} to ${BIN_DIR}
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | Packager a ${var.type}${var.target}
143 | The signing is ${var.signing}
144 | The output file is ${var.output}
145 | The options are ${var.options}
146 | ${FLEX_HOME}/lib/adt.jar -package ${var.signing} ${var.options} -target ${var.type}${var.target} ${var.output} ${APP_XML} ${var.fileordir} ${ANE_DIR_ARGS}
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | OS family is ${os.name}. The adl is ${var.adl}.
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 | runSimulatorDebug ${APP_XML} ${BIN_DIR}
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 | packair ${APP_XML} ${BIN_DIR}
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/lib/robotlegs-framework-v1.5.2.swc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/lib/robotlegs-framework-v1.5.2.swc
--------------------------------------------------------------------------------
/lib/zrongas3.swc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrong/sprite_sheet_editor/32764c96fd14d26967c675bcde21083a045c0255/lib/zrongas3.swc
--------------------------------------------------------------------------------
/sample.build.properties:
--------------------------------------------------------------------------------
1 | PROJECT_NAME=SpriteSheetEditor
2 |
3 | # The project can have multiple main class file.
4 | MAIN_NAME=SpriteSheetEditor
5 | MAIN_PATH=
6 |
7 | FLEX_HOME=D:/flashsdks/flex4.6.0
8 | FLEX_FRAMEWORKS=${FLEX_HOME}/frameworks
9 |
10 | # SRC - mxml and as files
11 | # CERT - p12 and mobileprovision files
12 | # BIN - output files
13 | # ANE - AIR Native Extension files
14 | # LIB - swc files
15 | # ASSET - assets file dir
16 | # ICON - icon files
17 | # TEMP - package temporary files
18 | # DIST - AIR release files
19 | SRC_DIR=${basedir}/src
20 | CERT_DIR=${basedir}/cert
21 | BIN_DIR=${basedir}/bin
22 | ANE_DIR=${basedir}/ane
23 | LIB_DIR=${basedir}/lib
24 | ASSET_DIR=${basedir}/asset
25 | ICON_DIR=${basedir}/asset/icon
26 | TEMP_DIR=${basedir}/temp
27 | DIST_DIR=${basedir}/dist
28 |
29 | # About AIR application packaging
30 | # http://livedocs.adobe.com/flex/3/html/help.html?content=CommandLineTools_5.html#1035959
31 | # http://livedocs.adobe.com/flex/3/html/distributing_apps_4.html#1037515
32 |
33 | # NOTICE: all paths are relative to project root
34 |
35 | # certification options
36 | AIR_CERT_NAME=SpriteSheetEditor
37 | AIR_CERT_PASS=fd
38 | AIR_CERT_FILE=${CERT_DIR}/${AIR_CERT_NAME}.p12
39 | AIR_ICONS=${ICON_DIR}
40 | AIR_DEV_SIGN=-storetype pkcs12 -keystore ${AIR_CERT_FILE} -storepass ${AIR_CERT_PASS}
41 | AIR_DIST_SIGN=-storetype pkcs12 -keystore ${AIR_CERT_FILE} -storepass ${AIR_CERT_PASS}
42 |
43 | # Application descriptor
44 | APP_XML=${basedir}/src/SpriteSheetEditor-app.xml
45 |
46 | # Flash Develop project file
47 | FD_PROJECT=${PROJECT_NAME}.as3proj
48 |
49 | # AIR Native Extensions(ANE)
50 | ANE_DIR_ARGS=
51 | #ANE_DIR_ARGS=-extdir ${ANE_DIR}
52 |
53 | # Your application ID (must match of Application descriptor)
54 | APP_ID=org.zengrong.SpriteSheetEditor
55 |
56 | # Output packages
57 | DIST_NAME=${MAIN_NAME}
58 |
59 | # Default variable value
60 | var.type=air
61 | var.target=
62 | #var.target=-captive-runtime
63 | var.output=${DIST_DIR}/${DIST_NAME}${var.target}.air
64 | var.options=
65 | #var.options=-tsa none
66 | var.signing=${AIR_DIST_SIGN}
67 | var.fileordir=-C ${TEMP_DIR} .
68 |
--------------------------------------------------------------------------------
/src/SSEContext.as:
--------------------------------------------------------------------------------
1 | package
2 | {
3 | import ctrl.BrowseFileCmd;
4 | import ctrl.DragFileCmd;
5 | import ctrl.PreviewSSChangeCmd;
6 | import ctrl.SaveCmd;
7 |
8 | import events.SSEvent;
9 |
10 | import flash.display.DisplayObjectContainer;
11 |
12 | import mediator.*;
13 | import mediator.comps.*;
14 | import mediator.panel.*;
15 |
16 | import model.*;
17 |
18 | import org.robotlegs.mvcs.Context;
19 |
20 | import utils.Global;
21 |
22 | import view.comps.FramesAndLabels;
23 | import view.comps.SSPreview;
24 | import view.panel.*;
25 |
26 | /**
27 | *
28 | * @author zrong(zengrong.net)
29 | * 创建日期:2012-07-18
30 | */
31 | public class SSEContext extends Context
32 | {
33 | public function SSEContext(contextView:DisplayObjectContainer=null, autoStartup:Boolean=true)
34 | {
35 | super(contextView, autoStartup);
36 | }
37 |
38 | private function init():void
39 | {
40 | Global.init(contextView as SpriteSheetEditor);
41 | }
42 |
43 | override public function startup():void
44 | {
45 | init();
46 | injector.mapSingleton(FileOpenerModel);
47 | injector.mapSingleton(FileSaverModel);
48 | injector.mapSingleton(StateModel);
49 | injector.mapSingleton(SpriteSheetModel);
50 |
51 | mediatorMap.mapView(SpriteSheetEditor, AppMediator);
52 | mediatorMap.mapView(TopPanel, TopPanelMediator);
53 | mediatorMap.mapView(SwfPanel, SwfPanelMediator);
54 | mediatorMap.mapView(SSPanel, SSPanelMediator);
55 | mediatorMap.mapView(StartPanel, StartPanelMediator);
56 | mediatorMap.mapView(PicPanel, PicPanelMediator);
57 |
58 | mediatorMap.mapView(SSPreview, SSPreviewMediator,null, false, false);
59 | mediatorMap.mapView(FramesAndLabels,FramesAndLabelMediator, null, false, false);
60 |
61 | commandMap.mapEvent(SSEvent.PREVIEW_SS_CHANGE, PreviewSSChangeCmd);
62 | commandMap.mapEvent(SSEvent.SAVE, SaveCmd);
63 | commandMap.mapEvent(SSEvent.BROWSE_FILE, BrowseFileCmd);
64 | commandMap.mapEvent(SSEvent.DRAG_FILE, DragFileCmd);
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/src/SpriteSheetEditor-app.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.zengrong.SpriteSheetEditor
4 | SpriteSheetEditor
5 | Sprite Sheet Editor
6 | 0.8.2
7 |
8 |
9 |
11 |
12 |
13 | zengrong.net
14 |
15 |
16 |
17 |
18 |
19 |
20 | SpriteSheetEditor.swf
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 800
35 |
36 | 600
37 |
38 |
39 |
40 |
41 |
42 | 800 600
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | true
56 | false
57 | false
58 | none
59 | standard
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
73 |
74 | icon/16.png
75 | icon/32.png
76 | icon/48.png
77 | icon/128.png
78 |
79 |
82 |
83 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/src/SpriteSheetEditor.mxml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/ctrl/BrowseFileCmd.as:
--------------------------------------------------------------------------------
1 | package ctrl
2 | {
3 | import air.update.utils.StringUtils;
4 | import events.SSEvent;
5 | import model.FileOpenerModel;
6 | import org.robotlegs.mvcs.Command;
7 |
8 | /**
9 | * 选择一个或者一组文件
10 | * @author zrong
11 | */
12 | public class BrowseFileCmd extends Command
13 | {
14 | [Inject]
15 | public var fileOpener:FileOpenerModel;
16 |
17 | [Inject]
18 | public var evt:SSEvent;
19 |
20 | override public function execute():void
21 | {
22 | fileOpener.open(evt.info as String);
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/ctrl/DragFileCmd.as:
--------------------------------------------------------------------------------
1 | package ctrl
2 | {
3 | import events.SSEvent;
4 | import gnu.as3.gettext.FxGettext;
5 | import model.FileOpenerModel;
6 | import model.StateModel;
7 | import org.robotlegs.mvcs.Command;
8 | import type.StateType;
9 | import utils.Funs;
10 |
11 | /**
12 | * 处理一个拖放文件
13 | * @author zrong
14 | * Creation: 2013-08-19
15 | */
16 | public class DragFileCmd extends Command
17 | {
18 | [Inject] public var evt:SSEvent;
19 | [Inject] public var fileOpener:FileOpenerModel;
20 | [Inject] public var stateModel:StateModel;
21 |
22 | public override function execute():void
23 | {
24 | var __files:Array = evt.info as Array;
25 | var __state:String = Funs.getStateByFile(__files[0]);
26 | if(!__state)
27 | {
28 | Funs.alert(FxGettext.gettext("These files are not supported!"));
29 | return;
30 | }
31 | if(__state == StateType.PIC)
32 | {
33 | //若当前位于PicPanel中,则将状态改为增加图像到列表
34 | if(stateModel.state == StateType.PIC) __state = StateType.ADD_TO_PIC_List;
35 | //若位于SSPanel中,则将状态改为增加到ss
36 | else if(stateModel.state == StateType.SS) __state = StateType.ADD_TO_SS;
37 | fileOpener.openFilesByDrag(__files, __state);
38 | }
39 | else if(__state == StateType.SS)
40 | {
41 | //若位于SSPanel中,则将状态改为增加到SS
42 | if(stateModel.state == StateType.SS)
43 | {
44 | __state = StateType.ADD_TO_SS;
45 | fileOpener.openFilesByDrag(__files, __state);
46 | }
47 | //否则直接切换到SS列表
48 | else fileOpener.openFilesByDrag([__files[0]], __state);
49 | }
50 | else if(__state == StateType.SWF)
51 | {
52 | fileOpener.openFilesByDrag([__files[0]], __state);
53 | }
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/ctrl/PreviewSSChangeCmd.as:
--------------------------------------------------------------------------------
1 | package ctrl
2 | {
3 | import events.SSEvent;
4 |
5 | import flash.display.BitmapData;
6 | import flash.geom.Rectangle;
7 |
8 | import model.SpriteSheetModel;
9 |
10 | import org.robotlegs.mvcs.Command;
11 |
12 | /**
13 | * 显示帧改变
14 | * @author zrong
15 | * 创建日期:2012-07-26
16 | */
17 | public class PreviewSSChangeCmd extends Command
18 | {
19 | [Inject] public var ssModel:SpriteSheetModel;
20 |
21 | override public function execute():void
22 | {
23 | updateFrameDisplay();
24 | }
25 |
26 | /**
27 | * 更新帧显示
28 | */
29 | private function updateFrameDisplay():void
30 | {
31 | if(ssModel.selectedFrameIndex<0) return;
32 | var __frameBmd:BitmapData = null;
33 | //根据选择显示原始的或者修剪过的Frame
34 | if(ssModel.displayCrop)
35 | {
36 | __frameBmd = ssModel.adjustedSheet.getTrimBMDByIndex(ssModel.selectedFrameIndex);
37 | }
38 | else
39 | {
40 | __frameBmd = ssModel.adjustedSheet.getBMDByIndex(ssModel.selectedFrameIndex);
41 | }
42 | //rect永远使用剪切过的值
43 | var __rect:Rectangle = ssModel.adjustedSheet.metadata.frameRects[ssModel.selectedFrameIndex];
44 | trace('更新帧:', __frameBmd.rect, ssModel.displayCrop);
45 | dispatch(new SSEvent(SSEvent.PREVIEW_SS_SHOW, {bmd:__frameBmd, rect:__rect}));
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/ctrl/SaveCmd.as:
--------------------------------------------------------------------------------
1 | package ctrl
2 | {
3 | import events.SSEvent;
4 | import model.FileSaverModel;
5 | import org.robotlegs.mvcs.Command;
6 | import vo.SaveVO;
7 |
8 | /**
9 | * 用于保存文件的Cmd
10 | * @author zrong
11 | * Creation: 2013-06-13
12 | */
13 | public class SaveCmd extends Command
14 | {
15 | [Inject]
16 | public var evt:SSEvent;
17 |
18 | [Inject]
19 | public var fileSaver:FileSaverModel;
20 |
21 | override public function execute():void
22 | {
23 | var __vo:SaveVO = evt.info as SaveVO;
24 | fileSaver.save(__vo);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/events/SSEvent.as:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | // zengrong.net
3 | // 创建者: zrong(zrongzrong@gmail.com)
4 | // 创建时间:2011-8-9
5 | ////////////////////////////////////////////////////////////////////////////////
6 |
7 | package events
8 | {
9 | import flash.events.Event;
10 |
11 | public class SSEvent extends Event
12 | {
13 | public static const ENTER_STATE:String = 'enterState';
14 | public static const EXIT_STATE:String = 'exitState';
15 |
16 | public static const FRAME_AND_LABEL_CHANGE:String = 'frameAndLabelChange';
17 |
18 | /**
19 | * 拖动一个文件到SSE中
20 | */
21 | public static const DRAG_FILE:String = "dragFile";
22 | /**
23 | * 要求File对象选择一个或者一组文件
24 | */
25 | public static const BROWSE_FILE:String = "browseFile";
26 |
27 | /**
28 | * 选择一个或者一组文件成功
29 | */
30 | public static const BROWSE_FILE_DONE:String = "browseFileDone";
31 | /**
32 | * 选择的帧变化了
33 | */
34 | public static const SELECTED_FRAMEINDICES_CHANGE:String = 'selectedFrameIndicesChange';
35 | public static const ADD_FRAME:String = 'addFrame';
36 |
37 |
38 | public static const CAPTURE_DONE:String = 'captureDone';
39 |
40 | public static const SAVE_PIC:String = 'savePic';
41 | public static const SAVE_META:String = 'saveMeta';
42 | public static const SAVE_ALL:String = 'saveAll';
43 | public static const SAVE_SEQ:String = 'saveSeq';
44 |
45 | /**
46 | * 所有类型的保存事件
47 | */
48 | public static const SAVE:String = "sssave";
49 |
50 | /**
51 | * 收到此事件的时候开始优化Sheet,一般在删除或者增加帧内容的时候执行
52 | */
53 | public static const OPTIMIZE_SHEET:String = 'optimizeSheet';
54 | /**
55 | * 优化完成之后发布此事件
56 | */
57 | public static const OPTIMIZE_SHEET_DONE:String = 'optimizeSheetDone';
58 |
59 | public static const FILE_MANAGER_SELECTION_CHANGE:String = 'selectionChange';
60 | public static const FILE_MANAGER_SELECTION_CHANGING:String = 'selectionChanging';
61 |
62 | public static const PREVIEW_LOAD_COMPLETE:String = 'previewLoadComplete';
63 | public static const PREVIEW_CLICK:String = 'previewClick';
64 |
65 | /**
66 | * 变形工具的大小和位置改变了
67 | */
68 | public static const TRANSFORM_CHANGE:String = "transformChange";
69 |
70 | /**
71 | * 变形工具的帧设置大小改变了
72 | */
73 | public static const TRANSFORM_FRAME_CHANGE:String = "transformFrameChange";
74 | /**
75 | * 变形工具中选择是否使用变形值的事件
76 | */
77 | public static const TRANSFORM_USE_CUSTOM_CHANGE:String = "transformUseCustomChange";
78 |
79 | /**
80 | * 控制SS的播放
81 | */
82 | public static const PREVIEW_SS_PLAY:String = 'previewSSPlay';
83 |
84 | /**
85 | * 改变SS中每一帧的大小
86 | */
87 | public static const PREVIEW_SS_RESIZE_SAVE:String = 'previewSSResizeSize';
88 |
89 | /**
90 | * 发送要预览的帧信息
91 | */
92 | public static const PREVIEW_SS_SHOW:String = 'previewSSShow';
93 |
94 | /**
95 | * 要预览的帧的显示范围变化变化,剪切/原始切换
96 | * 要预览的帧的显示形式变化,帧/Label切换
97 | */
98 | public static const PREVIEW_SS_CHANGE:String = 'previewSSChange';
99 |
100 | /**
101 | * 建立或优化SpriteSheet
102 | */
103 | public static const BUILD:String = 'build';
104 |
105 | public var info:*;
106 |
107 | public function SSEvent($type:String, $info:*=null, $bubbles:Boolean=false, $cancelable:Boolean=false)
108 | {
109 | super($type, $bubbles, $cancelable);
110 | info = $info;
111 | }
112 |
113 | override public function clone():Event
114 | {
115 | return new SSEvent(type, info, bubbles, cancelable);
116 | }
117 | }
118 | }
--------------------------------------------------------------------------------
/src/interf/IPreview.as:
--------------------------------------------------------------------------------
1 | package interf
2 | {
3 | import flash.display.IBitmapDrawable;
4 | import flash.events.IEventDispatcher;
5 |
6 | public interface IPreview extends IEventDispatcher
7 | {
8 | function destroy():void;
9 | function set source($so:*):void;
10 | function get content():IBitmapDrawable;
11 | }
12 | }
--------------------------------------------------------------------------------
/src/main.css:
--------------------------------------------------------------------------------
1 | /* CSS file */
2 | @namespace s "library://ns.adobe.com/flex/spark";
3 | @namespace mx "library://ns.adobe.com/flex/mx";
4 |
5 |
6 | global
7 | {
8 | font-size: 12;
9 | fontFamily: "Microsoft YaHei,simsun";
10 | chrome-color: #333333;
11 | color: #CCCCCC;
12 | content-background-color: #777777;
13 | symbol-color: #000000;
14 | roll-over-color: #555555;
15 | selection-color: #333333;
16 | focus-color: #999999;
17 | accent-color: #8C8C8C
18 | }
19 |
20 | s|Application,s|Panel,mx|Panel,mx|TitleWindow,mx|TabNavigator,mx|SwatchPanel
21 | {
22 | background-color: #666666;
23 | }
24 |
25 | s|RichEditableText
26 | {
27 | focusedTextSelectionColor: #333333;
28 | unfocusedTextSelectionColor: #333333;
29 | }
30 |
31 | mx|DataGrid
32 | {
33 | alternating-item-colors: #777777, #777777;
34 | }
35 |
36 | mx|ToolTip
37 | {
38 | font-size: 12;
39 | color: #000000;
40 | }
41 |
--------------------------------------------------------------------------------
/src/mediator/AppMediator.as:
--------------------------------------------------------------------------------
1 | package mediator
2 | {
3 | import events.SSEvent;
4 | import flash.desktop.ClipboardFormats;
5 | import flash.desktop.NativeDragManager;
6 | import flash.events.NativeDragEvent;
7 | import mx.events.FlexEvent;
8 | import org.robotlegs.mvcs.Mediator;
9 |
10 | public class AppMediator extends Mediator
11 | {
12 | [Inject] public var v:SpriteSheetEditor;
13 |
14 | override public function onRegister():void
15 | {
16 | // v.startState.addEventListener(FlexEvent.EXIT_STATE, handler_exitState);
17 | // v.picState.addEventListener(FlexEvent.EXIT_STATE, handler_exitState);
18 | // v.ssState.addEventListener(FlexEvent.EXIT_STATE, handler_exitState);
19 | // v.swfState.addEventListener(FlexEvent.EXIT_STATE, handler_exitState);
20 | eventMap.mapListener(eventDispatcher, SSEvent.ENTER_STATE, handler_enterState);
21 | v.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, handler_nativeDragEnter);
22 | v.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, handler_nativeDragDrop);
23 | }
24 |
25 | private function handler_nativeDragDrop($evt:NativeDragEvent):void
26 | {
27 | dispatch(new SSEvent(SSEvent.DRAG_FILE, $evt.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array));
28 | }
29 |
30 | private function handler_nativeDragEnter($evt:NativeDragEvent):void
31 | {
32 | if($evt.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT))
33 | {
34 | NativeDragManager.acceptDragDrop(v);
35 | }
36 | }
37 |
38 | private function handler_enterState($evt:SSEvent):void
39 | {
40 | v.currentState = $evt.info.newState;
41 | }
42 |
43 | protected function handler_exitState($event:FlexEvent):void
44 | {
45 | trace('退出状态', v.currentState);
46 | dispatch(new SSEvent(SSEvent.EXIT_STATE));
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/src/mediator/comps/SSPreviewMediator.as:
--------------------------------------------------------------------------------
1 | package mediator.comps
2 | {
3 | import flash.events.Event;
4 | import flash.events.MouseEvent;
5 |
6 | import mx.events.FlexEvent;
7 |
8 | import events.SSEvent;
9 |
10 | import gnu.as3.gettext.FxGettext;
11 |
12 | import model.SpriteSheetModel;
13 |
14 | import org.robotlegs.mvcs.Mediator;
15 |
16 | import view.comps.SSPreview;
17 |
18 | public class SSPreviewMediator extends Mediator
19 | {
20 | [Inject] public var v:SSPreview;
21 |
22 | [Inject] public var ssModel:SpriteSheetModel;
23 |
24 | override public function onRegister():void
25 | {
26 | eventMap.mapListener(v.playBTN, MouseEvent.CLICK, handler_playBTNclick);
27 | eventMap.mapListener(v.transControlBar.saveResizeBTN, MouseEvent.CLICK, handler_saveResizeBTNclick);
28 | eventMap.mapListener(v.transControlBar.useCustomSizeCB, FlexEvent.VALUE_COMMIT, handler_resizeOriginCBChange);
29 | eventMap.mapListener(v, FlexEvent.VALUE_COMMIT, handler_resizeOriginCBChange);
30 | addViewListener(SSEvent.TRANSFORM_CHANGE, handler_transformSizeChange);
31 |
32 | addContextListener(SSEvent.PREVIEW_SS_SHOW, handler_previewShow);
33 | addContextListener(SSEvent.FRAME_AND_LABEL_CHANGE, handler_framesAndLabelsChange);
34 | addContextListener(SSEvent.SELECTED_FRAMEINDICES_CHANGE, handler_framesAndLabelsChange);
35 | addContextListener(SSEvent.OPTIMIZE_SHEET, handler_optimizeSheet);
36 | addContextListener(SSEvent.PREVIEW_SS_CHANGE, handler_previewSSChange);
37 |
38 | v.init();
39 | setPlayEnable();
40 | }
41 |
42 | override public function onRemove():void
43 | {
44 | eventMap.unmapListener(v.playBTN, MouseEvent.CLICK, handler_playBTNclick);
45 | eventMap.unmapListener(v.transControlBar.saveResizeBTN, MouseEvent.CLICK, handler_saveResizeBTNclick);
46 | eventMap.unmapListener(v.transControlBar.useCustomSizeCB, FlexEvent.VALUE_COMMIT, handler_resizeOriginCBChange);
47 | removeViewListener(SSEvent.TRANSFORM_CHANGE, handler_transformSizeChange);
48 |
49 | removeContextListener(SSEvent.PREVIEW_SS_SHOW, handler_previewShow);
50 | removeContextListener(SSEvent.FRAME_AND_LABEL_CHANGE, handler_framesAndLabelsChange);
51 | removeContextListener(SSEvent.SELECTED_FRAMEINDICES_CHANGE, handler_framesAndLabelsChange);
52 | removeContextListener(SSEvent.OPTIMIZE_SHEET, handler_optimizeSheet);
53 | removeContextListener(SSEvent.PREVIEW_SS_CHANGE, handler_previewSSChange);
54 |
55 | v.destroy();
56 | handler_playBTNclick(null);
57 | }
58 |
59 | protected function handler_optimizeSheet($evt:SSEvent):void
60 | {
61 | v.destroyAni();
62 | }
63 |
64 | protected function handler_playBTNclick($event:MouseEvent):void
65 | {
66 | ssModel.playing = v.playBTN.selected;
67 | dispatch(new SSEvent(SSEvent.PREVIEW_SS_PLAY, v.playBTN.selected));
68 | }
69 |
70 | private function handler_saveResizeBTNclick($evt:MouseEvent):void
71 | {
72 | dispatch(new SSEvent(SSEvent.PREVIEW_SS_RESIZE_SAVE));
73 | }
74 |
75 | private function handler_previewShow($evt:SSEvent):void
76 | {
77 | v.showBmd($evt.info.bmd);
78 | }
79 |
80 | private function handler_previewSSChange($evt:SSEvent):void
81 | {
82 | updateFrame();
83 | v.title = ssModel.displayFrame ? FxGettext.gettext("Frame animation preview") : ("Label("+ssModel.displayLabel+")" + FxGettext.gettext("animation preview"));
84 | }
85 |
86 | private function handler_resizeOriginCBChange($evt:FlexEvent):void
87 | {
88 | updateFrame();
89 | }
90 |
91 | private function handler_framesAndLabelsChange($evt:SSEvent):void
92 | {
93 | updateFrame();
94 | }
95 |
96 | private function handler_transformSizeChange($evt:Event):void
97 | {
98 | updateFrame();
99 | }
100 |
101 | private function updateFrame():void
102 | {
103 | v.frameLabel.text = ssModel.selectedFrmaeNum.toString();
104 | setPlayEnable();
105 | setSaveEnable();
106 | ssModel.resizeRect = v.getResizeRect();
107 | }
108 |
109 | private function setSaveEnable():void
110 | {
111 | v.transControlBar.setResizeBtnEnable(!ssModel.playing && ssModel.selectedFrameIndices);
112 | }
113 |
114 | private function setPlayEnable():void
115 | {
116 | if(ssModel.displayFrame)
117 | {
118 | v.playBTN.enabled = ssModel.selectedFrameIndices && ssModel.selectedFrameIndices.length>1;
119 | }
120 | else
121 | {
122 | v.playBTN.enabled = true;
123 | }
124 | }
125 | }
126 | }
--------------------------------------------------------------------------------
/src/mediator/panel/PicPanelMediator.as:
--------------------------------------------------------------------------------
1 | package mediator.panel
2 | {
3 | import events.SSEvent;
4 | import flash.events.Event;
5 | import model.FileOpenerModel;
6 | import model.SpriteSheetModel;
7 | import model.StateModel;
8 | import org.robotlegs.mvcs.Mediator;
9 | import org.zengrong.display.spritesheet.SpriteSheetMetadata;
10 | import type.StateType;
11 | import view.panel.PicPanel;
12 | import vo.BrowseFileDoneVO;
13 | import vo.NamesVO;
14 |
15 | public class PicPanelMediator extends Mediator
16 | {
17 | [Inject] public var v:PicPanel;
18 |
19 | [Inject] public var stateModel:StateModel;
20 |
21 | [Inject] public var fileOpener:FileOpenerModel;
22 |
23 | [Inject] public var ssModel:SpriteSheetModel;
24 |
25 | override public function onRegister():void
26 | {
27 | addViewListener(SSEvent.CAPTURE_DONE, handler_captureDone);
28 | addViewListener(SSEvent.ADD_FRAME, handler_addFrame);
29 | eventMap.mapListener(v.fileM, Event.SELECT, handler_select);
30 | eventMap.mapListener(v.buildSetting, SSEvent.BUILD, handler_build);
31 | eventMap.mapListener(eventDispatcher, SSEvent.BROWSE_FILE_DONE, handler_browseFileDone);
32 |
33 | enterState(stateModel.oldState, stateModel.state);
34 | }
35 |
36 |
37 | override public function onRemove():void
38 | {
39 | removeViewListener(SSEvent.CAPTURE_DONE, handler_captureDone);
40 | removeViewListener(SSEvent.ADD_FRAME, handler_addFrame);
41 | eventMap.unmapListener(v.fileM, Event.SELECT, handler_select);
42 | eventMap.unmapListener(v.buildSetting, SSEvent.BUILD, handler_build);
43 | eventMap.unmapListener(eventDispatcher, SSEvent.BROWSE_FILE_DONE, handler_browseFileDone);
44 |
45 | v.fileM.init();
46 | v.pic.viewer.source = null;
47 | }
48 |
49 | /**
50 | * 在PicPanel界面中新增Pic
51 | * @param $evt
52 | */
53 | private function handler_select($evt:Event):void
54 | {
55 | this.dispatch(new SSEvent(SSEvent.BROWSE_FILE, StateType.ADD_TO_PIC_List));
56 | }
57 |
58 | private function handler_captureDone($evt:SSEvent):void
59 | {
60 | ssModel.drawOriginalSheet($evt.info.bmd);
61 | var __namesVO:NamesVO = $evt.info.updateNames as NamesVO;
62 | if(__namesVO)
63 | {
64 | ssModel.originalSheet.metadata.hasName = __namesVO.hasName;
65 | ssModel.originalSheet.metadata.names = __namesVO.names;
66 | ssModel.originalSheet.metadata.namesIndex = __namesVO.namesIndex;
67 | }
68 | stateModel.state = StateType.SS;
69 | }
70 |
71 | private function enterState($oldState:String, $newState:String):void
72 | {
73 | trace('picPanel.updateOnStateChanged:', $oldState, $newState);
74 | if($newState== StateType.PIC &&
75 | $oldState != $newState)
76 | {
77 | v.fileM.init();
78 | //如果是从START状态跳转过来的,就更新一次fileList的值
79 | if($oldState == StateType.START)
80 | {
81 | v.fileM.setFileList(fileOpener.selectedFiles);
82 | //trace("从start进入pic");
83 | //trace("file:", file.selectedFiles.length);
84 | //trace("enterState.fileList:", v.fileM.fileList.length);
85 | }
86 | }
87 | }
88 |
89 | protected function handler_build($event:SSEvent):void
90 | {
91 | ssModel.resetSheet(null, new SpriteSheetMetadata());
92 | v.capture();
93 | }
94 |
95 | private function handler_addFrame($evt:SSEvent):void
96 | {
97 | ssModel.addOriginalFrame($evt.info.bmd, $evt.info.rect);
98 | }
99 |
100 | private function handler_browseFileDone($evt:SSEvent):void
101 | {
102 | var __vo:BrowseFileDoneVO = $evt.info as BrowseFileDoneVO;
103 | if(__vo && __vo.openState == StateType.ADD_TO_PIC_List)
104 | {
105 | v.fileM.addFile2Manager(__vo.selectedFiles);
106 | }
107 | }
108 | }
109 | }
--------------------------------------------------------------------------------
/src/mediator/panel/SSPanelMediator.as:
--------------------------------------------------------------------------------
1 | package mediator.panel
2 | {
3 | import flash.display.BitmapData;
4 | import flash.events.Event;
5 | import flash.geom.Point;
6 | import flash.geom.Rectangle;
7 | import flash.text.ReturnKeyLabel;
8 | import vo.RectsAndBmdsVO;
9 |
10 | import events.SSEvent;
11 |
12 | import gnu.as3.gettext.FxGettext;
13 |
14 | import mediator.comps.FramesAndLabelMediator;
15 |
16 | import model.FileProcessor;
17 | import model.SpriteSheetModel;
18 | import model.StateModel;
19 |
20 | import org.robotlegs.mvcs.Mediator;
21 | import org.zengrong.display.spritesheet.ISpriteSheetMetadata;
22 | import org.zengrong.display.spritesheet.MaskType;
23 | import org.zengrong.display.spritesheet.SpriteSheetMetadata;
24 | import org.zengrong.display.spritesheet.SpriteSheetMetadataJSON;
25 | import org.zengrong.display.spritesheet.SpriteSheetMetadataStarling;
26 | import org.zengrong.display.spritesheet.SpriteSheetMetadataTXT;
27 | import org.zengrong.display.spritesheet.SpriteSheetMetadataXML;
28 | import org.zengrong.file.FileEnding;
29 | import org.zengrong.utils.BitmapUtil;
30 |
31 | import type.StateType;
32 |
33 | import utils.Funs;
34 |
35 | import view.panel.SSPanel;
36 |
37 | import vo.FrameVO;
38 | import vo.LabelListVO;
39 | import vo.SaveVO;
40 |
41 | public class SSPanelMediator extends Mediator
42 | {
43 | [Inject] public var v:SSPanel;
44 | [Inject] public var stateModel:StateModel;
45 | [Inject] public var ssModel:SpriteSheetModel;
46 |
47 | override public function onRegister():void
48 | {
49 | addContextListener(SSEvent.ENTER_STATE, handler_enterState);
50 | addContextListener(SSEvent.OPTIMIZE_SHEET, handler_optimizeSheet);
51 | addContextListener(SSEvent.PREVIEW_SS_CHANGE, handler_displayChange);
52 | addContextListener(SSEvent.PREVIEW_SS_SHOW, handler_previewShow);
53 | addContextListener(SSEvent.SELECTED_FRAMEINDICES_CHANGE, handler_selected_frameindices_change);
54 |
55 | eventMap.mapListener(v.saveSheet, SSEvent.SAVE_ALL, handler_saveAll);
56 | eventMap.mapListener(v.saveSheet, SSEvent.SAVE_META, handler_saveMeta);
57 | eventMap.mapListener(v.saveSheet, SSEvent.SAVE_PIC, handler_savePic);
58 | eventMap.mapListener(v.saveSeq, SSEvent.SAVE_SEQ, handler_saveSeq);
59 | eventMap.mapListener(v.optPanel, SSEvent.BUILD, handler_build);
60 | eventMap.mapListener(v.saveSheet.nameCB, Event.CHANGE, handler_nameCBChange);
61 | eventMap.mapListener(v.sheetPreview, SSEvent.PREVIEW_CLICK, handler_sheetPreviewClick);
62 |
63 | enterState();
64 | }
65 |
66 | override public function onRemove():void
67 | {
68 | trace('remove');
69 | removeContextListener(SSEvent.ENTER_STATE, handler_enterState);
70 | removeContextListener(SSEvent.OPTIMIZE_SHEET, handler_optimizeSheet);
71 | removeContextListener(SSEvent.PREVIEW_SS_CHANGE, handler_displayChange);
72 | removeContextListener(SSEvent.PREVIEW_SS_SHOW, handler_previewShow);
73 | removeContextListener(SSEvent.SELECTED_FRAMEINDICES_CHANGE, handler_selected_frameindices_change);
74 |
75 | eventMap.unmapListener(v.saveSheet, SSEvent.SAVE_ALL, handler_saveAll);
76 | eventMap.unmapListener(v.saveSheet, SSEvent.SAVE_META, handler_saveMeta);
77 | eventMap.unmapListener(v.saveSheet, SSEvent.SAVE_PIC, handler_savePic);
78 | eventMap.unmapListener(v.saveSeq, SSEvent.SAVE_SEQ, handler_saveSeq);
79 | eventMap.unmapListener(v.optPanel, SSEvent.BUILD, handler_build);
80 | eventMap.unmapListener(v.saveSheet.nameCB, Event.CHANGE, handler_nameCBChange);
81 | eventMap.unmapListener(v.sheetPreview, SSEvent.PREVIEW_CLICK, handler_sheetPreviewClick);
82 |
83 | exitState();
84 | }
85 |
86 | private function handler_sheetPreviewClick($evt:SSEvent):void
87 | {
88 | dispatch($evt);
89 | }
90 |
91 | protected function handler_nameCBChange($evt:Event):void
92 | {
93 | ssModel.adjustedSheet.metadata.hasName = v.saveSheet.nameCB.selected;
94 | }
95 |
96 | private function handler_displayChange($evt:SSEvent):void
97 | {
98 | v.saveSeq.titleLabel.text = ssModel.displayCrop ?
99 | FxGettext.gettext("trimmed size"):
100 | FxGettext.gettext("original size");
101 | }
102 |
103 | private function handler_saveAll($evt:SSEvent):void
104 | {
105 | updateMetadata();
106 | var __vo:SaveVO = v.getSheetSaveVO();
107 | var __bmd:BitmapData = ssModel.getBitmapDataForSave(v.maskTypeValue, v.transparent, v.bgColor);
108 | __vo.bitmapData = __bmd;
109 | __vo.metadata = getMetadata();
110 | __vo.type = StateType.SAVE_ALL;
111 | dispatch(new SSEvent(SSEvent.SAVE, __vo));
112 | }
113 |
114 | protected function handler_saveMeta($event:SSEvent):void
115 | {
116 | updateMetadata();
117 | var __vo:SaveVO = v.getSheetSaveVO();
118 | __vo.metadata = getMetadata();
119 | __vo.type = StateType.SAVE_META;
120 | dispatch(new SSEvent(SSEvent.SAVE, __vo));
121 | }
122 |
123 | protected function handler_savePic($event:SSEvent):void
124 | {
125 | updateMetadata();
126 | var __vo:SaveVO =v.getSheetSaveVO();
127 | __vo.bitmapData = ssModel.getBitmapDataForSave(v.maskTypeValue, v.transparent, v.bgColor);
128 | __vo.type = StateType.SAVE_SHEET_PIC;
129 | dispatch(new SSEvent(SSEvent.SAVE, __vo));
130 | }
131 |
132 | private function handler_saveSeq($evt:SSEvent):void
133 | {
134 | var __vo:SaveVO = v.getSeqSaveVO();
135 | __vo.fileNameList = v.getSeqFileNames(ssModel.adjustedSheet.metadata.totalFrame);
136 | __vo.type = StateType.SAVE_SEQ;
137 | //根据显示的帧类型来保存序列
138 | __vo.bitmapDataList = ssModel.getBMDList();
139 | dispatch(new SSEvent(SSEvent.SAVE, __vo));
140 | }
141 |
142 | private function handler_enterState($evt:SSEvent):void
143 | {
144 | enterState();
145 | }
146 |
147 | private function enterState():void
148 | {
149 | if(stateModel.state != StateType.SS) return;
150 | //更新调整后的Sheet
151 | ssModel.updateAdjustedSheet();
152 | v.init(ssModel.adjustedSheet.bitmapData, ssModel.originalSheet.metadata.hasName);
153 |
154 | mediatorMap.createMediator(v.framesAndLabels);
155 | }
156 |
157 | private function exitState():void
158 | {
159 | ssModel.destroySheet();
160 | v.destroy();
161 |
162 | mediatorMap.removeMediatorByView(v.framesAndLabels);
163 | }
164 |
165 | protected function handler_build($evt:SSEvent):void
166 | {
167 | dispatch(new SSEvent(SSEvent.OPTIMIZE_SHEET));
168 | }
169 |
170 | protected function handler_optimizeSheet($evt:SSEvent):void
171 | {
172 | optimizeSheet();
173 | }
174 |
175 | //在预览更新的时候,绘制帧的范围
176 | private function handler_previewShow($evt:SSEvent):void
177 | {
178 | //仅在播放的时候才绘制帧的范围
179 | if(ssModel.playing)
180 | {
181 | var __rect:Rectangle = $evt.info.rect as Rectangle;
182 | v.sheetPreview.clearCanva();
183 | v.sheetPreview.drawRect(__rect.x, __rect.y, __rect.width, __rect.height);
184 | }
185 | }
186 |
187 | //在选择帧的时候,绘制选择的帧的范围
188 | private function handler_selected_frameindices_change($evt:SSEvent):void
189 | {
190 | var __frames:Vector. = $evt.info as Vector.;
191 | if(__frames && __frames.length>0)
192 | {
193 | v.sheetPreview.clearCanva();
194 | for (var i:int = 0; i < __frames.length; i++)
195 | {
196 | var __rect:Rectangle = __frames[i].frameRect;
197 | v.sheetPreview.drawRect(__rect.x, __rect.y, __rect.width, __rect.height);
198 | }
199 | }
200 | }
201 |
202 | /**
203 | * 根据当前的选择优化Sheet,优化的信息会被写入adjustedSheet中
204 | */
205 | private function optimizeSheet():void
206 | {
207 | v.sheetPreview.destroy();
208 | if(ssModel.originalSheet.metadata.totalFrame==0 || ssModel.adjustedSheet.metadata.totalFrame==0)
209 | {
210 | Funs.alert(FxGettext.gettext("No frame info, can not generate the sheet."));
211 | v.leftPanelBG.enabled = false;
212 | return;
213 | }
214 | trace('优化帧数:', ssModel.originalSheet.metadata.totalFrame, ssModel.adjustedSheet.metadata.totalFrame);
215 | var __list:RectsAndBmdsVO = ssModel.getRectsAndBmds(v.trim, v.resetRect);
216 | trace('新生成的:', __list.bmds, __list.frameRects, __list.originRects)
217 | //保存新计算出的WH
218 | var __whRect:Rectangle = new Rectangle();
219 | //保存新计算出的每个帧在大Sheet中放置的位置
220 | var __newFrameRects:Vector. = new Vector.;
221 | //重新计算出最终Sheet的宽高以及修改过的frameRect
222 | Funs.calculateSize(
223 | __list.frameRects,
224 | __newFrameRects,
225 | __whRect,
226 | v.limitWidth,
227 | v.explicitSize,
228 | v.powerOf2,
229 | v.square
230 | );
231 | //绘制大Sheet位图
232 | var __sheetBmd:BitmapData = new BitmapData(__whRect.width, __whRect.height, v.transparent, v.bgColor);
233 | ssModel.redrawAdjustedSheet(__sheetBmd, new RectsAndBmdsVO(__list.bmds, __list.originRects, __newFrameRects));
234 | v.sheetPreview.source = ssModel.adjustedSheet.bitmapData;
235 | //优化完毕,FramesAndLabel需要更新
236 | dispatch(new SSEvent(SSEvent.OPTIMIZE_SHEET_DONE));
237 | }
238 |
239 | /**
240 | * 更新spriteSheet的metadata。在生成新的SpriteSheet前调用。
241 | */
242 | private function updateMetadata():void
243 | {
244 | //hasName, names, namesIndex, totalFrame, frameRects, originalFrameRects 这几个变量
245 | //是在生成Sheet的时候填充的,因此这里不需要更新
246 | var __meta:ISpriteSheetMetadata = ssModel.adjustedSheet.metadata;
247 | __meta.type = v.sheetType;
248 | __meta.maskType = v.saveSheet.maskDDL.selectedIndex;
249 | var __mediator:FramesAndLabelMediator = mediatorMap.retrieveMediator(v.framesAndLabels) as FramesAndLabelMediator;
250 | var __labelMeta:LabelListVO = __mediator.getLabels();
251 | __meta.hasLabel = __labelMeta.hasLabel;
252 | __meta.labels = __labelMeta.labels;
253 | __meta.labelsFrame = __labelMeta.labelsFrame;
254 | }
255 |
256 | private function getMetadata():ISpriteSheetMetadata
257 | {
258 | var __meta:ISpriteSheetMetadata = null;
259 | if(v.saveSheet.jsonRB.selected)
260 | {
261 | __meta = new SpriteSheetMetadataJSON(ssModel.adjustedSheet.metadata);
262 | }
263 | else if(v.saveSheet.xmlRB.selected)
264 | {
265 | __meta = new SpriteSheetMetadataXML(ssModel.adjustedSheet.metadata);
266 | SpriteSheetMetadataXML(__meta).header = Funs.getXMLHeader(FileEnding.UNIX);
267 | }
268 | else if(v.saveSheet.starlingRB.selected)
269 | {
270 | __meta = new SpriteSheetMetadataStarling(ssModel.adjustedSheet.metadata);
271 | SpriteSheetMetadataStarling(__meta).header = Funs.getXMLHeader(FileEnding.UNIX);
272 | }
273 | else
274 | {
275 | __meta = new SpriteSheetMetadataTXT(ssModel.adjustedSheet.metadata);
276 | }
277 | return __meta;
278 | }
279 | }
280 | }
--------------------------------------------------------------------------------
/src/mediator/panel/StartPanelMediator.as:
--------------------------------------------------------------------------------
1 | package mediator.panel
2 | {
3 | import events.SSEvent;
4 | import flash.events.MouseEvent;
5 | import model.FileProcessor;
6 | import org.robotlegs.mvcs.Mediator;
7 | import type.StateType;
8 | import view.panel.StartPanel;
9 |
10 | public class StartPanelMediator extends Mediator
11 | {
12 | [Inject] public var v:StartPanel;
13 |
14 | override public function onRegister():void
15 | {
16 | eventMap.mapListener(v.openSWFBTN, MouseEvent.CLICK, handler_openSWFBTNClick);
17 | eventMap.mapListener(v.openPicBTN, MouseEvent.CLICK, handler_openPicBTNClick);
18 | eventMap.mapListener(v.openSSBTN, MouseEvent.CLICK, handler_openSSBTNclick);
19 |
20 | //addContextListener(SSEvent.ENTER_STATE, handler_enterState);
21 | }
22 |
23 | override public function onRemove():void
24 | {
25 | eventMap.unmapListener(v.openSWFBTN, MouseEvent.CLICK, handler_openSWFBTNClick);
26 | eventMap.unmapListener(v.openPicBTN, MouseEvent.CLICK, handler_openPicBTNClick);
27 | eventMap.unmapListener(v.openSSBTN, MouseEvent.CLICK, handler_openSSBTNclick);
28 |
29 | //removeContextListener(SSEvent.ENTER_STATE, handler_enterState);
30 | }
31 |
32 |
33 | protected function handler_openSWFBTNClick(event:MouseEvent):void
34 | {
35 | dispatch(new SSEvent(SSEvent.BROWSE_FILE,StateType.SWF));
36 | }
37 |
38 | protected function handler_openPicBTNClick(event:MouseEvent):void
39 | {
40 | dispatch(new SSEvent(SSEvent.BROWSE_FILE,StateType.PIC));
41 | }
42 |
43 | protected function handler_openSSBTNclick(event:MouseEvent):void
44 | {
45 | dispatch(new SSEvent(SSEvent.BROWSE_FILE,StateType.SS));
46 | }
47 |
48 | public function handler_enterState($evt:SSEvent):void
49 | {
50 | //trace('StartPanelMediator.updateOnStateChanged:', $evt.info.oldState, $evt.info.newState);
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/src/mediator/panel/SwfPanelMediator.as:
--------------------------------------------------------------------------------
1 | package mediator.panel
2 | {
3 | import events.SSEvent;
4 | import flash.filesystem.File;
5 | import model.FileOpenerModel;
6 | import model.SpriteSheetModel;
7 | import model.StateModel;
8 | import org.robotlegs.mvcs.Mediator;
9 | import org.zengrong.display.spritesheet.SpriteSheetMetadata;
10 | import type.StateType;
11 | import view.panel.SwfPanel;
12 |
13 | /**
14 | * @author zrong
15 | * 创建日期:2012-07-18
16 | */
17 | public class SwfPanelMediator extends Mediator
18 | {
19 | [Inject] public var v:SwfPanel;
20 |
21 | [Inject] public var stateModel:StateModel;
22 |
23 | [Inject] public var fileOpener:FileOpenerModel;
24 |
25 | [Inject] public var ssModel:SpriteSheetModel;
26 |
27 | private var _swfURL:String;
28 |
29 | private var _swfContentX:int = 0;
30 | private var _swfContentY:int = 0;
31 |
32 | override public function onRegister():void
33 | {
34 | addViewListener(SSEvent.CAPTURE_DONE, handler_captureDone);
35 | addViewListener(SSEvent.ADD_FRAME, handler_addFrame);
36 | eventMap.mapListener(v.buildSetting, SSEvent.BUILD, handler_buildClick);
37 |
38 | addContextListener(SSEvent.ENTER_STATE, handler_enterState);
39 |
40 | enterState(stateModel.oldState, stateModel.state);
41 | }
42 |
43 | override public function onRemove():void
44 | {
45 | removeViewListener(SSEvent.CAPTURE_DONE, handler_captureDone);
46 | removeViewListener(SSEvent.ADD_FRAME, handler_addFrame);
47 | eventMap.unmapListener(v.buildSetting, SSEvent.BUILD, handler_buildClick);
48 |
49 | removeContextListener(SSEvent.ENTER_STATE, handler_enterState);
50 |
51 | v.destroy();
52 | v.swf.removeEventListener(SSEvent.PREVIEW_LOAD_COMPLETE, handler_swfLoadDone);
53 | }
54 |
55 | private function handler_captureDone($evt:SSEvent):void
56 | {
57 | v.state = StateType.LOAD_DONE;
58 | ssModel.drawOriginalSheet($evt.info);
59 | stateModel.state = StateType.SS;
60 | }
61 |
62 | private function handler_enterState($evt:SSEvent):void
63 | {
64 | enterState($evt.info.oldState, $evt.info.newState);
65 | }
66 |
67 | private function enterState($oldState:String, $newState:String):void
68 | {
69 | if($newState == StateType.SWF)
70 | {
71 | _swfURL = File(fileOpener.selectedFiles[0]).url;
72 | trace('swfPanel.load:', _swfURL);
73 | if(_swfURL)
74 | {
75 | v.swf.addEventListener(SSEvent.PREVIEW_LOAD_COMPLETE, handler_swfLoadDone);
76 | v.showSWF(_swfURL);
77 | }
78 | }
79 | }
80 |
81 | private function handler_swfLoadDone(event:SSEvent) : void
82 | {
83 | //若当前处于等待载入状态,则开始建立sheet
84 | if(v.state == StateType.WAIT_LOADED)
85 | {
86 | //如果允许调整尺寸,使用调整过的
87 | if(v.swf.enableDragContent)
88 | v.swf.moveContent(_swfContentX, _swfContentY);
89 | //开始capture
90 | v.state = StateType.PROCESSING;
91 | ssModel.resetSheet(null, new SpriteSheetMetadata());
92 | v.capture();
93 | }
94 | else
95 | {
96 | v.state = StateType.LOAD_DONE;
97 | }
98 | }
99 |
100 | private function handler_buildClick($evt:SSEvent):void
101 | {
102 | v.state = StateType.WAIT_LOADED;
103 | //记录当前移动的内容坐标,以便载入成功后还原
104 | _swfContentX = v.swf.contentX;
105 | _swfContentY = v.swf.contentY;
106 | v.build(_swfURL);
107 | }
108 |
109 | private function handler_addFrame($evt:SSEvent):void
110 | {
111 | ssModel.addOriginalFrame($evt.info.bmd, $evt.info.rect);
112 | }
113 | }
114 | }
--------------------------------------------------------------------------------
/src/mediator/panel/TopPanelMediator.as:
--------------------------------------------------------------------------------
1 | package mediator.panel
2 | {
3 | import events.SSEvent;
4 |
5 | import flash.events.Event;
6 | import flash.events.MouseEvent;
7 |
8 | import model.StateModel;
9 |
10 | import org.robotlegs.mvcs.Mediator;
11 | import org.zengrong.utils.SOUtil;
12 |
13 | import type.StateType;
14 |
15 | import view.panel.TopPanel;
16 |
17 | public class TopPanelMediator extends Mediator
18 | {
19 | [Inject] public var v:TopPanel;
20 |
21 | [Inject] public var stateModel:StateModel;
22 |
23 | private var _prevState:String;
24 |
25 | private var _so:SOUtil;
26 |
27 | override public function onRegister():void
28 | {
29 | eventMap.mapListener(v.prevBTN, MouseEvent.CLICK, handler_prievBTNClick);
30 | eventMap.mapListener(v.fpsNS, Event.CHANGE, handler_fpsNSChange);
31 |
32 | eventMap.mapListener(eventDispatcher, SSEvent.ENTER_STATE, handler_enterState);
33 |
34 | _so = SOUtil.getSOUtil('sse');
35 | showFPS();
36 | }
37 |
38 | private function handler_enterState($evt:SSEvent):void
39 | {
40 | enterState($evt.info.oldState, $evt.info.newState);
41 | }
42 |
43 | private function showFPS():void
44 | {
45 | v.fpsGRP.visible = (stateModel.state != StateType.START);
46 | var __frameRate:int = int(_so.get('frameRate'));
47 | if(__frameRate > 0)
48 | {
49 | v.fpsNS.value = __frameRate;
50 | v.stage.frameRate = v.fpsNS.value;
51 | }
52 | }
53 |
54 | private function enterState($oldState:String, $newState:String):void
55 | {
56 | if(!$oldState && !$newState) return;
57 | v.stateNameLabel.text = StateType.toMainStateName($newState);
58 | if($newState == StateType.START)
59 | {
60 | _prevState = null;
61 | }
62 | else
63 | {
64 | _prevState = $oldState;
65 | //如果状态是反向跳转(从后一步跳转到前一步),那么就将返回按钮指向第一步
66 | if( ($newState == StateType.PIC || $newState == StateType.SWF) &&
67 | ($oldState != StateType.START) )
68 | _prevState = StateType.START;
69 | }
70 | trace(_prevState);
71 | v.prevBTN.enabled = (_prevState != null);
72 | showFPS();
73 | }
74 |
75 | protected function handler_fpsNSChange(event:Event):void
76 | {
77 | v.stage.frameRate = v.fpsNS.value;
78 | _so.save(v.fpsNS.value, 'frameRate');
79 | }
80 |
81 | protected function handler_prievBTNClick(event:MouseEvent):void
82 | {
83 | stateModel.state = _prevState;
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/src/model/FileOpenerModel.as:
--------------------------------------------------------------------------------
1 | package model
2 | {
3 | import events.SSEvent;
4 | import flash.events.IOErrorEvent;
5 | import flash.filesystem.File;
6 | import gnu.as3.gettext.FxGettext;
7 | import org.zengrong.assets.AssetsType;
8 | import org.zengrong.display.spritesheet.SpriteSheetMetadataType;
9 | import org.zengrong.net.SpriteSheetLoader;
10 | import type.ExtendedNameType;
11 | import type.StateType;
12 | import flash.events.Event;
13 | import flash.events.FileListEvent;
14 | import utils.Funs;
15 | import vo.BrowseFileDoneVO;
16 | /**
17 | * 负责打开文件
18 | * @author zrong(zengrong.net)
19 | * Creation: 2013-08-19
20 | */
21 | public class FileOpenerModel extends FileProcessor
22 | {
23 | public function FileOpenerModel()
24 | {
25 | super();
26 | _ssLoader = new SpriteSheetLoader();
27 | _ssLoader.addEventListener(Event.COMPLETE, handler_ssLoadComplete);
28 | _ssLoader.addEventListener(IOErrorEvent.IO_ERROR, handler_ssLoadError);
29 | }
30 |
31 | [Inject] public var ssModel:SpriteSheetModel;
32 |
33 | private var _ssLoader:SpriteSheetLoader; //用于载入现有的SpriteSheet
34 |
35 | private var _selectedFiles:Array; //选择的文件数组
36 |
37 | public function get selectedFiles():Array
38 | {
39 | return _selectedFiles;
40 | }
41 |
42 | //----------------------------------------
43 | // 打开文件操作
44 | //----------------------------------------
45 |
46 | public function open($state:String):void
47 | {
48 | _openState = $state;
49 | switch(_openState)
50 | {
51 | case StateType.SWF:
52 | _file.browseForOpen(FxGettext.gettext("Select a swf file"), [ExtendedNameType.SWF_FILTER]);
53 | break;
54 | case StateType.SS:
55 | _file.browseForOpen(FxGettext.gettext("Select a Sprite Sheet file"), ExtendedNameType.ALL_PIC_FILTER_LIST);
56 | break;
57 | case StateType.PIC:
58 | _file.browseForOpenMultiple(FxGettext.gettext("Select image file"), ExtendedNameType.ALL_PIC_FILTER_LIST);
59 | break;
60 | case StateType.ADD_TO_PIC_List:
61 | _file.browseForOpenMultiple(FxGettext.gettext("Select image file"), ExtendedNameType.ALL_PIC_FILTER_LIST);
62 | break;
63 | case StateType.ADD_TO_SS:
64 | _file.browseForOpenMultiple(FxGettext.gettext("Select image file"), ExtendedNameType.ALL_PIC_FILTER_LIST);
65 | break;
66 | }
67 | }
68 |
69 |
70 | /**
71 | * 打开一个被拖入界面中的文件
72 | * @param $file 要处理的文件,可能是一个File,也可能是File数组
73 | * @param $openState 打开的状态
74 | */
75 | public function openFilesByDrag($files:Array, $openState:String):void
76 | {
77 | _openState = $openState;
78 | checkSelectedFiles($files);
79 | }
80 |
81 | private function checkSelectedFiles($files:Array):void
82 | {
83 | _selectedFiles = $files;
84 | if(StateType.isViewState(_openState))
85 | {
86 | //如果要切换到SS状态,需要等待SS文件载入并解析完毕后才能切换状态。
87 | //载入的工作交给SpriteSheetLaoderModel。
88 | if(_openState == StateType.SS)
89 | _ssLoader.load(File(_selectedFiles[0]).url);
90 | //如果发生选择事件的state是编辑器界面/open状态,就执行状态切换
91 | else
92 | stateModel.state = _openState;
93 | }
94 | if(_openState == StateType.ADD_TO_PIC_List ||
95 | _openState == StateType.ADD_TO_SS)
96 | {
97 | var __bfd:BrowseFileDoneVO = new BrowseFileDoneVO(_openState, _selectedFiles);
98 | //向SS中加入帧的时候,要判断加入的文件是否是SS类型
99 | if(_openState == StateType.ADD_TO_SS &&
100 | Funs.hasMetadataFile((_selectedFiles[0] as File).url, SpriteSheetMetadataType.XML))
101 | {
102 | __bfd.fileType = AssetsType.SPRITE_SHEET;
103 | __bfd.metaType = SpriteSheetMetadataType.XML;
104 | }
105 | this.dispatch(new SSEvent(SSEvent.BROWSE_FILE_DONE, __bfd));
106 | }
107 | //trace('checkSelectedFiles', _file.nativePath, $evt.files, _openState);
108 | }
109 |
110 | //----------------------------------------
111 | // handler
112 | //----------------------------------------
113 | override protected function handler_selectSingle($evt:Event):void
114 | {
115 | checkSelectedFiles([_file.clone()]);
116 | }
117 |
118 | override protected function handler_selectMulti($evt:FileListEvent):void
119 | {
120 | checkSelectedFiles($evt.files);
121 | }
122 |
123 | /**
124 | * 打开SS格式,载入SS完毕后调用
125 | */
126 | private function handler_ssLoadComplete($evt:Event):void
127 | {
128 | ssModel.updateOriginalSheet(_ssLoader.getSpriteSheet());
129 | stateModel.state = StateType.SS;
130 | }
131 |
132 | private function handler_ssLoadError($evt:IOErrorEvent):void
133 | {
134 | Funs.alert($evt.text);
135 | }
136 | }
137 | }
--------------------------------------------------------------------------------
/src/model/FileProcessor.as:
--------------------------------------------------------------------------------
1 | package model
2 | {
3 | import flash.events.Event;
4 | import flash.events.FileListEvent;
5 | import flash.filesystem.File;
6 | import org.robotlegs.mvcs.Actor;
7 |
8 | /**
9 | * 专门负责对文件的处理,基类。
10 | * @author zrong(zengrong.net)
11 | * Creation: 2011-8-3
12 | * Modification: 2013-08-19
13 | */
14 | public class FileProcessor extends Actor
15 | {
16 | [Inject] public var stateModel:StateModel;
17 |
18 | public function FileProcessor()
19 | {
20 | initFile(File.desktopDirectory);
21 | }
22 |
23 | protected var _file:File;
24 | protected var _openState:String;
25 |
26 | protected function initFile($file:File):void
27 | {
28 | if(_file)
29 | {
30 | _file.removeEventListener(FileListEvent.SELECT_MULTIPLE, handler_selectMulti);
31 | _file.removeEventListener(Event.SELECT, handler_selectSingle);
32 | _file.removeEventListener(Event.CANCEL, handler_selectCancel);
33 | }
34 | _file = $file;
35 | _file.addEventListener(FileListEvent.SELECT_MULTIPLE, handler_selectMulti);
36 | _file.addEventListener(Event.SELECT, handler_selectSingle);
37 | _file.addEventListener(Event.CANCEL, handler_selectCancel);
38 | }
39 |
40 | public function get openState():String
41 | {
42 | return _openState;
43 | }
44 |
45 | //----------------------------------------
46 | // handler
47 | //----------------------------------------
48 |
49 | protected function handler_selectSingle($evt:Event):void
50 | {
51 | }
52 |
53 | protected function handler_selectMulti($evt:FileListEvent):void
54 | {
55 | }
56 |
57 | protected function handler_selectCancel($evt:Event):void
58 | {
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/src/model/FileSaverModel.as:
--------------------------------------------------------------------------------
1 | package model
2 | {
3 | import flash.display.BitmapData;
4 | import flash.display.JPEGEncoderOptions;
5 | import flash.display.JPEGXREncoderOptions;
6 | import flash.display.PNGEncoderOptions;
7 | import flash.filesystem.File;
8 | import flash.filesystem.FileMode;
9 | import flash.filesystem.FileStream;
10 | import flash.utils.ByteArray;
11 | import gnu.as3.gettext.FxGettext;
12 | import type.ExtendedNameType;
13 | import type.StateType;
14 | import vo.SaveVO;
15 | import flash.events.Event;
16 | /**
17 | * 负责保存文件
18 | * @author zrong(zengrong.net)
19 | * Creation: 2013-08-19
20 | */
21 | public class FileSaverModel extends FileProcessor
22 | {
23 | public function FileSaverModel()
24 | {
25 | super();
26 | }
27 |
28 | private var _saveData:SaveVO;
29 |
30 | //----------------------------------------
31 | // 保存文件操作
32 | //----------------------------------------
33 |
34 | public function save($vo:SaveVO):void
35 | {
36 | _saveData = $vo;
37 | _openState = _saveData.type;
38 | var __title:String;
39 | switch(_saveData.type)
40 | {
41 | case StateType.SAVE_SHEET_PIC:
42 | __title = FxGettext.gettext("Select the save path of Sprite Sheet file");
43 | //更新一次File的引用,是为了避免File指向老的已经存在的图片,导致AIR的覆盖提示错误
44 | initFile(getFile(_saveData.picType));
45 | _file.browseForSave(__title);
46 | break;
47 | case StateType.SAVE_META:
48 | __title = FxGettext.gettext("Select the save path of metadata");
49 | _file.browseForSave(__title);
50 | break;
51 | case StateType.SAVE_SEQ:
52 | __title = FxGettext.gettext("Select the save path of the image sequence");
53 | _file.browseForDirectory(__title);
54 | break;
55 | case StateType.SAVE_ALL:
56 | __title = FxGettext.gettext("Select the save path of image and metedata");
57 | //更新一次File的引用,是为了避免File指向老的已经存在的图片,导致AIR的覆盖提示错误
58 | initFile(getFile(_saveData.picType));
59 | _file.browseForSave(__title);
60 | break;
61 | }
62 | }
63 |
64 | private function saveData():void
65 | {
66 | var __stream:FileStream = new FileStream();
67 | var __ba:ByteArray = null;
68 | var __imgFile:File = getFile(_saveData.picType);
69 | if(_openState == StateType.SAVE_META)
70 | {
71 | __stream.open(getFile(_saveData.metaType), FileMode.WRITE);
72 | __stream.writeUTFBytes(_saveData.metadata.objectify(_saveData.isSimple, _saveData.includeName, __imgFile.name));
73 | __stream.close();
74 | }
75 | else if(_openState == StateType.SAVE_SHEET_PIC)
76 | {
77 | __ba = getSheet(_saveData.bitmapData, _saveData.picType, _saveData.quality);
78 | __stream.open(__imgFile, FileMode.WRITE);
79 | __stream.writeBytes(__ba);
80 | __stream.close();
81 | }
82 | else if(_openState == StateType.SAVE_ALL)
83 | {
84 | //使用sheet的扩展名(数组元素0)新建一个File
85 | __ba = getSheet(_saveData.bitmapData, _saveData.picType, _saveData.quality);
86 | __stream.open(__imgFile, FileMode.WRITE);
87 | __stream.writeBytes(__ba);
88 | __stream.close();
89 |
90 | //使用metadata的扩展名(数组元素1)新建一个File
91 | __stream.open(getFile(_saveData.metaType), FileMode.WRITE);
92 | __stream.writeUTFBytes(_saveData.metadata.objectify(_saveData.isSimple, _saveData.includeName,__imgFile.name));
93 | __stream.close();
94 | }
95 | else if(_openState == StateType.SAVE_SEQ)
96 | {
97 | var __bmds:Vector. = _saveData.bitmapDataList;
98 | var __names:Vector. = _saveData.fileNameList;
99 | //获取文件的扩展名
100 | var __ext:String = __names[0].slice(__names[0].lastIndexOf('.'));
101 | for (var i:int = 0; i < __bmds.length; i++)
102 | {
103 | __ba = getSheet(__bmds[i], __ext, _saveData.quality);
104 | __stream.open(_file.resolvePath(__names[i]), FileMode.WRITE);
105 | __stream.writeBytes(__ba);
106 | __stream.close();
107 | }
108 | }
109 | }
110 |
111 | //----------------------------------------
112 | // 内部方法
113 | //----------------------------------------
114 |
115 | /**
116 | * 根据扩展名,制作一个新的File文件对象并返回
117 | */
118 | private function getFile($ext:String):File
119 | {
120 | var __file:File = _file.parent.resolvePath(_file.name.split('.')[0]+$ext);
121 | return __file;
122 | }
123 |
124 | /**
125 | * 获取压缩之后的Sheet的Byte
126 | */
127 | private function getSheet($bmd:BitmapData, $ext:String, $quality:int=70):ByteArray
128 | {
129 | var __ba:ByteArray = null;
130 | var __opt:*;
131 | if($ext == ExtendedNameType.PNG)
132 | {
133 | __opt = new PNGEncoderOptions();
134 | }
135 | else if($ext == ExtendedNameType.JPEG_XR)
136 | {
137 | __opt = new JPEGXREncoderOptions($quality);
138 | }
139 | else
140 | {
141 | __opt = new JPEGEncoderOptions($quality);
142 | }
143 | return $bmd.encode($bmd.rect, __opt);
144 | }
145 |
146 | override protected function handler_selectSingle($evt:Event):void
147 | {
148 | saveData();
149 | }
150 | }
151 | }
--------------------------------------------------------------------------------
/src/model/SpriteSheetModel.as:
--------------------------------------------------------------------------------
1 | package model
2 | {
3 | import flash.display.BitmapData;
4 | import flash.geom.Rectangle;
5 | import org.zengrong.display.spritesheet.MaskType;
6 | import org.zengrong.utils.BitmapUtil;
7 | import vo.RectsAndBmdsVO;
8 |
9 | import org.robotlegs.mvcs.Actor;
10 | import org.zengrong.display.spritesheet.SpriteSheet;
11 | import org.zengrong.display.spritesheet.SpriteSheetMetadata;
12 |
13 | /**
14 | * 暂存编辑过程中的位图资源
15 | * @author zrong
16 | * 创建日期:2012-07-25
17 | */
18 | public class SpriteSheetModel extends Actor
19 | {
20 | public function SpriteSheetModel()
21 | {
22 | }
23 |
24 |
25 | public function resetSheet($bmd:BitmapData=null, $meta:SpriteSheetMetadata=null):void
26 | {
27 | if(_originalSheet) _originalSheet.destroy();
28 | _originalSheet = new SpriteSheet($bmd, $meta);
29 | }
30 |
31 | public function getBMDList():Vector.
32 | {
33 | if(displayCrop) return adjustedSheet.getAll();
34 | return originalSheet.getAll();
35 | }
36 |
37 | public function destroySheet():void
38 | {
39 | if(_originalSheet) _originalSheet.destroy();
40 | _originalSheet = null;
41 | if(adjustedSheet) adjustedSheet.destroy();
42 | _adjustedSheet = null;
43 | }
44 |
45 | private var _originalSheet:SpriteSheet;
46 | /**
47 | * 刚生成的sheet,或者打开的sheet文件,保存在此对象中。在此sheet的基础上进行调整后保存
48 | */
49 | public function get originalSheet():SpriteSheet
50 | {
51 | return _originalSheet;
52 | }
53 |
54 | /**
55 | * 更新当前保存的原始Sheet
56 | */
57 | public function updateOriginalSheet($sheet:SpriteSheet):void
58 | {
59 | if(_originalSheet) _originalSheet.destroy();
60 | _originalSheet = $sheet;
61 | _originalSheet.parseSheet();
62 | }
63 |
64 | private var _adjustedSheet:SpriteSheet;
65 |
66 | /**
67 | * 保存调整过的Sheet。对生成的sheet经常会做一些调整,例如剔除透明像素,加背景色等等,调整后的结果保存在此对象中
68 | */
69 | public function get adjustedSheet():SpriteSheet
70 | {
71 | return _adjustedSheet;
72 | }
73 |
74 | /**
75 | * 基于原始的Sheet更新调整后的Sheet
76 | */
77 | public function updateAdjustedSheet():void
78 | {
79 | //TODO 将支持多语言
80 | if(!_originalSheet) throw new TypeError("无法获取原始Sprite Sheet!");
81 | if(_adjustedSheet) _adjustedSheet.destroy();
82 | _adjustedSheet = _originalSheet.clone();
83 | }
84 |
85 | public function drawOriginalSheet($bmd:BitmapData):void
86 | {
87 | _originalSheet.drawSheet($bmd);
88 | }
89 |
90 | public function addOriginalFrame($bmd:BitmapData, $sizeRect:Rectangle=null, $originalRect:Rectangle=null, $name:String=null):void
91 | {
92 | _originalSheet.addFrame($bmd, $sizeRect, $originalRect, $name);
93 | }
94 |
95 | public function addOriginalFrameAt($index:int, $bmd:BitmapData, $sizeRect:Rectangle=null, $originalRect:Rectangle=null,$name:String=null):void
96 | {
97 | _originalSheet.addFrameAt($index, $bmd, $sizeRect, $originalRect, $name);
98 | }
99 |
100 | /**
101 | * 重新设置Sheet中的帧信息,并重绘Sheet位图
102 | * @param $bmd
103 | * @param $list
104 | */
105 | public function redrawAdjustedSheet($bmd:BitmapData, $list:RectsAndBmdsVO):void
106 | {
107 | _adjustedSheet.setFrames($list.bmds, $list.frameRects, $list.originRects, originalSheet.metadata.names);
108 | _adjustedSheet.drawSheet($bmd);
109 | }
110 |
111 | public function addAdjustedFrame($bmd:BitmapData, $sizeRect:Rectangle=null, $originalRect:Rectangle=null, $name:String=null):void
112 | {
113 | _adjustedSheet.addFrame($bmd, $sizeRect, $originalRect, $name);
114 | }
115 |
116 | public function addAdjustedFrameAt($index:int, $bmd:BitmapData, $sizeRect:Rectangle=null, $originalRect:Rectangle=null,$name:String=null):void
117 | {
118 | _adjustedSheet.addFrameAt($index, $bmd, $sizeRect, $originalRect, $name);
119 | }
120 |
121 | /**
122 | * 绘制Mask,返回带有Mask的位图(如果有mask的话)
123 | */
124 | public function getBitmapDataForSave($maskType:int, $transparent:Boolean, $bgcolor:uint):BitmapData
125 | {
126 | if(MaskType.useMask($maskType))
127 | {
128 | return BitmapUtil.getBitmapDataWithMask(adjustedSheet.bitmapData, $maskType == MaskType.HOR_MASK, $transparent, $bgcolor);
129 | }
130 | return adjustedSheet.bitmapData;
131 | }
132 |
133 | /**
134 | * 返回生成的原始帧rect尺寸(origin),在大sheet中的rect尺寸(frame),以及所有的BitmapData列表(bmd)
135 | * @param $trim 是否修剪
136 | * @param $reset 是否重置大小
137 | */
138 | public function getRectsAndBmds($trim:Boolean, $reset:Boolean):RectsAndBmdsVO
139 | {
140 | //所有的BitmapData列表
141 | var __bmd:Vector. = null;
142 | //在大sheet中的rect列表
143 | var __frame:Vector. = null;
144 | //原始的(在程序中使用的)rect列表
145 | var __origin:Vector. = null;
146 | if($trim)
147 | {
148 | __bmd = new Vector.;
149 | __frame = new Vector.;
150 | __origin = new Vector.;
151 | var __sizeRect:Rectangle = null;
152 | //用于保存执行trim方法后的结果
153 | var __trim:Object = null;
154 | for (var i:int=0; i < originalSheet.metadata.totalFrame; i++)
155 | {
156 | __trim = BitmapUtil.trim(originalSheet.getBMDByIndex(i));
157 | __sizeRect = originalSheet.metadata.originalFrameRects[i];
158 | __frame[i] = __trim.rect;
159 | //如果重设帧的尺寸,就使用trim过后的帧的宽高建立一个新的Rect尺寸,并更新bmd
160 | if($reset)
161 | {
162 | __origin[i] = new Rectangle(0,0,__trim.rect.width,__trim.rect.height);
163 | __bmd[i] = __trim.bitmapData;
164 | }
165 | else
166 | {
167 | //如果不重设帧的尺寸,就使用原始大小的宽高。同时计算trim后的xy的偏移。
168 | //因为获得xy的偏移是基于与原始帧大小的正数,要将其转换为基于trim后的帧的偏移,用0减
169 | //不重设尺寸的情况下,不更新bmd,因为原始尺寸没变。SpriteSheet中保存的bmdList,永远都与原始尺寸相同
170 | __bmd = originalSheet.cloneFrames();
171 | __origin[i] = new Rectangle(
172 | 0-__trim.rect.x,
173 | 0-__trim.rect.y,
174 | __sizeRect.width,
175 | __sizeRect.height);
176 | }
177 | }
178 | }
179 | else
180 | {
181 | //bmdlist永远都是原始尺寸的,因此不需要重新绘制
182 | __bmd = originalSheet.cloneFrames();
183 | __frame = originalSheet.metadata.frameRects.concat();
184 | __origin = originalSheet.metadata.originalFrameRects.concat();
185 | //不trim,将以前trim过的信息还原
186 | for (var j:int = 0; j < __frame.length; j++)
187 | {
188 | __frame[j].width = __origin[j].width;
189 | __frame[j].height = __origin[j].height;
190 | __origin[j].x = 0;
191 | __origin[j].y = 0;
192 | }
193 | }
194 | return new RectsAndBmdsVO(__bmd, __origin, __frame);
195 | }
196 |
197 | /**
198 | * 是否显示修剪空白后的帧的效果
199 | */
200 | public var displayCrop:Boolean;
201 |
202 | /**
203 | * 为true代表显示选择的Frame,false代表显示Label
204 | */
205 | public var displayFrame:Boolean;
206 |
207 | /**
208 | * 当前选择的Label名称
209 | */
210 | public var displayLabel:String;
211 |
212 | public var resizeRect:Rectangle;
213 |
214 | /**
215 | * 保存当前选择的帧的编号
216 | */
217 | public var selectedFrameIndex:int=-1;
218 |
219 | public var selectedFrmaeNum:int = -1;
220 |
221 | public var selectedFrameIndices:Vector.;
222 |
223 | public var playing:Boolean;
224 | }
225 | }
--------------------------------------------------------------------------------
/src/model/StateModel.as:
--------------------------------------------------------------------------------
1 | package model
2 | {
3 | import events.SSEvent;
4 |
5 | import org.robotlegs.mvcs.Actor;
6 |
7 | public class StateModel extends Actor
8 | {
9 | public function StateModel()
10 | {
11 | }
12 |
13 | private var _state:String = 'start';
14 |
15 | private var _oldState:String;
16 |
17 | public function get oldState():String
18 | {
19 | return _oldState;
20 | }
21 |
22 | public function get state():String
23 | {
24 | return _state;
25 | }
26 |
27 | public function set state($state:String):void
28 | {
29 | _oldState = _state;
30 | _state = $state;
31 | this.dispatch(new SSEvent(SSEvent.ENTER_STATE, {oldState:_oldState, newState:$state}));
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/type/ExtendedNameType.as:
--------------------------------------------------------------------------------
1 | package type
2 | {
3 | import flash.net.FileFilter;
4 | import gnu.as3.gettext.FxGettext;
5 | /**
6 | * 文件扩展名
7 | * @author zrong
8 | * 创建日期:2012-07-20
9 | */
10 | public class ExtendedNameType
11 | {
12 | public static const JPEG_XR:String = '.wdp';
13 | public static const JPEG:String = '.jpg';
14 | public static const PNG:String = '.png';
15 |
16 | public static const JSON:String = '.json';
17 | public static const XML:String = '.xml';
18 | public static const TEXT:String = '.txt';
19 |
20 | /**
21 | * 要打开的图像文件类型
22 | */
23 | public static const PNG_FILTER:FileFilter = new FileFilter(FxGettext.gettext("PNG image"), '*.png');
24 | public static const JPG_FILTER:FileFilter = new FileFilter(FxGettext.gettext("JPEG image"), '*.jpg;*.jpeg');
25 | public static const JPEG_XR_FILTER:FileFilter = new FileFilter(FxGettext.gettext("JPEG-XR image"), '*.wdp;*.hdp');
26 | public static const SWF_FILTER:FileFilter = new FileFilter(FxGettext.gettext("SWF animation"), '*.swf');
27 | public static const ALL_PIC_FILTER:FileFilter = new FileFilter(FxGettext.gettext("All compatible image"), PNG_FILTER.extension + ';' + JPG_FILTER.extension + ';' + JPEG_XR_FILTER.extension);
28 |
29 | public static const ALL_PIC_FILTER_LIST:Array = [ ALL_PIC_FILTER, PNG_FILTER, JPG_FILTER, JPEG_XR_FILTER];
30 |
31 | }
32 | }
--------------------------------------------------------------------------------
/src/type/StateType.as:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | // zengrong.net
3 | // 创建者: zrong zrongzrong@gmail.com
4 | // 创建时间:2011-8-3
5 | ////////////////////////////////////////////////////////////////////////////////
6 |
7 | package type
8 | {
9 | import flash.filesystem.File;
10 | import gnu.as3.gettext.FxGettext;
11 | import org.zengrong.display.spritesheet.SpriteSheetMetadata;
12 |
13 | /**
14 | * 保存State的名称
15 | * @author zrong
16 | */
17 | public class StateType
18 | {
19 | //----------------------------------------
20 | // 以下是编辑器的主状态
21 | //----------------------------------------
22 |
23 | /**
24 | * 编辑器处于start状态
25 | */
26 | public static const START:String = 'start';
27 |
28 | /**
29 | * 编辑器处于载入SWF状态
30 | */
31 | public static const SWF:String = 'swf';
32 |
33 | /**
34 | * 编辑器处于载入图片状态
35 | */
36 | public static const PIC:String = 'pic';
37 |
38 | /**
39 | * 编辑器处于开启SS文件状态
40 | */
41 | public static const SS:String = 'ss';
42 |
43 | /**
44 | * 检测$state是不是主编辑器状态
45 | */
46 | public static function isViewState($state:String):Boolean
47 | {
48 | var __mainState:Vector. = Vector.([START, SWF, PIC, SS]);
49 | for (var i:int = 0; i < __mainState.length; i++)
50 | {
51 | if(__mainState[i] == $state)
52 | return true;
53 | }
54 | return false;
55 | }
56 |
57 | public static function toMainStateName($state:String):String
58 | {
59 | switch($state)
60 | {
61 | case StateType.START:
62 | return FxGettext.gettext("Start");
63 | case StateType.SS:
64 | return FxGettext.gettext("Edit Sprite Sheet");
65 | case StateType.SWF:
66 | return FxGettext.gettext("Import swf file");
67 | }
68 | return FxGettext.gettext("Process image file");
69 | }
70 |
71 | //----------------------------------------
72 | // 以下是保存状态
73 | //----------------------------------------
74 |
75 | /**
76 | * 保存Metadata文件
77 | */
78 | public static const SAVE_META:String = 'saveMeta';
79 |
80 | /**
81 | * 保存SpriteSheet文件
82 | */
83 | public static const SAVE_SHEET_PIC:String = 'saveSheet';
84 |
85 | /**
86 | * 同时保存SpriteSheet和metadata文件
87 | */
88 | public static const SAVE_ALL:String = 'saveAll';
89 |
90 | /**
91 | * 保存序列
92 | */
93 | public static const SAVE_SEQ:String = 'saveSeq';
94 |
95 | //----------------------------------------
96 | // 以下是其他状态
97 | //----------------------------------------
98 |
99 | /**
100 | * 等待载入完毕的状态
101 | */
102 | public static const WAIT_LOADED:String = 'waitLoaded';
103 |
104 | /**
105 | * 正在建立的状态
106 | */
107 | public static const PROCESSING:String = 'processing';
108 |
109 | /**
110 | * 载入完成的状态
111 | */
112 | public static const LOAD_DONE:String = 'loadDone';
113 |
114 | /**
115 | * 将内容加入到spritesheet中的状态
116 | */
117 | public static const ADD_TO_SS:String = 'addToSS';
118 |
119 | /**
120 | * 在PicPanel界面将图片加入到Pic列表中的状态
121 | */
122 | public static const ADD_TO_PIC_List:String = "addToPicList";
123 | }
124 | }
--------------------------------------------------------------------------------
/src/utils/Funs.as:
--------------------------------------------------------------------------------
1 | package utils
2 | {
3 | import flash.filesystem.File;
4 | import flash.geom.Rectangle;
5 | import org.zengrong.assets.AssetsType;
6 | import type.ExtendedNameType;
7 | import type.StateType;
8 |
9 | import mx.managers.PopUpManager;
10 |
11 | import gnu.as3.gettext.FxGettext;
12 | import gnu.as3.gettext.ISO_3166;
13 | import gnu.as3.gettext.ISO_639_1;
14 | import gnu.as3.gettext.Locale;
15 |
16 | import org.zengrong.air.utils.getDesc;
17 | import org.zengrong.utils.MathUtil;
18 | import org.zengrong.utils.SOUtil;
19 |
20 | import view.comps.Alert;
21 |
22 | public class Funs
23 | {
24 | public static function getLang():String
25 | {
26 | var __so:SOUtil = SOUtil.getSOUtil("sse");
27 | //获取已经保存的显示语言
28 | var __lang:String = __so.get("lang");
29 | //没有设置显示语言,则根据当前系统判断
30 | if(!__lang)
31 | {
32 | var __enus:String = mklocale(ISO_639_1.EN, ISO_3166.US);
33 | var __zhcn:String = mklocale(ISO_639_1.ZH, ISO_3166.CN);
34 | var __zhtw:String = mklocale(ISO_639_1.ZH, ISO_3166.TW);
35 | //若为简中或者繁中系统
36 | if( Locale.LANG == __zhcn ||
37 | Locale.LANG == __zhtw )
38 | {
39 | __lang = __zhcn;
40 | }
41 | //不是简中系统均使用英文
42 | else
43 | {
44 | __lang = __enus;
45 | }
46 | __so.save(__lang, "lang");
47 | }
48 | return __lang;
49 | }
50 |
51 | public static function mklocale(iso639:String, iso3166:String):String
52 | {
53 | return ISO_639_1.codes[iso639]+"_"+ISO_3166.codes[iso3166];
54 | }
55 |
56 | /**
57 | * 根据提供的Rectangle数组计算最终Sheet的宽高以及每帧在Sheet中的位置
58 | * @param $frameRect 当前帧的独立大小
59 | */
60 | public static function calculateSize($frameRects:Vector.,
61 | $newSizeRects:Vector.,
62 | $whRect:Rectangle,
63 | $limitW:Boolean,
64 | $wh:int,
65 | $powOf2:Boolean=false,
66 | $square:Boolean=false):void
67 | {
68 | if($frameRects.length==0) return;
69 | var __frameRect:Rectangle = $frameRects[0];
70 | $newSizeRects[0] = new Rectangle(0,0,__frameRect.width, __frameRect.height);
71 | var __rectInSheet:Rectangle = new Rectangle(0,0,__frameRect.width,__frameRect.height);
72 | trace('getSheetWH:', __rectInSheet, __frameRect, $whRect);
73 | //设置sheet的初始宽高
74 | if($limitW)
75 | {
76 | //若限制宽度小于帧的宽度,就扩大限制宽度
77 | $whRect.width = $wh;
78 | if($whRect.width<__frameRect.width) $whRect.width = __frameRect.width;
79 | //计算2的幂
80 | if($powOf2) $whRect.width = MathUtil.nextPowerOf2($whRect.width);
81 | $whRect.height = __frameRect.height;
82 | }
83 | else
84 | {
85 | $whRect.height = $wh;
86 | if($whRect.height<__frameRect.height) $whRect.height = __frameRect.height;
87 | if($powOf2) $whRect.height = MathUtil.nextPowerOf2($whRect.height);
88 | $whRect.width = __frameRect.width;
89 | }
90 | for (var i:int = 1; i < $frameRects.length; i++)
91 | {
92 | __frameRect = $frameRects[i];
93 | updateRectInSheet(__rectInSheet, $whRect, __frameRect, $limitW);
94 | trace('getSheetWH:', __rectInSheet, __frameRect, $whRect);
95 | $newSizeRects[i] = __rectInSheet.clone();
96 | }
97 | if($square)
98 | {
99 | //计算正方形的尺寸
100 | if($whRect.width!=$whRect.height)
101 | {
102 | //使用当前计算出的面积开方得到正方形的基准尺寸
103 | var __newWH:int = Math.sqrt($whRect.width*$whRect.height);
104 | //使用基准尺寸重新排列一次
105 | calculateSize($frameRects,$newSizeRects,$whRect,$limitW,__newWH, $powOf2);
106 | //trace('正方形计算1:', $whRect);
107 | //如果基准尺寸无法实现正方形尺寸,就使用结果WH中比较大的那个尺寸作为正方形边长
108 | if($whRect.width!=$whRect.height)
109 | {
110 | var __max:int = Math.max($whRect.width, $whRect.height);
111 | $whRect.width = __max;
112 | $whRect.height = __max;
113 | }
114 | //trace('正方形计算2:', $whRect);
115 | }
116 | }
117 | if($powOf2)
118 | {
119 | $whRect.width = MathUtil.nextPowerOf2($whRect.width);
120 | $whRect.height = MathUtil.nextPowerOf2($whRect.height);
121 | }
122 | }
123 |
124 | /**
125 | * 更新在Sheet中帧的Rect的位置,根据Rect位置计算出大Sheet的WH
126 | * 会直接修改$rectInSheet和$whRect参数的值。
127 | * @param $rectInSheet 当前处理的帧在整个Sheet中的位置和大小,会修改此参数的值
128 | * @param $whRect 保存Sheet的W和H,会修改此参数的值
129 | * @param $frameRect 要处理的帧大小的Rect
130 | * @param $limitW 为true代表限制宽度,否则是显示高度
131 | */
132 | public static function updateRectInSheet($rectInSheet:Rectangle,
133 | $whRect:Rectangle,
134 | $frameRect:Rectangle,
135 | $limitW:Boolean):void
136 | {
137 |
138 | //限制宽度的计算
139 | if($limitW)
140 | {
141 | $rectInSheet.height = $frameRect.height;
142 | //若限制宽度小于帧的宽度,就扩大限制宽度,并进入新行
143 | if($whRect.width < $frameRect.width)
144 | {
145 | $whRect.width = $frameRect.width;
146 | newRow($rectInSheet, $frameRect, $whRect);
147 | }
148 | //如果这一行的宽度已经不够放下当前的位图,就进入新行
149 | else if($rectInSheet.right + $frameRect.width > $whRect.width)
150 | {
151 | newRow($rectInSheet, $frameRect, $whRect);
152 | }
153 | else
154 | {
155 | $rectInSheet.x += $rectInSheet.width;
156 | //如果当前帧比较高,就增加Sheet的高度
157 | if($whRect.height<$rectInSheet.bottom)
158 | $whRect.height = $rectInSheet.bottom;
159 | }
160 | //更新帧的宽
161 | $rectInSheet.width = $frameRect.width;
162 | }
163 | //限制高度的计算
164 | else
165 | {
166 | //更新帧的宽
167 | $rectInSheet.width = $frameRect.width;
168 | //若限制高度小于帧的高度,就扩大限制高度,并进入新列
169 | if($whRect.height < $frameRect.height)
170 | {
171 | $whRect.height = $frameRect.height;
172 | newColumn($rectInSheet, $frameRect, $whRect);
173 | }
174 | //如果这一列的高度已经放不下当前的位图,就进入新列
175 | else if($rectInSheet.bottom + $frameRect.height > $whRect.height)
176 | {
177 | newColumn($rectInSheet, $frameRect, $whRect);
178 | }
179 | else
180 | {
181 | //如果当前帧比Sheet还要宽,就增大Sheet的宽度
182 | $rectInSheet.y += $rectInSheet.height;
183 | if($whRect.width<$rectInSheet.right)
184 | $whRect.width = $rectInSheet.right;
185 | }
186 |
187 | $rectInSheet.height = $frameRect.height;
188 | }
189 | }
190 |
191 | private static function newRow($rectInSheet:Rectangle, $frameRect:Rectangle, $whRect:Rectangle):void
192 | {
193 | //让x回到行首
194 | $rectInSheet.x = 0;
195 | //更新新行的y值
196 | $rectInSheet.y = $whRect.height;
197 | //更新Sheet的高度
198 | $whRect.height += $frameRect.height;
199 | }
200 |
201 | private static function newColumn($rectInSheet:Rectangle, $frameRect:Rectangle, $whRect:Rectangle):void
202 | {
203 | $rectInSheet.y = 0;
204 | $rectInSheet.x = $whRect.width;
205 | $whRect.width += $frameRect.width;
206 | }
207 |
208 | public static function alert($text:String, $title:String=null):void
209 | {
210 | var __alert:Alert = PopUpManager.createPopUp(Global.root, Alert, true) as Alert;
211 | __alert.title = $title?FxGettext.gettext($title):FxGettext.gettext("Warning");
212 | __alert.text = $text;
213 | var __xy:Array = getAlertXY(__alert);
214 | __alert.move(__xy[0], __xy[1]);
215 | }
216 |
217 | public static function confirm($text:String, $okHandler:Function, $cancelHandler:Function=null, $title:String=null):void
218 | {
219 | var __alert:Alert = PopUpManager.createPopUp(Global.root, Alert, true) as Alert;
220 | __alert.currentState = 'confirm';
221 | __alert.title = $title?FxGettext.gettext($title):FxGettext.gettext("Please Confirm");
222 | __alert.text = $text;
223 | __alert.okHandler = $okHandler;
224 | __alert.cancelHandler = $cancelHandler;
225 | var __xy:Array = getAlertXY(__alert);
226 | __alert.move(__xy[0], __xy[1]);
227 | }
228 |
229 | private static function getAlertXY($alert:Alert):Array
230 | {
231 | return [(Global.root.width-$alert.width)*.5, (Global.root.height-$alert.height)*.5];
232 | }
233 |
234 | public static function getCreatedWith():String
235 | {
236 | return "Created with " + getDesc("name") + " v" + getDesc("versionNumber");
237 | }
238 |
239 | public static function getXMLHeader($lineEnding:String):String
240 | {
241 | return '' +$lineEnding+
242 | "" + $lineEnding +
243 | "" + $lineEnding;
244 | }
245 |
246 | /**
247 | * 根据载入的图片的地址,获取同名的metadata文件
248 | */
249 | public static function getMetadataUrl($url:String, $type:String):String
250 | {
251 | var __dotIndex:int = $url.lastIndexOf('.');
252 | if(__dotIndex == -1)
253 | return $url + '.'+$type;
254 | return $url.slice(0, __dotIndex) + '.'+$type;
255 | }
256 |
257 | public static function hasMetadataFile($url:String, $type:String="xml"):Boolean
258 | {
259 | var __metaUrl:String = getMetadataUrl($url, $type);
260 | var __file:File = new File(__metaUrl);
261 | return __file.exists;
262 | }
263 |
264 | /**
265 | * 根据当前传递的文件类型取得当前的界面状态
266 | * @return
267 | */
268 | public static function getStateByFile($file:File):String
269 | {
270 | if(ExtendedNameType.SWF_FILTER.extension.indexOf($file.type) > -1)
271 | {
272 | return StateType.SWF;
273 | }
274 | else if( ExtendedNameType.ALL_PIC_FILTER.extension.indexOf($file.type) > -1)
275 | {
276 | if(hasMetadataFile($file.url, "xml")) return StateType.SS;
277 | return StateType.PIC;
278 | }
279 | return '';
280 | }
281 | }
282 | }
--------------------------------------------------------------------------------
/src/utils/Global.as:
--------------------------------------------------------------------------------
1 | package utils
2 | {
3 | import flash.display.Bitmap;
4 | import flash.display.BitmapData;
5 | import flash.display.Sprite;
6 | import flash.display.StageQuality;
7 | import flash.geom.Matrix;
8 | import flash.geom.Point;
9 | import flash.ui.Mouse;
10 | import flash.ui.MouseCursorData;
11 |
12 | public class Global
13 | {
14 | [Embed(source="/../asset/embed/chess.png")]
15 | public static const BMP_CHESS:Class;
16 |
17 | [Embed(source="/../asset/embed/about.txt",mimeType="application/octet-stream")]
18 | public static const ABOUT_TEXT:Class;
19 |
20 | //Assets.swf来自于Flex框架 %FLEX_SDK%\frameworks\projects\framework\assets\Assets.swf
21 | [Embed(source="Assets.swf",symbol="mx.skins.cursor.VBoxDivider")]
22 | public static const MC_CURSOR_VDIVIDER:Class;
23 |
24 | [Embed(source="Assets.swf",symbol="mx.skins.BoxDividerSkin")]
25 | public static const MC_BOX_DIVIDER:Class;
26 |
27 | public static const VDIVIDER:String = 'vdivider';
28 |
29 | /**
30 | * 保存root对象
31 | */
32 | public static var root:SpriteSheetEditor;
33 |
34 | public static var bmd_chess:BitmapData;
35 |
36 | public static var cursor_vdivider:MouseCursorData;
37 |
38 | public static function init($root:SpriteSheetEditor):void
39 | {
40 | root = $root;
41 | var __bmp:Bitmap = new BMP_CHESS as Bitmap;
42 | bmd_chess = __bmp.bitmapData;
43 |
44 | var __sp:Sprite = new MC_CURSOR_VDIVIDER as Sprite;
45 | var __bmd:BitmapData = new BitmapData(16, 16, true, 0x00000000);
46 | __bmd.drawWithQuality(__sp, new Matrix(1,0,0,1, 8, 8), null, null, null, true, StageQuality.BEST);
47 | cursor_vdivider = new MouseCursorData();
48 | cursor_vdivider.data = Vector.([__bmd]);
49 | cursor_vdivider.hotSpot = new Point(8,8);
50 | Mouse.registerCursor(VDIVIDER, cursor_vdivider);
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/src/view/About.mxml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 | ' + getDesc('name') + ' v'+ getDesc('versionNumber') +'
'
34 | +'Author: zrong(zrongzrong@gmail.com)
Blog: http://www.zengrong.net
';
35 | infoLabel.textFlow = TextConverter.importToFlow(__str, TextConverter.TEXT_FIELD_HTML_FORMAT);
36 | }
37 |
38 | ]]>
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/view/comps/Alert.mxml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 | {FxGettext.gettext("OK")}
11 |
12 |
13 | {FxGettext.gettext("Cancel")}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/view/comps/BMPPreview.mxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
12 |
13 |
14 |
15 | [Event(name="previewClick", type="events.SSEvent")]
16 |
17 |
18 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/src/view/comps/BuildSetting.mxml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 | [Event(name="build", type="events.SSEvent")]
11 |
12 |
13 |
14 |
15 |
16 |
17 | {FxGettext.gettext("Build Sprite Sheet")}
18 | {FxGettext.gettext("Optimize Sprite Sheet")}
19 |
20 |
21 |
22 |
23 | {FxGettext.gettext("Smooth")}
24 |
25 |
26 | {FxGettext.gettext("Transparent")}
27 |
28 |
29 |
30 |
31 | {FxGettext.gettext("Background")}
32 |
33 |
34 |
35 |
36 |
37 | {FxGettext.gettext("Select width or height of the SpriteSheet. Another dimension needed to automatically calculate.")}
38 |
39 | {FxGettext.gettext("Width")}
40 | {FxGettext.gettext("Height")}
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | {FxGettext.gettext("Trim blank")}
51 | {FxGettext.gettext("If selected, then in the top left corner of the pixel color as a benchmark, cutting off the edge of the redundant blank.")}
52 |
53 |
54 | {FxGettext.gettext("Reset frame size")}
55 | {FxGettext.gettext("If selected, reset the original frame to the size after pruning blank. In metadata, the trimmed frame size and the original frame size is same. Otherwise, it has only use in the trimmed size which has been saved Sprite Sheet, and save the original frame size and trimmed frame size in the metadata.")}
56 |
57 |
58 |
59 |
60 |
61 | {FxGettext.gettext("Power of 2")}
62 | {FxGettext.gettext("If selected, then output size are power of 2(e.g., 256,512)")}
63 |
64 |
65 | {FxGettext.gettext("Square")}
66 | {FxGettext.gettext("If selected, then output file is square, width and height are automatic identification")}
67 |
68 |
69 |
70 |
71 | {FxGettext.gettext("Build")}
72 | {FxGettext.gettext("Optimize")}
73 |
74 |
75 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/view/comps/FileManager.mxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | [Event(name="selectionChange", type="events.SSEvent")]
7 | [Event(name="selectionChanging", type="events.SSEvent")]
8 | [Event(name="select", type="flash.events.Event")]
9 |
10 |
11 | {FxGettext.gettext("File list")}
12 |
13 |
16 |
17 |
18 |
19 | {FxGettext.gettext("File name")}
20 |
21 |
22 | {FxGettext.gettext("File size")}
23 |
24 |
25 |
26 |
27 |
28 |
29 | {FxGettext.gettext("Add multiple files. If you select items in the list, add the file will appear in the option above.")}
30 |
31 |
32 | {FxGettext.gettext("Delete the selected file from the list.")}
33 |
34 |
35 | {FxGettext.gettext("Move to top")}
36 |
37 |
38 | {FxGettext.gettext("move to bottom")}
39 |
40 |
41 | {FxGettext.gettext("Move up")}
42 |
43 |
44 | {FxGettext.gettext("Move down")}
45 |
46 |
47 |
48 | 1) return;
81 | this.dispatchEvent(new SSEvent(SSEvent.FILE_MANAGER_SELECTION_CHANGE));
82 | }
83 |
84 | private function selectionChanging():void
85 | {
86 | //选择的行数大于1,不发给上层
87 | if(fileDG.selectionLength>1) return;
88 | this.dispatchEvent(new SSEvent(SSEvent.FILE_MANAGER_SELECTION_CHANGING));
89 | }
90 |
91 | protected function handler_topAndBottomFileClick($event:MouseEvent):void
92 | {
93 | var __indexAdjust:int = ($event.currentTarget == topFile) ? -100 : 100;
94 | moveItem(__indexAdjust);
95 | }
96 |
97 | protected function handler_upAndDownFileclick($event:MouseEvent):void
98 | {
99 | var __indexAdjust:int = ($event.currentTarget == upFile) ? -1 : 1;
100 | moveItem(__indexAdjust);
101 | }
102 |
103 | protected function handler_delFileclick($event:MouseEvent):void
104 | {
105 | var __indices:Vector. = fileDG.selectedIndices;
106 | for(var i:int=__indices.length-1;i>=0;i--)
107 | {
108 | fileList.removeItemAt(__indices[i]);
109 | }
110 | delFile.enabled = false;
111 | upFile.enabled = false;
112 | downFile.enabled = false;
113 | selectionChange();
114 | }
115 |
116 | protected function handler_addFileclick($event:MouseEvent):void
117 | {
118 | this.dispatchEvent(new Event(Event.SELECT));
119 | }
120 |
121 | public function addFile2Manager($filelist:Array):void
122 | {
123 | var __selectedFiles:Array = $filelist;
124 | var __index:int = fileDG.selectedIndex>-1?fileDG.selectedIndex:fileList.length;
125 | trace(__selectedFiles, __index);
126 | for (var i:int = 0; i < __selectedFiles.length; i++)
127 | {
128 | fileList.addItemAt({file:__selectedFiles[i]}, __index+i);
129 | }
130 | }
131 |
132 | private function moveItem($indexAdjust:int):void
133 | {
134 | //向上还是向下调整
135 | var __indices:Vector. = fileDG.selectedIndices;
136 | var __selectedList:ArrayList = new ArrayList();
137 |
138 | var i:int=0;
139 | //先删除后面的,避免影响列表的索引
140 | for(i=__indices.length-1;i>=0;i--)
141 | {
142 | __selectedList.addItemAt(fileList.removeItemAt(__indices[i]), 0);
143 | }
144 | //要插入的位置索引
145 | var __insertIndex:int = 0;
146 | //如果移动的范围大于1,就是顶部或底部移动
147 | if($indexAdjust<-1)
148 | {
149 | __insertIndex = 0;
150 | }
151 | else if($indexAdjust>1)
152 | {
153 | __insertIndex = fileList.length;
154 | }
155 | //否则就是上一项和下一项移动
156 | else
157 | {
158 | //要插入的位置索引就是最高一个项目的索引-1,或者最低的一个项目的索引+1
159 | __insertIndex = __indices[0] + $indexAdjust;
160 | //超出范围,就使用极值
161 | if($indexAdjust<0 && __insertIndex < 0)
162 | {
163 | __insertIndex = 0;
164 | }
165 | else if($indexAdjust>0 && __insertIndex > fileList.length)
166 | {
167 | __insertIndex = fileList.length;
168 | }
169 | }
170 |
171 | fileList.addAllAt(__selectedList, __insertIndex);
172 | //还原调整顺序之后的选择项目
173 | var __indicesNew:Vector. = new Vector.;
174 | for(i=0;i<__selectedList.length;i++)
175 | {
176 | __indicesNew[i] = fileList.getItemIndex(__selectedList.getItemAt(i));
177 | }
178 | fileDG.selectedIndices = __indicesNew;
179 | }
180 | ]]>
181 |
182 |
--------------------------------------------------------------------------------
/src/view/comps/FrameDataGrid.mxml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 | {FxGettext.gettext("Frame number")}
11 |
12 |
13 | {FxGettext.gettext("Frame name")}
14 |
15 |
16 | {FxGettext.gettext("Trimmed size")}
17 |
18 |
19 | {FxGettext.gettext("Original size")}
20 |
21 |
22 |
23 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/src/view/comps/FramesAndLabels.mxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | [Event(name="frameAndLabelChange", type="events.SSEvent")]
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {FxGettext.gettext("Open preview windows")}
27 |
28 |
29 |
30 |
32 | {FxGettext.gettext("Use frame")}
33 | {FxGettext.gettext("Play the animation of selected frames")}
34 |
35 |
37 | {FxGettext.gettext("Use label")}
38 | {FxGettext.gettext("Play the animation of selected label")}
39 |
40 |
41 |
42 |
44 | {FxGettext.gettext("Trim")}
45 | {FxGettext.gettext("Display width and height of trimmed frame.")}
46 |
47 |
49 | {FxGettext.gettext("Original")}
50 | {FxGettext.gettext("Display the width and height of trimmed. In order to reduce file size, we could trim the blank. If the file does not trim, the original size and the trimmed size is same.")}
51 |
52 |
53 |
54 |
55 |
56 | {frameDG.dataProvider?FxGettext.gettext("All available frames:")+frameDG.dataProvider.length:FxGettext.gettext("The frames are not available.")}
57 |
58 |
59 |
60 | {FxGettext.gettext("Add image frame Or Sprite Sheet")}
61 | {FxGettext.gettext("If the selected files are image file, they will be added to the end of the current Sprite Sheet as some frames.\nIf they are Sprite Sheet files, they will be added to the end of the current Sprite Sheet with follows rules:\n1. All frames will be added to the Sprite Sheet at the end of current;\n2. If the label is the same name, the label in the Sprite Sheet do not import, but all frames in the label will be imported;\n3. If the name is the same name, the name in the Sprite Sheet do not import;\n4. If original Sprite Sheet contains frame name, but imported Sprite Sheet does not, all frame in the Sprite Sheet will be automatically named.")}
62 |
63 |
64 |
65 |
66 | {FxGettext.gettext("Remove frame")}
67 | {FxGettext.gettext("Remove a frame from the list. Update the Sprite Sheet immediately.")}
68 |
69 |
70 | {FxGettext.gettext("Selecte all")}
71 |
72 |
73 |
74 |
75 | {FxGettext.gettext("Move up")}
76 | {FxGettext.gettext("Move the frame's position, the frmae Numbers will change after moving.")}
77 |
78 |
79 | {FxGettext.gettext("Move down")}
80 | {FxGettext.gettext("Move the frame's position, the frmae Numbers will change after moving.")}
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | {FxGettext.gettext("use label")}
89 |
90 |
92 |
93 |
94 | {FxGettext.gettext("Enter label")}
95 | {FxGettext.gettext("Label format: letters + Numbers")}
96 |
97 |
98 | {labelDDL.selectedItem ? ("LABEL("+labelDDL.selectedItem.name+"),"+FxGettext.gettext("Number of frame:") + frameInLabelDG.dataProvider.length) : FxGettext.gettext("No selected label")}
99 |
100 |
101 |
103 | {FxGettext.gettext("Add label")}
104 | {FxGettext.gettext("Add a label to the list.")}
105 |
106 |
108 | {FxGettext.gettext("Remove label")}
109 | {FxGettext.gettext("Remove the selected label")}
110 |
111 |
113 | {FxGettext.gettext("Modify label")}
114 |
115 |
116 |
117 |
118 | {FxGettext.gettext("Add frame")}
119 |
120 |
121 | {FxGettext.gettext("Remove frame")}
122 |
123 |
124 |
125 |
126 | {FxGettext.gettext("Move up")}
127 |
128 |
129 | {FxGettext.gettext("Move down")}
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | 0)
229 | {
230 | var __frame:FrameVO;
231 | for (var i:int = 0; i < frameDG.dataProvider.length; i++)
232 | {
233 | __frame = getFrameItemAt(i);
234 | //若找到位图对应的索引,判断键盘
235 | if(__frame.frameRect.containsPoint(__point))
236 | {
237 | var ___selectedLen:int = frameDG.selectedIndices.length ;
238 | //在已经选择过帧的情况下,才处理键盘
239 | if(___selectedLen > 0)
240 | {
241 | //处理Control按键,不连续选择
242 | var __newIndices:Vector. = new Vector.;
243 | if($info.controlKey)
244 | {
245 | __newIndices[0] = i;
246 | for (var j:int = 0; j < ___selectedLen; j++)
247 | {
248 | if(i != frameDG.selectedIndices[j])
249 | __newIndices.push(frameDG.selectedIndices[j]);
250 | }
251 | }
252 | //处理Shift按键,连续选择
253 | else if($info.shiftKey)
254 | {
255 | var __start:int = Math.min(frameDG.selectedIndices[0], i);
256 | var __end:int = Math.max(frameDG.selectedIndices[0], i);
257 | for (j = __start; j <= __end; j++)
258 | {
259 | __newIndices.push(j);
260 | }
261 | }
262 | if(__newIndices.length > 0)
263 | {
264 | frameDG.selectedIndices = __newIndices;
265 | frameDG.ensureCellIsVisible(__newIndices[0]);
266 | }
267 | else
268 | {
269 | frameDG.selectedIndex = i;
270 | frameDG.ensureCellIsVisible(i);
271 | }
272 | }
273 | else
274 | {
275 | frameDG.selectedIndex = i;
276 | frameDG.ensureCellIsVisible(i);
277 | }
278 | return;
279 | }
280 | }
281 | }
282 | }
283 |
284 | //----------------------------------------
285 | // handler
286 | //----------------------------------------
287 | protected function handler_allBTNclick($event:MouseEvent):void
288 | {
289 | var __indics:Vector. = new Vector.;
290 | for (var i:int = 0; i < frameDG.dataProvider.length; i++)
291 | {
292 | __indics[i] = i;
293 | }
294 | frameDG.selectedIndices = __indics;
295 | }
296 |
297 | protected function handler_dividedHeightDown($evt:MouseEvent):void
298 | {
299 | this.parent.addEventListener(MouseEvent.MOUSE_MOVE, handler_resizeHeight);
300 | this.parent.addEventListener(MouseEvent.MOUSE_UP, handler_mouseUp);
301 | this.parent.addEventListener(MouseEvent.RELEASE_OUTSIDE, handler_mouseUp);
302 | }
303 |
304 | private function handler_resizeHeight($evt:MouseEvent):void
305 | {
306 | // trace('contentGrpoup:',this.contentGroup.height);
307 | // trace(this.mouseY, _minHeight, this.height);
308 | if(this.height< this.minHeight)
309 | {
310 | this.height = this.minHeight;
311 | handler_mouseUp(null);
312 | return;
313 | }
314 | this.height = this.mouseY+10;
315 | }
316 |
317 | private function handler_mouseUp($evt:MouseEvent):void
318 | {
319 | this.parent.removeEventListener(MouseEvent.MOUSE_MOVE, handler_resizeHeight);
320 | this.parent.removeEventListener(MouseEvent.MOUSE_UP, handler_mouseUp);
321 | this.parent.removeEventListener(MouseEvent.RELEASE_OUTSIDE, handler_mouseUp);
322 | }
323 |
324 | protected function handler_labelEnterState($evt:FlexEvent):void
325 | {
326 | this.minHeight = 640;
327 | //更新容器实际高度
328 | this.addEventListener(FlexEvent.UPDATE_COMPLETE, handler_updateComp);
329 | //更新一次frame管理按钮的状态
330 | updateFrameBTNS();
331 | //更新一次Label管理按钮的状态
332 | updateFrameInLabelBTNS();
333 | //更新一次帧的状态
334 | updateFrameOrLabelGRP();
335 | }
336 |
337 | protected function handler_frameEnterState($evt:FlexEvent):void
338 | {
339 | this.minHeight = 440;
340 | updateFrameBTNS();
341 | updateFrameOrLabelGRP();
342 | }
343 |
344 | protected function handler_updateComp($evt:FlexEvent):void
345 | {
346 | //trace('updateComp:', this.contentGroup.height, this.height);
347 | //若不更新,可能会出现容器内容被遮挡的情况
348 | if(this.height < this.contentGroup.height) this.height = this.contentGroup.height;
349 | this.removeEventListener(FlexEvent.UPDATE_COMPLETE, handler_updateComp);
350 | }
351 |
352 | //有可用Label的时候,才允许选择Frame或者Label显示
353 | public function updateFrameOrLabelGRP():void
354 | {
355 | var __enabled:Boolean = labelCB.selected && labelDDL.selectedItem;
356 | frameOrLabelGRP.enabled= __enabled;
357 | //不可选择的时候,返回默认选项
358 | if(!__enabled) frameOrLabelRBG.selectedValue = true;
359 | }
360 |
361 | /**
362 | * 更新与Frame相关的按钮状态
363 | */
364 | public function updateFrameBTNS($playing:Boolean=false):void
365 | {
366 | //选中的帧中包含顶部或者底部帧的时候,禁止上移或者下移
367 | var __indices:Vector. = frameDG.selectedIndices;
368 | if(__indices.length > 0)
369 | {
370 | var __inTop:Boolean = false;
371 | var __inBottom:Boolean = false;
372 | for (var i:int = 0; i < __indices.length; i++)
373 | {
374 | if(__indices[i] == 0)
375 | __inTop = true;
376 | if(__indices[i] == frameDG.dataProvider.length-1)
377 | __inBottom = true;
378 | }
379 | upFrameBTN.enabled = !__inTop;
380 | downFrameBTN.enabled = !__inBottom;
381 | delFrameBTN.enabled = !$playing;
382 | //允许加入帧到label中
383 | addFrameToLabelBTN.enabled = labelCB.selected && labelDDL.selectedItem;
384 | }
385 | else
386 | {
387 | upFrameBTN.enabled = false;
388 | downFrameBTN.enabled = false;
389 | delFrameBTN.enabled = false;
390 | addFrameToLabelBTN.enabled = false;
391 | }
392 | selectAllFrameBTN.enabled = frameDG.dataProviderLength > 0;
393 | }
394 |
395 | /**
396 | * 更新与label相关按钮的状态
397 | */
398 | public function updateFrameInLabelBTNS():void
399 | {
400 | var __index:int = frameInLabelDG.selectedIndex;
401 | if(__index > -1)
402 | {
403 | removeFrameFromLabelBTN.enabled = true;
404 | upFrameInLabelBTN.enabled = __index > 0;
405 | downFrameInLabelBTN.enabled = __index < (frameInLabelDG.dataProvider.length - 1);
406 | }
407 | else
408 | {
409 | removeFrameFromLabelBTN.enabled = false;
410 | upFrameInLabelBTN.enabled = false;
411 | downFrameInLabelBTN.enabled = false;
412 | }
413 | }
414 |
415 | //向上移动label中的帧
416 | private function handler_upFrameInLabelBTNClick($evt:MouseEvent):void
417 | {
418 | var __oldIndex:int = frameInLabelDG.selectedIndex;
419 | var __framesInLabel:ArrayList = selectedLabelFrameList;
420 | __framesInLabel.addItemAt(__framesInLabel.removeItemAt(__oldIndex), __oldIndex-1);
421 | frameInLabelDG.selectedIndex = __oldIndex -1;
422 | updateFrameInLabelBTNS();
423 | }
424 |
425 | //向下移动label中的帧
426 | private function handler_downFrameInLabelBTNClick($evt:MouseEvent):void
427 | {
428 | var __oldIndex:int = frameInLabelDG.selectedIndex;
429 | var __framesInLabel:ArrayList = selectedLabelFrameList;
430 | __framesInLabel.addItemAt(__framesInLabel.removeItemAt(__oldIndex), __oldIndex+1);
431 | frameInLabelDG.selectedIndex = __oldIndex +1;
432 | updateFrameInLabelBTNS();
433 | }
434 |
435 | //从label中移除帧
436 | private function handler_removeFrameFromLabelBTNClick($evt:MouseEvent):void
437 | {
438 | var __frames:ArrayList = selectedLabelFrameList;
439 | var __delItem:FrameVO = __frames.getItemAt(frameInLabelDG.selectedIndex) as FrameVO;
440 | __frames.removeItem(__delItem);
441 | updateFrameInLabelBTNS();
442 | }
443 |
444 | //向label中添加帧
445 | private function handler_addFrameToLabelBTNClick($evt:MouseEvent):void
446 | {
447 | var __frames:Vector.
458 |
459 |
--------------------------------------------------------------------------------
/src/view/comps/ImagePreview.mxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/src/view/comps/ImageTypeSetting.mxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 | {FxGettext.gettext("PNG image")}
10 |
11 |
12 | {FxGettext.gettext("JPEG image")}
13 |
14 |
15 | {FxGettext.gettext("JPEG-XR image")}
16 |
17 |
18 |
19 | {FxGettext.gettext("Compress:")}
20 |
21 |
22 | {FxGettext.gettext("For JPEG, bigger is better;For JPEG-XR, smaller is better.")}
23 |
24 |
25 |
26 | [Event(name="change", type="flash.events.Event")]
27 |
28 |
29 |
82 |
83 |
--------------------------------------------------------------------------------
/src/view/comps/Preview.mxml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | [Event(name="previewLoadComplete", type="events.SSEvent")]
10 | [Event(name="transformChange", type="events.SSEvent")]
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
256 |
257 |
258 |
--------------------------------------------------------------------------------
/src/view/comps/SSPreview.mxml:
--------------------------------------------------------------------------------
1 |
2 |
9 | {FxGettext.gettext("Bitmap animation preview")}
10 |
11 |
12 |
13 |
14 | {transControlBar}
15 | source
16 |
17 |
18 |
19 |
20 |
21 | {playBTN.selected?FxGettext.gettext("Pause"):FxGettext.gettext("Play")}
22 |
23 |
24 |
25 |
26 |
55 |
56 |
--------------------------------------------------------------------------------
/src/view/comps/SaveSeqSetting.mxml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 | [Event(name="saveSeq", type="events.SSEvent")]
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | {FxGettext.gettext("Prefix")}
18 |
19 |
20 |
21 |
22 |
23 | {FxGettext.gettext("Start at:")}
24 |
25 |
26 |
27 |
28 |
29 | {FxGettext.gettext("Digits:")}
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {FxGettext.gettext("File name preview:")}
38 |
39 |
40 |
41 |
42 | {FxGettext.gettext("Save")}
43 |
44 |
45 |
57 | {
58 | var __names:Vector. = new Vector.($fileNum, true);
59 | for (var i:int = 0; i < $fileNum; i++)
60 | {
61 | __names[i] = getFileName(startNS.value+i);
62 | }
63 | return __names;
64 | }
65 |
66 | private function preview():void
67 | {
68 | _fileName = getFileName(startNS.value);
69 | }
70 |
71 | /**
72 | * 返回文件名的字符串形式(不包含扩展名),数字部分不足位数的补0
73 | */
74 | private function getFileName($num:int):String
75 | {
76 | var __str:String = preTI.text;
77 | for(var i:int=0; i<_ten.length; i++)
78 | {
79 | //位数不够的数字补0
80 | if($num<_ten[i])
81 | __str += '0';
82 | }
83 | return __str + String($num) + imageSetting.imageType;
84 | }
85 |
86 | protected function handler_saveSeqBTNClick(event:MouseEvent):void
87 | {
88 | dispatchEvent(new SSEvent(SSEvent.SAVE_SEQ));
89 | }
90 |
91 | protected function fillTen():void
92 | {
93 | //更新每位的最大值的数组
94 | _ten = [];
95 | for(var i:int=1;i
103 |
104 |
105 |
--------------------------------------------------------------------------------
/src/view/comps/SaveSheetSetting.mxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | [Event(name="savePic", type="events.SSEvent")]
13 | [Event(name="saveMeta", type="events.SSEvent")]
14 | [Event(name="saveAll", type="events.SSEvent")]
15 |
16 |
17 |
18 |
19 | {FxGettext.gettext("Sprite Sheet")}
20 |
21 |
22 |
23 |
24 | {FxGettext.gettext("Mask:")}
25 |
26 |
27 |
28 | {FxGettext.gettext("No mask")}
29 | {FxGettext.gettext("Horzontial mask")}
30 | {FxGettext.gettext("Vertical mask")}
31 |
32 |
33 |
34 |
35 |
36 |
37 | {FxGettext.gettext("Metedata")}
38 |
39 |
40 | {FxGettext.gettext("XML format")}
41 |
42 |
43 | {FxGettext.gettext("JSON format")}
44 |
45 |
46 | {FxGettext.gettext("TXT format")}
47 |
48 |
49 | {FxGettext.gettext("Starling format")}
50 |
51 |
52 | {FxGettext.gettext("Use simple metadata")}
53 | {FxGettext.gettext("If selected, coordinate and WH are saved only.")}
54 |
55 |
56 | {FxGettext.gettext("Include file name")}
57 | {FxGettext.gettext("If selected, the relationship between the image file name and the frame index are saved in metadata. Then, you can get the corresponding frame through the file name.")}
58 |
59 |
60 |
61 |
62 |
63 | {FxGettext.gettext("Save image")}
64 |
65 |
66 | {FxGettext.gettext("Save all")}
67 |
68 |
69 | {FxGettext.gettext("Save metadata")}
70 |
71 |
72 |
73 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/src/view/comps/TransformTool.as:
--------------------------------------------------------------------------------
1 | package view.comps
2 | {
3 | import events.SSEvent;
4 | import flash.events.Event;
5 | import flash.events.MouseEvent;
6 | import flash.geom.Point;
7 | import flash.geom.Rectangle;
8 | import spark.core.SpriteVisualElement;
9 |
10 | /**
11 | * 一个以拖动方式更改大小的矩形,用于确定截取范围
12 | * @author zrong(zengrong.net)
13 | * Creation: 2011-8-3
14 | * Modification: 2013-08-20
15 | */
16 | [Event(name = "transformChange",type="events.SSEvent" )]
17 | public class TransformTool extends SpriteVisualElement
18 | {
19 |
20 | public function TransformTool()
21 | {
22 | super();
23 | this.addEventListener(MouseEvent.MOUSE_DOWN, handler_mouseDown);
24 | }
25 |
26 | [Bindable] public var maxDragW:int;
27 | [Bindable] public var maxDragH:int;
28 |
29 | private var _handlerW:int = 10;
30 | private var _handlerH:int = 10;
31 | private var _handlerRectList:Object = { };
32 |
33 | private var _mouseDownX:int = 0;
34 | private var _mouseDownY:int = 0;
35 | private var _curHandlerLoc:String;
36 | private var _oldRect:Rectangle;
37 |
38 | private function addCheckRelease():void
39 | {
40 | this.addEventListener(MouseEvent.MOUSE_UP, handler_mouseUp);
41 | this.addEventListener(MouseEvent.RELEASE_OUTSIDE, handler_mouseUp);
42 | }
43 |
44 | private function removeCheckRelease():void
45 | {
46 | this.removeEventListener(MouseEvent.MOUSE_UP, handler_mouseUp);
47 | this.removeEventListener(MouseEvent.RELEASE_OUTSIDE, handler_mouseUp);
48 | }
49 |
50 | private function addenterFrameHandler():void
51 | {
52 | this.addEventListener(Event.ENTER_FRAME, handler_enterFrame);
53 | }
54 |
55 | private function removeEnterFrameHandler():void
56 | {
57 | this.removeEventListener(Event.ENTER_FRAME, handler_enterFrame);
58 | }
59 |
60 | private function dispatchChange():void
61 | {
62 | this.dispatchEvent(new SSEvent(SSEvent.TRANSFORM_CHANGE, transformRect));
63 |
64 | }
65 |
66 | private function draw():void
67 | {
68 | this.graphics.clear();
69 |
70 | this.graphics.lineStyle(2, 0);
71 | this.graphics.beginFill(0, .2);
72 | this.graphics.drawRect(0, 0, this.width, this.height);
73 | this.graphics.endFill();
74 |
75 | updateHandlerPos();
76 |
77 | drawHandler(_handlerRectList.top);
78 | drawHandler(_handlerRectList.right);
79 | drawHandler(_handlerRectList.bottom);
80 | drawHandler(_handlerRectList.left);
81 |
82 | dispatchChange();
83 | }
84 |
85 | private function updateHandlerPos():void
86 | {
87 | _handlerRectList["top"] = new Rectangle((this.width - _handlerW) / 2, 0, _handlerW, _handlerH);
88 | _handlerRectList["right"] = new Rectangle(this.width - _handlerW, (this.height-_handlerH)/2, _handlerW, _handlerH);
89 | _handlerRectList["bottom"] = new Rectangle((this.width - _handlerW) / 2, this.height-_handlerH, _handlerW, _handlerH);
90 | _handlerRectList["left"] = new Rectangle(0, (this.height-_handlerH)/2, _handlerW, _handlerH);
91 | }
92 |
93 | private function drawHandler($rect:Rectangle):void
94 | {
95 | this.graphics.lineStyle(2, 0xFFFFFF);
96 | this.graphics.beginFill(0);
97 | this.graphics.drawRect($rect.x, $rect.y, $rect.width, $rect.height);
98 | this.graphics.endFill();
99 | }
100 |
101 | override public function set width($w:Number):void
102 | {
103 | super.width = $w;
104 | //trace("set width:", this.width);
105 | draw();
106 | }
107 |
108 | override public function set height($h:Number):void
109 | {
110 | super.height = $h;
111 | //trace("set height:", this.height);
112 | draw();
113 | }
114 |
115 | public function get transformRect():Rectangle
116 | {
117 | return new Rectangle(this.x, this.y, this.width, this.height);
118 | }
119 |
120 | public function set transformRect($rect:Rectangle):void
121 | {
122 | move($rect.x, $rect.y);
123 | resize($rect.width, $rect.height);
124 | }
125 |
126 | private function move($x:int, $y:int):void
127 | {
128 | this.x = $x;
129 | this.y = $y;
130 | dispatchChange();
131 | }
132 | private function resize($w:int, $h:int):void
133 | {
134 | this.width = $w;
135 | this.height = $h;
136 | }
137 |
138 | private function getCurHandlerLoc():String
139 | {
140 | _mouseDownX = this.mouseX;
141 | _mouseDownY = this.mouseY;
142 | for (var __rectName:String in _handlerRectList)
143 | {
144 | var __rect:Rectangle = _handlerRectList[__rectName] as Rectangle;
145 | if(__rect.contains(_mouseDownX, _mouseDownY))
146 | {
147 | _curHandlerLoc = __rectName;
148 | _oldRect = this.getRect(this.parent);
149 | return __rectName;
150 | }
151 | }
152 | _oldRect = null;
153 | return null;
154 | }
155 |
156 | protected function handler_mouseDown($event:MouseEvent):void
157 | {
158 | addCheckRelease();
159 | addenterFrameHandler();
160 |
161 | _curHandlerLoc = getCurHandlerLoc();
162 | }
163 |
164 | protected function handler_mouseUp($event:Event):void
165 | {
166 | _curHandlerLoc = null;
167 | _oldRect = null;
168 | removeCheckRelease();
169 | removeEnterFrameHandler();
170 | }
171 |
172 | protected function handler_enterFrame($event:Event):void
173 | {
174 | var __mouseX:int = this.parent.mouseX;
175 | var __mouseY:int = this.parent.mouseY;
176 | var __x:int = __mouseX - _mouseDownX;
177 | var __y:int = __mouseY - _mouseDownY;
178 | //移动
179 | if(!_curHandlerLoc)
180 | {
181 | if(__mouseX -_mouseDownX< 0) __x = 0;
182 | else if(__mouseX - _mouseDownX > maxDragW - this.width) __x = maxDragW - this.width;
183 | if(__mouseY - _mouseDownY < 0) __y = 0;
184 | else if(__mouseY - _mouseDownY > maxDragH - this.height) __y = maxDragH - this.height ;
185 | move(__x, __y);
186 | return;
187 | }
188 | //下面是改变大小
189 | var __h:int = 0;
190 | var __w:int = 0;
191 | if (_curHandlerLoc == "top")
192 | {
193 | __h = _oldRect.height - (__mouseY - _oldRect.y);
194 | if (__h < 0)
195 | __h = 0;
196 | else if (__h > maxDragH - this.y)
197 | __h = maxDragH - this.y;
198 | if (__h > 0 && __mouseY > 0)
199 | this.y = __mouseY;
200 | this.height = __h;
201 | }
202 | else if (_curHandlerLoc == "bottom")
203 | {
204 | __h = __mouseY - _oldRect.y;
205 | if (__h < 0)
206 | __h = 0;
207 | else if (__h > maxDragH - this.y)
208 | __h = maxDragH - this.y;
209 | else
210 | //貌似高度计算有点问题 +2试试看
211 | __h += 2;
212 | this.height = __h;
213 | }
214 | else if (_curHandlerLoc == "left")
215 | {
216 | __w = _oldRect.width - (__mouseX - _oldRect.x);
217 | if (__w < 0)
218 | __w = 0;
219 | else if (__w > maxDragW - this.x)
220 | __w = maxDragW - this.x;
221 | if (__w > 0 && __mouseX > 0)
222 | this.x = __mouseX;
223 | this.width = __w;
224 | }
225 | else if (_curHandlerLoc == "right")
226 | {
227 | __w = __mouseX - _oldRect.x;
228 | if (__w < 0)
229 | __w = 0;
230 | else if (__w > maxDragW - this.x)
231 | __w = maxDragW - this.x;
232 | this.width = __w;
233 | }
234 | }
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/src/view/comps/TransformToolControlBar.mxml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | [Event(name="transformUseCustomChange", type="events.SSEvent")]
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/src/view/comps/TransformToolControlBarForSS.as:
--------------------------------------------------------------------------------
1 | package view.comps
2 | {
3 | import gnu.as3.gettext.FxGettext;
4 | import mx.controls.Spacer;
5 | import spark.components.CheckBox;
6 | import spark.components.HGroup;
7 | import spark.components.Button;
8 | import spark.layouts.VerticalLayout;
9 | /**
10 | * 专用于SSPreview界面的大小设定
11 | * @author zrong
12 | */
13 | public class TransformToolControlBarForSS extends TransformToolControlBar
14 | {
15 | public function TransformToolControlBarForSS()
16 | {
17 | super();
18 | var __layout:VerticalLayout = new VerticalLayout();
19 | __layout.horizontalAlign = "center";
20 | this.layout = __layout;
21 | }
22 |
23 | public var saveResizeBTN:Button = new Button();
24 |
25 | protected override function createChildren():void
26 | {
27 | super.createChildren();
28 | var __grp:HGroup = new HGroup();
29 | __grp.addElement(createCheckBox());
30 | __grp.addElement(createSpacer());
31 | __grp.addElement(createButton());
32 | this.addElement(__grp);
33 | this.addElement(nsGrp);
34 | }
35 |
36 | private function createSpacer():Spacer
37 | {
38 | var __spacer:Spacer = new Spacer();
39 | __spacer.percentHeight = 100;
40 | __spacer.height = 20;
41 | return __spacer;
42 | }
43 |
44 | private function createCheckBox():CheckBox
45 | {
46 | useCustomSizeCB.label = FxGettext.gettext("Adjust the original size(x,y,w,h)");
47 | useCustomSizeCB.toolTip = FxGettext.gettext("Is selected, the original size is reduced. But you can still be executed 'Trim blank' again on the basis of reduced size.");
48 | return useCustomSizeCB;
49 | }
50 |
51 | private function createButton():Button
52 | {
53 | saveResizeBTN.enabled = false;
54 | saveResizeBTN.label = FxGettext.gettext("Do adjusting");
55 | saveResizeBTN.toolTip = FxGettext.gettext("Recalculated according to the original size adjusted, and immediate optimization.\nThis action will directly modify the size of the original size.")
56 | return saveResizeBTN;
57 | }
58 |
59 | public function setResizeBtnEnable($enable:Boolean):void
60 | {
61 | saveResizeBTN.enabled = useCustom && $enable;
62 | }
63 | /**
64 |
65 |
66 | {FxGettext.gettext("Adjust the original size(x,y,w,h)")}
67 | {FxGettext.gettext("Is selected, the original size is reduced. But you can still be executed 'Trim blank' again on the basis of reduced size.")}
68 |
69 |
70 |
71 | {FxGettext.gettext("Do adjusting")}
72 | {FxGettext.gettext("Recalculated according to the original size adjusted, and immediate optimization.\nThis action will directly modify the size of the original size.")}
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | **/
82 | }
83 | }
--------------------------------------------------------------------------------
/src/view/comps/VDividedButton.mxml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/view/panel/PicPanel.mxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {FxGettext.gettext("frame(x,y,w,h)")}
22 |
23 |
24 | {FxGettext.gettext("Custom size of the frame")}
25 | false
26 |
27 |
28 |
29 |
30 |
31 |
33 |
36 |
37 |
38 | {transControlBar}
39 | viewer
40 |
41 |
42 | 0)
163 | {
164 | var __namesvo:NamesVO = new NamesVO();
165 | var __names:Vector. = new Vector.(fileM.fileList.length);
166 | var __namesIndex:Object = {};
167 | var __dotIndex:int = 0;
168 | var __name:String = '';
169 | var __main:String = '';
170 | for(var i:int=0;i
260 |
261 |
262 |
--------------------------------------------------------------------------------
/src/view/panel/SSPanel.mxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {FxGettext.gettext("Save a Sprite Sheet")}
19 |
20 |
21 | {FxGettext.gettext("Save a sequence")}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
151 | {
152 | return saveSeq.getFileNames($num);
153 | }
154 |
155 | private function getSaveVO():SaveVO
156 | {
157 | var __vo:SaveVO = new SaveVO();
158 | __vo.picType = imageType;
159 | __vo.metaType = saveSheet.metaRBG.selectedValue.toString();
160 | __vo.isSimple = isSimple;
161 | __vo.includeName = includeName;
162 | return __vo;
163 | }
164 |
165 | public function getSeqSaveVO():SaveVO
166 | {
167 | var __vo:SaveVO = getSaveVO();
168 | __vo.quality = seqQualityValue;
169 | return __vo;
170 | }
171 |
172 | public function getSheetSaveVO():SaveVO
173 | {
174 | var __vo:SaveVO = getSaveVO();
175 | __vo.quality = sheetQualityValue;
176 | return __vo;
177 | }
178 | ]]>
179 |
180 |
181 |
--------------------------------------------------------------------------------
/src/view/panel/StartPanel.mxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 | {FxGettext.gettext("Open a swf file")}
10 | {FxGettext.gettext("Convert a swf file to Sprite Sheet in sequential frame.")}
11 |
12 |
13 | {FxGettext.gettext("Import image file")}
14 | {FxGettext.gettext("Convert a set of file to a Sprite Sheet.")}
15 |
16 |
17 |
18 | {FxGettext.gettext("Open a Sprite Sheet")}
19 | {FxGettext.gettext("Open a Sprite Sheet for edit and optimize.")}
20 |
21 |
22 |
24 | {FxGettext.gettext("Check update")}
25 |
26 |
28 | {FxGettext.gettext("About")}
29 |
30 |
31 | {FxGettext.gettext("Visit zrong's blog")}
32 | {FxGettext.gettext("Visit zengrong.net")}
33 |
34 |
35 |
36 |
37 | {FxGettext.gettext("Language:")}
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/src/view/panel/SwfPanel.mxml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {FxGettext.gettext("frame(x,y,w,h)")}
16 |
17 |
18 | {FxGettext.gettext("Custom size of the frame")}
19 | false
20 |
21 |
22 |
23 |
24 |
25 |
26 | {FxGettext.gettext("1st frame(zero-based):")}
27 |
28 |
29 |
30 |
31 |
32 |
33 | {FxGettext.gettext("Total frames:")}
34 |
35 |
36 |
37 |
38 |
39 |
41 |
42 |
43 | {transControlBar}
44 | source
45 | true
46 |
47 |
48 | [Event(name="complete", type="flash.events.Event")]
49 |
50 |
51 | = firstFrameNS.value)
121 | {
122 | trace('drawing frame:', _frameNum-1)
123 | //如果没有设置_rectInSheet,应该是截取第一帧,这种情况下初始化rectInSheet、frameRect和whRect
124 | if(!_rectInSheet)
125 | {
126 | _frameRect = transControlBar.useCustom ? transControlBar.transformRect : new Rectangle(0,0,swf.sourceWidth, swf.sourceHeight);
127 | _rectInSheet = new Rectangle(0, 0, _frameRect.width, _frameRect.height);
128 | var __w:int=0;
129 | var __h:int=0;
130 | if(_limitW)
131 | {
132 | __w = buildSetting.whNS.value;
133 | __h = _frameRect.height;
134 | }
135 | else
136 | {
137 | __h = buildSetting.whNS.value;
138 | __w = _frameRect.width;
139 | }
140 | _whRect = new Rectangle(0,0,__w, __h);
141 | }
142 | else
143 | {
144 | //不是第一帧,直接更新rect
145 | Funs.updateRectInSheet(_rectInSheet, _whRect, _frameRect, _limitW);
146 | }
147 | var __bmd:BitmapData = drawBMD(_frameRect);
148 | //向Sheet中添加这个位图
149 | this.dispatchEvent(new SSEvent(SSEvent.ADD_FRAME, {bmd:__bmd, rect:_rectInSheet.clone()}));
150 | }
151 | //所有帧捕获完毕后取消侦听
152 | if (_frameNum - firstFrameNS.value >= totalFrameNS.value)
153 | {
154 | captureDone();
155 | }
156 | }
157 |
158 | /**
159 | * 绘制当前帧,返回位图
160 | */
161 | private function drawBMD($frameRect:Rectangle):BitmapData
162 | {
163 | var __bmd:BitmapData = new BitmapData($frameRect.width, $frameRect.height, buildSetting.transparentCB.selected, buildSetting.bgColorPicker.selectedColor);
164 | var __ma:Matrix = null;
165 | if(transControlBar.useCustom)
166 | {
167 | //需要向“左上角”移动,将当前帧绘制成位图
168 | __ma = new Matrix();
169 | __ma.translate(-1*$frameRect.x, -1*$frameRect.y);
170 | }
171 | if(swf.enableDragContent)
172 | {
173 | if(!__ma) __ma = new Matrix;
174 | __ma.translate(swf.contentX, swf.contentY);
175 | }
176 | __bmd.draw(swf.content, __ma, null, null, null, buildSetting.smoothCB.selected);
177 | return __bmd;
178 | }
179 | ]]>
180 |
181 |
182 |
--------------------------------------------------------------------------------
/src/view/panel/TopPanel.mxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 | {FxGettext.gettext("Back to previous")}
10 |
11 |
12 | {FxGettext.gettext("Start")}
13 |
14 |
16 |
17 |
18 |
19 |
20 |
32 |
33 |
--------------------------------------------------------------------------------
/src/vo/BrowseFileDoneVO.as:
--------------------------------------------------------------------------------
1 | package vo
2 | {
3 | import air.update.utils.StringUtils;
4 | import flash.filesystem.File;
5 | import org.zengrong.assets.AssetsType;
6 | /**
7 | * 选择一个或者一组文件成功后发出事件所带VO
8 | * @author zrong
9 | * Creation: 2013-06-18
10 | */
11 | public class BrowseFileDoneVO
12 | {
13 |
14 | public function BrowseFileDoneVO($state:String=null, $files:Array=null)
15 | {
16 | openState = $state;
17 | selectedFiles = $files;
18 | }
19 |
20 | public var openState:String;
21 | public var selectedFiles:Array;
22 |
23 | /**
24 | * 如果选择的文件是SS格式,则这个值为AssetsType.SPRITE_SHEET
25 | * @see org.zengrong.assets.AssetsType
26 | */
27 | public var fileType:String;
28 |
29 | /**
30 | * 若 fileType的值为AssetsType.SPRITE_SHEET,则这个值为SpriteSheetMetadataType中的值
31 | * @see org.zengrong.display.spritesheet.SpriteSheetMetadataType
32 | */
33 | public var metaType:String;
34 |
35 | /**
36 | * 返回供Assets载入的列表
37 | * @return
38 | */
39 | public function toAssetsList():Array
40 | {
41 | if(!selectedFiles && selectedFiles.length == 0) return null;
42 | var __file:File = null;
43 | var __urls:Array = [];
44 | var __urlobj:Object = null;
45 | for(var i:int=0;i;
16 | public var labelsFrame:Object;
17 | }
18 | }
--------------------------------------------------------------------------------
/src/vo/LabelVO.as:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | // zengrong.net
3 | // 创建者: zrong(zrongzrong@gmail.com)
4 | // 创建时间:2011-8-17
5 | ////////////////////////////////////////////////////////////////////////////////
6 |
7 | package vo
8 | {
9 | import mx.collections.ArrayList;
10 |
11 | /**
12 | * 保存一个Label的信息
13 | */
14 | [Bindable]
15 | public class LabelVO
16 | {
17 | public function LabelVO($lableName:String, $labelFrames:ArrayList)
18 | {
19 | name = $lableName;
20 | frames = $labelFrames;
21 | }
22 |
23 | public var name:String;
24 | public var frames:ArrayList;
25 |
26 | /**
27 | * 返回frames中保存的所有帧的帧号
28 | */
29 | public function getFramesIndex():Array
30 | {
31 | var __framesIndex:Array = [];
32 | for (var i:int = 0; i < frames.length; i++)
33 | {
34 | __framesIndex[i] = (frames.getItemAt(i) as FrameVO).frameNum;
35 | }
36 | return __framesIndex;
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/src/vo/NamesVO.as:
--------------------------------------------------------------------------------
1 | package vo
2 | {
3 | /**
4 | * 保存SpriteSheet中的Name相关的Key
5 | * @author zrong
6 | * 创建日期:2012-08-17
7 | */
8 | public class NamesVO
9 | {
10 | public function NamesVO()
11 | {
12 | }
13 |
14 | public var hasName:Boolean;
15 |
16 | public var names:Vector.;
17 |
18 | public var namesIndex:Object;
19 | }
20 | }
--------------------------------------------------------------------------------
/src/vo/RectsAndBmdsVO.as:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | // zengrong.net
3 | // 创建者: zrong(zrongzrong@gmail.com)
4 | // 创建时间:2013-06-14
5 | ////////////////////////////////////////////////////////////////////////////////
6 |
7 | package vo
8 | {
9 | import flash.geom.Rectangle;
10 | import flash.display.BitmapData;
11 |
12 | /**
13 | * 保存Sheet的修改后的rect列表、原始的rect列表和位图列表
14 | */
15 | [Bindable]
16 | public class RectsAndBmdsVO
17 | {
18 | public function RectsAndBmdsVO($bmds:Vector., $origin:Vector., $frame:Vector.)
19 | {
20 | bmds = $bmds;
21 | originRects = $origin;
22 | frameRects = $frame;
23 | }
24 |
25 | /**
26 | * 在大sheet中的rect列表
27 | */
28 | public var frameRects:Vector.;
29 |
30 | /**
31 | * 原始的(在程序中使用的)rect列表
32 | */
33 | public var originRects:Vector.;
34 |
35 | /**
36 | * 所有的BitmapData列表
37 | */
38 | public var bmds:Vector.;
39 | }
40 | }
--------------------------------------------------------------------------------
/src/vo/SaveVO.as:
--------------------------------------------------------------------------------
1 | package vo
2 | {
3 | import flash.display.BitmapData;
4 | import org.zengrong.display.spritesheet.ISpriteSheetMetadata;
5 |
6 | /**
7 | * 在保存执行之前暂存待保存的数据
8 | * @author zrong
9 | *
10 | */
11 | public class SaveVO
12 | {
13 | public function SaveVO()
14 | {
15 | }
16 |
17 | /**
18 | * 要保存元数据
19 | */
20 | public var metadata:ISpriteSheetMetadata;
21 |
22 | /**
23 | * 要保存的图像
24 | */
25 | public var bitmapData:BitmapData;
26 |
27 | /**
28 | * 要保存的图像数组,用于保存序列图
29 | */
30 | public var bitmapDataList:Vector.;
31 |
32 | /**
33 | * 要保存的文件名数组,用于保存序列图
34 | */
35 | public var fileNameList:Vector.;
36 |
37 | /**
38 | * 图像文件类型
39 | */
40 | public var picType:String;
41 |
42 | /**
43 | * 元数据类型
44 | */
45 | public var metaType:String;
46 |
47 | /**
48 | * JPEG压缩质量
49 | */
50 | public var quality:int;
51 |
52 | /**
53 | * 见StateType
54 | * @see type.StateType
55 | */
56 | public var type:String;
57 |
58 | /**
59 | * 仅包含简单信息
60 | */
61 | public var isSimple:Boolean;
62 |
63 | /**
64 | * 包含文件名
65 | */
66 | public var includeName:Boolean;
67 | }
68 | }
--------------------------------------------------------------------------------