Intercept GvMessage(s)



  • On 14/09/2016 at 15:35, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   17 
    Platform:    Mac  ;  Mac OSX  ; 
    Language(s) :     C++  ;

    ---------
    Following up on my previous thread:

    https://plugincafe.maxon.net/topic/9673/13012_item-selection-in-gvoperatordatafillportsmenu

    I've now got my ports menu filled out and I can manually add ports and connections to my nodes.

    My next issue is I want to intercept a couple of different GvMessage(s), particularly GV_MESSAGE_NODE_SELECTED and GV_MESSAGE_NODE_DESELECTED. Right now, I'm not sure which of my plugin(s)/classes are supposed to intercept these in their respective Message() methods. I tried in my GvOperatorData, GeDialog, and my GvNodeMaster's parent node, but they all never get those messages.

    Is there an example of this working? Also, I didn't see it in the GvMessage enum, but is there a message sent whenever the user has created a new connection between two nodes?

    Thanks!
    Ian



  • On 15/09/2016 at 03:43, xxxxxxxx wrote:

    Hi Ian,

    when the selection state of a node changes, there are basically two things happening:

    a) A CoreMessage EVMSG_GRAPHVIEWCHANGED is sent, which you can receive in the dialog hosting your GraphView. This is probably the right place, if you want to for example update a CustomGuiDescription, which is exposing the parameters of the nodes.

    b) A message hook gets called by GvWorld. You can register your own GvHook during PluginStart() with RegisterHook(), which provides means for a couple of different hooks, in this case you are interested in the message hook. 
    This could roughly look like so:

    	static Bool MessageHookFunc(GvMessHook &hook)
    	{
    		if (hook.id == GV_MESSAGE_NODE_CREATED)
    		{
    			BaseList2D* newNode = hook.mess.GetLink(GV_MESSAGE_FIRST_DATA_ID, hook.document);
    			GePrint("Node created: " + newNode->GetName());
    		}
    		else if (hook.id == GV_MESSAGE_PORT_RENAMED)
    		{
    			GePrint("port renamed");
    		}
    		else if ((hook.id == GV_MESSAGE_NODE_SELECTED) || (hook.id == GV_MESSAGE_NODE_DESELECTED))
    		{
    			BaseList2D* const selectedNode = hook.mess.GetLink(GV_MESSAGE_FIRST_DATA_ID, hook.document);
    			const Int32 operatorId = hook.mess.GetInt32(GV_MESSAGE_FIRST_DATA_ID + 1);
    			const Int32 ownerId = hook.mess.GetInt32(GV_MESSAGE_FIRST_DATA_ID + 2);
      
    			GePrint("Node selection change: " + selectedNode->GetName());
    		}
    		else
    		{
    			GePrint("Message ID: " + String::IntToString(hook.id));
    		}
    		return true;
    	}
      
    	Bool RegisterGVHook()
    	{
    		GvHook h;
    		h.hook_name = "My Hook";
    		h.hook_id = ID_MY_HOOK; // unique plugin ID, may be the same as the owner id, if a unique plugin ID is used for owner
    		h.owner_id = ID_GV_GENERAL_OWNER; // use to restrict callback to certain nodes (see op_owner of GvRegisterOperatorPlugin())
    		h.message = MessageHookFunc;
      
    		return GvGetWorld()->RegisterHook(h, nullptr);
    	}
    

    Note: In this way your message hook will be called for all other general nodes as well. Use owner Id as mentioned in comments to restrict this.



  • On 15/09/2016 at 14:56, xxxxxxxx wrote:

    Hi Andreas,

    I tried your first method and I do get the EVMSG_GRAPHVIEWCHANGED message, but I'm not sure how that relates to the other GV_MESSAGES? I checked ID of the BaseContainer (i.e.: msg.GetId()) but that doesn't seem to be in the range of any of the GV_MESSAGES. I thought I could query for it via the GvNodeGUI class, but it doesn't seem like that's possible.

    Let me try your second method and I'll get back to you if it works or not. I would prefer the first method, but if the second method works then I'll use that instead.

    Also, do you know the answer to my other question about what message is sent when a connection between two nodes are made?

    Thanks!
    Ian



  • On 16/09/2016 at 01:45, xxxxxxxx wrote:

    Hi Ian,

    with EVMSG_GRAPHVIEWCHANGED and EVMSG_CHANGE you are generally being notified about a change, that might affect your node system or pose a need for an update. Depending on your needs also EVMSG_DOCUMENTRECALCULATED should be taken into account. At this point you can scan your nodes and detect changes. These event messages do not relate to the graph view messages at all (except that in some situations both get triggered).

    And this is also the only option I'm aware of to detect new connections. Sorry, I overlooked this question in your first post.

    Just a side note, as it's often forgotten: It's a good idea to use CheckCoreMessage() on CoreMessage() for speedup.



  • On 16/09/2016 at 10:13, xxxxxxxx wrote:

    Hi Andreas,

    Hmm...that's going to be tough. I'm a little concerned about having to check the graph on every change. Some of our shading networks can be pretty large; I'm worried about speed if I have to traverse the graph just to see if a new connection was made somewhere in the graph. I'll try it out and see what it's like.

    By the way, your GvHook suggestion did work out for me, so a bit of good news. :)

    Thanks!
    Ian


Log in to reply