0
$\begingroup$

I have a Geometry Nodes setup, where I have an exposed parameter called Inflate amount:

enter image description here

I want to change this value via script.

I'm trying the following, but it doesn't work:

bpy.data.objects["Cube_WearOperator"].modifiers["GeometryNodes"]["Input_2"]

I get the following error message:

AttributeError: Writing to ID classes in this context is not allowed: Cube_WearOperator, Object datablock, error setting NodesModifier.Input_2

I tried to research the term 'context' with reference to Blender, and I have some idea of it, but not too much.

  1. Execute the script first, so that the tab called 'Wear' appears on the sidepanel.
  2. Uncomment line 118, then run again to reproduce the error.

Blender version 3.5.0

$\endgroup$
6
  • $\begingroup$ Hello and welcome. I tried it and it works fine. You have some other stuff in your blend file causing this problem. Can you make a simple setup that reproduces this problem and share the blend file blend-exchange.com $\endgroup$
    – Harry McKenzie
    Commented Jul 31, 2023 at 7:52
  • $\begingroup$ i downloaded the file but can't reproduce your problem. what version are you using? im on 3.6. better use the latest version 3.6 $\endgroup$
    – Harry McKenzie
    Commented Jul 31, 2023 at 8:39
  • $\begingroup$ I'm on 3.5.0. Will try to upgrade and test. Thanks. $\endgroup$
    – Nedudgi
    Commented Jul 31, 2023 at 8:48
  • $\begingroup$ @Nedudgi There is no script in the blend file. $\endgroup$
    – Karan
    Commented Jul 31, 2023 at 9:04
  • 1
    $\begingroup$ Please reduce the code to 10 lines. If you're just trying to change a read-only property for your context because it's drawing code, then it doesn't require a response. If you want to change the node tree property but change the modifier property, this also requires a separate explanation in question. $\endgroup$
    – mod nop
    Commented Aug 1, 2023 at 12:36

1 Answer 1

1
$\begingroup$

You can't edit/modify properties directly in draw() using bpy.data.objects["Cube_WearOperator"].modifiers["GeometryNodes"]["Input_2"] = 1

You have to set the default value in the operator like this:

modifierGeoNodes = obj.modifiers['GeometryNodes']
modifierGeoNodes.node_group = bpy.data.node_groups["inflate"]
modifierGeoNodes.node_group.inputs['Inflate amount'].default_value = 0.01
modifierGeoNodes.node_group.update_tag()
bl_info = {
    "name": "Wear",
    "blender": (2, 93, 0),
    "category": "Object",
}

import bpy

class AddEdgeWear(bpy.types.Operator):
    bl_idname = "rhl.addedgewear"
    bl_label = "Add Edge Wear"

    def execute(self, context):

        objOperatedOn = bpy.context.view_layer.objects.active
        baseName = objOperatedOn.name
        
        
        obj = bpy.context.scene.objects.get(baseName+"_WearOperator")
        if not obj:
            bpy.ops.object.duplicate()
            obj = bpy.context.active_object
        else:
            bpy.ops.object.select_all(action='DESELECT')
            bpy.context.view_layer.objects.active = obj
            obj.hide_set(False)
            obj.select_set(True)
            bpy.ops.object.delete()
            objOperatedOn.select_set(True)
            bpy.context.view_layer.objects.active = objOperatedOn
            bpy.ops.object.duplicate()
            obj = bpy.context.active_object

        bpy.ops.object.select_all(action='DESELECT')
        bpy.context.view_layer.objects.active = obj
        obj.select_set(True)
        obj.hide_set(True)

        obj.name = baseName+"_WearOperator"

        obj.modifiers.new("Remesh", type = "REMESH")
        obj.modifiers.new("GeometryNodes", type = "NODES")
        obj.modifiers.new("LaplacianSmooth", type = "LAPLACIANSMOOTH")
        obj.modifiers.new("Displace", type = "DISPLACE")
        
        modifierRemesh = obj.modifiers.get("Remesh")
        modifierGeoNodes = obj.modifiers['GeometryNodes']
        modifierGeoNodes.node_group = bpy.data.node_groups["inflate"]
        modifierGeoNodes.node_group.inputs['Inflate amount'].default_value = 0.01
        modifierGeoNodes.node_group.update_tag()
    
        modifierLaplacianSmooth = obj.modifiers["LaplacianSmooth"]
        modifierLaplacianSmooth.lambda_factor = 16
        
        modifierDisplace = obj.modifiers["Displace"]
        modifierDisplace.strength = .1
        displacementTexture = bpy.data.textures.get('EdgeWearDisplacementTexture')
        if not displacementTexture:
            displacementTexture = bpy.data.textures.new("EdgeWearDisplacementTexture", type='CLOUDS')
        modifierDisplace.texture = displacementTexture
        

        
        objOperatedOn.modifiers.new("WearBool", type = "BOOLEAN")
        modifierBoolean = objOperatedOn.modifiers['WearBool']
        modifierBoolean.operation = 'INTERSECT'
        modifierBoolean.solver = "FAST"
        modifierBoolean.object = obj
        
        
        print ("LOFASZ")
        #bpy.data.objects["EdgeWearOperator"].select_set(True)

        return {'FINISHED'}


