A Raindrop for Acorn

CloudApp is one of my favorite tools for sharing images quickly, and I also use Acorn quite a bit for quick image editing tasks. I’ve been wanting a quick way to upload a snapshot of what I’ve got in Acorn using CloudApp, so tonight I wrote AcornRaindrop.

AcornRaindrop exports the active document in Acorn as a PNG and uploads it using CloudApp. It’s a Raindrop, which is a plugin for CloudApp. You can download it, or peruse the source on GitHub. It is made available under the MIT License.

Note that testing at this point has been ridiculously limited. It works for me; hopefully it will work for you too!

The implementation is rather simplistic: it uses osascript to instruct Acorn to export the active document, then passes the result along to CloudApp. My first attempt was using NSAppleScript, but for reasons I don’t fully understand it blocked for about 30 seconds while running the script, but only under CloudApp. Something to do with loading frameworks, perhaps? At any rate it runs quite quickly with osascript.

Happy CloudApp+Acorning!

v1.0.1, 1/18/2012: Gus Mueller was kind enough to contribute some changes demonstrating how to connect directly to Acorn using NSConnection, so the osascript call is now history. This allows AcornRaindrop to base the filename uploaded to CloudApp on the filename of the exported document.

Posted in Cocoa, Mac, Projects | Leave a comment

All Too Familiar

There was a post on The Guardian’s Technology Blog by Matthew Baxter-Reynolds last week. The piece couches itself as an overview of mobile platforms for the developer looking to get his or her feet wet.

Turning its attention to iOS, The Guardian cuts with broad strokes on Objective-C and Xcode (“horrendously, absolutely awful”), and then opines:

The fact is that if your day job involves sitting in Visual Studio writing C# applications, or building Java applications in Eclipse (which will be most of you — albeit not necessarily in Eclipse), when you fire up Apple’s Xcode and start building CocoaTouch applications in Objective-C you’re going to come face-to-face with a toolset that has not had the sort of love put into it that the open source community has put into the Java toolset and associate platforms, or that Microsoft has put into VS and .NET over the past 10 years.

Today, John Gruber replied:

Objective-C is different than C++ or Java. Xcode is different than Visual Studio or Eclipse, and Xcode 4 is very different from previous versions of Xcode. Baxter-Reynolds certainly wouldn’t be alone in saying that he doesn’t like these differences. But it’s curious to argue Apple developer tools and frameworks are deficient due to a lack of time put into them. In numerous ways, both linguistically and tools-wise, Xcode, Objective-C, and Cocoa/Cocoa Touch are the evolutionary descendants of the NeXT developer platform from 1989.

Both of them are right, and both of them are wrong. Baxter-Reynolds’ “horrendously, absolutely awful” comment is ordinary internet grandstanding (aka trolling). The iOS platform would not be where it is today if Objective-C and Xcode were horrendously awful. Part of the success of iOS is that it is the first great mobile development platform. I’d wager that Gruber is partially correct in thinking that Baxter-Reynolds’ viewpoint here is rooted in fear/dismissal of the unfamiliar.

Where Gruber is wrong, however, is in his own dismissal of Baxter-Reynolds’ argument as simple, again, fear of the unfamiliar. Before I landed my dream job writing Mac and iOS apps (at last!), I spent many years with Visual Studio writing C++ and later C#. And while Xcode has been improving by leaps and bounds, let me tell you: Microsoft has set the bar very high with Visual Studio.

Visual Studio excels in two areas: debugging and autocomplete. The Visual Studio debugger is blazing fast. Stepping through statements is super speedy, and the variables view would keep up without breaking a sweat. Xcode’s debugger has a tendency to take its time when stepping, and the variables view can be ridiculously finicky.

My perception is that part of this sluggishness has to do with gdb, and maybe lldb will help to improve this over time. If you’re thinking that debugger stepping speed is a petty thing, think again: just like responsiveness in iOS is clearly a big deal — something Apple has put a lot of energy into — so is responsiveness in a developer’s tools.

