Skip to content

Commit

Permalink
Implement Extract Nuke camera as FBX file.
Browse files Browse the repository at this point in the history
  • Loading branch information
robin-ynput committed Sep 2, 2024
1 parent 7a08f57 commit 359161a
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 21 deletions.
3 changes: 2 additions & 1 deletion client/ayon_nuke/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
NukeWriteCreator,
NukeCreatorError,
get_instance_group_node_childs,
get_colorspace_from_node
get_colorspace_from_node,
get_publish_config
)
from .pipeline import (
NukeHost,
Expand Down
5 changes: 5 additions & 0 deletions client/ayon_nuke/api/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,11 @@ def get_review_presets_config():
return [str(name) for name, _prop in outputs.items()]


def get_publish_config():
settings = get_current_project_settings()
return settings["nuke"].get("publish", {})


class NukeLoader(LoaderPlugin):
container_id_knob = "containerId"
container_id = None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,17 @@
)


class AlembicCameraLoader(load.LoaderPlugin):
class _NukeCameraLoader(load.LoaderPlugin):
"""
This will load alembic camera into script.
This will load a camera into script.
"""

product_types = {"camera"}
representations = {"*"}
extensions = {"abc"}
enabled = False

settings_category = "nuke"

label = "Load Alembic Camera"
icon = "camera"
color = "orange"
node_color = "0x3469ffff"
Expand Down Expand Up @@ -57,12 +56,21 @@ def load(self, context, name, namespace, data):
file = self.filepath_from_context(context).replace("\\", "/")

with maintained_selection():
camera_node = nuke.createNode(
"Camera2",
"name {} file {} read_from_file True".format(
object_name, file),
inpanel=False
)

try:
camera_node = nuke.createNode(
"Camera3",
"name {} file {} read_from_file True".format(
object_name, file),
inpanel=False
)
except RuntimeError: # older nuke version
camera_node = nuke.createNode(
"Camera2",
"name {} file {} read_from_file True".format(
object_name, file),
inpanel=False
)

camera_node.forceValidate()
camera_node["frame_rate"].setValue(float(fps))
Expand Down Expand Up @@ -196,3 +204,52 @@ def remove(self, container):
node = container["node"]
with viewer_update_and_undo_stop():
nuke.delete(node)


class AlembicCameraLoader(_NukeCameraLoader):
"""
This will load alembic camera into script.
"""
extensions = {"abc"}
label = "Load Alembic Camera"
enabled = True


class FbxCameraLoader(_NukeCameraLoader):
"""
This will load fbx camera into script.
"""
extensions = {"fbx"}
label = "Load FBX Camera"
enabled = True

def load(self, context, name, namespace, data):
fbx_camera_node = super().load(context, name, namespace,data)

# Nuke forces 7 standard FBX cameras
# Producer Perspective, Producer Top, Producer Bottom...
# https://learn.foundry.com/nuke/11.1/content/comp_environment
# /3d_compositing/importing_fbx_cameras.html
# The following ensure the camera node is set to exported camera data.
fbx_camera_node.forceValidate()

try:
knob = fbx_camera_node["fbx_take_name"]
knob.setValue(0)

except NameError:
# WARNING - Nuke 15: Camera3 validate does not play along
# very well when mixing abc + fbx nodes in the same script.
# They need to reloaded manually.
#
# Hopefully this will be fixed by upcoming Camera4
raise RuntimeError(
"Could not load incoming FBX camera properly. "
"This could be caused by a mix of abc and fbx "
"into the script."
)

knob = fbx_camera_node["fbx_node_name"]
knob.setValue(knob.values()[-1])

return fbx_camera_node
45 changes: 35 additions & 10 deletions client/ayon_nuke/plugins/publish/extract_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from ayon_core.pipeline import publish
from ayon_nuke.api.lib import maintained_selection
from ayon_nuke.api.plugin import get_publish_config


