Solved Simple Organisational Structure Generation Script

I'm trying to create a simple script that creates a simple organisation structure using nulls. It's 99% of the way there but there is a minor detail that is evading me. You will also have to excuse the coding, this is my first foray into coding in Python so it is not the most elegant coding I'm sure.

When I set up the initial folder structure manually I set the 'Icon Color' of the Null object to 'Display Color'. In the documentation it seems I can only set it as None or Custom (ID_BASELIST_ICON_COLORIZE_MODE_NONE or ID_BASELIST_ICON_COLORIZE_MODE_CUSTOM). Obviously I could set it to a custom colour to match the layer colour but I would prefer it to be linked. Is this an option? Is there a value I can use to implement this?

from typing import Optional
import c4d
from pprint import pprint

doc: c4d.documents.BaseDocument  # The active document
op: Optional[c4d.BaseObject]  # The active object, None if unselected

def CreateLayer(name, data):
    newLayer = c4d.documents.LayerObject()
    newLayer.SetName(name)
    newLayer.SetLayerData(doc,data)
    newLayer.InsertUnder(doc.GetLayerObjectRoot())
    return newLayer

def CreateFolder(name, icon, layer):
    newFolder = c4d.BaseObject(c4d.Onull)
    newFolder[c4d.ID_BASELIST_NAME] = name
    newFolder[c4d.ID_BASELIST_ICON_FILE] = icon
    newFolder[c4d.ID_BASEOBJECT_USECOLOR] = c4d.ID_BASEOBJECT_USECOLOR_LAYER
    newFolder[c4d.ID_BASELIST_ICON_COLORIZE_MODE] = c4d.ID_BASELIST_ICON_COLORIZE_MODE_NONE
    newFolder.SetLayerObject(layer)
    doc.InsertObject(newFolder)
    c4d.EventAdd()
    return newFolder


def main() -> None:
    layerArchive = CreateLayer("ARCHIVE", {
        'solo':False,
        'view':False,
        'render':False,
        'manager':True,
        'locked':False,
        'animation':False,
        'generators':False,
        'deformers':False,
        'expressions':False,
        'xref':False,
        'color':c4d.Vector(128/255,128/255,128/255),
        })
    folderArchive = CreateFolder("ARCHIVE", "1052837", layerArchive)
    folderSpacer = CreateFolder("- - - - - - - - - - - - - - - - - - - -", "1031728", layerArchive)

    layerCameras = CreateLayer("CAMERAS", {
        'solo':False,
        'view':False,
        'render':True,
        'manager':True,
        'locked':False,
        'animation':True,
        'generators':True,
        'deformers':True,
        'expressions':True,
        'xref':True,
        'color':c4d.Vector(255/255,87/255,34/255),
        })
    folderCameras = CreateFolder("CAMERAS", "1052837", layerCameras)

    layerLights = CreateLayer("LIGHTS", {
        'solo':False,
        'view':False,
        'render':True,
        'manager':True,
        'locked':False,
        'animation':True,
        'generators':True,
        'deformers':True,
        'expressions':True,
        'xref':True,
        'color':c4d.Vector(255/255,193/255,7/255),
        })
    folderLights = CreateFolder("LIGHTS", "1052837", layerLights)

    layerGeo = CreateLayer("GEO", {
        'solo':False,
        'view':True,
        'render':True,
        'manager':True,
        'locked':False,
        'animation':True,
        'generators':True,
        'deformers':True,
        'expressions':True,
        'xref':True,
        'color':c4d.Vector(33/255,150/255,243/255),
        })
    folderGeo = CreateFolder("GEO", "1052837", layerGeo)

    layerGenerators = CreateLayer("GENERATORS", {
        'solo':False,
        'view':True,
        'render':True,
        'manager':True,
        'locked':False,
        'animation':True,
        'generators':True,
        'deformers':True,
        'expressions':True,
        'xref':True,
        'color':c4d.Vector(139/255,195/255,74/255),
        })
    folderGenerators = CreateFolder("GENERATORS", "1052837", layerGenerators)

if __name__ == '__main__':
    main()

Hi,

By default, the icon color has two modes, node or custom. Other mode can be added programmatically, that is the case of objects and lights for example. Lights do not have display color; the color parameter will be used instead.

That is why you must send a message to the object before defining the "third" value of the icon color. This message will initialise the internal data. There is no symbol defined for this "third" value. It is just ID_BASELIST_ICON_COLORIZE_MODE_CUSTOM + 1 (so 2)

newFolder.Message(c4d.MSG_GETCUSTOMICON_SETTINGS, dict())
newFolder[c4d.ID_BASELIST_ICON_COLORIZE_MODE] = 2

@bentraje solution also works and i do not see where or when it could fail but the message looks safer to me.
Thanks a lot @bentraje for sharing your knowledge on the forum it is really appreciated.

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

@nealhulme

Seems like a bug. Or a feature? Not sure lol.
Anyway, it seems like you need to trigger colorize first then change it.

def CreateFolder(name, icon, layer):
    newFolder = c4d.BaseObject(c4d.Onull)
    newFolder[c4d.ID_BASELIST_NAME] = name
    newFolder[c4d.ID_BASELIST_ICON_FILE] = icon
    newFolder[c4d.ID_BASEOBJECT_USECOLOR] = c4d.ID_BASEOBJECT_USECOLOR_LAYER
    newFolder[c4d.ID_BASELIST_ICON_COLORIZE_MODE] = 2
    newFolder[c4d.ID_BASELIST_ICON_COLORIZE_MODE] = 2
    newFolder.SetLayerObject(layer)
    doc.InsertObject(newFolder)
    c4d.EventAdd()
    return newFolder

Yep one of the lines is repeated. If you only retain one line, it wouldn't work. haha. Not sure why.

Result:
977106e6-ea2c-4e04-9b7c-28e5a737ffca-image.png

@bentraje

Thanks for the fix, at least it works how I want now. I did manage to find the value I wanted was 2 by printing it to the console but didn't think to put the line twice so it didn't seem to work. Hopefully someone may be able to explain why it is necessary to add the line twice?

Hi,

By default, the icon color has two modes, node or custom. Other mode can be added programmatically, that is the case of objects and lights for example. Lights do not have display color; the color parameter will be used instead.

That is why you must send a message to the object before defining the "third" value of the icon color. This message will initialise the internal data. There is no symbol defined for this "third" value. It is just ID_BASELIST_ICON_COLORIZE_MODE_CUSTOM + 1 (so 2)

newFolder.Message(c4d.MSG_GETCUSTOMICON_SETTINGS, dict())
newFolder[c4d.ID_BASELIST_ICON_COLORIZE_MODE] = 2

@bentraje solution also works and i do not see where or when it could fail but the message looks safer to me.
Thanks a lot @bentraje for sharing your knowledge on the forum it is really appreciated.

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

Thanks @Manuel , that is useful to know... how can be marked as 'Solved'?

@nealhulme

you can have a look at our forum guidelines we have a section that explains how to mark your thread as a question. Then you can select a post as the answer or mark the thread solved.

I forgot, welcome to the forum, i did not saw it was your first post.

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer