Skip to content

Commit

Permalink
Fixed parenting for controls and added an override_root kwarg so we c…
Browse files Browse the repository at this point in the history
…an not rely on instance.root being set and can use arbitrary "top" nodes to parent a rig

Fixed the auto_save_results so that we are now properly saving out files that represent the state of the test case.  This will make testing MUCH easier and quicker.

Changed auto_save_results to read environment variables instead so that we can set env vars instead of rely on passing kwargs which is less easy to do with unittests.
  • Loading branch information
AndresMWeber committed Mar 10, 2018
1 parent bc0650c commit 62c1a09
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 44 deletions.
9 changes: 5 additions & 4 deletions anvil/grouping/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,14 @@ def initialize_sub_rig_attributes(self, controller=None, attr_dict=None):
for attr, attr_kwargs in iteritems(attr_dict):
controller.add_attr(attr, **attr_kwargs)

def parent(self, new_parent):
nodes_exist = [rt.dcc.scene.exists(node) if node is not None else False for node in [self.root, new_parent]]
def parent(self, new_parent, override_root=None):
nodes_exist = [rt.dcc.scene.exists(node) if node is not None else False for node in
[override_root or self.root, new_parent]]
if all(nodes_exist or [False]):
self.root.parent(new_parent)
(override_root or self.root).parent(new_parent)
return True
else:
self.warning('Parent(%s) -> %r does not exist.', new_parent, self.root)
self.warning('Parent(%s) -> %r does not exist.', new_parent, override_root or self.root)
return False

def rename_chain(self, nodes, use_end_naming=False, **name_tokens):
Expand Down
5 changes: 4 additions & 1 deletion anvil/grouping/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ class Control(base.AbstractGrouping):
SHAPE_PARENT_KWARGS = {cfg.RELATIVE: True, cfg.ABSOLUTE: False, cfg.SHAPE: True}

def __init__(self, **kwargs):
super(Control, self).__init__(**kwargs)
self.controller = None
self.connection_group = None
self.offset_group = None
super(Control, self).__init__(**kwargs)

@classmethod
def build(cls, reference_object=None, parent=None, meta_data=None, name_tokens=None, **kwargs):
Expand Down Expand Up @@ -100,3 +100,6 @@ def swap_shape(self, new_shape, maintain_position=False):

def rename(self, *input_dicts, **kwargs):
super(Control, self).rename(*input_dicts, **kwargs)

def parent(self, new_parent, override_root=None):
super(Control, self).parent(new_parent, override_root=override_root or self.offset_group or self.controller)
6 changes: 3 additions & 3 deletions anvil/sub_rig_templates/base_sub_rig_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ def build_fk_chain(self, chain_start=None, chain_end=None, shape=None, duplicate
name_tokens=name_tokens,
meta_data=meta_data,
**kwargs)
fk_controls.append(control)

control_parent = fk_controls[-1].node.connection_group
control.parent(control_parent)
control_parent = control.node.connection_group
rt.dcc.connections.parent(control_parent, node, maintainOffset=True)
fk_controls.append(control)
return fk_chain, fk_controls
3 changes: 2 additions & 1 deletion tests/acceptance/test_MVP.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from six import itervalues
import anvil
import anvil.node_types as nt
from tests.base_test import TestBase, sanitize_scene
from tests.base_test import TestBase, sanitize_scene, auto_save_result


class TestBaseRig(TestBase):
Expand Down Expand Up @@ -36,6 +36,7 @@ def build_dependencies(cls):


class TestRigEyeBuild(TestBaseRig):
@auto_save_result
def test_control_created(self):
self.assertEqual(self.test_rig.find_node('universal'), self.test_rig.control.universal)

Expand Down
30 changes: 16 additions & 14 deletions tests/acceptance/test_biped.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import anvil.config as cfg
import anvil.node_types as nt
from anvil.rig_templates import Biped
from tests.base_test import TestBase, sanitize, auto_save_result
from tests.base_test import TestBase, clean_up_scene, auto_save_result


class TestBaseTemplateRigs(TestBase):
Expand All @@ -11,7 +11,6 @@ class TestBaseTemplateRigs(TestBase):
CLASS = Biped

@classmethod
@auto_save_result
def from_template_file(cls, template_file, **kwargs):
cls.import_template_files(template_file)

Expand All @@ -34,7 +33,8 @@ def from_template_file(cls, template_file, **kwargs):
for side in [cfg.LEFT, cfg.RIGHT]:
fingers = []
for finger in ['thb', 'ind', 'mid', 'rng', 'pnk']:
fingers.append(nt.LinearHierarchyNodeSet(finger_start % (side[0], finger), finger_end % (side[0], finger)))
fingers.append(
nt.LinearHierarchyNodeSet(finger_start % (side[0], finger), finger_end % (side[0], finger)))
sub_rig_dict[side + '_' + cfg.HAND] = {'finger_joints': fingers, 'scale': 0.3}

rig_instance = cls.CLASS(sub_rig_dict=sub_rig_dict, name_tokens={cfg.CHARACTER: 'hombre'}, **kwargs)
Expand All @@ -43,19 +43,21 @@ def from_template_file(cls, template_file, **kwargs):


class TestBuildBiped(TestBaseTemplateRigs):
@clean_up_scene
@auto_save_result
def test_build_with_parent_t_pose(self):
with sanitize():
parent = nt.Transform.build(name='test')
rig_instance = self.from_template_file(self.TPOSE, parent=parent)
self.assertEqual(str(rig_instance.root.get_parent()), str(parent))
parent = nt.Transform.build(name='test')
rig_instance = self.from_template_file(self.TPOSE, parent=parent)
self.assertEqual(str(rig_instance.root.get_parent()), str(parent))

@clean_up_scene
@auto_save_result
def test_build_with_parent_a_pose(self):
with sanitize():
parent = nt.Transform.build(name='test')
rig_instance = self.from_template_file(self.APOSE, parent=parent)
self.assertEqual(str(rig_instance.root.get_parent()), str(parent))
parent = nt.Transform.build(name='test')
rig_instance = self.from_template_file(self.APOSE, parent=parent)
self.assertEqual(str(rig_instance.root.get_parent()), str(parent))

@clean_up_scene
def test_sub_rigs(self):
with sanitize():
rig_instance = self.from_template_file(self.APOSE)
self.assertEqual(sorted(list(rig_instance.sub_rigs)), sorted(list(rig_instance.SUB_RIG_BUILD_TABLE)))
rig_instance = self.from_template_file(self.APOSE)
self.assertEqual(sorted(list(rig_instance.sub_rigs)), sorted(list(rig_instance.SUB_RIG_BUILD_TABLE)))
10 changes: 7 additions & 3 deletions tests/acceptance/test_biped_foot.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from six import iteritems
import anvil.node_types as nt
from anvil.sub_rig_templates import BipedFoot
from tests.base_test import TestBase, clean_up_scene, sanitize
from tests.base_test import TestBase, clean_up_scene, auto_save_result
import anvil.config as cfg


Expand All @@ -27,16 +27,19 @@ def from_template_file(cls, template_file, pre_build_hook=None, post_build_hook=

class TestBuildBipedFoot(TestBaseTemplateRigs):
@clean_up_scene
@auto_save_result
def test_build_no_kwargs(self):
self.from_template_file(self.FOOT)

@clean_up_scene
@auto_save_result
def test_build_with_parent(self):
parent = nt.Transform.build(name='test')
rig_instance = self.from_template_file(self.FOOT, parent=parent)
self.assertEqual(str(rig_instance.root.get_parent()), str(parent))

@clean_up_scene
@auto_save_result
def test_build_with_leg_ik_and_soles(self):
self.import_template_files(self.FOOT_WITH_LEG_AND_SOLES)
self.build_leg_ik()
Expand All @@ -50,6 +53,7 @@ def test_build_with_leg_ik_and_soles(self):
# [round(p, 5) for p in joint.get_world_position()])

@clean_up_scene
@auto_save_result
def test_build_with_leg_ik(self):
parent = nt.Transform.build(name='test')
rig_instance = self.from_template_file(self.FOOT_WITH_LEG, parent=parent, pre_build_hook=self.build_leg_ik)
Expand All @@ -58,8 +62,8 @@ def test_build_with_leg_ik(self):
@staticmethod
def build_leg_ik():
foot_ball_result = TestBuildBipedFoot.TEMPLATE().build_ik(nt.LinearHierarchyNodeSet('hip', 'foot',
node_filter=cfg.JOINT_TYPE),
solver=cfg.IK_RP_SOLVER)
node_filter=cfg.JOINT_TYPE),
solver=cfg.IK_RP_SOLVER)
return {'leg_ik': foot_ball_result[cfg.NODE_TYPE][cfg.DEFAULT]}


