Mel et Python

What I have learned about Mel & Python

-----Mel-----

Float - Decimal

Integer - Whole Number

Relational Operators:

< less than

<= less than or equal to

> greater than

>= greater than or equal to

== equal to

!= not equal to

Logical Operators:

&& and - both first and second conditions will be tested

|| or

! not

Arithmetic Operators:

+ Add two elements together

- Subtract two elements

* Multiply two elements

% Find the fractional remainder of the division

^ Find the cross product of two vectors

++ increment values by 1

-- decrement values by 1

Boolean Operators:

true, yes, on, 1

false, no, off, 0

Order of Precedence in which they are evaluated:

PEMDAS

( ), [ ], !, ++, --

*, /, %, ^

+, -

<, <=, >, >=

==, !=

&&

||

?:

=, +=, -=, *=, /=

Variables:
int
float
string
vector
array
matrix

Delimiters that MEL recognizes:
( ) Used for grouping and to denote argument or parameter lists

[ ] Used for array and matrix declaration and their indexing

{ } Used for procedure definitions, code blocks, and literal array values

" " Used for string literals

\ Used for special characters (aka "escape characters")
in string literals (\", \n, \r, \t, \\, \<Enter>)

` ` Evaluates an imperative command or procedure call as a MEL expression.

$ Used to indicate variable names and array names.

<< >> Used to delimit vector literals and matrix literals.

, Delimiter arguments, parameters, and items in literal array, vector, or matrix.

; Statement delimiter, also used in literal matrix values and for loops.

: Used to delimit cases in switch... case statements, default branching, and in the "? :" operator.

// Used for single-line comments.

/* */ Used for multi-line comments.

Values:

False is given a value of 0 and True is given a value of 1

A single = sets the variable and does not test for equality use == to test for equality
Example:

// gotcha prints "Match Found" when the argument's value equals 4
global proc gotcha(int $theNum)
{
if ($theNum = 4) {
print ("Match Found!\n");
}
}


--------Python Keywords--------

The Python keywords are:
And
Def
finally
in
Print
As
Del
for
is
Raise
Assert
Elif
from
lambda
Return
Break
Else
global
not
Try
Class
Except
if
or
While
Continue
Exec
import
pass
With

Yield


These 31 keywords are built right into the language, and the vast majority of them are statements and statement modifiers, with about six of them being keyword operators rather than full-fledged statements in their own right. We made a big deal about distinguishing statements from expressions in MEL, because MEL is strict about only having certain expressions qualify as statements. In Python, any expression can be treated as a statement, and that distinction is no longer so important.
The nine Python keywords that we've already seen in MEL are indicated above in blue. There are eight more which are slight syntactic variations from MEL or which do something equivalent to a common MEL command, indicated above in teal. Python's scope management and error handling mechanisms are much more sophisticated than MEL's, and there are nine such keywords have no direct MEL counterpart. They are indicated in dark red for scope and context management, and the ones related to error handling appear in bright red. The remaining five pertain to classes, functions, and objects. One of them is grayed out because it's particularly obscure, but the final four, shown above in black, are very basic and very important.

The Python keywords fall into the following groups:

class & function definition class, lambda, def, return, yield
flow control: branching if, elif, else
flow control: looping for, in while, continue, break, pass
import, scope, and context from, import, as global, with
exception handling raise, assert, try, except, finally
handy utility statements del, print, exec
Boolean operators is, and, or, not, in


Operators
arithmetic operators
+ - * / % ** //
shift & bitwise operators
<< >> & | ^ ~
relational operators
== != < > <= >= < > is in
logical operators
and or not
evaluation branching
if else
assignment delimiters
= += -= *= /= %=
**= //= <<= >>= &= |= ^=




The arithmetic operators are the same ones we saw in MEL, with two new additions and one removal. The additions are the power raising operator (**) and the floor division operator (//). (Floor division is like regular division, but it casts the result to an integer value.) Python does not have the ^ symbol as a vector cross product.
The shift and bitwise operators are some features from C and C++ that were not included in MEL because they are not relevant to Maya. They work only on integer types, treating the values of their operands as binary data. You probably won't ever use them, but if you need more information, look in the Python Language Reference at www.python.org.
The relational operators are the same as MEL's, with one very marginal addition, which is that the test for inequality to can be written in either of two ways, != or <>. (Even so, < > is antiquated, and you should never use it the code you write.)
The other delimiters that Python uses for various purposes are as follows:
() [] {} "" '' \ `` @ . , ; : # ''' """

Gone are the << and >>, which in Python are used for a different purpose. Also gone is the $, which Python allows only in comments and string literals.

In Python, function parameters have no type declared with them, and as a result, type conversion is somewhat less of an issue. Types maintain their compatibility in all results, except when they are explicitly converted to a lower type. I refer you to the copious online Python documentation, if you really want to know more about how it all works. We've already said plenty about variable scoping and exception handling, and both of these are much cleaner in Python than they are in MEL. However, just like MEL, when you operate in script editor or command line, all the variables that you introduce become global, except when you contain them in some kind of object.

Operator
Description
( ) [ ] { }
` `
Binding & Collection Display
String Conversion
x[i] x[i1:i2] x(arg) x.att
Index, Slice, Call, Attribute
**
Exponentiation (Power)
+x -x ~x
Unary Sign & Bitwise NOT
* / // %
Multiplication, Division, Remainder
+ -
Addition & Subtraction
<< >>
Bitwise Shifts
&
Bitwise AND
^
Bitwise XOR
|
Bitwise OR
in not in is is not
== != < > < > <= >=
All Relational Operators
not
Boolean NOT
and
Boolean AND
or
Boolean OR
lambda
Lambda Expression



Here is a python script that I have been working on for a class assignment. Still a work in progress.  

 # This script works with Maya 2015 and has not been tested with previous versions.   
 # No new commands were used in thsi script. If you test it, please let me know if it works.  
 # I do have dyslexia so if you find certain words misspelled please let me know at glen@robotracingmadness.com   
 # Copyright Glen Debello 2014  
 import maya.cmds as cmds  
 def gd_cameraBox():  
   window_name = "CameraBox"  
   window_title = "Create Camera Box"  
   if cmds.window("CameraBox", q=True, exists=True):  
     cmds.deleteUI("CameraBox")  
   winName = cmds.window(title="gd_CameraBox")  
   cmds.columnLayout()  
   cmds.separator(height=5, style='none')  
   cmds.text(label="Camera Visualizer")  
   cmds.separator(height=5, style='none')  
   cmds.text(label='Create Camera with default settings')  
   cmds.button(label = "Create Camera", command = "gd_createCameraBox()")  
   cmds.separator(height=20, style='none')  
   # A new window will be created since the camera has not been created yet. The clipping controls window  
   # cannot be opened until it creates a camera. This has to do with certain sliders connecting to the cameras  
   # attributes.   
   cmds.text(label='Will open new window')  
   cmds.button(label="Camera Controls", command = "clippingControls()")  
   cmds.separator(height=10, style='none')  
   cmds.showWindow(winName)  
 # Creates the main window for creating the camera box     
 def gd_createCameraBox():  
   cameraName = cmds.camera(fcp ='250')  
   cameraShape = cameraName[1]  
   cmds.textCurves(f='Times-Roman', t='camera',)  
   cmds.polyPlane(ax = [0,0,1], n='nearClipPlane')  
   cmds.polyPlane(ax = [0,0,1], n='farClipPlane')  
   # creates a reverse node that is has an input from the camera and outputs to the nearClipReverse shape.   
   # If you do not create and connect the reverse node, the shape will always go in reverse. This only   
   # creates the revers node, it does not connect any attributes   
   cmds.shadingNode('reverse', asUtility = True, n='nearClipReverse')  
   cmds.shadingNode('reverse', asUtility = True, n='farClipReverse')  
   # creates a custom resolution node that connects the render resolution   
   # to the far clipping plane shape.  
   cmds.shadingNode('resolution', asUtility=True, n='resolutionCustom1')  
   # connects the attributes associated with the resolution node and connects them  
   # to the width and height of the farclipping plane.  
   cmds.connectAttr('resolutionCustom1.width', 'polyPlane2.width')  
   cmds.connectAttr('resolutionCustom1.height', 'polyPlane2.height')  
   # connects the camera shape near clip plane to the reverse node. The reverse node was created  
   # earlier. We use the cmds.connectAttr to connect them to the reverse node.  
   cmds.connectAttr('cameraShape1.nearClipPlane', 'nearClipReverse.input.inputZ')  
   cmds.connectAttr('nearClipReverse.outputZ', 'nearClipPlane.translateZ')  
   cmds.connectAttr('cameraShape1.farClipPlane', 'farClipReverse.input.inputZ')  
   cmds.connectAttr('farClipReverse.outputZ', 'farClipPlane.translateZ')  
   #cmds.connectAttr('resolution1.width.', 'farClipPlane.scaleZ')  
   # Parents the the camera, far and near clipping planes, camera text, and creates a group.  
   cmds.parent('nearClipPlane', 'camera1', relative=True)  
   cmds.parent('farClipPlane', 'camera1', relative=True)  
   cmds.group('camera1', 'nearClipPlane', n='gd_visualGroup1')  
   cmds.parent('Text_camera_1', 'gd_visualGroup1')  
 def clippingControls():  
   if cmds.window("CameraBox", q=True, exists=True):  
     cmds.deleteUI("CameraBox")  
   window_name = "CamControls"  
   window_title = "Camera Controls"  
   if cmds.window("CamControls", q=True, exists=True):  
     cmds.deleteUI("CamControls")  
   winName = cmds.window(title="clippingControls")  
   cmds.columnLayout()  
   cmds.text(label="Camera Resolution Controls")  
   cmds.separator(height=10, style='none')  
   # to connect an attribute to a slider, you must find the attribute name to connect. This can be found   
   # easily using the Node Editor under Windows --> Node Editor and then with the tab button type in the name  
   # of the node you want to find. Select the radial button with the node and check for the attribute.  
   # Use echo all comands to find the actual name you connected the node to. This works for some but not all.  
   cmds.attrFieldSliderGrp(l='Far Clipping Plane Height', min=1, max=1080, at='resolutionCustom1.height')  
   cmds.attrFieldSliderGrp(l='Far Clipping Plane Width', min=1, max=1920, at='resolutionCustom1.width')  
   cmds.separator(height=10, style='none')  
   cmds.text(label="Near and Far Clipping Plane Controls")  
   # The near and far clipping planes attributes are then added to the Sliders.  
   cmds.attrFieldSliderGrp(l='Near Clipping Plane', min=1, max=50, at='cameraShape1.nearClipPlane')  
   cmds.attrFieldSliderGrp(l='Far Clipping Plane Controls', min=50, max=1200, at='cameraShape1.farClipPlane')  
   cmds.separator(height=10, style='none')  
   cmds.text(label="Create New Camera")  
   cmds.separator(height=5, style='none')  
   cmds.button(label = "Create Camera", command = "gd_CameraBox()")  
   cmds.showWindow(winName)  
 gd_cameraBox()