Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login
    1. Maxon Developers Forum
    2. victor
    3. Topics
    V
    • Profile
    • Following 0
    • Followers 0
    • Topics 12
    • Posts 24
    • Best 1
    • Controversial 0
    • Groups 0

    Topics created by victor

    • V

      Cinema S26 and newer is not longer threadsafe for ObjectData?

      Cinema 4D SDK
      • s26 windows c++ • • victor
      2
      0
      Votes
      2
      Posts
      478
      Views

      ferdinandF

      Hello @victor,

      Thank you for reaching out to us. While I am fairly confident that I understand your question, I am going to be very literal in my answer to avoid some ambiguities.

      Some Facts ObjectData was never 'thread-safe'. Or to be more precise, the classic API scene graph of Cinema 4D was never thread-safe (an ObjectData instance does not store any public data itself and therefore does not have to be accessed, i.e., falls outside of the notion of thread-safe or not). Some methods, as for example ObjectData::GetVirtualObjects, are never being called from the main thread and it is therefore forbidden for example to modify the scene graph or invoke EventAdd() or drawing calls from there. Some methods, e.g., ::Message(), are being called relatively often from the main thread and can therefore be used to execute things on the main thread. However, there is and never was any guarantee that ::Message() will always be on the main thread. You must still always check yourself with GeIsMainThread() or GeIsMainThreadAndNoDrawThread(). Some code could always send a message from any thread to your object. The fact that MSG_DOCUMENTINFO can now be broadcasted outside of the main thread is likely tied to async scene loading introduced with S26. The Problem with your Question

      You state that '[your] plugin requires third-party communications' and therefore assert that 'executing some functions on the main thread is necessary' for you. I do not understand what you mean by that. You should describe more precisely what you want to do in that message function.

      Do you want to modify scene graph data; add/remove objects, tags, shaders, etc. ? Do you want to modify your own global data? Do you want to communicate with a server or something like this? You should really clarify what your goals are and ideally share code with us either here or via sdk_suppport(at)maxon(dot).net. Otherwise it will be very hard to help you. Possible Solutions

      What the right solution is for you depends heavily on what you want to do. What however is not possible, is to force your ::Message method only being called from the main thread.

      Share Write Access to your own Global Data

      To do that, you should use a lock/semaphore, so that only one entity/thread at a time can access your data, e.g., write to a global log file or send data to a server. There are classic API and maxon API types which can help you with that. It is strongly recommend to use them over similar functions of the std library.

      Modify the Scene Graph

      You must defer the execution of your code to the main thread here. There are in principle two ways to achieve that.

      Defer by waiting: The simplest pattern is to simply store the notion that you want to do X on the main thread when you encounter the the state Y in a non-main thread. In the simplest form this could be a private field Bool _doX; on your object hook which you then set to true. The next time ::Message is being called and you are on the main thread, you then simply carry out doing X and then set the field back to false. The disadvantage of this approach is that you have no control over when X is actually carried out, as you must wait for something else calling your object hook on the main thread. The advantage is that you do not hold up everything else as with the second method.

      Defer with ExecuteOnMainThread: With this function you defer the execution of a lambda/delegate to the main thread. The advantage of this approach is that the changes are carried out immediately (at least relatively) and you can directly 'carry on' in your code. The disadvantage is that that the function is based on maxon::JobInterface, i.e., there is a queue of jobs on the main thread which are solved sequentially, and you might not be first in line. Also, this is by definition blocking. So, when you are inside a thread Y which has been optimized for speed, and you then defer the computationally heavy task X to the main thread, first wait for other things to be done, and then do your task X, the thread Y is waiting all that time for you and with it everything that relies on that thread. This does not mean that you should not use the function, but you should be careful.

      It could look something like this (untested pseudo-code):

      MyObjectData::Message(GeListNode* node, Int32 type, void* data) { // The #something event has happened, and we are not on the main thread. if ((type == ID_SOMETHING) && !GeIsMainThreadAndNoDrawThread()) { // We add a cube to the document of #node from the main thread. maxon::ExecuteOnMainThread([&node]() { iferr_scope_handler { err.CritStop(); return; }; BaseDocument* const doc = node.GetDocument(); BaseObject* const cube = BaseObject::Alloc(Ocube); if (!doc || !cube) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION); doc->InsertObject(cube, nullptr, nullptr); }, maxon::WAITMODE::DONT_WAIT); } // Other code ... return SUPER::Message(node, type, data); }

      You could also use other more complex approaches here, but they are always just a variation of these two (e.g., use a MessageData or SceneHookData plugin).

      Cheers,
      Ferdinand

    • V

      How to check if the object/document in on Render Queue

      Cinema 4D SDK
      • sdk c++ • • victor
      3
      0
      Votes
      3
      Posts
      530
      Views

      ferdinandF

      Hello @victor,

      without any further replies or questions, we will consider this thread as solved by Thursday and flag it accordingly.

      Thank you for your understanding,
      Ferdinand

    • V

      Knowing if C4D is actually rendering

      Cinema 4D SDK
      • • • victor
      3
      0
      Votes
      3
      Posts
      608
      Views

      ferdinandF

      Hello @victor,

      without any further questions, we will consider this topic as solved by Monday and flag it accordingly.

      Thank you for your understanding,
      Ferdinand

    • V

      Check if GetVirtualObjects is called for Motion Blur

      Cinema 4D SDK
      • c++ • • victor
      12
      0
      Votes
      12
      Posts
      2.0k
      Views

      M

      Hi @victor unfortunately, the development team told us there is no way to achieve that without hooking directly into the render which is not possible for Cinema 4D built-in rendered.

      Cheers,
      Maxime.

    • V

      Signal for actual closing C4D (not C4DPL_ENDPROGRAM)

      Cinema 4D SDK
      • c++ • • victor
      2
      0
      Votes
      2
      Posts
      544
      Views

      M

      Hi @victor, C4DPL_ENDPROGRAM is called really at the end of Cinema 4D just before it quits. It's most likely that you search for C4DPL_ENDACTIVITY which is sent before any PluginEnd so it's the place to free the resources.
      For more information see Plugin Functions Manual: Shutdown.

      If you have any questions, please let me know.
      Cheers,
      Maxime.

    • V

      Current document in Team Render

      Cinema 4D SDK
      • c++ • • victor
      3
      0
      Votes
      3
      Posts
      801
      Views

      V

      @r_gigante It was about updating an object during the render process but I used a different aproach just by sending the object's doc to that function so I think it could be solved already.

    • V

      ParseTupleAndKeywords in R20

      Cinema 4D SDK
      • c++ r20 python • • victor
      5
      0
      Votes
      5
      Posts
      1.4k
      Views

      V

      @y_puech said in ParseTupleAndKeywords in R20:

      Hi Victor,

      There's a logic error in the code you posted from the first post. The condition for R20 if (str.IsEmpty()!=false) returns false if the string has content.
      It makes more sense to call IsPopulated() for the R20 code instead of IsEmpty().

      You are right, thank you!!!

    • V

      Having issues with LoadDll and c4d_main

      Cinema 4D SDK
      • c++ r20 • • victor
      5
      0
      Votes
      5
      Posts
      1.3k
      Views

      V

      In our case it was a bit more complex but we managed to bypass the issue using load delay dlls.

      Thank you all!

    • V

      Force update interface of the plugin

      Cinema 4D SDK
      • c++ sdk • • victor
      4
      0
      Votes
      4
      Posts
      1.5k
      Views

      M

      @m_adam said in Force update interface of the plugin:

      Regarding advice from @mp5gosu, MSG_CHANGE is only needed when the structure of the object change (you change the count of point for example) since SetParemeter will automatically increase the dirty count of an object is not needed in your case.

      Sorry, I actually meant EventAdd().

    • V

      Add functions to python via C++ SDK [R20]

      Cinema 4D SDK
      • c++ python • • victor
      4
      0
      Votes
      4
      Posts
      1.5k
      Views

      Y

      Hi Víctor,

      To retrieve parameters a function must be initialized with PYFN_FLAGS::KEYWORDS. Then use pylib.ParseTupleAndKeywords() to get the value for each parameter.
      The following code shows the implementation of a function which expects a string, an integer and a float:

      static _PyObject *extendpyapi_PassParameters(_PyObject *self, _PyObject *args, _PyObject *keywords) { PythonLibrary pylib; String str; Int32 integer = 0; Float real = 0.0f; const Char *kwlist[] = {"str", "integer", "real", nullptr}; if (!pylib.ParseTupleAndKeywords(args, keywords, "$if", kwlist, &str, &integer, &real)) return nullptr; if (str.Content()) GePrint("Parameter str: " + str); GePrint("Parameter integer: " + String::IntToString(integer)); GePrint("Parameter real: " + String::FloatToString(real)); return pylib.ReturnPyNone(); } ... moduleFunctions[1].Init("PassParameters", (PyFn)extendpyapi_PassParameters, PYFN_FLAGS::KEYWORDS, "PassParameters() - Extend Python API");
    • V

      MAXON_MODULE_ID undeclared identifier [R20 C++ plugin]

      Cinema 4D SDK
      • • • victor
      8
      0
      Votes
      8
      Posts
      2.5k
      Views

      A

      Hi Riccardo!

      Thank you very very much for your detailed explanation.
      That helped me a lot and YEAHHHH....got it working ✌ ☺

      Thanx in advance for your time!

      Best regards
      Andi

    • V

      Problems with RegisterMessagePlugin in R20

      Cinema 4D SDK
      • • • victor
      2
      0
      Votes
      2
      Posts
      897
      Views

      a_blockA

      Hi,

      in Cinema 4D R20 the return value of NewObj() has changed. It now returns a ResultPtr<>. This simply means you need to properly handle the error case.

      In our C++ SDK documentation this is covered on the API Transition page and in more detail in the Error Handling manual.

      In the microsdk example there's a snippet showing one way to handle the error.

      One last request, please consider tagging your posts (as I did now here), so we can keep this forum tidy and easy to search.

      Cheers,
      Andreas