Solved Run a GUI Dialog AFTER C4D Launches not BEFORE?

Hi,

How do I run a dialog after C4D UI launches not before?

Here is the code that I used:

if __name__ == "__main__":

    if condition:
        c4d.gui.MessageDialog("BT Rendering Utilities. This beta version expired. Please download another on the website.")

    else:
        c4d.plugins.RegisterCommandPlugin(BASE_PLUGIN_ID, "_BT Rendering Utilities Pop Up",0, None, "_BT Rendering Utilities Pop Up", MyMenuPlugin())

591dcb62-ffcb-494e-8790-a475e819313e-image.png

Hi @bentraje,

I‘m not sure but maybe checking for c4d. C4DPL_PROGRAM_STARTED in def PluginMessage(id, data) could be of any help here.

Something like below.

import c4d
import sys

def PluginMessage(id, data):
    if id == c4d.C4DPL_PROGRAM_STARTED:
        # Do your messaging here. 
        return True

    return False

Cheers,
Sebastian!

Hi @HerrMay

Thanks for the response.
Unfortunately, it doesn't work in my use case since that code requires the plug-in to be initialized first.

I want to do the check first before any plug-in initialization.

I did try to have a pseudo plug-in. The plug-in to initialize first before others. But the PluginMessage only gets called after all the plug-in is initialized.

Hello @bentraje,

Thank you for reaching out to us. The answer from @HerrMay is correct, you should use PluginMessage, it will convey the multiple stages of a Cinema 4D app life cycle to you, including stages where the plugins have not yet been registered.

Be aware that in some stages, e.g., C4DPL_INIT_SYS, even system modules, e.g., c4d and maxon, might not have been fully initialized or are not fully functional. C4DPL_INIT is the earliest point where you are guaranteed to have full access to all modules.

Using dummy plugins is not recommend due to plugins slots being limited to fifty for NodeData derived plugins and the general overhead a plugin does produce. Also remember that you can make use of the different execution contexts of a module, when it is initialized and the execution context is '__main__', i.e., when Cinema 4D wants to actually register the plugin.

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net

@ferdinand

Ah gotcha. There is no way around it as again I don't want to initialize the plug-ins at all until the UI + check works out.

Anyway, having the the GUI dialog before C4D launches is not bad.
I was just wondering if I can do it after without initializing all the plugins.

Hello @bentraje,

I might have been unclear here. You can have the dialog at a different point of time, but you are bound to what PluginMessage is able to convey. You can also do it like you and licensing_example_r21.py are doing it, and simply rely on the __main__ execution context, because when the file is being called with it, you are in the C4DPL_INIT stage. But you can also launch your dialog when for example

  • C4DPL_STARTACTIVITY is being emitted after all plugins have been loaded but before Cinema 4D is done loading. dd6478f2-140b-487d-aea2-c3fbcb024b6a-image.png
  • or when C4DPL_PROGRAM_STARTED is being emitted, and the app is "ready to go"
    0af86ee9-ce51-4969-b714-a5c589f87f17-image.png

You can also go earlier or later; I would recommend having a look at the plugin message IDs. And just in case you are planning to do some hot swapping, i.e., update an outdated plugin before Cinema 4D wants to load it, this can be quite complicated, and it is not supported by us.

Find a simple example below.

Cheers,
Ferdinand

import c4d
import typing

LICENSE_IS_VALID: bool = True

def PluginMessage(mid: int, data: typing.Any) -> bool:
    """Called by Cinema 4D to convey larger portions of the app state starting or ending.
    """
    if mid == c4d.C4DPL_PROGRAM_STARTED and not LICENSE_IS_VALID:
        c4d.gui.MessageDialog("BT Rendering Utilities. This beta version expired. "
                              "Please download another one from our website.")
        return True
        
    return False

def RegisterPlugin() -> bool:
    """Checks the license of the plugin and registers it.

    Could also be done inside the __main__ context guard, but I like putting it in a function :)
    """
    CheckLicense = lambda : False

    # CHeck for a valid license and bail on registering when it is not given.
    if not CheckLicense():
        global LICENSE_IS_VALID
        LICENSE_IS_VALID = False
        return False
    
    # Do the registering ...
    # return c4d.plugins.Register...
    return True


if __name__ == "__main__":
    if not RegisterPlugin():
        print ("Warning: Could not register ...")

MAXON SDK Specialist
developers.maxon.net

@ferdinand

Thanks for the response.

With the illustration code you provided, I misunderstood the documentation. Thanks for the clarification.

Basically, I thought the

PluginMessage/RegisterPlugin functions should be method (i.e. they should be under the class of the plugin data, command data etc).

They actually live outside the classes.

It now works as expected.
Thanks! :)