@ferdinand Thank you very much! I got the min and max distances also working with your input! I used the code example from the docs to traverse through the DeformCache and it worked instantly
Cankar001
@Cankar001
I am Can, 23 years old and currently working at Corsair as a graphics developer and studying computer science in germany.
Best posts made by Cankar001
-
RE: Rendering debug UI in the viewport via plugin
-
RE: WebSocket usage in C++
Hi @m_adam, following your typescript example it worked now to connect! Thank you very much for your help
Merry Christmas and a Happy New Year!
Latest posts made by Cankar001
-
RE: Making changes to the document through a websocket
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!
-
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!
-
RE: WebSocket usage in C++
Hi @m_adam, following your typescript example it worked now to connect! Thank you very much for your help
Merry Christmas and a Happy New Year!
-
RE: WebSocket usage in C++
Hi @m_adam,
thank you again for the code suggestions, I got it compiling and running now, but now I do have a runtime failure, I am trying to test the websocket connection with postman, and I get a 500 error, the logs of Cinema 4D say this:
<net.maxon.datatype.internedid> net.maxon.http.type : <uint32> 1 <net.maxon.datatype.internedid> net.maxon.http.file : <net.maxon.interface.string-C> index.html <net.maxon.interface.string-C> sec-websocket-extensions : <net.maxon.interface.string-C> permessage-deflate; client_max_window_bits <net.maxon.interface.string-C> sec-websocket-version : <net.maxon.interface.string-C> 13 <net.maxon.interface.string-C> sec-websocket-key : <net.maxon.interface.string-C> j+y86BlBpKXcFzGDp/BOXg== <net.maxon.interface.string-C> host : <net.maxon.interface.string-C> localhost:19923 <net.maxon.datatype.internedid> net.maxon.http.connection : <net.maxon.interface.string-C> Upgrade <net.maxon.interface.string-C> upgrade : <net.maxon.interface.string-C> websocket protocol not found Connection: Stopped with error httpcode [network_websocket_base_impl.cpp(556)] Cause: websocket protocol not found [network_websocket_base_impl.cpp(646)]. httpcode [network_websocket_base_impl.cpp(556)] Cause: websocket protocol not found [network_websocket_base_impl.cpp(646)]
This is my current websocket implementation:
WebSocket::WebSocket(int port) : mPort(port) { } WebSocket::~WebSocket() { maxon::Result<void> res = mWebSocketServer.StopWebServer(); if (res.GetErrorPointer() != nullptr) { ApplicationOutput("Failed to shutdown the websocket!"); } } maxon::Result<void> WebSocket::Start() { iferr_scope; maxon::NetworkIpAddrPort addr(127, 0, 0, 1, mPort); mWebSocketServer = maxon::NetworkWebSocketServerClass().Create() iferr_return; WebSocket* instance = this; mWebSocketServer.ObservableConnected(true).AddObserver( [instance](const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) -> maxon::Result<void> { return instance->OnConnected(webSocket, request); }) iferr_return; mWebSocketServer.ObservableDisconnected(true).AddObserver( [instance](const maxon::NetworkWebSocketConnectionRef& webSocket) -> void { instance->OnDisconnected(webSocket); }) iferr_return; mWebSocketServer.ObservableHandshake(true).AddObserver( [instance](const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) -> maxon::Result<String> { return instance->OnHandShake(webSocket, request); }) iferr_return; mWebSocketServer.ObservableMessage(true).AddObserver( [instance](const maxon::NetworkWebSocketConnectionRef& webSocket, maxon::WEBSOCKET_OPCODE opCode, const maxon::BaseArray<Char>& data) -> maxon::Result<void> { return instance->OnMessage(webSocket, opCode, data); }) iferr_return; mWebSocketServer.StartWebServer(addr, false, "<tried different values here but no change>"_s) iferr_return; return maxon::OK; } maxon::Result<void> WebSocket::OnConnected(const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) { iferr_scope; return maxon::OK; } void WebSocket::OnDisconnected(const maxon::NetworkWebSocketConnectionRef& webSocket) { iferr_scope_handler { return; }; } maxon::Result<String> WebSocket::OnHandShake(const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) { iferr_scope; return ""_s; } maxon::Result<void> WebSocket::OnMessage(const maxon::NetworkWebSocketConnectionRef& webSocket, maxon::WEBSOCKET_OPCODE opCode, const maxon::BaseArray<Char>& data) { iferr_scope; return maxon::OK; }
Do you know, what could cause this error? Thank you very much for your help already!
-
RE: WebSocket usage in C++
Thank you so much @m_adam! I will take a deeper look into it and come back if I have any questions, also very good to see that there is a json parser as well already, as I was also planning to send json strings over the web socket
-
WebSocket usage in C++
Hi, i've spent quite some time now, setting up a websocket server in my plugin. The documentation unfortunately doesn't have many usage examples of the network.framework. Here is my current code that should setup and start the websocket correctly:
The instance of this class is global in the plugin main file and gets deleted when thePluginEnd
function is called. The problem that I currently have is this line:
mWebSocketServer.ObservableConnected(true).AddObserver( [](const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) -> maxon::Result<void> { return maxon::OK; }, nullptr);
This code does not compile, as the lambda can not be converted to maxon::ObserverObjectInterface*. But the docs here: https://developers.maxon.net/docs/cpp/2025_1_0/page_maxonapi_observers_usage.html state that Observers can take in lambdas and according to the header file the parameters of the lambda should be correct?
About some hints into the right direction I would be very happy
-
RE: Error compiling S24 plugin
@ferdinand Thank you very much! I rewrote my code to your example provided, and now it works. I had another issue, where I tried to set the rendering config data right in the PluginStart method, but to that time no renderer interface seemed to be running already, so I moved this dependent code to another thread, that tries to retrieve the renderer instance from the hashmap and waits every time, when it failed to retrieve the instance and sets the data if it succeeded. This workflow seems to work very good now, the config data is always provided and now I have the ability to decide in the PluginStart() function already, which debug rendering features I want to enable
I only didn't understand, why the initial errors occurred, as I didn't include any typeinfo header directly (maybe caused by another std header then). But moving the code away from std seemed to help with that too.
-
Error compiling S24 plugin
Hello,
I have worked for some weeks now on my plugin for the S24 version, but suddenly I got some compile errors, pointing to the platform toolset of visual studio. Has this happened to someone else as well? I am using VS2022, but the generator for S24 generated a VS2019 solution (or at least the projects are using the platform toolset of VS2019). Is this a known issue and does someone have a quick fix for this?
This is the error message I am getting:1>main.cpp 1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\typeinfo(39,18): error C3668: "std::bad_cast::_Doraise": Die Methode mit dem Überschreibungsspezifizierer "override" hat keine Basisklassenmethoden überschrieben. (Quelldatei wird kompiliert ..\source\SomeClass.cpp) 1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\typeinfo(40,9): error C3861: "_RAISE": Bezeichner wurde nicht gefunden. (Quelldatei wird kompiliert ..\source\SomeClass.cpp) 1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\typeinfo(51,18): error C3668: "std::bad_typeid::_Doraise": Die Methode mit dem Überschreibungsspezifizierer "override" hat keine Basisklassenmethoden überschrieben. (Quelldatei wird kompiliert ..\source\SomeClass.cpp) 1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\typeinfo(52,9): error C3861: "_RAISE": Bezeichner wurde nicht gefunden. (Quelldatei wird kompiliert ..\source\SomeClass.cpp)
The class SomeClass looks like this:
#pragma once #include <unordered_map> class DebugRenderer; class SomeClass { public: static SomeClass *GetInstance(); void RegisterDebugRenderer(int inCommandId, DebugRenderer *inRenderer); void UnregisterDebugRenderer(int inCommandId, DebugRenderer *inRenderer); DebugRenderer *FindDebugRenderer(int inCommandId); private: std::unordered_map<int, DebugRenderer*> mDebugRenderers; };
The class DebugRenderer registers itself in this singleton when being constructed and unregisters when its destructor is called.
Thank you for your time!
All the best,
CanEdit: I just tried out to remove the source files for SomeClass.h and SomeClass.cpp from the project and comment out every usage, then everything compiles successfully again. I added the files normally into the source directory and re-generated the project solution after that, so that it shows up inside visual studio and wrote the code normally inside VS. So I am not sure why this doesn't compile, any guidance would be greatly appreciated!
-
RE: Rendering debug UI in the viewport via plugin
@ferdinand Thank you very much! I got the min and max distances also working with your input! I used the code example from the docs to traverse through the DeformCache and it worked instantly
-
RE: Rendering debug UI in the viewport via plugin
Hi @ferdinand,
thank you, I managed to get it working!
This is what I tried to achieve, basically showing the distances between the objects.I still have one question, is it also possible to extract the submeshes of a mesh? The next feature I wanted to implement is to also show the min and max distances between the objects and for that I wanted to extract the submesh data, from which I could calculate the distance more precisely than from the object transform. Basically I want to be able to calculate the distance between objects from any location on the surface. How would I retrieve the surface data?
I tried doing something like this:
// current and next are two BaseObject* if (current->IsInstanceOf(Opolygon) && next->IsInstanceOf(Opolygon)) { PolygonObject *currentPolygon = static_cast<PolygonObject*>(current); PolygonObject *nextPolygon = static_cast<PolygonObject*>(next); }
But this doesn't seem to work if I test it with cubes, is there any other conversion function maybe that lets me extract the mesh surface data? Maybe extracting the faces of the object would already work for my purpose.
Thank you again!
Cheers,
Can