Sunday, December 21, 2014

Maya API: Setup Maya Plugin Wizard

I always got trouble to setup my Visual Studio for Maya C++ API. I saw couple different tutorials teaching how to setup, but some are over complex.

So, here I introduce a simple way. Hope it will help you step into Maya API world.
  • Go to your Maya directory, there is a pluginwizard fold underneath devkit folder, inside you should have MayaPluginWizard2.0.zip and MayaWizardReadme.txt

  • Extract MayaPluginWizard2.0.zip, you will get a MayaPluginWizard folder, inside of the folder, you should have MayaPluginWizard folder, MayaPluginWizard.ico,  MayaPluginWizard.vsdirMayaPluginWizard.vsz


  • Go to your Visual Studio directory, there is VCWizards folder underneath VC folder, copy the top MayaPluginWizard folder to here


  • Go to vcprojects folder, which is also underneath VC folder, copy MayaPluginWizard.ico,  MayaPluginWizard.vsdirMayaPluginWizard.vsz to here.

  • Use text editor to open MayaPluginWizard.vsz, and make sure the VsWizardEngine version number matches your Visual Studio version number. The default is 10.0. For example, my Visual Studio is 11.0, so I need to change here.

  • Once these all set up, you should be ready to go. Open your Visual Studio, and create a new C++ project, you will see Maya Plug-in Wizard

Saturday, December 20, 2014

Research & Study: Skin Weights

Here are a comparison by using different Maya smooth skin bind methods(default settings) to bind a character:
  • Closest distance
    • Ignores joint hierarchy
    • Using distance between vertexes and joint to bind
    • Causes inappropriate influences on nearby discontinuous area
    • Over falloff covers inappropriate area
  • Closest in hierarchy
    • Joint influence is based on skeleton hierarchy
    • Prevent inappropriate influences like closest distance method
    • Over falloff covers inappropriate area
  • Heat Map
    • Polygon mesh only
    • May fail when finding bad faces
    • Long time calculate to generate influences
    • Better falloff but a little bit rigid for organic rigging


Another comparison on complex shoulder part:



According to above comparison, none of the skin bind methods can provide 80-90% well-done skin influences. Less or more, they have different disadvantages. As well as, none of them provides interactive skin bind method, or easy and quick setup method, instead of traditional painting skin weights, which has already been using in over 20 years.


Maya also has Interactive Skin Bind, a good idea, but not good to use at all.
  • Interactive Skin Bind
    • Cannot be used on NURBS
    • Not accurate at initial setup, also hard to get accurate result by adjusting its manipulator
    • manipulator is not user-friendly, like hard to rotate or translate the manipulator
    • Increase the influences by dragging or changing the size of interactive skin bind manipulator. The manipulator may affect to discontinuous area, like legs or fingers, and causes inappropriate influences
    • Linear workflow with painting skin weights, which means user can use interactive skin bind to breakdown or initialize skin influences, then paint skin weights to get accurate result, but if goes back to use interactive skin bind manipulator to adjust the skin weights, user will lose what just painted skin weights.

Saturday, December 13, 2014

PyQt (5): QIcon & QPixmap

QIcon is used to create icons, and QPixmap is used to attach image on widget.

Case 1: 
touch image on a button.

Example:
from PyQt4 import QtGui, QtCore

# create icon and load image
icon = QtGui.QIcon('C:\icons\myIcon.png')
# create a button
button = QtGui.QPushButton()
# set icon to button
button.setIcon(icon)
# set the size of the icon
button.setIconSize(QtCore.QSize(200,200))
# show the button
button.show()
Case 2: 
set window icon.

Example:
from PyQt4 import QtGui, QtCore

# create icon and load image
icon = QtGui.QIcon('C:\icons\myIcon.png')
# create a widget
widget = QtGui.QWidget()
# set the icon as widget window icon
widget.setWindowIcon(icon)
# show the widget
widget.show()
Case 3: 
touch image to widget.

Example:
from PyQt4 import QtGui, QtCore

# create label widget, which is used to carry the image
label = QtGui.QLabel()
# create QPixmap and load the image
myPixmap = QtGui.QPixmap('C:\icons\myIcon.png')
# set pixmap to the label widget
label.setPixmap(myPixmap)
# show the widget
label.show()

Sunday, December 7, 2014

PyQt (4): QLineEdit

QLineEdit is a widget using to create a one-line text editor.

Case 1: 
The QLineEdit is used to be a user input area

Example:
from PyQt4 import QtGui, QtCore

# create main widget and its layout
mainWidget = QtGui.QWidget()
mainLayout = QtGui.QHBoxLayout()
mainWidget.setLayout(mainLayout)

# create a label
label = QtGui.QLabel('PrintOut Button: ')
# fine-tune the appearance of aligned text
label.setAlignment(QtCore.Qt.AlignCenter)

# create text area
textLine = QtGui.QLineEdit()
# set text when the text area is not activated
textLine.setPlaceholderText('please input something here!')

# create a button
btn = QtGui.QPushButton('Print')

# create button click function to print out what input in text line
def clickFunc():
    print str(textLine.text())

# create signal for the button
# when click the button, excute the click function
btn.clicked.connect(clickFunc)

# add ui elements to the main layout
mainLayout.addWidget(label)
mainLayout.addWidget(textLine)
mainLayout.addWidget(btn)

# show the main widget
mainWidget.show()
Case 2: 
The QLineEdit is used to be a display area and do not allow user to edit

Example:
from PyQt4 import QtGui, QtCore
import maya.cmds as mc

mainWidget = QtGui.QWidget()
mainLayout = QtGui.QHBoxLayout()
mainWidget.setLayout(mainLayout)

# create a label
label = QtGui.QLabel('File Path: ')
# fine-tune the appearance of aligned text
label.setAlignment(QtCore.Qt.AlignCenter)

# create text area
textLine = QtGui.QLineEdit()
# set text when the text area is not activated
textLine.setText('C:/test/test.py')
# set the text is read only, so that user still can copy text from text area
textLine.setReadOnly(True)

# add ui elements to the main layout
mainLayout.addWidget(label)
mainLayout.addWidget(textLine)

# show the main widget
mainWidget.show()

PyQt (3): QLabel

QLabel is a widget using to display text or image.

QtCore.Qt.AlignmentFlag provides flags to fine-tune the apperance of aligned text:

QtCore.Qt.QtAlignTop
QtCore.Qt.AlignBottom
QtCore.Qt.AlignRight
QtCore.Qt.AlignLeft
QtCore.Qt.AlignVCenter
QtCore.Qt.AlignHCenter
QtCore.Qt.AlignCenter

Example:
from PyQt4 import QtGui, QtCore

# create main widget and its layout
mainWidget = QtGui.QWidget()
mainLayout = QtGui.QHBoxLayout()
mainWidget.setLayout(mainLayout)

# create a label
label = QtGui.QLabel('PrintOut Button: ')
# fine-tune the appearance of aligned text
label.setAlignment(QtCore.Qt.AlignCenter)

# create a button
btn = QtGui.QPushButton('Button')

# create button click function
def clickFunc():
    print 'This is a button!'

# create signal for the button
# when click the button, excute the click function
btn.clicked.connect(clickFunc)

# add label and button to the main layout
mainLayout.addWidget(label)
mainLayout.addWidget(btn)

# show the main widget
mainWidget.show()

PyQt (2): QPushButton

QPushButton is a widget using to create a button.

Example:
from PyQt4 import QtGui
# create a button
btn = QtGui.QPushButton('Button')

# create button click function
def clickFunc():
    print 'This is a button!'

# create signal for the button
# when click the button, excute the click function
btn.clicked.connect(clickFunc)

# show the button ui
btn.show()

Thursday, December 4, 2014

Trick & Tip: Flat Dictionary and List

Case 1: flat a dictionary
Sometimes, we may have a dictionary which may have other dictionaries as its values.

Here is a method to flat the complex dictionary to a list, whose first item is the Key from dictionary and rest of items are the Value from dictionary.

Example:
# flat dictionary function
def flatDict(dic):
    def _flatDict(dic, list=[]):
        for k, v in dic.iteritems():
            if isinstance(v, type(dic)):
                _flatDict(v, list)
            else:
                list.append((k, v))
        return list
    return _flatDict(dic)

# create a dictionary
dic = {1:{'a':'red', 'b':'green', 'c':'blue'}, 2:{'L1':[1,2,3], 'L2':[10,20,30], 'L3': [100, 200, 300]}, 3:'this is a test!'}

# print flatten dictionary
print flatDict(dic)


Case 2: flat a list
Also, sometimes, we may meet a list which contents multiple list inside.

Here is a method to flat the complex list to a simple 1-level list.

Example:
# flat list function
def flatList(list):
    def _flatList(list, output=[]):
        for i in list:
            if isinstance(i, type(list)):
                _flatList(i)
            else:
                output.append(i)
        return output
    return _flatList(list)

# create a list
l = [1,2,3, ['a', 'b', ['red', 'yellow', 'blue'], 'c'], 5, 6]

# print out flatten list
print flatList(l)