verletCloth01

I made a new Python\Pygame app based on verlet intgrated ‘cloth’ sim.  See more info,  get executable,  source, on it’s PAGE.

Graphics using Python’s standard library (Tkinter)

I really dig Python. It just (seemingly) has no built-in graphics capabilities, which makes me sad. Or DOES it? It ships with the Tkinter module, right? Which can display built-in graphics via its canvas widget.  Based on that, presumably you can start to do some simple interactive graphical applications a-la Pygame \ Processing.  Right?

Well, I thought I’d give it a shot.  Considering I’ve not ever used Tkinter, this was my first real foray into that arena.  But you can display graphics and bind callbacks to events, so it has the foundation for doing what I want.

My first attempt is listed below.  Some things I learned:

  • How to query the mouse position in the Tkinter window.
  • How to create a rectangle, that will follow the mouse around.
  • How to… make a Tkinter window with callbacks that make all the magic happen.

Not very impressive on it’s own:  All you get is a small window with a blue rectangle that follows the mouse.  But baby steps here.  I’m interested to see how far this can go.

from Tkinter import *

class Rect(object):
    def __init__(self, canvas, width, height):
        self.canvas = canvas
        self.width = width
        self.height = height
        self.x = 0
        self.y = 0
        coord = self.getCoordinates()
        self.rect = self.canvas.create_rectangle(coord[0], coord[1],
                                                 coord[2], coord[2],
                                                 fill="blue")

    def getCoordinates(self):
        # Used to define the sides of the rect based on a starting x,y position.
        left = -self.width/2 + self.x
        top = -self.height/2 + self.y
        right = self.width/2 + self.x
        bottom = self.height/2 + self.y
        return left, top, bottom, right

    def move(self, x, y):
        # Move the Rect object to a new location.  What is called to by the
        # UI callback moveRect()
        deltaX = x - self.x
        deltaY = y - self.y
        self.canvas.move(self.rect, deltaX, deltaY)
        self.x = x
        self.y = y

class App(object):

    def __init__(self, width=256, height=256):
        self.width = width
        self.height = height

        self.root = Tk()
        self.root.title("tkinter_test01")
        self.root.geometry("%sx%s"%(self.width, self.height))

        self.canvas = Canvas(self.root, width=self.width, height=self.height)
        # Bind the event to move our Rect:
        self.canvas.bind("<Motion>", self.moveRect)
        self.canvas.pack()

        # Create our Rect object:
        self.rect = Rect(self.canvas, 32, 32)

        self.root.mainloop()

    def moveRect(self, event):
        # Callback that will move our Rect object
        self.rect.move(event.x, event.y)

if __name__ == "__main__":
    App()

New PyGame app: simpleParticle01

Been a while, but I finally got around to doing another simple PyGame app, which I’ve called ‘simpleParticle01’ (descriptive, yes…).

Find executable download, Python source, and description over on its page.

Find executable download, Python source, and description over on its page.

Uninstance all instances in a Maya scene

From over on my mel wiki:

Maya makes it easy to create an instance of a node, but I’ve found no built-in way to query what nodes in the scene are instanced.  Poking around a bit in the API however, it only takes a few lines of code:

# Python code
import maya.cmds as mc
import maya.OpenMaya as om

def getInstances():
    instances = []
    iterDag = om.MItDag(om.MItDag.kBreadthFirst)
    while not iterDag.isDone():
        instanced = om.MItDag.isInstanced(iterDag)
        if instanced:
            instances.append(iterDag.fullPathName())
        iterDag.next()
    return instances

This function will return a list of all the instances in the scene, nice! I have yet to find any other function that can do this via mel.

But how would you actually uninstance them? I worked on this problem quite a bit: If you simply have a bunch of leaf nodes that are instanced, it’s not hard to do. But if you have a say ten spheres all instanced, then you make two groups of five, then instance those groups, and parent all the groups, then instance that parent… very quickly things get hairy:  You try and uninstance a leaf by duplicating it, and now the duplicate appears in every other parental instance!
Like I just mentioned, most solutions I’ve found explain you can just ‘duplicate the instance’ to solve this problem, and this works on an individual instance that has no parent node that is an instance.  But when you have the situation I list above, the solution I found is this:  You can actually duplicate the instances parent, then delete the original parent, which will (via a loop) cleanly uninstance everything in the scene.  And since the getInstances() function returns a list parent-first, this works out great:

def uninstance():
    instances = getInstances()
    while len(instances):
        parent = mc.listRelatives(instances[0], parent=True, fullPath=True)[0]
        mc.duplicate(parent, renameChildren=True)
        mc.delete(parent)
        instances = getInstances()

lambda and map in Maya

Starting using a couple shorthand techniques today via map and lambda to save on screen real estate when authoring Python modules in Maya.  I often times will troll the scene for info and want to print stuff:

Here, I find the transform name for all mesh in the scene, then print them all with tabs in front:

import sys
import maya.cmds as mc
# Get transform for each mesh:
shapes = mc.ls(type='mesh')
transforms = map(lambda x: mc.listRelatives(x, parent=True)[0], shapes)
# print with tab in front:
map(lambda x: sys.stdout.write('\t%s\n'%x), transforms)

By using our map / lambda combo, I’m able to side-step the need to write any loops. Here’s how it would look otherwise:

import maya.cmds as mc
# Get transform for each mesh:
shapes = mc.ls(type='mesh')
transforms = []
for s in shapes:
    transforms.append(mc.listRelatives(s, parent=True)[0])
# print with tab in front:
for tran in transforms:
    print '\t', tran

Not counting imports and comments, I halved the number of lines of code. One could argue the bottom example is possibly more readable however.