We value your input! Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey
2021-11-06 12:23 PM - edited 2021-11-06 12:23 PM
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
Solved! Go to Solution.
2021-11-07 08:57 AM - edited 2021-11-07 09:05 AM
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 (¶ms);
}
}
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 (¶ms);
}
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);
2021-11-07 08:57 AM - edited 2021-11-07 09:05 AM
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 (¶ms);
}
}
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 (¶ms);
}
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);
2021-11-09 10:13 AM
Works great, thanks!
Structural engineer, developer of free addon for sync GDL param and properties