Expand Down
21 changes: 12 additions & 9 deletions tests/acceptance/test_hand.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from six import iteritems
import anvil.node_types as nt
from anvil.utils.scene import print_scene_tree
from anvil.sub_rig_templates import Hand
Expand All @@ -14,7 +13,6 @@ class TestHandBase(TestBase):
TEMPLATE_CLASS = Hand

@classmethod
@auto_save_result
def from_template_file(cls, template_file, finger_start_joints=None, **kwargs):
cls.import_template_files(template_file)

Expand All @@ -37,29 +35,34 @@ def setUpClass(cls):
print_scene_tree()
raise e

@auto_save_result
def test_build_no_kwargs_no_errors(self):
self.assertIsNotNone(self.hand)

def test_number_of_controls(self):

controls = [node for node in self.hand._flat_hierarchy() if isinstance(node, nt.Control)]
self.assertEqual(len(controls), 15)
def test_number_of_controls_from_flat_hierarchy(self):
pprint(self.hand.hierarchy)
self.assertEqual(len([node for node in self.hand._flat_hierarchy() if isinstance(node, nt.Control)]), 15)

def test_number_of_control_top_groups(self):
def test_number_of_controls_from_get_children(self):
pprint(self.hand.hierarchy)
self.assertEqual(len(self.hand.group_controls.get_children()), 10)

def test_number_of_joint_chains(self):
def test_number_of_joint_chains_from_get_children(self):
pprint(self.hand.hierarchy)
self.assertEqual(len(self.hand.group_joints.get_children()), 15)

def test_number_of_nodes(self):
def test_number_of_joints_from_flat_hierarchy(self):
pprint(self.hand.hierarchy)
self.assertEqual(len([node for node in self.hand._flat_hierarchy() if isinstance(node, nt.Joint)]), 15)

def test_number_of_nodes_from_get_children(self):
pprint(self.hand.hierarchy)
self.assertEqual(len(self.hand.group_nodes.get_children()), 5)


class TestBuildDefaultHand(TestHandBase):
@clean_up_scene
@auto_save_result
def test_build_with_parent(self):
parent = nt.Transform.build(name='test')
rig_instance = self.from_template_file(self.HAND_MERC, self.HAND_MERC_JOINTS, parent=parent)
Expand Down
22 changes: 13 additions & 9 deletions tests/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
from functools import wraps

os.environ['ANVIL_MODE'] = 'TEST'
import logging
os.environ['A_SAVE_PREFIX'] = 'test_results'
os.environ['A_SAVE_PATH'] = os.path.expanduser(os.path.join('~', '.anvil'))

from logging import getLogger, CRITICAL
from collections import Iterable
from anvil.utils.scene import sanitize_scene
from contextlib import contextmanager
Expand All @@ -18,8 +21,8 @@

class TestBase(unittest2.TestCase):
LOG = obtain_logger('testing')
logging.getLogger('pymel.core.nodetypes').setLevel(logging.CRITICAL)
LOG.setLevel(logging.CRITICAL)
getLogger('pymel.core.nodetypes').setLevel(CRITICAL)
LOG.setLevel(CRITICAL)

APOSE = 'APOSE'
TPOSE = 'TPOSE'
Expand Down Expand Up @@ -104,17 +107,18 @@ def wrapped(self, *args, **kwargs):

return wrapped


def auto_save_result(func):
@wraps(func)
def wrapped(self, *args, **kwargs):
save_file = kwargs.pop('save_file', False)
save_path = kwargs.pop('save_path', False)
save_file = os.environ.get('A_SAVE_PREFIX', None)
save_path = os.environ.get('A_SAVE_PATH', None)
func_return = func(self, *args, **kwargs)
if save_file:
rt.dcc.scene.fileop(rename=os.path.join([f for f in [save_path, save_file, 'mb'] if f]),
save=True,
type='mayaBinary')
path = os.path.join(*[f for f in [save_path, self.__class__.__name__+func.__name__+save_file+'.mb'] if f])
rt.dcc.scene.fileop(rename=path)
rt.dcc.scene.fileop(save=True, type='mayaBinary')
print('Saving test result file for test %s in path %s' % (self.__class__.__name__, path))
return func_return

return wrapped

0 comments on commit 62c1a09

Please sign in to comment.