BHColourPicker!

May 29th, 2009 § Comments Off on BHColourPicker! § permalink

It’s generally usable now, so I’ve decided to release it, warts and all. I’ve created a Google Code project for it, bhcolourpicker, where ‘bh’ stands for ‘bunnyhero’ :)

It’s not particularly well-documented at the moment, but that will (hopefully) change.

Here’s an excerpt from the HowTo page on the project site:

To show the colour picker, use code something like the following:

    //  since it has 'new' in the method name, you own it...
    BHColourPickerController *vc = [BHColourPickerController newColourPickerController];
    vc.delegate = self;                    // the delegate
    vc.colour = self.view.backgroundColor; // the initial colour
    vc.titleText = @"Some kind of title";  // title to display
    [self presentModalViewController:vc animated:YES];
    [vc release];   //  ...and must release it

You must implement the BHColourPickerControllerDelegate protocol in one of your objects. Implement the following two methods (with examples):

- (void)colourPickerControllerDidCancel:(BHColourPickerController *)controller
{
    // the user just cancelled it; put the picker away
    [self dismissModalViewControllerAnimated:YES];
}
 
- (void)colourPickerController:(BHColourPickerController *)controller didFinishPickingColour:(UIColor *)colour
{
    // the user confirmed a colour; do something with it
    self.view.backgroundColor = colour;
    // and put the picker away
    [self dismissModalViewControllerAnimated:YES];
}

I’ve released it under a New BSD Licence. Share and enjoy!

Colour picker in progress

May 23rd, 2009 § 1 comment § permalink

This isn’t quite done yet, but I am working on a colour picker for iPhone. I plan to release it under the MIT Licence when I’m ready. I’m fairly shy about open-sourcing my code, I’m always embarrassed about the quality…

Till then, here’s a screenshot:
iPhone colour picker

Note to myself: OpenGL gotchas

May 10th, 2009 § Comments Off on Note to myself: OpenGL gotchas § permalink

Not so much “gotchas” as “got-me”s, probably. It’s been so long since I’ve done any significant OpenGL coding that I keep forgetting little things that result in a blank screen or a white texture :) Anyway, I thought I’d record them here to remind myself.

Note that I’m currently using OpenGL for 2D drawing.

  • Set glTexParameter for GL_TEXTURE_MIN_FILTER to something like GL_LINEAR before calling glTexture2D. The default value for GL_TEXTURE_MIN_FILTER is GL_NEAREST_MIPMAP_LINEAR, and if you’re not using mipmaps, the texture won’t draw!
  • I forgot that glOrtho manipulates the current matrix. Which means that if you don’t call glLoadIdentity beforehand you might not be getting the projection matrix you were hoping for!
  • This one was particularly boneheaded :P Make sure that the type parameter in glTexCoordPointer is actually the same type as the array! As in, if you pass in a pointer to an array of floats, make sure that the type parameter is set to GL_FLOAT. I blame this one on copy/pasting without paying enough attention.

Well that’s enough embarrassment for today. And I also just found this article: Avoiding 16 Common OpenGL Pitfalls, which looks useful…

EDIT: Just needed to mention another oversight that had me scratching my head for a while when things weren’t rendering as expected. Note the difference between the GL constants GL_TEXTURE and GL_TEXTURE_2D! Use the former for the parameter to glMatrixMode. Use the latter for enabling/disable texturing with glEnable/glDisable!

Too many monkeys! A newbie lesson about viewDidLoad:

March 23rd, 2009 § Comments Off on Too many monkeys! A newbie lesson about viewDidLoad: § permalink

I recently learned another important newbie lesson about viewDidLoad: : it may be called multiple times during your application’s lifetime for any given UIViewController if its view is ever hidden and shown during low-memory situations.

Here’s the story: I am currently making a monkey app which features a single monkey. It was running fine in the simulator, but sometimes when I ran it on the device, an extra monkey was spawned every time I switched between the main view and the settings view! A couple of view switches and I’d have a bunch of monkeys onscreen, which was amusing but also very slow and not what was intended. Who was making the new monkeys?

My first iPhone test apps did a lot of initialization in viewDidLoad:. It makes sense because it is called right after a view has finished loading from its nib, and it feels like a good time to do your final initialization of things since the system has basically done everything it needs to do to display a window.

What I forgot was that the default behaviour of UIViewController didReceiveMemoryWarning is to release its view if it’s currently hidden (due to navigation, say). All well and good. But when the view becomes visible again, the view will be reloaded from its nib, and viewDidLoad: will be called again.

This is why I kept getting new monkeys: I was making the monkey in my MainViewController‘s viewDidLoad:. When I switched to the settings view when memory was short, the MainViewController purged its view. Switching back to the main view caused the MainViewController to reload the view from the nib, thus calling viewDidLoad: again, and thus creating another monkey.

So, any initialization code that goes into viewDidLoad: should make sense in that situation: i.e. view-specific stuff when recreating the UIView object, not application-level initialization stuff. Or, if your app-level initialization stuff needs a view to be loaded before running, then at least check to make sure that it hasn’t run already.

iPhone newbie lessons

March 20th, 2009 § Comments Off on iPhone newbie lessons § permalink

It’s been a long time since I messed around with Objective-C, even a little bit.

A couple of things that have bitten me lately:

  • @selector(apply:) is different than @selector(apply)! Note the lack of a colon in the second one. The colon means that there is one parameter to be passed with the message. No colon, no parameter. This makes a big difference when passing a selector as an argument to something like NSArray makeObjectsPerformSelector:.
  • I keep forgetting to pass nil as the terminating argument to methods like NSArray initWithObjects:. Forgetting the terminating nil will cause the iPhone to crash with a Bad Access exception as it runs off the end of the stack into the weeds.

And one very valuable debugging tip I found here:
how to find out what exception was thrown in the Xcode debugger. When an uncaught exception kills your iPhone app, Xcode doesn’t really have much information at that point. To remedy that, go to Run -> Show -> Breakpoints and in the Breakpoints window double-click on the entry that says “Double-Click for Symbol.” Enter “objc_exception_throw” and press Return. Now, when you run your app in the debugger, any exception will stop there and let you see the exception type.

Beginning iPhone development

March 13th, 2009 § Comments Off on Beginning iPhone development § permalink

I’ve just started to develop for the iPhone. I have the SDK and have joined the developer program. The last time I did any Objective-C was about 8 years ago, and that was just dabbling, too.

I will probably try to port one or two of my pets over to the iPhone, although the audience for iPhone apps is probably a lot different than the audience for MySpace Flash widgets (then again, with the prevalence of Fart apps on the iPhone app store, who knows?). Regardless, I’m hoping it will still be a good exercise.

Rename an element across all frames of a timeline

February 27th, 2009 § Comments Off on Rename an element across all frames of a timeline § permalink

I use a combination of timeline animation and scripting-based movement. All too often, I will create a timeline animation and only later realize that I need to give a MovieClip (or MovieClips) a name so I can refer to it from a script. Of course, this only happens after I’ve already created a zillion keyframes, and going through the entire animation to make sure that each MovieClip has its proper name in each keyframe is a real pain.

I finally got around to creating a simple JSFL script to automate this. It’s nothing special and it doesn’t do much error-checking or anything, but I thought I’d share it regardless in case it helps someone else :)

Copy and paste the following code into a file with the extension “.jsfl” (for example, “Multiframe renamer.jsfl”). Save the file in the appropriate folder, based on your platform:

  • Windows Vista™:
    boot drive\Users\username\Local Settings\Application Data\Adobe\Flash CS3\language\Configuration\Commands\
  • Windows® XP:
    boot drive\Documents and Settings\username\Local Settings\Application Data\Adobe\Flash CS3\language\Configuration\Commands\
  • Mac OS® X:
    Macintosh HD/Users/username/Library/Application Support/Adobe/Flash CS3/language/Configuration/Commands/

and restart Flash.

Then, in your document, select the element you want to be renamed across all frames. The go to the “Commands” menu and choose “Multiframe renamer”. You will be prompted to enter a name for the element (press “Cancel” to abort), and it will go and rename that element across all keyframes in that layer.

No warranty, use at your own risk, etc., but feel free to share and improve on it :)

/* multiframe renamer */
 
go();
 
 
function go()
{
    if ( ! fl.getDocumentDOM() || fl.getDocumentDOM().selection.length == 0) {
        alert("Please select an element");
        return false;
    }
    var element = fl.getDocumentDOM().selection[0];
    //  use the element's current name as the default
    var name = prompt("New name for elements on this layer?", element.name);
    if (name == null) {
        alert("Cancelled by user");
        return false;
    }
 
    var timeline = fl.getDocumentDOM().getTimeline();
 
    //  find the layer from the selection
    var layer = element.layer;
 
    //  all frames in this layer... rename first element to the name
    for (var i = 0; i < layer.frames.length; i++) {
        if (layer.frames[i].startFrame == i) {
            if (layer.frames[i].elements && layer.frames[i].elements.length > 0) {
                layer.frames[i].elements[0].name = name;
            }
        }
    }
 
    alert("Done!")
    return true;
}

Flash CS3 top-left redux

February 11th, 2009 § Comments Off on Flash CS3 top-left redux § permalink

Last May, I complained about the change in the “Info” panel from Flash MX 2004 to Flash CS3. Since I needed the functionality, I whipped up a very simple (and crude) panel to let me see and edit the top-left of an element.

Download the compiled panel and the source code.

topLeft

As you can see, it’s very primitive. Select the element you want to operate on, and click “Get topLeft” to read the values of its top and left bounds. Click “Set topLeft” to move the selected element.

This comes in handy for changing a MovieClip’s registration point while leaving its visual position intact. Select a MovieClip instance, click “Get topLeft,” then edit the MovieClip and slide its contents around so that the registration point is where you want. Exit MovieClip editing, then click “Set topLeft” (without changing the values in the edit fields). The instance will go back to its original visual position.

Flash CS4: styling device fonts in the IDE?

February 8th, 2009 § Comments Off on Flash CS4: styling device fonts in the IDE? § permalink

In Flash CS3, I could use the IDE to create a text field whose font was “bold _sans” (_sans, of course, being the “generic” sans-serif device font).

However, in Flash CS4, it seems I cannot do this, as the style menu is empty and disabled when any of the generic fonts are selected (or if “Use device fonts” is chosen). I can make a _sans text field, but not a bold or italic one.

It is still possible to apply the styling at runtime, but I shouldn’t have to do that.

Is there something I am missing?

The 4 things about UserVoice that drive me @#$%! insane

January 26th, 2009 § 3 comments § permalink

I don’t normally blog about sites that I find frustrating–it’s generally not worth the effort. But since both TweetDeck and Twhirl use UserVoice for customer feedback, I end up using it far more than I want to, and thus the frustrations build. I must vent!
» Read the rest of this entry «