2
$\begingroup$

Is there a way to go through every .blend file in a directory and do the following with each:

  • Open the file.

  • Move the cursor to 0,0,0

  • Enter edit mode (there is only 1 object in each file)

  • Select all vertices

  • Apply a scale by a constant across all 3 axis

  • Exit edit mode

  • Save the file

  • Export to .fbx

If someone can point me to the recursing/opening/saving and exporting portions of this I can likely get the rest - just not sure how to go about it because I've only made very small hacks to the spacebar hotkey plugin (like adding arc intersection calculators/snap-tos) and am not really familiar with Blender scripting beyond inserting the occasional menu item into a preexisting plugin.

Hoping for something quick and dirty.

$\endgroup$
3
$\begingroup$

Using Python and Unix Shell Scripting

You can accomplish this with some Python scripting and Unix shell code. If you are on a Unix system (macOS or Linux) this won't be a problem. If you are on Windows, you can try Cygwin, but I haven't tried it and the shell script might need some modification.

The first step is to save the following Python script as script.py (or something else) into the same directory as your .blend files:

import bpy
import os

scene = bpy.context.scene
obj = scene.objects.active

#Transform and save
k = 2 #scale constant
bpy.ops.transform.resize(value=(k,k,k))
bpy.ops.object.transform_apply(scale=True)
bpy.ops.wm.save_mainfile()

#copied from the basic export.py template
basedir = os.path.dirname(bpy.data.filepath)
if not basedir:
    raise Exception("Blend file is not saved")
name = bpy.path.clean_name(obj.name)
fn = os.path.join(basedir, name)
bpy.ops.export_scene.fbx(filepath=fn + ".fbx")

print("written:", fn)

Note: This script assumes only one object in the blend file, and won't always work if that isn't the case.

Next, in your Unix shell (terminal, command line, etc.) navigate to the directory that your files are in (cd /path/to/directory/).

Finally, run this script in the shell:

for file in *.blend; do /path/to/blender -b "$file" -P script.py; done

If you are on a Mac, and you installed Blender by copying it to the Applications folder, then /path/to/blender will be /Applications/blender.app/Contents/MacOS/blender. If you didn't, or are on Linux, it will be wherever you put Blender.

What the shell script does, is iterate through each of the .blend files in the directory, launch Blender, and then execute the Python script on each file.

Note: The console will not give you any feedback until the entire batch is done, at which time it will spit out all of the console logs at once. While it is running, though, you can check the .fbx files it outputs to make sure that everything is working correctly.

$\endgroup$
  • $\begingroup$ Does bpy.ops.object.transform.resize() apply the scaling to vertices (equivalent to pressing S in edit mode) or to the object itself? I'm trying to have the scale on the objects remain 1 before and after the operation with the actual vertices transformed. $\endgroup$ – CoryG Jan 19 '17 at 18:12
  • $\begingroup$ bpy.ops.object.transform.resize() applies the scaling to the object, and then bpy.ops.object.transform_apply(scale=True) applies the scale, setting the scale to 1 while maintaining the current size. $\endgroup$ – Scott Milner Jan 19 '17 at 19:22
  • $\begingroup$ Bad choice of words, sorry. The first command scales the object (like pressing S). The second command applies the scale (like pressing Ctrl + A). $\endgroup$ – Scott Milner Jan 20 '17 at 4:27
5
$\begingroup$

Using only Python and Blender

For clarity and security, I don't overwrite the original files.

This script will check for the scene files (which contain the object). Then, for each file separately, it will append all objects, scale them and save itself as the scaled file version. After that export the .fbx and finally on completion save itself as the original conversion script file.

With the script saved in the file convert.blend. My folder structure looks like this at the start.

enter image description here

Opening the file convert.blend and pressing Run Script the scaled scene files and fbx files will be created.

import bpy, os
import bmesh
import math
import mathutils

def clear_objects():
    for obj in bpy.data.objects:
        bpy.context.scene.objects.unlink(obj)
        obj.user_clear()
        bpy.data.objects.remove(obj)
    for me in bpy.data.meshes:
        me.user_clear()
        bpy.data.meshes.remove(me)

def save_scaled_objects(dir_source, dir_target, dir_fbx, scale = 1):
    dir_root = bpy.path.abspath("//")
    path_origin = bpy.data.filepath

    dir_source = os.path.join(dir_root, dir_source)
    dir_target = os.path.join(dir_root, dir_target)
    dir_fbx = os.path.join(dir_root, dir_fbx)

    files = os.listdir(dir_source)

    scn = bpy.context.scene

    for f in files:
        input_filepath = os.path.join(dir_source, f)
        output_filepath = os.path.join(dir_target, f)
        output_fbx = os.path.join(dir_fbx, os.path.splitext(f)[0] + ".fbx")

        print("DIR",output_fbx)
        # append object data block
        with bpy.data.libraries.load(input_filepath, link=False) as (data_from, data_to):
            data_to.objects = data_from.objects
        #link all objects to current scene
        for obj in data_to.objects:
            if obj is not None:
                scn.objects.link(obj)
                #scale the objects data
                scale = 0.1
                for v in obj.data.vertices:
                    v.co *= scale
        print(output_filepath)
        # saves the file
        bpy.ops.wm.save_mainfile(filepath=output_filepath)
        #export to fbx
        bpy.ops.export_scene.fbx(filepath = output_fbx)

        clear_objects()
    # on completion of all saves, restore the original path of this file
    bpy.ops.wm.save_mainfile(filepath=path_origin)


dir_source = "scn_files"
dir_target = "scn_files_scaled"
dir_fbx = "fbx_export"
save_scaled_objects(dir_source, dir_target, dir_fbx, scale = 0.1)

Linking and Appending
Remove Objects
Base Path, Path Joining, Splitext

$\endgroup$
  • $\begingroup$ Do you know how to enter edit mode, select all vertices and apply the scale from there before exiting edit mode? It's important that the scale remain 1 on the actual object and the vertices actually be scaled from edit mode. $\endgroup$ – CoryG Jan 19 '17 at 18:10
  • $\begingroup$ for v in obj.data.vertices: v.co *= scale; This scales all Vertices, not the object. The objects scale remains whatever it was. It is also faster (and more stable) than using "bpy.ops" and going into edit mode. You don't need edit mode to alter the mesh data in python. $\endgroup$ – Leander Jan 19 '17 at 18:17

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.