Use existing data for DynamicDescription
-
Hello,
I was checking on how to add a new tab in the attributes manager using DynamicDescription object but I could only do so if I create all the data by myself. Is there any way that I can do this but from the data that already exist.
Example:
I have a tree-view where you can add different shaders and what I need is that whenever a shader is selected I need to show the attributes of that shader (created in a res file) in the Attributes Manager. Is such a thing possible?
Thank you. -
Hello,
typically, you can extend the UI of a
NodeData
based plugin by implementingGetDDescription()
. This allows to add new groups and parameters to that element's parameter description.Within GetDDescription() you could access another object and use
GetDescription()
to load its description and copy it to your object's description.It is also possible to connect these newly created parameters to the original object. This way you can interact with these parameters and edit the original object. Such a connection is created by implementing TranslateDescID().
This is a quickly thrown together example of a
ObjectData
plugin's GetDDescription() and TranslateDescID() that copies the parameters of the first object in the scene into its own parameter description:Bool GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags) { if (!description->LoadDescription(node->GetType())) return false; auto AddDescription = [](GeListNode *node, Description *description) -> maxon::Result<void> { BaseDocument* const doc = node->GetDocument(); if(doc == nullptr) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION); BaseObject* const firstObject = doc->GetFirstObject(); if(firstObject == nullptr) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION); // don't get description of yourself if(firstObject->IsInstanceOf(node->GetType())) return maxon::OK; // add dynamic group const DescID groupID = DescLevel(4000, DTYPE_GROUP, 0); BaseContainer settings = GetCustomDataTypeDefault(DTYPE_GROUP); settings.SetString(DESC_NAME, "Dynamic Group"_s); description->SetParameter(groupID, settings, 0); AutoAlloc<Description> sourceDescription; if(sourceDescription == nullptr) return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION); // get the Description of the given object if(!firstObject->GetDescription(sourceDescription, DESCFLAGS_DESC::NONE)) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION); void* handle = sourceDescription->BrowseInit(); const BaseContainer* bc = nullptr; DescID id, gid; while (sourceDescription->GetNext(handle, &bc, id, gid)) { // define new ID DescLevel topLevel = id[0]; topLevel.id += 5000; DescID newID; newID.PushId(topLevel); const Int32 depth = id.GetDepth(); for (Int32 i = 1; i < depth; ++i) { newID.PushId(id[i]); } // insert paramter into the dynamic group description->SetParameter(newID, *bc, groupID); } sourceDescription->BrowseFree(handle); return maxon::OK; }; iferr(AddDescription(node, description)) { DiagnosticOutput("Error: @", err); } flags |= DESCFLAGS_DESC::LOADED; return SUPER::GetDDescription(node, description, flags); } Bool TranslateDescID(GeListNode *node, const DescID &id, DescID &res_id, C4DAtom *&res_at) { if (!node) return false; if (id[0].id >= 5000) { BaseDocument* const doc = node->GetDocument(); if (doc != nullptr) { BaseObject* const firstObject = doc->GetFirstObject(); if (firstObject != nullptr) { res_at = (C4DAtom*)firstObject; // define new ID DescLevel topLevel = id[0]; topLevel.id -= 5000; DescID newID; newID.PushId(topLevel); const Int32 depth = id.GetDepth(); for (Int32 i = 1; i < depth; ++i) { newID.PushId(id[i]); } res_id = newID; return true; } } } return ObjectData::TranslateDescID(node, id, res_id, res_at); }
best wishes,
Sebastian -
Thanks @s_bach
This is very helpful.
Best wishes.