Yesterday I finished porting Jade Virtual File System to Pluto. It involved mostly getting rid of all the "J" in the class names (JFilesSource to FilesSource and so on), some namespace clashes (System.IO.Directory with Pluto.VFS.Storage.Directory for example), and some new extra features to transform the VFS into a fully working Pluto plugin.
First, let's talk about Pluto: it stands for PLUgin TOolkit, and as it's name tells is a toolkit to give plugins support to any application. Pluto is not tied to the engine, although it was born from the work Reed and Quimbo did in Jaded. Our idea in our next Jade release is to use Pluto extensively to give us extensibility and flexibility. Pluto also comes with several base classes and tools to help you develop new plugins.
Pluto works publishing a set of services to the outside world, so other apps can use these services when needed. That means that the VFS must become a service in Pluto so other applications can query it. Let's see how to create and publish it in Pluto:
#region Using Directies
using Pluto.Core;
using Pluto.Configuration;
#endregion
namespace Pluto.VFS
{
/// <summary>
/// Exposes an <see cref="IVFSService"/> service.
/// </summary>
[CompletionStatus(100)]
[ExposedService(typeof(IVFSService))]
[ExposedService(typeof(IFilesSourceBuilderService))]
[ServiceDependency(typeof(IConfigurationService))]
public class VFSServicePlugin : ServicePluginBase
{
#region Methods
/// <summary>
/// Registers the <see cref="IVFSService"/>.
/// </summary>
protected override bool RegisterServices(IPlutoServiceContainer serviceContainer)
{
serviceContainer.AddService<IVFSService>(new VFSService(serviceContainer));
serviceContainer.AddService<IFilesSourceBuilderService>(new HardDiskSourceBuilder(), "HardDisk");
serviceContainer.AddService<IFilesSourceBuilderService>(new StorageSourceBuilder(), "Storage");
return true;
}
#endregion
}
}
Let's review the important (and probably a little strange right now) part of this code:
- VFSPluginService : PluginBase: all plugins in pluto must inherit from this class. When Pluto loads an assembly it queries for these classes to load their declared services.
- [ExposedService(typeof(IVFSService))] and [ExposedService(typeof(IFilesSourceBuilderService))] : these are the services that this plugin declares to the outside world. As you can see in the method RegisterServices I add them to Pluto ServiceContainer so other classes will be able to use them later. The services are declared as interfaces, so people can do and use different implementations of the same service and aren't tied to the default one we give in Pluto.
- [ServiceDependency(typeof(IConfigurationService))]: I also tell Pluto that our plugin will need the IConfigurationService to work. When a plugin depends on other plugins you should use this attribute so Pluto knows the right order to load plugins.
- [CompletionStatus(100)]: this attribute is a development attribute that tells us that this class is 100% done now. Pluto comes with an assembly browser that uses this attribute to see what classes, methods,.. are done, documented, tested and so on. It's pretty useful to know what's the status of things when a project gets big.
That's the plugin part. You can see it's pretty easy to create a plugin in Pluto. There are some other small changes in the VFS main code (in the constructor mainly, so I'll only post that code).
namespace Pluto.VFS
{
/// <summary>
/// Represents a virtual file system.
/// </summary>
/// <remarks>
/// The priority in the searches within this object is related to the order in which the
/// <see cref="IFilesSource"/> items are aggregated. The first item gets higher priority
/// and so on.
/// </remarks>
[CompletionStatus(100)]
public class VFSService : IVFSService
{
#region Constructors
/// <summary>
/// Default constructor.
/// </summary>
/// <remarks>
/// Uses the <see cref="IConfigurationService"/> to load itself
/// from the configuration.xml file.
/// </remarks>
internal VFSService(IPlutoServiceContainer serviceContainer)
{
_serviceContainer = serviceContainer;
IConfigurationService configuration = _serviceContainer.GetService<IConfigurationService>();
// Read the VFS main values
_name = configuration.ReadValue<string>("VFS", "Name", string.Empty);
_path = configuration.ReadValue<string>("VFS", "Path", string.Empty);
// Get all sources and load them
string[] keys = configuration.GetPaths("VFS/FilesSource", "Name");
foreach (string key in keys)
{
string type = configuration.ReadValue<string>(key, "Type", string.Empty);
string name = configuration.ReadValue<string>(key, "Name", string.Empty);
string path = configuration.ReadValue<string>(key, "Path", string.Empty);
IFilesSource source = _serviceContainer.GetService<IFilesSourceBuilderService>(type).Create(this, name, path);
// Get the defined paths of the source
if (source != null)
{
string[] paths = configuration.GetPaths(key + "/DefinedPath", "Name");
foreach (string definedPath in paths)
{
name = configuration.ReadValue<string>(definedPath, "Alias", string.Empty);
path = configuration.ReadValue<string>(definedPath, "Path", string.Empty);
source.AddDefinedPath(name, path);
}
_sources.Add(source);
}
}
}
#endregion
}
}
Now the VFS constructor uses the IConfigurationService to read the configuration values (from a xml file) file and the IFilesSourceBuilderService to create files sources (based on the type).
As you can see Pluto give us the ability to decouple components (services as interfaces, quering services to the ServiceContainer instead of having lots of statics properties and methods in the code) while doing things in a more .NET way (heavy usage of attributes). In the next post I'll probably talk about other nice things that are inside Pluto and how they relate to the engine.
If you look at the IRC log I posted in my last entry, you will see the new Jade website (not fully ready, but we are on it). We are pointing www.jadengine.com to it now, so until the information propagates the domain is pointing to a NS ads page ¬¬ The move should be finished in 24-36 hours at most. We'll continue using Codeplex for source control and to host our releases, but we'll use the new site for the documentation (it has a much better wiki than Codeplex).
Well, a little
later than expected but here it comes the
post about our last IRC meeting. First, I would like to thank all the people
who attended, Jade users and devs, but I would like to especially thank Borrillis for coming. If you
didn't know him, he is the current developer of Axiom and SharpInputSystem.
Why was another engine developer in Jade meeting?
Well, the main subject of our meeting was to see what would we do for our next
release. We have been working in the engine internals and we have found that several parts are really too hard to improve
without a complete rewrite. So we wanted to see how much people could help, and
depending on that we would do either minor core
changes or a complete rewrite. Even if we missed some people in the meeting because
of exams (these dates are really hard for students), we decided in the end to
go for the rewrite. That's where Axiom makes
sense: a complete rewrite is a very hard affair, so we plan to take things here
and there from other open source projects to speed things.
So far our idea is to build our new scenegraph using
OpenSceneGraph as a base and study
the Axiom renderer and materials system to see how well it would work with Jade's
current renderer and EffectBuilder. We also plan on
using SharpInputSystem for the new input. We aren't going to reinvent anything if we can avoid it :)
Another of
our objectives is to make the engine more ".NETish": currently most
engines out there are built in a "C++ way", and while C++ is nice for
some things, the .NET way of thinking is pretty
different for others. So expect things to
be more like .NET in the engine (events, delegates, reflection, and things like
that). There's a great deal of code using these features in Pluto, so you can
check there and see for yourself.
And well, you can read the chat log in this URL:
http://jadengine.dreamhosters.com/index.php?title=24/05/2007_-_Jade_1.2_Meeting
If you are asking yourself "what's
that site?", the answer is that it will be the new
Jade site/wiki :) So far it has all the old material (thanks to Reed for
setting everything up), but several sections (features, what's coming and
FAQs) badly need an update, so we won't be promoting much yet (but it should go live soon).