Archicad C++ API
About Archicad add-on development using the C++ API.
SOLVED!

How to read parameters of placed GDL panel in Curtian Wall?

kuvbur
Enthusiast

How to read the parameter value of curtain wall panels? Curtain wall panels are made by GDL objects. The usual way (ACAPI_Element_GetMemo(guid, &memo, APIMemoMask_AddPars) of reading parameters for objects does not work, because the panels do not have memo. Is there an alternative way to read panel parameters?

 

GSErrCode GetCWPanelsForCWall(const API_Guid& elemGuid, GS::Array<API_Guid>& panelGuid) {
	GSErrCode			err = NoError;
	API_Elem_Head elementhead = {};
	elementhead.guid = elemGuid;
	err = ACAPI_Element_GetHeader(&elementhead);
	if (err != NoError) return err;
	if (!elementhead.hasMemo) return err;
	API_ElementMemo	memo;
	BNZeroMemory(&memo, sizeof(API_ElementMemo));
	bool isDegenerate;
	err = ACAPI_Element_GetMemo(elemGuid, &memo, APIMemoMask_CWallPanels);
	if (err != NoError) {
		ACAPI_DisposeElemMemoHdls(&memo);
		return err;
	}
	GSSize nPanels = BMGetPtrSize(reinterpret_cast<GSPtr>(memo.cWallPanels)) / sizeof(API_CWPanelType);
	for (Int32 idx = 0; idx < nPanels; ++idx) {
		err = ACAPI_Database(APIDb_IsCWPanelDegenerateID, &memo.cWallPanels[idx].head.guid, &isDegenerate);
		if (!isDegenerate && memo.cWallPanels[idx].hasSymbol) {
			panelGuid.Push(memo.cWallPanels[idx].symbolID);
			API_Elem_Head panelhead = {};
			panelhead.guid = memo.cWallPanels[idx].symbolID;
			err = ACAPI_Element_GetHeader(&panelhead);
			if (!panelhead.hasMemo) {
				ErrorBeep("ACAPI_Element_GetMemo", err);
			}
		}
	}
	ACAPI_DisposeElemMemoHdls(&memo);
	return err;
}

 

 

 

 

Structural engineer, developer of free addon for sync GDL param and properties

1 ACCEPTED SOLUTION

Accepted Solutions
Solution
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni

If you have the GUID of the placed library part instance (= GDL based element = symbol), then you can get its parameters by using the APIAny_OpenParametersID, APIAny_GetActParametersID and APIAny_CloseParametersID methods. See the GetGDLParametersOfSymbol function below.

This works for CWPanels also.

 

 

API_Guid GetSymbolGuidOfCWPanel (const API_CWPanelType& cwPanel)
{
	bool isDegenerate = false;
	ACAPI_Database (APIDb_IsCWPanelDegenerateID, (void*)(&cwPanel.head.guid), &isDegenerate);
	if (isDegenerate || !cwPanel.hasSymbol) {
		return APINULLGuid;
	}

	return cwPanel.symbolID;
}

GSErrCode GetSymbolGuidOfCWPanel (const API_Guid& cwPanelGuid, API_Guid& symbolGuid)
{
	API_Element	elem = {};
	elem.header.guid = cwPanelGuid;

	const GSErrCode err = ACAPI_Element_Get (&elem);
	if (err != NoError) {
		return err;
	}

	symbolGuid = GetSymbolGuidOfCWPanel (elem.cwPanel);
	if (symbolGuid == APINULLGuid) {
		return APIERR_BADPARS;
	}

	return NoError;
}

GSErrCode GetCWPanelSymbolGuidsOfCW (const API_Guid& cwGuid, GS::Array<API_Guid>& panelSymbolGuids)
{
	GSErrCode	err = NoError;

	API_ElementMemo	memo = {};
	err = ACAPI_Element_GetMemo (cwGuid, &memo, APIMemoMask_CWallPanels);
	if (err != NoError) {
		ACAPI_DisposeElemMemoHdls (&memo);
		return err;
	}

	const GSSize nPanels = BMGetPtrSize (reinterpret_cast<GSPtr>(memo.cWallPanels)) / sizeof (API_CWPanelType);
	for (Int32 idx = 0; idx < nPanels; ++idx) {
		const API_Guid symbolGuid = GetSymbolGuidOfCWPanel (memo.cWallPanels[idx]);
		if (symbolGuid != APINULLGuid) {
			panelSymbolGuids.Push (std::move (symbolGuid));
		}
	}

	ACAPI_DisposeElemMemoHdls (&memo);
	return err;
}

GSErrCode GetGDLParametersOfSymbol (const API_Guid& symbolGuid, API_AddParType**& params)
{
	GSErrCode	err = NoError;

	API_ParamOwnerType	apiOwner = {};
	API_GetParamsType	apiParams = {};

	apiOwner.guid = symbolGuid;
	apiOwner.typeID = API_ObjectID;

	err = ACAPI_Goodies (APIAny_OpenParametersID, &apiOwner);
	if (err != NoError) {
		return err;
	}

	err = ACAPI_Goodies (APIAny_GetActParametersID, &apiParams);
	if (err != NoError) {
		return err;
	}

	params = apiParams.params;

	err = ACAPI_Goodies (APIAny_CloseParametersID);

	return err;
}

GSErrCode HandleGDLParameters (API_AddParType** params)
{
	Int32	addParNum = BMGetHandleSize ((GSHandle)params) / sizeof (API_AddParType);
	for (Int32 ii = 0; ii < addParNum; ++ii) {
		API_AddParType& actualParam = (*params)[ii];
		// Do whatever you want with it
		UNUSED_VARIABLE (actualParam);
	}

	return NoError;
}

// -----------------------------------------------------------------------------

void	Do_CWPanelGDLParameters (void)
{
	API_ElemTypeID	typeID;
	API_Guid		clickedElemGuid;
	if (!ClickAnElem ("Click a curtain wall or a cwpanel.", API_ZombieElemID, nullptr, &typeID, &clickedElemGuid)) {
		WriteReport_Alert ("No element was clicked.");
		return;
	}

	GSErrCode err = NoError;
	if (typeID == API_CurtainWallID) {
		GS::Array<API_Guid> cwPanelSymbolGuids;
		err = GetCWPanelSymbolGuidsOfCW (clickedElemGuid, cwPanelSymbolGuids);
		for (const API_Guid& symbolGuid : cwPanelSymbolGuids) {
			API_AddParType** params = {};
			err = GetGDLParametersOfSymbol (symbolGuid, params);
			if (params == nullptr || err != NoError) {
				continue;
			}

			HandleGDLParameters (params);

			ACAPI_DisposeAddParHdl (&params);
		}
	}
	else if (typeID == API_CurtainWallPanelID) {
		API_Guid symbolGuid;

		err = GetSymbolGuidOfCWPanel (clickedElemGuid, symbolGuid);

		API_AddParType** params = {};
		err = GetGDLParametersOfSymbol (symbolGuid, params);
		if (params == nullptr || err != NoError) {
			return;
		}

		HandleGDLParameters (params);

		ACAPI_DisposeAddParHdl (&params);
	}
	else {
		WriteReport_Alert ("The clicked element is not a curtain wall or a cwpanel.");
		return;
	}
}

// -----------------------------------------------------------------------------

 

 

Don't forget that the API_AddParType list returned by the APIAny_GetActParametersID method is just a copy! So if you modify it, then the parameters of the placed element won't be changed automatically. You have to call the ACAPI_Element_ChangeMemo explicitly to modify the parameters of the element:

API_ElementMemo	elemMemo = {};
elemMemo.params = params;

ACAPI_Element_ChangeMemo (symbolGuid, APIMemoMask_AddPars, &elemMemo);

 

 

View solution in original post

2 REPLIES 2
Solution
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni

If you have the GUID of the placed library part instance (= GDL based element = symbol), then you can get its parameters by using the APIAny_OpenParametersID, APIAny_GetActParametersID and APIAny_CloseParametersID methods. See the GetGDLParametersOfSymbol function below.

This works for CWPanels also.

 

 

API_Guid GetSymbolGuidOfCWPanel (const API_CWPanelType& cwPanel)
{
	bool isDegenerate = false;
	ACAPI_Database (APIDb_IsCWPanelDegenerateID, (void*)(&cwPanel.head.guid), &isDegenerate);
	if (isDegenerate || !cwPanel.hasSymbol) {
		return APINULLGuid;
	}

	return cwPanel.symbolID;
}

GSErrCode GetSymbolGuidOfCWPanel (const API_Guid& cwPanelGuid, API_Guid& symbolGuid)
{
	API_Element	elem = {};
	elem.header.guid = cwPanelGuid;

	const GSErrCode err = ACAPI_Element_Get (&elem);
	if (err != NoError) {
		return err;
	}

	symbolGuid = GetSymbolGuidOfCWPanel (elem.cwPanel);
	if (symbolGuid == APINULLGuid) {
		return APIERR_BADPARS;
	}

	return NoError;
}

GSErrCode GetCWPanelSymbolGuidsOfCW (const API_Guid& cwGuid, GS::Array<API_Guid>& panelSymbolGuids)
{
	GSErrCode	err = NoError;

	API_ElementMemo	memo = {};
	err = ACAPI_Element_GetMemo (cwGuid, &memo, APIMemoMask_CWallPanels);
	if (err != NoError) {
		ACAPI_DisposeElemMemoHdls (&memo);
		return err;
	}

	const GSSize nPanels = BMGetPtrSize (reinterpret_cast<GSPtr>(memo.cWallPanels)) / sizeof (API_CWPanelType);
	for (Int32 idx = 0; idx < nPanels; ++idx) {
		const API_Guid symbolGuid = GetSymbolGuidOfCWPanel (memo.cWallPanels[idx]);
		if (symbolGuid != APINULLGuid) {
			panelSymbolGuids.Push (std::move (symbolGuid));
		}
	}

	ACAPI_DisposeElemMemoHdls (&memo);
	return err;
}

GSErrCode GetGDLParametersOfSymbol (const API_Guid& symbolGuid, API_AddParType**& params)
{
	GSErrCode	err = NoError;

	API_ParamOwnerType	apiOwner = {};
	API_GetParamsType	apiParams = {};

	apiOwner.guid = symbolGuid;
	apiOwner.typeID = API_ObjectID;

	err = ACAPI_Goodies (APIAny_OpenParametersID, &apiOwner);
	if (err != NoError) {
		return err;
	}

	err = ACAPI_Goodies (APIAny_GetActParametersID, &apiParams);
	if (err != NoError) {
		return err;
	}

	params = apiParams.params;

	err = ACAPI_Goodies (APIAny_CloseParametersID);

	return err;
}

GSErrCode HandleGDLParameters (API_AddParType** params)
{
	Int32	addParNum = BMGetHandleSize ((GSHandle)params) / sizeof (API_AddParType);
	for (Int32 ii = 0; ii < addParNum; ++ii) {
		API_AddParType& actualParam = (*params)[ii];
		// Do whatever you want with it
		UNUSED_VARIABLE (actualParam);
	}

	return NoError;
}

// -----------------------------------------------------------------------------

void	Do_CWPanelGDLParameters (void)
{
	API_ElemTypeID	typeID;
	API_Guid		clickedElemGuid;
	if (!ClickAnElem ("Click a curtain wall or a cwpanel.", API_ZombieElemID, nullptr, &typeID, &clickedElemGuid)) {
		WriteReport_Alert ("No element was clicked.");
		return;
	}

	GSErrCode err = NoError;
	if (typeID == API_CurtainWallID) {
		GS::Array<API_Guid> cwPanelSymbolGuids;
		err = GetCWPanelSymbolGuidsOfCW (clickedElemGuid, cwPanelSymbolGuids);
		for (const API_Guid& symbolGuid : cwPanelSymbolGuids) {
			API_AddParType** params = {};
			err = GetGDLParametersOfSymbol (symbolGuid, params);
			if (params == nullptr || err != NoError) {
				continue;
			}

			HandleGDLParameters (params);

			ACAPI_DisposeAddParHdl (&params);
		}
	}
	else if (typeID == API_CurtainWallPanelID) {
		API_Guid symbolGuid;

		err = GetSymbolGuidOfCWPanel (clickedElemGuid, symbolGuid);

		API_AddParType** params = {};
		err = GetGDLParametersOfSymbol (symbolGuid, params);
		if (params == nullptr || err != NoError) {
			return;
		}

		HandleGDLParameters (params);

		ACAPI_DisposeAddParHdl (&params);
	}
	else {
		WriteReport_Alert ("The clicked element is not a curtain wall or a cwpanel.");
		return;
	}
}

// -----------------------------------------------------------------------------

 

 

Don't forget that the API_AddParType list returned by the APIAny_GetActParametersID method is just a copy! So if you modify it, then the parameters of the placed element won't be changed automatically. You have to call the ACAPI_Element_ChangeMemo explicitly to modify the parameters of the element:

API_ElementMemo	elemMemo = {};
elemMemo.params = params;

ACAPI_Element_ChangeMemo (symbolGuid, APIMemoMask_AddPars, &elemMemo);

 

 

kuvbur
Enthusiast

Works great, thanks!

Structural engineer, developer of free addon for sync GDL param and properties