1
$\begingroup$

I've created an importer for an obscure texture format and I can invoke it as an operator successfully. Because I'm chaining two addons together, (a model importer that also automatically imports textures), I really want to get the resultant image object from the texture import operator so that I can properly . However, because operators can only return success or failure codes (eg. {'FINISHED'}), I can only really guess as to what the resultant image name might be.

The texture importer execute function looks like this:

def execute(self, context):
    dtx = DTX(self.filepath)
    image_name = os.path.splitext(os.path.basename(self.filepath))[0]
    image = bpy.data.images.new(image_name, dtx.width, dtx.height, alpha=True)
    image.pixels[:] = dtx.pixels[:]
    # I want to "return" the image to the caller, indirectly, somehow.
    return {'FINISHED'}

The model import script calls the texture importer like so:

bpy.ops.io_lithtech.import_dtx(filepath=texture)

Is there a way to indirectly return anything from the execution of an operator?

$\endgroup$

2 Answers 2

2
$\begingroup$

Normally you should implement the Operation as a wrapper on existing code. This way you can call an internal method what can return more information. This is also faster as operations creates undo files.

def load_dtx_texture(filepath):
        dtx = DTX(filepath)
        image_name = os.path.splitext(os.path.basename(filepath))[0]
        image = bpy.data.images.new(image_name, dtx.width, dtx.height, alpha=True)
        image.pixels[:] = dtx.pixels[:]
        return image

class MyTextureImporter(Operator):
    def execute(self, context):
        load_dtx_texture(self.filepath)
        return {'FINISHED'}

class MyMeshImporter(Operator):
    def execute(self, context):

        ....

        image = load_dtx_texture(self.filepath)

        ....

        return {'FINISHED'}
$\endgroup$
1
$\begingroup$

You can add custom properties to blenders main types. For a global setting add one to scene while adding one to object will let you save a different value per object.

bpy.types.Scene.global_prop = bpy.props.StringProperty()
bpy.types.Object.obj_prop = bpy.props.StringProperty()

Then you access them like any other property.

context.object.obj_prop = image.name

For more complex requirements you can create a collection and define a class to hold multiple settings.

class SceneSettingItem(bpy.types.PropertyGroup):
    name = bpy.props.StringProperty(name="Test Prop", default="Unknown")
    value = bpy.props.IntProperty(name="Test Prop", default=22)

bpy.utils.register_class(SceneSettingItem)

bpy.types.Scene.my_settings = \
    bpy.props.CollectionProperty(type=SceneSettingItem)

my_item = bpy.context.scene.my_settings.add()
my_item.name = "Spam"
my_item.value = 1000

If you are making an addon, you can add the new properties in register() and then delete then in unregister()

def register():
    bpy.types.Scene.global_prop = bpy.props.StringProperty()

def unregister():
    del bpy.types.Scene.global_prop

It is also possible to add custom properties to individual objects. These work like the object is a dictionary, just assign a value to the key, you will also want to check that the property (key) exists before trying to read it.

context.object['obj_prop'] = 'something'
$\endgroup$
2
  • $\begingroup$ And how (related to the question) will help? $\endgroup$
    – J. Bakker
    Jan 26, 2018 at 12:28
  • $\begingroup$ You can't return data from one operator to another, you can store the data in a property and access it from both. $\endgroup$
    – sambler
    Jan 26, 2018 at 12:51

You must log in to answer this question.

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