Our Properties: Gamasutra GameCareerGuide IndieGames Indie Royale GDC IGF Game Developer Magazine GAO
My Message close
Latest News
spacer View All spacer
 
February 10, 2012
 
Analyst questions validity of unusual January NPD results [3]
 
DICE 2012: Blizzard's Pearce on World Of Warcraft's launch hangover
 
DICE 2012: Insomniac's Price on Quality Of Life, ditching the 'Loser' badge [2]
spacer
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
February 10, 2012
 
Airtight Games
Art Director
 
Telltale Games
Core Technology - Senior Systems Engineer
 
High 5 Games
Technical Artist
 
XEOPlay Inc
Game Developer (Mobile)
 
Kabam
Lead Software Engineer - Flash
 
Kabam
Lead Software Engineer-Ruby
spacer
Latest Features
spacer View All spacer
 
February 10, 2012
 
arrow Principles of an Indie Game Bottom Feeder [18]
 
arrow Postmortem: CyberConnect 2's Solatorobo: Red the Hunter [1]
 
arrow Jerked Around by the Magic Circle - Clearing the Air Ten Years Later [39]
 
arrow Building the World of Reckoning [4]
 
arrow SPONSORED FEATURE: TwitchTV - How to Build Community Around Your Game in 2012 [13]
 
arrow Happy Action, Happy Developer: Tim Schafer on Reimagining Double Fine [9]
 
arrow Building an iOS Hit: Phase 1 [11]
 
arrow Postmortem: Appy Entertainment's SpellCraft School of Magic [5]
spacer
Latest Blogs
spacer View All     Post     RSS spacer
 
February 10, 2012
 
Audio Passes: Success Through Layering
 
What the current RPG can learn from Diablo 1
 
Double Fine's Kickstarter Windfall: Will Patronage Supplant Traditional Game Publishing? [5]
 
The Principles of Game Monetization
 
Did DoubleFine Just break the publishing model for good? [11]
spacer
About
spacer Editor-In-Chief/News Director:
Kris Graft
Features Director:
Christian Nutt
Senior Contributing Editor:
Brandon Sheffield
News Editors:
Frank Cifaldi, Tom Curtis, Mike Rose, Eric Caoili, Kris Graft
Editors-At-Large:
Leigh Alexander, Chris Morris
Advertising:
Jennifer Sulik
Recruitment:
Gina Gross
 
Feature Submissions
 
Comment Guidelines
Sponsor
Features
  From 3D Studio MAX to Direct 3D, Part 2: How to Create a Plug-In
by Loic Baumann [Programming, Visual Art]
Post A Comment Share on Twitter Share on Facebook RSS
 
 
March 20, 1998
 

This time we're going to talk about how to develop a MAX plug-in. Enclosed with this article are two samples of a simple Utility plug-in -- one for the Visual C++ 4.x / Max 1.x, and the other one for Visual C++ 5.x / Max x.x. These samples will give you an overview of an exporter plug-in's skeleton. To save time, you can personalize them for your own Utility plug-ins.

plug-ins Overview


MAX offers many types of plug-ins.  In MAX, a plug-in is a DLL which is explicitly loaded during the MAX's startup. Every type of plug-in has a specific file extension (i.e. .DLU for Utility plug-ins, .DLM for Modifier plug-ins, .DLO for procedural Object plug-ins, etc…).  This extension is used by MAX to differentiate common DLLs from plug-ins.

Normally, plug-ins written by third party developers are stored in the \plug-ins directory of MAX.  To generate a .DLU DLL stored in the \plug-ins directory of MAX,  a VC++ DLL project should be used. Each time a plug-in is recompiled, you have to take care that MAX is not running (or the new DLL version won't be generated as the previous is already running).  MAX's startup won't last too long if your computer owns enough RAM for everything (VC++, your project and MAX) to stay continuously inside. For people who never used DLLs here's a brief reminder.

Windows DLLs

A Dynamic Linked Library can be seen as an executable (.EXE) which contains functions callable by another executable. Like an executable, it can also contain its own resources (dialog template, string, icons, etc…). Standard DLLs only give you the possibility to export C-like functions. With Visual C++'s MFCs you can create a new kind of DLL called 'MFC Extension' where it's possible to export C++ classes. When a client program uses a DLL's functions, the DLL's header file must be included in the .cpp files that use the functions, and the DLL's library (file extension .lib) must be linked to the project. Only functions that were declared to exportation can be used by a client program. Exportation declarations can be done using .def file (for both regular and extension DLLs) or using Microsoft's specific tokens (for extension DLLs only).

As MAX is a pure Win32 program, DLLs are not supposed to use MFC and must be of the Regular type only.  Using the .def file of your plug-in's project, four functions have to be declared in exportation. You'll have to edit the .def to make it looks like :

LIBRARY themaxplug-in
EXPORTS
  LibDescription @1
  LibNumberClasses @2
  LibClassDesc @3
  LibVersion @4
SECTIONS
  .data READ WRITE

Each exported functions are associated with a number that will be used to make the dynamic link when the client (MAX) will call the DLL's functions. The most important function is the LibClassDesc(). It's used to returned an object that will be used by MAX to create the plug-in.

MAX is not a MFC based program, which leads to some difficulties when you want to use MFC inside your plug-in. As I'm a lazy programmer, I like to use MFC in my programs, so I'm going to describe the steps for the creation of a MFC based plug-in.

Typical steps to create a MFC based utility plug-in

There's two ways to create a MFC based plug-in: the first with static linking of MFC DLLs, and the second with shared MFC DLLs. Both have advantages and disadvantages. For static linking, the MFC functions and resources will be statically linked to your plug-in.  This will, however, make your plug-in bigger in size. The advantage is that you can use MFC transparently, like a typical MFC program. For shared MFC DLLs (also called dynamic linking of MFC DLLs), the advantage is you keep a short DLL, but as your plug-in is also a DLL, the utilization of MFC resources needs some extra code, as nested DLLs are not managed transparently concerning resources. I'll explain the first method only, as its implementation is easier, and more understandable. Your plug-in will increase in size by about 100kb more than with the second method.

For the following steps, you can check the samples provided for more details.

1: Create a new project based on a MFC AppWizard DLL, choose static linked of MFC.
2: Edit the generated .def file as described below.
3: Create a Dialog Resource Template for the plug-in's panel, the width must be 104 units.
4: Include the max.h header file in the DLL's main file.
5:

Override (using class wizard) the InitInstance and ExitInstance of the CApp class create by the AppWizard. Add the following code to the InitInstance method:


//Get the DLL's HINSTANCE
HINSTANCE hInstance = AfxGetResourceHandle();

//Init 3DS Max Custom Controls
InitCustomControls(hInstance);

//Init Win32 Controls
InitCommonControls();

return TRUE;

6 Change compilation settings to generate the DLL in the MAX's \plug-ins directory. Don't forget to change the DLL's extension to .DLU.
7: Add the MAX's "core.lib" and "util.lib" library files to your project.
8: Create a plug-in's description class. Look at the PlugDesc class of the sample.
9: Create a plug-in's panel class. Refer to the sample's PlugPanel class.
10: Generate a new Class ID using the Kinetix's "gencid" program and define a constant of it in your plug-in's header file. i.e. : #define TESTPLUG_CLASS_ID Class_ID(0x24f21f8d, 0x59140b2b)
11: For the Panel class and miscellaneous code implementations, refer to the sample's "PlugTest.cpp" and "PlugTest.h" files.

 

Once you succeed at compiling your plug-in, you have to test it, and if somehow it hangs (it happens, sometimes…) you may want to debug to see what's going on.

Debugging is an inevitable step of programming, and even if your program doesn't hang, it's always interesting to trace a program to see how everything works. Debugging a MAX's plug-in is not as easy as debugging a program. Normally, you choose the "Debug" compilation mode when you're in the debugging phase of your project, but it's not something you can do with MAX's plug-ins. Visual C++ proposes two compilation modes : Debug and Release. Typically, you develop your project using the Debug Mode, because it offers many advantages like source level debugging, special memory management, crash protection/checking, etc… Once you finish your project, you compile it using the Release Mode which optimizes your code and suppresses debug information and debug purpose checking to make your project shorter and faster at execution.

So, where's the problem?  Memory heaps are not managed the same way if you compile in Release or Debug mode.  And, if a Release compiled project frees a heap allocated with a Debug compiled project, a crash will occur. The version of MAX you're using was compiled using the Release Mode.  It's impossible to compile your plug-in using the Debug Mode. The only choice your have is to create a new compilation Mode that manages heaps the same way as the Release Mode, and which generates Debug Information for being debugged. For the sample, I've called this new compilation mode "Special 3DSMax".  To view the setting use the "Settings…" command of the VC++'s "Project" menu.

Provided are the steps to create this new compilation mode:

1: Select the "Configurations…" command of the "Build" menu.
2: For your plug-in's project, choose "Add…"
3: Choose a name for your new compilation mode, copy settings from the Release Mode, keep the Win32 platform.
4: Edit the Setting (ALT+F7) of your plug-in. Choose your new compilation mode.
5: In the "C/C++" tab, change the "Debug Info" to "Program Database", set the "Optimizations" to "Disable(Debug)".
6: In the "Link" tab, check the "Generate Debug Info" check box.

As the Debug Compilation Mode can't be used for the plug-in, you can remove it by repeating Step 1, selecting the Debug Mode of your plug-in, and clicking the "Remove" button. Some features that were available in Debug Mode won't be used with this mode:

- Special memory management, memory leak display at debug exit
- TRACE macros.
- ASSERT, ASSERTVALID macros.

 

As the setting was taken from the Release Mode, the Preprocessing define "NDEBUG" is declared.  You can remove it ("C/C++" tab of the Project setting panel, "Preprocessor definitions") and set a new define (ie "SPECIALMAX" )

The Sample

There's two zip files :

- PlugTest_VC4.zip, for Visual C++ 4.x, with the MAX 1.x SDK.
- PlugTest_VC5.zip, for Visual C++ 5.x, with any version of the MAX SDK.

 

For your projects to be compiled correctly, you'll have to perform some slight changes:

- Change the path for the plug-in output file name, ALT+F7, link tab.
- Change the path of the MAX's libraries. It's easiest to remove the already inserted ones, and add the new ones (using Project/Add to Project/Files…)
- Set the MAX's SDK include directory, using Tools/Option…, Directories' tab.

 

The sample demonstrates a little plug-in that provides basic information about the node you selected. I strongly recommend you look at every line, to understand how the MAX's basic functions work.

If you experience some problems or don't understand something, don't forget to search in the MAX's SDK help.


Loic Baumann is creator and lead programmer at Fatal Design., a small, French-based, game development company. For the last five months, Mr. Baumann has kept himself busy working on a development environment to create real-time 3d applications. Check out his progress at perso.aic.fr:80/lbaumann.  Mr. Baumann can be reached at lbaumann@aic.fr.

 
Article Start Page of
 
Comments


none
 
Comment:
 




UBM Techweb
Game Network
Game Developers Conference | GDC Europe | GDC Online | GDC China | Gamasutra | Game Developer Magazine | Game Advertising Online
Game Career Guide | Independent Games Festival | Indie Royale | IndieGames

Other UBM TechWeb Networks
Business Technology | Business Technology Events | Telecommunications & Communications Providers

Privacy Policy | Terms of Service | Contact Us | Copyright © UBM TechWeb, All Rights Reserved.