diff --git a/Examples/Plugins/SdfFileFormat/Tests/CodeCoverageTests.swift b/Examples/Plugins/SdfFileFormat/Tests/CodeCoverageTests.swift new file mode 100644 index 0000000000..8e379b3570 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/CodeCoverageTests.swift @@ -0,0 +1,152 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +// This file runs through the test resources files included in usdcat-tests, +// but as in-process instead of calling out to usdcat, so we can measure code coverage + +import Foundation +import Testing +import OpenUSD + +public typealias pxr = pxrInternal_v0_26_8__pxrReserved__ + +func ensurePluginLoaded() throws { + let root = #bundle.resourceURL! + .absoluteURL + .deletingLastPathComponent() + .deletingLastPathComponent() + .deletingLastPathComponent() + + let toLoad = root.path(percentEncoded: false) + "*/Contents/Resources/plugInfo_macOS.json" + print(toLoad) + let plugins = pxr.PlugRegistry.GetInstance().RegisterPlugins(std.string(toLoad)) + try #require(!plugins.empty()) +} + +func resourcesUrl() -> URL { + #bundle.resourceURL!.appending(path: "Resources") +} + +func usdResourcesFiles() throws -> [URL] { + var result = [URL]() + let enumerator = try #require(FileManager.default.enumerator(at: resourcesUrl(), includingPropertiesForKeys: nil)) + for case let item as URL in enumerator { + guard item.pathExtension.hasPrefix("usd") else { continue } + guard !item.lastPathComponent.starts(with: "SKIP") else { continue } + result.append(item.absoluteURL) + } + result.sort(using: KeyPathComparator(\.path)) + try #require(!result.isEmpty) + return result +} + +func jsonResourcesFiles() throws -> [URL] { + var result = [URL]() + let enumerator = try #require(FileManager.default.enumerator(at: resourcesUrl(), includingPropertiesForKeys: nil)) + for case let item as URL in enumerator { + guard item.pathExtension == "json" else { continue } + guard !item.lastPathComponent.starts(with: "SKIP") else { continue } + result.append(item.absoluteURL) + } + result.sort(using: KeyPathComparator(\.path)) + try #require(!result.isEmpty) + return result +} + +func expectJsonFailure(_ x: URL) throws { + try Overlay.withTfErrorMark { mark in + // Note: The #expect/#require macros require all subexpressions to be Copyable, + // so we can't use `mark` because Overlay.TfErrorMarkWrapper is ~Copyable + var isClean = mark.IsClean() + try #require(isClean) + let layer = Overlay.DereferenceOrNil(pxr.SdfLayer.FindOrOpen(x.forUsd, .init())) + // Don't want to put `layer` in the `#require`, because if it fails, + // Swift Testing will try to using reflection/mirrors to introspect the subexpressions + // and hit a runtime crash + let layerIsNil = layer == nil + if let layer { + let usdaLayer = Overlay.Dereference(pxr.SdfLayer.CreateAnonymous("", .init())) + usdaLayer.TransferContent(Overlay.TfWeakPtr(layer)) + var s: std.string = "" + usdaLayer.ExportToString(&s) + print("\"\"\"\n" + String(s) + "\"\"\"") + } + try #require(layerIsNil, "\(x.forUsd)") + isClean = mark.IsClean() + try #require(!isClean) + } +} + +func usdcat(a: std.string, b: std.string) throws { + let layer = try #require(Overlay.DereferenceOrNil(pxr.SdfLayer.FindOrOpen(a, .init())), "\(a), \(b)") + #expect(layer.Export(b, layer.GetComment(), .init())) +} + +func diff(a: URL, b: URL) throws { + // Skip USDZ extraction since this isn't correctness, + // just code coverage + if a.pathExtension == "usdz" { return } + + // Fake usddiff normalization by just usdcatting once more. + let aCatForDiff = std.string(String(b.forUsd) + ".acatfordiff.usda") + let bCatForDiff = std.string(String(b.forUsd) + ".bcatfordiff.usda") + + try usdcat(a: a.forUsd, b: aCatForDiff) + try usdcat(a: b.forUsd, b: bCatForDiff) + + let aLines = try String(contentsOf: URL(fileURLWithPath: String(aCatForDiff)), + encoding: .utf8).components(separatedBy: .newlines) + let bLines = try String(contentsOf: URL(fileURLWithPath: String(bCatForDiff)), + encoding: .utf8).components(separatedBy: .newlines) + + try #require(aLines.count == bLines.count) + for i in 0.. +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/2_old-typename-transform.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/2_old-typename-transform.usda new file mode 100644 index 0000000000..44a3160cc4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/2_old-typename-transform.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + Transform transform = ( (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16) ) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/3_order-two-prepend-rels.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/3_order-two-prepend-rels.usda new file mode 100644 index 0000000000..de410d4c15 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/3_order-two-prepend-rels.usda @@ -0,0 +1,20 @@ +#usda 1.0 + +# pxr/usdImaging/usdImagingGL/testenv/testUsdImagingGLBasicDrawing/basicDrawing/shaders_bindings.usd + +def "Foo" ( + apiSchemas = ["CollectionAPI:myCollection"] +){ + prepend rel collection:myCollection:includes = [ + , + + ] +} + +def "Fizz1" +{ +} + +def "Fizz2" +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/4_permission-on-attr.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/4_permission-on-attr.usda new file mode 100644 index 0000000000..a8b323e5df --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/4_permission-on-attr.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def Mesh "card" +{ + int customInt (permission = public) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/5_reorder-listop.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/5_reorder-listop.usda new file mode 100644 index 0000000000..393ecbd72c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/5_reorder-listop.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "A" ( + reorder references = +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/6_reorder-listop-2.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/6_reorder-listop-2.usda new file mode 100644 index 0000000000..244c9b8891 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/10_deprecated/6_reorder-listop-2.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "A" ( + reorder clipSets = ["Fizz", "Buzz"] +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/1_extent-wrong-type-name.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/1_extent-wrong-type-name.usda new file mode 100644 index 0000000000..cc58f1c21f --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/1_extent-wrong-type-name.usda @@ -0,0 +1,14 @@ +#usda 1.0 + +# pxr/usdImaging/usdImagingGL/testenv/testUsdImagingGLShadeBool/shadebool.usda +# has two extent attributes with type `vec3f[]` when it should be `float3[]` + +def Scope "Geom" +{ + def Mesh "Foo" ( + prepend apiSchemas = ["MaterialBindingAPI"] + ) + { + vec3f[] extent = [(-1.21273, -1.21273, -1.21273), (1.21273, 1.21273, 1.21273)] + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/2_lossless-attr-collection-api.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/2_lossless-attr-collection-api.usda new file mode 100644 index 0000000000..a83f2b54ea --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/2_lossless-attr-collection-api.usda @@ -0,0 +1,10 @@ +#usda 1.0 + +def "Foo" ( + apiSchemas = ["CollectionAPI:bar"] +) { + # CollectionAPI specifies that includeRoot should be uniform, + # but pxr/usd/usd/testenv/testUsdNamespaceEditorProperties/basic/root.usda + # has a non-uniform collection::includeRoot attr + bool collection:bar:includeRoot = true +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/3_mismatched-types.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/3_mismatched-types.usda new file mode 100644 index 0000000000..dcbde6064d --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/3_mismatched-types.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +def "Foo" +{ + # @pxr/usdImaging/usdImagingGL/testenv/testUsdImagingGLShadeMaterial/coloredCubes.usda@ is written as a token but assigned a path value + token bar = +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/4_unregistered_listops.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/4_unregistered_listops.usda new file mode 100644 index 0000000000..f365f37d35 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/11_losslessly_handle_invalid_files/4_unregistered_listops.usda @@ -0,0 +1,6 @@ +#usda 1.0 + +def "A" ( + prepend foo = ["bar", "fizz"] +) { +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/10_spline_no_postExtrapolation.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/10_spline_no_postExtrapolation.json new file mode 100644 index 0000000000..ebbd374c13 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/10_spline_no_postExtrapolation.json @@ -0,0 +1,49 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/11_spline_no_innerLoopParams.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/11_spline_no_innerLoopParams.json new file mode 100644 index 0000000000..1122718131 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/11_spline_no_innerLoopParams.json @@ -0,0 +1,46 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/12_spline_no_knots.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/12_spline_no_knots.json new file mode 100644 index 0000000000..0cd4ad866c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/12_spline_no_knots.json @@ -0,0 +1,30 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/13_spline_no_mode.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/13_spline_no_mode.json new file mode 100644 index 0000000000..dafe3993e5 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/13_spline_no_mode.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/14_spline_no_slope.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/14_spline_no_slope.json new file mode 100644 index 0000000000..854ee8d604 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/14_spline_no_slope.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/15_spline_no_protoStart.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/15_spline_no_protoStart.json new file mode 100644 index 0000000000..a35d0d19e4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/15_spline_no_protoStart.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/16_spline_no_protoEnd.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/16_spline_no_protoEnd.json new file mode 100644 index 0000000000..776fd9db53 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/16_spline_no_protoEnd.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/17_spline_no_numPreLoops.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/17_spline_no_numPreLoops.json new file mode 100644 index 0000000000..6b61ab3d08 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/17_spline_no_numPreLoops.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/18_spline_no_numPostLoops.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/18_spline_no_numPostLoops.json new file mode 100644 index 0000000000..57b869c78e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/18_spline_no_numPostLoops.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/19_spline_no_valueOffset.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/19_spline_no_valueOffset.json new file mode 100644 index 0000000000..cbaf128e67 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/19_spline_no_valueOffset.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/1_empty_file.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/1_empty_file.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/20_spline_no_time.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/20_spline_no_time.json new file mode 100644 index 0000000000..c2a54d205a --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/20_spline_no_time.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/21_spline_no_nextInterpolation.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/21_spline_no_nextInterpolation.json new file mode 100644 index 0000000000..76c8463ce9 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/21_spline_no_nextInterpolation.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/22_spline_no_value.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/22_spline_no_value.json new file mode 100644 index 0000000000..250e8de924 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/22_spline_no_value.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/23_spline_no_preTanWidth.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/23_spline_no_preTanWidth.json new file mode 100644 index 0000000000..91a34d64f6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/23_spline_no_preTanWidth.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/24_spline_no_preTanSlope.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/24_spline_no_preTanSlope.json new file mode 100644 index 0000000000..cd6babac1c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/24_spline_no_preTanSlope.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/25_spline_no_preTanAlgorithm.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/25_spline_no_preTanAlgorithm.json new file mode 100644 index 0000000000..bf9550674e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/25_spline_no_preTanAlgorithm.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/26_no_postTanWidth.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/26_no_postTanWidth.json new file mode 100644 index 0000000000..5f8d8aeba9 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/26_no_postTanWidth.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/27_no_postTanSlope.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/27_no_postTanSlope.json new file mode 100644 index 0000000000..a8ea966e68 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/27_no_postTanSlope.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/28_no_postTanAlgorithm.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/28_no_postTanAlgorithm.json new file mode 100644 index 0000000000..8acc6677f5 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/28_no_postTanAlgorithm.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/29_bad_SdfUnregisteredValue.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/29_bad_SdfUnregisteredValue.json new file mode 100644 index 0000000000..1b092ae18f --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/29_bad_SdfUnregisteredValue.json @@ -0,0 +1,16 @@ +{ + "children": [{ + "metadata": { + "foo": { + "type": "SdfUnregisteredValue", + "value": { + "SdfUnregisteredValue": "", + "type": "foobar" + } + } + }, + "name": "A", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/2_invalid_file.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/2_invalid_file.json new file mode 100644 index 0000000000..d675fa44e5 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/2_invalid_file.json @@ -0,0 +1 @@ +foo bar diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/30_bad_SdfUnregisteredValue2.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/30_bad_SdfUnregisteredValue2.json new file mode 100644 index 0000000000..52a0d354ff --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/30_bad_SdfUnregisteredValue2.json @@ -0,0 +1,15 @@ +{ + "children": [{ + "metadata": { + "foo": { + "type": "SdfUnregisteredValue", + "value": { + "type": "foo" + } + } + }, + "name": "A", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/31_bad_layerOffset.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/31_bad_layerOffset.json new file mode 100644 index 0000000000..3ab9de5bf7 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/31_bad_layerOffset.json @@ -0,0 +1,5 @@ +{ + "name": "/", + "subLayerOffsets": [[10.0, 2.0, 5.0]], + "subLayers": ["foo.usda"] +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/32_variantSet_no_name.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/32_variantSet_no_name.json new file mode 100644 index 0000000000..90c7c3b08c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/32_variantSet_no_name.json @@ -0,0 +1,22 @@ +{ + "children": [{ + "name": "Foo", + "spec": "def", + "variantSets": [{ + "contents": { + "firstOption": { + "children": [{ + "name": "A", + "spec": "def" + }, { + "name": "B", + "spec": "def" + }], + "name": "firstOption", + "spec": "over" + } + } + }] + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/33_variantSet_no_contents.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/33_variantSet_no_contents.json new file mode 100644 index 0000000000..80cbbb713a --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/33_variantSet_no_contents.json @@ -0,0 +1,10 @@ +{ + "children": [{ + "name": "Foo", + "spec": "def", + "variantSets": [{ + "name": "firstSet" + }] + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/34_missing_type_key.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/34_missing_type_key.json new file mode 100644 index 0000000000..7253d54474 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/34_missing_type_key.json @@ -0,0 +1,13 @@ +{ + "children": [{ + "attributes": [{ + "default": 4, + "name": "customInt", + "variability": 0 + }], + "name": "card", + "spec": "def", + "type": "Mesh" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/35_unknown_type_key.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/35_unknown_type_key.json new file mode 100644 index 0000000000..462e2a0772 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/35_unknown_type_key.json @@ -0,0 +1,14 @@ +{ + "children": [{ + "attributes": [{ + "default": 4, + "name": "customInt", + "type": "", + "variability": 0 + }], + "name": "card", + "spec": "def", + "type": "Mesh" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/36_shortVec.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/36_shortVec.json new file mode 100644 index 0000000000..925dd06354 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/36_shortVec.json @@ -0,0 +1,13 @@ +{ + "children": [{ + "attributes": [{ + "default": [-1.0, -2.0], + "name": "myDouble3", + "type": "Double3", + "variability": 0 + }], + "name": "foo", + "spec": "def" + }], + "name": "/" +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/37_shortMat.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/37_shortMat.json new file mode 100644 index 0000000000..d948df50cc --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/37_shortMat.json @@ -0,0 +1,13 @@ +{ + "children": [{ + "attributes": [{ + "default": [-1.0, -2.0, -3.0], + "name": "bar", + "type": "Matrix2d", + "variability": 0 + }], + "name": "foo", + "spec": "def" + }], + "name": "/" +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/38_bad_timesample_time.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/38_bad_timesample_time.json new file mode 100644 index 0000000000..3ac30f3a65 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/38_bad_timesample_time.json @@ -0,0 +1,14 @@ +{ + "name": "/", + "children": [{ + "name": "Foo", + "spec": "def", + "attributes": [{ + "name": "myAttr", + "type": "int", + "timesamples": { + "123foobar" : 0 + } + }] + }] +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/39_bad_timesample_time2.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/39_bad_timesample_time2.json new file mode 100644 index 0000000000..6358c77ed3 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/39_bad_timesample_time2.json @@ -0,0 +1,14 @@ +{ + "name": "/", + "children": [{ + "name": "Foo", + "spec": "def", + "attributes": [{ + "name": "myAttr", + "type": "int", + "timesamples": { + "foobar" : 0 + } + }] + }] +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/3_name_int.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/3_name_int.json new file mode 100644 index 0000000000..ed3f2acdb4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/3_name_int.json @@ -0,0 +1,6 @@ +{ + "name": "/", + "children": [{ + "name": 3 + }] +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/4_children_without_name.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/4_children_without_name.json new file mode 100644 index 0000000000..b6f0e2ec08 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/4_children_without_name.json @@ -0,0 +1,6 @@ +{ + "children": [{ + "foo": "bar" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/5_missing_spec.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/5_missing_spec.json new file mode 100644 index 0000000000..5243863241 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/5_missing_spec.json @@ -0,0 +1,6 @@ +{ + "name": "/", + "children": [{ + "name": "foo" + }] +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/6_unknown_spec.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/6_unknown_spec.json new file mode 100644 index 0000000000..b8598f576c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/6_unknown_spec.json @@ -0,0 +1,7 @@ +{ + "name": "/", + "children": [{ + "name": "foo", + "spec": "bar" + }] +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/7_bad_relationship.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/7_bad_relationship.json new file mode 100644 index 0000000000..808cb9ee01 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/7_bad_relationship.json @@ -0,0 +1,10 @@ +{ + "name": "/", + "children": [{ + "name": "A", + "spec": "def", + "relationships": [{ + "name": "" + }] + }] +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/8_spline_no_curveType.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/8_spline_no_curveType.json new file mode 100644 index 0000000000..aa25c5c73c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/8_spline_no_curveType.json @@ -0,0 +1,52 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + }, + "preExtrapolation": { + "mode": 1, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/9_spline_no_preExtrapolation.json b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/9_spline_no_preExtrapolation.json new file mode 100644 index 0000000000..8024c921c8 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/12_bad_json/9_spline_no_preExtrapolation.json @@ -0,0 +1,49 @@ +{ + "children": [{ + "attributes": [{ + "name": "myAttr", + "spline": { + "curveType": 0, + "innerLoopParams": { + "numPostLoops": 0, + "numPreLoops": 0, + "protoEnd": 0.0, + "protoStart": 0.0, + "valueOffset": 0.0 + }, + "knots": [{ + "customData": {}, + "nextInterpolation": 3, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 1.0, + "value": 1.0 + }, { + "customData": {}, + "nextInterpolation": 0, + "postTanAlgorithm": 0, + "postTanSlope": 0.0, + "postTanWidth": 0.0, + "preTanAlgorithm": 0, + "preTanSlope": 0.0, + "preTanWidth": 0.0, + "time": 10.0, + "value": 10.0 + }], + "postExtrapolation": { + "mode": 0, + "slope": 0.0 + } + }, + "type": "Double", + "variability": 0 + }], + "name": "hello", + "spec": "def" + }], + "name": "/" +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/10_empty-timesamples.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/10_empty-timesamples.usda new file mode 100644 index 0000000000..2ecdd421fa --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/10_empty-timesamples.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "A" +{ + float3[] extent.timeSamples = { + } +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/11_attr_without_value.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/11_attr_without_value.usda new file mode 100644 index 0000000000..3fcc0d8054 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/11_attr_without_value.usda @@ -0,0 +1,6 @@ +#usda 1.0 + +def Shader "diffuseTexture" +{ + float3 outputs:rgb +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/12_one-relationship.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/12_one-relationship.usda new file mode 100644 index 0000000000..55008c127e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/12_one-relationship.usda @@ -0,0 +1,7 @@ +#usda 1.0 + + +def Mesh "foo" +{ + rel customRel +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/13_one-typed-class.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/13_one-typed-class.usda new file mode 100644 index 0000000000..6df0d84b91 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/13_one-typed-class.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +class Mesh "card" +{ +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/14_one-typed-over.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/14_one-typed-over.usda new file mode 100644 index 0000000000..3de649dcb6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/14_one-typed-over.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +over Mesh "card" +{ +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/15_simple-prim-ordering.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/15_simple-prim-ordering.usda new file mode 100644 index 0000000000..c51a0e5177 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/15_simple-prim-ordering.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +def Xform "B" +{ +} + +def Xform "A" +{ +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/16_simple-usdz.usdz b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/16_simple-usdz.usdz new file mode 100644 index 0000000000..9673cc6b58 Binary files /dev/null and b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/16_simple-usdz.usdz differ diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/1_empty.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/1_empty.usda new file mode 100644 index 0000000000..93b78be6da --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/1_empty.usda @@ -0,0 +1 @@ +#usda 1.0 diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/2_untyped_def.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/2_untyped_def.usda new file mode 100644 index 0000000000..ba42a92929 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/2_untyped_def.usda @@ -0,0 +1,5 @@ +#usda 1.0 + +def "hello" +{ +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/3_typed_def.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/3_typed_def.usda new file mode 100644 index 0000000000..61c2949f27 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/3_typed_def.usda @@ -0,0 +1,5 @@ +#usda 1.0 + +def Xform "hello" +{ +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/4_one-over.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/4_one-over.usda new file mode 100644 index 0000000000..984ca48cbf --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/4_one-over.usda @@ -0,0 +1,5 @@ +#usda 1.0 + +over "hello" +{ +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/5_nested_specs.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/5_nested_specs.usda new file mode 100644 index 0000000000..aab7013240 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/5_nested_specs.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def Xform "hello" +{ + def Sphere "world" + { + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/6_class-in-over.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/6_class-in-over.usda new file mode 100644 index 0000000000..8ef7c97001 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/6_class-in-over.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +over "hello" +{ + class "mydef" + { + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/7_def-in-over.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/7_def-in-over.usda new file mode 100644 index 0000000000..35af66cee5 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/7_def-in-over.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +over "hello" +{ + def "mydef" + { + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/8_one-attribute.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/8_one-attribute.usda new file mode 100644 index 0000000000..369100080c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/8_one-attribute.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def Mesh "card" +{ + int customInt = 4 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/9_matrix3d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/9_matrix3d.usda new file mode 100644 index 0000000000..41d2602bfc --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/1_essential/9_matrix3d.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def Mesh "card" +{ + matrix3d foo = ((2, 7, 1), (8.2, 8.1, 8.2), (8.45, 5.90, 4.52)) +} + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/1_comment.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/1_comment.usda new file mode 100644 index 0000000000..2dbfb85781 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/1_comment.usda @@ -0,0 +1,6 @@ +#usda 1.0 +( + """ + my comment here + """ +) \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/2_common-metadata.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/2_common-metadata.usda new file mode 100644 index 0000000000..74b8b6dd93 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/2_common-metadata.usda @@ -0,0 +1,9 @@ +#usda 1.0 +( + endTimeCode = 7 + framesPerSecond = 24 + metersPerUnit = 1 + startTimeCode = 1 + timeCodesPerSecond = 24 + upAxis = "Y" +) \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/3_one-instanceable.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/3_one-instanceable.usda new file mode 100644 index 0000000000..4d779d2a56 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/3_one-instanceable.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +def Mesh "card" ( + instanceable = true +) +{ +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/4_explicit-apischemas.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/4_explicit-apischemas.usda new file mode 100644 index 0000000000..94c00fa2e3 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/4_explicit-apischemas.usda @@ -0,0 +1,10 @@ +#usda 1.0 + +def Mesh "card" ( + apiSchemas = ["MaterialBindingAPI"] +) +{ +} + + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/5_prim-with-comment.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/5_prim-with-comment.usda new file mode 100644 index 0000000000..c2352c6ffb --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/5_prim-with-comment.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +def "Foo" ( + """ + my comment here + """ +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/6_simple-apischemas.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/6_simple-apischemas.usda new file mode 100644 index 0000000000..1e587b5f6b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/6_simple-apischemas.usda @@ -0,0 +1,10 @@ +#usda 1.0 + +def Mesh "card" ( + prepend apiSchemas = ["MaterialBindingAPI"] +) +{ +} + + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/7_non-blocked-empty-rel.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/7_non-blocked-empty-rel.usda new file mode 100644 index 0000000000..b458434d57 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/2_metadata/7_non-blocked-empty-rel.usda @@ -0,0 +1,13 @@ +#usda 1.0 + +def "Foo" +{ + rel bar ( + doc = """ + My doc + """ + ) +} + + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/1_blocked-value.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/1_blocked-value.usda new file mode 100644 index 0000000000..5363ba2a82 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/1_blocked-value.usda @@ -0,0 +1,6 @@ +#usda 1.0 + +def Shader "diffuseTexture" +{ + float3 outputs:rgb = None +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/2_animation-block.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/2_animation-block.usda new file mode 100644 index 0000000000..70a96ac6bb --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/2_animation-block.usda @@ -0,0 +1,6 @@ +#usda 1.0 + +def "Foo" +{ + int bar = AnimationBlock +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/3_prepend-relationship.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/3_prepend-relationship.usda new file mode 100644 index 0000000000..4c0633c3b4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/3_prepend-relationship.usda @@ -0,0 +1,14 @@ +#usda 1.0 + + +def "Root" +{ + def "A" + { + prepend rel myRel = + } + + def "B" + { + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/4_prim-ordering.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/4_prim-ordering.usda new file mode 100644 index 0000000000..6d3f2c9a77 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/4_prim-ordering.usda @@ -0,0 +1,21 @@ +#usda 1.0 + +def Xform "Root" +{ + def Xform "foo" + { + } + + def Xform "bar" + { + } + + def Xform "fizz" + { + } + + def Xform "buzz" + { + } +} + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/5_simple-custom-data.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/5_simple-custom-data.usda new file mode 100644 index 0000000000..68672e24a8 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/5_simple-custom-data.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +def "A" ( + customData = { + string foo = 'bar' + } +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/6_string-listop.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/6_string-listop.usda new file mode 100644 index 0000000000..9f88255b71 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/6_string-listop.usda @@ -0,0 +1,8 @@ +#usda 1.0 + + +def "foo" ( + delete clipSets = ["buzz"] +) +{ +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/7_blocked-relationship.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/7_blocked-relationship.usda new file mode 100644 index 0000000000..9ffb24f0fd --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/7_blocked-relationship.usda @@ -0,0 +1,7 @@ +#usda 1.0 + + +def Mesh "foo" +{ + rel customRel = None +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/8_explicit-empty-connection.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/8_explicit-empty-connection.usda new file mode 100644 index 0000000000..577ac2ad0c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/3_common/8_explicit-empty-connection.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "Foo" +{ + custom double bar + double bar.connect = None +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/10_one-layer-relocates-external-ref.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/10_one-layer-relocates-external-ref.usda new file mode 100644 index 0000000000..e36920e25a --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/10_one-layer-relocates-external-ref.usda @@ -0,0 +1,11 @@ +#usda 1.0 +( + defaultPrim = "Root" +) + +def "Root" +{ + def "B" + { + } +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/11_one-layer-relocates.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/11_one-layer-relocates.usda new file mode 100644 index 0000000000..0648a573fc --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/11_one-layer-relocates.usda @@ -0,0 +1,13 @@ +#usda 1.0 +( + relocates = { + : + } + upAxis = "Y" +) + +def "A" ( + prepend references = [@9_one-relocates-external-ref.usda@] +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/12_one-prim-relocates.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/12_one-prim-relocates.usda new file mode 100644 index 0000000000..dd9dd1dfb3 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/12_one-prim-relocates.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +def "A" ( + relocates = { + : + } +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/1_one-sublayer.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/1_one-sublayer.usda new file mode 100644 index 0000000000..98d51f0464 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/1_one-sublayer.usda @@ -0,0 +1,6 @@ +#usda 1.0 +( + subLayers = [ + @foo.usda@ + ] +) \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/2_one-sublayer-with-offset.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/2_one-sublayer-with-offset.usda new file mode 100644 index 0000000000..c0a35fbfd4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/2_one-sublayer-with-offset.usda @@ -0,0 +1,6 @@ +#usda 1.0 +( + subLayers = [ + @foo.usda@ (offset = 10; scale = 2) + ] +) \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/3_one-reference.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/3_one-reference.usda new file mode 100644 index 0000000000..e4499df647 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/3_one-reference.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "A" ( + references = [@./doesntexist.usda@] +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/4_one-payload.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/4_one-payload.usda new file mode 100644 index 0000000000..61004e930b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/4_one-payload.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "A" ( + payload = [@./doesntexist.usda@] +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/5_append-reference.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/5_append-reference.usda new file mode 100644 index 0000000000..f8c13e32f4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/5_append-reference.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "A" ( + append references = +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/6_add-reference.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/6_add-reference.usda new file mode 100644 index 0000000000..8cfc1d43c4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/6_add-reference.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "A" ( + add references = [ @./foo.usda@ ] +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/7_one-specialize.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/7_one-specialize.usda new file mode 100644 index 0000000000..7f79bdf166 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/7_one-specialize.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "A" ( + specializes = [] +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/8_one-inherit.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/8_one-inherit.usda new file mode 100644 index 0000000000..276d39a204 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/8_one-inherit.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "A" ( + inherits = [] +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/9_empty-relocates.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/9_empty-relocates.usda new file mode 100644 index 0000000000..74ec356852 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/4_composition_without_variants/9_empty-relocates.usda @@ -0,0 +1,9 @@ +#usda 1.0 + + +def "Foo" ( + relocates = { + } +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/1_one-variant-set.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/1_one-variant-set.usda new file mode 100644 index 0000000000..d68a55ed63 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/1_one-variant-set.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "Foo" ( + prepend variantSets = "firstSet" +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/2_one-variant-selection.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/2_one-variant-selection.usda new file mode 100644 index 0000000000..1cc4d3c566 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/2_one-variant-selection.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +def "Foo" ( + variants = { + string firstSet = "firstSelection" + } +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/3_variant-set-two-defs.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/3_variant-set-two-defs.usda new file mode 100644 index 0000000000..8fdce3666d --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/3_variant-set-two-defs.usda @@ -0,0 +1,16 @@ +#usda 1.0 + +def "Foo" +{ + variantSet "firstSet" = { + "firstOption" { + def "A" + { + } + + def "B" + { + } + } + } +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/4_variant-set-two-empty-options.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/4_variant-set-two-empty-options.usda new file mode 100644 index 0000000000..e0dcd248c1 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/4_variant-set-two-empty-options.usda @@ -0,0 +1,12 @@ +#usda 1.0 + +def "Foo" +{ + variantSet "firstSet" = { + "firstOption" { + } + + "secondOption" { + } + } +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/5_metadata-in-variant.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/5_metadata-in-variant.usda new file mode 100644 index 0000000000..efd4f81f76 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/5_metadata-in-variant.usda @@ -0,0 +1,11 @@ +#usda 1.0 + +def "Foo" +{ + variantSet "myVSet" = { + "myVariant" ( + references = @./other.usda@ + ) { + } + } +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/6_two-variant-sets-nonalphabetical.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/6_two-variant-sets-nonalphabetical.usda new file mode 100644 index 0000000000..59b4427f2e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/6_two-variant-sets-nonalphabetical.usda @@ -0,0 +1,16 @@ +#usda 1.0 + +def "Foo" ( + prepend variantSets = ["beta", "alpha"] +) +{ + variantSet "beta" = { + "beta2" { + } + } + + variantSet "alpha" = { + "alpha2" { + } + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/7_simple-useful-variants.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/7_simple-useful-variants.usda new file mode 100644 index 0000000000..3adbc7d5c2 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/7_simple-useful-variants.usda @@ -0,0 +1,39 @@ +#usda 1.0 + +def Xform "Cube" ( + variants = { + string color = "Blue" + } + prepend variantSets = "color" +) +{ + def Xform "Geom" + { + def Cube "model" + { + rel customRel + } + } + variantSet "color" = { + "Blue" { + over "Geom" + { + over "model" + { + color3f[] primvars:displayColor = [(0, 0, 1)] + rel customRel = + } + } + } + "Green" { + over "Geom" + { + over "model" + { + color3f[] primvars:displayColor = [(0, 1, 0)] + rel customRel = + } + } + } + } +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/8_testPcpMuseum_TrickyNestedVariants.testenv.TrickyNestedVariants.root.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/8_testPcpMuseum_TrickyNestedVariants.testenv.TrickyNestedVariants.root.usda new file mode 100644 index 0000000000..353b641016 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/5_variants/8_testPcpMuseum_TrickyNestedVariants.testenv.TrickyNestedVariants.root.usda @@ -0,0 +1,44 @@ +#usda 1.0 +( + """ + This file is taken from: + https://github.com/PixarAnimationStudios/OpenUSD/blob/v26.08/pxr/usd/pcp/testenv/testPcpMuseum_TrickyNestedVariants.testenv/TrickyNestedVariants/root.usda + """ +) + +def MfScope "A" ( + variantSets = ["v1"] + variants = { string v1 = "x" } +) +{ + variantSet "v1" = { + "x" ( add references = [ @./ref.usda@ ] ) { + over "B" ( + add variantSets = ["v2"] + variants = { string v2 = "y" } + ) + { + variantSet "v2" = { + "y" ( add references = [ @./ref.usda@ ] ) { + over "C" ( + add variantSets = ["v3"] + variants = { string v3 = "z" } + ) + { + variantSet "v3" = { + "z" ( add references = [ @./ref.usda@ ] ) { + } + } + } + } + } + def MfScope "C" ( add references = [ @./ref.usda@ ] ) { + } + } + } + } + def MfScope "B" ( add references = [ @./ref.usda@ ] ) { + def MfScope "C" ( add references = [ @./ref.usda@ ] ) { + } + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/100_vector3f_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/100_vector3f_array.usda new file mode 100644 index 0000000000..befb27a412 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/100_vector3f_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + vector3f[] myVector3fArray = [(1, 5, 10)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/101_vector3h_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/101_vector3h_array.usda new file mode 100644 index 0000000000..83a472819c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/101_vector3h_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + vector3h[] myVector3hArray = [(10, 5, 1)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/102_frame4d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/102_frame4d_array.usda new file mode 100644 index 0000000000..7d1da01968 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/102_frame4d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + frame4d[] myFrame4dArray = [( (1, 1, 2, 3), (5, 8, 13, 21), (34, 55, 89, 144), (0, 0, 0, 1) )] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/103_texCoord2d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/103_texCoord2d_array.usda new file mode 100644 index 0000000000..a5887ad10b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/103_texCoord2d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord2d[] myTexCoord2dArray = [(2, 8)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/104_texCoord2f_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/104_texCoord2f_array.usda new file mode 100644 index 0000000000..302a97e8fc --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/104_texCoord2f_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord2f[] myTexCoord2fArray = [(4, 16)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/105_texCoord2h_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/105_texCoord2h_array.usda new file mode 100644 index 0000000000..5b3913f08d --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/105_texCoord2h_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord2h[] myTexCoord2hArray = [(8, 32)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/106_texCoord3d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/106_texCoord3d_array.usda new file mode 100644 index 0000000000..c9f279717c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/106_texCoord3d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord3d[] myTexCoord3dArray = [(1, 4, 9)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/107_texCoord3f_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/107_texCoord3f_array.usda new file mode 100644 index 0000000000..b6b67c30b6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/107_texCoord3f_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord3f[] myTexCoord3fArray = [(16, 25, 36)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/108_texCoord3h_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/108_texCoord3h_array.usda new file mode 100644 index 0000000000..de299f51df --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/108_texCoord3h_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord3h[] myTexCoord3hArray = [(49, 64, 81)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/10_token.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/10_token.usda new file mode 100644 index 0000000000..a88e66b8e2 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/10_token.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + token myToken = "fizz buzz" +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/11_uchar.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/11_uchar.usda new file mode 100644 index 0000000000..3d36b9ada1 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/11_uchar.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + uchar myUchar = 137 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/12_uint.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/12_uint.usda new file mode 100644 index 0000000000..20d0f81d8b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/12_uint.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + uint myUint = 12 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/13_uint64.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/13_uint64.usda new file mode 100644 index 0000000000..52915d435b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/13_uint64.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + uint64 myUint64 = 123456 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/14_double2.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/14_double2.usda new file mode 100644 index 0000000000..51a14c27fd --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/14_double2.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + double2 myDouble2 = (-1, -2) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/15_double3.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/15_double3.usda new file mode 100644 index 0000000000..5cd126f7f6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/15_double3.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + double3 myDouble3 = (-1, -2, -3) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/16_double4.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/16_double4.usda new file mode 100644 index 0000000000..ea2367a98d --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/16_double4.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + double4 myDouble4 = (-1, -2, -3, -4) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/17_float2.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/17_float2.usda new file mode 100644 index 0000000000..9de2c57fc5 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/17_float2.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + float2 myFloat2 = (-10, -20) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/18_float3.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/18_float3.usda new file mode 100644 index 0000000000..d53fc620ba --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/18_float3.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + float3 myFloat3 = (-10, -20, -30) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/19_float4.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/19_float4.usda new file mode 100644 index 0000000000..e6625961be --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/19_float4.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + float4 myFloat4 = (-10, -20, -30, -40) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/1_asset.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/1_asset.usda new file mode 100644 index 0000000000..8f98877d82 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/1_asset.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + asset myAsset = @foo.png@ +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/20_half2.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/20_half2.usda new file mode 100644 index 0000000000..073a6cebbe --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/20_half2.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + half2 myHalf2 = (-0.01, -0.02) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/21_half3.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/21_half3.usda new file mode 100644 index 0000000000..8b57da0fc3 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/21_half3.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + half3 myHalf3 = (-0.01, -0.02, -0.03) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/22_half4.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/22_half4.usda new file mode 100644 index 0000000000..9e2d4e88ef --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/22_half4.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + half4 myHalf4 = (-0.01, -0.02, -0.03, -0.04) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/23_int2.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/23_int2.usda new file mode 100644 index 0000000000..424cdef3c5 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/23_int2.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int2 myInt2 = (-100, -200) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/24_int3.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/24_int3.usda new file mode 100644 index 0000000000..7d70fab1b2 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/24_int3.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int3 myInt3 = (-100, -200, -300) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/25_int4.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/25_int4.usda new file mode 100644 index 0000000000..5c1b461203 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/25_int4.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int4 myInt4 = (-100, -200, -300, -400) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/26_matrix2d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/26_matrix2d.usda new file mode 100644 index 0000000000..031a88b43d --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/26_matrix2d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + matrix2d myMatrix2d = ((26, 27), (28, 29)) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/27_matrix3d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/27_matrix3d.usda new file mode 100644 index 0000000000..3c3dbfbf20 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/27_matrix3d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + matrix3d myMatrix3d = ((30, 31, 32), (33, 34, 35), (36, 37, 38)) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/28_matrix4d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/28_matrix4d.usda new file mode 100644 index 0000000000..625a9f9039 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/28_matrix4d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + matrix4d myMatrix4d = ((39, 40, 41, 42), (43, 44, 45, 46), (47, 48, 49, 50), (51, 52, 53, 54)) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/29_quatd.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/29_quatd.usda new file mode 100644 index 0000000000..ce105831c1 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/29_quatd.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + quatd myQuatd = (1, 2, 3, 4) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/2_bool.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/2_bool.usda new file mode 100644 index 0000000000..21026ab657 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/2_bool.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + bool myBool = false +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/30_quatf.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/30_quatf.usda new file mode 100644 index 0000000000..dbbf9357c2 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/30_quatf.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + quatf myQuatf = (1, 2, 3, 4) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/31_quath.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/31_quath.usda new file mode 100644 index 0000000000..97dbecb8c6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/31_quath.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + quath myQuath = (1, 2, 3, 4) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/32_opaque.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/32_opaque.usda new file mode 100644 index 0000000000..d8da4136cb --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/32_opaque.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + opaque myOpaque = None +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/33_color3d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/33_color3d.usda new file mode 100644 index 0000000000..f823734570 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/33_color3d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color3d myColor3d = (1, 2, 3) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/34_color3f.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/34_color3f.usda new file mode 100644 index 0000000000..d67599d9cb --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/34_color3f.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color3f myColor3f = (4, 5, 6) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/35_color3h.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/35_color3h.usda new file mode 100644 index 0000000000..7133546a77 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/35_color3h.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color3h myColor3h = (7, 8, 9) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/36_color4d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/36_color4d.usda new file mode 100644 index 0000000000..41c87d62a5 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/36_color4d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color4d myColor4d = (1, 2, 3, 4) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/37_color4f.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/37_color4f.usda new file mode 100644 index 0000000000..7d4cbe9e54 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/37_color4f.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color4f myColor4f = (4, 3, 2, 1) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/38_color4h.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/38_color4h.usda new file mode 100644 index 0000000000..9703780141 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/38_color4h.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color4h myColor4h = (1, 4, 3, 2) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/39_normal3d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/39_normal3d.usda new file mode 100644 index 0000000000..ce8831f62b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/39_normal3d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + normal3d myNormal3d = (1, 0, 0) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/3_double.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/3_double.usda new file mode 100644 index 0000000000..0bb7e02eec --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/3_double.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + double myDouble = 1.05946309435929 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/40_normal3f.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/40_normal3f.usda new file mode 100644 index 0000000000..05dafff3cb --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/40_normal3f.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + normal3f myNormal3f = (0, 1, 0) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/41_normal3h.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/41_normal3h.usda new file mode 100644 index 0000000000..eb2101aec6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/41_normal3h.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + normal3h myNormal3h = (0, 0.8, -0.6) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/42_point3d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/42_point3d.usda new file mode 100644 index 0000000000..1b9c86fc3f --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/42_point3d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + point3d myPoint3d = (0.1, 0.2, 0.1) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/43_point3f.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/43_point3f.usda new file mode 100644 index 0000000000..399e6edc71 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/43_point3f.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + point3f myPoint3f = (1, 3, 3) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/44_point3h.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/44_point3h.usda new file mode 100644 index 0000000000..1c3bee36e9 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/44_point3h.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + point3h myPoint3h = (1, 1, 4) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/45_vector3d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/45_vector3d.usda new file mode 100644 index 0000000000..f1c08c908d --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/45_vector3d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + vector3d myVector3d = (6, 4, 1) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/46_vector3f.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/46_vector3f.usda new file mode 100644 index 0000000000..44177e8e17 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/46_vector3f.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + vector3f myVector3f = (1, 5, 10) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/47_vector3h.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/47_vector3h.usda new file mode 100644 index 0000000000..a311ff3d42 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/47_vector3h.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + vector3h myVector3h = (10, 5, 1) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/48_frame4d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/48_frame4d.usda new file mode 100644 index 0000000000..4065d0eee6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/48_frame4d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + frame4d myFrame4d = ( (1, 1, 2, 3), (5, 8, 13, 21), (34, 55, 89, 144), (0, 0, 0, 1) ) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/49_texCoord2d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/49_texCoord2d.usda new file mode 100644 index 0000000000..323731d87f --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/49_texCoord2d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord2d myTexCoord2d = (2, 8) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/4_float.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/4_float.usda new file mode 100644 index 0000000000..da43e03924 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/4_float.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + float myFloat = 6.28 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/50_texCoord2f.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/50_texCoord2f.usda new file mode 100644 index 0000000000..d9a064f5f9 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/50_texCoord2f.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord2f myTexCoord2f = (4, 16) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/51_texCoord2h.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/51_texCoord2h.usda new file mode 100644 index 0000000000..b8669fadad --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/51_texCoord2h.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord2h myTexCoord2h = (8, 32) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/52_texCoord3d.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/52_texCoord3d.usda new file mode 100644 index 0000000000..ea9617c251 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/52_texCoord3d.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord3d myTexCoord3d = (1, 4, 9) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/53_texCoord3f.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/53_texCoord3f.usda new file mode 100644 index 0000000000..3da638fbda --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/53_texCoord3f.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord3f myTexCoord3f = (16, 25, 36) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/54_texCoord3h.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/54_texCoord3h.usda new file mode 100644 index 0000000000..34b88d8b68 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/54_texCoord3h.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + texCoord3h myTexCoord3h = (49, 64, 81) +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/55_group.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/55_group.usda new file mode 100644 index 0000000000..88f021c291 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/55_group.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + group myGroup +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/56_asset_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/56_asset_array.usda new file mode 100644 index 0000000000..4cc311f207 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/56_asset_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + asset[] myAssetArray = [@foo.png@, @bar.png@] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/57_bool_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/57_bool_array.usda new file mode 100644 index 0000000000..72de69e51b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/57_bool_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + bool[] myBoolArray = [false, true] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/58_double_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/58_double_array.usda new file mode 100644 index 0000000000..c1f3ca02cc --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/58_double_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + double[] myDoubleArray = [1.05946309435929, -3.14] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/59_float_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/59_float_array.usda new file mode 100644 index 0000000000..6e14a3b6b4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/59_float_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + float[] myFloatArray = [6.28, 628] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/5_half.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/5_half.usda new file mode 100644 index 0000000000..a97865b83e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/5_half.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + half myHalf = -2.718 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/60_half_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/60_half_array.usda new file mode 100644 index 0000000000..337c9e500e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/60_half_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + half[] myHalfArray = [-2.718, 0.02718] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/61_int_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/61_int_array.usda new file mode 100644 index 0000000000..89dfd1793e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/61_int_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int[] myIntArray = [6, 61] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/62_int64_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/62_int64_array.usda new file mode 100644 index 0000000000..e354fc20eb --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/62_int64_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int64[] myInt64Array = [71, 62] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/63_string_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/63_string_array.usda new file mode 100644 index 0000000000..7da22d8db3 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/63_string_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + string[] myStringArray = ["bar", "baz"] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/64_timecode_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/64_timecode_array.usda new file mode 100644 index 0000000000..581b3426b9 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/64_timecode_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + timecode[] myTimecodeArray = [1.23, 4.56] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/65_token_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/65_token_array.usda new file mode 100644 index 0000000000..a8e4e483ac --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/65_token_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + token[] myTokenArray = ["fizz", "buzz"] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/66_uchar_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/66_uchar_array.usda new file mode 100644 index 0000000000..e6f42d4db5 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/66_uchar_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + uchar[] myUcharArray = [137, 66] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/67_uint_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/67_uint_array.usda new file mode 100644 index 0000000000..82a228554a --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/67_uint_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + uint[] myUintArray = [12, 34] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/68_uint64_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/68_uint64_array.usda new file mode 100644 index 0000000000..31d489df6e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/68_uint64_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + uint64[] myUint64Array = [123, 456] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/69_double2_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/69_double2_array.usda new file mode 100644 index 0000000000..e4da00f41a --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/69_double2_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + double2[] myDouble2Array = [(-1, -2), (3, 4)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/6_int.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/6_int.usda new file mode 100644 index 0000000000..e4a142f23f --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/6_int.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int myInt = 6 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/70_double3_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/70_double3_array.usda new file mode 100644 index 0000000000..35166b4948 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/70_double3_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + double3[] myDouble3Array = [(-1, -2, -3), (1, 2, 3)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/71_double4_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/71_double4_array.usda new file mode 100644 index 0000000000..d3077022ae --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/71_double4_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + double4[] myDouble4Array = [(-1, -2, -3, -4), (4, 3, 2, 1)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/72_float2_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/72_float2_array.usda new file mode 100644 index 0000000000..6b5f844cf2 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/72_float2_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + float2[] myFloat2Array = [(-10, -20), (7, 2)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/73_float3_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/73_float3_array.usda new file mode 100644 index 0000000000..ed8f40a0c1 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/73_float3_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + float3[] myFloat3Array = [(-10, -20, -30), (1, 2, 3)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/74_float4_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/74_float4_array.usda new file mode 100644 index 0000000000..fcb7a3259c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/74_float4_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + float4[] myFloat4Array = [(-10, -20, -30, -40), (40, 3, 20, 1)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/75_half2_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/75_half2_array.usda new file mode 100644 index 0000000000..9950cd1c9f --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/75_half2_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + half2[] myHalf2Array = [(-0.01, -0.02), (7, 5)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/76_half3_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/76_half3_array.usda new file mode 100644 index 0000000000..017759d49f --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/76_half3_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + half3[] myHalf3Array = [(-0.01, -0.02, -0.03), (1, 2, 3)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/77_half4_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/77_half4_array.usda new file mode 100644 index 0000000000..e9c47a2769 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/77_half4_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + half4[] myHalf4Array = [(-0.01, -0.02, -0.03, -0.04), (7, 7, 7, 7)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/78_int2_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/78_int2_array.usda new file mode 100644 index 0000000000..b65db86072 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/78_int2_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int2[] myInt2Array = [(-100, -200), (7, 8)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/79_int3_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/79_int3_array.usda new file mode 100644 index 0000000000..954281a232 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/79_int3_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int3[] myInt3Array = [(-100, -200, -300), (7, 9, 0)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/7_int64.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/7_int64.usda new file mode 100644 index 0000000000..9e11a68482 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/7_int64.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int64 myInt64 = 71 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/80_int4_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/80_int4_array.usda new file mode 100644 index 0000000000..f09eb313ab --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/80_int4_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + int4[] myInt4Array = [(-100, -200, -300, -400)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/81_matrix2d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/81_matrix2d_array.usda new file mode 100644 index 0000000000..85f6c08489 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/81_matrix2d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + matrix2d[] myMatrix2dArray = [((26, 27), (28, 29))] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/82_matrix3d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/82_matrix3d_array.usda new file mode 100644 index 0000000000..db508127a2 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/82_matrix3d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + matrix3d[] myMatrix3dArray = [((30, 31, 32), (33, 34, 35), (36, 37, 38))] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/83_matrix4d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/83_matrix4d_array.usda new file mode 100644 index 0000000000..9fb694a188 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/83_matrix4d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + matrix4d[] myMatrix4dArray = [((39, 40, 41, 42), (43, 44, 45, 46), (47, 48, 49, 50), (51, 52, 53, 54))] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/84_quatd_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/84_quatd_array.usda new file mode 100644 index 0000000000..f9a1308422 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/84_quatd_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + quatd[] myQuatdArray = [(1, 2, 3, 4)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/85_quatf_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/85_quatf_array.usda new file mode 100644 index 0000000000..3c6c23ed09 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/85_quatf_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + quatf[] myQuatfArray = [(1, 2, 3, 4)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/86_quath_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/86_quath_array.usda new file mode 100644 index 0000000000..d5ba165ebc --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/86_quath_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + quath[] myQuathArray = [(1, 2, 3, 4)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/87_color3d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/87_color3d_array.usda new file mode 100644 index 0000000000..645b4df307 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/87_color3d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color3d[] myColor3dArray = [] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/88_color3f_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/88_color3f_array.usda new file mode 100644 index 0000000000..d0ac8be1ac --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/88_color3f_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color3f[] myColor3fArray = [(4, 5, 6)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/89_color3h_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/89_color3h_array.usda new file mode 100644 index 0000000000..57d1a09761 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/89_color3h_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color3h[] myColor3hArray = [(7, 8, 9)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/8_string.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/8_string.usda new file mode 100644 index 0000000000..6a42b42d72 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/8_string.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + string myString = "bar" +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/90_color4d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/90_color4d_array.usda new file mode 100644 index 0000000000..d2277c1412 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/90_color4d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color4d[] myColor4dArray = [(1, 2, 3, 4)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/91_color4f_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/91_color4f_array.usda new file mode 100644 index 0000000000..7a26ee49e2 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/91_color4f_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color4f[] myColor4fArray = [(4, 3, 2, 1)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/92_color4h_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/92_color4h_array.usda new file mode 100644 index 0000000000..fc5d8d55b3 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/92_color4h_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + color4h[] myColor4hArray = [(1, 4, 3, 2)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/93_normal3d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/93_normal3d_array.usda new file mode 100644 index 0000000000..c7a0b07335 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/93_normal3d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + normal3d[] myNormal3dArray = [(1, 0, 0)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/94_normal3f_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/94_normal3f_array.usda new file mode 100644 index 0000000000..56c4e48168 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/94_normal3f_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + normal3f[] myNormal3fArray = [(0, 1, 0)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/95_normal3h_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/95_normal3h_array.usda new file mode 100644 index 0000000000..9e21bf20d2 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/95_normal3h_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + normal3h[] myNormal3hArray = [(0, 0.8, -0.6)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/96_point3d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/96_point3d_array.usda new file mode 100644 index 0000000000..1e2c9d1ae8 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/96_point3d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + point3d[] myPoint3dArray = [(0.1, 0.2, 0.1)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/97_point3f_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/97_point3f_array.usda new file mode 100644 index 0000000000..bb14354d0b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/97_point3f_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + point3f[] myPoint3fArray = [(1, 3, 3)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/98_point3h_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/98_point3h_array.usda new file mode 100644 index 0000000000..8dd560d389 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/98_point3h_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + point3h[] myPoint3hArray = [(1, 1, 4)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/99_vector3d_array.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/99_vector3d_array.usda new file mode 100644 index 0000000000..eb164517b4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/99_vector3d_array.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + vector3d[] myVector3dArray = [(6, 4, 1)] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/9_timecode.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/9_timecode.usda new file mode 100644 index 0000000000..4b0a4b12e8 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/6_comprehensive_typenames/9_timecode.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "foo" +{ + timecode myTimecode = 1.23 +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/1_one-spline.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/1_one-spline.usda new file mode 100644 index 0000000000..db57b1ad43 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/1_one-spline.usda @@ -0,0 +1,10 @@ +#usda 1.0 + +def "hello" +{ + double myAttr.spline = { + 1: 1; post curve, + 10: 10; post none, + post: none + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/2_another-spline.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/2_another-spline.usda new file mode 100644 index 0000000000..e4eb3a3733 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/2_another-spline.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "hello" +{ + double myAttr.spline = { + loop: (1, 2, 3, 4, 5) + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/3_empty-spline.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/3_empty-spline.usda new file mode 100644 index 0000000000..bf1a58c0b6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/3_empty-spline.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +# pxr/usd/usd/testenv/testUsdValueClips/dataFormat/generated_manifest_clip0.usda + +def "Foo" +{ + float myAttr.spline = {} + float myAttr.timeSamples = {0:1} +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/4_float-spline.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/4_float-spline.usda new file mode 100644 index 0000000000..e5d323ac9c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/4_float-spline.usda @@ -0,0 +1,10 @@ +#usda 1.0 + +def "hello" +{ + float myAttr.spline = { + 1: 1; post curve, + 10: 10; post none, + post: none + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/5_spline-with-custom-data.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/5_spline-with-custom-data.usda new file mode 100644 index 0000000000..752027b300 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/5_spline-with-custom-data.usda @@ -0,0 +1,10 @@ +#usda 1.0 + +def "hello" +{ + double myAttr.spline = { + 1: 1; post curve; { string comment = "foo" }, + 10: 10; post none, + post: none + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/6_one-spline-1.1.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/6_one-spline-1.1.usda new file mode 100644 index 0000000000..3f29c527bf --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/6_one-spline-1.1.usda @@ -0,0 +1,9 @@ +#usda 1.1 + +def "hello" +{ + double myAttr.spline = { + 1: 2; pre (3, 4, autoEase); post curve (5, 6), + post: none + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/7_loop_boundary_time.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/7_loop_boundary_time.usda new file mode 100644 index 0000000000..4d9a336035 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/7_loop_boundary_time.usda @@ -0,0 +1,9 @@ +#usda 1.1 + +def "hello" +{ + double myAttr.spline = { + 1: 2; pre (3, 4, autoEase); post curve (5, 6), + post: loop repeat(0.57), + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/8_preValue.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/8_preValue.usda new file mode 100644 index 0000000000..2a9efd3229 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/7_splines/8_preValue.usda @@ -0,0 +1,9 @@ +#usda 1.1 + +def "hello" +{ + double myAttr.spline = { + 1: 1.5 & 2; pre (3, 4, autoEase); post curve (5, 6), + post: loop repeat(0.57), + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/10_reference_with_custom_data.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/10_reference_with_custom_data.usda new file mode 100644 index 0000000000..2a77e56ff7 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/10_reference_with_custom_data.usda @@ -0,0 +1,11 @@ +#usda 1.0 + +def "Fizz" ( + prepend references = @./Foo.usda@ ( + customData = { + string foo = 'bar' + } + ) +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/1_attr-display-unit.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/1_attr-display-unit.usda new file mode 100644 index 0000000000..5d9a1449e7 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/1_attr-display-unit.usda @@ -0,0 +1,6 @@ +#usda 1.0 + +def "A" +{ + custom double foo = 1 (displayUnit = mm) +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/2_default-relationship.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/2_default-relationship.usda new file mode 100644 index 0000000000..4ace76ddda --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/2_default-relationship.usda @@ -0,0 +1,10 @@ +#usda 1.0 + +def "A" +{ + varying rel foo = [ + , + , + ] + varying rel foo.default = +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/3_reorder-rootprims.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/3_reorder-rootprims.usda new file mode 100644 index 0000000000..af53873d13 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/3_reorder-rootprims.usda @@ -0,0 +1,11 @@ +#usda 1.0 + +reorder rootPrims = ["B", "A"] + +def "A" +{ +} + +def "B" +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/4_reorder-properties.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/4_reorder-properties.usda new file mode 100644 index 0000000000..5cbe204f8d --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/4_reorder-properties.usda @@ -0,0 +1,8 @@ +#usda 1.0 + +def "A" +{ + reorder properties = ["fizz", "buzz"] + float buzz = 0 + float fizz = 0 +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/5_sdflistop-longlong.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/5_sdflistop-longlong.usda new file mode 100644 index 0000000000..fe6c5e3a57 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/5_sdflistop-longlong.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +# pxr/usdImaging/usdImagingGL/testenv/testUsdImagingGLPointInstancer/pi_masking.usda + +def PointInstancer "Foo" ( + inactiveIds = [3] +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/6_varying-relationship.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/6_varying-relationship.usda new file mode 100644 index 0000000000..13ee002cde --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/6_varying-relationship.usda @@ -0,0 +1,7 @@ +#usda 1.0 + + +def Mesh "foo" +{ + varying rel customRel +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/7_custom-relationship.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/7_custom-relationship.usda new file mode 100644 index 0000000000..ceb0252645 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/7_custom-relationship.usda @@ -0,0 +1,6 @@ +#usda 1.0 + +def "A" +{ + custom rel myCustomRel +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/8_reference_with_offset.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/8_reference_with_offset.usda new file mode 100644 index 0000000000..0f9ec61690 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/8_reference_with_offset.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "Fizz" ( + prepend references = @./Foo.usda@ (scale = 0.25) +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/9_payload_with_offset.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/9_payload_with_offset.usda new file mode 100644 index 0000000000..0acba419a6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/9_payload_with_offset.usda @@ -0,0 +1,7 @@ +#usda 1.0 + +def "Fizz" ( + prepend payload = @./Foo.usda@ (scale = 0.25) +) +{ +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/SKIP-one-array-edit.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/SKIP-one-array-edit.usda new file mode 100644 index 0000000000..81eac49363 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/8_uncommon/SKIP-one-array-edit.usda @@ -0,0 +1,16 @@ +#usda 1.0 + +# As of OpenUSD v26.08, there's no way to get at the operations held by a VtArrayEdit +# without breaking C++ access control or horrible hacks like reinterpret_casting a pointer +# to a VtArrayEdit to a pointer to another type constructed to have the same layout or +# trying to parse the result of printing it to a stream. +# This makes it impossible for custom file format plugins to losslessly handle VtArrayEdits + +def "Foo" +{ + double[] attr = edit [ + write 3.0 to [5] + ] +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/1_explicit-empty-apischemas.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/1_explicit-empty-apischemas.usda new file mode 100644 index 0000000000..fc2741e17e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/1_explicit-empty-apischemas.usda @@ -0,0 +1,8 @@ +#usda 1.0 + + +def "foo" ( + apiSchemas = [] +) +{ +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/2_one-unknown-metadata.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/2_one-unknown-metadata.usda new file mode 100644 index 0000000000..8224ed87e5 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/2_one-unknown-metadata.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +over "foo" ( + my_custom_key = true +) +{ +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/3_unregistered-dictionary.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/3_unregistered-dictionary.usda new file mode 100644 index 0000000000..5912ed0434 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/3_unregistered-dictionary.usda @@ -0,0 +1,18 @@ +#usda 1.0 + +# extras/usd/examples/usdRecursivePayloadsExample/params.usda +# has an unregistered dictionary + +def "Foo" ( + myUnregisteredMetadata = { + dictionary "Fizz" = { + int a = 1 + int b = 2 + } + dictionary "Buzz" = { + int c = 3 + } + } +) +{ +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/4_point-index.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/4_point-index.usda new file mode 100644 index 0000000000..4cdafb8c45 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/4_point-index.usda @@ -0,0 +1,16 @@ +#usda 1.0 + +def Mesh "card" +{ + # PointIndex is a role synonym for int. Seems mostly + # used by usdDraco? + PointIndex[] customPointArray = [1, 2, 3, 4] + PointIndex customPoint = 5 + + PointIndex animatedPoint.timeSamples = { + 0: 0, + 1: 1 + } +} + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/SKIP-custom-data-path-expression.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/SKIP-custom-data-path-expression.usda new file mode 100644 index 0000000000..0efe99604e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/SKIP-custom-data-path-expression.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +over "hello" ( + customData = { + pathExpression foo = "/Bar" + } +) +{ +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/SKIP-inf-point.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/SKIP-inf-point.usda new file mode 100644 index 0000000000..95c284061b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/SKIP-inf-point.usda @@ -0,0 +1,6 @@ +#usda 1.0 + +def Mesh "MyMesh"{ + float3[] points = [(-1, 0, -1), (1, 0, -1), (inf, inf, inf), (0, 0, 1)] + # float3 otherPoint = (inf, inf, inf) +} \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/SKIP_non-ascii-strings.usda b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/SKIP_non-ascii-strings.usda new file mode 100644 index 0000000000..25449aae27 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/9_edge_cases/SKIP_non-ascii-strings.usda @@ -0,0 +1,11 @@ +#usda 1.0 + +# pxr/usd/sdf/testenv/testSdfParsing.testenv/baseline/46_weirdStringContent.usda +# contains data that (I think) ends up being parsed as invalid Unicode sequences, +# which is not required to be supported + +def "foo" +{ + string s = "foo\x80\x81\x82\x83bar" +} + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/README b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/README new file mode 100644 index 0000000000..59a30d71ab --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Resources/README @@ -0,0 +1,35 @@ +These are test files for a SdfFileFormat that wants to be able to losslessly roundtrip USD files. + +They're loosely organized into different tiers of how essential/important/common different behavior is. If you're writing an SdfFileFormat plugin and using these files to test your plugin, focus on the earlier tiers first. + +1_essential: Prims, attributes, relationships. +Pay special attention to 15_simple-prim-ordering.usda. The order that prims appear in a USD file generally doesn't matter, but because usddiff does a simple textual diff of the USDA version of files, it's a good idea to record the order prims appear somewhere in your file format if you're using these test cases. + +2_metadata: Metadata on specs + +3_common: Grab bag of various common features not covered elsewhere, or slightly harder versions of previous test cases + +4_composition_without_variants: Composition arcs are an important part of OpenUSD. (Variants are the most complicated composition arc, and so are handled in the test tier) + +5_variants: The most complicated composition arc + +6_comprehensive_typenames: Individual files for every valid type name + +7_splines: Splines + +8_uncommon: Some uncommon features + +9_edge_cases: Obscure features like SdfUnregisteredValue and the PointIndex role + +10_deprecated: Some features are deprecated but still supported in OpenUSD, like old listops, type names, or metadata + +11_losslessly_handle_invalid_files: Some USD files may be invalid (in the sense that they contain some logical error or mistake) but still can be losslessly round-tripped by SdfFileFormat plugins if they put in the effort. + +12_bad_json: JSON files that this file format parser should fail on. (Likely not useful for other file format plugins) + + + + + +Note: The specification says that listop specializations are valid for at minimum these types: int, int64, uint, uint64, string, token. It also says the following specializations may be allowed: Reference, Payload, Inherit, Specializes, ObjectPath. Not all of these are currently implemented in this file format plugin, and I haven't been able to find any USD files that use the unimplemented ones. I'm not sure if there's currently a way to create them without writing code, since listops typically appear in metadata, I can't find any registered metadata that uses the unimplemented specializations, and any unregistered metadata is parsed as SdfUnregisteredValue when in a USDA file. + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/Driver.swift b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/Driver.swift new file mode 100644 index 0000000000..eca9517df1 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/Driver.swift @@ -0,0 +1,198 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import Subprocess +import System +import ArgumentParser + +class Driver { + init(args: Args) { + self.args = args + self.builtPluginDirectory = args.tempDir.appending(path: "plugin") + } + var args: Args + + var filesToTest: [URL] = [] + var builtPluginDirectory: URL + + func computeFilesToTest() throws { + let knownInvalidOpenUSDFiles = computeKnownInvalidOpenUSDFiles() + + for tree in [resourcesURL()] + args.additionalTrees { + guard let enumerator = FileManager.default.enumerator(at: tree, includingPropertiesForKeys: nil) else { return } + var thisBatch = [URL]() + for case let item as URL in enumerator { + guard item.pathExtension.hasPrefix("usd") else { continue } + guard !item.lastPathComponent.starts(with: "SKIP") else { continue } + + if !args.include.isEmpty { + var wasInInclude = false + for x in args.include { + if item.absoluteString.contains(x) { + wasInInclude = true + break + } + } + if !wasInInclude { continue } + } + + if !args.exclude.isEmpty { + var wasInExclude = false + for x in args.exclude { + if item.absoluteString.contains(x) { + wasInExclude = true + break + } + } + if wasInExclude { continue } + } + + var isKnownInvalidOpenUSDFile = false + for x in knownInvalidOpenUSDFiles { + if item.absoluteString.contains(x) { + isKnownInvalidOpenUSDFile = true + continue + } + } + if isKnownInvalidOpenUSDFile { continue } + + thisBatch.append(item.absoluteURL) + } + thisBatch.sort(using: KeyPathComparator(\.path)) + filesToTest.append(contentsOf: thisBatch) + } + + if args.shuffleTests { + filesToTest.shuffle() + } + } + + func buildPlugin() async throws { + let pluginRepoPath = args.plugin.path(percentEncoded: false) + let builtPluginPath = builtPluginDirectory.path(percentEncoded: false) + + if args.verbose { + print("cd \(pluginRepoPath) && swift build") + } + try await Subprocess.run( + .name("swift"), + arguments: ["build"], + workingDirectory: FilePath(args.plugin), + output: .currentStandardOutput, + error: .currentStandardError, + ) + .check("swift build") + + + if args.verbose { + print("cd \(pluginRepoPath) && swift package build-vanilla-openusd-plugin -o \(builtPluginPath)") + } + try await Subprocess.run( + .name("swift"), + arguments: ["package", "build-vanilla-openusd-plugin", "-o", builtPluginPath], + workingDirectory: FilePath(args.plugin), + output: .currentStandardOutput, + error: .currentStandardError, + ).check("swift package build-vanilla-openusd-plugin -o \(builtPluginPath)") + } + + func run() async throws { + + try computeFilesToTest() + + if args.listTestsOnly { + for file in filesToTest { + print(file.absoluteURL.path(percentEncoded: false)) + } + print("\n\(filesToTest.count) tests") + return + } + + if FileManager.default.fileExists(atPath: args.tempDir.path(percentEncoded: false)) { + try FileManager.default.removeItem(at: args.tempDir) + } + try FileManager.default.createDirectory(at: args.tempDir, withIntermediateDirectories: true) + + try await buildPlugin() + + try await runTestsInParallel() + } + + func runTestsInParallel() async throws { + let (nTests, failures) = try await withThrowingTaskGroup(of: TestOneResult.self) { + [args, filesToTest, builtPluginDirectory] taskGroup in + + var i = 0 + func launchTask() { + taskGroup.addTask { [i] in + await test_one(args: args, tempDir: args.tempDir.appending(path: String(i)), file: filesToTest[i], builtPluginDir: builtPluginDirectory) + + } + i += 1 + } + + while i < min(filesToTest.count, args.jobs) { + launchTask() + } + + var failures = [URL]() + var nTests = 0 + for try await child in taskGroup { + guard failures.isEmpty || !args.stopOnFirstFailure else { continue } + + nTests += 1 + let formattedDuration = String(format: "%.2f", child.duration) + print("\(args.verbose ? "\n" : "")Tested \(child.file.path(percentEncoded: false)) (\(formattedDuration)s) (\(nTests)/\(filesToTest.count))") + if args.verbose || !child.success { + for l in child.output where !l.isEmpty { + print(l) + } + } + if !child.success { + failures.append(child.file) + } + + if failures.count > 0 && args.stopOnFirstFailure { + taskGroup.cancelAll() + break + } else if i < filesToTest.count { + launchTask() + } + } + + return (nTests, failures) + } + + if !failures.isEmpty { + print("\nFailures:") + for f in failures { + print(f.path(percentEncoded: false)) + } + } + + print("\nSummary: \(nTests - failures.count) out of \(nTests) tests passed") + throw ExitCode(failures.count > 0 ? 1 : 0) + } +} + + + + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/Misc.swift b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/Misc.swift new file mode 100644 index 0000000000..488f830ee7 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/Misc.swift @@ -0,0 +1,270 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation + +func resourcesURL() -> URL { + URL(fileURLWithPath: #filePath) + .deletingLastPathComponent().deletingLastPathComponent() + .appendingPathComponent("Resources") +} + +func computeKnownInvalidOpenUSDFiles() -> [String] { + [ + // These are intentionally malformed, to check that Sdf parsing + // rejects invalid files + "pxr/usd/sdf/testenv/testSdfParsing.testenv/03_bad_file.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/05_bad_file.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/08_bad_file.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/09_bad_type.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/10_bad_value.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/12_bad_value.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/13_bad_value.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/14_bad_value.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/15_bad_list.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/16_bad_list.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/21_bad_newline1.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/22_bad_newline2.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/23_bad_newline3.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/24_bad_newline4.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/25_bad_newline5.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/26_bad_newline6.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/27_bad_newline7.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/28_bad_newline8.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/29_bad_newline9.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/30_bad_specifier.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/33_bad_relationship_duplicate_target.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/34_bad_relationship_duplicate_target_attr.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/42_bad_noNewlineBetweenComps.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/49_bad_list.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/50_bad_primPath.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/52_bad_attr.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/53_bad_typeName.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/54_bad_value.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/55_bad_value.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/55_bad_value_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/56_bad_value.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/56_bad_value_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/57_bad_relListEditing.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/58_bad_relListEditing.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/59_bad_connectListEditing.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/60_bad_groupListEditing.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/61_bad_primName.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/64_bad_boolPrimInstantiate.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/66_bad_attrVariability.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/69_bad_list.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/70_bad_list.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/80_bad_hidden.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/82_bad_tuple_dimensions1_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/82_bad_tuple_dimensions1.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/83_bad_tuple_dimensions2.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/83_bad_tuple_dimensions2_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/84_bad_tuple_dimensions3_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/84_bad_tuple_dimensions3.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/85_bad_tuple_dimensions4.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/85_bad_tuple_dimensions4_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/86_bad_tuple_dimensions5.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/89_bad_attribute_displayUnit.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/90_bad_dupePrim.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/91_bad_valueType.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/92_bad_variantSelectionType.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/94_bad_hiddenAttr.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/95_bad_hiddenRel.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/96_bad_valueType.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/96_bad_valueType_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/97_bad_valueType.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/98_bad_valueType.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/99_bad_typeNameChange.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/100_bad_roleNameChange.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/103_bad_attributeVariability.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/108_bad_inheritPath.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/114_bad_prefix_metadata.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/117_bad_permission_metadata.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/118_bad_permission_metadata_2.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/119_bad_permission_metadata_3.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/baseline/120_sub_attribute_relations.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/124_badwrite_marker_names.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/133_bad_reference.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/140_bad_relocates_paths_1.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/141_bad_relocates_paths_2.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/142_bad_relocates_paths_3.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/143_bad_relocates_formatting_1.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/144_bad_relocates_formatting_2.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/145_bad_relocates_formatting_3.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/146_bad_relocates_formatting_4.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/147_bad_relocates_formatting_5.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/150_bad_kind_metadata_1.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/153_bad_payloads.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/155_bad_relationship_noLoadHint.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/160_bad_variant_name1.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/161_bad_variant_name2.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/162_bad_variant_selection1.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/163_bad_variant_selection2.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/177_bad_empty_lists.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/179_bad_shaped_attr_dimensions1_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/179_bad_shaped_attr_dimensions1.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/181_bad_variant_in_connection.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/182_bad_variant_in_relationship.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/186_bad_prefix_substitution_key.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/194_bad_customLayerData_metadata.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/baseline/194_bad_customLayerData_metadata.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/197_bad_colorConfiguration_metadata.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/199_bad_colorSpace_metadata.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/200_bad_emptyFile.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/205_bad_assetPaths.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/206_bad_escaped_string1.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/207_bad_escaped_string2.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/208_bad_escaped_string3.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/209_bad_escaped_string4.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/211_bad_authored_opaque_attributes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/212_bad_variant_in_reference_path.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/213_bad_variant_in_payload_path.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/214_bad_variant_in_inherits_path.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/215_bad_variant_in_specializes_path.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/216_bad_variant_in_relocates_path.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/218_utf8_bad_identifier.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/219_utf8_bad_type_name.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/221_bad_spline_type.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/223_bad_spline_post_shaping_spacing.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/229_bad_spline_extrap_loop_boundary.usda", + + // This file claims to test the __END__ facility that stops the parser from proceeding, + // but usdcat fails on it. Maybe it's old behavior that was removed? + "pxr/usd/sdf/testenv/testSdfParsing.testenv/07_end.usda", + + // Malformed files + "pxr/usd/sdf/testenv/testSdfTargetFileFormat.testenv/anyCookie.usda", + "pxr/usd/sdf/testenv/testSdfTargetFileFormat.testenv/badCookie.usda", + "pxr/usd/sdf/testenv/testSdfTargetFileFormat.testenv/goodCookie.usda", + "pxr/usd/sdf/testenv/testSdfUsdcMalformed/bad_overflow_size.usdc", + "pxr/usd/sdf/testenv/testSdfUsdcMalformed/bad_str_oversize.usdc", + "pxr/usd/sdf/testenv/testSdfUsdcMalformed/bad_oversize_zerocopy.usdc", + "pxr/usd/sdf/testenv/testSdfUsdcMalformed/bad_moderate_oversize.usdc", + "pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.testenv/duplicate_prim_children.usdc", + "pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.testenv/root.usdc", + + // TODO: Consider whether we should suppress e.g. relocation errors so we can losslessly roundtrip + // this cattable but illegal file + "pxr/usd/pcp/testenv/testPcpMuseum_ErrorOpinionAtRelocationSource.testenv/ErrorOpinionAtRelocationSource/root.usda", + + // Can't be catted due to invalid relocates + "pxr/usd/pcp/testenv/testPcpMuseum_ErrorRelocateWithVariantSelection.testenv/ErrorRelocateWithVariantSelection/root.usda", + + // Invalid USDC file + "pxr/usd/usd/testenv/testUsdReadOutOfBounds/corrupt.usd", + "pxr/usd/usd/testenv/testUsdUsdcBugGHSA02.testenv/root.usdc", + // Invalid USDZ files + "pxr/usd/usd/testenv/testUsdUsdzBugGHSA01.testenv/root.usdz", + "pxr/usdValidation/bin/usdchecker/testenv/testUsdChecker/bad/alembic.usdz", + "pxr/usd/usd/testenv/testUsdUsdzFileFormat/first_file_not_usd.usdz", + "pxr/usd/sdf/testenv/testSdfZipFile.testenv/test_reader.usdz", + + // Bad header, probably a typo not caught due to being for doxygen + "pxr/usd/usdRender/doxygen/renderSettings.usda", + + // Invalid USDA file + "pxr/usd/pcp/testenv/testPcpMuseum_SubrootReferenceAndVariants.testenv/SubrootReferenceAndVariants/root.usda", + + // Invalid USDA file + "pxr/usd/usd/testenv/testUsdBug119633.testenv/ref.usda", + + // TODO: This uses `15.999999995559108` as a time sample key, which we seem to be dropping due to + // insufficient precision? + "pxr/usd/usd/testenv/testUsdValueClips/flatten/flat.usda", + + // TODO: Reenable these after patching rapidjson to recognize lowercase `inf` + "pxr/usd/sdf/testenv/testSdfParsing.testenv/31_attribute_values.usda", + "pxr/usd/pcp/testenv/testPcpMuseum_BasicVariantWithConnections.testenv/BasicVariantWithConnections/camera_perspective.usda", + "pxr/usd/usdPhysics/generatedSchema.usda", + "pxr/usd/usdPhysics/schema.usda", + "pxr/usdImaging/bin/testusdview/testenv/testUsdviewInfGeom/infGeom.usda", + "pxr/usd/pcp/testenv/testPcpDependencies.testenv/BasicVariantWithConnections/camera_perspective.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/31_attribute_values_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/baseline/31_attribute_values_oldtypes.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/baseline/31_attribute_values.usda", + + // Malformed file + "pxr/usdImaging/bin/testusdview/testenv/testUsdviewFileArguments/invalidSyntax.usda", + + // This file is malformed due to what is probably an unintentional typo + "pxr/exec/exec/testenv/testExecComputationRegistration/resources/schema.usda", + + // usdcat doesn't detect the file format, though these files would be a valid .usda file with that extension + "extras/usd/examples/usdRecursivePayloadsExample/cone.usdrecursivepayloadsexample", + "extras/usd/examples/usdRecursivePayloadsExample/sphere.usdrecursivepayloadsexample", + "extras/usd/examples/usdRecursivePayloadsExample/testenv/testUsdRecursivePayloadsExample/sphere.usdrecursivepayloadsexample", + "extras/usd/examples/usdRecursivePayloadsExample/testenv/testUsdRecursivePayloadsExample/cone.usdrecursivepayloadsexample", + + // Running usdcat on these files produces files that usdcat can't open (quotes are dropped on path expressions in customData dictionaries), + // which is a bug in OpenUSD. Skip for now. https://github.com/PixarAnimationStudios/OpenUSD/issues/4182 + "pxr/usd/usd/testenv/testUsdNamespaceEditorPathExpressionFixup/basic/sub1.usda", + "pxr/usd/usd/testenv/testUsdNamespaceEditorPathExpressionFixup/basic/root.usda", + "pxr/usd/usd/testenv/testUsdNamespaceEditorPathExpressionFixup/basic/sub2.usda", + + // Files that use VtArrayEdit + "pxr/usd/usd/testenv/testUsdFlatten/root.usd", + "pxr/usd/usd/testenv/testUsdValueClips/arrayEdits/root.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/227_arrayEdits.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/baseline/227_arrayEdits.usda", + "pxr/usd/usd/testenv/testUsdValueClips/arrayEdits/clip.usda", + + // Completely empty file (0 bytes, not an empty usda file) + "pxr/usd/usdUtils/testenv/testUsdUtilsDependencies/computeAllDependenciesInvalidPayload/invalid.usd", + + // usdcat fails on this file, not sure why + "pxr/usd/sdf/testenv/testSdfParsing.testenv/164_attr_mappers.usda", + + // usdcat fails on this file, maybe inherits used to support variant set selections? + "pxr/usd/pcp/testenv/testPcpMuseum_BasicInherits.testenv/BasicInherits/root.usda", + + // Empty variants in metadata are usdcatted as empty metadata, which disappears when usdcatted _again_, + // i.e. a single usdcat does not produce a fixed point as required by this usddiff test. + // Technically maybe a very minor OpenUSD formatting bug? Skip for now + "pxr/usd/pcp/testenv/testPcpRegressionBugs_bug92955.testenv/bug92955/root.usda", + + // Contains illegal Unicode sequences + "pxr/usd/sdf/testenv/testSdfParsing.testenv/baseline/46_weirdStringContent.usda", + "pxr/usd/sdf/testenv/testSdfParsing.testenv/46_weirdStringContent.usda", + + + + // From https://dpel.aswf.io/4004-moore-lane/: + // These files contain `nan`s which can't currently be roundtripped, same as `inf` + // TODO: Fix nan and inf roundtripping + "Intel_mooreLane_v1_2_0/Intel_mooreLane/USD/4004MooreLane_III_03_ASFW.usd", + "Intel_mooreLane_v1_2_0/Intel_mooreLane/USD/4004MooreLane_III_03_ASWF.usd", + "Intel_mooreLane_v1_2_0/Intel_mooreLane/USD/MooreLane_ASWF_0621_fullComposition.usda", + + // From https://dpel.aswf.io/alab/: + // These files are 880MB to multiple GB as .usdc files, and trying to + // run the tests on them caused my machine to crash (twice) due to + // running out of memory. They're probably fine, just very large. + "ALab-2.2.0/ALab/baked_procedurals/payload/stoat_body_main.1004.usd", + "ALab-2.2.0/ALab/baked_procedurals/payload/stoat_body_main.1014.usd", + "ALab-2.2.0/ALab/baked_procedurals/payload/stoat_body_main.1054.usd", + "ALab-2.2.0/ALab/baked_procedurals/payload/stoat_body_main.1044.usd", + "ALab-2.2.0/ALab/baked_procedurals/clip.topology.usd", + "ALab-2.2.0/ALab/baked_procedurals/payload/stoat_body_main.1024.usd", + "ALab-2.2.0/ALab/baked_procedurals/payload/stoat_body_main.1034.usd", + "ALab-2.2.0/ALab/baked_procedurals/stoat.usd", + "ALab-2.2.0/ALab/baked_procedurals/uvs.usd", + ] +} + diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/SubprocessUtil.swift b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/SubprocessUtil.swift new file mode 100644 index 0000000000..56108d86bc --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/SubprocessUtil.swift @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import Subprocess +import ArgumentParser + +struct FileHandleTextOutputStream: TextOutputStream { + let handle: FileHandle + + func write(_ string: String) { + handle.write(Data(string.utf8)) + } + + init(handle: FileHandle) { + self.handle = handle + } + + static var stderr: FileHandleTextOutputStream { + get { + return FileHandleTextOutputStream(handle: .standardError) + } set { + + } + } +} + +extension ExecutionResult { + func check(_ command: String) throws { + switch terminationStatus { + case .exited(let x): + if x != 0 { + print("Error: \(command) failed with exit code \(x).", to: &FileHandleTextOutputStream.stderr) + throw ExitCode(x) + } + + case .signaled(let x): + print("Error: \(command) failed with signal \(x).", to: &FileHandleTextOutputStream.stderr) + throw ExitCode(x) + } + } +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/TestOne.swift b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/TestOne.swift new file mode 100644 index 0000000000..acd17ef5ac --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/TestOne.swift @@ -0,0 +1,173 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import Subprocess +import System + +let STRING_SUBPROCESS_LIMIT = 100_000_000 + +enum TestOneError: Error { + case forwardCatFailed + case forwardCatProducedInvalidJson + case reverseCatFailed + case usddiffFailed +} + +func forwardCat(_ args: Args, _ a: URL, _ b: URL, _ env: Environment, _ output: inout [String]) async throws { + output.append("usdcat \(a.path(percentEncoded: false)) -o \(b.path(percentEncoded: false))") + let proc = try await Subprocess.run( + .name("usdcat"), + arguments: [a.path(percentEncoded: false), "-o", b.path(percentEncoded: false)], + environment: env, + output: .string(limit: STRING_SUBPROCESS_LIMIT), + error: .string(limit: STRING_SUBPROCESS_LIMIT) + ) + output.append(contentsOf: proc.standardOutput?.components(separatedBy: .newlines) ?? []) + output.append(contentsOf: proc.standardError?.components(separatedBy: .newlines) ?? []) + if !proc.terminationStatus.isSuccess { + output.append("usdcat exited with \(proc.terminationStatus)") + throw TestOneError.forwardCatFailed + } +} + +func verifyJsonFileIsActuallyJson(_ a: URL, _ output: inout [String]) throws { + do { + let data = try Data(contentsOf: a) + _ = try JSONSerialization.jsonObject(with: data) + } catch { + output.append("usdcat produced invalid json: \(error)") + throw TestOneError.forwardCatProducedInvalidJson + } +} + +func reverseCat(_ args: Args, _ a: URL, _ b: URL, _ env: Environment, _ output: inout [String]) async throws { + output.append("usdcat \(a.path(percentEncoded: false)) -o \(b.path(percentEncoded: false))") + let proc = try await Subprocess.run( + .name("usdcat"), + arguments: [a.path(percentEncoded: false), "-o", b.path(percentEncoded: false)], + environment: env, + output: .string(limit: STRING_SUBPROCESS_LIMIT), + error: .string(limit: STRING_SUBPROCESS_LIMIT) + ) + output.append(contentsOf: proc.standardOutput?.components(separatedBy: .newlines) ?? []) + output.append(contentsOf: proc.standardError?.components(separatedBy: .newlines) ?? []) + if !proc.terminationStatus.isSuccess { + output.append("usdcat exited with \(proc.terminationStatus)") + throw TestOneError.reverseCatFailed + } +} + +func usddiff(_ args: Args, _ a: URL, _ b: URL, _ output: inout [String]) async throws -> Bool { + var a = a + + if a.pathExtension == "usdz" { + // usddiff will say that a usdz with a single layer is different to a usda with + // the same contents as the usdz's layer. We want to allow those comparisons to + // proceed on single-layer zips so that we have more test cases. + + output.append("usdzip -l \(a.path(percentEncoded: false))") + let proc = try await Subprocess.run( + .name("usdzip"), + arguments: ["-l", a.path(percentEncoded: false)], + output: .string(limit: STRING_SUBPROCESS_LIMIT), + error: .discarded + ) + try proc.check("usdzip -l \(a.path(percentEncoded: false))") + guard proc.standardOutput?.components(separatedBy: .newlines).count == 1 else { + output.append("Warning: Skipping multi-layer usdz \(a.path(percentEncoded: false))") + return true + } + + let tempUsdzCat = b.deletingLastPathComponent().appending(path: b.lastPathComponent + ".usdzextraction.usda") + output.append("usdcat \(a.path(percentEncoded: false)) -o \(tempUsdzCat.path(percentEncoded: false))") + try await Subprocess.run( + .name("usdcat"), + arguments: [a.path(percentEncoded: false), "-o", tempUsdzCat.path(percentEncoded: false)], + output: .discarded, + ).check( + "usdcat \(a.path(percentEncoded: false)) -o \(tempUsdzCat.path(percentEncoded: false))" + ) + + a = tempUsdzCat + } + + output.append("usddiff \(a.path(percentEncoded: false)) \(b.path(percentEncoded: false))") + let proc = try await Subprocess.run( + .name("usddiff"), + arguments: [a.path(percentEncoded: false), b.path(percentEncoded: false)], + output: .string(limit: 16_000_000), + error: .string(limit: 16_000_000), + ) + output.append(contentsOf: proc.standardOutput?.components(separatedBy: .newlines) ?? []) + output.append(contentsOf: proc.standardError?.components(separatedBy: .newlines) ?? []) + + return proc.terminationStatus.isSuccess +} + +struct TestOneResult { + var output: [String] + var success: Bool + var file: URL + var duration: Double +} + +@concurrent func test_one(args: Args, tempDir: URL, file: URL, builtPluginDir: URL) async -> TestOneResult { + var output = [String]() + var success = false + let start = Date() + + let newPluginPathName = if let old = ProcessInfo.processInfo.environment["PXR_PLUGINPATH_NAME"] { + "\(builtPluginDir.path(percentEncoded: false)):\(old)" + } else { + "\(builtPluginDir.path(percentEncoded: false))" + } + let env: Environment = .inherit.updating([ + "PXR_PLUGINPATH_NAME" : newPluginPathName, + ]) + + do { + let jsonFile = tempDir.appending(path: file.lastPathComponent + ".json") + let recattedFile = tempDir.appending(path: file.lastPathComponent + ".recatted.usda") + try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) + + try await forwardCat(args, file, jsonFile, env, &output) + try verifyJsonFileIsActuallyJson(jsonFile, &output) + try await reverseCat(args, jsonFile, recattedFile, env, &output) + success = try await usddiff(args, file, recattedFile, &output) + } catch TestOneError.forwardCatFailed { + success = false + output.append("Forward cat failed") + } catch TestOneError.forwardCatProducedInvalidJson { + success = false + output.append("Forward cat produced invalid json") + } catch TestOneError.reverseCatFailed { + success = false + output.append("Reverse cat failed") + } catch TestOneError.usddiffFailed { + success = false + output.append("usddiff failed") + } catch { + success = false + output.append("Unknown error: \(error)") + } + + return TestOneResult(output: output, success: success, file: file, duration: Date().timeIntervalSince(start)) +} diff --git a/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/usdcat-tests.swift b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/usdcat-tests.swift new file mode 100644 index 0000000000..93b7041f1f --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/Tests/usdcat-tests/Sources/usdcat-tests.swift @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import ArgumentParser +import Subprocess +import System + +@main +struct Args: AsyncParsableCommand { + @Flag(help: "Show verbose output") + var verbose: Bool = false + + @Option(help: "Temporary directory to use", + transform: URL.init(fileURLWithPath:)) + var tempDir: URL = FileManager.default.temporaryDirectory.appending(path: UUID().uuidString) + + @Option(help: "Only run tests that match these files") + var include: [String] = [] + + @Option(help: "Don't run tests that match these files") + var exclude: [String] = [] + + @Option(help: "Also test any USD files in these trees", + transform: URL.init(fileURLWithPath:)) + var additionalTrees: [URL] = [] + + @Flag(help: "List the tests that would be run, and exit") + var listTestsOnly: Bool = false + + @Flag(help: "Stop testing after the first test failure") + var stopOnFirstFailure: Bool = false + + @Flag(help: "Run tests in a random order") + var shuffleTests: Bool = false + + @Option(help: "Run up to this many jobs in parallel") + var jobs: Int = ProcessInfo.processInfo.activeProcessorCount * 2 + + @Argument(help: "Plugin to build and test", + transform: URL.init(fileURLWithPath:)) + var plugin: URL + + func run() async throws { + try await Driver(args: self).run() + } +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/.gitignore b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/.gitignore new file mode 100644 index 0000000000..0023a53406 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Package.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Package.swift new file mode 100644 index 0000000000..4f9cbdf370 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Package.swift @@ -0,0 +1,52 @@ +// swift-tools-version: 6.2 +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + + +import PackageDescription + +let package = Package( + name: "sdfJson", + platforms: [.macOS(.v14), .iOS(.v17)], + products: [ + .library( + name: "sdfJson", + targets: ["sdfJson"] + ), + ], + dependencies: [ + .package(path: "SwiftUsd") + // We use a symlink to the SwiftUsd repo for this example, + // but typically you'd do something like this: + // .package(url: "https://github.com/apple/SwiftUsd", from: "8.1.0"), + ], + targets: [ + .target( + name: "sdfJson", + dependencies: [.product(name: "OpenUSD", package: "SwiftUsd")], + resources: [.copy("plugInfo.json")], + plugins: [.plugin(name: "generate-plug-info-json", package: "SwiftUsd")], + ), + .testTarget(name: "CodeCoverageTests", dependencies: ["sdfJson"], + resources: [.copy("Resources")], + swiftSettings: [.interoperabilityMode(.Cxx)]), + ], + cxxLanguageStandard: .gnucxx17 +) diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/README b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/README new file mode 100644 index 0000000000..a3512ac97a --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/README @@ -0,0 +1,34 @@ +# SdfFileFormat Json plugin (C++) + +This package is an example of how to write an SdfFileFormat plugin in C++. + +## Key details + +- In `plugInfo.json`, we use `@PLUG_INFO_LIBRARY_PATH@`, `@PLUG_INFO_RESOURCE_PATH@`, and `@PLUG_INFO_ROOT@` to allow our plugin to be used in both SwiftUsd-based apps and vanilla OpenUSD-based runtimes. +- In `Package.swift`, we use `.copy("plugInfo.json")` and `.plugin(name: "generate-plug-info-json", package: "SwiftUsd")` to have the build system fill in the `@PLUG_INFO_*@` values based on the target architecture +- In `fileFormat.hpp`, we subclass from `pxr::SdfFileFormat` and override/implement some of its virtual methods. +- In `fileFormat.cpp`, we use the `TF_REGISTRY_FUNCTION` macro along with `SDF_DEFINE_FILE_FORMAT` to tell the OpenUSD runtime how to use our custom plugin. + +## Usage +To use this plugin in a SwiftUsd-based app: +1. Add it as a package dependency to your Swift Package/Xcode project. + +To use this plugin in a vanilla OpenUSD-based app: +1. `cd` into the package directory +2. Run `swift build` +3. Run `swift package build-vanilla-openusd-plugin` and note the outputed plugin path +4. Set the `PXR_PLUGINPATH_NAME` environment variable to point to your plugin. For example: +``` +export PXR_PLUGINPATH_NAME="/Users/maddyadams/SwiftUsd/Examples/SdfFileFormat/hioJson_Cxx/.build/plugins/build-vanilla-openusd-plugin/outputs/sdfJson.usdplugin/:$PXR_PLUGINPATH_NAME" +usdcat example.usda -o example.json +usdcat example.json -o example2.usda +``` + +## Code structure +- `fileFormat.hpp`/`fileFormat.cpp` contains `class SdfJsonFileFormat: public pxr::SdfFileFormat`. It uses `pxr::JsValue` to handle Json parsing/printing, and calls into `readLayer` and `writeLayer` in `CoreSpecSerialization.hpp`. +- `CoreSpecSerialization.hpp`/`CoreSpecSerialization.cpp` handles the reading and writing of layers, prims, attributes, and relationships. +- `LIVERPSSerialization.hpp`/`LIVERPSSerialization.cpp` handles the reading and writing of composition arcs. +- `SdfSerialization.hpp`/`SdfSerialization.cpp` handles the reading and writing of other `Sdf` types. +- `TfSerialization.hpp`/`TfSerialization.cpp` handles the reading and writing of `Tf` types. +- `TsSerialization.hpp`/`TsSerialization.cpp` handles the reading and writing of `Ts` (spline) types. +- `VtSerialization.hpp`/`VtSerialization.cpp` handles the reading and writing of `Vt` types. Particular care is taken with `VtValue` to ensure that USD files can be losslessly converted into Json and back to USD. \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/CoreSpecSerialization.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/CoreSpecSerialization.cpp new file mode 100644 index 0000000000..b460231227 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/CoreSpecSerialization.cpp @@ -0,0 +1,485 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "CoreSpecSerialization.hpp" +#include "FundementalTypes.hpp" +#include "Diagnostics.hpp" +#include "TfSerialization.hpp" +#include "pxr/base/js/json.h" +#include "pxr/usd/ar/resolver.h" +#include "pxr/usd/ar/asset.h" + +void readLayer(const pxr::SdfLayerRefPtr& layer, const pxr::JsValue& value) { + readPrim(layer, layer->GetPseudoRoot(), value); +} + +void writeLayer(std::string* s, const pxr::SdfLayer& layer, const std::string& comment) { + pxr::JsObject js; + writePrim(js, layer.GetPseudoRoot()); + *s = pxr::JsWriteToString(pxr::JsValue(js)); +} + +void readMetadata(const pxr::JsValue& js, const pxr::SdfSpecHandle& spec) { + const pxr::JsObject& metadata = js.GetJsObject(); + + for (const auto& it : metadata) { + const pxr::JsObject& jsMetadataValue = it.second.GetJsObject(); + + TypedValue value = extractTypeHintAndValue(jsMetadataValue); + + MY_VERIFY(spec->SetField(pxr::TfToken(it.first), value.value), + "Failed to set metadata '%s' on '%s' to '%s'", it.first.c_str(), spec->GetPath().GetText(), pxr::TfStringify(value.value).c_str()); + } +} + +void writeMetadata(pxr::JsObject& js, const pxr::SdfSpecHandle& spec) { + pxr::JsObject metadata; + for (const auto& key : spec->GetMetaDataInfoKeys()) { + if (spec->GetField(key).IsEmpty()) { continue; } + if (key == "typeName" && spec->GetSpecType() == pxr::SdfSpecTypePrim) { continue; } + if (key == "payload") { + // For whatever reason, payloads appear as metadata in GetMetaDataInfoKeys. No other + // composition arcs appear this way. We handle payloads as part of the general LIVERPS handling + continue; + } + + TypedValue v = TypedValue::forVtValue(spec->GetField(key)); + metadata[key] = writeTypeHintAndValue(v); + } + + // GetMetaDataInfoKeys only handles known/registered metadata, but + // specs can have unknown metadata on them, e.g. test case one-unknown-metadata.usda. + // So, pull out all the fields on this spec, and then write out the ones + // that aren't registered. + pxr::TfTokenVector registeredFields = spec->GetSchema().GetFields(spec->GetSpecType()); + for (const auto& field : spec->ListFields()) { + bool isRegistered = false; + for (const auto& x : registeredFields) { + if (x == field) { + if (field == pxr::SdfFieldKeys->Comment && !spec->GetField(field).IsEmpty()) { + // pass. Comment isn't provided by GetMetaDataInfoKeys, but is a registered field. + // prim specs and property specs can have it. + } else { + isRegistered = true; + break; + } + } + } + if (isRegistered) { continue; } + + TypedValue v = TypedValue::forVtValue(spec->GetField(field)); + metadata[field] = writeTypeHintAndValue(v); + } + + if (!metadata.empty()) { + js["metadata"] = metadata; + } +} + +void dispatchObjectsUnderPrimForReading(const pxr::SdfLayerRefPtr& layer, const pxr::SdfPath& path, const pxr::JsObject& js, const std::string& key) { + ifValueExists(js, key, [&](const auto& x){ + for (const auto& it : x.GetJsArray()) { + const pxr::JsObject& subObject = it.GetJsObject(); + std::string name; + try { + name = subObject.at("name").GetString(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("'%s' must have a name key-value pair at '%s'", key.c_str(), path.GetText()); + } + + pxr::SdfPath subPath; + if (key == "children") { + subPath = path.AppendChild(pxr::TfToken(name)); + } else { + subPath = path.AppendProperty(pxr::TfToken(name)); + } + + if (key == "children") { + pxr::SdfCreatePrimInLayer(layer, subPath); + readPrim(layer, layer->GetPrimAtPath(subPath), subObject); + } else if (key == "attributes") { + readAttribute(layer, subPath, subObject); + } else if (key == "relationships") { + readRelationship(layer, subPath, subObject); + } else { + MY_FATAL_CODING_ERROR("Internal error, invalid dispatch key '%s'", key.c_str()); + } + } + }); +} + +void readPrim(const pxr::SdfLayerRefPtr& layer, const pxr::SdfPrimSpecHandle& handle, const pxr::JsValue& js) { + if (!handle) { MY_RUNTIME_ERROR_AND_RETURN("readPrim called with an invalid prim handle"); } + const pxr::JsObject& obj = js.GetJsObject(); + std::string spec; + try { + spec = obj.at("spec").GetString(); + } catch (const std::out_of_range&) { + if (!handle->GetPath().IsAbsoluteRootPath()) { + MY_RUNTIME_ERROR_AND_RETURN("readPrim requires spec key"); + } + } + + if (spec == "def") { + handle->SetSpecifier(pxr::SdfSpecifierDef); + } else if (spec == "over") { + handle->SetSpecifier(pxr::SdfSpecifierOver); + } else if (spec == "class") { + handle->SetSpecifier(pxr::SdfSpecifierClass); + } else { + if (handle->GetPath() != pxr::SdfPath::AbsoluteRootPath()) { + MY_RUNTIME_ERROR_AND_RETURN("Unknown specifier '%s'", spec.c_str()); + } + } + + + // LIVERPS + if (handle->GetPath().IsAbsoluteRootPath()) { + ifValueExists(obj, "subLayers", [&](const auto& x){ + layer->SetSubLayerPaths(extractSdfListProxy(x, extractString)); + }); + + ifValueExists(obj, "subLayerOffsets", [&](const auto& x){ + pxr::SdfLayerOffsetVector offsets = extractSdfLayerOffsetVector(x); + for (size_t i = 0; i < offsets.size(); i++) { + layer->SetSubLayerOffset(offsets[i], i); + } + }); + } + ifValueExists(obj, "inherits", [&](const auto& x){ + extractSdfListEditorProxy(x, handle->GetInheritPathList(), extractSdfPath); + }); + ifValueExists(obj, "variantSetNames", [&](const auto& x){ + extractSdfListEditorProxy(x, handle->GetVariantSetNameList(), extractString); + }); + + ifValueExists(obj, "variantSelections", [&](const auto& x){ + extractVariantSelections(handle, x); + }); + + ifValueExists(obj, "variantSets", [&](const auto& x){ + readVariantSets(handle->GetLayer(), handle->GetPath(), x); + }); + + + if (handle->GetPath().IsAbsoluteRootPath()) { + extractLayerRelocates(handle->GetLayer(), obj); + } else { + extractPrimRelocates(obj, handle); + } + ifValueExists(obj, "references", [&](const auto& x){ + extractSdfListEditorProxy(x, handle->GetReferenceList(), extractSdfReference); + }); + ifValueExists(obj, "payloads", [&](const auto& x){ + extractSdfListEditorProxy(x, handle->GetPayloadList(), extractSdfPayload); + }); + ifValueExists(obj, "specializes", [&](const auto& x){ + extractSdfListEditorProxy(x, handle->GetSpecializesList(), extractSdfPath); + }); + + + dispatchObjectsUnderPrimForReading(layer, handle->GetPath(), obj, "attributes"); + dispatchObjectsUnderPrimForReading(layer, handle->GetPath(), obj, "relationships"); + dispatchObjectsUnderPrimForReading(layer, handle->GetPath(), obj, "children"); + + if (!handle->GetPath().IsAbsoluteRootPath()) { + // Important: Set the type last. + // @pxr/usdImaging/usdImagingGL/testenv/testUsdImagingGLPointInstancer/pi_pi_xform.usda@ + // is specified as int[] instead of int64[] as expected by the UsdGeomPointInstancer schema. + // If we set the type before decoding attributes, trying to set the type of attributes will fail. + // By setting the type at the end, we can handle this slightly-incorrect file in a lossless manner + std::string type; + ifValueExists(obj, "type", [&](const auto& x){ type = x.GetString(); }); + if (!type.empty()) { + handle->SetTypeName(type); + } + } + + ifValueExists(obj, "propertyOrder", [&](const auto& x){ + pxr::TfTokenVector propertyOrder = extractTfTokenVector(x); + if (!propertyOrder.empty()) { + handle->SetPropertyOrder(propertyOrder); + } + }); + + ifValueExists(obj, "nameChildrenOrder", [&](const auto& x){ + pxr::TfTokenVector nameChildrenOrder = extractTfTokenVector(x); + if (!nameChildrenOrder.empty()) { + handle->SetNameChildrenOrder(nameChildrenOrder); + } + }); + + + // Similar to setting type at the end, set metadata at the end. + // Metadata can include API Schemas, which can e.g. make attributes + // be uniform when they weren't authored as such (technically out of spec + // with the API schema). See lossless-attr-collection-api.usda + ifValueExists(obj, "metadata", [&](const auto& x){ + readMetadata(x, handle); + }); +} + +void writePrim(pxr::JsObject& js, const pxr::SdfPrimSpecHandle& prim) { + js["name"] = pxr::JsValue(prim->GetName()); + if (prim->GetSpecType() != pxr::SdfSpecTypePseudoRoot) { + switch (prim->GetSpecifier()) { + case pxr::SdfSpecifierDef: + js["spec"] = pxr::JsValue("def"); + break; + case pxr::SdfSpecifierOver: + js["spec"] = pxr::JsValue("over"); + break; + case pxr::SdfSpecifierClass: + js["spec"] = pxr::JsValue("class"); + break; + case pxr::SdfNumSpecifiers: + MY_FATAL_CODING_ERROR("Prim '%s' has specifier SdfNumSpecifiers", prim->GetPath().GetText()); + break; + } + } + if (!prim->GetTypeName().IsEmpty()) { + js["type"] = pxr::JsValue(prim->GetTypeName().GetString()); + } + + writeMetadata(js, prim); + + // LIVERPS. Local is handled by GetAttributes, GetRelationships, and GetNameChildren + if (prim->GetSpecType() == pxr::SdfSpecTypePseudoRoot && prim->GetLayer()->GetNumSubLayerPaths() != 0) { + js["subLayers"] = writeSdfListProxy(prim->GetLayer()->GetSubLayerPaths(), writeString); + writeSubLayerOffsetsIfNeeded(js, prim->GetLayer()->GetSubLayerOffsets()); + } + if (prim->HasInheritPaths()) { + js["inherits"] = writeSdfListEditorProxy(prim->GetInheritPathList(), writeSdfPath); + } + if (prim->HasVariantSetNames()) { + js["variantSetNames"] = writeSdfListEditorProxy(prim->GetVariantSetNameList(), writeString); + } + writeVariantSelectionsIfNeeded(js, prim->GetVariantSelections()); + writeVariantSetsIfNeeded(js, prim->GetVariantSets()); + if (prim->HasRelocates()) { + js["relocates"] = writePrimRelocates(prim->GetRelocates()); + } + if (prim->GetSpecType() == pxr::SdfSpecTypePseudoRoot && prim->GetLayer()->HasRelocates()) { + js["relocates"] = writeLayerRelocates(prim->GetLayer()->GetRelocates()); + } + + if (prim->HasReferences()) { + js["references"] = writeSdfListEditorProxy(prim->GetReferenceList(), writeSdfReference); + } + if (prim->HasPayloads()) { + js["payloads"] = writeSdfListEditorProxy(prim->GetPayloadList(), writeSdfPayload); + } + if (prim->HasSpecializes()) { + js["specializes"] = writeSdfListEditorProxy(prim->GetSpecializesList(), writeSdfPath); + } + + pxr::JsArray attrs; + for (const auto& attr : prim->GetAttributes()) { + pxr::JsObject jsAttr; + writeAttribute(jsAttr, attr); + attrs.push_back(jsAttr); + } + if (!attrs.empty()) { + js["attributes"] = attrs; + } + + pxr::JsArray rels; + for (const auto& rel : prim->GetRelationships()) { + pxr::JsObject jsRel; + writeRelationship(jsRel, rel); + rels.push_back(jsRel); + } + if (!rels.empty()) { + js["relationships"] = rels; + } + + pxr::JsArray children; + for (const auto& child : prim->GetNameChildren()) { + pxr::JsObject jsChild; + writePrim(jsChild, child); + children.push_back(jsChild); + } + if (!children.empty()) { + js["children"] = children; + } + + if (prim->HasPropertyOrder()) { + js["propertyOrder"] = writeSdfListProxy(prim->GetPropertyOrder(), writeTfToken); + } + + if (prim->HasNameChildrenOrder()) { + js["nameChildrenOrder"] = writeSdfListProxy(prim->GetNameChildrenOrder(), writeTfToken); + } +} + +void readAttribute(const pxr::SdfLayerRefPtr& layer, const pxr::SdfPath& path, const pxr::JsValue& js) { + const pxr::JsObject& obj = js.GetJsObject(); + + // extractTypeHint might emit an error if there's an unknown type hint, + // but we know how to handle it. + pxr::TfErrorMark m; + TypedValue type = extractTypeHint(js); + m.Clear(); + + bool custom = false; + ifValueExists(obj, "custom", [&](const auto& x){ + custom = x.GetBool(); + }); + + pxr::SdfVariability variability = pxr::SdfVariabilityVarying; + ifValueExists(obj, "variability", [&](const auto& x){ + variability = static_cast(x.GetInt()); + }); + + pxr::SdfAttributeSpecHandle attrSpec = pxr::SdfCreatePrimAttributeInLayer(layer, path, type.valueTypeName, variability, custom); + if (!type.valueTypeName) { + // This could be PointIndex or PointIndex[], which we can't create a SdfValueTypeName for + attrSpec->SetField(pxr::SdfFieldKeys->TypeName, pxr::VtValue(pxr::TfToken(type.otherTypeName))); + } + + TypedValue defaultValue = type; + ifValueExists(obj, "default", [&](const auto& x){ + extractValueWithTypeHint(&defaultValue, x); + }); + + if (!defaultValue.value.IsEmpty()) { + if (!attrSpec->SetField(pxr::SdfFieldKeys->Default, defaultValue.value)) { + MY_RUNTIME_ERROR_AND_RETURN("Failed to set default value for attribute of '%s' at '%s'", attrSpec->GetTypeName().GetAsToken().GetText(), path.GetText()); + } + } + + ifValueExists(obj, "timesamples", [&](const auto& x){ + auto timeSamples = extractTimeCodeValueMapWithTypeHint(x, type); + for (const auto& it : timeSamples) { + attrSpec->SetTimeSample(it.first, it.second); + } + + if (timeSamples.size() == 0) { + // empty-timesamples.usda. If we encoded an empty time sample map, + // the above for loop will be empty, but we still want to set the TimeSamples field + attrSpec->SetField(pxr::SdfFieldKeys->TimeSamples, pxr::VtValue(pxr::SdfTimeSampleMap())); + + } + }); + + ifValueExists(obj, "connections", [&](const auto& x){ + extractSdfListEditorProxy(x, attrSpec->GetConnectionPathList(), extractSdfPath); + }); + + ifValueExists(obj, "spline", [&](const auto& x){ + attrSpec->SetSpline(extractTsSpline(x, type.valueTypeName)); + }); + + ifValueExists(obj, "displayUnit", [&](const auto& x){ + attrSpec->SetDisplayUnit(extractTfEnum(x)); + }); + + ifValueExists(obj, "metadata", [&](const auto& x){ + readMetadata(x, attrSpec); + }); +} + +void writeAttribute(pxr::JsObject& js, const pxr::SdfAttributeSpecHandle& attr) { + js["name"] = pxr::JsValue(attr->GetName()); + TypedValue type = TypedValue::forTypeName(attr->GetTypeName()); + js["type"] = writeTypeHint(type); + if (attr->IsCustom()) { + js["custom"] = pxr::JsValue(true); + } + js["variability"] = pxr::JsValue(attr->GetVariability()); + + type.value = attr->GetDefaultValue(); + if (!attr->GetDefaultValue().IsEmpty()) { + js["default"] = writeValueWithoutTypeHint(type); + } + + // Check if we have a field instead of GetNumTimeSamples() != 0 for + // empty-timesamples.usda + if (attr->HasField(pxr::SdfFieldKeys->TimeSamples)) { + js["timesamples"] = writeTimeCodeValueMapWithoutTypeHint(attr->GetTimeSampleMap(), type); + } + + if (attr->HasConnectionPaths()) { + js["connections"] = writeSdfListEditorProxy(attr->GetConnectionPathList(), writeSdfPath); + } + + if (attr->HasSpline()) { + js["spline"] = writeTsSpline(attr->GetSpline()); + } + + if (attr->HasDisplayUnit()) { + js["displayUnit"] = writeTfEnum(attr->GetDisplayUnit()); + } + + writeMetadata(js, attr); +} + +void readRelationship(const pxr::SdfLayerRefPtr& layer, const pxr::SdfPath& path, const pxr::JsValue& js) { + const pxr::JsObject& obj = js.GetJsObject(); + + bool custom = false; + ifValueExists(obj, "custom", [&](const auto& x){ + custom = x.GetBool(); + }); + + pxr::SdfVariability variability = pxr::SdfVariabilityVarying; + ifValueExists(obj, "variability", [&](const auto& x){ + variability = static_cast(x.GetInt()); + }); + + pxr::SdfRelationshipSpecHandle relSpec = pxr::SdfCreateRelationshipInLayer(layer, path, variability, custom); + if (!relSpec) { + MY_RUNTIME_ERROR_AND_RETURN("Failed to create relationship at '%s'", path.GetText()); + } + + ifValueExists(obj, "targets", [&](const auto& x){ + extractSdfListEditorProxy(x, relSpec->GetTargetPathList(), extractSdfPath); + }); + + ifValueExists(obj, "default", [&](const auto& x){ + TypedValue defaultValue = extractTypeHintAndValue(x); + relSpec->SetDefaultValue(defaultValue.value); + }); + + ifValueExists(obj, "metadata", [&](const auto& x){ + readMetadata(x, relSpec); + }); +} + +void writeRelationship(pxr::JsObject& js, const pxr::SdfRelationshipSpecHandle& rel) { + js["name"] = pxr::JsValue(rel->GetName()); + if (rel->IsCustom()) { + js["custom"] = pxr::JsValue(true); + } + const auto& targets = rel->GetTargetPathList(); + js["targets"] = writeSdfListEditorProxy(targets, writeSdfPath); + + js["variability"] = pxr::JsValue(rel->GetVariability()); + + if (rel->HasDefaultValue()) { + js["default"] = writeTypeHintAndValue(TypedValue::forVtValue(rel->GetDefaultValue())); + } + + writeMetadata(js, rel); +} + + + + diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/FundementalTypes.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/FundementalTypes.cpp new file mode 100644 index 0000000000..43241c70ee --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/FundementalTypes.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "FundementalTypes.hpp" + +bool ifValueExists(const pxr::JsObject& js, const std::string& key, std::function callback) { + const auto& it = js.find(key); + if (it != js.end()) { + callback(it->second); + return true; + } else { + return false; + } +} + +std::string extractString(const pxr::JsValue& x) { + return x.GetString(); +} +pxr::JsValue writeString(const std::string& x) { + return pxr::JsValue(x); +} + +long long extractLongLong(const pxr::JsValue& x) { + return x.GetInt64(); +} + +pxr::JsValue writeLongLong(long long x) { + return pxr::JsValue(x); +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/LIVERPSSerialization.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/LIVERPSSerialization.cpp new file mode 100644 index 0000000000..2065555a88 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/LIVERPSSerialization.cpp @@ -0,0 +1,227 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "LIVERPSSerialization.hpp" +#include "CoreSpecSerialization.hpp" +#include "Diagnostics.hpp" +#include "FundementalTypes.hpp" + + +pxr::SdfLayerOffset extractSdfLayerOffset(const pxr::JsValue& js) { + const pxr::JsArray& arr = js.GetJsArray(); + if (arr.size() != 2) { + MY_RUNTIME_ERROR_AND_RETURN("SdfLayerOffset should be 2-element array, had length %zu", arr.size()) pxr::SdfLayerOffset(); + } + + return pxr::SdfLayerOffset(arr[0].GetReal(), + arr[1].GetReal()); +} +pxr::JsValue writeSdfLayerOffset(const pxr::SdfLayerOffset& x) { + return pxr::JsArray({ + pxr::JsValue(x.GetOffset()), + pxr::JsValue(x.GetScale()) + }); +} + + +pxr::SdfLayerOffsetVector extractSdfLayerOffsetVector(const pxr::JsValue& js) { + pxr::SdfLayerOffsetVector result; + const pxr::JsArray& arr = js.GetJsArray(); + + for (const auto& x : arr) { + result.push_back(extractSdfLayerOffset(x)); + } + return result; +} +void writeSubLayerOffsetsIfNeeded(pxr::JsObject& js, const pxr::SdfLayerOffsetVector& offsets) { + pxr::JsArray result; + bool shouldWrite = false; + + for (const auto& x : offsets) { + shouldWrite = shouldWrite || !x.IsIdentity(); + result.push_back(writeSdfLayerOffset(x)); + } + + if (shouldWrite) { + js["subLayerOffsets"] = result; + } +} + +void extractPrimRelocates(const pxr::JsValue& js, const pxr::SdfPrimSpecHandle& prim) { + const pxr::JsObject& obj = js.GetJsObject(); + + pxr::SdfRelocatesMapProxy proxy = prim->GetRelocates(); + + ifValueExists(obj, "relocates", [&](const auto& x){ + for (const auto& it : x.GetJsObject()) { + proxy.insert({pxr::SdfPath(it.first), pxr::SdfPath(it.second.GetString())}); + } + if (x.GetJsObject().empty()) { + prim->SetField(pxr::SdfFieldKeys->Relocates, pxr::VtValue(pxr::SdfRelocatesMap())); + } + }); +} + +pxr::JsValue writePrimRelocates(const pxr::SdfRelocatesMapProxy& list) { + pxr::JsObject result; + for (const auto& it : list) { + result[it.first.GetString()] = pxr::JsValue(it.second.GetString()); + } + return result; +} + +void extractLayerRelocates(const pxr::SdfLayerRefPtr& layer, const pxr::JsValue& js) { + + const pxr::JsObject& obj = js.GetJsObject(); + + ifValueExists(obj, "relocates", [&](const auto& x){ + pxr::SdfRelocates relocates; + for (const auto& entry : x.GetJsArray()) { + const pxr::JsArray& subArr = entry.GetJsArray(); + MY_VERIFY(subArr.size() == 2, + "Layer relocates entry must be string-string pair"); + if (subArr.size() == 2) { + relocates.push_back({pxr::SdfPath(subArr[0].GetString()), pxr::SdfPath(subArr[1].GetString())}); + } + } + if (!relocates.empty()) { + layer->SetRelocates(relocates); + } + }); +} +pxr::JsValue writeLayerRelocates(const pxr::SdfRelocates& list) { + pxr::JsArray result; + for (const auto& it : list) { + result.push_back(pxr::JsArray({ + pxr::JsValue(it.first.GetString()), + pxr::JsValue(it.second.GetString()) + })); + } + return result; +} + +void extractVariantSelections(const pxr::SdfPrimSpecHandle& prim, const pxr::JsValue& js) { + for (const auto& it : js.GetJsObject()) { + prim->SetVariantSelection(it.first, it.second.GetString()); + } + + return; +} + +void writeVariantSelectionsIfNeeded(pxr::JsObject& js, const pxr::SdfVariantSelectionProxy& selections) { + if (!selections || selections.empty()) { return; } + + pxr::JsObject result; + + for (const auto& x : selections) { + result[x.first] = pxr::JsValue(x.second); + } + + js["variantSelections"] = result; +} + +void readVariantSets(const pxr::SdfLayerRefPtr& layer, const pxr::SdfPath& path, const pxr::JsValue& js) { + const pxr::JsArray& arr = js.GetJsArray(); + + const pxr::SdfPrimSpecHandle& prim = layer->GetPrimAtPath(path); + + for (const auto& variantSetSuperObjectElement : arr) { + const pxr::JsObject& variantSetSuperObject = variantSetSuperObjectElement.GetJsObject(); + + MY_VERIFY(variantSetSuperObject.size() == 2, + "Variant set super object must have size 2"); + std::string variantSetName; + try { + variantSetName = variantSetSuperObject.at("name").GetString(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("Variant set super object must have name key"); + } + + try { + const pxr::JsObject& jsVariantSet = variantSetSuperObject.at("contents").GetJsObject(); + + pxr::SdfVariantSetSpecHandle sdfVset; + auto it = prim->GetVariantSets().find(variantSetName); + if (it == prim->GetVariantSets().end()) { + sdfVset = pxr::SdfVariantSetSpec::New(prim, variantSetName); + } else { + sdfVset = it->second; + } + + readVariantSetSpec(jsVariantSet, sdfVset); + + } catch (const std::out_of_range&){ + MY_RUNTIME_ERROR_AND_RETURN("Variant set super object must have contents key"); + } + } + + return; +} + + +void writeVariantSetsIfNeeded(pxr::JsObject& js, const pxr::SdfVariantSetsProxy& sets) { + if (!sets || sets.empty()) { return; } + + pxr::JsArray result; + + for (const auto& x : sets) { + pxr::JsObject temp; + temp["name"] = pxr::JsValue(x.first); + temp["contents"] = writeVariantSetSpec(x.second); + result.push_back(temp); + } + + js["variantSets"] = result; +} + + +void readVariantSetSpec(const pxr::JsValue& js, const pxr::SdfVariantSetSpecHandle& variantSet) { + + const pxr::JsObject& jsVariantSet = js.GetJsObject(); + + for (const auto& it : jsVariantSet) { + const pxr::SdfVariantView& variantView = variantSet->GetVariants(); + pxr::SdfVariantSpecHandle vspecHandle; + if (variantView.find(it.first) == variantView.end()) { + // Important: Use variantSet->GetOwner()->GetPath() and not variantSet->GetPath().StripAllVariantSelections(), + // because the latter does not handle nested variant sets correctly but the former does. + pxr::SdfPath ownerPath = variantSet->GetOwner()->GetPath(); + vspecHandle = pxr::SdfCreateVariantInLayer(variantSet->GetLayer(), ownerPath, variantSet->GetName(), it.first); + } else { + vspecHandle = *variantView.find(it.first); + } + + + const pxr::JsObject& jsVspecPrimSpec = it.second.GetJsObject(); + readPrim(variantSet->GetLayer(), vspecHandle->GetPrimSpec(), jsVspecPrimSpec); + } +} + +pxr::JsValue writeVariantSetSpec(const pxr::SdfVariantSetSpecHandle& variantSet) { + pxr::JsObject result; + + for (const auto& variant : variantSet->GetVariants()) { + pxr::JsObject jsVariant; + writePrim(jsVariant, variant->GetPrimSpec()); + result[variant->GetName()] = jsVariant; + } + + return result; +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/SdfSerialization.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/SdfSerialization.cpp new file mode 100644 index 0000000000..44c54fcf98 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/SdfSerialization.cpp @@ -0,0 +1,169 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "SdfSerialization.hpp" +#include "Diagnostics.hpp" +#include "FundementalTypes.hpp" +#include "VtSerialization.hpp" +#include "pxr/usd/sdf/reference.h" +#include "pxr/usd/sdf/payload.h" + +pxr::SdfAnimationBlock extractSdfAnimationBlock(const pxr::JsValue& js) { + if (js == pxr::JsObject({ {"AnimationBlock", pxr::JsValue()} })) { + return pxr::SdfAnimationBlock(); + } + MY_RUNTIME_ERROR_AND_RETURN("SdfAnimationBlock deserialization error") pxr::SdfAnimationBlock(); +} +pxr::JsValue writeSdfAnimationBlock(const pxr::SdfAnimationBlock& x) { + return pxr::JsObject({ {"AnimationBlock", pxr::JsValue()} }); +} + +pxr::SdfPath extractSdfPath(const pxr::JsValue& x) { + return pxr::SdfPath(x.GetString()); +} +pxr::JsValue writeSdfPath(const pxr::SdfPath& x) { + return pxr::JsValue(x.GetString()); +} + +pxr::SdfUnregisteredValue extractSdfUnregisteredValue(const pxr::JsValue& js) { + const pxr::JsObject& obj = js.GetJsObject(); + + MY_VERIFY(obj.size() == 2, "SdfUnregisteredValue expects two keys"); + + std::string type; + try { + type = obj.at("type").GetString(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("SdfUnregisteredValue must have 'type' key") pxr::SdfUnregisteredValue(); + } + + try { + const pxr::JsValue& value = obj.at("SdfUnregisteredValue"); + + if (type == "string") { + return pxr::SdfUnregisteredValue(value.GetString()); + } else if (type == "VtDictionary") { + return pxr::SdfUnregisteredValue(extractVtDictionary(value)); + } else if (type == "SdfUnregisteredValueListOp") { + pxr::SdfUnregisteredValueListOp l = extractSdfListOp(value, extractSdfUnregisteredValue); + return pxr::SdfUnregisteredValue(l); + } else { + MY_RUNTIME_ERROR_AND_RETURN("Unknown type '%s' for SdfUnregisteredValue", type.c_str()) pxr::SdfUnregisteredValue(); + } + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("SdfUnregistered value must have 'SdfUnregisteredValue' key") pxr::SdfUnregisteredValue(); + } +} + +pxr::JsValue writeSdfUnregisteredValue(const pxr::SdfUnregisteredValue &value) { + pxr::JsObject result; + + if (value.GetValue().IsHolding()) { + std::string contents = value.GetValue().Get(); + result["SdfUnregisteredValue"] = pxr::JsValue(contents); + result["type"] = pxr::JsValue("string"); + return result; + } else if (value.GetValue().IsHolding()) { + pxr::VtDictionary contents = value.GetValue().Get(); + result["SdfUnregisteredValue"] = writeVtDictionary(contents); + result["type"] = pxr::JsValue("VtDictionary"); + return result; + } else if (value.GetValue().IsHolding()) { + pxr::SdfUnregisteredValueListOp contents = value.GetValue().Get(); + result["SdfUnregisteredValue"] = writeSdfListOp(contents, writeSdfUnregisteredValue); + result["type"] = pxr::JsValue("SdfUnregisteredValueListOp"); + return result; + } else { + MY_WARN("Unknown contents of SdfUnregisteredValue"); + } + return result; +} + +pxr::SdfReference extractSdfReference(const pxr::JsValue& js) { + const pxr::JsObject& obj = js.GetJsObject(); + pxr::SdfReference result; + + ifValueExists(obj, "asset", [&](const auto& x){ + result.SetAssetPath(x.GetString()); + }); + ifValueExists(obj, "prim", [&](const auto& x){ + result.SetPrimPath(extractSdfPath(x)); + }); + ifValueExists(obj, "offset", [&](const auto& x){ + result.SetLayerOffset(extractSdfLayerOffset(x)); + }); + ifValueExists(obj, "customData", [&](const auto& x){ + result.SetCustomData(extractVtDictionary(x)); + }); + + return result; +} + +pxr::JsValue writeSdfReference(const pxr::SdfReference& reference) { + pxr::JsObject result; + + if (!reference.GetAssetPath().empty()) { + result["asset"] = pxr::JsValue(reference.GetAssetPath()); + } + if (!reference.GetPrimPath().IsEmpty()) { + result["prim"] = writeSdfPath(reference.GetPrimPath()); + } + if (!reference.GetLayerOffset().IsIdentity()) { + result["offset"] = writeSdfLayerOffset(reference.GetLayerOffset()); + } + if (!reference.GetCustomData().empty()) { + result["customData"] = writeVtDictionary(reference.GetCustomData()); + } + + return result; +} + +pxr::SdfPayload extractSdfPayload(const pxr::JsValue& js) { + const pxr::JsObject& obj = js.GetJsObject(); + pxr::SdfPayload result; + + ifValueExists(obj, "asset", [&](const auto& x){ + result.SetAssetPath(x.GetString()); + }); + ifValueExists(obj, "prim", [&](const auto& x){ + result.SetPrimPath(extractSdfPath(x)); + }); + ifValueExists(obj, "offset", [&](const auto& x){ + result.SetLayerOffset(extractSdfLayerOffset(x)); + }); + + return result; +} + +pxr::JsValue writeSdfPayload(const pxr::SdfPayload& payload) { + pxr::JsObject result; + + if (!payload.GetAssetPath().empty()) { + result["asset"] = pxr::JsValue(payload.GetAssetPath()); + } + if (!payload.GetPrimPath().IsEmpty()) { + result["prim"] = writeSdfPath(payload.GetPrimPath()); + } + if (!payload.GetLayerOffset().IsIdentity()) { + result["offset"] = writeSdfLayerOffset(payload.GetLayerOffset()); + } + + return result; +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/TfSerialization.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/TfSerialization.cpp new file mode 100644 index 0000000000..4a01d601bf --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/TfSerialization.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "TfSerialization.hpp" + +pxr::TfToken extractTfToken(const pxr::JsValue& x) { + return pxr::TfToken(x.GetString()); +} + +pxr::JsValue writeTfToken(const pxr::TfToken& x) { + return pxr::JsValue(x.GetString()); +} + +pxr::TfTokenVector extractTfTokenVector(const pxr::JsValue& js) { + pxr::TfTokenVector result; + const pxr::JsArray& arr = js.GetJsArray(); + for (const auto& x : arr) { + result.push_back(extractTfToken(x)); + } + return result; +} + + +pxr::TfEnum extractTfEnum(const pxr::JsValue& js) { + return pxr::TfEnum::GetValueFromFullName(js.GetString()); +} +pxr::JsValue writeTfEnum(const pxr::TfEnum& x) { + return pxr::JsValue(pxr::TfEnum::GetFullName(x)); +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/TsSerialization.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/TsSerialization.cpp new file mode 100644 index 0000000000..a7116559db --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/TsSerialization.cpp @@ -0,0 +1,302 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "TsSerialization.hpp" +#include "Diagnostics.hpp" +#include "VtSerialization.hpp" +#include "FundementalTypes.hpp" + +pxr::TsSpline extractTsSpline(const pxr::JsValue& js, const pxr::SdfValueTypeName& type) { + + pxr::TsSpline result = pxr::TsSpline(type.GetType()); + const pxr::JsObject& obj = js.GetJsObject(); + + int curveType; + try { + curveType = obj.at("curveType").GetInt(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsSpline requires curveType key") pxr::TsSpline(); + } + result.SetCurveType(static_cast(curveType)); + + try { + pxr::TsExtrapolation preExtrapolation = extractTsExtrapolation(obj.at("preExtrapolation")); + result.SetPreExtrapolation(preExtrapolation); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsSpline requires preExtrapolation key") pxr::TsSpline(); + } + + try { + pxr::TsExtrapolation postExtrapolation = extractTsExtrapolation(obj.at("postExtrapolation")); + result.SetPostExtrapolation(postExtrapolation); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsSpline requires postExtrapolation key") pxr::TsSpline(); + } + + try { + pxr::TsLoopParams loopParams = extractTsLoopParams(obj.at("innerLoopParams")); + result.SetInnerLoopParams(loopParams); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsSpline requires innerLoopParams key") pxr::TsSpline(); + } + + + try { + pxr::TsKnotMap knots = extractTsKnotMap(obj.at("knots"), type); + if (!knots.empty()) { + // TsSpline::SetKnots checks if the spline's type matches the knot map's type. + // However, empty knot maps return the unknown type, so the comparison erronously fails. + // Arguably, TsSpline::SetKnots shouldn't report an error in this case, but we can + // just not set the knots with empty knot maps. + result.SetKnots(knots); + } + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsSpline requires knots key") pxr::TsSpline(); + } + + return result; +} +pxr::JsValue writeTsSpline(const pxr::TsSpline& x) { + pxr::JsObject result; + + result["curveType"] = pxr::JsValue(x.GetCurveType()); + result["preExtrapolation"] = writeTsExtrapolation(x.GetPreExtrapolation()); + result["postExtrapolation"] = writeTsExtrapolation(x.GetPostExtrapolation()); + result["innerLoopParams"] = writeTsLoopParams(x.GetInnerLoopParams()); + result["knots"] = writeTsKnotMap(x.GetKnots()); + + return result; +} + +pxr::TsExtrapolation extractTsExtrapolation(const pxr::JsValue& js) { + pxr::TsExtrapolation result; + const pxr::JsObject& obj = js.GetJsObject(); + + try { + int mode = obj.at("mode").GetInt(); + result.mode = static_cast(mode); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsExtrapolation mode") pxr::TsExtrapolation(); + } + + try { + double slope = obj.at("slope").GetReal(); + result.slope = slope; + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsExtrapolation slope") pxr::TsExtrapolation(); + } + + result.loopBoundaryTime = std::nullopt; + ifValueExists(obj, "loopBoundaryTime", [&](const auto& x){ + result.loopBoundaryTime = x.GetReal(); + }); + + + return result; +} +pxr::JsValue writeTsExtrapolation(const pxr::TsExtrapolation& x) { + pxr::JsObject result; + + result["mode"] = pxr::JsValue(x.mode); + result["slope"] = pxr::JsValue(x.slope); + if (x.loopBoundaryTime.has_value()) { + result["loopBoundaryTime"] = pxr::JsValue(*x.loopBoundaryTime); + } + + return result; +} + +pxr::TsLoopParams extractTsLoopParams(const pxr::JsValue& js) { + pxr::TsLoopParams result; + const pxr::JsObject& obj = js.GetJsObject(); + try { + result.protoStart = obj.at("protoStart").GetReal(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsLoopParams protoStart") pxr::TsLoopParams(); + } + try { + result.protoEnd = obj.at("protoEnd").GetReal(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsLoopParams protoEnd") pxr::TsLoopParams(); + } + try { + result.numPreLoops = obj.at("numPreLoops").GetInt(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsLoopParams numPreLoops") pxr::TsLoopParams(); + } + try { + result.numPostLoops = obj.at("numPostLoops").GetInt(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsLoopParams numPostLoops") pxr::TsLoopParams(); + } + try { + result.valueOffset = obj.at("valueOffset").GetReal(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsLoopParams valueOffset") pxr::TsLoopParams(); + } + + return result; +} + +pxr::JsValue writeTsLoopParams(const pxr::TsLoopParams& x) { + pxr::JsObject result; + + result["protoStart"] = pxr::JsValue(x.protoStart); + result["protoEnd"] = pxr::JsValue(x.protoEnd); + result["numPreLoops"] = pxr::JsValue(x.numPreLoops); + result["numPostLoops"] = pxr::JsValue(x.numPostLoops); + result["valueOffset"] = pxr::JsValue(x.valueOffset); + + return result; +} + +pxr::TsKnotMap extractTsKnotMap(const pxr::JsValue& js, const pxr::SdfValueTypeName& type) { + pxr::TsKnotMap result; + const pxr::JsArray& arr = js.GetJsArray(); + + for (const auto& it : arr) { + result.insert(extractTsKnot(it, type)); + } + return result; +} +pxr::JsValue writeTsKnotMap(const pxr::TsKnotMap& x) { + pxr::JsArray arr; + for (const auto& it : x) { + arr.push_back(writeTsKnot(it)); + } + return arr; +} + +pxr::TsKnot extractTsKnot(const pxr::JsValue& js, const pxr::SdfValueTypeName& type) { + pxr::TsKnot result = pxr::TsKnot(type.GetType()); + const pxr::JsObject& obj = js.GetJsObject(); + + try { + result.SetTime(obj.at("time").GetReal()); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsKnot time") pxr::TsKnot(); + } + + try { + int nextInterpolation = obj.at("nextInterpolation").GetInt(); + result.SetNextInterpolation(static_cast(nextInterpolation)); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsKnot nextInterpolation") pxr::TsKnot(); + } + + TypedValue value = TypedValue::forTypeName(type); + try { + extractValueWithTypeHint(&value, obj.at("value")); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsKnot value") pxr::TsKnot(); + } + result.SetValue(value.value); + + ifValueExists(obj, "preValue", [&](const auto& x){ + TypedValue preValue = TypedValue::forTypeName(type); + extractValueWithTypeHint(&preValue, x); + result.SetPreValue(preValue.value); + }); + + try { + result.SetPreTanWidth(obj.at("preTanWidth").GetReal()); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsKnot preTanWidth") pxr::TsKnot(); + } + + + TypedValue preTanSlope = TypedValue::forTypeName(type); + try { + extractValueWithTypeHint(&preTanSlope, obj.at("preTanSlope")); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsKnot preTanSlope") pxr::TsKnot(); + } + result.SetPreTanSlope(preTanSlope.value); + + try { + int preTanAlgorithm = obj.at("preTanAlgorithm").GetInt(); + result.SetPreTanAlgorithm(static_cast(preTanAlgorithm)); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsKnot preTanAlgorithm") pxr::TsKnot(); + } + + try { + pxr::TsTime postTanWidth = obj.at("postTanWidth").GetReal(); + result.SetPostTanWidth(postTanWidth); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsKnot postTanWidth") pxr::TsKnot(); + } + + TypedValue postTanSlope = TypedValue::forTypeName(type); + try { + extractValueWithTypeHint(&postTanSlope, obj.at("postTanSlope")); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsKnot postTanSlope") pxr::TsKnot(); + } + result.SetPostTanSlope(postTanSlope.value); + + try { + int postTanAlgorithm = obj.at("postTanAlgorithm").GetInt(); + result.SetPostTanAlgorithm(static_cast(postTanAlgorithm)); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("TsKnot postTanAlgorithm") pxr::TsKnot(); + } + + ifValueExists(obj, "customData", [&](const auto& x){ + result.SetCustomData(extractVtDictionary(x)); + }); + + return result; +} +pxr::JsValue writeTsKnot(const pxr::TsKnot& x) { + pxr::JsObject result; + + result["time"] = pxr::JsValue(x.GetTime()); + result["nextInterpolation"] = pxr::JsValue(x.GetNextInterpolation()); + + pxr::VtValue value; + x.GetValue(&value); + result["value"] = writeValueWithoutTypeHint(TypedValue::forVtValue(value)); + + if (x.IsDualValued()) { + pxr::VtValue pre; + x.GetPreValue(&pre); + result["preValue"] = writeValueWithoutTypeHint(TypedValue::forVtValue(pre)); + } + result["preTanWidth"] = pxr::JsValue(x.GetPreTanWidth()); + + pxr::VtValue preTanSlope; + x.GetPreTanSlope(&preTanSlope); + result["preTanSlope"] = writeValueWithoutTypeHint(TypedValue::forVtValue(preTanSlope)); + + result["preTanAlgorithm"] = pxr::JsValue(x.GetPreTanAlgorithm()); + + result["postTanWidth"] = pxr::JsValue(x.GetPostTanWidth()); + + pxr::VtValue postTanSlope; + x.GetPostTanSlope(&postTanSlope); + result["postTanSlope"] = writeValueWithoutTypeHint(TypedValue::forVtValue(postTanSlope)); + + result["postTanAlgorithm"] = pxr::JsValue(x.GetPostTanAlgorithm()); + + result["customData"] = writeVtDictionary(x.GetCustomData()); + + return result; +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/VtSerialization.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/VtSerialization.cpp new file mode 100644 index 0000000000..328458423c --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/VtSerialization.cpp @@ -0,0 +1,951 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include +#include "pxr/usd/sdf/types.h" +#include "pxr/base/js/value.h" +#include "pxr/base/tf/errorMark.h" +#include "VtSerialization.hpp" +#include "Diagnostics.hpp" +#include "FundementalTypes.hpp" +#include "SdfSerialization.hpp" +#include "LIVERPSSerialization.hpp" +#include "TfSerialization.hpp" + +TypedValue TypedValue::forVtValue(pxr::VtValue v) { + TypedValue result; + result.value = v; + result.valueTypeName = pxr::SdfGetValueTypeNameForValue(v); + result.otherTypeName = v.GetTypeName(); + return result; +} + +TypedValue TypedValue::forTypeName(pxr::SdfValueTypeName x) { + TypedValue result; + result.value = pxr::VtValue(); + result.valueTypeName = x; + result.otherTypeName = ""; + return result; +} + +TypedValue TypedValue::withOtherTypeName(std::string s) { + TypedValue result; + result.value = pxr::VtValue(); + result.valueTypeName = pxr::SdfValueTypeName(); + result.otherTypeName = s; + return result; +} + + +pxr::VtDictionary extractVtDictionary(const pxr::JsValue& js) { + pxr::VtDictionary result; + + for (const auto& it : js.GetJsObject()) { + TypedValue x = extractTypeHintAndValue(it.second); + result.insert({it.first, x.value}); + } + + return result; +} +pxr::JsValue writeVtDictionary(const pxr::VtDictionary& x) { + pxr::JsObject result; + for (const auto& it : x) { + TypedValue v = TypedValue::forVtValue(it.second); + result[it.first] = writeTypeHintAndValue(v); + } + return result; +} + +TypedValue extractTypeHint(const pxr::JsValue &js) { + const pxr::JsObject& obj = js.GetJsObject(); + + std::string s; + try { + s = obj.at("type").GetString(); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("extractTypeHint requires type key") TypedValue(); + } + +#define EXTRACT_TYPE_HINT(TYPE_STRING) \ + else if (s == #TYPE_STRING) { return TypedValue::forTypeName(pxr::SdfValueTypeNames->TYPE_STRING); } + + // Taken from `class Sdf_ValueTypeNamesType` in OpenUSD/pxr/usd/sdf/types.h + + if (false) {} + EXTRACT_TYPE_HINT(Bool) + EXTRACT_TYPE_HINT(UChar) + EXTRACT_TYPE_HINT(Int) + EXTRACT_TYPE_HINT(UInt) + EXTRACT_TYPE_HINT(Int64) + EXTRACT_TYPE_HINT(UInt64) + EXTRACT_TYPE_HINT(Half) + EXTRACT_TYPE_HINT(Float) + EXTRACT_TYPE_HINT(Double) + EXTRACT_TYPE_HINT(TimeCode) + EXTRACT_TYPE_HINT(String) + EXTRACT_TYPE_HINT(Token) + EXTRACT_TYPE_HINT(Asset) + EXTRACT_TYPE_HINT(Int2) + EXTRACT_TYPE_HINT(Int3) + EXTRACT_TYPE_HINT(Int4) + EXTRACT_TYPE_HINT(Half2) + EXTRACT_TYPE_HINT(Half3) + EXTRACT_TYPE_HINT(Half4) + EXTRACT_TYPE_HINT(Float2) + EXTRACT_TYPE_HINT(Float3) + EXTRACT_TYPE_HINT(Float4) + EXTRACT_TYPE_HINT(Double2) + EXTRACT_TYPE_HINT(Double3) + EXTRACT_TYPE_HINT(Double4) + EXTRACT_TYPE_HINT(Point3h) + EXTRACT_TYPE_HINT(Point3f) + EXTRACT_TYPE_HINT(Point3d) + EXTRACT_TYPE_HINT(Vector3h) + EXTRACT_TYPE_HINT(Vector3f) + EXTRACT_TYPE_HINT(Vector3d) + EXTRACT_TYPE_HINT(Normal3h) + EXTRACT_TYPE_HINT(Normal3f) + EXTRACT_TYPE_HINT(Normal3d) + EXTRACT_TYPE_HINT(Color3h) + EXTRACT_TYPE_HINT(Color3f) + EXTRACT_TYPE_HINT(Color3d) + EXTRACT_TYPE_HINT(Color4h) + EXTRACT_TYPE_HINT(Color4f) + EXTRACT_TYPE_HINT(Color4d) + EXTRACT_TYPE_HINT(Quath) + EXTRACT_TYPE_HINT(Quatf) + EXTRACT_TYPE_HINT(Quatd) + EXTRACT_TYPE_HINT(Matrix2d) + EXTRACT_TYPE_HINT(Matrix3d) + EXTRACT_TYPE_HINT(Matrix4d) + EXTRACT_TYPE_HINT(Frame4d) + EXTRACT_TYPE_HINT(TexCoord2h) + EXTRACT_TYPE_HINT(TexCoord2f) + EXTRACT_TYPE_HINT(TexCoord2d) + EXTRACT_TYPE_HINT(TexCoord3h) + EXTRACT_TYPE_HINT(TexCoord3f) + EXTRACT_TYPE_HINT(TexCoord3d) + EXTRACT_TYPE_HINT(Opaque) + EXTRACT_TYPE_HINT(Group) + EXTRACT_TYPE_HINT(PathExpression) + EXTRACT_TYPE_HINT(BoolArray) + EXTRACT_TYPE_HINT(UCharArray) + EXTRACT_TYPE_HINT(IntArray) + EXTRACT_TYPE_HINT(UIntArray) + EXTRACT_TYPE_HINT(Int64Array) + EXTRACT_TYPE_HINT(UInt64Array) + EXTRACT_TYPE_HINT(HalfArray) + EXTRACT_TYPE_HINT(FloatArray) + EXTRACT_TYPE_HINT(DoubleArray) + EXTRACT_TYPE_HINT(TimeCodeArray) + EXTRACT_TYPE_HINT(StringArray) + EXTRACT_TYPE_HINT(TokenArray) + EXTRACT_TYPE_HINT(AssetArray) + EXTRACT_TYPE_HINT(Int2Array) + EXTRACT_TYPE_HINT(Int3Array) + EXTRACT_TYPE_HINT(Int4Array) + EXTRACT_TYPE_HINT(Half2Array) + EXTRACT_TYPE_HINT(Half3Array) + EXTRACT_TYPE_HINT(Half4Array) + EXTRACT_TYPE_HINT(Float2Array) + EXTRACT_TYPE_HINT(Float3Array) + EXTRACT_TYPE_HINT(Float4Array) + EXTRACT_TYPE_HINT(Double2Array) + EXTRACT_TYPE_HINT(Double3Array) + EXTRACT_TYPE_HINT(Double4Array) + EXTRACT_TYPE_HINT(Point3hArray) + EXTRACT_TYPE_HINT(Point3fArray) + EXTRACT_TYPE_HINT(Point3dArray) + EXTRACT_TYPE_HINT(Vector3hArray) + EXTRACT_TYPE_HINT(Vector3fArray) + EXTRACT_TYPE_HINT(Vector3dArray) + EXTRACT_TYPE_HINT(Normal3hArray) + EXTRACT_TYPE_HINT(Normal3fArray) + EXTRACT_TYPE_HINT(Normal3dArray) + EXTRACT_TYPE_HINT(Color3hArray) + EXTRACT_TYPE_HINT(Color3fArray) + EXTRACT_TYPE_HINT(Color3dArray) + EXTRACT_TYPE_HINT(Color4hArray) + EXTRACT_TYPE_HINT(Color4fArray) + EXTRACT_TYPE_HINT(Color4dArray) + EXTRACT_TYPE_HINT(QuathArray) + EXTRACT_TYPE_HINT(QuatfArray) + EXTRACT_TYPE_HINT(QuatdArray) + EXTRACT_TYPE_HINT(Matrix2dArray) + EXTRACT_TYPE_HINT(Matrix3dArray) + EXTRACT_TYPE_HINT(Matrix4dArray) + EXTRACT_TYPE_HINT(Frame4dArray) + EXTRACT_TYPE_HINT(TexCoord2hArray) + EXTRACT_TYPE_HINT(TexCoord2fArray) + EXTRACT_TYPE_HINT(TexCoord2dArray) + EXTRACT_TYPE_HINT(TexCoord3hArray) + EXTRACT_TYPE_HINT(TexCoord3fArray) + EXTRACT_TYPE_HINT(TexCoord3dArray) + EXTRACT_TYPE_HINT(PathExpressionArray) + #undef EXTRACT_TYPE_HINT + else if (s == "SdfListOp") { return TypedValue::withOtherTypeName(s); } + else if (s == "SdfListOp") { return TypedValue::withOtherTypeName(s); } + else if (s == "SdfListOp") { return TypedValue::withOtherTypeName(s); } + else if (s == "VtDictionary") { return TypedValue::withOtherTypeName(s); } + else if (s == "SdfUnregisteredValue") { return TypedValue::withOtherTypeName(s); } + else if (s == "PointIndex" || s == "PointIndex[]") { return TypedValue::withOtherTypeName(s); } + else if (s == "SdfPermission") { return TypedValue::withOtherTypeName(s); } + else if (s == "SdfPath") { return TypedValue::withOtherTypeName(s); } + else if (!s.empty()) { + // Important: Lots of code depends on extractTypeHint, and the vast majority of it + // doesn't know how to handle unknown type hints. Emit an error that could be caught + // by TfErrorMark and return a valid TypedValue, so that sophisticated callers can + // handle this case if they want, while simpler callers can simply error out + + MY_RUNTIME_ERROR("Deserializing unknown type hint '%s'", s.c_str()); + return TypedValue::withOtherTypeName(s); + } else { + MY_RUNTIME_ERROR_AND_RETURN("Unknown type hint '%s'", s.c_str()) TypedValue(); + } +} + +pxr::JsValue writeTypeHint(const TypedValue& value) { + #define WRITE_TYPE_HINT(TYPE_STRING) \ + else if (value.valueTypeName == pxr::SdfValueTypeNames->TYPE_STRING) {\ + return pxr::JsValue(#TYPE_STRING); } + + if (false) {} + WRITE_TYPE_HINT(Bool) + WRITE_TYPE_HINT(UChar) + WRITE_TYPE_HINT(Int) + WRITE_TYPE_HINT(UInt) + WRITE_TYPE_HINT(Int64) + WRITE_TYPE_HINT(UInt64) + WRITE_TYPE_HINT(Half) + WRITE_TYPE_HINT(Float) + WRITE_TYPE_HINT(Double) + WRITE_TYPE_HINT(TimeCode) + WRITE_TYPE_HINT(String) + WRITE_TYPE_HINT(Token) + WRITE_TYPE_HINT(Asset) + WRITE_TYPE_HINT(Int2) + WRITE_TYPE_HINT(Int3) + WRITE_TYPE_HINT(Int4) + WRITE_TYPE_HINT(Half2) + WRITE_TYPE_HINT(Half3) + WRITE_TYPE_HINT(Half4) + WRITE_TYPE_HINT(Float2) + WRITE_TYPE_HINT(Float3) + WRITE_TYPE_HINT(Float4) + WRITE_TYPE_HINT(Double2) + WRITE_TYPE_HINT(Double3) + WRITE_TYPE_HINT(Double4) + WRITE_TYPE_HINT(Point3h) + WRITE_TYPE_HINT(Point3f) + WRITE_TYPE_HINT(Point3d) + WRITE_TYPE_HINT(Vector3h) + WRITE_TYPE_HINT(Vector3f) + WRITE_TYPE_HINT(Vector3d) + WRITE_TYPE_HINT(Normal3h) + WRITE_TYPE_HINT(Normal3f) + WRITE_TYPE_HINT(Normal3d) + WRITE_TYPE_HINT(Color3h) + WRITE_TYPE_HINT(Color3f) + WRITE_TYPE_HINT(Color3d) + WRITE_TYPE_HINT(Color4h) + WRITE_TYPE_HINT(Color4f) + WRITE_TYPE_HINT(Color4d) + WRITE_TYPE_HINT(Quath) + WRITE_TYPE_HINT(Quatf) + WRITE_TYPE_HINT(Quatd) + WRITE_TYPE_HINT(Matrix2d) + WRITE_TYPE_HINT(Matrix3d) + WRITE_TYPE_HINT(Matrix4d) + WRITE_TYPE_HINT(Frame4d) + WRITE_TYPE_HINT(TexCoord2h) + WRITE_TYPE_HINT(TexCoord2f) + WRITE_TYPE_HINT(TexCoord2d) + WRITE_TYPE_HINT(TexCoord3h) + WRITE_TYPE_HINT(TexCoord3f) + WRITE_TYPE_HINT(TexCoord3d) + WRITE_TYPE_HINT(Opaque) + WRITE_TYPE_HINT(Group) + WRITE_TYPE_HINT(PathExpression) + WRITE_TYPE_HINT(BoolArray) + WRITE_TYPE_HINT(UCharArray) + WRITE_TYPE_HINT(IntArray) + WRITE_TYPE_HINT(UIntArray) + WRITE_TYPE_HINT(Int64Array) + WRITE_TYPE_HINT(UInt64Array) + WRITE_TYPE_HINT(HalfArray) + WRITE_TYPE_HINT(FloatArray) + WRITE_TYPE_HINT(DoubleArray) + WRITE_TYPE_HINT(TimeCodeArray) + WRITE_TYPE_HINT(StringArray) + WRITE_TYPE_HINT(TokenArray) + WRITE_TYPE_HINT(AssetArray) + WRITE_TYPE_HINT(Int2Array) + WRITE_TYPE_HINT(Int3Array) + WRITE_TYPE_HINT(Int4Array) + WRITE_TYPE_HINT(Half2Array) + WRITE_TYPE_HINT(Half3Array) + WRITE_TYPE_HINT(Half4Array) + WRITE_TYPE_HINT(Float2Array) + WRITE_TYPE_HINT(Float3Array) + WRITE_TYPE_HINT(Float4Array) + WRITE_TYPE_HINT(Double2Array) + WRITE_TYPE_HINT(Double3Array) + WRITE_TYPE_HINT(Double4Array) + WRITE_TYPE_HINT(Point3hArray) + WRITE_TYPE_HINT(Point3fArray) + WRITE_TYPE_HINT(Point3dArray) + WRITE_TYPE_HINT(Vector3hArray) + WRITE_TYPE_HINT(Vector3fArray) + WRITE_TYPE_HINT(Vector3dArray) + WRITE_TYPE_HINT(Normal3hArray) + WRITE_TYPE_HINT(Normal3fArray) + WRITE_TYPE_HINT(Normal3dArray) + WRITE_TYPE_HINT(Color3hArray) + WRITE_TYPE_HINT(Color3fArray) + WRITE_TYPE_HINT(Color3dArray) + WRITE_TYPE_HINT(Color4hArray) + WRITE_TYPE_HINT(Color4fArray) + WRITE_TYPE_HINT(Color4dArray) + WRITE_TYPE_HINT(QuathArray) + WRITE_TYPE_HINT(QuatfArray) + WRITE_TYPE_HINT(QuatdArray) + WRITE_TYPE_HINT(Matrix2dArray) + WRITE_TYPE_HINT(Matrix3dArray) + WRITE_TYPE_HINT(Matrix4dArray) + WRITE_TYPE_HINT(Frame4dArray) + WRITE_TYPE_HINT(TexCoord2hArray) + WRITE_TYPE_HINT(TexCoord2fArray) + WRITE_TYPE_HINT(TexCoord2dArray) + WRITE_TYPE_HINT(TexCoord3hArray) + WRITE_TYPE_HINT(TexCoord3fArray) + WRITE_TYPE_HINT(TexCoord3dArray) + WRITE_TYPE_HINT(PathExpressionArray) + #undef WRITE_TYPE_HINT + else if (value.valueTypeName.GetAsToken() == pxr::SdfValueRoleNames->PointIndex) { + return pxr::JsValue(pxr::SdfValueRoleNames->PointIndex.GetString()); + } else if (value.valueTypeName.GetScalarType().GetAsToken() == pxr::SdfValueRoleNames->PointIndex) { + return pxr::JsValue(pxr::SdfValueRoleNames->PointIndex.GetString() + "[]"); + + } else if (value.otherTypeName.empty() && !value.valueTypeName.GetAsToken().IsEmpty()) { + // Important: Some type names may be invalid but should still round-trip. + // See extent-wrong-type-name.usda + return pxr::JsValue(value.valueTypeName.GetAsToken().GetString()); + } + else { + return pxr::JsValue(value.otherTypeName); + } +} + +template +void _extractGfVec(TypedValue* out, const pxr::JsValue& js) { + const pxr::JsArray& arr = js.GetJsArray(); + if (arr.size() != T::dimension) { + MY_VERIFY(arr.size() == T::dimension, + "Decoding type failure (%s)", out->valueTypeName.GetAsToken().GetText()); + return; + } + + T v; + for (size_t i = 0; i < arr.size(); i++) { + if constexpr (std::is_same_v) { + v[i] = arr[i].GetInt(); + } else { + v[i] = arr[i].GetReal(); + } + } + out->value = pxr::VtValue(v); +} + +template +void _extractGfMatrixd(TypedValue* out, const pxr::JsValue& js) { + const pxr::JsArray& arr = js.GetJsArray(); + if (arr.size() != T::numRows * T::numColumns) { + MY_VERIFY(arr.size() == T::numRows * T::numColumns, + "Decoding type failure (%s)", out->valueTypeName.GetAsToken().GetText()); + return; + } + + T m; + for (size_t i = 0; i < arr.size(); i++) { + m[i / T::numRows][i % T::numRows] = arr[i].GetReal(); + } + out->value = pxr::VtValue(m); +} + +template +void _extractArray(TypedValue* out, const pxr::JsValue& js) { + T decoded; + for (const auto& x : js.GetJsArray()) { + TypedValue temp = TypedValue::forTypeName(out->valueTypeName.GetScalarType()); + extractValueWithTypeHint(&temp, x); + decoded.push_back(temp.value.Get()); + } + out->value = pxr::VtValue(decoded); +} + +void extractValueWithTypeHint(TypedValue* out, const pxr::JsValue& js) { + if (js.IsNull()) { + out->value = pxr::VtValue(pxr::SdfValueBlock()); + return; + } + + // Speculatively try to decode SdfUnregisteredValue + { + pxr::TfErrorMark m; + out->value = pxr::VtValue(extractSdfUnregisteredValue(js)); + if (m.IsClean()) { + return; + } else { + m.Clear(); + } + } + + // Speculatively try to decode SdfAnimationBlock + { + pxr::TfErrorMark m; + out->value = pxr::VtValue(extractSdfAnimationBlock(js)); + if (m.IsClean()) { + return; + } else { + m.Clear(); + } + } + + + if (out->valueTypeName == pxr::SdfValueTypeNames->Bool) { + bool x = js.GetBool(); + out->value = pxr::VtValue(x); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->UChar) { + int x = js.GetInt(); + out->value = pxr::VtValue(static_cast(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Int) { + int x = js.GetInt(); + out->value = pxr::VtValue(static_cast(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->UInt) { + uint64_t x = js.GetUInt64(); + out->value = pxr::VtValue(static_cast(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Int64) { + int64_t x = js.GetInt64(); + out->value = pxr::VtValue(static_cast(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->UInt64) { + uint64_t x = js.GetUInt64(); + out->value = pxr::VtValue(static_cast(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Half) { + double x = js.GetReal(); + out->value = pxr::VtValue(pxr::GfHalf(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Float) { + double x = js.GetReal(); + out->value = pxr::VtValue(static_cast(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Double) { + double x = js.GetReal(); + out->value = pxr::VtValue(static_cast(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->TimeCode) { + double x = js.GetReal(); + out->value = pxr::VtValue(pxr::GfTimeCode(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->String) { + std::string x = js.GetString(); + out->value = pxr::VtValue(x); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Token) { + std::string x = js.GetString(); + out->value = pxr::VtValue(pxr::TfToken(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Asset) { + std::string x = js.GetString(); + out->value = pxr::VtValue(pxr::SdfAssetPath(x)); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Int2) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Int3) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Int4) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Half2) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Half3) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Half4) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Float2) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Float3) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Float4) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Double2) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Double3) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Double4) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Point3h) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Point3f) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Point3d) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Vector3h) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Vector3f) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Vector3d) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Normal3h) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Normal3f) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Normal3d) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Color3h) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Color3f) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Color3d) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Color4h) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Color4f) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Color4d) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Quath) { + TypedValue v; + _extractGfVec(&v, js); + out->value = pxr::VtValue(pxr::GfQuath(v.value.Get()[0], + v.value.Get()[1], + v.value.Get()[2], + v.value.Get()[3])); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Quatf) { + TypedValue v; + _extractGfVec(&v, js); + out->value = pxr::VtValue(pxr::GfQuatf(v.value.Get()[0], + v.value.Get()[1], + v.value.Get()[2], + v.value.Get()[3])); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Quatd) { + TypedValue v; + _extractGfVec(&v, js); + out->value = pxr::VtValue(pxr::GfQuatd(v.value.Get()[0], + v.value.Get()[1], + v.value.Get()[2], + v.value.Get()[3])); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Matrix2d) { + _extractGfMatrixd(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Matrix3d) { + _extractGfMatrixd(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Matrix4d) { + _extractGfMatrixd(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Frame4d) { + _extractGfMatrixd(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->TexCoord2h) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->TexCoord2f) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->TexCoord2d) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->TexCoord3h) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->TexCoord3f) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->TexCoord3d) { + _extractGfVec(out, js); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Opaque) { + MY_RUNTIME_ERROR_AND_RETURN("Decoding type failure (Opaque)"); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->Group) { + MY_RUNTIME_ERROR_AND_RETURN("Decoding type failure (Group)"); + } else if (out->valueTypeName == pxr::SdfValueTypeNames->PathExpression) { + std::string x = js.GetString(); + out->value = pxr::VtValue(pxr::SdfPathExpression(x)); + } + #define EXTRACT_ARRAY(TYPENAME, VTARRAY) \ + else if (out->valueTypeName == pxr::SdfValueTypeNames->TYPENAME) {\ + _extractArray(out, js);\ + } + EXTRACT_ARRAY(BoolArray, VtBoolArray) + EXTRACT_ARRAY(UCharArray, VtUCharArray) + EXTRACT_ARRAY(IntArray, VtIntArray) + EXTRACT_ARRAY(UIntArray, VtUIntArray) + EXTRACT_ARRAY(Int64Array, VtInt64Array) + EXTRACT_ARRAY(UInt64Array, VtUInt64Array) + EXTRACT_ARRAY(HalfArray, VtHalfArray) + EXTRACT_ARRAY(FloatArray, VtFloatArray) + EXTRACT_ARRAY(DoubleArray, VtDoubleArray) + EXTRACT_ARRAY(TimeCodeArray, VtTimeCodeArray) + EXTRACT_ARRAY(StringArray, VtStringArray) + EXTRACT_ARRAY(TokenArray, VtTokenArray) + EXTRACT_ARRAY(AssetArray, VtArray) + EXTRACT_ARRAY(Int2Array, VtVec2iArray) + EXTRACT_ARRAY(Int3Array, VtVec3iArray) + EXTRACT_ARRAY(Int4Array, VtVec4iArray) + EXTRACT_ARRAY(Half2Array, VtVec2hArray) + EXTRACT_ARRAY(Half3Array, VtVec3hArray) + EXTRACT_ARRAY(Half4Array, VtVec4hArray) + EXTRACT_ARRAY(Float2Array, VtVec2fArray) + EXTRACT_ARRAY(Float3Array, VtVec3fArray) + EXTRACT_ARRAY(Float4Array, VtVec4fArray) + EXTRACT_ARRAY(Double2Array, VtVec2dArray) + EXTRACT_ARRAY(Double3Array, VtVec3dArray) + EXTRACT_ARRAY(Double4Array, VtVec4dArray) + EXTRACT_ARRAY(Point3hArray, VtVec3hArray) + EXTRACT_ARRAY(Point3fArray, VtVec3fArray) + EXTRACT_ARRAY(Point3dArray, VtVec3dArray) + EXTRACT_ARRAY(Vector3hArray, VtVec3hArray) + EXTRACT_ARRAY(Vector3fArray, VtVec3fArray) + EXTRACT_ARRAY(Vector3dArray, VtVec3dArray) + EXTRACT_ARRAY(Normal3hArray, VtVec3hArray) + EXTRACT_ARRAY(Normal3fArray, VtVec3fArray) + EXTRACT_ARRAY(Normal3dArray, VtVec3dArray) + EXTRACT_ARRAY(Color3hArray, VtVec3hArray) + EXTRACT_ARRAY(Color3fArray, VtVec3fArray) + EXTRACT_ARRAY(Color3dArray, VtVec3dArray) + EXTRACT_ARRAY(Color4hArray, VtVec4hArray) + EXTRACT_ARRAY(Color4fArray, VtVec4fArray) + EXTRACT_ARRAY(Color4dArray, VtVec4dArray) + EXTRACT_ARRAY(QuathArray, VtQuathArray) + EXTRACT_ARRAY(QuatfArray, VtQuatfArray) + EXTRACT_ARRAY(QuatdArray, VtQuatdArray) + EXTRACT_ARRAY(Matrix2dArray, VtMatrix2dArray) + EXTRACT_ARRAY(Matrix3dArray, VtMatrix3dArray) + EXTRACT_ARRAY(Matrix4dArray, VtMatrix4dArray) + EXTRACT_ARRAY(Frame4dArray, VtMatrix4dArray) + EXTRACT_ARRAY(TexCoord2hArray, VtVec2hArray) + EXTRACT_ARRAY(TexCoord2fArray, VtVec2fArray) + EXTRACT_ARRAY(TexCoord2dArray, VtVec2dArray) + EXTRACT_ARRAY(TexCoord3hArray, VtVec3hArray) + EXTRACT_ARRAY(TexCoord3fArray, VtVec3fArray) + EXTRACT_ARRAY(TexCoord3dArray, VtVec3dArray) + EXTRACT_ARRAY(PathExpressionArray, VtArray) + #undef EXTRACT_ARRAY + +#warning todo: 6 listops + else if (out->otherTypeName == "SdfListOp") { + pxr::SdfListOp x = extractSdfListOp(js, extractTfToken); + out->value = pxr::VtValue(x); + } else if (out->otherTypeName == "SdfListOp") { + pxr::SdfListOp x = extractSdfListOp(js, extractLongLong); + out->value = pxr::VtValue(x); + } else if (out->otherTypeName == "SdfListOp") { + pxr::SdfListOp x = extractSdfListOp(js, extractString); + out->value = pxr::VtValue(x); + } else if (out->otherTypeName == "VtDictionary") { + pxr::VtDictionary x = extractVtDictionary(js); + out->value = pxr::VtValue(x); + } else if (out->otherTypeName == "SdfUnregisteredValue") { + pxr::SdfUnregisteredValue x = extractSdfUnregisteredValue(js); + out->value = pxr::VtValue(x); + } else if (out->otherTypeName == "PointIndex") { + TypedValue temp = TypedValue::forTypeName(pxr::SdfValueTypeNames->Int); + extractValueWithTypeHint(&temp, js); + out->value = temp.value; + } else if (out->otherTypeName == "PointIndex[]") { + TypedValue temp = TypedValue::forTypeName(pxr::SdfValueTypeNames->IntArray); + extractValueWithTypeHint(&temp, js); + out->value = temp.value; + } else if (out->otherTypeName == "SdfPermission") { + TypedValue temp = TypedValue::forTypeName(pxr::SdfValueTypeNames->Int); + extractValueWithTypeHint(&temp, js); + out->value = pxr::VtValue(static_cast(temp.value.Get())); + } else if (out->otherTypeName == "Transform") { + TypedValue temp = TypedValue::forTypeName(pxr::SdfValueTypeNames->Matrix4d); + extractValueWithTypeHint(&temp, js); + out->value = temp.value; + } else { + MY_RUNTIME_ERROR_AND_RETURN("Unknown type name '%s'/'%s'", out->valueTypeName.GetAsToken().GetText(), out->otherTypeName.c_str()); + } +} + +template +pxr::JsValue _writeGfVec(const TypedValue& value) { + T v = value.value.Get(); + pxr::JsArray arr; + for (size_t i = 0; i < T::dimension; i++) { + arr.push_back(pxr::JsValue(v[i])); + } + return arr; +} + +template +pxr::JsValue _writeGfMatrixd(const TypedValue& value) { + T m = value.value.Get(); + pxr::JsArray arr; + for (size_t r = 0; r < T::numRows; r++) { + for (size_t c = 0; c < T::numColumns; c++) { + arr.push_back(pxr::JsValue(m[r][c])); + } + } + return arr; +} + +template +pxr::JsValue _writeArray(const TypedValue& value) { + const T& arr = value.value.Get(); + pxr::JsArray result; + for (const auto& x : arr) { + TypedValue temp; + temp.value = pxr::VtValue(x); + temp.valueTypeName = value.valueTypeName.GetScalarType(); + result.push_back(writeValueWithoutTypeHint(temp)); + } + return result; +} + +pxr::JsValue writeValueWithoutTypeHint(const TypedValue& value) { + // Important: Use value.value.IsHolding instead of comparing to value.valueTypeName because + // of e.g. mismatched-types.usda + if (value.value.IsHolding()) { + return pxr::JsValue(); + } + + if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(static_cast(value.value.Get())); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get().GetValue()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get().GetString()); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get().GetAuthoredPath()); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + return _writeGfVec(value); + } else if (value.value.IsHolding()) { + pxr::GfQuath q = value.value.Get(); + TypedValue temp = TypedValue::forVtValue(pxr::VtValue(pxr::GfVec4h(q.GetReal(), q.GetImaginary()[0], q.GetImaginary()[1], q.GetImaginary()[2]))); + return _writeGfVec(temp); + } else if (value.value.IsHolding()) { + pxr::GfQuatf q = value.value.Get(); + TypedValue temp = TypedValue::forVtValue(pxr::VtValue(pxr::GfVec4f(q.GetReal(), q.GetImaginary()[0], q.GetImaginary()[1], q.GetImaginary()[2]))); + return _writeGfVec(temp); + } else if (value.value.IsHolding()) { + pxr::GfQuatd q = value.value.Get(); + TypedValue temp = TypedValue::forVtValue(pxr::VtValue(pxr::GfVec4d(q.GetReal(), q.GetImaginary()[0], q.GetImaginary()[1], q.GetImaginary()[2]))); + return _writeGfVec(temp); + } else if (value.value.IsHolding()) { + return _writeGfMatrixd(value); + } else if (value.value.IsHolding()) { + return _writeGfMatrixd(value); + } else if (value.value.IsHolding()) { + return _writeGfMatrixd(value); + } else if (value.value.IsHolding()) { + return pxr::JsValue(); + } else if (value.value.IsHolding()) { + return pxr::JsValue(value.value.Get().GetText()); + } + + #define WRITE_ARRAY(TYPENAME, VTARRAY) \ + else if (value.value.IsHolding()) {\ + return _writeArray(value);\ + } + WRITE_ARRAY(BoolArray, VtBoolArray) + WRITE_ARRAY(UCharArray, VtUCharArray) + WRITE_ARRAY(IntArray, VtIntArray) + WRITE_ARRAY(UIntArray, VtUIntArray) + WRITE_ARRAY(Int64Array, VtInt64Array) + WRITE_ARRAY(UInt64Array, VtUInt64Array) + WRITE_ARRAY(HalfArray, VtHalfArray) + WRITE_ARRAY(FloatArray, VtFloatArray) + WRITE_ARRAY(DoubleArray, VtDoubleArray) + WRITE_ARRAY(TimeCodeArray, VtTimeCodeArray) + WRITE_ARRAY(StringArray, VtStringArray) + WRITE_ARRAY(TokenArray, VtTokenArray) + WRITE_ARRAY(AssetArray, VtArray) + WRITE_ARRAY(Int2Array, VtVec2iArray) + WRITE_ARRAY(Int3Array, VtVec3iArray) + WRITE_ARRAY(Int4Array, VtVec4iArray) + WRITE_ARRAY(Half2Array, VtVec2hArray) + WRITE_ARRAY(Half3Array, VtVec3hArray) + WRITE_ARRAY(Half4Array, VtVec4hArray) + WRITE_ARRAY(Float2Array, VtVec2fArray) + WRITE_ARRAY(Float3Array, VtVec3fArray) + WRITE_ARRAY(Float4Array, VtVec4fArray) + WRITE_ARRAY(Double2Array, VtVec2dArray) + WRITE_ARRAY(Double3Array, VtVec3dArray) + WRITE_ARRAY(Double4Array, VtVec4dArray) + WRITE_ARRAY(Point3hArray, VtVec3hArray) + WRITE_ARRAY(Point3fArray, VtVec3fArray) + WRITE_ARRAY(Point3dArray, VtVec3dArray) + WRITE_ARRAY(Vector3hArray, VtVec3hArray) + WRITE_ARRAY(Vector3fArray, VtVec3fArray) + WRITE_ARRAY(Vector3dArray, VtVec3dArray) + WRITE_ARRAY(Normal3hArray, VtVec3hArray) + WRITE_ARRAY(Normal3fArray, VtVec3fArray) + WRITE_ARRAY(Normal3dArray, VtVec3dArray) + WRITE_ARRAY(Color3hArray, VtVec3hArray) + WRITE_ARRAY(Color3fArray, VtVec3fArray) + WRITE_ARRAY(Color3dArray, VtVec3dArray) + WRITE_ARRAY(Color4hArray, VtVec4hArray) + WRITE_ARRAY(Color4fArray, VtVec4fArray) + WRITE_ARRAY(Color4dArray, VtVec4dArray) + WRITE_ARRAY(QuathArray, VtQuathArray) + WRITE_ARRAY(QuatfArray, VtQuatfArray) + WRITE_ARRAY(QuatdArray, VtQuatdArray) + WRITE_ARRAY(Matrix2dArray, VtMatrix2dArray) + WRITE_ARRAY(Matrix3dArray, VtMatrix3dArray) + WRITE_ARRAY(Matrix4dArray, VtMatrix4dArray) + WRITE_ARRAY(Frame4dArray, VtMatrix4dArray) + WRITE_ARRAY(TexCoord2hArray, VtVec2hArray) + WRITE_ARRAY(TexCoord2fArray, VtVec2fArray) + WRITE_ARRAY(TexCoord2dArray, VtVec2dArray) + WRITE_ARRAY(TexCoord3hArray, VtVec3hArray) + WRITE_ARRAY(TexCoord3fArray, VtVec3fArray) + WRITE_ARRAY(TexCoord3dArray, VtVec3dArray) + WRITE_ARRAY(PathExpressionArray, VtArray) + #undef WRITE_ARRAY + + else if (value.value.IsHolding>()) { + return writeSdfListOp(value.value.Get>(), writeTfToken); + } else if (value.value.IsHolding>()) { + return writeSdfListOp(value.value.Get>(), writeLongLong); + } else if (value.value.IsHolding>()) { + return writeSdfListOp(value.value.Get>(), writeString); + + + } else if (value.value.IsHolding()) { + return writeVtDictionary(value.value.Get()); + } else if (value.value.IsHolding()) { + return writeSdfUnregisteredValue(value.value.Get()); + + + } else if (value.valueTypeName.GetAsToken() == pxr::SdfValueRoleNames->PointIndex || + value.valueTypeName.GetScalarType() == pxr::SdfValueRoleNames->PointIndex) { + return writeValueWithoutTypeHint(TypedValue::forVtValue(value.value)); + } else if (value.value.IsHolding()) { + return writeValueWithoutTypeHint(TypedValue::forVtValue(pxr::VtValue(static_cast(value.value.Get())))); + } else if (value.value.IsHolding()) { + // Important: Needs "<" and ">" for mismatched-types.usda, + // so default-relationship.usda has to filter them out later. + // Very tricky to handle misencoded types in Sdf in all cases. + std::string s = value.value.Get().GetString(); + s = "<" + s + ">"; + return writeValueWithoutTypeHint(TypedValue::forVtValue(pxr::VtValue(pxr::SdfUnregisteredValue(s)))); + } else if (value.value.IsHolding()) { + return writeSdfAnimationBlock(value.value.Get()); + } + else { + MY_RUNTIME_ERROR("Unknown type name '%s'/'%s'/'%s' for value '%s'", value.valueTypeName.GetAsToken().GetText(), value.otherTypeName.c_str(), value.value.GetTypeName().c_str(), pxr::TfStringify(value.value).c_str()); + return pxr::JsValue(); + } +} + + +TypedValue extractTypeHintAndValue(const pxr::JsValue& js) { + const pxr::JsObject& obj = js.GetJsObject(); + TypedValue result = extractTypeHint(js); + try { + extractValueWithTypeHint(&result, obj.at("value")); + } catch (const std::out_of_range&) { + MY_RUNTIME_ERROR_AND_RETURN("extractTypeHintAndValue requires value key") TypedValue(); + } + + + if (result.value.IsHolding()) { + pxr::SdfUnregisteredValue unregistered = result.value.Get(); + if (result.otherTypeName == "SdfPath") { + if (!unregistered.GetValue().IsHolding()) { + MY_RUNTIME_ERROR_AND_RETURN("SdfPath SdfUnregisteredValue wasn't holding a string") TypedValue(); + } + + // Important: mismatched-types.usda needs to add "<" and ">", + // so default-relationship.usda has to filter them out here. + // Very tricky to handle misencoded types in Sdf in all cases. + std::string unregisteredString = unregistered.GetValue().Get(); + if (unregisteredString.size() >= 2 && unregisteredString.front() == '<' && unregisteredString.back() == '>') { + unregisteredString = unregisteredString.substr(1, unregisteredString.size() - 2); + } + result.value = pxr::VtValue(pxr::SdfPath(unregisteredString)); + } + } + + + return result; +} + +pxr::JsValue writeTypeHintAndValue(const TypedValue& value) { + pxr::JsObject result; + result["type"] = writeTypeHint(value); + result["value"] = writeValueWithoutTypeHint(value); + return result; +} + +std::map extractTimeCodeValueMapWithTypeHint(const pxr::JsValue& js, const TypedValue& type) { + std::map result; + + for (const auto& it : js.GetJsObject()) { + try { + std::size_t pos = 0; + double d = std::stod(it.first, &pos); + if (pos != it.first.size()) { + MY_RUNTIME_ERROR_AND_RETURN("Failed to convert timesample key '%s' to double", it.first.c_str()) {}; + } + TypedValue v = type; + extractValueWithTypeHint(&v, it.second); + result[d] = v.value; + } catch (const std::invalid_argument&) { + MY_RUNTIME_ERROR_AND_RETURN("Failed to convert timesample key '%s' to double", it.first.c_str()) {}; + } + } + + return result; +} + +pxr::JsValue writeTimeCodeValueMapWithoutTypeHint(const std::map& samples, const TypedValue& type) { + pxr::JsObject result; + for (const auto& sample : samples) { + TypedValue temp = type; + temp.value = sample.second; + result[std::to_string(sample.first)] = writeValueWithoutTypeHint(temp); + } + return result; +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/fileFormat.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/fileFormat.cpp new file mode 100644 index 0000000000..2035c3475a --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/fileFormat.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "fileFormat.hpp" +#include "pxr/base/tf/pathUtils.h" +#include "pxr/base/trace/trace.h" +#include "pxr/usd/usd/stage.h" +#include "pxr/usd/ar/resolver.h" +#include "pxr/usd/ar/asset.h" +#include "pxr/usd/ar/writableAsset.h" +#include +#include "Diagnostics.hpp" +#include "CoreSpecSerialization.hpp" + +TF_DEFINE_PUBLIC_TOKENS(SdfJsonFileFormatTokens, SDFJSON_FILE_FORMAT_TOKENS); + +TF_REGISTRY_FUNCTION(TfType) { + SDF_DEFINE_FILE_FORMAT(SdfJsonFileFormat, SdfFileFormat); +} + +SdfJsonFileFormat::SdfJsonFileFormat() +: pxr::SdfFileFormat(SdfJsonFileFormatTokens->Id, + SdfJsonFileFormatTokens->Version, + SdfJsonFileFormatTokens->Target, + SdfJsonFileFormatTokens->Id) +{ +} + +SdfJsonFileFormat::~SdfJsonFileFormat() +{ +} + +bool SdfJsonFileFormat::CanRead(const std::string &file) const { + std::string extension = pxr::TfGetExtension(file); + if (extension != GetFormatId()) { + return false; + } + return true; +} + +bool _read(pxr::SdfLayer* layer, const pxr::JsValue& value) { + if (value.IsNull()) { + TF_RUNTIME_ERROR("Can't read layer, JsValue parse was null"); + return false; + } + + pxr::SdfLayerRefPtr myLayer = pxr::SdfLayer::CreateAnonymous(); + + pxr::TfErrorMark m; + readLayer(myLayer, value); + if (!m.IsClean()) { + return false; + } + + layer->TransferContent(myLayer); + return true; +} + +bool _write(std::string* str, const pxr::SdfLayer& l, const std::string& comment) { + pxr::TfErrorMark m; + writeLayer(str, l, comment); + return m.IsClean(); +} + +bool SdfJsonFileFormat::Read(pxr::SdfLayer *layer, const std::string &resolvedPath, bool metadataOnly) const { + TRACE_FUNCTION(); + + std::shared_ptr asset = pxr::ArGetResolver().OpenAsset(pxr::ArResolvedPath(resolvedPath)); + if (!asset) { return false; } + size_t buflen = asset->GetSize(); + std::shared_ptr buf = asset->GetBuffer(); + std::string s{buf.get(), buflen}; + + pxr::JsParseError err; + pxr::JsValue js = pxr::JsParseString(s, &err); + if (!err.reason.empty()) { + MY_RUNTIME_ERROR_AND_RETURN("JsParseString failed with '%s' at line %d column %d", err.reason.c_str(), err.line, err.column) false; + } + return _read(layer, js); +} + +bool SdfJsonFileFormat::ReadFromString(pxr::SdfLayer *layer, const std::string &str) const { + return _read(layer, pxr::JsParseString(str)); +} + +bool SdfJsonFileFormat::WriteToFile(const pxr::SdfLayer& layer, const std::string &filePath, const std::string& comment, const FileFormatArguments& args) const { + std::shared_ptr asset = pxr::ArGetResolver().OpenAssetForWrite(pxr::ArResolvedPath(filePath), pxr::ArResolver::WriteMode::Replace); + if (!asset) { + TF_RUNTIME_ERROR("Couldn't OpenAssetForWrite(%s)", filePath.c_str()); + return false; + } + std::string s; + if (!_write(&s, layer, comment)) { + TF_RUNTIME_ERROR("FileFormat write failed"); + return false; + } + if (!asset->Write(s.data(), s.size(), 0)) { + TF_RUNTIME_ERROR("ArWritableAsset->Write failed"); + return false; + } + return asset->Close(); +} + +bool SdfJsonFileFormat::SaveToFile(const pxr::SdfLayer& layer, const std::string &filePath, const std::string& comment, const FileFormatArguments& args) const { + return WriteToFile(layer, filePath, comment, args); +} + +bool SdfJsonFileFormat::WriteToString(const pxr::SdfLayer& layer, std::string *str, const std::string& comment) const { + return _write(str, layer, comment); +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/CoreSpecSerialization.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/CoreSpecSerialization.hpp new file mode 100644 index 0000000000..fb139ae5a2 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/CoreSpecSerialization.hpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef CoreSpecSerialization_hpp +#define CoreSpecSerialization_hpp + +#include +#include "pxr/base/js/value.h" +#include "pxr/usd/sdf/spec.h" +#include "pxr/usd/sdf/primSpec.h" +#include "pxr/usd/sdf/attributeSpec.h" +#include "pxr/usd/sdf/relationshipSpec.h" +#include "pxr/usd/sdf/layer.h" + +void readLayer(const pxr::SdfLayerRefPtr& layer, const pxr::JsValue& value); +void writeLayer(std::string* s, const pxr::SdfLayer& layer, const std::string& comment); + +void readPrim(const pxr::SdfLayerRefPtr& layer, const pxr::SdfPrimSpecHandle& prim, const pxr::JsValue& js); +void writePrim(pxr::JsObject& js, const pxr::SdfPrimSpecHandle& prim); + +void readAttribute(const pxr::SdfLayerRefPtr& layer, const pxr::SdfPath& path, const pxr::JsValue& js); +void writeAttribute(pxr::JsObject& js, const pxr::SdfAttributeSpecHandle& attr); + +void readRelationship(const pxr::SdfLayerRefPtr& layer, const pxr::SdfPath& path, const pxr::JsValue& js); +void writeRelationship(pxr::JsObject& js, const pxr::SdfRelationshipSpecHandle& rel); + +// Note: VariantSpec and VariantSetSpec are handled in LIVERPSSerialization + +#endif /* CoreSpecSerialization_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/Diagnostics.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/Diagnostics.hpp new file mode 100644 index 0000000000..fb0efc656b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/Diagnostics.hpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef Diagnostics_hpp +#define Diagnostics_hpp + +#include +#include "pxr/base/tf/diagnostic.h" + +// TfDiagnostic macros expect to be within `PXR_NAMESPACE_USING_DIRECTIVE` or `PXR_NAMESPACE_OPEN_SCOPE`, +// but we don't want to have to repeat those everywhere, so expose our own version of the macros + +#define MY_RUNTIME_ERROR(...) { PXR_NAMESPACE_USING_DIRECTIVE; TF_RUNTIME_ERROR(__VA_ARGS__); } +#define MY_RUNTIME_ERROR_AND_RETURN(...) MY_RUNTIME_ERROR(__VA_ARGS__); return +#define MY_WARN(...) { PXR_NAMESPACE_USING_DIRECTIVE; TF_WARN(__VA_ARGS__); } +#define MY_VERIFY(cond, ...) { PXR_NAMESPACE_USING_DIRECTIVE; TF_VERIFY(cond, __VA_ARGS__); } +#define MY_FATAL_CODING_ERROR(...) { PXR_NAMESPACE_USING_DIRECTIVE; TF_FATAL_CODING_ERROR(__VA_ARGS__); } +#define MY_STATUS(...) { PXR_NAMESPACE_USING_DIRECTIVE; TF_STATUS(__VA_ARGS__); } + + +#endif /* Diagnostics_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/FundementalTypes.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/FundementalTypes.hpp new file mode 100644 index 0000000000..8521df1b44 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/FundementalTypes.hpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef FundementalTypes_hpp +#define FundementalTypes_hpp + +#include +#include +#include "pxr/base/js/value.h" + +#include "LIVERPSSerialization.hpp" +#include "SdfSerialization.hpp" +#include "TsSerialization.hpp" +#include "VtSerialization.hpp" + +// Invokes the callback if the object has a value at the given key. +bool ifValueExists(const pxr::JsObject& js, const std::string& key, std::function callback); + +std::string extractString(const pxr::JsValue&); +pxr::JsValue writeString(const std::string&); + +long long extractLongLong(const pxr::JsValue&); +pxr::JsValue writeLongLong(long long); + +#endif /* FundementalTypes_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/LIVERPSSerialization.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/LIVERPSSerialization.hpp new file mode 100644 index 0000000000..be8642b0d6 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/LIVERPSSerialization.hpp @@ -0,0 +1,186 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef LIVERPSSerialization_hpp +#define LIVERPSSerialization_hpp + +#include +#include "pxr/base/js/value.h" +#include "pxr/base/js/json.h" +#include "pxr/usd/sdf/listOp.h" +#include "pxr/usd/sdf/layer.h" +#include "pxr/usd/sdf/variantSetSpec.h" +#include "pxr/usd/sdf/variantSpec.h" +#include "pxr/usd/sdf/reference.h" +#include "pxr/usd/sdf/payload.h" +#include "Diagnostics.hpp" + +template +pxr::JsValue writeSdfListProxy(pxr::SdfListProxy proxy, ConvertElement convertElement) { + pxr::JsArray result; + + for (const auto& element : proxy) { + result.push_back(convertElement(element)); + } + return result; +} + +template +std::vector extractSdfListProxy(const pxr::JsValue& js, ConvertElement convertElement) { + std::vector result; + + for (const auto& it : js.GetJsArray()) { + result.push_back(convertElement(it)); + } + + return result; +} + + +template +pxr::JsValue writeSdfListEditorProxy(pxr::SdfListEditorProxy proxy, ConvertElement convertElement) { + using Element = typename pxr::SdfListEditorProxy::value_type; + pxr::JsObject result; + + auto handleIndividualListProxy = [&](pxr::SdfListProxy list, std::string key){ + if (!list.empty()) { + result[key] = writeSdfListProxy(list, convertElement); + } + }; + + handleIndividualListProxy(proxy.GetExplicitItems(), "explicit"); + handleIndividualListProxy(proxy.GetAddedItems(), "add"); + handleIndividualListProxy(proxy.GetPrependedItems(), "prepend"); + handleIndividualListProxy(proxy.GetAppendedItems(), "append"); + handleIndividualListProxy(proxy.GetDeletedItems(), "delete"); + handleIndividualListProxy(proxy.GetOrderedItems(), "order"); + + if (result.empty() && proxy.IsExplicit()) { + result["explicit"] = pxr::JsArray(); + } + + return result; +} + +template +void extractSdfListEditorProxy(const pxr::JsValue& js, pxr::SdfListEditorProxy proxy, ConvertElement convertElement) { + using Element = typename pxr::SdfListEditorProxy::value_type; + const pxr::JsObject& obj = js.GetJsObject(); + + auto handleIndividualListProxy = [&](pxr::SdfListProxy list, std::string key) { + ifValueExists(obj, key, [&](const auto& x){ + std::vector toInsert = extractSdfListProxy(x, convertElement); + list.insert(list.end(), toInsert.begin(), toInsert.end()); + }); + }; + + handleIndividualListProxy(proxy.GetExplicitItems(), "explicit"); + handleIndividualListProxy(proxy.GetAddedItems(), "add"); + handleIndividualListProxy(proxy.GetPrependedItems(), "prepend"); + handleIndividualListProxy(proxy.GetAppendedItems(), "append"); + handleIndividualListProxy(proxy.GetDeletedItems(), "delete"); + handleIndividualListProxy(proxy.GetOrderedItems(), "order"); + + if (obj.find("explicit") != obj.end() && !proxy.HasKeys()) { + proxy.ClearEditsAndMakeExplicit(); + } +} + +template +pxr::JsValue writeSdfListOp(pxr::SdfListOp proxy, ConvertElement convertElement) { + pxr::JsObject result; + + auto writeIndividualArray = [&](const std::vector& items, std::string key) { + pxr::JsArray arr; + for (const auto& x : items) { + arr.push_back(convertElement(x)); + } + if (!arr.empty()) { + result[key] = arr; + } + }; + + writeIndividualArray(proxy.GetExplicitItems(), "explicit"); + writeIndividualArray(proxy.GetAddedItems(), "add"); + writeIndividualArray(proxy.GetPrependedItems(), "prepend"); + writeIndividualArray(proxy.GetAppendedItems(), "append"); + writeIndividualArray(proxy.GetDeletedItems(), "delete"); + writeIndividualArray(proxy.GetOrderedItems(), "order"); + if (result.empty() && proxy.IsExplicit()) { + result["explicit"] = pxr::JsArray(); + } + + return result; +} + +template +pxr::SdfListOp extractSdfListOp(const pxr::JsValue& js, ConvertElement convertElement) { + pxr::SdfListOp result; + const pxr::JsObject& obj = js.GetJsObject(); + + auto extractIndividualArray = [&](std::string jsKey, auto setter) { + ifValueExists(obj, jsKey, [&](const auto& x){ + std::vector result; + + for (const auto& it : x.GetJsArray()) { + result.push_back(convertElement(it)); + } + + setter(result); + }); + }; + + extractIndividualArray("explicit", [&](const auto& x){ result.SetExplicitItems(x); }); + extractIndividualArray("add", [&](const auto& x){ result.SetAddedItems(x); }); + extractIndividualArray("prepend", [&](const auto& x){ result.SetPrependedItems(x); }); + extractIndividualArray("append", [&](const auto& x){ result.SetAppendedItems(x); }); + extractIndividualArray("delete", [&](const auto& x){ result.SetDeletedItems(x); }); + extractIndividualArray("order", [&](const auto& x){ result.SetOrderedItems(x); }); + + return result; +} + + +pxr::SdfLayerOffset extractSdfLayerOffset(const pxr::JsValue& js); +pxr::JsValue writeSdfLayerOffset(const pxr::SdfLayerOffset& x); + +pxr::SdfLayerOffsetVector extractSdfLayerOffsetVector(const pxr::JsValue& js); +void writeSubLayerOffsetsIfNeeded(pxr::JsObject& js, const pxr::SdfLayerOffsetVector& offsets); + + +void extractPrimRelocates(const pxr::JsValue& js, const pxr::SdfPrimSpecHandle& prim); +pxr::JsValue writePrimRelocates(const pxr::SdfRelocatesMapProxy& list); + +void extractLayerRelocates(const pxr::SdfLayerRefPtr& layer, const pxr::JsValue& js); +pxr::JsValue writeLayerRelocates(const pxr::SdfRelocates& list); + +void extractVariantSelections(const pxr::SdfPrimSpecHandle& prim, const pxr::JsValue& js); +void writeVariantSelectionsIfNeeded(pxr::JsObject& js, const pxr::SdfVariantSelectionProxy& selections); + + +void readVariantSets(const pxr::SdfLayerRefPtr& layer, const pxr::SdfPath& path, const pxr::JsValue& js); +void writeVariantSetsIfNeeded(pxr::JsObject& js, const pxr::SdfVariantSetsProxy& sets); + + +void readVariantSetSpec(const pxr::JsValue& js, const pxr::SdfVariantSetSpecHandle& variantSet); +pxr::JsValue writeVariantSetSpec(const pxr::SdfVariantSetSpecHandle& variantSet); + + +#endif /* LIVERPSSerialization_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/SdfSerialization.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/SdfSerialization.hpp new file mode 100644 index 0000000000..c9dbc48d1e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/SdfSerialization.hpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef SdfSerialization_hpp +#define SdfSerialization_hpp + +#include +#include "pxr/usd/sdf/types.h" +#include "pxr/base/js/value.h" + +pxr::SdfAnimationBlock extractSdfAnimationBlock(const pxr::JsValue& js); +pxr::JsValue writeSdfAnimationBlock(const pxr::SdfAnimationBlock& x); + +pxr::SdfPath extractSdfPath(const pxr::JsValue&); +pxr::JsValue writeSdfPath(const pxr::SdfPath&); + +pxr::SdfUnregisteredValue extractSdfUnregisteredValue(const pxr::JsValue& js); +pxr::JsValue writeSdfUnregisteredValue(const pxr::SdfUnregisteredValue& value); + +pxr::SdfReference extractSdfReference(const pxr::JsValue& js); +pxr::JsValue writeSdfReference(const pxr::SdfReference& reference); + +pxr::SdfPayload extractSdfPayload(const pxr::JsValue& js); +pxr::JsValue writeSdfPayload(const pxr::SdfPayload& payload); + + +#endif /* SdfSerialization_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/TfSerialization.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/TfSerialization.hpp new file mode 100644 index 0000000000..2c46a8cff0 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/TfSerialization.hpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef TfSerialization_hpp +#define TfSerialization_hpp + +#include +#include +#include "pxr/base/js/value.h" +#include "pxr/base/tf/token.h" +#include "pxr/base/tf/enum.h" + +pxr::TfToken extractTfToken(const pxr::JsValue&); +pxr::JsValue writeTfToken(const pxr::TfToken&); + +pxr::TfTokenVector extractTfTokenVector(const pxr::JsValue&); + +pxr::TfEnum extractTfEnum(const pxr::JsValue& js); +pxr::JsValue writeTfEnum(const pxr::TfEnum& x); + + +#endif /* TfSerialization_hpp */ + diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/TsSerialization.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/TsSerialization.hpp new file mode 100644 index 0000000000..ae518ad451 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/TsSerialization.hpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef TsSerialization_hpp +#define TsSerialization_hpp + +#include +#include "pxr/base/js/value.h" +#include "pxr/base/ts/spline.h" +#include "pxr/usd/sdf/valueTypeName.h" + +pxr::TsSpline extractTsSpline(const pxr::JsValue& js, const pxr::SdfValueTypeName& type); +pxr::JsValue writeTsSpline(const pxr::TsSpline& x); + +pxr::TsExtrapolation extractTsExtrapolation(const pxr::JsValue& js); +pxr::JsValue writeTsExtrapolation(const pxr::TsExtrapolation& x); + +pxr::TsLoopParams extractTsLoopParams(const pxr::JsValue& js); +pxr::JsValue writeTsLoopParams(const pxr::TsLoopParams& x); + +pxr::TsKnotMap extractTsKnotMap(const pxr::JsValue& js, const pxr::SdfValueTypeName& type); +pxr::JsValue writeTsKnotMap(const pxr::TsKnotMap& x); + +pxr::TsKnot extractTsKnot(const pxr::JsValue& js, const pxr::SdfValueTypeName& type); +pxr::JsValue writeTsKnot(const pxr::TsKnot& x); + +#endif /* TsSerialization_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/VtSerialization.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/VtSerialization.hpp new file mode 100644 index 0000000000..6604075f3a --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/VtSerialization.hpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef VtSerialization_hpp +#define VtSerialization_hpp + +#include +#include "pxr/base/vt/value.h" +#include "pxr/usd/sdf/valueTypeName.h" + +/// Represents a VtValue along with some type information, +/// such as a role or non-value type name, or an empty VtValue +/// that is expected to later be filled in to match a given type +struct TypedValue { + pxr::VtValue value; + pxr::SdfValueTypeName valueTypeName; + std::string otherTypeName; + + static TypedValue forVtValue(pxr::VtValue); + static TypedValue forTypeName(pxr::SdfValueTypeName); + static TypedValue withOtherTypeName(std::string s); +}; + +pxr::VtDictionary extractVtDictionary(const pxr::JsValue& js); +pxr::JsValue writeVtDictionary(const pxr::VtDictionary& x); + +TypedValue extractTypeHint(const pxr::JsValue& js); +pxr::JsValue writeTypeHint(const TypedValue& value); + +/// Expects the type hint to be provided. See also extractTypeHintAndValue +void extractValueWithTypeHint(TypedValue* out, const pxr::JsValue& js); +pxr::JsValue writeValueWithoutTypeHint(const TypedValue& value); + +/// Will try to decode the type hint first before decoding the value. See also extractValueWithTypeHint +TypedValue extractTypeHintAndValue(const pxr::JsValue& js); +pxr::JsValue writeTypeHintAndValue(const TypedValue& value); + + +std::map extractTimeCodeValueMapWithTypeHint(const pxr::JsValue& js, const TypedValue& type); +pxr::JsValue writeTimeCodeValueMapWithoutTypeHint(const std::map& samples, const TypedValue& type); + + +#endif /* VtSerialization_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/fileFormat.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/fileFormat.hpp new file mode 100644 index 0000000000..ebcee6e62b --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/include/fileFormat.hpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef SdfJson_fileFormat_hpp +#define SdfJson_fileFormat_hpp + +#include +#include "pxr/usd/sdf/fileFormat.h" +#include "pxr/base/js/json.h" + +PXR_NAMESPACE_USING_DIRECTIVE; + +#define SDFJSON_FILE_FORMAT_TOKENS \ +((Id, "json")) \ +((Version, "1.0")) \ +((Target, "usd")) + +TF_DECLARE_PUBLIC_TOKENS(SdfJsonFileFormatTokens, SDFJSON_FILE_FORMAT_TOKENS); + +TF_DECLARE_WEAK_AND_REF_PTRS(SdfJsonFileFormat); + + +class SdfJsonFileFormat: public pxr::SdfFileFormat { +public: + + bool CanRead(const std::string& file) const override; + bool Read(pxr::SdfLayer* layer, const std::string& resolvedPath, bool metadataOnly) const override; + + bool WriteToFile( + const pxr::SdfLayer&, + const std::string& filePath, + const std::string& comment = std::string(), + const FileFormatArguments& args = FileFormatArguments() + ) const override; + bool SaveToFile( + const pxr::SdfLayer& layer, + const std::string& filePath, + const std::string& comment = std::string(), + const FileFormatArguments& args = FileFormatArguments() + ) const override; + + bool ReadFromString( + pxr::SdfLayer* layer, + const std::string& str + ) const override; + + bool WriteToString( + const pxr::SdfLayer& layer, + std::string* str, + const std::string& comment = std::string() + ) const override; + +protected: + SDF_FILE_FORMAT_FACTORY_ACCESS; + + SdfJsonFileFormat(); + ~SdfJsonFileFormat() override; +}; + +#endif /* SdfJson_fileFormat_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/plugInfo.json b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/plugInfo.json new file mode 100644 index 0000000000..85464421d9 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Sources/sdfJson/plugInfo.json @@ -0,0 +1,25 @@ +{ + "Plugins": [ + { + "Info": { + "Types": { + "SdfJsonFileFormat" : { + "bases": ["SdfFileFormat"], + "extensions": [ + "json" + ], + "formatId": "json", + "primary": true, + "target": "usd", + "supportsEditing": false + } + } + }, + "Name": "sdfJson", + "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@", + "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@", + "Root": "@PLUG_INFO_ROOT@", + "Type": "library" + } + ] +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/SwiftUsd b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/SwiftUsd new file mode 120000 index 0000000000..c866b86874 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/SwiftUsd @@ -0,0 +1 @@ +../../../.. \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Tests/CodeCoverageTests.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Tests/CodeCoverageTests.swift new file mode 120000 index 0000000000..d6f4e972b4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Tests/CodeCoverageTests.swift @@ -0,0 +1 @@ +../../Tests/CodeCoverageTests.swift \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Tests/Resources b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Tests/Resources new file mode 120000 index 0000000000..fe08fab09e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Cxx/Tests/Resources @@ -0,0 +1 @@ +../../Tests/usdcat-tests/Resources \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Package.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Package.swift new file mode 100644 index 0000000000..62f5341e8e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Package.swift @@ -0,0 +1,74 @@ +// swift-tools-version: 6.1 +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + + +import PackageDescription + +let package = Package( + name: "sdfJson", + platforms: [.macOS(.v14), .iOS(.v17)], + products: [ + .library( + name: "sdfJson", + targets: ["sdfJson"] + ), + ], + dependencies: [ + .package(path: "SwiftUsd") + // We use a symlink to the SwiftUsd repo for this example, + // but typically you'd do something like this: + // .package(url: "https://github.com/apple/SwiftUsd", from: "8.2.0"), + ], + targets: [ + .target(name: "TemporaryImplementations_Cxx", + dependencies: [.product(name: "OpenUSD", package: "SwiftUsd")]), + .target(name: "TemporaryImplementations_Swift", + dependencies: [.product(name: "OpenUSD", package: "SwiftUsd"), + "TemporaryImplementations_Cxx"], + swiftSettings: [.interoperabilityMode(.Cxx)]), + + .target( + name: "sdfJson", + dependencies: [.product(name: "OpenUSD", package: "SwiftUsd"), + "TemporaryImplementations_Cxx", + "TemporaryImplementations_Swift"], + resources: [.copy("plugInfo.json")], + swiftSettings: [ + .interoperabilityMode(.Cxx), + ] + enableExperimentalFeature_SymbolLinkageMarkers_ifNeeded(), + plugins: [.plugin(name: "generate-plug-info-json", package: "SwiftUsd")], + ), + .testTarget(name: "CodeCoverageTests", dependencies: ["sdfJson"], + resources: [.copy("Resources")], + swiftSettings: [.interoperabilityMode(.Cxx)]), + ], + cxxLanguageStandard: .gnucxx17 +) + +// Swift 6.3 adds the `@used` and `@section` attributes, but Swift 6.1 and Swift 6.2 +// can use the `@_used` and `@_section` underscored attributes with `SymbolLinkageMarkers` enabled +func enableExperimentalFeature_SymbolLinkageMarkers_ifNeeded() -> [SwiftSetting] { + #if compiler(<6.3) + [.enableExperimentalFeature("SymbolLinkageMarkers")] + #else + [] + #endif +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/README b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/README new file mode 100644 index 0000000000..c96d350bd4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/README @@ -0,0 +1,38 @@ +# SdfFileFormat Json plugin (Swift) + +This package is an example of how to write an SdfFileFormat plugin in Swift. + +## Key details +- In `plugInfo.json`, we use `@PLUG_INFO_LIBRARY_PATH@`, `@PLUG_INFO_RESOURCE_PATH@`, and `@PLUG_INFO_ROOT@` to allow our plugin to be used in both SwiftUsd-based apps and vanilla OpenUSD-based runtimes. +- In `Package.swift`, we use `.copy("plugInfo.json")` and `.plugin(name: "generate-plug-info-json", package: "SwiftUsd")` to have the build system fill in the `@PLUG_INFO_*@` values based on the target architecture +- In `Package.swift`, we add `.enableExperimentalFeature("SymbolLinkageMarkers")` as a Swift setting when using Swift 6.1/6.2, because Swift didn't gain official support for the `@used` and `@section` attributes until Swift 6.3. This allows us to write a plugin that can be used across as many Swift compiler versions as possible. +- In `FileFormat.swift`, we use the `@SWIFTUSD_PLUGIN` macro to tell the OpenUSD runtime how to use our custom plugin. We also subclass from `Overlay.SdfFileFormatSubclass` and override/implement some of its methods. + +## Usage +To use this plugin in a SwiftUsd-based app: +1. Add it as a package dependency to your Swift Package/Xcode project. + +To use this plugin in a vanilla OpenUSD-based app: +1. `cd` into the package directory +2. Run `swift build` +3. Run `swift package build-vanilla-openusd-plugin` and note the outputed plugin path +4. Set the `PXR_PLUGINPATH_NAME` environment variable to point to your plugin. For example: +``` +export PXR_PLUGINPATH_NAME="/Users/maddyadams/SwiftUsd/Examples/SdfFileFormat/hioJson_Swift/.build/plugins/build-vanilla-openusd-plugin/outputs/sdfJson.usdplugin/:$PXR_PLUGINPATH_NAME" +usdcat example.usda -o example.json +usdcat example.json -o example2.usda +``` + +## Code structure +- `FileFormat.swift` contains `@SWIFTUSD_PLUGIN final class SdfJsonFileFormat: Overlay.SdfFileFormatSubclass`. It uses `JsAny` to handle Json parsing/printing, and calls into `readLayer` and `writeLayer` in `CoreSpecSerialization.swift`. +- `CoreSpecSerialization.swift` handles the reading and writing of layers, prims, attributes, and relationships. +- `LIVERPSSerialization.swift` handles the reading and writing of composition arcs. +- `SdfSerialization.swift` handles the reading and writing of other `Sdf` types. +- `TfSerialization.swift` handles the reading and writing of `Tf` types. +- `TsSerialization.swift` handles the reading and writing of `Ts` (spline) types. +- `VtSerialization.swift` handles the reading and writing of `Vt` types. Particular care is taken with `VtValue` to ensure that USD files can be losslessly converted into Json and back to USD. +- `JsAny.swift` defines an alternative to `pxr::JsValue`, which is not particularly ergonomic when used in Swift. +- `ProxyTypesSequenceWorkarounds.swift` holds workarounds for some compiler bugs that occur when trying to conform proxy types in `Sdf` to `Sequence` +- `VtArrayTemplateErgonomics.swift` defines a protocol with specific operations on `pxr::VtArray`, and conforms many specializations of `pxr::VtArray` to the protocol. This lets `VtSerialization.swift` operate generically on any `pxr::VtArray`, keep code duplication to a minimum. +- Files in `TemporaryImplementations_Cxx` add some additional minor functionality to work around compiler limitations. +- `TemporaryImplementations_Swift/SdfProxyTypes.swift` defines protocols with specific operations on `pxr::SdfListOp`, `pxr::SdfListProxy`, and `pxr::SdfListEditorProxy`. Like with `VtArrayTemplateErgonomics.swift`, this lets other serialization code operate generically on any specialization of these types, keeping code duplication to a minimum. \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/SdfProxyTypes.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/SdfProxyTypes.cpp new file mode 100644 index 0000000000..a27ac20913 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/SdfProxyTypes.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "SdfProxyTypes.hpp" + +bool __Overlay::manual_operatorEqualsEquals(pxr::SdfVariantSetsProxy::const_iterator const& a, pxr::SdfVariantSetsProxy::const_iterator const& b) { + return a == b; +} + + +bool __Overlay::manual_operatorEqualsEquals(pxr::SdfRelocatesMapProxy::const_iterator const& a, pxr::SdfRelocatesMapProxy::const_iterator const& b) { + return a == b; +} + +bool __Overlay::manual_operatorEqualsEquals(pxr::SdfRelocatesMapProxy::iterator const& a, pxr::SdfRelocatesMapProxy::iterator const& b) { + return a == b; +} + +std::pair __Overlay::insert(pxr::SdfRelocatesMapProxy& p, pxr::SdfRelocatesMapProxy::value_type const& x) { + return p.insert(x); +} + +pxr::SdfRelocatesMapProxy::iterator __Overlay::erase(pxr::SdfRelocatesMapProxy& proxy, pxr::SdfRelocatesMapProxy::iterator const& it) { +#warning SdfRelocatesMapProxy::erase doesn't return its iterator. this workaround might be unsafe or incorrect + auto result = it; + result++; + proxy.erase(it); + return result; +} + +pxr::SdfRelocatesMapProxy::value_type __Overlay::operatorStar(pxr::SdfRelocatesMapProxy::iterator const& it) { + return *it; +} +void __Overlay::operatorStarSet(pxr::SdfRelocatesMapProxy::iterator& it, pxr::SdfRelocatesMapProxy::value_type const& newValue) { + it->second = newValue.second; +} + + + + +bool __Overlay::manual_operatorEqualsEquals(pxr::SdfVariantSelectionProxy::const_iterator const& a, pxr::SdfVariantSelectionProxy::const_iterator const& b) { + return a == b; +} + +bool __Overlay::manual_operatorEqualsEquals(pxr::SdfVariantSelectionProxy::iterator const& a, pxr::SdfVariantSelectionProxy::iterator const& b) { + return a == b; +} + +std::pair __Overlay::insert(pxr::SdfVariantSelectionProxy& p, pxr::SdfVariantSelectionProxy::value_type const& x) { + return p.insert(x); +} + +pxr::SdfVariantSelectionProxy::iterator __Overlay::erase(pxr::SdfVariantSelectionProxy& proxy, pxr::SdfVariantSelectionProxy::iterator const& it) { +#warning SdfVariantSelectionProxy::erase doesn't return its iterator. this workaround might be unsafe or incorrect + auto result = it; + result++; + proxy.erase(it); + return result; +} + +pxr::SdfVariantSelectionProxy::value_type __Overlay::operatorStar(pxr::SdfVariantSelectionProxy::iterator const& it) { + return *it; +} +void __Overlay::operatorStarSet(pxr::SdfVariantSelectionProxy::iterator& it, pxr::SdfVariantSelectionProxy::value_type const& newValue) { + it->second = newValue.second; +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/TemporaryImplementations.cpp b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/TemporaryImplementations.cpp new file mode 100644 index 0000000000..a631530716 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/TemporaryImplementations.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "TemporaryImplementations.hpp" + +std::optional __Overlay::DoubleOptional(double d) { + return {d}; +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/include/SdfProxyTypes.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/include/SdfProxyTypes.hpp new file mode 100644 index 0000000000..e64cbf2cb8 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/include/SdfProxyTypes.hpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef SdfTemplateProtocols_hpp +#define SdfTemplateProtocols_hpp + +#include +#include +#include +#include "pxr/usd/sdf/proxyTypes.h" +#include "pxr/usd/sdf/variantSetSpec.h" +#include "swiftUsd/Wrappers/SdfProxyTypesIteratorWrapper.h" + +// See the note in ProxyTypeSequenceWoarkarounds.swift, +// this is just what it takes sometimes to conform C++ types +// to the right Swift protocols + +namespace Overlay { + typedef std::pair SdfRelocatesMapProxy_Iterator_Bool_Pair; + typedef std::pair SdfVariantSelectionProxy_Iterator_Bool_Pair; + typedef std::pair SdfTimeSampleMap_Iterator_Bool_Pair; +} + +namespace __Overlay { + typedef SdfProxyTypesIteratorWrapper SdfNameEditorProxyListProxyIteratorWrapper; + typedef SdfProxyTypesIteratorWrapper SdfPathEditorProxyListProxyIteratorWrapper; + typedef SdfProxyTypesIteratorWrapper SdfPayloadEditorProxyListProxyIteratorWrapper; + typedef SdfProxyTypesIteratorWrapper SdfReferenceEditorProxyListProxyIteratorWrapper; + + + bool manual_operatorEqualsEquals(pxr::SdfVariantSetsProxy::const_iterator const& a, pxr::SdfVariantSetsProxy::const_iterator const& b); + + bool manual_operatorEqualsEquals(pxr::SdfRelocatesMapProxy::const_iterator const& a, pxr::SdfRelocatesMapProxy::const_iterator const& b); + bool manual_operatorEqualsEquals(pxr::SdfRelocatesMapProxy::iterator const& a, pxr::SdfRelocatesMapProxy::iterator const& b); + + std::pair insert(pxr::SdfRelocatesMapProxy&, pxr::SdfRelocatesMapProxy::value_type const&); + pxr::SdfRelocatesMapProxy::iterator erase(pxr::SdfRelocatesMapProxy&, pxr::SdfRelocatesMapProxy::iterator const&); + pxr::SdfRelocatesMapProxy::value_type operatorStar(pxr::SdfRelocatesMapProxy::iterator const&); + void operatorStarSet(pxr::SdfRelocatesMapProxy::iterator&, pxr::SdfRelocatesMapProxy::value_type const&); + + bool manual_operatorEqualsEquals(pxr::SdfVariantSelectionProxy::const_iterator const& a, pxr::SdfVariantSelectionProxy::const_iterator const& b); + bool manual_operatorEqualsEquals(pxr::SdfVariantSelectionProxy::iterator const& a, pxr::SdfVariantSelectionProxy::iterator const& b); + + std::pair insert(pxr::SdfVariantSelectionProxy&, pxr::SdfVariantSelectionProxy::value_type const&); + pxr::SdfVariantSelectionProxy::iterator erase(pxr::SdfVariantSelectionProxy&, pxr::SdfVariantSelectionProxy::iterator const&); + pxr::SdfVariantSelectionProxy::value_type operatorStar(pxr::SdfVariantSelectionProxy::iterator const&); + void operatorStarSet(pxr::SdfVariantSelectionProxy::iterator&, pxr::SdfVariantSelectionProxy::value_type const&); + +} + +#endif /* SdfTemplateProtocols_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/include/TemporaryImplementations.hpp b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/include/TemporaryImplementations.hpp new file mode 100644 index 0000000000..ffde38f6ca --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Cxx/include/TemporaryImplementations.hpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef TemporaryImplementations_hpp +#define TemporaryImplementations_hpp + +#include +#include +#include +#include +#include "pxr/usd/sdf/mapEditProxy.h" +#include "pxr/usd/sdf/proxyTypes.h" +#include "pxr/base/vt/value.h" +#include "pxr/usd/sdf/variantSetSpec.h" +#include "pxr/usd/sdf/variantSpec.h" +#include "pxr/base/vt/array.h" +#include "pxr/usd/sdf/pathExpression.h" + +// Prior to Swift 6.3, there's no way to directly create a non-empty +// std::optional in Swift, so we add a function to do that. + +namespace Overlay { + typedef std::optional Double_Optional; +} + +namespace __Overlay { + std::optional DoubleOptional(double d); +} + +#endif /* TemporaryImplementations_hpp */ diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Swift/SdfProxyTypes.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Swift/SdfProxyTypes.swift new file mode 100644 index 0000000000..36ebd54221 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Swift/SdfProxyTypes.swift @@ -0,0 +1,290 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD +import TemporaryImplementations_Cxx + +public protocol _StdVectorProtocol: Sequence where Element == value_type { + associatedtype value_type + init() + mutating func push_back(_ elem: value_type) +} + +// See the note in VtArrayTemplateErgonomics.swift. +// We need to work in a "C++ templates" way over different +// pxr::SdfListOp, pxr::SdfListProxy, and pxr::SdfListEditorProxy. +// We can do that by writing protocols that closely match the interface of +// the C++ template, and then conform the specializations to the protocols. +// Swift protocols can't fully express the entire interface of C++ templates +// in some circumstances, so certain members are commented out or excluded. +// It might make sense to move this into SwiftUsd itself at some point. + +// MARK: SdfListOp + +extension Overlay { + public protocol _SdfListOpProtocol { + typealias T = value_type + typealias ItemType = value_type + typealias ItemVector = value_vector_type + associatedtype value_type // T + associatedtype value_vector_type: _StdVectorProtocol // std::vector + +// static func CreateExplicit(_ explicitItems: ItemVector) -> Self +// static func Create(_ prependedItems: ItemVector, +// _ appendedItems: ItemVector, +// _ deletedItems: ItemVector) -> Self + + init() +// +// mutating func Swap(_ rhs: Self) +// + func HasKeys() -> Bool + func HasItem(_ item: T) -> Bool + func IsExplicit() -> Bool + func __GetExplicitItemsUnsafe() -> UnsafePointer + func __GetPrependedItemsUnsafe() -> UnsafePointer + func __GetAppendedItemsUnsafe() -> UnsafePointer + func __GetDeletedItemsUnsafe() -> UnsafePointer + func __GetItemsUnsafe(_ type: pxr.SdfListOpType) -> UnsafePointer + func GetAppliedItems() -> ItemVector + mutating func SetExplicitItems(_ items: ItemVector, _ errMsg: UnsafeMutablePointer!) -> Bool + mutating func SetPrependedItems(_ items: ItemVector, _ errMsg: UnsafeMutablePointer!) -> Bool + mutating func SetAppendedItems(_ items: ItemVector, _ errMsg: UnsafeMutablePointer!) -> Bool + mutating func SetDeletedItems(_ items: ItemVector, _ errMsg: UnsafeMutablePointer!) -> Bool + mutating func SetItems(_ items: ItemVector, _ type: pxr.SdfListOpType, _ errMsg: UnsafeMutablePointer!) -> Bool + mutating func Clear() + mutating func ClearAndMakeExplicit() +// +// associatedtype ApplyCallback +// func ApplyOperations(_ vec: UnsafeMutablePointer, _ cb: ApplyCallback) +// +// associatedtype StdOptionalStdListOpT +// func ApplyOperations(_ inner: Self) -> StdOptionalStdListOpT +// +// associatedtype ModifyCallback +// mutating func ModifyOperations(_ callback: ModifyCallback) -> Bool +// mutating func ModifyOperations(_ callback: ModifyCallback, _ unusedRemoveDuplicates: Bool) -> Bool +// mutating func ReplaceOperations(_ op: pxr.SdfListOpType, _ index: Int, _ n: Int, _ newItems: ItemVector) -> Bool +// +// mutating func ComposeOperations(_ stronger: Self, _ op: pxr.SdfListOpType) +// + func __GetAddedItemsUnsafe() -> UnsafePointer + func __GetOrderedItemsUnsafe() -> UnsafePointer + mutating func SetAddedItems(_ items: ItemVector) + mutating func SetOrderedItems(_ items: ItemVector) + + // == + // != + } +} + +extension Overlay._SdfListOpProtocol { + public borrowing func GetExplicitItems() -> ItemVector { __GetExplicitItemsUnsafe().pointee } + public borrowing func GetPrependedItems() -> ItemVector { __GetPrependedItemsUnsafe().pointee } + public borrowing func GetAppendedItems() -> ItemVector { __GetAppendedItemsUnsafe().pointee } + public borrowing func GetDeletedItems() -> ItemVector { __GetDeletedItemsUnsafe().pointee } + public borrowing func GetItems(_ type: pxr.SdfListOpType) -> ItemVector { __GetItemsUnsafe(type).pointee } + public borrowing func GetAddedItems() -> ItemVector { __GetAddedItemsUnsafe().pointee } + public borrowing func GetOrderedItems() -> ItemVector { __GetOrderedItemsUnsafe().pointee } +} + +extension pxr.SdfIntListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfIntListOp.value_vector_type: _StdVectorProtocol {} +extension pxr.SdfUIntListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfUIntListOp.value_vector_type: _StdVectorProtocol {} +extension pxr.SdfInt64ListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfInt64ListOp.value_vector_type: _StdVectorProtocol {} +extension pxr.SdfUInt64ListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfUInt64ListOp.value_vector_type: _StdVectorProtocol {} +extension pxr.SdfTokenListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfTokenListOp.value_vector_type: _StdVectorProtocol {} +extension pxr.SdfStringListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfStringListOp.value_vector_type: _StdVectorProtocol {} +extension pxr.SdfPathListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfPathListOp.value_vector_type: _StdVectorProtocol {} +extension pxr.SdfReferenceListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfReferenceListOp.value_vector_type: _StdVectorProtocol {} +extension pxr.SdfPayloadListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfPayloadListOp.value_vector_type: _StdVectorProtocol {} +extension pxr.SdfUnregisteredValueListOp: Overlay._SdfListOpProtocol {} +extension pxr.SdfUnregisteredValueListOp.value_vector_type: _StdVectorProtocol {} + +// MARK: SdfListProxy + +extension Overlay { + public protocol _SdfListProxyProtocol: Sequence { + associatedtype TypePolicy + typealias value_type = Element + associatedtype value_vector_type: _StdVectorProtocol + associatedtype iterator + associatedtype const_iterator + + init(_ op: pxr.SdfListOpType) + // init(editor, op) + + mutating func __beginMutatingUnsafe() -> iterator + mutating func __endMutatingUnsafe() -> iterator + + // rbegin + // rend + func __beginUnsafe() -> const_iterator + func __endUnsafe() -> const_iterator + + // rbegin + // rend + + func size() -> Int + func empty() -> Bool + + // [] + // [] + + // front + // back + // front + // back + + mutating func push_back(_ elem: value_type) + mutating func pop_back() + + mutating func __insertUnsafe(_ pos: iterator, _ x: value_type) -> iterator + // template insert +// mutating func __eraseUnsafe(_ pos: iterator) +// mutating func __eraseUnsafe(_ f: iterator, _ l: iterator) + mutating func clear() + mutating func resize(_ n: Int, _ t: value_type) + + // operator value_vector_type() const + + // == + // != + // < + // <= + // > + // >= + // == + // == + // != + // != + // < + // < + // > + // > + // <= + // <= + // >= + // >= + func __convertToBool() -> Bool + func GetLayer() -> pxr.SdfLayerHandle + func GetPath() -> pxr.SdfPath + func IsExpired() -> Bool + func Count(_ value: value_type) -> Int + func Find(_ value: value_type) -> Int + mutating func Insert(_ index: CInt, _ value: value_type) + mutating func Remove(_ value: value_type) + mutating func Replace(_ oldValue: value_type, _ newValue: value_type) + mutating func Erase(_ index: Int) + mutating func ApplyList(_ list: Self) +// mutating func ApplyEditsToList(_ vec: UnsafeMutablePointer?) + // ModifyItemEdits + } +} + +extension pxr.SdfNameOrderProxy: Overlay._SdfListProxyProtocol {} +extension pxr.SdfSubLayerProxy: Overlay._SdfListProxyProtocol {} + +// MARK: SdfListEditorProxy + +extension Overlay { + public protocol _SdfListEditorProxyProtocol { + associatedtype TypePolicy + associatedtype ListProxy: Overlay._SdfListProxyProtocol + typealias value_type = ListProxy.value_type + associatedtype value_vector_type: _StdVectorProtocol + + // ApplyCallback + + // ModifyCallback + + init() + + // init(listEditor) + + func IsExpired() -> Bool + func IsExplicit() -> Bool + func IsOrderedOnly() -> Bool + func HasKeys() -> Bool + // func ApplyEditsToList(_ vec: UnsafeMutablePointer?) + // template ApplyEditsToList + + mutating func CopyItems(_ other: Self) -> Bool + mutating func ClearEdits() -> Bool + mutating func ClearEditsAndMakeExplicit() -> Bool + + // template ModifyItemEdits + + func ContainsItemEdit(_ item: value_type, _ onlyAddOrExplicit: Bool) -> Bool + mutating func RemoveItemEdits(_ item: value_type) + mutating func ReplaceItemEdits(_ oldItem: value_type, _ newItem: value_type) + func GetExplicitItems() -> ListProxy + func GetAddedItems() -> ListProxy + func GetPrependedItems() -> ListProxy + func GetAppendedItems() -> ListProxy + func GetDeletedItems() -> ListProxy + func GetOrderedItems() -> ListProxy + func GetAddedOrExplicitItems() -> value_vector_type + func GetAppliedItems() -> value_vector_type + mutating func Add(_ value: value_type) + mutating func Prepend(_ value: value_type) + mutating func Append(_ value: value_type) + mutating func Remove(_ value: value_type) + mutating func Erase(_ value: value_type) + func __convertToBool() -> Bool + } +} + +extension pxr.SdfNameEditorProxy: Overlay._SdfListEditorProxyProtocol {} +extension pxr.SdfNameEditorProxy.ListProxy: __Overlay.SdfProxyTypesSequenceProtocol { + public typealias Iterator = __Overlay.SdfNameEditorProxyListProxyIteratorWrapper +} +extension pxr.SdfNameEditorProxy.ListProxy.Iterator: __Overlay.SdfProxyTypesIteratorProtocol {} +extension pxr.SdfNameEditorProxy.ListProxy: Overlay._SdfListProxyProtocol {} + +extension pxr.SdfPathEditorProxy: Overlay._SdfListEditorProxyProtocol {} +extension pxr.SdfPathEditorProxy.ListProxy: __Overlay.SdfProxyTypesSequenceProtocol { + public typealias Iterator = __Overlay.SdfPathEditorProxyListProxyIteratorWrapper +} +extension pxr.SdfPathEditorProxy.ListProxy.Iterator: __Overlay.SdfProxyTypesIteratorProtocol {} +extension pxr.SdfPathEditorProxy.ListProxy: Overlay._SdfListProxyProtocol {} + +extension pxr.SdfPayloadEditorProxy: Overlay._SdfListEditorProxyProtocol {} +extension pxr.SdfPayloadEditorProxy.ListProxy: __Overlay.SdfProxyTypesSequenceProtocol { + public typealias Iterator = __Overlay.SdfPayloadEditorProxyListProxyIteratorWrapper +} +extension pxr.SdfPayloadEditorProxy.ListProxy.Iterator: __Overlay.SdfProxyTypesIteratorProtocol {} +extension pxr.SdfPayloadEditorProxy.ListProxy: Overlay._SdfListProxyProtocol {} + +extension pxr.SdfReferenceEditorProxy: Overlay._SdfListEditorProxyProtocol {} +extension pxr.SdfReferenceEditorProxy.ListProxy: __Overlay.SdfProxyTypesSequenceProtocol { + public typealias Iterator = __Overlay.SdfReferenceEditorProxyListProxyIteratorWrapper +} +extension pxr.SdfReferenceEditorProxy.ListProxy.Iterator: __Overlay.SdfProxyTypesIteratorProtocol {} +extension pxr.SdfReferenceEditorProxy.ListProxy: Overlay._SdfListProxyProtocol {} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Swift/TemporaryImplementations.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Swift/TemporaryImplementations.swift new file mode 100644 index 0000000000..e5226e249e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/TemporaryImplementations_Swift/TemporaryImplementations.swift @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD +import TemporaryImplementations_Cxx + +public typealias pxr = pxrInternal_v0_26_8__pxrReserved__ + +// Prior to Swift 6.3, there's no way to directly create a non-empty +// std::optional in Swift, so we add a way to do that. + +#if compiler(<6.3) +extension Overlay.Double_Optional { + public init(_ x: Double) { + self = __Overlay.DoubleOptional(x) + } +} +#endif // #if compiler(<6.3) diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/CoreSpecSerialization.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/CoreSpecSerialization.swift new file mode 100644 index 0000000000..3c0c279017 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/CoreSpecSerialization.swift @@ -0,0 +1,483 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + + +import Foundation +import OpenUSD + +/* + A word on pxr::SdfHandle and pxr::SdfSpec: + + This Swift target deals with pxr::SdfHandle a lot by virtue of working at the Sdf layer. + In C++, you can easily do `myHandle->method()`, but in Swift, that has to be spelt `myHandle.pointee.method()`. + Doing that everywhere can be pretty noisy to no real benefit, so instead we write our methods to take spec types + (e.g. pxr.SdfSpec, pxr.SdfPrimSpec) directly instead of having handles. + + The downside of this is that `myHandle->method()` will automatically check if the handle is dormant on each acccess, + and safely terminate the program if that is the case. By working with SdfSpecs directly, we avoid doing that dormancy + check as frequently, which in some circumstances could open us up to memory safety issues. However, nothing that we do + would delete/destroy a spec (during the SdfFileFormat.WriteToFile/WriteToString phase, we are creating JsAny objects but + only reading from the SdfLayer; during the SdfFileFormat.Read phase, we are creating specs but never removing them), so + we do not need to worry that our own code will invalidate a spec we are still using. And, OpenUSD's threading model is + many readers or one writer; during SdfFileFormat.WriteToFile/WriteToString, we're reading the layer, so no other part of + OpenUSD is allowed to be modifying the layer, and during SdfFileFormat.Read, we're writing to the layer, so no other part + of OpenUSD is allowed to be accessing the layer. So in short, the fact that we are not doing as frequent checks for + dormancy does not make our Swift code less safe than the C++ version. + + Finally, we use the added computed property `pointeeOrThrow` to throw a Swift error if we try to dereference an invalid handle, + rather than let `myHandle->method()` safely terminate the program, so that we can report errors to the user without (safely) crashing. + */ + +func readLayer(_ layer: pxr.SdfLayer, _ data: Data) throws { + let jsAny: JsAny + do { + jsAny = try JsAny.decodeFromData(data) + } catch { + TF_RUNTIME_ERROR(std.string("Can't read layer, JS decode failed with \(error)")) + throw error + } + + if jsAny.isNull { + TF_RUNTIME_ERROR("Can't read layer, JsAny parse was null") + throw JsDecodingError.jsAnyParseWasNull + } + + return try readPrim(layer, layer.GetPseudoRoot().pointeeOrThrow, jsAny) +} +func writeLayer(_ layer: pxr.SdfLayer, _ comment: std.string) throws -> Data { + let jsAny = try writePrim(layer.GetPseudoRoot().pointeeOrThrow) + return try JsAny.encodeToData(jsAny) +} + +func readMetadata(_ js: JsAny, _ spec: pxr.SdfSpec) throws { + var spec = spec + for (k, v) in try js.castAsObject() { + let value = try extractTypeHintAndValue(v) + + guard spec.SetField(pxr.TfToken(k), value.value) else { + throw JsDecodingError.failedToSetMetadataOnPrim(k, spec.GetPath(), value.value) + } + } +} + +func writeMetadata(_ spec: pxr.SdfSpec) throws -> JsAny { + var result = [String : JsAny]() + + for key in spec.GetMetaDataInfoKeys() { + if spec.GetField(key).IsEmpty() { continue } + if key == pxr.TfToken("typeName") && spec.GetSpecType() == .SdfSpecTypePrim { + continue + } + if key == pxr.TfToken("payload") { + // For whatever reason, payloads appear as metadata in GetMetaDataInfoKeys. No other + // composition arcs appear this way. We handle payloads as part of the general LIVERPS handling + continue + } + + let v = TypedValue(vtValue: spec.GetField(key)) + result[String(key)] = try writeTypeHintAndValue(v) + } + + // GetMetaDataInfoKeys only handles known/registered metadata, but + // specs can have unknown metadata on them, e.g. test case one-unknown-metadata.usda. + // So, pull out all the fields on this spec, and then write out the ones + // that aren't registered. + let registeredFields = spec.GetSchema().GetFields(spec.GetSpecType()) + fieldLoop: for field in spec.ListFields() { + for x in registeredFields { + if x == field { + if (field == .SdfFieldKeys.Comment && !spec.GetField(field).IsEmpty()) { + // pass. Comment isn't provided by GetMetaDataInfoKeys, but is a registered field. + // prim specs and property specs can have it. + } else { + continue fieldLoop + } + } + } + + let v = TypedValue(vtValue: spec.GetField(field)) + result[String(field)] = try writeTypeHintAndValue(v) + } + + return .object(result) +} + +enum DispatchKey: String { + case children + case attributes + case relationships +} + +func dispatchObjectsUnderPrimForReading(_ layer: pxr.SdfLayer, _ path: pxr.SdfPath, _ js: [String : JsAny], _ key: DispatchKey) throws { + guard let x = js[key.rawValue] else { return } + + for element in try x.castAsArray() { + let subObject = try element.castAsObject() + let name = try subObject["name", errorMessage: "\(path)"].castAsString() + + let subPath: pxr.SdfPath + if key == .children { + subPath = path.AppendChild(pxr.TfToken(name)) + } else { + subPath = path.AppendProperty(pxr.TfToken(name)) + } + + switch key { + case .children: + pxr.SdfCreatePrimInLayer(Overlay.TfWeakPtr(layer), subPath) + try readPrim(layer, layer.GetPrimAtPath(subPath).pointeeOrThrow, element) + + case .attributes: + try readAttribute(layer, subPath, element) + + case .relationships: + try readRelationship(layer, subPath, element) + } + } +} + +func readPrim(_ layer: pxr.SdfLayer, _ prim: pxr.SdfPrimSpec, _ js: JsAny) throws { + var prim = prim + let obj = try js.castAsObject() + let spec: String + do { + spec = try obj["spec", errorMessage: "readPrim"].castAsString() + } catch where prim.GetPath().IsAbsoluteRootPath() { + spec = "" + } + + if spec == "def" { + prim.SetSpecifier(.SdfSpecifierDef) + } else if spec == "over" { + prim.SetSpecifier(.SdfSpecifierOver) + } else if spec == "class" { + prim.SetSpecifier(.SdfSpecifierClass) + } else { + if !prim.GetPath().IsAbsoluteRootPath() { + throw JsDecodingError.unknownSpecifier(spec, prim.GetPath()) + } + } + + // LIVERPS + if prim.GetPath().IsAbsoluteRootPath() { + if let x = obj["subLayers"] { + try layer.SetSubLayerPaths(extractSdfListProxy(pxr.SdfSubLayerProxy.self, x, extractString)) + } + + if let x = obj["subLayerOffsets"] { + let offsets = try extractSdfLayerOffsetVector(x) + for i in 0.. + // is specified as int[] instead of int64[] as expected by the UsdGeomPointInstancer schema. + // If we set the type before decoding attributes, trying to set the type of attributes will fail. + // By setting the type at the end, we can handle this slightly-incorrect file in a lossless manner + + if let x = try obj["type"]?.castAsString(), !x.isEmpty { + prim.SetTypeName(std.string(x)) + } + } + + if let x = obj["propertyOrder"] { + let propertyOrder = try extractTfTokenVector(x) + if !propertyOrder.empty() { + prim.SetPropertyOrder(propertyOrder) + } + } + + if let x = obj["nameChildrenOrder"] { + let nameChildrenOrder = try extractTfTokenVector(x) + if !nameChildrenOrder.empty() { + prim.SetNameChildrenOrder(nameChildrenOrder) + } + } + + // Similar to setting type at the end, set metadata at the end. + // Metadata can include API Schemas, which can e.g. make attributes + // be uniform when they weren't authored as such (technically out of spec + // with the API schema). See lossless-attr-collection-api.usda + if let x = obj["metadata"] { + try readMetadata(x, pxr.SdfSpec(prim)) + } +} +func writePrim(_ prim: pxr.SdfPrimSpec) throws -> JsAny { + var result = [String : JsAny]() + result["name"] = .string(String(prim.GetName())) + if prim.GetSpecType() != .SdfSpecTypePseudoRoot { + switch prim.GetSpecifier() { + case .SdfSpecifierDef: result["spec"] = "def" + case .SdfSpecifierOver: result["spec"] = "over" + case .SdfSpecifierClass: result["spec"] = "class" + default: fatalError("Prim '\(prim.GetPath())' has specifier \(prim.GetSpecifier())") + } + } + if !prim.GetTypeName().IsEmpty() { + result["type"] = .string(String(prim.GetTypeName())) + } + + result.insert(at: "metadata", ifIsNonEmptyContainer: try writeMetadata(pxr.SdfSpec(prim))) + + // LIVERPS. Local is handled by GetAttributes, GetRelationships, and GetNameChildren + if prim.GetSpecType() == .SdfSpecTypePseudoRoot && Overlay.Dereference(prim.GetLayer()).GetNumSubLayerPaths() != 0 { + result["subLayers"] = try writeSdfListProxy(Overlay.Dereference(prim.GetLayer()).GetSubLayerPaths(), writeString) + if let offsets = writeSubLayerOffsets(Overlay.Dereference(prim.GetLayer()).GetSubLayerOffsets()) { + result.insert(at: "subLayerOffsets", ifIsNonEmptyContainer: offsets) + } + } + if prim.HasInheritPaths() { + result["inherits"] = try writeSdfListEditorProxy(prim.GetInheritPathList(), writeSdfPath) + } + if prim.HasVariantSetNames() { + result["variantSetNames"] = try writeSdfListEditorProxy(prim.GetVariantSetNameList(), writeString) + } + result.insert(at: "variantSelections", ifIsNonEmptyContainer: writeVariantSelections(prim.GetVariantSelections())) + result.insert(at: "variantSets", ifIsNonEmptyContainer: try writeVariantSets(prim.GetVariantSets())) + if prim.HasRelocates() { + result["relocates"] = writePrimRelocates(prim.GetRelocates()) + } + if prim.GetSpecType() == .SdfSpecTypePseudoRoot && Overlay.Dereference(prim.GetLayer()).HasRelocates() { + result["relocates"] = writeLayerRelocates(Overlay.Dereference(prim.GetLayer()).GetRelocates()) + } + + if prim.HasReferences() { + result["references"] = try writeSdfListEditorProxy(prim.GetReferenceList(), writeSdfReference) + } + if prim.HasPayloads() { + result["payloads"] = try writeSdfListEditorProxy(prim.GetPayloadList(), writeSdfPayload) + } + if prim.HasSpecializes() { + result["specializes"] = try writeSdfListEditorProxy(prim.GetSpecializesList(), writeSdfPath) + } + + let attrs = try prim.GetAttributes().map { try writeAttribute($0.pointeeOrThrow) } + result.insert(at: "attributes", ifIsNonEmptyContainer: .array(attrs)) + + let rels = try prim.GetRelationships().map { try writeRelationship($0.pointeeOrThrow) } + result.insert(at: "relationships", ifIsNonEmptyContainer: .array(rels)) + + let children = try prim.GetNameChildren().map { try writePrim($0.pointeeOrThrow) } + result.insert(at: "children", ifIsNonEmptyContainer: .array(children)) + + if prim.HasPropertyOrder() { + result["propertyOrder"] = try writeSdfListProxy(prim.GetPropertyOrder(), writeTfToken) + } + + if prim.HasNameChildrenOrder() { + result["nameChildrenOrder"] = try writeSdfListProxy(prim.GetNameChildrenOrder(), writeTfToken) + } + + return .object(result) +} + +func readAttribute(_ layer: pxr.SdfLayer, _ path: pxr.SdfPath, _ js: JsAny) throws { + let obj = try js.castAsObject() + + // extractTypeHint might emit an error if there's an unknown type hint, + // but we know how to handle it. + let type = try Overlay.withTfErrorMark { m in + let type = try extractTypeHint(js) + m.Clear() + return type + } + + var custom = false + if let x = obj["custom"] { + custom = try x.castAsBool() + } + + var variability = Overlay.SdfVariabilityVarying + if let x = obj["variability"] { + variability = pxr.SdfVariability(rawValue: UInt32(try x.castAsInt())) + } + + var attr = try pxr.SdfCreatePrimAttributeInLayer(Overlay.TfWeakPtr(layer), path, type.valueTypeName, variability, custom).pointeeOrThrow + if !Bool(type.valueTypeName) { + // This could be PointIndex or PointIndex[], which we can't create a SdfValueTypeName for + attr.SetField(.SdfFieldKeys.TypeName, pxr.VtValue(pxr.TfToken(type.otherTypeName))) + } + + var defaultValue = type + if let x = obj["default"] { + try extractValueWithTypeHint(&defaultValue, x) + } + + if !defaultValue.value.IsEmpty() { + guard attr.SetField(.SdfFieldKeys.Default, defaultValue.value) else { + throw JsDecodingError.failedToSetDefaultAttributeValue(String(attr.GetTypeName().GetAsToken()), path, defaultValue.value) + } + } + + if let x = obj["timesamples"] { + let timeSamples = try extractTimeCodeValueMapWithTypeHint(x, type) + for kvPair in timeSamples { + attr.SetTimeSample(kvPair.first, kvPair.second) + } + + if timeSamples.empty() { + // empty-timesamples.usda. If we encoded an empty time sample map, + // the above for loop will be empty, but we still want to set the TimeSamples field + + attr.SetField(.SdfFieldKeys.TimeSamples, pxr.VtValue(pxr.SdfTimeSampleMap())) + } + } + + if let x = obj["connections"] { + try extractSdfListEditorProxy(x, attr.GetConnectionPathList(), extractSdfPath) + } + + if let x = obj["spline"] { + attr.SetSpline(try extractTsSpline(x, type.valueTypeName)) + } + + if let x = obj["displayUnit"] { + attr.SetDisplayUnit(try extractTfEnum(x)) + } + + if let x = obj["metadata"] { + try readMetadata(x, pxr.SdfSpec(attr)) + } +} +func writeAttribute(_ attr: pxr.SdfAttributeSpec) throws -> JsAny { + var result = [String : JsAny]() + + result["name"] = .string(String(attr.GetName())) + var type = TypedValue(typeName: attr.GetTypeName()) + result["type"] = writeTypeHint(type) + if attr.IsCustom() { + result["custom"] = true + } + result["variability"] = .int(Int(attr.GetVariability().rawValue)) + + type.value = attr.GetDefaultValue() + if !attr.GetDefaultValue().IsEmpty() { + result["default"] = try writeValueWithoutTypeHint(type) + } + + // Check if we have a field instead of GetNumTimeSamples() != 0 for + // empty-timesamples.usda + if attr.HasField(.SdfFieldKeys.TimeSamples) { + result["timesamples"] = try writeTimeCodeValueMapWithoutTypeHint(attr.GetTimeSampleMap(), type) + } + + if attr.HasConnectionPaths() { + result["connections"] = try writeSdfListEditorProxy(attr.GetConnectionPathList(), writeSdfPath) + } + + if attr.HasSpline() { + result["spline"] = try writeTsSpline(attr.GetSpline()) + } + + if attr.HasDisplayUnit() { + result["displayUnit"] = writeTfEnum(attr.GetDisplayUnit()) + } + + result.insert(at: "metadata", ifIsNonEmptyContainer: try writeMetadata(pxr.SdfSpec(attr))) + + return .object(result) +} + +func readRelationship(_ layer: pxr.SdfLayer, _ path: pxr.SdfPath, _ js: JsAny) throws { + let obj = try js.castAsObject() + + var custom = false + if let x = obj["custom"] { + custom = try x.castAsBool() + } + + var variability = Overlay.SdfVariabilityVarying + if let x = obj["variability"] { + variability = pxr.SdfVariability(rawValue: UInt32(try x.castAsInt())) + } + + var rel = try pxr.SdfCreateRelationshipInLayer(Overlay.TfWeakPtr(layer), path, variability, custom).pointeeOrThrow + + if let x = obj["targets"] { + try extractSdfListEditorProxy(x, rel.GetTargetPathList(), extractSdfPath) + } + + if let x = obj["default"] { + let defaultValue = try extractTypeHintAndValue(x) + rel.SetDefaultValue(defaultValue.value) + } + + if let x = obj["metadata"] { + try readMetadata(x, pxr.SdfSpec(rel)) + } +} +func writeRelationship(_ rel: pxr.SdfRelationshipSpec) throws -> JsAny { + var result = [String : JsAny]() + result["name"] = .string(String(rel.GetName())) + if rel.IsCustom() { + result["custom"] = true + } + result["targets"] = try writeSdfListEditorProxy(rel.GetTargetPathList(), writeSdfPath) + + + result["variability"] = .int(Int(rel.GetVariability().rawValue)) + + if rel.HasDefaultValue() { + result["default"] = try writeTypeHintAndValue(.init(vtValue: rel.GetDefaultValue())) + } + + result.insert(at: "metadata", ifIsNonEmptyContainer: try writeMetadata(pxr.SdfSpec(rel))) + + return .object(result) +} + +// Note: VariantSpec and VariantSetSpec are handled in LIVERPSSerialization diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/FileFormat.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/FileFormat.swift new file mode 100644 index 0000000000..33a33f3a87 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/FileFormat.swift @@ -0,0 +1,111 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD + +public typealias pxr = pxrInternal_v0_26_8__pxrReserved__ + +@SWIFTUSD_PLUGIN +final class SdfJsonFileFormat: Overlay.SdfFileFormatSubclass { + func CanRead(_ file: std.string) -> CBool { + let ext = pxr.TfGetExtension(file) + if ext != GetFormatId() { + return false + } + return true + } + + func _read(_ layer: pxr.SdfLayer?, _ d: Data) -> Bool { + let myLayer = Overlay.Dereference(pxr.SdfLayer.CreateAnonymous("", .init())) + + do { + try readLayer(myLayer, d) + } catch { + TF_RUNTIME_ERROR(std.string("Error while reading layer: \(error)")) + return false + } + + layer?.TransferContent(Overlay.TfWeakPtr(myLayer)) + return true + } + + func Read(_ layer: pxr.SdfLayer?, _ resolvedPath: std.string, _ metadataOnly: CBool) -> CBool { + let asset = Overlay.ArGetResolver().OpenAsset(pxr.ArResolvedPath(resolvedPath)) + guard Bool(asset) else { return false } + let buflen = asset.GetSize() + let buf = asset.GetBuffer() + let data = withExtendedLifetime((asset, buf)) { + if let bufPointer = buf.__getUnsafe() { + Data(bytes: bufPointer, count: buflen) + } else { + Data() + } + } + + return _read(layer, data) + } + + override func WriteToFile(_ layer: pxr.SdfLayer, _ filePath: std.string, _ comment: std.string, _ args: pxr.SdfFileFormat.FileFormatArguments) -> CBool { + var asset = Overlay.ArGetResolver().OpenAssetForWrite(pxr.ArResolvedPath(filePath), .Replace) + guard Bool(asset) else { + TF_RUNTIME_ERROR("Couldn't OpenAssetForWrite(\(filePath))") + return false + } + + do { + let data = try writeLayer(layer, comment) + let writeSucceeded = data.withUnsafeBytes { + asset.Write($0.baseAddress, $0.count, 0) + } + guard writeSucceeded != 0 else { + TF_RUNTIME_ERROR("ArWritableAsset->Write failed") + return false + } + return asset.Close() + } catch { + TF_RUNTIME_ERROR(std.string("Error while encoding layer: \(error)")) + return false + } + } + + override func SaveToFile(_ layer: pxr.SdfLayer, _ filePath: std.string, _ comment: std.string, _ args: pxr.SdfFileFormat.FileFormatArguments) -> CBool { + WriteToFile(layer, filePath, comment, args) + } + + override func ReadFromString(_ layer: pxr.SdfLayer?, _ str: std.string) -> CBool { + _read(layer, Data(String(str).utf8)) + } + + override func WriteToString(_ layer: pxr.SdfLayer, _ str: UnsafeMutablePointer?, _ comment: std.string) -> CBool { + do { + let data = try writeLayer(layer, comment) + str?.pointee = std.string(String(data: data, encoding: .utf8)) + return true + } catch { + TF_RUNTIME_ERROR(std.string("Error while encoding layer: \(error)")) + return false + } + } + + init() { + super.init("json", "1.0", "usd", "json") + } +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/FundamentalTypes.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/FundamentalTypes.swift new file mode 100644 index 0000000000..352670bc58 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/FundamentalTypes.swift @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation + +func extractString(_ x: JsAny) throws -> std.string { + std.string(try x.castAsString()) +} +func writeString(_ x: std.string) -> JsAny { + .string(String(x)) +} + +func extractLongLong(_ x: JsAny) throws -> Int64 { + Int64(try x.castAsInt()) +} +func writeLongLong(_ x: Int64) -> JsAny { + .int(Int(x)) +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/JsAny.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/JsAny.swift new file mode 100644 index 0000000000..c06d49a8a0 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/JsAny.swift @@ -0,0 +1,247 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation + +// pxr::JsValue uses const&'s for performance where possible +// in C++, which don't get imported super cleanly into Swift. +// Instead, we implement our own "JsAny" type, with good +// Swift ergnomics +indirect enum JsAny: Equatable, Codable { + case object([String : JsAny]) + case array([JsAny]) + case string(String) + case number(Double) + case bool(Bool) + case null + + static func encodeToData(_ x: JsAny) throws -> Data { + let encoder = JSONEncoder() + encoder.nonConformingFloatEncodingStrategy = .convertToString(positiveInfinity: "Infinity", negativeInfinity: "-Infinity", nan: "NaN") + return try encoder.encode(x) + } + + static func decodeFromData(_ d: Data) throws -> JsAny { + let decoder = JSONDecoder() + decoder.nonConformingFloatDecodingStrategy = .convertFromString(positiveInfinity: "Infinity", negativeInfinity: "-Infinity", nan: "NaN") + return try decoder.decode(JsAny.self, from: d) + } + + func encode(to encoder: Encoder) throws { + switch self { + case .object(let x): try x.encode(to: encoder) + case .array(let x): try x.encode(to: encoder) + case .string(let x): try x.encode(to: encoder) + case .number(let x): try x.encode(to: encoder) + case .bool(let x): try x.encode(to: encoder) + case .null: + var c = encoder.singleValueContainer() + try c.encodeNil() + } + } + + init(from decoder: Decoder) throws { + let c = try decoder.singleValueContainer() + if let x = try? c.decode([String : JsAny].self) { + self = .object(x); return + } else if let x = try? c.decode(String.self) { + self = .string(x); return + } else if let x = try? c.decode(Double.self) { + self = .number(x); return + } else if let x = try? c.decode(Bool.self) { + self = .bool(x); return + } else if c.decodeNil() { + self = .null; return + } else if let x = try? c.decode([JsAny].self) { + self = .array(x); return + } + + throw DecodingError.typeMismatch(JsAny.self, .init(codingPath: decoder.codingPath, debugDescription: "Couldn't determine JsAny concrete type")) + } + + enum Discriminant { + case object + case array + case string + case number + case bool + case null + } + + var discriminant: Discriminant { + switch self { + case .object: .object + case .array: .array + case .string: .string + case .number: .number + case .bool: .bool + case .null: .null + } + } + + struct CastError: Error { + var source: Discriminant + var target: Discriminant + var file: String + var line: Int + + init(from source: Discriminant, to target: Discriminant, + file: String, line: Int) { + self.source = source + self.target = target + self.file = file + self.line = line + } + } + + struct MissingKeyError: Error { + var key: String + var errorMessage: String + var file: String + var line: Int + } + + var isObject: Bool { discriminant == .object } + var isArray: Bool { discriminant == .array } + var isString: Bool { discriminant == .string } + var isNumber: Bool { discriminant == .number } + var isBool: Bool { discriminant == .bool } + var isNull: Bool { discriminant == .null } + + var isNonEmptyContainer: Bool { + switch self { + case .object(let x) where !x.isEmpty: true + case .array(let x) where !x.isEmpty: true + default: false + } + } + + static func int(_ x: Int) -> JsAny { + .number(Double(x)) + } + + var asObject: [String : JsAny]? { + if case let .object(x) = self { x } else { nil } + } + var asArray: [JsAny]? { + if case let .array(x) = self { x } else { nil } + } + var asString: String? { + if case let .string(x) = self { x } else { nil } + } + var asNumber: Double? { + if case let .number(x) = self { x } else { nil } + } + var asInt: Int? { + asNumber.map { Int($0) } + } + var asBool: Bool? { + if case let .bool(x) = self { x } else { nil } + } + var asNull: Void? { + if case .null = self { () } else { nil } + } + + private func unwrapOrThrow(_ x: T?, _ e: E) throws(E) -> T { + if let x { return x } + else { throw e } + } + + func castAsObject(_ file: String = #fileID, _ line: Int = #line) throws(CastError) -> [String : JsAny] { + try unwrapOrThrow(asObject, CastError(from: discriminant, to: .object, file: file, line: line)) + } + + func castAsArray(_ file: String = #fileID, _ line: Int = #line) throws(CastError) -> [JsAny] { + try unwrapOrThrow(asArray, CastError(from: discriminant, to: .array, file: file, line: line)) + } + + func castAsString(_ file: String = #fileID, _ line: Int = #line) throws(CastError) -> String { + try unwrapOrThrow(asString, CastError(from: discriminant, to: .string, file: file, line: line)) + } + + func castAsNumber(_ file: String = #fileID, _ line: Int = #line) throws(CastError) -> Double { + try unwrapOrThrow(asNumber, CastError(from: discriminant, to: .number, file: file, line: line)) + } + + func castAsInt(_ file: String = #fileID, _ line: Int = #line) throws(CastError) -> Int { + try unwrapOrThrow(asInt, CastError(from: discriminant, to: .number, file: file, line: line)) + } + + func castAsBool(_ file: String = #fileID, _ line: Int = #line) throws(CastError) -> Bool { + try unwrapOrThrow(asBool, CastError(from: discriminant, to: .bool, file: file, line: line)) + } + + func castAsNull(_ file: String = #fileID, _ line: Int = #line) throws(CastError) -> Void { + try unwrapOrThrow(asNull, CastError(from: discriminant, to: .null, file: file, line: line)) + } +} + +extension [String : JsAny] { + subscript(key: String, errorMessage errorMessage: String, file: String = #fileID, line: Int = #line) -> JsAny { + get throws(JsAny.MissingKeyError) { + guard let x = self[key] else { + throw JsAny.MissingKeyError(key: key, errorMessage: errorMessage, file: file, line: line) + } + return x + } + } + + mutating func insert(at key: String, ifIsNonEmptyContainer x: JsAny) { + if x.isNonEmptyContainer { + self[key] = x + } + } +} + +extension JsAny: ExpressibleByDictionaryLiteral { + init(dictionaryLiteral elements: (String, JsAny)...) { + self = .object(.init(uniqueKeysWithValues: elements)) + } +} + +extension JsAny: ExpressibleByArrayLiteral { + init(arrayLiteral: JsAny...) { + self = .array(arrayLiteral) + } +} + +extension JsAny: ExpressibleByStringLiteral { + init(stringLiteral: String) { + self = .string(stringLiteral) + } +} + +extension JsAny: ExpressibleByIntegerLiteral { + init(integerLiteral: Int) { + self = .int(integerLiteral) + } +} + +extension JsAny: ExpressibleByFloatLiteral { + init(floatLiteral: Double) { + self = .number(floatLiteral) + } +} + +extension JsAny: ExpressibleByBooleanLiteral { + init(booleanLiteral: Bool) { + self = .bool(booleanLiteral) + } +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/JsDecodingError.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/JsDecodingError.swift new file mode 100644 index 0000000000..7e43744d53 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/JsDecodingError.swift @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD + +enum JsDecodingError: Error { + case typeHintWasEmpty + case mismatchedVecLength + case mismatchedMatLength + case decodingTypeFailure(_ typeHint: String) + case unknownTypeName(pxr.TfToken, String) + case timeSampleMapKeyWasntDouble(String) + case sdfAnimationBlockDeserializationError + case sdfUnregisteredValueDeserializationError + case jsAnyParseWasNull + case failedToSetMetadataOnPrim(String, pxr.SdfPath, pxr.VtValue) + case unknownSpecifier(String, pxr.SdfPath) + case failedToSetDefaultAttributeValue(String, pxr.SdfPath, pxr.VtValue) + case layerRelocatesEntryInvalid + case variantSetSuperObjectInvalid + case invalidSdfLayerOffset + case unknownTypeNameAndValue(pxr.TfToken, String, std.string, String) + case sdfPathSdfUnregisteredValueWasntHoldingAString +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/LIVERPSSerialization.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/LIVERPSSerialization.swift new file mode 100644 index 0000000000..3602488c13 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/LIVERPSSerialization.swift @@ -0,0 +1,312 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD +import TemporaryImplementations_Cxx +import TemporaryImplementations_Swift + +func writeSdfListProxy(_ proxy: T, _ convertElement: (T.value_type) throws -> JsAny) throws -> JsAny where T: Overlay._SdfListProxyProtocol { + var result = [JsAny]() + for element in proxy { + result.append(try convertElement(element)) + } + + return .array(result) +} + +func extractSdfListProxy(_: T.Type, _ js: JsAny, _ convertElement: (JsAny) throws -> T.value_type) throws -> T.value_vector_type where T: Overlay._SdfListProxyProtocol { + var result = T.value_vector_type() + + for x in try js.castAsArray() { + result.push_back(try convertElement(x)) + } + + return result +} + +func writeSdfListEditorProxy(_ proxy: T, _ convertElement: (T.value_type) throws -> JsAny) throws -> JsAny where T: Overlay._SdfListEditorProxyProtocol { + var result = [String : JsAny]() + + func handleIndividualListProxy(_ list: T.ListProxy, _ key: String) throws { + if !list.empty() { + result[key] = try writeSdfListProxy(list, convertElement) + } + } + + try handleIndividualListProxy(proxy.GetExplicitItems(), "explicit") + try handleIndividualListProxy(proxy.GetAddedItems(), "add") + try handleIndividualListProxy(proxy.GetPrependedItems(), "prepend") + try handleIndividualListProxy(proxy.GetAppendedItems(), "append") + try handleIndividualListProxy(proxy.GetDeletedItems(), "delete") + try handleIndividualListProxy(proxy.GetOrderedItems(), "order") + + if result.isEmpty && proxy.IsExplicit() { + result["explicit"] = [] + } + + return .object(result) +} + +func extractSdfListEditorProxy(_ js: JsAny, _ proxy: T, _ convertElement: (JsAny) throws -> T.value_type) throws where T: Overlay._SdfListEditorProxyProtocol { + var proxy = proxy + let obj = try js.castAsObject() + + func handleIndividualListProxy(_ list: T.ListProxy, _ key: String) throws { + var list = list + guard let x = obj[key] else { return } + let toInsert = try extractSdfListProxy(T.ListProxy.self, x, convertElement) + for y in toInsert { + list.push_back(y) + } + } + + try handleIndividualListProxy(proxy.GetExplicitItems(), "explicit") + try handleIndividualListProxy(proxy.GetAddedItems(), "add") + try handleIndividualListProxy(proxy.GetPrependedItems(), "prepend") + try handleIndividualListProxy(proxy.GetAppendedItems(), "append") + try handleIndividualListProxy(proxy.GetDeletedItems(), "delete") + try handleIndividualListProxy(proxy.GetOrderedItems(), "order") + + if obj["explicit"] != nil && !proxy.HasKeys() { + proxy.ClearEditsAndMakeExplicit() + } +} + +func writeSdfListOp(_ proxy: T, _ convertElement: (T.value_type) throws -> JsAny) throws -> JsAny where T: Overlay._SdfListOpProtocol { + var result = [String : JsAny]() + + func writeIndividualArray(_ items: T.value_vector_type, _ key: String) throws { + var arr = [JsAny]() + for x in items { + arr.append(try convertElement(x)) + } + if !arr.isEmpty { + result[key] = .array(arr) + } + } + + try writeIndividualArray(proxy.GetExplicitItems(), "explicit") + try writeIndividualArray(proxy.GetAddedItems(), "add") + try writeIndividualArray(proxy.GetPrependedItems(), "prepend") + try writeIndividualArray(proxy.GetAppendedItems(), "append") + try writeIndividualArray(proxy.GetDeletedItems(), "delete") + try writeIndividualArray(proxy.GetOrderedItems(), "order") + + if result.isEmpty && proxy.IsExplicit() { + result["explicit"] = [] + } + + return .object(result) +} + +func extractSdfListOp(_: T.Type, _ js: JsAny, _ convertElement: (JsAny) throws -> T.value_type) throws -> T where T: Overlay._SdfListOpProtocol { + var result = T() + let obj = try js.castAsObject() + + func extractIndividualArray(_ jsKey: String, _ setter: (T.value_vector_type) -> ()) throws { + guard let x = obj[jsKey] else { return } + var result = T.value_vector_type() + for y in try x.castAsArray() { + result.push_back(try convertElement(y)) + } + + setter(result) + } + + try extractIndividualArray("explicit") { result.SetExplicitItems($0, nil) } + try extractIndividualArray("add") { result.SetAddedItems($0) } + try extractIndividualArray("prepend") { result.SetPrependedItems($0, nil) } + try extractIndividualArray("append") { result.SetAppendedItems($0, nil) } + try extractIndividualArray("delete") { result.SetDeletedItems($0, nil) } + try extractIndividualArray("order") { result.SetOrderedItems($0) } + + return result +} + +func extractSdfLayerOffset(_ js: JsAny) throws -> pxr.SdfLayerOffset { + let arr = try js.castAsArray() + guard arr.count == 2 else { + throw JsDecodingError.invalidSdfLayerOffset + } + + return pxr.SdfLayerOffset(try arr[0].castAsNumber(), + try arr[1].castAsNumber()) +} +func writeSdfLayerOffset(_ x: pxr.SdfLayerOffset) -> JsAny { + [ + .number(x.GetOffset()), + .number(x.GetScale()) + ] +} + +func extractSdfLayerOffsetVector(_ js: JsAny) throws -> pxr.SdfLayerOffsetVector { + let arr = try js.castAsArray() + var result = pxr.SdfLayerOffsetVector() + for x in arr { + result.push_back(try extractSdfLayerOffset(x)) + } + return result +} +func writeSubLayerOffsets(_ offsets: pxr.SdfLayerOffsetVector) -> JsAny? { + var result = [JsAny]() + var hadNonIdentity = false + for x in offsets { + hadNonIdentity = hadNonIdentity || !x.IsIdentity() + result.append(writeSdfLayerOffset(x)) + } + + return hadNonIdentity ? .array(result) : nil +} + +func extractPrimRelocates(_ js: JsAny, _ prim: pxr.SdfPrimSpec) throws { + var prim = prim + let obj = try js.castAsObject() + + var proxy = prim.GetRelocates() + guard let x = obj["relocates"] else { return } + for (k, v) in try x.castAsObject() { + proxy.insert(.init(first: pxr.SdfPath(k), second: pxr.SdfPath(try v.castAsString()))) + } + if try x.castAsObject().isEmpty { + prim.SetField(.SdfFieldKeys.Relocates, pxr.VtValue(pxr.SdfRelocatesMap())) + } +} + +func writePrimRelocates(_ list: pxr.SdfRelocatesMapProxy) -> JsAny { + var result = [String : JsAny]() + for x in list { + result[String(x.first)] = .string(String(x.second)) + } + return .object(result) +} + +func extractLayerRelocates(_ layer: pxr.SdfLayer, _ js: JsAny) throws { + let obj = try js.castAsObject() + guard let x = obj["relocates"] else { return } + + var relocates = pxr.SdfRelocates() + for entry in try x.castAsArray() { + let subArr = try entry.castAsArray() + guard subArr.count == 2 else { + throw JsDecodingError.layerRelocatesEntryInvalid + } + relocates.push_back(.init(first: pxr.SdfPath(try subArr[0].castAsString()), + second: pxr.SdfPath(try subArr[1].castAsString()))) + } + if !relocates.empty() { + layer.SetRelocates(relocates) + } +} +func writeLayerRelocates(_ list: pxr.SdfRelocates) -> JsAny { + var result = [JsAny]() + for x in list { + result.append([ + .string(String(x.first)), + .string(String(x.second)) + ]) + } + return .array(result) +} + +func extractVariantSelections(_ prim: pxr.SdfPrimSpec, _ js: JsAny) throws { + var prim = prim + for (k, v) in try js.castAsObject() { + prim.SetVariantSelection(std.string(k), std.string(try v.castAsString())) + } +} +func writeVariantSelections(_ selections: pxr.SdfVariantSelectionProxy) -> JsAny { + guard Bool(selections) && !selections.empty() else { return [] } + + var result = [String : JsAny]() + for x in selections { + result[String(x.first)] = .string(String(x.second)) + } + + return .object(result) +} + +func readVariantSets(_ layer: pxr.SdfLayer, _ path: pxr.SdfPath, _ js: JsAny) throws { + let arr = try js.castAsArray() + + let prim = try layer.GetPrimAtPath(path).pointeeOrThrow + + for variantSetSuperObjectElement in arr { + let variantSetSuperObject = try variantSetSuperObjectElement.castAsObject() + + guard variantSetSuperObject.count == 2 else { + throw JsDecodingError.variantSetSuperObjectInvalid + } + let variantSetName = try variantSetSuperObject["name", errorMessage: "Variant set super object"].castAsString() + + let jsVariantSet = try variantSetSuperObject["contents", errorMessage: "Variant set super object"] + + + let vsets = prim.GetVariantSets() + + let firstMatch = vsets.first(where: { $0.first == std.string(variantSetName) }) + let sdfVset: pxr.SdfVariantSetSpec = try firstMatch?.second.pointeeOrThrow ?? pxr.SdfVariantSetSpec.New(pxr.SdfPrimSpecHandle(prim), std.string(variantSetName)).pointeeOrThrow + + try readVariantSetSpec(jsVariantSet, sdfVset) + } +} + + +func writeVariantSets(_ sets: pxr.SdfVariantSetsProxy) throws -> JsAny { + guard Bool(sets) && !sets.empty() else { return [] } + + var result = [JsAny]() + + for x in sets { + result.append([ + "name" : .string(String(x.first)), + "contents" : try writeVariantSetSpec(x.second.pointeeOrThrow), + ]) + } + + return .array(result) +} + +func readVariantSetSpec(_ js: JsAny, _ variantSet: pxr.SdfVariantSetSpec) throws { + let jsVariantSet = try js.castAsObject() + + for (k, v) in jsVariantSet { + let variantView = variantSet.GetVariants() + + let firstMatch = try variantView.first(where: { try $0.pointeeOrThrow.GetName() == std.string(k) }) + // Important: Use variantSet->GetOwner()->GetPath() and not variantSet->GetPath().StripAllVariantSelections(), + // because the latter does not handle nested variant sets correctly but the former does. + let ownerPath = try variantSet.GetOwner().pointeeOrThrow.GetPath() + let vspec = try firstMatch?.pointeeOrThrow ?? pxr.SdfCreateVariantInLayer(variantSet.GetLayer(), ownerPath, variantSet.GetName(), std.string(k)).pointeeOrThrow + + + let jsVspecPrimSpec = try v.castAsObject() + try readPrim(Overlay.Dereference(variantSet.GetLayer()), vspec.GetPrimSpec().pointeeOrThrow, .object(jsVspecPrimSpec)) + } +} +func writeVariantSetSpec(_ variantSet: pxr.SdfVariantSetSpec) throws -> JsAny { + var result = [String : JsAny]() + + for variant in variantSet.GetVariants() { + try result[String(variant.pointeeOrThrow.GetName())] = try writePrim(variant.pointeeOrThrow.GetPrimSpec().pointeeOrThrow) + } + + return .object(result) +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/ProxyTypesSequenceWorkarounds.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/ProxyTypesSequenceWorkarounds.swift new file mode 100644 index 0000000000..d6e85703e4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/ProxyTypesSequenceWorkarounds.swift @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD +import TemporaryImplementations_Cxx +import TemporaryImplementations_Swift + +// These proxy types backing LIVERPS arcs should conform to Sequence, and that conformance should live in SwiftUsd, +// but when trying to do so, we run into: +// rdar://187057230 (Trying to use a `for` loop to iterate over a C++ type conformed to Sequence causes "Failure to produce diagnostic for expression" across a module boundary) +// Workaround: Put the conformance in the module that uses it +// +// There's nothing particularly interesting here, this is just what it takes sometimes to conform C++ types to the right Swift protocols. + + +extension pxr.SdfVariantSetsProxy: Sequence, CxxSequence { + public typealias RawIterator = const_iterator + public typealias Element = const_iterator.value_type +} +extension pxr.SdfVariantSetsProxy.const_iterator: UnsafeCxxInputIterator { + public static func ==(lhs: Self, _ rhs: Self) -> Bool { + __Overlay.manual_operatorEqualsEquals(lhs, rhs) + } +} + +extension pxr.SdfRelocatesMapProxy: Sequence, CxxSequence, CxxDictionary { + public typealias RawIterator = const_iterator + public typealias RawMutableIterator = iterator + + public typealias Key = pxr.SdfPath + public typealias Value = pxr.SdfPath + public typealias Size = size_type + public typealias InsertionResult = Overlay.SdfRelocatesMapProxy_Iterator_Bool_Pair + public typealias Element = value_type + + public mutating func __insertUnsafe(_ element: Self.Element) -> Self.InsertionResult { + __Overlay.insert(&self, element) + } + + public mutating func __eraseUnsafe(_ it: Self.iterator) -> Self.iterator { + __Overlay.erase(&self, it) + } +} + +extension pxr.SdfRelocatesMapProxy.const_iterator: UnsafeCxxInputIterator { + public static func ==(lhs: Self, _ rhs: Self) -> Bool { + __Overlay.manual_operatorEqualsEquals(lhs, rhs) + } +} +extension pxr.SdfRelocatesMapProxy.iterator: UnsafeCxxMutableInputIterator { + public var pointee: pxr.SdfRelocatesMapProxy.Element { + get { __Overlay.operatorStar(self) } + set { __Overlay.operatorStarSet(&self, newValue) } + } + + public typealias Pointee = pxr.SdfRelocatesMapProxy.Element + + public static func ==(lhs: Self, _ rhs: Self) -> Bool { + __Overlay.manual_operatorEqualsEquals(lhs, rhs) + } +} + +extension pxr.SdfVariantSelectionProxy: Sequence, CxxSequence, CxxDictionary { + public typealias RawIterator = const_iterator + public typealias RawMutableIterator = iterator + + public typealias Key = std.string + public typealias Value = std.string + public typealias Size = size_type + public typealias InsertionResult = Overlay.SdfVariantSelectionProxy_Iterator_Bool_Pair + public typealias Element = value_type + + public mutating func __insertUnsafe(_ element: Self.Element) -> Self.InsertionResult { + __Overlay.insert(&self, element) + } + + public mutating func __eraseUnsafe(_ it: Self.iterator) -> Self.iterator { + __Overlay.erase(&self, it) + } +} + +extension pxr.SdfVariantSelectionProxy.const_iterator: UnsafeCxxInputIterator { + public static func ==(lhs: Self, _ rhs: Self) -> Bool { + __Overlay.manual_operatorEqualsEquals(lhs, rhs) + } +} +extension pxr.SdfVariantSelectionProxy.iterator: UnsafeCxxMutableInputIterator { + public var pointee: pxr.SdfVariantSelectionProxy.Element { + get { __Overlay.operatorStar(self) } + set { __Overlay.operatorStarSet(&self, newValue) } + } + + public typealias Pointee = pxr.SdfVariantSelectionProxy.Element + + public static func ==(lhs: Self, _ rhs: Self) -> Bool { + __Overlay.manual_operatorEqualsEquals(lhs, rhs) + } +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/SdfSerialization.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/SdfSerialization.swift new file mode 100644 index 0000000000..f1223b5dad --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/SdfSerialization.swift @@ -0,0 +1,154 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD + +func extractSdfAnimationBlock(_ js: JsAny) throws -> pxr.SdfAnimationBlock { + guard js == ["AnimationBlock" : .null] else { + throw JsDecodingError.sdfAnimationBlockDeserializationError + } + return pxr.SdfAnimationBlock() +} +func writeSdfAnimationBlock(_ x: pxr.SdfAnimationBlock) -> JsAny { + ["AnimationBlock" : .null] +} + +func extractSdfPath(_ js: JsAny) throws -> pxr.SdfPath { + pxr.SdfPath(try js.castAsString()) +} +func writeSdfPath(_ x: pxr.SdfPath) -> JsAny { + .string(String(x)) +} + +func extractSdfUnregisteredValue(_ js: JsAny) throws -> pxr.SdfUnregisteredValue { + let obj = try js.castAsObject() + guard obj.count == 2 else { + throw JsDecodingError.sdfUnregisteredValueDeserializationError + } + + let type = try obj["type", errorMessage: "SdfUnregisteredValue"].castAsString() + + let value = try obj["SdfUnregisteredValue", errorMessage: "SdfUnregisteredValue"] + + if type == "string" { + return pxr.SdfUnregisteredValue(std.string(try value.castAsString())) + } else if type == "VtDictionary" { + return pxr.SdfUnregisteredValue(try extractVtDictionary(value)) + } else if type == "SdfUnregisteredValueListOp" { + let l = try extractSdfListOp(pxr.SdfUnregisteredValueListOp.self, value, extractSdfUnregisteredValue) + return pxr.SdfUnregisteredValue(l) + } else { + throw JsDecodingError.sdfUnregisteredValueDeserializationError + } +} +func writeSdfUnregisteredValue(_ x: pxr.SdfUnregisteredValue) throws -> JsAny { + var copy = x.GetValue() + + if copy.IsHolding(T: std.string.self) { + return [ + "SdfUnregisteredValue" : .string(String(copy.Get() as std.string)), + "type" : "string" + ] + } else if copy.IsHolding(T: pxr.VtDictionary.self) { + return [ + "SdfUnregisteredValue" : try writeVtDictionary(copy.Get() as pxr.VtDictionary), + "type" : "VtDictionary" + ] + } else if copy.IsHolding(T: pxr.SdfUnregisteredValueListOp.self) { + return [ + "SdfUnregisteredValue" : try writeSdfListOp(copy.Get() as pxr.SdfUnregisteredValueListOp, writeSdfUnregisteredValue), + "type" : "SdfUnregisteredValueListOp" + ] + } else { + TF_WARN("Unknown contents of SdfUnregisteredValue") + } + return [:] +} + +func extractSdfReference(_ js: JsAny) throws -> pxr.SdfReference { + let obj = try js.castAsObject() + var result = pxr.SdfReference(std.string(), pxr.SdfPath(), pxr.SdfLayerOffset(0, 1), pxr.VtDictionary()) + + if let x = obj["asset"] { + result.SetAssetPath(std.string(try x.castAsString())) + } + if let x = obj["prim"] { + result.SetPrimPath(try extractSdfPath(x)) + } + if let x = obj["offset"] { + result.SetLayerOffset(try extractSdfLayerOffset(x)) + } + if let x = obj["customData"] { + result.SetCustomData(try extractVtDictionary(x)) + } + + return result +} +func writeSdfReference(_ x: pxr.SdfReference) throws -> JsAny { + var result = [String : JsAny]() + + if !x.GetAssetPath().empty() { + result["asset"] = .string(String(x.GetAssetPath())) + } + if !x.GetPrimPath().IsEmpty() { + result["prim"] = writeSdfPath(x.GetPrimPath()) + } + if !x.GetLayerOffset().IsIdentity() { + result["offset"] = writeSdfLayerOffset(x.GetLayerOffset()) + } + if !x.GetCustomData().empty() { + result["customData"] = try writeVtDictionary(x.GetCustomData()) + } + + return .object(result) +} + +func extractSdfPayload(_ js: JsAny) throws -> pxr.SdfPayload { + let obj = try js.castAsObject() + var result = pxr.SdfPayload(std.string(), pxr.SdfPath(), pxr.SdfLayerOffset(0, 1)) + + if let x = obj["asset"] { + result.SetAssetPath(std.string(try x.castAsString())) + } + if let x = obj["prim"] { + result.SetPrimPath(try extractSdfPath(x)) + } + if let x = obj["offset"] { + result.SetLayerOffset(try extractSdfLayerOffset(x)) + } + + return result +} +func writeSdfPayload(_ x: pxr.SdfPayload) -> JsAny { + var result = [String : JsAny]() + + if !x.GetAssetPath().empty() { + result["asset"] = .string(String(x.GetAssetPath())) + } + if !x.GetPrimPath().IsEmpty() { + result["prim"] = writeSdfPath(x.GetPrimPath()) + } + if !x.GetLayerOffset().IsIdentity() { + result["offset"] = writeSdfLayerOffset(x.GetLayerOffset()) + } + + return .object(result) +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/SdfSpecHandleErgonomics.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/SdfSpecHandleErgonomics.swift new file mode 100644 index 0000000000..cb53ed6c97 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/SdfSpecHandleErgonomics.swift @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD + +// See the note in CoreSpecSerialization.swift + +struct DereferencedInvalidSdfHandleError: Error { + var type: pxr.SdfSpecType +} + +extension pxr.SdfSpecHandle { + var pointeeOrThrow: pxr.SdfSpec { + get throws { + guard Bool(self) else { throw DereferencedInvalidSdfHandleError(type: .SdfSpecTypeUnknown) } + return self.pointee + } + } +} + +extension pxr.SdfPropertySpecHandle { + var pointeeOrThrow: pxr.SdfPropertySpec { + get throws { + guard Bool(self) else { throw DereferencedInvalidSdfHandleError(type: .SdfSpecTypeUnknown) } + return self.pointee + } + } +} + +extension pxr.SdfPrimSpecHandle { + var pointeeOrThrow: pxr.SdfPrimSpec { + get throws { + guard Bool(self) else { throw DereferencedInvalidSdfHandleError(type: .SdfSpecTypePrim) } + return self.pointee + } + } +} + +extension pxr.SdfVariantSetSpecHandle { + var pointeeOrThrow: pxr.SdfVariantSetSpec { + get throws { + guard Bool(self) else { throw DereferencedInvalidSdfHandleError(type: .SdfSpecTypeVariantSet) } + return self.pointee + } + } +} + +extension pxr.SdfVariantSpecHandle { + var pointeeOrThrow: pxr.SdfVariantSpec { + get throws { + guard Bool(self) else { throw DereferencedInvalidSdfHandleError(type: .SdfSpecTypeVariant) } + return self.pointee + } + } +} + +extension pxr.SdfAttributeSpecHandle { + var pointeeOrThrow: pxr.SdfAttributeSpec { + get throws { + guard Bool(self) else { throw DereferencedInvalidSdfHandleError(type: .SdfSpecTypeAttribute) } + return self.pointee + } + } +} + +extension pxr.SdfRelationshipSpecHandle { + var pointeeOrThrow: pxr.SdfRelationshipSpec { + get throws { + guard Bool(self) else { throw DereferencedInvalidSdfHandleError(type: .SdfSpecTypeRelationship) } + return self.pointee + } + } +} + +extension pxr.SdfPseudoRootSpecHandle { + var pointeeOrThrow: pxr.SdfPseudoRootSpec { + get throws { + guard Bool(self) else { throw DereferencedInvalidSdfHandleError(type: .SdfSpecTypePseudoRoot) } + return self.pointee + } + } +} + diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/TfSerialization.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/TfSerialization.swift new file mode 100644 index 0000000000..22d3c94021 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/TfSerialization.swift @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD + +func extractTfToken(_ js: JsAny) throws -> pxr.TfToken { + try pxr.TfToken(js.castAsString()) +} +func writeTfToken(_ x: pxr.TfToken) -> JsAny { + .string(String(x)) +} + +func extractTfTokenVector(_ js: JsAny) throws -> pxr.TfTokenVector { + var result = pxr.TfTokenVector() + for x in try js.castAsArray() { + try result.push_back(extractTfToken(x)) + } + return result +} + +func extractTfEnum(_ js: JsAny) throws -> pxr.TfEnum { + try pxr.TfEnum.GetValueFromFullName(std.string(js.castAsString())) +} +func writeTfEnum(_ x: pxr.TfEnum) -> JsAny { + .string(String(pxr.TfEnum.GetFullName(x))) +} + diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/TsSerialization.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/TsSerialization.swift new file mode 100644 index 0000000000..8850c30e14 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/TsSerialization.swift @@ -0,0 +1,216 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import CxxStdlib +import OpenUSD +import TemporaryImplementations_Cxx +import TemporaryImplementations_Swift + +func extractTsSpline(_ js: JsAny, _ type: pxr.SdfValueTypeName) throws -> pxr.TsSpline { + var result = pxr.TsSpline(type.GetType()) + let obj = try js.castAsObject() + + let curveType = try obj["curveType", errorMessage: "TsSpline"].castAsInt() + result.SetCurveType(pxr.TsCurveType(rawValue: UInt32(curveType))) + + let preExtrapolation = try extractTsExtrapolation(obj["preExtrapolation", errorMessage: "TsSpline"]) + result.SetPreExtrapolation(preExtrapolation) + + let postExtrapolation = try extractTsExtrapolation(obj["postExtrapolation", errorMessage: "TsSpline"]) + result.SetPostExtrapolation(postExtrapolation) + + let loopParams = try extractTsLoopParams(obj["innerLoopParams", errorMessage: "TsSpline"]) + result.SetInnerLoopParams(loopParams) + + let knots = try extractTsKnotMap(obj["knots", errorMessage: "TsSpline"], type) + if !knots.empty() { + // TsSpline::SetKnots checks if the spline's type matches the knot map's type. + // However, empty knot maps return the unknown type, so the comparison erronously fails. + // Arguably, TsSpline::SetKnots shouldn't report an error in this case, but we can + // just not set the knots with empty knot maps. + result.SetKnots(knots) + } + + return result +} +func writeTsSpline(_ x: pxr.TsSpline) throws -> JsAny { + [ + "curveType" : .int(Int(x.GetCurveType().rawValue)), + "preExtrapolation" : writeTsExtrapolation(x.GetPreExtrapolation()), + "postExtrapolation" : writeTsExtrapolation(x.GetPostExtrapolation()), + "innerLoopParams" : writeTsLoopParams(x.GetInnerLoopParams()), + "knots" : try writeTsKnotMap(x.GetKnots()), + ] +} + +func extractTsExtrapolation(_ js: JsAny) throws -> pxr.TsExtrapolation { + var result = pxr.TsExtrapolation() + let obj = try js.castAsObject() + + let mode = try obj["mode", errorMessage: "TsExtrapolation"].castAsInt() + result.mode = pxr.TsExtrapMode(rawValue: UInt32(mode)) + + result.slope = try obj["slope", errorMessage: "TsExtrapolation"].castAsNumber() + + if let x = try obj["loopBoundaryTime"]?.castAsNumber() { + // Starting in Swift 6.3 (or 6.4?), it becomes easier to work with std::optional in Swift thanks to + // https://github.com/swiftlang/swift/commit/26e9907c8a10f79de06360db53778b436acc3dc9, + // but since we want to support before that, we need to handle things ourselves + result.loopBoundaryTime = .init(x) + } else { + result.loopBoundaryTime = nil + } + + return result +} +func writeTsExtrapolation(_ x: pxr.TsExtrapolation) -> JsAny { + var result = [String : JsAny]() + + result["mode"] = .int(Int(x.mode.rawValue)) + result["slope"] = .number(x.slope) + if x.loopBoundaryTime.has_value() { + result["loopBoundaryTime"] = .number(x.loopBoundaryTime.pointee) + } + + return .object(result) +} + +func extractTsLoopParams(_ js: JsAny) throws -> pxr.TsLoopParams { + var result = pxr.TsLoopParams() + let obj = try js.castAsObject() + + result.protoStart = try obj["protoStart", errorMessage: "TsLoopParams"].castAsNumber() + result.protoEnd = try obj["protoEnd", errorMessage: "TsLoopParams"].castAsNumber() + result.numPreLoops = Int32(try obj["numPreLoops", errorMessage: "TsLoopParams"].castAsInt()) + result.numPostLoops = Int32(try obj["numPostLoops", errorMessage: "TsLoopParams"].castAsInt()) + result.valueOffset = try obj["valueOffset", errorMessage: "TsLoopParams"].castAsNumber() + + return result +} +func writeTsLoopParams(_ x: pxr.TsLoopParams) -> JsAny { + [ + "protoStart": .number(x.protoStart), + "protoEnd": .number(x.protoEnd), + "numPreLoops": .int(Int(x.numPreLoops)), + "numPostLoops": .int(Int(x.numPostLoops)), + "valueOffset": .number(x.valueOffset), + ] +} + +func extractTsKnotMap(_ js: JsAny, _ type: pxr.SdfValueTypeName) throws -> pxr.TsKnotMap { + var result = pxr.TsKnotMap() + let arr = try js.castAsArray() + + for x in arr { + result.insert(try extractTsKnot(x, type)) + } + return result +} +func writeTsKnotMap(_ x: pxr.TsKnotMap) throws -> JsAny { + var arr = [JsAny]() + for y in x { + arr.append(try writeTsKnot(y)) + } + return .array(arr) +} + +func extractTsKnot(_ js: JsAny, _ type: pxr.SdfValueTypeName) throws -> pxr.TsKnot { + var result = pxr.TsKnot(type.GetType()) + let obj = try js.castAsObject() + + result.SetTime(try obj["time", errorMessage: "TsKnot"].castAsNumber()) + + let nextInterpolation = try obj["nextInterpolation", errorMessage: "TsKnot"].castAsInt() + result.SetNextInterpolation(pxr.TsInterpMode(rawValue: UInt32(nextInterpolation))) + + var value = TypedValue(typeName: type) + try extractValueWithTypeHint(&value, obj["value", errorMessage: "TsKnot"]) + result.SetValue(value.value) + + if let x = obj["preValue"] { + var preValue = TypedValue(typeName: type) + try extractValueWithTypeHint(&preValue, x) + result.SetPreValue(preValue.value) + } + + result.SetPreTanWidth(try obj["preTanWidth", errorMessage: "TsKnot"].castAsNumber()) + + var preTanSlope = TypedValue(typeName: type) + try extractValueWithTypeHint(&preTanSlope, obj["preTanSlope", errorMessage: "TsKnot"]) + result.SetPreTanSlope(preTanSlope.value) + + let preTanAlgorithm = try obj["preTanAlgorithm", errorMessage: "TsKnot"].castAsInt() + result.SetPreTanAlgorithm(pxr.TsTangentAlgorithm(rawValue: UInt32(preTanAlgorithm))) + + + result.SetPostTanWidth(try obj["postTanWidth", errorMessage: "TsKnot"].castAsNumber()) + + var postTanSlope = TypedValue(typeName: type) + try extractValueWithTypeHint(&postTanSlope, obj["postTanSlope", errorMessage: "TsKnot"]) + result.SetPostTanSlope(postTanSlope.value) + + let postTanAlgorithm = try obj["postTanAlgorithm", errorMessage: "TsKnot"].castAsInt() + result.SetPostTanAlgorithm(pxr.TsTangentAlgorithm(rawValue: UInt32(postTanAlgorithm))) + + if let x = obj["customData"] { + result.SetCustomData(try extractVtDictionary(x)) + } + + return result +} + +func writeTsKnot(_ x: pxr.TsKnot) throws -> JsAny { + var result = [String : JsAny]() + + result["time"] = .number(x.GetTime()) + result["nextInterpolation"] = .int(Int(x.GetNextInterpolation().rawValue)) + + var value = pxr.VtValue() + Overlay.GetValue(x, &value) + result["value"] = try writeValueWithoutTypeHint(TypedValue(vtValue: value)) + + if x.IsDualValued() { + var pre = pxr.VtValue() + Overlay.GetPreValue(x, &pre) + result["preValue"] = try writeValueWithoutTypeHint(TypedValue(vtValue: pre)) + } + + result["preTanWidth"] = .number(x.GetPreTanWidth()) + + var preTanSlope = pxr.VtValue() + Overlay.GetPreTanSlope(x, &preTanSlope) + result["preTanSlope"] = try writeValueWithoutTypeHint(TypedValue(vtValue: preTanSlope)) + + result["preTanAlgorithm"] = .int(Int(x.GetPreTanAlgorithm().rawValue)) + + result["postTanWidth"] = .number(x.GetPostTanWidth()) + + var postTanSlope = pxr.VtValue() + Overlay.GetPostTanSlope(x, &postTanSlope) + result["postTanSlope"] = try writeValueWithoutTypeHint(TypedValue(vtValue: postTanSlope)) + + result["postTanAlgorithm"] = .int(Int(x.GetPostTanAlgorithm().rawValue)) + + result["customData"] = try writeVtDictionary(x.GetCustomData()) + + return .object(result) +} + diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/VtArrayTemplateErgonomics.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/VtArrayTemplateErgonomics.swift new file mode 100644 index 0000000000..c1e572f926 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/VtArrayTemplateErgonomics.swift @@ -0,0 +1,273 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import CxxStdlib +import OpenUSD +import TemporaryImplementations_Cxx +import TemporaryImplementations_Swift + +// C++ templated code is fully specialized, so it can directly use all the functionality +// of its instantiations without any extra ceremony. Swift generics/protocols are +// not fully specialized, so we need a Swift protocol that C++ types conform to +// to let us write the equivalent of template code over them. +// +// In this case, we need to access VtArray. The first three +// protocol requirements here are taken directly from VtArray, +// so conforming doesn't require anything extra, but the last the +// protocol requirements have to be added because we need to +// express (e.g.) `pxr.VtValue(someVtArray)`, but protocols +// can only express requirements that are members of the conforming type, +// and `pxr::VtValue::VtValue(_:)` is not a member of `VtArray`. +// (Similarly for `vtValue.Get() as value_type` and `pxr.VtValue(arrayElement)`.) + +internal protocol _VtArrayExtractionWritingProtocol: Sequence { + associatedtype value_type + init() + mutating func push_back(_ x: value_type) + + var asVtValue: pxr.VtValue { get } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue +} +extension pxr.VtBoolArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtUCharArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtIntArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtUIntArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtInt64Array: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtUInt64Array: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtHalfArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtFloatArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtDoubleArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtTimeCodeArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtStringArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtTokenArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension Overlay.SdfAssetPath_VtArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec2iArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec3iArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec4iArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec2hArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec3hArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec4hArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec2fArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec3fArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec4fArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec2dArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec3dArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtVec4dArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtQuathArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtQuatfArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtQuatdArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtMatrix2dArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtMatrix3dArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension pxr.VtMatrix4dArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} +extension Overlay.SdfPathExpression_VtArray: _VtArrayExtractionWritingProtocol { + var asVtValue: pxr.VtValue { pxr.VtValue(self) } + static func scalarFromVtValue(_ x: pxr.VtValue) -> value_type { + var copy = x; return copy.Get() + } + static func scalarAsVtValue(_ x: Element) -> pxr.VtValue { pxr.VtValue(x) } +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/VtSerialization.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/VtSerialization.swift new file mode 100644 index 0000000000..cf5ba88986 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/VtSerialization.swift @@ -0,0 +1,1273 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation +import OpenUSD + +/// Represents a VtValue along with some type information, +/// such as a role or non-value type name, or an empty VtValue +/// that is expected to later be filled in to match a given type +struct TypedValue { + var value: pxr.VtValue + var valueTypeName: pxr.SdfValueTypeName + var otherTypeName: String + + init(vtValue: pxr.VtValue) { + self.value = vtValue + self.valueTypeName = pxr.SdfGetValueTypeNameForValue(vtValue) + self.otherTypeName = String(vtValue.GetTypeName()) + } + init(typeName: pxr.SdfValueTypeName) { + self.value = pxr.VtValue() + self.valueTypeName = typeName + self.otherTypeName = "" + } + init(otherTypeName: String) { + self.value = pxr.VtValue() + self.valueTypeName = pxr.SdfValueTypeName() + self.otherTypeName = otherTypeName + } +} + +func extractVtDictionary(_ js: JsAny) throws -> pxr.VtDictionary { + var result = pxr.VtDictionary() + + for (k, v) in try js.castAsObject() { + let x = try extractTypeHintAndValue(v) + result[std.string(k)] = x.value + } + + return result +} +func writeVtDictionary(_ x: pxr.VtDictionary) throws -> JsAny { + var result = [String : JsAny]() + for kvPair in x { + let v = TypedValue(vtValue: kvPair.second) + result[String(kvPair.first)] = try writeTypeHintAndValue(v) + } + return .object(result) +} + +func extractTypeHint(_ js: JsAny) throws -> TypedValue { + let obj = try js.castAsObject() + + let s = try obj["type", errorMessage: "extractTypeHint"].castAsString() + if false {} + + // Taken from `class Sdf_ValueTypeNamesType` in OpenUSD/pxr/usd/sdf/types.h + else if s == "Bool" { return .init(typeName: .Bool) } + else if s == "UChar" { return .init(typeName: .UChar) } + else if s == "Int" { return .init(typeName: .Int) } + else if s == "UInt" { return .init(typeName: .UInt) } + else if s == "Int64" { return .init(typeName: .Int64) } + else if s == "UInt64" { return .init(typeName: .UInt64) } + else if s == "Half" { return .init(typeName: .Half) } + else if s == "Float" { return .init(typeName: .Float) } + else if s == "Double" { return .init(typeName: .Double) } + else if s == "TimeCode" { return .init(typeName: .TimeCode) } + else if s == "String" { return .init(typeName: .String) } + else if s == "Token" { return .init(typeName: .Token) } + else if s == "Asset" { return .init(typeName: .Asset) } + else if s == "Int2" { return .init(typeName: .Int2) } + else if s == "Int3" { return .init(typeName: .Int3) } + else if s == "Int4" { return .init(typeName: .Int4) } + else if s == "Half2" { return .init(typeName: .Half2) } + else if s == "Half3" { return .init(typeName: .Half3) } + else if s == "Half4" { return .init(typeName: .Half4) } + else if s == "Float2" { return .init(typeName: .Float2) } + else if s == "Float3" { return .init(typeName: .Float3) } + else if s == "Float4" { return .init(typeName: .Float4) } + else if s == "Double2" { return .init(typeName: .Double2) } + else if s == "Double3" { return .init(typeName: .Double3) } + else if s == "Double4" { return .init(typeName: .Double4) } + else if s == "Point3h" { return .init(typeName: .Point3h) } + else if s == "Point3f" { return .init(typeName: .Point3f) } + else if s == "Point3d" { return .init(typeName: .Point3d) } + else if s == "Vector3h" { return .init(typeName: .Vector3h) } + else if s == "Vector3f" { return .init(typeName: .Vector3f) } + else if s == "Vector3d" { return .init(typeName: .Vector3d) } + else if s == "Normal3h" { return .init(typeName: .Normal3h) } + else if s == "Normal3f" { return .init(typeName: .Normal3f) } + else if s == "Normal3d" { return .init(typeName: .Normal3d) } + else if s == "Color3h" { return .init(typeName: .Color3h) } + else if s == "Color3f" { return .init(typeName: .Color3f) } + else if s == "Color3d" { return .init(typeName: .Color3d) } + else if s == "Color4h" { return .init(typeName: .Color4h) } + else if s == "Color4f" { return .init(typeName: .Color4f) } + else if s == "Color4d" { return .init(typeName: .Color4d) } + else if s == "Quath" { return .init(typeName: .Quath) } + else if s == "Quatf" { return .init(typeName: .Quatf) } + else if s == "Quatd" { return .init(typeName: .Quatd) } + else if s == "Matrix2d" { return .init(typeName: .Matrix2d) } + else if s == "Matrix3d" { return .init(typeName: .Matrix3d) } + else if s == "Matrix4d" { return .init(typeName: .Matrix4d) } + else if s == "Frame4d" { return .init(typeName: .Frame4d) } + else if s == "TexCoord2h" { return .init(typeName: .TexCoord2h) } + else if s == "TexCoord2f" { return .init(typeName: .TexCoord2f) } + else if s == "TexCoord2d" { return .init(typeName: .TexCoord2d) } + else if s == "TexCoord3h" { return .init(typeName: .TexCoord3h) } + else if s == "TexCoord3f" { return .init(typeName: .TexCoord3f) } + else if s == "TexCoord3d" { return .init(typeName: .TexCoord3d) } + else if s == "Opaque" { return .init(typeName: .Opaque) } + else if s == "Group" { return .init(typeName: .Group) } + else if s == "PathExpression" { return .init(typeName: .PathExpression) } + else if s == "BoolArray" { return .init(typeName: .BoolArray) } + else if s == "UCharArray" { return .init(typeName: .UCharArray) } + else if s == "IntArray" { return .init(typeName: .IntArray) } + else if s == "UIntArray" { return .init(typeName: .UIntArray) } + else if s == "Int64Array" { return .init(typeName: .Int64Array) } + else if s == "UInt64Array" { return .init(typeName: .UInt64Array) } + else if s == "HalfArray" { return .init(typeName: .HalfArray) } + else if s == "FloatArray" { return .init(typeName: .FloatArray) } + else if s == "DoubleArray" { return .init(typeName: .DoubleArray) } + else if s == "TimeCodeArray" { return .init(typeName: .TimeCodeArray) } + else if s == "StringArray" { return .init(typeName: .StringArray) } + else if s == "TokenArray" { return .init(typeName: .TokenArray) } + else if s == "AssetArray" { return .init(typeName: .AssetArray) } + else if s == "Int2Array" { return .init(typeName: .Int2Array) } + else if s == "Int3Array" { return .init(typeName: .Int3Array) } + else if s == "Int4Array" { return .init(typeName: .Int4Array) } + else if s == "Half2Array" { return .init(typeName: .Half2Array) } + else if s == "Half3Array" { return .init(typeName: .Half3Array) } + else if s == "Half4Array" { return .init(typeName: .Half4Array) } + else if s == "Float2Array" { return .init(typeName: .Float2Array) } + else if s == "Float3Array" { return .init(typeName: .Float3Array) } + else if s == "Float4Array" { return .init(typeName: .Float4Array) } + else if s == "Double2Array" { return .init(typeName: .Double2Array) } + else if s == "Double3Array" { return .init(typeName: .Double3Array) } + else if s == "Double4Array" { return .init(typeName: .Double4Array) } + else if s == "Point3hArray" { return .init(typeName: .Point3hArray) } + else if s == "Point3fArray" { return .init(typeName: .Point3fArray) } + else if s == "Point3dArray" { return .init(typeName: .Point3dArray) } + else if s == "Vector3hArray" { return .init(typeName: .Vector3hArray) } + else if s == "Vector3fArray" { return .init(typeName: .Vector3fArray) } + else if s == "Vector3dArray" { return .init(typeName: .Vector3dArray) } + else if s == "Normal3hArray" { return .init(typeName: .Normal3hArray) } + else if s == "Normal3fArray" { return .init(typeName: .Normal3fArray) } + else if s == "Normal3dArray" { return .init(typeName: .Normal3dArray) } + else if s == "Color3hArray" { return .init(typeName: .Color3hArray) } + else if s == "Color3fArray" { return .init(typeName: .Color3fArray) } + else if s == "Color3dArray" { return .init(typeName: .Color3dArray) } + else if s == "Color4hArray" { return .init(typeName: .Color4hArray) } + else if s == "Color4fArray" { return .init(typeName: .Color4fArray) } + else if s == "Color4dArray" { return .init(typeName: .Color4dArray) } + else if s == "QuathArray" { return .init(typeName: .QuathArray) } + else if s == "QuatfArray" { return .init(typeName: .QuatfArray) } + else if s == "QuatdArray" { return .init(typeName: .QuatdArray) } + else if s == "Matrix2dArray" { return .init(typeName: .Matrix2dArray) } + else if s == "Matrix3dArray" { return .init(typeName: .Matrix3dArray) } + else if s == "Matrix4dArray" { return .init(typeName: .Matrix4dArray) } + else if s == "Frame4dArray" { return .init(typeName: .Frame4dArray) } + else if s == "TexCoord2hArray" { return .init(typeName: .TexCoord2hArray) } + else if s == "TexCoord2fArray" { return .init(typeName: .TexCoord2fArray) } + else if s == "TexCoord2dArray" { return .init(typeName: .TexCoord2dArray) } + else if s == "TexCoord3hArray" { return .init(typeName: .TexCoord3hArray) } + else if s == "TexCoord3fArray" { return .init(typeName: .TexCoord3fArray) } + else if s == "TexCoord3dArray" { return .init(typeName: .TexCoord3dArray) } + else if s == "PathExpressionArray" { return .init(typeName: .PathExpressionArray) } + + // Edge cases not from OpenUSD/pxr/usd/sdf/types.h + else if s == "SdfListOp" { return .init(otherTypeName: s) } + else if s == "SdfListOp" { return .init(otherTypeName: s) } + else if s == "SdfListOp" { return .init(otherTypeName: s) } + else if s == "VtDictionary" { return .init(otherTypeName: s) } + else if s == "SdfUnregisteredValue" { return .init(otherTypeName: s) } + else if s == "PointIndex" || s == "PointIndex[]" { return .init(otherTypeName: s) } + else if s == "SdfPermission" { return .init(otherTypeName: s) } + else if s == "SdfPath" { return .init(otherTypeName: s) } + else if !s.isEmpty { + // Important: Lots of code depends on extractTypeHint, and the vast majority of it + // doesn't know how to handle unknown type hints. Emit an error that could be caught + // by TfErrorMark and return a valid TypedValue, so that sophisticated callers can + // handle this case if they want, while simpler callers can simply error out + + TF_RUNTIME_ERROR(std.string("Deserializing unknown type hint '\(s)'")) + return .init(otherTypeName: s) + } else { + throw JsDecodingError.typeHintWasEmpty + } +} +func writeTypeHint(_ value: TypedValue) -> JsAny { + if false {} + + else if value.valueTypeName == .Bool { return "Bool" } + else if value.valueTypeName == .UChar { return "UChar" } + else if value.valueTypeName == .Int { return "Int" } + else if value.valueTypeName == .UInt { return "UInt" } + else if value.valueTypeName == .Int64 { return "Int64" } + else if value.valueTypeName == .UInt64 { return "UInt64" } + else if value.valueTypeName == .Half { return "Half" } + else if value.valueTypeName == .Float { return "Float" } + else if value.valueTypeName == .Double { return "Double" } + else if value.valueTypeName == .TimeCode { return "TimeCode" } + else if value.valueTypeName == .String { return "String" } + else if value.valueTypeName == .Token { return "Token" } + else if value.valueTypeName == .Asset { return "Asset" } + else if value.valueTypeName == .Int2 { return "Int2" } + else if value.valueTypeName == .Int3 { return "Int3" } + else if value.valueTypeName == .Int4 { return "Int4" } + else if value.valueTypeName == .Half2 { return "Half2" } + else if value.valueTypeName == .Half3 { return "Half3" } + else if value.valueTypeName == .Half4 { return "Half4" } + else if value.valueTypeName == .Float2 { return "Float2" } + else if value.valueTypeName == .Float3 { return "Float3" } + else if value.valueTypeName == .Float4 { return "Float4" } + else if value.valueTypeName == .Double2 { return "Double2" } + else if value.valueTypeName == .Double3 { return "Double3" } + else if value.valueTypeName == .Double4 { return "Double4" } + else if value.valueTypeName == .Point3h { return "Point3h" } + else if value.valueTypeName == .Point3f { return "Point3f" } + else if value.valueTypeName == .Point3d { return "Point3d" } + else if value.valueTypeName == .Vector3h { return "Vector3h" } + else if value.valueTypeName == .Vector3f { return "Vector3f" } + else if value.valueTypeName == .Vector3d { return "Vector3d" } + else if value.valueTypeName == .Normal3h { return "Normal3h" } + else if value.valueTypeName == .Normal3f { return "Normal3f" } + else if value.valueTypeName == .Normal3d { return "Normal3d" } + else if value.valueTypeName == .Color3h { return "Color3h" } + else if value.valueTypeName == .Color3f { return "Color3f" } + else if value.valueTypeName == .Color3d { return "Color3d" } + else if value.valueTypeName == .Color4h { return "Color4h" } + else if value.valueTypeName == .Color4f { return "Color4f" } + else if value.valueTypeName == .Color4d { return "Color4d" } + else if value.valueTypeName == .Quath { return "Quath" } + else if value.valueTypeName == .Quatf { return "Quatf" } + else if value.valueTypeName == .Quatd { return "Quatd" } + else if value.valueTypeName == .Matrix2d { return "Matrix2d" } + else if value.valueTypeName == .Matrix3d { return "Matrix3d" } + else if value.valueTypeName == .Matrix4d { return "Matrix4d" } + else if value.valueTypeName == .Frame4d { return "Frame4d" } + else if value.valueTypeName == .TexCoord2h { return "TexCoord2h" } + else if value.valueTypeName == .TexCoord2f { return "TexCoord2f" } + else if value.valueTypeName == .TexCoord2d { return "TexCoord2d" } + else if value.valueTypeName == .TexCoord3h { return "TexCoord3h" } + else if value.valueTypeName == .TexCoord3f { return "TexCoord3f" } + else if value.valueTypeName == .TexCoord3d { return "TexCoord3d" } + else if value.valueTypeName == .Opaque { return "Opaque" } + else if value.valueTypeName == .Group { return "Group" } + else if value.valueTypeName == .PathExpression { return "PathExpression" } + else if value.valueTypeName == .BoolArray { return "BoolArray" } + else if value.valueTypeName == .UCharArray { return "UCharArray" } + else if value.valueTypeName == .IntArray { return "IntArray" } + else if value.valueTypeName == .UIntArray { return "UIntArray" } + else if value.valueTypeName == .Int64Array { return "Int64Array" } + else if value.valueTypeName == .UInt64Array { return "UInt64Array" } + else if value.valueTypeName == .HalfArray { return "HalfArray" } + else if value.valueTypeName == .FloatArray { return "FloatArray" } + else if value.valueTypeName == .DoubleArray { return "DoubleArray" } + else if value.valueTypeName == .TimeCodeArray { return "TimeCodeArray" } + else if value.valueTypeName == .StringArray { return "StringArray" } + else if value.valueTypeName == .TokenArray { return "TokenArray" } + else if value.valueTypeName == .AssetArray { return "AssetArray" } + else if value.valueTypeName == .Int2Array { return "Int2Array" } + else if value.valueTypeName == .Int3Array { return "Int3Array" } + else if value.valueTypeName == .Int4Array { return "Int4Array" } + else if value.valueTypeName == .Half2Array { return "Half2Array" } + else if value.valueTypeName == .Half3Array { return "Half3Array" } + else if value.valueTypeName == .Half4Array { return "Half4Array" } + else if value.valueTypeName == .Float2Array { return "Float2Array" } + else if value.valueTypeName == .Float3Array { return "Float3Array" } + else if value.valueTypeName == .Float4Array { return "Float4Array" } + else if value.valueTypeName == .Double2Array { return "Double2Array" } + else if value.valueTypeName == .Double3Array { return "Double3Array" } + else if value.valueTypeName == .Double4Array { return "Double4Array" } + else if value.valueTypeName == .Point3hArray { return "Point3hArray" } + else if value.valueTypeName == .Point3fArray { return "Point3fArray" } + else if value.valueTypeName == .Point3dArray { return "Point3dArray" } + else if value.valueTypeName == .Vector3hArray { return "Vector3hArray" } + else if value.valueTypeName == .Vector3fArray { return "Vector3fArray" } + else if value.valueTypeName == .Vector3dArray { return "Vector3dArray" } + else if value.valueTypeName == .Normal3hArray { return "Normal3hArray" } + else if value.valueTypeName == .Normal3fArray { return "Normal3fArray" } + else if value.valueTypeName == .Normal3dArray { return "Normal3dArray" } + else if value.valueTypeName == .Color3hArray { return "Color3hArray" } + else if value.valueTypeName == .Color3fArray { return "Color3fArray" } + else if value.valueTypeName == .Color3dArray { return "Color3dArray" } + else if value.valueTypeName == .Color4hArray { return "Color4hArray" } + else if value.valueTypeName == .Color4fArray { return "Color4fArray" } + else if value.valueTypeName == .Color4dArray { return "Color4dArray" } + else if value.valueTypeName == .QuathArray { return "QuathArray" } + else if value.valueTypeName == .QuatfArray { return "QuatfArray" } + else if value.valueTypeName == .QuatdArray { return "QuatdArray" } + else if value.valueTypeName == .Matrix2dArray { return "Matrix2dArray" } + else if value.valueTypeName == .Matrix3dArray { return "Matrix3dArray" } + else if value.valueTypeName == .Matrix4dArray { return "Matrix4dArray" } + else if value.valueTypeName == .Frame4dArray { return "Frame4dArray" } + else if value.valueTypeName == .TexCoord2hArray { return "TexCoord2hArray" } + else if value.valueTypeName == .TexCoord2fArray { return "TexCoord2fArray" } + else if value.valueTypeName == .TexCoord2dArray { return "TexCoord2dArray" } + else if value.valueTypeName == .TexCoord3hArray { return "TexCoord3hArray" } + else if value.valueTypeName == .TexCoord3fArray { return "TexCoord3fArray" } + else if value.valueTypeName == .TexCoord3dArray { return "TexCoord3dArray" } + else if value.valueTypeName == .PathExpressionArray { return "PathExpressionArray" } + + else if value.valueTypeName.GetAsToken() == .SdfValueRoleNames.PointIndex { + return .string(String(pxr.TfToken.SdfValueRoleNames.PointIndex)) + } else if value.valueTypeName.GetScalarType().GetAsToken() == .SdfValueRoleNames.PointIndex { + return .string(String(pxr.TfToken.SdfValueRoleNames.PointIndex) + "[]") + } else if value.otherTypeName.isEmpty && !value.valueTypeName.GetAsToken().IsEmpty() { + // Important: Some type names may be invalid but should still round-trip. + // See extent-wrong-type-name.usda + return .string(String(value.valueTypeName.GetAsToken())) + } else { + return .string(String(value.otherTypeName)) + } +} + +func _extractArray(_ out: inout TypedValue, _ js: JsAny, _ t: T.Type) throws { + var decoded = T.init() + for x in try js.castAsArray() { + var temp = TypedValue(typeName: out.valueTypeName.GetScalarType()) + try extractValueWithTypeHint(&temp, x) + decoded.push_back(T.scalarFromVtValue(temp.value)) + } + out.value = decoded.asVtValue +} + +/// Expects the type hint to be provided. See also extractTypeHintAndValue +func extractValueWithTypeHint(_ out: inout TypedValue, _ js: JsAny) throws { + if js.isNull { + out.value = pxr.VtValue(pxr.SdfValueBlock()) + return + } + + // Speculatively try to decode SdfUnregisteredValue + if let x = try? extractSdfUnregisteredValue(js) { + out.value = pxr.VtValue(x) + return + } + + // Speculatively try to decode SdfAnimationBlock + if let x = try? extractSdfAnimationBlock(js) { + out.value = pxr.VtValue(x) + return + } + + if out.valueTypeName == .Bool { + let x = try js.castAsBool() + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .UChar { + let x = try js.castAsInt() + out.value = pxr.VtValue(UInt8(x)) + } else if out.valueTypeName == .Int { + let x = try js.castAsInt() + out.value = pxr.VtValue(Int32(x)) + } else if out.valueTypeName == .UInt { + let x = try js.castAsInt() + out.value = pxr.VtValue(UInt32(x)) + } else if out.valueTypeName == .Int64 { + let x = try js.castAsInt() + out.value = pxr.VtValue(Int64(x)) + } else if out.valueTypeName == .UInt64 { + let x = try js.castAsInt() + out.value = pxr.VtValue(UInt64(x)) + } else if out.valueTypeName == .Half { + let x = try js.castAsNumber() + out.value = pxr.VtValue(pxr.GfHalf(x)) + } else if out.valueTypeName == .Float { + let x = try js.castAsNumber() + out.value = pxr.VtValue(Float(x)) + } else if out.valueTypeName == .Double { + let x = try js.castAsNumber() + out.value = pxr.VtValue(Double(x)) + } else if out.valueTypeName == .TimeCode { + let x = try js.castAsNumber() + out.value = pxr.VtValue(pxr.GfTimeCode(x)) + } else if out.valueTypeName == .String { + let x = try js.castAsString() + out.value = pxr.VtValue(std.string(x)) + } else if out.valueTypeName == .Token { + let x = try js.castAsString() + out.value = pxr.VtValue(pxr.TfToken(x)) + } else if out.valueTypeName == .Asset { + let x = try js.castAsString() + out.value = pxr.VtValue(pxr.SdfAssetPath(x)) + + } else if out.valueTypeName == .Int2 { + var x = pxr.GfVec2i() + let arr = try js.castAsArray() + guard arr.count == 2 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Int32(try arr[0].castAsInt()) + x[1] = Int32(try arr[1].castAsInt()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Int3 { + var x = pxr.GfVec3i() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Int32(try arr[0].castAsInt()) + x[1] = Int32(try arr[1].castAsInt()) + x[2] = Int32(try arr[2].castAsInt()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Int4 { + var x = pxr.GfVec4i() + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Int32(try arr[0].castAsInt()) + x[1] = Int32(try arr[1].castAsInt()) + x[2] = Int32(try arr[2].castAsInt()) + x[3] = Int32(try arr[3].castAsInt()) + out.value = pxr.VtValue(x) + } + + else if out.valueTypeName == .Half2 { + var x = pxr.GfVec2h() + let arr = try js.castAsArray() + guard arr.count == 2 else { throw JsDecodingError.mismatchedVecLength } + x[0] = pxr.GfHalf(try arr[0].castAsNumber()) + x[1] = pxr.GfHalf(try arr[1].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Half3 { + var x = pxr.GfVec3h() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = pxr.GfHalf(try arr[0].castAsNumber()) + x[1] = pxr.GfHalf(try arr[1].castAsNumber()) + x[2] = pxr.GfHalf(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Half4 { + var x = pxr.GfVec4h() + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + x[0] = pxr.GfHalf(try arr[0].castAsNumber()) + x[1] = pxr.GfHalf(try arr[1].castAsNumber()) + x[2] = pxr.GfHalf(try arr[2].castAsNumber()) + x[3] = pxr.GfHalf(try arr[3].castAsNumber()) + out.value = pxr.VtValue(x) + } + + else if out.valueTypeName == .Float2 { + var x = pxr.GfVec2f() + let arr = try js.castAsArray() + guard arr.count == 2 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Float(try arr[0].castAsNumber()) + x[1] = Float(try arr[1].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Float3 { + var x = pxr.GfVec3f() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Float(try arr[0].castAsNumber()) + x[1] = Float(try arr[1].castAsNumber()) + x[2] = Float(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Float4 { + var x = pxr.GfVec4f() + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Float(try arr[0].castAsNumber()) + x[1] = Float(try arr[1].castAsNumber()) + x[2] = Float(try arr[2].castAsNumber()) + x[3] = Float(try arr[3].castAsNumber()) + out.value = pxr.VtValue(x) + } + + else if out.valueTypeName == .Double2 { + var x = pxr.GfVec2d() + let arr = try js.castAsArray() + guard arr.count == 2 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Double(try arr[0].castAsNumber()) + x[1] = Double(try arr[1].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Double3 { + var x = pxr.GfVec3d() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Double(try arr[0].castAsNumber()) + x[1] = Double(try arr[1].castAsNumber()) + x[2] = Double(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Double4 { + var x = pxr.GfVec4d() + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Double(try arr[0].castAsNumber()) + x[1] = Double(try arr[1].castAsNumber()) + x[2] = Double(try arr[2].castAsNumber()) + x[3] = Double(try arr[3].castAsNumber()) + out.value = pxr.VtValue(x) + } + + else if out.valueTypeName == .Point3h { + var x = pxr.GfVec3h() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = pxr.GfHalf(try arr[0].castAsNumber()) + x[1] = pxr.GfHalf(try arr[1].castAsNumber()) + x[2] = pxr.GfHalf(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Point3f { + var x = pxr.GfVec3f() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Float(try arr[0].castAsNumber()) + x[1] = Float(try arr[1].castAsNumber()) + x[2] = Float(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Point3d { + var x = pxr.GfVec3d() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Double(try arr[0].castAsNumber()) + x[1] = Double(try arr[1].castAsNumber()) + x[2] = Double(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } + + else if out.valueTypeName == .Vector3h { + var x = pxr.GfVec3h() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = pxr.GfHalf(try arr[0].castAsNumber()) + x[1] = pxr.GfHalf(try arr[1].castAsNumber()) + x[2] = pxr.GfHalf(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Vector3f { + var x = pxr.GfVec3f() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Float(try arr[0].castAsNumber()) + x[1] = Float(try arr[1].castAsNumber()) + x[2] = Float(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Vector3d { + var x = pxr.GfVec3d() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Double(try arr[0].castAsNumber()) + x[1] = Double(try arr[1].castAsNumber()) + x[2] = Double(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } + + else if out.valueTypeName == .Normal3h { + var x = pxr.GfVec3h() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = pxr.GfHalf(try arr[0].castAsNumber()) + x[1] = pxr.GfHalf(try arr[1].castAsNumber()) + x[2] = pxr.GfHalf(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Normal3f { + var x = pxr.GfVec3f() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Float(try arr[0].castAsNumber()) + x[1] = Float(try arr[1].castAsNumber()) + x[2] = Float(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Normal3d { + var x = pxr.GfVec3d() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Double(try arr[0].castAsNumber()) + x[1] = Double(try arr[1].castAsNumber()) + x[2] = Double(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } + + else if out.valueTypeName == .Color3h { + var x = pxr.GfVec3h() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = pxr.GfHalf(try arr[0].castAsNumber()) + x[1] = pxr.GfHalf(try arr[1].castAsNumber()) + x[2] = pxr.GfHalf(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Color3f { + var x = pxr.GfVec3f() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Float(try arr[0].castAsNumber()) + x[1] = Float(try arr[1].castAsNumber()) + x[2] = Float(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Color3d { + var x = pxr.GfVec3d() + let arr = try js.castAsArray() + guard arr.count == 3 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Double(try arr[0].castAsNumber()) + x[1] = Double(try arr[1].castAsNumber()) + x[2] = Double(try arr[2].castAsNumber()) + out.value = pxr.VtValue(x) + } + + else if out.valueTypeName == .Color4h { + var x = pxr.GfVec4h() + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + x[0] = pxr.GfHalf(try arr[0].castAsNumber()) + x[1] = pxr.GfHalf(try arr[1].castAsNumber()) + x[2] = pxr.GfHalf(try arr[2].castAsNumber()) + x[3] = pxr.GfHalf(try arr[3].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Color4f { + var x = pxr.GfVec4f() + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Float(try arr[0].castAsNumber()) + x[1] = Float(try arr[1].castAsNumber()) + x[2] = Float(try arr[2].castAsNumber()) + x[3] = Float(try arr[3].castAsNumber()) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Color4d { + var x = pxr.GfVec4d() + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + x[0] = Double(try arr[0].castAsNumber()) + x[1] = Double(try arr[1].castAsNumber()) + x[2] = Double(try arr[2].castAsNumber()) + x[3] = Double(try arr[3].castAsNumber()) + out.value = pxr.VtValue(x) + } + + else if out.valueTypeName == .Quath { + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + let x = pxr.GfQuath( + pxr.GfHalf(try arr[0].castAsNumber()), + pxr.GfHalf(try arr[1].castAsNumber()), + pxr.GfHalf(try arr[2].castAsNumber()), + pxr.GfHalf(try arr[3].castAsNumber()), + ) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Quatf { + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + let x = pxr.GfQuatf( + Float(try arr[0].castAsNumber()), + Float(try arr[1].castAsNumber()), + Float(try arr[2].castAsNumber()), + Float(try arr[3].castAsNumber()), + ) + out.value = pxr.VtValue(x) + } else if out.valueTypeName == .Quatd { + let arr = try js.castAsArray() + guard arr.count == 4 else { throw JsDecodingError.mismatchedVecLength } + let x = pxr.GfQuatd( + Double(try arr[0].castAsNumber()), + Double(try arr[1].castAsNumber()), + Double(try arr[2].castAsNumber()), + Double(try arr[3].castAsNumber()), + ) + out.value = pxr.VtValue(x) + } + + else if (out.valueTypeName == .Matrix2d) { + var x = pxr.GfMatrix2d() + let arr = try js.castAsArray() + let (numRows, numColumns) = (2, 2) + guard arr.count == numRows * numColumns else { throw JsDecodingError.mismatchedMatLength } + for i in 0.." { + let x: pxr.SdfTokenListOp = try extractSdfListOp(pxr.SdfTokenListOp.self, js, extractTfToken) + out.value = pxr.VtValue(x) + } else if out.otherTypeName == "SdfListOp" { + let x: pxr.SdfInt64ListOp = try extractSdfListOp(pxr.SdfInt64ListOp.self, js, extractLongLong) + out.value = pxr.VtValue(x) + } else if out.otherTypeName == "SdfListOp" { + let x: pxr.SdfStringListOp = try extractSdfListOp(pxr.SdfStringListOp.self, js, extractString) + out.value = pxr.VtValue(x) + } else if out.otherTypeName == "VtDictionary" { + out.value = try pxr.VtValue(extractVtDictionary(js)) + } else if out.otherTypeName == "SdfUnregisteredValue" { + out.value = try pxr.VtValue(extractSdfUnregisteredValue(js)) + } else if out.otherTypeName == "PointIndex" { + var temp = TypedValue(typeName: .Int) + try extractValueWithTypeHint(&temp, js) + out.value = temp.value + } else if out.otherTypeName == "PointIndex[]" { + var temp = TypedValue(typeName: .IntArray) + try extractValueWithTypeHint(&temp, js) + out.value = temp.value + } else if out.otherTypeName == "SdfPermission" { + var temp = TypedValue(typeName: .Int) + try extractValueWithTypeHint(&temp, js) + var copy = temp.value + let x = copy.Get() as Int32 + out.value = pxr.VtValue(pxr.SdfPermission(rawValue: UInt32(x))) + } else if out.otherTypeName == "Transform" { + var temp = TypedValue(typeName: .Matrix4d) + try extractValueWithTypeHint(&temp, js) + out.value = temp.value + } else { + throw JsDecodingError.unknownTypeName(out.valueTypeName.GetAsToken(), out.otherTypeName) + } +} + +func _writeArray(_ arr: T, _ value: TypedValue) throws -> JsAny { + var result = [JsAny]() + for x in arr { + var temp = TypedValue(vtValue: T.scalarAsVtValue(x)) + temp.valueTypeName = value.valueTypeName.GetScalarType() + try result.append(writeValueWithoutTypeHint(temp)) + } + return .array(result) +} + + +func writeValueWithoutTypeHint(_ value: TypedValue) throws -> JsAny { + // Important: Use value.value.IsHolding instead of comparing to value.valueTypeName because + // of e.g. mismatched-types.usda + var copy = value.value + + if copy.IsHolding(T: pxr.SdfValueBlock.self) { + return .null + } + + if copy.IsHolding(T: Bool.self) { + return .bool(copy.Get() as Bool) + } else if copy.IsHolding(T: UInt8.self) { + return .int(Int(copy.Get() as UInt8)) + } else if copy.IsHolding(T: Int32.self) { + return .int(Int(copy.Get() as Int32)) + } else if copy.IsHolding(T: UInt32.self) { + return .int(Int(copy.Get() as UInt32)) + } else if copy.IsHolding(T: Int64.self) { + return .int(Int(copy.Get() as Int64)) + } else if copy.IsHolding(T: UInt64.self) { + return .int(Int(copy.Get() as UInt64)) + } else if copy.IsHolding(T: pxr.GfHalf.self) { + return .number(Double(copy.Get() as pxr.GfHalf)) + } else if copy.IsHolding(T: Float.self) { + return .number(Double(copy.Get() as Float)) + } else if copy.IsHolding(T: Double.self) { + return .number(Double(copy.Get() as Double)) + } else if copy.IsHolding(T: pxr.GfTimeCode.self) { + return .number(Double(copy.Get() as pxr.GfTimeCode)) + } else if copy.IsHolding(T: std.string.self) { + return .string(String(copy.Get() as std.string)) + } else if copy.IsHolding(T: pxr.TfToken.self) { + return .string(String(copy.Get() as pxr.TfToken)) + } else if copy.IsHolding(T: pxr.SdfAssetPath.self) { + return .string(String((copy.Get() as pxr.SdfAssetPath).GetAuthoredPath())) + } else if copy.IsHolding(T: pxr.GfVec2i.self) { + let x = copy.Get() as pxr.GfVec2i + return [ + .int(Int(x[0])), + .int(Int(x[1])) + ] + } else if copy.IsHolding(T: pxr.GfVec3i.self) { + let x = copy.Get() as pxr.GfVec3i + return [ + .int(Int(x[0])), + .int(Int(x[1])), + .int(Int(x[2])), + ] + } else if copy.IsHolding(T: pxr.GfVec4i.self) { + let x = copy.Get() as pxr.GfVec4i + return [ + .int(Int(x[0])), + .int(Int(x[1])), + .int(Int(x[2])), + .int(Int(x[3])), + ] + } else if copy.IsHolding(T: pxr.GfVec2h.self) { + let x = copy.Get() as pxr.GfVec2h + return [ + .number(Double(x[0])), + .number(Double(x[1])) + ] + } else if copy.IsHolding(T: pxr.GfVec3h.self) { + let x = copy.Get() as pxr.GfVec3h + return [ + .number(Double(x[0])), + .number(Double(x[1])), + .number(Double(x[2])), + ] + } else if copy.IsHolding(T: pxr.GfVec4h.self) { + let x = copy.Get() as pxr.GfVec4h + return [ + .number(Double(x[0])), + .number(Double(x[1])), + .number(Double(x[2])), + .number(Double(x[3])), + ] + } else if copy.IsHolding(T: pxr.GfVec2f.self) { + let x = copy.Get() as pxr.GfVec2f + return [ + .number(Double(x[0])), + .number(Double(x[1])) + ] + } else if copy.IsHolding(T: pxr.GfVec3f.self) { + let x = copy.Get() as pxr.GfVec3f + return [ + .number(Double(x[0])), + .number(Double(x[1])), + .number(Double(x[2])), + ] + } else if copy.IsHolding(T: pxr.GfVec4f.self) { + let x = copy.Get() as pxr.GfVec4f + return [ + .number(Double(x[0])), + .number(Double(x[1])), + .number(Double(x[2])), + .number(Double(x[3])), + ] + } else if copy.IsHolding(T: pxr.GfVec2d.self) { + let x = copy.Get() as pxr.GfVec2d + return [ + .number(Double(x[0])), + .number(Double(x[1])) + ] + } else if copy.IsHolding(T: pxr.GfVec3d.self) { + let x = copy.Get() as pxr.GfVec3d + return [ + .number(Double(x[0])), + .number(Double(x[1])), + .number(Double(x[2])), + ] + } else if copy.IsHolding(T: pxr.GfVec4d.self) { + let x = copy.Get() as pxr.GfVec4d + return [ + .number(Double(x[0])), + .number(Double(x[1])), + .number(Double(x[2])), + .number(Double(x[3])), + ] + } else if copy.IsHolding(T: pxr.GfQuath.self) { + let x = copy.Get() as pxr.GfQuath + return [ + .number(Double(x.GetReal())), + .number(Double(x.GetImaginary()[0])), + .number(Double(x.GetImaginary()[1])), + .number(Double(x.GetImaginary()[2])) + ] + } else if copy.IsHolding(T: pxr.GfQuatf.self) { + let x = copy.Get() as pxr.GfQuatf + return [ + .number(Double(x.GetReal())), + .number(Double(x.GetImaginary()[0])), + .number(Double(x.GetImaginary()[1])), + .number(Double(x.GetImaginary()[2])) + ] + } else if copy.IsHolding(T: pxr.GfQuatd.self) { + let x = copy.Get() as pxr.GfQuatd + return [ + .number(Double(x.GetReal())), + .number(Double(x.GetImaginary()[0])), + .number(Double(x.GetImaginary()[1])), + .number(Double(x.GetImaginary()[2])) + ] + } else if copy.IsHolding(T: pxr.GfMatrix2d.self) { + let x = copy.Get() as pxr.GfMatrix2d + return [ + .number(x[0][0]), + .number(x[0][1]), + .number(x[1][0]), + .number(x[1][1]), + ] + } else if copy.IsHolding(T: pxr.GfMatrix3d.self) { + let x = copy.Get() as pxr.GfMatrix3d + return [ + .number(x[0][0]), + .number(x[0][1]), + .number(x[0][2]), + .number(x[1][0]), + .number(x[1][1]), + .number(x[1][2]), + .number(x[2][0]), + .number(x[2][1]), + .number(x[2][2]), + ] + } else if copy.IsHolding(T: pxr.GfMatrix4d.self) { + let x = copy.Get() as pxr.GfMatrix4d + return [ + .number(x[0][0]), + .number(x[0][1]), + .number(x[0][2]), + .number(x[0][3]), + .number(x[1][0]), + .number(x[1][1]), + .number(x[1][2]), + .number(x[1][3]), + .number(x[2][0]), + .number(x[2][1]), + .number(x[2][2]), + .number(x[2][3]), + .number(x[3][0]), + .number(x[3][1]), + .number(x[3][2]), + .number(x[3][3]), + ] + } else if copy.IsHolding(T: pxr.SdfOpaqueValue.self) { + return .null + } else if copy.IsHolding(T: pxr.SdfPathExpression.self) { + return .string(String((copy.Get() as pxr.SdfPathExpression).GetText())) + } + + else if (copy.IsHolding(T: pxr.VtBoolArray.self)) { + return try _writeArray(copy.Get() as pxr.VtBoolArray, value) + } else if (copy.IsHolding(T: pxr.VtUCharArray.self)) { + return try _writeArray(copy.Get() as pxr.VtUCharArray, value) + } else if (copy.IsHolding(T: pxr.VtIntArray.self)) { + return try _writeArray(copy.Get() as pxr.VtIntArray, value) + } else if (copy.IsHolding(T: pxr.VtUIntArray.self)) { + return try _writeArray(copy.Get() as pxr.VtUIntArray, value) + } else if (copy.IsHolding(T: pxr.VtInt64Array.self)) { + return try _writeArray(copy.Get() as pxr.VtInt64Array, value) + } else if (copy.IsHolding(T: pxr.VtUInt64Array.self)) { + return try _writeArray(copy.Get() as pxr.VtUInt64Array, value) + } else if (copy.IsHolding(T: pxr.VtHalfArray.self)) { + return try _writeArray(copy.Get() as pxr.VtHalfArray, value) + } else if (copy.IsHolding(T: pxr.VtFloatArray.self)) { + return try _writeArray(copy.Get() as pxr.VtFloatArray, value) + } else if (copy.IsHolding(T: pxr.VtDoubleArray.self)) { + return try _writeArray(copy.Get() as pxr.VtDoubleArray, value) + } else if (copy.IsHolding(T: pxr.VtTimeCodeArray.self)) { + return try _writeArray(copy.Get() as pxr.VtTimeCodeArray, value) + } else if (copy.IsHolding(T: pxr.VtStringArray.self)) { + return try _writeArray(copy.Get() as pxr.VtStringArray, value) + } else if (copy.IsHolding(T: pxr.VtTokenArray.self)) { + return try _writeArray(copy.Get() as pxr.VtTokenArray, value) + } else if (copy.IsHolding(T: Overlay.SdfAssetPath_VtArray.self)) { + return try _writeArray(copy.Get() as Overlay.SdfAssetPath_VtArray, value) + } else if (copy.IsHolding(T: pxr.VtVec2iArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec2iArray, value) + } else if (copy.IsHolding(T: pxr.VtVec3iArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec3iArray, value) + } else if (copy.IsHolding(T: pxr.VtVec4iArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec4iArray, value) + } else if (copy.IsHolding(T: pxr.VtVec2hArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec2hArray, value) + } else if (copy.IsHolding(T: pxr.VtVec3hArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec3hArray, value) + } else if (copy.IsHolding(T: pxr.VtVec4hArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec4hArray, value) + } else if (copy.IsHolding(T: pxr.VtVec2fArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec2fArray, value) + } else if (copy.IsHolding(T: pxr.VtVec3fArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec3fArray, value) + } else if (copy.IsHolding(T: pxr.VtVec4fArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec4fArray, value) + } else if (copy.IsHolding(T: pxr.VtVec2dArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec2dArray, value) + } else if (copy.IsHolding(T: pxr.VtVec3dArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec3dArray, value) + } else if (copy.IsHolding(T: pxr.VtVec4dArray.self)) { + return try _writeArray(copy.Get() as pxr.VtVec4dArray, value) + } else if (copy.IsHolding(T: pxr.VtQuathArray.self)) { + return try _writeArray(copy.Get() as pxr.VtQuathArray, value) + } else if (copy.IsHolding(T: pxr.VtQuatfArray.self)) { + return try _writeArray(copy.Get() as pxr.VtQuatfArray, value) + } else if (copy.IsHolding(T: pxr.VtQuatdArray.self)) { + return try _writeArray(copy.Get() as pxr.VtQuatdArray, value) + } else if (copy.IsHolding(T: pxr.VtMatrix2dArray.self)) { + return try _writeArray(copy.Get() as pxr.VtMatrix2dArray, value) + } else if (copy.IsHolding(T: pxr.VtMatrix3dArray.self)) { + return try _writeArray(copy.Get() as pxr.VtMatrix3dArray, value) + } else if (copy.IsHolding(T: pxr.VtMatrix4dArray.self)) { + return try _writeArray(copy.Get() as pxr.VtMatrix4dArray, value) + } else if (copy.IsHolding(T: Overlay.SdfAssetPath_VtArray.self)) { + return try _writeArray(copy.Get() as Overlay.SdfAssetPath_VtArray, value) + } else if (copy.IsHolding(T: Overlay.SdfPathExpression_VtArray.self)) { + return try _writeArray(copy.Get() as Overlay.SdfPathExpression_VtArray, value) + } + + else if copy.IsHolding(T: pxr.SdfTokenListOp.self) { + return try writeSdfListOp(copy.Get() as pxr.SdfTokenListOp, writeTfToken) + } else if copy.IsHolding(T: pxr.SdfInt64ListOp.self) { + return try writeSdfListOp(copy.Get() as pxr.SdfInt64ListOp, writeLongLong) + } else if copy.IsHolding(T: pxr.SdfStringListOp.self) { + return try writeSdfListOp(copy.Get() as pxr.SdfStringListOp, writeString) + } else if copy.IsHolding(T: pxr.VtDictionary.self) { + return try writeVtDictionary(copy.Get() as pxr.VtDictionary) + } else if copy.IsHolding(T: pxr.SdfUnregisteredValue.self) { + return try writeSdfUnregisteredValue(copy.Get() as pxr.SdfUnregisteredValue) + } else if value.valueTypeName.GetAsToken() == .SdfValueRoleNames.PointIndex || value.valueTypeName.GetScalarType() == .SdfValueRoleNames.PointIndex { + return try writeValueWithoutTypeHint(.init(vtValue: copy)) + } else if copy.IsHolding(T: pxr.SdfPermission.self) { + let x = Int32((copy.Get() as pxr.SdfPermission).rawValue) + return try writeValueWithoutTypeHint(.init(vtValue: pxr.VtValue(x))) + } else if copy.IsHolding(T: pxr.SdfPath.self) { + // Important: Needs "<" and ">" for mismatched-types.usda, + // so default-relationship.usda has to filter them out later. + // Very tricky to handle misencoded types in Sdf in all cases. + let s = "<\(copy.Get() as pxr.SdfPath)>" + return try writeValueWithoutTypeHint(.init(vtValue: pxr.VtValue(pxr.SdfUnregisteredValue(std.string(s))))) + } else if copy.IsHolding(T: pxr.SdfAnimationBlock.self) { + return writeSdfAnimationBlock(copy.Get() as pxr.SdfAnimationBlock) + } else { + throw JsDecodingError.unknownTypeNameAndValue(value.valueTypeName.GetAsToken(), value.otherTypeName, copy.GetTypeName(), String(pxr.TfStringify(copy))) + } +} + +/// Will try to decode the type hint first before decoding the value. See also extractValueWithTypeHint +func extractTypeHintAndValue(_ js: JsAny) throws -> TypedValue { + let obj = try js.castAsObject() + var result = try extractTypeHint(js) + try extractValueWithTypeHint(&result, obj["value", errorMessage: "extractTypeHintAndValue"]) + + if result.value.IsHolding(T: pxr.SdfUnregisteredValue.self) { + var copy = result.value + let unregistered = copy.Get() as pxr.SdfUnregisteredValue + if result.otherTypeName == "SdfPath" { + if !unregistered.GetValue().IsHolding(T: std.string.self) { + throw JsDecodingError.sdfPathSdfUnregisteredValueWasntHoldingAString + + } + + // Important: mismatched-types.usda needs to add "<" and ">", + // so default-relationship.usda has to filter them out here. + // Very tricky to handle misencoded types in Sdf in all cases. + copy = unregistered.GetValue() + var unregisteredString = String(copy.Get() as std.string) + if unregisteredString.first == "<" && unregisteredString.last == ">" { + unregisteredString = String(unregisteredString.dropFirst().dropLast()) + } + result.value = pxr.VtValue(pxr.SdfPath(unregisteredString)) + } + } + + return result +} +func writeTypeHintAndValue(_ value: TypedValue) throws -> JsAny { + [ + "type" : writeTypeHint(value), + "value" : try writeValueWithoutTypeHint(value) + ] +} + +func extractTimeCodeValueMapWithTypeHint(_ js: JsAny, _ type: TypedValue) throws -> pxr.SdfTimeSampleMap { + var result = pxr.SdfTimeSampleMap() + + for (k, v) in try js.castAsObject() { + guard let d = Double(k) else { + throw JsDecodingError.timeSampleMapKeyWasntDouble(k) + } + var type = type + try extractValueWithTypeHint(&type, v) + result[d] = type.value + } + + return result +} +func writeTimeCodeValueMapWithoutTypeHint(_ samples: pxr.SdfTimeSampleMap, _ type: TypedValue) throws -> JsAny { + var result = [String : JsAny]() + for kvPair in samples { + var temp = type + temp.value = kvPair.second + result[String(kvPair.first)] = try writeValueWithoutTypeHint(temp) + } + return .object(result) +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/plugInfo.json b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/plugInfo.json new file mode 100644 index 0000000000..85464421d9 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Sources/sdfJson/plugInfo.json @@ -0,0 +1,25 @@ +{ + "Plugins": [ + { + "Info": { + "Types": { + "SdfJsonFileFormat" : { + "bases": ["SdfFileFormat"], + "extensions": [ + "json" + ], + "formatId": "json", + "primary": true, + "target": "usd", + "supportsEditing": false + } + } + }, + "Name": "sdfJson", + "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@", + "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@", + "Root": "@PLUG_INFO_ROOT@", + "Type": "library" + } + ] +} diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/SwiftUsd b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/SwiftUsd new file mode 120000 index 0000000000..c866b86874 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/SwiftUsd @@ -0,0 +1 @@ +../../../.. \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Tests/CodeCoverageTests.swift b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Tests/CodeCoverageTests.swift new file mode 120000 index 0000000000..d6f4e972b4 --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Tests/CodeCoverageTests.swift @@ -0,0 +1 @@ +../../Tests/CodeCoverageTests.swift \ No newline at end of file diff --git a/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Tests/Resources b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Tests/Resources new file mode 120000 index 0000000000..fe08fab09e --- /dev/null +++ b/Examples/Plugins/SdfFileFormat/sdfJson_Swift/Tests/Resources @@ -0,0 +1 @@ +../../Tests/usdcat-tests/Resources \ No newline at end of file diff --git a/SwiftUsd.docc/AboutThisRepo/OngoingWork.md b/SwiftUsd.docc/AboutThisRepo/OngoingWork.md index e3775a0a46..875cabd11d 100644 --- a/SwiftUsd.docc/AboutThisRepo/OngoingWork.md +++ b/SwiftUsd.docc/AboutThisRepo/OngoingWork.md @@ -9,6 +9,9 @@ SwiftUsd is currently a work-in-progress. Here is a list of potential future imp - Include tvOS binaries ### Small items +- `pxr.SdfZipFile.Find` should return check if the underlying iterator is at the end and return nil instead of returning a non-optional `Overlay.SdfZipFileIteratorWrapper` (next major release) +- Make `pxr.HioImage.OpenForReading/Writing` unavailable (next major release) +- Make `Overlay.HioImageSubclass.get_cxx()` and `.new()` unavailable (next major release) - Add missing `SWIFT_NONMUTATING`: - `pxr.UsdInherits` - `pxr.UsdPrim.RemoveProperty` @@ -20,6 +23,7 @@ SwiftUsd is currently a work-in-progress. Here is a list of potential future imp - Does API Notes support renaming extern variables, e.g. for `pxr::TfStaticData`? ### Medium items +- ast-answerer should report "abstract value types" as not being imported and not do code-gen for them (next major release) - Paper over `pxr::UsdSchemaBase::GetPrim()` by renaming the method and extending each subclass to have a definition of it. - Investigate adding `requires cplusplus` in the modulemap, which may or may not improve code completion - Why wasn't the typedef `pxr::SdfLayer::FileFormatArguments` found by ast-answerer? diff --git a/SwiftUsd.docc/TechnicalDetails/WritingAndUsingOpenUSDPlugins.md b/SwiftUsd.docc/TechnicalDetails/WritingAndUsingOpenUSDPlugins.md index 15f2045b62..cee71e779e 100644 --- a/SwiftUsd.docc/TechnicalDetails/WritingAndUsingOpenUSDPlugins.md +++ b/SwiftUsd.docc/TechnicalDetails/WritingAndUsingOpenUSDPlugins.md @@ -57,7 +57,7 @@ PXR_NAMESPACE_CLOSE_SCOPE ## Writing plugins in Swift with SwiftUsd See [SwiftUsd/Examples/Plugins/HioImage/hioPpm_Swift](https://github.com/apple/SwiftUsd/tree/main/Examples/Plugins/HioImage/hioPpm_Swift) for an example plugin. -> Note: Currently, only HioImage plugins can be written in Swift. +> Note: Currently, only HioImage and SdfFileFormat plugins can be written in Swift. 1. Create a Swift Package for your plugin diff --git a/source/SwiftOverlay/Codable.swift b/source/SwiftOverlay/Codable.swift index e2aaf03453..73252fb7d6 100644 --- a/source/SwiftOverlay/Codable.swift +++ b/source/SwiftOverlay/Codable.swift @@ -1462,6 +1462,24 @@ extension pxr.SdfPath: Codable { } } +extension pxr.SdfPathExpression: Codable { + public init(from decoder: Decoder) throws { + var container = try decoder.singleValueContainer() + + let x = try container.decode(String.self) + + self.init(std.string(x), "") + } + + public func encode(to encoder: Encoder) throws { + var container = try encoder.singleValueContainer() + + let x = String(self.GetText()) + + try container.encode(x) + } +} + // MARK: Usd extension pxr.UsdTimeCode: Codable { diff --git a/source/SwiftOverlay/Math.cpp b/source/SwiftOverlay/Math.cpp index 229d55e5d1..2e081b4b15 100644 --- a/source/SwiftOverlay/Math.cpp +++ b/source/SwiftOverlay/Math.cpp @@ -21,6 +21,26 @@ #include "swiftUsd/SwiftOverlay/Math.h" -const double* __Overlay::GfMatrix4d_subscript_workaround(const pxr::GfMatrix4d& x, int i) { +const double* __Overlay::GfMatrix2d_subscript_workaround(const pxr::GfMatrix2d &x, int i) { + return x[i]; +} + +double* __Overlay::GfMatrix2d_mutable_subscript_workaround(pxr::GfMatrix2d &x, int i) { + return x[i]; +} + +const double* __Overlay::GfMatrix3d_subscript_workaround(const pxr::GfMatrix3d &x, int i) { + return x[i]; +} + +double* __Overlay::GfMatrix3d_mutable_subscript_workaround(pxr::GfMatrix3d &x, int i) { + return x[i]; +} + +const double* __Overlay::GfMatrix4d_subscript_workaround(const pxr::GfMatrix4d &x, int i) { + return x[i]; +} + +double* __Overlay::GfMatrix4d_mutable_subscript_workaround(pxr::GfMatrix4d &x, int i) { return x[i]; } diff --git a/source/SwiftOverlay/Math.h b/source/SwiftOverlay/Math.h index b081c49103..bbf800da18 100644 --- a/source/SwiftOverlay/Math.h +++ b/source/SwiftOverlay/Math.h @@ -23,11 +23,20 @@ #include "pxr/pxr.h" #include "pxr/base/gf/rotation.h" +#include "pxr/base/gf/matrix2d.h" +#include "pxr/base/gf/matrix3d.h" #include "pxr/base/gf/matrix4d.h" namespace __Overlay { // Workaround for https://github.com/swiftlang/swift/issues/83112 (Calling Swift subscript across module boundary accesses uninitialized memory in Release (C++ interop)) + const double* GfMatrix2d_subscript_workaround(const pxr::GfMatrix2d& x, int i); + double* GfMatrix2d_mutable_subscript_workaround(pxr::GfMatrix2d& x, int i); + + const double* GfMatrix3d_subscript_workaround(const pxr::GfMatrix3d& x, int i); + double* GfMatrix3d_mutable_subscript_workaround(pxr::GfMatrix3d& x, int i); + const double* GfMatrix4d_subscript_workaround(const pxr::GfMatrix4d& x, int i); + double* GfMatrix4d_mutable_subscript_workaround(pxr::GfMatrix4d& x, int i); } #endif /* SWIFTUSD_SWIFTOVERLAY_MATH_H */ diff --git a/source/SwiftOverlay/Math.swift b/source/SwiftOverlay/Math.swift index abc9d8bd79..92a6074e3c 100644 --- a/source/SwiftOverlay/Math.swift +++ b/source/SwiftOverlay/Math.swift @@ -36,12 +36,7 @@ extension pxr.GfMatrix4d { return x } } -extension pxr.GfMatrix4d { - public subscript(_ x: Int) -> UnsafePointer { - // Workaround for https://github.com/swiftlang/swift/issues/83112 (Calling Swift subscript across module boundary accesses uninitialized memory in Release (C++ interop)) - return __Overlay.GfMatrix4d_subscript_workaround(self, Int32(x)) - } -} + extension pxr.GfHalf { public static func +(lhs: pxr.GfHalf, rhs: pxr.GfHalf) -> pxr.GfHalf { return pxr.GfHalf(Float(lhs) + Float(rhs)) @@ -55,3 +50,47 @@ public func *(lhs: pxr.GfVec3f, rhs: Float) -> pxr.GfVec3f { pxr.GfVec3f(lhs[0] * rhs, lhs[1] * rhs, lhs[2] * rhs) } + + + +extension pxr.GfMatrix2d { + public subscript(_ x: Int) -> UnsafePointer { + borrowing get { + // Workaround for https://github.com/swiftlang/swift/issues/83112 (Calling Swift subscript across module boundary accesses uninitialized memory in Release (C++ interop)) + __Overlay.GfMatrix2d_subscript_workaround(self, Int32(x)) + } + } + + @_disfavoredOverload + public subscript(_ x: Int) -> UnsafeMutablePointer { + mutating get { __Overlay.GfMatrix2d_mutable_subscript_workaround(&self, Int32(x)) } + } +} + +extension pxr.GfMatrix3d { + public subscript(_ x: Int) -> UnsafePointer { + borrowing get { + // Workaround for https://github.com/swiftlang/swift/issues/83112 (Calling Swift subscript across module boundary accesses uninitialized memory in Release (C++ interop)) + __Overlay.GfMatrix3d_subscript_workaround(self, Int32(x)) + } + } + + @_disfavoredOverload + public subscript(_ x: Int) -> UnsafeMutablePointer { + mutating get { __Overlay.GfMatrix3d_mutable_subscript_workaround(&self, Int32(x)) } + } +} + +extension pxr.GfMatrix4d { + public subscript(_ x: Int) -> UnsafePointer { + borrowing get { + // Workaround for https://github.com/swiftlang/swift/issues/83112 (Calling Swift subscript across module boundary accesses uninitialized memory in Release (C++ interop)) + __Overlay.GfMatrix4d_subscript_workaround(self, Int32(x)) + } + } + + @_disfavoredOverload + public subscript(_ x: Int) -> UnsafeMutablePointer { + mutating get { __Overlay.GfMatrix4d_mutable_subscript_workaround(&self, Int32(x)) } + } +} diff --git a/source/SwiftOverlay/MethodsReturningRefererences.swift b/source/SwiftOverlay/MethodsReturningRefererences.swift index bbe2658734..7d892f9fb9 100644 --- a/source/SwiftOverlay/MethodsReturningRefererences.swift +++ b/source/SwiftOverlay/MethodsReturningRefererences.swift @@ -378,4 +378,50 @@ extension pxr.SdfAssetPath { __GetResolvedPathUnsafe().pointee } } -#endif // #if compiler(>=6.4) \ No newline at end of file +#endif // #if compiler(>=6.4) + +extension pxr.SdfUnregisteredValue { + public borrowing func GetValue() -> pxr.VtValue { __GetValueUnsafe().pointee } +} + +extension pxr.SdfReference { + public borrowing func GetAssetPath() -> std.string { __GetAssetPathUnsafe().pointee } + public borrowing func GetPrimPath() -> pxr.SdfPath { __GetPrimPathUnsafe().pointee } + public borrowing func GetLayerOffset() -> pxr.SdfLayerOffset { __GetLayerOffsetUnsafe().pointee } + public borrowing func GetCustomData() -> pxr.VtDictionary { __GetCustomDataUnsafe().pointee } +} + +extension pxr.SdfPayload { + public borrowing func GetAssetPath() -> std.string { __GetAssetPathUnsafe().pointee } + public borrowing func GetPrimPath() -> pxr.SdfPath { __GetPrimPathUnsafe().pointee } + public borrowing func GetLayerOffset() -> pxr.SdfLayerOffset { __GetLayerOffsetUnsafe().pointee } +} + +// Prior to Swift 6.4, the compiler imports methods returning `const FRT&` from `SWIFT_SELF_CONTAINED`/`SwiftImportAs: owned` +// types as `__Unsafe`, but starting in Swift 6.4, it imports them directly. +#if compiler(<6.4) +extension pxr.SdfSpec { + public borrowing func GetSchema() -> pxr.SdfSchemaBase { __GetSchemaUnsafe() } +} +extension pxr.SdfPropertySpec { + public borrowing func GetSchema() -> pxr.SdfSchemaBase { __GetSchemaUnsafe() } +} +extension pxr.SdfPrimSpec { + public borrowing func GetSchema() -> pxr.SdfSchemaBase { __GetSchemaUnsafe() } +} +extension pxr.SdfVariantSetSpec { + public borrowing func GetSchema() -> pxr.SdfSchemaBase { __GetSchemaUnsafe() } +} +extension pxr.SdfVariantSpec { + public borrowing func GetSchema() -> pxr.SdfSchemaBase { __GetSchemaUnsafe() } +} +extension pxr.SdfAttributeSpec { + public borrowing func GetSchema() -> pxr.SdfSchemaBase { __GetSchemaUnsafe() } +} +extension pxr.SdfRelationshipSpec { + public borrowing func GetSchema() -> pxr.SdfSchemaBase { __GetSchemaUnsafe() } +} +extension pxr.SdfPseudoRootSpec { + public borrowing func GetSchema() -> pxr.SdfSchemaBase { __GetSchemaUnsafe() } +} +#endif // #if compiler(<6.4) \ No newline at end of file diff --git a/source/SwiftOverlay/SdfSpecHandle.h b/source/SwiftOverlay/SdfSpecHandle.h index 12419e0cfe..0a8c1a209c 100644 --- a/source/SwiftOverlay/SdfSpecHandle.h +++ b/source/SwiftOverlay/SdfSpecHandle.h @@ -21,6 +21,7 @@ #ifndef SWIFTUSD_SWIFTOVERLAY_SDFSPECHANDLE_H #define SWIFTUSD_SWIFTOVERLAY_SDFSPECHANDLE_H +#include #include "pxr/usd/sdf/spec.h" #include "pxr/usd/sdf/propertySpec.h" #include "pxr/usd/sdf/primSpec.h" @@ -39,6 +40,13 @@ namespace __Overlay { pxr::SdfAttributeSpec operatorArrow(const pxr::SdfAttributeSpecHandle& x); pxr::SdfRelationshipSpec operatorArrow(const pxr::SdfRelationshipSpecHandle& x); pxr::SdfPseudoRootSpec operatorArrow(const pxr::SdfPseudoRootSpecHandle& x); + + template + void dynamic_cast_sdf_spec_handles(Src src, Dest& out) { + static_assert(std::is_same_v>); + static_assert(std::is_same_v>); + out = pxr::TfDynamic_cast(src); + } } #endif /* SWIFTUSD_SWIFTOVERLAY_SDFSPECHANDLE_H */ diff --git a/source/SwiftOverlay/SdfSpecHandle.swift b/source/SwiftOverlay/SdfSpecHandle.swift index 99de9ab5ee..2613b6f392 100644 --- a/source/SwiftOverlay/SdfSpecHandle.swift +++ b/source/SwiftOverlay/SdfSpecHandle.swift @@ -20,6 +20,8 @@ import Foundation +// MARK: SdfSpecHandle.pointee + extension pxr.SdfSpecHandle { public var pointee: Self.SpecType { __Overlay.operatorArrow(self) @@ -60,3 +62,162 @@ extension pxr.SdfPseudoRootSpecHandle { __Overlay.operatorArrow(self) } } + +// MARK: SdfSpec upcasting/downcasting + +extension pxr.SdfSpec { + // Up + public init(_ x: pxr.SdfPropertySpec) { + let oldHandle = pxr.SdfPropertySpecHandle(x) + var newHandle = pxr.SdfSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } + public init(_ x: pxr.SdfPrimSpec) { + let oldHandle = pxr.SdfPrimSpecHandle(x) + var newHandle = pxr.SdfSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } + public init(_ x: pxr.SdfVariantSetSpec) { + let oldHandle = pxr.SdfVariantSetSpecHandle(x) + var newHandle = pxr.SdfSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } + public init(_ x: pxr.SdfVariantSpec) { + let oldHandle = pxr.SdfVariantSpecHandle(x) + var newHandle = pxr.SdfSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } + public init(_ x: pxr.SdfAttributeSpec) { + let oldHandle = pxr.SdfAttributeSpecHandle(x) + var newHandle = pxr.SdfSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } + public init(_ x: pxr.SdfRelationshipSpec) { + let oldHandle = pxr.SdfRelationshipSpecHandle(x) + var newHandle = pxr.SdfSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } + public init(_ x: pxr.SdfPseudoRootSpec) { + let oldHandle = pxr.SdfPseudoRootSpecHandle(x) + var newHandle = pxr.SdfSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } +} +extension pxr.SdfPropertySpec { + // Down + public init?(_ x: pxr.SdfSpec) { + let oldHandle = pxr.SdfSpecHandle(x) + var newHandle = pxr.SdfPropertySpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } + // Up + public init(_ x: pxr.SdfAttributeSpec) { + let oldHandle = pxr.SdfAttributeSpecHandle(x) + var newHandle = pxr.SdfPropertySpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } + public init(_ x: pxr.SdfRelationshipSpec) { + let oldHandle = pxr.SdfRelationshipSpecHandle(x) + var newHandle = pxr.SdfPropertySpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } +} +extension pxr.SdfPrimSpec { + // Down + public init?(_ x: pxr.SdfSpec) { + let oldHandle = pxr.SdfSpecHandle(x) + var newHandle = pxr.SdfPrimSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } + // Up + public init(_ x: pxr.SdfPseudoRootSpec) { + let oldHandle = pxr.SdfPseudoRootSpecHandle(x) + var newHandle = pxr.SdfPrimSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + self = newHandle.pointee + } +} +extension pxr.SdfVariantSetSpec { + // Down + public init?(_ x: pxr.SdfSpec) { + let oldHandle = pxr.SdfSpecHandle(x) + var newHandle = pxr.SdfVariantSetSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } +} +extension pxr.SdfVariantSpec { + // Down + public init?(_ x: pxr.SdfSpec) { + let oldHandle = pxr.SdfSpecHandle(x) + var newHandle = pxr.SdfVariantSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } +} +extension pxr.SdfAttributeSpec { + // Down + public init?(_ x: pxr.SdfSpec) { + let oldHandle = pxr.SdfSpecHandle(x) + var newHandle = pxr.SdfAttributeSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } + public init?(_ x: pxr.SdfPropertySpec) { + let oldHandle = pxr.SdfPropertySpecHandle(x) + var newHandle = pxr.SdfAttributeSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } +} +extension pxr.SdfRelationshipSpec { + // Down + public init?(_ x: pxr.SdfSpec) { + let oldHandle = pxr.SdfSpecHandle(x) + var newHandle = pxr.SdfRelationshipSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } + public init?(_ x: pxr.SdfPropertySpec) { + let oldHandle = pxr.SdfPropertySpecHandle(x) + var newHandle = pxr.SdfRelationshipSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } +} +extension pxr.SdfPseudoRootSpec { + // Down + public init?(_ x: pxr.SdfSpec) { + let oldHandle = pxr.SdfSpecHandle(x) + var newHandle = pxr.SdfPseudoRootSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } + public init?(_ x: pxr.SdfPrimSpec) { + let oldHandle = pxr.SdfPrimSpecHandle(x) + var newHandle = pxr.SdfPseudoRootSpecHandle() + __Overlay.dynamic_cast_sdf_spec_handles(oldHandle, &newHandle) + guard Bool(newHandle) else { return nil } + self = newHandle.pointee + } +} diff --git a/source/SwiftOverlay/Sequence.swift b/source/SwiftOverlay/Sequence.swift index ccf17e3660..9855f4b931 100644 --- a/source/SwiftOverlay/Sequence.swift +++ b/source/SwiftOverlay/Sequence.swift @@ -179,3 +179,11 @@ extension pxr.GfMultiInterval: CxxSequence { public typealias Element = pxr.GfInterval } extension pxr.GfMultiInterval.const_iterator: UnsafeCxxInputIterator {} + + +extension pxr.TsKnotMap: CxxSequence { + public typealias Element = pxr.TsKnot + public typealias RawIterator = const_iterator +} + +extension pxr.SdfTimeSampleMap: Sequence, CxxSequence, CxxDictionary {} \ No newline at end of file diff --git a/source/SwiftOverlay/SwiftSubclassCxx_handwritten.swift b/source/SwiftOverlay/SwiftSubclassCxx_handwritten.swift index 0f164d645e..1aa1766ee3 100644 --- a/source/SwiftOverlay/SwiftSubclassCxx_handwritten.swift +++ b/source/SwiftOverlay/SwiftSubclassCxx_handwritten.swift @@ -93,4 +93,21 @@ extension pxr.HioImage { public static func OpenForWriting(_ filename: std.string) -> pxr.HioImageSharedPtr { return __OpenForWritingUnsafe(filename) } -} \ No newline at end of file +} + +extension __OverlaySwift.HioImage.SwiftAdapter { + /// Almost all users should have no need to access the CxxAdapter, because it's an + /// internal implementation detail of how SwiftUsd and ast-answerer allow Swift + /// classes to "subclass" from certain C++ types + @_documentation(visibility: internal) + @available(*, deprecated, message: "This function can be memory unsafe and should not be used") + public func get_cxx() -> __Overlay.HioImage.CxxAdapter? { + return __get_cxxUnsafe() + } + + @_documentation(visibility: internal) + @available(*, deprecated, message: "Use Overlay.HioImageSubclass.init() instead") + public static func new() -> Overlay.HioImageSubclass { + return (Self.self as! Overlay.HioImageSubclass.Type).init() + } +} diff --git a/source/SwiftOverlay/TsKnot.cpp b/source/SwiftOverlay/TsKnot.cpp new file mode 100644 index 0000000000..735c96e756 --- /dev/null +++ b/source/SwiftOverlay/TsKnot.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "swiftUsd/SwiftOverlay/TsKnot.h" + +bool Overlay::GetValue(const pxr::TsKnot &knot, pxr::VtValue *valueOut) { + return knot.GetValue(valueOut); +} + +bool Overlay::GetPreValue(const pxr::TsKnot &knot, pxr::VtValue *valueOut) { + return knot.GetPreValue(valueOut); +} + +bool Overlay::GetPreTanSlope(const pxr::TsKnot &knot, pxr::VtValue *valueOut) { + return knot.GetPreTanSlope(valueOut); +} + +bool Overlay::GetPostTanSlope(const pxr::TsKnot &knot, pxr::VtValue *valueOut) { + return knot.GetPostTanSlope(valueOut); +} diff --git a/source/SwiftOverlay/TsKnot.h b/source/SwiftOverlay/TsKnot.h new file mode 100644 index 0000000000..9cfd6e2546 --- /dev/null +++ b/source/SwiftOverlay/TsKnot.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef SWIFTUSD_SWIFTOVERLAY_TSKNOT_H +#define SWIFTUSD_SWIFTOVERLAY_TSKNOT_H + +#include "pxr/base/ts/knot.h" +#include "pxr/base/vt/value.h" + +namespace Overlay { + bool GetValue(const pxr::TsKnot& knot, pxr::VtValue* valueOut); + bool GetPreValue(const pxr::TsKnot& knot, pxr::VtValue* valueOut); + bool GetPreTanSlope(const pxr::TsKnot& knot, pxr::VtValue* valueOut); + bool GetPostTanSlope(const pxr::TsKnot& knot, pxr::VtValue* valueOut); +} + +#endif /* SWIFTUSD_SWIFTOVERLAY_TSKNOT_H */ diff --git a/source/SwiftOverlay/TypeConversionInitializers.swift b/source/SwiftOverlay/TypeConversionInitializers.swift index a1c59d42c6..8e4868b1d9 100644 --- a/source/SwiftOverlay/TypeConversionInitializers.swift +++ b/source/SwiftOverlay/TypeConversionInitializers.swift @@ -39,6 +39,12 @@ extension pxr.GfHalf { } } +extension Double { + public init(_ x: pxr.GfTimeCode) { + self = x.GetValue() + } +} +// GfTimeCode.init(Double) provided by timeCode.h extension String { public init(_ token: pxr.TfToken) { diff --git a/source/SwiftOverlay/Typedefs.h b/source/SwiftOverlay/Typedefs.h index aa5f95d989..22b2a88631 100644 --- a/source/SwiftOverlay/Typedefs.h +++ b/source/SwiftOverlay/Typedefs.h @@ -44,6 +44,7 @@ #include "pxr/base/tf/diagnosticBase.h" #include "pxr/base/vt/array.h" #include "pxr/usd/sdf/assetPath.h" +#include "pxr/usd/sdf/pathExpression.h" #include "pxr/exec/execUsd/valueKey.h" namespace Overlay { @@ -75,6 +76,7 @@ namespace Overlay { typedef std::shared_ptr TfDiagnosticBase_Shared_Ptr; typedef pxr::VtArray SdfAssetPath_VtArray; + typedef pxr::VtArray SdfPathExpression_VtArray; } #endif /* SWIFTUSD_SWIFTOVERLAY_TYPEDEFS_H */ diff --git a/source/SwiftOverlay/VtArrayProtocol.swift b/source/SwiftOverlay/VtArrayProtocol.swift index 114ac311ad..c34b4e767e 100644 --- a/source/SwiftOverlay/VtArrayProtocol.swift +++ b/source/SwiftOverlay/VtArrayProtocol.swift @@ -394,3 +394,9 @@ extension pxr.VtTimeCodeArray: __Overlay.VtArrayProtocol { __Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count })) } } + +extension Overlay.SdfPathExpression_VtArray: __Overlay.VtArrayProtocol { + public mutating func __assign(_ p: UnsafeBufferPointer) { + __Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count })) + } +} \ No newline at end of file diff --git a/source/SwiftOverlay/operatorBool.cpp b/source/SwiftOverlay/operatorBool.cpp index acf9293fa8..084b8539d2 100644 --- a/source/SwiftOverlay/operatorBool.cpp +++ b/source/SwiftOverlay/operatorBool.cpp @@ -48,6 +48,9 @@ bool __Overlay::convertToBool(const pxr::UsdGeomXformOp& x) { bool __Overlay::convertToBool(const pxr::UsdRelationship& x) { return (bool) x; } +bool __Overlay::convertToBool(const pxr::SdfValueTypeName &x) { + return (bool) x; +} bool __Overlay::convertToBool(const pxr::SdfSpecHandle& x) { return (bool) x; } @@ -78,6 +81,13 @@ bool __Overlay::convertToBool(const pxr::ArResolvedPath& x) { bool __Overlay::convertToBool(const pxr::SdfZipFile& x) { return (bool) x; } +bool __Overlay::convertToBool(const pxr::SdfVariantSetsProxy &x) { + return (bool) x; +} + +bool __Overlay::convertToBool(const pxr::SdfVariantSelectionProxy &x) { + return (bool) x; +} bool __Overlay::convertToBool(const Overlay::ArAssetWrapper& x) { return (bool) x; } diff --git a/source/SwiftOverlay/operatorBool.h b/source/SwiftOverlay/operatorBool.h index e88c984df8..620439ec09 100644 --- a/source/SwiftOverlay/operatorBool.h +++ b/source/SwiftOverlay/operatorBool.h @@ -31,6 +31,7 @@ #include "pxr/usd/usd/attribute.h" #include "pxr/usd/usdGeom/xformOp.h" #include "pxr/usd/usd/relationship.h" +#include "pxr/usd/sdf/valueTypeName.h" #include "pxr/usd/sdf/spec.h" #include "pxr/usd/sdf/propertySpec.h" #include "pxr/usd/sdf/primSpec.h" @@ -39,6 +40,9 @@ #include "pxr/usd/sdf/attributeSpec.h" #include "pxr/usd/sdf/relationshipSpec.h" #include "pxr/usd/sdf/pseudoRootSpec.h" +#include "pxr/usd/sdf/childrenProxy.h" +#include "pxr/usd/sdf/proxyTypes.h" +#include "pxr/usd/sdf/mapEditProxy.h" #include "pxr/usd/sdf/zipFile.h" #include "pxr/usd/ar/resolvedPath.h" #include "pxr/imaging/hgi/texture.h" @@ -56,6 +60,7 @@ namespace __Overlay { bool convertToBool(const pxr::UsdAttribute& x); bool convertToBool(const pxr::UsdGeomXformOp& x); bool convertToBool(const pxr::UsdRelationship& x); + bool convertToBool(const pxr::SdfValueTypeName& x); bool convertToBool(const pxr::SdfSpecHandle& x); bool convertToBool(const pxr::SdfPropertySpecHandle& x); bool convertToBool(const pxr::SdfPrimSpecHandle& x); @@ -64,6 +69,8 @@ namespace __Overlay { bool convertToBool(const pxr::SdfAttributeSpecHandle& x); bool convertToBool(const pxr::SdfRelationshipSpecHandle& x); bool convertToBool(const pxr::SdfPseudoRootSpecHandle& x); + bool convertToBool(const pxr::SdfVariantSetsProxy& x); + bool convertToBool(const pxr::SdfVariantSelectionProxy& x); bool convertToBool(const pxr::ArResolvedPath& x); bool convertToBool(const pxr::SdfZipFile& x); bool convertToBool(const pxr::HgiTextureHandle& x); diff --git a/source/SwiftOverlay/operatorBool.swift b/source/SwiftOverlay/operatorBool.swift index accf3792e0..1089269102 100644 --- a/source/SwiftOverlay/operatorBool.swift +++ b/source/SwiftOverlay/operatorBool.swift @@ -55,6 +55,21 @@ extension Bool { self = __Overlay.convertToBool(handle) } + /// Returns `true` if the proxy object is valid + public init(_ x: pxr.SdfVariantSetsProxy) { + self.init(__Overlay.convertToBool(x)) + } + + /// Returns `true` if the value is valid + public init(_ x: pxr.SdfVariantSelectionProxy) { + self.init(__Overlay.convertToBool(x)) + } + + /// Returns `true` if the type name is valid and non-empty + public init(_ x: pxr.SdfValueTypeName) { + self.init(__Overlay.convertToBool(x)) + } + /// Returns `true` if the `UsdObject` is valid public init(_ object: pxr.UsdObject) { self = object.IsValid() diff --git a/source/Wrappers/PluginAndTfMacros.cpp b/source/Wrappers/PluginAndTfMacros.cpp index 8b30de0a80..04da5cc70e 100644 --- a/source/Wrappers/PluginAndTfMacros.cpp +++ b/source/Wrappers/PluginAndTfMacros.cpp @@ -22,8 +22,33 @@ #include #include "pxr/base/tf/type.h" -#include "pxr/imaging/hio/image.h" +#include "pxr/usd/sdf/fileFormat.h" + + + +namespace __Overlay { + class SwiftSdfFileFormatFactory: public pxr::Sdf_FileFormatFactoryBase { + public: + void*_Nonnull(*_Nonnull newImpl)(); + + SwiftSdfFileFormatFactory(void*_Nonnull(*_Nonnull newImpl)()) : newImpl(newImpl) {} + + pxr::SdfFileFormatRefPtr New() const { + void* p = newImpl(); + return pxr::TfCreateRefPtr(static_cast(p)); + } + }; + void setSwiftSdfFileFormatPluginFactory(std::string typeName, void*_Nonnull(*_Nonnull newImpl)()) { + pxr::TfType t = pxr::TfType::Declare(typeName); + t.SetFactory(std::make_unique(newImpl)); + } +} + + +#include "swiftUsd/defines.h" +#if SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT +#include "pxr/imaging/hio/image.h" namespace __Overlay { class SwiftHioImageFactory: public pxr::HioImageFactoryBase { @@ -43,3 +68,5 @@ namespace __Overlay { t.SetFactory(std::make_unique(newImpl)); } } + +#endif // #if SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT diff --git a/source/Wrappers/PluginAndTfMacros.h b/source/Wrappers/PluginAndTfMacros.h index 6e4dbf1ab4..04f531638f 100644 --- a/source/Wrappers/PluginAndTfMacros.h +++ b/source/Wrappers/PluginAndTfMacros.h @@ -23,8 +23,17 @@ #include +namespace __Overlay { + void setSwiftSdfFileFormatPluginFactory(std::string typeName, void*_Nonnull(*_Nonnull newImpl)()); +} + + +#include "swiftUsd/defines.h" +#if SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT namespace __Overlay { void setSwiftHioImagePluginFactory(std::string typeName, void*_Nonnull(*_Nonnull newImpl)()); } +#endif // #if SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT + #endif /* SWIFTUSD_WRAPPERS_PLUGINANDTFMACROS_H */ diff --git a/source/Wrappers/StdOstreamWrapper.cpp b/source/Wrappers/StdOstreamWrapper.cpp new file mode 100644 index 0000000000..dea1bba8b9 --- /dev/null +++ b/source/Wrappers/StdOstreamWrapper.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#include "swiftUsd/Wrappers/StdOstreamWrapper.h" + +#if !__swift__ +void Overlay::StdOstreamWrapper::operator<<(std::string const& s) const { + (*_impl) << s; +} +#endif // #if !__swift__ + +void Overlay::StdOstreamWrapper::__operatorLessThanLessThan(std::string const& s) const { + (*_impl) << s; +} + +Overlay::StdOstreamWrapper::StdOstreamWrapper(std::ostream& impl) : _impl(&impl) {} + +Overlay::StdOstreamWrapper::~StdOstreamWrapper() { + // Do nothing +} + +std::ostream* Overlay::StdOstreamWrapper::get() const { + return _impl; +} + diff --git a/source/Wrappers/StdOstreamWrapper.h b/source/Wrappers/StdOstreamWrapper.h new file mode 100644 index 0000000000..8d1056a7cb --- /dev/null +++ b/source/Wrappers/StdOstreamWrapper.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +#ifndef SWIFTUSD_WRAPPERS_STDOSTREAMWRAPPER_H +#define SWIFTUSD_WRAPPERS_STDOSTREAMWRAPPER_H + +#include +#include + +namespace Overlay { + /// Minimal std::ostream wrapper for SdfFileFormat plugins. + /// Intentionally not fully-featured. Don't use this unless you're + /// writing an SdfFileFormat plugin. + class StdOstreamWrapper { + public: + #if !__swift__ + // Intentionally return void because Swift's syntax doesn't support + // `a << b << c` without parentheses, so we'd rather users use multiple + // lines for multi-step outputing. + // + // Also, hide from Swift because Swift 6.1 crashes during a SIL phase. + void operator<<(std::string const&) const; + #endif // #if !__swift__ + void __operatorLessThanLessThan(std::string const&) const; + + // MARK: SwiftUsd implementation access + + /// SwiftUsd wrapping constructor + StdOstreamWrapper(std::ostream&); + + StdOstreamWrapper(const StdOstreamWrapper&) = delete; + StdOstreamWrapper& operator=(const StdOstreamWrapper&) = delete; + StdOstreamWrapper(StdOstreamWrapper&&) = default; + StdOstreamWrapper& operator=(StdOstreamWrapper&&) = default; + ~StdOstreamWrapper(); + + std::ostream* get() const; + + private: + std::ostream* _impl; + }; +} + + +#endif /* SWIFTUSD_WRAPPERS_STDOSTREAMWRAPPER_H */ diff --git a/source/Wrappers/StdOstreamWrapper.swift b/source/Wrappers/StdOstreamWrapper.swift new file mode 100644 index 0000000000..dc95754aeb --- /dev/null +++ b/source/Wrappers/StdOstreamWrapper.swift @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// This source file is part of github.com/apple/SwiftUsd +// +// Copyright © 2025 Apple Inc. and the SwiftUsd project authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 +//===----------------------------------------------------------------------===// + +import Foundation + +// Swift 6.1 crashes while compiling this function +#if compiler(>=6.2) +extension Overlay.StdOstreamWrapper { + public static func <<(lhs: borrowing Overlay.StdOstreamWrapper, rhs: some CustomStringConvertible) { + lhs.__operatorLessThanLessThan(std.string(String(describing: rhs))) + } +} +#endif // #if compiler(>=6.2) \ No newline at end of file diff --git a/source/_OpenUSD_MacroImplementations/PluginAndTfMacros.swift b/source/_OpenUSD_MacroImplementations/PluginAndTfMacros.swift index 26cde5fb94..71ecffb506 100644 --- a/source/_OpenUSD_MacroImplementations/PluginAndTfMacros.swift +++ b/source/_OpenUSD_MacroImplementations/PluginAndTfMacros.swift @@ -187,6 +187,37 @@ public struct TF_REGISTRY_FUNCTION_Macro: PeerMacro { } } +enum PluginKind: CaseIterable { + case hioImage + case sdfFileFormat + + static func fromInheritanceClause(_ inheritanceClause: InheritanceClauseSyntax) -> PluginKind? { + for inheritedType in inheritanceClause.inheritedTypes { + for pluginKind in PluginKind.allCases { + if SWIFTUSD_PLUGIN_Macro.extractType(from: inheritedType.type) == pluginKind.inheritanceSpelling { + return pluginKind + } + } + } + return nil + } + + var inheritanceSpelling: [String] { + switch self { + case .hioImage: ["Overlay", "HioImageSubclass"] + case .sdfFileFormat: ["Overlay", "SdfFileFormatSubclass"] + } + } + + var factoryName: String { + switch self { + case .hioImage: "setSwiftHioImagePluginFactory" + case .sdfFileFormat: "setSwiftSdfFileFormatPluginFactory" + } + } +} + + public struct SWIFTUSD_PLUGIN_Macro: PeerMacro { static func extractType(from type: TypeSyntax) -> [String] { var result = [String]() @@ -238,23 +269,14 @@ public struct SWIFTUSD_PLUGIN_Macro: PeerMacro { guard hasFinal else { throw CustomError.message("@SWIFTUSD_PLUGIN can only be applied to final classes") } - - var inheritsCorrectly = false - for inheritedType in inheritanceClause.inheritedTypes { - if extractType(from: inheritedType.type) == ["Overlay", "HioImageSubclass"] { - inheritsCorrectly = true - break - } - } - guard inheritsCorrectly else { + + guard let pluginKind = PluginKind.fromInheritanceClause(inheritanceClause) else { throw CustomError.message("@SWIFTUSD_PLUGIN only works on classes that inherit from OpenUSD plugin entry classes") } // Compute identifiers let userClassName = classDecl.name.text - let factoryName = "setSwiftHioImagePluginFactory" - let adapterName = "__Overlay.HioImage.CxxAdapter" // Finally, form the decl to return. // We want to just return a `@TF_REGISTRY_FUNCTION`-annotated @@ -266,8 +288,8 @@ public struct SWIFTUSD_PLUGIN_Macro: PeerMacro { argumentTypeText: "TfType", body: """ - __Overlay.\(factoryName)("\(userClassName)") { - Unmanaged<\(adapterName)>.passUnretained(\(userClassName).new().get_cxx()!).toOpaque() + __Overlay.\(pluginKind.factoryName)("\(userClassName)") { + \(userClassName).init().__get_cxx_rawUnsafe()! } """ ) diff --git a/source/generated/Comparable.cpp b/source/generated/Comparable.cpp index faa86f2d96..4db569a25f 100644 --- a/source/generated/Comparable.cpp +++ b/source/generated/Comparable.cpp @@ -153,6 +153,10 @@ bool __Overlay::operatorLess(const pxr::SdfSpecHandle& l, const pxr::SdfSpecHandle& r) { return l < r; } +bool __Overlay::operatorLess(const pxr::SdfSchemaBase& l, + const pxr::SdfSchemaBase& r) { + return &l < &r; +} bool __Overlay::operatorLess(const pxr::SdfSchema& l, const pxr::SdfSchema& r) { return &l < &r; diff --git a/source/generated/Comparable.h b/source/generated/Comparable.h index 3990cef5b9..fc01e1246b 100644 --- a/source/generated/Comparable.h +++ b/source/generated/Comparable.h @@ -269,6 +269,8 @@ namespace __Overlay { const pxr::SdfPropertySpec& r); bool operatorLess(const pxr::SdfSpecHandle& l, const pxr::SdfSpecHandle& r); + bool operatorLess(const pxr::SdfSchemaBase& l, + const pxr::SdfSchemaBase& r); bool operatorLess(const pxr::SdfSchema& l, const pxr::SdfSchema& r); bool operatorLess(const pxr::SdfNameChildrenOrderProxy& l, diff --git a/source/generated/Comparable.md b/source/generated/Comparable.md index 61e34b21fc..fda4066f93 100644 --- a/source/generated/Comparable.md +++ b/source/generated/Comparable.md @@ -66,6 +66,7 @@ These types conform to `Comparable` in Swift. - ``OpenUSD/C++/pxr/SdfPropertySpec`` - ``OpenUSD/C++/pxr/SdfHandle`` - ``OpenUSD/C++/pxr/SdfSpec`` +- ``OpenUSD/C++/pxr/SdfSchemaBase`` - ``OpenUSD/C++/pxr/SdfSchema`` - ``OpenUSD/C++/pxr/SdfListProxy`` - ``OpenUSD/C++/pxr/SdfListProxy`` diff --git a/source/generated/Comparable.swift b/source/generated/Comparable.swift index 740e05c6d0..12880479e0 100644 --- a/source/generated/Comparable.swift +++ b/source/generated/Comparable.swift @@ -210,6 +210,11 @@ extension pxr.SdfSpecHandle: Comparable { // classTemplateSpecialization } } extension pxr.SdfSpec: Comparable {} // foundBySwift +extension pxr.SdfSchemaBase: Comparable { // importedAsReference + public static func <(lhs: pxr.SdfSchemaBase, rhs: pxr.SdfSchemaBase) -> Bool { + __Overlay.operatorLess(lhs, rhs) + } +} extension pxr.SdfSchema: Comparable { // importedAsReference public static func <(lhs: pxr.SdfSchema, rhs: pxr.SdfSchema) -> Bool { __Overlay.operatorLess(lhs, rhs) diff --git a/source/generated/Equatable.cpp b/source/generated/Equatable.cpp index 8a0cda00ec..8f314c7c01 100644 --- a/source/generated/Equatable.cpp +++ b/source/generated/Equatable.cpp @@ -621,6 +621,10 @@ bool __Overlay::operatorEqualsEquals(const pxr::SdfSpecHandle& l, const pxr::SdfSpecHandle& r) { return l == r; } +bool __Overlay::operatorEqualsEquals(const pxr::SdfSchemaBase& l, + const pxr::SdfSchemaBase& r) { + return &l == &r; +} bool __Overlay::operatorEqualsEquals(const pxr::SdfSchema& l, const pxr::SdfSchema& r) { return &l == &r; diff --git a/source/generated/Equatable.h b/source/generated/Equatable.h index 86fb046b53..60db1c1d56 100644 --- a/source/generated/Equatable.h +++ b/source/generated/Equatable.h @@ -686,6 +686,8 @@ namespace __Overlay { const pxr::SdfPropertySpec& r); bool operatorEqualsEquals(const pxr::SdfSpecHandle& l, const pxr::SdfSpecHandle& r); + bool operatorEqualsEquals(const pxr::SdfSchemaBase& l, + const pxr::SdfSchemaBase& r); bool operatorEqualsEquals(const pxr::SdfSchema& l, const pxr::SdfSchema& r); bool operatorEqualsEquals(const pxr::SdfNameChildrenOrderProxy& l, diff --git a/source/generated/Equatable.md b/source/generated/Equatable.md index 61396c14ca..f19b4712e8 100644 --- a/source/generated/Equatable.md +++ b/source/generated/Equatable.md @@ -251,6 +251,7 @@ These types conform to `Equatable` in Swift. - ``OpenUSD/C++/pxr/SdfPropertySpec`` - ``OpenUSD/C++/pxr/SdfHandle`` - ``OpenUSD/C++/pxr/SdfSpec`` +- ``OpenUSD/C++/pxr/SdfSchemaBase`` - ``OpenUSD/C++/pxr/SdfSchema`` - ``OpenUSD/C++/pxr/SdfListProxy`` - ``OpenUSD/C++/pxr/SdfListProxy`` diff --git a/source/generated/Equatable.swift b/source/generated/Equatable.swift index 62043b5c13..8647384cb9 100644 --- a/source/generated/Equatable.swift +++ b/source/generated/Equatable.swift @@ -961,6 +961,11 @@ extension pxr.SdfSpecHandle: Equatable { // classTemplateSpecialization } } extension pxr.SdfSpec: Equatable {} // foundBySwift +extension pxr.SdfSchemaBase: Equatable { // importedAsReference + public static func ==(lhs: pxr.SdfSchemaBase, rhs: pxr.SdfSchemaBase) -> Bool { + __Overlay.operatorEqualsEquals(lhs, rhs) + } +} extension pxr.SdfSchema: Equatable { // importedAsReference public static func ==(lhs: pxr.SdfSchema, rhs: pxr.SdfSchema) -> Bool { __Overlay.operatorEqualsEquals(lhs, rhs) diff --git a/source/generated/Hashable.cpp b/source/generated/Hashable.cpp index 47eb43afa9..54e0966f3e 100644 --- a/source/generated/Hashable.cpp +++ b/source/generated/Hashable.cpp @@ -606,6 +606,9 @@ int64_t __Overlay::hash_value(const pxr::SdfSpecHandle& x) { int64_t __Overlay::hash_value(const pxr::SdfSpec& x) { return pxr::TfHash()(x); } +int64_t __Overlay::hash_value(const pxr::SdfSchemaBase& x) { + return (int64_t) &x; +} int64_t __Overlay::hash_value(const pxr::SdfSchema& x) { return (int64_t) &x; } diff --git a/source/generated/Hashable.h b/source/generated/Hashable.h index 7951f9bba3..6a65df32a4 100644 --- a/source/generated/Hashable.h +++ b/source/generated/Hashable.h @@ -451,6 +451,7 @@ namespace __Overlay { int64_t hash_value(const pxr::SdfPropertySpec& x); int64_t hash_value(const pxr::SdfSpecHandle& x); int64_t hash_value(const pxr::SdfSpec& x); + int64_t hash_value(const pxr::SdfSchemaBase& x); int64_t hash_value(const pxr::SdfSchema& x); int64_t hash_value(const pxr::SdfData& x); int64_t hash_value(const pxr::SdfDataRefPtr& x); diff --git a/source/generated/Hashable.md b/source/generated/Hashable.md index 322a42b5d1..3bc9e22806 100644 --- a/source/generated/Hashable.md +++ b/source/generated/Hashable.md @@ -221,6 +221,7 @@ These types conform to `Hashable` in Swift. - ``OpenUSD/C++/pxr/SdfPropertySpec`` - ``OpenUSD/C++/pxr/SdfHandle`` - ``OpenUSD/C++/pxr/SdfSpec`` +- ``OpenUSD/C++/pxr/SdfSchemaBase`` - ``OpenUSD/C++/pxr/SdfSchema`` - ``OpenUSD/C++/pxr/SdfData`` - ``OpenUSD/C++/pxr/TfRefPtr`` diff --git a/source/generated/Hashable.swift b/source/generated/Hashable.swift index 3f795f01a9..23a24c0da2 100644 --- a/source/generated/Hashable.swift +++ b/source/generated/Hashable.swift @@ -1057,6 +1057,11 @@ extension pxr.SdfSpec: Hashable { hasher.combine(__Overlay.hash_value(self)) } } +extension pxr.SdfSchemaBase: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(__Overlay.hash_value(self)) + } +} extension pxr.SdfSchema: Hashable { public func hash(into hasher: inout Hasher) { hasher.combine(__Overlay.hash_value(self)) diff --git a/source/generated/ReferenceTypeConformances.cpp b/source/generated/ReferenceTypeConformances.cpp index 1f6652ca02..2b0f813a1b 100644 --- a/source/generated/ReferenceTypeConformances.cpp +++ b/source/generated/ReferenceTypeConformances.cpp @@ -592,6 +592,37 @@ bool _isNonnull(const pxr::TfWeakPtr & p) { bool _isNonnull(const pxr::TfWeakPtr & p) { return (bool)p;} +void* _Nonnull _address(pxr::SdfSchemaBase* _Nonnull x) { + return reinterpret_cast(x); +} +pxr::TfWeakPtr _asWeakPtrType(pxr::SdfSchemaBase* _Nonnull x) { + return pxr::TfWeakPtr(x); +} +pxr::SdfSchemaBase * _Nullable _fromWeakPtrType(const pxr::TfWeakPtr& x) { + if (!x) { return nullptr; } + return x.operator->(); +} +pxr::SdfSchemaBase * _Nullable _fromConstWeakPtrType(const __SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_ConstWeakPtr& x) { + if (!x) { return nullptr; } + return const_cast(x.operator->()); +} +pxr::TfAnyWeakPtr _asAnyWeakPtr(const pxr::TfWeakPtr& x) { + return pxr::TfAnyWeakPtr(x); +} +pxr::TfWeakPtr_fromAnyWeakPtr__ZN3pxr13SdfSchemaBaseE(const pxr::TfAnyWeakPtr& x) { + if (!x) { return pxr::TfWeakPtr(nullptr); } + pxr::SdfSchemaBase* rawPtr = static_cast(const_cast(x.GetWeakBase())); + return pxr::TfWeakPtr(rawPtr); +} +pxr::TfWeakPtr_nullWeakPtr__ZN3pxr13SdfSchemaBaseE() { + return pxr::TfWeakPtr(nullptr); +} +bool _isNonnull(const pxr::TfWeakPtr & p) { + return (bool)p; +} +bool _isNonnull(const pxr::TfWeakPtr & p) { + return (bool)p;} + void* _Nonnull _address(pxr::SdfSchema* _Nonnull x) { return reinterpret_cast(x); } diff --git a/source/generated/ReferenceTypeConformances.h b/source/generated/ReferenceTypeConformances.h index 75b6db9fae..6dbde92789 100644 --- a/source/generated/ReferenceTypeConformances.h +++ b/source/generated/ReferenceTypeConformances.h @@ -636,6 +636,30 @@ bool _isNonnull(const pxr::TfWeakPtr &) bool _isNonnull(const pxr::TfWeakPtr &) SWIFT_NAME(__SwiftUsd_Typedef___ZN3pxr15SdfAbstractDataE_ConstWeakPtr._isNonnull(self:)); +typedef pxr::SdfSchemaBase __SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE; +typedef pxr::TfWeakPtr __SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_WeakPtr; +typedef pxr::TfWeakPtr __SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_ConstWeakPtr; +void* _Nonnull _address(pxr::SdfSchemaBase* _Nonnull) + SWIFT_NAME(getter:__SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE._address(self:)); +pxr::TfWeakPtr _asWeakPtrType(pxr::SdfSchemaBase* _Nonnull) + SWIFT_NAME(__SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE._asWeakPtrType(self:)); +pxr::SdfSchemaBase * _Nullable _fromWeakPtrType(const pxr::TfWeakPtr&) + // SWIFT_RETURNS_RETAINED is an error on immortal types + SWIFT_NAME(__SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE._fromWeakPtrType(_:)); +pxr::SdfSchemaBase * _Nullable _fromConstWeakPtrType(const pxr::TfWeakPtr &) + // SWIFT_RETURNS_RETAINED is an error on immortal types + SWIFT_NAME(__SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE._fromConstWeakPtrType(_:)); +pxr::TfAnyWeakPtr _asAnyWeakPtr(const pxr::TfWeakPtr&) + SWIFT_NAME(__SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_WeakPtr._asAnyWeakPtr(self:)); +pxr::TfWeakPtr_fromAnyWeakPtr__ZN3pxr13SdfSchemaBaseE(const pxr::TfAnyWeakPtr&) + SWIFT_NAME(__SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_WeakPtr._fromAnyWeakPtr(_:)); +pxr::TfWeakPtr_nullWeakPtr__ZN3pxr13SdfSchemaBaseE() + SWIFT_NAME(__SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_WeakPtr._nullPtr()); +bool _isNonnull(const pxr::TfWeakPtr &) + SWIFT_NAME(__SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_WeakPtr._isNonnull(self:)); +bool _isNonnull(const pxr::TfWeakPtr &) + SWIFT_NAME(__SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_ConstWeakPtr._isNonnull(self:)); + typedef pxr::SdfSchema __SwiftUsd_Typedef___ZN3pxr9SdfSchemaE; typedef pxr::TfWeakPtr __SwiftUsd_Typedef___ZN3pxr9SdfSchemaE_WeakPtr; typedef pxr::TfWeakPtr __SwiftUsd_Typedef___ZN3pxr9SdfSchemaE_ConstWeakPtr; diff --git a/source/generated/ReferenceTypeConformances.swift b/source/generated/ReferenceTypeConformances.swift index ba2333f691..f603931f90 100644 --- a/source/generated/ReferenceTypeConformances.swift +++ b/source/generated/ReferenceTypeConformances.swift @@ -216,6 +216,17 @@ extension __SwiftUsd_Typedef___ZN3pxr15SdfAbstractDataE_ConstWeakPtr: Overlay._T public typealias _TfWeakBaseType = pxr.SdfAbstractData } +extension pxr.SdfSchemaBase: Overlay._SwiftUsdReferenceTypeProtocol { + public typealias _SelfType = pxr.SdfSchemaBase +} +extension pxr.SdfSchemaBase: Overlay._TfWeakBaseProtocol {} +extension __SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_WeakPtr: Overlay._TfWeakPtrProtocol { + public typealias _TfWeakBaseType = pxr.SdfSchemaBase +} +extension __SwiftUsd_Typedef___ZN3pxr13SdfSchemaBaseE_ConstWeakPtr: Overlay._TfConstWeakPtrProtocol { + public typealias _TfWeakBaseType = pxr.SdfSchemaBase +} + extension pxr.SdfSchema: Overlay._SwiftUsdReferenceTypeProtocol { public typealias _SelfType = pxr.SdfSchema } diff --git a/source/generated/Sendable.md b/source/generated/Sendable.md index 2a78d37002..81d6748cde 100644 --- a/source/generated/Sendable.md +++ b/source/generated/Sendable.md @@ -364,6 +364,7 @@ Use this extension method sparingly! - `pxr.SdfValueTypeNameHash` - `pxr.SdfAllowed` - `pxr.SdfSpecTypeRegistration` +- `pxr.SdfSchemaBase.SpecDefinition` - `pxr.SdfFieldKeys_StaticTokenType` - `pxr.SdfChildrenKeys_StaticTokenType` - `pxr.SdfNameKeyPolicy` @@ -1437,6 +1438,8 @@ Use this extension method sparingly! - `pxr.SdfPropertySpec` - `pxr.SdfSpecHandle` - `pxr.SdfSpec` +- `pxr.SdfSchemaBase` +- `pxr.SdfSchemaBase.FieldDefinition` - `pxr.SdfSchema` - `pxr.SdfChangeBlock` - `pxr.SdfPathKeyPolicy` diff --git a/source/generated/Sendable.swift b/source/generated/Sendable.swift index 1db5356e66..fb4b267254 100644 --- a/source/generated/Sendable.swift +++ b/source/generated/Sendable.swift @@ -2418,7 +2418,6 @@ // std::unique_ptr> // pxr::TfSpan // pxr::TfSpan -// std::vector, std::allocator>> // std::pair // std::pair // std::deque, std::allocator>> @@ -3999,6 +3998,7 @@ extension pxr.SdfTupleDimensions: @unchecked Sendable {} extension pxr.SdfValueTypeNameHash: @unchecked Sendable {} extension pxr.SdfAllowed: @unchecked Sendable {} extension pxr.SdfSpecTypeRegistration: @unchecked Sendable {} +extension pxr.SdfSchemaBase.SpecDefinition: @unchecked Sendable {} extension pxr.SdfFieldKeys_StaticTokenType: @unchecked Sendable {} extension pxr.SdfChildrenKeys_StaticTokenType: @unchecked Sendable {} extension pxr.SdfNameKeyPolicy: @unchecked Sendable {} @@ -4935,6 +4935,7 @@ extension pxr.UsdIrImagingTokens_StaticTokenType: @unchecked Sendable {} @available(*, unavailable) extension pxr.JsObject: @unchecked Sendable {} @available(*, unavailable) extension pxr.JsOptionalValue: @unchecked Sendable {} @available(*, unavailable) extension pxr.JsArray: @unchecked Sendable {} +@available(*, unavailable) extension pxr.SdfSchemaBase.FieldDefinition.InfoVec: @unchecked Sendable {} @available(*, unavailable) extension pxr.TraceAggregateTreeRefPtr: @unchecked Sendable {} @available(*, unavailable) extension pxr.TraceAggregateTree: @unchecked Sendable {} @available(*, unavailable) extension pxr.TraceAggregateNodeRefPtr: @unchecked Sendable {} @@ -5027,6 +5028,8 @@ extension pxr.UsdIrImagingTokens_StaticTokenType: @unchecked Sendable {} @available(*, unavailable) extension pxr.SdfSpecHandle: @unchecked Sendable {} @available(*, unavailable) extension pxr.SdfSpec: @unchecked Sendable {} @available(*, unavailable) extension pxr.SdfSpecHandleVector: @unchecked Sendable {} +@available(*, unavailable) extension pxr.SdfSchemaBase: @unchecked Sendable {} +@available(*, unavailable) extension pxr.SdfSchemaBase.FieldDefinition: @unchecked Sendable {} @available(*, unavailable) extension pxr.SdfSchema: @unchecked Sendable {} @available(*, unavailable) extension pxr.SdfChangeBlock: @unchecked Sendable {} @available(*, unavailable) extension pxr.SdfPathKeyPolicy: @unchecked Sendable {} diff --git a/source/generated/SwiftSubclassCxx.cpp b/source/generated/SwiftSubclassCxx.cpp index 2c4fa3d6c2..32eaea14ba 100644 --- a/source/generated/SwiftSubclassCxx.cpp +++ b/source/generated/SwiftSubclassCxx.cpp @@ -21,6 +21,308 @@ // This file was generated by SwiftUsd-ast-answerer. Do not edit! #include "swiftUsd/generated/SwiftSubclassCxx.h" +// When constructing non-copyable wrapper types that get immediately passed to function pointers, +// we need to pass the wrapper as const* and not const& due to +// rdar://156635576 (Runtime crash calling C function pointer with const& argument from C++ when initialized with Swift closure). +// We can't use `fp(&SomeObject());` because taking the address of a temporary is illegal in C++, +// so we launder through this function. (Taking the address of a temporary is typically bad, +// but in the case of non-copyables, those are exposed as `borrowing` parameters in Swift, so +// Swift users can't escape the pointer/wrapper beyond the function pointer call, and C++ guarantees +// that temporary objects persist for the duration of the statement that constructs them, which is the +// function pointer call in `fp(__unsafeGetAddressOfTemporaryForFunctionPointer(SomeObject())`). + +template +const T* __unsafeGetAddressOfTemporaryForFunctionPointer(const T& x) { + return &x; +} + +// MARK: pxr::SdfFileFormat subclassing +__Overlay::SdfFileFormat::CxxAdapter::~CxxAdapter() { + if (__swiftSubclass) { + __releaseSwiftSubclass_FP(__swiftSubclass); + __swiftSubclass = nullptr; + __releaseSwiftSubclass_FP = nullptr; + } +} + +/* static */ void* __Overlay::SdfFileFormat::CxxAdapter::__toRaw(__Overlay::SdfFileFormat::CxxAdapter* x) { + return reinterpret_cast(x); +} +// Non-private constructors of pxr::SdfFileFormat will be exposed to Swift +__Overlay::SdfFileFormat::CxxAdapter::CxxAdapter(pxr::TfToken const & arg0, pxr::TfToken const & arg1, pxr::TfToken const & arg2, std::string const & arg3): +pxr::SdfFileFormat(arg0, arg1, arg2, arg3) +{} +/* static */ __Overlay::SdfFileFormat::CxxAdapter*_Nonnull __Overlay::SdfFileFormat::CxxAdapter::__swiftNew(pxr::TfToken const & arg0, pxr::TfToken const & arg1, pxr::TfToken const & arg2, std::string const & arg3) { + return new CxxAdapter(arg0, arg1, arg2, arg3); +} +__Overlay::SdfFileFormat::CxxAdapter::CxxAdapter(pxr::TfToken const & arg0, pxr::TfToken const & arg1, pxr::TfToken const & arg2, std::string const & arg3, pxr::SdfSchemaBase const & arg4): +pxr::SdfFileFormat(arg0, arg1, arg2, arg3, arg4) +{} +/* static */ __Overlay::SdfFileFormat::CxxAdapter*_Nonnull __Overlay::SdfFileFormat::CxxAdapter::__swiftNew(pxr::TfToken const & arg0, pxr::TfToken const & arg1, pxr::TfToken const & arg2, std::string const & arg3, pxr::SdfSchemaBase const & arg4) { + return new CxxAdapter(arg0, arg1, arg2, arg3, arg4); +} +__Overlay::SdfFileFormat::CxxAdapter::CxxAdapter(pxr::TfToken const & arg0, pxr::TfToken const & arg1, pxr::TfToken const & arg2, std::vector> const & arg3): +pxr::SdfFileFormat(arg0, arg1, arg2, arg3) +{} +/* static */ __Overlay::SdfFileFormat::CxxAdapter*_Nonnull __Overlay::SdfFileFormat::CxxAdapter::__swiftNew(pxr::TfToken const & arg0, pxr::TfToken const & arg1, pxr::TfToken const & arg2, std::vector> const & arg3) { + return new CxxAdapter(arg0, arg1, arg2, arg3); +} +__Overlay::SdfFileFormat::CxxAdapter::CxxAdapter(pxr::TfToken const & arg0, pxr::TfToken const & arg1, pxr::TfToken const & arg2, std::vector> const & arg3, pxr::SdfSchemaBase const & arg4): +pxr::SdfFileFormat(arg0, arg1, arg2, arg3, arg4) +{} +/* static */ __Overlay::SdfFileFormat::CxxAdapter*_Nonnull __Overlay::SdfFileFormat::CxxAdapter::__swiftNew(pxr::TfToken const & arg0, pxr::TfToken const & arg1, pxr::TfToken const & arg2, std::vector> const & arg3, pxr::SdfSchemaBase const & arg4) { + return new CxxAdapter(arg0, arg1, arg2, arg3, arg4); +} + +// Non-private destructor of CxxAdapter will be exposed to Swift +void __Overlay::SdfFileFormat::CxxAdapter::__swiftDeleteCxxAdapter() { + delete this; +} + +// Start total inheritance from pxr::SdfFileFormat +// Start fields from pxr::SdfFileFormat +// End fields from pxr::SdfFileFormat + +// Start methods from pxr::SdfFileFormat +pxr::SdfSchemaBase const & __Overlay::SdfFileFormat::CxxAdapter::__GetSchema_forward() const { + return GetSchema(); +} + +pxr::TfToken const & __Overlay::SdfFileFormat::CxxAdapter::__GetFormatId_forward() const { + return GetFormatId(); +} + +pxr::TfToken const & __Overlay::SdfFileFormat::CxxAdapter::__GetTarget_forward() const { + return GetTarget(); +} + +std::string const & __Overlay::SdfFileFormat::CxxAdapter::__GetFileCookie_forward() const { + return GetFileCookie(); +} + +pxr::TfToken const & __Overlay::SdfFileFormat::CxxAdapter::__GetVersionString_forward() const { + return GetVersionString(); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__IsPrimaryFormatForExtensions_forward() const { + return IsPrimaryFormatForExtensions(); +} + +std::vector> const & __Overlay::SdfFileFormat::CxxAdapter::__GetFileExtensions_forward() const { + return GetFileExtensions(); +} + +std::string const & __Overlay::SdfFileFormat::CxxAdapter::__GetPrimaryFileExtension_forward() const { + return GetPrimaryFileExtension(); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__IsSupportedExtension_forward(std::string const & arg0) const { + return IsSupportedExtension(arg0); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__IsPackage_default() const { + return pxr::SdfFileFormat::IsPackage(); +} +bool __Overlay::SdfFileFormat::CxxAdapter::IsPackage() const { + return __IsPackage_FP(__swiftSubclass); +} + +std::string __Overlay::SdfFileFormat::CxxAdapter::__GetPackageRootLayerPath_default(std::string const & arg0) const { + return pxr::SdfFileFormat::GetPackageRootLayerPath(arg0); +} +std::string __Overlay::SdfFileFormat::CxxAdapter::GetPackageRootLayerPath(std::string const & arg0) const { + return __GetPackageRootLayerPath_FP(__swiftSubclass, &arg0); +} + +std::map, std::allocator>> __Overlay::SdfFileFormat::CxxAdapter::__GetDefaultFileFormatArguments_default() const { + return pxr::SdfFileFormat::GetDefaultFileFormatArguments(); +} +std::map, std::allocator>> __Overlay::SdfFileFormat::CxxAdapter::GetDefaultFileFormatArguments() const { + return __GetDefaultFileFormatArguments_FP(__swiftSubclass); +} + +pxr::TfRefPtr __Overlay::SdfFileFormat::CxxAdapter::__InitData_default(std::map, std::allocator>> const & arg0) const { + return pxr::SdfFileFormat::InitData(arg0); +} +pxr::TfRefPtr __Overlay::SdfFileFormat::CxxAdapter::InitData(std::map, std::allocator>> const & arg0) const { + return __InitData_FP(__swiftSubclass, &arg0); +} + +pxr::TfRefPtr __Overlay::SdfFileFormat::CxxAdapter::__InitDetachedData_forward(std::map, std::allocator>> const & arg0) const { + return InitDetachedData(arg0); +} + +pxr::TfRefPtr __Overlay::SdfFileFormat::CxxAdapter::__NewLayer_forward(pxr::TfWeakPtr const & arg0, std::string const & arg1, std::string const & arg2, pxr::ArAssetInfo const & arg3, std::map, std::allocator>> const & arg4) const { + return NewLayer(arg0, arg1, arg2, arg3, arg4); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__ShouldSkipAnonymousReload_forward() const { + return ShouldSkipAnonymousReload(); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__ShouldReadAnonymousLayers_forward() const { + return ShouldReadAnonymousLayers(); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::CanRead(std::string const & arg0) const { + return __CanRead_FP(__swiftSubclass, &arg0); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::Read(pxr::SdfLayer * arg0, std::string const & arg1, bool arg2) const { + return __Read_FP(__swiftSubclass, arg0, &arg1, arg2); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__ReadDetached_forward(pxr::SdfLayer * arg0, std::string const & arg1, bool arg2) const { + return ReadDetached(arg0, arg1, arg2); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__WriteToFile_default(pxr::SdfLayer const & arg0, std::string const & arg1, std::string const & arg2, std::map, std::allocator>> const & arg3) const { + return pxr::SdfFileFormat::WriteToFile(arg0, arg1, arg2, arg3); +} +bool __Overlay::SdfFileFormat::CxxAdapter::WriteToFile(pxr::SdfLayer const & arg0, std::string const & arg1, std::string const & arg2, std::map, std::allocator>> const & arg3) const { + return __WriteToFile_FP(__swiftSubclass, &arg0, &arg1, &arg2, &arg3); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__SaveToFile_default(pxr::SdfLayer const & arg0, std::string const & arg1, std::string const & arg2, std::map, std::allocator>> const & arg3) const { + return pxr::SdfFileFormat::SaveToFile(arg0, arg1, arg2, arg3); +} +bool __Overlay::SdfFileFormat::CxxAdapter::SaveToFile(pxr::SdfLayer const & arg0, std::string const & arg1, std::string const & arg2, std::map, std::allocator>> const & arg3) const { + return __SaveToFile_FP(__swiftSubclass, &arg0, &arg1, &arg2, &arg3); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__ReadFromString_default(pxr::SdfLayer * arg0, std::string const & arg1) const { + return pxr::SdfFileFormat::ReadFromString(arg0, arg1); +} +bool __Overlay::SdfFileFormat::CxxAdapter::ReadFromString(pxr::SdfLayer * arg0, std::string const & arg1) const { + return __ReadFromString_FP(__swiftSubclass, arg0, &arg1); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__WriteToStream_default(pxr::SdfHandle const & arg0, Overlay::StdOstreamWrapper const & arg1, size_t arg2) const { + return pxr::SdfFileFormat::WriteToStream(arg0, *arg1.get(), arg2); +} +bool __Overlay::SdfFileFormat::CxxAdapter::WriteToStream(pxr::SdfHandle const & arg0, std::ostream & arg1, size_t arg2) const { + return __WriteToStream_FP(__swiftSubclass, &arg0, __unsafeGetAddressOfTemporaryForFunctionPointer(Overlay::StdOstreamWrapper(arg1)), arg2); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__WriteToString_default(pxr::SdfLayer const & arg0, std::string * arg1, std::string const & arg2) const { + return pxr::SdfFileFormat::WriteToString(arg0, arg1, arg2); +} +bool __Overlay::SdfFileFormat::CxxAdapter::WriteToString(pxr::SdfLayer const & arg0, std::string * arg1, std::string const & arg2) const { + return __WriteToString_FP(__swiftSubclass, &arg0, arg1, &arg2); +} + +std::set, std::allocator> __Overlay::SdfFileFormat::CxxAdapter::__GetExternalAssetDependencies_default(pxr::SdfLayer const & arg0) const { + return pxr::SdfFileFormat::GetExternalAssetDependencies(arg0); +} +std::set, std::allocator> __Overlay::SdfFileFormat::CxxAdapter::GetExternalAssetDependencies(pxr::SdfLayer const & arg0) const { + return __GetExternalAssetDependencies_FP(__swiftSubclass, &arg0); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__SupportsReading_forward() const { + return SupportsReading(); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__SupportsWriting_forward() const { + return SupportsWriting(); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::__SupportsEditing_forward() const { + return SupportsEditing(); +} + +/* static */ std::string __Overlay::SdfFileFormat::CxxAdapter::__GetFileExtension_forward(std::string const & arg0) { + return GetFileExtension(arg0); +} + +/* static */ std::set, std::allocator> __Overlay::SdfFileFormat::CxxAdapter::__FindAllFileFormatExtensions_forward() { + return FindAllFileFormatExtensions(); +} + +/* static */ std::set, std::allocator> __Overlay::SdfFileFormat::CxxAdapter::__FindAllDerivedFileFormatExtensions_forward(pxr::TfType const & arg0) { + return FindAllDerivedFileFormatExtensions(arg0); +} + +/* static */ bool __Overlay::SdfFileFormat::CxxAdapter::__FormatSupportsReading_forward(std::string const & arg0, std::string const & arg1) { + return FormatSupportsReading(arg0, arg1); +} + +/* static */ bool __Overlay::SdfFileFormat::CxxAdapter::__FormatSupportsWriting_forward(std::string const & arg0, std::string const & arg1) { + return FormatSupportsWriting(arg0, arg1); +} + +/* static */ bool __Overlay::SdfFileFormat::CxxAdapter::__FormatSupportsEditing_forward(std::string const & arg0, std::string const & arg1) { + return FormatSupportsEditing(arg0, arg1); +} + +/* static */ pxr::TfWeakPtr __Overlay::SdfFileFormat::CxxAdapter::__FindById_forward(pxr::TfToken const & arg0) { + return FindById(arg0); +} + +/* static */ pxr::TfWeakPtr __Overlay::SdfFileFormat::CxxAdapter::__FindByExtension_forward(std::string const & arg0, std::string const & arg1) { + return FindByExtension(arg0, arg1); +} + +/* static */ pxr::TfWeakPtr __Overlay::SdfFileFormat::CxxAdapter::__FindByExtension_forward(std::string const & arg0, std::map, std::allocator>> const & arg1) { + return FindByExtension(arg0, arg1); +} + +/* static */ void __Overlay::SdfFileFormat::CxxAdapter::___SetLayerData_forward(pxr::SdfLayer * arg0, pxr::TfRefPtr & arg1) { + return _SetLayerData(arg0, arg1); +} + +/* static */ void __Overlay::SdfFileFormat::CxxAdapter::___SetLayerData_forward(pxr::SdfLayer * arg0, pxr::TfRefPtr & arg1, pxr::SdfLayerHints arg2) { + return _SetLayerData(arg0, arg1, arg2); +} + +/* static */ pxr::TfWeakPtr __Overlay::SdfFileFormat::CxxAdapter::___GetLayerData_forward(pxr::SdfLayer const & arg0) { + return _GetLayerData(arg0); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::___ReadAndCopyLayerDataToMemory_forward(pxr::SdfLayer * arg0, std::string const & arg1, bool arg2, bool * arg3) const { + return _ReadAndCopyLayerDataToMemory(arg0, arg1, arg2, arg3); +} + +pxr::SdfLayer * __Overlay::SdfFileFormat::CxxAdapter::___InstantiateNewLayer_default(pxr::TfWeakPtr const & arg0, std::string const & arg1, std::string const & arg2, pxr::ArAssetInfo const & arg3, std::map, std::allocator>> const & arg4) const SWIFT_RETURNS_RETAINED { + return pxr::SdfFileFormat::_InstantiateNewLayer(arg0, arg1, arg2, arg3, arg4); +} +pxr::SdfLayer * __Overlay::SdfFileFormat::CxxAdapter::_InstantiateNewLayer(pxr::TfWeakPtr const & arg0, std::string const & arg1, std::string const & arg2, pxr::ArAssetInfo const & arg3, std::map, std::allocator>> const & arg4) const { + return ___InstantiateNewLayer_FP(__swiftSubclass, &arg0, &arg1, &arg2, &arg3, &arg4); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::___ShouldSkipAnonymousReload_default() const { + return pxr::SdfFileFormat::_ShouldSkipAnonymousReload(); +} +bool __Overlay::SdfFileFormat::CxxAdapter::_ShouldSkipAnonymousReload() const { + return ___ShouldSkipAnonymousReload_FP(__swiftSubclass); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::___ShouldReadAnonymousLayers_default() const { + return pxr::SdfFileFormat::_ShouldReadAnonymousLayers(); +} +bool __Overlay::SdfFileFormat::CxxAdapter::_ShouldReadAnonymousLayers() const { + return ___ShouldReadAnonymousLayers_FP(__swiftSubclass); +} + +pxr::TfRefPtr __Overlay::SdfFileFormat::CxxAdapter::___InitDetachedData_default(std::map, std::allocator>> const & arg0) const { + return pxr::SdfFileFormat::_InitDetachedData(arg0); +} +pxr::TfRefPtr __Overlay::SdfFileFormat::CxxAdapter::_InitDetachedData(std::map, std::allocator>> const & arg0) const { + return ___InitDetachedData_FP(__swiftSubclass, &arg0); +} + +bool __Overlay::SdfFileFormat::CxxAdapter::___ReadDetached_default(pxr::SdfLayer * arg0, std::string const & arg1, bool arg2) const { + return pxr::SdfFileFormat::_ReadDetached(arg0, arg1, arg2); +} +bool __Overlay::SdfFileFormat::CxxAdapter::_ReadDetached(pxr::SdfLayer * arg0, std::string const & arg1, bool arg2) const { + return ___ReadDetached_FP(__swiftSubclass, arg0, &arg1, arg2); +} + +// End methods from pxr::SdfFileFormat +// End total inheritance from pxr::SdfFileFormat + + + + #if SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT // MARK: pxr::HioImage subclassing __Overlay::HioImage::CxxAdapter::~CxxAdapter() { @@ -31,12 +333,15 @@ __Overlay::HioImage::CxxAdapter::~CxxAdapter() { } } +/* static */ void* __Overlay::HioImage::CxxAdapter::__toRaw(__Overlay::HioImage::CxxAdapter* x) { + return reinterpret_cast(x); +} // Non-private constructors of pxr::HioImage will be exposed to Swift -__Overlay::HioImage::CxxAdapter::CxxAdapter() : +__Overlay::HioImage::CxxAdapter::CxxAdapter(): pxr::HioImage() {} /* static */ __Overlay::HioImage::CxxAdapter*_Nonnull __Overlay::HioImage::CxxAdapter::__swiftNew() { - return new __Overlay::HioImage::CxxAdapter(); + return new CxxAdapter(); } // Non-private destructor of CxxAdapter will be exposed to Swift @@ -57,16 +362,10 @@ void __Overlay::HioImage::CxxAdapter::__swiftDeleteCxxAdapter() { return OpenForReading(arg0, arg1, arg2, arg3, arg4); } -bool __Overlay::HioImage::CxxAdapter::__Read_forward(pxr::HioImage::StorageSpec const & arg0) { - return Read(arg0); -} bool __Overlay::HioImage::CxxAdapter::Read(pxr::HioImage::StorageSpec const & arg0) { return __Read_FP(__swiftSubclass, &arg0); } -bool __Overlay::HioImage::CxxAdapter::__ReadCropped_forward(int const arg0, int const arg1, int const arg2, int const arg3, pxr::HioImage::StorageSpec const & arg4) { - return ReadCropped(arg0, arg1, arg2, arg3, arg4); -} bool __Overlay::HioImage::CxxAdapter::ReadCropped(int const arg0, int const arg1, int const arg2, int const arg3, pxr::HioImage::StorageSpec const & arg4) { return __ReadCropped_FP(__swiftSubclass, arg0, arg1, arg2, arg3, &arg4); } @@ -75,86 +374,50 @@ bool __Overlay::HioImage::CxxAdapter::ReadCropped(int const arg0, int const arg1 return OpenForWriting(arg0); } -bool __Overlay::HioImage::CxxAdapter::__Write_forward(pxr::HioImage::StorageSpec const & arg0, pxr::VtDictionary const & arg1) { - return Write(arg0, arg1); -} bool __Overlay::HioImage::CxxAdapter::Write(pxr::HioImage::StorageSpec const & arg0, pxr::VtDictionary const & arg1) { return __Write_FP(__swiftSubclass, &arg0, &arg1); } -std::string const & __Overlay::HioImage::CxxAdapter::__GetFilename_forward() const { - return GetFilename(); -} std::string const & __Overlay::HioImage::CxxAdapter::GetFilename() const { return *__GetFilename_FP(__swiftSubclass); } -int __Overlay::HioImage::CxxAdapter::__GetWidth_forward() const { - return GetWidth(); -} int __Overlay::HioImage::CxxAdapter::GetWidth() const { return __GetWidth_FP(__swiftSubclass); } -int __Overlay::HioImage::CxxAdapter::__GetHeight_forward() const { - return GetHeight(); -} int __Overlay::HioImage::CxxAdapter::GetHeight() const { return __GetHeight_FP(__swiftSubclass); } -pxr::HioFormat __Overlay::HioImage::CxxAdapter::__GetFormat_forward() const { - return GetFormat(); -} pxr::HioFormat __Overlay::HioImage::CxxAdapter::GetFormat() const { return __GetFormat_FP(__swiftSubclass); } -int __Overlay::HioImage::CxxAdapter::__GetBytesPerPixel_forward() const { - return GetBytesPerPixel(); -} int __Overlay::HioImage::CxxAdapter::GetBytesPerPixel() const { return __GetBytesPerPixel_FP(__swiftSubclass); } -int __Overlay::HioImage::CxxAdapter::__GetNumMipLevels_forward() const { - return GetNumMipLevels(); -} int __Overlay::HioImage::CxxAdapter::GetNumMipLevels() const { return __GetNumMipLevels_FP(__swiftSubclass); } -bool __Overlay::HioImage::CxxAdapter::__IsColorSpaceSRGB_forward() const { - return IsColorSpaceSRGB(); -} bool __Overlay::HioImage::CxxAdapter::IsColorSpaceSRGB() const { return __IsColorSpaceSRGB_FP(__swiftSubclass); } -bool __Overlay::HioImage::CxxAdapter::__GetMetadata_forward(pxr::TfToken const & arg0, pxr::VtValue * arg1) const { - return GetMetadata(arg0, arg1); -} bool __Overlay::HioImage::CxxAdapter::GetMetadata(pxr::TfToken const & arg0, pxr::VtValue * arg1) const { return __GetMetadata_FP(__swiftSubclass, &arg0, arg1); } -bool __Overlay::HioImage::CxxAdapter::__GetSamplerMetadata_forward(pxr::HioAddressDimension arg0, pxr::HioAddressMode * arg1) const { - return GetSamplerMetadata(arg0, arg1); -} bool __Overlay::HioImage::CxxAdapter::GetSamplerMetadata(pxr::HioAddressDimension arg0, pxr::HioAddressMode * arg1) const { return __GetSamplerMetadata_FP(__swiftSubclass, arg0, arg1); } -bool __Overlay::HioImage::CxxAdapter::___OpenForReading_forward(std::string const & arg0, int arg1, int arg2, pxr::HioImage::SourceColorSpace arg3, bool arg4) { - return _OpenForReading(arg0, arg1, arg2, arg3, arg4); -} bool __Overlay::HioImage::CxxAdapter::_OpenForReading(std::string const & arg0, int arg1, int arg2, pxr::HioImage::SourceColorSpace arg3, bool arg4) { return ___OpenForReading_FP(__swiftSubclass, &arg0, arg1, arg2, arg3, arg4); } -bool __Overlay::HioImage::CxxAdapter::___OpenForWriting_forward(std::string const & arg0) { - return _OpenForWriting(arg0); -} bool __Overlay::HioImage::CxxAdapter::_OpenForWriting(std::string const & arg0) { return ___OpenForWriting_FP(__swiftSubclass, &arg0); } diff --git a/source/generated/SwiftSubclassCxx.h b/source/generated/SwiftSubclassCxx.h index 5bcc143c16..3e75e47026 100644 --- a/source/generated/SwiftSubclassCxx.h +++ b/source/generated/SwiftSubclassCxx.h @@ -27,6 +27,195 @@ #if SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT #include "pxr/imaging/hio/image.h" #endif // #if SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT +#include "pxr/usd/sdf/fileFormat.h" + +#include +#include "pxr/usd/sdf/spec.h" +#include "pxr/usd/sdf/layerHints.h" +#include "swiftUsd/Wrappers/StdOstreamWrapper.h" + +// MARK: pxr::SdfFileFormat subclassing +namespace __Overlay { + namespace SdfFileFormat { + class CxxAdapter final: public pxr::SdfFileFormat { + public: + // Swift pointer + typedef void*_Nullable SwiftSubclass; + + SwiftSubclass __swiftSubclass = nullptr; + void (*_Nullable __releaseSwiftSubclass_FP)(SwiftSubclass) = nullptr; + virtual ~CxxAdapter(); + + static void*_Nullable __toRaw(CxxAdapter*_Nullable); + + // Conditional downcasting + static inline CxxAdapter*_Nullable __dynamic_cast(pxr::SdfFileFormat*_Nullable p) { + return dynamic_cast(p); + } + + // Unconditional upcasting + static inline pxr::SdfFileFormat*_Nonnull __static_cast(CxxAdapter*_Nonnull p, pxr::SdfFileFormat*_Nullable unused) { + return static_cast(p); + } + + // Non-public destructor of pxr::SdfFileFormat will not be exposed to Swift + + // Non-private constructors of pxr::SdfFileFormat will be exposed to Swift + CxxAdapter(pxr::TfToken const & formatId, pxr::TfToken const & versionString, pxr::TfToken const & target, std::string const & extension); + static __Overlay::SdfFileFormat::CxxAdapter*_Nonnull __swiftNew(pxr::TfToken const & formatId, pxr::TfToken const & versionString, pxr::TfToken const & target, std::string const & extension); + + CxxAdapter(pxr::TfToken const & formatId, pxr::TfToken const & versionString, pxr::TfToken const & target, std::string const & extension, pxr::SdfSchemaBase const & schema); + static __Overlay::SdfFileFormat::CxxAdapter*_Nonnull __swiftNew(pxr::TfToken const & formatId, pxr::TfToken const & versionString, pxr::TfToken const & target, std::string const & extension, pxr::SdfSchemaBase const & schema); + + CxxAdapter(pxr::TfToken const & formatId, pxr::TfToken const & versionString, pxr::TfToken const & target, std::vector> const & extensions); + static __Overlay::SdfFileFormat::CxxAdapter*_Nonnull __swiftNew(pxr::TfToken const & formatId, pxr::TfToken const & versionString, pxr::TfToken const & target, std::vector> const & extensions); + + CxxAdapter(pxr::TfToken const & formatId, pxr::TfToken const & versionString, pxr::TfToken const & target, std::vector> const & extensions, pxr::SdfSchemaBase const & schema); + static __Overlay::SdfFileFormat::CxxAdapter*_Nonnull __swiftNew(pxr::TfToken const & formatId, pxr::TfToken const & versionString, pxr::TfToken const & target, std::vector> const & extensions, pxr::SdfSchemaBase const & schema); + + // Non-private destructor of CxxAdapter will be exposed to Swift + void __swiftDeleteCxxAdapter(); + + // Start total inheritance from pxr::SdfFileFormat + // Start fields from pxr::SdfFileFormat + // End fields from pxr::SdfFileFormat + + // Start methods from pxr::SdfFileFormat + pxr::SdfSchemaBase const & __GetSchema_forward() const SWIFT_NAME(__GetSchema_forward()); + + pxr::TfToken const & __GetFormatId_forward() const SWIFT_NAME(__GetFormatId_forward()); + + pxr::TfToken const & __GetTarget_forward() const SWIFT_NAME(__GetTarget_forward()); + + std::string const & __GetFileCookie_forward() const SWIFT_NAME(__GetFileCookie_forward()); + + pxr::TfToken const & __GetVersionString_forward() const SWIFT_NAME(__GetVersionString_forward()); + + bool __IsPrimaryFormatForExtensions_forward() const SWIFT_NAME(__IsPrimaryFormatForExtensions_forward()); + + std::vector> const & __GetFileExtensions_forward() const SWIFT_NAME(__GetFileExtensions_forward()); + + std::string const & __GetPrimaryFileExtension_forward() const SWIFT_NAME(__GetPrimaryFileExtension_forward()); + + bool __IsSupportedExtension_forward(std::string const & extension) const SWIFT_NAME(__IsSupportedExtension_forward(_:)); + + bool (*_Nullable __IsPackage_FP)(SwiftSubclass); + bool __IsPackage_default() const SWIFT_NAME(__IsPackage_default()); + bool IsPackage() const override final SWIFT_NAME(IsPackage()); + + std::string (*_Nullable __GetPackageRootLayerPath_FP)(SwiftSubclass, std::string const *); + std::string __GetPackageRootLayerPath_default(std::string const & resolvedPath) const SWIFT_NAME(__GetPackageRootLayerPath_default(_:)); + std::string GetPackageRootLayerPath(std::string const & resolvedPath) const override final SWIFT_NAME(GetPackageRootLayerPath(_:)); + + std::map, std::allocator>> (*_Nullable __GetDefaultFileFormatArguments_FP)(SwiftSubclass); + std::map, std::allocator>> __GetDefaultFileFormatArguments_default() const SWIFT_NAME(__GetDefaultFileFormatArguments_default()); + std::map, std::allocator>> GetDefaultFileFormatArguments() const override final SWIFT_NAME(GetDefaultFileFormatArguments()); + + pxr::TfRefPtr (*_Nullable __InitData_FP)(SwiftSubclass, std::map, std::allocator>> const *); + pxr::TfRefPtr __InitData_default(std::map, std::allocator>> const & args) const SWIFT_NAME(__InitData_default(_:)); + pxr::TfRefPtr InitData(std::map, std::allocator>> const & args) const override final SWIFT_NAME(InitData(_:)); + + pxr::TfRefPtr __InitDetachedData_forward(std::map, std::allocator>> const & args) const SWIFT_NAME(__InitDetachedData_forward(_:)); + + pxr::TfRefPtr __NewLayer_forward(pxr::TfWeakPtr const & fileFormat, std::string const & identifier, std::string const & realPath, pxr::ArAssetInfo const & assetInfo, std::map, std::allocator>> const & args) const SWIFT_NAME(__NewLayer_forward(_:_:_:_:_:)); + + bool __ShouldSkipAnonymousReload_forward() const SWIFT_NAME(__ShouldSkipAnonymousReload_forward()); + + bool __ShouldReadAnonymousLayers_forward() const SWIFT_NAME(__ShouldReadAnonymousLayers_forward()); + + bool (*_Nullable __CanRead_FP)(SwiftSubclass, std::string const *); + bool CanRead(std::string const & file) const final SWIFT_NAME(CanRead(_:)); + + bool (*_Nullable __Read_FP)(SwiftSubclass, pxr::SdfLayer *, std::string const *, bool); + bool Read(pxr::SdfLayer * layer, std::string const & resolvedPath, bool metadataOnly) const final SWIFT_NAME(Read(_:_:_:)); + + bool __ReadDetached_forward(pxr::SdfLayer * layer, std::string const & resolvedPath, bool metadataOnly) const SWIFT_NAME(__ReadDetached_forward(_:_:_:)); + + bool (*_Nullable __WriteToFile_FP)(SwiftSubclass, pxr::SdfLayer const *, std::string const *, std::string const *, std::map, std::allocator>> const *); + bool __WriteToFile_default(pxr::SdfLayer const & layer, std::string const & filePath, std::string const & comment, std::map, std::allocator>> const & args) const SWIFT_NAME(__WriteToFile_default(_:_:_:_:)); + bool WriteToFile(pxr::SdfLayer const & layer, std::string const & filePath, std::string const & comment, std::map, std::allocator>> const & args) const override final SWIFT_NAME(WriteToFile(_:_:_:_:)); + + bool (*_Nullable __SaveToFile_FP)(SwiftSubclass, pxr::SdfLayer const *, std::string const *, std::string const *, std::map, std::allocator>> const *); + bool __SaveToFile_default(pxr::SdfLayer const & layer, std::string const & filePath, std::string const & comment, std::map, std::allocator>> const & args) const SWIFT_NAME(__SaveToFile_default(_:_:_:_:)); + bool SaveToFile(pxr::SdfLayer const & layer, std::string const & filePath, std::string const & comment, std::map, std::allocator>> const & args) const override final SWIFT_NAME(SaveToFile(_:_:_:_:)); + + bool (*_Nullable __ReadFromString_FP)(SwiftSubclass, pxr::SdfLayer *, std::string const *); + bool __ReadFromString_default(pxr::SdfLayer * layer, std::string const & str) const SWIFT_NAME(__ReadFromString_default(_:_:)); + bool ReadFromString(pxr::SdfLayer * layer, std::string const & str) const override final SWIFT_NAME(ReadFromString(_:_:)); + + bool (*_Nullable __WriteToStream_FP)(SwiftSubclass, pxr::SdfHandle const *, Overlay::StdOstreamWrapper const *, size_t); + bool __WriteToStream_default(pxr::SdfHandle const & spec, Overlay::StdOstreamWrapper const & out, size_t indent) const SWIFT_NAME(__WriteToStream_default(_:_:_:)); + bool WriteToStream(pxr::SdfHandle const & spec, std::ostream & out, size_t indent) const override final SWIFT_NAME(WriteToStream(_:_:_:)); + + bool (*_Nullable __WriteToString_FP)(SwiftSubclass, pxr::SdfLayer const *, std::string *, std::string const *); + bool __WriteToString_default(pxr::SdfLayer const & layer, std::string * str, std::string const & comment) const SWIFT_NAME(__WriteToString_default(_:_:_:)); + bool WriteToString(pxr::SdfLayer const & layer, std::string * str, std::string const & comment) const override final SWIFT_NAME(WriteToString(_:_:_:)); + + std::set, std::allocator> (*_Nullable __GetExternalAssetDependencies_FP)(SwiftSubclass, pxr::SdfLayer const *); + std::set, std::allocator> __GetExternalAssetDependencies_default(pxr::SdfLayer const & layer) const SWIFT_NAME(__GetExternalAssetDependencies_default(_:)); + std::set, std::allocator> GetExternalAssetDependencies(pxr::SdfLayer const & layer) const override final SWIFT_NAME(GetExternalAssetDependencies(_:)); + + bool __SupportsReading_forward() const SWIFT_NAME(__SupportsReading_forward()); + + bool __SupportsWriting_forward() const SWIFT_NAME(__SupportsWriting_forward()); + + bool __SupportsEditing_forward() const SWIFT_NAME(__SupportsEditing_forward()); + + static std::string __GetFileExtension_forward(std::string const & s) SWIFT_NAME(__GetFileExtension_forward(_:)); + + static std::set, std::allocator> __FindAllFileFormatExtensions_forward() SWIFT_NAME(__FindAllFileFormatExtensions_forward()); + + static std::set, std::allocator> __FindAllDerivedFileFormatExtensions_forward(pxr::TfType const & baseType) SWIFT_NAME(__FindAllDerivedFileFormatExtensions_forward(_:)); + + static bool __FormatSupportsReading_forward(std::string const & extension, std::string const & target) SWIFT_NAME(__FormatSupportsReading_forward(_:_:)); + + static bool __FormatSupportsWriting_forward(std::string const & extension, std::string const & target) SWIFT_NAME(__FormatSupportsWriting_forward(_:_:)); + + static bool __FormatSupportsEditing_forward(std::string const & extension, std::string const & target) SWIFT_NAME(__FormatSupportsEditing_forward(_:_:)); + + static pxr::TfWeakPtr __FindById_forward(pxr::TfToken const & formatId) SWIFT_NAME(__FindById_forward(_:)); + + static pxr::TfWeakPtr __FindByExtension_forward(std::string const & extension, std::string const & target) SWIFT_NAME(__FindByExtension_forward(_:_:)); + + static pxr::TfWeakPtr __FindByExtension_forward(std::string const & path, std::map, std::allocator>> const & args) SWIFT_NAME(__FindByExtension_forward(_:_:)); + + static void ___SetLayerData_forward(pxr::SdfLayer * layer, pxr::TfRefPtr & data) SWIFT_NAME(___SetLayerData_forward(_:_:)); + + static void ___SetLayerData_forward(pxr::SdfLayer * layer, pxr::TfRefPtr & data, pxr::SdfLayerHints hints) SWIFT_NAME(___SetLayerData_forward(_:_:_:)); + + static pxr::TfWeakPtr ___GetLayerData_forward(pxr::SdfLayer const & layer) SWIFT_NAME(___GetLayerData_forward(_:)); + + bool ___ReadAndCopyLayerDataToMemory_forward(pxr::SdfLayer * layer, std::string const & resolvedPath, bool metadataOnly, bool * didCopyData) const SWIFT_NAME(___ReadAndCopyLayerDataToMemory_forward(_:_:_:_:)); + + pxr::SdfLayer * (*_Nullable ___InstantiateNewLayer_FP)(SwiftSubclass, pxr::TfWeakPtr const *, std::string const *, std::string const *, pxr::ArAssetInfo const *, std::map, std::allocator>> const *); + pxr::SdfLayer * ___InstantiateNewLayer_default(pxr::TfWeakPtr const & fileFormat, std::string const & identifier, std::string const & realPath, pxr::ArAssetInfo const & assetInfo, std::map, std::allocator>> const & args) const SWIFT_NAME(___InstantiateNewLayer_default(_:_:_:_:_:)) SWIFT_RETURNS_RETAINED; + pxr::SdfLayer * _InstantiateNewLayer(pxr::TfWeakPtr const & fileFormat, std::string const & identifier, std::string const & realPath, pxr::ArAssetInfo const & assetInfo, std::map, std::allocator>> const & args) const override final SWIFT_NAME(_InstantiateNewLayer(_:_:_:_:_:)); + + bool (*_Nullable ___ShouldSkipAnonymousReload_FP)(SwiftSubclass); + bool ___ShouldSkipAnonymousReload_default() const SWIFT_NAME(___ShouldSkipAnonymousReload_default()); + bool _ShouldSkipAnonymousReload() const override final SWIFT_NAME(_ShouldSkipAnonymousReload()); + + bool (*_Nullable ___ShouldReadAnonymousLayers_FP)(SwiftSubclass); + bool ___ShouldReadAnonymousLayers_default() const SWIFT_NAME(___ShouldReadAnonymousLayers_default()); + bool _ShouldReadAnonymousLayers() const override final SWIFT_NAME(_ShouldReadAnonymousLayers()); + + pxr::TfRefPtr (*_Nullable ___InitDetachedData_FP)(SwiftSubclass, std::map, std::allocator>> const *); + pxr::TfRefPtr ___InitDetachedData_default(std::map, std::allocator>> const & args) const SWIFT_NAME(___InitDetachedData_default(_:)); + pxr::TfRefPtr _InitDetachedData(std::map, std::allocator>> const & args) const override final SWIFT_NAME(_InitDetachedData(_:)); + + bool (*_Nullable ___ReadDetached_FP)(SwiftSubclass, pxr::SdfLayer *, std::string const *, bool); + bool ___ReadDetached_default(pxr::SdfLayer * layer, std::string const & resolvedPath, bool metadataOnly) const SWIFT_NAME(___ReadDetached_default(_:_:_:)); + bool _ReadDetached(pxr::SdfLayer * layer, std::string const & resolvedPath, bool metadataOnly) const override final SWIFT_NAME(_ReadDetached(_:_:_:)); + + // End methods from pxr::SdfFileFormat + + // End total inheritance from pxr::SdfFileFormat + } SWIFT_UNSAFE_REFERENCE; + } +} + + + #if SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT // MARK: pxr::HioImage subclassing @@ -40,6 +229,8 @@ namespace __Overlay { SwiftSubclass __swiftSubclass = nullptr; void (*_Nullable __releaseSwiftSubclass_FP)(SwiftSubclass) = nullptr; virtual ~CxxAdapter(); + + static void*_Nullable __toRaw(CxxAdapter*_Nullable); // Conditional downcasting static inline CxxAdapter*_Nullable __dynamic_cast(pxr::HioImage*_Nullable p) { @@ -58,7 +249,7 @@ namespace __Overlay { // Non-private constructors of pxr::HioImage will be exposed to Swift CxxAdapter(); - static CxxAdapter*_Nonnull __swiftNew(); + static __Overlay::HioImage::CxxAdapter*_Nonnull __swiftNew(); // Non-private destructor of CxxAdapter will be exposed to Swift void __swiftDeleteCxxAdapter(); @@ -68,67 +259,53 @@ namespace __Overlay { // End fields from pxr::HioImage // Start methods from pxr::HioImage - static bool __IsSupportedImageFile_forward(std::string const & filename); + static bool __IsSupportedImageFile_forward(std::string const & filename) SWIFT_NAME(__IsSupportedImageFile_forward(_:)); - static std::shared_ptr __OpenForReading_forward(std::string const & filename, int subimage = 0, int mip = 0, pxr::HioImage::SourceColorSpace sourceColorSpace = pxr::HioImage::Auto, bool suppressErrors = false); + static std::shared_ptr __OpenForReading_forward(std::string const & filename, int subimage, int mip, pxr::HioImage::SourceColorSpace sourceColorSpace, bool suppressErrors) SWIFT_NAME(__OpenForReading_forward(_:_:_:_:_:)); - bool (*_Nullable __Read_FP)(SwiftSubclass, pxr::HioImage::StorageSpec const * storage) = nullptr; - bool __Read_forward(pxr::HioImage::StorageSpec const & storage); - bool Read(pxr::HioImage::StorageSpec const & storage) override final; + bool (*_Nullable __Read_FP)(SwiftSubclass, pxr::HioImage::StorageSpec const *); + bool Read(pxr::HioImage::StorageSpec const & storage) final SWIFT_NAME(Read(_:)); - bool (*_Nullable __ReadCropped_FP)(SwiftSubclass, int const cropTop, int const cropBottom, int const cropLeft, int const cropRight, pxr::HioImage::StorageSpec const * storage) = nullptr; - bool __ReadCropped_forward(int const cropTop, int const cropBottom, int const cropLeft, int const cropRight, pxr::HioImage::StorageSpec const & storage); - bool ReadCropped(int const cropTop, int const cropBottom, int const cropLeft, int const cropRight, pxr::HioImage::StorageSpec const & storage) override final; + bool (*_Nullable __ReadCropped_FP)(SwiftSubclass, int const, int const, int const, int const, pxr::HioImage::StorageSpec const *); + bool ReadCropped(int const cropTop, int const cropBottom, int const cropLeft, int const cropRight, pxr::HioImage::StorageSpec const & storage) final SWIFT_NAME(ReadCropped(_:_:_:_:_:)); - static std::shared_ptr __OpenForWriting_forward(std::string const & filename); + static std::shared_ptr __OpenForWriting_forward(std::string const & filename) SWIFT_NAME(__OpenForWriting_forward(_:)); - bool (*_Nullable __Write_FP)(SwiftSubclass, pxr::HioImage::StorageSpec const * storage, pxr::VtDictionary const * metadata) = nullptr; - bool __Write_forward(pxr::HioImage::StorageSpec const & storage, pxr::VtDictionary const & metadata = pxr::VtDictionary()); - bool Write(pxr::HioImage::StorageSpec const & storage, pxr::VtDictionary const & metadata = pxr::VtDictionary()) override final; + bool (*_Nullable __Write_FP)(SwiftSubclass, pxr::HioImage::StorageSpec const *, pxr::VtDictionary const *); + bool Write(pxr::HioImage::StorageSpec const & storage, pxr::VtDictionary const & metadata) final SWIFT_NAME(Write(_:_:)); - std::string * (*_Nullable __GetFilename_FP)(SwiftSubclass) = nullptr; - std::string const & __GetFilename_forward() const; - std::string const & GetFilename() const override final; + std::string const * (*_Nullable __GetFilename_FP)(SwiftSubclass); + std::string const & GetFilename() const final SWIFT_NAME(GetFilename()); - int (*_Nullable __GetWidth_FP)(SwiftSubclass) = nullptr; - int __GetWidth_forward() const; - int GetWidth() const override final; + int (*_Nullable __GetWidth_FP)(SwiftSubclass); + int GetWidth() const final SWIFT_NAME(GetWidth()); - int (*_Nullable __GetHeight_FP)(SwiftSubclass) = nullptr; - int __GetHeight_forward() const; - int GetHeight() const override final; + int (*_Nullable __GetHeight_FP)(SwiftSubclass); + int GetHeight() const final SWIFT_NAME(GetHeight()); - pxr::HioFormat (*_Nullable __GetFormat_FP)(SwiftSubclass) = nullptr; - pxr::HioFormat __GetFormat_forward() const; - pxr::HioFormat GetFormat() const override final; + pxr::HioFormat (*_Nullable __GetFormat_FP)(SwiftSubclass); + pxr::HioFormat GetFormat() const final SWIFT_NAME(GetFormat()); - int (*_Nullable __GetBytesPerPixel_FP)(SwiftSubclass) = nullptr; - int __GetBytesPerPixel_forward() const; - int GetBytesPerPixel() const override final; + int (*_Nullable __GetBytesPerPixel_FP)(SwiftSubclass); + int GetBytesPerPixel() const final SWIFT_NAME(GetBytesPerPixel()); - int (*_Nullable __GetNumMipLevels_FP)(SwiftSubclass) = nullptr; - int __GetNumMipLevels_forward() const; - int GetNumMipLevels() const override final; + int (*_Nullable __GetNumMipLevels_FP)(SwiftSubclass); + int GetNumMipLevels() const final SWIFT_NAME(GetNumMipLevels()); - bool (*_Nullable __IsColorSpaceSRGB_FP)(SwiftSubclass) = nullptr; - bool __IsColorSpaceSRGB_forward() const; - bool IsColorSpaceSRGB() const override final; + bool (*_Nullable __IsColorSpaceSRGB_FP)(SwiftSubclass); + bool IsColorSpaceSRGB() const final SWIFT_NAME(IsColorSpaceSRGB()); - bool (*_Nullable __GetMetadata_FP)(SwiftSubclass, pxr::TfToken const * key, pxr::VtValue * value) = nullptr; - bool __GetMetadata_forward(pxr::TfToken const & key, pxr::VtValue * value) const; - bool GetMetadata(pxr::TfToken const & key, pxr::VtValue * value) const override final; + bool (*_Nullable __GetMetadata_FP)(SwiftSubclass, pxr::TfToken const *, pxr::VtValue *); + bool GetMetadata(pxr::TfToken const & key, pxr::VtValue * value) const final SWIFT_NAME(GetMetadata(_:_:)); - bool (*_Nullable __GetSamplerMetadata_FP)(SwiftSubclass, pxr::HioAddressDimension dim, pxr::HioAddressMode * param) = nullptr; - bool __GetSamplerMetadata_forward(pxr::HioAddressDimension dim, pxr::HioAddressMode * param) const; - bool GetSamplerMetadata(pxr::HioAddressDimension dim, pxr::HioAddressMode * param) const override final; + bool (*_Nullable __GetSamplerMetadata_FP)(SwiftSubclass, pxr::HioAddressDimension, pxr::HioAddressMode *); + bool GetSamplerMetadata(pxr::HioAddressDimension dim, pxr::HioAddressMode * param) const final SWIFT_NAME(GetSamplerMetadata(_:_:)); - bool (*_Nullable ___OpenForReading_FP)(SwiftSubclass, std::string const * filename, int subimage, int mip, pxr::HioImage::SourceColorSpace sourceColorSpace, bool suppressErrors) = nullptr; - bool ___OpenForReading_forward(std::string const & filename, int subimage, int mip, pxr::HioImage::SourceColorSpace sourceColorSpace, bool suppressErrors); - bool _OpenForReading(std::string const & filename, int subimage, int mip, pxr::HioImage::SourceColorSpace sourceColorSpace, bool suppressErrors) override final; + bool (*_Nullable ___OpenForReading_FP)(SwiftSubclass, std::string const *, int, int, pxr::HioImage::SourceColorSpace, bool); + bool _OpenForReading(std::string const & filename, int subimage, int mip, pxr::HioImage::SourceColorSpace sourceColorSpace, bool suppressErrors) final SWIFT_NAME(_OpenForReading(_:_:_:_:_:)); - bool (*_Nullable ___OpenForWriting_FP)(SwiftSubclass, std::string const * filename) = nullptr; - bool ___OpenForWriting_forward(std::string const & filename); - bool _OpenForWriting(std::string const & filename) override final; + bool (*_Nullable ___OpenForWriting_FP)(SwiftSubclass, std::string const *); + bool _OpenForWriting(std::string const & filename) final SWIFT_NAME(_OpenForWriting(_:)); template bool GetMetadata(pxr::TfToken const & key, T * value) const { diff --git a/source/generated/SwiftSubclassCxx.md b/source/generated/SwiftSubclassCxx.md index e5865e0ac2..b68cbdae0c 100644 --- a/source/generated/SwiftSubclassCxx.md +++ b/source/generated/SwiftSubclassCxx.md @@ -8,5 +8,8 @@ This page lists which Usd types can be subclassed from Swift. Subclassing OpenUSD types in Swift should only be done for writing an OpenUSD plugin, due to an increased risk of memory-safety issues. See for more information. +### Sdf types +- ``OpenUSD/C++/pxr/SdfFileFormat`` + ### Hio types - ``OpenUSD/C++/pxr/HioImage`` diff --git a/source/generated/SwiftSubclassCxx.swift b/source/generated/SwiftSubclassCxx.swift index 845972c8ff..ccd155ece7 100644 --- a/source/generated/SwiftSubclassCxx.swift +++ b/source/generated/SwiftSubclassCxx.swift @@ -25,6 +25,389 @@ public enum __OverlaySwift{} +// MARK: pxr.SdfFileFormat subclassing +extension __Overlay.SdfFileFormat.CxxAdapter { + public var swift: Overlay.SdfFileFormatSubclass { + Unmanaged<__OverlaySwift.SdfFileFormat.SwiftAdapter>.fromOpaque(__swiftSubclass!).takeUnretainedValue() as! Overlay.SdfFileFormatSubclass + } +} + +// Conditional downcasting +extension pxr.SdfFileFormat { + public func `as`(_ t: T.Type = T.self) -> T? { + __Overlay.SdfFileFormat.CxxAdapter.__dynamic_cast(self)?.swift as? T + } +} + + +// Non-public destructor of pxr.SdfFileFormat will not be exposed to Swift + +public extension __OverlaySwift { + public enum SdfFileFormat { + open class SwiftAdapter { + private typealias UnmanagedSelf = Unmanaged<__OverlaySwift.SdfFileFormat.SwiftAdapter> + + // Detect if we're a zombie object to avoid setting __swiftDidDeinit.pointee in deinit after __releaseSwiftSubclass_FP deallocated it + private var __swiftIsZombie: Bool + + // Detect whether or not a call to Unmanaged.release() deinitialized us + // or if there's an outstanding strong pointer, making us a zombie + private var __swiftDidDeinit: UnsafeMutablePointer + + // Cxx pointer + private var __cxxSubclass: __Overlay.SdfFileFormat.CxxAdapter! + + public func __get_cxxUnsafe() -> __Overlay.SdfFileFormat.CxxAdapter? { __cxxSubclass } + public func __get_cxx_rawUnsafe() -> UnsafeMutableRawPointer? { __Overlay.SdfFileFormat.CxxAdapter.__toRaw(__cxxSubclass) } + + // Unconditional upcasting + public func `as`(_ t: pxr.SdfFileFormat.Type) -> pxr.SdfFileFormat { + __Overlay.SdfFileFormat.CxxAdapter.__static_cast(__cxxSubclass, nil) + } + + // Pointer/ref-returning method allocations + + private func __wireToCxx(_ __cxxSubclass: __Overlay.SdfFileFormat.CxxAdapter) { + func slf(_ raw: UnsafeMutableRawPointer?) -> Overlay.SdfFileFormatSubclass { + UnmanagedSelf.fromOpaque(raw!).takeUnretainedValue() as! Overlay.SdfFileFormatSubclass + } + + self.__cxxSubclass = __cxxSubclass + __cxxSubclass.__swiftSubclass = UnmanagedSelf.passRetained(self).toOpaque() + __cxxSubclass.__releaseSwiftSubclass_FP = { + let swiftDidDeinitPointer = slf($0).__swiftDidDeinit + let cxxSubclassPointer = slf($0).__cxxSubclass + slf($0).__cxxSubclass = nil + UnmanagedSelf.fromOpaque($0!).release() + let isZombie = !swiftDidDeinitPointer.pointee + swiftDidDeinitPointer.deallocate() + if isZombie { + slf($0).__swiftIsZombie = true + let cppInstance: UnsafeMutableRawPointer? = __Overlay.SdfFileFormat.CxxAdapter.__toRaw(cxxSubclassPointer) + __Overlay.SwiftSubclassCxx_zombieCreated(swiftInstance: $0, cppInstance: cppInstance, typeName: "pxr.SdfFileFormat") + } + } + // Start wire virtual methods from pxr.SdfFileFormat + __cxxSubclass.__IsPackage_FP = { slf($0).IsPackage() } + __cxxSubclass.__GetPackageRootLayerPath_FP = { slf($0).GetPackageRootLayerPath($1!.pointee) } + __cxxSubclass.__GetDefaultFileFormatArguments_FP = { slf($0).GetDefaultFileFormatArguments() } + __cxxSubclass.__InitData_FP = { slf($0).InitData($1!.pointee) } + __cxxSubclass.__CanRead_FP = { slf($0).CanRead($1!.pointee) } + __cxxSubclass.__Read_FP = { slf($0).Read($1, $2!.pointee, $3) } + __cxxSubclass.__WriteToFile_FP = { slf($0).WriteToFile($1!, $2!.pointee, $3!.pointee, $4!.pointee) } + __cxxSubclass.__SaveToFile_FP = { slf($0).SaveToFile($1!, $2!.pointee, $3!.pointee, $4!.pointee) } + __cxxSubclass.__ReadFromString_FP = { slf($0).ReadFromString($1, $2!.pointee) } + __cxxSubclass.__WriteToStream_FP = { slf($0).WriteToStream($1!.pointee, $2!.pointee, $3) } + __cxxSubclass.__WriteToString_FP = { slf($0).WriteToString($1!, $2, $3!.pointee) } + __cxxSubclass.__GetExternalAssetDependencies_FP = { slf($0).GetExternalAssetDependencies($1!) } + __cxxSubclass.___InstantiateNewLayer_FP = { slf($0)._InstantiateNewLayer($1!.pointee, $2!.pointee, $3!.pointee, $4!.pointee, $5!.pointee) } + __cxxSubclass.___ShouldSkipAnonymousReload_FP = { slf($0)._ShouldSkipAnonymousReload() } + __cxxSubclass.___ShouldReadAnonymousLayers_FP = { slf($0)._ShouldReadAnonymousLayers() } + __cxxSubclass.___InitDetachedData_FP = { slf($0)._InitDetachedData($1!.pointee) } + __cxxSubclass.___ReadDetached_FP = { slf($0)._ReadDetached($1, $2!.pointee, $3) } + // End wire virtual methods from pxr.SdfFileFormat + + } // public func __wireToCxx + + deinit { + // __releaseSwiftSubclass_FP, which is run by the C++ destructor, sets __cxxSubclass to nil. + // CxxAdapter has a strong pointer to SwiftAdapter, so SwiftAdapter.deinit running before ~CxxAdapter is a user-induced memory-safety issue + if self.__cxxSubclass != nil { + fatalError("Swift deinit running before C++ destructor ran violates invariants. Did you overrelease the Swift subclass instance?") + } + if !self.__swiftIsZombie { + // Set the flag but don't deallocate. The releaseFP will deallocate after checking if this flag was set + self.__swiftDidDeinit.pointee = true + } + } // deinit + + // Non-private constructors of pxr.SdfFileFormat will be exposed to Swift + + /// Creates a new instance of this subclass using `new pxr::SdfFileFormat(...);` in C++. + /// + /// The caller is responsible for deleting the instance in one of the following ways: + /// - Using `Overlay.SdfFileFormatSubclass.delete(_:)` in Swift + /// - Using `pxr.SdfFileFormat.delete(_:)` on the value returned by `self.get_cxx()` + /// - Using `delete p;` in C++ on the value returned by `self.get_cxx()` + /// - Passing the value returned by `self.get_cxx()` to something that will ensure it is eventually deleted, like `std::unique_ptr` or `std::shared_ptr` + /// Note that Swift ARC will _not_ automatically free the returned instance. Dropping the last strong reference in user code to the instance can result in memory leaks. + /// + /// This constructor was originally protected in C++. Use with caution. + public init(_ formatId: pxr.TfToken, _ versionString: pxr.TfToken, _ target: pxr.TfToken, _ `extension`: std.string) { + self.__swiftIsZombie = false + self.__swiftDidDeinit = UnsafeMutablePointer.allocate(capacity: 1) + self.__swiftDidDeinit.initialize(to: false) + + if type(of: self) == __OverlaySwift.SdfFileFormat.SwiftAdapter.self { + fatalError("Cannot construct instance of abstract base class Overlay.SdfFileFormatSubclass") + } + guard self is Overlay.SdfFileFormatSubclass else { + fatalError("Subclass \(type(of: self)) of pxr.SdfFileFormat must inherit from Overlay.SdfFileFormatSubclass") + } + let cxxAdapter = __Overlay.SdfFileFormat.CxxAdapter.__swiftNew(formatId, versionString, target, `extension`) + self.__wireToCxx(cxxAdapter) + } + + + /// Creates a new instance of this subclass using `new pxr::SdfFileFormat(...);` in C++. + /// + /// The caller is responsible for deleting the instance in one of the following ways: + /// - Using `Overlay.SdfFileFormatSubclass.delete(_:)` in Swift + /// - Using `pxr.SdfFileFormat.delete(_:)` on the value returned by `self.get_cxx()` + /// - Using `delete p;` in C++ on the value returned by `self.get_cxx()` + /// - Passing the value returned by `self.get_cxx()` to something that will ensure it is eventually deleted, like `std::unique_ptr` or `std::shared_ptr` + /// Note that Swift ARC will _not_ automatically free the returned instance. Dropping the last strong reference in user code to the instance can result in memory leaks. + /// + /// This constructor was originally protected in C++. Use with caution. + public init(_ formatId: pxr.TfToken, _ versionString: pxr.TfToken, _ target: pxr.TfToken, _ `extension`: std.string, _ schema: pxr.SdfSchemaBase) { + self.__swiftIsZombie = false + self.__swiftDidDeinit = UnsafeMutablePointer.allocate(capacity: 1) + self.__swiftDidDeinit.initialize(to: false) + + if type(of: self) == __OverlaySwift.SdfFileFormat.SwiftAdapter.self { + fatalError("Cannot construct instance of abstract base class Overlay.SdfFileFormatSubclass") + } + guard self is Overlay.SdfFileFormatSubclass else { + fatalError("Subclass \(type(of: self)) of pxr.SdfFileFormat must inherit from Overlay.SdfFileFormatSubclass") + } + let cxxAdapter = __Overlay.SdfFileFormat.CxxAdapter.__swiftNew(formatId, versionString, target, `extension`, schema) + self.__wireToCxx(cxxAdapter) + } + + + /// Creates a new instance of this subclass using `new pxr::SdfFileFormat(...);` in C++. + /// + /// The caller is responsible for deleting the instance in one of the following ways: + /// - Using `Overlay.SdfFileFormatSubclass.delete(_:)` in Swift + /// - Using `pxr.SdfFileFormat.delete(_:)` on the value returned by `self.get_cxx()` + /// - Using `delete p;` in C++ on the value returned by `self.get_cxx()` + /// - Passing the value returned by `self.get_cxx()` to something that will ensure it is eventually deleted, like `std::unique_ptr` or `std::shared_ptr` + /// Note that Swift ARC will _not_ automatically free the returned instance. Dropping the last strong reference in user code to the instance can result in memory leaks. + /// + /// This constructor was originally protected in C++. Use with caution. + public init(_ formatId: pxr.TfToken, _ versionString: pxr.TfToken, _ target: pxr.TfToken, _ extensions: Overlay.String_Vector) { + self.__swiftIsZombie = false + self.__swiftDidDeinit = UnsafeMutablePointer.allocate(capacity: 1) + self.__swiftDidDeinit.initialize(to: false) + + if type(of: self) == __OverlaySwift.SdfFileFormat.SwiftAdapter.self { + fatalError("Cannot construct instance of abstract base class Overlay.SdfFileFormatSubclass") + } + guard self is Overlay.SdfFileFormatSubclass else { + fatalError("Subclass \(type(of: self)) of pxr.SdfFileFormat must inherit from Overlay.SdfFileFormatSubclass") + } + let cxxAdapter = __Overlay.SdfFileFormat.CxxAdapter.__swiftNew(formatId, versionString, target, extensions) + self.__wireToCxx(cxxAdapter) + } + + + /// Creates a new instance of this subclass using `new pxr::SdfFileFormat(...);` in C++. + /// + /// The caller is responsible for deleting the instance in one of the following ways: + /// - Using `Overlay.SdfFileFormatSubclass.delete(_:)` in Swift + /// - Using `pxr.SdfFileFormat.delete(_:)` on the value returned by `self.get_cxx()` + /// - Using `delete p;` in C++ on the value returned by `self.get_cxx()` + /// - Passing the value returned by `self.get_cxx()` to something that will ensure it is eventually deleted, like `std::unique_ptr` or `std::shared_ptr` + /// Note that Swift ARC will _not_ automatically free the returned instance. Dropping the last strong reference in user code to the instance can result in memory leaks. + /// + /// This constructor was originally protected in C++. Use with caution. + public init(_ formatId: pxr.TfToken, _ versionString: pxr.TfToken, _ target: pxr.TfToken, _ extensions: Overlay.String_Vector, _ schema: pxr.SdfSchemaBase) { + self.__swiftIsZombie = false + self.__swiftDidDeinit = UnsafeMutablePointer.allocate(capacity: 1) + self.__swiftDidDeinit.initialize(to: false) + + if type(of: self) == __OverlaySwift.SdfFileFormat.SwiftAdapter.self { + fatalError("Cannot construct instance of abstract base class Overlay.SdfFileFormatSubclass") + } + guard self is Overlay.SdfFileFormatSubclass else { + fatalError("Subclass \(type(of: self)) of pxr.SdfFileFormat must inherit from Overlay.SdfFileFormatSubclass") + } + let cxxAdapter = __Overlay.SdfFileFormat.CxxAdapter.__swiftNew(formatId, versionString, target, extensions, schema) + self.__wireToCxx(cxxAdapter) + } + + // Non-private destructor of CxxAdapter will be exposed to Swift + + /// Deletes an instance of this subclass using `delete p;` in C++ on the pointer + /// returned by `self.get_cxx()`. + /// + /// The caller is responsible for ensuring that the pointer returned by + /// `self.get_cxx()` is not used after this function returns. + /// + /// Due to the way that SwiftUsd's mechanisms for subclassing C++ types from Swift are implemented, + /// this Swift instance may become a "zombie" if there is a strong reference keeping it + /// alive after this function returns. By default, SwiftUsd will print a warning to stdout + /// when this occurs. You can change this behavior by setting the environment variable + /// `SWIFTUSD_SWIFT_SUBCLASS_CXX_ZOMBIE_CREATION_BEHAVIOR` to `ignore` to suppress the warning, + /// or `terminate` to immediately exit the program. + /// After a zombie is created, any use of it might safely terminate the program. + public static func delete(_ swiftAdapter: consuming __OverlaySwift.SdfFileFormat.SwiftAdapter) { + let cxxAdapter = swiftAdapter.__cxxSubclass + _ = consume swiftAdapter + cxxAdapter?.__swiftDeleteCxxAdapter() + } + + // Start total inheritance from pxr.SdfFileFormat + // Start fields from pxr::SdfFileFormat + // End fields from pxr::SdfFileFormat + + // Start methods from pxr::SdfFileFormat + public func GetSchema() -> pxr.SdfSchemaBase { + return __cxxSubclass.__GetSchema_forward() + } + public func GetFormatId() -> pxr.TfToken { + return __cxxSubclass.__GetFormatId_forward().pointee + } + public func GetTarget() -> pxr.TfToken { + return __cxxSubclass.__GetTarget_forward().pointee + } + public func GetFileCookie() -> std.string { + return __cxxSubclass.__GetFileCookie_forward().pointee + } + public func GetVersionString() -> pxr.TfToken { + return __cxxSubclass.__GetVersionString_forward().pointee + } + public func IsPrimaryFormatForExtensions() -> CBool { + return __cxxSubclass.__IsPrimaryFormatForExtensions_forward() + } + public func GetFileExtensions() -> Overlay.String_Vector { + return __cxxSubclass.__GetFileExtensions_forward().pointee + } + public func GetPrimaryFileExtension() -> std.string { + return __cxxSubclass.__GetPrimaryFileExtension_forward().pointee + } + public func IsSupportedExtension(_ `extension`: std.string) -> CBool { + return __cxxSubclass.__IsSupportedExtension_forward(`extension`) + } + open func IsPackage() -> CBool { + return __cxxSubclass.__IsPackage_default() + } + open func GetPackageRootLayerPath(_ resolvedPath: std.string) -> std.string { + return __cxxSubclass.__GetPackageRootLayerPath_default(resolvedPath) + } + open func GetDefaultFileFormatArguments() -> pxr.SdfVariantSelectionMap { + return __cxxSubclass.__GetDefaultFileFormatArguments_default() + } + open func InitData(_ args: pxr.SdfVariantSelectionMap) -> pxr.SdfAbstractDataRefPtr { + return __cxxSubclass.__InitData_default(args) + } + public func InitDetachedData(_ args: pxr.SdfVariantSelectionMap) -> pxr.SdfAbstractDataRefPtr { + return __cxxSubclass.__InitDetachedData_forward(args) + } + public func NewLayer(_ fileFormat: pxr.SdfFileFormatConstPtr, _ identifier: std.string, _ realPath: std.string, _ assetInfo: pxr.ArAssetInfo, _ args: pxr.SdfVariantSelectionMap) -> pxr.SdfLayerRefPtr { + return __cxxSubclass.__NewLayer_forward(fileFormat, identifier, realPath, assetInfo, args) + } + public func ShouldSkipAnonymousReload() -> CBool { + return __cxxSubclass.__ShouldSkipAnonymousReload_forward() + } + public func ShouldReadAnonymousLayers() -> CBool { + return __cxxSubclass.__ShouldReadAnonymousLayers_forward() + } + public func ReadDetached(_ layer: pxr.SdfLayer?, _ resolvedPath: std.string, _ metadataOnly: CBool) -> CBool { + return __cxxSubclass.__ReadDetached_forward(layer, resolvedPath, metadataOnly) + } + open func WriteToFile(_ layer: pxr.SdfLayer, _ filePath: std.string, _ comment: std.string, _ args: pxr.SdfVariantSelectionMap) -> CBool { + return __cxxSubclass.__WriteToFile_default(layer, filePath, comment, args) + } + open func SaveToFile(_ layer: pxr.SdfLayer, _ filePath: std.string, _ comment: std.string, _ args: pxr.SdfVariantSelectionMap) -> CBool { + return __cxxSubclass.__SaveToFile_default(layer, filePath, comment, args) + } + open func ReadFromString(_ layer: pxr.SdfLayer?, _ str: std.string) -> CBool { + return __cxxSubclass.__ReadFromString_default(layer, str) + } + open func WriteToStream(_ spec: pxr.SdfSpecHandle, _ out: borrowing Overlay.StdOstreamWrapper, _ indent: Int) -> CBool { + return __cxxSubclass.__WriteToStream_default(spec, out, indent) + } + open func WriteToString(_ layer: pxr.SdfLayer, _ str: UnsafeMutablePointer?, _ comment: std.string) -> CBool { + return __cxxSubclass.__WriteToString_default(layer, str, comment) + } + open func GetExternalAssetDependencies(_ layer: pxr.SdfLayer) -> Overlay.String_Set { + return __cxxSubclass.__GetExternalAssetDependencies_default(layer) + } + public func SupportsReading() -> CBool { + return __cxxSubclass.__SupportsReading_forward() + } + public func SupportsWriting() -> CBool { + return __cxxSubclass.__SupportsWriting_forward() + } + public func SupportsEditing() -> CBool { + return __cxxSubclass.__SupportsEditing_forward() + } + public static func GetFileExtension(_ s: std.string) -> std.string { + return __Overlay.SdfFileFormat.CxxAdapter.__GetFileExtension_forward(s) + } + public static func FindAllFileFormatExtensions() -> Overlay.String_Set { + return __Overlay.SdfFileFormat.CxxAdapter.__FindAllFileFormatExtensions_forward() + } + public static func FindAllDerivedFileFormatExtensions(_ baseType: pxr.TfType) -> Overlay.String_Set { + return __Overlay.SdfFileFormat.CxxAdapter.__FindAllDerivedFileFormatExtensions_forward(baseType) + } + public static func FormatSupportsReading(_ `extension`: std.string, _ target: std.string) -> CBool { + return __Overlay.SdfFileFormat.CxxAdapter.__FormatSupportsReading_forward(`extension`, target) + } + public static func FormatSupportsWriting(_ `extension`: std.string, _ target: std.string) -> CBool { + return __Overlay.SdfFileFormat.CxxAdapter.__FormatSupportsWriting_forward(`extension`, target) + } + public static func FormatSupportsEditing(_ `extension`: std.string, _ target: std.string) -> CBool { + return __Overlay.SdfFileFormat.CxxAdapter.__FormatSupportsEditing_forward(`extension`, target) + } + public static func FindById(_ formatId: pxr.TfToken) -> pxr.SdfFileFormatConstPtr { + return __Overlay.SdfFileFormat.CxxAdapter.__FindById_forward(formatId) + } + public static func FindByExtension(_ `extension`: std.string, _ target: std.string) -> pxr.SdfFileFormatConstPtr { + return __Overlay.SdfFileFormat.CxxAdapter.__FindByExtension_forward(`extension`, target) + } + public static func FindByExtension(_ path: std.string, _ args: pxr.SdfVariantSelectionMap) -> pxr.SdfFileFormatConstPtr { + return __Overlay.SdfFileFormat.CxxAdapter.__FindByExtension_forward(path, args) + } + public static func _SetLayerData(_ layer: pxr.SdfLayer?, _ data: UnsafeMutablePointer) -> Void { + return __Overlay.SdfFileFormat.CxxAdapter.___SetLayerData_forward(layer, &data.pointee) + } + public static func _SetLayerData(_ layer: pxr.SdfLayer?, _ data: UnsafeMutablePointer, _ hints: pxr.SdfLayerHints) -> Void { + return __Overlay.SdfFileFormat.CxxAdapter.___SetLayerData_forward(layer, &data.pointee, hints) + } + public static func _GetLayerData(_ layer: pxr.SdfLayer) -> pxr.SdfAbstractDataConstPtr { + return __Overlay.SdfFileFormat.CxxAdapter.___GetLayerData_forward(layer) + } + public func _ReadAndCopyLayerDataToMemory(_ layer: pxr.SdfLayer?, _ resolvedPath: std.string, _ metadataOnly: CBool, _ didCopyData: UnsafeMutablePointer?) -> CBool { + return __cxxSubclass.___ReadAndCopyLayerDataToMemory_forward(layer, resolvedPath, metadataOnly, didCopyData) + } + open func _InstantiateNewLayer(_ fileFormat: pxr.SdfFileFormatConstPtr, _ identifier: std.string, _ realPath: std.string, _ assetInfo: pxr.ArAssetInfo, _ args: pxr.SdfVariantSelectionMap) -> pxr.SdfLayer? { + return __cxxSubclass.___InstantiateNewLayer_default(fileFormat, identifier, realPath, assetInfo, args) + } + open func _ShouldSkipAnonymousReload() -> CBool { + return __cxxSubclass.___ShouldSkipAnonymousReload_default() + } + open func _ShouldReadAnonymousLayers() -> CBool { + return __cxxSubclass.___ShouldReadAnonymousLayers_default() + } + open func _InitDetachedData(_ args: pxr.SdfVariantSelectionMap) -> pxr.SdfAbstractDataRefPtr { + return __cxxSubclass.___InitDetachedData_default(args) + } + open func _ReadDetached(_ layer: pxr.SdfLayer?, _ resolvedPath: std.string, _ metadataOnly: CBool) -> CBool { + return __cxxSubclass.___ReadDetached_default(layer, resolvedPath, metadataOnly) + } + // End methods from pxr::SdfFileFormat + // End total inheritance from pxr.SdfFileFormat + + public protocol PureVirtuals { + // Start methods from pxr.SdfFileFormat + init() // Synthesized, required for plugin entry points + func CanRead(_ file: std.string) -> CBool + func Read(_ layer: pxr.SdfLayer?, _ resolvedPath: std.string, _ metadataOnly: CBool) -> CBool + // End methods from pxr.SdfFileFormat + } // public protocol PureVirtuals + } + } +} + +extension Overlay { + public typealias SdfFileFormatSubclass = __OverlaySwift.SdfFileFormat.SwiftAdapter & __OverlaySwift.SdfFileFormat.SwiftAdapter.PureVirtuals +} + + + + #if canImport(SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT) // MARK: pxr.HioImage subclassing extension __Overlay.HioImage.CxxAdapter { @@ -58,9 +441,6 @@ public extension __OverlaySwift { open class SwiftAdapter { private typealias UnmanagedSelf = Unmanaged<__OverlaySwift.HioImage.SwiftAdapter> - // Detect calling __wireToCxx more than once, which is against core invariants - private var __swiftHasWired: Bool - // Detect if we're a zombie object to avoid setting __swiftDidDeinit.pointee in deinit after __releaseSwiftSubclass_FP deallocated it private var __swiftIsZombie: Bool @@ -68,17 +448,11 @@ public extension __OverlaySwift { // or if there's an outstanding strong pointer, making us a zombie private var __swiftDidDeinit: UnsafeMutablePointer - public required init() { - self.__swiftHasWired = false - self.__swiftIsZombie = false - self.__swiftDidDeinit = UnsafeMutablePointer.allocate(capacity: 1) - self.__swiftDidDeinit.initialize(to: false) - } - // Cxx pointer private var __cxxSubclass: __Overlay.HioImage.CxxAdapter! - public func get_cxx() -> __Overlay.HioImage.CxxAdapter? { __cxxSubclass } + public func __get_cxxUnsafe() -> __Overlay.HioImage.CxxAdapter? { __cxxSubclass } + public func __get_cxx_rawUnsafe() -> UnsafeMutableRawPointer? { __Overlay.HioImage.CxxAdapter.__toRaw(__cxxSubclass) } // Unconditional upcasting public func `as`(_ t: pxr.HioImage.Type) -> pxr.HioImage { @@ -92,11 +466,6 @@ public extension __OverlaySwift { func slf(_ raw: UnsafeMutableRawPointer?) -> Overlay.HioImageSubclass { UnmanagedSelf.fromOpaque(raw!).takeUnretainedValue() as! Overlay.HioImageSubclass } - if self.__swiftHasWired { - fatalError("Cannot call __wireToCxx more than once on a given instance. Don't call this from user code.") - } else { - self.__swiftHasWired = true - } self.__cxxSubclass = __cxxSubclass __cxxSubclass.__swiftSubclass = UnmanagedSelf.passRetained(self).toOpaque() @@ -109,14 +478,14 @@ public extension __OverlaySwift { swiftDidDeinitPointer.deallocate() if isZombie { slf($0).__swiftIsZombie = true - let cppInstance: UnsafeMutableRawPointer? = if let cxxSubclassPointer { Unmanaged<__Overlay.HioImage.CxxAdapter>.passUnretained(cxxSubclassPointer).toOpaque() } else { nil } + let cppInstance: UnsafeMutableRawPointer? = __Overlay.HioImage.CxxAdapter.__toRaw(cxxSubclassPointer) __Overlay.SwiftSubclassCxx_zombieCreated(swiftInstance: $0, cppInstance: cppInstance, typeName: "pxr.HioImage") } } // Start wire virtual methods from pxr.HioImage - __cxxSubclass.__Read_FP = { slf($0).Read($1.pointee) } - __cxxSubclass.__ReadCropped_FP = { slf($0).ReadCropped($1, $2, $3, $4, $5.pointee) } - __cxxSubclass.__Write_FP = { slf($0).Write($1.pointee, $2.pointee) } + __cxxSubclass.__Read_FP = { slf($0).Read($1!.pointee) } + __cxxSubclass.__ReadCropped_FP = { slf($0).ReadCropped($1, $2, $3, $4, $5!.pointee) } + __cxxSubclass.__Write_FP = { slf($0).Write($1!.pointee, $2!.pointee) } __cxxSubclass.__GetFilename_FP = { let newValue = slf($0).GetFilename() if slf($0).__returnIndirectionAllocation_GetFilename?.pointee != newValue { @@ -126,7 +495,7 @@ public extension __OverlaySwift { slf($0).__returnIndirectionAllocation_GetFilename = UnsafeMutablePointer.allocate(capacity: 1) slf($0).__returnIndirectionAllocation_GetFilename!.initialize(to: newValue) } - return slf($0).__returnIndirectionAllocation_GetFilename + return UnsafePointer(slf($0).__returnIndirectionAllocation_GetFilename!) } __cxxSubclass.__GetWidth_FP = { slf($0).GetWidth() } __cxxSubclass.__GetHeight_FP = { slf($0).GetHeight() } @@ -134,10 +503,10 @@ public extension __OverlaySwift { __cxxSubclass.__GetBytesPerPixel_FP = { slf($0).GetBytesPerPixel() } __cxxSubclass.__GetNumMipLevels_FP = { slf($0).GetNumMipLevels() } __cxxSubclass.__IsColorSpaceSRGB_FP = { slf($0).IsColorSpaceSRGB() } - __cxxSubclass.__GetMetadata_FP = { slf($0).GetMetadata($1.pointee, $2) } + __cxxSubclass.__GetMetadata_FP = { slf($0).GetMetadata($1!.pointee, $2) } __cxxSubclass.__GetSamplerMetadata_FP = { slf($0).GetSamplerMetadata($1, $2) } - __cxxSubclass.___OpenForReading_FP = { slf($0)._OpenForReading($1.pointee, $2, $3, $4, $5) } - __cxxSubclass.___OpenForWriting_FP = { slf($0)._OpenForWriting($1.pointee) } + __cxxSubclass.___OpenForReading_FP = { slf($0)._OpenForReading($1!.pointee, $2, $3, $4, $5) } + __cxxSubclass.___OpenForWriting_FP = { slf($0)._OpenForWriting($1!.pointee) } // End wire virtual methods from pxr.HioImage } // public func __wireToCxx @@ -165,17 +534,19 @@ public extension __OverlaySwift { /// - Using `delete p;` in C++ on the value returned by `self.get_cxx()` /// - Passing the value returned by `self.get_cxx()` to something that will ensure it is eventually deleted, like `std::unique_ptr` or `std::shared_ptr` /// Note that Swift ARC will _not_ automatically free the returned instance. Dropping the last strong reference in user code to the instance can result in memory leaks. - public static func new() -> Overlay.HioImageSubclass { - let swiftAdapter = Self.init() - if type(of: swiftAdapter) == __OverlaySwift.HioImage.SwiftAdapter.self { + public init() { + self.__swiftIsZombie = false + self.__swiftDidDeinit = UnsafeMutablePointer.allocate(capacity: 1) + self.__swiftDidDeinit.initialize(to: false) + + if type(of: self) == __OverlaySwift.HioImage.SwiftAdapter.self { fatalError("Cannot construct instance of abstract base class Overlay.HioImageSubclass") } - guard swiftAdapter is Overlay.HioImageSubclass else { - fatalError("Subclass \(type(of: swiftAdapter)) of pxr.HioImage must inherit from Overlay.HioImageSubclass") + guard self is Overlay.HioImageSubclass else { + fatalError("Subclass \(type(of: self)) of pxr.HioImage must inherit from Overlay.HioImageSubclass") } let cxxAdapter = __Overlay.HioImage.CxxAdapter.__swiftNew() - swiftAdapter.__wireToCxx(cxxAdapter) - return swiftAdapter as! Overlay.HioImageSubclass + self.__wireToCxx(cxxAdapter) } // Non-private destructor of CxxAdapter will be exposed to Swift @@ -205,19 +576,20 @@ public extension __OverlaySwift { // Start methods from pxr::HioImage public static func IsSupportedImageFile(_ filename: std.string) -> CBool { - __Overlay.HioImage.CxxAdapter.__IsSupportedImageFile_forward(filename) + return __Overlay.HioImage.CxxAdapter.__IsSupportedImageFile_forward(filename) } public static func OpenForReading(_ filename: std.string, _ subimage: CInt, _ mip: CInt, _ sourceColorSpace: pxr.HioImage.SourceColorSpace, _ suppressErrors: CBool) -> pxr.HioImageSharedPtr { - __Overlay.HioImage.CxxAdapter.__OpenForReading_forward(filename, subimage, mip, sourceColorSpace, suppressErrors) + return __Overlay.HioImage.CxxAdapter.__OpenForReading_forward(filename, subimage, mip, sourceColorSpace, suppressErrors) } public static func OpenForWriting(_ filename: std.string) -> pxr.HioImageSharedPtr { - __Overlay.HioImage.CxxAdapter.__OpenForWriting_forward(filename) + return __Overlay.HioImage.CxxAdapter.__OpenForWriting_forward(filename) } // End methods from pxr::HioImage // End total inheritance from pxr.HioImage public protocol PureVirtuals { // Start methods from pxr.HioImage + init() // Synthesized, required for plugin entry points func Read(_ storage: pxr.HioImage.StorageSpec) -> CBool func ReadCropped(_ cropTop: CInt, _ cropBottom: CInt, _ cropLeft: CInt, _ cropRight: CInt, _ storage: pxr.HioImage.StorageSpec) -> CBool func Write(_ storage: pxr.HioImage.StorageSpec, _ metadata: pxr.VtDictionary) -> CBool diff --git a/source/generated/_OpenUSD_SwiftBindingHelpers.apinotes b/source/generated/_OpenUSD_SwiftBindingHelpers.apinotes index fddb749e78..bcd39ee17a 100644 --- a/source/generated/_OpenUSD_SwiftBindingHelpers.apinotes +++ b/source/generated/_OpenUSD_SwiftBindingHelpers.apinotes @@ -252,6 +252,11 @@ Namespaces: - Name: GetName Availability: nonswift + - Name: SdfSchemaBase + SwiftImportAs: reference + SwiftRetainOp: immortal + SwiftReleaseOp: immortal + - Name: SdfSchema SwiftImportAs: reference SwiftRetainOp: immortal diff --git a/source/swiftUsd.h b/source/swiftUsd.h index a980107c24..75ca86ac1f 100644 --- a/source/swiftUsd.h +++ b/source/swiftUsd.h @@ -66,7 +66,8 @@ // The headers listed above are picked up as being for C++, // but we need to tell DocC which headers are meant for Swift. // (If a header is listed twice, that just means that it's -// meant for both Swift and C++.) +// meant for both Swift and C++. If it's listed once, that means +// it's either C++ only, or Swift only, depending on how its listed.) #ifdef OPENUSD_SWIFT_EMIT_SYMBOL_GRAPHS @@ -81,6 +82,7 @@ #includeforswiftdocc "swiftUsd/Wrappers/HgiWrapper.h" #includeforswiftdocc "swiftUsd/Wrappers/HioImageWrapper.h" #includeforswiftdocc "swiftUsd/Wrappers/SdfZipFileIteratorWrapper.h" +#includeforswiftdocc "swiftUsd/Wrappers/StdOstreamWrapper.h" #includeforswiftdocc "swiftUsd/Wrappers/TfErrorMarkWrapper.h" #includeforswiftdocc "swiftUsd/Wrappers/UsdAppUtilsFrameRecorderWrapper.h" #includeforswiftdocc "swiftUsd/Wrappers/UsdImagingGLEngineWrapper.h" @@ -89,6 +91,7 @@ #includeforswiftdocc "swiftUsd/SwiftOverlay/HydraHelpers.h" #includeforswiftdocc "swiftUsd/SwiftOverlay/Miscellaneous.h" #includeforswiftdocc "swiftUsd/SwiftOverlay/SdfLayer.h" +#includeforswiftdocc "swiftUsd/SwiftOverlay/TsKnot.h" #includeforswiftdocc "swiftUsd/SwiftOverlay/TfEnum.h" #includeforswiftdocc "swiftUsd/SwiftOverlay/Typedefs.h" #includeforswiftdocc "swiftUsd/SwiftOverlay/UsdAttribute.h"