Ejemplo n.º 1
0
    def validateJobPackages(self):
        '''
        Validate that job packages make sense
            1. ensure no duplicate packages (call the parent class method for this)
            2. ensure that no two packages of the same product exist (call the parent class method for this)
            3. Ensure that a package for the host product has been selected (call the parent class method for this)
            4. Ensure that a render package is present (unless just using maya software)
        '''
        is_valid = super(MayaConductorSubmitter, self).validateJobPackages()
        active_renderer = maya_utils.get_active_renderer()

        # If the renderer is other than mayaSoftware, ensure that there is a job package for it
        if active_renderer != "mayaSoftware":
            #  get info for the active renderer
            renderer_info = maya_utils.get_renderer_info(
                renderer_name=active_renderer)
            PluginInfoClass = maya_utils.get_plugin_info_class(
                renderer_info["plugin_name"])
            if not PluginInfoClass:
                title = "Currently active renderer '%s' not supported." % active_renderer
                msg = (
                    "The renderer %s is currently active in Maya.\n\n"
                    "Please switch to a supported renderer in \"Render Settings\"."
                ) % active_renderer
                pyside_utils.launch_error_box(title, msg, parent=self)
                return False
            plugin_product = PluginInfoClass.get_product()
            for package in self.getJobPackages():
                if package["product"] == plugin_product:
                    break
            else:
                title = "No package specified for %s!" % plugin_product
                msg = (
                    "No %s software package has been specified for the Job!\n\n"
                    "Please go the \"Job Software\" tab and add one that is "
                    "appropriate (potentially %s") % (
                        plugin_product, PluginInfoClass.get_version())
                pyside_utils.launch_error_box(title, msg, parent=self)
                self.ui_tabwgt.setCurrentIndex(self._job_software_tab_idx)
                return False

        return is_valid
    def validateJobPackages(self):
        '''
        Validate that job packages make sense
            1. ensure no duplicate packages (call the parent class method for this)
            2. ensure that no two packages of the same product exist (call the parent class method for this)
            3. Ensure that a package for the host product has been selected (call the parent class method for this)
            4. Ensure that a render package is present (unless just using maya software)
        '''
        is_valid = super(MayaConductorSubmitter, self).validateJobPackages()
        active_renderer = maya_utils.get_active_renderer()

        # If the renderer is other than mayaSoftware, ensure that there is a job package for it
        if active_renderer != "mayaSoftware":
            #  get info for the active renderer
            renderer_info = maya_utils.get_renderer_info(renderer_name=active_renderer)
            PluginInfoClass = maya_utils.get_plugin_info_class(renderer_info["plugin_name"])
            if not PluginInfoClass:
                title = "Currently active renderer '%s' not supported." % active_renderer
                msg = ("The renderer %s is currently active in Maya.\n\n"
                       "Please switch to a supported renderer in \"Render Settings\".") % active_renderer
                pyside_utils.launch_error_box(title, msg, parent=self)
                return False
            plugin_product = PluginInfoClass.get_product()
            for package in self.getJobPackages():
                if package["product"] == plugin_product:
                    break
            else:
                title = "No package specified for %s!" % plugin_product
                msg = ("No %s software package has been specified for the Job!\n\n"
                       "Please go the \"Job Software\" tab and add one that is "
                       "appropriate (potentially %s") % (plugin_product, PluginInfoClass.get_version())
                pyside_utils.launch_error_box(title, msg, parent=self)
                self.ui_tabwgt.setCurrentIndex(self._job_software_tab_idx)
                return False

        return is_valid
