Hello @tankun,
Welcome to the Plugin Café forum and the Cinema 4D development community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our Forum and Support Guidelines, as they line out details about the Maxon SDK Group support procedures. Of special importance are:
About your First Question
You got it almost right, good job for your first question on the tricky subject of reflection layers! Your main fault was that you treated your variable reftex
as if it were a str
or maxon.Url
, although it is in reality a BaseShader
or None
. There were also some minor bits and bobs, but they are not so important. Find an example for how I would write such thing below.
Cheers,
Ferdinand
Result:
Before:

After:

Code:
"""Demonstrates how to move the color shader of the first reflection layer
which has such shader to the color channel of the material.
"""
import c4d
doc: c4d.documents.BaseDocument
def main():
"""Runs the example.
"""
# For every material in the document, ...
for material in doc.GetMaterials():
# but skip over everything that does not have reflectance channels, ...
if not material.CheckType(c4d.Mmaterial):
continue
# iterate over all reflection layers to find the first layer that has a color shader.
i: int = 0
layer: c4d.ReflectionLayer | None = material.GetReflectionLayerIndex(i)
while(layer):
# Get the ID of the reflection layer color shader and retrieve the shader.
pid: int = layer.GetDataID() + c4d.REFLECTION_LAYER_COLOR_TEXTURE
colorShader: c4d.BaseShader | None = material[pid]
# Increment our counter and get the next layer.
i += 1
layer = material.GetReflectionLayerIndex(i)
# When the last layer did not have color shader, continue the inner iteration.
if not colorShader:
continue
# One of the flaws of your code was that you were reallocating a shader and also
# were trying to treat your #reftex like a str/Url, although it was of type
# c4d.BaseShader or None. But we can also just reuse the existing shader, no reallocation
# required. When you want to explicitly reallocate the shader, you should also remove
# the old shader, i.e., call #colorShader.Remove() in this case.
# Toggle the channels and move the shader reference. Also wrap the whole operation into
# an undo step. If you want the whole material conversion to be one undo, you would
# have to move the #StartUndo and #EndUndo outside of the outmost loop.
doc.StartUndo()
doc.AddUndo(c4d.UNDO_CHANGE, material)
material[c4d.MATERIAL_USE_COLOR] = True
material[c4d.MATERIAL_USE_REFLECTION] = False
material[pid] = None # This is important, a shader can only be refed once.
material[c4d.MATERIAL_COLOR_SHADER] = colorShader
doc.EndUndo()
# Break the inner iteration since we have set/found a color shader.
break
# Push an update event to Cinema 4D so that our changes are reflected in the UI.
c4d.EventAdd()
if __name__=='__main__':
main()