<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>vSwarm Forum - Blender 2.5</title>
        <description>Blender 2.5 job questions here</description>
        <link>http://forum.vswarm.com/list.php?24</link>
        <lastBuildDate>Tue, 07 Sep 2010 04:13:56 +0200</lastBuildDate>
        <generator>Phorum 5.2.15</generator>
        <item>
            <guid>http://forum.vswarm.com/read.php?24,927,927#msg-927</guid>
            <title>Blender 2.5 renderfarm.fi scripts (no replies)</title>
            <link>http://forum.vswarm.com/read.php?24,927,927#msg-927</link>
            <description><![CDATA[ Have you seen the last renderer addon scripts in blender 2.5 for Renderfarm.fi ? <br />
<br />
Would be great to have the same thing for vswarm to be able to send the job directly to it from blender, isn't it ? <br />
<br />
<br />
<pre class="bbcode">
# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
#
# Copyright 2009-2010 Laurea University of Applied Sciences
# Authors: Nathan Letwory, Jesse Kaukonen

import bpy
import hashlib
import http.client
import xmlrpc.client
import math
from os.path import abspath, isabs, join, isfile

bpy.CURRENT_VERSION = 2
bpy.found_newer_version = False
bpy.up_to_date = False
bpy.download_location = 'http://www.renderfarm.fi/blender'

bl_addon_info = {
    'name': 'Render: Renderfarm.fi',
    'author': 'Nathan Letwory &lt;nathan@letworyinteractive.com&gt;, Jesse Kaukonen &lt;jesse.kaukonen@gmail.com&gt;',
    'version': str(bpy.CURRENT_VERSION),
    'blender': (2, 5, 3),
    'location': 'Render &gt; Engine &gt; Renderfarm.fi',
    'description': 'Send .blend as session to [<a href="http://www.renderfarm.fi" rel="nofollow" >www.renderfarm.fi</a>] to render',
    'warning': '', # used for warning icon and text in addons panel
    'wiki_url': 'http://wiki.blender.org/index.php/Extensions:2.5/Py/' \
        'Scripts/Render/Renderfarm.fi',
    'tracker_url': 'https://projects.blender.org/tracker/index.php?'\
        'func=detail&amp;aid=22927&amp;group_id=153&amp;atid=469',
    'category': 'Render'}

bpy.errorMessages = {
    'missing_desc': 'You need to enter a title, short and long description',
    'missing_creds': 'You haven\'t entered your credentials yet'
}

bpy.statusMessage = {
    'title': 'TRIA_RIGHT',
    'shortdesc': 'TRIA_RIGHT',
    'longdesc': 'TRIA_RIGHT',
    'username': 'TRIA_RIGHT',
    'password': 'TRIA_RIGHT'
}

bpy.errors = []
bpy.ore_sessions = []
bpy.queue_selected = -1

def rnaType(rna_type):
	bpy.types.register(rna_type)
	return rna_type

def renderEngine(render_engine):
    bpy.types.register(render_engine)
    return render_engine

@rnaType
class ORESession(bpy.types.IDPropertyGroup):
    pass

@rnaType
class ORESettings(bpy.types.IDPropertyGroup):
    pass

# entry point for settings collection
bpy.types.Scene.PointerProperty(attr='ore_render', type=ORESettings, name='ORE Render', description='ORE Render Settings')

# fill the new struct
ORESettings.StringProperty(attr='username', name='E-mail', description='E-mail for Renderfarm.fi', maxlen=256, default='')
ORESettings.StringProperty(attr='password', name='Password', description='Renderfarm.fi password', maxlen=256, default='')
ORESettings.StringProperty(attr='hash', name='Hash', description='hash calculated out of credentials', maxlen=33, default='')

ORESettings.StringProperty(attr='shortdesc', name='Short description', description='A short description of the scene (100 characters)', maxlen=101, default='')
ORESettings.StringProperty(attr='longdesc', name='Long description', description='A more elaborate description of the scene (2k)', maxlen=2048, default='')
ORESettings.StringProperty(attr='title', name='Title', description='Title for this session (128 characters)', maxlen=128, default='')
ORESettings.StringProperty(attr='url', name='Project URL', description='Project URL. Leave empty if not applicable', maxlen=256, default='')

ORESettings.IntProperty(attr='parts', name='Parts/Frame', description='', min=1, max=1000, soft_min=1, soft_max=64, default=1)
ORESettings.IntProperty(attr='resox', name='Resolution X', description='X of render', min=1, max=10000, soft_min=1, soft_max=10000, default=1920)
ORESettings.IntProperty(attr='resoy', name='Resolution Y', description='Y of render', min=1, max=10000, soft_min=1, soft_max=10000, default=1080)
ORESettings.IntProperty(attr='memusage', name='Memory Usage', description='Estimated maximum memory usage during rendering in MB', min=1, max=6*1024, soft_min=1, soft_max=3*1024, default=256)
ORESettings.IntProperty(attr='start', name='Start Frame', description='Start Frame', default=1)
ORESettings.IntProperty(attr='end', name='End Frame', description='End Frame', default=250)
ORESettings.IntProperty(attr='fps', name='FPS', description='FPS', min=1, max=256, default=25)

ORESettings.BoolProperty(attr='prepared', name='Prepared', description='Set to True if preparation has been run', default=False)
ORESettings.BoolProperty(attr='debug', name='Debug', description='Verbose output in console', default=False)
ORESettings.IntProperty(attr='selected_session', name='Selected Session', description='The selected session', default=0)

# session struct
ORESession.StringProperty(attr='name', name='Name', description='Name of the session', maxlen=128, default='[session]')

licenses =  (
        ('1', 'CC by-nc-nd', 'Creative Commons: Attribution Non-Commercial No Derivatives'),
        ('2', 'CC by-nc-sa', 'Creative Commons: Attribution Non-Commercial Share Alike'),
        ('3', 'CC by-nd', 'Creative Commons: Attribution No Derivatives'),
        ('4', 'CC by-nc', 'Creative Commons: Attribution Non-Commercial'),
        ('5', 'CC by-sa', 'Creative Commons: Attribution Share Alike'),
        ('6', 'CC by', 'Creative Commons: Attribution'),
        ('7', 'Copyright', 'Copyright, no license specified'),
        )
ORESettings.EnumProperty(attr='inlicense', items=licenses, name='source license', description='license speficied for the source files', default='1')
ORESettings.EnumProperty(attr='outlicense', items=licenses, name='output license', description='license speficied for the output files', default='1')

ORESettings.CollectionProperty(attr='sessions', type=ORESession, name='Sessions', description='Sessions on Renderfarm.fi')
        
# all panels, except render panel
# Example of wrapping every class 'as is'
import properties_scene
for member in dir(properties_scene):
    subclass = getattr(properties_scene, member)
    try:        subclass.COMPAT_ENGINES.add('RENDERFARMFI_RENDER')
    except:    pass
del properties_scene

import properties_world
for member in dir(properties_world):
    subclass = getattr(properties_world, member)
    try:        subclass.COMPAT_ENGINES.add('RENDERFARMFI_RENDER')
    except:    pass
del properties_world

import properties_material
for member in dir(properties_material):
    subclass = getattr(properties_material, member)
    try:        subclass.COMPAT_ENGINES.add('RENDERFARMFI_RENDER')
    except:    pass
del properties_material

import properties_object
for member in dir(properties_object):
    subclass = getattr(properties_object, member)
    try:        subclass.COMPAT_ENGINES.add('RENDERFARMFI_RENDER')
    except:    pass
del properties_object

class RenderButtonsPanel(bpy.types.Panel):
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = &quot;render&quot;
    # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
    
    def poll(self, context):
        rd = context.scene.render
        return (rd.use_game_engine==False) and (rd.engine in self.COMPAT_ENGINES)

class RENDERFARM_MT_Session(bpy.types.Menu):
    bl_label = &quot;Show Session&quot;

    def draw(self, context):
        layout = self.layout

        layout.operator('ore.completed_sessions')
        layout.operator('ore.accept_sessions')
        layout.operator('ore.active_sessions')
        layout.separator()
        layout.operator('ore.cancelled_sessions')

class LOGIN_PT_RenderfarmFi(RenderButtonsPanel):
    bl_label = 'Login to Renderfarm.fi'
    COMPAT_ENGINES = set(['RENDERFARMFI_RENDER'])
    def draw(self, context):
        layout = self.layout
        # XXX layout.operator('ore.check_update')
        ore = context.scene.ore_render
        updateSessionList(ore)
        checkStatus(ore)

        if ore.hash=='':
            col = layout.column()
            if ore.hash=='':
                col.prop(ore, 'username', icon=bpy.statusMessage['username'])
                col.prop(ore, 'password', icon=bpy.statusMessage['password'])
            layout.operator('ore.login')
        else:
            layout.label(text='E-mail and password entered.', icon='INFO')
            layout.operator('ore.change_user')

class CHECK_PT_RenderfarmFi(RenderButtonsPanel):
    bl_label = 'Check for updates'
    COMPAT_ENGINES = set(['RENDERFARMFI_RENDER'])

    def draw(self, context):
        layout = self.layout
        ore = context.scene.ore_render

        if bpy.found_newer_version == True:
            layout.operator('ore.open_download_location')
        else:
            if bpy.up_to_date == True:
                layout.label(text='You have the latest version')
            layout.operator('ore.check_update')

class SESSIONS_PT_RenderfarmFi(RenderButtonsPanel):
    bl_label = 'Sessions'
    COMPAT_ENGINES = set(['RENDERFARMFI_RENDER'])

    def draw(self, context):
        layout = self.layout
        ore = context.scene.ore_render
        
        layout.menu(&quot;RENDERFARM_MT_Session&quot;)
        if bpy.queue_selected == 1:
            layout.label(text='Completed Sessions')
        elif bpy.queue_selected == 2:
            layout.label(text='Rendering Sessions')
        elif bpy.queue_selected == 3:
            layout.label(text='Pending Sessions')
        elif bpy.queue_selected == 4:
            layout.label(text='Cancelled and Rejected Sessions')
        layout.template_list(ore, 'sessions', ore, 'selected_session', rows=2)
        if bpy.queue_selected == 3:
            layout.operator('ore.cancel_session')

class RENDER_PT_RenderfarmFi(RenderButtonsPanel):
    bl_label = &quot;Scene Settings&quot;
    COMPAT_ENGINES = set(['RENDERFARMFI_RENDER'])

    def draw(self, context):
        layout = self.layout
        sce = context.scene
        ore = sce.ore_render

        if ore.prepared and ore.hash!='':
            layout.prop(ore, 'memusage')
            
            layout.separator()
            row = layout.row()
            row.label(text='Resolution: '+str(ore.resox)+'x'+str(ore.resoy))
            
            layout.separator()
            row = layout.row()
            row.prop(ore, 'inlicense')
            row.prop(ore, 'outlicense')
            
            layout.separator()
            row = layout.row()
            row.operator('ore.upload')
            row.operator('ore.reset', icon='FILE_REFRESH')
        else:
            layout.prop(ore, 'title', icon=bpy.statusMessage['title'])
            layout.prop(ore, 'shortdesc', icon=bpy.statusMessage['shortdesc'])
            layout.prop(ore, 'longdesc', icon=bpy.statusMessage['longdesc'])
            layout.prop(ore, 'url')
            layout.separator()
            layout.operator('ore.use_scene_settings', icon='HAND')
            row = layout.row()
            row.prop(ore, 'resox')
            row.prop(ore, 'resoy')
            layout.separator()
            layout.prop(ore, 'parts')
            row = layout.row()
            row.prop(ore, 'start')
            row.prop(ore, 'end')
            layout.prop(ore, 'fps')
            
            layout.separator()
            layout.operator('ore.prepare', icon='INFO')

def random_string(length):
    import string
    import random
    return ''.join(random.choice(string.ascii_letters) for ii in range(length + 1))

def encode_multipart_data(data, files):
    boundary = random_string(30)

    def get_content_type(filename):
        return 'application/octet-stream' # default this

    def encode_field(field_name):
        return ('--' + boundary,
                'Content-Disposition: form-data; name=&quot;%s&quot;' % field_name,
                '', str(data[field_name]))

    def encode_file(field_name):
        import codecs
        filename = files [field_name]
        return ('--' + boundary,
                'Content-Disposition: form-data; name=&quot;%s&quot;; filename=&quot;%s&quot;' % (field_name, filename),
                'Content-Type: %s' % get_content_type(filename),
                '', str(open(filename, 'rb').read(), encoding='iso-8859-1'))

    lines = []
    for name in data:
        lines.extend(encode_field(name))
    for name in files:
        lines.extend(encode_file(name))
    lines.extend(('--%s--' % boundary, ''))
    body = '\r\n'.join(lines)

    headers = {'content-type': 'multipart/form-data; boundary=' + boundary,
               'content-length': str(len(body))}

    return body, headers

def send_post(url, data, files):
    connection = http.client.HTTPConnection('xmlrpc.renderfarm.fi')
    connection.request('POST', '/file', *encode_multipart_data(data, files))
    response = connection.getresponse()
    res = response.read()
    return res

def md5_for_file(filepath):
    md5hash = hashlib.md5()
    blocksize = 0x10000
    f = open(filepath, &quot;rb&quot;)
    while True:
        data = f.read(blocksize)
        if not data:
            break
        md5hash.update(data)
    return md5hash.hexdigest()

def upload_file(key, userid, sessionid, server, path):
    assert isabs(path)
    assert isfile(path)

    data = {
        'userId': str(userid),
        'sessionKey': key,
        'sessionId': sessionid,
        'md5sum': md5_for_file(path)
    }
    files = {
        'blenderfile': path
    }

    r = send_post(server, data, files)

    #print 'Uploaded %r' % (path)
    
    return r

def run_upload(key, userid, sessionid, path):
    #print('Upload', path)
    r = upload_file(key, userid, sessionid, r'http://xmlrpc.renderfarm.fi/file', path)
    o = xmlrpc.client.loads(r)
    #print('Done!')
    
    return o[0][0]

def ore_upload(op, context):
    sce = context.scene
    ore = sce.ore_render
    if not ore.prepared:
        op.report(set(['ERROR']), 'Your user or scene information is not complete')
        return {'CANCELLED'}
    try:
        authproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/auth')
        res = authproxy.auth.getSessionKey(ore.username, ore.hash)
        key = res['key']
        userid = res['userId']
        
        proxy = xmlrpc.client.ServerProxy(r'http://xmlrpc.renderfarm.fi/session')
        proxy._ServerProxy__transport.user_agent = 'Renderfarm.fi Uploader/%s' % (bpy.CURRENT_VERSION)
        res = proxy.session.createSession(userid, key)
        sessionid = res['sessionId']
        key = res['key']
        res = run_upload(key, userid, sessionid, bpy.data.filepath)
        fileid = int(res['fileId'])
        
        res = proxy.session.setTitle(userid, res['key'], sessionid, ore.title)
        res = proxy.session.setLongDescription(userid, res['key'], sessionid, ore.longdesc)
        res = proxy.session.setShortDescription(userid, res['key'], sessionid, ore.shortdesc)
        if len(ore.url)&gt;0:
            res = proxy.session.setExternalURLs(userid, res['key'], sessionid, ore.url)
        res = proxy.session.setStartFrame(userid, res['key'], sessionid, ore.start)
        res = proxy.session.setEndFrame(userid, res['key'], sessionid, ore.end)
        res = proxy.session.setSplit(userid, res['key'], sessionid, ore.parts)
        res = proxy.session.setMemoryLimit(userid, res['key'], sessionid, ore.memusage)
        res = proxy.session.setXSize(userid, res['key'], sessionid, ore.resox)
        res = proxy.session.setYSize(userid, res['key'], sessionid, ore.resoy)
        res = proxy.session.setFrameRate(userid, res['key'], sessionid, ore.fps)
        res = proxy.session.setOutputLicense(userid, res['key'], sessionid, int(ore.outlicense))
        res = proxy.session.setInputLicense(userid, res['key'], sessionid, int(ore.inlicense))
        res = proxy.session.setPrimaryInputFile(userid, res['key'], sessionid, fileid)
        res = proxy.session.submit(userid, res['key'], sessionid)
        op.report(set(['INFO']), 'Submission sent to Renderfarm.fi')
    except xmlrpc.client.Error as v:
        print('ERROR:', v)
        op.report(set(['ERROR']), 'An error occurred while sending submission to Renderfarm.fi')
    except Exception as e:
        print('Unhandled error:', e)
        op.report(set(['ERROR']), 'An error occurred while sending submission to Renderfarm.fi')
    
    return {'FINISHED'}

def setStatus(property, status):
    if status:
        bpy.statusMessage[property] = 'ERROR'
    else:
        bpy.statusMessage[property] = 'TRIA_RIGHT'

def showStatus(layoutform, property, message):
    if bpy.statusMessage[property] == 'ERROR':
        layoutform.label(text='', icon='ERROR')

def checkStatus(ore):
    bpy.errors = []
        
    if ore.hash=='' and (ore.username=='' or ore.password==''):
        bpy.errors.append('missing_creds')
    
    if '' in (ore.title, ore.longdesc, ore.shortdesc):
        bpy.errors.append('missing_desc')
    
    setStatus('username', ore.hash=='' and ore.username=='')
    setStatus('password', ore.hash=='' and ore.password=='')

    setStatus('title', ore.title=='')
    setStatus('longdesc', ore.longdesc=='')
    setStatus('shortdesc', ore.shortdesc=='')

class OreSession:

    def __init__(self, id, title):
        self.id = id
        self.title = title
        self.frames = 0
        self.startframe = 0
        self.endframe = 0
        self.rendertime = 0
        self.percentage = 0

    def percentageComplete(self):
        totFrames = self.endframe - self.startframe
        done = math.floor((self.frames / totFrames)*100)
        if done &gt; 100: done = 100
        return done

def xmlSessionsToOreSessions(sessions, queue):
    bpy.ore_sessions = []
    completed = sessions[queue]
    for sid in completed:
        s = completed[sid]['title']
        t = completed[sid]['timestamps']
        sinfo = OreSession(sid, s) 
        if queue in ('completed', 'active'):
            sinfo.frames = completed[sid]['framesRendered']
        sinfo.startframe = completed[sid]['startFrame']
        sinfo.endframe = completed[sid]['endFrame']
        bpy.ore_sessions.append(sinfo)

def updateSessionList(ore):
    while(len(ore.sessions) &gt; 0):
        ore.sessions.remove(0)

    for s in bpy.ore_sessions:
        ore.sessions.add()
        session = ore.sessions[-1]
        session.name = s.title + ' [' + str(s.percentageComplete()) + '% complete]'

class ORE_OpenDownloadLocation(bpy.types.Operator):
    bl_idname = 'ore.open_download_location'
    bl_label = 'Download new version for your platform'

    def execute(self, context):
        import webbrowser
        webbrowser.open(bpy.download_location)
        return {'FINISHED'}

class ORE_CancelSession(bpy.types.Operator):
    bl_idname = 'ore.cancel_session'
    bl_label = 'Cancel Session'

    def execute(self, context):
        sce = context.scene
        ore = sce.ore_render
        userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')
        if len(bpy.ore_sessions)&gt;0:
            s = bpy.ore_sessions[ore.selected_session]
            try:
                res = userproxy.user.cancelSession(ore.username, ore.hash, int(s.id))
                self.report(set(['INFO']), 'Session ' + s.title + ' with id ' + s.id + ' cancelled')
            except:
                self.report(set(['ERROR']), 'Could not cancel session ' + s.title + ' with id ' + s.id)

        return {'FINISHED'}

class ORE_GetCompletedSessions(bpy.types.Operator):
    bl_idname = 'ore.completed_sessions'
    bl_label = 'Complete'

    def execute(self, context):
        sce = context.scene
        ore = sce.ore_render
        bpy.queue_selected = 1
        userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')

        sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'completed')

        xmlSessionsToOreSessions(sessions, 'completed')

        updateSessionList(ore)

        return {'FINISHED'}

class ORE_GetCancelledSessions(bpy.types.Operator):
    bl_idname = 'ore.cancelled_sessions'
    bl_label = 'Cancelled'

    def execute(self, context):
        sce = context.scene
        ore = sce.ore_render
        bpy.queue_selected = 4
        userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')

        sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'completed')

        xmlSessionsToOreSessions(sessions, 'canceled')

        updateSessionList(ore)

        return {'FINISHED'}

class ORE_GetActiveSessions(bpy.types.Operator):
    bl_idname = 'ore.active_sessions'
    bl_label = 'Rendering'

    def execute(self, context):
        sce = context.scene
        ore = sce.ore_render
        bpy.queue_selected = 2
        userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')

        sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'active')

        xmlSessionsToOreSessions(sessions, 'active')
    
        updateSessionList(ore)

        return {'FINISHED'}

class ORE_GetPendingSessions(bpy.types.Operator):
    bl_idname = 'ore.accept_sessions' # using ORE lingo in API. acceptQueue is session waiting for admin approval
    bl_label = 'Pending'

    def execute(self, context):
        sce = context.scene
        ore = sce.ore_render
        bpy.queue_selected = 3
        userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')

        sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'accept')

        xmlSessionsToOreSessions(sessions, 'accept')
    
        updateSessionList(ore)

        return {'FINISHED'}

class ORE_CheckUpdate(bpy.types.Operator):
    bl_idname = 'ore.check_update'
    bl_label = 'Check for new version'

    def execute(self, context):
        sce = context.scene
        ore = sce.ore_render
        blenderproxy = xmlrpc.client.ServerProxy(r'http://xmlrpc.renderfarm.fi/blender')
        try:
            self.report(set(['INFO']), 'Checking for newer version on Renderfarm.fi')
            dl_url = blenderproxy.blender.getCurrentVersion(bpy.CURRENT_VERSION)
            if len(dl_url['url']) &gt; 0:
                self.report(set(['INFO']), 'Found a newer version on Renderfarm.fi ' + dl_url['url'])
                bpy.download_location = dl_url['url']
                bpy.found_newer_version = True
            else:
                bpy.up_to_date = True
            self.report(set(['INFO']), 'Done checking for newer version on Renderfarm.fi')
        except xmlrpc.client.Fault as f:
            print('ERROR:', f)
            self.report(set(['ERROR']), 'An error occurred while checking for newer version on Renderfarm.fi')

        return {'FINISHED'}

class ORE_LoginOp(bpy.types.Operator):
    bl_idname = 'ore.login'
    bl_label = 'Confirm credentials'

    def execute(self, context):
        sce = context.scene
        ore = sce.ore_render

        if ore.hash=='':
            if ore.password != '' and ore.username != '':
                ore.hash = hashlib.md5(ore.password.encode() + ore.username.encode()).hexdigest()
                ore.password = ''

        checkStatus(ore)
        
        if len(bpy.errors) &gt; 0:
            ore.prepared = False
            return {'CANCELLED'}

        return {'FINISHED'}

class ORE_PrepareOp(bpy.types.Operator):
    '''Checking the scene will also save to the current file when successful!'''
    bl_idname = 'ore.prepare'
    bl_label = 'Check scene'
    
    def execute(self, context):
        def hasSSSMaterial():
            for m in bpy.data.materials:
                if m.subsurface_scattering.enabled:
                    return True
            return False

        def hasParticleSystem():
            if len(bpy.data.particles) &gt; 0:
                self.report({'WARNING'}, &quot;Found particle system&quot;)
                print(&quot;Found particle system&quot;)
                return True
            return False

        def hasSimulation(t):
            for o in bpy.data.objects:
                for m in o.modifiers:
                    if isinstance(m, t):
                        self.report({'WARNING'}, &quot;Found simulation: &quot; + str(t))
                        print(&quot;Found simulation: &quot; + str(t))
                        return True
            return False

        def hasFluidSimulation():
            return hasSimulation(bpy.types.FluidSimulationModifier)

        def hasSmokeSimulation():
            return hasSimulation(bpy.types.SmokeModifier)

        def hasClothSimulation():
            return hasSimulation(bpy.types.ClothModifier)

        def hasCollisionSimulation():
            return hasSimulation(bpy.types.CollisionModifier)

        def hasSoftbodySimulation():
            return hasSimulation(bpy.types.SoftBodyModifier)

        def hasUnsupportedSimulation():
            return hasSoftbodySimulation() or hasCollisionSimulation() or hasClothSimulation() or hasSmokeSimulation or hasFluidSimulation() or hasParticleSystem()

        sce = context.scene
        ore = sce.ore_render
        
        errors = False
        
        checkStatus(ore)
        
        if len(bpy.errors) &gt; 0:
            ore.prepared = False
            return {'CANCELLED'}

        rd = sce.render
        print(&quot;=============================================&quot;)
        rd.threads_mode = 'FIXED'
        rd.threads = 1
        rd.resolution_x = ore.resox
        rd.resolution_y = ore.resoy
        if (rd.resolution_percentage != 100):
            print(&quot;Resolution percentage is not 100. Changing to 100%&quot;)
            self.report({'WARNING'}, &quot;Resolution percentage is not 100. Changing to 100%&quot;)
            errors = True
        rd.resolution_percentage = 100
        if rd.file_format != 'PNG':
            print(&quot;Renderfarm.fi always uses PNG for output. Changing to PNG.&quot;)
            self.report({'WARNING'}, &quot;Renderfarm.fi always uses PNG for output. Changing to PNG.&quot;)
            errors = True
        rd.file_format = 'PNG'
        if rd.color_mode != 'RGBA':
            print(&quot;Color mode must be set to RGBA. Changing to RGBA.&quot;)
            self.report({'WARNING'}, &quot;Color mode must be set to RGBA. Changing to RGBA.&quot;)
            errors = True
        rd.color_mode = 'RGBA'
        if (rd.use_sss == True or hasSSSMaterial()) and ore.parts &gt; 1:
            print(&quot;Subsurface Scattering is not supported when rendering with parts &gt; 1. Disabling&quot;)
            self.report({'WARNING'}, &quot;Subsurface Scattering is not supported when rendering with parts &gt; 1. Disabling&quot;)
            rd.use_sss = False # disabling because ore.parts &gt; 1. It's ok to use SSS with 1part/frame
            errors = True
        if hasUnsupportedSimulation() == True:
            print(&quot;An unsupported simulation was detected. Please check your settings and remove them&quot;)
            self.report({'WARNING'}, &quot;An unsupported simulation was detected. Please check your settings and remove them&quot;)
            errors = True
        rd.save_buffers = False
        rd.free_image_textures = True
        print(&quot;Done checking the scene. Now do a test render&quot;)
        self.report({'INFO'}, &quot;Done checking the scene. Now do a test render&quot;)
        print(&quot;=============================================&quot;)
        
        if (errors == True):
            self.report({'WARNING'}, &quot;Settings were changed or other issues found. Check console and do a test render to make sure everything works.&quot;)
        
        ore.prepared = True
        rd.engine = 'BLENDER_RENDER'
        bpy.ops.wm.save_mainfile()
        rd.engine = 'RENDERFARMFI_RENDER'
        
        return {'FINISHED'}

class ORE_ResetOp(bpy.types.Operator):
    bl_idname = &quot;ore.reset&quot;
    bl_label = &quot;Reset Preparation&quot;
    
    def execute(self, context):
        sce = context.scene
        sce.ore_render.prepared = False
        return {'FINISHED'}

class ORE_UploaderOp(bpy.types.Operator):
    bl_idname = &quot;ore.upload&quot;
    bl_label = &quot;Render on Renderfarm.fi&quot;
    
    def execute(self, context):
        rd = context.scene.render
        rd.engine = 'BLENDER_RENDER'
        bpy.ops.wm.save_mainfile()
        return ore_upload(self, context)

class ORE_UseBlenderReso(bpy.types.Operator):
    bl_idname = &quot;ore.use_scene_settings&quot;
    bl_label = &quot;Use Scene resolution&quot;
    
    def execute(self, context):
        sce = context.scene
        ore = sce.ore_render
        
        ore.resox = sce.render.resolution_x
        ore.resoy = sce.render.resolution_y
        
        return {'FINISHED'}

class ORE_ChangeUser(bpy.types.Operator):
    bl_idname = &quot;ore.change_user&quot;
    bl_label = &quot;Change user&quot;
    
    def execute(self, context):
        ore = context.scene.ore_render
        ore.password = ''
        ore.hash = ''
        
        return {'FINISHED'}

class RenderfarmFi(bpy.types.RenderEngine):
    bl_idname = 'RENDERFARMFI_RENDER'
    bl_label = &quot;Renderfarm.fi&quot;

    def render(self, scene):
        print('Do test renders with Blender Render')

def menu_export(self, context):
    import os
    default_path = os.path.splitext(bpy.data.filepath)[0] + &quot;.py&quot;
    self.layout.operator(RenderfarmFi.bl_idname, text=RenderfarmFi.bl_label)

def register():
    bpy.types.register(RenderfarmFi)
    bpy.types.register(ORE_OpenDownloadLocation)
    bpy.types.register(ORE_CancelSession)
    bpy.types.register(ORE_GetCompletedSessions)
    bpy.types.register(ORE_GetCancelledSessions)
    bpy.types.register(ORE_GetActiveSessions)
    bpy.types.register(ORE_GetPendingSessions)
    bpy.types.register(ORE_CheckUpdate)
    bpy.types.register(ORE_LoginOp)
    bpy.types.register(ORE_PrepareOp)
    bpy.types.register(ORE_ResetOp)
    bpy.types.register(ORE_UploaderOp)
    bpy.types.register(ORE_UseBlenderReso)
    bpy.types.register(ORE_ChangeUser)
    bpy.types.register(RENDERFARM_MT_Session)
    bpy.types.register(LOGIN_PT_RenderfarmFi)
    bpy.types.register(CHECK_PT_RenderfarmFi)
    bpy.types.register(SESSIONS_PT_RenderfarmFi)
    bpy.types.register(RENDER_PT_RenderfarmFi)
    bpy.types.INFO_MT_render.append(menu_export)

