generated from ynput/ayon-addon-template
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
297 changed files
with
40,953 additions
and
1 deletion.
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 |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from .addon import ( | ||
MayaAddon, | ||
MAYA_ROOT_DIR, | ||
) | ||
|
||
|
||
__all__ = ( | ||
"MayaAddon", | ||
"MAYA_ROOT_DIR", | ||
) |
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,46 @@ | ||
import os | ||
from ayon_core.addon import AYONAddon, IHostAddon | ||
|
||
MAYA_ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) | ||
|
||
|
||
class MayaAddon(AYONAddon, IHostAddon): | ||
name = "maya" | ||
host_name = "maya" | ||
|
||
def add_implementation_envs(self, env, _app): | ||
# Add requirements to PYTHONPATH | ||
new_python_paths = [ | ||
os.path.join(MAYA_ROOT_DIR, "startup") | ||
] | ||
old_python_path = env.get("PYTHONPATH") or "" | ||
for path in old_python_path.split(os.pathsep): | ||
if not path: | ||
continue | ||
|
||
norm_path = os.path.normpath(path) | ||
if norm_path not in new_python_paths: | ||
new_python_paths.append(norm_path) | ||
|
||
# add vendor path | ||
new_python_paths.append( | ||
os.path.join(MAYA_ROOT_DIR, "vendor", "python") | ||
) | ||
env["PYTHONPATH"] = os.pathsep.join(new_python_paths) | ||
|
||
# Set default environments | ||
envs = { | ||
"AYON_LOG_NO_COLORS": "1", | ||
} | ||
for key, value in envs.items(): | ||
env[key] = value | ||
|
||
def get_launch_hook_paths(self, app): | ||
if app.host_name != self.host_name: | ||
return [] | ||
return [ | ||
os.path.join(MAYA_ROOT_DIR, "hooks") | ||
] | ||
|
||
def get_workfile_extensions(self): | ||
return [".ma", ".mb"] |
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,74 @@ | ||
"""Public API | ||
Anything that isn't defined here is INTERNAL and unreliable for external use. | ||
""" | ||
|
||
from .pipeline import ( | ||
uninstall, | ||
|
||
ls, | ||
containerise, | ||
MayaHost, | ||
) | ||
from .plugin import ( | ||
Creator, | ||
Loader | ||
) | ||
|
||
from .workio import ( | ||
open_file, | ||
save_file, | ||
current_file, | ||
has_unsaved_changes, | ||
file_extensions, | ||
work_root | ||
) | ||
|
||
from .lib import ( | ||
lsattr, | ||
lsattrs, | ||
read, | ||
|
||
apply_shaders, | ||
maintained_selection, | ||
suspended_refresh, | ||
|
||
unique_namespace, | ||
) | ||
|
||
|
||
__all__ = [ | ||
"uninstall", | ||
|
||
"ls", | ||
"containerise", | ||
"MayaHost", | ||
|
||
"Creator", | ||
"Loader", | ||
|
||
# Workfiles API | ||
"open_file", | ||
"save_file", | ||
"current_file", | ||
"has_unsaved_changes", | ||
"file_extensions", | ||
"work_root", | ||
|
||
# Utility functions | ||
"lsattr", | ||
"lsattrs", | ||
"read", | ||
|
||
"unique_namespace", | ||
|
||
"apply_shaders", | ||
"maintained_selection", | ||
"suspended_refresh", | ||
|
||
] | ||
|
||
# Backwards API compatibility | ||
open = open_file | ||
save = save_file |
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,146 @@ | ||
# absolute_import is needed to counter the `module has no cmds error` in Maya | ||
from __future__ import absolute_import | ||
|
||
import pyblish.api | ||
import ayon_api | ||
|
||
from ayon_core.pipeline.publish import ( | ||
get_errored_instances_from_context, | ||
get_errored_plugins_from_context | ||
) | ||
|
||
|
||
class GenerateUUIDsOnInvalidAction(pyblish.api.Action): | ||
"""Generate UUIDs on the invalid nodes in the instance. | ||
Invalid nodes are those returned by the plugin's `get_invalid` method. | ||
As such it is the plug-in's responsibility to ensure the nodes that | ||
receive new UUIDs are actually invalid. | ||
Requires: | ||
- instance.data["folderPath"] | ||
""" | ||
|
||
label = "Regenerate UUIDs" | ||
on = "failed" # This action is only available on a failed plug-in | ||
icon = "wrench" # Icon from Awesome Icon | ||
|
||
def process(self, context, plugin): | ||
|
||
from maya import cmds | ||
|
||
self.log.info("Finding bad nodes..") | ||
|
||
errored_instances = get_errored_instances_from_context(context) | ||
|
||
# Apply pyblish logic to get the instances for the plug-in | ||
instances = pyblish.api.instances_by_plugin(errored_instances, plugin) | ||
|
||
# Get the nodes from the all instances that ran through this plug-in | ||
all_invalid = [] | ||
for instance in instances: | ||
invalid = plugin.get_invalid(instance) | ||
|
||
# Don't allow referenced nodes to get their ids regenerated to | ||
# avoid loaded content getting messed up with reference edits | ||
if invalid: | ||
referenced = {node for node in invalid if | ||
cmds.referenceQuery(node, isNodeReferenced=True)} | ||
if referenced: | ||
self.log.warning("Skipping UUID generation on referenced " | ||
"nodes: {}".format(list(referenced))) | ||
invalid = [node for node in invalid | ||
if node not in referenced] | ||
|
||
if invalid: | ||
|
||
self.log.info("Fixing instance {}".format(instance.name)) | ||
self._update_id_attribute(instance, invalid) | ||
|
||
all_invalid.extend(invalid) | ||
|
||
if not all_invalid: | ||
self.log.info("No invalid nodes found.") | ||
return | ||
|
||
all_invalid = list(set(all_invalid)) | ||
self.log.info("Generated ids on nodes: {0}".format(all_invalid)) | ||
|
||
def _update_id_attribute(self, instance, nodes): | ||
"""Delete the id attribute | ||
Args: | ||
instance: The instance we're fixing for | ||
nodes (list): all nodes to regenerate ids on | ||
""" | ||
|
||
from . import lib | ||
|
||
# Expecting this is called on validators in which case 'folderEntity' | ||
# should be always available, but kept a way to query it by name. | ||
folder_entity = instance.data.get("folderEntity") | ||
if not folder_entity: | ||
folder_path = instance.data["folderPath"] | ||
project_name = instance.context.data["projectName"] | ||
self.log.info(( | ||
"Folder is not stored on instance." | ||
" Querying by path \"{}\" from project \"{}\"" | ||
).format(folder_path, project_name)) | ||
folder_entity = ayon_api.get_folder_by_path( | ||
project_name, folder_path, fields={"id"} | ||
) | ||
|
||
for node, _id in lib.generate_ids( | ||
nodes, folder_id=folder_entity["id"] | ||
): | ||
lib.set_id(node, _id, overwrite=True) | ||
|
||
|
||
class SelectInvalidAction(pyblish.api.Action): | ||
"""Select invalid nodes in Maya when plug-in failed. | ||
To retrieve the invalid nodes this assumes a static `get_invalid()` | ||
method is available on the plugin. | ||
""" | ||
label = "Select invalid" | ||
on = "failed" # This action is only available on a failed plug-in | ||
icon = "search" # Icon from Awesome Icon | ||
|
||
def process(self, context, plugin): | ||
|
||
try: | ||
from maya import cmds | ||
except ImportError: | ||
raise ImportError("Current host is not Maya") | ||
|
||
# Get the invalid nodes for the plug-ins | ||
self.log.info("Finding invalid nodes..") | ||
invalid = list() | ||
if issubclass(plugin, pyblish.api.ContextPlugin): | ||
errored_plugins = get_errored_plugins_from_context(context) | ||
if plugin in errored_plugins: | ||
invalid = plugin.get_invalid(context) | ||
else: | ||
errored_instances = get_errored_instances_from_context( | ||
context, plugin=plugin | ||
) | ||
for instance in errored_instances: | ||
invalid_nodes = plugin.get_invalid(instance) | ||
if invalid_nodes: | ||
if isinstance(invalid_nodes, (list, tuple)): | ||
invalid.extend(invalid_nodes) | ||
else: | ||
self.log.warning("Plug-in returned to be invalid, " | ||
"but has no selectable nodes.") | ||
|
||
# Ensure unique (process each node only once) | ||
invalid = list(set(invalid)) | ||
|
||
if invalid: | ||
self.log.info("Selecting invalid nodes: %s" % ", ".join(invalid)) | ||
cmds.select(invalid, replace=True, noExpand=True) | ||
else: | ||
self.log.info("No invalid nodes found.") | ||
cmds.select(deselect=True) |
Oops, something went wrong.