Welcome to the workshop"Easy plugins with Borland Delphi" for beginners |
Note: All products are registered trademarks of the software-produce and depend on their copyrights!
and sorry for my english...
Implement a DLL-funktion into a WDL
Addendum (some Acknex-types, -structures and functions)
To write a plugin for the Conitec 3DGS you'll need a supported version of
Borland Delphi (in this workshop we use Delphi 7/personal edition).
The necessary resources are available from version 3 to 7 for Delphi and for
Borland C 5.5 and Borland C++ Builder 3.x.
The sdk will be used here for 3DGS version 6.31.
All shown pictures are screenshots from Borland Delphi 7.0 personal edition.
The shown areas and topics are within other Delphi-versions named different
and/or at other locations.
At the internetpage from CONITEC (http://www.acknex.com/) you can find within the topic Downloads under Software / Updates the A5 Delphi Plugin SDK.
1. Load the sdk and unzip it to a directory on your computer.
2. Create within the lib-directory (e.g.: c:\programme\entwicklung\borland\delphi7\lib\) of your Delphi-Installation a subdirectory with the name 3dgs and copy all files from the sdk-directory of your Delphi-version (e.g. delphi7\).
3. Now you must also copy the file A5DLL2.PAS from the sdk-directory Delphi_DX8 in your lib\3dgs-subdirectory.
4. Start Borland Delphi and install a new package in the component administration:
Press ADD..., change to the \Lib\3dgs-directory and select the file A5SDK70.bpl.
The option "Build with runtime package" have not to be selected because the generated dll's wouldn't have necessary parts!
So then installation is completed!
To design a plugin is a very simple one:
1. Start Borland Delphi and create a ne dll-projekt:
2. Automatically the skeletal structure will be generated and should look like this:
library Project1; { Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. } uses
SysUtils,
Classes; {$R *.res} begin
end.
Beneath this library-Definition we need an separate unit within we
write our functions.
Therefor we create a new unit: (menu [File]-[New]-[Unit].
To correspond with the Acknex-engine we have to implement a header file with
the types and structures from the engine: the unit A5dll2.pas.
Just expand the uses-clause of the interface-declaration with A5DLL2:
unit unit1; interface uses SysUtils, Classes, A5DLL2; implementation end.
The skeletal structure now is finished and it's time to save our hard work.
I name my library "dll_3dgs.dpr" ans my unit "my_plugin.pas".
The above created skeletal structure now is the frame for all our functions we want to write for expanding the Acknex-engine.
Just as n simple example I want to create a function which returns the version
of our dll.
We add some lines to out unit (I've called "my_plugin.pas") with the
necessary code-lines for our dll (these lines are highlighted):
unit my_plugin; interface uses SysUtils, Classes, A5DLL2; { Prototype }
function GetVersion :gsfixed; cdecl; exports GetVersion; implementation { GetVersion - returns a (version-)number }
function GetVersion() : gsfixed;
begin
result:=INT2FIX(5);
end;
end.
That's it!
Compile/build the project and copy the dll into your 3DGS-direcory.
If you reached this point - I'm shure - you are able to understand this WDL-script
(world-definition-language).
Here is also a very simple script how to use plugin-functions::
(The most interested parts are highlighted)
//-------------------------------------------------------------------------------
// Workshop: Plugins with borland delphi
// author: u.seiffert
// date: 10.05
//-------------------------------------------------------------------------------
var dll_handle; // handle for dll's
var dll_version = 0;
//-------------------------------------------------------------------------------
var video_mode = 6;
var video_screen = 2;
var video_depth = 16;
//-------------------------------------------------------------------------------
font arial_font = "Arial",1,20; // truetype font
text ver_text {
pos_X = 100;
pos_Y = 200;
font = arial_font;
strings = 1;
string = "DLL-Version:";
flags = VISIBLE;
}
//-------------------------------------------------------------------------------
panel ver_info {
pos_X = 240;
pos_y = 200;
digits = 0,0,4,arial_font,1,dll_version;
flags = REFRESH,VISIBLE;
}
//-------------------------------------------------------------------------------
// pre-declaration
dllfunction GetVersion();
//-------------------------------------------------------------------------------
// main-function
function main {
// load dummy-level
level_load("demo.wmb");
wait(3);
// call DLL-function
dll_handle=dll_open("dll_3dgs.dll");
dll_version = GetVersion();
dll_close(dll_handle);
// wait for an end...
while(1){
wait(1);
}
}
There are just a few things that can happen while the installation and creation
of plugin.
Here is a list of errors/problems:
Typ |
3DGS-Typ |
Delphi-example |
GSFixed |
Numbers |
A longint or a double -> see helperfunction: function GetVersion() : gsfixed; |
PA4_STRING |
string |
Struktur mit chars und Länge: str_pascal:=StrPas(str_3dgs^.chars); |
PA4_ENTITY |
entity |
Struktur see A5DLL2.PAS |
PA4_TEX |
textur |
Struktur see A5DLL2.PAS |
PA4_BMAP |
bitmap (bmp, pcx, tga) |
Struktur see A5DLL2.PAS |
PA4_PARTICLE |
particle |
Struktur see A5DLL2.PAS |
PA4_FONT |
font |
Struktur see A5DLL2.PAS |
PA4_TEXT |
text |
Struktur see A5DLL2.PAS |
PA4_PANEL |
panel |
Struktur see A5DLL2.PAS |
PA4_VIEW |
view |
Struktur see A5DLL2.PAS |
To work with the type gsfixed Conitec has spent a hand full funktions,
to convert the pascal-type Longint and double to the Acknex-format:
function INT2FIX(i : LongInt) : GSFixed; |
Converts a Pascal-Longint into Acknex-Fixtype ack_fix = INT2FIX(pas_long); |
function FIX2INT(x : GSFixed) : LongInt; |
Converts a Acknex-Fixtype into pascal-Longint pas_int := FIX2INT(ack_fix); |
function FIX2FLOAT(x : GSFixed) : Double; |
Converts a Acknex-Kommazahl to a Pascal-Double-value pas_double := FIX2FLOAT(ack_fix);pas_double := FIX2FLOAT(ack_fix); |
function FLOAT2FIX(f : double) : GSFixed; |
Converts a Pascal-Double-Wert into an Acknex-float ack_fix = FLOAT2FIX(pas_double); |
version: 10.2005
Author: Ulrich Seiffert (3dgs@ulrich-seiffert.de)