Solved Hide description element using MessageData::CoreMessage() function

Hello,
I am aware of hiding elements using NodeData::GetDDescription() function, but I need to hide the elements using MessageData::CoreMessage() function.
My scenario is like this:
I am working on an external renderer, and on my render settings when clicking "Render" Button, I would hide that and show "Abort Render" button instead. I have handled this using NodeData::GetDDescription(), but now when the Rendering is finished I want to Hide "Abort Render" button and instead show "Render" button again.
Since I know when the rendering is finished (Adding a special event with ID = DL_RENDER_FINISHED "SpecialEventAdd(RENDERING_FINISHED);", and I can catch this event using CoreMessage() function, I thought it might possible to hide the elements on this function too.

Bool RenderManager::CoreMessage(Int32 id, const BaseContainer &bc)
{
	if (id == RENDERING_FINISHED) 
        {
	     ApplicationOutput("Finished"); //This get's shown exactly after rendering is finished so I know I get the message when I need it. 
             //Need a way to hide an element and show another instead.??
        }
}

Is there any way I can achieve this?
Thank you.

hi,

I'm a bit surprised that your render can be triggered from a NodeData (but why not)
But i don't understand why you can't use GetDDescription to update your node.

That's what i did (in a probably too naive way) but you got the idea. I just got a boolean display_aboard on my ObjectData and i switch it as i needed.
If i presse the button, i switch and i set dirty my node, if i receive the message that the render is finished (or stopped) i set my bool to false and i SetDirty my node.

static const Int32 g_pc12584ButtonID = 1000;

	
class pc12584_object : public ObjectData
{

	INSTANCEOF(pc12584_object, ObjectData);

public:
	static NodeData* Alloc() { return NewObjClear(pc12584_object); };

	Bool Init(GeListNode* node) override
	{
		display_aboard = false;
		return true;
	}

	BaseObject* GetVirtualObjects(BaseObject* op, HierarchyHelp* hh) override
	{
		BaseObject* null = BaseObject::Alloc(Onull);
		return null;
	}


	Bool GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags) override
	{
		
		if (!description->LoadDescription(Obase))
			return false;
		

		const DescID* singleid = description->GetSingleDescID();
		const Int32 ID = g_pc12584ButtonID;
		const DescID cid = DescLevel(ID, DTYPE_BUTTON, 0);

		if (!singleid || cid.IsPartOf(*singleid, nullptr))
		{
			BaseContainer bc = GetCustomDataTypeDefault(DTYPE_BUTTON);

			bc.SetInt32(DESC_CUSTOMGUI, CUSTOMGUI_BUTTON);
			if (display_aboard)
				bc.SetString(DESC_NAME, "Aboard Render"_s);
			else
				bc.SetString(DESC_NAME, "Render"_s);
			bc.SetInt32(DESC_ANIMATE, DESC_ANIMATE_OFF);
			bc.SetInt32(DESC_SCALEH, 1);

			description->SetParameter(cid, bc, DescLevel(ID_OBJECTPROPERTIES));
		}

		flags |= DESCFLAGS_DESC::LOADED;
		
		return SUPER::GetDDescription(node, description, flags);
	}


	Bool Message(GeListNode* node, Int32 type, void* data) override
	{
		switch (type)
		{
		case MSG_DESCRIPTION_COMMAND:
		{
			DescriptionCommand* dc = (DescriptionCommand*)data;

			const Int32 id = dc->_descId[0].id;

			if (id == g_pc12584ButtonID)
			{
				display_aboard = !display_aboard;
				node->SetDirty(DIRTYFLAGS::DESCRIPTION);
			}
			break;
		}
		case g_pc12584Message:
		{
			display_aboard = false;
			node->SetDirty(DIRTYFLAGS::DESCRIPTION);
			break;
		}
		}

		return SUPER::Message(node, type, data);
	};

private:
	Bool display_aboard = false;


};


// function to send a message to the ObjectData.
static maxon::Result<void> PC12854_Message(BaseDocument* doc)
{

	iferr_scope;
	// update the first object 
	BaseObject* op = doc->GetFirstObject();
	if (op == nullptr)
		return maxon::NullptrError(MAXON_SOURCE_LOCATION);

	op->Message(g_pc12584Message);


	return maxon::OK;
}


Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

hi,

it's a bit strange that you are talking about GetDDescription witch is for NodeData and CoreMessage witch is more about a GeDialog.

If you are inside a NodeData you should react to a message received and set a flag and the NodeData dirty.

display_aboard = false;
node->SetDirty(DIRTYFLAGS::DESCRIPTION);

Setting the node dirty will trigger the GetDDescription function and an update of the UI.

If you are in a GeDialog things are manage with groups and LayoutFlushGroup.

Basically you flush the group and recreate it.

