1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
"""
Basic FileHandler for Operator that imports multiple files
----------------------------------------------------------
Also operators can be invoked with multiple files from 'drag-and-drop',
but for this it is require to define the following properties:
.. code-block:: python
directory: StringProperty(subtype='FILE_PATH')
files: CollectionProperty(type=bpy.types.OperatorFileListElement)
This ``directory`` and ``files`` properties now will be used by the
``FileHandler`` to set 'drag-and-drop' filepath data.
"""
import bpy
from bpy_extras.io_utils import ImportHelper
from mathutils import Vector
class ShaderScriptImport(bpy.types.Operator, ImportHelper):
"""Test importer that creates scripts nodes from .txt files"""
bl_idname = "shader.script_import"
bl_label = "Import a text file as a script node"
"""
This Operator can import multiple .txt files, we need following directory and files
properties that the file handler will use to set files path data
"""
directory: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE', 'HIDDEN'})
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement, options={'SKIP_SAVE', 'HIDDEN'})
"""Allow the user to select if the node's label is set or not"""
set_label: bpy.props.BoolProperty(name="Set Label", default=False)
@classmethod
def poll(cls, context):
return (
context.region and context.region.type == 'WINDOW' and
context.area and context.area.ui_type == 'ShaderNodeTree' and
context.object and context.object.type == 'MESH' and
context.material
)
def execute(self, context):
""" The directory property need to be set. """
if not self.directory:
return {'CANCELLED'}
x = 0.0
y = 0.0
for file in self.files:
"""
Calls to the operator can set unfiltered file names,
ensure the file extension is .txt
"""
if file.name.endswith(".txt"):
node_tree = context.material.node_tree
text_node = node_tree.nodes.new(type="ShaderNodeScript")
text_node.mode = 'EXTERNAL'
import os
filepath = os.path.join(self.directory, file.name)
text_node.filepath = filepath
text_node.location = Vector((x, y))
# Set the node's title to the file name
if self.set_label:
text_node.label = file.name
x += 20.0
y -= 20.0
return {'FINISHED'}
# Use ImportHelper's invoke_popup() to handle the invocation so that this operator's properties
# are shown in a popup. This allows the user to configure additional settings on the operator like
# the `set_label` property. Consider having a draw() method on the operator in order to layout the
# properties in the UI appropriately.
#
# If filepath information is not provided the file select window will be invoked instead.
def invoke(self, context, event):
return self.invoke_popup(context)
class SHADER_FH_script_import(bpy.types.FileHandler):
bl_idname = "SHADER_FH_script_import"
bl_label = "File handler for shader script node import"
bl_import_operator = "shader.script_import"
bl_file_extensions = ".txt"
@classmethod
def poll_drop(cls, context):
return (
context.region and context.region.type == 'WINDOW' and
context.area and context.area.ui_type == 'ShaderNodeTree'
)
bpy.utils.register_class(ShaderScriptImport)
bpy.utils.register_class(SHADER_FH_script_import)
|