├── .gitignore ├── README.md ├── icon.png ├── libs ├── JSON.swc ├── gskinner_air.swc └── gskinner_as3.swc └── src ├── .gitignore ├── FlexSdkPath.conf.sample ├── Zoe-app.xml ├── Zoe.mxml ├── assets ├── 4x4Grid.png ├── ColorPicker.png ├── ColorPickerAlpha.png ├── DeleteConfigButton.png ├── FileIconAdd.png ├── FolderIcon.png ├── Graphics.fla ├── Graphics.swf ├── Refresh.png ├── RunArrow.png ├── TileMainBG.png ├── TileMenuBG.png ├── TilePopupBG.png ├── TransparencyBtn_over.gif ├── TransparencyBtn_up.png ├── fonts │ └── HelveticaLTStd-Light.otf ├── helpIcon.png ├── play-pause.png └── play.png ├── build.bat ├── build.sh ├── com └── gskinner │ ├── skins │ ├── ApplicationSkin.mxml │ ├── IconButtonSkin.mxml │ ├── ImageButtonSkin.mxml │ ├── UpdateDialogSkin.mxml │ ├── VScrollBarSkin.mxml │ ├── VScrollBarThumbSkin.mxml │ └── VScrollBarTrackSkin.mxml │ ├── ui │ └── Spinner.mxml │ └── zoe │ ├── controls │ ├── ColorPreviewText.as │ ├── Menu.mxml │ └── ToolTip.as │ ├── data │ ├── AnimationState.as │ ├── ExportType.as │ ├── FrameData.as │ └── SourceFileData.as │ ├── events │ ├── CaptureEvent.as │ ├── PreviewPanelEvent.as │ └── ResultEvent.as │ ├── model │ └── FileModel.as │ ├── skins │ ├── BottomMenuButtonBarSkin.mxml │ ├── BottomMenuButtonSkin.mxml │ ├── PlayPauseButton.mxml │ └── TransparencyButton.mxml │ ├── styles │ └── styles.css │ ├── ui │ └── Divider.mxml │ ├── utils │ ├── ApplicationUpdater.as │ ├── BitmapCompare.as │ ├── CaptureSWF.as │ ├── DottedLine.as │ └── FindSWFBounds.as │ └── views │ ├── CapturePreview.mxml │ ├── ExportDialog.mxml │ ├── Main.mxml │ ├── PreviewPanel.mxml │ └── ProgressOverlay.mxml ├── data └── version.xml └── icons ├── 128x128.png ├── 16x16.png ├── 32x32.png └── 48x48.png /.gitignore: -------------------------------------------------------------------------------- 1 | bin-*/ 2 | .settings 3 | .actionScriptProperties 4 | .flexProperties 5 | .project 6 | Spikes 7 | npm-debug.log 8 | */.idea/ 9 | */node_modules/* 10 | *.dmg 11 | *.air 12 | *.exe 13 | *.swf 14 | *.p12 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### Zoë 2 | 3 | Zoë is an open source tool for generating spritesheet images and frame data from SWF files. 4 | 5 | The source code is licensed under the MIT public license. 6 | 7 | If you just want to use Zoë, the latest stable .air installer can be found on the [Zoë](http://createjs.com/zoe) website. 8 | 9 | #### Using 10 | 11 | [Zoë](http://www.createjs.com/#!/Zoe) is designed to work with any AS3 SWF file version 9 or greater. It's best practice to have all your animations on the root timeline, and use labels to identify your different animations or frames. To begin, simply drag a swf file into Zoë, and click Export to create a SpriteSheet. 12 | 13 | Zoë and [Easel](http://www.createjs.com/#!/EaselJS) support custom registration points on images. To define one, simply place an empty clip on your timeline labeled registrationPoint. If needed, you can also define multiple points per file. 14 | 15 | #### Building 16 | 17 | **Command line (Recommended)** 18 | 19 | * Install the latest Flex SDK from Apache (http://flex.apache.org/) 20 | ** The latest version is built against Apace Flex 4.13.0 21 | * Make sure java is available on your PATH 22 | * Rename FlexSdkPath.conf.sample to FlexSdkPath.conf and edit the FLEX_SDK variable to point to your Flex SDK 23 | * For OSX run build.sh and for Windows run build.bat 24 | * Note that we don't distribute the default application *.p12 key 25 | ** To create your own key for testing visit: http://help.adobe.com/en_US/air/build/WS901d38e593cd1bac1e63e3d128fc240122-7ffc.html 26 | 27 | **FlexBuilder** 28 | 29 | * You can also build using Flex Builder by checking out the repo a creating a new Flex AIR/MXML project, and use this repo as your project root. 30 | 31 | #### Support 32 | 33 | You can ask questions and interact with other users at our [Community site](http://community.createjs.com/). 34 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/icon.png -------------------------------------------------------------------------------- /libs/JSON.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/libs/JSON.swc -------------------------------------------------------------------------------- /libs/gskinner_air.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/libs/gskinner_air.swc -------------------------------------------------------------------------------- /libs/gskinner_as3.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/libs/gskinner_as3.swc -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | #----------------------------- 2 | # SYSTEM 3 | #----------------------------- 4 | .DS_Store 5 | 6 | #----------------------------- 7 | # INVALID FILES 8 | # (for cross OS compatibility) 9 | #----------------------------- 10 | *[\<\>\:\"\/\\\|\?\*]* 11 | 12 | #----------------------------- 13 | # WORKSPACE 14 | #----------------------------- 15 | .idea/ 16 | FlexSdkPath.conf 17 | -------------------------------------------------------------------------------- /src/FlexSdkPath.conf.sample: -------------------------------------------------------------------------------- 1 | FLEX_SDK=your_sdk_path_here 2 | STORE_PASS=your_password_here 3 | -------------------------------------------------------------------------------- /src/Zoe-app.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Zoe 4 | Zoe 5 | Zoë 6 | 0.5.1 7 | 8 | 9 | Zoe.swf 10 | 750 430 11 | false 12 | false 13 | true 14 | 15 | 16 | 17 | icons/16x16.png 18 | icons/32x32.png 19 | icons/48x48.png 20 | icons/128x128.png 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Zoe.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 30 | 39 | 45 | 46 | 47 | = new Date().time) { 69 | ApplicationUpdater.checkForUpdates(true); 70 | lastUpdateTime = new Date(); 71 | } 72 | 73 | Preferences.setPref('lastUpdateCheck', lastUpdateTime, false, true); 74 | 75 | //Center on screen 76 | var s:Screen = Screen.mainScreen; 77 | this.nativeWindow.x = (s.bounds.width-width) >> 1; 78 | this.nativeWindow.y = (s.bounds.height-height) >> 1; 79 | 80 | this.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, handleError); 81 | } 82 | 83 | /** 84 | * @private 85 | * 86 | */ 87 | protected function handleError(event:UncaughtErrorEvent):void { 88 | event.preventDefault(); 89 | Alert.show((event.text.length) ? event.text : "An unexpected error has occurred.", "Error"); 90 | } 91 | 92 | /** 93 | * @private 94 | * 95 | * We allow draw and drop of multiple swfs. 96 | */ 97 | protected function handleDragOver(event:NativeDragEvent):void { 98 | if (!event.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)) { 99 | return; 100 | } 101 | 102 | var files:Array = event.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array; 103 | 104 | var l:uint = files.length; 105 | var validFiles:uint = 0; 106 | for (var i:uint=0;i 0) { 114 | NativeDragManager.acceptDragDrop(this); 115 | } 116 | } 117 | 118 | /** 119 | * @private 120 | * 121 | */ 122 | protected function handleDragDrop(event:NativeDragEvent):void { 123 | var files:Array = event.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array; 124 | var l:uint = files.length; 125 | 126 | var swfs:Array = []; 127 | for (var i:uint=0;i 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /src/assets/4x4Grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/4x4Grid.png -------------------------------------------------------------------------------- /src/assets/ColorPicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/ColorPicker.png -------------------------------------------------------------------------------- /src/assets/ColorPickerAlpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/ColorPickerAlpha.png -------------------------------------------------------------------------------- /src/assets/DeleteConfigButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/DeleteConfigButton.png -------------------------------------------------------------------------------- /src/assets/FileIconAdd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/FileIconAdd.png -------------------------------------------------------------------------------- /src/assets/FolderIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/FolderIcon.png -------------------------------------------------------------------------------- /src/assets/Graphics.fla: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/Graphics.fla -------------------------------------------------------------------------------- /src/assets/Graphics.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/Graphics.swf -------------------------------------------------------------------------------- /src/assets/Refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/Refresh.png -------------------------------------------------------------------------------- /src/assets/RunArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/RunArrow.png -------------------------------------------------------------------------------- /src/assets/TileMainBG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/TileMainBG.png -------------------------------------------------------------------------------- /src/assets/TileMenuBG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/TileMenuBG.png -------------------------------------------------------------------------------- /src/assets/TilePopupBG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/TilePopupBG.png -------------------------------------------------------------------------------- /src/assets/TransparencyBtn_over.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/TransparencyBtn_over.gif -------------------------------------------------------------------------------- /src/assets/TransparencyBtn_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/TransparencyBtn_up.png -------------------------------------------------------------------------------- /src/assets/fonts/HelveticaLTStd-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/fonts/HelveticaLTStd-Light.otf -------------------------------------------------------------------------------- /src/assets/helpIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/helpIcon.png -------------------------------------------------------------------------------- /src/assets/play-pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/play-pause.png -------------------------------------------------------------------------------- /src/assets/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/assets/play.png -------------------------------------------------------------------------------- /src/build.bat: -------------------------------------------------------------------------------- 1 | IF EXIST FlexSdkPath.conf ( 2 | for /f "delims=" %%x in (FlexSdkPath.conf) do (set "%%x") 3 | ) else ( 4 | ECHO "!! Create a FlexSdkPath.conf file, with your FLEX sdk source path as the only line." 5 | EXIT 6 | ) 7 | 8 | %FLEX_SDK%/bin/amxmlc.bat +configname=air -swf-version=19 -library-path+=../libs/gskinner_air.swc -library-path+=../libs/gskinner_as3.swc -library-path+=../libs/JSON.swc -output Zoe.swf Zoe.mxml && ^ 9 | %FLEX_SDK%/bin/adt.bat -package -storetype pkcs12 -keystore certificate.p12 -storepass %STORE_PASS% -target native Zoe.exe Zoe-app.xml Zoe.swf icons/16x16.png icons/32x32.png icons/48x48.png icons/128x128.png 10 | -------------------------------------------------------------------------------- /src/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [[ -e FlexSdkPath.conf ]]; then source FlexSdkPath.conf 4 | else echo "!! Create a FlexSdkPath.conf file."; exit; 5 | fi 6 | 7 | ${FLEX_SDK}/bin/mxmlc +configname=air -swf-version=19 -library-path+=../libs/gskinner_air.swc -library-path+=../libs/gskinner_as3.swc -library-path+=../libs/JSON.swc -output Zoe.swf Zoe.mxml 8 | ${FLEX_SDK}/bin/adt -package -storetype pkcs12 -keystore certificate.p12 -storepass ${STORE_PASS} -target native Zoe.dmg Zoe-app.xml Zoe.swf icons/16x16.png icons/32x32.png icons/48x48.png icons/128x128.png 9 | -------------------------------------------------------------------------------- /src/com/gskinner/skins/ApplicationSkin.mxml: -------------------------------------------------------------------------------- 1 | 28 | 30 | 31 | 32 | /** 33 | * @copy spark.skins.spark.ApplicationSkin#hostComponent 34 | */ 35 | [HostComponent("Object")] 36 | 37 | 38 | 39 | /* Define the skin elements that should not be colorized. 40 | * For WindowedApplication, border and status bar background are colorized, 41 | * but the content area and status text are not. 42 | * Exclude the titleBar and scroller because they are SparkSkins and we 43 | * don't want to colorize them twice. 44 | * 45 | * @langversion 3.0 46 | * @playerversion Flash 10 47 | * @playerversion AIR 1.5 48 | * @productversion Flex 4 49 | */ 50 | static private const exclusions:Array = ["backgroundRect", "contentGroup", "statusText"]; 51 | 52 | /** 53 | * @private 54 | */ 55 | override public function get colorizeExclusions():Array {return exclusions;} 56 | 57 | /** 58 | * @private 59 | */ 60 | override protected function initializationComplete():void 61 | { 62 | //useChromeColor = true; 63 | super.initializationComplete(); 64 | } 65 | 66 | /** 67 | * @private 68 | */ 69 | override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void 70 | { 71 | //backgroundFill.color = getStyle("backgroundColor"); 72 | //backgroundFill.alpha = getStyle("backgroundAlpha"); 73 | super.updateDisplayList(unscaledWidth, unscaledHeight); 74 | } 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /src/com/gskinner/skins/IconButtonSkin.mxml: -------------------------------------------------------------------------------- 1 | 28 | 34 | 35 | 36 | [HostComponent("spark.components.Button")] 37 | 38 | 39 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 98 | 99 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /src/com/gskinner/skins/ImageButtonSkin.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 34 | 35 | 36 | [HostComponent("spark.components.Button")] 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 77 | 78 | 79 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 95 | 96 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/com/gskinner/skins/UpdateDialogSkin.mxml: -------------------------------------------------------------------------------- 1 | 28 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | /* Define the skin elements that should not be colorized. 43 | For panel, border and title background are skinned, but the content area and title text are not. */ 44 | static private const exclusions:Array = ["background", "titleDisplay", "contentGroup", "controlBarGroup"]; 45 | 46 | /** 47 | * @private 48 | */ 49 | override public function get colorizeExclusions():Array {return exclusions;} 50 | 51 | /** 52 | * @private 53 | */ 54 | override protected function initializationComplete():void 55 | { 56 | useChromeColor = true; 57 | super.initializationComplete(); 58 | } 59 | 60 | /** 61 | * @private 62 | */ 63 | override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void 64 | { 65 | if (getStyle("borderVisible") == true) 66 | { 67 | border.visible = true; 68 | background.left = background.top = background.right = background.bottom = 1; 69 | contents.left = contents.top = contents.right = contents.bottom = 0; 70 | } 71 | else 72 | { 73 | border.visible = false; 74 | background.left = background.top = background.right = background.bottom = 0; 75 | contents.left = contents.top = contents.right = contents.bottom = 0; 76 | } 77 | 78 | dropShadow.visible = getStyle("dropShadowVisible"); 79 | 80 | var cr:Number = getStyle("cornerRadius"); 81 | var withControls:Boolean = 82 | (currentState == "disabledWithControlBar" || 83 | currentState == "normalWithControlBar"); 84 | 85 | if (cornerRadius != cr) 86 | { 87 | cornerRadius = cr; 88 | 89 | dropShadow.tlRadius = cornerRadius; 90 | dropShadow.trRadius = cornerRadius; 91 | dropShadow.blRadius = withControls ? cornerRadius : 0; 92 | dropShadow.brRadius = withControls ? cornerRadius : 0; 93 | 94 | setPartCornerRadii(topMaskRect, withControls); 95 | setPartCornerRadii(border, withControls); 96 | setPartCornerRadii(background, withControls); 97 | } 98 | 99 | if (bottomMaskRect) setPartCornerRadii(bottomMaskRect, withControls); 100 | 101 | borderStroke.color = getStyle("borderColor"); 102 | borderStroke.alpha = getStyle("borderAlpha"); 103 | backgroundFill.color = getStyle("backgroundColor"); 104 | backgroundFill.alpha = getStyle("backgroundAlpha"); 105 | 106 | super.updateDisplayList(unscaledWidth, unscaledHeight); 107 | } 108 | 109 | /** 110 | * @private 111 | */ 112 | private function setPartCornerRadii(target:Rect, includeBottom:Boolean):void 113 | { 114 | target.topLeftRadiusX = cornerRadius; 115 | target.topRightRadiusX = cornerRadius; 116 | target.bottomLeftRadiusX = includeBottom ? cornerRadius : 0; 117 | target.bottomRightRadiusX = includeBottom ? cornerRadius : 0; 118 | } 119 | 120 | private var cornerRadius:Number; 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 221 | 222 | 223 | 224 | 225 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | -------------------------------------------------------------------------------- /src/com/gskinner/skins/VScrollBarSkin.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | static private const exclusions:Array = ["track", "thumb", "decrementButton", "incrementButton"]; 41 | 42 | override public function get colorizeExclusions():Array {return exclusions;} 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 54 | 55 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/com/gskinner/skins/VScrollBarThumbSkin.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 31 | 32 | 33 | [HostComponent("spark.components.Button")] 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/com/gskinner/skins/VScrollBarTrackSkin.mxml: -------------------------------------------------------------------------------- 1 | 28 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/com/gskinner/ui/Spinner.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 33 | 34 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/controls/ColorPreviewText.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | package com.gskinner.zoe.controls { 30 | 31 | import flash.events.Event; 32 | 33 | import mx.controls.listClasses.BaseListData; 34 | import mx.core.IFlexModuleFactory; 35 | import mx.core.ITextInput; 36 | 37 | import spark.components.Group; 38 | import spark.components.TextInput; 39 | import spark.components.ToggleButton; 40 | import spark.events.TextOperationEvent; 41 | 42 | /** 43 | * Skin for the Flex ColorPicker syle "textInputClass" 44 | * Inserts a toggle button for transparency toggle. 45 | * 46 | */ 47 | public class ColorPreviewText extends Group implements ITextInput { 48 | 49 | /** 50 | * textInput 51 | */ 52 | protected var textInput:TextInput; 53 | 54 | /** 55 | * We can't get reference to this class though the ColorPicker API, 56 | * so we use a static interface to access its properties, via getInstance(); 57 | * 58 | */ 59 | public var toggleTransparencyButton:ToggleButton; 60 | 61 | /** 62 | * @private 63 | * 64 | */ 65 | protected static var _instance:ColorPreviewText; 66 | 67 | /** 68 | * Creates a new instance of the ColorPreviewText 69 | * 70 | */ 71 | public function ColorPreviewText() { 72 | super(); 73 | 74 | _instance = this; 75 | 76 | textInput = new TextInput(); 77 | textInput.addEventListener(TextOperationEvent.CHANGE, handleChangeText, false, 0, true); 78 | textInput.width = 50; 79 | toggleTransparencyButton = new ToggleButton(); 80 | toggleTransparencyButton.setActualSize(17, 17); 81 | toggleTransparencyButton.styleName = "transparentSkin"; 82 | toggleTransparencyButton.validateNow(); 83 | } 84 | 85 | /** 86 | * Returns this objects current instance. 87 | * Used so we can access the values from toggleTransparencyButton (the ColorPicker doesn't give us access to this component) 88 | * 89 | */ 90 | public static function getInstance():ColorPreviewText { 91 | if (_instance == null) { _instance = new ColorPreviewText(); } 92 | return _instance; 93 | } 94 | 95 | /** 96 | * @private 97 | * 98 | */ 99 | override protected function createChildren():void { 100 | super.createChildren(); 101 | addElement(textInput); 102 | addElement(toggleTransparencyButton); 103 | } 104 | 105 | /** 106 | * @private 107 | * 108 | */ 109 | override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { 110 | super.updateDisplayList(unscaledWidth, unscaledHeight); 111 | toggleTransparencyButton.x = 156; 112 | } 113 | 114 | /** 115 | * @private 116 | * 117 | */ 118 | protected function handleChangeText(event:TextOperationEvent):void { 119 | dispatchEvent(new Event(Event.CHANGE)); 120 | } 121 | 122 | /** 123 | * Required by ITextInput 124 | * 125 | */ 126 | public function get selectionActivePosition():int { 127 | return textInput.selectionActivePosition; 128 | } 129 | 130 | /** 131 | * Required by ITextInput 132 | * 133 | */ 134 | public function get selectionAnchorPosition():int { 135 | return textInput.selectionAnchorPosition; 136 | } 137 | 138 | /** 139 | * Required by ITextInput 140 | * 141 | */ 142 | public function get editable():Boolean { 143 | return textInput.editable; 144 | } 145 | 146 | /** 147 | * Required by ITextInput 148 | * 149 | */ 150 | public function set editable(value:Boolean):void { 151 | textInput.editable = value; 152 | } 153 | 154 | /** 155 | * Required by ITextInput 156 | * 157 | */ 158 | public function get maxChars():int { 159 | return textInput.maxChars; 160 | } 161 | 162 | /** 163 | * Required by ITextInput 164 | * 165 | */ 166 | public function set maxChars(value:int):void { 167 | textInput.maxChars = value; 168 | } 169 | 170 | /** 171 | * Required by ITextInput 172 | * 173 | */ 174 | public function get parentDrawsFocus():Boolean { 175 | return false; 176 | } 177 | 178 | /** 179 | * Required by ITextInput 180 | * 181 | */ 182 | public function set parentDrawsFocus(value:Boolean):void { 183 | } 184 | 185 | /** 186 | * Required by ITextInput 187 | * 188 | */ 189 | public function get restrict():String { 190 | return textInput.restrict; 191 | } 192 | 193 | /** 194 | * Required by ITextInput 195 | * 196 | */ 197 | public function set restrict(value:String):void { 198 | textInput.restrict = value; 199 | } 200 | 201 | /** 202 | * Required by ITextInput 203 | * 204 | */ 205 | public function get selectable():Boolean { 206 | return textInput.selectable; 207 | } 208 | 209 | /** 210 | * Required by ITextInput 211 | * 212 | */ 213 | public function set selectable(value:Boolean):void { 214 | textInput.selectable = value; 215 | } 216 | 217 | /** 218 | * Required by ITextInput 219 | * 220 | */ 221 | public function get text():String { 222 | return textInput.text; 223 | } 224 | 225 | /** 226 | * Required by ITextInput 227 | * 228 | */ 229 | public function set text(value:String):void { 230 | textInput.text = value; 231 | } 232 | 233 | /** 234 | * Required by ITextInput 235 | * 236 | */ 237 | public function showBorderAndBackground(visible:Boolean):void { 238 | 239 | } 240 | 241 | /** 242 | * Required by ITextInput 243 | * 244 | */ 245 | public function selectRange(anchorPosition:int, activePosition:int):void { 246 | textInput.selectRange(anchorPosition, activePosition); 247 | } 248 | 249 | /** 250 | * Required by ITextInput 251 | * 252 | */ 253 | public function get data():Object { 254 | return null; 255 | } 256 | 257 | /** 258 | * Required by ITextInput 259 | * 260 | */ 261 | public function set data(value:Object):void { 262 | } 263 | 264 | /** 265 | * Required by ITextInput 266 | * 267 | */ 268 | public function get listData():BaseListData { 269 | return null; 270 | } 271 | 272 | /** 273 | * Required by ITextInput 274 | * 275 | */ 276 | public function set listData(value:BaseListData):void { } 277 | 278 | /** 279 | * Required by ITextInput 280 | * 281 | */ 282 | public function get fontContext():IFlexModuleFactory { 283 | return null; 284 | } 285 | 286 | /** 287 | * Required by ITextInput 288 | * 289 | */ 290 | public function set fontContext(moduleFactory:IFlexModuleFactory):void { 291 | } 292 | 293 | /** 294 | * Required by ITextInput 295 | * 296 | */ 297 | public function get enableIME():Boolean { 298 | return false; 299 | } 300 | 301 | /** 302 | * Required by ITextInput 303 | * 304 | */ 305 | public function get imeMode():String { 306 | return null; 307 | } 308 | 309 | /** 310 | * Required by ITextInput 311 | * 312 | */ 313 | public function set imeMode(value:String):void { } 314 | } 315 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/controls/Menu.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 30 | 33 | 39 | 40 | 41 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/controls/ToolTip.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | package com.gskinner.zoe.controls { 30 | 31 | import flash.display.Graphics; 32 | import flash.filters.DropShadowFilter; 33 | import flash.text.TextFormat; 34 | 35 | import mx.containers.Canvas; 36 | 37 | import spark.components.Label; 38 | 39 | public class ToolTip extends Canvas { 40 | 41 | /** 42 | * @private 43 | * 44 | */ 45 | protected var _label:String; 46 | 47 | /** 48 | * @private 49 | * 50 | */ 51 | protected var tf:TextFormat; 52 | 53 | /** 54 | * @private 55 | * 56 | */ 57 | protected var padding:Number = 5; 58 | 59 | /** 60 | * @private 61 | * 62 | */ 63 | protected var _txt:Label; 64 | 65 | /** 66 | * Defines a custom ToolTip, currently used for displaying the Registration point. 67 | * 68 | */ 69 | public function ToolTip() { 70 | super(); 71 | 72 | _txt = new Label(); 73 | _txt.styleName = 'contentFont'; 74 | addElement(_txt); 75 | this.filters = [new DropShadowFilter(4, 45, 0x000000, 1, 5, 5, .56, 1)]; 76 | } 77 | 78 | /** 79 | * @private 80 | * 81 | */ 82 | public function show():void { 83 | this.setVisible(true); 84 | } 85 | 86 | /** 87 | * @private 88 | * 89 | */ 90 | public function hide():void { 91 | this.setVisible(false); 92 | } 93 | 94 | /** 95 | * @private 96 | * 97 | */ 98 | public function set labelField(value:String):void { 99 | _label = value; 100 | _txt.text = _label; 101 | draw(); 102 | } 103 | 104 | /** 105 | * Returns the width of this tip (including text width) 106 | * 107 | */ 108 | public function get actualWidth():Number { return _txt.width+padding; } 109 | 110 | /** 111 | * Returns the height of this tip (including text height) 112 | * 113 | */ 114 | public function get actualHeight():Number { return _txt.height+(padding/2); } 115 | 116 | /** 117 | * @private 118 | * 119 | */ 120 | protected function draw():void { 121 | var g:Graphics = this.graphics; 122 | g.clear(); 123 | 124 | g.beginFill(0xFFFFCC, 1); 125 | g.drawRoundRect(-padding/2, -padding/2, _txt.width + padding, _txt.height + (padding/2), 8, 8); 126 | g.endFill(); 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/data/AnimationState.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | package com.gskinner.zoe.data { 30 | 31 | /** 32 | * Defines a individual animation state, as created by CaptureSWF. 33 | * 34 | * @see com.gskinner.animationcapture.getStates 35 | * 36 | */ 37 | public class AnimationState { 38 | 39 | /** 40 | * Name of the state, as defined in the source swf file. 41 | * 42 | */ 43 | public var name:String; 44 | 45 | /** 46 | * The start of this state. 47 | * 48 | */ 49 | public var startFrame:uint; 50 | 51 | /** 52 | * End frame for this animation. 53 | * This value is auto-generated based on: 54 | * a) The start of a new sequence 55 | * or 56 | * b) An empty keyframe 57 | * 58 | */ 59 | public var endFrame:uint; 60 | 61 | public var speed:Number; 62 | 63 | public var next:String; 64 | 65 | /** 66 | * Creates a new AnimtaionState instance. 67 | * 68 | * @param name The name of this state, defined on the timeline by the loaded swf. 69 | * @param startFrame The 0 based start frame of this state. 70 | * @param endFrame The 0 based end frame of this state. 71 | * 72 | */ 73 | public function AnimationState(name:String, startFrame:uint, endFrame:uint, next:String, speed:Number) { 74 | this.name = name; 75 | this.startFrame = startFrame; 76 | this.endFrame = endFrame; 77 | this.next = next; 78 | this.speed = speed; 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/data/ExportType.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * 4 | * Copyright (c) 2010 Grant Skinner 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | package com.gskinner.zoe.data { 29 | 30 | /** 31 | * Constants used for Export formats. 32 | * 33 | */ 34 | public class ExportType { 35 | 36 | /** 37 | * When set Zoe will export individual PNG files. 38 | * 39 | */ 40 | public static const IMAGE_FRAME:String = 'imageFrame'; 41 | 42 | /** 43 | * When set Zoe will export a single PNG sprite sheet. 44 | * 45 | */ 46 | public static const IMAGE_SPRITE_SHEET:String = 'imageSheet'; 47 | 48 | /** 49 | * When set, Zoe will export JSON stub code for Easel. 50 | * @see http://www.easeljs.com 51 | * 52 | */ 53 | public static const DATA_JSON:String = 'dataJson'; 54 | 55 | /** 56 | * Will export JSON data, but wrap the result in a JSONP callback. 57 | * 58 | */ 59 | public static const DATA_JSONP:String = 'dataJsonp'; 60 | 61 | /** 62 | * When set Zoe will export no data. 63 | * 64 | */ 65 | public static const NONE:String = 'none'; 66 | 67 | } 68 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/data/FrameData.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | package com.gskinner.zoe.data { 29 | 30 | import flash.display.BitmapData; 31 | import flash.geom.Point; 32 | import flash.geom.Rectangle; 33 | 34 | public class FrameData { 35 | 36 | public var currentLabel:String; 37 | public var ref:BitmapData; 38 | public var rect:Rectangle; 39 | public var point:Point; 40 | public var index:uint; 41 | public var sheetIndex:int = 0; 42 | public var actualIndex:uint; 43 | public var registrationPoint:Point; 44 | 45 | public function FrameData(bmpd:BitmapData, index:uint, label:String) { 46 | this.ref = bmpd; 47 | this.index = index; 48 | this.currentLabel = label; 49 | } 50 | 51 | } 52 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/data/SourceFileData.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * 4 | * Copyright (c) 2010 Grant Skinner 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | package com.gskinner.zoe.data { 29 | 30 | import flash.geom.Rectangle; 31 | import flash.utils.escapeMultiByte; 32 | import flash.utils.unescapeMultiByte; 33 | 34 | /** 35 | * VO to hold settings for individual SWF files 36 | * used to define each row in the main file dropdown 37 | * 38 | */ 39 | public class SourceFileData { 40 | 41 | /** 42 | * The total number of frames to capture (0 means capture all) 43 | */ 44 | public var frameCount:Number; 45 | 46 | /** 47 | * The maximum width of the bitmap to export 48 | */ 49 | public var bitmapWidth:Number; 50 | 51 | /** 52 | * The maximum height of the bitmap to export 53 | */ 54 | public var bitmapHeight:Number; 55 | 56 | /** 57 | * Background color to display behind the animation. 58 | */ 59 | public var backgroundColor:uint; 60 | 61 | /** 62 | * Shows or hides the transparency grid behind the animation. 63 | */ 64 | public var showGrid:Boolean; 65 | 66 | /** 67 | * The bounds to capture from the loaded animation. 68 | */ 69 | public var frameBounds:Rectangle; 70 | 71 | /** 72 | * Extra padding to apply to the frameBound upon export (will not visually display) 73 | */ 74 | public var exportPadding:Number; 75 | 76 | /** 77 | * 78 | */ 79 | public var overPaint:Boolean; 80 | 81 | /** 82 | * The scale of the clip. 83 | */ 84 | public var scale:Number; 85 | 86 | /** 87 | * The absolute URI to the swf 88 | */ 89 | public var sourcePath:String; 90 | 91 | /** 92 | * Sets the image format to be exported. (A full SpriteSheet, or individual frames) 93 | * 94 | */ 95 | public var imageExportType:String; 96 | 97 | /** 98 | * Specifies whether there JSON source should be exported or not. 99 | */ 100 | public var dataExportType:String; 101 | 102 | /** 103 | * Specfies the name of the callback used when exporting jsonp 104 | */ 105 | public var jsonpCallback:String = 'callback'; 106 | 107 | /** 108 | * Specifies threshold level for comparing Bitmapdata. 109 | */ 110 | public var threshold:Number; 111 | 112 | /** 113 | * Specifies reuse frames. 114 | */ 115 | public var reuseFrames:Boolean; 116 | 117 | /** 118 | * Flag to always export image with pow(2,n) sizes. 119 | */ 120 | public var maintainPow2:Boolean; 121 | 122 | /** 123 | * What fps our Spritesheet should be exported with. 124 | */ 125 | public var fps:Number = 24; 126 | 127 | /** 128 | * @private 129 | */ 130 | protected var _name:String; 131 | 132 | /** 133 | * @private 134 | */ 135 | protected var _destinationPath:String; 136 | 137 | /** 138 | * @private 139 | */ 140 | public var variableFrameDimensions:Boolean; 141 | 142 | /** 143 | * @private 144 | */ 145 | public var isDirty:Boolean = true; 146 | 147 | /** 148 | * @private 149 | * 150 | */ 151 | public var basePath:String; 152 | 153 | protected var _animations:Object; 154 | 155 | /** 156 | * Creates a new SourceFileData instance 157 | * 158 | */ 159 | public function SourceFileData() { 160 | frameBounds = new Rectangle(); 161 | backgroundColor = 0xcccccc; 162 | showGrid = true; 163 | maintainPow2 = true; 164 | exportPadding = 0; 165 | overPaint = false; 166 | frameCount = 0; 167 | scale = 1; 168 | _animations = {}; 169 | 170 | //Set the default image size 171 | bitmapHeight = bitmapWidth = 2048; 172 | 173 | //Turn on re-use by default, set to a low tolerance (will only remove frames exactly the same) 174 | reuseFrames = true; 175 | threshold = .01; 176 | } 177 | 178 | /** 179 | * The name to use for export and display in the main ui. 180 | * 181 | */ 182 | public function set name(value:String):void { 183 | _name = escapeMultiByte(value); 184 | } 185 | public function get name():String { 186 | return unescapeMultiByte(_name); 187 | } 188 | 189 | /** 190 | * Defines the output folder to save captured assets. 191 | * 192 | */ 193 | public function set destinationPath(value:String):void { 194 | _destinationPath = escapeMultiByte(value); 195 | } 196 | public function get destinationPath():String { 197 | return unescapeMultiByte(_destinationPath); 198 | } 199 | 200 | public function getNextAnimationName(label:String):String { 201 | return _animations[label] == null?null:_animations[label].next; 202 | } 203 | 204 | public function getAnimationSpeed(label:String):Number { 205 | return _animations[label] == null?1:_animations[label].speed; 206 | } 207 | 208 | public function setAnimationData(anim:String, next:String, speed:Number):void { 209 | var value:Object = this._animations[anim] || {}; 210 | value.next = next; 211 | value.speed = speed; 212 | 213 | this._animations[anim] = value; 214 | } 215 | 216 | /** 217 | * Convert to an generic object, so we can save as AMF to the file system. 218 | * 219 | */ 220 | public function serialize():Object { 221 | 222 | var obj:Object = { 223 | bitmapWidth:bitmapWidth, 224 | bitmapHeight:bitmapHeight, 225 | backgroundColor:backgroundColor, 226 | showGrid:showGrid, 227 | frameBounds:{x:frameBounds.x, y:frameBounds.y, width:frameBounds.width, height:frameBounds.height}, 228 | exportPadding:exportPadding, 229 | overPaint:overPaint, 230 | scale:scale, 231 | destinationPath:destinationPath, 232 | sourcePath:sourcePath, 233 | name:name, 234 | threshold:threshold, 235 | jsonpCallback:jsonpCallback, 236 | 237 | imageExportType:imageExportType, 238 | dataExportType:dataExportType, 239 | fps:fps, 240 | animations:_animations, 241 | 242 | reuseFrames:reuseFrames, 243 | variableFrameDimensions:variableFrameDimensions, 244 | frameCount:frameCount, 245 | maintainPow2:maintainPow2, 246 | basePath:basePath, 247 | isDirty:isDirty 248 | } 249 | 250 | return obj; 251 | } 252 | 253 | /** 254 | * Converts our saved data into valid properties. 255 | * 256 | */ 257 | public function deserialize(value:Object):void { 258 | bitmapWidth = value.bitmapWidth; 259 | bitmapHeight = value.bitmapHeight; 260 | backgroundColor = value.backgroundColor; 261 | showGrid = value.showGrid; 262 | frameBounds = new Rectangle(value.frameBounds.x||0, value.frameBounds.y||0, value.frameBounds.width||0, value.frameBounds.height||0); 263 | 264 | exportPadding = value.exportPadding; 265 | 266 | // Fix old (Pre 0.5.0 padding values) 267 | if (!isNaN(exportPadding) && exportPadding > 2) { 268 | exportPadding = 2; 269 | } 270 | 271 | overPaint = value.overPaint || false; 272 | 273 | destinationPath = value.destinationPath; 274 | sourcePath = value.sourcePath; 275 | name = value.name; 276 | variableFrameDimensions = value.variableFrameDimensions == null?true:value.variableFrameDimensions; 277 | threshold = isNaN(value.threshold) ? 0 : value.threshold; 278 | frameCount = isNaN(value.frameCount)? 0: value.frameCount; 279 | isDirty = value.isDirty; 280 | reuseFrames = value.reuseFrames; 281 | dataExportType = value.dataExportType || ExportType.DATA_JSON; 282 | imageExportType = value.imageExportType || ExportType.IMAGE_SPRITE_SHEET; 283 | scale = value.scale || 1; 284 | maintainPow2 = value.maintainPow2 || true; 285 | jsonpCallback = value.jsonpCallback || 'callback'; 286 | fps = isNaN(value.fps)?24:value.fps; 287 | _animations = value.animations || {}; 288 | basePath = value.basePath || ''; 289 | } 290 | } 291 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/events/CaptureEvent.as: -------------------------------------------------------------------------------- 1 | package com.gskinner.zoe.events { 2 | 3 | import flash.events.Event; 4 | 5 | public class CaptureEvent extends Event { 6 | 7 | public static const BEGIN:String = "begin"; 8 | public static const INVALID_BITMAP:String = "invalidBitmap"; 9 | public static const INVALID_PATH:String = "invalidPath"; 10 | public static const SWF_INIT:String = "swfInit"; 11 | public static const REG_PT_CHANGE:String = "regPtChange"; 12 | public static const VAR_HEIGHT_COMPLETE:String = "varHeightComplete"; 13 | 14 | public var message:String; 15 | public var data:Object; 16 | 17 | public function CaptureEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, message:String = null, data:Object = null) { 18 | super(type, bubbles, cancelable); 19 | this.data = data; 20 | this.message = message; 21 | } 22 | 23 | override public function clone():Event { 24 | return new CaptureEvent(type, bubbles, cancelable, message); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/events/PreviewPanelEvent.as: -------------------------------------------------------------------------------- 1 | package com.gskinner.zoe.events { 2 | 3 | import flash.events.Event; 4 | 5 | public class PreviewPanelEvent extends Event { 6 | 7 | public static const COLOR_CHANGED:String = 'colorChanged'; 8 | public static const COLOR_OPEN:String = 'colorOpen'; 9 | public static const COLOR_MOVE:String = 'colorMove'; 10 | public static const PLAY_CLICKED:String = 'playClicked'; 11 | public static const FREQUENCY_RATE_CHANGED:String = 'frequencyRateChanged'; 12 | public static const UPDATE_FRAME_POSITION:String = 'updateFramePosition'; 13 | public static const CHANGE_END_FRAME_POSITION:String = 'changeEndFramePosition'; 14 | public static const CHANGE_START_FRAME_POSITION:String = 'changeStartFramePosition'; 15 | public static const UPDATE_SLIDER_POSITION:String = 'updateSliderPosition'; 16 | 17 | public function PreviewPanelEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) { 18 | super(type, bubbles, cancelable); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/events/ResultEvent.as: -------------------------------------------------------------------------------- 1 | package com.gskinner.zoe.events { 2 | 3 | import flash.events.Event; 4 | 5 | public class ResultEvent extends Event { 6 | 7 | public static const COMPLETE:String = Event.COMPLETE; 8 | 9 | public var data:Object; 10 | 11 | public function ResultEvent(type:String, data:Object) { 12 | this.data = data; 13 | 14 | super(type); 15 | } 16 | 17 | override public function clone():Event { 18 | return new ResultEvent(type, data); 19 | } 20 | 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/model/FileModel.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | package com.gskinner.zoe.model { 29 | 30 | import com.gskinner.filesystem.Preferences; 31 | import com.gskinner.utils.CallLater; 32 | import com.gskinner.zoe.data.SourceFileData; 33 | import com.gskinner.zoe.views.CapturePreview; 34 | 35 | import flash.events.Event; 36 | import flash.events.EventDispatcher; 37 | import flash.filesystem.File; 38 | import flash.geom.Rectangle; 39 | 40 | import mx.collections.ArrayList; 41 | 42 | import spark.components.DropDownList; 43 | import spark.events.IndexChangeEvent; 44 | 45 | /** 46 | * Instead of interacting with the top file list directly, we access it though this model. 47 | * This way we can handle saving and ui updating here. 48 | * 49 | */ 50 | public class FileModel extends EventDispatcher { 51 | 52 | protected const FILES_NAME:String = 'com.gskinner.animationcapture.data.FileList::files'; 53 | protected const INDEX_NAME:String = 'com.gskinner.animationcapture.data.FileList::index'; 54 | 55 | protected var _dp:ArrayList; 56 | protected var _target:DropDownList; 57 | protected var _swfCapture:CapturePreview; 58 | 59 | public function FileModel() { 60 | //Erase old prefs if they exist 61 | if (isNaN(Preferences.getPref('v'))) { 62 | Preferences.clear(true); 63 | Preferences.setPref('v', 1, false, true); 64 | } 65 | } 66 | 67 | /** 68 | * Returns a refernce to the swf CapturePreview 69 | * 70 | */ 71 | public function get swfCapture():CapturePreview { 72 | return _swfCapture; 73 | } 74 | 75 | /** 76 | * Gets the currenly selected item from the list, or null. 77 | * 78 | */ 79 | public function get selectedItem():SourceFileData { 80 | return _target!=null?_target.selectedItem:null; 81 | } 82 | 83 | /** 84 | * Sets the swf capture instance. 85 | * 86 | */ 87 | public function set swfCapture(value:CapturePreview):void { 88 | _swfCapture = value; 89 | } 90 | 91 | /** 92 | * Deletes the selected item from the list, 93 | * and saves the updated state. 94 | * 95 | */ 96 | public function deleteSelected():void { 97 | _dp.removeItem(selectedItem); 98 | invalidate(); 99 | 100 | _target.selectedIndex = 0; 101 | 102 | dispatchEvent(new Event(Event.CHANGE)); 103 | } 104 | 105 | /** 106 | * Gets the dropDownLiat we want to update (the main top drop-down) 107 | * 108 | */ 109 | public function get target():DropDownList { return _target; } 110 | public function set target(value:DropDownList):void { 111 | _target = value; 112 | _target.labelField = 'name'; 113 | _target.addEventListener(IndexChangeEvent.CHANGE, handleSelectionChange, false, 0, true); 114 | 115 | var oldDp:Array = Preferences.getPref(FILES_NAME); 116 | if (oldDp != null) { 117 | var arr:Array = []; 118 | var l:uint = oldDp.length; 119 | for (var i:uint=0;i -1) { 272 | (_dp.getItemAt(currentIndex) as SourceFileData).frameBounds = new Rectangle(); 273 | (_dp.getItemAt(currentIndex) as SourceFileData).exportPadding = 0; 274 | _target.selectedIndex = currentIndex; 275 | } else { 276 | _dp.addItem(fileToData(file)); 277 | _target.selectedIndex = _dp.length-1; 278 | } 279 | 280 | invalidate(); 281 | 282 | dispatchEvent(new Event(Event.CHANGE)); 283 | } 284 | 285 | /** 286 | * @private 287 | * 288 | */ 289 | protected function handleSelectionChange(event:IndexChangeEvent):void { 290 | invalidate(); 291 | dispatchEvent(new Event(Event.CHANGE)); 292 | } 293 | 294 | /** 295 | * @private 296 | * 297 | */ 298 | protected function indexOfItem(file:File):int { 299 | var l:uint = _dp.length; 300 | for (var i:uint=0;i 28 | 30 | 31 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 63 | 64 | 65 | 66 | 67 | 68 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/skins/BottomMenuButtonSkin.mxml: -------------------------------------------------------------------------------- 1 | 28 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 59 | 60 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/skins/PlayPauseButton.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | [Embed (source="../../../../assets/play.png")] 43 | [Bindable] 44 | protected var playIcon:Class; 45 | 46 | [Embed (source="../../../../assets/play-pause.png")] 47 | [Bindable] 48 | protected var pauseIcon:Class; 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/skins/TransparencyButton.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 32 | 33 | 34 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/styles/styles.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | @namespace s "library://ns.adobe.com/flex/spark"; 30 | @namespace mx "library://ns.adobe.com/flex/halo"; 31 | @namespace controls "com.gskinner.controls.*"; 32 | 33 | /**************************************************** 34 | * TEXT 35 | ****************************************************/ 36 | .header1 { 37 | fontFamily: contentFont; 38 | fontSize: 14; 39 | fontWeight: "bold"; 40 | paddingRight: 5; 41 | } 42 | 43 | .contentText { 44 | fontFamily: contentFont; 45 | fontSize: 14; 46 | lineHeight: 18; 47 | color: #555555; 48 | } 49 | 50 | .smallText { 51 | fontFamily: contentFont; 52 | fontSize: 10; 53 | color: #555555; 54 | } 55 | 56 | .formText { 57 | fontFamily: contentFont; 58 | fontSize: 12; 59 | color: #555555; 60 | } 61 | 62 | .formTextError { 63 | fontFamily: contentFont; 64 | fontSize: 12; 65 | color: #d50303; 66 | } 67 | 68 | .errorText { 69 | fontSize: 12; 70 | fontWeight: "bold"; 71 | color: #d50303; 72 | } 73 | 74 | .successText { 75 | fontSize: 12; 76 | fontWeight: "bold"; 77 | color: #175903; 78 | } 79 | 80 | .appTitleLarge { 81 | fontFamily: contentFont; 82 | fontSize: 24; 83 | fontWeight: "bold"; 84 | color: #000000; 85 | } 86 | 87 | .appTitleSmall { 88 | fontFamily: contentFont; 89 | fontSize: 11; 90 | fontWeight: "bold"; 91 | color: #7f7f7f; 92 | } 93 | 94 | .headerTextSmall { 95 | fontFamily: contentFont; 96 | fontSize: 13; 97 | fontWeight: "bold"; 98 | color: #000000; 99 | } 100 | 101 | #statusText { 102 | fontWeight: "bold"; 103 | lineHeight: 16; 104 | } 105 | 106 | .bottomMenu { 107 | fontFamily: contentFont; 108 | fontSize: 16; 109 | fontWeight: bold; 110 | color: #DDDDDD; 111 | } 112 | 113 | .versionCheck { 114 | fontFamily: contentFont; 115 | fontWeight: "bold"; 116 | color: #444444; 117 | fontSize: 11; 118 | } 119 | 120 | .versionCheckError { 121 | fontFamily: contentFont; 122 | fontWeight: "bold"; 123 | color: #DD0000; 124 | fontSize: 11; 125 | } 126 | 127 | .versionCheckCorrect { 128 | fontFamily: contentFont; 129 | fontWeight: "bold"; 130 | color: #175903; 131 | fontSize: 11; 132 | textAlign: "center" 133 | } 134 | 135 | /**************************************************** 136 | * Class Selectors 137 | ****************************************************/ 138 | s|WindowedApplication { 139 | backgroundColor: #333333; 140 | backgroundAlpha: 1; 141 | resizeAffordanceWidth: 6; 142 | backgroundImage: Embed(source="assets/TileMainBG.png"); 143 | left:10px; 144 | } 145 | 146 | s|VScrollBar { 147 | skinClass: ClassReference("com.gskinner.skins.VScrollBarSkin"); 148 | } 149 | 150 | s|NumericStepper { 151 | fontSize:11; 152 | } 153 | 154 | s|TextInput { 155 | borderVisible: false; 156 | contentBackgroundColor: "0xDDDDDD"; 157 | contentBackgroundAlpha: .6; 158 | } 159 | 160 | s|TextArea s|VScrollBar { 161 | skinClass: ClassReference("com.gskinner.skins.VScrollBarSkin"); 162 | } 163 | 164 | s|List { 165 | contentBackgroundColor: "0xDDDDDD"; 166 | contentBackgroundAlpha: 1; 167 | } 168 | 169 | s|Button { 170 | skinClass: ClassReference("com.gskinner.skins.IconButtonSkin"); 171 | } 172 | 173 | s|ButtonBar { 174 | skinClass: ClassReference("com.gskinner.zoe.skins.BottomMenuButtonBarSkin"); 175 | } 176 | 177 | s|ToggleButton { 178 | iconUp: Embed("assets/TransparencyBtn_up.png"); 179 | } 180 | 181 | /**************************************************** 182 | * Style Names / ID's 183 | ****************************************************/ 184 | .textButton { 185 | paddingLeft: 10; 186 | paddingRight: 6; 187 | } 188 | 189 | .addFileButton { 190 | skinClass: ClassReference("com.gskinner.skins.ImageButtonSkin"); 191 | iconUp: Embed("assets/FileIconAdd.png"); 192 | /*iconOver: "assets/images/FileIcon.png"; 193 | iconDown: "assets/images/FileIcon.png";*/ 194 | } 195 | 196 | .folderButton { 197 | skinClass: ClassReference("com.gskinner.skins.ImageButtonSkin"); 198 | iconUp: Embed("assets/FolderIcon.png"); 199 | } 200 | 201 | .helpButton { 202 | skinClass: ClassReference("com.gskinner.skins.ImageButtonSkin"); 203 | paddingLeft: -2; 204 | paddingTop:1; 205 | iconUp: Embed("assets/HelpIcon.png"); 206 | } 207 | 208 | .deleteButton { 209 | skinClass: ClassReference("com.gskinner.skins.ImageButtonSkin"); 210 | iconUp: Embed("assets/DeleteConfigButton.png"); 211 | } 212 | 213 | .refreshButton { 214 | skinClass: ClassReference("com.gskinner.skins.ImageButtonSkin"); 215 | iconUp: Embed("assets/Refresh.png"); 216 | } 217 | 218 | .exportButton { 219 | skinClass: ClassReference("com.gskinner.skins.IconButtonSkin"); 220 | iconUp: Embed("assets/RunArrow.png"); 221 | paddingRight: 4; 222 | paddingTop: 4; 223 | iconPaddingTop: -1; 224 | } 225 | 226 | .bgColorPicker { 227 | textInputClass: ClassReference("com.gskinner.zoe.controls.ColorPreviewText"); 228 | } 229 | 230 | .transparentSkin { 231 | skinClass: ClassReference("com.gskinner.zoe.skins.TransparencyButton"); 232 | } 233 | 234 | .simpleButton { 235 | paddingTop: 4; 236 | skinClass: ClassReference("com.gskinner.skins.IconButtonSkin"); 237 | } 238 | 239 | /******************************************************************************* 240 | * Embed Fonts through CSS 241 | ********************************************************************************/ 242 | 243 | /* SPARK */ 244 | @font-face { 245 | src: url("/assets/fonts/HelveticaLTStd-Light.otf"); 246 | fontFamily: arialEmbed; 247 | fontStyle: normal; 248 | fontWeight: normal; 249 | advancedAntiAliasing: true; 250 | cff: true; /* Set to true for use with Fx4 (Spark), false for Fx3 (Halo)*/ 251 | 252 | unicodeRange: 253 | U+0041-U+005A, /* Upper-Case [A..Z] */ 254 | U+0061-U+007A, /* Lower-Case a-z */ 255 | U+0030-U+0039, /* Numbers [0..9] */ 256 | U+00CB, /* ë */ 257 | U+0020-U+002F,U+003A-U+0040,U+005B-U+0060,U+007B-U+007E; /* Punctuation */ 258 | } 259 | 260 | @font-face { 261 | src: url("/assets/fonts/HelveticaLTStd-Light.otf"); 262 | fontFamily: contentFont; 263 | fontStyle: normal; 264 | fontWeight: bold; 265 | advancedAntiAliasing: true; 266 | cff: true; 267 | 268 | unicodeRange: 269 | U+0041-U+005A, 270 | U+0061-U+007A, 271 | U+0030-U+0039, 272 | U+00CB, /* ë */ 273 | U+0020-U+002F,U+003A-U+0040,U+005B-U+0060,U+007B-U+007E; 274 | } 275 | 276 | @font-face { 277 | src: url("/assets/fonts/HelveticaLTStd-Light.otf"); 278 | fontFamily: contentFont; 279 | fontStyle: italic; 280 | fontWeight: normal; 281 | advancedAntiAliasing: true; 282 | cff: true; 283 | 284 | unicodeRange: 285 | U+0041-U+005A, 286 | U+0061-U+007A, 287 | U+0030-U+0039, 288 | U+00CB, /* ë */ 289 | U+0020-U+002F,U+003A-U+0040,U+005B-U+0060,U+007B-U+007E; 290 | } 291 | 292 | @font-face { 293 | src: url("/assets/fonts/HelveticaLTStd-Light.otf"); 294 | fontFamily: contentFont; 295 | fontStyle: italic; 296 | fontWeight: bold; 297 | advancedAntiAliasing: true; 298 | cff: true; 299 | 300 | unicodeRange: 301 | U+0041-U+005A, 302 | U+0061-U+007A, 303 | U+0030-U+0039, 304 | U+00CB, /* ë */ 305 | U+0020-U+002F,U+003A-U+0040,U+005B-U+0060,U+007B-U+007E; 306 | } 307 | 308 | /* HALO */ 309 | @font-face { 310 | src: url("/assets/fonts/HelveticaLTStd-Light.otf"); 311 | fontFamily: contentFont; 312 | fontStyle: normal; 313 | fontWeight: normal; 314 | advancedAntiAliasing: true; 315 | cff: true; 316 | 317 | unicodeRange: 318 | U+0041-U+005A, 319 | U+0061-U+007A, 320 | U+0030-U+0039, 321 | U+00CB, /* ë */ 322 | U+0020-U+002F,U+003A-U+0040,U+005B-U+0060,U+007B-U+007E; 323 | } 324 | 325 | @font-face { 326 | src: url("/assets/fonts/HelveticaLTStd-Light.otf"); 327 | fontFamily: contentFont; 328 | fontStyle: normal; 329 | fontWeight: bold; 330 | advancedAntiAliasing: true; 331 | cff: false; 332 | 333 | unicodeRange: 334 | U+0041-U+005A, 335 | U+0061-U+007A, 336 | U+0030-U+0039, 337 | U+00CB, /* ë */ 338 | U+0020-U+002F,U+003A-U+0040,U+005B-U+0060,U+007B-U+007E; 339 | } 340 | 341 | @font-face { 342 | src: url("/assets/fonts/HelveticaLTStd-Light.otf"); 343 | fontFamily: contentFont; 344 | fontStyle: italic; 345 | fontWeight: normal; 346 | advancedAntiAliasing: true; 347 | cff: false; 348 | 349 | unicodeRange: 350 | U+0041-U+005A, 351 | U+0061-U+007A, 352 | U+0030-U+0039, 353 | U+00CB, /* ë */ 354 | U+0020-U+002F,U+003A-U+0040,U+005B-U+0060,U+007B-U+007E; 355 | } 356 | 357 | @font-face { 358 | src: url("/assets/fonts/HelveticaLTStd-Light.otf"); 359 | fontFamily: contentFont; 360 | fontStyle: italic; 361 | fontWeight: bold; 362 | advancedAntiAliasing: true; 363 | cff: false; 364 | 365 | 366 | unicodeRange: 367 | U+0041-U+005A, 368 | U+0061-U+007A, 369 | U+0030-U+0039, 370 | U+00CB, /* ë */ 371 | U+0020-U+002F,U+003A-U+0040,U+005B-U+0060,U+007B-U+007E; 372 | } 373 | 374 | 375 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/ui/Divider.mxml: -------------------------------------------------------------------------------- 1 | 28 | 34 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/utils/ApplicationUpdater.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | package com.gskinner.zoe.utils { 30 | 31 | import air.update.ApplicationUpdaterUI; 32 | import air.update.events.UpdateEvent; 33 | 34 | import flash.filesystem.File; 35 | 36 | /** 37 | * @private 38 | * 39 | */ 40 | public class ApplicationUpdater { 41 | 42 | /** 43 | * @private 44 | * 45 | */ 46 | protected static var updater:ApplicationUpdaterUI; 47 | 48 | /** 49 | * @private 50 | * 51 | */ 52 | protected static var wasInitilized:Boolean = false; 53 | 54 | public function ApplicationUpdater() { 55 | 56 | } 57 | 58 | /** 59 | * @private 60 | * 61 | */ 62 | public static function checkForUpdates(invisible:Boolean = false):void { 63 | if (wasInitilized == false) { 64 | updater = new ApplicationUpdaterUI(); 65 | updater.isCheckForUpdateVisible = !invisible; 66 | updater.addEventListener(UpdateEvent.INITIALIZED, handleUpdaterInit, false, 0, true); 67 | 68 | updater.configurationFile = File.applicationDirectory.resolvePath('data/version.xml'); 69 | 70 | updater.initialize(); 71 | } else { 72 | updater.isCheckForUpdateVisible = !invisible; 73 | updater.checkNow(); 74 | } 75 | } 76 | 77 | /** 78 | * @private 79 | * 80 | */ 81 | protected static function handleUpdaterInit(event:UpdateEvent):void { 82 | wasInitilized = true; 83 | updater.checkNow(); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/utils/BitmapCompare.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | package com.gskinner.zoe.utils { 30 | 31 | import flash.display.BitmapData; 32 | import flash.filters.BlurFilter; 33 | import flash.filters.ColorMatrixFilter; 34 | import flash.geom.Point; 35 | 36 | /** 37 | * Utility class used to compare bitmaps for reusing frames when exporting sprite sheet. 38 | * 39 | */ 40 | 41 | public class BitmapCompare { 42 | 43 | protected var colorMatrix:ColorMatrixFilter; 44 | 45 | /** 46 | * @private 47 | * 48 | */ 49 | protected var blur:BlurFilter; 50 | 51 | /** 52 | * @private 53 | * 54 | */ 55 | protected var _blurAmount:Number; 56 | 57 | /** 58 | * @private 59 | * 60 | */ 61 | protected var _threshold:Number = 0.5; 62 | 63 | public function BitmapCompare(blurAmount:Number=10) { 64 | colorMatrix = new ColorMatrixFilter( 65 | [ 66 | 0.3086, 0.6094, 0.0820, 0, 0, 67 | 0.3086, 0.6094, 0.0820, 0, 0, 68 | 0.3086, 0.6094, 0.0820, 0, 0, 69 | 0, 0, 0, 1, 0 70 | ]); 71 | 72 | _blurAmount = blurAmount; 73 | blur = new BlurFilter(blurAmount, blurAmount); 74 | } 75 | 76 | /** 77 | * @private 78 | * 79 | */ 80 | public function get threshold():Number { return _threshold; } 81 | 82 | /** 83 | * @private 84 | * 85 | */ 86 | public function set threshold(value:Number):void { 87 | _threshold = value; 88 | } 89 | 90 | /** 91 | * @private 92 | * 93 | */ 94 | public function get blurAmount():Number { return _blurAmount; } 95 | 96 | /** 97 | * @private 98 | * 99 | */ 100 | public function set blurAmount(value:Number):void { 101 | _blurAmount = value; 102 | } 103 | 104 | /** 105 | * @private 106 | * 107 | */ 108 | public function different(item:BitmapData, item2:BitmapData, index:Number):Boolean { 109 | var result:Object = item.compare(item2); 110 | if (result is BitmapData) { 111 | var resultBmpd:BitmapData = result as BitmapData; 112 | resultBmpd.applyFilter(resultBmpd, resultBmpd.rect, new Point(), colorMatrix); 113 | resultBmpd.applyFilter(resultBmpd, resultBmpd.rect, new Point(), blur); 114 | 115 | var container:BitmapData = new BitmapData(item.width,item.height,true,0x000000); 116 | var changedPixels:Number = container.threshold(resultBmpd, resultBmpd.rect, new Point(), ">", threshold * 0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF, false); 117 | 118 | if (changedPixels > 0) { 119 | return true; 120 | } 121 | return false; 122 | } else { 123 | if (result == 0) { 124 | //BitmapData objects are equivalent (with the same width, height, and identical pixel values; 125 | return false; 126 | } else if (result == -3) { 127 | //widths of the BitmapData objects are not equal; 128 | } else if (result == -4) { 129 | }//heights of the BitmapData objects are not equal, but the widths are the same; 130 | } 131 | return true; 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/utils/CaptureSWF.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | package com.gskinner.zoe.utils { 30 | 31 | import com.gskinner.zoe.data.AnimationState; 32 | import com.gskinner.zoe.data.ExportType; 33 | import com.gskinner.zoe.data.FrameData; 34 | import com.gskinner.zoe.events.CaptureEvent; 35 | import com.gskinner.zoe.events.ResultEvent; 36 | import com.gskinner.zoe.model.FileModel; 37 | import com.maccherone.json.JSON; 38 | 39 | import flash.display.BitmapData; 40 | import flash.display.DisplayObject; 41 | import flash.display.FrameLabel; 42 | import flash.display.MovieClip; 43 | import flash.display.PNGEncoderOptions; 44 | import flash.display.Stage; 45 | import flash.events.Event; 46 | import flash.events.EventDispatcher; 47 | import flash.filesystem.File; 48 | import flash.filesystem.FileMode; 49 | import flash.filesystem.FileStream; 50 | import flash.geom.ColorTransform; 51 | import flash.geom.Matrix; 52 | import flash.geom.Point; 53 | import flash.geom.Rectangle; 54 | import flash.net.URLVariables; 55 | import flash.utils.ByteArray; 56 | import flash.utils.Dictionary; 57 | 58 | import mx.controls.SWFLoader; 59 | 60 | /** 61 | * Utility class used to capture each frame of the loaded clip. 62 | * Also reads timeline information from the file, used for building a EaselJS BitmapSequence object 63 | * 64 | */ 65 | public class CaptureSWF extends EventDispatcher { 66 | 67 | protected static const MAX_WIDTH:Number = 2048; 68 | protected static const MAX_HEIGHT:Number = 2048; 69 | 70 | /** 71 | * @private 72 | * 73 | */ 74 | protected var bitmaps:Array; 75 | 76 | /** 77 | * @private 78 | * 79 | */ 80 | protected var currentCaptureFrame:uint; 81 | 82 | /** 83 | * @private 84 | * 85 | */ 86 | protected var swf:SWFLoader; 87 | 88 | /** 89 | * @private 90 | * 91 | */ 92 | protected var columnCount:uint; 93 | 94 | /** 95 | * @private 96 | * 97 | */ 98 | public var exportedImageNames:Array; 99 | 100 | /** 101 | * @private 102 | * 103 | */ 104 | protected var startFrameRate:uint; 105 | 106 | /** 107 | * @private 108 | * 109 | */ 110 | protected var fileModel:FileModel; 111 | 112 | /** 113 | * @private 114 | * 115 | */ 116 | protected var _threshold:Number; 117 | 118 | /** 119 | * @private 120 | * 121 | */ 122 | protected var boundsColorTint:uint = 0x0000FF; 123 | 124 | /** 125 | * @private 126 | * 127 | */ 128 | protected var stage:Stage; 129 | 130 | /** 131 | * @private 132 | * 133 | */ 134 | protected var findBoundsBmpd:BitmapData; 135 | 136 | /** 137 | * @private 138 | * 139 | */ 140 | protected var findBoundsColorTransform:ColorTransform; 141 | 142 | /** 143 | * @private 144 | * 145 | */ 146 | protected var rects:Vector. 147 | 148 | /** 149 | * @private 150 | * 151 | */ 152 | protected var rectLookup:Dictionary; 153 | 154 | /** 155 | * @private 156 | * 157 | */ 158 | protected var positions:Vector.; 159 | 160 | /** 161 | * @private 162 | * 163 | */ 164 | protected var pointLookup:Dictionary; 165 | 166 | /** 167 | * @private 168 | * 169 | */ 170 | protected var sheetWidth:Number; 171 | 172 | /** 173 | * @private 174 | * 175 | */ 176 | protected var sheetHeight:Number; 177 | 178 | /** 179 | * @private 180 | * 181 | */ 182 | protected var captureBounds:Array; 183 | 184 | /** 185 | * @private 186 | * 187 | */ 188 | protected var isComplex:Boolean = false; 189 | 190 | protected var zeroRegistrationPoint:Point; 191 | 192 | /** 193 | * @private 194 | * 195 | */ 196 | protected var _displayPoint:Point; 197 | 198 | protected var _frameCaptureWidth:Number; 199 | 200 | protected var _frameCaptureHeight:Number; 201 | 202 | protected var _startSwf:SWFLoader; 203 | 204 | protected var source:String; 205 | protected var _lastFrameLabel:String; 206 | 207 | protected var currentLabels:Vector.; 208 | 209 | /** 210 | * Created a new CaptureSwf instance. 211 | * We use an enter frame to capture individual frames, 212 | * they are drawn to individual bitmap objects, then on export 213 | * those objects are stitched together to make a sprite sheet. 214 | * 215 | * @param model The Model to pull the swf data from. 216 | * 217 | */ 218 | public function CaptureSWF(model:FileModel) { 219 | super(); 220 | 221 | fileModel = model; 222 | 223 | findBoundsColorTransform = new ColorTransform(); 224 | findBoundsColorTransform.color = boundsColorTint; 225 | 226 | zeroRegistrationPoint = new Point(); 227 | } 228 | 229 | /** 230 | * Sets a new swf and registrationPoint. 231 | * 232 | */ 233 | public function updateSWF(swf:SWFLoader, source:String):void { 234 | this.swf = swf; 235 | this.source = source; 236 | } 237 | 238 | public function get clip():MovieClip { 239 | return swf.content as MovieClip; 240 | } 241 | 242 | /** 243 | * Returns the current swf's frame count. 244 | * 245 | */ 246 | public function get frameCount():Number { 247 | return fileModel.selectedItem.frameCount == 0?clip.totalFrames:fileModel.selectedItem.frameCount; 248 | } 249 | 250 | /** 251 | * Sets Threshold level for comparing bitmaps. 252 | * 253 | */ 254 | public function set threshold(value:Number):void { 255 | _threshold = value; 256 | } 257 | 258 | /** 259 | * Begins the frame by frame capture of the current clip. 260 | * This operation is asynchronous, when capture is complete a complete event will be dispatched. 261 | * 262 | */ 263 | public function capture():void { 264 | isComplex = false; 265 | positions = null; 266 | pointLookup = null; 267 | bitmaps = []; 268 | captureBounds = []; 269 | 270 | //Reload the swf 271 | _startSwf = swf; 272 | 273 | if (swf) { 274 | swf.removeEventListener(Event.INIT, handleSwfInit); 275 | clip.removeEventListener(Event.EXIT_FRAME, handleCaptureFrames); 276 | } 277 | 278 | swf = new SWFLoader(); 279 | swf.setActualSize(MAX_WIDTH, MAX_HEIGHT); 280 | swf.addEventListener(Event.INIT, handleSwfInit, false, 0, true); 281 | swf.load(source); 282 | 283 | dispatchEvent(new CaptureEvent(CaptureEvent.BEGIN)); 284 | } 285 | 286 | protected function handleSwfInit(event:Event):void { 287 | getRegistrationPoint(); //Hides the registration point, if it exists 288 | 289 | currentCaptureFrame = 0; 290 | startFrameRate = _startSwf.stage.frameRate; 291 | _startSwf.stage.frameRate = 1000; 292 | clip.gotoAndPlay(0); 293 | 294 | var variableFrameDimensions:Boolean = fileModel.selectedItem.variableFrameDimensions; 295 | var reuseFrames:Boolean = fileModel.selectedItem.reuseFrames; 296 | 297 | if (variableFrameDimensions) { 298 | captureVariableSizeFrames(); 299 | } else { 300 | var _frameBounds:Rectangle = fileModel.selectedItem.frameBounds.clone(); 301 | _frameBounds.inflate(fileModel.selectedItem.exportPadding, fileModel.selectedItem.exportPadding); 302 | 303 | _frameCaptureWidth = _frameBounds.width; 304 | _frameCaptureHeight = _frameBounds.height; 305 | 306 | if (fileModel.selectedItem.maintainPow2) { 307 | _frameCaptureWidth = findNextPower2(_frameCaptureWidth); 308 | _frameCaptureHeight = findNextPower2(_frameCaptureHeight); 309 | } 310 | 311 | handleCaptureFrames(null); 312 | clip.addEventListener(Event.EXIT_FRAME, handleCaptureFrames, false, 0, true); 313 | } 314 | } 315 | 316 | public function createSizeBitmap():void { 317 | findBoundsBmpd = new BitmapData(MAX_WIDTH,MAX_HEIGHT, true, 0xff000000); 318 | } 319 | 320 | protected function captureVariableSizeFrames():void { 321 | var bounds:Rectangle = clip.getBounds(swf); 322 | 323 | stage = _startSwf.stage; 324 | 325 | handleVariableCaptureFrames(null); 326 | clip.addEventListener(Event.EXIT_FRAME, handleVariableCaptureFrames, false, 0, true); 327 | } 328 | 329 | public function getCurrentFrameBounds():Rectangle { 330 | if (!findBoundsBmpd) { 331 | createSizeBitmap(); 332 | } 333 | findBoundsBmpd.fillRect(findBoundsBmpd.rect, 0xFFFFFF); 334 | findBoundsBmpd.draw(swf, null, findBoundsColorTransform); 335 | var frame:Rectangle = findBoundsBmpd.getColorBoundsRect(0xFFFFFF, boundsColorTint, false); 336 | return frame; 337 | } 338 | 339 | protected function handleVariableCaptureFrames(event:Event):void { 340 | var frame:Rectangle = getCurrentFrameBounds(); 341 | frame.inflate(fileModel.selectedItem.exportPadding, fileModel.selectedItem.exportPadding); 342 | 343 | var scale:Number = fileModel.selectedItem.scale; 344 | frame.x *= scale; 345 | frame.y *= scale; 346 | frame.width *= scale; 347 | frame.height *= scale; 348 | 349 | captureBounds[currentCaptureFrame] = frame; 350 | 351 | var row:Number = currentCaptureFrame / columnCount | 0; 352 | var col:Number = currentCaptureFrame % columnCount | 0; 353 | 354 | var frameX:Number = (col * frame.width)-frame.width; 355 | var frameY:Number = row * frame.height; 356 | 357 | var rect:Rectangle = new Rectangle(frame.x, frame.y, frame.width, frame.height); 358 | 359 | if (rect.width == 0) { 360 | rect = new Rectangle(frame.x, frame.y, 1, 1); 361 | } 362 | 363 | //Capture just one frame here, we piece it together at the end. 364 | var mtx2:Matrix = new Matrix(); 365 | mtx2.scale(scale, scale); 366 | mtx2.translate(-rect.x, -rect.y); 367 | 368 | var singleFrame:BitmapData = new BitmapData(rect.width, rect.height, true, 0xff0000); 369 | singleFrame.draw(swf, mtx2, null,null, new Rectangle(0,0, rect.width, rect.height),true); 370 | var label:String = getLabel(currentCaptureFrame); 371 | 372 | var frameData:FrameData = new FrameData(singleFrame, currentCaptureFrame, label); 373 | frameData.registrationPoint = getRegistrationPoint(); 374 | bitmaps.push(frameData); 375 | 376 | currentCaptureFrame++; 377 | 378 | if (currentCaptureFrame == this.frameCount) { 379 | _startSwf.stage.frameRate = startFrameRate; 380 | clip.removeEventListener(Event.EXIT_FRAME, handleVariableCaptureFrames); 381 | finishCapture(); 382 | } 383 | } 384 | 385 | protected function getLabel(index:uint):String { 386 | // Always reset the labels when 0 is requested (probably a new swf) 387 | if (index == 0) { 388 | currentLabels = new Vector.(); 389 | } 390 | 391 | var i:uint, l:uint; 392 | 393 | // Normalize the currentLabels array 394 | // Sometimes 0/1 are the same and the last 2 frames can be the same. 395 | // This uses an 1 based index. 396 | l = clip.currentLabels.length; 397 | for (i=0;i(); 421 | rectLookup = new Dictionary(); 422 | 423 | var l:uint = captureBounds.length; 424 | for (var i:uint=0; i { 443 | getLabel(0); 444 | var states:Vector. = new Vector.(); 445 | var l:uint = currentLabels.length; 446 | var stateHash:Object = {}; 447 | var count:Number = 0; 448 | 449 | for (var i:uint=0;i= value) { 481 | break; 482 | } 483 | } 484 | return pow; 485 | } 486 | 487 | /** 488 | * @private 489 | * 490 | */ 491 | protected function handleCaptureFrames(event:Event):void { 492 | var _frameBounds:Rectangle = fileModel.selectedItem.frameBounds.clone(); 493 | _frameBounds.inflate(fileModel.selectedItem.exportPadding, fileModel.selectedItem.exportPadding); 494 | var scale:Number = fileModel.selectedItem.scale; 495 | 496 | var rect:Rectangle = new Rectangle(0, 0, _frameCaptureWidth, _frameCaptureHeight); 497 | 498 | //Capture just one frame here, we peice it together at the end. 499 | var mtx:Matrix = new Matrix(); 500 | mtx.scale(scale, scale); 501 | mtx.translate(-_frameBounds.x, -_frameBounds.y); 502 | 503 | var singleFrame:BitmapData = new BitmapData(rect.width, rect.height, true, 0xff0000); 504 | singleFrame.draw(swf, mtx, null, null, rect, true); 505 | 506 | var frameData:FrameData = new FrameData(singleFrame,currentCaptureFrame, getLabel(currentCaptureFrame)); 507 | frameData.registrationPoint = getRegistrationPoint(); 508 | bitmaps.push(frameData); 509 | 510 | captureBounds[currentCaptureFrame] = rect; 511 | 512 | if (++currentCaptureFrame == frameCount) { 513 | finishCapture(); 514 | } 515 | } 516 | 517 | protected function getRegistrationPoint():Point { 518 | var registrationPointClip:DisplayObject = clip.getChildByName('registrationPoint'); 519 | 520 | if (registrationPointClip) { 521 | registrationPointClip.visible = false; 522 | return new Point(registrationPointClip.x, registrationPointClip.y); 523 | } else { 524 | return zeroRegistrationPoint; 525 | } 526 | } 527 | 528 | /** 529 | * @private 530 | * 531 | */ 532 | protected function finishCapture():void { 533 | clip.removeEventListener(Event.EXIT_FRAME, handleCaptureFrames); 534 | _startSwf.stage.frameRate = startFrameRate; 535 | 536 | var fs:FileStream = new FileStream(); 537 | var saveFile:File; 538 | 539 | var i:uint; 540 | var l:uint; 541 | var rect:Rectangle; 542 | var point:Point; 543 | var matrix:Matrix; 544 | var captureBmd:BitmapData; 545 | var frameData:FrameData; 546 | var result:Object; 547 | 548 | var exportBitmaps:Array = []; 549 | var requestedWidth:Number = fileModel.selectedItem.bitmapWidth; 550 | var requestedHeight:Number = fileModel.selectedItem.bitmapHeight; 551 | var maintainPow2:Boolean = fileModel.selectedItem.maintainPow2; 552 | 553 | exportedImageNames = []; 554 | 555 | //Reuse frames. 556 | //This will drop bitmaps, and update the bitmaps array. 557 | if (fileModel.selectedItem.reuseFrames && fileModel.selectedItem.threshold > 0) { 558 | compareBitmaps(); 559 | isComplex = true; 560 | 561 | //Update our rects list for the packer code. 562 | l = bitmaps.length; 563 | rects = new Vector.(); 564 | rectLookup = new Dictionary(); 565 | for (i=0;i(l); 604 | pointLookup = new Dictionary(); 605 | 606 | sheetWidth = 0; 607 | sheetHeight = 0; 608 | 609 | for(i=0;i= requestedWidth) { 628 | currY += rect.height; 629 | currX = 0; 630 | } 631 | } 632 | } 633 | 634 | //Update bitmaps array with correct index's 635 | l = bitmaps.length; 636 | var actualIndex:uint = 0; 637 | for (i=0;i requestedHeight) { 671 | exportSheet = new BitmapData(requestedWidth, requestedHeight, true, 0xffffff); 672 | currentBitmapData = {bmpd:exportSheet, w:0, h:0}; 673 | exportBitmaps.push(currentBitmapData); 674 | pointYOffset += requestedHeight; 675 | point.y = startPointY - pointYOffset; 676 | } 677 | 678 | if (point.y < 0) { 679 | pointYOffset += point.y; 680 | point.y = 0; 681 | } 682 | 683 | frameData.sheetIndex = exportBitmaps.length-1; 684 | 685 | matrix = new Matrix(); 686 | matrix.translate(point.x, point.y); 687 | 688 | if (overPaint) { 689 | var scaledBitmap:BitmapData = new BitmapData(bmpd.width+sf, bmpd.height+sf, false); 690 | rect = new Rectangle(point.x, point.y, bmpd.width+sf, bmpd.height+sf); 691 | 692 | var scaleMatrix:Matrix = new Matrix(); 693 | scaleMatrix.scale(1+(sf/bmpd.width), 1+(sf/bmpd.height)); 694 | 695 | var offsetMatrix:Matrix = new Matrix(); 696 | offsetMatrix.translate(1, 1); 697 | 698 | //Draw our scaled bitmap first. 699 | scaledBitmap.draw(bmpd, scaleMatrix); 700 | 701 | // Draw the unscaled bitmap overtop, offet by 1px 702 | scaledBitmap.draw(bmpd, offsetMatrix); 703 | 704 | bmpd = scaledBitmap; 705 | } else { 706 | rect = new Rectangle(point.x, point.y, bmpd.width, bmpd.height); 707 | } 708 | 709 | currentBitmapData.w = Math.max(currentBitmapData.w, point.x + rect.width); 710 | currentBitmapData.h = Math.max(currentBitmapData.h, point.y + rect.height); 711 | 712 | exportSheet.draw(bmpd, matrix, null, null, rect, true); 713 | } 714 | 715 | l = exportBitmaps.length; 716 | for (i=0;i1?'_'+i:'') + '.png'; 718 | exportedImageNames.push(fileName); 719 | var realWidth:Number = exportBitmaps[i].w; 720 | var realHeight:Number = exportBitmaps[i].h; 721 | bmpd = exportBitmaps[i].bmpd; 722 | 723 | //Size the bitmap to a pow(2). 724 | //Doesn't work if we don't export all the frames (with correct positions); 725 | if (maintainPow2) { 726 | var newW:Number = findNextPower2(realWidth); 727 | var newH:Number = findNextPower2(realHeight); 728 | 729 | var tmpBitmap:BitmapData = new BitmapData(newW, newH, true, 0xffffff); 730 | if (overPaint) { 731 | tmpBitmap.copyPixels(bmpd,new Rectangle(0,0,realWidth,realHeight), new Point(-sf*.5, -sf*.5)); 732 | } else { 733 | tmpBitmap.copyPixels(bmpd,new Rectangle(0,0,realWidth,realHeight), new Point()); 734 | } 735 | 736 | bmpd = tmpBitmap; 737 | (exportBitmaps[i].bmpd as BitmapData).dispose(); 738 | } 739 | 740 | saved = saveImage(fileModel.selectedItem.destinationPath + '/'+fileName, bmpd); 741 | 742 | bmpd.dispose(); 743 | 744 | //An error happened during export ... user already has been notifyed, so ignore and move on. 745 | if (!saved) { return; } 746 | } 747 | } 748 | 749 | isComplex = fileModel.selectedItem.variableFrameDimensions || fileModel.selectedItem.reuseFrames || fileModel.selectedItem.imageExportType == ExportType.IMAGE_FRAME; 750 | 751 | //Export other data 752 | if (fileModel.selectedItem.imageExportType == ExportType.IMAGE_FRAME) { 753 | l = bitmapList.length; 754 | for (i=0;i = getStates(); 799 | var statesCount:uint = states.length; 800 | var animations:Object = {}; 801 | var padding:uint = fileModel.selectedItem.exportPadding; 802 | 803 | var origRect:Rectangle = fileModel.selectedItem.frameBounds.clone(); 804 | origRect.inflate(fileModel.selectedItem.exportPadding, fileModel.selectedItem.exportPadding); 805 | 806 | var framesDroppedCount:uint = 0; 807 | 808 | l = bitmaps.length; 809 | 810 | if (isComplex || fileModel.selectedItem.maintainPow2) { 811 | //Build the frames array. 812 | for (i=0;i 0) { 875 | animationDef.speed = state.speed; 876 | } 877 | animations[state.name] = animationDef; 878 | } 879 | } else { 880 | var frameBounds:Rectangle = fileModel.selectedItem.frameBounds.clone(); 881 | frameBounds.inflate(fileModel.selectedItem.exportPadding, fileModel.selectedItem.exportPadding); 882 | var registrationPoint:Point = (bitmaps[0] as FrameData).registrationPoint; 883 | 884 | frames = { 885 | width:frameBounds.width, 886 | height:frameBounds.height, 887 | regX:(registrationPoint) ? registrationPoint.x: 0, 888 | regY:(registrationPoint) ? registrationPoint.y: 0, 889 | count:frameCount 890 | }; 891 | 892 | for(i=0;i startIndex) { 1014 | // Minus 2 because Flash has 1 based frames + The frame labels always report as +1 off. 1015 | index = frame.frame-2; 1016 | break; 1017 | } 1018 | } 1019 | 1020 | // Check the previous frame, if its empty; index--; 1021 | if (index > 0) { 1022 | clip.gotoAndStop(frame.frame-1); 1023 | var regPoint:DisplayObject = clip.getChildByName('registrationPoint'); 1024 | if (clip.numChildren == 0 || (regPoint != null && clip.numChildren == 1)) { 1025 | return index-1; 1026 | } 1027 | } 1028 | 1029 | if (isNaN(index)) { 1030 | return frameCount; 1031 | } else if (index == -1) { 1032 | return 0; 1033 | } else { 1034 | return index; 1035 | } 1036 | } 1037 | 1038 | /** 1039 | * @private 1040 | * 1041 | */ 1042 | protected function compareBitmaps():void { 1043 | for (var i:Number=0; i(l); 1091 | pointLookup = new Dictionary(); 1092 | 1093 | var ttlW:Number = 0; 1094 | var ttlH:Number = 0; 1095 | for (var i:uint=0; i w) { 1112 | // see if we can fit anything else in: 1113 | var j:int = rects.length - 1; 1114 | while (j-- > 0) { 1115 | var rect2:Rectangle = rects[j]; 1116 | if (rx+rect2.width <= w) { 1117 | // this fits. 1118 | p = new Point(rx,ry); 1119 | positions[rectLookup[rect2]] = p; 1120 | pointLookup[p] = rect2; 1121 | rx += rect2.width; 1122 | rects.splice(j,1); 1123 | } 1124 | } 1125 | 1126 | if (rx + rect.width > maxW) { 1127 | maxW = rx; 1128 | } 1129 | 1130 | rx = 0; 1131 | ry += h; 1132 | h = rect.height; 1133 | if (ry+h > maxH) { 1134 | maxH = ry + h; 1135 | } 1136 | } 1137 | 1138 | p = new Point(rx,ry); 1139 | positions[rectLookup[rect]] = p; 1140 | pointLookup[p] = rect; 1141 | rx += rect.width; 1142 | } 1143 | 1144 | sheetWidth = maxW; 1145 | sheetHeight = maxH; 1146 | } 1147 | } 1148 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/utils/DottedLine.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Zoë by gskinner.com. 3 | * Visit www.gskinner.com/blog for documentation, updates and more free code. 4 | * 5 | * Copyright (c) 2010 Grant Skinner 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | 30 | package com.gskinner.zoe.utils { 31 | 32 | import flash.display.BitmapData; 33 | import flash.display.Graphics; 34 | import flash.display.Sprite; 35 | import flash.geom.Matrix; 36 | import flash.geom.Rectangle; 37 | 38 | /** 39 | * Utility class used to create a dotted line. 40 | * Used to show padding when creating sprite sheet. 41 | */ 42 | 43 | public class DottedLine extends Sprite { 44 | 45 | /** 46 | * @private 47 | * 48 | */ 49 | protected var pattern:Array; 50 | 51 | /** 52 | * @private 53 | * 54 | */ 55 | protected var colors:Array; 56 | 57 | /** 58 | * @private 59 | * 60 | */ 61 | protected var _x:Number = 0; 62 | 63 | /** 64 | * @private 65 | * 66 | */ 67 | protected var bmpd:BitmapData; 68 | 69 | /** 70 | * @private 71 | * 72 | */ 73 | protected var _padding:Number = 0; 74 | 75 | /** 76 | * @private 77 | * 78 | */ 79 | protected var _area:Rectangle; 80 | 81 | /** 82 | * @private 83 | * 84 | */ 85 | protected var patternLength:Number = 0; 86 | 87 | /** 88 | * Draws a rectangle with a dotted line. 89 | * 90 | */ 91 | public function DottedLine() { 92 | pattern = [4,4]; 93 | colors = [0xFF000000, 0x0000FF00]; 94 | 95 | createLineStyle(); 96 | } 97 | 98 | /** 99 | * Redraws the view. 100 | * 101 | */ 102 | public function update(area:Rectangle, padding:Number):void { 103 | _padding = padding+2; 104 | _area = area; 105 | drawLine(); 106 | } 107 | 108 | /** 109 | * @private 110 | * 111 | */ 112 | protected function createLineStyle():void { 113 | var l:Number = pattern.length; 114 | patternLength = 0; 115 | for (var i:Number = 0; i < l; i++) { 116 | patternLength += pattern[i]; 117 | } 118 | 119 | bmpd = new BitmapData(patternLength,1,true,0x000000); 120 | 121 | for (i=0; i 1) { 142 | swf.addEventListener(Event.EXIT_FRAME, handleFindBounds, false, 0, false); 143 | } 144 | } 145 | 146 | /** 147 | * Returns the bounds found by this class. 148 | * You need to call findBounds(); first. 149 | * 150 | */ 151 | public function get bounds():Rectangle { 152 | if (_bounds == null) { 153 | throw new new IllegalOperationError('No bounds found, call findBounds() first.'); 154 | } 155 | return _bounds; 156 | } 157 | 158 | /** 159 | * @private 160 | * 161 | */ 162 | protected function handleFindBounds(event:Event):void { 163 | findBoundsBmpd.draw(swf, null, findBoundsColorTransform); 164 | if (_frameCount == ++count) { 165 | stage.frameRate = startFrameRate; 166 | swf.removeEventListener(Event.EXIT_FRAME, handleFindBounds); 167 | 168 | _bounds = findBoundsBmpd.getColorBoundsRect(0xFFFFFF, boundsColorTint, false); 169 | 170 | findBoundsBmpd.dispose(); 171 | 172 | dispatchEvent(new Event(Event.COMPLETE)); 173 | } 174 | } 175 | } 176 | } -------------------------------------------------------------------------------- /src/com/gskinner/zoe/views/CapturePreview.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 30 | 35 | 40 | 41 | 42 | x && mouseY < y + h && mouseY > y) { 618 | return true; 619 | } else { 620 | return false; 621 | } 622 | } 623 | 624 | /** 625 | * @private 626 | * 627 | */ 628 | protected function cursorInResizeBounds():Boolean { 629 | if (_captureBounds == null) { return false; } 630 | 631 | var x:Number = _captureBounds.x; 632 | var y:Number = _captureBounds.y; 633 | var w:Number = _captureBounds.width; 634 | var h:Number = _captureBounds.height; 635 | 636 | if (mouseX < x + w && mouseX > w+x - 10 637 | && mouseY < y + h && mouseY > h+y - 10 638 | ) { 639 | return true; 640 | } else { 641 | return false; 642 | } 643 | } 644 | 645 | /** 646 | * @private 647 | * 648 | */ 649 | protected function handleSwfLoad():void { 650 | if (swfLoader.content is AVM1Movie) { 651 | Alert.show('Your SWF is not supported. Please use a swf that is compiled using Player 9 or greater and the language version is AS3.', 'Unsupported SWF'); 652 | fileModel.deleteSelected(); 653 | return; 654 | } 655 | 656 | if (!(swfLoader.content is MovieClip)) { 657 | Alert.show('Your SWF is not supported, please ensure target is a MovieClip.', 'Unsupported SWF'); 658 | fileModel.deleteSelected(); 659 | return; 660 | } 661 | 662 | if (content == null) { return; } 663 | 664 | updateRegPoint(); 665 | 666 | dispatchEvent(new CaptureEvent(CaptureEvent.SWF_INIT)); 667 | } 668 | 669 | /** 670 | * @private 671 | * 672 | */ 673 | protected function checkBoundary():void { 674 | var rect:Rectangle = this.background.getRect(background); 675 | if (mouseX + tt.actualWidth > rect.right) { 676 | tt.x = rect.right - tt.actualWidth; 677 | } else if (mouseX < rect.left) { 678 | tt.x = rect.left + tt.actualWidth; 679 | } 680 | if (mouseY + tt.actualHeight > (rect.bottom - (tt.actualHeight+5))) { 681 | tt.y = rect.bottom - tt.actualHeight; 682 | } else if (mouseY - tt.actualHeight < rect.top) { 683 | tt.y = rect.top + tt.actualHeight; 684 | } 685 | } 686 | 687 | /** 688 | * @private 689 | * 690 | */ 691 | public function updateRegPoint():void { 692 | if (!content || !regPtClipContainer) { 693 | return; 694 | } 695 | 696 | var registrationPointClip:DisplayObject = content.getChildByName('registrationPoint'); 697 | 698 | if (registrationPointClip) { 699 | registrationPointClip.visible = false; 700 | var registrationPoint:Point = new Point(registrationPointClip.x, registrationPointClip.y); 701 | 702 | regPtClipContainer.x = registrationPoint.x; 703 | regPtClipContainer.y = registrationPoint.y; 704 | } 705 | } 706 | 707 | /** 708 | * @private 709 | * 710 | */ 711 | protected function handleError():void { 712 | //Surpress 713 | } 714 | 715 | /** 716 | * @private 717 | * 718 | */ 719 | protected function createRegistrationPointSprite():Sprite { 720 | var s:Sprite = new Sprite(); 721 | var g:Graphics = s.graphics; 722 | var radius:Number = 5; 723 | 724 | g.lineStyle(1, 0x666666, 0, true); 725 | g.beginFill(0x000000, 0); 726 | g.drawCircle(0, 0, radius*2); 727 | g.beginFill(0xFFFFFF, 0); 728 | g.drawCircle(0, 0, radius-1); 729 | g.endFill(); 730 | 731 | g.lineStyle(1, 0x666666, 1, true); 732 | g.moveTo(-radius,0); 733 | g.lineTo(radius, 0); 734 | g.moveTo(0, radius); 735 | g.lineTo(0, -radius); 736 | 737 | return s; 738 | } 739 | 740 | protected function handleSwfTick(event:Event):void { 741 | updateRegPoint(); 742 | } 743 | 744 | ]]> 745 | 746 | 747 | 748 | 749 | 750 | 751 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/views/ExportDialog.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 30 | 35 | 42 | 43 | 44 | '+unescapeMultiByte(selItem.destinationPath)+''); 97 | results.push(''); 98 | 99 | //{json:jsonString, startFrames:startFrames, currentFrames:currentFrames, droppedFrames:framesDroppedCount} 100 | if (result) { 101 | results.push("SWF has: " + result.startFrames + ' frames.'); 102 | results.push("Dropped: " + result.droppedFrames + ' similar frames.'); 103 | results.push("Exported: " + result.currentFrames + ' frames.'); 104 | results.push(''); 105 | } 106 | 107 | switch (selItem.imageExportType) { 108 | case ExportType.IMAGE_SPRITE_SHEET: 109 | if (exportedImages.length == 1) { 110 | results.push('Sprite sheet exported as: ' + exportedImages[0]); 111 | } else { 112 | results.push('Multiple sprite sheets exported\: ' + exportedImages.join('
\t')); 113 | results.push(""); 114 | } 115 | 116 | break; 117 | case ExportType.IMAGE_FRAME: 118 | results.push(model.swfCapture.totalFrames + ' frames were exported'); break; 119 | } 120 | 121 | switch (selItem.dataExportType) { 122 | case ExportType.DATA_JSON: 123 | results.push('JSON exported as: ' + name + '.json'); break; 124 | } 125 | 126 | 127 | var css:StyleSheet = new StyleSheet(); 128 | css.setStyle("a:link", {color:"#0000FF"}); 129 | css.setStyle("a:hover", {color:"#9999FF"}); 130 | 131 | instance.outputText.styleSheet = css; 132 | instance.outputText.htmlText = unescapeMultiByte(results.join('
')); 133 | } 134 | 135 | /** 136 | * @private 137 | * 138 | */ 139 | protected function handelOpenExportFolder():void { 140 | var file:File = new File(model.selectedItem.destinationPath); 141 | file.openWithDefaultApplication(); 142 | } 143 | 144 | /** 145 | * @private 146 | * 147 | */ 148 | protected function handleCloseWindow():void { 149 | PopUpManager.removePopUp(this); 150 | } 151 | 152 | protected function handleResultClick(event:TextEvent):void { 153 | //new File(event.text).openWithDefaultApplication(); 154 | //navigateToURL(new URLRequest(event.text)); 155 | handelOpenExportFolder(); 156 | } 157 | 158 | protected function init(event:FlexEvent):void { 159 | 160 | } 161 | 162 | ]]> 163 |
164 | 165 | 166 | 167 | 168 | 169 | 170 | 172 | 173 | 179 | 180 | 181 | 182 | 183 | 184 | 185 |
186 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/views/PreviewPanel.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 30 | 35 | 39 | 40 | 41 | 175 | 176 | 177 | 178 | 179 | 180 | 184 | 185 | 189 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /src/com/gskinner/zoe/views/ProgressOverlay.mxml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 30 | 35 | 40 | 41 | 42 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /src/data/version.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | http://www.gskinner.com/apps/zoe/version.xml 4 | 1 5 | -------------------------------------------------------------------------------- /src/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/icons/128x128.png -------------------------------------------------------------------------------- /src/icons/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/icons/16x16.png -------------------------------------------------------------------------------- /src/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/icons/32x32.png -------------------------------------------------------------------------------- /src/icons/48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CreateJS/Zoe/2117fb58d025fafb345f2a4fc9eb5562003dc837/src/icons/48x48.png --------------------------------------------------------------------------------