Coding a Milkshape 3D Plugin

 

Coding a Milkshape 3D Plugin

A tutorial by jebus

Introduction
This tutorial will explain the process of creating a Milkshape 3D plugin using MSVC. In order to complete this tutorial you will need a general knowledge of C++ and the following:

  • Microsoft Visual C++ (works for versions 5.x & 6.x)
  • Milkshape 3D
  • Milkshape 3D SDK

Got everything above? Then we can go on.

The Project
The first thing you’ll want to do is create a new project. Milkshape plugins are DLL files, so we crank up MSVC and select File->New… and select the Projects tab. From the list of available projects, select Win32 Dynamic-Link Library. Give your project a name, location and select OK.

Another dialog should pop up asking what kind of DLL you want to make. To demonstrate building a DLL from scratch, we will select An empty DLL project and select Finish. Review everything in the next dialog and select OK. You now should have an empty DLL project.

The Environment
Next we’ll want to add the Milkshape 3D SDK paths to our project. Select Project->Settings… and select the C/C++ tab. For Category select Preprocessor and in the Additional include directories: field insert the path: <SDK folder>/msLib. Next, select the Link tab and switch the Category to Input. Again, for the Additional library path: insert the path: <SDK folder>/msLib/lib.

Still in the Link tab, change the Category to General and add the Milkshape library msModelLib.lib to the list of library modules. Finally, in the Output file name: field, change the path and filename to: <Milkshape folder>/msMyPlugin.dll. Note, the dLL name must begin with lowercase ms, but the rest of the filename can be whatever you like. Just make sure that the filename here matches with the filename we put in the definition file (we’ll cover the .def file later in this tutorial).

Whew! I think we’ve completed our project settings, so you can select OK and we can move on.

The Plugin
The code for our plugin will be divided into 3 sections: the plugin class, the export function and the definition file. We’ll begin by writing the code for our plugin class. Select File->New… and under the Files tab select C/C++ Header File give it a name and select OK.

Our plugin class will be derived off of a class defined in Milkshape’s plugin system. Go ahead and open msPlugIn.h from the SDK. You can see the declaration of cMsPlugIn and get an idea of what our class needs to function properly. So let’s start adding come code to our project. In the header you created, add the following:

#include \"msPlugIn.h\"

class MyPlugin : public cMsPlugIn
{
public:
   MyPlugin();
   virtual ~MyPlugin() { }

   int GetType();
   const char *GetTitle();
   int Execute(msModel *);

private:
   char szTitle[64];
};

A brief description of the above: GetType will return an integer to Milkshape telling which menu to place the link to the plugin; GetTitle will return szTitle, the text to place in the menu for the plugin, and Execute gets called when the plugin is selected from Milkshape’s menu. Easy, huh?

Now to make the class definition. Select File->New… and under the Files tab select C++ Source File. Give the file a name and select OK. In our new source file, add the following:

#include "plugin.h"
#include "mslib.h"

MyPlugin::MyPlugin()
{
   strcpy(szTitle, "MyPlugin");
}

int MyPlugin::GetType()
{
   return cMsPlugIn::eTypeTool;
}

const char *MyPlugin::GetTitle()
{
   return szTitle;
}

int MyPlugin::Execute(msModel *model)
{
   return 0;
}

First we see the include statements, giving us access to our class declaration and Milkshape’s plugin interface. Next we see our constructor. Here is where we give our plugin a name. This is the string that will be displayed in Milkshape’s menu. Next, you’ll see the definition of GetType. This function returns one of the enumerations defined in the cMsPlugIn class. There is an enumeration for each slot available to place your plugin link. The GetTitle function simply returns the szTitle variable. Lastly, we see Execute. Milkshape calls this guy when the plugin is executed. If you are making an importer, this function will be called with a newly allocated msModel, ready for you to populate with your own data. Exporters and tools will pass the current model into this function for you to edit.

Is that it? Almost. Now we need to add a handle so that Milkshape can get a hold of our class. In our source file, above the constructor add the following function:

cMsPlugIn *CreatePlugIn()
{
   return new MyPlugin;
}

This global function will be exported to allow Milkshape to get a pointer to our class. In order to make this function available publicly, we need our definition file. Select File->New… and under the Files tab select Text File. Name the file anything you want, but the extension must be .def. To this file we will add two things:

LIBRARY "msMyPlugin"

EXPORTS
   CreatePlugIn

The LIBRARY keyword must match the output filename we entered in the project settings. Without this matching, our DLL will not be built correctly. The second entry in this file describes which objects are exported from the DLL. The CreatePlugIn function is the only object we are exporting. And that’s it. We’re done writing the code.

Testing The Plugin
IF all has gone well so far you can attempt to build the plugin (press F7). If you encounter any warnings or errors, look back over your code and check it for any anomalys. If you entered your output path correctly in the project settings, then your DLL should be sitting in Milkshape’s main folder. Crank up Milkshape and select the menu that corresponds to the plugin type you specified in the GetType function. While you may be thinking that your plugin is quite useless, you’ve successfully built the framework for future Milkshape development.

What’s Next?
If you are feeling adventurous, browse around msLib.h in the Milkshape 3D SDK. That header outlines Milkshape’s interface for editing models. Also check back at this site for more information regarding Milkshape development.