[SOLVED]BuildShaderPopupMenuI python

On 03/04/2017 at 09:51, xxxxxxxx wrote:

Is there a function like BuildShaderPopupMenul in python?

If not is there any hint for recreating this function in python.

I feel dirty to register a c++ plugin only for creating and storing a basecontainer.
But if there is no other way I will go for it.

Thanks in advance ! :)

On 04/04/2017 at 11:11, xxxxxxxx wrote:


no, this function is not available in Python, sorry. And in C++ it's marked private, so we can not really recommend its use, currently. May I ask in what environment are you trying to build such a menu?

On 04/04/2017 at 11:18, xxxxxxxx wrote:

I'm currently working in a light lister for multiple render engine. And some render engine (Arnold for exemple) can take any shaders for a parameter. That allow for exemple to pass a noise to the light intensity.

So basicly in my light lister I want to offer to the user the possibility to create any kind of shader into my light lister.

Everything is working correctly I just need a list of all shader installed. And I guess it's why BuildShaderPopupMenul is done.
An other option is to manually write the BS with c4d shader and then with FilterPluginList retrieve plugin shader. But it will be long to do and tedious to do.

On 10/04/2017 at 10:09, xxxxxxxx wrote:


the issue with BuildShaderPopupMenu is that it also contains a bunch of commands, you most like don't want or even worse, which work only in specific context.

It's not that difficult to get the shaders and internally it's done roughly like so:

import c4d
def BrowseShaders(bcShader, bcPath, bp) :
    while bp is not None:
        if bp.GetType() == c4d.PLUGINTYPE_SHADER and (bp.GetInfo() & c4d.PLUGINFLAG_HIDE) == 0 :
            bpId = bp.GetID()
            bpName = bp.GetName()
            bpFilename = bp.GetFilename()
            #print bpId, bpName, bpFilename
            bcShader.SetString(bpId, bpName)
            if bcPath is not None:
                if bpId == 1012158 or bpId == 1012161 or bpId == 1012166 or bpId == 1012160:
                    bcPath.SetString(bpId, "Sketch and Toon")
                elif bpId == 1018767 or bpId == 1018654 or bpId == 1019397 or bpId == 440000050:
                    bcPath.SetString(bpId, "MoGraph")
                    bcPath.SetString(bpId, bpFilename)
        BrowseShaders(bcShader, bcPath, bp.GetDown())
        bp = bp.GetNext()
def main() :
    bcShader = c4d.BaseContainer()
    bcPath = c4d.BaseContainer()
    bp = c4d.plugins.GetFirstPlugin()
    BrowseShaders(bcShader, bcPath, bp)
    # print collected plugins
    print "PlugIns -------------------"
    for idx, value in bcShader:
        print idx, value
    # print collected paths
    print "Paths ---------------------"
    for idx, value in bcPath:
        print idx, value
if __name__=='__main__':

The main part is then the sorting, which I don't want to post here (and actually don't want to port to Python). That's also the reason for bcPath to be filled. So it's not that tedious.

On 10/04/2017 at 10:15, xxxxxxxx wrote:

Thanks you a lot andreas !

Yeah doing this way is not that tedious. I thinked about build it myself by saing ID XXXX = NOISE, ID XXX = SOMETHING ESLE who will be in this case very tedious ^^.
I often forget everything in c4d is plugin. And I didn't look for GetFirstPlugin my bad.
And thanks for taking time to make a compelte exemple.