From 71d07a2b9f098e4a734bbf246b6b1f9c1d686d0b Mon Sep 17 00:00:00 2001 From: Marcus Ottosson Date: Tue, 17 Jan 2017 11:23:10 +0100 Subject: [PATCH 1/6] Implement #7 --- bin/maya.bat | 2 +- example/README.md | 3 +++ .../assets/Bruce/work/temp/marcus/maya/workspace.mel | 10 ++++++++++ res/README.md | 3 +++ res/workspace.mel | 10 ++++++++++ 5 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 example/README.md create mode 100644 example/projects/hulk/assets/Bruce/work/temp/marcus/maya/workspace.mel create mode 100644 res/README.md create mode 100644 res/workspace.mel diff --git a/bin/maya.bat b/bin/maya.bat index 96abb0c..bbcc174 100644 --- a/bin/maya.bat +++ b/bin/maya.bat @@ -33,7 +33,7 @@ if Not exist %WORKDIR% ( mkdir %WORKDIR%\images rem etc.. - copy %PYBLISH%\etc\maya\workspace.mel %WORKDIR% >NUL + copy %PYBLISH_MINDBENDER%\res\workspace.mel %WORKDIR% >NUL ) :: userSetup.py files diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..4f46224 --- /dev/null +++ b/example/README.md @@ -0,0 +1,3 @@ +### Example + +This directory represents a shared network location. diff --git a/example/projects/hulk/assets/Bruce/work/temp/marcus/maya/workspace.mel b/example/projects/hulk/assets/Bruce/work/temp/marcus/maya/workspace.mel new file mode 100644 index 0000000..e9f0c3c --- /dev/null +++ b/example/projects/hulk/assets/Bruce/work/temp/marcus/maya/workspace.mel @@ -0,0 +1,10 @@ +//Maya 2016 Project Definition + +workspace -fr "shaders" "renderData/shaders"; +workspace -fr "alembicCache" "cache/alembic"; +workspace -fr "mayaAscii" "scenes"; +workspace -fr "mayaBinary" "scenes"; +workspace -fr "renderData" "renderData"; +workspace -fr "fileCache" "cache/nCache"; +workspace -fr "scene" "scenes"; +workspace -fr "sourceImages" "sourceimages"; diff --git a/res/README.md b/res/README.md new file mode 100644 index 0000000..3e8741a --- /dev/null +++ b/res/README.md @@ -0,0 +1,3 @@ +### Resources + +Native files for various applications, including thumbnails, icons and data files. diff --git a/res/workspace.mel b/res/workspace.mel new file mode 100644 index 0000000..e9f0c3c --- /dev/null +++ b/res/workspace.mel @@ -0,0 +1,10 @@ +//Maya 2016 Project Definition + +workspace -fr "shaders" "renderData/shaders"; +workspace -fr "alembicCache" "cache/alembic"; +workspace -fr "mayaAscii" "scenes"; +workspace -fr "mayaBinary" "scenes"; +workspace -fr "renderData" "renderData"; +workspace -fr "fileCache" "cache/nCache"; +workspace -fr "scene" "scenes"; +workspace -fr "sourceImages" "sourceimages"; From 945f1e9890e40bb0b01c53f6dde1fd1a3b64e05e Mon Sep 17 00:00:00 2001 From: Marcus Ottosson Date: Tue, 17 Jan 2017 13:53:13 +0100 Subject: [PATCH 2/6] Implement #8 --- mindbender/maya/lib.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mindbender/maya/lib.py b/mindbender/maya/lib.py index b369158..f206135 100644 --- a/mindbender/maya/lib.py +++ b/mindbender/maya/lib.py @@ -318,7 +318,13 @@ def apply_shaders(relationships): assert shader, "Associated shader not part of asset, this is a bug" for id_ in ids: - meshes = lsattr("mbID", value=id_) + mesh, faces = (id_.rsplit(".", 1) + [""])[:2] + + # Find all meshes matching this particular ID + # Convert IDs to mesh + id, e.g. "nameOfNode.f[1:100]" + meshes = list(".".join([mesh, faces]) + for mesh in lsattr("mbID", value=mesh)) + if not meshes: continue From a3137cb09ea90a24c6b4ee5e028c95450de0b336 Mon Sep 17 00:00:00 2001 From: Marcus Ottosson Date: Tue, 17 Jan 2017 13:53:23 +0100 Subject: [PATCH 3/6] Add look development validators --- mindbender/plugins/validate_lookdev_.py | 40 +++++++++++++++++++ .../plugins/validate_lookdev_member_type.py | 23 +++++++++++ 2 files changed, 63 insertions(+) create mode 100644 mindbender/plugins/validate_lookdev_.py create mode 100644 mindbender/plugins/validate_lookdev_member_type.py diff --git a/mindbender/plugins/validate_lookdev_.py b/mindbender/plugins/validate_lookdev_.py new file mode 100644 index 0000000..933a697 --- /dev/null +++ b/mindbender/plugins/validate_lookdev_.py @@ -0,0 +1,40 @@ +import pyblish.api + + +class ValidateMindbenderLookdevSingleShape(pyblish.api.InstancePlugin): + """One mesh per transform""" + + label = "Lookdev Member Shapes" + order = pyblish.api.ValidatorOrder + hosts = ["maya"] + families = ["mindbender.lookdev"] + + def process(self, instance): + from maya import cmds + + has_multiple_shapes = list() + for node in instance: + + children = cmds.listRelatives(node, allDescendents=True) or list() + shapes = cmds.listRelatives(node, shapes=True) or list() + + # Ensure there is only one child; there could be many, + # including other transform nodes. + has_single_shape = len(children) == 1 + + # Ensure the one child is a shape + has_single_child = len(shapes) == 1 + + # Ensure the one child is of type "mesh" + has_single_mesh = cmds.nodeType(shapes[0]) == "mesh" + + if not all([has_single_child, + has_single_shape, + has_single_mesh]): + has_multiple_shapes.append(node) + + assert not has_multiple_shapes, ( + "\"%s\" has transforms with multiple shapes: %s" % ( + instance, ", ".join( + "\"" + member + "\"" for member in has_multiple_shapes)) + ) diff --git a/mindbender/plugins/validate_lookdev_member_type.py b/mindbender/plugins/validate_lookdev_member_type.py new file mode 100644 index 0000000..1b5a7d2 --- /dev/null +++ b/mindbender/plugins/validate_lookdev_member_type.py @@ -0,0 +1,23 @@ +import pyblish.api + + +class ValidateMindbenderLookdevMembers(pyblish.api.InstancePlugin): + """A lookdev instance must only contain members of type 'transform'""" + + label = "Lookdev Member Type" + order = pyblish.api.ValidatorOrder + hosts = ["maya"] + families = ["mindbender.lookdev"] + + def process(self, instance): + from maya import cmds + + has_wrong_type = list( + node for node in instance + if cmds.nodeType(node) != "transform" + ) + + assert not has_wrong_type, "\"%s\" is has_wrong_type members: %s" % ( + instance, ", ".join("\"" + member + "\"" + for member in has_wrong_type)) + From f55d590004874f9ec64c041b5630321e686bf6f9 Mon Sep 17 00:00:00 2001 From: Marcus Ottosson Date: Tue, 17 Jan 2017 13:53:33 +0100 Subject: [PATCH 4/6] Extend ID validator to lookdev --- mindbender/plugins/validate_id.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mindbender/plugins/validate_id.py b/mindbender/plugins/validate_id.py index 3bb1e4d..16464bd 100644 --- a/mindbender/plugins/validate_id.py +++ b/mindbender/plugins/validate_id.py @@ -7,7 +7,7 @@ class ValidateMindbenderID(pyblish.api.InstancePlugin): label = "Mindbender ID" order = pyblish.api.ValidatorOrder hosts = ["maya"] - families = ["mindbender.model"] + families = ["mindbender.model", "mindbender.lookdev"] def process(self, instance): from maya import cmds From fbf6bd71896f2113a23232d8aa4189331dac337a Mon Sep 17 00:00:00 2001 From: Marcus Ottosson Date: Tue, 17 Jan 2017 13:53:46 +0100 Subject: [PATCH 5/6] Fix bug in Creator, on editing the name --- mindbender/tools/creator/app.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/mindbender/tools/creator/app.py b/mindbender/tools/creator/app.py index a3e8776..6ac352a 100644 --- a/mindbender/tools/creator/app.py +++ b/mindbender/tools/creator/app.py @@ -81,15 +81,25 @@ def __init__(self, parent=None): create_btn.clicked.connect(self.on_create) name.returnPressed.connect(self.on_create) - name.textChanged.connect(self.on_data_changed) - listing.currentItemChanged.connect(self.on_data_changed) + name.textChanged.connect(self.on_name_changed) + listing.currentItemChanged.connect(self.on_selection_changed) # Defaults self.resize(220, 250) name.setFocus() create_btn.setEnabled(False) - def on_data_changed(self, *args): + def on_name_changed(self, *args): + button = self.findChild(QtWidgets.QPushButton, "Create Button") + name = self.findChild(QtWidgets.QWidget, "Name") + item = self.findChild(QtWidgets.QWidget, "Listing").currentItem() + + button.setEnabled( + name.text().strip() != "" and + item.data(QtCore.Qt.ItemIsEnabled) + ) + + def on_selection_changed(self, *args): button = self.findChild(QtWidgets.QPushButton, "Create Button") name = self.findChild(QtWidgets.QWidget, "Name") item = self.findChild(QtWidgets.QWidget, "Listing").currentItem() From a60d24e075111067ce363fe7f7ff76fddedbfcfc Mon Sep 17 00:00:00 2001 From: Marcus Ottosson Date: Tue, 17 Jan 2017 13:53:55 +0100 Subject: [PATCH 6/6] Enable multi-selection in Loader --- mindbender/tools/loader/app.py | 42 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/mindbender/tools/loader/app.py b/mindbender/tools/loader/app.py index bc74717..d305fa6 100644 --- a/mindbender/tools/loader/app.py +++ b/mindbender/tools/loader/app.py @@ -58,6 +58,9 @@ def __init__(self, parent=None): assets = QtWidgets.QListWidget() subsets = QtWidgets.QListWidget() + # Enable loading many subsets at once + subsets.setSelectionMode(subsets.ExtendedSelection) + layout = QtWidgets.QHBoxLayout(container) layout.addWidget(assets) layout.addWidget(subsets) @@ -255,31 +258,32 @@ def on_load_pressed(self): autoclose_checkbox = self.data["button"]["autoclose"] asset_item = assets_model.currentItem() - subset_item = subsets_model.currentItem() - if subset_item is None: - return + for subset_item in subsets_model.selectedItems(): - asset = asset_item.data(AssetRole) - subset = subset_item.data(SubsetRole) - assert asset - assert subset + if subset_item is None: + return - try: - api.registered_host().load(asset, subset) + asset = asset_item.data(AssetRole) + subset = subset_item.data(SubsetRole) + assert asset + assert subset + + try: + api.registered_host().load(asset, subset) - except ValueError as e: - self.echo(e) - raise + except ValueError as e: + self.echo(e) + raise - except NameError as e: - self.echo(e) - raise + except NameError as e: + self.echo(e) + raise - # Catch-all - except Exception as e: - self.echo("Program error: %s" % str(e)) - raise + # Catch-all + except Exception as e: + self.echo("Program error: %s" % str(e)) + raise if autoclose_checkbox.checkState(): self.close()