示例#1
0
    def execute(self, operation, file_path, **kwargs):
        """
        Main hook entry point

        :operation: String
                    Scene operation to perform

        :file_path: String
                    File path to use if the operation
                    requires it (e.g. open)

        :returns:   Depends on operation:
                    'current_path' - Return the current scene
                                     file path as a String
                    all others     - None
        """

        if operation == "current_path":
            project = fx.activeProject()
            return project.path
        elif operation == "open":
            fx.loadProject(file_path)
        elif operation == "save":
            project = fx.activeProject()
            project.save()
    def execute(self):
        beginUndo("KMFX Clone Reset transforms and frame")

        node = activeNode()

        if node.type == "PaintNode":
            fx.activeProject().save()  # small hack to force state to update

            clonelist = ["0", "1"]  # both clone presets

            for n in clonelist:
                if fx.prefs["KMFX.Reset Clone also resets opacity"] is True:
                    fx.paint.setState('opacity', 100)
                if node.state['paint']['Clone.frameRelative:' + n] is True:
                    fx.paint.setState('Clone.frame:' + n, 0)

                else:
                    fx.paint.setState('Clone.frame:' + n, player.frame)

                fx.paint.setState('Clone.position:' + n, Point3D(0, 0))
                fx.paint.setState('Clone.rotate:' + n, 0)
                fx.paint.setState('Clone.scale:' + n, Point3D(1, 1))

            fx.activeProject().save()

        endUndo()
    def scan_scene(self):
        """
        The scan scene method is executed once at startup and its purpose is
        to analyze the current scene and return a list of references that are
        to be potentially operated on.

        The return data structure is a list of dictionaries. Each scene reference
        that is returned should be represented by a dictionary with three keys:

        - "node": The name of the 'node' that is to be operated on. Most DCCs have
          a concept of a node, path or some other way to address a particular
          object in the scene.
        - "type": The object type that this is. This is later passed to the
          update method so that it knows how to handle the object.
        - "path": Path on disk to the referenced object.

        Toolkit will scan the list of items, see if any of the objects matches
        any templates and try to determine if there is a more recent version
        available. Any such versions are then displayed in the UI as out of date.

        """
        reads = []

        project = fx.activeProject()
        # find source items in project
        for item in project.items:
            if isinstance(item, fx.SourceItem):
                source = item.source
                # label is human readable, but only id is unique
                reads.append({"node": (source.label, item.id),
                              "type": "source",
                              "path": source.property("path").value})

        return reads
示例#4
0
def run():
    import fx
    from tools.sequenceBuilder import SequenceBuilder

    # Grab the current project
    project = fx.activeProject()

    # Check the current selection
    node = fx.activeNode()

    print('[Output To Source]')
    print('\t[Node Name] ' + node.label)

    # Process a source node
    if node.type == 'OutputNode':
        # Find the active OutputNode path
        path = GetOutput(node)
        print('\t[Image] ' + path)

        # Create an image sequence from the url
        builder = SequenceBuilder(path)

        # Load the media into the project
        src = fx.Source(builder.path)

        # Add the other image types
        project.addItem(src)
    else:
        print('\t[Error] Select a Source or Output Node.')
示例#5
0
    def collect_current_silhouette_session(self, settings, parent_item):
        """
        Analyzes the current session open in Maya and parents a subtree of items
        under the parent_item passed in.

        :param dict settings: Configured settings for this collector
        :param parent_item: Root item instance
        """
        # get the current path
        active_project = fx.activeProject()
        if not active_project or not active_project.path:
            # the session has not been saved before (no path determined).
            # provide a save button. the session will need to be saved before
            # validation will succeed.
            self.logger.warning("The silhouette project has not been saved.",
                                extra=self._get_save_as_action())
        file_path = active_project.path

        # Define the item's properties
        properties = {}

        session_item = self._add_file_item(settings, parent_item, file_path,
                                           False, None,
                                           "Current Silhouette Session",
                                           "silhouette.session",
                                           parent_item.context, properties)

        self.logger.info("Collected item: %s" % session_item.name)
        return session_item
示例#6
0
def run():
    import fx

    print(
        '\n\n---------------------------------------------------------------------------------'
    )
    print('Project Explorer')
    print(
        '---------------------------------------------------------------------------------\n'
    )

    # Get the Project
    project = fx.activeProject()
    print('[Project]')
    print('\n\t[Project Path] ' + str(project.label))
    print('\n\t[Project Version] ' + str(project.version))

    print('\n\t[Project Sources]')
    for s in project.sources:
        print('\t\t[Sources] ' + str(s.label))

    print('\n\t[Project Sessions]')
    for s in project.sessions:
        print('\t\t[Sesssion] ' + str(s.label))

    # List all properties
    print('\n\t[Project Properties]')
    for i in range(len(project.properties.keys())):
        key = project.properties.keys()[i]
        print('\t\t[Property] ' + str(key) + ' [Value] "' +
              str(project.properties[key].value) + '"')
示例#7
0
def SaveProject():
    import fx

    # Get the Project
    project = fx.activeProject()

    # Save the project
    project.save()
示例#8
0
def StackVertical():
    import fx

    tool = 'Stack Vertical'
    PrintStatus(tool)
    fx.beginUndo(tool)

    # Get the Project
    project = fx.activeProject()

    # Get the node selection
    sel = fx.selection()

    # Padding width for node count
    padding = len(str(len(sel)))

    # Spacing distance between stacked nodes
    nodeSpacing = 100

    # Use the first selected object as a reference for the Node Y position
    referenceY = 0
    if len(sel) > 0:
        referenceY = sel[0].state.items()[1][1].y
        print('[Reference Y] ' + str(referenceY))

        # Scan all of the selected nodes
        i = 0
        for node in sel:
            # The node.state dict holds {'viewMode': 0, 'graph.pos': Point3D(394.641,22.4925)}
            if (node.state is not None) and (node != sel[0]):
                i = i + 1
                # The Point3D(0,0) datatype has .x and .y attributes
                pos = node.state.items()[1][1]
                if pos is not None:
                    # Stack the nodes side by side
                    node.setState(
                        'graph.pos',
                        fx.Point3D(pos.x, (referenceY + (i * nodeSpacing))))

                    # Read back the results
                    posUpdate = node.state.items()[1][1]
                    if posUpdate is not None:
                        print('[' + str(i).zfill(padding) + '] ' +
                              str(node.label) + ' [Original] [X]' +
                              str(pos.x) + ' [Y] ' + str(pos.y) +
                              ' [Updated] [X]' + str(posUpdate.x) + ' [Y] ' +
                              str(posUpdate.y))
    else:
        print('[Error] Please select 2 or more nodes.')

    fx.endUndo()

    # SaveProject()

    # hide the window
    snapWindow.hide()
示例#9
0
def SnapToGrid():
    import fx

    tool = 'Snap to Grid'
    PrintStatus(tool)
    fx.beginUndo(tool)

    # Get the Project
    project = fx.activeProject()

    # Get the node selection
    sel = fx.selection()

    # Padding width for node count
    padding = len(str(len(sel)))

    i = 0
    for node in sel:
        i = i + 1
        # The node.state dict holds {'viewMode': 0, 'graph.pos': Point3D(394.641,22.4925)}
        if node.state is not None:
            # The Point3D(0,0) datatype has .x and .y attributes
            pos = node.state.items()[1][1]
            if pos is not None:
                # Snap the nodes to a 10 unit grid
                #snapX = round(pos.x, -1)
                #snapY = round(pos.y, -1)

                # Snap to 50 grid units
                snapX = round(float(pos.x) * 2, -2) * 0.5
                snapY = round(float(pos.y) * 2, -2) * 0.5

                # Snap to 100 grid units on X and 50 gird units on Y
                snapX = round(pos.x, -2)
                snapY = round(float(pos.y) * 2, -2) * 0.5

                # Snap the nodes to a 100 unit grid
                #snapX = round(pos.x, -2)
                #snapY = round(pos.y, -2)

                # Update the grid snapped node position
                node.setState('graph.pos', fx.Point3D(snapX, snapY))

                posUpdate = node.state.items()[1][1]
                if posUpdate is not None:
                    print('[' + str(i).zfill(padding) + '] ' +
                          str(node.label) + ' [Original] [X]' + str(pos.x) +
                          ' [Y] ' + str(pos.y) + ' [Updated] [X]' +
                          str(posUpdate.x) + ' [Y] ' + str(posUpdate.y))

    fx.endUndo()

    # SaveProject()

    # hide the window
    snapWindow.hide()
示例#10
0
def AlignHorizontal():
    import fx

    tool = 'Align Horizontal'
    PrintStatus(tool)
    fx.beginUndo(tool)

    # Get the Project
    project = fx.activeProject()

    # Get the node selection
    sel = fx.selection()

    # Padding width for node count
    padding = len(str(len(sel)))

    # Use the first selected object as a reference for the Node X position
    referenceX = 0
    if len(sel) > 0:
        referenceX = sel[0].state.items()[1][1].x
        print('[Reference X] ' + str(referenceX))

        # Scan all of the selected nodes
        i = 0
        for node in sel:
            i = i + 1
            # The node.state dict holds {'viewMode': 0, 'graph.pos': Point3D(394.641,22.4925)}
            if node.state is not None:
                # The Point3D(0,0) datatype has .x and .y attributes
                pos = node.state.items()[1][1]
                if pos is not None:
                    # Snap all the nodes to the same X height
                    node.setState('graph.pos', fx.Point3D(referenceX, pos.y))

                    # Read back the results
                    posUpdate = node.state.items()[1][1]
                    if posUpdate is not None:
                        print('[' + str(i).zfill(padding) + '] ' +
                              str(node.label) + ' [Original] [X]' +
                              str(pos.x) + ' [Y] ' + str(pos.y) +
                              ' [Updated] [X]' + str(posUpdate.x) + ' [Y] ' +
                              str(posUpdate.y))
    else:
        print('[Error] Please select 2 or more nodes.')

    fx.endUndo()

    # SaveProject()

    # hide the window
    snapWindow.hide()
示例#11
0
    def _create_source(self, path, sg_publish_data):
        engine = self.parent.engine

        # silhouette requires format /path/to/file.[start-end].ext
        formatted_path, errors = engine.utils.seq_path_to_silhouette_format(
            self.sgtk, path)
        if errors:
            engine.utils.warn_with_pop_up(self.parent.logger,
                                          "Image path used as is", errors)
        source = fx.Source(formatted_path)

        # add source to project
        project = fx.activeProject()
        project.addItem(source)
示例#12
0
def AlignByCSV():
    import fx
    import csv

    path = '/Applications/SilhouetteFX/Silhouette v7.5/Silhouette.app/Contents/Resources/scripts/node_shape.csv'

    tool = 'Align By CSV'
    PrintStatus(tool)
    fx.beginUndo(tool)

    # Get the Project
    project = fx.activeProject()

    # Get the node selection
    sel = fx.selection()

    # Padding width for node count
    padding = 4

    # How many nodes are selected
    count = len(sel)

    # Prepare CSV reading
    with open(path, 'rb') as fp:
        reader = csv.reader(fp, delimiter=',')

        i = 0
        # Scan all of the selected nodes
        for row in reader:
            # Move onto the next node
            # The node.state dict holds {'viewMode': 0, 'graph.pos': Point3D(394.641,22.4925)}
            if i < count:
                node = sel[i]
                if (node.state is not None):
                    # The Point3D(0,0) datatype has .x and .y attributes
                    node.setState('graph.pos',
                                  fx.Point3D(float(row[0]), float(row[1])))

                    #posUpdate = node.state.items()[1][1]
                    #if posUpdate is not None:
                    # Read back the results
                    # print('{0},{1:.03f},{2:.03f}'.format(str(i).zfill(padding), posUpdate.x, posUpdate.y))
            i = i + 1

    fx.endUndo()

    # SaveProject()

    # hide the window
    snapWindow.hide()
    def _save_session(self, path, version, item):
        """
        Save the current session to the supplied path.
        """

        ensure_folder_exists(os.path.dirname(path))
        active_project = fx.activeProject()
        if path != active_project.path:
            save_path = self.parent.engine.utils.get_stripped_project_path(
                path)
            active_project.save(save_path)
        else:
            active_project.save()

        # Save the updated property
        item.properties.path = path
    def update(self, items):
        """
        Perform replacements given a number of scene items passed from the app.

        Once a selection has been performed in the main UI and the user clicks
        the update button, this method is called.

        The items parameter is a list of dictionaries on the same form as was
        generated by the scan_scene hook above. The path key now holds
        the that each node should be updated *to* rather than the current path.
        """
        engine = self.parent.engine

        # TODO: is there a way to find input nodes from source/source_item?
        project = fx.activeProject()
        source_node_mapping = {}
        for session in project.sessions:
            for node in session.inputs:
                source_id = node.property("stream.primary").value.id
                node_list = source_node_mapping.setdefault(source_id, [])
                node_list.append(node)

        for i in items:
            node_id = i["node"]
            node_type = i["type"]
            new_path = i["path"]

            if node_type == "source":
                source_label, source_item_id = node_id
                engine.log_debug("Path for source %s: Updating to version %s" % (source_label, new_path))

                # update source.property("path")
                source_item = fx.findObject(source_item_id)
                path_property = source_item.source.property("path")
                formatted_path, errors = engine.utils.seq_path_to_silhouette_format(self.sgtk, new_path)
                if errors:
                    engine.utils.warn_with_pop_up(self.parent.logger, "Image path used as is", errors)
                path_property.setValue(formatted_path)

                # update source and node labels.
                # TODO: does silhouette ever have anything in the trailing brackets?
                label = os.path.basename(formatted_path) + " []"

                # TODO: the display doesn't auto-refresh
                source_item.label = label
                for node in source_node_mapping[source_item.source.id]:
                    node.label = label
示例#15
0
def SourcesImport(url):
	import os
	import fx
	from tools.sequenceBuilder import SequenceBuilder
	
	# Grab the current project
	project = fx.activeProject()
	
	# Catch an error when loading media
	try:
		# Create an image sequence from the url
		builder = SequenceBuilder(url)
		
		# Load the media into the project
		src = fx.Source(builder.path)
		
		# Display the results
		statusMsg = '[Import Sources] "' + str(builder.path) + '"'
		fx.status(statusMsg)
		print(statusMsg)
		
		# Layer Names
		print('\t[Layers] ' + str(src.layers))
		
		# Add the images
		if src.layers is not None:
			# Split the EXR multi-part and multi-channel layers apart
			for layer in src.layers:
				print '\t\t[Creating Layer] ' + layer
				
				s = fx.Source(builder.path)
				project.addItem(s)
				
				# Rename the split EXR layer
				# s.label = str(layer)
				s.label = str(s.label) + '_' + str(layer)
				
				# Change the source layer
				if layer != 'default':
					s.property('layer').value = layer
		else:
			# Add the other image types
			project.addItem(src)
	except Exception as e:
		print e
