Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Hi everybody,
I have a class GUI : public GeDialog class and I have implemented the function bool GUI::Command(Int32 id, const BaseContainer &msg)
class GUI : public GeDialog
bool GUI::Command(Int32 id, const BaseContainer &msg)
I can send a message to that function like this: SpecialEventAdd(CUSTOMEVENT::UPDATE_UI_DIALOG, 3);
SpecialEventAdd(CUSTOMEVENT::UPDATE_UI_DIALOG, 3);
My issue is that my main thread is running a for loop and when it finishes it calls SpecialEventAdd and then starts another for loop, but my message isn't in caught in bool GUI::Command until after the for second for loop finishes. Is there anyway to make the main thread wait for the SpecialEventAdd message is caught?
for
SpecialEventAdd
bool GUI::Command
Shouldn't you catch core messages by implementing GeDialog::CoreMessage()?
GeDialog::CoreMessage()
SpecialEventAdd() adds a message to an event queue, which is processed at some point. So I don't think you can force that to process the message synchronously.
SpecialEventAdd()
If you somehow want to update the UI, there is GeUpdateUI(). But I don't know if that is synchronous or not.
Your totally right!
I actually do catch it in Bool GUI::CoreMessage(Int32 id, const BaseContainer &bc). Basically yes i want to force it synchronously =(
Bool GUI::CoreMessage(Int32 id, const BaseContainer &bc)
If i wanted to try GeUpdateUI() i think i would have the same issue because inside where I catch the message then I call SetString(DLG_DYNAMIC_RENDER_TEXT, "text"_s); so the message needs to still come before GeUpdateUI() i think.
GeUpdateUI()
SetString(DLG_DYNAMIC_RENDER_TEXT, "text"_s);
Should I update the UI with a different function then call GeUpdateUI() .
ApplicationOutput(); has the same issue. Its like the way to get synchronous output is writing to a file but then I cant see it in realtime.
ApplicationOutput();
Hi,
I think it would be best if you would provide some (dummy) code to illustrate what you are doing, because there multiple things that remain unclear (at least to me).
GeDialog
Cheers, zipit
Hi Zipit - sorry it took time to get back to this. Here is some sample code that I hope shows what i am trying to do. in the ZoomInOut function i want the SpecialEventAdd(); message to be caught by GUI::CoreMessage before the second for loop in in ZoomInOut starts.
ZoomInOut
SpecialEventAdd();
GUI::CoreMessage
In GUI::CoreMessage I catch the SpecialEventAdd(); message and call SetString(DLG_DYNAMIC_RENDER_TEXT, "test changed text"_s); which does change the AddStaticText dialog on my panel, but it doesnt update until after the second for loop.
SetString(DLG_DYNAMIC_RENDER_TEXT, "test changed text"_s);
AddStaticText
AddStaticText()
/////main.cpp///// Bool GUI::CoreMessage(Int32 id, const BaseContainer &bc) { switch (id) { case CUSTOMEVENT::UPDATE_UI_DIALOG: { SetString(DLG_DYNAMIC_RENDER_TEXT, "test changed text"_s); } } } bool GUI::CreateLayout() { AddStaticText(DLG_DYNAMIC_RENDER_TEXT, BFH_LEFT, 250, 12, "initial text "_s, BORDER_NONE); return true; } ////testclass.cpp//// void TestClass::ZoomInOut(int steps) { for (int i = 0; i < steps; i++) { CallCommand(14063); DrawViews(DRAWFLAGS::ONLY_ACTIVE_VIEW | DRAWFLAGS::NO_THREAD | DRAWFLAGS::NO_REDUCTION | DRAWFLAGS::STATICBREAK); } //this message isnt caught until the for loop below it is completed, need it to be synchronous SpecialEventAdd(CUSTOMEVENT::UPDATE_UI_DIALOG); for (int i = 0; i < steps; i++) { CallCommand(14064); DrawViews(DRAWFLAGS::ONLY_ACTIVE_VIEW | DRAWFLAGS::NO_THREAD | DRAWFLAGS::NO_REDUCTION | DRAWFLAGS::STATICBREAK); } }
Thank you for your help!
due to the flag DRAWFLAGS::NO_THREAD, your multiple viewport redraws are executed synchronously and make the execution of TestClass::ZoomInOut rather lengthy. This in turn blocks the redraw of your dialog, because that will only happen once the program left the scope of ZoomInOut (or more precisely the scope of the GeDialog method that called ZoomInOut).
DRAWFLAGS::NO_THREAD
TestClass::ZoomInOut
Despite that:
CallCommand
steps
hi,
Sorry, i don't understand what's the goal of your code ? Maybe it's just a design issu. That could surely help us to understand what you are trying to do.
Your function Bool GUI::CoreMessage(Int32 id, const BaseContainer &bc) in main.cpp ?
More important, who is calling ZoomInOut and from where ?
This question need some lights.
For example, if ZoomInOut is called in your tread, you can make it loop until the special event have done its job. If it's called in the main thread it's not a good way to go.
Cheers, Manuel
@zipit
Hi Zipit - I do want the DRAWFLAGS::NO_THREAD because when I time the draw calls having other threads would give me inconsistent timing over multiple tests. It sounds like the way C4D works this is all expected and because i am forcing so many draw calls the GeDialog doesnt get updated till after.
Your right about CallCommand - just being lazy to zoom in and out instead of changing the editor camera position. My use case dictates lots of draw calls, it is in the hundreds to thousands.
Thank you!
@m_magalhaes
Hi m_magalhaes - The goal is to time how long it takes to do all the draw calls inside ZoomInOut. Yes Bool GUI::CoreMessage(Int32 id, const BaseContainer &bc) in in main.cpp
main.cpp
I added to the code to show there is a button in GUI::CreateLayout() that calls GUI::Command(Int32 id, const BaseContainer &msg) which then calls ZoomInOut
GUI::CreateLayout()
GUI::Command(Int32 id, const BaseContainer &msg)
I have to call ZoomInOut from the main C4D thread because DrawViews can only be called by the main thread. I think that is how i understand the documentation.
DrawViews
/////main.cpp///// TestClass testClassInstance = TestClass(); Bool GUI::CoreMessage(Int32 id, const BaseContainer &bc) { switch (id) { case CUSTOMEVENT::UPDATE_UI_DIALOG: { SetString(DLG_DYNAMIC_RENDER_TEXT, "test changed text"_s); } } } bool GUI::CreateLayout() { AddStaticText(DLG_DYNAMIC_RENDER_TEXT, BFH_LEFT, 250, 12, "initial text "_s, BORDER_NONE); AddButton(RUN_TESTS, BFH_LEFT, 0, 0, "Run Test"_s); return true; } bool GUI::Command(Int32 id, const BaseContainer &msg) { switch (id) { case RUN_TESTS: { testClassInstance.ZoomInOut(); } } } ////testclass.cpp//// void TestClass::ZoomInOut(int steps) { for (int i = 0; i < steps; i++) { CallCommand(14063); DrawViews(DRAWFLAGS::ONLY_ACTIVE_VIEW | DRAWFLAGS::NO_THREAD | DRAWFLAGS::NO_REDUCTION | DRAWFLAGS::STATICBREAK); } //this message isnt caught until the for loop below it is completed, need it to be synchronous SpecialEventAdd(CUSTOMEVENT::UPDATE_UI_DIALOG); for (int i = 0; i < steps; i++) { CallCommand(14064); DrawViews(DRAWFLAGS::ONLY_ACTIVE_VIEW | DRAWFLAGS::NO_THREAD | DRAWFLAGS::NO_REDUCTION | DRAWFLAGS::STATICBREAK); } }
I would expect the gui to be with your class, the main only registering your CommandData but as long as you find yourself confortable, that's the same.
CommandData
What i could suggest is once you hit the button "start" you can use SetTimer using 1 as parameter.
You can override the function Timer or catch the message BFM_TIMER_MESSAGE inside your Message function.
Message
you can call
DrawViews(DRAWFLAGS::ONLY_ACTIVE_VIEW|DRAWFLAGS::NO_REDUCTION|DRAWFLAGS::NO_THREAD|DRAWFLAGS::NO_ANIMATION|DRAWFLAGS::PRIVATE_NO_WAIT_GL_FINISHED|DRAWFLAGS::NO_HIGHLIGHT_PLANE);
without feedback, i'll set this thread to solved tomorrow.