/// <summary>Renders the equipment starting from the specified slot.</summary> private void RenderEquipment( SpaceItemSlot slot, Vector2 offset, int depth = 1, float order = 0.5f, ItemSlotSize parentSize = ItemSlotSize.Small, bool?mirrored = null) { // Nothing to do if there's no item in the slot. if (slot.Item <= 0) { return; } // Get item info. var item = (SpaceItem)Manager.GetComponent(slot.Item, Item.TypeId); // Adjust depth we want to render at. order -= (item.DrawBelowParent ? -0.25f : 0.25f) / depth; // See if we should mirror rendering (e.g. left wing). var slotOffset = slot.Offset; var itemOffset = item.ModelOffset; if (mirrored.HasValue) { if (mirrored.Value) { slotOffset.Y = -slotOffset.Y; } } // ReSharper disable CompareOfFloatsByEqualityOperator Intentional. else if (slotOffset.Y != 0.0f) // ReSharper restore CompareOfFloatsByEqualityOperator { mirrored = slot.Offset.Y < 0; } if (mirrored.HasValue && mirrored.Value) { itemOffset.Y = -itemOffset.Y; } // Move the offset according to rotation and accumulate it. var localOffset = offset + parentSize.Scale() * slotOffset; var renderOffset = localOffset + item.RequiredSlotSize.Scale() * itemOffset; // Render this particular item. foreach (SimpleTextureDrawable drawable in Manager.GetComponents(item.Entity, SimpleTextureDrawable.TypeId)) { drawable.Draw( _spriteBatch, renderOffset, 0f, item.RequiredSlotSize.Scale() / drawable.Scale, mirrored.HasValue && mirrored.Value ? SpriteEffects.FlipVertically : SpriteEffects.None, order); } // Render sub-items. foreach (SpaceItemSlot childSlot in Manager.GetComponents(item.Entity, ItemSlot.TypeId)) { RenderEquipment(childSlot, localOffset, depth + 1, order, item.RequiredSlotSize, mirrored); } }
/// <summary> /// Computes the size of the model, i.e. the area covered by the fully rendered equipment starting with the /// specified slot. /// </summary> private RectangleF ComputeModelSize( SpaceItemSlot slot, Vector2 offset, ItemSlotSize parentSize = ItemSlotSize.Small, bool?mirrored = null) { // Nothing to do if there's no item in the slot. if (slot.Item <= 0) { return(RectangleF.Empty); } // Get item info. var item = (SpaceItem)Manager.GetComponent(slot.Item, Item.TypeId); // Get required bounds to render this item. var bounds = Manager.GetComponents(item.Entity, SimpleTextureDrawable.TypeId) .Cast <SimpleTextureDrawable>() .Aggregate( RectangleF.Empty, (current, drawable) => { var b = (RectangleF)drawable.Texture.Bounds; b.Offset(-b.Width / 2f, -b.Height / 2f); return(RectangleF.Union(current, b)); }); // See if we should mirror rendering (e.g. left wing). var slotOffset = slot.Offset; var itemOffset = item.ModelOffset; if (mirrored.HasValue) { if (mirrored.Value) { slotOffset.Y = -slotOffset.Y; } } // ReSharper disable CompareOfFloatsByEqualityOperator Intentional. else if (slotOffset.Y != 0.0f) // ReSharper restore CompareOfFloatsByEqualityOperator { mirrored = slot.Offset.Y < 0; } if (mirrored.HasValue && mirrored.Value) { itemOffset.Y = -itemOffset.Y; } // Move the offset according to rotation and accumulate it. var localOffset = offset + parentSize.Scale() * slotOffset; var renderOffset = localOffset + item.RequiredSlotSize.Scale() * itemOffset; // Adjust to actual area the texture is rendered to. bounds.Offset(renderOffset); bounds.Inflate( -bounds.Width / 2f * (1 - item.RequiredSlotSize.Scale()), -bounds.Height / 2f * (1 - item.RequiredSlotSize.Scale())); // Check sub-items. return(Manager.GetComponents(item.Entity, ItemSlot.TypeId) .Cast <SpaceItemSlot>() .Aggregate(bounds, (current, childSlot) => RectangleF.Union(current, ComputeModelSize(childSlot, localOffset, item.RequiredSlotSize, mirrored)))); }