<<

The MegaEdit code base

The current version of MegaEdit consists of more than 17000 lines of code. Because all code that is common to the various process types and all the necessary support functions are encapsulated in general modules, it is quite easy to add support for new process types.

How to add new process types to MegaEdit


This section shows how to add new process types to MegaEdit. Due to the object oriented structure of the code, it is not very difficult to add a new process. The description uses the (already available) process "Split Curve at Arc Length" as an example, to show the necessary steps.

  1. Create a proper definition of the new process and its associated parameters:
  2. Each editable parameter has to be represented by a string. Fixed parameters like the grid count in the grid concatenating process should be kept in integer form. They will never be represented by variables. It is recommended to look for an existing process using similar arguments and to copy the two corresponding files (one *.c and one *.h file).

  3. Add an integer identifyer for the new process near the end of the enumeration in "medit.h":
  4. The "Split Curve at Arc Length" process can be found as shown below:
    enum { READ_DATA,
           .
           .
           SPLIT_CURVE_CURVE,
           .
           .
            
    The order of the processes in the enumeration should be identical to the numbering scheme in the MegaCads main application (file general_definitions.h) to make sure that the integer process type identifiers are identical..

  5. Add a new union block to the PROCESS structure typedef in "metypes.h":
  6. The entry for the "Split Curve at Arc Length" process looks like:
    struct
      {
       PSTR pCurve;           /* element to split */
       PSTR pSplitLength;     /* length from element */
      } SplitCurveCurve;
            
    (PSTR is a typedef for "char*")

  7. Add the description of the new process to the pFunctions table in "medit.h":
  8. The entry for the "Split Curve at Arc Length" process looks like:
    { "split_curve_curve", "Split Curve at Curve", InitSplitCurveCurve }
            
    The first string of the entry specifies the process name as it appears in the script file. The second string represents the same information in a more readable form as it is visible to the user of MegaEdit. The third argument points to the Initialize function for this process type, which resides in the new code module (see next step).
    The new description block must be placed in the same position as in the enumeration in "medit.h"!

  9. Create a new code module containing the callback functions:
  10. All callback functions and the parameter definition structure should be declared static except the InitializeProcess function. This allows you to use the same basic function and structure names in different code modules and to create new processes by copying existing code modules and making minor changes. Only the InitializeProcess function will be visible from outside of the module. The code module contains a static array of structures which describes the parameters of the process:
    static DIALOGENTRY ParamDef[] =
      {
      {"Split Element (at +/-)",      TYPE_INDEX, ARGUMENT(Data.SplitCurvePoint.pCurve), 0},
      {"Point from Element (at +/-)", TYPE_INDEX, ARGUMENT(Data.SplitCurvePoint.pPoint), 0},
      {NULL, 0, 0, 0}
      };
            
    Each array element contains a description of the parameter, including hints for the valid range and the use of a sign. Use the following typical hints: (at +/-) to indicate first or last point, (a...b) to indicate a range of valid parameter values from 'a' to 'b', (0/1/2) to indicate a switch which can be 0,1, or 2.
    The next structure element can be one of the following:
    TYPE_INDEX ... an incrementable entity index,
    TYPE_ARRAY ... an allocatable array of incrementable entity indices,
    TYPE_VALUE ... a simple numeric value, no index, no string,
    TYPE_STRING... a string.
    The next argument specifies the offset of the structure member which holds the actual parameter. Use the ARGUMENT() macro to let the compiler calculate this offset for you.
    The last field of the structure is used for TYPE_ARRAY parameters only. Allocatable arrays are represented in the process data structure by two variables: an element count and a pointer to 'element count' PSTR pointers, pointing to the individual elements. The last field in a DIALOGENTRY entry specifies the offset of the structure member which holds the element count (the number of array elements) for the allocated array. You should set this parameter to zero if you did not specify a TYPE_ARRAY parameter.
    All entries in the last element of the DIALOGENTRY array must be set to ZERO to indicate the end of the array!

    InitializeProcess()

    The InitializeProcess function will be called under two contexts:
    1. when a new script line is interpreted, the parameter szLine is pointing to the script line, and
    2. when a new process is inserted; in this case szLine is NULL.
    First, the function should set the structure member pInfoText before forking into two branches. The branch for the first call context will collect the parameters from the script line. This is typically done using the functions GetNextParameter() and GetAllParameters() which scan the input line, allocate a buffer and return a pointer to the buffer. If you want to do your own parsing, beware of the fact, that the Get...Parameter...() functions use the strtok() library routine to parse the input line. See the Concat1stLayers module for an example how to parse the input line using strtok(). The second branch usually just calls ParameterDialog() function, supplying a pointer to the DIALOGENTRY structure. After one of the branches has been executed, the remaining members of the process structure can be set. It is important to call ParameterDialog() before setting the process structure members !

    FreeProcess()

    The FreeProcess function has to free all the memory blocks that have been allocated for the parameters of the process.

    WriteSaveProcFile()

    The WriteSaveProcFile function writes the process parameters to the script file. The calling routine has already written the header of the script line and will add the trailer of the line.

    CreateListEntry()

    The CreateListEntry function fills a buffer with a short representation of the script line, that will be displayed in the process script list window.

    ShowParents()

    The ShowParents function is responsible for the display of all process parents of the supplied process. It returns the new y-coordinate of the process tree, that has been returned from calls to ShowProcessParents() or to supplied y-coordinate (nY) if no call to ShowProcessParents() has been made.

    IncrementProcess()

    The IncrementProcess function typically calls the Increment() function to increment or decrement the arguments of the supplied process. It is called when processes are inserted or deleted in front of the process.

  11. Create a new header file containing the prototype for the InitializeProcess callback function only:
  12. The InitializeProcess function is the one and only function that is implicitely exported from the code module. It gets called, when a new process is added to the process list or when an existing process is edited.

  13. Include the new header file into "medit.h":
  14. Add one #include "...' line behind the last include statement at the top of the file. The corresponding line for the "Split Curve at Arc Length" process looks like:
    #include "splitcvcv.h"
            
    (The InitializeProcess function resides in the file "splitcvcv.h")

  15. Update the Makefile:
  16. Add one entry to the OBJECTS list in the Makefile, corresponding to your new code module.

  17. Make the new version of MegaEdit:
  18. Type make MACHINE where MACHINE is the name of the system you want to compile MegaEdit for.

<<