3
$\begingroup$

I am attempting to modify sculpt brush settings via a custom menu. To do this I'm setting a string property to specify the setting I wish to modify.

Since these settings are dependent on the active brush, I need to pull in the current brush via:

bpy.context.tool_settings.sculpt.brush

It seems this should work. I can confirm that it's accessing the correct brush. However, when I assign the brush context to a variable, and then call that variable within the data path it complains:

Traceback (most recent call last): File "/stringProp-tool.py", line 16, in execute TypeError: bpy_prop_collection[key]: invalid key, must be a string or an int, not Brush

Here is my script:

import bpy

class BrushSettings(bpy.types.Operator):
    """Toggle Setting For Active Brush"""
    bl_idname = "sculpt.brush_setting"
    bl_label = "Toggle Brush Setting"

    setting = bpy.props.StringProperty()

    def execute(self, context):

        setting = self.setting
        brush = bpy.context.tool_settings.sculpt.brush

        if setting == 'use_accumulate':
            value = bpy.data.brushes[brush].use_accumulate
            print(value)
            bpy.data.brushes[brush].use_accumulate = not value
        return {"FINISHED"}


class BrushSettingsMenu(bpy.types.Menu):
    bl_label = "Brush Settings"
    bl_idname = "sculpt.brush_settings_menu"

    def draw(self, context):
        layout = self.layout

        accumulate = layout.operator("sculpt.brush_setting", "Accumulate")
        accumulate.setting = 'use_accumulate'

def register():
    bpy.utils.register_class(BrushSettings)
    bpy.utils.register_class(BrushSettingsMenu)

def unregister():
    bpy.utils.unregister_class(BrushSettings)
    bpy.utils.unregister_class(BrushSettingsMenu)


if __name__ == "__main__":
    register()

    bpy.ops.wm.call_menu(name=BrushSettingsMenu.bl_idname)

The lines giving me grief are these:

value = bpy.data.brushes[brush].use_accumulate
bpy.data.brushes[brush].use_accumulate = not value
$\endgroup$
6
$\begingroup$

The value you get with brush = bpy.context.tool_settings.sculpt.brush is a Brush object:

>>> type(bpy.context.tool_settings.sculpt.brush)
<class 'bpy.types.Brush'>

When you access bpy.data.brushes[brush] it expects a name string (i.e. brush.name). Instead you can simply use the brush itself:

def execute(self, context):

    setting = self.setting
    brush = bpy.context.tool_settings.sculpt.brush
    print(brush)

    if setting == 'use_accumulate':
        value = brush.use_accumulate
        print(value)
        brush.use_accumulate = not value
    return {"FINISHED"}

One more suggestion:

Use the supplied context of the operator, this is better than using bpy.context:

brush = context.tool_settings.sculpt.brush
$\endgroup$
2
$\begingroup$

Accessing data via collection look-up they expects a string or an int: That is why you got the error.

bpy_prop_collection[key]: invalid key, must be a string or an int, not Brush

Running the following in the console window we can see that setting variable gets assigned a bpy.type.brush

>>> type(bpy.context.tool_settings.sculpt.brush)
<class 'bpy.types.Brush'>

Its a simple fix, you need to use the name of the brush.

value = bpy.data.brushes[brush.name].use_accumulate

However, obviously in this case you better just use.

value = brush.use_accumulate
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.