Important Note

While much of this information is still valid, it is strongly recommended that all new plugins are developed using the VastPark PluginFramework

Tutorial: Getting Started in developing a VastPark Plugin.

Summary: Learn how to develop and publish a VastPark Plugin and use it in virtual environments.
Aim: To gain a basic knowledge on developing and publishing your own plugin.
Required application: VastPark Publisher, VastPark Player, Visual Studio

What you need

To get started, download PluginExample - Framework v1.5.3.zip

Extract and open up the Plugin.Example.csproj in Visual Studio. If you don't have Visual Studio you can open Plugin.Example.cs in a text editor

When possible update all of your references in the project by either pointing them to local dlls that can be downloaded from http://www.vastpark.org/projects/list_files/vp under Libraries.rar, or download the latest code from http://www.vastpark.org/repositories/show/vp located inside the trunck/src folder.

Lets Get Started

Start by naming your Plugin. Put it inside a folder Plugin.______ and rename both the project name and namespace with what you have called the plugin.

Now you are ready to write your first Plugin class. To ensure that VastPark Player can interact with your Plugin class, you will need to implement the IPluginComponent interface. The interface specifies a set of methods which are automatically called by the VastPark Player during certain events. A description of the methods enforced by the IPluginComponent interface can be found below.

IPluginComponent Interface :

public bool MyVariable { get; set; }
This is a property that is able to be set via a Parameter which is nested within a plugin. The Parameter tag is simply a <Key, Value> pair where Key is the property name and Value is the user defined value for that property. Below is an example of how to set the boolean property MyVariable.

<Plugin Name="Plugin.Example" Enabled="True" Source="..." >
    <Parameter Key="MyVariable" Value="True" />
</Plugin> 

public void AddElement(ImmlElement element)
Elements passed into the plugin via <Element Name="SomeElement" /> appear here.

--In IMML
<Plugin Name="Plugin.Example" Enabled="True" Source="..." >
    <Element Name="someElement" />
</Plugin> 

//In code
private ImmlElement _Element;
public void AddElement(ImmlElement element)
{
   if(element.Name == "someElement")
   {
       _Element = element;
   }
}

In the above example, "someElement" will be automatically passed into the AddElement() method by the VastPark Player.

public void Load()
Final step prior to the plugin being completely loaded. This is called after the plugin has been instantiated and all elements are added via AddElement(). Typically this method contains code to process IMML elements which were passed in to the Plugin.

public void Update()
This is called once each update cycle by the PluginManager, typically this is every ~17ms (60 updates per second)

public bool Enabled { get; set; }
This property can change at runtime, when it is false, the PluginManager will not call Update

public void Dispose()
Dispose is called when the user refreshes the current IMML document or navigates to another world. This method allows you to deallocate unmanaged memory that may be in use and to release any other resources which the Plugin may be utilizing.

IParkObject Interface :

For extended functionality within the VastPark API, you may wish to implement the IParkObject interface in your Plugin. By doing so, you can obtain access to the current running engines of the VastPark Player to build a more powerful and integrated Plugin. There is only one method to implement with this interface.

public void SetParkEngine(IParkEngine engine)
Should you choose to implement IParkObject, the VastPark Player will pass in the current IParkEngine object to your Plugin as it loads. With this, you are exposed to various internal utilities such as : NetworkClient, SoundEngine, ScriptEngine, RenderEngine, VideoEngine, UserCamera.

These are some basic methods found in Plugins. You can extend Plugins further, making your own public methods which can be triggered by scripts.
From here you should have some basic understanding of developing a VastPark Plugin and can move onto publishing.

Custom Methods :

Now that you have the basics sorted out, you can move on to develop for your Plugin's use case scenarios. In the previous sections, we described the implementation of interface methods to be called by the VastPark Player autonomously. In this section, you will find an example of calling a Plugin method from IMML. With the use of triggers, you can turn create a user interface to interact with your Plugin.

--In IMML
<Plugin Name=“MyPlugin" Enabled="True" Source=“my.plugin">
    <Element Name=“BoxElement" />
    <Parameter Key=“Uri" Value=“http://example.org" />
</Plugin>

