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);