Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > SDK Help
  New Posts New Posts
  FAQ FAQ  Forum Search   Register Register  Login Login

Tag plugin

 Post Reply Post Reply
Author
Message
C4DS View Drop Down
Member
Member


Joined: 2015 Dec 01
Online Status: Offline
Posts: 125
Post Options Post Options   Quote C4DS Quote  Post ReplyReply Direct Link To This Post Topic: Tag plugin
    Posted: 2017 Nov 13 at 6:10am

User Information:

Cinema 4D Version:   R19 
Platform:   Windows  ;   
Language(s):     C++  ;   

---------

I am using a TagData to store information for an object.
There is a reason why i don't store this information into a container in the object itself, but out of scope of this question.

I would like -inside of the tag plugin- to use GetObject() to obtain the object the tag was assigned to.
But I haven't found a way for the TagData to know when the tag is being added to the object.
At time of TagData::Init the GetObject returns a nullptr since the tag is not yet assigned.

In a scenehook I have noticed I can do following in Message():


    if (type == MSG_DOCUMENTINFO)
    {
        DocumentInfoData* did = static_cast<DocumentInfoData*>(data);
        if (did && (did->type == MSG_DOCUMENTINFO_TYPE_TAG_INSERT))
        {
            BaseTag* tag = static_cast<BaseTag*>(did->bl);
...


At this point the tag is assigned to the object and I can thus get the object from:


tag->GetObject();


I would prefer to do so in the TagData itself, but the message isn't sent to the TagData.
Is there any method which gets called (or message sent) to indicate the tag is assigned to an object.

I am not using the Execute() method of the TagData, as this gets called more than once during the lifetime of the tag. Should I focus my effort on this method to be triggered with the appropriate object, and keep some state to only handle this once? Or is there a better way to get notified when the object is available to the tag instance?

Thanks.

Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1540
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Nov 14 at 10:30am
Hi,

in general storing information in a tag is perfectly fine and a common use-case of tags.

I'm not so sure about storing the object a tag is assigned to in any way. After all the user can decide to move the tag to other objects for example. So it's probably better to make use of Execute() roughly in the way you describe.

Cheers,
Andreas
SDK Support Engineer
Back to Top
C4DS View Drop Down
Member
Member


Joined: 2015 Dec 01
Online Status: Offline
Posts: 125
Post Options Post Options   Quote C4DS Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Nov 15 at 4:46am
The purpose of obtaining the object the tag is assigned to is in order to initialize tag data which is specific to the object the tag is assigned to (number of points and polygons).
When the tag is moved (or duplicated) onto another object, the tag data needs to be re-initialized with the then applicable number of points and polygons.

Doing this in the tag's Execute() seemed to be a plausible solution, until I read about the fact that this Execute is called in a thread context, and from further reading I understood it was then forbidden to:
- add an event
- call a Draw() function
- display messagebox
- create undos

The main action does happen as a result of user interaction, but the initialization will need to display message box in some cases (unsupported features depending number of points/polygons).

The initialization will also need to trigger redrawing of a UserArea, which is performed by a CallCommand to a separate CommandData plugin's ExecuteSubID(), so probably not a problem since no drawing is actually performed in the Tag::Execute()

I 'll probably also need to create undos since in some cases polygons will need to be selected as a result of the initialization. This needs to be added to some undo, otherwise the polygon remains selected when user undoes the step which triggers the initialization.

Unless I can manage to let the initialization within Tag::Execute() send a (custom) message to the tag itself, which would then perform the whole thing in the main thread (if I understand correctly).

EDIT: Right, I forgot once more that NodeData::Message is synchronous



Edited by C4DS - 2017 Nov 15 at 6:04am
Back to Top
C4DS View Drop Down
Member
Member


Joined: 2015 Dec 01
Online Status: Offline
Posts: 125
Post Options Post Options   Quote C4DS Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Nov 15 at 6:23am
I assumed incorrectly that sending a message was the solution to the threading issue.
Well it can be, but then it needs to be one meant for MessageData::CoreMessage()
as the "Important Threading Information" indicates.
It lists an example that uses the SpecialEventAdd to sent the message, but adding an event was forbidden? Confused!
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1540
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Nov 17 at 8:07am
There's a fundamental difference between messages (i.e. send and received via Message() in NodeData derived entities) and core messages (send by SpecialEventAdd() and received in CoreMessage() of for example a MessageData).
The first ones are synchronous messages, so the code is executed directly, when Message() is called. If it's called in a threaded context, the receiving side is executing in the same thread context.
Core messages (also event messages) are asynchronous, they get queued and will be received in CoreMessage() in the main thread.

See also the NodeData::Message() manual and the Core Messages manual.

In order to do you initialization work, you may want to look into MSG_MENUPREPARE (also NodeData::Message() - Creation manual), which will be send, when the user creates the tag. When received the tag is already inserted into the object.
And then later on messages like MSG_POINTS_CHANGED or MSG_POLYGONS_CHANGED may help to keep track. These will also be send, if the user moves the tag to another object (even if point/polygon count stay the same).

Cheers,
Andreas
SDK Support Engineer
Back to Top
C4DS View Drop Down
Member
Member


Joined: 2015 Dec 01
Online Status: Offline
Posts: 125
Post Options Post Options   Quote C4DS Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Nov 17 at 8:23am
I already understood the difference between "regular" messages and core messages.
My only confusion was that the documentation mentions that in a thread context no events are allowed to be sent, and then shows to use SpecialEventAdd().

EVMSG_xxx is a core message as a result of an EventAdd().
SpecialEventAdd() also generates a core message, thus an event.
Hence my confusion, of being/not-being allowed to add events from a thread context.

I still need to have a second look at MSG_MENUPREPARE and MSG_POLYGONS_CHANGED, but these will probably be very helpful. Thanks for reminding me of those.

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.109 seconds.