The Global ARCHICAD Community

Stay informed. Get help. Share your knowledge.

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

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

By HeadLess
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.
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.
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.
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);
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.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 :)
Today I revisited my addon and i found out my mistake which was that my memoMask was invalid, because i didn't find any reference to memoMask so i used the default memoMask (0 which may be means nothing).
But today i find memoMask's valid parameters on ACAPI_Element_GetMemo function page... ... nt_getmemo

Now it is working like charm.