示例#16
0
def SaveByCSV():
    import fx
    import csv

    path = '/Applications/SilhouetteFX/Silhouette v7.5/Silhouette.app/Contents/Resources/scripts/node_shape.csv'

    # Prepare CSV writing
    with open(path, 'wb') as fp:
        writer = csv.writer(fp, delimiter=',')
        # writer.writerow(['X', 'Y'])

        tool = 'Save CSV'
        PrintStatus(tool)
        fx.beginUndo(tool)

        # Get the Project
        project = fx.activeProject()

        # Get the node selection
        sel = fx.selection()

        # Padding width for node count
        padding = len(str(len(sel)))

        if len(sel) > 1:
            # Scan all of the selected nodes
            for node in sel:
                # The node.state dict holds {'viewMode': 0, 'graph.pos': Point3D(394.641,22.4925)}
                if node.state is not None:
                    # The Point3D(0,0) datatype has .x and .y attributes
                    pos = node.state.items()[1][1]
                    if pos is not None:
                        # Read back the results
                        # print('{0:.03f},{1:.03f}'.format(pos.x, pos.y))
                        writer.writerow([pos.x, pos.y])
        else:
            print('[Error] Please select 2 or more nodes.')

        fx.endUndo()
    def _get_dependency_paths(self, node=None):
        """
        Find all dependency paths for the current node. If no node specified,
        will return all dependency paths for the session.

        :param node: Optional node to process
        :return: List of upstream dependency paths
        """
        engine = self.parent.engine

        dependency_paths = set()

        # let's look at sources in the project
        active_project = fx.activeProject()
        for source in active_project.sources:
            source_path = source.property("path").value
            formatted_path, errors = engine.utils.seq_path_from_silhouette_format(
                self.sgtk, source_path)
            if errors:
                self.parent.log_error(errors)
            dependency_paths.add(formatted_path)

        return list(dependency_paths)
示例#18
0
    def execute(self, operation, file_path, context, parent_action,
                file_version, read_only, **kwargs):
        """
        Main hook entry point

        :param operation:       String
                                Scene operation to perform

        :param file_path:       String
                                File path to use if the operation
                                requires it (e.g. open)

        :param context:         Context
                                The context the file operation is being
                                performed in.

        :param parent_action:   This is the action that this scene operation is
                                being executed for.  This can be one of:
                                - open_file
                                - new_file
                                - save_file_as
                                - version_up

        :param file_version:    The version/revision of the file to be opened.  If this is 'None'
                                then the latest version should be opened.

        :param read_only:       Specifies if the file should be opened read-only or not

        :returns:               Depends on operation:
                                'current_path' - Return the current scene
                                                 file path as a String
                                'reset'        - True if scene was reset to an empty
                                                 state, otherwise False
                                all others     - None
        """
        active_project = fx.activeProject()
        temp_dir = os.path.realpath(tempfile.gettempdir())

        if operation == "current_path":
            # return the current project path
            if active_project:
                return active_project.path
            else:
                return None

        elif operation == "open":
            fx.loadProject(file_path)

        elif operation == "save":
            active_project.save()

        elif operation == "save_as":
            initial_project_path = os.path.realpath(active_project.path)

            save_path = self.parent.engine.utils.get_stripped_project_path(
                file_path)
            active_project.save(save_path)

            # delete earlier project directory if it was a temporary path
            if initial_project_path.startswith(temp_dir):
                shutil.rmtree(
                    os.path.dirname(os.path.dirname(initial_project_path)))

        elif operation == "reset":
            """
            Reset the scene to an empty state
            """
            # save activeProject
            exit_and_call_save = False
            if active_project:
                if active_project.path:
                    project_dir = os.path.realpath(
                        os.path.dirname(active_project.path))
                    if not project_dir.startswith(temp_dir):
                        active_project.save()
                    else:
                        exit_and_call_save = True
                else:
                    exit_and_call_save = True

            if exit_and_call_save:
                res = QtGui.QMessageBox.question(
                    QtGui.QApplication.activeWindow(), "Save your scene?",
                    "Your scene has unsaved changes. Save before proceeding?",
                    QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
                    | QtGui.QMessageBox.Cancel)

                if res == QtGui.QMessageBox.Cancel:
                    return False
                elif res == QtGui.QMessageBox.No:
                    pass
                else:
                    # there is an active project with no path or temp path - save it
                    # there is no silhouette python API to open a save file GUI, so just use sgtk
                    self.parent.engine.commands["File Save..."]["callback"]()
                    return False

            if parent_action == "new_file":
                # do new file. silhouette doesn't do unnamed projects well
                new_project_name = os.path.join(tempfile.mkdtemp(),
                                                "tk_silhouette_project")
                new_project = fx.Project(new_project_name)

                # silhouette 7 has method setActiveProject(), which can take None
                fx.activate(new_project)
                new_project.save()

                # make the user save the file immediately,
                # so that we can avoid using the temp location
                self.parent.engine.commands["File Save..."]["callback"]()

        return True
