Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5556c3194 | ||
|
|
8d0789ba0d | ||
|
|
c0670fd07c |
9 changed files with 95 additions and 22 deletions
|
|
@ -331,15 +331,19 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
provider,
|
||||
provider);
|
||||
host.Connect();
|
||||
var loweredSurface = new EveUiToolkitSurfaceLowerer().Lower(
|
||||
provider.CurrentDocument.SurfaceDocument,
|
||||
provider.Submit);
|
||||
var cockpit = loweredSurface.Q<VisualElement>("aetheria.daemon.game.cockpit");
|
||||
var mountedOverlay = root.GetComponent<EveUnityUiToolkitOverlay>();
|
||||
Assert.That(mountedOverlay, Is.Not.Null);
|
||||
var cockpit = mountedOverlay.Root.Q<VisualElement>("aetheria.daemon.game.cockpit");
|
||||
Assert.That(cockpit, Is.Not.Null, "The provider did not publish a generic cockpit overlay.");
|
||||
cockpitProgressCount = cockpit.Query<ProgressBar>().ToList().Count;
|
||||
Assert.That(cockpitProgressCount, Is.GreaterThanOrEqualTo(7));
|
||||
Assert.That(loweredSurface.Q<VisualElement>("aetheria.daemon.game.frame").style.display.value,
|
||||
Is.EqualTo(DisplayStyle.None), "Daemon diagnostics leaked into the pilot UI.");
|
||||
Assert.That(mountedOverlay.Root.Q<VisualElement>("aetheria.daemon.game.frame").style.display.value,
|
||||
Is.EqualTo(DisplayStyle.None), "Daemon diagnostics leaked into the mounted pilot UI.");
|
||||
Assert.That(mountedOverlay.Root.Q<VisualElement>("aetheria.daemon.game.main_menu").style.display.value,
|
||||
Is.EqualTo(DisplayStyle.None), "The closed main menu leaked into the mounted pilot UI.");
|
||||
Assert.That(provider.CurrentDocument.SurfaceDocument.Surface.Root.Children
|
||||
.Single(component => component.Id == "aetheria.daemon.game.frame").Layout["display"],
|
||||
Is.EqualTo("none"), "Daemon diagnostics leaked into the pilot UI.");
|
||||
trajectories = root.GetComponent<EveUnityShotTrajectoryRenderer>();
|
||||
Assert.That(trajectories, Is.Not.Null);
|
||||
host.ShotAvailable += shot =>
|
||||
|
|
@ -956,6 +960,9 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
Assert.That(captureFieldVolume.CompositeCount - initialCompositeCount,
|
||||
Is.GreaterThanOrEqualTo(temporalSettlingFrames),
|
||||
"The pilot capture ran before the advertised temporal reconstruction had settled.");
|
||||
Assert.That(cockpit.resolvedStyle.display, Is.Not.EqualTo(DisplayStyle.None));
|
||||
Assert.That(cockpit.worldBound.width, Is.GreaterThan(0),
|
||||
"The mounted provider cockpit has no visible screen layout.");
|
||||
Debug.Log($"EveUnity witness phase temporal-settling-128-frames took {temporalSettlingElapsed.Elapsed.TotalMilliseconds:0.###}ms.");
|
||||
var pilotCaptureElapsed = Stopwatch.StartNew();
|
||||
yield return null;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.43",
|
||||
"org.gamecult.eve.plugin-fields": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.3",
|
||||
"org.gamecult.eve.surface": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.4",
|
||||
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.102",
|
||||
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.103",
|
||||
"org.gamecult.eve.unity-uitoolkit": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-uitoolkit#eveunity-uitoolkit-v0.1.2"
|
||||
},
|
||||
"testables": [
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@
|
|||
"hash": "e08fa08335f99e9edddeb706912eecfad07cb281"
|
||||
},
|
||||
"org.gamecult.eve.unity-scene": {
|
||||
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.102",
|
||||
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.103",
|
||||
"depth": 0,
|
||||
"source": "git",
|
||||
"dependencies": {
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
"com.unity.render-pipelines.universal": "17.4.0",
|
||||
"com.unity.modules.particlesystem": "1.0.0"
|
||||
},
|
||||
"hash": "ddd2c5871f935978a0640d43cb58e18579523125"
|
||||
"hash": "050b2019bd6faa4275013516870d1ded245ee391"
|
||||
},
|
||||
"org.gamecult.eve.unity-uitoolkit": {
|
||||
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-uitoolkit#eveunity-uitoolkit-v0.1.2",
|
||||
|
|
|
|||
|
|
@ -331,15 +331,19 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
provider,
|
||||
provider);
|
||||
host.Connect();
|
||||
var loweredSurface = new EveUiToolkitSurfaceLowerer().Lower(
|
||||
provider.CurrentDocument.SurfaceDocument,
|
||||
provider.Submit);
|
||||
var cockpit = loweredSurface.Q<VisualElement>("aetheria.daemon.game.cockpit");
|
||||
var mountedOverlay = root.GetComponent<EveUnityUiToolkitOverlay>();
|
||||
Assert.That(mountedOverlay, Is.Not.Null);
|
||||
var cockpit = mountedOverlay.Root.Q<VisualElement>("aetheria.daemon.game.cockpit");
|
||||
Assert.That(cockpit, Is.Not.Null, "The provider did not publish a generic cockpit overlay.");
|
||||
cockpitProgressCount = cockpit.Query<ProgressBar>().ToList().Count;
|
||||
Assert.That(cockpitProgressCount, Is.GreaterThanOrEqualTo(7));
|
||||
Assert.That(loweredSurface.Q<VisualElement>("aetheria.daemon.game.frame").style.display.value,
|
||||
Is.EqualTo(DisplayStyle.None), "Daemon diagnostics leaked into the pilot UI.");
|
||||
Assert.That(mountedOverlay.Root.Q<VisualElement>("aetheria.daemon.game.frame").style.display.value,
|
||||
Is.EqualTo(DisplayStyle.None), "Daemon diagnostics leaked into the mounted pilot UI.");
|
||||
Assert.That(mountedOverlay.Root.Q<VisualElement>("aetheria.daemon.game.main_menu").style.display.value,
|
||||
Is.EqualTo(DisplayStyle.None), "The closed main menu leaked into the mounted pilot UI.");
|
||||
Assert.That(provider.CurrentDocument.SurfaceDocument.Surface.Root.Children
|
||||
.Single(component => component.Id == "aetheria.daemon.game.frame").Layout["display"],
|
||||
Is.EqualTo("none"), "Daemon diagnostics leaked into the pilot UI.");
|
||||
trajectories = root.GetComponent<EveUnityShotTrajectoryRenderer>();
|
||||
Assert.That(trajectories, Is.Not.Null);
|
||||
host.ShotAvailable += shot =>
|
||||
|
|
@ -956,6 +960,9 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
Assert.That(captureFieldVolume.CompositeCount - initialCompositeCount,
|
||||
Is.GreaterThanOrEqualTo(temporalSettlingFrames),
|
||||
"The pilot capture ran before the advertised temporal reconstruction had settled.");
|
||||
Assert.That(cockpit.resolvedStyle.display, Is.Not.EqualTo(DisplayStyle.None));
|
||||
Assert.That(cockpit.worldBound.width, Is.GreaterThan(0),
|
||||
"The mounted provider cockpit has no visible screen layout.");
|
||||
Debug.Log($"EveUnity witness phase temporal-settling-128-frames took {temporalSettlingElapsed.Elapsed.TotalMilliseconds:0.###}ms.");
|
||||
var pilotCaptureElapsed = Stopwatch.StartNew();
|
||||
yield return null;
|
||||
|
|
|
|||
|
|
@ -23,14 +23,17 @@ namespace GameCult.Eve.UnityScene
|
|||
{
|
||||
private readonly IEveUnityPlayableWorldSceneSink _sceneSink;
|
||||
private readonly IEveUnityPlayableWorldAssetResolver _assetResolver;
|
||||
private readonly bool _liveEntityBodyOwner;
|
||||
private readonly HashSet<string> _knownEntityIds = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
public EveUnityPlayableWorldPresenter(
|
||||
IEveUnityPlayableWorldSceneSink sceneSink,
|
||||
IEveUnityPlayableWorldAssetResolver assetResolver)
|
||||
IEveUnityPlayableWorldAssetResolver assetResolver,
|
||||
bool liveEntityBodyOwner = false)
|
||||
{
|
||||
_sceneSink = sceneSink ?? throw new ArgumentNullException(nameof(sceneSink));
|
||||
_assetResolver = assetResolver ?? throw new ArgumentNullException(nameof(assetResolver));
|
||||
_liveEntityBodyOwner = liveEntityBodyOwner;
|
||||
}
|
||||
|
||||
public EveUnityPlayableWorldPresentation Apply(EveUnitySceneProjection projection)
|
||||
|
|
@ -46,9 +49,26 @@ namespace GameCult.Eve.UnityScene
|
|||
{
|
||||
if (world == null) throw new ArgumentNullException(nameof(world));
|
||||
|
||||
var nextEntityIds = new HashSet<string>(StringComparer.Ordinal);
|
||||
_sceneSink.ConfigureWorld(world);
|
||||
|
||||
// A world that advertises a live entity body has one transform and
|
||||
// membership owner: the SoA generation presenter. The durable Eve
|
||||
// surface remains configuration/topology and must not periodically
|
||||
// overwrite realtime body state.
|
||||
if (_liveEntityBodyOwner &&
|
||||
(!string.IsNullOrWhiteSpace(world.EntityViewPointerId) ||
|
||||
!string.IsNullOrWhiteSpace(world.EntityBodyId)))
|
||||
return new EveUnityPlayableWorldPresentation(
|
||||
world.WorldRootId,
|
||||
world.PlayerEntityId,
|
||||
world.InputProfile,
|
||||
world.CameraRig,
|
||||
0,
|
||||
0,
|
||||
_knownEntityIds.Count);
|
||||
|
||||
var nextEntityIds = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
var upserted = 0;
|
||||
foreach (var entity in world.Entities)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,7 +41,10 @@ namespace GameCult.Eve.UnityScene
|
|||
_connection = new EveUnitySceneProviderConnection(_surfaceSource, commandSink);
|
||||
_client = new EveUnityPlayableWorldLiveClient(
|
||||
_connection,
|
||||
new EveUnityPlayableWorldPresenter(sceneSink, assetResolver ?? new EveUnityAssetRefResolver()),
|
||||
new EveUnityPlayableWorldPresenter(
|
||||
sceneSink,
|
||||
assetResolver ?? new EveUnityAssetRefResolver(),
|
||||
liveEntityBodyOwner: _entityViews != null),
|
||||
receiptSource);
|
||||
|
||||
if (assetManifestDocuments != null)
|
||||
|
|
|
|||
|
|
@ -1856,7 +1856,7 @@ namespace GameCult.Eve.UnityScene.Tests
|
|||
var presenter = new EveUnityPlayableWorldPresenter(sink, new EveUnityAssetRefResolver());
|
||||
|
||||
var firstProjection = lowerer.Lower(PlayableArpgDocument(), Advertisement("aetheria.daemon.game"));
|
||||
var firstPresentation = presenter.Apply(firstProjection);
|
||||
var firstPresentation = presenter.Apply(SnapshotWorld(firstProjection.PlayableWorld!));
|
||||
|
||||
Assert.That(firstPresentation.WorldRootId, Is.EqualTo("aetheria.daemon.game.playable"));
|
||||
Assert.That(firstPresentation.PlayerEntityId, Is.EqualTo("player-vanguard"));
|
||||
|
|
@ -1875,7 +1875,7 @@ namespace GameCult.Eve.UnityScene.Tests
|
|||
var secondProjection = lowerer.Lower(
|
||||
PlayableArpgDocument(includeRaider: false, playerPosition: "5,0,2"),
|
||||
Advertisement("aetheria.daemon.game"));
|
||||
var secondPresentation = presenter.Apply(secondProjection);
|
||||
var secondPresentation = presenter.Apply(SnapshotWorld(secondProjection.PlayableWorld!));
|
||||
|
||||
Assert.That(secondPresentation.UpsertedEntities, Is.EqualTo(2));
|
||||
Assert.That(secondPresentation.RemovedEntities, Is.EqualTo(1));
|
||||
|
|
@ -1888,6 +1888,27 @@ namespace GameCult.Eve.UnityScene.Tests
|
|||
Assert.That(sink.Upserts[3].entity.PositionZ, Is.EqualTo(2f));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PlayableWorldSurfaceCannotOverwriteLiveBodyEntities()
|
||||
{
|
||||
var projection = new EveUnitySceneSurfaceLowerer()
|
||||
.Lower(PlayableArpgDocument(), Advertisement("aetheria.daemon.game"));
|
||||
var sink = new FakePlayableWorldSceneSink();
|
||||
var presenter = new EveUnityPlayableWorldPresenter(
|
||||
sink,
|
||||
new EveUnityAssetRefResolver(),
|
||||
liveEntityBodyOwner: true);
|
||||
|
||||
var presentation = presenter.Apply(projection);
|
||||
|
||||
Assert.That(projection.PlayableWorld!.EntityBodyId, Is.Not.Empty);
|
||||
Assert.That(sink.ConfiguredWorlds.Count, Is.EqualTo(1));
|
||||
Assert.That(sink.Upserts, Is.Empty);
|
||||
Assert.That(sink.RemovedEntityIds, Is.Empty);
|
||||
Assert.That(presentation.UpsertedEntities, Is.Zero);
|
||||
Assert.That(presentation.RemovedEntities, Is.Zero);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LivePlayableWorldClientPresentsProviderSnapshotsAndKeepsCommandsProviderOwned()
|
||||
{
|
||||
|
|
@ -2950,6 +2971,21 @@ namespace GameCult.Eve.UnityScene.Tests
|
|||
}
|
||||
}
|
||||
|
||||
private static EveUnityPlayableWorldProjection SnapshotWorld(EveUnityPlayableWorldProjection source) =>
|
||||
new EveUnityPlayableWorldProjection(
|
||||
source.WorldRootId,
|
||||
source.StatePointerId,
|
||||
source.AssetManifest,
|
||||
source.InputProfile,
|
||||
source.CameraRig,
|
||||
source.ViewId,
|
||||
source.PlayerEntityId,
|
||||
source.MovementCommand,
|
||||
source.FocusCommand,
|
||||
source.TargetCommand,
|
||||
source.ActionCommand,
|
||||
source.Entities);
|
||||
|
||||
private static EveUnityPlayableWorldEntity PlayableEntityModel(
|
||||
string entityId,
|
||||
string assetRef,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "org.gamecult.eve.unity-scene",
|
||||
"displayName": "Eve Unity Scene Lowering",
|
||||
"version": "0.3.103",
|
||||
"version": "0.3.104",
|
||||
"unity": "6000.0",
|
||||
"description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.",
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ param(
|
|||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$expectedEveUnityCommit = "ddd2c5871f935978a0640d43cb58e18579523125"
|
||||
$expectedEveUnityCommit = "050b2019bd6faa4275013516870d1ded245ee391"
|
||||
$expectedEveFieldsCommit = "c5a4a75c1b727499b16c2dae1895f29e2a9f72f0"
|
||||
$expectedEveUnityUiToolkitCommit = "44390549775ec535ee31fc60a5bc594f372f4147"
|
||||
$expectedCultLibCommit = "f67f5122ed1bd11da016e7b820ed60145ccd0299"
|
||||
|
|
|
|||
Reference in a new issue