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

Max: Allows user to select material duplicates option during loading max scene object #164

Merged
merged 9 commits into from
Mar 13, 2024
87 changes: 82 additions & 5 deletions client/ayon_core/hosts/max/plugins/load/load_max_scene.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import os

from qtpy import QtWidgets, QtCore
from ayon_core.lib.attribute_definitions import EnumDef
from ayon_core.hosts.max.api import lib
from ayon_core.hosts.max.api.lib import (
unique_namespace,
get_namespace,
object_transform_set
object_transform_set,
is_headless
)
from ayon_core.hosts.max.api.pipeline import (
containerise, get_previous_loaded_object,
Expand All @@ -14,6 +16,59 @@
from ayon_core.pipeline import get_representation_path, load


class MaterialDupOptionsWindow(QtWidgets.QDialog):
"""The pop-up dialog allows users to choose material
duplicate options for importing Max objects when updating
or switching assets.
"""
def __init__(self, material_options):
super(MaterialDupOptionsWindow, self).__init__()
self.setWindowFlags(self.windowFlags() | QtCore.Qt.FramelessWindowHint)

self.material_option = None
self.material_options = material_options

self.widgets = {
"label": QtWidgets.QLabel(
"Select material duplicate options before loading the max scene."),
"material_options_list": QtWidgets.QListWidget(),
"warning": QtWidgets.QLabel("No material options selected!"),
"buttons": QtWidgets.QWidget(),
"okButton": QtWidgets.QPushButton("Ok"),
"cancelButton": QtWidgets.QPushButton("Cancel")
}
for key, value in material_options.items():
item = QtWidgets.QListWidgetItem(value)
self.widgets["material_options_list"].addItem(item)
item.setData(QtCore.Qt.UserRole, key)
# Build buttons.
layout = QtWidgets.QHBoxLayout(self.widgets["buttons"])
layout.addWidget(self.widgets["okButton"])
layout.addWidget(self.widgets["cancelButton"])
# Build layout.
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.widgets["label"])
layout.addWidget(self.widgets["material_options_list"])
layout.addWidget(self.widgets["buttons"])

self.widgets["okButton"].pressed.connect(self.on_ok_pressed)
self.widgets["cancelButton"].pressed.connect(self.on_cancel_pressed)
self.widgets["material_options_list"].itemPressed.connect(
self.on_material_options_pressed)

def on_material_options_pressed(self, item):
self.material_option = item.data(QtCore.Qt.UserRole)

def on_ok_pressed(self):
if self.material_option is None:
self.widgets["warning"].setVisible(True)
return
self.close()

def on_cancel_pressed(self):
self.material_option = "promptMtlDups"
self.close()

class MaxSceneLoader(load.LoaderPlugin):
"""Max Scene Loader."""

Expand All @@ -25,14 +80,31 @@ class MaxSceneLoader(load.LoaderPlugin):
order = -8
icon = "code-fork"
color = "green"
mtl_dup_default = "promptMtlDups"
mtl_dup_enum_dict = {
"promptMtlDups": "Prompt on Duplicate Materials",
"useMergedMtlDups": "Use Incoming Material",
"useSceneMtlDups": "Use Scene Material",
"renameMtlDups": "Merge and Rename Incoming Material"
}
@classmethod
def get_options(cls, contexts):
return [
EnumDef("mtldup",
items=cls.mtl_dup_enum_dict,
default=cls.mtl_dup_default,
label="Material Duplicate Options")
]

def load(self, context, name=None, namespace=None, data=None):
def load(self, context, name=None, namespace=None, options=None):
from pymxs import runtime as rt
mat_dup_options = options.get("mtldup", self.mtl_dup_default)
path = self.filepath_from_context(context)
path = os.path.normpath(path)
# import the max scene by using "merge file"
path = path.replace('\\', '/')
rt.MergeMaxFile(path, quiet=True, includeFullGroup=True)
rt.MergeMaxFile(path, rt.Name(mat_dup_options),
quiet=True, includeFullGroup=True)
max_objects = rt.getLastMergedNodes()
max_object_names = [obj.name for obj in max_objects]
# implement the OP/AYON custom attributes before load
Expand Down Expand Up @@ -67,7 +139,12 @@ def update(self, container, context):
for prev_max_obj in prev_max_objects:
if rt.isValidNode(prev_max_obj): # noqa
rt.Delete(prev_max_obj)
rt.MergeMaxFile(path, quiet=True)
material_option = self.mtl_dup_default
if not is_headless():
window = MaterialDupOptionsWindow(self.mtl_dup_enum_dict)
window.exec_()
material_option = window.material_option
rt.MergeMaxFile(path, rt.Name(material_option), quiet=True)

current_max_objects = rt.getLastMergedNodes()

Expand Down