mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
15dbd9fcac
23 changed files with 284 additions and 133 deletions
|
|
@ -378,6 +378,17 @@ def add_otio_metadata(otio_item, media_source, **kwargs):
|
|||
|
||||
def create_otio_timeline():
|
||||
|
||||
def set_prev_item(itemindex, track_item):
|
||||
# Add Gap if needed
|
||||
if itemindex == 0:
|
||||
# if it is first track item at track then add
|
||||
# it to previouse item
|
||||
return track_item
|
||||
|
||||
else:
|
||||
# get previouse item
|
||||
return track_item.parent().items()[itemindex - 1]
|
||||
|
||||
# get current timeline
|
||||
self.timeline = hiero.ui.activeSequence()
|
||||
self.project_fps = self.timeline.framerate().toFloat()
|
||||
|
|
@ -396,14 +407,6 @@ def create_otio_timeline():
|
|||
type(track), track.name())
|
||||
|
||||
for itemindex, track_item in enumerate(track):
|
||||
# skip offline track items
|
||||
if not track_item.isMediaPresent():
|
||||
continue
|
||||
|
||||
# skip if track item is disabled
|
||||
if not track_item.isEnabled():
|
||||
continue
|
||||
|
||||
# Add Gap if needed
|
||||
if itemindex == 0:
|
||||
# if it is first track item at track then add
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
|
|||
self.create_shot_instance(context, **data)
|
||||
|
||||
self.log.info("Creating instance: {}".format(instance))
|
||||
self.log.debug(
|
||||
self.log.info(
|
||||
"_ instance.data: {}".format(pformat(instance.data)))
|
||||
|
||||
if not with_audio:
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from openpype.hosts.hiero.otio import hiero_export
|
|||
from Qt.QtGui import QPixmap
|
||||
import tempfile
|
||||
|
||||
|
||||
class PrecollectWorkfile(pyblish.api.ContextPlugin):
|
||||
"""Inject the current working file into context"""
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ def install():
|
|||
pyblish.register_plugin_path(PUBLISH_PATH)
|
||||
avalon.register_plugin_path(avalon.Loader, LOAD_PATH)
|
||||
avalon.register_plugin_path(avalon.Creator, CREATE_PATH)
|
||||
avalon.register_plugin_path(avalon.InventoryAction, INVENTORY_PATH)
|
||||
log.info(PUBLISH_PATH)
|
||||
menu.install()
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,53 @@ import avalon.maya
|
|||
from openpype.api import PypeCreatorMixin
|
||||
|
||||
|
||||
def get_reference_node(members, log=None):
|
||||
"""Get the reference node from the container members
|
||||
Args:
|
||||
members: list of node names
|
||||
|
||||
Returns:
|
||||
str: Reference node name.
|
||||
|
||||
"""
|
||||
|
||||
from maya import cmds
|
||||
|
||||
# Collect the references without .placeHolderList[] attributes as
|
||||
# unique entries (objects only) and skipping the sharedReferenceNode.
|
||||
references = set()
|
||||
for ref in cmds.ls(members, exactType="reference", objectsOnly=True):
|
||||
|
||||
# Ignore any `:sharedReferenceNode`
|
||||
if ref.rsplit(":", 1)[-1].startswith("sharedReferenceNode"):
|
||||
continue
|
||||
|
||||
# Ignore _UNKNOWN_REF_NODE_ (PLN-160)
|
||||
if ref.rsplit(":", 1)[-1].startswith("_UNKNOWN_REF_NODE_"):
|
||||
continue
|
||||
|
||||
references.add(ref)
|
||||
|
||||
assert references, "No reference node found in container"
|
||||
|
||||
# Get highest reference node (least parents)
|
||||
highest = min(references,
|
||||
key=lambda x: len(get_reference_node_parents(x)))
|
||||
|
||||
# Warn the user when we're taking the highest reference node
|
||||
if len(references) > 1:
|
||||
if not log:
|
||||
from openpype.lib import PypeLogger
|
||||
|
||||
log = PypeLogger().get_logger(__name__)
|
||||
|
||||
log.warning("More than one reference node found in "
|
||||
"container, using highest reference node: "
|
||||
"%s (in: %s)", highest, list(references))
|
||||
|
||||
return highest
|
||||
|
||||
|
||||
def get_reference_node_parents(ref):
|
||||
"""Return all parent reference nodes of reference node
|
||||
|
||||
|
|
@ -109,7 +156,7 @@ class ReferenceLoader(api.Loader):
|
|||
loader=self.__class__.__name__
|
||||
))
|
||||
else:
|
||||
ref_node = self._get_reference_node(nodes)
|
||||
ref_node = get_reference_node(nodes, self.log)
|
||||
loaded_containers.append(containerise(
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
|
|
@ -126,46 +173,6 @@ class ReferenceLoader(api.Loader):
|
|||
"""To be implemented by subclass"""
|
||||
raise NotImplementedError("Must be implemented by subclass")
|
||||
|
||||
def _get_reference_node(self, members):
|
||||
"""Get the reference node from the container members
|
||||
Args:
|
||||
members: list of node names
|
||||
|
||||
Returns:
|
||||
str: Reference node name.
|
||||
|
||||
"""
|
||||
|
||||
from maya import cmds
|
||||
|
||||
# Collect the references without .placeHolderList[] attributes as
|
||||
# unique entries (objects only) and skipping the sharedReferenceNode.
|
||||
references = set()
|
||||
for ref in cmds.ls(members, exactType="reference", objectsOnly=True):
|
||||
|
||||
# Ignore any `:sharedReferenceNode`
|
||||
if ref.rsplit(":", 1)[-1].startswith("sharedReferenceNode"):
|
||||
continue
|
||||
|
||||
# Ignore _UNKNOWN_REF_NODE_ (PLN-160)
|
||||
if ref.rsplit(":", 1)[-1].startswith("_UNKNOWN_REF_NODE_"):
|
||||
continue
|
||||
|
||||
references.add(ref)
|
||||
|
||||
assert references, "No reference node found in container"
|
||||
|
||||
# Get highest reference node (least parents)
|
||||
highest = min(references,
|
||||
key=lambda x: len(get_reference_node_parents(x)))
|
||||
|
||||
# Warn the user when we're taking the highest reference node
|
||||
if len(references) > 1:
|
||||
self.log.warning("More than one reference node found in "
|
||||
"container, using highest reference node: "
|
||||
"%s (in: %s)", highest, list(references))
|
||||
|
||||
return highest
|
||||
|
||||
def update(self, container, representation):
|
||||
|
||||
|
|
@ -178,7 +185,7 @@ class ReferenceLoader(api.Loader):
|
|||
|
||||
# Get reference node from container members
|
||||
members = cmds.sets(node, query=True, nodesOnly=True)
|
||||
reference_node = self._get_reference_node(members)
|
||||
reference_node = get_reference_node(members, self.log)
|
||||
|
||||
file_type = {
|
||||
"ma": "mayaAscii",
|
||||
|
|
@ -274,7 +281,7 @@ class ReferenceLoader(api.Loader):
|
|||
|
||||
# Assume asset has been referenced
|
||||
members = cmds.sets(node, query=True)
|
||||
reference_node = self._get_reference_node(members)
|
||||
reference_node = get_reference_node(members, self.log)
|
||||
|
||||
assert reference_node, ("Imported container not supported; "
|
||||
"container must be referenced.")
|
||||
|
|
|
|||
29
openpype/hosts/maya/plugins/inventory/import_reference.py
Normal file
29
openpype/hosts/maya/plugins/inventory/import_reference.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
from maya import cmds
|
||||
|
||||
from avalon import api
|
||||
|
||||
from openpype.hosts.maya.api.plugin import get_reference_node
|
||||
|
||||
|
||||
class ImportReference(api.InventoryAction):
|
||||
"""Imports selected reference to inside of the file."""
|
||||
|
||||
label = "Import Reference"
|
||||
icon = "download"
|
||||
color = "#d8d8d8"
|
||||
|
||||
def process(self, containers):
|
||||
references = cmds.ls(type="reference")
|
||||
for container in containers:
|
||||
if container["loader"] != "ReferenceLoader":
|
||||
print("Not a reference, skipping")
|
||||
continue
|
||||
|
||||
node = container["objectName"]
|
||||
members = cmds.sets(node, query=True, nodesOnly=True)
|
||||
ref_node = get_reference_node(members)
|
||||
|
||||
ref_file = cmds.referenceQuery(ref_node, f=True)
|
||||
cmds.file(ref_file, importReference=True)
|
||||
|
||||
return True # return anything to trigger model refresh
|
||||
|
|
@ -9,7 +9,7 @@ class IncrementScriptVersion(pyblish.api.ContextPlugin):
|
|||
order = pyblish.api.IntegratorOrder + 0.9
|
||||
label = "Increment Script Version"
|
||||
optional = True
|
||||
families = ["workfile", "render", "render.local", "render.farm"]
|
||||
families = ["workfile"]
|
||||
hosts = ['nuke']
|
||||
|
||||
def process(self, context):
|
||||
|
|
|
|||
|
|
@ -10,16 +10,14 @@ from .constants import (
|
|||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import (
|
||||
ITrayModule,
|
||||
IPluginPaths,
|
||||
IFtrackEventHandlerPaths
|
||||
IPluginPaths
|
||||
)
|
||||
|
||||
|
||||
class ClockifyModule(
|
||||
OpenPypeModule,
|
||||
ITrayModule,
|
||||
IPluginPaths,
|
||||
IFtrackEventHandlerPaths
|
||||
IPluginPaths
|
||||
):
|
||||
name = "clockify"
|
||||
|
||||
|
|
@ -93,8 +91,8 @@ class ClockifyModule(
|
|||
"actions": [actions_path]
|
||||
}
|
||||
|
||||
def get_event_handler_paths(self):
|
||||
"""Implementaton of IFtrackEventHandlerPaths to get plugin paths."""
|
||||
def get_ftrack_event_handler_paths(self):
|
||||
"""Function for Ftrack module to add ftrack event handler paths."""
|
||||
return {
|
||||
"user": [CLOCKIFY_FTRACK_USER_PATH],
|
||||
"server": [CLOCKIFY_FTRACK_SERVER_PATH]
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ from openpype_interfaces import (
|
|||
ITrayModule,
|
||||
IPluginPaths,
|
||||
ILaunchHookPaths,
|
||||
ISettingsChangeListener,
|
||||
IFtrackEventHandlerPaths
|
||||
ISettingsChangeListener
|
||||
)
|
||||
from openpype.settings import SaveWarningExc
|
||||
|
||||
|
|
@ -81,9 +80,17 @@ class FtrackModule(
|
|||
|
||||
def connect_with_modules(self, enabled_modules):
|
||||
for module in enabled_modules:
|
||||
if not isinstance(module, IFtrackEventHandlerPaths):
|
||||
if not hasattr(module, "get_ftrack_event_handler_paths"):
|
||||
continue
|
||||
paths_by_type = module.get_event_handler_paths() or {}
|
||||
|
||||
try:
|
||||
paths_by_type = module.get_ftrack_event_handler_paths()
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if not isinstance(paths_by_type, dict):
|
||||
continue
|
||||
|
||||
for key, value in paths_by_type.items():
|
||||
if not value:
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
from abc import abstractmethod
|
||||
from openpype.modules import OpenPypeInterface
|
||||
|
||||
|
||||
class IFtrackEventHandlerPaths(OpenPypeInterface):
|
||||
"""Other modules interface to return paths to ftrack event handlers.
|
||||
|
||||
Expected output is dictionary with "server" and "user" keys.
|
||||
"""
|
||||
@abstractmethod
|
||||
def get_event_handler_paths(self):
|
||||
pass
|
||||
|
|
@ -5,8 +5,7 @@ from .constants import (
|
|||
CUST_ATTR_TOOLS,
|
||||
CUST_ATTR_APPLICATIONS
|
||||
)
|
||||
from . settings import (
|
||||
get_ftrack_url_from_settings,
|
||||
from .settings import (
|
||||
get_ftrack_event_mongo_info
|
||||
)
|
||||
from .custom_attributes import (
|
||||
|
|
@ -31,7 +30,6 @@ __all__ = (
|
|||
"CUST_ATTR_TOOLS",
|
||||
"CUST_ATTR_APPLICATIONS",
|
||||
|
||||
"get_ftrack_url_from_settings",
|
||||
"get_ftrack_event_mongo_info",
|
||||
|
||||
"default_custom_attributes_definition",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,4 @@
|
|||
import os
|
||||
from openpype.api import get_system_settings
|
||||
|
||||
|
||||
def get_ftrack_settings():
|
||||
return get_system_settings()["modules"]["ftrack"]
|
||||
|
||||
|
||||
def get_ftrack_url_from_settings():
|
||||
return get_ftrack_settings()["ftrack_server"]
|
||||
|
||||
|
||||
def get_ftrack_event_mongo_info():
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ class TimersManager(OpenPypeModule, ITrayService, IIdleManager):
|
|||
self.widget_user_idle.refresh_context()
|
||||
self.is_running = False
|
||||
|
||||
self.timer_stopper(None)
|
||||
self.timer_stopped(None)
|
||||
|
||||
def connect_with_modules(self, enabled_modules):
|
||||
for module in enabled_modules:
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class CollectHierarchy(pyblish.api.ContextPlugin):
|
|||
"""
|
||||
|
||||
label = "Collect Hierarchy"
|
||||
order = pyblish.api.CollectorOrder - 0.57
|
||||
order = pyblish.api.CollectorOrder - 0.47
|
||||
families = ["shot"]
|
||||
hosts = ["resolve", "hiero"]
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class CollectOcioFrameRanges(pyblish.api.InstancePlugin):
|
|||
Adding timeline and source ranges to instance data"""
|
||||
|
||||
label = "Collect OTIO Frame Ranges"
|
||||
order = pyblish.api.CollectorOrder - 0.58
|
||||
order = pyblish.api.CollectorOrder - 0.48
|
||||
families = ["shot", "clip"]
|
||||
hosts = ["resolve", "hiero"]
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class CollectOcioReview(pyblish.api.InstancePlugin):
|
|||
"""Get matching otio track from defined review layer"""
|
||||
|
||||
label = "Collect OTIO Review"
|
||||
order = pyblish.api.CollectorOrder - 0.57
|
||||
order = pyblish.api.CollectorOrder - 0.47
|
||||
families = ["clip"]
|
||||
hosts = ["resolve", "hiero"]
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class CollectOcioSubsetResources(pyblish.api.InstancePlugin):
|
|||
"""Get Resources for a subset version"""
|
||||
|
||||
label = "Collect OTIO Subset Resources"
|
||||
order = pyblish.api.CollectorOrder - 0.57
|
||||
order = pyblish.api.CollectorOrder - 0.47
|
||||
families = ["clip"]
|
||||
hosts = ["resolve", "hiero"]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
import pyblish.api
|
||||
import os
|
||||
import subprocess
|
||||
import openpype.lib
|
||||
try:
|
||||
import os.errno as errno
|
||||
except ImportError:
|
||||
import errno
|
||||
|
||||
|
||||
class ValidateFFmpegInstalled(pyblish.api.ContextPlugin):
|
||||
"""Validate availability of ffmpeg tool in PATH"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder
|
||||
label = 'Validate ffmpeg installation'
|
||||
optional = True
|
||||
|
||||
def is_tool(self, name):
|
||||
try:
|
||||
devnull = open(os.devnull, "w")
|
||||
subprocess.Popen(
|
||||
[name], stdout=devnull, stderr=devnull
|
||||
).communicate()
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
return False
|
||||
return True
|
||||
|
||||
def process(self, context):
|
||||
ffmpeg_path = openpype.lib.get_ffmpeg_tool_path("ffmpeg")
|
||||
self.log.info("ffmpeg path: `{}`".format(ffmpeg_path))
|
||||
if self.is_tool("{}".format(ffmpeg_path)) is False:
|
||||
self.log.error("ffmpeg not found in PATH")
|
||||
raise RuntimeError('ffmpeg not installed.')
|
||||
|
|
@ -102,6 +102,11 @@
|
|||
},
|
||||
"ExtractSlateFrame": {
|
||||
"viewer_lut_raw": false
|
||||
},
|
||||
"IncrementScriptVersion": {
|
||||
"enabled": true,
|
||||
"optional": true,
|
||||
"active": true
|
||||
}
|
||||
},
|
||||
"load": {
|
||||
|
|
|
|||
|
|
@ -173,6 +173,38 @@
|
|||
"label": "Viewer LUT raw"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"label": "Integrators"
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"key": "IncrementScriptVersion",
|
||||
"label": "IncrementScriptVersion",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "optional",
|
||||
"label": "Optional"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "active",
|
||||
"label": "Active"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ from openpype.lib import is_admin_password_required
|
|||
from openpype.widgets import PasswordDialog
|
||||
|
||||
from openpype import resources
|
||||
from openpype.api import (
|
||||
get_project_basic_paths,
|
||||
create_project_folders,
|
||||
Logger
|
||||
)
|
||||
from avalon.api import AvalonMongoDB
|
||||
|
||||
|
||||
|
|
@ -24,10 +29,15 @@ class ProjectManagerWindow(QtWidgets.QWidget):
|
|||
def __init__(self, parent=None):
|
||||
super(ProjectManagerWindow, self).__init__(parent)
|
||||
|
||||
self.log = Logger.get_logger(self.__class__.__name__)
|
||||
|
||||
self._initial_reset = False
|
||||
self._password_dialog = None
|
||||
self._user_passed = False
|
||||
|
||||
# keep track of the current project PM is viewing
|
||||
self._current_project = None
|
||||
|
||||
self.setWindowTitle("OpenPype Project Manager")
|
||||
self.setWindowIcon(QtGui.QIcon(resources.get_openpype_icon_filepath()))
|
||||
|
||||
|
|
@ -57,12 +67,18 @@ class ProjectManagerWindow(QtWidgets.QWidget):
|
|||
create_project_btn = QtWidgets.QPushButton(
|
||||
"Create project...", project_widget
|
||||
)
|
||||
create_folders_btn = QtWidgets.QPushButton(
|
||||
ResourceCache.get_icon("asset", "default"),
|
||||
"Create Starting Folders",
|
||||
project_widget
|
||||
)
|
||||
|
||||
project_layout = QtWidgets.QHBoxLayout(project_widget)
|
||||
project_layout.setContentsMargins(0, 0, 0, 0)
|
||||
project_layout.addWidget(project_combobox, 0)
|
||||
project_layout.addWidget(refresh_projects_btn, 0)
|
||||
project_layout.addWidget(create_project_btn, 0)
|
||||
project_layout.addWidget(create_folders_btn)
|
||||
project_layout.addStretch(1)
|
||||
|
||||
# Helper buttons
|
||||
|
|
@ -124,6 +140,7 @@ class ProjectManagerWindow(QtWidgets.QWidget):
|
|||
|
||||
refresh_projects_btn.clicked.connect(self._on_project_refresh)
|
||||
create_project_btn.clicked.connect(self._on_project_create)
|
||||
create_folders_btn.clicked.connect(self._on_create_folders)
|
||||
project_combobox.currentIndexChanged.connect(self._on_project_change)
|
||||
save_btn.clicked.connect(self._on_save_click)
|
||||
add_asset_btn.clicked.connect(self._on_add_asset)
|
||||
|
|
@ -139,6 +156,7 @@ class ProjectManagerWindow(QtWidgets.QWidget):
|
|||
self._refresh_projects_btn = refresh_projects_btn
|
||||
self._project_combobox = project_combobox
|
||||
self._create_project_btn = create_project_btn
|
||||
self._create_folders_btn = create_folders_btn
|
||||
|
||||
self._add_asset_btn = add_asset_btn
|
||||
self._add_task_btn = add_task_btn
|
||||
|
|
@ -179,7 +197,9 @@ class ProjectManagerWindow(QtWidgets.QWidget):
|
|||
self._set_project(self._project_combobox.currentText())
|
||||
|
||||
def _on_project_change(self):
|
||||
self._set_project(self._project_combobox.currentText())
|
||||
if self._project_combobox.currentIndex() != 0:
|
||||
self._current_project = self._project_combobox.currentText()
|
||||
self._set_project(self._current_project)
|
||||
|
||||
def _on_project_refresh(self):
|
||||
self.refresh_projects()
|
||||
|
|
@ -193,6 +213,29 @@ class ProjectManagerWindow(QtWidgets.QWidget):
|
|||
def _on_add_task(self):
|
||||
self.hierarchy_view.add_task()
|
||||
|
||||
def _on_create_folders(self):
|
||||
if not self._current_project:
|
||||
return
|
||||
|
||||
qm = QtWidgets.QMessageBox
|
||||
ans = qm.question(self,
|
||||
"OpenPype Project Manager",
|
||||
"Confirm to create starting project folders?",
|
||||
qm.Yes | qm.No)
|
||||
if ans == qm.Yes:
|
||||
try:
|
||||
# Get paths based on presets
|
||||
basic_paths = get_project_basic_paths(self._current_project)
|
||||
if not basic_paths:
|
||||
pass
|
||||
# Invoking OpenPype API to create the project folders
|
||||
create_project_folders(basic_paths, self._current_project)
|
||||
except Exception as exc:
|
||||
self.log.warning(
|
||||
"Cannot create starting folders: {}".format(exc),
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
def show_message(self, message):
|
||||
# TODO add nicer message pop
|
||||
self.message_label.setText(message)
|
||||
|
|
@ -203,9 +246,11 @@ class ProjectManagerWindow(QtWidgets.QWidget):
|
|||
if dialog.result() != 1:
|
||||
return
|
||||
|
||||
project_name = dialog.project_name
|
||||
self.show_message("Created project \"{}\"".format(project_name))
|
||||
self.refresh_projects(project_name)
|
||||
self._current_project = dialog.project_name
|
||||
self.show_message(
|
||||
"Created project \"{}\"".format(self._current_project)
|
||||
)
|
||||
self.refresh_projects(self._current_project)
|
||||
|
||||
def _show_password_dialog(self):
|
||||
if self._password_dialog:
|
||||
|
|
|
|||
80
start.py
80
start.py
|
|
@ -96,6 +96,7 @@ Attributes:
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
import platform
|
||||
import traceback
|
||||
import subprocess
|
||||
import site
|
||||
|
|
@ -339,6 +340,80 @@ def set_modules_environments():
|
|||
os.environ.update(env)
|
||||
|
||||
|
||||
def is_tool(name):
|
||||
try:
|
||||
import os.errno as errno
|
||||
except ImportError:
|
||||
import errno
|
||||
|
||||
try:
|
||||
devnull = open(os.devnull, "w")
|
||||
subprocess.Popen(
|
||||
[name], stdout=devnull, stderr=devnull
|
||||
).communicate()
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.ENOENT:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _startup_validations():
|
||||
"""Validations before OpenPype starts."""
|
||||
try:
|
||||
_validate_thirdparty_binaries()
|
||||
except Exception as exc:
|
||||
if os.environ.get("OPENPYPE_HEADLESS_MODE"):
|
||||
raise
|
||||
|
||||
import tkinter
|
||||
from tkinter.messagebox import showerror
|
||||
|
||||
root = tkinter.Tk()
|
||||
root.attributes("-alpha", 0.0)
|
||||
root.wm_state("iconic")
|
||||
if platform.system().lower() != "windows":
|
||||
root.withdraw()
|
||||
|
||||
showerror(
|
||||
"Startup validations didn't pass",
|
||||
str(exc)
|
||||
)
|
||||
root.withdraw()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def _validate_thirdparty_binaries():
|
||||
"""Check existence of thirdpart executables."""
|
||||
low_platform = platform.system().lower()
|
||||
binary_vendors_dir = os.path.join(
|
||||
os.environ["OPENPYPE_ROOT"],
|
||||
"vendor",
|
||||
"bin"
|
||||
)
|
||||
|
||||
error_msg = (
|
||||
"Missing binary dependency {}. Please fetch thirdparty dependencies."
|
||||
)
|
||||
# Validate existence of FFmpeg
|
||||
ffmpeg_dir = os.path.join(binary_vendors_dir, "ffmpeg", low_platform)
|
||||
if low_platform == "windows":
|
||||
ffmpeg_dir = os.path.join(ffmpeg_dir, "bin")
|
||||
ffmpeg_executable = os.path.join(ffmpeg_dir, "ffmpeg")
|
||||
if not is_tool(ffmpeg_executable):
|
||||
raise RuntimeError(error_msg.format("FFmpeg"))
|
||||
|
||||
# Validate existence of OpenImageIO (not on MacOs)
|
||||
if low_platform != "darwin":
|
||||
oiio_tool_path = os.path.join(
|
||||
binary_vendors_dir,
|
||||
"oiio",
|
||||
low_platform,
|
||||
"oiiotool"
|
||||
)
|
||||
if not is_tool(oiio_tool_path):
|
||||
raise RuntimeError(error_msg.format("OpenImageIO"))
|
||||
|
||||
|
||||
def _process_arguments() -> tuple:
|
||||
"""Process command line arguments.
|
||||
|
||||
|
|
@ -767,6 +842,11 @@ def boot():
|
|||
# ------------------------------------------------------------------------
|
||||
os.environ["OPENPYPE_ROOT"] = OPENPYPE_ROOT
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# Do necessary startup validations
|
||||
# ------------------------------------------------------------------------
|
||||
_startup_validations()
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# Play animation
|
||||
# ------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -6594,9 +6594,9 @@ prism-react-renderer@^1.1.1:
|
|||
integrity sha512-GHqzxLYImx1iKN1jJURcuRoA/0ygCcNhfGw1IT8nPIMzarmKQ3Nc+JcG0gi8JXQzuh0C5ShE4npMIoqNin40hg==
|
||||
|
||||
prismjs@^1.23.0:
|
||||
version "1.24.0"
|
||||
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.24.0.tgz#0409c30068a6c52c89ef7f1089b3ca4de56be2ac"
|
||||
integrity sha512-SqV5GRsNqnzCL8k5dfAjCNhUrF3pR0A9lTDSCUZeh/LIshheXJEaP0hwLz2t4XHivd2J/v2HR+gRnigzeKe3cQ==
|
||||
version "1.25.0"
|
||||
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756"
|
||||
integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue