CR, thanks
WOLF, basically, most of C++ code doesn't need to be modified unless your dealing with returning strings or are passing strings into a plugin.
To create a plugin, you need to create a C++ CLR Class Library project. Your project must reference the Redist/Plugins/.NET version/DGDKPlugins.dll file located with the DGDK.NET installation. This will allow your main plugin class to inherit CDGDKPlugin, so for example, my CSM Importer plugin class looks like this:
// CSMImporter.NET.h
#pragma once
#include "CSM_Importer.h"
using namespace System;
namespace CSMImporterNET {
public ref class CSMImport : CDGDKPlugin
{
public:
CSMImport( CDGDKGlobals ^ oGlobals )
: CDGDKPlugin( oGlobals )
{
Constructor();
}
~CSMImport()
{
Destructor( m_oGbl );
}
int Load( String ^ strFileName, int nLMFlag ) {
return CSM_Load( m_oGbl, strFileName, nLMFlag );
}
String ^ Version() {
String ^ strVersion = gcnew String(CSM_PLUGIN_VERSION);
return strVersion;
}
int GetLastError() {
return CSM_GetLastError();
}
String ^ GetLastErrorText() {
return CSM_GetLastErrorText();
}
int MakeCSMFromMemblock( int nMB, int nLMFlag ) {
return CSM_MakeCSMFromMemblock( m_oGbl, nMB, nLMFlag );
}
int Count( int nType ) {
return CSM_Count( nType );
}
void Clear( void ) {
CSM_Clear( m_oGbl );
}
int PropertyCount( int nType, int nIndex ) {
return CSM_PropertyCount( nType, nIndex );
}
int Flags( int nType, int nIndex ) {
return CSM_Flags( nType, nIndex );
}
String ^ Property( int nType, int nField, int nIndex, int nProperty ) {
return CSM_Property( nType, nField, nIndex, nProperty );
}
String ^ PropertyByKey( int nType, int nIndex, String ^ strKey ) {
return CSM_PropertyByKey( nType, nIndex, strKey );
}
String ^ TextureName( int nTexture ) {
return CSM_TextureName( nTexture );
}
int TextureID( int nTexture ) {
return CSM_TextureID( nTexture );
}
int TextureCreate( String ^ strName, int nImageID ) {
return CSM_TextureCreate( m_oGbl, strName, nImageID );
}
int SurfaceCount( int nIndex ) {
return CSM_SurfaceCount( nIndex );
}
int ObjectToGroup( int nObjID ) {
return CSM_ObjectToGroup( nObjID );
}
int GroupToObject( int nGroup ) {
return CSM_GroupToObject( nGroup );
}
int PivotToGroup( int nPivot ) {
return CSM_PivotToGroup( nPivot );
}
int GroupToPivot( int nGroup ) {
return CSM_GroupToPivot( nGroup );
}
int MeshToGroup( int nMesh ) {
return CSM_MeshToGroup( nMesh );
}
int EntityToGroup( int nEntity ) {
return CSM_EntityToGroup( nEntity );
}
float EntityX( int nEntity ) {
return CSM_EntityX( nEntity );
}
float EntityY( int nEntity ) {
return CSM_EntityY( nEntity );
}
float EntityZ( int nEntity ) {
return CSM_EntityZ( nEntity );
}
int PivotID( int nEntity ) {
return CSM_PivotID( nEntity );
}
int SurfaceTexture( int nMesh, int nSurface ) {
return CSM_SurfaceTexture( nMesh, nSurface );
}
int TextureMesh( int nMesh, int nSurface, int nTexture ) {
return CSM_TextureMesh( m_oGbl, nMesh, nSurface, nTexture );
}
void Move( int nPivot, float fX, float fY, float fZ ) {
CSM_Move( m_oGbl, nPivot, fX, fY, fZ );
}
void Position( int nPivot, float fX, float fY, float fZ ) {
CSM_Position( m_oGbl, nPivot, fX, fY, fZ );
}
void Angle( int nPivot, float fX, float fY, float fZ ) {
CSM_Angle( m_oGbl, nPivot, fX, fY, fZ );
}
void Rotate( int nPivot, float fX, float fY, float fZ ) {
CSM_Rotate( m_oGbl, nPivot, fX, fY, fZ );
}
void Show( int nPivot ) {
CSM_Show( m_oGbl, nPivot );
}
void Hide( int nPivot ) {
CSM_Hide( m_oGbl, nPivot );
}
void BlendMode( long dwBlendMode ) {
CSM_BlendMode( dwBlendMode );
}
void MapOffset( float fX, float fY, float fZ ) {
CSM_MapOffset( fX, fY, fZ );
}
void InitialObject( int nObj ) {
CSM_InitialObject( nObj );
}
void InitialImage( int nImage ) {
CSM_InitialImage( nImage );
}
int SetCurrentMap( int nMap ) {
return CSM_SetCurrentMap( nMap );
}
int GetCurrentMap( void ) {
return CSM_GetCurrentMap();
}
void ShowMap( void ) {
CSM_ShowMap( m_oGbl );
}
void HideMap( void ) {
CSM_HideMap( m_oGbl );
}
};
}
All of the C++ code itself is located in a separate file where I can use the #pragma managed and #pragma unmanaged macros to determine whether parts of the C++ code are handled as unmanaged code or vice versa.
All functions that handle strings, must be dealt with in the correct way, and I should direct you to this article at Microsoft's MSDN Knowledge base for this purpose:
http://msdn2.microsoft.com/en-us/library/ms235631(VS.80).aspx
It took me a little while to work through the issues of managed/unmanaged code symantics, but basically because of the shear genius of the guys who created the /CLR compiler option, a majority of normal C++ code can be compiled into .NET MSIL, allowing plugins to be created for the .NET language very very quickly.
I'll try to assist in areas that are a bit grey, but basically, this is the gist of it. Lastly, when testing your plugin by creating a normal DGDK.NET application, you must also add the 'dgdkPlugins.cs' or 'dgdkPlugins.vb' file so that you can instanciate your plguin's class using the GetDGDKGlobals() function. So typically, this is how my CSM plugin class is used in Visual Basic.NET:
Imports CSMImporterNET
Module CSMImporterDemo
Dim oCSMPlugin As New CSMImport(GetDGDKGlobals())
Sub Main()
Dim strVersion As String
If Not InitializeDGDK("") Then End
oDBDisplay.SetWindowOff()
oDBCore.SyncOn()
oDBCore.SyncRate(60)
oDBCamera.AutoCamOff()
oDBCamera.PositionCamera(0, 150, 0)
oCSMPlugin.Load("order_entry.csm", 2)
strVersion = oCSMPlugin.Version()
While oDBP.LoopGDK
oDBText.Text(0, 0, strVersion)
oDBCamera.ControlCameraUsingArrowKeys(0, 5.0F, 3.0F)
oDBCore.Sync()
End While
oCSMPlugin.Dispose()
End Sub
End Module
Hope that helps
Paul.