Exemplo n.º 1
0
 def get_last_solve_results(self):
     attr = const.COLLECTION_ATTR_LONG_NAME_SOLVER_RESULTS
     raw_data_list = self._get_attr_data(attr)
     solres_list = []
     for raw_data in raw_data_list:
         solres = solveresult.SolveResult(raw_data)
         solres_list.append(solres)
     return solres_list
Exemplo n.º 2
0
def _run_validate_action(vaction):
    """
    Call a single validate action, and see what happens.

    :param vaction: Validation action object to be run.
    :type vaction: Action

    :return:
        A tuple of 3 parts; First, did the validation succeed (as
        boolean)? Second, the user message we present for the state.
        Third, metrics about the solve (number of parameters, number
        of errors, and number of frames to solve)
    :rtype: (bool, str, (int, int, int))
    """
    num_param = 0
    num_err = 0
    num_frames = 0

    valid = True
    message = ('Validated parameters, errors and frames: '
               'param=%r errors=%r frames=%r')
    metrics = (num_param, num_err, num_frames)
    if not isinstance(vaction, api_action.Action):
        message = message % (num_param, num_err, num_frames)
        return valid, message, metrics
    vfunc, vargs, vkwargs = api_action.action_to_components(vaction)

    num_frames = len(vkwargs.get('frame', []))
    if num_frames == 0:
        valid = False
        metrics = (num_param, num_err, num_frames)
        msg = ('Failed to validate number of frames: '
               'param=%r errors=%r frames=%r')
        message = msg % (num_param, num_err, num_frames)
        return valid, message, metrics

    vfunc_is_mmsolver = api_action.action_func_is_mmSolver(vaction)
    if vfunc_is_mmsolver is False:
        return valid, message, metrics

    solve_data = vfunc(*vargs, **vkwargs)
    solres = solveresult.SolveResult(solve_data)
    print_stats = solres.get_print_stats()
    num_param = print_stats.get('number_of_parameters', 0)
    num_err = print_stats.get('number_of_errors', 0)
    metrics = (num_param, num_err, num_frames)
    if num_param == 0 or num_err == 0 or num_param > num_err:
        valid = False
        msg = ('Failed to validate number of parameters and errors: '
               'param=%r errors=%r frames=%r')
        message = msg % (num_param, num_err, num_frames)
        return valid, message, metrics
    message = message % (num_param, num_err, num_frames)
    return valid, message, metrics
Exemplo n.º 3
0
def _run_validate_action(vaction):
    num_param = 0
    num_err = 0
    num_frames = 0

    valid = True
    message = ('Validated parameters, errors and frames: '
               'param=%r errors=%r frames=%r')
    metrics = (num_param, num_err, num_frames)
    if not isinstance(vaction, api_action.Action):
        message = message % (num_param, num_err, num_frames)
        return valid, message, metrics
    vfunc, vargs, vkwargs = api_action.action_to_components(vaction)

    num_frames = len(vkwargs.get('frame', []))
    if num_frames == 0:
        valid = False
        metrics = (num_param, num_err, num_frames)
        msg = ('Failed to validate number of frames: '
               'param=%r errors=%r frames=%r')
        message = msg % (num_param, num_err, num_frames)
        return valid, message, metrics

    vfunc_is_mmsolver = api_action.action_func_is_mmSolver(vaction)
    if vfunc_is_mmsolver is False:
        return valid, message, metrics

    solve_data = vfunc(*vargs, **vkwargs)
    solres = solveresult.SolveResult(solve_data)
    print_stats = solres.get_print_stats()
    num_param = print_stats.get('number_of_parameters', 0)
    num_err = print_stats.get('number_of_errors', 0)
    metrics = (num_param, num_err, num_frames)
    if num_param == 0 or num_err == 0 or num_param > num_err:
        valid = False
        msg = ('Failed to validate number of parameters and errors: '
               'param=%r errors=%r frames=%r')
        message = msg % (num_param, num_err, num_frames)
        return valid, message, metrics
    message = message % (num_param, num_err, num_frames)
    return valid, message, metrics
