Jun 24 2017



Jun 24 2017



Jun 24 2017



Jun 8 2017



Mar 8 2015

Vimeo Mango site!

If you haven’t check it out already….

Mango now has it’s on page, with tons of short demos show that mango pipeline tools set…

check it out!

also if you’re on facebook like the mango page!

Sep 30 2014

About “Mango Pipeline”

What is mango?
Mango is a development project to create a “pipeline in a box” like product, to most this will sound like a very bold claim, and let me assure you that it is. To attempt to live up to this claim i have structure the development road map of mango into different phases. Through out the different phases of mango development road map, we will be tackling the different aspects of the big picture Studio pipeline, mango is currently on phase1 and phase 2 should be released early  2015, with more phases already planned.

What to expect from the Mango Phase 1 Deployment
Phase 1 is the entry point to the essentials building blocks that are need to be setup up and expandable pipeline, While at the same time using a common case scenario for small studios that it hopes to improve at the time of adoption.   The generalist pipeline is a common case scenario that can greatly be improved by automating and tracking their most basic needs.

this I identify as…

  1. Ingesting plates
  2. Making work files
  3. Making 3d elements for compositors
  4. Helping Compositors Build and keep comps up to date
  5. Publishing different outputs from comp (for editorial or DI)
  6. Dailies pipeline, reviewing work and having a running history (even when people don’t want , or can’t use shotgun)

To cover those basic goals, there was core infrastructure that had to be covered like, robust directory structure, and a fast locally hosted database driven versioning system, but i won’t bore you with those details. Instead let’s take a look at some of the more visible components of mango phase 1.

Application Agnostic Pipeline
One of my main initiatives is to write mango apps so that they can run in multiple applications with out much effort. This is done by using an API that translate generic command like file open, close, etc to native command the apps hosting the application can understand, By doing this the Pipeline logic, and UI code of the apps can be share across multiple applications.
This allows me the following…

  1. I can easily integrate new applications with mango as they start trending as long as they have python pyside support
  2. I can handle all future software integrations my self
  3. I can continue to update and enhance the applications with out the need to maintain duplicate code.
  4. Reduces testing and bug fixing freeing me up to work on other aspects of the pipeline

This is all done in the hopes that you the client, doesn’t have to worry about Mango or the big picture of Pipeline.
The current list of application that have been integrated are

  • 3dsmax
  • Maya
  • Nuke
  • Hiero.

With all that said let’s take a look at some of the applications you will be inheriting and the role the play in the Mango Phase 1 the “generalist” pipeline.
Software Launcher.

  • Configures all artist software before launching the app for the artist and allowing to begin work
  • Serves as the primary system to distribute tools, and plugins based on simple text based profiles
  • Sets a repository (for tools and plugins) standard for all applications (3ds Max, Nuke, Maya, Hiero) so that a single person can maintain all packages
  • It’s fully integrated with deadline and the render pipeline so that slaves will all ways have he same set of tools that were used when a job was submitted
  • Minimizes the need for IT to manage and push plugin installations by automating the process via deadline and user interaction with the software launcher
  • New plugins and tools can be deployed sooner and with out affecting other shows by separating this new additions into new profiles

Plate ingestion and proxy creation

  • Quickly ingest image sequences to be tracked in the pipeline via stand alone tool
  • Batch create project, sequence, shot and plate ingestion via csv ingestion tool
  • I’m currently working on writing a Hiero exporter so that plates can be ingested directly from Hiero(More on this at the end)
  • Automatically create jpg proxy versions of the ingested files via (ffmpg)
  • Automate Shotgun project creation and and tasks generation for shots

Version Viewer(Stand alone and software integrated)

  • Quickly find any and all resources made in the mango pipeline
  • Quickly jump to the directory where a selected resource version is stored
  • view resource dependencies (what went into making the currently selected version)
  • Flip current version (Currently using Open source flipbook application Jefecheck, but can be expanded to use other flipbook apps)
  • Submit version for review in shotgun (think of this as submit to dailies)
  • Setup or edit any new or exiting projects sequences or shots
  • Access the plate ingestion tools

Work Flow  Tools

Workflow tools are the apps integrated in the artist application that dictate how we do things (Mostly create resources, do hand offs, and receive new and updated work).
here’s a list of the workflow tools we will be deploying with phase 1

Workspace manger (3ds Max,Nuke,Maya,Hiero)

  • Quick tool for setting your work shot context
  • Create New work files
  • Open any previously create work files,
  • Checkout work files created by other artist
  • Find out if someone made a new version of your file in your absence

Publish Work File (3ds Max,Nuke,Maya,Hiero)

  • Just like it sounds published the currently opened work file to be shared with the rest of the studio

Snapshot Work File (3ds Max,Nuke,Maya,Hiero)

  • This, like the Publish Work File, allows the artist to iterate his current file but without publishing the work file. Think of it a private iteration (stays in the user work area)

Render Pass Manger(3ds Max)

  • Proprietary Render Pass manger for 3ds max
  • Fully tested and developed in production
  • Focus on smaller learning curve (vs RPManager), and optimized for larger scenes
  • Fully integrated into the Mango Versioning System
  • Batch Render and Publish your passes as 3delements
  • Automatically sets Exr optimized settings
  • Fully integrated with deadline (render passes can be batched rendered and published on the farm)
  • Automatically handles dependency tracking

Comp Central(Nuke)

  • This is a shot resource catalog application built for compositors
  • Find, review and import any resources available for comp
  • Find out what “Read” nodes are out of date and update them
  • Rollback “Read” nodes to any previous version at any time

Element Publish (Nuke, and Maya)

  • Render and publish your nuke outputs as any of the following resource types (comp, precomp, paint, roto, plate)
  • Render and publish  your Maya Render Passes as 3delements
  • Fully integrated with mango versioning system,
  • Fully integrated with deadline(render passes can be batched rendered and published on the farm)
  • Elements can also be published locally
  • Automatically handles dependency tracking

All of this tools will be available too you from day one and will be deeply covered in the training time we will have together. Please also keep in mind that as subscription customer, i will be extending Mango, and maintain all the tools and workflows above. Which means that you won’t really have to maintain any of this tools and workflows in house, and the workflows will continue to expand  as other areas of the pipeline are tackled.

Support and Mango Tickets
All support for mango goes through the http://mango1.zendesk.com, here you can make an account and submit problems, bugs, request
as well as track the status of any outstanding tickets (you will receive emails as well).

Shotgun Toolkit vs Mango
Mango is meant to replace the need for Shotgun Tool Kit altogether, and while Mango and STK  seem similar in fashion, it is important to know that they operate on different concepts.
When i worked with the Shotgun Tool Kit (at Pixo) I was not pleased with the over all pipeline vision that shotgun had for the tool kit, which was basically none. I can only guess this is why it is a marketed as  “tool kit” and not a “pipeline”.
Being that the bundled apps, “empty shells” with “hooks”, are written in a generic way so that the user can implement their own vision. I saw no real value in them, at least not in the context of my vision which revolves mostly about user experience. The overcomplicated system that comes along with using the toolkit purely as a deployment tool and directory structure generation tool, was so complicated and cover-some, That’s why I decided to create my on kit. A simpler system that allowed me to develop quickly from scratch and that did not impose road blocks by making me funnel my vision through tools that were created with no  practical cases in mind. What you get from Mango is not a tool kit, it is an end to end pipeline and set of standards and practices that will be developed in several separate pre-planed phases. To me the vision of the product is more important the the code it’s self. This is the main reason why i felt Mango could fill a real need in the industry, “Pipeline in a box”.  Mango those optionally interface with shotgun, but limits it to project management (Planning, Bidding, task tracking, work review, notes, etc), and keeps all the resource tracking to it’s self. Ideally Shotgun in mango is just a module, meaning that if at some point something better, and more affordable comes along, we can switch without changing any other aspect of the pipeline, or you can chose to not use it all.

Hiero Integration
Based on the customer feed back that I’ve received, Hiero still has some serious issues that will keep it from fully replacing smoke and flames in the near future as a finishing tool.  On the other hand it seems to be a great tool for creating project structure and kicking out plates and other elements received from clients via EDL, early in the post production stage.
Because of this, the first Hiero Mango integration project I want to tackle is a Mango Exporter for Hiero.
the idea being that if we get assets (movies or imagess sequences) and an EDL from the client, we can quickly create the entire mango project structure and ingest plates (and create secondary resolutions) for the entire project via Hiero.
I would like to spend some time with you guys and see in what other ways you are using Heiro in the production pipeline, to  see how else we can integrate or workflow and maximize the Hiero Mango integration.
but the Mango Exporter for Hiero is something that i hope to start developing this week.

If you guys are interested you can check an outline of the Mango development road map, and the currently scheduled phases.

Mango Development Road Map

  • Phase 1 (Finished)
    • work files
    •  lighting
    • comp
    • dailies
  • Phase 2 (Hope to finish early next year)
    • Modeling
    • Rigging
    • Animation
    • Look Dev
    • Finalizing Stereo (Nuke, Maya)
  • Phase 3
    • Asset Library
    • Show Archival
  • Phase 4
    • Inter studio remote location work sharing
  • Phase 5
    • Editorial
    • Flame, Smoke
    • Hiero
  • Phase 7
    • Color pipeline
    • show,seq, shot LUTs
    • openColorIO (Hardware profiles)
    • lens Distortion Pipeline

Jul 22 2014

Using Vector Math to Rig an Arm…

Quick example on how to use vector math (mostly) to get the most out of locator based rigging. The following example makes a joint chain and a pole vector locator using 3 positions (Shoulder, elbow, and wrist). All the joint orientations and pole vector position are worked out automatically by the use of some simple subtraction addition and cross multiplication of vectors. In the future, I’m hoping to write a more in-depth explanation of my process. But, in the mean while I hope it helps those diving into auto rigging who might not be so fresh on vector math 🙂
The example is done in Maya, since Maya joints can have much different orientations than those visually displayed in the view-port.
Being that this snippet is in python, we must make use of the mayaAPIs vector and matrix classes which is a departure to the way in which we used to do it, in mel.

Here’s the snippet!
hope you find it useful 🙂

from maya import cmds
import maya.api.OpenMaya as om

