The Global ARCHICAD Community

Stay informed. Get help. Share your knowledge.

Discussions about using GRAPHISOFT's tools (API DevKit) for independent software developers

Moderators: ejrolon, Barry Kelly, Karl Ottenstein, LaszloNagy, gkmethy, Mihály Palenik, Tibor Lorántfy, MOREH Tamas, Akos Somorjai, Ed Brown

By HeadLess
#281743
Hi there!

I'm very new to Archicad development (and c++ too), please be patient with me.

So my main goal is to load a a csv/txt file and based on that i want to place MEP models like pipes, ducts, other gdl object from library.

I tried to simply insert an element, but i'm not sure what should i define.

Code: Select all         //initalize element/memo
         API_Element* element;
         API_ObjectType obj;
         API_ElementMemo* elementMemo;
         //API_AddParType** parType;
         elementMemo=new API_ElementMemo;
         element=new API_Element;
         //element pointer
         element->header.typeID=API_ObjectID;
         element->header.floorInd=0;
         element->header.hasMemo=false;
         //initialize obj
         obj=element->object;
         //set obj paramter
         obj.angle=0;
         obj.pos.x=0;
         obj.pos.y=0;
         obj.level=1;
         obj.libInd=1;
         obj.ltypeInd=1;
         obj.pen=1;
         
         
         //write back new object params
         element->object=obj;
         
         //create element
         err=ACAPI_Element_Create(element,elementMemo);
         WriteReport("Element_Create",err);


this gives me
Code: Select allAPIERR_BADINDEX   -2130313114   81060066   The passed index is out of range.
error.
So my guess is that i didn't specify correctly one of the ID, index, or something. So i tried to find the mep library and inside that find the duct element to place that. I could find he libraryInfo, but after that i'm stuck, is there any function to find library parts, and then place that?

Code: Select all         GSErrCode err;

         //get loaded libraries
         GS::Array<API_LibraryInfo> activeLibs;
         Int32 embeddedLibraryIndex;
         err=ACAPI_Environment(APIEnv_GetLibrariesID,&activeLibs,&embeddedLibraryIndex);
         if(err!=NoError){
            WriteReport("GetLibrariesID",err);
         }
         //Loop through libraries and find mep library
         API_LibraryInfo libraryInfo;
         GS::UniString libraryName;
         for (UInt32 i = 0; i < activeLibs.GetSize(); i++) {
            libraryName=activeLibs[i].name;
            if(libraryName.Contains("MEP Modeler.apx")){
               //Found MEP library
               ACAPI_WriteReport(libraryName.ToCStr(),true);
            }
            
         }



There migth be lot of mistakes in the function usage and in c++ syntax also. Please guide me where to start what functions do i need to place a MEP element, I'll try my best to found out how to use them.
#281756
I think you're getting in over your head. The opening sections of the API documentation say right up front:
Who can do API development?
API developers have to be experienced in C or C++ programming language

If you don't have that experience, a lot of time is going to be spent cleaning up basic programming errors. I'd recommend the following actions:

1) Study C++. There are many good resources out there.
2) Read at least the main sections of the API documentation
3) Explore some of the examples that seem relevant to your development.

You'll save yourself a lot of time energy if you get a good grasp of the fundamentals first.
#281781
You are right, i didn't find the examples at first. From there i was able to do more, but now i have somthing else. Here is what i did
1. Loop through library elements to get the correct ElementTypeID,ElementVariationID,ObjectTypeID (working)
2. Initialize the element with the previously found variables (working)
Code: Select allelement.header.typeID=toolboxItemPipe.typeID; //ElementTypeID
element.header.variationID=toolboxItemPipe.variationID; //VariationTypeID
element.object.libInd=libIndPipe; //library index

3. Get the default memo for the initialized element (NoError)
Code: Select allerr=ACAPI_Element_GetDefaults(&element,&memo);

4. Verify the memo additional parameters and those looks just fine. DumpParameters implementation from the Docs. (Working)
Code: Select allDumpParameters(element.object.libInd,libPart_Pipe.typeID)


5. And here is problem i try to create the element with these initialized parameter, but it gives me an error.
Code: Select allerr=ACAPI_Element_Create(&element,&memo);
APIERR_REFUSEDCMD   -2130312312   81060388   The passed identifier is not subject to the operation.


