# VSwift

`PM.VSwift` adds part variants: the in-editor switcher that lets a single part take on different looks or configurations (a tank with or without a mount, an engine with a swappable bell). VSwift is the variant framework, and this module wires a part up to it from a patch.

The structure nests: a part gets a **part switch**, the part switch holds **variant sets**, a set holds **variants**, and a variant holds **transformers** that actually change the part when that variant is active.

## Adding a part switch

`PM.VSwift:AddPartSwitch(part, callback)` adds the part-switch module to a part and runs the callback against its data. This is also where you set which variants start active. Inside, you build up the variant sets:

```lua
PM.Parts:Patch("EngineMountVariants")
        :Named("engine_1.5v_methalox_cheetah")
        :Do(function(part)
            PM.VSwift:AddPartSwitch(part, function(data)
                data.ActiveVariants = { "WithMount" }
                data:EnsureVariantSet("Mount", function(set)
                    set.VariantSetLocalizationKey = "VSwift/Mount"
                    set:EnsureVariant("WithMount", function(variant)
                        variant.VariantLocalizationKey = "VSwift/Mount/With"
                        variant:EnsureTransformer("TransformActivator", function(transformer)
                            transformer.Transforms = { "cheetah_mount", "cheetah_mount_col" }
                        end)
                    end)
                    set:EnsureVariant("NoMount", function(variant)
                        variant.VariantLocalizationKey = "VSwift/Mount/Without"
                        variant:EnsureTransformer("AttachNodeMover", function(transformer)
                            transformer.MovedNodes = { top = { x = 0.0, y = 0.45, z = 0.0 } }
                        end)
                    end)
                end)
            end)
        end)
```

## The methods at each level

Every level uses the [shared Add/Patch/Ensure/Remove/Has pattern](/doc/typed-modules-nMMO0SZ6ac), so once you know it for one level it reads the same all the way down:

* On the part-switch data: `AddVariantSet`, `EnsureVariantSet`, `PatchVariantSet`, `RemoveVariantSet`.
* On a variant set: `AddVariant`, `EnsureVariant`, `PatchVariant`, `RemoveVariant`, `HasVariant`.
* On a variant: `AddTransformer`, `EnsureTransformer`, `PatchTransformer`, `RemoveTransformer`, `HasTransformer`.

`Ensure` is the usual choice when building, since it creates the piece if it is missing and edits it if it is already there, which makes a patch safe to run against a part that may already carry some variants.

## Transformers

A transformer is what a variant actually does when selected. The stock transformers include ones that toggle transforms on and off and ones that move attach nodes. You add a transformer by its short type name and configure its fields in the callback, as the `TransformActivator` and `AttachNodeMover` above show. The available transformer types and their fields are in `pm-vswift.d.lua`.

## Active variants and IDs

`data.ActiveVariants` is the list of variant ids that start selected, one per set. Variant sets are keyed by `VariantSetId` and variants by `VariantId`, which are the names you pass to the methods and list in `ActiveVariants`. The localization keys (`VariantSetLocalizationKey`, `VariantLocalizationKey`) drive the labels shown in the editor.

## Display in the parts manager

`PM.VSwift:AddPAMOverride(part)` adds a parts-manager display override so the switch shows under a proper header. `AddPartSwitch` applies this for you, so you only call it directly when you are managing the override separately.