Solved Dialog Plugin with Progress Bar or SetStatusBar

Hi folks,

I’m fiddling around with the c4d.CUSTOMGUI_PROGRESSBAR and c4d.SetStatusBar in Python for quite a while now but can’t get it to work correctly. I’m trying to e.g rename a bunch of objects from a Dialog Plugin and set the progress bar accordingly.

When I use the code from the example of this thread the bar is update accordingly to the Timer BUT the moment I put in my code to act on the selected objects, the objects get renamed and the bar immediately gets updated to 100% AFTER the renaming action. So no incremental update… Why is that? Is there any way to simultaneously do the work on the objects and have to bar update properly?

I also found this code example where in a video is shown how its supposed to work. However when I use this I get the same behavior as described above. BTW it does make NO difference if I execute this code from the Script Manager or as a Plugin.

I hope I could explained the problem well enough to follow. If not just let me know.
Ah, before I forget I’m doing all this weirdness on macOS with R18.

Cheers,
Sebastian

Hi @HerrMay sorry for the late reply, just re-checking and I can indeed confirm it doesn't work on R18 MAC. However, this is fixed in R19 mac and it's working correctly on windows.

Unfortunately, we don't support more than 2 versions, so R18 is out of scope, and since the issue comes from Cinema 4D side, I don't see a way for you to fix it.

Sorry for the long wait for just confirm that it doesn't work...
Cheers,
Maxime.

hi,

welcome to our forum :)
please have a look at our forum guidelines to use the tag functionality and "ask question" .

I would say that this depend on how fast is your action, if you are renaming only a few objects that can be so fast that you don't really have time to see the progess bar.
The example below show the difference, the "short" task will barely show the progress bar.

import c4d
from c4d import gui

class TestDialog(gui.GeDialog):
    
    PROGRESSBAR = 1001
    ID_BTN_01 = 1002
    ID_BTN_02 = 1003

    def __init__(self):
        self.progress = 0
    
    def StopProgress(self):
        self.progress = 0
        progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
        progressMsg.SetBool(c4d.BFM_STATUSBAR_PROGRESSON, False)
        self.SendMessage(self.PROGRESSBAR, progressMsg)
    
    def CreateLayout(self):
        self.SetTitle("ProgressBar Example")
        
        self.GroupBegin(id=1000, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP, cols=0, rows=1)
        self.AddCustomGui(self.PROGRESSBAR, c4d.CUSTOMGUI_PROGRESSBAR, "", c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 0, 0)
        self.GroupEnd()
        self.GroupBegin(id = 1005, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP, cols=2, rows=1)
        self.AddButton(self.ID_BTN_01, c4d.BFH_SCALEFIT, 100, 15, name="Do Something short") 
        self.AddButton(self.ID_BTN_02, c4d.BFH_SCALEFIT, 100, 15, name="Do Something longer") 
        self.GroupEnd()
        
        return True

    
    def Command(self, id, msg):
        if (id == self.ID_BTN_01):
            #do something short 
            opecnt = 100;
            for x in range(opecnt):
                self.progress += 1
                progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
                progressMsg[c4d.BFM_STATUSBAR_PROGRESSON] = True
                progressMsg[c4d.BFM_STATUSBAR_PROGRESS] = self.progress/opecnt
                self.SendMessage(self.PROGRESSBAR, progressMsg)
            self.StopProgress()
        if (id == self.ID_BTN_02):
            # do seomthing longer 
            opecnt = 10000;
            for x in range (opecnt):
                self.progress += 1
                progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
                progressMsg[c4d.BFM_STATUSBAR_PROGRESSON] = True
                progressMsg[c4d.BFM_STATUSBAR_PROGRESS] = self.progress/opecnt
                self.SendMessage(self.PROGRESSBAR, progressMsg)
            self.StopProgress()
        return True
        
    def AskClose(self):
        self.StopProgress()
        return False


if __name__=='__main__':
    dialog = TestDialog()
    dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=0, defaulth=400, defaultw=400)

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

Hi Manuel,

thanks for your the time and the example code. :-)

I’m aware that depending on the time the execution of my action takes, the process of updating the progress bar can take more or less time. Just to be sure I didn’t overlook some fundamental things, I gave your code a shot and well what can I say – it doesn’t work.

