Learn to manage BIM workflows and create professional Archicad templates with the BIM Manager Program.

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

Replacing Surface Materials based on MaterialName.

KirthikaSrinivasan-L
Participant

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;
}

 

 

 

2 REPLIES 2
Lingwisyer
Guru

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 3110Help Those Help You - Add a Signature
Self-taught, bend it till it breaksCreating a Thread
Win11 | i9 10850K | 64GB | RX6600 Win11 | R5 2600 | 16GB | GTX1660
Lingwisyer
Guru

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;

  1. parse material library for "const char", write result to A1 to An
  2. find index of A1 to An
  3. store string Prior to "const char" for A1 to An
  4. store string After "const char" for A1 to An
  5. delete A1 to An from material library
  6. duplicate B1 => B2 to Bn
  7. replace the index of B2 to Bn with the stored values from A1 to An?
  8. ammend name B2 to Bn with Prior "const char" After

Or is that just really memory inefficient?

Or maybe that is what you have done, I am no C++ coder...

AC22-28 AUS 3110Help Those Help You - Add a Signature
Self-taught, bend it till it breaksCreating a Thread
Win11 | i9 10850K | 64GB | RX6600 Win11 | R5 2600 | 16GB | GTX1660

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!