Hello @krfft,
@krfft said in Override material tag in take:
maxon::BaseArray<BaseTag*> FindTagsContaining(BaseObject* topObject, maxon::String contains) { maxon::BaseArray<BaseTag*> foundTags; BaseObject* child = topObject->GetDown(); if (child == nullptr) return maxon::BaseArray<BaseTag*>(); while (child != nullptr) { BaseTag* tag = child->GetTag(Ttexture); if(tag != nullptr) { maxon::String tagName = tag->GetName(); if (tagName.Find(contains, 0)) { (void)foundTags.Append(tag); } } (void)foundTags.AppendAll(FindTagsContaining(child,contains)); child = child->GetNext(); } return foundTags; }
This does look correct. It will however never find the tags on the first object you pass in, since it immediately does go down in the hierarchy. Only for the ongoing recursion the parent call will have handled the parent object. It also not advisable to do stuff like (void)foundTags.Append(tag)
, you should properly handle our error system instead. If you want to step over errors, you can use iferr_ignore
instead of iferr_return
. But generally speaking, this function seems okay.
I found a weird thing that if I print GetTypeName() on the tag returned by GetTag(Ttexture) it returns Material, that was the reason for my thinking that the term Texture tag was removed.
This has unfortunately always been the case that Ttexture
is being named a bit chaotically. I personally also always write Tmaterial
first, before some interpreter/preprocessor reminds that this symbol does not exist.
maxon::BaseArray<BaseTag*>::Iterator editTagIterator; for (editTagIterator = editTags->Begin(); editTagIterator != editTags->End(); editTagIterator++) { DescID idMaterialAssignment = DescID(DescLevel(TEXTURETAG_MATERIAL)); take->FindOrAddOverrideParam(td, *editTagIterator, idMaterialAssignment, GeData(GetMaterial(*materialDescription))); }
This also looks mostly fine. The iteration is a bit awfully explicit, you could also just write for (BaseTag* tag: editTags)
to iterate over all items in the BaseArray<BaseTag*>
editTags
. What is missing here though, is the validation that the nodes td
and editTagIterator
are not null. You also do not show which BaseTake
is referenced by take
. Remember that you cannot add overrides to the main take (the take that is already present in a newly created document).
BaseMaterial* GetMaterial(maxon::AssetDescription assetDescription) { iferr_scope_handler { ApplicationOutput("Stopped LoadMaterial() execution with the error: @", err); return nullptr; }; BaseDocument* doc = GetActiveDocument(); maxon::String matName = assetDescription.GetMetaString(maxon::OBJECT::BASE::NAME, maxon::LanguageRef()) iferr_return; BaseMaterial* material = doc->SearchMaterial(matName); if (material == nullptr) { maxon::Url url = assetDescription.GetUrl() iferr_return; if (url.IsEmpty()) return nullptr; maxon::String* error = {}; maxon::Bool didMerge = MergeDocument(doc, MaxonConvert(url), SCENEFILTER::MATERIALS, nullptr, error); material = doc->SearchMaterial(matName); } return material; }
This also looks mostly okay; I would point out two things though. A. It is not very desirable to return null pointers here since you must then deal later with them. B. That you do the merging of documents in an iterative fashion can throw a serious wrench into what you are doing.
So, since you do store pointers to tags and not BaseLink
for these tags, merging documents could produce problems here since you do not assure that these pointers are still valid when you use them (Cinema does reallocate classic API nodes from time to time when necessary). What I would do, is first load all your material assets you need into the scene, then build some kind of collcetion for these new materials in the document, e.g., a BaseArray, and then carry out the linking in takes. This seems like a much less error prone route to me.
Cheers,
Ferdinand