Merge branch 'develop' into feature/OP-1915_flame-ftrack-direct-link
39
CHANGELOG.md
|
|
@ -1,6 +1,6 @@
|
|||
# Changelog
|
||||
|
||||
## [3.7.0-nightly.4](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
||||
## [3.7.0-nightly.5](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.6.4...HEAD)
|
||||
|
||||
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- Settings: Webpublisher in hosts enum [\#2367](https://github.com/pypeclub/OpenPype/pull/2367)
|
||||
- Burnins: Be able recognize mxf OPAtom format [\#2361](https://github.com/pypeclub/OpenPype/pull/2361)
|
||||
- Local settings: Copyable studio paths [\#2349](https://github.com/pypeclub/OpenPype/pull/2349)
|
||||
- Assets Widget: Clear model on project change [\#2345](https://github.com/pypeclub/OpenPype/pull/2345)
|
||||
- General: OpenPype default modules hierarchy [\#2338](https://github.com/pypeclub/OpenPype/pull/2338)
|
||||
- General: FFprobe error exception contain original error message [\#2328](https://github.com/pypeclub/OpenPype/pull/2328)
|
||||
|
|
@ -21,6 +24,7 @@
|
|||
- Hiero: Add experimental tools action [\#2323](https://github.com/pypeclub/OpenPype/pull/2323)
|
||||
- Input links: Cleanup and unification of differences [\#2322](https://github.com/pypeclub/OpenPype/pull/2322)
|
||||
- General: Don't validate vendor bin with executing them [\#2317](https://github.com/pypeclub/OpenPype/pull/2317)
|
||||
- General: Multilayer EXRs support [\#2315](https://github.com/pypeclub/OpenPype/pull/2315)
|
||||
- General: Run process log stderr as info log level [\#2309](https://github.com/pypeclub/OpenPype/pull/2309)
|
||||
- General: Reduce vendor imports [\#2305](https://github.com/pypeclub/OpenPype/pull/2305)
|
||||
- Tools: Cleanup of unused classes [\#2304](https://github.com/pypeclub/OpenPype/pull/2304)
|
||||
|
|
@ -28,16 +32,20 @@
|
|||
- Ftrack: Synchronize input links [\#2287](https://github.com/pypeclub/OpenPype/pull/2287)
|
||||
- StandalonePublisher: Remove unused plugin ExtractHarmonyZip [\#2277](https://github.com/pypeclub/OpenPype/pull/2277)
|
||||
- Ftrack: Support multiple reviews [\#2271](https://github.com/pypeclub/OpenPype/pull/2271)
|
||||
- Ftrack: Remove unused clean component plugin [\#2269](https://github.com/pypeclub/OpenPype/pull/2269)
|
||||
- Royal Render: Support for rr channels in separate dirs [\#2268](https://github.com/pypeclub/OpenPype/pull/2268)
|
||||
- Houdini: Add experimental tools action [\#2267](https://github.com/pypeclub/OpenPype/pull/2267)
|
||||
- Nuke: extract baked review videos presets [\#2248](https://github.com/pypeclub/OpenPype/pull/2248)
|
||||
- TVPaint: Workers rendering [\#2209](https://github.com/pypeclub/OpenPype/pull/2209)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
- Webpublisher: Fix assignment of families of TVpaint instances [\#2373](https://github.com/pypeclub/OpenPype/pull/2373)
|
||||
- JobQueue: Fix loading of settings [\#2362](https://github.com/pypeclub/OpenPype/pull/2362)
|
||||
- Tools: Placeholder color [\#2359](https://github.com/pypeclub/OpenPype/pull/2359)
|
||||
- Launcher: Minimize button on MacOs [\#2355](https://github.com/pypeclub/OpenPype/pull/2355)
|
||||
- StandalonePublisher: Fix import of constant [\#2354](https://github.com/pypeclub/OpenPype/pull/2354)
|
||||
- Adobe products show issue [\#2347](https://github.com/pypeclub/OpenPype/pull/2347)
|
||||
- Maya Look Assigner: Fix Python 3 compatibility [\#2343](https://github.com/pypeclub/OpenPype/pull/2343)
|
||||
- Remove wrongly used host for hook [\#2342](https://github.com/pypeclub/OpenPype/pull/2342)
|
||||
- Tools: Use Qt context on tools show [\#2340](https://github.com/pypeclub/OpenPype/pull/2340)
|
||||
- Flame: Fix default argument value in custom dictionary [\#2339](https://github.com/pypeclub/OpenPype/pull/2339)
|
||||
- Timers Manager: Disable auto stop timer on linux platform [\#2334](https://github.com/pypeclub/OpenPype/pull/2334)
|
||||
- nuke: bake preset single input exception [\#2331](https://github.com/pypeclub/OpenPype/pull/2331)
|
||||
- Hiero: fixing multiple templates at a hierarchy parent [\#2330](https://github.com/pypeclub/OpenPype/pull/2330)
|
||||
|
|
@ -52,11 +60,10 @@
|
|||
- Alternate site for site sync doesnt work for sequences [\#2284](https://github.com/pypeclub/OpenPype/pull/2284)
|
||||
- FFmpeg: Execute ffprobe using list of arguments instead of string command [\#2281](https://github.com/pypeclub/OpenPype/pull/2281)
|
||||
- Nuke: Anatomy fill data use task as dictionary [\#2278](https://github.com/pypeclub/OpenPype/pull/2278)
|
||||
- Bug: fix variable name \_asset\_id in workfiles application [\#2274](https://github.com/pypeclub/OpenPype/pull/2274)
|
||||
- Version handling fixes [\#2272](https://github.com/pypeclub/OpenPype/pull/2272)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Update of avalon-core [\#2346](https://github.com/pypeclub/OpenPype/pull/2346)
|
||||
- Maya: configurable model top level validation [\#2321](https://github.com/pypeclub/OpenPype/pull/2321)
|
||||
|
||||
## [3.6.4](https://github.com/pypeclub/OpenPype/tree/3.6.4) (2021-11-23)
|
||||
|
|
@ -81,13 +88,14 @@
|
|||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- Ftrack: Remove unused clean component plugin [\#2269](https://github.com/pypeclub/OpenPype/pull/2269)
|
||||
- Tools: Assets widget [\#2265](https://github.com/pypeclub/OpenPype/pull/2265)
|
||||
- SceneInventory: Choose loader in asset switcher [\#2262](https://github.com/pypeclub/OpenPype/pull/2262)
|
||||
- Style: New fonts in OpenPype style [\#2256](https://github.com/pypeclub/OpenPype/pull/2256)
|
||||
- Tools: SceneInventory in OpenPype [\#2255](https://github.com/pypeclub/OpenPype/pull/2255)
|
||||
- Tools: Tasks widget [\#2251](https://github.com/pypeclub/OpenPype/pull/2251)
|
||||
- Nuke: extract baked review videos presets [\#2248](https://github.com/pypeclub/OpenPype/pull/2248)
|
||||
- Tools: Creator in OpenPype [\#2244](https://github.com/pypeclub/OpenPype/pull/2244)
|
||||
- Added endpoint for configured extensions [\#2221](https://github.com/pypeclub/OpenPype/pull/2221)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
|
|
@ -111,24 +119,12 @@
|
|||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.6.0-nightly.6...3.6.0)
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Add alternative sites for Site Sync [\#2206](https://github.com/pypeclub/OpenPype/pull/2206)
|
||||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- Tools: Subset manager in OpenPype [\#2243](https://github.com/pypeclub/OpenPype/pull/2243)
|
||||
- General: Skip module directories without init file [\#2239](https://github.com/pypeclub/OpenPype/pull/2239)
|
||||
- General: Static interfaces [\#2238](https://github.com/pypeclub/OpenPype/pull/2238)
|
||||
- Style: Fix transparent image in style [\#2235](https://github.com/pypeclub/OpenPype/pull/2235)
|
||||
- Add a "following workfile versioning" option on publish [\#2225](https://github.com/pypeclub/OpenPype/pull/2225)
|
||||
- Modules: Module can add cli commands [\#2224](https://github.com/pypeclub/OpenPype/pull/2224)
|
||||
- Webpublisher: Separate webpublisher logic [\#2222](https://github.com/pypeclub/OpenPype/pull/2222)
|
||||
- Add both side availability on Site Sync sites to Loader [\#2220](https://github.com/pypeclub/OpenPype/pull/2220)
|
||||
- Tools: Center loader and library loader on show [\#2219](https://github.com/pypeclub/OpenPype/pull/2219)
|
||||
- Maya : Validate shape zero [\#2212](https://github.com/pypeclub/OpenPype/pull/2212)
|
||||
- Maya : validate unique names [\#2211](https://github.com/pypeclub/OpenPype/pull/2211)
|
||||
- Tools: OpenPype stylesheet in workfiles tool [\#2208](https://github.com/pypeclub/OpenPype/pull/2208)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
|
|
@ -138,9 +134,6 @@
|
|||
- Python 2: Unicode to string conversion [\#2236](https://github.com/pypeclub/OpenPype/pull/2236)
|
||||
- Fix - enum for color coding in PS [\#2234](https://github.com/pypeclub/OpenPype/pull/2234)
|
||||
- Pyblish Tool: Fix targets handling [\#2232](https://github.com/pypeclub/OpenPype/pull/2232)
|
||||
- Ftrack: Base event fix of 'get\_project\_from\_entity' method [\#2214](https://github.com/pypeclub/OpenPype/pull/2214)
|
||||
- Maya : multiple subsets review broken [\#2210](https://github.com/pypeclub/OpenPype/pull/2210)
|
||||
- Fix - different command used for Linux and Mac OS [\#2207](https://github.com/pypeclub/OpenPype/pull/2207)
|
||||
|
||||
## [3.5.0](https://github.com/pypeclub/OpenPype/tree/3.5.0) (2021-10-17)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ def add_implementation_envs(env, _app):
|
|||
# Add requirements to HIERO_PLUGIN_PATH
|
||||
pype_root = os.environ["OPENPYPE_REPOS_ROOT"]
|
||||
new_hiero_paths = [
|
||||
os.path.join(pype_root, "openpype", "hosts", "hiero", "startup")
|
||||
os.path.join(pype_root, "openpype", "hosts", "hiero", "api", "startup")
|
||||
]
|
||||
old_hiero_path = env.get("HIERO_PLUGIN_PATH") or ""
|
||||
for path in old_hiero_path.split(os.pathsep):
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ from .pipeline import (
|
|||
|
||||
from .lib import (
|
||||
pype_tag_name,
|
||||
flatten,
|
||||
get_track_items,
|
||||
get_current_project,
|
||||
get_current_sequence,
|
||||
|
|
@ -75,6 +76,7 @@ __all__ = [
|
|||
|
||||
# Lib functions
|
||||
"pype_tag_name",
|
||||
"flatten",
|
||||
"get_track_items",
|
||||
"get_current_project",
|
||||
"get_current_sequence",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Host specific functions where host api is connected
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
import platform
|
||||
import ast
|
||||
import shutil
|
||||
import hiero
|
||||
|
|
@ -12,7 +13,6 @@ import avalon.api as avalon
|
|||
import avalon.io
|
||||
from openpype.api import (Logger, Anatomy, get_anatomy_settings)
|
||||
from . import tags
|
||||
from compiler.ast import flatten
|
||||
|
||||
try:
|
||||
from PySide.QtCore import QFile, QTextStream
|
||||
|
|
@ -38,6 +38,14 @@ self.default_bin_name = "openpypeBin"
|
|||
AVALON_CONFIG = os.getenv("AVALON_CONFIG", "pype")
|
||||
|
||||
|
||||
def flatten(_list):
|
||||
for item in _list:
|
||||
if isinstance(item, (list, tuple)):
|
||||
for sub_item in flatten(item):
|
||||
yield sub_item
|
||||
else:
|
||||
yield item
|
||||
|
||||
def get_current_project(remove_untitled=False):
|
||||
projects = flatten(hiero.core.projects())
|
||||
if not remove_untitled:
|
||||
|
|
@ -250,7 +258,7 @@ def set_track_item_pype_tag(track_item, data=None):
|
|||
Returns:
|
||||
hiero.core.Tag
|
||||
"""
|
||||
data = data or dict()
|
||||
data = data or {}
|
||||
|
||||
# basic Tag's attribute
|
||||
tag_data = {
|
||||
|
|
@ -284,7 +292,7 @@ def get_track_item_pype_data(track_item):
|
|||
Returns:
|
||||
dict: data found on pype tag
|
||||
"""
|
||||
data = dict()
|
||||
data = {}
|
||||
# get pype data tag from track item
|
||||
tag = get_track_item_pype_tag(track_item)
|
||||
|
||||
|
|
@ -299,8 +307,20 @@ def get_track_item_pype_data(track_item):
|
|||
|
||||
try:
|
||||
# capture exceptions which are related to strings only
|
||||
value = ast.literal_eval(v)
|
||||
except (ValueError, SyntaxError):
|
||||
if re.match(r"^[\d]+$", v):
|
||||
value = int(v)
|
||||
elif re.match(r"^True$", v):
|
||||
value = True
|
||||
elif re.match(r"^False$", v):
|
||||
value = False
|
||||
elif re.match(r"^None$", v):
|
||||
value = None
|
||||
elif re.match(r"^[\w\d_]+$", v):
|
||||
value = v
|
||||
else:
|
||||
value = ast.literal_eval(v)
|
||||
except (ValueError, SyntaxError) as msg:
|
||||
log.warning(msg)
|
||||
value = v
|
||||
|
||||
data.update({key: value})
|
||||
|
|
@ -729,9 +749,14 @@ def get_selected_track_items(sequence=None):
|
|||
def set_selected_track_items(track_items_list, sequence=None):
|
||||
_sequence = sequence or get_current_sequence()
|
||||
|
||||
# make sure only trackItems are in list selection
|
||||
only_track_items = [
|
||||
i for i in track_items_list
|
||||
if isinstance(i, hiero.core.TrackItem)]
|
||||
|
||||
# Getting selection
|
||||
timeline_editor = hiero.ui.getTimelineEditor(_sequence)
|
||||
return timeline_editor.setSelection(track_items_list)
|
||||
return timeline_editor.setSelection(only_track_items)
|
||||
|
||||
|
||||
def _read_doc_from_path(path):
|
||||
|
|
@ -759,6 +784,13 @@ def _set_hrox_project_knobs(doc, **knobs):
|
|||
# set attributes to Project Tag
|
||||
proj_elem = doc.documentElement().firstChildElement("Project")
|
||||
for k, v in knobs.items():
|
||||
if "ocioconfigpath" in k:
|
||||
paths_to_format = v[platform.system().lower()]
|
||||
for _path in paths_to_format:
|
||||
v = _path.format(**os.environ)
|
||||
if not os.path.exists(v):
|
||||
continue
|
||||
log.debug("Project colorspace knob `{}` was set to `{}`".format(k, v))
|
||||
if isinstance(v, dict):
|
||||
continue
|
||||
proj_elem.setAttribute(str(k), v)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import os
|
|||
import re
|
||||
import sys
|
||||
import ast
|
||||
from compiler.ast import flatten
|
||||
import opentimelineio as otio
|
||||
from . import utils
|
||||
import hiero.core
|
||||
|
|
@ -29,6 +28,15 @@ self.timeline = None
|
|||
self.include_tags = True
|
||||
|
||||
|
||||
def flatten(_list):
|
||||
for item in _list:
|
||||
if isinstance(item, (list, tuple)):
|
||||
for sub_item in flatten(item):
|
||||
yield sub_item
|
||||
else:
|
||||
yield item
|
||||
|
||||
|
||||
def get_current_hiero_project(remove_untitled=False):
|
||||
projects = flatten(hiero.core.projects())
|
||||
if not remove_untitled:
|
||||
|
|
@ -74,13 +82,11 @@ def create_time_effects(otio_clip, track_item):
|
|||
otio_effect = otio.schema.LinearTimeWarp()
|
||||
otio_effect.name = "Speed"
|
||||
otio_effect.time_scalar = speed
|
||||
otio_effect.metadata = {}
|
||||
|
||||
# freeze frame effect
|
||||
if speed == 0.:
|
||||
otio_effect = otio.schema.FreezeFrame()
|
||||
otio_effect.name = "FreezeFrame"
|
||||
otio_effect.metadata = {}
|
||||
|
||||
if otio_effect:
|
||||
# add otio effect to clip effects
|
||||
|
|
@ -191,7 +191,7 @@ class CreatorWidget(QtWidgets.QDialog):
|
|||
|
||||
content_layout = content_layout or self.content_layout[-1]
|
||||
# fix order of process by defined order value
|
||||
ordered_keys = data.keys()
|
||||
ordered_keys = list(data.keys())
|
||||
for k, v in data.items():
|
||||
try:
|
||||
# try removing a key from index which should
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 8 KiB After Width: | Height: | Size: 8 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
|
@ -18,7 +18,7 @@ except:
|
|||
### Magic Widget Finding Methods - This stuff crawls all the PySide widgets, looking for an answer
|
||||
def findWidget(w):
|
||||
global foundryWidgets
|
||||
if 'Foundry' in w.metaObject().className():
|
||||
if "Foundry" in w.metaObject().className():
|
||||
foundryWidgets += [w]
|
||||
|
||||
for c in w.children():
|
||||
|
|
@ -49,7 +49,7 @@ def activeSpreadsheetTreeView():
|
|||
Does some PySide widget Magic to detect the Active Spreadsheet TreeView.
|
||||
"""
|
||||
spreadsheetViews = getFoundryWidgetsWithClassName(
|
||||
filter='SpreadsheetTreeView')
|
||||
filter="SpreadsheetTreeView")
|
||||
for spreadSheet in spreadsheetViews:
|
||||
if spreadSheet.hasFocus():
|
||||
activeSpreadSheet = spreadSheet
|
||||
|
|
@ -77,23 +77,23 @@ class SpreadsheetExportCSVAction(QAction):
|
|||
spreadsheetTreeView = activeSpreadsheetTreeView()
|
||||
|
||||
if not spreadsheetTreeView:
|
||||
return 'Unable to detect the active TreeView.'
|
||||
return "Unable to detect the active TreeView."
|
||||
seq = hiero.ui.activeView().sequence()
|
||||
if not seq:
|
||||
print 'Unable to detect the active Sequence from the activeView.'
|
||||
print("Unable to detect the active Sequence from the activeView.")
|
||||
return
|
||||
|
||||
# The data model of the QTreeView
|
||||
model = spreadsheetTreeView.model()
|
||||
|
||||
csvSavePath = os.path.join(QDir.homePath(), 'Desktop',
|
||||
seq.name() + '.csv')
|
||||
csvSavePath = os.path.join(QDir.homePath(), "Desktop",
|
||||
seq.name() + ".csv")
|
||||
savePath, filter = QFileDialog.getSaveFileName(
|
||||
None,
|
||||
caption="Export Spreadsheet to .CSV as...",
|
||||
dir=csvSavePath,
|
||||
filter="*.csv")
|
||||
print 'Saving To: ' + str(savePath)
|
||||
print("Saving To: {}".format(savePath))
|
||||
|
||||
# Saving was cancelled...
|
||||
if len(savePath) == 0:
|
||||
|
|
@ -101,12 +101,12 @@ class SpreadsheetExportCSVAction(QAction):
|
|||
|
||||
# Get the Visible Header Columns from the QTreeView
|
||||
|
||||
#csvHeader = ['Event', 'Status', 'Shot Name', 'Reel', 'Track', 'Speed', 'Src In', 'Src Out','Src Duration', 'Dst In', 'Dst Out', 'Dst Duration', 'Clip', 'Clip Media']
|
||||
#csvHeader = ["Event", "Status", "Shot Name", "Reel", "Track", "Speed", "Src In", "Src Out","Src Duration", "Dst In", "Dst Out", "Dst Duration", "Clip", "Clip Media"]
|
||||
|
||||
# Get a CSV writer object
|
||||
f = open(savePath, 'w')
|
||||
f = open(savePath, "w")
|
||||
csvWriter = csv.writer(
|
||||
f, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||
f, delimiter=',', quotechar="|", quoting=csv.QUOTE_MINIMAL)
|
||||
|
||||
# This is a list of the Column titles
|
||||
csvHeader = []
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__author__ = "Daniel Flehner Heen"
|
||||
|
|
@ -9,7 +8,7 @@ import hiero.core
|
|||
from hiero.core import util
|
||||
|
||||
import opentimelineio as otio
|
||||
from openpype.hosts.hiero.otio import hiero_export
|
||||
from openpype.hosts.hiero.api.otio import hiero_export
|
||||
|
||||
class OTIOExportTask(hiero.core.TaskBase):
|
||||
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__author__ = "Daniel Flehner Heen"
|
||||
__credits__ = ["Jakub Jezek", "Daniel Flehner Heen"]
|
||||
|
||||
import hiero.ui
|
||||
import OTIOExportTask
|
||||
from .OTIOExportTask import (
|
||||
OTIOExportTask,
|
||||
OTIOExportPreset
|
||||
)
|
||||
|
||||
try:
|
||||
# Hiero >= 11.x
|
||||
|
|
@ -20,14 +22,14 @@ except ImportError:
|
|||
|
||||
FormLayout = QFormLayout # lint:ok
|
||||
|
||||
from openpype.hosts.hiero.otio import hiero_export
|
||||
from openpype.hosts.hiero.api.otio import hiero_export
|
||||
|
||||
class OTIOExportUI(hiero.ui.TaskUIBase):
|
||||
def __init__(self, preset):
|
||||
"""Initialize"""
|
||||
hiero.ui.TaskUIBase.__init__(
|
||||
self,
|
||||
OTIOExportTask.OTIOExportTask,
|
||||
OTIOExportTask,
|
||||
preset,
|
||||
"OTIO Exporter"
|
||||
)
|
||||
|
|
@ -67,6 +69,6 @@ class OTIOExportUI(hiero.ui.TaskUIBase):
|
|||
|
||||
|
||||
hiero.ui.taskUIRegistry.registerTaskUI(
|
||||
OTIOExportTask.OTIOExportPreset,
|
||||
OTIOExportPreset,
|
||||
OTIOExportUI
|
||||
)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
from .OTIOExportTask import OTIOExportTask
|
||||
from .OTIOExportUI import OTIOExportUI
|
||||
|
||||
__all__ = [
|
||||
"OTIOExportTask",
|
||||
"OTIOExportUI"
|
||||
]
|
||||
|
|
@ -21,7 +21,7 @@ def __trackActiveProjectHandler(event):
|
|||
global gTrackedActiveProject
|
||||
selection = event.sender.selection()
|
||||
binSelection = selection
|
||||
if len(binSelection) > 0 and hasattr(binSelection[0], 'project'):
|
||||
if len(binSelection) > 0 and hasattr(binSelection[0], "project"):
|
||||
proj = binSelection[0].project()
|
||||
|
||||
# We only store this if its a valid, active User Project
|
||||
|
|
@ -30,18 +30,18 @@ def __trackActiveProjectHandler(event):
|
|||
|
||||
|
||||
hiero.core.events.registerInterest(
|
||||
'kSelectionChanged/kBin', __trackActiveProjectHandler)
|
||||
"kSelectionChanged/kBin", __trackActiveProjectHandler)
|
||||
hiero.core.events.registerInterest(
|
||||
'kSelectionChanged/kTimeline', __trackActiveProjectHandler)
|
||||
"kSelectionChanged/kTimeline", __trackActiveProjectHandler)
|
||||
hiero.core.events.registerInterest(
|
||||
'kSelectionChanged/Spreadsheet', __trackActiveProjectHandler)
|
||||
"kSelectionChanged/Spreadsheet", __trackActiveProjectHandler)
|
||||
|
||||
|
||||
def activeProject():
|
||||
"""hiero.ui.activeProject() -> returns the current Project
|
||||
|
||||
Note: There is not technically a notion of a 'active' Project in Hiero/NukeStudio, as it is a multi-project App.
|
||||
This method determines what is 'active' by going down the following rules...
|
||||
Note: There is not technically a notion of a "active" Project in Hiero/NukeStudio, as it is a multi-project App.
|
||||
This method determines what is "active" by going down the following rules...
|
||||
|
||||
# 1 - If the current Viewer (hiero.ui.currentViewer) contains a Clip or Sequence, this item is assumed to give the active Project
|
||||
# 2 - If nothing is currently in the Viewer, look to the active View, determine project from active selection
|
||||
|
|
@ -54,7 +54,7 @@ def activeProject():
|
|||
|
||||
# Case 1 : Look for what the current Viewr tells us - this might not be what we want, and relies on hiero.ui.currentViewer() being robust.
|
||||
cv = hiero.ui.currentViewer().player().sequence()
|
||||
if hasattr(cv, 'project'):
|
||||
if hasattr(cv, "project"):
|
||||
activeProject = cv.project()
|
||||
else:
|
||||
# Case 2: We can't determine a project from the current Viewer, so try seeing what's selected in the activeView
|
||||
|
|
@ -66,16 +66,16 @@ def activeProject():
|
|||
|
||||
# Handle the case where nothing is selected in the active view
|
||||
if len(selection) == 0:
|
||||
# It's possible that there is no selection in a Timeline/Spreadsheet, but these views have 'sequence' method, so try that...
|
||||
# It's possible that there is no selection in a Timeline/Spreadsheet, but these views have "sequence" method, so try that...
|
||||
if isinstance(hiero.ui.activeView(), (hiero.ui.TimelineEditor, hiero.ui.SpreadsheetView)):
|
||||
activeSequence = activeView.sequence()
|
||||
if hasattr(currentItem, 'project'):
|
||||
if hasattr(currentItem, "project"):
|
||||
activeProject = activeSequence.project()
|
||||
|
||||
# The active view has a selection... assume that the first item in the selection has the active Project
|
||||
else:
|
||||
currentItem = selection[0]
|
||||
if hasattr(currentItem, 'project'):
|
||||
if hasattr(currentItem, "project"):
|
||||
activeProject = currentItem.project()
|
||||
|
||||
# Finally, Cases 3 and 4...
|
||||
|
|
@ -156,9 +156,14 @@ class SaveAllProjects(QAction):
|
|||
for proj in allProjects:
|
||||
try:
|
||||
proj.save()
|
||||
print 'Saved Project: %s to: %s ' % (proj.name(), proj.path())
|
||||
print("Saved Project: {} to: {} ".format(
|
||||
proj.name(), proj.path()
|
||||
))
|
||||
except:
|
||||
print 'Unable to save Project: %s to: %s. Check file permissions.' % (proj.name(), proj.path())
|
||||
print((
|
||||
"Unable to save Project: {} to: {}. "
|
||||
"Check file permissions.").format(
|
||||
proj.name(), proj.path()))
|
||||
|
||||
def eventHandler(self, event):
|
||||
event.menu.addAction(self)
|
||||
|
|
@ -190,32 +195,38 @@ class SaveNewProjectVersion(QAction):
|
|||
v = None
|
||||
prefix = None
|
||||
try:
|
||||
(prefix, v) = version_get(path, 'v')
|
||||
except ValueError, msg:
|
||||
print msg
|
||||
(prefix, v) = version_get(path, "v")
|
||||
except ValueError as msg:
|
||||
print(msg)
|
||||
|
||||
if (prefix is not None) and (v is not None):
|
||||
v = int(v)
|
||||
newPath = version_set(path, prefix, v, v + 1)
|
||||
try:
|
||||
proj.saveAs(newPath)
|
||||
print 'Saved new project version: %s to: %s ' % (oldName, newPath)
|
||||
print("Saved new project version: {} to: {} ".format(
|
||||
oldName, newPath))
|
||||
except:
|
||||
print 'Unable to save Project: %s. Check file permissions.' % (oldName)
|
||||
print((
|
||||
"Unable to save Project: {}. Check file permissions."
|
||||
).format(oldName))
|
||||
else:
|
||||
newPath = path.replace(".hrox", "_v01.hrox")
|
||||
answer = nuke.ask(
|
||||
'%s does not contain a version number.\nDo you want to save as %s?' % (proj, newPath))
|
||||
"%s does not contain a version number.\nDo you want to save as %s?" % (proj, newPath))
|
||||
if answer:
|
||||
try:
|
||||
proj.saveAs(newPath)
|
||||
print 'Saved new project version: %s to: %s ' % (oldName, newPath)
|
||||
print("Saved new project version: {} to: {} ".format(
|
||||
oldName, newPath))
|
||||
except:
|
||||
print 'Unable to save Project: %s. Check file permissions.' % (oldName)
|
||||
print((
|
||||
"Unable to save Project: {}. Check file "
|
||||
"permissions.").format(oldName))
|
||||
|
||||
def eventHandler(self, event):
|
||||
self.selectedProjects = []
|
||||
if hasattr(event.sender, 'selection') and event.sender.selection() is not None and len(event.sender.selection()) != 0:
|
||||
if hasattr(event.sender, "selection") and event.sender.selection() is not None and len(event.sender.selection()) != 0:
|
||||
selection = event.sender.selection()
|
||||
self.selectedProjects = uniquify(
|
||||
[item.project() for item in selection])
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"""Puts the selection project into "hiero.selection"""
|
||||
|
||||
import hiero
|
||||
|
||||
|
||||
def selectionChanged(event):
|
||||
hiero.selection = event.sender.selection()
|
||||
|
||||
hiero.core.events.registerInterest("kSelectionChanged", selectionChanged)
|
||||
|
|
@ -23,7 +23,7 @@ class SetFrameRateDialog(QDialog):
|
|||
self._itemSelection = itemSelection
|
||||
|
||||
self._frameRateField = QLineEdit()
|
||||
self._frameRateField.setToolTip('Enter custom frame rate here.')
|
||||
self._frameRateField.setToolTip("Enter custom frame rate here.")
|
||||
self._frameRateField.setValidator(QDoubleValidator(1, 99, 3, self))
|
||||
self._frameRateField.textChanged.connect(self._textChanged)
|
||||
layout.addRow("Enter fps: ",self._frameRateField)
|
||||
|
|
@ -35,13 +35,13 @@ class SetFrameRateDialog(QDialog):
|
|||
self._buttonbox.button(QDialogButtonBox.Ok).setEnabled(False)
|
||||
layout.addRow("",self._buttonbox)
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
def _updateOkButtonState(self):
|
||||
# Cancel is always an option but only enable Ok if there is some text.
|
||||
currentFramerate = float(self.currentFramerateString())
|
||||
enableOk = False
|
||||
enableOk = ((currentFramerate > 0.0) and (currentFramerate <= 250.0))
|
||||
print 'enabledOk',enableOk
|
||||
print("enabledOk", enableOk)
|
||||
self._buttonbox.button(QDialogButtonBox.Ok).setEnabled(enableOk)
|
||||
|
||||
def _textChanged(self, newText):
|
||||
|
|
@ -50,32 +50,32 @@ class SetFrameRateDialog(QDialog):
|
|||
# Returns the current frame rate as a string
|
||||
def currentFramerateString(self):
|
||||
return str(self._frameRateField.text())
|
||||
|
||||
|
||||
# Presents the Dialog and sets the Frame rate from a selection
|
||||
def showDialogAndSetFrameRateFromSelection(self):
|
||||
|
||||
|
||||
if self._itemSelection is not None:
|
||||
if self.exec_():
|
||||
# For the Undo loop...
|
||||
|
||||
|
||||
# Construct an TimeBase object for setting the Frame Rate (fps)
|
||||
fps = hiero.core.TimeBase().fromString(self.currentFramerateString())
|
||||
|
||||
|
||||
|
||||
# Set the frame rate for the selected BinItmes
|
||||
for item in self._itemSelection:
|
||||
item.setFramerate(fps)
|
||||
item.setFramerate(fps)
|
||||
return
|
||||
|
||||
# This is just a convenience method for returning QActions with a title, triggered method and icon.
|
||||
def makeAction(title, method, icon = None):
|
||||
action = QAction(title,None)
|
||||
action.setIcon(QIcon(icon))
|
||||
|
||||
|
||||
# We do this magic, so that the title string from the action is used to set the frame rate!
|
||||
def methodWrapper():
|
||||
method(title)
|
||||
|
||||
|
||||
action.triggered.connect( methodWrapper )
|
||||
return action
|
||||
|
||||
|
|
@ -88,13 +88,13 @@ class SetFrameRateMenu:
|
|||
|
||||
|
||||
# ant: Could use hiero.core.defaultFrameRates() here but messes up with string matching because we seem to mix decimal points
|
||||
self.frameRates = ['8','12','12.50','15','23.98','24','25','29.97','30','48','50','59.94','60']
|
||||
self.frameRates = ["8","12","12.50","15","23.98","24","25","29.97","30","48","50","59.94","60"]
|
||||
hiero.core.events.registerInterest("kShowContextMenu/kBin", self.binViewEventHandler)
|
||||
|
||||
|
||||
self.menuActions = []
|
||||
|
||||
def createFrameRateMenus(self,selection):
|
||||
selectedClipFPS = [str(bi.activeItem().framerate()) for bi in selection if (isinstance(bi,hiero.core.BinItem) and hasattr(bi,'activeItem'))]
|
||||
selectedClipFPS = [str(bi.activeItem().framerate()) for bi in selection if (isinstance(bi,hiero.core.BinItem) and hasattr(bi,"activeItem"))]
|
||||
selectedClipFPS = hiero.core.util.uniquify(selectedClipFPS)
|
||||
sameFrameRate = len(selectedClipFPS)==1
|
||||
self.menuActions = []
|
||||
|
|
@ -106,39 +106,41 @@ class SetFrameRateMenu:
|
|||
self.menuActions+=[makeAction(fps,self.setFrameRateFromMenuSelection, icon="icons:remove active.png")]
|
||||
else:
|
||||
self.menuActions+=[makeAction(fps,self.setFrameRateFromMenuSelection, icon=None)]
|
||||
|
||||
|
||||
# Now add Custom... menu
|
||||
self.menuActions+=[makeAction('Custom...',self.setFrameRateFromMenuSelection, icon=None)]
|
||||
|
||||
self.menuActions += [makeAction(
|
||||
"Custom...", self.setFrameRateFromMenuSelection, icon=None)
|
||||
]
|
||||
|
||||
frameRateMenu = QMenu("Set Frame Rate")
|
||||
for a in self.menuActions:
|
||||
frameRateMenu.addAction(a)
|
||||
|
||||
|
||||
return frameRateMenu
|
||||
|
||||
def setFrameRateFromMenuSelection(self, menuSelectionFPS):
|
||||
|
||||
selectedBinItems = [bi.activeItem() for bi in self._selection if (isinstance(bi,hiero.core.BinItem) and hasattr(bi,'activeItem'))]
|
||||
|
||||
selectedBinItems = [bi.activeItem() for bi in self._selection if (isinstance(bi,hiero.core.BinItem) and hasattr(bi,"activeItem"))]
|
||||
currentProject = selectedBinItems[0].project()
|
||||
|
||||
|
||||
with currentProject.beginUndo("Set Frame Rate"):
|
||||
if menuSelectionFPS == 'Custom...':
|
||||
if menuSelectionFPS == "Custom...":
|
||||
self._frameRatesDialog = SetFrameRateDialog(itemSelection = selectedBinItems )
|
||||
self._frameRatesDialog.showDialogAndSetFrameRateFromSelection()
|
||||
|
||||
else:
|
||||
for b in selectedBinItems:
|
||||
b.setFramerate(hiero.core.TimeBase().fromString(menuSelectionFPS))
|
||||
|
||||
|
||||
return
|
||||
|
||||
# This handles events from the Project Bin View
|
||||
def binViewEventHandler(self,event):
|
||||
if not hasattr(event.sender, 'selection'):
|
||||
if not hasattr(event.sender, "selection"):
|
||||
# Something has gone wrong, we should only be here if raised
|
||||
# by the Bin view which gives a selection.
|
||||
return
|
||||
|
||||
|
||||
# Reset the selection to None...
|
||||
self._selection = None
|
||||
s = event.sender.selection()
|
||||
|
|
@ -151,9 +153,9 @@ class SetFrameRateMenu:
|
|||
if len(self._selection)==0:
|
||||
return
|
||||
# Creating the menu based on items selected, to highlight which frame rates are contained
|
||||
|
||||
|
||||
self._frameRateMenu = self.createFrameRateMenus(self._selection)
|
||||
|
||||
|
||||
# Insert the Set Frame Rate Button before the Set Media Colour Transform Action
|
||||
for action in event.menu.actions():
|
||||
if str(action.text()) == "Set Media Colour Transform":
|
||||
|
|
@ -16,29 +16,29 @@ except:
|
|||
from PySide2.QtCore import *
|
||||
|
||||
|
||||
def whereAmI(self, searchType='TrackItem'):
|
||||
def whereAmI(self, searchType="TrackItem"):
|
||||
"""returns a list of TrackItem or Sequnece objects in the Project which contain this Clip.
|
||||
By default this will return a list of TrackItems where the Clip is used in its project.
|
||||
You can also return a list of Sequences by specifying the searchType to be 'Sequence'.
|
||||
You can also return a list of Sequences by specifying the searchType to be "Sequence".
|
||||
Should consider putting this into hiero.core.Clip by default?
|
||||
|
||||
Example usage:
|
||||
|
||||
shotsForClip = clip.whereAmI('TrackItem')
|
||||
sequencesForClip = clip.whereAmI('Sequence')
|
||||
shotsForClip = clip.whereAmI("TrackItem")
|
||||
sequencesForClip = clip.whereAmI("Sequence")
|
||||
"""
|
||||
proj = self.project()
|
||||
|
||||
if ('TrackItem' not in searchType) and ('Sequence' not in searchType):
|
||||
print "searchType argument must be 'TrackItem' or 'Sequence'"
|
||||
if ("TrackItem" not in searchType) and ("Sequence" not in searchType):
|
||||
print("searchType argument must be \"TrackItem\" or \"Sequence\"")
|
||||
return None
|
||||
|
||||
# If user specifies a TrackItem, then it will return
|
||||
searches = hiero.core.findItemsInProject(proj, searchType)
|
||||
|
||||
if len(searches) == 0:
|
||||
print 'Unable to find %s in any items of type: %s' % (str(self),
|
||||
str(searchType))
|
||||
print("Unable to find {} in any items of type: {}".format(
|
||||
str(self), searchType))
|
||||
return None
|
||||
|
||||
# Case 1: Looking for Shots (trackItems)
|
||||
|
|
@ -110,7 +110,7 @@ class VersionAllMenu(object):
|
|||
for shot in sequenceShotManifest[seq]:
|
||||
updateReportString += ' %s\n (New Version: %s)\n' % (
|
||||
shot.name(), shot.currentVersion().name())
|
||||
updateReportString += '\n'
|
||||
updateReportString += "\n"
|
||||
|
||||
infoBox = QMessageBox(hiero.ui.mainWindow())
|
||||
infoBox.setIcon(QMessageBox.Information)
|
||||
|
|
@ -202,7 +202,7 @@ class VersionAllMenu(object):
|
|||
if len(bins) > 0:
|
||||
# Grab the Clips inside of a Bin and append them to a list
|
||||
for bin in bins:
|
||||
clips = hiero.core.findItemsInBin(bin, 'Clip')
|
||||
clips = hiero.core.findItemsInBin(bin, "Clip")
|
||||
for clip in clips:
|
||||
if clip not in clipItems:
|
||||
clipItems.append(clip)
|
||||
|
|
@ -291,7 +291,7 @@ class VersionAllMenu(object):
|
|||
for clip in clipSelection:
|
||||
|
||||
# Look to see if it exists in a TrackItem somewhere...
|
||||
shotUsage = clip.whereAmI('TrackItem')
|
||||
shotUsage = clip.whereAmI("TrackItem")
|
||||
|
||||
# Next, depending on the versionOption, make the appropriate update
|
||||
# There's probably a more neat/compact way of doing this...
|
||||
|
|
@ -326,7 +326,7 @@ class VersionAllMenu(object):
|
|||
# This handles events from the Project Bin View
|
||||
def binViewEventHandler(self, event):
|
||||
|
||||
if not hasattr(event.sender, 'selection'):
|
||||
if not hasattr(event.sender, "selection"):
|
||||
# Something has gone wrong, we should only be here if raised
|
||||
# by the Bin view which gives a selection.
|
||||
return
|
||||
|
|
@ -15,55 +15,55 @@ except:
|
|||
from PySide2.QtWidgets import *
|
||||
from PySide2.QtCore import *
|
||||
|
||||
# Set to True, if you wat 'Set Status' right-click menu, False if not
|
||||
# Set to True, if you wat "Set Status" right-click menu, False if not
|
||||
kAddStatusMenu = True
|
||||
|
||||
# Set to True, if you wat 'Assign Artist' right-click menu, False if not
|
||||
# Set to True, if you wat "Assign Artist" right-click menu, False if not
|
||||
kAssignArtistMenu = True
|
||||
|
||||
# Global list of Artist Name Dictionaries
|
||||
# Note: Override this to add different names, icons, department, IDs.
|
||||
gArtistList = [{
|
||||
'artistName': 'John Smith',
|
||||
'artistIcon': 'icons:TagActor.png',
|
||||
'artistDepartment': '3D',
|
||||
'artistID': 0
|
||||
"artistName": "John Smith",
|
||||
"artistIcon": "icons:TagActor.png",
|
||||
"artistDepartment": "3D",
|
||||
"artistID": 0
|
||||
}, {
|
||||
'artistName': 'Savlvador Dali',
|
||||
'artistIcon': 'icons:TagActor.png',
|
||||
'artistDepartment': 'Roto',
|
||||
'artistID': 1
|
||||
"artistName": "Savlvador Dali",
|
||||
"artistIcon": "icons:TagActor.png",
|
||||
"artistDepartment": "Roto",
|
||||
"artistID": 1
|
||||
}, {
|
||||
'artistName': 'Leonardo Da Vinci',
|
||||
'artistIcon': 'icons:TagActor.png',
|
||||
'artistDepartment': 'Paint',
|
||||
'artistID': 2
|
||||
"artistName": "Leonardo Da Vinci",
|
||||
"artistIcon": "icons:TagActor.png",
|
||||
"artistDepartment": "Paint",
|
||||
"artistID": 2
|
||||
}, {
|
||||
'artistName': 'Claude Monet',
|
||||
'artistIcon': 'icons:TagActor.png',
|
||||
'artistDepartment': 'Comp',
|
||||
'artistID': 3
|
||||
"artistName": "Claude Monet",
|
||||
"artistIcon": "icons:TagActor.png",
|
||||
"artistDepartment": "Comp",
|
||||
"artistID": 3
|
||||
}, {
|
||||
'artistName': 'Pablo Picasso',
|
||||
'artistIcon': 'icons:TagActor.png',
|
||||
'artistDepartment': 'Animation',
|
||||
'artistID': 4
|
||||
"artistName": "Pablo Picasso",
|
||||
"artistIcon": "icons:TagActor.png",
|
||||
"artistDepartment": "Animation",
|
||||
"artistID": 4
|
||||
}]
|
||||
|
||||
# Global Dictionary of Status Tags.
|
||||
# Note: This can be overwritten if you want to add a new status cellType or custom icon
|
||||
# Override the gStatusTags dictionary by adding your own 'Status':'Icon.png' key-value pairs.
|
||||
# Add new custom keys like so: gStatusTags['For Client'] = 'forClient.png'
|
||||
# Override the gStatusTags dictionary by adding your own "Status":"Icon.png" key-value pairs.
|
||||
# Add new custom keys like so: gStatusTags["For Client"] = "forClient.png"
|
||||
gStatusTags = {
|
||||
'Approved': 'icons:status/TagApproved.png',
|
||||
'Unapproved': 'icons:status/TagUnapproved.png',
|
||||
'Ready To Start': 'icons:status/TagReadyToStart.png',
|
||||
'Blocked': 'icons:status/TagBlocked.png',
|
||||
'On Hold': 'icons:status/TagOnHold.png',
|
||||
'In Progress': 'icons:status/TagInProgress.png',
|
||||
'Awaiting Approval': 'icons:status/TagAwaitingApproval.png',
|
||||
'Omitted': 'icons:status/TagOmitted.png',
|
||||
'Final': 'icons:status/TagFinal.png'
|
||||
"Approved": "icons:status/TagApproved.png",
|
||||
"Unapproved": "icons:status/TagUnapproved.png",
|
||||
"Ready To Start": "icons:status/TagReadyToStart.png",
|
||||
"Blocked": "icons:status/TagBlocked.png",
|
||||
"On Hold": "icons:status/TagOnHold.png",
|
||||
"In Progress": "icons:status/TagInProgress.png",
|
||||
"Awaiting Approval": "icons:status/TagAwaitingApproval.png",
|
||||
"Omitted": "icons:status/TagOmitted.png",
|
||||
"Final": "icons:status/TagFinal.png"
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -78,17 +78,17 @@ class CustomSpreadsheetColumns(QObject):
|
|||
|
||||
# Ideally, we'd set this list on a Per Item basis, but this is expensive for a large mixed selection
|
||||
standardColourSpaces = [
|
||||
'linear', 'sRGB', 'rec709', 'Cineon', 'Gamma1.8', 'Gamma2.2',
|
||||
'Panalog', 'REDLog', 'ViperLog'
|
||||
"linear", "sRGB", "rec709", "Cineon", "Gamma1.8", "Gamma2.2",
|
||||
"Panalog", "REDLog", "ViperLog"
|
||||
]
|
||||
arriColourSpaces = [
|
||||
'Video - Rec709', 'LogC - Camera Native', 'Video - P3', 'ACES',
|
||||
'LogC - Film', 'LogC - Wide Gamut'
|
||||
"Video - Rec709", "LogC - Camera Native", "Video - P3", "ACES",
|
||||
"LogC - Film", "LogC - Wide Gamut"
|
||||
]
|
||||
r3dColourSpaces = [
|
||||
'Linear', 'Rec709', 'REDspace', 'REDlog', 'PDlog685', 'PDlog985',
|
||||
'CustomPDlog', 'REDgamma', 'SRGB', 'REDlogFilm', 'REDgamma2',
|
||||
'REDgamma3'
|
||||
"Linear", "Rec709", "REDspace", "REDlog", "PDlog685", "PDlog985",
|
||||
"CustomPDlog", "REDgamma", "SRGB", "REDlogFilm", "REDgamma2",
|
||||
"REDgamma3"
|
||||
]
|
||||
gColourSpaces = standardColourSpaces + arriColourSpaces + r3dColourSpaces
|
||||
|
||||
|
|
@ -97,52 +97,52 @@ class CustomSpreadsheetColumns(QObject):
|
|||
# This is the list of Columns available
|
||||
gCustomColumnList = [
|
||||
{
|
||||
'name': 'Tags',
|
||||
'cellType': 'readonly'
|
||||
"name": "Tags",
|
||||
"cellType": "readonly"
|
||||
},
|
||||
{
|
||||
'name': 'Colourspace',
|
||||
'cellType': 'dropdown'
|
||||
"name": "Colourspace",
|
||||
"cellType": "dropdown"
|
||||
},
|
||||
{
|
||||
'name': 'Notes',
|
||||
'cellType': 'readonly'
|
||||
"name": "Notes",
|
||||
"cellType": "readonly"
|
||||
},
|
||||
{
|
||||
'name': 'FileType',
|
||||
'cellType': 'readonly'
|
||||
"name": "FileType",
|
||||
"cellType": "readonly"
|
||||
},
|
||||
{
|
||||
'name': 'Shot Status',
|
||||
'cellType': 'dropdown'
|
||||
"name": "Shot Status",
|
||||
"cellType": "dropdown"
|
||||
},
|
||||
{
|
||||
'name': 'Thumbnail',
|
||||
'cellType': 'readonly'
|
||||
"name": "Thumbnail",
|
||||
"cellType": "readonly"
|
||||
},
|
||||
{
|
||||
'name': 'MediaType',
|
||||
'cellType': 'readonly'
|
||||
"name": "MediaType",
|
||||
"cellType": "readonly"
|
||||
},
|
||||
{
|
||||
'name': 'Width',
|
||||
'cellType': 'readonly'
|
||||
"name": "Width",
|
||||
"cellType": "readonly"
|
||||
},
|
||||
{
|
||||
'name': 'Height',
|
||||
'cellType': 'readonly'
|
||||
"name": "Height",
|
||||
"cellType": "readonly"
|
||||
},
|
||||
{
|
||||
'name': 'Pixel Aspect',
|
||||
'cellType': 'readonly'
|
||||
"name": "Pixel Aspect",
|
||||
"cellType": "readonly"
|
||||
},
|
||||
{
|
||||
'name': 'Artist',
|
||||
'cellType': 'dropdown'
|
||||
"name": "Artist",
|
||||
"cellType": "dropdown"
|
||||
},
|
||||
{
|
||||
'name': 'Department',
|
||||
'cellType': 'readonly'
|
||||
"name": "Department",
|
||||
"cellType": "readonly"
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ class CustomSpreadsheetColumns(QObject):
|
|||
"""
|
||||
Return the name of a custom column
|
||||
"""
|
||||
return self.gCustomColumnList[column]['name']
|
||||
return self.gCustomColumnList[column]["name"]
|
||||
|
||||
def getTagsString(self, item):
|
||||
"""
|
||||
|
|
@ -173,7 +173,7 @@ class CustomSpreadsheetColumns(QObject):
|
|||
"""
|
||||
Convenience method for returning all the Notes in a Tag as a string
|
||||
"""
|
||||
notes = ''
|
||||
notes = ""
|
||||
tags = item.tags()
|
||||
for tag in tags:
|
||||
note = tag.note()
|
||||
|
|
@ -186,67 +186,67 @@ class CustomSpreadsheetColumns(QObject):
|
|||
Return the data in a cell
|
||||
"""
|
||||
currentColumn = self.gCustomColumnList[column]
|
||||
if currentColumn['name'] == 'Tags':
|
||||
if currentColumn["name"] == "Tags":
|
||||
return self.getTagsString(item)
|
||||
|
||||
if currentColumn['name'] == 'Colourspace':
|
||||
if currentColumn["name"] == "Colourspace":
|
||||
try:
|
||||
colTransform = item.sourceMediaColourTransform()
|
||||
except:
|
||||
colTransform = '--'
|
||||
colTransform = "--"
|
||||
return colTransform
|
||||
|
||||
if currentColumn['name'] == 'Notes':
|
||||
if currentColumn["name"] == "Notes":
|
||||
try:
|
||||
note = self.getNotes(item)
|
||||
except:
|
||||
note = ''
|
||||
note = ""
|
||||
return note
|
||||
|
||||
if currentColumn['name'] == 'FileType':
|
||||
fileType = '--'
|
||||
if currentColumn["name"] == "FileType":
|
||||
fileType = "--"
|
||||
M = item.source().mediaSource().metadata()
|
||||
if M.hasKey('foundry.source.type'):
|
||||
fileType = M.value('foundry.source.type')
|
||||
elif M.hasKey('media.input.filereader'):
|
||||
fileType = M.value('media.input.filereader')
|
||||
if M.hasKey("foundry.source.type"):
|
||||
fileType = M.value("foundry.source.type")
|
||||
elif M.hasKey("media.input.filereader"):
|
||||
fileType = M.value("media.input.filereader")
|
||||
return fileType
|
||||
|
||||
if currentColumn['name'] == 'Shot Status':
|
||||
if currentColumn["name"] == "Shot Status":
|
||||
status = item.status()
|
||||
if not status:
|
||||
status = "--"
|
||||
return str(status)
|
||||
|
||||
if currentColumn['name'] == 'MediaType':
|
||||
if currentColumn["name"] == "MediaType":
|
||||
M = item.mediaType()
|
||||
return str(M).split('MediaType')[-1].replace('.k', '')
|
||||
return str(M).split("MediaType")[-1].replace(".k", "")
|
||||
|
||||
if currentColumn['name'] == 'Thumbnail':
|
||||
if currentColumn["name"] == "Thumbnail":
|
||||
return str(item.eventNumber())
|
||||
|
||||
if currentColumn['name'] == 'Width':
|
||||
if currentColumn["name"] == "Width":
|
||||
return str(item.source().format().width())
|
||||
|
||||
if currentColumn['name'] == 'Height':
|
||||
if currentColumn["name"] == "Height":
|
||||
return str(item.source().format().height())
|
||||
|
||||
if currentColumn['name'] == 'Pixel Aspect':
|
||||
if currentColumn["name"] == "Pixel Aspect":
|
||||
return str(item.source().format().pixelAspect())
|
||||
|
||||
if currentColumn['name'] == 'Artist':
|
||||
if currentColumn["name"] == "Artist":
|
||||
if item.artist():
|
||||
name = item.artist()['artistName']
|
||||
name = item.artist()["artistName"]
|
||||
return name
|
||||
else:
|
||||
return '--'
|
||||
return "--"
|
||||
|
||||
if currentColumn['name'] == 'Department':
|
||||
if currentColumn["name"] == "Department":
|
||||
if item.artist():
|
||||
dep = item.artist()['artistDepartment']
|
||||
dep = item.artist()["artistDepartment"]
|
||||
return dep
|
||||
else:
|
||||
return '--'
|
||||
return "--"
|
||||
|
||||
return ""
|
||||
|
||||
|
|
@ -262,10 +262,10 @@ class CustomSpreadsheetColumns(QObject):
|
|||
Return the tooltip for a cell
|
||||
"""
|
||||
currentColumn = self.gCustomColumnList[column]
|
||||
if currentColumn['name'] == 'Tags':
|
||||
if currentColumn["name"] == "Tags":
|
||||
return str([item.name() for item in item.tags()])
|
||||
|
||||
if currentColumn['name'] == 'Notes':
|
||||
if currentColumn["name"] == "Notes":
|
||||
return str(self.getNotes(item))
|
||||
return ""
|
||||
|
||||
|
|
@ -296,24 +296,24 @@ class CustomSpreadsheetColumns(QObject):
|
|||
Return the icon for a cell
|
||||
"""
|
||||
currentColumn = self.gCustomColumnList[column]
|
||||
if currentColumn['name'] == 'Colourspace':
|
||||
if currentColumn["name"] == "Colourspace":
|
||||
return QIcon("icons:LUT.png")
|
||||
|
||||
if currentColumn['name'] == 'Shot Status':
|
||||
if currentColumn["name"] == "Shot Status":
|
||||
status = item.status()
|
||||
if status:
|
||||
return QIcon(gStatusTags[status])
|
||||
|
||||
if currentColumn['name'] == 'MediaType':
|
||||
if currentColumn["name"] == "MediaType":
|
||||
mediaType = item.mediaType()
|
||||
if mediaType == hiero.core.TrackItem.kVideo:
|
||||
return QIcon("icons:VideoOnly.png")
|
||||
elif mediaType == hiero.core.TrackItem.kAudio:
|
||||
return QIcon("icons:AudioOnly.png")
|
||||
|
||||
if currentColumn['name'] == 'Artist':
|
||||
if currentColumn["name"] == "Artist":
|
||||
try:
|
||||
return QIcon(item.artist()['artistIcon'])
|
||||
return QIcon(item.artist()["artistIcon"])
|
||||
except:
|
||||
return None
|
||||
return None
|
||||
|
|
@ -322,9 +322,9 @@ class CustomSpreadsheetColumns(QObject):
|
|||
"""
|
||||
Return the size hint for a cell
|
||||
"""
|
||||
currentColumnName = self.gCustomColumnList[column]['name']
|
||||
currentColumnName = self.gCustomColumnList[column]["name"]
|
||||
|
||||
if currentColumnName == 'Thumbnail':
|
||||
if currentColumnName == "Thumbnail":
|
||||
return QSize(90, 50)
|
||||
|
||||
return QSize(50, 50)
|
||||
|
|
@ -335,7 +335,7 @@ class CustomSpreadsheetColumns(QObject):
|
|||
with the default cell painting.
|
||||
"""
|
||||
currentColumn = self.gCustomColumnList[column]
|
||||
if currentColumn['name'] == 'Tags':
|
||||
if currentColumn["name"] == "Tags":
|
||||
if option.state & QStyle.State_Selected:
|
||||
painter.fillRect(option.rect, option.palette.highlight())
|
||||
iconSize = 20
|
||||
|
|
@ -348,14 +348,14 @@ class CustomSpreadsheetColumns(QObject):
|
|||
painter.setClipRect(option.rect)
|
||||
for tag in item.tags():
|
||||
M = tag.metadata()
|
||||
if not (M.hasKey('tag.status')
|
||||
or M.hasKey('tag.artistID')):
|
||||
if not (M.hasKey("tag.status")
|
||||
or M.hasKey("tag.artistID")):
|
||||
QIcon(tag.icon()).paint(painter, r, Qt.AlignLeft)
|
||||
r.translate(r.width() + 2, 0)
|
||||
painter.restore()
|
||||
return True
|
||||
|
||||
if currentColumn['name'] == 'Thumbnail':
|
||||
if currentColumn["name"] == "Thumbnail":
|
||||
imageView = None
|
||||
pen = QPen()
|
||||
r = QRect(option.rect.x() + 2, (option.rect.y() +
|
||||
|
|
@ -409,35 +409,35 @@ class CustomSpreadsheetColumns(QObject):
|
|||
self.currentView = view
|
||||
|
||||
currentColumn = self.gCustomColumnList[column]
|
||||
if currentColumn['cellType'] == 'readonly':
|
||||
if currentColumn["cellType"] == "readonly":
|
||||
cle = QLabel()
|
||||
cle.setEnabled(False)
|
||||
cle.setVisible(False)
|
||||
return cle
|
||||
|
||||
if currentColumn['name'] == 'Colourspace':
|
||||
if currentColumn["name"] == "Colourspace":
|
||||
cb = QComboBox()
|
||||
for colourspace in self.gColourSpaces:
|
||||
cb.addItem(colourspace)
|
||||
cb.currentIndexChanged.connect(self.colourspaceChanged)
|
||||
return cb
|
||||
|
||||
if currentColumn['name'] == 'Shot Status':
|
||||
if currentColumn["name"] == "Shot Status":
|
||||
cb = QComboBox()
|
||||
cb.addItem('')
|
||||
cb.addItem("")
|
||||
for key in gStatusTags.keys():
|
||||
cb.addItem(QIcon(gStatusTags[key]), key)
|
||||
cb.addItem('--')
|
||||
cb.addItem("--")
|
||||
cb.currentIndexChanged.connect(self.statusChanged)
|
||||
|
||||
return cb
|
||||
|
||||
if currentColumn['name'] == 'Artist':
|
||||
if currentColumn["name"] == "Artist":
|
||||
cb = QComboBox()
|
||||
cb.addItem('')
|
||||
cb.addItem("")
|
||||
for artist in gArtistList:
|
||||
cb.addItem(artist['artistName'])
|
||||
cb.addItem('--')
|
||||
cb.addItem(artist["artistName"])
|
||||
cb.addItem("--")
|
||||
cb.currentIndexChanged.connect(self.artistNameChanged)
|
||||
return cb
|
||||
return None
|
||||
|
|
@ -479,15 +479,15 @@ class CustomSpreadsheetColumns(QObject):
|
|||
status = self.sender().currentText()
|
||||
project = selection[0].project()
|
||||
with project.beginUndo("Set Status"):
|
||||
# A string of '--' characters denotes clear the status
|
||||
if status != '--':
|
||||
# A string of "--" characters denotes clear the status
|
||||
if status != "--":
|
||||
for trackItem in selection:
|
||||
trackItem.setStatus(status)
|
||||
else:
|
||||
for trackItem in selection:
|
||||
tTags = trackItem.tags()
|
||||
for tag in tTags:
|
||||
if tag.metadata().hasKey('tag.status'):
|
||||
if tag.metadata().hasKey("tag.status"):
|
||||
trackItem.removeTag(tag)
|
||||
break
|
||||
|
||||
|
|
@ -500,15 +500,15 @@ class CustomSpreadsheetColumns(QObject):
|
|||
name = self.sender().currentText()
|
||||
project = selection[0].project()
|
||||
with project.beginUndo("Assign Artist"):
|
||||
# A string of '--' denotes clear the assignee...
|
||||
if name != '--':
|
||||
# A string of "--" denotes clear the assignee...
|
||||
if name != "--":
|
||||
for trackItem in selection:
|
||||
trackItem.setArtistByName(name)
|
||||
else:
|
||||
for trackItem in selection:
|
||||
tTags = trackItem.tags()
|
||||
for tag in tTags:
|
||||
if tag.metadata().hasKey('tag.artistID'):
|
||||
if tag.metadata().hasKey("tag.artistID"):
|
||||
trackItem.removeTag(tag)
|
||||
break
|
||||
|
||||
|
|
@ -518,7 +518,7 @@ def _getArtistFromID(self, artistID):
|
|||
global gArtistList
|
||||
artist = [
|
||||
element for element in gArtistList
|
||||
if element['artistID'] == int(artistID)
|
||||
if element["artistID"] == int(artistID)
|
||||
]
|
||||
if not artist:
|
||||
return None
|
||||
|
|
@ -530,7 +530,7 @@ def _getArtistFromName(self, artistName):
|
|||
global gArtistList
|
||||
artist = [
|
||||
element for element in gArtistList
|
||||
if element['artistName'] == artistName
|
||||
if element["artistName"] == artistName
|
||||
]
|
||||
if not artist:
|
||||
return None
|
||||
|
|
@ -542,8 +542,8 @@ def _artist(self):
|
|||
artist = None
|
||||
tags = self.tags()
|
||||
for tag in tags:
|
||||
if tag.metadata().hasKey('tag.artistID'):
|
||||
artistID = tag.metadata().value('tag.artistID')
|
||||
if tag.metadata().hasKey("tag.artistID"):
|
||||
artistID = tag.metadata().value("tag.artistID")
|
||||
artist = self.getArtistFromID(artistID)
|
||||
return artist
|
||||
|
||||
|
|
@ -554,30 +554,30 @@ def _updateArtistTag(self, artistDict):
|
|||
artistTag = None
|
||||
tags = self.tags()
|
||||
for tag in tags:
|
||||
if tag.metadata().hasKey('tag.artistID'):
|
||||
if tag.metadata().hasKey("tag.artistID"):
|
||||
artistTag = tag
|
||||
break
|
||||
|
||||
if not artistTag:
|
||||
artistTag = hiero.core.Tag('Artist')
|
||||
artistTag.setIcon(artistDict['artistIcon'])
|
||||
artistTag.metadata().setValue('tag.artistID',
|
||||
str(artistDict['artistID']))
|
||||
artistTag.metadata().setValue('tag.artistName',
|
||||
str(artistDict['artistName']))
|
||||
artistTag.metadata().setValue('tag.artistDepartment',
|
||||
str(artistDict['artistDepartment']))
|
||||
artistTag = hiero.core.Tag("Artist")
|
||||
artistTag.setIcon(artistDict["artistIcon"])
|
||||
artistTag.metadata().setValue("tag.artistID",
|
||||
str(artistDict["artistID"]))
|
||||
artistTag.metadata().setValue("tag.artistName",
|
||||
str(artistDict["artistName"]))
|
||||
artistTag.metadata().setValue("tag.artistDepartment",
|
||||
str(artistDict["artistDepartment"]))
|
||||
self.sequence().editFinished()
|
||||
self.addTag(artistTag)
|
||||
self.sequence().editFinished()
|
||||
return
|
||||
|
||||
artistTag.setIcon(artistDict['artistIcon'])
|
||||
artistTag.metadata().setValue('tag.artistID', str(artistDict['artistID']))
|
||||
artistTag.metadata().setValue('tag.artistName',
|
||||
str(artistDict['artistName']))
|
||||
artistTag.metadata().setValue('tag.artistDepartment',
|
||||
str(artistDict['artistDepartment']))
|
||||
artistTag.setIcon(artistDict["artistIcon"])
|
||||
artistTag.metadata().setValue("tag.artistID", str(artistDict["artistID"]))
|
||||
artistTag.metadata().setValue("tag.artistName",
|
||||
str(artistDict["artistName"]))
|
||||
artistTag.metadata().setValue("tag.artistDepartment",
|
||||
str(artistDict["artistDepartment"]))
|
||||
self.sequence().editFinished()
|
||||
return
|
||||
|
||||
|
|
@ -588,8 +588,9 @@ def _setArtistByName(self, artistName):
|
|||
|
||||
artist = self.getArtistFromName(artistName)
|
||||
if not artist:
|
||||
print 'Artist name: %s was not found in the gArtistList.' % str(
|
||||
artistName)
|
||||
print((
|
||||
"Artist name: {} was not found in "
|
||||
"the gArtistList.").format(artistName))
|
||||
return
|
||||
|
||||
# Do the update.
|
||||
|
|
@ -602,8 +603,8 @@ def _setArtistByID(self, artistID):
|
|||
|
||||
artist = self.getArtistFromID(artistID)
|
||||
if not artist:
|
||||
print 'Artist name: %s was not found in the gArtistList.' % str(
|
||||
artistID)
|
||||
print("Artist name: {} was not found in the gArtistList.".format(
|
||||
artistID))
|
||||
return
|
||||
|
||||
# Do the update.
|
||||
|
|
@ -625,15 +626,15 @@ def _status(self):
|
|||
status = None
|
||||
tags = self.tags()
|
||||
for tag in tags:
|
||||
if tag.metadata().hasKey('tag.status'):
|
||||
status = tag.metadata().value('tag.status')
|
||||
if tag.metadata().hasKey("tag.status"):
|
||||
status = tag.metadata().value("tag.status")
|
||||
return status
|
||||
|
||||
|
||||
def _setStatus(self, status):
|
||||
"""setShotStatus(status) -> Method to set the Status of a Shot.
|
||||
Adds a special kind of status Tag to a TrackItem
|
||||
Example: myTrackItem.setStatus('Final')
|
||||
Example: myTrackItem.setStatus("Final")
|
||||
|
||||
@param status - a string, corresponding to the Status name
|
||||
"""
|
||||
|
|
@ -641,25 +642,25 @@ def _setStatus(self, status):
|
|||
|
||||
# Get a valid Tag object from the Global list of statuses
|
||||
if not status in gStatusTags.keys():
|
||||
print 'Status requested was not a valid Status string.'
|
||||
print("Status requested was not a valid Status string.")
|
||||
return
|
||||
|
||||
# A shot should only have one status. Check if one exists and set accordingly
|
||||
statusTag = None
|
||||
tags = self.tags()
|
||||
for tag in tags:
|
||||
if tag.metadata().hasKey('tag.status'):
|
||||
if tag.metadata().hasKey("tag.status"):
|
||||
statusTag = tag
|
||||
break
|
||||
|
||||
if not statusTag:
|
||||
statusTag = hiero.core.Tag('Status')
|
||||
statusTag = hiero.core.Tag("Status")
|
||||
statusTag.setIcon(gStatusTags[status])
|
||||
statusTag.metadata().setValue('tag.status', status)
|
||||
statusTag.metadata().setValue("tag.status", status)
|
||||
self.addTag(statusTag)
|
||||
|
||||
statusTag.setIcon(gStatusTags[status])
|
||||
statusTag.metadata().setValue('tag.status', status)
|
||||
statusTag.metadata().setValue("tag.status", status)
|
||||
|
||||
self.sequence().editFinished()
|
||||
return
|
||||
|
|
@ -743,7 +744,7 @@ class SetStatusMenu(QMenu):
|
|||
|
||||
# This handles events from the Project Bin View
|
||||
def eventHandler(self, event):
|
||||
if not hasattr(event.sender, 'selection'):
|
||||
if not hasattr(event.sender, "selection"):
|
||||
# Something has gone wrong, we should only be here if raised
|
||||
# by the Timeline/Spreadsheet view which gives a selection.
|
||||
return
|
||||
|
|
@ -781,9 +782,9 @@ class AssignArtistMenu(QMenu):
|
|||
for artist in self.artists:
|
||||
self.menuActions += [
|
||||
titleStringTriggeredAction(
|
||||
artist['artistName'],
|
||||
artist["artistName"],
|
||||
self.setArtistFromMenuSelection,
|
||||
icon=artist['artistIcon'])
|
||||
icon=artist["artistIcon"])
|
||||
]
|
||||
|
||||
def setArtistFromMenuSelection(self, menuSelectionArtist):
|
||||
|
|
@ -818,7 +819,7 @@ class AssignArtistMenu(QMenu):
|
|||
|
||||
# This handles events from the Project Bin View
|
||||
def eventHandler(self, event):
|
||||
if not hasattr(event.sender, 'selection'):
|
||||
if not hasattr(event.sender, "selection"):
|
||||
# Something has gone wrong, we should only be here if raised
|
||||
# by the Timeline/Spreadsheet view which gives a selection.
|
||||
return
|
||||
|
|
@ -833,7 +834,7 @@ class AssignArtistMenu(QMenu):
|
|||
event.menu.addMenu(self)
|
||||
|
||||
|
||||
# Add the 'Set Status' context menu to Timeline and Spreadsheet
|
||||
# Add the "Set Status" context menu to Timeline and Spreadsheet
|
||||
if kAddStatusMenu:
|
||||
setStatusMenu = SetStatusMenu()
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ class PurgeUnusedAction(QAction):
|
|||
self.triggered.connect(self.PurgeUnused)
|
||||
hiero.core.events.registerInterest("kShowContextMenu/kBin",
|
||||
self.eventHandler)
|
||||
self.setIcon(QIcon('icons:TagDelete.png'))
|
||||
self.setIcon(QIcon("icons:TagDelete.png"))
|
||||
|
||||
# Method to return whether a Bin is empty...
|
||||
def binIsEmpty(self, b):
|
||||
|
|
@ -67,19 +67,19 @@ class PurgeUnusedAction(QAction):
|
|||
msgBox.setDefaultButton(QMessageBox.Ok)
|
||||
ret = msgBox.exec_()
|
||||
if ret == QMessageBox.Cancel:
|
||||
print 'Not purging anything.'
|
||||
print("Not purging anything.")
|
||||
elif ret == QMessageBox.Ok:
|
||||
with proj.beginUndo('Purge Unused Clips'):
|
||||
with proj.beginUndo("Purge Unused Clips"):
|
||||
BINS = []
|
||||
for clip in CLIPSTOREMOVE:
|
||||
BI = clip.binItem()
|
||||
B = BI.parentBin()
|
||||
BINS += [B]
|
||||
print 'Removing:', BI
|
||||
print("Removing: {}".format(BI))
|
||||
try:
|
||||
B.removeItem(BI)
|
||||
except:
|
||||
print 'Unable to remove: ' + BI
|
||||
print("Unable to remove: {}".format(BI))
|
||||
return
|
||||
|
||||
# For each sequence, iterate through each track Item, see if the Clip is in the CLIPS list.
|
||||
|
|
@ -104,24 +104,24 @@ class PurgeUnusedAction(QAction):
|
|||
ret = msgBox.exec_()
|
||||
|
||||
if ret == QMessageBox.Cancel:
|
||||
print 'Cancel'
|
||||
print("Cancel")
|
||||
return
|
||||
elif ret == QMessageBox.Ok:
|
||||
BINS = []
|
||||
with proj.beginUndo('Purge Unused Clips'):
|
||||
with proj.beginUndo("Purge Unused Clips"):
|
||||
# Delete the rest of the Clips
|
||||
for clip in CLIPSTOREMOVE:
|
||||
BI = clip.binItem()
|
||||
B = BI.parentBin()
|
||||
BINS += [B]
|
||||
print 'Removing:', BI
|
||||
print("Removing: {}".format(BI))
|
||||
try:
|
||||
B.removeItem(BI)
|
||||
except:
|
||||
print 'Unable to remove: ' + BI
|
||||
print("Unable to remove: {}".format(BI))
|
||||
|
||||
def eventHandler(self, event):
|
||||
if not hasattr(event.sender, 'selection'):
|
||||
if not hasattr(event.sender, "selection"):
|
||||
# Something has gone wrong, we shouldn't only be here if raised
|
||||
# by the Bin view which will give a selection.
|
||||
return
|
||||
|
|
@ -13,21 +13,22 @@ except:
|
|||
|
||||
#----------------------------------------------
|
||||
a = hiero.ui.findMenuAction('Import File(s)...')
|
||||
# Note: You probably best to make this 'Ctrl+R' - currently conflicts with 'Red' in the Viewer!
|
||||
a.setShortcut(QKeySequence('R'))
|
||||
# Note: You probably best to make this 'Ctrl+R' - currently conflicts with "Red" in the Viewer!
|
||||
a.setShortcut(QKeySequence("R"))
|
||||
#----------------------------------------------
|
||||
a = hiero.ui.findMenuAction('Import Folder(s)...')
|
||||
a.setShortcut(QKeySequence('Shift+R'))
|
||||
#----------------------------------------------
|
||||
a = hiero.ui.findMenuAction('Import EDL/XML/AAF...')
|
||||
a = hiero.ui.findMenuAction("Import EDL/XML/AAF...")
|
||||
a.setShortcut(QKeySequence('Ctrl+Shift+O'))
|
||||
#----------------------------------------------
|
||||
a = hiero.ui.findMenuAction('Metadata View')
|
||||
a.setShortcut(QKeySequence('I'))
|
||||
a = hiero.ui.findMenuAction("Metadata View")
|
||||
a.setShortcut(QKeySequence("I"))
|
||||
#----------------------------------------------
|
||||
a = hiero.ui.findMenuAction('Edit Settings')
|
||||
a.setShortcut(QKeySequence('S'))
|
||||
a = hiero.ui.findMenuAction("Edit Settings")
|
||||
a.setShortcut(QKeySequence("S"))
|
||||
#----------------------------------------------
|
||||
a = hiero.ui.findMenuAction('Monitor Output')
|
||||
a.setShortcut(QKeySequence('Ctrl+U'))
|
||||
a = hiero.ui.findMenuAction("Monitor Output")
|
||||
if a:
|
||||
a.setShortcut(QKeySequence('Ctrl+U'))
|
||||
#----------------------------------------------
|
||||
|
|
@ -44,16 +44,16 @@ def get_transition_type(otio_item, otio_track):
|
|||
_out = None
|
||||
|
||||
if _in and _out:
|
||||
return 'dissolve'
|
||||
return "dissolve"
|
||||
|
||||
elif _in and not _out:
|
||||
return 'fade_out'
|
||||
return "fade_out"
|
||||
|
||||
elif not _in and _out:
|
||||
return 'fade_in'
|
||||
return "fade_in"
|
||||
|
||||
else:
|
||||
return 'unknown'
|
||||
return "unknown"
|
||||
|
||||
|
||||
def find_trackitem(name, hiero_track):
|
||||
|
|
@ -84,10 +84,10 @@ def apply_transition(otio_track, otio_item, track):
|
|||
|
||||
# Figure out track kind for getattr below
|
||||
if isinstance(track, hiero.core.VideoTrack):
|
||||
kind = ''
|
||||
kind = ""
|
||||
|
||||
else:
|
||||
kind = 'Audio'
|
||||
kind = "Audio"
|
||||
|
||||
try:
|
||||
# Gather TrackItems involved in trasition
|
||||
|
|
@ -98,7 +98,7 @@ def apply_transition(otio_track, otio_item, track):
|
|||
)
|
||||
|
||||
# Create transition object
|
||||
if transition_type == 'dissolve':
|
||||
if transition_type == "dissolve":
|
||||
transition_func = getattr(
|
||||
hiero.core.Transition,
|
||||
'create{kind}DissolveTransition'.format(kind=kind)
|
||||
|
|
@ -111,7 +111,7 @@ def apply_transition(otio_track, otio_item, track):
|
|||
otio_item.out_offset.value
|
||||
)
|
||||
|
||||
elif transition_type == 'fade_in':
|
||||
elif transition_type == "fade_in":
|
||||
transition_func = getattr(
|
||||
hiero.core.Transition,
|
||||
'create{kind}FadeInTransition'.format(kind=kind)
|
||||
|
|
@ -121,7 +121,7 @@ def apply_transition(otio_track, otio_item, track):
|
|||
otio_item.out_offset.value
|
||||
)
|
||||
|
||||
elif transition_type == 'fade_out':
|
||||
elif transition_type == "fade_out":
|
||||
transition_func = getattr(
|
||||
hiero.core.Transition,
|
||||
'create{kind}FadeOutTransition'.format(kind=kind)
|
||||
|
|
@ -150,11 +150,11 @@ def apply_transition(otio_track, otio_item, track):
|
|||
def prep_url(url_in):
|
||||
url = unquote(url_in)
|
||||
|
||||
if url.startswith('file://localhost/'):
|
||||
return url.replace('file://localhost/', '')
|
||||
if url.startswith("file://localhost/"):
|
||||
return url.replace("file://localhost/", "")
|
||||
|
||||
url = '{url}'.format(
|
||||
sep=url.startswith(os.sep) and '' or os.sep,
|
||||
sep=url.startswith(os.sep) and "" or os.sep,
|
||||
url=url.startswith(os.sep) and url[1:] or url
|
||||
)
|
||||
|
||||
|
|
@ -228,8 +228,8 @@ def add_metadata(metadata, hiero_item):
|
|||
continue
|
||||
|
||||
if value is not None:
|
||||
if not key.startswith('tag.'):
|
||||
key = 'tag.' + key
|
||||
if not key.startswith("tag."):
|
||||
key = "tag." + key
|
||||
|
||||
hiero_item.metadata().setValue(key, str(value))
|
||||
|
||||
|
|
@ -371,10 +371,10 @@ def build_sequence(
|
|||
|
||||
if not sequence:
|
||||
# Create a Sequence
|
||||
sequence = hiero.core.Sequence(otio_timeline.name or 'OTIOSequence')
|
||||
sequence = hiero.core.Sequence(otio_timeline.name or "OTIOSequence")
|
||||
|
||||
# Set sequence settings from otio timeline if available
|
||||
if hasattr(otio_timeline, 'global_start_time'):
|
||||
if hasattr(otio_timeline, "global_start_time"):
|
||||
if otio_timeline.global_start_time:
|
||||
start_time = otio_timeline.global_start_time
|
||||
sequence.setFramerate(start_time.rate)
|
||||
|
|
@ -414,7 +414,7 @@ def build_sequence(
|
|||
if isinstance(otio_clip, otio.schema.Stack):
|
||||
bar = hiero.ui.mainWindow().statusBar()
|
||||
bar.showMessage(
|
||||
'Nested sequences are created separately.',
|
||||
"Nested sequences are created separately.",
|
||||
timeout=3000
|
||||
)
|
||||
build_sequence(otio_clip, project, otio_track.kind)
|
||||
|
|
@ -9,19 +9,19 @@ import hiero.core
|
|||
|
||||
import PySide2.QtWidgets as qw
|
||||
|
||||
from openpype.hosts.hiero.otio.hiero_import import load_otio
|
||||
from openpype.hosts.hiero.api.otio.hiero_import import load_otio
|
||||
|
||||
|
||||
class OTIOProjectSelect(qw.QDialog):
|
||||
|
||||
def __init__(self, projects, *args, **kwargs):
|
||||
super(OTIOProjectSelect, self).__init__(*args, **kwargs)
|
||||
self.setWindowTitle('Please select active project')
|
||||
self.setWindowTitle("Please select active project")
|
||||
self.layout = qw.QVBoxLayout()
|
||||
|
||||
self.label = qw.QLabel(
|
||||
'Unable to determine which project to import sequence to.\n'
|
||||
'Please select one.'
|
||||
"Unable to determine which project to import sequence to.\n"
|
||||
"Please select one."
|
||||
)
|
||||
self.layout.addWidget(self.label)
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ def get_sequence(view):
|
|||
|
||||
elif isinstance(view, hiero.ui.BinView):
|
||||
for item in view.selection():
|
||||
if not hasattr(item, 'acitveItem'):
|
||||
if not hasattr(item, "acitveItem"):
|
||||
continue
|
||||
|
||||
if isinstance(item.activeItem(), hiero.core.Sequence):
|
||||
|
|
@ -57,13 +57,13 @@ def get_sequence(view):
|
|||
def OTIO_menu_action(event):
|
||||
# Menu actions
|
||||
otio_import_action = hiero.ui.createMenuAction(
|
||||
'Import OTIO...',
|
||||
"Import OTIO...",
|
||||
open_otio_file,
|
||||
icon=None
|
||||
)
|
||||
|
||||
otio_add_track_action = hiero.ui.createMenuAction(
|
||||
'New Track(s) from OTIO...',
|
||||
"New Track(s) from OTIO...",
|
||||
open_otio_file,
|
||||
icon=None
|
||||
)
|
||||
|
|
@ -80,19 +80,19 @@ def OTIO_menu_action(event):
|
|||
otio_add_track_action.setEnabled(True)
|
||||
|
||||
for action in event.menu.actions():
|
||||
if action.text() == 'Import':
|
||||
if action.text() == "Import":
|
||||
action.menu().addAction(otio_import_action)
|
||||
action.menu().addAction(otio_add_track_action)
|
||||
|
||||
elif action.text() == 'New Track':
|
||||
elif action.text() == "New Track":
|
||||
action.menu().addAction(otio_add_track_action)
|
||||
|
||||
|
||||
def open_otio_file():
|
||||
files = hiero.ui.openFileBrowser(
|
||||
caption='Please select an OTIO file of choice',
|
||||
pattern='*.otio',
|
||||
requiredExtension='.otio'
|
||||
caption="Please select an OTIO file of choice",
|
||||
pattern="*.otio",
|
||||
requiredExtension=".otio"
|
||||
)
|
||||
|
||||
selection = None
|
||||
|
|
@ -117,7 +117,7 @@ def open_otio_file():
|
|||
else:
|
||||
bar = hiero.ui.mainWindow().statusBar()
|
||||
bar.showMessage(
|
||||
'OTIO Import aborted by user',
|
||||
"OTIO Import aborted by user",
|
||||
timeout=3000
|
||||
)
|
||||
return
|
||||
|
|
@ -10,15 +10,15 @@ except:
|
|||
|
||||
|
||||
def setPosterFrame(posterFrame=.5):
|
||||
'''
|
||||
"""
|
||||
Update the poster frame of the given clipItmes
|
||||
posterFrame = .5 uses the centre frame, a value of 0 uses the first frame, a value of 1 uses the last frame
|
||||
'''
|
||||
"""
|
||||
view = hiero.ui.activeView()
|
||||
|
||||
selectedBinItems = view.selection()
|
||||
selectedClipItems = [(item.activeItem()
|
||||
if hasattr(item, 'activeItem') else item)
|
||||
if hasattr(item, "activeItem") else item)
|
||||
for item in selectedBinItems]
|
||||
|
||||
for clip in selectedClipItems:
|
||||
|
|
@ -65,13 +65,9 @@ def open_file(filepath):
|
|||
|
||||
def current_file():
|
||||
current_file = hiero.core.projects()[-1].path()
|
||||
normalised = os.path.normpath(current_file)
|
||||
|
||||
# Unsaved current file
|
||||
if normalised == "":
|
||||
if not current_file:
|
||||
return None
|
||||
|
||||
return normalised
|
||||
return os.path.normpath(current_file)
|
||||
|
||||
|
||||
def work_root(session):
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import pyblish
|
||||
import openpype
|
||||
from openpype.hosts.hiero import api as phiero
|
||||
from openpype.hosts.hiero.otio import hiero_export
|
||||
from openpype.hosts.hiero.api.otio import hiero_export
|
||||
import hiero
|
||||
|
||||
from compiler.ast import flatten
|
||||
|
||||
# # developer reload modules
|
||||
from pprint import pformat
|
||||
|
||||
|
|
@ -339,10 +337,10 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
|
|||
continue
|
||||
|
||||
track_index = track.trackIndex()
|
||||
_sub_track_items = flatten(track.subTrackItems())
|
||||
_sub_track_items = phiero.flatten(track.subTrackItems())
|
||||
|
||||
# continue only if any subtrack items are collected
|
||||
if len(_sub_track_items) < 1:
|
||||
if not list(_sub_track_items):
|
||||
continue
|
||||
|
||||
enabled_sti = []
|
||||
|
|
@ -357,7 +355,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
|
|||
enabled_sti.append(_sti)
|
||||
|
||||
# continue only if any subtrack items are collected
|
||||
if len(enabled_sti) < 1:
|
||||
if not enabled_sti:
|
||||
continue
|
||||
|
||||
# add collection of subtrackitems to dict
|
||||
|
|
@ -371,7 +369,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
|
|||
Returns list of Clip's hiero.core.Annotation
|
||||
"""
|
||||
annotations = []
|
||||
subTrackItems = flatten(clip.subTrackItems())
|
||||
subTrackItems = phiero.flatten(clip.subTrackItems())
|
||||
annotations += [item for item in subTrackItems if isinstance(
|
||||
item, hiero.core.Annotation)]
|
||||
return annotations
|
||||
|
|
@ -382,7 +380,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
|
|||
Returns list of Clip's hiero.core.SubTrackItem
|
||||
"""
|
||||
subtracks = []
|
||||
subTrackItems = flatten(clip.parent().subTrackItems())
|
||||
subTrackItems = phiero.flatten(clip.parent().subTrackItems())
|
||||
for item in subTrackItems:
|
||||
if "TimeWarp" in item.name():
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import hiero.ui
|
|||
from openpype.hosts.hiero import api as phiero
|
||||
from avalon import api as avalon
|
||||
from pprint import pformat
|
||||
from openpype.hosts.hiero.otio import hiero_export
|
||||
from openpype.hosts.hiero.api.otio import hiero_export
|
||||
from Qt.QtGui import QPixmap
|
||||
import tempfile
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from pyblish import api
|
||||
import hiero
|
||||
import math
|
||||
from openpype.hosts.hiero.otio.hiero_export import create_otio_time_range
|
||||
from openpype.hosts.hiero.api.otio.hiero_export import create_otio_time_range
|
||||
|
||||
class PrecollectRetime(api.InstancePlugin):
|
||||
"""Calculate Retiming of selected track items."""
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
from OTIOExportTask import OTIOExportTask
|
||||
from OTIOExportUI import OTIOExportUI
|
||||
|
||||
__all__ = [
|
||||
'OTIOExportTask',
|
||||
'OTIOExportUI'
|
||||
]
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
"""Puts the selection project into 'hiero.selection'"""
|
||||
|
||||
import hiero
|
||||
|
||||
|
||||
def selectionChanged(event):
|
||||
hiero.selection = event.sender.selection()
|
||||
|
||||
hiero.core.events.registerInterest('kSelectionChanged', selectionChanged)
|
||||
|
|
@ -54,6 +54,10 @@ def install():
|
|||
''' Installing all requarements for Nuke host
|
||||
'''
|
||||
|
||||
# remove all registred callbacks form avalon.nuke
|
||||
from avalon import pipeline
|
||||
pipeline._registered_event_handlers.clear()
|
||||
|
||||
log.info("Registering Nuke plug-ins..")
|
||||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH)
|
||||
|
|
@ -62,6 +66,7 @@ def install():
|
|||
|
||||
# Register Avalon event for workfiles loading.
|
||||
avalon.api.on("workio.open_file", lib.check_inventory_versions)
|
||||
avalon.api.on("taskChanged", menu.change_context_label)
|
||||
|
||||
pyblish.api.register_callback(
|
||||
"instanceToggled", on_pyblish_instance_toggled)
|
||||
|
|
|
|||
|
|
@ -1,101 +1,128 @@
|
|||
import os
|
||||
import nuke
|
||||
from avalon.api import Session
|
||||
from avalon.nuke.pipeline import get_main_window
|
||||
|
||||
from .lib import WorkfileSettings
|
||||
from openpype.api import Logger, BuildWorkfile, get_current_project_settings
|
||||
from openpype.tools.utils import host_tools
|
||||
|
||||
from avalon.nuke.pipeline import get_main_window
|
||||
|
||||
log = Logger().get_logger(__name__)
|
||||
|
||||
menu_label = os.environ["AVALON_LABEL"]
|
||||
context_label = None
|
||||
|
||||
|
||||
def install():
|
||||
main_window = get_main_window()
|
||||
def change_context_label(*args):
|
||||
global context_label
|
||||
menubar = nuke.menu("Nuke")
|
||||
menu = menubar.findItem(menu_label)
|
||||
|
||||
# replace reset resolution from avalon core to pype's
|
||||
name = "Work Files..."
|
||||
rm_item = [
|
||||
(i, item) for i, item in enumerate(menu.items()) if name in item.name()
|
||||
][0]
|
||||
|
||||
log.debug("Changing Item: {}".format(rm_item))
|
||||
|
||||
menu.removeItem(rm_item[1].name())
|
||||
menu.addCommand(
|
||||
name,
|
||||
lambda: host_tools.show_workfiles(parent=main_window),
|
||||
index=2
|
||||
label = "{0}, {1}".format(
|
||||
os.environ["AVALON_ASSET"], os.environ["AVALON_TASK"]
|
||||
)
|
||||
menu.addSeparator(index=3)
|
||||
# replace reset resolution from avalon core to pype's
|
||||
name = "Reset Resolution"
|
||||
new_name = "Set Resolution"
|
||||
|
||||
rm_item = [
|
||||
(i, item) for i, item in enumerate(menu.items()) if name in item.name()
|
||||
(i, item) for i, item in enumerate(menu.items())
|
||||
if context_label in item.name()
|
||||
][0]
|
||||
|
||||
log.debug("Changing Item: {}".format(rm_item))
|
||||
# rm_item[1].setEnabled(False)
|
||||
menu.removeItem(rm_item[1].name())
|
||||
menu.addCommand(
|
||||
new_name,
|
||||
lambda: WorkfileSettings().reset_resolution(),
|
||||
|
||||
context_action = menu.addCommand(
|
||||
label,
|
||||
index=(rm_item[0])
|
||||
)
|
||||
context_action.setEnabled(False)
|
||||
|
||||
# replace reset frame range from avalon core to pype's
|
||||
name = "Reset Frame Range"
|
||||
new_name = "Set Frame Range"
|
||||
rm_item = [
|
||||
(i, item) for i, item in enumerate(menu.items()) if name in item.name()
|
||||
][0]
|
||||
log.debug("Changing Item: {}".format(rm_item))
|
||||
# rm_item[1].setEnabled(False)
|
||||
menu.removeItem(rm_item[1].name())
|
||||
menu.addCommand(
|
||||
new_name,
|
||||
lambda: WorkfileSettings().reset_frame_range_handles(),
|
||||
index=(rm_item[0])
|
||||
)
|
||||
log.info("Task label changed from `{}` to `{}`".format(
|
||||
context_label, label))
|
||||
|
||||
# add colorspace menu item
|
||||
name = "Set Colorspace"
|
||||
menu.addCommand(
|
||||
name, lambda: WorkfileSettings().set_colorspace()
|
||||
)
|
||||
log.debug("Adding menu item: {}".format(name))
|
||||
context_label = label
|
||||
|
||||
# add item that applies all setting above
|
||||
name = "Apply All Settings"
|
||||
menu.addCommand(
|
||||
name,
|
||||
lambda: WorkfileSettings().set_context_settings()
|
||||
|
||||
|
||||
def install():
|
||||
from openpype.hosts.nuke.api import reload_config
|
||||
|
||||
global context_label
|
||||
|
||||
# uninstall original avalon menu
|
||||
uninstall()
|
||||
|
||||
main_window = get_main_window()
|
||||
menubar = nuke.menu("Nuke")
|
||||
menu = menubar.addMenu(menu_label)
|
||||
|
||||
label = "{0}, {1}".format(
|
||||
os.environ["AVALON_ASSET"], os.environ["AVALON_TASK"]
|
||||
)
|
||||
log.debug("Adding menu item: {}".format(name))
|
||||
context_label = label
|
||||
context_action = menu.addCommand(label)
|
||||
context_action.setEnabled(False)
|
||||
|
||||
menu.addSeparator()
|
||||
|
||||
# add workfile builder menu item
|
||||
name = "Build Workfile"
|
||||
menu.addCommand(
|
||||
name, lambda: BuildWorkfile().process()
|
||||
"Work Files...",
|
||||
lambda: host_tools.show_workfiles(parent=main_window)
|
||||
)
|
||||
|
||||
menu.addSeparator()
|
||||
menu.addCommand(
|
||||
"Create...",
|
||||
lambda: host_tools.show_creator(parent=main_window)
|
||||
)
|
||||
menu.addCommand(
|
||||
"Load...",
|
||||
lambda: host_tools.show_loader(
|
||||
parent=main_window,
|
||||
use_context=True
|
||||
)
|
||||
)
|
||||
menu.addCommand(
|
||||
"Publish...",
|
||||
lambda: host_tools.show_publish(parent=main_window)
|
||||
)
|
||||
menu.addCommand(
|
||||
"Manage...",
|
||||
lambda: host_tools.show_scene_inventory(parent=main_window)
|
||||
)
|
||||
|
||||
menu.addSeparator()
|
||||
menu.addCommand(
|
||||
"Set Resolution",
|
||||
lambda: WorkfileSettings().reset_resolution()
|
||||
)
|
||||
menu.addCommand(
|
||||
"Set Frame Range",
|
||||
lambda: WorkfileSettings().reset_frame_range_handles()
|
||||
)
|
||||
menu.addCommand(
|
||||
"Set Colorspace",
|
||||
lambda: WorkfileSettings().set_colorspace()
|
||||
)
|
||||
menu.addCommand(
|
||||
"Apply All Settings",
|
||||
lambda: WorkfileSettings().set_context_settings()
|
||||
)
|
||||
|
||||
menu.addSeparator()
|
||||
menu.addCommand(
|
||||
"Build Workfile",
|
||||
lambda: BuildWorkfile().process()
|
||||
)
|
||||
log.debug("Adding menu item: {}".format(name))
|
||||
|
||||
# Add experimental tools action
|
||||
menu.addSeparator()
|
||||
menu.addCommand(
|
||||
"Experimental tools...",
|
||||
lambda: host_tools.show_experimental_tools_dialog(parent=main_window)
|
||||
)
|
||||
|
||||
# add reload pipeline only in debug mode
|
||||
if bool(os.getenv("NUKE_DEBUG")):
|
||||
menu.addSeparator()
|
||||
menu.addCommand("Reload Pipeline", reload_config)
|
||||
|
||||
# adding shortcuts
|
||||
add_shortcuts_from_presets()
|
||||
|
||||
|
|
|
|||
|
|
@ -116,16 +116,7 @@ class LoadClip(plugin.NukeLoader):
|
|||
"Representation id `{}` is failing to load".format(repr_id))
|
||||
return
|
||||
|
||||
name_data = {
|
||||
"asset": repr_cont["asset"],
|
||||
"subset": repr_cont["subset"],
|
||||
"representation": context["representation"]["name"],
|
||||
"ext": repr_cont["representation"],
|
||||
"id": context["representation"]["_id"],
|
||||
"class_name": self.__class__.__name__
|
||||
}
|
||||
|
||||
read_name = self.node_name_template.format(**name_data)
|
||||
read_name = self._get_node_name(context["representation"])
|
||||
|
||||
# Create the Loader with the filename path set
|
||||
read_node = nuke.createNode(
|
||||
|
|
@ -143,7 +134,7 @@ class LoadClip(plugin.NukeLoader):
|
|||
elif iio_colorspace is not None:
|
||||
read_node["colorspace"].setValue(iio_colorspace)
|
||||
|
||||
self.set_range_to_node(read_node, first, last, start_at_workfile)
|
||||
self._set_range_to_node(read_node, first, last, start_at_workfile)
|
||||
|
||||
# add additional metadata from the version to imprint Avalon knob
|
||||
add_keys = ["frameStart", "frameEnd",
|
||||
|
|
@ -171,7 +162,7 @@ class LoadClip(plugin.NukeLoader):
|
|||
data=data_imprint)
|
||||
|
||||
if version_data.get("retime", None):
|
||||
self.make_retimes(read_node, version_data)
|
||||
self._make_retimes(read_node, version_data)
|
||||
|
||||
self.set_as_member(read_node)
|
||||
|
||||
|
|
@ -230,6 +221,9 @@ class LoadClip(plugin.NukeLoader):
|
|||
"Representation id `{}` is failing to load".format(repr_id))
|
||||
return
|
||||
|
||||
read_name = self._get_node_name(representation)
|
||||
|
||||
read_node["name"].setValue(read_name)
|
||||
read_node["file"].setValue(file)
|
||||
|
||||
# to avoid multiple undo steps for rest of process
|
||||
|
|
@ -242,7 +236,7 @@ class LoadClip(plugin.NukeLoader):
|
|||
elif iio_colorspace is not None:
|
||||
read_node["colorspace"].setValue(iio_colorspace)
|
||||
|
||||
self.set_range_to_node(read_node, first, last, start_at_workfile)
|
||||
self._set_range_to_node(read_node, first, last, start_at_workfile)
|
||||
|
||||
updated_dict = {
|
||||
"representation": str(representation["_id"]),
|
||||
|
|
@ -279,21 +273,12 @@ class LoadClip(plugin.NukeLoader):
|
|||
self.log.info("udated to version: {}".format(version.get("name")))
|
||||
|
||||
if version_data.get("retime", None):
|
||||
self.make_retimes(read_node, version_data)
|
||||
self._make_retimes(read_node, version_data)
|
||||
else:
|
||||
self.clear_members(read_node)
|
||||
|
||||
self.set_as_member(read_node)
|
||||
|
||||
def set_range_to_node(self, read_node, first, last, start_at_workfile):
|
||||
read_node['origfirst'].setValue(int(first))
|
||||
read_node['first'].setValue(int(first))
|
||||
read_node['origlast'].setValue(int(last))
|
||||
read_node['last'].setValue(int(last))
|
||||
|
||||
# set start frame depending on workfile or version
|
||||
self.loader_shift(read_node, start_at_workfile)
|
||||
|
||||
def remove(self, container):
|
||||
|
||||
from avalon.nuke import viewer_update_and_undo_stop
|
||||
|
|
@ -307,7 +292,16 @@ class LoadClip(plugin.NukeLoader):
|
|||
for member in members:
|
||||
nuke.delete(member)
|
||||
|
||||
def make_retimes(self, parent_node, version_data):
|
||||
def _set_range_to_node(self, read_node, first, last, start_at_workfile):
|
||||
read_node['origfirst'].setValue(int(first))
|
||||
read_node['first'].setValue(int(first))
|
||||
read_node['origlast'].setValue(int(last))
|
||||
read_node['last'].setValue(int(last))
|
||||
|
||||
# set start frame depending on workfile or version
|
||||
self._loader_shift(read_node, start_at_workfile)
|
||||
|
||||
def _make_retimes(self, parent_node, version_data):
|
||||
''' Create all retime and timewarping nodes with coppied animation '''
|
||||
speed = version_data.get('speed', 1)
|
||||
time_warp_nodes = version_data.get('timewarps', [])
|
||||
|
|
@ -360,7 +354,7 @@ class LoadClip(plugin.NukeLoader):
|
|||
for i, n in enumerate(dependent_nodes):
|
||||
last_node.setInput(i, n)
|
||||
|
||||
def loader_shift(self, read_node, workfile_start=False):
|
||||
def _loader_shift(self, read_node, workfile_start=False):
|
||||
""" Set start frame of read node to a workfile start
|
||||
|
||||
Args:
|
||||
|
|
@ -371,3 +365,17 @@ class LoadClip(plugin.NukeLoader):
|
|||
if workfile_start:
|
||||
read_node['frame_mode'].setValue("start at")
|
||||
read_node['frame'].setValue(str(self.script_start))
|
||||
|
||||
def _get_node_name(self, representation):
|
||||
|
||||
repr_cont = representation["context"]
|
||||
name_data = {
|
||||
"asset": repr_cont["asset"],
|
||||
"subset": repr_cont["subset"],
|
||||
"representation": representation["name"],
|
||||
"ext": repr_cont["representation"],
|
||||
"id": representation["_id"],
|
||||
"class_name": self.__class__.__name__
|
||||
}
|
||||
|
||||
return self.node_name_template.format(**name_data)
|
||||
|
|
@ -138,7 +138,7 @@ class CollectTVPaintInstances(pyblish.api.ContextPlugin):
|
|||
"family": "render"
|
||||
}
|
||||
subset_name = get_subset_name_with_asset_doc(
|
||||
self.render_pass_family,
|
||||
self.render_layer_family,
|
||||
variant,
|
||||
task_name,
|
||||
asset_doc,
|
||||
|
|
@ -223,7 +223,7 @@ class CollectTVPaintInstances(pyblish.api.ContextPlugin):
|
|||
"name": subset_name,
|
||||
"subset": subset_name,
|
||||
"label": subset_name,
|
||||
"family": self.render_pass_family,
|
||||
"family": "render",
|
||||
# Add `review` family for thumbnail integration
|
||||
"families": [self.render_pass_family, "review"],
|
||||
"representations": [],
|
||||
|
|
@ -239,9 +239,9 @@ class CollectTVPaintInstances(pyblish.api.ContextPlugin):
|
|||
"name": subset_name,
|
||||
"subset": subset_name,
|
||||
"label": subset_name,
|
||||
"family": self.render_pass_family,
|
||||
"family": "render",
|
||||
# Add `review` family for thumbnail integration
|
||||
"families": [self.render_pass_family, "review"],
|
||||
"families": [self.render_layer_family, "review"],
|
||||
"representations": [],
|
||||
"layers": layers,
|
||||
"stagingDir": staging_dir
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import pyblish.api
|
|||
class CollectDefaultRRPath(pyblish.api.ContextPlugin):
|
||||
"""Collect default Royal Render path."""
|
||||
|
||||
order = pyblish.api.CollectorOrder + 0.01
|
||||
order = pyblish.api.CollectorOrder
|
||||
label = "Default Royal Render Path"
|
||||
|
||||
def process(self, context):
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import pyblish.api
|
|||
class CollectRRPathFromInstance(pyblish.api.InstancePlugin):
|
||||
"""Collect RR Path from instance."""
|
||||
|
||||
order = pyblish.api.CollectorOrder
|
||||
order = pyblish.api.CollectorOrder + 0.01
|
||||
label = "Royal Render Path from the Instance"
|
||||
families = ["rendering"]
|
||||
|
||||
|
|
@ -38,8 +38,8 @@ class CollectRRPathFromInstance(pyblish.api.InstancePlugin):
|
|||
if k in default_servers
|
||||
}
|
||||
|
||||
except AttributeError:
|
||||
# Handle situation were we had only one url for deadline.
|
||||
except (AttributeError, KeyError):
|
||||
# Handle situation were we had only one url for royal render.
|
||||
return render_instance.context.data["defaultRRPath"]
|
||||
|
||||
return rr_servers[
|
||||
|
|
|
|||
|
|
@ -168,9 +168,6 @@ class CollectSequencesFromJob(pyblish.api.ContextPlugin):
|
|||
start = data.get("frameStart", indices[0])
|
||||
end = data.get("frameEnd", indices[-1])
|
||||
|
||||
# root = os.path.normpath(root)
|
||||
# self.log.info("Source: {}}".format(data.get("source", "")))
|
||||
|
||||
ext = list(collection)[0].split('.')[-1]
|
||||
|
||||
instance.data.update({
|
||||
|
|
@ -195,6 +192,8 @@ class CollectSequencesFromJob(pyblish.api.ContextPlugin):
|
|||
'name': ext,
|
||||
'ext': '{}'.format(ext),
|
||||
'files': list(collection),
|
||||
"frameStart": start,
|
||||
"frameEnd": end,
|
||||
"stagingDir": root,
|
||||
"anatomy_template": "render",
|
||||
"fps": fps,
|
||||
|
|
|
|||
|
|
@ -38,28 +38,20 @@ class OpenPypeContextSelector:
|
|||
os.environ.get("PROGRAMFILES"),
|
||||
"OpenPype", "openpype_console.exe"
|
||||
)
|
||||
if os.path.exists(op_path):
|
||||
print(" - found OpenPype installation {}".format(op_path))
|
||||
else:
|
||||
if not os.path.exists(op_path):
|
||||
# try to find in user local context
|
||||
op_path = os.path.join(
|
||||
os.environ.get("LOCALAPPDATA"),
|
||||
"Programs",
|
||||
"OpenPype", "openpype_console.exe"
|
||||
)
|
||||
if os.path.exists(op_path):
|
||||
print(
|
||||
" - found OpenPype installation {}".format(
|
||||
op_path))
|
||||
else:
|
||||
if not os.path.exists(op_path):
|
||||
raise Exception("Error: OpenPype was not found.")
|
||||
|
||||
self.openpype_root = op_path
|
||||
op_path = os.path.dirname(op_path)
|
||||
print(" - found OpenPype installation {}".format(op_path))
|
||||
|
||||
# TODO: this should try to find metadata file. Either using
|
||||
# jobs custom attributes or using environment variable
|
||||
# or just using plain existence of file.
|
||||
# self.context = self._process_metadata_file()
|
||||
self.openpype_root = op_path
|
||||
|
||||
def _process_metadata_file(self):
|
||||
"""Find and process metadata file.
|
||||
|
|
@ -86,8 +78,8 @@ class OpenPypeContextSelector:
|
|||
automatically, no UI will be show and publishing will directly
|
||||
proceed.
|
||||
"""
|
||||
if not self.context:
|
||||
self.show()
|
||||
if not self.context and not self.show():
|
||||
return
|
||||
|
||||
self.context["user"] = self.job.userName
|
||||
self.run_publish()
|
||||
|
|
@ -120,10 +112,15 @@ class OpenPypeContextSelector:
|
|||
not self.context.get("asset") or \
|
||||
not self.context.get("task"):
|
||||
self._show_rr_warning("Context selection failed.")
|
||||
return
|
||||
return False
|
||||
|
||||
# self.context["app_name"] = self.job.renderer.name
|
||||
# there should be mapping between OpenPype and Royal Render
|
||||
# app names and versions, but since app_name is not used
|
||||
# currently down the line (but it is required by OP publish command
|
||||
# right now).
|
||||
self.context["app_name"] = "maya/2020"
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _show_rr_warning(text):
|
||||
|
|
|
|||
|
|
@ -171,8 +171,7 @@ class CollectOcioSubsetResources(pyblish.api.InstancePlugin):
|
|||
instance.data["representations"].append(repre)
|
||||
self.log.debug(">>>>>>>> {}".format(repre))
|
||||
|
||||
import pprint
|
||||
self.log.debug(pprint.pformat(instance.data))
|
||||
self.log.debug(instance.data)
|
||||
|
||||
def _create_representation(self, start, end, **kwargs):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -505,7 +505,7 @@
|
|||
"environment": {}
|
||||
},
|
||||
"__dynamic_keys_labels__": {
|
||||
"13-0": "13.0 (Testing only)",
|
||||
"13-0": "13.0",
|
||||
"12-2": "12.2",
|
||||
"12-0": "12.0",
|
||||
"11-3": "11.3",
|
||||
|
|
@ -642,7 +642,7 @@
|
|||
"environment": {}
|
||||
},
|
||||
"__dynamic_keys_labels__": {
|
||||
"13-0": "13.0 (Testing only)",
|
||||
"13-0": "13.0",
|
||||
"12-2": "12.2",
|
||||
"12-0": "12.0",
|
||||
"11-3": "11.3",
|
||||
|
|
|
|||
|
|
@ -154,7 +154,8 @@ class HostsEnumEntity(BaseEnumEntity):
|
|||
"resolve",
|
||||
"tvpaint",
|
||||
"unreal",
|
||||
"standalonepublisher"
|
||||
"standalonepublisher",
|
||||
"webpublisher"
|
||||
]
|
||||
|
||||
def _item_initialization(self):
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package declaring Pype version."""
|
||||
__version__ = "3.7.0-nightly.4"
|
||||
__version__ = "3.7.0-nightly.5"
|
||||
|
|
|
|||
20
poetry.lock
generated
|
|
@ -219,16 +219,16 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
|||
|
||||
[[package]]
|
||||
name = "clique"
|
||||
version = "1.5.0"
|
||||
version = "1.6.1"
|
||||
description = "Manage collections with common numerical component"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
python-versions = ">=2.7, <4.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["lowdown (>=0.1.0,<1)", "pytest (>=2.3.5,<3)", "pytest-cov (>=2,<3)", "pytest-runner (>=2.7,<3)", "sphinx (>=1.2.2,<2)", "sphinx-rtd-theme (>=0.1.6,<1)"]
|
||||
doc = ["lowdown (>=0.1.0,<1)", "sphinx (>=1.2.2,<2)", "sphinx-rtd-theme (>=0.1.6,<1)"]
|
||||
test = ["pytest (>=2.3.5,<3)", "pytest-cov (>=2,<3)", "pytest-runner (>=2.7,<3)"]
|
||||
dev = ["sphinx (>=2,<4)", "sphinx-rtd-theme (>=0.1.6,<1)", "lowdown (>=0.2.0,<1)", "pytest-runner (>=2.7,<3)", "pytest (>=2.3.5,<5)", "pytest-cov (>=2,<3)"]
|
||||
doc = ["sphinx (>=2,<4)", "sphinx-rtd-theme (>=0.1.6,<1)", "lowdown (>=0.2.0,<1)"]
|
||||
test = ["pytest-runner (>=2.7,<3)", "pytest (>=2.3.5,<5)", "pytest-cov (>=2,<3)"]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
|
|
@ -1580,7 +1580,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes
|
|||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "3.7.*"
|
||||
content-hash = "fb6db80d126fe7ef2d1d06d0381b6d11445d6d3e54b33585f6b0a0b6b0b9d372"
|
||||
content-hash = "877c1c6292735f495d915fc6aa85450eb20fc63f266a9c6bf7ba1125af3579a5"
|
||||
|
||||
[metadata.files]
|
||||
acre = []
|
||||
|
|
@ -1749,8 +1749,8 @@ click = [
|
|||
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
|
||||
]
|
||||
clique = [
|
||||
{file = "clique-1.5.0-py2-none-any.whl", hash = "sha256:77efbf5d99a398a50ca4591373def45c9c70fb43232cdc32f521cf5257ce4330"},
|
||||
{file = "clique-1.5.0.tar.gz", hash = "sha256:c34a4eac30187a5b7d75bc8cf600ddc50ceef50a423772a4c96f1dc8440af5fa"},
|
||||
{file = "clique-1.6.1-py2.py3-none-any.whl", hash = "sha256:8619774fa035661928dd8c93cd805acf2d42533ccea1b536c09815ed426c9858"},
|
||||
{file = "clique-1.6.1.tar.gz", hash = "sha256:90165c1cf162d4dd1baef83ceaa1afc886b453e379094fa5b60ea470d1733e66"},
|
||||
]
|
||||
colorama = [
|
||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||
|
|
@ -2180,9 +2180,13 @@ protobuf = [
|
|||
{file = "protobuf-3.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2ae692bb6d1992afb6b74348e7bb648a75bb0d3565a3f5eea5bec8f62bd06d87"},
|
||||
{file = "protobuf-3.17.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:99938f2a2d7ca6563c0ade0c5ca8982264c484fdecf418bd68e880a7ab5730b1"},
|
||||
{file = "protobuf-3.17.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6902a1e4b7a319ec611a7345ff81b6b004b36b0d2196ce7a748b3493da3d226d"},
|
||||
{file = "protobuf-3.17.3-cp38-cp38-win32.whl", hash = "sha256:59e5cf6b737c3a376932fbfb869043415f7c16a0cf176ab30a5bbc419cd709c1"},
|
||||
{file = "protobuf-3.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ebcb546f10069b56dc2e3da35e003a02076aaa377caf8530fe9789570984a8d2"},
|
||||
{file = "protobuf-3.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ffbd23640bb7403574f7aff8368e2aeb2ec9a5c6306580be48ac59a6bac8bde"},
|
||||
{file = "protobuf-3.17.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:26010f693b675ff5a1d0e1bdb17689b8b716a18709113288fead438703d45539"},
|
||||
{file = "protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e76d9686e088fece2450dbc7ee905f9be904e427341d289acbe9ad00b78ebd47"},
|
||||
{file = "protobuf-3.17.3-cp39-cp39-win32.whl", hash = "sha256:a38bac25f51c93e4be4092c88b2568b9f407c27217d3dd23c7a57fa522a17554"},
|
||||
{file = "protobuf-3.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:85d6303e4adade2827e43c2b54114d9a6ea547b671cb63fafd5011dc47d0e13d"},
|
||||
{file = "protobuf-3.17.3-py2.py3-none-any.whl", hash = "sha256:2bfb815216a9cd9faec52b16fd2bfa68437a44b67c56bee59bc3926522ecb04e"},
|
||||
{file = "protobuf-3.17.3.tar.gz", hash = "sha256:72804ea5eaa9c22a090d2803813e280fb273b62d5ae497aaf3553d141c4fdd7b"},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "OpenPype"
|
||||
version = "3.7.0-nightly.4" # OpenPype
|
||||
version = "3.7.0-nightly.5" # OpenPype
|
||||
description = "Open VFX and Animation pipeline with support."
|
||||
authors = ["OpenPype Team <info@openpype.io>"]
|
||||
license = "MIT License"
|
||||
|
|
@ -36,7 +36,7 @@ opentimelineio = { version = "0.14.0.dev1", source = "openpype" }
|
|||
appdirs = "^1.4.3"
|
||||
blessed = "^1.17" # openpype terminal formatting
|
||||
coolname = "*"
|
||||
clique = "1.5.*"
|
||||
clique = "1.6.*"
|
||||
Click = "^7"
|
||||
dnspython = "^2.1.0"
|
||||
ftrack-python-api = "2.0.*"
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 9499f6517a1ff2d3bf94c5d34c0aece146734760
|
||||
Subproject commit 85c656fcf9beb06ab92d3d6ce47f6472cf88df54
|
||||