Fix Export Transform Overrides (#USDU-216) (#279)
* Fix the XForm override export and add the option to the recorder * Remove sublayers, remove ref from root, ass tests * Rename exportXformOverride to exportTransformOverride * Update changelog * Fix UI Labels to workaround layout issues * Fixes from PR review. - Fix for null ref exception when the source GO is not a UsdAsset - Fix for unclear UI * XFormable schema type should not override the actual schema type. * Removes the reference to the original file from exported override files written out by Recorder. * Switch transform export back to Xform from Xformable, because using base UsdGeomXformable prim types is unusual --------- Co-authored-by: Vicky Clark <vickycl@unity3d.com> Co-authored-by: Andrew Lee <119626628+lee-aandrew@users.noreply.github.com> Co-authored-by: Vicky Clark <45685026+vickycl@users.noreply.github.com>
This commit is contained in:
Родитель
5f70448108
Коммит
fd48735070
|
@ -72,4 +72,5 @@ TestProject/**/Logs
|
|||
TestProject/**/*.csproj
|
||||
TestProject/**/*.sln
|
||||
TestProject/Usd-Development/Library
|
||||
TestProject/Usd-Development/.vs
|
||||
build_usdcs
|
||||
|
|
28
README.md
28
README.md
|
@ -124,6 +124,34 @@ When compatibility with runtime is required (i.e for a standalone build), the re
|
|||
|
||||
> **Note:** This feature has no dependency to and is not based on the Recorder package.
|
||||
|
||||
### Exporting Transform Overrides
|
||||
|
||||
Modifications to transforms in USD files can be exported as overrides to the original files.
|
||||
|
||||
Overrides can be exported from the USD menu with the GameObject containing the UsdAsset component selected, which will export transform overrides for the entire hierarchy. Alternatively, you can also export just the overrides when exporting from the Recorder window by changing the 'Override Setting' to 'Export Transform Overrides Only'.
|
||||
|
||||
For full asset pipeline flexibility these override files do not include a reference to the original file, but this can be added by manually adding a sublayer in the header of the resulting USDA file:
|
||||
|
||||
```
|
||||
#usda 1.0
|
||||
(
|
||||
defaultPrim = "myCube"
|
||||
endTimeCode = 0
|
||||
startTimeCode = 0
|
||||
upAxis = "Y"
|
||||
subLayers = [
|
||||
@c:/path/to/original/myCube.usda@
|
||||
]
|
||||
)
|
||||
|
||||
over "myCube"
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Note: Modifications to the transform of the Root GameObject is not currently reflected in the override, as Unity assumes the root in all USD files is at the origin.
|
||||
|
||||
# License
|
||||
|
||||
The USD Unity SDK is licensed under the terms of the Apache
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
# Changes in usd-unitysdk for Unity
|
||||
# Changes in usd-unity-sdk for Unity
|
||||
|
||||
## Unreleased
|
||||
### Features
|
||||
- The USD Recorder now has an option to export transform overrides.
|
||||
|
||||
### Bug Fixes
|
||||
- "Export Transform Override" now properly exports modified transforms only.
|
||||
- Fixed a bug where importing materials exported from USD version >= 21.11 would fail.
|
||||
- Fixed loading of meshes with arbitrary primvars.
|
||||
- Fixed regression in animated mesh properties.
|
||||
|
@ -17,7 +21,7 @@
|
|||
- Fixed an import bug causing instanced primitives not to be sanitized to fit Unity formats, including converting basis, triangulating and unwinding meshes, and unrolling primvars.
|
||||
|
||||
### Changed
|
||||
- GC allocs reduced by half for Scene.GetAttributeAtPath and Scene.GetRelationshipAtPath
|
||||
- GC allocs reduced by half for Scene.GetAttributeAtPath and Scene.GetRelationshipAtPath.
|
||||
- Disabled plugins on unsupported platforms.
|
||||
- Optimized triangulation to reduce the chance of a "Timed out while waiting for thread" error on importing a complex mesh.
|
||||
- Optimized PointInstance importing.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#if RECORDER_AVAILABLE
|
||||
using UnityEditor.Recorder;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Formats.USD.Recorder
|
||||
{
|
||||
|
@ -12,7 +13,8 @@ namespace UnityEditor.Formats.USD.Recorder
|
|||
EditorGUILayout.PropertyField(serializedObject.FindProperty("interpolationType"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("coordinateConversion"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("activePolicy"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("exportMaterials"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("exportTransformOverrides"), new GUIContent("Override Setting"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("exportMaterials"), new GUIContent("Materials"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("scale"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ namespace UnityEditor.Formats.USD.Recorder
|
|||
context.basisTransform = Settings.BasisTransformation;
|
||||
context.activePolicy = Settings.ActivePolicy;
|
||||
context.exportMaterials = Settings.ExportMaterials;
|
||||
context.exportTransformOverrides = Settings.ExportTransformOverrides;
|
||||
|
||||
context.scale = Settings.Scale;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#if RECORDER_AVAILABLE
|
||||
using Unity.Formats.USD;
|
||||
using UnityEditor.Recorder;
|
||||
using USD.NET;
|
||||
|
||||
namespace UnityEditor.Formats.USD.Recorder
|
||||
{
|
||||
|
@ -11,10 +12,28 @@ namespace UnityEditor.Formats.USD.Recorder
|
|||
|
||||
protected override void BeginRecording(RecordingSession session)
|
||||
{
|
||||
if (Context.exportTransformOverrides)
|
||||
{
|
||||
// Settings.
|
||||
UsdAsset usdAsset = Settings.GameObject.GetComponentInParent<UsdAsset>(); // Get the UsdAsset component in this GameObject or its nearest parent
|
||||
if (usdAsset != null)
|
||||
{
|
||||
Context.scene.AddSubLayer(usdAsset.GetScene());
|
||||
Context.scene.WriteMode = Scene.WriteModes.Over;
|
||||
}
|
||||
else
|
||||
UnityEngine.Debug.LogError($"Unable to perform a 'transform overrides only' recording as <{Settings.GameObject.name}> is not a UsdAsset.");
|
||||
}
|
||||
SceneExporter.SyncExportContext(Settings.GameObject, Context);
|
||||
SceneExporter.Export(Settings.GameObject,
|
||||
Context,
|
||||
zeroRootTransform: false);
|
||||
|
||||
if (Context.exportTransformOverrides)
|
||||
{
|
||||
// this is very brittle- if we have the chance of other sublayers in future we should store the index it was added at and only erase that one.
|
||||
Context.scene.Stage.GetRootLayer().GetSubLayerPaths().Erase(0);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void NewFrameReady(RecordingSession session)
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace UnityEditor.Formats.USD.Recorder
|
|||
[SerializeField] ActiveExportPolicy activePolicy = ActiveExportPolicy.ExportAsVisibility;
|
||||
[SerializeField] bool exportMaterials = true;
|
||||
[SerializeField] float scale = 1;
|
||||
[SerializeField] ExportOverridesSetting exportTransformOverrides;
|
||||
|
||||
public UsdRecorderSettings()
|
||||
{
|
||||
|
@ -31,6 +32,12 @@ namespace UnityEditor.Formats.USD.Recorder
|
|||
USDZ,
|
||||
}
|
||||
|
||||
public enum ExportOverridesSetting
|
||||
{
|
||||
ExportInFull,
|
||||
ExportTransformOverridesOnly
|
||||
}
|
||||
|
||||
public UsdInterpolationType InterpolationType
|
||||
{
|
||||
get => interpolationType;
|
||||
|
@ -49,6 +56,12 @@ namespace UnityEditor.Formats.USD.Recorder
|
|||
set => exportMaterials = value;
|
||||
}
|
||||
|
||||
public bool ExportTransformOverrides
|
||||
{
|
||||
get => exportTransformOverrides == ExportOverridesSetting.ExportTransformOverridesOnly ? true : false;
|
||||
set => exportTransformOverrides = value ? ExportOverridesSetting.ExportTransformOverridesOnly : ExportOverridesSetting.ExportInFull;
|
||||
}
|
||||
|
||||
public ActiveExportPolicy ActivePolicy
|
||||
{
|
||||
get => activePolicy;
|
||||
|
|
|
@ -82,6 +82,7 @@ namespace UnityEditor.Formats.USD.Recorder
|
|||
public Unity.Formats.USD.BasisTransformation BasisTransformation { get; set; }
|
||||
public UnityEditor.Formats.USD.Recorder.UsdRecorderSettings.Format ExportFormat { get; }
|
||||
public bool ExportMaterials { get; set; }
|
||||
public bool ExportTransformOverrides { get; set; }
|
||||
protected virtual string Extension { get; }
|
||||
public virtual System.Collections.Generic.IEnumerable<UnityEditor.Recorder.RecorderInputSettings> InputsSettings { get; }
|
||||
public pxr.UsdInterpolationType InterpolationType { get; set; }
|
||||
|
|
|
@ -600,6 +600,7 @@ namespace Unity.Formats.USD
|
|||
{
|
||||
throw new Exception("Could not open base layer: " + sceneToReference.usdFullPath);
|
||||
}
|
||||
overs.AddSubLayer(baseLayer);
|
||||
|
||||
overs.Time = baseLayer.Time;
|
||||
overs.StartTime = baseLayer.StartTime;
|
||||
|
@ -614,20 +615,20 @@ namespace Unity.Formats.USD
|
|||
overs,
|
||||
BasisTransformation.SlowAndSafe,
|
||||
exportUnvarying: false,
|
||||
zeroRootTransform: true);
|
||||
|
||||
var rel = ImporterBase.MakeRelativePath(overs.FilePath, sceneToReference.usdFullPath);
|
||||
GetFirstPrim(overs).GetReferences().AddReference(rel, GetFirstPrim(baseLayer).GetPath());
|
||||
zeroRootTransform: true,
|
||||
exportOverrides: true);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(ex);
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (overs != null)
|
||||
{
|
||||
// Remove the reference to the original USD from the override file for flexibility in an asset pipeline
|
||||
// TODO: Make this an optional setting
|
||||
overs.Stage.GetRootLayer().GetSubLayerPaths().Erase(0);
|
||||
overs.Save();
|
||||
overs.Close();
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@ namespace Unity.Formats.USD
|
|||
UnityEngine.Profiling.Profiler.BeginSample("USD: Xform Conversion");
|
||||
|
||||
XformSample sample = (XformSample)objContext.sample;
|
||||
var localRot = objContext.gameObject.transform.localRotation;
|
||||
var localScale = objContext.gameObject.transform.localScale;
|
||||
var path = new pxr.SdfPath(objContext.path);
|
||||
|
||||
// If exporting for Z-Up, rotate the world.
|
||||
|
@ -37,9 +35,32 @@ namespace Unity.Formats.USD
|
|||
correctZUp,
|
||||
path.IsRootPrimPath(),
|
||||
exportContext.basisTransform);
|
||||
|
||||
UnityEngine.Profiling.Profiler.EndSample();
|
||||
|
||||
// If exporting overrides, only export what changed
|
||||
if (exportContext.exportTransformOverrides)
|
||||
{
|
||||
UnityEngine.Profiling.Profiler.BeginSample("USD: Xform override check");
|
||||
var sourceSample = new XformSample();
|
||||
float tolerance = 0.0001f;
|
||||
exportContext.scene.Read(path, sourceSample);
|
||||
bool areClose = true;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (Mathf.Abs(sample.transform[i] - sourceSample.transform[i]) > tolerance)
|
||||
{
|
||||
areClose = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
UnityEngine.Profiling.Profiler.EndSample();
|
||||
if (areClose)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UnityEngine.Profiling.Profiler.BeginSample("USD: Xform Write");
|
||||
exportContext.scene.Write(objContext.path, sample);
|
||||
UnityEngine.Profiling.Profiler.EndSample();
|
||||
|
@ -55,7 +76,7 @@ namespace Unity.Formats.USD
|
|||
|
||||
try
|
||||
{
|
||||
foreach (var path in scene.Find<XformableSample>())
|
||||
foreach (var path in scene.Find<XformSample>())
|
||||
{
|
||||
GameObject go;
|
||||
if (!primMap.TryGetValue(path, out go))
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace Unity.Formats.USD
|
|||
public bool exportMaterials = true;
|
||||
public bool exportNative = false;
|
||||
public float scale = 1.0f;
|
||||
public bool exportTransformOverrides = false;
|
||||
|
||||
public BasisTransformation basisTransform = BasisTransformation.FastWithNegativeScale;
|
||||
public ActiveExportPolicy activePolicy = ActiveExportPolicy.ExportAsVisibility;
|
||||
|
@ -121,12 +122,14 @@ namespace Unity.Formats.USD
|
|||
bool exportUnvarying,
|
||||
bool zeroRootTransform,
|
||||
bool exportMaterials = false,
|
||||
bool exportMonoBehaviours = false)
|
||||
bool exportMonoBehaviours = false,
|
||||
bool exportOverrides = false)
|
||||
{
|
||||
var context = new ExportContext();
|
||||
context.scene = scene;
|
||||
context.basisTransform = basisTransform;
|
||||
context.exportRoot = root.transform.parent;
|
||||
context.exportTransformOverrides = exportOverrides;
|
||||
SyncExportContext(root, context);
|
||||
|
||||
// Since this is a one-shot convenience function, we will automatically split the export
|
||||
|
@ -537,91 +540,99 @@ namespace Unity.Formats.USD
|
|||
static void InitExportableObjects(GameObject go,
|
||||
ExportContext context)
|
||||
{
|
||||
var smr = go.GetComponent<SkinnedMeshRenderer>();
|
||||
var mr = go.GetComponent<MeshRenderer>();
|
||||
var mf = go.GetComponent<MeshFilter>();
|
||||
var cam = go.GetComponent<Camera>();
|
||||
Transform expRoot = context.exportRoot;
|
||||
|
||||
var tmpPath = new pxr.SdfPath(UnityTypeConverter.GetPath(go.transform, expRoot));
|
||||
while (!tmpPath.IsRootPrimPath())
|
||||
if (context.exportTransformOverrides)
|
||||
{
|
||||
tmpPath = tmpPath.GetParentPath();
|
||||
CreateExportPlan(go, CreateSample<XformSample>(context), XformExporter.ExportXform, context);
|
||||
}
|
||||
|
||||
// TODO: What if this path is in use?
|
||||
string materialBasePath = tmpPath.ToString() + "/Materials/";
|
||||
|
||||
// Ensure the "Materials" prim is defined with a valid prim type.
|
||||
context.scene.Write(materialBasePath.TrimEnd('/'), new ScopeSample());
|
||||
|
||||
if (smr != null)
|
||||
else
|
||||
{
|
||||
foreach (var mat in smr.sharedMaterials)
|
||||
var smr = go.GetComponent<SkinnedMeshRenderer>();
|
||||
|
||||
var mr = go.GetComponent<MeshRenderer>();
|
||||
var mf = go.GetComponent<MeshFilter>();
|
||||
var cam = go.GetComponent<Camera>();
|
||||
Transform expRoot = context.exportRoot;
|
||||
|
||||
var tmpPath = new pxr.SdfPath(UnityTypeConverter.GetPath(go.transform, expRoot));
|
||||
while (!tmpPath.IsRootPrimPath())
|
||||
{
|
||||
if (!context.matMap.ContainsKey(mat))
|
||||
{
|
||||
string usdPath = materialBasePath +
|
||||
pxr.UsdCs.TfMakeValidIdentifier(
|
||||
mat.name + "_" + mat.GetInstanceID().ToString());
|
||||
context.matMap.Add(mat, usdPath);
|
||||
}
|
||||
tmpPath = tmpPath.GetParentPath();
|
||||
}
|
||||
|
||||
CreateExportPlan(go, CreateSample<MeshSample>(context), MeshExporter.ExportSkinnedMesh, context);
|
||||
CreateExportPlan(go, CreateSample<MeshSample>(context), NativeExporter.ExportObject, context,
|
||||
insertFirst: false);
|
||||
if (smr.rootBone == null)
|
||||
// TODO: What if this path is in use?
|
||||
string materialBasePath = tmpPath.ToString() + "/Materials/";
|
||||
|
||||
// Ensure the "Materials" prim is defined with a valid prim type.
|
||||
context.scene.Write(materialBasePath.TrimEnd('/'), new ScopeSample());
|
||||
|
||||
if (smr != null)
|
||||
{
|
||||
Debug.LogWarning("No root bone at: " + UnityTypeConverter.GetPath(go.transform, expRoot));
|
||||
}
|
||||
else if (smr.bones == null || smr.bones.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("No bones at: " + UnityTypeConverter.GetPath(go.transform, expRoot));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Each mesh in a model may have a different root bone, which now must be merged into a
|
||||
// single skeleton for export to USD.
|
||||
try
|
||||
foreach (var mat in smr.sharedMaterials)
|
||||
{
|
||||
MergeBonesSimple(smr.transform, smr.rootBone, smr.bones, smr.sharedMesh.bindposes, context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(
|
||||
new Exception("Failed to merge bones for " + UnityTypeConverter.GetPath(smr.transform),
|
||||
ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mf != null && mr != null)
|
||||
{
|
||||
foreach (var mat in mr.sharedMaterials)
|
||||
{
|
||||
if (mat == null)
|
||||
{
|
||||
continue;
|
||||
if (!context.matMap.ContainsKey(mat))
|
||||
{
|
||||
string usdPath = materialBasePath +
|
||||
pxr.UsdCs.TfMakeValidIdentifier(
|
||||
mat.name + "_" + mat.GetInstanceID().ToString());
|
||||
context.matMap.Add(mat, usdPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.matMap.ContainsKey(mat))
|
||||
CreateExportPlan(go, CreateSample<MeshSample>(context), MeshExporter.ExportSkinnedMesh, context);
|
||||
CreateExportPlan(go, CreateSample<MeshSample>(context), NativeExporter.ExportObject, context,
|
||||
insertFirst: false);
|
||||
if (smr.rootBone == null)
|
||||
{
|
||||
string usdPath = materialBasePath +
|
||||
pxr.UsdCs.TfMakeValidIdentifier(
|
||||
mat.name + "_" + mat.GetInstanceID().ToString());
|
||||
context.matMap.Add(mat, usdPath);
|
||||
Debug.LogWarning("No root bone at: " + UnityTypeConverter.GetPath(go.transform, expRoot));
|
||||
}
|
||||
else if (smr.bones == null || smr.bones.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("No bones at: " + UnityTypeConverter.GetPath(go.transform, expRoot));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Each mesh in a model may have a different root bone, which now must be merged into a
|
||||
// single skeleton for export to USD.
|
||||
try
|
||||
{
|
||||
MergeBonesSimple(smr.transform, smr.rootBone, smr.bones, smr.sharedMesh.bindposes, context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(
|
||||
new Exception("Failed to merge bones for " + UnityTypeConverter.GetPath(smr.transform),
|
||||
ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mf != null && mr != null)
|
||||
{
|
||||
foreach (var mat in mr.sharedMaterials)
|
||||
{
|
||||
if (mat == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CreateExportPlan(go, CreateSample<MeshSample>(context), MeshExporter.ExportMesh, context);
|
||||
CreateExportPlan(go, CreateSample<MeshSample>(context), NativeExporter.ExportObject, context,
|
||||
insertFirst: false);
|
||||
}
|
||||
else if (cam)
|
||||
{
|
||||
CreateExportPlan(go, CreateSample<CameraSample>(context), CameraExporter.ExportCamera, context);
|
||||
CreateExportPlan(go, CreateSample<CameraSample>(context), NativeExporter.ExportObject, context,
|
||||
insertFirst: false);
|
||||
if (!context.matMap.ContainsKey(mat))
|
||||
{
|
||||
string usdPath = materialBasePath +
|
||||
pxr.UsdCs.TfMakeValidIdentifier(
|
||||
mat.name + "_" + mat.GetInstanceID().ToString());
|
||||
context.matMap.Add(mat, usdPath);
|
||||
}
|
||||
}
|
||||
|
||||
CreateExportPlan(go, CreateSample<MeshSample>(context), MeshExporter.ExportMesh, context);
|
||||
CreateExportPlan(go, CreateSample<MeshSample>(context), NativeExporter.ExportObject, context,
|
||||
insertFirst: false);
|
||||
}
|
||||
else if (cam)
|
||||
{
|
||||
CreateExportPlan(go, CreateSample<CameraSample>(context), CameraExporter.ExportCamera, context);
|
||||
CreateExportPlan(go, CreateSample<CameraSample>(context), NativeExporter.ExportObject, context,
|
||||
insertFirst: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace Unity.Formats.USD
|
|||
public bool exportMaterials;
|
||||
public bool exportNative;
|
||||
public UnityEngine.Transform exportRoot;
|
||||
public bool exportTransformOverrides;
|
||||
public System.Collections.Generic.Dictionary<UnityEngine.Material, string> matMap;
|
||||
public System.Collections.Generic.Dictionary<UnityEngine.Transform, UnityEngine.Transform[]> meshToBones;
|
||||
public System.Collections.Generic.Dictionary<UnityEngine.Transform, UnityEngine.Transform> meshToSkelRoot;
|
||||
|
@ -380,7 +381,7 @@ namespace Unity.Formats.USD
|
|||
public static class SceneExporter
|
||||
{
|
||||
public static void Export(UnityEngine.GameObject root, Unity.Formats.USD.ExportContext context, bool zeroRootTransform);
|
||||
public static void Export(UnityEngine.GameObject root, USD.NET.Scene scene, Unity.Formats.USD.BasisTransformation basisTransform, bool exportUnvarying, bool zeroRootTransform, bool exportMaterials = False, bool exportMonoBehaviours = False);
|
||||
public static void Export(UnityEngine.GameObject root, USD.NET.Scene scene, Unity.Formats.USD.BasisTransformation basisTransform, bool exportUnvarying, bool zeroRootTransform, bool exportMaterials = False, bool exportMonoBehaviours = False, bool exportOverrides = False);
|
||||
public static void SyncExportContext(UnityEngine.GameObject exportRoot, Unity.Formats.USD.ExportContext context);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ using UnityEditor;
|
|||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using USD.NET;
|
||||
using USD.NET.Unity;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
|
||||
namespace Unity.Formats.USD.Tests
|
||||
|
@ -209,4 +210,65 @@ namespace Unity.Formats.USD.Tests
|
|||
CollectionAssert.AreEqual(colours, mesh.colors);
|
||||
}
|
||||
}
|
||||
|
||||
class ExportXFormOverride
|
||||
{
|
||||
static readonly string SourceFilePath = Path.ChangeExtension(Path.GetTempFileName(), "usda");
|
||||
static readonly string OverFilePath = Path.ChangeExtension(Path.GetTempFileName(), "usda");
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void CreateLoadExport()
|
||||
{
|
||||
// Create a new Stage
|
||||
var scene = ExportHelpers.InitForSave(SourceFilePath);
|
||||
var xformToken = new TfToken("Xform");
|
||||
scene.Stage.DefinePrim(new SdfPath("/root/A"), xformToken);
|
||||
scene.Stage.DefinePrim(new SdfPath("/root/B"), xformToken);
|
||||
scene.Save();
|
||||
|
||||
// Load the stage and modify /root/A transform
|
||||
var root = ImportHelpers.ImportSceneAsGameObject(scene);
|
||||
scene.Close();
|
||||
var primA = root.transform.Find("A");
|
||||
primA.transform.localPosition = new Vector3(10.0f, 10.0f, 10.0f);
|
||||
|
||||
// Export overrides
|
||||
var usdAsset = root.GetComponentInParent<UsdAsset>();
|
||||
var overs = ExportHelpers.InitForSave(OverFilePath);
|
||||
usdAsset.ExportOverrides(overs);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExportXFormOverride_OnlyExportChanges_Success()
|
||||
{
|
||||
var outScene = Scene.Open(OverFilePath);
|
||||
NUnit.Framework.Assert.IsTrue(outScene.Stage.GetPrimAtPath(new SdfPath("/root/A")).IsValid());
|
||||
NUnit.Framework.Assert.IsFalse(outScene.Stage.GetPrimAtPath(new SdfPath("/root/B")).IsValid());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExportXFormOverride_NoSublayers_True()
|
||||
{
|
||||
var outScene = Scene.Open(OverFilePath);
|
||||
NUnit.Framework.Assert.Zero(outScene.Stage.GetRootLayer().GetNumSubLayerPaths());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExportXFormOverride_NoPrimDefined_True()
|
||||
{
|
||||
var outScene = Scene.Open(OverFilePath);
|
||||
foreach (var prim in outScene.Stage.GetAllPrims())
|
||||
{
|
||||
Debug.Log(prim.GetPath().ToString());
|
||||
NUnit.Framework.Assert.AreEqual(SdfSpecifier.SdfSpecifierOver, prim.GetSpecifier());
|
||||
}
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void DeleteTestFiles()
|
||||
{
|
||||
File.Delete(OverFilePath);
|
||||
File.Delete(SourceFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,12 +171,12 @@ namespace Unity.Formats.USD.Tests
|
|||
var skeletalRootInUsd = m_USDScene.Stage.GetPrimAtPath(new pxr.SdfPath(UnityTypeConverter.GetPath(skeletalRoot.transform)));
|
||||
var skeletalRootInUsdType = skeletalRootInUsd.GetTypeName();
|
||||
var expectedSkeletalRootInUsdType = new pxr.TfToken("SkelRoot");
|
||||
Assert.AreEqual(skeletalRootInUsdType, expectedSkeletalRootInUsdType);
|
||||
Assert.AreEqual(expectedSkeletalRootInUsdType, skeletalRootInUsdType);
|
||||
|
||||
var skeletonInUsd = m_USDScene.Stage.GetPrimAtPath(new pxr.SdfPath(UnityTypeConverter.GetPath(skeleton.transform)));
|
||||
var skeletonInUsdType = skeletonInUsd.GetTypeName();
|
||||
var expectedSkeletonInUsdType = new pxr.TfToken("Skeleton");
|
||||
Assert.AreEqual(skeletonInUsdType, expectedSkeletonInUsdType);
|
||||
Assert.AreEqual(expectedSkeletonInUsdType, skeletonInUsdType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче