Zooming & centering using Flash’s annoying ScrollPane

May 11, 2006

In the old Flash (the first version of MX) the FScrollPane component had a nice setScrollPosition function, with which one could set the position of the movie clip inside. This function no longer exists in the whizzy Flash 8 environment; it’s been replaced with ScrollPane, which has a much more obscure functionality, with the properties hPosition and vPosition. The documentation for hPosition states:

Property; the pixel position of the scroll pane’s horizontal scroll box (thumb). The 0 position is at the extreme left end of the scroll track, which causes the left edge of the scroll pane content to be visible in the scroll pane.

Liars! It’s nothing of the sort. hPosition does not descibe the scroll bars, it describes the horizontal position of the movieclip inside the pane; it is the amount the top-left corner of the clip is displaced to the left of the top-left corner of the pane. This is slightly confusing: Flash works on a rightwards-positive co-ordinate system, yet hPosition is always positive. Similarly, vPosition described displacement upwards, not downwards.

Anyway, with that confusion over, we can get something done. Let’s say we’re zooming into the clip by doubling its size, but we want to keep the display currently centered upon where we are. In the co-ordinate space of the movie clip (not the pane), where (0,0) is the top left corner of the clip, and the clip is currently displaced to the left by hPosition, then the x co-ordinate of the centre of the pane XC can be found by:

XC = hPosition + pane_mc.width/2

Doubling the clip in size will result in the co-ordinate of the new centre XC’ being twice that of the original. So we need to find the new displacement hPosition’

XC’ = 2XC
hPosition’ + pane_mc.width/2 = 2*(hPosition + pane_mc.width/2)
hPosition’ = 2*hPosition + pane_mc.width/2

Which means the following code will successfully zoom & center our clip:

// Scale our object
clip._xscale *= 2;
clip._yscale *= 2;

// New offset
var hPos = 2*scrollPane.hPosition + scrollPane.width/2;
var vPos = 2*scrollPane.vPosition + scrollPane.height/2;

// Refresh the pane to auto-add scrollbars
scrollPane.setSize(scrollPane.width, scrollPane.height);

// Set the new positions
scrollPane.hPosition = hPos;
scrollPane.vPosition = vPos;

You’ll need some extra code to deal with the clip not shifting outside the pane when you zoom back out again (which can happen) but this is trivial checking of bounds. Now you can use Flash’s ScrollPane to display zoomable clips (such as maps…)

Ming and version numbers

May 3, 2006

Ming has an obscure and not very well-documented function Ming_useSWFVersion() which can come in handy. In Ming 0.4.0, it defaults to Flash 5 SWF. This means if you want to add Flash 6+ functionality to your created SWF (e.g. you want to incorporate an onRollOver event function on an SWFSprite) from externally, it will not react. However, you can use the above function to set the version, e.g. (in Python, as always):

import ming

However, this creates what surely must be a bug. If you try adding code to a SWFSprite that uses the keyword this then the Ming ActionScript compiler throws an error, saying it does not recognise it. For me, this code does not work:

my_mc.add(SWFAction("this.onRelease = function() { trace('foo'); };"))

Luckily, I think you can miss out the this without too much worry, as Flash’s scoping usually picks up local variables first. If you really need it, you can always use eval to do:

  "t = eval('this'); t.onRelease = function() { trace('foo'); };"

and this compiles satisfactorily.

Remember to use nextFrame() when adding code and shapes to SWFSprites

May 2, 2006

In Ming, when working with SWFSprite objects (i.e. Flash MovieClips), you will often want to add in code and shape data to the sprite. When doing so, remember to “commit” the additions you make by calling nextFrame(), else nothing will appear. So, in Python, you would do something like:

clip = SWFMovie()
clip_shape = SWFShape()
clip_action = SWFAction("this.foo = bar;")

Thus the additions get properly “saved” into the object. This potential pitfall is also covered on page 4 of the Ming tutorial but it doesn’t hurt to have it written down twice.

Compiling Ming for Python on Windows

April 26, 2006

Ming is a highly useful open-source Flash SWF writer that I am using in creating a Flash mapping application. However, it is only available as C source code and not Windows binaries, which is a pain if (like me) you work with an exclusively Windows-only environment and you have no Linux resources to hand. Trying to compile it can be a pain; the Windows environment is demanding enough, and it can be especially for Windows regulars who aren’t used to mucking around with Linux. To make it worse, there is precious little documentation around for it. So, for the benefit of anyone else interested in the same, here is how I managed to get the Ming modules for Python to work in Windows

1. Download & install Python 2.4 for Windows in e.g. c:/python
2. Download & install Cygwin in e.g. c:/cygwin. This provides you with a shell and other tools. When it comes to picking the modules and applications to use, add in autoconf, bison and flex. Do not install gcc or make – these are taken care of in the next step.
3. Download & install MinGW in e.g. c:/mingw. MinGW is not Ming – MinGW is an entirely different application takes care of the compilation.
4. Download the MinGW-zlib library. Copy the two .h files in usr/include/mingw to c:/mingw/include
5. Copy the file libpython24.a from c:/python/libs to c:/mingw/lib.
6. Download & install the Ming source code, in e.g. c:/ming
7. Download the source code for zlib. Copy the files zlib.h and zconf.h into c:/ming/src
8. Fire up Cygwin and go into the ming directory (e.g. cd /cygdrive/c/ming)
9. Type the following commands:

  $ autoconfig
  $ ./configure
  $ cd src
  $ mingw32-make static
  $ cd ..
  $ ls libming.a

10. A file called libming.a should now exist. Type cd py_ext and press ENTER.
11. In this folder, there should be a file setup.py. Open it, delete the existing code and replace it with:

from distutils.core import setup, Extension

setup(name = "mingc",
      version = "0.4",
      description = "A library for creating Flash files",
      py_modules = ['ming', 'mingc'],
      ext_modules = [Extension(name="_mingc",
                               include_dirs=['/usr/local/include', '../src'],
                               library_dirs=['/usr/local/lib', '..'],

12. Run the following command:

$ ../../python/python setup.py build --compiler=mingw32

(The path to your python instance may be different from the above)
13. In the folder build/lib.win32-2.4 there should now be a spanking new file _mingc.pyd.
14. You can test this by moving the file _mingc.pyd up two levels, in the same folder as shape.py, then running:

$ ../../Python/python shape.py

15. This should have created an SWF called test.swf, which consists of a red quarter-circle with a grey border.

References: When coming up with the above, I found this newsgroup post and this MinGW introduction page useful resources.