Hello @Peek,
Thank you for reaching out to us. Please share your code, as things otherwise tend to become one giant guessing game for us. In general, I would recommend having a look at BaseShader: Access and Structure, as the hierarchy and branching structure of shaders is a bit dicey. I would also recommend having a look at this thread as it lines out some details about the layer shader.
Other than that, I am not quite sure what you want to do with LAYER_S_PARAM_SHADER
. It is just the stride for a group of parameters, namely these here:
/// @addtogroup LAYER_S_PARAM_SHADER
/// @ingroup group_containerid
/// @{
/// Parameters for @ref TypeShader layers.
#define LAYER_S_PARAM_SHADER_MODE 2000 ///< ::Int32 Blend mode: @enumerateEnum{BlendMode}
#define LAYER_S_PARAM_SHADER_BLEND 2001 ///< ::Float Blend parameter.
#define LAYER_S_PARAM_SHADER_LINK 2002 ///< @c void* Pointer to a BaseLink that contains the shader, read-only.
/// @}
Unless you want to ignore the whole c4d.LayerShaderLayer
interface, you will not have to deal with these strides, which divide the data container of the actual LayerShader
into bins. Without your code I can only guess what you are trying to do. Find an example below.
Cheers,
Ferdinand
Result:

shader = <c4d.LayerShader object called Layer/Layer with ID 1011123 at 2670729460672>
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_MODE) = 2
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND) = 1.0
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_LINK) = <c4d.LayerShader object ...
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_MODE) = 3
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND) = 0.75
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_LINK) = <c4d.BaseShader object ...
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_MODE) = 1
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND) = 0.5
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_LINK) = <c4d.BaseShader object ...
shader = <c4d.LayerShader object called Layer/Layer with ID 1011123 at 2670729454400>
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_MODE) = 2
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND) = 0.5
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_LINK) = <c4d.BaseShader object ...
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_MODE) = 1
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND) = 1.0
layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_LINK) = <c4d.BaseShader object ...
shader = <c4d.BaseShader object called Color/Color with ID 5832 at 2670659243072>
shader = <c4d.BaseShader object called Fusion/Fusion with ID 1011109 at 2670659205440>
shader = <c4d.BaseShader object called Noise/Noise with ID 1011116 at 2670659241152>
shader = <c4d.BaseShader object called Noise/Noise with ID 1011116 at 2670659215552>
shader = <c4d.BaseShader object called Gradient/Gradient with ID 1011100 at 2670729457088>
shader = <c4d.BaseShader object called Noise/Noise with ID 1011116 at 2670729455424>
Code:
"""Demonstrates how to reach layer shader information.
Run this script with at least one material in a scene, with a shader tree in its color channel.
See also:
https://plugincafe.maxon.net/topic/14059/
"""
import c4d
import typing
doc: c4d.documents.BaseDocument # The active document
def iter_shader(
shader: c4d.BaseShader, level: int = 0) -> typing.Iterator[tuple[c4d.BaseShader, int]]:
"""Yields all shader, level tuples in the shader tree #shader.
"""
if not isinstance(shader, c4d.BaseShader):
return
yield (shader, level)
# Because hierarchical relations between shaders are not standardized, we must traverse both
# their hierarchical relations and the shader branching relation.
for child in shader.GetChildren(): # hierarchy
for item in iter_shader(child, level + 1):
yield item
for item in iter_shader(shader.GetFirstShader(), level + 1): # branching
yield item
def main() -> None:
"""Runs the example.
"""
# Get the color channel sahder for the first material in the scene.
material: c4d.BaseMaterial | None = doc.GetFirstMaterial()
if not material:
raise RuntimeError("Please add at least one material to the document.")
colorShader: c4d.BaseShader | None = material[c4d.MATERIAL_COLOR_SHADER]
if not colorShader:
raise RuntimeError("Please add a color shader to the first material.")
# And traverse the whole tree.
for shader, level in iter_shader(colorShader):
print (f"{' ' * level}{shader = }")
# When it is a layer shader, inspect its layers.
if isinstance(shader, c4d.LayerShader):
layer: c4d.LayerShaderLayer | None = shader.GetFirstLayer()
if not layer:
continue
li: int = level + 1
while layer:
print (f"{' ' * li}{layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_MODE) = }")
print (f"{' ' * li}{layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND) = }")
print (f"{' ' * li}{layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_LINK) = }")
layer = layer.GetNext()
if __name__ == '__main__':
main()