def unregister():
    bpy.types.unregister(ORESession)
    bpy.types.unregister(ORESettings)

if __name__ == &quot;__main__&quot;:
    register()

</pre>]]></description>
            <dc:creator>truffe</dc:creator>
            <category>Blender 2.5</category>
            <pubDate>Sun, 01 Aug 2010 19:38:06 +0200</pubDate>
        </item>
        <item>
            <guid>http://forum.vswarm.com/read.php?24,876,876#msg-876</guid>
            <title>2.5 fluid animation (2 replies)</title>
            <link>http://forum.vswarm.com/read.php?24,876,876#msg-876</link>
            <description><![CDATA[ Hello everybody, Is there any way of rendering a fluid simulation over vSwarm with blender 2.5. Ive attempted a render but no fluids were rendered only the defualt cube containing the fluid. many thanks in advance]]></description>
            <dc:creator>blueseal86</dc:creator>
            <category>Blender 2.5</category>
            <pubDate>Thu, 29 Jul 2010 11:32:11 +0200</pubDate>
        </item>
        <item>
            <guid>http://forum.vswarm.com/read.php?24,803,803#msg-803</guid>
            <title>My first render -&gt; not success:o:o (4 replies)</title>
            <link>http://forum.vswarm.com/read.php?24,803,803#msg-803</link>
            <description><![CDATA[ After learning that 2.52 is supported, I tried submit a sample scene of 20 frames.<br />
It consist of a few boxes forming a room with no external textures,<br />
but has AO and some advance lighting, reflection which I plan to use in my project.<br />
It took about 20 minutes per frame on my Q9550.<br />
sample render is at my blog <a href="http://busyb.wordpress.com/2010/05/05/my-room/" rel="nofollow" >here</a><br />
<br />
After a few minutes I notice my Q9400 machine was rendering my frame,<br />
so I monitor it and found out that it only use 2 cores despite the setting to 4.<br />
And render time increased so much as it exceed 60 minutes only at 86%<br />
<br />
My own machine is the first to reach this point, means it's the fastest machine in the 9 that's rendering at the moment.<br />
<br />
My Q9550 machine soon started rendering my frame too, and I noticed it use only 2 cores as well.<br />
<br />
On the Q9400, after 86% the client then said job finished and try to upload the result.<br />
After a few minutes it say cannot upload 'cause the file is too big.(I use EXR)<br />
But I doubt my frame is ever finished at all. so I abort the job.<br />
<br />
<u>A few notices from my first experience :</u><br />
<br />
- the client won't use all my 4 cores.<br />
- most machines in the cloud are slow, way too slow to finish a frame with 1 hour time limit.<br />
   time limit should be vary by the node's computing power. or maybe extended a little?<br />
   ability to use many machine to render a portion of a frame would be the best solution.<br />
- is there a file size limit on the server that prevent a finished frame to upload properly?<br />
<br />
<br />
Well, I'm gonna try again with my less complex scene, soon.]]></description>
            <dc:creator>boyleo</dc:creator>
            <category>Blender 2.5</category>
            <pubDate>Sat, 15 May 2010 15:24:00 +0200</pubDate>
        </item>
    </channel>
</rss>
