Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Thursday, 13 August 2026

Joint physics article

What a beautifully concise and articulated article on the logic/maths behind a physics joint chain. Will be very useful for learning about this and re-creating this in your own tools:

 https://shirzadbahrami.com/physics-based-animation-undulation/

Friday, 21 November 2025

Debugging with sys.stdout

Add this to a file to generate a useful debug.log file! 

Useful if you're unable to access a console for printing but still need to know why a file is failing to execute!

sys.stdout = sys.stderr = open(r"C:\Users\Alex.Tavener\Documents\debug.log", "w")

 

Thursday, 6 November 2025

Perforce Diff in Vscode!

 Hate Perforce's default Diff window, with lack of syntax highlighting and interactive merge clicking...?




Yeah well me too, and you'll be glad to know you can set your preferred IDE as the diff tool for Perforce!

Perforce>Edit>Preferences>Diff:
'Other application' > Set to your IDE .exe
Arguments: -d %1 %2

And now look:
Beyoootiful.



Wednesday, 3 September 2025

VsCode - auto path completion/autocompletion

The Problem: 

For a while it haunted me that my custom repos/packages weren't auto-completing, not ctrl+mouse hover to see what a function did.

 The Fix:

F1 > Preferences: Open Workspace Settings (JSON)

 

Ensure you have "settings", if not, add it.

Ensure you have "python.analysis.extraPaths" : ["your paths here"], if not, add it. 

    "settings": {
        "git.ignoreLimitWarning": true,
        "python.analysis.extraPaths": [
            "C:\\Users\\a_tav\\3D work and portfolio\\AT_autorig",
            "C:\\Users\\a_tav\\3D work and portfolio\\scripts",
            "C:\\Users\\a_tav\\3D work and portfolio"
        ],
        "python.analysis.autoImportCompletions": true,
        "python.analysis.completeFunctionParens": true,
        "python.analysis.useLibraryCodeForTypes": true,
        "editor.definitionLinkOpensInPeek": true,
        "files.associations": {
            "random": "cpp"
        },

 

Wednesday, 18 December 2024

Morgan Loomis - Anim & Rig Tools

 I came across a pretty cool new zealander who is hosting a lot of his tools on his own personal website. Thought it was worth a link :) 

http://morganloomis.com/tools/

Monday, 22 April 2024

Python3 comparison operators

Meditate on this 🙏

'foo' is 'foo'
True

'foo' == 'foo'
True

'foo' is 'foo2'[:-1]
False

'foo' == 'foo2'[:-1]
True

'foo' is 'Foo'.lower()
False

'foo' == 'Foo'.lower()
True

0 == 0.0
True

0 is 0.0
False

0 is False
False

0 == False
True

not 0
True

Thanks to Joe Hornsby for providing these excellent examples.

Thursday, 28 March 2024

Can't undo in Maya

The Issue:

// Error: line 1: The undo queue is turned off.

:(


The Fix:

In script editor, on a python tab, run:

cmds.undoInfo(state=True)

:)

Friday, 27 October 2023

Python debug tip

 Want to know a secret?

"*"*100 takes me about 1 second to type.

Why not wrap it in a print?

 

print("*"*100)

print("var_a:", var_a) 

print("var_b:", var_b) 

print("var_c:", var_c)  

Result:

//****************************************************************************************************

// var_a: pineapple

// var_b: 64

// var_c: <__main__.Dog object at 0x00000248A53D7748> # 

//************************************************************************************************

 

Isn't that easier to read?

Monday, 23 October 2023

How to install numpy for Maya

I needed to install numpy for Maya the other day because its a dependancy of a package that I use.
But how? How do you install numpy for Maya?

Like this:
1.) Press windows, type in cmd and press enter
2.) type in: cd C:\Program Files\Autodesk\Maya20??\bin
3.) type in: mayapy -m pip install numpy

Obviously, replace the ?? in your Maya install directory with your version number.
And there you go - numpy installed! :)

Thursday, 23 March 2023

Python Generators - using yields and generators

