Documentation Showcase Screenshots Videos Acknowledgments

Advanced Topics


Extending the ParticleEffect class


Writing custom emitters


Writing custom modifiers

Creating your own custom modifiers couldn't be simpler! Simply extend the ProjectMercury.Modifiers.Modifier abstract base class and override the two methods required. In the Process nethod, you'll notice that you are passed a float value called 'dt' (delta time) which represents the elapsed seconds. You are also passed a pointer to a Particle object called particleArray, and an integer parameter called count. The pointer actually points to the first particle in an array of particles, and the count parameter tells you how many particles need to be processed in that array. You can step through the contents of the particle array using this following code sample:

for (int i = 0; i < count; i++)
{
    Particle* currentParticle = ( particleArray + i );

    // Process current particle...
}

Of course, as we are working with pointers, you will need to mark the method as unsafe by adding the unsafe keyword. Also, you must check the 'allow unsafe code' option in the configuration of the assembly that contains your modifier. You are also required to implement the DeepCopy method, which should return a clone of the Modifier.

Now your custom modifier class should look something like this:

namespace MyNamespace
{
    public sealed class MyModifier : ProjectMercury.Modifiers.Modifier
    {
        public override Modifier DeepCopy()
        {
            // Return a new MyModifier here...
            throw new NotImplementedException();
        }

        public override unsafe void Process(float dt, Particle* particleArray, int count)
        {
            for (int i = 0; i < count; i++)
            {
                Particle* currentParticle = ( particleArray + i );

                // Process current particle...
            }
        }
    }
}

For an example of a complete Modifier class, see the OpacityModifier class in the code repository.
How do I add design time support for my custom Modifier class?
To achieve design time support for your custom Modifier class, you will need to write a TypeConverter class that describes it. If you are an experienced Windows Forms programmer and have worked with the PropertyGrid control in the past, you may be familiar with the process that is required.

Your type converter class must extend System.ComponentModel.ExpandableObjectConverter, and it should override the GetProperties method, which returns an array of PropertyDescriptor objects. The PropertyDescriptor class itself is a little too limited because it cannot work with fields, so for that purpose you may choose to use the ProjectMercury.Design.SmartMemberDescriptor class, which can describe properties or fields. It is these PropertyDescriptor objects which hold the attributes that define how the property will be displayed on the PropertyGrid. Examples of these attributes are DescriptionAttribute, CategoryAttribute and DisplayNameAttribute.

An example of a TypeConverter for the OpacityModifier class can be seen in the ProjectMercury.Design.Modifiers.OpacityModifierTypeConverter class.

Now all that is left to do is to add a System.ComponentModel.TypeConverterAttribute attribute to your Modifier class, which defines which TypeConverter class describes your Modifier. An example of which may look like this:

[System.ComponentModel.TypeConverter("MyNamespace.MyModifierTypeConverter, MyAssemblyName")]
public sealed class MyModifier : Modifier
{
    ...
}

Writing plugins for the EffectEditor application

Now that you have created your own custom emitter or modifier class, you can make it available for use in the EffectEditor by writing a simple plugin. I recommend that you create a seperate project for this purpose. This assembly should have references to ProjectMercury.dll (windows assembly), ProjectMercury.EffectEditor.exe, System.ComponentModel.Composition.dll (MEF - you can find this in the EffectEditor folder), and whatever assembly contains your custom modifier class.

The EffectEditor assembly defines a set of interfaces for creating plugins, for this example we'll implement the ProjectMercury.EffectEditor.PluginInterfaces.IModifierPlugin interface...

    [Export(typeof(IModifierPlugin))]
    public class MyCustomModifierPlugin : IModifierPlugin
    {
        // This is where you define the name of the plugin...
        string Name { get; }

        // This is where you define the name of the plugin, as it appears in the editor...
        string DisplayName { get; }

        // Here you must return an icon that will be displayed alongside your plugin in the editor...
        Icon DisplayIcon { get; }

        // This text will be displayed in the tooltip for your plugin in the editor....
        string Description { get; }

        // Put your name here :)
        string Author { get; }

        // If your plugin is part of a library of plugins, put the library name here....
        string Library { get; }

        // (Modifier plugins only) Define a group for your modifier to be placed in here...
        string Category { get; }

        // Here you define the version number of your plugin (not currently used)...
        Version Version { get; }

        // Here you can define the minimum version of the ProjectMercury engine that your plugin needs
        // (not currently used, put 3.1.0.0 for safety)....
        Version MinimumRequiredVersion { get; }

        // This is the method that creates a default instance of your custom modifier class....
        Modifier CreateDefaultInstance();
    }

The ExportAttribute on the class is vitally important, if it is not applied your class will not be loaded as a plugin into the EffectEdtitor...

Now, all you have to do is drop that assembly into the plugins folder of the EffectEditor application, and next time you start the editor, your custom modifier should be available!

Using the content pipeline


Attaching custom data to particles

Last edited May 28, 2010 at 10:46 AM by JimJams, version 9