Xcode’s autocomplete has come a long, long way in the last couple years. However, it’s just not a fair fight against autocomplete with a strong typed language like C# or Java. Strong typing allows the IDE to provide fast, accurate autocomplete. With Objective-C’s dynamic typing, autocomplete becomes more of an art than a science. Additionally, the dot notation syntax of C# and Java give the IDE another leg up: the dot is the perfect cue to bring up autocomplete. Objective-C does not lend itself to this quite so easily.

As to the question of the amount of time put into Xcode versus Visual Studio, it’s worth pointing out that Apple’s Developer Tools team is almost certainly significantly smaller than Visual Studio team.

Xcode has come a long way, and it has one really amazing component — Instruments — that, as far as I know, Visual Studio doesn’t have anything close to (that isn’t a commercial add-on product). But Xcode is lacking in some key areas that can make a big difference in a developer’s perception of tool quality. I think it’s important that we, as proud Apple platform developers, are honest about that.

Posted in Opinion, Programming | 2 Comments

SwiftText 1.0

I’m pleased to announce the release of SwiftText, a text scratchpad app for Mac that makes itself available with a keyboard shortcut — and disappears just as quickly. It’s available now on the Mac App Store; you can see more screenshots on the SwiftText page.

Several months ago I needed an app just like this, but all of the possible solutions I found did too much. I simply wanted a lightweight app to pop up with a keystroke, let me type immediately, and get out of my way again with an escape when I was done. So I wrote SwiftText and found it useful enough that I figured there are probably other people out there with similar needs.

SwiftText is priced at US$1.99, but it’s available through April 8th at a special price of US$0.99. If you decide to give it a go, I hope you find it to be as useful as I have, and don’t be shy about sending your feedback (use the feedback tool in the app, or the address here). I have several ideas cooking for 1.1; I’d love to hear yours.

Posted in Mac | Tagged , | 1 Comment

Acorn + AppleScript: Adding a White Background

Say you have a lot of transparent images that you need to add a white background to. Flying Meat’s Acorn has some nice scripting bindings that are up to the task.

Not being a huge fan of AppleScript, I started out writing JSTalk inside an Automator task, but frankly I couldn’t figure out how to fill the new layer. Filling is, however, documented for AppleScript. I got an AppleScript version working, but quickly found that (at least on my system) running AppleScript inside Automator is very slow.

So I abandoned Automator and adapted that code to an AppleScript droplet. After saving it as an application from AppleScript Editor, I had a speedy app bundle that I could drop images on. Here’s the code:

on open input
    repeat with anImage in the input
        tell application "Acorn"
            open anImage as alias
            tell document 1
                duplicate layer 1
                fill with color (65535 & 65535 & 65535)
                merge visible layers
            end tell
            activate
        end tell
    end repeat
end open
Posted in Programming | Tagged , , | Leave a comment

Blanket Inquiry

Posted in Uncategorized | Tagged , | 1 Comment

From Blender to iPhone

My first iPhone game, Shufflepuck, was written in the dark ages — before the iPhone SDK was even available — and I modeled the 3D world using the tools I had: basic geometry equations applied to generate all of the vertices programmatically. And it worked! For a good while it was the sexiest table shuffleboard game on the App Store.

I was able to get by on programmatic models for that game, but if I wanted to be able to do something more interesting I was going to need to step things up. I write this now not as anything near an expert, but as a developer who has forced himself to wade into unfamiliar territory and figure out how to put the pieces together. My goal was to create a simple, textured model in a 3D modeling package and display that model in all of its textured glory on the iPhone.

Before I describe the steps I took, there is of course an easier path: using a game engine. There are several for iOS, most of them with their own model loaders and probably tutorials on how to do things end-to-end. For a few reasons, some more valid than others, I decided not to use any of these. They might make loading my textured model ridiculously easy, and there’s certainly value to that, but my research told me I could probably do it without them. Perhaps I just wanted a challenge.

Step 1: Learn Blender

Blender is a popular open source, cross-platform 3D modeling app. If your budget resembles mine, rockstar 3D apps like Autodesk’s Maya simply aren’t an option. So you will suffer with Blender, app of bewildering UI conventions. (I looked into Cheetah 3D briefly but at that stage I had already spent enough time with Blender that I thought there might be hope for it.) I used Blender 2.49b; it is my understanding that quite a bit has changed in 2.5x.

You don’t need to learn all of Blender before you export a model into your app. You just need to have a feeling for how to create objects, select vertices, move vertices, and so forth. Here are my recommendations on how to get there:

  1. Dust off your Mighty Mouse. The developers of Blender did not design it with your Magic Trackpad in mind.
  2. If at all possible, use a full size keyboard with a numeric keypad. The keypad is an important part of 3D view navigation.
  3. Force yourself to complete Unit 1 of Blender 3D: Noob to Pro, as well as Unit 2 sections 2A and 2B.

It will not be easy. Many times you will suspect that you will never feel comfortable in this unsettlingly open sourcy soup of window types and button panels. Particularly if you try to soldier on with your trackpad, as I did, unwarned.

Step 2: Learn Blender UV Map Basics

Now that you know your way around Blender (you do know how to create an icosphere and select a few of its vertices, yes?), skip to UV Map Basics, a later section of Noob to Pro. Frankly this section is not on the same quality level as prior sections, but I managed to cobble together some sense out of it.

Create a little Earth icosphere and setup the UV mapping as described. You should end up with a crude looking earth in Blender’s 3D view.

UV Mapping Earth in Blender 2.49b

Step 3: Get Jeff LaMarche’s Blender Objective-C Export Plugin

Next we need to get that Earth’s vertices, normals and UV texture coordinates out of Blender. There are two ways we could do this:

  1. Export the file as a common 3D object format, such as .obj. If we choose this route however we need some code to read that format in and turn it into vertices, normals, etc. Jeff LaMarche (iphonewavefrontloader) and Bill Dudney (link) have written code to do this, but it sounds like this is not the favored approach given differences in how normals are expressed (vertex vs surface).
  2. Use Blender’s Python API to export your models in a custom format.

Jeff LaMarche has created a script for Blender that does just this: it exports your object as an Objective-C header file. It is perhaps most conveniently used with his OpenGL ES project template, which provides the TexturedVertexData3D structure.

Copy the script in Blender’s scripts folder. On Mac you will find it in blender.app/Contents/MacOS/.blender/scripts. Unless you have Finder configured to show dot-files you can get there by opening the folder containing the Blender app bundle in Finder, then Shift-Command-G and enter the aforementioned path.

Now if you switch one of your Blender windows to “Scripts,” you will be able to click Scripts, Export, Objective-C Header and enter a .h file to save the currently selected object to.

Step 4: Incorporate The Model Into Your Project

You should now have a .h file, which contains the vertices, normals and texture coordinates for your icosphere, as well as a texture image, most likely of Earth.

If you followed the UV Map tutorial precisely, your texture image size will be 4096 x 2048, which is both quite large and not square. So you will need to make it smaller and squarer. I made a 1024×1024 texture. Keep in mind that texture coordinates are in the range 0.0-1.0, so when you make the texture square you will want to stretch it vertically so that the V texture coordinates are correct.

