In CalVR, new applications are added in the form of plugins. These plugin modules implement a virtual base class in the CalVR core and compile into a separate shared library. At runtime, this library is loaded and the plugin receives callbacks from the CalVR core through the implemented virtual functions.
It is recommended to build the doxygen documentation for the CalVR core for use during plugin development. You can turn this on with a flag in the ccmake config.
Adding a new Plugin for CalVR
Create a new directory named <YourPluginName>. Each source code directory must have a file "CMakeLists.txt".
For your plugin, use (CVRPlugins Dir)/calit2/ModelLoader/CMakeLists.txt as an example.
Change the LIB_NAME variable to be set to <YourPluginName> and replace the source and header files with those for your plugin.
If you need compile against other libraries, add entries for them with INCLUDE_DIRECTORIES and TARGET_LINK_LIBRARIES options.
In order for cmake to generate a makefile for the new plugin, we need to add an entries to the "CMakeLists.txt" in the parent directory.
Under the parent directory, e.g., (CVRPlugins Dir)/calit2/CmakeLists.txt, add the following lines:
OPTION(PLUGIN_YOURPLUGINNAME "YourPluginName" OFF)
IF(PLUGIN_YOURPLUGINNAME) ADD_SUBDIRECTORY(YourPluginName) ENDIF(PLUGIN_YOURPLUGINNAME)
Go to the root CVRPlugins directory and run:
Type 'c' to configure the project again.
You should now see an option to build your new plugin. Set this option to ON, re-configure, then type 'g' to generate the new makefiles.
You can now build your plugin by typing make.
Now we need to modify the CalVR Config File to turn on the new plugin. Now run CalVR, in the terminal we should see the init message of the new plugin.
The Plugin Base Class
Your plugin project will need to have a class the inherits from the CalVR plugin base class. This is the CVRPlugin class defined in:
The class may implement any needed virtual functions in this class to receive calls from the CalVR core during runtime.
There are doxygen comments for these functions, but I will note them here as well:
virtual bool init()
Called once right after the plugin is created. A return of true means the init went ok and false means there was some failure and the plugin should be unloaded. This is a good place to do one time setup operations like creating menus or a base scene graph structure.
virtual void preFrame()
Called once each frame right before the scene is rendered. This is where things like scene graph changes could take place and affect the current frame.
virtual void postFrame()
Called once each frame after rendering and buffer swap (for double buffered rendering). This call may have a situational use. Implement it if you feel you need it.
virtual bool processEvent(InteractionEvent * event)
Function that allow the plugin to use events generated by the CalVR core. These events are things like button presses, keyboard presses, valuators, etc. See doxygen or below for more on the InterationEvent class types. If true is returned the event is consumed, otherwise it continues through the event pipeline.
virtual void message(int type, char * & data, bool collaborative = false)
Called when the plugin is sent a message from another plugin or a collaborative session. TODO: create and link to message passing documentation
virtual int getPriority()
Returns a priority value for this plugin. This function is called once when the plugin is loaded. It is used to order all loaded plugins. A plugin with a higher priority gets function calls and events before lower priority plugins. The default is 50. This value really SHOULD NOT BE CHANGED unless you have a good reason to do so. This is designed to allow you to be able to enforce a relative order of plugin execution or event handling.
All plugins must also include a macro in the main .cpp file:
Where PluginName is the name of the class implementing the CVRPlugin class. This creates a small function that is used as an interface into the plugin shared library.
Using the Config File
For info on the config file itself, see CalVR Config File.
To access values from the config file you must first include the ConfigManager class.
This class provides static functions that return values listed in the config file. An example would be something like:
int myInt = ConfigManager::getInt("size","Plugin.MyPlugin.MyTag",100);
The ConfigManager looks for the given attribute "size" in the given tag search path "Plugin.MyPlugin.MyTag". If the tag/attribute is not found, the default value is returned, in this case 100. Optionally, you can include a bool pointer as a final argument in the function call. The bool value is filled with true if the tag/attribute is found and false otherwise. If this tag/attribute appears more than once in the config structure, the first one found is returned.
This is the xml structure the example is searching for:
<Plugin> <MyPlugin> <MyTag size="100" /> </MyPlugin> </Plugin>
There is a different function call for each type of value you wish to find, bool/int/float/etc. See the doxygen comments or header files for more info.
CalVR allows for use of menus to allow a user to dynamically interact with a plugin. You may create a structure of menu items and add them to one of the menu systems.
The two main types of menu items are sub menus and everything else.
The SubMenus create the structure of the menu. You may add any type of MenuItem into a SubMenu. You also add SubMenus to SubMenus.
To create a SubMenu, include:
Into the SubMenus you can add various types of items. I will list some of the main ones here:
A clickable button item.
A toggleable checkbox.
#include <menu/MenuRangeValue.h> | <menu/MenuRangeValueCompact.h>
Allows user to change a value within a range.
Allows insertion of non clickable text.
Using Menu Interaction
A plugin receives menu actions in the form of callbacks. In order for this to work, a few things need to be done. First, the class that is getting the callback must implement the MenuCallback interface:
class MyClass : public MenuCallback ...
The class must also define the function:
virtual void menuCallback(MenuItem *)
Now when the MenuItems are created, this class must be registered as the callback for the item:
MenuButton* button = new MenuButton("MyButton"); button->setCallback(this); // only if this class implements the MenuCallback interface // add button to menu
Now when the user interacts with the item, the callback fuction will be called. Within the callback function, you can look at the MenuItem * that is passed in and see if it equals one you have created. At this point, you know what the item is and you can properly handle the interaction.
There are a few places you can add menu item to let the user interact with them.
The main menu in CalVR includes options for navigation as well as a few other general things. Your plugin is able to add to this menu if needed. Normally, you create a SubMenu that is named the same as the plugin and place all needed items inside of it. To add items to the main menu, use the PluginHelper class.
The PluginHelper class is designed to collect useful functions to make plugin development easier. The class is include with:
All the fuctions in this class are static. Therefore, you do no need to create and instance of it.