Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add slapcomp compatibility #5

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions python/deadlinesubmissionsettings/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .app import show


__all__ = [
"show"
]
188 changes: 119 additions & 69 deletions python/deadlinesubmissionsettings/app.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import sys

from avalon import api, io
from avalon.tools import lib as tools_lib
from avalon.vendor.Qt import QtWidgets, QtCore
from avalon.vendor import qtawesome as qta

from . import lib
from . import mayalib

module = sys.modules[__name__]
module.window = None


class App(QtWidgets.QWidget):
"""Main application for alter settings per render job (layer)"""

def __init__(self):
QtWidgets.QWidget.__init__(self)
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)

self.setWindowTitle("Deadline Submission setting")
self.setFixedSize(250, 500)
self.setFixedSize(250, 480)

self.setup_ui()
self.connections()
Expand All @@ -29,14 +37,28 @@ def setup_ui(self):

publish = QtWidgets.QCheckBox("Suspend Publish Job")
defaultlayer = QtWidgets.QCheckBox("Include Default Render Layer")
run_slap_comp = QtWidgets.QCheckBox("Run Slap Comp")

browse_hlayout = QtWidgets.QHBoxLayout()
file_line = QtWidgets.QLineEdit()

brows_icon = qta.icon("fa.folder", color="white")
browse_btn = QtWidgets.QPushButton()
browse_btn.setIcon(brows_icon)

file_line.setPlaceholderText("<Slap Comp File>")
file_line.setEnabled(False)
browse_btn.setEnabled(False)

browse_hlayout.addWidget(file_line)
browse_hlayout.addWidget(browse_btn)

# region Priority
priority_grp = QtWidgets.QGroupBox("Priority")
priority_hlayout = QtWidgets.QHBoxLayout()

priority_value = QtWidgets.QSpinBox()
priority_value.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
priority_value.setEnabled(False)
priority_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
priority_slider.setMinimum(0)
priority_slider.setMaximum(99)
Expand Down Expand Up @@ -94,6 +116,8 @@ def setup_ui(self):

layout.addWidget(defaultlayer)
layout.addWidget(publish)
layout.addWidget(run_slap_comp)
layout.addLayout(browse_hlayout)
layout.addWidget(priority_grp)
layout.addWidget(list_type_grp)
layout.addLayout(machines_hlayout)
Expand All @@ -102,6 +126,9 @@ def setup_ui(self):
# Enable access for all methods
self.publish = publish
self.defaultlayer = defaultlayer
self.run_slap_comp = run_slap_comp
self.flow_file = file_line
self.browse_file_btn = browse_btn
self.priority_value = priority_value
self.priority_slider = priority_slider
self.black_list = black_list
Expand All @@ -115,16 +142,36 @@ def setup_ui(self):
self.setLayout(layout)

def connections(self):

self.run_slap_comp.toggled.connect(self.on_run_slap_comp_toggled)
self.browse_file_btn.clicked.connect(self.on_browse_clicked)

self.priority_slider.valueChanged[int].connect(
self.priority_value.setValue)

self.priority_value.valueChanged.connect(self.priority_slider.setValue)

self.add_machine_btn.clicked.connect(self.add_selected_machines)
self.remove_machine_btn.clicked.connect(self.remove_selected_machines)
self.accept.clicked.connect(self.parse_settings)

self.priority_slider.setValue(50)

def add_per_job_settings(self):
"""Create a mini settings for each render layer which is discovered"""
pass
def on_run_slap_comp_toggled(self):
state = self.run_slap_comp.isChecked()
self.flow_file.setEnabled(state)
self.browse_file_btn.setEnabled(state)

def on_browse_clicked(self):

workdir = lib.get_work_directory()
file_path, _ = QtWidgets.QFileDialog.getOpenFileName(
self, "Choose comp", workdir, filter="*.comp")

if not file_path:
return

self.flow_file.setText(file_path)

def add_selected_machines(self):
"""Add selected machines to the list which is going to be used"""
Expand All @@ -143,8 +190,7 @@ def add_selected_machines(self):
self.listed_machines.addItem(machine_name)

def remove_selected_machines(self):
machines = self.listed_machines.selectedItems()
for machine in machines:
for machine in self.listed_machines.selectedItems():
self.listed_machines.takeItem(self.listed_machines.row(machine))

def create_machine_limit_options(self):
Expand All @@ -153,68 +199,51 @@ def create_machine_limit_options(self):
for name in lib.get_machine_list():
self.machine_list.addItem(name)

def create_pools_options(self):
pools = lib.get_pool_list()
for pool in pools:
self.pools.addItem(pool)

def create_groups_options(self):
groups = lib.get_group_list()
for group in groups:
self.groups.addItem(group)

def refresh(self):

self.pools.clear()
self.groups.clear()
self.machine_list.clear()

self.create_machine_limit_options()
self.create_pools_options()
self.create_groups_options()

def parse_settings(self):
"""Convert the UI settings to Maya attributes"""

# Get UI settings as dict
job_info = {}

machine_limits = self._get_listed_machines()
machine_limits = " ".join(machine_limits)

job_info["priority"] = self.priority_value.value()
job_info["suspendPublishJob"] = self.publish.isChecked()
job_info["includeDefaultRenderLayer"] = self.defaultlayer.isChecked()

job_info["runSlapComp"] = self.run_slap_comp.isChecked()
job_info["flowFile"] = self.flow_file.text()

# Get the node, create node if none exists
job_info["whitelist"] = self._get_list_type()
job_info["machineList"] = machine_limits

# Get the node and apply settings
instance = mayalib.find_render_instance()
if not instance:
instance = mayalib.create_renderglobals_node()

# Get UI settings as dict
job_info = self._get_settings()
self.renderglobals_message()
return

mayalib.apply_settings(instance, job_info)

def renderglobals_message(self):

message = ("Please use the Creator from the Avalon menu to create "
"a renderglobalsDefault isntance or use the button on the "
"bottom of the screen.")
message = ("Please use the Creator from the Avalon menu to create"
"a renderglobalsDefault instance")

button = QtWidgets.QMessageBox.StandardButton.Ok

QtWidgets.QMessageBox.critical(self,
"Missing renderglobalsDefault node",
"Missing instance",
message,
button)
return

def _get_settings(self):

settings = {}
machine_list_type = self._get_list_type()

machine_limits = self._get_listed_machines()
machine_limits = " ".join(machine_limits)

settings["priority"] = self.priority_value.value()
settings["includeDefaultRenderLayer"] = self.defaultlayer.isChecked()
settings["suspendPublishJob"] = self.publish.isChecked()

settings[machine_list_type] = machine_limits

return settings

def _apply_settings(self):

instance = mayalib.find_render_instance()
Expand All @@ -225,37 +254,58 @@ def _apply_settings(self):

# Apply settings from node
self.publish.setChecked(settings["suspendPublishJob"])
self.defaultlayer.setChecked(settings["includeDefaultRenderLayer"])
self.priority_slider.setValue(settings["priority"])
self.defaultlayer.setChecked(settings["includeDefaultRenderLayer"])
self.run_slap_comp.setChecked(settings["runSlapComp"])

if settings.get("flowFile", None):
self.flow_file.setText(settings["flowFile"])

white_list = "Whitelist" in settings
white_list = "whitelist" in settings
self.white_list.setChecked(white_list)
self.black_list.setChecked(not white_list)

self.listed_machines.addItems(settings["machineList"].split())

def _get_list_type(self):
if self.white_list.isChecked():
return "Whitelist"
else:
return "Blacklist"
return self.white_list.isChecked()

def _get_listed_machines(self):
items = [self.listed_machines.item(r) for r in
range(self.listed_machines.count())]
listed_machines = [i.text() for i in items]
# Turn unicode to strings
return [str(self.listed_machines.item(r).text()) for r in
range(self.listed_machines.count())]


def show(root=None, debug=False, parent=None):
"""Display Loader GUI

return listed_machines
Arguments:
debug (bool, optional): Run loader in debug-mode,
defaults to False

"""

try:
module.window.close()
del module.window
except (RuntimeError, AttributeError):
pass

if debug is True:
io.install()

def launch():
global application
application = App()
application.show()
any_project = next(
project for project in io.projects()
if project.get("active", True) is not False
)

api.Session["AVALON_PROJECT"] = any_project["name"]

if __name__ == '__main__':
import sys
with tools_lib.application():
window = App(parent)
# Do not apply stylesheet, not nessecary in Maya
# window.setStyleSheet(style.load_stylesheet())
window.show()
window.refresh()

app = QtWidgets.QApplication(sys.argv)
test = App()
test.show()
app.exec_()
module.window = window
36 changes: 29 additions & 7 deletions python/deadlinesubmissionsettings/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,35 @@

import logging

import avalon
import os

from avalon import io, api, pipeline
from avalon.vendor import requests


log = logging.getLogger("DSS - Lib")


def get_work_directory():
"""Get the work directory to Fusion through the template"""

session = api.Session.copy()
project = io.find_one({"type": "project",
"name": api.Session["AVALON_PROJECT"]})
assert project, "This is a bug"
template = project["config"]["template"]["work"]

session["AVALON_TASK"] = "comp"
session["AVALON_APP"] = "fusion"
work_directory = pipeline._format_work_template(template, session)

if not os.path.isdir(work_directory):
print("Fusion app folder does not exist:\n%s" % work_directory)
work_directory = pipeline._format_work_template(template, api.Session)

return work_directory


def query(argument):
"""Lazy wrapper for request.get"""

Expand All @@ -29,22 +51,22 @@ def query(argument):

def get_machine_list(debug=None):
"""Fetch the machine list (slaves) from Deadline"""
AVALON_SESSION = debug or avalon.Session["AVALON_DEADLINE"]
argument = "{}/api/slaves?NamesOnly=true".format(AVALON_SESSION)
AVALON_DEADLINE = debug or api.Session["AVALON_DEADLINE"]
argument = "{}/api/slaves?NamesOnly=true".format(AVALON_DEADLINE)
return query(argument=argument)


def get_pool_list(debug=None):
"""Get all pools from Deadline"""
AVALON_SESSION = debug or avalon.Session["AVALON_DEADLINE"]
argument = "{}/api/pools?NamesOnly=true".format(AVALON_SESSION)
AVALON_DEADLINE = debug or api.Session["AVALON_DEADLINE"]
argument = "{}/api/pools?NamesOnly=true".format(AVALON_DEADLINE)
return query(argument)


def get_group_list(debug=None):
"""Get all groups from Deadline"""
AVALON_SESSION = debug or avalon.Session["AVALON_DEADLINE"]
argument = "{}/api/groups?NamesOnly=true".format(AVALON_SESSION)
AVALON_DEADLINE = debug or api.Session["AVALON_DEADLINE"]
argument = "{}/api/groups?NamesOnly=true".format(AVALON_DEADLINE)
return query(argument)


Expand Down
Loading