Hey @ferdinand ,
Sorry, full code below !
layer.SetParameter(...) returns True for each call as the assignation works. The code did not raise any error or exception. But if I undo/redo, bitmap shaders disappears, Corona ones as well as the previous Cinema ones. It seems that only Layer Shader's layers remain, but with a missing/broken shader link ?
# CT_C4DBitmapToCoronaBitmap
import c4d
def iter_shaders(material: c4d.BaseMaterial, mask: int = None) -> list:
shaders = []
shader = material.GetFirstShader()
if shader == None:
return
while shader:
if mask:
if shader.GetType() == mask:
shaders.append(shader)
else:
shaders.append(shader)
if shader.GetDown():
shader = shader.GetDown()
elif shader.GetNext():
shader = shader.GetNext()
else:
while shader.GetUp():
if shader.GetUp().GetNext():
shader = shader.GetUp().GetNext()
break
shader = shader.GetUp()
else:
shader = None
return shaders
def get_layershader_layer(doc: c4d.documents.BaseDocument, layer_shader: c4d.BaseShader, target_shader: c4d.BaseShader = None) -> c4d.LayerShaderLayer:
# Iterating over Layer Shader layers, looking
# for the specified type of shaders
if layer_shader.GetType() == c4d.Xlayer:
layer = layer_shader.GetFirstLayer()
while layer != None:
if layer.GetType() == c4d.TypeShader:
shader = layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_LINK)
if target_shader and shader == target_shader:
return layer
layer = layer.GetNext()
elif layer.GetNext():
layer = layer.GetNext()
else:
layer = None
def convert_c4d_bitmap(doc: c4d.documents.BaseDocument, c4d_bitmap: c4d.BaseShader, remove=True):
cr_bitmap = create_cr_bitmap_shader(
c4d_bitmap[c4d.BITMAPSHADER_FILENAME], c4d_bitmap[c4d.BITMAPSHADER_COLORPROFILE], c4d_bitmap[c4d.ID_BASELIST_NAME], c4d_bitmap[c4d.BITMAPSHADER_EXPOSURE], c4d_bitmap)
cr_bitmap_added = True
if c4d_bitmap.GetUp():
parent = c4d_bitmap.GetUp()
cr_bitmap.InsertUnder(parent)
doc.AddUndo(c4d.UNDOTYPE_NEW, cr_bitmap)
if parent.CheckType(c4d.Xlayer):
layer = get_layershader_layer(doc, parent, c4d_bitmap)
cr_bitmap[c4d.ID_BASELIST_NAME] = layer.GetName(doc)
doc.AddUndo(c4d.UNDOTYPE_CHANGE_SMALL, parent)
layer.SetParameter(c4d.LAYER_S_PARAM_SHADER_LINK, cr_bitmap)
else:
parent_shader_slot = get_bc_id(
parent.GetDataInstance(), c4d_bitmap)
doc.AddUndo(c4d.UNDOTYPE_CHANGE, parent)
parent[parent_shader_slot] = cr_bitmap
elif c4d_bitmap.GetMain():
parent = c4d_bitmap.GetMain()
doc.AddUndo(c4d.UNDOTYPE_CHANGE, parent)
parent.InsertShader(cr_bitmap)
doc.AddUndo(c4d.UNDOTYPE_NEW, cr_bitmap)
parent_shader_slot = get_bc_id(parent.GetDataInstance(), c4d_bitmap)
parent[parent_shader_slot] = cr_bitmap
else:
cr_bitmap_added = False
# Removing the old bitmap
if remove and cr_bitmap_added:
doc.AddUndo(c4d.UNDOTYPE_DELETEOBJ, c4d_bitmap)
c4d_bitmap.Remove()
return cr_bitmap
def create_cr_bitmap_shader(filepath: str, colorspc: int, basename: str, exposure: float, shader):
cr_bitmap = c4d.BaseShader(1036473)
cr_bitmap_bc = cr_bitmap.GetDataInstance()
cr_bitmap_bc.SetFilename(c4d.CORONA_BITMAP_FILENAME, filepath)
cr_bitmap_bc.SetInt32(c4d.CORONA_BITMAP_COLORPROFILE, colorspc)
cr_bitmap_bc.SetString(c4d.ID_BASELIST_NAME, basename)
cr_bitmap_bc.SetFloat(c4d.CORONA_BITMAP_EXPOSURE,
exposure if colorspc in [1, 3] else exposure * 2.2)
return cr_bitmap
def get_bc_id(target_bc, target_value):
for index, value in target_bc:
if value == target_value:
return index
def main():
doc = c4d.documents.GetActiveDocument()
materials = doc.GetActiveMaterials()
doc.StartUndo()
# Main loop
for material in materials:
# Step over non Corona Physical materials or Corona Legacy materials.
if material.GetType() not in (1056306, 1032100):
continue
for bitmap_shader in iter_shaders(material, c4d.Xbitmap):
convert_c4d_bitmap(doc, bitmap_shader)
doc.EndUndo()
c4d.EventAdd()
if __name__ == '__main__':
main()