Wednesday, December 8, 2010

Flex 4 Simple Button example

 So, I'm a programmer. I like to make reusable bits of code, called objects. These allow me to minimize the busy work I'm doing while building large complicated applications. Adobe, in some kind of pitched fever dream, decided to neuter the programmers ability to make reusable bits of code for visual elements by not providing any new kind of SimpleButton object compatible with skins.

Flex 4 introduced the concept of skins. Skins allow a designer (art people), using some other piece of Adobe software, to affect the look and feel of your buttons and whatnot without you (the programmer) having to get involved. So, as a one man band, if I want to make a button without graphics, I have nothing to worry about. I do not need a custom skin. But if I DO need custom graphics for my buttons, then it seems that Adobe wants me to make a unique skin for every, single, button.

This would add too many files to my project, making it cumbersome to support and maintain. I like the cleaner MVC/Spring Hybrid approach, so I decided to make a reusable simple button object myself. The button will take care of the skinning all by itself , and allow me to specify graphics files on the button object. The first thing I'll define is the button object. I've named it IconButton just to distinguish it from Adobe's SimpleButton. Note the imports, I'm extending spark components in order to be able to reference this in the Flash Builder visual designer, and just to show it can be done ;3.

import flash.display.Bitmap;
import flash.events.MouseEvent;

import spark.components.Button;

public class IconButton extends Button
{
 
    //  We have member variables bitmap classes for the
    //  various skin states, this allows us to specify files from
    // from the Flex 4 Visual Designer file chooser
   
    private var _bitmapUpClass:Class;
   
   
    private var _bitmapDownClass:Class;
   
   
    private var _bitmapOverClass:Class;
   
    // Note that as the classes get assigned we
    // immediatley create an instance of the class
    // for the corresponding bitmaps
   
    [Bindable]
    [Inspectable(category="General", type="Class")]
    public function set bitmapUpClass(value:Class):void{
        _bitmapUpClass = value;
        this.bitmapUp = new _bitmapUpClass();
    }
   
    [Bindable]
    [Inspectable(category="General", type="Class")]
    public function set bitmapDownClass(value:Class):void{
        _bitmapDownClass = value;
        this.bitmapDown = new _bitmapDownClass();
    }
   
    [Bindable]
    [Inspectable(category="General", type="Class")]
    public function set bitmapOverClass(value:Class):void{
        _bitmapOverClass = value;
        this.bitmapOver = new _bitmapOverClass();
    }
   
    private var _bitmapUp:Bitmap;
   
   
    private var _bitmapDown:Bitmap;
   
   
    private var _bitmapOver:Bitmap;
   
    [Bindable]
    public function set bitmapUp(value:Bitmap):void{
        _bitmapUp = value;
    }
   
    [Bindable]
    public function get bitmapUp():Bitmap{
        return _bitmapUp;
    }
   
    [Bindable]
    public function set bitmapDown(value:Bitmap):void{
        _bitmapDown = value;
    }
   
    [Bindable]
    public function get bitmapDown():Bitmap{
        return _bitmapDown;
    }
   
    [Bindable]
    public function set bitmapOver(value:Bitmap):void{
        _bitmapOver = value;
    }
   
    [Bindable]
    public function get bitmapOver():Bitmap{
        return _bitmapOver;
    }
   
    // The constructor, the call to setStyle with our custom
    // skin class is the key take away here
   
    public function IconButton()
    {
        super();
        setStyle("skinClass",com.rory.buttons.IconButtonSkin);
    }
   
}

So not a lot going on here, we take in classes that refer to bitmaps, and as they get assigned we immediately instantiate them and assign them to their corresponding bitmap member variables. We also set the style parameter "skinClass" in the constructor. Next we need to define the considerably more complicated IconButtonSkin class.

import flash.events.Event;

import mx.events.FlexEvent;
import mx.events.StateChangeEvent;
import mx.graphics.BitmapFill;
import mx.states.AddItems;
import mx.states.State;

import spark.primitives.supportClasses.GraphicElement;
import spark.skins.spark.ButtonSkin;

public class IconButtonSkin extends ButtonSkin
{
   
    //This binds the skin to our custom button object - it makes Flex happy
   
    [hostComponent("com.stthomas.edu.buttons.IconButton")]
   
    //This will allow to draw our own specified bitmaps
   
    private var _image:BitmapFill = new BitmapFill();
   
    //This will be our corporeal reference to the IconButton instance this
    //skin is tied to
   
    private var _hostIconButton:IconButton;
   
    //This is a convenience object that will help us disable the stuff we don't
    //want showing up over our lovely bitmaps.
   
    private var _stateToObjects:Object;
   
    //The constructor called by the flex framework when it feels motivated 
    //to do so. Note the listener being added to call creationCompleteListener. 
    //This is a little timing trick that makes the whole thing possible.
   
    public function IconButtonSkin()
    {
        super();         

       this.addEventListener(FlexEvent.CREATION_COMPLETE,creationCompleteListener);
    }
   
    //This is the workhorse of the whole thing.
   
    public function creationCompleteListener(event:Event){
       
        //This will intercept state changes and allow us to display our
        //own bitmaps
       
        addEventListener(StateChangeEvent.CURRENT_STATE_CHANGING, onStateChanging);
       
        //We can reference the button attached to this skin instance by referring
        //to super.hostComponent - the flex framework populated 

        //this for us assumingly with magic
       
        _hostIconButton = hostComponent as IconButton;
       
        //This sets up the initial thing we want to draw on the button, the
        //buttonUp image
       
        var widthOfBitmap:int = _hostIconButton.bitmapUp.width;
        _image.source = _hostIconButton.bitmapUp;
        _image.scaleX = 1.0;
        _image.scaleY = 1.0;
       
        //this populates the appropriately named member variable
       
        populateStateToObject();
       
        //this will strip out all of the layers of the 

        //flex button we currently don't
        //care about - in my real version of the class i have the 

        //option of leaving some of the sheen on that 
        //the default flex button provides (because it looks cool)
       
        setupSimpleButton();
       
        //some math junk that centers stuff
       
        if(widthOfBitmap< fill.width){
            fill.horizontalCenter = (( fill.width - widthOfBitmap)/2);
        }
    }
   
    //every spark object has a group of 'default' top level display elements

    //that get applied to every state, and every state has associated 'extra' 
    //display elements to apply when the spark object is in that specific
    //state. This simply sets all those elements to alpha=0.0 and ours to 1.0
   
    private function setupSimpleButton(){
        for(var prop:Object in _stateToObjects){
            var temp:Array = _stateToObjects[prop] as Array;
            for(var i:int = 0 ; i < temp.length ; i++){
                var element:GraphicElement = temp[i] as GraphicElement;
                element.alpha = 0.0;
            }
        }
        fill.alpha = 1.0;
        fill.fill = _image;
    }
   
    private function populateStateToObject(){
        stateToObjects = new Object();
        var _baseArray:Array = new Array();
       
        //gets all the 'default' objects
        for(var i:int = 0 ; i < numElements;i++){
            if(getElementAt(i) instanceof GraphicElement){
                _baseArray.push(getElementAt(i));
            }
        }
       
        //gets all the objects associated with a 'state' 


        for(var i:int = 0 ; i < states.length ; i++){
            var state:State = states[i];
            var itemsInState:Array = new Array();
            var override:Array = state.overrides;
            for(var k:int = 0 ; k < _baseArray.length ; k++){
                itemsInState.push(_baseArray[k]);
            }
            for(var j:int = 0 ; j < override.length; j++){
                var action:Object = override[j];
                if(action instanceof AddItems){
                    var addItem:AddItems = action as AddItems;
                    if(addItem.items instanceof GraphicElement && _baseArray.lastIndexOf(addItem.items,0)==-1){
                        itemsInState.push(addItem.items);
                    }
                }
            }
            _stateToObjects[state.name] = itemsInState;
        }
    }
   
    //finally we can catch a state and switch the bitmap 

    //we are displaying. We are grabbing the bitmap off 
    //of the host IconButton, this maybe breaks the line 
    //of 'visual code' and 'controller code'. But this
    //small break keeps us from having to define a new skin 

    //for every button with custom bitmaps :LSOS:?!
   
    public function onStateChanging(event:StateChangeEvent){
        switch (event.newState){
            case "down":
                _image.source = _hostIconButton.bitmapDown;
                break;
            case "over":
                _image.source = _hostIconButton.bitmapOver;
                break;
            default :
                _image.source = _hostIconButton.bitmapUp;
        }
    }
}


This skin is slightly simplified from what I use, but it should provide a functional simple button. You can do all sorts of fun things in the skin by overriding parent functions. Remember to use cntrl+click in Flex Builder to view the source (if available) of any interesting component.

If you put this in your flex project, it should show up in you visual designer component tab under the 'custom' directory.  You can drag and drop and assign your image classes in the categories section of the properties tab (under common). This simple button is really anything but, but it helps open the door into programmatic skins and well structured code :).

Sunday, December 5, 2010

Free and Legal Fonts

I quit my job a little under a year ago, one of my plans for my newly found free time was to finish and promote my iphone game at the time. As time went on I focused my effort on technical issues and getting just enough content to push the game out the door instead of focusing on style or art. I think this was largest contributing factor to my game not doing as well as I had hoped. So as I've been embarking on my new flash project, I have decided to put art first and everything else second.

One of the first things I focused on was finding fonts. Fonts go a long way to define your style and distinguish your application from others. At least that's what I'm guessing, I'm not a graphics designer, I just play one for free.

I started by ecstatically browsing to Blambot, a Font site I've heard mentioned on numerous comic book podcasts. "Finally!" I thought. "Justification for listening to comic book podcasts when I stopped collecting years ago!". My excitement was bolstered when I found that "Angry Birds" was using a Blambots font on it's top screen. I took a peak at the license for the font and was disappointed to see no mention of software distribution. So I shot an email off to the site and some time later I got the following response :

Available licenses:

COMMERCIAL LICENSE (For Free Fonts): The non-exclusive, perpetual, non-redistributive, commercial, 5-user license is $40.00 USD per font. (Commercial use would be defined as using the font in a logo, in print, etc.) There is a 25% discount if you license 3 or more commercial font licenses. Commercial licenses requiring more than 5-users can be arranged.

EMBEDDING LICENSE (For All Fonts): If you intend to embed the font in a software application, the non-exclusive embedding license fee is $300 per font. (Embedding is defined as inclusion as on-screen text in game software, flash applications, etc. where an end user can not access the fonts for their own usage.)

REDISTRIBUTIVE LICENSE (For All Fonts): If you intend to redistribute the font files, bundled with other software for access by a third party, the non-exclusive redistributive license fee is $500.00 USD per font. (Redistributive is defined as packaging the font software as part of a CD rom collection, etc.) Note, no Blambot pay font may be redistributed by a
ny means as stand-alone font files.

Kudos to Blambot for having the clearest written license text I've seen related to fonts, then and since. I'm guessing that $300 and $500 is pretty reasonable cost for a small company to cover in order to embed a nicely designed font in their application. Unfortunately I am not a small company, so I licked my wounds and moved on.

Next I tried MyFonts and Dafont. At every turn I was met with ambiguous license text. Emailing the providers didn't clear anything up for me, I usually just got a quote of the same license text that confused me. Both of these sites host and sell (donations in the case of dafonts) fonts that allow the owner to come up with their own license text. The text was almost always unclear about software distribution and exactly what embedding consisted of. I was left feeling uneasy about buying the fonts I needed and could afford.

At this point I became fed up with the idea of 'buying' a font. There was no security in it. If I was going to use font it was going to unambiguously free.

Next I came across openfontlibrary, a very nice looking site, with very useful and clear license. Unfortunately the fonts were not all that varied or useful. It's a site to keep you eye on, but currently their library needs some more content.

After one last round of searching I came across FontSquirrel. The text on the front page read "Only the best commercial-
use free fonts". Ah, beauty. They did have a great selection of free(ish) and commercial safe(ish) fonts. Each font still carries a hand written license, but most are pretty lenient and make it clear you can use the font for whatever your heart desires. So two thumbs up for font squirrel.

Hopefully a paysite can someday combine well written software embedding licenses and affordable fonts, but until then, fontsquirrel seems like the best alternative.

Thursday, December 2, 2010

Make swf without flash

As I am currently a Flash Builder only guy, I have run into some serious issues creating animations for my game. I started by using animated gifs, and quickly dumped those due to quality. If you're going to embed good-looking animation, it pretty much has to be a swf file. This is especially true if you only want certain bits to repeat indefinitely or want your animation to stop instead of repeat.

So I searched for tools that could help me out. I found mostly crap ware sites that wanted $30 for a thrown together tool that converted gifs to swfs, or swfs to flvs, or just about anything except making simple swfs from pngs. The only affordable tool (this dismisses Flash cs5) I could find which looked half decent was KoolMoves. The demo made it seem like a lite version of flash - but used only for simple animations, and very simple actionscript. About the time I was reaching for my credit card I stumbled across this, SWF export for Gimp. My wallet was saved! Since Gimp is my primary graphics tool, all my animations were ready for export. I needed python installed for the plug-in to work, so I booted up Ubuntu and got to it. The plugin worked great (after installing the swftools), and I was on my way.

Some time later I realised that I couldn't get Flex to control my animations. I couldn't stop, rewind, or effect the timing in any way. This became a huge problem and something the plug-in couldn't help me with. Even if I were able to stop the animation, the timing wasn't working correctly and my more intricate animations looked the worse for it. It burned me that all I seemed to be missing was the ability to stop and control time. (super-villians be damned) So instead of giving up and going for the Kool Moves option, I looked into what the gimp plugin was doing behind the scenes. God bless the linux command line and open source, it was only really using the swftools in a very predictable way. jpeg2swf to be exact. So if I could just get the tool to put a stop or loop or something in animation I would be golden.

I found another gimp plugin that lets you export all your layers as pngs, Export Layers Plugin. Using this I exported my animation and figured out the syntax for png2swf. But still, I found no mechanism for stopping. Apparently people only ever want to make infinitely repeating animations. Well, fair enough, it's not what I want though. I dug a little deeper and found swfc. It's part of the swftools package, and allows for animation building from simple(ish) script files. Huzzah! I finally hit the motherload. It took quite a bit of finagling and some guesswork, but I was able to adjust my animations and get the result I wanted by using swfc.

The workflow would go like this:

1)Make a folder for the animation and export you animation layers into the folder
2)Make a swfc script and save it in the same folder. I suffix my animation scripts with .swfc
3)Run >swfc scriptName.swfc
4)Enjoy your delightful animation!

The scripting language is sort of straight forward. I was able to divine the functionality I needed from the the scant examples I found and the poorly established manual. Oddly, very few examples showed how to make a simple animation with things like stopping and timing, most were focused on far more complicated topic like scaling,translating and other tweening transformations.

The most curious problem I ran into was that Flex did not respect the fps set in the swfc script. So the timing worked in Firefox, if I loaded the raw swf, but did not work if I loaded it into my flex application. To overcome this, I went with whatever framerate Flex decided to impose on me and increased the space between frames to make the timing work.


Another problem I needed to solve was how to create sub-animations within my animation. I solved it by making a sprite (in this case called 'poop') and referring to that in my main animation. I'll include that script as my example.


.flash filename="esoStealAnim.swf" version=10 fps=12 change-sets-all="yes" background="white"

.png s1 "1.png"
.png s2 "2.png"
.png s3 "3.png"
.png s4 "4.png"
.png s5 "5.png"
.png s6 "6.png"
.png s7 "7.png"
.png s8 "8.png"
.png s9 "9.png"
.png s10 "10.png"
.png s11 "11.png"

.sprite poop
.frame 1
.put s3
.frame 3
.del s3
.put s4
.frame 5
.del s4
.put s5
.frame 25
.del s5
.put s6
.frame 27
.del s6
.put s7
.frame 29
.del s7
.put s8
.frame 31
.del s8
.put s9
.frame 51
.del s9
.put s10
.end

.frame 1
.put s1
.frame 3
.del s1
.put s2
.frame 5
.del s2
.put s3
.frame 20
.del s3
.stop
.put poop
.play poop
.end


So far swfc has done everything I need it to, I have a feeling I will be getting a lot of use out of it in the future.

Peace!

Wednesday, December 1, 2010

Battle For MVC in Flex 4 : Pass by reference example

It is not impossible to find a reference to 'passing by reference' in the online documentation, but it is not easy. I scoured unrelated code and rented books to find the syntax for the most useful passing by reference syntax. (sorry, meta terms about language makes for awful reading) In Flex 4, this syntax is a necessary component to building a Flex with a MVC pattern. So here's what I've found, just for posterity's sake.


Simple Object Reference

< controllers:IndexController id="controller" playButton="{playButton}" />
< grumbles:PlayButton x="79" y="194" id="playButton" />


The {} syntax lets reference any object declared in your current mxml file, but it requires you name all your objects with the id parameter. Id is the parameter that flex uses to tie everything together. You can also reference member variables of names objects, much the same way you do in actionscript.


< controllers:IndexController id="controller" fooButtonId="{fooButton.id}" />
< grumbles:fooButton x="79" y="194" id="myCrazyId" />



Array of Object Reference

< controllers:MusicExerciseController id="controller" notesArray="{[e1,f1,g1]}"/>
< grumbles:note id="e1"/>
< grumbles:note id="f1"/>
< grumbles:note id="g1"/>


In this example we want a reference to a set of visual items, in this case a set
of musical notes. The member variable 'notesArray' is defined as an Array object. The {[]} notation is the key take away here.


Embedding Resources in Mxml

< grumbles:note id="a1Sharp" pictureSource="@Embed('../includes/notePicture.png')" />


This is similar to embedding resources in actionscript but slightly simplified. If you're using Flash Builder 4, it will kindly let you know if you resource doesn't exist at the location you specified.

I'm sure there's more reference syntax out there, but this is the core of what I've needed to make MVC work.