If you are using LaMarche’s template, edit GLViewController to:

  1. Instantiate the texture. You will only need to do this once:
    texture = [[OpenGLTexture3D alloc] initWithFilename:@"Earth.png"
                                                  width:0
                                                 height:0];
  2. Bind the texture and draw the vertices. You will find, at the bottom of the generated .h file, the lines necessary to draw the object. You may need to fiddle with the translate and scale values used here, depending on your object.
    - (void)drawView:(UIView *)theView
    {
        glColor4f(0.0, 0.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       
        glColor4f(1, 1, 1, 1);
        glEnable(GL_TEXTURE_2D);
        [self.earthTexture bind];
        glEnable(GL_CULL_FACE);
       
        glLoadIdentity();
        glTranslatef(0, 0, -2);
        glScalef(0.5, 0.5, 1);
       
        // Quick and dirty hack to make the model rotate:
        static float t = 0.0;
        glRotatef(t, 1, 1, 0);
        t += 1;
       
        // Drawing code from the header:
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        glVertexPointer(3, GL_FLOAT, sizeof(TexturedVertexData3D), &SphereVertexData[0].vertex);
        glNormalPointer(GL_FLOAT, sizeof(TexturedVertexData3D), &SphereVertexData[0].normal);
        glTexCoordPointer(2, GL_FLOAT, sizeof(TexturedVertexData3D), &SphereVertexData[0].texCoord);
        glDrawArrays(GL_TRIANGLES, 0, kSphereNumberOfVertices);
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
       
    }

Step 5: Enjoy

Textured model from Blender in iOS Simulator You should now have an Earth happily spinning away in your iOS Simulator; at right is my Earth.

1024×1024 is a pretty large texture; you should be able to get away with something smaller, depending on your application and how the model is used. (I chose that size because that’s what it took to look reasonable as a still.)

Hopefully you now have a pretty clear idea of how to use 3D models in your application. You can probably imagine some enhancements. For example, it would be nice to store models as app bundle resources rather than compiling them in as a header file. This is one of the nice things about Blender’s API: if you know a little Python you can write your own exporter.

Perhaps that will be the subject of my next blog post.

Posted in Cocoa | Tagged , , , | 6 Comments

Inheritance and Xcode Data Formatters

If you’re using data structures in your Xcode project and you’ve had to do any level of debugging, perhaps you’ve experimented with setting up Xcode Data Formatters. Data formatters determine what appears in the summary column of the debugger’s data outline view.

Data formatters are easy enough to setup for simple cases, but what if your classes are in a non-trivial arrangement — subclasses upon subclasses and so forth? Say all of the model objects in your application have the same base class, APModelObject, and on that object you have defined a name value, whose i-var name is mName. You configure a data formatter directly on APModelObject:

name=%mName%:s

Now you can easily see the name of any of your model objects by drilling down to the APModelObject superclass in the data outline. Which gets old. Very quickly. How can we see the name in our APModelObject subclasses? And their subclasses?

You might expect, as I did, that you can simply reference mName again. Unfortunately this gets us a grayed-out summary field, indicating that Xcode doesn’t like our data formatter. The answer is in the above document, disguised as guidance for C++ developers:

In C++, to access a member defined in the superclass of an object, the path to the member must include the name of the superclass. For example, %Superclass.x%.

Even though we’re writing Objective-C, let’s try it. In our APModelObject subclass (call it APDinner), we use this data formatter:

name=%APModelObject.mName%:s

And now we can see the name in that subclass. If we subclass APDinner with APTurkeyDinner, how do we see the name when debugging APTurkeyDinner? You might expect, as I did, to be able to reference the base class directly, but instead we must be very precise:

name=%APDinner.APModelObject.mName%:s

Setting all of this up gets rather tedious, but at least we only have to suffer through it once for each class. There is a slight shortcut, however. Let’s say that in APTurkeyDinner we only really care about the summary information for APDinner. Perhaps you’ve guessed that we can display its summary using this formatter in APTurkeyDinner:

%APDinner%:s

Now you know all you need to know to have a more pleasant debugging experience with your non-trivial models, be they dinner-themed or otherwise.

Posted in Cocoa | Tagged , | Leave a comment

A Manufacturer-Supported Pinball Mod Community

Pinball News has an interview with pinball player and Valve game designer Cayle George, in which he states:

One of the biggest things I think is missing from pinball, that is often encouraged in video games, is a mod community that is supported by game developers. Pinball manufacturers should make tools available to the public for modifying the rule set and code of their games. I truly understand the issues, problems, and liability questions this raises, but a successful community of end user game developers would help pinball grow beyond its current marketplace.

Cayle makes an interesting point. Independent mod communities such as P-ROC (with which I am involved) and FreeWPC exist and are showing signs of promise, but it sounds to me like Cayle is more interested in Stern Pinball supporting mods, which is an entirely different animal.

From time to time there is call on the newsgroups for Stern to open source its game software, usually with the suggestion that this is be a no-brainer. As far as I can tell this demand is mostly driven by game owners feeling that their game software as provided by Stern is incomplete (programmers pulled off the project before it is polished, or worse), and that if the source code were available somebody in the pinball community could enhance it.

Without any good information (I don’t know what Stern’s source code/OS looks like), I have a feeling that the chances that somebody in the community would be able to “finish” a game in a reasonable amount of time would be fairly slim, but it’s an interesting notion none the less. The minds of non-developers are prone to vastly oversimplify the amount of work required to make some modification, or add a mode. It’s one thing for a developer to write something new; it’s quite another to get inside another developer’s head and make modifications to their work, particularly in something like a pinball machine, and particularly when it probably wasn’t written with future developers in mind. Pinball software is done once, relatively speaking; there generally isn’t a “2.0″ a year or two later with new features that we see in the desktop app world.

Despite these challenges, I think there are three reasons Stern has yet to release their source code:

Support

New versions of game ROMs floating around has high potential to create a nightmare for Stern support. As we have experienced in the P-ROC project, pinball enthusiasts can have a difficult time grasping certain concepts, and as such I can easily imagine game owners running custom software and either not knowing that, or not understanding that this puts them in a position where their game is not supportable by Stern. Let alone fending off support calls from people trying to get the software tool chain setup, or having trouble getting their DMD images in the right format.

Money

It simply doesn’t make good business sense for Stern to do this. Even if they sold SDK licenses, my guess is that the positive impact on their balance sheet would be negligible. It just wouldn’t sell enough additional games. For a company with a product like Stern, open sourcing is a cultural decision, usually made with the understanding that there will be some cost associated, but that it’s worth it in order to suit the ideals of the owners. If we know anything about Stern it’s that they are about making and selling amusement devices, primarily to operators. Not creating warm fuzzies in the community. And they believe this is why they have survived. Why would they change? Why would they put money into creating the documentation to enable people in the community to meaningfully modify the software in their games?

Licenses

Stern does licensed games. My understanding is that various aspects of such games must be approved by the license-holder. I can’t imagine license-holders being too thrilled about the licensee supporting reworking of licensed assets (sound, music and video) outside of their control. Perhaps this could be overcome if Stern were to make an unlicensed title, but that would be at odds with past behavior.

I think it’s pretty clear that Cayle understands these issues too, and I should make it clear that while I think there are a lot of very good reasons for Stern not to do this (in addition to the question of whether developers in the community could do what other members of the community seem to think they can), I certainly wouldn’t complain if they or some other manufacturer did take a chance on this route. I could even see it as likely for a very small manufacturer, such as Snow Mountain Pinball, to try out. I do agree with Cayle that it would add some much-needed vitality to pinball.

Posted in Pinball | Leave a comment

Ripe for Domination: The Mac Twitter Client Market

I remember my excitement when Tweetie for Mac was released. On the Mac my Twitter client of choice was the website itself. I used Tweetie on the iPhone, but none of the available Mac clients matched my mental model of what a Twitter client should be. Tweetie for iPhone however was a perfect match. So when Tweetie for Mac became available and I saw that it had the same organization and similarly excellent visual treatments as Tweetie for iPhone, I wasted no time in purchasing my license.

Since its release Tweetie for Mac has become the dominant native Mac client, but the product has not aged well. Updates have been rare and largely focused on bug fixes (thankfully there have at least been those). But indications of the future growth of Tweetie for Mac have been even rarer still.

For me personally what has been most aggravating about Tweetie for Mac over time is its unflinching un-Mac-like-ness in the timeline. Have you ever tried to drag a URL from a tweet into Safari? Or use Snow Leopard’s new Services features to process text? Or get the definition of the word the mouse pointer is hovering over using Ctrl-Cmd-D? Tweetie for Mac draws its tweets as custom views and because of this implementation decision the user can’t take advantage of all of these great built-in features of Cocoa’s text system that are found in almost every application in the system — features that are a big part of what make Macs great. Instead, the users rely on the developer emulating these features as he has done (so far) with only text selection and URL-clicking. I appreciate the effort but emulating the correct behavior will forever be playing catch-up with the system controls.

Common keyboard shortcuts such as Fn-Up/Down Arrow (page up, page down) for navigation are missing as well — another conspicuous inconsistency. Perhaps you can see why the fact that Tweetie for Mac won the 2010 Ars Design Award for “Best Mac OS X User Experience” has mystified me.


Hibari 1.0, a new Mac Twitter client, was released today with various high profile links to it. It has a gorgeous website and attractive screenshots. As you can imagine I was excited to take it for a spin. After all, it has some great features: mute (a sort of silent unfollow), keyword block/filtering, individual tweet hiding and in-timeline conversation expansion.

While I am happy to find that Hibari 1.0′s timeline works just as a Mac user would expect with URL dragging, text services, and so forth, what’s puzzling about it is what it doesn’t offer:

  • You can’t use Hibari to follow new people or unfollow the tedious (@HibariApp was kind enough to respond to my question on this, explaining that they didn’t want to make the context menu any larger).
  • Clicking on any @name opens the user’s Twitter page in your web browser, which is very jarring if you’re accustomed to Tweetie for Mac’s ability to view any user’s tweets without switching apps. An unfortunate side effect of this is that you can only use the in-timeline conversation expansion on your own conversations; if you want to jump into another conversation you’re on your own.
  • Most frustrating, Hibari doesn’t hold your position in the scroll view as new tweets appear. Instead it always shows the most recent tweets in your timeline. (Update: @HibariApp informs us that this is on the way.)

Initially I was very put off that these features were missing. After all, it’s Hibari 1.0. Not 0.9, not Beta 3, but one-point-oh. Calling a product “1.0″ and accepting money for licenses signals to the customer that the product is Capital R Ready. You probably have a number of features sketched out for subsequent revisions, but you have presumably included all of the features you view as necessary to use the product. We can only assume that Hibari’s developer, Victoria Wang, did not view these features as necessary.

I qualified the sentence above with “Initially” because as I re-surveyed the top Twitter clients for Mac in writing this article, I realized how unique portions of Tweetie for Mac are. Neither Hibari, Twitterific nor Bluebird (1.0 Beta 3) support viewing an arbitrary user’s tweets. None of them support managing your follow/unfollow status, either. They are focused only on viewing the contents of your timeline, your mentions, and your direct messages.

What I find most disappointing about Hibari is that it has made its 1.0 splash demonstrating some great new features, but it lacks features that Tweetie (and other iPhone clients) have made users like me consider standard. Standard to the point that we will continue using Tweetie (despite its significant flaws) and hopefully check in again on Hibari once it reaches 2.0. As much as I would like to see these features in Hibari sooner than later, I would rather they be designed with the same care that seems to have been taken with the rest of the application.


Today the Mac Twitter client market is Tweetie’s to lose. Hibari shows promise with its filtering preferences but set its sights below providing what I would describe as a complete Twitter client. The draw of Tweetie is not just that it provides a pleasant way to keep up-to-date on my Twitter timeline, but that it provides me with the way I like to consume Twitter best, end-to-end. This is the potential power any native Mac client, for any service. Tweetie has shown us what’s possible; its languishment has been and continues to be a talented developer’s golden opportunity.

Update 9/21/2010: Evan Williams has stated: “We have no plans for an [sic] “official” desktop clients,” which doesn’t seem particularly encouraging for Tweetie’s future.

Posted in Mac, Opinion | Tagged , , , | 3 Comments

Tip of the Hat

I saw (via Kottke) that Steve Carrell says he will be leaving The Office at the conclusion of the seventh season. As someone who was a fan of the original The Office (the British one, you know) and who was dismayed to learn that The Office was coming to NBC (Are there no good, original ideas for shows waiting to be made? Are we so devoid of creativity that we have to adapt every hit BBC show?), and who, after several years, came to have a certain level of respect for the new adaptation The Office, I am happy to read this news. Not that I had reason to suspect otherwise, but I’m glad somebody over here knows how to quit when you’re ahead.

Part of the charm of the original The Office, part of what made it special, was that it was comprised of two seasons, a wonderful “Christmas special” tying up some loose ends, and poof. The End. Very neat, very very good, and complete. When every indication is that content creators cannot let go of anything, that every property must be propped up again and again for milking (c.f. endless classic movie remakes, even prequels to long-thought-complete trilogies, etc.), it is refreshing to see a message that’s all too rare: My work here is done; it’s time for something new.

Posted in Opinion | Leave a comment