I try to explain more clearly whats happening. If I run it as is I don’t even get a bar to see. I have to comment the self.StopProgress() method to actually see a bar at all. (This is maybe what you were referring to by saying: „… don’t really have time to see the progess bar…“

I then increased the count in your example to 100.000 and all I’m getting is a sort of freezing Cinema and a beachball of death (macOS mouse cursor) while it is running. When it’s done the progress bar is updated up to 100% in one go. When really what I want is an real time updating progress bar that has a 1:1 relationship with my selected objects/materials, etc…

Is this maybe a macOS related problem (as the examples in my first post didn’t work as well and the guy in the video was clearly running Windows)? Or do I have to this kind of progress bar updating from another thread? And if so – how would I go about it?

BTW I dont’t want to mix up things here, but the same goes for c4d.StatusSetBar(). Setting the percentage in a loop doesn’t incrementally update the bar.

Cheers,
Sebastian

hi,
my bad, on mac, it's a lot faster than on windows.
If i add a sleep on the code (making it a lot slower) than the progress bar is there.
if you don't add time and make 100000 loop, you will see the bar update twice (or something like that).
You can't ask the UI to be refresh 100000 in one second.

I would try to see how many time my code take to do its job.

progress_bar.gif

import c4d
from c4d import gui
import time

class TestDialog(gui.GeDialog):
    
    PROGRESSBAR = 1001
    ID_BTN_01 = 1002
    ID_BTN_02 = 1003

    def __init__(self):
        self.progress = 0
    
    def StopProgress(self):
        print("stop progress")
        self.progress = 0
        progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
        progressMsg.SetBool(c4d.BFM_STATUSBAR_PROGRESSON, False)
        self.SendMessage(self.PROGRESSBAR, progressMsg)
    
    def CreateLayout(self):
        self.SetTitle("ProgressBar Example")
        
        self.GroupBegin(id=1000, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP, cols=0, rows=1)
        self.AddCustomGui(self.PROGRESSBAR, c4d.CUSTOMGUI_PROGRESSBAR, "", c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 0, 0)
        self.GroupEnd()
        self.GroupBegin(id = 1005, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP, cols=2, rows=1)
        self.AddButton(self.ID_BTN_01, c4d.BFH_SCALEFIT, 100, 15, name="Do Something short") 
        self.AddButton(self.ID_BTN_02, c4d.BFH_SCALEFIT, 100, 15, name="Do Something longer") 
        self.GroupEnd()
        
        return True

    
    def Command(self, id, msg):
        if (id == self.ID_BTN_01):
            #do something short 
            opecnt = 100;
            for x in range(opecnt):
                self.progress += 1
                progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
                progressMsg[c4d.BFM_STATUSBAR_PROGRESSON] = True
                progressMsg[c4d.BFM_STATUSBAR_PROGRESS] = self.progress/opecnt
                self.SendMessage(self.PROGRESSBAR, progressMsg)
            self.StopProgress()
        if (id == self.ID_BTN_02):
            # do seomthing longer 
            opecnt = 10000;
            for x in range (opecnt):
                time.sleep(0.0001)
                self.progress += 1
                progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
                progressMsg[c4d.BFM_STATUSBAR_PROGRESSON] = True
                progressMsg[c4d.BFM_STATUSBAR_PROGRESS] = self.progress/opecnt
                self.SendMessage(self.PROGRESSBAR, progressMsg)
            self.StopProgress()
        return True
        
    def AskClose(self):
        self.StopProgress()
        return False


if __name__=='__main__':
    dialog = TestDialog()
    dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=0, defaulth=400, defaultw=400)

cheers
Manuel

MAXON SDK Specialist

MAXON Registered Developer

Hi Manuel,

hmm… that’s weird. Tried that code as well but the progress bar is still not showing up.
I recorded a small screen capture for you to see what i meant by saying: “…I don’t even get a bar to see…“
Maybe this will make things clearer.

Cheers,
Sebastian

Example.gif

Hi @HerrMay looks like you are in R18 meaning you are using Python 2.7 which by default do an int division so changing