def makeIkPlaneSetup(helpers, poleVectorDistance=5.0):
    if len(helpers) != 3:
        raise Exception('makeIkPlaneSetup input error, you need objects to pull positions from there were %s inputs\n' % len(helpers))
    shld = om.MVector(cmds.xform(helpers[0],q=True,ws=True,t=True))
    elbow = om.MVector(cmds.xform(helpers[1],q=True,ws=True,t=True))
    wrist = om.MVector(cmds.xform(helpers[2],q=True,ws=True,t=True))
    #figure out the upNode (plane direction)
    planeX = wrist - shld
    planeXL = planeX.length()

    armDis = (elbow - shld).length()
    foreArmDis = (wrist-elbow).length()
    fraction = armDis/(foreArmDis+armDis)
    planeP = shld + (planeX.normalize() * (planeXL*fraction))
    upNode = (elbow-planeP).normalize()
    pvPos = shld + (upNode * poleVectorDistance)
    #shoulder orintation matrix
    shdXAxis = (elbow-shld).normalize()
    shdYAxis = (upNode ^ shdXAxis).normalize() #cross product a noramalize....
    shdZAxis = (shdXAxis ^ shdYAxis).normalize() #cross product a noramalize....
    shldM = om.MMatrix([[shdXAxis.x,shdXAxis.y,shdXAxis.z,0],
    elbowXAxis = (wrist-elbow).normalize()
    elbowYAxis = shdYAxis
    elbowZAxis = (elbowXAxis ^ elbowYAxis).normalize()
    elbowM = om.MMatrix([[elbowXAxis.x,elbowXAxis.y,elbowXAxis.z,0],
    wristM = om.MMatrix([[elbowXAxis.x,elbowXAxis.y,elbowXAxis.z,0],
    pvM = om.MMatrix([[shdXAxis.x,shdXAxis.y,shdXAxis.z,0],
    #convert matrix values to list for xform input 
    shldML = [v for v in shldM]
    elbowML = [v for v in elbowM]
    wristML = [v for v in wristM]
    pvML = [v for v in pvM]
    #make pole vector point
    pv = cmds.spaceLocator()
    cmds.select(clear=True) #we'll keep joints parented to avoid rotation offset which maya creates when parenting joints post creation
    shldJ = cmds.joint()
    elbowJ = cmds.joint()
    wristJ = cmds.joint()


May 16 2014

Resetting Skinwrap Modifiers via maxscript

If you’re reading this right now, you’re probably trying to figure out why the F*&%$@ the built in method for resetting a skin-wrap in max, meshDeformOps.reset(), is doing absolutely nothing for you…
Turns out this method is broken in max.
Here’s a little hack that will allow press the reset button it’s self on any skinwrap via maxscript allowing you to by pass this roadblock.



fn resetSkinWrap md = 
	deselect $*
	select (refs.dependentNodes md)[1]
	max modify mode
	modpanel.setcurrentobject md

	maxHWND = windows.getMaxHWND() 
	for c in  (windows.getChildrenHWND maxHWND) do
		if c[4] == "CustButton" and c[5] == "Reset" then
			UIAccessor.PressButton c[1]
			return  True
for m in (getClassInstances skin_wrap) do resetSkinWrap m

May 2 2014

Parenting Qt gui’s to the main 3dsMax window (BlurPython)

I had a chance to break down the blurdev “Dialog” class today. This class is a modified QDialog class that automatically handles parenting the dialog to the max window. The way in which the Blur Developers achieve this is by compiling a Qt4 module (QtWinMigrate) that does not ship with either PySide or PyQt4 that can convert the windows handle id of the main max window into a QObject that we can use as a parent. the process is very simple, here’s a snippet…

from blurdev.gui.winwidget import WinWidget
parent = WinWidget.newInstance(blurdev.core.hwnd()) 

Here’s an example built directly into a class that inherits a QMainWindow…

import blurdev
from blurdev.gui.winwidget import WinWidget
from PyQt4 import QtGui,QtCore, uic

class test(QtGui.QMainWindow):
	def __init__(self,parent=None):
		if not parent:
			parent = WinWidget.newInstance(blurdev.core.hwnd()) 
		self.setAttribute(QtCore.Qt.WA_DeleteOnClose )
		self.setMouseTracking( True )
		self.checkScreenGeo = True
		self.aboutToClearPathsEnabled = True

gui = test()

last but not least here’s the example from my previous uic post using this code to parent the window to Max.

from PyQt4 import QtGui, QtCore, uic  
base,form = uic.loadUiType(r'c:\uifiles\mainUI.ui')
class mainApp(base,form):
    def __init__(self,parent=None):
    #populate a list box...
    def populateList(self):
        self.scnObjects = mxs.objects
        for o in self.scnObjects:self.listWidget.addItem(o.name)
    #-- connect event handlers
    def connectWidgets(self):
    #--list box events
    def selectObjects(self):
        sel = []
        for i in self.listWidget.selectedItems():
            obj = self.scnObjects[(self.listWidget.indexFromItem(i).row())]
    #-- button event
    def pressButton(self):
        sel = self.listWidget.selectedItems()
        QtGui.QMessageBox.about(self,'QtMessage',"%i objects selected" % len(mxs.selection))

def open():
	from blurdev.gui.winwidget import WinWidget
	app = mainApp(parent=WinWidget.newInstance(blurdev.core.hwnd()))
	return app

test = open()

Give it a go, i hope it works for you. Until next time, happy coding!

Apr 22 2014

Maxscript Simple Dictionary value type via custom struct

Sometimes being able to use a simple dictionary (vs crazy nested arrays) in max script can greatly simplify your code and can allow you to layout your logic in more manageable way.

Unfortunately maxscript doesn’t offer a native dictionary value type, and the .net equivalent “hashtable” is a pain to use in max. If you are not to keen on the use of .net hashtables you might want to try a custom struct like this one…

This dictionary struct uses “sorted keys” and “bsearch” to speed up the look up of keys and their values vs the “findItem” method that can be exponentially slower as as the number of keys grows in size.
take a look…

struct losDic
	table = #(),

	fn binSort a b =
		if a[1] > b[1] then 1
		else if a[1] < b[1] then -1
		else 0
	fn formatDic dic level:0 spaces:4 =
		strm = "\n" as stringStream
		padding = ""
		if level != 0 then
			for a=1 to level do for b=1 to spaces do padding += " "
		for k in (dic.keys()) do
			val = dic.getK k
			case (classof val) of
				(losDic):format "%%:\n%" padding k (formatDic val level:(level+1) spaces:spaces) to:strm
				default:format "%%:%\n" padding k val to:strm
		(strm as string)
	fn count = keys.count,
	fn getK k = 
		val = bsearch #(k) table binSort
		if val == undefined then return val

	fn setK k v =
		val = bsearch #(k) table binSort
		if val == undefined then
			append table #(k,v)
			qsort table binSort
			return this
		val[2] = v
	fn hasK k =
		t = case (bsearch #(k) table binSort) of
	fn delK k =
		indx --findItem keysL (k as name)
		for i=1 to table.count where table[i][1] == k do
			indx = i
		if indx == 0 then throw ("there is no key "+k+" in dictionary")
		deleteItem table indx
	fn keys =
		out = for k in table collect k[1]
	fn pprint =
		print (formatDic this)

Here’s an example of how it’s basic usage…

--make the dictionary
dic = losDic()
--set keys
dic.setK "pappa" 9999
--embeded dictonaries
dic.setK "powers" (losDic())
dic.setK "object" (sphere())
--set key in  the embeded dictionary
(dic.getK "powers").setK "lazerEyes" true
(dic.getK "powers").setK "bulletProof" true
--query the available keys
print "------keys------"
print (dic.keys())
print "----------------"

--loop throug a dictionary
print "print keys and values"
for k in dic.keys() do format "%:%\n" k (dic.getK k)

print "preaty print"
--prety print the dictionary

till next time!!