def commander_execute(self, msg, flags):
        # Stop recording
        lx.eval('replay.record stop')

        macro = replay.Macro()

        # Hack to fix crash bug.
        macro.select_event_treeview()

        if not macro.file_path:
            return

        if not macro.unsaved_changes:
            return

        if modo.dialogs.yesNo(message("MECCO_REPLAY", "REVERT_DIALOG_TITLE"), message("MECCO_REPLAY", "REVERT_FILE_MSG")) == 'yes':

            # No unsaved changes
            macro.unsaved_changes = False

            # Reload saved data
            macro.parse('open', macro.file_path)

            # Rebuild treeview
            macro.rebuild_view()

            notifier = replay.Notifier()
            notifier.Notify(lx.symbol.fCMDNOTIFY_CHANGE_ALL)
示例#2
0
 def commander_execute(self, msg, flags):
     # Register Undo object performing operation and apply it
     macro = replay.Macro()
     if macro.all_suppressed():
         modo.dialogs.alert(message("MECCO_REPLAY", "EMPTY_MACRO"), message("MECCO_REPLAY", "EMPTY_MACRO_MSG"), dtype='warning')
         return
     undo_svc = lx.service.Undo()
     if undo_svc.State() != lx.symbol.iUNDO_INVALID:
         step = UndoStep()
         try:
             step.undo_Forward()
         except:
             return
         undo_svc.Record(step)
示例#3
0
    def commander_execute(self, msg, flags):
        """Saves the current Macro() object to the destination stored in its
        `file_path` property. If `file_path` is `None`, prompt for a destination. Unlike
        `replay.fileSave` this command can save in multiple formats."""

        # Stop recording
        lx.eval('replay.record stop')

        macro = replay.Macro()

        format_val = self.commander_arg_value(0)
        file_path = self.commander_arg_value(1)

        if file_path is None:
            file_path = modo.dialogs.customFile(
                dtype='fileSave',
                title=message("MECCO_REPLAY", "EXPORT_DIALOG_TITLE"),
                names=macro.export_format_names,
                unames=macro.export_format_unames,
                ext=macro.export_format_extensions,
                path=self._path)
            if file_path is None:
                return
            self.__class__._path = file_path
            format_val = lx.eval('dialog.fileSaveFormat ?')

        replay.Macro().render(format_val, file_path)
示例#4
0
    def commander_execute(self, msg, flags):
        # Stop recording
        lx.eval('replay.record stop')

        macro = replay.Macro()

        if macro.file_path:
            lx.eval('cmds.mapKey command:{replay.runScript {%s}}' %
                    macro.file_path)

        else:
            default_path = lx.eval('query platformservice alias ? {scripts:}')

            # Get the path from the user, if not given as argument:
            file_path = modo.dialogs.customFile(
                dtype='fileOpen',
                title=message("MECCO_REPLAY", "KEY_MAPPING_SCRIPT"),
                names=macro.import_format_names,
                unames=macro.import_format_unames,
                patterns=macro.import_format_patterns,
                path=default_path)
            if file_path is None:
                return

            lx.eval('cmds.mapKey command:{@{%s}}' % file_path)
    def commander_execute(self, msg, flags):

        # Stop recording
        lx.eval('replay.record stop')

        file_path = replay.Macro().file_path

        if file_path is None:
            lx.eval('replay.saveAs')

        try:
            file_path = replay.Macro().file_path
            lx.eval('!!file.open {%s}' % file_path)
            lx.eval('replay.fileClose')
        except:
            modo.dialogs.alert(
                message("MECCO_REPLAY", "OPEN_FILE_FAIL"),
                message("MECCO_REPLAY", "OPEN_FILE_FAIL_MSG",
                        basename(file_path)))
