Example #1
0
    def set_knobs(cls, node):
        """
        Set values from context on a given knob.

        Args:
            node (nuke.Node): current node we are baking in the queue.
        """

        if node.knob("set_knobs") and node.knob("set_knobs").value():
            # get set knob list, split, and strip white space
            knobs = node.knob("knobs_to_set").value()
            raw_knobs_to_set = knobs.split(",")

            for raw_knob in raw_knobs_to_set:
                try:
                    knob = raw_knob.strip()
                    # clean up any spaces
                    raw_name, raw_value = knob.split("=")
                    name = raw_name.strip()
                    value = raw_value.strip()

                    getLog().info("Ada: Knobs to set: {0} : {1}".format(
                        name, value))
                    cls.bake_knob(node, name, value=value)
                except ValueError:
                    msg = "Unable to set: {0} missing value after '='"
                    getLog().warning(msg.format(node.name()))
Example #2
0
    def execute_code(node):
        """
        Take code from multi-eval stringe knob, put it in a button
        then execute the button. This allows the user to to create
        complex python script on nodes and reference nuke.thisNode().

        Args:
            node (nuke.Node): Node that hasa execute_code knob.

        Returns:
            bool: True if code execution is fine, otherwise false.
        """

        if node.knob("execute_code") and node.knob("execute_code").value():
            success = False
            # execute code inside a temp knob attached to the node
            py_script_knob = nuke.PyScript_Knob("__run", "Run")
            node.addKnob(py_script_knob)
            code = node.knob("code_to_execute").toScript()
            try:
                py_script_knob.setValue(code)
                py_script_knob.execute()
                success = True
            except Exception as e:
                getLog().warning(
                    "'{0}' failed to execute code:\n{1}\nreason:\n\t{2}\n".
                    format(node.fullName(), code, e))
            finally:
                # if nuke.delete(nuke.thisNode) is called in code to execute
                # the node.removeKnob will throw a ValueError
                if not node:
                    return success

                node.removeKnob(py_script_knob)
                return success
Example #3
0
    def fuel(template):
        """
        Fuel an empty script with a template and set the basic things
            that are required. Views should be handled here but inherited
            from the template graph file.

        Args:
            template (str): Path to template nuke script.

        """
        getLog().info("Ada: Fuel begin.")

        nuke.scriptOpen(template)
        template = nuke.Ada.template.location

        try:
            getLog().info("Ada: Reading template: {0}".format(template))
            nuke.scriptReadFile(template)

        except RuntimeError as err:
            getLog().warning("Ada: '{0}'".format(err))

        start = nuke.Ada.script_frame_range.start
        end = nuke.Ada.script_frame_range.end

        root = nuke.Root()
        root["first_frame"].setValue(start)
        root["last_frame"].setValue(end)

        getLog().info("Ada: setting root range: start: {0}, end: {1}".format(
            start, end))

        getLog().info("Ada: Fuel end.")
Example #4
0
    def execute_callbacks(cls, kind, template_class=None):
        """
        Callbacks are registered as global before/after or template specific.

        Args:
            kind (str): The callback group we want to execute.
            template_class (str): Script class name stored on the root node of Nuke.

        """
        cbs_to_execute = callback_kinds[kind]
        cb_message = "Ada: Executing {kind} callback: {name}"
        for callback_name in cbs_to_execute:
            if kind.startswith("GLOBAL"):
                getLog().info(
                    cb_message.format(kind=" ".join(kind.lower().split("_")),
                                      name=callback_name))
                for cb in cbs_to_execute[callback_name]:
                    cb.run()

            if kind.startswith("TEMPLATE") and template_class == callback_name:
                getLog().info(
                    cb_message.format(kind=" ".join(kind.lower().split("_")),
                                      name=callback_name))
                for cb in cbs_to_execute[callback_name]:
                    cb.run()
Example #5
0
def load_ada_context_from_file():
    """From a root script find an associated ada file with it."""

    root_script = nuke.Root().name()
    if not root_script.endswith(".nk"):
        return

    script_directory = os.path.dirname(root_script)
    script_name = os.path.basename(root_script)

    ada_context_file = "{0}.{1}".format(os.path.splitext(script_name)[0], "ada")
    ada_file_path = os.path.join(script_directory, ada_context_file)

    getLog().info("Ada: Attempting to find context file: {0}".format(ada_file_path))

    if os.path.exists(ada_file_path):
        getLog().debug("Ada: context found: {0}".format(ada_file_path))

        # read the ada context file from the script dir
        f = open(ada_file_path, "rb")
        nuke.Ada.ParseFromString(f.read())
        f.close()

        getLog().debug(
            "Ada: context successfully loaded from file: {0}".format(nuke.Ada)
        )
    elif nuke.Root().knobs().get("__ada"):
        get_ada_from_root = nuke.Root()["__ada"].value()
        nuke.Ada.ParseFromString(get_ada_from_root)
        getLog().debug(
            "Ada: context successfully loaded from root: {0}".format(nuke.Ada)
        )
Example #6
0
    def run(cls, nodes=None, bake_list=None, pause=None):
        """
        Once the nodes are gathered up then we can iterate over them
        and execute each knob on the tab from the top to the bottom.

        Args:
            nodes (list): Un-sorted nodes either a selection in Nuke.
            bake_list (list): List of nodes to be processed, these
                have already been gathered and sorted.
            pause (int): The queue order which you want to stop at.

        Returns:
            list: all the nodes which were executed successfully.
        """
        # any nuke script can add a __template_class_text knob to its
        # root node and register a callback against it
        cls.template_class = (nuke.Root().knobs().get(
            "__template_class__", nuke.Text_Knob("null", "null")).value())
        cls.template_class = None if cls.template_class == "" else cls.template_class

        # if we are not continuing a previous bake, then we need to
        # gather, sort and validate the nodes.
        if not bake_list:
            cls.input_nodes = nodes or nuke.allNodes(recurseGroups=True)
            gathered_nodes = cls.gather(cls.input_nodes)
            bake_list = cls.alpha_numeric_sort(gathered_nodes)

            getLog().info("Ada: Nodes to bake: {0}".format(bake_list))

        # run validation code / frame work before executing tabs
        cls.validate(bake_list)

        # queue nodes for baking
        queue = cls.queue(bake_list)
        getLog().info("template class: {}".format(cls.template_class))

        # execute registered global/template callbacks before
        cls.execute_callbacks("GLOBAL_BEFORE")
        cls.execute_callbacks("TEMPLATE_BEFORE",
                              template_class=cls.template_class)

        # process the nodes which have ada tabs
        results = cls.process(queue, bake_list, pause)

        # execute registered global/template callbacks after
        cls.execute_callbacks("TEMPLATE_AFTER")
        cls.execute_callbacks("GLOBAL_AFTER",
                              template_class=cls.template_class)

        return results
Example #7
0
def ada_knob_changed():
    """
    When a user interacts with the knobs to serialise knob they will be modifying context information, this knob
    changed keeps that context information up to date.
    """

    this_node = nuke.thisNode()
    this_knob = nuke.thisKnob()

    if this_knob.name() == "knobs_to_serialise" and has_ada_tab(this_node):

        # split all the values in knobs_to_serialise by their line
        for alias in this_knob.value().split("\n"):
            current_alias = alias.strip()

            if current_alias == "":
                continue

            # for this alias get the correct object with the data inside the function
            ada_data = deconstruct_knobs_to_serialise(current_alias)

            # check to make sure that the serialised data can be parsed
            if not ada_data:
                continue

            # look up the knob on this node
            knob = this_node[ada_data.knob.strip()]

            # get the current expression
            expression = knob.toScript()

            getLog().info("Current expression {0}:{1}".format(
                knob.name(), expression))

            execution_type = KNOB_TO_EXECUTION_TYPE.get(knob.Class())
            if isinstance(ada_data, KnobAlias):
                set_alias_knob(knob, expression, ada_data, "aliases")
                add_knob_to_ada_tab(this_node, execution_type, "aliases", knob,
                                    ada_data.alias)
            if isinstance(ada_data, KnobInput):
                set_alias_knob(knob, expression, ada_data, "inputs")
                add_knob_to_ada_tab(this_node, execution_type, "inputs", knob,
                                    ada_data.alias)
            if isinstance(ada_data, KnobOutput):
                set_alias_knob(knob, expression, ada_data, "outputs")
                add_knob_to_ada_tab(this_node, execution_type, "outputs", knob,
                                    ada_data.alias)
Example #8
0
    def bake_knobs(cls, node):
        """
        Take the string in the knobs to bake knob and then create a list of knobs to run bake_knob on.

        Args:
            node (nuke.Node): current node we are baking in the queue.
        """
        if node.knob("knobs_to_bake") and node.knob("knobs_to_bake").value():
            # get bake knob list, split, and strip white space
            knobs = node.knob("knobs_to_bake").value()
            raw_knobs_to_set = knobs.split(",")

            for raw_knob in raw_knobs_to_set:
                knob = raw_knob.strip()

                getLog().info("   Ada: Baking Knob: {0}.{1}".format(
                    node.name(), knob))
                cls.bake_knob(node, knob)
Example #9
0
    def process(cls, queues, all_nodes, break_point):
        """
        Bulk of the work happens here, knobs are baked, set, buttons are pressed, code is executed etc.

        Args:
            queues (itertools.groupby): Groups of nodes to process.
            all_nodes (list): List of all nodes to bake.
            break_point (int): Point at which we want Ada to stop executing to inspect something.

        Returns:
            list: Nodes which were successfully execute.
        """
        processed_nodes = []
        for queue_order, queue in queues:
            getLog().info("Ada: Executing Queue: {0}".format(queue_order))

            if queue_order == break_point:
                to_process = list(set(all_nodes) - set(processed_nodes))
                return to_process

            for node_name in list(queue):
                node = nuke.toNode(node_name)
                getLog().info("  Ada: Executing Node {0}".format(node.name()))
                # this is where values are converted from ada
                # expressions to serialised values.
                cls.bake_knobs(node)
                cls.set_knobs(node)

                # buttons are pressed if added in the Ada tab.
                cls.execute_buttons(node)

                # finally code is executed.
                cls.execute_code(node)

                # if all goes well return the node we just processed
                # to the list of processed nodes.
                processed_nodes.append(node_name)

        return processed_nodes
Example #10
0
    def execute_buttons(node):
        """
        Execute any buttons the user has added to the execute knobs list.

        Args:
            node (nuke.Node): The node we are currently baking.
        """
        if node.knob("execute_knobs") and node.knob("execute_knobs").value():
            # get button list, split, and strip white space
            buttons = node.knob("knobs_to_execute").value()
            raw_knobs_to_exec = buttons.split(",")

            for raw_knob in raw_knobs_to_exec:
                knob = raw_knob.strip()
                knob_object = node.knob(knob)
                if not knob_object or not hasattr(knob_object, "execute"):
                    getLog().warning(
                        "Executing knob: '{0}' not found on node '{1}'".format(
                            knob, node.name()))
                else:
                    getLog().info("Ada: Button to execute: {0}".format(knob))
                    knob_object.setFlag(0x0000000000010000)
                    knob_object.execute()
Example #11
0
def set_alias_knob(knob, expression, alias_data, kind):
    """
    Add an expression to the correct knob and add an alias to the ada context or if the user changes it then
    remove the old context item and add a new one.

    Args:
        knob (nuke.Knob): The knob we want to add the expression to.
        expression (str): The current expression on the node's knob.
        alias_data (namedtuple): The data from the knobs_to_serialise knob.
        kind (str):

    """
    this_alias = alias_data.alias.strip()

    value = alias_data.default_value.strip()

    expression_to_set = "[Ada {kind} {value}]".format(kind=kind,
                                                      value=this_alias)

    get_ada_kind = getattr(nuke.Ada, kind)

    if this_alias in get_ada_kind:
        getLog().info("Updating context data: {0} = {1}".format(
            this_alias, value))
        get_ada_kind[this_alias] = value

    elif this_alias not in get_ada_kind:
        getLog().info("Setting context data: {0} = {1}".format(
            this_alias, value))
        get_ada_kind[this_alias] = value
        knob.setExpression(expression_to_set)

    if this_alias not in expression and "[Ada" in expression:
        old_alias = expression.split("]")[0].split(" ")[-1]
        del get_ada_kind[old_alias]
        knob.setExpression(expression_to_set)
    else:
        getLog().info("Updating context data: {0} = {1}".format(
            this_alias, value))
Example #12
0
    def bake_knob(node, name, value=None):
        """
        Function to set a knob using knob=value or bake the knob directly.

        Args:
            node (nuke.Node): A node we are trying to bake a knob on.
            name (str): The knob name we are trying to set.
            value ([Optional str]): If value is None execute the
        """
        knob = node.knob(name)
        if not knob:
            return

        if value is None:
            if isinstance(knob, nuke.Array_Knob):
                views = nuke.views()
                start = nuke.Ada.script_frame_range.start
                end = nuke.Ada.script_frame_range.end
                for view in views:
                    curves = knob.animations(view)
                    for curve in curves:
                        values = set()
                        index = curve.knobIndex()
                        for frame in range(start, end + 1):
                            knob.setKeyAt(frame, index, view)
                            value = curve.evaluate(frame)
                            values.add(value)
                            knob.setValueAt(value, frame, index, view)

                        if len(values) > 1:
                            knob.setExpression("curve",
                                               channel=index,
                                               view=view)
                        else:
                            knob.clearAnimated()  # "BAKE"

            elif isinstance(knob, nuke.File_Knob):
                knob.setValue(str(nuke.tcl("subst", knob.value())))

            elif isinstance(knob, nuke.EvalString_Knob):
                knob.setValue(knob.evaluate())
            else:
                getLog().warning("{}.{} unsupported knob type {}".format(
                    node.name(), name, type(knob)))
        else:
            try:
                knob.clearAnimated()
            except AttributeError:
                pass
            try:
                if isinstance(knob, nuke.Int_Knob):
                    knob.setValue(int(value))
                elif isinstance(knob, nuke.Enumeration_Knob):
                    try:
                        knob.setValue(int(value))
                    except ValueError:
                        knob.setValue(str(value))
                elif isinstance(knob, nuke.Array_Knob):
                    knob.setValue(float(value))
                else:
                    knob.setValue(value)
            except TypeError as ee:
                getLog().warning("Ada: set {}.{}={} TypeError: {}".format(
                    node.name(), name, value, ee))
            except ValueError as ee:
                getLog().warning("Ada: set {}.{}={} ValueError: {}".format(
                    node.name(), name, value, ee))