The most compact solution that I found uses the method WindowsManager.fileselect_add()
in invoke()
, and doesn't use the Helpers.
The documentation of fileselect_add
says:
Opens a file selector with an operator. The string properties ‘filepath’, ‘filename’, ‘directory’ and a ‘files’ collection are assigned when present in the operator
Actually, you need to specify only a directory
StringProperty in your operator. In so doing, the possibility to select the name of the file will disappear.
Also, to show only folders by default you can add a property filter_folder = bpy.props.BoolProperty(default=True, options={'HIDDEN'})
.
Since v2.80, declaring string/bool properties requires using the colon :
sign instead of equal =
.
Full example, tested on Blender 3.6.0:
import bpy
from bpy.props import StringProperty, BoolProperty
from bpy.types import Operator
class SelectDirExample(Operator):
"""Create render for all chracters"""
bl_idname = "example.select_dir"
bl_label = "Dir Selection Example Operator"
bl_options = {'REGISTER'}
# Define this to tell 'fileselect_add' that we want a directoy
directory: StringProperty(
name="Outdir Path",
description="Where I will save my stuff"
# subtype='DIR_PATH' is not needed to specify the selection mode.
# But this will be anyway a directory path.
)
# Filters folders
filter_folder: BoolProperty(
default=True,
options={"HIDDEN"}
)
def execute(self, context):
print("Selected dir: '" + self.directory + "'")
return {'FINISHED'}
def invoke(self, context, event):
# Open browser, take reference to 'self' read the path to selected
# file, put path in predetermined self fields.
# See: https://docs.blender.org/api/current/bpy.types.WindowManager.html#bpy.types.WindowManager.fileselect_add
context.window_manager.fileselect_add(self)
# Tells Blender to hang on for the slow user input
return {'RUNNING_MODAL'}
def register():
bpy.utils.register_class(SelectDirExample)
def unregister():
bpy.utils.unregister_class(SelectDirExample)
#
# Invoke register if started from editor
if __name__ == "__main__":
register()
# OPTIONAL - test run
bpy.ops.example.select_dir('INVOKE_DEFAULT')
Full example, tested on Blender 2.79:
import bpy
from bpy.props import StringProperty, BoolProperty
from bpy.types import Operator
class SelectDirExample(bpy.types.Operator):
"""Create render for all chracters"""
bl_idname = "example.select_dir"
bl_label = "Dir Selection Example Operator"
bl_options = {'REGISTER'}
# Define this to tell 'fileselect_add' that we want a directoy
directory = StringProperty(
name="Outdir Path",
description="Where I will save my stuff"
# subtype='DIR_PATH' is not needed to specify the selection mode.
# But this will be anyway a directory path.
)
# Filters folders
filter_folder = BoolProperty(
default=True,
options={"HIDDEN"}
)
def execute(self, context):
print("Selected dir: '" + self.directory + "'")
return {'FINISHED'}
def invoke(self, context, event):
# Open browser, take reference to 'self' read the path to selected
# file, put path in predetermined self fields.
# See: https://docs.blender.org/api/current/bpy.types.WindowManager.html#bpy.types.WindowManager.fileselect_add
context.window_manager.fileselect_add(self)
# Tells Blender to hang on for the slow user input
return {'RUNNING_MODAL'}
def register():
bpy.utils.register_class(SelectDirExample)
def unregister():
bpy.utils.unregister_class(SelectDirExample)
#
# Invoke register if started from editor
if __name__ == "__main__":
register()
# OPTIONAL - test run
bpy.ops.example.select_dir('INVOKE_DEFAULT')
You can test the manual file selection by hitting SPACE on a 3D view and searching for Dir Selection Example Operator
.
Differently, when executed from Python code you can specify the directory on your own: bpy.ops.demo.select_dir_example(directory='/tmp')