Skip to content

Commit

Permalink
Crank: add support to use existing blendshapes nodes or creating node…
Browse files Browse the repository at this point in the history
…s in foc. First working version #416
  • Loading branch information
miquelcampos committed Jul 9, 2024
1 parent 249093e commit b7516c4
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 31 deletions.
94 changes: 68 additions & 26 deletions release/scripts/mgear/crank/crank_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
####################################

CRANK_TAG = "_isCrankLayer"
CRANK_BS_TAG = "_isCrankLayerBS"
CRANK_RENDER_LAYER_NAME = "crankLayer_randomColor"
CHANNEL_BOX_NAME = "Crank_Box"

Expand All @@ -50,11 +51,13 @@
####################################


def create_layer(oSel):
def create_layer(oSel, foc=False, useExsitingBS=False):
"""Create new crank layer for shot sculpting
Args:
oSel (Mesh list): Objects to be included in the layer
foc (bool, optional): Set the blendshape node in Front of the chain
useExsitingBS (bool, optional): If true will try to use existing blendshape
Returns:
dagNode: cranklayer node with all the layer data
Expand All @@ -80,42 +83,79 @@ def create_layer(oSel):
text = pm.promptDialog(query=True, text=True)
name = string.normalize(text)

layer_node = create_layer_node(name, oSel)
bs_list = create_blendshape_node(name, oSel)
for bs in bs_list:
layer_node.crank_layer_envelope >> bs.envelope
idx = attribute.get_next_available_index(
layer_node.layer_blendshape_node
)
pm.connectAttr(
bs.message, layer_node.layer_blendshape_node[idx]
)
bs.isHistoricallyInteresting.set(False)
pm.select(oSel)

return layer_node


def create_blendshape_node(bsName, oSel):
bs_list = create_blendshape_node(
name, oSel, foc=foc, useExsitingBS=useExsitingBS
)
# avoid creating layer if there are not blendshapes
if bs_list:
layer_node = create_layer_node(name, oSel)
for bs in bs_list:
layer_node.crank_layer_envelope >> bs.envelope
idx = attribute.get_next_available_index(
layer_node.layer_blendshape_node
)
pm.connectAttr(
bs.message, layer_node.layer_blendshape_node[idx]
)
if not useExsitingBS:
bs.isHistoricallyInteresting.set(False)
pm.select(oSel)

return layer_node


def create_blendshape_node(bsName, oSel, foc=False, useExsitingBS=False):
"""Create the blendshape node for each object in the layer
Args:
bsName (str): The name prefix for the blendshape node
oSel (Mesh list): The object to apply the blendshape node
foc (bool, optional): Set the blendshape node in Front of the chain
useExsitingBS (bool, optional): If true will try to use existing blendshape
Returns:
PyNode: The blendshape node list
"""
bs_list = []
creation_abort = False
for obj in oSel:
bs = pm.blendShape(
obj,
name="_".join([obj.name(), bsName, "blendShape_crank"]),
foc=False,
)[0]
bs_list.append(bs)
if useExsitingBS:
bs = None
bs_hist = pm.listHistory(obj.getShape(), type="blendShape")
for previous_bs in bs_hist:
if not previous_bs.hasAttr(CRANK_BS_TAG):
bs = previous_bs
break
if not bs:
pm.displayWarning(
"Object: {} don't have any previous blendshape node to use or not managed by Crank. Layer creation aborted".format(
obj.name()
)
)
creation_abort = True

return bs_list
else:
bs = pm.blendShape(
obj,
name="_".join([obj.name(), bsName, "blendShape_crank"]),
foc=foc,
)[0]
if bs:
# this attr will tag new bs nodes or existing bs nodes
# as managed by crank
attribute.addAttribute(
bs, CRANK_BS_TAG, "bool", False, keyable=False
)
bs_list.append(bs)

# if any of the objects is missing a blendshape node we will abort
# the layer creation
# I do the abort return here so we can get the complete print of warnings
# for all the objects
if creation_abort:
return None
else:
return bs_list


def create_layer_node(name, affectedElements):
Expand Down Expand Up @@ -836,7 +876,9 @@ def select_layer_node(self):

def create_layer(self):
"""Create a new layer and update the window list"""
create_layer(pm.selected())
foc = self.crankUIWInst.foc_checkBox.isChecked()
useExistingBS = self.crankUIWInst.useExistingBS_checkBox.isChecked()
create_layer(pm.selected(), foc=foc, useExsitingBS=useExistingBS)
self._refreshList()

def add_frame_sculpt(self):
Expand Down
17 changes: 15 additions & 2 deletions release/scripts/mgear/crank/crank_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Form implementation generated from reading ui file 'C:/datawork/repo/mgear4/release/scripts/mgear/crank/crank_ui.ui'
#
# Created: Tue Feb 20 09:34:46 2024
# Created: Tue Jul 9 12:44:23 2024
# by: pyside2-uic running on PySide2 2.0.0~alpha0
#
# WARNING! All changes made in this file will be lost!
Expand All @@ -12,7 +12,7 @@
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(299, 590)
Form.resize(401, 691)
self.gridLayout_4 = QtWidgets.QGridLayout(Form)
self.gridLayout_4.setSpacing(0)
self.gridLayout_4.setContentsMargins(5, 5, 5, 5)
Expand Down Expand Up @@ -49,6 +49,14 @@ def setupUi(self, Form):
self.layers_listView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.layers_listView.setObjectName("layers_listView")
self.gridLayout_2.addWidget(self.layers_listView, 2, 0, 1, 1)
self.foc_checkBox = QtWidgets.QCheckBox(self.groupBox)
self.foc_checkBox.setChecked(False)
self.foc_checkBox.setObjectName("foc_checkBox")
self.gridLayout_2.addWidget(self.foc_checkBox, 3, 0, 1, 1)
self.useExistingBS_checkBox = QtWidgets.QCheckBox(self.groupBox)
self.useExistingBS_checkBox.setChecked(False)
self.useExistingBS_checkBox.setObjectName("useExistingBS_checkBox")
self.gridLayout_2.addWidget(self.useExistingBS_checkBox, 4, 0, 1, 1)
self.gridLayout_4.addWidget(self.groupBox, 0, 0, 1, 1)
self.groupBox_2 = QtWidgets.QGroupBox(Form)
self.groupBox_2.setObjectName("groupBox_2")
Expand Down Expand Up @@ -117,13 +125,18 @@ def setupUi(self, Form):
self.gridLayout_4.addWidget(self.groupBox_2, 1, 0, 1, 1)

self.retranslateUi(Form)
QtCore.QObject.connect(self.useExistingBS_checkBox, QtCore.SIGNAL("clicked(bool)"), self.foc_checkBox.setDisabled)
QtCore.QMetaObject.connectSlotsByName(Form)

def retranslateUi(self, Form):
Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1))
self.groupBox.setTitle(QtWidgets.QApplication.translate("Form", "Sculpt Layers", None, -1))
self.createLayer_pushButton.setText(QtWidgets.QApplication.translate("Form", "Create Layer", None, -1))
self.refresh_pushButton.setText(QtWidgets.QApplication.translate("Form", "Refresh", None, -1))
self.foc_checkBox.setToolTip(QtWidgets.QApplication.translate("Form", "<html><head/><body><p>Create a New BlendShape node in Front of Chain (FOC)</p></body></html>", None, -1))
self.foc_checkBox.setText(QtWidgets.QApplication.translate("Form", "New BS node in front of chain", None, -1))
self.useExistingBS_checkBox.setToolTip(QtWidgets.QApplication.translate("Form", "<html><head/><body><p>Crank will use only existing Blendshapes nodes that are <span style=\" font-weight:600;\">not already managed </span>with other Crank layer. <br/>If any suitable Blendshape node is found the tool will <span style=\" font-weight:600;\">NOT create</span> a new node for the given object and the layer creation will be aborted</p></body></html>", None, -1))
self.useExistingBS_checkBox.setText(QtWidgets.QApplication.translate("Form", "Use Only Existing BlendShape Node", None, -1))
self.groupBox_2.setTitle(QtWidgets.QApplication.translate("Form", "Sculpt Frames", None, -1))
self.label_4.setText(QtWidgets.QApplication.translate("Form", "Post Hold", None, -1))
self.label.setText(QtWidgets.QApplication.translate("Form", "Ease In", None, -1))
Expand Down
49 changes: 46 additions & 3 deletions release/scripts/mgear/crank/crank_ui.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>299</width>
<height>590</height>
<width>401</width>
<height>691</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -106,6 +106,32 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="foc_checkBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Create a New BlendShape node in Front of Chain (FOC)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>New BS node in front of chain</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="useExistingBS_checkBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Crank will use only existing Blendshapes nodes that are &lt;span style=&quot; font-weight:600;&quot;&gt;not already managed &lt;/span&gt;with other Crank layer. &lt;br/&gt;If any suitable Blendshape node is found the tool will &lt;span style=&quot; font-weight:600;&quot;&gt;NOT create&lt;/span&gt; a new node for the given object and the layer creation will be aborted&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Use Only Existing BlendShape Node</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down Expand Up @@ -249,5 +275,22 @@
</layout>
</widget>
<resources/>
<connections/>
<connections>
<connection>
<sender>useExistingBS_checkBox</sender>
<signal>clicked(bool)</signal>
<receiver>foc_checkBox</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>181</x>
<y>313</y>
</hint>
<hint type="destinationlabel">
<x>183</x>
<y>289</y>
</hint>
</hints>
</connection>
</connections>
</ui>

0 comments on commit b7516c4

Please sign in to comment.