Ejemplo n.º 3
0
    def generateTasksData(self):
        '''
        Return a list of tasks data.  Each item in the list represents one
        task of work that will be created.

        Each task dictionary has the following
        keys:
            command: The command for the task to execute

            frames: [optional], helps to bind/display the relationship between a
                     task and the frames that the task is operating on.  Because
                     a task can be any arbitrary command, the notion of "frames"
                     may not be relevant and can be left empty.

        Eventually we may want to populate this with *everything* a task needs
        (offloading it from the Job entity). This would allow more per-task flexiblity (such as differing environments,
        files, etc).  Just general containment in general.


        Example(two tasks):

            # Task 0
            [ {"command": "Render -s 1 -e 1 -rl renderlayer1 \"maya_filepath.ma\""
               "frames": "1"},
            # Task 1
            {"command": "Render -s 10 -e 20 -b 2 \"maya_filepath.ma\""
             "frames": "10-20x2"} ]
        '''

        # Create a template command that be be used for each task's command
        cmd_template = "Render %s -s %s -e %s -b %s %s -rd /tmp/render_output/ %s %s"

        # Retrieve the source maya file
        maya_filepath = self.getSourceFilepath()
        # Strip the lettered drive from the filepath (if one exists).
        # This is a hack to allow a Windows filepath to be properly used
        # as an argument in a linux shell on the backend. Not pretty.
        maya_filepath_nodrive = file_utils.strip_drive_letter(maya_filepath)

        # Get the user-selected render layers
        render_layers = self.extended_widget.getSelectedRenderLayers()

        active_renderer = maya_utils.get_active_renderer()
        # If the active renderer is rman/renderman, then we must explicitly declare it
        # as the renderer in the command.  Otherwise the output path is not respected.
        # I assume this is a renderman bug.
        # TODO:(lws). This is a super ugly exception case that we need to better manage/abstract
        if active_renderer == "renderManRIS":
            renderer_arg = "-r rman"
        # If the active renderer is renderman, then we must explicitly declare it (see comment above).
        # We must also clear out the specified render layers because renderman 22 doesn't accept the rl
        # flag anymore. By not specifying any render layers, *all* active render layers will be rendered
        # TODO:(lws). This is really nasty/dangerous. Hopefully pixar/renderman will re-add support
        # for specifying render layers ASAP!
        elif active_renderer == "renderman":
            renderer_arg = "-r renderman"
            render_layers = []

        # For any other renderers, we don't need to specify the renderer arg (the renderer indicated
        # in the maya scene will be used).
        else:
            renderer_arg = ""

        # construct -rl flag (omit it if no render layers specified)
        render_layer_args = ("-rl " + ",".join(render_layers)) if render_layers else ""

        # Workspace/Project arg. Only add flag if a workspace has been indicated in the submitter ui
        workspace = self.extended_advanced_widget.getWorkspaceDir()
        # Strip the lettered drive from the workspace (if one exists).
        # This is a hack to allow a Windows filepath to be properly used
        # as an argument in a linux shell on the backend. Not pretty.
        workspace_nodrive = file_utils.strip_drive_letter(workspace)
        project_arg = "-proj %s" % file_utils.quote_path(workspace_nodrive) if workspace_nodrive.strip() else ""

        chunk_size = self.getChunkSize()
        frames_str = self.getFrameRangeString()
        frames = seqLister.expandSeq(frames_str.split(","), None)

        # Use the task frames generator to dispense the appropriate amount of
        # frames per task, generating a command for each task to execute
        tasks_data = []
        frames_generator = submitter.TaskFramesGenerator(frames, chunk_size=chunk_size, uniform_chunk_step=True)
        for start_frame, end_frame, step, task_frames in frames_generator:
            task_cmd = cmd_template % (renderer_arg,
                                       start_frame,
                                       end_frame,
                                       step,
                                       render_layer_args,
                                       project_arg,
                                       file_utils.quote_path(maya_filepath_nodrive))

            # Generate tasks data
            # convert the list of frame ints into a single string expression
            # TODO:(lws) this is silly. We should keep this as a native int list.
            task_frames_str = ", ".join(seqLister.condenseSeq(task_frames))
            tasks_data.append({"command": task_cmd,
                               "frames": task_frames_str})
        return tasks_data
Ejemplo n.º 4
0
    def generateTasksData(self):
        '''
        Return a list of tasks data.  Each item in the list represents one
        task of work that will be created.

        Each task dictionary has the following
        keys:
            command: The command for the task to execute

            frames: [optional], helps to bind/display the relationship between a
                     task and the frames that the task is operating on.  Because
                     a task can be any arbitrary command, the notion of "frames"
                     may not be relevant and can be left empty.

        Eventually we may want to populate this with *everything* a task needs
        (offloading it from the Job entity). This would allow more per-task flexiblity (such as differing environments,
        files, etc).  Just general containment in general.


        Example(two tasks):

            # Task 0
            [ {"command": "Render -s 1 -e 1 -rl renderlayer1 \"maya_filepath.ma\""
               "frames": "1"},
            # Task 1
            {"command": "Render -s 10 -e 20 -b 2 \"maya_filepath.ma\""
             "frames": "10-20x2"} ]
        '''

        # Create a template command that be be used for each task's command
        cmd_template = "Render %s -s %s -e %s -b %s %s -rd /tmp/render_output/ %s"

        # Retrieve the source maya file
        maya_filepath = self.getSourceFilepath()
        # Strip the lettered drive from the filepath (if one exists).
        # This is a hack to allow a Windows filepath to be properly used
        # as an argument in a linux shell on the backend. Not pretty.
        maya_filepath_nodrive = file_utils.strip_drive_letter(maya_filepath)

        # If the active renderer is renderman, then we must explictly declare it
        # as the renderer in the command.  Otherwise the output path is not respected.
        # I assume this is a renderman bug.
        # TODO:(lws). This is a super ugly exception case that we need to better manage/abstract
        renderer_arg = "-r rman" if maya_utils.get_active_renderer() in [
            "renderManRIS"
        ] else ""

        # Get the user-selected render layers
        render_layers = self.extended_widget.getSelectedRenderLayers()
        render_layer_args = "-rl " + ",".join(render_layers)

        chunk_size = self.getChunkSize()
        frames_str = self.getFrameRangeString()
        frames = seqLister.expandSeq(frames_str.split(","), None)

        # Use the task frames generator to dispense the appropriate amount of
        # frames per task, generating a command for each task to execute
        tasks_data = []
        frames_generator = submitter.TaskFramesGenerator(
            frames, chunk_size=chunk_size, uniform_chunk_step=True)
        for start_frame, end_frame, step, task_frames in frames_generator:
            task_cmd = cmd_template % (
                renderer_arg, start_frame, end_frame, step, render_layer_args,
                file_utils.quote_path(maya_filepath_nodrive))

            # Generate tasks data
            # convert the list of frame ints into a single string expression
            # TODO:(lws) this is silly. We should keep this as a native int list.
            task_frames_str = ", ".join(seqLister.condenseSeq(task_frames))
            tasks_data.append({"command": task_cmd, "frames": task_frames_str})
        return tasks_data
    def generateTasksData(self):
        '''
        Return a list of tasks data.  Each item in the list represents one
        task of work that will be created.

        Each task dictionary has the following
        keys:
            command: The command for the task to execute

            frames: [optional], helps to bind/display the relationship between a
                     task and the frames that the task is operating on.  Because
                     a task can be any arbitrary command, the notion of "frames"
                     may not be relevant and can be left empty.

        Eventually we may want to populate this with *everything* a task needs
        (offloading it from the Job entity). This would allow more per-task flexiblity (such as differing environments,
        files, etc).  Just general containment in general.


        Example(two tasks):

            # Task 0
            [ {"command": "Render -s 1 -e 1 -rl renderlayer1 \"maya_filepath.ma\""
               "frames": "1"},
            # Task 1
            {"command": "Render -s 10 -e 20 -b 2 \"maya_filepath.ma\""
             "frames": "10-20x2"} ]
        '''

        # Create a template command that be be used for each task's command
        cmd_template = "Render %s -s %s -e %s -b %s %s -rd /tmp/render_output/ %s %s"

        # Retrieve the source maya file
        maya_filepath = self.getSourceFilepath()
        # Strip the lettered drive from the filepath (if one exists).
        # This is a hack to allow a Windows filepath to be properly used
        # as an argument in a linux shell on the backend. Not pretty.
        maya_filepath_nodrive = file_utils.strip_drive_letter(maya_filepath)

        # Get the user-selected render layers
        render_layers = self.extended_widget.getSelectedRenderLayers()

        active_renderer = maya_utils.get_active_renderer()
        # If the active renderer is rman/renderman, then we must explicitly declare it
        # as the renderer in the command.  Otherwise the output path is not respected.
        # I assume this is a renderman bug.
        # TODO:(lws). This is a super ugly exception case that we need to better manage/abstract
        if active_renderer == "renderManRIS":
            renderer_arg = "-r rman"
        # If the active renderer is renderman, then we must explicitly declare it (see comment above).
        # We must also clear out the specified render layers because renderman 22 doesn't accept the rl
        # flag anymore. By not specifying any render layers, *all* active render layers will be rendered
        # TODO:(lws). This is really nasty/dangerous. Hopefully pixar/renderman will re-add support
        # for specifying render layers ASAP!
        elif active_renderer == "renderman":
            renderer_arg = "-r renderman"
            render_layers = []

        # For any other renderers, we don't need to specify the renderer arg (the renderer indicated
        # in the maya scene will be used).
        else:
            renderer_arg = ""

        # construct -rl flag (omit it if no render layers specified)
        render_layer_args = ("-rl " + ",".join(render_layers)) if render_layers else ""

        # Workspace/Project arg. Only add flag if a workspace has been indicated in the submitter ui
        workspace = self.extended_advanced_widget.getWorkspaceDir()
        project_arg = "-proj %s" % file_utils.quote_path(workspace) if workspace.strip() else ""

        chunk_size = self.getChunkSize()
        frames_str = self.getFrameRangeString()
        frames = seqLister.expandSeq(frames_str.split(","), None)

        # Use the task frames generator to dispense the appropriate amount of
        # frames per task, generating a command for each task to execute
        tasks_data = []
        frames_generator = submitter.TaskFramesGenerator(frames, chunk_size=chunk_size, uniform_chunk_step=True)
        for start_frame, end_frame, step, task_frames in frames_generator:
            task_cmd = cmd_template % (renderer_arg,
                                       start_frame,
                                       end_frame,
                                       step,
                                       render_layer_args,
                                       project_arg,
                                       file_utils.quote_path(maya_filepath_nodrive))

            # Generate tasks data
            # convert the list of frame ints into a single string expression
            # TODO:(lws) this is silly. We should keep this as a native int list.
            task_frames_str = ", ".join(seqLister.condenseSeq(task_frames))
            tasks_data.append({"command": task_cmd,
                               "frames": task_frames_str})
        return tasks_data