Table of Contents
Directory organization
The Proton SDK directory is setup like this:
install dir shared (source/libs shared between projects go here) RTBareBones (an app project directory) RTSimpleApp (an app project directory) your own app (put your stuff here too)
Everything that is shared between apps is in the “shared” directory.
When editing something in the “shared” directory, be careful because you could break other apps.
Projects are setup to use relative paths. This means you can cut and paste your main proton directory to another location and your projects will still compile with MSVC, Xcode, and to WebOS. Android compiles actually needs a few hardcoded paths setup right now so that part isn't perfect.
Each project directory is setup like this:
app dir source (app source code goes here) media (raw media, iphone icons and splash go here, "update_media.bat" is here, it processes and copies media to bin) bin (final windows binary and media goes here - this is where you would zip to give your windows version of the game to someone) Press And Docs (a good place to put screenshots and such, not really needed) script (.bat files that do things like make zips and upload to ftp sites, probably not useful to you) windows (MSVC solution/projects go here) OSX (Mac OS X xCode project goes in here) android (all android related things go here) WebOS (Palm WebOS related things go here) bbx (RIM playbook related things go here) linux (for linux makefiles, etc) In the main app dir there is also some iOS stuff: (Hmm, I should have put it in an iOS dir but meh, this is how the framework evolved) app name.xcodeproj (a file: you open this with xcode) Info.plist MainWindow.xib dist.plist
BaseApp.cpp and App.cpp
All apps have an App.h/App.cpp in their app/source directory. This subclasses BaseApp.cpp which is from the shared source dir.
Non-app specific code will use GetBaseApp() to access your App object using the BaseApp interface. You can do that as well, or use GetApp(), which will let you access your subclassed functions and variables as well. (They both point to the same class instance)
Shared files like main.cpp and main.mm are only glue to let Proton work across platforms. Think of App as the top level of your app where things should happen.
Signals and slots
Back in the day some smart guy figured out that instead of polling all the time, we could just connect a wire to an event (a signal) and the other end to a function that gets called. (a slot)
It allows app level functions to “connect” themselves to get notified when certain events happen.
Sadly, the code to make this work is slightly ugly and cryptic so there is a bit of a learning curve on using them. Just copy from places that work or check out the boost.signals docs.
Here is a real example of usage:
RTFont needs to know when surfaces are lost (for instance, when switching to another task in Android 1.6) and when to reload them. BaseApp offers many “signals” to connect to and this is one of them.
A signal can be connected to a function (SomeFunc(), or a class function of a specific instantiated instance. (MyObject::SomeFunc())
Code in RTFont:
//this is the function we want to get called void RTFont::OnLoadSurfaces() { ReloadFontTextureOnly(); } //... in RTFont's init code somewhere... //connect to the signal so our "OnLoadSurfaces" will get called GetBaseApp()->m_sig_loadSurfaces.connect(1, boost::bind(&RTFont::OnLoadSurfaces, this));
Makes sense (despite that weird bind stuff), right? If you have five font objects, all five will connect and be notified by the same signal.
Or, if you wanted a plain old function to be called when this happens you could do:
void SomeCrapFunction() { LogMsg("Woo"); } GetBaseApp()->m_sig_loadSurfaces.connect(&SomeCrapFunction);
That's simpler. A beautiful thing about these virtuals “wires” is if one end dies (an object is destroyed for instance), the wire is automatically disconnected and you don't have to worry about it.
If you're thinking, “so what, it's just a replacement for polling a message pump”, you still don't know the powah of the sigslot side <cackle>!
- Entities can create their own named signals and slots dynamically, on the fly
- MessageManager can schedule slots to be called in the future
- You can have a function called when a Variant variable changes
We'll get into it later, but it will totally rock your programming world.