mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge branch 'develop' into hotfix/nuke-publish-fixes
This commit is contained in:
commit
fe918b1bd6
17 changed files with 154 additions and 34 deletions
41
changelog.md
41
changelog.md
|
|
@ -1,6 +1,47 @@
|
|||
# Pype changelog #
|
||||
Welcome to pype changelog
|
||||
|
||||
## 2.3.0 ##
|
||||
_release date: 6 Oct 2019_
|
||||
|
||||
**new**:
|
||||
- _(maya)_ support for yeti rigs and yeti caches
|
||||
- _(maya)_ validator for comparing arbitrary attributes against ftrack
|
||||
- _(pype)_ burnins can now show current date and time
|
||||
- _(muster)_ pools can now be set in render globals in maya
|
||||
- _(pype)_ Rest API has been implemented in beta stage
|
||||
- _(nuke)_ LUT loader has been added
|
||||
- _(pype)_ rudimentary user module has been added as preparation for user management
|
||||
- _(pype)_ a simple logging GUI has been added to pype tray
|
||||
- _(nuke)_ nuke can now bake input process into mov
|
||||
- _(maya)_ imported models now have selection handle displayed by defaulting
|
||||
- _(avalon)_ it's is now possible to load multiple assets at once using loader
|
||||
- _(maya)_ added ability to automatically connect yeti rig to a mesh upon loading
|
||||
|
||||
**changed**:
|
||||
- _(ftrack)_ event server now runs two parallel processes and is able to keep queue of events to process.
|
||||
- _(nuke)_ task name is now added to all rendered subsets
|
||||
- _(pype)_ adding more families to standalone publisher
|
||||
- _(pype)_ standalone publisher now uses pyblish-lite
|
||||
- _(pype)_ standalone publisher can now create review quicktimes
|
||||
- _(ftrack)_ queries to ftrack were sped up
|
||||
- _(ftrack)_ multiple ftrack action have been deprecated
|
||||
- _(avalon)_ avalon upstream has been updated to 5.5.0
|
||||
- _(nukestudio)_ published transforms can now be animated
|
||||
-
|
||||
|
||||
**fix**:
|
||||
- _(maya)_ fps popup button didn't work in some cases
|
||||
- _(maya)_ geometry instances and references in maya were losing shader assignments
|
||||
- _(muster)_ muster rendering templates were not working correctly
|
||||
- _(maya)_ arnold tx texture conversion wasn't respecting colorspace set by the artist
|
||||
- _(pype)_ problems with avalon db sync
|
||||
- _(maya)_ ftrack was rounding FPS making it inconsistent
|
||||
- _(pype)_ wrong icon names in Creator
|
||||
- _(maya)_ scene inventory wasn't showing anything if representation was removed from database after it's been loaded to the scene
|
||||
- _(nukestudio)_ multiple bugs squashed
|
||||
- _(loader)_ loader was taking long time to show all the loading action when first launcher in maya
|
||||
|
||||
## 2.2.0 ##
|
||||
_release date: 8 Sept 2019_
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from pypeapp import config
|
|||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__version__ = "2.1.0"
|
||||
__version__ = "2.3.0"
|
||||
|
||||
PACKAGE_DIR = os.path.dirname(__file__)
|
||||
PLUGINS_DIR = os.path.join(PACKAGE_DIR, "plugins")
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ class Sync_to_Avalon(BaseEvent):
|
|||
avalon_project = result['project']
|
||||
|
||||
except Exception as e:
|
||||
session.reset() # reset session to clear it
|
||||
|
||||
message = str(e)
|
||||
title = 'Hey You! Unknown Error has been raised! (*look below*)'
|
||||
ftrack_message = (
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ class ThumbnailEvents(BaseEvent):
|
|||
if parent.get('thumbnail') and not task.get('thumbnail'):
|
||||
task['thumbnail'] = parent['thumbnail']
|
||||
self.log.info('>>> Updated thumbnail on [ %s/%s ]'.format(
|
||||
parent['name'], task['name']))
|
||||
parent['name'], task['name']
|
||||
))
|
||||
|
||||
# Update task thumbnail from published version
|
||||
# if (entity['entityType'] == 'assetversion' and
|
||||
|
|
@ -32,18 +33,24 @@ class ThumbnailEvents(BaseEvent):
|
|||
|
||||
version = session.get('AssetVersion', entity['entityId'])
|
||||
thumbnail = version.get('thumbnail')
|
||||
task = version['task']
|
||||
|
||||
if thumbnail:
|
||||
task['thumbnail'] = thumbnail
|
||||
task['parent']['thumbnail'] = thumbnail
|
||||
self.log.info('>>> Updating thumbnail for task and shot\
|
||||
[ {} ]'.format(task['name']))
|
||||
parent = version['asset']['parent']
|
||||
task = version['task']
|
||||
parent['thumbnail_id'] = version['thumbnail_id']
|
||||
if parent.entity_type.lower() == "project":
|
||||
name = parent["full_name"]
|
||||
else:
|
||||
name = parent["name"]
|
||||
msg = '>>> Updating thumbnail for shot [ {} ]'.format(name)
|
||||
|
||||
if task:
|
||||
task['thumbnail_id'] = version['thumbnail_id']
|
||||
msg += " and task [ {} ]".format(task["name"])
|
||||
|
||||
self.log.info(msg)
|
||||
|
||||
session.commit()
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def register(session, plugins_presets):
|
||||
'''Register plugin. Called when used as an plugin.'''
|
||||
|
|
|
|||
|
|
@ -533,7 +533,9 @@ if __name__ == "__main__":
|
|||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
if hasattr(signal, "SIGKILL"):
|
||||
signal.signal(signal.SIGKILL, signal_handler)
|
||||
|
||||
try:
|
||||
signal.signal(signal.SIGKILL, signal_handler)
|
||||
except OSError:
|
||||
pass
|
||||
sys.exit(main(sys.argv))
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ if __name__ == "__main__":
|
|||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
if hasattr(signal, "SIGKILL"):
|
||||
try:
|
||||
signal.signal(signal.SIGKILL, signal_handler)
|
||||
|
||||
except OSError:
|
||||
pass
|
||||
sys.exit(main(sys.argv))
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ if __name__ == "__main__":
|
|||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
if hasattr(signal, "SIGKILL"):
|
||||
try:
|
||||
signal.signal(signal.SIGKILL, signal_handler)
|
||||
|
||||
except OSError:
|
||||
pass
|
||||
sys.exit(main(sys.argv))
|
||||
|
|
|
|||
|
|
@ -94,7 +94,8 @@ if __name__ == "__main__":
|
|||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
if hasattr(signal, "SIGKILL"):
|
||||
try:
|
||||
signal.signal(signal.SIGKILL, signal_handler)
|
||||
|
||||
except OSError:
|
||||
pass
|
||||
sys.exit(main(sys.argv))
|
||||
|
|
|
|||
|
|
@ -963,7 +963,7 @@ class BuildWorkfile(WorkfileSettings):
|
|||
def process(self,
|
||||
regex_filter=None,
|
||||
version=None,
|
||||
representations=["exr", "dpx", "lutJson"]):
|
||||
representations=["exr", "dpx", "lutJson", "mov", "preview"]):
|
||||
"""
|
||||
A short description.
|
||||
|
||||
|
|
@ -1020,6 +1020,8 @@ class BuildWorkfile(WorkfileSettings):
|
|||
version=version,
|
||||
representations=representations)
|
||||
|
||||
log.info("__ subsets: `{}`".format(subsets))
|
||||
|
||||
nodes_backdrop = list()
|
||||
|
||||
for name, subset in subsets.items():
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from avalon import api
|
||||
import pype.maya.plugin
|
||||
import os
|
||||
import pymel.core as pm
|
||||
from pypeapp import config
|
||||
|
||||
|
||||
|
|
@ -70,6 +69,7 @@ class AssProxyLoader(pype.maya.plugin.ReferenceLoader):
|
|||
|
||||
import os
|
||||
from maya import cmds
|
||||
import pymel.core as pm
|
||||
|
||||
node = container["objectName"]
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ from avalon import api
|
|||
import pype.maya.plugin
|
||||
import os
|
||||
from pypeapp import config
|
||||
import pymel.core as pm
|
||||
reload(config)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import pymel.core as pc
|
||||
|
||||
from avalon import api
|
||||
from Qt import QtWidgets
|
||||
|
||||
|
|
@ -14,6 +12,8 @@ class ImagePlaneLoader(api.Loader):
|
|||
color = "orange"
|
||||
|
||||
def load(self, context, name, namespace, data):
|
||||
import pymel.core as pc
|
||||
|
||||
new_nodes = []
|
||||
image_plane_depth = 1000
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
import pype.maya.plugin
|
||||
import os
|
||||
from pypeapp import config
|
||||
import pymel.core as pm
|
||||
reload(config)
|
||||
import pype.maya.plugin
|
||||
reload(pype.maya.plugin)
|
||||
|
|
@ -20,9 +18,10 @@ class ReferenceLoader(pype.maya.plugin.ReferenceLoader):
|
|||
color = "orange"
|
||||
|
||||
def process_reference(self, context, name, namespace, data):
|
||||
|
||||
import maya.cmds as cmds
|
||||
from avalon import maya
|
||||
import pymel.core as pm
|
||||
|
||||
|
||||
try:
|
||||
family = context["representation"]["context"]["family"]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
import pype.maya.plugin
|
||||
import os
|
||||
from collections import defaultdict
|
||||
|
||||
from pypeapp import config
|
||||
import pype.maya.plugin
|
||||
from pype.maya import lib
|
||||
|
||||
|
||||
class YetiRigLoader(pype.maya.plugin.ReferenceLoader):
|
||||
"""
|
||||
This loader will load Yeti rig. You can select something in scene and if it
|
||||
has same ID as mesh published with rig, their shapes will be linked
|
||||
together.
|
||||
"""
|
||||
|
||||
families = ["yetiRig"]
|
||||
representations = ["ma"]
|
||||
|
|
@ -18,6 +26,32 @@ class YetiRigLoader(pype.maya.plugin.ReferenceLoader):
|
|||
import maya.cmds as cmds
|
||||
from avalon import maya
|
||||
|
||||
# get roots of selected hierarchies
|
||||
selected_roots = []
|
||||
for sel in cmds.ls(sl=True, long=True):
|
||||
selected_roots.append(sel.split("|")[1])
|
||||
|
||||
# get all objects under those roots
|
||||
selected_hierarchy = []
|
||||
for root in selected_roots:
|
||||
selected_hierarchy.append(cmds.listRelatives(
|
||||
root,
|
||||
allDescendents=True) or [])
|
||||
|
||||
# flatten the list and filter only shapes
|
||||
shapes_flat = []
|
||||
for root in selected_hierarchy:
|
||||
shapes = cmds.ls(root, long=True, type="mesh") or []
|
||||
for shape in shapes:
|
||||
shapes_flat.append(shape)
|
||||
|
||||
# create dictionary of cbId and shape nodes
|
||||
scene_lookup = defaultdict(list)
|
||||
for node in shapes_flat:
|
||||
cb_id = lib.get_id(node)
|
||||
scene_lookup[cb_id] = node
|
||||
|
||||
# load rig
|
||||
with maya.maintained_selection():
|
||||
nodes = cmds.file(self.fname,
|
||||
namespace=namespace,
|
||||
|
|
@ -26,6 +60,20 @@ class YetiRigLoader(pype.maya.plugin.ReferenceLoader):
|
|||
groupReference=True,
|
||||
groupName="{}:{}".format(namespace, name))
|
||||
|
||||
# for every shape node we've just loaded find matching shape by its
|
||||
# cbId in selection. If found outMesh of scene shape will connect to
|
||||
# inMesh of loaded shape.
|
||||
for destination_node in nodes:
|
||||
source_node = scene_lookup[lib.get_id(destination_node)]
|
||||
if source_node:
|
||||
self.log.info("found: {}".format(source_node))
|
||||
self.log.info(
|
||||
"creating connection to {}".format(destination_node))
|
||||
|
||||
cmds.connectAttr("{}.outMesh".format(source_node),
|
||||
"{}.inMesh".format(destination_node),
|
||||
force=True)
|
||||
|
||||
groupName = "{}:{}".format(namespace, name)
|
||||
|
||||
presets = config.get_presets(project=os.environ['AVALON_PROJECT'])
|
||||
|
|
@ -38,6 +86,4 @@ class YetiRigLoader(pype.maya.plugin.ReferenceLoader):
|
|||
c[0], c[1], c[2])
|
||||
self[:] = nodes
|
||||
|
||||
self.log.info("Yeti Rig Connection Manager will be available soon")
|
||||
|
||||
return nodes
|
||||
|
|
|
|||
|
|
@ -126,6 +126,18 @@ class ExtractYetiRig(pype.api.Extractor):
|
|||
with open(settings_path, "w") as fp:
|
||||
json.dump(settings, fp, ensure_ascii=False)
|
||||
|
||||
# add textures to transfers
|
||||
if 'transfers' not in instance.data:
|
||||
instance.data['transfers'] = []
|
||||
|
||||
for resource in instance.data.get('resources', []):
|
||||
for file in resource['files']:
|
||||
src = file
|
||||
dst = os.path.join(image_search_path, os.path.basename(file))
|
||||
instance.data['transfers'].append([src, dst])
|
||||
|
||||
self.log.info("adding transfer {} -> {}". format(src, dst))
|
||||
|
||||
# Ensure the imageSearchPath is being remapped to the publish folder
|
||||
attr_value = {"%s.imageSearchPath" % n: str(image_search_path) for
|
||||
n in yeti_nodes}
|
||||
|
|
|
|||
|
|
@ -196,12 +196,14 @@ class CollectPlatesData(api.InstancePlugin):
|
|||
|
||||
thumb_file = head + ".png"
|
||||
thumb_path = os.path.join(staging_dir, thumb_file)
|
||||
thumb_frame = instance.data["sourceIn"] + ((instance.data["sourceOut"] - instance.data["sourceIn"])/2)
|
||||
|
||||
thumbnail = item.thumbnail(instance.data["sourceIn"]).save(
|
||||
thumbnail = item.thumbnail(thumb_frame).save(
|
||||
thumb_path,
|
||||
format='png'
|
||||
)
|
||||
self.log.debug("__ thumbnail: {}".format(thumbnail))
|
||||
self.log.debug("__ sourceIn: `{}`".format(instance.data["sourceIn"]))
|
||||
self.log.debug("__ thumbnail: `{}`, frame: `{}`".format(thumbnail, thumb_frame))
|
||||
|
||||
thumb_representation = {
|
||||
'files': thumb_file,
|
||||
|
|
|
|||
|
|
@ -106,7 +106,6 @@ class CollectReviews(api.InstancePlugin):
|
|||
|
||||
def create_thumbnail(self, instance):
|
||||
item = instance.data["item"]
|
||||
source_in = instance.data["sourceIn"]
|
||||
|
||||
source_path = instance.data["sourcePath"]
|
||||
source_file = os.path.basename(source_path)
|
||||
|
|
@ -119,11 +118,17 @@ class CollectReviews(api.InstancePlugin):
|
|||
thumb_file = head + ".png"
|
||||
thumb_path = os.path.join(staging_dir, thumb_file)
|
||||
self.log.debug("__ thumb_path: {}".format(thumb_path))
|
||||
self.log.debug("__ source_in: {}".format(source_in))
|
||||
thumbnail = item.thumbnail(source_in).save(
|
||||
|
||||
thumb_frame = instance.data["sourceIn"] + ((instance.data["sourceOut"] - instance.data["sourceIn"])/2)
|
||||
|
||||
thumbnail = item.thumbnail(thumb_frame).save(
|
||||
thumb_path,
|
||||
format='png'
|
||||
)
|
||||
|
||||
self.log.debug("__ sourceIn: `{}`".format(instance.data["sourceIn"]))
|
||||
self.log.debug("__ thumbnail: `{}`, frame: `{}`".format(thumbnail, thumb_frame))
|
||||
|
||||
self.log.debug("__ thumbnail: {}".format(thumbnail))
|
||||
|
||||
thumb_representation = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue