Sunday, October 13, 2013

Codea Build Machine

This is something I wanted to do for a long time: not having to go to my computer to compile and install my Codea projects, but still have my plug-and-play add-ons and resource files.

After a few days of work, I am quite happy with the results. I can now create a brand new project in Codea, export it, and after only a few minutes, I receive an e-mail to install it on my device, with add-ons like music automatically integrated for me.

Even if you don't have a Mac you can leave turned on all the time, if you turn it on when needed, the build machine saves a lot of time building an exported project and installing it on your device.

As an added bonus, since everything, including add-ons, is in the Cloud, it is possible to modify or even add new add-ons directly on the iPad (I use Textastic, but any code/text editor supporting your cloud application would work).

I'm pretty sure I'm not the only one who will greatly appreciate having a Codea build machine, so I made everything available on GitHub.

https://github.com/jfperusse/CodeaProjectBuilder

If anyone tries it, let me know how that goes so I can improve the scripts and documentation!

You can also find my add-ons on GitHub, more to come soon!

https://github.com/jfperusse/CodeaAddons

Here's a video showing an example project with mp3 playback built completely on the iPad.


Saturday, July 6, 2013

Codea AddOns Auto-Registration

I am currently enjoying one week of vacation and just spent some time building a proof-of-concept to show that Codea AddOns could be plug-and-play.

The idea is to be able to add plugin files to a newly exported Codea XCode project, build, and immediately have access to the AddOns without adding registration code to the AppDelegate.

Something we often have to do in Unity to avoid having to modifying the AppDelegate is to register for notifications like UIApplicationDidFinishLaunchingNotification in the class +load function, so I wanted to see if I could apply this concept to Codea. (see this)

The problem is that UIApplicationDidFinishLaunchingNotification will happen after the version found in AppDelegate.mm, after the Codea project has been loaded, which is too late to register AddOns.

However, I realized that we can manually send named notifications to classes. With this, I had all the puzzle pieces to build a plug-and-play solution.

Here's the simple change which would need to be added to Codea's default AppDelegate.mm file.

1:  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
2:  {  
3:    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  
4:    self.viewController = [[CodeaViewController alloc] init];  
5:      
6:    [[NSNotificationCenter defaultCenter] postNotificationName:@"RegisterAddOns"  
7:                              object:self];  
8:      
9:    NSString* projectPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"MyProject.codea"];  
10:      
11:    [self.viewController loadProjectAtPath:projectPath];  
12:      
13:    self.window.rootViewController = self.viewController;  
14:    [self.window makeKeyAndVisible];  
15:      
16:    return YES;  
17:  }  

Once we have this, AddOn code can register for the RegisterAddOns notification and do the AddOn registration at the correct time. Here's an example:

1:  #import "AppDelegate.h"  
2:  #import "CodeaViewController.h"  
3:  #import "CommonAddOn.h"  
4:  #import "lua.h"  
5:    
6:  static CommonAddOn *commonAddOn;  
7:    
8:  @implementation CommonAddOn  
9:    
10:  + (void) load  
11:  {  
12:    [[NSNotificationCenter defaultCenter] addObserver:self  
13:                         selector:@selector(registerAddOn:)  
14:                           name:@"RegisterAddOns"  
15:                          object:nil];  
16:  }  
17:    
18:  + (void) registerAddOn:(NSNotification *)notification  
19:  {  
20:    commonAddOn = [[CommonAddOn alloc] init];  
21:    CodeaViewController *viewController = (CodeaViewController*)[(AppDelegate*)[[UIApplication sharedApplication]delegate] viewController];  
22:    [viewController registerAddon:commonAddOn];  
23:  }  
24:    
25:  - (id)init  
26:  {  
27:    self = [super init];  
28:    

I tested this solution and it works perfectly fine.

Now, let's hope the RegisterAddOns notification is actually added to Codea so that everyone can benefit from plug-and-play AddOns!

You can find the add-ons I wrote using this method on GitHub. I plan on converting other add-ons as well in the near future (GameCenter, etc.)

https://github.com/jfperusse/CodeaAddons