unitytk 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {unitytk-0.3.0/unitytk.egg-info → unitytk-0.4.0}/PKG-INFO +2 -2
- {unitytk-0.3.0 → unitytk-0.4.0}/pyproject.toml +7 -2
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_articulated_rig_runtime.py +16 -15
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_asset_delivery.py +5 -8
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_audio_events_integration.py +23 -19
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_base_test.py +62 -6
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_blender_render_effects_e2e.py +1 -5
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_blender_shadow_plane_integration.py +3 -7
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_blender_shot_metadata_integration.py +4 -10
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_clip_name_contract_integration.py +5 -9
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_controller_runtime_integration.py +1 -5
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_deploy_templates.py +150 -5
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_embedded_dependencies_integration.py +5 -7
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_emissive_groups_integration.py +1 -5
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_fade_window_preservation.py +1 -6
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_keyed_visibility.py +3 -11
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_lightmap_metadata_integration.py +382 -81
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_maya_surface_materials_integration.py +4 -7
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_multi_section_audio_integration.py +1 -14
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_render_effects_e2e.py +2 -2
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_render_opacity_controller.py +1 -6
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_render_opacity_e2e.py +5 -7
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_render_opacity_integration.py +1 -7
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_run_tests.py +17 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_shadow_plane_integration.py +5 -9
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_shadow_plane_runtime_integration.py +50 -15
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_shared_material_standalone.py +3 -11
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_shot_metadata_integration.py +99 -21
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_shots_audio_sidebyside_integration.py +15 -19
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_standalone_enduser.py +4 -11
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_temp_projects.py +117 -5
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/__init__.py +1 -1
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/ArticulatedRigController.cs +81 -249
- unitytk-0.4.0/unitytk/templates/ArticulatedRig/ArticulationRecord.g.cs +330 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/AudioEvent/AudioEventController.cs +63 -124
- unitytk-0.4.0/unitytk/templates/AudioEvent/AudioRecord.g.cs +260 -0
- unitytk-0.4.0/unitytk/templates/AudioEvent/AudioRecord.g.cs.meta +11 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/EmissiveGroup/EmissiveGroupController.cs +28 -56
- unitytk-0.4.0/unitytk/templates/EmissiveGroup/EmissiveGroupsRecord.g.cs +268 -0
- unitytk-0.4.0/unitytk/templates/EmissiveGroup/EmissiveGroupsRecord.g.cs.meta +11 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableLit.shader +20 -2
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableShading.cs +134 -24
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/HandoffBlock.g.cs +303 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/HandoffBlock.g.cs.meta +11 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/LightmapMetadataController.cs +224 -251
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/LightmapRecord.g.cs +466 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/LightmapRecord.g.cs.meta +11 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/MapAbsence.g.cs +18 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/MapAbsence.g.cs.meta +11 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/MaterialRecord.cs +81 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/MaterialRecord.cs.meta +11 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/MaterialRecord.g.cs +291 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/MaterialRecord.g.cs.meta +11 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/RenderingPolicy.g.cs +50 -0
- unitytk-0.4.0/unitytk/templates/LightmapMetadata/RenderingPolicy.g.cs.meta +11 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/MayaSurface/MayaSurfaceMaterialImporter.cs +10 -12
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/README.md +33 -28
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShadowPlane/ShadowPlane.shader +12 -5
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShadowPlane/ShadowPlaneController.cs +109 -111
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShadowPlane/ShadowPlaneHorizon.hlsl +4 -2
- unitytk-0.4.0/unitytk/templates/ShadowPlane/ShadowRecord.g.cs +419 -0
- unitytk-0.4.0/unitytk/templates/ShadowPlane/ShadowRecord.g.cs.meta +11 -0
- unitytk-0.4.0/unitytk/templates/ShotMetadata/AnimationRecord.g.cs +272 -0
- unitytk-0.4.0/unitytk/templates/ShotMetadata/AnimationRecord.g.cs.meta +11 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShotMetadata/ShotMetadataController.cs +56 -55
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/UnitytkSettings.cs +331 -16
- {unitytk-0.3.0 → unitytk-0.4.0/unitytk.egg-info}/PKG-INFO +2 -2
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk.egg-info/SOURCES.txt +20 -0
- unitytk-0.4.0/unitytk.egg-info/requires.txt +1 -0
- unitytk-0.3.0/unitytk/templates/ArticulatedRig/ArticulationRecord.g.cs +0 -202
- unitytk-0.3.0/unitytk.egg-info/requires.txt +0 -1
- {unitytk-0.3.0 → unitytk-0.4.0}/LICENSE +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/MANIFEST.in +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/docs/README.md +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/setup.cfg +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_bool_to_fade_curve.py +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_launcher.py +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/test/test_scene_builder.py +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/asset_delivery.py +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/launcher.py +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/scene_builder.py +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/template_deployer.py +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/ArticulatedRigController.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/ArticulatedRigPointerGrab.cs +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/ArticulatedRigPointerGrab.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/ArticulationRecord.g.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/XR/ArticulatedRigXRGrab.cs +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/XR/ArticulatedRigXRGrab.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/XR/ArticulatedRigXRSetup.cs +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/XR/ArticulatedRigXRSetup.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/XR/M3trik.Unitytk.XR.asmdef +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/XR/M3trik.Unitytk.XR.asmdef.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig/XR.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ArticulatedRig.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/AudioEvent/AudioEventController.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/AudioEvent.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/EmissiveGroup/EmissiveGroupController.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/EmissiveGroup/EmissiveGroups.hlsl +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/EmissiveGroup/EmissiveGroups.hlsl.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/EmissiveGroup/EmissiveGroupsLit.shader +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/EmissiveGroup/EmissiveGroupsLit.shader.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/EmissiveGroup.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableCubeUV.hlsl +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableCubeUV.hlsl.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableLit.shader.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverablePmrem.cs +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverablePmrem.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableShading.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableToneMap.shader +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableToneMap.shader.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableToneMapFeature.cs +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/DeliverableToneMapFeature.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata/LightmapMetadataController.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/LightmapMetadata.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/M3trik.Unitytk.asmdef +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/M3trik.Unitytk.asmdef.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/MayaSurface/MayaSurfaceMaterialImporter.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/MayaSurface.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/README.md.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/RenderEffects/RenderEffectsController.cs +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/RenderEffects/RenderEffectsController.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/RenderEffects.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShadowPlane/ShadowPlane.shader.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShadowPlane/ShadowPlaneController.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShadowPlane/ShadowPlaneHorizon.hlsl.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShadowPlane.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShotMetadata/ShotMetadataController.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/ShotMetadata.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/UnitytkSettings.cs.meta +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk/templates/__init__.py +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk.egg-info/dependency_links.txt +0 -0
- {unitytk-0.3.0 → unitytk-0.4.0}/unitytk.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unitytk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: A modular Python toolkit for Unity interaction.
|
|
5
5
|
Author-email: Ryan Simpson <m3trik@outlook.com>
|
|
6
6
|
License: MIT
|
|
@@ -13,7 +13,7 @@ Classifier: Operating System :: POSIX :: Linux
|
|
|
13
13
|
Requires-Python: >=3.9
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
License-File: LICENSE
|
|
16
|
-
Requires-Dist: pythontk>=0.
|
|
16
|
+
Requires-Dist: pythontk>=0.17.0
|
|
17
17
|
Dynamic: license-file
|
|
18
18
|
|
|
19
19
|
[](../test/)
|
|
@@ -17,7 +17,12 @@ classifiers = [
|
|
|
17
17
|
]
|
|
18
18
|
# The floor is HAND-RATCHETED: unitytk is off-chain from m3trik/push.ps1, so no
|
|
19
19
|
# release cascade bumps it.
|
|
20
|
-
# pythontk 0.
|
|
20
|
+
# pythontk 0.17.0, the release this one ships and was tested with: the
|
|
21
|
+
# templates read the scene records by their renamed keys alone (`animation`,
|
|
22
|
+
# `audio`, `lightmaps`, `shadows`, `materials`, `handoff` v3 -- was
|
|
23
|
+
# `shot_metadata`, `audio_manifest`, `lightmap_metadata`, `shadow_metadata`),
|
|
24
|
+
# and only pythontk 0.17.0 writes them; an older one's FBX imports with no
|
|
25
|
+
# shots, audio, lightmaps or shadows. Before it, pythontk 0.13.1: an FBX
|
|
21
26
|
# deliverable carries the files its records name through
|
|
22
27
|
# `FbxMedia.embed_dependencies` (new in 0.13.1; on 0.13.0 the copy deliverer
|
|
23
28
|
# ships the FBX without its maps), and the suite holds the templates to its
|
|
@@ -27,7 +32,7 @@ classifiers = [
|
|
|
27
32
|
# needs 0.8.84: it scans through `AppLauncher.scan_install_dirs` (new in
|
|
28
33
|
# 0.8.72) and needs its pattern order to be a priority (0.8.84), so the Hub's
|
|
29
34
|
# chosen install location wins over the default.
|
|
30
|
-
dependencies = ["pythontk>=0.
|
|
35
|
+
dependencies = ["pythontk>=0.17.0"]
|
|
31
36
|
|
|
32
37
|
[project.urls]
|
|
33
38
|
Homepage = "https://github.com/m3trik/unitytk"
|
|
@@ -857,7 +857,9 @@ class LiveExport:
|
|
|
857
857
|
|
|
858
858
|
|
|
859
859
|
def _invalid_rigs():
|
|
860
|
-
"""Rigs the reference refuses (ValueError); the port must refuse them too.
|
|
860
|
+
"""Rigs the reference refuses (ValueError); the port must refuse them too.
|
|
861
|
+
Each is a rig as the record states it -- every key its shape requires --
|
|
862
|
+
so each is refused for its own fault, not a key left out."""
|
|
861
863
|
base = {"name": "bad", "joints": [], "grab": []}
|
|
862
864
|
|
|
863
865
|
def rig(*joints):
|
|
@@ -865,6 +867,9 @@ def _invalid_rigs():
|
|
|
865
867
|
out["joints"] = list(joints)
|
|
866
868
|
return out
|
|
867
869
|
|
|
870
|
+
def channel(name, lo=None, hi=None):
|
|
871
|
+
return {"channel": name, "min": lo, "max": hi, "weight": 1.0}
|
|
872
|
+
|
|
868
873
|
ok = {
|
|
869
874
|
"name": "a",
|
|
870
875
|
"parent": None,
|
|
@@ -876,10 +881,10 @@ def _invalid_rigs():
|
|
|
876
881
|
return [
|
|
877
882
|
rig(ok, dict(ok, name="b", parent=1)), # parent not earlier
|
|
878
883
|
rig(dict(ok, rotate_order="xxy")), # unknown order
|
|
879
|
-
rig(dict(ok, channels=[
|
|
880
|
-
rig(dict(ok, channels=[
|
|
881
|
-
rig(dict(ok, channels=[
|
|
882
|
-
rig(ok, dict(ok, name="b", parent=0, channels=[
|
|
884
|
+
rig(dict(ok, channels=[channel("sx")])), # unknown channel
|
|
885
|
+
rig(dict(ok, channels=[channel("rx"), channel("rx")])), # twice
|
|
886
|
+
rig(dict(ok, channels=[channel("rz", lo=10, hi=-10)])), # reversed
|
|
887
|
+
rig(ok, dict(ok, name="b", parent=0, channels=[channel("tx", hi=3)])), # valid
|
|
883
888
|
] # fmt: skip
|
|
884
889
|
|
|
885
890
|
|
|
@@ -915,7 +920,7 @@ public class ArticulatedRigVerifier
|
|
|
915
920
|
static M.Frame[] Frames(object o) => L(o).Select(f => new M.Frame(Vec(L(f)[0]), Qt(L(f)[1]))).ToArray();
|
|
916
921
|
|
|
917
922
|
// ---- JSON out ---------------------------------------------------------
|
|
918
|
-
static string N(double v) =>
|
|
923
|
+
static string N(double v) => UnitytkJson.Number(v);
|
|
919
924
|
static string B(bool b) => b ? "true" : "false";
|
|
920
925
|
static string S(string s) => "\"" + (s ?? "").Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n").Replace("\r", "") + "\"";
|
|
921
926
|
static string A(double[] a) => a == null ? "null" : "[" + string.Join(",", a.Select(N)) + "]";
|
|
@@ -934,7 +939,7 @@ public class ArticulatedRigVerifier
|
|
|
934
939
|
try
|
|
935
940
|
{
|
|
936
941
|
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
|
937
|
-
inputs = O(
|
|
942
|
+
inputs = O(UnitytkJson.Parse(File.ReadAllText(INPUTS)));
|
|
938
943
|
}
|
|
939
944
|
catch (Exception e) { Put("inputs_error", S(e.ToString())); }
|
|
940
945
|
if (inputs != null)
|
|
@@ -1720,7 +1725,7 @@ class TestArticulatedRigRuntime(unittest.TestCase):
|
|
|
1720
1725
|
|
|
1721
1726
|
@classmethod
|
|
1722
1727
|
def setUpClass(cls):
|
|
1723
|
-
cls.temp_dir = TempProjects.allocate("articulated_rig_runtime")
|
|
1728
|
+
cls.temp_dir = TempProjects.allocate("articulated_rig_runtime", cls)
|
|
1724
1729
|
cls.unity = None
|
|
1725
1730
|
cls.doc = ptk.ArticulationConformance.cases(seed=SEED, per_rig=PER_RIG)
|
|
1726
1731
|
cls.scenario = ControllerScenario(cls.doc)
|
|
@@ -1756,10 +1761,6 @@ class TestArticulatedRigRuntime(unittest.TestCase):
|
|
|
1756
1761
|
}
|
|
1757
1762
|
logger.info(f"Temp dir: {cls.temp_dir}")
|
|
1758
1763
|
|
|
1759
|
-
@classmethod
|
|
1760
|
-
def tearDownClass(cls):
|
|
1761
|
-
logger.info(f"Results preserved in: {cls.temp_dir}")
|
|
1762
|
-
|
|
1763
1764
|
def _results(self):
|
|
1764
1765
|
unity = self.__class__.unity
|
|
1765
1766
|
if not unity:
|
|
@@ -2701,7 +2702,7 @@ public class ArticulatedRigXRVerifier
|
|
|
2701
2702
|
const string INPUTS = @"__INPUTS_PATH__";
|
|
2702
2703
|
|
|
2703
2704
|
static string B(bool b) => b ? "true" : "false";
|
|
2704
|
-
static string N(double v) =>
|
|
2705
|
+
static string N(double v) => UnitytkJson.Number(v);
|
|
2705
2706
|
static IList<object> L(object o) => (IList<object>)o;
|
|
2706
2707
|
static float F(object o) => (float)(double)o;
|
|
2707
2708
|
|
|
@@ -2710,7 +2711,7 @@ public class ArticulatedRigXRVerifier
|
|
|
2710
2711
|
var sb = new StringBuilder("{\n");
|
|
2711
2712
|
try
|
|
2712
2713
|
{
|
|
2713
|
-
var inputs = (IDictionary<string, object>)
|
|
2714
|
+
var inputs = (IDictionary<string, object>)UnitytkJson.Parse(File.ReadAllText(INPUTS));
|
|
2714
2715
|
var names = L(inputs["names"]);
|
|
2715
2716
|
var parents = L(inputs["parents"]);
|
|
2716
2717
|
var locals = L(inputs["locals"]);
|
|
@@ -2776,7 +2777,7 @@ class TestArticulatedRigXRI(unittest.TestCase):
|
|
|
2776
2777
|
|
|
2777
2778
|
@classmethod
|
|
2778
2779
|
def setUpClass(cls):
|
|
2779
|
-
cls.temp_dir = TempProjects.allocate("articulated_rig_xri")
|
|
2780
|
+
cls.temp_dir = TempProjects.allocate("articulated_rig_xri", cls)
|
|
2780
2781
|
cls.unity = None
|
|
2781
2782
|
|
|
2782
2783
|
@EnvSkip.unless(_unity_available(), "no Unity editor found")
|
|
@@ -394,16 +394,13 @@ class SelfContainedDeliveryTest(unittest.TestCase):
|
|
|
394
394
|
decision of 2026-10-05: every dependency embedded, zero sidecar files)."""
|
|
395
395
|
|
|
396
396
|
RECORDS = {
|
|
397
|
-
"
|
|
398
|
-
"version":
|
|
397
|
+
"lightmaps": {
|
|
398
|
+
"version": 2,
|
|
399
|
+
"unit_scale": 0.01,
|
|
399
400
|
"objects": [{"name": "Crate", "map": "Crate_Lightmap.exr", "uvIndex": 1}],
|
|
400
|
-
"probe": {
|
|
401
|
-
"map": "Room_Probe.exr",
|
|
402
|
-
"position": [0, 0, 0],
|
|
403
|
-
"unit_scale": 0.01,
|
|
404
|
-
},
|
|
401
|
+
"probe": {"map": "Room_Probe.exr", "position": [0, 0, 0], "box": None},
|
|
405
402
|
},
|
|
406
|
-
"
|
|
403
|
+
"shadows": {
|
|
407
404
|
"version": 2,
|
|
408
405
|
"planes": [
|
|
409
406
|
{
|
|
@@ -6,13 +6,13 @@ Validates the new single-carrier audio events pipeline end-to-end:
|
|
|
6
6
|
1. Maya (mayapy): Author audio tracks on the canonical ``data_internal``
|
|
7
7
|
carrier via :class:`mayatk.audio_utils.AudioUtils`, then call
|
|
8
8
|
:meth:`mayatk.audio_utils.audio_clips.AudioClips.prepare_for_export`
|
|
9
|
-
to bake ``
|
|
9
|
+
to bake the ``audio`` record as a plain string channel on ``data_export``
|
|
10
10
|
(the authoring state stays keyed on ``data_internal`` and never exports).
|
|
11
11
|
Animate a cube so the FBX contains at least one ``AnimationClip``
|
|
12
12
|
for the audio events to bind to. Export FBX.
|
|
13
13
|
2. Unity (batchmode): Import FBX with the real
|
|
14
14
|
``AudioEventController.cs`` deployed. Verify:
|
|
15
|
-
a. the ``
|
|
15
|
+
a. the ``audio`` record arrives on the ``data_export``
|
|
16
16
|
GameObject (raw user-property),
|
|
17
17
|
b. the importer auto-attaches an ``AudioEventController`` to the
|
|
18
18
|
prefab **root** (and explicitly NOT to the ``data_export``
|
|
@@ -414,17 +414,13 @@ class TestAudioEventsIntegration(unittest.TestCase):
|
|
|
414
414
|
|
|
415
415
|
@classmethod
|
|
416
416
|
def setUpClass(cls):
|
|
417
|
-
cls.temp_dir = TempProjects.allocate("audio_events_integ")
|
|
417
|
+
cls.temp_dir = TempProjects.allocate("audio_events_integ", cls)
|
|
418
418
|
cls.fbx_path = None
|
|
419
419
|
cls.maya_results = None
|
|
420
420
|
cls.unity_results = None
|
|
421
421
|
cls.postproc = None
|
|
422
422
|
logger.info(f"Temp dir: {cls.temp_dir}")
|
|
423
423
|
|
|
424
|
-
@classmethod
|
|
425
|
-
def tearDownClass(cls):
|
|
426
|
-
logger.info(f"Results preserved in: {cls.temp_dir}")
|
|
427
|
-
|
|
428
424
|
# ------------------------------------------------------------------
|
|
429
425
|
# Step 1: Maya export via AudioClips.prepare_for_export
|
|
430
426
|
# ------------------------------------------------------------------
|
|
@@ -469,7 +465,7 @@ class TestAudioEventsIntegration(unittest.TestCase):
|
|
|
469
465
|
self.__class__.fbx_path = r["fbx_path"]
|
|
470
466
|
self.assertTrue(r["fbx_exists"])
|
|
471
467
|
self.assertEqual(r["carrier"], "data_internal")
|
|
472
|
-
self.assertEqual(r["manifest_attr"], "
|
|
468
|
+
self.assertEqual(r["manifest_attr"], "audio")
|
|
473
469
|
# v2 manifest: versioned JSON. No shots in this scene, so events are
|
|
474
470
|
# unscoped (clip "") with frames RELATIVE to Maya's playback min
|
|
475
471
|
# (= 1 here) — Unity's clip clock maps Maya frame `min` to time 0.
|
|
@@ -623,11 +619,11 @@ class TestAudioEventsIntegration(unittest.TestCase):
|
|
|
623
619
|
f"in postprocessor results: {list(postproc)}",
|
|
624
620
|
)
|
|
625
621
|
self.assertIn(
|
|
626
|
-
"
|
|
622
|
+
"audio",
|
|
627
623
|
props,
|
|
628
|
-
f"
|
|
624
|
+
f"audio record missing on {name}; saw: {list(props)}",
|
|
629
625
|
)
|
|
630
|
-
manifest = props["
|
|
626
|
+
manifest = props["audio"]
|
|
631
627
|
for label in ("footstep", "jump", "land"):
|
|
632
628
|
self.assertIn(label, manifest)
|
|
633
629
|
|
|
@@ -648,7 +644,7 @@ class TestAudioEventsIntegration(unittest.TestCase):
|
|
|
648
644
|
|
|
649
645
|
# (c) the real AudioEventImporter auto-attached the controller to
|
|
650
646
|
# the prefab ROOT (where the Animator will live), NOT to the GO
|
|
651
|
-
# carrying
|
|
647
|
+
# carrying the audio record — this is the runtime-dispatch invariant.
|
|
652
648
|
self.assertTrue(
|
|
653
649
|
unity.get("controller_on_root"),
|
|
654
650
|
"AudioEventController should live on the prefab root so "
|
|
@@ -739,7 +735,7 @@ class TestAudioEventsIntegration(unittest.TestCase):
|
|
|
739
735
|
|
|
740
736
|
|
|
741
737
|
# ======================================================================
|
|
742
|
-
# Carrier precedence: one
|
|
738
|
+
# Carrier precedence: one audio record per model, the scene's own first
|
|
743
739
|
# ======================================================================
|
|
744
740
|
|
|
745
741
|
CARRIER_VERIFIER_CS = r"""
|
|
@@ -784,7 +780,7 @@ public class AudioCarrierVerifier
|
|
|
784
780
|
|
|
785
781
|
|
|
786
782
|
class TestAudioCarrierPrecedence(unittest.TestCase):
|
|
787
|
-
"""An FBX carrying ``
|
|
783
|
+
"""An FBX carrying the ``audio`` record on several carriers plays the
|
|
788
784
|
scene's own only.
|
|
789
785
|
|
|
790
786
|
An assembly ships a stray ``data_export1`` (and a module's
|
|
@@ -805,18 +801,26 @@ class TestAudioCarrierPrecedence(unittest.TestCase):
|
|
|
805
801
|
|
|
806
802
|
@classmethod
|
|
807
803
|
def setUpClass(cls):
|
|
808
|
-
cls.temp_dir = TempProjects.allocate("carrier_precedence")
|
|
804
|
+
cls.temp_dir = TempProjects.allocate("carrier_precedence", cls)
|
|
809
805
|
|
|
810
806
|
@BlenderEnv.skip_unless_available()
|
|
811
807
|
@EnvSkip.unless(_unity_available(), "no Unity editor found")
|
|
812
808
|
def test_the_scenes_own_carrier_wins(self):
|
|
813
|
-
own = {
|
|
814
|
-
|
|
809
|
+
own = {
|
|
810
|
+
"version": 2,
|
|
811
|
+
"fps": 24.0,
|
|
812
|
+
"events": [{"clip": "", "frame": 0, "name": "footstep"}],
|
|
813
|
+
}
|
|
814
|
+
stray = {
|
|
815
|
+
"version": 2,
|
|
816
|
+
"fps": 24.0,
|
|
817
|
+
"events": [{"clip": "", "frame": 3, "name": "door"}],
|
|
818
|
+
}
|
|
815
819
|
fixture = CarrierFbx.build(
|
|
816
820
|
os.path.join(self.temp_dir, "assembly.fbx"),
|
|
817
821
|
{
|
|
818
|
-
"data_export": {"
|
|
819
|
-
"data_export1": {"
|
|
822
|
+
"data_export": {"audio": own},
|
|
823
|
+
"data_export1": {"audio": stray},
|
|
820
824
|
},
|
|
821
825
|
)
|
|
822
826
|
|
|
@@ -656,6 +656,64 @@ class TemplateSourcesTest(unittest.TestCase):
|
|
|
656
656
|
with self.assertRaises(FileNotFoundError): # a bare, pre-move name
|
|
657
657
|
TemplateSources.copy_flat(["RenderEffectsController.cs"], dest)
|
|
658
658
|
|
|
659
|
+
def test_a_staged_set_must_carry_the_generated_records_it_reads(self):
|
|
660
|
+
"""AudioEventController.cs staged without AudioRecord.g.cs compiled to
|
|
661
|
+
CS0103 in Unity and only the batch editor said so (2026-10-23)."""
|
|
662
|
+
controller = "AudioEvent/AudioEventController.cs"
|
|
663
|
+
record = "AudioEvent/AudioRecord.g.cs"
|
|
664
|
+
self.assertEqual(TemplateSources.missing_records([controller]), [record])
|
|
665
|
+
self.assertEqual(TemplateSources.missing_records([controller, record]), [])
|
|
666
|
+
# A record named only in a comment is no dependency.
|
|
667
|
+
self.assertEqual(TemplateSources.missing_records(["UnitytkSettings.cs"]), [])
|
|
668
|
+
|
|
669
|
+
import pythontk as ptk
|
|
670
|
+
|
|
671
|
+
store = ptk.TempArtifacts("unitytk_template_sources", policy="scoped")
|
|
672
|
+
self.addCleanup(store.cleanup)
|
|
673
|
+
dest = os.path.join(store.dir_path(), "Scripts")
|
|
674
|
+
with self.assertRaises(ValueError) as ctx:
|
|
675
|
+
TemplateSources.copy_flat(["UnitytkSettings.cs", controller], dest)
|
|
676
|
+
self.assertIn(record, str(ctx.exception))
|
|
677
|
+
self.assertFalse(os.path.exists(dest), "a refused set copies nothing")
|
|
678
|
+
|
|
679
|
+
def test_every_suite_stages_a_compile_closed_set(self):
|
|
680
|
+
"""Each literal set a suite hands TemplateSources carries the records
|
|
681
|
+
its files read -- checked here, where no Unity is needed, because the
|
|
682
|
+
suites that stage them skip on every machine without one."""
|
|
683
|
+
calls = {"copy_flat", "available"}
|
|
684
|
+
offenders = []
|
|
685
|
+
for path in _source_files(".py", exclude=("base_test.py",)):
|
|
686
|
+
with open(path, encoding="utf-8", errors="replace") as fh:
|
|
687
|
+
tree = ast.parse(fh.read(), path)
|
|
688
|
+
consts = {
|
|
689
|
+
t.id: node.value
|
|
690
|
+
for node in tree.body
|
|
691
|
+
if isinstance(node, ast.Assign)
|
|
692
|
+
for t in node.targets
|
|
693
|
+
if isinstance(t, ast.Name)
|
|
694
|
+
}
|
|
695
|
+
for node in ast.walk(tree):
|
|
696
|
+
if not (
|
|
697
|
+
isinstance(node, ast.Call)
|
|
698
|
+
and isinstance(node.func, ast.Attribute)
|
|
699
|
+
and node.func.attr in calls
|
|
700
|
+
and isinstance(node.func.value, ast.Name)
|
|
701
|
+
and node.func.value.id == "TemplateSources"
|
|
702
|
+
and node.args
|
|
703
|
+
):
|
|
704
|
+
continue
|
|
705
|
+
arg = node.args[0]
|
|
706
|
+
arg = consts.get(arg.id, arg) if isinstance(arg, ast.Name) else arg
|
|
707
|
+
try:
|
|
708
|
+
names = ast.literal_eval(arg)
|
|
709
|
+
except ValueError:
|
|
710
|
+
continue # built at run time: copy_flat checks it then
|
|
711
|
+
missing = TemplateSources.missing_records(names)
|
|
712
|
+
if missing:
|
|
713
|
+
rel = os.path.relpath(path, REPO_ROOT)
|
|
714
|
+
offenders.append(f"{rel}:{node.lineno} lacks {missing}")
|
|
715
|
+
self.assertEqual(offenders, [], "\n".join(offenders))
|
|
716
|
+
|
|
659
717
|
def test_no_suite_joins_the_templates_dir_itself(self):
|
|
660
718
|
"""Five suites joined their own templates dir with a bare file name;
|
|
661
719
|
one of them silently skipped a copy that no longer resolved."""
|
|
@@ -679,10 +737,10 @@ class UserPropsProbeTest(unittest.TestCase):
|
|
|
679
737
|
self.assertFalse(UserPropsProbe.is_carrier(None))
|
|
680
738
|
|
|
681
739
|
def test_find_carrier_returns_the_matching_entry(self):
|
|
682
|
-
postproc = {"root": {}, "data_export 1": {"
|
|
740
|
+
postproc = {"root": {}, "data_export 1": {"animation": "{}"}}
|
|
683
741
|
name, props = UserPropsProbe.find_carrier(postproc)
|
|
684
742
|
self.assertEqual(name, "data_export 1")
|
|
685
|
-
self.assertEqual(props, {"
|
|
743
|
+
self.assertEqual(props, {"animation": "{}"})
|
|
686
744
|
|
|
687
745
|
def test_find_carrier_is_none_when_absent(self):
|
|
688
746
|
self.assertEqual(UserPropsProbe.find_carrier({"root": {}}), (None, None))
|
|
@@ -694,10 +752,8 @@ class UserPropsProbeTest(unittest.TestCase):
|
|
|
694
752
|
self.assertFalse(UserPropsProbe.is_carrier("root/data_export/child"))
|
|
695
753
|
|
|
696
754
|
def test_carrier_props_returns_just_the_props(self):
|
|
697
|
-
postproc = {"root": {}, "root/data_export": {"
|
|
698
|
-
self.assertEqual(
|
|
699
|
-
UserPropsProbe.carrier_props(postproc), {"shot_metadata": "{}"}
|
|
700
|
-
)
|
|
755
|
+
postproc = {"root": {}, "root/data_export": {"animation": "{}"}}
|
|
756
|
+
self.assertEqual(UserPropsProbe.carrier_props(postproc), {"animation": "{}"})
|
|
701
757
|
|
|
702
758
|
def test_carrier_props_is_none_when_absent(self):
|
|
703
759
|
self.assertIsNone(UserPropsProbe.carrier_props({"root": {}}))
|
|
@@ -306,15 +306,11 @@ class TestBlenderRenderEffectsE2E(unittest.TestCase):
|
|
|
306
306
|
|
|
307
307
|
@classmethod
|
|
308
308
|
def setUpClass(cls):
|
|
309
|
-
cls.temp_dir = TempProjects.allocate("blender_effects_e2e")
|
|
309
|
+
cls.temp_dir = TempProjects.allocate("blender_effects_e2e", cls)
|
|
310
310
|
cls.blender_results = None
|
|
311
311
|
cls.unity_results = None
|
|
312
312
|
logger.info(f"Temp dir: {cls.temp_dir}")
|
|
313
313
|
|
|
314
|
-
@classmethod
|
|
315
|
-
def tearDownClass(cls):
|
|
316
|
-
logger.info(f"Results preserved in: {cls.temp_dir}")
|
|
317
|
-
|
|
318
314
|
@BlenderEnv.skip_unless_available()
|
|
319
315
|
def test_01_blender_export(self):
|
|
320
316
|
"""Author both channels and the keyed visibility; write both ways."""
|
|
@@ -198,7 +198,7 @@ ok = exporter.perform_export(
|
|
|
198
198
|
tasks={"export_data_node": True},
|
|
199
199
|
)
|
|
200
200
|
fbx_path = os.path.join(output_dir, __FBX_NAME__ + ".fbx")
|
|
201
|
-
payload = btk.DataNodes.read(ptk.Scope.DELIVERABLE,
|
|
201
|
+
payload = btk.DataNodes.read(ptk.Scope.DELIVERABLE, ptk.SceneRecords.SHADOWS.key)
|
|
202
202
|
|
|
203
203
|
# The maps ship loose beside the FBX: the records name them by file name.
|
|
204
204
|
textures = []
|
|
@@ -542,15 +542,11 @@ class TestBlenderShadowPlaneIntegration(unittest.TestCase):
|
|
|
542
542
|
|
|
543
543
|
@classmethod
|
|
544
544
|
def setUpClass(cls):
|
|
545
|
-
cls.temp_dir = TempProjects.allocate("blender_shadow_integ")
|
|
545
|
+
cls.temp_dir = TempProjects.allocate("blender_shadow_integ", cls)
|
|
546
546
|
cls.blender_results = None
|
|
547
547
|
cls.unity_results = None
|
|
548
548
|
logger.info(f"Temp dir: {cls.temp_dir}")
|
|
549
549
|
|
|
550
|
-
@classmethod
|
|
551
|
-
def tearDownClass(cls):
|
|
552
|
-
logger.info(f"Results preserved in: {cls.temp_dir}")
|
|
553
|
-
|
|
554
550
|
def _blender(self):
|
|
555
551
|
blender = self.__class__.blender_results
|
|
556
552
|
if not blender:
|
|
@@ -590,7 +586,7 @@ class TestBlenderShadowPlaneIntegration(unittest.TestCase):
|
|
|
590
586
|
self.assertAlmostEqual(payload.get("unit_scale"), 1.0, places=6)
|
|
591
587
|
records = {p["name"]: p for p in payload.get("planes", [])}
|
|
592
588
|
for key, rig in r["rigs"].items():
|
|
593
|
-
self.assertIn(rig["plane"], records, f"{key}: no
|
|
589
|
+
self.assertIn(rig["plane"], records, f"{key}: no shadows record")
|
|
594
590
|
self.assertEqual(records[r["rigs"]["horizon"]["plane"]]["type"], "horizon")
|
|
595
591
|
self.assertEqual(
|
|
596
592
|
records[r["rigs"]["sun"]["plane"]]["source_type"], "directional"
|
|
@@ -151,7 +151,7 @@ for name, mode in VARIANTS.items():
|
|
|
151
151
|
)
|
|
152
152
|
path = os.path.join(output_dir, name + ".fbx")
|
|
153
153
|
exists = bool(ok) and os.path.exists(path)
|
|
154
|
-
meta = btk.DataNodes.read(ptk.Scope.DELIVERABLE,
|
|
154
|
+
meta = btk.DataNodes.read(ptk.Scope.DELIVERABLE, ptk.SceneRecords.SHOTS.key)
|
|
155
155
|
variants[name] = {
|
|
156
156
|
"mode": mode,
|
|
157
157
|
"fbx_exists": exists,
|
|
@@ -181,16 +181,12 @@ class TestBlenderShotMetadataIntegration(unittest.TestCase):
|
|
|
181
181
|
|
|
182
182
|
@classmethod
|
|
183
183
|
def setUpClass(cls):
|
|
184
|
-
cls.temp_dir = TempProjects.allocate("blender_shot_meta_integ")
|
|
184
|
+
cls.temp_dir = TempProjects.allocate("blender_shot_meta_integ", cls)
|
|
185
185
|
cls.blender_results = None
|
|
186
186
|
cls.unity_results = None
|
|
187
187
|
cls.postproc = None
|
|
188
188
|
logger.info(f"Temp dir: {cls.temp_dir}")
|
|
189
189
|
|
|
190
|
-
@classmethod
|
|
191
|
-
def tearDownClass(cls):
|
|
192
|
-
logger.info(f"Results preserved in: {cls.temp_dir}")
|
|
193
|
-
|
|
194
190
|
# ---- Step 1: Blender export ----------------------------------------
|
|
195
191
|
|
|
196
192
|
@BlenderEnv.skip_unless_available()
|
|
@@ -217,7 +213,6 @@ class TestBlenderShotMetadataIntegration(unittest.TestCase):
|
|
|
217
213
|
{c: (s["start"], s["end"]) for c, s in shots.items()}, SHOTS, name
|
|
218
214
|
)
|
|
219
215
|
self.assertEqual(shots["A01"]["description"], "Open the hangar doors")
|
|
220
|
-
self.assertEqual(shots["A01"]["section"], "A")
|
|
221
216
|
# Shots Only ships the shots; Full Sequence Only ships one take.
|
|
222
217
|
self.assertEqual(r["variants"]["shot_clips_shots"]["takes"], sorted(SHOTS))
|
|
223
218
|
self.assertEqual(len(r["variants"]["shot_clips_full"]["takes"]), 1)
|
|
@@ -313,8 +308,8 @@ class TestBlenderShotMetadataIntegration(unittest.TestCase):
|
|
|
313
308
|
self.assertTrue(unity.get("postprocessor_fired"))
|
|
314
309
|
carrier = UserPropsProbe.carrier_props(self.__class__.postproc or {})
|
|
315
310
|
self.assertIsNotNone(carrier, "no data_export carrier arrived")
|
|
316
|
-
self.assertIn("
|
|
317
|
-
self.assertIn("Open the hangar doors", carrier["
|
|
311
|
+
self.assertIn("animation", carrier)
|
|
312
|
+
self.assertIn("Open the hangar doors", carrier["animation"])
|
|
318
313
|
|
|
319
314
|
self.assertTrue(unity.get("prefab_loaded"))
|
|
320
315
|
self.assertTrue(unity.get("data_export_found"))
|
|
@@ -326,7 +321,6 @@ class TestBlenderShotMetadataIntegration(unittest.TestCase):
|
|
|
326
321
|
self.assertEqual(unity.get("record_count"), 2)
|
|
327
322
|
recs = {r.split("|")[0]: r.split("|") for r in unity.get("records", [])}
|
|
328
323
|
self.assertEqual(recs["A01"][1], "Open the hangar doors")
|
|
329
|
-
self.assertEqual(recs["A01"][2], "A")
|
|
330
324
|
self.assertEqual(recs["A02"][1], "Raise the platform")
|
|
331
325
|
clip_names = set(unity.get("clip_names", []))
|
|
332
326
|
for clip in recs: # every record's clip resolves to an imported clip
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"""Integration test: the Maya→Unity clip-name JOIN contract under stress.
|
|
4
4
|
|
|
5
5
|
The whole shots→Unity scheme hinges on one identity: the shot name == the FBX
|
|
6
|
-
take name == the imported ``AnimationClip.name`` == the ``
|
|
6
|
+
take name == the imported ``AnimationClip.name`` == the ``animation`` record's ``clip``
|
|
7
7
|
join key. The store refuses any name outside ``ShotStore.NAME_PATTERN``
|
|
8
8
|
(``[A-Za-z0-9_]``, unique ignoring case) instead of respelling it on export, so
|
|
9
9
|
what the user typed is what ships. This test proves both halves end to end:
|
|
@@ -97,7 +97,7 @@ view = store.to_export_view()
|
|
|
97
97
|
store.publish_export_view()
|
|
98
98
|
n_takes = FbxUtils.apply_takes_from_node()
|
|
99
99
|
# The take list the split realizes, read back off the carrier through the ONE
|
|
100
|
-
# reader of it (each
|
|
100
|
+
# reader of it (each animation-record clip's own range).
|
|
101
101
|
takes = ptk.SceneRecords.declared_takes(
|
|
102
102
|
lambda key: ptk.SceneRecords.resolve(key).load(DataNodes)
|
|
103
103
|
)
|
|
@@ -116,7 +116,7 @@ results = {
|
|
|
116
116
|
"fbx_exists": os.path.exists(fbx_path),
|
|
117
117
|
"n_takes": n_takes,
|
|
118
118
|
"clip_keys": [t["name"] for t in takes],
|
|
119
|
-
"meta_keys": [s["clip"] for s in view[
|
|
119
|
+
"meta_keys": [s["clip"] for s in view[ptk.SceneRecords.SHOTS.key]["shots"]],
|
|
120
120
|
"refused": refused,
|
|
121
121
|
}
|
|
122
122
|
with open(os.path.join(output_dir, "maya_results.json"), "w") as f:
|
|
@@ -168,7 +168,7 @@ public class ClipNameContractVerifier
|
|
|
168
168
|
.Select(c => c.name)
|
|
169
169
|
.ToList();
|
|
170
170
|
|
|
171
|
-
//
|
|
171
|
+
// The animation record's clip keys, via the attached controller (reflection).
|
|
172
172
|
var clipKeys = new List<string>();
|
|
173
173
|
var smcType = (Type.GetType("ShotMetadataController, M3trik.Unitytk") ?? Type.GetType("ShotMetadataController, Assembly-CSharp"));
|
|
174
174
|
var recType = (Type.GetType("ShotRecord, M3trik.Unitytk") ?? Type.GetType("ShotRecord, Assembly-CSharp"));
|
|
@@ -214,16 +214,12 @@ class TestClipNameContract(unittest.TestCase):
|
|
|
214
214
|
|
|
215
215
|
@classmethod
|
|
216
216
|
def setUpClass(cls):
|
|
217
|
-
cls.temp_dir = TempProjects.allocate("clip_name_contract")
|
|
217
|
+
cls.temp_dir = TempProjects.allocate("clip_name_contract", cls)
|
|
218
218
|
cls.fbx_path = None
|
|
219
219
|
cls.maya_results = None
|
|
220
220
|
cls.unity_results = None
|
|
221
221
|
logger.info(f"Temp dir: {cls.temp_dir}")
|
|
222
222
|
|
|
223
|
-
@classmethod
|
|
224
|
-
def tearDownClass(cls):
|
|
225
|
-
logger.info(f"Results preserved in: {cls.temp_dir}")
|
|
226
|
-
|
|
227
223
|
@MayaEnv.skip_unless_available()
|
|
228
224
|
def test_01_maya_export(self):
|
|
229
225
|
script_path = os.path.join(self.temp_dir, "maya_export.py")
|
|
@@ -168,14 +168,10 @@ class TestControllerRuntimeIntegration(unittest.TestCase):
|
|
|
168
168
|
|
|
169
169
|
@classmethod
|
|
170
170
|
def setUpClass(cls):
|
|
171
|
-
cls.temp_dir = TempProjects.allocate("ctrl_runtime_integ")
|
|
171
|
+
cls.temp_dir = TempProjects.allocate("ctrl_runtime_integ", cls)
|
|
172
172
|
cls.unity_results = None
|
|
173
173
|
logger.info(f"Temp dir: {cls.temp_dir}")
|
|
174
174
|
|
|
175
|
-
@classmethod
|
|
176
|
-
def tearDownClass(cls):
|
|
177
|
-
logger.info(f"Results preserved in: {cls.temp_dir}")
|
|
178
|
-
|
|
179
175
|
@EnvSkip.unless(_unity_available(), "no Unity editor found")
|
|
180
176
|
def test_01_unity_runtime(self):
|
|
181
177
|
"""Drive both controllers in a real Unity; capture the readback."""
|