示例#6
0
    def commander_execute(self, msg, flags):
        prompt_save = self.commander_arg_value(0, True)

        # Stop recording
        lx.eval('replay.record stop')

        macro = replay.Macro()

        # Hack to fix crash bug.
        macro.select_event_treeview()

        # If content is not empty ask user for save
        if prompt_save and macro.unsaved_changes and not macro.is_empty:
            file_path = macro.file_path
            if file_path is None:
                file_path = "Untitled"
            if modo.dialogs.yesNo(
                    message("MECCO_REPLAY", "ASK_FOR_SAVE_DIALOG_TITLE"),
                    message("MECCO_REPLAY",
                            "ASK_FOR_SAVE_DIALOG_MSG")) == 'yes':
                # If file path is not assigned ask for new file path
                if macro.file_path is None:
                    file_path = modo.dialogs.customFile(dtype = 'fileSave', title = message("MECCO_REPLAY", "SAVE_DIALOG_TITLE"), \
                                                 names = ('LXM',), unames = ('LXM file'), ext=('LXM',))
                    if file_path is None:
                        return

                macro.render_LXM(file_path)

        # No more file path
        macro.file_path = None
        macro.file_format = None
        macro.unsaved_changes = False

        # Clear current macro
        macro.clear()
        # Rebuild treeview
        macro.rebuild_view()

        notifier = replay.Notifier()
        notifier.Notify(lx.symbol.fCMDNOTIFY_CHANGE_ALL)
示例#7
0
    def commander_execute(self, msg, flags):

        # Stop recording
        lx.eval('replay.record stop')

        # Open the replay palette
        lx.eval('layout.createOrClose ReplayPalette {ReplayPalette} true {Replay Palette} width:400 height:600 persistent:true style:palette')

        # Try to get the path from the command line:
        input_path = self.commander_arg_value(0)

        macro = replay.Macro()

        # Get the path from the user, if not given as argument:
        if not input_path:
            input_path = modo.dialogs.customFile(
                dtype = 'fileOpen',
                title = message("MECCO_REPLAY", "OPEN_DIALOG_TITLE"),
                names = macro.import_format_names,
                unames = macro.import_format_unames,
                patterns = macro.import_format_patterns,
                path = self._path
            )
            if input_path is None:
                return
            self.__class__._path = input_path

        # Parse the file in replay.Macro() and rebuild the view:
        try:
            macro.parse('open', input_path)
            # If successfully parsed add to recently-opened
            lx.eval('replay.fileOpenAddRecent {%s}' % input_path)
        except Exception as err:
            lx.out("Error ", str(err))
            modo.dialogs.alert(message("MECCO_REPLAY", "OPEN_FILE_FAIL"), message("MECCO_REPLAY", "OPEN_FILE_FAIL_MSG", str(err)), dtype='warning')

        finally:
            macro.rebuild_view()
            notifier = replay.Notifier()
            notifier.Notify(lx.symbol.fCMDNOTIFY_CHANGE_ALL)
    def commander_execute(self, msg, flags):

        # Stop recording
        lx.eval('replay.record stop')

        # Try to get the path from the command line:
        input_path = self.commander_arg_value(0)

        macro = replay.Macro()

        # Get the path from the user, if not given as argument:
        if not input_path:
            input_path = modo.dialogs.customFile(
                dtype='fileOpen',
                title=message("MECCO_REPLAY", "OPEN_DIALOG_TITLE"),
                names=macro.import_format_names,
                unames=macro.import_format_unames,
                patterns=macro.import_format_patterns,
                path=self._path)
            if input_path is None:
                return
            self.__class__._path = input_path

        # Parse the file in replay.Macro() and rebuild the view:
        try:
            macro.parse('insert', input_path)
            replay.Macro().unsaved_changes = True
        except Exception as err:
            modo.dialogs.alert(message("MECCO_REPLAY", "OPEN_FILE_FAIL"),
                               message("MECCO_REPLAY", "OPEN_FILE_FAIL_MSG",
                                       str(err)),
                               dtype='warning')

        finally:
            macro.rebuild_view()
            notifier = replay.Notifier()
            notifier.Notify(lx.symbol.fCMDNOTIFY_CHANGE_ALL)
示例#9
0
    def list_scripts(self):
        path = lx.eval('query platformservice alias ? {%s}' %
                       self.commander_arg_value(0))

        commands_list = []
        for sub in [
                f for f in os.listdir(path)
                if is_valid_script(os.path.join(path, f))
        ]:
            commands_list.append((os.path.join(path,
                                               sub), os.path.basename(sub)))

        commands_list.append(('', '(%s)' % message("MECCO_REPLAY", "REFRESH")))

        return commands_list
