Bases: Extractor, OptionalPyblishPluginMixin
Extract Nuke script for matchmove.
Unfortunately built-in export script from 3DEqualizer is bound to its UI, and it is not possible to call it directly from Python. Because of that, we are executing the script in the same way as artist would do it, but we are patching the UI to silence it and to avoid any user interaction.
TODO: Utilize attributes defined in ExtractScriptBase
Source code in client/ayon_equalizer/plugins/publish/extract_matchmove_script_nuke.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 | class ExtractMatchmoveScriptNuke(publish.Extractor,
OptionalPyblishPluginMixin):
"""Extract Nuke script for matchmove.
Unfortunately built-in export script from 3DEqualizer is bound to its UI,
and it is not possible to call it directly from Python. Because of that,
we are executing the script in the same way as artist would do it, but
we are patching the UI to silence it and to avoid any user interaction.
TODO: Utilize attributes defined in ExtractScriptBase
"""
label = "Extract Nuke Script"
families: ClassVar[list] = ["matchmove"]
hosts: ClassVar[list] = ["equalizer"]
optional = True
order = pyblish.api.ExtractorOrder
def process(self, instance: pyblish.api.Instance) -> None:
"""Extract Nuke script from 3DEqualizer."""
if not self.is_active(instance.data):
return
cam = tde4.getCurrentCamera()
staging_dir = self.staging_dir(instance)
file_path = Path(staging_dir) / "nuke_export.nk"
# these patched methods are used to silence 3DEqualizer UI:
def patched_getWidgetValue(_, key: str) -> str: # noqa: N802, ANN001
"""Return value for given key in widget."""
if key == "file_browser":
return file_path.as_posix()
return tde4.getCameraFrameOffset(cam) - 1 \
if key == "startframe_field" else ""
# This is simulating artist clicking on "OK" button
# in the export dialog.
def patched_postCustomRequester(*args, **kwargs) -> int: # noqa: N802, ANN002, ANN003, ARG001
return 1
# This is silencing success/error message after the script
# is exported.
def patched_postQuestionRequester(*args, **kwargs) -> None: # noqa: N802, ANN002, ANN003, ARG001
return None
# import maya export script from 3DEqualizer
exporter_path = instance.context.data["tde4_path"] / "sys_data" / "py_scripts" / "export_nuke.py" # noqa: E501
self.log.debug("Patching 3dequalizer requester objects ...")
with patch("tde4.getWidgetValue", patched_getWidgetValue), \
patch("tde4.postCustomRequester", patched_postCustomRequester), \
patch("tde4.postQuestionRequester", patched_postQuestionRequester): # noqa: E501
with exporter_path.open() as f:
script = f.read()
self.log.debug("Importing %s", exporter_path.as_posix())
exec(script, {"tde4": tde4}) # noqa: S102
# create representation data
if "representations" not in instance.data:
instance.data["representations"] = []
representation = {
"name": "nk",
"ext": "nk",
"files": file_path.name,
"stagingDir": staging_dir,
}
self.log.debug("output: %s", file_path.as_posix())
instance.data["representations"].append(representation)
|
Extract Nuke script from 3DEqualizer.
Source code in client/ayon_equalizer/plugins/publish/extract_matchmove_script_nuke.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 | def process(self, instance: pyblish.api.Instance) -> None:
"""Extract Nuke script from 3DEqualizer."""
if not self.is_active(instance.data):
return
cam = tde4.getCurrentCamera()
staging_dir = self.staging_dir(instance)
file_path = Path(staging_dir) / "nuke_export.nk"
# these patched methods are used to silence 3DEqualizer UI:
def patched_getWidgetValue(_, key: str) -> str: # noqa: N802, ANN001
"""Return value for given key in widget."""
if key == "file_browser":
return file_path.as_posix()
return tde4.getCameraFrameOffset(cam) - 1 \
if key == "startframe_field" else ""
# This is simulating artist clicking on "OK" button
# in the export dialog.
def patched_postCustomRequester(*args, **kwargs) -> int: # noqa: N802, ANN002, ANN003, ARG001
return 1
# This is silencing success/error message after the script
# is exported.
def patched_postQuestionRequester(*args, **kwargs) -> None: # noqa: N802, ANN002, ANN003, ARG001
return None
# import maya export script from 3DEqualizer
exporter_path = instance.context.data["tde4_path"] / "sys_data" / "py_scripts" / "export_nuke.py" # noqa: E501
self.log.debug("Patching 3dequalizer requester objects ...")
with patch("tde4.getWidgetValue", patched_getWidgetValue), \
patch("tde4.postCustomRequester", patched_postCustomRequester), \
patch("tde4.postQuestionRequester", patched_postQuestionRequester): # noqa: E501
with exporter_path.open() as f:
script = f.read()
self.log.debug("Importing %s", exporter_path.as_posix())
exec(script, {"tde4": tde4}) # noqa: S102
# create representation data
if "representations" not in instance.data:
instance.data["representations"] = []
representation = {
"name": "nk",
"ext": "nk",
"files": file_path.name,
"stagingDir": staging_dir,
}
self.log.debug("output: %s", file_path.as_posix())
instance.data["representations"].append(representation)
|