Exemplo n.º 4
0
    def execute(self, verbose=False, refresh=False, prog_fn=None, status_fn=None):
        """
        Compile the collection, then pass that data to the 'mmSolver' command.

        The mmSolver command will return a list of strings, which will then be
        passed to the SolveResult class so the user can query the raw data
        using an interface.

        :return: List of SolveResults from the executed collection.
        :rtype: [SolverResult, ..]
        """
        # Ensure the plug-in is loaded, so we fail before trying to run.
        api_utils.load_plugin()

        # If 'refresh' is 'on' change all viewports to 'isolate
        # selected' on only the markers and bundles being solved. This
        # will speed up computations, especially per-frame solving as
        # it will not re-compute any invisible nodes (such as rigs or
        # image planes).
        panel_objs = {}
        panel_img_pl_vis = {}
        panels = self.__get_all_model_panels()
        if refresh is True:
            for panel in panels:
                state = maya.cmds.isolateSelect(
                    panel,
                    query=True,
                    state=True)
                nodes = None
                if state is True:
                    nodes = self.__get_isolated_nodes(panel)
                panel_objs[panel] = nodes
                panel_img_pl_vis[panel] = self.__get_image_plane_visibility(panel)

        # Save current frame, to revert to later on.
        cur_frame = maya.cmds.currentTime(query=True)

        undo_state = maya.cmds.undoInfo(query=True, state=True)
        undo_id = 'mmSolver.api.collection.execute: ' + str(uuid.uuid4())
        try:
            if undo_state is True:
                maya.cmds.undoInfo(openChunk=True, chunkName=undo_id)
            self.__set_progress(prog_fn, 0)
            self.__set_status(status_fn, 'Solver Initializing...')
            api_utils.set_solver_running(True)

            # Set the first current time to the frame before current.
            # This is to help trigger evaluations on the 'current
            # frame', if the current frame is the same as the first
            # frame.
            maya.cmds.currentTime(
                cur_frame - 1,
                edit=True,
                update=True
            )

            # Check for validity
            solres_list = []
            if self.is_valid() is False:
                LOG.warning('Collection not valid: %r', self.get_node())
                return solres_list
            kwargs_list = self._compile()
            self.__set_progress(prog_fn, 1)

            # Isolate all nodes used in all of the kwargs to be run.
            if refresh is True:
                isolate_nodes = set()
                for kwargs in kwargs_list:
                    isolate_nodes |= self.__generate_isolate_nodes(kwargs)
                if len(isolate_nodes) == 0:
                    raise excep.NotValid
                isolate_node_list = list(isolate_nodes)
                for panel in panels:
                    self.__set_image_plane_visibility(panel, False)
                    self.__set_isolated_nodes(panel, isolate_node_list, True)

            # Run Solver...
            start = 0
            total = len(kwargs_list)
            for i, kwargs in enumerate(kwargs_list):
                frame = kwargs.get('frame')
                self.__set_status(status_fn, 'Evaluating frames %r' % frame)
                if frame is None or len(frame) == 0:
                    raise excep.NotValid

                debug_file_path = kwargs.get('debugFile', None)
                if debug_file_path is not None:
                    options_file_path = debug_file_path.replace('.log', '.flags')
                    text = pprint.pformat(kwargs)
                    with open(options_file_path, 'w') as file_:
                        file_.write(text)

                # HACK: Overriding the verbosity, irrespective of what
                # the solver verbosity value is set to.
                if verbose is True:
                    kwargs['verbose'] = True

                # HACK for single frame solves.
                save_node_attrs = []
                is_single_frame = self.__is_single_frame(kwargs)
                if is_single_frame is True:
                    save_node_attrs = self.__disconnect_animcurves(kwargs)

                # Run Solver Maya plug-in command
                solve_data = maya.cmds.mmSolver(**kwargs)

                # Revert special HACK for single frame solves
                if is_single_frame is True:
                    self.__reconnect_animcurves(kwargs, save_node_attrs)

                # Create SolveResult.
                solres = solveresult.SolveResult(solve_data)
                solres_list.append(solres)

                # Update progress
                ratio = float(i) / float(total)
                percent = float(start) + (ratio * (100.0 - start))
                self.__set_progress(prog_fn, int(percent))

                if solres.get_success() is False:
                    msg = 'Solver failed!!!'
                    self.__set_status(status_fn, 'ERROR:' + msg)
                    LOG.error(msg)

                # Refresh the Viewport.
                if refresh is True:
                    maya.cmds.currentTime(
                        frame[0],
                        edit=True,
                        update=True
                    )
                    maya.cmds.refresh()
        except:
            solres_list = []
            # TODO: If we have failed, should we attempt to clean up the mess
            # and undo the entire undo chunk?
            raise
        finally:
            if refresh is True:
                for panel, objs in panel_objs.items():
                    if objs is None:
                        # No original objects, disable 'isolate
                        # selected' after resetting the objects.
                        self.__set_isolated_nodes(panel, [], False)
                        img_pl_vis = panel_img_pl_vis.get(panel, True)
                        self.__set_image_plane_visibility(panel, img_pl_vis)
                    else:
                        self.__set_isolated_nodes(panel, list(objs), True)

            self.__set_progress(prog_fn, 100)
            api_utils.set_solver_running(False)

            if undo_state is True:
                maya.cmds.undoInfo(closeChunk=True, chunkName=undo_id)
            maya.cmds.currentTime(cur_frame, edit=True, update=True)
        return solres_list
Exemplo n.º 5
0
    def execute(
            self,
            verbose=False,
            # TODO: Refactor arguments into a 'Preferences' object
            # to hold the different preferences.
            refresh=False,
            force_update=False,
            do_isolate=False,
            # TODO: Allow a dict to be passed to the function
            # specifying the object type and the visibility status
            # during solving. This allows us to turn on/off any
            # object type during solving. If an argument is not
            # given or is None, the object type visibility will
            # not be changed.
            display_image_plane=False,
            prog_fn=None,
            status_fn=None,
            info_fn=None):
        """
        Compile the collection, then pass that data to the 'mmSolver' command.

        The mmSolver command will return a list of strings, which will then be
        passed to the SolveResult class so the user can query the raw data
        using an interface.

        :param verbose: Print extra solver information while a solve is
                        running.
        :type verbose: bool

        :param refresh: Should the solver refresh the viewport while
                        solving?
        :type refresh: bool

        :param force_update: Force updating the DG network, to help the
                             solver in case of a Maya evaluation DG bug.
        :type force_update: bool

        :param do_isolate: Isolate only solving objects while running solve.
        :type do_isolate: bool

        :param display_image_plane: Display Image Planes while solving?
        :type display_image_plane: bool

        :param prog_fn: The function used report progress messages to
                        the user.
        :type prog_fn: callable or None

        :param status_fn: The function used to report status messages
                          to the user.
        :type status_fn: callable or None

        :param info_fn: The function used to report information
                        messages to the user.
        :type info_fn: callable or None

        :return: List of SolveResults from the executed collection.
        :rtype: [SolverResult, ..]
        """
        start_time = time.time()

        # Ensure the plug-in is loaded, so we fail before trying to run.
        api_utils.load_plugin()

        # If 'refresh' is 'on' change all viewports to 'isolate
        # selected' on only the markers and bundles being solved. This
        # will speed up computations, especially per-frame solving as
        # it will not re-compute any invisible nodes (such as rigs or
        # image planes).
        panel_objs = {}
        panel_img_pl_vis = {}
        panels = viewport_utils.get_all_model_panels()
        if refresh is True:
            for panel in panels:
                if do_isolate is True:
                    state = maya.cmds.isolateSelect(panel,
                                                    query=True,
                                                    state=True)
                    nodes = None
                    if state is True:
                        nodes = viewport_utils.get_isolated_nodes(panel)
                    panel_objs[panel] = nodes
                panel_img_pl_vis[
                    panel] = viewport_utils.get_image_plane_visibility(panel)

        # Save current frame, to revert to later on.
        cur_frame = maya.cmds.currentTime(query=True)

        try:
            collectionutils.run_progress_func(prog_fn, 0)
            ts = solveresult.format_timestamp(time.time())
            collectionutils.run_status_func(status_fn, 'Solve start (%s)' % ts)
            api_state.set_solver_running(True)

            # Check for validity
            solres_list = []
            if self.is_valid() is False:
                LOG.warning('Collection not valid: %r', self.get_node())
                return solres_list
            kwargs_list = self._compile()
            collectionutils.run_progress_func(prog_fn, 1)

            # Isolate all nodes used in all of the kwargs to be run.
            # Note; This assumes the isolated objects are visible, but
            # they may actually be hidden.
            if refresh is True:
                s = time.time()
                if do_isolate is True:
                    isolate_nodes = set()
                    for kwargs in kwargs_list:
                        isolate_nodes |= collectionutils.generate_isolate_nodes(
                            kwargs)
                    if len(isolate_nodes) == 0:
                        raise excep.NotValid
                    isolate_node_list = list(isolate_nodes)
                    for panel in panels:
                        viewport_utils.set_isolated_nodes(
                            panel, isolate_node_list, True)

                for panel in panels:
                    viewport_utils.set_image_plane_visibility(
                        panel, display_image_plane)
                e = time.time()
                LOG.debug('Perform Pre-Isolate; time=%r', e - s)

            # Set the first current time to the frame before current.
            # This is to help trigger evaluations on the 'current
            # frame', if the current frame is the same as the first
            # frame.
            frame_list = []
            for kwargs in kwargs_list:
                frame_list += kwargs.get('frame', [])
            frame_list = list(set(frame_list))
            frame_list = list(sorted(frame_list))
            is_whole_solve_single_frame = len(frame_list) == 1
            if is_whole_solve_single_frame is False:
                s = time.time()
                maya.cmds.currentTime(
                    cur_frame - 1,
                    edit=True,
                    update=force_update,
                )
                e = time.time()
                LOG.debug('Update previous of current time; time=%r', e - s)

            # Run Solver...
            marker_nodes = []
            start = 0
            total = len(kwargs_list)
            for i, kwargs in enumerate(kwargs_list):
                frame = kwargs.get('frame')
                collectionutils.run_status_func(info_fn,
                                                'Evaluating frames %r' % frame)
                if frame is None or len(frame) == 0:
                    raise excep.NotValid

                # Write solver flags to a debug file.
                debug_file_path = kwargs.get('debugFile', None)
                if debug_file_path is not None:
                    options_file_path = debug_file_path.replace(
                        '.log', '.flags')
                    text = pprint.pformat(kwargs)
                    with open(options_file_path, 'w') as file_:
                        file_.write(text)

                # HACK: Overriding the verbosity, irrespective of what
                # the solver verbosity value is set to.
                if verbose is True:
                    kwargs['verbose'] = True

                # HACK for single frame solves.
                save_node_attrs = []
                is_single_frame = collectionutils.is_single_frame(kwargs)
                if is_single_frame is True:
                    save_node_attrs = collectionutils.disconnect_animcurves(
                        kwargs)

                # Run Solver Maya plug-in command
                solve_data = maya.cmds.mmSolver(**kwargs)

                # Revert special HACK for single frame solves
                if is_single_frame is True:
                    collectionutils.reconnect_animcurves(
                        kwargs, save_node_attrs)

                # Create SolveResult.
                solres = solveresult.SolveResult(solve_data)
                solres_list.append(solres)

                # Update progress
                ratio = float(i) / float(total)
                percent = float(start) + (ratio * (100.0 - start))
                collectionutils.run_progress_func(prog_fn, int(percent))

                # Check if the user wants to stop solving.
                cmd_cancel = solres.get_user_interrupted()
                gui_cancel = api_state.get_user_interrupt()
                if cmd_cancel is True or gui_cancel is True:
                    msg = 'Cancelled by User'
                    api_state.set_user_interrupt(False)
                    collectionutils.run_status_func(status_fn,
                                                    'WARNING: ' + msg)
                    LOG.warning(msg)
                    break
                if solres.get_success() is False:
                    msg = 'Solver failed!!!'
                    collectionutils.run_status_func(status_fn, 'ERROR: ' + msg)
                    LOG.error(msg)

                marker_nodes += [x[0] for x in kwargs.get('marker', [])]

                # Refresh the Viewport.
                if refresh is True:
                    # TODO: If we solve per-frame without "refresh"
                    # on, then we get wacky solvers
                    # per-frame. Interestingly, the 'force_update'
                    # does not seem to make a difference, just the
                    # 'maya.cmds.refresh' call.
                    #
                    # Test scene file:
                    # ./tests/data/scenes/mmSolverBasicSolveD_before.ma
                    s = time.time()
                    maya.cmds.currentTime(
                        frame[0],
                        edit=True,
                        update=force_update,
                    )
                    maya.cmds.refresh()
                    e = time.time()
                    LOG.debug('Refresh Viewport; time=%r', e - s)
        finally:
            if refresh is True:
                s = time.time()
                for panel, objs in panel_objs.items():
                    if objs is None:
                        # No original objects, disable 'isolate
                        # selected' after resetting the objects.
                        if do_isolate is True:
                            viewport_utils.set_isolated_nodes(panel, [], False)
                        img_pl_vis = panel_img_pl_vis.get(panel, True)
                        viewport_utils.set_image_plane_visibility(
                            panel, img_pl_vis)
                    else:
                        if do_isolate is True:
                            viewport_utils.set_isolated_nodes(
                                panel, list(objs), True)
                e = time.time()
                LOG.debug('Finally; reset isolate selected; time=%r', e - s)

            collectionutils.run_status_func(status_fn, 'Solve Ended')
            collectionutils.run_progress_func(prog_fn, 100)
            api_state.set_solver_running(False)

            maya.cmds.currentTime(cur_frame, edit=True, update=True)

        # Store output information of the solver.
        end_time = time.time()
        duration = end_time - start_time
        self._set_last_solve_timestamp(end_time)
        self._set_last_solve_duration(duration)
        self._set_last_solve_results(solres_list)
        return solres_list
