Betray is the main platform abstraction layer that lets you open a window that you can draw to and access user input, and other operat ing system specific functionality. Betray is designed to be implemented on any kind of polatform that supports some form of OpenGL (It would be popssibble to extend its capabilities to other graphics APIS too), it is therefor similar to GLUT and SDL.
One of the main design goals with betray is to make it possible to write an applications that makes use of many different types of hardware setups, so that a single codebase can run on different hardware. If utilized corrrectly a single Betray application should be able to run on everything from a phone, to a laptop all the way to a sterioscopic headmounted display, or a multi user wall. The api is designed to try tto reduce the ammount of query needed to make the application run well on any hardware. For instance, all pointers are the same indipendently of if they are created using touch or one or more mice. The same goes for buttons and axis input. It is obviusly recomended that you try to test your application with as many different hardware setups as possible.
Betray is designed to be compiled in to any project, and therfore needs to be small, lightweight and not have any dependencies. On the other hand it is decirable for Betray to have as many dependencies to as many Hardware SDKs as possible in order to support a wide set of hardware. In order to solve this hardware paradox, Betray uses "imagine" to create a blugin interface where plugings can add functionality to betray. This way application developers can focus on building applications, and people who are interested in supporting hardware can write plugins that add functionality to Betray applications. Some functionality in Betrays API doesnt do anything until a plugin is present to provide the functionality (Like sound). A plugin can also expose settings to the applications using the settings API. If you are interested in writing a plugin for Betray, check out the separate betray_plugin_api.h.
Betray supports multi user inputs. This may be multiple game controlers, or more exotic setups like multi user multi touch walls. For most uses this does not matter to a developer, but in some cases (like matching a specific pointer activating a type-in feild to a specific keyboard) developers may want to take this in to account. All UI ellements in Seduce supports this.
The main loop:
In order to start betray and open a window the application needs to call betray_init, but this does not start the applications main loop. In order to start the main loop you first need to give betray a function pointer to call as the main loop using betray_action_func_set and then call betray_launch_main_loop to launch the application main loop. If the window is closed, the betray_launch_main_loop function will return. When the main loop is called it gets called with a pointer to a structure named BInputState. This read only structure contains a lot of information about the current state, such as pointer positions and events. One of the most important parameters of this structure is "mode" that describes why the function was called. It can be either BAM_DRAW because the application is asked to redraw the graphics, BAM_EVENT because the application needs to respond to incomming events, or BAM_MAIN because time has elapsed. Ofther all three are cvalled for each frame, but this is not always the case. BAM_DRAW may not be called if the application is minimized, but can also be called multiple times for each frame to support thinjgs like sterioscopic rendering. The application can read out the parameter draw_id and draw_count in order to know how many draw calls are expected and what call is currently being requested. This is very useful since you may for instance only want to calculate shadow buffers once even if you are drawing two different outputs. For multi drawcals to work propperly it is important to make use of betray_view_vantage and betray_view_direction. BAM_EVENT may only be called if there are any input events worth prosessing, but should always call at least twice after any event due to the design of the pointer and key events. BAM_MAIN is always called even if the application is minimized. This makes it useful for things like processing and network tradfic.
The main design goal of using the same callback for all three calls is that it makes easy to implement high level widgets that, by taking the BInputStruct as a parameter can themselves figure out what to do. For exammple one may implement a function like:
booelan my_button(BInputState *input, float pos_x, float pos_y);
This function can now either draw a button, or detect if the button is being pressed separatly. The user do not have to describe the button more then once even if the button functionaly does two diffferent things. The UI library Seduce is built entierly arround this concept.
A simple sample program using betray is included in the source package and is called betray_test.c. This example uses desktop OpenGL. A different sample program called betray_relinquish_test.c uses the relinquish rendering wrapper and is therefore compatible with OpenGL ES 2.0
Betray depends on Forge, Imagine, and OpenGL.
Betray is currently implemented for windows (both 32 and 64 bit) and a iOS port exists (with less functionality obviusly). My plan is to port the layer to other platforms in the future. If you are interested in helping me let me know.
- Functionality query
- Display Functionality
- Main loop
- Mouse Warp
- File requesters
- Clip board
- Button and key
- Sound Clip
- Sound Stream
- Sound Listener
- Sound Listener