cancel
Showing results for 
Search instead for 
Did you mean: 
EN
cancel
Showing results for 
Search instead for 
Did you mean: 
KirthikaSrinivasan-L
Contributor

Replacing one BIM Object with Another Object in the Archicad Project.

Hi there! I'm trying to replace one BIM Object (which is already available in the Embedded Library) with another BIM Object using the code below. I'm finding the Lib_Part indices of both objects and setting the libInd of the old object to the new object's libInd (element.object.libInd = replacementLibPart.index;).

 

I'm facing APIERR_REFUSEDCMD error or APIERR_BADPARS error, when the code reaches ACAPI_Element_Change(). No Matter what I try, I'm unable to fix this. Can you please help me fix this?

 

Please let me know if my approach has any issues.

 

Thanks in Advance!.

 

 

// Function to find an object by name
API_LibPart FindLibPartByName(const char* partName) {
	API_LibPart libPart;
	BNZeroMemory(&libPart, sizeof(API_LibPart));

	GSErrCode err;
	Int32 numLibParts;
	ACAPI_LibraryPart_GetNum(&numLibParts);

	for (Int32 i = 1; i <= numLibParts; i++) {
		BNZeroMemory(&libPart, sizeof(API_LibPart));
		libPart.index = i;

		err = ACAPI_LibraryPart_Get(&libPart);
		char	docuname[256];
		GS::UniString docName = GS::UniString(libPart.docu_UName);
		const char* cString = docName.ToCStr().Get();

		if (err == NoError && strcmp(cString, partName) == 0) {
			return libPart;
		}
	}

	libPart.index = 0; // Return invalid index if not found
	return libPart;
}

// Function to replace all instances of an old object with a new one
GSErrCode BrowserPalette::ReplaceBIMObjects(const char* oldObjectName, const char* newObjectName) {

	// Get current object's library part
	API_LibPart oldLibPart;
	BNZeroMemory(&oldLibPart, sizeof(API_LibPart));

	//Adding oldobjectname's libpart
	oldLibPart = FindLibPartByName(oldObjectName);
	GS::UniString OldLibpartName(oldLibPart.docu_UName);

	API_LibPart replacementLibPart;
	BNZeroMemory(&replacementLibPart, sizeof(API_LibPart));

	replacementLibPart = FindLibPartByName(newObjectName);
	GS::UniString newLibpartName(replacementLibPart.docu_UName);

	if (ACAPI_LibPart_Get(&oldLibPart) == NoError) {

		ACAPI_WriteReport("Found Object: %s", true, OldLibpartName);

		if (ACAPI_LibPart_Get(&replacementLibPart) == NoError) {

			ACAPI_WriteReport("Replacing %s with %s", true, OldLibpartName.ToCStr().Get(), newLibpartName.ToCStr().Get());

			// Update the object's library part reference
			GS::Array<API_Guid> objectList;
			ACAPI_Element_GetElemList(API_ObjectID, &objectList);

			for (const auto& objGuid : objectList) {
				API_Element element;
				BNZeroMemory(&element, sizeof(API_Element));
				element.header.guid = objGuid;

				if (ACAPI_Element_Get(&element) == NoError) {

					if (element.object.libInd == oldLibPart.index) {
						//ACAPI_WriteReport("Found Element: %s", true, element.object.libInd);

						element.object.libInd = replacementLibPart.index; // Replace with new object index

						GSErrCode err = ACAPI_CallUndoableCommand("Change Object",
							[&]() -> GSErrCode {
							return ACAPI_Element_Change(&element, nullptr, nullptr, 0, false);
						});
						
						//GSErrCode err = ACAPI_Element_Change(&element, nullptr, nullptr, 0, true);

						if (err != NoError) {
								ACAPI_WriteReport("Error updating object: %d", true, err);
						}

					}
				}
			}

		}
		else {
			ACAPI_WriteReport("Replacement object %s not found in Embedded Library.", true, newLibpartName.ToCStr().Get());
		}
	}

	return NoError;
	}

 

1 Solution

Accepted Solutions
Hiromichi Shinkawa
Graphisoft
Graphisoft

Hi, When you'd change an object, the index(libInd) only seems not enough. I think you need to set the mask ACAPI_ELEMENT_MASK_SET() as first, and pass the new object memo like:
ACAPI_Element_Change (&element, &mask, &memo, APIMemoMask_AddPars, true);
Please check the API Examples, you can find similar code which is using the command above.
HTH.

Go to post

1 Reply 1
Hiromichi Shinkawa
Graphisoft
Graphisoft

Hi, When you'd change an object, the index(libInd) only seems not enough. I think you need to set the mask ACAPI_ELEMENT_MASK_SET() as first, and pass the new object memo like:
ACAPI_Element_Change (&element, &mask, &memo, APIMemoMask_AddPars, true);
Please check the API Examples, you can find similar code which is using the command above.
HTH.

Didn't find the answer?

Check other topics in this Forum

Back to Forum

Read the latest accepted solutions!

Accepted Solutions

Start a new conversation!