The Global ARCHICAD Community

Stay informed. Get help. Share your knowledge.

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

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

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 all
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?
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 all
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)
Code: Select all
err=ACAPI_Element_GetDefaults(&element,&memo);
4. Verify the memo additional parameters and those looks just fine. DumpParameters implementation from the Docs. (Working)
Code: Select all
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.
Code: Select all
err=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 all
paramOwner.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 all
err = ACAPI_Goodies (APIAny_OpenParametersID, &paramOwner, nullptr);
3. Created an array of structure to hold the required parameters, and fill that
Code: Select all
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).
Code: Select all
err = 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 all
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... :(
Code: Select all
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 :)
#282518
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/docum ... nt_getmemo

Now it is working like charm.