I am struggling with getting a LinkBox UI to update when setting the content of the LinkBox from code. Specifically I can not get the arrow on the left of the LinkBox to appear that allows the user to edit the content of the LinkBox.
As soon as I interact with any other element on the UI the LinkBox refreshes and the arrow appears, but I would like to have it happen right away.
Attached is the code that creates and fills the LinkBox as well as the code that dynamically creates the Linkbox when GetDDescription is called.
Bool Material::Message(GeListNode* node, Int32 type, void* data)
{
case MSG_DESCRIPTION_COMMAND:
{
DescriptionCommand* dc = (DescriptionCommand*) data;
const Int32 msg_id = GetDescriptionCommandMessageId(dc);
switch (msg_id)
{
case:
(MATERIALGROUP_DYNAMIC +
MATERIALELEMENTS::ADD_MATERIAL_BUTTON))
{
auto doc = mat->GetDocument();
if (doc == nullptr)
{
return;
}
auto* material = BaseMaterial::Alloc(MAT_ID_material);
if (!material)
return;
doc->StartUndo();
doc->InsertMaterial(material);
EventAdd();
doc->AddUndo(UNDOTYPE_NEWOBJ, material);
doc->EndUndo();
int index_base = 0;
{
index_base = MATERIALGROUP_DYNAMIC;
BaseContainer* bc = material->GetDataInstance();
bc->SetLink(index_base + MATERIALELEMENTS::SHADER_LINK_MATERIAL, material);
}
//FAILED Attempts to get the UI to update so far below
C4dMainThreadDispatcher::enqueueAction([node]() {
node->SetDirty(DIRTYFLAGS::DESCRIPTION);
node->SetDirty(DIRTYFLAGS_ALL);
EventAdd(EVENT_FORCEREDRAW);
});
node->SetDirty(DIRTYFLAGS::DESCRIPTION);
node->SetDirty(DIRTYFLAGS_ALL);
EventAdd(EVENT_FORCEREDRAW);
break;
}
}
}
}
Bool Material::GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags)
{
if (!description->LoadDescription(material))
return false;
int group_id = MATERIALGROUP_DYNAMIC;
BaseContainer shader_group_bc = GetCustomDataTypeDefault(DTYPE_GROUP);
{
shader_group_bc.SetInt32(DESC_COLUMNS, 2);
shader_group_bc.SetInt32(DESC_SCALEH, 1);
description->SetParameter(DescLevel(group_id + MATERIALELEMENTS::SHADER_LINK_PARENT, DTYPE_GROUP, 0), shader_group_bc, group_id);
}
{
BaseContainer bc = GetCustomDataTypeDefault(DTYPE_BASELISTLINK);
bc.SetString(DESC_NAME, "Shader"_s);
bc.SetInt32(DESC_CUSTOMGUI, CUSTOMGUI_LINKBOX);
//list of allowed types
BaseContainer ac;
ac.SetInt32(Mmaterial, 1);
bc.SetContainer(DESC_ACCEPT, ac);
description->SetParameter(DescLevel(group_id + MATERIALELEMENTS::SHADER_LINK_MATERIAL, DTYPE_BASELISTLINK, 0),
bc, group_id + MATERIALELEMENTS::SHADER_LINK_PARENT);
}
{
BaseContainer bc = GetCustomDataTypeDefault(DTYPE_BUTTON);
bc.SetInt32(DESC_CUSTOMGUI, CUSTOMGUI_BUTTON);
bc.SetString(DESC_NAME, "Create Material"_s);
bc.SetInt32(DESC_ANIMATE, DESC_ANIMATE_OFF);
description->SetParameter(DescLevel(group_id + MATERIALELEMENTS::ADD_MATERIAL_BUTTON, DTYPE_BUTTON, 0), bc,
group_id + MATERIALELEMENTS::SHADER_LINK_PARENT);
}
flags |= DESCFLAGS_DESC_LOADED;
return SUPER::GetDDescription(node, description, flags);
}
As you can see I've tried calling EventAdd both on the C4D main thread as well as directly as well es setting some dirty flags that should trigger a redraw. From debugoutput I can tell, that GetDDescription does get called even multiple times after clicking on the "add Material" button.
Any suggestions are welcome
cheers,
Lorenz