Blender to Backburner (network render)

Yesterday I was doing some work over at Red Cartel, as part of it I coded a new network render submission script for Blender 2.5 to Autodesk Backburner – the default queue manager that comes with Max and Maya. I’d previously already made a similar exporter for Blender 2.4 which has been in use there for a while, allowing managing and prioritising Blender jobs alongside Max/vray jobs on the same farm.

I’ve packaged it up as a Blender 2.5 addon, it might be useful to any of you wanting to render Blender jobs in an Autodesk-centric environment. Get it here: http://mke3.net/projects/bpy/render_backburner.py

This script could be very useful here. Unfortunatly, it doesn’t work with new Blender’s versions.

I try to modify, and I managed to get the user interface appears, but it throws error if I touch anything. The error is :
“Writing to ID classes in this context is not allowed : Scene, Scene datablock …”

I tried to use a global variable, instead of a scene property to store datas, but it is worse.

I need help python gurus!

this is the modified script to have the interface


# This script is available under the terms of the Bugroff license:
# http://tunes.org/legalese/bugroff.html
#
# Authors: Matt Ebb

import bpy
import os
import subprocess

from bpy.props import PointerProperty, StringProperty, BoolProperty, EnumProperty, IntProperty, CollectionProperty


bl_addon_info = {
    "name": "Render: Submit to Backburner",
    "author": "Matt Ebb",
    "version": "2.0 2010/08/05",
    "blender": (2, 5, 8),
    "category": "Render",
    "location": "Property Editor > Render > Backburner",
    "description": "Submit the .blend file for network rendering on Autodesk Backburner",
    "warning": '', # used for warning icon and text in addons panel
    "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/My_Script",
    "tracker_url": "http://projects.blender.org/tracker/index.php?func=detail&aid=#&group_id=#&atid=#",
    "doc": """\
This allows network rendering .blend files on Autodesk Backburner.

Quick setup

In the Backburner panel:
1. Fill in the path to the blender executable that you wish to 
   render with in 'Blender Path'. This must be accessible over 
   the network with the same path, from all render nodes 
   running Backburner Server.
2. Fill in the path to cmdjob.exe in your local Backburner installation
   This is the command line backburner job submitter which this script
   uses to submit jobs for rendering

"""}

default_backburner_path = 'C:\\Program Files (x86)\\Autodesk\\Backburner\\cmdjob.exe'
default_blender_path = 'C:\\Program Files\\Blender Foundation\\Blender\\blender.exe'

#def rnaType(rna_type):
#    if bpy: bpy.types.register(rna_type)
#    return rna_type

#@rnaType



class BackburnerSettings(bpy.types.PropertyGroup):
    pass

bpy.utils.register_class(BackburnerSettings)

# entry point for settings collection
bpy.types.Scene.backburner = PointerProperty(
    type=BackburnerSettings, name='Backburner Submission', description='Backburner Submission Settings')

# fill the new struct
BackburnerSettings.job_name = StringProperty(
    name='Job Name', description='Name of the job to be shown in Backburner', maxlen=256, default='')

BackburnerSettings.frames_per_task = IntProperty(
    name='Frames per Task', description='Number of frames to give each render node', min=1, max=1000, soft_min=1, soft_max=64, default=1)
BackburnerSettings.timeout = IntProperty(
    name='Timeout', description='Timeout per task', min=1, max=1000, soft_min=1, soft_max=64, default=120)
BackburnerSettings.priority = IntProperty(name='Priority', description='Priority of this job', min=1, max=1000, soft_min=1, soft_max=64, default=50)

BackburnerSettings.override_frame_range = BoolProperty(
    name='Override Frame Range', description='Override scene start and end frames', default=False)
BackburnerSettings.frame_start = IntProperty(
    name='Start Frame', description='Start frame of animation sequence to render', min=1, max=1000, soft_min=1, soft_max=64, default=1)
BackburnerSettings.frame_end = IntProperty(
    name='End Frame', description='End frame of animation sequence to render', min=1, max=1000, soft_min=1, soft_max=64, default=250)

BackburnerSettings.group = StringProperty(
    name='Group', description='Render this job only with the servers in this group', maxlen=400, default='Default')
BackburnerSettings.servers = StringProperty(
    name='Servers', description='Render this job only with the servers specified (semi-colon separated list - ignored if group is used)', maxlen=400, default='')

BackburnerSettings.path_backburner = StringProperty(
    name='Backburner Path', description='Path to Backburner cmdjob.exe', maxlen=400, default=default_backburner_path, subtype='FILE_PATH')
BackburnerSettings.path_blender = StringProperty(
    name='Blender Path', description='Path to blender.exe', maxlen=400, default=default_blender_path, subtype='FILE_PATH')

