Live Reloading Qt Stylesheets

posted in: Uncategorized | 0

The more time I spend in PySide, the more I demand of it. Lately, I’ve put a lot of emphasis on the look and feel of my applications and have ventured deep into custom widget styles. Stylesheets do an awesome job at separating concerns of the functionality from the visuals. To date, they are my favorite system to change the appearance of QWidgets.

During a design phase, I found myself iterating rapidly on stylesheets to tweak the pixels between margins or dial in colors, all while having to relaunch my Python process between changes. This feedback loop is not immediate enough and gets tiresome pretty quickly. Today I’m sharing my recipe for live reloading stylesheets in the PySide framework! (This code should be easily reusable across PyQt as well.) The core is quite simple. Hold onto references of stylesheets when they’re applied to widgets and add QFileSystemWatchers to watch when they change. On modification, reload the stylesheet from disk and reapply the sheet to the widgets.

Here’s a quck demo. On the right side, I’m modifying the .css stylesheet. On the left side, the app window updates every time I save the file.

The StylesheetWatcher Class

from PySide import QtCore
import collections

class StylesheetWatcher(object):
    """
    A utility class for live-reloading Qt stylesheets.

    When watched, all changes made to a .css file automatically
    propagate to any running apps with live stylesheets.
    """

    def __init__(self):
        self._widget_sheet_map = collections.defaultdict(list)  # One-to-many map of stylesheets to their widgets
        self._watcher = None

    def watch(self, widget, stylesheet_path):
        """
        Establishes a live link between a widget and a stylesheet.
        When modified, the stylesheet will be reapplied to the widget.

        Args:
            widget: (QtGui.QWidget) A widget to apply style to.
            stylesheet_path: (str) Absolute file path on disk to a .css stylesheet.

        Returns: (None)
        """
        self._widget_sheet_map[stylesheet_path].append(widget)

        self._watcher = QtCore.QFileSystemWatcher()
        self._watcher.addPath(stylesheet_path)

        self._watcher.fileChanged.connect(self.update)

        self.update()

    def update(self):
        """
        Callback to reload and reapply a stylesheet when changed by the file system watcher.

        Returns: (None)
        """
        for stylesheet_path, widgets in self._widget_sheet_map.iteritems():
            with open(stylesheet_path, "r") as fid:
                raw_stylesheet = fid.read()

            for widget in widgets:
                widget.setStyleSheet(raw_stylesheet)

I’ll upload a complete demo app in the coming days with my “Steam” clone stylesheet. Happy designing!

PySide Decorators for Unity-like Context Menus

posted in: Uncategorized | 0

Today I wanted to share a recipe I’ve cooked up for creating menus in PySide. Having worked within the QWidgets framework of Qt for a while, I’ve always found the process of creating context menus and menu bars needlessly complex and error-prone. During my struggles trying to get hotkeys to work correctly and nested menus to build in the right order, I found myself reminiscing about Unity — in particular, its many intelligent API design choices made to aid with editor extensions. Fed up with the time I was spending on each new tool to get menu systems working correctly, I decided to develop a reusable library that would make me feel right at home.

The core problems I struggle with in PySide’s menu system are:

  • Creating hotkeys that actually fire QActions regardless of the state of the QMenu or QMenuItem
  • Building and managing nested QMenus
  • Flexibly specifying QMenuItem order in a QMenu
  • Creating callbacks for each QAction’s triggered signal

In PySide, I wanted to be able to do something like this Unity C# snippet:


// Add a new menu item with hotkey CTRL-A
[MenuItem("Tools/Create Actor %a")]
private static void CreateActor()
{
    // Do stuff...
}

And I ended up with this in:


# Adds a new menu item with hotkey CTRL-A
@AppContextMenu.register_action("Tools/Create Actor", shortcut="Ctrl+A")
def create_actor():
    # Do Stuff...
    pass

# App-specific code
class DemoMenuApp(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(DemoMenuApp, self).__init__(parent=parent)
        # Connect the context menu to tree_view_widget's right click
        AppContextMenu.add_widget(self.tree_view_widget)

Not bad, eh? For reference, in PySide the context menu appears like:

context_menus_01

A more complex example of a context menu created with this system.

What It Does

The register_action decorator handles building all QMenus and sub menus by parsing out /’s in your action name. It correctly hooks up QActions to fire when keyboard shortcuts are fired. It allows you to specify manual order with automatically placed separators by specifying a priority value. And lastly, it allows certain items to be enabled or disabled based by providing a validator callable.

The full source with the implementation of the BaseContextMenuTree class can be found on my GitHub. I’ve also included a mini PySide app to show different uses and demo its full feature set.
https://github.com/Mouthlessbobcat/Python-Projects/blob/master/milk/lib/qt/contextmenu.py

Afterthoughts

Implementing Unity’s API for creating menus was a neat exploration. In the process, I’ve come to terms with some of its design limitations. In both Unity’s and my implementation, it is not possible to pass arbitrary arguments into the decorated functions. Unity provides the user with some flexibility to unbox a generic “context object” into a specific type based on the context of the menu item. My system could be extended to do similar, but this relies on specific conventions and predetermined contexts. The system works best when functions are defined to operate on “static” objects and methods or where all the arguments required in the menu item’s action can be acquired from external systems.

Because Python evaluates its decorators as soon as the module is imported, all instances of my BaseContextMenuTree class must be declared in code as well. It is not possible to create new menu trees during runtime. However, it is possible to disable and enable certain menu items based on the “validator” parameter in the decorator. The validator is any callable that returns a boolean value. The callable is called each time the context menu is about to present itself. This allows for dynamic control of individual menu items. Validators offer more than enough freedom, so the limitation of not being able to create new menu trees becomes much easier to cope with.

For further reading, Unity’s documentation on its Menu Items system can be found here:

https://unity3d.com/learn/tutorials/modules/intermediate/editor/menu-items

Baby’s First Substance

posted in: Uncategorized | 0

Forward

Let’s get back to the blogging thing. I’ve recently picked up Substance Designer + Painter and the motivation to start making some arts. It’s been ages since I’ve posted here and even longer since I’ve modeled anything. Work has me wholly focused on code, so to keep my head balanced I’m starting up some small projects on the side to practice (read: learn) PBR and get back into Unity. But you say you’re only interesting in codes? Don’t worry. We’ll keep exploring cool patterns and strategies in Python and C# for application in art tools!


The Grenade Tutorial

I recently completed a fantastic tutorial by Tim Bergholz on Gum Road. The two-part series is free and goes through the entire process of modeling a realistic grenade in 3ds Max, followed by baking and texturing in Substance Painter. Having been my first project in Painter, I can say I’ll fallen in love. The baking workflow is thoughtfully designed, comprehensive, and fast! There are some superbly clever and intuitive design decisions made for layering materials together, like the ability to bias a layer’s height map up or down. This helps you nail those subtle depth changes across materials!

Here’s my results in Unity 2048×2048 textures…

grenade_render_beauty_01


Texture Maps

grenade_tex_maps
 

Bonus Points

I took the tutorial one step further and brought the asset into Unity for a real-time turnaround render. There were some tweaks needed to the normal map bake to account for Unity’s tangent space. I also needed to pack my roughness map into the alpha channel of my roughness map map and invert this roughness map into a metallic map. (I should totally make a Substance Designer material to automate this and provide clean exports for Unity.)
 
grenade_turnaround

The most amazing thing? Nope. Inspired design? Nah. But that comes next!

Transaction-Based Pipeline Programming – [C#]

posted in: Uncategorized | 0

Overview

Today we’ll be exploring the transaction programming pattern, and its relevance to developing an asset pipeline. A transaction can be thought of as a specific subset of the command design pattern, but with specific characteristics. In this post, I’ll be defining transactions in terms of three specific components: an executable action, a means to handle failure or error, and a post-action or “clean-up” step.


Case Example

Over time, I’ve encountered the need for this type of behavior all over the place. In particular, during the vast majority of asset export and import processes, I’ve made use of this pattern to prevent disasters. Before we dive deeper into the technical implementation of our transaction code, let’s think in terms of a practical example. Start out by imagining how a typical implementation of an export process might behave:

    Acquire all data to export
    Determine asset dependencies
    Process the asset  # (i.e. clean-up, meta-data, etc.)
    if (the export path doesn't exist):
       Create the output directory
    else:
        Delete the previous asset
    Copy/save the asset to the output path



This works all fine and well until, for whatever reason, some part of the export process fails. In a worst possible case, this might happen: you’re handling an object whose scene name contains a character not valid in Windows file paths. You are smart and determine the export path based on the object’s name but forget to perform path validation logic before trying to copy it and your program throws an exception. At this point, you’ve already deleted the previous working asset and haven’t even replaced it with the newly exported version.. what a mess!

In another case, the exporter might fail during a processing or conditioning step. Now you’ve left the artist’s scene in some unstable state. You’d better make sure the artist is immediately made aware that the exporter failed and hope they don’t save the half-exported asset before closing it. Have fun explaining how to fix the asset for export when the original file has been saved over.


Refactor Attempt #1

As you can see, this type of asset export processing is very dangerous the instant something occurs unexpectedly. Thankfully, there are some defensive programming techniques in our toolbox to help handle the worst of surprises. Exception handling seems like just the right fit for solving these issues! We can wrap up our export logic into a try clause and catch any exceptions that get thrown! Let’s look at how this new and improved exporter might function:

    try:
        Acquire all data to export
        Determine asset dependencies
        Process the asset (i.e. clean-up, meta-data, etc.)  
        if (The export path doesn't exist):
           Create the output directory
        else:
            Delete the previous asset
        Copy/save the asset to the output path     
    catch Errors:
        # Uh oh something went wrong!
        Close the current operating file without saving
        Display a pop-up window to the user with some error log

We’ve now safeguarded against any unexpected failures in the export process. Furthermore, we can cleanly abort the process and even display an informative log to the user! What’s cooler yet, is how we to take this a step further.

A Tangent on Sandboxing

Even though we’re failing beautifully, we’re still leaving the artist frustrated with a closed scene and likely some highly technical gibberish about what went wrong. To clean things up more, we’ll employ a sandboxing technique. Rather than operating directly on asset in question, we’ll insert an additional step at the beginning of our export process that saves a copy of the asset off to a temporary disk location so that no matter how bad things get, we won’t be touching the artist’s original work. At the end of our export process, we can even clean up this sandbox file to prevent hard drive clutter. We can ensure this clean-up step happens no matter what by tacking on a finally clause to our process. The code within this block will execute regardless of whether or not the export completes successfully!

    try:
        Create sandbox copy of original file
        Do all of the exciting export things...
    catch Errors:
        # Uh oh something went wrong!
        Close the current operating file without saving
        Display a pop-up window to the user with some error log
    finally:
        Delete sandbox copy

We’ve come a way now from our original implementation of the exporter and I bet you’ve been waiting out for some real code this whole time.


The Transaction Class

Remembering to implement all this try, catch, finally bulk around your code can clutter things up and makes re-organizing your actual logic dependent on fitting into these blocks. To abstract this process and genericize it into an easy-to-implement interface, I created the Transaction class designed with the intent that one could refactor old code into the transaction pattern and change logic out on the fly without worrying about the syntax blocks. Here’s the implementation in C#:

using System;

class Transaction : ITransaction
{
    readonly private Action doThis;
    readonly private Action handling;
    readonly private Action cleanUp;

    public Transaction(Action inDoThis, Action inHandling, Action inCleanup)
    {
        if (inDoThis == null)
        {
            throw new System.Exception("Can not assign a null function to the primary action of a transaction.");
        }

        this.doThis = inDoThis;
        this.handling = inHandling ?? this.nullMethod;
        this.cleanUp = inCleanup ?? this.nullMethod;
    }

    private void nullMethod() {}

    public void Execute()
    {
        try
        {
            doThis();
        }
        catch (System.Exception e)
        {
            handling();
        }
        finally
        {
            cleanUp();
        }
    }
}

The Transaction object requires three methods that don’t have return values. You’ll notice I do some additional null guard checking and override null values passed in for the second and third parameters with an empty function. Without these C# will throw a null reference when you try to call a null Action! For the first Action, I throw an exception if the user tries to pass in null since it doesn’t make much sense for a transaction to exist without a core action to execute.

I made the decisions to use C#’s System.Action delegate arguments for this implementation and an Execute method that returns void to constrain how the class is used. Rather than expecting some returned value from the transaction object, the user should typically be passing in methods that operate on existing objects and their internal data members. This contract is set in place by this brief ITransaction interface:

interface ITransaction
{
    void Execute();
}



With our Transaction class in hand, we’re ready to write some awesome pipeline tools! Let’s take a look at how we might use it in action. First we define our asset exporter class. I’ve nealty defined three class methods that wrap all the fancy busywork of exporting the asset. We can directly plug these into our Transaction class.

    class AssetExporter
    {
        public void DoExport()
        {
            // Create a working copy of the asset, clean it up, etc...
        }

        public void OnExportFailed()
        {
            // Display a pop-up window to the user...
        }

        public void CleanUp()
        {
            // Delete temporary assets and return to the existing state...
        }
    }

To execute the exporter, we build the Transaction with AssetExporter’s methods and call its main Execute method!

class Program
{
    public void Program()
    {
        AssetExporter exporter = new AssetExporter();
        Transaction exportTransaction = new Transaction(exporter.DoExport, exporter.OnExportFailed, exporter.CleanUp);
        exportTransaction.Execute();
    }
}

The logic to implement transaction-style processing is contained to two lines of code, making it simple to inject this pattern into existing work and to experiment in new code.


Outcome

The Transaction pattern provides a contract with which to operate and recover when things to unexpectedly. The use of language exception handling utilities simplify our work and can easily be contained in a Transaction Object that allows us to add and remove transaction-based logic wherever it is needed. This type of code flow is especially useful in asset processing or file authoring of any sorts.


Next time, we’ll be using this transaction style of programming to build a slick object-oriented Unity import pipeline to precisely manipulate import behavior!

Encapsulated Lazy Singleton Pattern – [C#]

posted in: Uncategorized | 1

Background

Singletons are a frequent topic of discussion among hobbyist game developers. The design pattern exists to solve the problem of limiting the creation of an object to only one instance while exposing a global handle to its reference for easy access. A quick web search yields a variety of ways to design a Singleton, but I though I’d introduce my favorite means of implementing the design pattern. Singletons are heavily used by game programmers due to the nature of many ‘global systems’ that all need to interact with one another and be easily accessible from other objects. This is especially true in rushed or small-scope projects when rapid development is prioritized over scalable architecture. I believe this pattern, which I’ve dubbed the ‘Encapsulated Lazy Singleton’, tackles the Singleton problem in an elegant way, offering encapsulation around the Singleton’d class instance and lazy instantiation – you won’t lose it (memory) if you don’t use it.

I will be demonstrating this example using a slightly contrived camera system built in Unity, but the pattern is completely re-usable outside of the game engine.


Case Example

Let’s say I am writing a camera system for the player and I realize that the player’s camera would be a good case for a singleton. There will probably only ever be one instance of the player camera and it sure would be nice to be able to access it whenever I wanted to. It seems like a good fit!

I’ve already written the logic for a general purpose camera that can be positioned in world space and continually updates its position each frame. I’ve named the class, Dynamic Camera.

using UnityEngine;

class DynamicCamera : MonoBehaviour
{
    private void Start()
    {
        // Set up camera here...
    }

    private void Update()
    {
        // Continually update camera...
    }

    public void FadeIn(float duration)
    {
        // Do fade in...
    }

    public void LookAt(Transform transform)
    {
        // Look at the transform...
    }

    // ...
}


Refactor Attempt #1

The class is a Monobehaviour so it lives on an object and is initialized on the Game Object’s start method. Your intuition might be to just throw a static instance reference to itself in its initialization like so.

class DynamicCamera : MonoBehaviour
{
    public static DynamicCamera Instance;

    public void Start()
    {
        Instance = this; // Singleton!
        // Set up camera here...
    }
// ...

Now I could easily access this particular instance of the DynamicCamera like DynamicCamera.Instance.LookAt(). We’ve achieved the Singleton pattern in a sufficiently simple but fragile way. Unfortunately, we have a few problems. It doesn’t ensure you’ll always maintain the same reference to the camera. Some other game object could easily come along and create another object with a DynamicCamera behavior and the Instance reference would change. It also has no safe measure to ensure the Instance is even initialized in the first place. You’ll end up with a null reference trying to access its methods before it’s initialized. Plus, the ‘.Instance’ notation is just plain ugly to look at and doesn’t clearly communicate to the user what is going on.

Let’s take a stab at refactoring the camera another way.


Refactor Attempt #2

I’ve created a new class called MainCamera. It is static and holds a private reference to the DynamicCamera class we want to turn into a singleton.

using UnityEngine;

public static class MainCamera
{
    private static readonly DynamicCamera instance = null;

    static MainCamera()
    {
        instance = new GameObject("Main Camera").AddComponent();
        instance.Initialize();
    }

    public static void Initialize(Transform playerTransform)
    {
        instance.transform.parent = playerTransform;
    }

    public static void FadeInCamera(float duration)
    {
        // Fade out the camera here...
        instance.FadeIn(duration);
    }
}

The MainCamera class includes static methods for operating on its singleton reference. Also notice that it uses a static constructor. We can take advantage of this because it guarantees initialization the first time the class is accessed.

I’ve also re-written the initialization step of the DynamicCamera class as follows.

using UnityEngine;

class DynamicCamera : MonoBehaviour
{
    // Note the lack of 'Start()' method
    public void Initialize()
    {
        // Set up camera here...
    }
// ...

To interact with the player camera, our code looks like MainCamera.LookAt(). We’ve removed the unnecessary .Instance characteristic of the earlier implementation and hidden it within the static class. This refactor also offers complete encapsulation over the DynamicCamera object, guarantees initialization of the singleton instance through the static constructor, and denies any accidental user modification to the instance reference because we’ve made it readonly.

An additional perk is that if our code never accesses the MainCamera class methods, the player camera will never be constructed. Nice and lazy.

I’ve put together a simple example of scene initialization using this pattern. We have a SceneManager node sitting in the scene that loads in everything else.

using UnityEngine;

public class SceneManager : MonoBehaviour
{

	// Initializes the entire scene
	void Start ()
    {
        // Create the player and the boss.
        GameObject myPlayer = new GameObject("The Player");
        GameObject bossMonster = new GameObject("The Boss");

        // Set up player cam
        MainCamera.Initialize(myPlayer.transform);
        MainCamera.FadeInCamera(5.0f);

        // Set up boss camera
        BossCamera.Initialize(bossMonster.transform);
        BossCamera.LookAtPlayer(myPlayer.transform);

        // Keep loading things...
	}

}

You’ll notice I also created another static class called BossCamera. It is another singleton that shares much of the implementation of the MainCamera class but also has some specific features like the ability to LookAtPlayer. Using this pattern, you have the ability to create multiple global instances that share the same underlying implementation! Both my MainCamera and BossCamera can be interfaced with identically and preserve all the characteristics of a Singleton we’re looking for. And if the scene doesn’t have a boss in it, we won’t need to allocate any resources for the BossCamera reference!


Outcome

There you have it. The Encapsulated Lazy Singleton offers everything you’d expect out of your singletons and with additional security. One thing that can not be overlooked is how easy it is to take a completed class and write the static class to hold the private singleton implementation. The internal implementation of the singleton’d class is unchanged and can still be used anywhere else a singleton isn’t necessary!

Maya Python – Select By Volume

posted in: Uncategorized | 1

I wrote up this quick script in response to a tech-artists.org forum post requested help on this selection-helper method. The below script should properly select all objects in a scene that are at least partially contained within the specified object’s bounding box volume.  This script is currently limited by the fact that the bounding box calculation performed by the xform command returns an axis-aligned box. To improve this, calculate the boundingbox with respect to the object’s local transformation – see http://tech-artists.org/forum/showthread.php?2860-maya-Object-Aligned-Bounding-Box. This will allow you to rotate your bounding volume object and still return visually expected results.

import maya.cmds as cmds

class BoundingBox():
''' Helper class for bounding box-related calculations. '''

    @classmethod
    def FromShape(cls, shapeObj):
    ''' Constructor method to create a bounding box from a shape. '''

        boundingBox = BoundingBox()
        bb = cmds.xform(shapeObj, q=True, bb=True)
        boundingBox.minX = bb[0]
        boundingBox.minY = bb[1]
        boundingBox.minZ = bb[2]
        boundingBox.maxX = bb[3]
        boundingBox.maxY = bb[4]
        boundingBox.maxZ = bb[5]
        return boundingBox

    def ContainsPoint(self, point):
    ''' Returns whether or not a point is contained in this bounding box. '''
        return (point[0] > self.minX and point[0] < self.maxX and point[1] > self.minY and point[1] < self.maxY and point[2] > self.minZ and point[2] < self.maxZ)

    def ContainsShape(self, shape):
    ''' Returns whether or not a shape is intersecting with this bounding box. '''
        shapeBB = BoundingBox.FromShape(shape)
        return (shapeBB.minX < self.maxX and shapeBB.maxX > self.minX) and (shapeBB.minY < self.maxY and shapeBB.maxY > self.minY) and(shapeBB.maxZ < self.maxZ and shapeBB.maxZ > self.minZ)

def SelectByVolume(volumeObj):
 ''' Selects all transforms in the scene that are within the specified argument's bounding box volume. '''

    # Create bounding box class from object
    boundingBox = BoundingBox.FromShape(volumeObj)

    # Get all scene objects asides from bounding box
    cmds.select(allDagObjects=True)
    sceneObjs = [obj for obj in cmds.ls(sl=True) if obj != volumeObj]

    # Compare against every object in our scene to determine what is in our volume
    newSelection = list()
    for obj in sceneObjs:
        objPos = cmds.xform(obj, q=True, rotatePivot=True, ws=True)

        # If the shape's bounding box intersects with the volume's bounding box
        if boundingBox.ContainsShape(obj):
            print "%s is contained."%obj
            newSelection.append(obj)

        # NOTE - Optional alternative means to determine objects within volume.
        # If the center of the object is contained
        #if boundingBox.ContainsPoint(objPos):
            # print "%s is contained."%obj
            # newSelection.append(obj)

    # Silly but compact list comprehension way of getting all our objects
    #newSelection = [obj for obj in [obj for obj in cmds.ls(sl=True) if obj != volumeObj] if boundingBox.ContainsPoint( cmds.xform(obj, q=True, rotatePivot=True, ws=True))]

    # Update selection
    if newSelection:
        cmds.select(newSelection)
    else:
        cmds.select(clear=True)

# Usage
yourVolumeObject = 'pCube1'
SelectByVolume(yourVolumeObject)

Unity Editor Script – Group Selected

posted in: Uncategorized | 0

This post offers an editor convenience class for Maya-like grouping of objects in the Unity scene hierarchy. It configures this script to run with the hotkey (Ctrl+G). Drop this into the editor. Your artists will love it. It currently does not take into account any parent groups that might be above your selected transforms. It will always try to group the selected to the an empty node at the world root.

 

using UnityEngine;
using UnityEditor;
using System.Collections;

public class GroupSelected : EditorWindow
{
    /// &lt;summary&gt;
    ///  Creates an empty node at the center of all selected nodes and parents all selected underneath it. 
    ///  Basically a nice re-creation of Maya grouping!
    /// &lt;/summary&gt;

    [MenuItem(&quot;GameObject/Group Selected %g&quot;, priority = 80)]
    static void Init()
    {
        Transform[] selected = Selection.GetTransforms(SelectionMode.ExcludePrefab | SelectionMode.TopLevel);

        GameObject emptyNode = new GameObject();
        Vector3 averagePosition = Vector3.zero;
        foreach(Transform node in selected)
        {
            averagePosition += node.position;
        }
        if (selected.Length &gt; 0)
        {
            averagePosition /= selected.Length;
        }
        emptyNode.transform.position = averagePosition;
        emptyNode.name = &quot;group&quot;;
        foreach (Transform node in selected)
        {
            node.parent = emptyNode.transform;
        }
   }
}

 

 

Select By Material – Python Snippet

posted in: Uncategorized | 0

Here’s another one-line snippet that selects all faces and objects in a scene based on shading group set. Material assignment in Maya is driven by “sets”. According to the Maya documentation, “a set is a logical grouping of an arbitrary collection of objects, attributes, or components of object.”  We’ll be querying a set to find everything assigned by a specific material and then selecting it.

cmds.select(cmds.sets(&quot;initialShadingGroup&quot;, q=True))

This line selects faces and objects assigned with lambert1, a helpful check I perform in scenes before exporting. (We never want artists to export default Maya materials.) It shows the artist where in the scene the lambert1 lives by highlighting it in the selection.

If you don’t know the name of the set associated with the material off hand (you probably won’t), you can easily translate from material name to set:

materialName = &quot;lambert1&quot;
shadingGroup = cmds.listConnections(materialName, type=&quot;shadingEngine&quot;)
componentsWithMaterial = cmds.sets(shadingGroup, q=True)
cmds.select(componentsWithMaterial)

 

List All Texture Files In Scene – Python Method

posted in: Uncategorized | 0

Here’s another Python snippet you can use in Maya to, in one line, gather a list of all the files referenced in your scene. This is of great use whenever you need to copy, export, or do other actions on textures associated with a particular Maya scene.

allFiles = [cmds.getAttr(&quot;%s.fileTextureName&quot;%file) for file in cmds.ls(type=&quot;file&quot;)]

This Python list comprehension iterates over every file found using the ls command and then gets the attribute that points to the file node’s texture path. Easy!

 

As an alternative, if you’re concerned about only transferring specific file types, or handling certain file types differently, you can use the following extended version of the above line.

fileFilter = &quot;.jpg&quot;
typedFiles = [cmds.getAttr(&quot;%s.fileTextureName&quot;%file) for file in cmds.ls(type=&quot;file&quot;) if fileFilter in cmds.getAttr(&quot;%s.fileTextureName&quot;%file)]

Save To Clipboard Python Method

posted in: Uncategorized | 0

Here’s a super useful snippet you can use to copy any string to the user’s OS clipboard. We use this for any manual data-entry into databases or spreadsheets.

def addToClipboard(text):
    command = 'echo ' + text.strip() + '| clip'
    mel.eval(&quot;system(&quot;%s&quot;) &quot;%command)

You’ll notice I wrap the system call with MEL. This is just a personal touch and definitely not needed. I’ve noticed the usual python call to os.system displays an empty command line window for a split second while executing the command. This is a bit distracting to me.. and  the MEL version seems to avoid that. :]