How to create plugins for the Nova Explorer
Overview
Nova Explorer allows the addition of new functionalities and personalized modules via the realization of plugins under Visual Studio 2008. Before describing in detail the realization process of a plugin for Nova Explorer, we need to go through this info:
- Nova Explorer was written exclusively in C#.NET 2.0 under Visual Studio 2005 while staying based on the Nova Omega Software Development Kit (SDK). Nova Omega SDK contains all the classes useful for the handling of scenes (at the mxb format ) exported via the Nova Exporter from 3ds Max. The objects (the 3D entities) are represented in .NET by some NovaObject, the lights by some NovaLight, the scenes by some NovaScene, etc. We will thus use this library (Vertice.Nova.dll and Vertice.Nova.Interop.dll) in our development projects of plugins.
- The libraries Vertice.Nova.dll, Vertice.Nova.Interop.dll are deployed during the installation of the Nova Explorer in the repertory selected for the installation (by default "C:\Program Files\Vertice\Nova 2009 \"). A documentation is available for the Nova Omega SDK from this same "Docs" repertory or directly via the Start menu ->Vertice\Nova Omega 2008\Documentation\. We invite you to read this documentation for all the details concerning the use of the Nova Omega SDK.
- A library has been developed especially to interact with the Nova Explorer (Vertice.Explorer.Plugins.dll). This library contains the elements useful for the interactions with the Nova Explorer (addition of menu, controls, recovery of the current scene, of the selected object, etc), it is thus the base of all the projects of development of plugins for the Nova Explorer. Vertice.Explorer.Plugins.dll is available in the installation repertory, on the same level of Vertice.Nova.dll, Vertice.Nova.Interop.dll.
- When starting, the Nova Explorer reads (starting from its installation repertory) the content of its "Plugins" repertory and loads the modules available (if they satisfy a certain criterion which we will talk about thereafter). All the plugins thus must be present in this repertory before being available in the Nova Explorer.
How to create a Visual Studio 2008 plugin project for the Nova Explorer
The type of project to be created is of the Class Library type. Indeed, we will not carry out an executable program but a dll that we will copy in the Plugins repertory of the Nova Explorer.
For the reasons listed above, the first action to be carried out is to specify in the Solution Explorer the references towards the libraries Vertice.Nova.dll, Vertice.Nova.Interop.dll and Vertice.Explorer.Plugins.dll:
|
|
|
Right click on the file « References » in the « Solution Explorer » of our project
|
Under the « Browse » tab, we go to the installation directory of the Nova Explorer to select the 3 dll to
reference.
|
We can begin the development of the plugin from here. Once compiled, it would be enough to copy the dll in the plugins repertory of the Nova Explorer, then launch the Nova Explorer. We will automate these tasks not to have to carry out them each time we test/compile the plugin:
|
|
Right click on the solution then « Properties »
|
|
|
The properties window of the solution appears. The tabs « Build » and « Debug » will be useful to us.
|
We have 2 things to automate:
To copy the dll directly in the Plugins repertory.
|
|
The initial Build tab of the of the Properties window. We will modify the « Output path ».
|
|
|
Output path » points from now on towards the Plugins repertory of the Nova Explorer.
|
To start automatically the Nova Explorer when we do a Start Debug/Release (F5).
|
|
The initial Debug tab of the Properties window. We will modify Start Action.
|
|
|
We tick "Start external program" in order to specify the path towards the executable of the Nova Explorer.
|
In order not to create any conflict between the versions of the dll Vertice.Nova.dll, Vertice.Nova.Interop.dll and Vertice.Nova.Plugins.dll, we must not deploy these in the Plugins folder. We will then turn the property Copy Local of all these dll to False (by clicking on the dll in the Solution Explorer and by filling the property Copy Local available in
the Properties):
By carrying out a Start Debug (or F5), we note that the Nova Explorer is automatically started and that the dll is well copied in the Plugins repertory of the Nova Explorer. This being said, no change appears in the Nova Explorer for the moment.
Note:
We can have this error coming from DirectX at the time of the first execution:
DLL
'C:\WINDOWS\assembly\GAC\Microsoft.DirectX\1.0.2902.0__31bf3856ad364e35\Microsoft.DirectX.dll'
is attempting managed execution inside OS Loader lock. Do not attempt to run
managed code inside a DllMain or image initialization function since doing so
can cause the application to hang.
It is a bug of DirectX that we can easily deactivate by carrying out the following operation:
In the Debug menu, click on the item "Exceptions"
By default, it is possible that "Exceptions" does not appear in Debug menu. We can however make Ctrl + Alt + E to reveal the Exceptions management window to add it by going in the Tools menu then by clicking on Customize to reveal the window of customization of Visual Studio 2008. In the Customize window, under the Commands tab, choose the Debug "Categories" and carry out a drag & drop of the "Exceptions" item towards the Debug menu.
In the window "Exceptions":
|
|
|
Reveal the sub-menu Managed Debugging Assistants, then deactivate "Thrown" at the level of the Loader Lock line:
|
|
Before continuing, ensure that the Nova Explorer is well launched when the solution is carried out and that the dll (carrying the name of the solution by default, NovaExplorerPlugin_Template.dll in our example) is well deployed in the Plugins directory of the Nova Explorer.
We will now see the mechanism allowing the Nova Explorer to recognize and to load some plugins.
The IPlugin interface
As in almost any development project of plugin, we will have an interface to implement so that the module (the dll) is recognized as a plugin.
In the case of the Nova Explorer, it is the interface IPlugin (Vertice.NovaExplorer.IPlugin):
When we launch the Nova Explorer, it consults its Plugins directory. If a module is found, Nova Explorer checks if one of the components implements the IPlugin class. If it is the case, the Start() method of this component is called.
When we leave the Nova Explorer, it calls the Stop() method of the charged modules (i.e. modules that we called the Start() method).
Let's take again the solution created previously:
Rename the class "Class1" created by default by Visual Studio "MyFirstPlugin" (for example).
Add a using Vertice.NovaExplorer.
Make inherit MyFirstPlugin from IPlugin.
Implement the IPlugin interface.
|
public
class
MyFirstPlugin:
IPlugin
{
#region
IPlugin Members
public
bool IsAvailable
{
get {
throw
new
NotImplementedException(); }
}
public
void Start()
{
throw
new
NotImplementedException();
}
public
void Stop()
{
throw
new
NotImplementedException();
}
#endregion
}
|
|
We post dialog boxes to each call of the 2 methods and of the property in order to understand the operation of the IPlugin interface well. To post a dialog box, we need the libraries Windows Forms (not included automatically at the time of the creation of a project of the Class Library type):
|
|
|
To compile and carry out the project (F5):
When Nova Explorer is launched, the dialog box with the text "Start method call" appears.
When we leave the Nova Explorer, the dialog box with the text "Stop method call" appears.
With the IPlugin interface, we allow our program to be recognized and carried out by the Nova Explorer. But how can we interact with this one? How to add a menu? How to have access to the current scene?
All these operations (and much more) will be carried out thanks to the PluginHelper class.
The PluginHelper utility class
The PluginHelper class allows us to have directly access to the Nova Explorer and to even react according to the users events (loading of a scene, selection of an object, etc.).
All the methods, all the properties, all the events are static members, we will thus never have to use PluginHelper (there is logically no manufacturer). We will now see all that is possible to be made with the PluginHelper class.
The PluginHelper utility class: Add/Suppress an element in the Plugin menu of the Nova Explorer
When at least one plugin is detected by the Nova Explorer, the Plugin menu is automatically created in the Explorer.
To add an entry in this menu, we will use the RegisterPluginMenuEntry method.
If we wish, at a given time, not to see appear anymore this entry in the menu, we will do an UnRegisterPluginMenuEntry.
For example, we would like to position one item "MyFirstPlugin" in the Plugin menu of the Nova Explorer and to start the posting of a dialog box when this item is turned on, then to remove the entry of the Plugin menu. The use of RegisterPluginMenuEntry and more particularly the image argument obliges us to
reference System.Drawing in our project:
|
public
class
MyFirstPlugin: IPlugin
{
#region IPlugin Members
public
bool IsAvailable
{
get
{
MessageBox.Show("IsAvailable field request");
return
true;
}
}
public
void Start()
{
PluginHelper.RegisterPluginMenuEntry("MyFirstPlugin",
Image.FromStream(Assembly.GetExecutingAssembly()
.GetManifestResourceStream("NovaExplorerPlugin_Template.Resources.notepad.jpg")),
new
EventHandler(MenuClick), this);
}
public
void MenuClick(object sender, EventArgs e)
{
PluginHelper.AddUIControl(typeof(NovaNotePad), "Nova Notepad");
}
public
void Stop()
{
MessageBox.Show("Stop method call");
}
#endregion
}
|
We now wish to add a customized control to the interface of the Nova Explorer.
The PluginHelper utility class: Add a customized control to the user interface of the Nova Explorer
We would like to create a plugin allowing to enter some text, to take notes during the navigation within a scene for example:
We call this NovaNotePad control, we add to it a RichTextBox control (from the toolbox of Visual Studio), and we "dock" this RichTextBox in NovaNotePad:
We still have to modify MyFirstPlugin.cs so that it adds this control to the interface of the Nova Explorer:
We would like now to associate an image to the plugin (in the menu):
We insert the icon in the project, and we incorporate it in the dll (in order not to have to deploy the "Resources" repertory).
We still have to modify the call to RegisterPluginMenuEntry:
public
void
Start()
{
PluginHelper.RegisterPluginMenuEntry("MyFirstPlugin",
Image.FromStream(Assembly.GetExecutingAssembly()
.GetManifestResourceStream(
"NovaExplorerPlugin_Template.Resources.notepad.jpg")),
new
EventHandler(MenuClick),
this);
}
|
So that the plugin can compile, we will have to add the following using:
using System.Drawing;
using System.Reflection;
|
The icon appears in the menu:
The PluginHelper utility class: Interact with the scenes of the Nova Explorer
We have access to the current scene via the ActiveScene property (Caution! It can be null):

The interactions of use with a scene launch events to which we can subscribe:
Loading of a scene:

Selection of a scene (when several scenes are opened in the Nova Explorer):

Closure of a scene:

To subscribe to these 3 events, we will use a delegate of the type:

To save the current scene:

To subscribe to this event, we will use a delegate of the type:
We will improve our plugin to transform it into a newspaper recapitulating the interactions of the user with the scene. We thus modify the NovaNotePad component:
public
partial
class
NovaNotePad: UserControl
{
public NovaNotePad()
{
InitializeComponent();
}
private
void
WriteLine(String strText)
{
this.richTextBox1.AppendText(String.Format("{0}\n",strText));
}
private
void
NovaNotePad_Load(object
sender,
EventArgs e)
{
PluginHelper.NovaSceneLoaded
+=
new
PluginHelper.NovaSceneDelegate(PluginHelper_NovaSceneLoaded);
PluginHelper.NovaSceneSaved
+=
new
PluginHelper.NovaSceneFileDelegate(PluginHelper_NovaSceneSaved);
PluginHelper.NovaSceneSelected
+=
new
PluginHelper.NovaSceneDelegate(PluginHelper_NovaSceneSelected);
PluginHelper.NovaSceneUnloaded
+=
new
PluginHelper.NovaSceneDelegate(PluginHelper_NovaSceneUnloaded);
PluginHelper.NovaSceneRendered
+=
new
PluginHelper.NovaSceneDelegate(PluginHelper_NovaSceneRendered);
}
void
PluginHelper_NovaSceneRendered(Vertice.Nova.NovaScene
scene)
{
WriteLine(
String.Format(
"Events NovaSceneRendered, Scene Rendered: {0}",
scene.Name));
}
void
PluginHelper_NovaSceneUnloaded(Vertice.Nova.NovaScene
scene)
{
WriteLine(
String.Format(
"Events NovaSceneUnloaded, Scene Unloaded: {0}",
scene.Name));
}
void
PluginHelper_NovaSceneSaved(Vertice.Nova.NovaScene
scene, string
filename)
{
WriteLine(
String.Format(
"Events NovaSceneSaved, Scene Saved: {0} in file
", scene.Name, filename));
}
void
PluginHelper_NovaSceneSelected(Vertice.Nova.NovaScene
scene)
{
WriteLine(
String.Format(
"Events NovaSceneSelected, Scene Selected: {0}",
scene.Name));
}
void
PluginHelper_NovaSceneLoaded(Vertice.Nova.NovaScene
scene)
{
WriteLine(
String.Format(
"Events NovaSceneLoaded, Scene Loaded: {0}",
scene.Name));
}
}
|
The PluginHelper utility class: Selection of objects in the Nova Explorer
It is possible to know the object(s) selected in the Explorer:
The event SelectionChanged is raised when:
An object is selected
An object is unselected
An object is (un)selected during a multiple selection
To subscribe to this event, we will use a delegate of the type:
It is possible to force the selection/unselection of an object directly from the plugin:
We just have to transform an object reference into a method parameter to select/unselect an object in the scene.
After having seen the addition of entries in the logs of the Nova Explorer, we will give a concrete example of the use of the selections of objects in the Nova Explorer.
The PluginHelper utility class: Add entries in the logs of the Nova Explorer
We would like to enter our own info in the log window of the Nova Explorer. We will use the following methods:
- To enter an information, we will
use::
To enter a warning, we will use:
To enter an error, we will use:
A plugin example for the Nova Explorer: de-activate the render of selected objects
We wish to create a plugin offering the following functionalities:
- When an object is selected in the Explorer, the rendering of this object is deactivated.
-
There is no graphic control for this plugin. When the plugin is activated, we will add one item in the plugin menu to allow to deactivate the plugin.
Here is the code corresponding to this plugin:
|
class
SelectedObjectRenderingPlugin: IPlugin
{
List<NovaScene> loadedScenes;
public
bool IsAvailable
{
get { return
true; }
}; }
public
void Start()
{
PluginHelper.RegisterPluginMenuEntry("Selected
object rendering", null,
new EventHandler(MenuClick),
this);
}; }
public
void Stop()
{
}
#region
PluginHelper events
void
PluginHelper_NovaSceneUnloaded(NovaScene
scene)
{
PluginHelper.LogInfo("Nova scene
unloaded event");
}
void
PluginHelper_NovaSceneSelected(NovaScene
scene)
{
PluginHelper.LogInfo("Nova scene
selected event");
}
void
PluginHelper_NovaSceneLoaded(NovaScene
scene)
{
PluginHelper.LogInfo("Nova scene
loaded event");
LoadScene(scene);
}
void
PluginHelper_SelectionChanged()
{
PluginHelper.LogInfo("Selection
changed event");
}
#endregion
#region
Menu Click events
public
void MenuClick(object
sender, EventArgs e)
{
PluginHelper.LogInfo("Selected object
rendering start");
loadedScenes = new
List<NovaScene>();
PluginHelper.UnregisterPluginMenuEntry("Selected
object rendering");
PluginHelper.RegisterPluginMenuEntry("Stop
Selected object rendering", null,
new EventHandler(MenuClickStop),
this);
if (PluginHelper.ActiveScene ==
null)
return;
else
LoadScene(PluginHelper.ActiveScene);
}
public
void MenuClickStop(object
sender, EventArgs e)
{
PluginHelper.LogInfo("Stop Selected
object rendering");
UnLoadScene();
PluginHelper.UnregisterPluginMenuEntry("Stop
Selected object rendering");
PluginHelper.RegisterPluginMenuEntry("Selected
object rendering", null,
new EventHandler(MenuClick),
this);
}
#endregion
void
LoadScene(NovaScene scene)
{
loadedScenes.Add(scene);
PluginHelper.NovaSceneLoaded += new
PluginHelper.NovaSceneDelegate(PluginHelper_NovaSceneLoaded);
PluginHelper.NovaSceneSelected += new
PluginHelper.NovaSceneDelegate(PluginHelper_NovaSceneSelected);
PluginHelper.NovaSceneUnloaded += new
PluginHelper.NovaSceneDelegate(PluginHelper_NovaSceneUnloaded);
PluginHelper.SelectionChanged += new
PluginHelper.SelectionDelegate(PluginHelper_SelectionChanged);
PluginHelper.ActiveScene.BeforeRender +=
new
Vertice.Nova.NovaScene.RenderingEvent(ActiveScene_BeforeRender);
}
void
UnLoadScene()
{
foreach (NovaScene scene
in loadedScenes)
{
scene.BeforeRender -= new Vertice.Nova.NovaScene.RenderingEvent(ActiveScene_BeforeRender);
foreach (NovaObject
obj in scene.Objects)
obj.Enabled = true;
}
}
void
ActiveScene_BeforeRender()
{
foreach (NovaObject obj
in PluginHelper.ActiveScene.Objects)
{
if (PluginHelper.SelectedObjects.Contains(obj))
obj.Enabled = false;
else
obj.Enabled = true;
}
}
}
|
Example n°2: How to import an XML format file in Nova Explorer ?
We will take back the content of the dll Vertice.NovaExplorer.Plugins and it is noted that it contains the tools necessary for the installation of a personalized importation of file to the proprietary
format in Nova Explorer:
- The class OpenScenePlugin to open its own file format.
- The interface ISavePlugin to save its own file format.

As considering previously, we create a project of the class library type that we name PluginImportXmlFile containing only one class named ImportXmlFile. We will not create personalized control but will only make available a new format of file in the "Open" menu of Nova Explorer. We will thus not implement a IPlugin interface like previously, we will make inherit our class ImportXmlFile of the OpenScenePlugin:
|
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Windows.Forms;
using
Vertice.NovaExplorer;
namespace
PluginImportXmlFile
{
public class ImportXmlFile:
OpenScenePlugin
{
}
}
|
If we compile the project just as it is, the following errors are obtained:
This means that the OpenFilePlugin class obliges us to redefine some methods and properties:
- The Description property which corresponds to the text posted in the fields "Files of type" of the dialog box Open of Nova Explorer.
- The Extension property which will enable us to specify the new extension of file to be added in the dialog box Open of Nova Explorer
- The Open method in which we will implement the process of reading of our proprietary file.
- The Icon property which correspond to the Nova Explorer Icon
- The Title property which correspond to the title of Nova Explorer
class
ImportXmlFile: OpenScenePlugin
{
public
override
string Description
{
get { throw
new
NotImplementedException(); }
}
public
override
string Extension
{
get { throw
new
NotImplementedException(); }
}
public
override
System.Drawing.Image
Icon
{
get { throw
new
NotImplementedException(); }
}
public
override
bool Open(Vertice.Nova.NovaScene
scene,
string
filename, bool
merge,
bool delta)
{
throw
new
NotImplementedException();
}
public
override
string
Title
{
get { throw
new
NotImplementedException(); }
}
}
|
We compile the project to deploy the dll in the Plugins repertory and Nova Explorer is launched
If we click on
then on "Imports" the item associated to our Plugin Xml appears:
We still have to implement the Open method so that it reads our file correctly. We will need some references. One thus adds to our solution the following dll:
- Microsoft.DirectX (in the repertory of installation of Nova)
- Microsoft.DirectX.Direct3D (in the repertory of installation of Nova)
- System.Drawing
For this example we have defined a descriptive file of a scene in XML format:
|
<?xml
version="1.0"
encoding="utf-8" ?>
<scene>
<cameras>
<camera
name="camera1">
<position x="0"
y="0"
z="-6"></position>
</camera>
</cameras>
<lights>
<light
name="lumiere1"
type="directional">
<position
x="0"
y="6"
z="-6"></position>
<diffuseColor
value="white"></diffuseColor>
<direction
x="-1"
y="0"
z="1"></direction>
</light>
</lights>
<materials>
<material
name="materiel1">
<diffuseColor
value="red"></diffuseColor>
</material>
<material
name="materiel2">
<diffuseColor
value="blue"></diffuseColor>
</material>
</materials>
<objects>
<object
name="sphere1"
type="sphere"
radius="0.5"
slices="32"
stacks="32">
<position x="0"
y="-1"
z="0"></position>
<materiel
name="materiel1"></materiel>
</object>
<object
name="box1"
type="box"
width="1"
height="1"
depth="1">
<position x="0"
y="1"
z="0"></position>
<materiel
name="materiel2"></materiel>
</object>
</objects>
</scene>
|
We then have to see the XML file in the Open method:
|
using
Vertice.NovaExplorer;
using
System.Drawing;
using
System.Reflection;
using
System.Xml;
using
Vertice.Nova;
using
Vertice.MathServices;
using
System.Globalization;
namespace
NovaExplorerPlugin_Template
{
class
ImportXmlFile: OpenScenePlugin
{
NovaScene
_scene;
public
override
string
Description
{
get
{
return
"Test import xml
file format (*.xml)";
}
}
public
override
string
Extension
{
get
{
return
"*.xml";
}
}
public
override
System.Drawing.Image
Icon
{
get
{
return
Image.FromStream(Assembly.GetExecutingAssembly().
GetManifestResourceStream(
"ImportXmlFileToNova.Resources.notepadSmall.jpg"));
}
}
public
override
bool
Open(Vertice.Nova.NovaScene
scene,
string filename, bool
merge,
bool delta)
{
// Create reference on the scene object from
Nova Explorer:
_scene = scene;
_scene.AutoClear = true;
XmlDocument document = new
XmlDocument();
// load fileName from the Open File Dialog box
document.Load(filename);
// node scene
XmlNode root = document.DocumentElement;
// node cameras
foreach (XmlNode childNode
in root.ChildNodes)
{
switch (childNode.Name)
{
case
"cameras":
ParseCamerasNode(childNode);
break;
case
"lights":
ParseLightsNode(childNode);
break;
case
"materials":
ParseMaterialsNode(childNode);
break;
case
"objects":
ParseObjectsNode(childNode);
break;
}
}
return true;
}
public
override
string
Title
{
get
{
return
"Test import xml
file format (*.xml)";
}
}
private
void ParseCamerasNode(XmlNode
node)
{
foreach (XmlNode cameraNode
in node.ChildNodes)
{
NovaCamera camera = _scene.CreateCamera(cameraNode.
Attributes["name"].Value);
camera.Position
= ParseVector3(cameraNode.ChildNodes[0]);
}
}
private
void ParseLightsNode(XmlNode
node)
{
foreach (XmlNode lightNode
in node.ChildNodes)
{
NovaLight light = _scene.CreateLight(lightNode.
Attributes["name"].Value);
light.Type
= Vertice.Nova.Core.NovaLightType.Directional;
light.Position
= ParseVector3(lightNode.ChildNodes[0]);
light.DiffuseColor
= Color.FromName(lightNode.ChildNodes[1].
Attributes["value"].Value);
light.Direction
= ParseVector3(lightNode.ChildNodes[2]);
}
}
private
void ParseMaterialsNode(XmlNode
node)
{
foreach (XmlNode materialNode
in node.ChildNodes)
{
Vertice.Nova.Materials.NovaStandardMaterial material =
_scene.CreateStandardMaterial(materialNode.Attributes["name"].Value);
material.Diffuse
= Color.FromName(materialNode.ChildNodes[0]
.Attributes["value"].Value);
}
}
private
void ParseObjectsNode(XmlNode
node)
{
foreach (XmlNode objectNode
in node.ChildNodes)
{
NovaObject obj = _scene.CreateObject(objectNode.Attributes["name"].Value);
switch (objectNode.Attributes["type"].Value)
{
case
"sphere":
float radius =
float.Parse(
objectNode.Attributes["radius"].Value,
CultureInfo.InvariantCulture);
int slices =
int.Parse(
objectNode.Attributes["slices"].Value);
int stacks =
int.Parse(
objectNode.Attributes["stacks"].Value);
obj.CreateAsSphere(radius, slices, stacks);
break;
case
"box":
float width =
float.Parse(objectNode.Attributes["width"].Value,
CultureInfo.InvariantCulture);
float
height =
float.Parse(objectNode.Attributes["height"].Value,
CultureInfo.InvariantCulture);
float
depth =
float.Parse(objectNode.Attributes["depth"].Value,
CultureInfo.InvariantCulture);
obj.CreateAsBox(width, height, depth);
break;
case "cylinder":
break;
}
obj.Position
= ParseVector3(objectNode.ChildNodes[0]);
obj.Material
= _scene.GetMaterial(objectNode.ChildNodes[1].
Attributes["name"].Value);
}
}
private
Vector3 ParseVector3(XmlNode
node)
{
Vector3 res = new
Vector3();
res.X =
float.Parse(node.Attributes["x"].Value,
CultureInfo.InvariantCulture);
res.Y =
float.Parse(node.Attributes["y"].Value,
CultureInfo.InvariantCulture);
res.Z =
float.Parse(node.Attributes["z"].Value,
CultureInfo.InvariantCulture);
return res;
}
}
}
|
Now we want to save a scene in our XML
format. We will us the ISavePlugin
interface.
For example, if we want to save the cameras of a scene in
our proprietary format:
using System;
using
System.Collections.Generic;
using
System.Text;
using
Vertice.NovaExplorer;
using
System.Xml;
using
Vertice.Nova;
namespace
ImportXmlFileToNova
{
class
SaveXmlFile: ISaveScenePlugin
{
#region ISaveScenePlugin
Members
public
string Extension
{
get
{
return
"*.xml";
}
}
public
string Description
{
get
{
return
"Save sTo Xml
file format (*.xml)";
}
}
public
void Save(Vertice.Nova.NovaScene
scene,
string filename,
Vertice.Nova.NovaScene.SaveOptions options)
{
XmlTextWriter writer =
new
XmlTextWriter(filename,
Encoding.Default);
writer.Formatting = Formatting.Indented;
writer.WriteStartDocument();
writer.WriteStartElement("scene");
WriteCameras(writer, scene);
WriteLights(writer, scene);
// todo
//WriteMaterials(writer, scene);
//WriteObjects(writer, scene);
writer.WriteEndElement();
writer.Close();
}
private
void WriteCameras(XmlTextWriter
writer,
NovaScene scene)
{
writer.WriteStartElement("cameras");
foreach (NovaCamera camera
in scene.Cameras)
{
writer.WriteStartElement("camera");
writer.WriteAttributeString("name", camera.Name);
WriteVector3(writer,
camera.Position, "position");
writer.WriteEndElement();
}
writer.WriteEndElement();
}
private
void WriteLights(XmlTextWriter
writer,
NovaScene scene)
{
writer.WriteStartElement("lights");
foreach (NovaLight tmpLight
in scene.Lights)
{
writer.WriteStartElement("light");
writer.WriteAttributeString("name", tmpLight.Name);
writer.WriteAttributeString("type",
tmpLight.Type.ToString());
WriteVector3(writer,
tmpLight.Position, "position");
WriteElementWithValue(writer,
"diffuseColor",
"value",
tmpLight.DiffuseColor.Name);
WriteVector3(writer,
tmpLight.Direction, "direction");
writer.WriteEndElement();
}
writer.WriteEndElement();
}
private
void WriteVector3(XmlTextWriter
writer,
Vertice.MathServices.Vector3 vector3, string
p)
{
writer.WriteStartElement(p);
writer.WriteAttributeString("x", vector3.X.ToString());
writer.WriteAttributeString("y", vector3.Y.ToString());
writer.WriteAttributeString("z", vector3.Z.ToString());
writer.WriteEndElement();
}
private
void
WriteElementWithValue(XmlTextWriter
writer,
String elementName, String
key,
String value)
{
writer.WriteStartElement(elementName);
writer.WriteAttributeString(key,
value);
writer.WriteEndElement();
}
#endregion
ISaveScenePlugin Members
}
}
|
|