• 0 Votes
    2 Posts
    213 Views
    ferdinandF
    Hello @writing-qi, Welcome to the Maxon developers forum and its 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 procedures. You did not do anything wrong, we point all new users to these rules. Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment. Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support. Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads. It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions. About your First Question Please familiarize yourself with our support guidelines, your first question is composed out of multiple explicit and implicit questions and also lacks executable code, which makes it rather hard to answer. GetDescription() returns parameters but all show "Access Failed" There is no such error in our API. I assume you mean an error like this instead: AttributeError: Parameter value not accessible (object unknown in Python). The Cinema 4D API is primarily a C++ API and therefore exist data types that simply have not been ported to Python. For example, many objects have the parameters ID_BASELIST_ICON_PRESET_BUTTONS and ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS (which are usually hidden) and when you try to access them, it will raise an error, because the respective data types simply have not been wrapped, so the Python API has no idea what to do with the data held by these parameters. In Redshift, which started out as a third party plugin and is still an optional feature of Cinema 4D, many data types have never been ported to Python which makes them simply inaccessible. But Redshift usually decomposes their data via channel decomposition. I.e., the parameter for a "Texture" (CUSTOMDATATYPE_RSFILE) itself is not exposed, but its sub channels such as the path, tiling, etc. are. This has been discussed quite a few times before on the forum, for example here. What is the correct API to enumerate all parameters in RS Shader Graph? Well, descriptions are the tool for that, but descriptions also contain things where you cannot get/set a parameter, either because the data type is not exposed to Python or simply because there is nothing to get and set. The next SDK release will also contain a function called mxutils.GetParameterTreeString which allows you to visualize the sensible parameters of a scene element. But neither it nor c4d.Description.__iter__ will automatically unfold sub-channels. E.g., when you come along a node which has a parameter of type DYTPE_VECTOR at ID_MY_VECTOR_PRAM, the description will yield you a parameter at ID_MY_VECTOR_PRAM but not its sub-channels (ID_MY_VECTOR_PRAM, VECTOR_X), (ID_MY_VECTOR_PRAM, VECTOR_Y), and (ID_MY_VECTOR_PRAM, VECTOR_Z). The same goes for Redshift datatypes, when you come across a parameter of type CUSTOMDATATYPE_RSFILE, e.g., for the 'Image > File' (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0) parameter of an RS Texture node. The description will list the parameter for REDSHIFT_SHADER_TEXTURESAMPLER_TEX0 for that node but not its nested parameters, such as [c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0,c4d.REDSHIFT_FILE_PATH], [..,c4d.REDSHIFT_FILE_LAYER], [...,c4d.REDSHIFT_FILE_COLORSPACE], etc. will not be listed. I am afraid there is no abstracted way to solve this in Python. You would need access to the datatype registries which you do not have in Python. And even in the public C++ API, I currently do not see a way to do this. You need access to our internal API to be able to query a data type for the sub-channels it does register. But you could of course just hardcode the cases, I have given a small example below for CUSTOMDATATYPE_RSFILE, it is not that much work for one data type. But Redshift did use a lot of custom data types in its old Xpresso system, so wrapping them all could be a bit of work (but should still be doable). Cheers, Ferdinand Output For this graph: [image: 1755687318630-72414249-863b-4c13-8acd-5247941e64b3-image.png] RS Xpresso Material: <c4d.BaseMaterial object called RS C4D Shader/RS Shader Graph with ID 1036224 at 1819322820416> Found Xpresso node: <c4d.modules.graphview.GvNode object called Shader Graph/XGroup with ID 1001102 at 1818547015360> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = Shader Graph Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.38, 0.384, 0.392) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Inputs First'(c4d.GV_GROUP_INPUTS_FIRST) = 0 Parameter 'Active'(c4d.GV_GROUP_ACTIVE) = 0 Found Xpresso node: <c4d.modules.graphview.GvNode object called Output/Output with ID 1001101 at 1819032444352> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = Output Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.286, 0.329, 0.463) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Material ID'(c4d.GV_REDSHIFT_OUTPUT_MATERIAL_ID) = 0 Found Xpresso node: <c4d.modules.graphview.GvNode object called RS Material/RS Shader with ID 1001101 at 1819032542400> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = RS Material Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.529, 0.345, 0.333) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Version'(c4d.GV_REDSHIFT_SHADER_META_VERSION) = 17 Parameter 'Shader Class'(c4d.GV_REDSHIFT_SHADER_META_CLASSNAME) = Material Parameter 'preset'(c4d.REDSHIFT_SHADER_MATERIAL_PRESET) = 65536 Parameter 'diffuse_color'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_COLOR) = Vector(0.5, 0.5, 0.5) Parameter 'diffuse_weight'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_WEIGHT) = 1.0 Parameter 'diffuse_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_ROUGHNESS) = 0.0 Parameter 'transl_color'(c4d.REDSHIFT_SHADER_MATERIAL_TRANSL_COLOR) = Vector(0.5, 0.5, 0.5) Parameter 'transl_weight'(c4d.REDSHIFT_SHADER_MATERIAL_TRANSL_WEIGHT) = 0.0 Parameter 'refl_color'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_COLOR) = Vector(1, 1, 1) Parameter 'refl_weight'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_WEIGHT) = 1.0 Parameter 'refl_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ROUGHNESS) = 0.0 Parameter 'refl_samples'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_SAMPLES) = 16 Parameter 'refl_brdf'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_BRDF) = 0 Parameter 'refl_aniso'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ANISO) = 0.0 Parameter 'refl_aniso_rotation'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ANISO_ROTATION) = 0.0 Parameter 'refl_fresnel_mode'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_FRESNEL_MODE) = 3 Parameter 'refl_reflectivity'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_REFLECTIVITY) = Vector(0.04, 0.04, 0.04) Parameter 'refl_edge_tint'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_EDGE_TINT) = Vector(0, 0, 0) Parameter 'refl_ior3'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_IOR3) = Vector(1.5, 1.5, 1.5) Parameter 'refl_k3'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_K3) = Vector(0, 0, 0) Parameter 'refl_metalness'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_METALNESS) = 0.0 Parameter 'refl_ior'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_IOR) = 1.5 Parameter 'sheen_color'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_COLOR) = Vector(1, 1, 1) Parameter 'sheen_weight'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_WEIGHT) = 0.0 Parameter 'sheen_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_ROUGHNESS) = 0.30000001192092896 Parameter 'sheen_samples'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_SAMPLES) = 64 Parameter 'refr_color'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_COLOR) = Vector(1, 1, 1) Parameter 'refr_weight'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_WEIGHT) = 0.0 Parameter 'refr_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ROUGHNESS) = 0.0 Parameter 'refr_samples'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_SAMPLES) = 8 Parameter 'refr_ior'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_IOR) = 1.5 Parameter 'refr_use_base_IOR'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_USE_BASE_IOR) = 1 Parameter 'refr_abbe'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ABBE) = 0.0 Parameter 'refr_thin_walled'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_THIN_WALLED) = 0 Parameter 'ss_unitsMode'(c4d.REDSHIFT_SHADER_MATERIAL_SS_UNITSMODE) = 0 Parameter 'refr_transmittance'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_TRANSMITTANCE) = Vector(1, 1, 1) Parameter 'refr_absorption_scale'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ABSORPTION_SCALE) = 0.009999999776482582 Parameter 'ss_extinction_coeff'(c4d.REDSHIFT_SHADER_MATERIAL_SS_EXTINCTION_COEFF) = Vector(0, 0, 0) Parameter 'ss_extinction_scale'(c4d.REDSHIFT_SHADER_MATERIAL_SS_EXTINCTION_SCALE) = 0.009999999776482582 Parameter 'ss_scatter_coeff'(c4d.REDSHIFT_SHADER_MATERIAL_SS_SCATTER_COEFF) = Vector(1, 1, 1) Parameter 'ss_amount'(c4d.REDSHIFT_SHADER_MATERIAL_SS_AMOUNT) = 0.0 Parameter 'ss_phase'(c4d.REDSHIFT_SHADER_MATERIAL_SS_PHASE) = 0.0 Parameter 'ss_samples'(c4d.REDSHIFT_SHADER_MATERIAL_SS_SAMPLES) = 16 Parameter 'ms_amount'(c4d.REDSHIFT_SHADER_MATERIAL_MS_AMOUNT) = 0.0 Parameter 'ms_radius_scale'(c4d.REDSHIFT_SHADER_MATERIAL_MS_RADIUS_SCALE) = 100.0 Parameter 'ms_mode'(c4d.REDSHIFT_SHADER_MATERIAL_MS_MODE) = 1 Parameter 'ms_samples'(c4d.REDSHIFT_SHADER_MATERIAL_MS_SAMPLES) = 64 Parameter 'ms_include_mode'(c4d.REDSHIFT_SHADER_MATERIAL_MS_INCLUDE_MODE) = 1 Parameter 'ms_color0'(c4d.REDSHIFT_SHADER_MATERIAL_MS_COLOR0) = Vector(1, 0.9, 0.7) Parameter 'ms_weight0'(c4d.REDSHIFT_SHADER_MATERIAL_MS_WEIGHT0) = 1.0 Parameter 'ms_radius0'(c4d.REDSHIFT_SHADER_MATERIAL_MS_RADIUS0) = 1.0 Parameter 'ms_color1'(c4d.REDSHIFT_SHADER_MATERIAL_MS_COLOR1) = Vector(1, 0.9, 0.7) Parameter 'ms_weight1'(c4d.REDSHIFT_SHADER_MATERIAL_MS_WEIGHT1) = 0.0 Parameter 'ms_radius1'(c4d.REDSHIFT_SHADER_MATERIAL_MS_RADIUS1) = 1.0 Parameter 'ms_color2'(c4d.REDSHIFT_SHADER_MATERIAL_MS_COLOR2) = Vector(1, 0.9, 0.7) Parameter 'ms_weight2'(c4d.REDSHIFT_SHADER_MATERIAL_MS_WEIGHT2) = 0.0 Parameter 'ms_radius2'(c4d.REDSHIFT_SHADER_MATERIAL_MS_RADIUS2) = 1.0 Parameter 'coat_color'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_COLOR) = Vector(1, 1, 1) Parameter 'coat_weight'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_WEIGHT) = 0.0 Parameter 'coat_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_ROUGHNESS) = 0.0 Parameter 'coat_samples'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_SAMPLES) = 16 Parameter 'coat_brdf'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_BRDF) = 0 Parameter 'coat_fresnel_mode'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_FRESNEL_MODE) = 3 Parameter 'coat_reflectivity'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_REFLECTIVITY) = Vector(0.027, 0.027, 0.027) Parameter 'coat_ior3'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_IOR3) = Vector(1.4, 1.4, 1.4) Parameter 'coat_ior'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_IOR) = 1.399999976158142 Parameter 'coat_transmittance'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_TRANSMITTANCE) = Vector(1, 1, 1) Parameter 'coat_thickness'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_THICKNESS) = 0.10000000149011612 Parameter 'coat_bump_input'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_BUMP_INPUT) = Vector(0, 0, 0) Parameter 'overall_color'(c4d.REDSHIFT_SHADER_MATERIAL_OVERALL_COLOR) = Vector(1, 1, 1) Parameter 'opacity_color'(c4d.REDSHIFT_SHADER_MATERIAL_OPACITY_COLOR) = Vector(1, 1, 1) Parameter 'emission_color'(c4d.REDSHIFT_SHADER_MATERIAL_EMISSION_COLOR) = Vector(0, 0, 0) Parameter 'emission_weight'(c4d.REDSHIFT_SHADER_MATERIAL_EMISSION_WEIGHT) = 0.0 Parameter 'bump_input'(c4d.REDSHIFT_SHADER_MATERIAL_BUMP_INPUT) = Vector(0, 0, 0) Parameter 'depth_override'(c4d.REDSHIFT_SHADER_MATERIAL_DEPTH_OVERRIDE) = 0 Parameter 'refl_depth'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_DEPTH) = 3 Parameter 'refl_enablecutoff'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ENABLECUTOFF) = 0 Parameter 'refl_cutoff'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_CUTOFF) = 0.009999999776482582 Parameter 'skip_inside_refl'(c4d.REDSHIFT_SHADER_MATERIAL_SKIP_INSIDE_REFL) = 1 Parameter 'refr_depth'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_DEPTH) = 5 Parameter 'refr_enablecutoff'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ENABLECUTOFF) = 0 Parameter 'refr_cutoff'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_CUTOFF) = 0.009999999776482582 Parameter 'combined_depth'(c4d.REDSHIFT_SHADER_MATERIAL_COMBINED_DEPTH) = 6 Parameter 'diffuse_direct'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_DIRECT) = 1.0 Parameter 'diffuse_indirect'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_INDIRECT) = 1.0 Parameter 'refl_direct'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_DIRECT) = 1.0 Parameter 'refl_indirect'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_INDIRECT) = 1.0 Parameter 'refl_isGlossiness'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ISGLOSSINESS) = 0 Parameter 'coat_direct'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_DIRECT) = 1.0 Parameter 'coat_indirect'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_INDIRECT) = 1.0 Parameter 'coat_isGlossiness'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_ISGLOSSINESS) = 0 Parameter 'sheen_direct'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_DIRECT) = 1.0 Parameter 'sheen_indirect'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_INDIRECT) = 1.0 Parameter 'sheen_isGlossiness'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_ISGLOSSINESS) = 0 Parameter 'refr_isGlossiness'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ISGLOSSINESS) = 0 Parameter 'decoupleIORFromRoughness'(c4d.REDSHIFT_SHADER_MATERIAL_DECOUPLEIORFROMROUGHNESS) = 0 Parameter 'shadow_opacity'(c4d.REDSHIFT_SHADER_MATERIAL_SHADOW_OPACITY) = 0.0 Parameter 'affects_alpha'(c4d.REDSHIFT_SHADER_MATERIAL_AFFECTS_ALPHA) = 1 Parameter 'block_volumes'(c4d.REDSHIFT_SHADER_MATERIAL_BLOCK_VOLUMES) = 1 Parameter 'energyCompMode'(c4d.REDSHIFT_SHADER_MATERIAL_ENERGYCOMPMODE) = 1 Parameter 'overallAffectsEmission'(c4d.REDSHIFT_SHADER_MATERIAL_OVERALLAFFECTSEMISSION) = 0 Parameter 'refl_endmode'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ENDMODE) = 1 Parameter 'anisotropy_orientation'(c4d.REDSHIFT_SHADER_MATERIAL_ANISOTROPY_ORIENTATION) = 2 Parameter 'anisotropy_uvChannel'(c4d.REDSHIFT_SHADER_MATERIAL_ANISOTROPY_UVCHANNEL) = Parameter 'anisotropy_tangentChannel'(c4d.REDSHIFT_SHADER_MATERIAL_ANISOTROPY_TANGENTCHANNEL) = Found Xpresso node: <c4d.modules.graphview.GvNode object called Baked Texture/RS Shader with ID 1001101 at 1819592565952> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = Baked Texture Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.663, 0.624, 0.424) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Version'(c4d.GV_REDSHIFT_SHADER_META_VERSION) = 17 Parameter 'Shader Class'(c4d.GV_REDSHIFT_SHADER_META_CLASSNAME) = TextureSampler Parameter 'tex0'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0) = Inaccessible in Python Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1000) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1010) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1011) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1001) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1006) = <c4d.BaseTime object at 0x000001A85FC0EDC0> Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1007) = <c4d.BaseTime object at 0x000001A85FC1F440> Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1009) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1003) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1004) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1005) = 30 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1008) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1002) = 0 Parameter 'tex0_layername'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_LAYERNAME) = Parameter 'tex0_colorSpace'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_COLORSPACE) = Parameter 'tex0_gamma'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_GAMMA) = 1.0 Parameter 'tspace_id'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TSPACE_ID) = Parameter 'mirrorU'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIRRORU) = 0 Parameter 'mirrorV'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIRRORV) = 0 Parameter 'wrapU'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_WRAPU) = 1 Parameter 'wrapV'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_WRAPV) = 1 Parameter 'scale'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_SCALE) = Vector(1, 1, 0) Parameter 'offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_OFFSET) = Vector(0, 0, 0) Parameter 'rotate'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ROTATE) = 0.0 Parameter 'color_multiplier'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_COLOR_MULTIPLIER) = Vector(1, 1, 1) Parameter 'color_offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_COLOR_OFFSET) = Vector(0, 0, 0) Parameter 'alpha_multiplier'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_MULTIPLIER) = 1.0 Parameter 'alpha_offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_OFFSET) = 0.0 Parameter 'alpha_is_luminance'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_IS_LUMINANCE) = 0 Parameter 'invalid_color'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_INVALID_COLOR) = Inaccessible in Python Parameter 'filter_enable_type'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_FILTER_ENABLE_TYPE) = 2 Parameter 'filter_bicubic'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_FILTER_BICUBIC) = 0 Parameter 'prefer_sharp'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_PREFER_SHARP) = 1 Parameter 'mip_bias'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIP_BIAS) = 0.0 Parameter 'tone_map_enable'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TONE_MAP_ENABLE) = 0 Parameter 'default_uv_if_invalid'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_DEFAULT_UV_IF_INVALID) = 1 Found Xpresso node: <c4d.modules.graphview.GvNode object called C4D Brick Shader/C4D Shader with ID 1001101 at 1819592570688> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = C4D Brick Shader Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.424, 0.392, 0.541) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Width'(c4d.GV_REDSHIFT_BAKER_TEXTURE_WIDTH) = 128 Parameter 'Height'(c4d.GV_REDSHIFT_BAKER_TEXTURE_HEIGHT) = 128 Parameter 'Depth'(c4d.GV_REDSHIFT_BAKER_TEXTURE_DEPTH) = 0 Parameter 'Shader'(c4d.GV_REDSHIFT_BAKER_SHADER) = <c4d.BaseShader object called Brick/Brick with ID 5804 at 1822672588480> Found Xpresso node: <c4d.modules.graphview.GvNode object called file_730884e9656be535~/RS Shader with ID 1001101 at 1819592599488> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = file_730884e9656be535~ Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.663, 0.624, 0.424) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Version'(c4d.GV_REDSHIFT_SHADER_META_VERSION) = 17 Parameter 'Shader Class'(c4d.GV_REDSHIFT_SHADER_META_CLASSNAME) = TextureSampler Parameter 'tex0'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0) = Inaccessible in Python Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1000) = asset:///file_730884e9656be535~.jpg?name=back-2.jpg&db=MaxonAssets.db (assets.maxon.net) Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1010) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1011) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1001) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1006) = <c4d.BaseTime object at 0x000001A797214AC0> Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1007) = <c4d.BaseTime object at 0x000001A79721BFC0> Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1009) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1003) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1004) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1005) = 30 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1008) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1002) = 0 Parameter 'tex0_layername'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_LAYERNAME) = Parameter 'tex0_colorSpace'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_COLORSPACE) = Parameter 'tex0_gamma'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_GAMMA) = 1.0 Parameter 'tspace_id'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TSPACE_ID) = Parameter 'mirrorU'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIRRORU) = 0 Parameter 'mirrorV'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIRRORV) = 0 Parameter 'wrapU'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_WRAPU) = 1 Parameter 'wrapV'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_WRAPV) = 1 Parameter 'scale'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_SCALE) = Vector(1, 1, 0) Parameter 'offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_OFFSET) = Vector(0, 0, 0) Parameter 'rotate'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ROTATE) = 0.0 Parameter 'color_multiplier'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_COLOR_MULTIPLIER) = Vector(1, 1, 1) Parameter 'color_offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_COLOR_OFFSET) = Vector(0, 0, 0) Parameter 'alpha_multiplier'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_MULTIPLIER) = 1.0 Parameter 'alpha_offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_OFFSET) = 0.0 Parameter 'alpha_is_luminance'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_IS_LUMINANCE) = 0 Parameter 'invalid_color'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_INVALID_COLOR) = Inaccessible in Python Parameter 'filter_enable_type'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_FILTER_ENABLE_TYPE) = 2 Parameter 'filter_bicubic'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_FILTER_BICUBIC) = 0 Parameter 'prefer_sharp'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_PREFER_SHARP) = 1 Parameter 'mip_bias'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIP_BIAS) = 0.0 Parameter 'tone_map_enable'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TONE_MAP_ENABLE) = 0 Parameter 'default_uv_if_invalid'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_DEFAULT_UV_IF_INVALID) = 1 Code """Prints the parameter values of all Xpresso nodes attached to the materials of a document. Adds custom handling for the Redshift data type `CUSTOMDATATYPE_RSFILE` to unfold its sub-channels. Note: This script requires Cinema 4D 2025.0.0 or higher to run because it uses mxutils.RecurseGraph to find all Xpresso nodes in a material. The general approach of this script can however be applied to much older versions of Cinema 4D (up to R21 guaranteed, maybe even older versions). """ import c4d import mxutils doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. # A bunch of data types to step over in descriptions because we do not care about them. NO_VALUE_TYPES: list[int] = [ c4d.DTYPE_BUTTON, c4d.DTYPE_CHILDREN, c4d.DTYPE_CHILDS, c4d.DTYPE_DYNAMIC, c4d.DTYPE_GROUP, c4d.DTYPE_MULTIPLEDATA, c4d.DTYPE_NONE, c4d.DTYPE_SEPARATOR, c4d.DTYPE_SUBCONTAINER, c4d.DTYPE_POPUP ] def main() -> None: """Called by Cinema 4D when the script is being executed. """ # Iterate over all materials in the document, stepping over everything that is not an # RS Xpresso material. for material in doc.GetMaterials(): if not material.CheckType(c4d.Mrsgraph): continue # Iterate over all Xpresso nodes owned by this material. #RecurseGraph is a 2025.0.0+ feature. # You can achieve the same effect with the Redshift API in earlier versions of Cinema 4D. But # since you did not share your code, I took this shortcut instead of writing some lengthy code # to find all RS Xpresso nodes for this material. print(f"RS Xpresso Material: {material}") for node in mxutils.RecurseGraph(material, yieldBranches=True, nodeFilter=[c4d.GVbase]): print(f"\tFound Xpresso node: {node}") # Iterate over the description of the node, stepping over all irrelevant data types. description: c4d.Description = node.GetDescription(c4d.DESCFLAGS_DESC_0) data: c4d.BaseContainer pid: c4d.DescID for data, pid, _ in description: if pid[0].dtype in NO_VALUE_TYPES: continue # Now we try to access the data at #pid. This can fail because the data type of #pid # might not be accessible in Python. value: any | None = None try: value = node[pid] except: value = "Inaccessible in Python" print(f"\t\tParameter '{data[c4d.DESC_NAME]}'(c4d.{data[c4d.DESC_IDENT]}) = {value}") # Hardcode one of the data types (CUSTOMDATATYPE_RSFILE) and unfold its sub-channels. if pid[0].dtype == c4d.CUSTOMDATATYPE_RSFILE and len(pid) == 1: for subChannel in (c4d.REDSHIFT_FILE_PATH, c4d.REDSHIFT_FILE_LAYER, c4d.REDSHIFT_FILE_COLORSPACE, c4d.REDSHIFT_FILE_ANIMATION_MODE, c4d.REDSHIFT_FILE_ANIMATION_RANGE_START, c4d.REDSHIFT_FILE_ANIMATION_RANGE_END, c4d.REDSHIFT_FILE_ANIMATION_LOOP_COUNT, c4d.REDSHIFT_FILE_ANIMATION_FRAME_START, c4d.REDSHIFT_FILE_ANIMATION_FRAME_END, c4d.REDSHIFT_FILE_ANIMATION_FRAME_RATE, c4d.REDSHIFT_FILE_ANIMATION_FRAME_OFFSET, c4d.REDSHIFT_FILE_ANIMATION_TIMING_MODE): try: value = node[pid[0].id, subChannel] except: # This, that the sub-chanel is inaccessible too, can also happen, as the # sub-channel could be as much an unwrapped data type as its parent # parameter. Technically, a DescID can be composed out of three # DescLevel, i.e., you could have a parameter X with N sub-channels # where each of the sub-channels could also have N sub-channels, e.g., # (ID_FOO, ID_SUB_1, ID_SUB_1_1). None of these sub-channels has to use # a data type that is wrapped in Python. But something like this is # rather rare. Parameters where the first desc level is not some kind of # container (e.g., DTYPE_SUBCONTAINER), usually only decomposes into # atomic data types that can also be read from Python. But there is no # hard guarantee that this is the case. value = "Sub-channel is inaccessible in Python" print(f"\t\t\tSub-channel parameter ({data[c4d.DESC_IDENT]}, " f"{subChannel}) = {value}") if __name__ == '__main__': main()
  • How to Modify Button Parameters?

    Cinema 4D SDK python
    2
    1
    0 Votes
    2 Posts
    176 Views
    ferdinandF
    Hey @Ross, Thank you for reaching out to us. You are right, we cannot support third party APIs, but questions about our API do not automatically become moot or out of scope of support, just because they happen in the context of a plugin. We will of course still answer such questions. We will just never write code for a third-party API or test user code that requires a plugin. Your question '[I] need help modifying the "Import Type" button parameters of an ImageTexture node' is however ambiguous. A parameter is Cinema 4D slang for an element in a description, one of the ways of how Cinema 4D defines UIs. This includes things that users would naturally call a parameter such as a textbox holding a string, a number edit holding a float, or a combo box holding a selection, i.e., things that hold a value. But it also includes things that are just part of the UI of a node that cannot hold a value, e.g., a group, a separator, or a button. When someone talks about 'modifying' a parameter I would usually assume that they talk about changing the description of a node, specifically at that parameter. E.g., changing the label of a button, adding or removing elements to/from a drop down, disabling an element, etc. You can only do this for nodes you own, i.e., implement yourself. You cannot change the UI of alien elements, because for you their description is read only. But I assume you are actually talking here about getting or setting the parameter of an element, e.g., set a float slider to the value '4.13'. What gets a bit in the way here in your case, is that Cinema 4D summarizes everything under the label of paramater, even things that do not naturally have a value which could be gotten or set. So, I assume you want to press this button, for that you have two options: Call c4d.CallButton Send the message c4d.MSG_DESCRIPTION_COMMAND Please note that both approaches are restricted to being called from the main thread only when the scene element upon which they are called is part of a loaded scene. E.g., calling one of them on a node in the active document from outside of the main thread: forbidden. Calling them from inside a GetVirtualObjects (or any other off-main thread context) on a scene element in a dummy document which has been constructed just for this purpose and is not loaded by Cinema 4D: absolutely fine. Cheers, Ferdinand
  • 0 Votes
    3 Posts
    277 Views
    A
    okay the docs you gave were great for insight working code to change parameter of roughness for x given mat selections import c4d import maxon from maxon import GraphDescription doc = c4d.documents.GetActiveDocument() # Get selected materials directly selected_materials = doc.GetActiveMaterials() # Modify roughness for each selected material for material in selected_materials: graph = GraphDescription.GetGraph(material, nodeSpaceId=maxon.NodeSpaceIdentifiers.RedshiftMaterial) GraphDescription.ApplyDescription(graph, { "$query": { "$type": "Standard Material" }, "Reflection/Roughness": 1 }) c4d.EventAdd()
  • How to get explicit import node space?

    Cinema 4D SDK windows python 2025
    3
    1
    0 Votes
    3 Posts
    196 Views
    DunhouD
    Thanks @ferdinand for your great solution! Cheers~ DunHou
  • 0 Votes
    5 Posts
    311 Views
    DunhouD
    Hey @ferdinand , thanks for details. Cheers~ DunHou About forum, I can get notification about my own topic, And I clear all the cache, but nothing changed. After I tried to reset my account settings manually, then it worked as expected.
  • Knowing if a font exists

    Cinema 4D SDK windows python 2025
    4
    0 Votes
    4 Posts
    255 Views
    D
    for my use case i will probably have a fallback solution with web-save or system fonts like this: import platform system_name = platform.system() if system_name == "Windows": font_name = "Consolas" elif system_name == "Darwin": font_name = "Menlo" elif system_name == "Linux": font_name = "DejaVu Sans Mono"
  • Bundle fonts with Cinema 4D submissions

    Cinema 4D SDK python 2025 2024
    7
    0 Votes
    7 Posts
    524 Views
    K
    Hey @ferdinand , Sorry for the late replies. You can only answer these with end user support and the beta community. I will do that. Although I haven't used the beta community yet, I'll post the same question there to better understand what the recommended workflows are right now. you would either have to limit the feature to 2024+ clients That's good enough for us. Our plugin officially supports only the latest versions of 2024 and 2025.
  • How to Encrypt Python Plugins without a License?

    Cinema 4D SDK python 2025
    2
    0 Votes
    2 Posts
    226 Views
    ferdinandF
    Hey @kbar, thank you for reaching out to us. Please remember creating new topics instead of posting in older one's, so that our forum remains a searchable database. I have forked your question. I understand the necessity and use case for this, but in the proposed form, this is not possible. At least not without more work than it makes sense to invest here. Because the license validation is one of the first steps in the boot sequence of Cinema 4D, and trying to evaluate a command line argument and use all the components of our API necessary to encrypt a file could easily lead to problems (as these modules might not have been loaded yet). What we could think about is offering this as a standalone tool. The issue is here that we cannot just ship the source for that tool (for third parties to compile it themself) as the source would then also be known to bad actors. And shipping it as a binary would be extra work. An alternative could be a REST service, but that is also extra work (but less than the former route). I currently have no time for either of this. At the end of the year I will probably do some website work, then we could think about the REST route. But it is likely that I then also do not have time for this. As an MRD, you also have the option to ask in our beta forums or make a source code sharing request. In the end, this is very simple code and could probably easily emulated with a couple of lines of Python code. That is probably the most sensible route, but we would have to involve PMs etc. here, if we are willing to do that. I myself am even not sure if I would greenlight such request due to the sensitive nature of the topic. So, unfortunately, there is no clear cut route here, although I definitely can see the use case. Cheers, Ferdinand
  • 0 Votes
    2 Posts
    302 Views
    ferdinandF
    Hey @Amazing_iKe, Thank you for reaching out to us. That RenderDocument does not support animations is only partially true. Effectively it does not for users, but that is more a regression than the lack of an actual feature. When you look into its documentation, you will see that many symbols and arguments are animation related. And when you send it a document which holds an animation, you are paying the price for rendering the full animation. The regressed state is however that you effectively only have access to the bitmap of the last frame of that animation. There is also the issue that the OCIO workflow with RenderDocument is a bit clunky at the moment. We have these issues in our backlog by I unfortunately cannot make any guarantees as to when we will fix them. You have two options: Render the document frame by frame yourself with RenderDocument and then assemble the animation yourself. Use the BatchRender, i.e., what is shown to the user as the render queue. You can use this in a fully programmatic manner, but you are restricted to rendering documents that have been saved to disk, and the output will also be put to disk. I.e., you do not have the 'memory only'-aspect of RenderDocument. There are many topics about this subject on this forum, for example here where I showed how you abstract some of the disc-only limitations aways. Maxime also recently added some features to the batch render like switching cameras and takes, which makes it less likely that you have to modify the file. I cannot write examples for all possible routes here. You have to decide yourself which route you want to go, and when you are then stuck there, I will help you. What to pick depends on your goals. When you expect the renderings to be quick, doing it manually with RenderDocument could be a solution. For more complex animations, the batch renderer is probably the better route. Cheers, Ferdinand
  • 0 Votes
    3 Posts
    199 Views
    J
    Thank you so much
  • 0 Votes
    3 Posts
    170 Views
    J
    Thank you so much
  • Create Xpresso Node with input port Object

    Cinema 4D SDK python
    7
    2
    0 Votes
    7 Posts
    289 Views
    J
    Ok thanks and sorry
  • 0 Votes
    3 Posts
    340 Views
    ferdinandF
    Hey @Amazing_iKe, Thank you for reaching out to us. You do the same thing you did incorrectly in your other thread. You create an async dialog and you do not keep it alive. We would prefer it to keep things G-rated here. I.e., no nudity, no violence, and no weapons. I removed the image in your posting. With that being said, and when I try out your script (with the dlg thing fixed). I end up with this: [image: 1752854682502-fc83d223-abc0-4568-98fc-deb82596b059-image.png] I.e., it just works. But you docked your dialog (and so did I imitating what you did). I now cannot reproduce this anymore, but when I did something in my layout, I think I dragged a palette, I got a similar result as yours. That is not too surprising though as you implement here an async dialog in a hacky manner. You have no CommandData.RestoreLayout which would handle layout events for your dialog. Something getting out of whack with scroll areas is not out of question for such irregular cases. Please follow the patterns shown in our GUI examples I would recommend to follow py-cmd_gui_simple_2024, it also contains code for handling layout events. I.e., this: def RestoreLayout(self, secret: any) -> bool: """Restores the dialog on layout changes. Implementing this is absolutely necessary, as otherwise the dialog will not be restored when the user changes the layout of Cinema 4D. """ return self.Dialog.Restore(self.ID_PLUGIN, secret) And to be clear, it is absolutely fine to share plugins with us here. It does not have to be a script manager script. Things should just not get too long. Feel free to anonymize your plugin IDs when you feel skittish about sharing them in public. Cheers, Ferdinand edit: Okay, there it is again. Not exactly the same as yours but close. But I would still have to ask you to provide an example where this happens inside a valid async dialog implementation (with a command or a similar owner). It is not out of question that there is a bug but we still need a non-hacky example. [image: 1752856082257-df89038f-124d-434f-8cde-3442bd9aebba-image.png]
  • 0 Votes
    3 Posts
    292 Views
    ferdinandF
    And just to be clear, using a modal dialog, e.g., DLG_TYPE_MODAL, is absolutely fine in a script manager script. Because then the GeDialog.Open call will only return when the dialog is closed (and you therefore do not have to keep the dialog alive). The hack I showed above is only needed when you need one of the async dialog types in a script manager script for testing purposes.
  • 0 Votes
    3 Posts
    330 Views
    Amazing_iKeA
    @ferdinand Thank you very much for your response and suggestions. I’ll make sure to follow best practices and provide a minimal, testable code sample when posting questions in the future. I’ll also give embedding a group a try. Thanks again for your support!
  • Unable to Sign In to Old Forum to Generate Plugin ID

    Cinema 4D SDK python
    3
    0 Votes
    3 Posts
    263 Views
    d_keithD
    Thanks Ferdinand - Up and running again!
  • 0 Votes
    13 Posts
    879 Views
    ferdinandF
    Hey, your second code snippet never sets self._result. Regarding loading vs. cloning documents: That I did it how I did it was no accident, but that does not necessarily mean that cloning things is bad. C4DAtom::GetClone is implemented in the different scene elements independently; i.e., BaseObject::GetClone, BaseDocument::GetClone, BaseTag::GetClone, etc. and C4DAtom::GetClone is just the empty implementation. The different implementations then rely on C4DAtom::CopyTo to copy data from the reference into a new instance of that scene element type. On top of that comes that Cinema 4D is largely Copy-on-Write these days, with data actually only being copied when you try to modify it. This all explains why BaseDocument::GetClone is so inexplicably performant, it just copies the metadata and only copies the real payload of the scene when it has to. On top of that comes that cloning from the same document from multiple threads in parallel could entail read-access violations (although somewhat unlikely). On the other hand, our rendering pipeline does exactly the same, it clones documents for rendering (the cloning is however done on the main thread). I personally would say what you are doing is probably okay, but I would not write such code as example code. I would have to spend more time on this to figure out if this is absolutely safe. Doing the actual cloning off-main-thread seems risky though (but is probably also fine in 99,9% of the cases). Cheers, Ferdinand
  • 0 Votes
    3 Posts
    279 Views
    ferdinandF
    Hey @lionlion44, Thank you for reaching out to us. We cannot provide support on third party libraries (Octane). But, yes, in general you are on the right track. We have this C++ example, which I loosely translated to Python. The thing to do which you are missing, is to check if such VP already exists, as you otherwise can land in a world of hurt. For everything else, you would have to talk with the Octane devs (of which some are here on this forum), if there are any special further steps to be taken for Octane. Cheers, Ferdinand """Provides an example for generically setting a render engine in Cinema 4D. Note that there is no guarantee that every render engine has a video post node, and when it has one, that it uses the same ID as the render engine. But it is highly conventional to implement a render engine like this. Derived from the C++ Example "Set Render Engine to Redshift": https://developers.maxon.net/docs/cpp/2023_2/page_manual_redshift_rendrer.html """ import c4d import mxutils doc: c4d.documents.BaseDocument # The active Cinema 4D document. def SetRenderEngine(doc: c4d.documents.BaseDocument, newEngineId: int, createsVideoPostNode: bool) -> bool: """Sets the render engine of the given document to the specified ID. """ # Make sure we are on the main thread, as we plan to modify the document and ensure that our # inputs are what we think they are. if not c4d.threading.GeIsMainThread(): raise RuntimeError("SetRenderEngine must be called from the main thread.") mxutils.CheckType(doc, c4d.documents.BaseDocument) mxutils.CheckType(newEngineId, int) mxutils.CheckType(createsVideoPostNode, bool) # Get the currently active render engine ID and get out if it matches the new one. renderData: c4d.documents.RenderData = doc.GetActiveRenderData() currentEngineId: int = renderData[c4d.RDATA_RENDERENGINE] if currentEngineId == newEngineId: print(f"Render engine {newEngineId} is already set, no changes made.") return True # Try to find a video post with the render engine ID. There is no absolute guarantee that every # render engine either has a video post node or that is gives it the same ID as the render # engine (but it is strongly conventional). if createsVideoPostNode: # Try to find an already existing video post node with the render engine ID. node: c4d.documents.BaseVideoPost | None = renderData.GetFirstVideoPost() while node: if node.GetType() == newEngineId: break node = node.GetNext() # There is no video post for the render engine, so we try to a new create one. if not node: try: node: c4d.documents.BaseVideoPost = c4d.documents.BaseVideoPost(newEngineId) renderData.InsertVideoPost(node) except Exception as e: raise RuntimeError(f"Failed to create video post node for render engine {newEngineId} ({e}).") # Finally, we set the render engine ID in the render data. renderData[c4d.RDATA_RENDERENGINE] = newEngineId return True def main() -> None: """Called by Cinema 4D to run the script. """ # Setting the standard render engine, here we do not have to create a video post node, since # the standard renderer is one of the rare cases that does not have a dedicated video post. SetRenderEngine(doc, newEngineId=c4d.RDATA_RENDERENGINE_STANDARD, createsVideoPostNode=False) # Set Redshift as the render engine, which does have a video post node. SetRenderEngine(doc, newEngineId=c4d.VPrsrenderer, createsVideoPostNode=True) # Push an update event. c4d.EventAdd() if __name__ == "__main__": main()
  • Joining Polygon Objects (MCOMMAND_JOIN)

    Moved Cinema 4D SDK python
    2
    0 Votes
    2 Posts
    273 Views
    ferdinandF
    Hello @Kantronin, Thank you for reaching out to us. Your script does not work because it does not follow the conditions of MCOMMAND_JOIN. Joins the objects that are parented to the passed null object. Passing multiple objects into SMC will not join them. edit: Moved this into the correct forum and added a small example. Cheers, Ferdinand Here is how I would write that in modern Cinema 4D. I have seen that your screenshot is from an older version such as S26, or even older, but I cannot write code examples for such old versions. There are multiple things that wont work in such old version such as type hinting and the mxutils lib, but you will be able to copy the general approach - move everything under a null while preserving the transforms. Code """Demonstrates how to join all objects in a document. """ import c4d import mxutils doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: """Called by Cinema 4D when the script is being executed. """ # There is no super good way to do this in the manner you implied, joining everything in a # document. I clone here the whole document, which is not the cheapest operation (but also # not as expensive as it may sound like). When we do not have to join everything, it is better # just to clone the things you want to join. En even better way could be to not clone anything # and instead use undos to revert the transform and hierarchy changes we have to make. temp: c4d.documents.BaseDocument = doc.GetClone(c4d.COPYFLAGS_NONE) firstObject: c4d.BaseObject | None = temp.GetFirstObject() if firstObject is None: c4d.gui.MessageDialog("No object selected.") return # Get all objects in the document, and move them under a null object. We must record and # restore their global matrices, when we deconstruct the scene and move it all under one null # object. allObjects: list[c4d.BaseObject] = list(mxutils.IterateTree(firstObject, True)) null: c4d.BaseObject = mxutils.CheckType(c4d.BaseObject(c4d.Onull)) for obj in allObjects: mg: c4d.Matrix = obj.GetMg() # save the transform of the object obj.Remove() # Technically not necessary in the Python API, as it will do it for you when # you call things like InsertUnderLast. But C++ will not do that and a node # cannot be inserted more than once in a document, otherwise the fireworks # will start. obj.InsertUnderLast(null) obj.SetMg(mg) # restore the transform of the object under the null # Insert the null object into the temporary document and then join all objects under it. temp.InsertObject(null) result: list[c4d.BaseObject] = c4d.utils.SendModelingCommand( command=c4d.MCOMMAND_JOIN, list=[null], doc=temp, mode=c4d.MODELINGCOMMANDMODE_ALL, ) if not result: c4d.gui.MessageDialog("Failed to join objects.") return # Now insert the joined object into the original document. joinedObject: c4d.BaseObject = result[0] joinedObject.SetName("Joined Object") joinedObject.Remove() doc.InsertObject(joinedObject) c4d.EventAdd() if __name__ == '__main__': main()
  • How to create a Track on a Vector Userdata?

    Cinema 4D SDK python
    3
    0 Votes
    3 Posts
    305 Views
    P
    Works! Thank you!