mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-21 17:16:16 +08:00
fix/encoder-stack-depth-json-flake
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c84c168585 |
Merge OpenUSD scene packages (#4384)
# Description Merge the draft OpenUSD Scene Materialization projects into the existing OpenUSD core and server packages: - move the scene companion model, document/value model, and `.usda` conversion APIs into `Opc.Ua.OpenUsd`; - move discovery, materialization, export, and Part 1 interop into `Opc.Ua.OpenUsd.Server`; - rename the CLR APIs to `Opc.Ua.OpenUsd.Scene`, `Opc.Ua.OpenUsd.Scene.Conversion`, and `Opc.Ua.OpenUsd.Server.Scene`; - remove the `Opc.Ua.OpenUsdScene` and `Opc.Ua.OpenUsdScene.Server` projects and NuGet package IDs; - update the connector, the consolidated OpenUSD test project, package READMEs, and developer docs. This is an intentional source- and binary-breaking cleanup for the draft Scene packages. The OPC UA Scene model URI, version, NodeIds, and wire behavior remain unchanged. ## Related Issues - Fixes #4383 ## Validation - `UA.slnx` Release builds completed for `CustomTestTarget=net10.0` and `CustomTestTarget=net48`. - OpenUSD tests passed on net10.0 (915) and net48 (879), excluding the existing host-culture assertion; the isolated assertion passed under invariant globalization. - The generated Release pack contains the expected 75 packages, emits neither retired Scene package, and passes `.azurepipelines\validate-source-generator-packages.ps1`. - The two surviving packages expose the new nested namespaces and contain no retired package dependencies. ## Checklist - [ ] I have signed the [CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf) and read the [CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md) doc. - [ ] I have added tests that prove my fix is effective or that my feature works and increased code coverage. - [x] I have added all necessary documentation. - [x] I have verified that my changes do not introduce (new) build or analyzer warnings. - [ ] I ran **all** tests locally using the **UA.slnx** solution against at least .net **framework** and .net **10**, and all passed. - [ ] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [ ] I have addressed **all** PR feedback received. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
0f257c05f0 |
OpenUSD scene: replace object in the USD value model with a UsdValue union (#4160)
Fixes #4151. ## The problem ```csharp public object? Value { get; set; } public SortedList<double, object?> TimeSamples { get; } public IDictionary<string, object?> Metadata { get; } ``` `object` in public API, and every consumer forced into type tests and casts. It was also why `UsdSceneExporter` had to call `Variant.AsBoxedObject(Variant.BoxingBehavior.Legacy)`, itself against guidance. `Variant` cannot stand in for it. The USD value model is recursive and **ragged**: tuples (`float3`), arrays, *arrays of tuples* (`color3f[]`), matrices authored as a tuple of row tuples, plus asset paths and prim path references that must round-trip as their own syntax. `Variant`/`MatrixOf<T>` cover rectangular scalar arrays but not the nested "array of tuple" shape. ## What this does Introduces `UsdValue`, a readonly struct scoping a value to the shapes a `.usda` document can express, and converts the model to it end to end - reader, writer, coercion and signature all speak `UsdValue`, so there is one representation rather than conversions at the edges. - `INullable`, so absence is `UsdValue.Null` / `.IsNull` - never `UsdValue?`. - `TryGet*` accessors only. No boxing accessor, nothing returning `object`. - `ArrayOf<UsdValue>` for the recursive tuple/array/matrix cases. - `Tuple` and `Array` stay distinct kinds because USD prints `(1, 2, 3)` and `[1, 2, 3]` differently, as do `Token` and `String`. - `Decoerce` now takes the `Variant` directly and reads it through its typed accessors, which is what **removes the `AsBoxedObject` call**. **The attribute's `TypeName` stays authoritative for rendering**, so the kinds add type safety without changing a single byte of emitted `.usda`. That is what makes this provably lossless: the existing fidelity and round-trip suites pass **with their expectations untouched**. ## Three defects the tests caught Worth calling out, because each would have shipped silently: 1. **Georeference dual authoring** read values through an `object`-typed `TryToDouble`, which stopped seeing CLR primitives once values became `UsdValue`. 2. **A `double3` scalar was emitted as `[1.0, 2.0, 3.0]`** instead of `(1.0, 2.0, 3.0)`, because the writer picked brackets from the value's kind. The shape is decided by the TypeName, not the container - so `UsdVal` now renders a composite as a parenthesised tuple unless the type is an array type. This is the same contract the H-1 regression guard documents. 3. **`UsdValue` did not load at all on .NET Framework.** Storing components as `ArrayOf<UsdValue>` made the struct layout recursive (`UsdValue` -> `ArrayOf<UsdValue>` -> `ReadOnlyMemory<UsdValue>`); CoreCLR resolves that, the net48 type loader throws `TypeLoadException` on every use. Only the net48 run surfaced it - net10.0 was entirely green. The payload is now a plain array, a reference type, which breaks the cycle while the public accessors still hand out `ArrayOf<UsdValue>`. ## Review feedback addressed - `UsdValue.GetHashCode` folds the dictionary entries (an order-independent sum of key/value hashes) instead of only the entry count, so same-size dictionaries no longer all collide. - `UsdValue.ToString` renders a `Dictionary` as its entries ordered by key instead of falling through to the empty-string default, which the metadata fallback paths rely on. - A `uint64` above `long.MaxValue` is no longer cast to `long` (which wrapped `ulong.MaxValue` into `-1`) - it is preserved as its invariant decimal text for scalars, arrays and matrices alike. `TryAsUInt64` reads that form back, and `UsdaReader` now parses an over-long integral literal as a token holding its exact digits instead of throwing `OverflowException`, so the value survives the whole round trip. ## Validation - Full `dotnet build UA.slnx -m:1 /p:UseSharedCompilation=false`: **0 errors, 0 warnings**. - `Opc.Ua.OpenUsd.Tests`: **772 passing on net10.0 and on net48** (632 existing + 140 new tests), with 99.0% patch coverage over the changed source lines. - `Opc.Ua.Di.Tests` 364, `Opc.Ua.Robotics.Tests` 103 - unchanged. - No `object`/`object?` left in the `Opc.Ua.OpenUsdScene` public API except the `Equals(object?)` override; no `AsBoxedObject`/`AsBoxedValue` anywhere in the OpenUSD assemblies. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8cbb8cd0-f0cb-4ab0-bea2-6202fbf69485 Copilot-Session: d089bd1c-b795-4f2b-a872-eb3090c11536 |
||
|
|
fb160a8f39 |
OpenUSD: the OPC UA to OpenUSD binding, scene materialization and connector (#4126)
**Stack 4/5** — base #4125. Part of the #4096 split; see #4096 for the overall picture. > Review after #4123, #4124 and #4125. ## What this is The generic OPC UA to OpenUSD binding, scene materialization, and the connector that drives a live stage from a running server. ## Contents **Binding (Part 1)** — `Opc.Ua.OpenUsd` and `Opc.Ua.OpenUsd.Server`. A server describes how its Variables drive USD prims, and serves the USD layers it refers to as Part 5 files with a content digest. **Scene materialization (Part 2)** — `Opc.Ua.OpenUsdScene` and `Opc.Ua.OpenUsdScene.Server`, including the USDA writer. - **Escaping fix**: string values, composition-arc references, variant set names and selections, `doc` and prim names were all emitted unescaped, so a value carrying a quote or a newline could author its own layer syntax. Every emit site now goes through the escapers. The tests assert the right property — not that the payload is absent (it legitimately survives inside the escaped literal) but that no payload becomes its own line of layer syntax. **Client** — `Opc.Ua.OpenUsd.Client` streams live values into an `IUsdSink`. `CompositeUsdSink` fans out to several sinks; the file sink interpolates between server samples so motion is continuous rather than stepped at the publishing interval. **Connector** — `tools/Opc.Ua.OpenUsd.Connector` composes a stage from a live server. The optional in-process viewport lives in a separate assembly probed at run time, so the connector still runs — and says why — when it is absent. - **Fix**: the asset cache and PKI root moved off the shared temp directory to `LocalApplicationData`. **Sample** — `PumpDeviceIntegrationServer` gains an OpenUSD representation of the pump. ## Notes for the reviewer - The viewport assembly is net10.0-only. It is what exercises the `Directory.Build.targets` change from 1/5: without it, the `net8.0` leg of the per-TFM CI build fails with `CS0433` because the `System.Threading.Lock` polyfill collides with the real type. - `UsdAssetDelivery` hashes through `SHA256.Create` rather than the static `HashData`, which does not exist on the net472/net48 targets this test project also builds for. ## Validation `dotnet build UA.slnx` — 0 errors, 0 warnings. | Suite | Result | | --- | --- | | Opc.Ua.OpenUsd.Tests | 621 / 0 | | Opc.Ua.Di.Tests | 321 / 0 | --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8cbb8cd0-f0cb-4ab0-bea2-6202fbf69485 |