SOLVED How to update the scene in a threaded

I need to use a thread to import model data. During this process, I need to refresh the scene, but according to the SDK documentation, I cannot use EventAdd(). How should I refresh the scene?

Thank,
AiMiDi

Hello @AiMiDi,

it would really help if you could clarify/confirm the context. I am still assuming that you are writing a SceneLoaderData, namely for your MikuMikuDance project.

We have an example on GitHub for how to implement an im- and exporter plugin, the STL-example. Invoking the status bar indicators, i.e., StatusSetSpin. StatusSetBar and StatusSetText, for a computational process, e.g., loading a file, are a bit of a special case regarding the UI-restrictions. I always also struggle with them and what is allowed where. In general, you can get away with a bit more with them, as they do not check immediately for being on the main thread and do not refuse execution if they are not. But you can also run into problems with them outside of the main thread. With that being said, our STL example also makes use of StatusSetBar, which sort of indicates that it is safe to use within SceneLoaderData::Load (more on that later).

Regarding providing a custom progress dialogs for the import process: Most importers of Cinema do not do that. There are exceptions like the FBX importer which spawns its own dialog to give feedback for the importing process.

When you invoke GeIsMainThread() in SceneLoaderData::Load, you will see that you are in almost all cases in the main thread (at least the ones where I did try). But in the end, there is no guarantee that this will always hold true. What I would do is safeguard all GUI operations with GeIsMainThread(), including status-bar operations, i.e., only carry them out when Load is being called from the main thread and otherwise just skip them. Then you can also open as many dialogs as you want from there.

Our FBX importer plugin for example instantiates an interface for handling importing FBX within Load. Cascading out from that interfac instantiation, also a ProgressDialog will be being instantiated and opened (there are some types involved in between). But frankly, I would not bother with all that complexity and just use the status bar of the main app, i.e., StatusSetBar. Checking for the main thread seems advisable though.

Cheers,
Ferdinand

Hello @AiMiDi,

thank you for reaching out to us. Unfortunately, your question is lacking precise information on the context in which you are encountering your problem. I am assuming that you are in a SceneLoaderData plugin and load scene geometry via SceneLoaderData::Load. I am also assuming that with "the scene" you are referring to the active document of Cinema 4D, i.e., the one that is visible to the user. When you refer to the documentation not allowing the use of EventAdd(), I assume you are referring to the Cinema 4D Threading Manual and its implications for NodeData methods that are not guaranteed to run on the main thread, e.g., SceneLoaderData::Load.

You can modify the document doc passed to SceneLoaderData::Load as much as you want, since this is its purpose. But you cannot modify the active document, invoke drawing operations for it or invoke events. So, EventAdd() is only a part of what is not allowed in SceneLoaderData::Load, as you would have to modify the active document in some form in order to make EventAdd() useful.

These restrictions are unfortunately there for a reason and trying to circumvent them is not eligible for support by us. See Forum Guidelines - Support Procedures: Scope of Support for details, circumventing the threading restrictions is named explicitly as an example for an algorithmic design that is in violation of principal design patterns of Cinema 4D. We are aware that this is not the most satisfying answer for users, but are unable to meet these support requests. It also does not mean that circumventing the threading restrictions is impossible in principle, it only means that developing a workaround entails more work and intimate knowledge of the API than we can provide on a per user and per case basis. And there are also no general solution for this, because otherwise there would not be the restrictions described in the Threading Manual.

In case we have misunderstood your question, I would have to ask you kindly to elaborate the parts we did misunderstood.

Thank you for your understanding,
Ferdinand

Thank you for your reply, I understand what you mean. I can put the import processing on the main thread, but I need to update the progress bar in the dialog window to detect whether the user has clicked the cancel button. This will become impossible when the main thread is occupied. How can I update my progress bar and Check button.

Thank,
AiMiDi

Hello @AiMiDi,

it would really help if you could clarify/confirm the context. I am still assuming that you are writing a SceneLoaderData, namely for your MikuMikuDance project.

We have an example on GitHub for how to implement an im- and exporter plugin, the STL-example. Invoking the status bar indicators, i.e., StatusSetSpin. StatusSetBar and StatusSetText, for a computational process, e.g., loading a file, are a bit of a special case regarding the UI-restrictions. I always also struggle with them and what is allowed where. In general, you can get away with a bit more with them, as they do not check immediately for being on the main thread and do not refuse execution if they are not. But you can also run into problems with them outside of the main thread. With that being said, our STL example also makes use of StatusSetBar, which sort of indicates that it is safe to use within SceneLoaderData::Load (more on that later).

Regarding providing a custom progress dialogs for the import process: Most importers of Cinema do not do that. There are exceptions like the FBX importer which spawns its own dialog to give feedback for the importing process.

When you invoke GeIsMainThread() in SceneLoaderData::Load, you will see that you are in almost all cases in the main thread (at least the ones where I did try). But in the end, there is no guarantee that this will always hold true. What I would do is safeguard all GUI operations with GeIsMainThread(), including status-bar operations, i.e., only carry them out when Load is being called from the main thread and otherwise just skip them. Then you can also open as many dialogs as you want from there.

Our FBX importer plugin for example instantiates an interface for handling importing FBX within Load. Cascading out from that interfac instantiation, also a ProgressDialog will be being instantiated and opened (there are some types involved in between). But frankly, I would not bother with all that complexity and just use the status bar of the main app, i.e., StatusSetBar. Checking for the main thread seems advisable though.

Cheers,
Ferdinand