class OBJECT_PT_wear(bpy.types.Panel):
    bl_label = "Wear"
    bl_idname = "OBJECT_PT_wear"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Wear'



    @classmethod
    def poll(cls, context):
        return context.object is not None and context.object.type == 'MESH'

    def draw(self, context):
        
        
        
        layout = self.layout
        layout.operator("rhl.addedgewear", text="Add Edge Wear")

        obj = context.object
        

        has_remesh_modifier = False
        for modifier in obj.modifiers:
            if modifier.type == 'REMESH':
                has_remesh_modifier = True
                break
        if (has_remesh_modifier):
            modifierRemesh = obj.modifiers.get("Remesh")
            layout.label(text="Carver resolution in world units")
            layout.prop(modifierRemesh, "voxel_size", text="Resolution")


        
        has_geometry_nodes_modifier = False
        for modifier in obj.modifiers:
            if modifier.type == 'NODES':
                has_geometry_nodes_modifier = True
                break
        if (has_geometry_nodes_modifier):
            modifierGeoNodes = obj.modifiers['GeometryNodes']
            layout.label(text="Edge width")
            layout.prop(modifierGeoNodes, '["Input_2"]', text="Edge width")
            #bpy.data.objects["wBox_WearOperator"].modifiers["GeometryNodes"]["Input_2"] = 1


        has_laplacian_modifier = False
        for modifier in obj.modifiers:
            if modifier.type == 'LAPLACIANSMOOTH':
                has_laplacian_modifier = True
                break
        if (has_laplacian_modifier):
            modifierLaplacianSmooth = obj.modifiers["LaplacianSmooth"]
            layout.label(text="Edge roundness")
            layout.prop(modifierLaplacianSmooth, "lambda_factor", text = "Roundness")

        has_displace_modifier = False
        for modifier in obj.modifiers:
            if modifier.type == 'DISPLACE':
                has_displace_modifier = True
                break
        if (has_displace_modifier):
            modifierDisplace = obj.modifiers["Displace"]
            noiseTexture = modifierDisplace.texture
            layout.label(text="Edge noise size")
            layout.prop(noiseTexture, "noise_scale", text = "Noise size")
            layout.label(text="Edge noise strength")
            layout.prop(modifierDisplace, "strength", text = "Noise strength")
            


    def adjust_edge_width(value):
        # Define the range of "edgeWidth" values
        min_edge_width = 0.1
        max_edge_width = 0.0

        # Ensure the input value is within the range [0, 1]
        value = max(0, min(1, value))

        # Calculate the new edgeWidth based on the input value
        edge_width = min_edge_width + (max_edge_width - min_edge_width) * value

        # Set the edgeWidth value to all selected objects (you can change this as needed)
        for obj in bpy.context.selected_objects:
            if "edgeWidth" in obj:
                obj["edgeWidth"] = edge_width
        return edge_width
      



def register():
    bpy.utils.register_class(OBJECT_PT_wear)
    bpy.utils.register_class(AddEdgeWear)
    
    bpy.types.Scene.edgeWidth = bpy.props.FloatProperty(
        name="Edge Width",
        default=0.0,
        min=0.0,
        max=1.0,
        description="Edge width"
    )


def unregister():
    bpy.utils.unregister_class(OBJECT_PT_wear)
    bpy.utils.unregister_class(AddEdgeWear)
    del bpy.types.Scene.my_custom_variable

if __name__ == "__main__":
    register()
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .