using System.Numerics;
namespace Tertius.Simulation;
/// Everything needed to create an entity. The world copies the lists when it accepts the description.
public sealed class SpawnDesc
{
///
/// The frame to spawn in. It can be null when is set: the entity is then a root frame. The frame
/// that an attached entity names does not count, because it becomes live in the frame of its parent (see
/// ). So an attached entity can leave this null.
///
public FrameHandle Frame { get; init; }
/// The pose in . For a frame entity, this is the frame's local pose.
public DPose Pose { get; init; } = DPose.Identity;
///
/// Linear velocity of the entity's origin, the point that its pose names, relative to , in its axes.
/// For a spinning body whose center of mass lies off its origin, that is not the velocity of the center of mass.
/// Physics converts it when it creates the body. Only a body
/// that physics integrates, a dynamic body or a character, and a kinematic hull, whose frame keeps it, take a spawn
/// velocity. A spawn refuses one on every other entity, which its motion intents, teleports, transform writes or parent
/// move: such a spawner gives instead.
///
public Double3 LinearVelocity { get; init; }
/// Angular velocity in frame axes. The same entities take it as take .
public Vector3 AngularVelocity { get; init; }
///
/// The new entity's first motion intent: how it moves in the step after its spawn, relative to , in
/// its axes (docs/plans/rails-components.md, "The first motion intent of a spawn"). It is the motion intent that the
/// entity would have written in the spawn's tick, had it run then, so that a frame on rails stands on its rails from its
/// first step. A component that calls in tick k gives the motion of the step that
/// ends at self.TimeAt(self.Tick + 2), and a game that calls outside a tick
/// the motion of the step that ends at World.TimeAt(World.TickNumber + 1). For the owner of a frame,
/// is the frame's semantic parent, and for the owner of a root frame it is null, so the intent is in
/// the root's own space. The default holds no case: the entity has no motion intent in that step, and a frame on rails
/// holds still for it. A spawn refuses a case that its entity would refuse, and a number that is not finite or a zero
/// rotation, with an .
///
public MotionIntent FirstMove { get; init; }
/// A physics body. If set, physics owns the entity's transform.
public BodyDesc? Body { get; init; }
/// The render row. Null means nothing to draw.
public RenderData? Render { get; init; }
///
/// The rig pose at the spawn, or null for none (docs/plans/skinning-and-morphs.md, "The rig pose in the simulation").
/// It fixes the entity's counts of joint poses and weights, and needs a row. A spawn throws
/// for a default array, a number that is not finite, more than
/// joint poses, or a rotation whose squared length is not finite or is at most 10^-12, the
/// rule of .
///
public RigPose? RigPose { get; init; }
/// The component instances. Each instance belongs to one entity, so do not share them between spawns.
public IReadOnlyList Components { get; init; } = [];
/// If set, the entity becomes a frame whose parent is and whose local pose is
/// .
public FrameSpec? AsFrame { get; init; }
///
/// If set, the entity follows this parent with the fixed local offset . An attached entity
/// has no body, cannot be a frame, and is destroyed with its parent. The world derives its pose and velocities from the
/// parent. It becomes live in the frame that the parent is in at that time, whatever names: at the
/// call outside a tick, and at the sync point during a tick. So if physics hands the parent into another frame in the
/// step of the same tick, or the parent's frame dies and the parent moves to an ancestor frame, the new entity becomes
/// live in the parent's new frame. The parent must be live at that time, and it must not own a root frame, because such
/// an owner is in no frame. For another parent, throws
/// outside a tick. At the sync point, the world drops the spawn and records an error in
/// .
///
public Entity AttachTo { get; init; }
/// The fixed pose of the entity relative to .
public Pose AttachOffset { get; init; } = Tertius.Pose.Identity;
/// Named topics to subscribe to. The frame topic is automatic.
public IReadOnlyList Subscriptions { get; init; } = [];
}
/// Makes a spawned entity a reference frame.
/// The bubble that decides which objects belong to the frame.
/// The gravity field that objects inside feel.
///
/// The gas that fills the frame, at rest in its axes, or none for vacuum (see ). Only puffs read
/// it: it lifts and drags them, and physics reads no medium.
///
///
/// The frame moves as its owner's body moves, not as this description says. For a frame with a parent, the owner's body
/// is the frame's hull, and the hull's motion is the motion of its description (see ): a
/// dynamic hull falls and coasts in the parent's physics system, a kinematic hull follows the motion samples of a rails
/// component of its entity, such as or , and a static hull holds
/// still. The owner changes the motion later with . A frame without a body follows the
/// samples of its rails component, or its owner's transform write, or holds still (docs/plans/rails-components.md).
///
public sealed record FrameSpec(FrameBounds Bounds, GravityField Gravity = default, MediumField Medium = default);