verletCloth01
I made a new Python\Pygame app based on verlet intgrated ‘cloth’ sim. See more info, get executable, source, on it’s PAGE.
I made a new Python\Pygame app based on verlet intgrated ‘cloth’ sim. See more info, get executable, source, on it’s PAGE.
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:
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()
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()
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.