Why tik.maya? ============= Maya scripting with ``maya.cmds`` is powerful but has pain points that compound in larger projects. tik.maya addresses these directly while maintaining Maya's flexibility. The Problem with ``maya.cmds`` ------------------------------ **String-based node references break easily** .. code-block:: python # Using maya.cmds import maya.cmds as cmds cube = cmds.polyCube(name="myCube")[0] cmds.setAttr(f"{cube}.translateX", 5) # If something renames the node... cmds.rename(cube, "renamedCube") # Your reference is now broken cmds.setAttr(f"{cube}.translateX", 10) # Error! "myCube" doesn't exist **Verbose, repetitive code** .. code-block:: python # Lock and hide attributes requires multiple calls cmds.setAttr("pCube1.scaleX", lock=True) cmds.setAttr("pCube1.scaleX", keyable=False) cmds.setAttr("pCube1.scaleX", channelBox=False) **No type safety** .. code-block:: python # Typos only discovered at runtime cmds.setAttr("pCube1.tranlsateX", 5) # Misspelled! How tik.maya Solves This ------------------------- MObject Tracking with UUID Backup ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tik.maya tracks nodes using :class:`maya.api.OpenMaya.MObject` handles for performance, with UUID as a backup for restoration. References stay valid through renames, namespacing, and re-parenting. .. code-block:: python import tik.maya as tm cube = tm.resolve("myCube") cube.translate_x = 5 # Rename works seamlessly cube.rename("renamedCube") cube.translate_x = 10 # Still works! Under the hood, tik.maya uses MObject as the primary handle for speed. If the MObject becomes stale (e.g., after undo/redo), tik.maya reconstructs it from the stored UUID, providing a fast path with a safe fallback. Flexible Dynamic Wrapping ~~~~~~~~~~~~~~~~~~~~~~~~~~ tik.maya's architecture brings **fine-tuning, speed, elegance, and extensibility** together through dynamic wrapping: .. code-block:: python # Works as a drop-in replacement for maya.cmds import tik.maya as tm # Instead of: import maya.cmds as cmds # All cmds functions work automatically cube = tm.polyCube(name="myCube")[0] tm.xform(cube, translation=(1, 2, 3)) tm.setAttr(f"{cube}.visibility", 0) **But with key advantages:** - **Automatic object wrapping:** Node-returning commands give you typed objects, not strings - **Selective overrides:** Performance-critical functions like ``createNode`` use optimized OpenMaya API - **Extensible design:** Add custom behavior without modifying Maya - **Zero migration cost:** Change your import statement and existing scripts work .. code-block:: python # You also get the object-oriented benefits cube.translate = (5, 6, 7) cube["visibility"].value = False cube["visibility"].locked = True # And mathematical operators for dependency networks driver = tm.spaceLocator()[0] (driver["translateX"] * 2.0 + 5) >> cube["translateY"] This flexible structure means you can migrate gradually — use ``tm.polyCube()`` just like ``cmds.polyCube()`` when convenient, or embrace the object-oriented API when it makes sense. See the ``snippets/comparisons/08_cylinder_rig/`` example to see how an entire rigging script works with just an import change! Concise, Readable Code ~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: python # Lock and hide in one line cube["scaleX"].locked = True cube["scaleX"].visible = False # Or batch operations for attr in ["scaleX", "scaleY", "scaleZ"]: cube[attr].locked = True cube[attr].visible = False # Connect with operators driver["translate"] >> cube["translate"] Pythonic and Type-Safe ~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: python # Properties for state, methods for actions cube.visibility = False cube.freeze(translate=True, rotate=True) # Automatic type resolution mesh = tm.resolve("pCubeShape1") # Returns Mesh joint = tm.resolve("joint1") # Returns Joint # IDE autocomplete and type hints work cube. # Shows: translate, rotate, freeze(), snap_to(), etc. Procedural Math Networks ~~~~~~~~~~~~~~~~~~~~~~~~ Build dependency graphs using Python operators: .. code-block:: python driver = tm.Transform.create(name="driver") follower = tm.Transform.create(name="follower") # Arithmetic creates and connects utility nodes automatically (driver["tx"] * 2.0 + 5) >> follower["ty"] Side-by-Side Comparison ----------------------- **Connecting attributes:** .. code-block:: python # maya.cmds cmds.connectAttr("driver.translateX", "driven.translateX", force=True) cmds.connectAttr("driver.translateY", "driven.translateY", force=True) cmds.connectAttr("driver.translateZ", "driven.translateZ", force=True) # tik.maya driver["translate"] >> driven["translate"] **Creating and positioning:** .. code-block:: python # maya.cmds loc = cmds.spaceLocator(name="myLocator")[0] cmds.setAttr(f"{loc}.translate", 1, 2, 3, type="double3") # tik.maya loc = tm.Locator.create(name="myLocator") loc.transform.translate = (1, 2, 3) When to Use What ---------------- **Use tik.maya when:** - Building tools that manipulate scene objects - Writing rigging scripts needing reliable references - You want maintainable, readable code **Consider raw API when:** - Performance-critical inner loops (though tik.maya is fast) - Operations tik.maya doesn't wrap yet .. note:: tik.maya and ``cmds`` coexist. Use ``node.name`` to pass tik.maya objects to ``cmds`` functions. Summary ------- +---------------------------+----------------------------------+-------------------------------------+-------------------------------------------+ | Pain Point | ``maya.cmds`` | ``maya.api.OpenMaya`` | **tik.maya** | +===========================+==================================+=====================================+===========================================+ | Node references | Strings — break on rename | MObject/MDagPath handles — robust | MObj/UUID-backed — survives renames | +---------------------------+----------------------------------+-------------------------------------+-------------------------------------------+ | Code verbosity | Multiple calls per operation | Verbose boilerplate (fn sets, plugs)| Concise properties and methods | +---------------------------+----------------------------------+-------------------------------------+-------------------------------------------+ | Performance | Moderate | Fastest (No Undo / Not crash safe) | Fast (With Undo support and more stable) | +---------------------------+----------------------------------+-------------------------------------+-------------------------------------------+ | Type safety | None — errors at runtime | Stronger typing via API classes | IDE completion, type hints | +---------------------------+----------------------------------+-------------------------------------+-------------------------------------------+ | API style | Procedural, flag-heavy | Low-level, explicit, handle-based | Pythonic, object-oriented | +---------------------------+----------------------------------+-------------------------------------+-------------------------------------------+ | Debugging | String matching errors | Object inspection via function sets | Object inspection, clear errors | +---------------------------+----------------------------------+-------------------------------------+-------------------------------------------+ tik.maya combines the simplicity of ``maya.cmds`` with the robustness of ``maya.api.OpenMaya``, wrapped in a Pythonic interface. Write less code, catch errors earlier, and stop worrying about node names.