class RENDER_PT_Backburner(bpy.types.Panel):
    bl_space_type = 'PROPERTIES'
 #   bl_idname = "RENDER_PT_Backburner"
    bl_region_type = 'WINDOW'
    bl_context = "render"
    bl_label = 'Backburner'
    bl_default_closed = True

    def draw(self, context):
        layout = self.layout      

        scene = context.scene
        bb = scene.backburner

        layout.operator('render.submit_to_backburner', icon='RENDER_ANIMATION')

        layout.separator()

        layout.prop(bb, 'job_name')
        layout.prop(bb, 'frames_per_task')
        row = layout.row()
        row.prop(bb, 'timeout')
        row.prop(bb, 'priority')

        if (bb.override_frame_range == False):
            bb.frame_start = scene.frame_start
            bb.frame_end = scene.frame_end

        layout.prop(bb, 'override_frame_range')

        row = layout.row()
        row.enabled = bb.override_frame_range
        row.prop(bb, 'frame_start')
        row.prop(bb, 'frame_end')

        layout.separator()

        layout.prop(bb, 'group')
        layout.prop(bb, 'servers')

        layout.prop(bb, 'path_backburner')
        layout.prop(bb, 'path_blender')

        

def write_tasklist(step, sframe, eframe, filename):
    dir = os.path.dirname(filename)
    
    # if we need a unique ID?
    # id = str(time.time())[:-3]
    # tasklist_path = dir + '\\submit_temp_' + id + '.txt'
    
    tasklist_path = dir + '\\submit_temp.txt'
    try:
        file = open(tasklist_path, 'w')
    except:
        print("couldn't open " + tasklist_path + " for writing")

    # dodgy method of writing out the frame sequences since I'm too
    # tired to think of a fancy mathematical construct
    # ... it works though!
    curframe = sframe
    while(curframe <= eframe):
        seq_sta = curframe
        seq_end = curframe + (step-1)
        if seq_end > eframe: seq_end = eframe
        curframe = seq_end + 1
        
        task = 'Frame ' + str(seq_sta)
        if seq_sta != seq_end:
            task += ' - ' + str(seq_end)
        task += '	'
        task += str(seq_sta) + '	' + str(seq_end) + '
'
        file.write(task)

    file.close()
    return tasklist_path
    

def submit(scene):

    bb = scene.backburner

    filename = bpy.data.filepath
    blenderdir = os.path.dirname(bb.path_blender)
    
    print('--- Submitting: ')
    description = 'Rendering_to_' + scene.render.filepath
    

    tasklist_path = write_tasklist(bb.frames_per_task, bb.frame_start, bb.frame_end, filename)

    cmd = '"' + bb.path_backburner + '"'
    cmd += ' -jobName:' + bb.job_name
    cmd += ' -jobNameAdjust'
    cmd += ' -description:' + description
    cmd += ' -priority:' + str(bb.priority)
    cmd += ' -timeout:' + str(bb.timeout)
    if bb.group != '':
        cmd += ' -group:' + bb.group
    if bb.servers != '':
        cmd += ' -servers:' + bb.servers
    cmd += ' -workPath:' + blenderdir
    cmd += ' -taskList:' + tasklist_path
    cmd += ' -taskName: 1'
    cmd += ' "' + bb.path_blender + '" --background '
    cmd += filename
    cmd += ' --frame-start %tp2 --frame-end %tp3 --render-anim'

    print(cmd)
    
    result = subprocess.call(cmd)
    if result != 0:
        print('Submit Failed for: ' + filename)
        submit_status = "FAILED"
    else:
        print('Submit Suceeded for: ' + filename)
        submit_status = "OK"

    os.remove(tasklist_path)


class SubmitToBackburner(bpy.types.Operator):
    ''''''
    bl_idname = "render.submit_to_backburner"
    bl_label = "Submit to Backburner"

    @classmethod
    def poll(cls, context):
        return context.scene != None

    def invoke(self, context, event):
        bb = context.scene.backburner
        if bb.path_blender == '':
            self.report({'ERROR'}, "Network path to Blender hasn't been set")
            return {'CANCELLED'}
        if bb.path_backburner == '':
            self.report({'ERROR'}, "Path to Backburner cmdjob.exe hasn't been set")
            return {'CANCELLED'}
        submit(context.scene)

    def execute(self, context):
        submit(context.scene)
        return {'FINISHED'}

bpy.utils.register_class(RENDER_PT_Backburner)

The python api has changed a lot in the year+ since this thread was started.

Yep Uncle!
I’ve noticed it has changed, but is there a way to understand what exactely have changed? I managed to get info about interface changes, but I don’t understand this context issue.