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))