Custom Component Tutorial
Custom components allow the user to add additional geometry types to OpenVSP. The custom type parameters, shape and GUI are all defined by a script written in AngelScript.
AngelScript is an embedded open source scripting language with a C/C++ syntax. Numerous OpenVSP functions and data types can be called from the script. For a complete list of exposed functions see http://www.openvsp.org/wiki/doku.php?id=api.
The script should be named with a .vsppart suffix and placed in the CustomScripts directory which should be located in the same directory as the vsp executable.
There are four functions required to define a custom component:
void Init() - This function is called once when the component is created. Use this function to create parameters and set up surfaces that will have a fixed number of cross-sections. You can also add default sources for CFD Meshing.
void InitGUI() - This function is called once at creation. Create the GUI needed to control the parameters of your component. Also associate the GUI with the parameters.
void UpdateGui() - Called every time the GUI is updated. This function can be used to disable/enable GUI or change associations with the parameters.
void UpdateSurf() - Called every time the geometry component is updated. Build, update and/or transform the surface geometry based on the current value of the parameters. You can also modify the surface skinning parameters.
The are two optional functions:
void Scale( float scale ) - Add code here to scale the geometry. If this function is not provided, the scale parameter will not do anything.
void ComputeCenter() - Add code to compute the center of rotation. If this function does not exist, a default function will attempt to computer the center based on cross-sections and the Origin parameter.
Lets say you need a cone shape with two parameters, height and diameter, controlling the shape. First create a file called “Cone.vsppart” in the CustomScript directory. To create the parameters, add the following code to Init():
//==== Add Parm Types =====// string height = AddParm( PARM_DOUBLE_TYPE, "Height", "Design" ); SetParmValLimits( height, 4.0, 0.001, 1.0e12 ); SetParmDescript( height, "Height of Cone" );
string diameter = AddParm( PARM_DOUBLE_TYPE, "Diameter", "Design" ); SetParmValLimits( diameter, 8.0, 0.001, 1.0e12 ); SetParmDescript( diameter, "Diameter of Cone" );
The first line creates a parm of type double, named “Height” and in the group “Design”. The returned string is a unique id that references the new parm. The next line uses the height parm id to set an initial value of 4.0 and a range between 0.001 and 1.0e12. The parm description is set in the following line. Descriptions might be important to give other users an idea of how to use your new geometry component.
Next create the cross section surface and define the cross sections. This could be done in UpdateSurf() but if the number of cross-sections do not change, it is more efficient to do it here.
//==== Add Cross Sections =====// string xsec_surf = AddXSecSurf(); AppendXSec( xsec_surf, XS_POINT); AppendXSec( xsec_surf, XS_CIRCLE); AppendXSec( xsec_surf, XS_POINT);
The first line creates and add a cross-section surface to the component. The surface id is returned as a string. AppendXSec adds cross-sections to the surface. The cross-section shape and placement will be handled later in UpdateSurf().
To define and build the user interface, add code to the InitGui function.
AddGui( GDEV_TAB, "Design" ); AddGui( GDEV_YGAP ); AddGui( GDEV_DIVIDER_BOX, "Design" ); AddGui( GDEV_SLIDER_ADJ_RANGE_INPUT, "Height", "Height", "Design" ); AddGui( GDEV_SLIDER_ADJ_RANGE_INPUT, "Diameter", "Diameter", "Design" ); AddGui( GDEV_YGAP, "" );
Each AddGui call adds a GUI element to the last defined tab. By default each element takes a full line. You can change this behavior with GDEV_BEGIN_SAME_LINE and GDEV_END_SAME_LINE. Notice the last two arguments in the function calls that add the sliders. These associate the slider with a parameter by passing the name and group of the parm.
In this example, no code is required in UpdateGUI() because the GUI does not dynamically change.
The final required function (UpdateSurf) uses the parm values to change the shape of the surface.
string geom_id = GetCurrCustomGeom();
//==== Set Base XSec Diameter ====// string dia_parm = GetParm( geom_id, "Diameter", "Design" ); double dia_val = GetParmVal( dia_parm );
This code first gets the id of the current custom component. Then queries the geometry for the diameter parm id and finally retrieves the current value of the diameter.
//==== Get The XSecs To Change ====// string xsec_surf = GetXSecSurf( geom_id, 0 ); string xsec1 = GetXSec( xsec_surf, 1 ); string xsec2 = GetXSec( xsec_surf, 2 );
These three lines find the ids for the surface and the last two cross-sections.
//==== Set The Diameter ====// string xsec1_dia = GetXSecParm( xsec1, "Circle_Diameter" ); SetParmVal( xsec1_dia, dia_val );
//==== Set The Height ====// double ht_val = GetParmVal( GetParm( geom_id, "Height", "Design" ) ); SetCustomXSecLoc( xsec2, vec3d( ht_val, 0, 0 ) );
The preceding code finds the id of the parameters controlling the diameter of the circle cross-section and the desired height of the code. Then it sets the parm vals and xsec location. To find the parameter name and group, click on the parm name button in the GUI.
The last line of code, SkinXSecSurf, skins a Bezier surface over the cross sections. The default continuity is C0. Use SetXSecContinuity, SetXSecTanAngles, SetXSecTanStrengths and SetXSecCurvatures to specify surface shape.