12.17 Plug-in Software Development Kit (SDK)

The plug-in system is supported only by VEGA ZZ. A plug-in is a DLL that must be placed in the Plugin directory and it's loaded automatically when VEGA ZZ starts. This DLL must have three exported functions:

 

VGP_EXTERN VGP_PLUGINFO * VGP_EXPORT Init(VGP_VEGAINFO *);
VGP_EXTERN VG_BOOL VGP_EXPORT Free(void);
VGP_EXTERN VG_BOOL VGP_EXPORT Call(VG_UWORD, void *);

 

All definitions, constants and macros are included in plugin.h header file.

 

12.17.1 Function description

VGP_EXTERN VGP_PLUGINFO * VGP_EXPORT Init(VGP_VEGAINFO *)

 

It's the first function that VEGA ZZ calls to initialize the plug-in. It must contain the initialization code for the plug-in. VEGA ZZ passes the pointer to VGP_VEGAINFO structure in which are present some useful information:

typedef struct {
  HD_UWORD      Version;            /* VEGA version                             */
  HD_UWORD      Release;            /* VEGA release                             */

  HD_ULONG *    GlobErr;            /* Pointer to global error variable         */
  HD_CHAR *     ErrStr;             /* Pointer to error string                  */

  HD_ATOM **    BegAtm;             /* Pointer to the pointer of the atom list  */
  HD_ATOM **    LastAtm;            /* Pointer to the pointer to the last atom  */
  HD_ULONG *    TotalAtm;           /* Pointer to the number of atoms variable  */
  HD_LIST **    SrfList;            /* Pointer to the pointer of the surface    */
                                    /* list defined by HD_LIST in hyperdrive.h  */
  HD_CHAR *     Result;             /* Pointer to the result string             */
  HD_VOID *     AppHandle;          /* Application handle                       */
  HWND          ComPort;            /* Communication port                       */
  HD_VOID *     Res1;               /* Reserved pointer                         */
  HDC           hDC;                /* Device context                           */
  HGLRC         hRC;                /* Rendering context                        */
  HMENU         hMenu;              /* Handle of the main menu                  */
  HMENU         hPopUpMenu;         /* Handle of the popup menu                 */
  HWND          hWnd;               /* Handle of the main window                */

  HD_CHAR       IniFile[MAX_PATH];  /* Plugin .ini file with full path          */
  HD_CHAR       PrgPath[MAX_PATH];  /* Program path \ terminated                */

  /**** Super API ****/

  HD_VOID       (*VegaCmd)(const HD_CHAR *);            /* Send a command               */
  HD_VOID       (*Free)(HD_VOID *);                     /* Free the memory              */
  HD_VOID *     (*Malloc)(HD_ULONG);                    /* Alloc the memory             */
  HD_ULONG      (*ChoosePixelFormat)(HD_VOID *Dc, HD_LONG *PixelFormat, HD_LONG Multisample, HD_LONG Stereo, HD_LONG RbgBits);
                                                        /* Choose the pixel format      */
  HD_VOID *     (*AW_InitAlphaWin)(HWND);               /* Initialize the alpha blend   */
  HD_VOID       (*AW_FadeOut)(HWND);                    /* Fade out the window          */
  HD_VOID       (*WaitCalc)(HD_VOID);                   /* Wait the calculation end     */
  HD_VOID       (*UndoDisable)(HD_BOOL);                /* Enable/disable the undo      */
  HD_BOOL       (*UndoPop)(HD_BOOL);                    /* Pop the redo/undo object     */
  HD_BOOL       (*UndoPush)(HD_LONG, const HD_CHAR *);  /* Push the undo object         */
  HD_BOOL       (*GetProcAddresses)(HD_VOID **, HD_CHAR *, int, ... );
                                                        /* Load a DLL dynamically       */
  HD_VOID       (*RegisterForm)(const HD_CHAR *Name, HD_VOID **Form, HD_VOID (*ShowFunc)(int));
                                                        /* Register the VCL form        */
  HD_VOID       (*UnRegisterForm)(HD_VOID **Form);      /* Unregister the VCL form      */
#ifdef __HDRIVE_H
  HD_LONG       (*VegaCmdThs)(HD_STRING Result, const HD_CHAR *Cmd);
                                                        /* VageCmd() thread safe        */
#endif
} VGP_VEGAINFO;

You must remember that this structure is read-only and the reserved pointers are for future uses.
The user-defined plug-in must return the pointer to VGP_PLUGINFO structure that VEGA ZZ manage it without writing anything.

typedef struct {
  HD_UWORD      Version;            /* Plugin version                           */
  HD_UWORD      Release;            /* Plugin release                           */
  HD_UWORD      VegaVer;            /* Minimum VEGA version required            */
  HD_UWORD      VegaRel;            /* Minimum VEGA release required            */

  HD_UWORD      Type;               /* Plugin type                              */
  HD_CHAR *     Name;               /* Plugin name                              */
  HD_CHAR *     Copyright;          /* Copyright message                        */

  VGP_FUNC *    FuncList;           /* List of the functions                    */
} VGP_PLUGINFO;

In this structure you can specify the version and the release of the plug-in, the minimum required version and release of VEGA ZZ (VegaVer and VegaRel), the plug-in type (Type),  the plug-in name (Name), the copyright message (Copyright) and the exported function list (FuncList). The plug-in type can be:

 

Value Constant name Description
0 VGP_TYPE_GENERIC Generic plug-in
1 VGP_TYPE_CALC Calculation plug-in
2 VGP_TYPE_CONSOLE Console plug-in
3 VGP_TYPE_RENDER Rendering plug-in
4 VGP_TYPE_CUSTOM Custom plug-in (for internal use only)

 

At the present time, only the VGP_TYPE_GENERIC is available for the user.

FuncList is a vector in which is included the entry for each user-defined function that VEGA ZZ can call.

typedef struct {
  HD_CHAR  *    MenuItem;           /* Menu item string                         */
  HD_UWORD      MenuPos;            /* Menu item to call the plugin function    */
  HBITMAP       MenuBmp;            /* 16x16 bitmap handle for menu icon        */
  HD_BOOL       MenuEnabled;        /* Set to TRUE to enable from the beginning */
  HD_ULONG      MenuAct;            /* Menu activation                          */
  HD_UWORD      Function;           /* Function code                            */
} VGP_FUNC;

MenuItem is the pointer to the string that is shown in the main menu that can be used to activate the specific function. VEGA ZZ calls Call function using Function as argument. Function is the function code associated to the menu item. The reserved function codes are:

 

Value Constant name Description
0 VGP_FUNC_NONE None
1 VGP_FUNC_ABOUT About function (called when you press the About button in the plug-in manager).
2 VGP_FUNC_CONFIG Configure function (called when you press the Configure button in the plug-in manager).
3 VGP_FUNC_HELP Help function (called when you press the Help button in the plug-in manager).
4 VGP_FUNC_MINIMIZE This function is called when the main window is minimized.
5 VGP_FUNC_RESTORE This function is called when the main window is restored.

 

The user functions must have a function code greater than 100 (e.g. 101, 102, etc) and no limits are present about the number of them.

MenuPos is the code that you can use to set the menu in which the item will be shown. The vertical position is selected by VEGA ZZ at the end of the standard menu item. The following tables shows the MenuPos values:

 

Value Constant name Menu name
0 VGP_MPOS_NONE Invisible menu item
1 VGP_MPOS_EDIT Edit menu
2 VGP_MPOS_VIEW View menu
3 VGP_MPOS_CALC Calculate menu
4 VGP_MPOS_TOOLS Tools menu
5 VGP_MPOS_HELP Help menu
6 VGP_MPOS_POPUP Popup menu
7 VGP_MPOS_PLUGCFG Tools Plug-in configuration submenu
8 VGP_MPOS_FILEOPEN File (open) menu
9 VGP_MPOS_FILESAVE File (save) menu
10 VGP_MPOS_BIOTOOLS Bioinformatics menu
11 VGP_MPOS_COLOR Color menu
12 VGP_MPOS_DISPLAY Display menu
13 VGP_MPOS_PROTCHK Calculate Protein check submenu
14 VGP_MPOS_DOCKING Calculate Docking submenu
15 VGP_MPOS_DOWNLOAD File Download submenu
16 VGP_MPOS_BUILD Edit Build submenu

 

MenuBmp is the handle of the 16x16 bitmap that is shown at the left of the item in the menu. If NULL, no bitmap is shown. A good idea is to store the bitmap in the resources of the DLL.
 

Example:

In the .rc file:

MMPIC_USER01 BITMAP "icon_16.bmp"
...

The initialization  code can be:

VGP_FUNC FuncList[] = {
  {"My function", VGP_MPOS_TOOLS, NULL, TRUE , VGP_CM_ALL , VGP_FUNC_USER_01},
  /**** Don't delete the last line ****/
  {NULL            , VGP_MPOS_NONE   , NULL, FALSE, VGP_CM_NONE, VGP_FUNC_NONE   }
};
...
PlugInfo.FuncList[1].MenuBmp = LoadBitmap(GetModuleHandle("MyPlugin.dll"),
                                          MAKEINTRESOURCE(MMPIC_USER01));
...

If MenuEnabled is TRUE (0),  the menu item is already enabled when VEGA starts. If it's FALSE (0), the item is disabled. The activation can be changed trough MenuAct variable. The following table shows the activation conditions:

 

Value Constant name Condition
0 VGP_CM_NONE Never
1 VGP_CM_NEW The New command is executed
2 VGP_CM_MOLE The molecule is loaded
4 VGP_CM_DEMO The demo mode is activated
8 VGP_CM_CALC A calculation is performed
16 VGP_CM_SURF A surface is loaded
32 VGP_CM_TRJA The trajectory analysis is started
64 VGP_CM_PKMS Measure picking
128 VGP_CM_NOEDIT No molecule edit
256 VGP_CM_SAVETRJ Trajectory saving
512 VGP_CM_MANUAL Manual control

 

You can combine more than one condition using the or operator (e.g. VGP_CM_NEW|VGP_CM_MOLE). If you want the item always enable, use the special VGP_CM_ALL constant.

 

IMPORTANT:
You must remember to end the VGP_FUNC array  with a null item, because it's used by VEGA ZZ to detect the last item.

 

 

VGP_EXTERN VG_BOOL VGP_EXPORT Free(void)

 

This function is called by VEGA to release all resources when the program is closing. In this subroutine you can include all code to free the resources that are used by your plug-in.

 

 

VGP_EXTERN VG_BOOL VGP_EXPORT Call(VG_UWORD, void *)

 

It's the core of the plug-in because this function select the  code associated with a specific menu item. When you select a plug-in menu item or press a button in the plug-in manager, VEGA ZZ calls this subroutine passing the function code and a void pointer that is reserved for future uses. A generic Call() function could be:

/**** Generic Call function ****/

VGP_EXTERN VG_BOOL VGP_EXPORT Call(VG_UWORD Func, void *Arg)
{
  switch(Func) {

  case VGP_FUNC_ABOUT:          /* About the plug-in           */
    printf("About\n");
    break;

  case VGP_FUNC_CONFIG:         /* Configure the plug-in       */
    printf("Configuration\n");
    break;

  case VGP_FUNC_HELP:           /* Show the help               */
    printf("Help\n");
    break;

  case VGP_FUNC_USER_01:        /* Activate the first function */
    printf("Function 1 activated\n");
    break;

  /**** If needed, you can insert other cases ****/

  } /* End of switch */

  return TRUE;
}

The Call() function should return a value: TRUE (1) if it's executed without errors, FALSE (0) if an error occurs.

 

12.17.2 How to read/write the atom list

VEGA ZZ stores the atom information in a memory list. Each atom has a its memory space allocated by calloc().  The end signal of the list is a null pointer to next atom structure. In the VGP_VEGAINFO structure you can find the pointer to the pointer to the first element in the atom list (**BegAtm), the pointer to the pointer to the last element (**LastAtm) and the pointer to the total number of atoms in memory (*TotalAtm).
This is a simple code to read the atom list:

VGP_VEGAINFO *VgInfo;    /* Initialized by Init() */
void MyReadAtm(void)
{
  ATOMO    *Atm;
  for(Atm = *VgInfo -> BegAtm; Atm; Atm = Atm -> Ptr) {

    /* Print the atom name and the coordinates */

    printf("%4.4s %f %f %f\n", Atm -> Name.C, Atm -> x, Atm -> y, Atm -> z);
  }
}

For more information about the ATOMO structure, see vgtypes.h header file.

 

12.17.3 How VEGA ZZ can be controlled by a plug-in

VEGA ZZ can be controlled by a plug-in using the standard windows messaging system. You can use this simple subroutine:

VGP_VEGAINFO *VgInfo;    /* Initialized by Init() */
/**** Send a VEGA command ****/

VG_ULONG SendVegaCmd(char *Com)
{
  COPYDATASTRUCT        Cds;

  Cds.dwData = 0;
  Cds.lpData = (void*)Com;
  Cds.cbData = strlen(Com) + 1;

  return SendMessage(VgInfo -> hWnd, WM_COPYDATA, NULL, (LPARAM)&Cds);
}

The argument is the string of the command to send to VEGA ZZ. If the command fails, the function return the global error code, otherwise return 0. If the sent command returns a value, you can read it trough the Result string pointer in VGP_VEGAINFO structure.

 

12.16.4 Saving/loading the plug-in configuration

As convention, the plug-in configuration should be loaded and saved in ...\VEGA ZZ\Config\Plugins.ini file. To manage this file, use GetPrivateProfileString() and WritePrivateProfileString() API functions. 

 

12.17.5 The null plug-in

This is a simple example of a plug-in that performs anything but is useful as skeleton to build your plug-in.


/*******************************************
****         VEGA Plug-in System        ****
****              Main code             ****
**** (c) 2002-2023, Alessandro Pedretti ****
*******************************************/


#include "..\plugin.h"

/**** Global variables ****/

VGP_VEGAINFO    *VgInfo;

/**** Description of the functions ****/
/**** All items are optional       ****/

VGP_FUNC FuncList[] = {
  {NULL          , VGP_MPOS_NONE   , NULL, TRUE , VGP_CM_NONE, VGP_FUNC_ABOUT  },
  {"Null Config.", VGP_MPOS_PLUGCFG, NULL, TRUE , VGP_CM_ALL , VGP_FUNC_CONFIG },
  {"Null Help"   , VGP_MPOS_HELP   , NULL, TRUE , VGP_CM_ALL , VGP_FUNC_HELP   },
  {"Start Null"  , VGP_MPOS_EDIT   , NULL, FALSE, VGP_CM_MOLE, VGP_FUNC_USER_01},

  /**** Don't delete the last line ****/

  {NULL          , VGP_MPOS_NONE   , NULL, FALSE, VGP_CM_NONE, VGP_FUNC_NONE   }
};

/**** Plug-in info structure ****/

VGP_PLUGINFO PlugInfo = {
  1,                            /* Plug-in version                         */
  0,                            /* Plug-in release                         */
  1,                            /* Minimum VEGA version required           */
  4,                            /* Minimum VEGA release required           */

  VGP_TYPE_GENERIC,             /* Plug-in type                            */
  "Null",                       /* Plug-in name                            */
  "Alessandro Pedretti",        /* Copyright message                       */
  FuncList                      /* List of the functions                   */
};


/**** Plug-in initialization ****/

VGP_EXTERN VGP_PLUGINFO * VGP_EXPORT Init(VGP_VEGAINFO *VegaInfo)
{
  VgInfo = VegaInfo;

  /* Enter here your initialization code */
  /* if needed.                          */

  printf("Null: Initialization\n");

  return &PlugInfo;
}


/**** Execute the plug-in function ****/

VGP_EXTERN VG_BOOL VGP_EXPORT Call(VG_UWORD Func, void *Arg)
{
  switch(Func) {

  case VGP_FUNC_ABOUT:          /* About the plug-in           */
    printf("Null: About\n");
    break;

  case VGP_FUNC_CONFIG:         /* Configure the plug-in       */
    printf("Null: Configuration\n");
    break;

  case VGP_FUNC_HELP:           /* Show the help               */
    printf("Null: Help\n");
    break;

  case VGP_FUNC_USER_01:        /* Activate the first function */
    printf("Null: Activated\n");
    break;
  } /* End of switch */

  return TRUE;
}


/**** Deallocate the resources ****/

VGP_EXTERN VG_BOOL VGP_EXPORT Free(void)
{
  printf("Null: Release all resources\n");

  return TRUE;
}

You can find a more complex example in Dhrystone plug-in source code, included in the SDK.