示例#10
0
    def commander_execute(self, msg, flags):

        # Try to get the path from the command line:
        input_path = self.commander_arg_value(0)

        macro = replay.Macro()

        # Get the path from the user, if not given as argument:
        if not input_path:
            input_path = modo.dialogs.customFile(
                dtype = 'fileOpen',
                title = message("MECCO_REPLAY", "RUN_DIALOG_TITLE"),
                names = macro.import_format_names,
                unames = macro.import_format_unames,
                patterns = macro.import_format_patterns
            )
            if input_path is None:
                return

        if macro.file_path == input_path and macro.unsaved_changes and not macro.is_empty:
            if modo.dialogs.yesNo(message("MECCO_REPLAY", "ASK_FOR_SAVE_BEFORE_RUN_DIALOG_TITLE"), message("MECCO_REPLAY", "ASK_FOR_SAVE_BEFORE_RUN_DIALOG_MSG")) == 'yes':
                macro.render(macro.file_format, macro.file_path)

        lx.eval('@{%s}' % input_path)
    def commander_execute(self, msg, flags):
        comment = self.commander_arg_value(0)
        macro = replay.Macro()

        # Check if selection exists
        selecteds = macro.selected_descendants
        if len(selecteds) == 0:
            modo.dialogs.alert(message("MECCO_REPLAY",
                                       "NO_SELECTED_COMMAND_MSG"),
                               dtype='warning')
            return

        # Collect list of selected command paths
        paths = list()
        for sel in selecteds:
            paths.append(sel.path)

        # Register Undo object performing operation and apply it
        undo_svc = lx.service.Undo()
        if undo_svc.State() != lx.symbol.iUNDO_INVALID:
            undo_svc.Apply(UndoInsertComment(paths, comment))
示例#12
0
    def commander_execute(self, msg, flags):

        # Stop recording
        lx.eval('replay.record stop')

        macro = replay.Macro()

        file_path = None
        file_format = macro.file_format
        # If there is no associated file path try to get from command line or prompt the user for new destination

        if file_path is None:
            # Try to get the path from the command line:
            file_path = self.commander_arg_value(0)
            file_format = "lxm"

            # Prompt the user
            if not file_path:
                file_path = modo.dialogs.customFile(dtype='fileSave',
                                                    title=message(
                                                        "MECCO_REPLAY",
                                                        "SAVE_DIALOG_TITLE"),
                                                    names=('LXM', ),
                                                    unames=('LXM file', ),
                                                    ext=('LXM', ),
                                                    path=self._path)
                if file_path is None:
                    return
                self.__class__._path = file_path
            # And save it for the next time
            macro.file_path = file_path

        macro.render(file_format, file_path)

        lx.eval('!!replay.fileClose')
        lx.eval('replay.fileOpen {%s}' % file_path)

        # Add to recently-opened
        lx.eval('replay.fileOpenAddRecent {%s}' % file_path)
示例#13
0
    def cmd_Query(self, index, vaQuery):
        """Fires whenever the value is displayed in the form. Should return the value(s)
        to be displayed in the edit field. If multiple values are provided, MODO will
        display "mixed..." in the edit field for batch editing."""

        # Create the ValueArray object
        va = lx.object.ValueArray()
        va.set(vaQuery)

        if index != 1:
            return lx.result.OK

        # GATHER VALUES
        # -------------

        argName = self.commander_args()['argName']

        datatype, hints, default = self.arg_info(1)

        argValues = set()
        for arg in self.args_by_argName(argName):
            argValues.add((arg.value))

        # If there are no values to return, don't bother.
        if not argValues:
            return lx.result.OK

        values_list = list(argValues)

        # RETURN VALUES
        # -------------

        # Need to add the proper datatype based on result from commander_query
        for value in values_list:
            # Sometimes we get passed empty values. Ignore those.
            if value is None:
                value = default

            if value is None:
                continue

            # Sadly, I am not aware of any way of handling datatypes except
            # by manually testing for them and doing the appropriate action.
            # MODO doesn't make this easy.

            # Strings
            if datatype in [
                    lx.symbol.sTYPE_DATE, lx.symbol.sTYPE_DATETIME,
                    lx.symbol.sTYPE_FILEPATH, lx.symbol.sTYPE_STRING,
                    lx.symbol.sTYPE_VERTMAPNAME
            ]:
                try:
                    va.AddString(str(value))
                except:
                    raise Exception(message("MECCO_REPLAY", "INVALID_STRING"),
                                    value, type(value), datatype)

            # Text Value Hints
            elif (datatype == lx.symbol.sTYPE_INTEGER) and hints:
                for idx, name in hints:
                    if name == value:
                        va.AddInt(idx)

            # Booleans
            elif datatype == lx.symbol.sTYPE_BOOLEAN:
                va.AddInt(1 if value.lower() in ['true', 'on', 'yes'] else 0)

            # Integers
            elif datatype in [
                    lx.symbol.sTYPE_INTEGER, lx.symbol.sTYPE_BOOLEAN
            ]:
                va.AddInt(int(value if value else 0))

            # Floats
            elif datatype in [
                    lx.symbol.sTYPE_ACCELERATION, lx.symbol.sTYPE_AXIS,
                    lx.symbol.sTYPE_COLOR1, lx.symbol.sTYPE_FLOAT,
                    lx.symbol.sTYPE_FORCE, lx.symbol.sTYPE_LIGHT,
                    lx.symbol.sTYPE_DISTANCE, lx.symbol.sTYPE_MASS,
                    lx.symbol.sTYPE_PERCENT, lx.symbol.sTYPE_SPEED,
                    lx.symbol.sTYPE_TIME, lx.symbol.sTYPE_UVCOORD
            ]:
                va.AddFloat(float(value))

            # Angles need to be converted to radians
            elif datatype in [lx.symbol.sTYPE_ANGLE]:
                va.AddFloat(math.radians(float(value)))

            # Vectors (i.e. strings that need parsing)
            elif datatype in [
                    lx.symbol.sTYPE_ANGLE3, lx.symbol.sTYPE_COLOR,
                    lx.symbol.sTYPE_DISTANCE3, lx.symbol.sTYPE_FLOAT3,
                    lx.symbol.sTYPE_PERCENT3, '&item'
            ]:
                emptyValue = va.AddEmptyValue()
                emptyValue.SetString(str(value))

            # If the datatype isn't handled explicitly above, we try adding it
            # to a generic value object. Failing that, barf.
            else:
                try:
                    va.AddValue(value)
                except:
                    raise Exception(
                        message("MECCO_REPLAY", "QUERY_DATATYPE_DETECT_ERROR"))

        return lx.result.OK
示例#14
0
    def valid_for_record(self, cmd, isResult=False):

        # Recording is disabled by user.
        if not self.state:
            return False

        # Recording `layout.createOrClose` is optional. It's important that we not only
        # skip the command itself, but also any sub-commands within it. As such, we disarm
        # until isResult. (Hence `if not self.armed:` happens _after_ this check.)
        if cmd.Name(
        ) == 'layout.createOrClose' and not self.layoutCreateOrClose:
            self.debug_path_print(
                cmd.Name() + " - Recording disabled by preference. Ignore.")
            self.armed = False
            if isResult:
                self.armed = True
            return False

        # Recording is disarmed for internal reasons.
        if not self.armed:
            return False

        # Never record "quiet" commands.
        if (cmd.Flags() & lx.symbol.fCMD_QUIET):
            self.debug_path_print(cmd.Name() + " - Quiet command. Ignore.")
            return False

        # Never record replay commands.
        if cmd.Name().startswith("replay."):
            self.debug_path_print(cmd.Name() + " - Replay command. Ignore.")
            return False

        # BLACK LIST
        # Certain commands can be safely ignored. These can be added here.
        # Note that any ignored command's sub-commands _will_ be recorded.
        if cmd.Name() in [
                'tool.attr', 'tool.noChange', 'actionCenter.state',
                'workPlane.state', 'falloff.state', 'layout.restore',
                'view3d.toggleHUD'
        ]:
            self.debug_path_print(cmd.Name() + " - Black list. Ignore.")
            return False

        # We cannot record undo/redo. There is no reliable method of doing so.
        # Instead, we simply stop recording.
        if cmd.Name() in ['app.undo', 'app.redo']:
            if isResult:
                self.queue_lazy_visitor(
                    replay_record_kill,
                    message("MECCO_REPLAY", "UNDO_DURING_RECORDING"),
                    message("MECCO_REPLAY", "CANNOT_RECORD_MSG", cmd.Name()))
            return False

        # We cannot record interactive selections (i.e. clicking in the viewport to select).
        # Instead, we simply warn the user and stop recording.
        # NOTE: This can cause crashes. Be careful.
        if cmd.Name() in ['select.paint', 'select.lasso']:
            if isResult:
                self.queue_lazy_visitor(
                    replay_record_kill,
                    message("MECCO_REPLAY", "INTERACTIVE_DURING_RECORDING"),
                    message("MECCO_REPLAY", "CANNOT_RECORD_MSG", cmd.Name()))
            return False

        # If we pass all of the above tests, we're good to record.
        return True
