Native Stack Overview
This section briefly explains the focus of each component of the DevKit and describes some of the important directories within them. Additionally the git repository for each component is included for reference.
Game Closure DevKit / Game Code
- git: devkit
- src: Contains the source of the code used to build the devkit tool.
- lib: Contains the source code for the Game Closure DevKit components.
- git: devkit-core
- native: This holds the js code used to communicate to and from native
- git: native-android, native-ios
- language: C++
- android:Tealeaf/jni/js: Directory containing the code to interface with the V8 interpreter.
- ios:tealeaf/js: Directory containing the code to interface with the Spidermonkey interpreter.
- git: native-core
- language: C/C++ directories:
- platform: Contains header files that are implemented differently per native platform.
- timestep: Directory containing code dealing specifically with the timestep game engine.
- git: native-android, native-ios
- language: C++, Objective C++
- android: Tealeaf/jni/platform: Directory containing code to interface between Android Java code, native code, and native core.
- iOS: tealeaf/platform: Directory containing code to interface between Objective-C code and native core.
Code to bridge the native core and the js-api with device specific code. On android this code is in C++ where as on iOS it is in Objective-C.
- git: native-android
- language: Java
Java code used to directly communicate with the Android OS and other device features.
Moving Around the Stack
The following is a brief overview on moving between the various regions in the DevKit stack. These boundaries exist because of the need to communicate between various programming languages and because they allow code reuse between different platforms.
Game Closure DevKit to/from Devkit-Core
Native-Core to/from Platform
Using code defined in platform headers, calls can be made into platform code so that it can be processed by the device. By keeping the headers separate from the definition the interface in core can be kept the same with different implementations per platform. For android the platform files are written in c++, whereas on iOS they are written in Objective c.
Platform to/from Java Code (Android Only)
Often code needs to be passed back to Java to interact directly with Android OS features. In Android, this is done using JNI calls which allow code to call from Java to C++ and C++ to Java. Within the Android platform code the
native_shim.cpp is an important file in this process.
Example: Playing a Sound
audiomanager.playwhich tries to play the required sound and we assume for this example it has not yet been loaded. Since we are running on a native device this means a call is made to
HTML5API.jsto start the loading process.
timestep/src/ui/backend/sound/HTML5API.js: This file represents an API for playing named sounds. In our example it will use the
Audio.jsclass in native to try and play the sound.
devkit-core/src/clientapi/native/Audio.js: Since the sound that is trying to be played has not yet been loaded it will be loaded by making a call to
native-android/TeaLeaf/jni/js/js_sound.cpp: This file contains the function
defLoadSoundwhich is ran when
sound_manager.cppin platform by calling
sound_manager_load_soundso that sound can be handled differently on iOS and Android.
native-android/TeaLeaf/jni/platform/sound_manager.cpp: Within this file a JNI call into java is made to
NativeShim.java: Within this file the sound being requested to load is placed on the sound queue by calling
SoundQueue.loadSoundwhich is processed in
SoundQueue.java: Within this file the
runfunction is ran on its own thread and it continually looks for events on the sound queue to process and will begin processing the newly added load event. The sound will be given to an instance of
SoundManagerto be loaded by calling
SoundManager.java: This is the file where sounds are actually loaded from the app or url. Within this file another
runfunction exists and is also ran on its own thread. The function runs continuously and checks for new sounds to load. Once the sound is loaded it adds a sound loaded event to
pushEventand are dispatched from the GLThread in Android in
dispatchEventsfunction is called on
EventQueueto send all events to native code through
dispatchEventsis declared in NativeShim.java and is called to dispatch the events to native code. The function is marked as native and is defined within the file
NativeShim.javais declared as
Java_com_tealeaf_NativeShim_dispatchEventswithin the native_shim. This c function is used to pass each event on the list to native core by calling
core_dispatch_eventfunction defined in
events.ctakes each event and makes a call to
NATIVE.events.dispatchEventwhich lives on the
devkit-core/src/clientapi/native/events.js: The call from native code ends up in the
events.jsfile which eventually sends the event to
devkit-core/src/native/soundLoading.js: Finally, the event makes it to the listener that was registered from with
soundLoading.js. This function takes the sound event and calls the
onLoadhandler associated with it.
While there may seem to be a lot of steps to loading a sound, the separation of concerns is important for maintaining a stable system that allows for code reuse.