Python generators were something that alluded me for quite a while. A spooky concept that didn't seem necessary. However after using Coroutines in C#, it sort of became a little more clear. 

Then, recently I stumbled across an excellent blog post explaining what generators do, how and when to use them:

https://github.com/qingkaikong/blog-1/blob/f453d320c06ac5b1a8d43380f9e6f9d9cf8c3022/content/2013-04-07-improve-your-python-yield-and-generators-explained.md

Check it out!

Thursday, 28 July 2022

Record time taken for any python function

Here's a useful function for debugging a tools performance.

It's handy to know how long each section of your code is taking without having to sprinkle lots of time.time() functions around. Therefore, wouldn't it be nice to add a decorator to any function that you would like to print the execution time of?

import time
import functools

def record_time(f):
    """Print execution time of wrapped function."""
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        start = time.time()
        try:
            return f(*args, **kwargs)

        finally:
            print(f.__name__, "time taken:", time.time()-start)

    return wrapper

Now you can just add @record_time to line directly above any function definition, and when the function is called, the time will be printed like so;

@record_time
def jelly():
	for i in range(0,10000):
		print i

jelly()
# ('jelly', 'time taken:', 2.1070001125335693)

Happy debugging!

Monday, 25 April 2022

Persistent Transform Nodes

Here's an age-old bug:

The Problem:

"My joint recieves a transform in the skeleton hierarchy, and I can't remove it!"

The Fix:

cmds.parent(problem_jnt, new_parent, relative=True)


Wednesday, 30 March 2022

Debug function call

I came across a useful python debugging library the other day that allows you to print where a function is being called from: 

from inspect import stack

def foo():
    print(stack()[1][1:4])

def bar():
    foo()
What this will do now is whenever foo() is called, it will also now spit out a message:
('name_of_file.py', line_number, function_calling_foo)
 
Or, as I call it in Maya's Script Editor:
('<maya console>', 6, 'bar') 

Brilliant for tracing nested funcs in a complex architecture!

Tuesday, 18 January 2022

Get current frame from Maya node - time

 Today I forgot how to get the current frame from a node, something which I wanted to access in order to create a 'turbine' auto-rig component. I tried going into the node editor and created a new 'time' node, but the 'outTime' attribute didn't seem to update with the timeline when I scrubbed through it.

However, it seems that every Maya scene has a persistant 'time' node called time1.

This is the correct node to query when wanting to access the current frame from a node, and as it is persistant in every Maya scene, it's fine to hardcode this name.








Tuesday, 21 December 2021

Maya won't save as .mb

I had an issue today where I couldn't save my Maya file as a .mb, and faced the following error:

The Problem:

 "File contains unknown nodes or data. To preserve this information, the current file type cannot be changed. //"

This can be caused by having unknown nodes in the scene, usually from an external plugin that you no longer have.

The Fix:

unknown_nodes = cmds.ls(type="unknown")
# Before you delete, check you want to delete these unknown nodes!
cmds.delete(unknown_nodes)
After running this code, you should be able to save as .mb again!

Tuesday, 20 October 2020

Disable viewport while running code

 Hello hello,

I just found a really cool bit of code to temporarily disable the Maya viewport whilst running code. Very useful for potentially 'heavy' stuff like caching, baking etc:


cmds.refresh(suspend=True)
doYourFunc()
cmds.refresh(suspend=False)

Tuesday, 22 September 2020

Maya Custom Hotkeys

 I feel it's about time to share my custom Maya hotkeys because I've been using them everyday for the past 4+ years in every job I've been in, and they were gifted to me by a friend who gave them to me on my first day, on my first job.

They'll save you hours days of your life! Days i tell you.

# Show geo only (alt+1)
import maya.cmds as mc
currentPanel = mc.getPanel(withFocus = True)
getStatus = mc.modelEditor(currentPanel, q=True, cameras=True)
if getStatus == True:
    mc.modelEditor(currentPanel, e=True, allObjects=False)
    mc.modelEditor(currentPanel, e=True, polymeshes=True)
else:
    mc.modelEditor(currentPanel, e=True, allObjects=True)
