Hi All,
My plugin needs to collect system configuration information.
It would be ideal to collect:
System Hostname
CPU Name
GPU Name
RAM capacity
I need this info for both windows and osx.
Thank you
Hi All,
My plugin needs to collect system configuration information.
It would be ideal to collect:
System Hostname
CPU Name
GPU Name
RAM capacity
I need this info for both windows and osx.
Thank you
Hi All,
Pretty straight forward. How can I quit the Cinema 4D application from my C++ plugin?
I cant find anything obvious in the documentation.
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
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
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.
/////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);
}
}
@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!
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.
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.
SpecialEventAdd();
that would be caught by GUI::CoreMessage
which calls AddStaticText()
and then would continue after SpecialEventAdd();
where more draw calls are. But since I think your right about a loop in C4D itself the GUI::CoreMessage
part of the loop isnt called when there are draw calls in the "queue". Maybe looking for a way to force it synchronously/////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!
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 =(
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.
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.
Hi everybody,
I have a class GUI : public GeDialog
class and I have implemented the function bool GUI::Command(Int32 id, const BaseContainer &msg)
I can send a message to that function like this: 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?
@PluginStudent Thank you for pointing me at the specific examples in the docs. It can be a little daunting finding the right thing. I was able to solve my problem using your example as a template.
Thanks!
@zipit Thank you for your comment! The render thread was trying to take the document from the main thread and that was the first part of my issue. I also had a progressHook
callback that was sending a SpecialEventAdd(CUSTOMEVENT::)
message and when I caught that message I was calling EventAdd()
which you can only do from the main thread I think.
Hi thanks for your help.
I did use NODOCUMENTCLONE
. doc is the current open and active document.
I setup the render like so:
RenderData* const rdata = doc->GetActiveRenderData();
BaseContainer renderSettings = rdata->GetData();
// render one frame
const BaseTime startFrame = renderSettings.GetTime(RDATA_FRAMEFROM, BaseTime());
renderSettings.SetTime(RDATA_FRAMETO, startFrame);
// target bitmap
AutoAlloc<BaseBitmap> bitmap;
const Int32 width = renderSettings.GetInt32(RDATA_XRES);
const Int32 height = renderSettings.GetInt32(RDATA_YRES);
const IMAGERESULT imageRes = bitmap->Init(width, height);
// render the image
const RENDERFLAGS renderFlags = RENDERFLAGS::NODOCUMENTCLONE;
const RENDERRESULT res = RenderDocument(doc, renderSettings, progHook, nullptr, bitmap, renderFlags, nullptr);
I might just copy that example you showed as that is very similar to what I need to do. Maybe you could also help explain the example: I don't get where g_displayBitmap
is initialized. Is it a global variable?
Hey There,
I am using a plugin to launch a render on a separate thread. In my threads main function I use this to start the render:
const RENDERRESULT res = RenderDocument(doc, renderSettings, progHook, nullptr, bitmap, renderFlags, nullptr);
A handfuls of seconds after the render starts I am left with an EXC_BAD_ACCESS error. I think this means I am accessing something in memory I shouldn't but I don't know how to debug which thread or which variable is causing me issues.
I have attached a screenshot of my error.
Thanks for any help!