#pragma once #include "CoreMinimal.h" #include "Player/Arm/DescentArmPose.h" /** The phases of the wall-plug sequence (DESIGN_UE.md 6.9; timing in Core/Tuning/DescentTune_Arm.h). */ enum class EDescentArmJackPhase : uint8 { Inactive, Raise, // the arm comes up from where it was to the ready position Reach, // the fingertips travel to the standoff point on the port's axis, the hand closes into the plug shape Plug, // straight in along the port's axis until the plug seats Feed, // the plug is seated; hold still while nutrition flows Withdraw, // straight back out along the port's axis Lower, // the arm goes back down to the pose it ends in Done, }; /** What the sequence needs to know, all in ARM SPACE (origin = shoulder, +X along the arm, cm). */ struct FDescentArmJackInput { /** The pose when the sequence began (the raise starts from it). */ FDescentArmPose Start; /** The pose the arm lowers to at the end. */ FDescentArmPose End; /** Where the middle fingertip must be when the plug is seated: the port's socket. */ FVector PortCm = FVector::ZeroVector; /** Unit vector: the way the hand moves into the port (the port's outward normal, reversed). */ FVector PlugDirection = FVector::ForwardVector; }; struct FDescentArmJackFrame { FDescentArmPose Pose; EDescentArmJackPhase Phase = EDescentArmJackPhase::Inactive; /** 0..1 inside the current phase. */ double PhaseProgress = 0.0; /** True from the moment the plug seats until it is pulled (the nutrition flows during this window). */ bool bFeeding = false; /** The reach solver's result for this frame: position error (cm), whether it is inside the stated accuracy, and how far the * hand is from the wanted direction (degrees). In Feed these are the jack-in's accuracy. */ double ReachErrorCm = 0.0; bool bReachable = true; double HandDirErrorDeg = 0.0; }; namespace Descent::Arm { THEDESCENT_API const TCHAR* JackPhaseName(EDescentArmJackPhase Phase); /** The phase at time T (seconds from the start) for the timing in the tuning header. */ THEDESCENT_API EDescentArmJackPhase JackPhaseAt(double T); /** * The arm at time T of the sequence. A pure function of (T, input): the same call always gives the same answer, so * the component can re-evaluate it every frame against a port that moves with the camera. */ THEDESCENT_API FDescentArmJackFrame EvaluateJack(double T, const FDescentArmJackInput& Input); }