diff --git a/README.md b/README.md index 72c37e9..d9ff192 100644 --- a/README.md +++ b/README.md @@ -43,13 +43,15 @@ $ pip install pyblish-starter ### Usage -Plug-ins are registered by calling `setup()`. +Starter is initialised by calling `setup()`. ```python >>> import pyblish_starter >>> pyblish_starter.setup() ``` +From here, you model, rig and animate as per the contract below. +

@@ -71,13 +73,13 @@ Starter defines these families. A generic representation of geometry. -**Target Audience** +![aud][] **Target Audience** - Texturing - Rigging - Final render -**Requirements** +![req][] **Requirements** - Static geometry (no deformers, generators) `*` - One shape per transform `*` @@ -90,11 +92,11 @@ A generic representation of geometry. - No faces with zero area `*` - No self-intersections `*` -**Data** +![dat][] **Data** - `label (str, optional)`: Pretty printed name in graphical user interfaces -**Sets** +![set][] **Sets** - `geometry_SEL (geometry)`: Meshes suitable for rigging - `aux_SEL (any, optional)`: Auxilliary meshes for e.g. fast preview, collision geometry @@ -108,17 +110,17 @@ A generic representation of geometry. The `starter.rig` contains the necessary implementation and interface for animators to produce -**Requirements** +![req][] **Requirements** - Channels in `controls_SEL` at *default* values`*` - No input connection to animatable channel in `controls_SEL` `*` - [No self-intersections on workout](#workout) `*` -**Data** +![dat][] **Data** - `label (str, optional)`: Pretty printed name in graphical user interfaces -**Sets** +![set][] **Sets** - `cache_SEL (geometry)`: Meshes suitable for pointcaching from animation - `controls_SEL (transforms)`: All animatable controls @@ -133,21 +135,21 @@ The `starter.rig` contains the necessary implementation and interface for animat Point positions and normals represented as one Alembic file. -**Requirements** +![req][] **Requirements** - [No infinite velocity](#extreme-acceleration) `*` - [No immediate acceleration](#extreme-acceleration) `*` - [No self-intersections](#self-intersections) `*` - No sub-frame keys `*` -- [Edge angles within -120 to 120 degrees on elastic surfaces](#extreme-surface-tangency) `*` +- [Edge angles > 30 degrees on elastic surfaces](#extreme-surface-tangency) `*` - [Edge lengths within 50-150% for elastic surfaces](#extreme-surface-stretch-or-compression) `*` - [Edge lengths within 90-110% for rigid surfaces](#extreme-surface-stretch-or-compression) `*` -**Data** +![dat][] **Data** - `label (str, optional)`: Pretty printed name in graphical user interfaces -**Sets** +![set][] **Sets** - None @@ -155,13 +157,19 @@ Point positions and normals represented as one Alembic file. **Legend** -| Title | Description -|:--------------------|:----------- -| **Target Audience** | Who is the end result of this family intended for? -| **Requirements** | What is expected of this asset before it passes the tests? -| **Data** | End-user configurable options -| **Sets** | Collection of specific items for publishing or use further down the pipeline. -| `*` | Todo +| | Title | Description +|:---------|:--------------------|:----------- +| ![aud][] | **Target Audience** | Who is the end result of this family intended for? +| ![req][] | **Requirements** | What is expected of this asset before it passes the tests? +| ![dat][] | **Data** | End-user configurable options +| ![set][] | **Sets** | Collection of specific items for publishing or use further down the pipeline. +| | `*` | Todo + + +[set]: https://cloud.githubusercontent.com/assets/2152766/18576835/f6b80574-7bdc-11e6-8237-1227f779815a.png +[dat]: https://cloud.githubusercontent.com/assets/2152766/18576836/f6ca19e4-7bdc-11e6-9ef8-3614474c58bb.png +[req]: https://cloud.githubusercontent.com/assets/2152766/18576838/f6da783e-7bdc-11e6-9935-78e1a6438e44.png +[aud]: https://cloud.githubusercontent.com/assets/2152766/18576837/f6d9c970-7bdc-11e6-8899-6eb8686b4173.png

@@ -239,8 +247,9 @@ from pyblish_starter.maya import ( cmds.file(new=True, force=True) # Load external asset -input_ = load("Paul_model", version=1, namespace="Paul_") -model_assembly = cmds.listRelatives(input_[0], children=True)[0] +reference = load("Paul_model", namespace="Paul_") +nodes = cmds.referenceQuery(reference, nodes=True) +model_assembly = cmds.listRelatives(nodes[0], children=True)[0] model_geometry = outmesh(cmds.listRelatives( model_assembly, shapes=True)[0], name="Model") @@ -292,7 +301,7 @@ for key, value in data.items(): cmds.setAttr(instance + "." + key, value, type="string") from pyblish import util -#util.publish() +util.publish() ```
@@ -304,14 +313,38 @@ Build upon the previous example by referencing and producing an animation from t ```python from maya import cmds from pyblish_starter.maya import ( - load + load, + create ) cmds.file(new=True, force=True) # Load external asset -rig = load("Paul_rig", version=1, namespace="Paul01_")[0] - +reference = load("Paul_rig", namespace="Paul01_") +nodes = cmds.referenceQuery(reference, nodes=True) + +# Animate +cmds.playbackOptions(minTime=1001, maxTime=1050) + +all_controls = next(ctrl for ctrl in nodes if "all_controls" in ctrl) +control = cmds.sets(all_controls, query=True)[0] + +keys = [ + (1001, 0), + (1025, 10), + (1050, 0) +] + +for time, value in keys: + cmds.setKeyframe(control, + attribute="translateY", + value=value, + time=time, + inTangentType="flat", + outTangentType="flat") + +# Publish +... ```
diff --git a/pyblish_starter/maya/__init__.py b/pyblish_starter/maya/__init__.py index a3fb276..72d5962 100644 --- a/pyblish_starter/maya/__init__.py +++ b/pyblish_starter/maya/__init__.py @@ -6,6 +6,7 @@ hierarchy_from_string, outmesh, load, + create, setup, ) @@ -15,5 +16,6 @@ "hierarchy_from_string", "outmesh", "load", + "create", "setup", ] diff --git a/pyblish_starter/maya/lib.py b/pyblish_starter/maya/lib.py index 225ac72..65a738e 100644 --- a/pyblish_starter/maya/lib.py +++ b/pyblish_starter/maya/lib.py @@ -1,4 +1,5 @@ import os +import re from maya import cmds @@ -70,29 +71,85 @@ def outmesh(shape, name=None): return outmesh -def load(asset, version, namespace=None): +def find_latest_version(versions): + """Return latest version from list of versions + + If multiple numbers are found in a single version, + the last one found is used. E.g. (6) from "v7_22_6" + + Arguments: + versions (list): Version numbers as string + + Example: + >>> find_next_version(["v001", "v002", "v003"]) + 4 + >>> find_next_version(["1", "2", "3"]) + 4 + >>> find_next_version(["v1", "v0002", "verision_3"]) + 4 + >>> find_next_version(["v2", "5_version", "verision_8"]) + 9 + >>> find_next_version(["v2", "v3_5", "_1_2_3", "7, 4"]) + 6 + >>> find_next_version(["v010", "v011"]) + 12 + + """ + + highest_version = 0 + for version in versions: + matches = re.findall(r"\d+", version) + + if not matches: + continue + + version = int(matches[-1]) + if version > highest_version: + highest_version = version + + return highest_version + + +def find_next_version(versions): + return find_latest_version(versions) + 1 + + +def load(asset, version=-1, namespace=None): """Load asset Arguments: asset (str): Name of asset - version (int): Version number + version (int, optional): Version number, defaults to latest namespace (str, optional): Name of namespace Returns: - Assembly/ies + Reference node """ assert isinstance(version, int), "Version must be integer" - asset = os.path.join( + dirname = os.path.join( + cmds.workspace(rootDirectory=True, query=True), "public", - asset, + asset + ) + + try: + versions = os.listdir(dirname) + except OSError: + raise OSError("\"%s\" not found." % asset) + + if version == -1: + version = find_latest_version(versions) + + fname = os.path.join( + dirname, "v%03d" % version, asset + ".ma" ) - cmds.file(asset, reference=True, namespace=namespace) - reference = cmds.file(asset, query=True, referenceNode=True) - nodes = cmds.referenceQuery(reference, nodes=True) - return cmds.ls(nodes, assemblies=True) + return cmds.file(fname, + namespace=namespace, + reference=True, + referenceNode=True) diff --git a/pyblish_starter/tools/instance_creator/__init__.py b/pyblish_starter/tools/instance_creator/__init__.py index ba1a186..8433962 100644 --- a/pyblish_starter/tools/instance_creator/__init__.py +++ b/pyblish_starter/tools/instance_creator/__init__.py @@ -1,7 +1,6 @@ from .lib import ( register_default, register_family, - create, ) from .app import ( @@ -11,7 +10,6 @@ __all__ = [ "register_default", "register_family", - "create", "show", ] diff --git a/pyblish_starter/tools/instance_creator/app.py b/pyblish_starter/tools/instance_creator/app.py index 7ec73aa..75b9b3b 100644 --- a/pyblish_starter/tools/instance_creator/app.py +++ b/pyblish_starter/tools/instance_creator/app.py @@ -2,6 +2,7 @@ import contextlib from ...vendor.Qt import QtWidgets, QtCore +from ...maya.lib import create import lib @@ -142,7 +143,7 @@ def on_create(self): use_selection = use_selection_chk.checkState() try: - lib.create(name, family, use_selection) + create(name, family, use_selection) except NameError as e: error_msg.setText(str(e))