Merge branch 'develop' into 2.x/develop

This commit is contained in:
Milan Kolar 2020-09-16 15:42:17 +02:00
commit 1f9a20ec02
233 changed files with 11532 additions and 221 deletions

View file

@ -1,3 +1,7 @@
from .settings import (
system_settings,
project_settings
)
from pypeapp import (
Logger,
Anatomy,
@ -49,6 +53,9 @@ from .lib import (
from .lib import _subprocess as subprocess
__all__ = [
"system_settings",
"project_settings",
"Logger",
"Anatomy",
"project_overrides_dir_path",

View file

@ -46,13 +46,14 @@ class ResolvePrelaunch(PypeHook):
"`RESOLVE_UTILITY_SCRIPTS_DIR` or reinstall DaVinci Resolve. \n"
f"RESOLVE_UTILITY_SCRIPTS_DIR: `{us_dir}`"
)
self.log.debug(f"-- us_dir: `{us_dir}`")
# correctly format path for pre python script
pre_py_sc = os.path.normpath(env.get("PRE_PYTHON_SCRIPT", ""))
env["PRE_PYTHON_SCRIPT"] = pre_py_sc
self.log.debug(f"-- pre_py_sc: `{pre_py_sc}`...")
try:
__import__("pype.resolve")
__import__("pype.hosts.resolve")
__import__("pyblish")
except ImportError as e:
@ -62,6 +63,7 @@ class ResolvePrelaunch(PypeHook):
else:
# Resolve Setup integration
importlib.reload(utils)
self.log.debug(f"-- utils.__file__: `{utils.__file__}`")
utils.setup(env)
return True

View file

@ -1,17 +1,34 @@
from .utils import (
setup,
get_resolve_module
)
from .pipeline import (
install,
uninstall,
ls,
containerise,
publish,
launch_workfiles_app
launch_workfiles_app,
maintained_selection
)
from .utils import (
setup,
get_resolve_module
from .lib import (
get_project_manager,
get_current_project,
get_current_sequence,
get_current_track_items,
create_current_sequence_media_bin,
create_compound_clip,
swap_clips,
get_pype_clip_metadata,
set_project_manager_to_folder_name
)
from .menu import launch_pype_menu
from .plugin import Creator
from .workio import (
open_file,
save_file,
@ -21,12 +38,8 @@ from .workio import (
work_root
)
from .lib import (
get_project_manager,
set_project_manager_to_folder_name
)
from .menu import launch_pype_menu
bmdvr = None
bmdvf = None
__all__ = [
# pipeline
@ -37,6 +50,7 @@ __all__ = [
"reload_pipeline",
"publish",
"launch_workfiles_app",
"maintained_selection",
# utils
"setup",
@ -44,16 +58,30 @@ __all__ = [
# lib
"get_project_manager",
"get_current_project",
"get_current_sequence",
"get_current_track_items",
"create_current_sequence_media_bin",
"create_compound_clip",
"swap_clips",
"get_pype_clip_metadata",
"set_project_manager_to_folder_name",
# menu
"launch_pype_menu",
# plugin
"Creator",
# workio
"open_file",
"save_file",
"current_file",
"has_unsaved_changes",
"file_extensions",
"work_root"
"work_root",
# singleton with black magic resolve module
"bmdvr",
"bmdvf"
]

View file

@ -21,9 +21,9 @@ class SelectInvalidAction(pyblish.api.Action):
def process(self, context, plugin):
try:
from pype.hosts.resolve.utils import get_resolve_module
resolve = get_resolve_module()
self.log.debug(resolve)
from . import get_project_manager
pm = get_project_manager()
self.log.debug(pm)
except ImportError:
raise ImportError("Current host is not Resolve")

View file

@ -1,20 +1,406 @@
import sys
from .utils import get_resolve_module
from pypeapp import Logger
import json
from opentimelineio import opentime
from pprint import pformat
from pype.api import Logger
log = Logger().get_logger(__name__, "resolve")
self = sys.modules[__name__]
self.pm = None
self.rename_index = 0
self.rename_add = 0
self.pype_metadata_key = "VFX Notes"
def get_project_manager():
from . import bmdvr
if not self.pm:
resolve = get_resolve_module()
self.pm = resolve.GetProjectManager()
self.pm = bmdvr.GetProjectManager()
return self.pm
def get_current_project():
# initialize project manager
get_project_manager()
return self.pm.GetCurrentProject()
def get_current_sequence():
# get current project
project = get_current_project()
return project.GetCurrentTimeline()
def get_current_track_items(
filter=False,
track_type=None,
selecting_color=None):
""" Gets all available current timeline track items
"""
track_type = track_type or "video"
selecting_color = selecting_color or "Chocolate"
project = get_current_project()
sequence = get_current_sequence()
selected_clips = list()
# get all tracks count filtered by track type
selected_track_count = sequence.GetTrackCount(track_type)
# loop all tracks and get items
_clips = dict()
for track_index in range(1, (int(selected_track_count) + 1)):
track_name = sequence.GetTrackName(track_type, track_index)
track_track_items = sequence.GetItemListInTrack(
track_type, track_index)
_clips[track_index] = track_track_items
_data = {
"project": project,
"sequence": sequence,
"track": {
"name": track_name,
"index": track_index,
"type": track_type}
}
# get track item object and its color
for clip_index, ti in enumerate(_clips[track_index]):
data = _data.copy()
data["clip"] = {
"item": ti,
"index": clip_index
}
ti_color = ti.GetClipColor()
if filter is True:
if selecting_color in ti_color:
selected_clips.append(data)
# ti.ClearClipColor()
else:
selected_clips.append(data)
return selected_clips
def create_current_sequence_media_bin(sequence):
seq_name = sequence.GetName()
media_pool = get_current_project().GetMediaPool()
root_folder = media_pool.GetRootFolder()
sub_folders = root_folder.GetSubFolderList()
testing_names = list()
print(f"_ sub_folders: {sub_folders}")
for subfolder in sub_folders:
subf_name = subfolder.GetName()
if seq_name in subf_name:
testing_names.append(subfolder)
else:
testing_names.append(False)
matching = next((f for f in testing_names if f is not False), None)
if not matching:
new_folder = media_pool.AddSubFolder(root_folder, seq_name)
media_pool.SetCurrentFolder(new_folder)
else:
media_pool.SetCurrentFolder(matching)
return media_pool.GetCurrentFolder()
def get_name_with_data(clip_data, presets):
"""
Take hierarchy data from presets and build name with parents data
Args:
clip_data (dict): clip data from `get_current_track_items()`
presets (dict): data from create plugin
Returns:
list: name, data
"""
def _replace_hash_to_expression(name, text):
_spl = text.split("#")
_len = (len(_spl) - 1)
_repl = f"{{{name}:0>{_len}}}"
new_text = text.replace(("#" * _len), _repl)
return new_text
# presets data
clip_name = presets["clipName"]
hierarchy = presets["hierarchy"]
hierarchy_data = presets["hierarchyData"].copy()
count_from = presets["countFrom"]
steps = presets["steps"]
# reset rename_add
if self.rename_add < count_from:
self.rename_add = count_from
# shot num calculate
if self.rename_index == 0:
shot_num = self.rename_add
else:
shot_num = self.rename_add + steps
print(f"shot_num: {shot_num}")
# clip data
_data = {
"sequence": clip_data["sequence"].GetName(),
"track": clip_data["track"]["name"].replace(" ", "_"),
"shot": shot_num
}
# solve # in test to pythonic explression
for k, v in hierarchy_data.items():
if "#" not in v:
continue
hierarchy_data[k] = _replace_hash_to_expression(k, v)
# fill up pythonic expresisons
for k, v in hierarchy_data.items():
hierarchy_data[k] = v.format(**_data)
# fill up clip name and hierarchy keys
hierarchy = hierarchy.format(**hierarchy_data)
clip_name = clip_name.format(**hierarchy_data)
self.rename_add = shot_num
print(f"shot_num: {shot_num}")
return (clip_name, {
"hierarchy": hierarchy,
"hierarchyData": hierarchy_data
})
def create_compound_clip(clip_data, folder, rename=False, **kwargs):
"""
Convert timeline object into nested timeline object
Args:
clip_data (dict): timeline item object packed into dict
with project, timeline (sequence)
folder (resolve.MediaPool.Folder): media pool folder object,
rename (bool)[optional]: renaming in sequence or not
kwargs (optional): additional data needed for rename=True (presets)
Returns:
resolve.MediaPoolItem: media pool item with compound clip timeline(cct)
"""
# get basic objects form data
project = clip_data["project"]
sequence = clip_data["sequence"]
clip = clip_data["clip"]
# get details of objects
clip_item = clip["item"]
track = clip_data["track"]
mp = project.GetMediaPool()
# get clip attributes
clip_attributes = get_clip_attributes(clip_item)
print(f"_ clip_attributes: {pformat(clip_attributes)}")
if rename:
presets = kwargs.get("presets")
if presets:
name, data = get_name_with_data(clip_data, presets)
# add hirarchy data to clip attributes
clip_attributes.update(data)
else:
name = "{:0>3}_{:0>4}".format(
int(track["index"]), int(clip["index"]))
else:
# build name
clip_name_split = clip_item.GetName().split(".")
name = "_".join([
track["name"],
str(track["index"]),
clip_name_split[0],
str(clip["index"])]
)
# get metadata
mp_item = clip_item.GetMediaPoolItem()
mp_props = mp_item.GetClipProperty()
mp_first_frame = int(mp_props["Start"])
mp_last_frame = int(mp_props["End"])
# initialize basic source timing for otio
ci_l_offset = clip_item.GetLeftOffset()
ci_duration = clip_item.GetDuration()
rate = float(mp_props["FPS"])
# source rational times
mp_in_rc = opentime.RationalTime((ci_l_offset), rate)
mp_out_rc = opentime.RationalTime((ci_l_offset + ci_duration - 1), rate)
# get frame in and out for clip swaping
in_frame = opentime.to_frames(mp_in_rc)
out_frame = opentime.to_frames(mp_out_rc)
# keep original sequence
sq_origin = sequence
# Set current folder to input media_pool_folder:
mp.SetCurrentFolder(folder)
# check if clip doesnt exist already:
clips = folder.GetClipList()
cct = next((c for c in clips
if c.GetName() in name), None)
if cct:
print(f"_ cct exists: {cct}")
else:
# Create empty timeline in current folder and give name:
cct = mp.CreateEmptyTimeline(name)
# check if clip doesnt exist already:
clips = folder.GetClipList()
cct = next((c for c in clips
if c.GetName() in name), None)
print(f"_ cct created: {cct}")
# Set current timeline to created timeline:
project.SetCurrentTimeline(cct)
# Add input clip to the current timeline:
mp.AppendToTimeline([{
"mediaPoolItem": mp_item,
"startFrame": mp_first_frame,
"endFrame": mp_last_frame
}])
# Set current timeline to the working timeline:
project.SetCurrentTimeline(sq_origin)
# Add collected metadata and attributes to the comound clip:
if mp_item.GetMetadata(self.pype_metadata_key):
clip_attributes[self.pype_metadata_key] = mp_item.GetMetadata(
self.pype_metadata_key)[self.pype_metadata_key]
# stringify
clip_attributes = json.dumps(clip_attributes)
# add attributes to metadata
for k, v in mp_item.GetMetadata().items():
cct.SetMetadata(k, v)
# add metadata to cct
cct.SetMetadata(self.pype_metadata_key, clip_attributes)
# reset start timecode of the compound clip
cct.SetClipProperty("Start TC", mp_props["Start TC"])
# swap clips on timeline
swap_clips(clip_item, cct, name, in_frame, out_frame)
cct.SetClipColor("Pink")
return cct
def swap_clips(from_clip, to_clip, to_clip_name, to_in_frame, to_out_frame):
"""
Swaping clips on timeline in timelineItem
It will add take and activate it to the frame range which is inputted
Args:
from_clip (resolve.mediaPoolItem)
to_clip (resolve.mediaPoolItem)
to_clip_name (str): name of to_clip
to_in_frame (float): cut in frame, usually `GetLeftOffset()`
to_out_frame (float): cut out frame, usually left offset plus duration
Returns:
bool: True if successfully replaced
"""
# add clip item as take to timeline
take = from_clip.AddTake(
to_clip,
float(to_in_frame),
float(to_out_frame)
)
if not take:
return False
for take_index in range(1, (int(from_clip.GetTakesCount()) + 1)):
take_item = from_clip.GetTakeByIndex(take_index)
take_mp_item = take_item["mediaPoolItem"]
if to_clip_name in take_mp_item.GetName():
from_clip.SelectTakeByIndex(take_index)
from_clip.FinalizeTake()
return True
return False
def validate_tc(x):
# Validate and reformat timecode string
if len(x) != 11:
print('Invalid timecode. Try again.')
c = ':'
colonized = x[:2] + c + x[3:5] + c + x[6:8] + c + x[9:]
if colonized.replace(':', '').isdigit():
print(f"_ colonized: {colonized}")
return colonized
else:
print('Invalid timecode. Try again.')
def get_pype_clip_metadata(clip):
"""
Get pype metadata created by creator plugin
Attributes:
clip (resolve.TimelineItem): resolve's object
Returns:
dict: hierarchy, orig clip attributes
"""
mp_item = clip.GetMediaPoolItem()
metadata = mp_item.GetMetadata()
return metadata.get(self.pype_metadata_key)
def get_clip_attributes(clip):
"""
Collect basic atrributes from resolve timeline item
Args:
clip (resolve.TimelineItem): timeline item object
Returns:
dict: all collected attributres as key: values
"""
mp_item = clip.GetMediaPoolItem()
data = {
"clipIn": clip.GetStart(),
"clipOut": clip.GetEnd(),
"clipLeftOffset": clip.GetLeftOffset(),
"clipRightOffset": clip.GetRightOffset(),
"clipMarkers": clip.GetMarkers(),
"clipFlags": clip.GetFlagList(),
"sourceId": mp_item.GetMediaId(),
"sourceProperties": mp_item.GetClipProperty()
}
return data
def set_project_manager_to_folder_name(folder_name):
"""
Sets context of Project manager to given folder by name.

View file

@ -1,6 +1,7 @@
QWidget {
background-color: #282828;
border-radius: 3;
font-size: 13px;
}
QPushButton {
@ -20,10 +21,38 @@ QPushButton:hover {
color: #e64b3d;
}
QSpinBox {
border: 1px solid #090909;
background-color: #201f1f;
color: #ffffff;
padding: 2;
max-width: 8em;
qproperty-alignment: AlignCenter;
}
QLineEdit {
border: 1px solid #090909;
border-radius: 3px;
background-color: #201f1f;
color: #ffffff;
padding: 2;
min-width: 10em;
qproperty-alignment: AlignCenter;
}
#PypeMenu {
border: 1px solid #fef9ef;
}
#Spacer {
QVBoxLayout {
background-color: #282828;
}
#Devider {
border: 1px solid #090909;
background-color: #585858;
}
QLabel {
color: #77776b;
}

View file

@ -2,27 +2,23 @@
Basic avalon integration
"""
import os
# import sys
import contextlib
from avalon.tools import workfiles
from avalon import api as avalon
from pyblish import api as pyblish
from pypeapp import Logger
import pype
from pype.api import Logger
log = Logger().get_logger(__name__, "resolve")
# self = sys.modules[__name__]
AVALON_CONFIG = os.environ["AVALON_CONFIG"]
PARENT_DIR = os.path.dirname(__file__)
PACKAGE_DIR = os.path.dirname(PARENT_DIR)
PLUGINS_DIR = os.path.join(PACKAGE_DIR, "plugins")
LOAD_PATH = os.path.join(PLUGINS_DIR, "resolve", "load")
CREATE_PATH = os.path.join(PLUGINS_DIR, "resolve", "create")
INVENTORY_PATH = os.path.join(PLUGINS_DIR, "resolve", "inventory")
LOAD_PATH = os.path.join(pype.PLUGINS_DIR, "resolve", "load")
CREATE_PATH = os.path.join(pype.PLUGINS_DIR, "resolve", "create")
INVENTORY_PATH = os.path.join(pype.PLUGINS_DIR, "resolve", "inventory")
PUBLISH_PATH = os.path.join(
PLUGINS_DIR, "resolve", "publish"
pype.PLUGINS_DIR, "resolve", "publish"
).replace("\\", "/")
AVALON_CONTAINERS = ":AVALON_CONTAINERS"
@ -40,11 +36,13 @@ def install():
See the Maya equivalent for inspiration on how to implement this.
"""
from . import get_resolve_module
# Disable all families except for the ones we explicitly want to see
family_states = [
"imagesequence",
"mov"
"mov",
"clip"
]
avalon.data["familiesStateDefault"] = False
avalon.data["familiesStateToggled"] = family_states
@ -59,6 +57,8 @@ def install():
avalon.register_plugin_path(avalon.Creator, CREATE_PATH)
avalon.register_plugin_path(avalon.InventoryAction, INVENTORY_PATH)
get_resolve_module()
def uninstall():
"""Uninstall all tha was installed
@ -140,3 +140,26 @@ def publish(parent):
"""Shorthand to publish from within host"""
from avalon.tools import publish
return publish.show(parent)
@contextlib.contextmanager
def maintained_selection():
"""Maintain selection during context
Example:
>>> with maintained_selection():
... node['selected'].setValue(True)
>>> print(node['selected'].value())
False
"""
try:
# do the operation
yield
finally:
pass
def reset_selection():
"""Deselect all selected nodes
"""
pass

View file

@ -1,6 +1,182 @@
import re
from avalon import api
# from pype.hosts.resolve import lib as drlib
from pype.hosts import resolve
from avalon.vendor import qargparse
from pype.api import config
from Qt import QtWidgets, QtCore
class CreatorWidget(QtWidgets.QDialog):
# output items
items = dict()
def __init__(self, name, info, presets, parent=None):
super(CreatorWidget, self).__init__(parent)
self.setObjectName(name)
self.setWindowFlags(
QtCore.Qt.Window
| QtCore.Qt.CustomizeWindowHint
| QtCore.Qt.WindowTitleHint
| QtCore.Qt.WindowCloseButtonHint
| QtCore.Qt.WindowStaysOnTopHint
)
self.setWindowTitle(name or "Pype Creator Input")
# Where inputs and labels are set
self.content_widget = [QtWidgets.QWidget(self)]
top_layout = QtWidgets.QFormLayout(self.content_widget[0])
top_layout.setObjectName("ContentLayout")
top_layout.addWidget(Spacer(5, self))
# first add widget tag line
top_layout.addWidget(QtWidgets.QLabel(info))
top_layout.addWidget(Spacer(5, self))
# main dynamic layout
self.content_widget.append(QtWidgets.QWidget(self))
content_layout = QtWidgets.QFormLayout(self.content_widget[-1])
# add preset data into input widget layout
self.items = self.add_presets_to_layout(content_layout, presets)
# Confirmation buttons
btns_widget = QtWidgets.QWidget(self)
btns_layout = QtWidgets.QHBoxLayout(btns_widget)
cancel_btn = QtWidgets.QPushButton("Cancel")
btns_layout.addWidget(cancel_btn)
ok_btn = QtWidgets.QPushButton("Ok")
btns_layout.addWidget(ok_btn)
# Main layout of the dialog
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.setContentsMargins(10, 10, 10, 10)
main_layout.setSpacing(0)
# adding content widget
for w in self.content_widget:
main_layout.addWidget(w)
main_layout.addWidget(btns_widget)
ok_btn.clicked.connect(self._on_ok_clicked)
cancel_btn.clicked.connect(self._on_cancel_clicked)
stylesheet = resolve.menu.load_stylesheet()
self.setStyleSheet(stylesheet)
def _on_ok_clicked(self):
self.result = self.value(self.items)
self.close()
def _on_cancel_clicked(self):
self.result = None
self.close()
def value(self, data):
for k, v in data.items():
if isinstance(v, dict):
print(f"nested: {k}")
data[k] = self.value(v)
elif getattr(v, "value", None):
print(f"normal int: {k}")
result = v.value()
data[k] = result()
else:
print(f"normal text: {k}")
result = v.text()
data[k] = result()
return data
def camel_case_split(self, text):
matches = re.finditer(
'.+?(?:(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|$)', text)
return " ".join([str(m.group(0)).capitalize() for m in matches])
def create_row(self, layout, type, text, **kwargs):
# get type attribute from qwidgets
attr = getattr(QtWidgets, type)
# convert label text to normal capitalized text with spaces
label_text = self.camel_case_split(text)
# assign the new text to lable widget
label = QtWidgets.QLabel(label_text)
label.setObjectName("LineLabel")
# create attribute name text strip of spaces
attr_name = text.replace(" ", "")
# create attribute and assign default values
setattr(
self,
attr_name,
attr(parent=self))
# assign the created attribute to variable
item = getattr(self, attr_name)
for func, val in kwargs.items():
if getattr(item, func):
func_attr = getattr(item, func)
func_attr(val)
# add to layout
layout.addRow(label, item)
return item
def add_presets_to_layout(self, content_layout, data):
for k, v in data.items():
if isinstance(v, dict):
# adding spacer between sections
self.content_widget.append(QtWidgets.QWidget(self))
devider = QtWidgets.QVBoxLayout(self.content_widget[-1])
devider.addWidget(Spacer(5, self))
devider.setObjectName("Devider")
# adding nested layout with label
self.content_widget.append(QtWidgets.QWidget(self))
nested_content_layout = QtWidgets.QFormLayout(
self.content_widget[-1])
nested_content_layout.setObjectName("NestedContentLayout")
# add nested key as label
self.create_row(nested_content_layout, "QLabel", k)
data[k] = self.add_presets_to_layout(nested_content_layout, v)
elif isinstance(v, str):
print(f"layout.str: {k}")
print(f"content_layout: {content_layout}")
data[k] = self.create_row(
content_layout, "QLineEdit", k, setText=v)
elif isinstance(v, int):
print(f"layout.int: {k}")
print(f"content_layout: {content_layout}")
data[k] = self.create_row(
content_layout, "QSpinBox", k, setValue=v)
return data
class Spacer(QtWidgets.QWidget):
def __init__(self, height, *args, **kwargs):
super(self.__class__, self).__init__(*args, **kwargs)
self.setFixedHeight(height)
real_spacer = QtWidgets.QWidget(self)
real_spacer.setObjectName("Spacer")
real_spacer.setFixedHeight(height)
layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(real_spacer)
self.setLayout(layout)
def get_reference_node_parents(ref):
@ -73,3 +249,25 @@ class SequenceLoader(api.Loader):
"""Remove an existing `container`
"""
pass
class Creator(api.Creator):
"""Creator class wrapper
"""
marker_color = "Purple"
def __init__(self, *args, **kwargs):
super(Creator, self).__init__(*args, **kwargs)
self.presets = config.get_presets()['plugins']["resolve"][
"create"].get(self.__class__.__name__, {})
# adding basic current context resolve objects
self.project = resolve.get_current_project()
self.sequence = resolve.get_current_sequence()
if (self.options or {}).get("useSelection"):
self.selected = resolve.get_current_track_items(filter=True)
else:
self.selected = resolve.get_current_track_items(filter=False)
self.widget = CreatorWidget

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python
import time
from pype.hosts.resolve.utils import get_resolve_module
from pypeapp import Logger
from pype.api import Logger
log = Logger().get_logger(__name__, "resolve")

View file

@ -3,7 +3,7 @@ import sys
import avalon.api as avalon
import pype
from pypeapp import Logger
from pype.api import Logger
log = Logger().get_logger(__name__)

View file

@ -1,65 +0,0 @@
#! python3
# -*- coding: utf-8 -*-
# convert clip def
def convert_clip(timeline=None):
"""Convert timeline item (clip) into compound clip pype container
Args:
timeline (MediaPool.Timeline): Object of timeline
Returns:
bool: `True` if success
Raises:
Exception: description
"""
pass
# decorator function create_current_timeline_media_bin()
def create_current_timeline_media_bin(timeline=None):
"""Convert timeline item (clip) into compound clip pype container
Args:
timeline (MediaPool.Timeline): Object of timeline
Returns:
bool: `True` if success
Raises:
Exception: description
"""
pass
# decorator function get_selected_track_items()
def get_selected_track_items():
"""Convert timeline item (clip) into compound clip pype container
Args:
timeline (MediaPool.Timeline): Object of timeline
Returns:
bool: `True` if success
Raises:
Exception: description
"""
print("testText")
# PypeCompoundClip() class
class PypeCompoundClip(object):
"""docstring for ."""
def __init__(self, arg):
super(self).__init__()
self.arg = arg
def create_compound_clip(self):
pass

View file

@ -1,57 +0,0 @@
import os
import sys
import pype
import importlib
import pyblish.api
import pyblish.util
import avalon.api
from avalon.tools import publish
from pypeapp import Logger
log = Logger().get_logger(__name__)
def main(env):
# Registers pype's Global pyblish plugins
pype.install()
# Register Host (and it's pyblish plugins)
host_name = env["AVALON_APP"]
# TODO not sure if use "pype." or "avalon." for host import
host_import_str = f"pype.{host_name}"
try:
host_module = importlib.import_module(host_import_str)
except ModuleNotFoundError:
log.error((
f"Host \"{host_name}\" can't be imported."
f" Import string \"{host_import_str}\" failed."
))
return False
avalon.api.install(host_module)
# Register additional paths
addition_paths_str = env.get("PUBLISH_PATHS") or ""
addition_paths = addition_paths_str.split(os.pathsep)
for path in addition_paths:
path = os.path.normpath(path)
if not os.path.exists(path):
continue
pyblish.api.register_plugin_path(path)
# Register project specific plugins
project_name = os.environ["AVALON_PROJECT"]
project_plugins_paths = env.get("PYPE_PROJECT_PLUGINS") or ""
for path in project_plugins_paths.split(os.pathsep):
plugin_path = os.path.join(path, project_name, "plugins")
if os.path.exists(plugin_path):
pyblish.api.register_plugin_path(plugin_path)
return publish.show()
if __name__ == "__main__":
result = main(os.environ)
sys.exit(not bool(result))

View file

@ -1,35 +0,0 @@
#! python3
# -*- coding: utf-8 -*-
import os
from pypeapp import execute, Logger
from pype.hosts.resolve.utils import get_resolve_module
log = Logger().get_logger("Resolve")
CURRENT_DIR = os.getenv("RESOLVE_UTILITY_SCRIPTS_DIR", "")
python_dir = os.getenv("PYTHON36_RESOLVE")
python_exe = os.path.normpath(
os.path.join(python_dir, "python.exe")
)
resolve = get_resolve_module()
PM = resolve.GetProjectManager()
P = PM.GetCurrentProject()
log.info(P.GetName())
# ______________________________________________________
# testing subprocessing Scripts
testing_py = os.path.join(CURRENT_DIR, "ResolvePageSwitcher.py")
testing_py = os.path.normpath(testing_py)
log.info(f"Testing path to script: `{testing_py}`")
returncode = execute(
[python_exe, os.path.normpath(testing_py)],
env=dict(os.environ)
)
# Check if output file exists
if returncode != 0:
log.error("Executing failed!")

View file

@ -0,0 +1,21 @@
#! python3
import sys
from pype.api import Logger
import DaVinciResolveScript as bmdvr
log = Logger().get_logger(__name__)
def main():
import pype.hosts.resolve as bmdvr
bm = bmdvr.utils.get_resolve_module()
log.info(f"blackmagicmodule: {bm}")
print(f"_>> bmdvr.scriptapp(Resolve): {bmdvr.scriptapp('Resolve')}")
if __name__ == "__main__":
result = main()
sys.exit(not bool(result))

View file

@ -9,18 +9,16 @@ import os
import shutil
from pypeapp import Logger
log = Logger().get_logger(__name__, "resolve")
self = sys.modules[__name__]
self.bmd = None
def get_resolve_module():
from pype.hosts import resolve
# dont run if already loaded
if self.bmd:
return self.bmd
if resolve.bmdvr:
log.info(("resolve module is assigned to "
f"`pype.hosts.resolve.bmdvr`: {resolve.bmdvr}"))
return resolve.bmdvr
try:
"""
The PYTHONPATH needs to be set correctly for this import
@ -71,8 +69,14 @@ def get_resolve_module():
)
sys.exit()
# assign global var and return
self.bmd = bmd.scriptapp("Resolve")
return self.bmd
bmdvr = bmd.scriptapp("Resolve")
# bmdvf = bmd.scriptapp("Fusion")
resolve.bmdvr = bmdvr
resolve.bmdvf = bmdvr.Fusion()
log.info(("Assigning resolve module to "
f"`pype.hosts.resolve.bmdvr`: {resolve.bmdvr}"))
log.info(("Assigning resolve module to "
f"`pype.hosts.resolve.bmdvf`: {resolve.bmdvf}"))
def _sync_utility_scripts(env=None):

View file

@ -2,8 +2,9 @@
import os
from pypeapp import Logger
from .lib import (
from . import (
get_project_manager,
get_current_project,
set_project_manager_to_folder_name
)
@ -26,7 +27,7 @@ def save_file(filepath):
pm = get_project_manager()
file = os.path.basename(filepath)
fname, _ = os.path.splitext(file)
project = pm.GetCurrentProject()
project = get_current_project()
name = project.GetName()
if "Untitled Project" not in name:

View file

@ -0,0 +1,5 @@
from .websocket_server import WebSocketServer
def tray_init(tray_widget, main_widget):
return WebSocketServer()

View file

@ -0,0 +1,47 @@
import asyncio
from pype.api import Logger
from wsrpc_aiohttp import WebSocketRoute
log = Logger().get_logger("WebsocketServer")
class ExternalApp1(WebSocketRoute):
"""
One route, mimicking external application (like Harmony, etc).
All functions could be called from client.
'do_notify' function calls function on the client - mimicking
notification after long running job on the server or similar
"""
def init(self, **kwargs):
# Python __init__ must be return "self".
# This method might return anything.
log.debug("someone called ExternalApp1 route")
return kwargs
async def server_function_one(self):
log.info('In function one')
async def server_function_two(self):
log.info('In function two')
return 'function two'
async def server_function_three(self):
log.info('In function three')
asyncio.ensure_future(self.do_notify())
return '{"message":"function tree"}'
async def server_function_four(self, *args, **kwargs):
log.info('In function four args {} kwargs {}'.format(args, kwargs))
ret = dict(**kwargs)
ret["message"] = "function four received arguments"
return str(ret)
# This method calls function on the client side
async def do_notify(self):
import time
time.sleep(5)
log.info('Calling function on server after delay')
awesome = 'Somebody server_function_three method!'
await self.socket.call('notify', result=awesome)

View file

@ -0,0 +1,179 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- CSS only -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
<script type="text/javascript" src="//unpkg.com/@wsrpc/client"></script>
<script>
WSRPC.DEBUG = true;
WSRPC.TRACE = true;
var url = (window.location.protocol==="https):"?"wss://":"ws://") + window.location.host + '/ws/';
url = 'ws://localhost:8099/ws/';
RPC = new WSRPC(url, 5000);
console.log(RPC.state());
// Configure client API, that can be called from server
RPC.addRoute('notify', function (data) {
console.log('Server called client route "notify":', data);
alert('Server called client route "notify":', data)
return data.result;
});
RPC.connect();
console.log(RPC.state());
$(document).ready(function() {
function NoReturn(){
// Call stateful route
// After you call that route, server would execute 'notify' route on the
// client, that is registered above.
RPC.call('ExternalApp1.server_function_one').then(function (data) {
console.log('Result for calling server route "server_function_one": ', data);
alert('Function "server_function_two" returned: '+data);
}, function (error) {
alert(error);
});
}
function ReturnValue(){
// Call stateful route
// After you call that route, server would execute 'notify' route on the
// client, that is registered above.
RPC.call('ExternalApp1.server_function_two').then(function (data) {
console.log('Result for calling server route "server_function_two": ', data);
alert('Function "server_function_two" returned: '+data);
}, function (error) {
alert(error);
});
}
function ValueAndNotify(){
// After you call that route, server would execute 'notify' route on the
// client, that is registered above.
RPC.call('ExternalApp1.server_function_three').then(function (data) {
console.log('Result for calling server route "server_function_three": ', data);
alert('Function "server_function_three" returned: '+data);
}, function (error) {
alert(error);
});
}
function SendValue(){
// After you call that route, server would execute 'notify' route on the
// client, that is registered above.
RPC.call('ExternalApp1.server_function_four', {foo: 'one', bar:'two'}).then(function (data) {
console.log('Result for calling server route "server_function_four": ', data);
alert('Function "server_function_four" returned: '+data);
}, function (error) {
alert(error);
});
}
$('#noReturn').click(function() {
NoReturn();
})
$('#returnValue').click(function() {
ReturnValue();
})
$('#valueAndNotify').click(function() {
ValueAndNotify();
})
$('#sendValue').click(function() {
SendValue();
})
})
<!-- // Call stateless method-->
<!-- RPC.call('test2').then(function (data) {-->
<!-- console.log('Result for calling server route "test2"', data);-->
<!-- });-->
</script>
</head>
<body>
<div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
<h5 class="my-0 mr-md-auto font-weight-normal">Test of wsrpc javascript client</h5>
</div>
<div class="container">
<div class="card-deck mb-3 text-center">
<div class="card mb-4 shadow-sm">
<div class="card-header">
<h4 class="my-0 font-weight-normal">No return value</h4>
</div>
<div class="card-body">
<ul class="list-unstyled mt-3 mb-4">
<li>Calls server_function_one</li>
<li>Function only logs on server</li>
<li>No return value</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
</ul>
<button type="button" id="noReturn" class="btn btn-lg btn-block btn-outline-primary">Call server</button>
</div>
</div>
<div class="card mb-4 shadow-sm">
<div class="card-header">
<h4 class="my-0 font-weight-normal">Return value</h4>
</div>
<div class="card-body">
<ul class="list-unstyled mt-3 mb-4">
<li>Calls server_function_two</li>
<li>Function logs on server</li>
<li>Returns simple text value</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
</ul>
<button type="button" id="returnValue" class="btn btn-lg btn-block btn-outline-primary">Call server</button>
</div>
</div>
<div class="card mb-4 shadow-sm">
<div class="card-header">
<h4 class="my-0 font-weight-normal">Notify</h4>
</div>
<div class="card-body">
<ul class="list-unstyled mt-3 mb-4">
<li>Calls server_function_three</li>
<li>Function logs on server</li>
<li>Returns json payload </li>
<li>Server then calls function ON the client after delay</li>
<li>&nbsp;</li>
</ul>
<button type="button" id="valueAndNotify" class="btn btn-lg btn-block btn-outline-primary">Call server</button>
</div>
</div>
<div class="card mb-4 shadow-sm">
<div class="card-header">
<h4 class="my-0 font-weight-normal">Send value</h4>
</div>
<div class="card-body">
<ul class="list-unstyled mt-3 mb-4">
<li>Calls server_function_four</li>
<li>Function logs on server</li>
<li>Returns modified sent values</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
</ul>
<button type="button" id="sendValue" class="btn btn-lg btn-block btn-outline-primary">Call server</button>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,34 @@
import asyncio
from wsrpc_aiohttp import WSRPCClient
"""
Simple testing Python client for wsrpc_aiohttp
Calls sequentially multiple methods on server
"""
loop = asyncio.get_event_loop()
async def main():
print("main")
client = WSRPCClient("ws://127.0.0.1:8099/ws/",
loop=asyncio.get_event_loop())
client.add_route('notify', notify)
await client.connect()
print("connected")
print(await client.proxy.ExternalApp1.server_function_one())
print(await client.proxy.ExternalApp1.server_function_two())
print(await client.proxy.ExternalApp1.server_function_three())
print(await client.proxy.ExternalApp1.server_function_four(foo="one"))
await client.close()
def notify(socket, *args, **kwargs):
print("called from server")
if __name__ == "__main__":
# loop.run_until_complete(main())
asyncio.run(main())

View file

@ -0,0 +1,187 @@
from pype.api import config, Logger
import threading
from aiohttp import web
import asyncio
from wsrpc_aiohttp import STATIC_DIR, WebSocketAsync
import os
import sys
import pyclbr
import importlib
log = Logger().get_logger("WebsocketServer")
class WebSocketServer():
"""
Basic POC implementation of asychronic websocket RPC server.
Uses class in external_app_1.py to mimic implementation for single
external application.
'test_client' folder contains two test implementations of client
WIP
"""
def __init__(self):
self.qaction = None
self.failed_icon = None
self._is_running = False
default_port = 8099
try:
self.presets = config.get_presets()["services"]["websocket_server"]
except Exception:
self.presets = {"default_port": default_port, "exclude_ports": []}
log.debug((
"There are not set presets for WebsocketServer."
" Using defaults \"{}\""
).format(str(self.presets)))
self.app = web.Application()
self.app.router.add_route("*", "/ws/", WebSocketAsync)
self.app.router.add_static("/js", STATIC_DIR)
self.app.router.add_static("/", ".")
# add route with multiple methods for single "external app"
directories_with_routes = ['hosts']
self.add_routes_for_directories(directories_with_routes)
self.websocket_thread = WebsocketServerThread(self, default_port)
def add_routes_for_directories(self, directories_with_routes):
""" Loops through selected directories to find all modules and
in them all classes implementing 'WebSocketRoute' that could be
used as route.
All methods in these classes are registered automatically.
"""
for dir_name in directories_with_routes:
dir_name = os.path.join(os.path.dirname(__file__), dir_name)
for file_name in os.listdir(dir_name):
if '.py' in file_name and '__' not in file_name:
self.add_routes_for_module(file_name, dir_name)
def add_routes_for_module(self, file_name, dir_name):
""" Auto routes for all classes implementing 'WebSocketRoute'
in 'file_name' in 'dir_name'
"""
module_name = file_name.replace('.py', '')
module_info = pyclbr.readmodule(module_name, [dir_name])
for class_name, cls_object in module_info.items():
sys.path.append(dir_name)
if 'WebSocketRoute' in cls_object.super:
log.debug('Adding route for {}'.format(class_name))
module = importlib.import_module(module_name)
cls = getattr(module, class_name)
WebSocketAsync.add_route(class_name, cls)
sys.path.pop()
def tray_start(self):
self.websocket_thread.start()
def tray_exit(self):
self.stop()
def stop_websocket_server(self):
self.stop()
@property
def is_running(self):
return self.websocket_thread.is_running
def stop(self):
if not self.is_running:
return
try:
log.debug("Stopping websocket server")
self.websocket_thread.is_running = False
self.websocket_thread.stop()
except Exception:
log.warning(
"Error has happened during Killing websocket server",
exc_info=True
)
def thread_stopped(self):
self._is_running = False
class WebsocketServerThread(threading.Thread):
""" Listener for websocket rpc requests.
It would be probably better to "attach" this to main thread (as for
example Harmony needs to run something on main thread), but currently
it creates separate thread and separate asyncio event loop
"""
def __init__(self, module, port):
super(WebsocketServerThread, self).__init__()
self.is_running = False
self.port = port
self.module = module
self.loop = None
self.runner = None
self.site = None
def run(self):
self.is_running = True
try:
log.info("Starting websocket server")
self.loop = asyncio.new_event_loop() # create new loop for thread
asyncio.set_event_loop(self.loop)
self.loop.run_until_complete(self.start_server())
log.debug(
"Running Websocket server on URL:"
" \"ws://localhost:{}\"".format(self.port)
)
asyncio.ensure_future(self.check_shutdown(), loop=self.loop)
self.loop.run_forever()
except Exception:
log.warning(
"Websocket Server service has failed", exc_info=True
)
finally:
self.loop.close() # optional
self.is_running = False
self.module.thread_stopped()
log.info("Websocket server stopped")
async def start_server(self):
""" Starts runner and TCPsite """
self.runner = web.AppRunner(self.module.app)
await self.runner.setup()
self.site = web.TCPSite(self.runner, 'localhost', self.port)
await self.site.start()
def stop(self):
"""Sets is_running flag to false, 'check_shutdown' shuts server down"""
self.is_running = False
async def check_shutdown(self):
""" Future that is running and checks if server should be running
periodically.
"""
while self.is_running:
await asyncio.sleep(0.5)
log.debug("Starting shutdown")
await self.site.stop()
log.debug("Site stopped")
await self.runner.cleanup()
log.debug("Runner stopped")
tasks = [task for task in asyncio.all_tasks() if
task is not asyncio.current_task()]
list(map(lambda task: task.cancel(), tasks)) # cancel all the tasks
results = await asyncio.gather(*tasks, return_exceptions=True)
log.debug(f'Finished awaiting cancelled tasks, results: {results}...')
await self.loop.shutdown_asyncgens()
# to really make sure everything else has time to stop
await asyncio.sleep(0.07)
self.loop.stop()

View file

@ -0,0 +1,79 @@
from pprint import pformat
from pype.hosts import resolve
from pype.hosts.resolve import lib
class CreateShotClip(resolve.Creator):
"""Publishable clip"""
label = "Shot"
family = "clip"
icon = "film"
defaults = ["Main"]
gui_name = "Pype sequencial rename with hirerarchy"
gui_info = "Define sequencial rename and fill hierarchy data."
gui_inputs = {
"clipName": "{episode}{sequence}{shot}",
"hierarchy": "{folder}/{sequence}/{shot}",
"countFrom": 10,
"steps": 10,
"hierarchyData": {
"folder": "shots",
"shot": "sh####",
"track": "{track}",
"sequence": "sc010",
"episode": "ep01"
}
}
presets = None
def process(self):
# solve gui inputs overwrites from presets
# overwrite gui inputs from presets
for k, v in self.gui_inputs.items():
if isinstance(v, dict):
# nested dictionary (only one level allowed)
for _k, _v in v.items():
if self.presets.get(_k):
self.gui_inputs[k][_k] = self.presets[_k]
if self.presets.get(k):
self.gui_inputs[k] = self.presets[k]
# open widget for plugins inputs
widget = self.widget(self.gui_name, self.gui_info, self.gui_inputs)
widget.exec_()
print(f"__ selected_clips: {self.selected}")
if len(self.selected) < 1:
return
if not widget.result:
print("Operation aborted")
return
# sequence attrs
sq_frame_start = self.sequence.GetStartFrame()
sq_markers = self.sequence.GetMarkers()
print(f"__ sq_frame_start: {pformat(sq_frame_start)}")
print(f"__ seq_markers: {pformat(sq_markers)}")
# create media bin for compound clips (trackItems)
mp_folder = resolve.create_current_sequence_media_bin(self.sequence)
print(f"_ mp_folder: {mp_folder.GetName()}")
lib.rename_add = 0
for i, t_data in enumerate(self.selected):
lib.rename_index = i
# clear color after it is done
t_data["clip"]["item"].ClearClipColor()
# convert track item to timeline media pool item
resolve.create_compound_clip(
t_data,
mp_folder,
rename=True,
**dict(
{"presets": widget.result})
)

View file

@ -0,0 +1,162 @@
import os
from pyblish import api
from pype.hosts import resolve
import json
class CollectClips(api.ContextPlugin):
"""Collect all Track items selection."""
order = api.CollectorOrder + 0.01
label = "Collect Clips"
hosts = ["resolve"]
def process(self, context):
# create asset_names conversion table
if not context.data.get("assetsShared"):
self.log.debug("Created `assetsShared` in context")
context.data["assetsShared"] = dict()
projectdata = context.data["projectEntity"]["data"]
selection = resolve.get_current_track_items(
filter=True, selecting_color="Pink")
for clip_data in selection:
data = dict()
# get basic objects form data
project = clip_data["project"]
sequence = clip_data["sequence"]
clip = clip_data["clip"]
# sequence attrs
sq_frame_start = sequence.GetStartFrame()
self.log.debug(f"sq_frame_start: {sq_frame_start}")
sq_markers = sequence.GetMarkers()
# get details of objects
clip_item = clip["item"]
track = clip_data["track"]
mp = project.GetMediaPool()
# get clip attributes
clip_metadata = resolve.get_pype_clip_metadata(clip_item)
clip_metadata = json.loads(clip_metadata)
self.log.debug(f"clip_metadata: {clip_metadata}")
compound_source_prop = clip_metadata["sourceProperties"]
self.log.debug(f"compound_source_prop: {compound_source_prop}")
asset_name = clip_item.GetName()
mp_item = clip_item.GetMediaPoolItem()
mp_prop = mp_item.GetClipProperty()
source_first = int(compound_source_prop["Start"])
source_last = int(compound_source_prop["End"])
source_duration = compound_source_prop["Frames"]
fps = float(mp_prop["FPS"])
self.log.debug(f"source_first: {source_first}")
self.log.debug(f"source_last: {source_last}")
self.log.debug(f"source_duration: {source_duration}")
self.log.debug(f"fps: {fps}")
source_path = os.path.normpath(
compound_source_prop["File Path"])
source_name = compound_source_prop["File Name"]
source_id = clip_metadata["sourceId"]
self.log.debug(f"source_path: {source_path}")
self.log.debug(f"source_name: {source_name}")
self.log.debug(f"source_id: {source_id}")
clip_left_offset = int(clip_item.GetLeftOffset())
clip_right_offset = int(clip_item.GetRightOffset())
self.log.debug(f"clip_left_offset: {clip_left_offset}")
self.log.debug(f"clip_right_offset: {clip_right_offset}")
# source in/out
source_in = int(source_first + clip_left_offset)
source_out = int(source_first + clip_right_offset)
self.log.debug(f"source_in: {source_in}")
self.log.debug(f"source_out: {source_out}")
clip_in = int(clip_item.GetStart() - sq_frame_start)
clip_out = int(clip_item.GetEnd() - sq_frame_start)
clip_duration = int(clip_item.GetDuration())
self.log.debug(f"clip_in: {clip_in}")
self.log.debug(f"clip_out: {clip_out}")
self.log.debug(f"clip_duration: {clip_duration}")
is_sequence = False
self.log.debug(
"__ assets_shared: {}".format(
context.data["assetsShared"]))
# Check for clips with the same range
# this is for testing if any vertically neighbouring
# clips has been already processed
clip_matching_with_range = next(
(k for k, v in context.data["assetsShared"].items()
if (v.get("_clipIn", 0) == clip_in)
and (v.get("_clipOut", 0) == clip_out)
), False)
# check if clip name is the same in matched
# vertically neighbouring clip
# if it is then it is correct and resent variable to False
# not to be rised wrong name exception
if asset_name in str(clip_matching_with_range):
clip_matching_with_range = False
# rise wrong name exception if found one
assert (not clip_matching_with_range), (
"matching clip: {asset}"
" timeline range ({clip_in}:{clip_out})"
" conflicting with {clip_matching_with_range}"
" >> rename any of clips to be the same as the other <<"
).format(
**locals())
if ("[" in source_name) and ("]" in source_name):
is_sequence = True
data.update({
"name": "_".join([
track["name"], asset_name, source_name]),
"item": clip_item,
"source": mp_item,
# "timecodeStart": str(source.timecodeStart()),
"timelineStart": sq_frame_start,
"sourcePath": source_path,
"sourceFileHead": source_name,
"isSequence": is_sequence,
"track": track["name"],
"trackIndex": track["index"],
"sourceFirst": source_first,
"sourceIn": source_in,
"sourceOut": source_out,
"mediaDuration": source_duration,
"clipIn": clip_in,
"clipOut": clip_out,
"clipDuration": clip_duration,
"asset": asset_name,
"subset": "plateMain",
"family": "clip",
"families": [],
"handleStart": projectdata.get("handleStart", 0),
"handleEnd": projectdata.get("handleEnd", 0)})
instance = context.create_instance(**data)
self.log.info("Created instance: {}".format(instance))
self.log.info("Created instance.data: {}".format(instance.data))
context.data["assetsShared"][asset_name] = {
"_clipIn": clip_in,
"_clipOut": clip_out
}
self.log.info(
"context.data[\"assetsShared\"]: {}".format(
context.data["assetsShared"]))

View file

@ -1,17 +0,0 @@
import pyblish.api
from pype.hosts.resolve.utils import get_resolve_module
class CollectProject(pyblish.api.ContextPlugin):
"""Collect Project object"""
order = pyblish.api.CollectorOrder - 0.1
label = "Collect Project"
hosts = ["resolve"]
def process(self, context):
resolve = get_resolve_module()
PM = resolve.GetProjectManager()
P = PM.GetCurrentProject()
self.log.info(P.GetName())

View file

@ -0,0 +1,29 @@
import os
import pyblish.api
from pype.hosts.resolve.utils import get_resolve_module
class CollectProject(pyblish.api.ContextPlugin):
"""Collect Project object"""
order = pyblish.api.CollectorOrder - 0.1
label = "Collect Project"
hosts = ["resolve"]
def process(self, context):
exported_projet_ext = ".drp"
current_dir = os.getenv("AVALON_WORKDIR")
resolve = get_resolve_module()
PM = resolve.GetProjectManager()
P = PM.GetCurrentProject()
name = P.GetName()
fname = name + exported_projet_ext
current_file = os.path.join(current_dir, fname)
normalised = os.path.normpath(current_file)
context.data["project"] = P
context.data["currentFile"] = normalised
self.log.info(name)
self.log.debug(normalised)

View file

@ -0,0 +1,9 @@
from .lib import (
system_settings,
project_settings
)
__all__ = (
"system_settings",
"project_settings"
)

View file

@ -0,0 +1,42 @@
{
"nuke": {
"root": {
"colorManagement": "Nuke",
"OCIO_config": "nuke-default",
"defaultViewerLUT": "Nuke Root LUTs",
"monitorLut": "sRGB",
"int8Lut": "sRGB",
"int16Lut": "sRGB",
"logLut": "Cineon",
"floatLut": "linear"
},
"viewer": {
"viewerProcess": "sRGB"
},
"write": {
"render": {
"colorspace": "linear"
},
"prerender": {
"colorspace": "linear"
},
"still": {
"colorspace": "sRGB"
}
},
"read": {
"[^-a-zA-Z0-9]beauty[^-a-zA-Z0-9]": "linear",
"[^-a-zA-Z0-9](P|N|Z|crypto)[^-a-zA-Z0-9]": "linear",
"[^-a-zA-Z0-9](plateRef)[^-a-zA-Z0-9]": "sRGB"
}
},
"maya": {
},
"houdini": {
},
"resolve": {
}
}

View file

@ -0,0 +1,55 @@
{
"nuke": {
"nodes": {
"connected": true,
"modifymetadata": {
"_id": "connect_metadata",
"_previous": "ENDING",
"metadata.set.pype_studio_name": "{PYPE_STUDIO_NAME}",
"metadata.set.avalon_project_name": "{AVALON_PROJECT}",
"metadata.set.avalon_project_code": "{PYPE_STUDIO_CODE}",
"metadata.set.avalon_asset_name": "{AVALON_ASSET}"
},
"crop": {
"_id": "connect_crop",
"_previous": "connect_metadata",
"box": [
"{metadata.crop.x}",
"{metadata.crop.y}",
"{metadata.crop.right}",
"{metadata.crop.top}"
]
},
"write": {
"render": {
"_id": "output_write",
"_previous": "connect_crop",
"file_type": "exr",
"datatype": "16 bit half",
"compression": "Zip (1 scanline)",
"autocrop": true,
"tile_color": "0xff0000ff",
"channels": "rgb"
},
"prerender": {
"_id": "output_write",
"_previous": "connect_crop",
"file_type": "exr",
"datatype": "16 bit half",
"compression": "Zip (1 scanline)",
"autocrop": false,
"tile_color": "0xc9892aff",
"channels": "rgba"
},
"still": {
"_previous": "connect_crop",
"channels": "rgba",
"file_type": "tiff",
"datatype": "16 bit",
"compression": "LZW",
"tile_color": "0x4145afff"
}
}
}
}
}

View file

@ -0,0 +1,5 @@
{
"windows": "C:/projects",
"linux": "/mnt/share/projects",
"darwin": "/Volumes/path"
}

View file

@ -0,0 +1,30 @@
{
"version_padding": 3,
"version": "v{version:0>{@version_padding}}",
"frame_padding": 4,
"frame": "{frame:0>{@frame_padding}}",
"work": {
"folder": "{root}/{project[name]}/{hierarchy}/{asset}/work/{task}",
"file": "{project[code]}_{asset}_{task}_{@version}<_{comment}>.{ext}",
"path": "{@folder}/{@file}"
},
"render": {
"folder": "{root}/{project[name]}/{hierarchy}/{asset}/publish/render/{subset}/{@version}",
"file": "{project[code]}_{asset}_{subset}_{@version}<_{output}><.{@frame}>.{representation}",
"path": "{@folder}/{@file}"
},
"texture": {
"path": "{root}/{project[name]}/{hierarchy}/{asset}/publish/{family}/{subset}"
},
"publish": {
"folder": "{root}/{project[name]}/{hierarchy}/{asset}/publish/{family}/{subset}/{@version}",
"file": "{project[code]}_{asset}_{subset}_{@version}<_{output}><.{@frame}>.{representation}",
"path": "{@folder}/{@file}",
"thumbnail": "{thumbnail_root}/{project[name]}/{_id}_{thumbnail_type}{ext}"
},
"master": {
"folder": "{root}/{project[name]}/{hierarchy}/{asset}/publish/{family}/{subset}/master",
"file": "{project[code]}_{asset}_{subset}_master<_{output}><.{frame}>.{representation}",
"path": "{@folder}/{@file}"
}
}

View file

@ -0,0 +1,16 @@
{
"sync_to_avalon": {
"statuses_name_change": ["not ready", "ready"]
},
"status_update": {
"_ignore_": ["in progress", "ommited", "on hold"],
"Ready": ["not ready"],
"In Progress" : ["_any_"]
},
"status_version_to_task": {
"__description__": "Status `from` (key) must be lowered!",
"in progress": "in progress",
"approved": "approved"
}
}

View file

@ -0,0 +1,165 @@
[{
"label": "FPS",
"key": "fps",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"write_security_role": ["ALL"],
"read_security_role": ["ALL"],
"default": null,
"config": {
"isdecimal": true
}
}, {
"label": "Applications",
"key": "applications",
"type": "enumerator",
"entity_type": "show",
"group": "avalon",
"config": {
"multiselect": true,
"data": [
{"blender_2.80": "Blender 2.80"},
{"blender_2.81": "Blender 2.81"},
{"blender_2.82": "Blender 2.82"},
{"blender_2.83": "Blender 2.83"},
{"celaction_local": "CelAction2D Local"},
{"maya_2017": "Maya 2017"},
{"maya_2018": "Maya 2018"},
{"maya_2019": "Maya 2019"},
{"nuke_10.0": "Nuke 10.0"},
{"nuke_11.2": "Nuke 11.2"},
{"nuke_11.3": "Nuke 11.3"},
{"nuke_12.0": "Nuke 12.0"},
{"nukex_10.0": "NukeX 10.0"},
{"nukex_11.2": "NukeX 11.2"},
{"nukex_11.3": "NukeX 11.3"},
{"nukex_12.0": "NukeX 12.0"},
{"nukestudio_10.0": "NukeStudio 10.0"},
{"nukestudio_11.2": "NukeStudio 11.2"},
{"nukestudio_11.3": "NukeStudio 11.3"},
{"nukestudio_12.0": "NukeStudio 12.0"},
{"harmony_17": "Harmony 17"},
{"houdini_16.5": "Houdini 16.5"},
{"houdini_17": "Houdini 17"},
{"houdini_18": "Houdini 18"},
{"photoshop_2020": "Photoshop 2020"},
{"python_3": "Python 3"},
{"python_2": "Python 2"},
{"premiere_2019": "Premiere Pro 2019"},
{"premiere_2020": "Premiere Pro 2020"},
{"resolve_16": "BM DaVinci Resolve 16"}
]
}
}, {
"label": "Avalon auto-sync",
"key": "avalon_auto_sync",
"type": "boolean",
"entity_type": "show",
"group": "avalon",
"write_security_role": ["API", "Administrator"],
"read_security_role": ["API", "Administrator"]
}, {
"label": "Intent",
"key": "intent",
"type": "enumerator",
"entity_type": "assetversion",
"group": "avalon",
"config": {
"multiselect": false,
"data": [
{"test": "Test"},
{"wip": "WIP"},
{"final": "Final"}
]
}
}, {
"label": "Library Project",
"key": "library_project",
"type": "boolean",
"entity_type": "show",
"group": "avalon",
"write_security_role": ["API", "Administrator"],
"read_security_role": ["API", "Administrator"]
}, {
"label": "Clip in",
"key": "clipIn",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"default": null
}, {
"label": "Clip out",
"key": "clipOut",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"default": null
}, {
"label": "Frame start",
"key": "frameStart",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"default": null
}, {
"label": "Frame end",
"key": "frameEnd",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"default": null
}, {
"label": "Tools",
"key": "tools_env",
"type": "enumerator",
"is_hierarchical": true,
"group": "avalon",
"config": {
"multiselect": true,
"data": [
{"mtoa_3.0.1": "mtoa_3.0.1"},
{"mtoa_3.1.1": "mtoa_3.1.1"},
{"mtoa_3.2.0": "mtoa_3.2.0"},
{"yeti_2.1.2": "yeti_2.1"}
]
}
}, {
"label": "Resolution Width",
"key": "resolutionWidth",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"default": null
}, {
"label": "Resolution Height",
"key": "resolutionHeight",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"default": null
}, {
"label": "Pixel aspect",
"key": "pixelAspect",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"config": {
"isdecimal": true
}
}, {
"label": "Frame handles start",
"key": "handleStart",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"default": null
}, {
"label": "Frame handles end",
"key": "handleEnd",
"type": "number",
"is_hierarchical": true,
"group": "avalon",
"default": null
}
]

View file

@ -0,0 +1,5 @@
{
"server_url": "",
"api_key": "",
"api_user": ""
}

View file

@ -0,0 +1,5 @@
{
"TestAction": {
"ignore_me": true
}
}

View file

@ -0,0 +1,18 @@
{
"fps": 25,
"frameStart": 1001,
"frameEnd": 1100,
"clipIn": 1001,
"clipOut": 1100,
"handleStart": 10,
"handleEnd": 10,
"resolutionHeight": 1080,
"resolutionWidth": 1920,
"pixelAspect": 1.0,
"applications": [
"maya_2019", "nuke_11.3", "nukex_11.3", "nukestudio_11.3", "deadline"
],
"tools_env": [],
"avalon_auto_sync": true
}

View file

@ -0,0 +1,8 @@
{
"Model": ["model"],
"Render Globals": ["light", "render"],
"Layout": ["layout"],
"Set Dress": ["setdress"],
"Look": ["look"],
"Rig": ["rigging"]
}

View file

@ -0,0 +1,22 @@
{
"__project_root__": {
"prod" : {},
"resources" : {
"footage": {
"plates": {},
"offline": {}
},
"audio": {},
"art_dept": {}
},
"editorial" : {},
"assets[ftrack.Library]": {
"characters[ftrack]": {},
"locations[ftrack]": {}
},
"shots[ftrack.Sequence]": {
"scripts": {},
"editorial[ftrack.Folder]": {}
}
}
}

View file

@ -0,0 +1,8 @@
{
"compositing": ["nuke", "ae"],
"modeling": ["maya", "app2"],
"lookdev": ["substance"],
"animation": [],
"lighting": [],
"rigging": []
}

View file

@ -0,0 +1,7 @@
{
"last_workfile_on_startup": [
{
"enabled": false
}
]
}

View file

@ -0,0 +1,108 @@
{
"Codec": {
"compression": "jpg",
"format": "image",
"quality": 95
},
"Display Options": {
"background": [
0.7137254901960784,
0.7137254901960784,
0.7137254901960784
],
"backgroundBottom": [
0.7137254901960784,
0.7137254901960784,
0.7137254901960784
],
"backgroundTop": [
0.7137254901960784,
0.7137254901960784,
0.7137254901960784
],
"override_display": true
},
"Generic": {
"isolate_view": true,
"off_screen": true
},
"IO": {
"name": "",
"open_finished": false,
"raw_frame_numbers": false,
"recent_playblasts": [],
"save_file": false
},
"PanZoom": {
"pan_zoom": true
},
"Renderer": {
"rendererName": "vp2Renderer"
},
"Resolution": {
"height": 1080,
"mode": "Custom",
"percent": 1.0,
"width": 1920
},
"Time Range": {
"end_frame": 25,
"frame": "",
"start_frame": 0,
"time": "Time Slider"
},
"Viewport Options": {
"cameras": false,
"clipGhosts": false,
"controlVertices": false,
"deformers": false,
"dimensions": false,
"displayLights": 0,
"dynamicConstraints": false,
"dynamics": false,
"fluids": false,
"follicles": false,
"gpuCacheDisplayFilter": false,
"greasePencils": false,
"grid": false,
"hairSystems": false,
"handles": false,
"high_quality": true,
"hud": false,
"hulls": false,
"ikHandles": false,
"imagePlane": false,
"joints": false,
"lights": false,
"locators": false,
"manipulators": false,
"motionTrails": false,
"nCloths": false,
"nParticles": false,
"nRigids": false,
"nurbsCurves": false,
"nurbsSurfaces": false,
"override_viewport_options": true,
"particleInstancers": false,
"pivots": false,
"planes": false,
"pluginShapes": false,
"polymeshes": true,
"shadows": false,
"strokes": false,
"subdivSurfaces": false,
"textures": false,
"twoSidedLighting": true
},
"Camera Options": {
"displayGateMask": false,
"displayResolution": false,
"displayFilmGate": false,
"displayFieldChart": false,
"displaySafeAction": false,
"displaySafeTitle": false,
"displayFilmPivot": false,
"displayFilmOrigin": false,
"overscan": 1.0
}
}

View file

@ -0,0 +1,19 @@
{
"3delight": 41,
"arnold": 46,
"arnold_sf": 57,
"gelato": 30,
"harware": 3,
"krakatoa": 51,
"file_layers": 7,
"mentalray": 2,
"mentalray_sf": 6,
"redshift": 55,
"renderman": 29,
"software": 1,
"software_sf": 5,
"turtle": 10,
"vector": 4,
"vray": 37,
"ffmpeg": 48
}

View file

@ -0,0 +1,11 @@
{
"ExtractCelactionDeadline": {
"enabled": true,
"deadline_department": "",
"deadline_priority": 50,
"deadline_pool": "",
"deadline_pool_secondary": "",
"deadline_group": "",
"deadline_chunk_size": 10
}
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,7 @@
{
"IntegrateFtrackNote": {
"enabled": false,
"note_with_intent_template": "{intent}: {comment}",
"note_labels": []
}
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,98 @@
{
"IntegrateMasterVersion": {
"enabled": false
},
"ExtractJpegEXR": {
"enabled": true,
"ffmpeg_args": {
"input": [
"-gamma 2.2"
],
"output": []
}
},
"ExtractReview": {
"enabled": true,
"profiles": [
{
"families": [],
"hosts": [],
"outputs": {
"h264": {
"filter": {
"families": [
"render",
"review",
"ftrack"
]
},
"ext": "mp4",
"ffmpeg_args": {
"input": [
"-gamma 2.2"
],
"video_filters": [],
"audio_filters": [],
"output": [
"-pix_fmt yuv420p",
"-crf 18",
"-intra"
]
},
"tags": [
"burnin",
"ftrackreview"
]
}
}
}
]
},
"ExtractBurnin": {
"enabled": false,
"options": {
"font_size": 42,
"opacity": 1,
"bg_opacity": 0,
"x_offset": 5,
"y_offset": 5,
"bg_padding": 5
},
"fields": {},
"profiles": [
{
"burnins": {
"burnin": {
"TOP_LEFT": "{yy}-{mm}-{dd}",
"TOP_RIGHT": "{anatomy[version]}",
"TOP_CENTERED": "",
"BOTTOM_RIGHT": "{frame_start}-{current_frame}-{frame_end}",
"BOTTOM_CENTERED": "{asset}",
"BOTTOM_LEFT": "{username}"
}
}
}
]
},
"IntegrateAssetNew": {
"template_name_profiles": {
"publish": {
"families": [],
"tasks": []
},
"render": {
"families": [
"review",
"render",
"prerender"
]
}
}
},
"ProcessSubmittedJobOnFarm": {
"enabled": false,
"deadline_department": "",
"deadline_pool": "",
"deadline_group": ""
}
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,9 @@
{
"Preset n1": {
"ValidateNoAnimation": false,
"ValidateShapeDefaultNames": false
},
"Preset n2": {
"ValidateNoAnimation": false
}
}

View file

@ -0,0 +1,18 @@
{
"colors": {
"model": [0.821, 0.518, 0.117],
"rig": [0.144, 0.443, 0.463],
"pointcache": [0.368, 0.821, 0.117],
"animation": [0.368, 0.821, 0.117],
"ass": [1.0, 0.332, 0.312],
"camera": [0.447, 0.312, 1.0],
"fbx": [1.0, 0.931, 0.312],
"mayaAscii": [0.312, 1.0, 0.747],
"setdress": [0.312, 1.0, 0.747],
"layout": [0.312, 1.0, 0.747],
"vdbcache": [0.312, 1.0, 0.428],
"vrayproxy": [0.258, 0.95, 0.541],
"yeticache": [0.2, 0.8, 0.3],
"yetiRig": [0, 0.8, 0.5]
}
}

View file

@ -0,0 +1,17 @@
{
"ValidateModelName": {
"enabled": false,
"material_file": "/path/to/shader_name_definition.txt",
"regex": "(.*)_(\\d)*_(?P<shader>.*)_(GEO)"
},
"ValidateAssemblyName": {
"enabled": false
},
"ValidateShaderName": {
"enabled": false,
"regex": "(?P<asset>.*)_(.*)_SHD"
},
"ValidateMeshHasOverlappingUVs": {
"enabled": false
}
}

View file

@ -0,0 +1,136 @@
[
{
"tasks": [
"lighting"
],
"current_context": [
{
"subset_name_filters": [
".+[Mm]ain"
],
"families": [
"model"
],
"repre_names": [
"abc",
"ma"
],
"loaders": [
"ReferenceLoader"
]
},
{
"families": [
"animation",
"pointcache"
],
"repre_names": [
"abc"
],
"loaders": [
"ReferenceLoader"
]
},
{
"families": [
"rendersetup"
],
"repre_names": [
"json"
],
"loaders": [
"RenderSetupLoader"
]
},
{
"families": [
"camera"
],
"repre_names": [
"abc"
],
"loaders": [
"ReferenceLoader"
]
}
],
"linked_assets": [
{
"families": [
"setdress"
],
"repre_names": [
"ma"
],
"loaders": [
"ReferenceLoader"
]
},
{
"families": [
"ass"
],
"repre_names": [
"ass"
],
"loaders": [
"assLoader"
]
}
]
},
{
"tasks": [
"animation"
],
"current_context": [
{
"families": [
"camera"
],
"repre_names": [
"abc",
"ma"
],
"loaders": [
"ReferenceLoader"
]
},
{
"families": [
"audio"
],
"repre_names": [
"wav"
],
"loaders": [
"RenderSetupLoader"
]
}
],
"linked_assets": [
{
"families": [
"setdress"
],
"repre_names": [
"proxy"
],
"loaders": [
"ReferenceLoader"
]
},
{
"families": [
"rig"
],
"repre_names": [
"ass"
],
"loaders": [
"rigLoader"
]
}
]
}
]

View file

@ -0,0 +1,8 @@
{
"CreateWriteRender": {
"fpath_template": "{work}/renders/nuke/{subset}/{subset}.{frame}.{ext}"
},
"CreateWritePrerender": {
"fpath_template": "{work}/prerenders/nuke/{subset}/{subset}.{frame}.{ext}"
}
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,53 @@
{
"ExtractThumbnail": {
"enabled": true,
"nodes": {
"Reformat": [
[
"type",
"to format"
],
[
"format",
"HD_1080"
],
[
"filter",
"Lanczos6"
],
[
"black_outside",
true
],
[
"pbb",
false
]
]
}
},
"ValidateNukeWriteKnobs": {
"enabled": false,
"knobs": {
"render": {
"review": true
}
}
},
"ExtractReviewDataLut": {
"enabled": false
},
"ExtractReviewDataMov": {
"enabled": true,
"viewer_lut_raw": false
},
"ExtractSlateFrame": {
"viewer_lut_raw": false
},
"NukeSubmitDeadline": {
"deadline_priority": 50,
"deadline_pool": "",
"deadline_pool_secondary": "",
"deadline_chunk_size": 1
}
}

View file

@ -0,0 +1,23 @@
[
{
"tasks": [
"compositing"
],
"current_context": [
{
"families": [
"render",
"plate"
],
"repre_names": [
"exr",
"dpx"
],
"loaders": [
"LoadSequence"
]
}
],
"linked_assets": []
}
]

View file

@ -0,0 +1,10 @@
{
"strict": {
"ValidateVersion": true,
"VersionUpWorkfile": true
},
"benevolent": {
"ValidateVersion": false,
"VersionUpWorkfile": false
}
}

View file

@ -0,0 +1,9 @@
{
"CollectInstanceVersion": {
"enabled": false
},
"ExtractReviewCutUpVideo": {
"enabled": true,
"tags_addition": []
}
}

View file

@ -0,0 +1,7 @@
{
"CreateShotClip": {
"clipName": "{track}{sequence}{shot}",
"folder": "takes",
"steps": 20
}
}

View file

@ -0,0 +1,27 @@
{
"ExtractThumbnailSP": {
"ffmpeg_args": {
"input": [
"-gamma 2.2"
],
"output": []
}
},
"ExtractReviewSP": {
"outputs": {
"h264": {
"input": [
"-gamma 2.2"
],
"output": [
"-pix_fmt yuv420p",
"-crf 18"
],
"tags": [
"preview"
],
"ext": "mov"
}
}
}
}

View file

@ -0,0 +1,8 @@
{
"MyTestCreator": {
"my_test_property": "B",
"active": false,
"new_property": "new",
"family": "new_family"
}
}

View file

@ -0,0 +1,10 @@
{
"MyTestPlugin": {
"label": "loaded from preset",
"optional": true,
"families": ["changed", "by", "preset"]
},
"MyTestRemovedPlugin": {
"enabled": false
}
}

View file

@ -0,0 +1,5 @@
{
"frameStart": 1001,
"handleStart": 0,
"handleEnd": 0
}

View file

@ -0,0 +1,21 @@
{
"defaultTasks": ["Layout", "Animation"],
"taskToSubsets": {
"Layout": ["reference", "audio"],
"Animation": ["audio"]
},
"subsetToRepresentations": {
"reference": {
"preset": "h264",
"representation": "mp4"
},
"thumbnail": {
"preset": "jpeg_thumb",
"representation": "jpg"
},
"audio": {
"preset": "48khz",
"representation": "wav"
}
}
}

View file

@ -0,0 +1,90 @@
{
"create_look": {
"name": "look",
"label": "Look",
"family": "look",
"icon": "paint-brush",
"defaults": ["Main"],
"help": "Shader connections defining shape look"
},
"create_model": {
"name": "model",
"label": "Model",
"family": "model",
"icon": "cube",
"defaults": ["Main", "Proxy", "Sculpt"],
"help": "Polygonal static geometry"
},
"create_workfile": {
"name": "workfile",
"label": "Workfile",
"family": "workfile",
"icon": "cube",
"defaults": ["Main"],
"help": "Working scene backup"
},
"create_camera": {
"name": "camera",
"label": "Camera",
"family": "camera",
"icon": "video-camera",
"defaults": ["Main"],
"help": "Single baked camera"
},
"create_pointcache": {
"name": "pointcache",
"label": "Pointcache",
"family": "pointcache",
"icon": "gears",
"defaults": ["Main"],
"help": "Alembic pointcache for animated data"
},
"create_rig": {
"name": "rig",
"label": "Rig",
"family": "rig",
"icon": "wheelchair",
"defaults": ["Main"],
"help": "Artist-friendly rig with controls"
},
"create_layout": {
"name": "layout",
"label": "Layout",
"family": "layout",
"icon": "cubes",
"defaults": ["Main"],
"help": "Simple scene for animators with camera"
},
"create_plate": {
"name": "plate",
"label": "Plate",
"family": "plate",
"icon": "camera",
"defaults": ["Main", "BG", "Reference"],
"help": "Plates for compositors"
},
"create_matchmove": {
"name": "matchmove",
"label": "Matchmove script",
"family": "matchmove",
"icon": "empire",
"defaults": ["Camera", "Object", "Mocap"],
"help": "Script exported from matchmoving application"
},
"create_images": {
"name": "image",
"label": "Image file",
"family": "image",
"icon": "image",
"defaults": ["ConceptArt", "Reference", "Texture", "MattePaint"],
"help": "Holder for all kinds of image data"
},
"create_editorial": {
"name": "editorial",
"label": "Editorial",
"family": "editorial",
"icon": "image",
"defaults": ["Main"],
"help": "Editorial files to generate shots."
}
}

View file

@ -0,0 +1,212 @@
{
"width": 1920,
"height": 1080,
"destination_path": "{destination_path}",
"style": {
"*": {
"font-family": "arial",
"font-color": "#ffffff",
"font-bold": false,
"font-italic": false,
"bg-color": "#0077ff",
"alignment-horizontal": "left",
"alignment-vertical": "top"
},
"layer": {
"padding": 0,
"margin": 0
},
"rectangle": {
"padding": 0,
"margin": 0,
"bg-color": "#E9324B",
"fill": true
},
"main_frame": {
"padding": 0,
"margin": 0,
"bg-color": "#252525"
},
"table": {
"padding": 0,
"margin": 0,
"bg-color": "transparent"
},
"table-item": {
"padding": 5,
"padding-bottom": 10,
"margin": 0,
"bg-color": "#212121",
"bg-alter-color": "#272727",
"font-color": "#dcdcdc",
"font-bold": false,
"font-italic": false,
"alignment-horizontal": "left",
"alignment-vertical": "top",
"word-wrap": false,
"ellide": true,
"max-lines": 1
},
"table-item-col[0]": {
"font-size": 20,
"font-color": "#898989",
"font-bold": true,
"ellide": false,
"word-wrap": true,
"max-lines": null
},
"table-item-col[1]": {
"font-size": 40,
"padding-left": 10
},
"#colorbar": {
"bg-color": "#9932CC"
}
},
"items": [{
"type": "layer",
"direction": 1,
"name": "MainLayer",
"style": {
"#MainLayer": {
"width": 1094,
"height": 1000,
"margin": 25,
"padding": 0
},
"#LeftSide": {
"margin-right": 25
}
},
"items": [{
"type": "layer",
"name": "LeftSide",
"items": [{
"type": "layer",
"direction": 1,
"style": {
"table-item": {
"bg-color": "transparent",
"padding-bottom": 20
},
"table-item-col[0]": {
"font-size": 20,
"font-color": "#898989",
"alignment-horizontal": "right"
},
"table-item-col[1]": {
"alignment-horizontal": "left",
"font-bold": true,
"font-size": 40
}
},
"items": [{
"type": "table",
"values": [
["Show:", "{project[name]}"]
],
"style": {
"table-item-field[0:0]": {
"width": 150
},
"table-item-field[0:1]": {
"width": 580
}
}
}, {
"type": "table",
"values": [
["Submitting For:", "{intent}"]
],
"style": {
"table-item-field[0:0]": {
"width": 160
},
"table-item-field[0:1]": {
"width": 218,
"alignment-horizontal": "right"
}
}
}]
}, {
"type": "rectangle",
"style": {
"bg-color": "#bc1015",
"width": 1108,
"height": 5,
"fill": true
}
}, {
"type": "table",
"use_alternate_color": true,
"values": [
["Version name:", "{version_name}"],
["Date:", "{date}"],
["Shot Types:", "{shot_type}"],
["Submission Note:", "{submission_note}"]
],
"style": {
"table-item": {
"padding-bottom": 20
},
"table-item-field[0:1]": {
"font-bold": true
},
"table-item-field[3:0]": {
"word-wrap": true,
"ellide": true,
"max-lines": 4
},
"table-item-col[0]": {
"alignment-horizontal": "right",
"width": 150
},
"table-item-col[1]": {
"alignment-horizontal": "left",
"width": 958
}
}
}]
}, {
"type": "layer",
"name": "RightSide",
"items": [{
"type": "placeholder",
"name": "thumbnail",
"path": "{thumbnail_path}",
"style": {
"width": 730,
"height": 412
}
}, {
"type": "placeholder",
"name": "colorbar",
"path": "{color_bar_path}",
"return_data": true,
"style": {
"width": 730,
"height": 55
}
}, {
"type": "table",
"use_alternate_color": true,
"values": [
["Vendor:", "{vendor}"],
["Shot Name:", "{shot_name}"],
["Frames:", "{frame_start} - {frame_end} ({duration})"]
],
"style": {
"table-item-col[0]": {
"alignment-horizontal": "left",
"width": 200
},
"table-item-col[1]": {
"alignment-horizontal": "right",
"width": 530,
"font-size": 30
}
}
}]
}]
}]
}

View file

@ -0,0 +1,4 @@
{
"dev_mode": false,
"install_unreal_python_engine": false
}

View file

@ -0,0 +1,16 @@
{
"AVALON_CONFIG": "pype",
"AVALON_PROJECTS": "{PYPE_PROJECTS_PATH}",
"AVALON_USERNAME": "avalon",
"AVALON_PASSWORD": "secret",
"AVALON_DEBUG": "1",
"AVALON_MONGO": "mongodb://localhost:2707",
"AVALON_DB": "avalon",
"AVALON_DB_DATA": "{PYPE_SETUP_PATH}/../mongo_db_data",
"AVALON_EARLY_ADOPTER": "1",
"AVALON_SCHEMA": "{PYPE_MODULE_ROOT}/schema",
"AVALON_LOCATION": "http://127.0.0.1",
"AVALON_LABEL": "Pype",
"AVALON_TIMEOUT": "1000",
"AVALON_THUMBNAIL_ROOT": ""
}

View file

@ -0,0 +1,7 @@
{
"BLENDER_USER_SCRIPTS": "{PYPE_SETUP_PATH}/repos/avalon-core/setup/blender",
"PYTHONPATH": [
"{PYPE_SETUP_PATH}/repos/avalon-core/setup/blender",
"{PYTHONPATH}"
]
}

View file

@ -0,0 +1,3 @@
{
"CELACTION_TEMPLATE": "{PYPE_MODULE_ROOT}/pype/hosts/celaction/celaction_template_scene.scn"
}

View file

@ -0,0 +1,3 @@
{
"DEADLINE_REST_URL": "http://localhost:8082"
}

View file

@ -0,0 +1,18 @@
{
"FTRACK_SERVER": "https://pype.ftrackapp.com",
"FTRACK_ACTIONS_PATH": [
"{PYPE_MODULE_ROOT}/pype/modules/ftrack/actions"
],
"FTRACK_EVENTS_PATH": [
"{PYPE_MODULE_ROOT}/pype/modules/ftrack/events"
],
"PYTHONPATH": [
"{PYPE_MODULE_ROOT}/pype/vendor",
"{PYTHONPATH}"
],
"PYBLISHPLUGINPATH": [
"{PYPE_MODULE_ROOT}/pype/plugins/ftrack/publish"
],
"FTRACK_EVENTS_MONGO_DB": "pype",
"FTRACK_EVENTS_MONGO_COL": "ftrack_events"
}

View file

@ -0,0 +1,44 @@
{
"PYPE_STUDIO_NAME": "Studio Name",
"PYPE_STUDIO_CODE": "stu",
"PYPE_APP_ROOT": "{PYPE_SETUP_PATH}/pypeapp",
"PYPE_MODULE_ROOT": "{PYPE_SETUP_PATH}/repos/pype",
"PYPE_PROJECT_PLUGINS": "",
"STUDIO_SOFT": "{PYP_SETUP_ROOT}/soft",
"FFMPEG_PATH": {
"windows": "{VIRTUAL_ENV}/localized/ffmpeg_exec/windows/bin;{PYPE_SETUP_PATH}/vendor/ffmpeg_exec/windows/bin",
"darwin": "{VIRTUAL_ENV}/localized/ffmpeg_exec/darwin/bin:{PYPE_SETUP_PATH}/vendor/ffmpeg_exec/darwin/bin",
"linux": "{VIRTUAL_ENV}/localized/ffmpeg_exec/linux:{PYPE_SETUP_PATH}/vendor/ffmpeg_exec/linux"
},
"DJV_PATH": {
"windows": [
"C:/Program Files/djv-1.1.0-Windows-64/bin/djv_view.exe",
"C:/Program Files/DJV/bin/djv_view.exe",
"{STUDIO_SOFT}/djv/windows/bin/djv_view.exe"
],
"linux": [
"usr/local/djv/djv_view",
"{STUDIO_SOFT}/djv/linux/bin/djv_view"
],
"darwin": "Application/DJV.app/Contents/MacOS/DJV"
},
"PATH": [
"{PYPE_CONFIG}/launchers",
"{PYPE_APP_ROOT}",
"{FFMPEG_PATH}",
"{PATH}"
],
"PYPE_OCIO_CONFIG": "{STUDIO_SOFT}/OpenColorIO-Configs",
"PYTHONPATH": {
"windows": "{VIRTUAL_ENV}/Lib/site-packages;{PYPE_MODULE_ROOT}/pype/tools;{PYTHONPATH}",
"linux": "{VIRTUAL_ENV}/lib/python{PYTHON_VERSION}/site-packages:{PYPE_MODULE_ROOT}/pype/tools:{PYTHONPATH}",
"darwin": "{VIRTUAL_ENV}/lib/python{PYTHON_VERSION}/site-packages:{PYPE_MODULE_ROOT}/pype/tools:{PYTHONPATH}"
},
"PYPE_PROJECT_CONFIGS": "{PYPE_SETUP_PATH}/../studio-project-configs",
"PYPE_PYTHON_EXE": {
"windows": "{VIRTUAL_ENV}/Scripts/python.exe",
"linux": "{VIRTUAL_ENV}/Scripts/python",
"darwin": "{VIRTUAL_ENV}/bin/python"
},
"PYBLISH_GUI": "pyblish_pype"
}

View file

@ -0,0 +1,4 @@
{
"AVALON_HARMONY_WORKFILES_ON_LAUNCH": "1",
"PYBLISH_GUI_ALWAYS_EXEC": "1"
}

View file

@ -0,0 +1,12 @@
{
"HOUDINI_PATH": {
"darwin": "{PYPE_MODULE_ROOT}/setup/houdini:&",
"linux": "{PYPE_MODULE_ROOT}/setup/houdini:&",
"windows": "{PYPE_MODULE_ROOT}/setup/houdini;&"
},
"HOUDINI_MENU_PATH": {
"darwin": "{PYPE_MODULE_ROOT}/setup/houdini:&",
"linux": "{PYPE_MODULE_ROOT}/setup/houdini:&",
"windows": "{PYPE_MODULE_ROOT}/setup/houdini;&"
}
}

View file

@ -0,0 +1,14 @@
{
"PYTHONPATH": [
"{PYPE_SETUP_PATH}/repos/avalon-core/setup/maya",
"{PYPE_SETUP_PATH}/repos/maya-look-assigner",
"{PYTHON_ENV}/python2/Lib/site-packages",
"{PYTHONPATH}"
],
"MAYA_DISABLE_CLIC_IPM": "Yes",
"MAYA_DISABLE_CIP": "Yes",
"MAYA_DISABLE_CER": "Yes",
"PYMEL_SKIP_MEL_INIT": "Yes",
"LC_ALL": "C",
"PYPE_LOG_NO_COLORS": "Yes"
}

View file

@ -0,0 +1,11 @@
{
"MAYA_VERSION": "2018",
"MAYA_LOCATION": {
"darwin": "/Applications/Autodesk/maya{MAYA_VERSION}/Maya.app/Contents",
"linux": "/usr/autodesk/maya{MAYA_VERSION}",
"windows": "C:/Program Files/Autodesk/Maya{MAYA_VERSION}"
},
"DYLD_LIBRARY_PATH": {
"darwin": "{MAYA_LOCATION}/MacOS"
}
}

View file

@ -0,0 +1,11 @@
{
"MAYA_VERSION": "2020",
"MAYA_LOCATION": {
"darwin": "/Applications/Autodesk/maya{MAYA_VERSION}/Maya.app/Contents",
"linux": "/usr/autodesk/maya{MAYA_VERSION}",
"windows": "C:/Program Files/Autodesk/Maya{MAYA_VERSION}"
},
"DYLD_LIBRARY_PATH": {
"darwin": "{MAYA_LOCATION}/MacOS"
}
}

View file

@ -0,0 +1,14 @@
{
"PYTHONPATH": [
"{PYPE_SETUP_PATH}/repos/avalon-core/setup/maya",
"{PYPE_SETUP_PATH}/repos/maya-look-assigner",
"{PYTHON_ENV}/python2/Lib/site-packages",
"{PYTHONPATH}"
],
"MAYA_DISABLE_CLIC_IPM": "Yes",
"MAYA_DISABLE_CIP": "Yes",
"MAYA_DISABLE_CER": "Yes",
"PYMEL_SKIP_MEL_INIT": "Yes",
"LC_ALL": "C",
"PYPE_LOG_NO_COLORS": "Yes"
}

View file

@ -0,0 +1,11 @@
{
"MAYA_VERSION": "2019",
"MAYA_LOCATION": {
"darwin": "/Applications/Autodesk/maya{MAYA_VERSION}/Maya.app/Contents",
"linux": "/usr/autodesk/maya{MAYA_VERSION}",
"windows": "C:/Program Files/Autodesk/Maya{MAYA_VERSION}"
},
"DYLD_LIBRARY_PATH": {
"darwin": "{MAYA_LOCATION}/MacOS"
}
}

View file

@ -0,0 +1,23 @@
{
"MTOA": "{PYPE_STUDIO_SOFTWARE}/arnold/mtoa_{MAYA_VERSION}_{MTOA_VERSION}",
"MTOA_VERSION": "3.1.1",
"MAYA_RENDER_DESC_PATH": "{MTOA}",
"MAYA_MODULE_PATH": "{MTOA}",
"ARNOLD_PLUGIN_PATH": "{MTOA}/shaders",
"MTOA_EXTENSIONS_PATH": {
"darwin": "{MTOA}/extensions",
"linux": "{MTOA}/extensions",
"windows": "{MTOA}/extensions"
},
"MTOA_EXTENSIONS": {
"darwin": "{MTOA}/extensions",
"linux": "{MTOA}/extensions",
"windows": "{MTOA}/extensions"
},
"DYLD_LIBRARY_PATH": {
"darwin": "{MTOA}/bin"
},
"PATH": {
"windows": "{PATH};{MTOA}/bin"
}
}

View file

@ -0,0 +1,3 @@
{
"MUSTER_REST_URL": "http://127.0.0.1:9890"
}

View file

@ -0,0 +1,15 @@
{
"NUKE_PATH": [
"{PYPE_SETUP_PATH}/repos/avalon-core/setup/nuke/nuke_path",
"{PYPE_MODULE_ROOT}/setup/nuke/nuke_path",
"{PYPE_STUDIO_PLUGINS}/nuke"
],
"PATH": {
"windows": "C:/Program Files (x86)/QuickTime/QTSystem/;{PATH}"
},
"PYPE_LOG_NO_COLORS": "True",
"PYTHONPATH": {
"windows": "{VIRTUAL_ENV}/Lib/site-packages;{PYTHONPATH}",
"linux": "{VIRTUAL_ENV}/lib/python3.6/site-packages:{PYTHONPATH}"
}
}

View file

@ -0,0 +1,11 @@
{
"HIERO_PLUGIN_PATH": [
"{PYPE_MODULE_ROOT}/setup/nukestudio/hiero_plugin_path"
],
"PATH": {
"windows": "C:/Program Files (x86)/QuickTime/QTSystem/;{PATH}"
},
"WORKFILES_STARTUP": "0",
"TAG_ASSETBUILD_STARTUP": "0",
"PYPE_LOG_NO_COLORS": "True"
}

View file

@ -0,0 +1,4 @@
{
"PYPE_LOG_NO_COLORS": "Yes",
"QT_PREFERRED_BINDING": "PySide"
}

View file

@ -0,0 +1,10 @@
{
"NUKE_PATH": [
"{PYPE_SETUP_PATH}/repos/avalon-core/setup/nuke/nuke_path",
"{PYPE_MODULE_ROOT}/setup/nuke/nuke_path",
"{PYPE_STUDIO_PLUGINS}/nuke"
],
"PATH": {
"windows": "C:/Program Files (x86)/QuickTime/QTSystem/;{PATH}"
}
}

View file

@ -0,0 +1,4 @@
{
"PYPE_LOG_NO_COLORS": "Yes",
"QT_PREFERRED_BINDING": "PySide"
}

View file

@ -0,0 +1,4 @@
{
"AVALON_PHOTOSHOP_WORKFILES_ON_LAUNCH": "1",
"PYTHONPATH": "{PYTHONPATH}"
}

View file

@ -0,0 +1,11 @@
{
"EXTENSIONS_PATH": {
"windows": "{USERPROFILE}/AppData/Roaming/Adobe/CEP/extensions",
"darvin": "{USER}/Library/Application Support/Adobe/CEP/extensions"
},
"EXTENSIONS_CACHE_PATH": {
"windows": "{USERPROFILE}/AppData/Local/Temp/cep_cache",
"darvin": "{USER}/Library/Application Support/Adobe/CEP/cep_cache"
},
"installed_zxp": ""
}

View file

@ -0,0 +1,40 @@
{
"RESOLVE_UTILITY_SCRIPTS_SOURCE_DIR": [
"{STUDIO_SOFT}/davinci_resolve/scripts/python"
],
"RESOLVE_SCRIPT_API": {
"windows": "{PROGRAMDATA}/Blackmagic Design/DaVinci Resolve/Support/Developer/Scripting",
"darvin": "/Library/Application Support/Blackmagic Design/DaVinci Resolve/Developer/Scripting",
"linux": "/opt/resolve/Developer/Scripting"
},
"RESOLVE_SCRIPT_LIB": {
"windows": "C:/Program Files/Blackmagic Design/DaVinci Resolve/fusionscript.dll",
"darvin": "/Applications/DaVinci Resolve/DaVinci Resolve.app/Contents/Libraries/Fusion/fusionscript.so",
"linux": "/opt/resolve/libs/Fusion/fusionscript.so"
},
"RESOLVE_UTILITY_SCRIPTS_DIR": {
"windows": "{PROGRAMDATA}/Blackmagic Design/DaVinci Resolve/Fusion/Scripts/Comp",
"darvin": "/Library/Application Support/Blackmagic Design/DaVinci Resolve/Fusion/Scripts/Comp",
"linux": "/opt/resolve/Fusion/Scripts/Comp"
},
"PYTHON36_RESOLVE": {
"windows": "{LOCALAPPDATA}/Programs/Python/Python36",
"darvin": "~/Library/Python/3.6/bin",
"linux": "/opt/Python/3.6/bin"
},
"PYTHONPATH": [
"{PYTHON36_RESOLVE}/Lib/site-packages",
"{VIRTUAL_ENV}/Lib/site-packages",
"{PYTHONPATH}",
"{RESOLVE_SCRIPT_API}/Modules",
"{PYTHONPATH}"
],
"PATH": [
"{PYTHON36_RESOLVE}",
"{PYTHON36_RESOLVE}/Scripts",
"{PATH}"
],
"PRE_PYTHON_SCRIPT": "{PYPE_MODULE_ROOT}/pype/resolve/preload_console.py",
"PYPE_LOG_NO_COLORS": "True",
"RESOLVE_DEV": "True"
}

View file

@ -0,0 +1,4 @@
{
"AVALON_TOONBOOM_WORKFILES_ON_LAUNCH": "1",
"PYBLISH_LITE_ALWAYS_EXEC": "1"
}

View file

@ -0,0 +1,5 @@
{
"AVALON_UNREAL_PLUGIN": "{PYPE_SETUP_PATH}/repos/avalon-unreal-integration",
"PYPE_LOG_NO_COLORS": "True",
"QT_PREFERRED_BINDING": "PySide"
}

View file

@ -0,0 +1,15 @@
{
"VRAY_VERSION": "43001",
"VRAY_ROOT": "C:/vray/vray_{VRAY_VERSION}",
"MAYA_RENDER_DESC_PATH": "{VRAY_ROOT}/maya_root/bin/rendererDesc",
"VRAY_FOR_MAYA2019_MAIN": "{VRAY_ROOT}/maya_vray",
"VRAY_FOR_MAYA2019_PLUGINS": "{VRAY_ROOT}/maya_vray/vrayplugins",
"VRAY_PLUGINS": "{VRAY_ROOT}/maya_vray/vrayplugins",
"VRAY_OSL_PATH_MAYA2019": "{VRAY_ROOT}/vray/opensl",
"PATH": "{VRAY_ROOT}/maya_root/bin;{PATH}",
"MAYA_PLUG_IN_PATH": "{VRAY_ROOT}/maya_vray/plug-ins",
"MAYA_SCRIPT_PATH": "{VRAY_ROOT}/maya_vray/scripts",
"PYTHONPATH": "{VRAY_ROOT}/maya_vray/scripts;{PYTHONPATH}",
"XBMLANGPATH": "{VRAY_ROOT}/maya_vray/icons;{XBMLANGPATH}",
"VRAY_AUTH_CLIENT_FILE_PATH": "{VRAY_ROOT}"
}

View file

@ -0,0 +1,34 @@
{
"blender_2.80": true,
"blender_2.81": true,
"blender_2.82": true,
"blender_2.83": true,
"celaction_local": true,
"celaction_remote": true,
"harmony_17": true,
"maya_2017": true,
"maya_2018": true,
"maya_2019": true,
"maya_2020": true,
"nuke_10.0": true,
"nuke_11.2": true,
"nuke_11.3": true,
"nuke_12.0": true,
"nukex_10.0": true,
"nukex_11.2": true,
"nukex_11.3": true,
"nukex_12.0": true,
"nukestudio_10.0": true,
"nukestudio_11.2": true,
"nukestudio_11.3": true,
"nukestudio_12.0": true,
"houdini_16": true,
"houdini_16.5": false,
"houdini_17": true,
"houdini_18": true,
"premiere_2019": true,
"premiere_2020": true,
"resolve_16": true,
"storyboardpro_7": true,
"unreal_4.24": true
}

View file

@ -0,0 +1,8 @@
{
"items": {
"wip": "WIP",
"test": "TEST",
"final": "FINAL"
},
"default": "wip"
}

View file

@ -0,0 +1,6 @@
{
"mtoa_3.0.1": true,
"mtoa_3.1.1": true,
"mtoa_3.2.0": true,
"yeti_2.1.2": true
}

View file

@ -0,0 +1,28 @@
{
"item_usage": {
"User settings": false,
"Ftrack": true,
"Muster": false,
"Avalon": true,
"Clockify": false,
"Standalone Publish": true,
"Logging": true,
"Idle Manager": true,
"Timers Manager": true,
"Rest Api": true,
"Adobe Communicator": true
},
"attributes": {
"Rest Api": {
"default_port": 8021,
"exclude_ports": []
},
"Timers Manager": {
"full_time": 15.0,
"message_time": 0.5
},
"Clockify": {
"workspace_name": ""
}
}
}

Some files were not shown because too many files have changed in this diff Show more