Basic Scripts (No UI)

Some times, you don’t need a UI but just a button to run some code.

Following are some example scripts to help you get started.

Important tips

1. Select All Animated Objects

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import bpy

animated_objs = []

for material in bpy.data.materials:
    if material.animation_data:
        for obj in bpy.data.objects:
            for slot in obj.material_slots:
                if slot.material == material:
                    animated_objs.append(obj)

for obj in bpy.data.objects:
    if obj.animation_data:
        animated_objs.append(obj)

for obj in animated_objs:
    obj.select_set(True)

2. Set Animation Range to selected object/s animation range

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import bpy
import math

# get keyframes of object list
def get_keyframes(obj_list):
    keyframes = []
    for obj in obj_list:
        anim = obj.animation_data
        if anim is not None and anim.action is not None:
            for fcu in anim.action.fcurves:
                for keyframe in fcu.keyframe_points:
                    x, y = keyframe.co
                    if x not in keyframes:
                        keyframes.append((math.ceil(x)))
    return keyframes

# get all selected objects
selection = bpy.context.selected_objects

# check if selection is not empty
if selection:

    # get all frames with assigned keyframes
    keys = get_keyframes(selection)

    # print all keyframes
    print (keys)   

    # print first and last keyframe
    print ("{} {}".format("first keyframe:", keys[0]))
    print ("{} {}".format("last keyframe:", keys[-1]))

    bpy.context.scene.frame_start = keys[0]
    bpy.context.scene.frame_end = keys[-1]
else:
    print ('nothing selected')

3. Create Curve Object with no CP

1
2
3
4
5
6
7
8
import bpy
bpy.ops.object.mode_set(mode = 'OBJECT')
bpy.ops.curve.primitive_bezier_curve_add(radius=1, enter_editmode=False, location=(0, 0, 0))
bpy.ops.object.editmode_toggle()
bpy.ops.curve.select_all(action='SELECT')
bpy.ops.curve.delete(type='VERT')
bpy.ops.object.editmode_toggle()


4. Create Curve Object with single CP

1
2
3
4
5
6
7
import bpy
bpy.ops.object.mode_set(mode = 'OBJECT')
bpy.ops.curve.primitive_bezier_curve_add(radius=1, enter_editmode=False, location=(0, 0, 0))
bpy.ops.object.editmode_toggle()
bpy.ops.curve.select_all(action='SELECT')
bpy.ops.curve.dissolve_verts()
bpy.ops.object.editmode_toggle()

5. Separate select mesh object faces

As you can see, these are unedited code from info panel pasted as it is, which just worked for me. I didn’t even bother to edit the long line which has so many default parameter

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import bpy

bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":(0, 0, 0), "orient_type":'GLOBAL', "orient_matrix":((0, 0, 0), (0, 0, 0), (0, 0, 0)), "orient_matrix_type":'GLOBAL', "constraint_axis":(False, False, False), "mirror":False, "use_proportional_edit":False, "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "use_proportional_connected":False, "use_proportional_projected":False, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "cursor_transform":False, "texture_space":False, "remove_on_cancel":False, "release_confirm":False, "use_accurate":False})

bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
bpy.ops.mesh.extrude_faces_move(MESH_OT_extrude_faces_indiv={"mirror":False}, TRANSFORM_OT_shrink_fatten={"value":0, "use_even_offset":False, "mirror":False, "use_proportional_edit":False, "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "use_proportional_connected":False, "use_proportional_projected":False, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "release_confirm":False, "use_accurate":False})
bpy.ops.mesh.select_all(action='INVERT')
bpy.ops.mesh.delete(type='FACE')
bpy.ops.mesh.select_all(action='INVERT')
bpy.ops.mesh.separate(type='LOOSE')
bpy.ops.object.editmode_toggle()


6. Purge Orphan Data

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# purge, it will removed unused deleted data.
import bpy

def purge():
    # purge won't run more than 5 times.
    # for any unknown reason, lets say their is some cyclic dependency and purge never return
    # {'CANCELLED'}, which it returns when it has nothing to purge
    # when I am using api, I don't fully understand, I use this trick to avoid infinite loop
    safety_cnt = 5
    for i in range(safety_cnt):
        op_result = bpy.ops.outliner.orphans_purge()
        # returns {'FINISHED'} or {'CANCELLED'}
        if op_result == {'CANCELLED'}:
            if i == 0:
                print(f'ran purge {i + 1} times, there was nothing to purge')
            else:
                print(f'ran purge {i + 1} times')
            return
    print(f"purging {safety_cnt} times wasn't enough, run once more")

purge()

Tip

Tips For beginners coders, for majority of tasks, rarely you need to write from scratch.

1. If you turn on preference->interface-> developer extra you get a copy python command in the context menu.

  1. Copy code from info_panel, it’s reflects history of commands you ran from interface.

  2. All the addons that are installed or you can find in net. execute method is called when operator is run, so you can copy that code and any other function that is called by that method

  3. Online from blender stack_exchange, blender_artist, SO etc