From efa35b66bdf8434149e508de4184269864ce1b8f Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sun, 13 Aug 2017 14:32:15 +0100 Subject: [PATCH 01/30] Refactor optimise vertex cache to nose test. Renamed files to drop the name asa already convention from dir structure --- tests/spells/nif/opt_vertex_cache.txt | 44 ----------------- ...sion_optimisation.py => test_collision.py} | 18 ++++--- ...oaster_optimisation.py => test_toaster.py} | 4 +- .../spells/nif/optimize/test_vertex_cache.py | 47 +++++++++++++++++++ tests/test_doctests.py | 1 - 5 files changed, 57 insertions(+), 57 deletions(-) delete mode 100644 tests/spells/nif/opt_vertex_cache.txt rename tests/spells/nif/optimize/{test_collision_optimisation.py => test_collision.py} (97%) rename tests/spells/nif/optimize/{test_toaster_optimisation.py => test_toaster.py} (95%) create mode 100644 tests/spells/nif/optimize/test_vertex_cache.py diff --git a/tests/spells/nif/opt_vertex_cache.txt b/tests/spells/nif/opt_vertex_cache.txt deleted file mode 100644 index 06daeb867..000000000 --- a/tests/spells/nif/opt_vertex_cache.txt +++ /dev/null @@ -1,44 +0,0 @@ -Regression test for vertex cache algorithm ------------------------------------------- - ->>> nif_dir = "tests/spells/nif/files/" ->>> filename = nif_dir + "test_opt_vertex_cache.nif" - ->>> from pyffi.formats.nif import NifFormat ->>> import pyffi.spells.nif.optimize ->>> data = NifFormat.Data() ->>> stream = open(filename, "rb") ->>> data.read(stream) ->>> # check original data ->>> data.roots[0].children[0].data.num_vertices -32 ->>> # run the spell that optimizes this ->>> spell = pyffi.spells.nif.optimize.SpellOptimizeGeometry(data=data) ->>> spell.recurse() -pyffi.toaster:INFO:--- opt_geometry --- -pyffi.toaster:INFO: ~~~ NiNode [fan] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [fan01] ~~~ -pyffi.toaster:INFO: removing duplicate vertices -pyffi.toaster:INFO: (num vertices was 32 and is now 32) -pyffi.toaster:INFO: optimizing triangle ordering -pyffi.toaster:INFO: (ATVR stable at 1.059) -pyffi.toaster:INFO: optimizing vertex ordering -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:WARNING:unused vertex -pyffi.toaster:INFO: recalculating tangent space ->>> # check optimized data ->>> data.roots[0].children[0].data.num_vertices -17 diff --git a/tests/spells/nif/optimize/test_collision_optimisation.py b/tests/spells/nif/optimize/test_collision.py similarity index 97% rename from tests/spells/nif/optimize/test_collision_optimisation.py rename to tests/spells/nif/optimize/test_collision.py index ddd2bb748..53b039893 100644 --- a/tests/spells/nif/optimize/test_collision_optimisation.py +++ b/tests/spells/nif/optimize/test_collision.py @@ -1,7 +1,3 @@ -from tests.scripts.nif import call_niftoaster -import os -import shutil - from . import BaseFileTestCase import nose import pyffi @@ -77,12 +73,14 @@ def test_box_from_unpacked_collision_optimisation(self): spell = pyffi.spells.nif.optimize.SpellOptimizeCollisionBox(data=self.data) spell.recurse() - # pyffi.toaster:INFO:--- opt_collisionbox --- - # pyffi.toaster:INFO: ~~~ NiNode [TestBhkNiTriStripsShape] ~~~ - # pyffi.toaster:INFO: ~~~ bhkCollisionObject [] ~~~ - # pyffi.toaster:INFO: ~~~ bhkRigidBodyT [] ~~~ - # pyffi.toaster:INFO: optimized box collision - # pyffi.toaster:INFO: ~~~ NiTriShape [Stuff] ~~~ + """ + pyffi.toaster:INFO:--- opt_collisionbox --- + pyffi.toaster:INFO: ~~~ NiNode [TestBhkNiTriStripsShape] ~~~ + pyffi.toaster:INFO: ~~~ bhkCollisionObject [] ~~~ + pyffi.toaster:INFO: ~~~ bhkRigidBodyT [] ~~~ + pyffi.toaster:INFO: optimized box collision + pyffi.toaster:INFO: ~~~ NiTriShape [Stuff] ~~~ + """ # check optimized data shape = self.data.roots[0].collision_object.body.shape diff --git a/tests/spells/nif/optimize/test_toaster_optimisation.py b/tests/spells/nif/optimize/test_toaster.py similarity index 95% rename from tests/spells/nif/optimize/test_toaster_optimisation.py rename to tests/spells/nif/optimize/test_toaster.py index bfa0d4b52..5673288f0 100644 --- a/tests/spells/nif/optimize/test_toaster_optimisation.py +++ b/tests/spells/nif/optimize/test_toaster.py @@ -8,11 +8,11 @@ from pyffi.spells import Toaster -class FileTestOptimisation(BaseFileTestCase): +class TestToasterOptimisation(BaseFileTestCase): # I didn't need setUp and tearDown here.. def setUp(self): - super(FileTestOptimisation, self).setUp() + super(TestToasterOptimisation, self).setUp() self.src_name = "test.nif" self.src_file = os.path.join(self.input_files, self.src_name) self.dest_file = os.path.join(self.out, self.src_name) diff --git a/tests/spells/nif/optimize/test_vertex_cache.py b/tests/spells/nif/optimize/test_vertex_cache.py new file mode 100644 index 000000000..50500009d --- /dev/null +++ b/tests/spells/nif/optimize/test_vertex_cache.py @@ -0,0 +1,47 @@ +from . import BaseFileTestCase +from nose.tools import assert_equals + +import pyffi + + +class TestVertexCacheOptimisation(BaseFileTestCase): + """Regression test for vertex cache algorithm""" + + def setUp(self): + super(TestVertexCacheOptimisation, self).setUp() + self.src_name = "test_opt_vertex_cache.nif" + super(TestVertexCacheOptimisation, self).copyFile() + super(TestVertexCacheOptimisation, self).readNifData() + + assert_equals(self.data.roots[0].children[0].data.num_vertices, 32) + + def test_non_interactive_opt_merge_duplicates(self): + spell = pyffi.spells.nif.optimize.SpellOptimizeGeometry(data=self.data) + spell.recurse() + + assert_equals(self.data.roots[0].children[0].data.num_vertices, 17) + """ + pyffi.toaster:INFO:--- opt_geometry --- + pyffi.toaster:INFO: ~~~ NiNode [fan] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [fan01] ~~~ + pyffi.toaster:INFO: removing duplicate vertices + pyffi.toaster:INFO: (num vertices was 32 and is now 32) + pyffi.toaster:INFO: optimizing triangle ordering + pyffi.toaster:INFO: (ATVR stable at 1.059) + pyffi.toaster:INFO: optimizing vertex ordering + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:WARNING:unused vertex + pyffi.toaster:INFO: recalculating tangent space """ diff --git a/tests/test_doctests.py b/tests/test_doctests.py index c5b1ca7f7..aa624fafd 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -104,7 +104,6 @@ def create_suite(): 'spells/nif/modify_substitutestringpalette.txt', 'spells/nif/opt_delunusedbones.txt', 'spells/nif/opt_delzeroscale.txt', - 'spells/nif/opt_vertex_cache.txt', # Contain outstanding issues # 'spells/egm/optimize.txt', From 60db61a1d08353dee4170bd72ed6ab8b50e8a215 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sun, 13 Aug 2017 15:19:35 +0100 Subject: [PATCH 02/30] Refactor optimisation spell to remove zero scale --- tests/spells/nif/opt_delzeroscale.txt | 40 ----------------- .../spells/nif/optimize/test_delzeroscale.py | 43 +++++++++++++++++++ tests/test_doctests.py | 1 - 3 files changed, 43 insertions(+), 41 deletions(-) delete mode 100644 tests/spells/nif/opt_delzeroscale.txt create mode 100644 tests/spells/nif/optimize/test_delzeroscale.py diff --git a/tests/spells/nif/opt_delzeroscale.txt b/tests/spells/nif/opt_delzeroscale.txt deleted file mode 100644 index 49175d2f3..000000000 --- a/tests/spells/nif/opt_delzeroscale.txt +++ /dev/null @@ -1,40 +0,0 @@ -Doctests for the opt_delzeroscale spell -======================================= - -NifToaster check ----------------- - ->>> nif_dir = "tests/spells/nif/files/" ->>> filename = nif_dir + "test_opt_zeroscale.nif" - ->>> from pyffi.formats.nif import NifFormat ->>> import pyffi.spells.nif.optimize ->>> from pyffi.spells import Toaster ->>> data = NifFormat.Data() ->>> stream = open(filename, "rb") ->>> data.read(stream) ->>> # check zero scale ->>> for child in data.roots[0].children[0].children: -... print(child.name, child.scale) -b'Tri Cone 0' 1.0 -b'Tri Cone 1' 0.0 -b'Tri Cone 2' 0.0 -b'Tri Cone 3' 1.0 ->>> # run the spell that fixes this ->>> spell = pyffi.spells.nif.optimize.SpellDelZeroScale(data=data) ->>> spell.recurse() -pyffi.toaster:INFO:--- opt_delzeroscale --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 0] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 1] ~~~ -pyffi.toaster:INFO: removing zero scaled branch -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 2] ~~~ -pyffi.toaster:INFO: removing zero scaled branch -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 3] ~~~ ->>> # check that zero scale nodes are gone ->>> for child in data.roots[0].children[0].children: -... if child: -... print(child.name, child.scale) -b'Tri Cone 0' 1.0 -b'Tri Cone 3' 1.0 diff --git a/tests/spells/nif/optimize/test_delzeroscale.py b/tests/spells/nif/optimize/test_delzeroscale.py new file mode 100644 index 000000000..9c914c7d5 --- /dev/null +++ b/tests/spells/nif/optimize/test_delzeroscale.py @@ -0,0 +1,43 @@ +from . import BaseFileTestCase +from nose.tools import assert_true +from tests import test_logger +import pyffi + + +class TestDelZeroScaleOptimisation(BaseFileTestCase): + """Test for the delete zero scale spell""" + + def setUp(self): + super(TestDelZeroScaleOptimisation, self).setUp() + self.src_name = "test_opt_zeroscale.nif" + super(TestDelZeroScaleOptimisation, self).copyFile() + super(TestDelZeroScaleOptimisation, self).readNifData() + + def test_zero_scale_deletion(self): + # check zero scale + children = self.data.roots[0].children[0].children + assert_true(len(children), 4) + for child in children: + test_logger.debug("{0}, {1}".format(child.name, child.scale)) + + # run the spell that fixes this + spell = pyffi.spells.nif.optimize.SpellDelZeroScale(data=self.data) + spell.recurse() + """ + pyffi.toaster:INFO:--- opt_delzeroscale --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 0] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 1] ~~~ + pyffi.toaster:INFO: removing zero scaled branch + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 2] ~~~ + pyffi.toaster:INFO: removing zero scaled branch + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 3] ~~~ + """ + + # check that zero scale nodes are gone + children = self.data.roots[0].children[0].children + for child in children: + if child: + test_logger.debug("{0}, {1}".format(child.name, child.scale)) + assert_true(len(children), 2) diff --git a/tests/test_doctests.py b/tests/test_doctests.py index aa624fafd..25d09f9db 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -103,7 +103,6 @@ def create_suite(): 'spells/nif/modify_delvertexcolor.txt', 'spells/nif/modify_substitutestringpalette.txt', 'spells/nif/opt_delunusedbones.txt', - 'spells/nif/opt_delzeroscale.txt', # Contain outstanding issues # 'spells/egm/optimize.txt', From 56c1660698b2c16aace80662d53977090646ba08 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sun, 13 Aug 2017 15:30:23 +0100 Subject: [PATCH 03/30] Refactor optimisation spell to remove unused bones --- tests/spells/nif/opt_delunusedbones.txt | 53 ------------------ .../nif/optimize/test_delunusedbones.py | 54 +++++++++++++++++++ tests/test_doctests.py | 1 - 3 files changed, 54 insertions(+), 54 deletions(-) delete mode 100644 tests/spells/nif/opt_delunusedbones.txt create mode 100644 tests/spells/nif/optimize/test_delunusedbones.py diff --git a/tests/spells/nif/opt_delunusedbones.txt b/tests/spells/nif/opt_delunusedbones.txt deleted file mode 100644 index f57796405..000000000 --- a/tests/spells/nif/opt_delunusedbones.txt +++ /dev/null @@ -1,53 +0,0 @@ -Doctests for the opt_delunusedbones spell -========================================= - -NifToaster check ----------------- - ->>> nif_dir = "tests/spells/nif/files/" ->>> filename = nif_dir + "test_opt_delunusedbones.nif" - ->>> from pyffi.formats.nif import NifFormat ->>> import pyffi.spells.nif.optimize ->>> from pyffi.spells import Toaster ->>> data = NifFormat.Data() ->>> stream = open(filename, "rb") ->>> data.read(stream) ->>> # check dummy bone ->>> print(data.roots[0].children[0].children[0].name) -b'Test' ->>> # run the spell that fixes this ->>> spell = pyffi.spells.nif.optimize.SpellDelUnusedBones(data=data) ->>> spell.recurse() -pyffi.toaster:INFO:--- opt_delunusedbones --- -pyffi.toaster:INFO: ~~~ NiNode [Bip01] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Pelvis] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Test] ~~~ -pyffi.toaster:INFO: removing unreferenced bone -pyffi.toaster:INFO: ~~~ NiNode [Dummy] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine1] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine2] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Neck] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Head] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Brain] ~~~ -pyffi.toaster:INFO: removing unreferenced bone -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Clavicle] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L UpperArm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Forearm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Clavicle] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R UpperArm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Forearm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Thigh] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Calf] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Foot] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Toe0] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Toe1] ~~~ -pyffi.toaster:INFO: removing unreferenced bone -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Thigh] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Calf] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Foot] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Toe0] ~~~ ->>> # check that dummy bone is gone ->>> print(data.roots[0].children[0].children[0]) -None diff --git a/tests/spells/nif/optimize/test_delunusedbones.py b/tests/spells/nif/optimize/test_delunusedbones.py new file mode 100644 index 000000000..28dd5a2ca --- /dev/null +++ b/tests/spells/nif/optimize/test_delunusedbones.py @@ -0,0 +1,54 @@ +from . import BaseFileTestCase +from nose.tools import assert_equals, assert_is +from pyffi.spells.nif.optimize import SpellDelUnusedBones + + +class TestDeleteUnusedBonesOptimisation(BaseFileTestCase): + """Tests for the opt_delunusedbones spell""" + + def setUp(self): + super(TestDeleteUnusedBonesOptimisation, self).setUp() + self.src_name = "test_opt_delunusedbones.nif" + super(TestDeleteUnusedBonesOptimisation, self).copyFile() + super(TestDeleteUnusedBonesOptimisation, self).readNifData() + + def test_unused_bone_deletion(self): + # check dummy bone + assert_equals(self.data.roots[0].children[0].children[0].name, b'Test') + + # run the spell that fixes this + spell = SpellDelUnusedBones(data=self.data) + spell.recurse() + """ + pyffi.toaster:INFO:--- opt_delunusedbones --- + pyffi.toaster:INFO: ~~~ NiNode [Bip01] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Pelvis] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Test] ~~~ + pyffi.toaster:INFO: removing unreferenced bone + pyffi.toaster:INFO: ~~~ NiNode [Dummy] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine1] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine2] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Neck] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Head] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Brain] ~~~ + pyffi.toaster:INFO: removing unreferenced bone + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Clavicle] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L UpperArm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Forearm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Clavicle] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R UpperArm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Forearm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Thigh] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Calf] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Foot] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Toe0] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Toe1] ~~~ + pyffi.toaster:INFO: removing unreferenced bone + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Thigh] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Calf] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Foot] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Toe0] ~~~ + """ + # check that dummy bone is gone + assert_is(self.data.roots[0].children[0].children[0], None) diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 25d09f9db..9802e0890 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -102,7 +102,6 @@ def create_suite(): 'spells/nif/modify_delbranches.txt', 'spells/nif/modify_delvertexcolor.txt', 'spells/nif/modify_substitutestringpalette.txt', - 'spells/nif/opt_delunusedbones.txt', # Contain outstanding issues # 'spells/egm/optimize.txt', From a3e92dc14b93f7a5a6735bdfb73aeccba066011f Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sun, 13 Aug 2017 15:56:01 +0100 Subject: [PATCH 04/30] Remove unused directory --- tests/spells/nif/files/out/.gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 tests/spells/nif/files/out/.gitignore diff --git a/tests/spells/nif/files/out/.gitignore b/tests/spells/nif/files/out/.gitignore deleted file mode 100644 index b722e9e13..000000000 --- a/tests/spells/nif/files/out/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore \ No newline at end of file From 3a96f9145d2752138d3633467ab175677c4de47e Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sun, 13 Aug 2017 15:58:39 +0100 Subject: [PATCH 05/30] Move base file class to util module. --- tests/spells/nif/__init__.py | 8 +--- tests/spells/nif/optimize/__init__.py | 42 ------------------- tests/spells/nif/optimize/test_collision.py | 2 +- .../nif/optimize/test_delunusedbones.py | 2 +- .../spells/nif/optimize/test_delzeroscale.py | 3 +- .../nif/optimize/test_mergeduplicates.py | 2 +- .../{test_toaster.py => test_niftoaster.py} | 22 ++++------ .../spells/nif/optimize/test_vertex_cache.py | 2 +- tests/utils/__init__.py | 38 ++++++++++++++++- 9 files changed, 53 insertions(+), 68 deletions(-) rename tests/spells/nif/optimize/{test_toaster.py => test_niftoaster.py} (78%) diff --git a/tests/spells/nif/__init__.py b/tests/spells/nif/__init__.py index 5cd5ce920..8da660db7 100644 --- a/tests/spells/nif/__init__.py +++ b/tests/spells/nif/__init__.py @@ -1,14 +1,14 @@ import imp import os.path import sys +import logging from os.path import dirname dir_path = __file__ for i in range(4): # recurse up to root repo dir dir_path = dirname(dir_path) -repo_root = dir_path -import logging +repo_root = dir_path logger = logging.getLogger(__name__) logger.info(repo_root) @@ -24,7 +24,3 @@ def call_niftoaster(*args): toaster.cli() sys.argv = oldargv return toaster - - -class TestNif(): - pass \ No newline at end of file diff --git a/tests/spells/nif/optimize/__init__.py b/tests/spells/nif/optimize/__init__.py index 344a1f420..e69de29bb 100644 --- a/tests/spells/nif/optimize/__init__.py +++ b/tests/spells/nif/optimize/__init__.py @@ -1,42 +0,0 @@ -"""Test the Optimize spell""" -import tempfile -import os -import shutil -import unittest - -from os.path import dirname - -from pyffi.formats.nif import NifFormat - -dir_path = __file__ -for i in range(4): # recurse up to root repo dir - dir_path = dirname(dir_path) -test_root = dir_path - - -class BaseFileTestCase(unittest.TestCase): - def setUp(self): - super(BaseFileTestCase, self).setUp() - # set up that everyone needs .. - self.input_files = os.path.join(test_root, 'spells', 'nif', 'files').replace("\\", "/") - self.out = tempfile.mkdtemp() - - def copyFile(self): - self.src_file = os.path.join(self.input_files, self.src_name) - self.dest_file = os.path.join(self.out, self.src_name) - shutil.copyfile(self.src_file, self.dest_file) - assert os.path.exists(self.dest_file) - - def readNifData(self): - self.data = NifFormat.Data() - stream = open(self.src_file, "rb") - self.data.read(stream) - - def tearDown(self): - shutil.rmtree(self.out) - # tear down that everyone needs .. - super(BaseFileTestCase, self).tearDown() - - - - diff --git a/tests/spells/nif/optimize/test_collision.py b/tests/spells/nif/optimize/test_collision.py index 53b039893..df701ca83 100644 --- a/tests/spells/nif/optimize/test_collision.py +++ b/tests/spells/nif/optimize/test_collision.py @@ -1,4 +1,4 @@ -from . import BaseFileTestCase +from tests.utils import BaseFileTestCase import nose import pyffi from pyffi.spells import Toaster diff --git a/tests/spells/nif/optimize/test_delunusedbones.py b/tests/spells/nif/optimize/test_delunusedbones.py index 28dd5a2ca..513ede08d 100644 --- a/tests/spells/nif/optimize/test_delunusedbones.py +++ b/tests/spells/nif/optimize/test_delunusedbones.py @@ -1,4 +1,4 @@ -from . import BaseFileTestCase +from tests.utils import BaseFileTestCase from nose.tools import assert_equals, assert_is from pyffi.spells.nif.optimize import SpellDelUnusedBones diff --git a/tests/spells/nif/optimize/test_delzeroscale.py b/tests/spells/nif/optimize/test_delzeroscale.py index 9c914c7d5..407c749b9 100644 --- a/tests/spells/nif/optimize/test_delzeroscale.py +++ b/tests/spells/nif/optimize/test_delzeroscale.py @@ -1,7 +1,8 @@ -from . import BaseFileTestCase +from tests.utils import BaseFileTestCase from nose.tools import assert_true from tests import test_logger import pyffi +from tests.utils import BaseFileTestCase class TestDelZeroScaleOptimisation(BaseFileTestCase): diff --git a/tests/spells/nif/optimize/test_mergeduplicates.py b/tests/spells/nif/optimize/test_mergeduplicates.py index af645d3d6..fc81cec5f 100644 --- a/tests/spells/nif/optimize/test_mergeduplicates.py +++ b/tests/spells/nif/optimize/test_mergeduplicates.py @@ -1,6 +1,6 @@ from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase -from . import BaseFileTestCase import pyffi from pyffi.spells import Toaster diff --git a/tests/spells/nif/optimize/test_toaster.py b/tests/spells/nif/optimize/test_niftoaster.py similarity index 78% rename from tests/spells/nif/optimize/test_toaster.py rename to tests/spells/nif/optimize/test_niftoaster.py index 5673288f0..f0aa6ba22 100644 --- a/tests/spells/nif/optimize/test_toaster.py +++ b/tests/spells/nif/optimize/test_niftoaster.py @@ -1,8 +1,5 @@ from tests.scripts.nif import call_niftoaster -import os -import shutil - -from . import BaseFileTestCase +from tests.utils import BaseFileTestCase from tests import test_logger from pyffi.spells import Toaster @@ -14,10 +11,7 @@ class TestToasterOptimisation(BaseFileTestCase): def setUp(self): super(TestToasterOptimisation, self).setUp() self.src_name = "test.nif" - self.src_file = os.path.join(self.input_files, self.src_name) - self.dest_file = os.path.join(self.out, self.src_name) - shutil.copyfile(self.src_file, self.dest_file) - assert os.path.exists(self.dest_file) + super(TestToasterOptimisation, self).copyFile() def test_non_interactive_optimisation(self): call_niftoaster("optimize", "--raise", "--noninteractive", "--verbose=1", self.dest_file) @@ -42,13 +36,13 @@ def test_non_interactive_optimisation(self): """ def test_simulate_user_optimisation(self): - Toaster.toast.__globals__['input'] = inputfunc + Toaster.toast.__globals__['input'] = input_func call_niftoaster("optimize", "--raise", "--verbose=1", self.dest_file) +inputs = ["yes it is", "n", "y"] # list of inputs of this test -inputlist = ["yes it is", "n", "y"] # list of inputs of this test -def inputfunc(self, msg=""): - result = inputlist.pop(0) - print("%s%s" % (msg, result)) - return result \ No newline at end of file +def input_func(self, msg=""): + result = inputs.pop(0) + test_logger.debug("%s%s" % (msg, result)) + return result diff --git a/tests/spells/nif/optimize/test_vertex_cache.py b/tests/spells/nif/optimize/test_vertex_cache.py index 50500009d..abe015268 100644 --- a/tests/spells/nif/optimize/test_vertex_cache.py +++ b/tests/spells/nif/optimize/test_vertex_cache.py @@ -1,4 +1,4 @@ -from . import BaseFileTestCase +from tests.utils import BaseFileTestCase from nose.tools import assert_equals import pyffi diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index c588b63ef..1ba6e957a 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -2,9 +2,45 @@ import nose import nose.tools +import tempfile +import os +import shutil +import unittest +from os.path import dirname +from pyffi.formats.nif import NifFormat def assert_tuple_values(a, b): """Wrapper func to cleanly assert tuple values""" for i, j in zip(a, b): - nose.tools.assert_almost_equal(i, j) \ No newline at end of file + nose.tools.assert_almost_equal(i, j) + +dir_path = __file__ +for i in range(2): # recurse up to root repo dir + dir_path = dirname(dir_path) +test_root = dir_path + + +class BaseFileTestCase(unittest.TestCase): + + def setUp(self): + super(BaseFileTestCase, self).setUp() + # set up that everyone needs .. + self.input_files = os.path.join(test_root, 'spells', 'nif', 'files').replace("\\", "/") + self.out = tempfile.mkdtemp() + + def copyFile(self): + self.src_file = os.path.join(self.input_files, self.src_name) + self.dest_file = os.path.join(self.out, self.src_name) + shutil.copyfile(self.src_file, self.dest_file) + assert os.path.exists(self.dest_file) + + def readNifData(self): + self.data = NifFormat.Data() + stream = open(self.src_file, "rb") + self.data.read(stream) + + def tearDown(self): + shutil.rmtree(self.out) + # tear down that everyone needs .. + super(BaseFileTestCase, self).tearDown() \ No newline at end of file From afdd255aac5af14eaa06c3e875aaa165007fddf7 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Mon, 14 Aug 2017 12:33:54 +0100 Subject: [PATCH 06/30] Migrate clamp material alpha to nose. --- tests/spells/nif/fix/__init__.py | 0 .../spells/nif/fix/test_clampmaterialalpha.py | 68 +++++++++++++++++ tests/spells/nif/fix_clampmaterialalpha.txt | 74 ------------------- tests/test_doctests.py | 1 - 4 files changed, 68 insertions(+), 75 deletions(-) create mode 100644 tests/spells/nif/fix/__init__.py create mode 100644 tests/spells/nif/fix/test_clampmaterialalpha.py delete mode 100644 tests/spells/nif/fix_clampmaterialalpha.txt diff --git a/tests/spells/nif/fix/__init__.py b/tests/spells/nif/fix/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spells/nif/fix/test_clampmaterialalpha.py b/tests/spells/nif/fix/test_clampmaterialalpha.py new file mode 100644 index 000000000..3c6dd4f71 --- /dev/null +++ b/tests/spells/nif/fix/test_clampmaterialalpha.py @@ -0,0 +1,68 @@ +"""Tests for the fix_texturepath spell""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase + +from pyffi.spells.nif.fix import SpellClampMaterialAlpha + +from nose.tools import assert_true, assert_equals + + +class TestFixTexturePathToaster(BaseFileTestCase): + """Invoke the fix_texturepath spell check through nif toaster""" + + def setUp(self): + super(TestFixTexturePathToaster, self).setUp() + self.src_name = "test_fix_clampmaterialalpha.nif" + super(TestFixTexturePathToaster, self).copyFile() + super(TestFixTexturePathToaster, self).readNifData() + assert_true(self.data.roots[0].children[0].children[0].properties[0].alpha > 1.01) + assert_true(self.data.roots[0].children[0].children[1].properties[0].alpha < -0.01) + + def test_explicit_fix_texture_path(self): + """run the spell that fixes texture path""" + + spell = SpellClampMaterialAlpha(data=self.data) + spell.recurse() + + """ + pyffi.toaster:INFO:--- fix_clampmaterialalpha --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 0] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ + pyffi.toaster:INFO: clamping alpha value (1000.000000 -> 1.0) + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 1] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Green] ~~~ + pyffi.toaster:INFO: clamping alpha value (-1000.000000 -> 0.0) + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 2] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Blue] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 3] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Yellow] ~~~ + """ + + # check that material alpha are no longer out of range + assert_equals(self.data.roots[0].children[0].children[0].properties[0].alpha, 1.0) + assert_equals(self.data.roots[0].children[0].children[1].properties[0].alpha, 0.0) + + def test_non_interactive_fix_clamp_material_alpha(self): + + call_niftoaster("--raise", "fix_clampmaterialalpha", "--dry-run", "--noninteractive", "--verbose=1", self.dest_file) + + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_clampmaterialalpha.nif === + pyffi.toaster:INFO: --- fix_clampmaterialalpha --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 0] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ + pyffi.toaster:INFO: clamping alpha value (1000.000000 -> 1.0) + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 1] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Green] ~~~ + pyffi.toaster:INFO: clamping alpha value (-1000.000000 -> 0.0) + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 2] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Blue] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 3] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Yellow] ~~~ + pyffi.toaster:INFO: writing to temporary file + pyffi.toaster:INFO:Finished. + """ diff --git a/tests/spells/nif/fix_clampmaterialalpha.txt b/tests/spells/nif/fix_clampmaterialalpha.txt deleted file mode 100644 index 8b70589e1..000000000 --- a/tests/spells/nif/fix_clampmaterialalpha.txt +++ /dev/null @@ -1,74 +0,0 @@ -Doctests for the fix_texturepath spell -====================================== - ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(4): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "nif") ->>> import sys ->>> script = os.path.join(script_dir, "niftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> nif_dir = "tests/spells/nif/files/" - - -NifToaster check ----------------- - ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "fix_clampmaterialalpha", "--dry-run", "--noninteractive", nif_dir + "test_fix_clampmaterialalpha.nif"] ->>> niftoaster.NifToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_clampmaterialalpha.nif === -pyffi.toaster:INFO: --- fix_clampmaterialalpha --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 0] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ -pyffi.toaster:INFO: clamping alpha value (1000.000000 -> 1.0) -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 1] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Green] ~~~ -pyffi.toaster:INFO: clamping alpha value (-1000.000000 -> 0.0) -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 2] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Blue] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 3] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Yellow] ~~~ -pyffi.toaster:INFO: writing to temporary file -pyffi.toaster:INFO:Finished. - -Explicit check --------------- - ->>> from pyffi.formats.nif import NifFormat ->>> from pyffi.spells.nif import fix ->>> from pyffi.spells import Toaster ->>> data = NifFormat.Data() ->>> stream = open(nif_dir + "test_fix_clampmaterialalpha.nif", "rb") ->>> data.read(stream) ->>> # check that material alpha is out of range ->>> data.roots[0].children[0].children[0].properties[0].alpha > 1.01 -True ->>> data.roots[0].children[0].children[1].properties[0].alpha < -0.01 -True ->>> # run the spell that fixes this ->>> spell = fix.SpellClampMaterialAlpha(data=data) ->>> spell.recurse() -pyffi.toaster:INFO:--- fix_clampmaterialalpha --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 0] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ -pyffi.toaster:INFO: clamping alpha value (1000.000000 -> 1.0) -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 1] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Green] ~~~ -pyffi.toaster:INFO: clamping alpha value (-1000.000000 -> 0.0) -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 2] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Blue] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 3] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Yellow] ~~~ ->>> # check that material alpha are no longer out of range ->>> "%.3f" % data.roots[0].children[0].children[0].properties[0].alpha -'1.000' ->>> "%.3f" % data.roots[0].children[0].children[1].properties[0].alpha -'0.000' diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 9802e0890..b37e0b52c 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -92,7 +92,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', 'spells/nif/ffvt3rskin.txt', - 'spells/nif/fix_clampmaterialalpha.txt', 'spells/nif/fix_cleanstringpalette.txt', 'spells/nif/fix_detachhavoktristripsdata.txt', 'spells/nif/fix_tangentspace.txt', From b779673dddda0e8d29c170edc523d5190be73ae2 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Mon, 14 Aug 2017 16:20:04 +0100 Subject: [PATCH 07/30] Migrate string palette cleanup spell to nose. --- .../spells/nif/fix/test_cleanstringpalette.py | 36 +++++++++++++++++++ tests/spells/nif/fix_cleanstringpalette.txt | 36 ------------------- tests/test_doctests.py | 1 - 3 files changed, 36 insertions(+), 37 deletions(-) create mode 100644 tests/spells/nif/fix/test_cleanstringpalette.py delete mode 100644 tests/spells/nif/fix_cleanstringpalette.txt diff --git a/tests/spells/nif/fix/test_cleanstringpalette.py b/tests/spells/nif/fix/test_cleanstringpalette.py new file mode 100644 index 000000000..20178deb7 --- /dev/null +++ b/tests/spells/nif/fix/test_cleanstringpalette.py @@ -0,0 +1,36 @@ +"""Tests for the fix_cleanstringpalette spell""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase + +from pyffi.spells.nif.fix import SpellCleanStringPalette + +from nose.tools import assert_equals + + +class TestFixTexturePathToaster(BaseFileTestCase): + """Invoke the fix_texturepath spell check through nif toaster""" + + + def setUp(self): + super(TestFixTexturePathToaster, self).setUp() + self.src_name = "test_fix_cleanstringpalette.nif" + super(TestFixTexturePathToaster, self).copyFile() + super(TestFixTexturePathToaster, self).readNifData() + + # check current string palette + strings = self.data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings() + expected = [b'Test', b'Hello', b'People', b'NiTransformController', b'Test NonAccum', b'Useless', b'Crap'] + assert_equals(strings, expected) + + def test_explicit_fix_string_palette(self): + """run the spell that fixes texture path""" + + spell = SpellCleanStringPalette(data=self.data) + spell.recurse() + + strings = self.data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings() + expected = [b'Test', b'NiTransformController', b'Test NonAccum'] + assert_equals(strings, expected) + + def test_non_interactive_fix_string_palette(self): + call_niftoaster("--raise", "fix_cleanstringpalette", "--dry-run", "--noninteractive", "--verbose=1", self.dest_file) diff --git a/tests/spells/nif/fix_cleanstringpalette.txt b/tests/spells/nif/fix_cleanstringpalette.txt deleted file mode 100644 index e00e756e6..000000000 --- a/tests/spells/nif/fix_cleanstringpalette.txt +++ /dev/null @@ -1,36 +0,0 @@ -Doctests for the fix_cleanstringpalette spell -============================================= - -NifToaster check ----------------- - ->>> from pyffi.formats.nif import NifFormat ->>> filename = "tests/spells/nif/files/test_fix_cleanstringpalette.nif" ->>> outfilename = "tests/spells/nif/files/_test_fix_cleanstringpalette.nif" ->>> # check current string palette ->>> data = NifFormat.Data() ->>> data.read(open(filename, "rb")) ->>> print(data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings()) -[b'Test', b'Hello', b'People', b'NiTransformController', b'Test NonAccum', b'Useless', b'Crap'] ->>> # clean - ->>> import sys ->>> sys.path.append("scripts/nif") ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "--prefix", "_", "--noninteractive", "fix_cleanstringpalette", filename] ->>> niftoaster.NifToaster().cli() # doctest: +REPORT_NDIFF +ELLIPSIS -pyffi.toaster:INFO:=== tests/spells/nif/files...test_fix_cleanstringpalette.nif === -pyffi.toaster:INFO: --- fix_cleanstringpalette --- -pyffi.toaster:INFO: ~~~ NiNode [TestCleanStringPalette] ~~~ -pyffi.toaster:INFO: ~~~ NiControllerManager [] ~~~ -pyffi.toaster:INFO: parsing string palette -pyffi.toaster:INFO: writing tests/spells/nif/files..._test_fix_cleanstringpalette.nif -pyffi.toaster:INFO:Finished. ->>> # check cleaned palette ->>> data = NifFormat.Data() ->>> data.read(open(outfilename, "rb")) ->>> print(data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings()) -[b'Test', b'NiTransformController', b'Test NonAccum'] ->>> # clean up ->>> import os ->>> os.remove(outfilename) diff --git a/tests/test_doctests.py b/tests/test_doctests.py index b37e0b52c..947807527 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -92,7 +92,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', 'spells/nif/ffvt3rskin.txt', - 'spells/nif/fix_cleanstringpalette.txt', 'spells/nif/fix_detachhavoktristripsdata.txt', 'spells/nif/fix_tangentspace.txt', 'spells/nif/fix_tangentspace_series_parallel.txt', From 94f35136cae435faae173b57f83c1b2e7956bf36 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Mon, 14 Aug 2017 16:36:16 +0100 Subject: [PATCH 08/30] Migrate detach havok tristripsdata spell to nose. --- .../nif/fix/test_detachhavoktristripsdata.py | 48 ++++++++++++++ .../nif/fix_detachhavoktristripsdata.txt | 63 ------------------- tests/test_doctests.py | 1 - 3 files changed, 48 insertions(+), 64 deletions(-) create mode 100644 tests/spells/nif/fix/test_detachhavoktristripsdata.py delete mode 100644 tests/spells/nif/fix_detachhavoktristripsdata.txt diff --git a/tests/spells/nif/fix/test_detachhavoktristripsdata.py b/tests/spells/nif/fix/test_detachhavoktristripsdata.py new file mode 100644 index 000000000..ec6d4533e --- /dev/null +++ b/tests/spells/nif/fix/test_detachhavoktristripsdata.py @@ -0,0 +1,48 @@ +"""Tests for the fix_detachhavoktristripsdata spell""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase + +from pyffi.spells.nif.fix import SpellDetachHavokTriStripsData + +from nose.tools import assert_equals, assert_true, assert_false + + +class TestDetachHavokTriStripsData(BaseFileTestCase): + """Invoke the fix_texturepath spell check through nif toaster""" + + def setUp(self): + super(TestDetachHavokTriStripsData, self).setUp() + self.src_name = "test_fix_detachhavoktristripsdata.nif" + super(TestDetachHavokTriStripsData, self).copyFile() + super(TestDetachHavokTriStripsData, self).readNifData() + + def test_explicit_detach_havok_tristripsdata(self): + """run the spell that detaches the trishapedata""" + + # check that data is shared + assert_true(self.data.roots[0].children[0].collision_object.body.shape.sub_shapes[0].strips_data[0] \ + is self.data.roots[0].children[0].data) + + s = SpellDetachHavokTriStripsData(data=self.data) + s.recurse() + + # check that data is no longer shared + assert_false(self.data.roots[0].children[0].collision_object.body.shape.sub_shapes[0].strips_data[0] + is self.data.roots[0].children[0].data) + + def test_non_interactive_fix_string_palette(self): + call_niftoaster("--raise", "fix_detachhavoktristripsdata", "--dry-run", "--noninteractive", "--verbose=1", + self.dest_file) + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_detachhavoktristripsdata.nif === + pyffi.toaster:INFO: --- fix_detachhavoktristripsdata --- + pyffi.toaster:INFO: ~~~ NiNode [MiddleWolfRug01] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [MiddleWolfRug01:0] ~~~ + pyffi.toaster:INFO: ~~~ bhkCollisionObject [] ~~~ + pyffi.toaster:INFO: ~~~ bhkRigidBodyT [] ~~~ + pyffi.toaster:INFO: ~~~ bhkListShape [] ~~~ + pyffi.toaster:INFO: ~~~ bhkNiTriStripsShape [] ~~~ + pyffi.toaster:INFO: detaching havok data + pyffi.toaster:INFO: writing to temporary file + pyffi.toaster:INFO:Finished. + """ diff --git a/tests/spells/nif/fix_detachhavoktristripsdata.txt b/tests/spells/nif/fix_detachhavoktristripsdata.txt deleted file mode 100644 index bd77b256d..000000000 --- a/tests/spells/nif/fix_detachhavoktristripsdata.txt +++ /dev/null @@ -1,63 +0,0 @@ -Doctests for the fix_detachhavoktristripsdata spell -=================================================== - - ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(4): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "nif") ->>> import sys ->>> script = os.path.join(script_dir, "niftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> nif_dir = "tests/spells/nif/files/" - - -NifToaster check ----------------- - ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "fix_detachhavoktristripsdata", "--dry-run", "--noninteractive", nif_dir + "test_fix_detachhavoktristripsdata.nif"] ->>> niftoaster.NifToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_detachhavoktristripsdata.nif === -pyffi.toaster:INFO: --- fix_detachhavoktristripsdata --- -pyffi.toaster:INFO: ~~~ NiNode [MiddleWolfRug01] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [MiddleWolfRug01:0] ~~~ -pyffi.toaster:INFO: ~~~ bhkCollisionObject [] ~~~ -pyffi.toaster:INFO: ~~~ bhkRigidBodyT [] ~~~ -pyffi.toaster:INFO: ~~~ bhkListShape [] ~~~ -pyffi.toaster:INFO: ~~~ bhkNiTriStripsShape [] ~~~ -pyffi.toaster:INFO: detaching havok data -pyffi.toaster:INFO: writing to temporary file -pyffi.toaster:INFO:Finished. - - -Explicit check --------------- - ->>> from pyffi.formats.nif import NifFormat ->>> from pyffi.spells.nif import fix ->>> from pyffi.spells import Toaster ->>> data = NifFormat.Data() ->>> stream = open(nif_dir + "test_fix_detachhavoktristripsdata.nif", "rb") ->>> data.read(stream) ->>> # check that data is shared ->>> data.roots[0].children[0].collision_object.body.shape.sub_shapes[0].strips_data[0] is data.roots[0].children[0].data -True ->>> # run the spell that fixes this ->>> spell = fix.SpellDetachHavokTriStripsData(data=data) ->>> spell.recurse() -pyffi.toaster:INFO:--- fix_detachhavoktristripsdata --- -pyffi.toaster:INFO: ~~~ NiNode [MiddleWolfRug01] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [MiddleWolfRug01:0] ~~~ -pyffi.toaster:INFO: ~~~ bhkCollisionObject [] ~~~ -pyffi.toaster:INFO: ~~~ bhkRigidBodyT [] ~~~ -pyffi.toaster:INFO: ~~~ bhkListShape [] ~~~ -pyffi.toaster:INFO: ~~~ bhkNiTriStripsShape [] ~~~ -pyffi.toaster:INFO: detaching havok data ->>> # check that data is no longer shared ->>> data.roots[0].children[0].collision_object.body.shape.sub_shapes[0].strips_data[0] is data.roots[0].children[0].data -False - diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 947807527..329fc32f4 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -92,7 +92,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', 'spells/nif/ffvt3rskin.txt', - 'spells/nif/fix_detachhavoktristripsdata.txt', 'spells/nif/fix_tangentspace.txt', 'spells/nif/fix_tangentspace_series_parallel.txt', 'spells/nif/fix_texturepath.txt', From 1f55b5098031db3d96a775f8777b25378c83f77d Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Mon, 14 Aug 2017 16:37:01 +0100 Subject: [PATCH 09/30] Migrate detach havok tristripsdata spell to nose. --- tests/spells/nif/fix/test_detachhavoktristripsdata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/spells/nif/fix/test_detachhavoktristripsdata.py b/tests/spells/nif/fix/test_detachhavoktristripsdata.py index ec6d4533e..c078692c2 100644 --- a/tests/spells/nif/fix/test_detachhavoktristripsdata.py +++ b/tests/spells/nif/fix/test_detachhavoktristripsdata.py @@ -8,7 +8,7 @@ class TestDetachHavokTriStripsData(BaseFileTestCase): - """Invoke the fix_texturepath spell check through nif toaster""" + """Invoke the fix_detachhavoktristripsdata spell check through nif toaster""" def setUp(self): super(TestDetachHavokTriStripsData, self).setUp() From 9b2269f4d59dd07ce66fe5d29b791b3ddc5e9e10 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Mon, 14 Aug 2017 19:25:43 +0100 Subject: [PATCH 10/30] Apply some more formatting changes --- pyffi/formats/nif/__init__.py | 2 +- pyffi/object_models/xml/array.py | 82 +++++++++---------- .../nif/fix_tangentspace_series_parallel.txt | 45 ---------- tests/spells/nif/optimize/test_collision.py | 1 + .../spells/nif/optimize/test_delzeroscale.py | 4 +- tests/utils/__init__.py | 2 +- 6 files changed, 46 insertions(+), 90 deletions(-) delete mode 100644 tests/spells/nif/fix_tangentspace_series_parallel.txt diff --git a/pyffi/formats/nif/__init__.py b/pyffi/formats/nif/__init__.py index d3e75c27c..16f7ffc3c 100644 --- a/pyffi/formats/nif/__init__.py +++ b/pyffi/formats/nif/__init__.py @@ -2128,7 +2128,7 @@ def __eq__(self, x): if isinstance(x, type(None)): return False if not isinstance(x, NifFormat.Vector3): - raise TypeError("do not know how to compare Vector3 and %s"%x.__class__) + raise TypeError("do not know how to compare Vector3 and %s" % x.__class__) if abs(self.x - x.x) > NifFormat.EPSILON: return False if abs(self.y - x.y) > NifFormat.EPSILON: return False if abs(self.z - x.z) > NifFormat.EPSILON: return False diff --git a/pyffi/object_models/xml/array.py b/pyffi/object_models/xml/array.py index 2a96b1db6..74a0cbb7d 100644 --- a/pyffi/object_models/xml/array.py +++ b/pyffi/object_models/xml/array.py @@ -45,11 +45,12 @@ from pyffi.utils.graph import DetailNode, EdgeFilter + class _ListWrap(list, DetailNode): """A wrapper for list, which uses get_value and set_value for getting and setting items of the basic type.""" - def __init__(self, element_type, parent = None): + def __init__(self, element_type, parent=None): self._parent = weakref.ref(parent) if parent else None self._elementType = element_type # we link to the unbound methods (that is, self.__class__.xxx @@ -119,20 +120,21 @@ def get_detail_child_names(self, edge_filter=EdgeFilter()): """Yield child names.""" return ("[%i]" % row for row in range(list.__len__(self))) + class Array(_ListWrap): """A general purpose class for 1 or 2 dimensional arrays consisting of either BasicBase or StructBase elements.""" logger = logging.getLogger("pyffi.nif.data.array") - arg = None # default argument + arg = None # default argument def __init__( - self, - element_type = None, - element_type_template = None, - element_type_argument = None, - count1 = None, count2 = None, - parent = None): + self, + element_type=None, + element_type_template=None, + element_type_argument=None, + count1=None, count2=None, + parent=None): """Initialize the array type. :param element_type: The class describing the type of each element. @@ -147,10 +149,10 @@ def __init__( array is an attribute of.""" if count2 is None: _ListWrap.__init__(self, - element_type = element_type, parent = parent) + element_type=element_type, parent=parent) else: _ListWrap.__init__(self, - element_type = _ListWrap, parent = parent) + element_type=_ListWrap, parent=parent) self._elementType = element_type self._parent = weakref.ref(parent) if parent else None self._elementTypeTemplate = element_type_template @@ -161,32 +163,30 @@ def __init__( if self._count2 is None: for i in range(self._len1()): elem_instance = self._elementType( - template = self._elementTypeTemplate, - argument = self._elementTypeArgument, - parent = self) + template=self._elementTypeTemplate, + argument=self._elementTypeArgument, + parent=self) self.append(elem_instance) else: for i in range(self._len1()): - elem = _ListWrap(element_type = element_type, parent = self) + elem = _ListWrap(element_type=element_type, parent=self) for j in range(self._len2(i)): elem_instance = self._elementType( - template = self._elementTypeTemplate, - argument = self._elementTypeArgument, - parent = elem) + template=self._elementTypeTemplate, + argument=self._elementTypeArgument, + parent=elem) elem.append(elem_instance) self.append(elem) def _len1(self): - """The length the array should have, obtained by evaluating - the count1 expression.""" + """The length the array should have, obtained by evaluating the count1 expression.""" if self._parent is None: return self._count1.eval() else: return self._count1.eval(self._parent()) def _len2(self, index1): - """The length the array should have, obtained by evaluating - the count2 expression.""" + """The length the array should have, obtained by evaluating the count2 expression.""" if self._count2 is None: raise ValueError('single array treated as double array (bug?)') if self._parent is None: @@ -199,8 +199,7 @@ def _len2(self, index1): return expr[index1] def deepcopy(self, block): - """Copy attributes from a given array which needs to have at least as - many elements (possibly more) as self.""" + """Copy attributes from a given array which needs to have at least as many elements (possibly more) as self.""" if self._count2 is None: for i in range(self._len1()): attrvalue = self[i] @@ -259,16 +258,16 @@ def update_size(self): if new_size < old_size: del self[new_size:old_size] else: - for i in range(new_size-old_size): + for i in range(new_size - old_size): elem = self._elementType( - template = self._elementTypeTemplate, - argument = self._elementTypeArgument) + template=self._elementTypeTemplate, + argument=self._elementTypeArgument) self.append(elem) else: if new_size < old_size: del self[new_size:old_size] else: - for i in range(new_size-old_size): + for i in range(new_size - old_size): self.append(_ListWrap(self._elementType)) for i, elemlist in enumerate(list.__iter__(self)): old_size_i = len(elemlist) @@ -276,10 +275,10 @@ def update_size(self): if new_size_i < old_size_i: del elemlist[new_size_i:old_size_i] else: - for j in range(new_size_i-old_size_i): + for j in range(new_size_i - old_size_i): elem = self._elementType( - template = self._elementTypeTemplate, - argument = self._elementTypeArgument) + template=self._elementTypeTemplate, + argument=self._elementTypeArgument) elemlist.append(elem) def read(self, stream, data): @@ -298,9 +297,9 @@ def read(self, stream, data): if self._count2 is None: for i in range(len1): elem = self._elementType( - template = self._elementTypeTemplate, - argument = self._elementTypeArgument, - parent = self) + template=self._elementTypeTemplate, + argument=self._elementTypeArgument, + parent=self) elem.read(stream, data) self.append(elem) else: @@ -308,12 +307,12 @@ def read(self, stream, data): len2i = self._len2(i) if len2i > 0x10000000: raise ValueError('array too long (%i)' % len2i) - elemlist = _ListWrap(self._elementType, parent = self) + elemlist = _ListWrap(self._elementType, parent=self) for j in range(len2i): elem = self._elementType( - template = self._elementTypeTemplate, - argument = self._elementTypeArgument, - parent = elemlist) + template=self._elementTypeTemplate, + argument=self._elementTypeArgument, + parent=elemlist) elem.read(stream, data) elemlist.append(elem) self.append(elemlist) @@ -323,8 +322,8 @@ def write(self, stream, data): self._elementTypeArgument = self.arg len1 = self._len1() if len1 != self.__len__(): - raise ValueError('array size (%i) different from to field \ -describing number of elements (%i)'%(self.__len__(),len1)) + raise ValueError('array size (%i) different from to field describing number of elements (%i)' % + (self.__len__(), len1)) if len1 > 0x10000000: raise ValueError('array too long (%i)' % len1) if self._count2 is None: @@ -334,8 +333,8 @@ def write(self, stream, data): for i, elemlist in enumerate(list.__iter__(self)): len2i = self._len2(i) if len2i != elemlist.__len__(): - raise ValueError("array size (%i) different from to field \ -describing number of elements (%i)"%(elemlist.__len__(),len2i)) + raise ValueError("array size (%i) different from to field describing number of elements (%i)" % + (elemlist.__len__(), len2i)) if len2i > 0x10000000: raise ValueError('array too long (%i)' % len2i) for elem in list.__iter__(elemlist): @@ -406,5 +405,6 @@ def _elementList(self, **kwargs): for elem in list.__iter__(elemlist): yield elem + from pyffi.object_models.xml.basic import BasicBase from pyffi.object_models.xml.struct_ import StructBase diff --git a/tests/spells/nif/fix_tangentspace_series_parallel.txt b/tests/spells/nif/fix_tangentspace_series_parallel.txt deleted file mode 100644 index 96858b80b..000000000 --- a/tests/spells/nif/fix_tangentspace_series_parallel.txt +++ /dev/null @@ -1,45 +0,0 @@ -Doctests for the tangentspace spells, and running spells in parallel and series -=============================================================================== - - ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(4): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "nif") ->>> import sys ->>> script = os.path.join(script_dir, "niftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> nif_dir = "tests/spells/nif/files/" - - ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "fix_deltangentspace", "fix_addtangentspace", "--dry-run", "--noninteractive", nif_dir + "test_fix_tangentspace.nif"] ->>> niftoaster.NifToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_tangentspace.nif === -pyffi.toaster:INFO: --- fix_deltangentspace & fix_addtangentspace --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Sphere] ~~~ -pyffi.toaster:INFO: removing tangent space block -pyffi.toaster:INFO: adding tangent space -pyffi.toaster:INFO: writing to temporary file -pyffi.toaster:INFO:Finished. - - ->>> # now run the spells in series ->>> sys.argv = ["niftoaster.py", "fix_deltangentspace", "fix_addtangentspace", "--series", "--dry-run", "--noninteractive", nif_dir + "test_fix_tangentspace.nif"] ->>> niftoaster.NifToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_tangentspace.nif === -pyffi.toaster:INFO: --- fix_deltangentspace --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Sphere] ~~~ -pyffi.toaster:INFO: removing tangent space block -pyffi.toaster:INFO: --- fix_addtangentspace --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Sphere] ~~~ -pyffi.toaster:INFO: adding tangent space -pyffi.toaster:INFO: writing to temporary file -pyffi.toaster:INFO:Finished. - diff --git a/tests/spells/nif/optimize/test_collision.py b/tests/spells/nif/optimize/test_collision.py index df701ca83..2c554a990 100644 --- a/tests/spells/nif/optimize/test_collision.py +++ b/tests/spells/nif/optimize/test_collision.py @@ -273,6 +273,7 @@ def test_optimise_collision_unpacked(self): nose.tools.assert_equals(shape.data.num_vertices, 8) nose.tools.assert_equals(shape.data.num_triangles, 12) + class TestPackedCollisionOptimisation(BaseFileTestCase): def setUp(self): diff --git a/tests/spells/nif/optimize/test_delzeroscale.py b/tests/spells/nif/optimize/test_delzeroscale.py index 407c749b9..d8c2a6994 100644 --- a/tests/spells/nif/optimize/test_delzeroscale.py +++ b/tests/spells/nif/optimize/test_delzeroscale.py @@ -3,7 +3,7 @@ from tests import test_logger import pyffi from tests.utils import BaseFileTestCase - +from pyffi.spells.nif.optimize import SpellDelZeroScale class TestDelZeroScaleOptimisation(BaseFileTestCase): """Test for the delete zero scale spell""" @@ -22,7 +22,7 @@ def test_zero_scale_deletion(self): test_logger.debug("{0}, {1}".format(child.name, child.scale)) # run the spell that fixes this - spell = pyffi.spells.nif.optimize.SpellDelZeroScale(data=self.data) + spell = SpellDelZeroScale(data=self.data) spell.recurse() """ pyffi.toaster:INFO:--- opt_delzeroscale --- diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index 1ba6e957a..261dfc0c4 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -13,7 +13,7 @@ def assert_tuple_values(a, b): """Wrapper func to cleanly assert tuple values""" for i, j in zip(a, b): - nose.tools.assert_almost_equal(i, j) + nose.tools.assert_almost_equal(i, j, places=3) dir_path = __file__ for i in range(2): # recurse up to root repo dir From 7146fc4a186e4bd03830e7abb61e39ea44352e36 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Mon, 14 Aug 2017 19:32:38 +0100 Subject: [PATCH 11/30] Migrate tangent space fix spell tests to nose --- tests/spells/nif/fix/test_tangentspace.py | 1552 +++++++++++++++++++++ tests/spells/nif/fix_tangentspace.txt | 1499 -------------------- tests/test_doctests.py | 2 - 3 files changed, 1552 insertions(+), 1501 deletions(-) create mode 100644 tests/spells/nif/fix/test_tangentspace.py delete mode 100644 tests/spells/nif/fix_tangentspace.txt diff --git a/tests/spells/nif/fix/test_tangentspace.py b/tests/spells/nif/fix/test_tangentspace.py new file mode 100644 index 000000000..8b87da45f --- /dev/null +++ b/tests/spells/nif/fix/test_tangentspace.py @@ -0,0 +1,1552 @@ +"""Regression test for tangent space algorithm""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase, assert_tuple_values + +from pyffi.spells.nif.fix import SpellAddTangentSpace + + +class TestFixTangentSpace(BaseFileTestCase): + """Invoke the fix_texturepath spell check through nif toaster""" + + def setUp(self): + super(TestFixTangentSpace, self).setUp() + self.src_name = "test_skincenterradius.nif" + super(TestFixTangentSpace, self).copyFile() + super(TestFixTangentSpace, self).readNifData() + + def test_explicit_fix_tangent_space(self): + """run the spell that generates normals""" + + spell = SpellAddTangentSpace(data=self.data) + spell.recurse() + + tangents = self.data.roots[0].children[1].data.tangents + + expected = [[-0.175, 0.967, 0.183], + [-0.367, 0.930, 0.000], + [-0.178, 0.918, 0.354], + [0.020, 0.994, 0.111], + [-0.992, 0.122, 0.035], + [-1.000, 0.028, 0.009], + [-0.363, -0.931, 0.039], + [-0.140, -0.990, 0.006], + [-0.239, -0.921, -0.306], + [-0.040, -0.997, -0.072], + [-0.992, 0.122, 0.035], + [-1.000, 0.028, 0.009], + [0.067, 0.997, 0.037], + [0.219, 0.975, 0.025], + [0.109, 0.993, -0.038], + [0.000, 0.961, 0.276], + [0.999, -0.034, 0.000], + [-0.492, 0.759, 0.428], + [-1.000, 0.015, 0.005], + [0.596, 0.274, 0.754], + [-0.690, 0.717, -0.094], + [0.915, -0.363, -0.177], + [0.640, -0.187, -0.745], + [-0.690, 0.717, -0.094], + [-0.960, 0.155, -0.231], + [-0.714, 0.653, 0.254], + [-0.714, 0.653, 0.254], + [0.141, 0.988, -0.069], + [-0.492, 0.759, 0.428], + [0.915, -0.363, -0.177], + [-0.690, 0.717, -0.094], + [0.069, 0.997, 0.030], + [0.014, 0.996, 0.093], + [-0.235, 0.972, 0.029], + [0.283, 0.949, -0.140], + [0.517, 0.820, -0.247], + [0.944, -0.234, 0.234], + [-0.271, 0.959, 0.085], + [0.498, -0.370, 0.784], + [0.476, -0.404, 0.781], + [0.944, -0.234, 0.234], + [0.517, 0.820, -0.247], + [-0.791, 0.230, 0.568], + [-0.714, 0.653, 0.254], + [0.915, -0.363, -0.177], + [0.136, 0.987, 0.083], + [0.336, 0.941, 0.049], + [1.000, -0.031, 0.005], + [0.187, 0.982, 0.013], + [0.160, 0.983, -0.089], + [1.000, -0.031, 0.005], + [1.000, -0.031, 0.005], + [0.233, -0.788, -0.570], + [0.007, -1.000, 0.004], + [0.048, -0.997, 0.068], + [-0.064, -0.965, -0.256], + [0.999, -0.034, 0.000], + [-0.572, -0.732, -0.370], + [-1.000, 0.015, 0.005], + [-0.643, -0.691, -0.331], + [0.640, -0.187, -0.745], + [0.915, -0.363, -0.177], + [-0.978, -0.146, -0.147], + [-0.643, -0.691, -0.331], + [-0.727, -0.644, -0.240], + [-0.727, -0.644, -0.240], + [0.081, -0.991, 0.109], + [0.915, -0.363, -0.177], + [-0.572, -0.732, -0.370], + [-0.040, -0.998, -0.044], + [0.020, -1.000, 0.023], + [-0.233, -0.973, 0.010], + [0.283, 0.949, -0.140], + [0.460, -0.842, 0.282], + [0.460, -0.842, 0.282], + [-0.277, -0.960, -0.038], + [0.460, -0.842, 0.282], + [0.915, -0.363, -0.177], + [-0.212, -0.656, -0.724], + [0.315, -0.885, -0.344], + [1.000, -0.031, 0.005], + [0.175, -0.984, 0.040], + [0.102, -0.986, 0.132], + [1.000, -0.031, 0.005], + [1.000, -0.031, 0.005], + [-0.084, 0.992, -0.092], + [-0.072, 0.988, -0.136], + [-0.156, 0.975, -0.157], + [-0.367, 0.930, 0.000], + [-0.029, 1.000, 0.004], + [-1.000, 0.016, -0.001], + [-1.000, 0.028, 0.000], + [-0.098, -0.988, 0.122], + [-0.098, -0.992, 0.081], + [-0.167, -0.975, 0.146], + [-0.363, -0.931, 0.039], + [-0.140, -0.990, 0.006], + [-1.000, 0.028, 0.000], + [-1.000, 0.016, -0.001], + [0.977, 0.122, -0.173], + [0.151, -0.978, -0.142], + [0.995, 0.055, 0.077], + [0.353, 0.931, 0.087], + [0.995, 0.055, 0.077], + [0.151, -0.978, -0.142], + [1.000, -0.016, -0.003], + [0.106, 0.980, 0.167], + [0.387, -0.889, -0.246], + [1.000, -0.016, -0.003], + [0.084, -0.980, -0.181], + [-0.270, -0.931, -0.246], + [0.995, 0.055, 0.077], + [0.977, 0.122, -0.173], + [0.239, -0.737, 0.632], + [0.379, 0.646, 0.663], + [-0.270, -0.931, -0.246], + [0.379, 0.646, 0.663], + [-0.270, -0.931, -0.246], + [-0.831, 0.538, 0.143], + [0.995, 0.055, 0.077], + [0.379, 0.646, 0.663], + [0.977, 0.122, -0.173], + [0.152, 0.986, 0.072], + [-0.245, 0.945, -0.217], + [-0.060, 0.998, -0.022], + [-0.918, -0.246, 0.311], + [-0.270, -0.931, -0.246], + [0.379, 0.646, 0.663], + [0.995, 0.055, 0.077], + [-0.186, 0.972, -0.145], + [-0.707, -0.506, 0.494], + [0.219, 0.975, 0.025], + [0.336, 0.941, 0.049], + [0.635, 0.768, -0.082], + [0.965, 0.169, -0.199], + [0.965, 0.169, -0.199], + [-0.270, -0.931, -0.246], + [0.995, 0.055, 0.077], + [0.965, 0.169, -0.199], + [0.239, -0.737, 0.632], + [-0.270, -0.931, -0.246], + [0.635, 0.768, -0.082], + [-0.918, -0.246, 0.311], + [0.392, -0.810, 0.435], + [0.654, -0.689, 0.311], + [-0.707, -0.506, 0.494], + [0.635, 0.768, -0.082], + [0.995, 0.055, 0.077], + [0.353, 0.931, 0.087], + [-0.899, -0.283, 0.336], + [-0.747, 0.626, -0.222], + [0.654, -0.689, 0.311], + [0.941, -0.337, 0.019], + [-0.270, -0.931, -0.246], + [-0.747, 0.558, 0.361], + [-0.899, -0.283, 0.336], + [-0.690, 0.717, -0.094], + [0.596, 0.274, 0.754], + [-0.747, 0.626, -0.222], + [-0.747, 0.626, -0.222], + [-0.690, 0.717, -0.094], + [-0.747, 0.626, -0.222], + [-0.872, 0.470, -0.139], + [0.136, 0.987, 0.083], + [-0.235, 0.972, 0.029], + [-0.003, 1.000, -0.006], + [-0.271, 0.959, 0.085], + [-0.872, 0.470, -0.139], + [-0.960, 0.155, -0.231], + [0.995, 0.055, 0.077], + [0.187, 0.982, 0.013], + [0.872, 0.449, 0.195], + [0.134, 0.904, 0.405], + [1.000, -0.005, -0.002], + [-0.661, -0.498, -0.561], + [-0.189, -0.408, -0.893], + [-0.461, -0.451, -0.764], + [0.399, 0.907, 0.132], + [0.399, 0.907, 0.132], + [-0.990, -0.112, -0.081], + [-0.641, -0.460, -0.614], + [-0.976, -0.092, -0.199], + [-0.990, -0.112, -0.081], + [-0.661, -0.498, -0.561], + [0.233, -0.788, -0.570], + [0.315, -0.885, -0.344], + [-0.108, -0.598, -0.794], + [0.977, 0.122, -0.173], + [0.399, 0.907, 0.132], + [-0.270, -0.931, -0.246], + [0.399, 0.907, 0.132], + [-0.824, -0.426, -0.374], + [-0.976, -0.092, -0.199], + [0.892, -0.324, -0.314], + [0.399, 0.907, 0.132], + [-0.824, -0.426, -0.374], + [0.892, -0.324, -0.314], + [-0.831, 0.538, 0.143], + [-0.824, -0.426, -0.374], + [0.399, 0.907, 0.132], + [-0.824, -0.426, -0.374], + [-0.108, -0.598, -0.794], + [0.892, -0.324, -0.314], + [-0.831, 0.538, 0.143], + [1.000, -0.005, -0.002], + [0.213, -0.816, -0.537], + [-0.791, 0.230, 0.568], + [0.392, -0.810, 0.435], + [-0.839, -0.529, 0.129], + [-0.990, -0.112, -0.081], + [0.654, -0.689, 0.311], + [0.654, -0.689, 0.311], + [0.892, -0.324, -0.314], + [-0.108, -0.598, -0.794], + [0.387, -0.889, -0.246], + [0.941, -0.337, 0.019], + [0.977, 0.122, -0.173], + [-0.976, -0.092, -0.199], + [-0.839, -0.529, 0.129], + [0.941, -0.337, 0.019], + [0.387, -0.889, -0.246], + [-0.108, -0.598, -0.794], + [0.315, -0.885, -0.344], + [0.387, -0.889, -0.246], + [-0.899, -0.283, 0.336], + [-0.747, 0.558, 0.361], + [-0.823, -0.290, -0.489], + [-0.594, -0.015, -0.804], + [-0.643, -0.691, -0.331], + [0.640, -0.187, -0.745], + [-0.839, -0.529, 0.129], + [-0.823, -0.290, -0.489], + [-0.643, -0.691, -0.331], + [-0.839, -0.529, 0.129], + [-0.971, -0.196, -0.137], + [-0.212, -0.656, -0.724], + [-0.899, -0.283, 0.336], + [-0.233, -0.973, 0.010], + [-0.028, -1.000, -0.008], + [-0.277, -0.960, -0.038], + [0.392, -0.810, 0.435], + [-0.990, -0.112, -0.081], + [0.654, -0.689, 0.311], + [-0.971, -0.196, -0.137], + [-0.643, -0.691, -0.331], + [-0.978, -0.146, -0.147], + [-0.971, -0.196, -0.137], + [0.315, -0.885, -0.344], + [0.175, -0.984, 0.040], + [0.872, 0.449, 0.195], + [0.213, -0.816, -0.537], + [1.000, -0.005, -0.002], + [0.872, 0.449, 0.195], + [0.213, -0.816, -0.537], + [-0.226, -0.973, -0.035], + [-0.296, -0.950, -0.100], + [-0.999, 0.028, -0.021], + [-0.997, 0.066, 0.026], + [-0.999, 0.028, -0.021], + [-0.997, 0.066, 0.026], + [-0.087, 0.994, 0.065], + [-0.123, 0.989, 0.087], + [0.058, -0.998, 0.018], + [-0.159, -0.986, -0.046], + [-0.356, -0.908, -0.223], + [-0.356, -0.908, -0.223], + [-0.067, 0.994, 0.084], + [0.040, 0.999, 0.014], + [-0.087, 0.994, 0.065], + [-0.123, 0.989, 0.087], + [-0.019, 1.000, 0.014], + [-0.033, 0.999, 0.005], + [-0.998, 0.017, 0.058], + [-1.000, 0.009, 0.013], + [-0.998, 0.017, 0.058], + [-1.000, 0.009, 0.013], + [-0.051, -0.998, 0.048], + [-0.095, -0.992, 0.078], + [-0.226, -0.973, -0.035], + [-0.296, -0.950, -0.100], + [0.040, 0.999, 0.014], + [0.014, 0.999, 0.037], + [0.090, 0.994, 0.062], + [0.058, -0.998, 0.018], + [0.025, -0.999, -0.029], + [0.090, 0.994, 0.062], + [-0.271, 0.953, 0.137], + [-0.200, 0.976, 0.086], + [-0.999, -0.033, 0.018], + [-0.997, -0.075, -0.030], + [-0.997, -0.075, -0.030], + [-0.999, -0.033, 0.018], + [-0.103, -0.993, -0.052], + [-0.146, -0.987, -0.068], + [-0.200, 0.976, 0.086], + [0.039, 0.998, 0.055], + [-0.118, 0.987, 0.108], + [-0.118, 0.987, 0.108], + [-0.314, 0.920, 0.233], + [-0.314, 0.920, 0.233], + [-0.045, -0.993, -0.107], + [0.042, -0.999, 0.012], + [-0.146, -0.987, -0.068], + [-0.103, -0.993, -0.052], + [-0.007, -0.999, 0.054], + [-0.004, -0.999, 0.050], + [-0.990, -0.137, -0.019], + [-0.110, 0.993, -0.041], + [-0.990, -0.137, -0.019], + [-0.072, 0.997, -0.011], + [-0.271, 0.953, 0.137], + [0.042, -0.999, 0.012], + [0.046, -0.999, 0.022], + [0.075, -0.997, -0.007], + [-0.013, 1.000, 0.022], + [0.075, -0.997, -0.007], + [0.077, 0.997, 0.005], + [0.078, 0.994, 0.081], + [0.996, -0.077, 0.054], + [0.996, -0.077, 0.054], + [0.015, -1.000, -0.005], + [-0.008, -0.999, 0.040], + [-0.008, -0.999, 0.040], + [0.949, 0.315, 0.004], + [0.949, 0.315, 0.004], + [0.077, 0.997, 0.005], + [0.207, 0.978, -0.036], + [0.069, 0.994, 0.084], + [0.998, -0.050, 0.044], + [0.998, -0.050, 0.044], + [0.079, -0.994, -0.074], + [0.177, -0.984, 0.012], + [0.177, -0.984, 0.012], + [0.106, -0.976, 0.188], + [0.992, -0.044, 0.119], + [0.992, -0.044, 0.119], + [0.207, 0.978, -0.036], + [0.038, 0.999, 0.015], + [0.703, 0.711, -0.015], + [-0.011, 1.000, 0.016], + [-0.914, -0.144, 0.380], + [-0.124, -0.991, 0.049], + [-0.124, -0.991, 0.049], + [-0.914, -0.144, 0.380], + [-0.062, -0.995, 0.082], + [-0.100, -0.987, 0.129], + [-0.068, -0.997, 0.036], + [-0.058, -0.998, 0.031], + [-0.068, -0.997, 0.036], + [-0.058, -0.998, 0.031], + [-0.027, -0.999, 0.031], + [-0.023, -0.999, 0.041], + [0.118, -0.990, 0.080], + [0.176, 0.982, -0.064], + [0.118, -0.990, 0.080], + [0.176, 0.982, -0.064], + [0.049, 0.998, -0.025], + [0.017, 1.000, -0.007], + [0.038, 0.999, 0.015], + [0.703, 0.711, -0.015], + [0.049, 0.999, 0.015], + [0.025, 0.999, 0.047], + [0.998, -0.001, -0.058], + [0.998, -0.001, -0.058], + [0.054, -0.997, -0.063], + [0.112, -0.993, 0.042], + [0.112, -0.993, 0.042], + [0.025, -0.993, 0.115], + [0.436, 0.899, 0.049], + [0.436, 0.899, 0.049], + [0.049, 0.999, 0.015], + [0.069, -0.997, 0.019], + [0.113, -0.993, -0.030], + [0.995, 0.087, -0.054], + [0.995, 0.087, -0.054], + [-0.008, 0.999, 0.036], + [0.004, 1.000, -0.002], + [0.004, 1.000, -0.002], + [0.997, -0.082, -0.012], + [0.997, -0.082, -0.012], + [0.069, -0.997, 0.019], + [0.200, -0.978, 0.061], + [0.106, -0.994, -0.039], + [0.997, 0.062, -0.043], + [0.997, 0.062, -0.043], + [0.058, 0.994, 0.096], + [0.172, 0.985, 0.029], + [0.119, 0.977, -0.175], + [0.172, 0.985, 0.029], + [0.991, 0.053, -0.122], + [0.991, 0.053, -0.122], + [0.200, -0.978, 0.061], + [0.703, 0.711, -0.015], + [0.177, -0.984, 0.005], + [0.060, -0.998, -0.005], + [-0.005, -0.998, 0.059], + [-0.980, -0.089, -0.179], + [0.617, -0.764, 0.189], + [0.617, -0.764, 0.189], + [-0.980, -0.089, -0.179], + [0.019, 0.990, -0.137], + [0.140, 0.945, -0.295], + [0.617, -0.764, 0.189], + [0.019, 0.990, -0.137], + [0.140, 0.945, -0.295], + [-0.063, 0.998, 0.002], + [-0.044, 0.999, -0.004], + [-0.044, 0.999, -0.004], + [-0.063, 0.998, 0.002], + [-0.016, 1.000, -0.026], + [-0.011, 0.999, -0.036], + [0.199, 0.977, -0.080], + [0.227, -0.973, 0.042], + [0.227, -0.973, 0.042], + [0.199, 0.977, -0.080], + [0.063, -0.998, -0.000], + [0.133, -0.990, 0.044], + [0.177, -0.984, 0.005], + [0.703, 0.711, -0.015], + [0.048, -0.999, 0.010], + [0.063, -0.998, -0.006], + [0.998, 0.023, 0.060], + [0.998, 0.023, 0.060], + [0.035, 0.996, 0.079], + [0.113, 0.994, -0.003], + [0.113, 0.994, -0.003], + [0.037, 0.994, -0.107], + [0.521, -0.849, -0.092], + [0.521, -0.849, -0.092], + [0.048, -0.999, 0.010], + [-0.584, 0.689, 0.429], + [-0.273, 0.957, -0.098], + [-0.424, 0.166, 0.890], + [0.315, 0.750, 0.581], + [0.494, 0.393, 0.775], + [-0.584, 0.689, 0.429], + [0.315, 0.750, 0.581], + [-0.219, -0.852, 0.476], + [0.660, 0.348, 0.666], + [0.660, 0.348, 0.666], + [-0.244, -0.938, 0.245], + [-0.219, -0.852, 0.476], + [-0.266, -0.960, -0.084], + [-0.109, -0.988, -0.105], + [0.029, -0.996, -0.078], + [-0.273, 0.957, -0.098], + [0.121, 0.989, 0.087], + [0.081, 0.992, -0.097], + [0.067, 0.992, -0.107], + [1.000, -0.019, -0.014], + [0.131, -0.983, 0.126], + [0.131, -0.983, 0.126], + [1.000, -0.019, -0.014], + [0.091, -0.995, 0.045], + [0.082, -0.991, 0.109], + [-0.244, -0.938, 0.245], + [0.130, 0.990, 0.051], + [0.940, -0.325, 0.105], + [0.940, -0.325, 0.105], + [0.146, -0.988, -0.053], + [0.006, 0.990, 0.140], + [-0.157, 0.988, 0.005], + [-0.157, 0.988, 0.005], + [0.029, -0.996, -0.078], + [0.146, -0.988, -0.053], + [0.029, -0.996, -0.078], + [-0.109, -0.988, -0.105], + [-0.266, -0.960, -0.084], + [-0.356, -0.933, 0.042], + [-0.244, -0.938, 0.245], + [0.091, -0.995, 0.045], + [0.121, -0.983, -0.139], + [-0.219, -0.852, 0.476], + [-0.244, -0.938, 0.245], + [0.121, -0.983, -0.139], + [-0.219, -0.852, 0.476], + [0.815, 0.561, 0.149], + [0.494, 0.393, 0.775], + [0.494, 0.393, 0.775], + [0.815, 0.561, 0.149], + [0.003, 0.943, 0.332], + [0.078, 0.954, 0.288], + [-0.584, 0.689, 0.429], + [0.121, 0.989, 0.087], + [-0.273, 0.957, -0.098], + [-0.994, -0.079, 0.081], + [-0.994, -0.079, 0.081], + [0.130, 0.990, 0.051], + [-0.356, -0.933, 0.042], + [0.006, 0.990, 0.140], + [-0.227, -0.973, -0.034], + [-0.441, -0.837, 0.325], + [-0.424, -0.166, -0.890], + [0.428, -0.712, -0.556], + [-0.441, -0.837, 0.325], + [0.442, 0.522, 0.730], + [0.428, -0.712, -0.556], + [0.442, 0.522, 0.730], + [-0.555, 0.831, 0.040], + [0.701, -0.303, -0.646], + [0.442, 0.522, 0.730], + [0.701, -0.303, -0.646], + [0.428, -0.712, -0.556], + [-0.189, 0.929, 0.318], + [0.701, -0.303, -0.646], + [-0.555, 0.831, 0.040], + [-0.109, 0.989, 0.104], + [-0.228, 0.973, 0.027], + [0.026, 0.997, 0.072], + [0.121, -0.979, -0.166], + [-0.227, -0.973, -0.034], + [0.231, -0.965, -0.127], + [0.255, -0.962, -0.092], + [0.992, 0.122, -0.000], + [0.327, 0.941, -0.088], + [0.992, 0.122, -0.000], + [0.327, 0.941, -0.088], + [0.126, 0.992, 0.019], + [0.149, 0.989, -0.018], + [0.149, 0.989, -0.018], + [-0.189, 0.929, 0.318], + [0.126, 0.992, 0.019], + [0.144, -0.964, -0.224], + [0.981, 0.165, -0.097], + [0.981, 0.165, -0.097], + [0.149, 0.984, 0.096], + [-0.022, -0.974, -0.225], + [0.257, -0.952, -0.167], + [0.257, -0.952, -0.167], + [0.026, 0.997, 0.072], + [0.149, 0.984, 0.096], + [-0.321, 0.946, -0.042], + [0.056, 0.972, 0.230], + [-0.555, 0.831, 0.040], + [0.725, -0.665, -0.181], + [0.442, 0.522, 0.730], + [0.725, -0.665, -0.181], + [-0.441, -0.837, 0.325], + [0.108, -0.960, -0.257], + [0.442, 0.522, 0.730], + [0.121, -0.979, -0.166], + [-0.441, -0.837, 0.325], + [-0.992, 0.094, -0.078], + [-0.992, 0.094, -0.078], + [0.144, -0.964, -0.224], + [-0.321, 0.946, -0.042], + [-0.022, -0.974, -0.225], + [0.268, -0.487, -0.831], + [-0.618, 0.310, -0.723], + [0.399, -0.465, -0.791], + [0.097, 0.661, -0.744], + [0.322, 0.669, -0.670], + [0.268, -0.487, -0.831], + [0.262, 0.381, -0.887], + [0.322, 0.669, -0.670], + [0.097, 0.661, -0.744], + [0.399, -0.465, -0.791], + [-0.121, 0.583, -0.804], + [-0.175, 0.680, -0.712], + [0.004, 0.655, -0.756], + [-0.006, 0.596, -0.803], + [0.004, 0.655, -0.756], + [-0.711, 0.450, -0.540], + [-0.006, 0.596, -0.803], + [-0.711, 0.450, -0.540], + [0.375, -0.927, -0.013], + [0.584, 0.174, -0.793], + [-0.006, 0.596, -0.803], + [0.375, -0.927, -0.013], + [0.375, -0.927, -0.013], + [0.399, -0.465, -0.791], + [-0.618, 0.310, -0.723], + [-0.175, 0.680, -0.712], + [-0.618, 0.310, -0.723], + [0.322, 0.669, -0.670], + [0.004, 0.655, -0.756], + [0.322, 0.669, -0.670], + [0.262, 0.381, -0.887], + [0.399, -0.465, -0.791], + [-0.121, 0.583, -0.804], + [0.004, 0.655, -0.756], + [-0.006, 0.596, -0.803], + [-0.190, -0.442, 0.876], + [0.269, 0.488, 0.831], + [0.340, 0.311, 0.888], + [0.300, -0.533, 0.791], + [0.097, -0.661, 0.744], + [0.149, -0.378, 0.914], + [0.269, 0.488, 0.831], + [0.300, -0.533, 0.791], + [0.097, -0.661, 0.744], + [0.340, 0.311, 0.888], + [0.214, -0.559, 0.801], + [-0.121, -0.581, 0.805], + [-0.055, -0.560, 0.826], + [-0.055, -0.560, 0.826], + [0.549, -0.571, 0.610], + [0.104, -0.574, 0.812], + [0.104, -0.574, 0.812], + [0.549, -0.571, 0.610], + [0.308, 0.909, -0.281], + [0.827, -0.017, 0.562], + [0.340, 0.311, 0.888], + [0.308, 0.909, -0.281], + [-0.190, -0.442, 0.876], + [0.214, -0.559, 0.801], + [-0.190, -0.442, 0.876], + [0.300, -0.533, 0.791], + [0.300, -0.533, 0.791], + [-0.055, -0.560, 0.826], + [0.149, -0.378, 0.914], + [-0.055, -0.560, 0.826], + [0.104, -0.574, 0.812], + [0.104, -0.574, 0.812], + [0.308, 0.909, -0.281], + [0.340, 0.311, 0.888], + [-0.121, -0.581, 0.805], + [0.962, -0.232, 0.145], + [0.999, 0.051, 0.002], + [0.971, -0.195, 0.136], + [0.971, -0.195, 0.136], + [0.999, 0.051, 0.002], + [0.997, -0.068, -0.030], + [0.996, 0.059, -0.062], + [-0.970, 0.086, 0.225], + [0.996, 0.059, -0.062], + [-0.970, 0.086, 0.225], + [-0.974, 0.103, 0.204], + [-0.980, 0.157, 0.118], + [-0.974, 0.103, 0.204], + [-0.980, 0.157, 0.118], + [-0.993, -0.018, -0.121], + [0.962, -0.232, 0.145], + [-0.993, -0.018, -0.121], + [0.962, -0.232, 0.145], + [0.971, -0.195, 0.136], + [-0.999, -0.038, 0.033], + [-0.990, 0.137, -0.041], + [-0.990, 0.137, -0.041], + [-0.993, -0.018, -0.121], + [-0.999, -0.038, 0.033], + [0.971, -0.195, 0.136], + [-0.956, -0.127, 0.264], + [-0.994, 0.090, 0.057], + [-0.987, -0.018, 0.163], + [-0.994, 0.090, 0.057], + [0.165, 0.808, -0.566], + [-0.987, -0.018, 0.163], + [0.165, 0.808, -0.566], + [0.995, 0.101, 0.004], + [1.000, -0.018, -0.023], + [0.997, 0.078, -0.026], + [0.939, 0.200, 0.279], + [-0.990, 0.051, 0.132], + [0.939, 0.200, 0.279], + [-0.990, 0.051, 0.132], + [-0.990, -0.131, -0.061], + [-0.966, 0.179, 0.187], + [-0.990, -0.131, -0.061], + [-0.966, 0.179, 0.187], + [-0.991, -0.007, 0.134], + [-0.977, 0.188, -0.101], + [-0.994, 0.090, 0.057], + [-0.977, 0.188, -0.101], + [0.995, 0.101, 0.004], + [-0.987, -0.018, 0.163], + [0.994, -0.101, -0.033], + [0.919, 0.249, 0.306], + [0.919, 0.249, 0.306], + [0.939, 0.200, 0.279], + [-0.897, 0.251, -0.365], + [-0.897, 0.251, -0.365], + [-0.897, 0.251, -0.365], + [-0.956, -0.127, 0.264], + [-0.753, -0.592, -0.286], + [-0.955, 0.215, -0.203], + [0.863, -0.429, 0.266], + [0.966, -0.227, 0.120], + [-0.753, -0.592, -0.286], + [0.863, -0.429, 0.266], + [0.948, -0.107, 0.299], + [-0.040, -0.946, -0.322], + [0.980, -0.179, 0.084], + [0.948, -0.107, 0.299], + [0.980, -0.179, 0.084], + [1.000, -0.004, 0.002], + [0.224, -0.788, -0.573], + [-0.964, -0.125, -0.234], + [-0.964, -0.125, -0.234], + [0.224, -0.788, -0.573], + [-0.971, -0.138, -0.197], + [-0.981, -0.158, -0.110], + [-0.981, -0.158, -0.110], + [-0.971, -0.138, -0.197], + [-0.066, -0.639, -0.766], + [-0.040, -0.946, -0.322], + [-0.040, -0.946, -0.322], + [-0.066, -0.639, -0.766], + [0.980, -0.179, 0.084], + [0.993, 0.089, -0.083], + [-0.126, -0.741, -0.659], + [-0.126, -0.741, -0.659], + [0.993, 0.089, -0.083], + [0.966, -0.227, 0.120], + [1.000, 0.019, 0.003], + [0.986, 0.164, -0.002], + [0.986, 0.164, -0.002], + [-0.952, 0.304, -0.019], + [-0.952, 0.304, -0.019], + [-0.998, 0.011, -0.058], + [-0.753, -0.592, -0.286], + [-0.126, -0.741, -0.659], + [0.966, -0.227, 0.120], + [0.863, -0.429, 0.266], + [0.994, 0.105, 0.010], + [0.921, -0.244, -0.304], + [0.986, 0.164, -0.002], + [0.921, -0.244, -0.304], + [-0.936, 0.340, 0.089], + [-0.952, 0.304, -0.019], + [0.986, 0.164, -0.002], + [-0.936, 0.340, 0.089], + [-0.936, 0.340, 0.089], + [-0.955, 0.215, -0.203]] + + for t, e in zip(tangents, expected): + assert_tuple_values(t.as_tuple(), e) + + bitangents = self.data.roots[0].children[1].data.bitangents + + expected = [[0.541, -0.061, 0.839], + [-0.097, -0.038, 0.995], + [0.796, -0.077, 0.600], + [0.832, -0.078, 0.549], + [0.126, 0.954, 0.271], + [0.030, 0.952, 0.304], + [0.111, -0.001, 0.994], + [0.076, -0.005, 0.997], + [-0.780, -0.006, 0.626], + [-0.831, -0.007, 0.556], + [0.126, 0.954, 0.271], + [0.030, 0.952, 0.304], + [0.777, -0.075, 0.625], + [0.102, -0.048, 0.994], + [0.890, -0.081, 0.448], + [0.954, -0.083, 0.289], + [-0.034, -0.999, 0.011], + [0.812, 0.221, 0.541], + [0.016, 0.948, 0.317], + [0.307, -0.946, 0.102], + [-0.063, 0.070, 0.996], + [-0.404, -0.822, -0.401], + [-0.241, -0.970, 0.037], + [-0.063, 0.070, 0.996], + [-0.234, 0.001, 0.972], + [0.643, 0.468, 0.606], + [0.643, 0.468, 0.606], + [0.822, -0.078, 0.565], + [0.812, 0.221, 0.541], + [-0.404, -0.822, -0.401], + [-0.063, 0.070, 0.996], + [0.660, -0.068, 0.748], + [0.739, -0.073, 0.670], + [-0.083, -0.050, 0.995], + [0.959, -0.280, 0.041], + [0.788, -0.343, 0.511], + [-0.331, -0.663, 0.672], + [0.060, -0.072, 0.996], + [-0.867, -0.245, 0.434], + [-0.879, -0.182, 0.441], + [-0.331, -0.663, 0.672], + [0.788, -0.343, 0.511], + [-0.611, -0.238, -0.755], + [0.643, 0.468, 0.606], + [-0.404, -0.822, -0.401], + [-0.394, -0.023, 0.919], + [-0.017, -0.046, 0.999], + [-0.031, -0.989, 0.145], + [0.202, -0.051, 0.978], + [0.800, -0.076, 0.596], + [-0.031, -0.986, 0.163], + [-0.031, -0.985, 0.170], + [0.033, -0.579, 0.814], + [-0.776, -0.003, 0.631], + [-0.895, -0.012, 0.446], + [-0.951, -0.019, 0.309], + [-0.034, -0.999, 0.011], + [-0.757, 0.297, 0.583], + [0.016, 0.948, 0.317], + [-0.246, -0.222, 0.943], + [-0.241, -0.970, 0.037], + [-0.404, -0.822, -0.401], + [-0.140, -0.057, 0.988], + [-0.246, -0.222, 0.943], + [-0.627, 0.479, 0.614], + [-0.627, 0.479, 0.614], + [-0.830, -0.007, 0.558], + [-0.404, -0.822, -0.401], + [-0.757, 0.297, 0.583], + [-0.738, 0.000, 0.675], + [-0.663, 0.004, 0.748], + [0.093, -0.012, 0.996], + [0.959, -0.280, 0.041], + [-0.822, -0.284, 0.493], + [-0.822, -0.284, 0.493], + [-0.046, -0.026, 0.999], + [-0.822, -0.284, 0.493], + [-0.404, -0.822, -0.401], + [0.365, -0.741, 0.564], + [0.118, -0.323, 0.939], + [-0.031, -0.989, 0.145], + [-0.212, 0.002, 0.977], + [-0.809, -0.005, 0.588], + [-0.031, -0.986, 0.163], + [-0.031, -0.985, 0.170], + [-0.775, -0.007, 0.632], + [-0.882, 0.001, 0.471], + [-0.735, -0.008, 0.678], + [-0.097, -0.038, 0.995], + [-0.510, -0.018, 0.860], + [-0.016, -0.996, 0.092], + [-0.028, -0.999, -0.017], + [0.880, -0.029, 0.475], + [0.773, -0.025, 0.633], + [0.732, -0.023, 0.681], + [0.111, -0.001, 0.994], + [0.076, -0.005, 0.997], + [-0.028, -0.999, -0.017], + [-0.016, -0.996, 0.092], + [-0.046, 0.920, 0.390], + [0.989, 0.149, 0.022], + [-0.081, 0.918, 0.388], + [-0.681, 0.192, 0.707], + [-0.081, 0.918, 0.388], + [0.989, 0.149, 0.022], + [0.016, 0.988, 0.157], + [-0.840, -0.002, 0.543], + [0.717, 0.122, 0.687], + [0.016, 0.988, 0.157], + [0.842, -0.028, 0.538], + [0.691, -0.365, 0.624], + [-0.081, 0.918, 0.388], + [-0.046, 0.920, 0.390], + [0.905, 0.404, 0.129], + [-0.924, 0.300, 0.236], + [0.691, -0.365, 0.624], + [-0.924, 0.300, 0.236], + [0.691, -0.365, 0.624], + [-0.521, -0.842, 0.142], + [-0.081, 0.918, 0.388], + [-0.924, 0.300, 0.236], + [-0.046, 0.920, 0.390], + [-0.286, -0.026, 0.958], + [-0.669, -0.003, 0.743], + [-0.559, -0.016, 0.829], + [-0.363, 0.836, -0.411], + [0.691, -0.365, 0.624], + [-0.924, 0.300, 0.236], + [-0.081, 0.918, 0.388], + [-0.631, -0.005, 0.776], + [-0.695, 0.628, -0.350], + [0.102, -0.048, 0.994], + [-0.017, -0.046, 0.999], + [-0.356, 0.385, 0.852], + [-0.120, 0.964, 0.237], + [-0.120, 0.964, 0.237], + [0.691, -0.365, 0.624], + [-0.081, 0.918, 0.388], + [-0.120, 0.964, 0.237], + [0.905, 0.404, 0.129], + [0.691, -0.365, 0.624], + [-0.356, 0.385, 0.852], + [-0.363, 0.836, -0.411], + [0.920, 0.343, -0.190], + [0.754, 0.563, -0.338], + [-0.695, 0.628, -0.350], + [-0.356, 0.385, 0.852], + [-0.081, 0.918, 0.388], + [-0.681, 0.192, 0.707], + [0.389, -0.867, 0.311], + [-0.588, -0.467, 0.661], + [0.754, 0.563, -0.338], + [0.331, 0.933, 0.138], + [0.691, -0.365, 0.624], + [-0.530, -0.828, 0.182], + [0.389, -0.867, 0.311], + [-0.063, 0.070, 0.996], + [0.307, -0.946, 0.102], + [-0.588, -0.467, 0.661], + [-0.588, -0.467, 0.661], + [-0.063, 0.070, 0.996], + [-0.588, -0.467, 0.661], + [-0.432, -0.604, 0.670], + [-0.394, -0.023, 0.919], + [-0.083, -0.050, 0.995], + [-0.867, 0.000, 0.498], + [0.060, -0.072, 0.996], + [-0.432, -0.604, 0.670], + [-0.234, 0.001, 0.972], + [-0.081, 0.918, 0.388], + [0.202, -0.051, 0.978], + [-0.489, 0.792, 0.366], + [-0.955, 0.008, 0.297], + [0.005, 0.746, 0.665], + [0.082, -0.792, 0.606], + [0.258, -0.898, 0.356], + [0.236, -0.892, 0.385], + [-0.786, 0.264, 0.559], + [-0.786, 0.264, 0.559], + [0.034, -0.765, 0.643], + [0.131, -0.854, 0.503], + [-0.022, -0.862, 0.506], + [0.034, -0.765, 0.643], + [0.082, -0.792, 0.606], + [0.033, -0.579, 0.814], + [0.118, -0.323, 0.939], + [0.671, -0.633, 0.386], + [-0.046, 0.920, 0.390], + [-0.786, 0.264, 0.559], + [0.691, -0.365, 0.624], + [-0.786, 0.264, 0.559], + [0.487, -0.869, -0.083], + [-0.022, -0.862, 0.506], + [0.451, 0.604, 0.657], + [-0.786, 0.264, 0.559], + [0.487, -0.869, -0.083], + [0.451, 0.604, 0.657], + [-0.521, -0.842, 0.142], + [0.487, -0.869, -0.083], + [-0.786, 0.264, 0.559], + [0.487, -0.869, -0.083], + [0.671, -0.633, 0.386], + [0.451, 0.604, 0.657], + [-0.521, -0.842, 0.142], + [0.005, 0.746, 0.665], + [0.960, 0.073, 0.271], + [-0.611, -0.238, -0.755], + [0.920, 0.343, -0.190], + [0.455, -0.551, 0.700], + [0.034, -0.765, 0.643], + [0.754, 0.563, -0.338], + [0.754, 0.563, -0.338], + [0.451, 0.604, 0.657], + [0.671, -0.633, 0.386], + [0.717, 0.122, 0.687], + [0.331, 0.933, 0.138], + [-0.046, 0.920, 0.390], + [-0.022, -0.862, 0.506], + [0.455, -0.551, 0.700], + [0.331, 0.933, 0.138], + [0.717, 0.122, 0.687], + [0.671, -0.633, 0.386], + [0.118, -0.323, 0.939], + [0.717, 0.122, 0.687], + [0.389, -0.867, 0.311], + [-0.530, -0.828, 0.182], + [0.097, -0.919, 0.383], + [0.015, -1.000, 0.008], + [-0.246, -0.222, 0.943], + [-0.241, -0.970, 0.037], + [0.455, -0.551, 0.700], + [0.097, -0.919, 0.383], + [-0.246, -0.222, 0.943], + [0.455, -0.551, 0.700], + [0.054, -0.740, 0.671], + [0.365, -0.741, 0.564], + [0.389, -0.867, 0.311], + [0.093, -0.012, 0.996], + [0.867, -0.028, 0.498], + [-0.046, -0.026, 0.999], + [0.920, 0.343, -0.190], + [0.034, -0.765, 0.643], + [0.754, 0.563, -0.338], + [0.054, -0.740, 0.671], + [-0.246, -0.222, 0.943], + [-0.140, -0.057, 0.988], + [0.054, -0.740, 0.671], + [0.118, -0.323, 0.939], + [-0.212, 0.002, 0.977], + [-0.489, 0.792, 0.366], + [0.960, 0.073, 0.271], + [0.005, 0.746, 0.665], + [-0.489, 0.792, 0.366], + [0.960, 0.073, 0.271], + [-0.298, 0.035, 0.954], + [-0.392, 0.025, 0.919], + [0.021, 0.956, 0.292], + [0.071, 0.959, 0.273], + [0.021, 0.956, 0.292], + [0.071, 0.959, 0.273], + [0.368, -0.028, 0.930], + [0.376, -0.034, 0.926], + [0.233, 0.031, 0.972], + [-0.577, 0.055, 0.815], + [-0.926, 0.310, 0.216], + [-0.926, 0.310, 0.216], + [0.700, -0.014, 0.714], + [-0.051, -0.012, 0.999], + [0.368, -0.028, 0.930], + [0.376, -0.034, 0.926], + [-0.568, -0.022, 0.823], + [-0.566, -0.023, 0.824], + [-0.016, -1.000, 0.011], + [-0.009, -0.999, 0.041], + [-0.016, -1.000, 0.011], + [-0.009, -0.999, 0.041], + [0.646, 0.003, 0.763], + [0.605, 0.004, 0.796], + [-0.298, 0.035, 0.954], + [-0.392, 0.025, 0.919], + [-0.051, -0.012, 0.999], + [-0.467, -0.026, 0.884], + [-0.967, 0.072, 0.246], + [0.233, 0.031, 0.972], + [0.764, -0.000, 0.645], + [-0.967, 0.072, 0.246], + [0.405, -0.016, 0.914], + [0.310, -0.021, 0.950], + [-0.026, 0.956, 0.292], + [-0.080, 0.957, 0.278], + [-0.080, 0.957, 0.278], + [-0.026, 0.956, 0.292], + [-0.365, -0.011, 0.931], + [-0.373, -0.009, 0.928], + [0.310, -0.021, 0.950], + [-0.236, -0.045, 0.971], + [0.587, -0.018, 0.810], + [0.587, -0.018, 0.810], + [0.941, 0.269, 0.206], + [0.941, 0.269, 0.206], + [-0.702, -0.045, 0.711], + [0.050, 0.014, 0.999], + [-0.373, -0.009, 0.928], + [-0.365, -0.011, 0.931], + [0.571, 0.040, 0.820], + [0.500, 0.041, 0.865], + [0.136, -0.990, 0.032], + [-0.600, -0.034, 0.799], + [0.136, -0.990, 0.032], + [-0.593, -0.034, 0.804], + [0.405, -0.016, 0.914], + [0.050, 0.014, 0.999], + [0.465, 0.041, 0.884], + [0.975, 0.072, 0.210], + [-0.772, -0.024, 0.635], + [0.975, 0.072, 0.210], + [0.321, -0.030, 0.947], + [-0.574, -0.022, 0.819], + [0.073, 0.994, 0.078], + [0.073, 0.994, 0.078], + [0.602, 0.005, 0.798], + [-0.329, 0.040, 0.943], + [-0.329, 0.040, 0.943], + [0.315, -0.949, 0.035], + [0.315, -0.949, 0.035], + [0.321, -0.030, 0.947], + [0.283, -0.025, 0.959], + [-0.653, -0.019, 0.758], + [0.045, 0.994, 0.100], + [0.045, 0.994, 0.100], + [0.699, 0.002, 0.716], + [0.124, 0.034, 0.992], + [0.124, 0.034, 0.992], + [-0.728, 0.052, 0.684], + [-0.075, -0.961, 0.268], + [-0.075, -0.961, 0.268], + [0.283, -0.025, 0.959], + [-0.034, -0.014, 0.999], + [-0.547, 0.555, 0.627], + [-0.635, -0.019, 0.772], + [0.184, -0.980, 0.072], + [0.992, -0.125, -0.032], + [0.992, -0.125, -0.032], + [0.184, -0.980, 0.072], + [0.811, -0.002, 0.585], + [0.801, -0.002, 0.599], + [-0.058, 0.040, 0.998], + [-0.323, 0.049, 0.945], + [-0.058, 0.040, 0.998], + [-0.323, 0.049, 0.945], + [-0.869, 0.039, 0.492], + [-0.852, 0.041, 0.522], + [-0.993, -0.118, -0.001], + [0.927, -0.143, 0.347], + [-0.993, -0.118, -0.001], + [0.927, -0.143, 0.347], + [0.554, -0.006, 0.832], + [0.420, -0.001, 0.907], + [-0.034, -0.014, 0.999], + [-0.547, 0.555, 0.627], + [0.029, -0.016, 0.999], + [-0.679, -0.017, 0.734], + [0.006, 0.997, 0.079], + [0.006, 0.997, 0.079], + [0.759, 0.000, 0.651], + [-0.012, 0.041, 0.999], + [-0.012, 0.041, 0.999], + [-0.831, 0.044, 0.554], + [0.815, -0.417, 0.401], + [0.815, -0.417, 0.401], + [0.029, -0.016, 0.999], + [-0.323, -0.005, 0.946], + [0.568, 0.040, 0.822], + [-0.083, 0.994, 0.078], + [-0.083, 0.994, 0.078], + [-0.602, -0.033, 0.798], + [0.330, 0.001, 0.944], + [0.330, 0.001, 0.944], + [-0.081, -0.996, 0.033], + [-0.081, -0.996, 0.033], + [-0.323, -0.005, 0.946], + [-0.289, 0.000, 0.957], + [0.647, 0.039, 0.761], + [-0.057, 0.993, 0.101], + [-0.057, 0.993, 0.101], + [-0.701, -0.028, 0.713], + [-0.131, -0.006, 0.991], + [0.726, 0.035, 0.687], + [-0.131, -0.006, 0.991], + [0.084, -0.960, 0.266], + [0.084, -0.960, 0.266], + [-0.289, 0.000, 0.957], + [-0.547, 0.555, 0.627], + [0.011, 0.008, 1.000], + [0.693, 0.038, 0.720], + [0.707, 0.038, 0.707], + [0.080, -0.995, 0.060], + [0.768, 0.637, 0.066], + [0.768, 0.637, 0.066], + [0.080, -0.995, 0.060], + [-0.813, 0.095, 0.575], + [-0.795, 0.285, 0.536], + [0.768, 0.637, 0.066], + [-0.813, 0.095, 0.575], + [-0.795, 0.285, 0.536], + [0.060, 0.002, 0.998], + [0.324, 0.018, 0.946], + [0.324, 0.018, 0.946], + [0.060, 0.002, 0.998], + [0.870, 0.027, 0.493], + [0.852, 0.028, 0.523], + [0.980, -0.199, 0.006], + [-0.915, -0.198, 0.351], + [-0.915, -0.198, 0.351], + [0.980, -0.199, 0.006], + [-0.552, -0.035, 0.833], + [-0.526, -0.033, 0.850], + [0.011, 0.008, 1.000], + [-0.547, 0.555, 0.627], + [-0.030, 0.008, 0.999], + [0.676, 0.039, 0.736], + [-0.027, 0.997, 0.077], + [-0.027, 0.997, 0.077], + [-0.761, -0.025, 0.649], + [0.008, 0.003, 1.000], + [0.008, 0.003, 1.000], + [0.831, 0.029, 0.556], + [-0.764, -0.511, 0.394], + [-0.764, -0.511, 0.394], + [-0.030, 0.008, 0.999], + [0.713, 0.182, 0.677], + [0.308, 0.183, 0.934], + [0.741, 0.629, 0.236], + [0.949, -0.267, -0.170], + [0.858, -0.366, -0.361], + [0.713, 0.182, 0.677], + [0.949, -0.267, -0.170], + [0.643, 0.241, 0.727], + [0.659, -0.693, -0.291], + [0.659, -0.693, -0.291], + [-0.029, 0.260, 0.965], + [0.643, 0.241, 0.727], + [0.535, -0.220, 0.815], + [0.664, -0.151, 0.732], + [-0.428, -0.083, 0.900], + [0.308, 0.183, 0.934], + [-0.001, -0.088, 0.996], + [0.570, 0.034, 0.821], + [0.700, 0.029, 0.714], + [-0.017, -0.990, 0.138], + [-0.978, -0.108, 0.176], + [-0.978, -0.108, 0.176], + [-0.017, -0.990, 0.138], + [-0.478, -0.003, 0.878], + [-0.594, 0.039, 0.804], + [-0.029, 0.260, 0.965], + [0.092, -0.063, 0.994], + [-0.330, -0.943, 0.035], + [-0.330, -0.943, 0.035], + [-0.070, -0.064, 0.995], + [-0.304, -0.131, 0.943], + [0.916, 0.144, 0.374], + [0.916, 0.144, 0.374], + [-0.428, -0.083, 0.900], + [-0.070, -0.064, 0.995], + [-0.428, -0.083, 0.900], + [0.664, -0.151, 0.732], + [0.535, -0.220, 0.815], + [0.934, -0.357, 0.001], + [-0.029, 0.260, 0.965], + [-0.478, -0.003, 0.878], + [0.568, -0.047, 0.822], + [0.643, 0.241, 0.727], + [-0.029, 0.260, 0.965], + [0.568, -0.047, 0.822], + [0.643, 0.241, 0.727], + [0.580, -0.779, -0.238], + [0.858, -0.366, -0.361], + [0.858, -0.366, -0.361], + [0.580, -0.779, -0.238], + [-0.940, -0.111, 0.324], + [-0.697, -0.154, 0.700], + [0.713, 0.182, 0.677], + [-0.001, -0.088, 0.996], + [0.308, 0.183, 0.934], + [0.063, -0.980, -0.191], + [0.063, -0.980, -0.191], + [0.092, -0.063, 0.994], + [0.934, -0.357, 0.001], + [-0.304, -0.131, 0.943], + [-0.343, 0.047, 0.938], + [0.344, 0.177, 0.922], + [-0.741, 0.629, 0.236], + [-0.903, -0.356, -0.240], + [0.344, 0.177, 0.922], + [0.886, -0.126, -0.446], + [-0.903, -0.356, -0.240], + [0.886, -0.126, -0.446], + [-0.393, -0.304, 0.868], + [-0.616, -0.714, -0.333], + [0.886, -0.126, -0.446], + [-0.616, -0.714, -0.333], + [-0.903, -0.356, -0.240], + [0.157, -0.291, 0.944], + [-0.616, -0.714, -0.333], + [-0.393, -0.304, 0.868], + [-0.664, -0.151, 0.732], + [-0.553, -0.152, 0.819], + [0.428, -0.076, 0.901], + [0.011, -0.166, 0.986], + [-0.343, 0.047, 0.938], + [-0.527, -0.233, 0.817], + [-0.655, -0.242, 0.716], + [0.121, -0.983, 0.139], + [0.932, -0.305, 0.198], + [0.121, -0.983, 0.139], + [0.932, -0.305, 0.198], + [0.470, -0.077, 0.879], + [0.581, -0.072, 0.811], + [0.581, -0.072, 0.811], + [0.157, -0.291, 0.944], + [0.470, -0.077, 0.879], + [-0.068, -0.236, 0.970], + [0.171, -0.984, 0.051], + [0.171, -0.984, 0.051], + [0.064, -0.106, 0.992], + [0.304, -0.221, 0.927], + [-0.893, -0.300, 0.335], + [-0.893, -0.300, 0.335], + [0.428, -0.076, 0.901], + [0.064, -0.106, 0.992], + [-0.947, -0.321, -0.001], + [-0.578, -0.156, 0.801], + [-0.393, -0.304, 0.868], + [-0.688, -0.693, -0.215], + [0.886, -0.126, -0.446], + [-0.688, -0.693, -0.215], + [0.344, 0.177, 0.922], + [0.693, -0.113, 0.712], + [0.886, -0.126, -0.446], + [0.011, -0.166, 0.986], + [0.344, 0.177, 0.922], + [-0.078, -0.978, -0.193], + [-0.078, -0.978, -0.193], + [-0.068, -0.236, 0.970], + [-0.947, -0.321, -0.001], + [0.304, -0.221, 0.927], + [0.922, -0.121, 0.368], + [-0.779, -0.364, 0.510], + [0.273, -0.763, 0.586], + [-0.690, 0.584, 0.428], + [0.092, 0.682, 0.726], + [0.922, -0.121, 0.368], + [0.959, 0.002, 0.285], + [0.092, 0.682, 0.726], + [-0.690, 0.584, 0.428], + [0.273, -0.763, 0.586], + [-0.201, 0.779, 0.595], + [-0.916, 0.152, 0.371], + [0.447, 0.675, 0.587], + [0.986, 0.140, 0.096], + [0.447, 0.675, 0.587], + [0.700, 0.375, -0.608], + [0.986, 0.140, 0.096], + [0.700, 0.375, -0.608], + [-0.167, -0.082, 0.983], + [0.778, -0.398, 0.486], + [0.986, 0.140, 0.096], + [-0.167, -0.082, 0.983], + [-0.167, -0.082, 0.983], + [0.273, -0.763, 0.586], + [-0.779, -0.364, 0.510], + [-0.916, 0.152, 0.371], + [-0.779, -0.364, 0.510], + [0.092, 0.682, 0.726], + [0.447, 0.675, 0.587], + [0.092, 0.682, 0.726], + [0.959, 0.002, 0.285], + [0.273, -0.763, 0.586], + [-0.201, 0.779, 0.595], + [0.447, 0.675, 0.587], + [0.986, 0.140, 0.096], + [0.976, -0.181, 0.121], + [-0.922, -0.120, 0.369], + [-0.344, -0.837, 0.425], + [-0.150, 0.793, 0.590], + [0.690, 0.584, 0.428], + [-0.983, 0.046, 0.180], + [-0.922, -0.120, 0.369], + [-0.150, 0.793, 0.590], + [0.690, 0.584, 0.428], + [-0.344, -0.837, 0.425], + [0.908, 0.417, 0.048], + [0.201, 0.780, 0.593], + [-0.444, 0.755, 0.483], + [-0.444, 0.755, 0.483], + [-0.818, -0.220, 0.531], + [-0.992, -0.118, 0.044], + [-0.992, -0.118, 0.044], + [-0.818, -0.220, 0.531], + [0.271, 0.199, 0.942], + [-0.512, -0.434, 0.741], + [-0.344, -0.837, 0.425], + [0.271, 0.199, 0.942], + [0.976, -0.181, 0.121], + [0.908, 0.417, 0.048], + [0.976, -0.181, 0.121], + [-0.150, 0.793, 0.590], + [-0.150, 0.793, 0.590], + [-0.444, 0.755, 0.483], + [-0.983, 0.046, 0.180], + [-0.444, 0.755, 0.483], + [-0.992, -0.118, 0.044], + [-0.992, -0.118, 0.044], + [0.271, 0.199, 0.942], + [-0.344, -0.837, 0.425], + [0.201, 0.780, 0.593], + [-0.167, -0.918, -0.361], + [0.008, -0.193, 0.981], + [-0.237, -0.840, 0.489], + [-0.237, -0.840, 0.489], + [0.008, -0.193, 0.981], + [0.020, -0.132, 0.991], + [0.014, 0.602, 0.798], + [-0.145, -0.955, -0.260], + [0.014, 0.602, 0.798], + [-0.145, -0.955, -0.260], + [0.088, -0.656, 0.750], + [0.057, -0.349, 0.935], + [0.088, -0.656, 0.750], + [0.057, -0.349, 0.935], + [-0.104, 0.639, 0.762], + [-0.167, -0.918, -0.361], + [-0.104, 0.639, 0.762], + [-0.167, -0.918, -0.361], + [-0.237, -0.840, 0.489], + [-0.044, 0.978, -0.204], + [0.049, 0.594, 0.803], + [0.049, 0.594, 0.803], + [-0.104, 0.639, 0.762], + [-0.044, 0.978, -0.204], + [-0.237, -0.840, 0.489], + [0.061, 0.794, 0.605], + [0.106, 0.904, 0.415], + [-0.061, 0.961, -0.269], + [0.106, 0.904, 0.415], + [0.986, -0.115, 0.124], + [-0.061, 0.961, -0.269], + [0.986, -0.115, 0.124], + [0.065, -0.662, 0.747], + [0.024, 0.031, 0.999], + [0.024, 0.028, 0.999], + [-0.328, 0.762, 0.559], + [-0.097, -0.925, -0.367], + [-0.328, 0.762, 0.559], + [-0.097, -0.925, -0.367], + [0.093, -0.901, 0.425], + [0.051, -0.576, 0.816], + [0.093, -0.901, 0.425], + [0.051, -0.576, 0.816], + [0.134, 0.012, 0.991], + [0.084, 0.773, 0.629], + [0.106, 0.904, 0.415], + [0.084, 0.773, 0.629], + [0.065, -0.662, 0.747], + [-0.061, 0.961, -0.269], + [0.026, -0.072, 0.997], + [-0.386, 0.727, 0.567], + [-0.386, 0.727, 0.567], + [-0.328, 0.762, 0.559], + [-0.376, -0.866, 0.329], + [-0.376, -0.866, 0.329], + [-0.376, -0.866, 0.329], + [0.061, 0.794, 0.605], + [-0.657, 0.689, 0.305], + [0.040, 0.776, 0.629], + [-0.480, -0.860, 0.172], + [-0.255, -0.783, 0.567], + [-0.657, 0.689, 0.305], + [-0.480, -0.860, 0.172], + [-0.314, -0.168, 0.934], + [-0.976, -0.033, 0.217], + [-0.197, -0.843, 0.500], + [-0.314, -0.168, 0.934], + [-0.197, -0.843, 0.500], + [-0.002, -0.052, 0.999], + [0.970, 0.121, 0.212], + [0.185, -0.949, -0.254], + [0.185, -0.949, -0.254], + [0.970, 0.121, 0.212], + [-0.070, -0.622, 0.780], + [-0.048, -0.349, 0.936], + [-0.048, -0.349, 0.936], + [-0.070, -0.622, 0.780], + [0.996, 0.006, -0.091], + [-0.976, -0.033, 0.217], + [-0.976, -0.033, 0.217], + [0.996, 0.006, -0.091], + [-0.197, -0.843, 0.500], + [0.118, -0.861, 0.494], + [-0.976, -0.026, 0.216], + [-0.976, -0.026, 0.216], + [0.118, -0.861, 0.494], + [-0.255, -0.783, 0.567], + [-0.004, 0.031, 1.000], + [-0.127, 0.770, 0.625], + [-0.127, 0.770, 0.625], + [-0.282, -0.858, 0.430], + [-0.282, -0.858, 0.430], + [-0.058, 0.012, 0.998], + [-0.657, 0.689, 0.305], + [-0.976, -0.026, 0.216], + [-0.255, -0.783, 0.567], + [-0.480, -0.860, 0.172], + [-0.002, -0.069, 0.998], + [0.381, 0.729, 0.568], + [-0.127, 0.770, 0.625], + [0.381, 0.729, 0.568], + [-0.257, -0.836, 0.485], + [-0.282, -0.858, 0.430], + [-0.127, 0.770, 0.625], + [-0.257, -0.836, 0.485], + [-0.257, -0.836, 0.485], + [0.040, 0.776, 0.629]] + + for e, b in zip(bitangents, expected): + assert_tuple_values(b, e.as_list()) + + """ + pyffi.toaster: INFO:--- fix_addtangentspace - -- + pyffi.toaster: INFO: ~~~ NiNode[Bip01) ~~~ + pyffi.toaster: INFO: ~~~ NiNode[Bip01 Pelvis) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 Spine) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 Spine1) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 Spine2) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 Neck) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 Head) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 L Clavicle) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 L UpperArm) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 L Forearm) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 R Clavicle) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 R UpperArm) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 R Forearm) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 L Thigh) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 L Calf) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 L Foot) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 L Toe0) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 R Thigh) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 R Calf) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 R Foot) ~~~ + pyffi.toaster: INFO: ~~~ NiNode(Bip01 R Toe0) ~~~ + pyffi.toaster: INFO: ~~~ NiTriShape(Body) ~~~ + pyffi.toaster: INFO: adding tangent space + """ + +class TestFixDeltaTangentSpace(BaseFileTestCase): + """Invoke the fix_texturepath spell check through nif toaster""" + + def setUp(self): + super(TestFixDeltaTangentSpace, self).setUp() + self.src_name = "test_fix_tangentspace.nif" + super(TestFixDeltaTangentSpace, self).copyFile() + super(TestFixDeltaTangentSpace, self).readNifData() + + def test_non_interactive_fix_addtangentspace(self): + + call_niftoaster("--raise", "fix_deltangentspace", "fix_addtangentspace", "--dry-run", "--noninteractive", + "--verbose=1", self.dest_file) + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_tangentspace.nif === + pyffi.toaster:INFO: --- fix_deltangentspace & fix_addtangentspace --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Sphere] ~~~ + pyffi.toaster:INFO: removing tangent space block + pyffi.toaster:INFO: adding tangent space + pyffi.toaster:INFO: writing to temporary file + pyffi.toaster:INFO:Finished. + """ + + + def test_non_interactive_fix_addtangentspace_series(self): + + call_niftoaster("--raise", "fix_deltangentspace", "fix_addtangentspace", "--series", + "--dry-run", "--noninteractive", "--verbose=1", self.dest_file) + + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_tangentspace.nif === + pyffi.toaster:INFO: --- fix_deltangentspace --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Sphere] ~~~ + pyffi.toaster:INFO: removing tangent space block + pyffi.toaster:INFO: --- fix_addtangentspace --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Sphere] ~~~ + pyffi.toaster:INFO: adding tangent space + pyffi.toaster:INFO: writing to temporary file + pyffi.toaster:INFO:Finished. + """ \ No newline at end of file diff --git a/tests/spells/nif/fix_tangentspace.txt b/tests/spells/nif/fix_tangentspace.txt deleted file mode 100644 index 7c7fb29cd..000000000 --- a/tests/spells/nif/fix_tangentspace.txt +++ /dev/null @@ -1,1499 +0,0 @@ -Regression test for tangent space algorithm -------------------------------------------- - ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(4): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "nif") ->>> import sys ->>> script = os.path.join(script_dir, "niftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> nif_dir = "tests/spells/nif/files/" - - ->>> from pyffi.formats.nif import NifFormat ->>> import pyffi.spells.nif.optimize ->>> data = NifFormat.Data() ->>> stream = open(nif_dir + "test_skincenterradius.nif", "rb") ->>> data.read(stream) ->>> # run the spell that optimizes this ->>> spell = pyffi.spells.nif.fix.SpellAddTangentSpace(data=data) ->>> spell.recurse() -pyffi.toaster:INFO:--- fix_addtangentspace --- -pyffi.toaster:INFO: ~~~ NiNode [Bip01] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Pelvis] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine1] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine2] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Neck] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Head] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Clavicle] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L UpperArm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Forearm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Clavicle] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R UpperArm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Forearm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Thigh] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Calf] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Foot] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Toe0] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Thigh] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Calf] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Foot] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Toe0] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Body] ~~~ -pyffi.toaster:INFO: adding tangent space ->>> # check data ->>> for v in data.roots[0].children[1].data.tangents: print(v) -[ -0.175 0.967 0.183 ] -[ -0.367 0.930 0.000 ] -[ -0.178 0.918 0.354 ] -[ 0.020 0.994 0.111 ] -[ -0.992 0.122 0.035 ] -[ -1.000 0.028 0.009 ] -[ -0.363 -0.931 0.039 ] -[ -0.140 -0.990 0.006 ] -[ -0.239 -0.921 -0.306 ] -[ -0.040 -0.997 -0.072 ] -[ -0.992 0.122 0.035 ] -[ -1.000 0.028 0.009 ] -[ 0.067 0.997 0.037 ] -[ 0.219 0.975 0.025 ] -[ 0.109 0.993 -0.038 ] -[ 0.000 0.961 0.276 ] -[ 0.999 -0.034 0.000 ] -[ -0.492 0.759 0.428 ] -[ -1.000 0.015 0.005 ] -[ 0.596 0.274 0.754 ] -[ -0.690 0.717 -0.094 ] -[ 0.915 -0.363 -0.177 ] -[ 0.640 -0.187 -0.745 ] -[ -0.690 0.717 -0.094 ] -[ -0.960 0.155 -0.231 ] -[ -0.714 0.653 0.254 ] -[ -0.714 0.653 0.254 ] -[ 0.141 0.988 -0.069 ] -[ -0.492 0.759 0.428 ] -[ 0.915 -0.363 -0.177 ] -[ -0.690 0.717 -0.094 ] -[ 0.069 0.997 0.030 ] -[ 0.014 0.996 0.093 ] -[ -0.235 0.972 0.029 ] -[ 0.283 0.949 -0.140 ] -[ 0.517 0.820 -0.247 ] -[ 0.944 -0.234 0.234 ] -[ -0.271 0.959 0.085 ] -[ 0.498 -0.370 0.784 ] -[ 0.476 -0.404 0.781 ] -[ 0.944 -0.234 0.234 ] -[ 0.517 0.820 -0.247 ] -[ -0.791 0.230 0.568 ] -[ -0.714 0.653 0.254 ] -[ 0.915 -0.363 -0.177 ] -[ 0.136 0.987 0.083 ] -[ 0.336 0.941 0.049 ] -[ 1.000 -0.031 0.005 ] -[ 0.187 0.982 0.013 ] -[ 0.160 0.983 -0.089 ] -[ 1.000 -0.031 0.005 ] -[ 1.000 -0.031 0.005 ] -[ 0.233 -0.788 -0.570 ] -[ 0.007 -1.000 0.004 ] -[ 0.048 -0.997 0.068 ] -[ -0.064 -0.965 -0.256 ] -[ 0.999 -0.034 0.000 ] -[ -0.572 -0.732 -0.370 ] -[ -1.000 0.015 0.005 ] -[ -0.643 -0.691 -0.331 ] -[ 0.640 -0.187 -0.745 ] -[ 0.915 -0.363 -0.177 ] -[ -0.978 -0.146 -0.147 ] -[ -0.643 -0.691 -0.331 ] -[ -0.727 -0.644 -0.240 ] -[ -0.727 -0.644 -0.240 ] -[ 0.081 -0.991 0.109 ] -[ 0.915 -0.363 -0.177 ] -[ -0.572 -0.732 -0.370 ] -[ -0.040 -0.998 -0.044 ] -[ 0.020 -1.000 0.023 ] -[ -0.233 -0.973 0.010 ] -[ 0.283 0.949 -0.140 ] -[ 0.460 -0.842 0.282 ] -[ 0.460 -0.842 0.282 ] -[ -0.277 -0.960 -0.038 ] -[ 0.460 -0.842 0.282 ] -[ 0.915 -0.363 -0.177 ] -[ -0.212 -0.656 -0.724 ] -[ 0.315 -0.885 -0.344 ] -[ 1.000 -0.031 0.005 ] -[ 0.175 -0.984 0.040 ] -[ 0.102 -0.986 0.132 ] -[ 1.000 -0.031 0.005 ] -[ 1.000 -0.031 0.005 ] -[ -0.084 0.992 -0.092 ] -[ -0.072 0.988 -0.136 ] -[ -0.156 0.975 -0.157 ] -[ -0.367 0.930 0.000 ] -[ -0.029 1.000 0.004 ] -[ -1.000 0.016 -0.001 ] -[ -1.000 0.028 0.000 ] -[ -0.098 -0.988 0.122 ] -[ -0.098 -0.992 0.081 ] -[ -0.167 -0.975 0.146 ] -[ -0.363 -0.931 0.039 ] -[ -0.140 -0.990 0.006 ] -[ -1.000 0.028 0.000 ] -[ -1.000 0.016 -0.001 ] -[ 0.977 0.122 -0.173 ] -[ 0.151 -0.978 -0.142 ] -[ 0.995 0.055 0.077 ] -[ 0.353 0.931 0.087 ] -[ 0.995 0.055 0.077 ] -[ 0.151 -0.978 -0.142 ] -[ 1.000 -0.016 -0.003 ] -[ 0.106 0.980 0.167 ] -[ 0.387 -0.889 -0.246 ] -[ 1.000 -0.016 -0.003 ] -[ 0.084 -0.980 -0.181 ] -[ -0.270 -0.931 -0.246 ] -[ 0.995 0.055 0.077 ] -[ 0.977 0.122 -0.173 ] -[ 0.239 -0.737 0.632 ] -[ 0.379 0.646 0.663 ] -[ -0.270 -0.931 -0.246 ] -[ 0.379 0.646 0.663 ] -[ -0.270 -0.931 -0.246 ] -[ -0.831 0.538 0.143 ] -[ 0.995 0.055 0.077 ] -[ 0.379 0.646 0.663 ] -[ 0.977 0.122 -0.173 ] -[ 0.152 0.986 0.072 ] -[ -0.245 0.945 -0.217 ] -[ -0.060 0.998 -0.022 ] -[ -0.918 -0.246 0.311 ] -[ -0.270 -0.931 -0.246 ] -[ 0.379 0.646 0.663 ] -[ 0.995 0.055 0.077 ] -[ -0.186 0.972 -0.145 ] -[ -0.707 -0.506 0.494 ] -[ 0.219 0.975 0.025 ] -[ 0.336 0.941 0.049 ] -[ 0.635 0.768 -0.082 ] -[ 0.965 0.169 -0.199 ] -[ 0.965 0.169 -0.199 ] -[ -0.270 -0.931 -0.246 ] -[ 0.995 0.055 0.077 ] -[ 0.965 0.169 -0.199 ] -[ 0.239 -0.737 0.632 ] -[ -0.270 -0.931 -0.246 ] -[ 0.635 0.768 -0.082 ] -[ -0.918 -0.246 0.311 ] -[ 0.392 -0.810 0.435 ] -[ 0.654 -0.689 0.311 ] -[ -0.707 -0.506 0.494 ] -[ 0.635 0.768 -0.082 ] -[ 0.995 0.055 0.077 ] -[ 0.353 0.931 0.087 ] -[ -0.899 -0.283 0.336 ] -[ -0.747 0.626 -0.222 ] -[ 0.654 -0.689 0.311 ] -[ 0.941 -0.337 0.019 ] -[ -0.270 -0.931 -0.246 ] -[ -0.747 0.558 0.361 ] -[ -0.899 -0.283 0.336 ] -[ -0.690 0.717 -0.094 ] -[ 0.596 0.274 0.754 ] -[ -0.747 0.626 -0.222 ] -[ -0.747 0.626 -0.222 ] -[ -0.690 0.717 -0.094 ] -[ -0.747 0.626 -0.222 ] -[ -0.872 0.470 -0.139 ] -[ 0.136 0.987 0.083 ] -[ -0.235 0.972 0.029 ] -[ -0.003 1.000 -0.006 ] -[ -0.271 0.959 0.085 ] -[ -0.872 0.470 -0.139 ] -[ -0.960 0.155 -0.231 ] -[ 0.995 0.055 0.077 ] -[ 0.187 0.982 0.013 ] -[ 0.872 0.449 0.195 ] -[ 0.134 0.904 0.405 ] -[ 1.000 -0.005 -0.002 ] -[ -0.661 -0.498 -0.561 ] -[ -0.189 -0.408 -0.893 ] -[ -0.461 -0.451 -0.764 ] -[ 0.399 0.907 0.132 ] -[ 0.399 0.907 0.132 ] -[ -0.990 -0.112 -0.081 ] -[ -0.641 -0.460 -0.614 ] -[ -0.976 -0.092 -0.199 ] -[ -0.990 -0.112 -0.081 ] -[ -0.661 -0.498 -0.561 ] -[ 0.233 -0.788 -0.570 ] -[ 0.315 -0.885 -0.344 ] -[ -0.108 -0.598 -0.794 ] -[ 0.977 0.122 -0.173 ] -[ 0.399 0.907 0.132 ] -[ -0.270 -0.931 -0.246 ] -[ 0.399 0.907 0.132 ] -[ -0.824 -0.426 -0.374 ] -[ -0.976 -0.092 -0.199 ] -[ 0.892 -0.324 -0.314 ] -[ 0.399 0.907 0.132 ] -[ -0.824 -0.426 -0.374 ] -[ 0.892 -0.324 -0.314 ] -[ -0.831 0.538 0.143 ] -[ -0.824 -0.426 -0.374 ] -[ 0.399 0.907 0.132 ] -[ -0.824 -0.426 -0.374 ] -[ -0.108 -0.598 -0.794 ] -[ 0.892 -0.324 -0.314 ] -[ -0.831 0.538 0.143 ] -[ 1.000 -0.005 -0.002 ] -[ 0.213 -0.816 -0.537 ] -[ -0.791 0.230 0.568 ] -[ 0.392 -0.810 0.435 ] -[ -0.839 -0.529 0.129 ] -[ -0.990 -0.112 -0.081 ] -[ 0.654 -0.689 0.311 ] -[ 0.654 -0.689 0.311 ] -[ 0.892 -0.324 -0.314 ] -[ -0.108 -0.598 -0.794 ] -[ 0.387 -0.889 -0.246 ] -[ 0.941 -0.337 0.019 ] -[ 0.977 0.122 -0.173 ] -[ -0.976 -0.092 -0.199 ] -[ -0.839 -0.529 0.129 ] -[ 0.941 -0.337 0.019 ] -[ 0.387 -0.889 -0.246 ] -[ -0.108 -0.598 -0.794 ] -[ 0.315 -0.885 -0.344 ] -[ 0.387 -0.889 -0.246 ] -[ -0.899 -0.283 0.336 ] -[ -0.747 0.558 0.361 ] -[ -0.823 -0.290 -0.489 ] -[ -0.594 -0.015 -0.804 ] -[ -0.643 -0.691 -0.331 ] -[ 0.640 -0.187 -0.745 ] -[ -0.839 -0.529 0.129 ] -[ -0.823 -0.290 -0.489 ] -[ -0.643 -0.691 -0.331 ] -[ -0.839 -0.529 0.129 ] -[ -0.971 -0.196 -0.137 ] -[ -0.212 -0.656 -0.724 ] -[ -0.899 -0.283 0.336 ] -[ -0.233 -0.973 0.010 ] -[ -0.028 -1.000 -0.008 ] -[ -0.277 -0.960 -0.038 ] -[ 0.392 -0.810 0.435 ] -[ -0.990 -0.112 -0.081 ] -[ 0.654 -0.689 0.311 ] -[ -0.971 -0.196 -0.137 ] -[ -0.643 -0.691 -0.331 ] -[ -0.978 -0.146 -0.147 ] -[ -0.971 -0.196 -0.137 ] -[ 0.315 -0.885 -0.344 ] -[ 0.175 -0.984 0.040 ] -[ 0.872 0.449 0.195 ] -[ 0.213 -0.816 -0.537 ] -[ 1.000 -0.005 -0.002 ] -[ 0.872 0.449 0.195 ] -[ 0.213 -0.816 -0.537 ] -[ -0.226 -0.973 -0.035 ] -[ -0.296 -0.950 -0.100 ] -[ -0.999 0.028 -0.021 ] -[ -0.997 0.066 0.026 ] -[ -0.999 0.028 -0.021 ] -[ -0.997 0.066 0.026 ] -[ -0.087 0.994 0.065 ] -[ -0.123 0.989 0.087 ] -[ 0.058 -0.998 0.018 ] -[ -0.159 -0.986 -0.046 ] -[ -0.356 -0.908 -0.223 ] -[ -0.356 -0.908 -0.223 ] -[ -0.067 0.994 0.084 ] -[ 0.040 0.999 0.014 ] -[ -0.087 0.994 0.065 ] -[ -0.123 0.989 0.087 ] -[ -0.019 1.000 0.014 ] -[ -0.033 0.999 0.005 ] -[ -0.998 0.017 0.058 ] -[ -1.000 0.009 0.013 ] -[ -0.998 0.017 0.058 ] -[ -1.000 0.009 0.013 ] -[ -0.051 -0.998 0.048 ] -[ -0.095 -0.992 0.078 ] -[ -0.226 -0.973 -0.035 ] -[ -0.296 -0.950 -0.100 ] -[ 0.040 0.999 0.014 ] -[ 0.014 0.999 0.037 ] -[ 0.090 0.994 0.062 ] -[ 0.058 -0.998 0.018 ] -[ 0.025 -0.999 -0.029 ] -[ 0.090 0.994 0.062 ] -[ -0.271 0.953 0.137 ] -[ -0.200 0.976 0.086 ] -[ -0.999 -0.033 0.018 ] -[ -0.997 -0.075 -0.030 ] -[ -0.997 -0.075 -0.030 ] -[ -0.999 -0.033 0.018 ] -[ -0.103 -0.993 -0.052 ] -[ -0.146 -0.987 -0.068 ] -[ -0.200 0.976 0.086 ] -[ 0.039 0.998 0.055 ] -[ -0.118 0.987 0.108 ] -[ -0.118 0.987 0.108 ] -[ -0.314 0.920 0.233 ] -[ -0.314 0.920 0.233 ] -[ -0.045 -0.993 -0.107 ] -[ 0.042 -0.999 0.012 ] -[ -0.146 -0.987 -0.068 ] -[ -0.103 -0.993 -0.052 ] -[ -0.007 -0.999 0.054 ] -[ -0.004 -0.999 0.050 ] -[ -0.990 -0.137 -0.019 ] -[ -0.110 0.993 -0.041 ] -[ -0.990 -0.137 -0.019 ] -[ -0.072 0.997 -0.011 ] -[ -0.271 0.953 0.137 ] -[ 0.042 -0.999 0.012 ] -[ 0.046 -0.999 0.022 ] -[ 0.075 -0.997 -0.007 ] -[ -0.013 1.000 0.022 ] -[ 0.075 -0.997 -0.007 ] -[ 0.077 0.997 0.005 ] -[ 0.078 0.994 0.081 ] -[ 0.996 -0.077 0.054 ] -[ 0.996 -0.077 0.054 ] -[ 0.015 -1.000 -0.005 ] -[ -0.008 -0.999 0.040 ] -[ -0.008 -0.999 0.040 ] -[ 0.949 0.315 0.004 ] -[ 0.949 0.315 0.004 ] -[ 0.077 0.997 0.005 ] -[ 0.207 0.978 -0.036 ] -[ 0.069 0.994 0.084 ] -[ 0.998 -0.050 0.044 ] -[ 0.998 -0.050 0.044 ] -[ 0.079 -0.994 -0.074 ] -[ 0.177 -0.984 0.012 ] -[ 0.177 -0.984 0.012 ] -[ 0.106 -0.976 0.188 ] -[ 0.992 -0.044 0.119 ] -[ 0.992 -0.044 0.119 ] -[ 0.207 0.978 -0.036 ] -[ 0.038 0.999 0.015 ] -[ 0.703 0.711 -0.015 ] -[ -0.011 1.000 0.016 ] -[ -0.914 -0.144 0.380 ] -[ -0.124 -0.991 0.049 ] -[ -0.124 -0.991 0.049 ] -[ -0.914 -0.144 0.380 ] -[ -0.062 -0.995 0.082 ] -[ -0.100 -0.987 0.129 ] -[ -0.068 -0.997 0.036 ] -[ -0.058 -0.998 0.031 ] -[ -0.068 -0.997 0.036 ] -[ -0.058 -0.998 0.031 ] -[ -0.027 -0.999 0.031 ] -[ -0.023 -0.999 0.041 ] -[ 0.118 -0.990 0.080 ] -[ 0.176 0.982 -0.064 ] -[ 0.118 -0.990 0.080 ] -[ 0.176 0.982 -0.064 ] -[ 0.049 0.998 -0.025 ] -[ 0.017 1.000 -0.007 ] -[ 0.038 0.999 0.015 ] -[ 0.703 0.711 -0.015 ] -[ 0.049 0.999 0.015 ] -[ 0.025 0.999 0.047 ] -[ 0.998 -0.001 -0.058 ] -[ 0.998 -0.001 -0.058 ] -[ 0.054 -0.997 -0.063 ] -[ 0.112 -0.993 0.042 ] -[ 0.112 -0.993 0.042 ] -[ 0.025 -0.993 0.115 ] -[ 0.436 0.899 0.049 ] -[ 0.436 0.899 0.049 ] -[ 0.049 0.999 0.015 ] -[ 0.069 -0.997 0.019 ] -[ 0.113 -0.993 -0.030 ] -[ 0.995 0.087 -0.054 ] -[ 0.995 0.087 -0.054 ] -[ -0.008 0.999 0.036 ] -[ 0.004 1.000 -0.002 ] -[ 0.004 1.000 -0.002 ] -[ 0.997 -0.082 -0.012 ] -[ 0.997 -0.082 -0.012 ] -[ 0.069 -0.997 0.019 ] -[ 0.200 -0.978 0.061 ] -[ 0.106 -0.994 -0.039 ] -[ 0.997 0.062 -0.043 ] -[ 0.997 0.062 -0.043 ] -[ 0.058 0.994 0.096 ] -[ 0.172 0.985 0.029 ] -[ 0.119 0.977 -0.175 ] -[ 0.172 0.985 0.029 ] -[ 0.991 0.053 -0.122 ] -[ 0.991 0.053 -0.122 ] -[ 0.200 -0.978 0.061 ] -[ 0.703 0.711 -0.015 ] -[ 0.177 -0.984 0.005 ] -[ 0.060 -0.998 -0.005 ] -[ -0.005 -0.998 0.059 ] -[ -0.980 -0.089 -0.179 ] -[ 0.617 -0.764 0.189 ] -[ 0.617 -0.764 0.189 ] -[ -0.980 -0.089 -0.179 ] -[ 0.019 0.990 -0.137 ] -[ 0.140 0.945 -0.295 ] -[ 0.617 -0.764 0.189 ] -[ 0.019 0.990 -0.137 ] -[ 0.140 0.945 -0.295 ] -[ -0.063 0.998 0.002 ] -[ -0.044 0.999 -0.004 ] -[ -0.044 0.999 -0.004 ] -[ -0.063 0.998 0.002 ] -[ -0.016 1.000 -0.026 ] -[ -0.011 0.999 -0.036 ] -[ 0.199 0.977 -0.080 ] -[ 0.227 -0.973 0.042 ] -[ 0.227 -0.973 0.042 ] -[ 0.199 0.977 -0.080 ] -[ 0.063 -0.998 -0.000 ] -[ 0.133 -0.990 0.044 ] -[ 0.177 -0.984 0.005 ] -[ 0.703 0.711 -0.015 ] -[ 0.048 -0.999 0.010 ] -[ 0.063 -0.998 -0.006 ] -[ 0.998 0.023 0.060 ] -[ 0.998 0.023 0.060 ] -[ 0.035 0.996 0.079 ] -[ 0.113 0.994 -0.003 ] -[ 0.113 0.994 -0.003 ] -[ 0.037 0.994 -0.107 ] -[ 0.521 -0.849 -0.092 ] -[ 0.521 -0.849 -0.092 ] -[ 0.048 -0.999 0.010 ] -[ -0.584 0.689 0.429 ] -[ -0.273 0.957 -0.098 ] -[ -0.424 0.166 0.890 ] -[ 0.315 0.750 0.581 ] -[ 0.494 0.393 0.775 ] -[ -0.584 0.689 0.429 ] -[ 0.315 0.750 0.581 ] -[ -0.219 -0.852 0.476 ] -[ 0.660 0.348 0.666 ] -[ 0.660 0.348 0.666 ] -[ -0.244 -0.938 0.245 ] -[ -0.219 -0.852 0.476 ] -[ -0.266 -0.960 -0.084 ] -[ -0.109 -0.988 -0.105 ] -[ 0.029 -0.996 -0.078 ] -[ -0.273 0.957 -0.098 ] -[ 0.121 0.989 0.087 ] -[ 0.081 0.992 -0.097 ] -[ 0.067 0.992 -0.107 ] -[ 1.000 -0.019 -0.014 ] -[ 0.131 -0.983 0.126 ] -[ 0.131 -0.983 0.126 ] -[ 1.000 -0.019 -0.014 ] -[ 0.091 -0.995 0.045 ] -[ 0.082 -0.991 0.109 ] -[ -0.244 -0.938 0.245 ] -[ 0.130 0.990 0.051 ] -[ 0.940 -0.325 0.105 ] -[ 0.940 -0.325 0.105 ] -[ 0.146 -0.988 -0.053 ] -[ 0.006 0.990 0.140 ] -[ -0.157 0.988 0.005 ] -[ -0.157 0.988 0.005 ] -[ 0.029 -0.996 -0.078 ] -[ 0.146 -0.988 -0.053 ] -[ 0.029 -0.996 -0.078 ] -[ -0.109 -0.988 -0.105 ] -[ -0.266 -0.960 -0.084 ] -[ -0.356 -0.933 0.042 ] -[ -0.244 -0.938 0.245 ] -[ 0.091 -0.995 0.045 ] -[ 0.121 -0.983 -0.139 ] -[ -0.219 -0.852 0.476 ] -[ -0.244 -0.938 0.245 ] -[ 0.121 -0.983 -0.139 ] -[ -0.219 -0.852 0.476 ] -[ 0.815 0.561 0.149 ] -[ 0.494 0.393 0.775 ] -[ 0.494 0.393 0.775 ] -[ 0.815 0.561 0.149 ] -[ 0.003 0.943 0.332 ] -[ 0.078 0.954 0.288 ] -[ -0.584 0.689 0.429 ] -[ 0.121 0.989 0.087 ] -[ -0.273 0.957 -0.098 ] -[ -0.994 -0.079 0.081 ] -[ -0.994 -0.079 0.081 ] -[ 0.130 0.990 0.051 ] -[ -0.356 -0.933 0.042 ] -[ 0.006 0.990 0.140 ] -[ -0.227 -0.973 -0.034 ] -[ -0.441 -0.837 0.325 ] -[ -0.424 -0.166 -0.890 ] -[ 0.428 -0.712 -0.556 ] -[ -0.441 -0.837 0.325 ] -[ 0.442 0.522 0.730 ] -[ 0.428 -0.712 -0.556 ] -[ 0.442 0.522 0.730 ] -[ -0.555 0.831 0.040 ] -[ 0.701 -0.303 -0.646 ] -[ 0.442 0.522 0.730 ] -[ 0.701 -0.303 -0.646 ] -[ 0.428 -0.712 -0.556 ] -[ -0.189 0.929 0.318 ] -[ 0.701 -0.303 -0.646 ] -[ -0.555 0.831 0.040 ] -[ -0.109 0.989 0.104 ] -[ -0.228 0.973 0.027 ] -[ 0.026 0.997 0.072 ] -[ 0.121 -0.979 -0.166 ] -[ -0.227 -0.973 -0.034 ] -[ 0.231 -0.965 -0.127 ] -[ 0.255 -0.962 -0.092 ] -[ 0.992 0.122 -0.000 ] -[ 0.327 0.941 -0.088 ] -[ 0.992 0.122 -0.000 ] -[ 0.327 0.941 -0.088 ] -[ 0.126 0.992 0.019 ] -[ 0.149 0.989 -0.018 ] -[ 0.149 0.989 -0.018 ] -[ -0.189 0.929 0.318 ] -[ 0.126 0.992 0.019 ] -[ 0.144 -0.964 -0.224 ] -[ 0.981 0.165 -0.097 ] -[ 0.981 0.165 -0.097 ] -[ 0.149 0.984 0.096 ] -[ -0.022 -0.974 -0.225 ] -[ 0.257 -0.952 -0.167 ] -[ 0.257 -0.952 -0.167 ] -[ 0.026 0.997 0.072 ] -[ 0.149 0.984 0.096 ] -[ -0.321 0.946 -0.042 ] -[ 0.056 0.972 0.230 ] -[ -0.555 0.831 0.040 ] -[ 0.725 -0.665 -0.181 ] -[ 0.442 0.522 0.730 ] -[ 0.725 -0.665 -0.181 ] -[ -0.441 -0.837 0.325 ] -[ 0.108 -0.960 -0.257 ] -[ 0.442 0.522 0.730 ] -[ 0.121 -0.979 -0.166 ] -[ -0.441 -0.837 0.325 ] -[ -0.992 0.094 -0.078 ] -[ -0.992 0.094 -0.078 ] -[ 0.144 -0.964 -0.224 ] -[ -0.321 0.946 -0.042 ] -[ -0.022 -0.974 -0.225 ] -[ 0.268 -0.487 -0.831 ] -[ -0.618 0.310 -0.723 ] -[ 0.399 -0.465 -0.791 ] -[ 0.097 0.661 -0.744 ] -[ 0.322 0.669 -0.670 ] -[ 0.268 -0.487 -0.831 ] -[ 0.262 0.381 -0.887 ] -[ 0.322 0.669 -0.670 ] -[ 0.097 0.661 -0.744 ] -[ 0.399 -0.465 -0.791 ] -[ -0.121 0.583 -0.804 ] -[ -0.175 0.680 -0.712 ] -[ 0.004 0.655 -0.756 ] -[ -0.006 0.596 -0.803 ] -[ 0.004 0.655 -0.756 ] -[ -0.711 0.450 -0.540 ] -[ -0.006 0.596 -0.803 ] -[ -0.711 0.450 -0.540 ] -[ 0.375 -0.927 -0.013 ] -[ 0.584 0.174 -0.793 ] -[ -0.006 0.596 -0.803 ] -[ 0.375 -0.927 -0.013 ] -[ 0.375 -0.927 -0.013 ] -[ 0.399 -0.465 -0.791 ] -[ -0.618 0.310 -0.723 ] -[ -0.175 0.680 -0.712 ] -[ -0.618 0.310 -0.723 ] -[ 0.322 0.669 -0.670 ] -[ 0.004 0.655 -0.756 ] -[ 0.322 0.669 -0.670 ] -[ 0.262 0.381 -0.887 ] -[ 0.399 -0.465 -0.791 ] -[ -0.121 0.583 -0.804 ] -[ 0.004 0.655 -0.756 ] -[ -0.006 0.596 -0.803 ] -[ -0.190 -0.442 0.876 ] -[ 0.269 0.488 0.831 ] -[ 0.340 0.311 0.888 ] -[ 0.300 -0.533 0.791 ] -[ 0.097 -0.661 0.744 ] -[ 0.149 -0.378 0.914 ] -[ 0.269 0.488 0.831 ] -[ 0.300 -0.533 0.791 ] -[ 0.097 -0.661 0.744 ] -[ 0.340 0.311 0.888 ] -[ 0.214 -0.559 0.801 ] -[ -0.121 -0.581 0.805 ] -[ -0.055 -0.560 0.826 ] -[ -0.055 -0.560 0.826 ] -[ 0.549 -0.571 0.610 ] -[ 0.104 -0.574 0.812 ] -[ 0.104 -0.574 0.812 ] -[ 0.549 -0.571 0.610 ] -[ 0.308 0.909 -0.281 ] -[ 0.827 -0.017 0.562 ] -[ 0.340 0.311 0.888 ] -[ 0.308 0.909 -0.281 ] -[ -0.190 -0.442 0.876 ] -[ 0.214 -0.559 0.801 ] -[ -0.190 -0.442 0.876 ] -[ 0.300 -0.533 0.791 ] -[ 0.300 -0.533 0.791 ] -[ -0.055 -0.560 0.826 ] -[ 0.149 -0.378 0.914 ] -[ -0.055 -0.560 0.826 ] -[ 0.104 -0.574 0.812 ] -[ 0.104 -0.574 0.812 ] -[ 0.308 0.909 -0.281 ] -[ 0.340 0.311 0.888 ] -[ -0.121 -0.581 0.805 ] -[ 0.962 -0.232 0.145 ] -[ 0.999 0.051 0.002 ] -[ 0.971 -0.195 0.136 ] -[ 0.971 -0.195 0.136 ] -[ 0.999 0.051 0.002 ] -[ 0.997 -0.068 -0.030 ] -[ 0.996 0.059 -0.062 ] -[ -0.970 0.086 0.225 ] -[ 0.996 0.059 -0.062 ] -[ -0.970 0.086 0.225 ] -[ -0.974 0.103 0.204 ] -[ -0.980 0.157 0.118 ] -[ -0.974 0.103 0.204 ] -[ -0.980 0.157 0.118 ] -[ -0.993 -0.018 -0.121 ] -[ 0.962 -0.232 0.145 ] -[ -0.993 -0.018 -0.121 ] -[ 0.962 -0.232 0.145 ] -[ 0.971 -0.195 0.136 ] -[ -0.999 -0.038 0.033 ] -[ -0.990 0.137 -0.041 ] -[ -0.990 0.137 -0.041 ] -[ -0.993 -0.018 -0.121 ] -[ -0.999 -0.038 0.033 ] -[ 0.971 -0.195 0.136 ] -[ -0.956 -0.127 0.264 ] -[ -0.994 0.090 0.057 ] -[ -0.987 -0.018 0.163 ] -[ -0.994 0.090 0.057 ] -[ 0.165 0.808 -0.566 ] -[ -0.987 -0.018 0.163 ] -[ 0.165 0.808 -0.566 ] -[ 0.995 0.101 0.004 ] -[ 1.000 -0.018 -0.023 ] -[ 0.997 0.078 -0.026 ] -[ 0.939 0.200 0.279 ] -[ -0.990 0.051 0.132 ] -[ 0.939 0.200 0.279 ] -[ -0.990 0.051 0.132 ] -[ -0.990 -0.131 -0.061 ] -[ -0.966 0.179 0.187 ] -[ -0.990 -0.131 -0.061 ] -[ -0.966 0.179 0.187 ] -[ -0.991 -0.007 0.134 ] -[ -0.977 0.188 -0.101 ] -[ -0.994 0.090 0.057 ] -[ -0.977 0.188 -0.101 ] -[ 0.995 0.101 0.004 ] -[ -0.987 -0.018 0.163 ] -[ 0.994 -0.101 -0.033 ] -[ 0.919 0.249 0.306 ] -[ 0.919 0.249 0.306 ] -[ 0.939 0.200 0.279 ] -[ -0.897 0.251 -0.365 ] -[ -0.897 0.251 -0.365 ] -[ -0.897 0.251 -0.365 ] -[ -0.956 -0.127 0.264 ] -[ -0.753 -0.592 -0.286 ] -[ -0.955 0.215 -0.203 ] -[ 0.863 -0.429 0.266 ] -[ 0.966 -0.227 0.120 ] -[ -0.753 -0.592 -0.286 ] -[ 0.863 -0.429 0.266 ] -[ 0.948 -0.107 0.299 ] -[ -0.040 -0.946 -0.322 ] -[ 0.980 -0.179 0.084 ] -[ 0.948 -0.107 0.299 ] -[ 0.980 -0.179 0.084 ] -[ 1.000 -0.004 0.002 ] -[ 0.224 -0.788 -0.573 ] -[ -0.964 -0.125 -0.234 ] -[ -0.964 -0.125 -0.234 ] -[ 0.224 -0.788 -0.573 ] -[ -0.971 -0.138 -0.197 ] -[ -0.981 -0.158 -0.110 ] -[ -0.981 -0.158 -0.110 ] -[ -0.971 -0.138 -0.197 ] -[ -0.066 -0.639 -0.766 ] -[ -0.040 -0.946 -0.322 ] -[ -0.040 -0.946 -0.322 ] -[ -0.066 -0.639 -0.766 ] -[ 0.980 -0.179 0.084 ] -[ 0.993 0.089 -0.083 ] -[ -0.126 -0.741 -0.659 ] -[ -0.126 -0.741 -0.659 ] -[ 0.993 0.089 -0.083 ] -[ 0.966 -0.227 0.120 ] -[ 1.000 0.019 0.003 ] -[ 0.986 0.164 -0.002 ] -[ 0.986 0.164 -0.002 ] -[ -0.952 0.304 -0.019 ] -[ -0.952 0.304 -0.019 ] -[ -0.998 0.011 -0.058 ] -[ -0.753 -0.592 -0.286 ] -[ -0.126 -0.741 -0.659 ] -[ 0.966 -0.227 0.120 ] -[ 0.863 -0.429 0.266 ] -[ 0.994 0.105 0.010 ] -[ 0.921 -0.244 -0.304 ] -[ 0.986 0.164 -0.002 ] -[ 0.921 -0.244 -0.304 ] -[ -0.936 0.340 0.089 ] -[ -0.952 0.304 -0.019 ] -[ 0.986 0.164 -0.002 ] -[ -0.936 0.340 0.089 ] -[ -0.936 0.340 0.089 ] -[ -0.955 0.215 -0.203 ] ->>> for v in data.roots[0].children[1].data.bitangents: print(v) -[ 0.541 -0.061 0.839 ] -[ -0.097 -0.038 0.995 ] -[ 0.796 -0.077 0.600 ] -[ 0.832 -0.078 0.549 ] -[ 0.126 0.954 0.271 ] -[ 0.030 0.952 0.304 ] -[ 0.111 -0.001 0.994 ] -[ 0.076 -0.005 0.997 ] -[ -0.780 -0.006 0.626 ] -[ -0.831 -0.007 0.556 ] -[ 0.126 0.954 0.271 ] -[ 0.030 0.952 0.304 ] -[ 0.777 -0.075 0.625 ] -[ 0.102 -0.048 0.994 ] -[ 0.890 -0.081 0.448 ] -[ 0.954 -0.083 0.289 ] -[ -0.034 -0.999 0.011 ] -[ 0.812 0.221 0.541 ] -[ 0.016 0.948 0.317 ] -[ 0.307 -0.946 0.102 ] -[ -0.063 0.070 0.996 ] -[ -0.404 -0.822 -0.401 ] -[ -0.241 -0.970 0.037 ] -[ -0.063 0.070 0.996 ] -[ -0.234 0.001 0.972 ] -[ 0.643 0.468 0.606 ] -[ 0.643 0.468 0.606 ] -[ 0.822 -0.078 0.565 ] -[ 0.812 0.221 0.541 ] -[ -0.404 -0.822 -0.401 ] -[ -0.063 0.070 0.996 ] -[ 0.660 -0.068 0.748 ] -[ 0.739 -0.073 0.670 ] -[ -0.083 -0.050 0.995 ] -[ 0.959 -0.280 0.041 ] -[ 0.788 -0.343 0.511 ] -[ -0.331 -0.663 0.672 ] -[ 0.060 -0.072 0.996 ] -[ -0.867 -0.245 0.434 ] -[ -0.879 -0.182 0.441 ] -[ -0.331 -0.663 0.672 ] -[ 0.788 -0.343 0.511 ] -[ -0.611 -0.238 -0.755 ] -[ 0.643 0.468 0.606 ] -[ -0.404 -0.822 -0.401 ] -[ -0.394 -0.023 0.919 ] -[ -0.017 -0.046 0.999 ] -[ -0.031 -0.989 0.145 ] -[ 0.202 -0.051 0.978 ] -[ 0.800 -0.076 0.596 ] -[ -0.031 -0.986 0.163 ] -[ -0.031 -0.985 0.170 ] -[ 0.033 -0.579 0.814 ] -[ -0.776 -0.003 0.631 ] -[ -0.895 -0.012 0.446 ] -[ -0.951 -0.019 0.309 ] -[ -0.034 -0.999 0.011 ] -[ -0.757 0.297 0.583 ] -[ 0.016 0.948 0.317 ] -[ -0.246 -0.222 0.943 ] -[ -0.241 -0.970 0.037 ] -[ -0.404 -0.822 -0.401 ] -[ -0.140 -0.057 0.988 ] -[ -0.246 -0.222 0.943 ] -[ -0.627 0.479 0.614 ] -[ -0.627 0.479 0.614 ] -[ -0.830 -0.007 0.558 ] -[ -0.404 -0.822 -0.401 ] -[ -0.757 0.297 0.583 ] -[ -0.738 0.000 0.675 ] -[ -0.663 0.004 0.748 ] -[ 0.093 -0.012 0.996 ] -[ 0.959 -0.280 0.041 ] -[ -0.822 -0.284 0.493 ] -[ -0.822 -0.284 0.493 ] -[ -0.046 -0.026 0.999 ] -[ -0.822 -0.284 0.493 ] -[ -0.404 -0.822 -0.401 ] -[ 0.365 -0.741 0.564 ] -[ 0.118 -0.323 0.939 ] -[ -0.031 -0.989 0.145 ] -[ -0.212 0.002 0.977 ] -[ -0.809 -0.005 0.588 ] -[ -0.031 -0.986 0.163 ] -[ -0.031 -0.985 0.170 ] -[ -0.775 -0.007 0.632 ] -[ -0.882 0.001 0.471 ] -[ -0.735 -0.008 0.678 ] -[ -0.097 -0.038 0.995 ] -[ -0.510 -0.018 0.860 ] -[ -0.016 -0.996 0.092 ] -[ -0.028 -0.999 -0.017 ] -[ 0.880 -0.029 0.475 ] -[ 0.773 -0.025 0.633 ] -[ 0.732 -0.023 0.681 ] -[ 0.111 -0.001 0.994 ] -[ 0.076 -0.005 0.997 ] -[ -0.028 -0.999 -0.017 ] -[ -0.016 -0.996 0.092 ] -[ -0.046 0.920 0.390 ] -[ 0.989 0.149 0.022 ] -[ -0.081 0.918 0.388 ] -[ -0.681 0.192 0.707 ] -[ -0.081 0.918 0.388 ] -[ 0.989 0.149 0.022 ] -[ 0.016 0.988 0.157 ] -[ -0.840 -0.002 0.543 ] -[ 0.717 0.122 0.687 ] -[ 0.016 0.988 0.157 ] -[ 0.842 -0.028 0.538 ] -[ 0.691 -0.365 0.624 ] -[ -0.081 0.918 0.388 ] -[ -0.046 0.920 0.390 ] -[ 0.905 0.404 0.129 ] -[ -0.924 0.300 0.236 ] -[ 0.691 -0.365 0.624 ] -[ -0.924 0.300 0.236 ] -[ 0.691 -0.365 0.624 ] -[ -0.521 -0.842 0.142 ] -[ -0.081 0.918 0.388 ] -[ -0.924 0.300 0.236 ] -[ -0.046 0.920 0.390 ] -[ -0.286 -0.026 0.958 ] -[ -0.669 -0.003 0.743 ] -[ -0.559 -0.016 0.829 ] -[ -0.363 0.836 -0.411 ] -[ 0.691 -0.365 0.624 ] -[ -0.924 0.300 0.236 ] -[ -0.081 0.918 0.388 ] -[ -0.631 -0.005 0.776 ] -[ -0.695 0.628 -0.350 ] -[ 0.102 -0.048 0.994 ] -[ -0.017 -0.046 0.999 ] -[ -0.356 0.385 0.852 ] -[ -0.120 0.964 0.237 ] -[ -0.120 0.964 0.237 ] -[ 0.691 -0.365 0.624 ] -[ -0.081 0.918 0.388 ] -[ -0.120 0.964 0.237 ] -[ 0.905 0.404 0.129 ] -[ 0.691 -0.365 0.624 ] -[ -0.356 0.385 0.852 ] -[ -0.363 0.836 -0.411 ] -[ 0.920 0.343 -0.190 ] -[ 0.754 0.563 -0.338 ] -[ -0.695 0.628 -0.350 ] -[ -0.356 0.385 0.852 ] -[ -0.081 0.918 0.388 ] -[ -0.681 0.192 0.707 ] -[ 0.389 -0.867 0.311 ] -[ -0.588 -0.467 0.661 ] -[ 0.754 0.563 -0.338 ] -[ 0.331 0.933 0.138 ] -[ 0.691 -0.365 0.624 ] -[ -0.530 -0.828 0.182 ] -[ 0.389 -0.867 0.311 ] -[ -0.063 0.070 0.996 ] -[ 0.307 -0.946 0.102 ] -[ -0.588 -0.467 0.661 ] -[ -0.588 -0.467 0.661 ] -[ -0.063 0.070 0.996 ] -[ -0.588 -0.467 0.661 ] -[ -0.432 -0.604 0.670 ] -[ -0.394 -0.023 0.919 ] -[ -0.083 -0.050 0.995 ] -[ -0.867 0.000 0.498 ] -[ 0.060 -0.072 0.996 ] -[ -0.432 -0.604 0.670 ] -[ -0.234 0.001 0.972 ] -[ -0.081 0.918 0.388 ] -[ 0.202 -0.051 0.978 ] -[ -0.489 0.792 0.366 ] -[ -0.955 0.008 0.297 ] -[ 0.005 0.746 0.665 ] -[ 0.082 -0.792 0.606 ] -[ 0.258 -0.898 0.356 ] -[ 0.236 -0.892 0.385 ] -[ -0.786 0.264 0.559 ] -[ -0.786 0.264 0.559 ] -[ 0.034 -0.765 0.643 ] -[ 0.131 -0.854 0.503 ] -[ -0.022 -0.862 0.506 ] -[ 0.034 -0.765 0.643 ] -[ 0.082 -0.792 0.606 ] -[ 0.033 -0.579 0.814 ] -[ 0.118 -0.323 0.939 ] -[ 0.671 -0.633 0.386 ] -[ -0.046 0.920 0.390 ] -[ -0.786 0.264 0.559 ] -[ 0.691 -0.365 0.624 ] -[ -0.786 0.264 0.559 ] -[ 0.487 -0.869 -0.083 ] -[ -0.022 -0.862 0.506 ] -[ 0.451 0.604 0.657 ] -[ -0.786 0.264 0.559 ] -[ 0.487 -0.869 -0.083 ] -[ 0.451 0.604 0.657 ] -[ -0.521 -0.842 0.142 ] -[ 0.487 -0.869 -0.083 ] -[ -0.786 0.264 0.559 ] -[ 0.487 -0.869 -0.083 ] -[ 0.671 -0.633 0.386 ] -[ 0.451 0.604 0.657 ] -[ -0.521 -0.842 0.142 ] -[ 0.005 0.746 0.665 ] -[ 0.960 0.073 0.271 ] -[ -0.611 -0.238 -0.755 ] -[ 0.920 0.343 -0.190 ] -[ 0.455 -0.551 0.700 ] -[ 0.034 -0.765 0.643 ] -[ 0.754 0.563 -0.338 ] -[ 0.754 0.563 -0.338 ] -[ 0.451 0.604 0.657 ] -[ 0.671 -0.633 0.386 ] -[ 0.717 0.122 0.687 ] -[ 0.331 0.933 0.138 ] -[ -0.046 0.920 0.390 ] -[ -0.022 -0.862 0.506 ] -[ 0.455 -0.551 0.700 ] -[ 0.331 0.933 0.138 ] -[ 0.717 0.122 0.687 ] -[ 0.671 -0.633 0.386 ] -[ 0.118 -0.323 0.939 ] -[ 0.717 0.122 0.687 ] -[ 0.389 -0.867 0.311 ] -[ -0.530 -0.828 0.182 ] -[ 0.097 -0.919 0.383 ] -[ 0.015 -1.000 0.008 ] -[ -0.246 -0.222 0.943 ] -[ -0.241 -0.970 0.037 ] -[ 0.455 -0.551 0.700 ] -[ 0.097 -0.919 0.383 ] -[ -0.246 -0.222 0.943 ] -[ 0.455 -0.551 0.700 ] -[ 0.054 -0.740 0.671 ] -[ 0.365 -0.741 0.564 ] -[ 0.389 -0.867 0.311 ] -[ 0.093 -0.012 0.996 ] -[ 0.867 -0.028 0.498 ] -[ -0.046 -0.026 0.999 ] -[ 0.920 0.343 -0.190 ] -[ 0.034 -0.765 0.643 ] -[ 0.754 0.563 -0.338 ] -[ 0.054 -0.740 0.671 ] -[ -0.246 -0.222 0.943 ] -[ -0.140 -0.057 0.988 ] -[ 0.054 -0.740 0.671 ] -[ 0.118 -0.323 0.939 ] -[ -0.212 0.002 0.977 ] -[ -0.489 0.792 0.366 ] -[ 0.960 0.073 0.271 ] -[ 0.005 0.746 0.665 ] -[ -0.489 0.792 0.366 ] -[ 0.960 0.073 0.271 ] -[ -0.298 0.035 0.954 ] -[ -0.392 0.025 0.919 ] -[ 0.021 0.956 0.292 ] -[ 0.071 0.959 0.273 ] -[ 0.021 0.956 0.292 ] -[ 0.071 0.959 0.273 ] -[ 0.368 -0.028 0.930 ] -[ 0.376 -0.034 0.926 ] -[ 0.233 0.031 0.972 ] -[ -0.577 0.055 0.815 ] -[ -0.926 0.310 0.216 ] -[ -0.926 0.310 0.216 ] -[ 0.700 -0.014 0.714 ] -[ -0.051 -0.012 0.999 ] -[ 0.368 -0.028 0.930 ] -[ 0.376 -0.034 0.926 ] -[ -0.568 -0.022 0.823 ] -[ -0.566 -0.023 0.824 ] -[ -0.016 -1.000 0.011 ] -[ -0.009 -0.999 0.041 ] -[ -0.016 -1.000 0.011 ] -[ -0.009 -0.999 0.041 ] -[ 0.646 0.003 0.763 ] -[ 0.605 0.004 0.796 ] -[ -0.298 0.035 0.954 ] -[ -0.392 0.025 0.919 ] -[ -0.051 -0.012 0.999 ] -[ -0.467 -0.026 0.884 ] -[ -0.967 0.072 0.246 ] -[ 0.233 0.031 0.972 ] -[ 0.764 -0.000 0.645 ] -[ -0.967 0.072 0.246 ] -[ 0.405 -0.016 0.914 ] -[ 0.310 -0.021 0.950 ] -[ -0.026 0.956 0.292 ] -[ -0.080 0.957 0.278 ] -[ -0.080 0.957 0.278 ] -[ -0.026 0.956 0.292 ] -[ -0.365 -0.011 0.931 ] -[ -0.373 -0.009 0.928 ] -[ 0.310 -0.021 0.950 ] -[ -0.236 -0.045 0.971 ] -[ 0.587 -0.018 0.810 ] -[ 0.587 -0.018 0.810 ] -[ 0.941 0.269 0.206 ] -[ 0.941 0.269 0.206 ] -[ -0.702 -0.045 0.711 ] -[ 0.050 0.014 0.999 ] -[ -0.373 -0.009 0.928 ] -[ -0.365 -0.011 0.931 ] -[ 0.571 0.040 0.820 ] -[ 0.500 0.041 0.865 ] -[ 0.136 -0.990 0.032 ] -[ -0.600 -0.034 0.799 ] -[ 0.136 -0.990 0.032 ] -[ -0.593 -0.034 0.804 ] -[ 0.405 -0.016 0.914 ] -[ 0.050 0.014 0.999 ] -[ 0.465 0.041 0.884 ] -[ 0.975 0.072 0.210 ] -[ -0.772 -0.024 0.635 ] -[ 0.975 0.072 0.210 ] -[ 0.321 -0.030 0.947 ] -[ -0.574 -0.022 0.819 ] -[ 0.073 0.994 0.078 ] -[ 0.073 0.994 0.078 ] -[ 0.602 0.005 0.798 ] -[ -0.329 0.040 0.943 ] -[ -0.329 0.040 0.943 ] -[ 0.315 -0.949 0.035 ] -[ 0.315 -0.949 0.035 ] -[ 0.321 -0.030 0.947 ] -[ 0.283 -0.025 0.959 ] -[ -0.653 -0.019 0.758 ] -[ 0.045 0.994 0.100 ] -[ 0.045 0.994 0.100 ] -[ 0.699 0.002 0.716 ] -[ 0.124 0.034 0.992 ] -[ 0.124 0.034 0.992 ] -[ -0.728 0.052 0.684 ] -[ -0.075 -0.961 0.268 ] -[ -0.075 -0.961 0.268 ] -[ 0.283 -0.025 0.959 ] -[ -0.034 -0.014 0.999 ] -[ -0.547 0.555 0.627 ] -[ -0.635 -0.019 0.772 ] -[ 0.184 -0.980 0.072 ] -[ 0.992 -0.125 -0.032 ] -[ 0.992 -0.125 -0.032 ] -[ 0.184 -0.980 0.072 ] -[ 0.811 -0.002 0.585 ] -[ 0.801 -0.002 0.599 ] -[ -0.058 0.040 0.998 ] -[ -0.323 0.049 0.945 ] -[ -0.058 0.040 0.998 ] -[ -0.323 0.049 0.945 ] -[ -0.869 0.039 0.492 ] -[ -0.852 0.041 0.522 ] -[ -0.993 -0.118 -0.001 ] -[ 0.927 -0.143 0.347 ] -[ -0.993 -0.118 -0.001 ] -[ 0.927 -0.143 0.347 ] -[ 0.554 -0.006 0.832 ] -[ 0.420 -0.001 0.907 ] -[ -0.034 -0.014 0.999 ] -[ -0.547 0.555 0.627 ] -[ 0.029 -0.016 0.999 ] -[ -0.679 -0.017 0.734 ] -[ 0.006 0.997 0.079 ] -[ 0.006 0.997 0.079 ] -[ 0.759 0.000 0.651 ] -[ -0.012 0.041 0.999 ] -[ -0.012 0.041 0.999 ] -[ -0.831 0.044 0.554 ] -[ 0.815 -0.417 0.401 ] -[ 0.815 -0.417 0.401 ] -[ 0.029 -0.016 0.999 ] -[ -0.323 -0.005 0.946 ] -[ 0.568 0.040 0.822 ] -[ -0.083 0.994 0.078 ] -[ -0.083 0.994 0.078 ] -[ -0.602 -0.033 0.798 ] -[ 0.330 0.001 0.944 ] -[ 0.330 0.001 0.944 ] -[ -0.081 -0.996 0.033 ] -[ -0.081 -0.996 0.033 ] -[ -0.323 -0.005 0.946 ] -[ -0.289 0.000 0.957 ] -[ 0.647 0.039 0.761 ] -[ -0.057 0.993 0.101 ] -[ -0.057 0.993 0.101 ] -[ -0.701 -0.028 0.713 ] -[ -0.131 -0.006 0.991 ] -[ 0.726 0.035 0.687 ] -[ -0.131 -0.006 0.991 ] -[ 0.084 -0.960 0.266 ] -[ 0.084 -0.960 0.266 ] -[ -0.289 0.000 0.957 ] -[ -0.547 0.555 0.627 ] -[ 0.011 0.008 1.000 ] -[ 0.693 0.038 0.720 ] -[ 0.707 0.038 0.707 ] -[ 0.080 -0.995 0.060 ] -[ 0.768 0.637 0.066 ] -[ 0.768 0.637 0.066 ] -[ 0.080 -0.995 0.060 ] -[ -0.813 0.095 0.575 ] -[ -0.795 0.285 0.536 ] -[ 0.768 0.637 0.066 ] -[ -0.813 0.095 0.575 ] -[ -0.795 0.285 0.536 ] -[ 0.060 0.002 0.998 ] -[ 0.324 0.018 0.946 ] -[ 0.324 0.018 0.946 ] -[ 0.060 0.002 0.998 ] -[ 0.870 0.027 0.493 ] -[ 0.852 0.028 0.523 ] -[ 0.980 -0.199 0.006 ] -[ -0.915 -0.198 0.351 ] -[ -0.915 -0.198 0.351 ] -[ 0.980 -0.199 0.006 ] -[ -0.552 -0.035 0.833 ] -[ -0.526 -0.033 0.850 ] -[ 0.011 0.008 1.000 ] -[ -0.547 0.555 0.627 ] -[ -0.030 0.008 0.999 ] -[ 0.676 0.039 0.736 ] -[ -0.027 0.997 0.077 ] -[ -0.027 0.997 0.077 ] -[ -0.761 -0.025 0.649 ] -[ 0.008 0.003 1.000 ] -[ 0.008 0.003 1.000 ] -[ 0.831 0.029 0.556 ] -[ -0.764 -0.511 0.394 ] -[ -0.764 -0.511 0.394 ] -[ -0.030 0.008 0.999 ] -[ 0.713 0.182 0.677 ] -[ 0.308 0.183 0.934 ] -[ 0.741 0.629 0.236 ] -[ 0.949 -0.267 -0.170 ] -[ 0.858 -0.366 -0.361 ] -[ 0.713 0.182 0.677 ] -[ 0.949 -0.267 -0.170 ] -[ 0.643 0.241 0.727 ] -[ 0.659 -0.693 -0.291 ] -[ 0.659 -0.693 -0.291 ] -[ -0.029 0.260 0.965 ] -[ 0.643 0.241 0.727 ] -[ 0.535 -0.220 0.815 ] -[ 0.664 -0.151 0.732 ] -[ -0.428 -0.083 0.900 ] -[ 0.308 0.183 0.934 ] -[ -0.001 -0.088 0.996 ] -[ 0.570 0.034 0.821 ] -[ 0.700 0.029 0.714 ] -[ -0.017 -0.990 0.138 ] -[ -0.978 -0.108 0.176 ] -[ -0.978 -0.108 0.176 ] -[ -0.017 -0.990 0.138 ] -[ -0.478 -0.003 0.878 ] -[ -0.594 0.039 0.804 ] -[ -0.029 0.260 0.965 ] -[ 0.092 -0.063 0.994 ] -[ -0.330 -0.943 0.035 ] -[ -0.330 -0.943 0.035 ] -[ -0.070 -0.064 0.995 ] -[ -0.304 -0.131 0.943 ] -[ 0.916 0.144 0.374 ] -[ 0.916 0.144 0.374 ] -[ -0.428 -0.083 0.900 ] -[ -0.070 -0.064 0.995 ] -[ -0.428 -0.083 0.900 ] -[ 0.664 -0.151 0.732 ] -[ 0.535 -0.220 0.815 ] -[ 0.934 -0.357 0.001 ] -[ -0.029 0.260 0.965 ] -[ -0.478 -0.003 0.878 ] -[ 0.568 -0.047 0.822 ] -[ 0.643 0.241 0.727 ] -[ -0.029 0.260 0.965 ] -[ 0.568 -0.047 0.822 ] -[ 0.643 0.241 0.727 ] -[ 0.580 -0.779 -0.238 ] -[ 0.858 -0.366 -0.361 ] -[ 0.858 -0.366 -0.361 ] -[ 0.580 -0.779 -0.238 ] -[ -0.940 -0.111 0.324 ] -[ -0.697 -0.154 0.700 ] -[ 0.713 0.182 0.677 ] -[ -0.001 -0.088 0.996 ] -[ 0.308 0.183 0.934 ] -[ 0.063 -0.980 -0.191 ] -[ 0.063 -0.980 -0.191 ] -[ 0.092 -0.063 0.994 ] -[ 0.934 -0.357 0.001 ] -[ -0.304 -0.131 0.943 ] -[ -0.343 0.047 0.938 ] -[ 0.344 0.177 0.922 ] -[ -0.741 0.629 0.236 ] -[ -0.903 -0.356 -0.240 ] -[ 0.344 0.177 0.922 ] -[ 0.886 -0.126 -0.446 ] -[ -0.903 -0.356 -0.240 ] -[ 0.886 -0.126 -0.446 ] -[ -0.393 -0.304 0.868 ] -[ -0.616 -0.714 -0.333 ] -[ 0.886 -0.126 -0.446 ] -[ -0.616 -0.714 -0.333 ] -[ -0.903 -0.356 -0.240 ] -[ 0.157 -0.291 0.944 ] -[ -0.616 -0.714 -0.333 ] -[ -0.393 -0.304 0.868 ] -[ -0.664 -0.151 0.732 ] -[ -0.553 -0.152 0.819 ] -[ 0.428 -0.076 0.901 ] -[ 0.011 -0.166 0.986 ] -[ -0.343 0.047 0.938 ] -[ -0.527 -0.233 0.817 ] -[ -0.655 -0.242 0.716 ] -[ 0.121 -0.983 0.139 ] -[ 0.932 -0.305 0.198 ] -[ 0.121 -0.983 0.139 ] -[ 0.932 -0.305 0.198 ] -[ 0.470 -0.077 0.879 ] -[ 0.581 -0.072 0.811 ] -[ 0.581 -0.072 0.811 ] -[ 0.157 -0.291 0.944 ] -[ 0.470 -0.077 0.879 ] -[ -0.068 -0.236 0.970 ] -[ 0.171 -0.984 0.051 ] -[ 0.171 -0.984 0.051 ] -[ 0.064 -0.106 0.992 ] -[ 0.304 -0.221 0.927 ] -[ -0.893 -0.300 0.335 ] -[ -0.893 -0.300 0.335 ] -[ 0.428 -0.076 0.901 ] -[ 0.064 -0.106 0.992 ] -[ -0.947 -0.321 -0.001 ] -[ -0.578 -0.156 0.801 ] -[ -0.393 -0.304 0.868 ] -[ -0.688 -0.693 -0.215 ] -[ 0.886 -0.126 -0.446 ] -[ -0.688 -0.693 -0.215 ] -[ 0.344 0.177 0.922 ] -[ 0.693 -0.113 0.712 ] -[ 0.886 -0.126 -0.446 ] -[ 0.011 -0.166 0.986 ] -[ 0.344 0.177 0.922 ] -[ -0.078 -0.978 -0.193 ] -[ -0.078 -0.978 -0.193 ] -[ -0.068 -0.236 0.970 ] -[ -0.947 -0.321 -0.001 ] -[ 0.304 -0.221 0.927 ] -[ 0.922 -0.121 0.368 ] -[ -0.779 -0.364 0.510 ] -[ 0.273 -0.763 0.586 ] -[ -0.690 0.584 0.428 ] -[ 0.092 0.682 0.726 ] -[ 0.922 -0.121 0.368 ] -[ 0.959 0.002 0.285 ] -[ 0.092 0.682 0.726 ] -[ -0.690 0.584 0.428 ] -[ 0.273 -0.763 0.586 ] -[ -0.201 0.779 0.595 ] -[ -0.916 0.152 0.371 ] -[ 0.447 0.675 0.587 ] -[ 0.986 0.140 0.096 ] -[ 0.447 0.675 0.587 ] -[ 0.700 0.375 -0.608 ] -[ 0.986 0.140 0.096 ] -[ 0.700 0.375 -0.608 ] -[ -0.167 -0.082 0.983 ] -[ 0.778 -0.398 0.486 ] -[ 0.986 0.140 0.096 ] -[ -0.167 -0.082 0.983 ] -[ -0.167 -0.082 0.983 ] -[ 0.273 -0.763 0.586 ] -[ -0.779 -0.364 0.510 ] -[ -0.916 0.152 0.371 ] -[ -0.779 -0.364 0.510 ] -[ 0.092 0.682 0.726 ] -[ 0.447 0.675 0.587 ] -[ 0.092 0.682 0.726 ] -[ 0.959 0.002 0.285 ] -[ 0.273 -0.763 0.586 ] -[ -0.201 0.779 0.595 ] -[ 0.447 0.675 0.587 ] -[ 0.986 0.140 0.096 ] -[ 0.976 -0.181 0.121 ] -[ -0.922 -0.120 0.369 ] -[ -0.344 -0.837 0.425 ] -[ -0.150 0.793 0.590 ] -[ 0.690 0.584 0.428 ] -[ -0.983 0.046 0.180 ] -[ -0.922 -0.120 0.369 ] -[ -0.150 0.793 0.590 ] -[ 0.690 0.584 0.428 ] -[ -0.344 -0.837 0.425 ] -[ 0.908 0.417 0.048 ] -[ 0.201 0.780 0.593 ] -[ -0.444 0.755 0.483 ] -[ -0.444 0.755 0.483 ] -[ -0.818 -0.220 0.531 ] -[ -0.992 -0.118 0.044 ] -[ -0.992 -0.118 0.044 ] -[ -0.818 -0.220 0.531 ] -[ 0.271 0.199 0.942 ] -[ -0.512 -0.434 0.741 ] -[ -0.344 -0.837 0.425 ] -[ 0.271 0.199 0.942 ] -[ 0.976 -0.181 0.121 ] -[ 0.908 0.417 0.048 ] -[ 0.976 -0.181 0.121 ] -[ -0.150 0.793 0.590 ] -[ -0.150 0.793 0.590 ] -[ -0.444 0.755 0.483 ] -[ -0.983 0.046 0.180 ] -[ -0.444 0.755 0.483 ] -[ -0.992 -0.118 0.044 ] -[ -0.992 -0.118 0.044 ] -[ 0.271 0.199 0.942 ] -[ -0.344 -0.837 0.425 ] -[ 0.201 0.780 0.593 ] -[ -0.167 -0.918 -0.361 ] -[ 0.008 -0.193 0.981 ] -[ -0.237 -0.840 0.489 ] -[ -0.237 -0.840 0.489 ] -[ 0.008 -0.193 0.981 ] -[ 0.020 -0.132 0.991 ] -[ 0.014 0.602 0.798 ] -[ -0.145 -0.955 -0.260 ] -[ 0.014 0.602 0.798 ] -[ -0.145 -0.955 -0.260 ] -[ 0.088 -0.656 0.750 ] -[ 0.057 -0.349 0.935 ] -[ 0.088 -0.656 0.750 ] -[ 0.057 -0.349 0.935 ] -[ -0.104 0.639 0.762 ] -[ -0.167 -0.918 -0.361 ] -[ -0.104 0.639 0.762 ] -[ -0.167 -0.918 -0.361 ] -[ -0.237 -0.840 0.489 ] -[ -0.044 0.978 -0.204 ] -[ 0.049 0.594 0.803 ] -[ 0.049 0.594 0.803 ] -[ -0.104 0.639 0.762 ] -[ -0.044 0.978 -0.204 ] -[ -0.237 -0.840 0.489 ] -[ 0.061 0.794 0.605 ] -[ 0.106 0.904 0.415 ] -[ -0.061 0.961 -0.269 ] -[ 0.106 0.904 0.415 ] -[ 0.986 -0.115 0.124 ] -[ -0.061 0.961 -0.269 ] -[ 0.986 -0.115 0.124 ] -[ 0.065 -0.662 0.747 ] -[ 0.024 0.031 0.999 ] -[ 0.024 0.028 0.999 ] -[ -0.328 0.762 0.559 ] -[ -0.097 -0.925 -0.367 ] -[ -0.328 0.762 0.559 ] -[ -0.097 -0.925 -0.367 ] -[ 0.093 -0.901 0.425 ] -[ 0.051 -0.576 0.816 ] -[ 0.093 -0.901 0.425 ] -[ 0.051 -0.576 0.816 ] -[ 0.134 0.012 0.991 ] -[ 0.084 0.773 0.629 ] -[ 0.106 0.904 0.415 ] -[ 0.084 0.773 0.629 ] -[ 0.065 -0.662 0.747 ] -[ -0.061 0.961 -0.269 ] -[ 0.026 -0.072 0.997 ] -[ -0.386 0.727 0.567 ] -[ -0.386 0.727 0.567 ] -[ -0.328 0.762 0.559 ] -[ -0.376 -0.866 0.329 ] -[ -0.376 -0.866 0.329 ] -[ -0.376 -0.866 0.329 ] -[ 0.061 0.794 0.605 ] -[ -0.657 0.689 0.305 ] -[ 0.040 0.776 0.629 ] -[ -0.480 -0.860 0.172 ] -[ -0.255 -0.783 0.567 ] -[ -0.657 0.689 0.305 ] -[ -0.480 -0.860 0.172 ] -[ -0.314 -0.168 0.934 ] -[ -0.976 -0.033 0.217 ] -[ -0.197 -0.843 0.500 ] -[ -0.314 -0.168 0.934 ] -[ -0.197 -0.843 0.500 ] -[ -0.002 -0.052 0.999 ] -[ 0.970 0.121 0.212 ] -[ 0.185 -0.949 -0.254 ] -[ 0.185 -0.949 -0.254 ] -[ 0.970 0.121 0.212 ] -[ -0.070 -0.622 0.780 ] -[ -0.048 -0.349 0.936 ] -[ -0.048 -0.349 0.936 ] -[ -0.070 -0.622 0.780 ] -[ 0.996 0.006 -0.091 ] -[ -0.976 -0.033 0.217 ] -[ -0.976 -0.033 0.217 ] -[ 0.996 0.006 -0.091 ] -[ -0.197 -0.843 0.500 ] -[ 0.118 -0.861 0.494 ] -[ -0.976 -0.026 0.216 ] -[ -0.976 -0.026 0.216 ] -[ 0.118 -0.861 0.494 ] -[ -0.255 -0.783 0.567 ] -[ -0.004 0.031 1.000 ] -[ -0.127 0.770 0.625 ] -[ -0.127 0.770 0.625 ] -[ -0.282 -0.858 0.430 ] -[ -0.282 -0.858 0.430 ] -[ -0.058 0.012 0.998 ] -[ -0.657 0.689 0.305 ] -[ -0.976 -0.026 0.216 ] -[ -0.255 -0.783 0.567 ] -[ -0.480 -0.860 0.172 ] -[ -0.002 -0.069 0.998 ] -[ 0.381 0.729 0.568 ] -[ -0.127 0.770 0.625 ] -[ 0.381 0.729 0.568 ] -[ -0.257 -0.836 0.485 ] -[ -0.282 -0.858 0.430 ] -[ -0.127 0.770 0.625 ] -[ -0.257 -0.836 0.485 ] -[ -0.257 -0.836 0.485 ] -[ 0.040 0.776 0.629 ] diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 329fc32f4..5c127c76c 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -92,8 +92,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', 'spells/nif/ffvt3rskin.txt', - 'spells/nif/fix_tangentspace.txt', - 'spells/nif/fix_tangentspace_series_parallel.txt', 'spells/nif/fix_texturepath.txt', 'spells/nif/modify_allbonepriorities.txt', 'spells/nif/modify_delbranches.txt', From 1a50834dbe0fcec07e7aaa351fa42ee9f3c295c7 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Mon, 14 Aug 2017 19:44:56 +0100 Subject: [PATCH 12/30] Migrate texture path spell test to nose. --- tests/spells/nif/fix/test_texturepath.py | 37 ++++++++++++++++++++++++ tests/spells/nif/fix_texturepath.txt | 37 ------------------------ tests/test_doctests.py | 1 - 3 files changed, 37 insertions(+), 38 deletions(-) create mode 100644 tests/spells/nif/fix/test_texturepath.py delete mode 100644 tests/spells/nif/fix_texturepath.txt diff --git a/tests/spells/nif/fix/test_texturepath.py b/tests/spells/nif/fix/test_texturepath.py new file mode 100644 index 000000000..bed1262ef --- /dev/null +++ b/tests/spells/nif/fix/test_texturepath.py @@ -0,0 +1,37 @@ +"""Tests for the fix_texturepath spell""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase, assert_tuple_values + +class TestFixTangentSpace(BaseFileTestCase): + """Invoke the fix_texturepath spell check through nif toaster""" + + def setUp(self): + super(TestFixTangentSpace, self).setUp() + self.src_name = "test_fix_texturepath.nif" + super(TestFixTangentSpace, self).copyFile() + super(TestFixTangentSpace, self).readNifData() + + def test_non_interactive_fix_texture_path(self): + call_niftoaster("--raise", "fix_texturepath", "fix_addtangentspace", "--dry-run", "--noninteractive", + "--verbose=1", self.dest_file) + + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_texturepath.nif === + pyffi.toaster:INFO: --- fix_texturepath --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Sphere] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: fixed file name 'path\test1.dds' + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: fixed file name 'an\other\path\also\backslashes\test2.dds' + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: fixed file name 'evil\rants\IS\not\good\no\no\test4.dds' + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: fixed file name 'doubleslash\test6.dds' + pyffi.toaster:INFO: writing to temporary file + pyffi.toaster:INFO:Finished. + """ + diff --git a/tests/spells/nif/fix_texturepath.txt b/tests/spells/nif/fix_texturepath.txt deleted file mode 100644 index 6a42308c8..000000000 --- a/tests/spells/nif/fix_texturepath.txt +++ /dev/null @@ -1,37 +0,0 @@ -Doctests for the fix_texturepath spell -====================================== - - ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(4): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "nif") ->>> import sys ->>> script = os.path.join(script_dir, "niftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> nif_dir = "tests/spells/nif/files/" - ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "fix_texturepath", "--dry-run", "--noninteractive", nif_dir + "test_fix_texturepath.nif"] ->>> niftoaster.NifToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_texturepath.nif === -pyffi.toaster:INFO: --- fix_texturepath --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Sphere] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: fixed file name 'path\test1.dds' -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: fixed file name 'an\other\path\also\backslashes\test2.dds' -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: fixed file name 'evil\rants\IS\not\good\no\no\test4.dds' -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: fixed file name 'doubleslash\test6.dds' -pyffi.toaster:INFO: writing to temporary file -pyffi.toaster:INFO:Finished. - diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 5c127c76c..981f716cf 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -92,7 +92,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', 'spells/nif/ffvt3rskin.txt', - 'spells/nif/fix_texturepath.txt', 'spells/nif/modify_allbonepriorities.txt', 'spells/nif/modify_delbranches.txt', 'spells/nif/modify_delvertexcolor.txt', From 906f25ac9421bcd9f6a17ffb70a060cc2ace1923 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Mon, 14 Aug 2017 20:02:07 +0100 Subject: [PATCH 13/30] Migrate modify bone priorities path spell test to nose. --- tests/spells/nif/modify/__init__.py | 0 .../nif/modify/test_allbonepriorities.py | 49 +++++++++++++++++++ tests/spells/nif/modify_allbonepriorities.txt | 45 ----------------- tests/test_doctests.py | 1 - 4 files changed, 49 insertions(+), 46 deletions(-) create mode 100644 tests/spells/nif/modify/__init__.py create mode 100644 tests/spells/nif/modify/test_allbonepriorities.py delete mode 100644 tests/spells/nif/modify_allbonepriorities.txt diff --git a/tests/spells/nif/modify/__init__.py b/tests/spells/nif/modify/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spells/nif/modify/test_allbonepriorities.py b/tests/spells/nif/modify/test_allbonepriorities.py new file mode 100644 index 000000000..05f6baee7 --- /dev/null +++ b/tests/spells/nif/modify/test_allbonepriorities.py @@ -0,0 +1,49 @@ +from nose.tools import assert_equals + +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase + + +class TestModifyAllBonePriorities(BaseFileTestCase): + """Tests for the modify_allbonepriorities spell""" + + def setUp(self): + super(TestModifyAllBonePriorities, self).setUp() + self.src_name = "test_fix_cleanstringpalette.nif" + super(TestModifyAllBonePriorities, self).copyFile() + super(TestModifyAllBonePriorities, self).readNifData() + + def test_non_interactive_modify_all_bone_priorities(self): + """Run the spell that modifies the bone prioirities""" + + # check current controller blocks + assert_equals([block.priority + for block in self.data.roots[0].controller.controller_sequences[0].controlled_blocks], + [0, 0]) + assert_equals([block.priority + for block in self.data.roots[0].controller.controller_sequences[1].controlled_blocks], + [0, 0]) + + call_niftoaster("--raise", "modify_allbonepriorities", "-a", "50", "--dry-run", "--noninteractive", + "--verbose=1", self.dest_file) + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_cleanstringpalette.nif === + pyffi.toaster:INFO: --- modify_allbonepriorities --- + pyffi.toaster:INFO: ~~~ NiNode [TestCleanStringPalette] ~~~ + pyffi.toaster:INFO: ~~~ NiControllerManager [] ~~~ + pyffi.toaster:INFO: ~~~ NiControllerSequence [Scared] ~~~ + pyffi.toaster:INFO: b'Test' priority changed to 50 + pyffi.toaster:INFO: b'Test NonAccum' priority changed to 50 + pyffi.toaster:INFO: ~~~ NiControllerSequence [Death] ~~~ + pyffi.toaster:INFO: b'Test' priority changed to 50 + pyffi.toaster:INFO: b'Test NonAccum' priority changed to 50 + pyffi.toaster:INFO: writing tests/spells/nif/files..._test_fix_cleanstringpalette.nif + pyffi.toaster:INFO:Finished. + """ + + assert_equals([block.priority + for block in self.data.roots[0].controller.controller_sequences[0].controlled_blocks], + [50, 50]) + assert_equals([block.priority + for block in self.data.roots[0].controller.controller_sequences[1].controlled_blocks], + [50, 50]) diff --git a/tests/spells/nif/modify_allbonepriorities.txt b/tests/spells/nif/modify_allbonepriorities.txt deleted file mode 100644 index 70d9e3ec0..000000000 --- a/tests/spells/nif/modify_allbonepriorities.txt +++ /dev/null @@ -1,45 +0,0 @@ -Doctests for the modify_allbonepriorities spell -=============================================== - -NifToaster check ----------------- - ->>> nif_dir = "tests/spells/nif/files/" ->>> filename = nif_dir + "test_fix_cleanstringpalette.nif" ->>> outfilename = nif_dir + "_test_fix_cleanstringpalette.nif" ->>> # check current string palette ->>> from pyffi.formats.nif import NifFormat ->>> data = NifFormat.Data() ->>> data.read(open(filename, "rb")) ->>> print([block.priority for block in data.roots[0].controller.controller_sequences[0].controlled_blocks]) -[0, 0] ->>> print([block.priority for block in data.roots[0].controller.controller_sequences[1].controlled_blocks]) -[0, 0] ->>> # update ->>> import sys ->>> sys.path.append("scripts/nif") ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "--prefix", "_", "--noninteractive", "modify_allbonepriorities", "-a", "50", filename] ->>> niftoaster.NifToaster().cli() # doctest: +REPORT_NDIFF +ELLIPSIS -pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_cleanstringpalette.nif === -pyffi.toaster:INFO: --- modify_allbonepriorities --- -pyffi.toaster:INFO: ~~~ NiNode [TestCleanStringPalette] ~~~ -pyffi.toaster:INFO: ~~~ NiControllerManager [] ~~~ -pyffi.toaster:INFO: ~~~ NiControllerSequence [Scared] ~~~ -pyffi.toaster:INFO: b'Test' priority changed to 50 -pyffi.toaster:INFO: b'Test NonAccum' priority changed to 50 -pyffi.toaster:INFO: ~~~ NiControllerSequence [Death] ~~~ -pyffi.toaster:INFO: b'Test' priority changed to 50 -pyffi.toaster:INFO: b'Test NonAccum' priority changed to 50 -pyffi.toaster:INFO: writing tests/spells/nif/files..._test_fix_cleanstringpalette.nif -pyffi.toaster:INFO:Finished. ->>> # check new bone priorities ->>> data = NifFormat.Data() ->>> data.read(open(outfilename, "rb")) ->>> print([block.priority for block in data.roots[0].controller.controller_sequences[0].controlled_blocks]) -[50, 50] ->>> print([block.priority for block in data.roots[0].controller.controller_sequences[1].controlled_blocks]) -[50, 50] ->>> # clean up ->>> import os ->>> os.remove(outfilename) diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 981f716cf..970adf0f8 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -92,7 +92,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', 'spells/nif/ffvt3rskin.txt', - 'spells/nif/modify_allbonepriorities.txt', 'spells/nif/modify_delbranches.txt', 'spells/nif/modify_delvertexcolor.txt', 'spells/nif/modify_substitutestringpalette.txt', From 5c9b09cef234da9d689c05ea268127680fe0c96d Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Thu, 17 Aug 2017 19:09:11 +0100 Subject: [PATCH 14/30] Fix bug where file was reading original file instead of copy. --- tests/spells/nif/fix/test_tangentspace.py | 2 +- tests/utils/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/spells/nif/fix/test_tangentspace.py b/tests/spells/nif/fix/test_tangentspace.py index 8b87da45f..2ce5029a6 100644 --- a/tests/spells/nif/fix/test_tangentspace.py +++ b/tests/spells/nif/fix/test_tangentspace.py @@ -1507,6 +1507,7 @@ def test_explicit_fix_tangent_space(self): pyffi.toaster: INFO: adding tangent space """ + class TestFixDeltaTangentSpace(BaseFileTestCase): """Invoke the fix_texturepath spell check through nif toaster""" @@ -1531,7 +1532,6 @@ def test_non_interactive_fix_addtangentspace(self): pyffi.toaster:INFO:Finished. """ - def test_non_interactive_fix_addtangentspace_series(self): call_niftoaster("--raise", "fix_deltangentspace", "fix_addtangentspace", "--series", diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index 261dfc0c4..de1ba0143 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -37,7 +37,7 @@ def copyFile(self): def readNifData(self): self.data = NifFormat.Data() - stream = open(self.src_file, "rb") + stream = open(self.dest_file, "rb") self.data.read(stream) def tearDown(self): From 0941242b492ec4082f479acd9c2377a57b0c8644 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Thu, 17 Aug 2017 19:10:47 +0100 Subject: [PATCH 15/30] Migrate delete branch spell test to nose. --- tests/spells/nif/modify/test_delbranches.py | 182 ++++++++++++++++++++ tests/spells/nif/modify_delbranches.txt | 175 ------------------- tests/test_doctests.py | 1 - 3 files changed, 182 insertions(+), 176 deletions(-) create mode 100644 tests/spells/nif/modify/test_delbranches.py delete mode 100644 tests/spells/nif/modify_delbranches.txt diff --git a/tests/spells/nif/modify/test_delbranches.py b/tests/spells/nif/modify/test_delbranches.py new file mode 100644 index 000000000..02a75a9fd --- /dev/null +++ b/tests/spells/nif/modify/test_delbranches.py @@ -0,0 +1,182 @@ +"""Tests for the modify_delbranches spell and its friends""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase + +from nose.tools import assert_equals + + +class TestModifyDelBranches(BaseFileTestCase): + """Invoke the modify_delbranches spell check through nif toaster""" + + def setUp(self): + super(TestModifyDelBranches, self).setUp() + self.src_name = "test_opt_mergeduplicates.nif" + super(TestModifyDelBranches, self).copyFile() + super(TestModifyDelBranches, self).readNifData() + + def test_non_interactive_modify_delbranches(self): + props = ['NiNode', 'NiVertexColorProperty', 'NiZBufferProperty', 'NiStencilProperty', 'NiDitherProperty', + 'NiNode', 'NiZBufferProperty', 'NiVertexColorProperty', 'NiStencilProperty', 'NiDitherProperty', + 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiSpecularProperty', + 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', + 'NiSpecularProperty', 'NiAlphaProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', + 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', 'NiAlphaProperty', 'NiTriStripsData', + 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', + 'NiDitherProperty', 'NiTriStripsData'] + + blocks = [block.__class__.__name__ for block in self.data.blocks] + assert_equals(props, blocks) + + # strip properties + call_niftoaster("--raise", "modify_delbranches", "-x", "NiProperty", "--noninteractive", "--verbose=1", + self.dest_file) + + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_opt_mergeduplicates.nif === + pyffi.toaster:INFO: --- modify_delbranches --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiZBufferProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiStencilProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ + pyffi.toaster:INFO: ~~~ NiZBufferProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiStencilProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 0] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiSpecularProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 1] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiMaterialProperty [AlsoRed] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiSpecularProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiAlphaProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 2] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Skin] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiWireframeProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiAlphaProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 3] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiWireframeProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ + pyffi.toaster:INFO: writing tests/spells/nif/files..._test_opt_mergeduplicates.nif + pyffi.toaster:INFO:Finished. + """ + # check that file no longer has properties + super(TestModifyDelBranches, self).readNifData() + blocks = [block.__class__.__name__ for block in self.data.blocks] + + branches = ['NiNode', 'NiNode', 'NiTriStrips', 'NiTriStripsData', 'NiTriStrips', + 'NiTriStripsData', 'NiTriStrips', 'NiTriStripsData', 'NiTriStrips', 'NiTriStripsData'] + assert_equals(blocks, branches) + + def test_non_interactive_modify_delalphaprop(self): + """NifToaster modify_delalphaprop check""" + + blocks = [block.__class__.__name__ for block in self.data.blocks] + # check that file has alpha properties + + branches = ['NiNode', 'NiVertexColorProperty', 'NiZBufferProperty', 'NiStencilProperty', 'NiDitherProperty', + 'NiNode', 'NiZBufferProperty', 'NiVertexColorProperty', 'NiStencilProperty', 'NiDitherProperty', + 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiSpecularProperty', + 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', + 'NiSpecularProperty', 'NiAlphaProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', + 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', 'NiAlphaProperty', + 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', + 'NiMaterialProperty', 'NiWireframeProperty', 'NiDitherProperty', 'NiTriStripsData'] + + assert_equals(blocks, branches) + + # strip properties + call_niftoaster("--raise", "modify_delalphaprop", "--noninteractive", "--verbose=1", self.dest_file) + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_opt_mergeduplicates.nif === + pyffi.toaster:INFO: --- modify_delalphaprop --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiZBufferProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiStencilProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ + pyffi.toaster:INFO: ~~~ NiZBufferProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiStencilProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 0] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ + pyffi.toaster:INFO: ~~~ NiSpecularProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 1] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [AlsoRed] ~~~ + pyffi.toaster:INFO: ~~~ NiSpecularProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiAlphaProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 2] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Skin] ~~~ + pyffi.toaster:INFO: ~~~ NiWireframeProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiAlphaProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 3] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ + pyffi.toaster:INFO: ~~~ NiWireframeProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ + pyffi.toaster:INFO: writing ..._test_opt_mergeduplicates.nif + pyffi.toaster:INFO:Finished. + """ + + super(TestModifyDelBranches, self).readNifData() + + # check that file no longer has properties + blocks = [block.__class__.__name__ for block in self.data.blocks] + branches = ['NiNode', 'NiVertexColorProperty', 'NiZBufferProperty', 'NiStencilProperty', 'NiDitherProperty', + 'NiNode', 'NiZBufferProperty', 'NiVertexColorProperty', 'NiStencilProperty', 'NiDitherProperty', + 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiSpecularProperty', + 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', + 'NiSpecularProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', + 'NiMaterialProperty', 'NiWireframeProperty', 'NiTriStripsData', 'NiTriStrips', + 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', + 'NiDitherProperty', 'NiTriStripsData'] + + assert_equals(blocks, branches) \ No newline at end of file diff --git a/tests/spells/nif/modify_delbranches.txt b/tests/spells/nif/modify_delbranches.txt deleted file mode 100644 index e5ed69aaf..000000000 --- a/tests/spells/nif/modify_delbranches.txt +++ /dev/null @@ -1,175 +0,0 @@ -Doctests for the modify_delbranches spell and its friends -========================================================= - -NifToaster modify_delbranches check ------------------------------------ - ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(3): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "nif") ->>> import sys ->>> script = os.path.join(script_dir, "niftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> nif_dir = "tests/spells/nif/files/" ->>> file_name = "test_opt_mergeduplicates.nif" ->>> file_name_full = nif_dir + file_name ->>> nif_dir_out = nif_dir + "out/" ->>> file_name_out = "_test_opt_mergeduplicates.nif" ->>> file_name_full_out = nif_dir + file_name_out - ->>> from pyffi.formats.nif import NifFormat ->>> data = NifFormat.Data() ->>> data.read(open(file_name_full, "rb")) ->>> # check that file has properties ->>> print([block.__class__.__name__ for block in data.blocks]) -['NiNode', 'NiVertexColorProperty', 'NiZBufferProperty', 'NiStencilProperty', 'NiDitherProperty', 'NiNode', 'NiZBufferProperty', 'NiVertexColorProperty', 'NiStencilProperty', 'NiDitherProperty', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiSpecularProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiSpecularProperty', 'NiAlphaProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', 'NiAlphaProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', 'NiDitherProperty', 'NiTriStripsData'] - - ->>> # strip properties ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "--prefix", "_", "--noninteractive", "-x", "NiProperty", "modify_delbranches", file_name_full] ->>> niftoaster.NifToaster().cli() # doctest: +REPORT_NDIFF +ELLIPSIS -pyffi.toaster:INFO:=== tests/spells/nif/files/test_opt_mergeduplicates.nif === -pyffi.toaster:INFO: --- modify_delbranches --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiZBufferProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiStencilProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ -pyffi.toaster:INFO: ~~~ NiZBufferProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiStencilProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 0] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiSpecularProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 1] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiMaterialProperty [AlsoRed] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiSpecularProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiAlphaProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 2] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Skin] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiWireframeProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiAlphaProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 3] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiWireframeProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ -pyffi.toaster:INFO: writing tests/spells/nif/files..._test_opt_mergeduplicates.nif -pyffi.toaster:INFO:Finished. ->>> # check that file no longer has properties ->>> data = NifFormat.Data() ->>> data.read(open(file_name_full_out, "rb")) ->>> print([block.__class__.__name__ for block in data.blocks]) -['NiNode', 'NiNode', 'NiTriStrips', 'NiTriStripsData', 'NiTriStrips', 'NiTriStripsData', 'NiTriStrips', 'NiTriStripsData', 'NiTriStrips', 'NiTriStripsData'] ->>> # clean up ->>> import os ->>> os.remove(file_name_full_out) - - -NifToaster modify_delalphaprop check ------------------------------------- - ->>> file_name = "test_opt_mergeduplicates.nif" ->>> file_name_out = "_" + file_name ->>> file_name_full = nif_dir + file_name ->>> file_name_full_out = nif_dir + file_name_out - ->>> from pyffi.formats.nif import NifFormat ->>> data = NifFormat.Data() ->>> data.read(open(file_name_full, "rb")) ->>> # check that file has alpha properties ->>> print([block.__class__.__name__ for block in data.blocks]) -['NiNode', 'NiVertexColorProperty', 'NiZBufferProperty', 'NiStencilProperty', 'NiDitherProperty', 'NiNode', 'NiZBufferProperty', 'NiVertexColorProperty', 'NiStencilProperty', 'NiDitherProperty', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiSpecularProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiSpecularProperty', 'NiAlphaProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', 'NiAlphaProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', 'NiDitherProperty', 'NiTriStripsData'] ->>> # strip properties - ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "--prefix", "_", "--noninteractive", "modify_delalphaprop", file_name_full] ->>> niftoaster.NifToaster().cli() # doctest: +REPORT_UDIFF +ELLIPSIS -pyffi.toaster:INFO:=== tests/spells/nif/files/test_opt_mergeduplicates.nif === -pyffi.toaster:INFO: --- modify_delalphaprop --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiZBufferProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiStencilProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ -pyffi.toaster:INFO: ~~~ NiZBufferProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiStencilProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 0] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ -pyffi.toaster:INFO: ~~~ NiSpecularProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 1] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [AlsoRed] ~~~ -pyffi.toaster:INFO: ~~~ NiSpecularProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiAlphaProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 2] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Skin] ~~~ -pyffi.toaster:INFO: ~~~ NiWireframeProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiAlphaProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Tri Cone 3] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiSourceTexture [] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ -pyffi.toaster:INFO: ~~~ NiWireframeProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiDitherProperty [] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ -pyffi.toaster:INFO: writing ..._test_opt_mergeduplicates.nif -pyffi.toaster:INFO:Finished. ->>> # check that file no longer has properties ->>> data = NifFormat.Data() ->>> data.read(open(file_name_full_out, "rb")) ->>> print([block.__class__.__name__ for block in data.blocks]) -['NiNode', 'NiVertexColorProperty', 'NiZBufferProperty', 'NiStencilProperty', 'NiDitherProperty', 'NiNode', 'NiZBufferProperty', 'NiVertexColorProperty', 'NiStencilProperty', 'NiDitherProperty', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiSpecularProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiSpecularProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', 'NiTriStripsData', 'NiTriStrips', 'NiTexturingProperty', 'NiSourceTexture', 'NiMaterialProperty', 'NiWireframeProperty', 'NiDitherProperty', 'NiTriStripsData'] ->>> # clean up ->>> import os ->>> os.remove(file_name_full_out) diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 970adf0f8..f61668e49 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -92,7 +92,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', 'spells/nif/ffvt3rskin.txt', - 'spells/nif/modify_delbranches.txt', 'spells/nif/modify_delvertexcolor.txt', 'spells/nif/modify_substitutestringpalette.txt', From 45b4a4edd79a411101737fd7167384ca73bb38e0 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Thu, 17 Aug 2017 22:02:35 +0100 Subject: [PATCH 16/30] Migrate delete vertex colors spell test to nose. --- .../spells/nif/modify/test_delvertexcolor.py | 47 ++++++++++++++++ tests/spells/nif/modify_delvertexcolor.txt | 55 ------------------- tests/test_doctests.py | 1 - 3 files changed, 47 insertions(+), 56 deletions(-) create mode 100644 tests/spells/nif/modify/test_delvertexcolor.py delete mode 100644 tests/spells/nif/modify_delvertexcolor.txt diff --git a/tests/spells/nif/modify/test_delvertexcolor.py b/tests/spells/nif/modify/test_delvertexcolor.py new file mode 100644 index 000000000..89cc1a9d2 --- /dev/null +++ b/tests/spells/nif/modify/test_delvertexcolor.py @@ -0,0 +1,47 @@ +"""Tests for the modify_delvertexcolor spell""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase + +from nose.tools import assert_equals, assert_false, assert_true + + +class TestModifyDelBranches(BaseFileTestCase): + """Invoke the modify_delvertexcolor spell check through nif toaster""" + + def setUp(self): + super(TestModifyDelBranches, self).setUp() + self.src_name = "test_vertexcolor.nif" + super(TestModifyDelBranches, self).copyFile() + super(TestModifyDelBranches, self).readNifData() + + def test_non_interactive_modify_delbranches(self): + """Test that we can delete vertex colors""" + blocks = [block.__class__.__name__ for block in self.data.blocks] + expected = ['NiNode', 'NiTriStrips', 'NiStencilProperty', 'NiSpecularProperty', 'NiMaterialProperty', + 'NiVertexColorProperty', 'NiTriStripsData'] + assert_equals(blocks, expected) + assert_true(self.data.roots[0].children[0].data.has_vertex_colors) + + + # delete vertex color + call_niftoaster("--raise", "modify_delvertexcolor", "--noninteractive", "--verbose=1", self.dest_file) + """ + pyffi.toaster:INFO:=== ...test_vertexcolor.nif === + pyffi.toaster:INFO: --- modify_delvertexcolor --- + pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ + pyffi.toaster:INFO: ~~~ NiTriStrips [Cube] ~~~ + pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ + pyffi.toaster:INFO: stripping this branch + pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ + pyffi.toaster:INFO: removing vertex colors + pyffi.toaster:INFO: writing ..._test_vertexcolor.nif + pyffi.toaster:INFO:Finished. + """ + + super(TestModifyDelBranches, self).readNifData() + + # check that file has no vertex color + blocks = [block.__class__.__name__ for block in self.data.blocks] + expected = ['NiNode', 'NiTriStrips', 'NiStencilProperty', 'NiSpecularProperty', 'NiMaterialProperty', 'NiTriStripsData'] + assert_equals(blocks, expected) + assert_false(self.data.roots[0].children[0].data.has_vertex_colors) diff --git a/tests/spells/nif/modify_delvertexcolor.txt b/tests/spells/nif/modify_delvertexcolor.txt deleted file mode 100644 index 1b06e9f87..000000000 --- a/tests/spells/nif/modify_delvertexcolor.txt +++ /dev/null @@ -1,55 +0,0 @@ -Doctests for the modify_delvertexcolor spell -============================================ - -NifToaster modify_delvertexcolor check --------------------------------------- - ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(3): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "nif") ->>> import sys ->>> script = os.path.join(script_dir, "niftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> nif_dir = "tests/spells/nif/files/" ->>> file_name = "test_vertexcolor.nif" ->>> file_name_full = nif_dir + file_name ->>> nif_dir_out = nif_dir + "out/" ->>> file_name_out = "_" + file_name ->>> file_name_full_out = nif_dir + file_name_out - ->>> from pyffi.formats.nif import NifFormat ->>> # check that file has vertex color ->>> data = NifFormat.Data() ->>> data.read(open(file_name_full, "rb")) ->>> print([block.__class__.__name__ for block in data.blocks]) -['NiNode', 'NiTriStrips', 'NiStencilProperty', 'NiSpecularProperty', 'NiMaterialProperty', 'NiVertexColorProperty', 'NiTriStripsData'] ->>> print(data.roots[0].children[0].data.has_vertex_colors) -True ->>> # delete vertex color ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "--prefix", "_", "--noninteractive", "modify_delvertexcolor", file_name_full] ->>> niftoaster.NifToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== ...test_vertexcolor.nif === -pyffi.toaster:INFO: --- modify_delvertexcolor --- -pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ -pyffi.toaster:INFO: ~~~ NiTriStrips [Cube] ~~~ -pyffi.toaster:INFO: ~~~ NiVertexColorProperty [] ~~~ -pyffi.toaster:INFO: stripping this branch -pyffi.toaster:INFO: ~~~ NiTriStripsData [] ~~~ -pyffi.toaster:INFO: removing vertex colors -pyffi.toaster:INFO: writing ..._test_vertexcolor.nif -pyffi.toaster:INFO:Finished. ->>> # check that file has no vertex color ->>> data = NifFormat.Data() ->>> data.read(open(file_name_full_out, "rb")) ->>> print([block.__class__.__name__ for block in data.blocks]) -['NiNode', 'NiTriStrips', 'NiStencilProperty', 'NiSpecularProperty', 'NiMaterialProperty', 'NiTriStripsData'] ->>> print(data.roots[0].children[0].data.has_vertex_colors) -False ->>> # clean up ->>> import os ->>> os.remove(file_name_full_out) diff --git a/tests/test_doctests.py b/tests/test_doctests.py index f61668e49..4f62a25ff 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -92,7 +92,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', 'spells/nif/ffvt3rskin.txt', - 'spells/nif/modify_delvertexcolor.txt', 'spells/nif/modify_substitutestringpalette.txt', # Contain outstanding issues From 81649e95e823f46064f2b9bb0035d380cb729d6a Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Thu, 17 Aug 2017 22:54:33 +0100 Subject: [PATCH 17/30] Migrate fix substitute string palette spell test to nose. --- .../nif/fix/test_substitutestringpalette.py | 45 +++++++++++++++++++ .../nif/modify_substitutestringpalette.txt | 40 ----------------- tests/test_doctests.py | 1 - 3 files changed, 45 insertions(+), 41 deletions(-) create mode 100644 tests/spells/nif/fix/test_substitutestringpalette.py delete mode 100644 tests/spells/nif/modify_substitutestringpalette.txt diff --git a/tests/spells/nif/fix/test_substitutestringpalette.py b/tests/spells/nif/fix/test_substitutestringpalette.py new file mode 100644 index 000000000..e3546eb18 --- /dev/null +++ b/tests/spells/nif/fix/test_substitutestringpalette.py @@ -0,0 +1,45 @@ +"""Tests for the modify_substitutestringpalette spell""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase + +from nose.tools import assert_true + + +class TestModifySubstitutePalette(BaseFileTestCase): + """Invoke the modify_substitutestringpalette spell check through nif toaster""" + + def setUp(self): + super(TestModifySubstitutePalette, self).setUp() + self.src_name = "test_fix_cleanstringpalette.nif" + super(TestModifySubstitutePalette, self).copyFile() + super(TestModifySubstitutePalette, self).readNifData() + + def test_non_interactive_modify_string_palette_values(self): + """Test that we can modify the string palette values""" + strings = self.data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings() + expected = [b'Test', b'Hello', b'People', b'NiTransformController', b'Test NonAccum', b'Useless', b'Crap'] + assert_true(strings, expected) + + # substitute + call_niftoaster("--raise", "modify_substitutestringpalette", "-a", "/Test/Woops", "--noninteractive", "--verbose=1", self.dest_file) + + """ + pyffi.toaster:INFO:=== tests/spells/nif/files...test_fix_cleanstringpalette.nif === + pyffi.toaster:INFO: --- modify_substitutestringpalette --- + pyffi.toaster:INFO: ~~~ NiNode [TestCleanStringPalette] ~~~ + pyffi.toaster:INFO: ~~~ NiControllerManager [] ~~~ + pyffi.toaster:INFO: parsing string palette + pyffi.toaster:INFO: b'Test' -> b'Woops' + pyffi.toaster:INFO: b'Test NonAccum' -> b'Woops NonAccum' + pyffi.toaster:INFO: b'Test' -> b'Woops' + pyffi.toaster:INFO: b'Test NonAccum' -> b'Woops NonAccum' + pyffi.toaster:INFO: writing tests/spells/nif/files..._test_fix_cleanstringpalette.nif + pyffi.toaster:INFO:Finished. + """ + + super(TestModifySubstitutePalette, self).readNifData() + + # check cleaned palette + strings = self.data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings() + expected = [b'Woops', b'NiTransformController', b'Woops NonAccum'] + assert_true(strings, expected) diff --git a/tests/spells/nif/modify_substitutestringpalette.txt b/tests/spells/nif/modify_substitutestringpalette.txt deleted file mode 100644 index f5fb23e81..000000000 --- a/tests/spells/nif/modify_substitutestringpalette.txt +++ /dev/null @@ -1,40 +0,0 @@ -Doctests for the modify_substitutestringpalette spell -===================================================== - -NifToaster check ----------------- - ->>> from pyffi.formats.nif import NifFormat ->>> nif_dir = "tests/spells/nif/files/" ->>> filename = nif_dir + "test_fix_cleanstringpalette.nif" ->>> outfilename = nif_dir + "_test_fix_cleanstringpalette.nif" ->>> # check current string palette ->>> data = NifFormat.Data() ->>> data.read(open(filename, "rb")) ->>> print(data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings()) -[b'Test', b'Hello', b'People', b'NiTransformController', b'Test NonAccum', b'Useless', b'Crap'] ->>> # substitute ->>> import sys ->>> sys.path.append("scripts/nif") ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "--prefix", "_", "--noninteractive", "modify_substitutestringpalette", "-a", "/Test/Woops", filename] ->>> niftoaster.NifToaster().cli() # doctest: +REPORT_NDIFF +ELLIPSIS -pyffi.toaster:INFO:=== tests/spells/nif/files...test_fix_cleanstringpalette.nif === -pyffi.toaster:INFO: --- modify_substitutestringpalette --- -pyffi.toaster:INFO: ~~~ NiNode [TestCleanStringPalette] ~~~ -pyffi.toaster:INFO: ~~~ NiControllerManager [] ~~~ -pyffi.toaster:INFO: parsing string palette -pyffi.toaster:INFO: b'Test' -> b'Woops' -pyffi.toaster:INFO: b'Test NonAccum' -> b'Woops NonAccum' -pyffi.toaster:INFO: b'Test' -> b'Woops' -pyffi.toaster:INFO: b'Test NonAccum' -> b'Woops NonAccum' -pyffi.toaster:INFO: writing tests/spells/nif/files..._test_fix_cleanstringpalette.nif -pyffi.toaster:INFO:Finished. ->>> # check cleaned palette ->>> data = NifFormat.Data() ->>> data.read(open(outfilename, "rb")) ->>> print(data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings()) -[b'Woops', b'NiTransformController', b'Woops NonAccum'] ->>> # clean up ->>> import os ->>> os.remove(outfilename) diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 4f62a25ff..b2ed72162 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -92,7 +92,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', 'spells/nif/ffvt3rskin.txt', - 'spells/nif/modify_substitutestringpalette.txt', # Contain outstanding issues # 'spells/egm/optimize.txt', From 06fc8e08571a7913d7811dcdb939ee3b43c4934b Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Thu, 17 Aug 2017 23:44:00 +0100 Subject: [PATCH 18/30] Migrate fix vertex weight influence test to nose. --- tests/spells/nif/ffvt3rskin.txt | 66 ------------------------ tests/spells/nif/fix/test_ffvt3rskin.py | 68 +++++++++++++++++++++++++ tests/test_doctests.py | 1 - 3 files changed, 68 insertions(+), 67 deletions(-) delete mode 100644 tests/spells/nif/ffvt3rskin.txt create mode 100644 tests/spells/nif/fix/test_ffvt3rskin.py diff --git a/tests/spells/nif/ffvt3rskin.txt b/tests/spells/nif/ffvt3rskin.txt deleted file mode 100644 index c4346e509..000000000 --- a/tests/spells/nif/ffvt3rskin.txt +++ /dev/null @@ -1,66 +0,0 @@ -Doctests for the fix_ffvt3rskinpartition spell -============================================== - ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(4): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "nif") ->>> import sys ->>> script = os.path.join(script_dir, "niftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> nif_dir = "tests/spells/nif/files/" - - ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "fix_ffvt3rskinpartition", "--dry-run", "--noninteractive", nif_dir + "test_fix_ffvt3rskinpartition.nif"] ->>> niftoaster.NifToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_ffvt3rskinpartition.nif === -pyffi.toaster:INFO: --- fix_ffvt3rskinpartition --- -pyffi.toaster:INFO: ~~~ NiNode [Bip01] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Pelvis] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine1] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine2] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Neck] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Head] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Clavicle] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L UpperArm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Forearm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Clavicle] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R UpperArm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Forearm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Thigh] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Calf] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Foot] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Toe0] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Thigh] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Calf] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Foot] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Toe0] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Body] ~~~ -pyffi.toaster:INFO: updating skin partition -pyffi.nif.nitribasedgeom:INFO:Counted minimum of 1 and maximum of 3 bones per vertex -pyffi.nif.nitribasedgeom:INFO:Imposing maximum of 4 bones per vertex. -pyffi.nif.nitribasedgeom:INFO:Imposing maximum of 4 bones per triangle (and hence, per partition). -pyffi.nif.nitribasedgeom:INFO:Creating partitions -pyffi.nif.nitribasedgeom:INFO:Created 12 small partitions. -pyffi.nif.nitribasedgeom:INFO:Merging partitions. -pyffi.nif.nitribasedgeom:INFO:Skin has 12 partitions. -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 0 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 1 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 2 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 3 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 4 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 5 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 6 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 7 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 8 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 9 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 10 -pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 11 -pyffi.toaster:INFO: writing to temporary file -pyffi.toaster:INFO:Finished. - diff --git a/tests/spells/nif/fix/test_ffvt3rskin.py b/tests/spells/nif/fix/test_ffvt3rskin.py new file mode 100644 index 000000000..dde0ce46b --- /dev/null +++ b/tests/spells/nif/fix/test_ffvt3rskin.py @@ -0,0 +1,68 @@ +"""Tests for the fix_ffvt3rskinpartition spell spell""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase + + +class TestFixVertexInfleunce(BaseFileTestCase): + """Invoke the modify_substitutestringpalette spell check through nif toaster""" + + def setUp(self): + super(TestFixVertexInfleunce, self).setUp() + self.src_name = "test_fix_ffvt3rskinpartition.nif" + super(TestFixVertexInfleunce, self).copyFile() + super(TestFixVertexInfleunce, self).readNifData() + + def test_non_interactive_fix_vertex_skin_partition(self): + """Test that we can repartition vertex weight influence""" + + # substitute + call_niftoaster("--raise", "fix_ffvt3rskinpartition", "--noninteractive", "--verbose=1", self.dest_file) + + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_ffvt3rskinpartition.nif === + pyffi.toaster:INFO: --- fix_ffvt3rskinpartition --- + pyffi.toaster:INFO: ~~~ NiNode [Bip01] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Pelvis] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine1] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine2] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Neck] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Head] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Clavicle] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L UpperArm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Forearm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Clavicle] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R UpperArm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Forearm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Thigh] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Calf] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Foot] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Toe0] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Thigh] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Calf] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Foot] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Toe0] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [Body] ~~~ + pyffi.toaster:INFO: updating skin partition + pyffi.nif.nitribasedgeom:INFO:Counted minimum of 1 and maximum of 3 bones per vertex + pyffi.nif.nitribasedgeom:INFO:Imposing maximum of 4 bones per vertex. + pyffi.nif.nitribasedgeom:INFO:Imposing maximum of 4 bones per triangle (and hence, per partition). + pyffi.nif.nitribasedgeom:INFO:Creating partitions + pyffi.nif.nitribasedgeom:INFO:Created 12 small partitions. + pyffi.nif.nitribasedgeom:INFO:Merging partitions. + pyffi.nif.nitribasedgeom:INFO:Skin has 12 partitions. + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 0 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 1 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 2 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 3 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 4 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 5 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 6 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 7 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 8 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 9 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 10 + pyffi.nif.nitribasedgeom:INFO:Optimizing triangle ordering in partition 11 + pyffi.toaster:INFO: writing to temporary file + pyffi.toaster:INFO:Finished. + """ diff --git a/tests/test_doctests.py b/tests/test_doctests.py index b2ed72162..642c01225 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -91,7 +91,6 @@ def create_suite(): file_paths = {'formats/cgf/cgftoaster.txt', 'spells/nif/dump_tex.txt', - 'spells/nif/ffvt3rskin.txt', # Contain outstanding issues # 'spells/egm/optimize.txt', From 5daf958f28d353e16e61c7c96af47193b9d9a4f0 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Thu, 17 Aug 2017 23:52:10 +0100 Subject: [PATCH 19/30] Migrate fix vertex weight influence test to nose. --- tests/spells/nif/dump/__init__.py | 0 .../spells/nif/{dump_tex.txt => dump/test_text.txt} | 11 ----------- tests/spells/nif/fix/test_ffvt3rskin.py | 13 ++++++------- 3 files changed, 6 insertions(+), 18 deletions(-) create mode 100644 tests/spells/nif/dump/__init__.py rename tests/spells/nif/{dump_tex.txt => dump/test_text.txt} (89%) diff --git a/tests/spells/nif/dump/__init__.py b/tests/spells/nif/dump/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spells/nif/dump_tex.txt b/tests/spells/nif/dump/test_text.txt similarity index 89% rename from tests/spells/nif/dump_tex.txt rename to tests/spells/nif/dump/test_text.txt index 65218aacd..5c930ad1e 100644 --- a/tests/spells/nif/dump_tex.txt +++ b/tests/spells/nif/dump/test_text.txt @@ -3,17 +3,6 @@ Doctests for the dump_tex spell @todo: some more advanced test ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(3): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "nif") ->>> import sys ->>> script = os.path.join(script_dir, "niftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> nif_dir = "tests/spells/nif/files/" >>> import niftoaster >>> sys.argv = ["niftoaster.py", "dump_tex", nif_dir + "test_dump_tex.nif"] diff --git a/tests/spells/nif/fix/test_ffvt3rskin.py b/tests/spells/nif/fix/test_ffvt3rskin.py index dde0ce46b..2fd8e6bdd 100644 --- a/tests/spells/nif/fix/test_ffvt3rskin.py +++ b/tests/spells/nif/fix/test_ffvt3rskin.py @@ -1,21 +1,20 @@ -"""Tests for the fix_ffvt3rskinpartition spell spell""" +"""Tests for the fix_ffvt3rskinpartition spell""" from tests.scripts.nif import call_niftoaster from tests.utils import BaseFileTestCase -class TestFixVertexInfleunce(BaseFileTestCase): - """Invoke the modify_substitutestringpalette spell check through nif toaster""" +class TestFixSkinPartition(BaseFileTestCase): + """Invoke the fix_ffvt3rskinpartition spell check through nif toaster""" def setUp(self): - super(TestFixVertexInfleunce, self).setUp() + super(TestFixSkinPartition, self).setUp() self.src_name = "test_fix_ffvt3rskinpartition.nif" - super(TestFixVertexInfleunce, self).copyFile() - super(TestFixVertexInfleunce, self).readNifData() + super(TestFixSkinPartition, self).copyFile() + super(TestFixSkinPartition, self).readNifData() def test_non_interactive_fix_vertex_skin_partition(self): """Test that we can repartition vertex weight influence""" - # substitute call_niftoaster("--raise", "fix_ffvt3rskinpartition", "--noninteractive", "--verbose=1", self.dest_file) """ From 8192ed8a0b850e5f76d4a0d05eaeef1117aa3ce2 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Fri, 18 Aug 2017 00:19:28 +0100 Subject: [PATCH 20/30] Migrate dump texture information spell test to nose. --- tests/spells/nif/dump/test_text.txt | 65 -------------- .../nif/dump/test_texture_properties.py | 89 +++++++++++++++++++ tests/test_doctests.py | 1 - 3 files changed, 89 insertions(+), 66 deletions(-) delete mode 100644 tests/spells/nif/dump/test_text.txt create mode 100644 tests/spells/nif/dump/test_texture_properties.py diff --git a/tests/spells/nif/dump/test_text.txt b/tests/spells/nif/dump/test_text.txt deleted file mode 100644 index 5c930ad1e..000000000 --- a/tests/spells/nif/dump/test_text.txt +++ /dev/null @@ -1,65 +0,0 @@ -Doctests for the dump_tex spell -============================== - -@todo: some more advanced test - - ->>> import niftoaster ->>> sys.argv = ["niftoaster.py", "dump_tex", nif_dir + "test_dump_tex.nif"] ->>> niftoaster.NifToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/spells/nif/files/test_dump_tex.nif === -pyffi.toaster:INFO: --- dump_tex --- -pyffi.toaster:INFO: ~~~ NiNode [test] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Cube] ~~~ -pyffi.toaster:INFO: ~~~ NiMaterialProperty [CubeMaterial] ~~~ -pyffi.toaster:INFO: ambient 0.76 0.43 0.43 -pyffi.toaster:INFO: diffuse 0.92 0.77 0.09 -pyffi.toaster:INFO: specular 0.45 0.19 0.77 -pyffi.toaster:INFO: emissive 0.00 0.00 0.00 -pyffi.toaster:INFO: glossiness 123.000000 -pyffi.toaster:INFO: alpha 0.560000 -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: [base] bitmap2.dds -pyffi.toaster:INFO: [detail] bitmap1.dds -pyffi.toaster:INFO: apply mode 2 -pyffi.toaster:INFO:Finished. - - ->>> sys.argv = ["niftoaster.py", "dump_tex", nif_dir + "test_fix_ffvt3rskinpartition.nif"] ->>> niftoaster.NifToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_ffvt3rskinpartition.nif === -pyffi.toaster:INFO: --- dump_tex --- -pyffi.toaster:INFO: ~~~ NiNode [Bip01] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Pelvis] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine1] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine2] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Neck] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 Head] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Clavicle] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L UpperArm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Forearm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Clavicle] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R UpperArm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Forearm] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Thigh] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Calf] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Foot] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Toe0] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Thigh] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Calf] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Foot] ~~~ -pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Toe0] ~~~ -pyffi.toaster:INFO: ~~~ NiTriShape [Body] ~~~ -pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ -pyffi.toaster:INFO: [base] body.dds -pyffi.toaster:INFO: apply mode 2 -pyffi.toaster:INFO: ~~~ NiMaterialProperty [Material] ~~~ -pyffi.toaster:INFO: ambient 0.50 0.50 0.50 -pyffi.toaster:INFO: diffuse 1.00 1.00 1.00 -pyffi.toaster:INFO: specular 0.50 0.50 0.50 -pyffi.toaster:INFO: emissive 0.00 0.00 0.00 -pyffi.toaster:INFO: glossiness 12.500000 -pyffi.toaster:INFO: alpha 1.000000 -pyffi.toaster:INFO:Finished. - diff --git a/tests/spells/nif/dump/test_texture_properties.py b/tests/spells/nif/dump/test_texture_properties.py new file mode 100644 index 000000000..606797d86 --- /dev/null +++ b/tests/spells/nif/dump/test_texture_properties.py @@ -0,0 +1,89 @@ +"""Tests for the dump_tex spell""" +from tests.scripts.nif import call_niftoaster +from tests.utils import BaseFileTestCase + + +class TestDumpTextureData(BaseFileTestCase): + """Invoke the dump_tex spell check through nif toaster""" + + def setUp(self): + super(TestDumpTextureData, self).setUp() + self.src_name = "test_dump_tex.nif" + super(TestDumpTextureData, self).copyFile() + super(TestDumpTextureData, self).readNifData() + + def test_non_interactive_dump_texture_properties(self): + """Test that we extract texture and material information""" + + call_niftoaster("--raise", "dump_tex", "--noninteractive", "--verbose=1", self.dest_file) + + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_dump_tex.nif === + pyffi.toaster:INFO: --- dump_tex --- + pyffi.toaster:INFO: ~~~ NiNode [test] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [Cube] ~~~ + pyffi.toaster:INFO: ~~~ NiMaterialProperty [CubeMaterial] ~~~ + pyffi.toaster:INFO: ambient 0.76 0.43 0.43 + pyffi.toaster:INFO: diffuse 0.92 0.77 0.09 + pyffi.toaster:INFO: specular 0.45 0.19 0.77 + pyffi.toaster:INFO: emissive 0.00 0.00 0.00 + pyffi.toaster:INFO: glossiness 123.000000 + pyffi.toaster:INFO: alpha 0.560000 + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: [base] bitmap2.dds + pyffi.toaster:INFO: [detail] bitmap1.dds + pyffi.toaster:INFO: apply mode 2 + pyffi.toaster:INFO:Finished. + """ + +class TestDumpTextureData(BaseFileTestCase): + """Invoke the dump_tex spell check through nif toaster""" + + def setUp(self): + super(TestDumpTextureData, self).setUp() + self.src_name = "test_fix_ffvt3rskinpartition.nif" + super(TestDumpTextureData, self).copyFile() + super(TestDumpTextureData, self).readNifData() + + def test_non_interactive_dump_texture_properties(self): + """Test that we extract texture and material information""" + + call_niftoaster("--raise", "dump_tex", "--noninteractive", "--verbose=1", self.dest_file) + + """ + pyffi.toaster:INFO:=== tests/spells/nif/files/test_fix_ffvt3rskinpartition.nif === + pyffi.toaster:INFO: --- dump_tex --- + pyffi.toaster:INFO: ~~~ NiNode [Bip01] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Pelvis] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine1] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Spine2] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Neck] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 Head] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Clavicle] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L UpperArm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Forearm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Clavicle] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R UpperArm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Forearm] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Thigh] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Calf] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Foot] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 L Toe0] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Thigh] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Calf] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Foot] ~~~ + pyffi.toaster:INFO: ~~~ NiNode [Bip01 R Toe0] ~~~ + pyffi.toaster:INFO: ~~~ NiTriShape [Body] ~~~ + pyffi.toaster:INFO: ~~~ NiTexturingProperty [] ~~~ + pyffi.toaster:INFO: [base] body.dds + pyffi.toaster:INFO: apply mode 2 + pyffi.toaster:INFO: ~~~ NiMaterialProperty [Material] ~~~ + pyffi.toaster:INFO: ambient 0.50 0.50 0.50 + pyffi.toaster:INFO: diffuse 1.00 1.00 1.00 + pyffi.toaster:INFO: specular 0.50 0.50 0.50 + pyffi.toaster:INFO: emissive 0.00 0.00 0.00 + pyffi.toaster:INFO: glossiness 12.500000 + pyffi.toaster:INFO: alpha 1.000000 + pyffi.toaster:INFO:Finished. + """ diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 642c01225..9e0fb0c73 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -90,7 +90,6 @@ def create_suite(): pass file_paths = {'formats/cgf/cgftoaster.txt', - 'spells/nif/dump_tex.txt', # Contain outstanding issues # 'spells/egm/optimize.txt', From a593a69477e1dad509fc38f8e5abc032830aa55f Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sat, 2 Sep 2017 22:14:52 +0100 Subject: [PATCH 21/30] Make the base file source generic to allow for format types. --- tests/scripts/nif/__init__.py | 1 - tests/scripts/nif/test_niftoaster.py | 6 +- .../nif/dump/test_texture_properties.py | 18 ++--- .../spells/nif/fix/test_clampmaterialalpha.py | 10 +-- .../spells/nif/fix/test_cleanstringpalette.py | 10 +-- .../nif/fix/test_detachhavoktristripsdata.py | 10 +-- tests/spells/nif/fix/test_ffvt3rskin.py | 10 +-- .../nif/fix/test_substitutestringpalette.py | 12 ++-- tests/spells/nif/fix/test_tangentspace.py | 18 ++--- tests/spells/nif/fix/test_texturepath.py | 10 +-- .../nif/modify/test_allbonepriorities.py | 10 +-- tests/spells/nif/modify/test_delbranches.py | 14 ++-- .../spells/nif/modify/test_delvertexcolor.py | 12 ++-- tests/spells/nif/optimize/test_collision.py | 66 +++++++++---------- .../nif/optimize/test_delunusedbones.py | 10 +-- .../spells/nif/optimize/test_delzeroscale.py | 12 ++-- .../nif/optimize/test_mergeduplicates.py | 22 +++---- tests/spells/nif/optimize/test_niftoaster.py | 8 +-- .../spells/nif/optimize/test_vertex_cache.py | 10 +-- tests/spells/test_toaster.py | 46 ++++++------- tests/test_doctests.py | 2 +- tests/utils/__init__.py | 10 ++- 22 files changed, 165 insertions(+), 162 deletions(-) diff --git a/tests/scripts/nif/__init__.py b/tests/scripts/nif/__init__.py index e0510676d..981d7f53c 100644 --- a/tests/scripts/nif/__init__.py +++ b/tests/scripts/nif/__init__.py @@ -17,7 +17,6 @@ def call_niftoaster(*args): """Call the NIF cli module""" oldargv = sys.argv[:] # -j1 to disable multithreading (makes various things impossible) - # --raise to ensure we catch issues sys.argv = ["niftoaster.py", "-j1"] + list(args) toaster = niftoaster.NifToaster() toaster.logger = test_logger diff --git a/tests/scripts/nif/test_niftoaster.py b/tests/scripts/nif/test_niftoaster.py index 5bf502ecc..1596b9671 100644 --- a/tests/scripts/nif/test_niftoaster.py +++ b/tests/scripts/nif/test_niftoaster.py @@ -2,9 +2,7 @@ import os import os.path - -from nose.tools import assert_equal, assert_raises, assert_almost_equal, raises - +from nose.tools import assert_equal, assert_almost_equal, raises from tests.scripts.nif import call_niftoaster nif_dir = "tests/spells/nif/files/" @@ -102,8 +100,8 @@ def test_prefix_suffix(): assert_equal(os.path.exists(nif_dir + "pre_test_suf.nif"), True) os.remove(nif_dir + "pre_test_suf.nif") -#TODO Move to spell test +#TODO Move to spell test def test_check_bhkbodycenter(): """Test body centre spell""" testfile = nif_dir + "test_fix_detachhavoktristripsdata.nif" diff --git a/tests/spells/nif/dump/test_texture_properties.py b/tests/spells/nif/dump/test_texture_properties.py index 606797d86..22f77d980 100644 --- a/tests/spells/nif/dump/test_texture_properties.py +++ b/tests/spells/nif/dump/test_texture_properties.py @@ -1,16 +1,16 @@ """Tests for the dump_tex spell""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase -class TestDumpTextureData(BaseFileTestCase): +class TestDumpTextureDataNif(BaseNifFileTestCase): """Invoke the dump_tex spell check through nif toaster""" def setUp(self): - super(TestDumpTextureData, self).setUp() + super(TestDumpTextureDataNif, self).setUp() self.src_name = "test_dump_tex.nif" - super(TestDumpTextureData, self).copyFile() - super(TestDumpTextureData, self).readNifData() + super(TestDumpTextureDataNif, self).copyFile() + super(TestDumpTextureDataNif, self).readNifData() def test_non_interactive_dump_texture_properties(self): """Test that we extract texture and material information""" @@ -36,14 +36,14 @@ def test_non_interactive_dump_texture_properties(self): pyffi.toaster:INFO:Finished. """ -class TestDumpTextureData(BaseFileTestCase): +class TestDumpTextureDataNif(BaseNifFileTestCase): """Invoke the dump_tex spell check through nif toaster""" def setUp(self): - super(TestDumpTextureData, self).setUp() + super(TestDumpTextureDataNif, self).setUp() self.src_name = "test_fix_ffvt3rskinpartition.nif" - super(TestDumpTextureData, self).copyFile() - super(TestDumpTextureData, self).readNifData() + super(TestDumpTextureDataNif, self).copyFile() + super(TestDumpTextureDataNif, self).readNifData() def test_non_interactive_dump_texture_properties(self): """Test that we extract texture and material information""" diff --git a/tests/spells/nif/fix/test_clampmaterialalpha.py b/tests/spells/nif/fix/test_clampmaterialalpha.py index 3c6dd4f71..58d7f2b5b 100644 --- a/tests/spells/nif/fix/test_clampmaterialalpha.py +++ b/tests/spells/nif/fix/test_clampmaterialalpha.py @@ -1,20 +1,20 @@ """Tests for the fix_texturepath spell""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from pyffi.spells.nif.fix import SpellClampMaterialAlpha from nose.tools import assert_true, assert_equals -class TestFixTexturePathToaster(BaseFileTestCase): +class TestFixTexturePathToasterNif(BaseNifFileTestCase): """Invoke the fix_texturepath spell check through nif toaster""" def setUp(self): - super(TestFixTexturePathToaster, self).setUp() + super(TestFixTexturePathToasterNif, self).setUp() self.src_name = "test_fix_clampmaterialalpha.nif" - super(TestFixTexturePathToaster, self).copyFile() - super(TestFixTexturePathToaster, self).readNifData() + super(TestFixTexturePathToasterNif, self).copyFile() + super(TestFixTexturePathToasterNif, self).readNifData() assert_true(self.data.roots[0].children[0].children[0].properties[0].alpha > 1.01) assert_true(self.data.roots[0].children[0].children[1].properties[0].alpha < -0.01) diff --git a/tests/spells/nif/fix/test_cleanstringpalette.py b/tests/spells/nif/fix/test_cleanstringpalette.py index 20178deb7..6ef08c4b0 100644 --- a/tests/spells/nif/fix/test_cleanstringpalette.py +++ b/tests/spells/nif/fix/test_cleanstringpalette.py @@ -1,21 +1,21 @@ """Tests for the fix_cleanstringpalette spell""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from pyffi.spells.nif.fix import SpellCleanStringPalette from nose.tools import assert_equals -class TestFixTexturePathToaster(BaseFileTestCase): +class TestFixTexturePathToasterNif(BaseNifFileTestCase): """Invoke the fix_texturepath spell check through nif toaster""" def setUp(self): - super(TestFixTexturePathToaster, self).setUp() + super(TestFixTexturePathToasterNif, self).setUp() self.src_name = "test_fix_cleanstringpalette.nif" - super(TestFixTexturePathToaster, self).copyFile() - super(TestFixTexturePathToaster, self).readNifData() + super(TestFixTexturePathToasterNif, self).copyFile() + super(TestFixTexturePathToasterNif, self).readNifData() # check current string palette strings = self.data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings() diff --git a/tests/spells/nif/fix/test_detachhavoktristripsdata.py b/tests/spells/nif/fix/test_detachhavoktristripsdata.py index c078692c2..6ab4961c1 100644 --- a/tests/spells/nif/fix/test_detachhavoktristripsdata.py +++ b/tests/spells/nif/fix/test_detachhavoktristripsdata.py @@ -1,20 +1,20 @@ """Tests for the fix_detachhavoktristripsdata spell""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from pyffi.spells.nif.fix import SpellDetachHavokTriStripsData from nose.tools import assert_equals, assert_true, assert_false -class TestDetachHavokTriStripsData(BaseFileTestCase): +class TestDetachHavokTriStripsDataNif(BaseNifFileTestCase): """Invoke the fix_detachhavoktristripsdata spell check through nif toaster""" def setUp(self): - super(TestDetachHavokTriStripsData, self).setUp() + super(TestDetachHavokTriStripsDataNif, self).setUp() self.src_name = "test_fix_detachhavoktristripsdata.nif" - super(TestDetachHavokTriStripsData, self).copyFile() - super(TestDetachHavokTriStripsData, self).readNifData() + super(TestDetachHavokTriStripsDataNif, self).copyFile() + super(TestDetachHavokTriStripsDataNif, self).readNifData() def test_explicit_detach_havok_tristripsdata(self): """run the spell that detaches the trishapedata""" diff --git a/tests/spells/nif/fix/test_ffvt3rskin.py b/tests/spells/nif/fix/test_ffvt3rskin.py index 2fd8e6bdd..d78d3e7c7 100644 --- a/tests/spells/nif/fix/test_ffvt3rskin.py +++ b/tests/spells/nif/fix/test_ffvt3rskin.py @@ -1,16 +1,16 @@ """Tests for the fix_ffvt3rskinpartition spell""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase -class TestFixSkinPartition(BaseFileTestCase): +class TestFixSkinPartitionNif(BaseNifFileTestCase): """Invoke the fix_ffvt3rskinpartition spell check through nif toaster""" def setUp(self): - super(TestFixSkinPartition, self).setUp() + super(TestFixSkinPartitionNif, self).setUp() self.src_name = "test_fix_ffvt3rskinpartition.nif" - super(TestFixSkinPartition, self).copyFile() - super(TestFixSkinPartition, self).readNifData() + super(TestFixSkinPartitionNif, self).copyFile() + super(TestFixSkinPartitionNif, self).readNifData() def test_non_interactive_fix_vertex_skin_partition(self): """Test that we can repartition vertex weight influence""" diff --git a/tests/spells/nif/fix/test_substitutestringpalette.py b/tests/spells/nif/fix/test_substitutestringpalette.py index e3546eb18..fc736f917 100644 --- a/tests/spells/nif/fix/test_substitutestringpalette.py +++ b/tests/spells/nif/fix/test_substitutestringpalette.py @@ -1,18 +1,18 @@ """Tests for the modify_substitutestringpalette spell""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from nose.tools import assert_true -class TestModifySubstitutePalette(BaseFileTestCase): +class TestModifySubstitutePaletteNif(BaseNifFileTestCase): """Invoke the modify_substitutestringpalette spell check through nif toaster""" def setUp(self): - super(TestModifySubstitutePalette, self).setUp() + super(TestModifySubstitutePaletteNif, self).setUp() self.src_name = "test_fix_cleanstringpalette.nif" - super(TestModifySubstitutePalette, self).copyFile() - super(TestModifySubstitutePalette, self).readNifData() + super(TestModifySubstitutePaletteNif, self).copyFile() + super(TestModifySubstitutePaletteNif, self).readNifData() def test_non_interactive_modify_string_palette_values(self): """Test that we can modify the string palette values""" @@ -37,7 +37,7 @@ def test_non_interactive_modify_string_palette_values(self): pyffi.toaster:INFO:Finished. """ - super(TestModifySubstitutePalette, self).readNifData() + super(TestModifySubstitutePaletteNif, self).readNifData() # check cleaned palette strings = self.data.roots[0].controller.controller_sequences[0].string_palette.palette.get_all_strings() diff --git a/tests/spells/nif/fix/test_tangentspace.py b/tests/spells/nif/fix/test_tangentspace.py index 2ce5029a6..8dab8cae6 100644 --- a/tests/spells/nif/fix/test_tangentspace.py +++ b/tests/spells/nif/fix/test_tangentspace.py @@ -1,18 +1,18 @@ """Regression test for tangent space algorithm""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase, assert_tuple_values +from tests.utils import BaseNifFileTestCase, assert_tuple_values from pyffi.spells.nif.fix import SpellAddTangentSpace -class TestFixTangentSpace(BaseFileTestCase): +class TestFixTangentSpaceNif(BaseNifFileTestCase): """Invoke the fix_texturepath spell check through nif toaster""" def setUp(self): - super(TestFixTangentSpace, self).setUp() + super(TestFixTangentSpaceNif, self).setUp() self.src_name = "test_skincenterradius.nif" - super(TestFixTangentSpace, self).copyFile() - super(TestFixTangentSpace, self).readNifData() + super(TestFixTangentSpaceNif, self).copyFile() + super(TestFixTangentSpaceNif, self).readNifData() def test_explicit_fix_tangent_space(self): """run the spell that generates normals""" @@ -1508,14 +1508,14 @@ def test_explicit_fix_tangent_space(self): """ -class TestFixDeltaTangentSpace(BaseFileTestCase): +class TestFixDeltaTangentSpaceNif(BaseNifFileTestCase): """Invoke the fix_texturepath spell check through nif toaster""" def setUp(self): - super(TestFixDeltaTangentSpace, self).setUp() + super(TestFixDeltaTangentSpaceNif, self).setUp() self.src_name = "test_fix_tangentspace.nif" - super(TestFixDeltaTangentSpace, self).copyFile() - super(TestFixDeltaTangentSpace, self).readNifData() + super(TestFixDeltaTangentSpaceNif, self).copyFile() + super(TestFixDeltaTangentSpaceNif, self).readNifData() def test_non_interactive_fix_addtangentspace(self): diff --git a/tests/spells/nif/fix/test_texturepath.py b/tests/spells/nif/fix/test_texturepath.py index bed1262ef..242c0b9ef 100644 --- a/tests/spells/nif/fix/test_texturepath.py +++ b/tests/spells/nif/fix/test_texturepath.py @@ -1,15 +1,15 @@ """Tests for the fix_texturepath spell""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase, assert_tuple_values +from tests.utils import BaseNifFileTestCase, assert_tuple_values -class TestFixTangentSpace(BaseFileTestCase): +class TestFixTangentSpaceNif(BaseNifFileTestCase): """Invoke the fix_texturepath spell check through nif toaster""" def setUp(self): - super(TestFixTangentSpace, self).setUp() + super(TestFixTangentSpaceNif, self).setUp() self.src_name = "test_fix_texturepath.nif" - super(TestFixTangentSpace, self).copyFile() - super(TestFixTangentSpace, self).readNifData() + super(TestFixTangentSpaceNif, self).copyFile() + super(TestFixTangentSpaceNif, self).readNifData() def test_non_interactive_fix_texture_path(self): call_niftoaster("--raise", "fix_texturepath", "fix_addtangentspace", "--dry-run", "--noninteractive", diff --git a/tests/spells/nif/modify/test_allbonepriorities.py b/tests/spells/nif/modify/test_allbonepriorities.py index 05f6baee7..4809fd894 100644 --- a/tests/spells/nif/modify/test_allbonepriorities.py +++ b/tests/spells/nif/modify/test_allbonepriorities.py @@ -1,17 +1,17 @@ from nose.tools import assert_equals from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase -class TestModifyAllBonePriorities(BaseFileTestCase): +class TestModifyAllBonePrioritiesNif(BaseNifFileTestCase): """Tests for the modify_allbonepriorities spell""" def setUp(self): - super(TestModifyAllBonePriorities, self).setUp() + super(TestModifyAllBonePrioritiesNif, self).setUp() self.src_name = "test_fix_cleanstringpalette.nif" - super(TestModifyAllBonePriorities, self).copyFile() - super(TestModifyAllBonePriorities, self).readNifData() + super(TestModifyAllBonePrioritiesNif, self).copyFile() + super(TestModifyAllBonePrioritiesNif, self).readNifData() def test_non_interactive_modify_all_bone_priorities(self): """Run the spell that modifies the bone prioirities""" diff --git a/tests/spells/nif/modify/test_delbranches.py b/tests/spells/nif/modify/test_delbranches.py index 02a75a9fd..a009cbc14 100644 --- a/tests/spells/nif/modify/test_delbranches.py +++ b/tests/spells/nif/modify/test_delbranches.py @@ -1,18 +1,18 @@ """Tests for the modify_delbranches spell and its friends""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from nose.tools import assert_equals -class TestModifyDelBranches(BaseFileTestCase): +class TestModifyDelBranchesNif(BaseNifFileTestCase): """Invoke the modify_delbranches spell check through nif toaster""" def setUp(self): - super(TestModifyDelBranches, self).setUp() + super(TestModifyDelBranchesNif, self).setUp() self.src_name = "test_opt_mergeduplicates.nif" - super(TestModifyDelBranches, self).copyFile() - super(TestModifyDelBranches, self).readNifData() + super(TestModifyDelBranchesNif, self).copyFile() + super(TestModifyDelBranchesNif, self).readNifData() def test_non_interactive_modify_delbranches(self): props = ['NiNode', 'NiVertexColorProperty', 'NiZBufferProperty', 'NiStencilProperty', 'NiDitherProperty', @@ -94,7 +94,7 @@ def test_non_interactive_modify_delbranches(self): pyffi.toaster:INFO:Finished. """ # check that file no longer has properties - super(TestModifyDelBranches, self).readNifData() + super(TestModifyDelBranchesNif, self).readNifData() blocks = [block.__class__.__name__ for block in self.data.blocks] branches = ['NiNode', 'NiNode', 'NiTriStrips', 'NiTriStripsData', 'NiTriStrips', @@ -166,7 +166,7 @@ def test_non_interactive_modify_delalphaprop(self): pyffi.toaster:INFO:Finished. """ - super(TestModifyDelBranches, self).readNifData() + super(TestModifyDelBranchesNif, self).readNifData() # check that file no longer has properties blocks = [block.__class__.__name__ for block in self.data.blocks] diff --git a/tests/spells/nif/modify/test_delvertexcolor.py b/tests/spells/nif/modify/test_delvertexcolor.py index 89cc1a9d2..15b17215f 100644 --- a/tests/spells/nif/modify/test_delvertexcolor.py +++ b/tests/spells/nif/modify/test_delvertexcolor.py @@ -1,18 +1,18 @@ """Tests for the modify_delvertexcolor spell""" from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from nose.tools import assert_equals, assert_false, assert_true -class TestModifyDelBranches(BaseFileTestCase): +class TestModifyDelBranchesNif(BaseNifFileTestCase): """Invoke the modify_delvertexcolor spell check through nif toaster""" def setUp(self): - super(TestModifyDelBranches, self).setUp() + super(TestModifyDelBranchesNif, self).setUp() self.src_name = "test_vertexcolor.nif" - super(TestModifyDelBranches, self).copyFile() - super(TestModifyDelBranches, self).readNifData() + super(TestModifyDelBranchesNif, self).copyFile() + super(TestModifyDelBranchesNif, self).readNifData() def test_non_interactive_modify_delbranches(self): """Test that we can delete vertex colors""" @@ -38,7 +38,7 @@ def test_non_interactive_modify_delbranches(self): pyffi.toaster:INFO:Finished. """ - super(TestModifyDelBranches, self).readNifData() + super(TestModifyDelBranchesNif, self).readNifData() # check that file has no vertex color blocks = [block.__class__.__name__ for block in self.data.blocks] diff --git a/tests/spells/nif/optimize/test_collision.py b/tests/spells/nif/optimize/test_collision.py index 2c554a990..e67e5f45d 100644 --- a/tests/spells/nif/optimize/test_collision.py +++ b/tests/spells/nif/optimize/test_collision.py @@ -1,4 +1,4 @@ -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase import nose import pyffi from pyffi.spells import Toaster @@ -7,13 +7,13 @@ from tests.utils import assert_tuple_values -class TestCollisionOptimisation(BaseFileTestCase): +class TestCollisionOptimisationNif(BaseNifFileTestCase): def setUp(self): - super(TestCollisionOptimisation, self).setUp() + super(TestCollisionOptimisationNif, self).setUp() self.src_name = "test_opt_collision_to_boxshape.nif" - super(TestCollisionOptimisation, self).copyFile() - super(TestCollisionOptimisation, self).readNifData() + super(TestCollisionOptimisationNif, self).copyFile() + super(TestCollisionOptimisationNif, self).readNifData() def test_box_optimisation(self): # check initial data @@ -53,13 +53,13 @@ def test_box_optimisation(self): nose.tools.assert_true(isinstance(shape, NifFormat.bhkBoxShape)) -class TestBoxCollisionOptimisation(BaseFileTestCase): +class TestBoxCollisionOptimisationNif(BaseNifFileTestCase): def setUp(self): - super(TestBoxCollisionOptimisation, self).setUp() + super(TestBoxCollisionOptimisationNif, self).setUp() self.src_name = "test_opt_collision_unpacked.nif" - super(TestBoxCollisionOptimisation, self).copyFile() - super(TestBoxCollisionOptimisation, self).readNifData() + super(TestBoxCollisionOptimisationNif, self).copyFile() + super(TestBoxCollisionOptimisationNif, self).readNifData() def test_box_from_unpacked_collision_optimisation(self): """Test Box conversion from unpacked collision""" @@ -88,13 +88,13 @@ def test_box_from_unpacked_collision_optimisation(self): nose.tools.assert_equals(shape.material.material, 9) -class TestPackedBoxCollisionOptimisation(BaseFileTestCase): +class TestPackedBoxCollisionOptimisationNif(BaseNifFileTestCase): def setUp(self): - super(TestPackedBoxCollisionOptimisation, self).setUp() + super(TestPackedBoxCollisionOptimisationNif, self).setUp() self.src_name = "test_opt_collision_packed.nif" - super(TestPackedBoxCollisionOptimisation, self).copyFile() - super(TestPackedBoxCollisionOptimisation, self).readNifData() + super(TestPackedBoxCollisionOptimisationNif, self).copyFile() + super(TestPackedBoxCollisionOptimisationNif, self).readNifData() def test_box_from_packed_collision_optimisation(self): """Test Box conversion from packed collision""" @@ -153,13 +153,13 @@ def test_box_from_mopp_collision_optimisation(self): nose.tools.assert_true(isinstance(shape.shape, NifFormat.bhkBoxShape)) -class TestNotBoxCollisionOptimisation(BaseFileTestCase): +class TestNotBoxCollisionOptimisationNif(BaseNifFileTestCase): def setUp(self): - super(TestNotBoxCollisionOptimisation, self).setUp() + super(TestNotBoxCollisionOptimisationNif, self).setUp() self.src_name = "test_opt_collision_to_boxshape_notabox.nif" - super(TestNotBoxCollisionOptimisation, self).copyFile() - super(TestNotBoxCollisionOptimisation, self).readNifData() + super(TestNotBoxCollisionOptimisationNif, self).copyFile() + super(TestNotBoxCollisionOptimisationNif, self).readNifData() def test_box_from_packed_collision_optimisation(self): """Test that a collision mesh which is not a box, but whose vertices form a box, is not converted to a box.""" @@ -182,12 +182,12 @@ def test_box_from_packed_collision_optimisation(self): nose.tools.assert_equals(self.data.roots[0].collision_object.body.shape.__class__.__name__, 'bhkMoppBvTreeShape') -class TestMoppCollisionOptimisation(BaseFileTestCase): +class TestMoppCollisionOptimisationNif(BaseNifFileTestCase): def setUp(self): - super(TestMoppCollisionOptimisation, self).setUp() + super(TestMoppCollisionOptimisationNif, self).setUp() self.src_name = "test_opt_collision_complex_mopp.nif" - super(TestMoppCollisionOptimisation, self).copyFile() - super(TestMoppCollisionOptimisation, self).readNifData() + super(TestMoppCollisionOptimisationNif, self).copyFile() + super(TestMoppCollisionOptimisationNif, self).readNifData() def test_optimise_collision_complex_mopp(self): @@ -239,13 +239,13 @@ def test_optimise_collision_complex_mopp(self): """ -class TestUnpackedCollisionOptimisation(BaseFileTestCase): +class TestUnpackedCollisionOptimisationNif(BaseNifFileTestCase): def setUp(self): - super(TestUnpackedCollisionOptimisation, self).setUp() + super(TestUnpackedCollisionOptimisationNif, self).setUp() self.src_name = "test_opt_collision_unpacked.nif" - super(TestUnpackedCollisionOptimisation, self).copyFile() - super(TestUnpackedCollisionOptimisation, self).readNifData() + super(TestUnpackedCollisionOptimisationNif, self).copyFile() + super(TestUnpackedCollisionOptimisationNif, self).readNifData() def test_optimise_collision_unpacked(self): """Test unpacked collision """ @@ -274,13 +274,13 @@ def test_optimise_collision_unpacked(self): nose.tools.assert_equals(shape.data.num_triangles, 12) -class TestPackedCollisionOptimisation(BaseFileTestCase): +class TestPackedCollisionOptimisationNif(BaseNifFileTestCase): def setUp(self): - super(TestPackedCollisionOptimisation, self).setUp() + super(TestPackedCollisionOptimisationNif, self).setUp() self.src_name = "test_opt_collision_packed.nif" - super(TestPackedCollisionOptimisation, self).copyFile() - super(TestPackedCollisionOptimisation, self).readNifData() + super(TestPackedCollisionOptimisationNif, self).copyFile() + super(TestPackedCollisionOptimisationNif, self).readNifData() def test_optimise_collision_packed(self): """Test packed collision """ @@ -316,13 +316,13 @@ def test_optimise_collision_packed(self): nose.tools.assert_equals(shape.data.num_triangles, 12) -class TestMoppCollisionOptimisation(BaseFileTestCase): +class TestMoppCollisionOptimisationNif(BaseNifFileTestCase): def setUp(self): - super(TestMoppCollisionOptimisation, self).setUp() + super(TestMoppCollisionOptimisationNif, self).setUp() self.src_name = "test_opt_collision_mopp.nif" - super(TestMoppCollisionOptimisation, self).copyFile() - super(TestMoppCollisionOptimisation, self).readNifData() + super(TestMoppCollisionOptimisationNif, self).copyFile() + super(TestMoppCollisionOptimisationNif, self).readNifData() def test_optimise_collision_packed(self): """Test packed collision """ diff --git a/tests/spells/nif/optimize/test_delunusedbones.py b/tests/spells/nif/optimize/test_delunusedbones.py index 513ede08d..d3aeb5cee 100644 --- a/tests/spells/nif/optimize/test_delunusedbones.py +++ b/tests/spells/nif/optimize/test_delunusedbones.py @@ -1,16 +1,16 @@ -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from nose.tools import assert_equals, assert_is from pyffi.spells.nif.optimize import SpellDelUnusedBones -class TestDeleteUnusedBonesOptimisation(BaseFileTestCase): +class TestDeleteUnusedBonesOptimisationNif(BaseNifFileTestCase): """Tests for the opt_delunusedbones spell""" def setUp(self): - super(TestDeleteUnusedBonesOptimisation, self).setUp() + super(TestDeleteUnusedBonesOptimisationNif, self).setUp() self.src_name = "test_opt_delunusedbones.nif" - super(TestDeleteUnusedBonesOptimisation, self).copyFile() - super(TestDeleteUnusedBonesOptimisation, self).readNifData() + super(TestDeleteUnusedBonesOptimisationNif, self).copyFile() + super(TestDeleteUnusedBonesOptimisationNif, self).readNifData() def test_unused_bone_deletion(self): # check dummy bone diff --git a/tests/spells/nif/optimize/test_delzeroscale.py b/tests/spells/nif/optimize/test_delzeroscale.py index d8c2a6994..31cd9fb20 100644 --- a/tests/spells/nif/optimize/test_delzeroscale.py +++ b/tests/spells/nif/optimize/test_delzeroscale.py @@ -1,18 +1,18 @@ -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from nose.tools import assert_true from tests import test_logger import pyffi -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from pyffi.spells.nif.optimize import SpellDelZeroScale -class TestDelZeroScaleOptimisation(BaseFileTestCase): +class TestDelZeroScaleOptimisationNif(BaseNifFileTestCase): """Test for the delete zero scale spell""" def setUp(self): - super(TestDelZeroScaleOptimisation, self).setUp() + super(TestDelZeroScaleOptimisationNif, self).setUp() self.src_name = "test_opt_zeroscale.nif" - super(TestDelZeroScaleOptimisation, self).copyFile() - super(TestDelZeroScaleOptimisation, self).readNifData() + super(TestDelZeroScaleOptimisationNif, self).copyFile() + super(TestDelZeroScaleOptimisationNif, self).readNifData() def test_zero_scale_deletion(self): # check zero scale diff --git a/tests/spells/nif/optimize/test_mergeduplicates.py b/tests/spells/nif/optimize/test_mergeduplicates.py index fc81cec5f..f74a7ebcf 100644 --- a/tests/spells/nif/optimize/test_mergeduplicates.py +++ b/tests/spells/nif/optimize/test_mergeduplicates.py @@ -1,5 +1,5 @@ from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase import pyffi from pyffi.spells import Toaster @@ -7,25 +7,25 @@ from nose.tools import assert_true, assert_false -class TestMergeDuplicatesOptimisation(BaseFileTestCase): +class TestMergeDuplicatesOptimisationNif(BaseNifFileTestCase): # I didn't need setUp and tearDown here.. def setUp(self): - super(TestMergeDuplicatesOptimisation, self).setUp() + super(TestMergeDuplicatesOptimisationNif, self).setUp() self.src_name = "test_opt_mergeduplicates.nif" - super(TestMergeDuplicatesOptimisation, self).copyFile() + super(TestMergeDuplicatesOptimisationNif, self).copyFile() def test_non_interactive_opt_merge_duplicates(self): call_niftoaster("--raise", "opt_mergeduplicates", "--dry-run", "--noninteractive", "--verbose=1", self.dest_file) -class TestMergeDuplicatesGeomOptimisation(BaseFileTestCase): +class TestMergeDuplicatesGeomOptimisationNif(BaseNifFileTestCase): # I didn't need setUp and tearDown here.. def setUp(self): - super(TestMergeDuplicatesGeomOptimisation, self).setUp() + super(TestMergeDuplicatesGeomOptimisationNif, self).setUp() self.src_name = "test_opt_dupgeomdata.nif" - super(TestMergeDuplicatesGeomOptimisation, self).copyFile() + super(TestMergeDuplicatesGeomOptimisationNif, self).copyFile() def test_non_interactive_opt_merge_duplicates(self): pass @@ -63,14 +63,14 @@ def has_duplicates(root): return False -class TestExplicitMergeDuplicatesGeomOptimisation(BaseFileTestCase): +class TestExplicitMergeDuplicatesGeomOptimisationNif(BaseNifFileTestCase): # I didn't need setUp and tearDown here.. def setUp(self): - super(TestExplicitMergeDuplicatesGeomOptimisation, self).setUp() + super(TestExplicitMergeDuplicatesGeomOptimisationNif, self).setUp() self.src_name = "test_opt_mergeduplicates.nif" - super(TestExplicitMergeDuplicatesGeomOptimisation, self).copyFile() - super(TestExplicitMergeDuplicatesGeomOptimisation, self).readNifData() + super(TestExplicitMergeDuplicatesGeomOptimisationNif, self).copyFile() + super(TestExplicitMergeDuplicatesGeomOptimisationNif, self).readNifData() def test_non_interactive_opt_merge_duplicates(self): # check that there are duplicates diff --git a/tests/spells/nif/optimize/test_niftoaster.py b/tests/spells/nif/optimize/test_niftoaster.py index f0aa6ba22..6b4dfea8a 100644 --- a/tests/spells/nif/optimize/test_niftoaster.py +++ b/tests/spells/nif/optimize/test_niftoaster.py @@ -1,17 +1,17 @@ from tests.scripts.nif import call_niftoaster -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from tests import test_logger from pyffi.spells import Toaster -class TestToasterOptimisation(BaseFileTestCase): +class TestToasterOptimisationNif(BaseNifFileTestCase): # I didn't need setUp and tearDown here.. def setUp(self): - super(TestToasterOptimisation, self).setUp() + super(TestToasterOptimisationNif, self).setUp() self.src_name = "test.nif" - super(TestToasterOptimisation, self).copyFile() + super(TestToasterOptimisationNif, self).copyFile() def test_non_interactive_optimisation(self): call_niftoaster("optimize", "--raise", "--noninteractive", "--verbose=1", self.dest_file) diff --git a/tests/spells/nif/optimize/test_vertex_cache.py b/tests/spells/nif/optimize/test_vertex_cache.py index abe015268..10a1682e6 100644 --- a/tests/spells/nif/optimize/test_vertex_cache.py +++ b/tests/spells/nif/optimize/test_vertex_cache.py @@ -1,17 +1,17 @@ -from tests.utils import BaseFileTestCase +from tests.utils import BaseNifFileTestCase from nose.tools import assert_equals import pyffi -class TestVertexCacheOptimisation(BaseFileTestCase): +class TestVertexCacheOptimisationNif(BaseNifFileTestCase): """Regression test for vertex cache algorithm""" def setUp(self): - super(TestVertexCacheOptimisation, self).setUp() + super(TestVertexCacheOptimisationNif, self).setUp() self.src_name = "test_opt_vertex_cache.nif" - super(TestVertexCacheOptimisation, self).copyFile() - super(TestVertexCacheOptimisation, self).readNifData() + super(TestVertexCacheOptimisationNif, self).copyFile() + super(TestVertexCacheOptimisationNif, self).readNifData() assert_equals(self.data.roots[0].children[0].data.num_vertices, 32) diff --git a/tests/spells/test_toaster.py b/tests/spells/test_toaster.py index 9f8b21f24..228267aef 100644 --- a/tests/spells/test_toaster.py +++ b/tests/spells/test_toaster.py @@ -3,7 +3,7 @@ import os import shutil -import nose.tools +from nose.tools import assert_true, assert_false from pyffi.formats.nif import NifFormat from pyffi.spells import Toaster @@ -19,43 +19,43 @@ class TestToaster: def test_toaster_default_admissible(self): """# no include or exclude: all admissible""" toaster = MyToaster() - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiProperty)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiNode)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiAVObject)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiLODNode)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiMaterialProperty)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiProperty)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiNode)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiAVObject)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiLODNode)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiMaterialProperty)) def test_toaster_exclude(self): """Test exclude NiProperty and NiNode inherited types""" toaster = MyToaster(options={"exclude": ["NiProperty", "NiNode"]}) - nose.tools.assert_false(toaster.is_admissible_branch_class(NifFormat.NiProperty)) - nose.tools.assert_false(toaster.is_admissible_branch_class(NifFormat.NiNode)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiAVObject)) - nose.tools.assert_false(toaster.is_admissible_branch_class(NifFormat.NiLODNode)) - nose.tools.assert_false(toaster.is_admissible_branch_class(NifFormat.NiMaterialProperty)) + assert_false(toaster.is_admissible_branch_class(NifFormat.NiProperty)) + assert_false(toaster.is_admissible_branch_class(NifFormat.NiNode)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiAVObject)) + assert_false(toaster.is_admissible_branch_class(NifFormat.NiLODNode)) + assert_false(toaster.is_admissible_branch_class(NifFormat.NiMaterialProperty)) def test_toaster_include(self): """Test include only NiProperty and NiNode inherited types""" toaster = MyToaster(options={"include": ["NiProperty", "NiNode"]}) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiProperty)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiNode)) - nose.tools.assert_false(toaster.is_admissible_branch_class(NifFormat.NiAVObject)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiLODNode)) # NiNode subclass! - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiMaterialProperty)) # NiProperties are! + assert_true(toaster.is_admissible_branch_class(NifFormat.NiProperty)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiNode)) + assert_false(toaster.is_admissible_branch_class(NifFormat.NiAVObject)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiLODNode)) # NiNode subclass! + assert_true(toaster.is_admissible_branch_class(NifFormat.NiMaterialProperty)) # NiProperties are! def test_toaster_include_and_exclude(self): """Test include NiProperty and NiNode, exclude NiMaterialProp and NiLODNode""" toaster = MyToaster(options={"include": ["NiProperty", "NiNode"], "exclude": ["NiMaterialProperty", "NiLODNode"]}) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiProperty)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiNode)) - nose.tools.assert_false(toaster.is_admissible_branch_class(NifFormat.NiAVObject)) - nose.tools.assert_false(toaster.is_admissible_branch_class(NifFormat.NiLODNode)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiSwitchNode)) - nose.tools.assert_false(toaster.is_admissible_branch_class(NifFormat.NiMaterialProperty)) - nose.tools.assert_true(toaster.is_admissible_branch_class(NifFormat.NiAlphaProperty)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiProperty)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiNode)) + assert_false(toaster.is_admissible_branch_class(NifFormat.NiAVObject)) + assert_false(toaster.is_admissible_branch_class(NifFormat.NiLODNode)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiSwitchNode)) + assert_false(toaster.is_admissible_branch_class(NifFormat.NiMaterialProperty)) + assert_true(toaster.is_admissible_branch_class(NifFormat.NiAlphaProperty)) class TestIniParser: diff --git a/tests/test_doctests.py b/tests/test_doctests.py index 9e0fb0c73..196fca2bd 100644 --- a/tests/test_doctests.py +++ b/tests/test_doctests.py @@ -89,7 +89,7 @@ def create_suite(): test_logger.debug(str(mod) + "does not have a test suite") pass - file_paths = {'formats/cgf/cgftoaster.txt', + file_paths = { # Contain outstanding issues # 'spells/egm/optimize.txt', diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index de1ba0143..143fd9f53 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -23,10 +23,12 @@ def assert_tuple_values(a, b): class BaseFileTestCase(unittest.TestCase): + FORMAT = "" + def setUp(self): super(BaseFileTestCase, self).setUp() # set up that everyone needs .. - self.input_files = os.path.join(test_root, 'spells', 'nif', 'files').replace("\\", "/") + self.input_files = os.path.join(test_root, 'spells', self.FORMAT, 'files').replace("\\", "/") self.out = tempfile.mkdtemp() def copyFile(self): @@ -43,4 +45,8 @@ def readNifData(self): def tearDown(self): shutil.rmtree(self.out) # tear down that everyone needs .. - super(BaseFileTestCase, self).tearDown() \ No newline at end of file + super(BaseFileTestCase, self).tearDown() + + +class BaseNifFileTestCase(BaseFileTestCase): + FORMAT = 'nif' From e8d7e35776b272e945db2dec0ec6e5dcba762d3e Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sat, 2 Sep 2017 22:20:37 +0100 Subject: [PATCH 22/30] Add a utility function to invoke cgftoaster --- tests/scripts/cgf/__init__.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/scripts/cgf/__init__.py diff --git a/tests/scripts/cgf/__init__.py b/tests/scripts/cgf/__init__.py new file mode 100644 index 000000000..ac635dbad --- /dev/null +++ b/tests/scripts/cgf/__init__.py @@ -0,0 +1,24 @@ +import imp +import os.path +import sys +from tests import test_logger + +from os.path import dirname +dir_path = __file__ +for i in range(4): # recurse up to root repo dir + dir_path = dirname(dir_path) + +repo_root = dir_path +cgftoaster = imp.load_module("cgftoaster", *imp.find_module("cgftoaster", [os.path.join(repo_root, "scripts", "cgf")])) + + +def call_cgftoaster(*args): + """Call the NIF cli module""" + oldargv = sys.argv[:] + # -j1 to disable multithreading (makes various things impossible) + sys.argv = ["cgftoaster.py", "-j1"] + list(args) + toaster = cgftoaster.CgfToaster() + toaster.logger = test_logger + toaster.cli() + sys.argv = oldargv + return toaster From 531b0526d606b6efc6126e04e23d1af8163f4b7f Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sat, 2 Sep 2017 22:21:34 +0100 Subject: [PATCH 23/30] Execute basic cgftoaster spells --- tests/scripts/cgf/test_cgftoaster.py | 65 ++++++++++++++++++ tests/spells/cgf/__init__.py | 0 .../cgf => spells/cgf/files}/invalid.cgf | Bin .../cgf => spells/cgf/files}/monkey.cgf | Bin .../cgf => spells/cgf/files}/monkey.mtl | 0 .../cgf => spells/cgf/files}/test.cgf | Bin .../cgf => spells/cgf/files}/vcols.cgf | Bin tests/utils/__init__.py | 3 + 8 files changed, 68 insertions(+) create mode 100644 tests/scripts/cgf/test_cgftoaster.py create mode 100644 tests/spells/cgf/__init__.py rename tests/{formats/cgf => spells/cgf/files}/invalid.cgf (100%) rename tests/{formats/cgf => spells/cgf/files}/monkey.cgf (100%) rename tests/{formats/cgf => spells/cgf/files}/monkey.mtl (100%) rename tests/{formats/cgf => spells/cgf/files}/test.cgf (100%) rename tests/{formats/cgf => spells/cgf/files}/vcols.cgf (100%) diff --git a/tests/scripts/cgf/test_cgftoaster.py b/tests/scripts/cgf/test_cgftoaster.py new file mode 100644 index 000000000..2e991eb93 --- /dev/null +++ b/tests/scripts/cgf/test_cgftoaster.py @@ -0,0 +1,65 @@ +"""Tests for the cgftoaster script""" +from nose.tools import raises +from tests.scripts.cgf import call_cgftoaster + +cfg_dir = "tests/spells/cgf/files/" + + +@raises(SystemExit) # --help uses sys.exit() +def test_help(): + """Tests spell help""" + call_cgftoaster("--raise", "--help") + + +def test_examples(): + """Tests example""" + call_cgftoaster("--raise", "--examples") + + +def test_spells(): + """Tests spells""" + call_cgftoaster("--raise", "--spells") + + """ + check_read + check_readwrite + check_tangentspace + check_vcols + dump + """ + + +@raises(ValueError) +def test_raise(): + """Test check_read and check_readwrite spells""" + call_cgftoaster("--raise", "check_read", cfg_dir) + + """ + pyffi.toaster:INFO:=== tests/formats/cgf/invalid.cgf === + pyffi.toaster:ERROR:FAILED ON tests/formats/cgf/invalid.cgf - with the follow exception + pyffi.toaster:ERROR:EXPT MSG : Invalid signature (got 'b'INVALI'' instead of 'CryTek' or 'NCAion') + pyffi.toaster:ERROR:If you were running a spell that came with PyFFI + pyffi.toaster:ERROR:Please report this issue - https://github.com/niftools/pyffi/issues + pyffi.toaster:INFO:=== tests/formats/cgf/monkey.cgf === + pyffi.toaster:INFO: --- check_read --- + pyffi.toaster:INFO:=== tests/formats/cgf/test.cgf === + pyffi.toaster:INFO: --- check_read --- + pyffi.toaster:INFO:=== tests/formats/cgf/vcols.cgf === + pyffi.toaster:INFO: --- check_read --- + pyffi.toaster:INFO:Finished. + """ + + +def test_read_write(): + test_file = cfg_dir + "test.cgf" + call_cgftoaster("--raise", "check_readwrite", test_file) + """ + pyffi.toaster:INFO:=== tests/formats/cgf/test.cgf === + pyffi.toaster:INFO: --- check_readwrite --- + pyffi.toaster:INFO: writing to temporary file + pyffi.toaster:INFO: comparing file sizes + pyffi.toaster:INFO: original size: 166 + pyffi.toaster:INFO: written size: 168 + pyffi.toaster:INFO: padding: 2 + pyffi.toaster:INFO:Finished. + """ diff --git a/tests/spells/cgf/__init__.py b/tests/spells/cgf/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/formats/cgf/invalid.cgf b/tests/spells/cgf/files/invalid.cgf similarity index 100% rename from tests/formats/cgf/invalid.cgf rename to tests/spells/cgf/files/invalid.cgf diff --git a/tests/formats/cgf/monkey.cgf b/tests/spells/cgf/files/monkey.cgf similarity index 100% rename from tests/formats/cgf/monkey.cgf rename to tests/spells/cgf/files/monkey.cgf diff --git a/tests/formats/cgf/monkey.mtl b/tests/spells/cgf/files/monkey.mtl similarity index 100% rename from tests/formats/cgf/monkey.mtl rename to tests/spells/cgf/files/monkey.mtl diff --git a/tests/formats/cgf/test.cgf b/tests/spells/cgf/files/test.cgf similarity index 100% rename from tests/formats/cgf/test.cgf rename to tests/spells/cgf/files/test.cgf diff --git a/tests/formats/cgf/vcols.cgf b/tests/spells/cgf/files/vcols.cgf similarity index 100% rename from tests/formats/cgf/vcols.cgf rename to tests/spells/cgf/files/vcols.cgf diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index 143fd9f53..dec29a739 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -50,3 +50,6 @@ def tearDown(self): class BaseNifFileTestCase(BaseFileTestCase): FORMAT = 'nif' + +class BaseCgfFileTestCase(BaseFileTestCase): + FORMAT = 'cgf' \ No newline at end of file From 24a6d5317939d40693969eb25db4fd7ed75fbf7c Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sat, 2 Sep 2017 22:55:58 +0100 Subject: [PATCH 24/30] Move file reading to specific format class --- tests/utils/__init__.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index dec29a739..502b58f03 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -7,13 +7,15 @@ import shutil import unittest from os.path import dirname + +from pyffi.formats.cgf import CgfFormat from pyffi.formats.nif import NifFormat def assert_tuple_values(a, b): """Wrapper func to cleanly assert tuple values""" - for i, j in zip(a, b): - nose.tools.assert_almost_equal(i, j, places=3) + for elem, j in zip(a, b): + nose.tools.assert_almost_equal(elem, j, places=3) dir_path = __file__ for i in range(2): # recurse up to root repo dir @@ -22,7 +24,6 @@ def assert_tuple_values(a, b): class BaseFileTestCase(unittest.TestCase): - FORMAT = "" def setUp(self): @@ -37,11 +38,6 @@ def copyFile(self): shutil.copyfile(self.src_file, self.dest_file) assert os.path.exists(self.dest_file) - def readNifData(self): - self.data = NifFormat.Data() - stream = open(self.dest_file, "rb") - self.data.read(stream) - def tearDown(self): shutil.rmtree(self.out) # tear down that everyone needs .. @@ -51,5 +47,16 @@ def tearDown(self): class BaseNifFileTestCase(BaseFileTestCase): FORMAT = 'nif' + def readNifData(self): + self.data = NifFormat.Data() + stream = open(self.dest_file, "rb") + self.data.read(stream) + + class BaseCgfFileTestCase(BaseFileTestCase): - FORMAT = 'cgf' \ No newline at end of file + FORMAT = 'cgf' + + def readCgfData(self): + self.data = CgfFormat.Data() + stream = open(self.dest_file, "rb") + self.data.read(stream) From 6cdb20b72f073b9d4b65d1e46638e812e9532f50 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sat, 2 Sep 2017 22:56:59 +0100 Subject: [PATCH 25/30] Migrated cgf dump file test to nose --- tests/spells/cgf/dump/__init__.py | 0 tests/spells/cgf/dump/test_dump_data.py | 40 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/spells/cgf/dump/__init__.py create mode 100644 tests/spells/cgf/dump/test_dump_data.py diff --git a/tests/spells/cgf/dump/__init__.py b/tests/spells/cgf/dump/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spells/cgf/dump/test_dump_data.py b/tests/spells/cgf/dump/test_dump_data.py new file mode 100644 index 000000000..167e168f3 --- /dev/null +++ b/tests/spells/cgf/dump/test_dump_data.py @@ -0,0 +1,40 @@ +"""Tests for the dump spell for cgf""" +from tests.utils import BaseCgfFileTestCase +from tests.scripts.cgf import call_cgftoaster + + +class TestDumpDataCgf(BaseCgfFileTestCase): + """Invoke the dump spell check through cgf toaster""" + + def setUp(self): + super(TestDumpDataCgf, self).setUp() + self.src_name = "test.cgf" + super(TestDumpDataCgf, self).copyFile() + super(TestDumpDataCgf, self).readCgfData() + + def test_non_interactive_dump(self): + """Test that we extract texture and material information""" + + call_cgftoaster("--raise", "dump", "--noninteractive", "--verbose=1", self.dest_file) + """ + pyffi.toaster:INFO:=== tests/scripts/cgf/files/test.cgf === + pyffi.toaster:INFO: --- dump --- + pyffi.toaster:INFO: ~~~ SourceInfoChunk [] ~~~ + pyffi.toaster:INFO: instance at 0x... + pyffi.toaster:INFO: * source_file : + pyffi.toaster:INFO: * date : Fri Sep 28 22:40:44 2007 + pyffi.toaster:INFO: * author : blender@BLENDER + pyffi.toaster:INFO: + pyffi.toaster:INFO: ~~~ TimingChunk [GlobalRange] ~~~ + pyffi.toaster:INFO: instance at 0x... + pyffi.toaster:INFO: * secs_per_tick : 0.0002083... + pyffi.toaster:INFO: * ticks_per_frame : 160 + pyffi.toaster:INFO: * global_range : + pyffi.toaster:INFO: instance at 0x... + pyffi.toaster:INFO: * name : GlobalRange + pyffi.toaster:INFO: * start : 0 + pyffi.toaster:INFO: * end : 100 + pyffi.toaster:INFO: * num_sub_ranges : 0 + pyffi.toaster:INFO: + pyffi.toaster:INFO:Finished. + """ From e816cc737399d01adb081f72a8fca4b89877cea6 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Sat, 2 Sep 2017 23:10:41 +0100 Subject: [PATCH 26/30] Convert vcol cgf tests to nose and delete doctest.txt file for cgf --- tests/formats/cgf/cgftoaster.txt | 124 ------------------- tests/spells/cgf/check/__init__.py | 0 tests/spells/cgf/check/test_tangentspace.py | 29 +++++ tests/spells/cgf/check/test_vertex_colors.py | 47 +++++++ 4 files changed, 76 insertions(+), 124 deletions(-) delete mode 100644 tests/formats/cgf/cgftoaster.txt create mode 100644 tests/spells/cgf/check/__init__.py create mode 100644 tests/spells/cgf/check/test_tangentspace.py create mode 100644 tests/spells/cgf/check/test_vertex_colors.py diff --git a/tests/formats/cgf/cgftoaster.txt b/tests/formats/cgf/cgftoaster.txt deleted file mode 100644 index 964198ff5..000000000 --- a/tests/formats/cgf/cgftoaster.txt +++ /dev/null @@ -1,124 +0,0 @@ -Doctests for the cgftoaster script -================================== - -The --spells switch -------------------- - ->>> import os ->>> from os.path import dirname ->>> dirpath = __file__ ->>> for i in range(3): #recurse up to root repo dir -... dirpath = dirname(dirpath) ->>> repo_root = dirpath ->>> script_dir = os.path.join(repo_root, "scripts", "cgf") ->>> import sys ->>> script = os.path.join(script_dir, "cgftoaster.py") ->>> sys.path.insert(-1, script_dir.replace("\\\\", "/")) ->>> import cgftoaster ->>> sys.argv = ["cgftoaster.py", "--spells"] ->>> cgftoaster.CgfToaster().cli() -check_read -check_readwrite -check_tangentspace -check_vcols -dump - -The check_read and check_readwrite spells ------------------------------------------ - ->>> sys.argv = ["cgftoaster.py", "--verbose=1", "check_read", "tests/formats/cgf/"] ->>> cgftoaster.CgfToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/formats/cgf/invalid.cgf === -pyffi.toaster:ERROR:FAILED ON tests/formats/cgf/invalid.cgf - with the follow exception -pyffi.toaster:ERROR:EXPT MSG : Invalid signature (got 'b'INVALI'' instead of 'CryTek' or 'NCAion') -pyffi.toaster:ERROR:If you were running a spell that came with PyFFI -pyffi.toaster:ERROR:Please report this issue - https://github.com/niftools/pyffi/issues -pyffi.toaster:INFO:=== tests/formats/cgf/monkey.cgf === -pyffi.toaster:INFO: --- check_read --- -pyffi.toaster:INFO:=== tests/formats/cgf/test.cgf === -pyffi.toaster:INFO: --- check_read --- -pyffi.toaster:INFO:=== tests/formats/cgf/vcols.cgf === -pyffi.toaster:INFO: --- check_read --- -pyffi.toaster:INFO:Finished. ->>> sys.argv = ["cgftoaster.py", "--verbose=1", "check_readwrite", "tests/formats/cgf/test.cgf"] ->>> cgftoaster.CgfToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/formats/cgf/test.cgf === -pyffi.toaster:INFO: --- check_readwrite --- -pyffi.toaster:INFO: writing to temporary file -pyffi.toaster:INFO: comparing file sizes -pyffi.toaster:INFO: original size: 166 -pyffi.toaster:INFO: written size: 168 -pyffi.toaster:INFO: padding: 2 -pyffi.toaster:INFO:Finished. - -The dump spell --------------- - ->>> import sys ->>> sys.path.append("scripts/cgf") ->>> import cgftoaster ->>> sys.argv = ["cgftoaster.py", "--verbose=1", "dump", "tests/formats/cgf/test.cgf"] ->>> cgftoaster.CgfToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/formats/cgf/test.cgf === -pyffi.toaster:INFO: --- dump --- -pyffi.toaster:INFO: ~~~ SourceInfoChunk [] ~~~ -pyffi.toaster:INFO: instance at 0x... -pyffi.toaster:INFO: * source_file : -pyffi.toaster:INFO: * date : Fri Sep 28 22:40:44 2007 -pyffi.toaster:INFO: * author : blender@BLENDER -pyffi.toaster:INFO: -pyffi.toaster:INFO: ~~~ TimingChunk [GlobalRange] ~~~ -pyffi.toaster:INFO: instance at 0x... -pyffi.toaster:INFO: * secs_per_tick : 0.0002083... -pyffi.toaster:INFO: * ticks_per_frame : 160 -pyffi.toaster:INFO: * global_range : -pyffi.toaster:INFO: instance at 0x... -pyffi.toaster:INFO: * name : GlobalRange -pyffi.toaster:INFO: * start : 0 -pyffi.toaster:INFO: * end : 100 -pyffi.toaster:INFO: * num_sub_ranges : 0 -pyffi.toaster:INFO: -pyffi.toaster:INFO:Finished. - -The check_tangentspace spell ----------------------------- - ->>> import sys ->>> sys.path.append("scripts/cgf") ->>> import cgftoaster ->>> sys.argv = ["cgftoaster.py", "--verbose=1", "check_tangentspace", "tests/formats/cgf/monkey.cgf"] ->>> cgftoaster.CgfToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/formats/cgf/monkey.cgf === -pyffi.toaster:INFO: --- check_tangentspace --- -pyffi.toaster:INFO: ~~~ NodeChunk [Merged] ~~~ -pyffi.toaster:INFO: ~~~ MeshChunk [] ~~~ -pyffi.toaster:INFO: recalculating new tangent space -pyffi.toaster:INFO: validating and checking old with new -pyffi.toaster:WARNING:... -... -pyffi.toaster:INFO: ~~~ NodeChunk [CryExportNode_monkey-CGF-monkey-DoExport-MergeNodes] ~~~ -pyffi.toaster:INFO:Finished. - -The check_vcols spell ---------------------- - ->>> import sys ->>> sys.path.append("scripts/cgf") ->>> import cgftoaster ->>> sys.argv = ["cgftoaster.py", "--verbose=1", "check_vcols", "tests/formats/cgf/monkey.cgf"] ->>> cgftoaster.CgfToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/formats/cgf/monkey.cgf === -pyffi.toaster:INFO: --- check_vcols --- -pyffi.toaster:INFO: ~~~ NodeChunk [Merged] ~~~ -pyffi.toaster:INFO: ~~~ MeshChunk [] ~~~ -pyffi.toaster:INFO: ~~~ NodeChunk [CryExportNode_monkey-CGF-monkey-DoExport-MergeNodes] ~~~ -pyffi.toaster:INFO:Finished. ->>> sys.argv = ["cgftoaster.py", "--verbose=1", "check_vcols", "tests/formats/cgf/vcols.cgf"] ->>> cgftoaster.CgfToaster().cli() # doctest: +ELLIPSIS +REPORT_NDIFF -pyffi.toaster:INFO:=== tests/formats/cgf/vcols.cgf === -pyffi.toaster:INFO: --- check_vcols --- -pyffi.toaster:INFO: ~~~ NodeChunk [Monkey] ~~~ -pyffi.toaster:INFO: ~~~ MeshChunk [] ~~~ -pyffi.toaster:INFO: has vertex colors! -pyffi.toaster:INFO:Finished. - diff --git a/tests/spells/cgf/check/__init__.py b/tests/spells/cgf/check/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spells/cgf/check/test_tangentspace.py b/tests/spells/cgf/check/test_tangentspace.py new file mode 100644 index 000000000..251d7eba5 --- /dev/null +++ b/tests/spells/cgf/check/test_tangentspace.py @@ -0,0 +1,29 @@ +"""Regression test for tangent space algorithm""" +from tests.scripts.cgf import call_cgftoaster +from tests.utils import BaseCgfFileTestCase + + +class TestCheckTangentSpaceCgf(BaseCgfFileTestCase): + """Invoke the fix_texturepath spell check through nif toaster""" + + def setUp(self): + super(TestCheckTangentSpaceCgf, self).setUp() + self.src_name = "monkey.cgf" + super(TestCheckTangentSpaceCgf, self).copyFile() + super(TestCheckTangentSpaceCgf, self).readCgfData() + + def test_non_interactive_check_tangentspace(self): + """Check_tangentspace spell""" + call_cgftoaster("--raise", "check_tangentspace", "--noninteractive", "--verbose=1", self.dest_file) + """ + pyffi.toaster:INFO:=== tests/formats/cgf/monkey.cgf === + pyffi.toaster:INFO: --- check_tangentspace --- + pyffi.toaster:INFO: ~~~ NodeChunk [Merged] ~~~ + pyffi.toaster:INFO: ~~~ MeshChunk [] ~~~ + pyffi.toaster:INFO: recalculating new tangent space + pyffi.toaster:INFO: validating and checking old with new + pyffi.toaster:WARNING:... + ... + pyffi.toaster:INFO: ~~~ NodeChunk [CryExportNode_monkey-CGF-monkey-DoExport-MergeNodes] ~~~ + pyffi.toaster:INFO:Finished. + """ \ No newline at end of file diff --git a/tests/spells/cgf/check/test_vertex_colors.py b/tests/spells/cgf/check/test_vertex_colors.py new file mode 100644 index 000000000..15413fbd7 --- /dev/null +++ b/tests/spells/cgf/check/test_vertex_colors.py @@ -0,0 +1,47 @@ +"""Regression test for vertex color spells""" +from tests.scripts.cgf import call_cgftoaster +from tests.utils import BaseCgfFileTestCase + + +class TestCheckVertexColorCgf(BaseCgfFileTestCase): + """Invoke the check_vcols spell check through cgf toaster""" + + def setUp(self): + super(TestCheckVertexColorCgf, self).setUp() + self.src_name = "monkey.cgf" + super(TestCheckVertexColorCgf, self).copyFile() + super(TestCheckVertexColorCgf, self).readCgfData() + + def test_non_interactive_check_vcols(self): + """Check the vertex color spell""" + call_cgftoaster("--raise", "check_vcols", "--noninteractive", "--verbose=1", self.dest_file) + """ + pyffi.toaster:INFO:=== tests/formats/cgf/monkey.cgf === + pyffi.toaster:INFO: --- check_vcols --- + pyffi.toaster:INFO: ~~~ NodeChunk [Merged] ~~~ + pyffi.toaster:INFO: ~~~ MeshChunk [] ~~~ + pyffi.toaster:INFO: ~~~ NodeChunk [CryExportNode_monkey-CGF-monkey-DoExport-MergeNodes] ~~~ + pyffi.toaster:INFO:Finished. + """ + + +class TestCheckVColCgf(BaseCgfFileTestCase): + """Invoke the check_vcols spell check through cgf toaster""" + + def setUp(self): + super(TestCheckVColCgf, self).setUp() + self.src_name = "vcols.cgf" + super(TestCheckVColCgf, self).copyFile() + super(TestCheckVColCgf, self).readCgfData() + + def test_non_interactive_check_vcols(self): + """Check the vertex color spell""" + call_cgftoaster("--raise", "check_vcols", "--noninteractive", "--verbose=1", self.dest_file) + """ + pyffi.toaster:INFO:=== tests/formats/cgf/vcols.cgf === + pyffi.toaster:INFO: --- check_vcols --- + pyffi.toaster:INFO: ~~~ NodeChunk [Monkey] ~~~ + pyffi.toaster:INFO: ~~~ MeshChunk [] ~~~ + pyffi.toaster:INFO: has vertex colors! + pyffi.toaster:INFO:Finished. + """ \ No newline at end of file From a8e1cd9da5d7f4534d2447b9c9369c3c84d2ce98 Mon Sep 17 00:00:00 2001 From: neomonkeus Date: Wed, 15 Nov 2017 19:33:43 +0000 Subject: [PATCH 27/30] Update setup.py for tests and remove pep line length --- setup.cfg | 4 ++++ tests/spells/nif/fix/test_clampmaterialalpha.py | 16 ---------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/setup.cfg b/setup.cfg index 7ee1b503f..64a6e158c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,3 +3,7 @@ universal = 1 [metadata] license_file = LICENSE.rst + +[pep8] +# line length +ignore=E501 \ No newline at end of file diff --git a/tests/spells/nif/fix/test_clampmaterialalpha.py b/tests/spells/nif/fix/test_clampmaterialalpha.py index 58d7f2b5b..c21d97148 100644 --- a/tests/spells/nif/fix/test_clampmaterialalpha.py +++ b/tests/spells/nif/fix/test_clampmaterialalpha.py @@ -24,22 +24,6 @@ def test_explicit_fix_texture_path(self): spell = SpellClampMaterialAlpha(data=self.data) spell.recurse() - """ - pyffi.toaster:INFO:--- fix_clampmaterialalpha --- - pyffi.toaster:INFO: ~~~ NiNode [Scene Root] ~~~ - pyffi.toaster:INFO: ~~~ NiNode [Cone] ~~~ - pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 0] ~~~ - pyffi.toaster:INFO: ~~~ NiMaterialProperty [Red] ~~~ - pyffi.toaster:INFO: clamping alpha value (1000.000000 -> 1.0) - pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 1] ~~~ - pyffi.toaster:INFO: ~~~ NiMaterialProperty [Green] ~~~ - pyffi.toaster:INFO: clamping alpha value (-1000.000000 -> 0.0) - pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 2] ~~~ - pyffi.toaster:INFO: ~~~ NiMaterialProperty [Blue] ~~~ - pyffi.toaster:INFO: ~~~ NiTriShape [Tri Cone 3] ~~~ - pyffi.toaster:INFO: ~~~ NiMaterialProperty [Yellow] ~~~ - """ - # check that material alpha are no longer out of range assert_equals(self.data.roots[0].children[0].children[0].properties[0].alpha, 1.0) assert_equals(self.data.roots[0].children[0].children[1].properties[0].alpha, 0.0) From bf7d27753cb65e2eabf7865e7631fec6c4c7e609 Mon Sep 17 00:00:00 2001 From: HENDRIX-ZT2 Date: Fri, 13 Sep 2019 14:47:50 +0200 Subject: [PATCH 28/30] Fix: weights in partition instead of skindata Fixes skinning for Wildlife Park 2&3 - would scale mesh to zero. Could wrap the actual skinning in a helper function to re-use code and save some lines. --- pyffi/formats/nif/__init__.py | 45 +++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/pyffi/formats/nif/__init__.py b/pyffi/formats/nif/__init__.py index 16f7ffc3c..849866cab 100644 --- a/pyffi/formats/nif/__init__.py +++ b/pyffi/formats/nif/__init__.py @@ -4691,19 +4691,50 @@ def get_skin_deformation(self): normals = [ NifFormat.Vector3() for i in range(self.data.num_vertices) ] sumweights = [ 0.0 for i in range(self.data.num_vertices) ] skin_offset = skindata.get_transform() + # store one transform & rotation per bone + bone_transforms = [] for i, bone_block in enumerate(skininst.bones): bonedata = skindata.bone_list[i] bone_offset = bonedata.get_transform() bone_matrix = bone_block.get_transform(skelroot) transform = bone_offset * bone_matrix * skin_offset scale, rotation, translation = transform.get_scale_rotation_translation() - for skinweight in bonedata.vertex_weights: - index = skinweight.index - weight = skinweight.weight - vertices[index] += weight * (self.data.vertices[index] * transform) - if self.data.has_normals: - normals[index] += weight * (self.data.normals[index] * rotation) - sumweights[index] += weight + bone_transforms.append( (transform, rotation) ) + + # the usual case + if skindata.has_vertex_weights: + for i, bone_block in enumerate(skininst.bones): + bonedata = skindata.bone_list[i] + transform, rotation = bone_transforms[i] + for skinweight in bonedata.vertex_weights: + index = skinweight.index + weight = skinweight.weight + vertices[index] += weight * (self.data.vertices[index] * transform) + if self.data.has_normals: + normals[index] += weight * (self.data.normals[index] * rotation) + sumweights[index] += weight + # we must get weights from the partition + else: + skinpartition = skininst.skin_partition + for block in skinpartition.skin_partition_blocks: + # get transforms for this block + block_bone_transforms = [bone_transforms[i] for i in block.bones] + + # go over each vert in this block + for vert_index, vertex_weights, bone_indices in zip(block.vertex_map, + block.vertex_weights, + block.bone_indices): + # skip verts that were already processed in an earlier block + if sumweights[vert_index] != 0.0: + continue + # go over all 4 weight / bone pairs and transform this vert + for weight, b_i in zip(vertex_weights, bone_indices): + if weight > 0.0: + transform, rotation = block_bone_transforms[b_i] + vertices[vert_index] += weight * (self.data.vertices[vert_index] * transform) + if self.data.has_normals: + normals[vert_index] += weight * (self.data.normals[vert_index] * rotation) + sumweights[vert_index] += weight for i, s in enumerate(sumweights): if abs(s - 1.0) > 0.01: From ca8e07567281400c3504a45c6db1a7650be4d3fc Mon Sep 17 00:00:00 2001 From: HENDRIX-ZT2 Date: Fri, 13 Sep 2019 16:14:36 +0200 Subject: [PATCH 29/30] Fix: Import bhkLimitedHingeConstraint Had no attribute sub_constraint, causing import to fail due to apply_scale() being called on it. --- pyffi/formats/nif/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pyffi/formats/nif/__init__.py b/pyffi/formats/nif/__init__.py index 849866cab..9afd36842 100644 --- a/pyffi/formats/nif/__init__.py +++ b/pyffi/formats/nif/__init__.py @@ -2335,17 +2335,17 @@ class bhkLimitedHingeConstraint: def apply_scale(self, scale): """Scale data.""" # apply scale on transform - self.sub_constraint.limited_hinge.pivot_a.x *= scale - self.sub_constraint.limited_hinge.pivot_a.y *= scale - self.sub_constraint.limited_hinge.pivot_a.z *= scale - self.sub_constraint.limited_hinge.pivot_b.x *= scale - self.sub_constraint.limited_hinge.pivot_b.y *= scale - self.sub_constraint.limited_hinge.pivot_b.z *= scale + self.limited_hinge.pivot_a.x *= scale + self.limited_hinge.pivot_a.y *= scale + self.limited_hinge.pivot_a.z *= scale + self.limited_hinge.pivot_b.x *= scale + self.limited_hinge.pivot_b.y *= scale + self.limited_hinge.pivot_b.z *= scale def update_a_b(self, parent): """Update the B data from the A data. The parent argument is simply a common parent to the entities.""" - self.sub_constraint.limited_hinge.update_a_b(self.get_transform_a_b(parent)) + self.limited_hinge.update_a_b(self.get_transform_a_b(parent)) class bhkListShape: def get_mass_center_inertia(self, density = 1, solid = True): From 7b2609575bc4d40592dcee2cbdb03d94db071c15 Mon Sep 17 00:00:00 2001 From: HENDRIX-ZT2 Date: Fri, 13 Sep 2019 16:27:36 +0200 Subject: [PATCH 30/30] Fix: Import bhkMalleableConstraint Not tested because I didn't find one in the wild, but it has the exact same pattern found in bhkLimitedHingeConstraint, and no sub_constraint attribute is noted in the nif.xml, but the corrected ones are. --- pyffi/formats/nif/__init__.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pyffi/formats/nif/__init__.py b/pyffi/formats/nif/__init__.py index 9afd36842..2b044eb85 100644 --- a/pyffi/formats/nif/__init__.py +++ b/pyffi/formats/nif/__init__.py @@ -2406,24 +2406,24 @@ class bhkMalleableConstraint: def apply_scale(self, scale): """Scale data.""" # apply scale on transform - self.sub_constraint.ragdoll.pivot_a.x *= scale - self.sub_constraint.ragdoll.pivot_a.y *= scale - self.sub_constraint.ragdoll.pivot_a.z *= scale - self.sub_constraint.ragdoll.pivot_b.x *= scale - self.sub_constraint.ragdoll.pivot_b.y *= scale - self.sub_constraint.ragdoll.pivot_b.z *= scale - self.sub_constraint.limited_hinge.pivot_a.x *= scale - self.sub_constraint.limited_hinge.pivot_a.y *= scale - self.sub_constraint.limited_hinge.pivot_a.z *= scale - self.sub_constraint.limited_hinge.pivot_b.x *= scale - self.sub_constraint.limited_hinge.pivot_b.y *= scale - self.sub_constraint.limited_hinge.pivot_b.z *= scale + self.ragdoll.pivot_a.x *= scale + self.ragdoll.pivot_a.y *= scale + self.ragdoll.pivot_a.z *= scale + self.ragdoll.pivot_b.x *= scale + self.ragdoll.pivot_b.y *= scale + self.ragdoll.pivot_b.z *= scale + self.limited_hinge.pivot_a.x *= scale + self.limited_hinge.pivot_a.y *= scale + self.limited_hinge.pivot_a.z *= scale + self.limited_hinge.pivot_b.x *= scale + self.limited_hinge.pivot_b.y *= scale + self.limited_hinge.pivot_b.z *= scale def update_a_b(self, parent): """Update the B data from the A data.""" transform = self.get_transform_a_b(parent) - self.sub_constraint.limited_hinge.update_a_b(transform) - self.sub_constraint.ragdoll.update_a_b(transform) + self.limited_hinge.update_a_b(transform) + self.ragdoll.update_a_b(transform) class bhkMoppBvTreeShape: def get_mass_center_inertia(self, density=1, solid=True):