2
$\begingroup$

I am trying to write a code as part of a larger add on, and one component is to have a button that will open the file explorer and import .stl or .off files. My code is reading the data but I cannot get the imported mesh to show in my work space (as an object I can then modify). I want this function to be as if I went to file--import--.stl (where it shows up in my 3D work space). I am new to blender and python (double-whammy) so any help is appreciated!

EDIT: I have reuploaded the code. I know it is reading the file without spitting out any errors but I don't know what to change/add to get it to import as a mesh in my 3D work space.

EDIT 2: I have posted my most recent code and I still not getting any error messages in the terminal but the file I am trying to import is no where to be seen in the work space.

import bpy
from bpy_extras.io_utils import ImportHelper
from bpy.types import Operator
from bpy.props import StringProperty, BoolProperty, EnumProperty

import base64


def read_some_data(context, filepath):
    #print("running read_some_data...")
    f = open(filepath, 'rb')
    data = f.read()
    encoded = base64.b64encode(data)
    data = encoded
    f.close()



    return {'FINISHED'}

class stl_file_import(Operator,ImportHelper):
    bl_idname = "object2surf.invoke_import"
    bl_label = "Import Mesh"
    bl_description = "Import triangular surfaces in .json,.jmsh,.bmsh,.off,.medit,.stl,.smf,.gts"
   
   

    # ImportHelper mixin class uses this
    filename_ext = "*.json;*.jmsh;*.bmsh;*.off;*.medit;*.stl;*.smf;*.gts"

    filter_glob: StringProperty(
        default="*.json;*.jmsh;*.bmsh;*.off;*.medit;*.stl;*.smf;*.gts",
        options={'HIDDEN'},
        maxlen=2048,  # Max internal buffer length, longer would be clamped.
    )


    use_setting: BoolProperty(
        name="Example Boolean",
        description="Example Tooltip",
        default=True,
    )



    def execute(self, context):
        return read_some_data(context, self.filepath)
    def add_mesh_to_scene(scene, mesh):
        obj = bpy.ops.import_scene.obj(filepath=path, axis_forward='-Z', axis_up='Y', filter_glob="*.obj;*.stl")
        scene.objects.link(obj)
        return obj

###
def register():
    bpy.utils.register_class(stl_file_import)
    bpy.types.TOPBAR_MT_file_import.append(menu_func_import)


def unregister():
    bpy.utils.unregister_class(stl_file_import)
    bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)

$\endgroup$
5
  • $\begingroup$ Hello. It seems you have some unused code here, so it's a bit hard to understand what you're trying to do. Could you clean the script a little bit ? $\endgroup$
    – Gorgious
    Apr 17, 2023 at 16:54
  • $\begingroup$ Your code only reads the file, it doesn’t convert it from stl/off to blender data nor adds any new objects to the scene $\endgroup$ Apr 17, 2023 at 17:05
  • $\begingroup$ I have reuploaded the code and tried to clean it up the best I can. I can tell it is reading the file but I do not know how to get it to import as an object into my workspace. There are no errors being printed out either. $\endgroup$ Apr 17, 2023 at 17:16
  • $\begingroup$ try: bpy.ops.import_scene.obj(filepath=self.filepath, ...) to pass selected path from ImportHelper to SceneImporter $\endgroup$
    – relaxed
    Apr 18, 2023 at 15:33
  • $\begingroup$ @relaxed I have that line in the code but it isnt doing anything. I tried changing .obj to .stl or .off and blender crashed with no error message in the command terminal $\endgroup$ Apr 18, 2023 at 19:13

1 Answer 1

1
$\begingroup$

Well, also with last change I see filepath=path not filepath=self.filepath in your example. And the import operator was moved in a function that´s not called. I'm beginning to think there might be some general confusion about importing objects into Blender. No need to open or read a file (function 'read_some_data'). No need to link imported objects to Scene by yourself (scene.objects.link). Imported objects are linked to the active collection by default. It´s all done by the Import-Operators. Let's break down the stuff.

Direct import:

import bpy
bpy.ops.import_mesh.stl()

raises error FileNotFoundError: [Errno 2] No such file or directory: '' because invalid (empty) filepath was passed to operator.

import bpy
my_filepath = r"C:\Users\username\Documents\untitled.stl" # (Windows example: r(String) to format windows pathes)
bpy.ops.import_mesh.stl(filepath = my_filepath)

object was imported and linked to active collection as long as filepath is valid. This means there must be a file named 'untitled.stl' in the given directory. filepath needs to be the complete path from mount to file-extension.

Direct import with selection:

import bpy
bpy.ops.import_mesh.stl('INVOKE_DEFAULT')

If ImportOperator is called with execution context 'INVOKE_DEFAULT' behind the scene another operator opens for file + folder selection (user interaction). By clicking the execution button, user filepath (selection) is passed to the ImportOperator. Rest as before. Object is imported and linked to active collection.

Import with selection from Panel:

Here the operator call is some different because Panel is invoked by default and layout.operator needs the bl_idname of the ImportOperator.

import bpy

# UI                      
class TEST_PT_Panel(bpy.types.Panel):
    bl_idname = 'TEST_PT_Panel'
    bl_label = "Test Panel"                      
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "TEST"
    def draw(self, context):
        layout = self.layout
        layout.operator('import_mesh.stl',  text="import .stl")  # use operator.bl_idname (all behind 'bpy.ops.') without 'INVOKE_DEFAULT'
        layout.operator('import_scene.obj', text="import .obj")  # .obj importer example
        
# REGISTER
bpy.utils.register_class(TEST_PT_Panel)
$\endgroup$
1
  • $\begingroup$ Thank you for explaining! $\endgroup$ Apr 21, 2023 at 17:06

You must log in to answer this question.

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