Learn to manage BIM workflows and create professional Archicad templates with the BIM Manager Program.
3 hours ago
- last edited
2 hours ago
by
Noemi Balogh
Hi! I'm looking into ways to replace Surface Material (API_MaterialID), based on the name of the Material (after downloading the Material into the project). If I already know that my project has a material A1 applied to a window/door/wall/slab, and I want to download and import a material say B1 into the Project and replace all the instances of A1 in the project, with B1, I'm unsure how to replace the instances.
I tried getting the Attribute Indices of A1 and B1 and replacing B1's
Attr.header.typeID, Attr.header.index, Attr.material and Attr.material.texture.fileLoc values with A1's corresponding values and deleting the A1 Attribute fully. But this doesn't seem to work.
Please let me know if there is any other way to make this replacement work, on surface material level.
API_AttributeIndex FindSurfaceMaterialIndex(const char* MaterialName)
{
API_AttrTypeID typeID;
GSErrCode err = NoError;
API_AttributeIndex test;
for (typeID = API_FirstAttributeID; typeID <= API_LastAttributeID; ((Int32&)typeID)++) {
GS::Array<API_Attribute> attributes;
err = ACAPI_Attribute_GetAttributesByType(typeID, attributes);
if (err != NoError) {
DBPrintf("Error in ACAPI_Attribute_GetAttributesByType", err);
continue;
}
if (typeID == API_MaterialID)
{
short count = 1;
for (API_Attribute& attrib : attributes) {
char guidStr[64];
APIGuid2GSGuid(attrib.header.guid).ConvertToString(guidStr);
if (strcmp(attrib.header.name, MaterialName) == 0) { // Match found
test = attrib.header.index;
return test;
}
count++; //index loc for reference
}
}
}
return ACAPI_CreateAttributeIndex(0);
}
// Function to replace a surface material
GSErrCode ReplaceSurfaceMaterial(const char* oldMaterialName, const char* newMaterialName) {
API_AttributeIndex oldAttribute = FindSurfaceMaterialIndex(oldMaterialName);
API_AttributeIndex newAttribute = FindSurfaceMaterialIndex(newMaterialName);
API_Attribute oldAttr, newAttr;
BNZeroMemory(&oldAttr, sizeof(API_Attribute));
BNZeroMemory(&newAttr, sizeof(API_Attribute));
oldAttr.header.typeID = API_MaterialID;
oldAttr.header.index = oldAttribute;
newAttr.header.typeID = API_MaterialID;
newAttr.header.index = newAttribute;
if (ACAPI_Attribute_Get(&oldAttr) != NoError) {
return 0;
}
// Copy all properties from the new material to the old material
newAttr.material = oldAttr.material;
newAttr.material.texture.fileLoc = oldAttr.material.texture.fileLoc;
char guidStr[64];
APIGuid2GSGuid(newAttr.header.guid).ConvertToString(guidStr);
DBPrintf("\n");
DBPrintf(" [%3s] {%s} \"%s\"", newAttr.header.index.ToUniString().ToCStr().Get(), guidStr, newAttr.header.name);
GSErrCode err2 = ACAPI_Attribute_Delete(oldAttr.header);
newAttr.header.index = oldAttr.header.index;
GSErrCode err = ACAPI_Attribute_Modify(&newAttr, nullptr);
if (err != NoError) {
return err;
}
if (ACAPI_Attribute_Get(&newAttr) != NoError) {
return 0;
}
return NoError;
}
3 hours ago
The API sub can be found here for future reference.
@Barry Kelly or someone can move this thread for you when they see it.
AC22-28 AUS 3110 | Help Those Help You - Add a Signature |
Self-taught, bend it till it breaks | Creating a Thread |
Win11 | i9 10850K | 64GB | RX6600 | Win11 | R5 2600 | 16GB | GTX1660 |
2 hours ago - last edited 2 hours ago
I am no C++ coder, but are you replacing the information within each material with that of your desired one? Would you not just completely replace the material;
Or is that just really memory inefficient?
Or maybe that is what you have done, I am no C++ coder...
AC22-28 AUS 3110 | Help Those Help You - Add a Signature |
Self-taught, bend it till it breaks | Creating a Thread |
Win11 | i9 10850K | 64GB | RX6600 | Win11 | R5 2600 | 16GB | GTX1660 |