示例#19
0
def DistributeSpacesHorizontal():
    import fx

    tool = 'Distribute Spaces Horizontal'
    PrintStatus(tool)
    fx.beginUndo(tool)

    # Get the Project
    project = fx.activeProject()

    # Get the node selection
    sel = fx.selection()

    # Padding width for node count
    padding = len(str(len(sel)))

    # How many does were selected
    nodeCount = len(sel)

    # Use the first selected object as a reference for the Node position
    referenceStartX = 0
    referenceEndX = 0
    if nodeCount > 0:
        print('[Selected Nodes] ' + str(nodeCount))

        referenceStartX = sel[0].state.items()[1][1].x
        print('[Reference Start X] ' + str(referenceStartX))

        referenceEndX = sel[nodeCount - 1].state.items()[1][1].x
        print('[Reference End X] ' + str(referenceEndX))

        # Start/End Node Distance
        nodeDistance = abs(referenceStartX - referenceEndX)
        print('[Node Distance X] ' + str(nodeDistance))

        # Spacing distance between stacked nodes
        nodeSpacing = (nodeDistance) / (nodeCount - 1)
        print('[Node Spacing X] ' + str(nodeSpacing))

        # Scan all of the selected nodes
        i = 0
        for node in sel:
            # The node.state dict holds {'viewMode': 0, 'graph.pos': Point3D(394.641,22.4925)}
            if (node.state is not None) and (node != sel[0]) and (
                    node != sel[nodeCount - 1]):
                # if (node.state is not None):
                i = i + 1
                # The Point3D(0,0) datatype has .x and .y attributes
                pos = node.state.items()[1][1]
                if pos is not None:
                    # Stack the nodes side by side
                    node.setState(
                        'graph.pos',
                        fx.Point3D((referenceStartX + (i * nodeSpacing)),
                                   pos.y))

                    # Read back the results
                    posUpdate = node.state.items()[1][1]
                    if posUpdate is not None:
                        print('[' + str(i).zfill(padding) + '] ' +
                              str(node.label) + ' [Original] [X]' +
                              str(pos.x) + ' [Y] ' + str(pos.y) +
                              ' [Updated] [X]' + str(posUpdate.x) + ' [Y] ' +
                              str(posUpdate.y))
    else:
        print('[Error] Please select 2 or more nodes.')

    fx.endUndo()

    # SaveProject()

    # hide the window
    snapWindow.hide()
