-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into change_bin_brdige_client_version
- Loading branch information
Showing
7 changed files
with
331 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,15 @@ | ||
"""USD Addon for AYON - client part.""" | ||
|
||
from .addon import USDAddon | ||
from .ayon_bin_client.ayon_bin_distro.util.zip import extract_zip_file | ||
from .utils import ( | ||
get_download_dir | ||
get_download_dir, | ||
get_usd_pinning_envs, | ||
) | ||
from .ayon_bin_client.ayon_bin_distro.util.zip import extract_zip_file | ||
|
||
__all__ = ( | ||
"USDAddon", | ||
"extract_zip_file", | ||
"get_download_dir", | ||
"get_usd_pinning_envs", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
"""Pre-launch hook to set USD pinning related environment variable.""" | ||
from typing import ClassVar | ||
|
||
from ayon_applications import LaunchTypes, PreLaunchHook | ||
|
||
|
||
class UsdPinningRoot(PreLaunchHook): | ||
"""Pre-launch hook to set USD_ROOT environment variable.""" | ||
|
||
app_groups: ClassVar = {"maya", "houdini", "blender", "unreal"} | ||
# this should be set to farm_render, but this issue | ||
# https://github.com/ynput/ayon-applications/issues/2 | ||
# stands in the way | ||
launch_types: ClassVar = {LaunchTypes.farm_publish} | ||
|
||
def execute(self) -> None: | ||
"""Set environments necessary for pinning.""" | ||
if self.launch_context.env.get("PINNING_FILE_PATH"): | ||
return | ||
anatomy = self.launch_context.anatomy | ||
self.launch_context.env["PINNING_FILE_PATH"] = anatomy.fill_root( | ||
self.launch_context.env.get("PINNING_FILE_PATH"), | ||
) | ||
|
||
roots = anatomy.roots() | ||
self.launch_context.env[ | ||
"PROJECT_ROOTS" | ||
] = ",".join(f"{key}={value}" | ||
for key, value in roots.items()) |
83 changes: 83 additions & 0 deletions
83
client/ayon_usd/plugins/publish/extract_skeleton_pinning_json.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
"""Extract Skeleton Pinning JSON file. | ||
This extractor creates a simple placeholder JSON file that is filled by | ||
Integrator plugin (Integrate Pinning File). This way, publishing process | ||
is much more simple and doesn't require any hacks. | ||
Side effects: | ||
- Creates a JSON file with skeleton pinning data that doesn't contain | ||
any real data, it's just a placeholder. If, for whatever reason, the | ||
publishing process is interrupted, the placeholder file will be | ||
still there even if the real data is not present. | ||
- Adds a timestamp to the JSON file. This timestamp can be later used | ||
to check if the processed data is up-to-date. | ||
""" | ||
import json | ||
from datetime import datetime | ||
from pathlib import Path | ||
from typing import ClassVar | ||
|
||
import pyblish.api | ||
from ayon_core.pipeline import OptionalPyblishPluginMixin, KnownPublishError | ||
|
||
|
||
class ExtractSkeletonPinningJSON(pyblish.api.InstancePlugin, | ||
OptionalPyblishPluginMixin): | ||
"""Extract Skeleton Pinning JSON file. | ||
Extracted JSON file doesn't contain any data, it's just a placeholder | ||
that is filled by Integrator plugin (Integrate Pinning File). | ||
""" | ||
|
||
label = "Extract Skeleton Pinning JSON" | ||
order = pyblish.api.ExtractorOrder + 0.49 | ||
families: ClassVar = ["usd", "usdrender"] | ||
|
||
@staticmethod | ||
def _has_usd_representation(representations: list) -> bool: | ||
return any( | ||
representation.get("name") == "usd" | ||
for representation in representations | ||
) | ||
|
||
def process(self, instance: pyblish.api.Instance) -> None: | ||
"""Process the plugin.""" | ||
if not self.is_active(instance.data): | ||
return | ||
|
||
# we need to handle usdrender differently as usd for rendering will | ||
# be produced much later on the farm. | ||
if "usdrender" not in instance.data.get("families", []): | ||
if not self._has_usd_representation(instance.data["representations"]): | ||
self.log.info("No USD representation found, skipping.") | ||
return | ||
|
||
try: | ||
staging_dir = Path(instance.data["stagingDir"]) | ||
except KeyError: | ||
self.log.debug("No staging directory on instance found.") | ||
try: | ||
staging_dir = Path(instance.data["ifdFile"]).parent | ||
except KeyError as e: | ||
self.log.error("No staging directory found.") | ||
raise KnownPublishError("Cannot determine staging directory.") from e | ||
|
||
pin_file = f"{staging_dir.stem}_pin.json" | ||
pin_file_path = staging_dir.joinpath(pin_file) | ||
pin_representation = { | ||
"name": "usd_pinning", | ||
"ext": "json", | ||
"files": pin_file_path.name, | ||
"stagingDir": staging_dir.as_posix(), | ||
} | ||
current_timestamp = datetime.now().timestamp() | ||
skeleton_pinning_data = { | ||
"timestamp": current_timestamp, | ||
} | ||
Path.mkdir(staging_dir, parents=True, exist_ok=True) | ||
with open(pin_file_path, "w") as f: | ||
json.dump(skeleton_pinning_data, f, indent=4) | ||
|
||
instance.data["representations"].append(pin_representation) |
134 changes: 134 additions & 0 deletions
134
client/ayon_usd/plugins/publish/integrate_pinning_file.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
"""Extract pinning file from USD file as a json file. | ||
This is WIP and will be refactored in the future. | ||
""" | ||
from __future__ import annotations | ||
|
||
from pathlib import Path | ||
|
||
import ayon_api | ||
import pyblish.api | ||
from ayon_core.pipeline import get_current_host_name, get_current_project_name | ||
from ayon_core.pipeline.publish import KnownPublishError | ||
from ayon_usd.standalone.usd.pinning import generate_pinning_file | ||
|
||
|
||
class IntegrateUsdPinningFile(pyblish.api.InstancePlugin): | ||
"""Extract pinning file from USD file as a json file.""" | ||
|
||
order = pyblish.api.IntegratorOrder + 0.01 | ||
label = "Integrate data into USD pinning file" | ||
families = ["usd", "usdrender"] | ||
|
||
def process(self, instance: pyblish.api.Instance) -> None: | ||
"""Process the plugin.""" | ||
|
||
anatomy = instance.context.data["anatomy"] | ||
usd_pinning_path = None | ||
|
||
# get pinning json file | ||
if "usdrender" in instance.data.get("families", []): | ||
self.log.debug( | ||
"Extracting USD pinning file for usdrender family.") | ||
usd_file_path = self.save_usd(instance) | ||
for rep in instance.data["representations"]: | ||
if rep["name"] == "usd_pinning": | ||
usd_pinning_path = Path(rep["stagingDir"]) / rep["files"] | ||
break | ||
else: | ||
if instance.data.get("versionEntity") is None: | ||
err_msg = "Instance was not integrated to AYON yet." | ||
raise KnownPublishError(err_msg) | ||
|
||
ayon_api.get_representation_by_name( | ||
get_current_project_name(), | ||
representation_name="usd_pinning", | ||
version_id=instance.data["versionEntity"]["id"]) | ||
|
||
published_repres = instance.data.get("published_representations") | ||
usd_file_rootless_path = None | ||
usd_pinning_rootless_file_path = None | ||
|
||
for repre_info in published_repres.values(): | ||
rep = repre_info["representation"] | ||
|
||
if rep["name"] == "usd": | ||
usd_file_rootless_path = rep["attrib"]["path"] | ||
continue | ||
if rep["name"] == "usd_pinning": | ||
usd_pinning_rootless_file_path = rep["attrib"]["path"] | ||
continue | ||
|
||
if usd_file_rootless_path and usd_pinning_rootless_file_path: | ||
break | ||
|
||
if not usd_file_rootless_path or not usd_pinning_rootless_file_path: | ||
self.log.info("No USD or USD pinning file found, skipping.") | ||
return | ||
|
||
# get the full path of the usd file | ||
usd_file_path = Path( | ||
anatomy.fill_root(usd_file_rootless_path)) | ||
usd_pinning_path = Path( | ||
anatomy.fill_root(usd_pinning_rootless_file_path)) | ||
|
||
if not usd_pinning_path: | ||
self.log.error("No USD pinning file found.") | ||
return | ||
|
||
generate_pinning_file( | ||
usd_file_path.as_posix(), | ||
ayon_api.get_project_roots_by_site_id(get_current_project_name()), | ||
usd_pinning_path.as_posix()) | ||
|
||
# clean temporary usd file | ||
if "usdrender" in instance.data.get("families", []): | ||
self.log.debug(f"Removing temporary USD file: {usd_file_path}") | ||
usd_file_path.unlink() | ||
|
||
def save_usd(self, instance: pyblish.api.Instance) -> Path: | ||
"""Save USD file to disk. | ||
Args: | ||
instance (pyblish.api.Instance): Instance object. | ||
Returns: | ||
str: The rootless path to the saved USD file. | ||
""" | ||
if get_current_host_name() == "houdini": | ||
return self._save_usd_from_houdini(instance) | ||
raise NotImplementedError( | ||
f"Unsupported host {get_current_host_name()}") | ||
|
||
def _save_usd_from_houdini(self, instance: pyblish.api.Instance) -> Path: | ||
"""Save USD file from Houdini. | ||
This is called only from running host so we can safely assume | ||
that Houdini Addon is available. | ||
Args: | ||
instance (pyblish.api.Instance): Instance object. | ||
Returns: | ||
str: The rootless path to the saved USD file. | ||
""" | ||
import hou # noqa: F401 | ||
from ayon_houdini.api import maintained_selection # noqa: F401 | ||
|
||
ropnode = hou.node(instance.data.get("instance_node")) | ||
filename = ropnode.parm("lopoutput").eval() | ||
directory = ropnode.parm("savetodirectory_directory").eval() | ||
filepath = Path(directory) / filename | ||
|
||
# create temp usdrop node | ||
with maintained_selection(): | ||
temp_usd_node = hou.node("/out").createNode("usd") | ||
temp_usd_node.parm("lopoutput").set( | ||
filepath.as_posix()) | ||
temp_usd_node.parm("loppath").set(ropnode.parm("loppath").eval()) | ||
temp_usd_node.render() | ||
temp_usd_node.destroy() | ||
|
||
return filepath |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters