AXL Development Kit for ActionScript

Transcription

AXL Development Kit for ActionScript
AXL
Development
Kit
for ActionScript 3.0
1
Table of contents:
AXL Library ................................................................................................................................................. 4
Overview ................................................................................................................................................. 5
AO – tweening engine......................................................................................................................... 6
BinAgent – terminal for flash ............................................................................................................. 10
BoundBox – the ui controller............................................................................................................. 13
Carousel – the must have UI component ......................................................................................... 17
LiveArranger – on screen swf display list editor ............................................................................... 22
Messages – standardized alert system ............................................................................................ 26
RSLLoader – runtime shared library loader...................................................................................... 28
AXLX Framework ..................................................................................................................................... 30
Overview ............................................................................................................................................... 31
Step by step .......................................................................................................................................... 31
Setting up the project ........................................................................................................................ 31
XML name and location .................................................................................................................... 31
XML structure .................................................................................................................................... 32
Interactivity ........................................................................................................................................ 43
Working with it ...................................................................................................................................... 48
Examples, documentation, requirements ............................................................................................. 48
AxlLoader ................................................................................................................................................. 49
Overview ............................................................................................................................................... 50
Download .............................................................................................................................................. 50
Opening files ......................................................................................................................................... 50
Hot Keys ............................................................................................................................................... 51
Main program shortcuts .................................................................................................................... 51
LiveArranger shortcuts ...................................................................................................................... 51
2
Supported files ...................................................................................................................................... 52
FlashVars.............................................................................................................................................. 52
Top Bar Clock ....................................................................................................................................... 53
Timestamp Generator........................................................................................................................... 53
Known issues........................................................................................................................................ 53
3
AXL Library
4
Overview
The AXL library is a complete toolbox for building modern ActionScript applications. Provides free for
commercial use, open source alternative to other market products. Can be used with web, mobile and
desktop projects. Speeds up development process by automating day to day dev tasks, bringing up
development process to higher level. Aside from automation and snipplets library provides two unique
(and sort of revolutionary) “indergediends”.
The AXL library consists of 10 main „must have‟ elements.
●
AO – lightweight yet powerful tweening engine
●
BinAgent – advanced flash console for logging and for INPUT – can evaluate ActionScript from
String quite well as for its size.
●
BoundBox – advanced and intuitive controller for building custom UI elements such as scroll
bars, volume bars, window panners, toggle switches, scrollable lists, etc.
●
Carousel – classic: infinite scrolls, image gallery, pick your item, or even slot machine are not a
a challenge for it.
●
LiveArranger – on screen swf display list editor. Allows to detect, select and move around any
DisplayObject with the mouse pointer. Allows to change any of DisplayObject‟s textual, numeric
or boolean property.
●
Ldr – efficient, easy to use assets loader and manager. Auto recognizes file types such as jpg,
gif, png, mp3, mpeg, xml, json, csv, txt. Supports queues, alternative directories, file storing (if
available). Provides detailed info on progress.
●
ConnectPHP – lightweight backend connector. Everything for POST and GET requests;
serialization, encryption, response type recognition, queues. All that with comprehensive log
info.
●
U – Static geometric utilty, snipplet container, reference to other library elements, the cockpit.
●
Counter – Combination of timeout and interval. Ideal for countdowns with single and multiple
time periods, custom and user defined time formatting.
●
Messages – standardized alert system.
●
RSLLoader - separated from repository Runtime Shared Library Loader, great for stubs
The AXL library is the base for AXLX framework. They‟re separate repositories but AXLX can‟t live
without AXL.
5
AO – tweening engine
Fast and lightweight (10kb compiled) ActionScript 3 tweening engine with set of standard and unique
features. Easiness and intuitiveness of use makes it fully competitive player on the market. It‟s
somewhere between GreenSock and GTween. Can animate any numeric property of any object within
given time.
Get it to the project
As a member of axl.utils package, AO class has a reference to just one class from axl library –
axl.utils.Easings. Other than that, it‟s ready to use, completely standalone. Doesn‟t have to be
instantiated manually – it provides static method (AO.animate()) which allows to make all complex
tweens and set all callbacks within it. There‟s no single requirement for you to set before start using it.
Just tween.
What makes it unique
Optimized easings
Easings class provides set of pre-defined, standard animation easing functions, but these benefit from
optimized alternatives (LUT) of flash Math.sin and Math.cos functions. Not noticeable on small scale,
proven significant performance boost on bigger. There‟s written quite a lot on this subject all over the
Internet.
Intervals
On top of “repeat” (cycles here), AO has one more layer of repeating animation sequence. Let‟s say
you would like to animate clock alarm or bird. It shakes for a while and then calms down. Shakes again
6
and pauses again. In other tweening engines that would definitely require more than one line of code.
Here you could just say
AO.animate(bird, 0.1, {x:10,cycles:3,yoyo:true,interval:5,intervalRepetitions:10});
and that would shake it 10px forth and back (yoyo) within 0.1 of second (per shake), freeze for 5
seconds and repeat sequence again. 10 times.
Incremental object updates
Considering interactive application, it‟s not hard to realize that more than one source may want to
update your objects at the same time, during animation. Regardless if it‟s user‟s mouse input or an
event of incoming data, neither “overriding” object‟s new values by animation, nor “killing” the animation
and starting from new point seems to be the right approach in many cases. Sometimes we want carry
on with tweening but respecting object‟s new values. How would you do it in other tweening engines?
Stop and start from new point? What would happen to your easing then?
AO has special flag nIncremental for it, which respects object properties whilst tweening. If it‟s set to
true – it only adds the calculated delta, rather than userp exclusivity on object updates.
Live time-scale changes
Speed and direction of changes can be tweaked during animation. It respects easing functions, so
original “curves” remain the same. Same for other properties such as cycles, yoyo, intervals. Property
timeScale accepts negative values too – this causes animation to play in reverse. You can also animate
timeScale of other tween to achieve truly special effects. Play around with slider in an example on top
of this page to see what it does.
What makes it standard
Along with good performance (4 properties on 2500 objects at 60 FPS) and great ease of use, AO
supports all typical features of tweening engine:
●
start, stop, pause, resume, go-to, restart methods to control playback
7
●
time can be defined as number of seconds or number of frames
●
delay property (respects frame and time based) for delaying animation
●
yoyo functionality for playing animations back and forth
●
cycles for repetition of the same animation
●
set of callbacks with arguments passed by user (onStart, onUpdate, onYoyoHalf, onCycle,
onInterval, onComplete)
●
pre-defined as well as user defined easing functions
●
static methods (one-liners) for firing and killing tweens
Using it
AO.animate – static method
For most of use cases, using AO.animate(target, time, properties) is all what you need.
However, this method supports up to 9 arguments, exposing most usable features. All the rest can be
passed into properties object. Arguments 1-3 are obligatory, 4-9 optional.
Note: If name of one or more keys inside properties object match name(s) of AO properties – values
from the object will override initial AO instance settings, including values passed in arguments of this
method. Full list of arguments:
1. target – object you want to animate
2. time – duration of animation in seconds or number of frames
3. properties – key-values object of properties to animate and its destination values. E.g. { x :
220, y : 100, rotation : 360 }
4. onComplete – callback function to execute once animation is completed (default null)
5. cycles – number of times to repeat animation instantly (default 1)
6. yoyo – once reached destination values, determines if animation is going to play in reverse –
back to start values (default false)
7. easingType – function to make your animation smooth, bouncy, elastic or other (default
easeOutQuart)
8. incremental – determines if updates on object respect its current values (adds the difference) or
update with absolute values (default false)
9. frameBased – determines if time is specified in frames or seconds (default false)
8
List above shows an order of arguments that AO.animate function can accept.
Animations created this way are self-starters, and they‟re disposed once tweening is complete.
Disposed instances cannot be re-used. They‟re created to be one-off, fire and forget. Small memory
foot print allows to create hundreds of them without worrying about optimization. In this case, we rarely
worry about playback controller methods (start, stop, pause, resume, restart). It‟s fine to just “kill” the
tween and start new one.
Using AO instance
Different scenario is when we require to use animation functionality thousands of times, perhaps on the
very same object and same set of properties (but different values) all the time. Typical use case for
that, would be building fancy UI component like scrollable list or animating in game character. There‟s
nothing wrong in using both methods at the same time, but generally, if it comes to thousands, you
should consider optimization by creating re-usable instance with flag destroyOnComplete =
false.
Constructor, similarly to animate method expects 3 obligatory arguments: target, time, properties. AO
instances require to call start method in order to run tweening.
Note: There‟re two group of properties:
●
properties that can be updated anytime during animation and an effect is immediate and
●
properties that require re-start of animation with flag readChanges=true
Members of that second group are prefixed with n letter: nTime, nFrameBased, nIncremental,
nProperties
Properties that can be applied anytime during animation: target, yoyo, easing, timeScale.
9
BinAgent – terminal for flash
Imagine talking to compiled flash file like you would type terminal/console commands in. Imagine
seeing all your trace stack without extra software. Imagine executing uncompiled Actionscript code at
runtime, in web browser, on mobile, tablet, tv. Imagine Actionscript eval is back.
Get it to the project
BinAgent class is where all library / framework logging is routed to, but it can be used completely standalone. There‟s no need to import entire library to benefit from this beast. All it needs is
axl.utils.binAgent package.
You don‟t have to set it up too much either. All mechanic and useful behaviors are processed behind
the scene. For most of the cases new BinAgent(this) in your root display object constructor is all
you need.
Open/close
BinAgent console window can be opened in three ways:
1. programatic: simple as binAgent.isOpen = true;
2. with definable keyboard shortcut/sequence (default: ctrl+alt+right)
3. with adjustable gesture (default: four horizontal drags in top left corner area)
It can be controlled also via allowKeyboardOpen and allowGestureOpen flags.
For any commercial use, please do change default settings, since this tool can cause serious harm to
your business logic.
10
Routing trace
Easy enough to integrate with your projects since it‟s simple as replacing all your trace(statements
with
■
BinAgent.log( if you use binAgent package only
■
U.log( if you use whole library
■
log( from inside of XML configs when using axlx framework
Don‟t worry, you won‟t lose your regular trace – use regularTraceToo to control it and by default it‟s
set to true.
Actually you can do further routing of your trace by providing externalTrace function to BinAgent.
Useful if you want to write log to a file or pass it to JavaScript console E.g.:
1
var b:BinAgent = new BinAgent(this);
2
b.externalTrace = function(output:String):void
3
{
4
if(flash.external.ExternalInterface.available)
5
{
6
7
flash.external.ExternalInterface.call('console.log',
output);
}
8
}
Like every other console, BinAgent allows you to limit maximum number of characters in your log. By
default maxChars = 80000.
Reading long log can cause headache; quick filter your output entering to the input field text you‟re
looking for followed by a colon. E.g. entering :config would display only lines that are containing “config”
chunk.
Executing code
Firstly, it does do it! Secondly not all of it.
Input interpreter is very compact, it‟s capabilities are slightly limited. The most missing functionality is
creating functions. This would be to ev(a/i)l. However, combined with axlx framework it does all of that,
including loops.
As for today, the raw BinAgent implementation (decoupled from framework) has:
11
Supported:
●
Returning, accessing and manipulating on public classes, its instances, public methods,
properties and its values
●
Type casting, comparisons, assignments, negations, concatenation, mathematical operations
with it‟s order, nesting in parentheses
●
Creating new Objects, Arrays and instances of any Classes available within application domain
of root
●
Conditionals with ternary operator of simple and nested structures (parentheses needed)
Not supported:
●
creating functions
●
accessing, executing package level functions
●
if-else-if and switch blocks (can be achieved via ternary operators)
●
for-do-while loops
●
in-de-crementation
Since input parser is designed to return one result, executing more commands at once can be achieved
by grouping them in array.
Code completion
BinAgent provides IDE style code-completion as you type. This has one serious weakness – the code
is being evaluated after every key input, therefore it may execute faster than you would expect (before
hitting enter key). Code completion can be disabled by setting property hints =false. Max number
of hints is determined by both max number of matching properties of subjected object and console
window height. Using up and down arrows in input field allows you to navigate in commands history.
Built in utilites
BinAgent API can be accessed via @ symbol. @.clear() clears the console,@.listClasses()lists
classes available in current application domain, @.displayList() prints well formatted string with
display list of any DisplayObjectContainer and any defined properties, @.structureToString()
prints out well formatted string of structure such as arrays, objects etc., @.pool
12
BoundBox – the ui controller
Tired of “skinning” infinite number of states when all you want is a simple scroll bar, slider, progress
bar, drag-able toggle switch? Did you ever try to build your own? Ever stuck with event listeners
sequence or geometry when panning a big image or window content? Has someone requested „neat
animation‟ on that scroll-able list you finally got to work?
BoundBox controller simplifies interaction between two display objects. It doesn‟t require adding a
single event listener from your side. Simply tell him “this is bound, this is box, let‟s play” and he‟ll know
what to do, how to make everyone happy.
Types of interaction
BoundBox is good with at least three things.
●
When you have to drag/move something, it takes care of controlling all necessary event
listeners. It does it clever and tested way.
●
When you have to limit movement to the certain area, it does all the necessary calculations for
you.
●
It gives clear and detailed information on what‟s the status, as well as powerful API to build
bespoke ui elements easily.
It‟s useful even when mouse listeners are not needed. Movements can be defined by delta, absolute
values and percentages. BoundBox always validates these requests first, respecting behaviors set.
Behaviors
Limiting box movement to the certain area is characterized by defining bound display object in general.
The way / the freedom which bound gives to the box is ruled by setting behaviors. Behaviors can be set
for x an y axis individually, allowing to achieve various results.
While dealing with behaviors, two general cases should be taken into consideration.
13
Box is smaller then the bound
Typical use cases are scrollbars. This is where the thumb/slider becomes your box, and scroll
track/scrolling region becomes your bound.
Box is bigger then the bound
BoundBox can control elements vertically and horizontally. All behaviors are named the same way for
both axis. Translation for horizontal behavior can be illustrated by rotating figures above by 90 degree
clockwise.
There is a significant difference in behavior between one element having two controllers (one for each
axis) and one controller having control over both axis. Each has it‟s own use cases which should be
considered separately.
14
Get it to the project
BoundBox class does not extend any of the DisplayObject classes. It has to be instantiated separately.
Due to animation capabilities, there‟s dependency on two other classes from axl toolkit (only!):
animation engine: axl.utils.AO and animation engine easing functions: axl.utils.Easing.
The simplest functionality is provided in minimum three lines.
1
var controller:BoundBox = new BoundBox();
2
controller.bound = spriteA;
3
controller.box = spriteB;
This alone allows to drag spriteB within area of spriteA. Since coordinates are not being translated to
the common coordinate space, only being a child of the same DisplayObjectContainer would guarantee
documented results. However, “same parent” is not required for properly working mechanism. Placing
bound and box in different containers can be used to achieve custom results.
Good practice is to create custom DisplayObject class, which BoundBox controller is a valid member of.
In other words, make your controller another property of Sprite, MovieClip, Shape or Bitmap.
Connecting two BoundBox controllers together
Little bit more advanced scenario is using bi-directional set of two (or more) actively working controllers
at the same time. Typical use case is draggable list with scrollbar. Scrollbar box moves within scrollbar
bound. List content moves within list container. Logically we want both scrollbar to update the list
position and list to update the scrollbar (if dragging list was used). It does sound simple and it is simple,
but there‟s a trap. If we set A to update B and B to update A, this is very likely going to cause infinite
update process. To overcome that we have to take care of change notifications stream in certain
circumstances. Updated scenario is A updates B if it isn‟t B who‟s the sender of changes to A and B
updates A only if it isn‟t A who requested changes on B. This can be done several ways but not all of
them are right. Eg. we could: setB.changeNotifications = false then request change on B,
then send the flag back to true again and do the same for A but this is not the right approach. This
would work ok if there‟s no animations on neither A nor B or both controllers have set
liveChanges=false. Due to animations, B would come back to notifying A on its changes as soon
as we set the flag back, which maybe way before B animation is finished.
Technique presented bellow allows to connect two controllers symbiotically.
15
1
controllerA.onChange = function(e:Object=null):void
2
{
3
if(e==controllerB)
4
return;
5
6
7
controllerB.setPercentageVertical(controllerA.percentageVertical
, false, controllerA);
}
8
9
10
controllerB.onChange = function(e:Object=null):void
{
if(e==controllerA)
11
return;
12
13
controllerA.setPercentageVertical(controllerB.percentageVertical
, false, controllerB);
}
Example above shows setPercentage* methods which “reduces absolute values to common
denominator”, therefore we don‟t have to translate position of box / bound in controllerA to controllerB
dimensions and coordinate space ourselves. Values from 0 to 1 determine both max position of list in
list container as well as position of thumbnail within scrollbar. Second argument of this method says
about omitting animation. Since we want it all to be animated it‟s false.
The key is third argument, which is “changesArgument”. It is being passed to all change notifications of
this particular movement directive, including every frame of animation. By passing “sender” to the
function, we‟re able to receive it in onChanges callback of other controller, detect it and cut infinite
updates off or pass it through if changes are requested by some other sender (E.g. MouseWheel
event).
16
Carousel – the must have UI component
Fancy image gallery? Slot machine? Animated watch? Sophisticated menu list? At the same time:
childlike simplicity, high precision, good optimization and unlimited elasticity? You got to the right place.
Get it to the project
Carousel class is member of axl.ui package, but it has no references to any other axl toolkit classes,
therefore it can be used completely standalone. It extends flash.display.Sprite class and its behaviour is
pretty much the same as any other display object container.
It‟s quite compact (under 300 lines) and provides minimal but core and quality functionality. It‟s the
essence, created to be extended or played with.
Remember – what youth is used to, age remembers.
Adding ponies
To add elements to the carousel use native addChild and addChildAt methods. Carousel class
overrides
standard
removeChildren,
children
removeChildAt,
manipulation
functions
getChildByName,
(addChild,
getChildAt,
addChildAt,
swapChildren,
removeChild,
swapChildrenAt,
getChildIndex, setChildIndex, numChildren). Elements are placed inside inner container (Sprite) called
rail and all overridden methods manipulate on that rail. Rail is there for optimization and “center
registration point maintenance”. After each child addition and removal, rail position is updated and
children are re-distributed.
Positioning
Positioning carousel
Elements inside rail are distributed from the most centre point. In other words, carousel has registration
point defined as “centre” rather than “top-left”. That obligates you to set x and y of your carousel exactly
where you want to see the centre of your carousel. Considering big carousels of big or variable number
of elements – centre registration point facilitates positioning of your carousel. That applies to both
vertical and horizontal alignment and remains the same even after carousel orientation change with
children inside (seamless axle switch).
Positioning elements
17
Setting coordinates of elements you want to add to carousel should not be needed at all. At least not
within the axle you‟ve set your carousel to work at. Just add it to container and that‟s it. Distribution is
automatic. Carousel always touches the only needed properties leaving other untouched. That means if
it‟s horizontal – takes care / overwrites x property only. If carousel is vertical – it only tweaks y of your
elements. Exceptional situation is when you set carousel‟s orientation with elements already inside.
Defining elements order
Objects are distributed based on their indices. Elements added in order a,b,c,d will be displayed in
initial order a,b,c,d. Shifting carousel to the right will produce d,a,b,c and then c,d,a,b thenb,c,d,a, etc.
Children indices are under control of carousel and are directly jointed to elements order. If, for any
reason, you‟d require to change elements order for already populated carousel, use setChildIndex,
swapChildren and swapChildrenAt native methods, taking into account that current indices may be
different from initial values (different to order they were added). Once new order is set, call rearange()
for changes to apply.
Changing Carousel orientation
To change carousel orientation use isHORIZONTAL and isVERTICAL flags.
Setting flag changes orientation immediately, redistributes children along new axle and sets
corresponding flags adequately. Carousel can‟t be horizontal and vertical at the same time.
As a rule, changing axle should be seamless. That means, if center point is in between 2nd and 3rd
element while horizontal, switching to vertical should still keep center point between 2nd and 3rd
element.
As mentioned in positioning paragraph, carousel touches only object‟s axle that is assigned to.
However, changing axle while children inside can overwrite user‟s values. Example:
Carousel is horizontal and has three elements inside. Each element is 20px wide and high. First two
elements have y property set as 0, but third one is at y=10. Original distributed state would look like:
{0,0,20,20}, {20,0,20,20}, {40,10,20,20}
For normal operating in horizontal mode, carousel will continue updating x property, leaving third‟s y at
10 untouched. However, after switching orientation to vertical, distribution would re-set all x to 0, and
distribute by y: {0,0,20,20}, {0,20,20,20}, {0,40,20,20}
At this point, original y property value for third element is lost. Switching component back to horizontal
mode would result in distribution {0,0,20,20}, {20,0,20,20}, {40,0,20,20} which is different to original.
18
Movement
Entire class provides just one method for propelling carousel. This method is calledmovementBit and
accepts just one argument – delta. Delta defines number of pixels we want to “twist” elements from
their current position. This can be negative (to move elements left if horizontal, up if vertical) or positive
(to move elements to the right or downwards).
Absolute delta value can be greater than aggregate sum of all elements dimensions and gaps –
necessary calculations always normalize these requests and put carousel elements precisely where
expected.
Result of movementBit function is instant. Objects are moved to their new positions immediately.
There‟s no animations API in this class. However, this function is all you need to make your carousel
animated.
The most basic example presenting animated carousel in action:
1
var carousel:Carusele = new Carusele();
2
carousel.x = carousel.y = 100;
3
addChild(carousel);
4
for(var i:int = 0; i < 10; i++)
5
{
6
var tf:TextField = new TextField();
7
tf.text = String(i);
8
carousel.addChild(tf);
9
}
10
11
this.addEventListener(Event.ENTER_FRAME, updateCarousel);
12
function updateCarousel(e:Event=null):void
13
{
14
15
carousel.movementBit(5);
}
Example above covers most basic carousel set up. From creating class instance, through positioning,
adding 10 text fields to carousel, to propelling it rightwards with speed of 5 pixels per frame.
●
In line one we‟re instantiating carousel like any other Class.
●
Line 2-3 positions carousel and adds it to the stage (see Positioning paragraph).
●
In lines 4-9 we create 10 text fields and add them to carousel in the loop.
19
●
The key is line 11, where we add ENTER_FRAME event listener.
●
Line 12-15 is body of that listener, and all it does is passing delta of 5 pixels to carousel‟s
movementBit function every time our flash file renders frame.
Connecting animation libraries to Carousel
Typically, animation engines such as Greensock, GTween, Starling.juggler, AO expose onUpdateor
onChange property, which is more attractive alternative for animating carousel comparing to boring,
linear 5px on enter frame event. Animation engines usually provide easing feature which allows to
make movements smooth, elastic, bouncy or add other fancy effects to it. Approach of movementBit
function allows to keep all your stuff in sync. Here‟s how to connect one of commercial animation
engines to carousel:
1
var proxy:Object = {x:0,y:0};
2
TweenLite.to(proxy, 30, {x:10000, onUpdate:updateCarousel});
3
function updateCarousel(e:Event=null):void
4
{
5
var delta:Number = proxy.x - proxy.y;
6
carousel.movementBit(delta);
7
proxy.y = proxy.x;
8
}
Example above shows how to connect Greensock‟s TweenLite to Carousel.
Firstly, we create dummy object called proxy. Next, we use TweenLite.to API to animate that dummy
non-displayable proxy object.
In line two, we set up duration for 30 seconds on distance of 10000 pixels on x axle and execution of
updateCarousel callback on every update to proxy element.
Inside of our callback (lines 4-7) we calculate difference between current and previous value of proxy‟s
x value. That difference is our delta argument for carousel movementBit function.
Similar approach should be satisfactory while dealing with draggable lists. Calculating differences
between current and previous location of touch event or mouse event always gives delta parameter.
20
Performance
Due to internal container system, carousel is quite well optimized. It has been profiled with 4000
elements inside and proven to be stable and efficient. Whenever possible, instead of iterating through
all children, only inner container is updated. Only when container reaches its maximum offset, children
are being re-sorted and container jumps back on place where offset is closest to 0, re-enabling
optimized movements again. This process is seamless, behind the scene and doesn‟t cause any visual
jerky glitches.
That point of resorting can be controlled by changing maxOffset value. Property is described by
percentage of aggregate carousel width. By default is 0.25. That means if there‟re five elements of
equal size of 200px each inside carousel, resorting will take place once aggregate delta exceeds 250 or
-250 px. After this, delta is reset to 0.
The closest to 0 maxOffset is set to, the more frequent resorting occurs and performance drops
down. Setting it to 0 will likely cause stack overflow. On the other hand, setting this value greater than
0.5 will allow carousel to offset all children from centre point completely (they‟ll all be on one side of the
axle in extreme case).
21
LiveArranger – on screen swf display list editor
Not using Flash Pro / CC / Animate? Is your display list getting hard to control? Adding content
dynamically? Doing animations programmatically? Ever wonder “What is this object doing there?
What‟s underneath it? What‟s its current or destination position, width, height, name, what‟s its parent,
what children does it have? How many times you‟ve had to republish your swf just to see something
moved few pixels to the left, right, scaled slightly different?
LiveArranger tool allows you to edit already published swf‟s display objects similar you would do in any
graphics editor. You can select and move things around with just your mouse, it shows you its outline
and basic info (type, name, x, y, width, height). Convenient hot-keys allow to traverse whole display list
up, down, and sideways. Built in editor exposes option to see, filter and edit any property of your target.
Get it to the project
Axl toolkit loves minimalism and self-sufficientness. There‟s no dependencies on other part of the toolkit
but class U. If you choose to use just LiveArranger, all you need is axl.utils.liveArange package and U
class itself. In total it‟s approx. 2KB!
22
Once your U class has fired the callback passed to init method, call new LiveAranger()anywhere in your
project and that‟s it.
Common concern is using this tool in production releases, but properly secured shouldn‟t cause much
harm.
Similarly to BinAgent, LiveAranger is a singleton class which controls it‟s singularity across application
domains. In larger applications, you can have multiple swfs loaded, each may want to declare its own
instance of LA, but only one will rule the runtime and control the stage.
Activate / deactivate
Once instantiated, LiveAranger is deactivated by default. That would be madness to have it on all the
time. Default hot-key to toggle its activity is keyCode 117 (F6). If you decide to keep LA in production,
for
safety
and
security
of
your
business
logic,
please
do
change
this
value.
Use
userKeyboarOpenSequence to provide an array of keyCodes that will switch it on and off. E.g.
LiveAranger.instance.userKeyboarOpenSequence = [45,35,45,35] would require press of keys Insert,
End, Insert, End alternately to launch/quit it.
Programmatic way is also available and it‟s simple as instance.isOn = !instance.isOn.
Working with it
Once activated, it‟s ready to use: objects under mouse pointer are being discovered, outlined,
described and pre-selected and few more keyboard actions is available.
Object pre-selected
Moving mouse pointer across your stage should keep detecting and pre-selecting new objects until you
either a) deactivate LiveArranger or b) lock/advance pre-selected object to selected object.
Considering nested contents, e.g. Sprite containing TextField, it could be arbitrary which object should
be pre-selected. By default, it picks the most top layer which isn‟t container. In the scenario above, text
field would be chosen first, traversing one level up would pre-select Sprite.
Pre-selected objects can be moved with both keyboard (arrows) and mouse (dragging).
Object selected
The only way to advance pre-selected object to selected state is to press one of the following keys:
Home (not available on mac), Page Down or Page Down.
23
Advancing object locks-down arranger from discovering new objects under mouse pointer and opens
up an additional micro-editor. To exit editor (degrade to pre-selected) use ESC key. Another technique
of the same result would be to de-activate and activate LA again.
Holding CTRL/COMMAND key allows to choose different object (with mouse pointer) while editor is still
on.
Traversing
Selecting parent, child or another display object within the same container against current is called
traversing.
For both pre-selected and selected objects use
●
“Z” to select parent layer,
●
“X” to get to first child of currently selected object,
●
“1” and “2” to select neighbours (1 select neighbour of lower childIndex, 2 – upper)
Selecting neighbours is “looped”, which means when child is already the most ground in container, next
“1” would select the most top child, and respectively – if selected object is already the most top layer in
container, pressing “2” would select child of index 0 in the same container.
Another way of traversing is using editor‟s buttons. Continuous traversing up should select Stage object
eventually.
Editor
Editor is a semi-transparent, movable and re-sizable mini window, which allows to view, filter and edit
values of any public property belonging to selected object, within supported types of properties
(primitives such as Strings, Numbers, Boolean values).
Editor contains three main elements:
1. Filter – input text field which allows to filter properties to these which match the pattern. Accepts
regular expressions, so ^(x|y)$ would limit it to display two rows containing object coordinates
only
2. Traverser – three micro buttons to traverse from selected object up (parent), down (children) or
sideways (sister). Using traverser changes editor‟s target
3. List – list of property-value text fields – all the text fields representing values are of type input,
where user can do live changes on selected object. To make changes easier, properties of type
int, Number or Boolean can be edited using keyboard arrows (sets the flag opposite or
increases/decreases numeric values).
24
When application focus is in editor, moving object with arrows is unavailable. Changes entered into
editor are attempted to be applied every key input. In case of incorrect values, changes are not applied.
Changing selector style
In some cases, selector may disturb you while editing the object. Typically, when dealing with small
objects, the information hint covers the content, or target colors mix with selector colors. To change
selector style use Shift key. There are six built in selection styles.
Hot keys cheat sheet
●
F6 – activates/deactivates LiveArranger.
●
PageUp, PageDown, Home – opens/closes editor window for selected object
●
ESC – closes editor. If editor is closed, turns arranger off.
●
Left arrow, Right arrow, Up arrow, Down arrow
○ if focus is on selected object: moves selected object horizontally and vertically
○ if focus is in editor input: increases and dis-creases numeric value or changes Boolean flag
●
Shift – changes selection style
●
Shift + arrows – multiplies movements by 5
●
Z – (traverse up) sets parent of selected object as selected object if available.
●
X – (traverse down) selects first child of selected object as selected object if available.
●
1 – (traverse side) selects another child(+1) in container of selected object if available.
●
2 – (traverse side) selects another child(-1) in container of selected object if available.
●
Press and hold CTRL or CMD
○ if editor is off: allows to drag buttons preventing from executing their functions
○ if editor is on: allows to select new object without exiting editor
25
Messages – standardized alert system
Something went wrong? Download is complete? Need to notify user promptly? User must accept T&C‟s
first? Validation error?
This tool provides quick, easy and simple way to display interactive notifications to the user. It‟s always
on the top, so can‟t be missed. One line of code have never been handier.
Display styled alert on top of your Stage. It automatically removes itself from there on user action. Or
not, if you set it so. It‟s always as wide as your stage is, which makes it looking integral to every project.
Get it to the project
Class Messages is a member of axl.utils package and has reference to U class only. It‟s a semisingleton. Core functionality is provided by one static function, therefore it doesn‟t have to be
instantiated separately.
For ease of use, class U exposes msg function in its own API, which allows to use this system without
even importing it.
Simplest call would be U.msg("Please, check your internet connection");
Interactivity
Default, pre-defined behaviour displays a message which disappears as soon as user clicks / touches
anything on the stage. But we can differ if it was “anything” or it was the message itself which user
interacted with, and perform custom actions accordingly. We can also force user user to click/touch
message object in order to take it off the stage. And yes, we‟re still talking about one line of code utility.
In fact Messages.msg() accepts total number of four non-obligatory arguments.
1. message:String – text or html text to print out – if it‟s null – message is removed from stage
(consider this manual removal)
2. onClickOutside:Function – callback to execute when user clicks anywhere but on
message
3. onClickInside:Function – callback to execute when user clicks on message
4. forceClickInside:Boolean – flag that can hold message displayed till the moment
message is clicked/touched
When forceClickInside flag is set to true, onClickOutside callback is executed as many times as user
touches anything else but message. Regardless of flag state, onClickInside is executed only once per
message. Defining one callback and not defining other is absolutely fine.
26
Since messages are displayed as htmlText, additional interactivity can be provided using htmlTextfrom
flash.text.Textfield API. Especially using <a href> tag, which allows not only opening user defined URL
in a web browser, but also dispatching flash.event.TextEvent.LINK of custom type. Really powerful and
worth to dig.
Styling
Messages class comes with predefined style. Actually, it‟s laughs to call it style. It‟s white Verdana text
on blue background. This colour theme doesn‟t always work well so it might be worth to first set it up
somewhere at the beginning of your project.
Use Messages.textfield, Messages.textFormat and Messages.bgColour to define general style and/or
use htmlText API to style each message separately. Html text also gives an option to, under certain
restrictions, display images within your message.
Other
Queuing messages is not available. Older message is always replaced by a new one, callbacks are
being overwritten. However, considering bigger applications, swfs loaded into separate application
domains can declare its own instance, but then, one click outside is received by all instances.
27
RSLLoader
– runtime shared library loader
Overview
Helps you to load Runtime Shared Library from libraryURLs to the ApplicationDomain you specify in
domainType via domain.
It maps classes from loaded content to classDictionary assoc array. This allows to use these even if
you decide to load your RSL to separated application domain, eg. to avoid class conflicts when different
assets have different versions of the same framework embedded in.
It supports alternative directories to satisfy dispersed systems and fall-backs. There are two
methodologies to pick from, controlled by twoStepLoading property:
●
Two step loading – loads binary content via URLLoader first, then loads from bytes with Loader
(may help with security issues but flash vars are only “attempted” to pass (don‟t work according
to documentation). Also supports loading from embedded assets (as class) and then first step is
skipped.
●
One Step Loading sorts everything in regular URLRequest passed to Loader but security errors
are more likely to happen.
Once complete, executes instance. onReady callback if set. Once onReady is called, you can access
several properties of loaded content:
●
instance. bytes
●
instance. libraryLoader
●
instance. classDictionary
●
instance. loadedContentLoaderInfo
Context Parameters
All parameters from query in URL are stripped out from initial URL but stored. The only valid parameter
for first step load is cachebust which can be controlled via useCachebust variable.
All parameters from initial query are passed to second step loading (from bytes) to loader context.
Additional parameters can be added to contextParameters property. Automatically RSLLoader adds
fileName parameter – file name of requester which is deducted as follows:
●
REQUESTER. loaderInfo.parameters.fileName – the highest
●
REQUESTER. loaderInfo.parameters.loadedURL – if fileName is not present, can be
stripped out from this one. Additionally, loadedURL is going to be used as a prefix for relative
28
addresses defined in libraryURLs. Good for changing relative paths context when loaded by
another app.
●
REQUESTER. loaderInfo.url – if none of above is present, fileName is deducted from
standard flash url property (which, due to security reasons, may not supply relevant information
in nested structures).
FileName parameter is ideal for stubs of which name is meaningfull.
Example
1
rslloader= new RSLLoader(this,trace);
2
rslloader.domainType = rslloader.domain.separated;
3
rslloader.libraryURLs = [serverURL,backupServerURL,local];
4
rslloader.onReady = onProgramLoaded;
5
rslloader.load();
AXL Library adhesion
RSLLoader is valid part of AXL library. Since AXL library can be used as dynamically linked RSL, in
many cases, keeping RSL away from Loader may be required. They‟re separate repositories but same
BSD license applies.
29
AXLX
Framework
30
Overview
AXLX is an Open Source framework for building projects based on dynamically loaded XML files.
It is an answer to constant need of fast updates to live projects. Since updating XML does not require
compilation/deployment afterwards, amends and bug fixes can be applied in an eye blink.
Unlike flex framework, where XML (MXML) files are used for compilation, in AXLX XMLs are used for
building flash content after compilation. XML definitions can define layouts, complex interactivity, logic,
data processing and even more sophisticated tasks. It benefits from set of UI components, controllers,
tweening engine and other elements of AXL library.
It actually allows to build, develop and update projects without IDE. All it needs is a swf file with AXLX
embedded in or a stub loading AXLX as a RSL. This can move weight of not necessarily developer
updates to other member of the team (copywriters, graphic designers). Since the most significant part is
externalized to XML, using AXLX framework have positive impact on source code control.
You can build your content completely on AXLX framework or just make it complementary part of larger
projects. It is easy to extend it by building your API on top of it.
Dedicated software to work with AXLX projects is AxlLoader small, fast open source (free) AIR app. It
allows to re-load projects quickly instead of constantly re-compiling or re-opening to view changes
made to XML definitions.
Step by step
Setting up the project
The most basic set-up is stupidly simple.
1. Create new web project, give it a name, let‟s say “Example”.
2. Import AXL Library and AXLX Framework to your project.
3. Navigate to your root class (Example.as) and make it extending xRoot class (import
axl.xdef.types.display.xRoot).
4. You‟re done! Debug your project and watch the console log.
XML name and location
Once you run a debug of Example.as, you‟ll probably see your swf blank with a blue alert saying
“Invalid config file“. When you look into console, you‟ll see a substantial log – the result of initial flow.
31
The flow is quite complex but there‟s not much to worry, all it does is finding out where to load config
from, loads it an builds the content.
The easiest way to find out what was the location the config file was searched for is to examinate log
for “xml” occurrences.
By default XML file name has to have the same name as the flash file. By default, it checks ONE
DIRECTORY UP relative to where your swf is placed (in web projects). It applies to content run locally
and to swf files put on server. This can be controlled by various settings, see independent server
directories, file name dictates sub-directories, hardcoding config filename,loading AXLX from stub. For
mobile projects, default location is File.applicationStorageDirectory.
In our case it‟s going to be “Example/bin-debug/../Example.xml”. That means our XML definition should
be placed in root of our project folder (outside “src”).
Ok, config not found (SKIPPED). Let‟s feed it. Let‟s create an empty Example.xml and debug it again.
Blue bar still says “Invalid config file”, but this time inside log we can see that file was LOADED (instead
of skipped like last time). It‟s also printed out that “Config isn‟t valid XML file”. Lets create valid XML file.
XML structure
1
<axlx>
2
<root/>
3
</axlx>
Minimal valid XML definiton of the config file
If we copy the code above, paste to our Example.xml created before and debug the project again, blue
error bar is finally gone, but swf is still blank. That‟s a good sign. We can start building content.
Nodes
There are two kind of nodes available: Grand Nodes and Child Nodes. Only Grand Nodes can be
children of top XML node. Child Nodes can only be children of Grand Nodes.
Grand nodes
There are three Grand Nodes interpreted from the XML definiton:
●
<root/> – represents your root display object (instance of Example class in our project).
Children of this node are processed (loaded, instantiated, added to the display list) right after
config file is loaded and project settings are read.
32
●
<project/> – sets up project / library related properties such as debug mode, time-out for
assets loading, time-out for POST and GET requests etc. Parsed right after config file is loaded
and validated, can be referenced later though.
●
<additions/> – container for Child Nodes that are not instantiated automatically. Children of
this node can be turned from XML nodes to valid ActionScript objects as a result of interactivity,
processed and added to display list or stay reference-able for further interactivity / processing.
Before instantiation they take up no more space in memory than XML nodes.
Child Nodes
Child Nodes represent particular data types. Each one (once instantiated) is a particular class instance.
These are classes or decorative functions defined by AXLX framework and can be divided on 3 groups:
12 displayable nodes, 4 functional nodes and 3 decorative nodes.
33
Displayable nodes
NODE
DESCRIPTION
<div>
Display object container
<img>
Bitmap, image
<txt>
Text field merged with TextFormat
<btn>
Button
<msk>
Interactive container with mask and bounding box
<swf>
Container to control loaded swf‟s timeline
<scrollBar>
<carousel>
Interactive container with bounding box, multi-purpose, plug-able to
<msk>
Interactive container, auto children distribution, infinite horizontal /
vertical scroll
<carouselSelectab
same as <carousel> but provides animated scroll from object to object
le>
and has got “center” object concept
<form>
<vod>
<root>
container that validates all input type text fields against regular
expressions they carry, exposes form object based on these
Video on demand player (regular flash video, stage video not supported
yet).
Master class of the framework, the root of display list, and context for
code execution, treat it as your stage, so it‟s once in the project.
Layering display list
If node is a recipe for descendant of DisplayObjectContainer, XML children of that node
representing other DisplayObject
descendants will automatically become children of that
DisplayObjectContainer. Example:
34
1
<div>
2
<txt/>
3
<img/>
4
</div>
is an equivalent of:
1
var s:Sprite = new Sprite();
2
s.addChild(new TextField());
3
s.addChild(new Bitmap());
It‟s not hard to notice the resemblance between layering display list this way and HTML. There are
more of these similarities in the framework. It‟s just upside down comparing to it! Particular nodes
represent instructions and they‟re read from top to bottom, putting last read object on top of the stack.
Functional nodes
Functional nodes cannot be added to the display list but they follow the same principal: placed in
<root> – processed (instantiated) right after config is loaded, placed in <additions> node take no
more space than their XML node until they‟re processed in a result of interactivity. Even they‟re not the
display objects, can be XML children of any Child Node – they‟ll be processed and available right after
their parent.
NODE
DESCRIPTION
<act>
Function equivalent
<data>
Lightweight container for loaded data (JSON, XML, CSV, Sound, swf with fonts)
<script>
Loads external XML definitions to the project such as templates, components
<timer>
Combination of setTimeout and setInterval
Since functional nodes operate entirely on attributes (no reason for them to have children), they‟re
typically occur as closed nodes e.g. <act attrib='123'/>. Attributes usage is described right after
Nodes.
35
Decorative nodes
Decorative nodes are not display objects themselves but they decorate display objects. In order to
decorate any of it, make it it‟s child.
NODE
DESCRIPTION
SUB-NODES
<colorTransform/>
assigns flash.geom.ColorTransform
no
<graphics>
draws on object using flash.display.Graphics
<command>
creates and assigns an array of descendands of
<filters>
flash.filters.BitmapFilter
<filter/>
Decorative nodes can only be used with display objects that support given style of decoration, that
means e.g. using <graphics> on <img> or <txt> has no effect.
1
<img>
2
3
<colorTransform/>
</img>
Example use of decorative node. Assigns flash.display.ColorTransform to Bitmap.
Attributes
In contrast to node type which defines what class is going to be instantiated, XML attributes of the node
are here to set properties of that particular instance. Handy inline key-value style saves a lot of space
and can be copied from one node to another. Example:
1
var t:TextField = new TextField();
2
t.type= "input";
3
t.border = true;
4
t.width
5
t.height = 60;
6
t.x = 30;
7
t.y = 20;
= 200;
36
Can be translated to:
1
<txt x='30' y='20' width='200' height='30' border='true' type='input'/>
Ok, let‟s come back to our Example project. We‟ve got an Example.swf file in bin-debug folder and
Example.xml file one directory up. We‟ve successfully debugged the project causing swf to load our
minimal valid XML. We now know that we can safely place any of 11 displayable Child Nodes into the
Grand Node called <root> and they‟ll be rendered right after config is loaded. We also know how to
set properties of any instance that node type is linked to, so let‟s try it out with the txt node from
example above. Our new Example.xml should look like this now:
1
2
3
4
5
<config>
<root>
<txt x='30'
type='input'/>
y='20'
width='200'
height='30'
border='true'
</root>
</config>
Debug or re-open Example.swf. Voilà! Rectangular, black border input text field appears on our flash.
But let‟s take a closer look. x, y, width, height are of Number data type, border is Boolean, type is
String. How does it know what to do, what happened to strong-typing? And what happens if we try to
use attribute that does not exist in instance that node is linked to?
How attributes are parsed
The order of attributes matters – they‟re being processed from left to right. Attributes can refer to
target‟s deeper properties. E.g.
1
<msk controller.animationTime="2"/>
37
Attribute key
If target (any object) does not own property specified as attribute in the node, then the property is not
assigned. If it does, value of the attribute is assigned to the target‟s property. If object is dynamic and
property of given attribute name does not exist, new property on target is not created.
Attribute value
Every attribute value is parsed by a single function. In regular cases it passes it throughJSON.parse
method and assigns either result of parsing if it was successful or original string value if it failed. This
allows to differentiate all primitives such as Numbers, Strings, Booleans, Arrays and Objects containing
other primitives. Quite a wide field already, e.g. for creating matrix for ColorMatrixFilter or gradient fill for
Graphics.
But parsing attribute can go further – it can go through the code evaluation and take value from
reference to other object or even create new object or instance of any class available in
ApplicationDomain.
In other words, it‟s available to write an ActionScript code inside attributes of any XML node. But this
should not be overused and actually avoided wherever possible. Internal parser is small and fast but no
way as fast as the real, compiled ActionScript. Use functionalities available within the framework.
How to write ActionScript in XML attributes
First of all, interpreter is quite limited. It performs really well (as for its size) but some limitations and
bizzarity apply. For instance, to refer to any class you may want to use (instantiation, static methods)
it‟s required to invoke full package. Eg. new flash.display.Sprite(). Another: parser is designed
to return one result, therefore more than one instruction at the time must be wrapped in an array, where
instructions are separated with coma character (semicolons are not recognized). Full overview of what
is supported and what is not, can be found here.
To make sure an attribute value will go through code evaluation, use dollar sign as a prefix. E.g.:
1
<txt width='$stage.stageWidth/2' height='$stage.stageHeight/2'/>
This applies to any native flash object properties available within ActionScript documentation. However,
within AXLX framework, there are certain properties of certain classes that do not require dollar sign
38
prefix in attribute value to contain uncompiled ActionScript. They actually expect a String, which is
going to be evaluated when needed. If you prefix such with dollar sign, evaluation will either occur to
early (not wanted) or you‟ll make a reference to other object containing the right string to evaluate
(advanced).
List of attributes that don‟t need dolar sign to evaluate value:
ATTRIBUTE
IMPLEMENTERS
onAddedToStage
every displayable node
onRemovedFromStage
every displayable node
onChildrenCreated
every display object container
onElementAdded
every display object container
onMovementComplete
<carouselSelectable>
onStop
<swf>
onSubmit, onError
<form>
onLinkEvent
<txt>
code
<act>, <btn>, <txt>
onOver, onOut, onDown, onRelease
<btn>
onTimeIndexChange, onUpdate, onComplete
<timer>
onInclude, onIncluded
<script>
onComplete, onExit, onPlayStart, onPlayStop, onBufferFull,
onBufferEmpty, onMeta, onTimerUpdate
<vod>
Each attribute containing uncompiled code can use this keyword. It works as expected – refers to the
instance which contains that code. E.g.:
39
1
<btn onDown='this.x += 10'>
2
3
<txt mouseEnabled='false' >click me</txt>
</btn>
Using “this” keyword example. Clicking button moves it by 10 pixels.
If keyword “this” is omitted, and for every other element, root context of our references and directives is
our root class – Example.as in this case. Since it extends framework‟s xRoot class, gives a rich API to
manipulate, add, remove, animate display objects, execute XML defined functions and more. How to
reference other objects within the project can be found in “The Registry” paragraph.
Special attributes
In contrast to standard attributes, which refer to instance‟s properties and methods, there are three
special ones, which are quite crucial for whole framework. They could be called Grand attributes. They
only apply to displayable and functional Child Nodes (excl. decorative) but not necessarily refer to
existing fields of it.
name
Each element you want to dynamically interact with should have name attribute of unique value. This is
the core functionality; to allow all elements within XML config file to be found, instantiated, added to
display list, animated, removed from display list, referenced from other elements, changed, functions to
be executed, it has to be legitimated by name property. That means every prime child of
<additions> Grand Node has to have name attribute defined. Unlike naming property e.g. ID or
anyhow else, this allows easy integration since “name” property is native to all display objects in flash.
It‟s also a part of the registry concept, described in Registry paragraph.
meta
ixDef interface enforces providing dynamic container – space for animations definitions and any other
referenceable properties. This variable suppose to be set up just once (be reset-resistant) in order to
securely store data/states. It has to be JSON style object, so the simplest implementation would look
like this:
1
<div meta='{}'/>
40
Most of the framework classes has also defined “meta keywords”, these are pre-reserved variable
names in meta object. Their existence will be exterminated and appropriate action taken when they‟re
found / looked for. None of meta keywords usage is obligatory but assigning inappropriate values to it
may lead to unexpected results.
List of meta keywords and their implementers:
META KEYWORD
meta.addedToStage,
meta.addChildAt,
meta.removeChildAt
meta.addChild,
meta.removeChild,
IMPLEMENTERS
every
displayable
node
meta.js
<btn>,<txt>
meta.url
<btn>
meta.post
<btn>
meta.replace
<txt>
TYPE OF ACTION
animation
calls external interface, array of
arguments
navigates to url on execution
performs POST or GET request
on execution
replaces
given
pattern
with
given source within text
If txt is child of form, form
meta.regexp
<txt>
checks for regular expressions
to validate input
src
Attribute src causes node to load resource from specified address, turns it into usable ActionScript
form (DisplayObject, XML, Sound, String, Object, ByteArray) and processes according to node type
context. Address can be absolute or relative. Relative addresses take original XML file location as a
base. If resource is already loaded (other object loaded same filename first), by default no subsequent
load call is made. In this case, for images, bitmap data is drawn (copied) from originally loaded source.
For other data types “stealing effect” may occur. To prevent it useoverwriteInLib=true attribute
along with src. To prevent getting file from cache in web projects, use cachebust='true' attribute.
Contextual behaviors when resource is loaded:
●
Draws loaded image to bitmapData associated with <img> node.
41
●
For any Display Object Container, creates new bitmap, draws to its bitmap data from resource,
and adds it to it‟s display list at index 0.
●
For <script> – loads external XML definition and merges it‟s additions node to main config‟s
additons node.
●
For <swf> – loads it, searches against MovieClip to control existence, puts it into displayable
container.
●
For <data> – loads and just keeps able to reference (for loading fonts in embeds swf its just
enough).
Let‟s try it out with our Example project. Next to Example.xml let‟s create folder called “assets” and put
dummy “Example.jpg” in it. Our folder structure should now look like this:
1
.
2
..
3
assets
4
5
|-Example.jpg
bin-debug
6
|-Example.swf
7
Example.xml
8
src
9
|-Example.as
Lets add the image reference to our config. We want to make it backgrund, so we‟ll put an<img> node
right after root tag is open, before <txt>. Now the config file should look like this:
1
2
3
4
5
6
<config>
<root>
<img src='/assets/Example.jpg'/>
<txt x='30'
type='input'/>
y='20'
width='200'
height='30'
border='true'
</root>
</config>
42
Run Example.swf again and watch. Has loading files ever been easier? In one line we can load,
instantiate, set tons of properties and add it to the right spot at the display list. Saves tens of lines of
code, eliminates dealing with event listeners, thinking about sequence and so on.
When processing any XML node, attribute src is checked before any other attribute, even before actual
instantiation of the object that node points to. Therefore you can be sure that every other attributes will
be processed when resource defined in src is ready.
When attributes are parsed
For non-displayable objects, attributes are parsed just once – at instantiation. In displayable objects
though, attributes are parsed on instantiation and (by default) every time object is added to stage! This
can cause loads of unwanted results, especially if you put some scripting in attributes. Most common
issue is object duplication. Most precious advantages of this behaviour are:
●
repeatable animations: when displayable object has an animation defined e.g. in
meta.onAddedToStage, then every time object is added, all properties are set to original and
animation can be performed exactly the same way. That can help building all screens selfsufficient and easy.
●
dynamic text always up to date: re-setting text for txt nodes makes assigned “replace”
mechanism to work, refresh.
However, to take control over parsing arguments at least twice (on instantiation, on added to stage)
with help comes ixDisplay interface method resetOnAddedToStage and ixDef interface method
reset.
Use resetOnAddedToStage='false' displayable node attribute if you want to avoid parsing
attributes and code evaluation multiple times. Use reset() interface method to re-parse attributes
manually, on demand.
Attribute src cannot be a subject of reset. There‟s no way to reload resource assigned to already
existing, instantiated node.
Interactivity
We now know how to create and set up objects on stage ( <root>). We also know that Child Nodes in
<additions> node are only recipes for objects. We probably also know a little bit of magic with writing
43
quasi ActionScript in attributes. Now, how to add objects from recipe to stage, how to add object to
another object, how to remove it from there dynamically?
Add, remove elements to/from display list
We‟ll now clear out our Example.XML‟s root, so we can start sort of from scratch. Let‟s first include
<additions> Grand Node. Ready? Does it look like this?:
1
<config>
2
<root>
3
</root>
4
<additions>
5
</additions>
6
</config>
Let‟s now create two buttons: A and B. We‟ll put A on the stage, but place B into additions node. We‟ll
give them a name „btnA‟ and „btnB‟ accordingly. Then we‟ll set button A to remove itself from stage and
add button B instead. We‟ll do it similarly for button B, remove itself but add button A back again. We‟ll
give them a txt node as a child so they‟ll have some labels. Our config file now is little bit more
developed, looks like this:
1
2
<config>
<root>
3
<btn name='btnA' x='0' code='[rmv("btnA"),add("btnB")]'>
4
5
<txt
8
11
12
size='30'>I'm
</root>
<additions>
<btn name='btnB' x='100' code='[rmv("btnB"),add("btnA")]'>
9
10
mouseEnabled='false'
</btn>
6
7
border='true'
A</txt>
<txt
border='true'
mouseEnabled='false'
size='30'>I'm
B</txt>
</btn>
</additions>
</config>
44
Let‟s run Example.swf again. As expected, on screen we can only see button A. Once clicked, button B
appears and A vanishes. After click on B, B disappears and button A is restored. Further sequences
give exactly the same results, it works! But how? Does it create new button every time?
The Registry
We‟ve used uncompiled ActionScript in button‟s code attribute to call two methods: add and rmv. From
“How to write ActionScript in XML attributes” we know, that default context for our commands is the
xRoot class. Both add and rmv methods indeed belong to API of this class. There are few variations of
add method but in general it follows the same scenario:
Adds one or more elements to display list. Searches through registry for already instantiated elements
of the same name first and adds it to display list if found. If not found, searches through additions node
for child with attribute name matching first argument value(s). If found in additions, instantiates and
adds object to display list.
There‟s just one but efficient enough rmv method and what it does is:
Removes elements from the display list. Searches through registry. Accepts arrays of display objects,
their names and mixes of it. Skips objects which are not part of the display list.
That‟s handy, we don‟t have to know where the actual object is, what is its parent, we can just remove it
by name, globally (provided that its name is unique).
They both mention registry object. What is it then? According to the documentation:
Registry is an associative array of all instantiated objects which can be identified by name attribute.
Multiple objects registered under the same name will cause registry to return only the most recently
registered one. Object registration is automatic but only within AXLX framework classes. Other ixDef
implementers can use XSupport class functions to register themselves or request change in registered
name.
Is it now clear how button A knew where to look for button B and opposite? Ok, fine. Caching objects.
For what else registry can be used? Literally for everything. Especially for references to any, even
outlying live elements of the project. It‟s way easier to say registry.tfSomething.text than
45
accessing it getChildAt(0).getChildAt(4).getChildAt(3).text way, isn‟t it? Registry, by
being proxy, flattens the structure in communication layer, completely. And if we don‟t want to make our
element able to reference through registry, encapsulate it a little? Then we just don‟t give a name our
object. Registry can also be used for other automated tasks like group animations.
Next to add, there are couple more API functions which check registry first, then additions node if not
found. One worth attention is executeFromXML.
Animations
Framework uses AO tweeining engine, which offers an API very similar to other market solutions like
GreenSock TweenLite, Gtween or Micro Tween. AXLX is designed to make every displayable object as
easy to animate as possible. For optimization purpose, all animations are set to be stopped
automatically when object is removed from stage.
meta variables, keywords
In general, tween definition are to be kept as meta object variables. These are expected to be arrays of
arguments for method animate function (excluding first argument, which is passed internally).
1
<div name='a' meta='{"addedToStage":[0.3,{"x":10}]}'/>
The shortest example of meta defined animation. Tweens object from whichever position to x 10 in
0.3sec every time object is added to stage.
One variable can contain more than one animation definition at the time. They shall be grouped in an
array. Adding break lines for readability is allowed.
1
<div name='a' meta='{
2
"addedToStage":[
3
[0.3,{"x":10}],
4
[0.6,{"y":20}],
5
[0.4,{"scaleX":3,"scaleY":3,"delay":1}]
6
7
]
}'/>
46
There are certain meta keywords for which animation definition is automatically recognized and
triggered without any manual calls. These are:
●
addedToStage (every time object is added to stage)
●
addChild, addChildAt (every time object is added to any ixDisplayContainer implementor
●
removeChild, removeChildAt (when object is about to remove, actual removal can be
automatically delayed by on remove animations). Even if object has on remove animation
defined, it can still be removed from display list instantly (without animation) if any of his
ancestors are removed.
meta variables, non keywords
Another way to animate objects is defining custom variables inside meta their object and triggering
these from API, on demand, anytime during runtime. Two top level functions to use in this case are:
●
animateAllRegisteredToScreen for group animations (whole registry is scanned for
objects containing that meta variable, every object matching it is animated)
●
singleAnimByMetaName for animating specific object defined by it‟s name or reference Nonkeywords animations are good for corresponding with states in your application.
●● <btn
1
name='submit'
code='animateAllRegisteredToScreen("STATE_SUBMITTED")' />
ui controller’s animations
Another type of animations available in the framework are the ones tied to pre-defined UI components.
For optimization purposes, there‟s limited access to it (no direct callbacks, no sequencing), but most
important things can be set up.
IMPLEMENTERS
<carouselSelectabl
e>
<msk>, <scrollBar>
ANIMATION RELATED PROPERTY
movementSpeed, easingType, onMovementComplete
controller.omitDraggingAnimation,
controller.animationTime,
controller.easing,
47
manual scripts
If you prefer to use tweening engine other, rough way, it‟s main animate function is exposed in top
level API, other are available by accessing full package to it (axl.utils.AO). You can also include any
other tweening engine to your project and bring it‟s API to top level by defining it in your root class.
Externalized animations
When dealing with complex timeline animations, proper art-work with shape morphing, tweening filters,
character‟s body animation and other frame by frame sequences scripting can become useless or
make the effort unreasonable. Quickly load exported animations and mock-ups as lightweight swfs with
<swf> tag and control it‟s playback via API. It‟s available to script these swfs too (access it‟s public
methods, properties, instances).
Network communication
For your back-end server communication is advised to build a proper API in your project. However
there are two main classes which are used all over the framework for two different aspect of
connectivity.
●
axl.utils.Ldr – for loading assets, resources, data feeds etc.
●
alx.utils.ConnectPHP – for making POST and GET requests. You can use this classes to
build your API solution quick or be creative with current solutions (meta.post, meta.url, meta.js).
Working with it
It‟s highly recommended to use AxlLoader application for your projects. It has built in development tools
such as display list editor which allows you to manipulate objects on screen easily, stand alone console
with command line and IDE style code completion, to view logs, script your project, see contents of
your registry etc., and moreover – reload takes less than quarter of the second, which comparing to
closing and opening or even worse: re-compiling project to see changes done to XML is a thunderbolt!
Examples, documentation, requirements
●
To see both AXL and AXLX in action visit examples page
●
Documentation is available under address http://axldns.com/docs/
●
Minimum Requirements are Adobe AIR or Flash Player 11.0
48
AxlLoader
49
Overview
AxlLoader is an AIR application (Windows, OSX) for opening swf files.
●
supports and speeds up development process
●
allows to preview network projects in local file system without IDE
●
contains number of dev-oriented tools, features and fascilities while still being small and fast
●
it‟s easy to integrate your projects with built in, powerful debugger
●
it‟s seamlessly updateable over the network
It‟s an official tool to support projects based on AXLX framework, but there are no technical limitations
to gain full benefits on any other projects*.
Download
INSTALLER
PORTABLE
Windows – installer
Windows – portable
OS X – installer
OS X – portable
AIR – universal
Opening files
There is a number of ways to load content in AxlLoader. Choose your favourite.
●
Drag and drop file onto application window or desktop icon
●
Associate files with AxlLoader – choose it as your default application for opening swf files
●
Copy file or link and paste it into main AxlLoader window
●
Use “Open” button on top bar menu
●
Use “History” button to navigate through previously loaded files, double click to load again
●
Use hot-keys to open files you loaded in the past
50
Hot Keys
AxlLoader is quite rich in hot keys. There are two groups it. First controls main application functions
(loading, reloading, bringing windows up/down). Second group gives directives to LiveArranger.
Main program shortcuts
HOT KEY
FUNCTION
ctrl/cmd + r
reload current file
ctrl/cmd + [0-9]
load file from history
ctrl/cmd + v
load file from clipboard
ctrl/cmd + l
show/hide top menu bar
ctrl/cmd + t
show/hide Timestamp Generator window
ctrl/cmd + f
show/hide FlashVars window
ctrl/cmd + shift + c
show/hide Console window
ctrl/cmd + shift + h
show/hide History window
LiveArranger shortcuts
HOT KEY
FUNCTION
F6
switches LiveArranger on/off
ESC
closes editor, if editor is closed, turns arranger off
Shift
changes selector style
Shift
+
multiplies movements by 5px
arrows
arrows
if focus is on selected object – moves selected object horizontally and vertically, if
51
focus is in editor input – increases and dis-creases numeric value or changes
Boolean flag
Z
(traverse up) sets parent of selected object as selected object if available
X
(traverse down) selects first child of selected object as selected object if available
1
(traverse side) selects another child(+1) in container of selected object if available
2
(traverse side) selects another child(-1) in container of selected object if available
PageUp,
PageDown,
opens/closes editor widget for selected object
Home
Press
and
If editor is off: allows to drag buttons preventing from executing their functions. If
hold CTRL or
editor is on: allows to select new object without exiting editor
CMD
Supported files
Despite the fact it‟s created to load flash files (swf), AxlLoader also provides primitive support for:
●
sounds – mp3, mpeg
●
images – png, jpg, gif
●
textual – xml, json, csv, txt
FlashVars
User defined FlashVars can be passed three ways.
●
paste links with query strings
●
manually – use built in FlashVars editor
●
semi-manually – drag-n‟drop JSON, XML or CSV file onto FlashVars editor
Aside from user defined parameters, there are three flash vars AxlLoader adds automatically:
●
fakeTimestamp – taken from top bar clock (great for spoofing server time)
●
loadedURL – an URL address of file that has been loaded
52
●
fileName – file name of loaded fileAll these three sources of flashvars (query defined, user
defined, built-in) are combined together (original URL is strpped) and passed to LoaderContext.
Top Bar Clock
Top Bar Clock is also interactive: mouse wheel and keyboard arrows can tweak the values, pressing
Enter key when focus is in any of its input fields reloads current content with new value of
fakeTimestamp. Just like clocks in Time Stamp Generator Window, it displays time in your local time
and generates Unix timestamp.
Timestamp Generator
AxlLoader provides built in utility for reading and generating timestamps. Small, separate, responsive
window helps you out with dates and times. Batch generation supports custom (user defined) time
format and locale. Generating is ruled by defining interval between start time and end time. All
timestamps are Unix timestamps, dates can be displayed both in UTC time and in user‟s local time.
Known issues
●
Problems with swfs with poor error handling. If flash project throws errors and exceptions from
the very first frame, it‟s quite likely AxlLoader and its fallbacks won‟t be able to handle it. By
default AxlLoader keeps content in non-html container (unlike Flash Pro, Adobe Animate).
Calling ExternalInterface.call without checking ExternalInterface.available is
most typical example of throwing exception AxlLoader struggles with.
●
Stage 3d projects support: LiveArranger does not support it, background covers it. Still able to
load, view, debug.
●
Fonts. Multiple swfs registering different fonts under the same name may cause rendering
wrong fonts. This requires application restart.
53