示例#20
0
    def execute(self, **kwargs):
        # fx.beginUndo("KMFX Paint Presets") # undo is not working on this

        paint_presets_path = fx.prefs["KMFX.Paint Presets Path"] if fx.prefs[
            "KMFX.Paint Presets Path"] != "" else os.environ[
                "SFX_SCRIPT_PATH"] + "/KMscripts/paint_presets/"

        #### check if the custom pref path exists and warn user if its wrong
        if paint_presets_path == fx.prefs["KMFX.Paint Presets Path"]:
            if not os.path.exists(paint_presets_path):
                displayError(
                    "The custom path '%s' could be wrong or\nwas not found or can't be read,\nplease check your KMFX preferences!\nFalling back to default path\n %s "
                    % (paint_presets_path, os.environ["SFX_SCRIPT_PATH"] +
                       "/KMscripts/paint_presets/"))
                # print("The custom path '%s' could be wrong / was not found / can't be read, please check your preferences\n falling back to default path\n %s " % (paint_presets_path,os.environ["SFX_SCRIPT_PATH"] + "/KMscripts/paint_presets/"))
                paint_presets_path = os.environ[
                    "SFX_SCRIPT_PATH"] + "/KMscripts/paint_presets/"

        mode = kwargs["mode"] if "mode" in kwargs.keys() else "save"

        node = activeNode()

        if node.type == "PaintNode":
            '''
			the actual brush used it saved on the <item type="string" id="brush"> on the preset.
			looks like the settings for the rest of the preset are not necessary
			'''
            fx.activeProject().save(
            )  ##small hack to force the state to update

            if mode == "save":

                fname = {
                    "id": "fname",
                    "label": "Filename",
                    "value": "Default"
                }
                result = getInput(fields=[fname])
                current = fx.paint.preset
                override = False

                if result != None:
                    dpath = paint_presets_path + "/" + result["fname"] + "/"
                    directory = os.path.dirname(dpath)

                    if os.path.exists(directory):
                        ov = askQuestion("Preset already exists, override?")
                        if ov == False:
                            return  # do not use this with UNDO
                    try:
                        if not os.path.exists(directory):
                            os.makedirs(directory)
                    except:
                        print(
                            "Error creating preset directory, check folder write permissions?\n %s"
                            % directory)
                    for i in range(0, 10):
                        fpath = paint_presets_path + "/" + result[
                            "fname"] + "/" + result["fname"] + "_" + str(
                                i) + '.json'
                        try:
                            fx.paint.preset = i
                            if len(node.state["preset" + str(i)]) > 0:
                                dic = node.state["preset" + str(i)]
                                ppreset = json.dumps(dic,
                                                     cls=GenericJSONEncoder)
                                with open(fpath, 'w') as file:
                                    file.write(ppreset)

                            print("Saved preset %s @ %s" % (i, fpath))

                        except:
                            print("Preset %s skipped" % i)
                            if os.path.exists(fpath):
                                os.remove(fpath)
                                print("Old Preset %s removed" % i)
                            # e = sys.exc_info()
                            # print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)
                try:
                    fx.paint.preset = current  ## go back to original active preset
                except:
                    pass

            elif mode == "load":
                jsonFiles = glob.glob(paint_presets_path + "/**/*.json",
                                      recursive=True)
                filelist = {}
                namecollection = []
                presetsfound = False
                if len(jsonFiles) > 0:
                    for f in jsonFiles:
                        name = os.path.basename(f)
                        name = str(name).rsplit("_", 1)[0]
                        namecollection.append(name)
                    namecollection = list(set(namecollection))
                    presetsfound = True
                else:
                    resulterror = getInput(title="Error",
                                           msg="No presets found")

                if presetsfound:
                    lista = {
                        "id": "list",
                        "label": "List",
                        "value": namecollection[0],
                        "items": namecollection
                    }
                    result = getInput(fields=[lista])
                    loadedpresets = []
                    if result != None:
                        for i in range(0, 10):
                            fx.paint.preset = i
                            try:
                                node.setState("preset" + str(i), None)

                                with open(paint_presets_path + "/" +
                                          result["list"] + "/" +
                                          result["list"] + "_" + str(i) +
                                          '.json') as complex_data:
                                    data = complex_data.read()
                                    b = json.loads(data,
                                                   cls=GenericJSONDecoder)

                                    for ii in b.keys():
                                        fx.paint.setState(ii, b[ii])
                                    fx.paint.savePreset(i)
                                    loadedpresets.append(i)

                            except:
                                pass

                        fx.paint.preset = min(
                            loadedpresets)  ## loads the first available preset