# Addon: how to make Blender run check()/redraw when option changed?

Operators have a check() function that Blender calls when it wants to check if it should redraw. Exporters usually use this to attach a file extension to the file name (eg).

I know check() already runs after the user has edited the filename field, or after they click a file in the filepicker. I would like it to run after the user changes an option too. For example, the glTF exporter does this:

If the prop is drawn by the operator.draw() function this happens automatically. However it does not happen automatically if the option is drawn by a separate panel. How can I get it to update in that case?

Here is a complete example you can test with: https://pastebin.com/2k6mBNGz

(PS. I already know how the glTF exporter does it. I'm interested in a "proper" solution.)

• Could you please elaborate on how the glTF exporter does it? Jan 8 at 11:31
• @batFINGER The EnumProperty is given an update function that calls the operator bpy.ops.file.filenum (that's the plus/minus buttons in the file field that add numbers to the end of the filename) in a way designed to have no net change on the filename. Jan 8 at 17:54
• Oh Ok. Have answered similar in that using an update method, however simply adjusting the spacedata field for file name instead of using the operator. Jan 9 at 15:38

Set the filebrowser filename

The code for the ExportHelper mixin class is shown in this question Right way to stop export operator from saving with empty filename?

As demonstrated in question it appears only the FILE_PT_operator is live wired to update the parameters using check.

def update_ext(self, context):
# if we wish to set filename_ext
self.filename_ext = f".{self.extension.lower()}"
#the filebrowser parameters
params  = context.space_data.params
# printed to console
for k in dir(params):
print(k, getattr(params, k))
# set the file name
params.filename = f"{Path(self.filepath).stem}.{self.extension.lower()}"


And use this as an update on the operator enum

extension: bpy.props.EnumProperty(
name='Extension',
items=(('FOO', '.foo', '.foo'), ('BAR', '.bar', '.bar')),
default='FOO',
update = update_ext,
)


If also using filename_ext make it a property and give it a default to match the enum, however can pretty much do without. The check_existing if set will deal with alerting re pre-existing. (Assume it does haven't checked)

So can pretty much replace the check method to redraw the file browser properties.

• Thanks a lot, this is an improvement over the filenum operator :) One addition: context.space_data needs some checks to make sure it's the expected file browser, or else the operator won't work when eg. called from the Python console. Jan 9 at 20:27
• When I try to do this in my own addon, the console barks at me with this message: "AttributeError: 'EXPORT_OT_gml' object has no attribute 'filename_ext'" - why might this happen? Am I using my update_ext() in the wrong context? Jun 25 at 7:06

you can use getter/setter functions for these kind of updates or can check them in modal functions by checking left clicks.

an example of getter/setter functions is described in API like below:

import bpy

# Simple property reading/writing from ID properties.
# This is what the RNA would do internally.
def get_float(self):
# do some stuff here before get
return self.get("myfloat",0.0)

# self in this method is the object which you attach the property to
# in this case self is any scene in bpy.data for example bpy.data.scenes[0]
def set_float(self, value):
# do some stuff here before/after set because no return is required
self["myfloat"] = value

bpy.types.Scene.myfloat = bpy.props.FloatProperty(get=get_float, set=set_float)


now whenever you get/set a scene.myfloat data above methods work.

• Recommend you test this. Returning the "got" value from the getter will recurse. Use the ID prop to emulate what the rna does. blender.stackexchange.com/a/134310/15543 Jan 8 at 11:35
• Thanks @batFinger. You are true with this. I've updated my answer. Jan 8 at 13:32
• Sorry, I don't follow. Can you please phrase the answer as a diff on the pastebin in the question that will make it work? Jan 8 at 18:04