Archive for the 'Flash' Category
Flash Player Security Settings Page Problems
Just in case anyone else is experiencing this. I noticed that the flash player security setting page was not working. Either the swf would not show up on the page, or it wouldn’t save settings you add to it.
I’m not entirely sure why this is happening, in terms of what’s going on with the domains / macromedia.com.
If you go here: http://macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html,you’ll see that either the swf doesn’t show, or it doesn’t save anything.
It’s missing the “www” in the URL, so go here: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html, and it will work.
2 commentsGuttershark Service Manager: SOAP
Ok folks, here’s how you can hook up soap with guttershark.
Here’s a main class: (there are a couple things I explain next)
package { public class Main extends Sprite { private var sm:ServiceManager; public function Main() { sm=ServiceManager.gi(); sm.createSOAPService("myWSDL","http://www.example.com/wsdl",3,5000); callSoap(); } public function callSoap() { sm.myWSDL.someMethod({ params:{someParameter:"hello world"}, resultHandlerClass:MySoapResultHandler, onResult:onSoapResult, onFault:onSoapFault, onFirstCall:onFirstCall, onMethodNotAvailable:onMethodNotAvailable, }); } public function onFirstCall():void { trace("trying soap service"); showLoader(); } public function onSoapFault(sf:SoapFault):void { trace("fault"); } public function onSoapResult(sr:SoapResult):void { trace("result"); trace(sr.raw); trace(sr.handler); //instance of resultHandlerClass. } public function onMethodNotAvailable():void { trace("method was not available on wsdl"); } } }
When you create a soap service (createSOAPService), the service manager downloads your WSDL and parses it out. It stores some information that you can get at runtime. For example, if you wanted to list out the supported methods on this wsdl:
sm.myWSDL.listMethods();
That’s generally all that you need, and that’s only needed in support of debugging.
Generating the Soap Message
The service manager generates the soap message to send to the server based off of the params object you give it. In the above code example, it’s going to generate a soap message that looks like this:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <someMethod xmlns="http://webservicelocation/"> <someParameter>hello world</someParameter> </someMethod> </soap:Body> </soap:Envelope>
Handling the Result
The service manager requires you to give it a “result handler class.” This handler class gives you a hook to handle the soap result, before it’s handed off to your callbacks.
In the above example, there is this line (part of call props):
resultHandlerClass:MySoapResultHandler,
“MySoapResultHandler” needs to be a class that you create, to handle the result. Here’s that class:
package { import net.guttershark.support.servicemanager.soap.SoapFaultError; import net.guttershark.support.servicemanager.soap.SoapResultHandler; public class MySoapResultHandler extends SoapResultHandler { public var somePropertyOnTheResult; override protected function process():void { super.process(); super.setNamespace(); super.setBody(); super.setFault(); //if it get's passed this its an ok result. if(soapFault) throw new SoapFaultError(soapFault); somePropertyOnTheResult = soapBody.someResult.toString(); } } }
The reason we create this soap result handler class is to delegate processing of the result XML into this class, and abstract it out of your application and the service manager.
There’s one thing to note that’s special about the SoapResultHandler, if you throw a “SoapFaultErorr”, anywhere from the process method, it will be raised back up through the service manager, and trigger your “onFault” callback.
So, in the above handler class, if “soapFault” is set, it throws an error - as mentioned this will ultimately trigger your onFault callback.
Now let’s take a look at an updated “onResult” callback function from the Main class, to do something with our handler:
public function onSoapResult(sr:SoapResult):void { trace("result"); trace(sr.raw); //raw soap xml response. trace(sr.handler); //this is the instance of your result handler - an instance of MySoapResultHandler. trace(sr.handler.somePropertyOnTheResult); }
After the service manager processes your soap result handler, it calls your onResult handler. There’s a property on the SoapResult class called “handler”, which will be an instance of your handler class.
The service manager uses your handler class as a middle man so you can do what you want with the result - before it’s passed on. Hopefully you can see how nice this is. It keeps everything abstract from your application, and allows you to just focus on business logic. And also not clutter the methods that do all the work with a result.
Generally, for every soap method you’re going to call, you create a soap handler class. Each soap handler class can process the result specifically for that method call.
Other things to note
There’s one additional property you can set on a service call “showSoapRequest”:
sm.myWSDL.someMethod({ params:{someParameter:"hello world"}, resultHandlerClass:MySoapResultHandler, onResult:onSoapResult, onFault:onSoapFault, onFirstCall:onFirstCall, onMethodNotAvailable:onMethodNotAvailable, showSoapRequest:true, // });
This option will trace the generated soap request that’s being sent to the server.
Integrating Soap With The Model
Here’s a model file:
<xml version="1.0" encoding="utf-8"> <model> <services> <service id="mySoapService" wsdl="mySoapServiceWSDL" attempts="3" timeout="5000" /> <wsdl id="mySoapServiceWSDL" endpoint="http://www.example.com/wsdl" /> </services> </model>
And here’s the update class file:
package { import net.guttershark.control.DocumentController; public class Main extends DocumentController { override protected function flashvarsForStandalone():Object { return { model:"model.xml", initServices:true, } } override protected function setupComplete():void { callSoap(); } public function callSoap() { sm.myWSDL.someMethod({ params:{someParameter:"hello world"}, resultHandlerClass:MySoapResultHandler, onResult:onSoapResult, onFault:onSoapFault, onFirstCall:onFirstCall, onMethodNotAvailable:onMethodNotAvailable, showSoapRequest:true, }); } public function onFirstCall():void { trace("trying soap service"); showLoader(); } public function onSoapFault(sf:SoapFault):void { trace("fault"); } public function onSoapResult(sr:SoapResult):void { trace("result"); trace(sr.raw); trace(sr.handler); //instance of resultHandlerClass. trace(sr.handler.somePropertyOnTheResult); } public function onMethodNotAvailable():void { trace("method was not available on wsdl"); } } }
Crossdomain Issues
With SOAP, Flash has to send over a header called “SOAPAction”, so you’re crossdomains need to allow headers for this.
Conclusion
Soap services are greatly simplified with guttershark - which allows you to focus on business logic of you’re application. Additionally, I hate wasting time on code that’s already been written, don’t you?
Additionally, you should read through the source of the classes that support SOAP functionality. They are in “net.guttershark.support.servicemanager.soap.”
6 commentsFont Libraries with Guttershark
Another key thing when working with Flash is fonts. It can be somewhat intimidating as the documentation for using font library symbols doesn’t make anything obvious. It takes a bit of reading and messing around to get it right.
If you do some snooping around on google, there are quite a few articles that outline the basics of using embedded fonts, or font libraries. I’ll take you beyond what the basics are, and show you how to integrate font libraries with guttershark.
First things first, let’s look at the model file for loading fonts:
<model> <assets> <asset libraryName="fonts" src="fonts.swf" preload="true" /> </assets> <fonts> <font libraryName="LucidaGrandeBold" /> <font libraryName="LucidaGrandeRegular" /> </fonts> </model>
This model file defines an asset to load, which is a swf that contains our fonts. And it declares two fonts that need to be registered with Flash’s Font.registerFont method.
Now let’s look at the first pass of a document controller:
package { import flash.text.TextFormat; import flash.text.TextField; import flash.events.Event; import net.guttershark.control.PreloadController; import net.guttershark.control.DocumentController; public class Main extends DocumentController { override protected function flashvarsForStandalone():Object { return {model:"model.xml"}; } override protected function setupComplete():void { pc=new PreloadController(); pc.addItems(ml.getAssetsForPreload()); pc.addEventListener(Event.COMPLETE,onComplete); pc.start(); } private function onComplete(e:Event):void { //this registers every font that is declared in model XML. ml.registerFonts(); } } }
This document controller set’s up the bare minimum to get fonts loaded in and registered. From there, we’re ready to start using embedded fonts on text fields with text formats, or stylesheets.
Before we do that, let’s take a look at some some key methods that guttershark has for getting and setting stylesheets or text formats, and i’ll explain what they do internally.
Two key methods:
- Model#getTextFormatById() - Model#getStyleSheetById()
The most important thing that these two methods do is automatically resolve fonts to their “proper name”. A proper name is the name of a font instance - the “fontName” property of a Font instance.
Here’s an addition to the model for a textformat:
... <textformats> <textformat id="labelText" font="LucidaGrandeBold" size="14" /> </textformats> ...
In this example, the “font=LucidaGrandeBold” indicates that the font to use is the font “LucidaGrandeBold” which in turn is the “export for actionscript” name in the fonts swf. Internally, the getTextFormatById method retrieves an instance of this font object, and assigns the “font” property of a textformat with “font.fontName”.
Here’s some psuedo code to show what this method does:
function getTextFormatById(id:String):TextFormat { finalTextFormat = new TextFormat(); tfNode = getXMLNodeByID; fontName = tfNode.@font; fontClass = getFontFromLibrary(fontName); Font.registerFont(fontClass); fontInstance = fontClass(); finaltextFormat.font = fontInstance.fontName; //KEY //apply other node attribtues to textFormat (bold, size, etc) return finalTextFormat; }
Simple right? Now let’s make an addition in the model for stylesheets:
... <stylesheets> <stylesheet id="example"> <![CDATA[ .body{ font:LucidaGrandeRegular; fontSize:10; } ]]> </stylesheet> </stylesheets> ...
Gutteshark supports a custom css property “font”, which indicates to guttershark that it should look up that font, and get the right “proper name” for that font, and use it as the “fontFamily” property.
Here’s some psuedo code for this method:
function getStyleSheetById(id:String):StyleSheet { styleSheet = getStyleSheetNodeFromXML; styleSheet = CSS.parseCSS(styleSheet.toString()); styleNames = styleSheet.styleNames; var finalFontFamily:String; l = styleNames.length; i = 0; for(i;i<l;i++) { style = styleSheet.getStyle(styleNames[i]) for(key in style) { if(key=="font") { fontClass = AssetManager.gi().getClass(style[key]); Font.registerFont(fontClass); fontInstance = fontClass(); finalFontFamily = fontInstance.fontName; delete style[key]; } } if(finalFontFamily) style['fontFamily'] = finalFontFamily; //KEY styleSheet.setStyle(styleNames[i],style); //update final style } return styleSheet; }
Fairly simple right?
The benefit of all this is that you no longer need to write exhaustive code for every text field, and with the help of some shortcuts, we can setup up embedded text fields into a few lines of code.
Here’s an example of the work required for setting up text formats for each text field, without the help of guttershark:
var fc:FontClass = AssetManager.gi().getClass("MyFontLibraryName"); Font.registerFont(fc); var fi:Font = fc(); var tf:TextFormat = new TextFormat(); tf.font = fi.fontName; //set other textFormat properties var tfield:TextField = myTFOnTheStage; tfield.embedFonts = true; tfield.defaultTextFormat = tf; tfield.text = "Hello World";
Here’s an example with guttershark’s help:
var tf:TextFormat = ml.getTextFormatById("example"); var tfield:TextField = myTextFieldOnTheStage; utils.text.textFormat(tfield,tf); tfield.text = "Hello World";
Much cleaner.
Ok, so let’s put some of this together with a real example. Here’s the final model xml file:
<?xml version="1.0" encoding="utf-8"?> <model> <assets> <asset libraryName="fonts" src="fonts.swf" preload="true" /> </assets> <fonts> <font libraryName="LucidaGrandeBold" /> <font libraryName="LucidaGrandeRegular" /> </fonts> <textformats> <textformat id="labelText" font="LucidaGrandeBold" size="14" /> <textformat id="lucidaGBold10" font="LucidaGrandeBold" size="10" bold="true" /> <textformat id="lucidaGBold12" font="LucidaGrandeBold" size="12" bold="true" /> <textformat id="lucidaGRegular10" font="LucidaGrandeRegular" size="10" /> <textformat id="lucidaGRegular12" font="LucidaGrandeRegular" size="12" /> </textformats> <stylesheets> <stylesheet id="example"> <![CDATA[ .body{ font:LucidaGrandeRegular; fontSize:10; } ]]> </stylesheet> <stylesheet id="example2"> <![CDATA[ .body{ font:LucidaGrandeRegular; fontSize:10; } .bold{ font:LucidaGrandeBold; fontWeight:bold; fontSize:14; color:#FF0066; } ]]> </stylesheet> </stylesheets> </model>
And here’s the final document controller:
package { import flash.text.TextFormat; import flash.text.TextField; import flash.events.Event; import net.guttershark.control.PreloadController; import net.guttershark.control.DocumentController; public class Main extends DocumentController { //bunch of fields on stage.. public var stylesheetsLabel:TextField; public var textFormatsLabel:TextField; public var txf1:TextField; public var txf2:TextField; public var txf3:TextField; public var txf4:TextField; public var txf5:TextField; public var txf6:TextField; public var txf7:TextField; public var ss1:TextField; public var ss2:TextField; public var ss3:TextField; public var ss4:TextField; public var ss5:TextField; public var ss6:TextField; public var ss7:TextField; override protected function flashvarsForStandalone():Object { return {model:"model.xml"}; } override protected function setupComplete():void { pc=new PreloadController(); pc.addItems(ml.getAssetsForPreload()); pc.addEventListener(Event.COMPLETE,onComplete); pc.start(); } private function onComplete(e:Event):void { //this registers every font that is declared in XML. ml.registerFonts(); //set up the labels. var labelTF:TextFormat = ml.getTextFormatById("labelText"); stylesheetsLabel.embedFonts=true; stylesheetsLabel.setTextFormat(labelTF); textFormatsLabel.embedFonts=true; textFormatsLabel.setTextFormat(labelTF); //TEXTFIELDS txf1.embedFonts=true; txf1.setTextFormat(ml.getTextFormatById("lucidaGBold10")); txf2.embedFonts=true; txf2.setTextFormat(ml.getTextFormatById("lucidaGBold12")); //use shortcuts for other textformats. utils.text.textFormat(txf3,ml.getTextFormatById("lucidaGRegular10")); utils.text.textFormat(txf4,ml.getTextFormatById("lucidaGRegular12")); //another shortcut type. utils.setters.textFormat(ml.getTextFormatById("lucidaGRegular10"),txf5,txf6,txf7); //STYLESHEETS ss1.embedFonts=true; ss1.styleSheet=ml.getStyleSheetById("example"); ss1.htmlText="<span class=\"body\">"+ss1.text+"</span>"; ss2.embedFonts=true; ss2.styleSheet=ml.getStyleSheetById("example2"); ss2.htmlText="<span class=\"body\">"+ss2.text+"<span class=\"bold\">. and this is bold.</span></span>"; //stylsheet shortcuts utils.text.styleSheet(ss3,ml.getStyleSheetById("example")); ss3.htmlText="<span class=\"body\">"+ss3.text+"</span>"; utils.text.styleSheet(ss4,ml.getStyleSheetById("example")); ss4.htmlText="<span class=\"body\">"+ss4.text+"</span>"; //another shortcut type utils.setters.stylesheet(ml.getStyleSheetById("example"),ss5,ss6,ss7); ss5.htmlText="<span class=\"body\">"+ss5.text+"</span>"; ss6.htmlText="<span class=\"body\">"+ss6.text+"</span>"; ss7.htmlText="<span class=\"body\">"+ss7.text+"</span>"; } } }
This example uses some other great shortcuts for preparing text fields for stylesheets, or text formats:
- utils.text.textFormat - utils.text.textWithTextFormat - utils.text.textWithTextFormatFromLocaleString - utils.text.textWithFormattingFromXML - utils.text.styleSheet - utils.setters.textFormat - utils.setters.styleSheet
I’m not going to explain all of those, I’d recommend reading the source for those methods. As well as reading the source for the two model methods (getTextFormatById, and getStyleSheetById).
I put this example in the guttershark repository for all. Pull down the latest version, and checkout “examples/other/font_libs/ex1″. You can get the latest version in git.
enjoy.
3 commentsBeing a Successful Development Team in Flash with Application Domains
A somewhat common problem I’ve run into a few times was how to “play nice” with other developers when working on projects that were quite big - and required a team effort. I’ve stumbled across a pretty cool way to build projects. Maybe others are aware of this, but I wasn’t, so maybe this can help you.
What I’m not talking about, is how to write better code so there aren’t any merge problems - or how to get along better. What I’ll explain is how you can alleviate pains with managing FLA files, and which developer can work on which FLA.
Here’s the situation: you have a shell file that loads some shared assets but more than one developer are trying to work in this assets FLA at the same time. You know version control presents a problem so you try to coordinate when and who is allowed to work on the FLA. Does that sound familiar? If not, maybe you’re already doing it right - maybe I can learn something from you.
Let’s think about this problem a little bit more, this is how I broke it down: we need a way to write code linked against some assets - which happen to live in a swf. The swfs will be used for part of a bigger application, but “the bigger application” doesn’t care which swf contains the assets or components.
The answer: write code that makes no assumptions about which swf the assets live in. How can you do that? Application domains. (I don’t really want to take the time to explain application domains - you can look through the livedocs for that.)
I’ll start to paint a very simple picture. We’ll have two final swfs:
main.swf (from main.fla) assets.swf (from assets.swf)
We have two developers on the team:
David, Sam
To start the project out, one developer will need to write some basic startup code, to kick everything off in the main swf. That startup code could do many things, but to keep this simple, let’s assume it just contains some assets for a preloader and the code to kick off the application when the required assets are loaded.
Once you get to that point, you can start to break things up. Here’s what you do: each developer creates his own FLA sandbox for developing components - which will be a work in progress FLA.
So now you have three FLA’s:
assets.fla assets_david.fla assets_sam.fla
This is where application domains, (with or without the help of guttershark) comes in. While your initially building the app, you load all three asset swfs. The model xml file would look like this:
<?xml version="1.0" encoding="utf-8"?> <model> <assets> <asset libraryName="assets" src="assets.swf" preload="true" /> <asset libraryName="assetsDavid" src="assets_david.swf" preload="true" /> <asset libraryName="assetsSam" src="assets_sam.swf" preload="true" /> </assets> </model>
The PreloadController loads in all assets into the same application domain - which means your application code doesn’t need to do any extra work, or extra logic - just to get clips out of the libraries.
As developers are hitting milestones with building components, they can come back to the main application code and fit in their components. Naturally one developer will fall into being the maintainer of the overall application, or architect.
This is what you’ll start to see happen: the architect will be able to work on building the entire application, using the components from the other developers’ sandboxes, and whatever milestones are ready in the main assets swf - without disturbing the other developers, and the other developers won’t conflict with each other.
Can you see how that shapes up? All developers contribute to code, using version control systems to merge your application code together - which is standard. But, while each developer is doing his individual efforts, he builds out components and visual assets in his sandboxed FLA. The architect can use all those pieces, and nobody has to worry about conflicts. Yes!
Each developer will naturally hit milestones with the components he’s building. When this happens, he makes sure it’s clear to merge in his milestone into the final assets swf. Delete those clip assets from his sandbox, and continue.
The cycle is perfect. Now it’s all about individual milestone’s and quick merges vs. merge and conflict resolution at every commit or update because of crappy fla conflicts.
Obviously this is a very basic example, and I have by no means come up with some perfect team model. But I’ve successfully been doing this on one project I’m working on, and let me tell you - we haven’t had any major FLA conflicts, and we haven’t had to plan or even think about who, when, or where someone edits an FLA.
Do you have any experiences with team development? Do you have team techniques that eliminate conflicts with FLA’s? I’d definitely like to hear about them.
3 commentsASDoc Bug
I’ve known about this bug for a while, just forgot to say something. It’s a very miniscule bug, but can be confusing to someone reading documentation generated by asdoc.
Take a look at this method definition:
public function flipProp(prop:String,value1:*,value2:*,...objs:Array):void
Now take a look at the method documentation here.
Notice a difference in the method definitions?
The answer: asdoc documents the method as if it were declared like this:
public function flipProp(prop:String,...value1,value2:*,objs:*):void
Notice that asdoc reverses the order of the (…) rest style parameter, with the objects that are defined as *. The only time it happens is if there are three or more parameters involved in the method. And it only happens when you use rest (…), immediately preceded by a *.
No my docs aren’t wrong. It’s asdoc!
No commentsNew Guttershark Logo
Thanks to Michael Trueman for the new logo! Check out the Guttershark page to see it - it’s awesome!
No commentsFlash CS4 Custom Keyboard Shortcuts Annoyance
I ran into this annoying issue when I was finally setting up my keyboard shortcuts for JSFL’s in Flash CS4. I always use cmd+opt+shift+[...], but unfortunately on a mac, when you throw the option key in the mix, Flash uses the unicode characters that are mapped to whichever key you press. Not all keys on the mac keyboard have a unicode character mapped to them, so for example, cmd+opt+shift+U works fine, but other keys don’t work so hot.
No commentsFlash cs4 text rendering difference
I haven’t been able to figure out why Flash 10 dynamic text seems to over-saturate the text. I’m not sure if that is the correct word, but here is an image to show the difference.
In the image below, the first set of text is Flash 9. The second set of text is Flash 10. In the Flash 10 text, you can see that the dynamic text is much thicker than Flash 10 static text, and much thicker than Flash 9 dynamic text.
Update: I figured out where the difference is important. If you haven’t set any character embedding for a dynamic text field, then you get this weird looking text, as soon as you embed character’s, it’s fixed.
(click image for larger)
If anyone has any idea. Definitely let me know.
4 comments