self.progress += 1 to self.progress += 1.0 will force a float division and give the expected result (the short one will produce nothing since it's executed too fast but the long one work)

Cheers,
Maxime.

Hi @m_adam,

I’m sorry, but nope that doesn’t change anything. I mean you’re right Python 2.7 is doing integer division by default but forcing a float division doesn’t do it for me here. As you can see in my screencast the UI is kind of blocked when I hit the button for „do something longer“. The progress bar only shows up if I comment self.StopProgress(). BUT it is then showing up completely full and not constantly updating like in Manuels example.

By now I slowly get the feeling that it is simply not working this way. To me it looks like the UI is blocking the update process. But then again I don’t understand why it is working in Manuels example. Since he is clearly executing the code on macOS as I do.

Here it's working as expected in R18 could you try the next code (use the Do something Longer button) (this is the same Manuel posted with the float modification)

import c4d
from c4d import gui
import time

class TestDialog(gui.GeDialog):
    
    PROGRESSBAR = 1001
    ID_BTN_01 = 1002
    ID_BTN_02 = 1003

    def __init__(self):
        self.progress = 0
    
    def StopProgress(self):
        print("stop progress")
        self.progress = 0
        progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
        progressMsg.SetBool(c4d.BFM_STATUSBAR_PROGRESSON, False)
        self.SendMessage(self.PROGRESSBAR, progressMsg)
    
    def CreateLayout(self):
        self.SetTitle("ProgressBar Example")
        
        self.GroupBegin(id=1000, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP, cols=0, rows=1)
        self.AddCustomGui(self.PROGRESSBAR, c4d.CUSTOMGUI_PROGRESSBAR, "", c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 0, 0)
        self.GroupEnd()
        self.GroupBegin(id = 1005, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP, cols=2, rows=1)
        self.AddButton(self.ID_BTN_01, c4d.BFH_SCALEFIT, 100, 15, name="Do Something short") 
        self.AddButton(self.ID_BTN_02, c4d.BFH_SCALEFIT, 100, 15, name="Do Something longer") 
        self.GroupEnd()
        
        return True

    
    def Command(self, id, msg):
        if (id == self.ID_BTN_01):
            #do something short 
            opecnt = 100
            for x in range(opecnt):
                self.progress += 1.0
                progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
                progressMsg[c4d.BFM_STATUSBAR_PROGRESSON] = True
                progressMsg[c4d.BFM_STATUSBAR_PROGRESS] = self.progress / opecnt
                self.SendMessage(self.PROGRESSBAR, progressMsg)
            self.StopProgress()
        if (id == self.ID_BTN_02):
            # do seomthing longer 
            opecnt = 10000;
            for x in range (opecnt):
                time.sleep(0.0001)
                self.progress += 1.0
                progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
                progressMsg[c4d.BFM_STATUSBAR_PROGRESSON] = True
                progressMsg[c4d.BFM_STATUSBAR_PROGRESS] = self.progress / opecnt
                self.SendMessage(self.PROGRESSBAR, progressMsg)
            self.StopProgress()
        return True
        
    def AskClose(self):
        self.StopProgress()
        return False


if __name__=='__main__':
    dialog = TestDialog()
    dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=0, defaulth=400, defaultw=400)

Hi @m_adam,

I tried your code as well but still no luck…
However in R20 it is working as expected. So maybe after all it is R18 related?

Cheers,
Sebastian

Hi @HerrMay sorry for the late reply, just re-checking and I can indeed confirm it doesn't work on R18 MAC. However, this is fixed in R19 mac and it's working correctly on windows.

Unfortunately, we don't support more than 2 versions, so R18 is out of scope, and since the issue comes from Cinema 4D side, I don't see a way for you to fix it.

Sorry for the long wait for just confirm that it doesn't work...
Cheers,
Maxime.

Hi @m_adam,
ah, okay I see. I was afraid that this would be the case.
However, thank you for clarification. ;-) You can close this thread if you like.
Cheers,
Sebastian

Hello @HerrMay,

thank you for your reply. Please note that we prefer users to flag topics as solved, as doing it ourselves always comes with the danger of erroneously flagging a posting as solved. Please refer to our Forum Guidelines - Forum Feature: Ask as Question in case you do not know how to do this.

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net