Making changes to the document through a websocket
-
Hi, I am currently working on a way, to trigger different actions through a websocket, for example triggering the undo/redo or to create a simple cube, I searched through the documentation a lot, and found the relevant functions, like creating a cube:
BaseDocument* const document = GetActiveDocument(); if (document == nullptr) return false; BaseObject* const cubeObject = BaseObject::Alloc(Ocube); if (cubeObject == nullptr) return false; cubeObject->SetName("This is a new object"_s); document->InsertObject(cubeObject, nullptr, nullptr); EventAdd();
but I am not quite sure about the context of how to use them. For example I tried making a hidden CommandData plugin to create a simple cube when it is called, to also include the creation in the undo/redo system but if the plugin is hidden from the user, its Execute function obviously is never called. Similarily, I tried calling the
BaseDocument *doc = GetActiveDocument(); if (doc) doc->DoUndo();
from within the websocket OnMessage function directly, this resultet in a breakpoint being hit inside the DoUndo() function. Probably caused by the networking layer being in a different thread than the main thread (I assume) and thus can not modify the BaseDocument in any way.
How would a design look like, to trigger such actions from within a websocket? Any help would be greatly appreciated!
-
I made some progress now, I changed the message type to be MessageData, to retrieve Core messages and in the websocket layer I now use SpecialEventAdd() with my own event ids, I see that the CoreMessage() method also supports the BaseContainer as a parameter, is it possible to fill it with custom data when calling SpecialEventAdd()? The function only seems to take two Uints as additional parameters, how would I get some custom data into my own CoreMessage method call?
Thank you again!
-
Hi using MessageData is correct, however the best way is to call ExecuteOnMainThread as you can see in the websocket example I share with you here.
This lambda will be executed on main thread, therefor it will be safe to create object and perform undo from it. One note make sure to pass a copy of the data to your lambda, since this lambda will be executed when the main thread is free and you do not know exactly when it can happen. And it can be latter than your OnMessage function, so with a copy you are sure that object are not nullptr.
Cheers,
Maxime. -
@m_adam Thanks got it! One last unrelated question, how can I switch between world and object coordinates through my plugin? I know that I can switch the tool through
BaseDocument *doc = GetActiveDocument(); doc->SetAction(ID_MODELING_MOVE);
But couldn't find any example for the coordinate space, that's the last feature set that I am missing for now
-
Hi please open new topic for any new question that is not directly related to your initial question.
If I understand correctly you want to toggle the Coordinate state, if that's the correct you can either use
CallCommand(12156) # Coordinate System
. You can find this number by opening the Script Log and if you click on the Coordinate System it will give you the Id. However CallCommand have the issue that it automatically add an Undo step, which can be an issue in some case.So the proper way would be to call:
bool enableWorld = true; doc->SetParameter(CreateDescID(DOCUMENT_STATEW), enableWorld , DESCFLAGS_SET::NONE);
How I found this, looking at the code internally, sadly it is no documented anywhere...
If you have any other questions related to this topic, reply to this topic and I will move it to a new topic.Cheers,
Maxime. -
@m_adam Thank you very much for your help in the last days! This worked as well as expected