In “Rei”, there is a curious little green “health” bar above the avatar’s head. That bar is not something that is built in to the viewer, rather, a simple plugin provides the functions that are necessary to have a very rudimentary health bar. Of course this TestPlugin is only to show what sort of things are possible with “Rei”.
Plugins are intended for two main purposes. First, to communicate - through javascript - with the 2D web, and second, to interact with objects within the 3d scene. Of course a plugin is a .NET assembly, so it can pretty much do anything, but the main functions it is intended for are the above two. For instance TestPlugin provides two javascript functions: one to inflict damage and one to heal, basically allowing a regular 2d web application, for instance an SNS site or an online game, to change the health meter of the avatar within the 3d world according its own rules. Responding to these javascript functions then, the plugin interacts with the 3d world by rendering its own little health bar above the user’s head.
To make things as simple as possible, “Rei” uses the same method for developing plugins as OpenSim. Essentially one writes an addin for the /OpenViewer/Managers extension by implementing the IManagerPlugin interface and then creating and embedding a plugin manifest to the assembly.
All plugins need to implement IManagerPlugin, which means implementing a few methods:
void Initialise(Viewer viewer);
-** Initialise **is the method that will be called right after constructing the plugin class. This will be only called once for the life of the plugin and is used to create objects that will persist through the entire lifetime such as static resources (textures, models), configurations.
void Initialize();
void Update(uint frame);
-** Update** is called every frame. This is the place to calculate the next state of the plugin, including objects in the 3d scene. This is the only place where it is allowed to change properties of any object that is within the scenegraph. By using the frame parameter, it is possible to count or skip frames.
void Draw();
void Cleanup();
RefController Reference { get; set; }
A plugin can call Reference.Viewer.Adapter.Dispatch(string action, string message) when it wants to send a message to javascript. If a handler was added to the javascript library for the particular action, this dispatch will be processed by passing the message to the handler function. For future compatibility it is recommended although not required that the message be passed in json format.
The Adapter supplies a Callback delegate and a registry to handle calls from Javascript. A plugin can register a callback method that it is interested in receiving by calling
Reference.Viewer.Adapter.RegisterCallback
. It must pass the name of the method it wants to listen to and the method to call when the event arrives. The way a Callback works is very much like delegates work in the .NET framework.
From the javascript side, one can use
ctrl.Callback("method", parameters)
and all plugins that are listening to “method” will receive a callback to their registered functions. For an example of Callbacks, you can see the DoDamage and DoHeal from test.js and TestPlugin.cs
It is also possible to send messages from one plugin to another, even without being aware of the other plugin. The mechanism is very similar to Callbacks: a plugin registers a message handler by calling
Reference.Viewer.Adapter.RegisterMessage
. The first parameter must be the name of the message to listen to and the second one is a message handler delegate.
A plugin can then raise a Message by calling
Rerence.Viewer.Adapter.SendMessage("message", parameters)
and all plugins that subscribed to the message being sent will receive it.