mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
Merge branch 'develop' into bugfix/unreal-on-linux
This commit is contained in:
commit
afc48fe7a5
15 changed files with 302 additions and 122 deletions
54
CHANGELOG.md
54
CHANGELOG.md
|
|
@ -1,8 +1,59 @@
|
|||
# Changelog
|
||||
|
||||
## [3.2.0-nightly.1](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/2.18.3...HEAD)
|
||||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- Autoupdate launcher [\#1725](https://github.com/pypeclub/OpenPype/pull/1725)
|
||||
- Subset template and TVPaint subset template docs [\#1717](https://github.com/pypeclub/OpenPype/pull/1717)
|
||||
- Overscan color extract review [\#1701](https://github.com/pypeclub/OpenPype/pull/1701)
|
||||
- Nuke: Prerender Frame Range by default [\#1699](https://github.com/pypeclub/OpenPype/pull/1699)
|
||||
- Smoother edges of color triangle [\#1695](https://github.com/pypeclub/OpenPype/pull/1695)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
- TVPaint use layer name for default variant [\#1724](https://github.com/pypeclub/OpenPype/pull/1724)
|
||||
- Default subset template for TVPaint review and workfile families [\#1716](https://github.com/pypeclub/OpenPype/pull/1716)
|
||||
- Maya: Extract review hotfix [\#1714](https://github.com/pypeclub/OpenPype/pull/1714)
|
||||
- Settings: Imageio improving granularity [\#1711](https://github.com/pypeclub/OpenPype/pull/1711)
|
||||
|
||||
## [2.18.3](https://github.com/pypeclub/OpenPype/tree/2.18.3) (2021-06-18)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/2.18.2...2.18.3)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
- Remove publish highlight icon in AE [\#1664](https://github.com/pypeclub/OpenPype/pull/1664)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Sync main 2.x back to 2.x develop [\#1715](https://github.com/pypeclub/OpenPype/pull/1715)
|
||||
- global: removing obsolete ftrack validator plugin [\#1710](https://github.com/pypeclub/OpenPype/pull/1710)
|
||||
- \#683 - Validate frame range in Standalone Publisher [\#1680](https://github.com/pypeclub/OpenPype/pull/1680)
|
||||
- Maya: Split model content validator [\#1654](https://github.com/pypeclub/OpenPype/pull/1654)
|
||||
|
||||
## [2.18.2](https://github.com/pypeclub/OpenPype/tree/2.18.2) (2021-06-16)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.1.0...2.18.2)
|
||||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- StandalonePublisher: adding exception for adding `delete` tag to repre [\#1650](https://github.com/pypeclub/OpenPype/pull/1650)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
- Maya: Extract review hotfix - 2.x backport [\#1713](https://github.com/pypeclub/OpenPype/pull/1713)
|
||||
- StandalonePublisher: instance data attribute `keepSequence` [\#1668](https://github.com/pypeclub/OpenPype/pull/1668)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- 1698 Nuke: Prerender Frame Range by default [\#1709](https://github.com/pypeclub/OpenPype/pull/1709)
|
||||
|
||||
## [3.1.0](https://github.com/pypeclub/OpenPype/tree/3.1.0) (2021-06-15)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.0.0...3.1.0)
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.1.0-nightly.4...3.1.0)
|
||||
|
||||
**🚀 Enhancements**
|
||||
|
||||
|
|
@ -33,6 +84,7 @@
|
|||
- Fix missing dbm python module [\#1652](https://github.com/pypeclub/OpenPype/pull/1652)
|
||||
- Transparent branches in view on Mac [\#1648](https://github.com/pypeclub/OpenPype/pull/1648)
|
||||
- Add asset on task item [\#1646](https://github.com/pypeclub/OpenPype/pull/1646)
|
||||
- Project manager save and queue [\#1645](https://github.com/pypeclub/OpenPype/pull/1645)
|
||||
- New project anatomy values [\#1644](https://github.com/pypeclub/OpenPype/pull/1644)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
|
|
|||
|
|
@ -58,18 +58,14 @@ class CreateRenderlayer(plugin.Creator):
|
|||
# Get currently selected layers
|
||||
layers_data = lib.layers_data()
|
||||
|
||||
group_ids = set()
|
||||
for layer in layers_data:
|
||||
if layer["selected"]:
|
||||
group_ids.add(layer["group_id"])
|
||||
|
||||
selected_layers = [
|
||||
layer
|
||||
for layer in layers_data
|
||||
if layer["selected"]
|
||||
]
|
||||
# Return layer name if only one is selected
|
||||
if len(group_ids) == 1:
|
||||
group_id = list(group_ids)[0]
|
||||
groups_data = lib.groups_data()
|
||||
for group in groups_data:
|
||||
if group["group_id"] == group_id:
|
||||
return group["name"]
|
||||
if len(selected_layers) == 1:
|
||||
return selected_layers[0]["name"]
|
||||
|
||||
# Use defaults
|
||||
if cls.defaults:
|
||||
|
|
|
|||
|
|
@ -232,6 +232,17 @@
|
|||
],
|
||||
"tasks": [],
|
||||
"template": "{family}{Task}_{Render_layer}_{Render_pass}"
|
||||
},
|
||||
{
|
||||
"families": [
|
||||
"review",
|
||||
"workfile"
|
||||
],
|
||||
"hosts": [
|
||||
"tvpaint"
|
||||
],
|
||||
"tasks": [],
|
||||
"template": "{family}{Task}"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -325,19 +325,59 @@ class ProjectModel(QtGui.QStandardItemModel):
|
|||
|
||||
self.hide_invisible = False
|
||||
self.project_icon = qtawesome.icon("fa.map", color="white")
|
||||
self._project_names = set()
|
||||
|
||||
def refresh(self):
|
||||
self.clear()
|
||||
self.beginResetModel()
|
||||
|
||||
project_names = set()
|
||||
for project_doc in self.get_projects():
|
||||
item = QtGui.QStandardItem(self.project_icon, project_doc["name"])
|
||||
self.appendRow(item)
|
||||
project_names.add(project_doc["name"])
|
||||
|
||||
self.endResetModel()
|
||||
origin_project_names = set(self._project_names)
|
||||
self._project_names = project_names
|
||||
|
||||
project_names_to_remove = origin_project_names - project_names
|
||||
if project_names_to_remove:
|
||||
row_counts = {}
|
||||
continuous = None
|
||||
for row in range(self.rowCount()):
|
||||
index = self.index(row, 0)
|
||||
index_name = index.data(QtCore.Qt.DisplayRole)
|
||||
if index_name in project_names_to_remove:
|
||||
if continuous is None:
|
||||
continuous = row
|
||||
row_counts[continuous] = 0
|
||||
row_counts[continuous] += 1
|
||||
else:
|
||||
continuous = None
|
||||
|
||||
for row in reversed(sorted(row_counts.keys())):
|
||||
count = row_counts[row]
|
||||
self.removeRows(row, count)
|
||||
|
||||
continuous = None
|
||||
row_counts = {}
|
||||
for idx, project_name in enumerate(sorted(project_names)):
|
||||
if project_name in origin_project_names:
|
||||
continuous = None
|
||||
continue
|
||||
|
||||
if continuous is None:
|
||||
continuous = idx
|
||||
row_counts[continuous] = []
|
||||
|
||||
row_counts[continuous].append(project_name)
|
||||
|
||||
for row in reversed(sorted(row_counts.keys())):
|
||||
items = []
|
||||
for project_name in row_counts[row]:
|
||||
item = QtGui.QStandardItem(self.project_icon, project_name)
|
||||
items.append(item)
|
||||
|
||||
self.invisibleRootItem().insertRows(row, items)
|
||||
|
||||
def get_projects(self):
|
||||
project_docs = []
|
||||
|
||||
for project_doc in sorted(
|
||||
self.dbcon.projects(), key=lambda x: x["name"]
|
||||
):
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ from .constants import (
|
|||
class ProjectBar(QtWidgets.QWidget):
|
||||
project_changed = QtCore.Signal(int)
|
||||
|
||||
# Project list will be refreshed each 10000 msecs
|
||||
refresh_interval = 10000
|
||||
|
||||
def __init__(self, dbcon, parent=None):
|
||||
super(ProjectBar, self).__init__(parent)
|
||||
|
||||
|
|
@ -47,14 +50,16 @@ class ProjectBar(QtWidgets.QWidget):
|
|||
QtWidgets.QSizePolicy.Maximum
|
||||
)
|
||||
|
||||
refresh_timer = QtCore.QTimer()
|
||||
refresh_timer.setInterval(self.refresh_interval)
|
||||
|
||||
self.model = model
|
||||
self.project_delegate = project_delegate
|
||||
self.project_combobox = project_combobox
|
||||
|
||||
# Initialize
|
||||
self.refresh()
|
||||
self.refresh_timer = refresh_timer
|
||||
|
||||
# Signals
|
||||
refresh_timer.timeout.connect(self._on_refresh_timeout)
|
||||
self.project_combobox.currentIndexChanged.connect(self.project_changed)
|
||||
|
||||
# Set current project by default if it's set.
|
||||
|
|
@ -62,6 +67,20 @@ class ProjectBar(QtWidgets.QWidget):
|
|||
if project_name:
|
||||
self.set_project(project_name)
|
||||
|
||||
def showEvent(self, event):
|
||||
if not self.refresh_timer.isActive():
|
||||
self.refresh_timer.start()
|
||||
super(ProjectBar, self).showEvent(event)
|
||||
|
||||
def _on_refresh_timeout(self):
|
||||
if not self.isVisible():
|
||||
# Stop timer if widget is not visible
|
||||
self.refresh_timer.stop()
|
||||
|
||||
elif self.isActiveWindow():
|
||||
# Refresh projects if window is active
|
||||
self.model.refresh()
|
||||
|
||||
def get_current_project(self):
|
||||
return self.project_combobox.currentText()
|
||||
|
||||
|
|
@ -69,27 +88,14 @@ class ProjectBar(QtWidgets.QWidget):
|
|||
index = self.project_combobox.findText(project_name)
|
||||
if index < 0:
|
||||
# Try refresh combobox model
|
||||
self.project_combobox.blockSignals(True)
|
||||
self.model.refresh()
|
||||
self.project_combobox.blockSignals(False)
|
||||
|
||||
self.refresh()
|
||||
index = self.project_combobox.findText(project_name)
|
||||
|
||||
if index >= 0:
|
||||
self.project_combobox.setCurrentIndex(index)
|
||||
|
||||
def refresh(self):
|
||||
prev_project_name = self.get_current_project()
|
||||
|
||||
# Refresh without signals
|
||||
self.project_combobox.blockSignals(True)
|
||||
|
||||
self.model.refresh()
|
||||
self.set_project(prev_project_name)
|
||||
|
||||
self.project_combobox.blockSignals(False)
|
||||
|
||||
self.project_changed.emit(self.project_combobox.currentIndex())
|
||||
|
||||
|
||||
class ActionBar(QtWidgets.QWidget):
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ class ProjectsPanel(QtWidgets.QWidget):
|
|||
"""Projects Page"""
|
||||
|
||||
project_clicked = QtCore.Signal(str)
|
||||
# Refresh projects each 10000 msecs
|
||||
refresh_interval = 10000
|
||||
|
||||
def __init__(self, dbcon, parent=None):
|
||||
super(ProjectsPanel, self).__init__(parent=parent)
|
||||
|
|
@ -106,21 +108,40 @@ class ProjectsPanel(QtWidgets.QWidget):
|
|||
flick.activateOn(view)
|
||||
model = ProjectModel(self.dbcon)
|
||||
model.hide_invisible = True
|
||||
model.refresh()
|
||||
view.setModel(model)
|
||||
|
||||
layout.addWidget(view)
|
||||
|
||||
refresh_timer = QtCore.QTimer()
|
||||
refresh_timer.setInterval(self.refresh_interval)
|
||||
|
||||
refresh_timer.timeout.connect(self._on_refresh_timeout)
|
||||
view.clicked.connect(self.on_clicked)
|
||||
|
||||
self.model = model
|
||||
self.view = view
|
||||
self.refresh_timer = refresh_timer
|
||||
|
||||
def on_clicked(self, index):
|
||||
if index.isValid():
|
||||
project_name = index.data(QtCore.Qt.DisplayRole)
|
||||
self.project_clicked.emit(project_name)
|
||||
|
||||
def showEvent(self, event):
|
||||
self.model.refresh()
|
||||
if not self.refresh_timer.isActive():
|
||||
self.refresh_timer.start()
|
||||
super(ProjectsPanel, self).showEvent(event)
|
||||
|
||||
def _on_refresh_timeout(self):
|
||||
if not self.isVisible():
|
||||
# Stop timer if widget is not visible
|
||||
self.refresh_timer.stop()
|
||||
|
||||
elif self.isActiveWindow():
|
||||
# Refresh projects if window is active
|
||||
self.model.refresh()
|
||||
|
||||
|
||||
class AssetsPanel(QtWidgets.QWidget):
|
||||
"""Assets page"""
|
||||
|
|
@ -276,6 +297,8 @@ class AssetsPanel(QtWidgets.QWidget):
|
|||
|
||||
class LauncherWindow(QtWidgets.QDialog):
|
||||
"""Launcher interface"""
|
||||
# Refresh actions each 10000msecs
|
||||
actions_refresh_timeout = 10000
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(LauncherWindow, self).__init__(parent)
|
||||
|
|
@ -344,6 +367,10 @@ class LauncherWindow(QtWidgets.QDialog):
|
|||
layout.setSpacing(0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
actions_refresh_timer = QtCore.QTimer()
|
||||
actions_refresh_timer.setInterval(self.actions_refresh_timeout)
|
||||
|
||||
self.actions_refresh_timer = actions_refresh_timer
|
||||
self.message_label = message_label
|
||||
self.project_panel = project_panel
|
||||
self.asset_panel = asset_panel
|
||||
|
|
@ -353,6 +380,7 @@ class LauncherWindow(QtWidgets.QDialog):
|
|||
self._page = 0
|
||||
|
||||
# signals
|
||||
actions_refresh_timer.timeout.connect(self._on_action_timer)
|
||||
actions_bar.action_clicked.connect(self.on_action_clicked)
|
||||
action_history.trigger_history.connect(self.on_history_action)
|
||||
project_panel.project_clicked.connect(self.on_project_clicked)
|
||||
|
|
@ -367,9 +395,11 @@ class LauncherWindow(QtWidgets.QDialog):
|
|||
self.resize(520, 740)
|
||||
|
||||
def showEvent(self, event):
|
||||
super().showEvent(event)
|
||||
# TODO implement refresh/reset which will trigger updating
|
||||
self.discover_actions()
|
||||
if not self.actions_refresh_timer.isActive():
|
||||
self.actions_refresh_timer.start()
|
||||
self.discover_actions()
|
||||
|
||||
super(LauncherWindow, self).showEvent(event)
|
||||
|
||||
def set_page(self, page):
|
||||
current = self.page_slider.currentIndex()
|
||||
|
|
@ -402,6 +432,15 @@ class LauncherWindow(QtWidgets.QDialog):
|
|||
def filter_actions(self):
|
||||
self.actions_bar.filter_actions()
|
||||
|
||||
def _on_action_timer(self):
|
||||
if not self.isVisible():
|
||||
# Stop timer if widget is not visible
|
||||
self.actions_refresh_timer.stop()
|
||||
|
||||
elif self.isActiveWindow():
|
||||
# Refresh projects if window is active
|
||||
self.discover_actions()
|
||||
|
||||
def on_project_clicked(self, project_name):
|
||||
self.dbcon.Session["AVALON_PROJECT"] = project_name
|
||||
# Refresh projects
|
||||
|
|
@ -412,7 +451,6 @@ class LauncherWindow(QtWidgets.QDialog):
|
|||
def on_back_clicked(self):
|
||||
self.dbcon.Session["AVALON_PROJECT"] = None
|
||||
self.set_page(0)
|
||||
self.project_panel.model.refresh() # Refresh projects
|
||||
self.discover_actions()
|
||||
|
||||
def on_action_clicked(self, action):
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package declaring Pype version."""
|
||||
__version__ = "3.1.0"
|
||||
__version__ = "3.2.0-nightly.1"
|
||||
|
|
|
|||
|
|
@ -4,35 +4,6 @@ from Qt import QtWidgets, QtCore, QtGui
|
|||
from .color_view import draw_checkerboard_tile
|
||||
|
||||
|
||||
slide_style = """
|
||||
QSlider::groove:horizontal {
|
||||
background: qlineargradient(
|
||||
x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #000, stop: 1 #fff
|
||||
);
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QSlider::handle:horizontal {
|
||||
background: qlineargradient(
|
||||
x1:0, y1:0, x2:1, y2:1, stop:0 #ddd, stop:1 #bbb
|
||||
);
|
||||
border: 1px solid #777;
|
||||
width: 8px;
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QSlider::handle:horizontal:hover {
|
||||
background: qlineargradient(
|
||||
x1:0, y1:0, x2:1, y2:1, stop:0 #eee, stop:1 #ddd
|
||||
);
|
||||
border: 1px solid #444;ff
|
||||
border-radius: 4px;
|
||||
}"""
|
||||
|
||||
|
||||
class AlphaSlider(QtWidgets.QSlider):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AlphaSlider, self).__init__(*args, **kwargs)
|
||||
|
|
@ -80,7 +51,7 @@ class AlphaSlider(QtWidgets.QSlider):
|
|||
|
||||
painter.fillRect(event.rect(), QtCore.Qt.transparent)
|
||||
|
||||
painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform)
|
||||
painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing)
|
||||
rect = self.style().subControlRect(
|
||||
QtWidgets.QStyle.CC_Slider,
|
||||
opt,
|
||||
|
|
@ -135,19 +106,8 @@ class AlphaSlider(QtWidgets.QSlider):
|
|||
|
||||
painter.save()
|
||||
|
||||
gradient = QtGui.QRadialGradient()
|
||||
radius = handle_rect.height() / 2
|
||||
center_x = handle_rect.width() / 2 + handle_rect.x()
|
||||
center_y = handle_rect.height()
|
||||
gradient.setCenter(center_x, center_y)
|
||||
gradient.setCenterRadius(radius)
|
||||
gradient.setFocalPoint(center_x, center_y)
|
||||
|
||||
gradient.setColorAt(0.9, QtGui.QColor(127, 127, 127))
|
||||
gradient.setColorAt(1, QtCore.Qt.transparent)
|
||||
|
||||
painter.setPen(QtCore.Qt.NoPen)
|
||||
painter.setBrush(gradient)
|
||||
painter.setBrush(QtGui.QColor(127, 127, 127))
|
||||
painter.drawEllipse(handle_rect)
|
||||
|
||||
painter.restore()
|
||||
|
|
|
|||
|
|
@ -241,7 +241,11 @@ class QtColorTriangle(QtWidgets.QWidget):
|
|||
|
||||
# Blit the static generated background with the hue gradient onto
|
||||
# the double buffer.
|
||||
buf = QtGui.QImage(self.bg_image.copy())
|
||||
buf = QtGui.QImage(
|
||||
self.bg_image.width(),
|
||||
self.bg_image.height(),
|
||||
QtGui.QImage.Format_RGB32
|
||||
)
|
||||
|
||||
# Draw the trigon
|
||||
# Find the color with only the hue, and max value and saturation
|
||||
|
|
@ -254,9 +258,21 @@ class QtColorTriangle(QtWidgets.QWidget):
|
|||
)
|
||||
|
||||
# Slow step: convert the image to a pixmap
|
||||
pix = QtGui.QPixmap.fromImage(buf)
|
||||
pix = self.bg_image.copy()
|
||||
pix_painter = QtGui.QPainter(pix)
|
||||
pix_painter.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||
|
||||
pix_painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing)
|
||||
|
||||
trigon_path = QtGui.QPainterPath()
|
||||
trigon_path.moveTo(self.point_a)
|
||||
trigon_path.lineTo(self.point_b)
|
||||
trigon_path.lineTo(self.point_c)
|
||||
trigon_path.closeSubpath()
|
||||
pix_painter.setClipPath(trigon_path)
|
||||
|
||||
pix_painter.drawImage(0, 0, buf)
|
||||
|
||||
pix_painter.setClipping(False)
|
||||
|
||||
# Draw an outline of the triangle
|
||||
pix_painter.setPen(self._triangle_outline_pen)
|
||||
|
|
@ -724,27 +740,37 @@ class QtColorTriangle(QtWidgets.QWidget):
|
|||
lx = leftX[y]
|
||||
rx = rightX[y]
|
||||
|
||||
# if the xdist is 0, don't draw anything.
|
||||
xdist = rx - lx
|
||||
if xdist == 0.0:
|
||||
continue
|
||||
|
||||
lxi = int(floor(lx))
|
||||
rxi = int(floor(rx))
|
||||
rc = rightColors[y]
|
||||
lc = leftColors[y]
|
||||
|
||||
# if the xdist is 0, don't draw anything.
|
||||
xdist = rx - lx
|
||||
if xdist != 0.0:
|
||||
r = lc.r
|
||||
g = lc.g
|
||||
b = lc.b
|
||||
rdelta = (rc.r - r) / xdist
|
||||
gdelta = (rc.g - g) / xdist
|
||||
bdelta = (rc.b - b) / xdist
|
||||
r = lc.r
|
||||
g = lc.g
|
||||
b = lc.b
|
||||
rdelta = (rc.r - r) / xdist
|
||||
gdelta = (rc.g - g) / xdist
|
||||
bdelta = (rc.b - b) / xdist
|
||||
|
||||
# Inner loop 2. Draws the line from left to right.
|
||||
for x in range(lxi, rxi + 1):
|
||||
buf.setPixel(x, y, QtGui.qRgb(int(r), int(g), int(b)))
|
||||
r += rdelta
|
||||
g += gdelta
|
||||
b += bdelta
|
||||
# Draw 2 more pixels on left side for smoothing
|
||||
for x in range(lxi - 2, lxi):
|
||||
buf.setPixel(x, y, QtGui.qRgb(int(r), int(g), int(b)))
|
||||
|
||||
# Inner loop 2. Draws the line from left to right.
|
||||
for x in range(lxi, rxi):
|
||||
buf.setPixel(x, y, QtGui.qRgb(int(r), int(g), int(b)))
|
||||
r += rdelta
|
||||
g += gdelta
|
||||
b += bdelta
|
||||
|
||||
# Draw 2 more pixels on right side for smoothing
|
||||
for x in range(rxi, rxi + 3):
|
||||
buf.setPixel(x, y, QtGui.qRgb(int(r), int(g), int(b)))
|
||||
|
||||
def _radius_at(self, pos, rect):
|
||||
mousexdist = pos.x() - float(rect.center().x())
|
||||
|
|
|
|||
30
website/docs/admin_hosts_tvpaint.md
Normal file
30
website/docs/admin_hosts_tvpaint.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
id: admin_hosts_tvpaint
|
||||
title: TVPaint
|
||||
sidebar_label: TVPaint
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
## Subset name templates
|
||||
Definition of possibile subset name templates in TVPaint integration.
|
||||
|
||||
### [Render Layer](artist_hosts_tvpaint#render-layer)
|
||||
Render layer has additional keys for subset name template. It is possible to use **render_layer** and **render_pass**.
|
||||
|
||||
- Key **render_layer** is alias for variant (user's input).
|
||||
- For key **render_pass** is used predefined value `"Beauty"` (ATM value can't be changed).
|
||||
|
||||
### [Render pass](artist_hosts_tvpaint#render-pass)
|
||||
Render pass has additional keys for subset name template. It is possible to use **render_layer** and **render_pass**.
|
||||
- Key **render_layer** is filled with value of **render_pass** from `renderLayer` group.
|
||||
- Key **render_pass** is alias for variant (user's input).
|
||||
|
||||
:::important Render Layer/Pass templates
|
||||
It is recommended to use same subset name template for both **renderLayer** and **renderPass** families.
|
||||
- Example template: `"{family}{Task}_{Render_layer}_{Render_pass}"`
|
||||
:::
|
||||
|
||||
### [Review](artist_hosts_tvpaint#review) and [Workfile](artist_hosts_tvpaint#workfile)
|
||||
Families **review** and **workfile** are not manually created but are automatically generated during publishing. That's why it is recommended to not use **variant** key in their subset name template.
|
||||
|
|
@ -45,7 +45,7 @@ In TVPaint you can find the Tools in OpenPype menu extension. The OpenPype Tools
|
|||
|
||||
|
||||
## Create
|
||||
In TVPaint you can create and publish **[Reviews](#review)**, **[Render Passes](#render-pass)**, and **[Render Layers](#render-layer)**.
|
||||
In TVPaint you can create and publish **[Reviews](#review)**, **[Workfile](#workfile)**, **[Render Passes](#render-pass)** and **[Render Layers](#render-layer)**.
|
||||
|
||||
You have the possibility to organize your layers by using `Color group`.
|
||||
|
||||
|
|
@ -67,26 +67,13 @@ OpenPype specifically never tries to guess what you want to publish from the sce
|
|||
|
||||
When you want to publish `review` or `render layer` or `render pass`, open the `Creator` through the Tools menu `Create` button.
|
||||
|
||||
### Review
|
||||
### Review
|
||||
`Review` renders the whole file as is and sends the resulting QuickTime to Ftrack.
|
||||
- Is automatically created during publishing.
|
||||
|
||||
<div class="row markdown">
|
||||
<div class="col col--6 markdown">
|
||||
|
||||
`Review` renders the whole file as is and sends the resulting QuickTime to Ftrack.
|
||||
|
||||
To create reviewable quicktime of your animation:
|
||||
|
||||
- select `Review` in the `Creator`
|
||||
- press `Create`
|
||||
- When you run [publish](#publish), file will be rendered and converted to quicktime.`
|
||||
|
||||
</div>
|
||||
<div class="col col--6 markdown">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
</div>
|
||||
### Workfile
|
||||
`Workfile` stores the source workfile as is during publishing (e.g. for backup).
|
||||
- Is automatically created during publishing.
|
||||
|
||||
### Render Layer
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
|
|
@ -172,6 +172,39 @@ Applicable context filters:
|
|||
## Tools
|
||||
Settings for OpenPype tools.
|
||||
|
||||
## Creator
|
||||
Settings related to [Creator tool](artist_tools.md#details).
|
||||
|
||||
### Subset name profiles
|
||||

|
||||
|
||||
Subset name helps to identify published content. More specific name helps with organization and avoid mixing of published content. Subset name is defined using one of templates defined in **Subset name profiles settings**. The template is filled with context information at the time of creation.
|
||||
|
||||
Usage of template is defined by profile filtering using creator's family, host and task name. Profile without filters is used as default template and it is recommend to set default template. If default template is not available `"{family}{Task}"` is used.
|
||||
|
||||
**Formatting keys**
|
||||
|
||||
All templates can contain text and formatting keys **family**, **task** and **variant** e.g. `"MyStudio_{family}_{task}"` (example - not recommended in production).
|
||||
|
||||
|Key|Description|
|
||||
|---|---|
|
||||
|family|Creators family|
|
||||
|task|Task under which is creation triggered|
|
||||
|variant|User input in creator tool|
|
||||
|
||||
**Formatting keys have 3 variants with different letter capitalization.**
|
||||
|
||||
|Task|Key variant|Description|Result|
|
||||
|---|---|---|---|
|
||||
|`bgAnim`|`{task}`|Keep original value as is.|`bgAnim`|
|
||||
|`bgAnim`|`{Task}`|Capitalize first letter of value.|`BgAnim`|
|
||||
|`bgAnim`|`{TASK}`|Each letter which be capitalized.|`BGANIM`|
|
||||
|
||||
Template may look like `"{family}{Task}{Variant}"`.
|
||||
|
||||
Some creators may have other keys as their context may require more information or more specific values. Make sure you've read documentation of host you're using.
|
||||
|
||||
|
||||
## Workfiles
|
||||
All settings related to Workfile tool.
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,8 @@ module.exports = {
|
|||
"admin_hosts_maya",
|
||||
"admin_hosts_resolve",
|
||||
"admin_hosts_harmony",
|
||||
"admin_hosts_aftereffects"
|
||||
"admin_hosts_aftereffects",
|
||||
"admin_hosts_tvpaint"
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue