diff options
author | Jesse Kaukonen <jesse.kaukonen@gmail.com> | 2011-09-29 12:02:49 +0400 |
---|---|---|
committer | Jesse Kaukonen <jesse.kaukonen@gmail.com> | 2011-09-29 12:02:49 +0400 |
commit | f51dee9e5108b93205c56d0bf2d1a55b6a4f1ae1 (patch) | |
tree | e29d2a34efa7bf391aec8449738c1b44bbb487ef /render_renderfarmfi.py | |
parent | a088b57ec15c1b628b3b32c5d47b4cc9173a4d4c (diff) |
Uploader version 9 features:
- You must now log in first before doing anything. Old system did everything in one call, while this new system has 3 calls:
1: Login and check password, downloading session information
2: Do optional session list refreshing
3: Handle file uploads to the service
- Changed the UI:
* You can no longer edit ore_resox or the other ore settings. These are copied from Blender's render settings directly
* You can change ore parts and ore memory usage, but these are tagged as "optional advanced settings"
* There is now a link to the Renderfarm.fi render panel in the main render panel. You can easily switch between Blender Render and Renderfarm.fi render
* The UI gives you visible errors instead of hiding these in the console, although not all errors are visible
- The preparation is performed once the user presses "upload" or changes to the Renderfarm.fi tab
* This no longer stops the upload, but instead gives a warning if there are issues
* If a texture is not found, give a warning
* If a linked file is not found, give a warning
- The file is no longer saved into the original master file, but a copy is created with the name "renderfarm.blend".
- Short description field was removed. This still exists code-wise, but it's simply filled with a dummy letter. Instead, the UI asks for simply "description" and "tags". Tags might be implemented soon-ish(tm).
- The old method of listing and canceling sessions is completely re-written:
* The new system fetches out all the user's sessions and stores them in lists, then fetching what is required. The old system required a new XMLRPC call if you wanted to switch your selected list from one to another such as "completed" to "canceled". I removed this "list by session type" -feature entirely and simply added one list that has everything. The sessions still have the % complete next to the name.
* Canceling works like before, except it gives a visible error if canceling isn't possible (ie session is already running or rejected)
* There is a refresh button that fetches out new listings from the server
- Particles generate a warning:
* If there are emitter type particles, recommend checking particle baking
* If there are hair type particles with child_type 'SIMPLE', change the mode to 'INTERPOLATED'. This seems to fix most of our problems. Also shows a note about this
- Fluid simulations generate a warning about them not working at all. This won't prevent uploading.
- Possibly some tiny fixes I forgot to mention
Diffstat (limited to 'render_renderfarmfi.py')
-rw-r--r-- | render_renderfarmfi.py | 992 |
1 files changed, 526 insertions, 466 deletions
diff --git a/render_renderfarmfi.py b/render_renderfarmfi.py index 0f72eb40..5ca4b8bc 100644 --- a/render_renderfarmfi.py +++ b/render_renderfarmfi.py @@ -19,9 +19,9 @@ bl_info = { "name": "Renderfarm.fi", "author": "Nathan Letwory <nathan@letworyinteractive.com>, Jesse Kaukonen <jesse.kaukonen@gmail.com>", - "version": (8,), - "blender": (2, 5, 7), - "api": 36487, + "version": (9,), + "blender": (2, 5, 9), + "api": 40652, "location": "Render > Engine > Renderfarm.fi", "description": "Send .blend as session to http://www.renderfarm.fi to render", "warning": "", @@ -42,6 +42,7 @@ import http.client import xmlrpc.client import math from os.path import isabs, isfile +import time from bpy.props import PointerProperty, StringProperty, BoolProperty, EnumProperty, IntProperty, CollectionProperty @@ -58,6 +59,7 @@ bpy.errorMessages = { bpy.statusMessage = { 'title': 'TRIA_RIGHT', 'shortdesc': 'TRIA_RIGHT', + 'tags': 'TRIA_RIGHT', 'longdesc': 'TRIA_RIGHT', 'username': 'TRIA_RIGHT', 'password': 'TRIA_RIGHT' @@ -65,7 +67,24 @@ bpy.statusMessage = { bpy.errors = [] bpy.ore_sessions = [] +bpy.ore_completed_sessions = [] +bpy.ore_active_sessions = [] +bpy.ore_rejected_sessions = [] +bpy.ore_pending_sessions = [] +bpy.ore_active_session_queue = [] +bpy.ore_complete_session_queue = [] bpy.queue_selected = -1 +bpy.errorStartTime = -1.0 +bpy.infoError = False +bpy.cancelError = False +bpy.texturePackError = False +bpy.linkedFileError = False +bpy.uploadInProgress = False +bpy.originalFileName = bpy.path.display_name_from_filepath(bpy.data.filepath) +bpy.particleBakeWarning = False +bpy.childParticleWarning = False +bpy.simulationWarning = False +bpy.ready = False def renderEngine(render_engine): bpy.utils.register_class(render_engine) @@ -88,12 +107,13 @@ class ORESettings(bpy.types.PropertyGroup): username = StringProperty(name='E-mail', description='E-mail for Renderfarm.fi', maxlen=256, default='') password = StringProperty(name='Password', description='Renderfarm.fi password', maxlen=256, default='') hash = StringProperty(name='Hash', description='hash calculated out of credentials', maxlen=33, default='') - - shortdesc = StringProperty(name='Short description', description='A short description of the scene (100 characters)', maxlen=101, default='') - longdesc = StringProperty(name='Long description', description='A more elaborate description of the scene (2k)', maxlen=2048, default='') + + shortdesc = StringProperty(name='Short description', description='A short description of the scene (100 characters)', maxlen=101, default='-') + tags = StringProperty(name='Tags', description='A list of tags that best suit the animation', maxlen=102, default='') + longdesc = StringProperty(name='Description', description='Description of the scene (2k)', maxlen=2048, default='') title = StringProperty(name='Title', description='Title for this session (128 characters)', maxlen=128, default='') url = StringProperty(name='Project URL', description='Project URL. Leave empty if not applicable', maxlen=256, default='') - + parts = IntProperty(name='Parts/Frame', description='', min=1, max=1000, soft_min=1, soft_max=64, default=1) resox = IntProperty(name='Resolution X', description='X of render', min=1, max=10000, soft_min=1, soft_max=10000, default=1920) resoy = IntProperty(name='Resolution Y', description='Y of render', min=1, max=10000, soft_min=1, soft_max=10000, default=1080) @@ -101,15 +121,22 @@ class ORESettings(bpy.types.PropertyGroup): start = IntProperty(name='Start Frame', description='Start Frame', default=1) end = IntProperty(name='End Frame', description='End Frame', default=250) fps = IntProperty(name='FPS', description='FPS', min=1, max=256, default=25) - + prepared = BoolProperty(name='Prepared', description='Set to True if preparation has been run', default=False) + loginInserted = BoolProperty(name='LoginInserted', description='Set to True if user has logged in', default=False) + passwordCorrect = BoolProperty(name='PasswordCorrect', description='Set to False if the password is incorrect', default=True) debug = BoolProperty(name='Debug', description='Verbose output in console', default=False) selected_session = IntProperty(name='Selected Session', description='The selected session', default=0) hasUnsupportedSimulation = BoolProperty(name='HasSimulation', description='Set to True if therea re unsupported simulations', default=False) - + inlicense = EnumProperty(items=licenses, name='source license', description='license speficied for the source files', default='1') outlicense = EnumProperty(items=licenses, name='output license', description='license speficied for the output files', default='1') sessions = CollectionProperty(type=ORESession, name='Sessions', description='Sessions on Renderfarm.fi') + completed_sessions = CollectionProperty(type=ORESession, name='Completed sessions', description='Sessions that have been already rendered') + rejected_sessions = CollectionProperty(type=ORESession, name='Rejected sessions', description='Sessions that have been rejected') + pending_sessions = CollectionProperty(type=ORESession, name='Pending sessions', description='Sessions that are waiting for approval') + active_sessions = CollectionProperty(type=ORESession, name='Active sessions', description='Sessions that are currently rendering') + all_sessions = CollectionProperty(type=ORESession, name='All sessions', description='List of all of the users sessions') # session struct @@ -143,159 +170,209 @@ for member in dir(properties_object): except: pass del properties_object +def hasSSSMaterial(): + for m in bpy.data.materials: + if m.subsurface_scattering.use: + return True + return False + +def tuneParticles(): + for p in bpy.data.particles: + if (p.type == 'EMITTER'): + bpy.particleBakeWarning = True + if (p.type == 'HAIR'): + if (p.child_type == 'SIMPLE'): + p.child_type = 'INTERPOLATED' + bpy.childParticleWarning = True + +def hasParticleSystem(): + if (len(bpy.data.particles) > 0): + 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): + 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() + +def isFilterNode(node): + t = type(node) + return t==bpy.types.CompositorNodeBlur or t==bpy.types.CompositorNodeDBlur + +def changeSettings(): + + sce = bpy.context.scene + rd = sce.render + ore = sce.ore_render + + # Necessary settings for BURP + ore.resox = rd.resolution_x + ore.resoy = rd.resolution_y + ore.start = sce.frame_start + ore.end = sce.frame_end + ore.fps = rd.fps + + # Multipart support doesn' work if SSS is used + if ((rd.use_sss == True and hasSSSMaterial()) and ore.parts > 1): + ore.parts = 1; + + if (hasParticleSystem()): + tuneParticles() + else: + bpy.particleBakeWarning = False + bpy.childParticleWarning = False + + if (hasUnsupportedSimulation()): + simulationWarning = True + else: + bpy.simulationWarning = False + +def prepareScene(): + sce = bpy.context.scene + rd = sce.render + ore = sce.ore_render + + changeSettings() + + print("Packing external textures...") + # Pack all external textures + try: + bpy.ops.file.pack_all() + bpy.texturePackError = False + except Exception as e: + bpy.texturePackError = True + print(e) + + linkedData = bpy.utils.blend_paths() + if (len(linkedData) > 0): + print("Appending linked .blend files...") + try: + bpy.ops.object.make_local(type='ALL') + bpy.linkedFileError = False + except Exception as e: + bpy.linkedFileError = True + print(e) + else: + print("No external .blends used, skipping...") + + # Save with a different name + print("Saving into a new file...") + try: + # If the filename is empty, we'll make one from the path of the Blender installation + if (len(bpy.originalFileName) == 0): + bpy.originalFileName = bpy.utils.resource_path(type='LOCAL') + "renderfarm.blend" + bpy.ops.wm.save_mainfile(filepath=bpy.originalFileName) + else: + savePath = bpy.originalFileName + savePath = savePath + "_renderfarm" + bpy.ops.wm.save_mainfile(filepath=savePath) + except Exception as e: + print(e) + + print(".blend prepared") + class RenderButtonsPanel(): 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 -class SUMMARY_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): - # Prints a summary to the panel before uploading. If scene settings differ from ore settings, then display a warning icon - bl_label = 'Summary' - bl_options = {'DEFAULT_CLOSED'} - COMPAT_ENGINES = set(['RENDERFARMFI_RENDER']) +class OpSwitchRenderfarm(bpy.types.Operator): + bl_label = "Switch to Renderfarm.fi" + bl_idname = "ore.switch_to_renderfarm_render" - @classmethod - def poll(cls, context): - rd = context.scene.render - return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES) + def execute(self, context): + changeSettings() + bpy.context.scene.render.engine = 'RENDERFARMFI_RENDER' + return {'FINISHED'} + +class OpSwitchBlenderRender(bpy.types.Operator): + bl_label = "Switch to Blender Render" + bl_idname = "ore.switch_to_blender_render" + def execute(self, context): + bpy.context.scene.render.engine = 'BLENDER_RENDER' + return {'FINISHED'} + +# We re-write the default render panel +class RENDER_PT_render(RenderButtonsPanel, bpy.types.Panel): + bl_label = "Render" + COMPAT_ENGINES = {'BLENDER_RENDER'} def draw(self, context): - sce = context.scene - rd = context.scene.render - ore = context.scene.ore_render layout = self.layout - problems = False - - # Check if correct resolution is set - if rd.resolution_x != ore.resox: - layout.label(text='Resolution X: ' + str(ore.resox), icon='ERROR') - problems = True - else: - layout.label(text='Resolution X: ' + str(ore.resox), icon='FILE_TICK') - if rd.resolution_y != ore.resoy: - layout.label(text='Resolution Y: ' + str(ore.resoy), icon='ERROR') - problems = True - else: - layout.label(text='Resolution Y: ' + str(ore.resoy), icon='FILE_TICK') - - # Check if correct number of frames is specified - if (sce.frame_start != ore.start) and not ( (sce.frame_start == ore.start and sce.frame_end == ore.end) and sce.frame_start == sce.frame_end): - layout.label(text='Start frame: ' + str(ore.start), icon='ERROR') - layout.label(text='.blend Start frame is different to the one specified in the uploader script. Please verify!') - problems = True - else: - layout.label(text='Start frame: ' + str(ore.start), icon='FILE_TICK') - if (sce.frame_end != ore.end) and not ( (sce.frame_start == ore.start and sce.frame_end == ore.end) and sce.frame_start == sce.frame_end): - layout.label(text='End frame: ' + str(ore.end), icon='ERROR') - layout.label(text='.blend End frame is different to the one specified in the uploader script. Please verify!') - problems = True - else: - layout.label(text='End frame: ' + str(ore.end), icon='FILE_TICK') - - # Check if more than 1 frame is specified - if (sce.frame_start == ore.start and sce.frame_end == ore.end) and (sce.frame_start == sce.frame_end): - layout.label(text='Only one frame specified to be rendered!') - layout.label(text='This is highly ineffective when using distributed rendering') - problems = True - - if rd.resolution_percentage != 100: - layout.label(text='Resolution percentage: ' + str(rd.resolution_percentage), icon='ERROR') - problems = True - else: - layout.label(text='Resolution percentage: ' + str(rd.resolution_percentage), icon='FILE_TICK') - - if rd.file_format != 'PNG': - layout.label(text='Output format: ' + rd.file_format, icon='ERROR') - layout.label(text='Output format must be set to PNG') - problems = True - else: - layout.label(text='Output format: ' + rd.file_format, icon='FILE_TICK') - - if ore.parts > 1 and rd.use_sss == True: - layout.label(text='Subsurface Scattering: ' + str(rd.use_sss), icon='ERROR') - layout.label(text='If you want to use SSS, parts must be set to 1') - problems = True - else: - layout.label(text='Subsurface Scattering: ' + str(rd.use_sss), icon='FILE_TICK') - - if rd.use_compositing == False: - layout.label(text='Composite nodes: ' + str(rd.use_compositing), icon='ERROR') - layout.label(text='Composite nodes are disabled.') - layout.label(text='The script automatically disables them if: ') - layout.label(text='- Filter type nodes are used and parts are more than 1') - layout.label(text='- There is an output node') - problems = True - else: - layout.label(text='Composite nodes: ' + str(rd.use_compositing), icon='FILE_TICK') - - if rd.use_save_buffers: - layout.label(text='Save buffers: ' + str(rd.use_save_buffers), icon='ERROR') - layout.label(text='Save buffers must be disabled') - layout.label(text='Can only disabled if Full Sample is turned off') - problems = True - else: - layout.label(text='Save buffers: ' + str(rd.use_save_buffers), icon='FILE_TICK') - - if rd.use_border: - layout.label(text='Border render: ' + str(rd.use_border), icon='ERROR') - layout.label(text='Border render must be disabled') - else: - layout.label(text='Border render: ' + str(rd.use_border), icon='FILE_TICK') - - if rd.threads_mode != 'FIXED' or rd.threads > 1: - layout.label(text='Threads: ' + rd.threads_mode + ' ' + str(rd.threads), icon='ERROR') - layout.label(text='Threads must be set to Fixed, 1') - problems = True - else: - layout.label(text='Threads: ' + rd.threads_mode + ' ' + str(rd.threads), icon='FILE_TICK') - - if ore.hasUnsupportedSimulation == True: - layout.label(text='There is an unsupported simulation', icon='ERROR') - layout.label(text='Fluid/smoke/cloth/collision/softbody simulations are not supported') - problems = True - else: - layout.label(text='No unsupported simulations found', icon='FILE_TICK') - - if ore.prepared == False: - layout.label(text='The script reports "not ready".', icon='ERROR') - layout.label(text='Please review the settings above') - layout.label(text='If everything is in order, click Check Scene again') - layout.label(text='The script automatically changes settings, so make sure they are correct') + rd = context.scene.render + row = layout.row() + row.operator("ore.switch_to_renderfarm_render", text="Renderfarm.fi", icon='WORLD') + row.operator("ore.switch_to_blender_render", text="Blender Render", icon='BLENDER') + row = layout.row() + if (bpy.context.scene.render.engine == 'BLENDER_RENDER'): + row.operator("render.render", text="Image", icon='RENDER_STILL') + row.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True + layout.prop(rd, "display_mode", text="Display") else: - layout.label(text='The script reports "All settings ok!"', icon='FILE_TICK') - layout.label(text='Please render one frame using Blender Render first') - row = layout.row() - row.operator('ore.test_render') - layout.label(text='If you are sure that the render works, click Render on Renderfarm.fi') + 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 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') + ore = context.scene.ore_render + + if (ore.loginInserted == True): + layout.operator('ore.completed_sessions') + layout.operator('ore.accept_sessions') + layout.operator('ore.active_sessions') + layout.separator() + layout.operator('ore.cancelled_sessions') + else: + row = layout.row() + row.label(text="You must login first") class LOGIN_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): bl_label = 'Login to Renderfarm.fi' COMPAT_ENGINES = set(['RENDERFARMFI_RENDER']) - + @classmethod def poll(cls, context): rd = context.scene.render return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES) - + def draw(self, context): layout = self.layout - # XXX layout.operator('ore.check_update') ore = context.scene.ore_render checkStatus(ore) - + + if (ore.passwordCorrect == False): + row = layout.row() + row.label(text="Email or password missing/incorrect", icon='ERROR') if ore.hash=='': col = layout.column() if ore.hash=='': @@ -303,56 +380,38 @@ class LOGIN_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): col.prop(ore, 'password', icon=bpy.statusMessage['password']) layout.operator('ore.login') else: - layout.label(text='E-mail and password entered.', icon='INFO') + layout.label(text='Successfully logged in', icon='INFO') layout.operator('ore.change_user') -class CHECK_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): - bl_label = 'Check for updates' - COMPAT_ENGINES = set(['RENDERFARMFI_RENDER']) - - @classmethod - def poll(cls, context): - rd = context.scene.render - return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES) - - def draw(self, context): - layout = self.layout - - 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, bpy.types.Panel): - bl_label = 'Sessions' + bl_label = 'My sessions' COMPAT_ENGINES = set(['RENDERFARMFI_RENDER']) - + @classmethod def poll(cls, context): rd = context.scene.render return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES) - + 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: + if (ore.passwordCorrect == True and ore.loginInserted == True): + layout = self.layout + + layout.template_list(ore, 'all_sessions', ore, 'selected_session', rows=5) layout.operator('ore.cancel_session') + if (bpy.cancelError == True): + layout.label("This session cannot be cancelled") + errorTime = time.time() - bpy.errorStartTime + if (errorTime > 4): + bpy.cancelError = False + bpy.errorStartTime = -1 + layout.operator('ore.refresh_session_list') + else: + layout = self.layout + layout.label(text="You must login first") -class CONDITIONS_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): - bl_label = "IMPORTANT: Rendering on Renderfarm.fi" +class RENDER_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): + bl_label = "Settings" COMPAT_ENGINES = set(['RENDERFARMFI_RENDER']) @classmethod @@ -362,22 +421,30 @@ class CONDITIONS_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): def draw(self, context): layout = self.layout + sce = context.scene + ore = sce.ore_render + rd = sce.render - layout.label(text='- The render must take more than 50 seconds / frame') - layout.label(text='- The animation must be at least 20 frames long') - layout.label(text='- No still renders') - layout.label(text='- All external data must be included:') - layout.label(text=' * Linked files: L in object mode') - layout.label(text=' * Textures: File menu -> External Data') - layout.label(text='- No Python scripts') - layout.label(text='- Memory usage max 3GB') - layout.label(text='- If your render takes more than an hour / frame:') - layout.label(text=' * No filter type composite nodes (blur, glare etc.)') - layout.label(text=' * No SSS') - layout.label(text=' * No Motion Blur') + if (ore.passwordCorrect == False or ore.loginInserted == False): + layout.label(text='You must login first') + else: + layout.prop(ore, 'title', icon=bpy.statusMessage['title']) + layout.label(text="Example: Blue Skies project, scene 8") + # layout.prop(ore, 'shortdesc', icon=bpy.statusMessage['shortdesc']) + layout.prop(ore, 'longdesc', icon=bpy.statusMessage['longdesc']) + layout.label(text="Example: In this shot the main hero is running across a flowery field towards the castle.") + layout.prop(ore, 'tags', icon=bpy.statusMessage['tags']) + layout.label(text="Example: blue skies hero castle flowers grass particles") + layout.prop(ore, 'url') + layout.label(text="Example: www.sintel.org") + checkStatus(ore) + if (len(bpy.errors) > 0): + bpy.ready = False + else: + bpy.ready = True -class RENDER_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): - bl_label = "Scene Settings" +class UPLOAD_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): + bl_label = "Upload" COMPAT_ENGINES = set(['RENDERFARMFI_RENDER']) @classmethod @@ -389,41 +456,84 @@ class RENDER_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel): 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() - - layout.separator() - row = layout.row() - row.prop(ore, 'inlicense') - row.prop(ore, 'outlicense') - - layout.separator() - row = layout.row() - row.operator('ore.upload') - layout.label(text='Blender may seem frozen during the upload!') - row.operator('ore.reset', icon='FILE_REFRESH') + rd = sce.render + if (ore.passwordCorrect == False or ore.loginInserted == False): + layout.label(text="You must login first") 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') + if (bpy.ready): + layout.label(text="Policies", icon='LAMP') + layout.label(text="- The animation must be at least 20 frames long") + layout.label(text="- No still renders") + layout.label(text="- No Python scripts") + layout.label(text="- Memory usage max 3GB") + layout.label(text="- If your render takes more than an hour / frame:") + layout.label(text=" * No filter type composite nodes (blur, glare etc.)") + layout.label(text=" * No SSS") + layout.label(text=" * No Motion Blur") + + layout.separator() + + layout.label(text="Please verify your settings", icon='MODIFIER') + row = layout.row() + row.label(text="Resolution: " + str(ore.resox) + "x" + str(ore.resoy)) + row = layout.row() + row.label(text="Frames: " + str(ore.start) + " - " + str(ore.end)) + row = layout.row() + if (ore.start == ore.end): + row.label(text="You have selected only 1 frame to be rendered", icon='ERROR') + row = layout.row() + row.label(text="Renderfarm.fi does not render stills - only animations") + row = layout.row() + row.label(text="Frame rate: " + str(ore.fps)) + row = layout.row() + layout.separator() + + layout.label(text="Optional advanced settings", icon='MODIFIER') + row = layout.row() + row.prop(ore, 'memusage') + row.prop(ore, 'parts') + layout.separator() + row = layout.row() + + layout.label(text="Licenses", icon='FILE_REFRESH') + row = layout.row() + row.prop(ore, 'inlicense') + row.prop(ore, 'outlicense') + + row = layout.row() + if (bpy.uploadInProgress == True): + layout.label(text="Attempting upload...") + if (bpy.texturePackError): + layout.label(text="There was an error in packing external textures", icon='ERROR') + layout.label(text="Make sure that all your textures exist on your computer") + layout.label(text="The render will still work, but won't have the missing textures") + layout.label(text="You may want to cancel your render above") + if (bpy.linkedFileError): + layout.label(text="There was an error in appending linked .blend files", icon='ERROR') + layout.label(text="Your render might not have all the external content") + layout.label(text="You may want to cancel your render above") + if (bpy.particleBakeWarning): + layout.label(text="You have a particle simulation", icon='ERROR') + layout.label(text="All Emitter type particles must be baked") + if (bpy.childParticleWarning): + layout.label(text="Child particle mode changed!", icon='ERROR') + layout.label(text="Renderfarm.fi requires that you use 'Interpolated'") + if (bpy.simulationWarning): + layout.label(text="There is a simulation!", icon='ERROR') + layout.label(text="- Fluid simulations aren't supported") + layout.label(text="- Collision simulations must be baked") + row = layout.row() + row.operator('ore.upload', icon='FILE_TICK') + if (bpy.infoError == True): + layout.label("You must fill in the scene info first", icon='ERROR') + errorTime = time.time() - bpy.errorStartTime + if (errorTime > 4): + bpy.infoError = False + bpy.errorStartTime = -1 + layout.label(text="Blender may seem frozen during the upload!", icon='LAMP') + row.operator('ore.reset', icon='FILE_REFRESH') + else: + layout.label(text="Fill the scene information first") def random_string(length): import string @@ -432,22 +542,22 @@ def random_string(length): 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): 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)) @@ -455,10 +565,10 @@ def encode_multipart_data(data, 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): @@ -488,12 +598,13 @@ def upload_file(key, userid, sessionid, server, path): 'sessionId': sessionid, 'md5sum': md5_for_file(path) } + print("d") files = { 'blenderfile': path } - + print("e") r = send_post(server, data, files) - + print("f") #print 'Uploaded %r' % (path) return r @@ -502,14 +613,18 @@ 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!') + print("Done!") return o[0][0] def ore_upload(op, context): sce = context.scene ore = sce.ore_render - if not ore.prepared: + + if not bpy.ready: op.report(set(['ERROR']), 'Your user or scene information is not complete') + bpy.infoError = True + bpy.errorStartTime = time.time() + bpy.context.scene.render.engine = 'RENDERFARMFI_RENDER' return {'CANCELLED'} try: authproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/auth') @@ -541,12 +656,16 @@ def ore_upload(op, context): res = proxy.session.submit(userid, res['key'], sessionid) op.report(set(['INFO']), 'Submission sent to Renderfarm.fi') except xmlrpc.client.Error as v: + bpy.context.scene.render.engine = 'RENDERFARMFI_RENDER' print('ERROR:', v) op.report(set(['ERROR']), 'An error occurred while sending submission to Renderfarm.fi') except Exception as e: + bpy.context.scene.render.engine = 'RENDERFARMFI_RENDER' print('Unhandled error:', e) op.report(set(['ERROR']), 'An error occurred while sending submission to Renderfarm.fi') + bpy.context.scene.render.engine = 'RENDERFARMFI_RENDER' + doRefresh() return {'FINISHED'} def setStatus(property, status): @@ -561,22 +680,23 @@ def showStatus(layoutform, property, message): 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') + bpy.infoError = True 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 @@ -585,7 +705,7 @@ class OreSession: self.endframe = 0 self.rendertime = 0 self.percentage = 0 - + def percentageComplete(self): totFrames = self.endframe - self.startframe if totFrames != 0: @@ -598,31 +718,90 @@ class OreSession: return done def xmlSessionsToOreSessions(sessions, queue): - bpy.ore_sessions = [] - completed = sessions[queue] - for sid in completed: - s = completed[sid]['title'] - # t = completed[sid]['timestamps'] # UNUSED + #bpy.ore_sessions = [] + output = [] + sessionFilter = [] + sessionFilter = sessions[queue] + for sid in sessionFilter: + s = sessionFilter[sid]['title'] + t = sessionFilter[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] + if queue in ('completed', 'active'): + sinfo.frames = sessionFilter[sid]['framesRendered'] + sinfo.startframe = sessionFilter[sid]['startFrame'] + sinfo.endframe = sessionFilter[sid]['endFrame'] + #bpy.ore_sessions.append(sinfo) + output.append(sinfo) + return output + +def doRefresh(): + sce = bpy.context.scene + ore = sce.ore_render + try: + userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user') + sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'completed') + bpy.ore_sessions = [] + bpy.ore_sessions = xmlSessionsToOreSessions(sessions, 'completed') + bpy.ore_completed_sessions = bpy.ore_sessions + bpy.ore_cancelled_sessions = xmlSessionsToOreSessions(sessions, 'canceled') + sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'accept') + bpy.ore_pending_sessions = xmlSessionsToOreSessions(sessions, 'accept') + sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'active') + bpy.ore_active_sessions = xmlSessionsToOreSessions(sessions, 'active') + + updateCompleteSessionList(ore) + + return 0 + except xmlrpc.client.Error as v: + self.report({'WARNING'}, "Error at refresh") + print(v) + return 1 + +class ORE_RefreshOp(bpy.types.Operator): + bl_idname = 'ore.refresh_session_list' + bl_label = 'Refresh' + + def execute(self, context): + result = doRefresh() + if (result == 0): + return {'FINISHED'} + else: + return {'CANCELLED'} + +def updateSessionList(session_list, ore): + while(len(session_list) > 0): + session_list.remove(0) + + for s in bpy.ore_active_session_queue: + session_list.add() + session = session_list[-1] session.name = s.title + ' [' + str(s.percentageComplete()) + '% complete]' +def updateCompleteSessionList(ore): + all_sessions = [] + + bpy.ore_active_session_queue = bpy.ore_cancelled_sessions + updateSessionList(ore.rejected_sessions, ore) + bpy.ore_active_session_queue = bpy.ore_active_sessions + updateSessionList(ore.active_sessions, ore) + bpy.ore_active_session_queue = bpy.ore_pending_sessions + updateSessionList(ore.pending_sessions, ore) + bpy.ore_active_session_queue = bpy.ore_completed_sessions + updateSessionList(ore.completed_sessions, ore) + + bpy.ore_complete_session_queue = [] + bpy.ore_complete_session_queue.extend(bpy.ore_pending_sessions) + bpy.ore_complete_session_queue.extend(bpy.ore_active_sessions) + bpy.ore_complete_session_queue.extend(bpy.ore_completed_sessions) + bpy.ore_complete_session_queue.extend(bpy.ore_cancelled_sessions) + + bpy.ore_active_session_queue = bpy.ore_complete_session_queue + updateSessionList(ore.all_sessions, ore) + 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) @@ -631,97 +810,80 @@ class ORE_OpenDownloadLocation(bpy.types.Operator): 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] + s = bpy.ore_complete_session_queue[ore.selected_session] try: userproxy.user.cancelSession(ore.username, ore.hash, int(s.id)) + doRefresh() 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) - + bpy.cancelError = True + bpy.errorStartTime = time.time() + return {'FINISHED'} class ORE_GetCompletedSessions(bpy.types.Operator): bl_idname = 'ore.completed_sessions' bl_label = 'Completed sessions' - + 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) - + bpy.ore_active_session_queue = bpy.ore_completed_sessions + updateSessionList(completed_sessions, ore) + return {'FINISHED'} class ORE_GetCancelledSessions(bpy.types.Operator): bl_idname = 'ore.cancelled_sessions' bl_label = 'Cancelled sessions' - + 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) - + bpy.ore_active_session_queue = bpy.ore_cancelled_sessions + updateSessionList(cancelled_sessions, ore) + return {'FINISHED'} class ORE_GetActiveSessions(bpy.types.Operator): bl_idname = 'ore.active_sessions' bl_label = 'Rendering sessions' - + 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) - + bpy.ore_active_session_queue = bpy.ore_active_sessions + updateSessionList(active_sessions, 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 sessions' - + 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) - + bpy.ore_active_session_queue = bpy.ore_pending_sessions + updateSessionList(pending_sessions, ore) + return {'FINISHED'} class ORE_CheckUpdate(bpy.types.Operator): bl_idname = 'ore.check_update' - bl_label = 'Check for new version' - + bl_label = 'Check for a new version' + def execute(self, context): blenderproxy = xmlrpc.client.ServerProxy(r'http://xmlrpc.renderfarm.fi/blender') try: @@ -737,184 +899,70 @@ class ORE_CheckUpdate(bpy.types.Operator): 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' - + bl_label = 'Login' + 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) + ore.loginInserted = False - if len(bpy.errors) > 0: - ore.prepared = False + try: + userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user') + sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'completed') + bpy.ore_sessions = xmlSessionsToOreSessions(sessions, 'completed') + bpy.ore_completed_sessions = bpy.ore_sessions + bpy.ore_cancelled_sessions = xmlSessionsToOreSessions(sessions, 'canceled') + sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'accept') + bpy.ore_pending_sessions = xmlSessionsToOreSessions(sessions, 'accept') + sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'active') + bpy.ore_active_sessions = xmlSessionsToOreSessions(sessions, 'active') + + bpy.ore_active_session_queue = bpy.ore_completed_sessions + updateSessionList(ore.completed_sessions, ore) + + bpy.ore_active_session_queue = bpy.ore_pending_sessions + updateSessionList(ore.pending_sessions, ore) + + bpy.ore_active_session_queue = bpy.ore_active_sessions + updateSessionList(ore.active_sessions, ore) + + bpy.ore_active_session_queue = bpy.ore_cancelled_sessions + updateSessionList(ore.rejected_sessions, ore) + + ore.passwordCorrect = True + ore.loginInserted = True + + except xmlrpc.client.Error as v: + bpy.ready = False + ore.loginInserted = False + ore.passwordCorrect = False + ore.hash = '' + ore.password = '' + self.report({'WARNING'}, "Incorrect login") + print(v) 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.use: - 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() - - def isFilterNode(node): - t = type(node) - return t==bpy.types.CompositorNodeBlur or t==bpy.types.CompositorNodeDBlur - - def hasCompositingErrors(use_nodes, nodetree, parts): - if not use_nodes: # no nodes in use, ignore check - return False - - for node in nodetree.nodes: - # output file absolutely forbidden - if type(node)==bpy.types.CompositorNodeOutputFile: - self.report({'ERROR'}, 'File output node is disallowed, remove them from your compositing nodetrees.') - return True - # blur et al are problematic when rendering ore.parts>1 - if isFilterNode(node) and parts>1: - self.report({'WARNING'}, 'A filtering node found and parts > 1. This combination will give bad output.') - return True - - return False - - sce = context.scene - ore = sce.ore_render - errors = False + all_sessions = [] + bpy.ore_complete_session_queue = [] - checkStatus(ore) + bpy.ore_complete_session_queue.extend(bpy.ore_pending_sessions) + bpy.ore_complete_session_queue.extend(bpy.ore_active_sessions) + bpy.ore_complete_session_queue.extend(bpy.ore_completed_sessions) + bpy.ore_complete_session_queue.extend(bpy.ore_cancelled_sessions) - if len(bpy.errors) > 0: - ore.prepared = False - return {'CANCELLED'} + bpy.ore_active_session_queue = bpy.ore_complete_session_queue + updateSessionList(ore.all_sessions, ore) - rd = sce.render - - bpy.ops.file.pack_all() - 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%") - 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") - rd.file_format = 'PNG' - 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") - rd.use_sss = False # disabling because ore.parts > 1. It's ok to use SSS with 1part/frame - 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") - ore.hasUnsupportedSimulation = True - errors = True - else: - ore.hasUnsupportedSimulation = False - if (rd.use_full_sample == True and rd.use_save_buffers == True): - print("Save Buffers is not supported. As you also have Full " \ - "Sample on, I'm turning both of the settings off") - self.report({'WARNING'}, "Save Buffers is not supported; as you " \ - "also have Full Sample on, I'm turning " \ - "both of the settings off") - if (rd.use_full_sample == False and rd.use_save_buffers == True): - print("Save buffers needs to be turned off. Changing to off") - self.report({'WARNING'}, "Save buffers needs to be turned off, " \ - "changing to off") - rd.use_full_sample = False - rd.use_save_buffers = False - rd.use_free_image_textures = True - if (rd.use_border == True): - print("Border render is not supported. Turning it off") - self.report({'WARNING'}, "Border render is not supported, " \ - "turning it off") - rd.use_border = False - if rd.use_compositing: - if hasCompositingErrors(sce.use_nodes, sce.node_tree, ore.parts): - print("Found disallowed nodes or problematic setup") - rd.use_compositing = False - self.report({'WARNING'}, "Found disallowed nodes or " \ - "problematic setup") - 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 found, don't allow to upload, instead have user - # go through this until everything is ok - # Errors is only True if there is a setting that could not be changed to the correct setting - # In short, unsupported simulations - if errors: - self.report({'WARNING'}, "Some issues found, check console and " \ - "do a test render to make sure " \ - "everything works") - ore.prepared = False - else: - ore.prepared = True - rd.engine = 'BLENDER_RENDER' - bpy.ops.wm.save_mainfile() - rd.engine = 'RENDERFARMFI_RENDER' - return {'FINISHED'} class ORE_ResetOp(bpy.types.Operator): @@ -923,8 +971,19 @@ class ORE_ResetOp(bpy.types.Operator): def execute(self, context): sce = context.scene - sce.ore_render.prepared = False - sce.render.threads_mode = 'AUTO' + ore = sce.ore_render + ore.prepared = False + ore.loginInserted = False + bpy.prepared = False + ore.hash = '' + ore.username = '' + ore.passowrd = '' + ore.longdesc = '' + ore.shortdesc = '-' + ore.tags = '' + ore.title = '' + ore.url = '' + return {'FINISHED'} class ORE_TestRenderOp(bpy.types.Operator): @@ -947,10 +1006,13 @@ class ORE_UploaderOp(bpy.types.Operator): 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) + + bpy.uploadInProgress = True + prepareScene() + + returnValue = ore_upload(self, context) + bpy.uploadInProgress = False + return returnValue class ORE_UseBlenderReso(bpy.types.Operator): bl_idname = "ore.use_scene_settings" @@ -977,6 +1039,8 @@ class ORE_ChangeUser(bpy.types.Operator): ore = context.scene.ore_render ore.password = '' ore.hash = '' + ore.passwordCorrect = False + ore.loginInserted = False return {'FINISHED'} @@ -996,11 +1060,7 @@ class RenderfarmFi(bpy.types.RenderEngine): def register(): bpy.utils.register_module(__name__) - - bpy.types.Scene.ore_render = PointerProperty( - type=ORESettings, - name='ORE Render', - description='ORE Render Settings') + bpy.types.Scene.ore_render = PointerProperty(type=ORESettings, name='ORE Render', description='ORE Render Settings') #~ bpy.types.INFO_MT_render.append(menu_export) |