4
$\begingroup$

EDIT: as of yet I haven't been able to find a concrete example of someone using an addon exporter in a python script, so if any of you have that I would be very grateful!

I have hundreds of files and I'm using a small script to standardize them and convert them to .json files for use in three.js, but I can't get the exporter to work. It is throwing an error (evidently a different one than ImportError) at bpy.ops.wm.addon_expand(module="three") - when I mouse over the addon in the "export" submenu, it gives me the bpy.ops.export.three(filepath = "export path") operation as how to access it, but it is still throwing errors. Here's my testing code:

import bpy
import addon_utils

def main():
    cube = bpy.data.objects[1]
    bpy.ops.object.delete()
    # import
    filePath = "import path"
    bpy.ops.import_scene.obj(filepath=filePath)
    tablet = bpy.data.objects[1]
    # find dimensions and scale accordingly
    tabletDimensions = tablet.dimensions
    scale = min(10/tabletDimensions[0],10/tabletDimensions[1],10/tabletDimensions[2])
    # give 3dcursor new coordinates
    bpy.context.scene.cursor_location = (0.0,0.0,0.0)
    # set the origin on the current object to the 3dcursor location
    bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN')
    tablet.scale = (scale,scale,scale)
    print(addon_utils.paths())
    try:
        bpy.ops.wm.addon_expand(module="three")
        bpy.ops.export.three(filepath = "export path")
    except ImportError:
        print("Threejs importer addon not available")

    #bpy.ops.mesh.primitive_uv_sphere_add(size=2,location=(5,5,5))
main()
$\endgroup$
4
$\begingroup$

I'll ignore the part of your code which you seem to have working. MrDoob advised in the readme to use the exporter available from the Three.js github repo. It's tucked away in a directory.

github.com/mrdoob/three.js/tree/master/utils/exporters/blender/addons/io_three

If you are using the one that comes with Blender it may not be up to date. Working under the assumption that you're using the latest and greatest (from the link above), then something like this will export the active object.

bpy.ops.export.three(filepath="/home/zeffii/Desktop/barbaric.json")

If you have specific options to pass then they must be passed as keyword arguments. Use Python Console's auto-complete to get the full list or read the source of the exporter.

>>> bpy.ops.export.three(
three()
bpy.ops.export.three(
    filepath="",
    check_existing=True,
    option_vertices=True,
    option_faces=True,
    option_normals=True,
    (...)
    option_influences=2)

Enabling the add-on via a script is a separate issue from running the operator. If you are really stuck it may just be simpler to store that preference in the startup.blend. If you run the script and Blender hasn't yet loaded the add-ons then you may want to read this how to enable addon via script.

I took the liberty to rewrite/augment your script, I think this does (in an admittedly awkward way) what you wanted.

import os
import bpy
import addon_utils

def clear_scene():
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete(use_global=False)

def main(filePath, fileName):
    clear_scene()

    fullPath = os.path.join(filePath, fileName)
    bpy.ops.import_scene.obj(filepath=fullPath)
    obj = bpy.data.objects[0]

    # find dimensions and scale accordingly
    dims = obj.dimensions
    scale = min(10 / dims[0], 10 / dims[1], 10 / dims[2])

    # set cursor to world origin, and set object-origin the same
    bpy.context.scene.cursor_location = (0, 0, 0)
    bpy.context.scene.objects.active = obj
    bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN')
    obj.scale = (scale, scale, scale)

    json_fileName =  fileName[:-3] + '.json'
    finalPath = os.path.join(filePath, json_fileName)
    bpy.ops.export.three(filepath=finalPath)

def ensure_addon():
    try:
        addon_utils.enable("io_three")
        return True
    except:
        print('failed to enable io_three')
        return False

def path_iterator(path_name, ftype):
    for fp in os.listdir(path_name):
        if fp.endswith(ftype):
            yield fp

if ensure_addon():
    filePath = "/home/zeffii/Desktop/Objs"

    for fileName in path_iterator(filePath, '.obj'):
        print(fileName)
        main(filePath, fileName)

To clarify my changes / thoughts.
The obj import doesn't place the object in the active state, just selected. The export feature seems to require the object to be active, and ignores objects that are merely selected. To take care of that, use the reference to the only object in the scene and set it active:

bpy.context.scene.objects.active = obj

The error message, context is incorrect, is in this scenario a poor error message. (if the above is genuinely why the initial code failed.. )

$\endgroup$
1
$\begingroup$

Changing

bpy.ops.wm.addon_expand(module="three")

to

bpy.ops.wm.addon_expand(module="threejs")

gives me a {'FINISHED'} but then I get a fail when actually calling the export whether I use three or threejs. I get

RuntinmeError: Operator bpy.ops.export.three.poll() failed, context is incorrect

$\endgroup$
  • $\begingroup$ bpy.ops.wm.addon_expand(...) only expands the addon details in the UI, it doesn't install nor enable the addon. $\endgroup$ – batFINGER Dec 15 '15 at 16:46

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.