diff --git a/__init__.py b/__init__.py index 257e694..d742f95 100644 --- a/__init__.py +++ b/__init__.py @@ -76,7 +76,7 @@ def log_exhook(exc_type, exc_value, exc_traceback): # log that an unhandled exception occured in Alice/LG's log file LookingGlassAddonLogger.critical("An unhandled error occured. Here is the traceback:\n", exc_info=(exc_type, exc_value, exc_traceback)) - + # then continue with the system behavior sys.__excepthook__(exc_type, exc_value, exc_traceback) diff --git a/lightfield_render.py b/lightfield_render.py index 95b48f3..0eb63ab 100644 --- a/lightfield_render.py +++ b/lightfield_render.py @@ -80,6 +80,7 @@ def __init__(self, scene, animation, use_lockfile, use_multiview, blocking): self.rows = None self.columns = None self.total_views = None + self.used_views = None self.quilt_aspect = None self.view_cone = None @@ -183,7 +184,7 @@ def view_filepath(self, view=None, frame=None): # if an animation is rendered if self.animation: - return os.path.join(self.file_dirname, self.file_basename + "_f" + str(frame).zfill(len(str(self.scene.frame_end))) + self.get_quilt_suffix() + "_v" + str(view).zfill(len(str(self.total_views - 1))) + self.file_extension) + return os.path.join(self.file_dirname, self.file_basename + "_f" + str(frame).zfill(len(str(self.scene.frame_end))) + self.get_quilt_suffix() + "_v" + str(view).zfill(len(str(self.used_views))) + self.file_extension) # if an animation is rendered elif not self.animation: @@ -262,7 +263,7 @@ def invoke(self): # setup the camera (system) for rendering def setup_camera(self): - # check, if there is an active camera marker in this frame + # check, if there is an active camera marker in this frame marker_camera_found = False marker_cameras = [marker for marker in bpy.context.scene.timeline_markers if marker.camera is not None] if marker_cameras: @@ -333,8 +334,8 @@ def setup_camera(self): # required for single cameras. Rendering still works, # which is nice, because the camera remains invisible. # Leave this here for debugging purposes. - # # add this camera to the master collection of the scene - # self.scene.collection.objects.link(self._camera_active) + # add this camera to the master collection of the scene + #self.scene.collection.objects.link(self._camera_active) # CAMERA SETTINGS: APPLY POSITION AND SHIFT @@ -406,13 +407,13 @@ def setup_camera(self): self._view_matrix_inv = self._view_matrix.inverted_safe() # loop through all views - for view in range(self.view_start, self.view_end): + for view in range(self.view_start, self.view_end + 1): # COPY CAMERA # +++++++++++++++++++++++++++++++++++++++++++++++ # if the cameras not already exist - if not len(self._camera_temp) == self.total_views: + if not len(self._camera_temp) == self.used_views: # create a new, temporary camera using a copy of the original camera self._camera_temp.append(bpy.data.objects.new(self._camera_temp_basename + "_v" + str(view).zfill(len(str(self.total_views - 1))), self._camera_active.data.copy())) @@ -623,7 +624,7 @@ def clean_up(self): LookingGlassAddonLogger.info("Cleaning up camera setup.") - # if there is an active camera marker in this frame + # if there is an active camera marker in this frame marker_camera_found = False marker_cameras = [marker for marker in bpy.context.scene.timeline_markers if marker.camera is not None] if marker_cameras: @@ -644,7 +645,7 @@ def clean_up(self): # if no marker camera was found if not marker_camera_found: - + # restore the original active camera self.scene.camera = self._camera_original @@ -679,9 +680,9 @@ def clean_up(self): bpy.data.cameras.remove(camera.data, do_unlink=True, do_id_user=True, do_ui_user=True) # remove the corresponding temporary multiview data block - if self.scene.render.views.find(self._multiview_view_basename + str(view).zfill(len(str(self.total_views - 1)))) != -1: - LookingGlassAddonLogger.info(" [#] Delete render view: %s" % (self.scene.render.views[self._multiview_view_basename + str(view).zfill(len(str(self.total_views - 1)))])) - self.scene.render.views.remove(self.scene.render.views[self._multiview_view_basename + str(view).zfill(len(str(self.total_views - 1)))]) + if self.scene.render.views.find(self._multiview_view_basename + str(view + self.view_start).zfill(len(str(self.total_views - 1)))) != -1: + LookingGlassAddonLogger.info(" [#] Delete render view: %s" % (self.scene.render.views[self._multiview_view_basename + str(view + self.view_start).zfill(len(str(self.total_views - 1)))])) + self.scene.render.views.remove(self.scene.render.views[self._multiview_view_basename + str(view + self.view_start).zfill(len(str(self.total_views - 1)))]) # clear the list self._camera_temp.clear() @@ -692,7 +693,7 @@ def clean_up(self): # set to view format to self.scene.render.views_format = 'STEREO_3D' - # deactivate 'left' and 'right' view + # re-activate 'left' and 'right' view self.scene.render.views['left'].use = True self.scene.render.views['right'].use = True @@ -706,11 +707,11 @@ def update_progress(self): # if a single frame shall be rendered if self.animation == False: - return int(self.view / ((self.total_views - 1)) * 100) + return int(self.view / ((self.used_views)) * 100) # for animations else: - return int(((self.frame - self.scene.frame_start) * (self.total_views - 1) + self.view) / ((self.total_views - 1) * (self.scene.frame_end - self.scene.frame_start + 1)) * 100) + return int(((self.frame - self.scene.frame_start) * (self.used_views) + self.view) / ((self.used_views) * (self.scene.frame_end - self.scene.frame_start + 1)) * 100) # MULTIVIEW CAMERA RENDERING # ++++++++++++++++++++++++++++++++++ @@ -718,11 +719,11 @@ def update_progress(self): # if a single frame shall be rendered if self.animation == False: - return int(self.view / ((self.total_views - 1)) * 100) + return int(self.view / ((self.used_views)) * 100) # for animations else: - return int(((self.frame - self.scene.frame_start) * (self.total_views - 1) + self.view) / ((self.total_views - 1) * (self.scene.frame_end - self.scene.frame_start + 1)) * 100) + return int(((self.frame - self.scene.frame_start) * (self.used_views) + self.view) / ((self.used_views) * (self.scene.frame_end - self.scene.frame_start + 1)) * 100) # CALLBACK FUNCTIONS / APPLICATION HANDLERS # +++++++++++++++++++++++++++++++++++++++++++++++ @@ -858,7 +859,7 @@ def __init__(self, BlenderScene, animation, use_lockfile, use_multiview, blockin # deactivate the "Add Metadata option" self.scene.addon_settings.render_add_suffix = False - # if an starting frame was specified + # if a starting frame was specified if "-s" in LookingGlassAddon.addon_arguments or "--frame-start" in LookingGlassAddon.addon_arguments: # get the file name position @@ -920,7 +921,7 @@ def __init__(self, BlenderScene, animation, use_lockfile, use_multiview, blockin # set the current frame self.scene.frame_current = int(LookingGlassAddon.addon_arguments[index]) - # if a rendering frame was specified + # if a rendering view was specified if "-v" in LookingGlassAddon.addon_arguments or "--render-view" in LookingGlassAddon.addon_arguments: # get the view index @@ -945,7 +946,6 @@ def __init__(self, BlenderScene, animation, use_lockfile, use_multiview, blockin # set the current frame self.view_end = int(LookingGlassAddon.addon_arguments[index + 1]) + 1 - # INITIALIZATION # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -991,10 +991,28 @@ def __init__(self, BlenderScene, animation, use_lockfile, use_multiview, blockin # get all quilt presets from pylio self._qs = pylio.LookingGlassQuilt.formats.get() - # set view range to default if None was given - if self.view_start is None: self.view_start = 0 - if self.view_end is None: self.view_end = self._qs[int(self._quilt_preset)]["total_views"] + if self.addon_settings.render_use_view_range: + # The quilt will fail if all needed views are not made so select 'views only' + self.addon_settings.render_output = '2' + + # check start and end are within range + if self.addon_settings.render_view_start < self._qs[int(self._quilt_preset)]["total_views"]: + self.view_start = self.addon_settings.render_view_start + else: + LookingGlassAddonLogger.warning(f"View start is greater than total number of views supported by selected device ({self._qs[int(self._quilt_preset)]['total_views']-1})") + + if self.addon_settings.render_view_end < self._qs[int(self._quilt_preset)]["total_views"] and self.view_start <= self.addon_settings.render_view_end: + self.view_end = self.addon_settings.render_view_end + else: + if self.view_start <= self.addon_settings.render_view_end: + LookingGlassAddonLogger.warning(f"View end is greater than total number of views supported by selected device ({self._qs[int(self._quilt_preset)]['total_views']-1})") + else: + LookingGlassAddonLogger.warning(f"View end is greater than view start") + # set view range to default if None was given or was invalid + if self.view_start is None: self.view_start = 0 + if self.view_end is None: self.view_end = self._qs[int(self._quilt_preset)]["total_views"] -1 + self.job.used_views = self.view_end + 1 - self.view_start # PATH SETTINGS # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -1006,7 +1024,6 @@ def __init__(self, BlenderScene, animation, use_lockfile, use_multiview, blockin self.job.lockfile_path = bpy.path.abspath(LookingGlassAddon.tmp_path + os.path.basename(bpy.data.filepath) + ".lock") - # ORIGINAL SETTINGS # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -1015,7 +1032,6 @@ def __init__(self, BlenderScene, animation, use_lockfile, use_multiview, blockin self.original = self.copy() - # RENDER JOB SETTINGS # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # if the lockfile shall be used @@ -1052,6 +1068,8 @@ def __init__(self, BlenderScene, animation, use_lockfile, use_multiview, blockin self.job.columns = self._qs[int(self._quilt_preset)]["columns"] self.job.total_views = self._qs[int(self._quilt_preset)]["total_views"] + + # set view range to render self.job.view_start = self.view_start self.job.view_end = self.view_end @@ -1090,7 +1108,7 @@ def __init__(self, BlenderScene, animation, use_lockfile, use_multiview, blockin # NOTE: This function is largely taken from https://stackoverflow.com/a/1118038 def to_dict(self, obj, classkey=None): - # if this is an dictionary + # if this is a dictionary if isinstance(obj, dict): data = {} for (k, v) in obj.items(): @@ -1376,6 +1394,7 @@ def cancel(self, context): + # CLEAR IMAGE & PIXEL DATA # +++++++++++++++++++++++++ self.render_settings.job._view_image = None @@ -1384,6 +1403,7 @@ def cancel(self, context): + # CLEAN-UP FILES # +++++++++++++++++++++++++++++++++++++++++++ # if the view files shall not be kept OR (still was rendered AND no filename was specfied) OR the file keeping is forced OR the incomplete render job was discarded @@ -1408,6 +1428,7 @@ def cancel(self, context): + # RESTORE USER SETTINGS # +++++++++++++++++++++++++ # if this call was not just invoked to discard an incomplete render job @@ -1605,11 +1626,11 @@ def invoke(self, context, event): if bpy.context.scene.render.use_compositing and not bpy.context.scene.render.use_sequencer: # notify user self.report({"WARNING"}, "The compositor is active. This might cause issues during quilt rendering.") - + elif not bpy.context.scene.render.use_compositing and bpy.context.scene.render.use_sequencer: # notify user self.report({"WARNING"}, "The sequencer is active. This might cause issues during quilt rendering.") - + elif bpy.context.scene.render.use_compositing and bpy.context.scene.render.use_sequencer: # notify user self.report({"WARNING"}, "The compositor and sequencer are active. This might cause issues during quilt rendering.") @@ -1743,13 +1764,13 @@ def modal(self, context, event): if self.render_settings.job.animation == False: # notify user - self.report({"INFO"},"Rendering view " + str(self.render_settings.job.view + 1) + "/" + str(self.render_settings.job.total_views) + " ..") + self.report({"INFO"},"Rendering view " + str(self.render_settings.job.view + 1) + "/" + str(self.render_settings.job.view_end) + " ..") # if an animation shall be rendered elif self.render_settings.job.animation == True: # notify user - self.report({"INFO"},"Rendering view " + str(self.render_settings.job.view + 1) + "/" + str(self.render_settings.job.total_views) + " of frame " + str(self.render_settings.job.frame) + " ..") + self.report({"INFO"},"Rendering view " + str(self.render_settings.job.view + 1) + "/" + str(self.render_settings.job.view_end) + " of frame " + str(self.render_settings.job.frame) + " ..") # pass event through return {'PASS_THROUGH'} @@ -1765,43 +1786,46 @@ def modal(self, context, event): # QUILT ASSEMBLY # ++++++++++++++++++++++++++++++++++++++++++++ # if this was the last view OR a multiview render - if self.render_settings.job.view == (self.render_settings.job.view_end - 1) or self.use_multiview: + if self.render_settings.job.view == (self.render_settings.job.view_end) or self.use_multiview: start = time.time() - # assemble the quilt from the view data - if not self.render_settings.job.assemble_quilt(): + # if 'views only' is selected, don't render the quilt + if self.render_settings.addon_settings.render_output != '2': - # cancel the operator - self.render_settings.addon_settings.render_stop = True + # assemble the quilt from the view data + if not self.render_settings.job.assemble_quilt(): + + # cancel the operator + self.render_settings.addon_settings.render_stop = True - # force the operator to keep the view Files - self.file_force_keep = True + # force the operator to keep the view Files + self.file_force_keep = True - # notify user - self.cancel_sign = "ERROR" - self.cancel_message = "Render job can not be continued. Missing view file(s) of the previously failed render job." + # notify user + self.cancel_sign = "ERROR" + self.cancel_message = "Render job can not be continued. Missing view file(s) of the previously failed render job." - # QUILT DISPLAY AS RENDER RESULT - # ++++++++++++++++++++++++++++++++++++++++++++ - for window in context.window_manager.windows: - for area in window.screen.areas: + # QUILT DISPLAY AS RENDER RESULT + # ++++++++++++++++++++++++++++++++++++++++++++ + for window in context.window_manager.windows: + for area in window.screen.areas: - if area.type == 'IMAGE_EDITOR': + if area.type == 'IMAGE_EDITOR': - if area.spaces.active != None: + if area.spaces.active != None: - if area.spaces.active.image != None: + if area.spaces.active.image != None: - if area.spaces.active.image.name == "Render Result": + if area.spaces.active.image.name == "Render Result": - # and change the active image shown here to the quilt - area.spaces.active.image = self.render_settings.job._quilt_image + # and change the active image shown here to the quilt + area.spaces.active.image = self.render_settings.job._quilt_image - # fit the zoom factor in this window to show the complete quilt - # bpy.ops.image.view_all({'window': window, 'screen': window.screen, 'area': area}) + # fit the zoom factor in this window to show the complete quilt + # bpy.ops.image.view_all({'window': window, 'screen': window.screen, 'area': area}) - break + break # UPDATE LOCKFILE @@ -1821,7 +1845,7 @@ def modal(self, context, event): if self.render_settings.job.animation == False: # if this was not the last view AND the multiview mechanism is NOT used - if self.render_settings.job.view < (self.render_settings.job.view_end - 1) and not self.use_multiview: + if self.render_settings.job.view < (self.render_settings.job.view_end) and not self.use_multiview: # increase view count self.render_settings.job.view += 1 @@ -1834,8 +1858,7 @@ def modal(self, context, event): # notify user self.cancel_sign = "INFO" - self.cancel_message = "Complete quilt rendered." - + self.cancel_message = "Complete quilt rendered." if self.render_settings.addon_settings.render_output != '2' else "Render complete" # stop the operator self.render_settings.addon_settings.render_stop = True @@ -1844,7 +1867,7 @@ def modal(self, context, event): elif self.render_settings.job.animation == True: # if this was not the last view AND the multiview mechanism is NOT used - if self.render_settings.job.view < (self.render_settings.job.view_end - 1) and not self.use_multiview: + if self.render_settings.job.view < (self.render_settings.job.view_end) and not self.use_multiview: # increase view count self.render_settings.job.view += 1 @@ -1853,7 +1876,7 @@ def modal(self, context, event): self.render_settings.job._state = "INVOKE_RENDER" # if this was the last view OR the multiview mechanism is used - elif self.render_settings.job.view == (self.render_settings.job.view_end - 1) or self.use_multiview: + elif self.render_settings.job.view == (self.render_settings.job.view_end) or self.use_multiview: # but if this was not the last frame if self.render_settings.job.frame < self.render_settings.job.scene.frame_end: @@ -1866,7 +1889,7 @@ def modal(self, context, event): # if the view files shall not be kept if ((self.render_settings.addon_settings.render_output == '1') and self.render_settings.job.file_force_keep == False): - +# # delete views of the rendered frame self.render_settings.job.delete_files(self.render_settings.job.frame) @@ -1893,7 +1916,7 @@ def modal(self, context, event): # notify user self.cancel_sign = "INFO" - self.cancel_message = "Complete animation quilt rendered." + self.cancel_message = "Complete animation quilt rendered." if self.render_settings.addon_settings.render_output != '2' else "animation render complete" # log debug info LookingGlassAddonLogger.debug("Render job completed.") diff --git a/ui.py b/ui.py index f7d8114..e3bc103 100644 --- a/ui.py +++ b/ui.py @@ -284,7 +284,6 @@ def update_render_setting_with_preset(self, context): # update function for property updates concerning render settings (WITHOUT quilt preset) def update_render_setting_without_preset(self, context): - # if a device is selected by the user if int(context.window_manager.addon_settings.activeDisplay) != -1: pylio.DeviceManager.set_active(int(context.window_manager.addon_settings.activeDisplay)) else: pylio.DeviceManager.reset_active() @@ -349,7 +348,6 @@ def update_render_setting_without_preset(self, context): return None - # update settings for the viewport editor blocks def update_viewport_block_settings(self, context): @@ -457,9 +455,7 @@ def update_camera_synchronization(self, context): if not LookingGlassAddonUI.synchronize_active_camera in bpy.app.handlers.depsgraph_update_post: bpy.app.handlers.depsgraph_update_post.append(LookingGlassAddonUI.synchronize_active_camera) if not LookingGlassAddonUI.synchronize_active_camera in bpy.app.handlers.frame_change_post: bpy.app.handlers.frame_change_post.append(LookingGlassAddonUI.synchronize_active_camera) - elif not context.scene.addon_settings.toggleCameraSync: - if LookingGlassAddonUI.synchronize_active_camera in bpy.app.handlers.depsgraph_update_post: bpy.app.handlers.depsgraph_update_post.remove(LookingGlassAddonUI.synchronize_active_camera) if LookingGlassAddonUI.synchronize_active_camera in bpy.app.handlers.frame_change_post: bpy.app.handlers.frame_change_post.remove(LookingGlassAddonUI.synchronize_active_camera) @@ -489,7 +485,7 @@ def update_camera_selection(self, context): if not (bpy.context.scene.addon_settings.clip_start < bpy.context.scene.addon_settings.focalPlane < bpy.context.scene.addon_settings.clip_end): bpy.context.scene.addon_settings.focalPlane = 5 - + # set flag context.scene.addon_settings.lookingglassCamera.data.is_lightfield = True @@ -584,7 +580,7 @@ def focal_plane_getter(self): if camera: if self.get('focalPlane', 5) != camera.data.dof.focus_distance: bpy.context.scene.addon_settings.focalPlane = camera.data.dof.focus_distance - + return self.get('focalPlane', 5) # setter for the focalPlane @@ -1022,11 +1018,37 @@ class LookingGlassAddonSettingsScene(bpy.types.PropertyGroup): # File handling render_output: bpy.props.EnumProperty( items = [('0', 'View and Quilt Files', 'Each view is rendered to a separate file in the output directory in addition to the quilt.'), - ('1', 'Only Quilt File', 'Each view is rendered to a temporary file in the output directory. These files are deleted after the quilt is complete.')], - default='1', + ('1', 'Only Quilt File', 'Each view is rendered to a temporary file in the output directory. These files are deleted after the quilt is complete.'), + ('2', 'Only View Files', 'Each view is rendered to a separate file in the output directory.')], + default='0', name="Output", ) + # Use custom view range or not + render_use_view_range: bpy.props.BoolProperty( + name="Use View Range", + description="Enables and disables using custom view ranges", + default = False, + ) + + # View range start + render_view_start: bpy.props.IntProperty( + name = "View Start", + default = 0, + min = 0, + step = 1, + description = "The starting viewing angle for the render.", + ) + + # View range end + render_view_end: bpy.props.IntProperty( + name = "View End", + default = 65, + min = 0, + step = 1, + description = "The last viewing angle for the render.", + ) + # Progress bar render_progress: bpy.props.FloatProperty( name = "", @@ -1479,7 +1501,6 @@ def draw(self, context): # display the clipping settings camera = context.scene.addon_settings.lookingglassCamera if camera: - column.separator() row_clip_start = column.row(align = True) row_clip_start.prop(context.scene.addon_settings, "clip_start") @@ -1537,6 +1558,10 @@ def draw(self, context): row_metadata = row_general_options.row(align = True) render_add_suffix = row_metadata.prop(context.scene.addon_settings, "render_add_suffix") + # Use custom view range or not + row_use_view_range = row_general_options.row(align = True) + render_use_view_range = row_use_view_range.prop(context.scene.addon_settings, "render_use_view_range") + # Render orientation row_orientation = layout.row(align = True) column_1 = row_orientation.row(align = True) @@ -1556,13 +1581,36 @@ def draw(self, context): column_2.scale_x = 0.7 # Output file handling - row_output = layout.row(align = True) - column_1 = row_output.row(align = True) - column_1.label(text="Output:") - column_1.scale_x = 0.3 - column_2 = row_output.row(align = True) - column_2.prop(context.scene.addon_settings, "render_output", text="") - column_2.scale_x = 0.7 + # If the user wants to specify the view range, the program cannot create a quilt with incomplete data + # so 'veiws only' will be selected by the program + if not context.scene.addon_settings.render_use_view_range: + row_output = layout.row(align = True) + column_1 = row_output.row(align = True) + column_1.label(text="Output:") + column_1.scale_x = 0.3 + column_2 = row_output.row(align = True) + column_2.prop(context.scene.addon_settings, "render_output", text="") + column_2.scale_x = 0.7 + + # Start view + # If the user has selected to use a view range + if context.scene.addon_settings.render_use_view_range: + row_view_start = layout.row(align = True) + column_1 = row_view_start.row(align = True) + column_1.label(text="Start View:") + column_1.scale_x = 0.3 + column_2 = row_view_start.row(align = True) + column_2.prop(context.scene.addon_settings, "render_view_start", text="") + column_2.scale_x = 0.7 + + # End view + row_view_end = layout.row(align = True) + column_1 = row_view_end.row(align = True) + column_1.label(text="End View:") + column_1.scale_x = 0.3 + column_2 = row_view_end.row(align = True) + column_2.prop(context.scene.addon_settings, "render_view_end", text="") + column_2.scale_x = 0.7 # if no lockfile was detected on start-up OR the render job is running if not LookingGlassAddon.has_lockfile or LookingGlassAddon.RenderInvoked: @@ -1576,9 +1624,9 @@ def draw(self, context): else: # Button to start rendering a single quilt using the current render settings row_render_still = layout.row(align = True) - render_quilt = row_render_still.operator("render.quilt", text="Render Quilt", icon='RENDER_STILL') + render_quilt = row_render_still.operator("render.quilt", text="Start Render" if (context.scene.addon_settings.render_use_view_range or context.scene.addon_settings.render_output == "2") else "Render Quilt", icon='RENDER_STILL') render_quilt.animation = False - render_quilt.use_multiview = (context.preferences.addons[__package__].preferences.camera_mode == '1') + render_quilt.use_multiview = (context.preferences.addons[__package__].preferences.camera_mode == '1' and context.scene.addon_settings.render_view_start != context.scene.addon_settings.render_view_end) if LookingGlassAddon.RenderInvoked == True and LookingGlassAddon.RenderAnimation == True: # Show the corresponding progress bar for the rendering process @@ -1588,9 +1636,9 @@ def draw(self, context): else: # Button to start rendering a animation quilt using the current render settings row_render_animation = layout.row(align = True) - render_quilt = row_render_animation.operator("render.quilt", text="Render Animation Quilt", icon='RENDER_ANIMATION') + render_quilt = row_render_animation.operator("render.quilt", text="Render Animation" if (context.scene.addon_settings.render_use_view_range or context.scene.addon_settings.render_output == "2") else"Render Animation Quilts", icon='RENDER_ANIMATION') render_quilt.animation = True - render_quilt.use_multiview = (context.preferences.addons[__package__].preferences.camera_mode == '1') + render_quilt.use_multiview = (context.preferences.addons[__package__].preferences.camera_mode == '1' and context.scene.addon_settings.render_view_start != context.scene.addon_settings.render_view_end) # if a lockfile was detected on start-up @@ -1600,8 +1648,14 @@ def draw(self, context): row_metadata.enabled = False row_use_device.enabled = False row_orientation.enabled = False + row_use_view_range.enabled = False row_preset.enabled = False - row_output.enabled = False + # can't disable if not drawn + if not context.scene.addon_settings.render_use_view_range: + row_output.enabled = False + else: + row_view_start.enabled = False + row_view_end.enabled = False # inform the user and provide options to continue or to discard row_render_still = layout.row(align = True) @@ -1616,16 +1670,19 @@ def draw(self, context): render_quilt.use_multiview = (context.preferences.addons[__package__].preferences.camera_mode == '1') render_quilt.discard_lockfile = True - - - # disable the render settings, if a rendering process is running if LookingGlassAddon.RenderInvoked == True: row_metadata.enabled = False row_use_device.enabled = False row_orientation.enabled = False + row_use_view_range.enabled = False row_preset.enabled = False - row_output.enabled = False + # can't disable if not drawn + if not context.scene.addon_settings.render_use_view_range: + row_output.enabled = False + else: + row_view_start.enabled = False + row_view_end.enabled = False if LookingGlassAddon.RenderAnimation == True: row_render_still.enabled = False if LookingGlassAddon.RenderAnimation == False: row_render_animation.enabled = False @@ -1637,8 +1694,14 @@ def draw(self, context): row_metadata.enabled = False row_use_device.enabled = False row_orientation.enabled = False + row_use_view_range.enabled = False row_preset.enabled = False - row_output.enabled = False + # can't disable if not drawn + if not context.scene.addon_settings.render_use_view_range: + row_output.enabled = False + else: + row_view_start.enabled = False + row_view_end.enabled = False row_render_still.enabled = False row_render_animation.enabled = False @@ -1648,6 +1711,12 @@ def draw(self, context): # disable all elements row_orientation.enabled = False row_preset.enabled = False + row_use_view_range.enabled = False + # can't disable if not drawn + if context.scene.addon_settings.render_use_view_range: + row_view_start.enabled = False + row_view_end.enabled = False + # if no Looking Glass was detected AND debug mode is not activated if not pylio.DeviceManager.count() and not LookingGlassAddon.debugging_use_dummy_device: @@ -1725,6 +1794,7 @@ def draw(self, context): row_preset = column.row() row_preset.prop(context.window_manager.addon_settings, "lightfieldMode", text="") row_preset.operator("lookingglass.refresh_lightfield", text="", icon='FILE_REFRESH') + #WHAT # Preview settings row_output = column.row(align = True) @@ -2011,6 +2081,8 @@ def draw(self, context): column_2.prop(context.scene.addon_settings, "imageeditor_block_device_type", text="") column_2.scale_x = 0.7 + + #huh # Quilt settings row_preset = layout.row(align = True) row_preset.enabled = (not LookingGlassAddon.ImageBlockRenderer.is_imageeditor_detected())