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
$\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 '18 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 '18 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.