|  Home   |  About   |  LW Resources   |  Tutorials   |  Software   |  Projects   |  Gallery   |  Links   |  Site Map   |  Contacts  |
   

Introduction:  I was chatting with a friend who wanted to get into writing plugins for LW and conned me into writing this quick and easy tutorial for him. This tutorial will show you how to get started with writing a HelloWorld plugin but more importantly how to just simply use VC6 to setup a project and a decent workflow for interacting fast and easy with LW while working on plugin development. I'm going to skip a lot of the why's of each part of the actual project setup since most people don't care about them at this level. The sad part for a lot of you is that this tutorial is for VC6 users. Yes I have VC7 and gcc but I still prefer to work with VC6 as does my friend. If you want to see how to get started in VC7 I highly recommend this great tutorial How to configure 'VisualC++ .net 2003' to compile LightWave 3DTM plugins. written by Patrik Westlin and hosetd by SplineCage. I'm assuming that if you have VC6 you know how to use it and know at least alittle bit of programming with c/c++. All that being said lets get started.

1 - Open your VC6 and create a new project (File->New or Ctrl+N.)

2 - Under the 'Projects' tab select 'Win32 Dynamic-Link Library, select the directory you want the new project to be created in and give it a Project Name. I used LW_HelloWorld for mine. We will give the compiled a different plugin name later so don't stress on the project title righ now. Go ahead and hit 'OK'.

3 - In the next step of the wizard select to create 'An empty DLL project' and hit 'Finish'

4 - The next wizard steps just ask you to accept and finish the project creation say 'OK' to those dialogs.

5 - We now have our new project but we have a few things we need to do. First we need to add a few files to our project. So open Windows Exploder, err Explorer and navigate to your LightWave 8 directory. Then navigate to its 'SDK\source' directory. In there you'll find the files you'll need.

serv.def
servdesc.c
servmain.c
shutdown.c
startup.c
username.c

I almost always include all those files except the username.c. So copy them, except the username.c file, and paste them into your project directory.

I'm assuming that you have already built the server.lib library. If not don't worry. If you want to build it, and I recommend you do, just check out the SDK docs, they'll explain how to do it fairly decently.  Even with the lib built I usually don't worry about it and add these files? Why because many moons ago someone said I could do it without having to build and worry about a release and debug copy of the library. Sure enough it works.

6 - In your 'File View' tab right click on the 'Source Files' folder and select 'Add Files to Folder'. Now add all the files you just placed into your directory except for the servdesc.c file.

7 - We are almost there gang. We just have to make a couple of project setting changes and we should be ready to play. So right click on the LW_HelloWorld project and select 'Settings'. First make sure you switch 'Settings For:' to 'All Configurations'.

8 - Jump to the 'Debug' tab. It is possible to debug your plugin with LW but you need to let it know what's happening where. So in the 'Executable for debug session' give it the path and file of the executable you plan on working with(in). For this tutorial we'll be using Layout but you'll need to change this to Modeler.exe if that's the app your building a plugin for. The 'Working directory' just needs the path to the executable and the 'Programs arguments' needs the path and any arguments you want to use to start the executable up with. I have added the -0 and -c arg's. You can also add in the -d arg, which will get Layout/Modeler running in a debug mode for easier debugging. However I have found that unless I really need it I leave the -d arg out.

9 - Jump to the C/C++ tab and switch the 'Category' to 'Precompiled Headers'. Unless you are creating your own precompiled headers for your plugins for some bizarre reason then make sure you switch it to 'Not using precompiled headers'

10 - Now jump to the 'Preprocessor' Category. I'm not 100% sure what preprocessor definitions really have to be here to get things to work right but I do know that things work really well with these definitions. NDEBUG,WIN32,_WINDOWS,_X86_,_WIN32

You'll also need to add the path to your SDK\includes directory in the 'Additional include directories'.

11 - With these settings you are all ready to go and start writing your plugin code. However I want to show you a cool trick to make life easier for you, well at least it does for me and this is the real reason why I'm writing this tutorial. First jump back into exploder, ( Windows Explorer) and navigate to where you normally store your plugins for LW. Create a new directory under it named something like 'Development', 'Test' or whatever you like. I normally use 'Development' but for this tutorial I created a new one named 'Test'. Copy the full path to this directory. Back in VC6 move to the 'Link' tab. Under the 'Output file name' paste the path to your new directory. Now at the end of it type in the name you want to call your plugin file. I called mine HelloWorld.p. Normally VC6 is going to save your compiled file under a default 'Debug' or 'Release' directory with a .dll extension. We need a .p extension and we don't want to keep moving the file to our storage directory all the time this takes care of both problems. We are not completely done with our trick yet. I'll finish it in a few minutes.

12 - Now we are ready to write our first plugin. This being our first we have to do the traditional 'HelloWorld' dialog. So select 'File->New'. Under the 'Files' tab select 'C++ Source File' and name it 'hello.c'

13 - I have no desire to waste time in this tutorial explaining what is what and why so I'll just show you the remedial code for our first plugin. It's just from a code shell that I made for myself based on some sample code from way back in LW 6. Its commented semi-decently so you can follow along and somewhat figure out what is going on. What I will do is create a separate series of tutorials that will actually teach you how to program LW plugins using the LW SDK. For now just copy the code into your new hello.c file. The code can be found at the bottom of this page.

14 -Once you have the code in place then go ahead and build your project (Build->Rebuild All). When it is finished you should not have any errors or warnings and if you look in your new plugin Development directory you should see your new plugin.

15 - OK now to setup the second half of the quick workflow setup I promised earlier. Go ahead and open Layout.

16 - Naviagte to Utilities->Plugins->Add Plugins and then navigate to your plugin development directory you created earlier. Finally select your new plugin. You should then get a message stating '1 plugins have been successfully added.'.

17 - Now lets make life easier for us. Go to 'Edit->Edit Menu Layout' and the 'Configure Menus' panel will open up.

18 - Under the 'Menus' column, go down to the 'Utilities' row and click on the arrow to expand it. Now click on the arrow next to the 'Plugins' to expand it. Now just click on the 'Additional' row to select it but not expanding it. With it selected hit the 'New Group' button. You should have a new row called 'New Group' under the 'Additional' row.

19 - Select the 'New Group' you just created and choose 'Rename' and name it something like 'Development'.

20 - Under the 'Command' column on the left go down, click on the arrow next to 'Plugins' and then scroll down till you find your 'HelloWorld' Plugin. Now simply select it by clicking on it and dragging the selection to your new 'Development' group (the little blue bar should be under and just to the right side of the 'Development' row.

21 - Now hit 'Done' and click on your new Development menu selection you will find your new 'HelloWorld' plugin. Go ahead and select it and voila there's your very first LW plugin. Granted its nothing special but it's a start.

22 - So now you ask what's so special about all we did setting up these directories, groups and stuff. We'll for one it is a nice organized way of keeping all of your development plugins separated from all your cool and often extensive list of plugins. You compile straight to the Development directory so no continual moving of files all around. You have a nice neat group separate from all the other plugins in Layout (mind you, you could and should do the same Menu layout setup in Modeler as well if you plan on building Modeler plugins.  The nice thing by leaving outthe -d arg parameter from the debug parameters list is that you can look at your plugin and test it. Close the plugin, jump back into VC (with Layout still running!) make adjustments to your code, recompile then shift-tab back into Layout/Modeler, open your Development menu selection, select your plugin and bham there she is! None of that moving files around, adding this and that. Cool Aye! True time maybe money but sanity rules all! 

23 - Well that's all for this tutorial. We never really talked about any coding but we have a fast, easy way to start up and work on your plugins and mind you this is just my way. I'm sure there are others that have other, maybe better, ways of setting things up, I just have yet to see them so here's one way for you. So enjoy and start reading through the SDK documentation.

In upcoming tutorials I'll start walking you through creating panels for real and all the neat little GUI features the LW SDK has to offer us.

                                                             Hello.c CODE
/*****************************************************************************\
                                hello.c

Your first 'Hello World' LightWave plugin
\*****************************************************************************/
#include <lwserver.h>            // All plug-ins need this
#include <lwgeneric.h>          // For the LayoutGeneric class
#include <lwpanel.h>            // For panels
#include <stdio.h>               // For NULL #define

LWPanelFuncs *panf;           // Panel functions
LWPanelID panelID;              // The panel
LWControl *ctl;                   // Control(s) on the panel
LWPanControlDesc desc;       // Used by macros in lwpanel.h

/*****************************************************************************\
                          HelloworldPanel()

The activation function.  Layout calls this when the user selects the
generic from the list of generics in Layout's interface.
\*****************************************************************************/
XCALL_(int)
HelloworldPanel(long version, GlobalFunc *global, LWLayoutGeneric *local,
   void *serverData)
{
   int OK;
   const char *szText[] = {"My Hello World LightWave Plugin!", NULL};

   //Make sure you have a valid plugin version
   if(version != LWLAYOUTGENERIC_VERSION)
      return AFUNC_BADVERSION;

   //Get the panel fxns
   panf = global(LWPANELFUNCS_GLOBAL, GFUSE_TRANSIENT);

   //If the panel is not valid then exit
   if(!panf)
      return AFUNC_BADGLOBAL;

   //Init panel fxns and create the panel
   panf->globalFun = global;

   panelID = PAN_CREATE(panf, "Hello World!");
   
   //If the panel is not created correctly then exit
   if(!panelID) 
     return AFUNC_BADGLOBAL;

   //Add our Hello World msg
   ctl = TEXT_CTL(panf,panelID,"",szText);

   //Display the panel
   OK = panf->open(panelID, PANF_BLOCKING | PANF_CANCEL);

   //Free up the panel
   PAN_KILL(panf, panelID);

   //All done time to go learn more
   return AFUNC_OK;
}

/*****************************************************************************\
The all important server description which LW looks at first. This fxn
tells LW what plugins are included in this project, thier type, name 
and where the activation fxn is..
\*****************************************************************************/
ServerRecord ServerDesc[] = 
{
  {LWLAYOUTGENERIC_CLASS, "Hello World", HelloworldPanel},
  {NULL}
};

SPECIAL NOTE FOR WORKING WITH AND COMPILING C++ .cpp FILES

Normally you would create and build LW plug-ins written in pure C code. However if you're like me you like some of the benefits of writing in C++. In order to get your plug-ins to compile properly you will need to make a couple of type-casting changes in your code and the above code. The first thing you will need to do is explicitly cast the ServerRecord as extern C so change:

ServerRecord ServerDesc[] = 
{
  {LWLAYOUTGENERIC_CLASS, "Hello World", HelloworldPanel},
  {NULL}
};

		to
		
extern "C" {ServerRecord ServerDesc[] = 
{
  {(const char*)LWLAYOUTGENERIC_CLASS, (const char*)"Hello World", (ActivateFunc*)HelloworldPanel},
  {NULL}
};
}		
Notice that the each of the ServDesc[] parameters were also explicitly type cast as well.

One last note is that you will need to explicitly typecast some of the LW functions to keep them properly aligned. How will you know if you need to do this? Well if you get a message like this;

F:\DiskK_Programming\LW_HelloWorld\hello.cpp(35) : error C2440: '=' : cannot convert from 'void *' to 'struct st_LWPanelFuncs *'
        Conversion from 'void*' to pointer to non-'void' requires an explicit cast

That would be a good indication you will need to explicitly type cast the offending function call. In this case you will need to change this line of code

     //Get the panel fxns
     panf = global(LWPANELFUNCS_GLOBAL, GFUSE_TRANSIENT);
		
		to
		
     //Get the panel fxns
     panf = (LWPanelFuncs*)global(LWPANELFUNCS_GLOBAL, GFUSE_TRANSIENT);

Noting that panf was originally casted as LWPanelFuncs.

If you really want to learn more about programming plugins and or LScripting I highly recommend you check out Carbon8's, 'SplinCage' site. Its home to all things CG programming related! http://www.splinecage.com/index.php

Please feel free to contact me with any question or comments: aurora@auroragrafx.com