Move fly/chase publication, combat target tracking, and local player projection behind typed runtime owners. Preserve the inbound-created projection/reconcile barrier while removing GameWindow callbacks and duplicate shadow helpers.
114 lines
4.4 KiB
C#
114 lines
4.4 KiB
C#
using AcDream.App.Combat;
|
|
using AcDream.App.Input;
|
|
using AcDream.App.Update;
|
|
using AcDream.Core.Rendering;
|
|
|
|
namespace AcDream.App.Rendering;
|
|
|
|
/// <summary>
|
|
/// Owns the per-update fly/chase camera publication tail.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The local object phase normally publishes the player before inbound
|
|
/// traffic. When the player is first created by that inbound pass, the local
|
|
/// frame publishes its initial root here and the spatial reconciler refreshes
|
|
/// child/effect anchors before either chase camera samples it.
|
|
/// </remarks>
|
|
internal sealed class CameraFrameController : ICameraFramePhase
|
|
{
|
|
private readonly CameraController _camera;
|
|
private readonly IInputCaptureSource _capture;
|
|
private readonly ICameraFrameInputSource _input;
|
|
private readonly ILocalPlayerPresentationRuntime _player;
|
|
private readonly IChaseCameraSource _chase;
|
|
private readonly RetailLocalPlayerFrameController _localFrame;
|
|
private readonly ILiveSpatialReconcilePhase _spatialReconciler;
|
|
private readonly ICombatCameraTargetSource _combatTarget;
|
|
|
|
public CameraFrameController(
|
|
CameraController camera,
|
|
IInputCaptureSource capture,
|
|
ICameraFrameInputSource input,
|
|
ILocalPlayerPresentationRuntime player,
|
|
IChaseCameraSource chase,
|
|
RetailLocalPlayerFrameController localFrame,
|
|
ILiveSpatialReconcilePhase spatialReconciler,
|
|
ICombatCameraTargetSource combatTarget)
|
|
{
|
|
_camera = camera ?? throw new ArgumentNullException(nameof(camera));
|
|
_capture = capture ?? throw new ArgumentNullException(nameof(capture));
|
|
_input = input ?? throw new ArgumentNullException(nameof(input));
|
|
_player = player ?? throw new ArgumentNullException(nameof(player));
|
|
_chase = chase ?? throw new ArgumentNullException(nameof(chase));
|
|
_localFrame = localFrame ?? throw new ArgumentNullException(nameof(localFrame));
|
|
_spatialReconciler = spatialReconciler
|
|
?? throw new ArgumentNullException(nameof(spatialReconciler));
|
|
_combatTarget = combatTarget ?? throw new ArgumentNullException(nameof(combatTarget));
|
|
}
|
|
|
|
public void Tick(UpdateFrameTiming timing)
|
|
{
|
|
if (_capture.DevToolsWantCaptureKeyboard || !_input.IsAvailable)
|
|
return;
|
|
|
|
if (_camera.IsFlyMode)
|
|
{
|
|
FlyCameraInput input = _input.CaptureFly();
|
|
_camera.Fly.Update(
|
|
timing.SimulationDeltaSeconds,
|
|
input.Forward,
|
|
input.Left,
|
|
input.Backward,
|
|
input.Right,
|
|
input.Up,
|
|
input.Down,
|
|
input.Boost);
|
|
return;
|
|
}
|
|
|
|
PlayerMovementController? controller = _player.Controller;
|
|
ChaseCamera? legacy = _chase.Legacy;
|
|
RetailChaseCamera? retail = _chase.Retail;
|
|
if (!_player.CanPresentPlayer || controller is null || legacy is null)
|
|
return;
|
|
|
|
if (CameraDiagnostics.UseRetailChaseCamera && retail is not null)
|
|
{
|
|
ChaseCameraAdjustmentInput input = _input.CaptureChaseAdjustment();
|
|
float adjustment = CameraDiagnostics.CameraAdjustmentSpeed
|
|
* timing.SimulationDeltaSecondsSingle;
|
|
if (input.ZoomIn)
|
|
retail.AdjustDistance(-adjustment);
|
|
if (input.ZoomOut)
|
|
retail.AdjustDistance(+adjustment);
|
|
if (input.Raise)
|
|
retail.AdjustPitch(+adjustment * 0.02f);
|
|
if (input.Lower)
|
|
retail.AdjustPitch(-adjustment * 0.02f);
|
|
}
|
|
|
|
if (!_localFrame.TryGetPresentationAfterNetwork(out var playerFrame))
|
|
return;
|
|
|
|
if (!playerFrame.AdvancedBeforeNetwork)
|
|
_spatialReconciler.Reconcile();
|
|
|
|
MovementResult result = playerFrame.Movement;
|
|
legacy.Update(
|
|
result.RenderPosition,
|
|
controller.Yaw,
|
|
isOnGround: result.IsOnGround,
|
|
dt: timing.SimulationDeltaSecondsSingle);
|
|
|
|
retail?.Update(
|
|
result.RenderPosition,
|
|
controller.Yaw,
|
|
playerVelocity: controller.BodyVelocity,
|
|
isOnGround: result.IsOnGround,
|
|
contactPlaneNormal: controller.ContactPlane.Normal,
|
|
dt: timing.SimulationDeltaSecondsSingle,
|
|
cellId: controller.CellId,
|
|
selfEntityId: controller.LocalEntityId,
|
|
trackedTargetPoint: _combatTarget.GetTrackedTargetPoint());
|
|
}
|
|
}
|