Skip to content
This repository was archived by the owner on Oct 10, 2024. It is now read-only.

Commit 667d6a4

Browse files
committed
Merge commit
1 parent 0bcd4e8 commit 667d6a4

File tree

15 files changed

+375
-1458
lines changed

15 files changed

+375
-1458
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**What happened?**
11+
A clear and concise description of what the bug is, e.g. *"when I clicked on X, Y happened"*
12+
13+
**What did you expect?**
14+
A similarly short description of your expectations, e.g. *"Z should have happened"*.
15+
16+
**To Reproduce**
17+
Steps to reproduce the behavior, preferably a bullet-list.
18+
19+
**Additional context**
20+
Add any other context about the problem here.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**Is your feature request related to a problem? Please describe.**
11+
A clear and concise description of what the problem is, e.g. *"To many clicks to do X"*
12+
13+
**Describe the solution you'd like**
14+
A clear and concise description of what you want to happen, e.g. *"Wish I could multi-select"*
15+
16+
**Describe alternatives you've considered**
17+
A clear and concise description of any alternative solutions or features you've considered.
18+
19+
**Additional context**
20+
Add any other context or screenshots about the feature request here.

.github/pull_request_template.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Thank you for your contribution to Avalon! Here's how you can get your code merged quickly.
2+
3+
**What's changed?**
4+
Briefly summarise the changes you've made, something human-readable to get the reader up-to-speed with your thought process (hint: everyone loves bullet-lists). If the PR is in response to an existing issue (it should), link to this here.
5+
6+
**Health Check**
7+
To ensure your code lives up the standards of Avalon, consult the [Pull-Request](https://github.com/getavalon/core/blob/master/CONTRIBUTING.md#pull-request) section of `CONTRIBUTION.md` for details.
8+
9+
**Examples**
10+
If you are unsure of how to format your pull-request, have a look at these examples. [#403](https://github.com/getavalon/core/pull/403), [#400](https://github.com/getavalon/core/pull/400)

avalon/nuke/__init__.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
from .lib import (
88
add_publish_knob,
9-
ls_img_sequence,
109
maintained_selection,
1110
get_node_path,
1211
get_avalon_knob_data,
@@ -52,6 +51,13 @@
5251

5352
"Creator",
5453

54+
"file_extensions",
55+
"has_unsaved_changes",
56+
"save_file",
57+
"open_file",
58+
"current_file",
59+
"work_root",
60+
5561
"containerise",
5662
"parse_container",
5763
"update_container",
@@ -64,17 +70,8 @@
6470
"get_avalon_knob_data",
6571
"set_avalon_knob_data",
6672
"add_publish_knob",
67-
"ls_img_sequence",
6873
"maintained_selection",
6974
"get_node_path",
70-
71-
# Workfiles API
72-
"open",
73-
"save",
74-
"current_file",
75-
"has_unsaved_changes",
76-
"file_extensions",
77-
"work_root"
7875
]
7976

8077
# Backwards API compatibility

avalon/nuke/lib.py

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ def reset_selection():
4747
"""
4848
clear_selection_recursive()
4949

50+
Parse user data into Node knobs.
51+
Use `collections.OrderedDict` to ensure knob order.
5052

5153
def select_nodes(nodes):
5254
"""Selects all inputed nodes
@@ -80,6 +82,46 @@ def add_publish_knob(node):
8082
node.addKnob(knob)
8183
return node
8284

85+
Returns:
86+
None
87+
88+
Examples:
89+
```
90+
import nuke
91+
from avalon.nuke import lib
92+
93+
node = nuke.createNode("NoOp")
94+
data = {
95+
# Regular type of attributes
96+
"myList": ["x", "y", "z"],
97+
"myBool": True,
98+
"myFloat": 0.1,
99+
"myInt": 5,
100+
101+
# Creating non-default imprint type of knob
102+
"MyFilePath": lib.Knobby("File_Knob", "/file/path"),
103+
"divider": lib.Knobby("Text_Knob", ""),
104+
105+
# Manual nice knob naming
106+
("my_knob", "Nice Knob Name"): "some text",
107+
108+
# dict type will be created as knob group
109+
"KnobGroup": {
110+
"knob1": 5,
111+
"knob2": "hello",
112+
"knob3": ["a", "b"],
113+
},
114+
115+
# Nested dict will be created as tab group
116+
"TabGroup": {
117+
"tab1": {"count": 5},
118+
"tab2": {"isGood": True},
119+
"tab3": {"direction": ["Left", "Right"]},
120+
},
121+
}
122+
lib.imprint(node, data, tab="Demo")
123+
124+
```
83125

84126
def set_avalon_knob_data(node, data={}, prefix="ak:"):
85127
""" Sets a data into nodes's avalon knob
@@ -226,9 +268,13 @@ def check_subsetname_exists(nodes, subset_name):
226268
return result
227269

228270

229-
def imprint(node, data):
230-
"""Adding `Avalon data` into a node's Avalon Tab/Avalon knob
231-
also including publish knob
271+
class Knobby(object):
272+
"""For creating knob which it's type isn't mapped in `create_knobs`
273+
274+
Args:
275+
type (string): Nuke knob type name
276+
value: Value to be set with `Knob.setValue`, put `None` if not required
277+
*args: Args other than knob name for initializing knob class
232278
233279
Arguments:
234280
node (obj): A nuke's node object
@@ -284,6 +330,24 @@ def ls_img_sequence(path):
284330
return False
285331

286332

333+
def get_avalon_knob_data(node, prefix="avalon:"):
334+
""" Get data from nodes's avalon knob
335+
336+
Arguments:
337+
node (nuke.Node): Nuke node to search for data,
338+
prefix (str, optional): filtering prefix
339+
340+
Returns:
341+
data (dict)
342+
"""
343+
data = {
344+
knob[len(prefix):]: node[knob].value()
345+
for knob in node.knobs().keys()
346+
if knob.startswith(prefix)
347+
}
348+
return data
349+
350+
287351
def fix_data_for_node_create(data):
288352
"""Fixing data to be used for nuke knobs
289353
"""

avalon/nuke/pipeline.py

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
log = logging.getLogger(__name__)
1515

16+
self = sys.modules[__name__]
17+
self._parent = None # Main Window cache
18+
1619
AVALON_CONFIG = os.environ["AVALON_CONFIG"]
1720

1821

@@ -76,6 +79,18 @@ def containerise(node,
7679
node (obj): containerised nuke's node object
7780
7881
"""
82+
data = OrderedDict(
83+
[
84+
("schema", "avalon-core:container-2.0"),
85+
("id", AVALON_CONTAINER_ID),
86+
("name", name),
87+
("namespace", namespace),
88+
("loader", str(loader)),
89+
("representation", context["representation"]["_id"]),
90+
],
91+
92+
**data or dict()
93+
)
7994

8095
data_imprint = OrderedDict({
8196
"schema": "avalon-core:container-2.0",
@@ -126,34 +141,30 @@ def parse_container(node, validate=True):
126141

127142
# Store the node's name
128143
container["objectName"] = node["name"].value()
129-
130144
# Store reference to the node object
131145
container["_node"] = node
132146

133147
return container
134148

135149

136-
def update_container(node, keys=dict()):
150+
def update_container(node, keys=None):
137151
"""Returns node with updateted containder data
138152
139153
Arguments:
140-
node (object): The node in Nuke to imprint as container,
141-
keys (dict): data which should be updated
154+
node (nuke.Node): The node in Nuke to imprint as container,
155+
keys (dict, optional): data which should be updated
142156
143157
Returns:
144-
node (object): nuke node with updated container data
145-
"""
158+
node (nuke.Node): nuke node with updated container data
146159
147160
data = lib.get_avalon_knob_data(node)
148161
149162
container = dict()
150163
container = {key: data[key] for key in data}
151164
152-
for key, value in container.items():
153-
try:
154-
container[key] = keys[key]
155-
except KeyError:
156-
pass
165+
container = parse_container(node)
166+
if not container:
167+
raise TypeError("Not a valid container node.")
157168
158169
node = lib.set_avalon_knob_data(node, container)
159170
@@ -272,6 +283,18 @@ def find_host_config(config):
272283
return config
273284
274285
286+
def get_main_window():
287+
"""Acquire Nuke's main window"""
288+
if self._parent is None:
289+
top_widgets = QtWidgets.QApplication.topLevelWidgets()
290+
name = "Foundry::UI::DockMainWindow"
291+
main_window = next(widget for widget in top_widgets if
292+
widget.inherits("QMainWindow") and
293+
widget.metaObject().className() == name)
294+
self._parent = main_window
295+
return self._parent
296+
297+
275298
def uninstall(config):
276299
"""Uninstall all that was previously installed
277300

@@ -312,13 +335,26 @@ def _install_menu():
312335
api.Session["AVALON_ASSET"], api.Session["AVALON_TASK"]
313336
)
314337
context_menu = menu.addMenu(label)
315-
context_menu.addCommand("Set Context", contextmanager.show)
338+
context_menu.addCommand("Set Context",
339+
lambda: contextmanager.show(
340+
parent=get_main_window())
341+
)
342+
menu.addSeparator()
343+
menu.addCommand("Create...",
344+
lambda: creator.show(parent=get_main_window()))
345+
menu.addCommand("Load...",
346+
lambda: loader.show(parent=get_main_window(),
347+
use_context=True))
348+
menu.addCommand("Publish...",
349+
lambda: publish.show(parent=get_main_window()))
350+
menu.addCommand("Manage...",
351+
lambda: sceneinventory.show(parent=get_main_window()))
316352
317353
menu.addSeparator()
318354
menu.addCommand("Work Files...",
319355
lambda: workfiles.show(
320-
os.environ["AVALON_WORKDIR"]
321-
)
356+
os.environ["AVALON_WORKDIR"],
357+
parent=get_main_window())
322358
)
323359
menu.addSeparator()
324360
menu.addCommand("Create...", creator.show)

avalon/pipeline.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,12 @@ def update_current_task(task=None, asset=None, app=None):
995995
if not os.path.exists(workdir):
996996
os.makedirs(workdir)
997997

998+
parents = asset_document['data'].get('parents', [])
999+
hierarchy = ""
1000+
if len(parents) > 0:
1001+
hierarchy = os.path.sep.join(parents)
1002+
changed['AVALON_HIERARCHY'] = hierarchy
1003+
9981004
# Update the full session in one go to avoid half updates
9991005
Session.update(changed)
10001006

0 commit comments

Comments
 (0)