Tag plugin

On 17/11/2017 at 08:07, xxxxxxxx wrote:

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).

On 17/11/2017 at 08:23, xxxxxxxx wrote:

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.

On 20/11/2017 at 08:10, xxxxxxxx wrote:

Hi Daniel,

my apology, I agree, my answer missed the point of your question.

Maybe the warning not to use EventAdd() in a threaded context is a bit harsh. Of course you are right, it just posts an event. The function is thread safe, too. The warning is actually more about, that it should not be done. Posting EventAdd() during scene execution pipeline can easily get you into an endless loop of scene evaluation, for example.
Or maybe view it from the other side: You shouldn't do anything in a threaded context, that makes EventAdd() necessary.

In any case I think, you have a valid point, our documentation is a bit weak here. I have put it on our ToDo list to add some more explanation and context on this topic.

On 21/11/2017 at 00:35, xxxxxxxx wrote:

Andreas, no need to apologize.
Your comment about messages did bring up MSG_MENUPREPARE and MSG_POLYGONS_CHANGED, which was exactly what I needed for the initialization part. So, thanks for bringing that up.

However, (yep, there's always a but), I have noticed that MSG_POLYGONS_CHANGED, along with MSG_POINTS_CHANGED, both gets posted twice in a row when the tag is drag-n-dropped from one object onto another. Of course I only check on the changed polygon message, but still process it twice, as I have no clue when to skip the second one.

While it isn't the end of the world to initialize the tag data twice, I am wondering the reason for the double post.
Whenever I modify the object's geometry, I only get the messages once.

On 21/11/2017 at 01:51, xxxxxxxx wrote:

Did some further testing with MSG_POLYGONS_CHANGED when I modify an object's geometry.
This message is apparently sent before the whole object structure change is finalized.

Let me explain.
I create a cube primitive (6 polygons) and make it editable.
I then select the top polygon (= polygon index 4)
I switch to edge mode, and select edges via a ring selection, and apply a "connect edges".
This results in 4 of the 6 polygons to be splitted nicely in two. Resulting in 10 polygons, 12 points, no ngons.

However, when the MSG_POLYGONS_CHANGED comes in and following code is executed:

          Int32 polyCount = ToPoly(obj)->GetPolygonCount();  
          Int32 pointCount = ToPoly(obj)->GetPointCount();  
          Int32 ngonCount = ToPoly(obj)->GetNgonCount();  
          BaseSelect* polygonS = ToPoly(obj)->GetPolygonS();  
          maxon::BaseArray<Int32> polySel;  
          Int32 seg = 0, a, b, i;  
          while (polygonS->GetRange(seg++, LIMIT<Int32>::MAX, &a, &b))  
              for (i = a; i <= b; ++i)  

Results are:
pointCount = 12 -> OK
polyCount = 10 -> OK
ngonCount = 4 -> WHAAAT ???

polySel = Count 1, [4] -> a single polygon with index that of the original polygon BEFORE the geometry change, while that polygon has been splitted into new polygons with indeces 8 and 4.

But the ngon count is what bugs me the most.
Well, OK, the polygon selection is also an important piece of information which I hoped being able to use.
Guess this MSG_POLYGONS_CHANGED isn't the one to rely on after all. It looked such a good solution, though.

On 21/11/2017 at 06:03, xxxxxxxx wrote:

No really good news here.

a) When a tag gets dragged to another object, the polygon/point change messages are sent twice. Yes, indeed. There's nothing you can do to avoid this.

b) Also your second observation is correct. MSG_POINTS_CHANGED/MSG_POLYGONS_CHANGED do get sent before the final update of the object (at least in several occasions). So really the only info you should rely upon is the point or polygon count delivered with the message.


On 23/11/2017 at 03:03, xxxxxxxx wrote:

No good news indeed.

a) I can do some internal trickery (using the object's GUID) to detect that the second message is for the same object. No worries there.
However, I mistakenly assumed (once more) that when an object's geometry gets changed its GUID remains the same. Apparently this isn't the case.
As such, there is no way to distinguish the incoming MSG_POLYGONS_CHANGED being related to a tag being dropped onto another object, or if the assigned object's geometry gets changed.

Back to the drawing board for me then.

b) for completeness (to those reading this thread) :
Along with the message a VariableChanged is passed, containing the old and new point count or polygoncount (depending the message).
In case of moving the tag to another object, the first message passes along in the "old_cnt" the number of points/polygon of the object where the tag is moved away from, and in the "new_cnt" the number of points/polygon of the object the tag is moved to.
The second message then contains the number of points/polygon of the moved-to object in both members.
Not that this is useful to me, but it might for anyone reading this (now or in the future).

On 23/11/2017 at 10:00, xxxxxxxx wrote:

Regarding a) and GUIDs, did you see this thread.
Unfortunately we have no optimal solution in there, either. But at least it contains a lot of background info and maybe some ideas that might help.

On 24/11/2017 at 01:00, xxxxxxxx wrote:

Hi Andreas,

Yes, I followed that thread when it was active, but didn't care much about the cache and generator related information. I understood the GUID was the way to go for general editing and manipulation of objects.
Read it all again last week, and just now. Still am confused about all that information, as it seems there is not a single way to refer to any object in a unique way.

Furthermore, Riccardo talks about CRC64 being used internally, while only CRC32 is available in the SDK.

I'll have a look if using GUID in combination with GeMarker is a better solution, as the latter seems to remain identical when geometry is changed.

In the end MSG_MENUPREPARE and MSG_POLYGONS_CHANGED seem to be useful, but not in the context I need. As such, I will probably revert to using the scenehook solution, since this was a generic solution when tag is added via tag menu, or InsertTag() or MakeTag() command, or python script.