From b6b5496085bf5adac74e3e14385b60995b910249 Mon Sep 17 00:00:00 2001 From: Luca Bonavita Date: Tue, 20 Jul 2010 20:47:38 +0000 Subject: == addons == - moved renderfarm to render_renderfarmfi.py - fixed bl_addon_info: new wiki page, tracker page, category --- render_renderfarmfi.py | 799 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 799 insertions(+) create mode 100644 render_renderfarmfi.py (limited to 'render_renderfarmfi.py') diff --git a/render_renderfarmfi.py b/render_renderfarmfi.py new file mode 100644 index 00000000..9c2db3c7 --- /dev/null +++ b/render_renderfarmfi.py @@ -0,0 +1,799 @@ +# ##### 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 , Jesse Kaukonen ', + 'version': str(bpy.CURRENT_VERSION), + 'blender': (2, 5, 3), + 'location': 'Render > Engine > Renderfarm.fi', + 'description': 'Send .blend as session to http://www.renderfarm.fi 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&aid=22927&group_id=153&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 = "render" + # 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 = "Show Session" + + 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("RENDERFARM_MT_Session") + 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 = "Scene Settings" + 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="%s"' % field_name, + '', str(data[field_name])) + + def encode_file(field_name): + import codecs + filename = files [field_name] + return ('--' + boundary, + 'Content-Disposition: form-data; name="%s"; filename="%s"' % (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, "rb") + 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)>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 > 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) > 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)>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']) > 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) > 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) > 0: + self.report({'WARNING'}, "Found particle system") + print("Found particle system") + 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'}, "Found simulation: " + str(t)) + print("Found simulation: " + 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) > 0: + ore.prepared = False + return {'CANCELLED'} + + rd = sce.render + print("=============================================") + rd.threads_mode = 'FIXED' + rd.threads = 1 + rd.resolution_x = ore.resox + rd.resolution_y = ore.resoy + if (rd.resolution_percentage != 100): + print("Resolution percentage is not 100. Changing to 100%") + self.report({'WARNING'}, "Resolution percentage is not 100. Changing to 100%") + errors = True + rd.resolution_percentage = 100 + if rd.file_format != 'PNG': + print("Renderfarm.fi always uses PNG for output. Changing to PNG.") + self.report({'WARNING'}, "Renderfarm.fi always uses PNG for output. Changing to PNG.") + errors = True + rd.file_format = 'PNG' + if rd.color_mode != 'RGBA': + print("Color mode must be set to RGBA. Changing to RGBA.") + self.report({'WARNING'}, "Color mode must be set to RGBA. Changing to RGBA.") + errors = True + rd.color_mode = 'RGBA' + if (rd.use_sss == True or hasSSSMaterial())and ore.parts > 1: + print("Subsurface Scattering is not supported when rendering with parts > 1. Disabling") + self.report({'WARNING'}, "Subsurface Scattering is not supported when rendering with parts > 1. Disabling") + errors = True + if hasUnsupportedSimulation() == True: + print("An unsupported simulation was detected. Please check your settings and remove them") + self.report({'WARNING'}, "An unsupported simulation was detected. Please check your settings and remove them") + errors = True + rd.use_sss = False + rd.save_buffers = False + rd.free_image_textures = True + print("Done checking the scene. Now do a test render") + self.report({'INFO'}, "Done checking the scene. Now do a test render") + print("=============================================") + + if (errors == True): + self.report({'WARNING'}, "Settings were changed or other issues found. Check console and do a test render to make sure everything works.") + + 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 = "ore.reset" + bl_label = "Reset Preparation" + + def execute(self, context): + sce = context.scene + sce.ore_render.prepared = False + return {'FINISHED'} + +class ORE_UploaderOp(bpy.types.Operator): + bl_idname = "ore.upload" + bl_label = "Render on Renderfarm.fi" + + 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 = "ore.use_scene_settings" + bl_label = "Use Scene resolution" + + 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 = "ore.change_user" + bl_label = "Change user" + + 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 = "Renderfarm.fi" + + 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] + ".py" + 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__ == "__main__": + register() -- cgit v1.2.3