示例#15
0
# python

import lx, lxifc, modo, replay
from replay import message as message
"""A simple example of a blessed MODO command using the commander module.
https://github.com/adamohern/commander for details"""

PREFIXES = [('', message("MECCO_REPLAY", "PREFIX_NONE")),
            ('!', message("MECCO_REPLAY", "PREFIX_SUPPRESS_DIALOGS")),
            ('!!', message("MECCO_REPLAY", "PREFIX_SUPPRESS_ALL_DIALOGS")),
            ('+', message("MECCO_REPLAY", "PREFIX_SHOW_DIALOGS")),
            ('++', message("MECCO_REPLAY", "PREFIX_SHOW_ALL_DIALOGS")),
            ('q', message("MECCO_REPLAY", "PREFIX_SHOW_COMMAND_DIALOG"))]


class CommandClass(replay.commander.CommanderClass):
    """Sets the prefix for the currently selected command(s) to one of the standard
    dialog prefixes:

        `'!'`   - Suppress dialogs.
        `'!!'`  - Suppress all dialogs.
        `'+'`   - Show dialogs.
        `'++'`  - Show all dialogs.
        `'?'`   - Show command dialog.

    NOTE: Since commands cannot accept `?` as an argument, use `q` for `?`.

    See http://sdk.luxology.com/wiki/Command_System:_Executing#Special_Prefixes"""
    def commander_arguments(self):
        return [{
            'name': 'command_prefix',
    def prepare_action_list(self, mode, index):

        # Checking mode validity
        if mode not in ['up', 'down', 'top', 'bottom', 'index']:
            modo.dialogs.alert(message("MECCO_REPLAY", "INVALID_MODE"),
                               message("MECCO_REPLAY", "INVALID_MODE_MSG",
                                       mode),
                               dtype='warning')
            return None

        macro = replay.Macro()

        # Checking index range
        if (mode == 'index') and (index >= len(macro.children)):
            modo.dialogs.alert(message("MECCO_REPLAY", "OUT_OF_RANGE"),
                               message("MECCO_REPLAY", "OUT_OF_RANGE_MSG",
                                       index),
                               dtype='warning')
            return None

        # Checking if selection exists
        if len(macro.selected_children) == 0:
            modo.dialogs.alert(message("MECCO_REPLAY", "NO_SELECTED_COMMAND"),
                               message("MECCO_REPLAY",
                                       "NO_SELECTED_COMMAND_MSG"),
                               dtype='warning')
            return None

        actionList = MoveActionList()

        # Getting
        sel_children = macro.selected_children

        # If going up, we move up starting with the top of the list and move down.
        if mode == "up":
            for child in sel_children:
                actionList.append(child.index, child.index - 1)

        elif mode == "down":
            # If going any other direction, start
            sel_children.sort(key=lambda x: x.index, reverse=True)

            for child in sel_children:
                actionList.append(child.index, child.index + 1)

        elif mode == "top":
            for child in sel_children:
                actionList.append(child.index, 0)

        elif mode == "bottom":
            # If going any other direction, start
            sel_children.sort(key=lambda x: x.index, reverse=True)

            for child in sel_children:
                actionList.append(child.index, len(child.parent.children) - 1)

        elif mode == "index":
            # Sort all children standing below target index in reverse order
            sel_children_above = [x for x in sel_children if x.index > index]
            sel_children_below = [x for x in sel_children if x.index <= index]
            sel_children_below.sort(key=lambda x: x.index, reverse=True)
            for child in sel_children_above + sel_children_below:
                actionList.append(child.index, index)

        return actionList