We got example of dynamic GeDialog here and also for Descriptions

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

hi @m_magalhaes
Yes I am talking about NodeData and the CoreMessage used is not GeDialog::CoreMessage() but is a MessagePlugin MessageData::CoreMessage() which I am using to receive core messages which in this case are the SpecialEvents I have added when clicking Render Button as in below.

Bool RenderSettings::Message(GeListNode* i_node, Int32 i_type, void* i_data)
{
        DescriptionCommand* dc = (DescriptionCommand*)i_data;
	BaseContainer* dldata = ((BaseVideoPost*)i_node)->GetDataInstance();
	switch (i_type)
	{
	case MSG_DESCRIPTION_COMMAND:
	{
                switch (dc->_descId[0].id)
		{
		case RENDER_BUTTON:
		  SpecialEventAdd(START_RENDER);
		  break;
                //Other cases
                 }
        }
}

Now I am catching this special events using CoreMessage function of MessageData. I am doing this way because I need an event telling me when the rendering is finished and this has nothing to do with a NodeData(Which tells me when the rendering starts) or GeDialog as none of this tells me how long does it take for the rendering to finish.

Hi,

I do not fully understand what you are trying to do, but @m_magalhaes already gave you the crucial hint IMHO. You can flag your node as description dirty via SetDirty(DIRTYFLAGS::DESCRIPTION) and then react there to whatever you want to react to. AFAIK it is impossible to modify a description of a node outside of GetDDescription and have these description changes properly reflected in the GUI of the node. So unless I am wrong about this, you won't have any choice but to go this route.

Cheers,
zipit

MAXON SDK Specialist
developers.maxon.net

hi,

I'm a bit surprised that your render can be triggered from a NodeData (but why not)
But i don't understand why you can't use GetDDescription to update your node.

That's what i did (in a probably too naive way) but you got the idea. I just got a boolean display_aboard on my ObjectData and i switch it as i needed.
If i presse the button, i switch and i set dirty my node, if i receive the message that the render is finished (or stopped) i set my bool to false and i SetDirty my node.

static const Int32 g_pc12584ButtonID = 1000;

	
class pc12584_object : public ObjectData
{

	INSTANCEOF(pc12584_object, ObjectData);

public:
	static NodeData* Alloc() { return NewObjClear(pc12584_object); };

	Bool Init(GeListNode* node) override
	{
		display_aboard = false;
		return true;
	}

	BaseObject* GetVirtualObjects(BaseObject* op, HierarchyHelp* hh) override
	{
		BaseObject* null = BaseObject::Alloc(Onull);
		return null;
	}


	Bool GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags) override
	{
		
		if (!description->LoadDescription(Obase))
			return false;
		

		const DescID* singleid = description->GetSingleDescID();
		const Int32 ID = g_pc12584ButtonID;
		const DescID cid = DescLevel(ID, DTYPE_BUTTON, 0);

		if (!singleid || cid.IsPartOf(*singleid, nullptr))
		{
			BaseContainer bc = GetCustomDataTypeDefault(DTYPE_BUTTON);

			bc.SetInt32(DESC_CUSTOMGUI, CUSTOMGUI_BUTTON);
			if (display_aboard)
				bc.SetString(DESC_NAME, "Aboard Render"_s);
			else
				bc.SetString(DESC_NAME, "Render"_s);
			bc.SetInt32(DESC_ANIMATE, DESC_ANIMATE_OFF);
			bc.SetInt32(DESC_SCALEH, 1);

			description->SetParameter(cid, bc, DescLevel(ID_OBJECTPROPERTIES));
		}

		flags |= DESCFLAGS_DESC::LOADED;
		
		return SUPER::GetDDescription(node, description, flags);
	}


	Bool Message(GeListNode* node, Int32 type, void* data) override
	{
		switch (type)
		{
		case MSG_DESCRIPTION_COMMAND:
		{
			DescriptionCommand* dc = (DescriptionCommand*)data;

			const Int32 id = dc->_descId[0].id;

			if (id == g_pc12584ButtonID)
			{
				display_aboard = !display_aboard;
				node->SetDirty(DIRTYFLAGS::DESCRIPTION);
			}
			break;
		}
		case g_pc12584Message:
		{
			display_aboard = false;
			node->SetDirty(DIRTYFLAGS::DESCRIPTION);
			break;
		}
		}

		return SUPER::Message(node, type, data);
	};

private:
	Bool display_aboard = false;


};


// function to send a message to the ObjectData.
static maxon::Result<void> PC12854_Message(BaseDocument* doc)
{

	iferr_scope;
	// update the first object 
	BaseObject* op = doc->GetFirstObject();
	if (op == nullptr)
		return maxon::NullptrError(MAXON_SOURCE_LOCATION);

	op->Message(g_pc12584Message);


	return maxon::OK;
}


Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer