Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Nuke's lib.read #476

Merged
merged 9 commits into from
Dec 13, 2019
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion avalon/nuke/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
"""

from .lib import (
add_publish_knob,
maintained_selection,
read,

add_publish_knob,
get_node_path,
)

Expand Down Expand Up @@ -58,6 +60,8 @@
"parse_container",
"update_container",

"read",

# Experimental
"viewer_update_and_undo_stop",

Expand Down
70 changes: 68 additions & 2 deletions avalon/nuke/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,24 @@ class Knobby(object):
Args:
type (string): Nuke knob type name
value: Value to be set with `Knob.setValue`, put `None` if not required
flags (list, optional): Knob flags to be set with `Knob.setFlag`
*args: Args other than knob name for initializing knob class

"""

def __init__(self, type, value, *args):
def __init__(self, type, value, flags=None, *args):
self.type = type
self.value = value
self.flags = flags or []
self.args = args

def create(self, name, nice=None):
knob_cls = getattr(nuke, self.type)
knob = knob_cls(name, nice, *self.args)
if self.value is not None:
knob.setValue(self.value)
for flag in self.flags:
knob.setFlag(flag)
return knob


Expand Down Expand Up @@ -195,6 +199,66 @@ def nice_naming(key):
return knobs


EXCLUDED_KNOB_TYPE_ON_READ = (
20, # Tab Knob
26, # Text Knob (But for backward compatibility, still be read
# if value is not an empty string.)
)


def read(node):
"""Return user-defined knobs from given `node`

Args:
node (nuke.Node): Nuke node object

Returns:
list: A list of nuke.Knob object

"""
def compat_prefixed(knob_name):
if knob_name.startswith("avalon:"):
return knob_name[len("avalon:"):]
elif knob_name.startswith("ak:"):
return knob_name[len("ak:"):]
else:
return knob_name

data = dict()

pattern = ("(?<=addUserKnob {)"
davidlatwe marked this conversation as resolved.
Show resolved Hide resolved
"([0-9]*) (\S*)" # Matching knob type and knob name
"(?=[ |}])")
tcl_script = node.writeKnobs(nuke.WRITE_USER_KNOB_DEFS)
result = re.search(pattern, tcl_script)

if result:
first_user_knob = result.group(2)
# Collect user knobs from the end of the knob list
for knob in reversed(node.allKnobs()):
knob_name = knob.name()
if not knob_name:
# Ignore unnamed knob
continue

knob_type = nuke.knob(knob.fullyQualifiedName(), type=True)
value = knob.value()

if (
knob_type not in EXCLUDED_KNOB_TYPE_ON_READ or
# For compating read-only string data that imprinted
# by `nuke.Text_Knob`.
(knob_type == 26 and value)
):
key = compat_prefixed(knob_name)
data[key] = value

if knob_name == first_user_knob:
break

return data


def add_publish_knob(node):
"""Add Publish knob to node

Expand Down Expand Up @@ -252,7 +316,9 @@ def set_avalon_knob_data(node, data=None, prefix="avalon:"):
if key in editable:
create[name] = value
else:
create[name] = Knobby("Text_Knob", str(value))
create[name] = Knobby("String_Knob",
str(value),
flags=[nuke.READ_ONLY])

if tab_name in existed_knobs:
tab_name = None
Expand Down
19 changes: 8 additions & 11 deletions avalon/nuke/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,28 +107,25 @@ def parse_container(node):
node (nuke.Node): Nuke's node object to read imprinted data

Returns:
container (dict): imprinted container data
"""
data = lib.get_avalon_knob_data(node)
dict: The container schema data for this container node.

if not isinstance(data, dict):
return
"""
data = lib.read(node)

# (TODO) Remove key validation when `ls` has re-implemented.
#
# If not all required data return the empty container
required = ["schema", "id", "name",
"namespace", "loader", "representation"]

if not all(key in data for key in required):
return

container = {key: data[key] for key in required}

# Store the node's name
container["objectName"] = node["name"].value()
data["objectName"] = node["name"].value()
# Store reference to the node object
container["_node"] = node
data["_node"] = node

return container
return data


def update_container(node, keys=None):
Expand Down