Exemplo n.º 6
0
    def execute(self, verbose=False, refresh=False, prog_fn=None, status_fn=None):
        """
        Compile the collection, then pass that data to the 'mmSolver' command.

        The mmSolver command will return a list of strings, which will then be
        passed to the SolveResult class so the user can query the raw data
        using an interface.

        :return: List of SolveResults
        :rtype: list of solveresult.SolverResult
        """
        # Ensure the plug-in is loaded, so we fail before trying to run.
        api_utils.load_plugin()

        # Save current frame, to revert to later on.
        cur_frame = maya.cmds.currentTime(query=True)

        undo_state = maya.cmds.undoInfo(query=True, state=True)
        undo_id = 'mmSolver.api.collection.execute: ' + str(uuid.uuid4())
        try:
            if undo_state is True:
                maya.cmds.undoInfo(openChunk=True, chunkName=undo_id)
            self.__set_progress(prog_fn, 0)
            self.__set_status(status_fn, 'Solver Initializing...')

            # Check for validity
            solres_list = []
            if self.is_valid() is False:
                LOG.warning('collection not valid: %r', self.get_node())
                return solres_list
            kwargs_list = self._compile()
            self.__set_progress(prog_fn, 1)

            # Run Solver...
            start = 0
            total = len(kwargs_list)
            for i, kwargs in enumerate(kwargs_list):
                frame = kwargs.get('frame')
                self.__set_status(status_fn, 'Evaluating frames %r' % frame)
                if frame is None or len(frame) == 0:
                    raise excep.NotValid

                # HACK: Overriding the verbosity, irrespective of what
                # the solver verbosity value is set to.
                if verbose is True:
                    kwargs['verbose'] = True

                # HACK for single frame solves.
                save_node_attrs = []
                is_single_frame = self.__is_single_frame(kwargs)
                if is_single_frame is True:
                    save_node_attrs = self.__disconnect_animcurves(kwargs)

                # Run Solver Maya plug-in command
                solve_data = maya.cmds.mmSolver(**kwargs)

                # Revert special HACK for single frame solves
                if is_single_frame is True:
                    self.__reconnect_animcurves(kwargs, save_node_attrs)

                # Create SolveResult.
                solres = solveresult.SolveResult(solve_data)
                solres_list.append(solres)

                # Update progress
                ratio = float(i) / float(total)
                percent = float(start) + (ratio * (100.0 - start))
                self.__set_progress(prog_fn, int(percent))

                if solres.get_success() is False:
                    msg = 'Solver failed!!!'
                    self.__set_status(status_fn, 'ERROR:' + msg)
                    LOG.error(msg)

                # Refresh the Viewport.
                if refresh is True:
                    self.__set_status(status_fn, 'Refresh Viewport...')
                    maya.cmds.currentTime(
                        frame[0],
                        edit=True,
                        update=True
                    )
                    maya.cmds.refresh()
        except:
            solres_list = []
            # TODO: If we have failed, should we attempt to clean up the mess
            # and undo the entire undo chunk?
            raise
        finally:
            self.__set_progress(prog_fn, 100)

            if undo_state is True:
                maya.cmds.undoInfo(closeChunk=True, chunkName=undo_id)
            maya.cmds.currentTime(cur_frame, edit=True, update=True)
        return solres_list
Exemplo n.º 7
0
def execute(col,
            options=None,
            validate_mode=None,
            log_level=None,
            prog_fn=None,
            status_fn=None,
            info_fn=None):
    """
    Compile the collection, then pass that data to the 'mmSolver' command.

    The mmSolver command will return a list of strings, which will then be
    passed to the SolveResult class so the user can query the raw data
    using an interface.

    :param col: The Collection to execute.
    :type col: Collection

    :param options: The options for the execution.
    :type options: ExecuteOptions

    :param validate_mode: How should the solve validate? Must be one of
                          the VALIDATE_MODE_VALUE_LIST values.
    :type validate_mode: str or None

    :param log_level: The log level for the execution.
    :type log_level: str

    :param prog_fn: The function used report progress messages to
                    the user.
    :type prog_fn: callable or None

    :param status_fn: The function used to report status messages
                      to the user.
    :type status_fn: callable or None

    :param info_fn: The function used to report information
                    messages to the user.
    :type info_fn: callable or None

    :return: List of SolveResults from the executed collection.
    :rtype: [SolverResult, ..]
    """
    if options is None:
        options = createExecuteOptions()
    if validate_mode is None:
        validate_mode = const.VALIDATE_MODE_NONE_VALUE
    assert validate_mode in const.VALIDATE_MODE_VALUE_LIST
    if log_level is None:
        log_level = const.LOG_LEVEL_DEFAULT
    assert isinstance(log_level, (str, unicode))

    start_time = time.time()

    # Ensure the plug-in is loaded, so we fail before trying to run.
    api_utils.load_plugin()
    assert 'mmSolver' in dir(maya.cmds)

    vp2_state = viewport_utils.get_viewport2_active_state()

    panels = viewport_utils.get_all_model_panels()
    panel_objs, panel_node_type_vis = preSolve_queryViewportState(
        options, panels
    )

    # Save current frame, to revert to later on.
    cur_frame = maya.cmds.currentTime(query=True)

    try:
        if options.disable_viewport_two is True:
            viewport_utils.set_viewport2_active_state(False)
        preSolve_updateProgress(prog_fn, status_fn)

        # Check for validity and compile actions.
        solres_list = []
        withtest = validate_mode in [const.VALIDATE_MODE_PRE_VALIDATE_VALUE,
                                     const.VALIDATE_MODE_AT_RUNTIME_VALUE]
        col_node = col.get_node()
        sol_list = col.get_solver_list()
        mkr_list = col.get_marker_list()
        attr_list = col.get_attribute_list()
        try:
            s = time.time()
            action_list, vaction_list = api_compile.collection_compile(
                col_node,
                sol_list,
                mkr_list,
                attr_list,
                withtest=withtest,
                prog_fn=prog_fn,
                status_fn=status_fn
            )
            e = time.time()
            LOG.debug('compile time (execute): %r', e - s)
        except excep.NotValid as e:
            LOG.warning(e)
            return solres_list
        collectionutils.run_progress_func(prog_fn, 1)

        if validate_mode == 'pre_validate':
            valid, msg, metrics_list = _run_validate_action_list(vaction_list)
            if valid is not True:
                LOG.warning(msg)
                return solres_list

        # Prepare frame solve
        preSolve_setIsolatedNodes(action_list, options, panels)
        preSolve_triggerEvaluation(action_list, cur_frame, options)

        # Run Solver Actions...
        start = 0
        total = len(action_list)
        for i, (action, vaction) in enumerate(zip(action_list, vaction_list)):
            if isinstance(vaction, api_action.Action) and validate_mode == 'at_runtime':
                valid, message, metrics = _run_validate_action(vaction)
                if valid is not True:
                    LOG.warn(message)
                    return

            func, args, kwargs = api_action.action_to_components(action)
            func_is_mmsolver = api_action.action_func_is_mmSolver(action)

            save_node_attrs = None
            is_single_frame = None
            if func_is_mmsolver is True:
                frame = kwargs.get('frame')
                collectionutils.run_status_func(info_fn, 'Evaluating frames %r' % frame)
                if frame is None or len(frame) == 0:
                    raise excep.NotValid

                # Write solver flags to a debug file.
                debug_file_path = kwargs.get('debugFile', None)
                if debug_file_path is not None:
                    options_file_path = debug_file_path.replace('.log', '.flags')
                    text = pprint.pformat(kwargs)
                    with open(options_file_path, 'w') as file_:
                        file_.write(text)

                # Overriding the verbosity, irrespective of what
                # the solver verbosity value is set to.
                if log_level is not None and log_level.lower() == 'verbose':
                    kwargs['verbose'] = True

                # HACK for single frame solves.
                save_node_attrs = []
                is_single_frame = collectionutils.is_single_frame(kwargs)
                if is_single_frame is True:
                    save_node_attrs = collectionutils.disconnect_animcurves(kwargs)

            # Run Solver Maya plug-in command
            solve_data = func(*args, **kwargs)

            # Revert special HACK for single frame solves
            if func_is_mmsolver is True:
                if is_single_frame is True:
                    collectionutils.reconnect_animcurves(kwargs, save_node_attrs)

            # Create SolveResult.
            solres = None
            if solve_data is not None and func_is_mmsolver is True:
                solres = solveresult.SolveResult(solve_data)
                solres_list.append(solres)

            # Update Progress
            interrupt = postSolve_setUpdateProgress(
                start, i, total, solres,
                prog_fn, status_fn
            )
            if interrupt is True:
                break

            # Refresh the Viewport.
            if func_is_mmsolver is True:
                frame = kwargs.get('frame')
                postSolve_refreshViewport(options, frame)
    finally:
        postSolve_setViewportState(
            options, panel_objs, panel_node_type_vis
        )
        collectionutils.run_status_func(status_fn, 'Solve Ended')
        collectionutils.run_progress_func(prog_fn, 100)
        api_state.set_solver_running(False)
        if options.disable_viewport_two is True:
            viewport_utils.set_viewport2_active_state(vp2_state)
        maya.cmds.currentTime(
            cur_frame,
            edit=True,
            update=options.force_update
        )

    # Store output information of the solver.
    end_time = time.time()
    duration = end_time - start_time
    col._set_last_solve_timestamp(end_time)
    col._set_last_solve_duration(duration)
    col._set_last_solve_results(solres_list)
    return solres_list
Exemplo n.º 8
0
def execute(col,
            options=None,
            validate_mode=None,
            log_level=None,
            prog_fn=None,
            status_fn=None,
            info_fn=None):
    """
    Compile the collection, then pass that data to the 'mmSolver' command.

    The mmSolver command will return a list of strings, which will then be
    passed to the SolveResult class so the user can query the raw data
    using an interface.

    :param col: The Collection to execute.
    :type col: Collection

    :param options: The options for the execution.
    :type options: ExecuteOptions

    :param validate_mode: How should the solve validate? Must be one of
                          the VALIDATE_MODE_VALUE_LIST values.
    :type validate_mode: str or None

    :param log_level: The log level for the execution.
    :type log_level: str

    :param prog_fn: The function used report progress messages to
                    the user.
    :type prog_fn: callable or None

    :param status_fn: The function used to report status messages
                      to the user.
    :type status_fn: callable or None

    :param info_fn: The function used to report information
                    messages to the user.
    :type info_fn: callable or None

    :return: List of SolveResults from the executed collection.
    :rtype: [SolverResult, ..]
    """
    if options is None:
        options = createExecuteOptions()
    if validate_mode is None:
        validate_mode = const.VALIDATE_MODE_PRE_VALIDATE_VALUE
    assert validate_mode in const.VALIDATE_MODE_VALUE_LIST
    if log_level is None:
        log_level = const.LOG_LEVEL_DEFAULT
    assert isinstance(log_level, pycompat.TEXT_TYPE)
    validate_runtime = validate_mode == const.VALIDATE_MODE_AT_RUNTIME_VALUE
    validate_before = validate_mode == const.VALIDATE_MODE_PRE_VALIDATE_VALUE

    start_time = time.time()

    # Ensure the plug-in is loaded, so we (do not) fail before trying
    # to run.
    api_utils.load_plugin()
    assert 'mmSolver' in dir(maya.cmds)

    vp2_state = viewport_utils.get_viewport2_active_state()
    current_eval_manager_mode = maya.cmds.evaluationManager(query=True,
                                                            mode=True)

    panels = viewport_utils.get_all_model_panels()
    panel_objs, panel_node_type_vis = preSolve_queryViewportState(
        options, panels)

    # Save scene state, to revert to later on.
    cur_frame = maya.cmds.currentTime(query=True)
    prev_auto_key_state = maya.cmds.autoKeyframe(query=True, state=True)
    prev_cycle_check = maya.cmds.cycleCheck(query=True, evaluation=True)

    # State information needed to revert reconnect animation curves in
    # 'finally' block.
    kwargs = {}
    save_node_attrs = []
    func_is_mmsolver = False
    is_single_frame = False

    try:
        if options.disable_viewport_two is True:
            viewport_utils.set_viewport2_active_state(False)
        maya.cmds.autoKeyframe(edit=True, state=False)
        maya.cmds.evaluationManager(mode='off')
        maya.cmds.cycleCheck(evaluation=False)
        preSolve_updateProgress(prog_fn, status_fn)

        # Check for validity and compile actions.
        solres_list = []
        withtest = validate_mode in [
            const.VALIDATE_MODE_PRE_VALIDATE_VALUE,
            const.VALIDATE_MODE_AT_RUNTIME_VALUE
        ]
        sol_list = col.get_solver_list()
        mkr_list = col.get_marker_list()
        attr_list = col.get_attribute_list()
        try:
            action_list, vaction_list = api_compile.collection_compile(
                col,
                sol_list,
                mkr_list,
                attr_list,
                withtest=withtest,
                prog_fn=prog_fn,
                status_fn=status_fn)
        except excep.NotValid as e:
            LOG.warn(e)
            return solres_list
        collectionutils.run_progress_func(prog_fn, 1)

        vaction_state_list = []
        if validate_before is True:
            vaction_state_list = _run_validate_action_list(vaction_list)
            assert len(vaction_list) == len(vaction_state_list)

        # Prepare frame solve
        preSolve_setIsolatedNodes(action_list, options, panels)
        preSolve_triggerEvaluation(action_list, cur_frame, options)

        # Ensure prediction attributes are created and initialised.
        collectionutils.set_initial_prediction_attributes(
            col, attr_list, cur_frame)

        # Run Solver Actions...
        message_hashes = set()
        start = 0
        total = len(action_list)
        number_of_solves = 0
        for i, (action, vaction) in enumerate(zip(action_list, vaction_list)):
            state = None
            if len(vaction_state_list) > 0:
                # We have pre-computed the state list.
                state = vaction_state_list[i]
            if isinstance(vaction, api_action.Action) and validate_runtime:
                # We will calculate the state just-in-time.
                state = _run_validate_action(vaction)
            if state is not None:
                if state.status != const.ACTION_STATUS_SUCCESS:
                    assert isinstance(state, ActionState)
                    h = hash(state.message)
                    if h not in message_hashes:
                        LOG.warn(state.message)
                    message_hashes.add(h)
                    # Skip this action, since the test failed.
                    continue

            func, args, kwargs = api_action.action_to_components(action)
            func_is_mmsolver = api_action.action_func_is_mmSolver(action)

            if func_is_mmsolver is True:
                frame = kwargs.get('frame')
                collectionutils.run_status_func(info_fn,
                                                'Evaluating frames %r' % frame)
                if frame is None or len(frame) == 0:
                    raise excep.NotValid

                # Write solver flags to a debug file.
                debug_file_path = kwargs.get('debugFile', None)
                if debug_file_path is not None:
                    options_file_path = debug_file_path.replace(
                        '.log', '.flags')
                    text = pprint.pformat(kwargs)
                    with open(options_file_path, 'w') as file_:
                        file_.write(text)

                # Overriding the verbosity, irrespective of what the
                # solver verbosity value is set to.
                kwargs['verbose'] = False
                if log_level is not None and log_level.lower() == 'verbose':
                    kwargs['verbose'] = True

                # HACK for single frame solves.
                is_single_frame = collectionutils.is_single_frame(kwargs)
                if is_single_frame is True:
                    save_node_attrs = collectionutils.disconnect_animcurves(
                        kwargs)
                else:
                    # Reset the data structure so in the 'finally'
                    # block we can detect animcurves are not needing
                    # to be reset.
                    save_node_attrs = []

            # Run Solver Maya plug-in command
            solve_data = func(*args, **kwargs)

            # Revert special HACK for single frame solves
            if func_is_mmsolver is True:
                if is_single_frame is True:
                    collectionutils.reconnect_animcurves(
                        kwargs, save_node_attrs)
                    # Reset the data structure so in the 'finally'
                    # block we can detect animcurves are not needing
                    # to be reset.
                    save_node_attrs = []

            # Create SolveResult.
            solres = None
            if solve_data is not None and func_is_mmsolver is True:
                solres = solveresult.SolveResult(solve_data)
                solres_list.append(solres)

            if func_is_mmsolver is True and solres.get_success() is True:
                frame = kwargs.get('frame')
                if frame is None or len(frame) == 0:
                    raise excep.NotValid
                single_frame = frame[0]

                if number_of_solves == 0:
                    collectionutils.set_initial_prediction_attributes(
                        col, attr_list, single_frame)
                # Count number of solves, so we don't need to set the
                # initial prediction attributes again.
                number_of_solves += 1

                # Calculate the mean, variance values, and predict the
                # next attribute value.
                collectionutils.compute_attribute_value_prediction(
                    col,
                    attr_list,
                    single_frame,
                )

            # Update Progress
            interrupt = postSolve_setUpdateProgress(start, i, total, solres,
                                                    prog_fn, status_fn)
            if interrupt is True:
                break

            # Refresh the Viewport.
            if func_is_mmsolver is True:
                frame = kwargs.get('frame')
                postSolve_refreshViewport(options, frame)
    finally:
        # If something has gone wrong, or the user cancels the solver
        # without finishing, then we make sure to reconnect animcurves
        # that were disconnected for single frame solves.
        if func_is_mmsolver is True and is_single_frame is True:
            if len(save_node_attrs):
                collectionutils.reconnect_animcurves(kwargs, save_node_attrs)

        postSolve_setViewportState(options, panel_objs, panel_node_type_vis)
        collectionutils.run_status_func(status_fn, 'Solve Ended')
        collectionutils.run_progress_func(prog_fn, 100)
        maya.cmds.evaluationManager(mode=current_eval_manager_mode[0])
        maya.cmds.cycleCheck(evaluation=prev_cycle_check)
        maya.cmds.autoKeyframe(edit=True, state=prev_auto_key_state)
        api_state.set_solver_running(False)
        if options.disable_viewport_two is True:
            viewport_utils.set_viewport2_active_state(vp2_state)
        maya.cmds.currentTime(cur_frame,
                              edit=True,
                              update=options.force_update)

    # Store output information of the solver.
    end_time = time.time()
    duration = end_time - start_time
    col._set_last_solve_timestamp(end_time)
    col._set_last_solve_duration(duration)
    col._set_last_solve_results(solres_list)
    return solres_list
Exemplo n.º 9
0
def _run_validate_action(vaction):
    """
    Call a single validate action, and see what happens.

    :param vaction: Validation action object to be run.
    :type vaction: Action

    :return:
        A tuple of 3 parts; First, did the validation succeed (as
        boolean)? Second, the user message we present for the state.
        Third, metrics about the solve (number of parameters, number
        of errors, and number of frames to solve)
    :rtype: ActionState
    """
    if not isinstance(vaction, api_action.Action):
        state = _create_action_state(status=const.ACTION_STATUS_SUCCESS,
                                     message='Action cannot be run.')
        return state
    vfunc, vargs, vkwargs = api_action.action_to_components(vaction)
    vfunc_is_mmsolver = api_action.action_func_is_mmSolver(vaction)

    num_param = 0
    num_err = 0
    frames = list(sorted(vkwargs.get('frame', [])))
    num_frames = len(frames)
    if num_frames == 0 and vfunc_is_mmsolver is True:
        msg = ('Failed to validate number of frames: '
               'param=%r errors=%r frames=%r')
        message = msg % (num_param, num_err, num_frames)
        state = _create_action_state(status=const.ACTION_STATUS_FAILED,
                                     message=message,
                                     error_number=num_err,
                                     parameter_number=num_param,
                                     frames_number=num_frames,
                                     frames=frames)
        return state

    # Run validate function
    solve_data = vfunc(*vargs, **vkwargs)

    if vfunc_is_mmsolver is False:
        msg = ('Validated parameters, errors and frames: '
               'param=%r errors=%r frames=%r')
        message = msg % (num_param, num_err, num_frames)
        state = _create_action_state(status=const.ACTION_STATUS_SUCCESS,
                                     message=message,
                                     error_number=num_err,
                                     parameter_number=num_param,
                                     frames_number=num_frames,
                                     frames=frames)
        return state

    solres = solveresult.SolveResult(solve_data)
    print_stats = solres.get_print_stats()
    num_param = print_stats.get('number_of_parameters', 0)
    num_err = print_stats.get('number_of_errors', 0)
    if num_param == 0 or num_err == 0 or num_param > num_err:
        msg = 'Invalid parameters and errors, skipping solve: %r'
        message = msg % list(sorted(frames))
        state = _create_action_state(status=const.ACTION_STATUS_FAILED,
                                     message=message,
                                     error_number=num_err,
                                     parameter_number=num_param,
                                     frames_number=num_frames,
                                     frames=frames)
        return state

    msg = ('Validated parameters, errors and frames: '
           'param=%r errors=%r frames=%r')
    message = msg % (num_param, num_err, num_frames)
    state = _create_action_state(status=const.ACTION_STATUS_SUCCESS,
                                 message=message,
                                 error_number=num_err,
                                 parameter_number=num_param,
                                 frames_number=num_frames,
                                 frames=frames)
    return state