Group Details Private

administrators

  • RE: WebSocket usage in C++

    Hi I do not have access to PostMan so it's hard to reproduce. Would be nice if you can provide a Python/C++/Javascript code that act as a client. So take my answers with a grain of salt.
    In my example I used a VsCode plugin (so a NodeJS instance), you can have a look at the client implementation
    Cinema-4D-Visual-Studio-Code-Extension
    .

    With that's said looking at the error I would say your request header should contain the protocol in the Sec-WebSocket-Protocol fields which should match the one you defined in mWebSocketServer.StartWebServer(addr, false, "<tried different values here but no change>"_s) iferr_return;.
    While Sec-WebSocket-Protocol is normally not a mandatory field, in our implementation it is mandatory to provide one.

    Cheers,
    Maxime.

    posted in Cinema 4D SDK
  • RE: WebSocket usage in C++

    Hi @Cankar001 we do not really have any official example for the Websocket, but fortunately I did make the Visual Studio Code Bridge project, which have the duty to exchange code from VSCode to Cinema via Websocket, and it's open source. So it is not nicely documented and explained as an example could be but it can serve you as a base.
    So find this example in Cinema-4D-Legacy-Visual-Studio-Code-Bridge-Plugin and look at the websocket_json_codeexchange.h and cpp.

    The main entry point is in WebSocketJsonCodeExchangeImpl::Start where all the observable are properly feed.

    Three special notes:

    • The code was written for S26 and is now directly merged into Cinema 4D, so it is not up to date, so for the observable the new way is to call it like that:
    g_wsServer.ObservableHandshake(true).AddObserver(OnHandShake) iferr_return;
    g_wsServer.ObservableConnected(true).AddObserver(OnConnected) iferr_return;
    g_wsServer.ObservableDisconnected(true).AddObserver(OnDisconnected) iferr_return;
    g_wsServer.ObservableMessage(true).AddObserver(OnMessage) iferr_return;
    
    • ObservableHandshake observable always need to be defined otherwise you won't be able to connect. Even if it's empty (like mine in OnHandShake).
    • You need to close all connections before calling StopWebServer otherwise it will wait forever. This means you needs to keep tracks of all theses connections somehow. In my case I do it by storing connections in a BaseArray during the OnConnect within the WebSocketJsonCodeExchangeImpl which is as a Singleton (so only one instance of it exist).

    Regarding your question it does not compile because you are calling it wrongly if I may say. First you pass a nullptr argument at the end that is not needed and secondly you do not handle the error that AddObserver emit which is probably the cause of the non-compilation. I would advice you to read Maxon API - Error Handling. With that's said here the adapted version that compile:

    g_wsServer.ObservableConnected(true).AddObserver(
    	[](const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) -> maxon::Result<void>
    	{
    		iferr_scope;
    		return maxon::OK;
    	}) iferr_return;
    

    If you need more help and there is detail you have hard time to understand in the code example do not hesitate to ask questions.
    Cheers,
    Maxime.

    posted in Cinema 4D SDK
  • RE: Center Axis with Python

    Hi @Kantronin,

    Instead of creating multiple consequent postings please consolidate them in a single one. I've also noticed that you've added "programming" tag but haven't mentioned the language you're talking about (is it c++ or python?).

    Regarding your questions. Transforming the axis of a PointObject effectively means transforming the point values. There're some helping commands that I've shown you in my previous message, but what they effectively do is just transforming the points. Please have a look into the operation_transfer_axis_s26.py example, which demonstrates how to perform axis translation.

    As for the rotation part, I'd need to point you once again to our Matrix Manual, which actually contains the answer to your question. Namely, the chapter "Constructing and Combining Transforms" explains the usage of functions c4d.utils.MatrixRotX(), c4d.utils.MatrixRotY() and c4d.utils.MatrixRotZ(). I will not copy & paste the same code snippet from our manual, so please check it youself.

    Combining these with the example above should do the trick for you, unless you don't have the initial transformation of your ring splines. If that's the case, then your task turns into a way more complex form of the optimization problem.

    Please also note, that you can only do the object axis transformations on PointObject (and on PolygonObject since it's inherited from PointObject). This effectively means that if you're using the Osplinecircle instead of an ordinary Ospline, this wouldn't work, as it doesn't store any points inside. In this case you'd need to convert to Ospline. If that's not an option for you, you can check the Geometry Axis and Geometry Orientation scene nodes, as they allow you to transform the axis "on-the-fly", so this would work even with non-point objects.

    Cheers,
    Ilia

    posted in General Talk
  • RE: Help on Car Rig

    Hey @chakuew0 this question is out of scope of this forum which is solely about the Cinema 4D API. So we will let the community answers.

    For any question related to the pure usage of Cinema 4D without any scripting please reach the Maxon Support.

    Cheers,
    Maxime.

    posted in General Talk
  • RE: Get and Set any parameter with Tag

    Hi @gheyret,

    For such complex drag-n-drop scenarios you're welcome to use our C++ SDK (check the DragAndDrop class), as Python SDK is usually pretty limiting for the drag-n-drop use cases.

    You could potentially try to work around this using MultilineEditText, which parses the attributes that were dragged onto it, but I'm afraid this is not what you're looking for after all.

    Cheers,
    Ilia

    posted in Cinema 4D SDK
  • RE: Center Axis with Python

    Hi @Kantronin,

    I'm struggling to understand what exactly you're trying to achieve here. For your further postings please double check our Support Precedures, namely the How To Ask Questions section. Your question is also lacking the scope of question (taking into account you're posting in "General Talk"). Please note, that for the end-user questions we kindly ask you to proceed to our Support Center, where our colleauges can provide you with better support on given topic.

    With that's said and as you've mentioned you're using python, I move your posting to the "Cinema 4D SDK" subforum and give you some hints.

    I kind of induce that you want to align the global coordinate system with the local coordinate system of your object. However, the way you're saying it that you'd like to move the origin of your document into the origin of your object, confuses me a bit.

    You can check the Workplane Modes to set your workplane properly (e.g. lock it to your object ring):
    73c0a190-1899-4285-a61a-90061da1716f-image.png

    If what you're trying to do is to work with the transformation of your object, please refer to our Matrix Manual, which explains how transformations work for objects in cinema 4d. In this case you can either work with commands utilizing the transformation manipulation of the object, such as
    "Reset Transform" if you'd like to move your object to the origin or "Freeze Transform", if you'd like to define the local coordinate system for the object (which is addressed as "relative" in our API). You might be also interested in "Center to ..." group of commands, which offer you a toolset on most common transfomation manipulation actions.
    20756bf4-5539-496d-ac1d-73cc9b3e2bf6-image.png

    When you'd like to work with bare matrices, I suspect that what you're looking for is the transformation from the global origin into the object's local coordinate system, which would be defined as a global transformation matrix of the object c4d.BaseObject.GetMg():

    originToObject: c4d.Matrix = op.GetMg()
    

    or in the opposite direction is the inverse of such matrix:

    objectToOrigin: c4d.Matrix = ~op.GetMg()
    

    Cheers,
    Ilia

    posted in General Talk
  • RE: SetParameter Returns True but Doesn't Update UV Grid Checkbox in C4D

    Hi @shahir-zaman ,

    Welcome to the Maxon developers forum and its community, it is great to have you with us!

    Getting Started

    Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.

    • Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
    • Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
    • Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.

    It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: Asking Questions.

    About your First Question

    Assuming that what you're trying to achieve is to toggle the "UV Grid" option
    d09d5b8d-51a2-4a6a-9618-90b2dbcc6638-image.png
    You effectively have two options:

    1. The easiest one is to execute CallCommand(170776) (you can find the command ID in the Script Log)
    2. The more involved but also more flexible way is to find the UV settings scenehook and go through all its branches (or may be not all of them, depending on what specifically you want to achieve). Please find the C++ and Python code snippets below.

    Cheers,
    Ilia

    C++ commanddata execute function code snippet:

    Bool MyCommandData::Execute(BaseDocument* doc, GeDialog* parentManager)
    {
      const Int32 ID_UV_SETTINGS_HOOK = 1053309;
      
      if (!doc)
        return true;
     
      BaseSceneHook* sceneHook = static_cast<BaseSceneHook*>(doc->FindSceneHook(ID_UV_SETTINGS_HOOK));
      if (!sceneHook)
        return true;
     
      maxon::BufferedBaseArray<BranchInfo, 20> infos;
      sceneHook->GetBranchInfo(infos, GETBRANCHINFO::NONE) iferr_ignore("GetBranchInfo");
     
      for (BranchInfo& info : infos)
      {
        if (info.name != "UVSettingsBranch"_s)
          continue;
     
        GeListNode* viewSettings = info.head->GetFirst();
        while (viewSettings)
        {
          GeData value;
          viewSettings->GetParameter(CreateDescID(UV_SETTINGS_FILTER_SHOW_GRID), value, DESCFLAGS_GET::NONE);
          Bool valueBool = value.GetBool();
     
          value = {!valueBool};
     
          viewSettings->SetParameter(CreateDescID(UV_SETTINGS_FILTER_SHOW_GRID), value, DESCFLAGS_SET::NONE);
     
          viewSettings = viewSettings->GetNext();
        }
      }
     
      EventAdd();
     
      return true;
    }
    

    Python script code snippet (special thanks to @m_adam on this one):

    import c4d
    
    def main() -> None:
        sh = doc.FindSceneHook(1053309)
        for branch in sh.GetBranchInfo():
            if branch["name"] != "UVSettingsBranch":
                continue
            
            viewSettings = branch["head"].GetFirst()
            while viewSettings:
                viewSettings[c4d.UV_SETTINGS_FILTER_SHOW_GRID] = not viewSettings[c4d.UV_SETTINGS_FILTER_SHOW_GRID]
                viewSettings = viewSettings.GetNext()       
            
        c4d.EventAdd()
    
    if __name__ == '__main__':
        main()
    
    posted in Cinema 4D SDK
  • RE: ZBrush 2024 FileExecute Issue

    Hi @blizz_nsm ,

    Welcome to the Maxon developers forum and its community, it is great to have you with us!

    Getting Started

    Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.

    • Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
    • Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
    • Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.

    It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: Asking Questions.

    About your First Question

    Using the FileExecute is indeed the intended way to load your plugin. However, without deeper investigation it's hard to say whether such change in behavior is expected or should be considered as a bug.

    As a result of my discussion with one of our devs, there could have been some core changes that could lead to such behavior change. If that's the case, it's highly unlikely to be changed. If you'd like to proceed further with this issue, I'd kindly ask you to report the issue to our Support Center (you can mention our discussion here). Alternatively, you can add reproduction steps for the issue directly here. I picture it as a zip-folder with the hello world project that compiles in the dll + the ZScript you're using to load this dll; please also don't forget to include the specific ZBrush versions, where the issue is reproducible, as well as your system info - operating system version and CPU architecture.

    Anyway, the developer I mentioned above suggested some workaround. Namely, you can create another dll without any dependencies (let's call it "resolver"), which purpose is to search for the full paths of the dependencies of your plugin (e.g. by searching in the environment PATH variable). This way your ZScript can first execute the resolver to retrieve all your dependency absolute paths, which you could then directly load first before loading your plugin dll. Please note that we have neither confirmed your issue (as you haven't yet shared the repro steps), nor haven't we double checked the above-mentioned workaround.

    Cheers,
    Ilia

    posted in ZBrush SDK
  • RE: Change posemorph's name

    Hi thanks for the question, I've opened a bug report, for the moment the only workaround would be to remove the Morph and re-add it.

    For the moment the name in the treeview is only updated when manually edited from the treeview and on the insertion of the item in the tree view.

    Cheers,
    Maxime.

    posted in Bugs
  • RE: Is there anyway to get/set the Place tool?

    Hi sadly this is not possible. I've reached to responsible team to make them aware about it.

    Cheers,
    Maxime.

    posted in Cinema 4D SDK