<Trigger Event=“Loaded" Target=“OnLoad" /> --When IMML is loaded the script OnLoad will execute

<Script Name=“OnLoad" Language="Lua">
    function main(obj, args)
        myplugin:dosomething()  --Calls DoSomething() method of the plugin (method name is case insensitive in LUA)
    end
</Script>

//In code
public class MyPlugin : IPluginComponent
{
    //...

    public void DoSomething()
    {
        //do work
    }
}

Overview at runtime :

The following is the order of actions that occur as the VastPark Player attempts to load your Plugin:
1. blueprint.xml is loaded
2. Dependent assemblies extracted and loaded
3. First CLR assembly found that implements IPluginComponent is constructed/instantiated
4. If instance implements IParkObject, an IParkEngine reference is passed to the Plugin
5. Parameters specified in IMML are set to the requested values on the plug-in object
6. Elements specified in the IMML as <Element Name=“someElement” /> are passed to AddElement() method
7. IPluginComponent.Load() is invoked
8. If blueprint.xml defined this plugin as ScriptVisible, the plugin is available via name within a scripting context
9. If the Plugin is set to Enabled in the IMML, IPluginComponent.Enabled property is set to true and at each update cycle it will result in a call to the IPluginComponent.Update() method of the plug-in.

Plugin Best Practice :

  • Avoid blocking IPluginComponent.Update() for long periods of time or performing process intensive tasks as VastPark aims to perform 60 updates per second. Use separate threads in these situations.
  • Avoid blocking in the IPluginComponent.Enabled setter
  • Avoid overloaded methods as LUA may have difficulty with dynamic binding
  • Set threads you create to the background : thread.IsBackground = true
    -This enables the VastPark Player to close any active threads when it exits. Otherwise the VastPark Player will fail to close.

Preparing your Plugin for release :

Once you have completed the Plugin the next step is to to get it ready for publishing.
In order to publish the Plugin you will need an xml blueprint, this is included in the Plugin.Example.zip

XML Blueprint

Open the xml blueprint in a text editor and change the Source to the name of the project default name, and the name that you have given your Plugin.

Source="Plugin.____.dll"

Name="Plugin.____"

If your Plugin contains other libraries you will need to have dependency source tags that target any other dll's not part of VastPark.

<Dependency Source="ExtraDependency.dll"/>

After the blueprint is done copy it inside the Release build, as well as any extra dll's that are needed so they can all be grabbed at the same time.

Publishing your Plugin :

With your Release build ready open the VastPark Publisher, log in and select the group you want to publish your Plugin to.

  • If you are publishing a Plugin for the first time click the new button at the bottom of the screen.
  • If you want to overwrite an existing Plugin you have previously published select it from the list, go into its Asset Tab and click on browse.

You will be asked to find an xml file, here you need to navigate to where you have built your plugin and find the xml blueprint.
Make sure you include all dlls that are needed, otherwise the plugin will be ignored and not loaded. (It would come up as an error that there is no (name of plugin) is global.)

When ready you can click the Publish button in the bottom right and your Plugin will be added to the Metaforik Library. It will then be available for use inside an IMML file.

See it in action :

Save the example-plugin.imml located here or at the bottom of this page.

Open the IMML file up in IMMLpad and you will need overwrite "myplugin.plugin with the Source of your Plugin.

<Plugin Source="myplugin.plugin" Name="ExamplePlugin">
  <Element Name="someElement" />
  <Parameter Key="MyVariable" Value="True" />
</Plugin>

You will also need to add a trigger to Box "someElement" if you want it to fire the script.

<Primitive Name="someElement" Type="Box">
  <Trigger Name="someElement-Trigger" Event="MouseClick" Target="Script" Enabled="True" />
</Primitive>

Save the IMML file and open it in the VastPark_Player, clicking on the box will trigger the event.

Plugin.Example.zip (10.9 kB) Adrian Shepherd, 08/04/2010 02:46 pm

example-plugin.imml (424 Bytes) Adrian Shepherd, 08/04/2010 03:40 pm

Plugin.Example-Framework_v1.5.3.zip (369.8 kB) Craig Presti, 07/19/2011 07:45 pm