We value your input!
Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey

GDL
About building parametric objects with GDL.

Insert Library element (MEP) to the model

Anonymous
Not applicable
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.
			//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
APIERR_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?
			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.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.
5 REPLIES 5
Ralph Wessel
Mentor
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.
Ralph Wessel BArch
Software Engineer Speckle Systems
Anonymous
Not applicable
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)
element.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)
err=ACAPI_Element_GetDefaults(&element,&memo);
4. Verify the memo additional parameters and those looks just fine. DumpParameters implementation from the Docs. (Working)
DumpParameters(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.
err=ACAPI_Element_Create(&element,&memo);
APIERR_REFUSEDCMD	-2130312312	81060388	The passed identifier is not subject to the operation.
Here is my whole code:
			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).typeMod == API_ParSimple) {
						DumpOneParam ((*memo.params).typeID, (*memo.params).name, (*memo.params).flags,
				(*memo.params).value.real, (*memo.params).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);
Ralph Wessel
Mentor
Have you started an undo session for this operation? If not, take a look at ACAPI_CallUndoableCommand
Ralph Wessel BArch
Software Engineer Speckle Systems
Anonymous
Not applicable
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).
paramOwner.libInd = element.object.libInd;
paramOwner.typeID = element.header.typeID;
paramOwner.variationID=element.header.variationID;
paramOwner.guid   = element.header.guid;
2. open parameters (NoError)
err = ACAPI_Goodies (APIAny_OpenParametersID, &paramOwner, nullptr);
3. Created an array of structure to hold the required parameters, and fill that
typedef 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).
err = ACAPI_Goodies (APIAny_GetActParametersID, &getParams, nullptr);
chgParam.index = param.ID;
CHCopyC (param.name, chgParam.name);
chgParam.realValue = param.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
err=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...
err = 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
Anonymous
Not applicable
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...http://archicadapi.graphisoft.com/documentation/acapi_element_getmemo

Now it is working like charm.