# Show joints only (alt+2)
import maya.cmds as mc
currentPanel = mc.getPanel(withFocus = True)
getStatus = mc.modelEditor(currentPanel, q=True, cameras=True)
if getStatus == True:
    mc.modelEditor(currentPanel, e=True, allObjects=False)
    mc.modelEditor(currentPanel, e=True, joints=True)
    mc.modelEditor(currentPanel, e=True, handles=True)
else:
    mc.modelEditor(currentPanel, e=True, allObjects=True)
#Show joints and geo only (alt+3)
import maya.cmds as mc
currentPanel = mc.getPanel(withFocus = True)
getStatus = mc.modelEditor(currentPanel, q=True, cameras=True)
if getStatus == True:
    mc.modelEditor(currentPanel, e=True, allObjects=False)
    mc.modelEditor(currentPanel, e=True, joints=True)
    mc.modelEditor(currentPanel, e=True, polymeshes=True)
else:
    mc.modelEditor(currentPanel, e=True, allObjects=True)
#Show curves and geo only (alt+4)
import maya.cmds as mc
currentPanel = mc.getPanel(withFocus = True)
getStatus = mc.modelEditor(currentPanel, q=True, cameras=True)
if getStatus == True:
    mc.modelEditor(currentPanel, e=True, allObjects=False)
    mc.modelEditor(currentPanel, e=True, nurbsCurves=True)
    mc.modelEditor(currentPanel, e=True, polymeshes=True)
    mc.modelEditor(currentPanel, e=True, cv=True)
    mc.modelEditor(currentPanel, e=True, nurbsSurfaces=True)
else:
    mc.modelEditor(currentPanel, e=True, allObjects=True)
# Show curves only (alt+5)
import maya.cmds as mc
currentPanel = mc.getPanel(withFocus = True)
getStatus = mc.modelEditor(currentPanel, q=True, cameras=True)
if getStatus == True:
    mc.modelEditor(currentPanel, e=True, allObjects=False)
    mc.modelEditor(currentPanel, e=True, nurbsCurves=True)
    mc.modelEditor(currentPanel, e=True, cv=True)
    mc.modelEditor(currentPanel, e=True, nurbsSurfaces=True)
    mc.modelEditor(currentPanel, e=True, locators=True)
else:
    mc.modelEditor(currentPanel, e=True, allObjects=True)

Friday, 6 March 2020

Interactive interpolation visualisation tool

Here's a nice tool for visualising bezier curves, and how they're made.
This was really helpful when coding up my own lerp (linear interpolation) python library and writing a recursive bezier function.
http://acegikmo.com/bezier/

Here's the main lerp algorithm in a python function to start you off:

def lerp(input1, input2, step):
    """ Linearly interpolation between input1 and input2 given
    a value between 0.0 and 1.0.
    Args:
        input1 (int): starting integer to lerp from.
        input2 (int): destination integer to lerp towards.
        step (float): float value between 0.0 and 1.0
    """
    return (1 - step) * input1 + step * input2



Tuesday, 10 September 2019

Convert MEL to Python

Still converting MEL to python the oldschool way by deleting semi-colon here, adding a bracket there?

Pffffttt just use this!



import pymel.tools.mel2py as mel2py

print mel2py.mel2pyStr("""spaceLocator -p 0 0 0;""")


Output:


spaceLocator(p=(0, 0, 0))



Remember to add a cmds. to the start, because for some reason it doesn't add it on for you!

Now you can just replace 'spaceLocator -p 0 0 0;'  with any other MEL code that the script editor may spit out whilst you're Maya'ing and BAM insta-python!

Sure, it doesn't work for all cases but for other cases where you just want to copy & paste a handy addAttr line and can't be bothered to google it, it can come in handy and help speed things along.

Monday, 20 May 2019

Maya's new combinationShape node

Check out this great post explaining how to use Maya's new combinationShape node. This node is useful for an array of things, including driving blendShape targets in a facial rig & creating a min/max function.

https://rigmarolestudio.com/min-and-max-nodes-in-maya/amp/?__twitter_impression=true