4 weeks ago - last edited 3 weeks ago
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 A applied to a window/door/wall/slab, and I want to download and import a material say B into the Project and replace all the instances of A in the project, with B, I'm unsure how to replace the instances.
I tried getting the Attribute Indices of A and B and replacing B's
Attr.header.typeID, Attr.header.index, Attr.material and Attr.material.texture.fileLoc values with A's corresponding values and deleting the A 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.
Edit: Let me rename the elements as plain A and B, as I think A1 and B1 is creating some confusions.
Thank you in Advance.
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;
}
4 weeks 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 |
4 weeks ago - last edited 4 weeks 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 |
3 weeks ago
Hi, Your code shows me that you deleted the oldAttr, then you try to use the oldAttr index to modify...
newAttr.header.index = oldAttr.header.index;
ACAPI_Attribute_Modify(&newAttr,...
If you'd modify a material attribute, the material should not be removed.
HTH.
2 weeks ago
Thank you for your reply!
That doesn't fix the problem. The replacement of the Surface Material still doesn't seem to work.
For example, I want the Surface Material used in the API_WindowID and API_DoorID to be overwritten with a new Surface Material, based on the Material Name.
Please let me know how to do this.