Since version 2.1 cocos2d-iphone comes with ability to write code in JavaScript. This allows you to write your code once and then reuse the code with cocos2d-x or cococs2d-html5. All cocos2d nodes, CocosDension, CocosBuilder reader and Chipmunk are supported. But what about third parties? Do we need to rewrite other great libraries in JS to use them? No. And here jsbindings project comes for the rescue.
While official documentation is pretty good to get started, there are few pitfalls when using this tool in real project. So, lets explore the process of binding generation step by step and allow JS coders to use CCScrollView. At this tutorial we’ll explore automatic binding process and bind most of the CCScrollView methods to JS, next time we’ll focus on manual bindings and complete the rest.
Preparations
We will be using cocos2d-iphone 2.1-beta3. Download it and install Xcode templates if you haven’t yet. Create new “cocos2d iOS with JavaScript” project.
Next download CCBReader project and copy CCScrollView directory to libs
folder in your project (same directory that contains cocos2d, CocosDension and other 3rd party libraries).
Finally, download JSBindings 0.3 and place it
somewhere on your computer. In following examples I’ll assume that its installed in home directory. If you have
installed it somewhere else, don’t forget to replace ~/jsbingings
with your path when following further
instructions.
Step 1: gen_bridge_metadata
As documentation suggests, step 1 is generating bridge support files for your project. Open terminal in
YOUR_PROJECT/libs/CCScrollView
directory and execute following command:
1
|
|
BridgeSupport is an xml file that describes C functions, ObjC classes, methods and their parameters, etc.
gen_bridge_metadata
script uses libclang to parse Objective-C code and generate BridgeSupport files.
If you look carefully through generated file you’ll see the first problems: all cocos2d classes like CCNode
replaced with id
. To fix this you’ll need to tell gen_bridge_metadata
script to include cocos2d headers
in search path. The -c
options in above command allows to pass additional compiler arguments to libclang and
-I
compiler flag adds directory to compiler path. So, fixed version of the command will be:
1
|
|
Now BridgeSupport file should contain right types of parameters and properties.
Step 2: complement file
Second step is generating a complement file. Complement is a file with additional metadata not provided by BridgeSupport such as class hierarchy, protocols and properties. The command is:
1
|
|
Script will tell you that it completed successfully, but don’t trust him: if you open the file it generated you’ll see that it contains no data.
The problem is that CCScrollView files for some reason have Mac OS 9 line endings (CR) and generate_complement
scripts expects Unix (LF). We can fix either the script, or convert file line endings. I choose the second path.
Execute following commands from CCScrollView directory:
1 2 |
|
Let’s run a generate_complement
command again:
1 2 3 4 5 6 7 |
|
Now the problem is the following: to parse code generate_complement
uses set of regular expressions and they are
very specific about code formatting. Again, the solution would be either to patch utility (the ideal variant would
be using libclang instead of regexps) or fix the code formatting. Again, I choose the second variant.
Open CCScrollView.h header and find CCScrollViewDelegate
protocol declaration. Change it from this:
1 2 3 4 |
|
to this:
1
|
|
Then, change CCScrollView
class declaration from this:
1 2 |
|
to this:
1
|
|
Run the same command third time and you’ll finally get a complement file.
Step 3: Config file
Finally, lets write a config file and generate some bindings. Create CCScrollView.jsb.ini
file in
libs/CCScrollView
directory with a following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
Explanations:
- We tell generator to remove CC prefix from class names. Later, we will register binded class under
cc
namespace, soCCScrollView
will be accessible ascc.ScrollView
in JS code; - We tell that we already have manual bindings for
CCLayer
,CCNode
andNSObject
. Cocos2d bindings already covers this classes, but without this line generator will try to generate them again.manual
option prevents generator from this behaviour while still allowing remaining code to use this classes; - Generated bindings will inherit class methods from the base class until virst class constructor encoutered;
- All binding files will include two headers:
CCScrollView.h
to access our native class;js_bindings_cocos2d_ios_classes.h
to access bindings forCCLayer
,CCNode
andNSObject
.
- Two important things happens here:
- Diffrent name for the methods in JS is set using
name
option. This allows to use JS-friendly names in our script code and brings comatability with cocos2d-html5 implementation; - Multiple native methods are merged into single JS method using
merge
option. This makes sense for similar methods with different number of arguments. Glue code will choose appropriate native implementation based on the number of arguments passed to JS function. Note: method with largest number of argments should be on a left side of expression.
- Diffrent name for the methods in JS is set using
- Just rename a few methods to be compatable with HTML5 version;
- Don’t generate bindings for delegate getter and setter. Currently, jsbindings can’t generate glue code for
protocols. In the following article we change this setting to
manual
and write binding ourself, but for now we will just ignore the methods. - Tell generator that we’ll have manual bindings for
CGPoint
,CGRect
andCGSize
. Similar to the manual classes above, cocos2d will provide this bindings. Without this bindings properties of this types could not be set or read from JavaScript. - Setting the path to the BridgeSupport and complement files generated on previous steps.
Now lets run binding generator:
1 2 3 4 5 6 7 |
|
For some reason it reports ignored methods as errors. Looks like a bug in generate_js_bindings
script. Just
ignore this errors for now, correct binding files will be generated anyway.
Step 4: Registration file
Now we need to create a function that will register our bindings with JS engine. This part is done manually.
Create js_bindings_CCScrollView_registration.h
with the following content:
1 2 3 4 5 6 7 |
|
Create Create js_bindings_CCScrollView_registration.mm
with the following content:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Some knowledge of Spider Monkey API required to understand this code. We dive more deeply into JSAPI in the next article when we’ll be discussing manual bindings, now I give only breif explanation:
- Registration function receives two parameters:
- JSContext - central part of JSAPI. It maintains call stack, contains global object and required by almost every JSAPI function.
- Global object - object, that contains all other objects, avaliable to the scripts. For example,
window
inside web browser is a global object for it.
- Getting
cc
property from global object. This property is a namespace for cocos2d, it contains all other functions, classes and constants of the engine. We want to add ScrollView to the same namespace, so we need to get a reference to it. This code assumes that it will be called after cocos2d has been registered. - Now, we have a namespace property, but it can have value of any type in JS: number, string, object, etc.
Autegenerated registration functions require namespace to be an object named
CCScrollView
(generally, namespace variable should be the same as section header in config file). So, we convert the value to satisfy requirements. - Importing files with autegenrated functions that register all the classes.
Step 5: Adding files to a project
Open Xcode project and add following files to it:
* js_bindings_CCScrollView_classes.h
;
* js_bindings_CCScrollView_classes.mm
;
* js_bindings_CCScrollView_classes_registration.h
;
* js_bindings_CCScrollView_registration.mm
;
* js_bindings_CCScrollView_registration.mm
.
Open libs/jsbindings/src/manual/js_bindings_config.h
and add following lines to it:
1 2 3 |
|
This will enable compilation of our bindings.
Open libs/jsbindings/src/manual/js_bindings_core.mm
and add followig import to it:
1
|
|
Then find createRuntime
method and add following lines to it
after cocos2d registration:
1 2 3 |
|
Step 6: Constants file and test:
Add jsb_constants_ccscrollview.js file to resources of your application:
1 2 3 |
|
Its just the same constants that defined in CCScrollViewDirection
enum. jsbindings doesn’t support enums,
so all constants should be redefined in JS.
Now its time to test the results. Replace Resources/main.js
file content with the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
If everything was done right, you should see nice scrolling and bouncing gradient.
The end
First part of tutorial is over, code can be found on GitHub, but it uses different folder structure. Next time we’ll dive into manual binding process and allow CCScrollView to have JavaScript delegate.