Here is my whole code:
Code: Select all         API_LibPart  libPart;
         API_LibPart  libPart_Pipe={};
         API_LibPart  libPart_PipeBend={};
         API_ToolBoxItem toolboxItemPipe={},toolboxItemPipeBend={};
         Int32        i, count,libIndPipe=0,libIndPipeBend=0;
         GSErrCode    err;
         GS::UniString libPartName;


         //Found out which library elements ID for mep elements...
         err = ACAPI_LibPart_GetNum (&count);
         if (!err) {
            for (i = 1; i <= count; i++) {
               BNZeroMemory (&libPart, sizeof (API_LibPart));
               libPart.index = i;
               err = ACAPI_LibPart_Get (&libPart);
               if (!err) {
                  libPartName="Pipe Straight 20";
                  if(GS::UniString (libPart.docu_UName)==libPartName){
                     libPart_Pipe=libPart;
                     libIndPipe=i;
                     err=ACAPI_Goodies(APIAny_GetLibPartToolVariationID,&libPart,&toolboxItemPipe);
                     if(err){
                        WriteReport("APIAny_GetLibPartToolVariationID",err);
                     }else{
                        WriteReport("toolboxItemPipe.typeID",toolboxItemPipe.typeID);
                        WriteReport("toolboxItemPipe.variationID",toolboxItemPipe.variationID);
                     }
                  }
                  libPartName="Pipe Bend 20";
                  if(GS::UniString (libPart.docu_UName)==libPartName){
                     libPart_PipeBend=libPart;
                     libIndPipeBend=i;
                     err=ACAPI_Goodies(APIAny_GetLibPartToolVariationID,&libPart,&toolboxItemPipeBend);
                     if(err){
                        WriteReport("APIAny_GetLibPartToolVariationID",err);
                     }else{
                        WriteReport("toolboxItemPipeBend.typeID",toolboxItemPipeBend.typeID);
                        WriteReport("toolboxItemPipeBend.variationID",toolboxItemPipeBend.variationID);
                     }
                  }
               }
                  if (libPart.location != nullptr)
                     delete libPart.location;
            }
         }
         
         //Define element
         API_Element element;
         API_ElementMemo memo;

         //TODO for cycle to read data from CSV line by line

         //Clear element, memo
         BNZeroMemory (&element, sizeof (API_Element));
         BNZeroMemory (&memo, sizeof (API_ElementMemo));
         
         //initialize element.header
         element.header.typeID=toolboxItemPipe.typeID; //ElementTypeID
         element.header.variationID=toolboxItemPipe.variationID; //VariationTypeID
         element.header.floorInd=0;
         element.header.hasMemo=true;
         
         //initialize element.object
         element.object.libInd=libIndPipe; //library index
         /*element.object.level=0; //height from the floor
         element.object.pos.x=0;
         element.object.pos.y=0;
         element.object.angle=0; //element angle
         */
         WriteReport("element.object.libInd",element.object.libInd);

         //Get memo Defaults
         err=ACAPI_Element_GetDefaults(&element,&memo);
         if(!err){
            //Element_GetDefaults was successfull
            //Get default parameters
            double a,b;
            Int32 parCount;
            API_AddParType **addPars=nullptr;
            err=ACAPI_LibPart_GetParams(libIndPipe,&a,&b,&parCount,&addPars);
            if(!err){
               WriteReport("Parameters count",parCount);
               //write default parameters to memo
               memo.params=addPars;
               //parCount=1;
               //DumpParameters(element.object.libInd,libPart_Pipe.typeID);
               for(i=0;i<parCount;i++){
                  
                 if ((*memo.params)[i].typeMod == API_ParSimple) {
                  DumpOneParam ((*memo.params)[i].typeID, (*memo.params)[i].name, (*memo.params)[i].flags,
            (*memo.params)[i].value.real, (*memo.params)[i].value.uStr,
                          0,0);
                  }
               }
               //try to create the element
               err=ACAPI_Element_Create(&element,&memo);
               if(!err){
                  //element successfully created
                  ACAPI_WriteReport("Element created",false);
               }else{
                  WriteReport("Element_Create",err);
               }
            }else{
                  WriteReport("ACAPI_LibPart_GetParams",err);
            }
         }else{
            WriteReport("Element_GetDefaults",err);
         }
         ACAPI_DisposeElemMemoHdls (&memo);
#281800
Thank you very much that was what i missed.

I thought it would be easier after that, but now i have problem with modification of the library element, however it is not giving me any error as it is changed but on the model that did not appear.

What i did.
1. initialize paramOwner (i want to modify the instance of the element so i set the GUID as well).
Code: Select allparamOwner.libInd = element.object.libInd;
paramOwner.typeID = element.header.typeID;
paramOwner.variationID=element.header.variationID;
paramOwner.guid   = element.header.guid;

2. open parameters (NoError)
Code: Select allerr = ACAPI_Goodies (APIAny_OpenParametersID, &paramOwner, nullptr);

3. Created an array of structure to hold the required parameters, and fill that
Code: Select alltypedef struct parameter {   char name[32];
                     short ID;
                     double value;
} parameter;
parameter param[1]={};
strcpy(param[0].name,"MEP_StraightLength"); //that is the parameter name.
param[0].value=2;
param[0].ID=10;
...


4. Get active parameters (NoError) and change them (NoError).
Code: Select allerr = ACAPI_Goodies (APIAny_GetActParametersID, &getParams, nullptr);
chgParam.index = param[j].ID;
CHCopyC (param[j].name, chgParam.name);
chgParam.realValue = param[j].value;
                           
err = ACAPI_Goodies (APIAny_ChangeAParameterID, &chgParam, nullptr);


5. close opened parameters with success. And set memo.params to the new params. clear mask. Looks fine
Code: Select allerr=ACAPI_Goodies (APIAny_CloseParametersID, nullptr, nullptr);
memo.params = getParams.params;
ACAPI_ELEMENT_MASK_CLEAR(mask);


6. Call the change with undoable command... It appears on the previous menu but nothing changed on the element... :(

Code: Select allerr = ACAPI_CallUndoableCommand ("Change Element",
                        [&] () -> GSErrCode {
                           return ACAPI_Element_Change(&element, &mask, &memo,0,true);
                        });


So I don't know whats wrong. Maybe you know something about this element. I tried to change a length(MEP_StraightLength) i can modify from the GUI, but not from the addon, but there is no error under runtime...

Thanks for your help :)