class ExtractCamera(publish.Extractor):
Expand All @@ -19,14 +20,37 @@ class ExtractCamera(publish.Extractor):

settings_category = "nuke"

# presets
write_geo_knobs = [
("file_type", "abc"),
("storageFormat", "Ogawa"),
("writeGeometries", False),
("writePointClouds", False),
("writeAxes", False)
]
def _get_camera_export_presets(self, instance):
"""
Args:
instance (dict): The current instance being published.
Returns:
presets (list.): The camera export presets to use.
"""
write_geo_knobs = [
("writeGeometries", False),
("writePointClouds", False),
("writeAxes", False)
]

publish_settings = get_publish_config()
extract_camera_settings = publish_settings.get("ExtractCameraFormat", {})
export_camera_settings = extract_camera_settings.get("export_camera_format", "abc")

if export_camera_settings == "abc":
write_geo_knobs.insert(0, ("file_type", "abc"))
write_geo_knobs.append((("storageFormat", "Ogawa")))

elif export_camera_settings == "fbx":
write_geo_knobs.insert(0, ("file_type", "fbx"))
write_geo_knobs.append(("writeLights", False))

else:
raise ValueError("Invalid Camera export format: %s" % export_format)

return write_geo_knobs


def process(self, instance):
camera_node = instance.data["transientData"]["node"]
Expand All @@ -43,7 +67,8 @@ def process(self, instance):
staging_dir = self.staging_dir(instance)

# get extension form preset
extension = next((k[1] for k in self.write_geo_knobs
export_presets = self._get_camera_export_presets(instance)
extension = next((k[1] for k in export_presets
if k[0] == "file_type"), None)
if not extension:
raise RuntimeError(
Expand All @@ -68,7 +93,7 @@ def process(self, instance):
wg_n = nuke.createNode("WriteGeo")
wg_n["file"].setValue(file_path)
# add path to write to
for k, v in self.write_geo_knobs:
for k, v in export_presets:
wg_n[k].setValue(v)
rm_nodes.append(wg_n)

Expand Down
24 changes: 24 additions & 0 deletions server/settings/publish_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ def nuke_product_types_enum():
] + nuke_render_publish_types_enum()


def nuke_export_formats_enum():
"""Return all nuke export format available in creators."""
return [
{"value": "abc", "label": "Alembic"},
{"value": "fbx", "label": "FBX"},
]


class NodeModel(BaseSettingsModel):
name: str = SettingsField(
title="Node name"
Expand Down Expand Up @@ -186,6 +194,15 @@ class FVFXScopeOfWorkModel(BaseSettingsModel):
template: str = SettingsField(title="Template")


class ExtractCameraFormatModel(BaseSettingsModel):
export_camera_format: str = SettingsField(
enum_resolver=nuke_export_formats_enum,
conditionalEnum=True,
title="Camera export format",
description="Switch between different camera export formats",
)


class ExctractSlateFrameParamModel(BaseSettingsModel):
f_submission_note: FSubmissionNoteModel = SettingsField(
title="f_submission_note",
Expand Down Expand Up @@ -260,6 +277,10 @@ class PublishPluginsModel(BaseSettingsModel):
default_factory=ExtractReviewIntermediatesModel
)
)
ExtractCameraFormat: ExtractCameraFormatModel = SettingsField(
title="Extract Camera Format",
default_factory=ExtractCameraFormatModel
)
ExtractSlateFrame: ExtractSlateFrameModel = SettingsField(
title="Extract Slate Frame",
default_factory=ExtractSlateFrameModel
Expand Down Expand Up @@ -387,6 +408,9 @@ class PublishPluginsModel(BaseSettingsModel):
}
]
},
"ExtractCameraFormat": {
"export_camera_format": "abc",
},
"ExtractSlateFrame": {
"viewer_lut_raw": False,
"key_value_mapping": {
Expand Down

0 comments on commit 359161a

Please sign in to comment.